summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-24 02:13:59 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-24 02:13:59 +0000
commita6d58bb6052ac8cb01805a48c4ad2f129126116f (patch)
treedd867a099fcbb263a8009a9fb22695b87855dad6 /src
downloadkvirc-a6d58bb6052ac8cb01805a48c4ad2f129126116f.tar.gz
kvirc-a6d58bb6052ac8cb01805a48c4ad2f129126116f.zip
Added KDE3 version of kvirc
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/kvirc@1095341 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am10
-rw-r--r--src/config.h.in247
-rw-r--r--src/kvi_configstatus.h248
-rw-r--r--src/kvilib/Makefile.am5
-rw-r--r--src/kvilib/build/Makefile.am339
-rw-r--r--src/kvilib/config/Makefile.am5
-rw-r--r--src/kvilib/config/kvi_confignames.h61
-rw-r--r--src/kvilib/config/kvi_debug.h52
-rw-r--r--src/kvilib/config/kvi_defaults.h65
-rw-r--r--src/kvilib/config/kvi_fileextensions.h37
-rw-r--r--src/kvilib/config/kvi_settings.h140
-rw-r--r--src/kvilib/config/kvi_sourcesdate.h40
-rw-r--r--src/kvilib/config/kvi_version.h33
-rw-r--r--src/kvilib/config/kvi_wincfg.h210
-rw-r--r--src/kvilib/core/Makefile.am5
-rw-r--r--src/kvilib/core/kvi_bswap.h63
-rw-r--r--src/kvilib/core/kvi_error.cpp237
-rw-r--r--src/kvilib/core/kvi_error.h188
-rw-r--r--src/kvilib/core/kvi_heapobject.cpp96
-rw-r--r--src/kvilib/core/kvi_heapobject.h50
-rw-r--r--src/kvilib/core/kvi_inttypes.h95
-rw-r--r--src/kvilib/core/kvi_malloc.cpp198
-rw-r--r--src/kvilib/core/kvi_malloc.h88
-rw-r--r--src/kvilib/core/kvi_memmove.cpp253
-rw-r--r--src/kvilib/core/kvi_memmove.h105
-rw-r--r--src/kvilib/core/kvi_pointerhashtable.h999
-rw-r--r--src/kvilib/core/kvi_pointerlist.h1069
-rw-r--r--src/kvilib/core/kvi_qcstring.h39
-rw-r--r--src/kvilib/core/kvi_qstring.cpp1125
-rw-r--r--src/kvilib/core/kvi_qstring.h293
-rw-r--r--src/kvilib/core/kvi_strasm.h194
-rw-r--r--src/kvilib/core/kvi_string.cpp3063
-rw-r--r--src/kvilib/core/kvi_string.h552
-rw-r--r--src/kvilib/core/kvi_stringarray.cpp119
-rw-r--r--src/kvilib/core/kvi_stringarray.h55
-rw-r--r--src/kvilib/core/kvi_valuelist.h37
-rw-r--r--src/kvilib/ext/Makefile.am5
-rw-r--r--src/kvilib/ext/kvi_accel.h38
-rw-r--r--src/kvilib/ext/kvi_cmdformatter.cpp242
-rw-r--r--src/kvilib/ext/kvi_cmdformatter.h64
-rw-r--r--src/kvilib/ext/kvi_config.cpp1007
-rw-r--r--src/kvilib/ext/kvi_config.h162
-rw-r--r--src/kvilib/ext/kvi_crypt.cpp240
-rw-r--r--src/kvilib/ext/kvi_crypt.h160
-rw-r--r--src/kvilib/ext/kvi_databuffer.cpp135
-rw-r--r--src/kvilib/ext/kvi_databuffer.h56
-rw-r--r--src/kvilib/ext/kvi_dcophelper.cpp357
-rw-r--r--src/kvilib/ext/kvi_dcophelper.h82
-rw-r--r--src/kvilib/ext/kvi_doublebuffer.cpp90
-rw-r--r--src/kvilib/ext/kvi_doublebuffer.h62
-rw-r--r--src/kvilib/ext/kvi_draganddrop.h45
-rw-r--r--src/kvilib/ext/kvi_garbage.cpp148
-rw-r--r--src/kvilib/ext/kvi_garbage.h51
-rw-r--r--src/kvilib/ext/kvi_imagelib.cpp138
-rw-r--r--src/kvilib/ext/kvi_imagelib.h73
-rw-r--r--src/kvilib/ext/kvi_md5.cpp298
-rw-r--r--src/kvilib/ext/kvi_md5.h68
-rw-r--r--src/kvilib/ext/kvi_mediatype.cpp541
-rw-r--r--src/kvilib/ext/kvi_mediatype.h83
-rw-r--r--src/kvilib/ext/kvi_miscutils.cpp86
-rw-r--r--src/kvilib/ext/kvi_miscutils.h44
-rw-r--r--src/kvilib/ext/kvi_msgtype.cpp68
-rw-r--r--src/kvilib/ext/kvi_msgtype.h74
-rw-r--r--src/kvilib/ext/kvi_osinfo.cpp510
-rw-r--r--src/kvilib/ext/kvi_osinfo.h43
-rw-r--r--src/kvilib/ext/kvi_parameterlist.cpp254
-rw-r--r--src/kvilib/ext/kvi_parameterlist.h72
-rw-r--r--src/kvilib/ext/kvi_pixmap.cpp180
-rw-r--r--src/kvilib/ext/kvi_pixmap.h61
-rw-r--r--src/kvilib/ext/kvi_proxydb.cpp192
-rw-r--r--src/kvilib/ext/kvi_proxydb.h86
-rw-r--r--src/kvilib/ext/kvi_regchan.cpp181
-rw-r--r--src/kvilib/ext/kvi_regchan.h74
-rw-r--r--src/kvilib/ext/kvi_regusersdb.cpp743
-rw-r--r--src/kvilib/ext/kvi_regusersdb.h201
-rw-r--r--src/kvilib/ext/kvi_sharedfiles.cpp391
-rw-r--r--src/kvilib/ext/kvi_sharedfiles.h133
-rw-r--r--src/kvilib/ext/kvi_stringconversion.cpp277
-rw-r--r--src/kvilib/ext/kvi_stringconversion.h91
-rw-r--r--src/kvilib/ext/kvi_xlib.h45
-rw-r--r--src/kvilib/ext/moc_kvi_crypt.cpp94
-rw-r--r--src/kvilib/ext/moc_kvi_garbage.cpp104
-rw-r--r--src/kvilib/ext/moc_kvi_regusersdb.cpp143
-rw-r--r--src/kvilib/ext/moc_kvi_sharedfiles.cpp157
-rw-r--r--src/kvilib/file/Makefile.am5
-rw-r--r--src/kvilib/file/kvi_file.cpp256
-rw-r--r--src/kvilib/file/kvi_file.h120
-rw-r--r--src/kvilib/file/kvi_fileutils.cpp505
-rw-r--r--src/kvilib/file/kvi_fileutils.h112
-rw-r--r--src/kvilib/file/kvi_packagefile.cpp1028
-rw-r--r--src/kvilib/file/kvi_packagefile.h142
-rw-r--r--src/kvilib/include/Makefile.am4
-rw-r--r--src/kvilib/irc/Makefile.am5
-rw-r--r--src/kvilib/irc/kvi_avatar.cpp165
-rw-r--r--src/kvilib/irc/kvi_avatar.h83
-rw-r--r--src/kvilib/irc/kvi_avatarcache.cpp250
-rw-r--r--src/kvilib/irc/kvi_avatarcache.h69
-rw-r--r--src/kvilib/irc/kvi_ircmask.cpp760
-rw-r--r--src/kvilib/irc/kvi_ircmask.h164
-rw-r--r--src/kvilib/irc/kvi_ircserver.cpp373
-rw-r--r--src/kvilib/irc/kvi_ircserver.h206
-rw-r--r--src/kvilib/irc/kvi_ircserverdb.cpp646
-rw-r--r--src/kvilib/irc/kvi_ircserverdb.h116
-rw-r--r--src/kvilib/irc/kvi_ircuserdb.cpp285
-rw-r--r--src/kvilib/irc/kvi_ircuserdb.h145
-rw-r--r--src/kvilib/irc/kvi_mirccntrl.cpp307
-rw-r--r--src/kvilib/irc/kvi_mirccntrl.h163
-rw-r--r--src/kvilib/irc/kvi_nickserv.cpp312
-rw-r--r--src/kvilib/irc/kvi_nickserv.h112
-rw-r--r--src/kvilib/irc/kvi_useridentity.cpp252
-rw-r--r--src/kvilib/irc/kvi_useridentity.h145
-rw-r--r--src/kvilib/irc/moc_kvi_ircuserdb.cpp119
-rw-r--r--src/kvilib/net/Makefile.am5
-rw-r--r--src/kvilib/net/kvi_dns.cpp450
-rw-r--r--src/kvilib/net/kvi_dns.h142
-rw-r--r--src/kvilib/net/kvi_http.cpp1440
-rw-r--r--src/kvilib/net/kvi_http.h209
-rw-r--r--src/kvilib/net/kvi_netutils.cpp1504
-rw-r--r--src/kvilib/net/kvi_netutils.h104
-rw-r--r--src/kvilib/net/kvi_socket.cpp31
-rw-r--r--src/kvilib/net/kvi_socket.h356
-rw-r--r--src/kvilib/net/kvi_sockettype.h45
-rw-r--r--src/kvilib/net/kvi_ssl.cpp687
-rw-r--r--src/kvilib/net/kvi_ssl.h180
-rw-r--r--src/kvilib/net/kvi_url.cpp164
-rw-r--r--src/kvilib/net/kvi_url.h63
-rw-r--r--src/kvilib/net/moc_kvi_dns.cpp137
-rw-r--r--src/kvilib/net/moc_kvi_http.cpp263
-rw-r--r--src/kvilib/system/Makefile.am5
-rw-r--r--src/kvilib/system/kvi_byteorder.h62
-rw-r--r--src/kvilib/system/kvi_env.cpp89
-rw-r--r--src/kvilib/system/kvi_env.h60
-rw-r--r--src/kvilib/system/kvi_library.h115
-rw-r--r--src/kvilib/system/kvi_locale.cpp1191
-rw-r--r--src/kvilib/system/kvi_locale.h146
-rw-r--r--src/kvilib/system/kvi_process.h37
-rw-r--r--src/kvilib/system/kvi_stdarg.h65
-rw-r--r--src/kvilib/system/kvi_thread.cpp644
-rw-r--r--src/kvilib/system/kvi_thread.h378
-rw-r--r--src/kvilib/system/kvi_time.cpp135
-rw-r--r--src/kvilib/system/kvi_time.h92
-rw-r--r--src/kvilib/system/moc_kvi_locale.cpp92
-rw-r--r--src/kvilib/system/moc_kvi_thread.cpp104
-rw-r--r--src/kvilib/tal/Makefile.am5
-rw-r--r--src/kvilib/tal/kvi_tal_application.cpp69
-rw-r--r--src/kvilib/tal/kvi_tal_application.h34
-rw-r--r--src/kvilib/tal/kvi_tal_application_kde.h37
-rw-r--r--src/kvilib/tal/kvi_tal_application_qt.h37
-rw-r--r--src/kvilib/tal/kvi_tal_filedialog.cpp176
-rw-r--r--src/kvilib/tal/kvi_tal_filedialog.h40
-rw-r--r--src/kvilib/tal/kvi_tal_filedialog_kde.h50
-rw-r--r--src/kvilib/tal/kvi_tal_filedialog_qt.h44
-rw-r--r--src/kvilib/tal/kvi_tal_filedialog_qt4.h46
-rw-r--r--src/kvilib/tal/kvi_tal_grid.cpp34
-rw-r--r--src/kvilib/tal/kvi_tal_grid.h36
-rw-r--r--src/kvilib/tal/kvi_tal_grid_qt3.h39
-rw-r--r--src/kvilib/tal/kvi_tal_grid_qt4.h41
-rw-r--r--src/kvilib/tal/kvi_tal_groupbox.cpp34
-rw-r--r--src/kvilib/tal/kvi_tal_groupbox.h36
-rw-r--r--src/kvilib/tal/kvi_tal_groupbox_qt3.h47
-rw-r--r--src/kvilib/tal/kvi_tal_groupbox_qt4.h47
-rw-r--r--src/kvilib/tal/kvi_tal_hbox.cpp32
-rw-r--r--src/kvilib/tal/kvi_tal_hbox.h36
-rw-r--r--src/kvilib/tal/kvi_tal_hbox_qt3.h41
-rw-r--r--src/kvilib/tal/kvi_tal_hbox_qt4.h41
-rw-r--r--src/kvilib/tal/kvi_tal_iconview.cpp215
-rw-r--r--src/kvilib/tal/kvi_tal_iconview.h36
-rw-r--r--src/kvilib/tal/kvi_tal_iconview_qt3.h100
-rw-r--r--src/kvilib/tal/kvi_tal_iconview_qt4.h99
-rw-r--r--src/kvilib/tal/kvi_tal_listbox.cpp513
-rw-r--r--src/kvilib/tal/kvi_tal_listbox.h50
-rw-r--r--src/kvilib/tal/kvi_tal_listbox_qt3.h157
-rw-r--r--src/kvilib/tal/kvi_tal_listbox_qt4.h152
-rw-r--r--src/kvilib/tal/kvi_tal_listview.cpp1542
-rw-r--r--src/kvilib/tal/kvi_tal_listview.h51
-rw-r--r--src/kvilib/tal/kvi_tal_listview_qt3.h190
-rw-r--r--src/kvilib/tal/kvi_tal_listview_qt4.h199
-rw-r--r--src/kvilib/tal/kvi_tal_mainwindow.cpp69
-rw-r--r--src/kvilib/tal/kvi_tal_mainwindow.h38
-rw-r--r--src/kvilib/tal/kvi_tal_mainwindow_kde.h36
-rw-r--r--src/kvilib/tal/kvi_tal_mainwindow_qt3.h36
-rw-r--r--src/kvilib/tal/kvi_tal_mainwindow_qt4.h39
-rw-r--r--src/kvilib/tal/kvi_tal_menubar.cpp58
-rw-r--r--src/kvilib/tal/kvi_tal_menubar.h33
-rw-r--r--src/kvilib/tal/kvi_tal_menubar_kde.h35
-rw-r--r--src/kvilib/tal/kvi_tal_menubar_qt.h35
-rw-r--r--src/kvilib/tal/kvi_tal_popupmenu.cpp33
-rw-r--r--src/kvilib/tal/kvi_tal_popupmenu.h36
-rw-r--r--src/kvilib/tal/kvi_tal_popupmenu_qt3.h42
-rw-r--r--src/kvilib/tal/kvi_tal_popupmenu_qt4.h89
-rw-r--r--src/kvilib/tal/kvi_tal_scrollview.cpp33
-rw-r--r--src/kvilib/tal/kvi_tal_scrollview.h36
-rw-r--r--src/kvilib/tal/kvi_tal_scrollview_qt3.h41
-rw-r--r--src/kvilib/tal/kvi_tal_scrollview_qt4.h41
-rw-r--r--src/kvilib/tal/kvi_tal_tabdialog.cpp34
-rw-r--r--src/kvilib/tal/kvi_tal_tabdialog.h36
-rw-r--r--src/kvilib/tal/kvi_tal_tabdialog_qt3.h39
-rw-r--r--src/kvilib/tal/kvi_tal_tabdialog_qt4.h39
-rw-r--r--src/kvilib/tal/kvi_tal_textedit.cpp34
-rw-r--r--src/kvilib/tal/kvi_tal_textedit.h36
-rw-r--r--src/kvilib/tal/kvi_tal_textedit_qt3.h39
-rw-r--r--src/kvilib/tal/kvi_tal_textedit_qt4.h39
-rw-r--r--src/kvilib/tal/kvi_tal_toolbar.cpp107
-rw-r--r--src/kvilib/tal/kvi_tal_toolbar.h37
-rw-r--r--src/kvilib/tal/kvi_tal_toolbar_kde.h37
-rw-r--r--src/kvilib/tal/kvi_tal_toolbar_qt3.h39
-rw-r--r--src/kvilib/tal/kvi_tal_toolbar_qt4.h47
-rw-r--r--src/kvilib/tal/kvi_tal_toolbardocktype.h71
-rw-r--r--src/kvilib/tal/kvi_tal_tooltip.cpp125
-rw-r--r--src/kvilib/tal/kvi_tal_tooltip.h79
-rw-r--r--src/kvilib/tal/kvi_tal_vbox.cpp33
-rw-r--r--src/kvilib/tal/kvi_tal_vbox.h36
-rw-r--r--src/kvilib/tal/kvi_tal_vbox_qt3.h42
-rw-r--r--src/kvilib/tal/kvi_tal_vbox_qt4.h42
-rw-r--r--src/kvilib/tal/kvi_tal_widgetstack.cpp33
-rw-r--r--src/kvilib/tal/kvi_tal_widgetstack.h36
-rw-r--r--src/kvilib/tal/kvi_tal_widgetstack_qt3.h42
-rw-r--r--src/kvilib/tal/kvi_tal_widgetstack_qt4.h42
-rw-r--r--src/kvilib/tal/kvi_tal_windowstate.h42
-rw-r--r--src/kvilib/tal/kvi_tal_wizard.cpp584
-rw-r--r--src/kvilib/tal/kvi_tal_wizard.h169
-rw-r--r--src/kvilib/tal/moc_kvi_tal_wizard.cpp128
-rw-r--r--src/kvirc/Makefile.am5
-rw-r--r--src/kvirc/build/Makefile.am537
-rw-r--r--src/kvirc/include/Makefile.am3
-rw-r--r--src/kvirc/kernel/Makefile.am5
-rw-r--r--src/kvirc/kernel/kvi_action.cpp434
-rw-r--r--src/kvirc/kernel/kvi_action.h157
-rw-r--r--src/kvirc/kernel/kvi_actionmanager.cpp321
-rw-r--r--src/kvirc/kernel/kvi_actionmanager.h118
-rw-r--r--src/kvirc/kernel/kvi_app.cpp2074
-rw-r--r--src/kvirc/kernel/kvi_app.h344
-rw-r--r--src/kvirc/kernel/kvi_app_fs.cpp726
-rw-r--r--src/kvirc/kernel/kvi_app_setup.cpp864
-rw-r--r--src/kvirc/kernel/kvi_asynchronousconnectiondata.cpp39
-rw-r--r--src/kvirc/kernel/kvi_asynchronousconnectiondata.h54
-rw-r--r--src/kvirc/kernel/kvi_coreactionnames.h69
-rw-r--r--src/kvirc/kernel/kvi_coreactions.cpp1206
-rw-r--r--src/kvirc/kernel/kvi_coreactions.h188
-rw-r--r--src/kvirc/kernel/kvi_customtoolbardescriptor.cpp278
-rw-r--r--src/kvirc/kernel/kvi_customtoolbardescriptor.h86
-rw-r--r--src/kvirc/kernel/kvi_customtoolbarmanager.cpp239
-rw-r--r--src/kvirc/kernel/kvi_customtoolbarmanager.h76
-rw-r--r--src/kvirc/kernel/kvi_filetransfer.cpp190
-rw-r--r--src/kvirc/kernel/kvi_filetransfer.h116
-rw-r--r--src/kvirc/kernel/kvi_iconmanager.cpp924
-rw-r--r--src/kvirc/kernel/kvi_iconmanager.h501
-rw-r--r--src/kvirc/kernel/kvi_internalcmd.cpp81
-rw-r--r--src/kvirc/kernel/kvi_internalcmd.h72
-rw-r--r--src/kvirc/kernel/kvi_ipc.cpp269
-rw-r--r--src/kvirc/kernel/kvi_ipc.h75
-rw-r--r--src/kvirc/kernel/kvi_ircconnection.cpp1354
-rw-r--r--src/kvirc/kernel/kvi_ircconnection.h282
-rw-r--r--src/kvirc/kernel/kvi_ircconnectionantictcpflooddata.cpp38
-rw-r--r--src/kvirc/kernel/kvi_ircconnectionantictcpflooddata.h48
-rw-r--r--src/kvirc/kernel/kvi_ircconnectionasyncwhoisdata.cpp81
-rw-r--r--src/kvirc/kernel/kvi_ircconnectionasyncwhoisdata.h72
-rw-r--r--src/kvirc/kernel/kvi_ircconnectionnetsplitdetectordata.cpp37
-rw-r--r--src/kvirc/kernel/kvi_ircconnectionnetsplitdetectordata.h46
-rw-r--r--src/kvirc/kernel/kvi_ircconnectionserverinfo.cpp285
-rw-r--r--src/kvirc/kernel/kvi_ircconnectionserverinfo.h141
-rw-r--r--src/kvirc/kernel/kvi_ircconnectionstatedata.cpp42
-rw-r--r--src/kvirc/kernel/kvi_ircconnectionstatedata.h77
-rw-r--r--src/kvirc/kernel/kvi_ircconnectionstatistics.cpp38
-rw-r--r--src/kvirc/kernel/kvi_ircconnectionstatistics.h50
-rw-r--r--src/kvirc/kernel/kvi_ircconnectiontarget.cpp66
-rw-r--r--src/kvirc/kernel/kvi_ircconnectiontarget.h69
-rw-r--r--src/kvirc/kernel/kvi_ircconnectiontargetresolver.cpp555
-rw-r--r--src/kvirc/kernel/kvi_ircconnectiontargetresolver.h88
-rw-r--r--src/kvirc/kernel/kvi_ircconnectionuserinfo.cpp65
-rw-r--r--src/kvirc/kernel/kvi_ircconnectionuserinfo.h88
-rw-r--r--src/kvirc/kernel/kvi_irccontext.cpp906
-rw-r--r--src/kvirc/kernel/kvi_irccontext.h188
-rw-r--r--src/kvirc/kernel/kvi_ircdatastreammonitor.cpp41
-rw-r--r--src/kvirc/kernel/kvi_ircdatastreammonitor.h50
-rw-r--r--src/kvirc/kernel/kvi_irclink.cpp406
-rw-r--r--src/kvirc/kernel/kvi_irclink.h122
-rw-r--r--src/kvirc/kernel/kvi_ircsocket.cpp1910
-rw-r--r--src/kvirc/kernel/kvi_ircsocket.h174
-rw-r--r--src/kvirc/kernel/kvi_ircurl.cpp363
-rw-r--r--src/kvirc/kernel/kvi_ircurl.h78
-rw-r--r--src/kvirc/kernel/kvi_lagmeter.cpp266
-rw-r--r--src/kvirc/kernel/kvi_lagmeter.h74
-rw-r--r--src/kvirc/kernel/kvi_main.cpp412
-rw-r--r--src/kvirc/kernel/kvi_notifylist.cpp1277
-rw-r--r--src/kvirc/kernel/kvi_notifylist.h161
-rw-r--r--src/kvirc/kernel/kvi_options.cpp1381
-rw-r--r--src/kvirc/kernel/kvi_options.h737
-rw-r--r--src/kvirc/kernel/kvi_out.h169
-rw-r--r--src/kvirc/kernel/kvi_sslmaster.cpp168
-rw-r--r--src/kvirc/kernel/kvi_sslmaster.h47
-rw-r--r--src/kvirc/kernel/kvi_texticonmanager.cpp254
-rw-r--r--src/kvirc/kernel/kvi_texticonmanager.h85
-rw-r--r--src/kvirc/kernel/kvi_theme.cpp299
-rw-r--r--src/kvirc/kernel/kvi_theme.h171
-rw-r--r--src/kvirc/kernel/kvi_useraction.cpp46
-rw-r--r--src/kvirc/kernel/kvi_useraction.h83
-rw-r--r--src/kvirc/kernel/kvi_userinput.cpp148
-rw-r--r--src/kvirc/kernel/kvi_userinput.h43
-rw-r--r--src/kvirc/kernel/moc_kvi_action.cpp137
-rw-r--r--src/kvirc/kernel/moc_kvi_actionmanager.cpp143
-rw-r--r--src/kvirc/kernel/moc_kvi_coreactions.cpp927
-rw-r--r--src/kvirc/kernel/moc_kvi_filetransfer.cpp212
-rw-r--r--src/kvirc/kernel/moc_kvi_ircconnection.cpp202
-rw-r--r--src/kvirc/kernel/moc_kvi_ircconnectiontargetresolver.cpp128
-rw-r--r--src/kvirc/kernel/moc_kvi_irccontext.cpp119
-rw-r--r--src/kvirc/kernel/moc_kvi_irclink.cpp119
-rw-r--r--src/kvirc/kernel/moc_kvi_ircsocket.cpp134
-rw-r--r--src/kvirc/kvs/Makefile.am5
-rw-r--r--src/kvirc/kvs/kvi_kvs.cpp144
-rw-r--r--src/kvirc/kvs/kvi_kvs.h59
-rw-r--r--src/kvirc/kvs/kvi_kvs_action.cpp66
-rw-r--r--src/kvirc/kvs/kvi_kvs_action.h59
-rw-r--r--src/kvirc/kvs/kvi_kvs_aliasmanager.cpp121
-rw-r--r--src/kvirc/kvs/kvi_kvs_aliasmanager.h67
-rw-r--r--src/kvirc/kvs/kvi_kvs_array.cpp227
-rw-r--r--src/kvirc/kvs/kvi_kvs_array.h63
-rw-r--r--src/kvirc/kvs/kvi_kvs_arraycast.cpp44
-rw-r--r--src/kvirc/kvs/kvi_kvs_arraycast.h50
-rw-r--r--src/kvirc/kvs/kvi_kvs_asyncdnsoperation.cpp122
-rw-r--r--src/kvirc/kvs/kvi_kvs_asyncdnsoperation.h53
-rw-r--r--src/kvirc/kvs/kvi_kvs_asyncoperation.cpp66
-rw-r--r--src/kvirc/kvs/kvi_kvs_asyncoperation.h59
-rw-r--r--src/kvirc/kvs/kvi_kvs_callbackobject.cpp108
-rw-r--r--src/kvirc/kvs/kvi_kvs_callbackobject.h84
-rw-r--r--src/kvirc/kvs/kvi_kvs_corecallbackcommands.cpp1187
-rw-r--r--src/kvirc/kvs/kvi_kvs_corecallbackcommands.h78
-rw-r--r--src/kvirc/kvs/kvi_kvs_corefunctions.cpp156
-rw-r--r--src/kvirc/kvs/kvi_kvs_corefunctions.h148
-rw-r--r--src/kvirc/kvs/kvi_kvs_corefunctions_af.cpp1131
-rw-r--r--src/kvirc/kvs/kvi_kvs_corefunctions_gl.cpp888
-rw-r--r--src/kvirc/kvs/kvi_kvs_corefunctions_mr.cpp679
-rw-r--r--src/kvirc/kvs/kvi_kvs_corefunctions_sz.cpp1109
-rw-r--r--src/kvirc/kvs/kvi_kvs_coresimplecommands.cpp237
-rw-r--r--src/kvirc/kvs/kvi_kvs_coresimplecommands.h126
-rw-r--r--src/kvirc/kvs/kvi_kvs_coresimplecommands_af.cpp1277
-rw-r--r--src/kvirc/kvs/kvi_kvs_coresimplecommands_gl.cpp693
-rw-r--r--src/kvirc/kvs/kvi_kvs_coresimplecommands_mr.cpp1335
-rw-r--r--src/kvirc/kvs/kvi_kvs_coresimplecommands_sz.cpp975
-rw-r--r--src/kvirc/kvs/kvi_kvs_dnsmanager.cpp180
-rw-r--r--src/kvirc/kvs/kvi_kvs_dnsmanager.h86
-rw-r--r--src/kvirc/kvs/kvi_kvs_event.cpp80
-rw-r--r--src/kvirc/kvs/kvi_kvs_event.h54
-rw-r--r--src/kvirc/kvs/kvi_kvs_eventhandler.cpp78
-rw-r--r--src/kvirc/kvs/kvi_kvs_eventhandler.h106
-rw-r--r--src/kvirc/kvs/kvi_kvs_eventmanager.cpp678
-rw-r--r--src/kvirc/kvs/kvi_kvs_eventmanager.h120
-rw-r--r--src/kvirc/kvs/kvi_kvs_eventtable.cpp3147
-rw-r--r--src/kvirc/kvs/kvi_kvs_eventtable.h212
-rw-r--r--src/kvirc/kvs/kvi_kvs_eventtriggers.h289
-rw-r--r--src/kvirc/kvs/kvi_kvs_hash.cpp96
-rw-r--r--src/kvirc/kvs/kvi_kvs_hash.h64
-rw-r--r--src/kvirc/kvs/kvi_kvs_kernel.cpp221
-rw-r--r--src/kvirc/kvs/kvi_kvs_kernel.h134
-rw-r--r--src/kvirc/kvs/kvi_kvs_moduleinterface.cpp180
-rw-r--r--src/kvirc/kvs/kvi_kvs_moduleinterface.h228
-rw-r--r--src/kvirc/kvs/kvi_kvs_object.cpp1743
-rw-r--r--src/kvirc/kvs/kvi_kvs_object.h192
-rw-r--r--src/kvirc/kvs/kvi_kvs_object_class.cpp234
-rw-r--r--src/kvirc/kvs/kvi_kvs_object_class.h102
-rw-r--r--src/kvirc/kvs/kvi_kvs_object_controller.cpp229
-rw-r--r--src/kvirc/kvs/kvi_kvs_object_controller.h70
-rw-r--r--src/kvirc/kvs/kvi_kvs_object_functioncall.cpp28
-rw-r--r--src/kvirc/kvs/kvi_kvs_object_functioncall.h49
-rw-r--r--src/kvirc/kvs/kvi_kvs_object_functionhandler.cpp50
-rw-r--r--src/kvirc/kvs/kvi_kvs_object_functionhandler.h57
-rw-r--r--src/kvirc/kvs/kvi_kvs_object_functionhandlerimpl.cpp148
-rw-r--r--src/kvirc/kvs/kvi_kvs_object_functionhandlerimpl.h115
-rw-r--r--src/kvirc/kvs/kvi_kvs_parameterprocessor.cpp371
-rw-r--r--src/kvirc/kvs/kvi_kvs_parameterprocessor.h140
-rw-r--r--src/kvirc/kvs/kvi_kvs_parser.cpp3827
-rw-r--r--src/kvirc/kvs/kvi_kvs_parser.h300
-rw-r--r--src/kvirc/kvs/kvi_kvs_parser_command.cpp339
-rw-r--r--src/kvirc/kvs/kvi_kvs_parser_comment.cpp101
-rw-r--r--src/kvirc/kvs/kvi_kvs_parser_dollar.cpp331
-rw-r--r--src/kvirc/kvs/kvi_kvs_parser_expression.cpp636
-rw-r--r--src/kvirc/kvs/kvi_kvs_parser_lside.cpp1196
-rw-r--r--src/kvirc/kvs/kvi_kvs_parser_macros.h47
-rw-r--r--src/kvirc/kvs/kvi_kvs_parser_specialcommands.cpp1988
-rw-r--r--src/kvirc/kvs/kvi_kvs_popupmanager.cpp117
-rw-r--r--src/kvirc/kvs/kvi_kvs_popupmanager.h57
-rw-r--r--src/kvirc/kvs/kvi_kvs_popupmenu.cpp1234
-rw-r--r--src/kvirc/kvs/kvi_kvs_popupmenu.h300
-rw-r--r--src/kvirc/kvs/kvi_kvs_processmanager.cpp376
-rw-r--r--src/kvirc/kvs/kvi_kvs_processmanager.h105
-rw-r--r--src/kvirc/kvs/kvi_kvs_report.cpp262
-rw-r--r--src/kvirc/kvs/kvi_kvs_report.h75
-rw-r--r--src/kvirc/kvs/kvi_kvs_runtimecall.cpp50
-rw-r--r--src/kvirc/kvs/kvi_kvs_runtimecall.h82
-rw-r--r--src/kvirc/kvs/kvi_kvs_runtimecontext.cpp206
-rw-r--r--src/kvirc/kvs/kvi_kvs_runtimecontext.h256
-rw-r--r--src/kvirc/kvs/kvi_kvs_rwevaluationresult.cpp66
-rw-r--r--src/kvirc/kvs/kvi_kvs_rwevaluationresult.h70
-rw-r--r--src/kvirc/kvs/kvi_kvs_script.cpp356
-rw-r--r--src/kvirc/kvs/kvi_kvs_script.h155
-rw-r--r--src/kvirc/kvs/kvi_kvs_scriptaddonmanager.cpp386
-rw-r--r--src/kvirc/kvs/kvi_kvs_scriptaddonmanager.h129
-rw-r--r--src/kvirc/kvs/kvi_kvs_switchlist.cpp75
-rw-r--r--src/kvirc/kvs/kvi_kvs_switchlist.h87
-rw-r--r--src/kvirc/kvs/kvi_kvs_timermanager.cpp256
-rw-r--r--src/kvirc/kvs/kvi_kvs_timermanager.h123
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode.h375
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_aliasfunctioncall.cpp84
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_aliasfunctioncall.h45
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_aliassimplecommand.cpp120
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_aliassimplecommand.h47
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_arraycount.cpp86
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_arraycount.h47
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_arrayelement.cpp161
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_arrayelement.h54
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_arrayorhashelement.cpp45
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_arrayorhashelement.h42
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_arrayreferenceassert.cpp107
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_arrayreferenceassert.h54
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_base.cpp37
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_base.h51
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_baseobjectfunctioncall.cpp72
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_baseobjectfunctioncall.h50
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_callbackcommand.cpp73
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_callbackcommand.h48
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_command.cpp80
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_command.h54
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_commandevaluation.cpp60
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_commandevaluation.h46
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_commandwithparameters.cpp66
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_commandwithparameters.h49
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_compositedata.cpp86
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_compositedata.h48
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_constantdata.cpp80
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_constantdata.h52
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_corecallbackcommand.cpp72
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_corecallbackcommand.h51
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_corefunctioncall.cpp62
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_corefunctioncall.h48
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_coresimplecommand.cpp70
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_coresimplecommand.h49
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_data.cpp107
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_data.h66
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_datalist.cpp110
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_datalist.h57
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_expression.cpp776
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_expression.h249
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_expressionreturn.cpp68
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_expressionreturn.h45
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_extendedscopevariable.cpp79
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_extendedscopevariable.h45
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_functioncall.cpp62
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_functioncall.h47
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_globalvariable.cpp63
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_globalvariable.h45
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_hashcount.cpp88
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_hashcount.h47
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_hashelement.cpp164
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_hashelement.h52
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_hashreferenceassert.cpp107
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_hashreferenceassert.h53
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_indirectdata.cpp46
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_indirectdata.h42
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_instruction.cpp43
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_instruction.h54
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_instructionblock.cpp88
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_instructionblock.h55
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_localvariable.cpp76
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_localvariable.h45
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_modulecallbackcommand.cpp97
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_modulecallbackcommand.h50
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_modulefunctioncall.cpp90
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_modulefunctioncall.h48
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_modulesimplecommand.cpp97
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_modulesimplecommand.h48
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_multipleparameteridentifier.cpp89
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_multipleparameteridentifier.h49
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_objectfield.cpp80
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_objectfield.h47
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_objectfunctioncall.cpp60
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_objectfunctioncall.h45
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_operation.cpp1497
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_operation.h296
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_parameterreturn.cpp88
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_parameterreturn.h45
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_rebindingswitch.cpp96
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_rebindingswitch.h49
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_scopeoperator.cpp148
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_scopeoperator.h58
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_simplecommand.cpp58
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_simplecommand.h43
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_singleparameteridentifier.cpp74
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_singleparameteridentifier.h50
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_specialcommand.cpp54
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_specialcommand.h41
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_specialcommandbreak.cpp55
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_specialcommandbreak.h45
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_specialcommandclass.cpp157
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_specialcommandclass.h69
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_specialcommanddefpopup.cpp424
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_specialcommanddefpopup.h193
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_specialcommanddo.cpp87
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_specialcommanddo.h51
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_specialcommandfor.cpp133
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_specialcommandfor.h53
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_specialcommandforeach.cpp191
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_specialcommandforeach.h53
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_specialcommandif.cpp94
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_specialcommandif.h50
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_specialcommandswitch.cpp349
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_specialcommandswitch.h117
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_specialcommandunset.cpp74
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_specialcommandunset.h47
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_specialcommandwhile.cpp97
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_specialcommandwhile.h51
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_stringcast.cpp67
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_stringcast.h45
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_switchlist.cpp170
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_switchlist.h61
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_thisobjectfunctioncall.cpp73
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_thisobjectfunctioncall.h49
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_variable.cpp54
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_variable.h47
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_voidfunctioncall.cpp66
-rw-r--r--src/kvirc/kvs/kvi_kvs_treenode_voidfunctioncall.h47
-rw-r--r--src/kvirc/kvs/kvi_kvs_types.h38
-rw-r--r--src/kvirc/kvs/kvi_kvs_useraction.cpp277
-rw-r--r--src/kvirc/kvs/kvi_kvs_useraction.h97
-rw-r--r--src/kvirc/kvs/kvi_kvs_variant.cpp1615
-rw-r--r--src/kvirc/kvs/kvi_kvs_variant.h208
-rw-r--r--src/kvirc/kvs/kvi_kvs_variantlist.cpp199
-rw-r--r--src/kvirc/kvs/kvi_kvs_variantlist.h81
-rw-r--r--src/kvirc/kvs/moc_kvi_kvs_action.cpp92
-rw-r--r--src/kvirc/kvs/moc_kvi_kvs_asyncdnsoperation.cpp107
-rw-r--r--src/kvirc/kvs/moc_kvi_kvs_asyncoperation.cpp92
-rw-r--r--src/kvirc/kvs/moc_kvi_kvs_dnsmanager.cpp104
-rw-r--r--src/kvirc/kvs/moc_kvi_kvs_object.cpp104
-rw-r--r--src/kvirc/kvs/moc_kvi_kvs_popupmenu.cpp217
-rw-r--r--src/kvirc/kvs/moc_kvi_kvs_processmanager.cpp116
-rw-r--r--src/kvirc/kvs/moc_kvi_kvs_timermanager.cpp92
-rw-r--r--src/kvirc/kvs/moc_kvi_kvs_useraction.cpp92
-rw-r--r--src/kvirc/module/Makefile.am5
-rw-r--r--src/kvirc/module/kvi_mexlinkfilter.cpp35
-rw-r--r--src/kvirc/module/kvi_mexlinkfilter.h45
-rw-r--r--src/kvirc/module/kvi_mexserverimport.cpp33
-rw-r--r--src/kvirc/module/kvi_mexserverimport.h45
-rw-r--r--src/kvirc/module/kvi_mextoolbar.cpp38
-rw-r--r--src/kvirc/module/kvi_mextoolbar.h38
-rw-r--r--src/kvirc/module/kvi_module.cpp379
-rw-r--r--src/kvirc/module/kvi_module.h204
-rw-r--r--src/kvirc/module/kvi_moduleextension.cpp253
-rw-r--r--src/kvirc/module/kvi_moduleextension.h143
-rw-r--r--src/kvirc/module/kvi_modulemanager.cpp369
-rw-r--r--src/kvirc/module/kvi_modulemanager.h70
-rw-r--r--src/kvirc/module/moc_kvi_mexlinkfilter.cpp94
-rw-r--r--src/kvirc/module/moc_kvi_mexserverimport.cpp124
-rw-r--r--src/kvirc/module/moc_kvi_mextoolbar.cpp94
-rw-r--r--src/kvirc/module/moc_kvi_modulemanager.cpp129
-rw-r--r--src/kvirc/sparser/Makefile.am5
-rw-r--r--src/kvirc/sparser/kvi_antispam.cpp122
-rw-r--r--src/kvirc/sparser/kvi_antispam.h31
-rw-r--r--src/kvirc/sparser/kvi_ircmessage.cpp179
-rw-r--r--src/kvirc/sparser/kvi_ircmessage.h106
-rw-r--r--src/kvirc/sparser/kvi_numeric.h430
-rw-r--r--src/kvirc/sparser/kvi_sp_ctcp.cpp1855
-rw-r--r--src/kvirc/sparser/kvi_sp_literal.cpp1867
-rw-r--r--src/kvirc/sparser/kvi_sp_numeric.cpp2003
-rw-r--r--src/kvirc/sparser/kvi_sp_tables.cpp1089
-rw-r--r--src/kvirc/sparser/kvi_sparser.cpp150
-rw-r--r--src/kvirc/sparser/kvi_sparser.h268
-rw-r--r--src/kvirc/ui/Makefile.am5
-rw-r--r--src/kvirc/ui/kvi_actiondrawer.cpp227
-rw-r--r--src/kvirc/ui/kvi_actiondrawer.h107
-rw-r--r--src/kvirc/ui/kvi_channel.cpp1628
-rw-r--r--src/kvirc/ui/kvi_channel.h313
-rw-r--r--src/kvirc/ui/kvi_colorwin.cpp122
-rw-r--r--src/kvirc/ui/kvi_colorwin.h47
-rw-r--r--src/kvirc/ui/kvi_console.cpp1283
-rw-r--r--src/kvirc/ui/kvi_console.h212
-rw-r--r--src/kvirc/ui/kvi_cryptcontroller.cpp390
-rw-r--r--src/kvirc/ui/kvi_cryptcontroller.h116
-rw-r--r--src/kvirc/ui/kvi_ctcppagedialog.cpp147
-rw-r--r--src/kvirc/ui/kvi_ctcppagedialog.h56
-rw-r--r--src/kvirc/ui/kvi_customtoolbar.cpp670
-rw-r--r--src/kvirc/ui/kvi_customtoolbar.h91
-rw-r--r--src/kvirc/ui/kvi_debugwindow.cpp132
-rw-r--r--src/kvirc/ui/kvi_debugwindow.h54
-rw-r--r--src/kvirc/ui/kvi_dynamictooltip.cpp61
-rw-r--r--src/kvirc/ui/kvi_dynamictooltip.h61
-rw-r--r--src/kvirc/ui/kvi_filedialog.cpp229
-rw-r--r--src/kvirc/ui/kvi_filedialog.h55
-rw-r--r--src/kvirc/ui/kvi_frame.cpp1450
-rw-r--r--src/kvirc/ui/kvi_frame.h259
-rw-r--r--src/kvirc/ui/kvi_historywin.cpp255
-rw-r--r--src/kvirc/ui/kvi_historywin.h61
-rw-r--r--src/kvirc/ui/kvi_htmldialog.cpp155
-rw-r--r--src/kvirc/ui/kvi_htmldialog.h87
-rw-r--r--src/kvirc/ui/kvi_imagedialog.cpp367
-rw-r--r--src/kvirc/ui/kvi_imagedialog.h109
-rw-r--r--src/kvirc/ui/kvi_input.cpp2680
-rw-r--r--src/kvirc/ui/kvi_input.h262
-rw-r--r--src/kvirc/ui/kvi_ipeditor.cpp453
-rw-r--r--src/kvirc/ui/kvi_ipeditor.h62
-rw-r--r--src/kvirc/ui/kvi_irctoolbar.cpp441
-rw-r--r--src/kvirc/ui/kvi_irctoolbar.h95
-rw-r--r--src/kvirc/ui/kvi_ircview.cpp5161
-rw-r--r--src/kvirc/ui/kvi_ircview.h252
-rw-r--r--src/kvirc/ui/kvi_ircviewprivate.h164
-rw-r--r--src/kvirc/ui/kvi_ircviewtools.cpp348
-rw-r--r--src/kvirc/ui/kvi_ircviewtools.h119
-rw-r--r--src/kvirc/ui/kvi_listview.cpp212
-rw-r--r--src/kvirc/ui/kvi_listview.h58
-rw-r--r--src/kvirc/ui/kvi_maskeditor.cpp350
-rw-r--r--src/kvirc/ui/kvi_maskeditor.h108
-rw-r--r--src/kvirc/ui/kvi_mdicaption.cpp285
-rw-r--r--src/kvirc/ui/kvi_mdicaption.h101
-rw-r--r--src/kvirc/ui/kvi_mdichild.cpp576
-rw-r--r--src/kvirc/ui/kvi_mdichild.h122
-rw-r--r--src/kvirc/ui/kvi_mdimanager.cpp1126
-rw-r--r--src/kvirc/ui/kvi_mdimanager.h144
-rw-r--r--src/kvirc/ui/kvi_menubar.cpp415
-rw-r--r--src/kvirc/ui/kvi_menubar.h83
-rw-r--r--src/kvirc/ui/kvi_modeeditor.cpp336
-rw-r--r--src/kvirc/ui/kvi_modeeditor.h70
-rwxr-xr-xsrc/kvirc/ui/kvi_modew.cpp175
-rwxr-xr-xsrc/kvirc/ui/kvi_modew.h57
-rw-r--r--src/kvirc/ui/kvi_msgbox.cpp89
-rw-r--r--src/kvirc/ui/kvi_msgbox.h53
-rw-r--r--src/kvirc/ui/kvi_optionswidget.cpp722
-rw-r--r--src/kvirc/ui/kvi_optionswidget.h163
-rw-r--r--src/kvirc/ui/kvi_query.cpp659
-rw-r--r--src/kvirc/ui/kvi_query.h95
-rw-r--r--src/kvirc/ui/kvi_scriptbutton.cpp98
-rw-r--r--src/kvirc/ui/kvi_scriptbutton.h79
-rw-r--r--src/kvirc/ui/kvi_scripteditor.cpp139
-rw-r--r--src/kvirc/ui/kvi_scripteditor.h69
-rw-r--r--src/kvirc/ui/kvi_selectors.cpp839
-rw-r--r--src/kvirc/ui/kvi_selectors.h367
-rw-r--r--src/kvirc/ui/kvi_splash.cpp222
-rw-r--r--src/kvirc/ui/kvi_splash.h72
-rw-r--r--src/kvirc/ui/kvi_statusbar.cpp643
-rw-r--r--src/kvirc/ui/kvi_statusbar.h130
-rw-r--r--src/kvirc/ui/kvi_statusbarapplet.cpp563
-rw-r--r--src/kvirc/ui/kvi_statusbarapplet.h195
-rw-r--r--src/kvirc/ui/kvi_styled_controls.cpp373
-rw-r--r--src/kvirc/ui/kvi_styled_controls.h113
-rw-r--r--src/kvirc/ui/kvi_taskbar.cpp1509
-rw-r--r--src/kvirc/ui/kvi_taskbar.h312
-rw-r--r--src/kvirc/ui/kvi_texticonwin.cpp283
-rw-r--r--src/kvirc/ui/kvi_texticonwin.h64
-rw-r--r--src/kvirc/ui/kvi_themedlabel.cpp154
-rw-r--r--src/kvirc/ui/kvi_themedlabel.h62
-rw-r--r--src/kvirc/ui/kvi_toolbar.cpp160
-rw-r--r--src/kvirc/ui/kvi_toolbar.h52
-rw-r--r--src/kvirc/ui/kvi_toolwindows_container.cpp140
-rw-r--r--src/kvirc/ui/kvi_toolwindows_container.h65
-rw-r--r--src/kvirc/ui/kvi_topicw.cpp834
-rw-r--r--src/kvirc/ui/kvi_topicw.h120
-rw-r--r--src/kvirc/ui/kvi_userlistview.cpp1972
-rw-r--r--src/kvirc/ui/kvi_userlistview.h259
-rw-r--r--src/kvirc/ui/kvi_window.cpp1518
-rw-r--r--src/kvirc/ui/kvi_window.h393
-rw-r--r--src/kvirc/ui/moc_kvi_actiondrawer.cpp238
-rw-r--r--src/kvirc/ui/moc_kvi_customtoolbar.cpp180
-rw-r--r--src/kvirc/ui/moc_kvi_debugwindow.cpp92
-rw-r--r--src/kvirc/ui/moc_kvi_htmldialog.cpp107
-rw-r--r--src/kvirc/ui/moc_kvi_imagedialog.cpp126
-rw-r--r--src/kvirc/ui/moc_kvi_ircviewtools.cpp116
-rw-r--r--src/kvirc/ui/moc_kvi_listview.cpp92
-rw-r--r--src/kvirc/ui/moc_kvi_mdicaption.cpp238
-rw-r--r--src/kvirc/ui/moc_kvi_mdichild.cpp141
-rw-r--r--src/kvirc/ui/moc_kvi_mdimanager.cpp191
-rw-r--r--src/kvirc/ui/moc_kvi_statusbar.cpp126
-rw-r--r--src/kvirc/ui/moc_kvi_statusbarapplet.cpp496
-rw-r--r--src/kvirc/ui/moc_kvi_toolwindows_container.cpp165
-rw-r--r--src/modules/Makefile.am61
-rw-r--r--src/modules/about/ENTRIES259
-rw-r--r--src/modules/about/Makefile.am27
-rw-r--r--src/modules/about/aboutdialog.cpp166
-rw-r--r--src/modules/about/aboutdialog.h39
-rw-r--r--src/modules/about/abouttext.inc768
-rw-r--r--src/modules/about/libkviabout.cpp100
-rw-r--r--src/modules/about/mkabouttext.pl172
-rw-r--r--src/modules/action/Makefile.am17
-rw-r--r--src/modules/action/libkviaction.cpp533
-rw-r--r--src/modules/actioneditor/Makefile.am21
-rw-r--r--src/modules/actioneditor/actioneditor.cpp1009
-rw-r--r--src/modules/actioneditor/actioneditor.h210
-rw-r--r--src/modules/actioneditor/libkviactioneditor.cpp86
-rw-r--r--src/modules/addon/Makefile.am22
-rw-r--r--src/modules/addon/libkviaddon.cpp659
-rw-r--r--src/modules/addon/managementdialog.cpp403
-rw-r--r--src/modules/addon/managementdialog.h114
-rw-r--r--src/modules/addon/pics/Makefile.am9
-rw-r--r--src/modules/addon/pics/kvi_dialog_addons.pngbin0 -> 191267 bytes
-rw-r--r--src/modules/aliaseditor/Makefile.am21
-rw-r--r--src/modules/aliaseditor/aliaseditor.cpp1408
-rw-r--r--src/modules/aliaseditor/aliaseditor.h197
-rw-r--r--src/modules/aliaseditor/libkvialiaseditor.cpp90
-rw-r--r--src/modules/avatar/Makefile.am20
-rw-r--r--src/modules/avatar/libkviavatar.cpp585
-rw-r--r--src/modules/avatar/libkviavatar.h54
-rw-r--r--src/modules/chan/Makefile.am18
-rw-r--r--src/modules/chan/libkvichan.cpp1635
-rw-r--r--src/modules/channelsjoin/Makefile.am20
-rw-r--r--src/modules/channelsjoin/channelsjoinwindow.cpp301
-rw-r--r--src/modules/channelsjoin/channelsjoinwindow.h70
-rw-r--r--src/modules/channelsjoin/libkvichannelsjoin.cpp108
-rw-r--r--src/modules/clock/Makefile.am20
-rw-r--r--src/modules/clock/libkviclock.cpp257
-rw-r--r--src/modules/clock/libkviclock.h46
-rw-r--r--src/modules/codetester/Makefile.am17
-rw-r--r--src/modules/codetester/codetester.cpp157
-rw-r--r--src/modules/codetester/codetester.h67
-rw-r--r--src/modules/codetester/libkvicodetester.cpp89
-rw-r--r--src/modules/config/Makefile.am18
-rw-r--r--src/modules/config/libkviconfig.cpp877
-rw-r--r--src/modules/context/Makefile.am18
-rw-r--r--src/modules/context/libkvicontext.cpp401
-rw-r--r--src/modules/dcc/Makefile.am66
-rw-r--r--src/modules/dcc/adpcmcodec.cpp294
-rw-r--r--src/modules/dcc/adpcmcodec.h59
-rw-r--r--src/modules/dcc/broker.cpp898
-rw-r--r--src/modules/dcc/broker.h124
-rw-r--r--src/modules/dcc/canvas.cpp301
-rw-r--r--src/modules/dcc/canvas.h74
-rw-r--r--src/modules/dcc/canvaswidget.cpp1601
-rw-r--r--src/modules/dcc/canvaswidget.h322
-rw-r--r--src/modules/dcc/chat.cpp842
-rw-r--r--src/modules/dcc/chat.h101
-rw-r--r--src/modules/dcc/codec.cpp88
-rw-r--r--src/modules/dcc/codec.h57
-rw-r--r--src/modules/dcc/descriptor.cpp224
-rw-r--r--src/modules/dcc/descriptor.h163
-rw-r--r--src/modules/dcc/dialogs.cpp206
-rw-r--r--src/modules/dcc/dialogs.h82
-rw-r--r--src/modules/dcc/gsmcodec.cpp149
-rw-r--r--src/modules/dcc/gsmcodec.h54
-rw-r--r--src/modules/dcc/kvi_dccfiletransfericons.pngbin0 -> 25192 bytes
-rw-r--r--src/modules/dcc/libkvidcc.cpp2766
-rw-r--r--src/modules/dcc/marshal.cpp647
-rw-r--r--src/modules/dcc/marshal.h112
-rw-r--r--src/modules/dcc/requests.cpp1154
-rw-r--r--src/modules/dcc/send.cpp1898
-rw-r--r--src/modules/dcc/send.h260
-rw-r--r--src/modules/dcc/thread.cpp111
-rw-r--r--src/modules/dcc/thread.h79
-rw-r--r--src/modules/dcc/utils.cpp169
-rw-r--r--src/modules/dcc/utils.h34
-rw-r--r--src/modules/dcc/voice.cpp1041
-rw-r--r--src/modules/dcc/voice.h440
-rw-r--r--src/modules/dcc/window.cpp53
-rw-r--r--src/modules/dcc/window.h49
-rw-r--r--src/modules/dialog/Makefile.am21
-rw-r--r--src/modules/dialog/libkvidialog.cpp920
-rw-r--r--src/modules/dialog/libkvidialog.h133
-rw-r--r--src/modules/dockwidget/Makefile.am33
-rw-r--r--src/modules/dockwidget/kvi_dock.pngbin0 -> 1959 bytes
-rw-r--r--src/modules/dockwidget/kvi_dock_part-0.pngbin0 -> 1477 bytes
-rw-r--r--src/modules/dockwidget/kvi_dock_part-1.pngbin0 -> 1027 bytes
-rw-r--r--src/modules/dockwidget/kvi_dock_part-2.pngbin0 -> 1034 bytes
-rw-r--r--src/modules/dockwidget/libkvidockwidget.h34
-rw-r--r--src/modules/dockwidget/libkvidockwidget_qt3.cpp858
-rw-r--r--src/modules/dockwidget/libkvidockwidget_qt3.h95
-rw-r--r--src/modules/dockwidget/libkvidockwidget_qt4.cpp691
-rw-r--r--src/modules/dockwidget/libkvidockwidget_qt4.h81
-rw-r--r--src/modules/editor/Makefile.am20
-rw-r--r--src/modules/editor/libkvieditor.cpp94
-rw-r--r--src/modules/editor/scripteditor.cpp1224
-rw-r--r--src/modules/editor/scripteditor.h200
-rw-r--r--src/modules/eventeditor/Makefile.am21
-rw-r--r--src/modules/eventeditor/eventeditor.cpp536
-rw-r--r--src/modules/eventeditor/eventeditor.h120
-rw-r--r--src/modules/eventeditor/libkvieventeditor.cpp88
-rw-r--r--src/modules/file/Makefile.am18
-rw-r--r--src/modules/file/libkvifile.cpp1260
-rw-r--r--src/modules/filetransferwindow/Makefile.am22
-rw-r--r--src/modules/filetransferwindow/caps/Makefile.am9
-rw-r--r--src/modules/filetransferwindow/caps/filetransferwindow0
-rw-r--r--src/modules/filetransferwindow/filetransferwindow.cpp768
-rw-r--r--src/modules/filetransferwindow/filetransferwindow.h111
-rw-r--r--src/modules/filetransferwindow/libkvifiletransferwindow.cpp161
-rw-r--r--src/modules/help/Makefile.am22
-rw-r--r--src/modules/help/helpwidget.cpp154
-rw-r--r--src/modules/help/helpwidget.h61
-rw-r--r--src/modules/help/helpwindow.cpp329
-rw-r--r--src/modules/help/helpwindow.h75
-rwxr-xr-xsrc/modules/help/index.cpp854
-rwxr-xr-xsrc/modules/help/index.h124
-rw-r--r--src/modules/help/libkvihelp.cpp236
-rw-r--r--src/modules/http/Makefile.am26
-rw-r--r--src/modules/http/httpfiletransfer.cpp489
-rw-r--r--src/modules/http/httpfiletransfer.h104
-rw-r--r--src/modules/http/kvi_httpicons.pngbin0 -> 19630 bytes
-rw-r--r--src/modules/http/libkvihttp.cpp324
-rw-r--r--src/modules/ident/Makefile.am20
-rw-r--r--src/modules/ident/libkviident.cpp615
-rw-r--r--src/modules/ident/libkviident.h86
-rw-r--r--src/modules/iograph/Makefile.am20
-rw-r--r--src/modules/iograph/libkviiograph.cpp297
-rw-r--r--src/modules/iograph/libkviiograph.h55
-rw-r--r--src/modules/lamerizer/Makefile.am27
-rw-r--r--src/modules/lamerizer/lamerizer1
-rw-r--r--src/modules/lamerizer/libkvilamerizer.cpp279
-rw-r--r--src/modules/lamerizer/libkvilamerizer.h47
-rw-r--r--src/modules/links/Makefile.am20
-rw-r--r--src/modules/links/libkvilinks.cpp116
-rw-r--r--src/modules/links/linkswindow.cpp472
-rw-r--r--src/modules/links/linkswindow.h89
-rw-r--r--src/modules/list/Makefile.am20
-rw-r--r--src/modules/list/libkvilist.cpp101
-rw-r--r--src/modules/list/listwindow.cpp535
-rw-r--r--src/modules/list/listwindow.h122
-rw-r--r--src/modules/log/Makefile.am18
-rw-r--r--src/modules/log/libkvilog.cpp309
-rw-r--r--src/modules/logview/Makefile.am23
-rw-r--r--src/modules/logview/caps/Makefile.am9
-rw-r--r--src/modules/logview/caps/logview0
-rw-r--r--src/modules/logview/libkvilogview.cpp170
-rw-r--r--src/modules/logview/logviewmdiwindow.cpp477
-rw-r--r--src/modules/logview/logviewmdiwindow.h125
-rw-r--r--src/modules/logview/logviewwidget.cpp76
-rw-r--r--src/modules/logview/logviewwidget.h86
-rw-r--r--src/modules/mask/Makefile.am18
-rw-r--r--src/modules/mask/libkvimask.cpp201
-rw-r--r--src/modules/math/Makefile.am18
-rw-r--r--src/modules/math/libkvimath.cpp475
-rw-r--r--src/modules/mediaplayer/Makefile.am36
-rw-r--r--src/modules/mediaplayer/libkvimediaplayer.cpp1751
-rw-r--r--src/modules/mediaplayer/mp_amarokinterface.cpp189
-rw-r--r--src/modules/mediaplayer/mp_amarokinterface.h76
-rw-r--r--src/modules/mediaplayer/mp_amipinterface.cpp400
-rw-r--r--src/modules/mediaplayer/mp_amipinterface.h58
-rw-r--r--src/modules/mediaplayer/mp_dcopinterface.cpp224
-rw-r--r--src/modules/mediaplayer/mp_dcopinterface.h57
-rw-r--r--src/modules/mediaplayer/mp_interface.cpp277
-rw-r--r--src/modules/mediaplayer/mp_interface.h238
-rw-r--r--src/modules/mediaplayer/mp_jukinterface.cpp185
-rw-r--r--src/modules/mediaplayer/mp_jukinterface.h77
-rw-r--r--src/modules/mediaplayer/mp_mp3.cpp468
-rw-r--r--src/modules/mediaplayer/mp_mp3.h137
-rw-r--r--src/modules/mediaplayer/mp_winampinterface.cpp566
-rw-r--r--src/modules/mediaplayer/mp_winampinterface.h76
-rw-r--r--src/modules/mediaplayer/mp_xmmsinterface.cpp355
-rw-r--r--src/modules/mediaplayer/mp_xmmsinterface.h84
-rw-r--r--src/modules/mircimport/Makefile.am22
-rw-r--r--src/modules/mircimport/caps/Makefile.am9
-rw-r--r--src/modules/mircimport/caps/mircimport1
-rw-r--r--src/modules/mircimport/libkvimircimport.cpp385
-rw-r--r--src/modules/mircimport/libkvimircimport.h82
-rw-r--r--src/modules/mircimport/pics/Makefile.am9
-rw-r--r--src/modules/mircimport/pics/kvi_mircimport.pngbin0 -> 733 bytes
-rw-r--r--src/modules/my/Makefile.am20
-rw-r--r--src/modules/my/idle.cpp133
-rw-r--r--src/modules/my/idle.h84
-rw-r--r--src/modules/my/idle_mac.cpp162
-rw-r--r--src/modules/my/idle_x11.cpp113
-rw-r--r--src/modules/my/libkvimy.cpp430
-rw-r--r--src/modules/notifier/Makefile.am44
-rw-r--r--src/modules/notifier/libkvinotifier.cpp323
-rw-r--r--src/modules/notifier/libkvinotifier.kvc28
-rw-r--r--src/modules/notifier/notifiermessage.cpp107
-rw-r--r--src/modules/notifier/notifiermessage.h97
-rw-r--r--src/modules/notifier/notifiersettings.h66
-rw-r--r--src/modules/notifier/notifierwindow.cpp1427
-rw-r--r--src/modules/notifier/notifierwindow.h194
-rw-r--r--src/modules/notifier/notifierwindowbody.cpp232
-rw-r--r--src/modules/notifier/notifierwindowbody.h147
-rw-r--r--src/modules/notifier/notifierwindowborder.cpp220
-rw-r--r--src/modules/notifier/notifierwindowborder.h154
-rw-r--r--src/modules/notifier/notifierwindowprogressbar.cpp51
-rw-r--r--src/modules/notifier/notifierwindowprogressbar.h67
-rw-r--r--src/modules/notifier/notifierwindowtabs.cpp705
-rw-r--r--src/modules/notifier/notifierwindowtabs.h263
-rwxr-xr-xsrc/modules/notifier/pics/Makefile.am9
-rwxr-xr-xsrc/modules/notifier/pics/notifier_background.pngbin0 -> 4306 bytes
-rw-r--r--src/modules/notifier/pics/notifier_close.pngbin0 -> 311 bytes
-rw-r--r--src/modules/notifier/pics/notifier_down.pngbin0 -> 491 bytes
-rw-r--r--src/modules/notifier/pics/notifier_icon_body_next_clicked.pngbin0 -> 630 bytes
-rw-r--r--src/modules/notifier/pics/notifier_icon_body_next_off.pngbin0 -> 561 bytes
-rw-r--r--src/modules/notifier/pics/notifier_icon_body_next_on.pngbin0 -> 568 bytes
-rw-r--r--src/modules/notifier/pics/notifier_icon_body_prev_clicked.pngbin0 -> 599 bytes
-rw-r--r--src/modules/notifier/pics/notifier_icon_body_prev_off.pngbin0 -> 520 bytes
-rw-r--r--src/modules/notifier/pics/notifier_icon_body_prev_on.pngbin0 -> 535 bytes
-rw-r--r--src/modules/notifier/pics/notifier_icon_body_write_clicked.pngbin0 -> 166 bytes
-rw-r--r--src/modules/notifier/pics/notifier_icon_body_write_off.pngbin0 -> 171 bytes
-rw-r--r--src/modules/notifier/pics/notifier_icon_body_write_on.pngbin0 -> 160 bytes
-rw-r--r--src/modules/notifier/pics/notifier_icon_close_clicked.pngbin0 -> 1087 bytes
-rw-r--r--src/modules/notifier/pics/notifier_icon_close_clicked_hl.pngbin0 -> 1064 bytes
-rw-r--r--src/modules/notifier/pics/notifier_icon_close_out.pngbin0 -> 1248 bytes
-rw-r--r--src/modules/notifier/pics/notifier_icon_close_out_hl.pngbin0 -> 1214 bytes
-rw-r--r--src/modules/notifier/pics/notifier_icon_close_over.pngbin0 -> 1374 bytes
-rw-r--r--src/modules/notifier/pics/notifier_icon_close_over_hl.pngbin0 -> 1338 bytes
-rw-r--r--src/modules/notifier/pics/notifier_icon_tab_close_clicked.pngbin0 -> 518 bytes
-rw-r--r--src/modules/notifier/pics/notifier_icon_tab_close_off.pngbin0 -> 428 bytes
-rw-r--r--src/modules/notifier/pics/notifier_icon_tab_close_on.pngbin0 -> 517 bytes
-rw-r--r--src/modules/notifier/pics/notifier_icon_tab_next_clicked.pngbin0 -> 809 bytes
-rw-r--r--src/modules/notifier/pics/notifier_icon_tab_next_out.pngbin0 -> 828 bytes
-rw-r--r--src/modules/notifier/pics/notifier_icon_tab_next_over.pngbin0 -> 870 bytes
-rw-r--r--src/modules/notifier/pics/notifier_icon_tab_prev_clicked.pngbin0 -> 773 bytes
-rw-r--r--src/modules/notifier/pics/notifier_icon_tab_prev_out.pngbin0 -> 827 bytes
-rw-r--r--src/modules/notifier/pics/notifier_icon_tab_prev_over.pngbin0 -> 843 bytes
-rw-r--r--src/modules/notifier/pics/notifier_left.pngbin0 -> 442 bytes
-rw-r--r--src/modules/notifier/pics/notifier_pen.pngbin0 -> 712 bytes
-rw-r--r--src/modules/notifier/pics/notifier_pix_body_dwn.pngbin0 -> 138 bytes
-rw-r--r--src/modules/notifier/pics/notifier_pix_body_dwndx.pngbin0 -> 162 bytes
-rw-r--r--src/modules/notifier/pics/notifier_pix_body_dwnsx.pngbin0 -> 162 bytes
-rw-r--r--src/modules/notifier/pics/notifier_pix_body_dx.pngbin0 -> 136 bytes
-rw-r--r--src/modules/notifier/pics/notifier_pix_body_kvirc.pngbin0 -> 2599 bytes
-rw-r--r--src/modules/notifier/pics/notifier_pix_body_kvirc_dwn.pngbin0 -> 249 bytes
-rw-r--r--src/modules/notifier/pics/notifier_pix_body_kvirc_sx.pngbin0 -> 172 bytes
-rw-r--r--src/modules/notifier/pics/notifier_pix_body_sx.pngbin0 -> 136 bytes
-rw-r--r--src/modules/notifier/pics/notifier_pix_caption_bkg.pngbin0 -> 154 bytes
-rw-r--r--src/modules/notifier/pics/notifier_pix_caption_bkg_hl.pngbin0 -> 154 bytes
-rw-r--r--src/modules/notifier/pics/notifier_pix_caption_dx.pngbin0 -> 196 bytes
-rw-r--r--src/modules/notifier/pics/notifier_pix_caption_dx_hl.pngbin0 -> 196 bytes
-rw-r--r--src/modules/notifier/pics/notifier_pix_caption_sx.pngbin0 -> 195 bytes
-rw-r--r--src/modules/notifier/pics/notifier_pix_caption_sx_hl.pngbin0 -> 195 bytes
-rw-r--r--src/modules/notifier/pics/notifier_pix_tab_bkg.pngbin0 -> 150 bytes
-rw-r--r--src/modules/notifier/pics/notifier_pix_tab_dx.pngbin0 -> 157 bytes
-rw-r--r--src/modules/notifier/pics/notifier_pix_tab_focused_bkg.pngbin0 -> 156 bytes
-rw-r--r--src/modules/notifier/pics/notifier_pix_tab_focused_dx.pngbin0 -> 187 bytes
-rw-r--r--src/modules/notifier/pics/notifier_pix_tab_focused_sx.pngbin0 -> 184 bytes
-rw-r--r--src/modules/notifier/pics/notifier_pix_tab_sx.pngbin0 -> 157 bytes
-rw-r--r--src/modules/notifier/pics/notifier_pix_tab_unfocused_bkg.pngbin0 -> 175 bytes
-rw-r--r--src/modules/notifier/pics/notifier_pix_tab_unfocused_dx.pngbin0 -> 210 bytes
-rw-r--r--src/modules/notifier/pics/notifier_pix_tab_unfocused_sx.pngbin0 -> 204 bytes
-rw-r--r--src/modules/notifier/pics/notifier_pix_wnd_dwn.pngbin0 -> 156 bytes
-rw-r--r--src/modules/notifier/pics/notifier_pix_wnd_dwn_hl.pngbin0 -> 156 bytes
-rw-r--r--src/modules/notifier/pics/notifier_pix_wnd_dwndx.pngbin0 -> 193 bytes
-rw-r--r--src/modules/notifier/pics/notifier_pix_wnd_dwndx_hl.pngbin0 -> 193 bytes
-rw-r--r--src/modules/notifier/pics/notifier_pix_wnd_dwnsx.pngbin0 -> 196 bytes
-rw-r--r--src/modules/notifier/pics/notifier_pix_wnd_dwnsx_hl.pngbin0 -> 196 bytes
-rw-r--r--src/modules/notifier/pics/notifier_pix_wnd_dx.pngbin0 -> 150 bytes
-rw-r--r--src/modules/notifier/pics/notifier_pix_wnd_dx_hl.pngbin0 -> 150 bytes
-rw-r--r--src/modules/notifier/pics/notifier_pix_wnd_sx.pngbin0 -> 150 bytes
-rw-r--r--src/modules/notifier/pics/notifier_pix_wnd_sx_hl.pngbin0 -> 150 bytes
-rw-r--r--src/modules/notifier/pics/notifier_right.pngbin0 -> 443 bytes
-rw-r--r--src/modules/notifier/pics/notifier_up.pngbin0 -> 488 bytes
-rw-r--r--src/modules/objects/Makefile.am143
-rw-r--r--src/modules/objects/class_button.cpp178
-rw-r--r--src/modules/objects/class_button.h58
-rw-r--r--src/modules/objects/class_buttongroup.cpp87
-rw-r--r--src/modules/objects/class_buttongroup.h44
-rw-r--r--src/modules/objects/class_checkbox.cpp128
-rw-r--r--src/modules/objects/class_checkbox.h48
-rw-r--r--src/modules/objects/class_combobox.cpp368
-rw-r--r--src/modules/objects/class_combobox.h71
-rw-r--r--src/modules/objects/class_dialog.cpp89
-rw-r--r--src/modules/objects/class_dialog.h44
-rw-r--r--src/modules/objects/class_dockwindow.cpp276
-rw-r--r--src/modules/objects/class_dockwindow.h49
-rw-r--r--src/modules/objects/class_file.cpp488
-rw-r--r--src/modules/objects/class_file.h113
-rw-r--r--src/modules/objects/class_groupbox.cpp376
-rw-r--r--src/modules/objects/class_groupbox.h64
-rw-r--r--src/modules/objects/class_hbox.cpp128
-rw-r--r--src/modules/objects/class_hbox.h47
-rw-r--r--src/modules/objects/class_label.cpp409
-rw-r--r--src/modules/objects/class_label.h54
-rw-r--r--src/modules/objects/class_layout.cpp274
-rw-r--r--src/modules/objects/class_layout.h52
-rw-r--r--src/modules/objects/class_lcd.cpp180
-rw-r--r--src/modules/objects/class_lcd.h51
-rw-r--r--src/modules/objects/class_lineedit.cpp461
-rw-r--r--src/modules/objects/class_lineedit.h81
-rw-r--r--src/modules/objects/class_list.cpp392
-rw-r--r--src/modules/objects/class_list.h64
-rw-r--r--src/modules/objects/class_listbox.cpp390
-rw-r--r--src/modules/objects/class_listbox.h70
-rw-r--r--src/modules/objects/class_listview.cpp557
-rw-r--r--src/modules/objects/class_listview.h102
-rw-r--r--src/modules/objects/class_listviewitem.cpp421
-rw-r--r--src/modules/objects/class_listviewitem.h88
-rw-r--r--src/modules/objects/class_mainwindow.cpp158
-rw-r--r--src/modules/objects/class_mainwindow.h47
-rw-r--r--src/modules/objects/class_menubar.cpp76
-rw-r--r--src/modules/objects/class_menubar.h40
-rw-r--r--src/modules/objects/class_multilineedit.cpp1217
-rw-r--r--src/modules/objects/class_multilineedit.h110
-rw-r--r--src/modules/objects/class_painter.cpp1007
-rw-r--r--src/modules/objects/class_painter.h96
-rw-r--r--src/modules/objects/class_pixmap.cpp317
-rw-r--r--src/modules/objects/class_pixmap.h72
-rw-r--r--src/modules/objects/class_popupmenu.cpp361
-rw-r--r--src/modules/objects/class_popupmenu.h58
-rw-r--r--src/modules/objects/class_process.cpp317
-rw-r--r--src/modules/objects/class_process.h74
-rw-r--r--src/modules/objects/class_progressbar.cpp162
-rw-r--r--src/modules/objects/class_progressbar.h51
-rw-r--r--src/modules/objects/class_radiobutton.cpp138
-rw-r--r--src/modules/objects/class_radiobutton.h51
-rw-r--r--src/modules/objects/class_slider.cpp287
-rw-r--r--src/modules/objects/class_slider.h64
-rw-r--r--src/modules/objects/class_socket.cpp1331
-rw-r--r--src/modules/objects/class_socket.h185
-rw-r--r--src/modules/objects/class_spinbox.cpp265
-rw-r--r--src/modules/objects/class_spinbox.h64
-rw-r--r--src/modules/objects/class_tabwidget.cpp541
-rw-r--r--src/modules/objects/class_tabwidget.h61
-rw-r--r--src/modules/objects/class_tbrowser.cpp143
-rw-r--r--src/modules/objects/class_tbrowser.h52
-rw-r--r--src/modules/objects/class_toolbar.cpp156
-rw-r--r--src/modules/objects/class_toolbar.h50
-rw-r--r--src/modules/objects/class_toolbutton.cpp341
-rw-r--r--src/modules/objects/class_toolbutton.h69
-rw-r--r--src/modules/objects/class_urllabel.cpp330
-rw-r--r--src/modules/objects/class_urllabel.h64
-rw-r--r--src/modules/objects/class_vbox.cpp128
-rw-r--r--src/modules/objects/class_vbox.h45
-rw-r--r--src/modules/objects/class_widget.cpp1745
-rw-r--r--src/modules/objects/class_widget.h113
-rw-r--r--src/modules/objects/class_window.cpp158
-rw-r--r--src/modules/objects/class_window.h64
-rw-r--r--src/modules/objects/class_wizard.cpp371
-rw-r--r--src/modules/objects/class_wizard.h79
-rw-r--r--src/modules/objects/class_workspace.cpp262
-rw-r--r--src/modules/objects/class_workspace.h53
-rw-r--r--src/modules/objects/class_wrapper.cpp269
-rw-r--r--src/modules/objects/class_wrapper.h53
-rw-r--r--src/modules/objects/class_xmlreader.cpp343
-rw-r--r--src/modules/objects/class_xmlreader.h46
-rw-r--r--src/modules/objects/libkviobjects.cpp1066
-rw-r--r--src/modules/objects/object_macros.h90
-rw-r--r--src/modules/options/Makefile.am157
-rw-r--r--src/modules/options/container.cpp123
-rw-r--r--src/modules/options/container.h53
-rw-r--r--src/modules/options/dialog.cpp675
-rw-r--r--src/modules/options/dialog.h104
-rw-r--r--src/modules/options/instances.cpp3590
-rw-r--r--src/modules/options/instances.h83
-rw-r--r--src/modules/options/libkvioptions.cpp324
-rwxr-xr-xsrc/modules/options/mkcreateinstanceproc.sh441
-rw-r--r--src/modules/options/optw_antispam.cpp64
-rw-r--r--src/modules/options/optw_antispam.h47
-rw-r--r--src/modules/options/optw_avatar.cpp131
-rw-r--r--src/modules/options/optw_avatar.h45
-rw-r--r--src/modules/options/optw_away.cpp71
-rw-r--r--src/modules/options/optw_away.h46
-rw-r--r--src/modules/options/optw_connection.cpp321
-rw-r--r--src/modules/options/optw_connection.h116
-rw-r--r--src/modules/options/optw_ctcp.cpp90
-rw-r--r--src/modules/options/optw_ctcp.h41
-rw-r--r--src/modules/options/optw_ctcpfloodprotection.cpp116
-rw-r--r--src/modules/options/optw_ctcpfloodprotection.h41
-rw-r--r--src/modules/options/optw_dcc.cpp393
-rw-r--r--src/modules/options/optw_dcc.h139
-rw-r--r--src/modules/options/optw_generalopt.cpp51
-rw-r--r--src/modules/options/optw_generalopt.h39
-rw-r--r--src/modules/options/optw_highlighting.cpp128
-rw-r--r--src/modules/options/optw_highlighting.h67
-rw-r--r--src/modules/options/optw_ident.cpp37
-rw-r--r--src/modules/options/optw_ident.h28
-rw-r--r--src/modules/options/optw_identity.cpp729
-rw-r--r--src/modules/options/optw_identity.h192
-rw-r--r--src/modules/options/optw_ignore.cpp62
-rw-r--r--src/modules/options/optw_ignore.h47
-rw-r--r--src/modules/options/optw_input.cpp156
-rw-r--r--src/modules/options/optw_input.h61
-rw-r--r--src/modules/options/optw_interfacefeatures.cpp88
-rw-r--r--src/modules/options/optw_interfacefeatures.h48
-rw-r--r--src/modules/options/optw_interfacelookglobal.cpp215
-rw-r--r--src/modules/options/optw_interfacelookglobal.h113
-rw-r--r--src/modules/options/optw_irc.cpp220
-rw-r--r--src/modules/options/optw_irc.h116
-rw-r--r--src/modules/options/optw_ircoutput.cpp94
-rw-r--r--src/modules/options/optw_ircoutput.h49
-rw-r--r--src/modules/options/optw_ircview.cpp168
-rw-r--r--src/modules/options/optw_ircview.h83
-rw-r--r--src/modules/options/optw_lag.cpp85
-rw-r--r--src/modules/options/optw_lag.h40
-rw-r--r--src/modules/options/optw_logging.cpp64
-rw-r--r--src/modules/options/optw_logging.h42
-rw-r--r--src/modules/options/optw_mediatypes.cpp262
-rw-r--r--src/modules/options/optw_mediatypes.h83
-rw-r--r--src/modules/options/optw_messages.cpp693
-rw-r--r--src/modules/options/optw_messages.h186
-rw-r--r--src/modules/options/optw_nickserv.cpp368
-rw-r--r--src/modules/options/optw_nickserv.h89
-rw-r--r--src/modules/options/optw_notify.cpp134
-rw-r--r--src/modules/options/optw_notify.h54
-rw-r--r--src/modules/options/optw_protection.cpp50
-rw-r--r--src/modules/options/optw_protection.h48
-rw-r--r--src/modules/options/optw_proxy.cpp367
-rw-r--r--src/modules/options/optw_proxy.h94
-rw-r--r--src/modules/options/optw_query.cpp115
-rw-r--r--src/modules/options/optw_query.h43
-rw-r--r--src/modules/options/optw_servers.cpp1712
-rw-r--r--src/modules/options/optw_servers.h210
-rw-r--r--src/modules/options/optw_sound.cpp310
-rw-r--r--src/modules/options/optw_sound.h94
-rw-r--r--src/modules/options/optw_ssl.cpp35
-rw-r--r--src/modules/options/optw_ssl.h29
-rw-r--r--src/modules/options/optw_taskbar.cpp255
-rw-r--r--src/modules/options/optw_taskbar.h125
-rw-r--r--src/modules/options/optw_textencoding.cpp139
-rw-r--r--src/modules/options/optw_textencoding.h50
-rw-r--r--src/modules/options/optw_texticons.cpp244
-rw-r--r--src/modules/options/optw_texticons.h105
-rw-r--r--src/modules/options/optw_theme.cpp26
-rw-r--r--src/modules/options/optw_theme.h30
-rw-r--r--src/modules/options/optw_tools.cpp50
-rw-r--r--src/modules/options/optw_tools.h46
-rw-r--r--src/modules/options/optw_topiclabel.cpp43
-rw-r--r--src/modules/options/optw_topiclabel.h41
-rw-r--r--src/modules/options/optw_transport.cpp33
-rw-r--r--src/modules/options/optw_transport.h29
-rw-r--r--src/modules/options/optw_tray.cpp91
-rw-r--r--src/modules/options/optw_tray.h50
-rw-r--r--src/modules/options/optw_uparser.cpp62
-rw-r--r--src/modules/options/optw_uparser.h40
-rw-r--r--src/modules/options/optw_urlhandlers.cpp127
-rw-r--r--src/modules/options/optw_urlhandlers.h52
-rw-r--r--src/modules/options/optw_userlist.cpp245
-rw-r--r--src/modules/options/optw_userlist.h114
-rw-r--r--src/modules/perl/Makefile.am18
-rw-r--r--src/modules/perl/libkviperl.cpp600
-rw-r--r--src/modules/perlcore/KVIrc.xs139
-rw-r--r--src/modules/perlcore/Makefile.am23
-rw-r--r--src/modules/perlcore/libkviperlcore.cpp414
-rw-r--r--src/modules/perlcore/perlcoreinterface.h59
-rw-r--r--src/modules/perlcore/ppport.h540
-rw-r--r--src/modules/perlcore/typemap313
-rw-r--r--src/modules/perlcore/xs.inc277
-rw-r--r--src/modules/popupeditor/Makefile.am17
-rw-r--r--src/modules/popupeditor/libkvipopupeditor.cpp88
-rw-r--r--src/modules/popupeditor/popupeditor.cpp1433
-rw-r--r--src/modules/popupeditor/popupeditor.h206
-rw-r--r--src/modules/raweditor/Makefile.am17
-rw-r--r--src/modules/raweditor/libkviraweditor.cpp87
-rw-r--r--src/modules/raweditor/raweditor.cpp563
-rw-r--r--src/modules/raweditor/raweditor.h118
-rw-r--r--src/modules/regchan/Makefile.am18
-rw-r--r--src/modules/regchan/libkviregchan.cpp426
-rw-r--r--src/modules/reguser/Makefile.am25
-rw-r--r--src/modules/reguser/dialog.cpp903
-rw-r--r--src/modules/reguser/dialog.h148
-rw-r--r--src/modules/reguser/edituser.cpp781
-rw-r--r--src/modules/reguser/edituser.h152
-rw-r--r--src/modules/reguser/libkvireguser.cpp1239
-rw-r--r--src/modules/reguser/wizard.cpp464
-rw-r--r--src/modules/reguser/wizard.h89
-rw-r--r--src/modules/rijndael/Makefile.am23
-rw-r--r--src/modules/rijndael/ablowfish.cpp632
-rw-r--r--src/modules/rijndael/ablowfish.h141
-rw-r--r--src/modules/rijndael/caps/Makefile.am9
-rw-r--r--src/modules/rijndael/caps/rijndael1
-rw-r--r--src/modules/rijndael/libkvirijndael.cpp853
-rw-r--r--src/modules/rijndael/libkvirijndael.h169
-rw-r--r--src/modules/rijndael/rijndael.cpp1626
-rw-r--r--src/modules/rijndael/rijndael.h153
-rw-r--r--src/modules/setup/Makefile.am26
-rw-r--r--src/modules/setup/libkvisetup.cpp158
-rw-r--r--src/modules/setup/setupwizard.cpp1132
-rw-r--r--src/modules/setup/setupwizard.h164
-rw-r--r--src/modules/sharedfile/Makefile.am18
-rw-r--r--src/modules/sharedfile/libkvisharedfile.cpp281
-rw-r--r--src/modules/sharedfileswindow/Makefile.am22
-rw-r--r--src/modules/sharedfileswindow/caps/Makefile.am9
-rw-r--r--src/modules/sharedfileswindow/caps/sharedfileswindow0
-rw-r--r--src/modules/sharedfileswindow/libkvisharedfileswindow.cpp158
-rw-r--r--src/modules/sharedfileswindow/sharedfileswindow.cpp742
-rw-r--r--src/modules/sharedfileswindow/sharedfileswindow.h114
-rw-r--r--src/modules/snd/Makefile.am22
-rw-r--r--src/modules/snd/libkvisnd.cpp744
-rw-r--r--src/modules/snd/libkvisnd.h213
-rw-r--r--src/modules/socketspy/Makefile.am20
-rw-r--r--src/modules/socketspy/libkvisocketspy.cpp92
-rw-r--r--src/modules/socketspy/socketspywindow.cpp125
-rw-r--r--src/modules/socketspy/socketspywindow.h53
-rw-r--r--src/modules/spaste/Makefile.am24
-rw-r--r--src/modules/spaste/controller.cpp121
-rw-r--r--src/modules/spaste/controller.h59
-rw-r--r--src/modules/spaste/libkvispaste.cpp346
-rw-r--r--src/modules/spaste/libkvispaste.h13
-rw-r--r--src/modules/str/Makefile.am18
-rw-r--r--src/modules/str/libkvistr.cpp2330
-rw-r--r--src/modules/system/Makefile.am18
-rw-r--r--src/modules/system/libkvisystem.cpp749
-rw-r--r--src/modules/system/plugin.cpp427
-rw-r--r--src/modules/system/plugin.h80
-rw-r--r--src/modules/term/Makefile.am21
-rw-r--r--src/modules/term/libkviterm.cpp167
-rw-r--r--src/modules/term/termwidget.cpp179
-rw-r--r--src/modules/term/termwidget.h72
-rw-r--r--src/modules/term/termwindow.cpp84
-rw-r--r--src/modules/term/termwindow.h54
-rw-r--r--src/modules/texticons/Makefile.am18
-rw-r--r--src/modules/texticons/libkvitexticons.cpp161
-rw-r--r--src/modules/theme/Makefile.am36
-rw-r--r--src/modules/theme/libkvitheme.cpp193
-rw-r--r--src/modules/theme/managementdialog.cpp459
-rw-r--r--src/modules/theme/managementdialog.h109
-rw-r--r--src/modules/theme/packthemedialog.cpp489
-rw-r--r--src/modules/theme/packthemedialog.h66
-rw-r--r--src/modules/theme/savethemedialog.cpp301
-rw-r--r--src/modules/theme/savethemedialog.h71
-rw-r--r--src/modules/theme/themefunctions.cpp396
-rw-r--r--src/modules/theme/themefunctions.h54
-rw-r--r--src/modules/tip/Makefile.am30
-rw-r--r--src/modules/tip/kvi_tip.pngbin0 -> 2590 bytes
-rw-r--r--src/modules/tip/libkvitip.cpp309
-rw-r--r--src/modules/tip/libkvitip.h71
-rw-r--r--src/modules/tip/libkvitip.kvc28
-rw-r--r--src/modules/tip/libkvitip_cs.kvc29
-rw-r--r--src/modules/tip/libkvitip_it.kvc28
-rw-r--r--src/modules/tip/libkvitip_ru.kvc29
-rw-r--r--src/modules/tmphighlight/Makefile.am22
-rw-r--r--src/modules/tmphighlight/libkvitmphighlight.cpp174
-rw-r--r--src/modules/toolbar/Makefile.am18
-rw-r--r--src/modules/toolbar/libkvitoolbar.cpp602
-rw-r--r--src/modules/toolbareditor/Makefile.am20
-rw-r--r--src/modules/toolbareditor/libkvitoolbareditor.cpp96
-rw-r--r--src/modules/toolbareditor/toolbareditor.cpp537
-rw-r--r--src/modules/toolbareditor/toolbareditor.h119
-rw-r--r--src/modules/torrent/Makefile.am30
-rw-r--r--src/modules/torrent/libkvitorrent.cpp904
-rw-r--r--src/modules/torrent/tc_interface.cpp31
-rw-r--r--src/modules/torrent/tc_interface.h164
-rw-r--r--src/modules/torrent/tc_ktorrentdcopinterface.cpp500
-rw-r--r--src/modules/torrent/tc_ktorrentdcopinterface.h131
-rw-r--r--src/modules/torrent/tc_statusbarapplet.cpp69
-rw-r--r--src/modules/torrent/tc_statusbarapplet.h26
-rw-r--r--src/modules/url/Makefile.am23
-rw-r--r--src/modules/url/caps/Makefile.am9
-rw-r--r--src/modules/url/caps/url0
-rw-r--r--src/modules/url/icons.h554
-rw-r--r--src/modules/url/libkviurl.cpp910
-rw-r--r--src/modules/url/libkviurl.h144
-rw-r--r--src/modules/window/Makefile.am21
-rw-r--r--src/modules/window/libkviwindow.cpp1547
-rw-r--r--src/modules/window/userwindow.cpp107
-rw-r--r--src/modules/window/userwindow.h48
1228 files changed, 286452 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 00000000..a3f12af2
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,10 @@
+###############################################################################
+# KVirc IRC client Makefile - 16.12.98 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+SUBDIRS = kvilib kvirc modules
+
+headers_HEADERS=kvi_configstatus.h
+
+kvi_configstatus.h: config.h
+ cp -f config.h kvi_configstatus.h
diff --git a/src/config.h.in b/src/config.h.in
new file mode 100644
index 00000000..e79ea040
--- /dev/null
+++ b/src/config.h.in
@@ -0,0 +1,247 @@
+/* src/config.h.in. Generated from configure.in by autoheader. */
+
+/* define this to the number of average channel users */
+#undef AVERAGE_CHANNEL_USERS
+
+/* define this if you are on a big endian machine */
+#undef BIG_ENDIAN_MACHINE_BYTE_ORDER
+
+/* this is the build date (configure date rather) */
+#undef BUILD_DATE
+
+/* these are the build flags */
+#undef BUILD_FLAGS
+
+/* define if you want to enable the Arts daemon support */
+#undef COMPILE_ARTS_SUPPORT
+
+/* define if you want to enable the Audiofile library support */
+#undef COMPILE_AUDIOFILE_SUPPORT
+
+/* define if you want to compile the crypt support */
+#undef COMPILE_CRYPT_SUPPORT
+
+/* define if you want to disable DCC VOICE sound support */
+#undef COMPILE_DISABLE_DCC_VOICE
+
+/* define if you want to enable the Esound daemon support */
+#undef COMPILE_ESD_SUPPORT
+
+/* define if you have the SIOCGIFADDR ioctl and the related headers */
+#undef COMPILE_GET_INTERFACE_ADDRESS
+
+/* define this if you want to ignore the SIGALARM signal */
+#undef COMPILE_IGNORE_SIGALARM
+
+/* define if you want the info tips to be compiled in */
+#undef COMPILE_INFO_TIPS
+
+/* define if you want the IpV6 support */
+#undef COMPILE_IPV6_SUPPORT
+
+/* define if you want to compile the KDE 3.x support */
+#undef COMPILE_KDE_SUPPORT
+
+/* define if you want the memory checks */
+#undef COMPILE_MEMORY_CHECKS
+
+/* define if you want the gcc memory profile */
+#undef COMPILE_MEMORY_PROFILE
+
+/* define if you want to enable the new KVS parser */
+#undef COMPILE_NEW_KVS
+
+/* define this if you want to disable the inter-process communication support
+ */
+#undef COMPILE_NO_IPC
+
+/* define if you want to ignore X Windows completely */
+#undef COMPILE_NO_X
+
+/* define if you want to disable the X bell support */
+#undef COMPILE_NO_X_BELL
+
+/* define if you want to use only the new KVS parser */
+#undef COMPILE_ONLY_NEW_KVS
+
+/* define if you want to enable OSS sound support */
+#undef COMPILE_OSS_SUPPORT
+
+/* define if you have perl and want the perl scripting support in kvirc */
+#undef COMPILE_PERL_SUPPORT
+
+/* define if you have the KDE support and want the pseudo transparency */
+#undef COMPILE_PSEUDO_TRANSPARENCY
+
+/* define if you have openssl and want the ssl support in kvirc */
+#undef COMPILE_SSL_SUPPORT
+
+/* define if you want to use the pthreads library */
+#undef COMPILE_THREADS_USE_POSIX
+
+/* define if you want to use the solaris libthread */
+#undef COMPILE_THREADS_USE_SOLARIS_LIBTHREAD
+
+/* define if your compiler supports gotos do dynamic labels */
+#undef COMPILE_USE_DYNAMIC_LABELS
+
+/* define if you have libgsm and want the GSM code to be compiled */
+#undef COMPILE_USE_GSM
+
+/* define if you want to compile the Qt 4.x support */
+#undef COMPILE_USE_QT4
+
+/* define if you trust your memmove() function */
+#undef COMPILE_WITH_SYSTEM_MEMMOVE
+
+/* define if you want to enable the ZLib library support */
+#undef COMPILE_XSS_SUPPORT
+
+/* define if you want to enable the ZLib library support */
+#undef COMPILE_ZLIB_SUPPORT
+
+/* define if you want the i386 asm code */
+#undef COMPILE_ix86_ASM
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you have the `getenv' function. */
+#undef HAVE_GETENV
+
+/* Define to 1 if you have the `getnameinfo' function. */
+#undef HAVE_GETNAMEINFO
+
+/* Define to 1 if you have the `gmtime_r' function. */
+#undef HAVE_GMTIME_R
+
+/* Define to 1 if you have the `inet_aton' function. */
+#undef HAVE_INET_ATON
+
+/* Define to 1 if you have the `inet_ntoa' function. */
+#undef HAVE_INET_NTOA
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <linux/soundcard.h> header file. */
+#undef HAVE_LINUX_SOUNDCARD_H
+
+/* Define to 1 if you have the `localtime_r' function. */
+#undef HAVE_LOCALTIME_R
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `putenv' function. */
+#undef HAVE_PUTENV
+
+/* Define to 1 if you have the `setenv' function. */
+#undef HAVE_SETENV
+
+/* Define to 1 if you have the <soundcard.h> header file. */
+#undef HAVE_SOUNDCARD_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the `strerror' function. */
+#undef HAVE_STRERROR
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/soundcard.h> header file. */
+#undef HAVE_SYS_SOUNDCARD_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the `unsetenv' function. */
+#undef HAVE_UNSETENV
+
+/* 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 `int', as computed by sizeof. */
+#undef SIZEOF_INT
+
+/* The size of `long int', as computed by sizeof. */
+#undef SIZEOF_LONG_INT
+
+/* The size of `long long int', as computed by sizeof. */
+#undef SIZEOF_LONG_LONG_INT
+
+/* The size of `short int', as computed by sizeof. */
+#undef SIZEOF_SHORT_INT
+
+/* The size of `unsigned int', as computed by sizeof. */
+#undef SIZEOF_UNSIGNED_INT
+
+/* The size of `unsigned long int', as computed by sizeof. */
+#undef SIZEOF_UNSIGNED_LONG_INT
+
+/* The size of `unsigned long long int', as computed by sizeof. */
+#undef SIZEOF_UNSIGNED_LONG_LONG_INT
+
+/* The size of `unsigned short int', as computed by sizeof. */
+#undef SIZEOF_UNSIGNED_SHORT_INT
+
+/* The size of `void *', as computed by sizeof. */
+#undef SIZEOF_VOID_P
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Version number of package */
+#undef VERSION
+
+/* MAJOR.MINOR part of version */
+#undef VERSION_BRANCH
+
+/* Define to 1 if the X Window System is missing or not being used. */
+#undef X_DISPLAY_MISSING
+
+/* Define to 1 if on AIX 3.
+ System headers sometimes define this.
+ We just want to avoid a redefinition error message. */
+#ifndef _ALL_SOURCE
+# undef _ALL_SOURCE
+#endif
+
+/* Define to 1 if on MINIX. */
+#undef _MINIX
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+ this defined. */
+#undef _POSIX_1_SOURCE
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+#undef _POSIX_SOURCE
diff --git a/src/kvi_configstatus.h b/src/kvi_configstatus.h
new file mode 100644
index 00000000..c776b26a
--- /dev/null
+++ b/src/kvi_configstatus.h
@@ -0,0 +1,248 @@
+/* src/config.h. Generated from config.h.in by configure. */
+/* src/config.h.in. Generated from configure.in by autoheader. */
+
+/* define this to the number of average channel users */
+#define AVERAGE_CHANNEL_USERS 101
+
+/* define this if you are on a big endian machine */
+/* #undef BIG_ENDIAN_MACHINE_BYTE_ORDER */
+
+/* this is the build date (configure date rather) */
+#define BUILD_DATE "Thu Mar 13 02:29:23 UTC 2008"
+
+/* these are the build flags */
+#define BUILD_FLAGS "x86_64-cfgikopsAGTZ"
+
+/* define if you want to enable the Arts daemon support */
+/* #undef COMPILE_ARTS_SUPPORT */
+
+/* define if you want to enable the Audiofile library support */
+#define COMPILE_AUDIOFILE_SUPPORT 1
+
+/* define if you want to compile the crypt support */
+#define COMPILE_CRYPT_SUPPORT 1
+
+/* define if you want to disable DCC VOICE sound support */
+/* #undef COMPILE_DISABLE_DCC_VOICE */
+
+/* define if you want to enable the Esound daemon support */
+/* #undef COMPILE_ESD_SUPPORT */
+
+/* define if you have the SIOCGIFADDR ioctl and the related headers */
+#define COMPILE_GET_INTERFACE_ADDRESS 1
+
+/* define this if you want to ignore the SIGALARM signal */
+/* #undef COMPILE_IGNORE_SIGALARM */
+
+/* define if you want the info tips to be compiled in */
+#define COMPILE_INFO_TIPS 1
+
+/* define if you want the IpV6 support */
+#define COMPILE_IPV6_SUPPORT 1
+
+/* define if you want to compile the KDE 3.x support */
+#define COMPILE_KDE_SUPPORT 1
+
+/* define if you want the memory checks */
+/* #undef COMPILE_MEMORY_CHECKS */
+
+/* define if you want the gcc memory profile */
+/* #undef COMPILE_MEMORY_PROFILE */
+
+/* define if you want to enable the new KVS parser */
+#define COMPILE_NEW_KVS 1
+
+/* define this if you want to disable the inter-process communication support
+ */
+/* #undef COMPILE_NO_IPC */
+
+/* define if you want to ignore X Windows completely */
+/* #undef COMPILE_NO_X */
+
+/* define if you want to disable the X bell support */
+/* #undef COMPILE_NO_X_BELL */
+
+/* define if you want to use only the new KVS parser */
+#define COMPILE_ONLY_NEW_KVS 1
+
+/* define if you want to enable OSS sound support */
+#define COMPILE_OSS_SUPPORT 1
+
+/* define if you have perl and want the perl scripting support in kvirc */
+#define COMPILE_PERL_SUPPORT 1
+
+/* define if you have the KDE support and want the pseudo transparency */
+#define COMPILE_PSEUDO_TRANSPARENCY 1
+
+/* define if you have openssl and want the ssl support in kvirc */
+#define COMPILE_SSL_SUPPORT 1
+
+/* define if you want to use the pthreads library */
+#define COMPILE_THREADS_USE_POSIX 1
+
+/* define if you want to use the solaris libthread */
+/* #undef COMPILE_THREADS_USE_SOLARIS_LIBTHREAD */
+
+/* define if your compiler supports gotos do dynamic labels */
+#define COMPILE_USE_DYNAMIC_LABELS 1
+
+/* define if you have libgsm and want the GSM code to be compiled */
+#define COMPILE_USE_GSM 1
+
+/* define if you want to compile the Qt 4.x support */
+/* #undef COMPILE_USE_QT4 */
+
+/* define if you trust your memmove() function */
+#define COMPILE_WITH_SYSTEM_MEMMOVE 1
+
+/* define if you want to enable the ZLib library support */
+#define COMPILE_XSS_SUPPORT 1
+
+/* define if you want to enable the ZLib library support */
+#define COMPILE_ZLIB_SUPPORT 1
+
+/* define if you want the i386 asm code */
+/* #undef COMPILE_ix86_ASM */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the `getenv' function. */
+#define HAVE_GETENV 1
+
+/* Define to 1 if you have the `getnameinfo' function. */
+#define HAVE_GETNAMEINFO 1
+
+/* Define to 1 if you have the `gmtime_r' function. */
+#define HAVE_GMTIME_R 1
+
+/* Define to 1 if you have the `inet_aton' function. */
+#define HAVE_INET_ATON 1
+
+/* Define to 1 if you have the `inet_ntoa' function. */
+#define HAVE_INET_NTOA 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <linux/soundcard.h> header file. */
+#define HAVE_LINUX_SOUNDCARD_H 1
+
+/* Define to 1 if you have the `localtime_r' function. */
+#define HAVE_LOCALTIME_R 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `putenv' function. */
+#define HAVE_PUTENV 1
+
+/* Define to 1 if you have the `setenv' function. */
+#define HAVE_SETENV 1
+
+/* Define to 1 if you have the <soundcard.h> header file. */
+/* #undef HAVE_SOUNDCARD_H */
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strerror' function. */
+#define HAVE_STRERROR 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/soundcard.h> header file. */
+#define HAVE_SYS_SOUNDCARD_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `unsetenv' function. */
+#define HAVE_UNSETENV 1
+
+/* Name of package */
+#define PACKAGE "kvirc"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT ""
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME ""
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING ""
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION ""
+
+/* The size of `int', as computed by sizeof. */
+#define SIZEOF_INT 4
+
+/* The size of `long int', as computed by sizeof. */
+#define SIZEOF_LONG_INT 8
+
+/* The size of `long long int', as computed by sizeof. */
+#define SIZEOF_LONG_LONG_INT 8
+
+/* The size of `short int', as computed by sizeof. */
+#define SIZEOF_SHORT_INT 2
+
+/* The size of `unsigned int', as computed by sizeof. */
+#define SIZEOF_UNSIGNED_INT 4
+
+/* The size of `unsigned long int', as computed by sizeof. */
+#define SIZEOF_UNSIGNED_LONG_INT 8
+
+/* The size of `unsigned long long int', as computed by sizeof. */
+#define SIZEOF_UNSIGNED_LONG_LONG_INT 8
+
+/* The size of `unsigned short int', as computed by sizeof. */
+#define SIZEOF_UNSIGNED_SHORT_INT 2
+
+/* The size of `void *', as computed by sizeof. */
+#define SIZEOF_VOID_P 8
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Version number of package */
+#define VERSION "3.4.0"
+
+/* MAJOR.MINOR part of version */
+#define VERSION_BRANCH "3.4"
+
+/* Define to 1 if the X Window System is missing or not being used. */
+/* #undef X_DISPLAY_MISSING */
+
+/* Define to 1 if on AIX 3.
+ System headers sometimes define this.
+ We just want to avoid a redefinition error message. */
+#ifndef _ALL_SOURCE
+/* # undef _ALL_SOURCE */
+#endif
+
+/* Define to 1 if on MINIX. */
+/* #undef _MINIX */
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+ this defined. */
+/* #undef _POSIX_1_SOURCE */
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+/* #undef _POSIX_SOURCE */
diff --git a/src/kvilib/Makefile.am b/src/kvilib/Makefile.am
new file mode 100644
index 00000000..1268e5e0
--- /dev/null
+++ b/src/kvilib/Makefile.am
@@ -0,0 +1,5 @@
+###############################################################################
+# KVirc IRC client Makefile - 16.12.98 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+SUBDIRS = build config core ext file include irc net system tal
diff --git a/src/kvilib/build/Makefile.am b/src/kvilib/build/Makefile.am
new file mode 100644
index 00000000..51e9333a
--- /dev/null
+++ b/src/kvilib/build/Makefile.am
@@ -0,0 +1,339 @@
+########################################################################################################################
+#
+# KVILIB Makefile : KVIrc utility library
+# Szymon Stefanek 21.09.2001
+#
+########################################################################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ $(SS_INCDIRS) $(SS_CPPFLAGS)
+
+lib_LTLIBRARIES = libkvilib.la
+libkvilib_la_LDFLAGS = $(SS_LDFLAGS) -version-info 3:0:0 $(SS_LIBDIRS)
+libkvilib_la_LIBADD = $(SS_LIBLINK)
+
+#
+# Command useful to find out all the sources
+# SRC=`find ../ -name *.cpp | sort`
+# echo $SRC
+#
+
+nodist_libkvilib_la_SOURCES = \
+ ../ext/moc_kvi_crypt.cpp \
+ ../ext/moc_kvi_garbage.cpp \
+ ../ext/moc_kvi_regusersdb.cpp \
+ ../ext/moc_kvi_sharedfiles.cpp \
+ ../irc/moc_kvi_ircuserdb.cpp \
+ ../net/moc_kvi_dns.cpp \
+ ../net/moc_kvi_http.cpp \
+ ../system/moc_kvi_locale.cpp \
+ ../system/moc_kvi_thread.cpp \
+ ../tal/moc_kvi_tal_wizard.cpp
+
+libkvilib_la_SOURCES = \
+ ../core/kvi_error.cpp \
+ ../core/kvi_heapobject.cpp \
+ ../core/kvi_malloc.cpp \
+ ../core/kvi_memmove.cpp \
+ ../core/kvi_qstring.cpp \
+ ../core/kvi_string.cpp \
+ ../core/kvi_stringarray.cpp \
+ ../ext/kvi_cmdformatter.cpp \
+ ../ext/kvi_config.cpp \
+ ../ext/kvi_crypt.cpp \
+ ../ext/kvi_databuffer.cpp \
+ ../ext/kvi_dcophelper.cpp \
+ ../ext/kvi_doublebuffer.cpp \
+ ../ext/kvi_garbage.cpp \
+ ../ext/kvi_osinfo.cpp \
+ ../ext/kvi_imagelib.cpp \
+ ../ext/kvi_md5.cpp \
+ ../ext/kvi_mediatype.cpp \
+ ../ext/kvi_miscutils.cpp \
+ ../ext/kvi_msgtype.cpp \
+ ../ext/kvi_parameterlist.cpp \
+ ../ext/kvi_pixmap.cpp \
+ ../ext/kvi_proxydb.cpp \
+ ../ext/kvi_regchan.cpp \
+ ../ext/kvi_regusersdb.cpp \
+ ../ext/kvi_sharedfiles.cpp \
+ ../ext/kvi_stringconversion.cpp \
+ ../file/kvi_file.cpp \
+ ../file/kvi_fileutils.cpp \
+ ../file/kvi_packagefile.cpp \
+ ../irc/kvi_avatar.cpp \
+ ../irc/kvi_avatarcache.cpp \
+ ../irc/kvi_ircmask.cpp \
+ ../irc/kvi_ircserver.cpp \
+ ../irc/kvi_ircserverdb.cpp \
+ ../irc/kvi_ircuserdb.cpp \
+ ../irc/kvi_mirccntrl.cpp \
+ ../irc/kvi_nickserv.cpp \
+ ../irc/kvi_useridentity.cpp \
+ ../net/kvi_dns.cpp \
+ ../net/kvi_http.cpp \
+ ../net/kvi_netutils.cpp \
+ ../net/kvi_socket.cpp \
+ ../net/kvi_ssl.cpp \
+ ../net/kvi_url.cpp \
+ ../system/kvi_env.cpp \
+ ../system/kvi_locale.cpp \
+ ../system/kvi_thread.cpp \
+ ../system/kvi_time.cpp \
+ ../tal/kvi_tal_application.cpp \
+ ../tal/kvi_tal_filedialog.cpp \
+ ../tal/kvi_tal_grid.cpp \
+ ../tal/kvi_tal_groupbox.cpp \
+ ../tal/kvi_tal_hbox.cpp \
+ ../tal/kvi_tal_iconview.cpp \
+ ../tal/kvi_tal_listbox.cpp \
+ ../tal/kvi_tal_listview.cpp \
+ ../tal/kvi_tal_mainwindow.cpp \
+ ../tal/kvi_tal_menubar.cpp \
+ ../tal/kvi_tal_popupmenu.cpp \
+ ../tal/kvi_tal_scrollview.cpp \
+ ../tal/kvi_tal_tabdialog.cpp \
+ ../tal/kvi_tal_textedit.cpp \
+ ../tal/kvi_tal_toolbar.cpp \
+ ../tal/kvi_tal_tooltip.cpp \
+ ../tal/kvi_tal_vbox.cpp \
+ ../tal/kvi_tal_widgetstack.cpp \
+ ../tal/kvi_tal_wizard.cpp
+
+#
+# Command useful to find out all the headers
+# rm -f ../include/*.h
+# SRC=`find ../ -name *.h | sort`
+# echo $SRC
+#
+
+
+headers_HEADERS = \
+ ../config/kvi_confignames.h \
+ ../config/kvi_debug.h \
+ ../config/kvi_defaults.h \
+ ../config/kvi_fileextensions.h \
+ ../config/kvi_settings.h \
+ ../config/kvi_sourcesdate.h \
+ ../config/kvi_wincfg.h \
+ ../core/kvi_bswap.h \
+ ../core/kvi_error.h \
+ ../core/kvi_heapobject.h \
+ ../core/kvi_inttypes.h \
+ ../core/kvi_malloc.h \
+ ../core/kvi_memmove.h \
+ ../core/kvi_pointerlist.h \
+ ../core/kvi_pointerhashtable.h \
+ ../core/kvi_qcstring.h \
+ ../core/kvi_qstring.h \
+ ../core/kvi_strasm.h \
+ ../core/kvi_string.h \
+ ../core/kvi_stringarray.h \
+ ../core/kvi_valuelist.h \
+ ../ext/kvi_accel.h \
+ ../ext/kvi_cmdformatter.h \
+ ../ext/kvi_config.h \
+ ../ext/kvi_crypt.h \
+ ../ext/kvi_databuffer.h \
+ ../ext/kvi_doublebuffer.h \
+ ../ext/kvi_draganddrop.h \
+ ../ext/kvi_osinfo.h \
+ ../ext/kvi_garbage.h \
+ ../ext/kvi_imagelib.h \
+ ../ext/kvi_md5.h \
+ ../ext/kvi_mediatype.h \
+ ../ext/kvi_miscutils.h \
+ ../ext/kvi_msgtype.h \
+ ../ext/kvi_parameterlist.h \
+ ../ext/kvi_pixmap.h \
+ ../ext/kvi_proxydb.h \
+ ../ext/kvi_regchan.h \
+ ../ext/kvi_regusersdb.h \
+ ../ext/kvi_sharedfiles.h \
+ ../ext/kvi_stringconversion.h \
+ ../ext/kvi_xlib.h \
+ ../file/kvi_file.h \
+ ../file/kvi_fileutils.h \
+ ../file/kvi_packagefile.h \
+ ../irc/kvi_avatar.h \
+ ../irc/kvi_avatarcache.h \
+ ../irc/kvi_ircmask.h \
+ ../irc/kvi_ircserverdb.h \
+ ../irc/kvi_ircserver.h \
+ ../irc/kvi_ircuserdb.h \
+ ../irc/kvi_mirccntrl.h \
+ ../irc/kvi_nickserv.h \
+ ../irc/kvi_useridentity.h \
+ ../net/kvi_dns.h \
+ ../net/kvi_http.h \
+ ../net/kvi_netutils.h \
+ ../net/kvi_socket.h \
+ ../net/kvi_sockettype.h \
+ ../net/kvi_ssl.h \
+ ../net/kvi_url.h \
+ ../system/kvi_env.h \
+ ../system/kvi_library.h \
+ ../system/kvi_locale.h \
+ ../system/kvi_process.h \
+ ../system/kvi_stdarg.h \
+ ../system/kvi_thread.h \
+ ../system/kvi_time.h \
+ ../tal/kvi_tal_application.h \
+ ../tal/kvi_tal_application_kde.h \
+ ../tal/kvi_tal_application_qt.h \
+ ../tal/kvi_tal_filedialog.h \
+ ../tal/kvi_tal_filedialog_kde.h \
+ ../tal/kvi_tal_filedialog_qt.h \
+ ../tal/kvi_tal_filedialog_qt4.h \
+ ../tal/kvi_tal_grid.h \
+ ../tal/kvi_tal_grid_qt3.h \
+ ../tal/kvi_tal_grid_qt4.h \
+ ../tal/kvi_tal_groupbox.h \
+ ../tal/kvi_tal_groupbox_qt3.h \
+ ../tal/kvi_tal_groupbox_qt4.h \
+ ../tal/kvi_tal_hbox.h \
+ ../tal/kvi_tal_hbox_qt3.h \
+ ../tal/kvi_tal_hbox_qt4.h \
+ ../tal/kvi_tal_iconview.h \
+ ../tal/kvi_tal_iconview_qt3.h \
+ ../tal/kvi_tal_iconview_qt4.h \
+ ../tal/kvi_tal_listbox.h \
+ ../tal/kvi_tal_listbox_qt3.h \
+ ../tal/kvi_tal_listbox_qt4.h \
+ ../tal/kvi_tal_listview.h \
+ ../tal/kvi_tal_listview_qt3.h \
+ ../tal/kvi_tal_listview_qt4.h \
+ ../tal/kvi_tal_mainwindow.h \
+ ../tal/kvi_tal_mainwindow_kde.h \
+ ../tal/kvi_tal_mainwindow_qt3.h \
+ ../tal/kvi_tal_mainwindow_qt4.h \
+ ../tal/kvi_tal_menubar.h \
+ ../tal/kvi_tal_menubar_kde.h \
+ ../tal/kvi_tal_menubar_qt.h \
+ ../tal/kvi_tal_popupmenu.h \
+ ../tal/kvi_tal_popupmenu_qt3.h \
+ ../tal/kvi_tal_popupmenu_qt4.h \
+ ../tal/kvi_tal_scrollview.h \
+ ../tal/kvi_tal_scrollview_qt3.h \
+ ../tal/kvi_tal_scrollview_qt4.h \
+ ../tal/kvi_tal_tabdialog.h \
+ ../tal/kvi_tal_tabdialog_qt3.h \
+ ../tal/kvi_tal_tabdialog_qt4.h \
+ ../tal/kvi_tal_textedit.h \
+ ../tal/kvi_tal_textedit_qt3.h \
+ ../tal/kvi_tal_textedit_qt4.h \
+ ../tal/kvi_tal_toolbar.h \
+ ../tal/kvi_tal_toolbar_kde.h \
+ ../tal/kvi_tal_toolbar_qt3.h \
+ ../tal/kvi_tal_toolbar_qt4.h \
+ ../tal/kvi_tal_toolbardocktype.h \
+ ../tal/kvi_tal_tooltip.h \
+ ../tal/kvi_tal_vbox.h \
+ ../tal/kvi_tal_vbox_qt3.h \
+ ../tal/kvi_tal_vbox_qt4.h \
+ ../tal/kvi_tal_widgetstack.h \
+ ../tal/kvi_tal_widgetstack_qt3.h \
+ ../tal/kvi_tal_widgetstack_qt4.h \
+ ../tal/kvi_tal_wizard.h \
+ ../tal/kvi_tal_windowstate.h
+
+
+../ext/moc_%.cpp: ../ext/%.h
+ $(SS_QT_MOC) $(SS_QT_MOC_FLAGS) $< -o $@
+
+../file/moc_%.cpp: ../file/%.h
+ $(SS_QT_MOC) $(SS_QT_MOC_FLAGS) $< -o $@
+
+../irc/moc_%.cpp: ../irc/%.h
+ $(SS_QT_MOC) $(SS_QT_MOC_FLAGS) $< -o $@
+
+../net/moc_%.cpp: ../net/%.h
+ $(SS_QT_MOC) $(SS_QT_MOC_FLAGS) $< -o $@
+
+../system/moc_%.cpp: ../system/%.h
+ $(SS_QT_MOC) $(SS_QT_MOC_FLAGS) $< -o $@
+
+../tal/moc_%.cpp: ../tal/%.h
+ $(SS_QT_MOC) $(SS_QT_MOC_FLAGS) $< -o $@
+
+
+%.moc: %.h
+ $(SS_QT_MOC) $(SS_QT_MOC_FLAGS) $< -o $@
+
+#%.h.gch: %.h
+# $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c $< -o $@
+
+#PRECOMPILED_HDRS = \
+# ../config/kvi_confignames.h.gch \
+# ...
+
+#
+# Command useful to find the moc dependancies
+# grep "\.moc" ../*/*.cpp | sort | sed -e 's/[[:space:]]*#include//' | sed -e 's/\"//g'
+# needs to be modified by hand then to add the moc file path... :)
+#
+
+../tal/kvi_tal_application.cpp: ../tal/kvi_tal_application_kde.moc
+../tal/kvi_tal_application.cpp: ../tal/kvi_tal_application_qt.moc
+../tal/kvi_tal_mainwindow.cpp: ../tal/kvi_tal_mainwindow_kde.moc
+../tal/kvi_tal_mainwindow.cpp: ../tal/kvi_tal_mainwindow_qt3.moc
+../tal/kvi_tal_mainwindow.cpp: ../tal/kvi_tal_mainwindow_qt4.moc
+../tal/kvi_tal_menubar.cpp: ../tal/kvi_tal_menubar_kde.moc
+../tal/kvi_tal_menubar.cpp: ../tal/kvi_tal_menubar_qt.moc
+../tal/kvi_tal_filedialog.cpp: ../tal/kvi_tal_filedialog_kde.moc
+../tal/kvi_tal_filedialog.cpp: ../tal/kvi_tal_filedialog_qt.moc
+../tal/kvi_tal_filedialog.cpp: ../tal/kvi_tal_filedialog_qt4.moc
+../tal/kvi_tal_grid.cpp: ../tal/kvi_tal_grid_qt3.moc
+../tal/kvi_tal_grid.cpp: ../tal/kvi_tal_grid_qt4.moc
+../tal/kvi_tal_groupbox.cpp: ../tal/kvi_tal_groupbox_qt3.moc
+../tal/kvi_tal_groupbox.cpp: ../tal/kvi_tal_groupbox_qt4.moc
+../tal/kvi_tal_hbox.cpp: ../tal/kvi_tal_hbox_qt3.moc
+../tal/kvi_tal_hbox.cpp: ../tal/kvi_tal_hbox_qt4.moc
+../tal/kvi_tal_vbox.cpp: ../tal/kvi_tal_vbox_qt3.moc
+../tal/kvi_tal_vbox.cpp: ../tal/kvi_tal_vbox_qt4.moc
+../tal/kvi_tal_popupmenu.cpp: ../tal/kvi_tal_popupmenu_qt3.moc
+../tal/kvi_tal_popupmenu.cpp: ../tal/kvi_tal_popupmenu_qt4.moc
+../tal/kvi_tal_listview.cpp: ../tal/kvi_tal_listview_qt3.moc
+../tal/kvi_tal_listview.cpp: ../tal/kvi_tal_listview_qt4.moc
+../tal/kvi_tal_listbox.cpp: ../tal/kvi_tal_listbox_qt3.moc
+../tal/kvi_tal_listbox.cpp: ../tal/kvi_tal_listbox_qt4.moc
+../tal/kvi_tal_iconview.cpp: ../tal/kvi_tal_iconview_qt3.moc
+../tal/kvi_tal_iconview.cpp: ../tal/kvi_tal_iconview_qt4.moc
+../tal/kvi_tal_scrollview.cpp: ../tal/kvi_tal_scrollview_qt3.moc
+../tal/kvi_tal_scrollview.cpp: ../tal/kvi_tal_scrollview_qt4.moc
+../tal/kvi_tal_tabdialog.cpp: ../tal/kvi_tal_tabdialog_qt3.moc
+../tal/kvi_tal_tabdialog.cpp: ../tal/kvi_tal_tabdialog_qt4.moc
+../tal/kvi_tal_textedit.cpp: ../tal/kvi_tal_textedit_qt3.moc
+../tal/kvi_tal_textedit.cpp: ../tal/kvi_tal_textedit_qt4.moc
+../tal/kvi_tal_toolbar.cpp: ../tal/kvi_tal_toolbar_qt3.moc
+../tal/kvi_tal_toolbar.cpp: ../tal/kvi_tal_toolbar_qt4.moc
+../tal/kvi_tal_toolbar.cpp: ../tal/kvi_tal_toolbar_kde.moc
+../tal/kvi_tal_tooltip.cpp: ../tal/kvi_tal_tooltip.moc
+../tal/kvi_tal_widgetstack.cpp: ../tal/kvi_tal_widgetstack_qt3.moc
+../tal/kvi_tal_widgetstack.cpp: ../tal/kvi_tal_widgetstack_qt4.moc
+
+#
+# All the cpp files depend on the precompiled headers being up-to-date
+#
+
+#../*/*.cpp: symlinks $(PRECOMPILED_HDRS) gchsymlinks
+
+../*/*.cpp: symlinks
+
+#
+# Symlinks depend on all the header files: symlink is rebuilt whenewer an *.h file changes
+#
+
+symlinks: ../config/*.h ../core/*.h ../ext/*.h ../file/*.h ../irc/*.h ../net/*.h ../system/*.h ../tal/*.h
+ cd ../include; for i in kvi_*.h; do if [ ! -f $$i ]; then rm -f $$i; fi; done; for i in $(SS_TOPSRCDIR)/src/kvilib/*/kvi_*.h; do $(LN_S) $$i . >/dev/null 2>&1; echo "Created link to $$i"; done;
+ touch symlinks
+
+# gchsymlinks: ../config/*.h ../core/*.h ../ext/*.h ../file/*.h ../irc/*.h ../net/*.h ../system/*.h ../tal/*.h
+# cd ../include; for i in kvi_*.gch; do if [ ! -f $$i ]; then rm -f $$i; fi; done; for i in $(SS_TOPSRCDIR)/src/kvilib/*/kvi_*.h.gch; do $(LN_S) $$i . >/dev/null 2>&1; echo "Created link to $$i"; done;
+# touch gchsymlinks
+
+#
+# When cleaning...remove also the symlinks, gchsymlinks and gch headers
+#
+
+#CLEANFILES = ../include/*.h ../include/*.gch symlinks gchsymlinks ../*/*.moc ../*/moc_kvi_*.cpp ../*/*.gch
+CLEANFILES = ../include/*.h symlinks ../*/*.moc ../*/moc_kvi_*.cpp
diff --git a/src/kvilib/config/Makefile.am b/src/kvilib/config/Makefile.am
new file mode 100644
index 00000000..23078cbb
--- /dev/null
+++ b/src/kvilib/config/Makefile.am
@@ -0,0 +1,5 @@
+###############################################################################
+# KVirc IRC client Makefile - 16.12.98 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+EXTRA_DIST = *.h
diff --git a/src/kvilib/config/kvi_confignames.h b/src/kvilib/config/kvi_confignames.h
new file mode 100644
index 00000000..ccff3399
--- /dev/null
+++ b/src/kvilib/config/kvi_confignames.h
@@ -0,0 +1,61 @@
+#ifndef _KVI_CONFIGNAMES_H_
+#define _KVI_CONFIGNAMES_H_
+
+//=============================================================================
+//
+// File : kvi_confignames.h
+// Creation date : Wed Oct 18 2000 14:16:22 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_fileextensions.h"
+
+//=============================================================================
+// This file contains the config file names used in KVIrc
+//
+// You can play a bit with these, but be aware that some (bad) scripts
+// may find themselves in trouble
+//=============================================================================
+
+#define KVI_CONFIGFILE_MAIN "main." KVI_FILEEXTENSION_CONFIG
+#define KVI_CONFIGFILE_WINPROPERTIES "winproperties." KVI_FILEEXTENSION_CONFIG
+#define KVI_CONFIGFILE_SERVERDB "serverdb." KVI_FILEEXTENSION_CONFIG
+#define KVI_CONFIGFILE_PROXYDB "proxydb." KVI_FILEEXTENSION_CONFIG
+#define KVI_CONFIGFILE_EVENTS "events." KVI_FILEEXTENSION_CONFIG
+#define KVI_CONFIGFILE_RAWEVENTS "rawevents." KVI_FILEEXTENSION_CONFIG
+#define KVI_CONFIGFILE_POPUPS "popups." KVI_FILEEXTENSION_CONFIG
+#define KVI_CONFIGFILE_SCRIPTTOOLBARS "toolbars." KVI_FILEEXTENSION_CONFIG
+#define KVI_CONFIGFILE_CUSTOMTOOLBARS "customtoolbars." KVI_FILEEXTENSION_CONFIG
+#define KVI_CONFIGFILE_MEDIATYPES "mediatypes." KVI_FILEEXTENSION_CONFIG
+#define KVI_CONFIGFILE_REGUSERDB "reguserdb." KVI_FILEEXTENSION_CONFIG
+#define KVI_CONFIGFILE_SHAREDFILES "sharedfiles." KVI_FILEEXTENSION_CONFIG
+#define KVI_CONFIGFILE_RECENT "recent." KVI_FILEEXTENSION_CONFIG
+#define KVI_CONFIGFILE_TOOLBARS "toolbarpos." KVI_FILEEXTENSION_CONFIG
+#define KVI_CONFIGFILE_ALIASES "aliases." KVI_FILEEXTENSION_CONFIG
+#define KVI_CONFIGFILE_NICKSERVDATABASE "nickserv." KVI_FILEEXTENSION_CONFIG
+#define KVI_CONFIGFILE_TEXTICONS "texticons." KVI_FILEEXTENSION_CONFIG
+#define KVI_CONFIGFILE_REGCHANDB "regchan." KVI_FILEEXTENSION_CONFIG
+#define KVI_CONFIGFILE_INPUTHISTORY "inputhistory." KVI_FILEEXTENSION_CONFIG
+#define KVI_CONFIGFILE_AVATARCACHE "avatarcache." KVI_FILEEXTENSION_CONFIG
+#define KVI_CONFIGFILE_USERACTIONS "useractions." KVI_FILEEXTENSION_CONFIG
+#define KVI_CONFIGFILE_SCRIPTADDONS "scriptaddons." KVI_FILEEXTENSION_CONFIG
+#define KVI_CONFIGFILE_IDENTITIES "identities." KVI_FILEEXTENSION_CONFIG
+
+#endif //_KVI_CONFIGNAMES_H_
diff --git a/src/kvilib/config/kvi_debug.h b/src/kvilib/config/kvi_debug.h
new file mode 100644
index 00000000..8ae1a120
--- /dev/null
+++ b/src/kvilib/config/kvi_debug.h
@@ -0,0 +1,52 @@
+#ifndef _KVI_DEBUG_H_
+#define _KVI_DEBUG_H_
+
+//=============================================================================
+//
+// File : kvi_debug.h
+// Creation date : Fri Mar 19 1999 03:10:39 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include <qglobal.h>
+
+//=============================================================================
+// This file contains the definition of the debug macros
+// You can enable ALL the debugging output by uncommenting the next line
+//
+// #define _KVI_DEBUG_CHECK_RANGE_
+//
+//=============================================================================
+
+#ifdef _KVI_DEBUG_CHECK_RANGE_
+ #define __range_valid(_expr) if(!(_expr))debug("[kvirc]: ASSERT FAILED: \"%s\" is false in %s (%d)",#_expr,__FILE__,__LINE__)
+ #define __range_invalid(_expr) if(_expr)debug("[kvirc]: ASSERT FAILED: \"%s\" is true in %s (%d)",#_expr,__FILE__,__LINE__)
+#else
+ #define __range_valid(_expr)
+ #define __range_invalid(_expr)
+#endif
+
+#if defined(_KVI_DEBUG_) || defined(__KVI_DEBUG__)
+ #define __ASSERT(_expr) if(!(_expr))debug("[kvirc]: ASSERT FAILED: \"%s\" is false in %s (%d)",#_expr,__FILE__,__LINE__)
+#else
+ #define __ASSERT(_expr)
+#endif
+
+#endif //_KVI_DEBUG_H_
diff --git a/src/kvilib/config/kvi_defaults.h b/src/kvilib/config/kvi_defaults.h
new file mode 100644
index 00000000..fc375b05
--- /dev/null
+++ b/src/kvilib/config/kvi_defaults.h
@@ -0,0 +1,65 @@
+#ifndef _KVI_DEFAULTS_H_
+#define _KVI_DEFAULTS_H_
+
+//=============================================================================
+//
+// File : kvi_defaults.h
+// Creation date : Wed Jun 21 2000 13:23:13 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+//=============================================================================
+// This file contains (more or less) freely customizable compile time defaults
+//
+// You can safely play with the ones you understand the meaning of
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_ON_WINDOWS
+ #define KVI_HOME_CONFIG_FILE_NAME "kvirc.ini"
+#else
+ #define KVI_HOME_CONFIG_FILE_NAME ".kvirc.rc"
+#endif
+
+
+#define KVI_DEFAULT_INCOMING_SUBDIRECTORY_NAME "download"
+
+#define KVI_DEFAULT_NICKNAME1 "newbie"
+#define KVI_DEFAULT_NICKNAME2 "[newbie]"
+#define KVI_DEFAULT_NICKNAME3 "_newbie_"
+#define KVI_DEFAULT_NICKNAME4 "newbie4"
+#define KVI_DEFAULT_USERNAME "kvirc"
+#define KVI_DEFAULT_REALNAME "KVIrc " VERSION " '" KVI_RELEASE_NAME "' http://kvirc.net/"
+
+#define KVI_DEFAULT_PART_MESSAGE "No matter how dark the night, somehow the Sun rises once again"
+#define KVI_DEFAULT_QUIT_MESSAGE "KVIrc $version $version(r) http://www.kvirc.net/"
+#define KVI_DEFAULT_CTCP_USERINFO_REPLY "I'm too lazy to edit this field."
+#define KVI_DEFAULT_CTCP_PAGE_REPLY "Your message has been received and logged"
+#define KVI_DEFAULT_AWAY_MESSAGE "I'm off to see the wizard."
+#define KVI_DEFAULT_AWAY_NICK "%nick%|NotHere"
+
+#define KVI_MAX_PENDING_AVATARS 20
+#define KVI_MAX_RECENT_SERVERS 10
+#define KVI_MAX_RECENT_CHANNELS 30
+#define KVI_MAX_RECENT_NICKNAMES 10
+#define KVI_RECENT_TOPIC_ENTRIES 20
+
+#endif //_KVI_DEFAULTS_H_
diff --git a/src/kvilib/config/kvi_fileextensions.h b/src/kvilib/config/kvi_fileextensions.h
new file mode 100644
index 00000000..e181c974
--- /dev/null
+++ b/src/kvilib/config/kvi_fileextensions.h
@@ -0,0 +1,37 @@
+#ifndef _KVI_FILEEXTENSIONS_H_
+#define _KVI_FILEEXTENSIONS_H_
+
+//=============================================================================
+//
+// File : kvi_fileextensions.h
+// Creation date : Tue Dec 26 2006 05:09:22 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+//=============================================================================
+// This file contains the file extensions used by KVIrc
+//=============================================================================
+
+#define KVI_FILEEXTENSION_CONFIG "kvc"
+#define KVI_FILEEXTENSION_SCRIPT "kvs"
+#define KVI_FILEEXTENSION_THEMEPACKAGE "kvt"
+#define KVI_FILEEXTENSION_ADDONPACKAGE "kva"
+
+#endif //_KVI_FILEEXTENSIONS_H_
diff --git a/src/kvilib/config/kvi_settings.h b/src/kvilib/config/kvi_settings.h
new file mode 100644
index 00000000..ee6044bd
--- /dev/null
+++ b/src/kvilib/config/kvi_settings.h
@@ -0,0 +1,140 @@
+#ifndef _KVI_SETTINGS_H_
+#define _KVI_SETTINGS_H_
+
+//=============================================================================
+//
+// File : kvi_settings.h
+// Creation date : Fri Mar 19 1999 05:21:13 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+//=============================================================================
+// This file contains compile time settings, either set by configure or
+// non-customizable defaults
+//
+// Better do not touch this
+//=============================================================================
+
+#include <qglobal.h>
+
+#if defined(_OS_WIN32_) || defined(Q_OS_WIN32) || defined(Q_OS_WIN32_)
+
+ #define FEEL_LIKE_I_AM_COMPILING_UNDER_WINDOZE
+ #define COMPILE_ON_WINDOWS
+
+ // Windows has no config.h
+
+ #include "kvi_wincfg.h"
+
+ #ifdef __KVILIB__
+ #define KVILIB_API __declspec(dllexport)
+ #else
+ #define KVILIB_API __declspec(dllimport)
+ #endif
+
+ #ifdef __KVIRC__
+ #define KVIRC_API __declspec(dllexport)
+ #else
+ #define KVIRC_API __declspec(dllimport)
+ #endif
+
+#else
+
+ #ifdef KVIRC_EXTERNAL_MODULE
+ // when compiling an external module
+ // include the last configuration
+ #include "kvi_configstatus.h"
+ #else
+ #ifdef HAVE_CONFIG_H
+ #include "config.h"
+ #else
+ #error "You're missing the config.h file: you must run configure before running make!"
+ #endif
+ #endif
+
+ #define KVILIB_API
+ #define KVIRC_API
+
+ #ifndef VERSION
+ #define VERSION "?.?.?"
+ #endif
+
+ #ifndef BUILD_DATE
+ #define BUILD_DATE "?"
+ #endif
+
+ #ifndef BUILD_FLAGS
+ #define BUILD_FLAGS "?"
+ #endif
+
+#endif
+
+#define KVI_VERSION VERSION
+#define KVI_VERSION_BRANCH VERSION_BRANCH
+#define KVI_BUILD_DATE BUILD_DATE
+#define KVI_BUILD_FLAGS BUILD_FLAGS
+
+#define KVI_RELEASE_NAME "Virgo"
+
+// We want _GNU_SOURCE features
+#ifndef _GNU_SOURCE
+ #define _GNU_SOURCE
+#endif
+
+
+#if defined(__GNUC__)
+ // gcc
+ #if __GNUC__ >= 3
+ #define KVI_PTR2MEMBER(__x) &__x
+ #else
+ #define KVI_PTR2MEMBER(__x) &(__x)
+ #endif
+#elif defined(COMPILE_ON_WINDOWS)
+ // Visual C++
+ #define KVI_PTR2MEMBER(__x) &__x
+#elif defined(__SUNPRO_CC)
+ // Sun Forte
+ #define KVI_PTR2MEMBER(__x) (__x)
+#else
+ // default
+ #define KVI_PTR2MEMBER(__x) &(__x)
+#endif
+
+#ifdef COMPILE_NO_X
+ #ifndef COMPILE_NO_X_BELL
+ #define COMPILE_NO_X_BELL
+ #endif
+#endif
+
+/*
+#if __GNUC__ - 0 > 3 || (__GNUC__ - 0 == 3 && __GNUC_MINOR__ - 0 >= 2)
+ #define KVI_DEPRECATED __attribute__ ((deprecated))
+#else
+ #define KVI_DEPRECATED
+#endif
+*/
+#define KVI_DEPRECATED
+
+#ifdef COMPILE_USE_QT4
+ #define debug qDebug
+#endif
+
+
+#endif //_KVI_SETTINGS_H_
diff --git a/src/kvilib/config/kvi_sourcesdate.h b/src/kvilib/config/kvi_sourcesdate.h
new file mode 100644
index 00000000..263fc092
--- /dev/null
+++ b/src/kvilib/config/kvi_sourcesdate.h
@@ -0,0 +1,40 @@
+
+#ifndef _KVI_SOURCESDATE_H_
+#define _KVI_SOURCESDATE_H_
+
+//=============================================================================
+//
+// File : kvi_sourcesdate.h
+// Creation date : Sun Mar 5 2006 23:22:22 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#define KVI_SOURCES_DATE "20080323"
+#define KVI_SOURCES_DATE_NUMERIC 0x20080323
+
+// this is the date of the sources before that we should force a setup
+// this is usually changed only when a setup is really needed because
+// of an incompatible change in the configuration files
+// .. so do NOT change it just when you change KVI_SOURCES_DATE_NUMERIC :)
+#define KVI_SOURCES_DATE_NUMERIC_FORCE_SETUP 0x20080101
+
+#endif //!_KVI_SOURCESDATE_H_
diff --git a/src/kvilib/config/kvi_version.h b/src/kvilib/config/kvi_version.h
new file mode 100644
index 00000000..e09dacef
--- /dev/null
+++ b/src/kvilib/config/kvi_version.h
@@ -0,0 +1,33 @@
+#ifndef _KVI_VERSION_H_
+#define _KVI_VERSION_H_
+
+//=============================================================================
+//
+// File : kvi_version.h
+// Creation date : Sun Mar 5 2006 23:22:22 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+
+
+#endif //!_KVI_VERSION_H_
+
diff --git a/src/kvilib/config/kvi_wincfg.h b/src/kvilib/config/kvi_wincfg.h
new file mode 100644
index 00000000..f90998a8
--- /dev/null
+++ b/src/kvilib/config/kvi_wincfg.h
@@ -0,0 +1,210 @@
+#ifndef _KVI_WINCFG_H_
+#define _KVI_WINCFG_H_
+
+//=============================================================================
+//
+// File : kvi_wincfg.h
+// Creation date : Fri Sep 21 16:21:09 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+//=============================================================================
+// Windows configuration: do not touch
+//=============================================================================
+
+/* define if you want to compile with new parser */
+#define COMPILE_NEW_KVS 1
+
+/* define if you want to use the Qt 4.x support */
+/* #undef COMPILE_USE_QT4 */
+
+#define COMPILE_USE_QT4
+
+/* define if you want to use only the new KVS parser */
+#define COMPILE_ONLY_NEW_KVS 1
+
+/* define if you want to disable DCC VOICE sound support */
+/* #undef COMPILE_WITH_NO_SOUND */
+
+/* define if you have libgsm and want the GSM code to be compiled */
+/* #undef COMPILE_USE_GSM */
+
+/* define if you want the info tips to be compiled in */
+#define COMPILE_INFO_TIPS 1
+
+/* define if you want to compile the KDE 2.x support */
+/* #undef COMPILE_KDE_SUPPORT */
+
+/* define if you want the gcc memory profile */
+/* #undef COMPILE_MEMORY_PROFILE */
+
+/* define if you want the memory checks */
+/* #undef COMPILE_MEMORY_CHECKS */
+
+/* define if you trust your memmove() function */
+#define COMPILE_WITH_SYSTEM_MEMMOVE 1
+
+/* define if you want to compile the crypt support */
+#define COMPILE_CRYPT_SUPPORT 1
+
+/* define if you want the i386 asm code */
+/* #undef COMPILE_ix86_ASM */
+
+/* define if your compiler supports gotos do dynamic labels */
+/* #undef COMPILE_USE_DYNAMIC_LABELS */
+
+/* define if you want to compile the localization support */
+#define COMPILE_LOCALE_STUFF 1
+
+/* define if you want the IpV6 support */
+#define COMPILE_IPV6_SUPPORT 1
+
+/* define if you want zlib support */
+#define COMPILE_ZLIB_SUPPORT 1
+
+/* define if you want to use the pthreads library */
+/* #undef COMPILE_THREADS_USE_POSIX */
+
+/* define if you want to use the solaris libthread */
+/* #undef COMPILE_THREADS_USE_SOLARIS_LIBTHREAD */
+
+#define COMPILE_PSEUDO_TRANSPARENCY
+
+/* define if you have the SIOCGIFADDR ioctl and the related headers */
+/* #undef COMPILE_GET_INTERFACE_ADDRESS */
+
+/* this is the build date (configure date rather) */
+#define BUILD_DATE __DATE__" "__TIME__
+
+/* these are the build flags */
+#define BUILD_FLAGS "win32"
+
+/* define if you have strings.h */
+/* #undef HAVE_STRINGS_H */
+
+/* define if you have the getenv function */
+/* #undef HAVE_GETENV */
+
+/* define if you have the strerror function */
+#define HAVE_STRERROR 1
+
+/* define if you have the inet_aton function */
+/* #define HAVE_INET_ATON 1 */
+
+/* define if you have the inet_ntoa function */
+/* #define HAVE_INET_NTOA 1 */
+
+/* define if you have the inet_pton function */
+/* #undef HAVE_INET_PTON */
+
+/* define if you have the inet_ntop function */
+/* #undef HAVE_INET_NTOP */
+
+/* define if you have the getnameinfo function */
+#define HAVE_GETNAMEINFO
+
+/* define if you have the getaddrinfo function */
+#define HAVE_GETADDRINFO
+
+/* define this to the number of average channel users */
+#define AVERAGE_CHANNEL_USERS 101
+
+/* define this if you want to ignore the SIGALARM signal */
+/* #undef COMPILE_IGNORE_SIGALARM */
+
+/* define this if you are on a big endian machine */
+/* #undef BIG_ENDIAN_MACHINE_BYTE_ORDER */
+
+/* define this if you want to use the unicode-local 8bit charset translation */
+/* #undef COMPILE_USE_LOCAL_8BIT */
+
+/* define this if you want to disable the inter-process communication support */
+/* #undef COMPILE_NO_IPC */
+
+/* Define if you have the `getenv' function. */
+/* #undef HAVE_GETENV */
+
+/* Define if you have the <linux/soundcard.h> header file. */
+/* #undef HAVE_LINUX_SOUNDCARD_H */
+
+/* Define if you have the <soundcard.h> header file. */
+/* #undef HAVE_SOUNDCARD_H */
+
+/* Define if you have the <sys/soundcard.h> header file. */
+/* #undef HAVE_SYS_SOUNDCARD_H */
+
+/* Name of package */
+#define PACKAGE "kvirc"
+
+/* Version number of package */
+#define VERSION "3.4.0"
+
+#define VERSION_BRANCH "3.4"
+
+
+/* Define if the system does not provide POSIX.1 features except with this
+ defined. */
+/* #undef _POSIX_1_SOURCE */
+
+/* Define if you need to in order for `stat' and other things to work. */
+/* #undef _POSIX_SOURCE */
+
+// for now we need this....dcc voice is not ported yet
+#define COMPILE_WITH_NO_SOUND
+
+#define COMPILE_DISABLE_DCC_VOICE
+
+/* No X support */
+#define COMPILE_NO_X
+
+/* No X bell! */
+#define COMPILE_NO_X_BELL
+
+/* define if you have openssl and want the ssl support in kvirc */
+#define COMPILE_SSL_SUPPORT
+
+/* define if you want perl scripting support */
+#define COMPILE_PERL_SUPPORT
+
+/* The size of a `int', as computed by sizeof. */
+#define SIZEOF_INT 4
+
+/* The size of a `long int', as computed by sizeof. */
+#define SIZEOF_LONG_INT 4
+
+/* The size of a `long long int', as computed by sizeof. */
+#define SIZEOF_LONG_LONG_INT 8
+
+/* The size of a `short int', as computed by sizeof. */
+#define SIZEOF_SHORT_INT 2
+
+/* The size of a `unsigned int', as computed by sizeof. */
+#define SIZEOF_UNSIGNED_INT 4
+
+/* The size of a `unsigned long int', as computed by sizeof. */
+#define SIZEOF_UNSIGNED_LONG_INT 4
+
+/* The size of a `unsigned long long int', as computed by sizeof. */
+#define SIZEOF_UNSIGNED_LONG_LONG_INT 8
+
+/* The size of a `unsigned short int', as computed by sizeof. */
+#define SIZEOF_UNSIGNED_SHORT_INT 2
+
+#endif //_KVI_WINCFG_H_
diff --git a/src/kvilib/core/Makefile.am b/src/kvilib/core/Makefile.am
new file mode 100644
index 00000000..c84487eb
--- /dev/null
+++ b/src/kvilib/core/Makefile.am
@@ -0,0 +1,5 @@
+###############################################################################
+# KVirc IRC client Makefile - 16.12.98 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+EXTRA_DIST = *.cpp *.h
diff --git a/src/kvilib/core/kvi_bswap.h b/src/kvilib/core/kvi_bswap.h
new file mode 100644
index 00000000..5d5ef5bb
--- /dev/null
+++ b/src/kvilib/core/kvi_bswap.h
@@ -0,0 +1,63 @@
+#ifndef _KVI_BSWAP_H_
+#define _KVI_BSWAP_H_
+
+//=============================================================================
+//
+// File : kvi_bswap.h
+// Creation date : Fri Mar 19 1999 03:15:21 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_inttypes.h"
+
+
+// KVILIB_API has been removed from therse two functions
+// these should always go inlined
+
+inline kvi_u64_t kvi_swap64(kvi_u64_t i)
+{
+ // abcdefgh to hgfedcba
+ return ((i << 56) | /* h to a */
+ ((i & 0xff00) << 40) | /* g to b */
+ ((i & 0xff0000) << 24) | /* f to c */
+ ((i & 0xff000000) << 8) | /* e to d */
+ ((i >> 8) & 0xff000000) | /* d to e */
+ ((i >> 24) & 0xff0000) | /* c to f */
+ ((i >> 40) & 0xff00) | /* b to g */
+ (i >> 56)); /* a to h */
+}
+
+inline kvi_u32_t kvi_swap32(kvi_u32_t i)
+{
+ // abcd to dcba
+ return ((i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | (i >> 24));
+}
+
+inline kvi_u16_t kvi_swap16(kvi_u16_t i)
+{
+ // ab to ba
+ return ((i << 8) | (i >> 8));
+}
+
+
+
+
+#endif // !_KVI_BSWAP_H_
diff --git a/src/kvilib/core/kvi_error.cpp b/src/kvilib/core/kvi_error.cpp
new file mode 100644
index 00000000..6497c757
--- /dev/null
+++ b/src/kvilib/core/kvi_error.cpp
@@ -0,0 +1,237 @@
+//=============================================================================
+//
+// File : kvi_error.cpp
+// Creation date : Sun Jul 02 2000 18:37:02 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+
+#define _KVI_ERROR_CPP_
+
+#include "kvi_locale.h"
+#include "kvi_error.h"
+#include "kvi_settings.h"
+
+
+#ifdef COMPILE_ON_WINDOWS
+#include <winsock2.h> // for the WSAE* error codes
+#endif
+
+#include <errno.h>
+
+#ifdef HAVE_STRERROR
+#include <string.h> // for strerror()
+#endif
+
+// FIXME: This stuff should basically die and be eventually replaced with some
+// helper functions for handling ONLY system errors.
+//
+// WARNING: getDescription() is not even thread safe... it will die in the near future
+
+const char * g_errorTable[KVI_NUM_ERRORS]=
+{
+ __tr_no_lookup("Success"), // 000: success
+ __tr_no_lookup("Unknown error"), // 001: unkonwnError
+ __tr_no_lookup("Internal error"), // 002: internalError
+ __tr_no_lookup("Unknown command"), // 003: unknownCommand
+ __tr_no_lookup("Missing closing brace"), // 004: missingClosingBrace
+ __tr_no_lookup("Unexpected end of command in string"), // 005: unexpectedEndInString
+ __tr_no_lookup("Unexpected end of command in dictionary key"), // 006: unexpectedEndInDictionaryKey
+ __tr_no_lookup("Switch dash without switch letter"), // 007: switchDashWithoutSwitchLetter
+ __tr_no_lookup("Unknown function"), // 008: unknownFunction
+ __tr_no_lookup("Unexpected end of command in parenthesis"), // 009: unexpectedEndInParenthesis
+ __tr_no_lookup("Unexpected end of command in function parameters"), // 010: unexpectedEndInFunctionParams
+ __tr_no_lookup("Missing variable name"), // 011: missingVariableName
+ __tr_no_lookup("Variable or identifier expected"), // 012: variableOrIdentifierExpected
+ __tr_no_lookup("Left operand is not a number"), // 013: leftOperandIsNotANumber
+ __tr_no_lookup("Multiple operations not supported for numeric operators"), // 014: multipleOpsNotSupportedForOperator
+ __tr_no_lookup("Division by zero"), // 015: divisionByZero
+ __tr_no_lookup("Modulo by zero"), // 016: moduloByZero
+ __tr_no_lookup("Right operand is not a number"), // 017: rightOperandIsNotANumber
+ __tr_no_lookup("Unterminated expression (missing ')' ?)"), // 018: unterminatedExpression
+ __tr_no_lookup("Unterminated subexpression (Parenthesis mismatch)"), // 019: unterminatedSubexpression
+ __tr_no_lookup("Unexpected character"), // 020: unexpectedCharacter
+ __tr_no_lookup("Unknown operator"), // 021: unknownOperator
+ __tr_no_lookup("No host to resolve"), // 022
+ __tr_no_lookup("(DNS Internal) Unsupported address family"), // 023
+ __tr_no_lookup("Valid name but the host has no IP address"), // 024
+ __tr_no_lookup("Unrecoverable nameserver error (crashed ?)"), // 025
+ __tr_no_lookup("Dns temporaneous fault (try again)"), // 026
+ __tr_no_lookup("(DNS Internal) Bad flags"), // 027
+ __tr_no_lookup("(DNS Internal) Out of memory"), // 028
+ __tr_no_lookup("(DNS Internal) Service not supported"), // 029
+ __tr_no_lookup("Unknown node (host not found)"), // 030
+ __tr_no_lookup("(DNS Internal) Unsupported socket type"), // 031
+ __tr_no_lookup("Dns query failed"), // 032
+ __tr_no_lookup("This KVIrc executable has no IPV6 support"), // 033
+ __tr_no_lookup("Host not found"), // 034
+ __tr_no_lookup("(DNS Internal) IPC failure (slave data corrupted)"), // 035
+ __tr_no_lookup("Another connection in progress"), // 036
+ __tr_no_lookup("Invalid IP address"), // 037
+ __tr_no_lookup("Socket creation failed"), // 038
+ __tr_no_lookup("Failed to put the socket in non blocking mode"), // 039
+ __tr_no_lookup("Bad file descriptor"), // 040
+ __tr_no_lookup("Out of address space"), // 041
+ __tr_no_lookup("Connection refused"), // 042
+ __tr_no_lookup("Kernel networking panic"), // 043
+ __tr_no_lookup("Connection timed out"), // 044
+ __tr_no_lookup("Network is unreachable"), // 045
+ __tr_no_lookup("Broken pipe"), // 046
+ __tr_no_lookup("Invalid proxy address"), // 047
+ __tr_no_lookup("Remote end has closed the connection"), // 048
+ __tr_no_lookup("Invalid irc context id"), // 049
+ __tr_no_lookup("Error in loading module"), // 050
+ __tr_no_lookup("No such module command"), // 051
+ __tr_no_lookup("No such module function"), // 052
+ __tr_no_lookup("Left operand is not a dictionary reference"), // 053
+ __tr_no_lookup("Right operand is not a dictionary reference"), // 054
+ __tr_no_lookup("Missing object class name"), // 055
+ __tr_no_lookup("No such object class"), // 056
+ __tr_no_lookup("No such object"), // 057
+ __tr_no_lookup("No such object function"), // 058
+ __tr_no_lookup("Invalid left operand"), // 059
+ __tr_no_lookup("Not enough parameters"), // 060
+ __tr_no_lookup("Integer parameter expected"), // 061
+ __tr_no_lookup("Invalid parameter"), // 062
+ __tr_no_lookup("No such file"), // 063
+ __tr_no_lookup("Open parenthesis expected"), // 064
+ __tr_no_lookup("Open brace expected"), // 065
+ __tr_no_lookup("Can't kill a builtin class"), // 066
+ __tr_no_lookup("The SOCKSV4 protocol lacks IpV6 support"), // 067
+ __tr_no_lookup("Unrecognized proxy reply"), // 068
+ __tr_no_lookup("Proxy response: auth failed: access denied"),
+ __tr_no_lookup("Proxy response: No acceptable auth method: request rejected"),
+ __tr_no_lookup("Proxy response: request failed"),
+ __tr_no_lookup("Proxy response: ident failed"),
+ __tr_no_lookup("Proxy response: ident not matching"),
+ __tr_no_lookup("Proxy response: general SOCKS failure"),
+ __tr_no_lookup("Proxy response: connection not allowed"),
+ __tr_no_lookup("Proxy response: network unreachable"),
+ __tr_no_lookup("Proxy response: host unreachable"),
+ __tr_no_lookup("Proxy response: connection refused"),
+ __tr_no_lookup("Proxy response: TTL expired"),
+ __tr_no_lookup("Proxy response: command not supported"),
+ __tr_no_lookup("Proxy response: address type not supported"),
+ __tr_no_lookup("Proxy response: invalid address"),
+ __tr_no_lookup("Invalid port number"),
+ __tr_no_lookup("Socket not connected"),
+ __tr_no_lookup("Insufficient resources to complete the operation"),
+ __tr_no_lookup("Can't setup a listening socket : bind failed"),
+ __tr_no_lookup("Can't resolve the localhost name"),
+ __tr_no_lookup("Unsupported image format"),
+ __tr_no_lookup("Can't open file for appending"),
+ __tr_no_lookup("Can't open file for writing"),
+ __tr_no_lookup("File I/O error"),
+ __tr_no_lookup("Acknowledge error"),
+ __tr_no_lookup("Can't open file for reading"),
+ __tr_no_lookup("Can't send a zero-size file"),
+ __tr_no_lookup("Missing popup name"),
+ __tr_no_lookup("'item', 'popup', 'label' or 'separator' keyword expected"),
+ __tr_no_lookup("Self modification not allowed"),
+ __tr_no_lookup("UNUSED"),
+ __tr_no_lookup("Feature not available"),
+ __tr_no_lookup("Unexpected characters in array index"),
+ __tr_no_lookup("Unexpected end in expression"),
+ __tr_no_lookup("Unexpected end in array index"),
+ __tr_no_lookup("Connection thru HTTP proxy failed"),
+ __tr_no_lookup("Case , match , regexp , default or break keyword expected"),
+ __tr_no_lookup("Access denied"),
+ __tr_no_lookup("Address already in use"),
+ __tr_no_lookup("Can't assign the requested address"),
+ __tr_no_lookup("Connection reset by peer"),
+ __tr_no_lookup("Host unreachable (no route to host)"),
+ __tr_no_lookup("Variable expected"),
+ __tr_no_lookup("Invalid array index: positive integer expected"),
+ __tr_no_lookup("listen() call failed"),
+ __tr_no_lookup("This executable has been compiled without SSL support"),
+ __tr_no_lookup("Secure Socket Layer error"),
+ __tr_no_lookup("Slash (/) character expected"),
+ __tr_no_lookup("Unknown string manipulation operation"),
+ __tr_no_lookup("Operation aborted"),
+ __tr_no_lookup("Unexpected token"),
+ __tr_no_lookup("Scope object already defined (unexpected @)"),
+ __tr_no_lookup("There is no $this pointer in this scope (unexpected @)")
+};
+
+namespace KviError
+{
+ const char * getUntranslatedDescription(int iErrorCode)
+ {
+ if((iErrorCode < KVI_NUM_ERRORS) && (iErrorCode >= 0))
+ return g_errorTable[iErrorCode];
+#ifdef HAVE_STRERROR
+ if(iErrorCode < 0)return strerror(-iErrorCode);
+#endif
+ return g_errorTable[KviError_unknownError];
+ }
+
+ QString getDescription(int iErrorCode)
+ {
+ return __tr2qs_no_xgettext(getUntranslatedDescription(iErrorCode));
+ }
+
+ int translateSystemError(int iErrNo)
+ {
+#ifdef COMPILE_ON_WINDOWS
+ switch(iErrNo)
+ {
+ case EBADF: return KviError_badFileDescriptor; break;
+ case WSAEINVAL:
+ case WSAEFAULT:
+ case EFAULT: return KviError_outOfAddressSpace; break;
+ case WSAECONNREFUSED: return KviError_connectionRefused; break;
+ case WSAENOTSOCK: return KviError_kernelNetworkingPanic; break;
+ case WSAETIMEDOUT: return KviError_connectionTimedOut; break;
+ case WSAENETUNREACH: return KviError_networkUnreachable; break;
+ case EPIPE: return KviError_brokenPipe; break;
+ case WSAENOTCONN: return KviError_socketNotConnected; break;
+
+ case WSAEACCES: return KviError_accessDenied; break;
+ case WSAEADDRINUSE: return KviError_addressAlreadyInUse; break;
+ case WSAEADDRNOTAVAIL: return KviError_cantAssignRequestedAddress; break;
+ case WSAEAFNOSUPPORT: return KviError_unsupportedAddressFamily; break;
+ case WSAECONNRESET: return KviError_connectionResetByPeer; break;
+ case WSAEHOSTUNREACH: return KviError_hostUnreachable; break;
+
+ //case ENOBUFS: return KviError_insufficientResources; break;
+ // Unhandled error...pass errno to the strerror function
+ default: return -iErrNo; break;
+ }
+#else
+ switch(iErrNo)
+ {
+ case EBADF: return KviError_badFileDescriptor; break;
+ case EFAULT: return KviError_outOfAddressSpace; break;
+ case ECONNREFUSED: return KviError_connectionRefused; break;
+ case ENOTSOCK: return KviError_kernelNetworkingPanic; break;
+ case ETIMEDOUT: return KviError_connectionTimedOut; break;
+ case ENETUNREACH: return KviError_networkUnreachable; break;
+ case EPIPE: return KviError_brokenPipe; break;
+ case ENOTCONN: return KviError_socketNotConnected; break;
+ case ENOBUFS: return KviError_insufficientResources; break;
+ case EHOSTUNREACH: return KviError_hostUnreachable; break;
+ // Unhandled error...pass errno to the strerror function
+ default: return -iErrNo; break;
+ }
+#endif
+ }
+};
+
diff --git a/src/kvilib/core/kvi_error.h b/src/kvilib/core/kvi_error.h
new file mode 100644
index 00000000..7ab55e88
--- /dev/null
+++ b/src/kvilib/core/kvi_error.h
@@ -0,0 +1,188 @@
+#ifndef _KVI_ERROR_H_
+#define _KVI_ERROR_H_
+//=============================================================================
+//
+// File : kvi_error.h
+// Creation date : Sun Jul 02 2000 18:35:56 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+
+#define KviError_success 0
+#define KviError_unknownError 1
+#define KviError_internalError 2
+#define KviError_unknownCommand 3
+#define KviError_missingClosingBrace 4
+#define KviError_unexpectedEndInString 5
+#define KviError_unexpectedEndInDictionaryKey 6
+#define KviError_switchDashWithoutSwitchLetter 7
+#define KviError_unknownFunction 8
+#define KviError_unexpectedEndInParenthesis 9
+#define KviError_unexpectedEndInFunctionParams 10
+#define KviError_missingVariableName 11
+#define KviError_variableOrIdentifierExpected 12
+#define KviError_leftOperandIsNotANumber 13
+#define KviError_multipleOpsNotSupportedForOperator 14
+#define KviError_divisionByZero 15
+#define KviError_moduloByZero 16
+#define KviError_rightOperandIsNotANumber 17
+#define KviError_unterminatedExpression 18
+#define KviError_unterminatedSubexpression 19
+#define KviError_unexpectedCharacter 20
+#define KviError_unknownOperator 21
+
+#define KviError_noHostToResolve 22
+#define KviError_unsupportedAddressFamily 23
+#define KviError_validNameButNoIpAddress 24
+#define KviError_unrecoverableNameserverError 25
+#define KviError_dnsTemporaneousFault 26
+#define KviError_dnsInternalErrorBadFlags 27
+#define KviError_dnsInternalErrorOutOfMemory 28
+#define KviError_dnsInternalErrorServiceNotSupported 29
+#define KviError_dnsNoName 30
+#define KviError_dnsInternalErrorUnsupportedSocketType 31
+#define KviError_dnsQueryFailed 32
+#define KviError_noIpV6Support 33
+#define KviError_hostNotFound 34
+#define KviError_dnsInternalIPCFailure 35
+
+#define KviError_anotherConnectionInProgress 36
+#define KviError_invalidIpAddress 37
+#define KviError_socketCreationFailed 38
+#define KviError_asyncSocketFailed 39
+#define KviError_badFileDescriptor 40
+#define KviError_outOfAddressSpace 41
+#define KviError_connectionRefused 42
+#define KviError_kernelNetworkingPanic 43
+#define KviError_connectionTimedOut 44
+#define KviError_networkUnreachable 45
+#define KviError_brokenPipe 46
+#define KviError_invalidProxyAddress 47
+#define KviError_remoteEndClosedConnection 48
+
+#define KviError_invalidIrcContextId 49
+#define KviError_errorInLoadingModule 50
+#define KviError_noSuchModuleCommand 51
+#define KviError_noSuchModuleFunction 52
+
+#define KviError_leftOperandIsNotADictionaryReference 53
+#define KviError_rightOperandIsNotADictionaryReference 54
+
+#define KviError_missingObjectClassName 55
+#define KviError_noSuchObjectClass 56
+#define KviError_noSuchObject 57
+#define KviError_noSuchObjectFunction 58
+
+#define KviError_invalidLeftOperand 59
+
+#define KviError_notEnoughParameters 60
+#define KviError_integerParameterExpected 61
+#define KviError_invalidParameter 62
+
+#define KviError_noSuchFile 63
+
+#define KviError_openParenthesisExpected 64
+#define KviError_openBraceExpected 65
+
+#define KviError_cantKillABuiltinClass 66
+#define KviError_socksV4LacksIpV6Support 67
+#define KviError_unrecognizedProxyReply 68
+#define KviError_proxyAuthFailed 69
+#define KviError_proxyNoAcceptableAuthMethod 70
+
+#define KviError_proxyReply91RequestFailed 71
+#define KviError_proxyReply92IdentFailed 72
+#define KviError_proxyReply93IdentNotMatching 73
+#define KviError_proxyReply01GeneralSOCKSFailure 74
+#define KviError_proxyReply02ConnectionNotAllowed 75
+#define KviError_proxyReply03NetworkUnreachable 76
+#define KviError_proxyReply04HostUnreachable 77
+#define KviError_proxyReply05ConnectionRefused 78
+#define KviError_proxyReply06TTLExpired 79
+#define KviError_proxyReply07CommandNotSupported 80
+#define KviError_proxyReply08AddressTypeNotSupported 81
+#define KviError_proxyReply09InvalidAddress 82
+
+#define KviError_invalidPortNumber 83
+#define KviError_socketNotConnected 84
+#define KviError_insufficientResources 85
+#define KviError_bindFailed 86
+#define KviError_cantResolveLocalhost 87
+
+#define KviError_unsupportedImageFormat 88
+
+#define KviError_cantOpenFileForAppending 89
+#define KviError_cantOpenFileForWriting 90
+#define KviError_fileIOError 91
+#define KviError_acknowledgeError 92
+#define KviError_cantOpenFileForReading 93
+#define KviError_cantSendAZeroSizeFile 94
+
+#define KviError_missingPopupName 95
+#define KviError_itemPopupOrSeparatorExpected 96
+#define KviError_selfModificationNotAllowed 97
+
+//#define KviError_recursionTooDeep 98
+#define KviError_featureNotAvailable 99
+
+#define KviError_unexpectedCharactersInArrayIndex 100
+#define KviError_unexpectedEndInExpression 101
+#define KviError_unexpectedEndInArrayIndex 102
+
+#define KviError_proxyHttpFailure 103
+#define KviError_caseMatchRegexpDefaultOrBreakExpected 104
+
+
+#define KviError_accessDenied 105
+#define KviError_addressAlreadyInUse 106
+#define KviError_cantAssignRequestedAddress 107
+#define KviError_connectionResetByPeer 108
+#define KviError_hostUnreachable 109
+
+#define KviError_variableExpected 110
+#define KviError_invalidArrayIndex 111
+
+#define KviError_listenFailed 112
+
+#define KviError_noSSLSupport 113
+#define KviError_SSLError 114
+
+#define KviError_slashCharacterExpected 115
+#define KviError_unknownStringManipulationOperator 116
+
+#define KviError_operationAborted 117
+
+#define KviError_unexpectedToken 118
+
+#define KviError_scopeObjectAlreadyDefined 119
+#define KviError_noThisObject 120
+
+#define KVI_NUM_ERRORS 121
+
+namespace KviError
+{
+ KVILIB_API QString getDescription(int iErrorCode);
+ KVILIB_API const char * getUntranslatedDescription(int iErrorCode);
+ KVILIB_API int translateSystemError(int iErrNo);
+};
+
+#endif //_KVI_ERROR_H_
diff --git a/src/kvilib/core/kvi_heapobject.cpp b/src/kvilib/core/kvi_heapobject.cpp
new file mode 100644
index 00000000..7568086d
--- /dev/null
+++ b/src/kvilib/core/kvi_heapobject.cpp
@@ -0,0 +1,96 @@
+//=============================================================================
+//
+// File : kvi_heapobject.cpp
+// Created on Wed 24 Mar 2004 04:45:17 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004-2006 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+
+
+#include "kvi_heapobject.h"
+#include "kvi_malloc.h"
+
+// On windows we need to override new and delete operators
+// to ensure that always the right new/delete pair is called for an object instance
+// This bug jumps out because windows uses a local heap for each
+// executable module (exe or dll).
+// (this is a well known bug described in Q122675 of MSDN)
+
+// on Linux it is not needed: there is a single global heap
+
+
+
+// 05.02.2005 : scalar/vector deleting destructors in modules
+//
+// There are also other issues involving the MSVC compiler.
+// When the operator new is called on an object with a virtual
+// destructor the compiler generates a helper function
+// called "vector deleting destructor" that is used to both
+// free the object's memory and call the object's destructor.
+// (In fact there is also a "scalar deleting destructor" but
+// MSVC seems to call the vector version also for scalar deletes ?!?)
+// The problem arises when operator new is called in a module:
+// the helper function gets stuffed in one of the module's sections
+// and when the module is unloaded any attempt to delete
+// the object will simply jump into no man's land.
+
+// An "unhandled exception" in a "call [%eax]" corresponding
+// to a delete <pointer> may be a symptom of this problem.
+
+// I haven't been able to find a solution nicer than having
+// a static allocation function in each class that can be
+// created from inside a module and destroyed anywhere else
+// and has a virtual destructor.
+
+#ifdef COMPILE_ON_WINDOWS
+ void * KviHeapObject::operator new(size_t uSize)
+ {
+ return kvi_malloc(uSize);
+ }
+
+ void KviHeapObject::operator delete(void * pData)
+ {
+ kvi_free(pData);
+ }
+
+ void * KviHeapObject::operator new[](size_t uSize)
+ {
+ return kvi_malloc(uSize);
+ }
+
+ void KviHeapObject::operator delete[](void * pData)
+ {
+ kvi_free(pData);
+ }
+
+ // these are the debug versions...
+ void * KviHeapObject::operator new(size_t uSize,const char *,int)
+ {
+ return kvi_malloc(uSize);
+ }
+
+ void KviHeapObject::operator delete(void * pData,const char *,int)
+ {
+ kvi_free(pData);
+ }
+#endif
+
+
diff --git a/src/kvilib/core/kvi_heapobject.h b/src/kvilib/core/kvi_heapobject.h
new file mode 100644
index 00000000..3d1638cf
--- /dev/null
+++ b/src/kvilib/core/kvi_heapobject.h
@@ -0,0 +1,50 @@
+#ifndef _KVI_HEAPOBJECT_H_
+#define _KVI_HEAPOBJECT_H_
+//=============================================================================
+//
+// File : kvi_heapobject.h
+// Created on Wed 24 Mar 2004 04:45:17 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004-2006 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+// See kvi_heapobject.cpp for comments on this class
+
+#ifdef COMPILE_ON_WINDOWS
+
+ class KVILIB_API KviHeapObject
+ {
+ public:
+ void * operator new(size_t uSize);
+ void operator delete(void * pData);
+ void * operator new[](size_t uSize);
+ void operator delete[](void * pData);
+ void * operator new(size_t uSize,const char *,int);
+ void operator delete(void * pData,const char *,int);
+ };
+#else //!COMPILE_ON_WINDOWS
+ class KVILIB_API KviHeapObject
+ {
+ // on other platforms this crap is not necessary
+ };
+#endif //!COMPILE_ON_WINDOWS
+
+#endif //!_KVI_HEAPOBJECT_H_
diff --git a/src/kvilib/core/kvi_inttypes.h b/src/kvilib/core/kvi_inttypes.h
new file mode 100644
index 00000000..6405ee79
--- /dev/null
+++ b/src/kvilib/core/kvi_inttypes.h
@@ -0,0 +1,95 @@
+#ifndef _KVI_INTTYPES_H_
+#define _KVI_INTTYPES_H_
+//=============================================================================
+//
+// File : kvi_inttypes.h
+// Creation date : Wed Sep 4 22:28:00 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002-2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_ON_WINDOWS
+ // we don't have a configure script here
+ // so we can't check the size of types
+ // We rely on the ms specific definitions then
+ typedef __int64 kvi_i64_t;
+ typedef unsigned __int64 kvi_u64_t;
+ typedef int kvi_i32_t;
+ typedef unsigned int kvi_u32_t;
+ typedef short int kvi_i16_t;
+ typedef short unsigned int kvi_u16_t;
+ typedef char kvi_i8_t;
+ typedef unsigned char kvi_u8_t;
+#else
+ #if SIZEOF_LONG_INT == 8
+ // the most common case on 64 bit machines
+ typedef long int kvi_i64_t;
+ typedef unsigned long int kvi_u64_t;
+ #elif SIZEOF_INT == 8
+ // 64 bit ints ?.. a Cray ? :D
+ typedef int kvi_i64_t;
+ typedef unsigned int kvi_u64_t;
+ #elif SIZEOF_LONG_LONG_INT == 8
+ // the most common case on 32 bit machines
+ typedef long long int kvi_i64_t;
+ typedef unsigned long long int kvi_u64_t;
+ #else
+ // attempt to live without a 64bit integer type anyway...
+ // dunno if it will work tough...
+ typedef long long int kvi_i64_t;
+ typedef unsigned long long int kvi_u64_t;
+ #endif
+
+ #if SIZEOF_INT == 4
+ // the most common case
+ typedef int kvi_i32_t;
+ typedef unsigned int kvi_u32_t;
+ #elif SIZEOF_SHORT_INT == 4
+ // 32 bit shorts ?.. a Cray ? :D
+ typedef short int kvi_i32_t;
+ typedef short unsigned int kvi_u32_t;
+ #elif SIZEOF_LONG_INT == 4
+ typedef long int kvi_i32_t;
+ typedef unsigned long int kvi_u32_t;
+ #else
+ #error "Can't find a 32 bit integral type on this system"
+ #error "Please report to pragma at kvirc dot net"
+ #endif
+
+ #if SIZEOF_SHORT_INT == 2
+ // the most common case
+ typedef short int kvi_i16_t;
+ typedef short unsigned int kvi_u16_t;
+ #elif SIZEOF_INT == 2
+ // this isn't going to work anyway, I think..
+ typedef int kvi_i16_t;
+ typedef long int kvi_u16_t;
+ #else
+ #error "Can't find a 16 bit integral type on this system"
+ #error "Please report to pragma at kvirc dot net"
+ #endif
+
+ // assume that char is always 8 bit
+ typedef char kvi_i8_t;
+ typedef unsigned char kvi_u8_t;
+#endif
+
+#endif //_KVI_INTTYPES_H_
diff --git a/src/kvilib/core/kvi_malloc.cpp b/src/kvilib/core/kvi_malloc.cpp
new file mode 100644
index 00000000..9c418ec5
--- /dev/null
+++ b/src/kvilib/core/kvi_malloc.cpp
@@ -0,0 +1,198 @@
+//=============================================================================
+//
+// File : kvi_malloc.cpp
+// Creation date : Sun Jun 18 2000 18:26:27 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+//=============================================================================
+// C memory allocation routines
+// This stuff is rather unused, because in normal compilations
+// kvi_malloc , kvi_free and kvi_realloc are macros (see kvi_malloc.h)
+//=============================================================================
+
+#define __KVILIB__
+
+#define _KVI_MALLOC_CPP_
+#include "kvi_malloc.h"
+
+#include <stdio.h>
+
+
+
+#ifdef COMPILE_MEMORY_PROFILE
+
+ //
+ // Memory profile stuff
+ // Used to find memory leaks etc...
+ //
+
+ #include "kvi_pointerlist.h"
+
+ typedef struct _KviMallocEntry {
+ struct _KviMallocEntry * prev;
+ void * pointer;
+ int size;
+ void * return_addr1;
+ void * return_addr2;
+ struct _KviMallocEntry * next;
+ } KviMallocEntry;
+
+ int g_iMaxRequestSize = 0;
+ void * g_pMaxRequestReturnAddress1 = 0;
+ void * g_pMaxRequestReturnAddress2 = 0;
+ unsigned int g_iMallocCalls = 0;
+ unsigned int g_iReallocCalls = 0;
+ unsigned int g_iFreeCalls = 0;
+ unsigned int g_iTotalMemAllocated = 0;
+ unsigned int g_uAllocationPeak = 0;
+ KviMallocEntry * g_pEntries = 0;
+
+ void * kvi_malloc(int size)
+ {
+ g_iMallocCalls ++;
+ g_iTotalMemAllocated += size;
+ if(g_iTotalMemAllocated > g_uAllocationPeak)g_uAllocationPeak = g_iTotalMemAllocated;
+ if(g_iMaxRequestSize < size){
+ g_iMaxRequestSize = size;
+ g_pMaxRequestReturnAddress1 = __builtin_return_address(1);
+ g_pMaxRequestReturnAddress2 = __builtin_return_address(2);
+ }
+ KviMallocEntry * e = (KviMallocEntry *)malloc(sizeof(KviMallocEntry));
+ e->pointer = malloc(size);
+ e->size = size;
+ e->return_addr1 = __builtin_return_address(1);
+ e->return_addr2 = __builtin_return_address(2);
+ e->next = g_pEntries;
+ e->prev = 0;
+ if(g_pEntries)g_pEntries->prev = e;
+ g_pEntries = e;
+ return e->pointer;
+ }
+
+ void * kvi_realloc(void * ptr,int size)
+ {
+ g_iReallocCalls ++;
+ if(ptr == 0)return kvi_malloc(size);
+ if(g_iMaxRequestSize < size){
+ g_iMaxRequestSize = size;
+ g_pMaxRequestReturnAddress1 = __builtin_return_address(1);
+ g_pMaxRequestReturnAddress2 = __builtin_return_address(2);
+ }
+ KviMallocEntry *e = g_pEntries;
+ while(e){
+ if(e->pointer == ptr){
+ g_iTotalMemAllocated -= e->size;
+ g_iTotalMemAllocated += size;
+ if(g_iTotalMemAllocated > g_uAllocationPeak)g_uAllocationPeak = g_iTotalMemAllocated;
+ e->pointer = realloc(ptr,size);
+ e->size = size;
+ e->return_addr1 = __builtin_return_address(1);
+ e->return_addr2 = __builtin_return_address(2);
+ return e->pointer;
+ }
+ e = e->next;
+ }
+ fprintf(stderr,"Attempt to realloc an inexisting pointer (%p) (called from %p (%p))\n",ptr,__builtin_return_address(1),__builtin_return_address(2));
+ return realloc(ptr,size);
+ }
+
+ void kvi_free(void * ptr)
+ {
+ g_iFreeCalls++;
+ if(ptr == 0){
+ fprintf(stderr,"Attempt to free a null pointer (called from %p (%p))\n",__builtin_return_address(1),__builtin_return_address(2));
+ exit(-1);
+ }
+ KviMallocEntry * e= g_pEntries;
+ while(e){
+ if(e->pointer == ptr){
+ g_iTotalMemAllocated -= e->size;
+ if(e->prev){
+ if(e == g_pEntries)fprintf(stderr,"Mem profiling internal error!\n");
+ e->prev->next = e->next;
+ if(e->next)e->next->prev = e->prev;
+ } else {
+ if(e != g_pEntries)fprintf(stderr,"Mem profiling internal error!\n");
+ if(e->next)e->next->prev = 0;
+ g_pEntries = e->next;
+ }
+ free(e);
+ return;
+ }
+ e = e->next;
+ }
+ fprintf(stderr,"Attempt to free an inexisting pointer (%p) (called from %p (%p))\n",ptr,__builtin_return_address(1),__builtin_return_address(2));
+ }
+
+ void kvi_memory_profile() __attribute__((destructor));
+ void kvi_memory_profile()
+ {
+ unsigned int countUnfreed = 0;
+ KviMallocEntry * e = g_pEntries;
+ while(e){
+ countUnfreed++;
+ e = e->next;
+ }
+ fprintf(stderr,"|====|====|====|====|====|====|====|====\n");
+ fprintf(stderr,"| Memory profile for KVIrc\n");
+ fprintf(stderr,"| Unfreed chunks : %d\n",countUnfreed);
+ fprintf(stderr,"| Total unfreed memory : %u bytes\n",g_iTotalMemAllocated);
+ fprintf(stderr,"|====|====|====|====|====|====|====|====\n");
+ fprintf(stderr,"| Possible unfreed chunks dump:\n");
+ e = g_pEntries;
+ while(e){
+ fprintf(stderr,"|====|====|\n");
+ fprintf(stderr,"| Currently unfreed chunk: %p\n",e->pointer);
+ fprintf(stderr,"| Size: %d\n",e->size);
+ fprintf(stderr,"| Caller address 1: %p\n",e->return_addr1);
+ fprintf(stderr,"| Caller address 2: %p\n",e->return_addr2);
+ if(e->size > 10)fprintf(stderr,"| Data: %.10s\n",e->pointer);
+ else if(e->size > 5)fprintf(stderr,"| Data: %.5s\n",e->pointer);
+ KviMallocEntry *toFree = e;
+ e = e->next;
+ free(toFree);
+ }
+ fprintf(stderr,"|====|====|====|====|====|====|====|====\n");
+ fprintf(stderr,"| Allocation peak : %u bytes\n",g_uAllocationPeak);
+ fprintf(stderr,"|====|====|====|====|====|====|====|====\n");
+ fprintf(stderr,"| Max request size : %d bytes\n",g_iMaxRequestSize);
+ fprintf(stderr,"| Called from %p (%p)\n",g_pMaxRequestReturnAddress1,g_pMaxRequestReturnAddress2);
+ fprintf(stderr,"|====|====|====|====|====|====|====|====\n");
+ fprintf(stderr,"| Malloc calls: %u\n",g_iMallocCalls);
+ fprintf(stderr,"| Realloc calls: %u\n",g_iReallocCalls);
+ fprintf(stderr,"| Free calls: %u\n",g_iFreeCalls);
+ fprintf(stderr,"|====|====|====|====|====|====|====|====\n");
+ }
+
+#else
+
+ #ifdef COMPILE_MEMORY_CHECKS
+
+ void outOfMemory()
+ {
+ //What a cool message :)
+ fprintf(stderr,"Virtual memory exhausted in malloc call....bye!\n");
+ exit(-1);
+ }
+
+ #endif
+
+#endif
diff --git a/src/kvilib/core/kvi_malloc.h b/src/kvilib/core/kvi_malloc.h
new file mode 100644
index 00000000..8a7204a5
--- /dev/null
+++ b/src/kvilib/core/kvi_malloc.h
@@ -0,0 +1,88 @@
+#ifndef _KVI_MALLOC_H_
+#define _KVI_MALLOC_H_
+
+//=============================================================================
+//
+// File : kvi_malloc.h
+// Creation date : Sun Jun 18 2000 18:18:36 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+//=============================================================================
+// C memory allocation routines: macros in common compilations
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#include <stdlib.h>
+
+#ifdef COMPILE_MEMORY_PROFILE
+
+ #ifdef COMPILE_ON_WINDOWS
+ #error "This stuff should be never compiled on Windows"
+ #endif
+
+ extern void * kvi_malloc(int size);
+ extern void * kvi_realloc(void * ptr,int size);
+ extern void kvi_free(void * ptr);
+
+#else
+
+ #ifndef COMPILE_MEMORY_CHECKS
+
+ // These two are the "common" ones
+ #define kvi_malloc(__size_) malloc(__size_)
+ #define kvi_realloc(__ptr_,__size_) realloc((void *)__ptr_,__size_)
+
+ #else
+
+ #ifdef COMPILE_ON_WINDOWS
+ #error "This stuff should be never compiled on Windows"
+ #endif
+
+ // Want to check all the pointers
+ #define kvi_malloc(__size_) kvi_safe_malloc(__size_)
+ #define kvi_realloc(__ptr_,__size_) kvi_safe_realloc((void *)__ptr_,__size_)
+
+ #ifndef _KVI_MALLOC_CPP_
+ extern void outOfMemory();
+ #endif
+
+ inline void * kvi_safe_malloc(int size)
+ {
+ void * ptr = malloc(size);
+ if(!ptr)outOfMemory();
+ return ptr;
+ }
+
+ inline void * kvi_safe_realloc(void * ptr,int size)
+ {
+ ptr = realloc(ptr,size);
+ if(!ptr)outOfMemory();
+ return ptr;
+ }
+
+ #endif //COMPILE_MEMORY_CHECKS
+
+ #define kvi_free(__ptr_) free((void *)__ptr_)
+
+#endif
+
+#endif //_KVI_MALLOC_H_
diff --git a/src/kvilib/core/kvi_memmove.cpp b/src/kvilib/core/kvi_memmove.cpp
new file mode 100644
index 00000000..1beb920a
--- /dev/null
+++ b/src/kvilib/core/kvi_memmove.cpp
@@ -0,0 +1,253 @@
+//=============================================================================
+//
+// File : kvi_memmove.cpp
+// Creation date : Sun Jun 18 2000 18:27:50 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+
+#define _KVI_DEBUG_CHECK_RANGE_
+#include "kvi_debug.h"
+
+#define _KVI_MEMMOVE_CPP_
+#include "kvi_memmove.h"
+
+// FIXME: #warning "With system memmove could be guessed by configure"
+
+#ifndef COMPILE_WITH_SYSTEM_MEMMOVE
+
+ #ifdef COMPILE_ix86_ASM
+
+
+ void *kvi_memmove(void * dst_ptr,const void *src_ptr,int len)
+ {
+ __range_valid(dst_ptr);
+ __range_valid(src_ptr);
+ __range_valid(len >= 0);
+ // Save pointer registers
+ asm(" pushl %esi"); // save %esi
+ asm(" pushl %edi"); // save %edi
+ // Load arguments
+ asm(" movl 16(%ebp),%ecx"); // %ecx = len
+ asm(" movl 12(%ebp),%esi"); // %esi = src
+ asm(" movl 8(%ebp),%edi"); // %edi = dst
+ // Compare src and dest
+ asm(" cmpl %esi,%edi"); // %edi - %esi
+ asm(" jbe move_from_bottom_to_top"); // if(%edi < %esi) jump to move_from_bottom_to_top
+ // dst_ptr > src_ptr
+ asm(" addl %ecx,%esi"); // %esi += %ecx (src_ptr += len);
+ asm(" addl %ecx,%edi"); // %edi += %ecx (dst_ptr += len);
+ asm(" decl %esi"); // %esi--; (src_ptr--);
+ asm(" decl %edi"); // %edi--; (dst_ptr--);
+ asm(" std"); // set direction flag (decrement esi and edi in movsb)
+ // Optimization : check for non-odd len (1,3,5,7...)
+ asm(" shr $1,%ecx"); // %ecx >> 1 , shifted bit -> CF
+ asm(" jnc move_two_bytes_top_to_bottom_directly"); // if !carry (CF == 0) skip this move
+ // Move the first byte (non-odd)
+ asm(" movsb %ds:(%esi),%es:(%edi)"); // *dst-- = *src-- if DF else *dst++ = *src++
+ asm("move_two_bytes_top_to_bottom_directly:");
+ asm(" decl %esi"); // %esi--; (src_ptr--);
+ asm(" decl %edi"); // %edi--; (dst_ptr--);
+ asm("move_two_bytes_top_to_bottom:");
+ asm(" shr $1,%ecx"); // %ecx >> 1 , shifted bit -> CF
+ asm(" jnc move_the_rest_top_to_bottom_directly"); // if !carry (CF == 0) skip this move
+ // Move the next two bytes
+ asm(" movsw %ds:(%esi),%es:(%edi)"); // *((word *)dst)-- = *((word)src)-- if DF else *((word *)dst)++ = *((word)src)++
+ asm("move_the_rest_top_to_bottom_directly:");
+ asm(" subl $2,%esi"); // %esi-=2; (src-=2);
+ asm(" subl $2,%edi"); // %edi-=2; (dst-=2);
+ asm(" jmp move_the_rest"); // call last repnz movsl
+ // dst_ptr <= src_ptr
+ asm("move_from_bottom_to_top:");
+ asm(" cld"); // clear direction flag (increment esi and edi in movsb)
+ // Optimization : check for non-odd len (1,3,5,7...)
+ asm(" shr $1,%ecx"); // %ecx >> 1 , shifted bit -> CF
+ asm(" jnc move_two_bytes"); // if !carry (CF == 0) skip this move
+ // Move the first byte (non-odd)
+ asm(" movsb %ds:(%esi),%es:(%edi)"); // *dst-- = *src-- if DF else *dst++ = *src++
+ // Optimization : pass 2 , check for %2 and %3
+ asm("move_two_bytes:");
+ asm(" shr $1,%ecx"); // %ecx >> 1 , shifted bit -> CF
+ asm(" jnc move_the_rest"); // if !carry (CF == 0) skip this move
+ // Move the next two bytes
+ asm(" movsw %ds:(%esi),%es:(%edi)"); // *((word *)dst)-- = *((word)src)-- if DF else *((word *)dst)++ = *((word)src)++
+ // Main move remaining part
+ asm("move_the_rest:");
+ asm(" repnz; movsl %ds:(%esi),%es:(%edi)"); // loop moving 4 bytes at once (increment or decrement as above)
+ // Restore pointer registers
+ asm(" popl %edi"); // restore %edi
+ asm(" popl %esi"); // restore %esi
+ return dst_ptr; //asm(" movl 8(%ebp),%eax"); <-- gcc will put that (AFTER THE OPTIMISATION PASS!)
+ }
+
+ void *kvi_memmoveodd(void * dst_ptr,const void *src_ptr,int len)
+ {
+ __range_valid(dst_ptr);
+ __range_valid(src_ptr);
+ __range_valid(len >= 0);
+ // Save pointer registers
+ asm(" pushl %esi"); // save %esi
+ asm(" pushl %edi"); // save %edi
+ // Load arguments
+ asm(" movl 16(%ebp),%ecx"); // %ecx = len
+ asm(" movl 12(%ebp),%esi"); // %esi = src
+ asm(" movl 8(%ebp),%edi"); // %edi = dst
+ // Compare src and dest
+ asm(" cmpl %esi,%edi"); // %edi - %esi
+ asm(" jbe xmove_from_bottom_to_top"); // if(%edi < %esi) jump to move_from_bottom_to_top
+ // dst_ptr > src_ptr
+ asm(" addl %ecx,%esi"); // %esi += %ecx (src_ptr += len);
+ asm(" addl %ecx,%edi"); // %edi += %ecx (dst_ptr += len);
+ asm(" std"); // set direction flag (decrement esi and edi in movsb)
+ // start moving
+ asm(" shr $2,%ecx"); // %ecx >> 2 , last shifted bit -> CF
+ asm(" jnc xmove_the_rest_top_to_bottom_directly"); // if !carry (CF == 0) skip this move
+ // Move the next two bytes
+ asm(" subl $2,%esi"); // %esi-=2; (src_ptr-=2);
+ asm(" subl $2,%edi"); // %edi-=2; (dst_ptr-=2);
+ asm(" movsw %ds:(%esi),%es:(%edi)"); // *((word *)dst)-- = *((word)src)-- if DF else *((word *)dst)++ = *((word)src)++
+ asm(" subl $2,%esi"); // %esi-=2; (src_ptr-=2);
+ asm(" subl $2,%edi"); // %edi-=2; (dst_ptr-=2);
+ asm(" jmp xmove_the_rest");
+ asm("xmove_the_rest_top_to_bottom_directly:");
+ asm(" subl $4,%esi"); // %esi-=4; (src-=4);
+ asm(" subl $4,%edi"); // %edi-=4; (dst-=4);
+ asm(" jmp xmove_the_rest"); // call last repnz movsl
+ // dst_ptr <= src_ptr
+ asm("xmove_from_bottom_to_top:");
+ asm(" cld"); // clear direction flag (increment esi and edi in movsb)
+ // move it
+ asm(" shr $2,%ecx"); // %ecx >> 2 , last shifted bit -> CF
+ asm(" jnc xmove_the_rest"); // if !carry (CF == 0) skip this move
+ // Move the next two bytes
+ asm(" movsw %ds:(%esi),%es:(%edi)"); // *((word *)dst)-- = *((word)src)-- if DF else *((word *)dst)++ = *((word)src)++
+ // Main move remaining part
+ asm("xmove_the_rest:");
+ asm(" repnz; movsl %ds:(%esi),%es:(%edi)"); // loop moving 4 bytes at once (increment or decrement as above)
+ // Restore pointer registers
+ asm(" popl %edi"); // restore %edi
+ asm(" popl %esi"); // restore %esi
+ return dst_ptr; //asm(" movl 8(%ebp),%eax"); <-- gcc will put that (AFTER THE OPTIMISATION PASS!)
+ }
+
+ #else // ndef COMPILE_ix86_ASM
+
+
+
+ // The next 4 functions could be optimized with the & and shift technique
+ // used in the assembly implementations but the compilers usually
+ // will not translate the carry bit trick producing code
+ // that works slower on short block of memory (really near the average case)
+
+ // The trick would be:
+ //
+ // if(len & 1) // the length is even
+ // *dst-- = *src--; // move one byte
+ // len >> 1; // drop the last bit (thus divide by 2)
+ // if(len & 1) // the length is still even
+ // *((short *)dst)-- = *((short *)src)--; // move two bytes
+ // len >> 1; // again drop the last bit (thus divide by 2)
+ // while(len--)*((int *)dst)-- = *((int *)src)--; // move four bytes at a time
+ //
+ //
+
+ void *kvi_memmove(void *dst_ptr,const void *src_ptr,int len)
+ {
+ __range_valid(dst_ptr);
+ __range_valid(src_ptr);
+ __range_valid(len >= 0);
+ register char *dst;
+ register const char *src;
+ if(dst_ptr > src_ptr){
+ dst = (char *)dst_ptr + len - 1;
+ src = (const char *)src_ptr + len - 1;
+ while(len--)*dst-- = *src--;
+ } else { //it is valid even if dst_ptr == src_ptr
+ dst = (char *)dst_ptr;
+ src = (const char *)src_ptr;
+ while(len--)*dst++ = *src++;
+ }
+ return dst_ptr;
+ }
+
+ void *kvi_memmoveodd(void *dst_ptr,const void *src_ptr,int len)
+ {
+ __range_valid(dst_ptr);
+ __range_valid(src_ptr);
+ __range_valid(len >= 0);
+ __range_valid((len & 1) == 0);
+ register short *dst;
+ register const short *src;
+ if(dst_ptr > src_ptr){
+ dst = (short *) (((char *)dst_ptr) + len - 2);
+ src = (const short *) (((const char *)src_ptr) + len - 2);
+ while(len > 0)
+ {
+ *dst-- = *src--;
+ len -= 2;
+ }
+ } else { //it is valid even if dst_ptr == src_ptr
+ dst = (short *)dst_ptr;
+ src = (const short *)src_ptr;
+ while(len > 0)
+ {
+ *dst++ = *src++;
+ len -= 2;
+ }
+ }
+ return dst_ptr;
+ }
+
+ void kvi_fastmove(void *dst_ptr,const void *src_ptr,int len)
+ {
+ __range_valid(dst_ptr);
+ __range_valid(src_ptr);
+ __range_valid(len >= 0);
+ register const char *src = (const char *)src_ptr;
+ register char *dst = (char *)dst_ptr;
+ while(len--)*dst++ = *src++;
+ }
+
+ void kvi_fastmoveodd(void *dst_ptr,const void *src_ptr,int len)
+ {
+ __range_valid(dst_ptr);
+ __range_valid(src_ptr);
+ __range_valid(len >= 0);
+ __range_valid((len & 1) == 0);
+ register const short *src = (const short *)src_ptr;
+ register short *dst = (short *)dst_ptr;
+ while(len > 0){
+ *dst++ = *src++;
+ len -= 2;
+ }
+ }
+
+ #endif // !COMPILE_ix86_ASM
+
+ void kvi_memset(void *dst_ptr,char c,int len)
+ {
+ __range_valid(dst_ptr);
+ __range_valid(len >= 0);
+ register char *dst = (char *)dst_ptr;
+ while(len--)*dst++ = c;
+ }
+
+#endif // !COMPILE_WITH_SYSTEM_MEMMOVE
diff --git a/src/kvilib/core/kvi_memmove.h b/src/kvilib/core/kvi_memmove.h
new file mode 100644
index 00000000..d1319a41
--- /dev/null
+++ b/src/kvilib/core/kvi_memmove.h
@@ -0,0 +1,105 @@
+#ifndef _KVI_MEMMOVE_H_
+#define _KVI_MEMMOVE_H_
+
+//=============================================================================
+//
+// File : kvi_memmove.h
+// Creation date : Fri Mar 19 1999 03:15:21 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+
+#include "kvi_settings.h"
+
+//#undef COMPILE_WITH_SYSTEM_MEMMOVE
+//#define COMPILE_MMX_ASM
+
+#ifndef _KVI_MEMMOVE_CPP_
+
+ #ifdef COMPILE_WITH_SYSTEM_MEMMOVE
+
+ #include <string.h>
+
+ #define kvi_memmove memmove
+ #define kvi_memmoveodd memmove
+ #define kvi_memset memset
+ #define kvi_fastmove memcpy
+ #define kvi_fastmoveodd memcpy
+
+ #else
+
+ #ifdef COMPILE_ON_WINDOWS
+ #error "This stuff should be never compiled on Windows"
+ #endif
+
+ extern void *kvi_memmove(void *dst_ptr,const void *src_ptr,int len);
+ extern void *kvi_memmoveodd(void *dst_ptr,const void *src_ptr,int len);
+ extern void *kvi_memset(void *dst_ptr,char c,int len);
+ // In fastmove the src and dst may not overlap
+
+ #ifdef COMPILE_ix86_ASM
+
+ // WE WANT repnz; movsq\n"!!!
+
+ inline void kvi_fastmove(void * dst_ptr,const void *src_ptr,int len)
+ {
+ __asm__ __volatile__(
+ " cld\n"
+ " shr $1,%0\n"
+ " jnc 1f\n"
+ " movsb\n"
+ "1:\n"
+ " shr $1,%0\n"
+ " jnc 2f\n"
+ " movsw\n"
+ "2:\n"
+ " repnz; movsl\n"
+ : "=c" (len), "=&S" (src_ptr), "=&D" (dst_ptr)
+ : "0" (len), "1" (src_ptr), "2" (dst_ptr)
+ );
+ }
+
+ inline void kvi_fastmoveodd(void * dst_ptr,const void *src_ptr,int len)
+ {
+ __asm__ __volatile__(
+ " cld\n"
+ " shr $2,%0\n"
+ " jnc 1f\n"
+ " movsw\n"
+ "1:\n"
+ " repnz; movsl\n"
+ : "=c" (len), "=&S" (src_ptr), "=&D" (dst_ptr)
+ : "0" (len), "1" (src_ptr), "2" (dst_ptr)
+ );
+ }
+
+ #else // ! COMPILE_ix86_ASM
+
+ extern void kvi_fastmove(void *dst_ptr,const void *src_ptr,int len);
+ extern void kvi_fastmoveodd(void *dst_ptr,const void *src_ptr,int len);
+
+ #endif // !COMPILE_ix86_ASM
+
+ #endif // COMPILE_WITH_SYSTEM_MEMMOVE
+
+#endif // _KVI_MEMMOVE_CPP_
+
+#endif // !_KVI_MEMMOVE_H_
diff --git a/src/kvilib/core/kvi_pointerhashtable.h b/src/kvilib/core/kvi_pointerhashtable.h
new file mode 100644
index 00000000..9066c091
--- /dev/null
+++ b/src/kvilib/core/kvi_pointerhashtable.h
@@ -0,0 +1,999 @@
+#ifndef _KVI_POINTERHASHTABLE_H_
+#define _KVI_POINTERHASHTABLE_H_
+//=================================================================================================
+//
+// File : kvi_pointerhashtable.h
+// Creation date : Sat Jan 12 2008 04:53 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2008 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=================================================================================================
+
+#include "kvi_settings.h"
+#include "kvi_pointerlist.h"
+#include "kvi_string.h"
+#include "kvi_qstring.h"
+#include "kvi_malloc.h"
+#include "kvi_memmove.h"
+
+#include <ctype.h>
+
+///
+/// Hash functions for various data types
+///
+
+inline unsigned int kvi_hash_hash(const char * szKey,bool bCaseSensitive)
+{
+ unsigned int uResult = 0;
+ if(bCaseSensitive)
+ {
+ while(*szKey)
+ {
+ uResult += (unsigned char)(*(szKey));
+ szKey++;
+ }
+ } else {
+ while(*szKey)
+ {
+ uResult += (unsigned char)tolower(*(szKey));
+ szKey++;
+ }
+ }
+ return uResult;
+}
+
+inline bool kvi_hash_key_equal(const char * szKey1,const char * szKey2,bool bCaseSensitive)
+{
+ if(bCaseSensitive)
+ {
+ while(*szKey1 && *szKey2)
+ {
+ if(*szKey1 != *szKey2)
+ return false;
+ szKey1++;
+ szKey2++;
+ }
+ } else {
+ while(*szKey1 && *szKey2)
+ {
+ if(tolower(*szKey1) != tolower(*szKey2))
+ return false;
+ szKey1++;
+ szKey2++;
+ }
+ }
+ return true;
+}
+
+inline void kvi_hash_key_copy(const char * const &szFrom,const char * &szTo,bool bDeepCopy)
+{
+ if(bDeepCopy)
+ {
+ int len = kvi_strLen(szFrom);
+ char * dst = (char *)kvi_malloc(len+1);
+ kvi_fastmove(dst,szFrom,len+1);
+ szTo = dst;
+ } else {
+ szTo = szFrom; // we never modify it anyway
+ }
+}
+
+inline void kvi_hash_key_destroy(const char * &szKey,bool bDeepCopy)
+{
+ if(bDeepCopy)
+ kvi_free(szKey);
+}
+
+inline const char * & kvi_hash_key_default(const char **)
+{
+ static const char * static_null = NULL;
+ return static_null;
+}
+
+inline unsigned int kvi_hash_hash(const KviStr &szKey,bool bCaseSensitive)
+{
+ unsigned int uResult = 0;
+ const char * p = szKey.ptr();
+ if(bCaseSensitive)
+ {
+ while(*p)
+ {
+ uResult += *((const unsigned char *)p);
+ p++;
+ }
+ } else {
+ while(*p)
+ {
+ uResult += tolower(*((const unsigned char *)p));
+ p++;
+ }
+ }
+ return uResult;
+}
+
+inline bool kvi_hash_key_equal(const KviStr &szKey1,const KviStr &szKey2)
+{
+ return kvi_hash_key_equal(szKey1.ptr(),szKey2.ptr());
+}
+
+inline void kvi_hash_key_copy(const KviStr &szFrom,KviStr &szTo,bool)
+{
+ szTo = szFrom;
+}
+
+inline void kvi_hash_key_destroy(KviStr &szKey,bool)
+{
+}
+
+inline const KviStr & kvi_hash_key_default(KviStr *)
+{
+ return KviStr::emptyString();
+}
+
+inline unsigned int kvi_hash_hash(const int &iKey,bool)
+{
+ return (unsigned int)iKey;
+}
+
+inline bool kvi_hash_key_equal(const int &iKey1,const int &iKey2,bool)
+{
+ return iKey1 == iKey2;
+}
+
+inline void kvi_hash_key_copy(const int &iKeyFrom,int &iKeyTo,bool)
+{
+ iKeyTo = iKeyFrom;
+}
+
+inline void kvi_hash_key_destroy(int &iKey,bool)
+{
+}
+
+inline const int & kvi_hash_key_default(int *)
+{
+ static int static_default = 0;
+ return static_default;
+}
+
+inline unsigned int kvi_hash_hash(const unsigned short &iKey,bool)
+{
+ return (unsigned int)iKey;
+}
+
+inline bool kvi_hash_key_equal(const unsigned short &iKey1,const unsigned short &iKey2,bool)
+{
+ return iKey1 == iKey2;
+}
+
+inline void kvi_hash_key_copy(const unsigned short &iKeyFrom,unsigned short &iKeyTo,bool)
+{
+ iKeyTo = iKeyFrom;
+}
+
+inline void kvi_hash_key_destroy(unsigned short &iKey,bool)
+{
+}
+
+inline const unsigned short & kvi_hash_key_default(unsigned short *)
+{
+ static unsigned short static_default = 0;
+ return static_default;
+}
+
+
+inline unsigned int kvi_hash_hash(void * pKey,bool)
+{
+ unsigned char * pBytes = (unsigned char *)&(pKey);
+ unsigned char * pEnd = pBytes + sizeof(void *);
+ unsigned int uSum = 0;
+ while(pBytes < pEnd)
+ {
+ uSum += *pBytes;
+ pBytes++;
+ }
+ return uSum;
+}
+
+inline bool kvi_hash_key_equal(void *pKey1,void *pKey2,bool)
+{
+ return pKey1 == pKey2;
+}
+
+inline void kvi_hash_key_copy(void * const &pKeyFrom,void *&pKeyTo,bool)
+{
+ pKeyTo = pKeyFrom;
+}
+
+inline void kvi_hash_key_destroy(void *iKey,bool)
+{
+}
+
+inline void * & kvi_hash_key_default(void *)
+{
+ static void * static_default = NULL;
+ return static_default;
+}
+
+inline unsigned int kvi_hash_hash(const QString &szKey,bool bCaseSensitive)
+{
+ unsigned int uResult = 0;
+ const QChar * p = KviQString::nullTerminatedArray(szKey);
+ if(!p)return 0;
+ if(bCaseSensitive)
+ {
+ while(p->unicode())
+ {
+ uResult += p->unicode();
+ p++;
+ }
+ } else {
+ while(p->unicode())
+ {
+#ifdef COMPILE_USE_QT4
+ uResult += p->toLower().unicode();
+#else
+ uResult += p->lower().unicode();
+#endif
+ p++;
+ }
+ }
+ return uResult;
+}
+
+inline bool kvi_hash_key_equal(const QString &szKey1,const QString &szKey2,bool bCaseSensitive)
+{
+ if(bCaseSensitive)
+ return KviQString::equalCS(szKey1,szKey2);
+ return KviQString::equalCI(szKey1,szKey2);
+}
+
+inline void kvi_hash_key_copy(const QString &szFrom,QString &szTo,bool)
+{
+ szTo = szFrom;
+}
+
+inline void kvi_hash_key_destroy(QString &szKey,bool)
+{
+}
+
+inline const QString & kvi_hash_key_default(QString *)
+{
+ return KviQString::empty;
+}
+
+template<typename Key,typename T> class KviPointerHashTable;
+template<typename Key,typename T> class KviPointerHashTableIterator;
+
+template<typename Key,typename T> class KviPointerHashTableEntry
+{
+ friend class KviPointerHashTable<Key,T>;
+protected:
+ T * pData;
+ Key hKey;
+public:
+ Key & key(){ return hKey; };
+ T * data(){ return pData; };
+};
+
+///
+///
+/// \class KviPointerHashTable
+/// \brief A fast pointer hash table implementation
+///
+/// A very cool, very fast hash table implementation :P
+///
+/// To use this hash table you need to provide implementations
+/// for the following functions:
+///
+/// \verbatim
+///
+/// unsigned int kvi_hash_hash(const Key &hKey,bool bCaseSensitive);
+/// bool kvi_hash_key_equal(const Key &hKey1,const Key &hKey2,bool bCaseSensitive);
+/// void kvi_hash_key_copy(const Key &hKeyFrom,Key &hKeyTo,bool bDeepCopy);
+/// void kvi_hash_key_destroy(Key &hKey,bool bIsDeepCopy);
+/// const Key & kvi_hash_key_default(Key *);
+///
+/// \endverbatim
+///
+/// Implementations for the most likey Key data types are provided below.
+/// KviPointerHashTable will automagically work with const char *,QString,KviStr
+/// and integer types as keys.
+///
+/// For string Key types, the hash table may or may not be case sensitive.
+/// For other Key types the case sensitive flag has no meaning and will
+/// (hopefully) be optimized out by the compiler.
+///
+/// For pointer based keys the hash table may or may not mantain deep copies
+/// of Key data. For example, with char * keys, if deep copying is enabled
+/// then a private copy of the string data will be mantained. With deep
+/// copying disabled only char * pointers will be kept. For types
+/// that do not have meaning of deep copy the deep copying code will
+/// (hopefully) be optimized out by the compiler.
+///
+/// The hashtable mantains an array of KviPointerList based buckets.
+/// The number of buckets may be specified by the application user
+/// and does NOT need to be a prime number. Yet better to have it a power
+/// of two so the memory allocation routines will feel better and are
+/// less likely to waste space.
+///
+template<class Key,class T> class KviPointerHashTable
+{
+ friend class KviPointerHashTableIterator<Key,T>;
+protected:
+ KviPointerList<KviPointerHashTableEntry<Key,T> > ** m_pDataArray;
+ bool m_bAutoDelete;
+ unsigned int m_uSize;
+ unsigned int m_uCount;
+ bool m_bCaseSensitive;
+ bool m_bDeepCopyKeys;
+ unsigned int m_uIteratorIdx;
+public:
+ ///
+ /// Returns the item associated to the key hKey
+ /// or NULL if no such item exists in the hash table.
+ /// Places the hash table iterator at the position
+ /// of the item found.
+ ///
+ T * find(const Key & hKey)
+ {
+ m_uIteratorIdx = kvi_hash_hash(hKey,m_bCaseSensitive) % m_uSize;
+ if(!m_pDataArray[m_uIteratorIdx])return 0;
+ for(KviPointerHashTableEntry<Key,T> * e = m_pDataArray[m_uIteratorIdx]->first();e;e = m_pDataArray[m_uIteratorIdx]->next())
+ {
+ if(kvi_hash_key_equal(e->hKey,hKey,m_bCaseSensitive))return (T *)e->pData;
+ }
+ return 0;
+ }
+
+ ///
+ /// Returns the item associated to the key hKey
+ /// or NULL if no such item exists in the hash table.
+ /// Places the hash table iterator at the position
+ /// of the item found. This is an alias to find().
+ ///
+ T * operator[](const Key & hKey)
+ {
+ return find(hKey);
+ }
+
+ ///
+ /// Returns the number of items in this hash table
+ ///
+ unsigned int count() const
+ {
+ return m_uCount;
+ }
+
+ ///
+ /// Returns true if the hash table is empty
+ ///
+ bool isEmpty() const
+ {
+ return m_uCount == 0;
+ }
+
+ ///
+ /// Inserts the item pData at the position specified by the key hKey.
+ /// Replaces any previous item with the same key
+ /// The replaced item is deleted if autodelete is enabled.
+ /// The hash table iterator is placed at the newly inserted item.
+ ///
+ void insert(const Key & hKey,T * pData)
+ {
+ if(!pData)return;
+ unsigned int uEntry = kvi_hash_hash(hKey,m_bCaseSensitive) % m_uSize;
+ if(!m_pDataArray[uEntry])m_pDataArray[uEntry] = new KviPointerList<KviPointerHashTableEntry<Key,T> >(true);
+ for(KviPointerHashTableEntry<Key,T> * e = m_pDataArray[uEntry]->first();e;e = m_pDataArray[uEntry]->next())
+ {
+ if(kvi_hash_key_equal(e->hKey,hKey,m_bCaseSensitive))
+ {
+ if(!m_bCaseSensitive)
+ {
+ // must change the key too
+ kvi_hash_key_destroy(e->hKey,m_bDeepCopyKeys);
+ kvi_hash_key_copy(hKey,e->hKey,m_bDeepCopyKeys);
+ }
+ if(m_bAutoDelete)delete e->pData;
+ e->pData = pData;
+ return;
+ }
+ }
+ KviPointerHashTableEntry<Key,T> * n = new KviPointerHashTableEntry<Key,T>;
+ kvi_hash_key_copy(hKey,n->hKey,m_bDeepCopyKeys);
+ n->pData = pData;
+ m_pDataArray[uEntry]->append(n);
+ m_uCount++;
+ }
+
+ ///
+ /// Inserts the item pData at the position specified by the key hKey.
+ /// Replaces any previous item with the same key
+ /// The replaced item is deleted if autodelete is enabled.
+ /// The hash table iterator is placed at the newly inserted item.
+ /// This is just an alias to insert() with a different name.
+ ///
+ void replace(const Key & hKey,T * pData)
+ {
+ insert(hKey,pData);
+ }
+
+ ///
+ /// Removes the item pointer associated to the key hKey, if such an item
+ /// exists in the hash table. The item is deleted if autodeletion
+ /// is enabled. Returns true if the item was found and removed and false if it wasn't found.
+ /// Invalidates the hash table iterator.
+ ///
+ bool remove(const Key & hKey)
+ {
+ unsigned int uEntry = kvi_hash_hash(hKey,m_bCaseSensitive) % m_uSize;
+ if(!m_pDataArray[uEntry])return false;
+ for(KviPointerHashTableEntry<Key,T> * e = m_pDataArray[uEntry]->first();e;e = m_pDataArray[uEntry]->next())
+ {
+ if(kvi_hash_key_equal(e->hKey,hKey,m_bCaseSensitive))
+ {
+ kvi_hash_key_destroy(e->hKey,m_bDeepCopyKeys);
+ if(m_bAutoDelete)delete ((T *)(e->pData));
+ m_pDataArray[uEntry]->removeRef(e);
+ if(m_pDataArray[uEntry]->isEmpty())
+ {
+ delete m_pDataArray[uEntry];
+ m_pDataArray[uEntry] = 0;
+ }
+ m_uCount--;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ ///
+ /// Removes the first occurence of the item pointer pRef. The item is deleted if autodeletion
+ /// is enabled. Returns true if the pointer was found and false otherwise
+ /// Invalidates the hash table iterator.
+ ///
+ bool removeRef(const T * pRef)
+ {
+ for(unsigned int i=0;i<m_uSize;i++)
+ {
+ if(m_pDataArray[i])
+ {
+ for(KviPointerHashTableEntry<Key,T> * e = m_pDataArray[i]->first();e;e = m_pDataArray[i]->next())
+ {
+ if(e->pData == pRef)
+ {
+ kvi_hash_key_destroy(e->hKey,m_bDeepCopyKeys);
+ if(m_bAutoDelete)delete ((T *)(e->pData));
+ m_pDataArray[i]->removeRef(e);
+ if(m_pDataArray[i]->isEmpty())
+ {
+ delete m_pDataArray[i];
+ m_pDataArray[i] = 0;
+ }
+ m_uCount--;
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ ///
+ /// Removes all the items from the hash table.
+ /// The items are deleted if autodeletion is enabled.
+ /// Invalidates the hash table iterator.
+ ///
+ void clear()
+ {
+ for(unsigned int i=0;i<m_uSize;i++)
+ {
+ if(m_pDataArray[i])
+ {
+ for(KviPointerHashTableEntry<Key,T> * e = m_pDataArray[i]->first();e;e = m_pDataArray[i]->next())
+ {
+ kvi_hash_key_destroy(e->hKey,m_bDeepCopyKeys);
+ if(m_bAutoDelete)
+ delete ((T *)(e->pData));
+ }
+ delete m_pDataArray[i];
+ m_pDataArray[i] = 0;
+ }
+ }
+ m_uCount = 0;
+ }
+
+ ///
+ /// Searches for the item pointer pRef and returns
+ /// it's hash table entry, if found, and NULL otherwise.
+ /// The hash table iterator is placed at the item found.
+ ///
+ KviPointerHashTableEntry<Key,T> * findRef(const T * pRef)
+ {
+ for(m_uIteratorIdx = 0;m_uIteratorIdx<m_uSize;m_uIteratorIdx++)
+ {
+ if(m_pDataArray[m_uIteratorIdx])
+ {
+ for(KviPointerHashTableEntry<Key,T> * e = m_pDataArray[m_uIteratorIdx]->first();e;e = m_pDataArray[m_uIteratorIdx]->next())
+ {
+ if(e->pData == pRef)return e;
+ }
+ }
+ }
+ return 0;
+ }
+
+ ///
+ /// Returns the entry pointed by the hash table iterator.
+ /// This function must be preceeded by a call to firstEntry(), first()
+ /// or findRef().
+ ///
+ KviPointerHashTableEntry<Key,T> * currentEntry()
+ {
+ if(m_uIteratorIdx >= m_uSize)return 0;
+ if(m_pDataArray[m_uIteratorIdx])return m_pDataArray[m_uIteratorIdx]->current();
+ return 0;
+ }
+
+ ///
+ /// Places the hash table iterator at the first entry
+ /// and returns it.
+ ///
+ KviPointerHashTableEntry<Key,T> * firstEntry()
+ {
+ m_uIteratorIdx = 0;
+ while(m_uIteratorIdx < m_uSize && (!m_pDataArray[m_uIteratorIdx]))
+ {
+ m_uIteratorIdx++;
+ }
+ if(m_uIteratorIdx == m_uSize)return 0;
+ return m_pDataArray[m_uIteratorIdx]->first();
+ }
+
+ ///
+ /// Places the hash table iterator at the next entry
+ /// and returns it.
+ /// This function must be preceeded by a call to firstEntry(), first()
+ /// or findRef().
+ ///
+ KviPointerHashTableEntry<Key,T> * nextEntry()
+ {
+ if(m_uIteratorIdx >= m_uSize)return 0;
+
+ if(m_uIteratorIdx < m_uSize)
+ {
+ KviPointerHashTableEntry<Key,T> * t = m_pDataArray[m_uIteratorIdx]->next();
+ if(t)return t;
+ }
+
+ m_uIteratorIdx++;
+
+ while(m_uIteratorIdx < m_uSize && (!m_pDataArray[m_uIteratorIdx]))
+ {
+ m_uIteratorIdx++;
+ }
+
+ if(m_uIteratorIdx == m_uSize)return 0;
+
+ return m_pDataArray[m_uIteratorIdx]->first();
+
+ }
+
+ ///
+ /// Returns the data value pointer pointed by the hash table iterator.
+ /// This function must be preceeded by a call to firstEntry(), first()
+ /// or findRef().
+ ///
+ T * current()
+ {
+ if(m_uIteratorIdx >= m_uSize)return 0;
+ if(m_pDataArray[m_uIteratorIdx])
+ {
+ KviPointerHashTableEntry<Key,T> * e = m_pDataArray[m_uIteratorIdx]->current();
+ if(!e)return 0;
+ return e->data();
+ }
+ return 0;
+ }
+
+ ///
+ /// Returns the key pointed by the hash table iterator.
+ /// This function must be preceeded by a call to firstEntry(), first()
+ /// or findRef().
+ ///
+ const Key & currentKey()
+ {
+ if(m_uIteratorIdx >= m_uSize)return kvi_hash_key_default(((Key *)NULL));
+ if(m_pDataArray[m_uIteratorIdx])
+ {
+ KviPointerHashTableEntry<Key,T> * e = m_pDataArray[m_uIteratorIdx]->current();
+ if(!e)return kvi_hash_key_default(((Key *)NULL));
+ return e->key();
+ }
+ return kvi_hash_key_default(((Key *)NULL));
+ }
+
+ ///
+ /// Places the hash table iterator at the first entry
+ /// and returns the associated data value pointer.
+ ///
+ T * first()
+ {
+ m_uIteratorIdx = 0;
+ while(m_uIteratorIdx < m_uSize && (!m_pDataArray[m_uIteratorIdx]))
+ {
+ m_uIteratorIdx++;
+ }
+ if(m_uIteratorIdx == m_uSize)return 0;
+ KviPointerHashTableEntry<Key,T> * e = m_pDataArray[m_uIteratorIdx]->first();
+ if(!e)return 0;
+ return e->data();
+ }
+
+ ///
+ /// Places the hash table iterator at the next entry
+ /// and returns the associated data value pointer.
+ /// This function must be preceeded by a call to firstEntry(), first()
+ /// or findRef().
+ ///
+ T * next()
+ {
+ if(m_uIteratorIdx >= m_uSize)return 0;
+
+ if(m_uIteratorIdx < m_uSize)
+ {
+ KviPointerHashTableEntry<Key,T> * t = m_pDataArray[m_uIteratorIdx]->next();
+ if(t)
+ {
+ return t->data();
+ }
+ }
+
+ m_uIteratorIdx++;
+
+ while(m_uIteratorIdx < m_uSize && (!m_pDataArray[m_uIteratorIdx]))
+ {
+ m_uIteratorIdx++;
+ }
+
+ if(m_uIteratorIdx == m_uSize)return 0;
+
+ KviPointerHashTableEntry<Key,T> * e = m_pDataArray[m_uIteratorIdx]->first();
+ if(!e)return 0;
+ return e->data();
+ }
+
+ ///
+ /// Removes all items in the hash table and then
+ /// makes a complete shallow copy of the data contained in t.
+ /// The removed items are deleted if autodeletion is enabled.
+ /// The hash table iterator is invalidated.
+ /// Does not change autodelete flag: make sure you not delete the items twice :)
+ ///
+ void copyFrom(KviPointerHashTable<Key,T> &t)
+ {
+ clear();
+ for(KviPointerHashTableEntry<Key,T> * e = t.firstEntry();e;e = t.nextEntry())
+ insert(e->key(),e->data());
+ }
+
+ ///
+ /// Inserts a complete shallow copy of the data contained in t.
+ /// The hash table iterator is invalidated.
+ ///
+ void insert(KviPointerHashTable<Key,T> &t)
+ {
+ for(KviPointerHashTableEntry<Key,T> * e = t.firstEntry();e;e = t.nextEntry())
+ insert(e->key(),e->data());
+ }
+
+ ///
+ /// Enables or disabled the autodeletion feature.
+ /// Items are deleted upon removal when the feature is enabled.
+ ///
+ void setAutoDelete(bool bAutoDelete)
+ {
+ m_bAutoDelete = bAutoDelete;
+ }
+
+ ///
+ /// Creates an empty hash table.
+ /// Automatic deletion is enabled.
+ ///
+ /// \param uSize The number of hash buckets: does NOT necesairly need to be prime
+ /// \param bCaseSensitive Are the key comparisons case sensitive ?
+ /// \param Do we need to mantain deep copies of keys ?
+ ///
+ KviPointerHashTable(unsigned int uSize = 32,bool bCaseSensitive = true,bool bDeepCopyKeys = true)
+ {
+ m_uCount = 0;
+ m_bCaseSensitive = bCaseSensitive;
+ m_bAutoDelete = true;
+ m_bDeepCopyKeys = bDeepCopyKeys;
+ m_uSize = uSize > 0 ? uSize : 32;
+ m_pDataArray = new KviPointerList<KviPointerHashTableEntry<Key,T> > *[m_uSize];
+ for(unsigned int i=0;i<m_uSize;i++)m_pDataArray[i] = NULL;
+ }
+
+ ///
+ /// First creates an empty hash table
+ /// and then inserts a copy of all the item pointers present in t.
+ /// The autodelete feature is automatically disabled (take care!).
+ ///
+ KviPointerHashTable(KviPointerHashTable<Key,T> &t)
+ {
+ m_uCount = 0;
+ m_bAutoDelete = false;
+ m_bCaseSensitive = t.m_bCaseSensitive;
+ m_bDeepCopyKeys = t.m_bDeepCopyKeys;
+ m_uSize = t.m_uSize;
+ m_pDataArray = new KviPointerList<KviPointerHashTableEntry<Key,T> > *[m_uSize];
+ for(unsigned int i=0;i<m_uSize;i++)m_pDataArray[i] = NULL;
+ copyFrom(t);
+ }
+
+ ///
+ /// Destroys the hash table and all the items contained within.
+ /// Items are deleted if autodeletion is enabled.
+ ///
+ ~KviPointerHashTable()
+ {
+ clear();
+ delete [] m_pDataArray;
+ }
+};
+
+template<typename Key,typename T> class KviPointerHashTableIterator
+{
+protected:
+ const KviPointerHashTable<Key,T> * m_pHashTable;
+ unsigned int m_uEntryIndex;
+ KviPointerListIterator<KviPointerHashTableEntry<Key,T> > * m_pIterator;
+public:
+ ///
+ /// Creates an iterator copy.
+ /// The new iterator points exactly to the item pointed by src.
+ ///
+ void operator = (const KviPointerHashTableIterator<Key,T> &src)
+ {
+ m_pHashTable = src.m_pHashTable;
+ m_uEntryIndex = src.m_uEntryIndex;
+ if(src.m_pIterator)
+ m_pIterator = new KviPointerListIterator<KviPointerHashTableEntry<Key,T> >(*(src.m_pIterator));
+ else
+ m_pIterator = NULL;
+ }
+
+ ///
+ /// Moves the iterator to the first element of the hash table.
+ /// Returns true in case of success or false if the hash table is empty.
+ ///
+ bool moveFirst()
+ {
+ if(m_pIterator)
+ {
+ delete m_pIterator;
+ m_pIterator = NULL;
+ }
+
+ m_uEntryIndex = 0;
+ while((m_uEntryIndex < m_pHashTable->m_uSize) && (!(m_pHashTable->m_pDataArray[m_uEntryIndex])))
+ {
+ m_uEntryIndex++;
+ }
+
+ if(m_uEntryIndex == m_pHashTable->m_uSize)
+ return false;
+
+ m_pIterator = new KviPointerListIterator<KviPointerHashTableEntry<Key,T> >(*(m_pHashTable->m_pDataArray[m_uEntryIndex]));
+ bool bRet = m_pIterator->moveFirst();
+ if(!bRet)
+ {
+ delete m_pIterator;
+ m_pIterator = NULL;
+ }
+ return bRet;
+ }
+
+ ///
+ /// Moves the iterator to the last element of the hash table.
+ /// Returns true in case of success or false if the hash table is empty.
+ ///
+ bool moveLast()
+ {
+ if(m_pIterator)
+ {
+ delete m_pIterator;
+ m_pIterator = NULL;
+ }
+
+ m_uEntryIndex = m_pHashTable->m_uSize;
+ while(m_uEntryIndex > 0)
+ {
+ m_uEntryIndex--;
+ if(m_pHashTable->m_pDataArray[m_uEntryIndex])
+ {
+ m_pIterator = new KviPointerListIterator<KviPointerHashTableEntry<Key,T> >(*(m_pHashTable->m_pDataArray[m_uEntryIndex]));
+ bool bRet = m_pIterator->moveLast();
+ if(!bRet)
+ {
+ delete m_pIterator;
+ m_pIterator = NULL;
+ }
+ return bRet;
+ }
+ }
+ return false;
+ }
+
+ ///
+ /// Moves the iterator to the next element of the hash table.
+ /// The iterator must be actually valid for this function to work.
+ /// Returns true in case of success or false if there is no next item.
+ ///
+ bool moveNext()
+ {
+ if(!m_pIterator)
+ return false;
+ if(m_pIterator->moveNext())
+ return true;
+ if(m_pIterator)
+ {
+ delete m_pIterator;
+ m_pIterator = NULL;
+ }
+ m_uEntryIndex++;
+ while((m_uEntryIndex < m_pHashTable->m_uSize) && (!(m_pHashTable->m_pDataArray[m_uEntryIndex])))
+ {
+ m_uEntryIndex++;
+ }
+ if(m_uEntryIndex == m_pHashTable->m_uSize)
+ return false;
+ m_pIterator = new KviPointerListIterator<KviPointerHashTableEntry<Key,T> >(*(m_pHashTable->m_pDataArray[m_uEntryIndex]));
+ bool bRet = m_pIterator->moveFirst();
+ if(!bRet)
+ {
+ delete m_pIterator;
+ m_pIterator = NULL;
+ }
+ return bRet;
+ }
+
+ ///
+ /// Moves the iterator to the next element of the hash table.
+ /// The iterator must be actually valid for this function to work.
+ /// Returns true in case of success or false if there is no next item.
+ /// This is just an alias to moveNext().
+ ///
+ bool operator ++()
+ {
+ return moveNext();
+ }
+
+ ///
+ /// Moves the iterator to the previous element of the hash table.
+ /// The iterator must be actually valid for this function to work.
+ /// Returns true in case of success or false if there is no previous item.
+ ///
+ bool movePrev()
+ {
+ if(!m_pIterator)
+ return false;
+ if(m_pIterator->movePrev())
+ return true;
+ if(m_pIterator)
+ {
+ delete m_pIterator;
+ m_pIterator = NULL;
+ }
+ if(m_uEntryIndex >= m_pHashTable->m_uSize)
+ return false;
+ while(m_uEntryIndex > 0)
+ {
+ m_uEntryIndex--;
+ if(m_pHashTable->m_pDataArray[m_uEntryIndex])
+ {
+ m_pIterator = new KviPointerListIterator<KviPointerHashTableEntry<Key,T> >(*(m_pHashTable->m_pDataArray[m_uEntryIndex]));
+ bool bRet = m_pIterator->moveLast();
+ if(!bRet)
+ {
+ delete m_pIterator;
+ m_pIterator = NULL;
+ }
+ return bRet;
+ }
+ }
+ return false;
+ }
+
+
+ ///
+ /// Moves the iterator to the previous element of the hash table.
+ /// The iterator must be actually valid for this function to work.
+ /// Returns true in case of success or false if there is no previous item.
+ /// This is just an alias to movePrev() with a different name.
+ ///
+ bool operator --()
+ {
+ return movePrev();
+ }
+
+ ///
+ /// Returs the value pointed by the iterator
+ /// or a default constructed value if the iterator is not valid.
+ /// This is an alias to operator *() with just a different name.
+ ///
+ T * current() const
+ {
+ return m_pIterator ? m_pIterator->current()->data() : NULL;
+ }
+
+ ///
+ /// Returs the value pointed by the iterator
+ /// or a default constructed value if the iterator is not valid.
+ /// This is an alias to current() with just a different name.
+ ///
+ T * operator *() const
+ {
+ return m_pIterator ? m_pIterator->current()->data() : NULL;
+ }
+
+ ///
+ /// Returs the key pointed by the iterator
+ /// or a default constructed key if the iterator is not valid.
+ ///
+ const Key & currentKey() const
+ {
+ return m_pIterator ? m_pIterator->current()->key() : kvi_hash_key_default(((Key *)NULL));
+ }
+
+ ///
+ /// Moves the iterator to the first element of the hash table.
+ /// Returns the first item found or NULL if the hash table is empty.
+ ///
+ T * toFirst()
+ {
+ if(!moveFirst())
+ return NULL;
+ return current();
+ }
+public:
+ ///
+ /// Creates an iterator pointing to the first item in the hash table, if any.
+ ///
+ KviPointerHashTableIterator(const KviPointerHashTable<Key,T> &hTable)
+ {
+ m_pHashTable = &hTable;
+ m_uEntryIndex = 0;
+ m_pIterator = NULL;
+ moveFirst();
+ }
+
+ ///
+ /// Destroys the iterator
+ ///
+ ~KviPointerHashTableIterator()
+ {
+ if(m_pIterator)
+ delete m_pIterator;
+ }
+};
+
+
+
+
+#endif //_KVI_POINTERHASHTABLE_H_
diff --git a/src/kvilib/core/kvi_pointerlist.h b/src/kvilib/core/kvi_pointerlist.h
new file mode 100644
index 00000000..381780c8
--- /dev/null
+++ b/src/kvilib/core/kvi_pointerlist.h
@@ -0,0 +1,1069 @@
+#ifndef _KVI_POINTERLIST_H_
+#define _KVI_POINTERLIST_H_
+//=================================================================================================
+//
+// File : kvi_pointerlist.h
+// Creation date : Tue Jul 6 1999 14:52:20 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=================================================================================================
+//=============================================================================
+//
+// C++ Template based double linked pointer list class
+// Original ss_list.h Created on 10 Dec 2001
+// Copyright (C) 2001-2007 Szymon Stefanek (pragma at kvirc dot net)
+// Added to KVIrc on 02 Jan 2008.
+//
+//=============================================================================
+
+// Qt changes the collection classes too much and too frequently.
+// I think we need to be independent of that to the maximum degree possible.
+// That's why we have our own fast pointer list class.
+// This does not depend on Qt AT ALL and has an interface similar
+// to the Qt<=3.x series. The pointer lists with the autodelete
+// feature was great and I don't completly understand why they have
+// been removed from Qt4 in favor of the value based non-autodeleting
+// lists... anyway: here we go :)
+
+#include "kvi_settings.h"
+
+template<typename T> class KviPointerList;
+template<typename T> class KviPointerListIterator;
+
+#ifndef NULL
+ #define NULL 0
+#endif
+
+///
+/// \internal
+///
+class KviPointerListNode
+{
+public:
+ KviPointerListNode * m_pPrev;
+ void * m_pData;
+ KviPointerListNode * m_pNext;
+};
+
+///
+/// \class KviPointerListIterator
+/// \brief A fast KviPointerList iterator.
+///
+/// This class allows traversing the list sequentially.
+/// Multilpe iterators can traverse the list at the same time.
+///
+/// Iteration example 1:
+///
+/// \verbatim
+/// KviPointerListIterator<T> it(list);
+/// for(bool b = it.moveFirst();b;b = it.moveNext())
+/// {
+/// T * pData = it.data();
+/// doSomethingWithData(pData);
+/// }
+/// \endverbatim
+///
+/// Iteration example 2:
+///
+/// \verbatim
+/// KviPointerListIterator<T> it(list);
+/// if(it.moveFirst())
+/// {
+/// do {
+/// T * pData = it.data();
+/// doSomethingWithData(pData);
+/// } while(it.moveNext());
+/// }
+/// \endverbatim
+///
+/// Iteration example 3:
+///
+/// \verbatim
+/// KviPointerListIterator<T> it(list.iteratorAt(10));
+/// if(it.isValid())
+/// {
+/// do {
+/// T * pData = it.data();
+/// doSomethingWithData(pData);
+/// while(it.movePrev());
+/// }
+/// \endverbatim
+///
+/// Please note that you must NOT remove any item from
+/// the list when using the iterators. An iterator pointing
+/// to a removed item will crash your application if you use it.
+/// The following code will NOT work (and crash):
+///
+/// \verbatim
+/// KviPointerList<T> l;
+/// l.append(new KviStr("x"));
+/// l.append(new KviStr("y"));
+/// KviPointerListIterator<T> it(l);
+/// it.moveFirst();
+/// l.removeFirst();
+/// KviStr * tmp = it.data(); <-- this will crash
+/// \endverbatim
+///
+/// In the rare cases in that you need to remove items
+/// while traversing the list you should put them
+/// in a temporary list and remove them after the iteration.
+///
+/// I've choosen this way because usually you don't modify
+/// the list while traversing it and a fix for this
+/// would add a constant overhead to several list operation.
+/// You just must take care of it yourself.
+///
+/// \warning This class is not thread safe by itself.
+///
+template<typename T> class KviPointerListIterator
+{
+protected:
+ KviPointerList<T> * m_pList;
+ KviPointerListNode * m_pNode;
+public:
+ ///
+ /// Creates an iterator copy.
+ /// The new iterator points exactly to the item pointed by src.
+ ///
+ KviPointerListIterator(const KviPointerListIterator<T> &src)
+ {
+ m_pList = src.m_pList;
+ m_pNode = src.m_pNode;
+ }
+
+ ///
+ /// Creates an iterator for the list l.
+ /// The iterator points to the first list item, if any.
+ ///
+ KviPointerListIterator(KviPointerList<T> &l)
+ {
+ m_pList = (KviPointerList<T> *)&l;
+ m_pNode = m_pList->m_pHead;
+ }
+
+ ///
+ /// Creates an iterator for the list l.
+ /// The iterator points to the specified list node.
+ ///
+ KviPointerListIterator(KviPointerList<T> &l,KviPointerListNode * pNode)
+ {
+ m_pList = (KviPointerList<T> *)&l;
+ m_pNode = pNode;
+ }
+
+ ///
+ /// Creates an iterator copy.
+ /// The new iterator points exactly to the item pointed by src.
+ ///
+ void operator = (const KviPointerListIterator<T> &src)
+ {
+ m_pList = src.m_pList;
+ m_pNode = src.m_pNode;
+ }
+public:
+ ///
+ /// Moves the iterator to the first element of the list.
+ /// Returns true in case of success or false if the list is empty.
+ ///
+ bool moveFirst()
+ {
+ m_pNode = m_pList->m_pHead;
+ return m_pNode != NULL;
+ }
+
+ ///
+ /// Moves the iterator to the last element of the list.
+ /// Returns true in case of success or false if the list is empty.
+ ///
+ bool moveLast()
+ {
+ m_pNode = m_pList->m_pTail;
+ return m_pNode != NULL;
+ }
+
+ ///
+ /// Moves the iterator to the next element of the list.
+ /// The iterator must be actually valid for this function to work.
+ /// Returns true in case of success or false if there is no next item.
+ ///
+ bool moveNext()
+ {
+ if(!m_pNode)return false;
+ m_pNode = m_pNode->m_pNext;
+ return m_pNode != NULL;
+ }
+
+ ///
+ /// Moves the iterator to the next element of the list.
+ /// The iterator must be actually valid for this operator to work.
+ /// Returns true in case of success or false if there is no next item.
+ /// This is just a convenient alias to moveNext().
+ ///
+ bool operator ++()
+ {
+ if(!m_pNode)return false;
+ m_pNode = m_pNode->m_pNext;
+ return m_pNode != NULL;
+ }
+
+ ///
+ /// Moves the iterator to the previous element of the list.
+ /// The iterator must be actually valid for this function to work.
+ /// Returns true in case of success or false if there is no previous item.
+ ///
+ bool movePrev()
+ {
+ if(!m_pNode)return false;
+ m_pNode = m_pNode->m_pPrev;
+ return m_pNode != NULL;
+ }
+
+ ///
+ /// Moves the iterator to the previous element of the list.
+ /// The iterator must be actually valid for this operator to work.
+ /// Returns true in case of success or false if there is no previous item.
+ /// This is just a convenient alias to movePrev().
+ ///
+ bool operator --()
+ {
+ if(!m_pNode)return false;
+ m_pNode = m_pNode->m_pPrev;
+ return m_pNode != NULL;
+ }
+
+ ///
+ /// Returs the value pointed by the iterator
+ /// or NULL if the iterator is not valid.
+ ///
+ T * current()
+ {
+ return m_pNode ? (T *)(m_pNode->m_pData) : NULL;
+ }
+
+ ///
+ /// Returs the value pointed by the iterator
+ /// or NULL if the iterator is not valid.
+ /// This is just an alias to current().
+ ///
+ T * operator *()
+ {
+ return m_pNode ? (T *)(m_pNode->m_pData) : NULL;
+ }
+
+ ///
+ /// Returns true if this iterator points to a valid
+ /// element of the list and false otherwise.
+ ///
+ bool isValid()
+ {
+ return m_pNode != NULL;
+ }
+};
+
+///
+/// \class KviPointerList
+/// \brief A template double linked list of pointers.
+///
+/// The main advantage of this type of list is speed.
+/// Insertion of pointers is very fast when compared
+/// to the typical "copy constructor" call used
+/// in the "plain type" template list implementations.
+///
+/// Iterating over pointers is also very fast and this
+/// class contains an internal iterator that allows to
+/// write loops in a compact and clean way.
+/// See the first(), next(), current() and findRef()
+/// functions for the description of this feature.
+///
+/// There is also a non-const external iterator
+/// that you can use to traverse the list concurrently.
+/// There is no const iterator (and no const access methods)
+/// since the list provides the autoDelete() method
+/// which vould implicitly violate constness.
+/// If you have to deal with const objects then
+/// you need to use a QList instead.
+///
+/// Your objects also do not need to support copy constructors
+/// or >= operators. This class will work fine without them
+/// as opposed to a plain QList.
+///
+/// This class also supports automatic deletion of the inseted items.
+/// See the setAutoDelete() and autoDelete() members for the
+/// description of the feature.
+///
+/// Typcal usage:
+///
+/// \verbatim
+/// KviPointerList<MyClass> list();
+/// list.append(new MyClass());
+/// list.append(new MyClass());
+/// ...
+/// for(MyClass * c = list.first();c;c = list.next())doSomethingWith(c);
+/// delete list; // autodelete is set to true in the constructor
+/// \endverbatim
+///
+/// \warning This class is absolutely NOT thread safe. You must
+/// protect concurrent access from multiple threads by
+/// using an external synchronization tool (such as KviMutex).
+///
+template<typename T> class KviPointerList
+{
+ friend class KviPointerListIterator<T>;
+protected:
+ bool m_bAutoDelete; //< do we automatically delete items when they are removed ?
+
+ KviPointerListNode * m_pHead; //< our list head pointer (NULL if there are no items in the list)
+ KviPointerListNode * m_pTail; //< our list tail
+ KviPointerListNode * m_pAux; //< our iteration pointer
+
+ unsigned int m_uCount; //< the count of items in the list
+protected:
+ ///
+ /// \internal
+ ///
+ /// inserts the item d before the item ref or at the beginning
+ /// if ref is not found in the list
+ /// also sets the current iteration pointer to the newly inserted item
+ ///
+ void insertBeforeSafe(KviPointerListNode * ref,const T * d)
+ {
+ m_pAux = ref;
+ KviPointerListNode * n = new KviPointerListNode;
+ n->m_pPrev = m_pAux->m_pPrev;
+ n->m_pNext = m_pAux;
+ if(m_pAux->m_pPrev)
+ {
+ m_pAux->m_pPrev->m_pNext = n;
+ } else {
+ m_pHead = n;
+ }
+ m_pAux->m_pPrev = n;
+ n->m_pData = (void *)d;
+ m_uCount++;
+ }
+
+ ///
+ /// \internal
+ ///
+ /// Grabs the first element from the list src
+ /// and puts it as the first element of this list.
+ ///
+ void grabFirstAndPrepend(KviPointerList<T> * src)
+ {
+ KviPointerListNode * pNewHead = src->m_pHead;
+ if(!pNewHead)
+ return;
+
+ if(pNewHead->m_pNext)
+ {
+ src->m_pHead = pNewHead->m_pNext;
+ src->m_pHead->m_pPrev = NULL;
+ } else {
+ src->m_pHead = NULL;
+ src->m_pTail = NULL;
+ }
+
+ if(m_pHead)
+ {
+ m_pHead->m_pPrev = pNewHead;
+ pNewHead->m_pNext = m_pHead;
+ m_pHead = pNewHead;
+ } else {
+ m_pHead = pNewHead;
+ m_pTail = pNewHead;
+ m_pHead->m_pNext = NULL;
+ }
+ m_uCount++;
+ src->m_uCount--;
+ }
+
+ ///
+ /// \internal
+ ///
+ /// Removes the current iteration item assuming that it is valid.
+ ///
+ void removeCurrentSafe()
+ {
+ if(m_pAux->m_pPrev)
+ m_pAux->m_pPrev->m_pNext = m_pAux->m_pNext;
+ else
+ m_pHead = m_pAux->m_pNext;
+ if(m_pAux->m_pNext)
+ m_pAux->m_pNext->m_pPrev = m_pAux->m_pPrev;
+ else
+ m_pTail = m_pAux->m_pPrev;
+ const T * pAuxData = (const T *)(m_pAux->m_pData);
+ delete m_pAux;
+ m_pAux = NULL;
+ m_uCount--;
+ if(m_bAutoDelete)
+ delete pAuxData; // this can cause recursion, so do it at the end
+ }
+
+public:
+ ///
+ /// Inserts the list src inside this list
+ /// by respecting the sort order.
+ /// The src list elements are removed.
+ ///
+ void merge(KviPointerList<T> * src)
+ {
+ m_pAux = m_pHead;
+ KviPointerListNode * n = src->m_pHead;
+ m_uCount += src->m_uCount;
+ while(m_pAux && n)
+ {
+ if(kvi_compare((const T *)(m_pAux->m_pData),(const T *)(n->m_pData)) > 0)
+ {
+ // our element is greater, n->m_pData goes first
+ KviPointerListNode * pNext = n->m_pNext;
+ n->m_pPrev = m_pAux->m_pPrev; // his prev becomes
+ n->m_pNext = m_pAux;
+ if(m_pAux->m_pPrev)
+ m_pAux->m_pPrev->m_pNext = n;
+ else
+ m_pHead = n;
+ m_pAux->m_pPrev = n;
+ n = pNext;
+ } else {
+ // that element is greater
+ m_pAux = m_pAux->m_pNext;
+ }
+ }
+ if(n)
+ {
+ // last items to append
+ if(m_pTail)
+ {
+ m_pTail->m_pNext = n;
+ n->m_pPrev = m_pTail;
+ } else {
+ m_pHead = n;
+ m_pTail = n;
+ n->m_pPrev = NULL;
+ }
+ m_pTail = src->m_pTail;
+ }
+
+ src->m_pHead = NULL;
+ src->m_pTail = NULL;
+ src->m_uCount = 0;
+ }
+
+ void swap(KviPointerList<T> * src)
+ {
+ KviPointerListNode * n = m_pHead;
+ m_pHead = src->m_pHead;
+ src->m_pHead = n;
+ n = m_pTail;
+ m_pTail = src->m_pTail;
+ src->m_pTail = n;
+ unsigned int uCount = m_uCount;
+ m_uCount = src->m_uCount;
+ src->m_uCount = uCount;
+ }
+
+
+ ///
+ /// Sorts this list in ascending order.
+ /// There must be an int kvi_compare(const T *p1,const T *p2) function
+ /// which returns a value less than, equal to
+ /// or greater than zero when the item p1 is considered lower than,
+ /// equal to or greater than p2.
+ ///
+ void sort()
+ {
+ if(m_uCount < 2)return;
+
+ KviPointerList<T> carry;
+ KviPointerList<T> tmp[64];
+ KviPointerList * fill = &tmp[0];
+ KviPointerList * counter;
+
+ do {
+ carry.grabFirstAndPrepend(this);
+
+ for(counter = &tmp[0];counter != fill && !counter->isEmpty();++counter)
+ {
+ counter->merge(&carry);
+ carry.swap(counter);
+ }
+ carry.swap(counter);
+ if(counter == fill)
+ ++fill;
+ } while(m_uCount > 0);
+
+ for(counter = &tmp[1];counter != fill;++counter)
+ counter->merge(counter-1);
+ swap(fill-1);
+ }
+
+ ///
+ /// Inserts the item respecting the sorting order inside the list.
+ /// The list itself must be already sorted for this to work correctly.
+ /// There must be a int kvi_compare(const T *p1,const T * p2)
+ /// that returns a value less than, equal to
+ /// or greater than zero when the item p1 is considered lower than,
+ /// equal to or greater than p2.
+ ///
+ void inSort(T * t)
+ {
+ KviPointerListNode * x = m_pHead;
+ while(x && (kvi_compare(((T *)x->m_pData),t) > 0))x = x->m_pNext;
+ if(!x)append(t);
+ else insertBeforeSafe(x,t);
+ }
+
+ ///
+ /// Returns true if the list is empty
+ ///
+ bool isEmpty() const
+ {
+ return (m_pHead == NULL);
+ }
+
+ ///
+ /// Returns the count of the items in the list
+ ///
+ unsigned int count() const
+ {
+ return m_uCount;
+ }
+
+ ///
+ /// Sets the iteration pointer to the first item in the list
+ /// and returns that item (or 0 if the list is empty)
+ ///
+ T * first()
+ {
+ if(!m_pHead)
+ {
+ m_pAux = NULL;
+ return NULL;
+ }
+ m_pAux = m_pHead;
+ return (T *)(m_pAux->m_pData);
+ }
+
+ ///
+ /// Removes the first element from the list
+ /// and returns it to the caller. This function
+ /// obviously never deletes the item (regadless of autoDeletion()).
+ ///
+ T * takeFirst()
+ {
+ if(!m_pHead)return NULL;
+ T * pData = (T *)m_pHead->m_pData;
+ if(m_pHead->m_pNext)
+ {
+ m_pHead = m_pHead->m_pNext;
+ delete m_pHead->m_pPrev;
+ m_pHead->m_pPrev = NULL;
+ } else {
+ delete m_pHead;
+ m_pHead = NULL;
+ m_pTail = NULL;
+ }
+ m_uCount--;
+ return pData;
+ }
+
+ ///
+ /// Returns an iterator pointing to the first item of the list.
+ ///
+ KviPointerListIterator<T> iteratorAtFirst()
+ {
+ return KviPointerListIterator<T>(*this,m_pHead);
+ }
+
+ ///
+ /// Sets the iteration pointer to the last item in the list
+ /// and returns that item (or 0 if the list is empty)
+ ///
+ T * last()
+ {
+ if(!m_pTail)
+ {
+ m_pAux = NULL;
+ return NULL;
+ }
+ m_pAux = m_pTail;
+ return (T *)(m_pAux->m_pData);
+ }
+
+ ///
+ /// Returns an iterator pointing to the first item of the list.
+ ///
+ KviPointerListIterator<T> iteratorAtLast()
+ {
+ return KviPointerListIterator<T>(*this,m_pTail);
+ }
+
+ ///
+ /// Returns the current iteration item
+ /// A call to this function MUST be preceded by a call to
+ /// first(),last(),at() or findRef()
+ ///
+ T * current()
+ {
+ return (T *)(m_pAux->m_pData);
+ }
+
+ ///
+ /// Returns the current iteration item
+ /// A call to this function should be preceded by a call to
+ /// first(),last(),at() or findRef().
+ /// This function will return a NULL pointer if the current
+ /// item has been invalidated due to a remove operation.
+ ///
+ T * safeCurrent()
+ {
+ return m_pAux ? (T *)(m_pAux->m_pData) : NULL;
+ }
+
+
+ ///
+ /// Returns an iterator pointing to the current item in the list.
+ /// A call to this function MUST be preceded by a call to
+ /// first(),last(),at() or findRef()
+ ///
+ KviPointerListIterator<T> iteratorAtCurrent()
+ {
+ return KviPointerListIterator<T>(*this,m_pAux);
+ }
+
+ ///
+ /// Sets the iteration pointer to the next item in the list
+ /// and returns that item (or 0 if the end of the list has been reached)
+ /// A call to this function MUST be preceded by a _succesfull_ call to
+ /// first(),last(),at() or findRef().
+ ///
+ T * next()
+ {
+ if(!m_pAux)return NULL;
+ m_pAux = m_pAux->m_pNext;
+ if(m_pAux)return (T *)(m_pAux->m_pData);
+ return NULL;
+ }
+
+ ///
+ /// Sets the iteration pointer to the previous item in the list
+ /// and returns that item (or 0 if the beginning of the list has been reached)
+ /// A call to this function MUST be preceded by a _succesfull_ call to
+ /// first(),last(),at() or findRef()
+ ///
+ T * prev()
+ {
+ if(!m_pAux)return NULL;
+ m_pAux = m_pAux->m_pPrev;
+ if(m_pAux)return (T *)(m_pAux->m_pData);
+ return NULL;
+ }
+
+ ///
+ /// Sets the iteration pointer to the nTh item in the list
+ /// and returns that item (or 0 if the index is out of range)
+ ///
+ T * at(int idx)
+ {
+ T * t = first();
+ int cnt = 0;
+ while(t)
+ {
+ if(idx == cnt)return t;
+ t = next();
+ cnt++;
+ }
+ return 0;
+ }
+
+ ///
+ /// Returns an iterator pointing to the item at the specified index.
+ ///
+ KviPointerListIterator<T> iteratorAt(int idx)
+ {
+ KviPointerListNode * n = m_pHead;
+ int cnt = 0;
+ while(n)
+ {
+ if(idx == cnt)
+ return KviPointerListIterator<T>(*this,n);
+ n = n->m_pNext;
+ cnt++;
+ }
+ return KviPointerListIterator<T>(*this,NULL);
+ }
+
+ ///
+ /// Sets the iteration pointer to the item with pointer d
+ /// and returns its position (zero based index) in the list or -1 if the
+ /// item cannot be found
+ ///
+ int findRef(const T * d)
+ {
+ int ret = 0;
+ for(T * t = first();t;t = next())
+ {
+ if(t == d)return ret;
+ ret++;
+ }
+ return -1;
+ }
+
+ ///
+ /// Returns an iterator pointing to the item with pointer d.
+ ///
+ KviPointerListIterator<T> iteratorAtRef(const T * d)
+ {
+ KviPointerListNode * n = m_pHead;
+ while(n)
+ {
+ if(n->m_pData == d)
+ return KviPointerListIterator<T>(*this,n);
+ n = n->m_pNext;
+ }
+ return KviPointerListIterator<T>(*this,NULL);
+ }
+
+ ///
+ /// Appends an item at the end of the list
+ ///
+ void append(const T * d)
+ {
+ if(!m_pHead)
+ {
+ m_pHead = new KviPointerListNode;
+ m_pHead->m_pPrev = NULL;
+ m_pHead->m_pNext = NULL;
+ m_pHead->m_pData = (void *)d;
+ m_pTail = m_pHead;
+ } else {
+ m_pTail->m_pNext = new KviPointerListNode;
+ m_pTail->m_pNext->m_pPrev = m_pTail;
+ m_pTail->m_pNext->m_pNext = NULL;
+ m_pTail->m_pNext->m_pData = (void *)d;
+ m_pTail = m_pTail->m_pNext;
+ }
+ m_uCount++;
+ }
+
+ ///
+ /// Appends all the items from the list l to this list
+ ///
+ void append(KviPointerList<T> * l)
+ {
+ for(T * t = l->first();t;t = l->next())append(t);
+ }
+
+ ///
+ /// Prepends (inserts in head position) all the items from
+ /// the list l to this list
+ ///
+ void prepend(KviPointerList<T> * l)
+ {
+ for(T * t = l->last();t;t = l->prev())prepend(t);
+ }
+
+ ///
+ /// Inserts the item d in the head position
+ ///
+ void prepend(const T * d)
+ {
+ if(!m_pHead)
+ {
+ m_pHead = new KviPointerListNode;
+ m_pHead->m_pPrev = NULL;
+ m_pHead->m_pNext = NULL;
+ m_pHead->m_pData = (void *)d;
+ m_pTail = m_pHead;
+ } else {
+ m_pHead->m_pPrev = new KviPointerListNode;
+ m_pHead->m_pPrev->m_pNext = m_pHead;
+ m_pHead->m_pPrev->m_pPrev = NULL;
+ m_pHead->m_pPrev->m_pData = (void *)d;
+ m_pHead = m_pHead->m_pPrev;
+ m_uCount++;
+ }
+ }
+
+ ///
+ /// Inserts the item d at the zero-based position
+ /// specified by iIndex. If the specified position
+ /// is out of the list then the item is appended.
+ /// Note that this function costs O(n).
+ /// It's really better to use insertAfter() or
+ /// insertBefore(), if possible.
+ ///
+ void insert(int iIndex,const T * d)
+ {
+ m_pAux = m_pHead;
+ while(m_pAux && iIndex > 0)
+ {
+ iIndex--;
+ m_pAux = m_pAux->m_pNext;
+ }
+ if(m_pAux)
+ insertBeforeSafe(m_pAux,d);
+ else
+ append(d);
+ }
+
+ ///
+ /// Removes the firstitem (if any)
+ /// the item is deleted if autoDelete() is set to true
+ ///
+ bool removeFirst()
+ {
+ if(!m_pHead)return false;
+ const T * pAuxData;
+ if(m_pHead->m_pNext)
+ {
+ m_pHead = m_pHead->m_pNext;
+ pAuxData = (const T *)(m_pHead->m_pPrev->m_pData);
+ delete m_pHead->m_pPrev;
+ m_pHead->m_pPrev = NULL;
+ } else {
+ pAuxData = (const T *)(m_pHead->m_pData);
+ delete m_pHead;
+ m_pHead = NULL;
+ m_pTail = NULL;
+ }
+ m_pAux = NULL;
+ m_uCount--;
+ if(m_bAutoDelete)
+ delete pAuxData;
+ return true;
+ }
+
+ ///
+ /// Removes the firstitem (if any)
+ /// the item is deleted if autoDelete() is set to true
+ ///
+ bool removeLast()
+ {
+ if(!m_pTail)return false;
+ const T * pAuxData;
+ if(m_pTail->m_pPrev)
+ {
+ m_pTail = m_pTail->m_pPrev;
+ pAuxData = (const T *)(m_pTail->m_pNext->m_pData);
+ delete m_pTail->m_pNext;
+ m_pTail->m_pNext = NULL;
+ } else {
+ pAuxData = (const T *)(m_pTail->m_pData);
+ delete m_pTail;
+ m_pHead = NULL;
+ m_pTail = NULL;
+ }
+ m_pAux = NULL;
+ m_uCount--;
+ if(m_bAutoDelete)
+ delete pAuxData;
+ return true;
+ }
+
+ ///
+ /// Removes the item at zero-based position iIndex.
+ /// Does nothing and returns false if iIndex is out of the list.
+ /// Please note that this function costs O(n).
+ ///
+ bool remove(int iIndex)
+ {
+ m_pAux = m_pHead;
+ while(m_pAux && iIndex > 0)
+ {
+ iIndex--;
+ m_pAux = m_pAux->m_pNext;
+ }
+ if(!m_pAux)
+ return false;
+ removeCurrentSafe();
+ return true;
+ }
+
+ ///
+ /// Sets the autodelete flag
+ /// When this flag is on (default) , all the items
+ /// are deleted when removed from the list (or when the list is destroyed
+ /// or cleared explicitly)
+ ///
+ void setAutoDelete(bool bAutoDelete)
+ {
+ m_bAutoDelete = bAutoDelete;
+ }
+
+ ///
+ /// Returns the autodelete flag.
+ ///
+ bool autoDelete()
+ {
+ return m_bAutoDelete;
+ };
+
+ ///
+ /// Removes all the items from the list
+ /// (the items are deleted if the autoDelete() flag is set to true)
+ ///
+ void clear()
+ {
+ while(m_pHead)removeFirst();
+ }
+
+ ///
+ /// Removes the current iteration item.
+ /// Returns true if the current iteration item was valid (and was removed)
+ /// and false otherwise.
+ ///
+ bool removeCurrent()
+ {
+ if(!m_pAux)
+ return false;
+ removeCurrentSafe();
+ return true;
+ }
+
+ ///
+ /// Removes the item pointed by d (if found in the list)
+ /// the item is deleted if the autoDelete() flag is set to true)
+ /// Returns true if the item was in the list and false otherwise.
+ ///
+ bool removeRef(const T * d)
+ {
+ if(findRef(d) == -1)return false;
+ removeCurrentSafe();
+ return true;
+ }
+
+ ///
+ /// inserts the item d after the item ref or at the end
+ /// if ref is not found in the list
+ /// also sets the current iteration pointer to the newly inserted item
+ ///
+ void insertAfter(const T * ref,const T * d)
+ {
+ if(findRef(ref) == -1)
+ {
+ append(d);
+ return;
+ }
+ KviPointerListNode * n = new KviPointerListNode;
+ n->m_pPrev = m_pAux;
+ n->m_pNext = m_pAux->m_pNext;
+ if(m_pAux->m_pNext)
+ m_pAux->m_pNext->m_pPrev = n;
+ else
+ m_pTail = n;
+ m_pAux->m_pNext = n;
+ n->m_pData = (void *)d;
+ m_uCount++;
+ }
+
+ ///
+ /// inserts the item d before the item ref or at the beginning
+ /// if ref is not found in the list
+ /// also sets the current iteration pointer to the newly inserted item
+ ///
+ void insertBefore(const T * ref,const T * d)
+ {
+ if(findRef(ref) == -1)
+ {
+ prepend(d);
+ return;
+ }
+ KviPointerListNode * n = new KviPointerListNode;
+ n->m_pPrev = m_pAux->m_pPrev;
+ n->m_pNext = m_pAux;
+ if(m_pAux->m_pPrev)
+ m_pAux->m_pPrev->m_pNext = n;
+ else
+ m_pHead = n;
+ m_pAux->m_pPrev = n;
+ n->m_pData = (void *)d;
+ m_uCount++;
+ }
+
+ ///
+ /// Inverts the elements in the list.
+ ///
+ void invert()
+ {
+ if(!m_pHead)return;
+ KviPointerListNode * oldHead = m_pHead;
+ KviPointerListNode * oldTail = m_pTail;
+ KviPointerListNode * n = m_pHead;
+ while(n)
+ {
+ KviPointerListNode * next = n->m_pNext;
+ n->m_pNext = n->m_pPrev;
+ n->m_pPrev = next;
+ n = next;
+ }
+ m_pTail = oldHead;
+ m_pHead = oldTail;
+ }
+
+ ///
+ /// clears the list and inserts all the items from the list l
+ ///
+ void copyFrom(KviPointerList<T> * l)
+ {
+ clear();
+ for(T * t = l->first();t;t = l->next())append(t);
+ }
+
+ ///
+ /// equivalent to copyFrom(l)
+ ///
+ KviPointerList<T> & operator = (KviPointerList<T> &l)
+ {
+ copyFrom(&l);
+ return *this;
+ }
+
+ ///
+ /// creates a template list
+ ///
+ KviPointerList<T>(bool bAutoDelete = true)
+ {
+ m_bAutoDelete = bAutoDelete;
+ m_pHead = NULL;
+ m_pTail = NULL;
+ m_uCount = 0;
+ m_pAux = NULL;
+ };
+
+ ///
+ /// destroys the list
+ /// if autoDelete() is set to true, all the items are deleted
+ ///
+ virtual ~KviPointerList<T>()
+ {
+ clear();
+ };
+};
+
+#define KviPointerListBase KviPointerList
+
+// BROKEN MSVC LINKER
+#ifdef COMPILE_ON_WINDOWS
+ #include "kvi_string.h"
+ template class KVILIB_API KviPointerList<KviStr>;
+#endif
+
+#endif //_KVI_POINTERLIST_H_
diff --git a/src/kvilib/core/kvi_qcstring.h b/src/kvilib/core/kvi_qcstring.h
new file mode 100644
index 00000000..0693e205
--- /dev/null
+++ b/src/kvilib/core/kvi_qcstring.h
@@ -0,0 +1,39 @@
+#ifndef _KVI_QCSTRING_H_
+#define _KVI_QCSTRING_H_
+
+//=============================================================================
+//
+// File : kvi_qcstring.h
+// Creation date : Thu Jan 18 2007 00:34:33 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_USE_QT4
+ #include <q3cstring.h> // includes <qbytearray.h>
+ #define KviQCString QByteArray
+#else
+ // this is dead in Qt 4.x
+ #include <qcstring.h>
+ #define KviQCString QCString
+#endif
+
+#endif //!_KVI_QCSTRING_H_
diff --git a/src/kvilib/core/kvi_qstring.cpp b/src/kvilib/core/kvi_qstring.cpp
new file mode 100644
index 00000000..eba255aa
--- /dev/null
+++ b/src/kvilib/core/kvi_qstring.cpp
@@ -0,0 +1,1125 @@
+//=============================================================================
+//
+// File : kvi_qstring.cpp
+// Creation date : Mon Aug 04 2003 13:36:33 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003-2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+//=============================================================================
+//
+// Helper functions for the QString class
+//
+//=============================================================================
+
+#define __KVILIB__
+
+
+#include "kvi_qstring.h"
+#include "kvi_string.h"
+#include "kvi_malloc.h"
+#include "kvi_locale.h"
+
+#include <ctype.h> // for tolower()
+#include <stdio.h> // for sprintf()
+#include <qregexp.h>
+
+// kvi_string.cpp
+extern unsigned char iso88591_toLower_map[256];
+extern unsigned char iso88591_toUpper_map[256];
+
+#define MY_MIN(a,b) (((a) < (b)) ? (a) : (b))
+
+namespace KviQString
+{
+ // The global empty (and null) string
+ const QString empty;
+
+ bool equalCSN(const QString &sz1,const QString &sz2,unsigned int len)
+ {
+ if(len == 0)return true; // assume equal
+ const QChar * c1 = sz1.unicode();
+ const QChar * c2 = sz2.unicode();
+ unsigned int lmin = MY_MIN(sz1.length(),sz2.length());
+ if(lmin < len)return false;
+ const QChar * c1e = c1 + len;
+
+ if(!c1 || !c2)return (c1 == c2);
+
+ while(c1 < c1e)
+ {
+ if(c1->unicode() != c2->unicode())return false;
+ c1++;
+ c2++;
+ }
+ return (c1 == c1e);
+ }
+
+ bool equalCIN(const QString &sz1,const QString &sz2,unsigned int len)
+ {
+ if(len == 0)return true; // assume equal
+ const QChar * c1 = sz1.unicode();
+ const QChar * c2 = sz2.unicode();
+ unsigned int lmin = MY_MIN(sz1.length(),sz2.length());
+ if(lmin < len)return false;
+ const QChar * c1e = c1 + len;
+
+ if(!c1 || !c2)return (c1 == c2);
+
+ while(c1 < c1e)
+ {
+#ifdef COMPILE_USE_QT4
+ if(c1->toLower().unicode() != c2->toLower().unicode())return false;
+#else
+ if(c1->lower().unicode() != c2->lower().unicode())return false;
+#endif
+ c1++;
+ c2++;
+ }
+ return (c1 == c1e);
+ }
+
+ bool equalCSN(const QString &sz1,const char * sz2,unsigned int len)
+ {
+ if(len == 0)return true; // assume equal
+ const QChar * c1 = sz1.unicode();
+ if(sz1.length() < len)return false;
+ const QChar * c1e = c1 + len;
+
+ if(!sz2)return !c1;
+ if(!c1)return !sz2;
+
+ while((c1 < c1e) && (*sz2))
+ {
+ if(c1->unicode() != *sz2)return false;
+ c1++;
+ sz2++;
+ }
+ return (c1 == c1e);
+ }
+
+ bool equalCIN(const QString &sz1,const char * sz2,unsigned int len)
+ {
+ if(len == 0)return true; // assume equal
+ const QChar * c1 = sz1.unicode();
+ if(sz1.length() < len)return false;
+ const QChar * c1e = c1 + len;
+
+ if(!sz2)return !c1;
+ if(!c1)return !(*sz2);
+
+ while((c1 < c1e) && (*sz2))
+ {
+#ifdef COMPILE_USE_QT4
+ if(c1->toLower().unicode() != tolower(*sz2))return false;
+#else
+ if(c1->lower().unicode() != tolower(*sz2))return false;
+#endif
+ c1++;
+ sz2++;
+ }
+ return (c1 == c1e);
+ }
+
+ // sz2 is assumed to be null terminated, sz1 is not!
+ bool equalCIN(const QString &sz1,const QChar *sz2,unsigned int len)
+ {
+ if(len == 0)return true; // assume equal
+ const QChar * c1 = sz1.unicode();
+ if(sz1.length() < len)return false;
+ const QChar * c1e = c1 + len;
+
+ if(!sz2)return !c1;
+ if(!c1)return !(sz2->unicode());
+
+ while((c1 < c1e) && (sz2->unicode()))
+ {
+#ifdef COMPILE_USE_QT4
+ if(c1->toLower().unicode() != sz2->toLower().unicode())return false;
+#else
+ if(c1->lower().unicode() != sz2->lower().unicode())return false;
+#endif
+ c1++;
+ sz2++;
+ }
+ return (c1 == c1e);
+ }
+
+ QString makeSizeReadable(size_t bytes)
+ {
+ double size = bytes;
+ if(size<900)
+ return QString(__tr2qs("%1 bytes")).arg(size,0,'f',3);
+
+ size/=1024;
+ if(size<900)
+ return QString(__tr2qs("%1 KB")).arg(size,0,'f',3);
+
+ size/=1024;
+ if(size<900)
+ return QString(__tr2qs("%1 MB")).arg(size,0,'f',3);
+
+ //Pirated DVD?;)
+ size/=1024;
+ if(size<900)
+ return QString(__tr2qs("%1 GB")).arg(size,0,'f',3);
+
+ //Uhm.. We are downloading a whole internet:)))
+ size/=1024;
+ return QString(__tr2qs("%1 TB")).arg(size,0,'f',3);
+ }
+
+ bool equalCS(const QString &sz1,const QString &sz2)
+ {
+ if(sz1.length() != sz2.length())return false;
+
+ const QChar * c1 = sz1.unicode();
+ const QChar * c2 = sz2.unicode();
+ const QChar * c1e = c1 + sz1.length();
+
+ if(!c1 || !c2)return (c1 == c2);
+
+ while(c1 < c1e)
+ {
+ if(c1->unicode() != c2->unicode())return false;
+ c1++;
+ c2++;
+ }
+ return (c1 == c1e);
+ }
+
+ bool equalCI(const QString &sz1,const QString &sz2)
+ {
+ if(sz1.length() != sz2.length())return false;
+
+ const QChar * c1 = sz1.unicode();
+ const QChar * c2 = sz2.unicode();
+ const QChar * c1e = c1 + sz1.length();
+
+ if(!c1 || !c2)return (c1 == c2);
+
+ while(c1 < c1e)
+ {
+#ifdef COMPILE_USE_QT4
+ if(c1->toLower().unicode() != c2->toLower().unicode())return false;
+#else
+ if(c1->lower().unicode() != c2->lower().unicode())return false;
+#endif
+ c1++;
+ c2++;
+ }
+ return (c1 == c1e);
+ }
+
+ // sz2 is assumed to be null terminated, sz1 is not!
+ bool equalCI(const QString &sz1,const QChar *sz2)
+ {
+ const QChar * c1 = sz1.unicode();
+ const QChar * c1e = c1 + sz1.length();
+
+ if(!c1 || !sz2)return (c1 == sz2);
+
+ while(c1 < c1e)
+ {
+ if(!sz2->unicode())return false; // sz1 has at least another character
+#ifdef COMPILE_USE_QT4
+ if(c1->toLower().unicode() != sz2->toLower().unicode())return false;
+#else
+ if(c1->lower().unicode() != sz2->lower().unicode())return false;
+#endif
+ c1++;
+ sz2++;
+ }
+ return (c1 == c1e) && (!sz2->unicode());
+ }
+
+ bool equalCS(const QString &sz1,const char * sz2)
+ {
+ const QChar * c1 = sz1.unicode();
+ const QChar * c1e = c1 + sz1.length();
+
+ if(!c1)return !sz2;
+
+ while((c1 < c1e) && (*sz2))
+ {
+ if(c1->unicode() != *sz2)return false;
+ c1++;
+ sz2++;
+ }
+ return ((c1 == c1e) && (*sz2 == '\0'));
+ }
+
+ bool equalCI(const QString &sz1,const char * sz2)
+ {
+ const QChar * c1 = sz1.unicode();
+ const QChar * c1e = c1 + sz1.length();
+
+ if(!c1)return !sz2;
+
+ while((c1 < c1e) && (*sz2))
+ {
+#ifdef COMPILE_USE_QT4
+ if(c1->toLower().unicode() != tolower(*sz2))return false;
+#else
+ if(c1->lower().unicode() != tolower(*sz2))return false;
+#endif
+ c1++;
+ sz2++;
+ }
+ return ((c1 == c1e) && (*sz2 == '\0'));
+ }
+
+ int cmpCS(const QString &sz1,const QString &sz2)
+ {
+ const QChar * c1 = sz1.unicode();
+ const QChar * c2 = sz2.unicode();
+ const QChar * c1e = c1 + sz1.length();
+ const QChar * c2e = c2 + sz2.length();
+
+ if(!c1)
+ {
+ if(!c2)return 0;
+ return -1;
+ }
+ if(!c2)return 1;
+
+
+ for(;;)
+ {
+ if(c1 >= c1e)
+ {
+ if(c2 < c2e)return /* 0 */ - (c2->unicode());
+ return 0;
+ }
+ if(c2 >= c2e)return c1->unicode() /* - 0 */;
+
+ int diff = c1->unicode() - c2->unicode();
+ if(diff)return diff;
+
+ c1++;
+ c2++;
+ }
+
+ return 0; // never here
+ }
+
+ int cmpCI(const QString &sz1,const QString &sz2)
+ {
+ const QChar * c1 = sz1.unicode();
+ const QChar * c2 = sz2.unicode();
+ const QChar * c1e = c1 + sz1.length();
+ const QChar * c2e = c2 + sz2.length();
+
+ if(!c1)
+ {
+ if(!c2)return 0;
+ return -1;
+ }
+ if(!c2)return 1;
+
+ for(;;)
+ {
+ if(c1 >= c1e)
+ {
+#ifdef COMPILE_USE_QT4
+ if(c2 < c2e)return /* 0 */ - (c2->toLower().unicode());
+#else
+ if(c2 < c2e)return /* 0 */ - (c2->lower().unicode());
+#endif
+ return 0;
+ }
+#ifdef COMPILE_USE_QT4
+ if(c2 >= c2e)return c1->toLower().unicode() /* - 0 */;
+#else
+ if(c2 >= c2e)return c1->lower().unicode() /* - 0 */;
+#endif
+
+#ifdef COMPILE_USE_QT4
+ int diff = c1->toLower().unicode() - c2->toLower().unicode();
+#else
+ int diff = c1->lower().unicode() - c2->lower().unicode();
+#endif
+ if(diff)return diff;
+
+ c1++;
+ c2++;
+ }
+
+ return 0; // never here
+ }
+
+ int cmpCIN(const QString &sz1,const QString &sz2,unsigned int len)
+ {
+ if(len == 0)return 0; // assume equal
+ unsigned int l1 = MY_MIN(len,sz1.length());
+ unsigned int l = MY_MIN(l1,sz2.length()); // FIXME: THIS IS NOT OK
+
+ const QChar * c1 = sz1.unicode();
+ const QChar * c2 = sz2.unicode();
+ const QChar * c1e = c1 + l;
+
+ if(!c1)
+ {
+ if(!c2)return 0;
+ return -1;
+ }
+ if(!c2)return 1;
+
+ int diff = 0;
+
+#ifdef COMPILE_USE_QT4
+ while((c1 < c1e) && !(diff = (c1->toLower().unicode() - c2->toLower().unicode())))
+#else
+ while((c1 < c1e) && !(diff = (c1->lower().unicode() - c2->lower().unicode())))
+#endif
+ {
+ c1++;
+ c2++;
+ }
+
+ return diff;
+ }
+
+ void ensureLastCharIs(QString &szString,const QChar &c)
+ {
+ if(!lastCharIs(szString,c))szString.append(c);
+ }
+
+ QString getToken(QString &szString,const QChar &sep)
+ {
+ int i=0;
+ while(i < szString.length())
+ {
+ if(szString[i] == sep)break;
+ i++;
+ }
+ QString ret;
+ if(i == szString.length())
+ {
+ ret = szString;
+ szString = "";
+ } else {
+ ret = szString.left(i);
+ while(i < szString.length())
+ {
+ if(szString[i] != sep)break;
+ i++;
+ }
+ if(i == szString.length())szString = "";
+ else szString.remove(0,i);
+ }
+ return ret;
+ }
+
+ void stripRightWhiteSpace(QString &s)
+ {
+ int iRemove = 0;
+ while(iRemove < s.length())
+ {
+ if(s.at(s.length() - (iRemove + 1)).isSpace())iRemove++;
+ else break;
+ }
+ if(iRemove > 0)s.remove(s.length() - iRemove,iRemove);
+ }
+
+ void stripRight(QString &s,const QChar &c)
+ {
+ int iRemove = 0;
+ while(iRemove < s.length())
+ {
+ if(s.at(s.length() - (iRemove + 1)) == c)iRemove++;
+ else break;
+ }
+ if(iRemove > 0)s.remove(s.length() - iRemove,iRemove);
+ }
+
+ void stripLeft(QString &s,const QChar &c)
+ {
+ int iRemove = 0;
+ while(iRemove < s.length())
+ {
+ if(s[iRemove] == c)
+ iRemove++;
+ else
+ break;
+ }
+ if(iRemove > 0)s.remove(0,iRemove);
+ }
+
+ void detach(QString &sz)
+ {
+#ifdef COMPILE_USE_QT4
+ sz.resize(sz.length());
+#else
+ sz.setLength(sz.length());
+#endif
+ }
+
+ const QChar * nullTerminatedArray(const QString &sz)
+ {
+ //sz.setLength(sz.length()); // detach!
+#ifdef COMPILE_USE_QT4
+ return sz.constData();
+#else
+ return (const QChar *)sz.ucs2(); // MAY BE NULL!
+#endif
+ }
+
+ void appendNumber(QString &s,double dReal)
+ {
+ char buffer[512];
+ ::sprintf(buffer,"%f",dReal);
+ s.append(buffer);
+ }
+
+ void appendNumber(QString &s,int iInteger)
+ {
+ char buffer[64];
+ ::sprintf(buffer,"%d",iInteger);
+ s.append(buffer);
+ }
+
+ void appendNumber(QString &s,kvi_i64_t iInteger)
+ {
+ char buffer[64];
+ ::sprintf(buffer,"%ld",iInteger);
+ s.append(buffer);
+ }
+
+ void appendNumber(QString &s,kvi_u64_t uInteger)
+ {
+ char buffer[64];
+ ::sprintf(buffer,"%lu",uInteger);
+ s.append(buffer);
+ }
+
+ void appendNumber(QString &s,unsigned int uInteger)
+ {
+ char buffer[64];
+ ::sprintf(buffer,"%u",uInteger);
+ s.append(buffer);
+ }
+
+ void vsprintf(QString &s,const QString &szFmt,kvi_va_list list)
+ {
+#define MEMINCREMENT 32
+
+ int reallen = 0;
+ int allocsize = MEMINCREMENT;
+
+ //s.setLength(allocsize);
+
+ const QChar * fmt = nullTerminatedArray(szFmt);
+ if(!fmt)
+ {
+ s = QString::null;
+ return;
+ }
+
+ QChar * buffer = (QChar *)kvi_malloc(sizeof(QChar) * allocsize);
+ //QChar * p = (QChar *)s.unicode();
+
+ char *argString;
+ long argValue;
+ unsigned long argUValue;
+
+ //9999999999999999999999999999999\0
+ char numberBuffer[32]; //enough ? 10 is enough for 32bit unsigned int...
+ char *pNumBuf;
+ unsigned int tmp;
+
+ QChar * p = buffer;
+
+#define INCREMENT_MEM \
+ { \
+ allocsize += MEMINCREMENT; \
+ buffer = (QChar *)kvi_realloc(buffer,sizeof(QChar) * allocsize); \
+ p = buffer + reallen; \
+ }
+
+#define INCREMENT_MEM_BY(numchars) \
+ { \
+ allocsize += numchars + MEMINCREMENT; \
+ buffer = (QChar *)kvi_realloc(buffer,sizeof(QChar) * allocsize); \
+ p = buffer + reallen; \
+ }
+
+
+ for(; fmt->unicode() ; ++fmt)
+ {
+ if(reallen == allocsize)INCREMENT_MEM
+
+ //copy up to a '%'
+ if(fmt->unicode() != '%')
+ {
+ *p++ = *fmt;
+ reallen++;
+ continue;
+ }
+
+ ++fmt; //skip this '%'
+ switch(fmt->unicode())
+ {
+ case 's': // char * string
+ {
+ argString = kvi_va_arg(list,char *);
+ if(!argString)argString = "[!NULL!]";
+ QString str(argString);
+ if(str.isEmpty())continue;
+ int len = str.length();
+ const QChar * ch = str.unicode();
+ if(!ch)continue;
+ if((allocsize - reallen) < len)INCREMENT_MEM_BY(len)
+ while(len--)*p++ = *ch++;
+ reallen += str.length();
+ continue;
+ }
+ case 'S': // KviStr * string
+ {
+ KviStr * str = kvi_va_arg(list,KviStr *);
+ if(!str)continue;
+ if((allocsize - reallen) < str->len())INCREMENT_MEM_BY(str->len())
+ argString = str->ptr();
+ while(*argString)*p++ = QChar(*argString++);
+ reallen += str->len();
+ continue;
+ }
+ case 'Q': // QString * string
+ {
+ QString * str = kvi_va_arg(list,QString *);
+ if(!str)continue;
+ if(str->isEmpty())continue;
+ int len = str->length();
+ const QChar * ch = str->unicode();
+ if(!ch)continue;
+ if((allocsize - reallen) < len)INCREMENT_MEM_BY(len)
+ while(len--)*p++ = *ch++;
+ reallen += str->length();
+ continue;
+ }
+ case 'c': //char
+ {
+ //
+ // I'm not sure about this...
+ // In the linux kernel source the
+ // unsigned char is extracted from an integer type.
+ // We assume that gcc stacks a char argument
+ // as sizeof(int) bytes value.
+ // Is this always true ?
+ //
+ *p++ = (char)kvi_va_arg(list,int);
+ reallen++;
+ continue;
+ }
+ case 'q': // QChar *
+ {
+ //
+ // I'm not sure about this...
+ // In the linux kernel source the
+ // unsigned char is extracted from an integer type.
+ // We assume that gcc stacks a char argument
+ // as sizeof(int) bytes value.
+ // Is this always true ?
+ //
+ *p++ = *((QChar *)kvi_va_arg(list,QChar *));
+ reallen++;
+ continue;
+ }
+ case 'd': //signed integer
+ {
+ argValue = kvi_va_arg(list,int);
+ if(argValue < 0)
+ { //negative integer
+ *p++ = '-';
+ reallen++;
+ argValue = -argValue; //need to have it positive
+ // most negative integer exception (avoid completely senseless (non digit) responses)
+ if(argValue < 0)argValue = 0; //we get -0 here
+ }
+ //write the number in a temporary buffer
+ pNumBuf = numberBuffer;
+ do {
+ tmp = argValue / 10;
+ *pNumBuf++ = argValue - (tmp * 10) + '0';
+ } while((argValue = tmp));
+ //copy now....
+ argUValue = pNumBuf - numberBuffer; //length of the number string
+ if((allocsize - reallen) < (int)argUValue)INCREMENT_MEM_BY(argUValue)
+ do { *p++ = QChar(*--pNumBuf); } while(pNumBuf != numberBuffer);
+ reallen += argUValue;
+ continue;
+ }
+ case 'u': //unsigned integer
+ {
+ argUValue = kvi_va_arg(list,unsigned int); //many implementations place int here
+ //write the number in a temporary buffer
+ pNumBuf = numberBuffer;
+ do {
+ tmp = argUValue / 10;
+ *pNumBuf++ = argUValue - (tmp * 10) + '0';
+ } while((argUValue = tmp));
+ //copy now....
+ argValue = pNumBuf - numberBuffer; //length of the number string
+ if((allocsize - reallen) < argValue)INCREMENT_MEM_BY(argValue)
+ do { *p++ = *--pNumBuf; } while(pNumBuf != numberBuffer);
+ reallen += argValue;
+ continue;
+ }
+ case 'h':
+ case 'x': // hexadecimal unsigned integer
+ {
+ static char hexsmalldigits[]="0123456789abcdef";
+ argUValue = kvi_va_arg(list,unsigned int); //many implementations place int here
+ //write the number in a temporary buffer
+ pNumBuf = numberBuffer;
+ do {
+ tmp = argUValue / 16;
+ *pNumBuf++ = hexsmalldigits[argUValue - (tmp * 16)];
+ } while((argUValue = tmp));
+ //copy now....
+ argValue = pNumBuf - numberBuffer; //length of the number string
+ if((allocsize - reallen) < argValue)INCREMENT_MEM_BY(argValue)
+ do { *p++ = *--pNumBuf; } while(pNumBuf != numberBuffer);
+ reallen += argValue;
+ continue;
+ }
+ case 'H':
+ case 'X': // hexadecimal unsigned integer
+ {
+ static char hexbigdigits[]="0123456789ABCDEF";
+ argUValue = kvi_va_arg(list,unsigned int); //many implementations place int here
+ //write the number in a temporary buffer
+ pNumBuf = numberBuffer;
+ do {
+ tmp = argUValue / 16;
+ *pNumBuf++ = hexbigdigits[argUValue - (tmp * 16)];
+ } while((argUValue = tmp));
+ //copy now....
+ argValue = pNumBuf - numberBuffer; //length of the number string
+ if((allocsize - reallen) < argValue)INCREMENT_MEM_BY(argValue)
+ do { *p++ = *--pNumBuf; } while(pNumBuf != numberBuffer);
+ reallen += argValue;
+ continue;
+ }
+ default: //a normal percent followed by some char
+ {
+ *p++ = '%'; //write it
+ reallen++;
+ if(fmt->unicode())
+ {
+ if(reallen == allocsize)INCREMENT_MEM
+ *p++ = *fmt;
+ reallen++;
+ }
+ continue;
+ }
+ }
+ }
+
+ s.setUnicode(buffer,reallen);
+ kvi_free(buffer);
+ //s.squeeze();
+ }
+
+
+ QString & sprintf(QString &s,const QString &szFmt,...)
+ {
+ kvi_va_list list;
+ kvi_va_start_by_reference(list,szFmt);
+ //print...with max 256 chars
+ KviQString::vsprintf(s,szFmt,list);
+ kvi_va_end(list);
+ return s;
+ }
+
+ void appendFormatted(QString &s,const QString &szFmt,...)
+ {
+ QString tmp;
+ kvi_va_list list;
+ kvi_va_start_by_reference(list,szFmt);
+ //print...with max 256 chars
+ KviQString::vsprintf(tmp,szFmt,list);
+ kvi_va_end(list);
+ s.append(tmp);
+ }
+
+ bool matchWildExpressionsCI(const QString &szM1,const QString &szM2)
+ {
+ //Matches two regular expressions containging wildcards (* and ?)
+
+ // s1
+ // m1
+ // mask1 : *xor
+ // mask2 : xorand*xor
+ // m2
+ // s2
+
+ // s2
+ // m2
+ // |
+ // XorT!xor@111.111.111.11
+ //
+ // *!*@*.net
+ // |
+ // m1
+ // s1
+ //
+
+#ifdef COMPILE_USE_QT4
+ const QChar * m1 = (const QChar *)szM1.constData();
+ const QChar * m2 = (const QChar *)szM2.constData();
+#else
+ const QChar * m1 = (const QChar *)szM1.ucs2();
+ const QChar * m2 = (const QChar *)szM2.ucs2();
+#endif
+
+ if(!(m1 && m2 && (m1->unicode())))return false;
+ const QChar * savePos1 = 0;
+ const QChar * savePos2 = m2;
+ while(m1->unicode())
+ {
+ //loop managed by m1 (initially first mask)
+ if(m1->unicode()=='*')
+ {
+ //Found a wildcard in m1
+ savePos1 = ++m1; //move to the next char and save the position...this is our jolly
+ if(!savePos1->unicode())return true; //last was a wildcard , matches everything ahead...
+ savePos2 = m2+1; //next return state for the second string
+ continue; //and return
+ }
+ if(!m2->unicode())return false; //m2 finished and we had something to match here!
+#ifdef COMPILE_USE_QT4
+ if(m1->toLower()==m2->toLower())
+#else
+ if(m1->lower()==m2->lower())
+#endif
+ {
+ //chars matched
+ m1++; //Go ahead in the two strings
+ m2++; //
+ if((!(m1->unicode())) && m2->unicode() && savePos1)
+ {
+ //m1 finished , but m2 not yet and we have a savePosition for m1 (there was a wildcard)...
+ //retry matching the string following the * from the savePos2 (one char ahead last time)
+ m1 = savePos1; //back to char after wildcard
+ m2 = savePos2; //back to last savePos2
+ savePos2++; //next savePos2 will be next char
+ }
+ } else {
+ if(m2->unicode() == '*')
+ {
+ //A wlidcard in the second string
+ //Invert the game : mask1 <-> mask2
+ //mask2 now leads the game...
+ savePos1 = m1; //aux
+ m1 = m2; //...swap
+ m2 = savePos1; //...swap
+ savePos1 = m1; //sync save pos1
+ savePos2 = m2 + 1; //sync save pos2
+ continue; //...and again
+ }
+ // m1 != m2 , m1 != * , m2 != *
+ if((m1->unicode() == '?') || (m2->unicode() == '?'))
+ {
+ m1++;
+ m2++;
+ if((!(m1->unicode())) && m2->unicode() && savePos1)
+ {
+ //m1 finished , but m2 not yet and we have a savePosition for m1 (there was a wildcard)...
+ //retry matching the string following the * from the savePos2 (one char ahead last time)
+ m1 = savePos1; //back to char after wildcard
+ m2 = savePos2; //back to last savePos2
+ savePos2++; //next savePos2 will be next char
+ }
+ } else {
+ if(savePos1)
+ {
+ //Have a jolly man...allow not matching...
+ m1 = savePos1; //go back to char after wildcard...need to rematch...
+ m2 = savePos2; //back to last savePos2
+ savePos2++; //and set next savePos2
+ } else return false; //No previous wildcards...not matched!
+ }
+ }
+ }
+ return (!(m2->unicode())); //m1 surely finished , so for the match , m2 must be finished too
+ }
+
+ bool matchStringCI(const QString &szExp,const QString &szStr,bool bIsRegExp,bool bExact)
+ {
+ QString szWildcard;
+#ifdef COMPILE_USE_QT4
+ QChar* ptr=(QChar*)szExp.constData();
+#else
+ QChar* ptr=(QChar*)szExp.ucs2();
+#endif
+ if(!ptr) return 0;
+ while(ptr->unicode())
+ {
+ if((ptr->unicode()=='[') || (ptr->unicode()==']'))
+ {
+ szWildcard.append("[");
+ szWildcard.append(*ptr);
+ szWildcard.append("]");
+ } else {
+ szWildcard.append(*ptr);
+ }
+ ptr++;
+ }
+#ifdef COMPILE_USE_QT4
+ QRegExp re(szWildcard,Qt::CaseInsensitive,bIsRegExp ? QRegExp::RegExp : QRegExp::Wildcard);
+#else
+ QRegExp re(szWildcard,false,!bIsRegExp);
+#endif
+ if(bExact) return re.exactMatch(szStr);
+#ifdef COMPILE_USE_QT4
+ return re.indexIn(szStr) != -1;
+#else
+ return re.search(szStr) != -1;
+#endif
+ }
+
+ bool matchStringCS(const QString &szExp,const QString &szStr,bool bIsRegExp,bool bExact)
+ {
+ QString szWildcard;
+#ifdef COMPILE_USE_QT4
+ QChar* ptr=(QChar*)szExp.constData();
+#else
+ QChar* ptr=(QChar*)szExp.ucs2();
+#endif
+ if(!ptr) return 0;
+ while(ptr->unicode())
+ {
+ if((ptr->unicode()=='[')) // <-- hum ?
+ {
+ szWildcard.append("[");
+ szWildcard.append(*ptr);
+ szWildcard.append("]");
+ } else {
+ szWildcard.append(*ptr);
+ }
+ ptr++;
+ }
+#ifdef COMPILE_USE_QT4
+ QRegExp re(szWildcard,Qt::CaseSensitive,bIsRegExp ? QRegExp::RegExp : QRegExp::Wildcard);
+#else
+ QRegExp re(szWildcard,true,!bIsRegExp);
+#endif
+ if(bExact) return re.exactMatch(szStr);
+#ifdef COMPILE_USE_QT4
+ return re.indexIn(szStr) != -1;
+#else
+ return re.search(szStr) != -1;
+#endif
+ }
+
+ void cutFromFirst(QString &s,const QChar &c,bool bIncluded)
+ {
+#ifdef COMPILE_USE_QT4
+ int idx = s.indexOf(c);
+#else
+ int idx = s.find(c);
+#endif
+ if(idx == -1)return;
+ s.truncate(bIncluded ? idx : idx + 1);
+ }
+
+ void cutFromLast(QString &s,const QChar &c,bool bIncluded)
+ {
+#ifdef COMPILE_USE_QT4
+ int idx = s.lastIndexOf(c);
+#else
+ int idx = s.findRev(c);
+#endif
+ if(idx == -1)return;
+ s.truncate(bIncluded ? idx : idx + 1);
+ }
+
+ void cutToFirst(QString &s,const QChar &c,bool bIncluded,bool bClearIfNotFound)
+ {
+#ifdef COMPILE_USE_QT4
+ int idx = s.indexOf(c);
+#else
+ int idx = s.find(c);
+#endif
+ if(idx == -1)
+ {
+ if(bClearIfNotFound)s = "";
+ return;
+ }
+ s.remove(0,bIncluded ? idx + 1 : idx);
+ }
+
+ void cutToLast(QString &s,const QChar &c,bool bIncluded,bool bClearIfNotFound)
+ {
+#ifdef COMPILE_USE_QT4
+ int idx = s.lastIndexOf(c);
+#else
+ int idx = s.findRev(c);
+#endif
+ if(idx == -1)
+ {
+ if(bClearIfNotFound)s = "";
+ return;
+ }
+ s.remove(0,bIncluded ? idx + 1 : idx);
+ }
+
+ void cutFromFirst(QString &s,const QString &c,bool bIncluded)
+ {
+#ifdef COMPILE_USE_QT4
+ int idx = s.indexOf(c);
+#else
+ int idx = s.find(c);
+#endif
+ if(idx == -1)return;
+ s.truncate(bIncluded ? idx : idx + c.length());
+ }
+
+ void cutFromLast(QString &s,const QString &c,bool bIncluded)
+ {
+#ifdef COMPILE_USE_QT4
+ int idx = s.lastIndexOf(c);
+#else
+ int idx = s.findRev(c);
+#endif
+ if(idx == -1)return;
+ s.truncate(bIncluded ? idx : idx + c.length());
+ }
+
+ void cutToFirst(QString &s,const QString &c,bool bIncluded,bool bClearIfNotFound)
+ {
+#ifdef COMPILE_USE_QT4
+ int idx = s.indexOf(c);
+#else
+ int idx = s.find(c);
+#endif
+ if(idx == -1)
+ {
+ if(bClearIfNotFound)s = "";
+ return;
+ }
+ s.remove(0,bIncluded ? idx + c.length() : idx);
+ }
+
+ void cutToLast(QString &s,const QString &c,bool bIncluded,bool bClearIfNotFound)
+ {
+#ifdef COMPILE_USE_QT4
+ int idx = s.lastIndexOf(c);
+#else
+ int idx = s.findRev(c);
+#endif
+ if(idx == -1)
+ {
+ if(bClearIfNotFound)s = "";
+ return;
+ }
+ s.remove(0,bIncluded ? idx + c.length() : idx);
+ }
+
+ QString upperISO88591(const QString &szSrc)
+ {
+ const QChar * c = nullTerminatedArray(szSrc);
+ if(!c)
+ {
+ QString ret;
+ return ret;
+ }
+ QChar * buffer = (QChar *)kvi_malloc(sizeof(QChar) * szSrc.length());
+ QChar * b = buffer;
+ unsigned short us = c->unicode();
+ while(us)
+ {
+ if(us < 256)
+ *b=QChar((unsigned short)iso88591_toUpper_map[us]);
+ else
+ *b = *c;
+ c++;
+ b++;
+ us = c->unicode();
+ }
+ QString ret(buffer,szSrc.length());
+ kvi_free(buffer);
+ return ret;
+ }
+
+ QString lowerISO88591(const QString &szSrc)
+ {
+ const QChar * c = nullTerminatedArray(szSrc);
+ if(!c)
+ {
+ QString ret;
+ return ret;
+ }
+ QChar * buffer = (QChar *)kvi_malloc(sizeof(QChar) * szSrc.length());
+ QChar * b = buffer;
+ unsigned short us = c->unicode();
+ while(us)
+ {
+ if(us < 256)
+ {
+ *b=QChar((unsigned short)iso88591_toLower_map[us]);
+ } else
+ *b = *c;
+ c++;
+ b++;
+ us = c->unicode();
+ }
+ QString ret(buffer,szSrc.length());
+ kvi_free(buffer);
+ return ret;
+ }
+
+ void transliterate(QString &s,const QString &szToFind,const QString &szReplacement)
+ {
+ int i=0;
+ int il = MY_MIN(szToFind.length(),szReplacement.length());
+ while(i < il)
+ {
+ int k=0;
+ int kl = s.length();
+ while(k < kl)
+ {
+ if(s[k] == szToFind[i])s[k] = szReplacement[i];
+ k++;
+ }
+ i++;
+ }
+ }
+
+ static char hexdigits[16] = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' };
+
+ void bufferToHex(QString &szRetBuffer,const unsigned char * buffer,unsigned int len)
+ {
+#ifdef COMPILE_USE_QT4
+ szRetBuffer.resize(len * 2);
+#else
+ szRetBuffer.setLength(len * 2);
+#endif
+ unsigned int i=0;
+ while(i < (len*2))
+ {
+ szRetBuffer[int(i)] = QChar( (unsigned int) hexdigits[(*buffer) / 16] );
+ i++;
+ szRetBuffer[int(i)] = QChar( (unsigned int)hexdigits[(*buffer) % 16] );
+ i++;
+ buffer++;
+ }
+ }
+};
diff --git a/src/kvilib/core/kvi_qstring.h b/src/kvilib/core/kvi_qstring.h
new file mode 100644
index 00000000..c82063e9
--- /dev/null
+++ b/src/kvilib/core/kvi_qstring.h
@@ -0,0 +1,293 @@
+#ifndef _KVI_QSTRING_H_
+#define _KVI_QSTRING_H_
+
+//=============================================================================
+//
+// File : kvi_qstring.h
+// Creation date : Mon Aug 04 2003 13:36:33 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003-2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+//=============================================================================
+//
+// Helper functions for the QString class
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_inttypes.h"
+#include "kvi_stdarg.h"
+#include "kvi_qcstring.h"
+
+#include <qstring.h>
+
+///
+/// \namespace KviQString
+///
+/// \brief A namespace for QString helper functions
+///
+/// This namespace contains several helper functions
+/// that are used when dealing with QString.
+///
+namespace KviQString
+{
+ extern KVILIB_API QString makeSizeReadable(size_t size);
+ extern KVILIB_API bool equalCS(const QString &sz1,const QString &sz2);
+ extern KVILIB_API bool equalCI(const QString &sz1,const QString &sz2);
+ extern KVILIB_API bool equalCS(const QString &sz1,const char * sz2);
+ extern KVILIB_API bool equalCI(const QString &sz1,const char * sz2);
+ // sz2 is assumed to be null terminated here!
+ extern KVILIB_API bool equalCI(const QString &sz1,const QChar * sz2);
+ inline bool equalCS(const char * sz1,const QString &sz2)
+ { return equalCS(sz2,sz1); };
+ inline bool equalCI(const char * sz1,const QString &sz2)
+ { return equalCI(sz2,sz1); };
+ // sz1 is assumed to be null terminated here!
+ inline bool equalCI(const QChar * sz1,const QString &sz2)
+ { return equalCI(sz2,sz1); };
+
+ extern KVILIB_API bool equalCSN(const QString &sz1,const QString &sz2,unsigned int len);
+ extern KVILIB_API bool equalCIN(const QString &sz1,const QString &sz2,unsigned int len);
+ extern KVILIB_API bool equalCSN(const QString &sz1,const char * sz2,unsigned int len);
+ extern KVILIB_API bool equalCIN(const QString &sz1,const char * sz2,unsigned int len);
+ // sz2 is assumed to be null terminated here!
+ extern KVILIB_API bool equalCIN(const QString &sz1,const QChar * sz2,unsigned int len);
+ inline bool equalCSN(const char * sz1,const QString &sz2,unsigned int len)
+ { return equalCSN(sz2,sz1,len); };
+ inline bool equalCIN(const char * sz1,const QString &sz2,unsigned int len)
+ { return equalCIN(sz2,sz1,len); };
+ // sz1 is assumed to be null terminated here!
+ inline bool equalCIN(const QChar * sz1,const QString &sz2,unsigned int len)
+ { return equalCIN(sz2,sz1,len); };
+
+ //note that greater here means that come AFTER in the alphabetic order
+ // return < 0 ---> str1 < str2
+ // return = 0 ---> str1 = str2
+ // return > 0 ---> str1 > str2
+ extern KVILIB_API int cmpCI(const QString &sz1,const QString &sz2);
+ extern KVILIB_API int cmpCIN(const QString &sz1,const QString &sz2,unsigned int len);
+ extern KVILIB_API int cmpCS(const QString &sz1,const QString &sz2);
+
+ extern KVILIB_API void detach(QString &sz);
+
+ // this makes the QString sz appear as a null terminated array
+ // it MAY RETURN 0 when the QString is null!
+ extern KVILIB_API const QChar * nullTerminatedArray(const QString &sz);
+
+ inline bool lastCharIs(QString &szString,const QChar &c)
+ { return szString.endsWith(c); };
+
+ extern KVILIB_API void ensureLastCharIs(QString &szString,const QChar &c);
+
+ // wild expression matching
+ extern KVILIB_API bool matchWildExpressionsCI(const QString &szM1,const QString &szM2);
+ // wild or regexp matching
+ extern KVILIB_API bool matchStringCI(const QString &szExp,const QString &szStr,bool bIsRegExp = false,bool bExact = false);
+ extern KVILIB_API bool matchStringCS(const QString &szExp,const QString &szStr,bool bIsRegExp = false,bool bExact = false);
+
+ extern KVILIB_API void vsprintf(QString &s,const QString &szFmt,kvi_va_list list);
+ extern KVILIB_API QString & sprintf(QString &s,const QString &szFmt,...);
+ extern KVILIB_API void stripRightWhiteSpace(QString &s);
+ extern KVILIB_API void stripLeft(QString &s,const QChar &c);
+ extern KVILIB_API void stripRight(QString &s,const QChar &c);
+ extern KVILIB_API void appendFormatted(QString &s,const QString &szFmt,...);
+ extern KVILIB_API void appendNumber(QString &s,double dReal);
+ extern KVILIB_API void appendNumber(QString &s,kvi_i64_t iInteger);
+ extern KVILIB_API void appendNumber(QString &s,int iInteger);
+ extern KVILIB_API void appendNumber(QString &s,unsigned int uInteger);
+ extern KVILIB_API void appendNumber(QString &s,kvi_u64_t uInteger);
+
+ extern KVILIB_API void cutFromFirst(QString &s,const QChar &c,bool bIncluded = true);
+ extern KVILIB_API void cutFromLast(QString &s,const QChar &c,bool bIncluded = true);
+ extern KVILIB_API void cutToFirst(QString &s,const QChar &c,bool bIncluded = true,bool bClearIfNotFound = false);
+ extern KVILIB_API void cutToLast(QString &s,const QChar &c,bool bIncluded = true,bool bClearIfNotFound = false);
+ extern KVILIB_API void cutFromFirst(QString &s,const QString &c,bool bIncluded = true);
+ extern KVILIB_API void cutFromLast(QString &s,const QString &c,bool bIncluded = true);
+ extern KVILIB_API void cutToFirst(QString &s,const QString &c,bool bIncluded = true,bool bClearIfNotFound = false);
+ extern KVILIB_API void cutToLast(QString &s,const QString &c,bool bIncluded = true,bool bClearIfNotFound = false);
+
+ extern KVILIB_API QString upperISO88591(const QString &szSrc);
+ extern KVILIB_API QString lowerISO88591(const QString &szSrc);
+ extern KVILIB_API QString getToken(QString &szString,const QChar &sep);
+
+ extern KVILIB_API void transliterate(QString &s,const QString &szToFind,const QString &szReplacement);
+
+ extern KVILIB_API void bufferToHex(QString &szRetBuffer,const unsigned char * buffer,unsigned int len);
+
+ // a global empty string (note that this is ALSO NULL under Qt 3.x)
+ extern KVILIB_API const QString empty;
+
+ ///
+ /// A portability wrapper which with Qt3 and Qt4.
+ /// Returns a lowcase version of the parameter string.
+ ///
+ inline QString toLower(const QString &s)
+ {
+#ifdef COMPILE_USE_QT4
+ return s.toLower();
+#else
+ return s.lower();
+#endif
+ }
+
+ inline int find(const QString &s,QChar c,int index = 0,bool cs = true)
+ {
+#ifdef COMPILE_USE_QT4
+ return s.indexOf(c,index,cs ? Qt::CaseSensitive : Qt::CaseInsensitive);
+#else
+ return s.find(c,index,cs);
+#endif
+ }
+
+ inline int find(const QString &s,char c,int index = 0,bool cs = true)
+ {
+#ifdef COMPILE_USE_QT4
+ return s.indexOf(c,index,cs ? Qt::CaseSensitive : Qt::CaseInsensitive);
+#else
+ return s.find(c,index,cs);
+#endif
+ }
+
+ inline int find(const QString &s,const QString & str,int index = 0,bool cs = true)
+ {
+#ifdef COMPILE_USE_QT4
+ return s.indexOf(str,index,cs ? Qt::CaseSensitive : Qt::CaseInsensitive);
+#else
+ return s.find(str,index,cs);
+#endif
+ }
+
+ inline int find(const QString &s,const QRegExp & rx,int index = 0)
+ {
+#ifdef COMPILE_USE_QT4
+ return s.indexOf(rx,index);
+#else
+ return s.find(rx,index);
+#endif
+ }
+
+ inline int find(const QString &s,const char * str,int index = 0)
+ {
+#ifdef COMPILE_USE_QT4
+ return s.indexOf(QString(str),index);
+#else
+ return s.find(str,index);
+#endif
+ }
+
+ inline int findRev(const QString &s,QChar c,int index = -1,bool cs = true)
+ {
+#ifdef COMPILE_USE_QT4
+ return s.lastIndexOf(c,index,cs ? Qt::CaseSensitive : Qt::CaseInsensitive);
+#else
+ return s.findRev(c,index,cs);
+#endif
+ }
+
+ inline int findRev(const QString &s,char c,int index = -1,bool cs = true)
+ {
+#ifdef COMPILE_USE_QT4
+ return s.lastIndexOf(c,index,cs ? Qt::CaseSensitive : Qt::CaseInsensitive);
+#else
+ return s.findRev(c,index,cs);
+#endif
+ }
+
+ inline int findRev(const QString &s,const QString & str,int index = -1,bool cs = true)
+ {
+#ifdef COMPILE_USE_QT4
+ return s.lastIndexOf(str,index,cs ? Qt::CaseSensitive : Qt::CaseInsensitive);
+#else
+ return s.findRev(str,index,cs);
+#endif
+ }
+
+ inline int findRev(const QString &s,const QRegExp & rx,int index = -1)
+ {
+#ifdef COMPILE_USE_QT4
+ return s.lastIndexOf(rx,index);
+#else
+ return s.findRev(rx,index);
+#endif
+ }
+
+ inline int findRev(const QString &s,const char * str,int index = -1)
+ {
+#ifdef COMPILE_USE_QT4
+ return s.lastIndexOf(QString(str),index);
+#else
+ return s.findRev(str,index);
+#endif
+ }
+
+ inline QString trimmed(const QString &s)
+ {
+#ifdef COMPILE_USE_QT4
+ return s.trimmed();
+#else
+ return s.stripWhiteSpace();
+#endif
+ }
+
+ // WARNING: DO NOT USE CONSTRUCTS LIKE char * c = KviQString::toUtf8(something).data();
+ // They are dangerous since with many compilers the returned string gets destroyed
+ // at the end of the instruction and the c pointer gets thus invalidated.
+ // Use
+ // KviQCString tmp = KviQString::toUtf8(something);
+ // char * c = tmp.data();
+ // instead.
+ // Yes, I know that it sucks, but it's the only way to
+ // transit to qt 4.x more or less cleanly...
+ inline KviQCString toUtf8(const QString &s)
+ {
+#ifdef COMPILE_USE_QT4
+ return s.toUtf8();
+#else
+ return s.utf8();
+#endif
+ }
+
+ inline KviQCString toLocal8Bit(const QString &s)
+ {
+ return s.local8Bit();
+ }
+
+ inline kvi_i64_t toI64(QString &szNumber,bool * bOk)
+ {
+#if SIZEOF_LONG_INT == 8
+ return szNumber.toLong(bOk);
+#else
+ return szNumber.toLongLong(bOk);
+#endif
+ }
+
+ inline kvi_u64_t toU64(QString &szNumber,bool * bOk)
+ {
+#if SIZEOF_LONG_INT == 8
+ return szNumber.toULong(bOk);
+#else
+ return szNumber.toULongLong(bOk);
+#endif
+ }
+};
+
+// QT4SUX: Because QString::null is gone. QString() is SLOWER than QString::null since it invokes a constructor and destructor.
+
+#endif //!_KVI_QSTRING_H_
diff --git a/src/kvilib/core/kvi_strasm.h b/src/kvilib/core/kvi_strasm.h
new file mode 100644
index 00000000..5d3b19ca
--- /dev/null
+++ b/src/kvilib/core/kvi_strasm.h
@@ -0,0 +1,194 @@
+#ifndef _KVI_STRASM_H_
+#define _KVI_STRASM_H_
+
+//=============================================================================
+//
+// File : kvi_strasm.h
+// Creation date : Sun Jun 18 2000 18:38:26 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+//=============================================================================
+//
+// Inline assembly implementations of the commonly used string functions
+// These will work only on i386 based machines and can be compiled
+// only by gcc
+//
+//=============================================================================
+
+extern inline bool kvi_strEqualCS(const char * str1,const char * str2)
+{
+ // An instruction pattern is really useful in this case.
+ // When inlining, GCC can optimize to load esi and edi
+ // directly with the strings , without pushing and getting it
+ // from the stack...
+ register bool eax;
+ __asm__ __volatile__ (
+ " cld\n"
+ "1:\n"
+ " lodsb %%ds:(%%esi),%%al\n"
+ " scasb %%es:(%%edi),%%al\n"
+ " jne 2f\n"
+ " testb %%al,%%al\n"
+ " jne 1b\n"
+ " movl $0x1,%%eax\n"
+ " jmp 3f\n"
+ "2:\n"
+ " xorl %%eax,%%eax\n"
+ "3:"
+ : "=a" (eax), "=&S" (str1), "=&D" (str2)
+ : "1" (str1), "2" (str2)
+ );
+ return eax;
+}
+
+extern inline bool kvi_strEqualCSN(const char * str1,const char * str2,int len)
+{
+ register bool eax;
+ __asm__ __volatile__ (
+ "1:\n"
+ " decl %3\n"
+ " js 2f\n"
+ " movb (%1),%%al\n"
+ " incl %1\n"
+ " cmpb %%al,(%2)\n"
+ " jne 3f\n"
+ " incl %2\n"
+ " testb %%al,%%al\n"
+ " jne 1b\n"
+ "2:\n"
+ " movl $0x1,%%eax\n"
+ " jmp 4f\n"
+ "3:\n"
+ " xorl %%eax,%%eax\n"
+ "4:\n"
+ : "=a" (eax), "=r" (str1), "=r" (str2), "=r" (len)
+ : "1" (str1), "2" (str2), "3" (len)
+ );
+ return eax;
+}
+
+// OPTIMIZATION
+// The following two functions are used to compare a variable string with one in that
+// only A-Z<->a-z case insensivity is significant.
+// For example
+// kvi_strEqualNoLocalCI("a string that does not contain any strange char",str2)
+// will always give the correct result
+// These will NOT work with localizable characters:
+// 'a' with umlaut will be not equal to 'A' with umlaut
+
+extern inline bool kvi_strEqualNoLocaleCI(const char *str1,const char *str2)
+{
+ // Trivial implementation
+ // Ignores completely locales....only A-Z chars are transformed to a-z
+ // Anyway...it will work for IRC :)
+ register int reg;
+ register bool eax;
+ __asm__ __volatile__ (
+ "1:\n"
+ " movb (%2),%%al\n"
+ " cmpb $65,%%al\n"
+ " jb 2f\n"
+ " cmpb $90,%%al\n"
+ " ja 2f\n"
+ " addb $32,%%al\n"
+ "2:\n"
+ " movb (%3),%b1\n"
+ " cmpb $65,%b1\n"
+ " jb 3f\n"
+ " cmpb $90,%b1\n"
+ " ja 3f\n"
+ " addb $32,%b1\n"
+ "3:\n"
+ " cmpb %%al,%b1\n"
+ " jne 4f\n"
+ " incl %2\n"
+ " incl %3\n"
+ " testb %%al,%%al\n"
+ " jne 1b\n"
+ " movl $1,%%eax\n"
+ " jmp 5f\n"
+ "4:\n"
+ " xorl %%eax,%%eax\n"
+ "5:\n"
+ : "=a" (eax), "=q" (reg), "=r" (str1), "=r" (str2)
+ : "2" (str1), "3" (str2)
+ );
+ return eax;
+}
+
+extern inline bool kvi_strEqualNoLocaleCIN(const char *str1,const char *str2,int len)
+{
+
+ register int reg;
+ register bool eax;
+ __asm__ __volatile__ (
+ "1:\n"
+ " decl %4\n"
+ " js 4f\n"
+ " movb (%2),%%al\n"
+ " cmpb $65,%%al\n"
+ " jb 2f\n"
+ " cmpb $90,%%al\n"
+ " ja 2f\n"
+ " addb $32,%%al\n"
+ "2:\n"
+ " movb (%3),%b1\n"
+ " cmpb $65,%b1\n"
+ " jb 3f\n"
+ " cmpb $90,%b1\n"
+ " ja 3f\n"
+ " addb $32,%b1\n"
+ "3:\n"
+ " cmpb %%al,%b1\n"
+ " jne 5f\n"
+ " incl %2\n"
+ " incl %3\n"
+ " testb %%al,%%al\n"
+ " jne 1b\n"
+ "4:\n"
+ " movl $1,%%eax\n"
+ " jmp 6f\n"
+ "5:\n"
+ " xorl %%eax,%%eax\n"
+ "6:\n"
+ : "=a" (eax), "=q" (reg), "=r" (str1), "=r" (str2), "=r" (len)
+ : "2" (str1), "3" (str2), "4" (len)
+ );
+ return eax;
+}
+
+
+extern inline int kvi_strLen(const char * str)
+{
+ register int ecx;
+ __asm__ __volatile__(
+ " cld\n"
+ " repne\n"
+ " scasb\n"
+ " notl %0\n"
+ " decl %0"
+ : "=c" (ecx), "=&D" (str)
+ : "0" (0xffffffff), "1" (str), "a" (0)
+ );
+ return ecx;
+}
+
+#endif //_KVI_STRASM_H_
diff --git a/src/kvilib/core/kvi_string.cpp b/src/kvilib/core/kvi_string.cpp
new file mode 100644
index 00000000..3f201352
--- /dev/null
+++ b/src/kvilib/core/kvi_string.cpp
@@ -0,0 +1,3063 @@
+//=============================================================================
+//
+// File : kvi_string.cpp
+// Creation date : Fri Mar 19 1999 03:20:45 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+
+
+#define _KVI_DEBUG_CHECK_RANGE_
+#include "kvi_debug.h"
+
+#define _KVI_STRING_CPP_
+#include "kvi_string.h"
+
+#include "kvi_memmove.h"
+#include "kvi_malloc.h"
+
+#include "kvi_qstring.h"
+
+kvi_wslen_t kvi_wstrlen(const kvi_wchar_t * str)
+{
+ const kvi_wchar_t * ptr = str;
+ while(*ptr)ptr++;
+ return (ptr - str);
+}
+
+
+// %s = Latin1 char string (can't be null)
+// %d = signed int (short,char)
+// %u = unsigned int (short,char)
+// %c = char value (kvi_wchar_t value)
+
+// %f = double value
+
+// %w = kvi_wchar_t string (can't be null)
+
+// %S = Latin1 KviStr pointer (#ifdef WSTRINGCONFIG_USE_KVISTR) : can't be NULL!
+// %W = KviWStr pointer : can't be NULL!
+// %Q = QString pointer : can't be NULL!
+
+#define _WSTRING_WMEMCPY(_dst,_src,_len) kvi_fastmoveodd((void *)(_dst),(const void *)(_src),sizeof(kvi_wchar_t) * (_len))
+#define _WSTRING_STRLEN(_str) kvi_strLen(_str)
+
+#define WVSNPRINTF_BODY \
+\
+ register kvi_wchar_t *p; \
+ long int argValue; \
+ unsigned long argUValue; \
+\
+ kvi_wchar_t numberBuffer[32]; \
+ kvi_wchar_t *pNumBuf; \
+ unsigned int tmp; \
+\
+ for(p=buffer ; *fmt ; ++fmt) \
+ { \
+ if(len < 1)return (-1); \
+\
+ if(*fmt != '%') \
+ { \
+ *p++ = *fmt; \
+ --len; \
+ continue; \
+ } \
+\
+ ++fmt; \
+\
+ switch(*fmt) \
+ { \
+ case 's': \
+ { \
+ char * argString = kvi_va_arg(list,char *); \
+ argValue = (int)_WSTRING_STRLEN(argString); \
+ if(len <= argValue)return (-1); \
+ while(*argString)*p++ = *argString++; \
+ len -= argValue; \
+ } \
+ break; \
+ case 'S': \
+ { \
+ KviStr * pString = kvi_va_arg(list,KviStr *); \
+ char * argString = pString->ptr(); \
+ if(len <= ((int)(pString->len())))return (-1); \
+ while(*argString)*p++ = *argString++; \
+ len -= pString->len(); \
+ } \
+ break; \
+ case 'Q': \
+ { \
+ QString * pString = kvi_va_arg(list,QString *); \
+ if(pString->length() > 0) \
+ { \
+ if(len <= ((int)(pString->length())))return (-1); \
+ _WSTRING_WMEMCPY(p,pString->unicode(),pString->length()); \
+ p += pString->length(); \
+ len -= pString->length(); \
+ } \
+ } \
+ break; \
+ case 'd': \
+ argValue = kvi_va_arg(list,int); \
+ if(argValue < 0) \
+ { \
+ *p++ = '-'; \
+ if(--len == 0)return (-1); \
+ argValue = -argValue; \
+ if(argValue < 0)argValue = 0; \
+ } \
+ pNumBuf = numberBuffer; \
+ do { \
+ tmp = argValue / 10; \
+ *pNumBuf++ = argValue - (tmp * 10) + '0'; \
+ } while((argValue = tmp)); \
+ argUValue = pNumBuf - numberBuffer; \
+ if(((unsigned int)len) <= argUValue)return (-1); \
+ do { \
+ *p++ = *--pNumBuf; \
+ } while(pNumBuf != numberBuffer); \
+ len -= argUValue; \
+ break; \
+ case 'u': \
+ argUValue = kvi_va_arg(list,unsigned int); \
+ pNumBuf = numberBuffer; \
+ do { \
+ tmp = argUValue / 10; \
+ *pNumBuf++ = argUValue - (tmp * 10) + '0'; \
+ } while((argUValue = tmp)); \
+ argValue = pNumBuf - numberBuffer; \
+ if(len <= argValue)return (-1); \
+ do { \
+ *p++ = *--pNumBuf; \
+ } while(pNumBuf != numberBuffer); \
+ len -= argValue; \
+ break; \
+ case 'f': \
+ { \
+ double dVal = (double)kvi_va_arg(list,double); \
+ char sprintfBuffer[32]; \
+ argValue = sprintf(sprintfBuffer,"%f",dVal); \
+ if(len <= argValue)return (-1); \
+ char * pSprintfBuffer = sprintfBuffer; \
+ while(*pSprintfBuffer)*p++ = *pSprintfBuffer++; \
+ len -= argValue; \
+ } \
+ break; \
+ case 'c': \
+ *p++ = (kvi_wchar_t)kvi_va_arg(list,int); \
+ --len; \
+ break; \
+ default: \
+ *p++ = '%'; \
+ if(--len == 0)return (-1); \
+ if(*fmt){ \
+ *p++ = *fmt; \
+ --len; \
+ } \
+ break; \
+ } \
+ continue; \
+ } \
+ if(len < 1)return (-1); \
+ *p = 0; \
+ return p-buffer;
+
+int kvi_wvsnprintcf(kvi_wchar_t *buffer,kvi_wslen_t len,const char *fmt,kvi_va_list list)
+{
+ WVSNPRINTF_BODY
+}
+
+int kvi_wvsnprintf(kvi_wchar_t *buffer,kvi_wslen_t len,const kvi_wchar_t *fmt,kvi_va_list list)
+{
+ WVSNPRINTF_BODY
+}
+
+bool kvi_qstringEqualCI(const QString &s1,const QString &s2)
+{
+ const QChar * p1 = s1.unicode();
+ const QChar * p2 = s2.unicode();
+ int l = s1.length() < s2.length() ? s1.length() : s2.length();
+#ifdef COMPILE_USE_QT4
+ while(l-- && (p1->toLower() == p2->toLower()))p1++,p2++;
+#else
+ while(l-- && (p1->lower() == p2->lower()))p1++,p2++;
+#endif
+ if(l==-1)return true;
+ return false;
+}
+
+bool kvi_matchStringCI(register const char * exp,register const char * str)
+{
+ // a
+ // .
+ // exp = a*x?mem*a
+ // str = arexoxmexamemizazv
+ // .
+ // n
+ const char * afterWild = 0;
+ const char * nextStrToCheck = 0;
+
+ while(*exp)
+ {
+ if(*exp == '*')
+ {
+ // exp is a wildcard...
+ afterWild = ++exp;
+ nextStrToCheck = str + 1;
+ if(!(*exp))return true; // and it's the last char in the string: matches everything ahead
+ continue;
+ }
+
+ if(!(*str))return false; // str finished but we had something to match :(
+
+ if(tolower(*exp) == tolower(*str))
+ {
+ // chars matched
+ ++exp;
+ ++str;
+ if((!(*exp)) && *str)goto check_recovery;
+ continue;
+ }
+
+ if(*exp == '?')
+ {
+ // any-char wildcard
+ ++exp;
+ ++str;
+ continue;
+ }
+
+check_recovery:
+ // chars unmatched!!!
+ if(afterWild)
+ {
+ // we had a wildcard in exp...
+ // let's use this jolly then
+ exp = afterWild;
+ str = nextStrToCheck;
+ nextStrToCheck++;
+ // and try to compare now
+ continue;
+ }
+
+ return false; // no match :(
+ }
+ return (!(*str));
+}
+
+
+bool kvi_matchStringCS(register const char * exp,register const char * str)
+{
+ // a
+ // .
+ // exp = a*x?mem*a
+ // str = arexoxmexamemizazv
+ // .
+ // n
+ const char * afterWild = 0;
+ const char * nextStrToCheck = 0;
+
+ while(*exp)
+ {
+ if(*exp == '*')
+ {
+ // exp is a wildcard...
+ afterWild = ++exp;
+ nextStrToCheck = str + 1;
+ if(!(*exp))return true; // and it's the last char in the string: matches everything ahead
+ continue;
+ }
+
+ if(!(*str))return false; // str finished but we had something to match :(
+
+ if(*exp == *str)
+ {
+ // chars matched
+ ++exp;
+ ++str;
+ if((!(*exp)) && *str)goto check_recovery;
+ continue;
+ }
+
+ if(*exp == '?')
+ {
+ // any-char wildcard
+ ++exp;
+ ++str;
+ continue;
+ }
+
+check_recovery:
+ // chars unmatched!!!
+ if(afterWild)
+ {
+ // we had a wildcard in exp...
+ // let's use this jolly then
+ exp = afterWild;
+ str = nextStrToCheck;
+ nextStrToCheck++;
+ // and try to compare now
+ continue;
+ }
+
+ return false; // no match :(
+ }
+ return (!(*str));
+}
+
+
+
+bool kvi_matchStringWithTerminator(register const char * exp,register const char * str,char terminator,const char ** r1,const char ** r2)
+{
+#define NOT_AT_END(__str) (*__str && (*__str != terminator))
+
+ // a
+ // .
+ // exp = a*x?mem*a
+ // str = arexoxmexamemizazv
+ // .
+ // n
+ const char * afterWild = 0;
+ const char * nextStrToCheck = 0;
+
+ while(NOT_AT_END(exp))
+ {
+ if(*exp == '*')
+ {
+ // exp is a wildcard...
+ afterWild = ++exp;
+ nextStrToCheck = str + 1;
+ if(!(NOT_AT_END(exp)))
+ {
+ while(NOT_AT_END(str))str++;
+ *r1 = exp;
+ *r2 = str;
+ return true; // and it's the last char in the string: matches everything ahead
+ }
+ continue;
+ }
+
+ if(!(*str))return false; // str finished but we had something to match :(
+
+ if(tolower(*exp) == tolower(*str))
+ {
+ // chars matched
+ ++exp;
+ ++str;
+ if((!(NOT_AT_END(exp))) && NOT_AT_END(str))goto check_recovery;
+ continue;
+ }
+
+ if(*exp == '?')
+ {
+ // any-char wildcard
+ ++exp;
+ ++str;
+ continue;
+ }
+
+check_recovery:
+ // chars unmatched!!!
+ if(afterWild)
+ {
+ // we had a wildcard in exp...
+ // let's use this jolly then
+ exp = afterWild;
+ str = nextStrToCheck;
+ nextStrToCheck++;
+ // and try to compare now
+ continue;
+ }
+
+ return false; // no match :(
+ }
+ *r1 = exp;
+ *r2 = str;
+ return (!(NOT_AT_END(str)));
+
+#undef NOT_AT_END
+}
+
+bool kvi_matchWildExpr(register const char *m1,register const char *m2)
+{
+ //Matches two regular expressions containging wildcards (* and ?)
+
+ // s1
+ // m1
+ // mask1 : *xor
+ // mask2 : xorand*xor
+ // m2
+ // s2
+
+ // s2
+ // m2
+ // |
+ // XorT!xor@111.111.111.11
+ //
+ // *!*@*.net
+ // |
+ // m1
+ // s1
+ //
+
+ if(!(m1 && m2 && (*m1)))return false;
+ const char * savePos1 = 0;
+ const char * savePos2 = m2;
+ while(*m1)
+ {
+ //loop managed by m1 (initially first mask)
+ if(*m1=='*')
+ {
+ //Found a wildcard in m1
+ savePos1 = ++m1; //move to the next char and save the position...this is our jolly
+ if(!*savePos1)return true; //last was a wildcard , matches everything ahead...
+ savePos2 = m2+1; //next return state for the second string
+ continue; //and return
+ }
+ if(!(*m2))return false; //m2 finished and we had something to match here!
+ if(tolower(*m1)==tolower(*m2))
+ {
+ //chars matched
+ m1++; //Go ahead in the two strings
+ m2++; //
+ if((!(*m1)) && *m2 && savePos1)
+ {
+ //m1 finished , but m2 not yet and we have a savePosition for m1 (there was a wildcard)...
+ //retry matching the string following the * from the savePos2 (one char ahead last time)
+ m1 = savePos1; //back to char after wildcard
+ m2 = savePos2; //back to last savePos2
+ savePos2++; //next savePos2 will be next char
+ }
+ } else {
+ if(*m2 == '*')
+ {
+ //A wlidcard in the second string
+ //Invert the game : mask1 <-> mask2
+ //mask2 now leads the game...
+ savePos1 = m1; //aux
+ m1 = m2; //...swap
+ m2 = savePos1; //...swap
+ savePos1 = m1; //sync save pos1
+ savePos2 = m2 + 1; //sync save pos2
+ continue; //...and again
+ }
+ // m1 != m2 , m1 != * , m2 != *
+ if((*m1 == '?') || (*m2 == '?'))
+ {
+ m1++;
+ m2++;
+ if((!(*m1)) && *m2 && savePos1)
+ {
+ //m1 finished , but m2 not yet and we have a savePosition for m1 (there was a wildcard)...
+ //retry matching the string following the * from the savePos2 (one char ahead last time)
+ m1 = savePos1; //back to char after wildcard
+ m2 = savePos2; //back to last savePos2
+ savePos2++; //next savePos2 will be next char
+ }
+ } else {
+ if(savePos1)
+ {
+ //Have a jolly man...allow not matching...
+ m1 = savePos1; //go back to char after wildcard...need to rematch...
+ m2 = savePos2; //back to last savePos2
+ savePos2++; //and set next savePos2
+ } else return false; //No previous wildcards...not matched!
+ }
+ }
+ }
+ return (!(*m2)); //m1 surely finished , so for the match , m2 must be finished too
+
+}
+
+/*
+
+ WARNING: Don't remove: working code but actually unused in KVIrc
+ Later it might become useful
+
+bool kvi_matchWildExprCS(register const char *m1,register const char *m2)
+{
+ if(!(m1 && m2 && (*m1)))return false;
+ const char * savePos1 = 0;
+ const char * savePos2 = m2;
+ while(*m1){ //loop managed by m1 (initially first mask)
+ if(*m1=='*'){
+ //Found a wildcard in m1
+ savePos1 = ++m1; //move to the next char and save the position...this is our jolly
+ if(!*savePos1)return true; //last was a wildcard , matches everything ahead...
+ savePos2 = m2+1; //next return state for the second string
+ continue; //and return
+ }
+ if(!(*m2))return false; //m2 finished and we had something to match here!
+ if((*m1)==(*m2)){
+ //chars matched
+ m1++; //Go ahead in the two strings
+ m2++; //
+ if((!(*m1)) && *m2 && savePos1){
+ //m1 finished , but m2 not yet and we have a savePosition for m1 (there was a wildcard)...
+ //retry matching the string following the * from the savePos2 (one char ahead last time)
+ m1 = savePos1; //back to char after wildcard
+ m2 = savePos2; //back to last savePos2
+ savePos2++; //next savePos2 will be next char
+ }
+ } else {
+ if(*m2 == '*'){
+ //A wlidcard in the second string
+ //Invert the game : mask1 <-> mask2
+ //mask2 now leads the game...
+ savePos1 = m1; //aux
+ m1 = m2; //...swap
+ m2 = savePos1; //...swap
+ savePos1 = m1; //sync save pos1
+ savePos2 = m2 + 1; //sync save pos2
+ continue; //...and again
+ }
+ if(savePos1){ //Have a jolly man...allow not matching...
+ m1 = savePos1; //go back to char after wildcard...need to rematch...
+ m2 = savePos2; //back to last savePos2
+ savePos2++; //and set next savePos2
+ } else return false; //No previous wildcards...not matched!
+ }
+ }
+ return (!(*m2)); //m1 surely finished , so for the match , m2 must be finished too
+
+}
+*/
+
+bool kvi_matchWildExprWithTerminator(register const char *m1,register const char *m2,char terminator,
+ const char ** r1,const char ** r2)
+{
+ //Matches two regular expressions containging wildcards
+
+#define NOT_AT_END(__str) (*__str && (*__str != terminator))
+
+ bool bSwapped = false;
+ if(!(m1 && m2 && (NOT_AT_END(m1))))return false;
+ const char * savePos1 = 0;
+ const char * savePos2 = m2;
+ while(NOT_AT_END(m1))
+ {
+ //loop managed by m1 (initially first mask)
+ if(*m1=='*')
+ {
+ //Found a wildcard in m1
+ savePos1 = ++m1; //move to the next char and save the position...this is our jolly
+ if(!NOT_AT_END(savePos1))
+ {
+ //last was a wildcard , matches everything ahead...
+ while(NOT_AT_END(m2))m2++;
+ *r1 = bSwapped ? m2 : m1;
+ *r2 = bSwapped ? m1 : m2;
+ return true;
+ }
+ savePos2 = m2+1; //next return state for the second string
+ continue; //and return
+ }
+ if(!NOT_AT_END(m2))return false; //m2 finished and we had something to match here!
+ if(tolower(*m1)==tolower(*m2))
+ {
+ //chars matched
+ m1++; //Go ahead in the two strings
+ m2++; //
+ if((!NOT_AT_END(m1)) && NOT_AT_END(m2) && savePos1)
+ {
+ //m1 finished , but m2 not yet and we have a savePosition for m1 (there was a wildcard)...
+ //retry matching the string following the * from the savePos2 (one char ahead last time)
+ m1 = savePos1; //back to char after wildcard
+ m2 = savePos2; //back to last savePos2
+ savePos2++; //next savePos2 will be next char
+ }
+ } else {
+ if(*m2 == '*')
+ {
+ //A wlidcard in the second string
+ //Invert the game : mask1 <-> mask2
+ //mask2 now leads the game...
+ bSwapped = !bSwapped;
+ savePos1 = m1; //aux
+ m1 = m2; //...swap
+ m2 = savePos1; //...swap
+ savePos1 = m1; //sync save pos1
+ savePos2 = m2 + 1; //sync save pos2
+ continue; //...and again
+ }
+ // m1 != m2 , m1 != * , m2 != *
+ if((*m1 == '?') || (*m2 == '?'))
+ {
+ m1++;
+ m2++;
+ if((!NOT_AT_END(m1)) && NOT_AT_END(m2) && savePos1)
+ {
+ //m1 finished , but m2 not yet and we have a savePosition for m1 (there was a wildcard)...
+ //retry matching the string following the * from the savePos2 (one char ahead last time)
+ m1 = savePos1; //back to char after wildcard
+ m2 = savePos2; //back to last savePos2
+ savePos2++; //next savePos2 will be next char
+ }
+ } else {
+ if(savePos1)
+ {
+ //Have a jolly man...allow not matching...
+ m1 = savePos1; //go back to char after wildcard...need to rematch...
+ m2 = savePos2; //back to last savePos2
+ savePos2++; //and set next savePos2
+ } else return false; //No previous wildcards...not matched!
+ }
+ }
+ }
+ *r1 = bSwapped ? m2 : m1;
+ *r2 = bSwapped ? m1 : m2;
+
+ return (!NOT_AT_END(m2)); //m1 surely finished , so for the match , m2 must be finished too
+
+#undef NOT_AT_END
+}
+
+
+
+const char * kvi_extractToken(KviStr &str,const char *aux_ptr,char sep)
+{
+ __range_valid(aux_ptr);
+ while(*aux_ptr && (*aux_ptr == sep))aux_ptr++;
+ const char *p=aux_ptr;
+ while(*p && (*p != sep))p++;
+ str.m_len=p-aux_ptr;
+ str.m_ptr = (char *)kvi_realloc(str.m_ptr,str.m_len+1);
+ kvi_fastmove(str.m_ptr,aux_ptr,str.m_len);
+ *(str.m_ptr+str.m_len)='\0';
+ while(*p && (*p == sep))p++;
+ return p;
+}
+
+const char * kvi_extractUpTo(KviStr &str,const char *aux_ptr,char sep)
+{
+ __range_valid(aux_ptr);
+ const char *p=aux_ptr;
+ while(*p && (*p != sep))p++;
+ str.m_len=p-aux_ptr;
+ str.m_ptr = (char *)kvi_realloc(str.m_ptr,str.m_len+1);
+ kvi_fastmove(str.m_ptr,aux_ptr,str.m_len);
+ *(str.m_ptr+str.m_len)='\0';
+ return p;
+}
+
+int kvi_vsnprintf(char *buffer,int len,const char *fmt,kvi_va_list list)
+{
+ __range_valid(fmt);
+ __range_valid(buffer);
+ __range_valid(len > 0); //printing 0 characters is senseless
+
+ register char *p;
+ char *argString;
+ long argValue;
+ unsigned long argUValue;
+
+ //9999999999999999999999999999999\0
+ char numberBuffer[32]; //enough ? 10 is enough for 32bit unsigned int...
+ char *pNumBuf;
+ unsigned int tmp;
+
+
+ for(p=buffer ; *fmt ; ++fmt)
+ {
+ if(len < 1)return (-1); //not enough space ... (in fact this could be len < 2 for the terminator)
+ //copy up to a '%'
+ if(*fmt != '%')
+ {
+ *p++ = *fmt;
+ --len;
+ continue;
+ }
+
+ ++fmt; //skip this '%'
+ switch(*fmt)
+ {
+ case 's': //string
+ argString = kvi_va_arg(list,char *);
+ if(!argString)continue;
+ argValue = (long)strlen(argString);
+ //check for space...
+ if(len <= argValue)return (-1); //not enough space for buffer and terminator
+ while(*argString)*p++ = *argString++;
+ len -= argValue;
+ continue;
+ case 'd': //signed integer
+ argValue = kvi_va_arg(list,int);
+ if(argValue < 0){ //negative integer
+ *p++ = '-';
+ if(--len == 0)return (-1);
+ argValue = -argValue; //need to have it positive
+ // most negative integer exception (avoid completely senseless (non digit) responses)
+ if(argValue < 0)argValue = 0; //we get -0 here
+ }
+ //write the number in a temporary buffer
+ pNumBuf = numberBuffer;
+ do {
+ tmp = argValue / 10;
+ *pNumBuf++ = argValue - (tmp * 10) + '0';
+ } while((argValue = tmp));
+ //copy now....
+ argUValue = pNumBuf - numberBuffer; //length of the number string
+ if(((uint)len) <= argUValue)return (-1); //not enough space for number and terminator
+ do { *p++ = *--pNumBuf; } while(pNumBuf != numberBuffer);
+ len -= argUValue;
+ continue;
+ case 'u': //unsigned integer
+ argUValue = kvi_va_arg(list,unsigned int); //many implementations place int here
+ //write the number in a temporary buffer
+ pNumBuf = numberBuffer;
+ do {
+ tmp = argUValue / 10;
+ *pNumBuf++ = argUValue - (tmp * 10) + '0';
+ } while((argUValue = tmp));
+ //copy now....
+ argValue = pNumBuf - numberBuffer; //length of the number string
+ if(len <= argValue)return (-1); //not enough space for number and terminator
+ do { *p++ = *--pNumBuf; } while(pNumBuf != numberBuffer);
+ len -= argValue;
+ continue;
+ case 'c': //char
+ //
+ // I'm not sure about this...
+ // In the linux kernel source the
+ // unsigned char is extracted from an integer type.
+ // We assume that gcc stacks a char argument
+ // as sizeof(int) bytes value.
+ // Is this always true ?
+ //
+ *p++ = (char)kvi_va_arg(list,int);
+ --len;
+ continue;
+ case 'Q': // QString! (this should almost never happen)
+ {
+ QString * s = kvi_va_arg(list,QString *);
+ KviQCString cs = KviQString::toUtf8(*s);
+ const char * t = cs.data();
+ if(!t)continue; // nothing to do
+ //check for space...
+ if(len <= (int)cs.length())return (-1); //not enough space for buffer and terminator
+ while(*t)*p++ = *t++;
+ len -= cs.length();
+ continue;
+ }
+ default: //a normal percent
+ *p++ = '%'; //write it
+ if(--len == 0)return (-1); //not enough space for next char or terminator
+ if(*fmt){ //this if is just in case that we have a % at the end of the string.
+ *p++ = *fmt; //and write this char
+ --len;
+ }
+ continue;
+ }
+ }
+ if(len < 1)return (-1); //missing space for terminator
+ *p = '\0';
+ return p-buffer;
+}
+
+//
+// Nearly the same as the above function...
+//
+
+int kvi_irc_vsnprintf(char *buffer,const char *fmt,kvi_va_list list,bool *bTruncated)
+{
+ __range_valid(fmt);
+ __range_valid(buffer);
+ if( !( buffer && fmt) ) return false;
+ register char *p;
+ char *argString;
+ long argValue;
+ unsigned long argUValue;
+ char numberBuffer[64]; //enough ? 10 is enough for 32bit unsigned int...
+ char *pNumBuf;
+ unsigned int tmp;
+ *bTruncated = false;
+ int len = 512;
+
+ for (p=buffer ; *fmt ; ++fmt) {
+ if(len < 3)goto truncate;
+ //copy up to a '%'
+ if (*fmt != '%') {
+ *p++ = *fmt;
+ --len;
+ continue;
+ }
+ ++fmt; //skip this '%'
+ switch(*fmt){
+ case 's': //string
+ argString = kvi_va_arg(list,char *);
+ if(!argString)continue;
+ //check for space...
+ while(*argString){
+ *p++ = *argString++;
+ if(--len < 3)goto truncate;
+ }
+ continue;
+ case 'Q': // QString! (this should almost never happen)
+ {
+ QString * s = kvi_va_arg(list,QString *);
+ KviQCString cs = KviQString::toUtf8(*s);
+ const char * t = cs.data();
+ if(!t)continue; // nothing to do
+ while(*t)
+ {
+ *p++ = *t++;
+ if(--len < 3)goto truncate;
+ }
+ continue;
+ }
+ case 'd': //signed integer
+ argValue = kvi_va_arg(list,int);
+ if(argValue < 0){ //negative integer
+ *p++ = '-';
+ if(--len < 3)goto truncate; //place just for CRLF
+ argValue = -argValue; //need to have it positive
+ if(argValue < 0)argValue = 0; // -0 (hack the exception)
+ }
+ //write the number in a temporary buffer
+ pNumBuf = numberBuffer;
+ do {
+ tmp = argValue / 10;
+ *pNumBuf++ = argValue - (tmp * 10) + '0';
+ } while((argValue = tmp));
+ //copy now....
+ do {
+ *p++ = *--pNumBuf;
+ if(--len < 3)goto truncate;
+ } while(pNumBuf != numberBuffer);
+ continue;
+ case 'u': //unsigned integer
+ argUValue = kvi_va_arg(list,unsigned int); //many implementations place int here
+ //write the number in a temporary buffer
+ pNumBuf = numberBuffer;
+ do {
+ tmp = argUValue / 10;
+ *pNumBuf++ = argUValue - (tmp * 10) + '0';
+ } while((argUValue = tmp));
+ //copy now....
+ if(--len < 3)goto truncate; //no place for digits
+ do {
+ *p++ = *--pNumBuf;
+ if(--len < 3)goto truncate;
+ } while(pNumBuf != numberBuffer);
+ continue;
+ case 'c': //char
+ *p++ = (char)kvi_va_arg(list,int);
+ --len;
+ continue;
+ default: //a normal percent
+ *p++ = '%'; //write it
+ if(--len < 3)goto truncate; //not enough space for next char
+ if(*fmt){ //this if is just in case that we have a % at the end of the string.
+ *p++ = *fmt; //and write this char
+ --len;
+ }
+ continue;
+ }
+ }
+ //succesfull finish
+ __range_valid(len >= 2);
+ *p++ = '\r';
+ *p = '\n';
+ return ((p-buffer)+1);
+truncate:
+ __range_valid(len >= 2);
+ *bTruncated = true;
+ *p++ = '\r';
+ *p = '\n';
+ return ((p-buffer)+1);
+}
+
+#ifndef COMPILE_ix86_ASM
+
+bool kvi_strEqualCS(const char *str1,const char *str2)
+{
+ __range_valid(str1);
+ __range_valid(str2);
+ if( !( str1 && str2 ) ) return false;
+ register unsigned char *s1 = (unsigned char *)str1;
+ register unsigned char *s2 = (unsigned char *)str2;
+ while(*s1)if(*s1++ != *s2++)return false;
+ return (*s1 == *s2);
+}
+
+bool kvi_strEqualCSN(const char *str1,const char *str2,int len)
+{
+ __range_valid(str1);
+ __range_valid(str2);
+ __range_valid(len >= 0);
+ if( !( str1 && str2 && (len >= 0) ) ) return false;
+ register unsigned char *s1 = (unsigned char *)str1;
+ register unsigned char *s2 = (unsigned char *)str2;
+ while(len-- && *s1)if(*s1++ != *s2++)return false;
+ return (len < 0);
+}
+
+#endif
+
+bool kvi_strEqualCIN(const char *str1,const char *str2,int len)
+{
+ __range_valid(str1);
+ __range_valid(str2);
+ __range_valid(len >= 0);
+ if( !( str1 && str2 && (len >= 0) ) ) return false;
+ register unsigned char *s1 = (unsigned char *)str1;
+ register unsigned char *s2 = (unsigned char *)str2;
+ while(len-- && *s1)if(tolower(*s1++) != tolower(*s2++))return false;
+ return (len < 0);
+}
+
+bool kvi_strEqualCI(const char *str1,const char *str2)
+{
+ __range_valid(str1);
+ __range_valid(str2);
+ if( !( str1 && str2) ) return false;
+ register unsigned char *s1 = (unsigned char *)str1;
+ register unsigned char *s2 = (unsigned char *)str2;
+ while(*s1)if(tolower(*s1++) != tolower(*s2++))return false;
+ return (*s1 == *s2);
+}
+
+//note that greater here means that come AFTER in the alphabetic order
+// return < 0 ---> str1 < str2
+// return = 0 ---> str1 = str2
+// return > 0 ---> str1 > str2
+int kvi_strcmpCI(const char *str1,const char *str2)
+{
+ //abcd abce
+ __range_valid(str1);
+ __range_valid(str2);
+ if( !( str1 && str2) ) return false;
+ register unsigned char *s1 = (unsigned char *)str1;
+ register unsigned char *s2 = (unsigned char *)str2;
+ int diff;
+ unsigned char rightchar;
+ while(!(diff=(rightchar=tolower(*s1++)) - tolower(*s2++)))if(!rightchar)break;
+ return diff; //diff is nonzero or end of both was reached (it is positive if *s2 > *s1
+}
+
+//
+////note that greater here means that come AFTER in the alphabetic order
+//// return < 0 ---> str1 < str2
+//// return = 0 ---> str1 = str2
+//// return > 0 ---> str1 > str2
+//int kvi_strcmpCIN(const char *str1,const char *str2,int len)
+//{
+// //abcd abce
+// __range_valid(str1);
+// __range_valid(str2);
+// register unsigned char *s1 = (unsigned char *)str1;
+// register unsigned char *s2 = (unsigned char *)str2;
+// int diff;
+// unsigned char rightchar;
+// while(len--)
+// {
+// if(!(diff=(rightchar=tolower(*s1++)) - tolower(*s2++)))break;
+// if(!rightchar)break;
+// }
+// return diff; //diff is nonzero or end of both was reached (it is positive if *s2 > *s1
+//}
+
+int kvi_strcmpCS(const char *str1,const char *str2)
+{
+ //abcd abce
+ __range_valid(str1);
+ __range_valid(str2);
+ if( !( str1 && str2) ) return false;
+ register unsigned char *s1 = (unsigned char *)str1;
+ register unsigned char *s2 = (unsigned char *)str2;
+ int diff;
+ while(!(diff=(*s1)-(*s2++)))if(!*s1++)break;
+ return diff; //diff is nonzero or end of both was reached (it is positive if *s2 > *s1
+}
+
+int kvi_strMatchRevCS(const char *str1, const char *str2, int index)
+{
+ __range_valid(str1);
+ __range_valid(str2);
+ if( !( str1 && str2) ) return false;
+ register char *s1=(char *)str1;
+ register char *s2=(char *)str2;
+
+ int curlen=(int)strlen(str1);
+ int diff;
+
+ if (index<0 || index >= curlen) index = curlen-1;
+
+ s1+=index;
+ while (*s2) s2++;
+ s2--;
+
+ // now start comparing
+ while (1){
+ /* in this case, we have str1 = "lo" and str2 = "hello" */
+ if (s1<str1 && !(s2<str2)) return 256;
+ if (s2<str2) return 0;
+ if ((diff=(*s1)-(*s2))) return diff;
+ s1--;
+ s2--;
+ }
+}
+
+KviStr::KviStr()
+{
+ m_ptr = (char *)kvi_malloc(1);
+ *m_ptr = '\0';
+ m_len = 0;
+}
+
+KviStr::KviStr(const char *str)
+{
+ //Deep copy constructor
+ if(str){
+ //Deep copy
+ m_len = (int)strlen(str);
+ m_ptr = (char *)kvi_malloc(m_len+1);
+ kvi_fastmove(m_ptr,str,m_len+1);
+ } else {
+ m_ptr = (char *)kvi_malloc(1);
+ *m_ptr = '\0';
+ m_len = 0;
+ }
+}
+
+KviStr::KviStr(const KviQCString &str)
+{
+ //Deep copy constructor
+ if(str.data())
+ {
+ //Deep copy
+ m_len = str.length();
+ m_ptr = (char *)kvi_malloc(m_len+1);
+ kvi_fastmove(m_ptr,str,m_len+1);
+ } else {
+ m_ptr = (char *)kvi_malloc(1);
+ *m_ptr = '\0';
+ m_len = 0;
+ }
+}
+
+
+KviStr::KviStr(const char *str,int len)
+{
+ __range_valid(str);
+ //__range_valid(len <= ((int)strlen(str))); <-- we trust the user here (and a strlen() call may run AFTER len if data is not null terminated)
+ __range_valid(len >= 0);
+ m_len = len;
+ m_ptr = (char *)kvi_malloc(m_len+1);
+ kvi_fastmove(m_ptr,str,m_len);
+ *(m_ptr+m_len) = '\0';
+}
+
+KviStr::KviStr(const char *bg,const char *end)
+{
+ __range_valid(bg);
+ __range_valid(end);
+ __range_valid(bg <= end);
+ m_len = end-bg;
+ m_ptr = (char *)kvi_malloc(m_len +1);
+ kvi_fastmove(m_ptr,bg,m_len);
+ *(m_ptr + m_len)='\0';
+}
+
+KviStr::KviStr(KviFormatConstructorTag tag,const char *fmt,...)
+{
+ m_ptr=(char *)kvi_malloc(256);
+ //First try
+ kvi_va_list list;
+ kvi_va_start(list,fmt);
+ //print...with max 256 chars
+ m_len=kvi_vsnprintf(m_ptr,256,fmt,list);
+ kvi_va_end(list);
+
+ //check if we failed
+ if(m_len < 0){
+ //yes , failed....
+ int dummy=256;
+ do{ //we failed , so retry with 256 more chars
+ dummy+=256;
+ //realloc
+ m_ptr=(char *)kvi_realloc(m_ptr,dummy);
+ //print...
+ kvi_va_start(list,fmt);
+ m_len=kvi_vsnprintf(m_ptr,dummy,fmt,list);
+ kvi_va_end(list);
+ } while(m_len < 0);
+ }
+ //done...
+ //now m_len is the length of the written string not including the terminator...
+ //perfect! :)
+ m_ptr=(char *)kvi_realloc(m_ptr,m_len+1);
+}
+
+KviStr::KviStr(const KviStr &str)
+{
+ __range_valid(str.m_ptr);
+ m_len = str.m_len;
+ m_ptr = (char *)kvi_malloc(m_len+1);
+ kvi_fastmove(m_ptr,str.m_ptr,m_len+1);
+}
+
+KviStr::KviStr(const QString &str)
+{
+ KviQCString sz = KviQString::toUtf8(str);
+ if(sz.length() > 0)
+ {
+ m_len = sz.length();
+ m_ptr = (char *)kvi_malloc(m_len+1);
+ kvi_fastmove(m_ptr,sz.data(),m_len+1);
+ } else {
+ m_ptr = (char *)kvi_malloc(1);
+ *m_ptr = '\0';
+ m_len = 0;
+ }
+}
+
+KviStr::KviStr(char c,int fillLen)
+{
+ __range_valid(fillLen >= 0);
+ m_len = fillLen;
+ m_ptr = (char *)kvi_malloc(m_len+1);
+ register char *p=m_ptr;
+ while(fillLen--)*p++=c;
+ *p='\0';
+}
+
+
+KviStr::KviStr(const kvi_wchar_t * unicode)
+{
+ if(!unicode)
+ {
+ m_len = 0;
+ m_ptr = (char *)kvi_malloc(1);
+ *m_ptr = 0;
+ } else {
+ m_len = kvi_wstrlen(unicode);
+ m_ptr = (char *)kvi_malloc(m_len + 1);
+ register char * p = m_ptr;
+ while(*unicode)*p++ = *unicode++;
+ *p = 0;
+ }
+}
+
+KviStr::KviStr(const kvi_wchar_t * unicode,int len)
+{
+ m_len = len;
+ m_ptr = (char *)kvi_malloc(m_len + 1);
+ register char * p = m_ptr;
+ char * end = p + len;
+ while(p != end)
+ {
+ *p++ = *unicode++;
+ }
+ *p = 0;
+}
+
+
+
+
+KviStr::~KviStr()
+{
+ kvi_free(m_ptr);
+}
+
+void KviStr::setLength(int iLen)
+{
+ __range_valid(iLen >= 0);
+ m_len = iLen;
+ m_ptr = (char *)kvi_realloc(m_ptr,m_len+1);
+ *(m_ptr + m_len) = '\0';
+}
+
+KviStr & KviStr::operator=(const KviStr &str)
+{
+ __range_valid(str.m_ptr);
+ __range_valid(str.m_ptr != m_ptr);
+ m_len = str.m_len;
+ m_ptr = (char *)kvi_realloc(m_ptr,m_len+1);
+ kvi_fastmove(m_ptr,str.m_ptr,m_len+1);
+ return (*this);
+}
+
+KviStr & KviStr::operator=(const KviQCString &str)
+{
+ m_len = str.length();
+ m_ptr = (char *)kvi_realloc(m_ptr,m_len+1);
+ if(str.data())kvi_fastmove(m_ptr,str.data(),m_len+1);
+ else *m_ptr = 0;
+ return (*this);
+}
+
+KviStr & KviStr::operator=(const char *str)
+{
+ //__range_valid(str);
+ if(str){
+ m_len = (int)strlen(str);
+ m_ptr = (char *)kvi_realloc(m_ptr,m_len+1);
+ kvi_memmove(m_ptr,str,m_len+1);
+ } else {
+ m_ptr = (char *)kvi_realloc(m_ptr,1);
+ *m_ptr = '\0';
+ m_len = 0;
+ }
+ return (*this);
+}
+
+void KviStr::clear()
+{
+ m_ptr = (char *)kvi_realloc(m_ptr,1);
+ *m_ptr = '\0';
+ m_len = 0;
+}
+
+
+bool KviStr::hasNonWhiteSpaceData() const
+{
+ const char * aux = m_ptr;
+ while(*aux)
+ {
+ if(((*aux) != ' ') && ((*aux) != '\t'))return true;
+ aux++;
+ }
+ return false;
+}
+
+static char hexdigits[16] = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' };
+
+void KviStr::bufferToHex(const char *buffer,int len)
+{
+ __range_valid(buffer);
+ m_len = (len * 2);
+ m_ptr = (char *)kvi_realloc(m_ptr,m_len + 1);
+ char * aux = m_ptr;
+ while(len)
+ {
+ *aux = hexdigits[(unsigned int)(((unsigned char)(*buffer)) / 16)];
+ aux++;
+ *aux = hexdigits[(unsigned int)(((unsigned char)(*buffer)) % 16)];
+ aux++;
+ len--;
+ buffer++;
+ }
+ *(m_ptr+m_len) = '\0';
+}
+
+
+
+static char get_decimal_from_hex_digit_char(char dgt)
+{
+ if((dgt >= '0') && (dgt <= '9'))return (dgt - '0');
+ if((dgt >= 'A') && (dgt <= 'F'))return (10 + (dgt - 'A'));
+ if((dgt >= 'a') && (dgt <= 'f'))return (10 + (dgt - 'a'));
+ return -1;
+}
+
+// This is just error-correcting...it treats non hex stuff as zeros
+/*
+static inline char get_decimal_from_hex_digit_char(char dgt)
+{
+ char c = pedantic_get_decimal_from_hex_digit(dgt);
+ if(c == -1)return 0;
+ return c;
+}
+
+int KviStr::hexToBuffer(char ** buffer,bool bNullToNewlines)
+{
+ int len;
+ if(m_len % 2)len = (m_len / 2) + 1;
+ else len = (m_len / 2);
+ *buffer = (char *)kvi_malloc(len);
+
+ char * ptr = *buffer;
+
+ char * aux = m_ptr;
+ while(*aux)
+ {
+ *ptr = get_decimal_from_hex_digit_char(*aux) * 16;
+ aux++;
+ if(*aux)
+ {
+ *ptr += get_decimal_from_hex_digit_char(*aux);
+ aux++;
+ }
+ if(bNullToNewlines)if(!(*ptr))*ptr = '\n';
+ ptr++;
+ }
+ return len;
+}
+*/
+
+int KviStr::hexToBuffer(char ** buffer,bool bNullToNewlines)
+{
+ *buffer = 0;
+ if((m_len == 0) || (m_len & 1))return -1; // this is an error
+ int len = (m_len / 2);
+ if(len < 1)return -1;
+ *buffer = (char *)kvi_malloc(len);
+
+ char * ptr = *buffer;
+ char * aux = m_ptr;
+
+ char aux2;
+
+ while(*aux)
+ {
+ *ptr = get_decimal_from_hex_digit_char(*aux) * 16;
+ if(*ptr == -1)
+ {
+ kvi_free(*buffer);
+ *buffer = 0;
+ return -1;
+ }
+ aux++;
+ aux2 = get_decimal_from_hex_digit_char(*aux);
+ if(aux2 == -1)
+ {
+ kvi_free(*buffer);
+ *buffer = 0;
+ return -1;
+ }
+ *ptr += aux2;
+ aux++;
+ if(bNullToNewlines)if(!(*ptr))*ptr = '\n';
+ ptr++;
+ }
+ return len;
+}
+
+static const char * base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+
+void KviStr::bufferToBase64(const char * buffer,int len)
+{
+ m_len = (len / 3) << 2;
+ if(len % 3)m_len += 4;
+
+ m_ptr = (char *)kvi_realloc(m_ptr,m_len + 1);
+
+ unsigned char aux1,aux2,aux3;
+ char * aux_ptr = m_ptr;
+ while(len > 2)
+ {
+ aux1 = (unsigned char)*buffer++;
+ aux2 = (unsigned char)*buffer++;
+ aux3 = (unsigned char)*buffer++;
+ *aux_ptr++ = base64_chars[(aux1 & 0xFC) >> 2];
+ *aux_ptr++ = base64_chars[((aux1 & 0x03) << 4) | ((aux2 & 0xF0) >> 4)];
+ *aux_ptr++ = base64_chars[((aux2 & 0x0F) << 2) | ((aux3 & 0xC0) >> 6)];
+ *aux_ptr++ = base64_chars[(aux3 & 0x3F)];
+ len -= 3;
+ }
+ switch(len)
+ {
+ case 2:
+ aux1 = (unsigned char)*buffer++;
+ aux2 = (unsigned char)*buffer++;
+ *aux_ptr++ = base64_chars[(aux1 & 0xFC) >> 2];
+ *aux_ptr++ = base64_chars[((aux1 & 0x03) << 4) | ((aux2 & 0xF0) >> 4)];
+ *aux_ptr++ = base64_chars[((aux2 & 0x0F) << 2)];
+ *aux_ptr++ = '=';
+ break;
+ case 1:
+ aux1 = (unsigned char)*buffer++;
+ aux2 = (unsigned char)*buffer++;
+ *aux_ptr++ = base64_chars[(aux1 & 0xFC) >> 2];
+ *aux_ptr++ = base64_chars[((aux1 & 0x03) << 4)];
+ *aux_ptr++ = '=';
+ *aux_ptr++ = '=';
+ break;
+ }
+ *aux_ptr = 0;
+}
+
+static unsigned char get_base64_idx(char base64)
+{
+ if((base64 >= 'A') && (base64 <= 'Z'))return (base64 - 'A');
+ if((base64 >= 'a') && (base64 <= 'z'))return ((base64 - 'a') + 26);
+ if((base64 >= '0') && (base64 <= '9'))return ((base64 - '0') + 52);
+ if(base64 == '+')return 62;
+ if(base64 == '/')return 63;
+ if(base64 == '=')return 64;
+ return 65;
+}
+
+
+int KviStr::base64ToBuffer(char ** buffer,bool bNullToNewlines)
+{
+ *buffer = 0;
+ if((m_len == 0) || (m_len & 3))return -1; // this is an error
+ int len = (m_len >> 2) * 3;
+ *buffer = (char *)kvi_malloc(len);
+
+ char * auxBuf = *buffer;
+
+ unsigned char aux1,aux2,aux3,aux4;
+ char * aux_ptr = m_ptr;
+
+ int newLen = len;
+
+ while(*aux_ptr)
+ {
+ if(newLen != len)
+ {
+ // ops... there was a padding and we still have chars after it
+ // this is an error
+ kvi_free(*buffer);
+ *buffer = 0;
+ return -1;
+ }
+ aux1 = get_base64_idx(*aux_ptr++);
+ aux2 = get_base64_idx(*aux_ptr++);
+ aux3 = get_base64_idx(*aux_ptr++);
+ aux4 = get_base64_idx(*aux_ptr++);
+ if((aux3 > 64) || (aux4 > 64))
+ {
+ // error
+ kvi_free(*buffer);
+ *buffer = 0;
+ return -1;
+ }
+ if((aux1 | aux2) > 63)
+ {
+ // again error...impossible padding
+ kvi_free(*buffer);
+ *buffer = 0;
+ return -1;
+ }
+ if(aux4 == 64)
+ {
+ if(aux3 == 64)
+ {
+ // Double padding, only one digit here
+ *auxBuf++ = (char)((aux1 << 2) | (aux2 >> 4));
+ newLen -= 2;
+ } else {
+ // Single padding, two digits here
+ *auxBuf++ = (char)((aux1 << 2) | (aux2 >> 4)); // >> 4 is a shr , not a ror! :)
+ *auxBuf++ = (char)((aux2 << 4) | (aux3 >> 2));
+ newLen -= 1;
+ }
+ } else {
+ if(aux3 == 64)
+ {
+ // error... impossible padding
+ kvi_free(*buffer);
+ *buffer = 0;
+ return -1;
+ } else {
+ // Ok , no padding, three digits here
+ *auxBuf++ = (char)((aux1 << 2) | (aux2 >> 4));
+ *auxBuf++ = (char)((aux2 << 4) | (aux3 >> 2));
+ *auxBuf++ = (char)((aux3 << 6) | aux4);
+ }
+ }
+ }
+
+ if(newLen != len)*buffer = (char *)kvi_realloc(*buffer,newLen);
+ return newLen;
+}
+
+KviStr & KviStr::setStr(const char *str,int len)
+{
+ if(!str)
+ {
+ clear();
+ return *this;
+ }
+ int alen = (int)strlen(str);
+ if((len < 0) || (len > alen))m_len = alen;
+ else m_len = len;
+ m_ptr = (char *)kvi_realloc(m_ptr,m_len+1);
+ kvi_memmove(m_ptr,str,m_len);
+ *(m_ptr+m_len) = '\0';
+ return (*this);
+}
+
+KviStr & KviStr::operator=(const QString &str)
+{
+ KviQCString sz = KviQString::toUtf8(str);
+ if(sz.length() > 0){
+ m_len = sz.length();
+ m_ptr = (char *)kvi_realloc(m_ptr,m_len+1);
+ kvi_fastmove(m_ptr,sz.data(),m_len+1);
+ } else {
+ m_ptr = (char *)kvi_realloc(m_ptr,1);
+ *m_ptr = '\0';
+ m_len = 0;
+ }
+ return (*this);
+}
+
+KviStr & KviStr::operator=(char c)
+{
+ m_len = 1;
+ m_ptr = (char *)kvi_realloc(m_ptr,2);
+ *m_ptr = c;
+ *(m_ptr+1)='\0';
+ return (*this);
+}
+
+void KviStr::append(char c)
+{
+ m_ptr = (char *)kvi_realloc(m_ptr,m_len+2);
+ *(m_ptr+m_len)=c;
+ m_len++;
+ *(m_ptr+m_len)='\0';
+}
+
+void KviStr::append(const KviStr &str)
+{
+ __range_valid(str.m_ptr);
+ m_ptr = (char *)kvi_realloc(m_ptr,m_len+str.m_len+1);
+ kvi_fastmove((m_ptr+m_len),str.m_ptr,str.m_len+1);
+ m_len += str.m_len;
+}
+
+void KviStr::append(const char *str)
+{
+ if(!str)return;
+ int len = (int)strlen(str);
+ m_ptr = (char *)kvi_realloc(m_ptr,m_len+len+1);
+ kvi_fastmove((m_ptr+m_len),str,len+1);
+ m_len += len;
+}
+
+void KviStr::append(const QString &str)
+{
+ KviQCString sz = KviQString::toUtf8(str);
+ if(sz.length() < 1)return;
+ m_ptr = (char *)kvi_realloc(m_ptr,m_len+sz.length()+1);
+ kvi_fastmove((m_ptr+m_len),sz.data(),sz.length()+1);
+ m_len += sz.length();
+}
+
+void KviStr::append(const char *str,int len)
+{
+ __range_valid(str);
+// __range_valid(len <= ((int)strlen(str)));
+ __range_valid(len >= 0);
+ m_ptr = (char *)kvi_realloc(m_ptr,m_len+len+1);
+ kvi_fastmove((m_ptr+m_len),str,len);
+ m_len += len;
+ *(m_ptr + m_len)='\0';
+}
+
+void KviStr::append(KviFormatConstructorTag tag,const char *fmt,...)
+{
+ int auxLen;
+ m_ptr=(char *)kvi_realloc(m_ptr,m_len + 256);
+ //First try
+ kvi_va_list list;
+ kvi_va_start(list,fmt);
+ //print...with max 256 chars
+ auxLen =kvi_vsnprintf(m_ptr + m_len,256,fmt,list);
+ kvi_va_end(list);
+
+ //check if we failed
+ if(auxLen < 0){
+ //yes , failed....
+ int dummy=256;
+ do{ //we failed , so retry with 256 more chars
+ dummy+=256;
+ //realloc
+ m_ptr=(char *)kvi_realloc(m_ptr,m_len + dummy);
+ //print...
+ kvi_va_start(list,fmt);
+ auxLen=kvi_vsnprintf(m_ptr + m_len,dummy,fmt,list);
+ kvi_va_end(list);
+ } while(auxLen < 0);
+ }
+ m_len += auxLen;
+ //done...
+ //now m_len is the length of the written string not including the terminator...
+ //perfect! :)
+ m_ptr=(char *)kvi_realloc(m_ptr,m_len+1);
+}
+
+void KviStr::extractFromString(const char *begin,const char *end)
+{
+ __range_valid(begin);
+ __range_valid(end);
+ __range_valid(end >= begin);
+ m_len = end-begin;
+ m_ptr = (char *)kvi_realloc(m_ptr,m_len+1);
+ kvi_fastmove(m_ptr,begin,m_len);
+ *(m_ptr + m_len)='\0';
+}
+
+void KviStr::prepend(const KviStr &str)
+{
+ __range_valid(str.m_ptr);
+ __range_valid(str.m_ptr != m_ptr);
+ m_ptr = (char *)kvi_realloc(m_ptr,m_len+str.m_len+1);
+ kvi_memmove((m_ptr+str.m_len),m_ptr,m_len+1); //move self
+ kvi_fastmove(m_ptr,str.m_ptr,str.m_len);
+ m_len += str.m_len;
+}
+
+void KviStr::prepend(const char *str)
+{
+ if(!str)return;
+ int len = (int)strlen(str);
+ m_ptr = (char *)kvi_realloc(m_ptr,m_len+len+1);
+ kvi_memmove((m_ptr+len),m_ptr,m_len+1); //move self
+ kvi_fastmove(m_ptr,str,len);
+ m_len += len;
+}
+
+void KviStr::prepend(const char *str,int len)
+{
+ __range_valid(str);
+ __range_valid(len <= ((int)strlen(str)));
+ __range_valid(len >= 0);
+ m_ptr = (char *)kvi_realloc(m_ptr,m_len+len+1);
+ kvi_memmove((m_ptr+len),m_ptr,m_len+1); //move self
+ kvi_fastmove(m_ptr,str,len);
+ m_len += len;
+}
+
+unsigned char iso88591_toUpper_map[256]=
+{
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+};
+
+void KviStr::toUpperISO88591()
+{
+ register char *p=m_ptr;
+ while(*p)
+ {
+ *p=(char)iso88591_toUpper_map[(unsigned char)*p];
+ p++;
+ }
+}
+
+void KviStr::toUpper()
+{
+ register char *p=m_ptr;
+ while(*p)
+ {
+ *p=toupper(*p);
+ p++;
+ }
+}
+
+unsigned char iso88591_toLower_map[256]=
+{
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+ 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+};
+
+void KviStr::toLowerISO88591()
+{
+ register char *p=m_ptr;
+ while(*p)
+ {
+ *p=(char)iso88591_toLower_map[(unsigned char)*p];
+ p++;
+ }
+}
+
+
+void KviStr::toLower()
+{
+ register char *p=m_ptr;
+ while(*p)
+ {
+ *p=tolower(*p);
+ p++;
+ }
+}
+
+KviStr KviStr::upper() const
+{
+ KviStr tmp(*this);
+ tmp.toUpper();
+ return tmp;
+}
+
+KviStr KviStr::upperISO88591() const
+{
+ KviStr tmp(*this);
+ tmp.toUpperISO88591();
+ return tmp;
+}
+
+KviStr KviStr::lower() const
+{
+ KviStr tmp(*this);
+ tmp.toLower();
+ return tmp;
+}
+
+KviStr KviStr::lowerISO88591() const
+{
+ KviStr tmp(*this);
+ tmp.toLowerISO88591();
+ return tmp;
+}
+
+KviStr KviStr::left(int maxLen) const
+{
+ if(maxLen <= 0)
+ {
+ KviStr empty;
+ return empty;
+ }
+ if(maxLen > m_len)maxLen=m_len;
+ KviStr str(m_ptr,maxLen);
+ return str;
+}
+
+KviStr KviStr::right(int maxLen) const
+{
+ if(maxLen <= 0)
+ {
+ KviStr empty;
+ return empty;
+ }
+ if(maxLen > m_len)maxLen=m_len;
+ KviStr str((m_ptr+(m_len-maxLen)),maxLen);
+ return str;
+}
+
+KviStr KviStr::middle(int idx,int maxLen) const
+{
+ __range_valid(maxLen >= 0);
+ __range_valid(idx >= 0);
+ if((maxLen <= 0) || (idx < 0)){ //max len negative...invalid params
+ KviStr ret;
+ return ret;
+ }
+ if((maxLen + idx) <= m_len){ //valid params
+ KviStr str(m_ptr+idx,maxLen);
+ return str;
+ }
+ if(idx < m_len){ //string shorter than requested
+ KviStr str(m_ptr+idx);
+ return str;
+ }
+ // idx out of bounds
+ KviStr ret;
+ return ret;
+}
+
+KviStr ** KviStr::splitToArray(char sep,int max,int * realCount) const
+{
+ KviStr ** strings = (KviStr **)kvi_malloc(sizeof(KviStr *));
+ int number = 0;
+ char * ptr = m_ptr;
+ char * last = ptr;
+ while((max > 0) && *ptr)
+ {
+ strings = (KviStr **)kvi_realloc((void *)strings,sizeof(KviStr *) * (number + 2));
+ if(max > 1)
+ {
+ while(*ptr && (*ptr != sep))ptr++;
+ strings[number] = new KviStr(last,ptr - last);
+ } else {
+ strings[number] = new KviStr(ptr);
+ }
+ number++;
+ max--;
+ if(*ptr)
+ {
+ ptr++;
+ last = ptr;
+ }
+ }
+ if(realCount)*realCount = number;
+ strings[number] = 0;
+ return strings;
+}
+/*
+ WORKING BUT UNUSED
+
+KviStr ** KviStr::splitToArray(const char * sep,int max,int * realCount) const
+{
+ KviStr ** strings = (KviStr **)kvi_malloc(sizeof(KviStr *));
+ KviStr tmp = *this;
+ int idx = tmp.findFirstIdx(sep);
+ int number = 0;
+ int seplen = kvi_strLen(sep);
+
+
+ while(idx != -1)
+ {
+ strings = (KviStr **)kvi_realloc(sizeof(KviStr *) * (number + 2));
+ strings[number] = new KviStr(tmp.ptr(),idx);
+ tmp.cutLeft(idx + seplen);
+ number++;
+ idx = tmp.findFirstIdx(sep);
+ }
+
+ if(tmp.hasData())
+ {
+ strings = (KviStr **)kvi_realloc(sizeof(KviStr *) * (number + 2));
+ strings[number] = new KviStr(tmp);
+ number++;
+ }
+
+ if(realCount)*realCount = number;
+ strings[number] = 0;
+ return strings;
+}
+*/
+void KviStr::freeArray(KviStr ** strings)
+{
+ if(!strings)return;
+ KviStr ** aux = strings;
+ while(*aux)
+ {
+ delete (*aux); // delete (KviStr *)
+ aux++;
+ }
+ kvi_free(strings);
+}
+
+void KviStr::freeBuffer(char * buffer)
+{
+ if(!buffer)return;
+ kvi_free(buffer);
+}
+
+void KviStr::joinFromArray(KviStr ** strings,const char * sep,bool bLastSep)
+{
+ setLen(0);
+ if(!strings)return;
+
+ while(*strings)
+ {
+ append(*(*strings));
+ strings++;
+ if(*strings)
+ {
+ if(sep)append(sep);
+ } else {
+ if(sep && bLastSep)append(sep);
+ }
+ }
+}
+
+KviStr & KviStr::insert(int idx,const char *data)
+{
+ __range_valid(data);
+ if(idx <= m_len){
+ int len = (int)strlen(data);
+ m_ptr = (char *)kvi_realloc(m_ptr,m_len+len+1);
+ kvi_memmove(m_ptr+idx+len,m_ptr+idx,(m_len - idx)+1);
+ kvi_fastmove(m_ptr+idx,data,len);
+ m_len+=len;
+ }
+ return (*this);
+}
+
+KviStr & KviStr::insert(int idx,char c)
+{
+ if(idx <= m_len){
+ m_ptr = (char *)kvi_realloc(m_ptr,m_len+2);
+ kvi_memmove(m_ptr+idx+1,m_ptr+idx,(m_len - idx)+1);
+ m_len++;
+ *(m_ptr + idx) = c;
+ }
+ return (*this);
+}
+
+// FIXME: #warning "Double check the following two functions !!!"
+
+KviStr & KviStr::hexEncodeWithTable(const unsigned char table[256])
+{
+ char * aux = m_ptr;
+ char * begin = m_ptr;
+
+ char * n = 0;
+ int curSize = 0;
+
+ while(*aux)
+ {
+ if(table[*((unsigned char *)aux)] || (*aux == '%'))
+ {
+ int len = aux - begin;
+ n = (char *)kvi_realloc(n,curSize + len + 3);
+ kvi_memmove(n + curSize,begin,len);
+ curSize += len;
+
+ n[curSize] = '%';
+ curSize++;
+ n[curSize] = hexdigits[(unsigned int)(((unsigned char)(*aux)) / 16)];
+ curSize++;
+ n[curSize] = hexdigits[(unsigned int)(((unsigned char)(*aux)) % 16)];
+ curSize++;
+
+ aux++;
+ begin = aux;
+
+ } else aux++;
+ }
+
+ int len = aux - begin;
+ n = (char *)kvi_realloc(n,curSize + len + 1);
+ kvi_memmove(n + curSize,begin,len);
+ curSize += len;
+
+ n[curSize] = '\0';
+
+ kvi_free((void *)m_ptr);
+ m_ptr = n;
+ m_len = curSize;
+
+ return (*this);
+}
+
+KviStr & KviStr::hexEncodeWhiteSpace()
+{
+ static unsigned char ascii_jump_table[256]=
+ {
+ // 000 001 002 003 004 005 006 007 008 009 010 011 012 013 014 015
+ // NUL SOH STX ETX EOT ENQ ACK BEL BS HT LF VT FF CR SO SI
+ 1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,
+ // 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031
+ // DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US
+ 1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,
+ // 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047
+ // ! " # $ % & ' ( ) * + , - . /
+ 1 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+ // 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063
+ // 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+ // 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079
+ // @ A B C D E F G H I J K L M N O
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+ // 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095
+ // P Q R S T U V W X Y Z [ \ ] ^ _
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+ // 096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111
+ // ` a b c d e f g h i j k l m n o
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+ // 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
+ // p q r s t u v w x y z { | } ~ 
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+ // 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
+ //
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+ // 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
+ //
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+ // 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
+ //
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+ // 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
+ //
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+ // 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
+ // � � � � � � � � � � � � � � � �
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+ // 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
+ // � � � � � � � � � � � � � � � �
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+ // 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
+ // � � � � � � � � � � � � � � � �
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+ // 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
+ // � � � � � � � �
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ };
+
+ return hexEncodeWithTable(ascii_jump_table);
+}
+
+KviStr & KviStr::hexDecode(const char * pFrom)
+{
+ // WARNING: pFrom can be also m_ptr here!
+ const char * aux = pFrom;
+ const char * begin = pFrom;
+
+ char * n = 0;
+ int curSize = 0;
+
+ while(*aux)
+ {
+ if(*aux == '%')
+ {
+ // move last block
+ int len = aux - begin;
+ n = (char *)kvi_realloc(n,curSize + len + 1);
+ kvi_memmove(n + curSize,begin,len);
+ curSize += len;
+
+ // get the hex code
+ aux++;
+
+ char theChar = get_decimal_from_hex_digit_char(*aux);
+ if(theChar < 0)
+ {
+ n[curSize] = '%'; // wrong code...just a '%'
+ curSize++;
+ } else {
+ aux++;
+ char theChar2 = get_decimal_from_hex_digit_char(*aux);
+ if(theChar2 < 0)
+ {
+ // wrong code...just a '%' and step back
+ n[curSize] = '%';
+ curSize++;
+ aux--;
+ } else {
+ n[curSize] = (theChar * 16) + theChar2;
+ curSize++;
+ aux++;
+ }
+ }
+
+ begin = aux;
+
+ } else aux++;
+ }
+
+ int len = aux - begin;
+ n = (char *)kvi_realloc(n,curSize + len + 2);
+ kvi_memmove(n + curSize,begin,len);
+ curSize += len;
+ n[curSize] = '\0';
+
+ kvi_free((void *)m_ptr);
+ m_ptr = n;
+ m_len = curSize;
+
+ return (*this);
+}
+
+KviStr & KviStr::replaceAll(char c,const char *str)
+{
+ int idx = findFirstIdx(c);
+ KviStr tmp;
+ while(idx >= 0){
+ if(idx > 0)tmp += left(idx);
+ cutLeft(idx+1);
+ tmp.append(str);
+ idx = findFirstIdx(c);
+ }
+ tmp.append(*this);
+ // Now copy
+ m_len = tmp.m_len;
+ m_ptr = (char *)kvi_realloc(m_ptr,m_len+1);
+ kvi_fastmove(m_ptr,tmp.m_ptr,m_len+1);
+ return (*this);
+}
+
+KviStr & KviStr::replaceAll(char *toFind,const char *str,bool bCaseS)
+{
+ int len = (int)strlen(toFind);
+ int idx = findFirstIdx(toFind,bCaseS);
+ KviStr tmp;
+ while(idx >= 0)
+ {
+ if(idx > 0)tmp += left(idx);
+ cutLeft(idx+len);
+ tmp.append(str);
+ idx = findFirstIdx(toFind,bCaseS);
+ }
+ tmp.append(*this);
+ // Now copy
+ m_len = tmp.m_len;
+ m_ptr = (char *)kvi_realloc(m_ptr,m_len+1);
+ kvi_fastmove(m_ptr,tmp.m_ptr,m_len+1);
+ return (*this);
+}
+
+KviStr & KviStr::transliterate(const char * szToFind,const char * szReplacement)
+{
+ while(*szToFind && *szReplacement)
+ {
+ char * p = m_ptr;
+ while(*p)
+ {
+ if(*p == *szToFind)*p = *szReplacement;
+ ++p;
+ }
+ ++szToFind;
+ ++szReplacement;
+ }
+ return (*this);
+}
+
+
+int KviStr::occurences(char c,bool caseS) const
+{
+ register char *p = m_ptr;
+ int cnt=0;
+ if(caseS){
+ while(*p){
+ if(*p == c)cnt++;
+ p++;
+ }
+ } else {
+ char b=tolower(c);
+ while(*p){
+ if(tolower(*p) == b)cnt++;
+ p++;
+ }
+ }
+ return cnt;
+}
+
+int KviStr::occurences(const char *str,bool caseS) const
+{
+ __range_valid(str);
+ register char *p = m_ptr;
+ int cnt=0;
+ int len = (int)strlen(str);
+ if(caseS){
+ while(*p){
+ if(*p == *str){
+ if(kvi_strEqualCSN(p,str,len))cnt++;
+ }
+ p++;
+ }
+ } else {
+ while(*p){
+ char c = tolower(*str);
+ if(tolower(*p) == c){
+ if(kvi_strEqualCIN(p,str,len))cnt++;
+ }
+ p++;
+ }
+ }
+ return cnt;
+}
+
+bool KviStr::contains(char c,bool caseS) const
+{
+ register char *p = m_ptr;
+ if(caseS)
+ {
+ while(*p)
+ {
+ if(*p == c)return true;
+ p++;
+ }
+ } else {
+ char b=tolower(c);
+ while(*p)
+ {
+ if(tolower(*p) == b)return true;
+ p++;
+ }
+ }
+ return false;
+}
+
+bool KviStr::contains(const char *str,bool caseS) const
+{
+ __range_valid(str);
+ register char *p = m_ptr;
+ int len = (int)strlen(str);
+ if(caseS)
+ {
+ while(*p)
+ {
+ if(*p == *str)
+ {
+ if(kvi_strEqualCSN(p,str,len))return true;
+ }
+ p++;
+ }
+ } else {
+ while(*p)
+ {
+ char c = tolower(*str);
+ if(tolower(*p) == c)
+ {
+ if(kvi_strEqualCIN(p,str,len))return true;
+ }
+ p++;
+ }
+ }
+ return false;
+}
+
+
+KviStr & KviStr::setNum(long num)
+{
+ char numberBuffer[30];
+ bool bNegative = false;
+ long tmp;
+ register char *p;
+ register char *pNumBuf = numberBuffer;
+
+ // somebody can explain me why -(-2147483648) = -2147483648 ? (2^31)
+ // it is like signed char x = 128 ---> 10000000 that is signed -0 (!?)
+ // mmmmh...or it is assumed to be -128 (a number rappresentation exception)
+ // at least on my machine it happens...
+
+ // found the solution by myself today...
+ //
+ // ABS(3) Linux Programmer's Manual ABS(3)
+ // NAME
+ // abs - computes the absolute value of an integer.
+ // ...
+ // DESCRIPTION
+ // The abs() function computes the absolute value of the integer argument j.
+ // RETURN VALUE
+ // Returns the absolute value of the integer argument.
+ // CONFORMING TO
+ // SVID 3, POSIX, BSD 4.3, ISO 9899
+ // NOTE ##################################################################################
+ // Trying to take the absolute value of the most negative integer is not defined.
+ // #######################################################################################
+
+ // so should i use temporaneous doubles to make calculations ?
+
+ if(num < 0){ //negative integer
+ bNegative = true;
+ num = -num; //need to have it positive
+ if(num < 0){ // 2^31 exception
+ // We need to avoid absurd responses like ".(./),." :)
+ num = 0; // we get a negative zero here...it is still an exception
+ }
+ }
+
+ //write the number in a temporary buffer (at least '0')
+ do {
+ tmp = num / 10;
+ *pNumBuf++ = num - (tmp * 10) + '0';
+ } while((num = tmp));
+
+ //copy now....
+ m_len = pNumBuf - numberBuffer; //length of the number string
+ if(bNegative){
+ m_len++;
+ m_ptr = (char *)kvi_realloc(m_ptr,m_len+1);
+ p=m_ptr;
+ *p++='-';
+ } else {
+ m_ptr = (char *)kvi_realloc(m_ptr,m_len+1);
+ p=m_ptr;
+ }
+ do { *p++ = *--pNumBuf; } while(pNumBuf != numberBuffer);
+ *(m_ptr + m_len)='\0';
+ return (*this);
+}
+
+KviStr & KviStr::setNum(unsigned long num)
+{
+ char numberBuffer[30];
+ unsigned long tmp;
+ register char *p;
+ register char *pNumBuf = numberBuffer;
+
+ //write the number in a temporary buffer (at least '0')
+ do {
+ tmp = num / 10;
+ *pNumBuf++ = num - (tmp * 10) + '0';
+ } while((num = tmp));
+
+ //copy now....
+ m_len = pNumBuf - numberBuffer; //length of the number string
+ m_ptr = (char *)kvi_realloc(m_ptr,m_len+1);
+ p=m_ptr;
+ do { *p++ = *--pNumBuf; } while(pNumBuf != numberBuffer);
+ *(m_ptr + m_len)='\0';
+ return (*this);
+}
+
+long KviStr::toLong(bool *bOk) const
+{
+ long result = 0;
+ if(bOk)*bOk = false;
+ register char *p=m_ptr;
+ bool bNeg = false;
+ while(isspace(*p))p++; //skip spaces
+ if(*p == '-'){
+ bNeg = true;
+ p++;
+ } else {
+ if(*p == '+')p++;
+ }
+ if(isdigit(*p)){ //point to something interesting ?
+ do{
+ result = (result * 10) + (*p - '0');
+ p++;
+ } while(isdigit(*p));
+ if(bNeg)result = -result;
+ while(isspace(*p))p++; //skip trailing spaces
+ if(*p)return 0; //if this is not the end...die.
+ if(bOk)*bOk = true;
+ return result;
+ }
+ return 0;
+}
+
+unsigned long KviStr::toULong(bool *bOk) const
+{
+ unsigned long result = 0;
+ if(bOk)*bOk = false;
+ register char *p=m_ptr;
+ while(isspace(*p))p++; //skip spaces
+ if(isdigit(*p)){ //point to something interesting ?
+ do{
+ result = (result * 10) + (*p - '0');
+ p++;
+ } while(isdigit(*p));
+ while(isspace(*p))p++; //skip trailing spaces
+ if(*p)return 0; //if this is not the end...die.
+ if(bOk)*bOk = true;
+ return result;
+ }
+ return 0;
+}
+
+long KviStr::toLongExt(bool *bOk,int base)
+{
+ if(m_len == 0){
+ if(bOk)*bOk = false;
+ return 0;
+ }
+ char * endptr;
+ long result = strtol(m_ptr,&endptr,base);
+ if(*endptr){
+ // must be whitespaces , otherwise there is trailing garbage inside
+ while(isspace(*endptr) && (*endptr))endptr++;
+ if(*endptr){
+ // still not at the end
+ // trailing garbage not allowed
+ if(bOk)*bOk = false;
+ return result;
+ }
+ }
+ if(bOk)*bOk = true;
+ return result;
+}
+
+//
+//working code , but unused in kvirc
+//
+//unsigned long KviStr::toULongExt(bool *bOk = 0,int base = 0)
+//{
+// if(m_len == 0){
+// if(bOk)*bOk = false;
+// return 0;
+// }
+// char * endptr;
+// unsigned long result = strtoul(m_ptr,&endptr,base);
+// if(*endptr != '\0'){
+// if(bOk)*bOk = false;
+// }
+// return result;
+//}
+
+KviStr & KviStr::cutLeft(int len)
+{
+ __range_valid(len >= 0);
+ if(len <= m_len){
+ m_len -= len;
+ kvi_memmove(m_ptr,m_ptr+len,m_len+1);
+ m_ptr = (char *)kvi_realloc(m_ptr,m_len+1);
+ } else {
+ m_ptr = (char *)kvi_realloc(m_ptr,1);
+ *m_ptr = '\0';
+ m_len = 0;
+ }
+ return (*this);
+}
+
+KviStr & KviStr::cutRight(int len)
+{
+ __range_valid(len >= 0);
+ if(len <= m_len){
+ m_len -= len;
+ m_ptr = (char *)kvi_realloc(m_ptr,m_len+1);
+ *(m_ptr +m_len)='\0';
+ } else {
+ m_ptr = (char *)kvi_realloc(m_ptr,1);
+ *m_ptr = '\0';
+ m_len = 0;
+ }
+ return (*this);
+}
+
+KviStr & KviStr::cut(int idx,int len)
+{
+ __range_valid(idx >= 0);
+ __range_valid(len >= 0);
+ if(idx < m_len){
+ // idx = 3 len = 3 m_len = 10
+ // 0123456789
+ // abcdefghij
+ // ^ ^
+ // p1 p2
+ char * p1 = m_ptr+idx;
+ if(len + idx > m_len)len = m_len - idx;
+ char * p2 = p1+len;
+ kvi_memmove(p1,p2,(m_len - (len+idx)) +1);
+ m_len -= len;
+ m_ptr = (char *)kvi_realloc(m_ptr,m_len+1);
+ }
+ return (*this);
+}
+
+KviStr & KviStr::cutToFirst(char c,bool bIncluded)
+{
+ int idx = findFirstIdx(c);
+ if(idx != -1)cutLeft(bIncluded ? idx + 1 : idx);
+ return (*this);
+}
+
+KviStr KviStr::leftToFirst(char c,bool bIncluded) const
+{
+ int idx = findFirstIdx(c);
+ if(idx == -1)return KviStr(*this);
+ return KviStr(m_ptr,bIncluded ? idx + 1 : idx);
+}
+
+
+KviStr KviStr::leftToLast(char c,bool bIncluded) const
+{
+ int idx = findLastIdx(c);
+ return KviStr(m_ptr,bIncluded ? idx + 1 : idx);
+}
+
+KviStr & KviStr::cutFromFirst(char c,bool bIncluded)
+{
+ int idx = findFirstIdx(c);
+ if(idx != -1)cutRight(bIncluded ? (m_len - idx) : (m_len - (idx + 1)));
+ return (*this);
+}
+
+KviStr & KviStr::cutToLast(char c,bool bIncluded)
+{
+ int idx = findLastIdx(c);
+ if(idx != -1)cutLeft(bIncluded ? idx + 1 : idx);
+ return (*this);
+}
+
+KviStr & KviStr::cutFromLast(char c,bool bIncluded)
+{
+ int idx = findLastIdx(c);
+ if(idx != -1)cutRight(bIncluded ? (m_len - idx) : (m_len - (idx + 1)));
+ return (*this);
+}
+
+KviStr & KviStr::cutToFirst(const char *c,bool bIncluded)
+{
+ int len = (int)strlen(c);
+ int idx = findFirstIdx(c);
+ if(idx != -1)cutLeft(bIncluded ? idx + len : idx);
+ return (*this);
+}
+
+KviStr & KviStr::cutFromFirst(const char *c,bool bIncluded)
+{
+ int len = (int)strlen(c);
+ int idx = findFirstIdx(c);
+ if(idx != -1)cutRight(bIncluded ? (m_len - idx) : (m_len - (idx + len)));
+ return (*this);
+}
+
+KviStr & KviStr::cutToLast(const char *c,bool bIncluded)
+{
+ int len = (int)strlen(c);
+ int idx = findLastIdx(c);
+ if(idx != -1)cutLeft(bIncluded ? idx + len : idx);
+ return (*this);
+}
+
+KviStr & KviStr::cutFromLast(const char *c,bool bIncluded)
+{
+ int len = (int)strlen(c);
+ int idx = findLastIdx(c);
+ if(idx != -1)cutRight(bIncluded ? (m_len - idx) : (m_len - (idx + len)));
+ return (*this);
+}
+
+KviStr & KviStr::setLen(int len)
+{
+ __range_valid(len >= 0);
+ m_ptr = (char *)kvi_realloc(m_ptr,len+1);
+ *(m_ptr+len)='\0';
+ m_len = len;
+ return (*this);
+}
+
+KviStr & KviStr::stripLeftWhiteSpace()
+{
+ register char *p=m_ptr;
+ while(isspace(*p))p++;
+ m_len -= (p-m_ptr);
+ kvi_memmove(m_ptr,p,m_len+1);
+ m_ptr = (char *)kvi_realloc(m_ptr,m_len+1);
+ return (*this);
+}
+
+KviStr & KviStr::stripLeft(char c)
+{
+ __range_valid(c != '\0');
+ register char *p=m_ptr;
+ while(*p == c)p++;
+ m_len -= (p-m_ptr);
+ kvi_memmove(m_ptr,p,m_len+1);
+ m_ptr = (char *)kvi_realloc(m_ptr,m_len+1);
+ return (*this);
+}
+
+bool KviStr::getToken(KviStr & str,char sep)
+{
+ __range_valid(str.m_ptr);
+ __range_valid(str.m_ptr != m_ptr);
+ register char *p=m_ptr;
+ //skip to the end
+ while(*p && (*p != sep))p++;
+ //0123456789
+ //abcd xyz
+ //^ ^
+ str.m_len = p-m_ptr;
+ str.m_ptr = (char *)kvi_realloc(str.m_ptr,str.m_len+1);
+ kvi_fastmove(str.m_ptr,m_ptr,str.m_len);
+ *(str.m_ptr + str.m_len)='\0';
+ while(*p && (*p == sep))p++;
+ cutLeft(p-m_ptr);
+ return (m_len != 0);
+}
+
+bool KviStr::getLine(KviStr &str)
+{
+ __range_valid(str.m_ptr);
+ __range_valid(str.m_ptr != m_ptr);
+ if(m_len == 0)return false;
+ register char *p=m_ptr;
+ //skip to the end
+ while(*p && (*p != '\n'))p++;
+ //0123456789
+ //abcd xyz
+ //^ ^
+ str.m_len = p-m_ptr;
+ str.m_ptr = (char *)kvi_realloc(str.m_ptr,str.m_len+1);
+ kvi_fastmove(str.m_ptr,m_ptr,str.m_len);
+ *(str.m_ptr + str.m_len)='\0';
+ p++;
+ cutLeft(p-m_ptr);
+ return true;
+}
+
+KviStr KviStr::getToken(char sep)
+{
+ register char *p=m_ptr;
+ while(*p && (*p != sep))p++;
+ KviStr ret(m_ptr,p);
+ while(*p && (*p == sep))p++;
+ cutLeft(p-m_ptr);
+ return ret;
+}
+
+KviStr & KviStr::sprintf(const char *fmt,...)
+{
+ m_ptr=(char *)kvi_realloc(m_ptr,256);
+ //First try
+ kvi_va_list list;
+ kvi_va_start(list,fmt);
+ //print...with max 256 chars
+ m_len=kvi_vsnprintf(m_ptr,256,fmt,list);
+ kvi_va_end(list);
+
+ //check if we failed
+ if(m_len < 0){
+ //yes , failed....
+ int dummy=256;
+ do{ //we failed , so retry with 256 more chars
+ dummy+=256;
+ //realloc
+ m_ptr=(char *)kvi_realloc(m_ptr,dummy);
+ //print...
+ kvi_va_start(list,fmt);
+ m_len=kvi_vsnprintf(m_ptr,dummy,fmt,list);
+ kvi_va_end(list);
+ } while(m_len < 0);
+ }
+ //done...
+ //now m_len is the length of the written string not including the terminator...
+ //perfect! :)
+ m_ptr=(char *)kvi_realloc(m_ptr,m_len+1);
+ return (*this);
+}
+
+int KviStr::find(const char *str,int idx,bool caseS) const
+{
+ if(idx >= m_len)return -1;
+ register char *p=m_ptr + idx;
+ int len = (int)strlen(str);
+ if(caseS){
+ for(;;){
+ while(*p && (*p != *str))p++;
+ if(*p){
+ if(kvi_strEqualCSN(str,p,len))return (p-m_ptr);
+ else p++;
+ } else return -1;
+ }
+ } else {
+ for(;;){
+ char tmp = toupper(*str);
+ while(*p && (toupper(*p) != tmp))p++;
+ if(*p){
+ if(kvi_strEqualCIN(str,p,len))return (p-m_ptr);
+ else p++;
+ } else return -1;
+ }
+ }
+}
+
+int KviStr::find(char c,int idx) const
+{
+ if(idx >= m_len)return -1;
+ register char *p=m_ptr + idx;
+ while(*p && (*p != c))p++;
+ return (*p ? p-m_ptr : -1);
+}
+
+
+int KviStr::findRev(const char *str,int idx,bool caseS) const
+{
+ if((m_len + idx) < 0)return -1;
+ register char *p=m_ptr + m_len + idx;
+ int len = (int)strlen(str);
+ if(caseS)
+ {
+ for(;;)
+ {
+ while((p >= m_ptr) && (*p != *str))p--;
+ if(p >= m_ptr){
+ if(kvi_strEqualCSN(str,p,len))return (p-m_ptr);
+ else p--;
+ } else return -1;
+ }
+ } else {
+ for(;;){
+ char tmp = toupper(*str);
+ while((p >= m_ptr) && (toupper(*p) != tmp))p--;
+ if(p >= m_ptr){
+ if(kvi_strEqualCIN(str,p,len))return (p-m_ptr);
+ else p--;
+ } else return -1;
+ }
+ }
+}
+
+int KviStr::findFirstIdx(char c) const
+{
+ register char *p=m_ptr;
+ while(*p && (*p != c))p++;
+ return (*p ? p-m_ptr : -1);
+}
+
+int KviStr::findFirstIdx(const char *str,bool caseS) const
+{
+ // This function can't be used to search inside
+ // multibyte encoded strings... convert your
+ // code to QString and use QString::findRev().
+ // We must throw away KviStr at all in this case...
+
+ // return QString(m_ptr).find(QString(str),0,caseS);;
+
+ // Both this KviStr and the const char * str are assumed
+ // to be in the proper (and same) encoding.
+ // If KviStr is in encoding A then QString(m_ptr) might
+ // or not be decoded correctly.
+ // Also if KviStr is in UTF-8 (for example), then
+ // a position in QString() does not map to the position in the char array
+ // since a single UNICODE char may use one or more bytes...
+
+ __range_valid(str);
+ register char *p=m_ptr;
+ int len = (int)strlen(str);
+ if(caseS){
+ for(;;){
+ while(*p && (*p != *str))p++;
+ if(*p){
+ if(kvi_strEqualCSN(str,p,len))return (p-m_ptr);
+ else p++;
+ } else return -1;
+ }
+ } else {
+ // this will NOT work for strings that aren't in the current system encoding :(
+ for(;;){
+ char tmp = toupper(*str);
+ while(*p && (toupper(*p) != tmp))p++;
+ if(*p){
+ if(kvi_strEqualCIN(str,p,len))return (p-m_ptr);
+ else p++;
+ } else return -1;
+ }
+ }
+}
+
+int KviStr::findLastIdx(char c) const
+{
+ //Empty string ?
+ if(m_len < 1)return -1;
+ //p points to the last character in the string
+ register char *p=((m_ptr+m_len)-1);
+ //go back until we find a match or we run to the first char in the string.
+ while((*p != c) && (p > m_ptr))p--;
+ //if *p == c --> matched , else we are at the beginning of the string.
+ return ((*p == c)? p-m_ptr : -1);
+}
+
+int KviStr::findLastIdx(const char *str,bool caseS) const
+{
+ // This function can't be used to search inside
+ // multibyte encoded strings... convert your
+ // code to QString and use QString::findRev().
+ // We must throw away KviStr at all in this case...
+
+ // return QString(m_ptr).findRev(QString(str),-1,caseS);
+
+ __range_valid(str);
+ //Calc the len of the searched string
+ int len = (int)strlen(str);
+ //Too long ?
+ if(m_len < len)return -1;
+ //p points to the last character in the string
+ register char *p=((m_ptr+m_len)-1);
+ if(caseS){
+ for(;;){
+ //go back until we find a character that mathes or we run to the first char.
+ while((*p != *str) && (p > m_ptr))p--;
+ if(*p == *str){
+ //maybe occurence....
+ if(kvi_strEqualCSN(str,p,len))return (p-m_ptr);
+ else {
+ //Nope...continue if there is more data to check...
+ if(p == m_ptr)return -1;
+ p--;
+ }
+ } else return -1; //Beginning of the string
+ }
+ } else {
+ // case insensitive
+ for(;;){
+ //go back until we find a character that mathes or we run to the first char.
+ char tmp = toupper(*str);
+ while((toupper(*p) != tmp) && (p > m_ptr))p--;
+ if(toupper(*p) == tmp){
+ //maybe occurence....
+ if(kvi_strEqualCIN(str,p,len))return (p-m_ptr);
+ else {
+ //Nope...continue if there is more data to check...
+ if(p == m_ptr)return -1;
+ p--;
+ }
+ } else return -1; //Beginning of the string
+ }
+ }
+}
+
+KviStr & KviStr::stripWhiteSpace()
+{
+ // 0123456789
+ // abcd 0
+ // ^ ^
+ // left right
+ register char *left=m_ptr;
+ register char *right=m_ptr+m_len-1;
+ // skip initial spaces
+ while(isspace(*left))left++;
+ if(*left){
+ // valid string , left points to first non-space
+ while((right >= left) && isspace(*right))right--;
+ // 0123456789
+ // abcd 0
+ // ^ ^
+ // left right
+ m_len = (right - left)+1;
+ kvi_memmove(m_ptr,left,m_len);
+ m_ptr = (char *)kvi_realloc(m_ptr,m_len+1);
+ *(m_ptr+m_len)='\0';
+ } else {
+ m_ptr = (char *)kvi_realloc(m_ptr,1);
+ *m_ptr = '\0';
+ m_len = 0;
+ }
+ return (*this);
+}
+
+KviStr & KviStr::stripRightWhiteSpace()
+{
+ if(*m_ptr)
+ {
+ register char *right=m_ptr+m_len-1;
+ const char *start=right;
+ while((right >= m_ptr) && isspace( *right ))right--;
+ if(right != start)
+ {
+ m_len = (right - m_ptr) + 1;
+ m_ptr = (char *)kvi_realloc(m_ptr,m_len+1);
+ *(m_ptr+m_len)='\0';
+ }
+ }
+ return (*this);
+}
+
+KviStr & KviStr::stripRight(char c)
+{
+ if(*m_ptr)
+ {
+ register char *right=m_ptr+m_len-1;
+ const char *start=right;
+ while((right >= m_ptr) && (*right == c))right--;
+ if(right != start)
+ {
+ m_len = (right - m_ptr) + 1;
+ m_ptr = (char *)kvi_realloc(m_ptr,m_len+1);
+ *(m_ptr+m_len)='\0';
+ }
+ }
+ return (*this);
+}
+
+KviStr & KviStr::stripSpace()
+{
+ // 0123456789
+ // abcd 0
+ // ^ ^
+ // left right
+ register char *left=m_ptr;
+ register char *right=m_ptr+m_len-1;
+ // skip initial spaces
+ while((*left == ' ') || (*left == '\t'))left++;
+ if(*left){
+ // valid string , left points to first non-space
+ while((right >= left) && ((*right == ' ') || (*right == '\t')))right--;
+ // 0123456789
+ // abcd 0
+ // ^ ^
+ // left right
+ m_len = (right - left)+1;
+ kvi_memmove(m_ptr,left,m_len);
+ m_ptr = (char *)kvi_realloc(m_ptr,m_len+1);
+ *(m_ptr+m_len)='\0';
+ } else {
+ m_ptr = (char *)kvi_realloc(m_ptr,1);
+ *m_ptr = '\0';
+ m_len = 0;
+ }
+ return (*this);
+}
+
+bool KviStr::isNum() const
+{
+ register char *p=m_ptr;
+ while(isspace(*p))p++;
+ if(*p=='-')p++;
+ if(!isdigit(*p))return false;
+ while(isdigit(*p))p++;
+ while(isspace(*p))p++;
+ return (*p=='\0');
+}
+
+bool KviStr::isUnsignedNum() const
+{
+ register char *p=m_ptr;
+ while(isspace(*p))p++;
+ if(!isdigit(*p))return false;
+ while(isdigit(*p))p++;
+ while(isspace(*p))p++;
+ return (*p=='\0');
+}
+
+static KviStr g_szApplicationWideEmptyString;
+
+KviStr & KviStr::emptyString()
+{
+ return g_szApplicationWideEmptyString;
+}
+
+
+bool KviStr::ext_contains(register const char * data,const char * item,bool caseS)
+{
+ if(item && data)
+ {
+ int len = (int)strlen(item);
+ char c = tolower(*item);
+ if(caseS)
+ {
+ while(*data)
+ {
+ while(*data && (tolower(*data) != c))data++;
+ if(*data)
+ {
+ if(kvi_strEqualCSN(item,data,len))return true;
+ else data++;
+ }
+ }
+ } else {
+ while(*data)
+ {
+ while(*data && (tolower(*data) != c))data++;
+ if(*data)
+ {
+ if(kvi_strEqualCIN(item,data,len))return true;
+ else data++;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+
+//void KviStr::pointerToBitString(const void * ptr)
+//{
+// m_len = (sizeof(void *) * 8);
+// m_ptr = kvi_realloc(m_ptr,m_len + 1);
+// for(int i=0;i < m_len;i++)
+// {
+// m_ptr[i] = (ptr & 1) ? '1' : '0';
+// ptr >> 1;
+// }
+// m_ptr[i] = '\0';
+//}
+//
+//void * KviStr::bitStringToPointer()
+//{
+// if(m_len != (sizeof(void *) * 8))return 0;
+// const char * aux = m_ptr;
+// void * ptr = 0;
+// for(int i=m_len - 1;i >= 0;i--)
+// {
+// if(m_ptr[i] == '1')ptr &= 1;
+// else if(m_ptr[i] !='0')return 0;
+// ptr << 1;
+// }
+// return ptr;
+//}
+
+
+
+
+// static char ascii_jump_table[256]=
+// {
+// // 000 001 002 003 004 005 006 007 008 009 010 011 012 013 014 015
+// // NUL SOH STX ETX EOT ENQ ACK BEL BS HT LF VT FF CR SO SI
+// 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+// // 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031
+// // DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US
+// 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+// // 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047
+// // ! " # $ % & ' ( ) * + , - . /
+// 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+// // 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063
+// // 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
+// 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+// // 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079
+// // @ A B C D E F G H I J K L M N O
+// 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+// // 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095
+// // P Q R S T U V W X Y Z [ \ ] ^ _
+// 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+// // 096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111
+// // ` a b c d e f g h i j k l m n o
+// 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+// // 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
+// // p q r s t u v w x y z { | } ~ 
+// 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+// // 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
+// //
+// 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+// // 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
+// //
+// 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+// // 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
+// //
+// 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+// // 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
+// //
+// 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+// // 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
+// // � � � � � � � � � � � � � � � �
+// 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+// // 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
+// // � � � � � � � � � � � � � � � �
+// 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+// // 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
+// // � � � � � � � � � � � � � � � �
+// 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+// // 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
+// // � � � � � � � �
+// 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+// };
diff --git a/src/kvilib/core/kvi_string.h b/src/kvilib/core/kvi_string.h
new file mode 100644
index 00000000..602173cd
--- /dev/null
+++ b/src/kvilib/core/kvi_string.h
@@ -0,0 +1,552 @@
+#ifndef _KVI_STRING_H_
+#define _KVI_STRING_H_
+//=============================================================================
+//
+// File : kvi_string.h
+// Creation date : Fri Mar 19 1999 03:06:26 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#ifdef HAVE_STRINGS_H
+ #include <strings.h> // useless ?
+#endif
+
+#include <qglobal.h>
+#include <qstring.h>
+
+
+#include "kvi_qcstring.h"
+#include "kvi_inttypes.h"
+#include "kvi_heapobject.h"
+#include "kvi_stdarg.h"
+
+
+
+//
+// sigh...
+// IRC is not UNICODE ...(yet) :(
+//
+
+#undef __KVI_EXTERN
+#ifdef _KVI_STRING_CPP_
+ #define __KVI_EXTERN
+#else
+ #define __KVI_EXTERN extern
+#endif
+
+
+__KVI_EXTERN KVILIB_API bool kvi_qstringEqualCI(const QString &s1,const QString &s2);
+
+
+// Include inlined assembly implementations if required
+#ifdef COMPILE_ix86_ASM
+ #include "kvi_strasm.h"
+#else
+ // Returns true if the string str1 is equal to str2. case sensitive.
+ __KVI_EXTERN KVILIB_API bool kvi_strEqualCS(const char *str1,const char *str2);
+ // Returns true if the forst len characters of string str1 are equal to str2.
+ // case sensitive.
+ // Note that if str1 or str2 are shorter than len characters then are considered as NOT equal!
+ __KVI_EXTERN KVILIB_API bool kvi_strEqualCSN(const char *str1,const char *str2,int len);
+ // no such tricks in non-asm
+ #define kvi_strEqualNoLocaleCI(str1,str2) kvi_strEqualCI(str1,str2)
+ #define kvi_strEqualNoLocaleCIN(str1,str2,len) kvi_strEqualCIN(str1,str2,len)
+ #define kvi_strLen(str) strlen(str)
+#endif
+
+// Returns true if the string str1 is equal to str2.
+// case insensitive.
+__KVI_EXTERN KVILIB_API bool kvi_strEqualCI(const char *str1,const char *str2);
+// Returns true if the forst len characters of string str1 are equal to str2.
+// case insensitive.
+// Note that if str1 or str2 are shorter than len characters then are considered as NOT equal!
+__KVI_EXTERN KVILIB_API bool kvi_strEqualCIN(const char *str1,const char *str2,int len);
+// My own implementations of strcmp and strncasecmp
+// Once I wrote it , I KNOW what they do : ALWAYS :)
+// Note that greater here means that comes AFTER in the alphabetic order.
+__KVI_EXTERN KVILIB_API int kvi_strcmpCI(const char *str1,const char *str2);
+//__KVI_EXTERN KVILIB_API int kvi_strcmpCIN(const char *str1,const char *str2,int len);
+__KVI_EXTERN KVILIB_API int kvi_strcmpCS(const char *str1,const char *str2);
+
+// some wide char stuff
+typedef kvi_u16_t kvi_wchar_t;
+typedef kvi_u32_t kvi_wslen_t;
+
+__KVI_EXTERN KVILIB_API kvi_wslen_t kvi_wstrlen(const kvi_wchar_t * str);
+__KVI_EXTERN KVILIB_API int kvi_wvsnprintcf(kvi_wchar_t * buffer,kvi_wslen_t len,const char *fmt,kvi_va_list list);
+__KVI_EXTERN KVILIB_API int kvi_wvsnprintf(kvi_wchar_t * buffer,kvi_wslen_t len,const kvi_wchar_t *fmt,kvi_va_list list);
+
+//=============================================================================
+//
+// A simple string class.<br>
+// -No data sharing.<br>
+// -Not UNICODE.<br>
+// -Has ALWAYS NON-NULL DATA.<br>
+// -(Maybe)Unsafe :)<br>
+// WARNING : Handle with care and use at own risk :)<br>
+//
+//=============================================================================
+
+class KVILIB_API KviStr : public KviHeapObject
+{
+public:
+ // No particular reason for these two names...
+ // It is just because I like it :)
+
+ enum KviFormatConstructorTag { Format , Sprintf };
+
+ //=============================================================================
+ // Constructors
+ //=============================================================================
+
+ // Empty string == "", len = 0, 1 byte allocated
+ KviStr();
+
+ // Deep copy of the NULL TERMINATED string (NULL str SAFE)
+ KviStr(const char *str);
+
+ // Copy len characters from string str (NOT NULL str SAFE, str MUST be at least len chars long)
+ KviStr(const char *str,int len);
+
+ // bg and end are pointers to a SINGLE string.<br>
+ // A string is extracted starting from bg and ending at end (not included).<br>
+ KviStr(const char *bg,const char *end);
+
+ // Format constructor.<br>
+ // tag is....yes....a dummy number used to resolve ambiguities.<br>
+ // It is SAFE: will fail only if we run out of memory,<br>
+ // but can handle only %s %d %u and %c.
+ KviStr(KviFormatConstructorTag tag,const char *fmt,...);
+
+ // Carbon copy :)...fast
+ KviStr(const KviStr &str);
+
+ // Compat with QT...<br>
+ // WARNING : With QT2.x it WILL loose UNICODE data.<br>
+ // Safe even if the QString is null.
+ KviStr(const QString &str);
+
+ KviStr(const KviQCString &str);
+
+ // Fill sonstructor.
+ // Creates a string long fillLen characters filled with character c.<br>
+ KviStr(char c,int fillLen = 1);
+
+ KviStr(const kvi_wchar_t * unicode);
+
+ KviStr(const kvi_wchar_t * unicode,int len);
+
+ // just free(m_ptr)
+ ~KviStr();
+public:
+ //yes...public..but think it as private...:)
+ char *m_ptr; // pointer to allocated buffer , do not change this!
+ int m_len; // string data length not including the terminator
+
+public:
+ //=============================================================================
+ // Basic const interface (read stuff)
+ //=============================================================================
+
+ // Internal data buffer
+ char * ptr() const { return m_ptr; };
+ // Length: fast, cached
+ int len() const { return m_len; };
+
+ // I hate this operator...but sometimes it is really useful
+ // especially in macros (kvi_options.cpp)
+ operator const char * () const { return m_ptr; };
+
+ bool isEmpty() const { return (m_len == 0); };
+ bool hasData() const { return (m_len != 0); };
+
+ // this is better than string = "", it does not call strlen
+ void clear();
+
+ // forces the length of this string to be iLen (iLen does NOT include the trailing null : it is automatically added)
+ void setLength(int iLen);
+
+ // Returns true if there is something "readable" inside the string
+ bool hasNonWhiteSpaceData() const;
+
+ // Character at zero-based index : always safe!
+ char & at(int idx) const { return ((idx < m_len) ? m_ptr[idx] : m_ptr[m_len]); };
+
+ // character checks
+ bool lastCharIs(char ch) const { return (m_len > 0) ? (*(m_ptr + m_len - 1) == ch) : false; };
+ bool firstCharIs(char ch) const { return (*m_ptr == ch); };
+
+ // upper and lower case copies
+ KviStr upper() const;
+ KviStr lower() const;
+ KviStr upperISO88591() const;
+ KviStr lowerISO88591() const;
+
+ // left , right & co.
+ // all parameters are safety-checked
+ KviStr left(int maxLen) const;
+ KviStr right(int maxLen) const ;
+ KviStr middle(int idx,int maxLen) const;
+
+ KviStr leftToFirst(char c,bool bIncluded = false) const;
+ KviStr leftToLast(char c,bool bIncluded = false) const;
+// KviStr leftToFirst(const char * str); const;
+
+ //=============================================================================
+ // Non-const interface (write stuff)
+ //=============================================================================
+
+ // Null terminator is NOT included in len
+ KviStr & setLen(int len);
+ // str must not be 0, but len can be anything (it is checked)
+ KviStr & setStr(const char *str,int len = -1);
+ // Like the special constructor that gets the same args.
+ void extractFromString(const char *begin,const char *end);
+
+
+ // Safe sprintf. This one will never write past the end of the string
+ // It can handle only %s %d %u and %c format flags.
+ KviStr & sprintf(const char *fmt,...);
+
+ // append functions
+ void append(const KviStr &str);
+ void append(const QString &str);
+ void append(char c);
+ void append(const char *str); // str CAN be 0
+ void append(const char *str,int len); // str CAN NOT be 0, and MUST be at least len chars long
+ void append(KviFormatConstructorTag dummy,const char *fmt,...);
+
+ // prepend stuff , same as above
+ void prepend(const KviStr &str);
+ void prepend(const char *str); // str CAN be 0
+ void prepend(const char *str,int len); // str CAN NOT be 0, and MUST be at least len chars long
+
+ // if lastCharIs ch does nothing otherwise appends it
+ void ensureLastCharIs(char ch) { if(!lastCharIs(ch))append(ch); };
+
+ // Change THIS string to uppercase or lowercase
+ void toUpperISO88591();
+ void toUpper(); // this is LOCALE AWARE (in Turkish it maps i to Ý!)
+ void toLowerISO88591();
+ void toLower();
+
+ // Assignment
+ KviStr & operator=(const KviStr &str); // deep copy
+ KviStr & operator=(const char *str); // str can be NULL here
+ KviStr & operator=(char c); // 2 bytes allocated ,m_len = 1
+ KviStr & operator=(const QString &str);
+ KviStr & operator=(const KviQCString &str);
+
+ // Append operators
+ KviStr & operator+=(const KviStr &str) { append(str); return (*this); };
+ KviStr & operator+=(const char *str) { append(str); return (*this); };
+ KviStr & operator+=(char c) { append(c); return (*this); };
+ KviStr & operator+=(const QString &str) { append(str); return (*this); };
+
+ // Comparison
+ bool equalsCI(const KviStr &other) const { if(m_len != other.m_len)return false; return kvi_strEqualCI(m_ptr,other.m_ptr); };
+ bool equalsCS(const KviStr &other) const { if(m_len != other.m_len)return false; return kvi_strEqualCS(m_ptr,other.m_ptr); };
+ bool equalsCI(const char * other) const { return kvi_strEqualCI(m_ptr,other); };
+ bool equalsCS(const char * other) const { return kvi_strEqualCS(m_ptr,other); };
+ bool equalsCIN(const char * other,int len) const { return kvi_strEqualCIN(m_ptr,other,len); };
+ bool equalsCSN(const char * other,int len) const { return kvi_strEqualCSN(m_ptr,other,len); };
+
+ //=============================================================================
+ // HEX and Base64 stuff
+ //=============================================================================
+
+ // HEX transforms functions
+ void bufferToHex(const char *buffer,int len);
+ // Allocates the needed buffer and returns the allocated length,
+ // returns -1 in case of error (and allocates nothing)
+ // The string MUST contain only hex digits, and the digits MUST be in couples. (len % 2) must equal 0!
+ // So this will fail also if there are leading or trailing spaces!
+ int hexToBuffer(char ** buffer,bool bNullToNewlines = false);
+ // BASE64 stuff
+ void bufferToBase64(const char * buffer,int len);
+ // same as hexToBuffer but obviously transforms base64 notation to binary data (len % 4) must equal 0!
+ int base64ToBuffer(char ** buffer,bool bNullToNewlines = false);
+
+ // frees a buffer allocated by hexToBuffer or base64ToBuffer
+ static void freeBuffer(char * buffer);
+
+ //=============================================================================
+ // Splitters
+ //=============================================================================
+
+ // cut
+ KviStr & cutLeft(int len); // kills the first len characters
+ KviStr & cutRight(int len); // kills the last len characters
+ KviStr & cut(int idx,int len);
+ KviStr & cutToFirst(char c,bool bIncluded = true); // cuts the left part of the string up to the first character c or does nothing if the char c is not in the string
+ KviStr & cutToLast(char c,bool bIncluded = true);
+ KviStr & cutFromFirst(char c,bool bIncluded = true);
+ KviStr & cutFromLast(char c,bool bIncluded = true);
+ KviStr & cutToFirst(const char *c,bool bIncluded = true); // cuts the left part of the string up to the first character c or does nothing if the char c is not in the string
+ KviStr & cutToLast(const char *c,bool bIncluded = true);
+ KviStr & cutFromFirst(const char *c,bool bIncluded = true);
+ KviStr & cutFromLast(const char *c,bool bIncluded = true);
+ // & paste
+ KviStr & insert(int idx,const char *data);
+ KviStr & insert(int idx,char c);
+ //Replaces all occurences of char c with the string str
+ KviStr & replaceAll(char c,const char *str);
+ //same as above but with a string
+ KviStr & replaceAll(char *toFind,const char *str,bool bCaseS = true);
+
+ KviStr & transliterate(const char * szToFind,const char * szReplacement);
+
+ // Strips whitespace characters from beginning of this string.
+ KviStr & stripLeftWhiteSpace();
+ KviStr & stripRightWhiteSpace();
+ // Stips inital and final WHITESPACE characters (see man isspace),<br>
+ // and returns a reference to this string.
+ KviStr & stripWhiteSpace();
+
+ // Strips spaces and tabs only
+ KviStr & stripSpace();
+ // Strips all occurences of the character c from the beginning of the string.<br>
+ // Note that c can not be '\0' :)
+ KviStr & stripLeft(char c);
+ KviStr & stripRight(char c);
+
+ //=============================================================================
+ // Tokenize
+ //=============================================================================
+
+ // Extracts (copy to str and remove) a token from this string ,<br>
+ // and returns true if there are more tokens to extract<br>
+ // Does not strip initial separators!!<br>
+ // str can NOT be this string.
+ bool getToken(KviStr &str,char sep);
+ // Does not strip initial separators!<br>
+ // Can assign also to this string.
+ KviStr getToken(char sep);
+ // Extracts a line from the string.<br>
+ // Returns false if there was no data to extract
+ bool getLine(KviStr &str);
+
+ // splits this string in a null-terminated array of strings
+ // separated by sep.
+ KviStr ** splitToArray(char sep,int max,int * realCount) const;
+ //KviStr ** splitToArray(const char * sep,int max,int * realCount) const;
+ static void freeArray(KviStr ** strings);
+ // joins the array to this string
+ // if sep is not 0 , it is inserted between the strings
+ // if bLastSep is true and sep is non 0 , then sep is also appended at the end
+ // of the buffer (after the last string)
+ void joinFromArray(KviStr ** strings,const char * sep = 0,bool bLastSep = false);
+
+ //=============================================================================
+ // Utils
+ //=============================================================================
+
+ // encodes chars that have nonzero in the jumptable
+ // into %HH equivalents
+ KviStr & hexEncodeWithTable(const unsigned char table[256]);
+ KviStr & hexEncodeWhiteSpace();
+ KviStr & hexDecode(const char * pFrom);
+ KviStr & hexDecode(){ return hexDecode(m_ptr); };
+
+ //=============================================================================
+ // Contains / occurence count
+ //=============================================================================
+
+ // Returns true if at least one occurence of str is found
+ bool contains(const char *str,bool caseS=true) const;
+ // Returns true if at least one occurence of character c is found in this string
+ bool contains(char c,bool caseS=true) const;
+ // Returns the number of occurences of string str in this string.<br>
+ // Overlapped matches are counted.
+ int occurences(const char *str,bool caseS=true) const;
+ // Returns the number of occurences of character c in this string
+ int occurences(char c,bool caseS=true) const;
+
+ //=============================================================================
+ // Find
+ //=============================================================================
+
+ // Finds the first occurence of the character c in this string,<br>
+ // and returns its zero-based index or -1 if c can not be found.<br>
+ // c can NOT be '\0' here.
+ int findFirstIdx(char c) const;
+ // Finds the first occurence of the sub-string str in this string,<br>
+ // and returns its zero-based index or -1 if the sub-string can not be found.<br>
+ // str can NOT be 0 here.
+ int findFirstIdx(const char *str,bool caseS = true) const;
+ // Finds the last occurence of the character c in this string,<br>
+ // and returns its zero-based index or -1 if the character can not be found.
+ int findLastIdx(char c) const;
+ // Finds the last occurence of the sub-string str in this string,<br>
+ // and returns its zero-based index or -1 if the sub-string can not be found.<br>
+ // str can NOT be 0 here.
+ int findLastIdx(const char *str,bool caseS = true) const;
+
+ int find(char c,int startIdx) const;
+ int find(const char * str,int startIdx,bool caseS = true) const;
+ int findRev(const char * str,int startIdx,bool caseS = true) const;
+
+ //=============================================================================
+ // Numbers
+ //=============================================================================
+
+ // everything in base 10.... no overflow checks here
+ long toLong(bool *bOk=0) const;
+ unsigned long toULong(bool *bOk=0) const;
+ char toChar(bool *bOk=0) const { return (char)toLong(bOk); };
+ unsigned char toUChar(bool *bOk=0) const { return (unsigned char)toULong(bOk); };
+ int toInt(bool *bOk=0) const { return (int)toLong(bOk); };
+ unsigned int toUInt(bool *bOk=0) const { return (unsigned int)toULong(bOk); };
+ short toShort(bool *bOk=0) const { return (short)toLong(bOk); };
+ unsigned short toUShort(bool *bOk=0) const { return (unsigned short)toLong(bOk); };
+
+ KviStr & setNum(long num);
+ KviStr & setNum(unsigned long num);
+
+ KviStr & setNum(int num) { return setNum((long)num); };
+ KviStr & setNum(unsigned int num) { return setNum((unsigned long)num); };
+ KviStr & setNum(short num) { return setNum((long)num); };
+ KviStr & setNum(unsigned short num) { return setNum((unsigned long)num); };
+ KviStr & setNum(char num) { return setNum((long)num); };
+ KviStr & setNum(unsigned char num) { return setNum((unsigned long)num); };
+
+ // Retuns true if the string contains only digits and an optional '-' character
+ // at the beginning.<be>
+ // Space characters are allowed at the begginning and the end.<br>
+ // There is no overflow check!
+ bool isNum() const;
+ bool isUnsignedNum() const;
+
+ // special functions for multiple bases
+ long toLongExt(bool *bOk = 0,int base = 0);
+ // unsigned long toULongExt(bool *bOk = 0,int base = 0); //never used
+
+ // returns an empty string...
+ // this if often useful!
+ static KviStr & emptyString();
+
+ //=============================================================================
+ // Dead interface
+ //=============================================================================
+
+ // Transform a pointer to a string with all 0 and 1
+ // void pointerToBitString(const void * ptr);
+ // Get a pointer from a string all of 0 and 1 : return 0 if invalid
+ // void * bitStringToPointer();
+
+ //=============================================================================
+ // "External string" helper functions
+ //=============================================================================
+
+ // FIXME: Should it be KviStrExt::contains namespace ?
+ static bool ext_contains(register const char * data,const char * item,bool caseS = true);
+};
+
+// FIXME: the functions below should end in the KviStr namespace ???
+
+
+// Cool string parsing function.
+// It will extract the first found token from the string aux_ptr , and return
+// a pointer to the beginning of the next token , or end of the string.
+// It skips the initial sep characters!
+__KVI_EXTERN KVILIB_API const char * kvi_extractToken(KviStr &str,const char *aux_ptr,char sep =' ');
+// Does not skip the beginning separators!
+// Extracts data from the string up to the next separator character or the end of the string.
+// and returns a pointer to that separator (or string end).
+__KVI_EXTERN KVILIB_API const char * kvi_extractUpTo(KviStr &str,const char *aux_ptr,char sep=' ');
+// Reduced vsnprintf...
+// Handles %s,%c,%d,%u (%% are TWO percents here and not one.)
+// Returns -1 if the formatted string exceeded the buffer length.
+// Otherwise returns the length of the formatted buffer...(not including '\0')
+__KVI_EXTERN KVILIB_API int kvi_vsnprintf(char *buffer,int len,const char *fmt,kvi_va_list list);
+// Reduced vsnprintf: special version for irc.
+// Handles %s,%c,%d,%u (%% are TWO percents here and not one.)
+// Writes up to 510 characters and terminates the string with a CRLF
+// Sets bTruncated if the requested format string was too large to fit in 512 bytes
+// otherwise sets it to false; The buffer MUST be at least 512 bytes long.
+// Always returns the length of the formatted buffer...(max 512 - min 2=CRLF)
+__KVI_EXTERN KVILIB_API int kvi_irc_vsnprintf(char *buffer,const char *fmt,kvi_va_list list,bool *bTruncated);
+
+// WILDCARD EXPRESSION MATCHING FUNCTIONS
+
+// Returns true if the two regular expressions with wildcards matches
+__KVI_EXTERN KVILIB_API bool kvi_matchWildExpr(register const char *m1,register const char *m2);
+// Returns true if the two regular expressions with wildcards matches, case sensitive
+//__KVI_EXTERN bool kvi_matchWildExprCS(register const char *m1,register const char *m2); // actually unused
+// Same as kvi_matchWildExpr but with an additional char that acts as string terminator
+// If there is a match this function returns true and puts the pointers where it stopped in r1 and r2
+__KVI_EXTERN KVILIB_API bool kvi_matchWildExprWithTerminator(register const char *m1,register const char *m2,char terminator,
+ const char ** r1,const char ** r2);
+
+// Returns true if the wildcard expression exp matches the string str
+__KVI_EXTERN KVILIB_API bool kvi_matchStringCI(register const char * exp,register const char * str);
+#define kvi_matchString kvi_matchStringCI
+__KVI_EXTERN KVILIB_API bool kvi_matchStringCS(register const char * exp,register const char * str);
+__KVI_EXTERN KVILIB_API bool kvi_matchStringWithTerminator(register const char * exp,register const char * str,char terminator,const char ** r1,const char ** r2);
+
+// This function works like a particular case of strncmp.
+// It evaluates if str2 is the terminal part of str1.
+// example: if str1 is "this is an experiment" and str2 is "xperiment"
+// return 0.
+// With the index parameter, the match start on str1 from the specified
+// index. For example:
+// if str1 is "this is an experiment" and str2 is "an" we have return !0
+// but "this is an experiment"
+// 012345678901234567890
+// if we call kvi_strsubRevCS("this is an experiment","an", 9) we got a match.
+__KVI_EXTERN KVILIB_API int kvi_strMatchRevCS(const char *str1, const char *str2, int index=-1);
+
+// KviStr comparison non-member operators
+__KVI_EXTERN KVILIB_API inline bool operator==(const KviStr &left,const KviStr &right)
+{ return (left.m_len == right.m_len) ? kvi_strEqualCS(left.m_ptr,right.m_ptr) : false; }
+__KVI_EXTERN KVILIB_API inline bool operator==(const KviStr &left,const char *right)
+{ return kvi_strEqualCS(left.m_ptr,right); }
+__KVI_EXTERN KVILIB_API inline bool operator==(const char *left,const KviStr &right)
+{ return kvi_strEqualCS(left,right.m_ptr); }
+__KVI_EXTERN KVILIB_API inline bool operator!=(const KviStr &left,const KviStr &right)
+{ return !kvi_strEqualCS(left.m_ptr,right.m_ptr); }
+__KVI_EXTERN KVILIB_API inline bool operator!=(const KviStr &left,const char *right)
+{ return !kvi_strEqualCS(left.m_ptr,right); }
+__KVI_EXTERN KVILIB_API inline bool operator!=(const char *left,const KviStr &right)
+{ return !kvi_strEqualCS(left,right.m_ptr); }
+
+__KVI_EXTERN KVILIB_API inline KviStr operator+(const KviStr &left,const KviStr &right)
+{ KviStr ret(left); ret += right; return ret; }
+__KVI_EXTERN KVILIB_API inline KviStr operator+(const KviStr &left,const char *right)
+{ KviStr ret(left); ret += right; return ret; }
+__KVI_EXTERN KVILIB_API inline KviStr operator+(const char *left,const KviStr &right)
+{ KviStr ret(left); ret += right; return ret; }
+__KVI_EXTERN KVILIB_API inline KviStr operator+(const KviStr &left,char right)
+{ KviStr ret(left); ret += right; return ret; }
+__KVI_EXTERN KVILIB_API inline KviStr operator+(char left,const KviStr &right)
+{ KviStr ret(left); ret += right; return ret; }
+
+inline int kvi_compare(const KviStr * p1,const KviStr * p2)
+{
+ return kvi_strcmpCI(p1->ptr(),p2->ptr());
+}
+
+#endif //_KVI_STRING_H_
diff --git a/src/kvilib/core/kvi_stringarray.cpp b/src/kvilib/core/kvi_stringarray.cpp
new file mode 100644
index 00000000..d160ce28
--- /dev/null
+++ b/src/kvilib/core/kvi_stringarray.cpp
@@ -0,0 +1,119 @@
+//=================================================================================================
+//
+// File : kvi_stringarray.cpp
+// Creation date : Tue Jun 6 02:20:20 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=================================================================================================
+
+#define __KVILIB__
+
+
+#include "kvi_stringarray.h"
+#include "kvi_malloc.h"
+
+KviStringArray::KviStringArray()
+{
+ m_uSize = 0;
+ m_pData = 0;
+ m_uHighestIdx = 0;
+}
+
+KviStringArray::~KviStringArray()
+{
+ if(m_pData)clear();
+}
+
+
+void KviStringArray::clear()
+{
+ if(!m_pData)return;
+ for(unsigned int i=0;i<m_uSize;i++)
+ {
+ if(m_pData[i])delete m_pData[i];
+ }
+ kvi_free(m_pData);
+ m_pData = 0;
+ m_uHighestIdx = 0;
+ m_uSize = 0;
+}
+
+void KviStringArray::insert(unsigned int uIdx,KviStr * pVal)
+{
+ if(m_uSize <= uIdx)
+ {
+ unsigned int uOldSize = m_uSize;
+ m_uSize = uIdx + KVI_STRING_ARRAY_FREESPACE_SIZE;
+ m_pData = (KviStr **)kvi_realloc(m_pData,m_uSize * sizeof(KviStr *));
+ for(unsigned int u = uOldSize;u < m_uSize;u++)
+ {
+ m_pData[u] = 0;
+ }
+ } else {
+ if(m_pData[uIdx])delete m_pData[uIdx];
+ }
+ if(uIdx > m_uHighestIdx)m_uHighestIdx = uIdx;
+ m_pData[uIdx] = pVal;
+}
+
+void KviStringArray::remove(unsigned int uIdx)
+{
+ if(uIdx > m_uHighestIdx)return;
+ if(m_pData[uIdx])
+ {
+ delete m_pData[uIdx];
+ m_pData[uIdx] = 0;
+ if(uIdx == m_uHighestIdx)
+ {
+ // shrink the array
+ if(m_uHighestIdx == 0)clear();
+ else {
+ unsigned int u = m_uHighestIdx - 1;
+ while(!m_pData[u])u--;
+ if((m_uHighestIdx - u) > KVI_STRING_ARRAY_FREESPACE_SIZE)shrink(u);
+ else m_uHighestIdx = u; // just set the max index
+ }
+ }
+ }
+}
+
+void KviStringArray::shrink(unsigned int uMaxItem)
+{
+ m_uHighestIdx = uMaxItem;
+ m_uSize = uMaxItem + 1;
+ m_pData = (KviStr **)kvi_realloc(m_pData,sizeof(KviStr *) * m_uSize);
+}
+
+void KviStringArray::copyFrom(KviStringArray * a)
+{
+ clear();
+ m_uSize = a->m_uSize;
+ m_uHighestIdx = a->m_uHighestIdx;
+ if(m_uSize > 0)
+ {
+ m_pData = (KviStr **)kvi_malloc(sizeof(KviStr *) * m_uSize);
+ for(unsigned int i=0;i<m_uSize;i++)
+ {
+ if(a->m_pData[i])m_pData[i] = new KviStr(*(a->m_pData[i]));
+ else m_pData[i] = 0;
+ }
+ } else {
+ m_pData = 0;
+ }
+}
diff --git a/src/kvilib/core/kvi_stringarray.h b/src/kvilib/core/kvi_stringarray.h
new file mode 100644
index 00000000..3db9a564
--- /dev/null
+++ b/src/kvilib/core/kvi_stringarray.h
@@ -0,0 +1,55 @@
+#ifndef _KVI_STRINGARRAY_H_
+#define _KVI_STRINGARRAY_H_
+//=================================================================================================
+//
+// File : kvi_stringarray.h
+// Creation date : Tue Jun 6 02:20:20 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=================================================================================================
+
+#include "kvi_settings.h"
+#include "kvi_string.h"
+#include "kvi_heapobject.h"
+
+#define KVI_STRING_ARRAY_FREESPACE_SIZE 16
+
+class KVILIB_API KviStringArray : public KviHeapObject
+{
+public:
+ KviStringArray();
+ ~KviStringArray();
+public:
+ unsigned int m_uSize;
+ unsigned int m_uHighestIdx;
+ KviStr ** m_pData;
+public:
+ void clear();
+ void insert(unsigned int uIdx,KviStr * pVal);
+ void copyFrom(KviStringArray * a);
+ unsigned int size(){ return (m_uSize == 0) ? 0 : (m_uHighestIdx + 1); };
+ bool isEmpty(){ return m_uSize == 0; };
+ void remove(unsigned int uIdx);
+ void shrink(unsigned int uMaxItem);
+ KviStr * uncheckedAt(unsigned int uIdx){ return m_pData[uIdx]; };
+ KviStr * at(unsigned int uIdx){ return m_uSize > uIdx ? m_pData[uIdx] : 0; };
+ KviStr * getAt(unsigned int uIdx){ KviStr * t = at(uIdx); if(t)m_pData[uIdx] = 0; return t; };
+};
+
+#endif //_KVI_STRINGARRAY_H_
diff --git a/src/kvilib/core/kvi_valuelist.h b/src/kvilib/core/kvi_valuelist.h
new file mode 100644
index 00000000..fde9d5b6
--- /dev/null
+++ b/src/kvilib/core/kvi_valuelist.h
@@ -0,0 +1,37 @@
+#ifndef _KVI_VALUELIST_H_
+#define _KVI_VALUELIST_H_
+//=================================================================================================
+//
+// File : kvi_valuelist.h
+// Creation date : Mon Jan 15 2007 04:53 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=================================================================================================
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_USE_QT4
+ #include <q3valuelist.h>
+ #define KviValueList Q3ValueList
+#else
+ #include <qvaluelist.h>
+ #define KviValueList QValueList
+#endif
+
+#endif //_KVI_VALUELIST_H_
diff --git a/src/kvilib/ext/Makefile.am b/src/kvilib/ext/Makefile.am
new file mode 100644
index 00000000..c84487eb
--- /dev/null
+++ b/src/kvilib/ext/Makefile.am
@@ -0,0 +1,5 @@
+###############################################################################
+# KVirc IRC client Makefile - 16.12.98 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+EXTRA_DIST = *.cpp *.h
diff --git a/src/kvilib/ext/kvi_accel.h b/src/kvilib/ext/kvi_accel.h
new file mode 100644
index 00000000..34cca3c1
--- /dev/null
+++ b/src/kvilib/ext/kvi_accel.h
@@ -0,0 +1,38 @@
+#ifndef _KVI_ACCEL_H_
+#define _KVI_ACCEL_H_
+
+//=============================================================================
+//
+// File : kvi_accel.h
+// Creation date : Wed Feb 01 2007 01:45:21 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_USE_QT4
+ #include <q3accel.h>
+ #define KviAccel Q3Accel
+#else
+ #include <qaccel.h>
+ #define KviAccel QAccel
+#endif
+
+#endif //!_KVI_ACCEL_H_
diff --git a/src/kvilib/ext/kvi_cmdformatter.cpp b/src/kvilib/ext/kvi_cmdformatter.cpp
new file mode 100644
index 00000000..e2b3e1f6
--- /dev/null
+++ b/src/kvilib/ext/kvi_cmdformatter.cpp
@@ -0,0 +1,242 @@
+//=============================================================================
+//
+// File : kvi_cmdformatter.cpp
+// Creation date : Tue Jun 12 2001 03:08:12 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+
+#include "kvi_cmdformatter.h"
+
+namespace KviCommandFormatter
+{
+ bool hasLeadingChars(KviStr ** array,char c)
+ {
+ if(!(*array))return false; // can't have more leading chars
+ bool bGotIt = false;
+ while(*array)
+ {
+ if(*((*array)->ptr()) == c)
+ {
+ // found at least one such leading char
+ bGotIt = true;
+ } else {
+ // we pretend this line to be empty
+ KviStr tmp = *(*array);
+ tmp.stripWhiteSpace();
+ if(tmp.hasData())return false;
+ *(*array) = ""; // set it to empty also in the main buffer
+ }
+ array++;
+ }
+ return bGotIt;
+ }
+
+ bool hasLeadingChars(QStringList &list,const QChar &c)
+ {
+ bool bGotIt = false;
+ for(QStringList::Iterator it = list.begin();it != list.end();++it)
+ {
+ if((*it).length() < 1)continue;
+ if((*it).at(0) == c)
+ {
+ // found at least one such leading char
+ bGotIt = true;
+ } else {
+ // we pretend this line to be empty
+ QString tmp = *it;
+#ifdef COMPILE_USE_QT4
+ tmp = tmp.trimmed();
+#else
+ tmp = tmp.stripWhiteSpace();
+#endif
+ if(!tmp.isEmpty())return false;
+ *it = ""; // set it to empty also in the main buffer
+ }
+ }
+ return bGotIt;
+ }
+
+ void trimLeading(KviStr ** array)
+ {
+ while(*array)
+ {
+ if((*array)->hasData())(*array)->cutLeft(1);
+ array++;
+ }
+ }
+
+ void trimLeading(QStringList &list)
+ {
+ for(QStringList::Iterator it = list.begin();it != list.end();++it)
+ {
+ (*it).remove(0,1);
+ }
+ }
+
+
+ void addLeading(KviStr ** array,char c)
+ {
+ while(*array)
+ {
+ if((*array)->hasData())(*array)->prepend(c);
+ array++;
+ }
+ }
+
+ void addLeading(QStringList &list,const QChar & c)
+ {
+ for(QStringList::Iterator it = list.begin();it != list.end();++it)
+ {
+ (*it).prepend(c);
+ }
+ }
+
+
+ void unindent(KviStr &buffer)
+ {
+ // we can format correctly up to 65536 lines (that's really enough)
+ int realLen;
+ KviStr ** array = buffer.splitToArray('\n',65536,&realLen);
+ if(array)
+ {
+ while(hasLeadingChars(array,'\t') || hasLeadingChars(array,' '))trimLeading(array);
+ buffer.joinFromArray(array,"\n",true);
+ KviStr::freeArray(array);
+ }
+ }
+
+
+ void unindent(QString &buffer)
+ {
+#ifdef COMPILE_USE_QT4
+ QStringList list = buffer.split("\n",QString::KeepEmptyParts);
+#else
+ QStringList list = QStringList::split("\n",buffer,true);
+#endif
+ while(hasLeadingChars(list,QChar('\t')) || hasLeadingChars(list,QChar(' ')))trimLeading(list);
+ //buffer = list.join("\n"); join implementation sux :D
+ // we WANT the last newline
+ buffer = "";
+ for(QStringList::Iterator it = list.begin();it != list.end();++it)
+ {
+ buffer.append(*it);
+ buffer.append(QChar('\n'));
+ }
+ }
+
+
+ void bufferFromBlock(KviStr &buffer)
+ {
+ buffer.stripWhiteSpace();
+
+ if((*(buffer.ptr()) == '{') && buffer.lastCharIs('}'))
+ {
+ // leading and trailing { must be stripped
+ buffer.cutLeft(1);
+ buffer.cutRight(1);
+ }
+
+ unindent(buffer);
+
+ buffer.stripWhiteSpace();
+ }
+
+ void bufferFromBlock(QString &buffer)
+ {
+#ifdef COMPILE_USE_QT4
+ buffer = buffer.trimmed();
+#else
+ buffer = buffer.stripWhiteSpace();
+#endif
+
+ if(buffer.isEmpty())return;
+
+ if((buffer.at(0) == QChar('{')) && buffer.endsWith(QChar('}')))
+ {
+ buffer.remove(0,1);
+ buffer.remove(buffer.length() - 1,1);
+ while((buffer.length() > 0) && ((buffer.at(0) == QChar('\n')) || (buffer.at(0) == QChar('\r'))))
+ buffer.remove(0,1);
+ }
+
+ unindent(buffer);
+
+#ifdef COMPILE_USE_QT4
+ buffer = buffer.trimmed();
+#else
+ buffer = buffer.stripWhiteSpace();
+#endif
+ }
+
+
+ void indent(KviStr &buffer)
+ {
+ // we can format correctly up to 65536 lines (that's really enough)
+ int realLen;
+ KviStr ** array = buffer.splitToArray('\n',65536,&realLen);
+ if(array)
+ {
+ addLeading(array,'\t');
+ buffer.joinFromArray(array,"\n",true);
+ KviStr::freeArray(array);
+ }
+ }
+
+ void indent(QString &buffer)
+ {
+#ifdef COMPILE_USE_QT4
+ QStringList list = buffer.split("\n",QString::KeepEmptyParts);
+#else
+ QStringList list = QStringList::split("\n",buffer,true);
+#endif
+ addLeading(list,QChar('\t'));
+ //buffer = list.join("\n"); join implementation sux :D
+ // we WANT the last newline
+ buffer = "";
+ for(QStringList::Iterator it = list.begin();it != list.end();++it)
+ {
+ buffer.append(*it);
+ buffer.append(QChar('\n'));
+ }
+ }
+
+
+ void blockFromBuffer(KviStr &buffer)
+ {
+ indent(buffer);
+ buffer.prepend("{\n");
+ buffer.stripRightWhiteSpace();
+ buffer.ensureLastCharIs('\n');
+ buffer.append("}\n");
+ }
+
+ void blockFromBuffer(QString &buffer)
+ {
+ indent(buffer);
+ buffer.prepend("{\n");
+ KviQString::stripRightWhiteSpace(buffer);
+ KviQString::ensureLastCharIs(buffer,'\n');
+ buffer.append("}\n");
+ }
+};
+
+// FIXME: #warning "move popups and events to this formatting stuff!"
diff --git a/src/kvilib/ext/kvi_cmdformatter.h b/src/kvilib/ext/kvi_cmdformatter.h
new file mode 100644
index 00000000..b6efa98b
--- /dev/null
+++ b/src/kvilib/ext/kvi_cmdformatter.h
@@ -0,0 +1,64 @@
+#ifndef _KVI_CMDFORMATTER_H_
+#define _KVI_CMDFORMATTER_H_
+
+//=============================================================================
+//
+// File : kvi_cmdformatter.h
+// Creation date : Tue Jun 12 2001 03:04:05 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_string.h"
+#include "kvi_settings.h"
+
+#include "kvi_qstring.h"
+#include <qstringlist.h>
+
+namespace KviCommandFormatter
+{
+ extern KVILIB_API bool hasLeadingChars(KviStr * array,char c);
+ extern KVILIB_API bool hasLeadingChars(QStringList &list,const QChar &c);
+
+ extern KVILIB_API void trimLeading(KviStr ** array);
+ extern KVILIB_API void trimLeading(QStringList &list);
+
+ extern KVILIB_API void addLeading(KviStr ** array,char c);
+ extern KVILIB_API void addLeading(QStringList &list,const QChar &c);
+
+ extern KVILIB_API void trimBlockBraces(KviStr &buffer);
+ extern KVILIB_API void trimBlockBraces(QString &buffer);
+
+ extern KVILIB_API void unindent(KviStr &buffer);
+ extern KVILIB_API void unindent(QString &buffer);
+
+ extern KVILIB_API void bufferFromBlock(KviStr &buffer);
+ extern KVILIB_API void bufferFromBlock(QString &buffer);
+
+ extern KVILIB_API void addBlockBraces(KviStr &buffer);
+ extern KVILIB_API void addBlockBraces(QString &buffer);
+
+ extern KVILIB_API void indent(KviStr &buffer);
+ extern KVILIB_API void indent(QString &buffer);
+
+ extern KVILIB_API void blockFromBuffer(KviStr &buffer);
+ extern KVILIB_API void blockFromBuffer(QString &buffer);
+};
+
+#endif //_KVI_CMDFORMATTER_H_
diff --git a/src/kvilib/ext/kvi_config.cpp b/src/kvilib/ext/kvi_config.cpp
new file mode 100644
index 00000000..eb3dc0bc
--- /dev/null
+++ b/src/kvilib/ext/kvi_config.cpp
@@ -0,0 +1,1007 @@
+//==========================================================================================
+//
+// File : kvi_config.cpp
+// Last major modification : Thu Jan 14 1999 18:03:59 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//==========================================================================================
+
+#define __KVILIB__
+
+#include "kvi_config.h"
+#include "kvi_fileutils.h"
+#include "kvi_pixmap.h"
+#include "kvi_msgtype.h"
+#include "kvi_stringconversion.h"
+#include "kvi_memmove.h"
+#include "kvi_malloc.h"
+#include "kvi_file.h"
+
+
+KviConfig::KviConfig(const QString &filename,FileMode f,bool bLocal8Bit)
+{
+ m_bLocal8Bit = bLocal8Bit;
+ m_szFileName = filename;
+ m_bDirty = false;
+ m_szGroup = KVI_CONFIG_DEFAULT_GROUP;
+ m_bPreserveEmptyGroups = false;
+ m_bReadOnly = (f == KviConfig::Read);
+ m_pDict = new KviPointerHashTable<QString,KviConfigGroup>(17,false);
+ m_pDict->setAutoDelete(true);
+ if(f != KviConfig::Write)load();
+}
+
+KviConfig::KviConfig(const char* filename,FileMode f,bool bLocal8Bit)
+{
+ m_bLocal8Bit = bLocal8Bit;
+ m_szFileName = QString::fromUtf8(filename);
+ m_bDirty = false;
+ m_szGroup = KVI_CONFIG_DEFAULT_GROUP;
+ m_bPreserveEmptyGroups = false;
+ m_bReadOnly = (f == KviConfig::Read);
+ m_pDict = new KviPointerHashTable<QString,KviConfigGroup>(17,false);
+ m_pDict->setAutoDelete(true);
+ if(f != KviConfig::Write)load();
+}
+
+
+KviConfig::~KviConfig()
+{
+ if(m_bDirty)save();
+ delete m_pDict;
+}
+
+void KviConfig::clear()
+{
+ delete m_pDict;
+ m_pDict = new KviPointerHashTable<QString,KviConfigGroup>(17,false);
+ m_pDict->setAutoDelete(true);
+ m_bDirty = false;
+ m_szGroup = KVI_CONFIG_DEFAULT_GROUP;
+}
+
+void KviConfig::clearGroup(const QString & szGroup)
+{
+ m_bDirty = true;
+ m_pDict->remove(szGroup);
+ if(!m_pDict->find(m_szGroup))m_szGroup = KVI_CONFIG_DEFAULT_GROUP; //removed the current one
+}
+
+void KviConfig::clearKey(const QString & szKey)
+{
+ m_bDirty = true;
+ KviConfigGroup * p_group = getCurrentGroup();
+ p_group->remove(szKey);
+ if(p_group->count() == 0)clearGroup(m_szGroup);
+}
+
+/*
+void KviConfig::getContentsString(KviStr &buffer)
+{
+ buffer = __tr("Contents of config file ");
+ buffer.append(m_szFileName.ptr());
+ buffer.append('\n');
+ int sections = 0;
+ int keys = 0;
+ KviPointerHashTableIterator<QString,KviStrDict> it(*m_pDict);
+ while(it.current()){
+ buffer.append(" Section [");
+ buffer.append(it.currentKey());
+ buffer.append("]\n");
+ int sectionKeys = 0;
+ KviPointerHashTableIterator<QString,KviStr> it2(*it.current());
+ while(it2.current()){
+ buffer.append(" Key [");
+ buffer.append(it2.currentKey());
+ buffer.append("] : ");
+ buffer.append(it2.current()->ptr());
+ buffer.append('\n');
+ ++it2;
+ ++sectionKeys;
+ ++keys;
+ }
+ KviStr tmp(KviStr::Format,__tr(" Total: %d keys"),sectionKeys);
+ buffer.append(tmp);
+ buffer.append('\n');
+ ++it;
+ ++sections;
+ }
+ KviStr tmp(KviStr::Format,__tr("Total: %d keys in %d sections"),keys,sections);
+ buffer.append(tmp);
+}
+*/
+
+
+
+#define LOAD_BLOCK_SIZE 32768
+
+bool KviConfig::load()
+{
+ // this is really faster than the old version :)
+
+ // open the file
+ KviFile f(m_szFileName);
+ if(!f.openForReading())return false;
+
+ KviStr tmp;
+ KviConfigGroup * p_group = 0;
+
+ int iLoadBlockSize = LOAD_BLOCK_SIZE;
+
+ char * buffer = (char *)kvi_malloc(iLoadBlockSize * sizeof(char));
+
+ int toRead;
+ int readedLen;
+ int remainingLen = 0;
+
+ char * p = buffer; // start writing to the beginning of the buffer
+
+ do {
+ // compute the length to read
+ toRead = iLoadBlockSize - remainingLen;
+ if(toRead < 1)
+ {
+ // ops... a string longer than iLoadBlockSize - 1 chars
+ iLoadBlockSize += LOAD_BLOCK_SIZE;
+ int iOffset = p - buffer;
+ buffer = (char *)kvi_realloc(buffer,iLoadBlockSize * sizeof(char));
+ p = buffer + iOffset;
+ toRead += LOAD_BLOCK_SIZE;
+ }
+
+ // do read
+ readedLen = f.readBlock(p,toRead);
+ if(readedLen < toRead)
+ {
+ // check for errors
+ if(readedLen <= 0)
+ {
+ if(readedLen < 0)
+ {
+ // error at all
+ f.close();
+ kvi_free(buffer);
+ return true; // nothing more to parse anyway
+ } else {
+ // just a zero byte read
+ if(remainingLen == 0)
+ {
+ // there was nothing in the buffer
+ f.close(); // nothing to parse anyway
+ kvi_free(buffer);
+ return true;
+ }
+ // there is something in the buffer but we have readed 0 bytes
+ // this usually means that the last line in the file has no trailing newline
+ // ...we just fake it :)
+ *p = '\n';
+ readedLen = 1;
+ }
+ } else {
+ // just readed something but less than expected
+ // check if the last readed char is a newline
+ // if it isn't , fake it
+ if(*(p + readedLen - 1) != '\n')
+ {
+ *(p + readedLen) = '\n';
+ readedLen++;
+ }
+ }
+ }
+ // compute the end pointer
+ char * endp = p + readedLen;
+
+ p = buffer; // start from beginning of the data buffer at all
+ // begin of the current string
+ char * begin = p;
+
+ // and loop
+ while(p < endp)
+ {
+ // find a newline
+ if(*p != '\n')
+ {
+ p++;
+ continue;
+ }
+ // newline!
+ *p = 0;
+ // now begin points to the string that terminates in p
+ // skip leading whitespace
+ while((*begin == '\t') || (*begin == ' '))begin++;
+
+ if(p == begin)
+ {
+ // empty line
+ p++;
+ begin = p;
+ continue;
+ }
+ // now p > begin
+ // check if there are trailing spaces (include CR so CRLF is trimmed too)
+ char * trail = p - 1;
+
+ p++;
+
+ while(trail >= begin)
+ {
+ if((*trail == '\r') || (*trail == '\t') || (*trail == ' '))*trail = 0;
+ else break;
+ trail--;
+ }
+
+ // yeah, have some data in this line :D
+ switch(*begin)
+ {
+ case 0:
+ // empty line
+ break;
+ case '#':
+ // comment: just skip it
+ break;
+ case '[':
+ // group ?
+ begin++;
+ if(*begin && (*begin != ']'))
+ {
+ char * z = begin;
+#define COMPAT_WITH_OLD_CONFIGS
+#ifdef COMPAT_WITH_OLD_CONFIGS
+ // run to the end of the string
+ while(*z)z++;
+ // run back to the trailing ']'
+ while((z > begin) && (*z != ']'))z--;
+ // if it is not ther just run back to the end of the string
+ if(*z != ']')while(*z)z++;
+#else
+ // new configs have it always encoded properly
+ while(*z && (*z != ']'))z++;
+#endif
+ *z = 0;
+ tmp.hexDecode(begin);
+ tmp.stripRightWhiteSpace(); // no external spaces in group names
+
+ if(!tmp.isEmpty())
+ {
+ QString szGroup = m_bLocal8Bit ?
+ QString::fromLocal8Bit(tmp.ptr(),tmp.len()) :
+ QString::fromUtf8(tmp.ptr(),tmp.len());
+ p_group = m_pDict->find(szGroup);
+ if(!p_group)
+ {
+ p_group = new KviConfigGroup(17,false);
+ p_group->setAutoDelete(true);
+ m_pDict->insert(szGroup,p_group);
+ }
+ }
+ }
+ break;
+ default:
+ {
+ // real data ?
+ char * z = begin;
+ while(*z && (*z != '='))z++;
+ if(*z && (z != begin))
+ {
+ *z = 0;
+ tmp.hexDecode(begin);
+ tmp.stripRightWhiteSpace(); // No external spaces at all in keys
+ if(!tmp.isEmpty())
+ {
+ QString szKey = m_bLocal8Bit ?
+ QString::fromLocal8Bit(tmp.ptr(),tmp.len()) :
+ QString::fromUtf8(tmp.ptr(),tmp.len());
+ z++;
+ while(*z && ((*z == ' ') || (*z == '\t')))z++;
+ if(*z)
+ {
+ tmp.hexDecode(z);
+ QString * pVal = new QString( m_bLocal8Bit ?
+ QString::fromLocal8Bit(tmp.ptr(),tmp.len()) :
+ QString::fromUtf8(tmp.ptr(),tmp.len())
+ );
+ if(!p_group)
+ {
+ // ops...we're missing a group
+ // use the default one
+ p_group = new KviConfigGroup(17,false);
+ p_group->setAutoDelete(true);
+ m_pDict->insert(KVI_CONFIG_DEFAULT_GROUP,p_group);
+ }
+ p_group->replace(szKey,pVal);
+ } else {
+ // we in fact need this (mercy :D)
+ // otherwise the empty options will be treated as non-existing ones
+ // and will get the defaults (which is bad)
+ QString * pVal = new QString(QString::null);
+ p_group->replace(szKey,pVal);
+ }
+ }
+ }
+ }
+ break;
+ }
+ begin = p;
+ }
+ if(begin != endp)
+ {
+ // there is data with no trailing newline in the buffer
+ remainingLen = endp-begin;
+ if(buffer != begin)
+ {
+ kvi_memmove(buffer,begin,remainingLen);
+ p = buffer + remainingLen;
+ } // else p remains where it is
+ } else {
+ p = buffer;
+ }
+ } while(readedLen == toRead);
+
+ f.close();
+ kvi_free(buffer);
+ return true;
+}
+
+/*
+
+bool KviConfig::load()
+{
+ QFile f(m_szFileName);
+ if(!f.open(IO_ReadOnly))return false;
+
+
+ KviConfigGroup * p_group = 0;
+
+ KviStr dataLine;
+ bool bContinue;
+
+ do {
+ bContinue = kvi_readLine(&f,dataLine);
+ dataLine.stripWhiteSpace();
+ if(dataLine.hasData())
+ {
+ switch(*(dataLine.ptr()))
+ {
+ case '#':
+ // just skip it , it is a comment
+ break;
+ case '[':
+ {
+ //set the group
+ dataLine.cutLeft(1);
+ dataLine.cutRight(1);
+ dataLine.hexDecode();
+ if(dataLine.hasData())
+ {
+ QString szUtf8 = QString::fromUtf8(dataLine.ptr());
+ p_group = m_pDict->find(szUtf8);
+
+ if(!p_group)
+ {
+ p_group = new KviConfigGroup(17,false);
+ p_group->setAutoDelete(true);
+ m_pDict->insert(szUtf8,p_group);
+ }
+ }
+ }
+ break;
+ default:
+ {
+ //data entry...split in two...
+ KviStr name=dataLine.getToken('=');
+ name.stripRightWhiteSpace(); // strip any whitespace added externally
+ name.hexDecode();
+ if(name.hasData())
+ {
+ dataLine.stripLeftWhiteSpace(); // strip any whitespace added externally
+ dataLine.hexDecode();
+ //insert (replace items if needed)
+ QString *p_data=new QString(QString::fromUtf8(dataLine.ptr()));
+ if(!p_group)
+ {
+ // ops...we're missing a group
+ // use the default one
+ p_group = new KviConfigGroup(17,false);
+ p_group->setAutoDelete(true);
+ m_pDict->insert(KVI_CONFIG_DEFAULT_GROUP,p_group);
+ }
+ QString szName = QString::fromUtf8(name.ptr());
+ p_group->replace(szName,p_data);
+ }
+ }
+ break;
+ }
+ }
+ } while (bContinue);
+
+ f.close();
+ return true;
+}
+
+*/
+
+bool KviConfig::save()
+{
+ static unsigned char encode_table[256]=
+ {
+ // 000 001 002 003 004 005 006 007 008 009 010 011 012 013 014 015
+ // NUL SOH STX ETX EOT ENQ ACK BEL BS HT LF VT FF CR SO SI
+ 1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,
+ // 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031
+ // DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US
+ 1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,
+ // 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047
+ // ! " # $ % & ' ( ) * + , - . /
+ 1 ,0 ,0 ,1 ,0 ,1 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+ // 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063
+ // 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,1 ,0 ,0 ,
+ // 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079
+ // @ A B C D E F G H I J K L M N O
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+ // 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095
+ // P Q R S T U V W X Y Z [ \ ] ^ _
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,1 ,0 ,1 ,0 ,0 ,
+ // 096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111
+ // ` a b c d e f g h i j k l m n o
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+ // 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
+ // p q r s t u v w x y z { | } ~ 
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+ // 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
+ //
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+ // 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
+ //
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+ // 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
+ //
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+ // 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
+ //
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+ // 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
+ // � � � � � � � � � � � � � � � �
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+ // 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
+ // � � � � � � � � � � � � � � � �
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+ // 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
+ // � � � � � � � � � � � � � � � �
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+ // 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
+ // � � � � � � � �
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ };
+
+
+ if(m_bReadOnly)return false;
+
+ KviFile f(m_szFileName);
+ if(!f.openForWriting())return false;
+ if(f.writeBlock("# KVIrc configuration file\n",27) != 27)return false;
+
+ KviPointerHashTableIterator<QString,KviConfigGroup> it(*m_pDict);
+ while (it.current())
+ {
+ if((it.current()->count() != 0) || (m_bPreserveEmptyGroups))
+ {
+ KviStr group(m_bLocal8Bit ? KviQString::toLocal8Bit(it.currentKey()) : KviQString::toUtf8(it.currentKey()));
+ group.hexEncodeWithTable(encode_table);
+
+ if(!f.putChar('['))return false;
+ if(f.writeBlock(group.ptr(),group.len()) < (int) group.len())return false;
+ if(f.writeBlock("]\n",2) < 2)return false;
+
+ KviConfigGroup * dict = (KviConfigGroup *)it.current();
+ KviConfigGroupIterator it2(*dict);
+
+ KviStr szName,szValue;
+ while(QString * p_str = it2.current())
+ {
+ szName = m_bLocal8Bit ? KviQString::toLocal8Bit(it2.currentKey()) : KviQString::toUtf8(it2.currentKey());
+ szValue = m_bLocal8Bit ? KviQString::toLocal8Bit(*p_str) : KviQString::toUtf8(*p_str);
+ szName.hexEncodeWithTable(encode_table);
+ szValue.hexEncodeWhiteSpace();
+
+ if(f.writeBlock(szName.ptr(),szName.len()) < (int) szName.len())return false;
+ if(!f.putChar('='))return false;
+ if(f.writeBlock(szValue.ptr(),szValue.len()) < (int) szValue.len())return false;
+ if(!f.putChar('\n'))return false;
+ ++it2;
+ }
+ }
+ ++it;
+ }
+ f.close();
+ m_bDirty = false;
+ return true;
+}
+
+void KviConfig::setGroup(const QString & szGroup)
+{
+ m_szGroup = szGroup;
+ if(m_bPreserveEmptyGroups)
+ {
+ if(!hasGroup(szGroup))
+ {
+ getCurrentGroup(); // we need it to be created.
+ m_bDirty = true;
+ }
+ }
+}
+
+bool KviConfig::hasKey(const QString & szKey)
+{
+ KviConfigGroup * p_group = getCurrentGroup();
+ return (p_group->find(szKey) != 0);
+}
+
+bool KviConfig::hasGroup(const QString & szGroup)
+{
+ return (m_pDict->find(szGroup) != 0);
+}
+
+KviConfigGroup * KviConfig::getCurrentGroup()
+{
+ if(m_szGroup.isEmpty())m_szGroup = KVI_CONFIG_DEFAULT_GROUP;
+ KviConfigGroup * p_group = m_pDict->find(m_szGroup);
+ if(!p_group)
+ {
+ //create the group
+ p_group = new KviConfigGroup(17,false);
+ p_group->setAutoDelete(true);
+ m_pDict->insert(m_szGroup,p_group);
+ }
+ return p_group;
+}
+
+////////////////////////////////// KviStr
+
+void KviConfig::writeEntry(const QString & szKey,const QString & szValue)
+{
+ m_bDirty = true;
+ KviConfigGroup * p_group = getCurrentGroup();
+ QString *p_data=new QString(szValue);
+ p_group->replace(szKey,p_data);
+}
+
+// FIXME: #warning "We have probs here ?"
+
+QString KviConfig::readEntry(const QString & szKey,const QString & szDefault)
+{
+ KviConfigGroup * p_group = getCurrentGroup();
+ QString * p_str = p_group->find(szKey);
+ if(!p_str)
+ {
+ m_szStrBuffer = szDefault;
+ } else {
+ m_szStrBuffer = *p_str;
+ }
+ return m_szStrBuffer;
+}
+
+//////////////////////////////////// QString
+
+/*
+QString KviConfig::readQStringEntry(const char *szKey,const QString &szDefault)
+{
+ KviStrDict * p_group = getCurrentGroup();
+ KviStr * p_str = p_group->find(szKey);
+ if(!p_str)return szDefault;
+ return QString::fromUtf8(p_str->ptr());
+}
+*/
+
+/*
+void KviConfig::writeEntry(const char *szKey,const QString &szValue)
+{
+ m_bDirty = true;
+ KviStrDict * p_group = getCurrentGroup();
+ p_group->replace(szKey,new KviStr(szValue.utf8().data()));
+}
+*/
+
+////////////////////////////////// QStringList
+
+static QString g_szConfigStringListSeparator(",\\[ITEM],");
+
+QStringList KviConfig::readStringListEntry(const QString & szKey,const QStringList &list)
+{
+ KviConfigGroup * p_group = getCurrentGroup();
+ QString * p_str = p_group->find(szKey);
+ if(!p_str)return list;
+#ifdef COMPILE_USE_QT4
+ return p_str->split(g_szConfigStringListSeparator);
+#else
+ return QStringList::split(g_szConfigStringListSeparator,*p_str);
+#endif
+}
+
+void KviConfig::writeEntry(const QString & szKey,const QStringList &list)
+{
+ m_bDirty = true;
+ KviConfigGroup * p_group = getCurrentGroup();
+ QString *p_data=new QString(list.join(g_szConfigStringListSeparator));
+ p_group->replace(szKey,p_data);
+}
+
+////////////////////////////////// KviValueList<int>
+
+KviValueList<int> KviConfig::readIntListEntry(const QString & szKey,const KviValueList<int> &list)
+{
+ KviConfigGroup * p_group = getCurrentGroup();
+ QString * p_str = p_group->find(szKey);
+ if(!p_str)
+ {
+ //debug("Returning default list for group %s and key %s",m_szGroup.latin1(),szKey.latin1());
+ return list;
+ }
+#ifdef COMPILE_USE_QT4
+ QStringList sl = p_str->split(",");
+#else
+ QStringList sl = QStringList::split(",",*p_str);
+#endif
+ KviValueList<int> ret;
+
+ //debug("Got option list for group %s and key %s: %s",m_szGroup.latin1(),szKey.latin1(),p_str->latin1());
+
+ for(QStringList::Iterator it = sl.begin();it != sl.end();++it)
+ {
+ bool bOk;
+ int iTmp = (*it).toInt(&bOk);
+ if(bOk)ret.append(iTmp);
+ }
+
+ return ret;
+}
+
+
+void KviConfig::writeEntry(const QString & szKey,const KviValueList<int> &list)
+{
+ m_bDirty = true;
+ KviConfigGroup * p_group = getCurrentGroup();
+ KviStr szData;
+ for(KviValueList<int>::ConstIterator it = list.begin();it != list.end();++it)
+ {
+ if(szData.hasData())szData.append(',');
+ szData.append(KviStr::Format,"%d",*it);
+ }
+ //debug("Writing option list for group %s and key %s: %s",m_szGroup.latin1(),szKey.latin1(),szData.ptr());
+
+ p_group->replace(szKey,new QString(szData.ptr()));
+}
+
+////////////////////////////////// KviPixmap
+
+// FIXME: #warning "Spaces in image names ?"
+
+void KviConfig::writeEntry(const QString & szKey,const KviPixmap &pixmap)
+{
+ m_bDirty = true;
+ KviConfigGroup * p_group = getCurrentGroup();
+ QString *p_data=new QString();
+ KviStringConversion::toString(pixmap,*p_data);
+ p_group->replace(szKey,p_data);
+}
+
+KviPixmap KviConfig::readPixmapEntry(const QString & szKey,const KviPixmap &pixDef)
+{
+ KviConfigGroup * p_group = getCurrentGroup();
+ QString * p_str = p_group->find(szKey);
+ if(p_str)
+ {
+ KviPixmap ret("");
+ return KviStringConversion::fromString(*p_str,ret) ? ret : pixDef;
+ } else {
+ return pixDef;
+ }
+}
+
+////////////////////////////////// KviMsgType
+
+void KviConfig::writeEntry(const QString & szKey,const KviMsgType &msg)
+{
+ m_bDirty = true;
+ KviConfigGroup * p_group = getCurrentGroup();
+ QString szData;
+ KviStringConversion::toString(msg,szData);
+ p_group->replace(szKey,new QString(szData));
+}
+
+KviMsgType KviConfig::readMsgTypeEntry(const QString & szKey,const KviMsgType &msgDef)
+{
+ KviConfigGroup * p_group = getCurrentGroup();
+ QString * p_str = p_group->find(szKey);
+ if(!p_str)return msgDef;
+ KviMsgType ret = msgDef;
+ KviStringConversion::fromString(*p_str,ret);
+ return ret;
+}
+
+////////////////////////////////// QColor
+
+void KviConfig::writeEntry(const QString & szKey,const QColor &clr)
+{
+ m_bDirty = true;
+ KviConfigGroup * p_group = getCurrentGroup();
+ KviStr szData(KviStr::Format,"%d,%d,%d",clr.red(),clr.green(),clr.blue());
+ p_group->replace(szKey,new QString(szData.ptr()));
+}
+
+QColor KviConfig::readColorEntry(const QString & szKey,const QColor &clr)
+{
+ KviConfigGroup * p_group = getCurrentGroup();
+ QColor color(clr);
+ QString * pointer_that_IS_initialized = p_group->find(szKey);
+
+
+ if(pointer_that_IS_initialized)
+ {
+
+ KviStr str(*pointer_that_IS_initialized);
+ str.stripLeftWhiteSpace();
+
+ KviStr red,green,blue;
+
+ str.getToken(red,',');
+ str.getToken(green,',');
+ str.getToken(blue,',');
+
+ if((red.isUnsignedNum())&&(green.isUnsignedNum())&&(blue.isUnsignedNum())){
+ bool bOk;
+ int r = red.toInt(&bOk) % 256;
+ int g = green.toInt(&bOk) % 256;
+ int b = blue.toInt(&bOk) % 256;
+ if(r < 0)r = -r;
+ if(g < 0)g = -g;
+ if(b < 0)b = -b;
+ color.setRgb(r,g,b);
+ }
+ }
+ return color;
+}
+
+////////////////////////////////// QFont
+
+void KviConfig::getFontProperties(KviStr & buffer,QFont *fnt)
+{
+ QString tmp;
+ KviStringConversion::toString(*fnt,tmp);
+ buffer = tmp;
+}
+
+void KviConfig::writeEntry(const QString & szKey,QFont &fnt)
+{
+ m_bDirty = true;
+ KviConfigGroup * p_group = getCurrentGroup();
+ QString *p_data = new QString();
+ KviStringConversion::toString(fnt,*p_data);
+ p_group->replace(szKey,p_data);
+}
+
+
+void KviConfig::setFontProperties(KviStr & str,QFont *fnt)
+{
+ KviStringConversion::fromString(str.ptr(),*fnt);
+}
+
+QFont KviConfig::readFontEntry(const QString & szKey,const QFont &fnt)
+{
+ QFont font(fnt);
+ KviConfigGroup * p_group = getCurrentGroup();
+ QString * p_str = p_group->find(szKey);
+ if(p_str)
+ {
+ //FontEntry=Arial,12,9,0,100,italic,underline,strikeout,
+ KviStr str(*p_str);
+ str.stripLeftWhiteSpace();
+ setFontProperties(str,&font);
+ }
+ return font;
+}
+
+////////////////////////////////// bool
+
+void KviConfig::writeEntry(const QString & szKey,bool bTrue)
+{
+ m_bDirty = true;
+ KviConfigGroup * p_group = getCurrentGroup();
+ QString *p_data = new QString(bTrue ? "true" : "false");
+ p_group->replace(szKey,p_data);
+}
+
+bool KviConfig::readBoolEntry(const QString & szKey,bool bTrue)
+{
+ KviConfigGroup * p_group = getCurrentGroup();
+ QString * p_str = p_group->find(szKey);
+ if(!p_str)return bTrue;
+ static QString szTrue = "true";
+ return (KviQString::toLower(*p_str) == szTrue);
+}
+
+////////////////////////////////// QRect
+
+void KviConfig::writeEntry(const QString & szKey,const QRect &rct)
+{
+ m_bDirty = true;
+ KviConfigGroup * p_group = getCurrentGroup();
+ QString szBuf;
+ KviStringConversion::toString(rct,szBuf);
+ p_group->replace(szKey,new QString(szBuf));
+}
+
+QRect KviConfig::readRectEntry(const QString & szKey,const QRect &rct)
+{
+ KviConfigGroup * p_group = getCurrentGroup();
+ QString * str = p_group->find(szKey);
+ if(!str)return rct;
+ QRect ret;
+ return KviStringConversion::fromString(*str,ret) ? ret : rct;
+}
+
+////////////////////////////////// unsigned short
+
+void KviConfig::writeEntry(const QString & szKey,unsigned short usValue)
+{
+ m_bDirty = true;
+ KviConfigGroup * p_group = getCurrentGroup();
+ QString *p_data = new QString();
+ p_data->setNum(usValue);
+ p_group->replace(szKey,p_data);
+}
+
+unsigned short int KviConfig::readUShortEntry(const QString & szKey,unsigned short int usDefault)
+{
+ KviConfigGroup * p_group = getCurrentGroup();
+ QString * p_str = p_group->find(szKey);
+ if(!p_str)return usDefault;
+ bool bOk;
+ unsigned short int usVal=p_str->toUShort(&bOk);
+ return bOk ? usVal : usDefault;
+}
+
+/*
+////////////////////////////////// unsigned long
+
+Unused code
+void KviConfig::writeEntry(const char *szKey,unsigned long lValue)
+{
+ m_bDirty = true;
+ KviStrDict * p_group = getCurrentGroup();
+ KviStr *p_data = new KviStr();
+ p_data->setNum(lValue);
+ p_group->replace(szKey,p_data);
+}
+
+unsigned long KviConfig::readULongEntry(const char *szKey,unsigned long lDefault)
+{
+ KviStrDict * p_group = getCurrentGroup();
+ KviStr * p_str = p_group->find(szKey);
+ if(!p_str)return lDefault;
+ bool bOk;
+ unsigned long lVal=p_str->toULong(&bOk);
+ return bOk ? lVal : lDefault;
+}
+*/
+
+////////////////////////////////// int
+
+void KviConfig::writeEntry(const QString & szKey,int iValue)
+{
+ m_bDirty = true;
+ KviConfigGroup * p_group = getCurrentGroup();
+ QString *p_data = new QString();
+ p_data->setNum(iValue);
+ p_group->replace(szKey,p_data);
+}
+
+int KviConfig::readIntEntry(const QString & szKey,int iDefault)
+{
+ KviConfigGroup * p_group = getCurrentGroup();
+ QString * p_str = p_group->find(szKey);
+ if(!p_str)return iDefault;
+ bool bOk;
+ int iVal=p_str->toInt(&bOk);
+ return bOk ? iVal : iDefault;
+}
+
+////////////////////////////////// unsigned int
+
+void KviConfig::writeEntry(const QString & szKey,unsigned int iValue)
+{
+ m_bDirty = true;
+ KviConfigGroup * p_group = getCurrentGroup();
+ QString *p_data = new QString();
+ p_data->setNum(iValue);
+ p_group->replace(szKey,p_data);
+}
+
+unsigned int KviConfig::readUIntEntry(const QString & szKey,unsigned int iDefault)
+{
+ KviConfigGroup * p_group = getCurrentGroup();
+ QString * p_str = p_group->find(szKey);
+ if(!p_str)return iDefault;
+ bool bOk;
+ unsigned int iVal=p_str->toUInt(&bOk);
+ return bOk ? iVal : iDefault;
+}
+
+////////////////////////////////// char
+
+void KviConfig::writeEntry(const QString & szKey,char iValue)
+{
+ m_bDirty = true;
+ KviConfigGroup * p_group = getCurrentGroup();
+ QString * p_data = new QString();
+ p_data->setNum(iValue);
+ p_group->replace(szKey,p_data);
+}
+
+char KviConfig::readCharEntry(const QString & szKey,char iDefault)
+{
+ KviConfigGroup * p_group = getCurrentGroup();
+ QString * p_str = p_group->find(szKey);
+ if(!p_str)return iDefault;
+ bool bOk;
+ char iVal=(char)p_str->toInt(&bOk);
+ return bOk ? iVal : iDefault;
+}
+
+////////////////////////////////// unsigned char
+
+void KviConfig::writeEntry(const QString & szKey,unsigned char iValue)
+{
+ m_bDirty = true;
+ KviConfigGroup * p_group = getCurrentGroup();
+ QString *p_data = new QString();
+ p_data->setNum(iValue);
+ p_group->replace(szKey,p_data);
+}
+
+unsigned char KviConfig::readUCharEntry(const QString & szKey,unsigned char iDefault)
+{
+ KviConfigGroup * p_group = getCurrentGroup();
+ QString * p_str = p_group->find(szKey);
+ if(!p_str)return iDefault;
+ bool bOk;
+ unsigned char iVal=(unsigned char)p_str->toUInt(&bOk);
+ return bOk ? iVal : iDefault;
+}
+
+
+#ifdef COMPILE_ON_WINDOWS
+
+ // On windows we need to override new and delete operators
+ // to ensure that always the right new/delete pair is called for an object instance
+ // This bug is present in all the classes exported by a module that
+ // can be instantiated/destroyed from external modules.
+ // (this is a well known bug described in Q122675 of MSDN)
+
+ void * KviConfig::operator new(size_t tSize)
+ {
+ return kvi_malloc(tSize);
+ }
+
+ void KviConfig::operator delete(void * p)
+ {
+ kvi_free(p);
+ }
+
+#endif
diff --git a/src/kvilib/ext/kvi_config.h b/src/kvilib/ext/kvi_config.h
new file mode 100644
index 00000000..6eef4e05
--- /dev/null
+++ b/src/kvilib/ext/kvi_config.h
@@ -0,0 +1,162 @@
+#ifndef _KVI_CONFIG_H_INCLUDED_
+#define _KVI_CONFIG_H_INCLUDED_
+
+//=============================================================================
+//
+// File : kvi_config.h (/usr/build/NEW_kvirc/kvirc/kvilib/kvi_config.h)
+// Last major modification : Thu Jan 14 1999 18:01:22 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_string.h"
+#include "kvi_settings.h"
+#include "kvi_heapobject.h"
+#include "kvi_pointerhashtable.h"
+#include "kvi_valuelist.h"
+
+#include <qcolor.h>
+#include <qfont.h>
+#include <qrect.h>
+#include <qstringlist.h>
+
+#define KVI_CONFIG_DEFAULT_GROUP "KVIrc"
+
+class KviPixmap;
+class KviMsgType;
+
+typedef KviPointerHashTable<QString,QString> KviConfigGroup;
+typedef KviPointerHashTableIterator<QString,QString> KviConfigGroupIterator;
+typedef KviPointerHashTableIterator<QString,KviConfigGroup> KviConfigIterator;
+
+class KVILIB_API KviConfig : public KviHeapObject
+{
+public:
+ enum FileMode { Read = 1 , Write = 2 , ReadWrite = 3 };
+public:
+ KviConfig(const QString &filename,FileMode f/* = ReadWrite*/,bool bLocal8Bit = false);
+ KviConfig(const char *filename,FileMode f/* = ReadWrite*/,bool bLocal8Bit = false);
+ ~KviConfig();
+private:
+ bool m_bLocal8Bit;
+ KviPointerHashTable<QString,KviConfigGroup> * m_pDict;
+ QString m_szFileName;
+ bool m_bDirty;
+ QString m_szStrBuffer;
+ QString m_szGroup;
+ bool m_bPreserveEmptyGroups;
+ bool m_bReadOnly;
+private:
+ bool load();
+ bool save();
+ KviConfigGroup * getCurrentGroup();
+public:
+ //
+ // Useful when saving...
+ // Normally this class does not save empty groups
+ // and setGroup() is never a config modification.
+ // If the group is not existing it will be effectively
+ // created only at the first attempt to read from it or write to it.
+ // With this flag set to true the KviConfig class will
+ // write down also the empty groups , and calls to setGroup()
+ // will create the groups if not existing yet (and set the config data
+ // as modified).
+ //
+ void preserveEmptyGroups(bool bPreserve){ m_bPreserveEmptyGroups = bPreserve; };
+ const QString & fileName(){ return m_szFileName; };
+ bool readOnly(){ return m_bReadOnly; };
+ void setReadOnly(bool bReadOnly){ m_bReadOnly = bReadOnly; };
+ bool dirty(){ return m_bDirty; };
+ //
+ // This sets the save path for the config file
+ // In this way you can load a system-wide read-only config file
+ // as default configuration, alter its settings and save it to the
+ // user local configuration directory
+ void setSavePath(const QString & savePath){ m_szFileName = savePath; };
+ KviPointerHashTable<QString,KviConfigGroup> *dict(){ return m_pDict; };
+
+ void clearDirtyFlag(){ m_bDirty = false; };
+ void clear();
+ void clearGroup(const QString & szGroup);
+ void clearKey(const QString & szKey);
+ unsigned int groupsCount(){ return m_pDict->count(); };
+ bool sync(){ return save(); };
+ bool hasKey(const QString & szKey);
+ bool hasGroup(const QString & szGroup);
+ void setGroup(const QString & szGroup);
+ //void getContentsString(KviStr &buffer);
+ const QString & group(){ return m_szGroup; };
+ void writeEntry(const QString & szKey,const QString & szValue);
+ void writeEntry(const QString & szKey,const char * szValue)
+ { writeEntry(szKey,QString::fromUtf8(szValue)); };
+ QString readEntry(const QString & szKey,const QString & szDefault = QString::null);
+ // HACK for KviOptions.. (FIXME)
+ QString readKviStrEntry(const QString &szKey,const KviStr &szDefault)
+ { return readEntry(szKey,szDefault.ptr()); };
+ //void writeEntry(const char *szKey,KviStr &szValue);
+ //const char * readEntry(const char *szKey,KviStr &szDefault);
+ void writeEntry(const QString & szKey,const KviPixmap &pixmap);
+ KviPixmap readPixmapEntry(const QString & szKey,const KviPixmap &pixDef);
+ void writeEntry(const QString & szKey,const KviMsgType &msg);
+ KviMsgType readMsgTypeEntry(const QString & szKey,const KviMsgType &msgDef);
+ void writeEntry(const QString & szKey,const QColor &clr);
+ QColor readColorEntry(const QString & szKey,const QColor &clr);
+ void writeEntry(const QString & szKey,QFont &fnt);
+ QFont readFontEntry(const QString & szKey,const QFont &fnt);
+ void writeEntry(const QString & szKey,bool bTrue);
+ bool readBoolEntry(const QString & szKey,bool bTrue);
+ QRect readRectEntry(const QString & szKey,const QRect &rct);
+ void writeEntry(const QString & szKey,const QRect &rct);
+ QStringList readStringListEntry(const QString & szKey,const QStringList &list);
+ void writeEntry(const QString & szKey,const QStringList &list);
+ KviValueList<int> readIntListEntry(const QString & ,const KviValueList<int> &list);
+ void writeEntry(const QString & szKey,const KviValueList<int> &list);
+ QString readQStringEntry(const QString & szKey,const QString &szDefault = QString::null)
+ { return readEntry(szKey,szDefault); };
+ //void writeEntry(const QString & szKey,const QString &szValue);
+ //void writeEntry(const char *szKey,unsigned long lValue);
+ //unsigned long readULongEntry(const char *szKey,unsigned long lDefault);
+ //void writeEntry(const char *szKey,long lValue);
+ //long readLongEntry(const char *szKey,long lDefault);
+ void writeEntry(const QString & szKey,int iValue);
+ int readIntEntry(const QString & szKey,int iDefault);
+ void writeEntry(const QString & szKey,unsigned short int usValue);
+ unsigned short int readUShortEntry(const QString & szKey,unsigned short int usDefault);
+ void writeEntry(const QString & szKey,unsigned int iValue);
+ unsigned int readUIntEntry(const QString & szKey,unsigned int iDefault);
+ void writeEntry(const QString & szKey,char iValue);
+ char readCharEntry(const QString & szKey,char iDefault);
+ void writeEntry(const QString & szKey,unsigned char iValue);
+ unsigned char readUCharEntry(const QString & szKey,unsigned char iDefault);
+
+ static void getFontProperties(KviStr & buffer,QFont *fnt);
+ static void setFontProperties(KviStr & str,QFont *fnt);
+
+#ifdef COMPILE_ON_WINDOWS
+ // On windows we need to override new and delete operators
+ // to ensure that always the right new/delete pair is called for an object instance
+ // This bug is present in all the classes exported by a module that
+ // can be instantiated/destroyed from external modules.
+ // (this is a well known bug described in Q122675 of MSDN)
+ void * operator new(size_t tSize);
+ void operator delete(void * p);
+#endif
+};
+
+#endif //!_KVI_CONFIG_H_INCLUDED_
diff --git a/src/kvilib/ext/kvi_crypt.cpp b/src/kvilib/ext/kvi_crypt.cpp
new file mode 100644
index 00000000..84a636aa
--- /dev/null
+++ b/src/kvilib/ext/kvi_crypt.cpp
@@ -0,0 +1,240 @@
+//=============================================================================
+//
+// File : kvi_crypt.cpp
+// Creation date : Fri Nov 03 2000 02:34:43 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+
+#include "kvi_crypt.h"
+#include "kvi_locale.h"
+
+#ifdef COMPILE_ON_WINDOWS
+ #include "kvi_malloc.h"
+#endif
+
+/*
+ @doc: crypt_engines
+ @type:
+ generic
+ @keyterms:
+ cryptography, privacy, private key, text transformation
+ @title:
+ Cryptography and text transformation
+ @short:
+ Crypt/text transformation engines and how to use them
+ @body:
+ [big]Introduction[/big][br]
+ Well , there is a concrete background noise about security around the net.
+ And I've thought that adding a little cryptography support to KVIrc wasn't
+ a bad idea. So I've first comed out with the "crypt engines", that
+ allowed to have secure conversations on channels, queries and dcc chats;
+ then found out that the realized structure was perfect to be "generalized"
+ into "text transformation" support.[br]
+ [big]The concept[/big][br]
+ In few words, the "text transformation" engine is a layer between the user and the
+ IRC connection. You type some text in the input line of a query window (for example),
+ the engine transforms the text in some way and then sends it to the remote target.
+ The trick works also in the reverse way: some data come from the remote target,
+ the engine retransforms the text in some other way and displays it to the local user.[br]
+ The "incoming" transformation is usually the inverse of the "outgoing" one, but it
+ is not mandatory. It will become clear in few sentences that some engines will do no "incoming"
+ transformation at all. The original use of the transformation engines was to crypt the
+ outgoing data and to decrypt the incoming data; anyway, the engines can perform
+ other funky tasks. One of them is remapping the local charset to a "standardized" one
+ when sending text to a channel (or some other target) and doing the inverse map on
+ the way back. A totally "fantastic" usage of this concept could be an "on-the-fly translator";
+ it could translate for example Italian to English while sending to a channel
+ and English to Italian on the way back...the implementation of a such engine is left
+ to the reader as exercise :) Another (maybe less interesting) usage is to
+ colorize the outgoing text, or transform it
+ in a way that it is still readable but has a different look. This engine
+ would not require a back transformation (so no "decrypt stage"). A "symmetric"
+ idea could be an engine that strips the color codes from the incoming text: this
+ engine would not require a "crypting" stage.[br]
+
+ [big]The name of this stuf[/big][br]
+ Initially all this stuff was named "cryptography support".
+ Then the "cryptography" comed out to be not "enough" to describe
+ the framework, so "text transformation" is a more generic term.
+ Anyway, both terms were used in the documentation and the source.
+ Just as example, the "text transformation engine" is called
+ KviCryptEngine in the sources. So actually the terms "crypt"
+ and "text transformations" refer to the "same thing".
+ You will often find the term "encrypt" standing for "outgoing text
+ transformation" and "decrypt" standing for "incoming text transformation".[br]
+
+ [big]Yes, but why cryptography (on IRC) ?[/big][br]
+ Because it MAY be useful. More than once people have asked me to add some
+ crypting support to the dcc chats. Yes , I know that there are other
+ "secure communication" tools , but actually I can't find one that is able to
+ implement a "secure real time conversation". And what about a MULTIPLE real
+ time secure conversation ? This can be done on an IRC channel now.[br]
+
+ [big]The working things[/big][br]
+ KVIrc can use a text transformation engine on irc channels, in the queries
+ and the dcc chats. At the time I am writing, only the [module:rijndael]Rijndael[/module] crypt engine
+ is available: this is a private key encryption algorithm that assures
+ a "pretty good" security level. More engines will be surely available
+ at the time of the 3.0.0 release of KVIrc. The engines
+ can be activated by the dedicated dialog that can be accessed from the "button bar"
+ of the window. Once an engine has been enabled all the text that you type
+ in the input line (that is not a command obviously) is encrypted
+ and sent to the remote endpoint. If you want to sent a non crypted message
+ while an engine is working you can use the CTRL+P escape: by placing
+ that character as the FIRST CHARACTER of the line you will avoid crypting.
+ Every engine has different capabilities: some can both encrypt
+ and decrypt, other perform only half of the operations. Some engines
+ need a key (the crypt engines obviously), or two keys (you can specify
+ one for the outgoing data and one for the incoming). You can specify
+ all these options in the crypt/text transformation dialog.[br]
+ Obviously (with the current implementations) all the conversation endpoints
+ must agree on the engine (or better algorithm) used and on the key(s).
+ The key is user specified, so you have to find a secure way to negotiate
+ it with your communication engpoints. If you can meet the persons in the "real life",
+ this is the best way to exchange the keys, otherwise you can use mail & pgp.
+ Yes, this is a "miss" of the crypt protocol: it is missing a public key handshake.[br]
+
+ [big]The first test[/big][br]
+ A cool way to test a crypting engine is to use a "self query": connect to
+ any irc server, and execute [cmd]query[/cmd] <yournickname>; a query window
+ with you both as source and target will popup; activate a crypt engine
+ and enable both encryption and decryption; specify the same key for
+ bot directions and then type some text in the input line: you will see
+ the message twice: one is "your local text" and the other is the server routed one.
+ Then you can try to activate encryption only and leaving decryption disabled:
+ you will see how the text would appear to a possible "man in the middle".
+ You can also try to use different keys for encrypting and decrypting,
+ and play with the CTRL+P escape.[br]
+
+ [big]The protocol[/big][br]
+ Well, there is no protocol actually , only the existing implementations , that
+ can be accessed by anyone that want to reproduce them. There are only some
+ points relating to the crypting engines that need to be cleared:[br]
+ The crypted text must be suitable to be sent thru an IRC connection;
+ this means that some characters can not appear in the crypted text (e.g. CR,LF,NULL....).
+ KVIrc solves it in a simple way: the crypted binary data is encoded,
+ either as hexadecimal numeric string or in base64.[br]
+ An escape character has been defined to identify messages that are "crypted" from the
+ ones that are not: this character has ascii code 30 (decimal).[br]
+ The encoding is used in private messages only and has the following format:[br]
+ PRIVMSG <target> :<escape_char_ascii_30><encrypted message>[br]
+ ASCII 30 does not correspond to any widely used escape sequence and allows
+ mixing encrypted and plain text messages in a conversation...Well, this is not
+ so pretty but you can exchange crypted messages with one or two friends while
+ talking on a normal IRC channel: nobody else than your friends will be able
+ to understand the message; others will see senseless sequences of characters.
+ You will be still able to read the unencrypted messages of the other people
+ on the channel.[br] The escape character is not needed if the engine
+ performs non-crypting tasks: a charset mapper will produce text that
+ is meant to be readed by anyone on the channel, a text colorizer will
+ act in a similar way too. So the escape character is used for the "crypting"
+ engines only.
+
+ [big]An idea for the future implementations[/big][br]
+ A "public key" handshake protocol could be implemented.
+*/
+
+
+ KviCryptEngine::KviCryptEngine()
+ {
+#ifdef COMPILE_CRYPT_SUPPORT
+ setLastError(__tr2qs("Invalid crypt engine"));
+ m_iMaxEncryptLen = -1; // unlimited
+ m_deallocFunc = 0;
+#endif //COMPILE_CRYPT_SUPPORT
+ }
+
+ KviCryptEngine::~KviCryptEngine()
+ {
+ }
+
+#ifdef COMPILE_CRYPT_SUPPORT
+
+ bool KviCryptEngine::init(const char *,int,const char *,int)
+ {
+ return false;
+ }
+
+ KviCryptEngine::EncryptResult KviCryptEngine::encrypt(const char *,KviStr &)
+ {
+// debug("Pure virtual KviCryptEngine::encrypt() called");
+ return EncryptError;
+ }
+
+ KviCryptEngine::DecryptResult KviCryptEngine::decrypt(const char *,KviStr &)
+ {
+// debug("Pure virtual KviCryptEngine::decrypt() called");
+ return DecryptError;
+ }
+
+
+ KviCryptEngineManager::KviCryptEngineManager()
+ {
+ m_pEngineDict = new KviPointerHashTable<QString,KviCryptEngineDescription>;
+ m_pEngineDict->setAutoDelete(true);
+ }
+
+ KviCryptEngineManager::~KviCryptEngineManager()
+ {
+ delete m_pEngineDict;
+ }
+
+ void KviCryptEngineManager::registerEngine(KviCryptEngineDescription * d)
+ {
+ m_pEngineDict->replace(d->szName,d);
+ }
+
+ void KviCryptEngineManager::unregisterEngine(const QString &szName)
+ {
+ m_pEngineDict->remove(szName);
+ }
+
+ void KviCryptEngineManager::unregisterEngines(void * providerHandle)
+ {
+ KviPointerHashTableIterator<QString,KviCryptEngineDescription> it(*m_pEngineDict);
+ while(it.current())
+ {
+ if(it.current()->providerHandle == providerHandle)
+ m_pEngineDict->remove(it.currentKey());
+ else
+ ++it;
+ }
+ }
+
+ KviCryptEngine * KviCryptEngineManager::allocateEngine(const QString &szName)
+ {
+ KviCryptEngineDescription * d = m_pEngineDict->find(szName);
+ if(!d)return 0;
+ KviCryptEngine * e = d->allocFunc();
+ if(!e)return 0;
+ e->m_deallocFunc = d->deallocFunc; // remember the dealloc func from now on
+ return e;
+ }
+
+ void KviCryptEngineManager::deallocateEngine(KviCryptEngine * e)
+ {
+ if(!e)return;
+ crypt_engine_deallocator_func deallocFunc = e->m_deallocFunc;
+ deallocFunc(e);
+ }
+
+#endif //COMPILE_CRYPT_SUPPORT
diff --git a/src/kvilib/ext/kvi_crypt.h b/src/kvilib/ext/kvi_crypt.h
new file mode 100644
index 00000000..ae3bc4f0
--- /dev/null
+++ b/src/kvilib/ext/kvi_crypt.h
@@ -0,0 +1,160 @@
+#ifndef _KVI_CRYPT_H_
+#define _KVI_CRYPT_H_
+
+//=============================================================================
+//
+// File : kvi_crypt.h
+// Creation date : Fri Nov 03 2000 01:45:21 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+
+//
+// Base class for all IRC crypt engines
+// These intend to encrypt plain text into something
+// that can be sent through the IRC protocol...
+// so it should not contain NULL, CR , LF and other
+// similar stuff...
+//
+
+
+#include "kvi_qstring.h"
+#include "kvi_string.h"
+#include "kvi_heapobject.h"
+#include "kvi_pointerhashtable.h"
+
+#include <qobject.h>
+
+#ifdef COMPILE_CRYPT_SUPPORT
+ class KviCryptEngine;
+
+ typedef KviCryptEngine * (*crypt_engine_allocator_func)();
+ typedef void (*crypt_engine_deallocator_func)(KviCryptEngine *);
+#endif //COMPILE_CRYPT_SUPPORT
+
+ // we must include this declaration to make moc happy even
+ // if we're not compiling the crypt support
+
+ class KVILIB_API KviCryptEngine : public QObject, public KviHeapObject
+ {
+ Q_OBJECT
+ friend class KviCryptEngineManager;
+ public:
+ KviCryptEngine();
+ virtual ~KviCryptEngine();
+
+#ifdef COMPILE_CRYPT_SUPPORT
+ private:
+ crypt_engine_deallocator_func m_deallocFunc; // this is accessed by KviCryptEngineManager only
+ QString m_szLastError;
+ int m_iMaxEncryptLen;
+ public:
+ void setMaxEncryptLen(int m){ m_iMaxEncryptLen = m; };
+ int maxEncryptLen(){ return m_iMaxEncryptLen; };
+ virtual bool init(const char * encKey,int encKeyLen,const char * decKey,int decKeyLen);
+ //
+ // Encrypts utf8 plainText and returns the encrypted
+ // data in outBuffer. The encrypted data must be
+ // suitable for sending thru an IRC (eventually DCC
+ // that is less restrictive) connection and must be utf8 encoded: so
+ // no NULL, CR and LF in the output.
+ // 0x01 should be also avoided since
+ // it is the CTCP delimiter.
+ // Converting the result in a HEX string
+ // is a good trick...also Base64 could be used.
+ // Should return false in case of an error.
+ // Theoretically we could allow NULLs in plainText
+ // but this is not the case of KVIrc.
+ //
+ enum EncryptResult { Encrypted, Encoded, EncryptError };
+ virtual EncryptResult encrypt(const char * plainText,KviStr &outBuffer);
+ //
+ // Decrypts the utf8 data in inBuffer and puts the decrypted utf8
+ // stuff in plainText. inBuffer is the thingie
+ // that we got from outBuffer of encrupt() so it
+ // follows the same rules.
+ // Should return false in case of error.
+ //
+ enum DecryptResult { DecryptOkWasEncrypted, DecryptOkWasEncoded, DecryptOkWasPlainText, DecryptError };
+ virtual DecryptResult decrypt(const char * inBuffer,KviStr &plainText);
+ //
+ // Returns the string containing the description
+ // of the last error or an empty string if there
+ // was no error after the last init() call.
+ //
+ const QString &lastError(){ return m_szLastError; };
+ protected:
+ //
+ // The following two should have clear meaning
+ //
+ void clearLastError(){ m_szLastError = ""; };
+ void setLastError(const QString &err){ m_szLastError = err; };
+#endif //COMPILE_CRYPT_SUPPORT
+ };
+
+#ifdef COMPILE_CRYPT_SUPPORT
+ #define KVI_CRYPTENGINE_CAN_ENCRYPT 1
+ #define KVI_CRYPTENGINE_CAN_DECRYPT 2
+ #define KVI_CRYPTENGINE_WANT_ENCRYPT_KEY 4
+ #define KVI_CRYPTENGINE_WANT_DECRYPT_KEY 8
+
+ class KVILIB_API KviCryptEngineDescription : public KviHeapObject
+ {
+ public:
+ KviCryptEngineDescription(){};
+ virtual ~KviCryptEngineDescription(){};
+ public:
+ QString szName; // engine name
+ QString szDescription; // details
+ QString szAuthor; // algorithm author
+ int iFlags; // properties
+ crypt_engine_allocator_func allocFunc; // engine allocator
+ crypt_engine_deallocator_func deallocFunc; // deallocation function (if called from outside the origin module)
+ void * providerHandle; // used to identify the provider module
+ };
+
+
+ class KVILIB_API KviCryptEngineManager
+ {
+ public:
+ KviCryptEngineManager();
+ virtual ~KviCryptEngineManager();
+ private:
+ KviPointerHashTable<QString,KviCryptEngineDescription> * m_pEngineDict;
+ public:
+ const KviPointerHashTable<QString,KviCryptEngineDescription> * engineDict(){ return m_pEngineDict; };
+ void registerEngine(KviCryptEngineDescription * d);
+ void unregisterEngine(const QString &szName);
+ void unregisterEngines(void * providerHandle);
+ //
+ // Allocates a crypt engine
+ // Please note that the engine may be deleted from outside
+ // so you'd better connect the "destroyed" signal
+ //
+ KviCryptEngine * allocateEngine(const QString &szName);
+ void deallocateEngine(KviCryptEngine * e);
+ };
+
+#endif //COMPILE_CRYPT_SUPPORT
+
+
+#endif //!_KVI_CRYPT_H_
diff --git a/src/kvilib/ext/kvi_databuffer.cpp b/src/kvilib/ext/kvi_databuffer.cpp
new file mode 100644
index 00000000..7cad39c4
--- /dev/null
+++ b/src/kvilib/ext/kvi_databuffer.cpp
@@ -0,0 +1,135 @@
+//
+// File : kvi_databuffer.cpp
+// Creation date : Thu Aug 23 17:04:24 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#define __KVILIB__
+
+
+#define _KVI_DEBUG_CHECK_RANGE_
+
+#include "kvi_debug.h"
+
+#include "kvi_databuffer.h"
+#include "kvi_malloc.h"
+#include "kvi_memmove.h"
+
+// FIXME: this could resize in chunks!...this would be damn faster :)
+
+KviDataBuffer::KviDataBuffer(int uSize,const unsigned char * data)
+{
+ __range_valid(uSize > 0);
+ m_uSize = uSize;
+ m_pData = (unsigned char *)kvi_malloc(sizeof(unsigned char) * uSize);
+ if(data)kvi_memmove(m_pData,data,uSize);
+}
+
+KviDataBuffer::KviDataBuffer()
+{
+ m_uSize = 0;
+ m_pData = 0;
+}
+
+KviDataBuffer::~KviDataBuffer()
+{
+ if(m_pData)
+ {
+ __range_valid(m_uSize);
+ kvi_free(m_pData);
+ }
+}
+
+int KviDataBuffer::find(const unsigned char * block,int uSize)
+{
+ if(uSize < 1)return -1;
+ if(uSize > m_uSize)return -1;
+
+ int uSearchSize = (m_uSize - uSize) + 1;
+
+ for(int i=0;i<uSearchSize;i++)
+ {
+ if(m_pData[i] == *block)
+ {
+ // good beginning
+ if(uSize == 1)return i;
+ int j;
+ for(j = 1;j<uSize;j++)
+ {
+ if(m_pData[i + j] != block[j])
+ {
+ j = 0;
+ break;
+ }
+ }
+ if(j > 0)return i;
+ }
+ }
+
+ return -1;
+}
+
+int KviDataBuffer::find(unsigned char c)
+{
+ const unsigned char * p = m_pData;
+ const unsigned char * e = p + m_uSize;
+ while(p < e)
+ {
+ if(*p == c)return (p - m_pData);
+ p++;
+ }
+ return -1;
+}
+
+
+void KviDataBuffer::remove(int uSize)
+{
+ __range_valid((uSize <= m_uSize) && (uSize > 0));
+
+ m_uSize -= uSize;
+
+ if(m_uSize > 0)
+ {
+ kvi_memmove(m_pData,m_pData + uSize,m_uSize);
+ m_pData = (unsigned char *)kvi_realloc(m_pData,m_uSize * sizeof(unsigned char));
+ } else {
+ kvi_free(m_pData);
+ m_pData = 0;
+ }
+}
+
+void KviDataBuffer::resize(int uSize)
+{
+ __range_valid(uSize >= 0);
+ if(uSize > 0)
+ {
+ m_pData = (unsigned char *)kvi_realloc(m_pData,uSize * sizeof(unsigned char));
+ } else {
+ kvi_free(m_pData);
+ m_pData = 0;
+ }
+ m_uSize = uSize;
+}
+
+void KviDataBuffer::append(const unsigned char * data,int uSize)
+{
+ m_pData = (unsigned char *)kvi_realloc(m_pData,m_uSize + uSize);
+ kvi_memmove(m_pData + m_uSize,data,uSize);
+ m_uSize += uSize;
+}
diff --git a/src/kvilib/ext/kvi_databuffer.h b/src/kvilib/ext/kvi_databuffer.h
new file mode 100644
index 00000000..62e09b06
--- /dev/null
+++ b/src/kvilib/ext/kvi_databuffer.h
@@ -0,0 +1,56 @@
+#ifndef _KVI_DATABUFFER_H_
+#define _KVI_DATABUFFER_H_
+//
+// File : kvi_databuffer.h
+// Creation date : Thu Aug 23 17:04:25 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+#include "kvi_heapobject.h"
+
+class KVILIB_API KviDataBuffer : public KviHeapObject
+{
+public:
+ // uSize MUST be greater than 0
+ // if data is non-zero, it MUST point to a buffer at least uSize bytes long
+ // and the data is COPIED from that buffer!
+ KviDataBuffer(int uSize,const unsigned char * data = 0);
+ KviDataBuffer();
+ ~KviDataBuffer();
+private:
+ int m_uSize;
+ unsigned char * m_pData;
+public:
+ int size() const { return m_uSize; };
+ unsigned char * data() const { return m_pData; };
+ // uSize MUST be smaller or equal to size()
+ // consumes data!
+ void remove(int uSize);
+ void clear(){ if(m_uSize > 0)remove(m_uSize); };
+ // uSize MUST be greater than 0
+ void resize(int uSize);
+ void addSize(int uSize){ resize(m_uSize + uSize); };
+ void append(const unsigned char * data,int uSize);
+ void append(const KviDataBuffer &b){ append(b.data(),b.size()); };
+ int find(unsigned char c);
+ int find(const unsigned char * block,int uSize);
+};
+
+#endif //_KVI_DATABUFFER_H_
diff --git a/src/kvilib/ext/kvi_dcophelper.cpp b/src/kvilib/ext/kvi_dcophelper.cpp
new file mode 100644
index 00000000..83f34f4e
--- /dev/null
+++ b/src/kvilib/ext/kvi_dcophelper.cpp
@@ -0,0 +1,357 @@
+//=============================================================================
+//
+// File : kvi_dcophelper.cpp
+// Created on Sat 20 Jan 2007 12:35:21 by Alexander Stillich
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot net>
+// Copyright (C) 2007 Alexander Stillich <torque at pltn dot org>
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+#include "kvi_dcophelper.h"
+
+#ifdef COMPILE_KDE_SUPPORT
+
+#include "dcopclient.h"
+
+#include <qdatastream.h>
+#include <qvaluelist.h>
+
+// must be included this way, since kvilib is built
+// before kvirc and symlinks to headers aren't set yet
+#include "../../kvirc/kernel/kvi_app.h"
+#include "kvi_thread.h"
+
+KviDCOPHelper::KviDCOPHelper(bool bStartApp, const KviQCString &szAppId)
+{
+ m_szAppId = szAppId;
+}
+
+KviDCOPHelper::~KviDCOPHelper()
+{
+}
+
+bool KviDCOPHelper::ensureAppRunning(const QString &szApp)
+{
+ if (findRunningApp(m_szAppId))
+ return true;
+
+ if (m_bStartApp)
+ return startApp(m_szAppId,400);
+
+ return false;
+}
+
+
+bool KviDCOPHelper::voidRetVoidDCOPCall(const KviQCString &szObj,const KviQCString &szFunc)
+{
+ if(!ensureAppRunning(m_szAppId))return false;
+ QByteArray data;
+ return g_pApp->dcopClient()->send(m_szAppId,szObj,szFunc,data);
+}
+
+bool KviDCOPHelper::voidRetBoolDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,bool bVal)
+{
+ if(!ensureAppRunning(m_szAppId))return false;
+ QByteArray data;
+ QDataStream arg(data, IO_WriteOnly);
+ arg << bVal;
+ return g_pApp->dcopClient()->send(m_szAppId,szObj,szFunc,data);
+}
+
+bool KviDCOPHelper::voidRetIntDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,int iVal)
+{
+ if(!ensureAppRunning(m_szAppId))return false;
+ QByteArray data;
+ QDataStream arg(data, IO_WriteOnly);
+ arg << iVal;
+ return g_pApp->dcopClient()->send(m_szAppId,szObj,szFunc,data);
+}
+
+bool KviDCOPHelper::voidRetIntBoolDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,int iVal, bool bVal)
+{
+ if(!ensureAppRunning(m_szAppId))return false;
+ QByteArray data;
+ QDataStream arg(data, IO_WriteOnly);
+ arg << iVal;
+ arg << bVal;
+ return g_pApp->dcopClient()->send(m_szAppId,szObj,szFunc,data);
+}
+
+bool KviDCOPHelper::voidRetIntIntIntDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,int iVal1, int iVal2, int iVal3)
+{
+ if(!ensureAppRunning(m_szAppId))return false;
+ QByteArray data;
+ QDataStream arg(data, IO_WriteOnly);
+ arg << iVal1;
+ arg << iVal2;
+ arg << iVal3;
+ return g_pApp->dcopClient()->send(m_szAppId,szObj,szFunc,data);
+}
+
+bool KviDCOPHelper::voidRetFloatDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,float fVal)
+{
+ if(!ensureAppRunning(m_szAppId))return false;
+ QByteArray data;
+ QDataStream arg(data, IO_WriteOnly);
+ arg << fVal;
+ return g_pApp->dcopClient()->send(m_szAppId,szObj,szFunc,data);
+}
+
+bool KviDCOPHelper::voidRetStringDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,const QString &szVal)
+{
+ if(!ensureAppRunning(m_szAppId))return false;
+ QByteArray data;
+ QDataStream arg(data, IO_WriteOnly);
+ arg << szVal;
+ return g_pApp->dcopClient()->send(m_szAppId,szObj,szFunc,data);
+}
+
+bool KviDCOPHelper::stringRetVoidDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,QString &szRet)
+{
+ if(!ensureAppRunning(m_szAppId))return false;
+ QByteArray data, replyData;
+ KviQCString replyType;
+ if(!g_pApp->dcopClient()->call(m_szAppId,szObj,szFunc,data,replyType,replyData))
+ return false;
+ QDataStream reply( replyData, IO_ReadOnly );
+ if(replyType == "QString")
+ {
+ reply >> szRet;
+ return true;
+ }
+ return false;
+}
+
+bool KviDCOPHelper::stringRetIntDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,QString &szRet,int iVal)
+{
+ if(!ensureAppRunning(m_szAppId))return false;
+ QByteArray data, replyData;
+ KviQCString replyType;
+
+ QDataStream arg(data, IO_WriteOnly);
+ arg << iVal;
+
+ if(!g_pApp->dcopClient()->call(m_szAppId,szObj,szFunc,data,replyType,replyData))
+ return false;
+
+ QDataStream reply( replyData, IO_ReadOnly );
+ if(replyType == "QString")
+ {
+ reply >> szRet;
+ return true;
+ }
+ return false;
+}
+
+bool KviDCOPHelper::intRetVoidDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,int &ret)
+{
+ if(!ensureAppRunning(m_szAppId))return false;
+ QByteArray data, replyData;
+ KviQCString replyType;
+ if(!g_pApp->dcopClient()->call(m_szAppId,szObj,szFunc,data,replyType,replyData))
+ return false;
+ QDataStream reply( replyData, IO_ReadOnly );
+ if(replyType == "int")
+ {
+ reply >> ret;
+ return true;
+ }
+ return false;
+}
+
+bool KviDCOPHelper::intRetIntDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,int &ret, int iVal)
+{
+ if(!ensureAppRunning(m_szAppId))return false;
+ QByteArray data, replyData;
+ KviQCString replyType;
+
+ QDataStream arg(data, IO_WriteOnly);
+ arg << iVal;
+
+ if(!g_pApp->dcopClient()->call(m_szAppId,szObj,szFunc,data,replyType,replyData))
+ return false;
+
+ QDataStream reply( replyData, IO_ReadOnly );
+ if(replyType == "int")
+ {
+ reply >> ret;
+ return true;
+ }
+ return false;
+}
+
+bool KviDCOPHelper::boolRetVoidDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,bool &ret)
+{
+ if(!ensureAppRunning(m_szAppId))return false;
+ QByteArray data, replyData;
+ KviQCString replyType;
+ if(!g_pApp->dcopClient()->call(m_szAppId,szObj,szFunc,data,replyType,replyData))
+ return false;
+ QDataStream reply( replyData, IO_ReadOnly );
+ if(replyType == "bool")
+ {
+ reply >> ret;
+ return true;
+ }
+ return false;
+}
+
+bool KviDCOPHelper::qvalueListIntRetIntDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,KviValueList<int> &ret, int iVal)
+{
+ if(!ensureAppRunning(m_szAppId))
+ return false;
+
+ QByteArray data, replyData;
+ KviQCString replyType;
+ QDataStream arg(data, IO_WriteOnly);
+
+ arg << iVal;
+
+
+ if(!g_pApp->dcopClient()->call(m_szAppId,szObj,szFunc,data,replyType,replyData))
+ return false;
+
+ if(replyType != "QValueList<int>")
+ return false;
+
+ QDataStream replyStream(replyData, IO_ReadOnly);
+ replyStream >> ret;
+
+ return true;
+}
+
+bool KviDCOPHelper::qcstringListRetVoidDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,KviQCStringList &ret)
+{
+ QByteArray data, replyData;
+ KviQCString replyType;
+
+ if (!g_pApp->dcopClient()->call(m_szAppId,szObj,szFunc,data,replyType,replyData))
+ return false;
+
+ if (replyType != "KviQCStringList")
+ return false;
+
+ QDataStream replyStream(replyData, IO_ReadOnly);
+ replyStream >> ret;
+
+ return true;
+}
+
+bool KviDCOPHelper::qcstringListRetIntDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,KviQCStringList &ret, int iVal)
+{
+ QByteArray data, replyData;
+ KviQCString replyType;
+
+ QDataStream arg(data, IO_WriteOnly);
+ arg << iVal;
+
+ if (!g_pApp->dcopClient()->call(m_szAppId,szObj,szFunc,data,replyType,replyData))
+ return false;
+
+ if (replyType != "KviQCStringList")
+ return false;
+
+ QDataStream replyStream(replyData, IO_ReadOnly);
+ replyStream >> ret;
+
+ return true;
+}
+
+bool KviDCOPHelper::findRunningApp(const QString &szApp)
+{
+ QValueList<KviQCString> allApps = g_pApp->dcopClient() ->registeredApplications();
+ QValueList<KviQCString>::iterator iterator;
+ KviQCString sz = szApp.local8Bit();
+ for (iterator = allApps.begin();iterator != allApps.end();iterator++)
+ {
+ if(*iterator == sz)
+ return true;
+ }
+ return false;
+}
+
+int KviDCOPHelper::detectApp(const QString &szApp,bool bStart,int iScoreWhenFound,int iScoreWhenStarted)
+{
+ // dcop available
+ if(!g_pApp->dcopClient())
+ return 0;
+
+ if(findRunningApp(szApp))
+ return 95; // found a running app, no need to run further
+
+ // no app found running
+ if(bStart)
+ {
+ // try to start it
+ if(!startApp(szApp,5000))
+ return 10; // very low possibility
+ return findRunningApp(szApp) ? 99 : 0; // try to find it again
+ }
+
+ return 30; // it still might be installed on the system but we're just unable to start it...
+}
+
+
+bool KviDCOPHelper::startApp(const QString &szApp,int iWaitMSecs)
+{
+ // we could use KApplication::startServiceByDesktopName here
+ // but we want to be able to wait a defined amount of time
+ QStringList tmp;
+ QByteArray data, replyData;
+ KviQCString replyType;
+ QDataStream arg(data, IO_WriteOnly);
+ arg << szApp << tmp;
+ if(!g_pApp->dcopClient()->call(
+ "klauncher",
+ "klauncher",
+ "start_service_by_desktop_name(QString,QStringList)",
+ data,
+ replyType,
+ replyData))
+ {
+ return false;
+ } else {
+ QDataStream reply(replyData, IO_ReadOnly);
+ if(replyType != "serviceResult")return false;
+ int result;
+ KviQCString dcopName;
+ QString error;
+ reply >> result >> dcopName >> error;
+ if(result != 0)return false;
+ }
+ // ok , we seem to have started it.. but it might take some seconds
+ // for the app to get registered
+ // we wait up to five seconds
+ if(iWaitMSecs > 0)
+ {
+ int i = 0;
+ while(i < iWaitMSecs)
+ {
+ if(findRunningApp(szApp))return true;
+ KviThread::msleep(100);
+ i += 100;
+ }
+ return findRunningApp(szApp);
+ }
+ return true;
+}
+
+
+#endif //COMPILE_KDE_SUPPORT
diff --git a/src/kvilib/ext/kvi_dcophelper.h b/src/kvilib/ext/kvi_dcophelper.h
new file mode 100644
index 00000000..de605e37
--- /dev/null
+++ b/src/kvilib/ext/kvi_dcophelper.h
@@ -0,0 +1,82 @@
+#ifndef _KVI_DCOPHELPER_H_
+#define _KVI_DCOPHELPER_H_
+//=============================================================================
+//
+// File : kvi_dcophelper.h
+// Created on Sat 20 Jan 2007 12:35:21 by Alexander Stillich
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot net>
+// Copyright (C) 2007 Alexander Stillich <torque at pltn dot org>
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_qcstring.h"
+#include "kvi_valuelist.h"
+
+#ifdef COMPILE_KDE_SUPPORT
+
+typedef KviValueList<KviQCString> KviQCStringList;
+
+class KVILIB_API KviDCOPHelper
+{
+
+public:
+
+ // Constructs a DCOP helper object.
+ // bStartApp: tries to start application when a dcop call is about to be made and the app is not already running
+ // szAppID: application name as seen by DCOP
+ KviDCOPHelper(bool bStartApp, const KviQCString &szAppId);
+ ~KviDCOPHelper();
+
+protected:
+
+ KviQCString m_szAppId;
+ bool m_bStartApp;
+
+protected:
+
+ bool ensureAppRunning(const QString &szApp);
+ bool findRunningApp(const QString &szApp);
+ bool startApp(const QString &szApp,int iWaitMSecs = 0);
+ int detectApp(const QString &szApp,bool bStart,int iScoreWhenFound,int iScoreWhenStarted);
+
+ // naming convention: [return value] Ret [argument type(s)] DCOPCall
+
+ bool voidRetVoidDCOPCall(const KviQCString &szObj,const KviQCString &szFunc);
+ bool voidRetIntDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,int iVal);
+ bool voidRetIntBoolDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,int iVal, bool bVal);
+ bool voidRetIntIntIntDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,int iVal1, int iVal2, int iVal3);
+ bool voidRetBoolDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,bool bVal);
+ bool voidRetStringDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,const QString &szVal);
+ bool voidRetFloatDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,float fVal);
+ bool stringRetVoidDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,QString &szRet);
+ bool stringRetIntDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,QString &szRet,int iVal);
+ bool intRetVoidDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,int &ret);
+ bool intRetIntDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,int &ret, int iVal);
+ bool boolRetVoidDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,bool &ret);
+
+ bool qvalueListIntRetIntDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,KviValueList<int> &ret, int iVal);
+ bool qcstringListRetIntDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,KviQCStringList &ret, int iVal);
+ bool qcstringListRetVoidDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,KviQCStringList &ret);
+};
+
+#endif //COMPILE_KDE_SUPPORT
+
+#endif // _KVI_DCOPHELPER_H_
diff --git a/src/kvilib/ext/kvi_doublebuffer.cpp b/src/kvilib/ext/kvi_doublebuffer.cpp
new file mode 100644
index 00000000..5997e934
--- /dev/null
+++ b/src/kvilib/ext/kvi_doublebuffer.cpp
@@ -0,0 +1,90 @@
+//=============================================================================
+//
+// File : kvi_doublebuffer.cpp
+// Created on Fri 27 Jan 2006 18:59:54 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2006 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+
+#include "kvi_doublebuffer.h"
+
+static QPixmap * g_pMemoryPixmap = 0;
+static unsigned int g_uMaxRequestedWidth = 0;
+static unsigned int g_uMaxRequestedHeight = 0;
+
+KviDoubleBuffer::KviDoubleBuffer(unsigned int uWidth,unsigned int uHeight)
+{
+ if((g_pMemoryPixmap->width() < uWidth) || (g_pMemoryPixmap->height() < uHeight))
+ {
+ // The memory buffer is too small
+ // There is either no such user requirement or it has grown by the meantime
+ unsigned int uMaxW = uWidth > g_pMemoryPixmap->width() ? uWidth : g_pMemoryPixmap->width();
+ unsigned int uMaxH = uHeight > g_pMemoryPixmap->height() ? uHeight : g_pMemoryPixmap->height();
+#ifdef COMPILE_USE_QT4
+ // QT4SUX: QPixmap::resize() is missing (it's a widely used function and assigning a new QPixmap() seems to be slower and not intuitive)
+ *g_pMemoryPixmap = QPixmap(uMaxW,uMaxH);
+#else
+ g_pMemoryPixmap->resize(uMaxW,uMaxH);
+#endif
+ }
+
+ if(uWidth > g_uMaxRequestedWidth)g_uMaxRequestedWidth = uWidth;
+ if(uHeight > g_uMaxRequestedHeight)g_uMaxRequestedHeight = uHeight;
+}
+
+KviDoubleBuffer::~KviDoubleBuffer()
+{
+ // We never shrink here (it's time consuming)
+}
+
+QPixmap * KviDoubleBuffer::pixmap()
+{
+ return g_pMemoryPixmap;
+}
+
+void KviDoubleBuffer::init()
+{
+ if(g_pMemoryPixmap)return;
+ g_pMemoryPixmap = new QPixmap();
+}
+
+void KviDoubleBuffer::done()
+{
+ if(!g_pMemoryPixmap)return;
+ delete g_pMemoryPixmap;
+ g_pMemoryPixmap = 0;
+}
+
+void KviDoubleBuffer::heartbeat()
+{
+ if(((g_uMaxRequestedHeight + 64) < g_pMemoryPixmap->height()) || ((g_uMaxRequestedWidth + 64) < g_pMemoryPixmap->width()))
+ {
+ // do shrink :)
+#ifdef COMPILE_USE_QT4
+ // QT4SUX: QPixmap::resize() is missing (it's a widely used function and assigning a new QPixmap() seems to be slower and not intuitive)
+ *g_pMemoryPixmap = QPixmap(g_uMaxRequestedWidth,g_uMaxRequestedHeight);
+#else
+ g_pMemoryPixmap->resize(g_uMaxRequestedWidth,g_uMaxRequestedHeight);
+#endif
+ }
+ g_uMaxRequestedHeight = 0;
+ g_uMaxRequestedWidth = 0;
+}
diff --git a/src/kvilib/ext/kvi_doublebuffer.h b/src/kvilib/ext/kvi_doublebuffer.h
new file mode 100644
index 00000000..103759a1
--- /dev/null
+++ b/src/kvilib/ext/kvi_doublebuffer.h
@@ -0,0 +1,62 @@
+#ifndef _KVI_DOUBLEBUFFER_H_
+#define _KVI_DOUBLEBUFFER_H_
+//=============================================================================
+//
+// File : kvi_doublebuffer.h
+// Created on Fri 27 Jan 2006 18:59:54 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2006 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#include <qpixmap.h>
+
+//
+// This class is basically a huge shared memory pixmap meant to be used in double-buffer
+// painting operations. The memory buffer is resized on the fly so you will always obtain
+// a pixmap that is at least of the specified size. The problem is that this is a time
+// consuming operation (not good in a paint event). We solve it by keeping the buffer
+// with the greatest requested size in the last N minutes.
+//
+// The keyword in all this thingie is "memory is cheap, processing time is not".
+// We know in advance that KVIrc needs a huge double buffer anyway...
+// So we basically grow instantly but we are really lazy at shrinking.
+//
+
+class KVILIB_API KviDoubleBuffer
+{
+public:
+ KviDoubleBuffer(unsigned int uWidth,unsigned int uHeight);
+ ~KviDoubleBuffer();
+public:
+ // This returns a pointer to the memory buffer. The buffer is at least
+ // of the size declared in the constructor.
+ QPixmap * pixmap();
+
+ // The stuff below is internal (used only by KviApp)
+
+ // to be called at application initialisation and cleanup
+ static void init();
+ static void done();
+ // this has to be called at sensible intervals (like 2 minutes)
+ static void heartbeat();
+};
+
+#endif //!_KVI_DOUBLEBUFFER_H_
diff --git a/src/kvilib/ext/kvi_draganddrop.h b/src/kvilib/ext/kvi_draganddrop.h
new file mode 100644
index 00000000..c8bd9f3e
--- /dev/null
+++ b/src/kvilib/ext/kvi_draganddrop.h
@@ -0,0 +1,45 @@
+#ifndef _KVI_DRAGANDDROP_H_
+#define _KVI_DRAGANDDROP_H_
+
+//=============================================================================
+//
+// File : kvi_draganddrop.h
+// Creation date : Wed Feb 01 2007 01:45:21 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+
+#ifdef COMPILE_USE_QT4
+ #include <q3dragobject.h>
+ #define KviDragObject Q3DragObject
+ #define KviUriDrag Q3UriDrag
+ #define KviTextDrag Q3TextDrag
+ #define KviImageDrag Q3ImageDrag
+#else
+ #include <qdragobject.h>
+ #define KviDragObject QDragObject
+ #define KviUriDrag QUriDrag
+ #define KviTextDrag QTextDrag
+ #define KviImageDrag QImageDrag
+#endif
+
+#endif //!_KVI_DRAGANDDROP_H_
diff --git a/src/kvilib/ext/kvi_garbage.cpp b/src/kvilib/ext/kvi_garbage.cpp
new file mode 100644
index 00000000..0e2e8881
--- /dev/null
+++ b/src/kvilib/ext/kvi_garbage.cpp
@@ -0,0 +1,148 @@
+//
+// File : kvi_garbage.cpp
+// Creation date : Mon Dec 3 16:49:15 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+#define __KVILIB__
+
+
+
+#include "kvi_garbage.h"
+
+#include <qvariant.h>
+
+KviGarbageCollector::KviGarbageCollector()
+: QObject(0)
+{
+ m_pGarbageList = 0;
+ m_pCleanupTimer = 0;
+ m_bForceCleanupNow = false;
+}
+
+KviGarbageCollector::~KviGarbageCollector()
+{
+ m_bForceCleanupNow = true;
+ cleanup();
+}
+
+void KviGarbageCollector::collect(QObject * g)
+{
+ if(!m_pGarbageList)
+ {
+ m_pGarbageList = new KviPointerList<QObject>;
+ m_pGarbageList->setAutoDelete(true);
+ }
+ //debug("COLLECTING GARBAGE %s",g->className());
+ m_pGarbageList->append(g);
+// debug("Registering garbage object %d (%s:%s)",g,g->className(),g->name());
+ connect(g,SIGNAL(destroyed()),this,SLOT(garbageSuicide()));
+ triggerCleanup(0);
+}
+
+void KviGarbageCollector::garbageSuicide()
+{
+ if(!m_pGarbageList)
+ {
+ debug("Ops... garbage suicide while no garbage list");
+ return;
+ }
+ int idx = m_pGarbageList->findRef(sender());
+ if(idx == -1)
+ {
+ debug("Ops... unregistered garbage suicide");
+ return;
+ }
+ m_pGarbageList->removeRef(sender());
+ if(m_pGarbageList->isEmpty())
+ {
+ cleanup();
+ }
+}
+
+void KviGarbageCollector::triggerCleanup(int iTimeout)
+{
+ //debug("TRIGGERING CLEANUP AFTER %d msecs",iTimeout);
+ if(m_pCleanupTimer)
+ {
+ m_pCleanupTimer->stop();
+ } else {
+ m_pCleanupTimer = new QTimer(this);
+ connect(m_pCleanupTimer,SIGNAL(timeout()),this,SLOT(cleanup()));
+ }
+ m_pCleanupTimer->start(iTimeout);
+}
+
+void KviGarbageCollector::cleanup()
+{
+ //debug("CLEANUP CALLED !");
+ if(m_pGarbageList)
+ {
+ //debug("SOME GARBAGE TO DELETE");
+ KviPointerList<QObject> dying;
+ dying.setAutoDelete(false);
+ for(QObject * o = m_pGarbageList->first();o;o = m_pGarbageList->next())
+ {
+ //debug("CHECKING GARBAGE CLASS %s",o->className());
+ bool bDeleteIt = m_bForceCleanupNow;
+ if(!bDeleteIt)
+ {
+ //debug("CLEANUP NOT FORCED");
+ QVariant v = o->property("blockingDelete");
+ if(v.isValid())
+ {
+ //debug("HAS A VALID VARIANT!");
+// debug("[Garbage collector]: garbage has a blockingDelete property");
+ bDeleteIt = !(v.toBool());
+// if(!bDeleteIt)debug("And doesn't want to be delete now!");
+ } else bDeleteIt = true; // must be deleted
+ }
+ if(bDeleteIt)dying.append(o);
+ }
+
+ for(QObject * o2 = dying.first();o2;o2 = dying.next())
+ {
+ //debug("KILLING GARBAGE CLASS %s",o2->className());
+ disconnect(o2,SIGNAL(destroyed()),this,SLOT(garbageSuicide()));
+ m_pGarbageList->removeRef(o2);
+ }
+
+ if(m_pGarbageList->isEmpty())
+ {
+ delete m_pGarbageList;
+ m_pGarbageList = 0;
+ }
+ }
+
+ if(m_pGarbageList)
+ {
+// debug("[Garbage collector cleanup]: Some stuff left to be deleted, will retry in a while");
+ // something left to be destroyed
+ if(m_bForceCleanupNow)debug("[Garbage collector]: Ops...I've left some undeleted stuff!");
+ triggerCleanup(5000); // retry in 5 sec
+ } else {
+// debug("[Garbage collector cleanup]: Completed");
+ // nothing left to delete
+ if(m_pCleanupTimer)
+ {
+ delete m_pCleanupTimer;
+ m_pCleanupTimer = 0;
+ }
+ }
+}
+
diff --git a/src/kvilib/ext/kvi_garbage.h b/src/kvilib/ext/kvi_garbage.h
new file mode 100644
index 00000000..6bb75641
--- /dev/null
+++ b/src/kvilib/ext/kvi_garbage.h
@@ -0,0 +1,51 @@
+#ifndef _KVI_GARBAGE_H_
+#define _KVI_GARBAGE_H_
+//
+// File : kvi_garbage.h
+// Creation date : Mon Dec 3 16:49:13 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+
+#include <qobject.h>
+#include "kvi_pointerlist.h"
+#include <qtimer.h>
+
+
+class KVILIB_API KviGarbageCollector : public QObject
+{
+ Q_OBJECT
+public:
+ KviGarbageCollector();
+ ~KviGarbageCollector();
+protected:
+ KviPointerList<QObject> * m_pGarbageList;
+ QTimer * m_pCleanupTimer;
+ bool m_bForceCleanupNow;
+public:
+ void collect(QObject * g);
+protected:
+ void triggerCleanup(int iTimeout);
+protected slots:
+ void cleanup();
+ void garbageSuicide();
+};
+
+#endif //_KVI_GARBAGE_H_
diff --git a/src/kvilib/ext/kvi_imagelib.cpp b/src/kvilib/ext/kvi_imagelib.cpp
new file mode 100644
index 00000000..10835b25
--- /dev/null
+++ b/src/kvilib/ext/kvi_imagelib.cpp
@@ -0,0 +1,138 @@
+//=============================================================================
+//
+// File : kvi_imagelib.cpp
+// Creation date : Wed Jul 21 1999 16:41:26 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+
+#include <qnamespace.h>
+
+#include "kvi_imagelib.h"
+#include "kvi_fileutils.h"
+#include "kvi_locale.h"
+#include "kvi_memmove.h"
+
+#include <qpixmap.h>
+
+
+//KviImageLibrary::KviImageLibrary(const QPixmap &pixmap,int imageWidth,int imageHeight)
+//{
+// if(pixmap.isNull())m_pLibrary=0;
+// else m_pLibrary=new QPixmap(pixmap);
+// setImageSize(imageWidth,imageHeight);
+//}
+
+KviImageLibrary::KviImageLibrary(const QString &path,int imageWidth,int imageHeight)
+{
+ m_pLibrary=0;
+ loadLibrary(path);
+ setImageSize(imageWidth,imageHeight);
+}
+
+KviImageLibrary::KviImageLibrary(const QString &path1,const QString &path2,int imageWidth,int imageHeight)
+{
+ m_pLibrary=0;
+ if(KviFileUtils::fileExists(path1))
+ {
+ loadLibrary(path1);
+ if(m_pLibrary==0)loadLibrary(path2);
+ } else loadLibrary(path2);
+ setImageSize(imageWidth,imageHeight);
+}
+
+
+KviImageLibrary::~KviImageLibrary()
+{
+ unloadLibrary();
+}
+
+void KviImageLibrary::unloadLibrary()
+{
+ if(m_pLibrary)delete m_pLibrary;
+ m_pLibrary=0;
+}
+
+bool KviImageLibrary::setImageSize(int imageWidth,int imageHeight)
+{
+ m_iWidth=((imageWidth>0) ? imageWidth : 16);
+ m_iHeight=((imageHeight>0) ? imageHeight : 16);
+ return true;
+}
+
+bool KviImageLibrary::loadLibrary(const QString &path)
+{
+ if(m_pLibrary)delete m_pLibrary;
+ m_pLibrary=new QImage(path);
+ if(m_pLibrary->isNull())
+ {
+ delete m_pLibrary;
+ m_pLibrary=0;
+ debug("WARNING : Can not load image library %s",KviQString::toUtf8(path).data());
+ }
+ return (m_pLibrary != 0);
+}
+
+int KviImageLibrary::imageCount()
+{
+ if(!m_pLibrary)return 0;
+ if((m_iWidth<1)||(m_iHeight<1))return 0;
+ int nRows=m_pLibrary->width()/m_iWidth;
+ return ( nRows * (m_pLibrary->height()/m_iHeight));
+}
+
+QPixmap KviImageLibrary::getImage(int zeroBasedIndex)
+{
+ if((zeroBasedIndex >= imageCount())||(zeroBasedIndex < 0)||(m_pLibrary->depth() < 8))
+ {
+ QPixmap image(32,32);
+ image.fill(); //White fill
+ return image;
+ }
+
+ // Im per row is not zero...because imageCount returned non zero.
+ int imPerRow=(m_pLibrary->width() / m_iWidth);
+ int xOffset=(zeroBasedIndex % imPerRow) * m_iWidth;
+ int yOffset=(zeroBasedIndex / imPerRow) * m_iHeight;
+
+#ifdef COMPILE_USE_QT4
+ QImage image(m_iWidth,m_iHeight,m_pLibrary->format());
+#else
+ QImage image(m_iWidth,m_iHeight,m_pLibrary->depth());
+#endif
+
+ int d = image.depth() / 8;
+#ifndef COMPILE_USE_QT4
+ if(d == 4)image.setAlphaBuffer(true); // Qt 4.x should manage it automagically
+#endif
+ //Copy the image data
+ //bitBlt(&image,0,0,m_pLibrary,xOffset,yOffset,m_iWidth,m_iHeight,Qt::CopyROP,false);
+
+ for(int i=0;i<m_iHeight;i++)
+ kvi_memmove(image.scanLine(i),m_pLibrary->scanLine(i + yOffset) + (xOffset * d),m_iWidth * d);
+
+#ifdef COMPILE_USE_QT4
+ QPixmap p = QPixmap::fromImage(image);
+#else
+ QPixmap p(image);
+#endif
+ return p;
+}
diff --git a/src/kvilib/ext/kvi_imagelib.h b/src/kvilib/ext/kvi_imagelib.h
new file mode 100644
index 00000000..d78c8d19
--- /dev/null
+++ b/src/kvilib/ext/kvi_imagelib.h
@@ -0,0 +1,73 @@
+#ifndef _KVI_IMAGELIB_H_
+#define _KVI_IMAGELIB_H_
+
+//
+// File : kvi_imagelib.h
+// Creation date : Wed Jul 21 1999 16:41:26 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+//
+// A class to manage multiple image libraries.
+// The library is in fact a big image that contains
+// several rows of other smaller images of the same size.
+// The images inside the 'library' are indexed in the following way:
+//
+// -------------
+// |...|...|...|
+// |.0.|.1.|.2.|
+// -------------
+// |...|...|...|
+// |.3.|.4.|.5.|
+// -------------
+// |...|...|...|
+//
+// The 'library' image should have the size that is a multiple
+// of the single image size. If not , the remaining part is ignored.
+// The first image starts always in the left upper corner.
+//
+
+// WARNING: This class will be removed in the near future. Don't use it.
+
+#include "kvi_settings.h"
+
+#include <qimage.h>
+
+class KVILIB_API KviImageLibrary
+{
+public: // Consruction & Destruction
+// KviImageLibrary(const QPixmap &pixmap,int imageWidth,int imageHeight);
+ KviImageLibrary(const QString &path,int imageWidth,int imageHeight);
+ KviImageLibrary(const QString &path1,const QString &path2,int imageWidth,int imageHeight);
+ ~KviImageLibrary();
+public: // Fields
+ QImage *m_pLibrary;
+ int m_iWidth;
+ int m_iHeight;
+public: // Methods
+ bool loadLibrary(const QString &path);
+ void unloadLibrary();
+ int imageCount();
+ bool libraryLoaded(){ return (m_pLibrary != 0); };
+ QImage *getLibrary(){ return m_pLibrary; };
+ QPixmap getImage(int zeroBasedIndex);
+ bool setImageSize(int imageWidth,int imageHeight);
+};
+
+#endif //_KVI_IMAGELIB_H_INCLUDED_
diff --git a/src/kvilib/ext/kvi_md5.cpp b/src/kvilib/ext/kvi_md5.cpp
new file mode 100644
index 00000000..cbf01500
--- /dev/null
+++ b/src/kvilib/ext/kvi_md5.cpp
@@ -0,0 +1,298 @@
+//
+// File : kvi_md5.cpp
+// Creation date : Wed Sep 4 22:16:45 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#define __KVILIB__
+
+
+
+/*
+ ######################################################################
+
+ MD5Sum - MD5 Message Digest Algorithm.
+
+ This code implements the MD5 message-digest algorithm. The algorithm is
+ due to Ron Rivest. This code was written by Colin Plumb in 1993, no
+ copyright is claimed. This code is in the public domain; do with it what
+ you wish.
+
+ Equivalent code is available from RSA Data Security, Inc. This code has
+ been tested against that, and is equivalent, except that you don't need to
+ include two pages of legalese with every copy.
+
+ To compute the message digest of a chunk of bytes, instantiate the class,
+ and repeatedly call one of the Add() members. When finished the Result
+ method will return the Hash and finalize the value.
+
+ Changed so as no longer to depend on Colin Plumb's `usual.h' header
+ definitions; now uses stuff from dpkg's config.h.
+ - Ian Jackson <ijackson@nyx.cs.du.edu>.
+
+ Changed into a C++ interface and made work with APT's config.h.
+ - Jason Gunthorpe <jgg@gpu.srv.ualberta.ca>
+
+ Interface adapted to the KVIrc irc client
+ - Szymon Stefanek <pragma at kvirc dot net>
+
+ The classes use arrays of char that are a specific size. We cast those
+ arrays to uint8_t's and go from there. This allows us to advoid using
+ the uncommon inttypes.h in a public header or internally newing memory.
+ In theory if C9x becomes nicely accepted
+
+ ##################################################################### */
+
+#include "kvi_md5.h"
+#include "kvi_settings.h"
+#include "kvi_bswap.h"
+#include "kvi_memmove.h"
+
+/* Swap n 32 bit longs in given buffer */
+#ifdef BIG_ENDIAN_MACHINE_BYTE_ORDER
+ static void byteSwap(kvi_u32_t *buf,unsigned int words)
+ {
+// kvi_u8_t *p = (kvi_u8_t *)buf;
+// do
+// {
+// *buf++ = (kvi_u32_t)((unsigned)p[3] << 8 | p[2]) << 16 | ((unsigned)p[1] << 8 | p[0]);
+// p += 4;
+// } while (--words);
+ do {
+ *buf = kvi_swap32(*buf);
+ buf++;
+ } while(--words);
+ }
+#else
+ #define byteSwap(buf,words)
+#endif
+
+/* The core of the MD5 algorithm, this alters an existing MD5 hash to
+ reflect the addition of 16 longwords of new data. Add blocks
+ the data and converts bytes into longwords for this routine. */
+
+// The four core functions - F1 is optimized somewhat
+// #define F1(x, y, z) (x & y | ~x & z)
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+// This is the central step in the MD5 algorithm.
+#define MD5STEP(f,w,x,y,z,in,s) \
+ (w += f(x,y,z) + in, w = (w<<s | w>>(32-s)) + x)
+
+static void MD5Transform(kvi_u32_t buf[4],const kvi_u32_t in[16])
+{
+ register kvi_u32_t a, b, c, d;
+
+ a = buf[0];
+ b = buf[1];
+ c = buf[2];
+ d = buf[3];
+
+ MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+ MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+ MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+ MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+ MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+ MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+ MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+ MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+ MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+ MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+ MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+ MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+ MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+ MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+ MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+ MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+ MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+ MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+ MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+ MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+ MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+ MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+ MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+ MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+ MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+ MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+ MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+ MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+ MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+ MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+ MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+ MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+ MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+ MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+ MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+ MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+ MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+ MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+ MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+ MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+ MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+ MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+ MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+ MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+ MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+ MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+ MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+ MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+ MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+ MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+ MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+ MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+ MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+ MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+ MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+ MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+ MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+ MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+ MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+ MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+ MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+ MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+ MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+ MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+ buf[0] += a;
+ buf[1] += b;
+ buf[2] += c;
+ buf[3] += d;
+}
+
+KviMd5::KviMd5()
+{
+ kvi_u32_t *buf = (kvi_u32_t *)m_pBuf;
+ kvi_u32_t *bytes = (kvi_u32_t *)m_pBytes;
+
+ buf[0] = 0x67452301;
+ buf[1] = 0xefcdab89;
+ buf[2] = 0x98badcfe;
+ buf[3] = 0x10325476;
+
+ bytes[0] = 0;
+ bytes[1] = 0;
+
+ m_bDone = false;
+}
+
+KviMd5::~KviMd5()
+{
+}
+
+bool KviMd5::add(const unsigned char *data,unsigned long len)
+{
+ if(m_bDone)return false;
+
+ kvi_u32_t *buf = (kvi_u32_t *)m_pBuf;
+ kvi_u32_t *bytes = (kvi_u32_t *)m_pBytes;
+ kvi_u32_t *in = (kvi_u32_t *)m_pIn;
+
+ // Update byte count and carry (this could be done with a long long?)
+ kvi_u32_t t = bytes[0];
+
+ if ((bytes[0] = t + len) < t)bytes[1]++;
+
+ // Space available (at least 1)
+ t = 64 - (t & 0x3f);
+ if (t > len)
+ {
+ kvi_fastmove((unsigned char *)in + 64 - t,data,len);
+ return true;
+ }
+
+ // First chunk is an odd size
+ kvi_fastmove((unsigned char *)in + 64 - t,data,t);
+ byteSwap(in, 16);
+
+ MD5Transform(buf,in);
+ data += t;
+ len -= t;
+
+ // Process data in 64-byte chunks
+ while (len >= 64)
+ {
+ kvi_fastmove(in,data,64);
+ byteSwap(in,16);
+ MD5Transform(buf,in);
+ data += 64;
+ len -= 64;
+ }
+
+ // Handle any remaining bytes of data.
+ kvi_memmove(in,data,len);
+
+ return true;
+}
+
+
+// ---------------------------------------------------------------------
+/* Because this must add in the last bytes of the series it prevents anyone
+ from calling add after. */
+
+KviStr KviMd5::result()
+{
+ kvi_u32_t *buf = (kvi_u32_t *)m_pBuf;
+ kvi_u32_t *bytes = (kvi_u32_t *)m_pBytes;
+ kvi_u32_t *in = (kvi_u32_t *)m_pIn;
+
+ if(!m_bDone)
+ {
+ // Number of bytes in In
+ int count = bytes[0] & 0x3f;
+ unsigned char *p = (unsigned char *)in + count;
+
+ // Set the first char of padding to 0x80. There is always room.
+ *p++ = 0x80;
+
+ // Bytes of padding needed to make 56 bytes (-8..55)
+ count = 56 - 1 - count;
+
+ // Padding forces an extra block
+ if (count < 0)
+ {
+ kvi_memset(p,0,count + 8);
+ byteSwap(in, 16);
+ MD5Transform(buf,in);
+ p = (unsigned char *)in;
+ count = 56;
+ }
+
+ kvi_memset(p, 0, count);
+ byteSwap(in, 14);
+
+ // Append length in bits and transform
+ in[14] = bytes[0] << 3;
+ in[15] = bytes[1] << 3 | bytes[0] >> 29;
+ MD5Transform(buf,in);
+ byteSwap(buf,4);
+ m_bDone = true;
+ }
+
+ // m_pBuf now contains the md5 sum
+ KviStr ret;
+ ret.bufferToHex((char *)m_pBuf,16);
+
+ return ret;
+}
diff --git a/src/kvilib/ext/kvi_md5.h b/src/kvilib/ext/kvi_md5.h
new file mode 100644
index 00000000..113c3a7c
--- /dev/null
+++ b/src/kvilib/ext/kvi_md5.h
@@ -0,0 +1,68 @@
+#ifndef _KVI_MD5_H_
+#define _KVI_MD5_H_
+//
+// File : kvi_md5.h
+// Creation date : Wed Sep 4 22:16:44 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+
+/* ######################################################################
+
+ MD5SumValue - Storage for a MD5Sum
+ MD5Summation - MD5 Message Digest Algorithm.
+
+ This is a C++ interface to a set of MD5Sum functions. The class can
+ store a MD5Sum in 16 bytes of memory.
+
+ A MD5Sum is used to generate a (hopefully) unique 16 byte number for a
+ block of data. This can be used to gaurd against corruption of a file.
+ MD5 should not be used for tamper protection, use SHA or something more
+ secure.
+
+ There are two classes because computing a MD5 is not a continual
+ operation unless 64 byte blocks are used. Also the summation requires an
+ extra 18*4 bytes to operate.
+
+ ##################################################################### */
+
+#include "kvi_settings.h"
+#include "kvi_inttypes.h"
+#include "kvi_string.h"
+
+class KviMd5
+{
+public:
+ KviMd5();
+ ~KviMd5();
+protected:
+ unsigned char m_pBuf[4*4];
+ unsigned char m_pBytes[2*4];
+ unsigned char m_pIn[16*4];
+ bool m_bDone;
+
+public:
+ bool add(const unsigned char *Data,unsigned long Size);
+
+ KviStr result();
+};
+
+
+#endif //_KVI_MD5_H_
diff --git a/src/kvilib/ext/kvi_mediatype.cpp b/src/kvilib/ext/kvi_mediatype.cpp
new file mode 100644
index 00000000..87c7926d
--- /dev/null
+++ b/src/kvilib/ext/kvi_mediatype.cpp
@@ -0,0 +1,541 @@
+//
+// File : kvi_mediatype.cpp
+// Creation date : Mon Aug 21 2000 17:51:56 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#define __KVILIB__
+
+
+//#define _KVI_DEBUG_CHECK_RANGE_
+
+
+
+#include "kvi_debug.h"
+#include "kvi_mediatype.h"
+#include "kvi_config.h"
+#include "kvi_fileutils.h"
+#include "kvi_locale.h"
+#include "kvi_file.h"
+
+#include "kvi_settings.h"
+
+#include <qregexp.h>
+#include <qdir.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+
+#ifndef COMPILE_ON_WINDOWS
+ #include <unistd.h>
+ #include "kvi_malloc.h"
+#endif
+
+
+
+#ifndef S_ISDIR
+#define S_ISDIR(__f) (__f & _S_IFDIR)
+#endif
+
+#ifndef S_ISFIFO
+#define S_ISFIFO(__f) (__f & _S_IFIFO)
+#endif
+
+#ifndef S_ISREG
+#define S_ISREG(__f) (__f & _S_IFREG)
+#endif
+
+#ifndef S_ISCHR
+#define S_ISCHR(__f) (__f & _S_IFCHR)
+#endif
+
+#ifndef COMPILE_ON_WINDOWS
+ #include <dirent.h>
+#else
+ #include "kvi_malloc.h"
+#endif
+
+
+
+
+KviMediaManager::KviMediaManager()
+: KviMutex()
+{
+ m_pMediaTypeList = new KviPointerList<KviMediaType>;
+ m_pMediaTypeList->setAutoDelete(true);
+}
+
+KviMediaManager::~KviMediaManager()
+{
+ delete m_pMediaTypeList;
+}
+
+KviMediaType * KviMediaManager::findMediaTypeByIanaType(const char * ianaType)
+{
+ __range_valid(locked());
+ for(KviMediaType * mt = m_pMediaTypeList->first();mt;mt = m_pMediaTypeList->next())
+ {
+ if(kvi_strEqualCI(mt->szIanaType.ptr(),ianaType))return mt;
+ }
+
+ return 0;
+}
+
+KviMediaType * KviMediaManager::findMediaTypeByFileMask(const char * filemask)
+{
+ __range_valid(locked());
+ for(KviMediaType * mt = m_pMediaTypeList->first();mt;mt = m_pMediaTypeList->next())
+ {
+// FIXME: #warning "Should this be case sensitive ?"
+ if(kvi_strEqualCI(mt->szFileMask.ptr(),filemask))return mt;
+ }
+
+ return 0;
+}
+
+void KviMediaManager::copyMediaType(KviMediaType * dst,KviMediaType * src)
+{
+ dst->szFileMask = src->szFileMask;
+ dst->szMagicBytes = src->szMagicBytes;
+ dst->szIanaType = src->szIanaType;
+ dst->szDescription = src->szDescription;
+ dst->szSavePath = src->szSavePath;
+ dst->szCommandline = src->szCommandline;
+ dst->szRemoteExecCommandline = src->szRemoteExecCommandline;
+ dst->szIcon = src->szIcon;
+}
+
+
+void KviMediaManager::insertMediaType(KviMediaType * m)
+{
+ __range_valid(locked());
+ int iWildCount = m->szFileMask.occurences('*');
+ int iNonWildCount = m->szFileMask.len() - iWildCount;
+
+ // The masks with no wildcards go first in the list
+ // then we insert the ones with more non-wild chars
+
+ int index = 0;
+ for(KviMediaType * mt = m_pMediaTypeList->first();mt;mt = m_pMediaTypeList->next())
+ {
+ if(iWildCount)
+ {
+ // the new mask has wildcards... if the current one has none, skip it
+ int iWildCountExisting = mt->szFileMask.occurences('*');
+ if(iWildCountExisting)
+ {
+ // the one in the list has wildcards too...
+ // the ones with more non-wild chars go first...
+ int iNonWildCountExisting = mt->szFileMask.len() - iWildCountExisting;
+ if(iNonWildCountExisting < iNonWildCount)
+ {
+ // ok...the new one has more non-wildcards , insert
+ m_pMediaTypeList->insert(index,m);
+ return;
+ } else {
+ if(iNonWildCount == iNonWildCountExisting)
+ {
+ // the same number of non-wildcards
+ // let the number of wildcards decide (it will be eventually equal)
+ if(iWildCount < iWildCountExisting)
+ {
+ // the new one has less wildcards... goes first
+ m_pMediaTypeList->insert(index,m);
+ return;
+ } // else the same number of wildcards and non-wildcards...skip
+ } // else the existing one has more non-wildcards...skip
+ }
+ } // else the current has no wildcards...skip
+ } else {
+ // the new mask has no wildcards....
+ if(mt->szFileMask.contains('*'))
+ {
+ // current one has wildcards...insert
+ m_pMediaTypeList->insert(index,m);
+ return;
+ }
+ // the current one has no wildcards...
+ // the longer masks go first....
+ if(mt->szFileMask.len() < m->szFileMask.len())
+ {
+ // the current one is shorter than the new one...insert
+ m_pMediaTypeList->insert(index,m);
+ return;
+ } // else current one is longer...skip
+ }
+ index++;
+ }
+ m_pMediaTypeList->append(m);
+
+/*
+ // the masks with no wildcards go first
+ // longer masks go first
+
+ bool bHasWildcards = m->szFileMask.contains('*');
+ int index = 0;
+ for(KviMediaType * mt = m_pMediaTypeList->first();mt;mt = m_pMediaTypeList->next())
+ {
+ if(bHasWildcards)
+ {
+ if(mt->szFileMask.len() < m->szFileMask.len())
+ {
+ m_pMediaTypeList->insert(index,m);
+ return;
+ } else if(mt->szFileMask.len() == m->szFileMask.len())
+ {
+ if(mt->szMagicBytes.len() < m->szMagicBytes.len())
+ {
+ m_pMediaTypeList->insert(index,m);
+ return;
+ }
+ }
+ } else {
+ if(mt->szFileMask.contains('*'))
+ {
+ m_pMediaTypeList->insert(index,m);
+ return;
+ } else {
+ if(mt->szFileMask.len() < m->szFileMask.len())
+ {
+ m_pMediaTypeList->insert(index,m);
+ return;
+ } else if(mt->szFileMask.len() == m->szFileMask.len())
+ {
+ if(mt->szMagicBytes.len() < m->szMagicBytes.len())
+ {
+ m_pMediaTypeList->insert(index,m);
+ return;
+ }
+ }
+ }
+ }
+ index++;
+ }
+ m_pMediaTypeList->append(m);
+*/
+}
+
+
+KviMediaType * KviMediaManager::findMediaType(const char * filename,bool bCheckMagic)
+{
+ // FIXME: This should be ported at least to QString....
+ __range_valid(locked());
+
+ KviStr szFullPath = filename;
+ if(!kvi_isAbsolutePath(szFullPath.ptr()))
+ {
+#ifdef COMPILE_USE_QT4
+ KviStr tmp = QDir::currentPath();
+#else
+ KviStr tmp = QDir::currentDirPath();
+#endif
+ tmp.ensureLastCharIs('/');
+ szFullPath.prepend(tmp);
+ }
+
+ KviStr szFile = filename;
+ szFile.cutToLast('/',true);
+
+
+ // first of all , lstat() the file
+#ifdef COMPILE_ON_WINDOWS
+ struct _stat st;
+ if(_stat(szFullPath.ptr(),&st) != 0)
+#else
+ struct stat st;
+ if(lstat(szFullPath.ptr(),&st) != 0)
+#endif
+ {
+ //debug("Problems while stating file %s",szFullPath.ptr());
+ // We do just the pattern matching
+ // it's better to avoid magic checks
+ // if the file is a device , we would be blocked while attempting to read data
+ return findMediaTypeForRegularFile(szFullPath.ptr(),szFile.ptr(),false);
+ } else {
+ // If it is a link , stat() the link target
+#ifndef COMPILE_ON_WINDOWS
+ if(S_ISLNK(st.st_mode))
+ {
+ if(stat(szFullPath.ptr(),&st) != 0)
+ {
+ debug("Problems while stating() target for link %s",szFullPath.ptr());
+ // Same as above
+ return findMediaTypeForRegularFile(szFullPath.ptr(),szFile.ptr(),false);
+ }
+ }
+#endif
+ }
+
+
+ if(S_ISDIR(st.st_mode))
+ {
+ // Directory : return default media type
+ KviMediaType * mtd = findMediaTypeByIanaType("inode/directory");
+ if(!mtd)
+ {
+ // Add it
+ mtd = new KviMediaType;
+ mtd->szIanaType = "inode/directory";
+ mtd->szDescription = __tr("Directory");
+ mtd->szCommandline = "dirbrowser.open -m $0";
+ mtd->szIcon = "kvi_dbfolder.png"; // hardcoded ?
+ insertMediaType(mtd);
+ }
+ return mtd;
+ }
+
+
+#ifndef COMPILE_ON_WINDOWS
+ if(S_ISSOCK(st.st_mode))
+ {
+ // Socket : return default media type
+ KviMediaType * mtd = findMediaTypeByIanaType("inode/socket");
+ if(!mtd)
+ {
+ // Add it
+ mtd = new KviMediaType;
+ mtd->szIanaType = "inode/socket";
+ mtd->szDescription = __tr("Socket");
+ mtd->szIcon = "kvi_dbsocket.png"; // hardcoded ?
+ insertMediaType(mtd);
+ }
+ return mtd;
+ }
+#endif
+
+ if(S_ISFIFO(st.st_mode))
+ {
+ // Fifo: return default media type
+ KviMediaType * mtd = findMediaTypeByIanaType("inode/fifo");
+ if(!mtd)
+ {
+ // Add it
+ mtd = new KviMediaType;
+ mtd->szIanaType = "inode/fifo";
+ mtd->szDescription = __tr("Fifo");
+ mtd->szIcon = "kvi_dbfifo.png"; // hardcoded ?
+ insertMediaType(mtd);
+ }
+ return mtd;
+ }
+
+#ifndef COMPILE_ON_WINDOWS
+ if(S_ISBLK(st.st_mode))
+ {
+ // Block device: return default media type
+ KviMediaType * mtd = findMediaTypeByIanaType("inode/blockdevice");
+ if(!mtd)
+ {
+ // Add it
+ mtd = new KviMediaType;
+ mtd->szIanaType = "inode/blockdevice";
+ mtd->szDescription = __tr("Block device");
+ mtd->szIcon = "kvi_dbblockdevice.png"; // hardcoded ?
+ insertMediaType(mtd);
+ }
+ return mtd;
+ }
+#endif
+
+ if(S_ISCHR(st.st_mode))
+ {
+ // Char device: return default media type
+ KviMediaType * mtd = findMediaTypeByIanaType("inode/chardevice");
+ if(!mtd)
+ {
+ // Add it
+ mtd = new KviMediaType;
+ mtd->szIanaType = "inode/chardevice";
+ mtd->szDescription = __tr("Char device");
+ mtd->szIcon = "kvi_dbchardevice.png"; // hardcoded ?
+ insertMediaType(mtd);
+ }
+ return mtd;
+ }
+
+
+ // this is a regular file (or at least it looks like one)
+ return findMediaTypeForRegularFile(szFullPath.ptr(),szFile.ptr(),bCheckMagic);
+}
+
+KviMediaType * KviMediaManager::findMediaTypeForRegularFile(const char * szFullPath,const char * szFileName,bool bCheckMagic)
+{
+ char buffer[17];
+ int len = 0;
+
+ if(bCheckMagic)
+ {
+ QString szTmp=QString::fromUtf8(szFullPath);
+ KviFile f(szTmp);
+ if(f.openForReading())
+ {
+ len = f.readBlock(buffer,16);
+ if(len > 0)
+ {
+ buffer[len] = '\0';
+ if(buffer[0] == 0)len = 0; // no way to match it
+ }
+ f.close();
+ }
+ }
+
+ for(KviMediaType * m = m_pMediaTypeList->first();m;m = m_pMediaTypeList->next())
+ {
+// FIXME: #warning "Should this be case sensitive ?"
+ if(kvi_matchWildExpr(m->szFileMask.ptr(),szFileName))
+ {
+ if(len && m->szMagicBytes.hasData())
+ {
+ QRegExp re(m->szMagicBytes.ptr());
+ // It looks like they can't decide the name for this function :D
+ // ... well, maybe the latest choice is the best one.
+#ifdef COMPILE_USE_QT4
+ if(re.indexIn(buffer) > -1)return m; // matched!
+#else
+ #if QT_VERSION >= 300
+ if(re.search(buffer) > -1)return m; // matched!
+ #else
+ if(re.find(buffer,0) > -1)return m; // matched!
+ #endif
+#endif
+ // else magic failed...not a match
+ } else return m; // matched! (no magic check)
+ }
+ }
+
+ KviMediaType * mtd = findMediaTypeByIanaType("application/octet-stream");
+ if(!mtd)
+ {
+ // Add it
+ mtd = new KviMediaType;
+ mtd->szIanaType = "application/octet-stream";
+ mtd->szDescription = __tr("Octet stream (unknown)");
+ mtd->szCommandline = "editor.open $0";
+ mtd->szIcon = "kvi_dbunknown.png"; // hardcoded ?
+ insertMediaType(mtd);
+ }
+
+ return mtd;
+}
+
+typedef struct _KviDefaultMediaType
+{
+ const char * filemask;
+ const char * magicbytes;
+ const char * ianatype;
+ const char * description;
+ const char * commandline;
+} KviDefaultMediaType;
+
+
+// FIXME : default handlers for windows ?
+
+static KviDefaultMediaType g_defMediaTypes[]=
+{
+ { "*.jpg","^\\0330\\0377","image/jpeg","JPEG image","run kview $0" },
+ { "*.jpeg","^\\0330\\0377","image/jpeg","JPEG image","run kview $0" },
+ { "*.png","","image/png","PNG image","run kview $0" },
+ { "*.mp3","","audio/mpeg","MPEG audio","run xmms -e $0" },
+ { "*.gif","","image/gif","GIF image","run kvirc $0" },
+ { "*.mpeg","","video/mpeg","MPEG video","run xanim $0" },
+ { "*.exe","","application/x-executable-file","Executable file","run $0" },
+ { "*.zip","^PK\\0003\\0004","application/zip","ZIP archive","run ark $0" },
+ { "*.tar.gz","","application/x-gzip","GZipped tarball","run ark $0" },
+ { "*.tar.bz2","","applicatoin/x-bzip2","BZipped tarball","run ark $0" },
+ { "*.tgz","","application/x-gzip","GZipped tarball","run ark $0" },
+ { "*.wav","","audio/wav","Wave audio","run play $0" },
+ { 0,0,0,0,0 }
+};
+
+void KviMediaManager::load(const char * filename)
+{
+ __range_valid(locked());
+
+ KviConfig cfg(filename,KviConfig::Read);
+ cfg.setGroup("MediaTypes");
+ unsigned int nEntries = cfg.readUIntEntry("NEntries",0);
+ for(unsigned int i = 0; i < nEntries;i++)
+ {
+ KviMediaType * m = new KviMediaType;
+ KviStr tmp(KviStr::Format,"%dFileMask",i);
+ m->szFileMask = cfg.readEntry(tmp.ptr(),"");
+ tmp.sprintf("%dMagicBytes",i);
+ m->szMagicBytes = cfg.readEntry(tmp.ptr(),"");
+ tmp.sprintf("%dIanaType",i);
+ m->szIanaType = cfg.readEntry(tmp.ptr(),"application/unknown");
+ tmp.sprintf("%dDescription",i);
+ m->szDescription = cfg.readEntry(tmp.ptr(),"");
+ tmp.sprintf("%dSavePath",i);
+ m->szSavePath = cfg.readEntry(tmp.ptr(),"");
+ tmp.sprintf("%dCommandline",i);
+ m->szCommandline = cfg.readEntry(tmp.ptr(),"");
+ tmp.sprintf("%dRemoteExecCommandline",i);
+ m->szRemoteExecCommandline = cfg.readEntry(tmp.ptr(),"");
+ tmp.sprintf("%dIcon",i);
+ m->szIcon = cfg.readEntry(tmp.ptr(),"");
+ insertMediaType(m);
+ }
+
+ for(int u = 0;g_defMediaTypes[u].filemask;u++)
+ {
+ if(!findMediaTypeByFileMask(g_defMediaTypes[u].filemask))
+ {
+ KviMediaType * m = new KviMediaType;
+ m->szFileMask = g_defMediaTypes[u].filemask;
+ m->szMagicBytes = g_defMediaTypes[u].magicbytes;
+ m->szIanaType = g_defMediaTypes[u].ianatype;
+ m->szDescription = g_defMediaTypes[u].description;
+ m->szCommandline = g_defMediaTypes[u].commandline;
+ insertMediaType(m);
+ }
+ }
+
+}
+
+void KviMediaManager::save(const char * filename)
+{
+ __range_valid(locked());
+ KviConfig cfg(filename,KviConfig::Write);
+
+ cfg.clear();
+ cfg.setGroup("MediaTypes");
+ cfg.writeEntry("NEntries",m_pMediaTypeList->count());
+ int index = 0;
+ for(KviMediaType * m= m_pMediaTypeList->first();m;m = m_pMediaTypeList->next())
+ {
+ KviStr tmp(KviStr::Format,"%dFileMask",index);
+ cfg.writeEntry(tmp.ptr(),m->szFileMask.ptr());
+ tmp.sprintf("%dMagicBytes",index);
+ cfg.writeEntry(tmp.ptr(),m->szMagicBytes.ptr());
+ tmp.sprintf("%dIanaType",index);
+ cfg.writeEntry(tmp.ptr(),m->szIanaType.ptr());
+ tmp.sprintf("%dDescription",index);
+ cfg.writeEntry(tmp.ptr(),m->szDescription.ptr());
+ tmp.sprintf("%dSavePath",index);
+ cfg.writeEntry(tmp.ptr(),m->szSavePath.ptr());
+ tmp.sprintf("%dCommandline",index);
+ cfg.writeEntry(tmp.ptr(),m->szCommandline.ptr());
+ tmp.sprintf("%dRemoteExecCommandline",index);
+ cfg.writeEntry(tmp.ptr(),m->szRemoteExecCommandline.ptr());
+ tmp.sprintf("%dIcon",index);
+ cfg.writeEntry(tmp.ptr(),m->szIcon.ptr());
+ ++index;
+ }
+}
diff --git a/src/kvilib/ext/kvi_mediatype.h b/src/kvilib/ext/kvi_mediatype.h
new file mode 100644
index 00000000..77e96594
--- /dev/null
+++ b/src/kvilib/ext/kvi_mediatype.h
@@ -0,0 +1,83 @@
+#ifndef _KVI_MEDIATYPE_H_
+#define _KVI_MEDIATYPE_H_
+//
+// File : kvi_mediatype.h
+// Creation date : Mon Aug 21 2000 17:19:56 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+#include "kvi_heapobject.h"
+#include "kvi_string.h"
+#include "kvi_thread.h"
+
+#include "kvi_pointerlist.h"
+
+
+//
+// IANA media-types matching subsystem
+//
+// WARNING: This class is used in multiple threads
+// Thus every usage of the classes and structures defined
+// in this file MUST be protected by calls
+// to KviMediaManager::lock() and KviMediaManager::unlock()
+//
+
+
+class KVILIB_API KviMediaType : public KviHeapObject
+{
+public:
+ KviMediaType(){};
+ ~KviMediaType(){};
+public:
+ KviStr szFileMask;
+ KviStr szMagicBytes;
+ KviStr szIanaType;
+ KviStr szDescription;
+ KviStr szSavePath;
+ KviStr szCommandline;
+ KviStr szRemoteExecCommandline;
+ KviStr szIcon;
+};
+
+class KVILIB_API KviMediaManager : public KviMutex
+{
+public:
+ KviMediaManager();
+ ~KviMediaManager();
+protected:
+ KviPointerList<KviMediaType> * m_pMediaTypeList;
+private:
+ KviMediaType * findMediaTypeForRegularFile(const char * szFullPath,const char * szFileName,bool bCheckMagic);
+public:
+ KviPointerList<KviMediaType> * mediaTypeList(){ return m_pMediaTypeList; };
+ KviMediaType * findMediaTypeByFileMask(const char * filemask);
+ KviMediaType * findMediaTypeByIanaType(const char * ianaType);
+ bool removeMediaType(KviMediaType * t){ return m_pMediaTypeList->removeRef(t); };
+ void clear(){ m_pMediaTypeList->clear(); };
+ void insertMediaType(KviMediaType * t);
+ KviMediaType * findMediaType(const char * filename,bool bCheckMagic = true);
+ static void copyMediaType(KviMediaType * dst,KviMediaType * src);
+
+ void load(const char * filename);
+ void save(const char * filename);
+};
+
+
+#endif //_KVI_MEDIATYPE_H_
diff --git a/src/kvilib/ext/kvi_miscutils.cpp b/src/kvilib/ext/kvi_miscutils.cpp
new file mode 100644
index 00000000..184345ed
--- /dev/null
+++ b/src/kvilib/ext/kvi_miscutils.cpp
@@ -0,0 +1,86 @@
+//=============================================================================
+//
+// File : kvi_miscutils.cpp
+// Created on Mon 08 Jan 2007 04:07:31 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2007 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+#include "kvi_miscutils.h"
+
+#include <qstringlist.h>
+
+namespace KviMiscUtils
+{
+ int compareVersions(const QString &szVersion1,const QString &szVersion2)
+ {
+#ifdef COMPILE_USE_QT4
+ QStringList sl1 = szVersion1.split(".");
+ QStringList sl2 = szVersion2.split(".");
+#else
+ QStringList sl1 = QStringList::split(".",szVersion1);
+ QStringList sl2 = QStringList::split(".",szVersion2);
+#endif
+
+ QStringList::Iterator it1 = sl1.begin();
+ QStringList::Iterator it2 = sl2.begin();
+ while((it1 != sl1.end()) && (it2 != sl2.end()))
+ {
+ bool bOk;
+ int i1 = (*it1).toInt(&bOk);
+ if(!bOk)return 1;
+ int i2 = (*it2).toInt(&bOk);
+ if(!bOk)return -1;
+ if(i1 != i2)
+ {
+ // field not equal
+ if(i1 > i2)return -1;
+ else return 1;
+ }
+ it1++;
+ it2++;
+ }
+ // both are equal until now
+ if(it1 != sl1.end())return -1; // 1 has at least one field more
+ if(it2 != sl2.end())return 1; // 2 has at least one field more
+ // both are equal also in length
+ return 0;
+ }
+
+ bool isValidVersionString(const QString &szVersion)
+ {
+#ifdef COMPILE_USE_QT4
+ QStringList sl = szVersion.split(".");
+#else
+ QStringList sl = QStringList::split(".",szVersion);
+#endif
+ if(sl.isEmpty())return false;
+ // must all be numbers
+ for(QStringList::Iterator it = sl.begin();it != sl.end();++it)
+ {
+ bool bOk;
+ int i = (*it).toInt(&bOk);
+ if(!bOk)return false;
+ if(i < 0)return false;
+ }
+ return true;
+ }
+
+};
diff --git a/src/kvilib/ext/kvi_miscutils.h b/src/kvilib/ext/kvi_miscutils.h
new file mode 100644
index 00000000..f09d63a7
--- /dev/null
+++ b/src/kvilib/ext/kvi_miscutils.h
@@ -0,0 +1,44 @@
+#ifndef _KVI_MISCUTILS_H_
+#define _KVI_MISCUTILS_H_
+//=============================================================================
+//
+// File : kvi_miscutils.h
+// Created on Mon 08 Jan 2007 04:07:31 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2007 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+
+// this is the namespace for single function stuff that doesn't really fit anywhere else
+
+namespace KviMiscUtils
+{
+ // Compare two x.y.z... version strings.
+ // The function behaves like strcmp: it returns 0 when the versions
+ // are equal, -1 if the szVersion1 is greater and 1 if szVersion2 is greater
+ extern KVILIB_API int compareVersions(const QString &szVersion1,const QString &szVersion2);
+
+ // Check if the argument string is a valid x.y.z.... version string
+ extern KVILIB_API bool isValidVersionString(const QString &szVersion);
+
+};
+
+#endif //!_KVI_MISCUTILS_H_
diff --git a/src/kvilib/ext/kvi_msgtype.cpp b/src/kvilib/ext/kvi_msgtype.cpp
new file mode 100644
index 00000000..d79a6220
--- /dev/null
+++ b/src/kvilib/ext/kvi_msgtype.cpp
@@ -0,0 +1,68 @@
+//
+// File : kvi_msgtype.cpp
+// Creation date : Fri 30 24 2000 13:53:21 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#define __KVILIB__
+
+
+#define _KVI_DEBUG_CHECK_RANGE_
+
+#include "kvi_debug.h"
+#include "kvi_msgtype.h"
+
+KviMsgType::KviMsgType(const char * type,int pixId,unsigned char fore,unsigned char back,bool bLog,int iLevel)
+{
+ m_szType = type;
+ m_iPixId = pixId;
+ m_cForeColor = fore;
+ m_cBackColor = back;
+ m_bLogEnabled = bLog;
+ if((iLevel < KVI_MSGTYPE_MINLEVEL) || (iLevel > KVI_MSGTYPE_MAXLEVEL))iLevel = 1;
+ m_iLevel = iLevel;
+}
+
+KviMsgType::KviMsgType(const KviMsgType &msg)
+{
+ m_szType = msg.m_szType;
+ m_iPixId = msg.m_iPixId;
+ m_cForeColor = msg.m_cForeColor;
+ m_cBackColor = msg.m_cBackColor;
+ m_bLogEnabled = msg.m_bLogEnabled;
+ m_iLevel = msg.m_iLevel;
+}
+
+KviMsgType::~KviMsgType()
+{
+}
+
+
+
+KviMsgType & KviMsgType::operator=(const KviMsgType &msg)
+{
+ //if(m_szType.ptr() == msg.m_szType.ptr())return (*this); // self assignment (!!!)
+ m_szType = msg.m_szType;
+ m_iPixId = msg.m_iPixId;
+ m_cForeColor = msg.m_cForeColor;
+ m_cBackColor = msg.m_cBackColor;
+ m_bLogEnabled = msg.m_bLogEnabled;
+ m_iLevel = msg.m_iLevel;
+ return (*this);
+}
diff --git a/src/kvilib/ext/kvi_msgtype.h b/src/kvilib/ext/kvi_msgtype.h
new file mode 100644
index 00000000..ca4553ef
--- /dev/null
+++ b/src/kvilib/ext/kvi_msgtype.h
@@ -0,0 +1,74 @@
+#ifndef _KVI_MSGTYPE_H_
+#define _KVI_MSGTYPE_H_
+
+//
+// File : kvi_msgtype.h
+// Creation date : Fri Jun 30 2000 13:50:11 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+#include "kvi_string.h"
+
+#define KVI_MSGTYPE_MINLEVEL 0
+#define KVI_MSGTYPE_LEVEL_0 0
+#define KVI_MSGTYPE_LEVEL_1 1
+#define KVI_MSGTYPE_LEVEL_2 2
+#define KVI_MSGTYPE_LEVEL_3 3
+#define KVI_MSGTYPE_LEVEL_4 4
+#define KVI_MSGTYPE_LEVEL_5 5
+#define KVI_MSGTYPE_MAXLEVEL 5
+
+// 1 : Common activity
+// 2 : People talking
+// 3 : Response messages (whois , dns)
+// 4 :
+// 5 : Highlighted text
+
+// FIXME: Check the message ranges!!!
+
+class KVILIB_API KviMsgType
+{
+public:
+ KviMsgType(const char * type,int pixId,unsigned char fore,unsigned char back,bool bLog,int iLevel);
+ KviMsgType(const KviMsgType &msg);
+ ~KviMsgType();
+public:
+ const char * m_szType;
+ int m_iPixId;
+ unsigned char m_cForeColor;
+ unsigned char m_cBackColor;
+ bool m_bLogEnabled;
+ int m_iLevel;
+public:
+ void setBack(char back){ m_cBackColor = back; };
+ void setFore(char fore){ m_cForeColor = fore; };
+ int pixId(){ return m_iPixId; };
+ int level(){ return m_iLevel; };
+ void setLevel(int iLevel){ if((iLevel < KVI_MSGTYPE_MINLEVEL) || (iLevel > KVI_MSGTYPE_MAXLEVEL))m_iLevel = 1; else m_iLevel = iLevel; };
+ void setPixId(int pixId){ m_iPixId = pixId; };
+ unsigned char back(){ return m_cBackColor; };
+ unsigned char fore(){ return m_cForeColor; };
+ bool logEnabled(){ return m_bLogEnabled; };
+ void enableLogging(bool bEnable){ m_bLogEnabled = bEnable; };
+ const char * type(){ return m_szType; };
+ KviMsgType & operator=(const KviMsgType &msg); // deep copy
+};
+
+#endif //_KVI_MSGTYPE_H_
diff --git a/src/kvilib/ext/kvi_osinfo.cpp b/src/kvilib/ext/kvi_osinfo.cpp
new file mode 100644
index 00000000..51037a48
--- /dev/null
+++ b/src/kvilib/ext/kvi_osinfo.cpp
@@ -0,0 +1,510 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// File : kvi_osinfo.cpp
+// Creation date : 19 Jan 2006 GMT by Alexey Uzhva
+//
+// This toolbar is part of the KVirc irc client distribution
+// Copyright (C) 2006 Alexey Uzhva
+//
+// 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 opinion) 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.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#define __KVILIB__
+
+#include "kvi_osinfo.h"
+#include "kvi_locale.h"
+#include "kvi_qstring.h"
+
+#ifndef COMPILE_ON_WINDOWS
+ #include <sys/utsname.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+#endif
+
+#ifdef COMPILE_ON_WINDOWS
+#include <windows.h>
+
+typedef enum QueryInfo
+{
+ Os_Release,
+ Os_Version,
+ Os_Type
+};
+typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);
+typedef BOOL (WINAPI *PGETPRODUCTINFO)(DWORD,DWORD,DWORD,DWORD,PDWORD);
+
+#define SM_SERVERR2 89
+#define BUFSIZE 1024
+
+//Vista :/
+
+#define PRODUCT_BUSINESS 0x00000006
+#define PRODUCT_BUSINESS_N 0x00000010
+#define PRODUCT_CLUSTER_SERVER 0x00000012
+#define PRODUCT_DATACENTER_SERVER 0x00000008
+#define PRODUCT_DATACENTER_SERVER_CORE 0x0000000C
+#define PRODUCT_ENTERPRISE 0x00000004
+#define PRODUCT_ENTERPRISE_SERVER 0x0000000A
+#define PRODUCT_ENTERPRISE_SERVER_CORE 0x0000000E
+#define PRODUCT_ENTERPRISE_SERVER_IA64 0x0000000F
+#define PRODUCT_HOME_BASIC 0x00000002
+#define PRODUCT_HOME_BASIC_N 0x00000005
+#define PRODUCT_HOME_PREMIUM 0x00000003
+#define PRODUCT_HOME_SERVER 0x00000013
+#define PRODUCT_SERVER_FOR_SMALLBUSINESS 0x00000018
+#define PRODUCT_SMALLBUSINESS_SERVER 0x00000009
+#define PRODUCT_SMALLBUSINESS_SERVER_PREMIUM 0x00000019
+#define PRODUCT_STANDARD_SERVER 0x00000007
+#define PRODUCT_STANDARD_SERVER_CORE 0x0000000D
+#define PRODUCT_STARTER 0x0000000B
+#define PRODUCT_STORAGE_ENTERPRISE_SERVER 0x00000017
+#define PRODUCT_STORAGE_EXPRESS_SERVER 0x00000014
+#define PRODUCT_STORAGE_STANDARD_SERVER 0x00000015
+#define PRODUCT_STORAGE_WORKGROUP_SERVER 0x00000016
+#define PRODUCT_UNDEFINED 0x00000000
+#define PRODUCT_ULTIMATE 0x00000001
+#define PRODUCT_WEB_SERVER 0x00000011
+
+static QString queryWinInfo( QueryInfo info)
+{
+ QString szVersion;
+ OSVERSIONINFOEX osvi;
+ SYSTEM_INFO si;
+ PGNSI pGNSI;
+ BOOL bOsVersionInfoEx;
+
+ ZeroMemory(&si, sizeof(SYSTEM_INFO));
+ ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
+
+ // Try calling GetVersionEx using the OSVERSIONINFOEX structure.
+ // If that fails, try using the OSVERSIONINFO structure.
+
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+
+ if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) )
+ {
+ osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
+ if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) )
+ return FALSE;
+ }
+
+ // Call GetNativeSystemInfo if supported or GetSystemInfo otherwise.
+
+ pGNSI = (PGNSI) GetProcAddress(
+ GetModuleHandle(TEXT("kernel32.dll")),
+ "GetNativeSystemInfo");
+ if(NULL != pGNSI)
+ pGNSI(&si);
+ else GetSystemInfo(&si);
+
+ switch (osvi.dwPlatformId)
+ {
+ // Test for the Windows NT product family.
+
+ case VER_PLATFORM_WIN32_NT:
+
+ // Test for the specific product.
+
+ if ( osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0 )
+ {
+ if( osvi.wProductType == VER_NT_WORKSTATION )
+ szVersion+= "Windows Vista ";
+ else szVersion+="Windows Server \"Longhorn\" ";
+ }
+
+ if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2 )
+ {
+ if( GetSystemMetrics(SM_SERVERR2) )
+ szVersion+="Windows Server 2003 \"R2\" ";
+ else if( osvi.wProductType == VER_NT_WORKSTATION &&
+ si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64)
+ {
+ szVersion+="Windows XP Professional x64 Edition ";
+ }
+ else szVersion+="Windows Server 2003, ";
+ }
+
+ if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1 )
+ szVersion+="Windows XP ";
+
+ if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0 )
+ szVersion+="Windows 2000 ";
+
+ if ( osvi.dwMajorVersion <= 4 )
+ szVersion+="Windows NT ";
+
+ PGETPRODUCTINFO pGetProductInfo;
+ pGetProductInfo = (PGETPRODUCTINFO) GetProcAddress(
+ GetModuleHandle(TEXT("kernel32.dll")), "GetProductInfo");
+ // Test for specific product on Windows NT 4.0 SP6 and later.
+ if( bOsVersionInfoEx )
+ {
+ DWORD dwPlatformInfo;
+ if(NULL != pGetProductInfo)
+ if(pGetProductInfo(osvi.dwMajorVersion,osvi.dwMinorVersion,
+ osvi.wServicePackMajor,osvi.wServicePackMinor,&dwPlatformInfo))
+ {
+ switch(dwPlatformInfo)
+ {
+ case PRODUCT_BUSINESS:
+ szVersion+="Business Edition";
+ break;
+ case PRODUCT_BUSINESS_N:
+ szVersion+="Business N Edition";
+ break;
+ case PRODUCT_CLUSTER_SERVER:
+ szVersion+="Cluster Server Edition";
+ break;
+ case PRODUCT_DATACENTER_SERVER:
+ szVersion+="Server Datacenter Edition (full installation)";
+ break;
+ case PRODUCT_DATACENTER_SERVER_CORE:
+ szVersion+="Server Datacenter Edition (core installation)";
+ break;
+ case PRODUCT_ENTERPRISE:
+ szVersion+="Enterprise Edition";
+ break;
+ case PRODUCT_ENTERPRISE_SERVER:
+ szVersion+="Server Enterprise Edition (full installation)";
+ break;
+ case PRODUCT_ENTERPRISE_SERVER_CORE:
+ szVersion+="Server Enterprise Edition (core installation)";
+ break;
+ case PRODUCT_ENTERPRISE_SERVER_IA64:
+ szVersion+="Server Enterprise Edition for Itanium-based Systems";
+ break;
+ case PRODUCT_HOME_BASIC:
+ szVersion+="Home Basic Edition";
+ break;
+ case PRODUCT_HOME_BASIC_N:
+ szVersion+="Home Basic N Edition";
+ break;
+ case PRODUCT_HOME_PREMIUM:
+ szVersion+="Home Premium Edition";
+ break;
+ case PRODUCT_HOME_SERVER:
+ szVersion+="Home Server Edition";
+ break;
+ case PRODUCT_SERVER_FOR_SMALLBUSINESS:
+ szVersion+="Server for Small Business Edition";
+ break;
+ case PRODUCT_SMALLBUSINESS_SERVER:
+ szVersion+="Small Business Server";
+ break;
+ case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM:
+ szVersion+="Small Business Server Premium Edition";
+ break;
+ case PRODUCT_STANDARD_SERVER:
+ szVersion+="Server Standard Edition (full installation)";
+ break;
+ case PRODUCT_STANDARD_SERVER_CORE:
+ szVersion+="Server Standard Edition (core installation)";
+ break;
+ case PRODUCT_STARTER:
+ szVersion+="Starter Edition";
+ break;
+ case PRODUCT_STORAGE_ENTERPRISE_SERVER:
+ szVersion+="Storage Server Enterprise Edition";
+ break;
+ case PRODUCT_STORAGE_EXPRESS_SERVER:
+ szVersion+="Storage Server Express Edition";
+ break;
+ case PRODUCT_STORAGE_STANDARD_SERVER:
+ szVersion+="Storage Server Standard Edition";
+ break;
+ case PRODUCT_STORAGE_WORKGROUP_SERVER:
+ szVersion+="Storage Server Workgroup Edition";
+ break;
+ case PRODUCT_UNDEFINED:
+ szVersion+="An unknown product";
+ break;
+ case PRODUCT_ULTIMATE:
+ szVersion+="Ultimate Edition";
+ break;
+ case PRODUCT_WEB_SERVER:
+ szVersion+="Web Server Edition";
+ break;
+
+ }
+ szVersion+=" ";
+ if (si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64)
+ {
+ szVersion+="(x64) ";
+ }
+ } else {
+ // Test for the workstation type.
+ if ( osvi.wProductType == VER_NT_WORKSTATION &&
+ si.wProcessorArchitecture!=PROCESSOR_ARCHITECTURE_AMD64)
+ {
+ if( osvi.dwMajorVersion == 4 )
+ szVersion+= "Workstation 4.0 " ;
+ else if( osvi.wSuiteMask & VER_SUITE_PERSONAL )
+ szVersion+= "Home Edition " ;
+ else szVersion+= "Professional " ;
+ }
+
+ // Test for the server type.
+ else if ( osvi.wProductType == VER_NT_SERVER ||
+ osvi.wProductType == VER_NT_DOMAIN_CONTROLLER )
+ {
+ if(osvi.dwMajorVersion==5 && osvi.dwMinorVersion==2)
+ {
+ if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_IA64 )
+ {
+ if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
+ szVersion+= "Datacenter Edition for Itanium-based Systems" ;
+ else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
+ szVersion+= "Enterprise Edition for Itanium-based Systems" ;
+ }
+
+ else if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64 )
+ {
+ if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
+ szVersion+= "Datacenter x64 Edition " ;
+ else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
+ szVersion+= "Enterprise x64 Edition " ;
+ else szVersion+= "Standard x64 Edition " ;
+ }
+
+ else
+ {
+ if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
+ szVersion+= "Datacenter Edition " ;
+ else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
+ szVersion+= "Enterprise Edition " ;
+ else if ( osvi.wSuiteMask == VER_SUITE_BLADE )
+ szVersion+= "Web Edition " ;
+ else szVersion+= "Standard Edition " ;
+ }
+ }
+ else if(osvi.dwMajorVersion==5 && osvi.dwMinorVersion==0)
+ {
+ if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
+ szVersion+= "Datacenter Server " ;
+ else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
+ szVersion+= "Advanced Server " ;
+ else szVersion+= "Server " ;
+ }
+ else // Windows NT 4.0
+ {
+ if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
+ szVersion+="Server 4.0, Enterprise Edition " ;
+ else szVersion+= "Server 4.0 " ;
+ }
+ }
+ }
+ }
+ // Test for specific product on Windows NT 4.0 SP5 and earlier
+ else
+ {
+ HKEY hKey;
+ TCHAR szProductType[BUFSIZE];
+ DWORD dwBufLen=BUFSIZE*sizeof(TCHAR);
+ LONG lRet;
+
+ lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
+ TEXT("SYSTEM\\CurrentControlSet\\Control\\ProductOptions"),
+ 0, KEY_QUERY_VALUE, &hKey );
+ if( lRet != ERROR_SUCCESS )
+ return FALSE;
+
+ lRet = RegQueryValueEx( hKey, TEXT("ProductType"), NULL, NULL,
+ (LPBYTE) szProductType, &dwBufLen);
+ RegCloseKey( hKey );
+
+ if( (lRet != ERROR_SUCCESS) || (dwBufLen > BUFSIZE*sizeof(TCHAR)) )
+ return FALSE;
+
+ if ( lstrcmpi( TEXT("WINNT"), szProductType) == 0 )
+ szVersion+= "Workstation " ;
+ if ( lstrcmpi( TEXT("LANMANNT"), szProductType) == 0 )
+ szVersion+= "Server " ;
+ if ( lstrcmpi( TEXT("SERVERNT"), szProductType) == 0 )
+ szVersion+= "Advanced Server " ;
+ }
+
+
+ // Display service pack (if any) and build number.
+
+ if( osvi.dwMajorVersion == 4 &&
+ lstrcmpi( osvi.szCSDVersion, TEXT("Service Pack 6") ) == 0 )
+ {
+ HKEY hKey;
+ LONG lRet;
+
+ // Test for SP6 versus SP6a.
+ lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
+ TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009"),
+ 0, KEY_QUERY_VALUE, &hKey );
+ if( lRet == ERROR_SUCCESS )
+ szVersion+= QString("Service Pack 6a (Build %1)").arg( osvi.dwBuildNumber & 0xFFFF );
+ else // Windows NT 4.0 prior to SP6a
+ {
+ szVersion+= QString( "%1 (Build %2)").arg( osvi.szCSDVersion).arg( osvi.dwBuildNumber & 0xFFFF);
+ }
+
+ RegCloseKey( hKey );
+ }
+ else // not Windows NT 4.0
+ {
+ szVersion+= QString( "%1 (Build %2)").arg( osvi.szCSDVersion).arg( osvi.dwBuildNumber & 0xFFFF);
+ }
+
+ break;
+
+ // Test for the Windows Me/98/95.
+ case VER_PLATFORM_WIN32_WINDOWS:
+
+ if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
+ {
+ szVersion+="Windows 95 ";
+ if (osvi.szCSDVersion[1]=='C' || osvi.szCSDVersion[1]=='B')
+ szVersion+="OSR2 ";
+ }
+
+ if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
+ {
+ szVersion+="Windows 98 ";
+ if ( osvi.szCSDVersion[1]=='A' || osvi.szCSDVersion[1]=='B')
+ szVersion+="SE ";
+ }
+
+ if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
+ {
+ szVersion+="Windows Millennium Edition";
+ }
+ break;
+
+ case VER_PLATFORM_WIN32s:
+
+ szVersion+="Win32s";
+ break;
+ }
+ if(info==Os_Release)
+ {
+ unsigned long major = osvi.dwMajorVersion;
+ unsigned long minor = osvi.dwMinorVersion;
+ unsigned long release = osvi.dwBuildNumber;
+ QString szMajor, szMinor, szRelease, szVersion;
+ szMajor.setNum(major);
+ szMinor.setNum(minor);
+ szRelease.setNum(release);
+ szVersion = "Release : "+szMajor +"."+ szMinor +"."+ szRelease;
+ return szVersion;
+ }
+ if(info==Os_Type)
+ {
+ if(osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) return " NT ";
+ if(osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) return " Windows ";
+ if(osvi.dwPlatformId == VER_PLATFORM_WIN32s) return " Win32s ";
+ return __tr2qs("Unknown ");
+ }
+ if(info==Os_Version)
+ {
+ return szVersion;
+ }
+
+ return "what's wrong? o.O";
+}
+#endif
+
+
+namespace KviOsInfo
+{
+ QString type()
+ {
+#ifdef COMPILE_ON_WINDOWS
+ return queryWinInfo(Os_Type);
+#else
+ #ifdef Q_OS_MACX
+ return "macosx";
+ #else
+ return "unix";
+ #endif
+#endif
+ }
+
+ QString name()
+ {
+#ifdef COMPILE_ON_WINDOWS
+ return "windows";
+#else
+ struct utsname uts;
+ if(uname(&uts) == 0)
+ return QString::fromLocal8Bit(uts.sysname);
+ return KviQString::empty;
+#endif
+ }
+
+ QString version()
+ {
+#ifdef COMPILE_ON_WINDOWS
+ return queryWinInfo(Os_Version);
+#else
+ struct utsname uts;
+ if(uname(&uts) == 0)
+ return QString::fromLocal8Bit(uts.version);
+ return KviQString::empty;
+#endif
+ }
+
+ QString release()
+ {
+#ifdef COMPILE_ON_WINDOWS
+ return queryWinInfo(Os_Release);
+#else
+ struct utsname uts;
+ if(uname(&uts) == 0)
+ return QString::fromLocal8Bit(uts.release);
+ return KviQString::empty;
+#endif
+ }
+
+ QString machine()
+ {
+#ifdef COMPILE_ON_WINDOWS
+ QString mach = getenv("PROCESSOR_IDENTIFIER");
+ return mach.section(",",0,0);
+#else
+ struct utsname uts;
+ if(uname(&uts) == 0)
+ return QString::fromLocal8Bit(uts.machine);
+ return KviQString::empty;
+#endif
+ }
+
+ QString nodename()
+ {
+#ifdef COMPILE_ON_WINDOWS
+ return "windows";
+#else
+ struct utsname uts;
+ if(uname(&uts) == 0)
+ return QString::fromLocal8Bit(uts.nodename);
+ return KviQString::empty;
+#endif
+ }
+
+ QString hostname()
+ {
+ char hbuffer[1024];
+ if(gethostname(hbuffer,1024) == 0)
+ return QString::fromLocal8Bit(hbuffer);
+ else
+ return KviQString::empty;
+ }
+}
+
diff --git a/src/kvilib/ext/kvi_osinfo.h b/src/kvilib/ext/kvi_osinfo.h
new file mode 100644
index 00000000..9df4a990
--- /dev/null
+++ b/src/kvilib/ext/kvi_osinfo.h
@@ -0,0 +1,43 @@
+#ifndef _KVI_OSINFO_H_
+#define _KVI_OSINFO_H_
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// File : kvi_osinfo.h
+// Creation date : 19 Jan 2006 GMT by Alexey Uzhva
+//
+// This toolbar is part of the KVirc irc client distribution
+// Copyright (C) 2006 Alexey Uzhva
+//
+// 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 opinion) 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.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "kvi_settings.h"
+
+#include <qstring.h>
+
+namespace KviOsInfo
+{
+ extern KVILIB_API QString type();
+ extern KVILIB_API QString name();
+ extern KVILIB_API QString version();
+ extern KVILIB_API QString release();
+ extern KVILIB_API QString machine();
+ extern KVILIB_API QString nodename();
+ extern KVILIB_API QString hostname();
+};
+
+#endif //!_KVI_OSINFO_H_
diff --git a/src/kvilib/ext/kvi_parameterlist.cpp b/src/kvilib/ext/kvi_parameterlist.cpp
new file mode 100644
index 00000000..318cd3d1
--- /dev/null
+++ b/src/kvilib/ext/kvi_parameterlist.cpp
@@ -0,0 +1,254 @@
+//
+// File : kvi_parameterlist.cpp
+// Creation date : Tue Sep 12 2000 18:14:01 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#define __KVILIB__
+
+
+#include "kvi_parameterlist.h"
+
+KviParameterList::KviParameterList()
+: KviPointerList<KviStr>()
+{
+ setAutoDelete(true);
+}
+
+KviParameterList::KviParameterList(KviStr *p1)
+: KviPointerList<KviStr>()
+{
+ setAutoDelete(true);
+ append(p1);
+}
+
+KviParameterList::KviParameterList(KviStr *p1,KviStr *p2)
+: KviPointerList<KviStr>()
+{
+ setAutoDelete(true);
+ append(p1);
+ append(p2);
+}
+
+KviParameterList::KviParameterList(KviStr *p1,KviStr *p2,KviStr *p3)
+: KviPointerList<KviStr>()
+{
+ setAutoDelete(true);
+ append(p1);
+ append(p2);
+ append(p3);
+}
+
+KviParameterList::KviParameterList(KviStr *p1,KviStr *p2,KviStr *p3,KviStr *p4)
+: KviPointerList<KviStr>()
+{
+ setAutoDelete(true);
+ append(p1);
+ append(p2);
+ append(p3);
+ append(p4);
+}
+
+KviParameterList::KviParameterList(KviStr *p1,KviStr *p2,KviStr *p3,KviStr *p4,KviStr *p5)
+: KviPointerList<KviStr>()
+{
+ setAutoDelete(true);
+ append(p1);
+ append(p2);
+ append(p3);
+ append(p4);
+ append(p5);
+}
+
+KviParameterList::KviParameterList(KviStr *p1,KviStr *p2,KviStr *p3,KviStr *p4,KviStr *p5,KviStr *p6)
+: KviPointerList<KviStr>()
+{
+ setAutoDelete(true);
+ append(p1);
+ append(p2);
+ append(p3);
+ append(p4);
+ append(p5);
+ append(p6);
+}
+
+
+KviParameterList::KviParameterList(KviStr *p1,KviStr *p2,KviStr *p3,KviStr *p4,KviStr *p5,KviStr *p6,KviStr *p7)
+: KviPointerList<KviStr>()
+{
+ setAutoDelete(true);
+ append(p1);
+ append(p2);
+ append(p3);
+ append(p4);
+ append(p5);
+ append(p6);
+ append(p7);
+}
+
+KviParameterList::KviParameterList(const char *paramBuffer)
+: KviPointerList<KviStr>()
+{
+ setAutoDelete(true);
+ while(*paramBuffer)
+ {
+ KviStr * pStr = new KviStr();
+ paramBuffer = kvi_extractToken(*pStr,paramBuffer);
+ append(pStr);
+ }
+}
+
+KviParameterList::~KviParameterList()
+{
+}
+
+KviStr * KviParameterList::safeFirst()
+{
+ KviStr * f= first();
+ return f ? f : &m_szEmpty;
+}
+
+KviStr * KviParameterList::safeNext()
+{
+ KviStr * f = next();
+ return f ? f : &m_szEmpty;
+}
+
+
+bool KviParameterList::getBool()
+{
+ KviStr * par = current();
+ (void)next();
+ if(par)
+ {
+ if(kvi_strEqualCS(par->ptr(),"0"))return false;
+ }
+ return true; // default
+}
+
+int KviParameterList::getInt(bool * bOk)
+{
+ KviStr * par = current();
+ (void)next();
+ if(par)
+ {
+ return par->toInt(bOk);
+ }
+ if(bOk)*bOk = false;
+ return 0;
+}
+
+unsigned int KviParameterList::getUInt(bool * bOk)
+{
+ KviStr * par = current();
+ (void)next();
+ if(par)
+ {
+ return par->toUInt(bOk);
+ }
+ if(bOk)*bOk = false;
+ return 0;
+}
+
+QRect KviParameterList::getRect(bool * bOk)
+{
+ int val[4];
+ for(int i=0;i<4;i++)
+ {
+ KviStr * pszv = current();
+ (void)next();
+ if(!pszv)
+ {
+ if(bOk)*bOk = false;
+ return QRect(); // invalid
+ }
+ bool mybOk;
+ val[i] = pszv->toInt(&mybOk);
+ if(!mybOk)
+ {
+ if(bOk)*bOk = false;
+ return QRect(); // invalid
+ }
+ }
+ if(bOk)*bOk = true;
+ return QRect(val[0],val[1],val[2],val[3]);
+}
+
+QPoint KviParameterList::getPoint(bool * bOk)
+{
+ int val[2];
+ for(int i=0;i<2;i++)
+ {
+ KviStr * pszv = current();
+ (void)next();
+ if(!pszv)
+ {
+ if(bOk)*bOk = false;
+ return QPoint(); // invalid
+ }
+ bool mybOk;
+ val[i] = pszv->toInt(&mybOk);
+ if(!mybOk)
+ {
+ if(bOk)*bOk = false;
+ return QPoint(); // invalid
+ }
+ }
+ if(bOk)*bOk = true;
+ return QPoint(val[0],val[1]);
+}
+
+QSize KviParameterList::getSize(bool * bOk)
+{
+ int val[2];
+ for(int i=0;i<2;i++)
+ {
+ KviStr * pszv = current();
+ (void)next();
+ if(!pszv)
+ {
+ if(bOk)*bOk = false;
+ return QSize(); // invalid
+ }
+ bool mybOk;
+ val[i] = pszv->toInt(&mybOk);
+ if(!mybOk)
+ {
+ if(bOk)*bOk = false;
+ return QSize(); // invalid
+ }
+ }
+ if(bOk)*bOk = true;
+ return QSize(val[0],val[1]);
+}
+
+//#ifdef COMPILE_ON_WINDOWS
+//
+// #include "kvi_malloc.h"
+//
+// void * KviParameterList::operator new(size_t tSize)
+// {
+// return kvi_malloc(tSize);
+// }
+//
+// void KviParameterList::operator delete(void * p)
+// {
+// kvi_free(p);
+// }
+//#endif
diff --git a/src/kvilib/ext/kvi_parameterlist.h b/src/kvilib/ext/kvi_parameterlist.h
new file mode 100644
index 00000000..51c573e0
--- /dev/null
+++ b/src/kvilib/ext/kvi_parameterlist.h
@@ -0,0 +1,72 @@
+#ifndef _KVI_PARAMETERLIST_H_
+#define _KVI_PARAMETERLIST_H_
+
+//
+// File : kvi_parameterlist.h
+// Creation date : Tue Sep 12 2000 18:00:01 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+#include "kvi_heapobject.h"
+#include "kvi_string.h"
+
+#include "kvi_pointerlist.h"
+#include <qrect.h>
+#include <qpoint.h>
+#include <qsize.h>
+
+class KVILIB_API KviParameterList : public KviPointerList<KviStr>, public KviHeapObject
+{
+public:
+ KviParameterList();
+ KviParameterList(KviStr *p1);
+ KviParameterList(KviStr *p1,KviStr *p2);
+ KviParameterList(KviStr *p1,KviStr *p2,KviStr *p3);
+ KviParameterList(KviStr *p1,KviStr *p2,KviStr *p3,KviStr *p4);
+ KviParameterList(KviStr *p1,KviStr *p2,KviStr *p3,KviStr *p4,KviStr *p5);
+ KviParameterList(KviStr *p1,KviStr *p2,KviStr *p3,KviStr *p4,KviStr *p5,KviStr *p6);
+ KviParameterList(KviStr *p1,KviStr *p2,KviStr *p3,KviStr *p4,KviStr *p5,KviStr *p6,KviStr *p7);
+ KviParameterList(const char * paramBuffer);
+ virtual ~KviParameterList();
+private:
+ KviStr m_szEmpty;
+public:
+ void init(){ (void)first(); };
+ // These functions have to be called when the
+ // current() points to the FIRST item that has
+ // to be interpreted as Bool,Int,UInt,Rect etc...
+ // At the call exit the current() points
+ // to the first item that was NOT used by the call
+ bool getBool();
+ int getInt(bool * bOk = 0);
+ unsigned int getUInt(bool * bOk = 0);
+ QRect getRect(bool * bOk = 0);
+ QPoint getPoint(bool * bOk = 0);
+ QSize getSize(bool * bOk = 0);
+ KviStr * safeFirst();
+ KviStr * safeNext();
+ const char * safeFirstParam(){ return safeFirst()->ptr(); };
+ const char * safeNextParam(){ return safeNext()->ptr(); };
+
+};
+
+
+
+#endif //_KVI_PARAMETERLIST_H_
diff --git a/src/kvilib/ext/kvi_pixmap.cpp b/src/kvilib/ext/kvi_pixmap.cpp
new file mode 100644
index 00000000..f22b03ef
--- /dev/null
+++ b/src/kvilib/ext/kvi_pixmap.cpp
@@ -0,0 +1,180 @@
+//=============================================================================
+//
+// File : kvi_pixmap.cpp
+// Creation date : Sat Jun 24 2000 14:00:27 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+
+#define __KVILIB__
+
+
+#include "kvi_debug.h"
+#include "kvi_pixmap.h"
+#include "kvi_qstring.h"
+
+#include <qpainter.h>
+
+KviPixmap::KviPixmap()
+{
+ m_pPix = 0;
+}
+
+KviPixmap::KviPixmap(const char * path)
+{
+ m_pPix = 0;
+ load(path);
+}
+
+KviPixmap::KviPixmap(const KviPixmap &pix)
+{
+ m_pPix = 0;
+ m_szPath = pix.path();
+
+ if(!m_szPath.isEmpty())
+ {
+ if(pix.pixmap())
+ {
+ m_pPix = new QPixmap(*(pix.pixmap()));
+ }
+ }
+}
+
+KviPixmap::~KviPixmap()
+{
+ if(m_pPix)delete m_pPix;
+ m_pPix = 0; // just to be sure :)
+}
+
+bool KviPixmap::load(const char * path)
+{
+ if(m_pPix)delete m_pPix;
+ m_pPix = 0;
+ m_szPath = path;
+ if(m_szPath.isEmpty())return false;
+
+ m_pPix = new QPixmap(m_szPath);
+
+ if(m_pPix->isNull())
+ {
+ delete m_pPix;
+ m_pPix = 0;
+ m_szPath = "";
+ return false;
+ }
+ return true;
+}
+
+bool KviPixmap::load(const QString& path)
+{
+ if(m_pPix)delete m_pPix;
+ m_pPix = 0;
+ m_szPath = path;
+ if(m_szPath.isEmpty())return false;
+
+ m_pPix = new QPixmap(m_szPath);
+
+ if(m_pPix->isNull())
+ {
+ delete m_pPix;
+ m_pPix = 0;
+ m_szPath = "";
+ return false;
+ }
+ return true;
+}
+
+void KviPixmap::set(const QPixmap &pix,const QString &szPath)
+{
+ if(pix.isNull())
+ {
+ setNull();
+ return;
+ }
+
+ if(m_pPix)delete m_pPix;
+ m_pPix = new QPixmap(pix);
+ m_szPath = szPath;
+}
+
+
+void KviPixmap::setNull()
+{
+ if(m_pPix)delete m_pPix;
+ m_pPix = 0;
+ m_szPath = "";
+}
+
+KviPixmap & KviPixmap::operator=(const KviPixmap &pix)
+{
+ if(m_pPix == pix.m_pPix)return (*this); // self assignment (!!!)
+ if(KviQString::equalCI(m_szPath,pix.path()))return (*this); // same pix
+
+ if(m_pPix)delete m_pPix;
+ m_pPix = 0;
+ m_szPath = pix.path();
+
+ if(!m_szPath.isEmpty())
+ {
+ if(pix.pixmap())
+ {
+ m_pPix = new QPixmap(*(pix.pixmap()));
+ }
+ }
+ return (*this);
+}
+
+
+void KviPixmapUtils::drawPixmapWithPainter(QPainter* p,QPixmap * pix,int flags,const QRect& paintRect,int iWidgetWidth,int iWidgetHeight,int dx,int dy)
+{
+ if(!pix)return;
+ if(!flags)
+ {
+ p->drawTiledPixmap(paintRect.left(),paintRect.top(),paintRect.width(),paintRect.height(),*pix,dx,dy);
+ return;
+ }
+
+ int iPixWidth=pix->width();
+ int iPixHeight=pix->height();
+ int x=0;
+ int y=0;
+
+ if( !(flags & Qt::AlignHorizontal_Mask ))
+ x=-1;
+ else if ( flags & Qt::AlignRight )
+ x=iWidgetWidth - iPixWidth;
+ else if( flags & Qt::AlignHCenter )
+ x=(iWidgetWidth - iPixWidth)/2;
+
+ if( !(flags & Qt::AlignVertical_Mask ))
+ y=-1;
+ else if ( flags & Qt::AlignBottom )
+ y=iWidgetHeight - iPixHeight;
+ else if( flags & Qt::AlignVCenter )
+ y=(iWidgetHeight - iPixHeight)/2;
+
+ if(x==-1) {
+ p->drawTiledPixmap(paintRect.left(),y,paintRect.width(),iPixHeight,*pix,dx,dy);
+ } else if(y==-1) {
+ p->drawTiledPixmap(x,paintRect.top(),iPixWidth,paintRect.height(),*pix,dx,dy);
+ } else {
+ p->drawPixmap(x,y,*pix);
+ }
+}
diff --git a/src/kvilib/ext/kvi_pixmap.h b/src/kvilib/ext/kvi_pixmap.h
new file mode 100644
index 00000000..7ba91cec
--- /dev/null
+++ b/src/kvilib/ext/kvi_pixmap.h
@@ -0,0 +1,61 @@
+#ifndef _KVI_PIXMAP_H_
+#define _KVI_PIXMAP_H_
+
+//=============================================================================
+//
+// File : kvi_pixmap.h
+// Creation date : Sat Jun 24 2000 13:59:04 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+
+#include "kvi_settings.h"
+#include "kvi_string.h"
+#include <qpixmap.h>
+
+class KVILIB_API KviPixmap
+{
+public:
+ KviPixmap();
+ KviPixmap(const char * path);
+ KviPixmap(const KviPixmap &pix);
+ ~KviPixmap();
+private:
+ QPixmap * m_pPix;
+ QString m_szPath;
+public:
+ bool isNull(){ return m_pPix == 0; };
+ bool load(const char * path);
+ bool load(const QString& path);
+ const QString& path() const { return m_szPath; };
+ QPixmap * pixmap() const { return m_pPix; };
+ void set(const QPixmap &pix,const QString &szPath);
+ KviPixmap & operator=(const KviPixmap &pix); // deep copy
+ void setNull();
+};
+
+namespace KviPixmapUtils
+{
+ extern KVILIB_API void drawPixmapWithPainter(QPainter* p,QPixmap * pix,int flags,const QRect& paintRect,int iWidgetWidth,int iWidgetHeight,int dx,int dy);
+ inline void drawPixmapWithPainter(QPainter* p,QPixmap * pix,int flags,const QRect& paintRect,int iWidgetWidth,int iWidgetHeight)
+ { KviPixmapUtils::drawPixmapWithPainter(p,pix,flags,paintRect,iWidgetWidth,iWidgetHeight,paintRect.left(),paintRect.top()); };
+};
+
+#endif //_KVI_PIXMAP_H_
diff --git a/src/kvilib/ext/kvi_proxydb.cpp b/src/kvilib/ext/kvi_proxydb.cpp
new file mode 100644
index 00000000..917795c3
--- /dev/null
+++ b/src/kvilib/ext/kvi_proxydb.cpp
@@ -0,0 +1,192 @@
+//
+// File : kvi_proxydb.cpp
+// Creation date : Sat Jul 22 2000 18:23:23 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#define __KVILIB__
+
+
+#include "kvi_proxydb.h"
+#include "kvi_config.h"
+
+
+KviProxy::KviProxy()
+{
+ m_szHostname = "proxy.example.net";
+ m_uPort = 1080;
+ m_protocol = Socks4;
+ m_bIsIpV6 = false;
+}
+
+KviProxy::KviProxy(const KviProxy &prx)
+{
+ m_szHostname = prx.m_szHostname;
+ m_szIp = prx.m_szIp;
+ m_szUser = prx.m_szUser;
+ m_szPass = prx.m_szPass;
+ m_uPort = prx.m_uPort;
+ m_protocol = prx.m_protocol;
+ m_bIsIpV6 = prx.m_bIsIpV6;
+}
+
+KviProxy::~KviProxy()
+{
+}
+
+static const char * proxy_protocols_table[3]= { "SOCKSv4", "SOCKSv5", "HTTP" };
+
+const char * KviProxy::protocolName() const
+{
+ switch(m_protocol)
+ {
+ case Socks5: return proxy_protocols_table[1]; break;
+ case Http: return proxy_protocols_table[2]; break;
+ default: return proxy_protocols_table[0]; break;
+ }
+
+ return proxy_protocols_table[0];
+}
+
+void KviProxy::setNamedProtocol(const char * proto)
+{
+ if(kvi_strEqualCI(proto,"SOCKSv5"))m_protocol = KviProxy::Socks5;
+ else if(kvi_strEqualCI(proto,"HTTP"))m_protocol = KviProxy::Http;
+ else m_protocol = KviProxy::Socks4;
+}
+
+void KviProxy::getSupportedProtocolNames(QStringList & buf)
+{
+ for(int i=0;i<3;i++)buf.append(QString(proxy_protocols_table[i]));
+}
+
+void KviProxy::normalizeUserAndPass()
+{
+ m_szUser.stripWhiteSpace();
+ m_szPass.stripWhiteSpace();
+}
+
+KviProxyDataBase::KviProxyDataBase()
+{
+ m_pProxyList = new KviPointerList<KviProxy>;
+ m_pProxyList->setAutoDelete(true);
+ m_pCurrentProxy = 0;
+}
+
+KviProxyDataBase::~KviProxyDataBase()
+{
+ delete m_pProxyList;
+}
+
+void KviProxyDataBase::updateProxyIp(const char * proxy,const char * ip)
+{
+ for(KviProxy * prx = m_pProxyList->first();prx;prx = m_pProxyList->next())
+ {
+ if(kvi_strEqualCI(proxy,prx->m_szHostname.ptr()))
+ {
+ prx->m_szIp = ip;
+ return;
+ }
+ }
+}
+
+void KviProxyDataBase::clear()
+{
+ delete m_pProxyList;
+ m_pProxyList = new KviPointerList<KviProxy>;
+ m_pProxyList->setAutoDelete(true);
+ m_pCurrentProxy = 0;
+}
+
+void KviProxyDataBase::load(const char * filename)
+{
+ clear();
+ KviConfig cfg(filename,KviConfig::Read);
+
+ unsigned int nEntries = cfg.readUIntEntry("Entries",0);
+
+ for(unsigned int i=0;i<nEntries;i++)
+ {
+ KviProxy * p = new KviProxy();
+ KviStr tmp(KviStr::Format,"%u_Hostname",i);
+ p->m_szHostname = cfg.readEntry(tmp.ptr(),"proxy.example.net");
+ tmp.sprintf("%u_Port",i);
+ p->m_uPort = cfg.readUIntEntry(tmp.ptr(),7000);
+ tmp.sprintf("%u_Ip",i);
+ p->m_szIp = cfg.readEntry(tmp.ptr(),"");
+ tmp.sprintf("%u_User",i);
+ p->m_szUser = cfg.readEntry(tmp.ptr(),"");
+ tmp.sprintf("%u_Pass",i);
+ p->m_szPass = cfg.readEntry(tmp.ptr(),"");
+
+ tmp.sprintf("%u_Protocol",i);
+ KviStr type = cfg.readEntry(tmp.ptr(),"SOCKSv4");
+ p->setNamedProtocol(type.ptr());
+
+ tmp.sprintf("%u_IsIpV6",i);
+ p->m_bIsIpV6 = cfg.readBoolEntry(tmp.ptr(),false);
+ tmp.sprintf("%u_Current",i);
+ if(cfg.readBoolEntry(tmp.ptr(),false))m_pCurrentProxy = p;
+ m_pProxyList->append(p);
+ }
+
+ if(!m_pCurrentProxy)m_pCurrentProxy = m_pProxyList->first();
+}
+
+void KviProxyDataBase::save(const char * filename)
+{
+ KviConfig cfg(filename,KviConfig::Write);
+
+ cfg.clear();
+
+ cfg.writeEntry("Entries",m_pProxyList->count());
+
+
+ int i=0;
+
+ for(KviProxy * p=m_pProxyList->first();p;p=m_pProxyList->next())
+ {
+ KviStr tmp(KviStr::Format,"%u_Hostname",i);
+ cfg.writeEntry(tmp.ptr(),p->m_szHostname.ptr());
+ tmp.sprintf("%u_Port",i);
+ cfg.writeEntry(tmp.ptr(),p->m_uPort);
+ tmp.sprintf("%u_Ip",i);
+ cfg.writeEntry(tmp.ptr(),p->m_szIp.ptr());
+ tmp.sprintf("%u_User",i);
+ cfg.writeEntry(tmp.ptr(),p->m_szUser.ptr());
+ tmp.sprintf("%u_Pass",i);
+ cfg.writeEntry(tmp.ptr(),p->m_szPass.ptr());
+
+ tmp.sprintf("%u_Protocol",i);
+ KviStr type;
+ switch(p->m_protocol)
+ {
+ case KviProxy::Socks5: type = "SOCKSv5"; break;
+ case KviProxy::Http: type = "HTTP"; break;
+ default: type = "SOCKSv4"; break;
+ }
+ cfg.writeEntry(tmp.ptr(),type.ptr());
+
+ tmp.sprintf("%u_IsIpV6",i);
+ cfg.writeEntry(tmp.ptr(),p->m_bIsIpV6);
+ tmp.sprintf("%u_Current",i);
+ if(m_pCurrentProxy == p)cfg.writeEntry(tmp.ptr(),true);
+ i++;
+ }
+}
diff --git a/src/kvilib/ext/kvi_proxydb.h b/src/kvilib/ext/kvi_proxydb.h
new file mode 100644
index 00000000..92fa2c44
--- /dev/null
+++ b/src/kvilib/ext/kvi_proxydb.h
@@ -0,0 +1,86 @@
+#ifndef _KVI_PROXYDB_H_
+#define _KVI_PROXYDB_H_
+
+//
+// File : kvi_proxydb.h
+// Creation date : Sat Jul 22 2000 18:19:01 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+
+#include "kvi_string.h"
+#include "kvi_inttypes.h"
+#include "kvi_pointerlist.h"
+#include <qstringlist.h>
+
+class KVILIB_API KviProxy
+{
+public:
+ enum Protocol { Socks4 , Socks5 , Http };
+ KviProxy();
+ KviProxy(const KviProxy &prx);
+ ~KviProxy();
+public:
+ KviStr m_szHostname;
+ KviStr m_szIp;
+ KviStr m_szPass;
+ KviStr m_szUser;
+ kvi_u32_t m_uPort;
+ Protocol m_protocol;
+ bool m_bIsIpV6;
+public:
+ bool isIpV6() const { return m_bIsIpV6; };
+ Protocol protocol() const { return m_protocol; };
+ const char * protocolName() const;
+ void setNamedProtocol(const char * proto);
+ kvi_u32_t port() const { return m_uPort; };
+ const char * user() const { return m_szUser.ptr(); };
+ const char * pass() const { return m_szPass.ptr(); };
+ const char * ip() const { return m_szIp.ptr(); };
+ const char * hostname() const { return m_szHostname.ptr(); };
+ void normalizeUserAndPass();
+ bool hasPass() const { return m_szPass.hasData(); };
+ bool hasUser() const { return m_szUser.hasData(); };
+ unsigned int passLen() const { return (unsigned int)m_szPass.len(); };
+ unsigned int userLen() const { return (unsigned int)m_szUser.len(); };
+ static void getSupportedProtocolNames(QStringList & buf);
+};
+
+
+class KVILIB_API KviProxyDataBase
+{
+public:
+ KviProxyDataBase();
+ ~KviProxyDataBase();
+private:
+ KviPointerList<KviProxy> * m_pProxyList;
+ KviProxy * m_pCurrentProxy;
+public:
+ void clear();
+ KviPointerList<KviProxy> * proxyList(){ return m_pProxyList; };
+ KviProxy * currentProxy(){ return m_pCurrentProxy; };
+ void updateProxyIp(const char * proxy,const char * ip);
+ void setCurrentProxy(KviProxy * prx){ m_pCurrentProxy = prx; };
+ void insertProxy(KviProxy * prx){ m_pProxyList->append(prx); };
+ void load(const char * filename);
+ void save(const char * filename);
+};
+
+#endif //_KVI_PROXYDB_H_
diff --git a/src/kvilib/ext/kvi_regchan.cpp b/src/kvilib/ext/kvi_regchan.cpp
new file mode 100644
index 00000000..a26c5969
--- /dev/null
+++ b/src/kvilib/ext/kvi_regchan.cpp
@@ -0,0 +1,181 @@
+//=============================================================================
+//
+// File : kvi_regchan.cpp
+// Creation date : Sat Jun 29 01:01:16 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+
+#include "kvi_regchan.h"
+#include "kvi_config.h"
+#include "kvi_qstring.h"
+
+KviRegisteredChannel::KviRegisteredChannel(const KviStr &name,const KviStr &netmask)
+{
+ m_szName = name;
+ m_szNetMask = netmask;
+ m_pPropertyDict = new KviPointerHashTable<const char *,KviStr>(7,false,true);
+ m_pPropertyDict->setAutoDelete(true);
+}
+
+KviRegisteredChannel::~KviRegisteredChannel()
+{
+ delete m_pPropertyDict;
+}
+
+
+
+KviRegisteredChannelDataBase::KviRegisteredChannelDataBase()
+{
+ m_pChannelDict = new KviPointerHashTable<const char *,KviRegisteredChannelList>(17,false,true);
+ m_pChannelDict->setAutoDelete(true);
+}
+
+KviRegisteredChannelDataBase::~KviRegisteredChannelDataBase()
+{
+ delete m_pChannelDict;
+}
+
+void KviRegisteredChannelDataBase::load(const char * filename)
+{
+ KviConfig cfg(filename,KviConfig::Read);
+ m_pChannelDict->clear();
+ KviConfigIterator it(*(cfg.dict()));
+ while(KviConfigGroup * d = it.current())
+ {
+ KviStr szMask = it.currentKey();
+ KviStr szChan = szMask.leftToLast('@');
+ szMask.cutToLast('@');
+ KviRegisteredChannel * c = new KviRegisteredChannel(szChan,szMask);
+ add(c);
+ KviConfigGroupIterator sit(*d);
+ while(QString * s = sit.current())
+ {
+ c->setProperty(KviQString::toUtf8(sit.currentKey()).data(),new KviStr(*s));
+ ++sit;
+ }
+ ++it;
+ }
+}
+
+void KviRegisteredChannelDataBase::save(const char * filename)
+{
+ KviConfig cfg(filename,KviConfig::Write);
+ cfg.clear();
+
+ KviPointerHashTableIterator<const char *,KviRegisteredChannelList> it(*m_pChannelDict);
+ while(KviRegisteredChannelList * l = it.current())
+ {
+ for(KviRegisteredChannel * c = l->first();c;c = l->next())
+ {
+ KviStr szGrp(KviStr::Format,"%s@%s",c->name().ptr(),c->netMask().ptr());
+ cfg.setGroup(szGrp.ptr());
+ KviPointerHashTableIterator<const char *,KviStr> pit(*(c->propertyDict()));
+ while(KviStr * s = pit.current())
+ {
+ cfg.writeEntry(pit.currentKey(),s->ptr());
+ ++pit;
+ }
+ }
+ ++it;
+ }
+}
+
+KviRegisteredChannel * KviRegisteredChannelDataBase::find(const char * name,const char * net)
+{
+ KviRegisteredChannelList * l = m_pChannelDict->find(name);
+ if(!l)return 0;
+ for(KviRegisteredChannel * c = l->first();c;c = l->next())
+ {
+ if(kvi_matchString(c->netMask().ptr(),net))return c;
+ }
+
+ return 0;
+}
+
+KviRegisteredChannel * KviRegisteredChannelDataBase::findExact(const char * name,const char * netmask)
+{
+ KviRegisteredChannelList * l = m_pChannelDict->find(name);
+ if(!l)return 0;
+ for(KviRegisteredChannel * c = l->first();c;c = l->next())
+ {
+ if(kvi_strEqualCI(c->netMask().ptr(),netmask))return c;
+ }
+ return 0;
+}
+
+void KviRegisteredChannelDataBase::remove(KviRegisteredChannel * c)
+{
+ KviRegisteredChannelList * l = m_pChannelDict->find(c->name().ptr());
+ if(!l)return;
+ for(KviRegisteredChannel * ch = l->first();ch;ch = l->next())
+ {
+ if(ch == c)
+ {
+ if(l->count() <= 1)
+ {
+ m_pChannelDict->remove(c->name().ptr());
+ } else {
+ l->removeRef(c);
+ }
+ return;
+ }
+ }
+}
+
+
+void KviRegisteredChannelDataBase::add(KviRegisteredChannel * c)
+{
+ KviRegisteredChannel * old = findExact(c->name().ptr(),c->netMask().ptr());
+ if(old)
+ {
+ KviPointerHashTableIterator<const char *,KviStr> pit(*(old->propertyDict()));
+ while(KviStr *s = pit.current())
+ {
+ if(!c->property(pit.currentKey()))
+ c->setProperty(pit.currentKey(),new KviStr(*s));
+ ++pit;
+ }
+ remove(old);
+ }
+ KviRegisteredChannelList * l = m_pChannelDict->find(c->name().ptr());
+ if(!l)
+ {
+ l = new KviRegisteredChannelList;
+ l->setAutoDelete(true);
+ m_pChannelDict->insert(c->name().ptr(),l);
+ }
+ // insert where there are less wildcards
+ int o = c->netMask().occurences('*');
+ int idx = 0;
+ for(KviRegisteredChannel * rc = l->first();rc;rc = l->next())
+ {
+ if(rc->netMask().occurences('*') > o)
+ {
+ // the existing has more wildcards , insert here!
+ l->insert(idx,c);
+ return;
+ }
+ idx++;
+ }
+ l->append(c);
+}
+
diff --git a/src/kvilib/ext/kvi_regchan.h b/src/kvilib/ext/kvi_regchan.h
new file mode 100644
index 00000000..f447c313
--- /dev/null
+++ b/src/kvilib/ext/kvi_regchan.h
@@ -0,0 +1,74 @@
+#ifndef _KVI_REGCHAN_H_
+#define _KVI_REGCHAN_H_
+//=============================================================================
+//
+// File : kvi_regchan.h
+// Creation date : Sat Jun 29 01:01:15 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_heapobject.h"
+#include "kvi_string.h"
+#include "kvi_pointerlist.h"
+
+#include "kvi_pointerhashtable.h"
+
+class KVILIB_API KviRegisteredChannel : public KviHeapObject
+{
+ friend class KviRegisteredChannelDataBase;
+public:
+ KviRegisteredChannel(const KviStr &name,const KviStr &netmask);
+ ~KviRegisteredChannel();
+protected:
+ KviStr m_szName;
+ KviStr m_szNetMask;
+ KviPointerHashTable<const char *,KviStr> * m_pPropertyDict;
+public:
+ KviPointerHashTable<const char *,KviStr> * propertyDict(){ return m_pPropertyDict; };
+ const KviStr & name(){ return m_szName; };
+ const KviStr & netMask(){ return m_szNetMask; };
+ KviStr * property(const char * name){ return m_pPropertyDict->find(name); };
+ // val must be allocated with NEW!
+ void setProperty(const char * name,KviStr * val){ m_pPropertyDict->replace(name,val); };
+ void removeProperty(const char * name){ m_pPropertyDict->remove(name); };
+};
+
+typedef KVILIB_API KviPointerList<KviRegisteredChannel> KviRegisteredChannelList;
+
+class KVILIB_API KviRegisteredChannelDataBase
+{
+public:
+ KviRegisteredChannelDataBase();
+ ~KviRegisteredChannelDataBase();
+protected:
+ KviPointerHashTable<const char *,KviRegisteredChannelList> * m_pChannelDict;
+public:
+ KviPointerHashTable<const char *,KviRegisteredChannelList> * channelDict(){ return m_pChannelDict; };
+ KviRegisteredChannel * find(const char * name,const char * net);
+ KviRegisteredChannel * findExact(const char * name,const char * netmask);
+ void remove(KviRegisteredChannel * c);
+ void add(KviRegisteredChannel * c);
+ void load(const char * filename);
+ void save(const char * filename);
+};
+
+
+#endif //_KVI_REGCHAN_H_
diff --git a/src/kvilib/ext/kvi_regusersdb.cpp b/src/kvilib/ext/kvi_regusersdb.cpp
new file mode 100644
index 00000000..6d36c975
--- /dev/null
+++ b/src/kvilib/ext/kvi_regusersdb.cpp
@@ -0,0 +1,743 @@
+//=================================================================================================
+//
+// File : kvi_regusersdb.cpp
+// Creation date : Sat Sep 09 2000 15:46:12 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=================================================================================================
+
+
+#define __KVILIB__
+
+#include "kvi_debug.h"
+
+#define _KVI_REGUSERDB_CPP_
+#include "kvi_regusersdb.h"
+
+#include "kvi_config.h"
+#include "kvi_locale.h"
+
+/*
+ @doc: registered_users
+ @title:
+ Registered users
+ @type:
+ generic
+ @short:
+ Registration of users in KVIrc
+ @keyterms:
+ registered users, registration mask, registered user properties,
+ user properties, notify property, avatar property
+ @body:
+ [big]Introduction[/big][br]
+ The "registered user database" is basically a set of users with associated
+ [doc:irc_masks]irc-masks[/doc] and properties.[br]
+ It is used to recognize users on IRC and associate properties to them.[br]
+ This works more or less like the IRC ban list, K-Line list, or invite list.[br]
+ [big]User entry[/big][br]
+ A registered user database entry is identified by an [b]unique[/b] name.[br]
+ It may be the nickname of the user that you want to match, or the real name (if you know it)
+ or any other string (even with spaces). The name is an "internal identifier" for the user entry:
+ each name maps to a single entry and each entry has a single name.[br]
+ Each entry has a set of registration [doc:irc_masks]irc-masks[/doc]: these masks
+ are used to recognize the user on irc.[br]
+ [br]
+ [big]Registration masks[/big][br]
+ The masks have the common IRC mask format: [b]<nick>!<user>@<host>[/b][br]
+ The masks may contain '*' and '?' wildcards that match any portion of text.[br]
+ [b]*!*@*[/b][br]
+ [b]Pragma!*@*[/b][br]
+ [b]*!~daemon@*[/b][br]
+ [b]Pragma!*daemon@*.it[/b][br]
+ [b]Pragma!?daemon@some*.it[/b][br]
+ [b]Pragma!~daemon@some.host.it[/b][br]
+ Are examples of valid registration masks.[br]
+ The masks with wildcards can actually match more than a single user.[br]
+ For example the mask *!root@*.host.com will match all the users
+ having root as username and coming from the host.com domain.[br]
+ For this reason putting wildcards in nicknames could become a problem
+ if not used carefully (but may also be used to achieve interesting tricks).[br]
+ If you don't use wildcards in nicknames you are sure that
+ in a single irc connection , a mask will always refer to a single user.[br]
+ You will commonly use the following format:[br]
+ <nick>!*<username>@*.<host>.<top>[br]
+ or[br]
+ <nick>!*<username>@<number>.<number>.<number>.*[br]
+ In this way you can be 95% sure that the mask will really match the correct user.[br]
+ [br]
+ [big]Example of registration and lookups[/big]
+ Assume that you want to registere a friend of yours: Derek Riggs.[br]
+ Derek often uses "Eddie" as his nickname
+ "stranger" as username and has a dial-up connection that makes his IP address appear as
+ <variable-number>.somewhere.in.time.org.[br]
+ You will add an entry with name "Derek Riggs" and a registration mask like the following:
+ Eddie!stranger@*.somewhere.in.time.org.[br]
+ If the IRC servers keep adding strange characters ([doc:irc_masks]prefixes[/doc]) at the beginning of his username you may use
+ Eddie!*stranger@*.somewhere.in.time.org.[br]
+ If Eddie also often connects from the wasted.years.org domain and gets 'eddie' as username there, you might add a second registration mask as follows:
+ Eddie!*eddie@*.wasted.years.org.[br]
+ An alternative could be use only one mask with *.org as domain and allow any username (Eddie!*@*.org) but this
+ could become dangerous since it could match the users that you don't want to.[br]
+ On the other hand, if you dislike the users with the nickname Eddie that come from .org
+ and you're implementing an auto-kick system, the correct mask to register is "Eddie!*@*.org".[br]
+ [br]
+ KVirc ties to be smart , and always find the most correct match for an user:
+ If you have two masks registered: Pragma!*xor@*.myisp.it and *!*@*.myisp.it,
+ kvirc will match Pragma!~xor@233-dyn.myisp.it with the first one even if the second
+ one matches too; the firs one is a best match.[br]
+ [br]
+ [big]Properties[/big][br]
+ A registered user has an (eventually empty) set of properties
+ defined by name/value pairs. (In versions prior to 3.0.0 flags were used instead,
+ but revealed to be insufficient).[br]
+ KVirc recognizes some of these proprietes and associates semantic actions to it; other properties
+ are left for scripting extension. Property names are case insensitive.[br]
+ One of the recognized properties is the "[doc:notify_list]notify[/doc]" property.
+ When an user is found to have this property set to a special value
+ KVIrc will attempt to track the user presence on IRC.
+ Another one is the [doc:avatar]avatar[/doc] property. Its value should be the
+ name of the "default" [doc:avatar]avatar image file[/doc] for the specified user.[br]
+ The "ignore" property should be set to "1" (or "true") for users that have to be ignored (:D).[br]
+ [br]
+ [big]The interface to the database[/big][br]
+ The [module:reguser]reguser module[/module] is the interface to the "registered users database".[br]
+ It provides a set of commands for adding and removing masks and manipulating properties.[br]
+*/
+
+//============================================================================================================
+//
+// KviRegisteredMask
+//
+
+KVILIB_API KviRegisteredUserDataBase* g_pRegisteredUserDataBase = 0;
+
+KviRegisteredMask::KviRegisteredMask(KviRegisteredUser * u,KviIrcMask * m)
+{
+ m_pUser = u;
+ m_pMask = m;
+ m_iMaskNonWildChars = m_pMask->nonWildChars();
+}
+
+//============================================================================================================
+//
+// KviRegisteredUser
+//
+
+
+KviRegisteredUser::KviRegisteredUser(const QString & name)
+{
+ m_iIgnoreFlags =0;
+ m_bIgnoreEnabled=false;
+ m_szName = name;
+ m_pPropertyDict = 0;
+ m_pMaskList = new KviPointerList<KviIrcMask>;
+ m_pMaskList->setAutoDelete(true);
+}
+
+KviRegisteredUser::~KviRegisteredUser()
+{
+ if(m_pPropertyDict)delete m_pPropertyDict;
+ delete m_pMaskList;
+}
+
+bool KviRegisteredUser::isIgnoreEnabledFor(IgnoreFlags flag)
+{
+ if(!m_bIgnoreEnabled) return false;
+ return m_iIgnoreFlags & flag;
+}
+
+KviIrcMask * KviRegisteredUser::findMask(const KviIrcMask &mask)
+{
+ for(KviIrcMask * m = m_pMaskList->first();m;m = m_pMaskList->next())
+ {
+ if(*m == mask)return m;
+ }
+ return 0;
+}
+
+bool KviRegisteredUser::addMask(KviIrcMask * mask)
+{
+ if(findMask(*mask))
+ {
+ delete mask;
+ mask = 0;
+ return false;
+ }
+ m_pMaskList->append(mask);
+ return true;
+}
+
+bool KviRegisteredUser::removeMask(KviIrcMask * mask)
+{
+ if(!mask)return false;
+ return m_pMaskList->removeRef(mask);
+}
+
+bool KviRegisteredUser::matches(const KviIrcMask &mask)
+{
+ for(KviIrcMask * m = m_pMaskList->first();m;m = m_pMaskList->next())
+ {
+ if(m->matches(mask))return true;
+ }
+ return false;
+}
+
+bool KviRegisteredUser::matchesFixed(const KviIrcMask &mask)
+{
+ for(KviIrcMask * m = m_pMaskList->first();m;m = m_pMaskList->next())
+ {
+ if(m->matchesFixed(mask))return true;
+ }
+ return false;
+}
+
+bool KviRegisteredUser::matchesFixed(const QString & nick,const QString & user,const QString & host)
+{
+ for(KviIrcMask * m = m_pMaskList->first();m;m = m_pMaskList->next())
+ {
+ if(m->matchesFixed(nick,user,host))return true;
+ }
+ return false;
+}
+
+void KviRegisteredUser::setProperty(const QString &name,bool value)
+{
+ setProperty(name,value ? QString("true") : QString("false"));
+}
+
+void KviRegisteredUser::setProperty(const QString & name,const QString & value)
+{
+ if(!value.isEmpty())
+ {
+ if(!m_pPropertyDict)
+ {
+ m_pPropertyDict = new KviPointerHashTable<QString,QString>(7,false);
+ m_pPropertyDict->setAutoDelete(true);
+ }
+#ifdef COMPILE_USE_QT4
+ QString * val = new QString(value.trimmed());
+#else
+ QString * val = new QString(value.stripWhiteSpace());
+#endif
+ if(!val->isEmpty())
+ {
+ m_pPropertyDict->replace(name,val);
+ } else {
+ delete val;
+ val = 0;
+ }
+ } else {
+ if(m_pPropertyDict)m_pPropertyDict->remove(name);
+ }
+}
+
+bool KviRegisteredUser::getProperty(const QString & name,QString &value)
+{
+ if(!m_pPropertyDict)return false;
+ if(name.isEmpty()) return false;
+ QString * pValue = m_pPropertyDict->find(name);
+ if(pValue)value = *pValue;
+ else return false;
+ return true;
+}
+
+const QString & KviRegisteredUser::getProperty(const QString & name)
+{
+ if(!m_pPropertyDict)return KviQString::empty;
+ if(name.isEmpty())return KviQString::empty;
+ QString * pValue = m_pPropertyDict->find(name);
+ if(pValue)return *pValue;
+ return KviQString::empty;
+}
+
+bool KviRegisteredUser::getBoolProperty(const QString & name,bool def)
+{
+ if(!m_pPropertyDict)return def;
+ if(name.isEmpty()) return def;
+ QString * pValue = m_pPropertyDict->find(name);
+ if(pValue)
+ {
+ // be flexible , allow more "true" values (pragma)
+ if(KviQString::equalCS(*pValue,"1"))return true;
+ if(KviQString::equalCI(*pValue,"true"))return true;
+ if(KviQString::equalCI(*pValue,"yes"))return true;
+ //if(KviQString::equalCI(*pValue,"yeah"))return true;
+ //if(KviQString::equalCI(*pValue,"sure"))return true;
+ //if(KviQString::equalCI(*pValue,"sureashell"))return true;
+ }
+ return def;
+}
+
+//============================================================================================================
+//
+// KviRegisteredUserGroup
+//
+
+KviRegisteredUserGroup::KviRegisteredUserGroup(const QString &name)
+{
+ setName(name);
+}
+
+KviRegisteredUserGroup::~KviRegisteredUserGroup()
+{
+}
+
+
+//============================================================================================================
+//
+// KviRegisteredUserDb
+//
+
+KviRegisteredUserDataBase::KviRegisteredUserDataBase()
+{
+ m_pUserDict = new KviPointerHashTable<QString,KviRegisteredUser>(31,false); // do not copy keys
+ m_pUserDict->setAutoDelete(true);
+
+ m_pWildMaskList = new KviRegisteredMaskList;
+ m_pWildMaskList->setAutoDelete(true);
+
+ m_pMaskDict = new KviPointerHashTable<QString,KviRegisteredMaskList>(49,false); // copy keys here!
+ m_pMaskDict->setAutoDelete(true);
+
+ m_pGroupDict = new KviPointerHashTable<QString,KviRegisteredUserGroup>(5,false); // copy keys here!
+ m_pGroupDict->setAutoDelete(true);
+}
+
+KviRegisteredUserDataBase::~KviRegisteredUserDataBase()
+{
+ emit(databaseCleared());
+ delete m_pUserDict;
+ delete m_pWildMaskList;
+ delete m_pMaskDict;
+ delete m_pGroupDict;
+}
+
+KviRegisteredUser * KviRegisteredUserDataBase::addUser(const QString & name)
+{
+ if(name.isEmpty()) return false;
+ if(m_pUserDict->find(name))return 0;
+ KviRegisteredUser * u = new KviRegisteredUser(name);
+ m_pUserDict->replace(u->name(),u); //u->name() because we're NOT copying keys!
+ emit(userAdded(name));
+ return u;
+}
+
+KviRegisteredUserGroup * KviRegisteredUserDataBase::addGroup(const QString & name)
+{
+ if(name.isEmpty()) return false;
+ if(m_pGroupDict->find(name))return 0;
+ KviRegisteredUserGroup * pGroup = new KviRegisteredUserGroup(name);
+ m_pGroupDict->replace(pGroup->name(),pGroup); //u->name() because we're NOT copying keys!
+ return pGroup;
+}
+
+KviRegisteredUser * KviRegisteredUserDataBase::getUser(const QString & name)
+{
+ if(name.isEmpty()) return 0;
+ KviRegisteredUser * u = m_pUserDict->find(name);
+ if(!u)
+ {
+ u = new KviRegisteredUser(name);
+ m_pUserDict->replace(u->name(),u); //u->name() because we're NOT copying keys!
+ }
+ return u;
+}
+
+static void append_mask_to_list(KviRegisteredMaskList *l,KviRegisteredUser *u,KviIrcMask *mask)
+{
+ KviRegisteredMask * newMask = new KviRegisteredMask(u,mask);
+ int idx = 0;
+ for(KviRegisteredMask * m = l->first();m;m = l->next())
+ {
+ if(m->nonWildChars() < newMask->nonWildChars())
+ {
+ l->insert(idx,newMask);
+ return;
+ }
+ idx++;
+ }
+ l->append(newMask);
+}
+
+KviRegisteredUser * KviRegisteredUserDataBase::addMask(KviRegisteredUser * u,KviIrcMask * mask)
+{
+ if(!u || !mask) return 0;
+ __range_valid(u == m_pUserDict->find(u->name()));
+
+ KviRegisteredMaskList * l;
+ if(mask->hasWildNick())
+ {
+ for(KviRegisteredMask * m = m_pWildMaskList->first();m;m = m_pWildMaskList->next())
+ {
+ if(*(m->mask()) == *mask)
+ {
+ delete mask;
+ mask = 0;
+ return m->user();
+ }
+ }
+ // not found ...ok... add it
+ // masks with more info go first in the list
+ l = m_pWildMaskList;
+ } else {
+ l = m_pMaskDict->find(mask->nick());
+ if(l)
+ {
+ // FIXME: #warning "Here we could compare the host and username only: nick matches for sure"
+ for(KviRegisteredMask * m = l->first();m;m = l->next())
+ {
+ if(*(m->mask()) == *mask)
+ {
+ delete mask;
+ mask = 0;
+ return m->user();
+ }
+ }
+ // not found ...ok... add it
+ } else {
+ // not found ...ok... add it
+ // this is the first mask in the list
+ l = new KviRegisteredMaskList;
+ l->setAutoDelete(true);
+ if(!u->addMask(mask))
+ {
+ debug(" Ops...got an incoherent regusers action...recovered ?");
+ delete l;
+ l = 0;
+ } else {
+ append_mask_to_list(l,u,mask);
+ m_pMaskDict->insert(mask->nick(),l);
+ }
+ return 0;
+ }
+ }
+ // Ok...add it
+ if(!u->addMask(mask))
+ {
+ debug("ops...got an incoherent regusers action...recovered ?");
+ return 0; // ops...already there ?
+ }
+ append_mask_to_list(l,u,mask);
+ return 0;
+}
+
+void KviRegisteredUserDataBase::copyFrom(KviRegisteredUserDataBase * db)
+{
+ m_pUserDict->clear();
+ m_pWildMaskList->clear();
+ m_pMaskDict->clear();
+ m_pGroupDict->clear();
+ emit(databaseCleared());
+
+ KviPointerHashTableIterator<QString,KviRegisteredUser> it(*(db->m_pUserDict));
+
+ while(KviRegisteredUser * theCur = it.current())
+ {
+ KviRegisteredUser * u = getUser(theCur->name());
+ // copy masks
+ KviPointerList<KviIrcMask> * l = theCur->maskList();
+ for(KviIrcMask * m=l->first();m;m = l->next())
+ {
+ KviIrcMask * m2 = new KviIrcMask(*m);
+ addMask(u,m2);
+ }
+ // copy properties
+ KviPointerHashTable<QString,QString> * pd = theCur->propertyDict();
+ if(pd)
+ {
+ KviPointerHashTableIterator<QString,QString> pdi(*pd);
+ while(pdi.current())
+ {
+ u->setProperty(pdi.currentKey(),*(pdi.current()));
+ ++pdi;
+ }
+ }
+ u->m_iIgnoreFlags=theCur->m_iIgnoreFlags;
+ u->m_bIgnoreEnabled=theCur->m_bIgnoreEnabled;
+ u->setGroup(theCur->group());
+ ++it;
+ }
+
+ KviPointerHashTableIterator<QString,KviRegisteredUserGroup> git(*db->m_pGroupDict);
+ while(git.current())
+ {
+ addGroup(git.currentKey());
+ ++git;
+ }
+}
+
+
+bool KviRegisteredUserDataBase::removeUser(const QString & name)
+{
+ if(name.isEmpty()) return false;
+ KviRegisteredUser * u = m_pUserDict->find(name);
+ if(!u)return false;
+ while(KviIrcMask * mask = u->maskList()->first())
+ {
+ if(!removeMaskByPointer(mask))
+ debug("Ops... removeMaskByPointer(%s) failed ?",KviQString::toUtf8(name).data());
+ }
+ emit(userRemoved(name));
+ m_pUserDict->remove(name);
+ return true;
+}
+bool KviRegisteredUserDataBase::removeGroup(const QString & name)
+{
+ if(name.isEmpty()) return false;
+ m_pGroupDict->remove(name);
+ return true;
+}
+
+bool KviRegisteredUserDataBase::removeMask(const KviIrcMask &mask)
+{
+ // find the mask pointer
+ KviRegisteredMask * m = findExactMask(mask);
+ // and remove it
+ if(m){
+ if(removeMaskByPointer(m->mask()))
+ {
+ return true;
+ }
+ }
+ return 0;
+}
+
+bool KviRegisteredUserDataBase::removeMaskByPointer(KviIrcMask * mask)
+{
+ if(!mask) return 0;
+ if(mask->hasWildNick())
+ {
+ // remove from the wild list
+ for(KviRegisteredMask * m = m_pWildMaskList->first();m;m = m_pWildMaskList->next())
+ {
+ if(m->mask() == mask)
+ {
+ // ok..got it, remove from the list and from the user struct (user struct deletes it!)
+ emit(userChanged(mask->nick()));
+ m->user()->removeMask(mask); // this one deletes m->mask()
+ m_pWildMaskList->removeRef(m); // this one deletes m
+ return true;
+ }
+ }
+ // not found ...opz :)
+ } else {
+ KviRegisteredMaskList * l = m_pMaskDict->find(mask->nick());
+ if(l)
+ {
+ // FIXME: #warning "Here we could compare the host and username only: nick matches for sure"
+ for(KviRegisteredMask * m = l->first();m;m = l->next())
+ {
+ if(m->mask() == mask)
+ {
+ QString nick = mask->nick();
+ emit(userChanged(nick));
+ m->user()->removeMask(mask); // this one deletes m->mask() (or mask)
+ l->removeRef(m); // this one deletes m
+ if(l->count() == 0)m_pMaskDict->remove(nick);
+ return true;
+ }
+ }
+ // not found ...opz
+ }
+ }
+ // not found...
+ return false;
+}
+
+
+
+/*
+KviRegisteredUser * KviRegisteredUserDataBase::findMatchingUser(const KviIrcMask &mask)
+{
+ // first lookup the nickname in the maskDict
+ KviRegisteredMaskList * l = m_pMaskDict->find(mask.nick());
+ if(l)
+ {
+ for(KviRegisteredMask *m = l->first();m;m = l->next())
+ {
+ if(m->mask()->matchesFixed(0,mask.user(),mask.host()))return m->user();
+ }
+ }
+ // not found....lookup the wild ones
+ for(KviRegisteredMask * m = m_pWildMaskList->first();m;m = m_pWildMaskList->next())
+ {
+ if(m->mask()->matchesFixed(mask))return m->user();
+ }
+ return 0; // no match at all
+}
+*/
+KviRegisteredUser * KviRegisteredUserDataBase::findMatchingUser(const QString & nick,const QString &user,const QString & host)
+{
+ KviRegisteredMask * m = findMatchingMask(nick,user,host);
+ if(m)return m->user();
+ return 0; // no match at all
+}
+
+KviRegisteredMask * KviRegisteredUserDataBase::findMatchingMask(const QString & nick,const QString &user,const QString & host)
+{
+ // first lookup the nickname in the maskDict
+ if(nick.isEmpty()) return false;
+ KviRegisteredMaskList * l = m_pMaskDict->find(nick);
+ if(l)
+ {
+ for(KviRegisteredMask *m = l->first();m;m = l->next())
+ {
+ if(m->mask()->matchesFixed(nick,user,host))return m;
+ }
+ }
+ // not found....lookup the wild ones
+ for(KviRegisteredMask * m = m_pWildMaskList->first();m;m = m_pWildMaskList->next())
+ {
+ if(m->mask()->matchesFixed(nick,user,host))return m;
+ }
+ return 0; // no match at all
+}
+
+KviRegisteredUser * KviRegisteredUserDataBase::findUserWithMask(const KviIrcMask &mask)
+{
+ KviRegisteredMask * m = findExactMask(mask);
+ if(m)return m->user();
+ return 0;
+}
+
+KviRegisteredMask * KviRegisteredUserDataBase::findExactMask(const KviIrcMask &mask)
+{
+ // first lookup the nickname in the maskDict
+ if(mask.nick()=="") return 0;
+ KviRegisteredMaskList * l = m_pMaskDict->find(mask.nick());
+ if(l)
+ {
+ for(KviRegisteredMask *m = l->first();m;m = l->next())
+ {
+ if(*(m->mask()) == mask)return m;
+ }
+ }
+ // not found....lookup the wild ones
+ for(KviRegisteredMask * m = m_pWildMaskList->first();m;m = m_pWildMaskList->next())
+ {
+ if(*(m->mask()) == mask)return m;
+ }
+ return 0; // no match at all
+}
+/*
+bool KviRegisteredUserDataBase::isIgnoredUser(const QString & nick,const QString & user,const QString & host)
+{
+ KviRegisteredUser * u = findMatchingUser(nick,user,host);
+ if(u)return u->getBoolProperty("IGNORE");
+ else return false;
+}
+*/
+void KviRegisteredUserDataBase::load(const QString & filename)
+{
+ QString szCurrent;
+ KviConfig cfg(filename,KviConfig::Read);
+
+ KviConfigIterator it(*cfg.dict());
+ while(it.current())
+ {
+ cfg.setGroup(it.currentKey());
+ szCurrent=it.currentKey();
+ if(KviQString::equalCSN("#Group ",szCurrent,7))
+ {
+ szCurrent.remove(0,7);
+ addGroup(szCurrent);
+ } else {
+ KviRegisteredUser * u = addUser(szCurrent);
+
+ if(u)
+ {
+ u->setIgnoreEnabled(cfg.readBoolEntry("IgnoreEnabled",false));
+ u->setIgnoreFlags(cfg.readIntEntry("IgnoreFlags",0));
+ KviConfigGroupIterator sdi(*(it.current()));
+ while(sdi.current())
+ {
+ QString tmp = sdi.currentKey();
+ if(KviQString::equalCSN("prop_",tmp,5))
+ {
+ tmp.remove(0,5);
+ u->setProperty(tmp,*(sdi.current()));
+ } else if(KviQString::equalCSN("mask_",tmp,5))
+ {
+ KviIrcMask * mask = new KviIrcMask(*(sdi.current()));
+ addMask(u,mask);
+ } else if(KviQString::equalCI(tmp,"Group"))
+ {
+ u->setGroup(*(sdi.current()));
+ }
+ ++sdi;
+ }
+ }
+ }
+ ++it;
+ }
+ if(!m_pGroupDict->find(__tr("Default")))
+ addGroup(__tr("Default"));
+}
+
+
+void KviRegisteredUserDataBase::save(const QString & filename)
+{
+ KviConfig cfg(filename,KviConfig::Write);
+ cfg.clear();
+ cfg.preserveEmptyGroups(true);
+
+ KviPointerHashTableIterator<QString,KviRegisteredUser> it(*m_pUserDict);
+
+ while(it.current())
+ {
+ cfg.setGroup(it.current()->name());
+ // Write properties
+ cfg.writeEntry("IgnoreEnabled",it.current()->ignoreEnagled());
+ cfg.writeEntry("IgnoreFlags",it.current()->ignoreFlags());
+ if(it.current()->propertyDict())
+ {
+ KviPointerHashTableIterator<QString,QString> pit(*(it.current()->propertyDict()));
+ while(pit.current())
+ {
+ QString tmp = "prop_";
+ tmp.append(pit.currentKey());
+ cfg.writeEntry(tmp,*(pit.current()));
+ ++pit;
+ }
+ }
+ // Write masks
+ int idx = 0;
+ for(KviIrcMask * m = it.current()->maskList()->first();m;m = it.current()->maskList()->next())
+ {
+ QString tmp;
+ KviQString::sprintf(tmp,"mask_%d",idx);
+ QString mask;
+ m->mask(mask,KviIrcMask::NickUserHost);
+ cfg.writeEntry(tmp,mask);
+ ++idx;
+ }
+ cfg.writeEntry("Group",it.current()->group());
+ ++it;
+ }
+
+ KviPointerHashTableIterator<QString,KviRegisteredUserGroup> git(*m_pGroupDict);
+ QString szTmp;
+ while(git.current())
+ {
+ KviQString::sprintf(szTmp,"#Group %Q",&(git.current()->name()));
+ cfg.setGroup(szTmp);
+ ++git;
+ }
+
+}
diff --git a/src/kvilib/ext/kvi_regusersdb.h b/src/kvilib/ext/kvi_regusersdb.h
new file mode 100644
index 00000000..06152f24
--- /dev/null
+++ b/src/kvilib/ext/kvi_regusersdb.h
@@ -0,0 +1,201 @@
+#ifndef _KVI_REGUSERSDB_H_
+#define _KVI_REGUSERSDB_H_
+//=================================================================================================
+//
+// File : kvi_regusersdb.h
+// Creation date : Sat Sep 09 2000 15:30:56 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=================================================================================================
+
+//
+// REGISTERED USERS
+//
+// Here we manage users resigered by mask and their (generic!) properties
+//
+
+#include "kvi_settings.h"
+#include "kvi_heapobject.h"
+#include "kvi_qstring.h"
+#include "kvi_ircmask.h"
+#include "kvi_debug.h"
+
+#include "kvi_pointerlist.h"
+#include "kvi_pointerhashtable.h"
+#include <qobject.h>
+
+class KviRegisteredUserDataBase;
+
+#ifndef _KVI_REGUSERDB_CPP_
+ extern KVILIB_API KviRegisteredUserDataBase * g_pRegisteredUserDataBase;
+#endif //!_KVI_REGUSERDB_CPP_
+
+//=================================================================================================
+//
+// KviRegisteredUser
+//
+
+class KVILIB_API KviRegisteredUser : public KviHeapObject
+{
+ friend class KviRegisteredUserDataBase;
+public:
+ enum IgnoreFlags {
+ Channel=1,
+ Query=2,
+ Notice=4,
+ Ctcp=8,
+ Invite=16,
+ Dcc=32
+ };
+
+ KviRegisteredUser(const QString &name);
+ ~KviRegisteredUser();
+private:
+ int m_iIgnoreFlags;
+ bool m_bIgnoreEnabled;
+ QString m_szName;
+ QString m_szGroup;
+ KviPointerHashTable<QString,QString> * m_pPropertyDict; // owned properties
+ KviPointerList<KviIrcMask> * m_pMaskList; // owned masks
+protected:
+ // mask ownership is transferred! (always!) returns false if the mask was already there
+ bool addMask(KviIrcMask * mask);
+ bool removeMask(KviIrcMask * mask);
+ KviIrcMask * findMask(const KviIrcMask &mask);
+public:
+ int ignoreFlags() { return m_iIgnoreFlags; };
+ void setIgnoreFlags(int flags) {m_iIgnoreFlags=flags; };
+ bool ignoreEnagled() { return m_bIgnoreEnabled; };
+ void setIgnoreEnabled(bool enabled) {m_bIgnoreEnabled=enabled;};
+ bool isIgnoreEnabledFor(IgnoreFlags flag);
+
+ const QString &name(){ return m_szName; };
+ bool matches(const KviIrcMask &mask);
+ bool matchesFixed(const KviIrcMask &mask);
+ bool matchesFixed(const QString &nick,const QString &user,const QString &host);
+
+ void setProperty(const QString &name,const QString &value);
+ void setProperty(const QString &name,bool value);
+
+ void setGroup(const QString &name) { m_szGroup=name; };
+ const QString &group(){ return m_szGroup; };
+
+ const QString & getProperty(const QString &name); // returns 0 if the property is not there
+ bool getProperty(const QString &name,QString &value); // returns false if the property is not there
+ bool getBoolProperty(const QString &name,bool def=FALSE); // returns true if the property is there and is true
+ // the propertyDict may be 0!
+ KviPointerHashTable<QString,QString> * propertyDict(){ return m_pPropertyDict; };
+ // this is never zero (but may contain no masks)
+ KviPointerList<KviIrcMask> * maskList(){ return m_pMaskList; };
+};
+
+//============================================================================================================
+//
+// KviRegisteredUserGroup
+//
+
+class KVILIB_API KviRegisteredUserGroup : public KviHeapObject
+{
+ friend class KviRegisteredUserDataBase;
+public:
+ KviRegisteredUserGroup(const QString &name);
+ ~KviRegisteredUserGroup();
+
+ void setName(const QString &name) { m_szName=name; };
+ const QString &name(){ return m_szName; };
+private:
+ QString m_szName;
+};
+//============================================================================================================
+//
+// KviRegisteredMask
+//
+
+class KVILIB_API KviRegisteredMask
+{
+private:
+ KviRegisteredUser * m_pUser; // pointer , not owned!
+ KviIrcMask * m_pMask; // pointer , not owned!
+ int m_iMaskNonWildChars;
+public:
+ KviRegisteredMask(KviRegisteredUser * u,KviIrcMask * m);
+ ~KviRegisteredMask(){};
+public:
+ int nonWildChars(){ return m_iMaskNonWildChars; };
+ KviRegisteredUser * user(){ return m_pUser; };
+ KviIrcMask * mask(){ return m_pMask; };
+};
+
+typedef KviPointerList<KviRegisteredMask> KviRegisteredMaskList;
+
+//=================================================================================================
+//
+// KviRegisteredUsersDb
+//
+// Manages a set of KviRegisteredUser instances stored in the m_pUserDict dictionary
+// The users are identified by masks stored in m_pMaskDict and m_pWildMaskList
+// m_pMaskDict contains lists of non wild-nick KviRegisteredMask that point to users
+// m_pWildMaskList is a list of wild-nick KviRegisteredMask that point to users
+//
+
+class KVILIB_API KviRegisteredUserDataBase : public QObject
+{
+ Q_OBJECT
+public:
+ KviRegisteredUserDataBase();
+ ~KviRegisteredUserDataBase();
+private:
+ KviPointerHashTable<QString,KviRegisteredUser> * m_pUserDict; // unique namespace, owns the objects, does not copy keys
+ KviPointerHashTable<QString,KviRegisteredMaskList> * m_pMaskDict; // owns the objects, copies the keys
+ KviRegisteredMaskList * m_pWildMaskList; // owns the objects
+ KviPointerHashTable<QString,KviRegisteredUserGroup>* m_pGroupDict;
+public:
+ void copyFrom(KviRegisteredUserDataBase * db);
+ KviRegisteredUser * addUser(const QString &name); // returns 0 if already there
+ KviRegisteredUser * getUser(const QString &name); // returns existing or adds
+ bool removeUser(const QString &name);
+ bool removeGroup(const QString &name);
+ KviRegisteredUser * findUserByName(const QString &name){ return m_pUserDict->find(name); };
+ // mask must be allocated on the heap and the ownership is transferred!
+ // returns non zero if there is already an user with this mask (returns the pointer to it!)
+ KviRegisteredUser * addMask(KviRegisteredUser * u,KviIrcMask * mask);
+ bool removeMaskByPointer(KviIrcMask * mask);
+ bool removeMask(const KviIrcMask &mask);
+ KviRegisteredUser * findMatchingUser(const QString &nick,const QString &user,const QString &host);
+ KviRegisteredUser * findUserWithMask(const KviIrcMask &mask);
+ KviRegisteredMask * findExactMask(const KviIrcMask &mask);
+ KviRegisteredMask * findMatchingMask(const QString &nick,const QString &user,const QString &host);
+ //Only used in few places (actually one) of the code, but lot of times;perfect for inlining...
+ //bool isIgnoredUser(const char * nick,const char * user,const char * host);
+ void load(const QString &filename);
+ void save(const QString &filename);
+
+ KviPointerHashTable<QString,KviRegisteredUser> * userDict(){ return m_pUserDict; };
+ KviPointerHashTable<QString,KviRegisteredUserGroup>* groupDict() { return m_pGroupDict; };
+
+ KviRegisteredUserGroup* addGroup(const QString &name);
+signals:
+ void userRemoved(const QString&);
+ void userChanged(const QString&);
+ void userAdded (const QString&);
+ void databaseCleared();
+};
+
+
+#endif //_KVI_REGUSERSDB_H_
diff --git a/src/kvilib/ext/kvi_sharedfiles.cpp b/src/kvilib/ext/kvi_sharedfiles.cpp
new file mode 100644
index 00000000..65ce0d69
--- /dev/null
+++ b/src/kvilib/ext/kvi_sharedfiles.cpp
@@ -0,0 +1,391 @@
+//=============================================================================
+//
+// File : kvi_filetrader.cpp
+// Creation date : Wed Aug 27 2000 10:33:11 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+
+
+#include "kvi_sharedfiles.h"
+
+#include "kvi_config.h"
+#include "kvi_fileutils.h"
+
+#include <qfileinfo.h>
+
+// TODO: Match servers that the file requests come from
+// TODO: Max number of downloads ?
+
+// FIXME: MD5SUM ?
+
+/*
+ @doc: shared_files
+ @title:
+ Sharing files with KVIrc
+ @type:
+ generic
+ @short:
+ Automatically sharing your files with other IRC users
+ @keyterms:
+ file sharing
+ @body:
+ [big]What is this ?[/big]
+ The "file offers" are a simple way to share your files with other IRC users.[br]
+ Basically , you setup an offer by selecting a local file, choosing a "visible name" for it.
+ Remote users will be able to request you the file and download it automatically by
+ issuing a simple DCC GET request.[br]
+ [big]Details[/big]
+ Each offer refers to an existing file on one of your locally mounted file systems.
+ The offer is given a visible name that the remote users will effectively request.
+ To share the file /usr/arch/mp3/SonataArctica_SingInSilence_Live.mp3 you will add a file offer
+ with /usr/arch/mp3/SonataArctica_SingInSilence_Live.mp3 as real file path , something like
+ "SonataArctica_SingInSilence.mp3". A remote user will then request you a DCC GET SonataArctica_SingInSilence.mp3
+ and KVIrc will automatically send the file.[br]
+ Each file offer has an "user mask" that the requesting remote users must match to
+ obtain the file: *!*@* matches any user, Pragma!*@* matches any user with nickname pragma,
+ *!*@*.omnikron.net matches any user coming from the omnikron.net domain.[br]
+ Each offer can have an expire time: the offer will be automatically removed after
+ a defined number of seconds. An expire time of '0' seconds means that the offer should never expire.[br]
+ If you have two file offers with the same name and different file, the remote user can
+ use an additional "size" parameter in the DCC GET request.[br]
+ [big]Security issues[/big]
+ This is a nice but unsecure method of sharing files.[br]
+ The user mask is a good protection but you have to use it properly!.[br]
+ Setting the user mask to Nick!*@* can be easily exploited (just by making an user disconnect
+ in one of the well known ways and then by using his nickname).[br]
+ On the other side, the remote end must know exactly the visible name of the offer to request
+ and noone but you will tell him that name.[br]
+ In sum:[br]
+ Don't share any really important files: this *might* be like putting it on your webpage :D[br]
+ Please don't send complains if someone stoles your /etc/passwd : it is because you have permitted that.[br]
+*/
+
+KviSharedFile::KviSharedFile(const QString &szName,const QString &szAbsPath,const QString &szUserMask,time_t expireTime,unsigned int uFileSize)
+{
+ m_szName = szName;
+ m_szAbsFilePath = szAbsPath;
+ m_szUserMask = szUserMask;
+ m_expireTime = expireTime;
+ m_uFileSize = uFileSize;
+#ifdef COMPILE_USE_QT4
+ // QT4ROX: Because they have finally moved the functionality of QString::contains() to QString::count(), and QString::contains() now does the right job
+ m_uWildCount = m_szUserMask.count('*');
+#else
+ m_uWildCount = m_szUserMask.contains('*');
+#endif
+ m_uNonWildCount = m_szUserMask.length() - m_uWildCount;
+}
+
+KviSharedFile::~KviSharedFile()
+{
+}
+
+
+KviSharedFilesManager::KviSharedFilesManager()
+: QObject()
+{
+ m_pSharedListDict = new KviPointerHashTable<QString,KviSharedFileList>();
+ m_pSharedListDict->setAutoDelete(true);
+ m_pCleanupTimer = new QTimer();
+ connect(m_pCleanupTimer,SIGNAL(timeout()),this,SLOT(cleanup()));
+}
+
+KviSharedFilesManager::~KviSharedFilesManager()
+{
+ if(m_pCleanupTimer->isActive())m_pCleanupTimer->stop();
+ delete m_pCleanupTimer;
+ delete m_pSharedListDict;
+}
+
+void KviSharedFilesManager::cleanup()
+{
+ KviPointerHashTableIterator<QString,KviSharedFileList> it(*m_pSharedListDict);
+ time_t curTime = time(0);
+
+ bool bOtherStuffToCleanup = false;
+ //bool bChanged = false;
+
+ KviPointerList<QString> lDying;
+ lDying.setAutoDelete(true);
+
+ while(KviSharedFileList * l = it.current())
+ {
+ KviPointerList<KviSharedFile> tmp;
+ tmp.setAutoDelete(false);
+ for(KviSharedFile * o = l->first();o;o = l->next())
+ {
+ if(o->expireTime() > 0)
+ {
+ if(((int)o->expireTime()) <= ((int)curTime))
+ {
+ tmp.append(o);
+ //bChanged = true;
+ } else {
+ bOtherStuffToCleanup = true;
+ }
+ }
+ }
+ for(KviSharedFile * fo = tmp.first();fo;fo = tmp.next())
+ {
+ l->removeRef(fo);
+ emit sharedFileRemoved(fo);
+ }
+ if(l->count() == 0)
+ lDying.append(new QString(it.currentKey()));
+
+ ++it;
+ }
+
+ for(QString * pDyingKey = lDying.first();pDyingKey;pDyingKey = lDying.next())
+ m_pSharedListDict->remove(*pDyingKey);
+
+ if(!bOtherStuffToCleanup)m_pCleanupTimer->stop();
+ //if(bChanged)emit sharedFilesChanged();
+}
+
+void KviSharedFilesManager::clear()
+{
+ m_pSharedListDict->clear();
+ emit sharedFilesChanged();
+}
+
+void KviSharedFilesManager::doInsert(KviSharedFileList * l, KviSharedFile * o)
+{
+ int index = 0;
+ for(KviSharedFile * fo =l->first();fo;fo = l->next())
+ {
+ if(o->wildcardCount() > 0)
+ {
+ // the new mask has wildcards... if the current one has none, skip it
+ if(fo->wildcardCount() > 0)
+ {
+ // the one in the list has wildcards too...
+ // the ones with more non-wild chars go first...
+ if(fo->nonWildcardCount() < o->nonWildcardCount())
+ {
+ // ok...the new one has more non-wildcards , insert
+ l->insert(index,o);
+ return;
+ } else {
+ if(o->nonWildcardCount() == fo->nonWildcardCount())
+ {
+ // the same number of non-wildcards
+ // let the number of wildcards decide (it will be eventually equal)
+ if(o->wildcardCount() < fo->wildcardCount())
+ {
+ // the new one has less wildcards... goes first
+ l->insert(index,o);
+ return;
+ } // else the same number of wildcards and non-wildcards...skip
+ } // else the existing one has more non-wildcards...skip
+ }
+ } // else the current has no wildcards...skip
+ } else {
+ // the new mask has no wildcards....
+ if(fo->wildcardCount() > 0)
+ {
+ // current one has wildcards...insert
+ l->insert(index,o);
+ return;
+ }
+ // the current one has no wildcards...
+ // the longer masks go first....
+ if(fo->maskLength() < o->maskLength())
+ {
+ // the current one is shorter than the new one...insert
+ l->insert(index,o);
+ return;
+ } // else current one is longer...skip
+ }
+ index++;
+ }
+ l->append(o);
+}
+
+void KviSharedFilesManager::addSharedFile(KviSharedFile * f)
+{
+ // First find the list
+ KviSharedFileList * l = m_pSharedListDict->find(f->name());
+ if(!l)
+ {
+ l = new KviSharedFileList;
+ l->setAutoDelete(true);
+ m_pSharedListDict->replace(f->name(),l);
+ }
+
+ doInsert(l,f);
+
+ if(((int)f->expireTime()) > 0)
+ {
+ if(!m_pCleanupTimer->isActive())m_pCleanupTimer->start(60000);
+ }
+
+ emit sharedFileAdded(f);
+}
+
+KviSharedFile * KviSharedFilesManager::addSharedFile(const QString &szName,const QString &szAbsPath,const QString &szMask,int timeoutInSecs)
+{
+ QFileInfo inf(szAbsPath);
+ if(inf.exists() && inf.isFile() && inf.isReadable() && (inf.size() > 0))
+ {
+ // First find the list
+ KviSharedFileList * l = m_pSharedListDict->find(szName);
+ if(!l)
+ {
+ l = new KviSharedFileList;
+ l->setAutoDelete(true);
+ m_pSharedListDict->replace(szName,l);
+ }
+
+ // Now insert
+ KviSharedFile * o = new KviSharedFile(szName,szAbsPath,szMask,timeoutInSecs > 0 ? (((int)(time(0))) + timeoutInSecs) : 0,inf.size());
+
+ doInsert(l,o);
+
+ if(((int)o->expireTime()) > 0)
+ {
+ if(!m_pCleanupTimer->isActive())m_pCleanupTimer->start(60000);
+ }
+
+ emit sharedFileAdded(o);
+
+ return o;
+ } else {
+ debug("File %s unreadable: can't add offer",KviQString::toUtf8(szAbsPath).data());
+ return 0;
+ }
+}
+
+KviSharedFile * KviSharedFilesManager::lookupSharedFile(const QString &szName,KviIrcMask * mask,unsigned int uFileSize)
+{
+ KviSharedFileList * l = m_pSharedListDict->find(szName);
+ if(!l)return 0;
+
+ for(KviSharedFile * o = l->first();o;o = l->next())
+ {
+ bool bMatch;
+ if(mask)
+ {
+ KviIrcMask umask(o->userMask());
+ bMatch = mask->matchedBy(umask);
+ } else bMatch = KviQString::equalCS(o->userMask(),"*!*@*");
+ if(bMatch)
+ {
+ if(uFileSize > 0)
+ {
+ if(uFileSize == o->fileSize())return o;
+ } else return o;
+ }
+ }
+
+ return 0;
+}
+bool KviSharedFilesManager::removeSharedFile(const QString &szName,const QString &szMask,unsigned int uFileSize)
+{
+ KviSharedFileList * l = m_pSharedListDict->find(szName);
+ if(!l)return false;
+ for(KviSharedFile * o = l->first();o;o = l->next())
+ {
+ if(KviQString::equalCI(szMask,o->userMask()))
+ {
+ bool bMatch = uFileSize > 0 ? uFileSize == o->fileSize() : true;
+ if(bMatch)
+ {
+ QString save = szName; // <-- szName MAY Be a pointer to o->name()
+ l->removeRef(o);
+ if(l->count() == 0)m_pSharedListDict->remove(save);
+ emit sharedFileRemoved(o);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool KviSharedFilesManager::removeSharedFile(const QString &szName,KviSharedFile * off)
+{
+ KviSharedFileList * l = m_pSharedListDict->find(szName);
+ if(!l)return false;
+ for(KviSharedFile * o = l->first();o;o = l->next())
+ {
+ if(off == o)
+ {
+ QString save = szName; // <-- szName MAY Be a pointer to o->name()
+ l->removeRef(o);
+ if(l->count() == 0)m_pSharedListDict->remove(save);
+ emit sharedFileRemoved(off);
+ return true;
+ }
+ }
+ return false;
+}
+
+
+void KviSharedFilesManager::load(const QString &filename)
+{
+ KviConfig cfg(filename,KviConfig::Read);
+ //cfg.clear();
+ cfg.setGroup("PermanentFileOffers");
+ int num = cfg.readIntEntry("NEntries",0);
+ for(int idx=0;idx<num;idx++)
+ {
+ QString tmp;
+ KviQString::sprintf(tmp,"%dFName",idx);
+ QString szName = cfg.readQStringEntry(tmp,"");
+ KviQString::sprintf(tmp,"%dFilePath",idx);
+ QString szPath = cfg.readQStringEntry(tmp,"");
+ KviQString::sprintf(tmp,"%dUserMask",idx);
+ QString szMask = cfg.readQStringEntry(tmp,"");
+ if(!szMask.isEmpty() && !szPath.isEmpty() && !szName.isEmpty())
+ addSharedFile(szName,szPath,szMask,0);
+ }
+}
+
+void KviSharedFilesManager::save(const QString &filename)
+{
+ KviConfig cfg(filename,KviConfig::Write);
+ cfg.clear();
+ cfg.setGroup("PermanentFileOffers");
+
+ KviPointerHashTableIterator<QString,KviSharedFileList> it(*m_pSharedListDict);
+ int idx = 0;
+ while(KviSharedFileList * l = it.current())
+ {
+ for(KviSharedFile * o = l->first();o;o = l->next())
+ {
+ if(((int)(o->expireTime())) == 0)
+ {
+ QString tmp;
+ KviQString::sprintf(tmp,"%dFName",idx);
+ cfg.writeEntry(tmp,it.currentKey());
+ KviQString::sprintf(tmp,"%dFilePath",idx);
+ cfg.writeEntry(tmp,o->absFilePath());
+ KviQString::sprintf(tmp,"%dUserMask",idx);
+ cfg.writeEntry(tmp,o->userMask());
+ ++idx;
+ }
+ }
+ ++it;
+ }
+ cfg.writeEntry("NEntries",idx);
+}
+
diff --git a/src/kvilib/ext/kvi_sharedfiles.h b/src/kvilib/ext/kvi_sharedfiles.h
new file mode 100644
index 00000000..3a6d2239
--- /dev/null
+++ b/src/kvilib/ext/kvi_sharedfiles.h
@@ -0,0 +1,133 @@
+#ifndef _KVI_FILETRADER_H_
+#define _KVI_FILETRADER_H_
+//=============================================================================
+//
+// File : kvi_filetrader.h
+// Creation date : Wed Aug 27 2000 10:28:51 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_heapobject.h"
+#include "kvi_string.h"
+#include "kvi_ircmask.h"
+#include "kvi_pointerlist.h"
+#include "kvi_qstring.h"
+
+#include "kvi_pointerhashtable.h"
+
+#include <time.h>
+#include <qtimer.h>
+
+
+class KVILIB_API KviSharedFile : public KviHeapObject
+{
+public:
+ KviSharedFile(const QString &szName,const QString &szAbsPath,const QString &szUserMask,time_t expireTime,unsigned int uFileSize);
+ ~KviSharedFile();
+private:
+ QString m_szName;
+ QString m_szAbsFilePath;
+ time_t m_expireTime;
+ QString m_szUserMask;
+ unsigned int m_uFileSize;
+ unsigned int m_uWildCount;
+ unsigned int m_uNonWildCount;
+public:
+ const QString &name(){ return m_szName; };
+
+ const QString &absFilePath(){ return m_szAbsFilePath; };
+
+ const QString &userMask(){ return m_szUserMask; };
+
+ time_t expireTime(){ return m_expireTime; };
+ bool expires(){ return (m_expireTime != 0); };
+
+ unsigned int fileSize(){ return m_uFileSize; };
+
+ unsigned int wildcardCount(){ return m_uWildCount; };
+ unsigned int nonWildcardCount(){ return m_uNonWildCount; };
+ int maskLength(){ return m_szUserMask.length(); };
+};
+
+
+typedef KviPointerList<KviSharedFile> KviSharedFileList;
+
+
+class KVILIB_API KviSharedFilesManager : public QObject
+{
+ Q_OBJECT
+public:
+ KviSharedFilesManager();
+ ~KviSharedFilesManager();
+private:
+ QTimer * m_pCleanupTimer;
+ KviPointerHashTable<QString,KviSharedFileList> * m_pSharedListDict;
+public:
+ void addSharedFile(KviSharedFile * f);
+ KviSharedFile * addSharedFile(const QString &szName,const QString &szAbsPath,const QString &szMask,int timeoutInSecs);
+ KviSharedFile * lookupSharedFile(const QString &szName,KviIrcMask * mask,unsigned int uFileSize = 0);
+ bool removeSharedFile(const QString &szName,const QString &szMask,unsigned int uFileSize);
+ bool removeSharedFile(const QString &szName,KviSharedFile * off);
+ void load(const QString &filename);
+ void save(const QString &filename);
+ void clear();
+ KviPointerHashTable<QString,KviSharedFileList> * sharedFileListDict(){ return m_pSharedListDict; };
+private:
+ void doInsert(KviSharedFileList * l, KviSharedFile * o);
+private slots:
+ void cleanup();
+signals:
+ void sharedFilesChanged(); // emitted when the list is cleared at once
+ void sharedFileAdded(KviSharedFile * f);
+ void sharedFileRemoved(KviSharedFile * f);
+};
+
+
+/*
+class KviSharedFile
+{
+ KviSharedFile();
+ KviSharedFile(const KviStr &filePath,const KviStr &userMask);
+ ~KviSharedFile();
+protected:
+ KviStr m_szFilePath;
+ KviStr m_szVisibleName;
+ KviStr m_szMd5Sum;
+ KviStr m_szUserMask;
+ unsigned short int m_uWildCount;
+ unsigned short int m_uNonWildCount;
+
+ unsigned int m_uFileSize;
+ time_t m_tExpireTime;
+public:
+ void setFilePath(const KviStr &filePath);
+ void setUserMask(const KviStr &userMask);
+ void setVisibleName(const KviStr &visibleName);
+ void setMd5Sum(const KviStr &md5Sum);
+ void setFileSize(unsigned int uFileSize);
+ void setExpireTime(time_t expireTime);
+ void doNotExpire(){ setExpireTime((time_t)0); };
+
+ void computeMd5Sum();
+};
+*/
+
+#endif //_KVI_FILETRADER_H_
diff --git a/src/kvilib/ext/kvi_stringconversion.cpp b/src/kvilib/ext/kvi_stringconversion.cpp
new file mode 100644
index 00000000..3d0255cc
--- /dev/null
+++ b/src/kvilib/ext/kvi_stringconversion.cpp
@@ -0,0 +1,277 @@
+//=============================================================================
+//
+// File : kvi_stringconversion.cpp
+// Creation date : Thu Oct 20 2000 14:12:21 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+
+
+#define _KVI_STRINGCONVERSION_CPP_
+#include "kvi_stringconversion.h"
+
+#include "kvi_qstring.h"
+#include <stdio.h>
+
+QString g_szGlobalDir;
+QString g_szLocalDir;
+
+namespace KviStringConversion
+{
+
+ void init(const QString& szGlobalDir,const QString& szLocalDir)
+ {
+ g_szGlobalDir=szGlobalDir;
+ g_szLocalDir=szLocalDir;
+ }
+
+ void encodePath(QString& buffer)
+ {
+ if(!buffer.isEmpty())
+ {
+ if(!g_szLocalDir.isEmpty())
+ {
+ if(KviQString::find(buffer,g_szLocalDir)==0)
+ {
+ buffer.remove(0,g_szLocalDir.length());
+ buffer.prepend("local://");
+ }
+ }
+ if(!g_szGlobalDir.isEmpty())
+ {
+ if(KviQString::find(buffer,g_szGlobalDir)==0)
+ {
+ buffer.remove(0,g_szGlobalDir.length());
+ buffer.prepend("global://");
+ }
+ }
+ }
+ }
+
+ void decodePath(QString& buffer)
+ {
+ if(!buffer.isEmpty())
+ {
+ if(!g_szLocalDir.isEmpty())
+ {
+ if(KviQString::find(buffer,"local://")==0)
+ {
+ buffer.remove(0,8);
+ buffer.prepend(g_szLocalDir);
+ }
+ }
+ if(!g_szGlobalDir.isEmpty())
+ {
+ if(KviQString::find(buffer,"global://")==0)
+ {
+ buffer.remove(0,9);
+ buffer.prepend(g_szGlobalDir);
+ }
+ }
+ }
+ }
+
+ void encodePath(QStringList& buffer)
+ {
+ for ( QStringList::Iterator it = buffer.begin(); it != buffer.end(); ++it )
+ {
+ encodePath(*it);
+ }
+ }
+
+ void decodePath(QStringList& buffer)
+ {
+ for ( QStringList::Iterator it = buffer.begin(); it != buffer.end(); ++it )
+ {
+ decodePath(*it);
+ }
+ }
+
+ void toString(const bool bValue,QString &buffer)
+ {
+ buffer = bValue ? '1' : '0';
+ }
+
+ bool fromString(const QString & szValue,bool &buffer)
+ {
+ if(szValue.isEmpty())buffer = false;
+ else buffer = !((KviQString::equalCS(szValue,"0")) || (KviQString::equalCI(szValue,"false")));
+ return true;
+ }
+
+ void toString(const int iValue,QString &buffer)
+ {
+ buffer.setNum(iValue);
+ }
+
+ bool fromString(const QString &szValue,int &buffer)
+ {
+ bool bOk;
+ buffer = szValue.toInt(&bOk);
+ return bOk;
+ }
+
+ void toString(const unsigned int uValue,QString &buffer)
+ {
+ buffer.setNum(uValue);
+ }
+
+ bool fromString(const QString & szValue,unsigned int &buffer)
+ {
+ bool bOk;
+ buffer= szValue.toUInt(&bOk);
+ return bOk;
+ }
+
+ void toString(const QRect &rValue,QString &buffer)
+ {
+ buffer.sprintf("%d,%d,%d,%d",rValue.x(),rValue.y(),rValue.width(),rValue.height());
+ }
+
+ bool fromString(const QString & szValue,QRect &buffer)
+ {
+ KviQCString tmp = KviQString::toUtf8(szValue);
+ const char * c = tmp.data();
+ if(!c)return false;
+ int l,t,w,h;
+ if(sscanf(c,"%d,%d,%d,%d",&l,&t,&w,&h) != 4)return false;
+ buffer.setRect(l,t,w,h);
+ return true;
+ }
+
+ void toString(const QString &szValue,QString &buffer)
+ {
+ buffer = szValue;
+ }
+
+ bool fromString(const QString & szValue,QString &buffer)
+ {
+ buffer = szValue;
+ return true;
+ }
+
+ void toString(const KviPixmap &pValue,QString &buffer)
+ {
+ buffer=pValue.path();
+ encodePath(buffer);
+ }
+
+ bool fromString(const QString & szValue,KviPixmap &buffer)
+ {
+ QString szPath(szValue);
+ decodePath(szPath);
+ if(szPath.isEmpty()) {
+ buffer.setNull();
+ return true;
+ } else {
+ return buffer.load(szPath);
+ }
+ }
+
+ void toString(const KviMsgType &mValue,QString &buffer)
+ {
+ buffer.sprintf("%d,%u,%u,%d,%d",mValue.m_iPixId,mValue.m_cForeColor,mValue.m_cBackColor,mValue.m_bLogEnabled,mValue.m_iLevel);
+ }
+
+ bool fromString(const QString & szValue,KviMsgType &buffer)
+ {
+ int iId,iLog,iLevel;
+ unsigned int uFore,uBack;
+ KviQCString tmp = KviQString::toUtf8(szValue);
+ char * cx = tmp.data();
+ if(!cx)return false;
+ if(sscanf(cx,"%d,%u,%u,%d,%d",&iId,&uFore,&uBack,&iLog,&iLevel) != 5)return false;
+ buffer = KviMsgType(buffer.m_szType,iId,uFore,uBack,iLog,iLevel);
+ return true;
+ }
+
+ void toString(const QColor &cValue,QString &buffer)
+ {
+ buffer = cValue.name();
+ }
+
+ bool fromString(const QString & szValue,QColor &buffer)
+ {
+ buffer.setNamedColor(szValue); return true;
+ }
+
+ void toString(const QFont &fValue,QString &buffer)
+ {
+ QString family(fValue.family());
+ buffer.sprintf("%s,%d,%d,%d",KviQString::toUtf8(family).data(),fValue.pointSize(),fValue.styleHint(),fValue.weight());
+ QString options;
+ if(fValue.bold())options.append('b');
+ if(fValue.italic())options.append('i');
+ if(fValue.underline())options.append('u');
+ if(fValue.strikeOut())options.append('s');
+ if(fValue.fixedPitch())options.append('f');
+
+ if(!options.isEmpty())
+ {
+ buffer.append(',');
+ buffer.append(options);
+ }
+ }
+
+ bool fromString(const QString & szValue,QFont &buffer)
+ {
+ KviStr str = szValue;
+ KviStr family,pointSize,styleHint,weight,options;
+ str.getToken(family,',');
+ str.getToken(pointSize,',');
+ str.getToken(styleHint,',');
+ str.getToken(weight,',');
+ if(!family.isEmpty())buffer.setFamily(family.ptr());
+ int i;
+ bool bOk;
+ i = pointSize.toInt(&bOk);
+ if(bOk && (i > 0))buffer.setPointSize(i);
+ i = styleHint.toInt(&bOk);
+ if(bOk && (i >= 0))buffer.setStyleHint((QFont::StyleHint)i);
+ i = weight.toInt(&bOk);
+ if(bOk && (i >= 0))buffer.setWeight(i);
+ if(!str.isEmpty())
+ {
+ buffer.setBold(str.contains("b"));
+ buffer.setItalic(str.contains("i"));
+ buffer.setUnderline(str.contains("u"));
+ buffer.setStrikeOut(str.contains("s"));
+ buffer.setFixedPitch(str.contains("f"));
+ }
+ return true;
+ }
+
+ void toString(const QStringList &sValue,QString &buffer)
+ {
+ buffer = sValue.join(",");
+ }
+
+ bool fromString(const QString & szValue,QStringList &buffer)
+ {
+#ifdef COMPILE_USE_QT4
+ buffer = szValue.split(",");
+#else
+ buffer = QStringList::split(",",szValue);
+#endif
+ return true;
+ }
+
+}
diff --git a/src/kvilib/ext/kvi_stringconversion.h b/src/kvilib/ext/kvi_stringconversion.h
new file mode 100644
index 00000000..78f8d417
--- /dev/null
+++ b/src/kvilib/ext/kvi_stringconversion.h
@@ -0,0 +1,91 @@
+#ifndef _KVI_STRINGCONVERSION_H_
+#define _KVI_STRINGCONVERSION_H_
+
+//=============================================================================
+//
+// File : kvi_stringconversion.h
+// Creation date : Thu Oct 20 2000 13:27:12 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_string.h"
+#include "kvi_pixmap.h"
+#include "kvi_msgtype.h"
+
+#include <qrect.h>
+#include <qcolor.h>
+#include <qfont.h>
+#include <qstringlist.h>
+#include <qstring.h>
+
+
+namespace KviStringConversion
+{
+ extern KVILIB_API void init(const QString& szGlobalDir,const QString& szLocalDir);
+
+ extern KVILIB_API void encodePath(QString& buffer);
+ extern KVILIB_API void decodePath(QString& buffer);
+
+ extern KVILIB_API void encodePath(QStringList& buffer);
+ extern KVILIB_API void decodePath(QStringList& buffer);
+
+ // bool <->
+ extern KVILIB_API void toString(const bool bValue,QString &buffer);
+ extern KVILIB_API bool fromString(const QString &szValue,bool &buffer);
+
+ // int <-> QString
+ extern KVILIB_API void toString(const int iValue,QString &buffer);
+ extern KVILIB_API bool fromString(const QString &szValue,int &buffer);
+
+ // uint <-> QString
+ extern KVILIB_API void toString(const unsigned int uValue,QString &buffer);
+ extern KVILIB_API bool fromString(const QString &szValue,unsigned int &buffer);
+
+ // QRect <-> QString
+ extern KVILIB_API void toString(const QRect &rValue,QString &buffer);
+ extern KVILIB_API bool fromString(const QString &szValue,QRect &buffer);
+
+ // QString <-> QString (Null conversion)
+ extern KVILIB_API void toString(const QString &szValue,QString &buffer);
+ extern KVILIB_API bool fromString(const QString &szValue,QString &buffer);
+
+ // KviPixmap <-> QString
+ extern KVILIB_API void toString(const KviPixmap &pValue,QString &buffer);
+ extern KVILIB_API bool fromString(const QString &szValue,KviPixmap &buffer);
+
+ // QFont <-> QString
+ extern KVILIB_API void toString(const QFont &fValue,QString &buffer);
+ extern KVILIB_API bool fromString(const QString &szValue,QFont &buffer);
+
+ // KviMsgType <-> QString
+ extern KVILIB_API void toString(const KviMsgType &mValue,QString &buffer);
+ extern KVILIB_API bool fromString(const QString &szValue,KviMsgType &buffer);
+
+ // QColor <-> QString
+ extern KVILIB_API void toString(const QColor &cValue,QString &buffer);
+ extern KVILIB_API bool fromString(const QString &szValue,QColor &buffer);
+
+ // QStringList <-> QString
+ extern KVILIB_API void toString(const QStringList &sValue,QString &buffer);
+ extern KVILIB_API bool fromString(const QString &szValue,QStringList &buffer);
+};
+
+#endif //!_KVI_STRINGCONVERSION_H_
diff --git a/src/kvilib/ext/kvi_xlib.h b/src/kvilib/ext/kvi_xlib.h
new file mode 100644
index 00000000..ef6ca177
--- /dev/null
+++ b/src/kvilib/ext/kvi_xlib.h
@@ -0,0 +1,45 @@
+#ifndef _KVI_XLIB_H_
+#define _KVI_XLIB_H_
+//=============================================================================
+//
+// File : kvi_xlib.h
+// Creation date : Tue Aug 14 18:17:21 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#ifndef COMPILE_NO_X
+
+ #ifdef Bool
+ // Someone has defined Bool ?
+ #undef Bool
+ #endif
+
+ #include <X11/Xlib.h>
+
+ // Too bad that X11/Xlib.h defines Bool, Error and Success... this basically
+ // SUX since we can't use them anywhere in the source!
+ // this breaks, enums in Qt, enums in KVIrc and other stuff all around...
+ // Shame on you Xlib.h author :D
+
+#endif // !COMPILE_NO_X
+
+#endif //_KVI_XLIB_H_
diff --git a/src/kvilib/ext/moc_kvi_crypt.cpp b/src/kvilib/ext/moc_kvi_crypt.cpp
new file mode 100644
index 00000000..89c29d46
--- /dev/null
+++ b/src/kvilib/ext/moc_kvi_crypt.cpp
@@ -0,0 +1,94 @@
+/****************************************************************************
+** KviCryptEngine meta object code from reading C++ file 'kvi_crypt.h'
+**
+** Created: Sun Mar 23 20:56:10 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_crypt.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviCryptEngine::className() const
+{
+ return "KviCryptEngine";
+}
+
+QMetaObject *KviCryptEngine::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviCryptEngine( "KviCryptEngine", &KviCryptEngine::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviCryptEngine::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviCryptEngine", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviCryptEngine::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviCryptEngine", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviCryptEngine::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = QObject::staticMetaObject();
+ metaObj = QMetaObject::new_metaobject(
+ "KviCryptEngine", parentObject,
+ 0, 0,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviCryptEngine.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviCryptEngine::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviCryptEngine" ) )
+ return this;
+ if ( !qstrcmp( clname, "KviHeapObject" ) )
+ return (KviHeapObject*)this;
+ return QObject::qt_cast( clname );
+}
+
+bool KviCryptEngine::qt_invoke( int _id, QUObject* _o )
+{
+ return QObject::qt_invoke(_id,_o);
+}
+
+bool KviCryptEngine::qt_emit( int _id, QUObject* _o )
+{
+ return QObject::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviCryptEngine::qt_property( int id, int f, QVariant* v)
+{
+ return QObject::qt_property( id, f, v);
+}
+
+bool KviCryptEngine::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvilib/ext/moc_kvi_garbage.cpp b/src/kvilib/ext/moc_kvi_garbage.cpp
new file mode 100644
index 00000000..0c1a98ef
--- /dev/null
+++ b/src/kvilib/ext/moc_kvi_garbage.cpp
@@ -0,0 +1,104 @@
+/****************************************************************************
+** KviGarbageCollector meta object code from reading C++ file 'kvi_garbage.h'
+**
+** Created: Sun Mar 23 20:56:12 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_garbage.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviGarbageCollector::className() const
+{
+ return "KviGarbageCollector";
+}
+
+QMetaObject *KviGarbageCollector::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviGarbageCollector( "KviGarbageCollector", &KviGarbageCollector::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviGarbageCollector::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviGarbageCollector", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviGarbageCollector::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviGarbageCollector", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviGarbageCollector::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = QObject::staticMetaObject();
+ static const QUMethod slot_0 = {"cleanup", 0, 0 };
+ static const QUMethod slot_1 = {"garbageSuicide", 0, 0 };
+ static const QMetaData slot_tbl[] = {
+ { "cleanup()", &slot_0, QMetaData::Protected },
+ { "garbageSuicide()", &slot_1, QMetaData::Protected }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviGarbageCollector", parentObject,
+ slot_tbl, 2,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviGarbageCollector.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviGarbageCollector::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviGarbageCollector" ) )
+ return this;
+ return QObject::qt_cast( clname );
+}
+
+bool KviGarbageCollector::qt_invoke( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->slotOffset() ) {
+ case 0: cleanup(); break;
+ case 1: garbageSuicide(); break;
+ default:
+ return QObject::qt_invoke( _id, _o );
+ }
+ return TRUE;
+}
+
+bool KviGarbageCollector::qt_emit( int _id, QUObject* _o )
+{
+ return QObject::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviGarbageCollector::qt_property( int id, int f, QVariant* v)
+{
+ return QObject::qt_property( id, f, v);
+}
+
+bool KviGarbageCollector::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvilib/ext/moc_kvi_regusersdb.cpp b/src/kvilib/ext/moc_kvi_regusersdb.cpp
new file mode 100644
index 00000000..092add9f
--- /dev/null
+++ b/src/kvilib/ext/moc_kvi_regusersdb.cpp
@@ -0,0 +1,143 @@
+/****************************************************************************
+** KviRegisteredUserDataBase meta object code from reading C++ file 'kvi_regusersdb.h'
+**
+** Created: Sun Mar 23 20:56:14 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_regusersdb.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviRegisteredUserDataBase::className() const
+{
+ return "KviRegisteredUserDataBase";
+}
+
+QMetaObject *KviRegisteredUserDataBase::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviRegisteredUserDataBase( "KviRegisteredUserDataBase", &KviRegisteredUserDataBase::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviRegisteredUserDataBase::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviRegisteredUserDataBase", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviRegisteredUserDataBase::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviRegisteredUserDataBase", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviRegisteredUserDataBase::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = QObject::staticMetaObject();
+ static const QUParameter param_signal_0[] = {
+ { 0, &static_QUType_QString, 0, QUParameter::In }
+ };
+ static const QUMethod signal_0 = {"userRemoved", 1, param_signal_0 };
+ static const QUParameter param_signal_1[] = {
+ { 0, &static_QUType_QString, 0, QUParameter::In }
+ };
+ static const QUMethod signal_1 = {"userChanged", 1, param_signal_1 };
+ static const QUParameter param_signal_2[] = {
+ { 0, &static_QUType_QString, 0, QUParameter::In }
+ };
+ static const QUMethod signal_2 = {"userAdded", 1, param_signal_2 };
+ static const QUMethod signal_3 = {"databaseCleared", 0, 0 };
+ static const QMetaData signal_tbl[] = {
+ { "userRemoved(const QString&)", &signal_0, QMetaData::Public },
+ { "userChanged(const QString&)", &signal_1, QMetaData::Public },
+ { "userAdded(const QString&)", &signal_2, QMetaData::Public },
+ { "databaseCleared()", &signal_3, QMetaData::Public }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviRegisteredUserDataBase", parentObject,
+ 0, 0,
+ signal_tbl, 4,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviRegisteredUserDataBase.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviRegisteredUserDataBase::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviRegisteredUserDataBase" ) )
+ return this;
+ return QObject::qt_cast( clname );
+}
+
+// SIGNAL userRemoved
+void KviRegisteredUserDataBase::userRemoved( const QString& t0 )
+{
+ activate_signal( staticMetaObject()->signalOffset() + 0, t0 );
+}
+
+// SIGNAL userChanged
+void KviRegisteredUserDataBase::userChanged( const QString& t0 )
+{
+ activate_signal( staticMetaObject()->signalOffset() + 1, t0 );
+}
+
+// SIGNAL userAdded
+void KviRegisteredUserDataBase::userAdded( const QString& t0 )
+{
+ activate_signal( staticMetaObject()->signalOffset() + 2, t0 );
+}
+
+// SIGNAL databaseCleared
+void KviRegisteredUserDataBase::databaseCleared()
+{
+ activate_signal( staticMetaObject()->signalOffset() + 3 );
+}
+
+bool KviRegisteredUserDataBase::qt_invoke( int _id, QUObject* _o )
+{
+ return QObject::qt_invoke(_id,_o);
+}
+
+bool KviRegisteredUserDataBase::qt_emit( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->signalOffset() ) {
+ case 0: userRemoved((const QString&)static_QUType_QString.get(_o+1)); break;
+ case 1: userChanged((const QString&)static_QUType_QString.get(_o+1)); break;
+ case 2: userAdded((const QString&)static_QUType_QString.get(_o+1)); break;
+ case 3: databaseCleared(); break;
+ default:
+ return QObject::qt_emit(_id,_o);
+ }
+ return TRUE;
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviRegisteredUserDataBase::qt_property( int id, int f, QVariant* v)
+{
+ return QObject::qt_property( id, f, v);
+}
+
+bool KviRegisteredUserDataBase::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvilib/ext/moc_kvi_sharedfiles.cpp b/src/kvilib/ext/moc_kvi_sharedfiles.cpp
new file mode 100644
index 00000000..83ea82a4
--- /dev/null
+++ b/src/kvilib/ext/moc_kvi_sharedfiles.cpp
@@ -0,0 +1,157 @@
+/****************************************************************************
+** KviSharedFilesManager meta object code from reading C++ file 'kvi_sharedfiles.h'
+**
+** Created: Sun Mar 23 20:56:15 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_sharedfiles.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviSharedFilesManager::className() const
+{
+ return "KviSharedFilesManager";
+}
+
+QMetaObject *KviSharedFilesManager::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviSharedFilesManager( "KviSharedFilesManager", &KviSharedFilesManager::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviSharedFilesManager::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviSharedFilesManager", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviSharedFilesManager::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviSharedFilesManager", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviSharedFilesManager::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = QObject::staticMetaObject();
+ static const QUMethod slot_0 = {"cleanup", 0, 0 };
+ static const QMetaData slot_tbl[] = {
+ { "cleanup()", &slot_0, QMetaData::Private }
+ };
+ static const QUMethod signal_0 = {"sharedFilesChanged", 0, 0 };
+ static const QUParameter param_signal_1[] = {
+ { "f", &static_QUType_ptr, "KviSharedFile", QUParameter::In }
+ };
+ static const QUMethod signal_1 = {"sharedFileAdded", 1, param_signal_1 };
+ static const QUParameter param_signal_2[] = {
+ { "f", &static_QUType_ptr, "KviSharedFile", QUParameter::In }
+ };
+ static const QUMethod signal_2 = {"sharedFileRemoved", 1, param_signal_2 };
+ static const QMetaData signal_tbl[] = {
+ { "sharedFilesChanged()", &signal_0, QMetaData::Private },
+ { "sharedFileAdded(KviSharedFile*)", &signal_1, QMetaData::Private },
+ { "sharedFileRemoved(KviSharedFile*)", &signal_2, QMetaData::Private }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviSharedFilesManager", parentObject,
+ slot_tbl, 1,
+ signal_tbl, 3,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviSharedFilesManager.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviSharedFilesManager::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviSharedFilesManager" ) )
+ return this;
+ return QObject::qt_cast( clname );
+}
+
+// SIGNAL sharedFilesChanged
+void KviSharedFilesManager::sharedFilesChanged()
+{
+ activate_signal( staticMetaObject()->signalOffset() + 0 );
+}
+
+#include <qobjectdefs.h>
+#include <qsignalslotimp.h>
+
+// SIGNAL sharedFileAdded
+void KviSharedFilesManager::sharedFileAdded( KviSharedFile* t0 )
+{
+ if ( signalsBlocked() )
+ return;
+ QConnectionList *clist = receivers( staticMetaObject()->signalOffset() + 1 );
+ if ( !clist )
+ return;
+ QUObject o[2];
+ static_QUType_ptr.set(o+1,t0);
+ activate_signal( clist, o );
+}
+
+// SIGNAL sharedFileRemoved
+void KviSharedFilesManager::sharedFileRemoved( KviSharedFile* t0 )
+{
+ if ( signalsBlocked() )
+ return;
+ QConnectionList *clist = receivers( staticMetaObject()->signalOffset() + 2 );
+ if ( !clist )
+ return;
+ QUObject o[2];
+ static_QUType_ptr.set(o+1,t0);
+ activate_signal( clist, o );
+}
+
+bool KviSharedFilesManager::qt_invoke( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->slotOffset() ) {
+ case 0: cleanup(); break;
+ default:
+ return QObject::qt_invoke( _id, _o );
+ }
+ return TRUE;
+}
+
+bool KviSharedFilesManager::qt_emit( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->signalOffset() ) {
+ case 0: sharedFilesChanged(); break;
+ case 1: sharedFileAdded((KviSharedFile*)static_QUType_ptr.get(_o+1)); break;
+ case 2: sharedFileRemoved((KviSharedFile*)static_QUType_ptr.get(_o+1)); break;
+ default:
+ return QObject::qt_emit(_id,_o);
+ }
+ return TRUE;
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviSharedFilesManager::qt_property( int id, int f, QVariant* v)
+{
+ return QObject::qt_property( id, f, v);
+}
+
+bool KviSharedFilesManager::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvilib/file/Makefile.am b/src/kvilib/file/Makefile.am
new file mode 100644
index 00000000..c84487eb
--- /dev/null
+++ b/src/kvilib/file/Makefile.am
@@ -0,0 +1,5 @@
+###############################################################################
+# KVirc IRC client Makefile - 16.12.98 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+EXTRA_DIST = *.cpp *.h
diff --git a/src/kvilib/file/kvi_file.cpp b/src/kvilib/file/kvi_file.cpp
new file mode 100644
index 00000000..8ab1e739
--- /dev/null
+++ b/src/kvilib/file/kvi_file.cpp
@@ -0,0 +1,256 @@
+//=============================================================================
+//
+// File : kvi_file.cpp
+// Creation date : Mon Dec 17 2001 00:04:12 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+
+
+#include "kvi_file.h"
+#include "kvi_byteorder.h"
+
+
+KviFile::KviFile()
+: QFile()
+{
+}
+
+KviFile::KviFile(const QString &name)
+: QFile(name)
+{
+}
+
+KviFile::~KviFile()
+{
+}
+
+bool KviFile::openForReading()
+{
+#ifdef COMPILE_USE_QT4
+ return open(QFile::ReadOnly);
+#else
+ return open(IO_ReadOnly);
+#endif
+}
+
+bool KviFile::openForWriting(bool bAppend)
+{
+#ifdef COMPILE_USE_QT4
+ return open(QFile::WriteOnly | (bAppend ? QFile::Append : QFile::Truncate));
+#else
+ return open(IO_WriteOnly | (bAppend ? IO_Append : IO_Truncate));
+#endif
+}
+
+
+bool KviFile::save(const QByteArray &bData)
+{
+ if(!save((kvi_u32_t)(bData.size())))return false;
+ return (writeBlock(bData.data(),bData.size()) == ((int)(bData.size())));
+}
+
+bool KviFile::load(QByteArray &bData)
+{
+ kvi_u32_t iLen;
+ if(!load(iLen))return false;
+ bData.resize(iLen); // it is automatically null terminated in Qt 4.x... BLEAH :D
+ if(readBlock((char *)(bData.data()),iLen) != iLen)return false;
+ return true;
+}
+
+#ifndef COMPILE_USE_QT4
+
+bool KviFile::save(const KviQCString &szData)
+{
+ if(!save((kvi_u32_t)(szData.length())))return false;
+ return (writeBlock(szData.data(),szData.length()) == ((int)(szData.length())));
+}
+
+bool KviFile::load(KviQCString &szData)
+{
+ kvi_u32_t iLen;
+ if(!load(iLen))return false;
+ szData.resize(iLen + 1); // this would allocate one extra byte with Qt 4.x...
+ if(readBlock((char *)(szData.data()),iLen) != iLen)return false;
+ *(szData.data() + iLen) = 0;
+ return true;
+}
+
+#endif
+
+
+bool KviFile::save(const QString &szData)
+{
+ KviQCString c = KviQString::toUtf8(szData);
+ if(!save((kvi_u32_t)(c.length())))return false;
+ return (writeBlock(c.data(),c.length()) == ((int)(c.length())));
+}
+
+bool KviFile::load(QString &szData)
+{
+ kvi_u32_t iLen;
+ if(!load(iLen))return false;
+ KviQCString tmp;
+ tmp.resize(iLen + 1);
+ if(readBlock((char *)(tmp.data()),iLen) != iLen)return false;
+ *(tmp.data() + iLen) = 0;
+ szData = QString::fromUtf8(tmp.data());
+ return true;
+}
+
+bool KviFile::save(const KviStr &szData)
+{
+ if(!save((kvi_u32_t)(szData.len())))return false;
+ return (writeBlock(szData.ptr(),szData.len()) == (int) szData.len());
+}
+
+bool KviFile::load(KviStr &szData)
+{
+ kvi_u32_t iLen;
+ if(!load(iLen))return false;
+ szData.setLength(iLen);
+ return (readBlock((char *)(szData.ptr()),iLen) == iLen);
+}
+
+bool KviFile::save(kvi_u32_t t)
+{
+#ifndef LOCAL_CPU_LITTLE_ENDIAN
+ t = kvi_localCpuToLittleEndian32(t);
+#endif
+ return (writeBlock((const char *)(&t),sizeof(kvi_u32_t)) == sizeof(kvi_u32_t));
+}
+
+bool KviFile::load(kvi_u32_t &t)
+{
+ if(!(readBlock((char *)(&t),sizeof(kvi_u32_t)) == sizeof(kvi_u32_t)))return false;
+#ifndef LOCAL_CPU_LITTLE_ENDIAN
+ t = kvi_littleEndianToLocalCpu32(t);
+#endif
+ return true;
+}
+
+bool KviFile::save(kvi_u64_t t)
+{
+#ifndef LOCAL_CPU_LITTLE_ENDIAN
+ t = kvi_localCpuToLittleEndian64(t);
+#endif
+ return (writeBlock((const char *)(&t),sizeof(kvi_u64_t)) == sizeof(kvi_u64_t));
+}
+
+bool KviFile::load(kvi_u64_t &t)
+{
+ if(!(readBlock((char *)(&t),sizeof(kvi_u32_t)) == sizeof(kvi_u32_t)))return false;
+#ifndef LOCAL_CPU_LITTLE_ENDIAN
+ t = kvi_littleEndianToLocalCpu32(t);
+#endif
+ return true;
+}
+
+
+bool KviFile::save(kvi_u16_t t)
+{
+#ifndef LOCAL_CPU_LITTLE_ENDIAN
+ t = kvi_localCpuToLittleEndian16(t);
+#endif
+ return (writeBlock((const char *)(&t),sizeof(kvi_u16_t)) == sizeof(kvi_u16_t));
+}
+
+bool KviFile::load(kvi_u16_t &t)
+{
+ if(!(readBlock((char *)(&t),sizeof(kvi_u16_t)) == sizeof(kvi_u16_t)))return false;
+#ifndef LOCAL_CPU_LITTLE_ENDIAN
+ t = kvi_littleEndianToLocalCpu16(t);
+#endif
+ return true;
+}
+
+bool KviFile::save(kvi_u8_t t)
+{
+ return (writeBlock((const char *)(&t),sizeof(kvi_u8_t)) == sizeof(kvi_u8_t));
+}
+
+bool KviFile::load(kvi_u8_t &t)
+{
+ return (readBlock((char *)(&t),sizeof(kvi_u8_t)) == sizeof(kvi_u8_t));
+}
+
+
+bool KviFile::save(KviPointerList<KviStr> * pData)
+{
+ if(!save((int)(pData->count())))return false;
+ for(KviStr * s = pData->first();s;s = pData->next())
+ {
+ if(!save(*s))return false;
+ }
+ return true;
+}
+
+bool KviFile::load(KviPointerList<KviStr> * pData)
+{
+ pData->clear();
+ int iCount;
+ if(!load(iCount))return false;
+ for(int i=0;i<iCount;i++)
+ {
+ KviStr * s = new KviStr();
+ if(!load(*s))
+ {
+ delete s;
+ s = 0;
+ return false;
+ }
+ pData->append(s);
+ }
+ return true;
+}
+
+bool KviFile::skipFirst(char t,unsigned int maxdist)
+{
+ while(maxdist > 0)
+ {
+ char c;
+ if(!getChar(&c))return false;
+ if(((char)c) == t)return true;
+ maxdist--;
+ }
+ return false;
+}
+
+bool KviFile::skipFirst(const KviStr &t,unsigned int maxdist)
+{
+ char * ptr = t.ptr();
+ while(maxdist > 0)
+ {
+ char c;
+ if(!getChar(&c))return false;
+ if(c == *ptr)
+ {
+ ptr++;
+ if(!*ptr)return true;
+ } else {
+ ptr = t.ptr();
+ }
+ maxdist--;
+ }
+ return false;
+}
+
diff --git a/src/kvilib/file/kvi_file.h b/src/kvilib/file/kvi_file.h
new file mode 100644
index 00000000..188a9dad
--- /dev/null
+++ b/src/kvilib/file/kvi_file.h
@@ -0,0 +1,120 @@
+#ifndef _KVI_FILE_H_
+#define _KVI_FILE_H_
+
+//=============================================================================
+//
+// File : kvi_file.h
+// Creation date : Mon Dec 17 2001 00:05:04 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_heapobject.h"
+#include "kvi_qstring.h"
+#include "kvi_string.h"
+#include "kvi_pointerlist.h"
+#include "kvi_inttypes.h"
+#include "kvi_qcstring.h"
+
+#include <qfile.h>
+#include <time.h>
+
+#ifdef COMPILE_USE_QT4
+ #define kvi_file_offset_t qlonglong
+#else
+ #define kvi_file_offset_t QFile::Offset
+#endif
+
+
+class KVILIB_API KviFile : public QFile, public KviHeapObject
+{
+public:
+ KviFile();
+ KviFile(const QString &name);
+ ~KviFile();
+public:
+ // Wrappers portable across Qt 3.x and Qt 4.x
+ bool openForReading();
+ bool openForWriting(bool bAppend = false);
+
+#ifndef COMPILE_USE_QT4
+ // Functions present in Qt 4.x but not Qt 3.x
+ bool putChar(char c){ return putch(c) != -1; };
+ bool ungetChar(char c){ return ungetch(c) != -1; };
+ bool getChar(char * c){ *c = getch(); return *c != -1; };
+ bool seek(kvi_file_offset_t o){ return at(o); };
+ kvi_file_offset_t pos(){ return at(); };
+#endif
+
+#ifdef COMPILE_USE_QT4
+ // Missing functions in Qt 4.x
+ quint64 writeBlock(const char * data,quint64 uLen){ return write(data,uLen); };
+ quint64 readBlock(char * data,quint64 uLen){ return read(data,uLen); };
+#endif
+
+ // This stuff loads and saves LITTLE ENDIAN DATA!
+ bool save(kvi_u64_t t);
+ bool load(kvi_u64_t &t);
+
+ bool save(kvi_i64_t t){ return save((kvi_u64_t)t); };
+ bool load(kvi_i64_t &t){ return load((kvi_u64_t &)t); };
+
+ bool save(kvi_u32_t t);
+ bool load(kvi_u32_t &t);
+
+ bool save(kvi_i32_t t){ return save((kvi_u32_t)t); };
+ bool load(kvi_i32_t &t){ return load((kvi_u32_t &)t); };
+
+ bool save(kvi_u16_t t);
+ bool load(kvi_u16_t &t);
+
+ bool save(kvi_i16_t t){ return save((kvi_u16_t)t); };
+ bool load(kvi_i16_t &t){ return load((kvi_u16_t &)t); };
+
+ bool save(kvi_u8_t t);
+ bool load(kvi_u8_t &t);
+
+ bool save(kvi_i8_t t){ return save((kvi_u8_t)t); };
+ bool load(kvi_i8_t &t){ return load((kvi_u8_t &)t); };;
+
+ bool save(const KviStr &szData);
+ bool load(KviStr &szData);
+
+#ifndef COMPILE_USE_QT4
+ // Under Qt 4.x these collide with QByteArray
+ bool save(const KviQCString &szData);
+ bool load(KviQCString &szData);
+#endif
+
+ bool save(const QByteArray &bData);
+ bool load(QByteArray &bData);
+
+ bool save(const QString &szData);
+ bool load(QString &szData);
+
+ bool skipFirst(char t,unsigned int maxdist = 0xffffffff);
+ bool skipFirst(const KviStr &t,unsigned int maxdist = 0xffffffff);
+
+ bool save(KviPointerList<KviStr> * pData);
+ bool load(KviPointerList<KviStr> * pData);
+};
+
+
+#endif //_KVI_FILE_H_
diff --git a/src/kvilib/file/kvi_fileutils.cpp b/src/kvilib/file/kvi_fileutils.cpp
new file mode 100644
index 00000000..648d9125
--- /dev/null
+++ b/src/kvilib/file/kvi_fileutils.cpp
@@ -0,0 +1,505 @@
+//=============================================================================
+//
+// File : kvi_fileutils.cpp
+// Creation date : Fri Dec 25 1998 18:26:48 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1998-2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+
+
+#define _KVI_FILEUTLIS_CPP_
+#include "kvi_fileutils.h"
+#include "kvi_qstring.h"
+#include "kvi_file.h"
+#include "kvi_malloc.h"
+
+#include <qdir.h>
+#include <qfileinfo.h>
+#include <qglobal.h>
+#include <qtextcodec.h>
+#include <qtextstream.h>
+
+
+namespace KviFileUtils
+{
+ /*
+ WORKING CODE BUT UNUSED FOR NOW
+ bool readLine(QFile * f,QString &szBuffer,bool bClearBuffer)
+ {
+ // FIXME: Should this assume UTF8 encoding ?
+ char tmp_buf[256];
+ int cur_len = 0;
+ //char *cur_ptr = tmp_buf;
+ if(bClearBuffer)szBuffer = "";
+ int ch = f->getch();
+
+ while((ch != -1)&&(ch != '\n')&&(ch != 0))
+ {
+ tmp_buf[cur_len] = ch;
+ cur_len++;
+ if(cur_len > 255)
+ {
+ if(tmp_buf[255] == '\r')cur_len--; //Ignore CR...
+ int lastlen = szBuffer.length();
+ szBuffer.setLength(lastlen + cur_len);
+ QChar *p1 = szBuffer.unicode() + lastlen;
+ char * p2 = tmp_buf;
+ for(int i=0;i<cur_len;i++)*p1++ = *p2++;
+ cur_len = 0;
+ }
+ ch = f->getch();
+ }
+ if(ch == 0)
+ {
+ debug("Warning : %s is not an ascii file",f->name().latin1());
+ }
+ if(cur_len > 0)
+ {
+ if(tmp_buf[cur_len - 1] == '\r')cur_len--; //Ignore CR...
+ int lastlen = szBuffer.length();
+ szBuffer.setLength(lastlen + cur_len);
+ QChar *p1 = szBuffer.unicode() + lastlen;
+ char * p2 = tmp_buf;
+ for(int i=0;i<cur_len;i++)*p1++ = *p2++;
+ }
+ return (ch == '\n'); //more data to read else a broken file or EOF
+ }
+
+ bool loadFileStripCR(const QString &szPath,QString &szBuffer)
+ {
+ QFile f(szPath);
+ if(!f.open(IO_ReadOnly))return false;
+ szBuffer = "";
+ while(readLine(&f,szBuffer,false))
+ {
+ szBuffer.append('\n'); // readLine returned true...last char was a newline
+ }
+ // readLine returned false , no ending newline encountered
+ return true;
+ }
+ */
+
+ bool makeDir(const QString &szPath)
+ {
+ QDir d;
+ QString dir = KviQString::trimmed(szPath);
+ adjustFilePath(dir);
+ QString createdDir;
+
+#ifdef COMPILE_ON_WINDOWS
+#ifdef COMPILE_USE_QT4
+ int idx = dir.indexOf(':');
+#else
+ int idx = dir.find(':');
+#endif
+ if(idx == 1)
+ {
+ createdDir = dir.left(2);
+ dir.remove(0,2);
+ }
+#endif
+
+ KviQString::stripLeft(dir,KVI_PATH_SEPARATOR_CHAR);
+ while(!dir.isEmpty())
+ {
+ createdDir += KVI_PATH_SEPARATOR;
+ createdDir += KviQString::getToken(dir,KVI_PATH_SEPARATOR_CHAR);
+ if(!directoryExists(createdDir))
+ {
+ if(!d.mkdir(createdDir))
+ {
+ debug("Can't create directory %s",KviQString::toUtf8(createdDir).data());
+ return false;
+ }
+ }
+ KviQString::stripLeft(dir,KVI_PATH_SEPARATOR_CHAR);
+ }
+ return true;
+ }
+
+ bool makeDir(const char* path)
+ {
+ QString szPath=QString::fromUtf8(path);
+ return makeDir(szPath);
+ }
+
+ bool renameFile(const QString &szSrc,const QString &szDst)
+ {
+ QDir d;
+ return d.rename(szSrc,szDst);
+ }
+
+ bool renameFile(const char* path,const char* path2)
+ {
+ QString szPath=QString::fromUtf8(path);
+ QString szPath2=QString::fromUtf8(path2);
+ return renameFile(szPath,szPath2);
+ }
+
+ bool copyFile(const QString &szSrc,const QString &szDst)
+ {
+ KviFile f1(szSrc);
+ if(!f1.openForReading())return false;
+ KviFile f2(szDst);
+ if(!f2.openForWriting())
+ {
+ f1.close();
+ return false;
+ }
+ char buffer[1024];
+ while(!f1.atEnd())
+ {
+ int len = f1.readBlock(buffer,1024);
+ if(len <= 0)
+ {
+ f1.close();
+ f2.close();
+ return false; //"serious error"
+ }
+ f2.writeBlock(buffer,len);
+ }
+ f1.close();
+ f2.close();
+ return true;
+ }
+
+ bool copyFile(const char* path,const char* path2)
+ {
+ QString szPath=QString::fromUtf8(path);
+ QString szPath2=QString::fromUtf8(path2);
+ return copyFile(szPath,szPath2);
+ }
+
+ bool loadFile(const QString &szPath,QString &szBuffer,bool bUtf8)
+ {
+ KviFile f(szPath);
+ if(!f.openForReading())return false;
+ if(bUtf8)
+ {
+ QByteArray ba = f.readAll();
+ szBuffer = QString::fromUtf8(ba.data(),ba.size());
+ //debug("BUFFERLEN: %d",szBuffer.length());
+ } else {
+ szBuffer = QString(f.readAll());
+ }
+ return true;
+ }
+
+ bool loadFile(const char* path,QString &szBuffer,bool bUtf8)
+ {
+ QString szPath=QString::fromUtf8(path);
+ return loadFile(szPath,szBuffer,bUtf8);
+ }
+
+ void adjustFilePath(QString &szPath)
+ {
+#ifdef COMPILE_ON_WINDOWS
+ szPath.replace('/',"\\");
+#ifdef COMPILE_USE_QT4
+ szPath.replace("\\\\","\\");
+#else
+ while(szPath.find("\\\\") != -1)szPath.replace("\\\\","\\");
+#endif
+ // FIXME: Use the default drive here ?
+ if(szPath.startsWith("\\"))szPath.prepend("C:");
+#else
+ szPath.replace('\\',"/");
+#ifdef COMPILE_USE_QT4
+ szPath.replace("//","/");
+#else
+ while(KviQString::find(szPath,"//") != -1)szPath.replace("//","/");
+#endif
+ // deal with windows paths
+ if((szPath.length() > 2) && (szPath.at(0) != QChar('/')))
+ {
+ if((szPath.at(1) == QChar(':')) && (szPath.at(2) == QChar('/')))
+ {
+ szPath.remove(0,2);
+ }
+ }
+#ifdef COMPILE_USE_QT4
+ szPath=QDir::cleanPath(szPath);
+#else
+ szPath=QDir::cleanDirPath(szPath);
+#endif
+#endif
+
+ }
+
+ bool directoryExists(const QString &szPath)
+ {
+ QFileInfo f(szPath);
+ return (f.exists() && f.isDir());
+ }
+
+ bool directoryExists(const char* path)
+ {
+ QString szPath=QString::fromUtf8(path);
+ QFileInfo f(szPath);
+ return (f.exists() && f.isDir());
+ }
+
+ bool fileExists(const QString &szPath)
+ {
+ QFileInfo f(szPath);
+ return (f.exists() && f.isFile());
+ }
+
+ bool fileExists(const char* path)
+ {
+ QString szPath=QString::fromUtf8(path);
+ return fileExists(szPath);
+ }
+
+ bool removeFile(const QString &szPath)
+ {
+ QDir d;
+ return d.remove(szPath);
+ }
+
+ bool removeFile(const char* path)
+ {
+ QString szPath=QString::fromUtf8(path);
+ return removeFile(szPath);
+ }
+
+ bool removeDir(const QString &szPath)
+ {
+ QDir d;
+ return d.rmdir(szPath);
+ }
+
+ bool removeDir(const char* path)
+ {
+ QString szPath=QString::fromUtf8(path);
+ return removeDir(szPath);
+ }
+
+ bool deleteDir(const QString &szPath)
+ {
+ QDir d(szPath);
+ QStringList sl = d.entryList(QDir::Dirs);
+ QStringList::Iterator it;
+ for(it=sl.begin();it != sl.end();it++)
+ {
+ QString szSubdir = *it;
+ if(!(KviQString::equalCS(szSubdir,"..") || KviQString::equalCS(szSubdir,".")))
+ {
+ QString szSubPath = szPath;
+ KviQString::ensureLastCharIs(szSubPath,QChar(KVI_PATH_SEPARATOR_CHAR));
+ szSubPath += szSubdir;
+ if(!KviFileUtils::deleteDir(szSubPath))
+ return false;
+ }
+ }
+
+ sl = d.entryList(QDir::Files);
+ for(it=sl.begin();it != sl.end();it++)
+ {
+ QString szFilePath = szPath;
+ KviQString::ensureLastCharIs(szFilePath,QChar(KVI_PATH_SEPARATOR_CHAR));
+ szFilePath += *it;
+ if(!KviFileUtils::removeFile(szFilePath))
+ return false;
+ }
+
+ return KviFileUtils::removeDir(szPath);
+ }
+
+ bool writeFile(const QString &szPath,const QString &szData,bool bAppend)
+ {
+ KviFile f(szPath);
+ if(!f.openForWriting(bAppend))return false;
+ KviQCString szTmp = KviQString::toUtf8(szData);
+ if(!szTmp.data())return true;
+ if(f.writeBlock(szTmp.data(),szTmp.length()) != ((int)(szTmp.length())))return false;
+ return true;
+ }
+
+ bool writeFile(const char* path,const QString &szData,bool bAppend)
+ {
+ QString szPath=QString::fromUtf8(path);
+ return writeFile(szPath,szData,bAppend);
+ }
+
+ bool writeFileLocal8Bit(const QString &szPath,const QString &szData,bool bAppend)
+ {
+ KviFile f(szPath);
+ if(!f.openForWriting(bAppend))return false;
+ KviQCString szTmp = QTextCodec::codecForLocale()->fromUnicode(szData);
+ if(!szTmp.data())return true;
+ if(f.writeBlock(szTmp.data(),szTmp.length()) != ((int)(szTmp.length())))return false;
+ return true;
+ }
+
+ bool writeFileLocal8Bit(const char* path,const QString &szData,bool bAppend)
+ {
+ QString szPath=QString::fromUtf8(path);
+ return writeFileLocal8Bit(szPath,szData,bAppend);
+ }
+
+ bool readFile(const QString &szPath,QString &szBuffer,unsigned int uMaxSize)
+ {
+ KviFile f(szPath);
+ if(!f.openForReading())return false;
+ if(f.size() < 1)
+ {
+ szBuffer = "";
+ f.close();
+ return true;
+ }
+ if(f.size() > uMaxSize)return false;
+ char * buf = new char[f.size() + 1];
+ if(f.readBlock(buf,f.size()) != ((long int)f.size()))
+ {
+ delete buf;
+ buf = 0;
+ return false;
+ }
+ buf[f.size()] = '\0';
+ szBuffer = QString::fromUtf8(buf);
+ delete[] buf;
+ return true;
+ }
+
+ bool readFile(const char* path,QString &szBuffer,unsigned int uMaxSize)
+ {
+ QString szPath=QString::fromUtf8(path);
+ return readFile(szPath,szBuffer,uMaxSize);
+ }
+
+
+ QString extractFileName(const QString &szFileNameWithPath)
+ {
+ return QFileInfo(szFileNameWithPath).fileName();
+ }
+
+ QString extractFilePath(const QString &szFileNameWithPath)
+ {
+ return QFileInfo(szFileNameWithPath).dirPath(true);
+ }
+
+ bool readLine(QFile * f,QString &szBuffer,bool bUtf8)
+ {
+ QTextStream stream(f);
+ stream.setEncoding(bUtf8 ? QTextStream::UnicodeUTF8 : QTextStream::Locale);
+ szBuffer=stream.readLine();
+ return !szBuffer.isNull();
+ }
+
+ bool readLines(QFile * f,QStringList &buffer,int iStartLine, int iCount, bool bUtf8)
+ {
+ QTextStream stream( f );
+ stream.setEncoding(bUtf8 ? QTextStream::UnicodeUTF8 : QTextStream::Locale);
+ for(int i=0;i<iStartLine;i++)
+ stream.readLine();
+
+ if(iCount>0)
+ {
+ for(; (iCount>0 && !stream.atEnd()) ; iCount-- )
+ buffer.append(stream.readLine());
+ } else {
+ while(!stream.atEnd()) {
+ buffer.append(stream.readLine());
+ }
+ }
+ return buffer.count()!= 0;
+ }
+
+ bool isReadable(const QString &szFname)
+ {
+ QFileInfo f(szFname);
+ return (f.exists() && f.isFile() && f.isReadable());
+ }
+
+ bool isReadable(const char* path)
+ {
+ QString szPath=QString::fromUtf8(path);
+ return isReadable(szPath);
+ }
+
+ bool isAbsolutePath(const QString &szPath)
+ {
+ QFileInfo f(szPath);
+ return !f.isRelative();
+ }
+};
+
+static char hexchars[16] = { '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , 'A' , 'B' , 'C' , 'D' , 'E' , 'F' };
+
+
+void kvi_encodeFileName(KviStr & path)
+{
+ QString szPath(path.ptr());
+ kvi_encodeFileName(szPath);
+ path=szPath;
+}
+
+void kvi_encodeFileName(QString & path)
+{
+ QString src(path);
+ path="";
+ for(int i=0;i<src.length();i++)
+ {
+ QChar cur=src[i];
+ if( ! (cur.isLetter() || cur.isDigit() || cur==' ' || cur=='_' || cur=='.' || cur=='#' || cur=='%') )
+ {
+ if(cur.row()!=0)
+ {
+ path+='%';
+ path+=hexchars[cur.row() >> 4];
+ path+=hexchars[cur.row() & 15];
+ }
+ path+='%';
+ path+=hexchars[cur.cell() >> 4];
+ path+=hexchars[cur.cell() & 15];
+ } else if (cur=='%')
+ {
+ path+="%%";
+ } else {
+ path+=cur;
+ }
+ }
+}
+
+//================ kvi_isAbsolutePath ===============//
+
+bool kvi_isAbsolutePath(const char *path)
+{
+ if(*path == '/')return true;
+ if(isalpha(*path))
+ {
+ if((*(path + 1)) == ':')return true;
+ }
+ return false;
+}
+
+//=================== kvi_readLine =====================//
+
+bool kvi_readLine(QFile *f,KviStr &str)
+{
+ QTextStream stream(f);
+ QString szBuff=stream.readLine();
+ str=szBuff;
+ return szBuff.isNull() ? 1 : 0;
+}
+
+
diff --git a/src/kvilib/file/kvi_fileutils.h b/src/kvilib/file/kvi_fileutils.h
new file mode 100644
index 00000000..dcead8ae
--- /dev/null
+++ b/src/kvilib/file/kvi_fileutils.h
@@ -0,0 +1,112 @@
+#ifndef _KVI_FILEUTILS_H_
+#define _KVI_FILEUTILS_H_
+
+//
+// File : kvi_fileutils.h
+// Creation date : Fri Dec 25 1998 18:27:04 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+#include "kvi_string.h"
+
+#include <qfile.h>
+#include <qstringlist.h>
+
+#include <time.h>
+
+
+#ifdef COMPILE_ON_WINDOWS
+ #define KVI_PATH_SEPARATOR "\\"
+ #define KVI_PATH_SEPARATOR_CHAR '\\'
+#else
+ #define KVI_PATH_SEPARATOR "/"
+ #define KVI_PATH_SEPARATOR_CHAR '/'
+#endif
+
+// #warning "Add kvi_trashFile(const char * path) ? - is it needed in the whole app"
+// #warning "or should it be availible only for dirbrowser module ?"
+namespace KviFileUtils
+{
+ //extern KVILIB_API bool readLine(QFile * f,QString &szBuffer,bool bClearBuffer = true);
+ //extern KVILIB_API bool loadFileStripCR(const QString &szPath,QString &szBuffer);
+
+ // loads the file at szPath to szBuffer eventually converting from utf8
+ extern KVILIB_API bool loadFile(const QString &szPath,QString &szBuffer,bool bUtf8 = true);
+ extern KVILIB_API bool loadFile(const char* szPath,QString &szBuffer,bool bUtf8 = true);
+ // adjusts the file path to the current platform
+ extern KVILIB_API void adjustFilePath(QString &szPath);
+ // returns true if szPath points to an existing directory
+ extern KVILIB_API bool directoryExists(const QString &szPath);
+ extern KVILIB_API bool directoryExists(const char* path);
+ // returns true if szPath points to an existing file
+ extern KVILIB_API bool fileExists(const QString &szPath);
+ extern KVILIB_API bool fileExists(const char* szPath);
+ // removes a file
+ extern KVILIB_API bool removeFile(const QString &szPath);
+ extern KVILIB_API bool removeFile(const char* path);
+ // removes a dir (must be empty)
+ extern KVILIB_API bool removeDir(const QString &szPath);
+ extern KVILIB_API bool removeDir(const char* path);
+ // removes a dir recursively
+ extern KVILIB_API bool deleteDir(const QString &szPath);
+ // writes a complete file (utf8 version)
+ extern KVILIB_API bool writeFile(const QString &szPath,const QString &szData,bool bAppend = false);
+ extern KVILIB_API bool writeFile(const char* path,const QString &szData,bool bAppend = false);
+ // writes a complete file (local 8 bit version)
+ extern KVILIB_API bool writeFileLocal8Bit(const QString &szPath,const QString &szData,bool bAppend = false);
+ extern KVILIB_API bool writeFileLocal8Bit(const char* path,const QString &szData,bool bAppend = false);
+ // reads a complete file and puts it in the string szBuffer, if the file is smaller than uMaxSize bytes
+ extern KVILIB_API bool readFile(const QString &szPath,QString &szBuffer,unsigned int uMaxSize = 65535);
+ extern KVILIB_API bool readFile(const char* path,QString &szBuffer,unsigned int uMaxSize = 65535);
+ // extracts the filename from a complete path (strips leading path)
+ extern KVILIB_API QString extractFileName(const QString &szFileNameWithPath);
+
+ extern KVILIB_API QString extractFilePath(const QString &szFileNameWithPath);
+ // cp -f
+ extern KVILIB_API bool copyFile(const QString &szSrc,const QString &szDst);
+ extern KVILIB_API bool copyFile(const char* src,const char* dst);
+ // mv
+ extern KVILIB_API bool renameFile(const QString &szSrc,const QString &szDst);
+ extern KVILIB_API bool renameFile(const char* src,const char* dst);
+ // mkdir
+ extern KVILIB_API bool makeDir(const QString &szPath);
+ extern KVILIB_API bool makeDir(const char* path);
+ // reads a text line, returns false if EOF is reached
+ extern KVILIB_API bool readLine(QFile * f,QString &szBuffer,bool bUtf8 = true);
+ extern KVILIB_API bool readLines(QFile * f,QStringList &buffer,int iStartLine = 0, int iCount = -1, bool bUtf8 = true);
+ extern KVILIB_API bool isReadable(const QString &szFname);
+ extern KVILIB_API bool isAbsolutePath(const QString &szPath);
+};
+
+// ALL THIS STUFF BELOW SHOULD DIE: IF YOU SEE IT, REPLACE WITH THE FUNCTIONS IN THE NAMESPACE ABOVE
+
+// Returns true if the path begins with '/'
+KVILIB_API extern bool kvi_isAbsolutePath(const char *path);
+// Translates ANY string into a valid filename (with no path!)
+// There is NO way to come back to the original string
+// the algo is one-way only
+KVILIB_API extern void kvi_encodeFileName(KviStr & path);
+KVILIB_API extern void kvi_encodeFileName(QString & path);
+
+// Reads a single line from the file and returns false if EOF was encountered.
+KVILIB_API extern bool kvi_readLine(QFile *f,KviStr &str);
+// Removes a file
+
+#endif //_KVI_FILEUTILS_H_INCLUDED_
diff --git a/src/kvilib/file/kvi_packagefile.cpp b/src/kvilib/file/kvi_packagefile.cpp
new file mode 100644
index 00000000..3e7bcc17
--- /dev/null
+++ b/src/kvilib/file/kvi_packagefile.cpp
@@ -0,0 +1,1028 @@
+//=============================================================================
+//
+// File : kvi_packagefile.cpp
+// Created on Tue 26 Dec 2006 05:33:33 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2006 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+#include "kvi_packagefile.h"
+
+#include "kvi_file.h"
+#include "kvi_fileutils.h"
+#include "kvi_locale.h"
+#include "kvi_inttypes.h"
+
+#include <qprogressdialog.h>
+#include <qlabel.h>
+
+#include <qdir.h>
+
+#ifdef COMPILE_ZLIB_SUPPORT
+ #include <zlib.h>
+#endif
+
+//
+// A KVIrc Package File is basically a simple zip file with some additional meta-data.
+// The package file has the following format
+//
+
+// Field Type Bytes Description
+//-------------------------------------------------------------------------------
+// Package:
+// PackageHeader
+// PackageInfo
+// PackageData
+
+// PackageHeader:
+// Magic Bytes 4 'KVPF': Signature for the Kvirc Package File
+// Version uint32 4 0x00000001: Version of this package file
+// Flags uint32 4 0x00000000: Flags, in version 1 is reserved and must be zero
+//
+
+// PackageInfo:
+// InfoFieldCount uint32 4 Number of package info fields
+// InfoField InfoField Variable A list of informational name-value pairs
+// InfoField InfoField Variable A list of informational name-value pairs
+// InfoField InfoField Variable A list of informational name-value pairs
+// .... .... ....
+
+// PackageData:
+// DataField DataField Variable A list of data fields with format defined below
+// DataField DataField Variable A list of data fields with format defined below
+// DataField DataField Variable A list of data fields with format defined below
+// .... .... ....
+
+// InfoField:
+// Name UniString Variable The "name" element of the info field
+// ValueType uint32 4 The type of the following ValueData field
+// ValueData ValueData Variable
+
+// ValueData for ValueType 1 (string field)
+// Value UniString Variable The value element of type string of the the info field
+
+// ValueData for ValueType 2 (binary buffer field)
+// BufferLen uint32 4 The length of the binary buffer
+// BufferData Bytes Variable The data for the binary buffer
+
+
+// UniString:
+// StringLen uint32 4 The length of the string data in BYTES (null terminator NOT included)
+// StringData Bytes StringLen An utf8 encoded string (do NOT write the NULL terminator)
+
+// Bytes:
+// Byte uint8 1 A byte
+// Byte uint8 1 A byte
+// .... .... ....
+
+// DataField:
+// FieldType uint32 4 The type of the field, see below for defined values
+// FieldLen uint32 4 FieldData length in bytes (useful for skipping a field if unsupported)
+// FieldData Variable FieldLen The data of the field, see below for defined values
+
+// FieldData for FieldType 1 (file field)
+// Flags uint32 4 Bitmask. Bits: 1=FileIsDeflated
+// Path UniString Variable A relative path expressed as utf8 string. \ AND / are considered to be separators
+// Size uint32 4 Size of the following file data
+// FilePayload Bytes Variable
+
+// Everything is stored in LITTLE ENDIAN byte order.
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Da Base Engine
+
+KviPackageIOEngine::KviPackageIOEngine()
+{
+ m_pProgressDialog = 0;
+ m_pStringInfoFields = new KviPointerHashTable<QString,QString>();
+ m_pStringInfoFields->setAutoDelete(true);
+ m_pBinaryInfoFields = new KviPointerHashTable<QString,QByteArray>();
+ m_pBinaryInfoFields->setAutoDelete(true);
+}
+
+KviPackageIOEngine::~KviPackageIOEngine()
+{
+ if(m_pProgressDialog)delete m_pProgressDialog;
+ delete m_pStringInfoFields;
+ delete m_pBinaryInfoFields;
+}
+
+
+bool KviPackageIOEngine::updateProgress(int iProgress,const QString &szLabel)
+{
+ if(!m_pProgressDialog)return true;
+#ifdef COMPILE_USE_QT4
+ m_pProgressDialog->setValue(iProgress);
+#else
+ m_pProgressDialog->setProgress(iProgress);
+#endif
+ m_pProgressDialogLabel->setText(szLabel);
+ qApp->processEvents();
+ if(m_pProgressDialog->wasCanceled())
+ {
+ setLastError(__tr2qs("Operation cancelled"));
+ return false;
+ }
+ return true;
+}
+
+void KviPackageIOEngine::showProgressDialog(const QString &szCaption,int iTotalSteps)
+{
+#ifdef COMPILE_USE_QT4
+ m_pProgressDialog = new QProgressDialog(QString(""),__tr2qs("Cancel"),0,iTotalSteps,0);
+ m_pProgressDialog->setModal(true);
+ m_pProgressDialog->setWindowTitle(szCaption);
+#else
+ m_pProgressDialog = new QProgressDialog(QString(""),__tr2qs("Cancel"),iTotalSteps,0,"",true);
+ m_pProgressDialog->setCaption(szCaption);
+#endif
+ m_pProgressDialogLabel = new QLabel(m_pProgressDialog);
+ m_pProgressDialogLabel->setMaximumSize(500,300);
+ m_pProgressDialog->setLabel(m_pProgressDialogLabel);
+}
+
+void KviPackageIOEngine::hideProgressDialog()
+{
+ if(!m_pProgressDialog)return;
+ delete m_pProgressDialog;
+ m_pProgressDialog = 0;
+}
+
+bool KviPackageIOEngine::writeError()
+{
+ setLastError(__tr2qs("File write error"));
+ return false;
+}
+
+bool KviPackageIOEngine::readError()
+{
+ setLastError(__tr2qs("File read error"));
+ return false;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Da Writer
+
+
+KviPackageWriter::KviPackageWriter()
+: KviPackageIOEngine()
+{
+ m_pDataFields = new KviPointerList<DataField>();
+ m_pDataFields->setAutoDelete(true);
+}
+
+KviPackageWriter::~KviPackageWriter()
+{
+ delete m_pDataFields;
+}
+
+void KviPackageWriter::addInfoField(const QString &szName,const QString &szValue)
+{
+ m_pStringInfoFields->replace(szName,new QString(szValue));
+}
+
+void KviPackageWriter::addInfoField(const QString &szName,QByteArray * pValue)
+{
+ m_pBinaryInfoFields->replace(szName,pValue);
+}
+
+bool KviPackageWriter::addFile(const QString &szLocalFileName,const QString &szTargetFileName,kvi_u32_t uAddFileFlags)
+{
+ QFileInfo fi(szLocalFileName);
+ return addFileInternal(&fi,szLocalFileName,szTargetFileName,uAddFileFlags);
+}
+
+bool KviPackageWriter::addFileInternal(const QFileInfo * fi,const QString &szLocalFileName,const QString &szTargetFileName,kvi_u32_t uAddFileFlags)
+{
+ if(!(fi->isFile() && fi->isReadable()))
+ return false;
+
+ if(!(uAddFileFlags & FollowSymLinks))
+ {
+ if(fi->isSymLink())
+ return true; // do NOT add a symlink
+ }
+
+ DataField * f = new DataField();
+ f->m_uType = KVI_PACKAGE_DATAFIELD_TYPE_FILE;
+ f->m_bFileAllowCompression = !(uAddFileFlags & NoCompression);
+ f->m_szFileLocalName = szLocalFileName;
+ f->m_szFileTargetName = szTargetFileName;
+ m_pDataFields->append(f);
+
+ return true;
+}
+
+bool KviPackageWriter::addDirectory(const QString &szLocalDirectoryName,const QString &szTargetDirectoryPrefix,kvi_u32_t uAddFileFlags)
+{
+ QDir d(szLocalDirectoryName);
+#ifdef COMPILE_USE_QT4
+ QDir::Filters iFlags;
+#else
+ int iFlags;
+#endif
+ iFlags = QDir::Files | QDir::Readable;
+ if(!(uAddFileFlags & FollowSymLinks))
+ iFlags |= QDir::NoSymLinks;
+
+ // QT4SUX: Because the QDir::entryInfoList() breaks really a lot of code by returning an object that behaves in a _totally_ different way.. it's also much slower
+
+#ifdef COMPILE_USE_QT4
+ int j;
+ QFileInfoList sl = d.entryInfoList(iFlags);
+ for(j=0;j<sl.size();j++)
+ {
+#else
+ const QFileInfoList * sl = d.entryInfoList(iFlags);
+ if(!sl)return false;
+ QFileInfoListIterator it(*sl);
+ while(QFileInfo * fi = it.current())
+ {
+#endif
+ QString szSFileName = szLocalDirectoryName;
+ KviQString::ensureLastCharIs(szSFileName,QChar(KVI_PATH_SEPARATOR_CHAR));
+#ifdef COMPILE_USE_QT4
+ QFileInfo slowCopy = sl.at(j);
+ szSFileName += slowCopy.fileName();
+#else
+ szSFileName += fi->fileName();
+#endif
+ QString szDFileName = szTargetDirectoryPrefix;
+ KviQString::ensureLastCharIs(szDFileName,QChar(KVI_PATH_SEPARATOR_CHAR));
+#ifdef COMPILE_USE_QT4
+ szDFileName += slowCopy.fileName();
+ if(!addFileInternal(&slowCopy,szSFileName,szDFileName,uAddFileFlags))
+ return false;
+#else
+ szDFileName += fi->fileName();
+ if(!addFileInternal(fi,szSFileName,szDFileName,uAddFileFlags))
+ return false;
+#endif
+#ifndef COMPILE_USE_QT4
+ ++it;
+#endif
+ }
+ iFlags = QDir::Dirs | QDir::Readable;
+ if(!(uAddFileFlags & FollowSymLinks))
+ iFlags |= QDir::NoSymLinks;
+ sl = d.entryInfoList(iFlags);
+#ifdef COMPILE_USE_QT4
+ for(j=0;j<sl.size();j++)
+ {
+ QString szDir = sl.at(j).fileName();
+#else
+ if(!sl)return false;
+ QFileInfoListIterator it2(*sl);
+ while(QFileInfo * fi2 = it2.current())
+ {
+ QString szDir = fi2->fileName();
+#endif
+ if(!KviQString::equalCS(szDir,"..") && !KviQString::equalCS(szDir,"."))
+ {
+ QString szSDirName = szLocalDirectoryName;
+ KviQString::ensureLastCharIs(szSDirName,QChar(KVI_PATH_SEPARATOR_CHAR));
+ szSDirName += szDir;
+ QString szDDirName = szTargetDirectoryPrefix;
+ KviQString::ensureLastCharIs(szDDirName,QChar(KVI_PATH_SEPARATOR_CHAR));
+ szDDirName += szDir;
+ if(!addDirectory(szSDirName,szDDirName,uAddFileFlags))
+ return false;
+ }
+#ifndef COMPILE_USE_QT4
+ ++it2;
+#endif
+ }
+
+ return true;
+}
+
+
+
+#define BUFFER_SIZE 32768
+
+bool KviPackageWriter::packFile(KviFile * pFile,DataField * pDataField)
+{
+ QString szProgressText;
+ KviQString::sprintf(szProgressText,__tr2qs("Packaging file %Q"),&(pDataField->m_szFileLocalName));
+ if(!updateProgress(m_iCurrentProgress,szProgressText))
+ return false; // aborted
+
+
+ KviFile source(pDataField->m_szFileLocalName);
+ if(!source.openForReading())
+ {
+ setLastError(__tr2qs("Failed to open a source file for reading"));
+ return false;
+ }
+
+ kvi_u32_t uSize = source.size();
+
+ // Flags
+#ifdef COMPILE_ZLIB_SUPPORT
+ kvi_u32_t uFlags = pDataField->m_bFileAllowCompression ?
+ (uSize > 64 ? KVI_PACKAGE_DATAFIELD_FLAG_FILE_DEFLATE : 0)
+ : 0;
+#else
+ kvi_u32_t uFlags = 0;
+#endif
+
+ if(!pFile->save(uFlags))return writeError();
+
+ KviQCString szTargetFileName = KviQString::toUtf8(pDataField->m_szFileTargetName);
+
+ // Path
+ if(!pFile->save(szTargetFileName))return writeError();
+
+ kvi_file_offset_t savedSizeOffset = pFile->pos();
+
+ // Size : will update it if compression is requested
+ if(!pFile->save(uSize))return writeError();
+
+ pDataField->m_uWrittenFieldLength = 4 + 4 + 4 + szTargetFileName.length(); // sizeof(flags + uncompressed size + path len + path)
+
+ // FilePayload
+#ifdef COMPILE_ZLIB_SUPPORT
+ if(uFlags & KVI_PACKAGE_DATAFIELD_FLAG_FILE_DEFLATE)
+ {
+ unsigned char ibuffer[BUFFER_SIZE];
+ unsigned char obuffer[BUFFER_SIZE];
+
+ kvi_i32_t iReaded = source.readBlock((char *)ibuffer,BUFFER_SIZE);
+ if(iReaded < 0)
+ return readError();
+
+ z_stream zstr;
+ zstr.zalloc = Z_NULL;
+ zstr.zfree = Z_NULL;
+ zstr.opaque = Z_NULL;
+ zstr.next_in = ibuffer;
+ zstr.avail_in = iReaded;
+ zstr.next_out = obuffer;
+ zstr.avail_out = BUFFER_SIZE;
+
+ if(deflateInit(&zstr,9) != Z_OK)
+ {
+ setLastError(__tr2qs("Compression library initialization error"));
+ return false;
+ }
+
+ while(iReaded > 0)
+ {
+ zstr.next_out = obuffer;
+ zstr.avail_out = BUFFER_SIZE;
+
+ if(deflate(&zstr,Z_NO_FLUSH) != Z_OK)
+ {
+ setLastError(__tr2qs("Compression library error"));
+ return false;
+ }
+
+ if(zstr.avail_out < BUFFER_SIZE)
+ {
+ int iCompressed = zstr.next_out - obuffer;
+ pDataField->m_uWrittenFieldLength += iCompressed;
+ if(pFile->writeBlock((char *)obuffer,iCompressed) != iCompressed)
+ {
+ deflateEnd(&zstr);
+ return writeError();
+ }
+ }
+
+ if(zstr.avail_in < BUFFER_SIZE)
+ {
+ int iDataToRead = BUFFER_SIZE - zstr.avail_in;
+ if(iDataToRead < BUFFER_SIZE)
+ {
+ if(ibuffer != zstr.next_in)
+ {
+ // hum, there is still some data in the buffer to be readed
+ // and it is not at the beginning...move it to the beginning of ibuffer
+ memmove(ibuffer,zstr.next_in,zstr.avail_in);
+ }
+ }
+ iReaded = source.readBlock((char *)(ibuffer + zstr.avail_in),iDataToRead);
+ if(iReaded < 0)
+ {
+ deflateEnd(&zstr);
+ return readError();
+ }
+ zstr.avail_in += iReaded;
+ zstr.next_in = ibuffer;
+
+ if((zstr.total_in % 2000000) == 0)
+ {
+ QString szTmp;
+ KviQString::sprintf(szTmp,QString(" (%d of %d bytes)"),zstr.total_in,uSize);
+ QString szPrg = szProgressText + szTmp;
+ if(!updateProgress(m_iCurrentProgress,szPrg))
+ return false; // aborted
+ }
+
+
+ }
+ }
+
+ // flush pending output
+ zstr.next_out = obuffer;
+ zstr.avail_out = BUFFER_SIZE;
+
+ int ret;
+ do
+ {
+ ret = deflate(&zstr,Z_FINISH);
+
+ if((ret == Z_OK) || (ret == Z_STREAM_END))
+ {
+ if(zstr.avail_out < BUFFER_SIZE)
+ {
+ int iCompressed = zstr.next_out - obuffer;
+ pDataField->m_uWrittenFieldLength += iCompressed;
+ if(pFile->writeBlock((char *)obuffer,iCompressed) != iCompressed)
+ {
+ deflateEnd(&zstr);
+ return writeError();
+ }
+ } else {
+ deflateEnd(&zstr);
+ setLastError(__tr2qs("Compression library internal error"));
+ return false;
+ }
+
+ zstr.next_out = obuffer;
+ zstr.avail_out = BUFFER_SIZE;
+ }
+
+ } while(ret == Z_OK);
+
+ // store the compressed data size
+ kvi_file_offset_t here = pFile->pos();
+ pFile->seek(savedSizeOffset);
+ uSize = zstr.total_out;
+
+ deflateEnd(&zstr);
+ if(!pFile->save(uSize))return writeError();
+
+ if(ret != Z_STREAM_END)
+ {
+ setLastError(__tr2qs("Error while compressing a file stream"));
+ return false;
+ }
+
+ pFile->seek(here);
+ } else {
+#endif
+ unsigned char buffer[BUFFER_SIZE];
+ int iTotalFileSize = 0;
+ kvi_i32_t iReaded = source.readBlock((char *)buffer,BUFFER_SIZE);
+ if(iReaded < 0)
+ return readError();
+ while(iReaded > 0)
+ {
+ iTotalFileSize += iReaded;
+ if((iTotalFileSize % 1000000) == 0)
+ {
+ QString szTmp;
+ KviQString::sprintf(szTmp,QString(" (%d of %d bytes)"),iTotalFileSize,uSize);
+ QString szPrg = szProgressText + szTmp;
+ if(!updateProgress(m_iCurrentProgress,szPrg))
+ return false; // aborted
+ }
+ pDataField->m_uWrittenFieldLength += iReaded;
+ if(pFile->writeBlock((char *)buffer,iReaded) != iReaded)
+ return writeError();
+ iReaded = source.readBlock((char *)buffer,BUFFER_SIZE);
+ }
+#ifdef COMPILE_ZLIB_SUPPORT
+ }
+#endif
+ source.close();
+
+ return true;
+}
+
+bool KviPackageWriter::pack(const QString &szFileName,kvi_u32_t uPackFlags)
+{
+ m_iCurrentProgress = 0;
+ if(!(uPackFlags & NoProgressDialog))
+ {
+ showProgressDialog(__tr2qs("Creating package..."),100);
+ updateProgress(m_iCurrentProgress,__tr2qs("Writing package header"));
+ }
+
+ bool bRet = packInternal(szFileName,uPackFlags);
+
+ hideProgressDialog();
+ return bRet;
+}
+
+bool KviPackageWriter::packInternal(const QString &szFileName,kvi_u32_t uPackFlags)
+{
+
+ KviFile f(szFileName);
+ if(!f.openForWriting())
+ {
+ setLastError(__tr2qs("Can't open file for writing"));
+ return false;
+ }
+
+ // write the PackageHeader
+
+ // Magic
+ char magic[4];
+ magic[0] = 'K';
+ magic[1] = 'V';
+ magic[2] = 'P';
+ magic[3] = 'F';
+ if(f.writeBlock(magic,4) != 4)return writeError();
+
+ // Version
+ kvi_u32_t uVersion = 0x1;
+ if(!f.save(uVersion))return writeError();
+
+ // Flags
+ kvi_u32_t uFlags = 0x0;
+ if(!f.save(uFlags))return writeError();
+
+ // write PackageInfo
+
+ // InfoFieldCount
+ kvi_u32_t uCount = m_pStringInfoFields->count() + m_pBinaryInfoFields->count();
+ if(!f.save(uCount))return writeError();
+
+ m_iCurrentProgress = 5;
+ if(!updateProgress(m_iCurrentProgress,__tr2qs("Writing informational fields")))
+ return false; // aborted
+
+ // InfoFields (string)
+ KviPointerHashTableIterator<QString,QString> it(*m_pStringInfoFields);
+ while(QString * s = it.current())
+ {
+ if(!f.save(it.currentKey()))return writeError();
+ kvi_u32_t uType = KVI_PACKAGE_INFOFIELD_TYPE_STRING;
+ if(!f.save(uType))return writeError();
+ if(!f.save(*s))return writeError();
+ ++it;
+ }
+
+ // InfoFields (binary)
+ KviPointerHashTableIterator<QString,QByteArray> it2(*m_pBinaryInfoFields);
+ while(QByteArray * b = it2.current())
+ {
+ if(!f.save(it2.currentKey()))return writeError();
+ kvi_u32_t uType = KVI_PACKAGE_INFOFIELD_TYPE_BINARYBUFFER;
+ if(!f.save(uType))return writeError();
+ if(!f.save(*b))return writeError();
+ ++it2;
+ }
+
+ m_iCurrentProgress = 10;
+ if(!updateProgress(m_iCurrentProgress,__tr2qs("Writing package data")))
+ return false; // aborted
+
+ // write PackageData
+ int iIdx = 0;
+ for(DataField * pDataField = m_pDataFields->first();pDataField;pDataField = m_pDataFields->next())
+ {
+ kvi_u32_t uDataFieldType = pDataField->m_uType;
+ if(!f.save(uDataFieldType))return writeError();
+
+ kvi_file_offset_t savedLenOffset = f.pos();
+ // here we will store the length of the field once it's written
+ if(!f.save(uDataFieldType))return writeError();
+
+ m_iCurrentProgress = 10 + ((90 * iIdx) / m_pDataFields->count());
+
+ switch(pDataField->m_uType)
+ {
+ case KVI_PACKAGE_DATAFIELD_TYPE_FILE:
+ if(!packFile(&f,pDataField))
+ return false;
+ break;
+ default:
+ setLastError(__tr2qs("Internal error"));
+ return false;
+ break;
+ }
+
+ kvi_file_offset_t savedEndOffset = f.pos();
+ f.seek(savedLenOffset);
+ if(!f.save(pDataField->m_uWrittenFieldLength))
+ return writeError();
+
+ f.seek(savedEndOffset);
+ iIdx++;
+ }
+
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Da Reader
+
+KviPackageReader::KviPackageReader()
+: KviPackageIOEngine()
+{
+}
+
+KviPackageReader::~KviPackageReader()
+{
+}
+
+bool KviPackageReader::readHeaderInternal(KviFile * pFile,const QString &szLocalFileName)
+{
+ // read the PackageHeader
+
+ // Magic
+ char magic[4];
+
+ if(pFile->readBlock(magic,4) != 4)return readError();
+ if((magic[0] != 'K') || (magic[1] != 'V') || (magic[2] != 'P') || (magic[3] != 'F'))
+ {
+ setLastError(__tr2qs("The file specified is not a valid KVIrc package"));
+ return false;
+ }
+
+ // Version
+ kvi_u32_t uVersion;
+ if(!pFile->load(uVersion))return readError();
+ if(uVersion != 0x1)
+ {
+ setLastError(__tr2qs("The package has an invalid version number, it might have been created by a newer KVIrc"));
+ return false;
+ }
+
+ // Flags
+ kvi_u32_t uFlags;
+ if(!pFile->load(uFlags))return readError();
+ // we ignore them at the moment
+
+ // read PackageInfo
+
+ // InfoFieldCount
+ kvi_u32_t uCount;
+ if(!pFile->load(uCount))return writeError();
+
+ m_pStringInfoFields->clear();
+ m_pBinaryInfoFields->clear();
+
+ kvi_u32_t uIdx = 0;
+ while(uIdx < uCount)
+ {
+ QString szKey;
+ if(!pFile->load(szKey))return readError();
+ kvi_u32_t uFieldType;
+ if(!pFile->load(uFieldType))return readError();
+ switch(uFieldType)
+ {
+ case KVI_PACKAGE_INFOFIELD_TYPE_STRING:
+ {
+ QString szValue;
+ if(!pFile->load(szValue))return readError();
+ m_pStringInfoFields->replace(szKey,new QString(szValue));
+ }
+ break;
+ case KVI_PACKAGE_INFOFIELD_TYPE_BINARYBUFFER:
+ {
+ QByteArray * pbValue = new QByteArray();
+ if(!pFile->load(*pbValue))
+ {
+ delete pbValue;
+ return readError();
+ }
+ m_pBinaryInfoFields->replace(szKey,pbValue);
+ }
+ break;
+ default:
+ setLastError(__tr2qs("Invalid info field: the package is probably corrupt"));
+ break;
+ }
+ uIdx++;
+ }
+
+ return true;
+}
+
+
+bool KviPackageReader::readHeader(const QString &szLocalFileName)
+{
+ KviFile f(szLocalFileName);
+ if(!f.openForReading())
+ {
+ setLastError(__tr2qs("Can't open file for reading"));
+ return false;
+ }
+
+ return readHeaderInternal(&f,szLocalFileName);
+}
+
+bool KviPackageReader::unpackFile(KviFile * pFile,const QString &szUnpackPath)
+{
+ // Flags
+ kvi_u32_t uFlags;
+ if(!pFile->load(uFlags))return readError();
+
+#ifndef COMPILE_ZLIB_SUPPORT
+ if(uFlags & KVI_PACKAGE_DATAFIELD_FLAG_FILE_DEFLATE)
+ {
+ setLastError(__tr2qs("The package contains compressed data but this executable does not support compression"));
+ return false;
+ }
+#endif
+
+ // Path
+ QString szPath;
+ if(!pFile->load(szPath))return readError();
+
+ QString szFileName = szUnpackPath;
+ KviQString::ensureLastCharIs(szFileName,QChar(KVI_PATH_SEPARATOR_CHAR));
+
+ szFileName += szPath;
+
+ // no attacks please :)
+ szFileName.replace(QString("..\\"),QString(""));
+ szFileName.replace(QString("..//"),QString(""));
+
+ KviFileUtils::adjustFilePath(szFileName);
+
+ int idx = KviQString::findRev(szFileName,QChar(KVI_PATH_SEPARATOR_CHAR));
+ if(idx != -1)
+ {
+ QString szPrefixPath = szFileName.left(idx);
+ if(!KviFileUtils::makeDir(szPrefixPath))
+ {
+ setLastError(__tr2qs("Failed to create the target directory"));
+ return false;
+ }
+ }
+
+ KviFile dest(szFileName);
+ if(!dest.openForWriting())
+ {
+ setLastError(__tr2qs("Failed to open a source file for reading"));
+ return false;
+ }
+
+ QString szProgressText;
+ KviQString::sprintf(szProgressText,__tr2qs("Unpacking file %Q"),&szFileName);
+ if(!updateProgress(pFile->pos(),szProgressText))
+ return false; // aborted
+
+ // Size
+ kvi_u32_t uSize;
+ if(!pFile->load(uSize))return readError();
+
+
+ // FilePayload
+#ifdef COMPILE_ZLIB_SUPPORT
+ if(uFlags & KVI_PACKAGE_DATAFIELD_FLAG_FILE_DEFLATE)
+ {
+ int iRemainingSize = uSize;
+ unsigned char ibuffer[BUFFER_SIZE];
+ unsigned char obuffer[BUFFER_SIZE];
+
+ int iToRead = iRemainingSize;
+ if(iToRead > BUFFER_SIZE)iToRead = BUFFER_SIZE;
+ int iReaded = pFile->readBlock((char *)ibuffer,iToRead);
+ iRemainingSize -= iReaded;
+
+ z_stream zstr;
+ zstr.zalloc = Z_NULL;
+ zstr.zfree = Z_NULL;
+ zstr.opaque = Z_NULL;
+ zstr.next_in = ibuffer;
+ zstr.avail_in = iReaded;
+ zstr.next_out = obuffer;
+ zstr.avail_out = BUFFER_SIZE;
+
+ if(inflateInit(&zstr) != Z_OK)
+ {
+ setLastError(__tr2qs("Compression library initialization error"));
+ return false;
+ }
+
+ while((iReaded > 0) && (iRemainingSize > 0))
+ {
+ zstr.next_out = obuffer;
+ zstr.avail_out = BUFFER_SIZE;
+
+ if(inflate(&zstr,Z_NO_FLUSH) != Z_OK)
+ {
+ setLastError(__tr2qs("Compression library error"));
+ return false;
+ }
+
+ if(zstr.avail_out < BUFFER_SIZE)
+ {
+ int iDecompressed = zstr.next_out - obuffer;
+ if(dest.writeBlock((char *)obuffer,iDecompressed) != iDecompressed)
+ {
+ inflateEnd(&zstr);
+ return writeError();
+ }
+ }
+
+ if(zstr.avail_in < BUFFER_SIZE)
+ {
+ int iDataToRead = BUFFER_SIZE - zstr.avail_in;
+ if(iDataToRead < BUFFER_SIZE)
+ {
+ if(ibuffer != zstr.next_in)
+ {
+ // hum, there is still some data in the buffer to be readed
+ // and it is not at the beginning...move it to the beginning of ibuffer
+ memmove(ibuffer,zstr.next_in,zstr.avail_in);
+ }
+ }
+
+ if(iDataToRead > iRemainingSize)
+ iDataToRead = iRemainingSize;
+
+ iReaded = pFile->readBlock((char *)(ibuffer + zstr.avail_in),iDataToRead);
+ if(iReaded < 0)
+ {
+ inflateEnd(&zstr);
+ return readError();
+ }
+
+ iRemainingSize -= iReaded;
+ zstr.avail_in += iReaded;
+ zstr.next_in = ibuffer;
+
+ if((zstr.total_in % 2000000) == 0)
+ {
+ QString szTmp;
+ KviQString::sprintf(szTmp,QString(" (%d of %d bytes)"),zstr.total_in,uSize);
+ QString szPrg = szProgressText + szTmp;
+ if(!updateProgress(pFile->pos(),szPrg))
+ return false; // aborted
+ }
+ }
+ }
+
+ // flush pending output
+ zstr.next_out = obuffer;
+ zstr.avail_out = BUFFER_SIZE;
+
+ int ret;
+
+ do {
+ ret = inflate(&zstr,Z_FINISH);
+
+ if((ret == Z_OK) || (ret == Z_STREAM_END) || (ret == Z_BUF_ERROR))
+ {
+ if(zstr.avail_out < BUFFER_SIZE)
+ {
+ int iDecompressed = zstr.next_out - obuffer;
+ if(dest.writeBlock((char *)obuffer,iDecompressed) != iDecompressed)
+ {
+ inflateEnd(&zstr);
+ return writeError();
+ }
+ } /* else { THIS HAPPENS FOR ZERO SIZE FILES
+ debug("hum.... internal, rEWq (ret = %d) (avail_out = %d)",ret,zstr.avail_out);
+
+ inflateEnd(&zstr);
+ setLastError(__tr2qs("Compression library internal error"));
+ return false;
+ } */
+ zstr.next_out = obuffer;
+ zstr.avail_out = BUFFER_SIZE;
+ }
+
+ } while((ret == Z_OK) || (ret == Z_BUF_ERROR));
+
+ inflateEnd(&zstr);
+
+ if(ret != Z_STREAM_END)
+ {
+ setLastError(__tr2qs("Error in compressed file stream"));
+ return false;
+ }
+
+ } else {
+#endif
+ unsigned char buffer[BUFFER_SIZE];
+ int iTotalFileSize = 0;
+ int iRemainingData = uSize;
+ int iToRead = iRemainingData;
+ if(iToRead > BUFFER_SIZE)iToRead = BUFFER_SIZE;
+ int iReaded = 1;
+
+ while((iReaded > 0) && (iToRead > 0))
+ {
+ iReaded = pFile->readBlock((char *)buffer,iToRead);
+ if(iReaded > 0)
+ {
+ iTotalFileSize += iReaded;
+ iRemainingData -= iReaded;
+
+ if((iTotalFileSize % 3000000) == 0)
+ {
+ QString szTmp;
+ KviQString::sprintf(szTmp,QString(" (%d of %d bytes)"),iTotalFileSize,uSize);
+ QString szPrg = szProgressText + szTmp;
+ if(!updateProgress(pFile->pos(),szPrg))
+ return false; // aborted
+ }
+
+ if(dest.writeBlock((char *)buffer,iReaded) != iReaded)
+ return writeError();
+ }
+
+ int iToRead = iRemainingData;
+ if(iToRead > BUFFER_SIZE)iToRead = BUFFER_SIZE;
+ }
+#ifdef COMPILE_ZLIB_SUPPORT
+ }
+#endif
+ dest.close();
+
+ return true;
+}
+
+bool KviPackageReader::getStringInfoField(const QString &szName,QString &szBuffer)
+{
+ QString * pVal = m_pStringInfoFields->find(szName);
+ if(!pVal)return false;
+ szBuffer = *pVal;
+ return true;
+}
+
+bool KviPackageReader::unpack(const QString &szLocalFileName,const QString &szUnpackPath,kvi_u32_t uUnpackFlags)
+{
+ bool bRet = unpackInternal(szLocalFileName,szUnpackPath,uUnpackFlags);
+ hideProgressDialog();
+ return bRet;
+}
+
+bool KviPackageReader::unpackInternal(const QString &szLocalFileName,const QString &szUnpackPath,kvi_u32_t uUnpackFlags)
+{
+
+ KviFile f(szLocalFileName);
+ if(!f.openForReading())
+ {
+ setLastError(__tr2qs("Can't open file for reading"));
+ return false;
+ }
+
+ kvi_file_offset_t size = f.size();
+
+ if(!(uUnpackFlags & NoProgressDialog))
+ {
+ showProgressDialog(__tr2qs("Reading package..."),size);
+ updateProgress(0,__tr2qs("Reading package header"));
+ }
+
+
+ if(!readHeaderInternal(&f,szLocalFileName))
+ return false;
+
+ if(!updateProgress(f.pos(),__tr2qs("Reading package data")))
+ return false; // aborted
+
+ while(!f.atEnd())
+ {
+ // DataFieldType
+ kvi_u32_t uDataFieldType;
+ if(!f.load(uDataFieldType))return readError();
+ // DataFieldLen
+ kvi_u32_t uDataFieldLen;
+ if(!f.load(uDataFieldLen))return readError();
+
+ switch(uDataFieldType)
+ {
+ case KVI_PACKAGE_DATAFIELD_TYPE_FILE:
+ if(!unpackFile(&f,szUnpackPath))
+ return false;
+ break;
+ default:
+ setLastError(__tr2qs("Invalid data field: the package is probably corrupt"));
+ return false;
+ break;
+ }
+
+ }
+
+ return true;
+}
+
+
+
diff --git a/src/kvilib/file/kvi_packagefile.h b/src/kvilib/file/kvi_packagefile.h
new file mode 100644
index 00000000..3e330554
--- /dev/null
+++ b/src/kvilib/file/kvi_packagefile.h
@@ -0,0 +1,142 @@
+#ifndef _KVI_PACKAGEFILE_H_
+#define _KVI_PACKAGEFILE_H_
+//=============================================================================
+//
+// File : kvi_packagefile.h
+// Created on Tue 26 Dec 2006 05:33:33 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2006 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_pointerhashtable.h"
+#include "kvi_qcstring.h" // QByteArray anyway
+#include <qobject.h>
+#include "kvi_pointerlist.h"
+
+class KviFile;
+class QProgressDialog;
+class QLabel;
+class QFileInfo;
+
+//
+// This class is used for creating KVIrc package files.
+// You simply instantiate it, add some info fields, add some files and then call pack().
+//
+
+class KVILIB_API KviPackageIOEngine
+{
+public:
+ KviPackageIOEngine();
+ virtual ~KviPackageIOEngine();
+protected:
+ QString m_szLastError;
+ KviPointerHashTable<QString,QString> * m_pStringInfoFields;
+ KviPointerHashTable<QString,QByteArray> * m_pBinaryInfoFields;
+ QProgressDialog * m_pProgressDialog;
+ QLabel * m_pProgressDialogLabel;
+public:
+ const QString & lastError(){ return m_szLastError; };
+ void setLastError(const QString &szLastError){ m_szLastError = szLastError; };
+ KviPointerHashTable<QString,QString> * stringInfoFields(){ return m_pStringInfoFields; };
+ KviPointerHashTable<QString,QByteArray> * binaryInfoFields(){ return m_pBinaryInfoFields; };
+protected:
+ void showProgressDialog(const QString &szCaption,int iTotalSteps);
+ void hideProgressDialog();
+ bool updateProgress(int iProgress,const QString &szLabel);
+ bool writeError();
+ bool readError();
+};
+
+#define KVI_PACKAGE_INFOFIELD_TYPE_STRING 1
+#define KVI_PACKAGE_INFOFIELD_TYPE_BINARYBUFFER 2
+
+#define KVI_PACKAGE_DATAFIELD_TYPE_FILE 1
+
+#define KVI_PACKAGE_DATAFIELD_FLAG_FILE_DEFLATE 1
+
+class KVILIB_API KviPackageWriter : public KviPackageIOEngine
+{
+public:
+ KviPackageWriter();
+ virtual ~KviPackageWriter();
+protected:
+
+ class DataField
+ {
+ public:
+ kvi_u32_t m_uType;
+ // output length of the field
+ kvi_u32_t m_uWrittenFieldLength;
+ // data fields for the File DataFieldType
+ bool m_bFileAllowCompression;
+ QString m_szFileLocalName;
+ QString m_szFileTargetName;
+ };
+
+ KviPointerList<DataField> * m_pDataFields;
+ int m_iCurrentProgress;
+public:
+ // Adds a file to the package. The file must be specified as absolute local
+ // path and as target path relative to the KVIrc local directory.
+ // ... more ?
+ enum AddFileFlags {
+ NoCompression = 1,
+ FollowSymLinks = 2
+ };
+ bool addFile(const QString &szLocalFileName,const QString &szTargetFileName,kvi_u32_t uAddFileFlags = 0);
+ bool addDirectory(const QString &szLocalDirectoryName,const QString &szTargetDirectoryPrefix,kvi_u32_t uAddFileFlags = 0);
+ // Adds an info field as a name=value pair
+ void addInfoField(const QString &szName,const QString &szValue);
+ void addInfoField(const QString &szName,QByteArray * pArray);
+ // Attempts to pack everything and store it as the specified file.
+ // There is no mandatory extension but you *should* use KVI_FILEEXTENSION_THEMEPACKAGE for themes
+ // and KVI_FILEEXTENSION_ADDONPACKAGE for addons. See kvi_fileextension.h
+ enum PackFlags {
+ NoProgressDialog = 1
+ };
+ bool pack(const QString &szFileName,kvi_u32_t uPackFlags = 0);
+private:
+ bool packInternal(const QString &szFileName,kvi_u32_t uPackFlags = 0);
+ bool packFile(KviFile * pFile,DataField * pDataField);
+ bool addFileInternal(const QFileInfo * fi,const QString &szLocalFileName,const QString &szTargetFileName,kvi_u32_t uAddFileFlags = 0);
+};
+
+class KVILIB_API KviPackageReader : public KviPackageIOEngine
+{
+public:
+ KviPackageReader();
+ virtual ~KviPackageReader();
+public:
+ bool readHeader(const QString &szLocalFileName);
+ enum UnpackFlags {
+ NoProgressDialog = 1
+ };
+ bool getStringInfoField(const QString &szName,QString &szBuffer);
+ bool unpack(const QString &szLocalFileName,const QString &szUnpackPath,kvi_u32_t uUnpackFlags = 0);
+private:
+ bool unpackInternal(const QString &szLocalFileName,const QString &szUnpackPath,kvi_u32_t uUnpackFlags = 0);
+ bool unpackFile(KviFile * pFile,const QString &szUnpackPath);
+ bool readHeaderInternal(KviFile * pFile,const QString &szLocalFileName);
+};
+
+
+
+#endif //!_KVI_PACKAGEFILE_H_
diff --git a/src/kvilib/include/Makefile.am b/src/kvilib/include/Makefile.am
new file mode 100644
index 00000000..60838ee7
--- /dev/null
+++ b/src/kvilib/include/Makefile.am
@@ -0,0 +1,4 @@
+###############################################################################
+# KVirc IRC client Makefile - 16.12.98 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
diff --git a/src/kvilib/irc/Makefile.am b/src/kvilib/irc/Makefile.am
new file mode 100644
index 00000000..c84487eb
--- /dev/null
+++ b/src/kvilib/irc/Makefile.am
@@ -0,0 +1,5 @@
+###############################################################################
+# KVirc IRC client Makefile - 16.12.98 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+EXTRA_DIST = *.cpp *.h
diff --git a/src/kvilib/irc/kvi_avatar.cpp b/src/kvilib/irc/kvi_avatar.cpp
new file mode 100644
index 00000000..1642560a
--- /dev/null
+++ b/src/kvilib/irc/kvi_avatar.cpp
@@ -0,0 +1,165 @@
+//=============================================================================
+//
+// File : kvi_avatar.cpp
+// Creation date : Fri Dec 01 2000 13:58:12 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+#define __KVILIB__
+
+
+#include "kvi_avatar.h"
+#include "kvi_qstring.h"
+
+#include <qimage.h>
+
+
+/*
+ @doc: ctcp_avatar
+ @title:
+ The AVATAR idea
+ @short:
+ Extending IRC fun: the AVATAR idea
+ @body:
+ [big]Introduction[/big]
+ Starting from version 3.0.0 KVIrc supports the AVATAR protocol.
+ The AVATAR term dictionary definitions include:[br]
+ - Hindu mythology incarnation of a God[br]
+ - Embodiment of a concept or philosophy[br]
+ - In [b]cyberspace communities[/b], the rappresentation of an
+ user in a shared virtual reality.[br]
+ The AVATAR protocol attempts to improve the IRC communication
+ by adding a method for associating a graphical rappresentation
+ to an IRC user.[br]
+ Since this may involve binary data transfers between users,
+ the protocol is intended to be client based.
+ [big]The terms[/big]
+ The user that wants to offer a digital rappresentation of himself
+ will be called "source user". The ones that will receive the notification
+ will be called "target users".
+ Every irc user can be either a source user or target user.
+ [big]The idea[/big]
+ Every irc user has a client-side property called AVATAR. Let's say that there
+ are two users: A and B.[br]
+ When user A wants to see the B's avatar he simply sends a CTCP AVATAR request
+ to B (the request is sent through a PRIVMSG irc command).[br]
+ User B replies with a CTCP AVATAR notification (sent through a NOTICE irc command)
+ with the name or url of his avatar.[br]
+ The actual syntax for the notification is:[br]
+ [b]AVATAR <avatar_file> [<filesize>][/b]
+ The <avatar_file> may be either the name of a B's local image file or an url
+ pointing to an image on some web server.[br]
+ The optional <filesize> parameter is sent only if <avatar_file> is
+ stored on the B's machine and there will be more info on that later.[br]
+ Anyway, after A has received the notification he tries to locate the avatar
+ file in its local cache (yes, <filesize> may help here and more on this later).
+ If the file can be found
+ and loaded then it is simply displayed in some way near the B's nickname
+ otherwise A must download the avatar from some place.
+ If the <avatar_file> contains a leading url prefix (http://) then
+ A fetches the image from the specified url and after that displays
+ it near the B's nickname. If the <avatar_file> does not contain the
+ leading url prefix then it is assumed that B offers this file for
+ downloading via DCC from his machine. In this case A may also avoid
+ requesting the file if the <filesize> is too large and the transfer
+ would occupy too much bandwidth (for example).
+ The DCC download is initiated by issuing a DCC GET <avatar_file> request to B.
+ B may then reply with a standard DCC SEND or a DCC RSEND (kvirc's extension).[br]
+ The implementation of the DCC GET protocol is defined by other documents here around :).[br]
+ [br]
+ The CTCP AVATAR messages can be sent to a single user , a set of users or a channel:
+ this depends only on the source user and how many clients he wants to reach.
+ [br]
+ There should be a convention on the image sizes: not a protocol limit.
+ For example, the convention could be that all the images should be smaller than
+ 129x129 pixels. The preferred image format is "png" (Portable Network Graphics)
+ since it allows good compression rates without compromising the image quality.
+ Other formats may be accepted as well (Theoretically this protocol could be
+ extended to allow movies or 3D images).
+ The "preferred" image size may grow with time, as the network transmission speed grows.
+*/
+
+KviAvatar::KviAvatar(const QString &szLocalPath,const QString &szName,QPixmap * pix)
+{
+ m_pPixmap = pix;
+ m_pScaledPixmap = 0;
+ if(m_pPixmap == 0)m_pPixmap = new QPixmap(32,32); // cool memory map :)
+
+ m_bRemote = KviQString::equalCIN("http://",szName,7);
+
+ m_szLocalPath = szLocalPath;
+ m_szName = szName;
+}
+
+KviAvatar::~KviAvatar()
+{
+ delete m_pPixmap;
+ if(m_pScaledPixmap)delete m_pScaledPixmap;
+}
+
+QPixmap * KviAvatar::scaledPixmap(unsigned int w,unsigned int h)
+{
+ if(((unsigned int)(m_pPixmap->width())) == w)
+ {
+ if(((unsigned int)(m_pPixmap->height())) == h)
+ return m_pPixmap;
+ }
+
+ if(m_pScaledPixmap)
+ {
+ if((m_uLastScaleWidth == w) && (m_uLastScaleHeight == h))return m_pScaledPixmap;
+ delete m_pScaledPixmap;
+ m_pScaledPixmap = 0;
+ }
+
+ int curW = m_pPixmap->width();
+ int curH = m_pPixmap->height();
+
+ if(curW < 1)curW = 1;
+ if(curH < 1)curH = 1;
+
+ m_uLastScaleWidth = w;
+ m_uLastScaleHeight = h;
+
+ int scaleW = w;
+ int scaleH;
+
+ /* We want to maintain the aspect of the image instead simply set
+ height and width. The first step is trying to adapt the image size
+ by "w" vaule */
+
+ scaleH = (curH * scaleW) / curW;
+
+ /* Now check the resized image size. If it is too wide or too tall,
+ resize it again by "h" value */
+ if(scaleH > h) {
+ scaleH = h;
+ scaleW = (scaleH * curW) / curH;
+ }
+
+#ifdef COMPILE_USE_QT4
+ m_pScaledPixmap = new QPixmap(m_pPixmap->scaled(scaleW,scaleH));
+#else
+ QImage img = m_pPixmap->convertToImage();
+
+ m_pScaledPixmap = new QPixmap();
+ m_pScaledPixmap->convertFromImage(img.smoothScale(scaleW,scaleH));
+#endif
+ return m_pScaledPixmap;
+}
diff --git a/src/kvilib/irc/kvi_avatar.h b/src/kvilib/irc/kvi_avatar.h
new file mode 100644
index 00000000..ba8edbc5
--- /dev/null
+++ b/src/kvilib/irc/kvi_avatar.h
@@ -0,0 +1,83 @@
+#ifndef _KVI_AVATAR_H_
+#define _KVI_AVATAR_H_
+
+//=============================================================================
+//
+// File : kvi_avatar.h
+// Creation date : Fri Dec 01 2000 13:54:04 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_string.h"
+#include "kvi_heapobject.h"
+#include "kvi_settings.h"
+
+#include <qpixmap.h>
+
+class KVILIB_API KviAvatar : public KviHeapObject
+{
+public:
+ KviAvatar(const QString &szLocalPath,const QString &szName,QPixmap * pix);
+ ~KviAvatar();
+private:
+ QString m_szLocalPath;
+ QString m_szName;
+ bool m_bRemote;
+
+ QPixmap * m_pPixmap;
+ QPixmap * m_pScaledPixmap;
+
+ unsigned int m_uLastScaleWidth;
+ unsigned int m_uLastScaleHeight;
+public:
+ QPixmap * pixmap(){ return m_pPixmap; };
+ QPixmap * scaledPixmap(unsigned int w,unsigned int h);
+
+ bool isRemote(){ return m_bRemote; };
+
+ const QString &localPath(){ return m_szLocalPath; };
+ const QString &name(){ return m_szName; };
+
+ // string that uniquely identifies this avatar
+ // for remote avatars that have name starting with http://
+ // the name is used.
+ // for local avatars the localPath is used instead
+ const QString &identificationString(){ return m_bRemote ? m_szName : m_szLocalPath; };
+
+
+ // if name is http://xxxx
+ // then identification is the name
+ // if name is xxx.png
+ // then identification is the local path
+
+
+ // name : visible name of the avatar : url or filename
+ // ex: http://www.kvirc.net/img/pragma.png
+ // ex: pragma.png
+ // local path : local path
+ // ex: /home/pragma/.kvirc/avatars/http.www.kvirc.net.img.pragma.png
+ // ex: /home/pragma/.kvirc/avatars/pragma.png
+
+ // local path->name : strip leading path informations
+ // name->local path : replace : / and
+
+};
+
+#endif //_KVI_AVATAR_H_
diff --git a/src/kvilib/irc/kvi_avatarcache.cpp b/src/kvilib/irc/kvi_avatarcache.cpp
new file mode 100644
index 00000000..d24562ea
--- /dev/null
+++ b/src/kvilib/irc/kvi_avatarcache.cpp
@@ -0,0 +1,250 @@
+//=============================================================================
+//
+// File : kvi_avatarcache.cpp
+// Created on Sat 27 Dec 2003 21:19:47 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+#define __KVILIB__
+
+
+#include "kvi_avatarcache.h"
+#include "kvi_pointerlist.h"
+#include "kvi_config.h"
+
+// this level triggers a cleanup
+#define MAX_AVATARS_IN_CACHE 100
+// this is the level that has be reached by a cleanup
+#define CACHE_GUARD_LEVEL 85
+// dictionary size
+#define CACHE_DICT_SIZE 101
+// keep the unaccessed avatars for 30 days
+#define MAX_UNACCESSED_TIME (3600 * 24 * 30)
+
+
+KviAvatarCache * KviAvatarCache::m_pAvatarCacheInstance = 0;
+
+void KviAvatarCache::init()
+{
+ if(m_pAvatarCacheInstance)
+ {
+ debug("WARNING: trying to initialize the avatar cache twice");
+ return;
+ }
+
+ m_pAvatarCacheInstance = new KviAvatarCache();
+}
+
+void KviAvatarCache::done()
+{
+ if(!m_pAvatarCacheInstance)
+ {
+ debug("WARNING: trying to destroy an uninitialized avatar cache");
+ return;
+ }
+
+ delete m_pAvatarCacheInstance;
+ m_pAvatarCacheInstance = 0;
+}
+
+
+KviAvatarCache::KviAvatarCache()
+{
+ m_pAvatarDict = new KviPointerHashTable<QString,KviAvatarCacheEntry>(CACHE_DICT_SIZE,false);
+ m_pAvatarDict->setAutoDelete(true);
+}
+
+KviAvatarCache::~KviAvatarCache()
+{
+ delete m_pAvatarDict;
+}
+
+
+void KviAvatarCache::replace(const QString &szIdString,const KviIrcMask &mask,const QString &szNetwork)
+{
+ QString szKey;
+
+ mask.mask(szKey,KviIrcMask::NickCleanUserSmartNet);
+ szKey.append(QChar('+'));
+ szKey.append(szNetwork);
+
+ KviAvatarCacheEntry * e = new KviAvatarCacheEntry;
+ e->szIdString = szIdString;
+ e->tLastAccess = kvi_unixTime();
+
+ m_pAvatarDict->replace(szKey,e);
+
+ if(m_pAvatarDict->count() > MAX_AVATARS_IN_CACHE)
+ {
+ cleanup();
+ }
+}
+
+void KviAvatarCache::remove(const KviIrcMask &mask,const QString &szNetwork)
+{
+ QString szKey;
+
+ mask.mask(szKey,KviIrcMask::NickCleanUserSmartNet);
+ szKey.append(QChar('+'));
+ szKey.append(szNetwork);
+
+ m_pAvatarDict->remove(szKey);
+}
+
+
+
+const QString & KviAvatarCache::lookup(const KviIrcMask &mask,const QString &szNetwork)
+{
+ QString szKey;
+
+ mask.mask(szKey,KviIrcMask::NickCleanUserSmartNet);
+ szKey.append(QChar('+'));
+ szKey.append(szNetwork);
+
+ KviAvatarCacheEntry * e = m_pAvatarDict->find(szKey);
+ if(!e)return KviQString::empty;
+ e->tLastAccess = kvi_unixTime();
+ return e->szIdString;
+}
+
+void KviAvatarCache::load(const QString &szFileName)
+{
+ m_pAvatarDict->clear();
+
+ KviConfig cfg(szFileName,KviConfig::Read);
+
+ kvi_time_t tNow = kvi_unixTime();
+
+ KviConfigIterator it(*(cfg.dict()));
+
+ int cnt = 0;
+
+ while(it.current())
+ {
+ cfg.setGroup(it.currentKey());
+
+ kvi_time_t tLastAccess = cfg.readUIntEntry("LastAccess",0);
+ if((tNow - tLastAccess) < MAX_UNACCESSED_TIME)
+ {
+ QString szIdString = cfg.readQStringEntry("Avatar","");
+
+ if(!szIdString.isEmpty())
+ {
+ KviAvatarCacheEntry * e = new KviAvatarCacheEntry;
+ e->tLastAccess = tLastAccess;
+ e->szIdString = szIdString;
+ m_pAvatarDict->replace(it.currentKey(),e);
+ cnt++;
+ if(cnt >= MAX_AVATARS_IN_CACHE)return; // done
+ }
+ }
+ ++it;
+ }
+}
+
+void KviAvatarCache::save(const QString &szFileName)
+{
+ KviConfig cfg(szFileName,KviConfig::Write);
+// cfg.clear(); // not needed with KviConfig::Write
+
+ KviPointerHashTableIterator<QString,KviAvatarCacheEntry> it(*m_pAvatarDict);
+
+ while(KviAvatarCacheEntry * e = it.current())
+ {
+ if(e->tLastAccess)
+ {
+ cfg.setGroup(it.currentKey());
+ cfg.writeEntry("Avatar",e->szIdString);
+ cfg.writeEntry("LastAccess",((unsigned int)(e->tLastAccess)));
+ }
+ ++it;
+ }
+}
+
+void KviAvatarCache::cleanup()
+{
+ // first do a quick run deleting the avatars really too old
+ KviPointerHashTableIterator<QString,KviAvatarCacheEntry> it(*m_pAvatarDict);
+
+ kvi_time_t tNow = kvi_unixTime();
+
+ KviPointerList<QString> l;
+ l.setAutoDelete(false);
+
+ KviAvatarCacheEntry * e;
+
+ while((e = it.current()))
+ {
+ if((tNow - e->tLastAccess) > MAX_UNACCESSED_TIME)
+ {
+ l.append(new QString(it.currentKey()));
+ }
+ ++it;
+ }
+
+ for(QString *s = l.first();s;s = l.next())m_pAvatarDict->remove(*s);
+
+ if(m_pAvatarDict->count() < CACHE_GUARD_LEVEL)return;
+
+ // not done.. need to kill the last accessed :/
+
+ it.toFirst();
+
+ KviPointerList<KviAvatarCacheEntry> ll;
+ ll.setAutoDelete(true);
+
+ // here we use the cache entries in another way
+ // szAvatar is the KEY instead of the avatar name
+
+ while((e = it.current()))
+ {
+ KviAvatarCacheEntry * current = ll.first();
+ unsigned int idx = 0;
+ while(current)
+ {
+ // if the current is newer than the inserted one
+ // then stop searching and insert it just before
+ if(current->tLastAccess > e->tLastAccess)break;
+ // otherwise the current is older and the inserted
+ // one goes after
+ current = ll.next();
+ idx++;
+ }
+
+ KviAvatarCacheEntry * xx = new KviAvatarCacheEntry;
+ xx->szIdString = it.currentKey();
+ xx->tLastAccess = e->tLastAccess;
+
+ if(current)ll.insert(idx,xx);
+ else ll.append(xx);
+ ++it;
+ }
+
+ // the oldest keys are at the beginning
+ int uRemove = ll.count() - CACHE_GUARD_LEVEL;
+ if(uRemove < 1)return; // huh ?
+
+ // remember that szAvatar contains the key!
+ for(e = ll.first();e && (uRemove > 0);e = ll.next())
+ {
+ m_pAvatarDict->remove(e->szIdString);
+ uRemove--;
+ }
+ // now we should be ok
+}
diff --git a/src/kvilib/irc/kvi_avatarcache.h b/src/kvilib/irc/kvi_avatarcache.h
new file mode 100644
index 00000000..7d715256
--- /dev/null
+++ b/src/kvilib/irc/kvi_avatarcache.h
@@ -0,0 +1,69 @@
+#ifndef _KVI_AVATARCACHE_H_
+#define _KVI_AVATARCACHE_H_
+//=============================================================================
+//
+// File : kvi_avatarcache.h
+// Created on Sat 27 Dec 2003 21:19:47 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_time.h"
+#include "kvi_ircmask.h"
+
+#include "kvi_pointerhashtable.h"
+
+
+typedef struct _KviAvatarCacheEntry
+{
+ QString szIdString;
+ kvi_time_t tLastAccess;
+} KviAvatarCacheEntry;
+
+
+
+class KVILIB_API KviAvatarCache
+{
+protected:
+ KviAvatarCache();
+ ~KviAvatarCache();
+public:
+ KviPointerHashTable<QString,KviAvatarCacheEntry> * m_pAvatarDict;
+protected:
+ static KviAvatarCache * m_pAvatarCacheInstance;
+public:
+ static void init();
+ static void done();
+
+ static KviAvatarCache * instance(){ return m_pAvatarCacheInstance; };
+
+ void replace(const QString &szIdString,const KviIrcMask &mask,const QString &szNetwork);
+ void remove(const KviIrcMask &mask,const QString &szNetwork);
+ const QString & lookup(const KviIrcMask &mask,const QString &szNetwork);
+
+ void cleanup();
+
+ void load(const QString &szFileName);
+ void save(const QString &szFileName);
+};
+
+
+#endif //!_KVI_AVATARCACHE_H_
diff --git a/src/kvilib/irc/kvi_ircmask.cpp b/src/kvilib/irc/kvi_ircmask.cpp
new file mode 100644
index 00000000..dbdc1b6c
--- /dev/null
+++ b/src/kvilib/irc/kvi_ircmask.cpp
@@ -0,0 +1,760 @@
+//=============================================================================
+//
+// File : kvi_ircuser.cpp
+// Creation date : Fri Jan 8 1999 20:56:07 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+
+
+#include "kvi_debug.h"
+#include "kvi_ircmask.h"
+
+/*
+ @doc: irc_masks
+ @title:
+ Irc masks
+ @type:
+ generic
+ @short:
+ Decription of the standard IRC masks
+ @keyterms:
+ irc masks , nickname , username , hostname , wildcard
+ @body:
+ [big]Simple masks[/big][br]
+ An irc mask is a string in a special format that identifies an user on irc.[br]
+ The standard basic format is:[br]
+ [b]<nick>!<username>@<host>[/b][br]
+ The <nick> part contains the nickname with that the user is widely known across the network.[br]
+ The nickname format is generally restricted by the irc network rules: usually it has a maximum
+ length (9 on actual IrcNet servers for example), and can contain only a defined set of characters.
+ Just as example, the character '!' obviously can't be included in a nickname.[br]
+ The <username> part is the machine username of the remote user: this is usually
+ retrieved by the irc server at connect time by contacting the ident service on the user's machine.
+ Some IRC servers allow specifying this username inside the login messages and do not connect
+ to the ident service at all.[br]
+ The <username> often has a special prefix character added by the irc server:[br]
+ this is rather server specific protocol , but the prefixes are somewhat standardized and
+ the common meanings of them are:[br]
+ noprefix: I line with ident[br]
+ ^: I line with OTHER type ident[br]
+ ~: I line, no ident[br]
+ +: i line with ident[br]
+ =: i line with OTHER type ident[br]
+ -: i line, no ident[br]
+ So finally you can find <username> strings like "~pragma" or "^pragma", where "pragma"
+ is the system username of the irc-user and ~ and ^ are prefixes.[br]
+ The <host> part is the hostname of the remote user.[br]
+ In most cases it is the human-readable format of the host name, but sometimes
+ it happens to be an IP-address (when the host has no reverse dns entry).[br]
+ The IP address can be either in IPV4 format or in IPV6 format.[br]
+ Some (weird from my point of view) servers hide certain parts of the IP address to
+ prevent attacks to the user's machine.[br]
+ Here are some examples of full irc-masks:[br]
+ Pragma!^pragma@staff.kvirc.net[br]
+ [jazz]!~jazz@jazz.myhome.com[br]
+ luke!=skywalker@212.213.41.12[br]
+ HAN!^solo@ff0f:a0a0:1011::ea80:1[br]
+ Darth!vader@210.11.12.XXX[br]
+ The irc-masks are [b]case insensitive[/b].[br]
+ [br]
+ [big]Wildcard masks[/big][br]
+ In some contexts the irc-masks can contain '*' and '?' wildcards.[br]
+ The wild masks are used to "match" an user within a set of them.[br]
+ '*' matches any sequence (eventually empty) of characters and '?' matches a single character.[br]
+ Wildcards are allowed only in the <nick> , <user> and <host> part: so the
+ "wildest" mask possible is:[br]
+ [b]*!*@*[/b][br]
+ that designates "any nickname, any username on any host".[br]
+ Here are some examples of wild masks:[br]
+ Pragma!*pragma@212.101.102.*: matches any user with nickname "Pragma" , username that ends with "pragma" and
+ coming from any machine on the 212.101.102 network.[br]
+ *!solo@*.starwars.org: matches any nick with username solo (no prefix!) coming from any machine in
+ the starwars.org domain.[br]
+ Pragma!*@*: matches any user with nickname "Pragma".[br]
+*/
+
+/*
+const char * KviIrcMask::setMask(const char *szMask,char c)
+{
+ __range_valid(szMask);
+ //nick!username@host.top
+ //0123456789
+ register const char *p=szMask;
+ //Run over nick....
+ while(*p && (*p != '!'))p++;
+ int len = p - szMask;
+ if(len > 0){
+ m_nick_ptr = (char *)kvi_realloc(m_nick_ptr,len+1);
+ kvi_memmove((void *)m_nick_ptr,(void *)szMask,len);
+ } else { //Empty nick...set it to "*"
+ len = 1;
+ m_nick_ptr = (char *)kvi_realloc(m_nick_ptr,len+1);
+ kvi_memmove((void *)m_nick_ptr,(void *)"*",len);
+ }
+ *(m_nick_ptr+len) = '\0'; //With zero length nick it will be just an empty-string
+ if(!(*p)){
+ setHost("*");
+ setUsername("*");
+ return p;
+ }
+ szMask = ++p;
+ //The username
+ while(*p && (*p != '@'))p++;
+ len = p - szMask;
+ if(len > 0){
+ m_user_ptr = (char *)kvi_realloc(m_user_ptr,len+1);
+ kvi_memmove((void *)m_user_ptr,(void *)szMask,len);
+ } else {
+ len = 1;
+ m_user_ptr = (char *)kvi_realloc(m_user_ptr,len+1);
+ kvi_memmove((void *)m_user_ptr,(void *)"*",len);
+ }
+ *(m_user_ptr+len) = '\0';
+ if(!(*p)){
+ setHost("*");
+ return p;
+ }
+ szMask = ++p;
+ //And finally the host
+ while(*p && (*p != c))p++;
+ len = p - szMask;
+ if(len > 0){
+ m_host_ptr = (char *)kvi_realloc(m_host_ptr,len+1);
+ kvi_memmove((void *)m_host_ptr,(void *)szMask,len);
+ } else {
+ len = 1;
+ m_host_ptr = (char *)kvi_realloc(m_host_ptr,len+1);
+ kvi_memmove((void *)m_host_ptr,(void *)"*",len);
+ }
+ *(m_host_ptr+len) = '\0';
+ return p;
+}
+
+const char * KviIrcMask::setUserhostMask(const char *szMask)
+{
+ __range_valid(szMask);
+ //nick[*]=<+!->username@host.top
+ //0123456789
+ register const char *p=szMask;
+ // Run over nick....
+ while(*p && (*p != '*') && (*p != '=') && (!isspace(*p)))p++;
+ // extract it
+ int len = p - szMask;
+ if(len > 0){
+ m_nick_ptr = (char *)kvi_realloc(m_nick_ptr,len+1);
+ kvi_memmove((void *)m_nick_ptr,(void *)szMask,len);
+ } else { //Empty nick...set it to "*"
+ len = 1;
+ m_nick_ptr = (char *)kvi_realloc(m_nick_ptr,len+1);
+ kvi_memmove((void *)m_nick_ptr,(void *)"*",len);
+ }
+ *(m_nick_ptr+len) = '\0'; //With zero length nick it will be just an empty-string
+ // now skip all the flags
+ while(*p && ((*p=='*')||(*p=='=')||(*p=='+')||(*p=='-')) && (!isspace(*p)))p++;
+ // check...
+ if((!(*p)) || isspace(*p)){
+ // ooops , finished or isspace
+ setHost("*");
+ setUsername("*");
+ while(*p && isspace(*p))p++;
+ return p;
+ }
+
+ szMask = p;
+ //The username
+ while(*p && (*p != '@') && (!isspace(*p)))p++;
+ len = p - szMask;
+ if(len > 0){
+ m_user_ptr = (char *)kvi_realloc(m_user_ptr,len+1);
+ kvi_memmove((void *)m_user_ptr,(void *)szMask,len);
+ } else {
+ len = 1;
+ m_user_ptr = (char *)kvi_realloc(m_user_ptr,len+1);
+ kvi_memmove((void *)m_user_ptr,(void *)"*",len);
+ }
+ *(m_user_ptr+len) = '\0';
+
+ if((!(*p))||isspace(*p)){
+ // oops finished or isspace
+ setHost("*");
+ while(*p && isspace(*p))p++;
+ return p;
+ }
+ szMask = ++p;
+ //And finally the host
+ while(*p && (!isspace(*p)))p++;
+ len = p - szMask;
+ if(len > 0){
+ m_host_ptr = (char *)kvi_realloc(m_host_ptr,len+1);
+ kvi_memmove((void *)m_host_ptr,(void *)szMask,len);
+ } else {
+ len = 1;
+ m_host_ptr = (char *)kvi_realloc(m_host_ptr,len+1);
+ kvi_memmove((void *)m_host_ptr,(void *)"*",len);
+ }
+ *(m_host_ptr+len) = '\0';
+ while(*p && isspace(*p))p++;
+ return p;
+}
+
+*/
+
+KviIrcMask::KviIrcMask()
+{
+ m_szHost = m_szWild;
+ m_szUser = m_szWild;
+ m_szNick = m_szWild;
+}
+
+KviIrcMask::KviIrcMask(const QString &szMask)
+{
+ static QString szWild("*");
+ const QChar * b = KviQString::nullTerminatedArray(szMask);
+ if(b)
+ {
+ const QChar * p = b;
+ while(p->unicode() && (p->unicode() != '!'))p++;
+ if(p->unicode())
+ {
+ if(p != b)
+ {
+ m_szNick.setUnicode(b,p-b);
+ } else {
+ m_szNick = szWild; // ???
+ }
+ } else {
+ if(p != b)m_szNick.setUnicode(b,p-b);
+ else m_szNick = szWild; // ???
+ m_szUser = szWild;
+ m_szHost = szWild;
+ return;
+ }
+ p++;
+ b = p;
+ while(p->unicode() && (p->unicode() != '@'))p++;
+ if(p->unicode())
+ {
+ if(p != b)
+ {
+ m_szUser.setUnicode(b,p-b);
+ } else {
+ m_szUser = szWild; // ???
+ }
+ } else {
+ if(p != b)m_szUser.setUnicode(b,p-b);
+ else m_szUser = szWild; // ???
+ m_szHost = szWild;
+ return;
+ }
+ p++;
+ b=p;
+ while(p->unicode())p++;
+ if(p != b)
+ {
+ m_szHost.setUnicode(b,p-b);
+ } else {
+ m_szHost = szWild; // ???
+ }
+
+ } else {
+ m_szUser = szWild;
+ m_szHost = szWild;
+ m_szNick = szWild;
+ }
+}
+
+QString KviIrcMask::m_szWild("*");
+
+bool KviIrcMask::hasNumericHost() const
+{
+ const QChar * p = KviQString::nullTerminatedArray(m_szHost);
+ if(!p)return false;
+ int nPoints = 0;
+ int nDoublePoints = 0;
+ unsigned short uc;
+ while((uc = p->unicode()))
+ {
+ if(uc == '.')nPoints++; // ipv6 masks can contain dots too!
+ else {
+ if(uc == ':')nDoublePoints++;
+ else {
+ if((uc < '0') || (uc > '9'))
+ {
+#ifdef COMPILE_USE_QT4
+ uc = p->toUpper().unicode();
+#else
+ uc = p->upper().unicode();
+#endif
+ if((uc < 'A') || (uc > 'F'))return false;
+ }
+ }
+ }
+ p++;
+ }
+ return ((nPoints == 3) || (nDoublePoints > 1));
+}
+
+
+/**
+* Retuns in szMask the specified (if possible) mask of this user.<br>
+* If the host or username are not known , the mask may contain less information
+* than requested.<br>
+* Mask types:<br>
+* 0 : nick!user@machine.host.top (nick!user@XXX.XXX.XXX.XXX) (default)<br>
+* 1 : nick!user@*.host.top (nick!user@XXX.XXX.XXX.*)<br>
+* 2 : nick!user@*<br>
+* 3 : nick!*@machine.host.top (nick!user@XXX.XXX.XXX.XXX)<br>
+* 4 : nick!*@*.host.top (nick!user@XXX.XXX.XXX.*)<br>
+* 5 : nick!*@*<br>
+* 6 : *!user@machine.host.top (*!user@XXX.XXX.XXX.XX)<br>
+* 7 : *!user@*.host.top (*!user@XXX.XXX.XXX.*)<br>
+* 8 : *!user@*<br>
+* 9 : *!*@machine.host.top (*!*@XXX.XXX.XXX.XXX)<br>
+* 10: *!*@*.host.top (*!*@XXX.XXX.XXX.*)<br>
+* 11: nick!*user@machine.host.top (nick!*user@machine.host.top)<br>
+* 12: nick!*user@*.host.top (nick!*user@*.host.top)<br>
+* 13: nick!*user@*<br>
+* 14: *!*user@machine.host.top (*!*user@machine.host.top)<br>
+* 15: *!*user@*.host.top (*!*user@*.host.top)<br>
+* 16: *!*user@*<br>
+* 17: nick!~user@*.host.top (nick!~user@XXX.XXX.*)
+* 18: nick!*@*.host.top (nick!*@XXX.XXX.*)
+* 19: *!~user@*.host.top (*!~user@XXX.XXX.*)
+* 20: nick!*user@*.host.top (nick!*user@XXX.XXX.*)
+* 21: *!*user@*.host.top (*!user@*XXX.XXX.*)
+* smart versions of the masks 17-21 that try take care of masked ip addresses
+* in the form xxx.xxx.INVALID-TOP-MASK
+* 22: nick!~user@*.host.top (nick!~user@XXX.XXX.*)
+* 23: nick!*@*.host.top (nick!*@XXX.XXX.*)
+* 24: *!~user@*.host.top (*!~user@XXX.XXX.*)
+* 25: nick!*user@*.host.top (nick!*user@XXX.XXX.*)
+* 26: *!*user@*.host.top (*!user@*XXX.XXX.*)
+* If some data is missing , these types may change:<br>
+* For example , if hostname is missing , the mask type 3 or 4 may be reduced to type 5
+*/
+
+/*
+** ident is fun.. ahem
+** prefixes used:
+** none I line with ident
+** ^ I line with OTHER type ident
+** ~ I line, no ident
+** + i line with ident
+** = i line with OTHER type ident
+** - i line, no ident
+*/
+
+static unsigned char maskTable[27][3] = {
+ { 0 , 0 , 0 }, //0 means normal block
+ { 0 , 0 , 2 }, //2 in the third field means type *.abc.host.top (or XXX.XXX.XXX.*) host mask
+ { 0 , 0 , 1 }, //2 in the second field means *user (strip prefixes)
+ { 0 , 1 , 0 }, //1 means *
+ { 0 , 1 , 2 }, //3 in the third field means type *.host.top (or XXX.XXX.*) host mask
+ { 0 , 1 , 1 }, //4 in the third field is like 3 but tries to detect masked ip addresses too
+ { 1 , 0 , 0 },
+ { 1 , 0 , 2 },
+ { 1 , 0 , 1 },
+ { 1 , 1 , 0 },
+ { 1 , 1 , 2 },
+ { 0 , 2 , 0 },
+ { 0 , 2 , 2 },
+ { 0 , 2 , 1 },
+ { 1 , 2 , 0 },
+ { 1 , 2 , 2 },
+ { 1 , 2 , 1 },
+ { 0 , 0 , 3 },
+ { 0 , 1 , 3 },
+ { 1 , 0 , 3 },
+ { 0 , 2 , 3 },
+ { 1 , 2 , 3 },
+ { 0 , 0 , 4 },
+ { 0 , 1 , 4 },
+ { 1 , 0 , 4 },
+ { 0 , 2 , 4 },
+ { 1 , 2 , 4 }
+};
+
+void KviIrcMask::mask(QString &szMask,MaskType eMaskType) const
+{
+ if((((int)eMaskType) > 26)||(((int)eMaskType) < 0))eMaskType = NickUserHost;
+ szMask = maskTable[((int)eMaskType)][0] ? m_szWild : m_szNick;
+ szMask.append("!");
+ switch(maskTable[((int)eMaskType)][1])
+ {
+ case 0:
+ szMask.append(m_szUser);
+ break;
+ case 1:
+ szMask.append(m_szWild);
+ break;
+ default:
+ if (m_szUser.length() > 0) {
+ if(m_szUser[0].unicode() != '*')
+ szMask.append(m_szWild);
+ if ((m_szUser[0].unicode() == '~') ||
+ (m_szUser[0].unicode() == '^') ||
+ (m_szUser[0].unicode() == '+') ||
+ (m_szUser[0].unicode() == '-') ||
+ (m_szUser[0].unicode() == '='))szMask.append(m_szUser.right(m_szUser.length() - 1));
+ else
+ szMask.append(m_szUser);
+ }
+ break;
+ }
+ szMask.append('@');
+ switch(maskTable[((int)eMaskType)][2])
+ {
+ case 0:
+ szMask.append(m_szHost);
+ break;
+ case 1:
+ szMask.append(m_szWild);
+ break;
+ case 2:
+ if(m_szHost != m_szWild)
+ {
+ if(hasNumericHost())
+ {
+ QString szHost(m_szHost.left(getIpDomainMaskLen()));
+ szMask.append(szHost);
+ szMask.append(m_szWild);
+ } else {
+ szMask.append(m_szWild);
+ szMask.append(getHostDomainMask());
+ }
+ } else {
+ szMask.append(m_szWild);
+ }
+ break;
+ case 3:
+ if(m_szHost != m_szWild)
+ {
+ if(hasNumericHost())
+ {
+ QString szHost(m_szHost.left(getLargeIpDomainMaskLen()));
+ szMask.append(szHost);
+ szMask.append(m_szWild);
+ } else {
+ szMask.append(m_szWild);
+ szMask.append(getLargeHostDomainMask());
+ }
+ } else {
+ szMask.append(m_szWild);
+ }
+ break;
+ default: // case 4 and others
+ if(m_szHost != m_szWild)
+ {
+ if(hasNumericHost() || hasMaskedIp())
+ {
+ QString szHost(m_szHost.left(getLargeIpDomainMaskLen()));
+ szMask.append(szHost);
+ szMask.append(m_szWild);
+ } else {
+ szMask.append(m_szWild);
+ szMask.append(getLargeHostDomainMask());
+ }
+ } else {
+ szMask.append(m_szWild);
+ }
+ break;
+ }
+}
+
+
+/*
+bool KviIrcMask::matches(const char *szMask)
+{
+ const char * ret1;
+ const char * ret2;
+
+ if(kvi_matchWildExprWithTerminator(szMask,m_nick_ptr,'!',&ret1,&ret2))
+ {
+ if(*ret1 == '!')
+ {
+ ret1++;
+ if(kvi_matchWildExprWithTerminator(ret1,m_user_ptr,'@',&ret1,&ret2))
+ {
+ if(*ret1 == '@')
+ {
+ ret1++;
+ return kvi_matchWildExpr(ret1,m_host_ptr);
+ }
+ }
+ }
+ }
+ return false;
+}
+*/
+
+/*
+bool KviIrcMask::matchesFixed(const char *szMask) const
+{
+ const char * ret1;
+ const char * ret2;
+
+ if(kvi_matchStringWithTerminator(m_nick_ptr,szMask,'!',&ret1,&ret2))
+ {
+ if(*ret2 == '!')
+ {
+ ret2++;
+ if(kvi_matchStringWithTerminator(m_user_ptr,ret2,'@',&ret1,&ret2))
+ {
+ if(*ret2 == '@')
+ {
+ ret2++;
+ return kvi_matchString(m_host_ptr,ret2);
+ }
+ }
+ }
+ }
+ return false;
+}
+*/
+
+/*
+bool KviIrcMask::matchedBy(const QString &szMask) const
+{
+ const char * ret1;
+ const char * ret2;
+
+ if(kvi_matchStringWithTerminator(szMask,m_nick_ptr,'!',&ret1,&ret2))
+ {
+ if(*ret1 == '!')
+ {
+ ret1++;
+ if(kvi_matchStringWithTerminator(ret1,m_user_ptr,'@',&ret1,&ret2))
+ {
+ if(*ret1 == '@')
+ {
+ ret1++;
+ return kvi_matchString(ret1,m_host_ptr);
+ }
+ }
+ }
+ }
+ return false;
+}
+*/
+
+bool KviIrcMask::matches(const KviIrcMask &mask) const
+{
+ if(KviQString::matchWildExpressionsCI(m_szNick,mask.m_szNick))
+ {
+ if(KviQString::matchWildExpressionsCI(m_szUser,mask.m_szUser))
+ {
+ if(KviQString::matchWildExpressionsCI(m_szHost,mask.m_szHost))return true;
+ }
+ }
+ return false;
+}
+
+bool KviIrcMask::matchesFixed(const KviIrcMask &mask) const
+{
+ if(KviQString::matchStringCI(m_szNick,mask.m_szNick,0,1))
+ {
+ if(KviQString::matchStringCI(m_szUser,mask.m_szUser,0,1))
+ {
+ if(KviQString::matchStringCI(m_szHost,mask.m_szHost,0,1))return true;
+ }
+ }
+ return false;
+}
+
+/*
+bool KviIrcMask::matches(const char * nick,const char * user,const char * host)
+{
+ if(nick)
+ {
+ if(!kvi_matchWildExpr(m_nick_ptr,nick))return false;
+ }
+
+ if(user)
+ {
+ if(!kvi_matchWildExpr(m_user_ptr,user))return false;
+ }
+
+ if(host)
+ {
+ if(!kvi_matchWildExpr(m_host_ptr,host))return false;
+ }
+ return true;
+}
+*/
+
+bool KviIrcMask::matchesFixed(const QString &nick,const QString &user,const QString &host) const
+{
+ if(!KviQString::matchStringCI(m_szNick,nick,0,1))return false;
+ if(!KviQString::matchStringCI(m_szUser,user,0,1))return false;
+ if(!KviQString::matchStringCI(m_szHost,host,0,1))return false;
+ return true;
+}
+
+//Internals for mask()
+
+int KviIrcMask::getIpDomainMaskLen() const
+{
+ int len = m_szHost.length();
+ const QChar *p = m_szHost.unicode();
+ const QChar *b = p;
+ p += len;
+ if(b < p)
+ {
+ p--;
+ while((b < p) && (p->unicode() != '.') && (p->unicode() != ':'))p--;
+ }
+ // 000.000.000.000
+ // p
+ //
+ return (p == b) ? 0 : ((p-b) + 1);
+}
+
+
+int KviIrcMask::getLargeIpDomainMaskLen() const
+{
+ int len = m_szHost.length();
+ const QChar *p = m_szHost.unicode();
+ const QChar *b = p;
+ p += len;
+ if(b < p)
+ {
+ p--;
+ while((b < p) && (p->unicode() != '.') && (p->unicode() != ':'))p--;
+ if(b < p)
+ {
+ p--;
+ while((b < p) && (p->unicode() != '.') && (p->unicode() != ':'))p--;
+ }
+ }
+ // 000.000.000.000
+ // p
+ //
+ return (p == b) ? 0 : ((p-b) + 1);
+}
+
+QString KviIrcMask::getHostDomainMask() const
+{
+ int len = m_szHost.length();
+ const QChar *p=KviQString::nullTerminatedArray(m_szHost);
+ if(!p)return QString::null;
+ const QChar *b = p;
+ while(p->unicode() && p->unicode() != '.')p++;
+ QString ret(p,len - (p - b));
+ return ret;
+}
+
+
+QString KviIrcMask::getLargeHostDomainMask() const
+{
+ int len = m_szHost.length();
+ const QChar *p = m_szHost.unicode();
+ const QChar *b = p;
+ p += len;
+
+ if(b < p)
+ {
+ p--;
+ while((b < p) && (p->unicode() != '.'))p--;
+ if(b < p)
+ {
+ p--;
+ while((b < p) && (p->unicode() != '.'))p--;
+ }
+ }
+
+ // xyz.klm.abc.host.top
+ // p
+
+ QString ret(p,len - (p - b));
+ return ret;
+}
+
+// this is just a GUESS and must be called AFTER making sure that it is NOT a plain numeric IP
+bool KviIrcMask::hasMaskedIp() const
+{
+ int len = m_szHost.length();
+ const QChar *p = m_szHost.unicode();
+ const QChar *b = p;
+ if(len == 0)return false;
+ //run to the end
+ p += len;
+ const QChar *e = p;
+ p--;
+ while((b < p) && (p->unicode() != '.'))p--;
+ return ((e - p) > 4); // at the moment 4 should be enough : the largest top part is "name"
+}
+
+
+bool KviIrcMask::operator==(const KviIrcMask &user)
+{
+ if(KviQString::equalCI(m_szNick,user.m_szNick))
+ {
+ if(KviQString::equalCI(m_szUser,user.m_szUser))
+ {
+ if(KviQString::equalCI(m_szHost,user.m_szHost))return true;
+ }
+ }
+ return false;
+}
+
+bool KviIrcMask::hasWildNick()
+{
+ const QChar * aux = KviQString::nullTerminatedArray(m_szNick);
+ if(!aux)return false;
+ unsigned short uc;
+ while((uc = aux->unicode()))
+ {
+ if((uc == '*') || (uc == '?'))return true;
+ aux++;
+ }
+ return false;
+}
+
+int KviIrcMask::nonWildChars()
+{
+ int iCnt = 0;
+ const QChar * aux = KviQString::nullTerminatedArray(m_szNick);
+ if(!aux)return 0;
+ unsigned short uc;
+
+ while((uc = aux->unicode()))
+ {
+ if((uc != '*') && (uc != '?'))iCnt++;
+ aux++;
+ }
+
+ aux = KviQString::nullTerminatedArray(m_szUser);
+ while((uc = aux->unicode()))
+ {
+ if((uc != '*') && (uc != '?'))iCnt++;
+ aux++;
+ }
+
+
+ aux = KviQString::nullTerminatedArray(m_szHost);
+ while((uc = aux->unicode()))
+ {
+ if((uc != '*') && (uc != '?'))iCnt++;
+ aux++;
+ }
+ return iCnt;
+}
diff --git a/src/kvilib/irc/kvi_ircmask.h b/src/kvilib/irc/kvi_ircmask.h
new file mode 100644
index 00000000..3c9ccf5d
--- /dev/null
+++ b/src/kvilib/irc/kvi_ircmask.h
@@ -0,0 +1,164 @@
+#ifndef _KVI_IRCMASK_H_
+#define _KVI_IRCMASK_H_
+
+//=============================================================================
+//
+// File : kvi_ircmask.h
+// Creation date : Fri Jan 8 1999 19:50:35 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+// originally this file was named kvi_ircuser.h and the class was KviIrcUser
+// ported to UNICODE on 2004.10.28 1:50 am
+
+#include "kvi_settings.h"
+#include "kvi_heapobject.h"
+#include "kvi_qstring.h"
+
+//=============================================================================
+// Irc user mask abstraction
+//=============================================================================
+
+class KVILIB_API KviIrcMask : public KviHeapObject
+{
+ friend class KviIrcUserList;
+ friend class KviIrcUserChanList;
+private:
+ QString m_szNick;
+ QString m_szUser;
+ QString m_szHost;
+ static QString m_szWild;
+public:
+ // Sets the nick for this user.<br>
+ // If szNick is NULL or it points to an empty string the nick is set to "*".<br>
+ void setNick(const QString &szNick){ m_szNick = szNick.isEmpty() ? m_szWild : szNick; };
+ // Sets the username for this user.<br>
+ // If szUsername is NULL or it points to an empty string the username is set to "*".<br>
+ void setUsername(const QString &szUser){ m_szUser = szUser.isEmpty() ? m_szWild : szUser; };
+ void setUser(const QString &szUser){ m_szUser = szUser.isEmpty() ? m_szWild : szUser; };
+ // Sets the host for this user.<br>
+ // If szHost is NULL or it points to an empty string the host is set to "*".<br>
+ void setHost(const QString &szHost){ m_szHost = szHost.isEmpty() ? m_szWild : szHost; };
+ // Sets the host , nick and username extracting it from an irc mask:<br>
+ // nick!user@host<br>
+ // The mask is terminated by end-of string null character or a character equal to c in the string.<br>
+ // Returns the pointer to the end of the mask in the szMask string.(c or null-terminator)<br>
+ //const char * setMask(const QString &szMask,char c=' ');
+ // Sets the host , nick and username extracting it from an userhost mask:<br>
+ // nick[*]=<+|->user@host<br>
+ // The mask is terminated by end-of string null char or a space character.<br>
+ // Returns the pointer to the next non-space char in the szMask string or to the null-terminator<br>
+ // If there are no more masks avaiable.
+ // WARNING : the szMask pointer can NOT be NULL
+ //const char *setUserhostMask(const QString &szMask);
+ // Returns the nick of this user.<br>
+ // In the worst case you get a string == "*"<br>
+ const QString &nick() const { return m_szNick; };
+ // DEPRECATED!
+ const QString &username() const { return m_szUser; };
+ const QString &user() const { return m_szUser; };
+ const QString &host() const { return m_szHost; };
+
+ bool hasUser() const { return !(m_szUser.isEmpty() || (m_szUser == m_szWild)); };
+ bool hasHost() const { return !(m_szHost.isEmpty() || (m_szHost == m_szWild)); };
+
+ bool hasNumericHost() const;
+ // Retuns in szMask the specified (if possible) mask of this user.<br>
+ // If the host or username are not known , the mask may contain less information
+ // than requested.<br>
+
+ enum MaskType
+ {
+ NickUserHost = 0, // nick!~user@machine.host.top (nick!~user@XXX.XXX.XXX.XXX) (default)
+ NickUserNet = 1, // 1 : nick!~user@*.abc.host.top (nick!~user@XXX.XXX.XXX.*)
+ NickUser = 2, // 2 : nick!~user@*
+ NickHost = 3, // 3 : nick!*@machine.host.top (nick!*@XXX.XXX.XXX.XXX)
+ NickNet = 4, // 4 : nick!*@*.abc.host.top (nick!*@XXX.XXX.XXX.*)
+ Nick = 5, // 5 : nick!*@*
+ UserHost = 6, // 6 : *!~user@machine.host.top (*!~user@XXX.XXX.XXX.XXX)
+ UserNet = 7, // 7 : *!~user@*.abc.host.top (*!~user@XXX.XXX.XXX.*)
+ User = 8, // 8 : *!~user@*
+ Host = 9, // 9 : *!*@machine.host.top (*!*@XXX.XXX.XXX.XXX)
+ Net = 10, // 10: *!*@*.abc.host.top (*!*@XXX.XXX.XXX.*)
+ NickCleanUserHost = 11, // 11 : nick!*user@machine.host.top (nick!*user@XXX.XXX.XXX.XXX)
+ NickCleanUserNet = 12, // 12 : nick!*user@*.abc.host.top (nick!*user@XXX.XXX.XXX.*)
+ NickCleanUser = 13, // 13 : nick!*user@*
+ CleanUserHost = 14, // 14 : *!*user@machine.host.top (*!user@*XXX.XXX.XXX.XXX)
+ CleanUserNet = 15, // 15 : *!*user@*.abc.host.top (*!user@*XXX.XXX.XXX.*)
+ CleanUser = 16, // 16 : *!*user@*
+ NickUserLargeNet = 17, // 17 : nick!~user@*.host.top (nick!~user@XXX.XXX.*)
+ NickLargeNet = 18, // 18 : nick!*@*.host.top (nick!*@XXX.XXX.*)
+ UserLargeNet = 19, // 19 : *!~user@*.host.top (*!~user@XXX.XXX.*)
+ NickCleanUserLargeNet = 20, // 20 : nick!*user@*.host.top (nick!*user@XXX.XXX.*)
+ CleanUserLargeNet = 21, // 21 : *!*user@*.host.top (*!user@*XXX.XXX.*)
+ // smart versions of the masks 17-21 that try take care of masked ip addresses
+ // in the form xxx.xxx.INVALID-TOP-MASK
+ NickUserSmartNet = 22, // 22 : nick!~user@*.host.top (nick!~user@XXX.XXX.*)
+ NickSmartNet = 23, // 23 : nick!*@*.host.top (nick!*@XXX.XXX.*)
+ UserSmartNet = 24, // 24 : *!~user@*.host.top (*!~user@XXX.XXX.*)
+ NickCleanUserSmartNet = 25, // 25 : nick!*user@*.host.top (nick!*user@XXX.XXX.*)
+ CleanUserSmartNet = 26 // 26 : *!*user@*.host.top (*!user@*XXX.XXX.*)
+ };
+
+ void mask(QString &szMask,MaskType eMaskType = NickCleanUserHost) const;
+ bool hasWildNick();
+
+ // Wild external matches (this and external are wild)
+
+// bool matches(const char *szMask);
+// // passing 0 as one of params here means that it is a match by default
+// bool matches(const char *nick,const char *user,const char *host);
+ bool matches(const KviIrcMask &mask) const;
+
+
+ // Fixed external matches (this is wild , external is fixed)
+ bool matchesFixed(const QString &nick,const QString &user,const QString &host) const;
+// bool matchesFixed(const QString &szMask) const;
+ bool matchesFixed(const KviIrcMask &mask) const;
+
+ // Fixed internal matches (this is fixed , external is wild)
+ //bool matchedBy(const QString &szMask) const;
+ bool matchedBy(const KviIrcMask &mask) const { return mask.matchesFixed(*this); };
+
+ int nonWildChars();
+ bool operator==(const KviIrcMask &user);
+public:
+ // Constructs an empty mask (*!*@*)
+ KviIrcMask();
+ // Constructs this KviIrcMask object from a string mask
+ KviIrcMask(const QString &szMask);
+ // Carbon copy
+ KviIrcMask(const KviIrcMask &ircUser)
+ : m_szNick(ircUser.m_szNick), m_szUser(ircUser.m_szUser), m_szHost(ircUser.m_szHost) {};
+ KviIrcMask(const QString &nick,const QString &user,const QString &host)
+ : m_szNick(nick), m_szUser(user), m_szHost(host) {};
+private:
+ int getIpDomainMaskLen() const;
+ QString getHostDomainMask() const;
+ int getLargeIpDomainMaskLen() const;
+ QString getLargeHostDomainMask() const;
+ // this is just a GUESS and must be called AFTER making sure that it is NOT a plain numeric IP
+ bool hasMaskedIp() const;
+};
+
+
+
+
+#endif //_KVI_IRCMASK_H_
diff --git a/src/kvilib/irc/kvi_ircserver.cpp b/src/kvilib/irc/kvi_ircserver.cpp
new file mode 100644
index 00000000..5f03fb5e
--- /dev/null
+++ b/src/kvilib/irc/kvi_ircserver.cpp
@@ -0,0 +1,373 @@
+//=============================================================================
+//
+// File : kvi_ircserver.cpp
+// Creation date : Mon Jul 10 2000 03:42:59 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+
+#include "kvi_ircserver.h"
+#include "kvi_malloc.h"
+
+#include "kvi_config.h"
+#include "kvi_nickserv.h"
+#include "kvi_time.h"
+#include "kvi_proxydb.h"
+#include <stdlib.h>
+
+// This is not allowed on windows unless we force the symbol to be undefined
+// It works on linux since gcc allows undefined symbols by default
+// but it is also "theoretically" wrong:
+// kvilib is not linked to kvirc: it's kvirc being linked to kvilib
+// thus kvilib should not depend on symbols defined in the kvirc core.
+// We must find another way to do that (like having just the id and finding
+// the proxy in the kvirc core, or just passing the pointer to the db from outside).
+// Pragma
+
+//extern KVIRC_API KviProxyDataBase * g_pProxyDataBase;
+
+// FIXME: This should be renamed to KviServer or sth like that
+KviIrcServer::KviIrcServer()
+{
+ m_pReconnectInfo=0;
+ m_uFlags = 0;
+ m_uPort = 6667;
+ m_pChannelList = 0;
+ m_bAutoConnect = false;
+ m_iProxy = -1;
+}
+
+KviProxy* KviIrcServer::proxyServer(KviProxyDataBase * pDb)
+{
+ int i=0;
+ if(proxy()<0) return 0;
+ KviPointerList<KviProxy> * proxylist = pDb->proxyList();
+ for(KviProxy * p = proxylist->first();p;p = proxylist->next())
+ {
+ if(i==proxy()) return p;
+ i++;
+ }
+ return 0;
+}
+
+KviIrcServer::KviIrcServer(const KviIrcServer &serv)
+{
+ m_pReconnectInfo = 0;
+ m_szHostname = serv.m_szHostname;
+ m_szIp = serv.m_szIp;
+ m_szDescription = serv.m_szDescription;
+ m_szUser = serv.m_szUser;
+ m_szPass = serv.m_szPass;
+ m_uPort = serv.m_uPort;
+ m_szNick = serv.m_szNick;
+ m_szRealName = serv.m_szRealName;
+ m_szEncoding = serv.m_szEncoding;
+ m_uFlags = serv.m_uFlags;
+ m_szInitUMode = serv.m_szInitUMode;
+ m_szOnConnectCommand = serv.m_szOnConnectCommand;
+ m_szOnLoginCommand = serv.m_szOnLoginCommand;
+ m_szLinkFilter = serv.m_szLinkFilter;
+ m_szId = serv.m_szId;
+ m_iProxy = serv.m_iProxy;
+ m_szUserIdentityId = serv.m_szUserIdentityId;
+ if(serv.m_pChannelList)
+ m_pChannelList = new QStringList(*(serv.m_pChannelList));
+ else m_pChannelList = 0;
+ m_bAutoConnect = serv.m_bAutoConnect;
+}
+
+void KviIrcServer::operator=(const KviIrcServer &serv)
+{
+ m_szHostname = serv.m_szHostname;
+ m_szIp = serv.m_szIp;
+ m_szDescription = serv.m_szDescription;
+ m_szUser = serv.m_szUser;
+ m_szPass = serv.m_szPass;
+ m_uPort = serv.m_uPort;
+ m_szNick = serv.m_szNick;
+ m_szRealName = serv.m_szRealName;
+ m_szEncoding = serv.m_szEncoding;
+ m_uFlags = serv.m_uFlags;
+ m_szInitUMode = serv.m_szInitUMode;
+ m_szOnConnectCommand = serv.m_szOnConnectCommand;
+ m_szOnLoginCommand = serv.m_szOnLoginCommand;
+ m_szLinkFilter = serv.m_szLinkFilter;
+ m_szId = serv.m_szId;
+ m_szUserIdentityId = serv.m_szUserIdentityId;
+ m_iProxy = serv.m_iProxy;
+ if(m_pChannelList)delete m_pChannelList;
+ if(serv.m_pChannelList)
+ m_pChannelList = new QStringList(*(serv.m_pChannelList));
+ else m_pChannelList = 0;
+ m_bAutoConnect = serv.m_bAutoConnect;
+}
+
+
+KviIrcServer::~KviIrcServer()
+{
+ if(m_pChannelList)delete m_pChannelList;
+ if(m_pReconnectInfo) delete m_pReconnectInfo;
+}
+
+void KviIrcServer::generateUniqueId()
+{
+ struct timeval tv;
+ kvi_gettimeofday(&tv,0);
+ KviQString::sprintf(m_szId,"myserver%d%d%d",tv.tv_usec,rand() % 1000,rand() % 1000);
+}
+
+QString KviIrcServer::ircUri()
+{
+ QString uri("irc");
+ if(useSSL())uri += "s";
+ if(isIpV6())uri += "6";
+ uri += "://";
+ uri += m_szHostname;
+
+ if(m_uPort!=6667)
+ {
+ uri += ":";
+ QString num;
+ num.setNum(m_uPort);
+ uri += num;
+ }
+ return uri;
+}
+
+void KviIrcServer::setAutoJoinChannelList(QStringList * pNewChannelList)
+{
+ if(m_pChannelList)delete m_pChannelList;
+ m_pChannelList = pNewChannelList;
+}
+
+
+bool KviIrcServer::load(KviConfig * cfg,const QString &prefix)
+{
+ QString tmp;
+ KviQString::sprintf(tmp,"%QHostname",&prefix);
+ m_szHostname = cfg->readQStringEntry(tmp);
+ KviQString::sprintf(tmp,"%QIp",&prefix);
+ m_szIp = cfg->readQStringEntry(tmp);
+ if(m_szHostname.isEmpty() && m_szIp.isEmpty())return false;
+ KviQString::sprintf(tmp,"%QDescription",&prefix);
+ m_szDescription = cfg->readQStringEntry(tmp);
+ KviQString::sprintf(tmp,"%QUser",&prefix);
+ m_szUser = cfg->readQStringEntry(tmp);
+ KviQString::sprintf(tmp,"%QPass",&prefix);
+ m_szPass = cfg->readQStringEntry(tmp);
+ KviQString::sprintf(tmp,"%QNick",&prefix);
+ m_szNick = cfg->readQStringEntry(tmp);
+ KviQString::sprintf(tmp,"%QRealName",&prefix);
+ m_szRealName = cfg->readQStringEntry(tmp);
+ KviQString::sprintf(tmp,"%QInitUmode",&prefix);
+ m_szInitUMode = cfg->readQStringEntry(tmp);
+ KviQString::sprintf(tmp,"%QAutoJoinChannels",&prefix);
+ QStringList l = cfg->readStringListEntry(tmp,QStringList());
+ if(l.count() > 0)setAutoJoinChannelList(new QStringList(l));
+ KviQString::sprintf(tmp,"%QAutoConnect",&prefix);
+ m_bAutoConnect = cfg->readBoolEntry(tmp,false);
+ KviQString::sprintf(tmp,"%QEncoding",&prefix);
+ m_szEncoding = cfg->readQStringEntry(tmp);
+ KviQString::sprintf(tmp,"%QOnConnectCommand",&prefix);
+ m_szOnConnectCommand = cfg->readQStringEntry(tmp);
+ KviQString::sprintf(tmp,"%QOnLoginCommand",&prefix);
+ m_szOnLoginCommand = cfg->readQStringEntry(tmp);
+ KviQString::sprintf(tmp,"%QLinkFilter",&prefix);
+ m_szLinkFilter = cfg->readQStringEntry(tmp);
+ KviQString::sprintf(tmp,"%QPort",&prefix);
+ m_uPort = cfg->readUIntEntry(tmp,6667);
+ KviQString::sprintf(tmp,"%QId",&prefix);
+ m_szId = cfg->readQStringEntry(tmp);
+ if(m_szId.isEmpty())generateUniqueId();
+ KviQString::sprintf(tmp,"%QIpV6",&prefix);
+ setIpV6(cfg->readBoolEntry(tmp,false));
+ KviQString::sprintf(tmp,"%QCacheIp",&prefix);
+ setCacheIp(cfg->readBoolEntry(tmp,false)); // true ?
+ KviQString::sprintf(tmp,"%QSSL",&prefix);
+ setUseSSL(cfg->readBoolEntry(tmp,false));
+ KviQString::sprintf(tmp,"%QProxy",&prefix);
+ setProxy(cfg->readIntEntry(tmp,-2));
+ KviQString::sprintf(tmp,"%QUserIdentityId",&prefix);
+ m_szUserIdentityId = cfg->readQStringEntry(tmp);
+ return true;
+}
+
+void KviIrcServer::save(KviConfig * cfg,const QString &prefix)
+{
+ QString tmp;
+ KviQString::sprintf(tmp,"%QHostname",&prefix);
+ cfg->writeEntry(tmp,m_szHostname);
+ KviQString::sprintf(tmp,"%QId",&prefix);
+ cfg->writeEntry(tmp,m_szId);
+ if(!m_szIp.isEmpty())
+ {
+ KviQString::sprintf(tmp,"%QIp",&prefix);
+ cfg->writeEntry(tmp,m_szIp);
+ }
+ if(!m_szDescription.isEmpty())
+ {
+ KviQString::sprintf(tmp,"%QDescription",&prefix);
+ cfg->writeEntry(tmp,m_szDescription);
+ }
+ if(!m_szUser.isEmpty())
+ {
+ KviQString::sprintf(tmp,"%QUser",&prefix);
+ cfg->writeEntry(tmp,m_szUser);
+ }
+ if(!m_szPass.isEmpty())
+ {
+ KviQString::sprintf(tmp,"%QPass",&prefix);
+ cfg->writeEntry(tmp,m_szPass);
+ }
+ if(!m_szNick.isEmpty())
+ {
+ KviQString::sprintf(tmp,"%QNick",&prefix);
+ cfg->writeEntry(tmp,m_szNick);
+ }
+ if(!m_szRealName.isEmpty())
+ {
+ KviQString::sprintf(tmp,"%QRealName",&prefix);
+ cfg->writeEntry(tmp,m_szRealName);
+ }
+ if(!m_szInitUMode.isEmpty())
+ {
+ KviQString::sprintf(tmp,"%QInitUMode",&prefix);
+ cfg->writeEntry(tmp,m_szInitUMode);
+ }
+ if(autoJoinChannelList())
+ {
+ KviQString::sprintf(tmp,"%QAutoJoinChannels",&prefix);
+ cfg->writeEntry(tmp,*(autoJoinChannelList()));
+ }
+ if(autoConnect()) // otherwise it defaults to false anyway
+ {
+ KviQString::sprintf(tmp,"%QAutoConnect",&prefix);
+ cfg->writeEntry(tmp,autoConnect());
+ }
+ if(!m_szEncoding.isEmpty())
+ {
+ KviQString::sprintf(tmp,"%QEncoding",&prefix);
+ cfg->writeEntry(tmp,m_szEncoding);
+ }
+ if(!m_szOnConnectCommand.isEmpty())
+ {
+ KviQString::sprintf(tmp,"%QOnConnectCommand",&prefix);
+ cfg->writeEntry(tmp,m_szOnConnectCommand);
+ }
+ if(!m_szOnLoginCommand.isEmpty())
+ {
+ KviQString::sprintf(tmp,"%QOnLoginCommand",&prefix);
+ cfg->writeEntry(tmp,m_szOnLoginCommand);
+ }
+ if(!m_szLinkFilter.isEmpty())
+ {
+ KviQString::sprintf(tmp,"%QLinkFilter",&prefix);
+ cfg->writeEntry(tmp,m_szLinkFilter);
+ }
+ if(m_uPort != 6667)
+ {
+ KviQString::sprintf(tmp,"%QPort",&prefix);
+ cfg->writeEntry(tmp,m_uPort);
+ }
+ if(isIpV6())
+ {
+ KviQString::sprintf(tmp,"%QIpV6",&prefix);
+ cfg->writeEntry(tmp,isIpV6());
+ }
+ if(cacheIp())
+ {
+ KviQString::sprintf(tmp,"%QCacheIp",&prefix);
+ cfg->writeEntry(tmp,cacheIp());
+ }
+ if(useSSL())
+ {
+ KviQString::sprintf(tmp,"%QSSL",&prefix);
+ cfg->writeEntry(tmp,useSSL());
+ }
+ if(proxy()!=-2)
+ {
+ KviQString::sprintf(tmp,"%QProxy",&prefix);
+ cfg->writeEntry(tmp,proxy());
+ }
+ if(!m_szUserIdentityId.isEmpty())
+ {
+ KviQString::sprintf(tmp,"%QUserIdentityId",&prefix);
+ cfg->writeEntry(tmp,m_szUserIdentityId);
+ }
+}
+
+
+
+KviIrcNetwork::KviIrcNetwork(const KviIrcNetwork &src)
+{
+ m_pChannelList = 0;
+ m_pNickServRuleSet = 0;
+ copyFrom(src);
+}
+
+KviIrcNetwork::KviIrcNetwork(const QString &name)
+{
+ m_szName = name;
+ m_pChannelList = 0;
+ m_pNickServRuleSet = 0;
+ m_bAutoConnect = false;
+ // m_szEncoding = QString::null; // set by default
+}
+
+KviIrcNetwork::~KviIrcNetwork()
+{
+ if(m_pChannelList)delete m_pChannelList;
+ if(m_pNickServRuleSet)delete m_pNickServRuleSet;
+}
+
+void KviIrcNetwork::setAutoJoinChannelList(QStringList * pNewChannelList)
+{
+ if(m_pChannelList)delete m_pChannelList;
+ m_pChannelList = pNewChannelList;
+}
+
+void KviIrcNetwork::setNickServRuleSet(KviNickServRuleSet * s)
+{
+ if(m_pNickServRuleSet)delete m_pNickServRuleSet;
+ m_pNickServRuleSet = s;
+}
+
+
+void KviIrcNetwork::copyFrom(const KviIrcNetwork &src)
+{
+ m_szName = src.m_szName;
+ m_szEncoding = src.m_szEncoding;
+ m_szDescription = src.m_szDescription;
+ m_szNickName = src.m_szNickName;
+ m_szRealName = src.m_szRealName;
+ m_szUserName = src.m_szUserName;
+ m_bAutoConnect = src.m_bAutoConnect;
+ m_szUserIdentityId = src.m_szUserIdentityId;
+ m_szOnConnectCommand = src.m_szOnConnectCommand;
+ m_szOnLoginCommand = src.m_szOnLoginCommand;
+ if(m_pChannelList)delete m_pChannelList;
+ if(src.m_pChannelList)m_pChannelList = new QStringList(*(src.m_pChannelList));
+ else m_pChannelList = 0;
+ if(m_pNickServRuleSet)delete m_pNickServRuleSet;
+ if(src.m_pNickServRuleSet)m_pNickServRuleSet = new KviNickServRuleSet(*(src.m_pNickServRuleSet));
+ else m_pNickServRuleSet = 0;
+}
+
diff --git a/src/kvilib/irc/kvi_ircserver.h b/src/kvilib/irc/kvi_ircserver.h
new file mode 100644
index 00000000..4c0ca54d
--- /dev/null
+++ b/src/kvilib/irc/kvi_ircserver.h
@@ -0,0 +1,206 @@
+#ifndef _KVI_IRCSERVER_H_
+#define _KVI_IRCSERVER_H_
+
+//=============================================================================
+//
+// File : kvi_ircserver.h
+// Creation date : Mon Jul 10 2000 03:24:11 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_heapobject.h"
+#include "kvi_qstring.h"
+#include "kvi_pointerlist.h"
+
+#include <qstringlist.h>
+
+class KviConfig;
+class KviNickServRuleSet;
+class KviProxy;
+class KviProxyDataBase;
+class KviIrcServer;
+
+#define KVI_IRCSERVER_FLAG_IPV6 1
+#define KVI_IRCSERVER_FLAG_CACHEIP 2
+#define KVI_IRCSERVER_FLAG_SSL 4
+
+class KVILIB_API KviIrcServerReconnectInfo {
+public:
+ QString m_szNick;
+ QString m_szAwayReason;
+ QString m_szJoinChannels;
+ QStringList m_szOpenQueryes;
+ bool m_bIsAway;
+};
+
+class KVILIB_API KviIrcServer : public KviHeapObject
+{
+public:
+ KviIrcServer();
+ KviIrcServer(const KviIrcServer &serv);
+ ~KviIrcServer();
+public:
+ KviIrcServerReconnectInfo *m_pReconnectInfo;
+ QString m_szHostname; // the server hostname (or ip eventually)
+ QString m_szIp; // the server's cached ip (if we're caching)
+ QString m_szDescription; // the server description
+ kvi_u32_t m_uPort; // the server's port
+ unsigned short int m_uFlags; // flags
+
+ // Extended data
+ QString m_szUserIdentityId; // The user identity to use for this server: if empty
+ // Then use the network identity instead
+
+ QString m_szUser; // special username
+ QString m_szPass; // special password
+ QString m_szNick; // special nickname
+ QString m_szRealName; // special real name
+ QString m_szInitUMode; // special user mode
+ QString m_szOnConnectCommand; // the command to run on connect
+ QString m_szOnLoginCommand; // the command to run after login
+ QString m_szLinkFilter; // the link filter object
+ QString m_szEncoding; // if empty, use network encoding
+ QStringList * m_pChannelList; // Channels to auto join
+ bool m_bAutoConnect; // autoconnect
+ QString m_szId; // the server's may-be-unique id, may be auto-generated
+ int m_iProxy; // proxy server's id
+public:
+ int proxy() { return m_iProxy; };
+ KviProxy* proxyServer(KviProxyDataBase * pDb);
+
+ kvi_u32_t port() const { return m_uPort; };
+ const QString & ipAddress() const { return m_szIp; };
+ const QString & password() const { return m_szPass; };
+ const QString & nickName() const { return m_szNick; };
+ const QString & initUMode() const { return m_szInitUMode; };
+ const QString & hostName() const { return m_szHostname; };
+ const QString & ip() const { return m_szIp; };
+ const QString & onLoginCommand() const { return m_szOnLoginCommand; };
+ const QString & onConnectCommand() const { return m_szOnConnectCommand; };
+ const QString & userName() const { return m_szUser; };
+ const QString & realName() const { return m_szRealName; };
+ const QString & linkFilter() const { return m_szLinkFilter; };
+ const QString & description() const { return m_szDescription; };
+ const QString & encoding() const { return m_szEncoding; };
+ const QString & id() const { return m_szId; };
+ const QString & userIdentityId() const { return m_szUserIdentityId; };
+ bool autoConnect() const { return m_bAutoConnect; };
+ QStringList* autoJoinChannelList(){ return m_pChannelList; };
+ bool isIpV6() const { return (m_uFlags & KVI_IRCSERVER_FLAG_IPV6); };
+ bool useSSL() const { return (m_uFlags & KVI_IRCSERVER_FLAG_SSL); };
+ bool cacheIp() const { return (m_uFlags & KVI_IRCSERVER_FLAG_CACHEIP); };
+
+ void setProxy(int p){ m_iProxy = p; };
+ void setIpAddress(const QString &a){ m_szIp = a; };
+ void setPort(kvi_u32_t p){ m_uPort = p; };
+ void setHostName(const QString &n){ m_szHostname = n; };
+ void setDescription(const QString &d){ m_szDescription = d; };
+ void setUserName(const QString &u){ m_szUser = u; };
+ void setPassword(const QString &p){ m_szPass = p; };
+ void setNickName(const QString &n){ m_szNick = n; };
+ void setRealName(const QString &r){ m_szRealName = r; };
+ void setEncoding(const QString &e){ m_szEncoding = e; };
+ void setInitUMode(const QString &u){ m_szInitUMode = u; };
+ void setOnConnectCommand(const QString &cmd){ m_szOnConnectCommand = cmd; };
+ void setOnLoginCommand(const QString &cmd){ m_szOnLoginCommand = cmd; };
+ void setLinkFilter(const QString &f){ m_szLinkFilter = f; };
+ // the channel list must be allocated with new!
+ void setAutoJoinChannelList(QStringList * pNewChannelList);
+ void setAutoConnect(bool autoconnect) { m_bAutoConnect = autoconnect; };
+ void setUserIdentityId(const QString &szUserIdentityId){ m_szUserIdentityId = szUserIdentityId; };
+ void setIpV6(bool bSet)
+ {
+ if(bSet)m_uFlags |= KVI_IRCSERVER_FLAG_IPV6;
+ else m_uFlags &= ((unsigned short)~KVI_IRCSERVER_FLAG_IPV6);
+ };
+ void setUseSSL(bool bSet)
+ {
+ if(bSet)m_uFlags |= KVI_IRCSERVER_FLAG_SSL;
+ else m_uFlags &= ((unsigned short)~KVI_IRCSERVER_FLAG_SSL);
+ };
+ void setCacheIp(bool bSet)
+ {
+ if(bSet)m_uFlags |= KVI_IRCSERVER_FLAG_CACHEIP;
+ else m_uFlags &= ((unsigned short)~KVI_IRCSERVER_FLAG_CACHEIP);
+ };
+ void operator =(const KviIrcServer &s);
+
+ bool load(KviConfig * cfg,const QString &prefix);
+ void save(KviConfig * cfg,const QString &prefix);
+
+ void generateUniqueId();
+ void setId(const QString &szId){ m_szId = szId; if(m_szId.isEmpty())generateUniqueId(); };
+
+ QString ircUri();
+};
+
+class KVILIB_API KviIrcNetwork : public KviHeapObject
+{
+ friend class KviIrcServerDataBase;
+public:
+ KviIrcNetwork(const KviIrcNetwork &src);
+ KviIrcNetwork(const QString &name);
+ ~KviIrcNetwork();
+protected:
+ QString m_szName;
+ QString m_szDescription;
+ QString m_szEncoding; // if empty, use system default
+ QString m_szNickName; // preferred nick name
+ QString m_szUserName; // preferred user name
+ QString m_szRealName; // preferred real name
+ QString m_szOnConnectCommand; // the command to run on connect
+ QString m_szOnLoginCommand; // the command to run after login
+ QStringList * m_pChannelList; // Channels to auto join
+ KviNickServRuleSet * m_pNickServRuleSet; // set of nick serv rules
+ bool m_bAutoConnect; // autoconnect
+ QString m_szUserIdentityId; // The user identity to use for this server: if empty
+ // Then use the global primary identity
+public:
+ const QString & name() const { return m_szName; };
+ const QString & encoding() const { return m_szEncoding; };
+ const QString & description() const { return m_szDescription; };
+ const QString & nickName() const { return m_szNickName; };
+ const QString & realName() const { return m_szRealName; };
+ const QString & userName() const { return m_szUserName; };
+ const QString & onLoginCommand() const { return m_szOnLoginCommand; };
+ const QString & onConnectCommand() const { return m_szOnConnectCommand; };
+ const QString & userIdentityId() const { return m_szUserIdentityId; };
+ bool autoConnect() const { return m_bAutoConnect; };
+ QStringList* autoJoinChannelList(){ return m_pChannelList; };
+ KviNickServRuleSet * nickServRuleSet(){ return m_pNickServRuleSet; };
+ void setNickServRuleSet(KviNickServRuleSet * s);
+ void copyFrom(const KviIrcNetwork &d);
+ void setName(const QString &szName){ m_szName = szName; };
+ void setEncoding(const QString &szEncoding){ m_szEncoding = szEncoding; };
+ void setDescription(const QString &szDescription){ m_szDescription = szDescription; };
+ void setOnConnectCommand(const QString &cmd){ m_szOnConnectCommand = cmd; };
+ void setOnLoginCommand(const QString &cmd){ m_szOnLoginCommand = cmd; };
+ void setNickName(const QString &n){ m_szNickName = n; };
+ void setRealName(const QString &r){ m_szRealName = r; };
+ void setUserName(const QString &u){ m_szUserName = u; };
+ void setAutoJoinChannelList(QStringList * pNewChannelList);
+ void setAutoConnect(bool bAutoConnect){ m_bAutoConnect = bAutoConnect; };
+ void setUserIdentityId(const QString &szUserIdentityId){ m_szUserIdentityId = szUserIdentityId; };
+};
+
+
+
+#endif //_KVI_IRCSERVER_H_
diff --git a/src/kvilib/irc/kvi_ircserverdb.cpp b/src/kvilib/irc/kvi_ircserverdb.cpp
new file mode 100644
index 00000000..88198b12
--- /dev/null
+++ b/src/kvilib/irc/kvi_ircserverdb.cpp
@@ -0,0 +1,646 @@
+//=============================================================================
+//
+// File : kvi_ircserverdb.cpp
+// Creation date : Mon Jul 10 2000 14:25:00 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+
+
+#include <qapplication.h>
+#include <qlayout.h>
+#include <qmessagebox.h>
+#include <qcheckbox.h>
+
+#include "kvi_ircserverdb.h"
+#include "kvi_config.h"
+#include "kvi_locale.h"
+#include "kvi_netutils.h"
+#include "kvi_nickserv.h"
+
+KviIrcServerDataBaseRecord::KviIrcServerDataBaseRecord(KviIrcNetwork * n)
+{
+ m_pNetwork = n;
+ m_pServerList = new KviPointerList<KviIrcServer>;
+ m_pServerList->setAutoDelete(true);
+ m_pCurrentServer = 0;
+}
+
+KviIrcServerDataBaseRecord::~KviIrcServerDataBaseRecord()
+{
+ delete m_pNetwork;
+ delete m_pServerList;
+}
+
+void KviIrcServerDataBaseRecord::insertServer(KviIrcServer *srv)
+{
+ m_pServerList->append(srv);
+}
+
+KviIrcServer * KviIrcServerDataBaseRecord::findServer(const KviIrcServer * pServer)
+{
+ for(KviIrcServer *s=m_pServerList->first();s;s=m_pServerList->next())
+ {
+ if(KviQString::equalCI(s->m_szHostname,pServer->m_szHostname) &&
+ (s->m_uPort == pServer->m_uPort) &&
+ (s->useSSL() == pServer->useSSL()) &&
+ (s->isIpV6() == pServer->isIpV6()))return s;
+ }
+ return 0;
+}
+
+void KviIrcServerDataBaseRecord::setCurrentServer(KviIrcServer *srv)
+{
+ if(m_pServerList->findRef(srv) != -1)m_pCurrentServer = srv;
+}
+
+KviIrcServer * KviIrcServerDataBaseRecord::currentServer()
+{
+ if(m_pCurrentServer)return m_pCurrentServer;
+ m_pCurrentServer = m_pServerList->first();
+ return m_pCurrentServer;
+}
+
+
+
+
+
+
+
+
+
+
+KviIrcServerDataBase::KviIrcServerDataBase()
+{
+ m_pRecords = new KviPointerHashTable<QString,KviIrcServerDataBaseRecord>(17,false);
+ m_pRecords->setAutoDelete(true);
+ m_pAutoConnectOnStartupServers = 0;
+ m_pAutoConnectOnStartupNetworks = 0;
+}
+
+KviIrcServerDataBase::~KviIrcServerDataBase()
+{
+ delete m_pRecords;
+ if(m_pAutoConnectOnStartupServers)delete m_pAutoConnectOnStartupServers;
+ if(m_pAutoConnectOnStartupNetworks)delete m_pAutoConnectOnStartupNetworks;
+}
+
+void KviIrcServerDataBase::clearAutoConnectOnStartupServers()
+{
+ if(!m_pAutoConnectOnStartupServers)return;
+ delete m_pAutoConnectOnStartupServers;
+ m_pAutoConnectOnStartupServers = 0;
+}
+
+void KviIrcServerDataBase::clearAutoConnectOnStartupNetworks()
+{
+ if(!m_pAutoConnectOnStartupNetworks)return;
+ delete m_pAutoConnectOnStartupNetworks;
+ m_pAutoConnectOnStartupNetworks = 0;
+}
+
+void KviIrcServerDataBase::clear()
+{
+ m_pRecords->clear();
+ m_szCurrentNetwork = "";
+}
+
+KviIrcServerDataBaseRecord * KviIrcServerDataBase::insertNetwork(KviIrcNetwork *n)
+{
+ KviIrcServerDataBaseRecord * r = new KviIrcServerDataBaseRecord(n);
+ m_pRecords->replace(n->name(),r);
+ return r;
+}
+
+KviIrcServerDataBaseRecord * KviIrcServerDataBase::findRecord(const QString &szNetName)
+{
+ return m_pRecords->find(szNetName);
+}
+
+
+KviIrcNetwork * KviIrcServerDataBase::findNetwork(const QString &szName)
+{
+ KviIrcServerDataBaseRecord * r = m_pRecords->find(szName);
+ if(!r)return 0;
+ return r->network();
+}
+
+KviIrcServerDataBaseRecord * KviIrcServerDataBase::currentRecord()
+{
+ KviIrcServerDataBaseRecord * r = 0;
+ if(!m_szCurrentNetwork.isEmpty())r = m_pRecords->find(m_szCurrentNetwork);
+ if(r)return r;
+
+ KviPointerHashTableIterator<QString,KviIrcServerDataBaseRecord> it(*m_pRecords);
+ r = it.current();
+ if(!r)return 0;
+ m_szCurrentNetwork = r->network()->name();
+ return r;
+}
+
+void KviIrcServerDataBase::updateServerIp(KviIrcServer * pServer,const QString & ip)
+{
+ KviPointerHashTableIterator<QString,KviIrcServerDataBaseRecord> it(*m_pRecords);
+ while(KviIrcServerDataBaseRecord * r = it.current())
+ {
+ KviIrcServer * srv = r->findServer(pServer);
+ if(srv)
+ {
+ srv->m_szIp = ip;
+ return;
+ }
+ ++it;
+ }
+}
+
+bool KviIrcServerDataBase::makeCurrentBestServerInNetwork(const QString &szNetName,KviIrcServerDataBaseRecord * r,QString &szError)
+{
+ m_szCurrentNetwork = szNetName;
+ // find a round-robin server in that network
+
+ if(r->m_pServerList->isEmpty())
+ {
+ szError = __tr2qs("The specified network has no server entries");
+ return false;
+ }
+
+ for(KviIrcServer * s = r->m_pServerList->first();s;s = r->m_pServerList->next())
+ {
+#ifdef COMPILE_USE_QT4
+ if(s->m_szDescription.contains("random",Qt::CaseInsensitive) ||
+ (s->m_szDescription.contains("round",Qt::CaseInsensitive) && s->m_szDescription.contains("robin",Qt::CaseInsensitive)))
+#else
+ if(s->m_szDescription.contains("random",false) ||
+ (s->m_szDescription.contains("round",false) && s->m_szDescription.contains("robin",false)))
+#endif
+ {
+ r->setCurrentServer(s);
+ return true;
+ }
+ }
+
+ // no explicit round robin... try some common names
+
+ QString tryAlso1,tryAlso2,tryAlso3;
+
+ KviQString::sprintf(tryAlso1,"irc.%Q.org",&szNetName);
+ KviQString::sprintf(tryAlso2,"irc.%Q.net",&szNetName);
+ KviQString::sprintf(tryAlso3,"irc.%Q.com",&szNetName);
+
+ for(KviIrcServer * ss = r->m_pServerList->first();ss;ss = r->m_pServerList->next())
+ {
+ if(KviQString::equalCI(ss->m_szHostname,tryAlso1) ||
+ KviQString::equalCI(ss->m_szHostname,tryAlso2) ||
+ KviQString::equalCI(ss->m_szHostname,tryAlso3))
+ {
+ r->setCurrentServer(ss);
+ return true;
+ }
+ }
+
+ // a random one in this network
+ return true;
+}
+
+
+bool KviIrcServerDataBase::makeCurrentServer(KviIrcServerDefinition * d,QString &szError)
+{
+ KviIrcServer * pServer = 0;
+
+ KviPointerHashTableIterator<QString,KviIrcServerDataBaseRecord> it(*m_pRecords);
+ KviIrcServerDataBaseRecord * r = 0;
+ KviIrcServer * srv;
+
+ if(KviQString::equalCIN(d->szServer,"net:",4))
+ {
+ // net:networkname form
+ QString szNet = d->szServer;
+ szNet.remove(0,4);
+ KviIrcServerDataBaseRecord * r = m_pRecords->find(szNet);
+ if(r)return makeCurrentBestServerInNetwork(szNet,r,szError);
+ szError = __tr2qs("The server specification seems to be in the net:<string> but the network couln't be found in the database");
+ return false;
+ }
+
+ if(KviQString::equalCIN(d->szServer,"id:",3))
+ {
+ // id:serverid form
+ QString szId = d->szServer;
+ szId.remove(0,3);
+
+ while((r = it.current()))
+ {
+ for(srv = r->serverList()->first();srv && (!pServer);srv = r->serverList()->next())
+ {
+ if(KviQString::equalCI(srv->id(),szId))
+ {
+ pServer = srv;
+ goto search_finished;
+ }
+ }
+ ++it;
+ }
+ szError = __tr2qs("The server specification seems to be in the id:<string> form but the identifier coulnd't be found in the database");
+ return false;
+ }
+
+ it.toFirst();
+
+ while((r = it.current()))
+ {
+ for(srv = r->serverList()->first();srv && (!pServer);srv = r->serverList()->next())
+ {
+ if(KviQString::equalCI(srv->hostName(),d->szServer))
+ {
+ if(d->bIpV6 == srv->isIpV6())
+ {
+ if(d->bSSL == srv->useSSL())
+ {
+ if(d->bPortIsValid)
+ {
+ // must match the port
+ if(d->uPort == srv->port())
+ {
+ // port matches
+ if(!d->szLinkFilter.isEmpty())
+ {
+ // must match the link filter
+ if(KviQString::equalCI(d->szLinkFilter,srv->linkFilter()))
+ {
+ // link filter matches
+ pServer = srv;
+ goto search_finished;
+ } // else link filter doesn't match
+ } else {
+ // no need to match the link filter
+ pServer = srv;
+ goto search_finished;
+ }
+ } // else port doesn't match
+ } else {
+ // no need to match the port
+ if(!d->szLinkFilter.isEmpty())
+ {
+ // must match the link filter
+ if(KviQString::equalCI(d->szLinkFilter,srv->linkFilter()))
+ {
+ // link filter matches
+ pServer = srv;
+ goto search_finished;
+ } // else link filter doesn't match
+ } else {
+ // no need to match the link filter
+ pServer = srv;
+ goto search_finished;
+ }
+ }
+ }
+ }
+ }
+ }
+ ++it;
+ }
+
+search_finished:
+
+ if(r && pServer)
+ {
+ if(!d->szNick.isEmpty())pServer->m_szNick = d->szNick;
+ if(!d->szPass.isEmpty())pServer->m_szPass = d->szPass; // don't clear the pass!
+ if(!d->szInitUMode.isEmpty())pServer->m_szInitUMode = d->szInitUMode;
+
+ m_szCurrentNetwork = r->network()->name();
+ r->setCurrentServer(pServer);
+ return true;
+ }
+
+ // no such server: is it a valid ip address or hostname ?
+ bool bIsValidIpV4 = KviNetUtils::isValidStringIp(d->szServer);
+#ifdef COMPILE_IPV6_SUPPORT
+ bool bIsValidIpV6 =KviNetUtils::isValidStringIp_V6(d->szServer);
+#else
+ bool bIsValidIpV6 = false;
+#endif
+
+ if(!(bIsValidIpV4 || bIsValidIpV6))
+ {
+ // is it a valid hostname ? (must contain at least one dot)
+#ifdef COMPILE_USE_QT4
+ if(!d->szServer.contains('.'))
+#else
+ if(d->szServer.contains('.') < 1)
+#endif
+ {
+ // assume it is a network name!
+ KviIrcServerDataBaseRecord * r = m_pRecords->find(d->szServer);
+ if(r)return makeCurrentBestServerInNetwork(d->szServer,r,szError);
+ // else probably not a network name
+ }
+ }
+
+ // a valid hostname or ip address , not found in list : add it and make it current
+
+ r = m_pRecords->find(__tr2qs("Standalone Servers"));
+ if(!r)
+ {
+ r = new KviIrcServerDataBaseRecord(new KviIrcNetwork(__tr2qs("Standalone Servers")));
+ m_pRecords->replace(r->network()->name(),r);
+ }
+
+ KviIrcServer * s = new KviIrcServer();
+ s->m_szHostname = d->szServer;
+ if(bIsValidIpV4)
+ {
+ s->m_szIp = d->szServer;
+ s->setCacheIp(true);
+#ifdef COMPILE_IPV6_SUPPORT
+ } else {
+ if(bIsValidIpV6)
+ {
+ s->m_szIp = d->szServer;
+ s->setCacheIp(true);
+ d->bIpV6 = true;
+ }
+ }
+#else
+ }
+#endif
+ s->m_uPort = d->bPortIsValid ? d->uPort : 6667;
+ s->setLinkFilter(d->szLinkFilter);
+ s->m_szPass= d->szPass;
+ s->m_szNick= d->szNick;
+ s->m_szInitUMode = d->szInitUMode;
+ s->setIpV6(d->bIpV6);
+ s->setUseSSL(d->bSSL);
+ r->insertServer(s);
+ m_szCurrentNetwork = r->network()->name();
+ r->setCurrentServer(s);
+
+ return true;
+}
+
+void parseMircServerRecord(QString entry,QString& szNet,
+ QString& szDescription,QString& szHost,QString& szPort,bool& bSsl,kvi_u32_t& uPort)
+{
+ bSsl = false;
+ int idx = KviQString::find(entry,"SERVER:");
+ if(idx != -1)
+ {
+ szDescription = entry.left(idx);
+ szNet=szDescription.section(':',0,0);
+ szDescription=szDescription.section(':',1,1);
+
+ entry.remove(0,idx + 7);
+ idx = KviQString::find(entry,"GROUP:");
+ if(idx != -1)
+ {
+ szHost = entry.left(idx);
+ } else {
+ szHost = entry;
+ }
+
+ szPort = szHost.section(':',1,1);
+ if(szPort[0]=='+')
+ {
+ bSsl = true;
+ szPort.remove(0,1);
+ }
+ szHost = szHost.section(':',0,0);
+
+ bool bOk;
+ uPort = szPort.toUInt(&bOk);
+ if(!bOk)uPort = 6667;
+ }
+}
+
+void KviIrcServerDataBase::loadFromMircIni(const QString & filename, const QString & szMircIni, QStringList& recentServers)
+{
+ clear();
+ recentServers.clear();
+ QString szDefaultServer;
+ KviConfig mircCfg(szMircIni,KviConfig::Read,true);
+ if(mircCfg.hasGroup("mirc"))
+ {
+ mircCfg.setGroup("mirc");
+ szDefaultServer = mircCfg.readQStringEntry("host");
+ }
+
+ KviConfig cfg(filename,KviConfig::Read,true);
+ int i = 0;
+
+ QString entry;
+ QString key;
+ if(cfg.hasGroup("recent"))
+ {
+ cfg.setGroup("recent");
+ do {
+ KviQString::sprintf(key,"n%d",i);
+ entry = cfg.readEntry(key);
+ if(!entry.isEmpty())
+ {
+ QString szNet;
+ QString szDescription;
+ QString szHost;
+ QString szPort;
+ bool bSsl = false;
+ kvi_u32_t uPort = 0;
+
+ parseMircServerRecord(entry,szNet,
+ szDescription,szHost,szPort,bSsl,uPort);
+
+ recentServers << (bSsl ? "ircs://" : "irc://" ) +szHost+":"+szPort;
+ }
+ i++;
+ } while(!entry.isEmpty());
+ }
+
+ i = 0;
+ if(cfg.hasGroup("servers"))
+ {
+ cfg.setGroup("servers");
+ do {
+ KviQString::sprintf(key,"n%d",i);
+ entry = cfg.readEntry(key);
+ if(!entry.isEmpty())
+ {
+ bool bDefault = false;
+ QString szNet;
+ QString szDescription;
+ QString szHost;
+ QString szPort;
+ bool bSsl = false;
+ kvi_u32_t uPort = 0;
+ // <net>:<description>SERVER:<server:port>GROUP:<group???>
+ if(entry==szDefaultServer)
+ bDefault = true;
+
+ parseMircServerRecord(entry,szNet,
+ szDescription,szHost,szPort,bSsl,uPort);
+
+ KviIrcServerDataBaseRecord * r = findRecord(szNet);
+
+ if(!r) {
+ KviIrcNetwork * n = new KviIrcNetwork(szNet);
+ r = insertNetwork(n);
+ }
+
+ KviIrcServer *s = new KviIrcServer();
+ s->m_szHostname = szHost;
+ s->m_szDescription = szDescription;
+ s->m_uPort = uPort;
+
+
+ r->m_pServerList->append(s);
+ if(bDefault)
+ {
+ m_szCurrentNetwork = szNet;
+ }
+ }
+ i++;
+ } while(!entry.isEmpty());
+ }
+}
+
+
+void KviIrcServerDataBase::load(const QString & filename)
+{
+ clear();
+ KviConfig cfg(filename,KviConfig::Read);
+
+ KviConfigIterator it(*(cfg.dict()));
+
+ QString tmp;
+
+ while(it.current())
+ {
+ if(it.current()->count() > 0)
+ {
+ KviIrcNetwork * n = new KviIrcNetwork(it.currentKey());
+ KviIrcServerDataBaseRecord * r = insertNetwork(n);
+ cfg.setGroup(it.currentKey());
+ n->m_szEncoding = cfg.readQStringEntry("Encoding");
+ n->m_szDescription = cfg.readQStringEntry("Description");
+ n->m_szNickName = cfg.readQStringEntry("NickName");
+ n->m_szRealName = cfg.readQStringEntry("RealName");
+ n->m_szUserName = cfg.readQStringEntry("UserName");
+ n->m_szOnConnectCommand = cfg.readQStringEntry("OnConnectCommand");
+ n->m_szOnLoginCommand = cfg.readQStringEntry("OnLoginCommand");
+ n->m_pNickServRuleSet = KviNickServRuleSet::load(&cfg,QString::null);
+ n->m_bAutoConnect = cfg.readBoolEntry("AutoConnect",false);
+ n->m_szUserIdentityId = cfg.readQStringEntry("UserIdentityId");
+ if(n->m_bAutoConnect)
+ {
+ if(!m_pAutoConnectOnStartupNetworks)
+ {
+ m_pAutoConnectOnStartupNetworks = new KviPointerList<KviIrcServerDataBaseRecord>;
+ m_pAutoConnectOnStartupNetworks->setAutoDelete(false);
+ }
+ m_pAutoConnectOnStartupNetworks->append(r);
+ }
+ QStringList l = cfg.readStringListEntry("AutoJoinChannels",QStringList());
+ if(l.count() > 0)n->setAutoJoinChannelList(new QStringList(l));
+
+ if(cfg.readBoolEntry("Current",false))m_szCurrentNetwork = it.currentKey();
+
+ int nServers = cfg.readIntEntry("NServers",0);
+ for(int i=0;i < nServers;i++)
+ {
+ KviIrcServer *s = new KviIrcServer();
+ KviQString::sprintf(tmp,"%d_",i);
+ if(s->load(&cfg,tmp))
+ {
+ r->m_pServerList->append(s);
+ KviQString::sprintf(tmp,"%d_Current",i);
+ if(cfg.readBoolEntry(tmp,false))r->m_pCurrentServer = s;
+ if(s->autoConnect())
+ {
+ if(!m_pAutoConnectOnStartupServers)
+ {
+ m_pAutoConnectOnStartupServers = new KviPointerList<KviIrcServer>;
+ m_pAutoConnectOnStartupServers->setAutoDelete(false);
+ }
+ m_pAutoConnectOnStartupServers->append(s);
+ }
+ } else delete s;
+ }
+ if(!r->m_pCurrentServer)r->m_pCurrentServer = r->m_pServerList->first();
+ }
+ ++it;
+ }
+}
+
+void KviIrcServerDataBase::save(const QString &filename)
+{
+ KviConfig cfg(filename,KviConfig::Write);
+
+ cfg.clear(); // clear any old entry
+
+ KviPointerHashTableIterator<QString,KviIrcServerDataBaseRecord> it(*m_pRecords);
+
+ QString tmp;
+
+ while(KviIrcServerDataBaseRecord * r = it.current())
+ {
+ KviIrcNetwork * n = r->network();
+ cfg.setGroup(n->m_szName);
+ cfg.writeEntry("NServers",r->m_pServerList->count());
+ if(n->m_bAutoConnect)
+ cfg.writeEntry("AutoConnect",true);
+ if(!n->m_szEncoding.isEmpty())
+ cfg.writeEntry("Encoding",n->m_szEncoding);
+ if(!n->m_szDescription.isEmpty())
+ cfg.writeEntry("Description",n->m_szDescription);
+ if(!n->m_szNickName.isEmpty())
+ cfg.writeEntry("NickName",n->m_szNickName);
+ if(!n->m_szRealName.isEmpty())
+ cfg.writeEntry("RealName",n->m_szRealName);
+ if(!n->m_szUserName.isEmpty())
+ cfg.writeEntry("UserName",n->m_szUserName);
+ if(!n->m_szOnConnectCommand.isEmpty())
+ cfg.writeEntry("OnConnectCommand",n->m_szOnConnectCommand);
+ if(!n->m_szOnLoginCommand.isEmpty())
+ cfg.writeEntry("OnLoginCommand",n->m_szOnLoginCommand);
+ if(n->m_pNickServRuleSet)n->m_pNickServRuleSet->save(&cfg,QString::null);
+ if(n->autoJoinChannelList())
+ cfg.writeEntry("AutoJoinChannels",*(n->autoJoinChannelList()));
+ if(n->m_szName == m_szCurrentNetwork)cfg.writeEntry("Current",true);
+ if(!n->m_szUserIdentityId.isEmpty())
+ cfg.writeEntry("UserIdentityId",n->m_szUserIdentityId);
+ int i=0;
+ for(KviIrcServer *s = r->m_pServerList->first();s;s = r->m_pServerList->next())
+ {
+ KviQString::sprintf(tmp,"%d_",i);
+ s->save(&cfg,tmp);
+
+ if(s == r->m_pCurrentServer)
+ {
+ KviQString::sprintf(tmp,"%d_Current",i);
+ cfg.writeEntry(tmp,true);
+ }
+
+ i++;
+ }
+ ++it;
+ }
+}
+
+
+
diff --git a/src/kvilib/irc/kvi_ircserverdb.h b/src/kvilib/irc/kvi_ircserverdb.h
new file mode 100644
index 00000000..b5d55231
--- /dev/null
+++ b/src/kvilib/irc/kvi_ircserverdb.h
@@ -0,0 +1,116 @@
+#ifndef _KVI_IRCSERVERDB_H_
+#define _KVI_IRCSERVERDB_H_
+//=============================================================================
+//
+// File : kvi_ircserverdb.h
+// Creation date : Mon Jul 10 2000 14:15:42 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_ircserver.h"
+
+#include "kvi_pointerhashtable.h"
+
+typedef struct _KviIrcServerDefinition
+{
+ QString szServer;
+ kvi_u32_t uPort;
+ bool bPortIsValid;
+ bool bIpV6;
+ bool bSSL;
+ QString szLinkFilter;
+ QString szPass;
+ QString szNick;
+ QString szInitUMode;
+} KviIrcServerDefinition;
+
+
+
+class KVILIB_API KviIrcServerDataBaseRecord
+{
+ friend class KviIrcServerDataBase;
+public:
+ KviIrcServerDataBaseRecord(KviIrcNetwork * n);
+ ~KviIrcServerDataBaseRecord();
+protected:
+ KviIrcNetwork * m_pNetwork;
+ KviPointerList<KviIrcServer> * m_pServerList;
+
+ KviIrcServer * m_pCurrentServer;
+public:
+ KviIrcNetwork * network(){ return m_pNetwork; };
+ KviPointerList<KviIrcServer> * serverList(){ return m_pServerList; };
+ KviIrcServer * currentServer();
+ void insertServer(KviIrcServer *srv);
+ KviIrcServer * findServer(const KviIrcServer * pServer);
+ void setCurrentServer(KviIrcServer *srv);
+};
+
+
+
+
+
+class KVILIB_API KviIrcServerDataBase
+{
+public:
+ KviIrcServerDataBase();
+ ~KviIrcServerDataBase();
+private:
+ KviPointerHashTable<QString,KviIrcServerDataBaseRecord> * m_pRecords;
+ QString m_szCurrentNetwork;
+ // This list is computed when the data are loaded from disk
+ // during the startup and is used by KviApp to
+ // start the connections.
+ // The pointer is zero if there are no autoConnect servers
+ // The list is valid only during the startup phase
+ // because it contains shallow pointers to the servers
+ // really contained in the server/network list
+ // and it is never updated later
+ KviPointerList<KviIrcServer> * m_pAutoConnectOnStartupServers;
+ KviPointerList<KviIrcServerDataBaseRecord> * m_pAutoConnectOnStartupNetworks;
+public:
+ void clear();
+ KviPointerHashTable<QString,KviIrcServerDataBaseRecord> * recordDict(){ return m_pRecords; };
+ KviPointerList<KviIrcServer> * autoConnectOnStartupServers(){ return m_pAutoConnectOnStartupServers; };
+ KviPointerList<KviIrcServerDataBaseRecord> * autoConnectOnStartupNetworks(){ return m_pAutoConnectOnStartupNetworks; };
+ void clearAutoConnectOnStartupServers();
+ void clearAutoConnectOnStartupNetworks();
+ void setCurrentNetwork(const QString &szNetName){ m_szCurrentNetwork = szNetName; };
+ const QString & currentNetworkName(){ return m_szCurrentNetwork; };
+ KviIrcServerDataBaseRecord * currentRecord();
+ KviIrcServerDataBaseRecord * findRecord(const QString &szNetName);
+ KviIrcNetwork * findNetwork(const QString &name);
+ void loadFromMircIni(const QString & filename, const QString & szMircIni, QStringList& recentServers);
+ void load(const QString & filename);
+ void save(const QString & filename);
+ KviIrcServerDataBaseRecord * insertNetwork(KviIrcNetwork * n);
+ void updateServerIp(KviIrcServer * pServer,const QString &ip);
+ bool makeCurrentServer(KviIrcServerDefinition * d,QString &szError);
+ bool makeCurrentBestServerInNetwork(const QString &szNetName,KviIrcServerDataBaseRecord * d,QString &szError);
+};
+
+
+
+
+
+
+#endif //_KVI_IRCSERVERDB_H_
diff --git a/src/kvilib/irc/kvi_ircuserdb.cpp b/src/kvilib/irc/kvi_ircuserdb.cpp
new file mode 100644
index 00000000..38b52522
--- /dev/null
+++ b/src/kvilib/irc/kvi_ircuserdb.cpp
@@ -0,0 +1,285 @@
+//=============================================================================
+//
+// File : kvi_ircuserdb.cpp
+// Creation date : Mon Jul 31 2000 21:23:22 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+
+
+#include "kvi_debug.h"
+#include "kvi_ircuserdb.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_qstring.h"
+#include "kvi_stringconversion.h"
+
+//static int cacheHit = 0;
+//static int cacheMiss = 0;
+
+KviIrcUserEntry::KviIrcUserEntry(const QString &user,const QString &host)
+{
+ m_szUser = user;
+ m_szHost = host;
+ m_pAvatar = 0;
+ m_nRefs = 1;
+ m_iHops = -1;
+ m_bAway = false;
+ m_eGender = Unknown;
+ m_bBot = false;
+ m_bNotFoundRegUserLoockup=false;
+ m_bUseCustomColor=false;
+}
+
+void KviIrcUserEntry::setRealName(const QString &rn)
+{
+ m_szRealName = rn;
+ m_szRealName = KviQString::trimmed(m_szRealName);
+ if(m_szRealName.length()>=3)
+ {
+ if( (m_szRealName[0].unicode()==KVI_TEXT_COLOR) && (m_szRealName[2].unicode()==KVI_TEXT_RESET) )
+ {
+ switch(m_szRealName[1].unicode())
+ {
+ case '1': // hum.. encoded as hidden color code eh ? publish is somewhere, so others might implement this...
+ setGender(Male);
+ break;
+ case '2':
+ setGender(Female);
+ break;
+ case '3':
+ setBot(true);
+ break;
+ }
+ m_szRealName.remove(0,3);
+ }
+ }
+}
+
+KviIrcUserEntry::~KviIrcUserEntry()
+{
+ if(m_pAvatar)delete m_pAvatar;
+}
+
+void KviIrcUserEntry::setAvatar(KviAvatar * av)
+{
+ if(m_pAvatar)delete m_pAvatar;
+ m_pAvatar = av;
+}
+
+KviAvatar * KviIrcUserEntry::forgetAvatar()
+{
+ KviAvatar * ret = m_pAvatar;
+ m_pAvatar = 0;
+ return ret;
+}
+
+KviIrcUserDataBase::KviIrcUserDataBase()
+: QObject()
+{
+ // we expect a maximum of ~4000 users (= ~16 KB array on a 32 bit machine)
+ // ...after that we will loose in performance
+ // ... well...4000 users is a really big number...say 6-7 really big channels
+ // (4001 is prime)
+ // up to 12000 users we will have a reasonably fast access.
+ // the performance increase since kvirc versions < 3.0.0
+ // is really big anyway (there was a linear list instead of a hash!!!)
+
+ m_pDict = new KviPointerHashTable<QString,KviIrcUserEntry>(4001,false);
+ m_pDict->setAutoDelete(true);
+ setupConnectionWithReguserDb();
+}
+
+KviIrcUserDataBase::~KviIrcUserDataBase()
+{
+ delete m_pDict;
+}
+
+bool KviIrcUserDataBase::haveCustomColor(const QString & nick)
+{
+ KviIrcUserEntry *u = find(nick);
+ if(!u) return false;
+ if( u->m_szLastRegisteredMatchNick!=nick)
+ registeredUser(nick);
+ if(!u->m_bNotFoundRegUserLoockup)
+ {
+ return u->m_bUseCustomColor;
+ }
+ return false;
+}
+
+QColor* KviIrcUserDataBase::customColor(const QString & nick)
+{
+ KviIrcUserEntry *u = find(nick);
+ if(!u) return 0;
+ if( u->m_szLastRegisteredMatchNick!=nick)
+ registeredUser(nick);
+
+ if(!u->m_bNotFoundRegUserLoockup)
+ {
+ return &(u->m_cachedColor);
+ }
+ return 0;
+}
+
+
+KviRegisteredUser* KviIrcUserDataBase::registeredUser(const QString & nick,const QString & user,const QString & host)
+{
+ if(nick.isEmpty()) return 0;
+ KviIrcUserEntry *u = find(nick);
+ if(!u) return g_pRegisteredUserDataBase->findMatchingUser(nick,user,host);
+ KviRegisteredUser* pUser=0;
+
+ if(u->m_bNotFoundRegUserLoockup && u->m_szLastRegisteredMatchNick==nick)
+ {
+ //cacheHit++;
+ //debug("cache hits/miss = %i/%i",cacheHit,cacheMiss);
+ return 0;
+ }
+
+ if(!u->m_szRegisteredUserName.isEmpty() && u->m_szLastRegisteredMatchNick==nick)
+ {
+ pUser = g_pRegisteredUserDataBase->getUser(u->m_szRegisteredUserName);
+ //if(pUser) cacheHit++;
+ }
+
+ if(!pUser) {
+ //user renamed or it is a first loockup
+ if(u->hasHost() && u->hasUser())
+ {
+ pUser=g_pRegisteredUserDataBase->findMatchingUser(nick,u->user(),u->host());
+ //cacheMiss++;
+ if(pUser) {
+ u->m_szLastRegisteredMatchNick=nick;
+ u->m_szRegisteredUserName=pUser->name();
+
+ u->m_bUseCustomColor=pUser->getBoolProperty("useCustomColor");
+ QString szTmp=pUser->getProperty("customColor");
+ KviStringConversion::fromString(szTmp,u->m_cachedColor);
+
+ u->m_bNotFoundRegUserLoockup=false; //to be shure
+ } else {
+ u->m_szLastRegisteredMatchNick=nick;
+ u->m_bNotFoundRegUserLoockup=true;
+ }
+ }
+ }
+
+// debug("cache hits/miss = %i/%i",cacheHit,cacheMiss);
+ return pUser;
+}
+
+KviRegisteredUser* KviIrcUserDataBase::registeredUser(const QString & nick)
+{
+ if(nick.isEmpty()) return 0;
+ KviIrcUserEntry *u = find(nick);
+ if(!u) return 0;
+ return registeredUser(nick,u->user(),u->host());
+}
+
+void KviIrcUserDataBase::clear()
+{
+ delete m_pDict;
+ m_pDict = new KviPointerHashTable<QString,KviIrcUserEntry>(4001,false);
+ m_pDict->setAutoDelete(true);
+}
+
+KviIrcUserEntry * KviIrcUserDataBase::insertUser(const QString &nick,const QString &user,const QString &hostname)
+{
+ KviIrcUserEntry * e = m_pDict->find(nick);
+ if(e)
+ {
+ e->m_nRefs++;
+ if(e->m_szUser.isEmpty())
+ {
+ e->m_szUser = user;
+ e->m_szHost = hostname;
+ }
+ } else {
+ e = new KviIrcUserEntry(user,hostname);
+ m_pDict->insert(nick,e);
+ }
+ return e;
+}
+
+void KviIrcUserDataBase::removeUser(const QString &nick,KviIrcUserEntry * e)
+{
+ e->m_nRefs--;
+ if(e->m_nRefs == 0)m_pDict->remove(nick);
+}
+
+void KviIrcUserDataBase::setupConnectionWithReguserDb()
+{
+ connect(g_pRegisteredUserDataBase,SIGNAL(userRemoved(const QString&)),this,SLOT(registeredUserRemoved(const QString&)));
+ connect(g_pRegisteredUserDataBase,SIGNAL(userChanged(const QString&)),this,SLOT(registeredUserChanged(const QString&)));
+ connect(g_pRegisteredUserDataBase,SIGNAL(userAdded(const QString&)),this,SLOT(registeredUserAdded(const QString&)));
+ connect(g_pRegisteredUserDataBase,SIGNAL(databaseCleared()),this,SLOT(registeredDatabaseCleared()));
+
+
+}
+
+void KviIrcUserDataBase::registeredUserRemoved(const QString& user)
+{
+ KviPointerHashTableIterator<QString,KviIrcUserEntry> it( *m_pDict );
+ for( ; it.current(); ++it )
+ {
+ if(it.current()->m_szRegisteredUserName==user)
+ {
+ it.current()->m_szRegisteredUserName="";
+ it.current()->m_bNotFoundRegUserLoockup=false;
+ }
+ }
+}
+
+void KviIrcUserDataBase::registeredUserChanged(const QString& user)
+{
+ //the same as above
+ KviPointerHashTableIterator<QString,KviIrcUserEntry> it( *m_pDict );
+ for( ; it.current(); ++it )
+ {
+ if(it.current()->m_szRegisteredUserName==user)
+ {
+ it.current()->m_szRegisteredUserName="";
+ it.current()->m_bNotFoundRegUserLoockup=false;
+ }
+ }
+}
+
+void KviIrcUserDataBase::registeredUserAdded(const QString& user)
+{
+ KviPointerHashTableIterator<QString,KviIrcUserEntry> it( *m_pDict );
+ for( ; it.current(); ++it )
+ {
+ if(it.current()->m_szRegisteredUserName.isEmpty())
+ {
+ it.current()->m_bNotFoundRegUserLoockup=false;
+ }
+ }
+}
+
+void KviIrcUserDataBase::registeredDatabaseCleared()
+{
+ KviPointerHashTableIterator<QString,KviIrcUserEntry> it( *m_pDict );
+ for( ; it.current(); ++it )
+ {
+ it.current()->m_szRegisteredUserName="";
+ it.current()->m_bNotFoundRegUserLoockup=false;
+ }
+}
diff --git a/src/kvilib/irc/kvi_ircuserdb.h b/src/kvilib/irc/kvi_ircuserdb.h
new file mode 100644
index 00000000..bdf7c51c
--- /dev/null
+++ b/src/kvilib/irc/kvi_ircuserdb.h
@@ -0,0 +1,145 @@
+#ifndef _KVI_IRCUSERDB_H_
+#define _KVI_IRCUSERDB_H_
+
+//=============================================================================
+//
+// File : kvi_ircuserdb.h
+// Creation date : Mon Jul 31 2000 20:59:12 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#include "kvi_pointerhashtable.h"
+
+#include "kvi_string.h"
+#include "kvi_avatar.h"
+#include "kvi_regusersdb.h"
+
+class KviIrcUserDataBase;
+
+class KVILIB_API KviIrcUserEntry
+{
+ friend class KviIrcUserDataBase;
+public:
+ KviIrcUserEntry(const QString &user,const QString &host);
+ ~KviIrcUserEntry();
+
+ enum Gender {
+ Male = 0,
+ Female = 1,
+ Unknown = 3
+ };
+
+protected:
+ QString m_szUser;
+ QString m_szHost;
+
+ QString m_szServer;
+ QString m_szRealName;
+ int m_iHops;
+ Gender m_eGender;
+
+ bool m_bAway;
+
+ KviAvatar * m_pAvatar;
+
+ int m_nRefs;
+ bool m_bBot;
+
+ bool m_bNotFoundRegUserLoockup;
+ QString m_szRegisteredUserName;
+ QString m_szLastRegisteredMatchNick;
+
+ QColor m_cachedColor;
+ bool m_bUseCustomColor;
+public:
+ Gender gender() { return m_eGender; };
+ void setBot(bool bIsBot) { m_bBot = bIsBot; };
+ bool isBot() { return m_bBot; };
+ void setGender(Gender g) { m_eGender=g; };
+ void setUser(const QString &user) { m_szUser = user; };
+ bool hasUser() { return (!m_szUser.isEmpty()); };
+ void setHost(const QString &host) { m_szHost = host; };
+ bool hasHost() { return (!m_szHost.isEmpty()); };
+ void setServer(const QString &serv) { m_szServer = serv; };
+ void setRealName(const QString &rn);
+ void setHops(int hops) { m_iHops = hops; };
+ const QString &user() { return m_szUser; };
+ const QString &host() { return m_szHost; };
+ bool hasServer() { return (!m_szServer.isEmpty()); };
+ const QString &server() { return m_szServer; };
+ bool hasRealName() { return (!m_szRealName.isEmpty()); };
+ const QString &realName() { return m_szRealName; };
+ bool hasHops() { return m_iHops >= 0; };
+ int hops() { return m_iHops; };
+ KviAvatar * avatar() { return m_pAvatar; };
+ int nRefs() { return m_nRefs; };
+ bool isAway() const { return m_bAway; };
+ void setAway(bool bAway) { m_bAway = bAway; };
+ // warning! the ownership passes to this class!
+ void setAvatar(KviAvatar * av = 0);
+ KviAvatar * forgetAvatar();
+};
+
+// from least powerful to most powerful
+#define KVI_USERFLAG_USEROP 1
+#define KVI_USERFLAG_VOICE 2
+#define KVI_USERFLAG_HALFOP 4
+#define KVI_USERFLAG_OP 8
+#define KVI_USERFLAG_CHANADMIN 16
+#define KVI_USERFLAG_CHANOWNER 32
+
+// 1 | 2 | 4 | 8 | 16 | 32
+#define KVI_USERFLAG_MASK (KVI_USERFLAG_OP | KVI_USERFLAG_VOICE | KVI_USERFLAG_HALFOP | KVI_USERFLAG_CHANADMIN | KVI_USERFLAG_USEROP | KVI_USERFLAG_CHANOWNER)
+// at the moment all the flags are usermodes
+#define KVI_USERFLAG_MODEMASK KVI_USERFLAG_MASK
+
+
+class KVILIB_API KviIrcUserDataBase : public QObject
+{
+ Q_OBJECT
+public:
+ KviIrcUserDataBase();
+ ~KviIrcUserDataBase();
+private:
+ KviPointerHashTable<QString,KviIrcUserEntry> * m_pDict;
+public:
+ void clear();
+ KviIrcUserEntry * insertUser(const QString &nick,const QString &user,const QString &hostname);
+ KviIrcUserEntry * find(const QString &nick){ return m_pDict->find(nick); };
+ void removeUser(const QString &nick,KviIrcUserEntry * e);
+ KviPointerHashTable<QString,KviIrcUserEntry> * dict(){ return m_pDict; };
+
+ KviRegisteredUser* registeredUser(const QString & nick);
+ KviRegisteredUser* registeredUser(const QString & nick,const QString & user,const QString & host);
+
+ bool haveCustomColor(const QString & nick);
+ QColor* customColor(const QString & nick);
+
+ void setupConnectionWithReguserDb();
+protected slots:
+ void registeredUserRemoved(const QString&);
+ void registeredUserChanged(const QString&);
+ void registeredUserAdded (const QString&);
+ void registeredDatabaseCleared();
+};
+
+#endif //_KVI_IRCUSERDB_H_
diff --git a/src/kvilib/irc/kvi_mirccntrl.cpp b/src/kvilib/irc/kvi_mirccntrl.cpp
new file mode 100644
index 00000000..fbf3c2d3
--- /dev/null
+++ b/src/kvilib/irc/kvi_mirccntrl.cpp
@@ -0,0 +1,307 @@
+//
+// File : kvi_mirccntrl.cpp
+// Creation date : Sat Aug 31 17:07:36 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#define __KVILIB__
+
+#define _KVI_MIRCCNTRL_CPP_
+
+#include "kvi_mirccntrl.h"
+
+KVILIB_API const char * getColorBytes(const char *data_ptr,unsigned char *byte_1,unsigned char *byte_2)
+{
+ //
+ // Scans the data_ptr for a mIrc color code XX,XX
+ // and fills the color values in the two bytes
+ //
+
+ //First we can have a digit or a coma
+ if(((*data_ptr >= '0') && (*data_ptr <='9')))
+ {
+ //Something interesting ok.
+ (*byte_1)=(*data_ptr)-'0'; //store the code
+ data_ptr++; //and check the next
+ if(((*data_ptr >= '0') && (*data_ptr <= '9'))||(*data_ptr==','))
+ {
+ //Yes we can understand it
+ if(*data_ptr==',')
+ {
+ //A coma , need to check for background
+ data_ptr++;
+ } else {
+ //A number
+ (*byte_1)=((((*byte_1)*10)+((*data_ptr)-'0'))%16);
+ data_ptr++;
+ if(*data_ptr==',')
+ {
+ //A coma , need to check for background
+ data_ptr++;
+ } else {
+ //Senseless return
+ (*byte_2)=KVI_NOCHANGE;
+ return data_ptr;
+ }
+ }
+ } else {
+ //Senseless character control code OK and return
+ (*byte_2)=KVI_NOCHANGE;
+ return data_ptr;
+ }
+ } else {
+ //Senseless character : only a CTRL+K code
+ (*byte_1)=KVI_NOCHANGE;
+ (*byte_2)=KVI_NOCHANGE;
+ return data_ptr;
+ }
+
+ if((*data_ptr >= '0') && (*data_ptr <='9'))
+ {
+ //Background , a color code
+ (*byte_2)=(*data_ptr)-'0';
+ data_ptr++;
+ if((*data_ptr >= '0') && (*data_ptr <='9'))
+ {
+ (*byte_2)=((((*byte_2)*10)+((*data_ptr)-'0'))%16);
+ data_ptr++;
+ }
+ return data_ptr;
+ } else {
+ (*byte_2)=KVI_NOCHANGE;
+ return data_ptr-1;
+ }
+}
+
+
+KVILIB_API const kvi_wchar_t * getColorBytesW(const kvi_wchar_t *data_ptr,unsigned char *byte_1,unsigned char *byte_2)
+{
+ //
+ // Scans the data_ptr for a mIrc color code XX,XX
+ // and fills the color values in the two bytes
+ //
+
+ //First we can have a digit or a coma
+ if(((*data_ptr >= '0') && (*data_ptr <='9')))
+ {
+ //Something interesting ok.
+ (*byte_1)=((*data_ptr)-'0'); //store the code
+ data_ptr++; //and check the next
+ if(((*data_ptr >= '0') && (*data_ptr <= '9'))||(*data_ptr==','))
+ {
+ //Yes we can understand it
+ if(*data_ptr==',')
+ {
+ //A coma , need to check for background
+ data_ptr++;
+ } else {
+ //A number
+ //(*byte_1)=((((*byte_1)*10)+((*data_ptr)-'0'))%16);
+ (*byte_1)=((*byte_1)*10)+((*data_ptr)-'0');
+ data_ptr++;
+ if(*data_ptr==',')
+ {
+ //A coma , need to check for background
+ data_ptr++;
+ } else {
+ //Senseless return
+ (*byte_2)=KVI_NOCHANGE;
+ return data_ptr;
+ }
+ }
+ } else {
+ //Senseless character control code OK and return
+ (*byte_2)=KVI_NOCHANGE;
+ return data_ptr;
+ }
+ } else {
+ //Senseless character : only a CTRL+K code
+ (*byte_1)=KVI_NOCHANGE;
+ (*byte_2)=KVI_NOCHANGE;
+ return data_ptr;
+ }
+
+ if((*data_ptr >= '0') && (*data_ptr <='9'))
+ {
+ //Background , a color code
+ (*byte_2)=(*data_ptr)-'0';
+ data_ptr++;
+ if((*data_ptr >= '0') && (*data_ptr <='9'))
+ {
+ //(*byte_2)=((((*byte_2)*10)+((*data_ptr)-'0'))%16);
+ (*byte_2)=((*byte_2)*10)+((*data_ptr)-'0');
+ data_ptr++;
+ }
+ return data_ptr;
+ } else {
+ (*byte_2)=KVI_NOCHANGE;
+ return data_ptr-1;
+ }
+}
+
+KVILIB_API unsigned int getUnicodeColorBytes(const QString &szData,unsigned int charIdx,unsigned char *byte_1,unsigned char *byte_2)
+{
+ //
+ // Scans the szData for a mIrc color code XX,XX
+ // and fills the color values in the two bytes
+ //
+
+ if(charIdx >= szData.length())
+ {
+ (*byte_1)=KVI_NOCHANGE;
+ (*byte_2)=KVI_NOCHANGE;
+ return charIdx;
+ }
+
+ unsigned short c = szData[(int)charIdx].unicode();
+
+ //First we can have a digit or a coma
+ if(((c < '0') || (c > '9')))
+ {
+ // senseless : only a CTRL+K code
+ (*byte_1)=KVI_NOCHANGE;
+ (*byte_2)=KVI_NOCHANGE;
+ return charIdx;
+ }
+
+ //Something interesting ok.
+ (*byte_1)=c - '0'; //store the code
+ charIdx++;
+ if(charIdx >= szData.length())
+ {
+ (*byte_2)=KVI_NOCHANGE;
+ return charIdx;
+ }
+
+ c = szData[(int)charIdx].unicode();
+
+ if(((c < '0') || (c > '9')) && (c != ','))
+ {
+ (*byte_2)=KVI_NOCHANGE;
+ return charIdx;
+ }
+
+
+ if((c >= '0') && (c <= '9'))
+ {
+ (*byte_1)=(((*byte_1)*10)+(c-'0'))%16;
+ charIdx++;
+ if(charIdx >= szData.length())
+ {
+ (*byte_2)=KVI_NOCHANGE;
+ return charIdx;
+ }
+ c = szData[(int)charIdx].unicode();
+ }
+
+ if(c == ',')
+ {
+ charIdx++;
+ if(charIdx >= szData.length())
+ {
+ (*byte_2)=KVI_NOCHANGE;
+ return charIdx;
+ }
+ c = szData[(int)charIdx].unicode();
+ } else {
+ (*byte_2)=KVI_NOCHANGE;
+ return charIdx;
+ }
+
+ if((c < '0') || (c > '9'))
+ {
+ (*byte_2)=KVI_NOCHANGE;
+ if(szData[(int)(charIdx-1)].unicode()==',')
+ return charIdx-1;
+ else
+ return charIdx;
+ }
+
+ //Background , a color code
+ (*byte_2)=c-'0';
+ charIdx++;
+ if(charIdx >= szData.length())return charIdx;
+ c = szData[(int)charIdx].unicode();
+
+ if((c >= '0') && (c <='9'))
+ {
+ (*byte_2)=(((*byte_2)*10)+(c-'0'))%16;
+ charIdx++;
+ }
+
+ return charIdx;
+}
+
+
+namespace KviMircCntrl
+{
+ QString stripControlBytes(const QString &szData)
+ {
+ QString ret;
+
+ int i = 0;
+ int l = szData.length();
+ int begin = 0;
+ unsigned char b1;
+ unsigned char b2;
+ while(i < l)
+ {
+ switch(szData[i].unicode())
+ {
+ case KVI_TEXT_UNDERLINE:
+ case KVI_TEXT_BOLD:
+ case KVI_TEXT_RESET:
+ case KVI_TEXT_REVERSE:
+ case KVI_TEXT_CRYPTESCAPE:
+ case KVI_TEXT_CTCP:
+ if(i != begin)
+ ret += szData.mid(begin,i - begin);
+ i++;
+ begin = i;
+ break;
+ case KVI_TEXT_COLOR:
+ if(i != begin)
+ ret += szData.mid(begin,i - begin);
+ i++;
+ i = getUnicodeColorBytes(szData,i,&b1,&b2);
+ begin = i;
+ break;
+ case KVI_TEXT_ICON:
+ if(i != begin)
+ ret += szData.mid(begin,i - begin);
+ i++;
+ while(i < l)
+ {
+ if(szData[i].unicode() == ' ')break;
+ else i++;
+ }
+ begin = i;
+ break;
+ default:
+ i++;
+ break;
+ }
+ }
+ if(i != begin)
+ ret += szData.mid(begin,i - begin);
+ return ret;
+ }
+}
+
+
diff --git a/src/kvilib/irc/kvi_mirccntrl.h b/src/kvilib/irc/kvi_mirccntrl.h
new file mode 100644
index 00000000..c3028568
--- /dev/null
+++ b/src/kvilib/irc/kvi_mirccntrl.h
@@ -0,0 +1,163 @@
+#ifndef _KVI_MIRCCNTRL_H_
+#define _KVI_MIRCCNTRL_H_
+
+//=============================================================================
+//
+// File : kvi_mirccntrl.h
+// Creation date : Thu Jun 29 2000 21:06:55 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+//=============================================================================
+// This file contains non-customizable standards
+//
+// Better do not touch this :)
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_string.h"
+
+//
+// mIrc color codes
+//
+
+#define KVI_WHITE 0
+#define KVI_BLACK 1
+#define KVI_DARKBLUE 2
+#define KVI_DARKGREEN 3
+#define KVI_RED 4
+#define KVI_DARKRED 5
+#define KVI_DARKVIOLET 6
+#define KVI_ORANGE 7
+#define KVI_YELLOW 8
+#define KVI_LIGHTGREEN 9
+#define KVI_BLUEMARINE 10
+#define KVI_LIGHTBLUE 11
+#define KVI_BLUE 12
+#define KVI_LIGHTVIOLET 13
+#define KVI_DARKGRAY 14
+#define KVI_LIGHTGRAY 15
+
+#define KVI_MIRCCOLOR_MAX_FOREGROUND 15
+#define KVI_MIRCCOLOR_MAX_BACKGROUND 15
+
+//
+// Non-standard color codes for KviIrcView
+//
+#define KVI_TRANSPARENT 100
+#define KVI_NOCHANGE 101
+//
+// Internal control codes for KviIrcView
+//
+// (Totally artificial and internal to KviIrcView)
+#define KVI_TEXT_ESCAPE 0x04
+#define KVI_TEXT_UNESCAPE 0x05
+#define KVI_TEXT_UNICON 0x06
+//#define KVI_TEXT_EMOTICON 0x07
+
+// ASCII Stuff: the following defines are meant to be escape sequences
+// that can go thru an IRC connection
+
+// The following table is a 30-minute analysis of the escape characters commonly used over the IRC protocol...
+// created when looking for a good placement for the CRYPT escape char in KVirc.
+// I guess that the best chars to be used were FS,GS,RS,US,DC1,DC2,DC3,DC4...they have the "less defined"
+// meaning as ASCII control chars.
+// mmmh... :)
+
+// ASCII IRC Meaning
+// 000 NUL Null (Cannot be assigned)
+// 001 SOH Start of heading ( CTCP Escape: only beginning of the message )
+// 002 STX Start of text ( Bold text )
+// 003 ETX End of text ( Color text escape sequence )
+// 004 EOT End of transmission ( Assigned internally (escape) )
+// 005 ENQ Enquiry (WRU: Who are you) ( Assigned internally (unescape) )
+// 006 ACK Acknowledge (Not so good, but can be used as last resource)
+// 007 BEL Bell ( Recognized as bell by terminals and IRCII ) (Used also by some IRC servers)
+// 008 BS Backspace (Should not be assigned: terminal control)
+// 009 HT Horizontal tabulation (Should not be assigned: terminal control)
+// 010 LF Line feed (Should not be assigned: terminal control)
+// 011 VT Vertical tabulation (Should not be assigned: terminal control)
+// 012 FF Form feed (Should not be assigned: terminal control)
+// 013 CR Carriage return (Should not be assigned: terminal control)
+// 014 SO Shift out (Should not be assigned: terminal control)
+// 015 SI Shift in ( Resets Bold,Color,Underline and Reverse ) (Conflicting with terminal control)
+// 016 DLE Data link escape (Decent , can be assigned)
+// 017 DC1 Device control 1 (Good to be assigned)
+// 018 DC2 Device control 2 (Good to be assigned)
+// 019 DC3 Device control 3 (Good to be assigned)
+// 020 DC4 Device control 4 (Good to be assigned)
+// 021 NAK Negative acknowledge (Not so good, but could be used as last resource)
+// 022 SYN Synchronous idle ( Reverse text )
+// 023 ETB End of transmission block (Decent , can be assigned)
+// 024 CAN Cancel (Should not be assigned: terminal control)
+// 025 EM End of medium (Decent , can be assigned)
+// 026 SUB Substitute (Should not be assigned: terminal control)
+// 027 ESC Escape (Should not be assigned: terminal control)
+// 028 FS File separator (Excellent , should be used as first candidate)
+// 029 GS Group separator ( ICONS Escape: beginning of a word )
+// 030 RS Record separator ( CRYPT Escape: only beginning of the message )
+// 031 US Unit separator ( Underline text )
+
+
+//
+// mIrc control codes
+//
+
+//31 (0001 1111) US (Unit separator)
+#define KVI_TEXT_UNDERLINE 0x1f
+//2 (0000 0010) STX (Start of text)
+#define KVI_TEXT_BOLD 0x02
+//15 (0000 1111) SI (Shift in)
+#define KVI_TEXT_RESET 0x0f
+//22 (0001 0110) SYN (Synchronous idle)
+#define KVI_TEXT_REVERSE 0x16
+//3 (0000 0011) ETX (End of text)
+#define KVI_TEXT_COLOR 0x03
+
+//
+// Irc control codes
+//
+//1 (0000 0001) SOH (Start of heading)
+#define KVI_TEXT_CTCP 0x01
+
+//
+// KVirc added control codes
+//
+//30 (0001 1110) RS (Record separator)
+#define KVI_TEXT_CRYPTESCAPE 0x1e
+//29 (0001 1101) GS (Group separator)
+#define KVI_TEXT_ICON 0x1d
+
+#ifndef _KVI_MIRCCNTRL_CPP_
+ extern KVILIB_API const char * getColorBytes(const char *data_ptr,unsigned char *byte_1,unsigned char *byte_2);
+ extern KVILIB_API const kvi_wchar_t * getColorBytesW(const kvi_wchar_t *data_ptr,unsigned char *byte_1,unsigned char *byte_2);
+ extern KVILIB_API unsigned int getUnicodeColorBytes(const QString &szData,unsigned int charIdx,unsigned char *byte_1,unsigned char *byte_2);
+ inline const QChar * getUnicodeColorBytes(const QChar *pData,unsigned char *byte_1,unsigned char *byte_2)
+ { return (QChar *)getColorBytesW((const kvi_wchar_t *)pData,byte_1,byte_2); };
+
+#endif
+
+namespace KviMircCntrl
+{
+ KVILIB_API QString stripControlBytes(const QString &szData);
+}
+
+
+#endif //_KVI_MIRCCNTRL_H_
diff --git a/src/kvilib/irc/kvi_nickserv.cpp b/src/kvilib/irc/kvi_nickserv.cpp
new file mode 100644
index 00000000..a1809f84
--- /dev/null
+++ b/src/kvilib/irc/kvi_nickserv.cpp
@@ -0,0 +1,312 @@
+//=============================================================================
+//
+// File : kvi_nickserv.cpp
+// Creation date : Thu Aug 09 2001 17:44:56 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+
+
+#include "kvi_nickserv.h"
+#include "kvi_config.h"
+#include "kvi_ircmask.h"
+
+#include <qregexp.h>
+
+
+
+/*
+ @doc: nickserv_proto
+ @title:
+ Authentication with NickServ
+ @keyterms:
+ NickServ, automatic authentication with NickServ
+ @type:
+ generic
+ @short:
+ Automatic authentication with NickServ
+ @body:
+ KVIrc supports automatic authentication with the NickServ service.[br]
+ This service is commonly implemented on major IRC networks: basically
+ it is a program that allows users to register their nickname and protect
+ it from being stolen by others.[br] The NickServ protocol is
+ not standardized (at the time that I'm writing this doc) and automatic
+ authentication is a pure experimental protocol.[br]
+ Once you get on IRC with a registered nickname , the NickServ will
+ ask you for identification by sending you a NOTICE.[br]
+ The message will look in a way similar to the following:[br]
+ <b>You're using a registered nickname: if this is your nick,
+ please type /msg NickServ IDENTIFY password, otherwise please
+ choose another nickname</b>.[br]
+ The message is often broken in two or three lines of text.[br]
+ Please note that many network policies suggest to avoid automatic authentication
+ with NickServ.[br]I have implemented it because I know that it works on the networks
+ that I'm usually on.[br]You have to check that this protocol works on your network and
+ then eventually use it at your own risk.[br]
+*/
+
+
+// FIXME: The doc above is a bit outdated , fix it
+
+KviNickServRuleSet::KviNickServRuleSet()
+: KviHeapObject()
+{
+ m_bEnabled = false;
+ m_pRules = 0;
+}
+
+KviNickServRuleSet::KviNickServRuleSet(const KviNickServRuleSet &s)
+{
+ m_pRules = 0;
+ copyFrom(s);
+}
+
+
+KviNickServRuleSet::~KviNickServRuleSet()
+{
+ if(m_pRules)delete m_pRules;
+}
+
+void KviNickServRuleSet::save(KviConfig * cfg,const QString &prefix)
+{
+ if(!m_pRules)return; // nothing to save
+ if(m_pRules->isEmpty())return; // should never happen anyway
+ QString tmp;
+ if(m_bEnabled)
+ {
+ KviQString::sprintf(tmp,"%QNSEnabled",&prefix);
+ cfg->writeEntry(tmp,m_bEnabled);
+ }
+ KviQString::sprintf(tmp,"%QNSRules",&prefix);
+ cfg->writeEntry(tmp,m_pRules->count());
+ int idx = 0;
+ for(KviNickServRule * r = m_pRules->first();r;r = m_pRules->next())
+ {
+ KviQString::sprintf(tmp,"%QNSRule%d_",&prefix,idx);
+ r->save(cfg,tmp);
+ idx++;
+ }
+}
+
+KviNickServRuleSet * KviNickServRuleSet::load(KviConfig * cfg,const QString &prefix)
+{
+ QString tmp;
+ KviQString::sprintf(tmp,"%QNSRules",&prefix);
+ unsigned int cnt = cfg->readUIntEntry(tmp,0);
+ if(cnt == 0)return 0;
+ KviNickServRuleSet * s = new KviNickServRuleSet();
+ if(s->loadPrivate(cfg,prefix,cnt))return s;
+ delete s;
+ return 0;
+}
+
+void KviNickServRuleSet::load(const QString &szConfigFile)
+{
+ clear();
+ KviConfig cfg(szConfigFile,KviConfig::Read);
+
+ QString tmp;
+ KviQString::sprintf(tmp,"NSRules");
+ unsigned int cnt = cfg.readUIntEntry(tmp,0);
+ if(cnt == 0)return;
+ loadPrivate(&cfg,QString(""),cnt);
+}
+
+void KviNickServRuleSet::save(const QString &szConfigFile)
+{
+ KviConfig cfg(szConfigFile,KviConfig::Write);
+ cfg.clear();
+ save(&cfg,QString(""));
+}
+
+bool KviNickServRuleSet::loadPrivate(KviConfig * cfg,const QString &prefix,unsigned int nEntries)
+{
+ if(m_pRules)m_pRules->clear();
+ else {
+ m_pRules = new KviPointerList<KviNickServRule>;
+ m_pRules->setAutoDelete(true);
+ }
+
+ if(nEntries != 0)
+ {
+ QString tmp;
+ KviQString::sprintf(tmp,"%QNSEnabled",&prefix);
+ m_bEnabled = cfg->readBoolEntry(tmp,false);
+ for(unsigned int u=0;u<nEntries;u++)
+ {
+ KviQString::sprintf(tmp,"%QNSRule%u_",&prefix,u);
+ KviNickServRule * r = new KviNickServRule();
+ if(!r->load(cfg,tmp))delete r;
+ else m_pRules->append(r);
+ }
+ }
+
+ if(m_pRules->isEmpty())
+ {
+ m_bEnabled = false;
+ delete m_pRules;
+ m_pRules = 0;
+ return false;
+ }
+ return true;
+}
+
+void KviNickServRuleSet::clear()
+{
+ if(m_pRules)
+ {
+ delete m_pRules;
+ m_pRules = 0;
+ }
+ m_bEnabled = false;
+}
+
+void KviNickServRuleSet::addRule(KviNickServRule * r)
+{
+ if(!m_pRules)
+ {
+ m_pRules = new KviPointerList<KviNickServRule>;
+ m_pRules->setAutoDelete(true);
+ }
+ m_pRules->append(r);
+}
+
+KviNickServRuleSet * KviNickServRuleSet::createInstance()
+{
+ return new KviNickServRuleSet();
+}
+
+
+KviNickServRule * KviNickServRuleSet::matchRule(const QString &szNick,const KviIrcMask *nickServ,const QString &szMsg,const QString &szServer)
+{
+ if(!m_pRules)return 0;
+ for(KviNickServRule *r = m_pRules->first();r;r = m_pRules->next())
+ {
+ if(!KviQString::matchStringCI(r->registeredNick(),szNick,false,true)) continue;
+ if(!szServer.isEmpty())
+ {
+#ifdef COMPILE_USE_QT4
+ QRegExp res(r->serverMask(),Qt::CaseInsensitive,QRegExp::Wildcard);
+#else
+ QRegExp res(r->serverMask(),false,true);
+#endif
+ if(!res.exactMatch(szServer))continue;
+ }
+ if(!nickServ->matchedBy(KviIrcMask(r->nickServMask())))continue;
+#ifdef COMPILE_USE_QT4
+ QRegExp re(r->messageRegexp(),Qt::CaseInsensitive,QRegExp::Wildcard);
+#else
+ QRegExp re(r->messageRegexp(),false,true);
+#endif
+ if(re.exactMatch(szMsg))return r;
+ }
+ return 0;
+}
+
+void KviNickServRuleSet::copyFrom(const KviNickServRuleSet &src)
+{
+ if(src.m_pRules)
+ {
+ if(m_pRules)m_pRules->clear();
+ else {
+ m_pRules = new KviPointerList<KviNickServRule>;
+ m_pRules->setAutoDelete(true);
+ }
+ for(KviNickServRule * r = src.m_pRules->first();r;r = src.m_pRules->next())
+ {
+ KviNickServRule * c = new KviNickServRule();
+ c->copyFrom(*r);
+ m_pRules->append(c);
+ }
+ if(m_pRules->isEmpty())
+ {
+ m_bEnabled = false;
+ delete m_pRules;
+ m_pRules = 0;
+ } else {
+ m_bEnabled = src.m_bEnabled;
+ }
+ } else {
+ m_bEnabled = false;
+ if(m_pRules)
+ {
+ delete m_pRules;
+ m_pRules = 0;
+ }
+ }
+}
+
+
+void KviNickServRule::copyFrom(const KviNickServRule &src)
+{
+ m_szRegisteredNick = src.m_szRegisteredNick;
+ m_szNickServMask = src.m_szNickServMask;
+ m_szMessageRegexp = src.m_szMessageRegexp;
+ m_szIdentifyCommand = src.m_szIdentifyCommand;
+ m_szServerMask = src.m_szServerMask;
+}
+
+void KviNickServRule::save(KviConfig * cfg,const QString &prefix)
+{
+ QString tmp;
+ KviQString::sprintf(tmp,"%QRegisteredNick",&prefix);
+ cfg->writeEntry(tmp,m_szRegisteredNick);
+ KviQString::sprintf(tmp,"%QNickServMask",&prefix);
+ cfg->writeEntry(tmp,m_szNickServMask);
+ KviQString::sprintf(tmp,"%QMessageRegexp",&prefix);
+ cfg->writeEntry(tmp,m_szMessageRegexp);
+ KviQString::sprintf(tmp,"%QIdentifyCommand",&prefix);
+ cfg->writeEntry(tmp,m_szIdentifyCommand);
+ KviQString::sprintf(tmp,"%QServerMask",&prefix);
+ cfg->writeEntry(tmp,m_szServerMask);
+}
+
+bool KviNickServRule::load(KviConfig * cfg,const QString &prefix)
+{
+ QString tmp;
+ KviQString::sprintf(tmp,"%QRegisteredNick",&prefix);
+ m_szRegisteredNick = KviQString::trimmed(cfg->readQStringEntry(tmp));
+ if(m_szRegisteredNick.isEmpty())return false;
+ KviQString::sprintf(tmp,"%QNickServMask",&prefix);
+ m_szNickServMask = cfg->readQStringEntry(tmp);
+ if(m_szNickServMask.isEmpty())return false;
+ KviQString::sprintf(tmp,"%QServerMask",&prefix);
+ m_szServerMask = cfg->readQStringEntry(tmp,QString::null);
+ KviQString::sprintf(tmp,"%QMessageRegexp",&prefix);
+ m_szMessageRegexp = cfg->readQStringEntry(tmp);
+ if(m_szMessageRegexp.isEmpty())return false;
+ KviQString::sprintf(tmp,"%QIdentifyCommand",&prefix);
+ m_szIdentifyCommand = cfg->readQStringEntry(tmp);
+ return !m_szIdentifyCommand.isEmpty();
+}
+
+KviNickServRule * KviNickServRule::createInstance(const QString &szRegisteredNick,
+ const QString &szNickServMask,
+ const QString &szMessageRegexp,
+ const QString &szIdentifyCommand,
+ const QString &szServerMask)
+{
+ return new KviNickServRule(szRegisteredNick,szNickServMask,szMessageRegexp,szIdentifyCommand,szServerMask);
+}
+
+
+
+
diff --git a/src/kvilib/irc/kvi_nickserv.h b/src/kvilib/irc/kvi_nickserv.h
new file mode 100644
index 00000000..105eed1c
--- /dev/null
+++ b/src/kvilib/irc/kvi_nickserv.h
@@ -0,0 +1,112 @@
+#ifndef _KVI_NICKSERV_H_
+#define _KVI_NICKSERV_H_
+//=============================================================================
+//
+// File : kvi_nickserv.h
+// Creation date : Thu Aug 09 2001 16:43:56 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_heapobject.h"
+#include "kvi_pointerlist.h"
+
+class KviConfig;
+class KviIrcMask;
+
+class KVILIB_API KviNickServRule : public KviHeapObject
+{
+protected:
+ QString m_szRegisteredNick; // my registered nickname
+ QString m_szNickServMask; // the NickServ service mask
+ QString m_szMessageRegexp; // the NickServ message regexp
+ QString m_szIdentifyCommand; // the IDENTIFY command to send to server
+ QString m_szServerMask; // the mask that the server must match (not used in per-network rules)
+public:
+ KviNickServRule() : KviHeapObject() {};
+ KviNickServRule(
+ const QString &szRegisteredNick,
+ const QString &szNickServMask,
+ const QString &szMessageRegexp,
+ const QString &szIdentifyCommand,
+ const QString &szServerMask = QString::null)
+ : KviHeapObject(),
+ m_szRegisteredNick(szRegisteredNick),
+ m_szNickServMask(szNickServMask),
+ m_szMessageRegexp(szMessageRegexp),
+ m_szIdentifyCommand(szIdentifyCommand),
+ m_szServerMask(szServerMask)
+ {};
+public:
+ const QString & registeredNick() const { return m_szRegisteredNick; };
+ const QString & nickServMask() const { return m_szNickServMask; };
+ const QString & messageRegexp() const { return m_szMessageRegexp; };
+ const QString & identifyCommand() const { return m_szIdentifyCommand; };
+ const QString & serverMask() const { return m_szServerMask; };
+ void setRegisteredNick(const QString &szRegisteredNick){ m_szRegisteredNick = szRegisteredNick; };
+ void setNickServMask(const QString &szNickServMask){ m_szNickServMask = szNickServMask; };
+ void setMessageRegexp(const QString &szMessageRegexp){ m_szMessageRegexp = szMessageRegexp; };
+ void setIdentifyCommand(const QString &szIdentifyCommand){ m_szIdentifyCommand = szIdentifyCommand; };
+ void setServerMask(const QString &szServerMask){ m_szServerMask = szServerMask; };
+public:
+ // avoid crashes under windows
+ static KviNickServRule * createInstance(const QString &szRegisteredNick,
+ const QString &szNickServMask,
+ const QString &szMessageRegexp,
+ const QString &szIdentifyCommand,
+ const QString &szServerMask = QString::null);
+
+ void save(KviConfig * cfg,const QString &prefix);
+ // returns false if the loaded data has no sense
+ bool load(KviConfig * cfg,const QString &prefix);
+ void copyFrom(const KviNickServRule &src);
+};
+
+class KVILIB_API KviNickServRuleSet : public KviHeapObject
+{
+public:
+ KviNickServRuleSet();
+ KviNickServRuleSet(const KviNickServRuleSet &s);
+ ~KviNickServRuleSet();
+protected:
+ KviPointerList<KviNickServRule> * m_pRules; // FIXME: Replace with KviPointerHashTable<QString,KviPointerList>
+ bool m_bEnabled;
+public:
+ // avoid crashes under windows
+ static KviNickServRuleSet * createInstance();
+ void clear();
+ bool isEnabled(){ return m_bEnabled; };
+ void setEnabled(bool bEnabled){ m_bEnabled = bEnabled; };
+ bool isEmpty(){ return m_pRules ? m_pRules->isEmpty() : true; };
+ void addRule(KviNickServRule * r);
+ KviNickServRule * matchRule(const QString &szNick,const KviIrcMask *nickServ,const QString &szMsg,const QString &szServer = QString::null);
+ void copyFrom(const KviNickServRuleSet &src);
+ void load(const QString &szConfigFile);
+ void save(const QString &szConfigFile);
+ void save(KviConfig * cfg,const QString &prefix);
+ KviPointerList<KviNickServRule> * rules(){ return m_pRules; };
+ static KviNickServRuleSet * load(KviConfig * cfg,const QString &prefix);
+protected:
+ bool loadPrivate(KviConfig * cfg,const QString &prefix,unsigned int nEntries);
+};
+
+
+#endif // _KVI_NICKSERV_H_
diff --git a/src/kvilib/irc/kvi_useridentity.cpp b/src/kvilib/irc/kvi_useridentity.cpp
new file mode 100644
index 00000000..d4791333
--- /dev/null
+++ b/src/kvilib/irc/kvi_useridentity.cpp
@@ -0,0 +1,252 @@
+//=============================================================================
+//
+// File : kvi_useridentity.cpp
+// Created on Sun 21 Jan 2007 04:31:47 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2007 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+
+#include "kvi_useridentity.h"
+#include "kvi_locale.h"
+#include "kvi_defaults.h"
+
+// FIXME: Put here also the default away message, default away nick, default ctcp replies etc ?
+
+bool KviUserIdentity::load(KviConfig &cfg)
+{
+ m_szId = cfg.group();
+ m_szNickName = cfg.readQStringEntry("NickName");
+ m_szAltNickName1 = cfg.readQStringEntry("AltNickName1");
+ m_szAltNickName2 = cfg.readQStringEntry("AltNickName2");
+ m_szAltNickName3 = cfg.readQStringEntry("AltNickName3");
+ m_szUserName = cfg.readQStringEntry("UserName");
+ // FIXME: At least scramble the pass ?
+ m_szPassword = cfg.readQStringEntry("Password");
+ KviPixmap def;
+ m_pixAvatar = cfg.readPixmapEntry("Avatar",def);
+ m_szPartMessage = cfg.readQStringEntry("PartMessage");
+ m_szQuitMessage= cfg.readQStringEntry("QuitMessage");
+ m_szAge = cfg.readQStringEntry("Age");
+ m_szGender = cfg.readQStringEntry("Gender");
+ m_szLocation = cfg.readQStringEntry("Location");
+ m_szLanguages = cfg.readQStringEntry("Languages");
+ m_szOtherInfo = cfg.readQStringEntry("OtherInfo");
+ m_szUserMode = cfg.readQStringEntry("UserMode");
+ m_szOnConnectCommand = cfg.readQStringEntry("OnConnectCommand");
+ m_szOnLoginCommand = cfg.readQStringEntry("OnLoginCommand");
+ return !(m_szId.isEmpty() || m_szNickName.isEmpty());
+}
+
+bool KviUserIdentity::save(KviConfig &cfg)
+{
+ cfg.setGroup(m_szId);
+ cfg.writeEntry("NickName",m_szNickName);
+ cfg.writeEntry("AltNickName1",m_szAltNickName1);
+ cfg.writeEntry("AltNickName2",m_szAltNickName2);
+ cfg.writeEntry("AltNickName3",m_szAltNickName3);
+ cfg.writeEntry("UserName",m_szUserName);
+ // FIXME: At least scramble the pass ?
+ cfg.writeEntry("Password",m_szPassword);
+ cfg.writeEntry("Avatar",m_pixAvatar);
+ cfg.writeEntry("PartMessage",m_szPartMessage);
+ cfg.writeEntry("QuitMessage",m_szQuitMessage);
+ cfg.writeEntry("Age",m_szAge);
+ cfg.writeEntry("Gender",m_szGender);
+ cfg.writeEntry("Location",m_szLocation);
+ cfg.writeEntry("Languages",m_szLanguages);
+ cfg.writeEntry("OtherInfo",m_szOtherInfo);
+ cfg.writeEntry("UserMode",m_szUserMode);
+ cfg.writeEntry("OnConnectCommand",m_szOnConnectCommand);
+ cfg.writeEntry("OnLoginCommand",m_szOnLoginCommand);
+ return true;
+}
+
+void KviUserIdentity::copyFrom(const KviUserIdentity &src)
+{
+ m_szId = src.m_szId;
+ m_szNickName = src.m_szNickName;
+
+ m_szAltNickName1 = src.m_szAltNickName1;
+ m_szAltNickName2 = src.m_szAltNickName2;
+ m_szAltNickName3 = src.m_szAltNickName3;
+
+ m_szUserName = src.m_szUserName;
+ m_szRealName = src.m_szRealName;
+ m_szPassword = src.m_szPassword;
+
+ m_pixAvatar = src.m_pixAvatar;
+
+ m_szUserName = src.m_szUserName;
+ m_szRealName = src.m_szRealName;
+ m_szPassword = src.m_szPassword;
+
+ m_pixAvatar = src.m_pixAvatar;
+
+ m_szPartMessage = src.m_szPartMessage;
+ m_szQuitMessage = src.m_szQuitMessage;
+
+ m_szAge = src.m_szAge;
+ m_szGender = src.m_szGender;
+ m_szLocation = src.m_szLocation;
+ m_szLanguages = src.m_szLanguages;
+ m_szOtherInfo = src.m_szOtherInfo;
+
+ m_szUserMode = src.m_szUserMode;
+
+ m_szOnConnectCommand = src.m_szOnConnectCommand;
+ m_szOnLoginCommand = src.m_szOnLoginCommand;
+}
+
+
+KviUserIdentityManager * KviUserIdentityManager::m_pInstance = 0;
+
+KviUserIdentityManager::KviUserIdentityManager()
+: KviHeapObject()
+{
+ m_pIdentityDict = new KviPointerHashTable<QString,KviUserIdentity>();
+ m_pIdentityDict->setAutoDelete(true);
+}
+
+KviUserIdentityManager::~KviUserIdentityManager()
+{
+ delete m_pIdentityDict;
+}
+
+void KviUserIdentityManager::init()
+{
+ if(m_pInstance)return;
+ m_pInstance = new KviUserIdentityManager();
+}
+
+void KviUserIdentityManager::done()
+{
+ if(!m_pInstance)return;
+ delete m_pInstance;
+ m_pInstance = 0;
+}
+
+const KviUserIdentity * KviUserIdentityManager::defaultIdentity()
+{
+ KviUserIdentity * ret;
+ if(!m_szDefaultIdentity.isEmpty())
+ {
+ ret = m_pIdentityDict->find(m_szDefaultIdentity);
+ if(ret)return ret;
+ }
+
+ // the default identity is borken :/
+ // grab the first one
+ KviPointerHashTableIterator<QString,KviUserIdentity> it(*m_pIdentityDict);
+ ret = it.current();
+ if(ret)
+ {
+ m_szDefaultIdentity = ret->id();
+ return ret;
+ }
+ // no identities available: create the default
+ ret = new KviUserIdentity();
+
+ ret->setId(__tr2qs("Default"));
+ ret->setNickName(KVI_DEFAULT_NICKNAME1);
+ ret->setAltNickName1(KVI_DEFAULT_NICKNAME2);
+ ret->setAltNickName2(KVI_DEFAULT_NICKNAME3);
+ ret->setAltNickName3(KVI_DEFAULT_NICKNAME4);
+ ret->setUserName(KVI_DEFAULT_USERNAME);
+ ret->setRealName(KVI_DEFAULT_REALNAME);
+ ret->setPartMessage(KVI_DEFAULT_PART_MESSAGE);
+ ret->setQuitMessage(KVI_DEFAULT_QUIT_MESSAGE);
+
+ m_pIdentityDict->replace(ret->id(),ret);
+
+ return ret;
+}
+
+void KviUserIdentityManager::load(const QString &szFileName)
+{
+ m_pIdentityDict->clear();
+
+ KviConfig cfg(szFileName,KviConfig::Read);
+
+ cfg.setGroup("KVIrc");
+
+ m_szDefaultIdentity = cfg.readQStringEntry("DefaultIdentity","");
+
+ KviConfigIterator it(*(cfg.dict()));
+ while(KviConfigGroup * grp = it.current())
+ {
+ if(!KviQString::equalCI(it.currentKey(),"KVIrc"))
+ {
+ cfg.setGroup(it.currentKey());
+
+ KviUserIdentity * id = new KviUserIdentity();
+ if(id->load(cfg))
+ m_pIdentityDict->replace(id->id(),id);
+ else
+ delete id;
+ }
+ ++it;
+ }
+}
+
+void KviUserIdentityManager::save(const QString &szFileName)
+{
+ KviConfig cfg(szFileName,KviConfig::Write);
+ cfg.clear();
+
+ cfg.setGroup("KVIrc");
+
+ cfg.writeEntry("DefaultIdentity",m_szDefaultIdentity);
+
+ KviPointerHashTableIterator<QString,KviUserIdentity> it(*m_pIdentityDict);
+ while(KviUserIdentity * id = it.current())
+ {
+ id->save(cfg);
+ ++it;
+ }
+}
+
+void KviUserIdentityManager::copyFrom(KviUserIdentityManager * pWorkingCopy)
+{
+ m_pIdentityDict->clear();
+ m_szDefaultIdentity = pWorkingCopy->m_szDefaultIdentity;
+ KviPointerHashTableIterator<QString,KviUserIdentity> it(*(pWorkingCopy->m_pIdentityDict));
+ while(KviUserIdentity * id = it.current())
+ {
+ KviUserIdentity * pNew = new KviUserIdentity();
+ pNew->copyFrom(*id);
+ m_pIdentityDict->replace(pNew->id(),pNew);
+ ++it;
+ }
+}
+
+KviUserIdentityManager * KviUserIdentityManager::createWorkingCopy()
+{
+ KviUserIdentityManager * pCopy = new KviUserIdentityManager();
+ pCopy->copyFrom(this);
+ return pCopy;
+}
+
+void KviUserIdentityManager::releaseWorkingCopy(KviUserIdentityManager * pWorkingCopy)
+{
+ if(pWorkingCopy)delete pWorkingCopy;
+}
+
+
diff --git a/src/kvilib/irc/kvi_useridentity.h b/src/kvilib/irc/kvi_useridentity.h
new file mode 100644
index 00000000..c1018f1a
--- /dev/null
+++ b/src/kvilib/irc/kvi_useridentity.h
@@ -0,0 +1,145 @@
+#ifndef _KVI_USERIDENTITY_H_
+#define _KVI_USERIDENTITY_H_
+//=============================================================================
+//
+// File : kvi_useridentity.h
+// Created on Sun 21 Jan 2007 04:31:47 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2007 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_heapobject.h"
+#include "kvi_pixmap.h"
+#include "kvi_config.h"
+#include "kvi_pointerhashtable.h"
+
+class KVILIB_API KviUserIdentity : public KviHeapObject
+{
+ friend class KviUserIdentityManager;
+public:
+ KviUserIdentity()
+ : KviHeapObject()
+ {
+ }
+ ~KviUserIdentity()
+ {
+ }
+protected:
+ QString m_szId; // the identity set name
+
+ QString m_szNickName;
+
+ QString m_szAltNickName1;
+ QString m_szAltNickName2;
+ QString m_szAltNickName3;
+
+ QString m_szUserName;
+ QString m_szRealName;
+ QString m_szPassword;
+
+ KviPixmap m_pixAvatar;
+
+ QString m_szPartMessage;
+ QString m_szQuitMessage;
+
+ QString m_szAge;
+ QString m_szGender;
+ QString m_szLocation;
+ QString m_szLanguages;
+ QString m_szOtherInfo;
+
+ QString m_szUserMode;
+
+ QString m_szOnConnectCommand;
+ QString m_szOnLoginCommand;
+public:
+ const QString & id() const { return m_szId; };
+ const QString & nickName() const { return m_szNickName; };
+ const QString & altNickName1() const { return m_szAltNickName1; };
+ const QString & altNickName2() const { return m_szAltNickName2; };
+ const QString & altNickName3() const { return m_szAltNickName3; };
+ const QString & userName() const { return m_szUserName; };
+ const QString & password() const { return m_szPassword; };
+ const KviPixmap & avatar() const { return m_pixAvatar; };
+ const QString & partMessage() const { return m_szPartMessage; };
+ const QString & quitMessage() const { return m_szQuitMessage; };
+ const QString & age() const { return m_szAge; };
+ const QString & gender() const { return m_szGender; };
+ const QString & location() const { return m_szLocation; };
+ const QString & languages() const { return m_szLanguages; };
+ const QString & otherInfo() const { return m_szOtherInfo; };
+ const QString & userMode() const { return m_szUserMode; };
+ const QString & onConnectCommand() const { return m_szOnConnectCommand; };
+ const QString & onLoginCommand() const { return m_szOnLoginCommand; };
+ void setId(const QString &szId){ m_szId = szId; };
+ void setNickName(const QString &szNickName){ m_szNickName = szNickName; };
+ void setAltNickName1(const QString &szNickName){ m_szAltNickName1 = szNickName; };
+ void setAltNickName2(const QString &szNickName){ m_szAltNickName2 = szNickName; };
+ void setAltNickName3(const QString &szNickName){ m_szAltNickName3 = szNickName; };
+ void setUserName(const QString &szUserName){ m_szUserName = szUserName; };
+ void setRealName(const QString &szRealName){ m_szRealName = szRealName; };
+ void setPassword(const QString &szPassword){ m_szPassword = szPassword; };
+ void setAvatar(const KviPixmap &pix){ m_pixAvatar = pix; };
+ void setPartMessage(const QString &szMsg){ m_szPartMessage = szMsg; };
+ void setQuitMessage(const QString &szMsg){ m_szQuitMessage = szMsg; };
+ void setAge(const QString &szAge){ m_szAge = szAge; };
+ void setGender(const QString &szGender){ m_szGender = szGender; };
+ void setLocation(const QString &szLocation){ m_szLocation = szLocation; };
+ void setLanguages(const QString &szLanguages){ m_szLanguages = szLanguages; };
+ void setOtherInfo(const QString &szOtherInfo){ m_szOtherInfo = szOtherInfo; };
+ void setUserMode(const QString &szUserMode){ m_szUserMode = szUserMode; };
+ void setOnConnectCommand(const QString &szOnConnectCommand){ m_szOnConnectCommand = szOnConnectCommand; };
+ void setOnLoginCommand(const QString &szOnLoginCommand){ m_szOnLoginCommand = szOnLoginCommand; };
+protected:
+ void copyFrom(const KviUserIdentity &src);
+ bool save(KviConfig &cfg);
+ bool load(KviConfig &cfg);
+};
+
+class KVILIB_API KviUserIdentityManager : public KviHeapObject
+{
+protected:
+ KviUserIdentityManager();
+ ~KviUserIdentityManager();
+protected:
+ static KviUserIdentityManager * m_pInstance;
+ KviPointerHashTable<QString,KviUserIdentity> * m_pIdentityDict;
+ QString m_szDefaultIdentity;
+public:
+ static void init();
+ static void done();
+ static KviUserIdentityManager * instance(){ return m_pInstance; };
+
+ KviPointerHashTable<QString,KviUserIdentity> * identityDict(){ return m_pIdentityDict; };
+ const KviUserIdentity * findIdentity(const QString &szId){ return m_pIdentityDict->find(szId); };
+ // NEVER NULL
+ const KviUserIdentity * defaultIdentity();
+
+ void setDefaultIdentity(const QString &szIdentityId){ m_szDefaultIdentity = szIdentityId; };
+
+ KviUserIdentityManager * createWorkingCopy();
+ void copyFrom(KviUserIdentityManager * pWorkingCopy);
+ void releaseWorkingCopy(KviUserIdentityManager * pWorkingCopy);
+
+ void save(const QString &szFileName);
+ void load(const QString &szFileName);
+};
+
+#endif //!_KVI_USERIDENTITY_H_
diff --git a/src/kvilib/irc/moc_kvi_ircuserdb.cpp b/src/kvilib/irc/moc_kvi_ircuserdb.cpp
new file mode 100644
index 00000000..2b4d1482
--- /dev/null
+++ b/src/kvilib/irc/moc_kvi_ircuserdb.cpp
@@ -0,0 +1,119 @@
+/****************************************************************************
+** KviIrcUserDataBase meta object code from reading C++ file 'kvi_ircuserdb.h'
+**
+** Created: Sun Mar 23 20:56:18 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_ircuserdb.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviIrcUserDataBase::className() const
+{
+ return "KviIrcUserDataBase";
+}
+
+QMetaObject *KviIrcUserDataBase::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviIrcUserDataBase( "KviIrcUserDataBase", &KviIrcUserDataBase::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviIrcUserDataBase::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviIrcUserDataBase", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviIrcUserDataBase::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviIrcUserDataBase", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviIrcUserDataBase::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = QObject::staticMetaObject();
+ static const QUParameter param_slot_0[] = {
+ { 0, &static_QUType_QString, 0, QUParameter::In }
+ };
+ static const QUMethod slot_0 = {"registeredUserRemoved", 1, param_slot_0 };
+ static const QUParameter param_slot_1[] = {
+ { 0, &static_QUType_QString, 0, QUParameter::In }
+ };
+ static const QUMethod slot_1 = {"registeredUserChanged", 1, param_slot_1 };
+ static const QUParameter param_slot_2[] = {
+ { 0, &static_QUType_QString, 0, QUParameter::In }
+ };
+ static const QUMethod slot_2 = {"registeredUserAdded", 1, param_slot_2 };
+ static const QUMethod slot_3 = {"registeredDatabaseCleared", 0, 0 };
+ static const QMetaData slot_tbl[] = {
+ { "registeredUserRemoved(const QString&)", &slot_0, QMetaData::Protected },
+ { "registeredUserChanged(const QString&)", &slot_1, QMetaData::Protected },
+ { "registeredUserAdded(const QString&)", &slot_2, QMetaData::Protected },
+ { "registeredDatabaseCleared()", &slot_3, QMetaData::Protected }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviIrcUserDataBase", parentObject,
+ slot_tbl, 4,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviIrcUserDataBase.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviIrcUserDataBase::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviIrcUserDataBase" ) )
+ return this;
+ return QObject::qt_cast( clname );
+}
+
+bool KviIrcUserDataBase::qt_invoke( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->slotOffset() ) {
+ case 0: registeredUserRemoved((const QString&)static_QUType_QString.get(_o+1)); break;
+ case 1: registeredUserChanged((const QString&)static_QUType_QString.get(_o+1)); break;
+ case 2: registeredUserAdded((const QString&)static_QUType_QString.get(_o+1)); break;
+ case 3: registeredDatabaseCleared(); break;
+ default:
+ return QObject::qt_invoke( _id, _o );
+ }
+ return TRUE;
+}
+
+bool KviIrcUserDataBase::qt_emit( int _id, QUObject* _o )
+{
+ return QObject::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviIrcUserDataBase::qt_property( int id, int f, QVariant* v)
+{
+ return QObject::qt_property( id, f, v);
+}
+
+bool KviIrcUserDataBase::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvilib/net/Makefile.am b/src/kvilib/net/Makefile.am
new file mode 100644
index 00000000..c84487eb
--- /dev/null
+++ b/src/kvilib/net/Makefile.am
@@ -0,0 +1,5 @@
+###############################################################################
+# KVirc IRC client Makefile - 16.12.98 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+EXTRA_DIST = *.cpp *.h
diff --git a/src/kvilib/net/kvi_dns.cpp b/src/kvilib/net/kvi_dns.cpp
new file mode 100644
index 00000000..faa2e126
--- /dev/null
+++ b/src/kvilib/net/kvi_dns.cpp
@@ -0,0 +1,450 @@
+//=============================================================================
+//
+// File : kvi_dns.cpp
+// Creation date : Sat Jul 21 2000 17:19:31 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+#define __KVILIB__
+
+#include "kvi_dns.h"
+#include "kvi_error.h"
+#include "kvi_netutils.h"
+
+#include <errno.h>
+
+#ifdef COMPILE_ON_WINDOWS
+ #include <winsock2.h>
+
+ #ifdef COMPILE_IPV6_SUPPORT
+ #ifdef WIN2K
+ #include <ws2ip6.h>
+ #else
+ #include <ws2tcpip.h>
+ //#include <tpipv6.h>
+ #endif
+ #endif
+#else
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netdb.h>
+#endif
+
+// this is for FreeBSD
+#ifndef EAI_ADDRFAMILY
+ #define EAI_ADDRFAMILY EAI_FAMILY
+#endif
+
+#ifndef EAI_NODATA
+ #define EAI_NODATA 0
+#endif
+
+
+
+KviDnsResult::KviDnsResult()
+{
+ m_iError = KviError_success;
+ m_pHostnameList = new KviPointerList<QString>;
+ m_pHostnameList->setAutoDelete(true);
+ m_pIpAddressList = new KviPointerList<QString>;
+ m_pIpAddressList->setAutoDelete(true);
+
+}
+
+KviDnsResult::~KviDnsResult()
+{
+ delete m_pHostnameList;
+ delete m_pIpAddressList;
+}
+
+void KviDnsResult::appendHostname(const QString &host)
+{
+ m_pHostnameList->append(new QString(host));
+}
+
+
+void KviDnsResult::appendAddress(const QString &addr)
+{
+ m_pIpAddressList->append(new QString(addr));
+}
+
+
+
+KviDnsThread::KviDnsThread(KviDns * pDns)
+{
+ m_pParentDns = pDns;
+}
+
+KviDnsThread::~KviDnsThread()
+{
+}
+
+int KviDnsThread::translateDnsError(int iErr)
+{
+#if defined(COMPILE_IPV6_SUPPORT) || !defined(COMPILE_ON_WINDOWS)
+
+ switch(iErr)
+ {
+ case EAI_FAMILY: return KviError_unsupportedAddressFamily; break;
+#if !defined(COMPILE_ON_WINDOWS) && defined(EAI_ADDRFAMILY) && (EAI_ADDRFAMILY != EAI_FAMILY)
+ case EAI_ADDRFAMILY: return KviError_unsupportedAddressFamily; break;
+#endif
+// NOT FreeBSD ARE WE?
+#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
+// YARR
+ case EAI_NODATA: return KviError_validNameButNoIpAddress; break;
+#endif
+ case EAI_FAIL: return KviError_unrecoverableNameserverError; break;
+ case EAI_AGAIN: return KviError_dnsTemporaneousFault; break;
+ // this should never happen
+ case EAI_BADFLAGS: return KviError_dnsInternalErrorBadFlags; break;
+ case EAI_MEMORY: return KviError_dnsInternalErrorOutOfMemory; break;
+ // got this when experimenting with protocols
+ case EAI_SERVICE: return KviError_dnsInternalErrorServiceNotSupported; break;
+#ifndef COMPILE_ON_WINDOWS
+ case EAI_NONAME: return KviError_dnsNoName; break;
+#endif
+ // got this when experimenting with protocols
+ case EAI_SOCKTYPE: return KviError_dnsInternalErrorUnsupportedSocketType; break;
+#ifndef COMPILE_ON_WINDOWS
+ case EAI_SYSTEM: return -errno;
+#endif
+ }
+
+#endif
+ return KviError_dnsQueryFailed;
+}
+
+void KviDnsThread::postDnsError(KviDnsResult * dns,int iErr)
+{
+ dns->setError(iErr);
+ KviThreadDataEvent<KviDnsResult> * e = new KviThreadDataEvent<KviDnsResult>(KVI_DNS_THREAD_EVENT_DATA);
+ e->setData(dns);
+ postEvent(m_pParentDns,e);
+}
+
+void KviDnsThread::run()
+{
+ KviDnsResult * dns = new KviDnsResult();
+
+ dns->setQuery(m_szQuery);
+
+ if(m_szQuery.isEmpty())
+ {
+ postDnsError(dns,KviError_noHostToResolve);
+ return;
+ }
+
+#ifndef COMPILE_IPV6_SUPPORT
+ if(m_queryType != KviDns::IpV4)
+ {
+ if(m_queryType == KviDns::IpV6)
+ {
+ postDnsError(dns,KviError_noIpV6Support);
+ return;
+ }
+ m_queryType = KviDns::IpV4;
+ }
+#endif
+
+#if defined(COMPILE_ON_WINDOWS) && !defined(COMPILE_IPV6_SUPPORT)
+
+ if(m_queryType == KviDns::IpV6)
+ {
+ postDnsError(dns,KviError_noIpV6Support);
+ return;
+ }
+
+ // gethostbyaddr and gethostbyname are thread-safe on Windoze
+ struct in_addr inAddr;
+ struct hostent *pHostEntry = 0;
+
+
+ // DIE DIE!....I hope that this stuff will disappear sooner or later :)
+
+ if(KviNetUtils::stringIpToBinaryIp(m_szQuery,&inAddr))
+ {
+ pHostEntry = gethostbyaddr((const char *)&inAddr,sizeof(inAddr),AF_INET);
+ } else {
+ pHostEntry = gethostbyname(m_szQuery);
+ }
+
+ if(!pHostEntry)
+ {
+ switch(h_errno)
+ {
+ case HOST_NOT_FOUND: dns->setError(KviError_hostNotFound); break;
+ case NO_ADDRESS: dns->setError(KviError_validNameButNoIpAddress); break;
+ case NO_RECOVERY: dns->setError(KviError_unrecoverableNameserverError); break;
+ case TRY_AGAIN: dns->setError(KviError_dnsTemporaneousFault); break;
+ default: dns->setError(KviError_dnsQueryFailed); break;
+ }
+ } else {
+ dns->appendHostname(pHostEntry->h_name);
+ QString szIp;
+ KviNetUtils::binaryIpToStringIp(* ((struct in_addr*)(pHostEntry->h_addr)),szIp);
+ dns->appendAddress(szIp);
+
+ int idx = 1;
+ while(pHostEntry->h_addr_list[idx])
+ {
+ QString tmp;
+ KviNetUtils::binaryIpToStringIp(* ((struct in_addr*)(pHostEntry->h_addr_list[idx])),tmp);
+ if(tmp.hasData())dns->appendAddress(tmp);
+ ++idx;
+ }
+ if(pHostEntry->h_aliases[0])
+ {
+ dns->appendHostname(QString::fromUtf8(pHostEntry->h_aliases[0]));
+ if(pHostEntry->h_aliases[1])dns->appendHostname(QString::fromUtf8(pHostEntry->h_aliases[1]));
+ }
+ }
+
+
+#else //!COMPILE_ON_WINDOWS || COMPILE_IPV6_SUPPORT
+
+ int retVal;
+
+
+//#ifdef HAVE_GETNAMEINFO
+ struct sockaddr_in ipv4Addr;
+
+#ifdef COMPILE_IPV6_SUPPORT
+ struct sockaddr_in6 ipv6Addr;
+ bool bIsIpV6Ip = false;
+#endif
+
+ bool bIsIpV4Ip = KviNetUtils::stringIpToBinaryIp(m_szQuery,(struct in_addr *)&(ipv4Addr.sin_addr));
+
+#ifdef COMPILE_IPV6_SUPPORT
+ if(!bIsIpV4Ip)bIsIpV6Ip = KviNetUtils::stringIpToBinaryIp_V6(m_szQuery,(struct in6_addr *)&(ipv6Addr.sin6_addr));
+#endif
+
+//#ifdef HAVE_GETNAMEINFO
+
+#ifdef COMPILE_IPV6_SUPPORT
+ if(bIsIpV4Ip || bIsIpV6Ip)
+ {
+#else
+ if(bIsIpV4Ip)
+ {
+#endif
+ // use getnameinfo...
+ char retname[1025]; // should be enough....
+
+#ifdef COMPILE_IPV6_SUPPORT
+ if(bIsIpV4Ip)
+ {
+#endif
+ ipv4Addr.sin_family = AF_INET;
+ ipv4Addr.sin_port = 0;
+ // NI_NAMEREQD as last param ?
+ retVal = getnameinfo((struct sockaddr *)&ipv4Addr,sizeof(ipv4Addr),retname,1025,0,0,NI_NAMEREQD);
+#ifdef COMPILE_IPV6_SUPPORT
+ } else {
+ ipv6Addr.sin6_family = AF_INET6;
+ ipv6Addr.sin6_port = 0;
+ retVal = getnameinfo((struct sockaddr *)&ipv6Addr,sizeof(ipv6Addr),retname,1025,0,0,NI_NAMEREQD);
+ }
+#endif
+
+ if(retVal != 0)dns->setError(translateDnsError(retVal));
+ else {
+ dns->appendHostname(retname);
+ dns->appendAddress(m_szQuery);
+ }
+
+ } else {
+//#endif //HAVE_GETNAMEINFO
+
+
+//#ifdef COMPILE_IPV6_SUPPORT
+// struct in6_addr in6Addr;
+//#endif
+ struct addrinfo * pRet = 0;
+ struct addrinfo * pNext;
+ struct addrinfo hints;
+ hints.ai_flags = 0; //AI_CANONNAME; <-- for IPV6 it makes cannoname to point to the IP address!
+#ifdef COMPILE_IPV6_SUPPORT
+ hints.ai_family = (m_queryType == KviDns::IpV6) ? PF_INET6 : ((m_queryType == KviDns::IpV4) ? PF_INET : PF_UNSPEC);
+#else
+ hints.ai_family = PF_INET;
+#endif
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = 0;
+ hints.ai_addrlen = 0;
+ hints.ai_canonname = 0;
+ hints.ai_addr = 0;
+ hints.ai_next = 0;
+
+ retVal = getaddrinfo(KviQString::toUtf8(m_szQuery).data(),0,&hints,&pRet);
+
+ if(retVal != 0)dns->setError(translateDnsError(retVal));
+ else {
+ dns->appendHostname(pRet->ai_canonname ? QString::fromUtf8(pRet->ai_canonname) : m_szQuery);
+ QString szIp;
+#ifdef COMPILE_IPV6_SUPPORT
+ if(pRet->ai_family == PF_INET6)KviNetUtils::binaryIpToStringIp_V6(((sockaddr_in6 *)(pRet->ai_addr))->sin6_addr,szIp);
+ else {
+#endif
+ KviNetUtils::binaryIpToStringIp(((sockaddr_in *)(pRet->ai_addr))->sin_addr,szIp);
+#ifdef COMPILE_IPV6_SUPPORT
+ }
+#endif
+ dns->appendAddress(szIp);
+
+ pNext = pRet->ai_next;
+ while(pNext)
+ {
+ QString tmp;
+#ifdef COMPILE_IPV6_SUPPORT
+ if(pNext->ai_family == PF_INET6)KviNetUtils::binaryIpToStringIp_V6(((sockaddr_in6 *)(pNext->ai_addr))->sin6_addr,tmp);
+ else {
+#endif
+ KviNetUtils::binaryIpToStringIp(((sockaddr_in *)(pNext->ai_addr))->sin_addr,tmp);
+#ifdef COMPILE_IPV6_SUPPORT
+ }
+#endif
+ if(!tmp.isEmpty())dns->appendAddress(tmp);
+
+ if(pNext->ai_canonname)
+ {
+ // FIXME: only of not equal to other names ?
+ dns->appendHostname(QString::fromUtf8(pNext->ai_canonname));
+ }
+
+ pNext = pNext->ai_next;
+
+ }
+ }
+ if(pRet)freeaddrinfo(pRet);
+//#ifdef HAVE_GETNAMEINFO
+ }
+//#endif //HAVE_GETNAMEINFO
+
+#endif // !COMPILE_ON_WINDOWS
+
+
+ KviThreadDataEvent<KviDnsResult> * e = new KviThreadDataEvent<KviDnsResult>(KVI_DNS_THREAD_EVENT_DATA);
+ e->setData(dns);
+ postEvent(m_pParentDns,e);
+}
+
+
+
+
+KviDns::KviDns()
+: QObject()
+{
+ m_pSlaveThread = new KviDnsThread(this);
+ m_pDnsResult = new KviDnsResult();
+ m_pAuxData = 0;
+ m_state = Idle;
+}
+
+KviDns::~KviDns()
+{
+ if(m_pSlaveThread)delete m_pSlaveThread; // will eventually terminate it (but it will also block us!!!)
+ KviThreadManager::killPendingEvents(this);
+ if(m_pDnsResult)delete m_pDnsResult;
+ if(m_pAuxData)debug("You're leaking memory man! m_pAuxData is non 0!");
+}
+
+
+bool KviDns::isRunning() const
+{
+ return (m_state == Busy);
+};
+
+bool KviDns::lookup(const QString &query,QueryType type)
+{
+ if(m_state == Busy)return false;
+ m_pSlaveThread->setQuery(KviQString::trimmed(query),type);
+ bool bStarted = m_pSlaveThread->start();
+ m_state = bStarted ? Busy : Failure;
+ return bStarted;
+}
+
+int KviDns::error()
+{
+ if(!m_pDnsResult)return KviError_dnsQueryFailed;
+ return m_pDnsResult->error();
+}
+
+KviDnsResult * KviDns::result()
+{
+ if(!m_pDnsResult)m_pDnsResult = new KviDnsResult();
+ return m_pDnsResult;
+}
+
+KviPointerList<QString> * KviDns::hostnameList()
+{
+ return result()->hostnameList();
+}
+
+KviPointerList<QString> * KviDns::ipAddressList()
+{
+ return result()->ipAddressList();
+}
+
+int KviDns::hostnameCount()
+{
+ return result()->hostnameList()->count();
+}
+
+int KviDns::ipAddressCount()
+{
+ return result()->ipAddressList()->count();
+}
+
+const QString & KviDns::firstHostname()
+{
+ QString * pStr = result()->hostnameList()->first();
+ if(pStr)return *pStr;
+ return KviQString::empty;
+}
+
+const QString & KviDns::firstIpAddress()
+{
+ QString * pStr = result()->ipAddressList()->first();
+ if(pStr)return *pStr;
+ return KviQString::empty;
+}
+
+const QString & KviDns::query()
+{
+ return result()->query();
+}
+
+bool KviDns::event(QEvent *e)
+{
+ if(e->type() == KVI_THREAD_EVENT)
+ {
+ if(((KviThreadEvent *)e)->id() == KVI_DNS_THREAD_EVENT_DATA)
+ {
+ if(m_pDnsResult)delete m_pDnsResult;
+ m_pDnsResult = ((KviThreadDataEvent<KviDnsResult> *)e)->getData();
+ m_state = (m_pDnsResult->error() == KviError_success) ? Success : Failure;
+ emit lookupDone(this);
+ return true;
+ } // else ops... unknown thread event ?
+ }
+ return QObject::event(e);
+}
+
diff --git a/src/kvilib/net/kvi_dns.h b/src/kvilib/net/kvi_dns.h
new file mode 100644
index 00000000..3f423c24
--- /dev/null
+++ b/src/kvilib/net/kvi_dns.h
@@ -0,0 +1,142 @@
+#ifndef _KVI_DNS_H_
+#define _KVI_DNS_H_
+
+//=============================================================================
+//
+// File : kvi_dns.h
+// Creation date : Sat Jul 21 2000 13:59:11 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_heapobject.h"
+#include "kvi_thread.h"
+#include "kvi_qstring.h"
+
+
+class KviDnsThread; // not part of the API
+
+
+class KVILIB_API KviDnsResult : public KviHeapObject
+{
+ friend class KviDns;
+ friend class KviDnsThread;
+protected:
+ KviDnsResult();
+public:
+ ~KviDnsResult();
+protected:
+ int m_iError;
+ KviPointerList<QString> * m_pHostnameList;
+ KviPointerList<QString> * m_pIpAddressList;
+ QString m_szQuery;
+public:
+ int error(){ return m_iError; };
+ // never store nor delete these pointers!
+ // (these are NEVER 0)
+ KviPointerList<QString> * hostnameList(){ return m_pHostnameList; };
+ KviPointerList<QString> * ipAddressList(){ return m_pIpAddressList; };
+ const QString &query(){ return m_szQuery; };
+protected:
+ void setError(int iError){ m_iError = iError; };
+ void setQuery(const QString &query){ m_szQuery = query; };
+ void appendHostname(const QString &host);
+ void appendAddress(const QString &addr);
+};
+
+
+
+class KVILIB_API KviDns : public QObject, public KviHeapObject
+{
+ Q_OBJECT
+ Q_PROPERTY(bool blockingDelete READ isRunning)
+public:
+ KviDns();
+ ~KviDns();
+public:
+ enum QueryType { IpV4 , IpV6 , Any };
+ enum State { Idle , Busy , Failure , Success };
+protected:
+ void * m_pAuxData;
+ KviDnsThread * m_pSlaveThread;
+ KviDnsResult * m_pDnsResult;
+ State m_state;
+public:
+ /////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Public interface
+ //
+
+ // Lookup start
+ bool lookup(const QString &szQuery,QueryType type);
+
+ // Current object state
+ State state(){ return m_state; };
+
+ // Results (return always non null-data..but valid results only if state() == Success or Failure)
+ int error();
+ const QString & firstHostname();
+ const QString & firstIpAddress();
+ int hostnameCount();
+ int ipAddressCount();
+ KviPointerList<QString> * hostnameList();
+ KviPointerList<QString> * ipAddressList();
+ const QString & query();
+ bool isRunning() const;
+
+ // Auxiliary data store
+ void setAuxData(void * pAuxData){ m_pAuxData = pAuxData; };
+ void * releaseAuxData(){ void * pData = m_pAuxData; m_pAuxData = 0; return pData; };
+protected:
+ virtual bool event(QEvent *e);
+private:
+ KviDnsResult * result();
+signals:
+ void lookupDone(KviDns *);
+};
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////
+// INTERNAL CLASSES
+//
+
+#define KVI_DNS_THREAD_EVENT_DATA (KVI_THREAD_USER_EVENT_BASE + 7432)
+
+class KviDnsThread : public KviThread
+{
+ friend class KviDns;
+protected:
+ KviDnsThread(KviDns * pDns);
+ ~KviDnsThread();
+protected:
+ QString m_szQuery;
+ KviDns::QueryType m_queryType;
+ KviDns * m_pParentDns;
+public:
+ void setQuery(const QString &query,KviDns::QueryType type){ m_szQuery = query; m_queryType = type; };
+protected:
+ virtual void run();
+ int translateDnsError(int iErr);
+ void postDnsError(KviDnsResult * dns,int iErr);
+};
+
+
+#endif //_KVI_DNS_H_
diff --git a/src/kvilib/net/kvi_http.cpp b/src/kvilib/net/kvi_http.cpp
new file mode 100644
index 00000000..2e94abbe
--- /dev/null
+++ b/src/kvilib/net/kvi_http.cpp
@@ -0,0 +1,1440 @@
+//=============================================================================
+//
+// File : kvi_http.cpp
+// Creation date : Sat Aug 17 13:43:32 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002-2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+
+
+#include <qdir.h>
+#include <qtimer.h>
+//#include <zlib.h>
+
+#include "kvi_http.h"
+#include "kvi_locale.h"
+#include "kvi_netutils.h"
+#include "kvi_dns.h"
+#include "kvi_error.h"
+#include "kvi_debug.h"
+#include "kvi_socket.h"
+#include "kvi_time.h"
+#ifdef COMPILE_SSL_SUPPORT
+ #include "kvi_ssl.h"
+#endif
+
+
+#define KVI_HTTP_REQUEST_THREAD_EVENT_CONNECTED (KVI_THREAD_USER_EVENT_BASE + 0xCAFE)
+#define KVI_HTTP_REQUEST_THREAD_EVENT_REQUESTSENT (KVI_THREAD_USER_EVENT_BASE + 0xCAFF)
+
+KviHttpRequest::KviHttpRequest()
+: QObject()
+{
+ m_pDns = 0;
+ m_pThread = 0;
+ m_pFile = 0;
+ m_pPrivateData = 0;
+ m_bHeaderProcessed = false;
+ m_pBuffer = new KviDataBuffer();
+
+ resetStatus();
+ resetData();
+}
+
+KviHttpRequest::~KviHttpRequest()
+{
+ resetInternalStatus();
+ delete m_pBuffer;
+}
+
+void KviHttpRequest::abort()
+{
+ resetInternalStatus();
+ m_szLastError = __tr2qs("Aborted");
+ emit terminated(false);
+}
+
+void KviHttpRequest::resetInternalStatus()
+{
+ if(m_pThread)delete m_pThread;
+ if(m_pDns)delete m_pDns;
+
+ m_pDns = 0;
+ m_pThread = 0;
+
+ if(!m_pFile)return;
+ m_pFile->close();
+ delete m_pFile;
+ m_pFile = 0;
+
+ m_pBuffer->clear();
+ m_bHeaderProcessed = false;
+
+ KviThreadManager::killPendingEvents(this);
+}
+
+void KviHttpRequest::resetStatus()
+{
+ m_szLastError = __tr2qs("No request");
+ m_uTotalSize = 0;
+ m_uReceivedSize = 0;
+}
+
+void KviHttpRequest::resetData()
+{
+ m_szFileName = "";
+ m_eProcessingType = WholeFile;
+ m_eExistingFileAction = RenameIncoming;
+ m_url = "";
+ m_uMaxContentLength = 0;
+ m_uContentOffset = 0;
+ m_bChunkedTransferEncoding = false;
+ m_bGzip = false;
+ m_bIgnoreRemainingData = false;
+ m_uRemainingChunkSize = 0;
+}
+
+void KviHttpRequest::reset()
+{
+ resetStatus();
+ resetData();
+ resetInternalStatus();
+}
+
+bool KviHttpRequest::get(const KviUrl &u,ProcessingType p,const QString &szFileName)
+{
+ reset();
+ setUrl(u);
+ setProcessingType(p);
+ setFileName(szFileName);
+ return start();
+}
+
+bool KviHttpRequest::start()
+{
+ // ensure that the file is closed
+ resetInternalStatus();
+ resetStatus();
+
+ if(m_eProcessingType == StoreToFile)
+ {
+ if(m_szFileName.isEmpty())
+ {
+ m_szLastError = __tr2qs("No filename specified for the \"StoreToFile\" processing type");
+ return false;
+ }
+
+ if((m_eExistingFileAction == Resume) && (m_uContentOffset == 0))
+ {
+ // determine the content offset automatically
+ if(KviFile::exists(m_szFileName))
+ {
+ // we check it
+ QFileInfo fi(m_szFileName);
+ m_uContentOffset = fi.size();
+ }
+ }
+ }
+
+ if(m_url.host().isEmpty())
+ {
+ resetInternalStatus();
+ m_szLastError = __tr2qs("Invalid URL: Missing hostname");
+ return false;
+ }
+
+ if((!kvi_strEqualCI(m_url.protocol().ptr(),"http")) && (!kvi_strEqualCI(m_url.protocol().ptr(),"https")))
+ {
+ resetInternalStatus();
+ m_szLastError=__tr2qs("Unsupported protocol %1").arg(m_url.protocol().ptr());
+ return false;
+ }
+
+ if(kvi_isValidStringIp(m_url.host().ptr()))
+ {
+ m_szIp = m_url.host();
+ QTimer::singleShot(10,this,SLOT(haveServerIp()));
+ return true;
+ }
+
+ return startDnsLookup();
+}
+
+bool KviHttpRequest::startDnsLookup()
+{
+ m_pDns = new KviDns();
+ connect(m_pDns,SIGNAL(lookupDone(KviDns *)),this,SLOT(dnsLookupDone(KviDns *)));
+
+ if(!m_pDns->lookup(m_url.host().ptr(),KviDns::IpV4))
+ {
+ resetInternalStatus();
+ m_szLastError = __tr2qs("Unable to start the DNS lookup");
+ return false;
+ }
+
+ QString tmp;
+ KviQString::sprintf(tmp,__tr2qs("Looking up host %s"),m_url.host().ptr());
+ emit status(tmp); // FIXME
+
+ emit resolvingHost(QString(m_url.host().ptr()));
+
+ return true;
+}
+
+void KviHttpRequest::dnsLookupDone(KviDns *d)
+{
+ if(d->state() == KviDns::Success)
+ {
+ m_szIp = d->firstIpAddress();
+ delete m_pDns;
+ m_pDns = 0;
+ QString tmp;
+ KviQString::sprintf(tmp,__tr2qs("Host %s resolved to %Q"),m_url.host().ptr(),&m_szIp);
+ emit status(tmp);
+ haveServerIp();
+ } else {
+ int iErr = d->error();
+ resetInternalStatus();
+ m_szLastError = KviError::getDescription(iErr);
+ emit terminated(false);
+ }
+}
+
+void KviHttpRequest::haveServerIp()
+{
+ unsigned short uPort = m_url.port();
+ if(uPort == 0)uPort = 80;
+
+ QString tmp;
+ KviQString::sprintf(tmp,"%Q:%u",&m_szIp,uPort);
+ emit contactingHost(tmp);
+
+ if(m_pThread)delete m_pThread;
+
+ m_pThread = new KviHttpRequestThread(
+ this,
+ m_url.host().ptr(),
+ m_szIp,
+ uPort,
+ m_url.path().ptr(),
+ m_uContentOffset,
+ (m_eProcessingType == HeadersOnly) ? KviHttpRequestThread::Head : (m_szPostData.isEmpty() ? KviHttpRequestThread::Get : KviHttpRequestThread::Post),
+ m_szPostData,
+ kvi_strEqualCI(m_url.protocol().ptr(),"https"));
+
+ if(!m_pThread->start())
+ {
+ resetInternalStatus();
+ m_szLastError = __tr2qs("Unable to start the request slave thread");
+ emit terminated(false);
+ return;
+ }
+
+ KviQString::sprintf(tmp,__tr2qs("Contacting host %Q on port %u"),&m_szIp,uPort);
+ emit status(tmp);
+}
+
+bool KviHttpRequest::event(QEvent *e)
+{
+ if(e->type() == KVI_THREAD_EVENT)
+ {
+ switch(((KviThreadEvent *)e)->id())
+ {
+ case KVI_THREAD_EVENT_BINARYDATA:
+ {
+ KviDataBuffer * b = ((KviThreadDataEvent<KviDataBuffer> *)e)->getData();
+ processData(b);
+ delete b;
+ return true;
+ }
+ break;
+ case KVI_HTTP_REQUEST_THREAD_EVENT_CONNECTED:
+ emit connectionEstabilished();
+ emit status(__tr2qs("Connection established, sending request"));
+ return true;
+ break;
+ case KVI_HTTP_REQUEST_THREAD_EVENT_REQUESTSENT:
+ {
+ QString * req = ((KviThreadDataEvent<QString> *)e)->getData();
+#ifdef COMPILE_USE_QT4
+ QStringList sl = req->split("\r\n");
+#else
+ QStringList sl = QStringList::split("\r\n",*req);
+#endif
+ emit requestSent(sl);
+ delete req;
+ return true;
+ }
+ break;
+ case KVI_THREAD_EVENT_SUCCESS:
+ if(!m_pThread && !m_bHeaderProcessed)
+ {
+ // the thread has already been deleted
+ // probably because the response was something like a 404
+ // just ignore the event
+ return true;
+ }
+ switch(m_eProcessingType)
+ {
+ case WholeFile:
+ // happens always
+ emit binaryData(*m_pBuffer);
+ break;
+ case Blocks:
+ // an unprocessed block ?.. should never happend.. but well :D
+ if(m_pBuffer->size() > 0)emit binaryData(*m_pBuffer);
+ break;
+ case Lines:
+ if(m_pBuffer->size() > 0)
+ {
+ // something left in the buffer and has no trailing LF
+ KviStr tmp((const char *)(m_pBuffer->data()),m_pBuffer->size());
+ emit data(tmp);
+ }
+ break;
+ case StoreToFile:
+ // same as above... should never happen.. but well :D
+ if(m_pFile && m_pBuffer->size() > 0)m_pFile->writeBlock((const char *)(m_pBuffer->data()),m_pBuffer->size());
+ break;
+ default:
+ // nothing... just make gcc happy
+ break;
+ }
+ resetInternalStatus();
+ m_szLastError = __tr2qs("Success");
+ emit terminated(true);
+ return true;
+ break;
+ case KVI_THREAD_EVENT_ERROR:
+ {
+ KviStr * err = ((KviThreadDataEvent<KviStr> *)e)->getData();
+ m_szLastError = __tr2qs_no_xgettext(err->ptr());
+ delete err;
+ resetInternalStatus();
+ emit terminated(false);
+ return true;
+ }
+ break;
+ case KVI_THREAD_EVENT_MESSAGE:
+ {
+ KviStr * msg = ((KviThreadDataEvent<KviStr> *)e)->getData();
+ emit status(__tr2qs_no_xgettext(msg->ptr()));
+ delete msg;
+ return true;
+ }
+ break;
+ }
+ }
+ return QObject::event(e);
+}
+
+void KviHttpRequest::emitLines(KviDataBuffer * pDataBuffer)
+{
+ int idx = pDataBuffer->find((const unsigned char *)"\n",1);
+ while(idx != -1)
+ {
+ KviStr tmp((const char *)(m_pBuffer->data()),idx);
+ tmp.stripRight('\r');
+ pDataBuffer->remove(idx + 1);
+ idx = pDataBuffer->find((const unsigned char *)"\n",1);
+ emit data(tmp);
+ }
+}
+
+// header += "Accept: ";
+// QString acceptHeader = metaData("accept");
+// if (!acceptHeader.isEmpty())
+// header += acceptHeader;
+// else
+// header += DEFAULT_ACCEPT_HEADER;
+// header += "\r\n";
+//
+//#ifdef DO_GZIP
+// if (m_request.allowCompressedPage)
+// header += "Accept-Encoding: x-gzip, x-deflate, gzip, deflate, identity\r\n";
+//#endif
+//
+// if (!m_request.charsets.isEmpty())
+// header += "Accept-Charset: " + m_request.charsets + "\r\n";
+//
+// if (!m_request.languages.isEmpty())
+// header += "Accept-Language: " + m_request.languages + "\r\n";
+//
+//
+// /* support for virtual hosts and required by HTTP 1.1 */
+// header += "Host: ";
+// header += "Pragma: no-cache\r\n"; /* for HTTP/1.0 caches */
+// header += "Cache-control: no-cache\r\n"; /* for HTTP >=1.1 caches */
+
+// header += "Referer: "; //Don't try to correct spelling!
+// header += m_request.referrer;
+// header += "\r\n";
+bool KviHttpRequest::openFile()
+{
+ if(m_eProcessingType != StoreToFile)return true;
+
+ bool bAppend = false;
+
+ // take action when the file is existing
+ if(KviFile::exists(m_szFileName))
+ {
+ switch(m_eExistingFileAction)
+ {
+ case Resume:
+ {
+ bAppend = true;
+ }
+ break;
+ case RenameIncoming:
+ {
+ int i=0;
+ QString tmp = m_szFileName;
+ do {
+ i++;
+ m_szFileName = tmp + QString(".kvirnm-%1").arg(i);
+ } while(KviFile::exists(m_szFileName));
+ }
+ break;
+ case RenameExisting:
+ {
+ int i=0;
+ QString tmp;
+ do {
+ i++;
+ tmp = m_szFileName + QString(".kvirnm-%1").arg(i);
+ } while(KviFile::exists(tmp));
+ QDir d;
+ if(!d.rename(m_szFileName,tmp))
+ {
+ // fail :(
+ resetInternalStatus();
+ m_szLastError = __tr2qs("Failed to rename the existing file, please rename manually and retry");
+ emit terminated(false);
+ return false;
+ }
+ }
+ break;
+ case Overwrite:
+ default:
+ // nothing
+ break;
+ }
+ }
+
+ m_pFile = new KviFile(m_szFileName);
+
+ if(!m_pFile->openForWriting(bAppend))
+ {
+ resetInternalStatus();
+ KviQString::sprintf(m_szLastError,__tr2qs("Can't open file \"%Q\" for writing"),&m_szFileName);
+ emit terminated(false);
+ return false;
+ }
+
+ return true;
+}
+
+
+
+
+
+bool KviHttpRequest::processHeader(KviStr &szHeader)
+{
+ int idx = szHeader.findFirstIdx("\r\n");
+ KviStr szResponse;
+ if(idx != -1)
+ {
+ szResponse = szHeader.left(idx);
+ szHeader.cutLeft(idx + 2);
+ } else {
+ szResponse = szHeader;
+ szHeader = "";
+ }
+
+ szResponse.stripWhiteSpace();
+
+ bool bValid = false;
+
+ unsigned int uStatus = 0;
+
+ // check the response value
+ if(kvi_strEqualCSN(szResponse.ptr(),"HTTP",4))
+ {
+ KviStr szR = szResponse;
+ szR.cutToFirst(' ');
+ szR.stripWhiteSpace();
+ int idx = szR.findFirstIdx(' ');
+ KviStr szNumber;
+ if(idx != -1)szNumber = szR.left(idx);
+ else szNumber = szR;
+ bool bOk;
+ uStatus = szNumber.toUInt(&bOk);
+ if(bOk)bValid = true;
+ }
+
+ if(!bValid)
+ {
+ // the response is invalid ?
+ resetInternalStatus();
+ m_szLastError=__tr2qs("Invalid HTTP response: %s").arg(szResponse.ptr());
+ emit terminated(false);
+ return false;
+ }
+
+ QString tmp;
+ KviQString::sprintf(tmp,__tr2qs("Received HTTP response: %s"),szResponse.ptr());
+
+ emit status(tmp);
+ emit receivedResponse(QString(szResponse.ptr()));
+
+ KviPointerList<KviStr> hlist;
+ hlist.setAutoDelete(true);
+
+ idx = szHeader.findFirstIdx("\r\n");
+ while(idx != -1)
+ {
+ if(idx > 0)
+ {
+ hlist.append(new KviStr(szHeader.ptr(),idx));
+ szHeader.cutLeft(idx + 2);
+ }
+ idx = szHeader.findFirstIdx("\r\n");
+ }
+ if(szHeader.hasData())hlist.append(new KviStr(szHeader));
+
+ KviPointerHashTable<const char *,KviStr> hdr(11,false,true);
+ hdr.setAutoDelete(true);
+
+ for(KviStr * s = hlist.first();s;s = hlist.next())
+ {
+ idx = s->findFirstIdx(":");
+ if(idx != -1)
+ {
+ KviStr szName = s->left(idx);
+ s->cutLeft(idx + 1);
+ s->stripWhiteSpace();
+ hdr.replace(szName.ptr(),new KviStr(*s));
+ //debug("FOUND HEADER (%s)=(%s)",szName.ptr(),s->ptr());
+ }
+ }
+
+ KviStr * size = hdr.find("Content-length");
+ if(size)
+ {
+ bool bOk;
+ m_uTotalSize = size->toUInt(&bOk);
+ if(!bOk)m_uTotalSize = 0;
+ }
+
+ KviStr * contentEncoding = hdr.find("Content-encoding");
+ if(contentEncoding)
+ {
+ m_bGzip = contentEncoding->equalsCI("gzip");
+ }
+
+ KviStr * transferEncoding = hdr.find("Transfer-Encoding");
+ if(transferEncoding)
+ {
+ if(kvi_strEqualCI(transferEncoding->ptr(),"chunked"))
+ {
+ // be prepared to handle the chunked transfer encoding as required by HTTP/1.1
+ m_bChunkedTransferEncoding = true;
+ m_uRemainingChunkSize = 0;
+ }
+ }
+
+ emit header(&hdr);
+
+ // check the status
+
+ // case 200: // OK
+ // case 206: // Partial content
+
+ // case 100: // Continue ??
+ // case 101: // Switching protocols ???
+ // case 201: // Created
+ // case 202: // Accepted
+ // case 203: // Non-Authoritative Information
+ // case 204: // No content
+ // case 205: // Reset content
+ // case 300: // Multiple choices
+ // case 301: // Moved permanently
+ // case 302: // Found
+ // case 303: // See Other
+ // case 304: // Not modified
+ // case 305: // Use Proxy
+ // case 306: // ???
+ // case 307: // Temporary Redirect
+ // case 400: // Bad request
+ // case 401: // Unauthorized
+ // case 402: // Payment Required
+ // case 403: // Forbidden
+ // case 404: // Not found
+ // case 405: // Method not allowed
+ // case 406: // Not acceptable
+ // case 407: // Proxy authentication required
+ // case 408: // Request timeout
+ // case 409: // Conflict
+ // case 410: // Gone
+ // case 411: // Length required
+ // case 412: // Precondition failed
+ // case 413: // Request entity too large
+ // case 414: // Request-URI Too Long
+ // case 415: // Unsupported media type
+ // case 416: // Requested range not satisfiable
+ // case 417: // Expectation Failed
+ // case 500: // Internal server error
+ // case 501: // Not implemented
+ // case 502: // Bad gateway
+ // case 503: // Service unavailable
+ // case 504: // Gateway timeout
+ // case 505: // HTTP Version not supported
+
+ if((uStatus != 200) && (uStatus != 206))
+ {
+ // this is not "OK" and not "Partial content"
+ // Error , redirect or something confusing
+ if(m_eProcessingType != HeadersOnly)
+ {
+ // this is an error then
+ resetInternalStatus();
+ m_szLastError = szResponse.ptr();
+ emit terminated(false);
+ return false;
+ } // else the server will terminate (it was a HEAD request)
+ }
+
+ if((m_uMaxContentLength > 0) && (m_uTotalSize > ((unsigned int)m_uMaxContentLength)))
+ {
+ resetInternalStatus();
+ m_szLastError=__tr2qs("Stream exceeding maximum length");
+ emit terminated(false);
+ return false;
+ }
+
+ // fixme: could check for data type etc...
+
+ return true;
+}
+#define BUFFER_SIZE 32768
+
+void KviHttpRequest::processData(KviDataBuffer * data)
+{
+// unsigned char obuffer[BUFFER_SIZE];
+ if(m_bChunkedTransferEncoding && m_bIgnoreRemainingData)
+ {
+ // In chunked transfer encoding mode there may be additional headers
+ // after the last chunk of data. We simply ignore them.
+ return;
+ }
+
+ if(!m_bHeaderProcessed)
+ {
+ // time to process the header
+ m_pBuffer->append(*data);
+
+ int idx = m_pBuffer->find((const unsigned char *)"\r\n\r\n",4);
+ if(idx == -1)
+ {
+ // header not complete
+ if(m_pBuffer->size() > 4096)
+ {
+ resetInternalStatus();
+ m_szLastError = __tr2qs("Header too long: exceeded 4096 bytes");
+ emit terminated(false);
+ }
+ return;
+ }
+ KviStr szHeader((const char *)(m_pBuffer->data()),idx);
+ m_pBuffer->remove(idx + 4);
+
+ if(!processHeader(szHeader))return;
+ m_bHeaderProcessed = true;
+
+ if(m_eProcessingType == StoreToFile)
+ {
+ if(!openFile())return;
+ }
+
+ m_uReceivedSize = m_pBuffer->size();
+
+
+ // here the header is complete and the eventual remaining data is in m_pBuffer. data has been already used.
+
+ } else {
+ // header already processed
+ m_uReceivedSize += data->size();
+
+ // here the header is complete and some data *might* be already in m_pBuffer. data is unused yet.
+
+ // Optimisation: If the transfer is NOT chunked (so we don't have to parse it)
+ // and the requested processing type is either Blocks or StoreToFile
+ // then we just can avoid to copy the data to m_pBuffer.
+ // This is a good optimisation since for large files we can save allocating
+ // space for and moving megabytes of data...
+
+
+ if((!m_bChunkedTransferEncoding) && ((m_eProcessingType == Blocks) || (m_eProcessingType == StoreToFile)))
+ {
+ switch(m_eProcessingType)
+ {
+ case Blocks:
+ emit binaryData(*data);
+ break;
+ case StoreToFile:
+ m_pFile->writeBlock((const char *)(data->data()),data->size());
+ break;
+ }
+
+ if(((m_uTotalSize > 0) && (m_uReceivedSize > m_uTotalSize)) || ((m_uMaxContentLength > 0) && (m_uReceivedSize > m_uMaxContentLength)))
+ {
+ resetInternalStatus();
+ m_szLastError=__tr2qs("Stream exceeded expected length");
+ emit terminated(false);
+ }
+
+ return;
+ }
+
+ // need to append to m_pBuffer and process it
+ m_pBuffer->append(*data);
+ }
+
+ // we're processing data in m_pBuffer here
+ if(m_bChunkedTransferEncoding)
+ {
+ // The transfer encoding is chunked: the buffer contains
+ // chunks of data with an initial header composed
+ // of a hexadecimal length, an optional bullshit and a single CRLF
+ // The transfer terminates when we read a last chunk of size 0
+ // that may be followed by optional headers...
+ // This sux :)
+ while(m_pBuffer->size() > 0) // <-- note that we may exit from this loop also for other conditions (there is a goto below)
+ {
+ // we process chunks of parts of chunks at a time.
+ if(m_uRemainingChunkSize > 0)
+ {
+ // process the current chunk data
+ unsigned int uProcessSize = m_uRemainingChunkSize;
+ if(uProcessSize > m_pBuffer->size())uProcessSize = m_pBuffer->size();
+ m_uRemainingChunkSize -= uProcessSize;
+
+ switch(m_eProcessingType)
+ {
+ case Blocks:
+ if(m_pBuffer->size() == uProcessSize)
+ {
+ // avoid copying to a new buffer
+ emit binaryData(*m_pBuffer);
+ } else {
+ // must copy
+ KviDataBuffer tmp(uProcessSize,m_pBuffer->data());
+ emit binaryData(tmp);
+ m_pBuffer->remove(uProcessSize);
+ }
+ break;
+ case Lines:
+ if(m_pBuffer->size() == uProcessSize)
+ {
+ // avoid copying to a new buffer
+ emitLines(m_pBuffer);
+ } else {
+ // must copy
+ KviDataBuffer tmp(uProcessSize,m_pBuffer->data());
+ emitLines(&tmp);
+ m_pBuffer->remove(uProcessSize);
+ }
+ break;
+ case StoreToFile:
+ m_pFile->writeBlock((const char *)(m_pBuffer->data()),uProcessSize);
+ m_pBuffer->remove(uProcessSize);
+ break;
+ default:
+ // nothing.. just make gcc happy
+ break;
+ }
+ // now either the buffer is empty or there is another chunk header: continue looping
+ } else {
+ // We're looking for the beginning of a chunk now.
+ // Note that we might be at the end of a previous chunk that has a CRLF terminator
+ // we need to skip it.
+ int crlf = m_pBuffer->find((const unsigned char *)"\r\n",2);
+ if(crlf != -1)
+ {
+ if(crlf == 0)
+ {
+ // This is a plain CRLF at the beginning of the buffer BEFORE a chunk header.
+ // It comes from the previous chunk terminator. Skip it.
+ m_pBuffer->remove(2);
+ } else {
+ // got a chunk header
+ KviStr szHeader((const char *)(m_pBuffer->data()),crlf);
+ szHeader.cutFromFirst(' ');
+ // now szHeader should contain a hexadecimal chunk length... (why the hell it is hex and not decimal ????)
+ QString szHexHeader = szHeader.ptr();
+ bool bOk;
+ m_uRemainingChunkSize = szHexHeader.toLong(&bOk,16);
+ if(!bOk)
+ {
+ resetInternalStatus();
+ m_szLastError = __tr2qs("Protocol error: invalid chunk size");
+ emit terminated(false);
+ return;
+ }
+ m_pBuffer->remove(crlf+2);
+ if(m_uRemainingChunkSize == 0)
+ {
+ // this is the last chunk of data. It may be followed by optional headers
+ // but we actually don't need them (since we're surely not in HEAD mode)
+ m_bIgnoreRemainingData = true;
+ m_pBuffer->clear();
+ goto check_stream_length;
+ }
+ }
+ // the rest is valid data of a non-zero chunk: continue looping
+ } else {
+ // chunk header not complete
+ if(m_pBuffer->size() > 4096)
+ {
+ resetInternalStatus();
+ m_szLastError = __tr2qs("Chunk header too long: exceeded 4096 bytes");
+ emit terminated(false);
+ return;
+ }
+ goto check_stream_length;
+ }
+ }
+ }
+ } else {
+ // the transfer encoding is not chunked: m_pBuffer contains only valid data
+ switch(m_eProcessingType)
+ {
+ case Blocks:
+ if(m_pBuffer->size() > 0)emit binaryData(*m_pBuffer);
+ m_pBuffer->clear();
+ break;
+ case Lines:
+ if(m_pBuffer->size() > 0)emitLines(m_pBuffer);
+ break;
+ case StoreToFile:
+ m_pFile->writeBlock((const char *)(m_pBuffer->data()),m_pBuffer->size());
+ m_pBuffer->clear();
+ break;
+ default:
+ // nothing.. just make gcc happy
+ break;
+ }
+ }
+
+check_stream_length:
+
+ if(((m_uTotalSize > 0) && (m_uReceivedSize > m_uTotalSize)) || ((m_uMaxContentLength > 0) && (m_uReceivedSize > m_uMaxContentLength)))
+ {
+ resetInternalStatus();
+ m_szLastError=__tr2qs("Stream exceeded expected length");
+ emit terminated(false);
+ }
+ return;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+KviHttpRequestThread::KviHttpRequestThread(
+ KviHttpRequest * r,
+ const QString &szHost,
+ const QString &szIp,
+ unsigned short uPort,
+ const QString & szPath,
+ unsigned int uContentOffset,
+ RequestMethod m,
+ const QString &szPostData,
+ bool bUseSSL
+) : KviSensitiveThread()
+{
+ m_pRequest = r;
+ m_szHost = szHost;
+ m_szIp = szIp;
+ m_szPath = szPath;
+ m_uPort = uPort > 0 ? uPort : 80;
+ m_uContentOffset = uContentOffset;
+ m_eRequestMethod = m;
+ m_szPostData = szPostData;
+ m_sock = KVI_INVALID_SOCKET;
+ m_bUseSSL = bUseSSL;
+#ifdef COMPILE_SSL_SUPPORT
+ m_pSSL = 0;
+#endif
+}
+
+KviHttpRequestThread::~KviHttpRequestThread()
+{
+}
+
+bool KviHttpRequestThread::processInternalEvents()
+{
+ while(KviThreadEvent *e = dequeueEvent())
+ {
+ switch(e->id())
+ {
+ case KVI_THREAD_EVENT_TERMINATE:
+ {
+ delete e;
+ return false;
+ }
+ break;
+ default:
+ debug("Unrecognized event in http thread");
+ delete e;
+ return false;
+ break;
+ }
+ }
+
+ return true;
+}
+
+bool KviHttpRequestThread::failure(const char *error)
+{
+ if(error)
+ {
+ postEvent(m_pRequest,new KviThreadDataEvent<KviStr>(KVI_THREAD_EVENT_ERROR,new KviStr(error)));
+ } /*else {
+ postEvent(m_pRequest,new KviThreadDataEvent<KviStr>(KVI_THREAD_EVENT_ERROR,new KviStr(__tr2qs("Aborted"))));
+ }*/
+ return false;
+}
+
+
+bool KviHttpRequestThread::selectForWrite(int iTimeoutInSecs)
+{
+
+ kvi_time_t startTime = kvi_unixTime();
+
+ for(;;)
+ {
+ if(!processInternalEvents())
+ {
+ return failure(0);
+ }
+
+ fd_set writeSet;
+
+ FD_ZERO(&writeSet);
+
+ FD_SET(m_sock,&writeSet);
+
+ struct timeval tmv;
+ tmv.tv_sec = 0;
+ tmv.tv_usec = 1000; // we wait 1000 usecs for an event
+
+
+ int nRet = kvi_socket_select(m_sock + 1,0,&writeSet,0,&tmv);
+
+ if(nRet > 0)
+ {
+ if(FD_ISSET(m_sock,&writeSet))
+ {
+ // connected!
+ return true;
+ }
+ } else {
+ if(nRet < 0)
+ {
+ int err = kvi_socket_error();
+#ifdef COMPILE_ON_WINDOWS
+ if((err != EAGAIN) && (err != EINTR) && (err != WSAEWOULDBLOCK))
+#else
+ if((err != EAGAIN) && (err != EINTR))
+#endif
+ {
+ return failure(KviError::getUntranslatedDescription(KviError::translateSystemError(err)));
+ }
+ }
+ }
+
+
+ if((time(0) - startTime) > iTimeoutInSecs)return failure(__tr_no_lookup("Operation timed out"));
+
+ usleep(100000); // 1/10 sec
+ }
+
+ return false;
+}
+
+bool KviHttpRequestThread::sslFailure()
+{
+#ifdef COMPILE_SSL_SUPPORT
+ KviStr buffer;
+ if(m_pSSL->getLastErrorString(buffer))
+ {
+ failure(buffer.ptr());
+ } else {
+ failure(__tr_no_lookup("Unexpected SSL error"));
+ }
+#endif
+ return false;
+}
+
+bool KviHttpRequestThread::connectToRemoteHost()
+{
+ m_sock = kvi_socket_create(KVI_SOCKET_PF_INET,KVI_SOCKET_TYPE_STREAM,0); //tcp
+ if(m_sock == KVI_INVALID_SOCKET)
+ return failure(__tr_no_lookup("Failed to create the socket"));
+
+ if(!kvi_socket_setNonBlocking(m_sock))
+ return failure(__tr_no_lookup("Failed to enter non blocking mode"));
+
+ sockaddr_in saddr;
+
+ if(!KviNetUtils::stringIpToBinaryIp(m_szIp,&(saddr.sin_addr)))
+ return failure(__tr_no_lookup("Invalid target address"));
+
+ saddr.sin_port = htons(m_uPort);
+ saddr.sin_family = AF_INET;
+
+ if(!kvi_socket_connect(m_sock,(struct sockaddr *)&saddr,sizeof(saddr)))
+ {
+ int err = kvi_socket_error();
+ if(!kvi_socket_recoverableConnectError(err))
+ {
+ return failure(KviError::getUntranslatedDescription(KviError::translateSystemError(err)));
+ }
+ }
+
+ // now loop selecting for write
+
+ //#warning "This should be a tuneable timeout"
+ if(!selectForWrite(60))return false;
+
+ int sockError;
+ int iSize=sizeof(sockError);
+ if(!kvi_socket_getsockopt(m_sock,SOL_SOCKET,SO_ERROR,(void *)&sockError,&iSize))sockError = -1;
+ if(sockError != 0)
+ {
+ //failed
+ if(sockError > 0)sockError = KviError::translateSystemError(sockError);
+ else sockError = KviError_unknownError;
+ return failure(KviError::getUntranslatedDescription(sockError));
+ }
+
+#ifdef COMPILE_SSL_SUPPORT
+ if(m_bUseSSL)
+ {
+ m_pSSL = new KviSSL();
+ if(!m_pSSL->initContext(KviSSL::Client))
+ return failure(__tr_no_lookup("Failed to initialize the SSL context"));
+ if(!m_pSSL->initSocket(m_sock))
+ return failure(__tr_no_lookup("Failed to initialize the SSL connection"));
+
+ for(;;)
+ {
+ switch(m_pSSL->connect())
+ {
+ case KviSSL::Success:
+ // done: connected.
+ return true;
+ break;
+ case KviSSL::WantRead:
+ if(!selectForRead(60))return false;
+ break;
+ case KviSSL::WantWrite:
+ if(!selectForWrite(60))return false;
+ break;
+ case KviSSL::RemoteEndClosedConnection:
+ return failure(__tr_no_lookup("Remote end has closed the connection"));
+ break;
+ case KviSSL::SSLError:
+ return sslFailure();
+ break;
+ case KviSSL::SyscallError:
+ {
+ // syscall problem
+ int err = kvi_socket_error();
+ if(!kvi_socket_recoverableError(err))
+ {
+ // Declare problems :)
+ return failure(__tr_no_lookup("Unrecoverable SSL error during handshake"));
+ } // else can recover ? (EAGAIN , EINTR ?) ... should select for read or for write
+ }
+ break;
+ default:
+ return sslFailure();
+ break;
+ }
+ }
+
+ // never here
+ return true;
+ }
+#endif
+
+ return true;
+}
+
+
+bool KviHttpRequestThread::sendBuffer(const char * buffer,int bufLen,int iTimeoutInSecs)
+{
+ const char * ptr = buffer;
+ int curLen = bufLen;
+
+ time_t startTime = time(0);
+
+ for(;;)
+ {
+ if(!processInternalEvents())return failure();
+
+ int wrtn;
+#ifdef COMPILE_SSL_SUPPORT
+ if(m_pSSL)
+ {
+ wrtn = m_pSSL->write((char *)ptr,curLen);
+ } else {
+#endif
+ wrtn = kvi_socket_send(m_sock,ptr,curLen);
+#ifdef COMPILE_SSL_SUPPORT
+ }
+#endif
+
+ if(wrtn > 0)
+ {
+ curLen -= wrtn;
+
+ if(curLen <= 0)break;
+
+ ptr += wrtn;
+ } else {
+ if(wrtn < 0)
+ {
+#ifdef COMPILE_SSL_SUPPORT
+ if(m_pSSL)
+ {
+ // ops...might be an SSL error
+ switch(m_pSSL->getProtocolError(wrtn))
+ {
+ case KviSSL::WantWrite:
+ if(!selectForWrite(60))return false;
+ break;
+ case KviSSL::WantRead:
+ if(!selectForRead(60))return false;
+ break;
+ case KviSSL::SyscallError:
+ if(wrtn == 0)
+ {
+ return failure(__tr_no_lookup("Remote end has closed the connection"));
+ } else {
+ int iSSLErr = m_pSSL->getLastError(true);
+ if(iSSLErr != 0)
+ {
+ return sslFailure();
+ } else {
+ goto handle_system_error;
+ }
+ }
+ break;
+ case KviSSL::SSLError:
+ return sslFailure();
+ break;
+ default:
+ return sslFailure();
+ break;
+ }
+ } else {
+#endif //COMPILE_SSL_SUPPORT
+
+handle_system_error:
+ int err = kvi_socket_error();
+#ifdef COMPILE_ON_WINDOWS
+ if((err != EAGAIN) && (err != EINTR) && (err != WSAEWOULDBLOCK))
+#else
+ if((err != EAGAIN) && (err != EINTR))
+#endif
+ {
+ return failure(KviError::getUntranslatedDescription(KviError::translateSystemError(err)));
+ }
+#ifdef COMPILE_SSL_SUPPORT
+ }
+#endif
+ }
+ }
+
+ int diff = time(0) - startTime;
+ if(diff > iTimeoutInSecs)
+ return failure(__tr_no_lookup("Operation timed out"));
+
+ usleep(10000);
+ }
+
+ return true;
+}
+
+
+int KviHttpRequestThread::selectForReadStep()
+{
+ // calls select on the main socket
+ // returns 1 if there is data available for reading
+ // returns 0 if there is no data available but there was no error
+ // returns -1 if there was a critical error (socket closed)
+ fd_set readSet;
+
+ FD_ZERO(&readSet);
+
+ FD_SET(m_sock,&readSet);
+
+ struct timeval tmv;
+ tmv.tv_sec = 0;
+ tmv.tv_usec = 1000; // we wait 1000 usecs for an event
+
+
+ int nRet = kvi_socket_select(m_sock + 1,&readSet,0,0,&tmv);
+
+ if(nRet > 0)
+ {
+ if(FD_ISSET(m_sock,&readSet))
+ {
+ // ok
+ return 1;
+ }
+ } else {
+ if(nRet < 0)
+ {
+ int err = kvi_socket_error();
+#ifdef COMPILE_ON_WINDOWS
+ if((err != EAGAIN) && (err != EINTR) && (err != WSAEWOULDBLOCK))
+#else
+ if((err != EAGAIN) && (err != EINTR))
+#endif
+ {
+ failure(KviError::getUntranslatedDescription(KviError::translateSystemError(err)));
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+bool KviHttpRequestThread::selectForRead(int iTimeoutInSecs)
+{
+ // waits for some data to arrive on the socket
+ // up to iTimeoutInSecs seconds
+ // returns true if data is available on the socket
+ // or false if there was a select() error or no data
+ // was available in the specified amount of time
+
+ time_t startTime = time(0);
+
+ for(;;)
+ {
+ if(!processInternalEvents())
+ {
+ return failure(); // ensure that the socket is closed
+ }
+
+ int nRet = selectForReadStep();
+
+ if(nRet < 0)return false;
+ if(nRet > 0)return true;
+
+ int diff = time(0) - startTime;
+ if(diff > iTimeoutInSecs)
+ return failure(__tr_no_lookup("Operation timed out (while selecting for read)"));
+
+ usleep(100000); // 1/10 sec
+ }
+
+ return false;
+}
+
+bool KviHttpRequestThread::readDataStep()
+{
+ unsigned char buffer[2048];
+ int readed;
+
+
+#ifdef COMPILE_SSL_SUPPORT
+ if(m_pSSL)
+ {
+ readed = m_pSSL->read((char *)buffer,2048);
+ if(readed <= 0)
+ {
+ // ssl error....?
+ switch(m_pSSL->getProtocolError(readed))
+ {
+ case KviSSL::ZeroReturn:
+ readed = 0;
+ break;
+ case KviSSL::WantRead:
+ return selectForRead(120);
+ break;
+ case KviSSL::WantWrite:
+ return selectForWrite(120);
+ break;
+ case KviSSL::SyscallError:
+ {
+ int iE = m_pSSL->getLastError(true);
+ if(iE != 0)return sslFailure();
+ }
+ break;
+ case KviSSL::SSLError:
+ return sslFailure();
+ break;
+ default:
+ return sslFailure();
+ break;
+ }
+ }
+ } else {
+#endif
+ readed = kvi_socket_read(m_sock,buffer,2048);
+#ifdef COMPILE_SSL_SUPPORT
+ }
+#endif
+
+ if(readed > 0)
+ {
+ postEvent(m_pRequest,new KviThreadDataEvent<KviDataBuffer>(KVI_THREAD_EVENT_BINARYDATA,new KviDataBuffer(readed,buffer)));
+ } else {
+ if(readed < 0)
+ {
+ // Read error ?
+ int err = kvi_socket_error();
+#ifdef COMPILE_ON_WINDOWS
+ if((err != EAGAIN) && (err != EINTR) && (err != WSAEWOULDBLOCK))
+#else
+ if((err != EAGAIN) && (err != EINTR))
+#endif
+ {
+ // yes...read error
+ return failure(KviError::getUntranslatedDescription(KviError::translateSystemError(err)));
+ }
+ return selectForRead(120); // EINTR or EAGAIN...transient problem
+ } else {
+ // readed == 0
+ // Connection closed by remote host
+ postEvent(m_pRequest,new KviThreadEvent(KVI_THREAD_EVENT_SUCCESS));
+ return false;
+ }
+ }
+ return selectForRead(120);
+}
+
+void KviHttpRequestThread::run()
+{
+ // setup:
+ // nothing needed
+
+ // run:
+ runInternal();
+
+ // cleanup:
+#ifdef COMPILE_SSL_SUPPORT
+ if(m_pSSL)
+ {
+ delete m_pSSL;
+ m_pSSL = 0;
+ }
+#endif
+
+ if(kvi_socket_isValid(m_sock))
+ {
+ kvi_socket_close(m_sock);
+ m_sock = KVI_INVALID_SOCKET;
+ }
+}
+
+void KviHttpRequestThread::runInternal()
+{
+#ifndef COMPILE_SSL_SUPPORT
+ if(m_bUseSSL)
+ {
+ failure(__tr_no_lookup("This KVIrc executable has no SSL support"));
+ return;
+ }
+#endif
+
+ if(!connectToRemoteHost())return;
+
+ postEvent(m_pRequest,new KviThreadEvent(KVI_HTTP_REQUEST_THREAD_EVENT_CONNECTED));
+
+ // FIXME: Other headers ?
+
+ KviStr szMethod;
+ switch(m_eRequestMethod)
+ {
+ case Head: szMethod = "HEAD"; break;
+ case Post: szMethod = "POST"; break;
+ case Get: szMethod = "GET"; break;
+ }
+
+ KviStr szRequest(KviStr::Format,"%s %s HTTP/1.1\r\n" \
+ "Host: %s\r\n" \
+ "Connection: Close\r\n" \
+ "User-Agent: KVIrc-http-slave/1.0.0\r\n" \
+ "Accept: */*\r\n",
+ szMethod.ptr(),KviQString::toUtf8(m_szPath).data(),KviQString::toUtf8(m_szHost).data());
+
+ if(m_uContentOffset > 0)
+ szRequest.append(KviStr::Format,"Range: bytes=%u-\r\n",m_uContentOffset);
+
+ if(m_eRequestMethod == Post)
+ {
+ szRequest.append(KviStr::Format,"Content-Type: application/x-www-form-urlencoded\r\n" \
+ "Content-Length: %u\r\n" \
+ "Cache-control: no-cache\r\n" \
+ "Pragma: no-cache\r\n",m_szPostData.length());
+ }
+
+ szRequest += "\r\n";
+
+ if(m_eRequestMethod == Post)
+ {
+ if(!m_szPostData.isEmpty())
+ szRequest.append(m_szPostData);
+ szRequest += "\r\n";
+ }
+
+ //debug("SENDING REQUEST:\n%s",szRequest.ptr());
+
+ if(!sendBuffer(szRequest.ptr(),szRequest.len(),60))return;
+
+ // now loop reading data
+ postEvent(m_pRequest,new KviThreadDataEvent<QString>(KVI_HTTP_REQUEST_THREAD_EVENT_REQUESTSENT,new QString(szRequest)));
+
+ for(;;)
+ {
+ if(!readDataStep())return;
+ }
+}
+
diff --git a/src/kvilib/net/kvi_http.h b/src/kvilib/net/kvi_http.h
new file mode 100644
index 00000000..1bd6a9d9
--- /dev/null
+++ b/src/kvilib/net/kvi_http.h
@@ -0,0 +1,209 @@
+#ifndef _KVI_HTTP_H_
+#define _KVI_HTTP_H_
+//=============================================================================
+//
+// File : kvi_http.h
+// Creation date : Sat Aug 17 13:43:31 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002-2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) any later version.
+//
+// This program is distributed in the HOPE that it will be USEFUL,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc. ,59 Temple Place - Suite 33, Boston, MA 02110-1301, USA.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_heapobject.h"
+#include "kvi_string.h"
+#include "kvi_thread.h"
+#include "kvi_sockettype.h"
+#include "kvi_databuffer.h"
+#include "kvi_inttypes.h"
+#include "kvi_url.h"
+
+#include <qobject.h>
+#include "kvi_pointerhashtable.h"
+#include "kvi_file.h"
+#include <qstringlist.h>
+
+class KviDns;
+class KviSSL;
+class KviHttpRequestThread;
+
+//
+// This class implements a HTTP protocol client.
+// It's able to send GET, POST and HEAD requests,
+// download stuff to a file or to a qt SLOT().
+//
+
+class KVILIB_API KviHttpRequest : public QObject, public KviHeapObject
+{
+ Q_OBJECT
+public:
+ enum ProcessingType
+ {
+ HeadersOnly, // Download headers only (HEAD request)
+ WholeFile, // Emit the data as whole file (binaryData() is emitted)
+ Blocks, // Emit the data as blocks (binaryData() is emitted)
+ Lines, // Emit the data as ASCII text lines (the client must take care of decoding the data)
+ StoreToFile // Store the data to a file
+ };
+ enum ExistingFileAction
+ {
+ Overwrite, // Overwrite existing file
+ RenameIncoming, // Automatically rename the incoming file
+ RenameExisting, // Automatically rename the existing file
+ Resume // Attempt to resume the file (get partial content)
+ };
+public:
+ KviHttpRequest();
+ ~KviHttpRequest();
+protected:
+ // data
+ KviUrl m_url;
+ QString m_szFileName;
+ ProcessingType m_eProcessingType;
+ ExistingFileAction m_eExistingFileAction;
+ void * m_pPrivateData;
+ unsigned int m_uMaxContentLength;
+ unsigned int m_uContentOffset;
+ QString m_szPostData;
+ // status
+ QString m_szLastError;
+ unsigned int m_uTotalSize;
+ unsigned int m_uReceivedSize;
+ // internal status
+ QString m_szIp;
+ KviDns * m_pDns;
+ KviHttpRequestThread * m_pThread;
+ KviDataBuffer * m_pBuffer;
+ bool m_bHeaderProcessed;
+ bool m_bChunkedTransferEncoding;
+ bool m_bGzip;
+ unsigned int m_uRemainingChunkSize;
+ bool m_bIgnoreRemainingData; // used in chunked transfer after the last chunk has been seen
+ KviFile * m_pFile;
+protected:
+ bool startDnsLookup();
+ virtual bool event(QEvent *e);
+ void processData(KviDataBuffer * data);
+ bool processHeader(KviStr &szHeader);
+ bool openFile();
+ void emitLines(KviDataBuffer * pDataBuffer);
+
+ void resetStatus();
+ void resetData();
+ void resetInternalStatus();
+protected slots:
+ void dnsLookupDone(KviDns *d);
+ void haveServerIp();
+public:
+ const KviUrl & url(){ return m_url; };
+ ProcessingType processingType(){ return m_eProcessingType; };
+ ExistingFileAction existingFileAction(){ return m_eExistingFileAction; };
+ const QString &fileName(){ return m_szFileName; };
+ void * privateData(){ return m_pPrivateData; };
+ unsigned int maxContentLength(){ return m_uMaxContentLength; };
+ unsigned int contentOffset(){ return m_uContentOffset; };
+ unsigned int totalSize(){ return m_uTotalSize; };
+ unsigned int receivedSize(){ return m_uReceivedSize; };
+
+ void reset();
+
+ void setPostData(const QString &szPostData){ m_szPostData = szPostData; };
+ void setUrl(const KviUrl &u){ m_url = u; };
+ void setProcessingType(ProcessingType t){ m_eProcessingType = t; };
+ void setExistingFileAction(ExistingFileAction a){ m_eExistingFileAction = a; };
+ void setFileName(const QString &szFileName){ m_szFileName = szFileName; };
+ void setPrivateData(void * ptr){ m_pPrivateData = ptr; };
+ void setMaxContentLength(int uMaxContentLength){ m_uMaxContentLength = uMaxContentLength; }; //0 means unlimited
+ // this will work regardless of ExistingFileAction : even if the file doesn't exist
+ void setContentOffset(int uContentOffset){ m_uContentOffset = uContentOffset; };
+
+ bool start();
+
+ // this is a shortcut for reset()+setUrl()+setProcessingType()+setFileName()+start()
+ bool get(const KviUrl &u,ProcessingType p = WholeFile,const QString &szFileName = QString::null);
+
+ const QString & lastError(){ return m_szLastError; };
+
+ void abort();
+signals:
+ void resolvingHost(const QString &hostname);
+ void contactingHost(const QString &ipandport);
+ void connectionEstabilished();
+ void receivedResponse(const QString &response);
+
+ void terminated(bool bSuccess);
+
+
+ void status(const QString &message);
+ void data(const KviStr &data);
+ void binaryData(const KviDataBuffer &data);
+ void header(KviPointerHashTable<const char *,KviStr> * hdr);
+ void requestSent(const QStringList &request);
+};
+
+
+class KviHttpRequestThread : public KviSensitiveThread
+{
+ friend class KviHttpRequest;
+public:
+ enum RequestMethod { Post, Get , Head };
+protected:
+ KviHttpRequestThread(KviHttpRequest * r,
+ const QString &szHost,
+ const QString &szIp,
+ unsigned short uPort,
+ const QString &szPath,
+ unsigned int uContentOffset,
+ RequestMethod m,
+ const QString &szPostData = QString::null,
+ bool bUseSSL = false);
+
+public:
+ ~KviHttpRequestThread();
+protected:
+ KviHttpRequest * m_pRequest;
+
+ QString m_szHost;
+ QString m_szIp;
+ QString m_szPath;
+ unsigned int m_uContentOffset;
+ RequestMethod m_eRequestMethod;
+ QString m_szPostData;
+
+ unsigned short m_uPort;
+ kvi_socket_t m_sock;
+ bool m_bUseSSL;
+#ifdef COMPILE_SSL_SUPPORT
+ KviSSL * m_pSSL;
+#endif
+protected:
+ int selectForReadStep();
+ bool selectForRead(int iTimeoutInSecs);
+ bool readDataStep();
+ bool sendBuffer(const char *buffer,int bufLen,int iTimeoutInSecs);
+ bool failure(const char *error=0);
+ bool sslFailure();
+ bool selectForWrite(int iTimeoutInSecs);
+ bool connectToRemoteHost();
+ bool processInternalEvents();
+ void runInternal();
+ virtual void run();
+};
+
+
+#endif //_KVI_HTTP_H_
diff --git a/src/kvilib/net/kvi_netutils.cpp b/src/kvilib/net/kvi_netutils.cpp
new file mode 100644
index 00000000..0cdb8b02
--- /dev/null
+++ b/src/kvilib/net/kvi_netutils.cpp
@@ -0,0 +1,1504 @@
+//=============================================================================
+
+//
+
+// File : kvi_netutlis.cpp
+
+// Creation date : Sun Jun 18 2000 18:37:27 by Szymon Stefanek
+
+//
+
+// This file is part of the KVirc irc client distribution
+
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+
+//
+
+//=============================================================================
+
+// AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARGH!
+// This effect is caused by the combination of broken CVS installation and
+// the ugly windows "text mode" files
+
+#define __KVILIB__
+
+
+
+
+
+#define _KVI_NETUTILS_CPP_
+
+
+
+#include "kvi_netutils.h"
+
+#include "kvi_memmove.h"
+#include <qstringlist.h>
+
+
+#ifndef COMPILE_ON_WINDOWS
+
+#include <sys/time.h> // struct timeval
+
+#endif
+
+
+
+#include <sys/types.h>
+
+
+
+#include "kvi_qstring.h"
+
+
+
+#ifndef COMPILE_ON_WINDOWS
+
+ #include <unistd.h>
+
+ #include <netdb.h>
+
+#endif
+
+
+
+#ifdef COMPILE_GET_INTERFACE_ADDRESS
+
+ #include <sys/ioctl.h>
+
+ #include <net/if.h>
+
+#endif //COMPILE_GET_INTERFACE_ADDRESS
+
+
+
+#ifndef HAVE_INET_ATON
+
+
+
+
+
+// FIXME: #warning "Your system lacks the inet_aton function,"
+
+// FIXME: #warning "you're trying to compile this file without"
+
+// FIXME: #warning "the config.h created by the configure script,"
+
+// FIXME: #warning "Using own internal implementation of inet_aton."
+
+
+
+#include <ctype.h>
+
+
+
+
+
+// Need own inet_aton implementation
+
+
+
+//
+
+// Check whether "cp" is a valid ascii representation
+
+// of an Internet address and convert to a binary address.
+
+// Returns 1 if the address is valid, 0 if not.
+
+// This replaces inet_addr, the return value from which
+
+// cannot distinguish between failure and a local broadcast address.
+
+//
+
+// Original code comes from the ircd source.
+
+//
+
+
+
+bool kvi_stringIpToBinaryIp(const char *szIp,struct in_addr *address)
+
+{
+
+ register unsigned long val;
+
+ register int base, n;
+
+ register char c;
+
+ unsigned int parts[4];
+
+ register unsigned int *pp = parts;
+
+ if(!szIp)return false;
+
+ c = *szIp;
+
+ for(;;){
+
+ // Collect number up to ``.''.
+
+ // Values are specified as for C:
+
+ // 0x=hex, 0=octal, isdigit=decimal.
+
+ if(!isdigit(c))return false;
+
+ val = 0;
+
+ base = 10;
+
+ if(c == '0'){
+
+ c = *++szIp;
+
+ if((c == 'x')||(c == 'X'))base = 16, c = *++szIp;
+
+ else base = 8;
+
+ }
+
+ for (;;) {
+
+ if(isascii(c) && isdigit(c)) {
+
+ val = (val * base) + (c - '0');
+
+ c = *++szIp;
+
+ } else if (base == 16 && isascii(c) && isxdigit(c)) {
+
+ val = (val << 4) | (c + 10 - (islower(c) ? 'a' : 'A'));
+
+ c = *++szIp;
+
+ } else break;
+
+ }
+
+ if(c == '.'){
+
+ // Internet format:
+
+ // a.b.c.d
+
+ // a.b.c (with c treated as 16 bits)
+
+ // a.b (with b treated as 24 bits)
+
+ if(pp >= (parts + 3)) return false;
+
+ *pp++ = val;
+
+ c = *++szIp;
+
+ } else break;
+
+ }
+
+ // Check for trailing characters.
+
+ if ((c != '\0') && (!isascii(c) || !isspace(c)))return false;
+
+ // Concact the address according to
+
+ // the number of parts specified.
+
+ n = pp - parts + 1;
+
+ switch (n) {
+
+ case 0: return false; // initial nondigit
+
+ case 1: break; // a -- 32 bits
+
+ case 2: // a.b -- 8.24 bits
+
+ if(val > 0xffffff) return false;
+
+ val |= parts[0] << 24;
+
+ break;
+
+ case 3: // a.b.c -- 8.8.16 bits
+
+ if(val > 0xffff)return false;
+
+ val |= (parts[0] << 24) | (parts[1] << 16);
+
+ break;
+
+ case 4: // a.b.c.d -- 8.8.8.8 bits
+
+ if(val > 0xff)return false;
+
+ val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
+
+ break;
+
+ }
+
+ if(address)address->s_addr = htonl(val);
+
+ return true;
+
+}
+
+
+
+#else //!HAVE_INET_ATON
+
+
+
+bool kvi_stringIpToBinaryIp(const char *szIp,struct in_addr *address)
+
+{
+
+ if(!szIp)return false;
+
+ return (inet_aton(szIp,address) != 0);
+
+}
+
+
+
+#endif //!HAVE_INET_ATON
+
+
+
+#ifndef HAVE_INET_NTOA
+
+
+
+// FIXME: #warning "Your system lacks the inet_ntoa function,"
+
+// FIXME: #warning "you're trying to compile this file without"
+
+// FIXME: #warning "the config.h created by the configure script,"
+
+// FIXME: #warning "Using own internal implementation of inet_ntoa."
+
+
+
+//
+
+// Original code comes from the ircd source.
+
+//
+
+
+
+bool kvi_binaryIpToStringIp(struct in_addr in,QString &szBuffer)
+
+{
+
+ unsigned char *s = (unsigned char *)&in;
+
+ int a,b,c,d;
+
+ a = (int)*s++;
+
+ b = (int)*s++;
+
+ c = (int)*s++;
+
+ d = (int)*s;
+
+ szBuffer.sprintf("%d.%d.%d.%d", a,b,c,d );
+
+ return true;
+
+}
+
+
+
+#else //HAVE_INET_NTOA
+
+
+
+bool kvi_binaryIpToStringIp(struct in_addr in,QString &szBuffer)
+
+{
+
+// FIXME: #warning "This is NOT thread safe!"
+
+ char * ptr = inet_ntoa(in);
+
+ if(!ptr)return false;
+
+ szBuffer = ptr;
+
+ return true;
+
+}
+
+
+
+#endif //HAVE_INET_NTOA
+
+
+
+bool kvi_isValidStringIp(const char *szIp)
+
+{
+
+ struct in_addr address;
+
+ if(!szIp)return false;
+
+ if(!isdigit(*szIp))return false;
+
+ return kvi_stringIpToBinaryIp(szIp,&address);
+
+}
+
+
+
+
+
+#ifdef COMPILE_IPV6_SUPPORT
+
+
+
+#ifdef COMPILE_ON_WINDOWS
+
+
+
+//#include <stdlib.h>
+
+//#include <sys/socket.h>
+
+//#include <arpa/inet.h>/
+
+//#include <errno.h>
+
+//#include "dietfeatures.h"
+
+
+
+static unsigned int scan_ip6(const char *s,char ip[16])
+
+{
+
+ unsigned int i;
+
+ unsigned int len=0;
+
+ unsigned long u;
+
+
+
+ char suffix[16];
+
+ unsigned int prefixlen=0;
+
+ unsigned int suffixlen=0;
+
+
+
+ for (i=0; i<16; i++) ip[i]=0;
+
+
+
+ for (;;) {
+
+ if (*s == ':') {
+
+ len++;
+
+ if (s[1] == ':') { /* Found "::", skip to part 2 */
+
+ s+=2;
+
+ len++;
+
+ break;
+
+ }
+
+ s++;
+
+ }
+
+ {
+
+ char *tmp;
+
+ u=strtoul(s,&tmp,16);
+
+ i=tmp-s;
+
+ }
+
+
+
+ if (!i) return 0;
+
+ if (prefixlen==12 && s[i]=='.') {
+
+ /* the last 4 bytes may be written as IPv4 address */
+
+ if (kvi_stringIpToBinaryIp(s,(struct in_addr*)(ip+12)))
+
+ return i+len;
+
+ else
+
+ return 0;
+
+ }
+
+ ip[prefixlen++] = (u >> 8);
+
+ ip[prefixlen++] = (u & 255);
+
+ s += i; len += i;
+
+ if (prefixlen==16)
+
+ return len;
+
+ }
+
+
+
+/* part 2, after "::" */
+
+ for (;;) {
+
+ if (*s == ':') {
+
+ if (suffixlen==0)
+
+ break;
+
+ s++;
+
+ len++;
+
+ } else if (suffixlen!=0)
+
+ break;
+
+ {
+
+ char *tmp;
+
+ u=strtol(s,&tmp,16);
+
+ i=tmp-s;
+
+ }
+
+ if (!i) {
+
+ if (*s) len--;
+
+ break;
+
+ }
+
+ if (suffixlen+prefixlen<=12 && s[i]=='.') {
+
+ if (kvi_stringIpToBinaryIp(s,(struct in_addr*)(suffix+suffixlen))) {
+
+ suffixlen+=4;
+
+ len+=(unsigned int)strlen(s);
+
+ break;
+
+ } else
+
+ prefixlen=12-suffixlen; /* make end-of-loop test true */
+
+ }
+
+ suffix[suffixlen++] = (u >> 8);
+
+ suffix[suffixlen++] = (u & 255);
+
+ s += i; len += i;
+
+ if (prefixlen+suffixlen==16)
+
+ break;
+
+ }
+
+ for (i=0; i<suffixlen; i++)
+
+ ip[16-suffixlen+i] = suffix[i];
+
+ return len;
+
+}
+
+
+
+#ifndef WIN2K
+
+
+
+int inet_pton(int AF, const char *CP, void *BUF) {
+
+ int len;
+
+ if (AF==AF_INET) {
+
+ if (!kvi_stringIpToBinaryIp(CP,(struct in_addr*)BUF))
+
+ return 0;
+
+ } else if (AF==AF_INET6) {
+
+ if (CP[len=scan_ip6(CP,(char *)BUF)])
+
+ return 0;
+
+ } else {
+
+ errno=WSAEPFNOSUPPORT;
+
+ return -1;
+
+ }
+
+ return 1;
+
+}
+
+
+
+#endif //WIN2K
+
+
+
+//#include <sys/socket.h>
+
+//#include <arpa/inet.h>
+
+
+
+//extern char *inet_ntoa_r(struct in_addr in,char* buf);
+
+
+
+static const unsigned char V4mappedprefix[12]={0,0,0,0,0,0,0,0,0,0,0xff,0xff};
+
+
+
+static char tohex(char hexdigit) {
+
+ return hexdigit>9?hexdigit+'a'-10:hexdigit+'0';
+
+}
+
+
+
+static int fmt_xlong(char* s,unsigned int i)
+
+{
+
+ char* bak=s;
+
+ *s=tohex((i>>12)&0xf); if (s!=bak || *s!='0') ++s;
+
+ *s=tohex((i>>8)&0xf); if (s!=bak || *s!='0') ++s;
+
+ *s=tohex((i>>4)&0xf); if (s!=bak || *s!='0') ++s;
+
+ *s=tohex(i&0xf);
+
+ return s-bak+1;
+
+}
+
+
+
+static unsigned int i2a(char* dest,unsigned int x)
+
+{
+
+ register unsigned int tmp=x;
+
+ register unsigned int len=0;
+
+ if (x>=100) { *dest++=tmp/100+'0'; tmp=tmp%100; ++len; }
+
+ if (x>=10) { *dest++=tmp/10+'0'; tmp=tmp%10; ++len; }
+
+ *dest++=tmp+'0';
+
+ return len+1;
+
+}
+
+
+
+char *inet_ntoa_r(struct in_addr in,char* buf)
+
+{
+
+ unsigned int len;
+
+ unsigned char *ip=(unsigned char*)&in;
+
+ len=i2a(buf,ip[0]); buf[len]='.'; ++len;
+
+ len+=i2a(buf+ len,ip[1]); buf[len]='.'; ++len;
+
+ len+=i2a(buf+ len,ip[2]); buf[len]='.'; ++len;
+
+ len+=i2a(buf+ len,ip[3]); buf[len]=0;
+
+ return buf;
+
+}
+
+
+
+
+
+unsigned int fmt_ip6(char *s,const char ip[16])
+
+{
+
+ unsigned int len;
+
+ unsigned int i;
+
+ unsigned int temp;
+
+ unsigned int compressing; // 0 not compressing , 1 compressing now , 2 already compressed once
+
+
+
+ len = 0;
+
+ compressing = 0;
+
+
+
+ for(int j=0;j<16;j+=2)
+
+ {
+
+ if (j==12 && !memcmp(ip,V4mappedprefix,12))
+
+ {
+
+ inet_ntoa_r(*(struct in_addr*)(ip+12),s);
+
+ temp=(unsigned int)strlen(s);
+
+ return len+temp;
+
+ }
+
+ temp = ((unsigned long) (unsigned char) ip[j] << 8) + (unsigned long) (unsigned char) ip[j+1];
+
+ if(temp == 0)
+
+ {
+
+ if(compressing == 0)
+
+ {
+
+ compressing=1;
+
+ if (j==0)
+
+ {
+
+ *s++=':';
+
+ ++len;
+
+ }
+
+ }
+
+ } else {
+
+ if(compressing == 1)
+
+ {
+
+ compressing=2; // don't do it again
+
+ *s++=':'; ++len;
+
+ }
+
+ i = fmt_xlong(s,temp);
+
+ len += i;
+
+ s += i;
+
+ if (j<14)
+
+ {
+
+ *s++ = ':';
+
+ ++len;
+
+ }
+
+ }
+
+ }
+
+ if(compressing == 1)
+
+ {
+
+ *s++=':';
+
+ ++len;
+
+ }
+
+ *s=0;
+
+ return len;
+
+}
+
+
+
+const char* inet_ntop(int AF, const void *CP, char *BUF, size_t LEN)
+
+{
+
+ char buf[100];
+
+ size_t len;
+
+ if (AF==AF_INET)
+
+ {
+
+ inet_ntoa_r(*(struct in_addr*)CP,buf);
+
+ len=strlen(buf);
+
+ } else if (AF==AF_INET6)
+
+ {
+
+ len=fmt_ip6(buf,(char *)CP);
+
+ } else
+
+ return 0;
+
+ if (len<LEN)
+
+ {
+
+ strcpy(BUF,buf);
+
+ return BUF;
+
+ }
+
+ return 0;
+
+}
+
+
+
+
+
+
+
+
+
+
+
+#endif
+
+
+
+
+
+bool kvi_stringIpToBinaryIp_V6(const char *szIp,struct in6_addr *address)
+
+{
+
+ if(!szIp)return false;
+
+ return (inet_pton(AF_INET6,szIp,(void *)address) == 1);
+
+}
+
+
+
+bool kvi_isValidStringIp_V6(const char *szIp)
+
+{
+
+ struct in6_addr address;
+
+ if(!szIp)return false;
+
+ return kvi_stringIpToBinaryIp_V6(szIp,&address);
+
+}
+
+
+
+
+
+
+
+bool kvi_binaryIpToStringIp_V6(struct in6_addr in,QString &szBuffer)
+
+{
+
+ char buf[46];
+
+ bool bRet = inet_ntop(AF_INET6,(void *)&in,buf,46);
+
+ szBuffer= buf;
+
+ return bRet;
+
+}
+
+
+
+#endif
+
+
+
+#include <errno.h>
+
+
+
+bool kvi_select(int fd,bool * bCanRead,bool * bCanWrite,int iUSecs)
+
+{
+
+ // FIXME: This stuff should DIE!
+
+ fd_set rs;
+
+ fd_set ws;
+
+ FD_ZERO(&rs);
+
+ FD_ZERO(&ws);
+
+ FD_SET(fd,&rs);
+
+ FD_SET(fd,&ws);
+
+ struct timeval tv;
+
+ tv.tv_sec = 0;
+
+ tv.tv_usec = iUSecs;
+
+ int ret = select(fd + 1,&rs,&ws,0,&tv);
+
+ if(ret < 1)return false; // EINTR or ENOSTUFFATALL
+
+ *bCanRead = FD_ISSET(fd,&rs);
+
+ *bCanWrite = FD_ISSET(fd,&ws);
+
+ return true;
+
+}
+
+
+
+namespace KviNetUtils
+
+{
+
+ bool stringIpToBinaryIp(const QString &szStringIp,struct in_addr * address)
+ {
+#ifndef HAVE_INET_ATON
+ QString szAddr = szStringIp.simplifyWhiteSpace();
+ Q_UINT32 iAddr=0;
+ QStringList ipv4 = QStringList::split(".", szAddr, FALSE);
+ if (ipv4.count() == 4) {
+ int i = 0;
+ bool ok = TRUE;
+ while(ok && i < 4) {
+ uint byteValue = ipv4[i].toUInt(&ok);
+ if ( (byteValue > 255) && ok )
+ ok = FALSE;
+ if (ok)
+ iAddr = (iAddr << 8) + byteValue;
+ ++i;
+ }
+ if (ok)
+ {
+ if(address)address->s_addr = htonl(iAddr);
+ return true;
+ }
+ }
+ return FALSE;
+#else //HAVE_INET_ATON
+ if(szStringIp.isEmpty())return false;
+ return (inet_aton(KviQString::toUtf8(szStringIp).data(),address) != 0);
+#endif //HAVE_INET_ATON
+ }
+
+
+ bool isValidStringIp(const QString &szIp)
+
+ {
+
+ struct in_addr address;
+
+ if(szIp.isEmpty())return false;
+
+ if(!szIp[0].isNumber())return false;
+
+ return stringIpToBinaryIp(szIp,&address);
+
+ }
+
+
+
+#ifdef COMPILE_IPV6_SUPPORT
+
+ bool stringIpToBinaryIp_V6(const QString &szStringIp,struct in6_addr * address)
+
+ {
+
+ return (inet_pton(AF_INET6,KviQString::toUtf8(szStringIp).data(),(void *)address) == 1);
+
+ }
+
+
+
+ bool isValidStringIp_V6(const QString &szIp)
+
+ {
+
+ struct in6_addr address;
+
+ if(szIp.isEmpty())return false;
+
+ return stringIpToBinaryIp_V6(szIp,&address);
+
+ }
+
+ bool binaryIpToStringIp_V6(struct in6_addr in,QString &szBuffer)
+ {
+ char buf[46];
+ bool bRet = inet_ntop(AF_INET6,(void *)&in,buf,46);
+ szBuffer= buf;
+ return bRet;
+ }
+
+
+#endif //COMPILE_IPV6_SUPPORT
+
+
+
+ bool binaryIpToStringIp(struct in_addr in,QString &szBuffer)
+
+ {
+
+ char * ptr = inet_ntoa(in);
+
+ if(!ptr)return false;
+
+ szBuffer = ptr;
+
+ return true;
+
+ }
+
+
+
+ bool isRoutableIpString(const QString &szIpString)
+
+ {
+
+ struct in_addr a;
+
+ if(szIpString.isEmpty())return false;
+
+ stringIpToBinaryIp(szIpString,&a);
+
+ return isRoutableIp((const char *)&a);
+
+ }
+
+
+
+ bool isRoutableIp(const char * ipaddr)
+
+ {
+
+ if(!ipaddr)return false;
+
+ const unsigned char * ip = (const unsigned char *)ipaddr;
+
+ if(ip[0] == 0)return false; // old-style broadcast
+
+ if(ip[0] == 10)return false; // Class A VPN
+
+ if(ip[0] == 127)return false; // loopback
+
+ if((ip[0] == 172) && (ip[1] >= 16) && (ip[1] <= 31))return false; // Class B VPN
+
+ if((ip[0] == 192) && (ip[1] == 168))return false; // Class C VPN
+
+ if((ip[0] == 169) && (ip[1] == 254))return false; // APIPA
+
+ if((ip[0] == 192) && (ip[1] == 0) && (ip[2] == 2))return false; // Class B VPN
+
+ if(ip[0] >= 224)return false; // class D multicast and class E reserved
+
+
+
+ return true;
+
+ }
+
+
+
+ bool getInterfaceAddress(const QString &szInterfaceName,QString &szBuffer)
+
+ {
+
+#ifdef COMPILE_GET_INTERFACE_ADDRESS
+
+ struct sockaddr *sa;
+
+ struct sockaddr_in *sin;
+
+ struct ifreq ifr;
+
+ int len = szInterfaceName.length();
+
+ if(len > (IFNAMSIZ - 1))return false; // invalid interface anyway
+
+
+
+ kvi_memmove(ifr.ifr_name,KviQString::toUtf8(szInterfaceName).data(),len + 1);
+
+
+
+ int fd = socket(AF_INET,SOCK_STREAM,0);
+
+ if(fd < 0)return false;
+
+
+
+ if(ioctl(fd,SIOCGIFADDR,&ifr) == -1)return false; // supports only IPV4 ?
+
+
+
+ close(fd);
+
+
+
+ sa = (struct sockaddr *)&(ifr.ifr_addr);
+
+
+
+ if (sa->sa_family != AF_INET) return false;
+
+ sin = (struct sockaddr_in*) sa;
+
+ return binaryIpToStringIp(sin->sin_addr,szBuffer);
+
+ // (this seems to work for AF_INET only anyway)
+
+#else //!COMPILE_GET_INTERFACE_ADDRESS
+
+ return false;
+
+#endif //!COMPILE_GET_INTERFACE_ADDRESS
+
+ }
+
+
+
+ void formatNetworkBandwidthString(QString &szBuffer,unsigned int uBytesPerSec)
+
+ {
+
+ if(uBytesPerSec > (1024 * 1024))
+
+ {
+
+ unsigned int uMB = uBytesPerSec / (1024 * 1024);
+
+ unsigned int uRem = ((uBytesPerSec % (1024 * 1024)) * 100) / (1024 * 1024);
+
+ KviQString::sprintf(szBuffer,"%u.%u%u MB/s",uMB,uRem / 10,uRem % 10);
+
+ return;
+
+ }
+
+ if(uBytesPerSec >= 1024)
+
+ {
+
+ unsigned int uKB = uBytesPerSec / 1024;
+
+ unsigned int uRem = ((uBytesPerSec % 1024) * 100) / 1024;
+
+ KviQString::sprintf(szBuffer,"%u.%u%u KB/s",uKB,uRem / 10,uRem % 10);
+
+ return;
+
+ }
+
+ KviQString::sprintf(szBuffer,"%u B/s",uBytesPerSec);
+
+ }
+
+
+
+
+
+};
+
+
+
+bool kvi_getInterfaceAddress(const char * ifname,QString &buffer)
+
+{
+
+ debug("kvi_getInterfaceAddress is deprecated: use KviNetUtils::getInterfaceAddress");
+
+ QString szRet;
+
+ bool bRes = KviNetUtils::getInterfaceAddress(QString(ifname),szRet);
+
+ buffer = szRet;
+
+ return bRes;
+
+}
+
+
+
+bool kvi_isRoutableIpString(const char * ipstring)
+
+{
+
+ struct in_addr a;
+
+ if(!ipstring)return false;
+
+ kvi_stringIpToBinaryIp(ipstring,&a);
+
+ return kvi_isRoutableIp((const char *)&a);
+
+}
+
+
+
+bool kvi_isRoutableIp(const char * ipaddr)
+
+{
+
+ if(!ipaddr)return false;
+
+ const unsigned char * ip = (const unsigned char *)ipaddr;
+
+ if(ip[0] == 0)return false; // old-style broadcast
+
+ if(ip[0] == 10)return false; // Class A VPN
+
+ if(ip[0] == 127)return false; // loopback
+
+ if((ip[0] == 172) && (ip[1] >= 16) && (ip[1] <= 31))return false; // Class B VPN
+
+ if((ip[0] == 192) && (ip[1] == 168))return false; // Class C VPN
+
+ if((ip[0] == 169) && (ip[1] == 254))return false; // APIPA
+
+ if((ip[0] == 192) && (ip[1] == 0) && (ip[2] == 2))return false; // Class B VPN
+
+ if(ip[0] >= 224)return false; // class D multicast and class E reserved
+
+
+
+ return true;
+
+}
+
+
+
+bool kvi_getLocalHostAddress(QString &buffer)
+
+{
+
+ // This will work only on windoze...
+
+ char buf[1024];
+
+ if(gethostname(buf,1024) != 0)return false;
+
+ struct hostent * h = gethostbyname(buf);
+
+ if(!h)return false;
+
+ QString tmp;
+
+ int i=0;
+
+ while(h->h_addr_list[i])
+
+ {
+
+ if(kvi_binaryIpToStringIp(*((struct in_addr *)(h->h_addr_list[i])),tmp))
+
+ {
+
+ if(kvi_isRoutableIp(h->h_addr_list[i]))
+
+ {
+
+ buffer = tmp;
+
+ return true;
+
+ }
+
+ }
+
+ i++;
+
+ }
+
+ buffer = tmp;
+
+ return true;
+
+}
+
+
+
+
+
+
+
+
+
+
+
+KviSockaddr::KviSockaddr(const char * szIpAddress,kvi_u32_t uPort,bool bIpV6,bool bUdp)
+
+{
+ struct addrinfo hints;
+ kvi_memset((void *)&hints,0,sizeof(hints));
+ hints.ai_flags = AI_NUMERICHOST;
+#ifdef COMPILE_IPV6_SUPPORT
+ hints.ai_family = bIpV6 ? PF_INET6 : PF_INET;
+#else
+ hints.ai_family = PF_INET;
+#endif
+
+ hints.ai_socktype = bUdp ? SOCK_DGRAM : SOCK_STREAM;
+
+ hints.ai_protocol = 0;
+ m_pData = 0;
+ KviStr szPort(KviStr::Format,"%u",uPort);
+ getaddrinfo(szIpAddress,szPort.ptr(),&hints,(struct addrinfo **)&m_pData);
+
+}
+
+
+KviSockaddr::KviSockaddr(kvi_u32_t uPort,bool bIpV6,bool bUdp) // passive sockaddr
+
+{
+ struct addrinfo hints;
+ kvi_memset((void *)&hints,0,sizeof(hints));
+ hints.ai_flags = AI_NUMERICHOST | AI_PASSIVE;
+#ifdef COMPILE_IPV6_SUPPORT
+ hints.ai_family = bIpV6 ? PF_INET6 : PF_INET;
+#else
+ hints.ai_family = PF_INET;
+#endif
+ hints.ai_socktype = bUdp ? SOCK_DGRAM : SOCK_STREAM;
+ hints.ai_protocol = 0;
+ m_pData = 0;
+ KviStr szPort(KviStr::Format,"%u",uPort);
+ getaddrinfo(0,szPort.ptr(),&hints,(struct addrinfo **)&m_pData);
+
+}
+
+
+
+KviSockaddr::~KviSockaddr()
+
+{
+
+ if(m_pData)
+
+ {
+
+ freeaddrinfo((struct addrinfo *)m_pData);
+
+ m_pData = 0;
+
+ }
+
+}
+
+
+
+struct sockaddr * KviSockaddr::socketAddress()
+
+{
+
+ if(!m_pData)return 0;
+
+ return ((struct addrinfo *)m_pData)->ai_addr;
+
+}
+
+
+
+size_t KviSockaddr::addressLength()
+
+{
+
+ if(!m_pData)return 0;
+
+ return ((struct addrinfo *)m_pData)->ai_addrlen;
+
+}
+
+
+
+int KviSockaddr::addressFamily()
+
+{
+
+ if(!m_pData)return 0;
+
+ return ((struct addrinfo *)m_pData)->ai_family;
+
+}
+
+
+
+bool KviSockaddr::isIpV6()
+
+{
+
+ if(!m_pData)return false;
+
+#ifdef COMPILE_IPV6_SUPPORT
+
+ return false;
+
+#else
+
+ return (addressFamily() == AF_INET6);
+
+#endif
+
+}
+
+
+
+kvi_u32_t KviSockaddr::port()
+
+{
+ if(!m_pData)return 0;
+#ifdef COMPILE_IPV6_SUPPORT
+ switch(((struct addrinfo *)m_pData)->ai_family)
+ {
+ case AF_INET:
+ return ntohs(((struct sockaddr_in *)(((struct addrinfo *)m_pData)->ai_addr))->sin_port);
+ break;
+ case AF_INET6:
+ return ntohs(((struct sockaddr_in6 *)(((struct addrinfo *)m_pData)->ai_addr))->sin6_port);
+ break;
+ }
+ return 0;
+#else
+ return ntohs(((struct sockaddr_in *)(((struct addrinfo *)m_pData)->ai_addr))->sin_port);
+#endif
+
+}
+
+
+
+bool KviSockaddr::getStringAddress(QString &szBuffer)
+
+{
+
+ if(!m_pData)return 0;
+
+#ifdef COMPILE_IPV6_SUPPORT
+
+ switch(((struct addrinfo *)m_pData)->ai_family)
+
+ {
+
+ case AF_INET:
+
+ return kvi_binaryIpToStringIp(((struct sockaddr_in *)(((struct addrinfo *)m_pData)->ai_addr))->sin_addr,szBuffer);
+
+ break;
+
+ case AF_INET6:
+
+ return kvi_binaryIpToStringIp_V6(((struct sockaddr_in6 *)(((struct addrinfo *)m_pData)->ai_addr))->sin6_addr,szBuffer);
+
+ break;
+
+ }
+
+ return false;
+
+#else
+
+ return kvi_binaryIpToStringIp(((struct sockaddr_in *)(((struct addrinfo *)m_pData)->ai_addr))->sin_addr,szBuffer);
+
+#endif
+
+}
+
diff --git a/src/kvilib/net/kvi_netutils.h b/src/kvilib/net/kvi_netutils.h
new file mode 100644
index 00000000..b43326f0
--- /dev/null
+++ b/src/kvilib/net/kvi_netutils.h
@@ -0,0 +1,104 @@
+#ifndef _KVI_NETUTILS_H_
+#define _KVI_NETUTILS_H_
+
+//
+// File : kvi_netutlis.h
+// Creation date : Sun Jun 18 2000 18:37:27 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+#include "kvi_inttypes.h"
+
+#ifdef COMPILE_ON_WINDOWS
+ #include <winsock2.h>
+ #ifdef COMPILE_IPV6_SUPPORT
+ #ifdef WIN2K
+ #include <ws2ip6.h>
+ #else
+ #include <ws2tcpip.h>
+ //#include <tpipv6.h>
+ #define in6_addr in_addr6
+ #endif
+ #endif
+#else
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netinet/in.h> //in_addr
+ #include <arpa/inet.h> //inet_ntoa inet_ntop and inet_pton depend on this one.
+#endif
+
+#include "kvi_string.h"
+
+
+KVILIB_API extern bool kvi_isValidStringIp(const char * szIp);
+KVILIB_API extern bool kvi_stringIpToBinaryIp(const char * szIp,struct in_addr * address);
+KVILIB_API extern bool kvi_binaryIpToStringIp(struct in_addr in,QString &szBuffer);
+
+#ifdef COMPILE_IPV6_SUPPORT
+ KVILIB_API extern bool kvi_isValidStringIp_V6(const char * szIp);
+ KVILIB_API extern bool kvi_stringIpToBinaryIp_V6(const char * szIp,struct in6_addr * address);
+ KVILIB_API extern bool kvi_binaryIpToStringIp_V6(struct in6_addr in,QString &szBuffer);
+#endif
+
+class KVILIB_API KviSockaddr
+{
+public:
+ KviSockaddr(const char * szIpAddress,kvi_u32_t uPort,bool bIpV6,bool bUdp = false);
+ KviSockaddr(kvi_u32_t uPort,bool bIpV6,bool bUdp = false); // passive
+ ~KviSockaddr();
+private:
+ void * m_pData; //addrinfo
+public:
+ struct sockaddr * socketAddress();
+ size_t addressLength();
+ int addressFamily();
+ bool isIpV6();
+ bool getStringAddress(QString &szBuffer);
+ kvi_u32_t port();
+
+};
+
+
+KVILIB_API extern bool kvi_select(int fd,bool * bCanRead,bool * bCanWrite,int iUSecs = 0);
+KVILIB_API extern bool kvi_getInterfaceAddress(const char * ifname,QString &buffer);
+
+// Warning : NOT THREAD SAFE!
+KVILIB_API extern bool kvi_getLocalHostAddress(QString &buffer);
+KVILIB_API extern bool kvi_isRoutableIp(const char * ipaddr);
+KVILIB_API extern bool kvi_isRoutableIpString(const char * ipstring);
+
+namespace KviNetUtils
+{
+ KVILIB_API bool stringIpToBinaryIp(const QString &szStringIp,struct in_addr * address);
+ KVILIB_API bool isValidStringIp(const QString &szStringIp);
+ KVILIB_API bool binaryIpToStringIp(struct in_addr in,QString &szBuffer);
+ KVILIB_API bool getInterfaceAddress(const QString &szInterfaceName,QString &szBuffer);
+#ifdef COMPILE_IPV6_SUPPORT
+ KVILIB_API bool isValidStringIp_V6(const QString &szStringIp);
+ KVILIB_API bool stringIpToBinaryIp_V6(const QString &szStringIp,struct in6_addr * address);
+ KVILIB_API bool binaryIpToStringIp_V6(struct in6_addr in,QString &szBuffer);
+#endif
+ KVILIB_API bool isRoutableIp(const char * ipaddr);
+ KVILIB_API bool isRoutableIpString(const QString &szIpString);
+ KVILIB_API void formatNetworkBandwidthString(QString &szBuffer,unsigned int uBytesPerSec);
+};
+
+
+#endif //!_KVI_NETUTILS_H_
diff --git a/src/kvilib/net/kvi_socket.cpp b/src/kvilib/net/kvi_socket.cpp
new file mode 100644
index 00000000..9bd3de9e
--- /dev/null
+++ b/src/kvilib/net/kvi_socket.cpp
@@ -0,0 +1,31 @@
+//
+// File : kvi_socket.cpp
+// Creation date : Thu Sep 20 03:50:24 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#define _KVI_SOCKET_CPP_
+
+#define __KVILIB__
+
+#include "kvi_socket.h"
+#include "kvi_inttypes.h"
+
+KVILIB_API kvi_u64_t g_uOutgoingTraffic;
+KVILIB_API kvi_u64_t g_uIncomingTraffic;
diff --git a/src/kvilib/net/kvi_socket.h b/src/kvilib/net/kvi_socket.h
new file mode 100644
index 00000000..47d51510
--- /dev/null
+++ b/src/kvilib/net/kvi_socket.h
@@ -0,0 +1,356 @@
+#ifndef _KVI_SOCKET_H_
+#define _KVI_SOCKET_H_
+//=============================================================================
+//
+// File : kvi_socket.h
+// Creation date : Thu Sep 20 03:50:22 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+//=============================================================================
+// Socket stuff abstraction layer
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_sockettype.h" // <--- this includes <winsock2.h> if needed
+
+#include <errno.h>
+
+#include "kvi_inttypes.h"
+
+//#ifndef _KVI_SOCKET_CPP_
+ extern KVILIB_API kvi_u64_t g_uOutgoingTraffic;
+ extern KVILIB_API kvi_u64_t g_uIncomingTraffic;
+//#endif //!_KVI_SOCKET_CPP_
+
+
+
+#ifdef COMPILE_ON_WINDOWS
+
+ #define KVI_INVALID_SOCKET INVALID_SOCKET
+
+#else
+
+ #include <sys/time.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netinet/tcp.h>
+ #include <netinet/in.h>
+ #include <fcntl.h>
+ #include <unistd.h>
+
+ #define KVI_INVALID_SOCKET (-1)
+
+#endif
+
+#ifndef MSG_NOSIGNAL
+ // At least solaris seems to not have it
+ #define MSG_NOSIGNAL 0
+#endif
+
+//#include "kvi_socketcalls.h"
+
+
+//================================================================================================
+// Constants for kvi_socket_create
+//
+
+#define KVI_SOCKET_PF_INET PF_INET
+#define KVI_SOCKET_PF_INET6 PF_INET6
+#define KVI_SOCKET_PF_UNIX PF_UNIX
+
+#define KVI_SOCKET_TYPE_STREAM SOCK_STREAM
+#define KVI_SOCKET_TYPE_DGRAM SOCK_DGRAM
+
+#define KVI_SOCKET_PROTO_TCP 0
+
+//================================================================================================
+// kvi_socket_create
+// kvi_socket_open
+//
+// Open a socket of the specified protocol family , type and protocol
+// You should always use the KVI_SOCKET_* constants as parameters
+// Returns KVI_INVALID_SOCKET if the socket creation has failed.
+// The returned socket is in blocking mode!
+//
+
+#define kvi_socket_open kvi_socket_create
+
+inline kvi_socket_t kvi_socket_create(int pf,int type,int proto)
+{
+ return (kvi_socket_t)socket(pf,type,proto);
+};
+
+//================================================================================================
+// kvi_socket_isValid
+//
+// Check if a socket is valid or not
+//
+
+inline void kvi_socket_flushTrafficCounters()
+{
+ g_uOutgoingTraffic = 0;
+ g_uIncomingTraffic = 0;
+}
+
+inline bool kvi_socket_isValid(kvi_socket_t sock)
+{
+ return (sock != ((kvi_socket_t)(KVI_INVALID_SOCKET)));
+}
+
+//================================================================================================
+// kvi_socket_destroy
+// kvi_socket_close
+//
+// Close a socket...that's all :)
+//
+
+#define kvi_socket_close kvi_socket_destroy
+
+inline void kvi_socket_destroy(kvi_socket_t sock)
+{
+#ifdef COMPILE_ON_WINDOWS
+ closesocket(sock);
+#else
+ close(sock);
+#endif
+};
+
+//================================================================================================
+// kvi_socket_setNonBlocking
+//
+// Sets the socket in nonBlocking mode. Obviously returns false in case of failure
+//
+
+inline bool kvi_socket_setNonBlocking(kvi_socket_t sock)
+{
+#ifdef COMPILE_ON_WINDOWS
+ unsigned long arg = 1;
+ return (ioctlsocket(sock,FIONBIO,(unsigned long FAR *)&arg) == 0);
+#else
+ return (fcntl(sock,F_SETFL,O_NONBLOCK) == 0);
+#endif
+};
+
+//================================================================================================
+// kvi_socket_bind
+//
+// Standard bind() call on the socket. Returns false in case of failure
+//
+
+inline bool kvi_socket_bind(kvi_socket_t sock,const struct sockaddr * sa,int salen)
+{
+ return (::bind(sock,sa,salen) == 0);
+};
+
+//================================================================================================
+// kvi_socket_connect
+//
+// Starts a connection to the specified remote address
+// returns false if the connection can not be started.
+// You might take a look at kvi_socket_errno() then.
+//
+
+inline bool kvi_socket_connect(kvi_socket_t sock,const struct sockaddr *sa,int salen)
+{
+#ifdef COMPILE_ON_WINDOWS
+ return (WSAConnect(sock,sa,salen,0,0,0,0) == 0);
+#else
+ return (::connect(sock,sa,salen) == 0);
+#endif
+};
+
+inline bool kvi_socket_recoverableConnectError(int err)
+{
+#ifdef COMPILE_ON_WINDOWS
+ return ((err == WSAEINPROGRESS) || (err == WSAEWOULDBLOCK));
+#else
+ return (err == EINPROGRESS);
+#endif
+};
+
+inline bool kvi_socket_recoverableError(int err)
+{
+#ifdef COMPILE_ON_WINDOWS
+ return ((err == WSAEWOULDBLOCK) || (err == EINTR) || (err == EAGAIN));
+#else
+ return ((err == EINTR) || (err = EAGAIN));
+#endif
+}
+
+//================================================================================================
+// kvi_socket_accept
+//
+// Standard accept() call. Returns KVI_INVALID_SOCKET in case of failure
+// You should check kvi_socket_errno() then.
+//
+
+inline kvi_socket_t kvi_socket_accept(kvi_socket_t sock,struct sockaddr *sa,int * salen)
+{
+#ifdef COMPILE_ON_WINDOWS
+ return (kvi_socket_t)::accept(sock,sa,salen);
+#else
+ return (kvi_socket_t)::accept(sock,sa,(socklen_t *)salen);
+#endif
+};
+
+//================================================================================================
+// kvi_socket_listen
+//
+// Standard listen() call. Returns false in case of failure
+// You should check kvi_socket_errno() then.
+//
+
+inline bool kvi_socket_listen(kvi_socket_t sock,int backlog)
+{
+ return (::listen(sock,backlog) == 0);
+};
+
+//================================================================================================
+// kvi_socket_select
+//
+// Standard select() call. This is complex so here is a mini-reminder:
+// nhpo is the number of the highest file descriptor in the sets plus one!
+// Returns the number of sockets with data available (or space available)
+// or something that is less than 0 in case of error. You should check kvi_socket_errno() then.
+//
+
+inline int kvi_socket_select(int nhpo,fd_set *r,fd_set *w,fd_set *e,struct timeval * t)
+{
+ return ::select(nhpo,r,w,e,t);
+};
+
+//================================================================================================
+// kvi_socket_send
+// kvi_socket_write
+//
+// Standard send() call. On UNIX ignores SIGPIPE. Returns the number of bytes sent or
+// -1 in case of failure. You should check kvi_socket_errno() then.
+//
+
+#define kvi_socket_write kvi_socket_send
+
+inline int kvi_socket_send(kvi_socket_t sock,const void * buf,int size)
+{
+ g_uOutgoingTraffic+=size;
+#ifdef COMPILE_ON_WINDOWS
+ return ::send(sock,(const char *)buf,size,0);
+#else
+ return ::send(sock,buf,size,MSG_NOSIGNAL | MSG_DONTWAIT);
+#endif
+};
+
+//================================================================================================
+// kvi_socket_recv
+// kvi_socket_read
+//
+// Standard read() call. On UNIX ignores SIGPIPE. Returns the number of bytes readed or
+// -1 in case of failure. You should check kvi_socket_errno() then.
+//
+
+#define kvi_socket_read kvi_socket_recv
+
+inline int kvi_socket_recv(kvi_socket_t sock,void * buf,int maxlen)
+{
+ int iReceived;
+#ifdef COMPILE_ON_WINDOWS
+ iReceived = ::recv(sock,(char *)buf,maxlen,0);
+#else
+ iReceived = ::recv(sock,buf,maxlen,MSG_NOSIGNAL);
+#endif
+ g_uIncomingTraffic+=iReceived;
+ return iReceived;
+};
+
+//================================================================================================
+// kvi_socket_getsockopt
+//
+// Standard getsockopt() call. Returns false in case of failure.
+// You should check kvi_socket_errno() then.
+//
+
+inline bool kvi_socket_getsockopt(kvi_socket_t sock,int level,int optname,void *optval,int *optlen)
+{
+#ifdef COMPILE_ON_WINDOWS
+ return (::getsockopt(sock,level,optname,(char FAR *)optval,optlen) == 0);
+#else
+ return (::getsockopt(sock,level,optname,optval,(socklen_t *)optlen) == 0);
+#endif
+}
+
+//================================================================================================
+// kvi_socket_setsockopt
+//
+// Standard setsockopt() call. Returns false in case of failure.
+// You should check kvi_socket_errno() then.
+//
+
+inline bool kvi_socket_setsockopt(kvi_socket_t sock,int level,int optname,const void *optval,int optlen)
+{
+#ifdef COMPILE_ON_WINDOWS
+ return (::setsockopt(sock,level,optname,(char FAR *)optval,optlen) == 0);
+#else
+ return (::setsockopt(sock,level,optname,optval,optlen) == 0);
+#endif
+}
+
+
+//================================================================================================
+// kvi_socket_disableNagle
+//
+// Disables the nagle algorithm (sets TCP_NODELAY)
+//
+
+/*
+ unused for now
+inline bool kvi_socket_disableNagle(kvi_socket_t sock)
+{
+ int opt = 1;
+ return kvi_socket_setsockopt(sock,IPPROTO_TCP,TCP_NODELAY,&opt,sizeof(opt));
+};
+*/
+
+//================================================================================================
+// kvi_socket_getsockname
+//
+// Standard getsockname() call. Returns false in case of failure.
+// You should check kvi_socket_errno() then.
+//
+
+inline bool kvi_socket_getsockname(kvi_socket_t sock,struct sockaddr * addr,int * addrlen)
+{
+#ifdef COMPILE_ON_WINDOWS
+ return (::getsockname(sock,addr,addrlen) == 0);
+#else
+ return (::getsockname(sock,addr,(socklen_t *)addrlen) == 0);
+#endif
+}
+
+inline int kvi_socket_error()
+{
+#ifdef COMPILE_ON_WINDOWS
+ return WSAGetLastError();
+#else
+ return errno;
+#endif
+}
+
+
+#endif //_KVI_SOCKET_H_
diff --git a/src/kvilib/net/kvi_sockettype.h b/src/kvilib/net/kvi_sockettype.h
new file mode 100644
index 00000000..c8a45743
--- /dev/null
+++ b/src/kvilib/net/kvi_sockettype.h
@@ -0,0 +1,45 @@
+#ifndef _KVI_SOCKETTYPE_H_
+#define _KVI_SOCKETTYPE_H_
+//=============================================================================
+//
+// File : kvi_sockettype.h
+// Creation date : Thu Sep 20 05:41:46 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+//=============================================================================
+// Socket stuff abstraction layer
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_ON_WINDOWS
+
+ #include <winsock2.h>
+
+ typedef SOCKET kvi_socket_t;
+
+#else
+
+ typedef int kvi_socket_t;
+
+#endif
+
+#endif //_KVI_SOCKETTYPE_H_
diff --git a/src/kvilib/net/kvi_ssl.cpp b/src/kvilib/net/kvi_ssl.cpp
new file mode 100644
index 00000000..6748e062
--- /dev/null
+++ b/src/kvilib/net/kvi_ssl.cpp
@@ -0,0 +1,687 @@
+//=============================================================================
+//
+// File : kvi_ssl.cpp
+// Creation date : Mon May 27 2002 21:36:12 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+
+
+#include "kvi_ssl.h"
+#include "kvi_locale.h"
+
+#ifdef COMPILE_SSL_SUPPORT
+
+#include "kvi_thread.h"
+#include "kvi_memmove.h"
+#include "kvi_malloc.h"
+
+#include <openssl/asn1.h>
+#include <openssl/err.h>
+#include <openssl/dh.h>
+
+#include <stdio.h>
+
+static bool g_bSSLInitialized = false;
+static KviMutex * g_pSSLMutex = 0;
+
+
+static inline void my_ssl_lock()
+{
+ g_pSSLMutex->lock();
+}
+
+static inline void my_ssl_unlock()
+{
+ g_pSSLMutex->unlock();
+}
+
+
+// THIS PART OF OpenSSL SUCKS
+
+static DH * dh_512 = 0;
+static DH * dh_1024 = 0;
+static DH * dh_2048 = 0;
+static DH * dh_4096 = 0;
+
+static unsigned char dh512_p[]={
+ 0x90,0x86,0xDD,0x06,0xE8,0x0F,0x10,0x86,0xF0,0x91,0xC5,0x55,
+ 0x4D,0x6B,0xAF,0x69,0x4F,0x01,0xED,0xF9,0x57,0x8F,0x3B,0xB8,
+ 0x9C,0x87,0xAE,0x85,0xC1,0xBF,0x57,0xA5,0xD5,0xBA,0x81,0x24,
+ 0xE7,0x99,0xE3,0xF6,0xCD,0xB4,0x41,0xB7,0x7F,0x6E,0x7B,0xB1,
+ 0xD2,0xF3,0xE9,0x0F,0xB9,0x0E,0x4D,0xEB,0x9D,0xD4,0xA9,0xE5,
+ 0x03,0x67,0xA7,0x27
+};
+static unsigned char dh512_g[]={ 0x05 };
+
+static unsigned char dh1024_p[]={
+ 0xA5,0x4C,0xB9,0xB9,0xC4,0x35,0x88,0x68,0x9B,0x79,0x48,0x6C,
+ 0x21,0xA7,0x8E,0xE2,0x9C,0xAF,0x2F,0x04,0xBF,0x45,0xBC,0xF5,
+ 0xAB,0x35,0x86,0xC8,0xBB,0x9B,0x75,0x18,0x7C,0x9B,0xAB,0xE8,
+ 0x52,0x7F,0x57,0x3E,0xD8,0x65,0x7D,0x2B,0xE1,0x6D,0x3D,0xA5,
+ 0x32,0xE8,0xA0,0x2B,0x7A,0x58,0x6B,0x47,0x16,0x4E,0xB1,0xFC,
+ 0x09,0xB7,0x7C,0xC6,0xE9,0x6E,0xC7,0xC7,0xA1,0x42,0x0F,0x4B,
+ 0x43,0xFB,0x58,0xBA,0xC7,0x66,0xD6,0xCA,0x6B,0xC7,0x45,0x7C,
+ 0x99,0xE4,0x46,0x02,0x93,0x3F,0x28,0xD2,0xCE,0x0C,0x8A,0xDD,
+ 0x6A,0x22,0x2E,0xA9,0x9A,0xCA,0x16,0x48,0x4E,0x67,0x4C,0xE9,
+ 0xC8,0x54,0xCD,0x18,0xC9,0xF3,0x30,0x3A,0x74,0xAB,0xF9,0xAF,
+ 0xE4,0xA4,0x0D,0x56,0x62,0x28,0x07,0xBF
+};
+static unsigned char dh1024_g[]={ 0x05 };
+
+static unsigned char dh2048_p[]={
+ 0xBF,0x67,0x7B,0x79,0xA5,0x22,0xD3,0xB5,0x0C,0x13,0xE6,0x92,
+ 0x54,0xFD,0x64,0xBF,0x57,0x25,0xBD,0x02,0x7C,0xFD,0x72,0x97,
+ 0x82,0xA4,0xA6,0x0A,0xB9,0xE6,0x4B,0xFA,0xBD,0xFA,0x71,0x8A,
+ 0x2E,0x36,0xF9,0x03,0x58,0x1B,0xB6,0x3A,0xFD,0x15,0xCC,0x87,
+ 0x5D,0x04,0xF7,0x45,0xE0,0xE2,0x34,0x7F,0x54,0x5F,0x5D,0x14,
+ 0xD3,0xCA,0x3E,0xFD,0x2A,0x92,0x10,0x89,0xA0,0xB0,0xB4,0xE5,
+ 0x80,0x05,0x13,0xBE,0xA3,0xD0,0x42,0x4B,0x98,0x44,0x54,0xB3,
+ 0xE0,0x23,0x26,0xF5,0x6B,0x0E,0x4D,0x2A,0x81,0xB2,0x8A,0x06,
+ 0xC8,0x00,0x9E,0xAB,0x1B,0x77,0xDC,0x87,0x9C,0x6C,0xD5,0xEE,
+ 0xB4,0xB4,0xDD,0xDA,0x3F,0x40,0xA3,0xFA,0xC1,0x1E,0xC0,0xA2,
+ 0x9E,0xB8,0xAC,0x31,0xE8,0x12,0x93,0x9C,0x71,0xF6,0xE7,0xF0,
+ 0x65,0x7F,0xA5,0x20,0xF7,0x49,0x3D,0xD6,0xF9,0xD3,0xF0,0x3F,
+ 0xB3,0xF0,0xD0,0x23,0x22,0x82,0xA5,0xDD,0xFB,0xD9,0x9C,0x7D,
+ 0xE7,0xA0,0x78,0xE8,0xF9,0x02,0x0C,0x2F,0x1D,0x52,0xC7,0x61,
+ 0xED,0xA0,0xC9,0x06,0x14,0xDF,0xE7,0xB1,0x1E,0x50,0x98,0x4F,
+ 0x10,0xB9,0x87,0x4C,0x1C,0x9C,0xB3,0xD2,0x98,0x23,0x7C,0x47,
+ 0xD2,0x3C,0xC5,0x29,0x65,0xC5,0x67,0x4E,0xC0,0x76,0x0F,0x43,
+ 0x27,0x28,0x89,0x69,0x30,0x7D,0x04,0xFD,0xF7,0x89,0xE5,0xD6,
+ 0xE6,0x97,0x7D,0xBB,0x54,0x5F,0xB7,0x94,0x1D,0xBC,0x82,0xAB,
+ 0x9A,0xF5,0x0A,0x0C,0x89,0x68,0xE7,0x0A,0x8C,0x2D,0x0D,0x82,
+ 0x44,0xA7,0xB8,0xF9,0x0B,0x8E,0xCB,0xA4,0x6A,0xA7,0xEC,0x5F,
+ 0x0A,0xF8,0x5F,0xE7
+};
+static unsigned char dh2048_g[]={ 0x05 };
+
+static unsigned char dh4096_p[]={
+ 0xFA,0x14,0x72,0x52,0xC1,0x4D,0xE1,0x5A,0x49,0xD4,0xEF,0x09,
+ 0x2D,0xC0,0xA8,0xFD,0x55,0xAB,0xD7,0xD9,0x37,0x04,0x28,0x09,
+ 0xE2,0xE9,0x3E,0x77,0xE2,0xA1,0x7A,0x18,0xDD,0x46,0xA3,0x43,
+ 0x37,0x23,0x90,0x97,0xF3,0x0E,0xC9,0x03,0x50,0x7D,0x65,0xCF,
+ 0x78,0x62,0xA6,0x3A,0x62,0x22,0x83,0xA1,0x2F,0xFE,0x79,0xBA,
+ 0x35,0xFF,0x59,0xD8,0x1D,0x61,0xDD,0x1E,0x21,0x13,0x17,0xFE,
+ 0xCD,0x38,0x87,0x9E,0xF5,0x4F,0x79,0x10,0x61,0x8D,0xD4,0x22,
+ 0xF3,0x5A,0xED,0x5D,0xEA,0x21,0xE9,0x33,0x6B,0x48,0x12,0x0A,
+ 0x20,0x77,0xD4,0x25,0x60,0x61,0xDE,0xF6,0xB4,0x4F,0x1C,0x63,
+ 0x40,0x8B,0x3A,0x21,0x93,0x8B,0x79,0x53,0x51,0x2C,0xCA,0xB3,
+ 0x7B,0x29,0x56,0xA8,0xC7,0xF8,0xF4,0x7B,0x08,0x5E,0xA6,0xDC,
+ 0xA2,0x45,0x12,0x56,0xDD,0x41,0x92,0xF2,0xDD,0x5B,0x8F,0x23,
+ 0xF0,0xF3,0xEF,0xE4,0x3B,0x0A,0x44,0xDD,0xED,0x96,0x84,0xF1,
+ 0xA8,0x32,0x46,0xA3,0xDB,0x4A,0xBE,0x3D,0x45,0xBA,0x4E,0xF8,
+ 0x03,0xE5,0xDD,0x6B,0x59,0x0D,0x84,0x1E,0xCA,0x16,0x5A,0x8C,
+ 0xC8,0xDF,0x7C,0x54,0x44,0xC4,0x27,0xA7,0x3B,0x2A,0x97,0xCE,
+ 0xA3,0x7D,0x26,0x9C,0xAD,0xF4,0xC2,0xAC,0x37,0x4B,0xC3,0xAD,
+ 0x68,0x84,0x7F,0x99,0xA6,0x17,0xEF,0x6B,0x46,0x3A,0x7A,0x36,
+ 0x7A,0x11,0x43,0x92,0xAD,0xE9,0x9C,0xFB,0x44,0x6C,0x3D,0x82,
+ 0x49,0xCC,0x5C,0x6A,0x52,0x42,0xF8,0x42,0xFB,0x44,0xF9,0x39,
+ 0x73,0xFB,0x60,0x79,0x3B,0xC2,0x9E,0x0B,0xDC,0xD4,0xA6,0x67,
+ 0xF7,0x66,0x3F,0xFC,0x42,0x3B,0x1B,0xDB,0x4F,0x66,0xDC,0xA5,
+ 0x8F,0x66,0xF9,0xEA,0xC1,0xED,0x31,0xFB,0x48,0xA1,0x82,0x7D,
+ 0xF8,0xE0,0xCC,0xB1,0xC7,0x03,0xE4,0xF8,0xB3,0xFE,0xB7,0xA3,
+ 0x13,0x73,0xA6,0x7B,0xC1,0x0E,0x39,0xC7,0x94,0x48,0x26,0x00,
+ 0x85,0x79,0xFC,0x6F,0x7A,0xAF,0xC5,0x52,0x35,0x75,0xD7,0x75,
+ 0xA4,0x40,0xFA,0x14,0x74,0x61,0x16,0xF2,0xEB,0x67,0x11,0x6F,
+ 0x04,0x43,0x3D,0x11,0x14,0x4C,0xA7,0x94,0x2A,0x39,0xA1,0xC9,
+ 0x90,0xCF,0x83,0xC6,0xFF,0x02,0x8F,0xA3,0x2A,0xAC,0x26,0xDF,
+ 0x0B,0x8B,0xBE,0x64,0x4A,0xF1,0xA1,0xDC,0xEE,0xBA,0xC8,0x03,
+ 0x82,0xF6,0x62,0x2C,0x5D,0xB6,0xBB,0x13,0x19,0x6E,0x86,0xC5,
+ 0x5B,0x2B,0x5E,0x3A,0xF3,0xB3,0x28,0x6B,0x70,0x71,0x3A,0x8E,
+ 0xFF,0x5C,0x15,0xE6,0x02,0xA4,0xCE,0xED,0x59,0x56,0xCC,0x15,
+ 0x51,0x07,0x79,0x1A,0x0F,0x25,0x26,0x27,0x30,0xA9,0x15,0xB2,
+ 0xC8,0xD4,0x5C,0xCC,0x30,0xE8,0x1B,0xD8,0xD5,0x0F,0x19,0xA8,
+ 0x80,0xA4,0xC7,0x01,0xAA,0x8B,0xBA,0x53,0xBB,0x47,0xC2,0x1F,
+ 0x6B,0x54,0xB0,0x17,0x60,0xED,0x79,0x21,0x95,0xB6,0x05,0x84,
+ 0x37,0xC8,0x03,0xA4,0xDD,0xD1,0x06,0x69,0x8F,0x4C,0x39,0xE0,
+ 0xC8,0x5D,0x83,0x1D,0xBE,0x6A,0x9A,0x99,0xF3,0x9F,0x0B,0x45,
+ 0x29,0xD4,0xCB,0x29,0x66,0xEE,0x1E,0x7E,0x3D,0xD7,0x13,0x4E,
+ 0xDB,0x90,0x90,0x58,0xCB,0x5E,0x9B,0xCD,0x2E,0x2B,0x0F,0xA9,
+ 0x4E,0x78,0xAC,0x05,0x11,0x7F,0xE3,0x9E,0x27,0xD4,0x99,0xE1,
+ 0xB9,0xBD,0x78,0xE1,0x84,0x41,0xA0,0xDF
+};
+static unsigned char dh4096_g[]={ 0x02 };
+
+static DH * my_get_dh(int keylength)
+{
+ DH * dh = 0;
+ unsigned char * p = 0;
+ unsigned char * g = 0;
+ int sp = 0;
+ int sg = 0;
+ switch(keylength)
+ {
+ case 512:
+ dh = dh_512;
+ p = dh512_p;
+ g = dh512_g;
+ sp = sizeof(dh512_p);
+ sg = sizeof(dh512_g);
+ break;
+ case 1024:
+ dh = dh_1024;
+ p = dh1024_p;
+ g = dh1024_g;
+ sp = sizeof(dh1024_p);
+ sg = sizeof(dh1024_g);
+ break;
+ case 2048:
+ dh = dh_2048;
+ p = dh2048_p;
+ g = dh2048_g;
+ sp = sizeof(dh2048_p);
+ sg = sizeof(dh2048_g);
+ break;
+ case 4096:
+ dh = dh_4096;
+ p = dh4096_p;
+ g = dh4096_g;
+ sp = sizeof(dh4096_p);
+ sg = sizeof(dh4096_g);
+ break;
+ default:
+ // What the hell do you want from me ?
+ debug("OpenSSL is asking for a DH param with keylen %d: no way :D",keylength);
+ break;
+
+ }
+
+ if(dh)return dh;
+ dh = DH_new();
+ if(!dh)return 0;
+ dh->p=BN_bin2bn(p,sp,0);
+ dh->g=BN_bin2bn(g,sg,0);
+ if((dh->p == 0) || (dh->g == 0))
+ {
+ DH_free(dh);
+ return 0;
+ }
+ return dh;
+}
+
+DH * my_ugly_dh_callback(SSL *s, int is_export, int keylength)
+{
+ my_ssl_lock();
+ DH *dh = my_get_dh(keylength);
+ my_ssl_unlock();
+ return dh;
+}
+
+void KviSSL::globalInit()
+{
+ if(g_pSSLMutex)return;
+ g_pSSLMutex = new KviMutex();
+}
+
+void KviSSL::globalDestroy()
+{
+ if(!g_pSSLMutex)return;
+ if(dh_512)DH_free(dh_512);
+ if(dh_1024)DH_free(dh_1024);
+ if(dh_2048)DH_free(dh_2048);
+ if(dh_4096)DH_free(dh_4096);
+ delete g_pSSLMutex;
+ g_pSSLMutex = 0;
+}
+
+KviSSL::KviSSL()
+{
+ my_ssl_lock();
+ if(!g_bSSLInitialized)
+ {
+ // FIXME: this should be done only if SSL is really needed
+ SSL_library_init();
+ SSL_load_error_strings();
+ g_bSSLInitialized = true;
+ }
+ my_ssl_unlock();
+ m_pSSL = 0;
+ m_pSSLCtx = 0;
+}
+
+KviSSL::~KviSSL()
+{
+ shutdown();
+}
+
+#ifdef COMPILE_ON_WINDOWS
+
+ // On windows we need to override new and delete operators
+ // to ensure that always the right new/delete pair is called for an object instance
+ // This bug is present in all the classes exported by a module that
+ // can be instantiated/destroyed from external modules.
+ // (this is a well known bug described in Q122675 of MSDN)
+
+ void * KviSSL::operator new(size_t tSize)
+ {
+ return kvi_malloc(tSize);
+ }
+
+ void KviSSL::operator delete(void * p)
+ {
+ kvi_free(p);
+ }
+
+#endif
+
+void KviSSL::shutdown()
+{
+ if(m_pSSL)
+ {
+ // At least attempt to shutdown the connection gracefully
+ SSL_shutdown(m_pSSL);
+ SSL_free(m_pSSL);
+ m_pSSL = 0;
+ }
+ if(m_pSSLCtx)
+ {
+ SSL_CTX_free(m_pSSLCtx);
+ m_pSSLCtx = 0;
+ }
+}
+
+
+bool KviSSL::initContext(Method m)
+{
+ if(m_pSSL)return false;
+ m_pSSLCtx = SSL_CTX_new(m == Client ? SSLv23_client_method() : SSLv23_server_method());
+ if(!m_pSSLCtx)return false;
+ // FIXME: this should be configurable ?
+ SSL_CTX_set_cipher_list(m_pSSLCtx,"ALL:eNULL");
+ SSL_CTX_set_tmp_dh_callback(m_pSSLCtx,my_ugly_dh_callback);
+ return true;
+}
+
+bool KviSSL::initSocket(kvi_socket_t fd)
+{
+ if(!m_pSSLCtx)return false;
+ m_pSSL = SSL_new(m_pSSLCtx);
+ if(!m_pSSL)return false;
+ if(!SSL_set_fd(m_pSSL,fd))return false;
+ return true;
+
+}
+
+static int cb(char *buf, int size, int rwflag, void *u)
+{
+ KviStr * p = (KviStr *)u;
+ int len = p->len();
+ if(len >= size)return 0;
+ kvi_memmove(buf,p->ptr(),len + 1);
+// debug("PASS REQYESTED: %s",p->ptr());
+ return len;
+}
+
+KviSSL::Result KviSSL::useCertificateFile(const char * cert,const char * pass)
+{
+ if(!m_pSSLCtx)return NotInitialized;
+ m_szPass = pass;
+ if(m_szPass.len() < 4)m_szPass.append("xxxx");
+ X509 * x509 = 0;
+
+ FILE * f = fopen(cert,"r");
+ if(!f)return FileIoError;
+
+// debug("READING CERTIFICATE %s",cert);
+ if(PEM_read_X509(f,&x509,cb,&m_szPass))
+ {
+ if(!SSL_CTX_use_certificate(m_pSSLCtx,x509))
+ {
+ X509_free(x509);
+ return SSLError;
+ }
+ }
+
+ fclose(f);
+ return Success;
+}
+
+
+KviSSL::Result KviSSL::usePrivateKeyFile(const char * key,const char * pass)
+{
+ if(!m_pSSLCtx)return NotInitialized;
+ m_szPass = pass;
+ if(m_szPass.len() < 4)m_szPass.append("xxxx");
+
+ EVP_PKEY * k = 0;
+
+ FILE * f = fopen(key,"r");
+ if(!f)return FileIoError;
+
+// debug("READING KEY %s",key);
+ if(PEM_read_PrivateKey(f,&k,cb,&m_szPass))
+ {
+ if(!SSL_CTX_use_PrivateKey(m_pSSLCtx,k))
+ {
+ EVP_PKEY_free(k);
+ return SSLError;
+ }
+ }
+
+ fclose(f);
+ return Success;
+}
+
+unsigned long KviSSL::getLastError(bool bPeek)
+{
+ return bPeek ? ERR_peek_error() : ERR_get_error();
+}
+
+bool KviSSL::getLastErrorString(KviStr &buffer,bool bPeek)
+{
+ unsigned long uErr = getLastError(bPeek);
+ if(uErr != 0)
+ {
+ const char * err = ERR_reason_error_string(uErr);
+ buffer = err ? err : "Unknown error";
+ return true;
+ }
+ return false;
+}
+
+KviSSL::Result KviSSL::connect()
+{
+ if(!m_pSSL)return NotInitialized;
+ int ret = SSL_connect(m_pSSL);
+ return connectOrAcceptError(ret);
+}
+
+KviSSL::Result KviSSL::accept()
+{
+ if(!m_pSSL)return NotInitialized;
+ int ret = SSL_accept(m_pSSL);
+ return connectOrAcceptError(ret);
+}
+
+KviSSL::Result KviSSL::connectOrAcceptError(int ret)
+{
+ switch(SSL_get_error(m_pSSL,ret))
+ {
+ case SSL_ERROR_NONE: return Success; break;
+ case SSL_ERROR_WANT_READ: return WantRead; break;
+ case SSL_ERROR_WANT_WRITE: return WantWrite; break;
+ case SSL_ERROR_ZERO_RETURN: return RemoteEndClosedConnection; break;
+ case SSL_ERROR_WANT_X509_LOOKUP: return ObscureError; break;
+ case SSL_ERROR_SYSCALL:
+ {
+ if(getLastError(true) != 0)return SSLError;
+ if(ret == 0)return RemoteEndClosedConnection;
+ return SyscallError;
+ }
+ break;
+ case SSL_ERROR_SSL: return SSLError; break;
+ default: return UnknownError; break;
+ }
+ return UnknownError;
+}
+
+int KviSSL::read(char * buffer,int len)
+{
+// if(!m_pSSL)return -1;
+ return SSL_read(m_pSSL,buffer,len);
+}
+int KviSSL::write(const char * buffer,int len)
+{
+// if(!m_pSSL)return -1;
+ return SSL_write(m_pSSL,buffer,len);
+}
+
+KviSSL::Result KviSSL::getProtocolError(int ret)
+{
+ if(!m_pSSL)return NotInitialized;
+ switch(SSL_get_error(m_pSSL,ret))
+ {
+ case SSL_ERROR_NONE: return Success; break;
+ case SSL_ERROR_WANT_READ: return WantRead; break;
+ case SSL_ERROR_WANT_WRITE: return WantWrite; break;
+ case SSL_ERROR_ZERO_RETURN: return ZeroReturn; break;
+ case SSL_ERROR_WANT_X509_LOOKUP: return ObscureError; break;
+ case SSL_ERROR_SYSCALL: return SyscallError; break;
+ case SSL_ERROR_SSL: return SSLError; break;
+ default: return UnknownError; break;
+ }
+ return UnknownError;
+}
+
+KviSSLCertificate * KviSSL::getPeerCertificate()
+{
+ if(!m_pSSL)return 0;
+ X509 * x509 = SSL_get_peer_certificate(m_pSSL);
+ if(!x509)return 0;
+ return new KviSSLCertificate(x509);
+}
+
+KviSSLCipherInfo * KviSSL::getCurrentCipherInfo()
+{
+ if(!m_pSSL)return 0;
+ SSL_CIPHER * c = SSL_get_current_cipher(m_pSSL);
+ if(!c)return 0;
+ return new KviSSLCipherInfo(c);
+}
+
+
+
+KviSSLCertificate::KviSSLCertificate(X509 * x509)
+{
+ m_pSubject = new KviPointerHashTable<const char *,KviStr>(17);
+ m_pSubject->setAutoDelete(true);
+ m_pIssuer = new KviPointerHashTable<const char *,KviStr>(17);
+ m_pIssuer->setAutoDelete(true);
+ m_pX509 = 0;
+ setX509(x509);
+}
+
+KviSSLCertificate::~KviSSLCertificate()
+{
+ X509_free(m_pX509);
+ delete m_pSubject;
+ delete m_pIssuer;
+}
+
+#ifdef COMPILE_ON_WINDOWS
+
+ // On windows we need to override new and delete operators
+ // to ensure that always the right new/delete pair is called for an object instance
+ // This bug is present in all the classes exported by a module that
+ // can be instantiated/destroyed from external modules.
+ // (this is a well known bug described in Q122675 of MSDN)
+
+ void * KviSSLCertificate::operator new(size_t tSize)
+ {
+ return kvi_malloc(tSize);
+ }
+
+ void KviSSLCertificate::operator delete(void * p)
+ {
+ kvi_free(p);
+ }
+
+#endif
+
+void KviSSLCertificate::setX509(X509 * x509)
+{
+ if(m_pX509)X509_free(m_pX509);
+ m_pX509 = x509;
+ m_iVersion = X509_get_version(x509);
+ extractSubject();
+ extractIssuer();
+ extractPubKeyInfo();
+ extractSerialNumber();
+ extractSignature();
+}
+
+void KviSSLCertificate::extractSubject()
+{
+ char buffer[1024];
+ char * t = X509_NAME_oneline(X509_get_subject_name(m_pX509),buffer,1024);
+ if (!t)return;
+ m_pSubject->clear();
+ splitX509String(m_pSubject,t);
+}
+
+void KviSSLCertificate::extractIssuer()
+{
+ char buffer[1024];
+ char * t = X509_NAME_oneline(X509_get_issuer_name(m_pX509),buffer,1024);
+ if (!t)return;
+ m_pIssuer->clear();
+ splitX509String(m_pIssuer,t);
+}
+
+void KviSSLCertificate::splitX509String(KviPointerHashTable<const char *,KviStr> * dict,const char * t)
+{
+ KviStr buf = t;
+ int cnt;
+ KviStr ** arr = buf.splitToArray('/',50,&cnt);
+ if(arr)
+ {
+ if(cnt > 0)
+ {
+ for(int i=0;i<cnt;i++)
+ {
+ int idx = arr[i]->findFirstIdx('=');
+ if(idx != -1)
+ {
+ KviStr szTok = arr[i]->left(idx);
+ arr[i]->cutLeft(idx + 1);
+ if(szTok.hasData() && arr[i]->hasData())
+ {
+ dict->replace(szTok.ptr(),new KviStr(arr[i]->ptr()));
+ }
+ }
+ }
+ }
+
+ KviStr::freeArray(arr);
+ }
+}
+
+
+const char * KviSSLCertificate::dictEntry(KviPointerHashTable<const char *,KviStr> * dict,const char * entry)
+{
+ KviStr * t = dict->find(entry);
+ if(!t)return __tr("Unknown");
+ return t->ptr();
+}
+
+
+/*
+void KviSSLCertificate::getPKeyType(int type,KviStr &buffer)
+{
+ switch(type)
+ {
+#ifndef NO_RSA
+ case EVP_PKEY_RSA: buffer = "RSA"; break;
+#endif
+#ifndef NO_DSA
+ case EVP_PKEY_DSA: buffer = "DSA"; break;
+#endif
+#ifndef NO_DH
+ case EVP_PKEY_DH: buffer = "DH"; break;
+#endif
+ case EVP_PKEY_NONE: buffer = "NONE"; break;
+ }
+}
+*/
+
+void KviSSLCertificate::extractPubKeyInfo()
+{
+ EVP_PKEY *p = X509_get_pubkey(m_pX509);
+ if(p)
+ {
+ m_iPubKeyBits = EVP_PKEY_bits(p);
+ m_szPubKeyType = (p->type == NID_undef) ? __tr("Unknown") : OBJ_nid2ln(p->type);
+// getPKeyType(p->type,m_szPubKeyType);
+ } else {
+ m_iPubKeyBits = 0;
+ m_szPubKeyType = "None";
+ }
+
+}
+
+void KviSSLCertificate::extractSerialNumber()
+{
+ ASN1_INTEGER * i = X509_get_serialNumber(m_pX509);
+ if(i)m_iSerialNumber = ASN1_INTEGER_get(i);
+ else m_iSerialNumber = -1;
+}
+
+void KviSSLCertificate::extractSignature()
+{
+ static char hexdigits[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
+
+ //getPKeyType(X509_get_signature_type(m_pX509),m_szSignatureType);
+
+ int i = OBJ_obj2nid(m_pX509->sig_alg->algorithm);
+ m_szSignatureType = (i == NID_undef) ? __tr("Unknown") : OBJ_nid2ln(i);
+
+ m_szSignatureContents = "";
+
+ for(i = 0;i < m_pX509->signature->length;i++)
+ {
+ if(m_szSignatureContents.hasData())m_szSignatureContents.append(":");
+ m_szSignatureContents.append(hexdigits[(m_pX509->signature->data[i] & 0xf0) >> 4]);
+ m_szSignatureContents.append(hexdigits[(m_pX509->signature->data[i] & 0x0f)]);
+ }
+}
+
+/*
+const char * KviSSLCertificate::verify()
+{
+
+}
+*/
+
+
+KviSSLCipherInfo::KviSSLCipherInfo(SSL_CIPHER * c)
+{
+ m_szVersion = SSL_CIPHER_get_version(c);
+ m_iNumBitsUsed = SSL_CIPHER_get_bits(c,&m_iNumBits);
+ m_szName = SSL_CIPHER_get_name(c);
+ char buf[1024];
+ m_szDescription = SSL_CIPHER_description(c,buf,1024);
+}
+
+KviSSLCipherInfo::~KviSSLCipherInfo()
+{
+}
+
+#ifdef COMPILE_ON_WINDOWS
+
+ // On windows we need to override new and delete operators
+ // to ensure that always the right new/delete pair is called for an object instance
+ // This bug is present in all the classes exported by a module that
+ // can be instantiated/destroyed from external modules.
+ // (this is a well known bug described in Q122675 of MSDN)
+
+ void * KviSSLCipherInfo::operator new(size_t tSize)
+ {
+ return kvi_malloc(tSize);
+ }
+
+ void KviSSLCipherInfo::operator delete(void * p)
+ {
+ kvi_free(p);
+ }
+
+#endif
+
+#endif //COMPILE_SSL_SUPPORT
diff --git a/src/kvilib/net/kvi_ssl.h b/src/kvilib/net/kvi_ssl.h
new file mode 100644
index 00000000..5547ecbb
--- /dev/null
+++ b/src/kvilib/net/kvi_ssl.h
@@ -0,0 +1,180 @@
+#ifndef _KVI_SSL_H_
+#define _KVI_SSL_H_
+//
+// File : kvi_ssl.h
+// Creation date : Mon May 27 2002 21:36:12 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_SSL_SUPPORT
+
+#include "kvi_string.h"
+#include "kvi_sockettype.h"
+
+#include "kvi_pointerhashtable.h"
+
+#include <openssl/ssl.h>
+
+
+class KVILIB_API KviSSLCertificate
+{
+public:
+ KviSSLCertificate(X509 * x509);
+ ~KviSSLCertificate();
+protected:
+ X509 * m_pX509;
+ KviPointerHashTable<const char *,KviStr> * m_pSubject;
+ KviPointerHashTable<const char *,KviStr> * m_pIssuer;
+ int m_iPubKeyBits;
+ KviStr m_szPubKeyType;
+ int m_iSerialNumber;
+ int m_iVersion;
+ KviStr m_szSignatureType;
+ KviStr m_szSignatureContents;
+private:
+ void extractSubject();
+ void extractIssuer();
+ void extractPubKeyInfo();
+ void extractSerialNumber();
+ void extractSignature();
+ const char * dictEntry(KviPointerHashTable<const char *,KviStr> * dict,const char * entry);
+ void splitX509String(KviPointerHashTable<const char *,KviStr> * dict,const char * t);
+// void getPKeyType(int type,KviStr &buffer);
+public:
+ void setX509(X509 * x509);
+
+ const char * signatureType(){ return m_szSignatureType.ptr(); };
+ const char * signatureContents(){ return m_szSignatureContents.ptr(); };
+
+ const char * subjectCountry(){ return dictEntry(m_pSubject,"C"); };
+ const char * subjectStateOrProvince(){ return dictEntry(m_pSubject,"ST"); };
+ const char * subjectLocality(){ return dictEntry(m_pSubject,"L"); };
+ const char * subjectOrganization(){ return dictEntry(m_pSubject,"O"); };
+ const char * subjectOrganizationalUnit(){ return dictEntry(m_pSubject,"OU"); };
+ const char * subjectCommonName(){ return dictEntry(m_pSubject,"CN"); };
+
+ const char * issuerCountry(){ return dictEntry(m_pIssuer,"C"); };
+ const char * issuerStateOrProvince(){ return dictEntry(m_pIssuer,"ST"); };
+ const char * issuerLocality(){ return dictEntry(m_pIssuer,"L"); };
+ const char * issuerOrganization(){ return dictEntry(m_pIssuer,"O"); };
+ const char * issuerOrganizationalUnit(){ return dictEntry(m_pIssuer,"OU"); };
+ const char * issuerCommonName(){ return dictEntry(m_pIssuer,"CN"); };
+
+ int publicKeyBits(){ return m_iPubKeyBits; };
+ const char * publicKeyType(){ return m_szPubKeyType.ptr(); };
+
+ int serialNumber(){ return m_iSerialNumber; };
+
+ int version(){ return m_iVersion; };
+#ifdef COMPILE_ON_WINDOWS
+ // On windows we need to override new and delete operators
+ // to ensure that always the right new/delete pair is called for an object instance
+ // This bug is present in all the classes exported by a module that
+ // can be instantiated/destroyed from external modules.
+ // (this is a well known bug described in Q122675 of MSDN)
+ void * operator new(size_t tSize);
+ void operator delete(void * p);
+#endif
+};
+
+class KVILIB_API KviSSLCipherInfo
+{
+public:
+ KviSSLCipherInfo(SSL_CIPHER * c);
+ ~KviSSLCipherInfo();
+protected:
+ KviStr m_szVersion;
+ int m_iNumBits;
+ int m_iNumBitsUsed;
+ KviStr m_szName;
+ KviStr m_szDescription;
+public:
+ const char * name(){ return m_szName.ptr(); };
+ const char * description(){ return m_szDescription.ptr(); };
+ int bits(){ return m_iNumBits; };
+ int bitsUsed(){ return m_iNumBitsUsed; };
+ const char * version(){ return m_szVersion.ptr(); };
+#ifdef COMPILE_ON_WINDOWS
+ // On windows we need to override new and delete operators
+ // to ensure that always the right new/delete pair is called for an object instance
+ // This bug is present in all the classes exported by a module that
+ // can be instantiated/destroyed from external modules.
+ // (this is a well known bug described in Q122675 of MSDN)
+ void * operator new(size_t tSize);
+ void operator delete(void * p);
+#endif
+};
+
+#ifdef Success
+ #undef Success
+#endif
+
+
+class KVILIB_API KviSSL
+{
+public:
+ enum Method { Client , Server };
+ enum Result { Success , NotInitialized , WantRead , WantWrite , ZeroReturn , FileIoError ,
+ UnknownError , ObscureError , SSLError , SyscallError , RemoteEndClosedConnection };
+public:
+ KviSSL();
+ ~KviSSL();
+public:
+ SSL * m_pSSL;
+ SSL_CTX * m_pSSLCtx;
+ KviStr m_szPass;
+public:
+ static void globalInit();
+ static void globalDestroy();
+public:
+ bool initSocket(kvi_socket_t fd);
+ bool initContext(KviSSL::Method m);
+ void shutdown();
+ KviSSL::Result connect();
+ KviSSL::Result accept();
+ int read(char * buffer,int len);
+ int write(const char * buffer,int len);
+ // SSL ERRORS
+ unsigned long getLastError(bool bPeek = false);
+ bool getLastErrorString(KviStr &buffer,bool bPeek = false);
+ // Protocol error
+ KviSSL::Result getProtocolError(int ret);
+ KviSSLCertificate * getPeerCertificate();
+ KviSSLCipherInfo * getCurrentCipherInfo();
+ KviSSL::Result useCertificateFile(const char * cert,const char * pass);
+ KviSSL::Result usePrivateKeyFile(const char * key,const char * pass);
+#ifdef COMPILE_ON_WINDOWS
+ // On windows we need to override new and delete operators
+ // to ensure that always the right new/delete pair is called for an object instance
+ // This bug is present in all the classes exported by a module that
+ // can be instantiated/destroyed from external modules.
+ // (this is a well known bug described in Q122675 of MSDN)
+ void * operator new(size_t tSize);
+ void operator delete(void * p);
+#endif
+private:
+ KviSSL::Result connectOrAcceptError(int ret);
+};
+
+
+#endif //COMPILE_SSL_SUPPORT
+
+#endif //_KVI_SSL_H_
diff --git a/src/kvilib/net/kvi_url.cpp b/src/kvilib/net/kvi_url.cpp
new file mode 100644
index 00000000..f980729c
--- /dev/null
+++ b/src/kvilib/net/kvi_url.cpp
@@ -0,0 +1,164 @@
+//
+// File : kvi_url.cpp
+// Creation date : Sat Aug 17 14:09:18 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+#define __KVILIB__
+
+
+#include "kvi_url.h"
+
+KviUrl::KviUrl()
+{
+}
+
+KviUrl::KviUrl(const KviUrl & u)
+{
+ *this = u;
+}
+
+KviUrl::KviUrl(const char * szUrl)
+{
+ m_szUrl = szUrl;
+ parse();
+}
+
+KviUrl::KviUrl(const QString &szUrl)
+{
+ m_szUrl = szUrl;
+ parse();
+}
+
+KviUrl::~KviUrl()
+{
+
+}
+
+void KviUrl::parse()
+{
+ m_szProtocol = "";
+ m_szHost = "";
+ m_szPath = "";
+ m_szUser = "";
+ m_szPass = "";
+
+ m_szUrl.stripWhiteSpace();
+
+ KviStr u = m_szUrl;
+
+ // proto
+
+ kvi_u32_t uDefaultPort = 80;
+
+ int i = u.findFirstIdx(":/");
+ if(i != -1)
+ {
+ // there is a protocol path
+ m_szProtocol = u.left(i);
+ u.cutLeft(i + 2);
+ u.stripLeft('/');
+ u.stripWhiteSpace();
+
+ // fix the default ports
+ if(kvi_strEqualCI(m_szProtocol,"https"))uDefaultPort = 443;
+ else if(kvi_strEqualCI(m_szProtocol,"ftp"))uDefaultPort = 21;
+ } else {
+ // no proto... assume http
+ u.stripLeft('/');
+ m_szProtocol = "http";
+ }
+
+ m_uPort = uDefaultPort;
+
+ // user and pass
+
+ i = u.findFirstIdx('@');
+
+ if(i != -1)
+ {
+ KviStr szUserPass = u.left(i);
+ szUserPass.stripWhiteSpace();
+ u.cutLeft(i + 1);
+
+ i = szUserPass.findFirstIdx(':');
+ if(i != -1)
+ {
+ m_szUser = szUserPass.left(i);
+ szUserPass.cutLeft(i + 1);
+ m_szPass = szUserPass;
+ m_szPass.stripWhiteSpace();
+ } else {
+ m_szUser = szUserPass;
+ }
+ }
+
+ // host
+
+ i = u.findFirstIdx('/');
+ if(i != -1)
+ {
+ KviStr h = u.left(i);
+ u.cutLeft(i + 1);
+ i = h.findFirstIdx(':');
+ if(i != -1)
+ {
+ // has a port part
+ m_szHost = h.left(i);
+ h.cutLeft(i + 1);
+ h.stripWhiteSpace();
+ bool bOk;
+ m_uPort = h.toUInt(&bOk);
+ if(!bOk)m_uPort = uDefaultPort;
+ } else {
+ // no port : assume default
+ m_szHost = h;
+ }
+ m_szPath = u;
+ } else {
+ m_szHost = u;
+ }
+
+ m_szHost.stripWhiteSpace();
+ m_szPath.stripWhiteSpace();
+ if(!m_szPath.firstCharIs('/'))m_szPath.prepend('/');
+}
+
+
+KviUrl & KviUrl::operator=(const char * szUrl)
+{
+ m_szUrl = szUrl;
+ parse();
+ return *this;
+}
+
+KviUrl & KviUrl::operator=(const KviUrl &u)
+{
+ m_szUrl = u.m_szUrl;
+ m_szProtocol = u.m_szProtocol;
+ m_szHost = u.m_szHost;
+ m_szPath = u.m_szPath;
+ m_szUser = u.m_szUser;
+ m_szPass = u.m_szPass;
+ m_uPort = u.m_uPort;
+ return *this;
+}
+
+
diff --git a/src/kvilib/net/kvi_url.h b/src/kvilib/net/kvi_url.h
new file mode 100644
index 00000000..89adeb9f
--- /dev/null
+++ b/src/kvilib/net/kvi_url.h
@@ -0,0 +1,63 @@
+#ifndef _KVI_URL_H_
+#define _KVI_URL_H_
+//
+// File : kvi_url.h
+// Creation date : Sat Aug 17 14:09:16 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_string.h"
+#include "kvi_heapobject.h"
+#include "kvi_inttypes.h"
+
+class KVILIB_API KviUrl : public KviHeapObject
+{
+public:
+ KviUrl();
+ KviUrl(const char * szUrl);
+ KviUrl(const QString &szUrl);
+ KviUrl(const KviUrl &u);
+ ~KviUrl();
+protected:
+ KviStr m_szUrl;
+
+ KviStr m_szProtocol;
+ KviStr m_szHost;
+ KviStr m_szPath;
+ KviStr m_szUser;
+ KviStr m_szPass;
+ kvi_u32_t m_uPort;
+protected:
+ void parse();
+public:
+ const KviStr & url() const { return m_szUrl; };
+ const KviStr & protocol() const { return m_szProtocol; };
+ const KviStr & host() const { return m_szHost; };
+ const KviStr & path() const { return m_szPath; };
+ const KviStr & user() const { return m_szUser; };
+ const KviStr & pass() const { return m_szPass; };
+ kvi_u32_t port() const { return m_uPort; };
+
+ KviUrl & operator = (const char * szUrl);
+ KviUrl & operator = (const KviUrl &u);
+
+};
+
+
+#endif //_KVI_URL_H_
diff --git a/src/kvilib/net/moc_kvi_dns.cpp b/src/kvilib/net/moc_kvi_dns.cpp
new file mode 100644
index 00000000..5b8857a9
--- /dev/null
+++ b/src/kvilib/net/moc_kvi_dns.cpp
@@ -0,0 +1,137 @@
+/****************************************************************************
+** KviDns meta object code from reading C++ file 'kvi_dns.h'
+**
+** Created: Sun Mar 23 20:56:20 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_dns.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+#include <qvariant.h>
+const char *KviDns::className() const
+{
+ return "KviDns";
+}
+
+QMetaObject *KviDns::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviDns( "KviDns", &KviDns::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviDns::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviDns", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviDns::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviDns", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviDns::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = QObject::staticMetaObject();
+ static const QUParameter param_signal_0[] = {
+ { 0, &static_QUType_ptr, "KviDns", QUParameter::In }
+ };
+ static const QUMethod signal_0 = {"lookupDone", 1, param_signal_0 };
+ static const QMetaData signal_tbl[] = {
+ { "lookupDone(KviDns*)", &signal_0, QMetaData::Private }
+ };
+#ifndef QT_NO_PROPERTIES
+ static const QMetaProperty props_tbl[1] = {
+ { "bool","blockingDelete", 0x12000001, &KviDns::metaObj, 0, -1 }
+ };
+#endif // QT_NO_PROPERTIES
+ metaObj = QMetaObject::new_metaobject(
+ "KviDns", parentObject,
+ 0, 0,
+ signal_tbl, 1,
+#ifndef QT_NO_PROPERTIES
+ props_tbl, 1,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviDns.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviDns::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviDns" ) )
+ return this;
+ if ( !qstrcmp( clname, "KviHeapObject" ) )
+ return (KviHeapObject*)this;
+ return QObject::qt_cast( clname );
+}
+
+#include <qobjectdefs.h>
+#include <qsignalslotimp.h>
+
+// SIGNAL lookupDone
+void KviDns::lookupDone( KviDns* t0 )
+{
+ if ( signalsBlocked() )
+ return;
+ QConnectionList *clist = receivers( staticMetaObject()->signalOffset() + 0 );
+ if ( !clist )
+ return;
+ QUObject o[2];
+ static_QUType_ptr.set(o+1,t0);
+ activate_signal( clist, o );
+}
+
+bool KviDns::qt_invoke( int _id, QUObject* _o )
+{
+ return QObject::qt_invoke(_id,_o);
+}
+
+bool KviDns::qt_emit( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->signalOffset() ) {
+ case 0: lookupDone((KviDns*)static_QUType_ptr.get(_o+1)); break;
+ default:
+ return QObject::qt_emit(_id,_o);
+ }
+ return TRUE;
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviDns::qt_property( int id, int f, QVariant* v)
+{
+ switch ( id - staticMetaObject()->propertyOffset() ) {
+ case 0: switch( f ) {
+ case 1: *v = QVariant( this->isRunning(), 0 ); break;
+ case 3: case 4: case 5: break;
+ default: return FALSE;
+ } break;
+ default:
+ return QObject::qt_property( id, f, v );
+ }
+ return TRUE;
+}
+
+bool KviDns::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvilib/net/moc_kvi_http.cpp b/src/kvilib/net/moc_kvi_http.cpp
new file mode 100644
index 00000000..7ea9b591
--- /dev/null
+++ b/src/kvilib/net/moc_kvi_http.cpp
@@ -0,0 +1,263 @@
+/****************************************************************************
+** KviHttpRequest meta object code from reading C++ file 'kvi_http.h'
+**
+** Created: Sun Mar 23 20:56:22 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_http.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviHttpRequest::className() const
+{
+ return "KviHttpRequest";
+}
+
+QMetaObject *KviHttpRequest::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviHttpRequest( "KviHttpRequest", &KviHttpRequest::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviHttpRequest::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviHttpRequest", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviHttpRequest::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviHttpRequest", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviHttpRequest::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = QObject::staticMetaObject();
+ static const QUParameter param_slot_0[] = {
+ { "d", &static_QUType_ptr, "KviDns", QUParameter::In }
+ };
+ static const QUMethod slot_0 = {"dnsLookupDone", 1, param_slot_0 };
+ static const QUMethod slot_1 = {"haveServerIp", 0, 0 };
+ static const QMetaData slot_tbl[] = {
+ { "dnsLookupDone(KviDns*)", &slot_0, QMetaData::Protected },
+ { "haveServerIp()", &slot_1, QMetaData::Protected }
+ };
+ static const QUParameter param_signal_0[] = {
+ { "hostname", &static_QUType_QString, 0, QUParameter::In }
+ };
+ static const QUMethod signal_0 = {"resolvingHost", 1, param_signal_0 };
+ static const QUParameter param_signal_1[] = {
+ { "ipandport", &static_QUType_QString, 0, QUParameter::In }
+ };
+ static const QUMethod signal_1 = {"contactingHost", 1, param_signal_1 };
+ static const QUMethod signal_2 = {"connectionEstabilished", 0, 0 };
+ static const QUParameter param_signal_3[] = {
+ { "response", &static_QUType_QString, 0, QUParameter::In }
+ };
+ static const QUMethod signal_3 = {"receivedResponse", 1, param_signal_3 };
+ static const QUParameter param_signal_4[] = {
+ { "bSuccess", &static_QUType_bool, 0, QUParameter::In }
+ };
+ static const QUMethod signal_4 = {"terminated", 1, param_signal_4 };
+ static const QUParameter param_signal_5[] = {
+ { "message", &static_QUType_QString, 0, QUParameter::In }
+ };
+ static const QUMethod signal_5 = {"status", 1, param_signal_5 };
+ static const QUParameter param_signal_6[] = {
+ { "data", &static_QUType_ptr, "KviStr", QUParameter::In }
+ };
+ static const QUMethod signal_6 = {"data", 1, param_signal_6 };
+ static const QUParameter param_signal_7[] = {
+ { "data", &static_QUType_ptr, "KviDataBuffer", QUParameter::In }
+ };
+ static const QUMethod signal_7 = {"binaryData", 1, param_signal_7 };
+ static const QUParameter param_signal_8[] = {
+ { "hdr", &static_QUType_ptr, "KviPointerHashTable<const char*,KviStr>", QUParameter::In }
+ };
+ static const QUMethod signal_8 = {"header", 1, param_signal_8 };
+ static const QUParameter param_signal_9[] = {
+ { "request", &static_QUType_varptr, "\x04", QUParameter::In }
+ };
+ static const QUMethod signal_9 = {"requestSent", 1, param_signal_9 };
+ static const QMetaData signal_tbl[] = {
+ { "resolvingHost(const QString&)", &signal_0, QMetaData::Public },
+ { "contactingHost(const QString&)", &signal_1, QMetaData::Public },
+ { "connectionEstabilished()", &signal_2, QMetaData::Public },
+ { "receivedResponse(const QString&)", &signal_3, QMetaData::Public },
+ { "terminated(bool)", &signal_4, QMetaData::Public },
+ { "status(const QString&)", &signal_5, QMetaData::Public },
+ { "data(const KviStr&)", &signal_6, QMetaData::Public },
+ { "binaryData(const KviDataBuffer&)", &signal_7, QMetaData::Public },
+ { "header(KviPointerHashTable<const char*,KviStr>*)", &signal_8, QMetaData::Public },
+ { "requestSent(const QStringList&)", &signal_9, QMetaData::Public }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviHttpRequest", parentObject,
+ slot_tbl, 2,
+ signal_tbl, 10,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviHttpRequest.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviHttpRequest::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviHttpRequest" ) )
+ return this;
+ if ( !qstrcmp( clname, "KviHeapObject" ) )
+ return (KviHeapObject*)this;
+ return QObject::qt_cast( clname );
+}
+
+// SIGNAL resolvingHost
+void KviHttpRequest::resolvingHost( const QString& t0 )
+{
+ activate_signal( staticMetaObject()->signalOffset() + 0, t0 );
+}
+
+// SIGNAL contactingHost
+void KviHttpRequest::contactingHost( const QString& t0 )
+{
+ activate_signal( staticMetaObject()->signalOffset() + 1, t0 );
+}
+
+// SIGNAL connectionEstabilished
+void KviHttpRequest::connectionEstabilished()
+{
+ activate_signal( staticMetaObject()->signalOffset() + 2 );
+}
+
+// SIGNAL receivedResponse
+void KviHttpRequest::receivedResponse( const QString& t0 )
+{
+ activate_signal( staticMetaObject()->signalOffset() + 3, t0 );
+}
+
+// SIGNAL terminated
+void KviHttpRequest::terminated( bool t0 )
+{
+ activate_signal_bool( staticMetaObject()->signalOffset() + 4, t0 );
+}
+
+// SIGNAL status
+void KviHttpRequest::status( const QString& t0 )
+{
+ activate_signal( staticMetaObject()->signalOffset() + 5, t0 );
+}
+
+#include <qobjectdefs.h>
+#include <qsignalslotimp.h>
+
+// SIGNAL data
+void KviHttpRequest::data( const KviStr& t0 )
+{
+ if ( signalsBlocked() )
+ return;
+ QConnectionList *clist = receivers( staticMetaObject()->signalOffset() + 6 );
+ if ( !clist )
+ return;
+ QUObject o[2];
+ static_QUType_ptr.set(o+1,&t0);
+ activate_signal( clist, o );
+}
+
+// SIGNAL binaryData
+void KviHttpRequest::binaryData( const KviDataBuffer& t0 )
+{
+ if ( signalsBlocked() )
+ return;
+ QConnectionList *clist = receivers( staticMetaObject()->signalOffset() + 7 );
+ if ( !clist )
+ return;
+ QUObject o[2];
+ static_QUType_ptr.set(o+1,&t0);
+ activate_signal( clist, o );
+}
+
+// SIGNAL header
+void KviHttpRequest::header( KviPointerHashTable<const char*,KviStr>* t0 )
+{
+ if ( signalsBlocked() )
+ return;
+ QConnectionList *clist = receivers( staticMetaObject()->signalOffset() + 8 );
+ if ( !clist )
+ return;
+ QUObject o[2];
+ static_QUType_ptr.set(o+1,t0);
+ activate_signal( clist, o );
+}
+
+// SIGNAL requestSent
+void KviHttpRequest::requestSent( const QStringList& t0 )
+{
+ if ( signalsBlocked() )
+ return;
+ QConnectionList *clist = receivers( staticMetaObject()->signalOffset() + 9 );
+ if ( !clist )
+ return;
+ QUObject o[2];
+ static_QUType_varptr.set(o+1,&t0);
+ activate_signal( clist, o );
+}
+
+bool KviHttpRequest::qt_invoke( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->slotOffset() ) {
+ case 0: dnsLookupDone((KviDns*)static_QUType_ptr.get(_o+1)); break;
+ case 1: haveServerIp(); break;
+ default:
+ return QObject::qt_invoke( _id, _o );
+ }
+ return TRUE;
+}
+
+bool KviHttpRequest::qt_emit( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->signalOffset() ) {
+ case 0: resolvingHost((const QString&)static_QUType_QString.get(_o+1)); break;
+ case 1: contactingHost((const QString&)static_QUType_QString.get(_o+1)); break;
+ case 2: connectionEstabilished(); break;
+ case 3: receivedResponse((const QString&)static_QUType_QString.get(_o+1)); break;
+ case 4: terminated((bool)static_QUType_bool.get(_o+1)); break;
+ case 5: status((const QString&)static_QUType_QString.get(_o+1)); break;
+ case 6: data((const KviStr&)*((const KviStr*)static_QUType_ptr.get(_o+1))); break;
+ case 7: binaryData((const KviDataBuffer&)*((const KviDataBuffer*)static_QUType_ptr.get(_o+1))); break;
+ case 8: header((KviPointerHashTable<const char*,KviStr>*)static_QUType_ptr.get(_o+1)); break;
+ case 9: requestSent((const QStringList&)*((const QStringList*)static_QUType_ptr.get(_o+1))); break;
+ default:
+ return QObject::qt_emit(_id,_o);
+ }
+ return TRUE;
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviHttpRequest::qt_property( int id, int f, QVariant* v)
+{
+ return QObject::qt_property( id, f, v);
+}
+
+bool KviHttpRequest::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvilib/system/Makefile.am b/src/kvilib/system/Makefile.am
new file mode 100644
index 00000000..c84487eb
--- /dev/null
+++ b/src/kvilib/system/Makefile.am
@@ -0,0 +1,5 @@
+###############################################################################
+# KVirc IRC client Makefile - 16.12.98 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+EXTRA_DIST = *.cpp *.h
diff --git a/src/kvilib/system/kvi_byteorder.h b/src/kvilib/system/kvi_byteorder.h
new file mode 100644
index 00000000..dea1902d
--- /dev/null
+++ b/src/kvilib/system/kvi_byteorder.h
@@ -0,0 +1,62 @@
+#ifndef _KVI_BYTEORDER_H_
+#define _KVI_BYTEORDER_H_
+
+//=============================================================================
+//
+// File : kvi_byteorder.h
+// Creation date : Mon Dec 25 2006 19:56:16 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_bswap.h"
+#include "kvi_inttypes.h"
+
+
+//
+// Byte Orders Reminder
+// Number 0xaabbccdd
+// Little Endian Stores 0xdd 0xcc 0xbb 0xaa
+// Big Endian Stores 0xaa 0xbb 0xcc 0xdd
+// Perverse Middle Endian 0xbb 0xaa 0xdd 0xcc or another braindamaged combination (unsupported)
+// Network Byte Order is Big Endian
+// Intel Stuff uses Little Endian
+//
+
+#ifdef BIG_ENDIAN_MACHINE_BYTE_ORDER
+ #define kvi_localCpuToLittleEndian16(u) kvi_swap16((kvi_u16_t)(u))
+ #define kvi_localCpuToLittleEndian32(u) kvi_swap32((kvi_u32_t)(u))
+ #define kvi_localCpuToLittleEndian64(u) kvi_swap64((kvi_u64_t)(u))
+ #define kvi_littleEndianToLocalCpu16(u) kvi_swap16((kvi_u16_t)(u))
+ #define kvi_littleEndianToLocalCpu32(u) kvi_swap32((kvi_u32_t)(u))
+ #define kvi_littleEndianToLocalCpu64(u) kvi_swap64((kvi_u64_t)(u))
+#else
+ // We ASSUME that the local cpu is little endian.. if it isn't.. well :)
+ #define LOCAL_CPU_LITTLE_ENDIAN
+ #define kvi_localCpuToLittleEndian16(u) (u)
+ #define kvi_localCpuToLittleEndian32(u) (u)
+ #define kvi_localCpuToLittleEndian64(u) (u)
+ #define kvi_littleEndianToLocalCpu16(u) (u)
+ #define kvi_littleEndianToLocalCpu32(u) (u)
+ #define kvi_littleEndianToLocalCpu64(u) (u)
+#endif
+
+
+#endif // !_KVI_BYTEORDER_H_
diff --git a/src/kvilib/system/kvi_env.cpp b/src/kvilib/system/kvi_env.cpp
new file mode 100644
index 00000000..1497632e
--- /dev/null
+++ b/src/kvilib/system/kvi_env.cpp
@@ -0,0 +1,89 @@
+//=============================================================================
+//
+// File : kvi_env.cpp
+// Creation date : Sat May 05 2002 02:15:21 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma@kvirc.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 opinion) 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.
+//
+//=============================================================================
+#define __KVILIB__
+
+#define _KVI_ENV_CPP_
+
+#include "kvi_env.h"
+#include "kvi_string.h"
+#include "kvi_malloc.h"
+#include "kvi_memmove.h"
+
+#ifndef COMPILE_ON_WINDOWS
+
+bool kvi_setenv(const char * name,const char * value)
+{
+#ifdef HAVE_SETENV
+ return (setenv(name,value,1) == 0);
+#else
+ #ifdef HAVE_PUTENV
+ int iLen1 = kvi_strLen(name);
+ int iLen2 = kvi_strLen(value);
+ char * buf = (char *)kvi_malloc(iLen1 + iLen2 + 2);
+ kvi_memmove(buf,name,iLen1);
+ *(buf + iLen1) = '=';
+ kvi_memmove(buf + iLen1 + 1,value,iLen2);
+ *(buf + iLen1 + iLen2 + 1) = '\0';
+ int iRet = putenv(buf);
+ if(iRet != 0)
+ {
+ kvi_free(buf);
+ return false;
+ }
+ return true;
+ #else
+ // no setenv , no putenv.. what the hell of system is this ?
+ return false;
+ #endif
+#endif
+}
+
+void kvi_unsetenv(const char * name)
+{
+#ifdef HAVE_UNSETENV
+ unsetenv(name);
+#else
+ #ifdef HAVE_PUTENV
+ int iLen1 = kvi_strLen(name);
+ char * buf = (char *)kvi_malloc(iLen1 + 1);
+ kvi_memmove(buf,name,iLen1);
+ *(buf + iLen1) = '\0';
+ int iRet = putenv(buf);
+ if(iRet != 0)
+ {
+ kvi_free(buf);
+ } else {
+ // hmmm
+ if(kvi_getenv(name) == 0)
+ {
+ // ok , the string is not in the environment
+ // we can free it
+ kvi_free(buf);
+ } // else this system sux
+ }
+ #endif
+#endif
+}
+
+#endif //!COMPILE_ON_WINDOWS
diff --git a/src/kvilib/system/kvi_env.h b/src/kvilib/system/kvi_env.h
new file mode 100644
index 00000000..b3b24a2f
--- /dev/null
+++ b/src/kvilib/system/kvi_env.h
@@ -0,0 +1,60 @@
+#ifndef _KVI_ENV_H_
+#define _KVI_ENV_H_
+
+//=============================================================================
+//
+// File : kvi_env.h
+// Creation date : Sat May 05 2002 02:15:21 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma@kvirc.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 opinion) 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.
+//
+//=============================================================================
+
+//=============================================================================
+// Enviroinement function wrappers
+//=============================================================================
+
+#include "kvi_settings.h"
+
+
+
+#include <stdlib.h>
+
+inline char * kvi_getenv(const char * name)
+{
+#ifdef HAVE_GETENV
+ return getenv(name);
+#else
+ return 0;
+#endif
+}
+
+#ifdef COMPILE_ON_WINDOWS
+ #define kvi_setenv(__name,__value) SetEnvironmentVariable(__name,__value)
+ #define kvi_unsetenv(__name) SetEnvironmentVariable(__name,NULL)
+#else
+ #ifndef _KVI_ENV_CPP_
+ KVILIB_API extern bool kvi_setenv(const char * name,const char * value);
+ KVILIB_API extern void kvi_unsetenv(const char * name);
+ #endif
+#endif
+
+
+
+
+#endif //_KVI_ENV_H_
diff --git a/src/kvilib/system/kvi_library.h b/src/kvilib/system/kvi_library.h
new file mode 100644
index 00000000..393ed5c7
--- /dev/null
+++ b/src/kvilib/system/kvi_library.h
@@ -0,0 +1,115 @@
+#ifndef _KVI_LIBRARY_H_
+#define _KVI_LIBRARY_H_
+
+//=====================================================================================
+//
+// File : kvi_library.h
+// Creation date : Tue Sep 25 16:20:40 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=====================================================================================
+
+
+//=====================================================================================
+// System dynamic linker interface abstraction
+//=====================================================================================
+
+
+#include "kvi_settings.h"
+
+
+#ifdef COMPILE_ON_WINDOWS
+
+ //#include <windows.h>
+ #include <winsock2.h> // this will pull in windows.h
+
+ typedef HMODULE kvi_library_t;
+
+ inline kvi_library_t kvi_library_open(const char * path)
+ {
+#ifndef DEBUG
+ // this is to avoid the ugly message boxes when the dll has
+ // ... but do it only in release mode
+ UINT nOldErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
+#endif
+ kvi_library_t ret = LoadLibrary(path);
+#ifndef DEBUG
+ SetErrorMode(nOldErrorMode);
+#endif
+ return ret;
+ };
+
+ inline void kvi_library_close(kvi_library_t lib)
+ {
+ FreeLibrary(lib);
+ };
+
+ inline void * kvi_library_symbol(kvi_library_t lib,const char * symName)
+ {
+ return GetProcAddress(lib,symName);
+ };
+
+ inline const char * kvi_library_error()
+ {
+ return "Windoze-like error";
+ };
+
+#else
+
+ #include <dlfcn.h>
+
+ // sparc-unknown-openbsd3.0 (At least) has only RTLD_LAZY
+ #ifndef RTLD_NOW
+ #define RTLD_NOW RTLD_LAZY
+ #endif
+ #ifndef RTLD_GLOBAL
+ #define RTLD_GLOBAL 0
+ #endif
+
+ typedef void * kvi_library_t;
+
+ inline kvi_library_t kvi_library_open(const char * path)
+ {
+ return dlopen(path,RTLD_GLOBAL | RTLD_NOW);
+ };
+
+ inline void kvi_library_close(kvi_library_t lib)
+ {
+ dlclose(lib);
+ };
+
+
+ inline void * kvi_library_symbol(kvi_library_t lib,const char * symName)
+ {
+ return dlsym(lib,symName);
+ };
+
+ inline const char * kvi_library_error()
+ {
+ return dlerror();
+ };
+
+
+#endif //!COMPILE_ON_WINDOWS
+
+
+#define kvi_library_load kvi_library_open
+#define kvi_library_unload kvi_library_close
+
+#endif //_KVI_LIBRARY_H_
diff --git a/src/kvilib/system/kvi_locale.cpp b/src/kvilib/system/kvi_locale.cpp
new file mode 100644
index 00000000..f49eabe4
--- /dev/null
+++ b/src/kvilib/system/kvi_locale.cpp
@@ -0,0 +1,1191 @@
+//=============================================================================
+//
+// File : kvi_locale.cpp
+// Creation date : Fri Mar 19 1999 19:08:41 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+
+
+//#define _KVI_DEBUG_CHECK_RANGE_
+#include "kvi_debug.h"
+#include "kvi_malloc.h"
+#include "kvi_bswap.h"
+
+#define _KVI_LOCALE_CPP_
+#include "kvi_locale.h"
+
+#include <qglobal.h> //for debug()
+#include <qtextcodec.h>
+#include <qdir.h>
+
+#ifdef COMPILE_USE_QT4
+ #include <qlocale.h>
+#endif
+
+#include "kvi_string.h"
+#include "kvi_qcstring.h"
+#include "kvi_env.h"
+#include "kvi_fileutils.h"
+#include "kvi_file.h"
+
+
+KVILIB_API KviMessageCatalogue * g_pMainCatalogue = 0;
+
+static KviStr g_szLang;
+static KviTranslator * g_pTranslator = 0;
+static KviPointerHashTable<const char *,KviMessageCatalogue> * g_pCatalogueDict = 0;
+static QTextCodec * g_pUtf8TextCodec = 0;
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// The following code was extracted and adapted from gutf8.c
+// from the GNU GLIB2 package.
+//
+// gutf8.c - Operations on UTF-8 strings.
+//
+// Copyright (C) 1999 Tom Tromey
+// Copyright (C) 2000 Red Hat, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser 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
+// Lesser 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.
+//
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+typedef char gchar;
+typedef unsigned char guchar;
+typedef signed int gssize;
+typedef unsigned int gunichar;
+
+
+
+#define UNICODE_VALID(Char) \
+ ((Char) < 0x110000 && \
+ (((Char) & 0xFFFFF800) != 0xD800) && \
+ ((Char) < 0xFDD0 || (Char) > 0xFDEF) && \
+ ((Char) & 0xFFFE) != 0xFFFE)
+
+#define CONTINUATION_CHAR \
+ if ((*(guchar *)p & 0xc0) != 0x80) /* 10xxxxxx */ \
+ goto error; \
+ val <<= 6; \
+ val |= (*(guchar *)p) & 0x3f;
+
+
+static const char *
+fast_validate (const char *str)
+
+{
+ gunichar val = 0;
+ gunichar min = 0;
+ const gchar *p;
+
+ for (p = str; *p; p++)
+ {
+ if (*(guchar *)p < 128)
+ /* done */;
+ else
+ {
+ const gchar *last;
+
+ last = p;
+ if ((*(guchar *)p & 0xe0) == 0xc0) /* 110xxxxx */
+ {
+ if ((*(guchar *)p & 0x1e) == 0)
+ goto error;
+ p++;
+ if ((*(guchar *)p & 0xc0) != 0x80) /* 10xxxxxx */
+ goto error;
+ }
+ else
+ {
+ if ((*(guchar *)p & 0xf0) == 0xe0) /* 1110xxxx */
+ {
+ min = (1 << 11);
+ val = *(guchar *)p & 0x0f;
+ goto TWO_REMAINING;
+ }
+ else if ((*(guchar *)p & 0xf8) == 0xf0) /* 11110xxx */
+ {
+ min = (1 << 16);
+ val = *(guchar *)p & 0x07;
+ }
+ else
+ goto error;
+
+ p++;
+ CONTINUATION_CHAR;
+ TWO_REMAINING:
+ p++;
+ CONTINUATION_CHAR;
+ p++;
+ CONTINUATION_CHAR;
+
+ if (val < min)
+ goto error;
+
+ if (!UNICODE_VALID(val))
+ goto error;
+ }
+
+ continue;
+
+ error:
+ return last;
+ }
+ }
+
+ return p;
+}
+
+static const gchar *
+fast_validate_len (const char *str,
+ gssize max_len)
+
+{
+ gunichar val = 0;
+ gunichar min = 0;
+ const gchar *p;
+
+ for (p = str; (max_len < 0 || (p - str) < max_len) && *p; p++)
+ {
+ if (*(guchar *)p < 128)
+ /* done */;
+ else
+ {
+ const gchar *last;
+
+ last = p;
+ if ((*(guchar *)p & 0xe0) == 0xc0) /* 110xxxxx */
+ {
+ if (max_len >= 0 && max_len - (p - str) < 2)
+ goto error;
+
+ if ((*(guchar *)p & 0x1e) == 0)
+ goto error;
+ p++;
+ if ((*(guchar *)p & 0xc0) != 0x80) /* 10xxxxxx */
+ goto error;
+ }
+ else
+ {
+ if ((*(guchar *)p & 0xf0) == 0xe0) /* 1110xxxx */
+ {
+ if (max_len >= 0 && max_len - (p - str) < 3)
+ goto error;
+
+ min = (1 << 11);
+ val = *(guchar *)p & 0x0f;
+ goto TWO_REMAINING;
+ }
+ else if ((*(guchar *)p & 0xf8) == 0xf0) /* 11110xxx */
+ {
+ if (max_len >= 0 && max_len - (p - str) < 4)
+ goto error;
+
+ min = (1 << 16);
+ val = *(guchar *)p & 0x07;
+ }
+ else
+ goto error;
+
+ p++;
+ CONTINUATION_CHAR;
+ TWO_REMAINING:
+ p++;
+ CONTINUATION_CHAR;
+ p++;
+ CONTINUATION_CHAR;
+
+ if (val < min)
+ goto error;
+ if (!UNICODE_VALID(val))
+ goto error;
+ }
+
+ continue;
+
+ error:
+ return last;
+ }
+ }
+
+ return p;
+}
+
+static bool g_utf8_validate (const char *str,
+ gssize max_len,
+ const gchar **end)
+
+{
+ const gchar *p;
+
+ if (max_len < 0)
+ p = fast_validate (str);
+ else
+ p = fast_validate_len (str, max_len);
+
+ if (end)
+ *end = p;
+
+ if ((max_len >= 0 && p != str + max_len) ||
+ (max_len < 0 && *p != '\0'))
+ return false;
+ else
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+// End of gutf8.c
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+
+class KviSmartTextCodec : public QTextCodec
+{
+protected:
+ KviQCString m_szName;
+ QTextCodec * m_pRecvCodec;
+ QTextCodec * m_pSendCodec;
+public:
+ KviSmartTextCodec(const char * szName,const char * szChildCodecName,bool bSendInUtf8)
+ : QTextCodec()
+ {
+ m_szName = szName;
+ if(!g_pUtf8TextCodec)
+ {
+ g_pUtf8TextCodec = QTextCodec::codecForName("UTF-8");
+ if(!g_pUtf8TextCodec)
+ {
+ debug("Can't find the global utf8 text codec!");
+ g_pUtf8TextCodec = QTextCodec::codecForLocale(); // try anything else...
+ }
+ }
+ m_pRecvCodec = QTextCodec::codecForName(szChildCodecName);
+ if(!m_pRecvCodec)
+ {
+ debug("Can't find the codec for name %s (composite codec creation)",szName);
+ m_pRecvCodec = g_pUtf8TextCodec;
+ }
+ if(bSendInUtf8)
+ m_pSendCodec = g_pUtf8TextCodec;
+ else
+ m_pSendCodec = m_pRecvCodec;
+ }
+public:
+ bool ok(){ return m_pRecvCodec && g_pUtf8TextCodec; };
+
+ virtual int mibEnum () const { return 0; };
+
+#ifdef COMPILE_USE_QT4
+ virtual QByteArray name() const { return m_szName; };
+protected:
+ virtual QByteArray convertFromUnicode(const QChar * input,int number,ConverterState * state) const
+ {
+ return m_pSendCodec->fromUnicode(input,number,state);
+ }
+ virtual QString convertToUnicode(const char * chars,int len,ConverterState * state) const
+ {
+ if(g_utf8_validate(chars,len,NULL))return g_pUtf8TextCodec->toUnicode(chars,len,state);
+ return m_pRecvCodec->toUnicode(chars,len,state);
+ }
+#else
+public:
+ virtual const char * mimeName () const { return m_pRecvCodec->mimeName(); };
+ virtual const char * name () const { return m_szName.data(); };
+ virtual QTextDecoder * makeDecoder () const { return m_pRecvCodec->makeDecoder(); };
+ virtual QTextEncoder * makeEncoder () const { return m_pSendCodec->makeEncoder(); };
+ QCString fromUnicode (const QString & uc) const { return m_pSendCodec->fromUnicode(uc); };
+ virtual QCString fromUnicode (const QString & uc,int & lenInOut) const { return m_pSendCodec->fromUnicode(uc,lenInOut); };
+ QString toUnicode(const char * chars) const
+ {
+ if(g_utf8_validate(chars,-1,NULL))return g_pUtf8TextCodec->toUnicode(chars);
+ return m_pRecvCodec->toUnicode(chars);
+ };
+ virtual QString toUnicode(const char * chars,int len) const
+ {
+ if(g_utf8_validate(chars,len,NULL))return g_pUtf8TextCodec->toUnicode(chars,len);
+ return m_pRecvCodec->toUnicode(chars,len);
+ };
+ QString toUnicode(const QByteArray & a,int len) const
+ {
+ if(g_utf8_validate(a.data(),len,NULL))return g_pUtf8TextCodec->toUnicode(a,len);
+ return m_pRecvCodec->toUnicode(a,len);
+ };
+ QString toUnicode(const QByteArray & a) const
+ {
+ if(g_utf8_validate(a.data(),a.size(),NULL))return g_pUtf8TextCodec->toUnicode(a);
+ return m_pRecvCodec->toUnicode(a);
+ };
+ QString toUnicode(const QCString & a,int len) const
+ {
+ if(g_utf8_validate(a.data(),len,NULL))return g_pUtf8TextCodec->toUnicode(a,len);
+ return m_pRecvCodec->toUnicode(a,len);
+ };
+ QString toUnicode(const QCString & a) const
+ {
+ if(g_utf8_validate(a.data(),-1,NULL))return g_pUtf8TextCodec->toUnicode(a);
+ return m_pRecvCodec->toUnicode(a);
+ };
+
+ virtual bool canEncode(QChar ch) const { return m_pSendCodec->canEncode(ch); };
+ virtual bool canEncode(const QString &s) const { return m_pSendCodec->canEncode(s); };
+ virtual int heuristicContentMatch(const char * chars,int len) const
+ {
+ int iii = g_pUtf8TextCodec->heuristicContentMatch(chars,len);
+ if(iii < 0)return m_pRecvCodec->heuristicContentMatch(chars,len);
+ return iii;
+ }
+ virtual int heuristicNameMatch(const char * hint) const { return 0; };
+#endif
+};
+
+static KviPointerHashTable<const char *,KviSmartTextCodec> * g_pSmartCodecDict = 0;
+
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// The following code was extracted and adapted from gettext.h and gettextP.h
+// from the GNU gettext package.
+//
+// Internal header for GNU gettext internationalization functions.
+// Copyright (C) 1995, 1997 Free Software Foundation, Inc.
+//
+// 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, 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 Library General Public
+// License along with the GNU C 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.
+//
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+
+#if HAVE_LIMITS_H || _LIBC
+ #include <limits.h>
+#endif
+
+// The magic number of the GNU message catalog format.
+#define KVI_LOCALE_MAGIC 0x950412de
+#define KVI_LOCALE_MAGIC_SWAPPED 0xde120495
+
+// Revision number of the currently used .mo (binary) file format.
+#define MO_REVISION_NUMBER 0
+
+
+// Header for binary .mo file format.
+struct GnuMoFileHeader
+{
+ // The magic number.
+ kvi_u32_t magic;
+ // The revision number of the file format.
+ kvi_u32_t revision;
+ // The number of strings pairs.
+ kvi_u32_t nstrings;
+ // Offset of table with start offsets of original strings.
+ kvi_u32_t orig_tab_offset;
+ // Offset of table with start offsets of translation strings.
+ kvi_u32_t trans_tab_offset;
+ // Size of hashing table.
+ kvi_u32_t hash_tab_size;
+ // Offset of first hashing entry.
+ kvi_u32_t hash_tab_offset;
+};
+
+struct GnuMoStringDescriptor
+{
+ // Length of addressed string.
+ kvi_u32_t length;
+ // Offset of string in file.
+ kvi_u32_t offset;
+};
+
+#define KVI_SWAP_IF_NEEDED(flag,value) (flag ? kvi_swap32(value) : (value))
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+// End of gettext.h & gettextP.h
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+
+// HELPERS
+
+static int somePrimeNumbers[90]=
+{
+ 257 , 521 , 769 , 1031, 1087, 1091, 1103, 1117, 1123, 1151, // Incomplete *.mo files
+ 1163, 1171, 1181, 1193, 1201, 1213, 1217, 1223, 1229, 1231, // Complete *.mo files
+ 1237, 1249, 1259, 1277, 1283, 1289, 1291, 1297, 1307, 1319,
+ 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, 1433,
+ 1447, 1459, 1471, 1481, 1493, 1511, 1523, 1531, 1543, 1553,
+ 1567, 1571, 1583, 1597, 1609, 1619, 1627, 1637, 1657, 1667, // Too big for KVIrc *.mo files
+ 1693, 1709, 1721, 1733, 1741, 1753, 1777, 1789, 1811, 1831,
+ 1907, 2069, 2111, 2221, 2309, 2441, 2531, 2617, 2731, 2837,
+ 2903, 3121, 3329, 3331, 3767, 4127, 5051, 6089, 7039, 9973
+};
+
+int kvi_getFirstBiggerPrime(int number)
+{
+ for(int i=0;i<90;i++){
+ if(somePrimeNumbers[i] >= number)return somePrimeNumbers[i];
+ }
+ return 9973; //error!
+}
+
+
+KviMessageCatalogue::KviMessageCatalogue()
+{
+ //m_uEncoding = 0;
+ m_pTextCodec = QTextCodec::codecForLocale();
+
+ //m_pMessages = new KviPointerHashTable<const char *,KviTranslationEntry>(1123,true,false); // dictSize, case sensitive , don't copy keys
+ m_pMessages = new KviPointerHashTable<const char *,KviTranslationEntry>(32,true,false); // dictSize, case sensitive , don't copy keys
+ m_pMessages->setAutoDelete(true);
+}
+
+KviMessageCatalogue::~KviMessageCatalogue()
+{
+ if(m_pMessages)
+ delete m_pMessages;
+}
+
+bool KviMessageCatalogue::load(const QString& name)
+{
+ QString szCatalogueFile(name);
+
+ // Try to load the header
+ KviFile f(szCatalogueFile);
+ if(!f.openForReading())
+ {
+ debug("[KviLocale]: Failed to open the messages file %s: probably doesn't exist",KviQString::toUtf8(szCatalogueFile).data());
+ return false;
+ }
+
+ GnuMoFileHeader hdr;
+
+ if(f.readBlock((char *)&hdr,sizeof(GnuMoFileHeader)) < (int)sizeof(GnuMoFileHeader))
+ {
+ debug("KviLocale: Failed to read header of %s",KviQString::toUtf8(szCatalogueFile).data());
+ f.close();
+ return false;
+ }
+
+ bool bMustSwap = false;
+
+ if(hdr.magic != KVI_LOCALE_MAGIC)
+ {
+ if(hdr.magic == KVI_LOCALE_MAGIC_SWAPPED)
+ {
+ debug("KviLocale: Swapped magic for file %s: swapping data too",KviQString::toUtf8(szCatalogueFile).data());
+ bMustSwap = true;
+ } else {
+ debug("KviLocale: Bad locale magic for file %s: not a *.mo file ?",KviQString::toUtf8(szCatalogueFile).data());
+ f.close();
+ return false;
+ }
+ }
+
+ if(KVI_SWAP_IF_NEEDED(bMustSwap,hdr.revision) != MO_REVISION_NUMBER)
+ {
+ debug("KviLocale: Invalid *.mo file revision number for file %s",KviQString::toUtf8(szCatalogueFile).data());
+ f.close();
+ return false;
+ }
+
+ int numberOfStrings = KVI_SWAP_IF_NEEDED(bMustSwap,hdr.nstrings);
+
+ if(numberOfStrings <= 0)
+ {
+ debug("KviLocale: No translated messages found in file %s",KviQString::toUtf8(szCatalogueFile).data());
+ f.close();
+ return false;
+ }
+
+ if(numberOfStrings >= 9972)
+ {
+ debug("Number of strings too big...sure that it is a KVIrc catalog file ?");
+ numberOfStrings = 9972;
+ }
+
+ // return back
+ f.seek(0);
+
+ unsigned int fSize = f.size();
+ char * buffer = (char *)kvi_malloc(fSize);
+
+ // FIXME: maybe read it in blocks eh ?
+ if(f.readBlock(buffer,fSize) < (int)fSize)
+ {
+ debug("KviLocale: Error while reading the translation file %s",KviQString::toUtf8(szCatalogueFile).data());
+ kvi_free(buffer);
+ f.close();
+ return false;
+ }
+
+ // Check for broken *.mo files
+ if(fSize < (24 + (sizeof(GnuMoStringDescriptor) * numberOfStrings)))
+ {
+ debug("KviLocale: Broken translation file %s (too small for all descriptors)",KviQString::toUtf8(szCatalogueFile).data());
+ kvi_free(buffer);
+ f.close();
+ return false;
+ }
+
+ GnuMoStringDescriptor * origDescriptor = (GnuMoStringDescriptor *)(buffer + KVI_SWAP_IF_NEEDED(bMustSwap,hdr.orig_tab_offset));
+ GnuMoStringDescriptor * transDescriptor = (GnuMoStringDescriptor *)(buffer + KVI_SWAP_IF_NEEDED(bMustSwap,hdr.trans_tab_offset));
+
+ // Check again for broken *.mo files
+ int expectedFileSize = KVI_SWAP_IF_NEEDED(bMustSwap,transDescriptor[numberOfStrings - 1].offset) +
+ KVI_SWAP_IF_NEEDED(bMustSwap,transDescriptor[numberOfStrings - 1].length);
+
+ if(fSize < (unsigned int)expectedFileSize)
+ {
+ debug("KviLocale: Broken translation file %s (too small for all the message strings)",KviQString::toUtf8(szCatalogueFile).data());
+ kvi_free(buffer);
+ f.close();
+ return false;
+ }
+
+ // Ok...we can run now
+
+ int dictSize = kvi_getFirstBiggerPrime(numberOfStrings);
+ if(m_pMessages)
+ delete m_pMessages;
+ m_pMessages = new KviPointerHashTable<const char *,KviTranslationEntry>(dictSize,true,false); // dictSize, case sensitive , don't copy keys
+ m_pMessages->setAutoDelete(true);
+
+ KviStr szHeader;
+
+ for(int i=0;i < numberOfStrings;i++)
+ {
+ // FIXME: "Check for NULL inside strings here ?"
+ //debug("original seems to be at %u and %u byttes long",KVI_SWAP_IF_NEEDED(bMustSwap,origDescriptor[i].offset),
+ // KVI_SWAP_IF_NEEDED(bMustSwap,origDescriptor[i].length));
+ //debug("translated seems to be at %u and %u byttes long",KVI_SWAP_IF_NEEDED(bMustSwap,transDescriptor[i].offset),
+ // KVI_SWAP_IF_NEEDED(bMustSwap,transDescriptor[i].length));
+
+ KviTranslationEntry * e = new KviTranslationEntry(
+ (char *)(buffer + KVI_SWAP_IF_NEEDED(bMustSwap,origDescriptor[i].offset)),
+ KVI_SWAP_IF_NEEDED(bMustSwap,origDescriptor[i].length),
+ (char *)(buffer + KVI_SWAP_IF_NEEDED(bMustSwap,transDescriptor[i].offset)),
+ KVI_SWAP_IF_NEEDED(bMustSwap,transDescriptor[i].length));
+
+ // In some (or all?) *.mo files the first string
+ // is zero bytes long and the translated one contains
+ // informations about the translation
+ if(e->m_szKey.len() == 0)
+ {
+ szHeader = e->m_szEncodedTranslation;
+ delete e;
+ continue;
+ }
+
+ m_pMessages->insert(e->m_szKey.ptr(),e);
+ }
+
+ kvi_free(buffer);
+ f.close();
+
+ m_pTextCodec = 0;
+
+ // find out the text encoding , if possible
+ if(szHeader.hasData())
+ {
+ // find "charset=*\n"
+ int idx = szHeader.findFirstIdx("charset=");
+ if(idx != -1)
+ {
+ szHeader.cutLeft(idx + 8);
+ szHeader.cutFromFirst('\n');
+ szHeader.stripWhiteSpace();
+ m_pTextCodec = KviLocale::codecForName(szHeader.ptr());
+ if(!m_pTextCodec)
+ {
+ debug("Can't find the codec for charset=%s",szHeader.ptr());
+ debug("Falling back to codecForLocale()");
+ m_pTextCodec = QTextCodec::codecForLocale();
+ }
+ }
+ }
+
+ if(!m_pTextCodec)
+ {
+ debug("The message catalogue does not have a \"charset\" header");
+ debug("Assuming utf8"); // FIXME: or codecForLocale() ?
+ m_pTextCodec = QTextCodec::codecForName("UTF-8");
+ }
+
+ return true;
+}
+
+const char * KviMessageCatalogue::translate(const char *text)
+{
+ KviTranslationEntry * aux = m_pMessages->find(text);
+ if(aux)return aux->m_szEncodedTranslation.ptr();
+ return text;
+}
+
+const QString & KviMessageCatalogue::translateToQString(const char *text)
+{
+ KviTranslationEntry * aux = m_pMessages->find(text);
+ if(aux)
+ {
+ if(aux->m_pQTranslation)return *(aux->m_pQTranslation);
+ aux->m_pQTranslation = new QString(m_pTextCodec->toUnicode(aux->m_szEncodedTranslation.ptr()));
+ return *(aux->m_pQTranslation);
+ }
+ // no translation is available: let's avoid continous string decoding
+ aux = new KviTranslationEntry(text);
+ m_pMessages->insert(aux->m_szKey.ptr(),aux);
+ aux->m_pQTranslation = new QString(m_pTextCodec->toUnicode(aux->m_szEncodedTranslation.ptr()));
+ return *(aux->m_pQTranslation);
+}
+
+
+
+
+namespace KviLocale
+{
+#ifndef QT_NO_BIG_CODECS
+ #define NUM_ENCODINGS 109
+#else
+ #define NUM_ENCODINGS 85
+#endif
+
+
+
+ static EncodingDescription supported_encodings[]=
+ {
+ { "UTF-8" , 0 , 0 , "8-bit Unicode" },
+ { "ISO-8859-1" , 0 , 0 , "Western, Latin-1" },
+ { "ISO-8859-2" , 0 , 0 , "Central European 1" },
+ { "ISO-8859-3" , 0 , 0 , "Central European 2" },
+ { "ISO-8859-4" , 0 , 0 , "Baltic, Standard" },
+ { "ISO-8859-5" , 0 , 0 , "Cyrillic, ISO" },
+ { "ISO-8859-6" , 0 , 0 , "Arabic, Standard" },
+ { "ISO-8859-7" , 0 , 0 , "Greek" },
+ { "ISO-8859-8" , 0 , 0 , "Hebrew, visually ordered" },
+ { "ISO-8859-8-i" , 0 , 0 , "Hebrew, logically ordered" },
+ { "ISO-8859-9" , 0 , 0 , "Turkish, Latin-5" },
+ { "ISO-8859-15" , 0 , 0 , "Western, Latin-1 + Euro" },
+ { "KOI8-R" , 0 , 0 , "Cyrillic, KOI" },
+ { "KOI8-U" , 0 , 0 , "Ukrainian" },
+ { "CP-1250" , 0 , 0 , "Central European 3" },
+ { "CP-1251" , 0 , 0 , "Cyrillic, Windows" },
+ { "CP-1252" , 0 , 0 , "Western, CP" },
+ { "CP-1253" , 0 , 0 , "Greek, CP" },
+ { "CP-1256" , 0 , 0 , "Arabic, CP" },
+ { "CP-1257" , 0 , 0 , "Baltic, CP" },
+ { "CP-1255" , 0 , 0 , "Hebrew, CP" },
+ { "CP-1254" , 0 , 0 , "Turkish, CP" },
+ { "TIS-620" , 0 , 0 , "Thai" },
+#ifndef QT_NO_BIG_CODECS
+ { "Big5" , 0 , 0 , "Chinese Traditional" },
+ { "Big5-HKSCS" , 0 , 0 , "Chinese Traditional, Hong Kong" },
+ { "GB18030" , 0 , 0 , "Chinese Simplified" },
+ { "JIS7" , 0 , 0 , "Japanese (JIS7)" },
+ { "Shift-JIS" , 0 , 0 , "Japanese (Shift-JIS)" },
+ { "EUC-JP" , 0 , 0 , "Japanese (EUC-JP)" },
+ { "EUC-KR" , 0 , 0 , "Korean" },
+ { "TSCII" , 0 , 0 , "Tamil" },
+#endif
+ { "ISO-8859-10" , 0 , 0 , "ISO-8859-10" },
+ { "ISO-8859-13" , 0 , 0 , "ISO-8859-13" },
+ { "ISO-8859-14" , 0 , 0 , "ISO-8859-14" },
+ { "IBM-850" , 0 , 0 , "IBM-850" },
+ { "IBM-866" , 0 , 0 , "IBM-866" },
+ { "CP874" , 0 , 0 , "CP874" },
+
+ // smart codecs that send in the local charset
+ { "ISO-8859-1 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Western Latin-1, O: Western Latin-1" },
+ { "ISO-8859-2 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Central European 1, O: Central European 1" },
+ { "ISO-8859-3 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Central European 2, O: Central European 2" },
+ { "ISO-8859-4 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Baltic, Standard, O: Baltic, Standard" },
+ { "ISO-8859-5 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Cyrillic, ISO, O: Cyrillic, ISO" },
+ { "ISO-8859-6 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Arabic, Standard, O: Arabic, Standard" },
+ { "ISO-8859-7 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Greek, O: Greek" },
+ { "ISO-8859-8 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Hebrew, visually ordered, O: Hebrew, visually ordered" },
+ { "ISO-8859-8-i [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Hebrew, logically ordered, O: Hebrew, logically ordered" },
+ { "ISO-8859-9 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Turkish, Latin-5, O: Turkish, Latin-5" },
+ { "ISO-8859-15 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Western, Latin-1 + Euro, O: Western, Latin-1 + Euro" },
+ { "KOI8-R [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Cyrillic, KOI, O: Cyrillic, KOI" },
+ { "KOI8-U [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Ukrainian, O: Ukrainian" },
+ { "CP-1250 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Central European 3, O: Central European 3" },
+ { "CP-1251 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Cyrillic, Windows, O: Cyrillic, Windows" },
+ { "CP-1252 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Western, CP, O: Western, CP" },
+ { "CP-1253 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Greek, CP, O: Greek, CP" },
+ { "CP-1256 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Arabic, CP, O: Arabic, CP" },
+ { "CP-1257 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Baltic, CP, O: Baltic, CP" },
+ { "CP-1255 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Hebrew, CP, O: Hebrew, CP" },
+ { "CP-1254 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Turkish, CP, O: Turkish, CP" },
+ { "TIS-620 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Thai, O: Thai" },
+#ifndef QT_NO_BIG_CODECS
+ { "Big5 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Chinese Traditional, O: Chinese Traditional" },
+ { "Big5-HKSCS [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Chinese Traditional, Hong Kong, O: Chinese Traditional, Hong Kong" },
+ { "GB18030 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Chinese Simplified, O: Chinese Simplified" },
+ { "JIS7 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Japanese (JIS7), O: Japanese " },
+ { "Shift-JIS [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Japanese (Shift-JIS), O: Japanese (Shift-JIS)" },
+ { "EUC-JP [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Japanese (EUC-JP), O: Japanese (EUC-JP)" },
+ { "EUC-KR [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Korean, O: Korean" },
+ { "TSCII [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / Tamil, O: Tamil" },
+#endif
+ { "ISO-8859-10 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / ISO-8859-10, O: ISO-8859-10" },
+ { "ISO-8859-13 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / ISO-8859-13, O: ISO-8859-13" },
+ { "ISO-8859-14 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / ISO-8859-14, O: ISO-8859-14" },
+ { "IBM-850 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / IBM-850, O: IBM-850" },
+ { "IBM-866 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / IBM-866, O: IBM-866" },
+ { "CP874 [UTF-8]" , 1 , 0 , "I: 8-bit Unicode / CP874, O: CP874" },
+
+ // smart codecs that send in utf8
+ { "UTF-8 [ISO-8859-1]" , 1 , 1 , "I: 8-bit Unicode / Western Latin-1, O: 8-bit Unicode" },
+ { "UTF-8 [ISO-8859-2]" , 1 , 1 , "I: 8-bit Unicode / Central European 1, O: 8-bit Unicode" },
+ { "UTF-8 [ISO-8859-3]" , 1 , 1 , "I: 8-bit Unicode / Central European 2, O: 8-bit Unicode" },
+ { "UTF-8 [ISO-8859-4]" , 1 , 1 , "I: 8-bit Unicode / Baltic, Standard, O: 8-bit Unicode" },
+
+ { "UTF-8 [ISO-8859-5]" , 1 , 1 , "I: 8-bit Unicode / Cyrillic, ISO, O: 8-bit Unicode" },
+ { "UTF-8 [ISO-8859-6]" , 1 , 1 , "I: 8-bit Unicode / Arabic, Standard, O: 8-bit Unicode" },
+ { "UTF-8 [ISO-8859-7]" , 1 , 1 , "I: 8-bit Unicode / Greek, O: 8-bit Unicode" },
+ { "UTF-8 [ISO-8859-8]" , 1 , 1 , "I: 8-bit Unicode / Hebrew, visually ordered, O: 8-bit Unicode" },
+
+ { "UTF-8 [ISO-8859-8-i]" , 1 , 1 , "I: 8-bit Unicode / Hebrew, logically ordered, O: 8-bit Unicode" },
+ { "UTF-8 [ISO-8859-9]" , 1 , 1 , "I: 8-bit Unicode / Turkish, Latin-5, O: 8-bit Unicode" },
+ { "UTF-8 [ISO-8859-15]" , 1 , 1 , "I: 8-bit Unicode / Western, Latin-1 + Euro, O: 8-bit Unicode" },
+ { "UTF-8 [KOI8-R]" , 1 , 1 , "I: 8-bit Unicode / Cyrillic, KOI, O: 8-bit Unicode" },
+
+ { "UTF-8 [KOI8-U]" , 1 , 1 , "I: 8-bit Unicode / Ukrainian, O: 8-bit Unicode" },
+ { "UTF-8 [CP-1250]" , 1 , 1 , "I: 8-bit Unicode / Central European 3, O: 8-bit Unicode" },
+ { "UTF-8 [CP-1251]" , 1 , 1 , "I: 8-bit Unicode / Cyrillic, Windows, O: 8-bit Unicode" },
+ { "UTF-8 [CP-1252]" , 1 , 1 , "I: 8-bit Unicode / Western, CP, O: 8-bit Unicode" },
+
+ { "UTF-8 [CP-1253]" , 1 , 1 , "I: 8-bit Unicode / Greek, CP, O: 8-bit Unicode" },
+ { "UTF-8 [CP-1256]" , 1 , 1 , "I: 8-bit Unicode / Arabic, CP, O: 8-bit Unicode" },
+ { "UTF-8 [CP-1257]" , 1 , 1 , "I: 8-bit Unicode / Baltic, CP, O: 8-bit Unicode" },
+ { "UTF-8 [CP-1255]" , 1 , 1 , "I: 8-bit Unicode / Hebrew, CP, O: 8-bit Unicode" },
+
+ { "UTF-8 [CP-1254]" , 1 , 1 , "I: 8-bit Unicode / Turkish, CP, O: 8-bit Unicode" },
+ { "UTF-8 [TIS-620]" , 1 , 1 , "I: 8-bit Unicode / Thai, O: 8-bit Unicode" },
+#ifndef QT_NO_BIG_CODECS
+ { "UTF-8 [Big5]" , 1 , 1 , "I: 8-bit Unicode / Chinese Traditional, O: 8-bit Unicode" },
+ { "UTF-8 [Big5-HKSCS]" , 1 , 1 , "I: 8-bit Unicode / Chinese Traditional, Hong Kong, O: 8-bit Unicode" },
+
+ { "UTF-8 [GB18030]" , 1 , 1 , "I: 8-bit Unicode / Chinese Simplified, O: 8-bit Unicode" },
+ { "UTF-8 [JIS7]" , 1 , 1 , "I: 8-bit Unicode / Japanese (JIS7), O: 8-bit Unicode" },
+ { "UTF-8 [Shift-JIS]" , 1 , 1 , "I: 8-bit Unicode / Japanese (Shift-JIS), O: Japanese (Shift-JIS)" },
+ { "UTF-8 [EUC-JP]" , 1 , 1 , "I: 8-bit Unicode / Japanese (EUC-JP), O: Japanese (EUC-JP)" },
+
+ { "UTF-8 [EUC-KR]" , 1 , 1 , "I: 8-bit Unicode / Korean, O: 8-bit Unicode" },
+ { "UTF-8 [TSCII]" , 1 , 1 , "I: 8-bit Unicode / Tamil, O: 8-bit Unicode" },
+#endif
+ { "UTF-8 [ISO-8859-10]" , 1 , 1 , "I: 8-bit Unicode / ISO-8859-10, O: 8-bit Unicode" },
+ { "UTF-8 [ISO-8859-13]" , 1 , 1 , "I: 8-bit Unicode / ISO-8859-13, O: 8-bit Unicode" },
+
+ { "UTF-8 [ISO-8859-14]" , 1 , 1 , "I: 8-bit Unicode / ISO-8859-14, O: 8-bit Unicode" },
+ { "UTF-8 [IBM-850]" , 1 , 1 , "I: 8-bit Unicode / IBM-850, O: 8-bit Unicode" },
+ { "UTF-8 [IBM-866]" , 1 , 1 , "I: 8-bit Unicode / IBM-866, O: 8-bit Unicode" },
+ { "UTF-8 [CP874]" , 1 , 1 , "I: 8-bit Unicode / CP874, O: 8-bit Unicode" },
+
+ { 0 , 0 , 0 , 0 }
+ };
+
+ EncodingDescription * encodingDescription(int iIdx)
+ {
+ if(iIdx > NUM_ENCODINGS)return &(supported_encodings[NUM_ENCODINGS]);
+ return &(supported_encodings[iIdx]);
+ }
+
+ QTextCodec * codecForName(const char * szName)
+ {
+ KviStr szTmp = szName;
+ int idx = szTmp.findFirstIdx('[');
+ if(idx != -1)
+ {
+ // composite codec: either UTF-8 [child codec] or child codec [UTF-8]
+ KviSmartTextCodec * c = g_pSmartCodecDict->find(szName);
+ if(c)return c;
+
+
+ if(kvi_strEqualCIN("UTF-8 [",szName,7))
+ {
+ szTmp.replaceAll("UTF-8 [","");
+ szTmp.replaceAll("]","");
+ // smart codec that sends UTF-8
+ c = new KviSmartTextCodec(szName,szTmp.ptr(),true);
+ } else {
+ szTmp.cutFromFirst(' ');
+ // smart codec that sends child encoding
+ c = new KviSmartTextCodec(szName,szTmp.ptr(),false);
+ }
+ if(c->ok())
+ {
+ g_pSmartCodecDict->replace(szName,c);
+ return c;
+ } else {
+ delete c;
+ }
+ }
+ return QTextCodec::codecForName(szName);
+ }
+
+ const KviStr & localeName()
+ {
+ return g_szLang;
+ }
+
+ bool loadCatalogue(const QString &name,const QString &szLocaleDir)
+ {
+ //debug("Looking up catalogue %s",name);
+ if(g_pCatalogueDict->find(KviQString::toUtf8(name).data()))return true; // already loaded
+
+ QString szBuffer;
+
+ if(findCatalogue(szBuffer,name,szLocaleDir))
+ {
+ KviMessageCatalogue * c = new KviMessageCatalogue();
+ if(c->load(szBuffer))
+ {
+ //debug("KviLocale: loaded catalogue %s",name);
+ g_pCatalogueDict->insert(KviQString::toUtf8(name).data(),c);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool unloadCatalogue(const QString &name)
+ {
+ //debug("Unloading catalogue : %s",name);
+ return g_pCatalogueDict->remove(KviQString::toUtf8(name).data());
+ }
+
+ bool findCatalogue(QString &szBuffer,const QString& name,const QString& szLocaleDir)
+ {
+ KviStr szLocale = g_szLang;
+
+ QString szLocDir = szLocaleDir;
+ KviQString::ensureLastCharIs(szLocDir,KVI_PATH_SEPARATOR_CHAR);
+
+ KviQString::sprintf(szBuffer,"%Q%Q_%s.mo",&szLocDir,&name,szLocale.ptr());
+
+ if(KviFileUtils::fileExists(szBuffer))return true;
+
+ if(szLocale.findFirstIdx('.') != -1)
+ {
+ // things like en_GB.utf8
+ // kill them
+ szLocale.cutFromFirst('.');
+
+ KviQString::sprintf(szBuffer,"%Q%Q_%s.mo",&szLocDir,&name,szLocale.ptr());
+ if(KviFileUtils::fileExists(szBuffer))return true;
+ }
+
+ if(szLocale.findFirstIdx('@') != -1)
+ {
+ // things like @euro ?
+ // kill them
+ szLocale.cutFromFirst('@');
+ KviQString::sprintf(szBuffer,"%Q%Q_%s.mo",&szLocDir,&name,szLocale.ptr());
+ if(KviFileUtils::fileExists(szBuffer))return true;
+ }
+
+ if(szLocale.findFirstIdx('_') != -1)
+ {
+ // things like en_GB
+ // kill them
+ szLocale.cutFromFirst('_');
+ KviQString::sprintf(szBuffer,"%Q%Q_%s.mo",&szLocDir,&name,szLocale.ptr());
+ if(KviFileUtils::fileExists(szBuffer))return true;
+ }
+
+ // try the lower case version too
+ szLocale.toLower();
+ KviQString::sprintf(szBuffer,"%Q%Q_%s.mo",&szLocDir,&name,szLocale.ptr());
+ if(KviFileUtils::fileExists(szBuffer))return true;
+
+ return false;
+ }
+
+ //
+ // This function attempts to determine the current locale
+ // and then load the corresponding translation file
+ // from the KVIrc locale directory
+ // Returns true if the locale was correctly set
+ // i.e. the locale is C or POSIX (no translation needed)
+ // or the locale is correctly defined and the
+ // translation map was sucesfully loaded
+ //
+
+ void init(QApplication * app,const QString &localeDir)
+ {
+ // first of all try to find out the current locale
+ g_szLang="";
+#ifdef COMPILE_USE_QT4
+ QString szLangFile=QString("%1/.kvirc_force_locale").arg(QDir::homePath());
+#else
+ QString szLangFile=QString("%1/.kvirc_force_locale").arg(QDir::homeDirPath());
+#endif
+ if(KviFileUtils::fileExists(szLangFile))
+ {
+ QString szTmp;
+ KviFileUtils::readFile(szLangFile,szTmp);
+ g_szLang=szTmp;
+ }
+ if(g_szLang.isEmpty())g_szLang = kvi_getenv("KVIRC_LANG");
+#ifdef COMPILE_USE_QT4
+ if(g_szLang.isEmpty())g_szLang = QLocale::system().name();
+#else
+ if(g_szLang.isEmpty())g_szLang = QTextCodec::locale();
+#endif
+ if(g_szLang.isEmpty())g_szLang = kvi_getenv("LC_MESSAGES");
+ if(g_szLang.isEmpty())g_szLang = kvi_getenv("LANG");
+ if(g_szLang.isEmpty())g_szLang = "en";
+ g_szLang.stripWhiteSpace();
+
+ // the main catalogue is supposed to be kvirc_<language>.mo
+ g_pMainCatalogue = new KviMessageCatalogue();
+ // the catalogue dict
+ g_pCatalogueDict = new KviPointerHashTable<const char *,KviMessageCatalogue>;
+ g_pCatalogueDict->setAutoDelete(true);
+
+ // the smart codec dict
+ g_pSmartCodecDict = new KviPointerHashTable<const char *,KviSmartTextCodec>;
+ // the Qt docs explicitly state that we shouldn't delete
+ // the codecs by ourselves...
+ g_pSmartCodecDict->setAutoDelete(false);
+
+ if(g_szLang.hasData())
+ {
+ QString szBuffer;
+ if(findCatalogue(szBuffer,"kvirc",localeDir))
+ {
+ g_pMainCatalogue->load(szBuffer);
+ g_pTranslator = new KviTranslator(app,"kvirc_translator");
+ app->installTranslator(g_pTranslator);
+ } else {
+ KviStr szTmp = g_szLang;
+ szTmp.cutFromFirst('.');
+ szTmp.cutFromFirst('_');
+ szTmp.cutFromFirst('@');
+ szTmp.toLower();
+ if(!(kvi_strEqualCI(szTmp.ptr(),"en") ||
+ kvi_strEqualCI(szTmp.ptr(),"c") ||
+ kvi_strEqualCI(szTmp.ptr(),"us") ||
+ kvi_strEqualCI(szTmp.ptr(),"gb") ||
+ kvi_strEqualCI(szTmp.ptr(),"posix")))
+ {
+ // FIXME: THIS IS NO LONGER VALID!!!
+ debug("Can't find the catalogue for locale \"%s\" (%s)",g_szLang.ptr(),szTmp.ptr());
+ debug("There is no such translation or the $LANG variable was incorrectly set");
+ debug("You can use $KVIRC_LANG to override the catalogue name");
+ debug("For example you can set KVIRC_LANG to it_IT to force usage of the it.mo catalogue");
+ }
+ }
+ }
+
+ //g_pTextCodec = QTextCodec::codecForLocale();
+ //if(!g_pTextCodec)g_pTextCodec = QTextCodec::codecForLocale();
+ }
+
+ void done(QApplication * app)
+ {
+ delete g_pMainCatalogue;
+ delete g_pCatalogueDict;
+ delete g_pSmartCodecDict;
+ g_pMainCatalogue = 0;
+ g_pCatalogueDict = 0;
+ g_pSmartCodecDict = 0;
+ if(g_pTranslator)
+ {
+ app->removeTranslator(g_pTranslator);
+ delete g_pTranslator;
+ g_pTranslator = 0;
+ }
+ }
+
+ KviMessageCatalogue * getLoadedCatalogue(const QString& name)
+ {
+ return g_pCatalogueDict->find(KviQString::toUtf8(name).data());
+ }
+
+
+ const char * translate(const char * text,const char * context)
+ {
+ if(context)
+ {
+ KviMessageCatalogue * c = g_pCatalogueDict->find(context);
+ if(!c)
+ {
+ // FIXME: Should really try to load the catalogue here!
+ c = new KviMessageCatalogue();
+ g_pCatalogueDict->insert(context,c);
+ }
+ return c->translate(text);
+ }
+ return g_pMainCatalogue->translate(text);
+ }
+
+ const QString & translateToQString(const char * text,const char * context)
+ {
+ if(context)
+ {
+ KviMessageCatalogue * c = g_pCatalogueDict->find(context);
+ if(!c)
+ {
+ // FIXME: Should really try to load the catalogue here!
+ c = new KviMessageCatalogue();
+ g_pCatalogueDict->insert(context,c);
+ }
+ return c->translateToQString(text);
+ }
+ return g_pMainCatalogue->translateToQString(text);
+ }
+};
+
+KviTranslator::KviTranslator(QObject * par,const char * nam)
+#ifdef COMPILE_USE_QT4
+: QTranslator(par)
+#else
+: QTranslator(par,nam)
+#endif
+{
+}
+
+KviTranslator::~KviTranslator()
+{
+}
+
+#ifdef COMPILE_USE_QT4
+QString KviTranslator::translate(const char *context,const char * message,const char * comment) const
+{
+ // we ignore contexts and comments for qt translations
+ return g_pMainCatalogue->translateToQString(message);
+}
+#endif
+
+QString KviTranslator::find(const char *context,const char * message) const
+{
+ // we ignore contexts for qt translations
+ return g_pMainCatalogue->translateToQString(message);
+}
+
+#ifndef COMPILE_USE_QT4
+QTranslatorMessage KviTranslator::findMessage(const char * context,const char * sourceText,const char * comment) const
+{
+ // we ignore contexts for qt translations
+ return QTranslatorMessage(context,sourceText,comment,g_pMainCatalogue->translateToQString(sourceText));
+}
+#endif
+
+#if 0
+
+// a fake table that will force these translations
+// to be included in the *.pot file
+
+static QString fake_translations_table[]=
+{
+ // global
+ __tr2qs("OK"),
+ __tr2qs("Cancel"),
+ // color dialog
+ __tr2qs("Select color"),
+ __tr2qs("&Basic colors"),
+ __tr2qs("&Custom colors"),
+ __tr2qs("&Red"),
+ __tr2qs("&Green"),
+ __tr2qs("Bl&ue"),
+ __tr2qs("&Define Custom Colors >>"),
+ __tr2qs("&Add to Custom Colors"),
+ // font dialog
+ __tr2qs("Select Font"),
+ __tr2qs("&Font"),
+ __tr2qs("Font st&yle"),
+ __tr2qs("&Size"),
+ __tr2qs("Sample"),
+ __tr2qs("Effects"),
+ __tr2qs("Stri&keout"),
+ __tr2qs("&Underline"),
+ __tr2qs("Scr&ipt"),
+ //File selector
+ __tr2qs("Parent Directory"),
+ __tr2qs("Back"),
+ __tr2qs("Forward"),
+ __tr2qs("Reload"),
+ __tr2qs("New Directory"),
+ __tr2qs("Bookmarks"),
+ __tr2qs("Add Bookmark"),
+ __tr2qs("&Edit Bookmarks"),
+ __tr2qs("New Bookmark Folder..."),
+ __tr2qs("Configure"),
+ __tr2qs("Sorting"),
+ __tr2qs("By Name"),
+ __tr2qs("By Date"),
+ __tr2qs("By Size"),
+ __tr2qs("Reverse"),
+ __tr2qs("Directories First"),
+ __tr2qs("Case Insensitive"),
+ __tr2qs("Short View"),
+ __tr2qs("Detailed View"),
+ __tr2qs("Show Hidden Files"),
+ __tr2qs("Show Quick Access Navigation Panel"),
+ __tr2qs("Show Preview"),
+ __tr2qs("Separate Directories"),
+ __tr2qs("Often used directories"),
+ __tr2qs("Desktop"),
+ __tr2qs("Home Directory"),
+ __tr2qs("Floppy"),
+ __tr2qs("Temporary Files"),
+ __tr2qs("Network"),
+ __tr2qs("New Directory..."),
+ __tr2qs("Delete"),
+ __tr2qs("Thumbnail Previews"),
+ __tr2qs("Large Icons"),
+ __tr2qs("Small Icons"),
+ __tr2qs("Properties..."),
+ __tr2qs("&Automatic Preview"),
+ __tr2qs("&Preview"),
+ __tr2qs("&Location:"),
+ __tr2qs("&Filter:"),
+ __tr2qs("All Files"),
+ __tr2qs("&OK"),
+ __tr2qs("&Cancel")
+
+}
+
+#endif
diff --git a/src/kvilib/system/kvi_locale.h b/src/kvilib/system/kvi_locale.h
new file mode 100644
index 00000000..bc3ed8eb
--- /dev/null
+++ b/src/kvilib/system/kvi_locale.h
@@ -0,0 +1,146 @@
+#ifndef _KVI_LOCALE_H_
+#define _KVI_LOCALE_H_
+
+//=============================================================================
+//
+// File : kvi_locale.h
+// Creation date : Sat Jan 16 1999 18:15:01 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_string.h"
+#include "kvi_pointerhashtable.h"
+
+#include <qapplication.h>
+
+class QTextCodec;
+class KviMessageCatalogue;
+
+namespace KviLocale
+{
+ typedef struct _EncodingDescription
+ {
+ char * szName;
+ char bSmart; // is it a smart codec ?
+ char bSendUtf8; // does it send utf8 or the local charset ?
+ char * szDescription;
+ } EncodingDescription;
+
+ // you MUST start iterating from 0 and terminate when
+ // you get an entry with a NULL szName
+ KVILIB_API EncodingDescription * encodingDescription(int iIdx);
+ KVILIB_API QTextCodec * codecForName(const char * szName);
+ KVILIB_API const KviStr & localeName();
+ KVILIB_API bool findCatalogue(QString &szBuffer,const QString& name,const QString& szLocaleDir);
+ KVILIB_API bool loadCatalogue(const QString& name,const QString& szLocaleDir);
+ KVILIB_API KviMessageCatalogue * getLoadedCatalogue(const QString& name);
+ KVILIB_API bool unloadCatalogue(const QString& name);
+ KVILIB_API void init(QApplication * app,const QString& localeDir);
+ KVILIB_API void done(QApplication * app);
+ KVILIB_API const char * translate(const char * text,const char * context);
+ KVILIB_API const QString & translateToQString(const char * text,const char * context);
+};
+
+// not exported
+class KviTranslationEntry
+{
+public:
+ KviStr m_szKey;
+ KviStr m_szEncodedTranslation;
+ QString * m_pQTranslation;
+public:
+ KviTranslationEntry(char * keyptr,int keylen,char * trptr,int trlen)
+ : m_szKey(keyptr,keylen) , m_szEncodedTranslation(trptr,trlen)
+ {
+ m_pQTranslation = 0;
+ }
+
+ KviTranslationEntry(const char * keyandtr)
+ : m_szKey(keyandtr) , m_szEncodedTranslation(keyandtr)
+ {
+ m_pQTranslation = 0;
+ }
+
+ ~KviTranslationEntry()
+ {
+ if(m_pQTranslation)delete m_pQTranslation;
+ }
+};
+
+
+class KVILIB_API KviMessageCatalogue
+{
+public:
+ KviMessageCatalogue();
+ ~KviMessageCatalogue();
+protected:
+ //KviPointerHashTable<const char *,KviTranslationEntry> * m_pMessages;
+ KviPointerHashTable<const char *,KviTranslationEntry> * m_pMessages;
+ QTextCodec * m_pTextCodec;
+public:
+ bool load(const QString& name);
+ const char * translate(const char * text);
+ const QString & translateToQString(const char * text);
+};
+
+#ifndef _KVI_LOCALE_CPP_
+ extern KVILIB_API KviMessageCatalogue * g_pMainCatalogue;
+#endif // !_KVI_LOCALE_CPP_
+
+#define __tr(__text__) g_pMainCatalogue->translate(__text__)
+#define __tr_no_lookup(__text__) __text__
+#define __tr_no_xgettext(__text__) g_pMainCatalogue->translate(__text__)
+
+#define __tr2qs(__text__) g_pMainCatalogue->translateToQString(__text__)
+#define __tr2qs_no_xgettext(__text__) g_pMainCatalogue->translateToQString(__text__)
+
+#define __tr_ctx(__text__,__context__) KviLocale::translate(__text__,__context__)
+#define __tr_no_lookup_ctx(__text__,__context__) __text__
+#define __tr_no_xgettext_ctx(__text__,__context__) KviLocale::translate(__text__,__context__)
+#define __tr2qs_ctx(__text__,__context__) KviLocale::translateToQString(__text__,__context__)
+#define __tr2qs_ctx_no_xgettext(__text__,__context__) KviLocale::translateToQString(__text__,__context__)
+#define __tr2qs_no_lookup(__text__) __text__
+
+#include <qtranslator.h>
+#include <qstring.h>
+
+class KVILIB_API KviTranslator : public QTranslator
+{
+ Q_OBJECT
+ public:
+ KviTranslator(QObject * parent,const char * name);
+ ~KviTranslator();
+ public:
+#ifdef COMPILE_USE_QT4
+ virtual QString translate(const char * context,const char * message,const char * comment) const;
+#endif
+ // Deprecated in qt 4.x
+ virtual QString find(const char * context,const char * message) const;
+#ifndef COMPILE_USE_QT4
+ // Dead in qt 4.x
+ virtual QTranslatorMessage findMessage(const char * context,const char * sourceText,const char * comment = 0) const;
+#endif
+};
+
+
+#endif //!_KVI_LOCALE_H_
diff --git a/src/kvilib/system/kvi_process.h b/src/kvilib/system/kvi_process.h
new file mode 100644
index 00000000..ea2275dc
--- /dev/null
+++ b/src/kvilib/system/kvi_process.h
@@ -0,0 +1,37 @@
+#ifndef _KVI_PROCESS_H_
+#define _KVI_PROCESS_H_
+//=============================================================================
+//
+// File : kvi_process.h
+// Creation date : Tue Jan 30 2007 04:05:41 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_USE_QT4
+ #include <q3process.h>
+ #define KviProcess Q3Process
+#else
+ #include <qprocess.h>
+ #define KviProcess QProcess
+#endif
+
+#endif //!_KVI_PROCESS_H_
diff --git a/src/kvilib/system/kvi_stdarg.h b/src/kvilib/system/kvi_stdarg.h
new file mode 100644
index 00000000..15c5e078
--- /dev/null
+++ b/src/kvilib/system/kvi_stdarg.h
@@ -0,0 +1,65 @@
+#ifndef _KVI_STDARG_H_
+#define _KVI_STDARG_H_
+
+//=============================================================================
+//
+// File : kvi_stdarg.h
+// Creation date : Sat Jan 03 2004 02:08:14 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include <stdarg.h>
+
+#define kvi_va_list va_list
+#define kvi_va_start va_start
+//
+// kvi_va_start_by_reference should be used when the last known argument
+// is a reference type and not a pointer
+//
+// int SomeClass::sprintf(const QString &fmt,...)
+// {
+// kvi_va_list list;
+// kvi_va_start_by_reference(list,fmt);
+// ...
+// }
+//
+//
+#ifdef COMPILE_ON_WINDOWS
+ #define kvi_va_start_by_reference(__list,__arg) \
+ { \
+ int supercalifragilisticoespiralidoso=_INTSIZEOF(__arg); \
+ __asm lea eax,__arg \
+ __asm add eax,supercalifragilisticoespiralidoso \
+ __asm mov __list,eax \
+ }
+#elif defined(__GNUC__)
+ // gcc doesn't use the second argument
+ // so we just fool it to avoid the warnings
+ #define kvi_va_start_by_reference(__list,__arg) va_start(__list,((const char *)(&(__arg))))
+#else
+ #define kvi_va_start_by_reference va_start
+#endif
+#define kvi_va_arg va_arg
+#define kvi_va_end va_end
+
+
+
+#endif //_KVI_STDARG_H_
diff --git a/src/kvilib/system/kvi_thread.cpp b/src/kvilib/system/kvi_thread.cpp
new file mode 100644
index 00000000..e9ec3ac5
--- /dev/null
+++ b/src/kvilib/system/kvi_thread.cpp
@@ -0,0 +1,644 @@
+//=============================================================================
+//
+// File : kvi_thread.cpp
+// Creation date : Tue Jul 6 1999 16:04:45 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+
+
+#ifndef _GNU_SOURCE
+ #define _GNU_SOURCE
+#endif
+
+#include "kvi_thread.h"
+
+#ifdef COMPILE_ON_WINDOWS
+ #include <io.h> // for _pipe()
+#else
+ #include <unistd.h> //for pipe() and other tricks
+ #include <signal.h> // on Windows it is useless
+ #include <fcntl.h>
+#endif
+
+#include <errno.h>
+
+
+#include "kvi_string.h"
+#include "kvi_settings.h"
+#include "kvi_error.h"
+
+
+#include <qapplication.h>
+
+
+static void kvi_threadIgnoreSigalarm()
+{
+ // On Windows this stuff is useless anyway
+#ifdef COMPILE_IGNORE_SIGALARM
+ #ifndef COMPILE_ON_WINDOWS
+ // Funky hack for some Solaris machines (maybe others ?)
+ // For an obscure (at least to me) reason
+ // when using threads ,some part of the system
+ // starts kidding us by sending a SIGALRM in apparently
+ // "random" circumstances. (Xlib ?) (XServer ?)
+ // The default action for SIGALRM is to exit the application.
+ // Could not guess more about this stuff...
+ // Here goes a "blind" hack for that.
+
+ // Update: now we have an explaination too
+ //
+ // From: "Andre Stechert" (astechert at email dot com)
+ // To: pragma at kvirc dot net
+ // Subject: sigalarm on solaris ...
+ // Date: 26/7/2005 09:36
+
+ // Hi,
+ //    I noticed in your readme that you were having problems with sigalarm
+ // in your solaris port and you weren't sure why.  I quickly scanned your
+ // source code and noticed that you use usleep and threads.  That's the problem,
+ // if you haven't already figured it out. On Solaris, usleep is implemented with
+ // SIGALARM. So is threading. So if you the active thread changes while
+ // a usleep is in progress, bang, the process is dead.
+ //
+ // There is no real feedback on this at the moment: if somebody
+ // experiences the problems please drop me a mail at pragma at kvirc dot net
+ // and we'll try to look for a better solution.
+ // If the explaination is correct then KVIrc could even lock up on those machines
+ // (never returning from an usleep() call ?)...
+
+ struct sigaction ignr_act;
+ ignr_act.sa_handler = SIG_IGN;
+ sigemptyset(&ignr_act.sa_mask);
+
+ #ifdef SA_NOMASK
+ ignr_act.sa_flags = SA_NOMASK;
+ #else
+ ignr_act.sa_flags = 0;
+ #endif
+
+ #ifdef SA_RESTART
+ ignr_act.sa_flags |= SA_RESTART;
+ #endif
+
+ if(sigaction(SIGALRM,&ignr_act,0) == -1)debug("Failed to set SIG_IGN for SIGALRM.");
+ #endif
+#endif
+}
+
+#ifndef COMPILE_ON_WINDOWS
+
+static void kvi_threadSigpipeHandler(int)
+{
+ debug("Thread ????: Caught SIGPIPE: ignoring.");
+}
+
+#endif
+
+static void kvi_threadCatchSigpipe()
+{
+ // On windows this stuff is useless
+#ifndef COMPILE_ON_WINDOWS
+ struct sigaction act;
+ act.sa_handler=&kvi_threadSigpipeHandler;
+ sigemptyset(&(act.sa_mask));
+ sigaddset(&(act.sa_mask), SIGPIPE);
+ // CC: take care of SunOS which automatically restarts interrupted system
+ // calls (and thus does not have SA_RESTART)
+#ifdef SA_NOMASK
+ act.sa_flags = SA_NOMASK;
+#else
+ act.sa_flags = 0;
+#endif
+
+#ifdef SA_RESTART
+ act.sa_flags |= SA_RESTART;
+#endif
+
+ if(sigaction(SIGPIPE,&act,0L) == -1)debug("Failed to set the handler for SIGPIPE.");
+#endif
+}
+
+static void kvi_threadInitialize()
+{
+#ifndef COMPILE_ON_WINDOWS
+ kvi_threadIgnoreSigalarm();
+ kvi_threadCatchSigpipe();
+#endif
+}
+
+
+
+#define KVI_THREAD_PIPE_SIDE_MASTER 0
+#define KVI_THREAD_PIPE_SIDE_SLAVE 1
+
+// the maximum length of the slave->master queue
+// over this length , the slave is forced to usleep()
+#define KVI_THREAD_MAX_EVENT_QUEUE_LENGTH 50
+
+static KviThreadManager * g_pThreadManager = 0;
+
+void KviThreadManager::globalInit()
+{
+ kvi_threadInitialize(); // we want this to apply to the main thread too
+ g_pThreadManager = new KviThreadManager();
+}
+
+void KviThreadManager::globalDestroy()
+{
+ delete g_pThreadManager;
+ g_pThreadManager = 0;
+}
+
+KviThreadManager::KviThreadManager()
+: QObject()
+{
+ if(g_pThreadManager)debug("Hey...what are ya doing ?");
+
+
+ m_pMutex = new KviMutex();
+ m_pThreadList = new KviPointerList<KviThread>;
+ m_pThreadList->setAutoDelete(false);
+
+ m_iWaitingThreads = 0;
+
+#ifndef COMPILE_ON_WINDOWS
+
+ m_iTriggerCount = 0;
+
+ m_pEventQueue = new KviPointerList<KviThreadPendingEvent>;
+ m_pEventQueue->setAutoDelete(true);
+
+ if(pipe(m_fd) != 0)
+ {
+ debug("Ops...thread manager pipe creation failed (%s)",KviQString::toUtf8(KviError::getDescription(KviError::translateSystemError(errno))).data());
+ }
+
+ if(fcntl(m_fd[KVI_THREAD_PIPE_SIDE_SLAVE],F_SETFL,O_NONBLOCK) == -1)
+ {
+ debug("Ops...thread manager slave pipe initialisation failed (%s)",KviQString::toUtf8(KviError::getDescription(KviError::translateSystemError(errno))).data());
+ }
+
+ if(fcntl(m_fd[KVI_THREAD_PIPE_SIDE_MASTER],F_SETFL,O_NONBLOCK) == -1)
+ {
+ debug("Ops...thread manager master pipe initialisation failed (%s)",KviQString::toUtf8(KviError::getDescription(KviError::translateSystemError(errno))).data());
+ }
+
+ m_pSn = new QSocketNotifier(m_fd[KVI_THREAD_PIPE_SIDE_MASTER],QSocketNotifier::Read);
+ connect(m_pSn,SIGNAL(activated(int)),this,SLOT(eventsPending(int)));
+ m_pSn->setEnabled(true);
+#endif
+}
+
+
+KviThreadManager::~KviThreadManager()
+{
+ m_pMutex->lock();
+ // Terminate all the slaves
+ while(KviThread *t = m_pThreadList->first())
+ {
+ m_pMutex->unlock();
+ delete t;
+ m_pMutex->lock();
+ }
+
+ // there are no more child threads
+ // thus no more slave events are sent.
+ // Disable the socket notifier, we no longer need it
+#ifndef COMPILE_ON_WINDOWS
+ m_pSn->setEnabled(false);
+ delete m_pSn;
+ m_pSn = 0;
+#endif
+
+ // we're no longer in this world
+ g_pThreadManager = 0;
+
+#ifndef COMPILE_ON_WINDOWS
+ // close the pipes
+ close(m_fd[KVI_THREAD_PIPE_SIDE_SLAVE]);
+ close(m_fd[KVI_THREAD_PIPE_SIDE_MASTER]);
+ // Kill the pending events
+ while(KviThreadPendingEvent *ev = m_pEventQueue->first())
+ {
+ delete ev->e;
+ m_pEventQueue->removeFirst();
+ }
+ delete m_pEventQueue;
+ m_pEventQueue = 0;
+#endif
+
+ m_pMutex->unlock();
+
+ // finish the cleanup
+ delete m_pMutex;
+ m_pMutex = 0;
+ delete m_pThreadList;
+ m_pThreadList = 0;
+
+ // byez :)
+}
+
+void KviThreadManager::killPendingEvents(QObject * receiver)
+{
+#ifndef COMPILE_ON_WINDOWS
+ if(!g_pThreadManager)return;
+ g_pThreadManager->killPendingEventsByReceiver(receiver);
+#endif
+}
+
+void KviThreadManager::killPendingEventsByReceiver(QObject * receiver)
+{
+#ifndef COMPILE_ON_WINDOWS
+ KviPointerList<KviThreadPendingEvent> l;
+ l.setAutoDelete(false);
+ m_pMutex->lock();
+ for(KviThreadPendingEvent * ev = m_pEventQueue->first();ev;ev = m_pEventQueue->next())
+ {
+ if(ev->o == receiver)l.append(ev);
+ }
+ for(KviThreadPendingEvent * ev = l.first();ev;ev = l.next())
+ {
+ delete ev->e;
+ m_pEventQueue->removeRef(ev);
+ }
+ m_pMutex->unlock();
+#endif
+}
+
+void KviThreadManager::registerSlaveThread(KviThread *t)
+{
+ m_pMutex->lock();
+ m_pThreadList->append(t);
+ m_pMutex->unlock();
+}
+
+void KviThreadManager::unregisterSlaveThread(KviThread *t)
+{
+ m_pMutex->lock();
+ m_pThreadList->removeRef(t);
+ m_pMutex->unlock();
+}
+
+void KviThreadManager::postSlaveEvent(QObject *o,QEvent *e)
+{
+#ifdef COMPILE_ON_WINDOWS
+ QApplication::postEvent(o,e); // we believe this to be thread-safe
+#else
+ KviThreadPendingEvent * ev = new KviThreadPendingEvent;
+ ev->o = o;
+ ev->e = e;
+
+ m_pMutex->lock();
+
+ // if the queue gets too long , make this (slave) thread sleep
+
+ // there is a special case where we can't stop the slaves posting events
+ // it's when a thread-master-side is waiting for it's thread-slave-side
+ // it the thread-master-side runs in the application main thread then
+ // the main thread is sleeping and can't process events.
+ // Since we can't be really sure that the thread-master-side will be running
+ // on the main application thread we also can't artificially process the events.
+ // So the solution is to skip this algorithm when at least one
+ // thread is in waiting state.
+ while((m_pEventQueue->count() > KVI_THREAD_MAX_EVENT_QUEUE_LENGTH) && (m_iWaitingThreads < 1))
+ {
+ // wait for the master to process the queue
+
+ m_pMutex->unlock();
+
+ // WARNING : This will fail if for some reason
+ // the master thread gets here! It will wait indefinitely for itself
+ // if(pthread_self() != m_hMasterThread) ... ????
+
+#ifdef COMPILE_ON_WINDOWS
+ ::Sleep(1); // 1ms
+#else
+ // FIXME : use nanosleep() ?
+ ::usleep(1000); // 1 ms
+#endif
+ m_pMutex->lock();
+ }
+
+ m_pEventQueue->append(ev);
+ // Write bulk to the pipe... but only if there is no other wakeup pending
+ if(m_iTriggerCount < 1)
+ {
+ // I don't know if writing to a pipe is reentrant
+ // thus, in doubt, the write is interlocked (it's non blocking anyway)
+ int written = write(m_fd[KVI_THREAD_PIPE_SIDE_SLAVE],"?",1);
+ if(written < 1)
+ {
+ // ops.. failed to write down the event..
+ // this is quite irritating now...
+ debug("Ops.. failed to write down the trigger");
+ // FIXME: maybe a single shot timer ?
+ } else {
+ m_iTriggerCount++;
+ }
+ } // else no need to trigger : there is a wakeup pending in there
+
+ m_pMutex->unlock();
+
+#endif
+}
+
+void KviThreadManager::eventsPending(int fd)
+{
+#ifndef COMPILE_ON_WINDOWS
+ char buf[10];
+ // do we need to check for errors here ?
+ int readed = read(fd,buf,10);
+
+ m_pMutex->lock();
+ // welcome to the critical section :)
+
+ // grab the first event in the queue
+ while(KviThreadPendingEvent *ev = m_pEventQueue->first())
+ {
+ // allow the other threads to post events:
+ // unlock the event queue
+ m_pMutex->unlock();
+ // let the app process the event
+ // DANGER !
+ QApplication::postEvent(ev->o,ev->e);
+
+ // jump out of the loop if we have been destroyed
+ if(!g_pThreadManager)return;
+ // ufff... we're still alive :)))
+
+ // regrab the event queue
+ m_pMutex->lock();
+ // remove the event we have just processed
+ m_pEventQueue->removeRef(ev);
+ // here we're looping locked and havn't decremended the trigger count
+ }
+ // decrement the trigger count on the line: still atomic
+ if(readed >= 0)
+ {
+ if(readed < m_iTriggerCount)
+ {
+ m_iTriggerCount -= readed;
+ } else {
+ m_iTriggerCount = 0;
+ }
+ }
+
+ // ok , job done.. can relax now
+ m_pMutex->unlock();
+
+#endif
+}
+
+void KviThreadManager::threadEnteredWaitState()
+{
+ m_pMutex->lock();
+ m_iWaitingThreads++;
+ m_pMutex->unlock();
+}
+
+void KviThreadManager::threadLeftWaitState()
+{
+ m_pMutex->lock();
+ m_iWaitingThreads--;
+ if(m_iWaitingThreads < 0)
+ {
+ debug("Ops.. got a negative number of waiting threads ?");
+ m_iWaitingThreads = 0;
+ }
+ m_pMutex->unlock();
+}
+
+#ifndef COMPILE_ON_WINDOWS
+ bool KviMutex::locked()
+ {
+ if(!kvi_threadMutexTryLock(&m_mutex))return true;
+ kvi_threadMutexUnlock(&m_mutex);
+ return false;
+ }
+#endif
+
+#ifdef COMPILE_ON_WINDOWS
+DWORD WINAPI internal_start_thread(LPVOID arg)
+{
+ // Slave thread...
+ ((KviThread *)arg)->internalThreadRun_doNotTouchThis();
+ return 0;
+}
+#else
+static void * internal_start_thread(void * arg)
+{
+ // Slave thread...
+ ((KviThread *)arg)->internalThreadRun_doNotTouchThis();
+ return 0;
+}
+#endif
+
+KviThread::KviThread()
+{
+ g_pThreadManager->registerSlaveThread(this);
+ m_pRunningMutex = new KviMutex();
+ setRunning(false);
+ setStartingUp(false);
+}
+
+KviThread::~KviThread()
+{
+// debug(">> KviThread::~KviThread() : (this = %d)",this);
+ wait();
+ delete m_pRunningMutex;
+ g_pThreadManager->unregisterSlaveThread(this);
+// debug("<< KviThread::~KviThread() : (this = %d)",this);
+}
+
+void KviThread::setRunning(bool bRunning)
+{
+ m_pRunningMutex->lock();
+ m_bRunning = bRunning;
+ m_pRunningMutex->unlock();
+}
+
+void KviThread::setStartingUp(bool bStartingUp)
+{
+ m_pRunningMutex->lock();
+ m_bStartingUp = bStartingUp;
+ m_pRunningMutex->unlock();
+}
+
+bool KviThread::isRunning()
+{
+ bool bRunning = true;
+ m_pRunningMutex->lock();
+ bRunning = m_bRunning;
+ m_pRunningMutex->unlock();
+ return bRunning;
+}
+
+bool KviThread::isStartingUp()
+{
+ bool bIsStartingUp = true;
+ m_pRunningMutex->lock();
+ bIsStartingUp = m_bStartingUp;
+ m_pRunningMutex->unlock();
+ return bIsStartingUp;
+}
+
+bool KviThread::start()
+{
+ // We're on the master side thread here!
+ if(isStartingUp() || isRunning())return false;
+ setStartingUp(true);
+ return kvi_threadCreate(&m_thread,internal_start_thread,this);
+}
+
+void KviThread::wait()
+{
+ // We're on the master side here...and we're waiting the slave to exit
+// debug(">> KviThread::wait() (this=%d)",this);
+ while(isStartingUp())usleep(500); // sleep 500 microseconds
+// debug("!! KviThread::wait() (this=%d)",this);
+ g_pThreadManager->threadEnteredWaitState();
+ while(isRunning())
+ {
+ usleep(500); // sleep 500 microseconds
+ }
+ g_pThreadManager->threadLeftWaitState();
+// debug("<< KviThread::wait() (this=%d)",this);
+}
+
+void KviThread::exit()
+{
+ // We're on the slave side thread here! (m_bRunning is true , m_bStartingUp is false)
+ setRunning(false);
+ kvi_threadExit();
+}
+
+void KviThread::internalThreadRun_doNotTouchThis()
+{
+ // we're on the slave thread here!
+// debug(">> KviThread::internalRun (this=%d)",this);
+ setRunning(true);
+ setStartingUp(false);
+ kvi_threadInitialize();
+ run();
+ setRunning(false);
+// debug("<< KviThread::internalRun (this=%d",this);
+}
+
+void KviThread::usleep(unsigned long usec)
+{
+#ifdef COMPILE_ON_WINDOWS
+ int s = usec / 1000;
+ if(s < 1)s = 1;
+ ::Sleep(s); // Sleep one millisecond...this is the best that we can do
+#else
+ // FIXME : use nanosleep() ?
+ ::usleep(usec);
+#endif
+}
+
+void KviThread::msleep(unsigned long msec)
+{
+#ifdef COMPILE_ON_WINDOWS
+ ::Sleep(msec);
+#else
+ // FIXME : use nanosleep() ?
+ ::usleep(msec * 1000);
+#endif
+}
+
+void KviThread::sleep(unsigned long sec)
+{
+#ifdef COMPILE_ON_WINDOWS
+ ::Sleep(sec * 1000);
+#else
+ ::sleep(sec);
+#endif
+}
+
+void KviThread::postEvent(QObject * o,QEvent *e)
+{
+ // slave side
+ g_pThreadManager->postSlaveEvent(o,e);
+}
+
+
+
+KviSensitiveThread::KviSensitiveThread()
+: KviThread()
+{
+ m_pLocalEventQueueMutex = new KviMutex();
+ m_pLocalEventQueue = new KviPointerList<KviThreadEvent>;
+ m_pLocalEventQueue->setAutoDelete(false);
+}
+
+KviSensitiveThread::~KviSensitiveThread()
+{
+// debug("Entering KviSensitiveThread::~KviSensitiveThread (this=%d)",this);
+ terminate();
+// debug("KviSensitiveThread::~KviSensitiveThread : terminate called (This=%d)",this);
+ m_pLocalEventQueueMutex->lock();
+ m_pLocalEventQueue->setAutoDelete(true);
+ delete m_pLocalEventQueue;
+ m_pLocalEventQueue = 0;
+ m_pLocalEventQueueMutex->unlock();
+ delete m_pLocalEventQueueMutex;
+ m_pLocalEventQueueMutex = 0;
+// debug("Exiting KviSensitiveThread::~KviSensitiveThread (this=%d)",this);
+}
+
+void KviSensitiveThread::enqueueEvent(KviThreadEvent *e)
+{
+// debug(">>> KviSensitiveThread::enqueueEvent() (this=%d)",this);
+ m_pLocalEventQueueMutex->lock();
+ if(!m_pLocalEventQueue)
+ {
+ // ops...already terminated (???)...eat the event and return
+ delete e;
+ m_pLocalEventQueueMutex->unlock();
+ return;
+ }
+ m_pLocalEventQueue->append(e);
+ m_pLocalEventQueueMutex->unlock();
+// debug("<<< KviSensitiveThread::enqueueEvent() (this=%d)",this);
+}
+
+KviThreadEvent * KviSensitiveThread::dequeueEvent()
+{
+// debug(">>> KviSensitiveThread::dequeueEvent() (this=%d)",this);
+ KviThreadEvent * ret;
+ m_pLocalEventQueueMutex->lock();
+ ret = m_pLocalEventQueue->first();
+ if(ret)m_pLocalEventQueue->removeFirst();
+ m_pLocalEventQueueMutex->unlock();
+// debug("<<< KviSensitiveThread::dequeueEvent() (this=%d)",this);
+ return ret;
+}
+
+void KviSensitiveThread::terminate()
+{
+// debug("Entering KviSensitiveThread::terminate (this=%d)",this);
+ enqueueEvent(new KviThreadEvent(KVI_THREAD_EVENT_TERMINATE));
+// debug("KviSensitiveThread::terminate() : event enqueued waiting (this=%d)",this);
+ wait();
+// debug("Exiting KviSensitiveThread::terminate (this=%d)",this);
+}
+
diff --git a/src/kvilib/system/kvi_thread.h b/src/kvilib/system/kvi_thread.h
new file mode 100644
index 00000000..bd6dab3b
--- /dev/null
+++ b/src/kvilib/system/kvi_thread.h
@@ -0,0 +1,378 @@
+#ifndef _KVI_THREAD_H_
+#define _KVI_THREAD_H_
+//
+// File : kvi_thread.h
+// Creation date : Mon May 17 1999 04:26:41 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+#include "kvi_heapobject.h"
+#include "kvi_string.h"
+
+#include <qnamespace.h>
+#include <qobject.h>
+#include <qsocketnotifier.h>
+#include "kvi_pointerlist.h"
+#include <qevent.h>
+
+
+//
+// Simple thread implementation
+// This is enough for KVIrc needs
+// HANDLE WITH CARE
+//
+
+
+// Portability stuff
+
+#ifdef COMPILE_ON_WINDOWS
+
+ #include <winsock2.h> // this will pull in windows.h and will avoid windock.h inclusion
+ //#include <windows.h>
+ // Windoze thread abstraction layer
+ #define kvi_mutex_t HANDLE
+ inline void kvi_threadMutexInit(kvi_mutex_t * _pMutex_t)
+ {
+ *_pMutex_t = CreateMutex(0,0,NULL);
+ }
+ #define kvi_threadMutexLock(_pMutex_t) WaitForSingleObject(*_pMutex_t,INFINITE)
+ #define kvi_threadMutexUnlock(_pMutex_t) ReleaseMutex(*_pMutex_t)
+ #define kvi_threadMutexDestroy(_pMutex_t) CloseHandle(*_pMutex_t)
+ inline bool kvi_threadMutexTryLock(kvi_mutex_t *_pMutex_t)
+ {
+ return (WaitForSingleObject(*_pMutex_t,0) == WAIT_OBJECT_0);
+ }
+
+ #define kvi_thread_t HANDLE
+
+ inline bool kvi_threadCreate(kvi_thread_t *t,LPTHREAD_START_ROUTINE start_routine,void * arg)
+ {
+ DWORD dwThreadId;
+ *t = CreateThread(NULL,0,start_routine,arg,0,&dwThreadId);
+ return (*t != NULL);
+ }
+
+ #define kvi_threadExit() ExitThread(0)
+
+#else
+ #ifdef COMPILE_THREADS_USE_POSIX
+ // Glibc pthread implementation
+
+ #include <pthread.h>
+ #include <errno.h> // for EBUSY
+
+ // Mutex stuff
+ #define kvi_mutex_t pthread_mutex_t
+ #define kvi_threadMutexInit(_pMutex_t) pthread_mutex_init(_pMutex_t,0)
+ #define kvi_threadMutexLock(_pMutex_t) pthread_mutex_lock(_pMutex_t)
+ #define kvi_threadMutexUnlock(_pMutex_t) pthread_mutex_unlock(_pMutex_t)
+ #define kvi_threadMutexDestroy(_pMutex_t) pthread_mutex_destroy(_pMutex_t)
+ inline bool kvi_threadMutexTryLock(kvi_mutex_t *_pMutex_t)
+ {
+ return (pthread_mutex_trylock(_pMutex_t) != EBUSY);
+ }
+ // Actually unused
+ // #define kvi_threadMutexTryLock(_pMutex_t) pthread_mutex_trylock(_pMutex_t)
+
+ // Thread stuff
+ #define kvi_thread_t pthread_t
+
+ inline bool kvi_threadCreate(kvi_thread_t *t,void * (*start_routine)(void *),void * arg)
+ {
+ pthread_attr_t a;
+ pthread_attr_init(&a);
+ pthread_attr_setinheritsched(&a,PTHREAD_INHERIT_SCHED);
+ pthread_attr_setdetachstate(&a,PTHREAD_CREATE_DETACHED);
+
+ int ret = pthread_create(t,&a,start_routine,arg);
+
+ pthread_attr_destroy(&a);
+ return (ret == 0);
+ }
+
+ // We don't care about exit codes at all
+ #define kvi_threadExit() pthread_exit(0)
+ #else
+ #ifdef COMPILE_THREADS_USE_SOLARIS_LIBTHREAD
+ // Native solaris implementation
+ #include <thread.h>
+ #include <synch.h>
+ #include <errno.h>
+
+ // Mutex stuff
+ #define kvi_mutex_t mutex_t
+ #define kvi_threadMutexInit(_pMutex_t) mutex_init(_pMutex_t,0,0)
+ #define kvi_threadMutexLock(_pMutex_t) mutex_lock(_pMutex_t)
+ #define kvi_threadMutexUnlock(_pMutex_t) mutex_unlock(_pMutex_t)
+ #define kvi_threadMutexDestroy(_pMutex_t) mutex_destroy(_pMutex_t)
+ inline bool kvi_threadMutexTryLock(kvi_mutex_t *_pMutex_t)
+ {
+ return (mutex_trylock(_pMutex_t) != EBUSY);
+ };
+ // Actually unused
+ // #define kvi_threadMutexTryLock(_pMutex_t) mutex_trylock(_pMutex_t)
+
+ // Thread stuff
+ #define kvi_thread_t thread_t
+
+ inline bool kvi_threadCreate(kvi_thread_t *t,void * (*start_routine)(void *),void *arg)
+ {
+ return (thr_create(0,0,start_routine,arg,THR_DETACHED,t) == 0);
+ }
+
+ // We don't care about exit codes at all
+ #define kvi_threadExit() thr_exit(0)
+ #else
+// FIXME: #warning "Missing a decent thread implementation: we're going to fail , sorry!"
+ #endif
+ #endif
+#endif
+
+class KVILIB_API KviMutex : public KviHeapObject
+{
+private:
+ kvi_mutex_t m_mutex;
+#ifdef COMPILE_ON_WINDOWS
+ bool m_bLocked;
+#endif
+public:
+ KviMutex(){ kvi_threadMutexInit(&m_mutex); };
+ virtual ~KviMutex(){ kvi_threadMutexDestroy(&m_mutex); };
+public:
+#ifdef COMPILE_ON_WINDOWS
+ void lock(){ kvi_threadMutexLock(&m_mutex); m_bLocked = true; };
+ void unlock(){ m_bLocked = false; kvi_threadMutexUnlock(&m_mutex); };
+ bool locked(){ return m_bLocked; };
+#else
+ void lock(){ kvi_threadMutexLock(&m_mutex); };
+ void unlock(){ kvi_threadMutexUnlock(&m_mutex); };
+ bool locked();
+#endif
+};
+
+
+// simple thread class implementation
+// this is also called "Blind" thread class
+
+class KVILIB_API KviThread : public KviHeapObject
+{
+public:
+ KviThread();
+ virtual ~KviThread();
+private:
+ kvi_thread_t m_thread;
+ bool m_bRunning;
+ bool m_bStartingUp;
+ KviMutex * m_pRunningMutex;
+ KviPointerList<QEvent> * m_pLocalEventQueue;
+public:
+ // public KviThread interface
+ // HANDLE WITH CARE
+
+ // Runs the thread...call only from external threads!!! :)
+ // This function returns true if the child thread has been succesfully created
+ // this des not mean that run() is being already executed...
+ // isStartingUp() will return true from this moment until
+ // the child thread jumps into run() where it will be set to running state (isRunning() == true)
+ // and removed from startingUp state.
+ bool start();
+ // Returns the state of the thread...safe to call from anywhere
+ bool isRunning();
+ // Returns the state of the thread...safe to call from anywhere
+ bool isStartingUp(); // start() called , but not in run() yet...
+ // Waits for the termination of this thread: call only from external threads!!! :)
+ void wait();
+ // DO NOT TOUCH THIS ONE!
+ void internalThreadRun_doNotTouchThis();
+
+ static void sleep(unsigned long sec);
+ static void msleep(unsigned long msec);
+ static void usleep(unsigned long usec);
+protected:
+ // protected KviThread interface
+ // HANDLE WITH CARE TOO!
+
+ // Reimplement this with your job
+ virtual void run(){};
+ // Terminates the execution of the calling thread
+ void exit();
+ // The tricky part: threadsafe event dispatching
+ // Slave thread -> main thread objects
+ void postEvent(QObject *o,QEvent *e);
+private:
+ void setRunning(bool bRunning);
+ void setStartingUp(bool bStartingUp);
+};
+
+// QEvent::Type for Thread events
+#define KVI_THREAD_EVENT (((int)QEvent::User) + 2000)
+
+// CONSTANTS FOR KviThreadEvent::eventId();
+
+///////////////////////////////////////////////////////////////
+// extern -> slave thread
+
+// Your reimplementation of KviSensitiveThread MUST handle this
+// and exit when this event is received
+
+// Terminate is a plain KviThreadEvent
+#define KVI_THREAD_EVENT_TERMINATE 0
+
+///////////////////////////////////////////////////////////////
+// slave thread -> master object
+
+// The following standard events are sent from the thread to the master object
+
+// The following are plain KviThreadEvent objects
+#define KVI_THREAD_EVENT_SUCCESS 100
+
+// The following are KviThreadDataEvent<int>
+#define KVI_THREAD_EVENT_STATECHANGE 150
+
+// The following are KviThreadDataEvent<KviStr>
+#define KVI_THREAD_EVENT_MESSAGE 200
+#define KVI_THREAD_EVENT_WARNING 201
+#define KVI_THREAD_EVENT_ERROR 202
+#define KVI_THREAD_EVENT_DATA 203
+
+// The following is KviThreadDataEvent<KviDataBuffer>
+#define KVI_THREAD_EVENT_BINARYDATA 300
+
+// The user events
+#define KVI_THREAD_USER_EVENT_BASE 1000
+
+// #warning "Get rid of the m_szMessage member of KviThreadEvent : eventual data should be passed with a KviThreadDataEvent"
+
+// Base class for all thread events
+class KVILIB_API KviThreadEvent : public QEvent, public KviHeapObject
+{
+protected:
+ int m_eventId;
+ KviThread * m_pSender;
+public:
+ KviThreadEvent(int evId,KviThread * sender = 0)
+ : QEvent((QEvent::Type)KVI_THREAD_EVENT) , m_eventId(evId) , m_pSender(sender) {};
+ virtual ~KviThreadEvent(){};
+public:
+ // This is the sender of the event
+ // WARNING : this MAY be null , threads CAN send anonymous events
+ KviThread * sender(){ return m_pSender; };
+ int id(){ return m_eventId; };
+};
+
+template<class TData> class KviThreadDataEvent : public KviThreadEvent
+{
+protected:
+ TData * m_pData;
+public:
+ KviThreadDataEvent(int evId,TData * pData = 0,KviThread * sender = 0)
+ : KviThreadEvent(evId,sender){ m_pData = pData; };
+ virtual ~KviThreadDataEvent(){ if(m_pData)delete m_pData; };
+public:
+ void setData(TData * d){ if(m_pData)delete m_pData; m_pData = d; };
+ TData * getData(){ TData * aux = m_pData; m_pData = 0; return aux; };
+ TData * data(){ return m_pData; };
+};
+
+// A thread that has also an internal event queue
+// so events can be posted from the master side to the slave one
+// Reimplementations of this class should periodically check
+// dequeueEvent() and eventually process the incoming events (and then DELETE it)
+
+// KVI_THREAD_EVENT_TERMINATE should be always handled by the reimplementation
+// and it should always exit (cleanly) when this event is received
+
+
+class KVILIB_API KviSensitiveThread : public KviThread
+{
+public:
+ KviSensitiveThread();
+ virtual ~KviSensitiveThread();
+protected:
+ KviMutex * m_pLocalEventQueueMutex;
+ KviPointerList<KviThreadEvent> * m_pLocalEventQueue;
+public:
+ // enqueues an event directed to THIS thread
+ // the event must be allocated with NEW and
+ // will be destroyed on the slave side
+ void enqueueEvent(KviThreadEvent *e);
+ // enqueues a terminate event and waits() for the slave thread
+ // the slave thread MUST handle KVI_THREAD_EVENT_TERMINATE
+ void terminate();
+protected:
+ // slave side:
+ // returns the first event in the local queue
+ // the event MUST BE DELETED after processing
+ KviThreadEvent * dequeueEvent();
+};
+
+// =============================================================================================//
+// This is private stuff...only KviThread and KviApp may use it
+// and may call only specific functions...don't touch.
+
+typedef struct _KviThreadPendingEvent
+{
+ QObject *o;
+ QEvent *e;
+} KviThreadPendingEvent;
+
+class KVILIB_API KviThreadManager : public QObject
+{
+ friend class KviApp;
+ friend class KviThread;
+ Q_OBJECT
+protected:
+ // These should be private...but we don't want anyone to complain
+ // Treat as private plz.
+ KviThreadManager();
+ ~KviThreadManager();
+public:
+ static void killPendingEvents(QObject * receiver);
+private:
+#ifndef COMPILE_ON_WINDOWS
+ QSocketNotifier * m_pSn;
+#endif
+ KviMutex * m_pMutex; // This class performs only atomic operations
+ KviPointerList<KviThread> * m_pThreadList;
+ int m_iWaitingThreads;
+#ifndef COMPILE_ON_WINDOWS
+ KviPointerList<KviThreadPendingEvent> * m_pEventQueue;
+ int m_fd[2];
+ int m_iTriggerCount;
+#endif
+protected:
+ // Public to KviThread only
+ void registerSlaveThread(KviThread *t);
+ void unregisterSlaveThread(KviThread *t);
+
+ void threadEnteredWaitState();
+ void threadLeftWaitState();
+
+ void postSlaveEvent(QObject *o,QEvent *e);
+ void killPendingEventsByReceiver(QObject * receiver);
+ // Public to KviApp only
+ static void globalInit();
+ static void globalDestroy();
+private slots:
+ void eventsPending(int fd);
+};
+
+
+#endif //!_KVI_THREAD_H_
diff --git a/src/kvilib/system/kvi_time.cpp b/src/kvilib/system/kvi_time.cpp
new file mode 100644
index 00000000..f500b7d4
--- /dev/null
+++ b/src/kvilib/system/kvi_time.cpp
@@ -0,0 +1,135 @@
+//=============================================================================
+//
+// File : kvi_time.cpp
+// Creation date : Tue Sep 25 17:35:13 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+
+
+#include "kvi_time.h"
+#include "kvi_qstring.h"
+#include "kvi_locale.h"
+
+#ifdef COMPILE_ON_WINDOWS
+ #include <windows.h> // GetSystemTime
+
+ // Call SystemTimeToFileTime to copy the system time to a FILETIME structure.
+ // Call GetSystemTime to get the current system time to pass to SystemTimeToFileTime.
+ // Copy the contents of the FILETIME structure to a ULARGE_INTEGER structure.
+ // Initialize a SYSTEMTIME structure with the date and time of the first second of January 1, 1970.
+ // Call SystemTimeToFileTime, passing the SYSTEMTIME structure initialized in Step 3 to the call.
+ // Copy the contents of the FILETIME structure returned by SystemTimeToFileTime in Step 4 to
+ // a second ULARGE_INTEGER. The copied value should be greater than or equal to the value copied
+ // in Step 2. Subtract the 64-bit value in the ULARGE_INTEGER structure initialized in Step 2
+ // from the 64-bit value of the ULARGE_INTEGER structure initialized in Step 5.
+ // This produces a value in 100-nanosecond intervals since January 1, 1970.
+ // To convert this value to seconds, divide by 10,000,000.
+
+ // buah buah buahhhh lol ghgh :DDDDDDDDD
+
+ void kvi_gettimeofday(struct timeval * tmv,struct timezone *)
+ {
+ SYSTEMTIME st;
+ GetSystemTime(&st);
+
+ // this is simply fucked up..
+ // to minimize the possibility of wrapping we use also the day field.
+ // we actually give something that is near the number of seconds from the beginning
+ // of the current month...
+ // We cannot use the wMonth field since the months have variable length :/
+ tmv->tv_sec = (st.wDay * 86400) + (st.wHour * 3600) + (st.wMinute * 60) + (st.wSecond);
+ tmv->tv_usec = st.wMilliseconds * 1000;
+ }
+#endif
+
+KviMSecTimeInterval::KviMSecTimeInterval()
+{
+ m_uReferenceSecs = 0;
+ m_uReferenceUSecs = 0;
+}
+
+
+unsigned long KviMSecTimeInterval::mark()
+{
+ struct timeval tmv;
+ kvi_gettimeofday(&tmv,0);
+ unsigned long uDiff = ((((unsigned long)(tmv.tv_sec)) - m_uReferenceSecs) * 1000);
+ if(((unsigned long)(tmv.tv_usec)) > m_uReferenceUSecs)uDiff += (((unsigned long)(tmv.tv_usec) - m_uReferenceUSecs) / 1000);
+ else uDiff -= ((m_uReferenceUSecs - (unsigned long)(tmv.tv_usec)) / 1000);
+ m_uReferenceSecs = (unsigned long)tmv.tv_sec;
+ m_uReferenceUSecs = (unsigned long)tmv.tv_usec;
+ return uDiff;
+}
+
+namespace KviTimeUtils
+{
+ void secondsToDaysHoursMinsSecs(unsigned int uSecs,
+ unsigned int * uD,unsigned int * uH,unsigned int * uM,unsigned int * uS)
+ {
+ *uD = uSecs / 86400;
+ uSecs = uSecs % 86400;
+ *uH = uSecs / 3600;
+ uSecs = uSecs % 3600;
+ *uM = uSecs / 60;
+ *uS = uSecs % 60;
+ }
+
+ QString formatTimeInterval(unsigned int uSeconds,int iFlags)
+ {
+ unsigned int d,h,m,s;
+ secondsToDaysHoursMinsSecs(uSeconds,&d,&h,&m,&s);
+ QString ret;
+ // the following tricks maybe will help translators a bit...
+ if(iFlags & FillWithHypens)
+ {
+ ret = __tr2qs("- d -- h -- m -- s");
+ } else {
+ if((iFlags & NoLeadingEmptyIntervals) && (d == 0))
+ {
+ if(h > 0)
+ {
+ if(iFlags & NoLeadingZeroes)
+ KviQString::sprintf(ret,__tr2qs("%u h %u m %u s"),h,m,s);
+ else
+ KviQString::sprintf(ret,__tr2qs("%u h %u%u m %u%u s"),h,m / 10,m % 10,s / 10,s % 10);
+ } else {
+ if(m > 0)
+ {
+ if(iFlags & NoLeadingZeroes)
+ KviQString::sprintf(ret,__tr2qs("%u m %u s"),m,s);
+ else
+ KviQString::sprintf(ret,__tr2qs("%u m %u%u s"),m,s / 10,s % 10);
+ } else {
+ KviQString::sprintf(ret,__tr2qs("%u s"),s);
+ }
+ }
+ } else {
+ if(iFlags & NoLeadingZeroes)
+ KviQString::sprintf(ret,__tr2qs("%u d %u h %u m %u s"),d,h,m,s);
+ else
+ KviQString::sprintf(ret,__tr2qs("%u d %u%u h %u%u m %u%u s"),d,h / 10,h % 10,m / 10,m % 10,s / 10,s % 10);
+ }
+ }
+ return ret;
+ }
+
+}
diff --git a/src/kvilib/system/kvi_time.h b/src/kvilib/system/kvi_time.h
new file mode 100644
index 00000000..309eec10
--- /dev/null
+++ b/src/kvilib/system/kvi_time.h
@@ -0,0 +1,92 @@
+#ifndef _KVI_TIME_H_
+#define _KVI_TIME_H_
+
+//=============================================================================
+//
+// File : kvi_time.h
+// Creation date : Tue Sep 25 17:28:46 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include <qstring.h>
+
+
+#include <time.h> // for time()
+
+#define kvi_unixTime() time(0)
+#define kvi_timeSpan(_time_now,_time_before) ((_time_now) - (_time_before))
+#define kvi_secondsSince(_that_time_t) kvi_timeSpan(kvi_unixTime(),_that_time_t)
+
+#define kvi_time_t time_t
+
+#ifdef COMPILE_ON_WINDOWS
+
+ #include <winsock2.h> // struct timeval
+
+ extern KVILIB_API void kvi_gettimeofday(struct timeval * tmv,struct timezone * tmz);
+
+#else //!COMPILE_ON_WINDOWS
+
+ #include <sys/time.h> // gettimeofday() , struct timeval
+
+ inline void kvi_gettimeofday(struct timeval * tmv,struct timezone * tmz)
+ {
+ gettimeofday(tmv,tmz);
+ };
+
+#endif //!COMPILE_ON_WINDOWS
+
+// this works for time intervals a bit longer than 24 days
+class KVILIB_API KviMSecTimeInterval
+{
+public:
+ KviMSecTimeInterval();
+protected:
+ unsigned long m_uReferenceSecs;
+ unsigned long m_uReferenceUSecs;
+public:
+ // returns the number of milliseconds since
+ // mark() was last called (and thus marks
+ // the beginning of a new interval).
+ unsigned long mark();
+ // this wors ONLY in the same second that mark was called in
+ // and returns the tv_sec field of the gettimeofday()
+ // (remember that gettimeofday() is broken on windows)
+ unsigned long secondsCounter(){ return m_uReferenceSecs; };
+};
+
+namespace KviTimeUtils
+{
+
+
+ // splits the time span uSecs in days, hours, minutes and seconds
+ KVILIB_API void secondsToDaysHoursMinsSecs(unsigned int uSecs,
+ unsigned int * uD,unsigned int * uH,unsigned int * uM,unsigned int * uS);
+ // returns a string formatted like x d x h xx m xx s
+ enum FormatTimeSpanFlags {
+ NoLeadingEmptyIntervals = 1, // causes the leading empty intervals to be omitted
+ NoLeadingZeroes = 2, // no leading zeroes are printed in hours and seconds
+ FillWithHypens = 4 // uses only -- %d -- %h -- etc.. discards all other flags
+ };
+ KVILIB_API QString formatTimeInterval(unsigned int uSeconds,int iFlags = 0);
+};
+
+#endif //_KVI_TIME_H_
diff --git a/src/kvilib/system/moc_kvi_locale.cpp b/src/kvilib/system/moc_kvi_locale.cpp
new file mode 100644
index 00000000..52e2ae22
--- /dev/null
+++ b/src/kvilib/system/moc_kvi_locale.cpp
@@ -0,0 +1,92 @@
+/****************************************************************************
+** KviTranslator meta object code from reading C++ file 'kvi_locale.h'
+**
+** Created: Sun Mar 23 20:56:24 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_locale.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviTranslator::className() const
+{
+ return "KviTranslator";
+}
+
+QMetaObject *KviTranslator::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviTranslator( "KviTranslator", &KviTranslator::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviTranslator::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviTranslator", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviTranslator::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviTranslator", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviTranslator::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = QTranslator::staticMetaObject();
+ metaObj = QMetaObject::new_metaobject(
+ "KviTranslator", parentObject,
+ 0, 0,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviTranslator.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviTranslator::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviTranslator" ) )
+ return this;
+ return QTranslator::qt_cast( clname );
+}
+
+bool KviTranslator::qt_invoke( int _id, QUObject* _o )
+{
+ return QTranslator::qt_invoke(_id,_o);
+}
+
+bool KviTranslator::qt_emit( int _id, QUObject* _o )
+{
+ return QTranslator::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviTranslator::qt_property( int id, int f, QVariant* v)
+{
+ return QTranslator::qt_property( id, f, v);
+}
+
+bool KviTranslator::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvilib/system/moc_kvi_thread.cpp b/src/kvilib/system/moc_kvi_thread.cpp
new file mode 100644
index 00000000..556849a9
--- /dev/null
+++ b/src/kvilib/system/moc_kvi_thread.cpp
@@ -0,0 +1,104 @@
+/****************************************************************************
+** KviThreadManager meta object code from reading C++ file 'kvi_thread.h'
+**
+** Created: Sun Mar 23 20:56:25 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_thread.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviThreadManager::className() const
+{
+ return "KviThreadManager";
+}
+
+QMetaObject *KviThreadManager::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviThreadManager( "KviThreadManager", &KviThreadManager::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviThreadManager::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviThreadManager", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviThreadManager::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviThreadManager", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviThreadManager::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = QObject::staticMetaObject();
+ static const QUParameter param_slot_0[] = {
+ { "fd", &static_QUType_int, 0, QUParameter::In }
+ };
+ static const QUMethod slot_0 = {"eventsPending", 1, param_slot_0 };
+ static const QMetaData slot_tbl[] = {
+ { "eventsPending(int)", &slot_0, QMetaData::Private }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviThreadManager", parentObject,
+ slot_tbl, 1,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviThreadManager.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviThreadManager::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviThreadManager" ) )
+ return this;
+ return QObject::qt_cast( clname );
+}
+
+bool KviThreadManager::qt_invoke( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->slotOffset() ) {
+ case 0: eventsPending((int)static_QUType_int.get(_o+1)); break;
+ default:
+ return QObject::qt_invoke( _id, _o );
+ }
+ return TRUE;
+}
+
+bool KviThreadManager::qt_emit( int _id, QUObject* _o )
+{
+ return QObject::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviThreadManager::qt_property( int id, int f, QVariant* v)
+{
+ return QObject::qt_property( id, f, v);
+}
+
+bool KviThreadManager::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvilib/tal/Makefile.am b/src/kvilib/tal/Makefile.am
new file mode 100644
index 00000000..c84487eb
--- /dev/null
+++ b/src/kvilib/tal/Makefile.am
@@ -0,0 +1,5 @@
+###############################################################################
+# KVirc IRC client Makefile - 16.12.98 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+EXTRA_DIST = *.cpp *.h
diff --git a/src/kvilib/tal/kvi_tal_application.cpp b/src/kvilib/tal/kvi_tal_application.cpp
new file mode 100644
index 00000000..4d8bd0d5
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_application.cpp
@@ -0,0 +1,69 @@
+//
+// File : kvi_tal_application.coo
+// Creation date : Sun Aug 12 2001 04:34:21 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#define __KVILIB__
+
+
+#include "kvi_tal_application.h"
+
+#ifdef COMPILE_KDE_SUPPORT
+
+ // The constructor below triggers a warning
+ // ../tal/kvi_tal_application.cpp: In constructor
+ // `KviTalApplication::KviTalApplication(int, char**)':
+ // ../tal/kvi_tal_application.cpp:31: warning: `__base_ctor' is deprecated
+ // (declared at /opt/kde/include/kapplication.h:198)
+ //
+ // The KApplication constructor has been declared as deprecated
+ // in favor of a complexier initialization that uses KCmdLineArgs
+ // and can't be abstracted easily.
+ // The other constructors are not "old" and "stable" enough
+ // to be safely used at this time. We'll rethink this when KDE 4 is out.
+
+ KviTalApplication::KviTalApplication(int &argc,char ** argv)
+ : KApplication(argc,argv,"kvirc")
+ {
+
+
+
+ }
+
+ KviTalApplication::~KviTalApplication()
+ {
+ }
+
+ #include "kvi_tal_application_kde.moc"
+
+#else
+
+ KviTalApplication::KviTalApplication(int &argc,char ** argv)
+ : QApplication(argc,argv)
+ {
+ }
+
+ KviTalApplication::~KviTalApplication()
+ {
+ }
+
+ #include "kvi_tal_application_qt.moc"
+
+#endif
diff --git a/src/kvilib/tal/kvi_tal_application.h b/src/kvilib/tal/kvi_tal_application.h
new file mode 100644
index 00000000..4f9e96df
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_application.h
@@ -0,0 +1,34 @@
+#ifndef _KVI_TAL_APPLICATION_H_
+#define _KVI_TAL_APPLICATION_H_
+
+//
+// File : kvi_appbase_kde.h
+// Creation date : Sun Jun 18 2000 12:53:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_KDE_SUPPORT
+ #include "kvi_tal_application_kde.h"
+#else
+ #include "kvi_tal_application_qt.h"
+#endif
+
+#endif // _KVI_TAL_APPLICATION_H_
diff --git a/src/kvilib/tal/kvi_tal_application_kde.h b/src/kvilib/tal/kvi_tal_application_kde.h
new file mode 100644
index 00000000..05d6e87f
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_application_kde.h
@@ -0,0 +1,37 @@
+#ifndef _KVI_TAL_APPLICATION_KDE_H_
+#define _KVI_TAL_APPLICATION_KDE_H_
+
+//
+// File : kvi_tal_application_kde.h
+// Creation date : Sun Aug 12 2001 04:32:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include <kapp.h>
+
+
+class KVILIB_API KviTalApplication : public KApplication
+{
+ Q_OBJECT
+public:
+ KviTalApplication(int &argc,char ** argv);
+ ~KviTalApplication();
+};
+
+#endif // _KVI_TAL_APPLICATION_KDE_H_
diff --git a/src/kvilib/tal/kvi_tal_application_qt.h b/src/kvilib/tal/kvi_tal_application_qt.h
new file mode 100644
index 00000000..953608fe
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_application_qt.h
@@ -0,0 +1,37 @@
+#ifndef _KVI_TAL_APPLICATION_QT_H_
+#define _KVI_TAL_APPLICATION_QT_H_
+
+//
+// File : kvi_tal_application_qt.h
+// Creation date : Sun Aug 12 2001 04:33:21 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include <qapplication.h>
+
+
+class KVILIB_API KviTalApplication : public QApplication
+{
+ Q_OBJECT
+public:
+ KviTalApplication(int &argc,char ** argv);
+ ~KviTalApplication();
+};
+
+#endif // _KVI_TAL_APPLICATION_QT_H_
diff --git a/src/kvilib/tal/kvi_tal_filedialog.cpp b/src/kvilib/tal/kvi_tal_filedialog.cpp
new file mode 100644
index 00000000..b345fd0b
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_filedialog.cpp
@@ -0,0 +1,176 @@
+//=============================================================================
+//
+// File : kvi_tal_filedialog.coo
+// Creation date : Thu Sep 11 2003 04:09:24 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003-2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+
+
+#include "kvi_tal_filedialog.h"
+
+#ifdef COMPILE_USE_QT4
+
+ #include <qdir.h>
+
+ KviTalFileDialog::KviTalFileDialog(const QString &dirName,const QString &filter,QWidget *parent,const char *name,bool modal)
+ : QFileDialog(parent,"",dirName,filter)
+ {
+ setModal(modal);
+ }
+
+ KviTalFileDialog::~KviTalFileDialog()
+ {
+ }
+
+ void KviTalFileDialog::setFileMode(FileMode m)
+ {
+ switch(m)
+ {
+ case AnyFile:
+ QFileDialog::setFileMode(QFileDialog::AnyFile);
+ break;
+ case ExistingFile:
+ QFileDialog::setFileMode(QFileDialog::ExistingFile);
+ break;
+ case ExistingFiles:
+ QFileDialog::setFileMode(QFileDialog::ExistingFiles);
+ break;
+ case Directory:
+ QFileDialog::setFileMode(QFileDialog::Directory);
+ break;
+ case DirectoryOnly:
+ QFileDialog::setFileMode(QFileDialog::DirectoryOnly);
+ break;
+ default:
+ QFileDialog::setFileMode(QFileDialog::AnyFile);
+ break;
+ }
+ }
+
+ void KviTalFileDialog::setDirectory(const QString &szDirectory)
+ {
+ QFileDialog::setDirectory(szDirectory);
+ }
+
+
+ #include "kvi_tal_filedialog_qt4.moc"
+
+#else
+
+ #ifdef COMPILE_KDE_SUPPORT
+
+ KviTalFileDialog::KviTalFileDialog(const QString &dirName,const QString &filter,QWidget *parent,const char *name,bool modal)
+ : KFileDialog(dirName,filter,parent,name,modal)
+ {
+ clearWFlags(WDestructiveClose);
+ }
+
+ KviTalFileDialog::~KviTalFileDialog()
+ {
+ }
+
+ void KviTalFileDialog::setFileMode(FileMode m)
+ {
+ switch(m)
+ {
+ case AnyFile:
+ setMode(KFile::File | KFile::LocalOnly);
+ setOperationMode(Saving);
+ break;
+ case ExistingFile:
+ setMode(KFile::File | KFile::ExistingOnly | KFile::LocalOnly);
+ setOperationMode(Opening);
+ break;
+ case ExistingFiles:
+ setMode(KFile::Files | KFile::ExistingOnly | KFile::LocalOnly);
+ setOperationMode(Opening);
+ break;
+ case Directory:
+ setMode(KFile::Directory);
+ break;
+ case DirectoryOnly:
+ setMode(KFile::Directory);
+ break;
+ default:
+ setMode(KFile::File | KFile::LocalOnly);
+ setOperationMode(Saving);
+ break;
+ }
+ }
+
+ void KviTalFileDialog::setDirectory(const QString &szDirectory)
+ {
+ setURL(szDirectory);
+ }
+
+
+ #include "kvi_tal_filedialog_kde.moc"
+
+ #else
+
+ #include <qdir.h>
+
+ KviTalFileDialog::KviTalFileDialog(const QString &dirName,const QString &filter,QWidget *parent,const char *name,bool modal)
+ : QFileDialog(dirName,filter,parent,name,modal)
+ {
+ clearWFlags(WDestructiveClose);
+ }
+
+ KviTalFileDialog::~KviTalFileDialog()
+ {
+ }
+
+ void KviTalFileDialog::setFileMode(FileMode m)
+ {
+ switch(m)
+ {
+ case AnyFile:
+ setMode(QFileDialog::AnyFile);
+ break;
+ case ExistingFile:
+ setMode(QFileDialog::ExistingFile);
+ break;
+ case ExistingFiles:
+ setMode(QFileDialog::ExistingFiles);
+ break;
+ case Directory:
+ setMode(QFileDialog::Directory);
+ break;
+ case DirectoryOnly:
+ setMode(QFileDialog::DirectoryOnly);
+ break;
+ default:
+ setMode(QFileDialog::AnyFile);
+ break;
+ }
+ }
+
+ void KviTalFileDialog::setDirectory(const QString &szDirectory)
+ {
+ setDir(QDir(szDirectory));
+ }
+
+
+ #include "kvi_tal_filedialog_qt.moc"
+
+ #endif
+#endif
diff --git a/src/kvilib/tal/kvi_tal_filedialog.h b/src/kvilib/tal/kvi_tal_filedialog.h
new file mode 100644
index 00000000..eac2e645
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_filedialog.h
@@ -0,0 +1,40 @@
+#ifndef _KVI_TAL_FILEDIALOG_H_
+#define _KVI_TAL_FILEDIALOG_H_
+
+//=============================================================================
+//
+// File : kvi_tal_filedialog.h
+// Creation date : Thu Sep 11 2003 04:41:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003-2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_USE_QT4
+ #include "kvi_tal_filedialog_qt4.h"
+#else
+ #ifdef COMPILE_KDE_SUPPORT
+ #include "kvi_tal_filedialog_kde.h"
+ #else
+ #include "kvi_tal_filedialog_qt.h"
+ #endif
+#endif
+
+#endif // _KVI_TAL_FILEDIALOG_H_
diff --git a/src/kvilib/tal/kvi_tal_filedialog_kde.h b/src/kvilib/tal/kvi_tal_filedialog_kde.h
new file mode 100644
index 00000000..0f04a80c
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_filedialog_kde.h
@@ -0,0 +1,50 @@
+#ifndef _KVI_TAL_FILEDIALOG_KDE_H_
+#define _KVI_TAL_FILEDIALOG_KDE_H_
+
+//
+// File : kvi_tal_filedialog_kde.h
+// Creation date : Thu Aug 11 2003 04:43:58 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include <kfiledialog.h>
+#include <qfiledialog.h>
+
+class KVILIB_API KviTalFileDialog : public KFileDialog
+{
+ Q_OBJECT
+public:
+ KviTalFileDialog(const QString &dirName,const QString &filter = QString::null,QWidget *parent = 0,const char *name = 0,bool modal = FALSE);
+ ~KviTalFileDialog();
+public:
+ enum FileMode { AnyFile, ExistingFile, ExistingFiles, Directory, DirectoryOnly };
+
+ void setFileMode(FileMode m);
+ void setDirectory(const QString &szDirectory);
+
+
+ static QString getExistingDirectoryPath(const QString &dir = QString::null,const QString &caption = QString::null,QWidget *parent = 0)
+ {
+ // QFileDialog allows making new directories...kfiledialog not :/
+ return QFileDialog::getExistingDirectory(dir,parent,0,caption);
+ //return getExistingDirectory(dir,parent,caption);
+ };
+};
+
+#endif // _KVI_TAL_FILEDIALOG_KDE_H_
diff --git a/src/kvilib/tal/kvi_tal_filedialog_qt.h b/src/kvilib/tal/kvi_tal_filedialog_qt.h
new file mode 100644
index 00000000..14a24854
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_filedialog_qt.h
@@ -0,0 +1,44 @@
+#ifndef _KVI_TAL_FILEDIALOG_QT_H_
+#define _KVI_TAL_FILEDIALOG_QT_H_
+
+//
+// File : kvi_tal_filedialog_qt.h
+// Creation date : Thu Aug 11 2003 04:43:58 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include <qfiledialog.h>
+
+class KVILIB_API KviTalFileDialog : public QFileDialog
+{
+ Q_OBJECT
+public:
+ KviTalFileDialog(const QString &dirName,const QString &filter = QString::null,QWidget *parent = 0,const char *name = 0,bool modal = FALSE);
+ ~KviTalFileDialog();
+public:
+ enum FileMode { AnyFile, ExistingFile, ExistingFiles, Directory, DirectoryOnly };
+
+ void setFileMode(FileMode m);
+ void setDirectory(const QString &szDirectory);
+
+ static QString getExistingDirectoryPath(const QString &dir = QString::null,const QString &caption = QString::null,QWidget *parent = 0)
+ { return getExistingDirectory(dir,parent,0 /* name */,caption); };
+};
+
+#endif // _KVI_TAL_FILEDIALOG_QT_H_
diff --git a/src/kvilib/tal/kvi_tal_filedialog_qt4.h b/src/kvilib/tal/kvi_tal_filedialog_qt4.h
new file mode 100644
index 00000000..eb5f7ab6
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_filedialog_qt4.h
@@ -0,0 +1,46 @@
+#ifndef _KVI_TAL_FILEDIALOG_QT4_H_
+#define _KVI_TAL_FILEDIALOG_QT4_H_
+
+//=============================================================================
+//
+// File : kvi_tal_filedialog_qt4.h
+// Creation date : Fri 19 Jan 2007 02:17:12 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include <qfiledialog.h>
+
+class KVILIB_API KviTalFileDialog : public QFileDialog
+{
+ Q_OBJECT
+public:
+ KviTalFileDialog(const QString &dirName,const QString &filter = QString::null,QWidget *parent = 0,const char *name = 0,bool modal = FALSE);
+ ~KviTalFileDialog();
+public:
+ enum FileMode { AnyFile, ExistingFile, ExistingFiles, Directory, DirectoryOnly };
+
+ void setFileMode(FileMode m);
+ void setDirectory(const QString &szDirectory);
+
+ static QString getExistingDirectoryPath(const QString &dir = QString::null,const QString &caption = QString::null,QWidget *parent = 0)
+ { return getExistingDirectory(parent,caption,dir); };
+};
+
+#endif // _KVI_TAL_FILEDIALOG_QT_H_
diff --git a/src/kvilib/tal/kvi_tal_grid.cpp b/src/kvilib/tal/kvi_tal_grid.cpp
new file mode 100644
index 00000000..472af5a0
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_grid.cpp
@@ -0,0 +1,34 @@
+//=============================================================================
+//
+// File : kvi_tal_grid.cpp
+// Creation date : Mon Jan 22 2007 11:25:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+#include "kvi_tal_grid.h"
+
+
+#ifdef COMPILE_USE_QT4
+ #include "kvi_tal_grid_qt4.moc"
+#else
+ #include "kvi_tal_grid_qt3.moc"
+#endif
+
diff --git a/src/kvilib/tal/kvi_tal_grid.h b/src/kvilib/tal/kvi_tal_grid.h
new file mode 100644
index 00000000..18c4af98
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_grid.h
@@ -0,0 +1,36 @@
+#ifndef _KVI_TAL_GRID_H_
+#define _KVI_TAL_GRID_H_
+
+//=============================================================================
+//
+// File : kvi_tal_grid.h
+// Creation date : Mon Jan 22 2007 11:25:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_USE_QT4
+ #include "kvi_tal_grid_qt4.h"
+#else
+ #include "kvi_tal_grid_qt3.h"
+#endif
+
+#endif // _KVI_TAL_GRID_H_
diff --git a/src/kvilib/tal/kvi_tal_grid_qt3.h b/src/kvilib/tal/kvi_tal_grid_qt3.h
new file mode 100644
index 00000000..fd77d15c
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_grid_qt3.h
@@ -0,0 +1,39 @@
+#ifndef _KVI_TAL_GRID_QT3_H_
+#define _KVI_TAL_GRID_QT3_H_
+
+//=============================================================================
+//
+// File : kvi_tal_grid_qt3.h
+// Creation date : Mon Jan 22 2007 11:25:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include <qgrid.h>
+
+class KVILIB_API KviTalGrid : public QGrid
+{
+ Q_OBJECT
+public:
+ KviTalGrid(int n,Qt::Orientation orient,QWidget * pParent = 0)
+ : QGrid(n,orient,pParent) {};
+ ~KviTalGrid() {};
+};
+
+#endif // _KVI_TAL_GRID_QT3_H_
diff --git a/src/kvilib/tal/kvi_tal_grid_qt4.h b/src/kvilib/tal/kvi_tal_grid_qt4.h
new file mode 100644
index 00000000..57612b3c
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_grid_qt4.h
@@ -0,0 +1,41 @@
+#ifndef _KVI_TAL_GRID_QT4_H_
+#define _KVI_TAL_GRID_QT4_H_
+
+//=============================================================================
+//
+// File : kvi_tal_grid_qt4.h
+// Creation date : Mon Jan 22 2007 11:25:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#include <q3grid.h>
+
+class KVILIB_API KviTalGrid : public Q3Grid
+{
+ Q_OBJECT
+public:
+ KviTalGrid(int n,Qt::Orientation orient,QWidget * pParent = 0)
+ : Q3Grid(n,orient,pParent) {};
+ ~KviTalGrid() {};
+};
+
+#endif // _KVI_TAL_GRID_QT4_H_
diff --git a/src/kvilib/tal/kvi_tal_groupbox.cpp b/src/kvilib/tal/kvi_tal_groupbox.cpp
new file mode 100644
index 00000000..bf2f5689
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_groupbox.cpp
@@ -0,0 +1,34 @@
+//=============================================================================
+//
+// File : kvi_tal_groupbox.cpp
+// Creation date : Mon Jan 22 2007 11:25:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+#include "kvi_tal_groupbox.h"
+
+
+#ifdef COMPILE_USE_QT4
+ #include "kvi_tal_groupbox_qt4.moc"
+#else
+ #include "kvi_tal_groupbox_qt3.moc"
+#endif
+
diff --git a/src/kvilib/tal/kvi_tal_groupbox.h b/src/kvilib/tal/kvi_tal_groupbox.h
new file mode 100644
index 00000000..ae82519b
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_groupbox.h
@@ -0,0 +1,36 @@
+#ifndef _KVI_TAL_GROUPBOX_H_
+#define _KVI_TAL_GROUPBOX_H_
+
+//=============================================================================
+//
+// File : kvi_tal_groupbox.h
+// Creation date : Mon Jan 22 2007 11:25:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_USE_QT4
+ #include "kvi_tal_groupbox_qt4.h"
+#else
+ #include "kvi_tal_groupbox_qt3.h"
+#endif
+
+#endif // _KVI_TAL_GROUPBOX_H_
diff --git a/src/kvilib/tal/kvi_tal_groupbox_qt3.h b/src/kvilib/tal/kvi_tal_groupbox_qt3.h
new file mode 100644
index 00000000..be3340a3
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_groupbox_qt3.h
@@ -0,0 +1,47 @@
+#ifndef _KVI_TAL_GROUPBOX_QT3_H_
+#define _KVI_TAL_GROUPBOX_QT3_H_
+
+//=============================================================================
+//
+// File : kvi_tal_groupbox_qt3.h
+// Creation date : Mon Jan 22 2007 11:25:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include <qgroupbox.h>
+
+class KVILIB_API KviTalGroupBox : public QGroupBox
+{
+ Q_OBJECT
+public:
+ KviTalGroupBox(QWidget * parent = 0)
+ : QGroupBox(parent) {};
+ KviTalGroupBox(const QString & title,QWidget * parent = 0)
+ : QGroupBox(title,parent) {};
+ KviTalGroupBox(int strips,Qt::Orientation orientation,QWidget * parent = 0)
+ : QGroupBox(strips,orientation,parent) {};
+ KviTalGroupBox(int strips,Qt::Orientation orientation,const QString & title,QWidget * parent = 0)
+ : QGroupBox(strips,orientation,title,parent) {};
+ ~KviTalGroupBox() {};
+};
+
+
+
+#endif // _KVI_TAL_GROUPBOX_QT3_H_
diff --git a/src/kvilib/tal/kvi_tal_groupbox_qt4.h b/src/kvilib/tal/kvi_tal_groupbox_qt4.h
new file mode 100644
index 00000000..c8917385
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_groupbox_qt4.h
@@ -0,0 +1,47 @@
+#ifndef _KVI_TAL_GROUPBOX_QT4_H_
+#define _KVI_TAL_GROUPBOX_QT4_H_
+
+//=============================================================================
+//
+// File : kvi_tal_groupbox_qt4.h
+// Creation date : Mon Jan 22 2007 11:25:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include <q3groupbox.h>
+
+class KVILIB_API KviTalGroupBox : public Q3GroupBox
+{
+ Q_OBJECT
+public:
+ KviTalGroupBox(QWidget * parent = 0)
+ : Q3GroupBox(parent) {};
+ KviTalGroupBox(const QString & title,QWidget * parent = 0)
+ : Q3GroupBox(title,parent) {};
+ KviTalGroupBox(int strips,Qt::Orientation orientation,QWidget * parent = 0)
+ : Q3GroupBox(strips,orientation,parent) {};
+ KviTalGroupBox(int strips,Qt::Orientation orientation,const QString & title,QWidget * parent = 0)
+ : Q3GroupBox(strips,orientation,title,parent) {};
+ ~KviTalGroupBox() {};
+};
+
+
+
+#endif // _KVI_TAL_GROUPBOX_QT4_H_
diff --git a/src/kvilib/tal/kvi_tal_hbox.cpp b/src/kvilib/tal/kvi_tal_hbox.cpp
new file mode 100644
index 00000000..6df56ee8
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_hbox.cpp
@@ -0,0 +1,32 @@
+//=============================================================================
+//
+// File : kvi_tal_hbox.cpp
+// Creation date : Mon Jan 22 2007 11:25:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+#include "kvi_tal_hbox.h"
+
+#ifdef COMPILE_USE_QT4
+ #include "kvi_tal_hbox_qt4.moc"
+#else
+ #include "kvi_tal_hbox_qt3.moc"
+#endif
diff --git a/src/kvilib/tal/kvi_tal_hbox.h b/src/kvilib/tal/kvi_tal_hbox.h
new file mode 100644
index 00000000..6f955ed6
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_hbox.h
@@ -0,0 +1,36 @@
+#ifndef _KVI_TAL_HBOX_H_
+#define _KVI_TAL_HBOX_H_
+
+//=============================================================================
+//
+// File : kvi_tal_hbox.h
+// Creation date : Mon Jan 22 2007 11:25:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_USE_QT4
+ #include "kvi_tal_hbox_qt4.h"
+#else
+ #include "kvi_tal_hbox_qt3.h"
+#endif
+
+#endif // _KVI_TAL_HBOX_H_
diff --git a/src/kvilib/tal/kvi_tal_hbox_qt3.h b/src/kvilib/tal/kvi_tal_hbox_qt3.h
new file mode 100644
index 00000000..992ca03a
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_hbox_qt3.h
@@ -0,0 +1,41 @@
+#ifndef _KVI_TAL_HBOX_QT3_H_
+#define _KVI_TAL_HBOX_QT3_H_
+
+//=============================================================================
+//
+// File : kvi_tal_hbox_qt3.h
+// Creation date : Mon Jan 22 2007 11:25:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#include <qhbox.h>
+
+class KVILIB_API KviTalHBox : public QHBox
+{
+ Q_OBJECT
+public:
+ KviTalHBox(QWidget * pParent)
+ : QHBox(pParent) {};
+ virtual ~KviTalHBox() {};
+};
+
+#endif // _KVI_TAL_HBOX_QT3_H_
diff --git a/src/kvilib/tal/kvi_tal_hbox_qt4.h b/src/kvilib/tal/kvi_tal_hbox_qt4.h
new file mode 100644
index 00000000..384910c2
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_hbox_qt4.h
@@ -0,0 +1,41 @@
+#ifndef _KVI_TAL_HBOX_QT4_H_
+#define _KVI_TAL_HBOX_QT4_H_
+
+//=============================================================================
+//
+// File : kvi_tal_hbox_qt4.h
+// Creation date : Mon Jan 22 2007 11:25:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#include <q3hbox.h>
+
+class KVILIB_API KviTalHBox : public Q3HBox
+{
+ Q_OBJECT
+public:
+ KviTalHBox(QWidget * pParent,char* name=0)
+ : Q3HBox(pParent,name) {};
+ virtual ~KviTalHBox() {};
+};
+
+#endif // _KVI_TAL_HBOX_QT4_H_
diff --git a/src/kvilib/tal/kvi_tal_iconview.cpp b/src/kvilib/tal/kvi_tal_iconview.cpp
new file mode 100644
index 00000000..2f63388c
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_iconview.cpp
@@ -0,0 +1,215 @@
+//=============================================================================
+//
+// File : kvi_tal_iconview.cpp
+// Creation date : Mon Jan 22 2007 11:25:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+#include "kvi_tal_iconview.h"
+
+#ifdef COMPILE_USE_QT4
+
+ KviTalIconView::KviTalIconView(QWidget * pParent,Qt::WFlags f)
+ : Q3IconView(pParent,0,f)
+ {
+ connect(this,SIGNAL(selectionChanged(Q3IconViewItem *)),this,SLOT(redirect_selectionChanged(Q3IconViewItem *)));
+ connect(this,SIGNAL(currentChanged(Q3IconViewItem *)),this,SLOT(redirect_currentChanged(Q3IconViewItem *)));
+ connect(this,SIGNAL(clicked(Q3IconViewItem *)),this,SLOT(redirect_clicked(Q3IconViewItem *)));
+ connect(this,SIGNAL(clicked(Q3IconViewItem *,const QPoint &)),this,SLOT(redirect_clicked(Q3IconViewItem *,const QPoint &)));
+ connect(this,SIGNAL(pressed(Q3IconViewItem *)),this,SLOT(redirect_pressed(Q3IconViewItem *)));
+ connect(this,SIGNAL(pressed(Q3IconViewItem *,const QPoint &)),this,SLOT(redirect_pressed(Q3IconViewItem *,const QPoint &)));
+ connect(this,SIGNAL(doubleClicked(Q3IconViewItem *)),this,SLOT(redirect_doubleClicked(Q3IconViewItem *)));
+ connect(this,SIGNAL(returnPressed(Q3IconViewItem *)),this,SLOT(redirect_returnPressed(Q3IconViewItem *)));
+ connect(this,SIGNAL(rightButtonClicked(Q3IconViewItem *,const QPoint &)),this,SLOT(redirect_rightButtonClicked(Q3IconViewItem *,const QPoint &)));
+ connect(this,SIGNAL(rightButtonPressed(Q3IconViewItem *,const QPoint &)),this,SLOT(redirect_rightButtonPressed(Q3IconViewItem *,const QPoint &)));
+ connect(this,SIGNAL(mouseButtonClicked(int,Q3IconViewItem *,const QPoint &)),this,SLOT(redirect_mouseButtonClicked(int,Q3IconViewItem *,const QPoint &)));
+ connect(this,SIGNAL(mouseButtonPressed(int,Q3IconViewItem *,const QPoint &)),this,SLOT(redirect_mouseButtonPressed(int,Q3IconViewItem *,const QPoint &)));
+ connect(this,SIGNAL(contextMenuRequested(Q3IconViewItem *,const QPoint &)),this,SLOT(redirect_contextMenuRequested(Q3IconViewItem *,const QPoint &)));
+ connect(this,SIGNAL(onItem(Q3IconViewItem *)),this,SLOT(redirect_onItem(Q3IconViewItem *)));
+ }
+
+ void KviTalIconView::redirect_selectionChanged(Q3IconViewItem * pItem)
+ {
+ emit selectionChanged((KviTalIconViewItem *)pItem);
+ }
+
+ void KviTalIconView::redirect_currentChanged(Q3IconViewItem * pItem)
+ {
+ emit currentChanged((KviTalIconViewItem *)pItem);
+ }
+
+ void KviTalIconView::redirect_clicked(Q3IconViewItem * pItem)
+ {
+ emit clicked((KviTalIconViewItem *)pItem);
+ }
+
+ void KviTalIconView::redirect_clicked(Q3IconViewItem * pItem,const QPoint &pnt)
+ {
+ emit clicked((KviTalIconViewItem *)pItem,pnt);
+ }
+
+ void KviTalIconView::redirect_pressed(Q3IconViewItem * pItem)
+ {
+ emit pressed((KviTalIconViewItem *)pItem);
+ }
+
+ void KviTalIconView::redirect_pressed(Q3IconViewItem * pItem,const QPoint &pnt)
+ {
+ emit pressed((KviTalIconViewItem *)pItem,pnt);
+ }
+
+ void KviTalIconView::redirect_doubleClicked(Q3IconViewItem * pItem)
+ {
+ emit doubleClicked((KviTalIconViewItem *)pItem);
+ }
+
+ void KviTalIconView::redirect_returnPressed(Q3IconViewItem * pItem)
+ {
+ emit returnPressed((KviTalIconViewItem *)pItem);
+ }
+
+ void KviTalIconView::redirect_rightButtonClicked(Q3IconViewItem * pItem,const QPoint &pnt)
+ {
+ emit rightButtonClicked((KviTalIconViewItem *)pItem,pnt);
+ }
+
+ void KviTalIconView::redirect_rightButtonPressed(Q3IconViewItem * pItem,const QPoint &pnt)
+ {
+ emit rightButtonPressed((KviTalIconViewItem *)pItem,pnt);
+ }
+
+ void KviTalIconView::redirect_mouseButtonClicked(int iButton,Q3IconViewItem * pItem,const QPoint &pnt)
+ {
+ emit mouseButtonClicked(iButton,(KviTalIconViewItem *)pItem,pnt);
+ }
+
+ void KviTalIconView::redirect_mouseButtonPressed(int iButton,Q3IconViewItem * pItem,const QPoint &pnt)
+ {
+ emit mouseButtonPressed(iButton,(KviTalIconViewItem *)pItem,pnt);
+ }
+
+ void KviTalIconView::redirect_contextMenuRequested(Q3IconViewItem * pItem,const QPoint &pnt)
+ {
+ emit contextMenuRequested((KviTalIconViewItem *)pItem,pnt);
+ }
+
+ void KviTalIconView::redirect_onItem(Q3IconViewItem * pItem)
+ {
+ emit onItem((KviTalIconViewItem *)pItem);
+ }
+
+
+ #include "kvi_tal_iconview_qt4.moc"
+#else
+
+ KviTalIconView::KviTalIconView(QWidget * pParent,Qt::WFlags f)
+ : QIconView(pParent,0,f)
+ {
+ connect(this,SIGNAL(selectionChanged(QIconViewItem *)),this,SLOT(redirect_selectionChanged(QIconViewItem *)));
+ connect(this,SIGNAL(currentChanged(QIconViewItem *)),this,SLOT(redirect_currentChanged(QIconViewItem *)));
+ connect(this,SIGNAL(clicked(QIconViewItem *)),this,SLOT(redirect_clicked(QIconViewItem *)));
+ connect(this,SIGNAL(clicked(QIconViewItem *,const QPoint &)),this,SLOT(redirect_clicked(QIconViewItem *,const QPoint &)));
+ connect(this,SIGNAL(pressed(QIconViewItem *)),this,SLOT(redirect_pressed(QIconViewItem *)));
+ connect(this,SIGNAL(pressed(QIconViewItem *,const QPoint &)),this,SLOT(redirect_pressed(QIconViewItem *,const QPoint &)));
+ connect(this,SIGNAL(doubleClicked(QIconViewItem *)),this,SLOT(redirect_doubleClicked(QIconViewItem *)));
+ connect(this,SIGNAL(returnPressed(QIconViewItem *)),this,SLOT(redirect_returnPressed(QIconViewItem *)));
+ connect(this,SIGNAL(rightButtonClicked(QIconViewItem *,const QPoint &)),this,SLOT(redirect_rightButtonClicked(QIconViewItem *,const QPoint &)));
+ connect(this,SIGNAL(rightButtonPressed(QIconViewItem *,const QPoint &)),this,SLOT(redirect_rightButtonPressed(QIconViewItem *,const QPoint &)));
+ connect(this,SIGNAL(mouseButtonClicked(int,QIconViewItem *,const QPoint &)),this,SLOT(redirect_mouseButtonClicked(int,QIconViewItem *,const QPoint &)));
+ connect(this,SIGNAL(mouseButtonPressed(int,QIconViewItem *,const QPoint &)),this,SLOT(redirect_mouseButtonPressed(int,QIconViewItem *,const QPoint &)));
+ connect(this,SIGNAL(contextMenuRequested(QIconViewItem *,const QPoint &)),this,SLOT(redirect_contextMenuRequested(QIconViewItem *,const QPoint &)));
+ connect(this,SIGNAL(onItem(QIconViewItem *)),this,SLOT(redirect_onItem(QIconViewItem *)));
+ }
+
+ void KviTalIconView::redirect_selectionChanged(QIconViewItem * pItem)
+ {
+ emit selectionChanged((KviTalIconViewItem *)pItem);
+ }
+
+ void KviTalIconView::redirect_currentChanged(QIconViewItem * pItem)
+ {
+ emit currentChanged((KviTalIconViewItem *)pItem);
+ }
+
+ void KviTalIconView::redirect_clicked(QIconViewItem * pItem)
+ {
+ emit clicked((KviTalIconViewItem *)pItem);
+ }
+
+ void KviTalIconView::redirect_clicked(QIconViewItem * pItem,const QPoint &pnt)
+ {
+ emit clicked((KviTalIconViewItem *)pItem,pnt);
+ }
+
+ void KviTalIconView::redirect_pressed(QIconViewItem * pItem)
+ {
+ emit pressed((KviTalIconViewItem *)pItem);
+ }
+
+ void KviTalIconView::redirect_pressed(QIconViewItem * pItem,const QPoint &pnt)
+ {
+ emit pressed((KviTalIconViewItem *)pItem,pnt);
+ }
+
+ void KviTalIconView::redirect_doubleClicked(QIconViewItem * pItem)
+ {
+ emit doubleClicked((KviTalIconViewItem *)pItem);
+ }
+
+ void KviTalIconView::redirect_returnPressed(QIconViewItem * pItem)
+ {
+ emit returnPressed((KviTalIconViewItem *)pItem);
+ }
+
+ void KviTalIconView::redirect_rightButtonClicked(QIconViewItem * pItem,const QPoint &pnt)
+ {
+ emit rightButtonClicked((KviTalIconViewItem *)pItem,pnt);
+ }
+
+ void KviTalIconView::redirect_rightButtonPressed(QIconViewItem * pItem,const QPoint &pnt)
+ {
+ emit rightButtonPressed((KviTalIconViewItem *)pItem,pnt);
+ }
+
+ void KviTalIconView::redirect_mouseButtonClicked(int iButton,QIconViewItem * pItem,const QPoint &pnt)
+ {
+ emit mouseButtonClicked(iButton,(KviTalIconViewItem *)pItem,pnt);
+ }
+
+ void KviTalIconView::redirect_mouseButtonPressed(int iButton,QIconViewItem * pItem,const QPoint &pnt)
+ {
+ emit mouseButtonPressed(iButton,(KviTalIconViewItem *)pItem,pnt);
+ }
+
+ void KviTalIconView::redirect_contextMenuRequested(QIconViewItem * pItem,const QPoint &pnt)
+ {
+ emit contextMenuRequested((KviTalIconViewItem *)pItem,pnt);
+ }
+
+ void KviTalIconView::redirect_onItem(QIconViewItem * pItem)
+ {
+ emit onItem((KviTalIconViewItem *)pItem);
+ }
+
+
+ #include "kvi_tal_iconview_qt3.moc"
+#endif
+
diff --git a/src/kvilib/tal/kvi_tal_iconview.h b/src/kvilib/tal/kvi_tal_iconview.h
new file mode 100644
index 00000000..53b1137b
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_iconview.h
@@ -0,0 +1,36 @@
+#ifndef _KVI_TAL_ICONVIEW_H_
+#define _KVI_TAL_ICONVIEW_H_
+
+//=============================================================================
+//
+// File : kvi_tal_iconview.h
+// Creation date : Mon Jan 22 2007 11:25:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_USE_QT4
+ #include "kvi_tal_iconview_qt4.h"
+#else
+ #include "kvi_tal_iconview_qt3.h"
+#endif
+
+#endif // _KVI_TAL_ICONVIEW_H_
diff --git a/src/kvilib/tal/kvi_tal_iconview_qt3.h b/src/kvilib/tal/kvi_tal_iconview_qt3.h
new file mode 100644
index 00000000..7cfec586
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_iconview_qt3.h
@@ -0,0 +1,100 @@
+#ifndef _KVI_TAL_ICONVIEW_QT3_H_
+#define _KVI_TAL_ICONVIEW_QT3_H_
+
+//=============================================================================
+//
+// File : kvi_tal_iconview_qt3.h
+// Creation date : Mon Jan 22 2007 11:25:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+
+#include <qiconview.h>
+
+class KviTalIconViewItem;
+
+
+class KVILIB_API KviTalIconView : public QIconView
+{
+ Q_OBJECT
+public:
+ KviTalIconView(QWidget * pParent,Qt::WFlags f = 0);
+ virtual ~KviTalIconView() {};
+signals:
+ void selectionChanged(KviTalIconViewItem * pItem);
+ void currentChanged(KviTalIconViewItem * pItem);
+ void clicked(KviTalIconViewItem * pItem);
+ void clicked(KviTalIconViewItem * pItem,const QPoint &pnt);
+ void pressed(KviTalIconViewItem * pItem);
+ void pressed(KviTalIconViewItem * pItem,const QPoint &pnt);
+ void doubleClicked(KviTalIconViewItem * pItem);
+ void returnPressed(KviTalIconViewItem * pItem);
+ void rightButtonClicked(KviTalIconViewItem * pItem,const QPoint &pnt);
+ void rightButtonPressed(KviTalIconViewItem * pItem,const QPoint &pnt);
+ void mouseButtonClicked(int iButton,KviTalIconViewItem * pItem,const QPoint &pnt);
+ void mouseButtonPressed(int iButton,KviTalIconViewItem * pItem,const QPoint &pnt);
+ void contextMenuRequested(KviTalIconViewItem * pItem,const QPoint &pnt);
+ void onItem(KviTalIconViewItem * pItem);
+protected slots:
+ void redirect_selectionChanged(QIconViewItem * pItem);
+ void redirect_currentChanged(QIconViewItem * pItem);
+ void redirect_clicked(QIconViewItem * pItem);
+ void redirect_clicked(QIconViewItem * pItem,const QPoint &pnt);
+ void redirect_pressed(QIconViewItem * pItem);
+ void redirect_pressed(QIconViewItem * pItem,const QPoint &pnt);
+ void redirect_doubleClicked(QIconViewItem * pItem);
+ void redirect_returnPressed(QIconViewItem * pItem);
+ void redirect_rightButtonClicked(QIconViewItem * pItem,const QPoint &pnt);
+ void redirect_rightButtonPressed(QIconViewItem * pItem,const QPoint &pnt);
+ void redirect_mouseButtonClicked(int iButton,QIconViewItem * pItem,const QPoint &pnt);
+ void redirect_mouseButtonPressed(int iButton,QIconViewItem * pItem,const QPoint &pnt);
+ void redirect_contextMenuRequested(QIconViewItem * pItem,const QPoint &pnt);
+ void redirect_onItem(QIconViewItem * pItem);
+public:
+ KviTalIconViewItem * firstItem() const { return (KviTalIconViewItem *)QIconView::firstItem(); };
+ KviTalIconViewItem * lastItem() const { return (KviTalIconViewItem *)QIconView::lastItem(); };
+ KviTalIconViewItem * currentItem() const { return (KviTalIconViewItem *)QIconView::currentItem(); };
+};
+
+class KVILIB_API KviTalIconViewItem : public QIconViewItem
+{
+public:
+ KviTalIconViewItem(KviTalIconView * parent)
+ : QIconViewItem(parent) {};
+ KviTalIconViewItem(KviTalIconView * parent,KviTalIconViewItem * after)
+ : QIconViewItem(parent,after) {};
+ KviTalIconViewItem(KviTalIconView * parent, const QString & text)
+ : QIconViewItem(parent,text) {};
+ KviTalIconViewItem(KviTalIconView * parent, KviTalIconViewItem * after, const QString & text)
+ : QIconViewItem(parent,after,text) {};
+ KviTalIconViewItem(KviTalIconView * parent, const QString & text, const QPixmap & icon)
+ : QIconViewItem(parent,text,icon) {};
+ KviTalIconViewItem(KviTalIconView * parent, KviTalIconViewItem * after, const QString & text, const QPixmap & icon)
+ : QIconViewItem(parent,after,text,icon) {};
+public:
+ KviTalIconView * iconView() const { return (KviTalIconView *)QIconViewItem::iconView(); };
+ KviTalIconViewItem * prevItem() const { return (KviTalIconViewItem *)QIconViewItem::prevItem(); };
+ KviTalIconViewItem * nextItem() const { return (KviTalIconViewItem *)QIconViewItem::nextItem(); };
+};
+
+
+#endif // _KVI_TAL_ICONVIEW_QT3_H_
diff --git a/src/kvilib/tal/kvi_tal_iconview_qt4.h b/src/kvilib/tal/kvi_tal_iconview_qt4.h
new file mode 100644
index 00000000..899acaac
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_iconview_qt4.h
@@ -0,0 +1,99 @@
+#ifndef _KVI_TAL_ICONVIEW_QT4_H_
+#define _KVI_TAL_ICONVIEW_QT4_H_
+
+//=============================================================================
+//
+// File : kvi_tal_iconview_qt4.h
+// Creation date : Mon Jan 22 2007 11:25:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) any later version.
+//
+// This program is distributed in the HOPE that it will be USEFUL,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc. ,59 Temple Place - Suite 440, Boston, MA 02111-1407, USA.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+
+#include <q3iconview.h>
+
+class KviTalIconViewItem;
+
+class KVILIB_API KviTalIconView : public Q3IconView
+{
+ Q_OBJECT
+public:
+ KviTalIconView(QWidget * pParent,Qt::WFlags f = 0);
+ virtual ~KviTalIconView() {};
+signals:
+ void selectionChanged(KviTalIconViewItem * pItem);
+ void currentChanged(KviTalIconViewItem * pItem);
+ void clicked(KviTalIconViewItem * pItem);
+ void clicked(KviTalIconViewItem * pItem,const QPoint &pnt);
+ void pressed(KviTalIconViewItem * pItem);
+ void pressed(KviTalIconViewItem * pItem,const QPoint &pnt);
+ void doubleClicked(KviTalIconViewItem * pItem);
+ void returnPressed(KviTalIconViewItem * pItem);
+ void rightButtonClicked(KviTalIconViewItem * pItem,const QPoint &pnt);
+ void rightButtonPressed(KviTalIconViewItem * pItem,const QPoint &pnt);
+ void mouseButtonClicked(int iButton,KviTalIconViewItem * pItem,const QPoint &pnt);
+ void mouseButtonPressed(int iButton,KviTalIconViewItem * pItem,const QPoint &pnt);
+ void contextMenuRequested(KviTalIconViewItem * pItem,const QPoint &pnt);
+ void onItem(KviTalIconViewItem * pItem);
+protected slots:
+ void redirect_selectionChanged(Q3IconViewItem * pItem);
+ void redirect_currentChanged(Q3IconViewItem * pItem);
+ void redirect_clicked(Q3IconViewItem * pItem);
+ void redirect_clicked(Q3IconViewItem * pItem,const QPoint &pnt);
+ void redirect_pressed(Q3IconViewItem * pItem);
+ void redirect_pressed(Q3IconViewItem * pItem,const QPoint &pnt);
+ void redirect_doubleClicked(Q3IconViewItem * pItem);
+ void redirect_returnPressed(Q3IconViewItem * pItem);
+ void redirect_rightButtonClicked(Q3IconViewItem * pItem,const QPoint &pnt);
+ void redirect_rightButtonPressed(Q3IconViewItem * pItem,const QPoint &pnt);
+ void redirect_mouseButtonClicked(int iButton,Q3IconViewItem * pItem,const QPoint &pnt);
+ void redirect_mouseButtonPressed(int iButton,Q3IconViewItem * pItem,const QPoint &pnt);
+ void redirect_contextMenuRequested(Q3IconViewItem * pItem,const QPoint &pnt);
+ void redirect_onItem(Q3IconViewItem * pItem);
+public:
+ KviTalIconViewItem * firstItem() const { return (KviTalIconViewItem *)Q3IconView::firstItem(); };
+ KviTalIconViewItem * lastItem() const { return (KviTalIconViewItem *)Q3IconView::lastItem(); };
+ KviTalIconViewItem * currentItem() const { return (KviTalIconViewItem *)Q3IconView::currentItem(); };
+};
+
+class KVILIB_API KviTalIconViewItem : public Q3IconViewItem
+{
+public:
+ KviTalIconViewItem(KviTalIconView * parent)
+ : Q3IconViewItem(parent) {};
+ KviTalIconViewItem(KviTalIconView * parent,KviTalIconViewItem * after)
+ : Q3IconViewItem(parent,after) {};
+ KviTalIconViewItem(KviTalIconView * parent, const QString & text)
+ : Q3IconViewItem(parent,text) {};
+ KviTalIconViewItem(KviTalIconView * parent, KviTalIconViewItem * after, const QString & text)
+ : Q3IconViewItem(parent,after,text) {};
+ KviTalIconViewItem(KviTalIconView * parent, const QString & text, const QPixmap & icon)
+ : Q3IconViewItem(parent,text,icon) {};
+ KviTalIconViewItem(KviTalIconView * parent, KviTalIconViewItem * after, const QString & text, const QPixmap & icon)
+ : Q3IconViewItem(parent,after,text,icon) {};
+public:
+ KviTalIconView * iconView() const { return (KviTalIconView *)Q3IconViewItem::iconView(); };
+ KviTalIconViewItem * prevItem() const { return (KviTalIconViewItem *)Q3IconViewItem::prevItem(); };
+ KviTalIconViewItem * nextItem() const { return (KviTalIconViewItem *)Q3IconViewItem::nextItem(); };
+};
+
+
+#endif // _KVI_TAL_ICONVIEW_QT4_H_
diff --git a/src/kvilib/tal/kvi_tal_listbox.cpp b/src/kvilib/tal/kvi_tal_listbox.cpp
new file mode 100644
index 00000000..f5fcc087
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_listbox.cpp
@@ -0,0 +1,513 @@
+//=============================================================================
+//
+// File : kvi_tal_listbox.cpp
+// Creation date : Mon Jan 22 2007 11:25:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+#include "kvi_tal_listbox.h"
+
+#ifdef COMPILE_USE_QT4
+ #include <qpainter.h>
+ #include <qstyle.h>
+ #include <qapplication.h>
+
+ KviTalListBox::KviTalListBox(QWidget * pParent,Qt::WFlags f)
+ : Q3ListBox(pParent,0,f)
+ {
+ connect(this,SIGNAL(highlighted(Q3ListBoxItem *)),this,SLOT(redirect_highlighted(Q3ListBoxItem *)));
+ connect(this,SIGNAL(selected(Q3ListBoxItem *)),this,SLOT(redirect_selected(Q3ListBoxItem *)));
+ connect(this,SIGNAL(selectionChanged(Q3ListBoxItem *)),this,SLOT(redirect_selectionChanged(Q3ListBoxItem *)));
+ connect(this,SIGNAL(currentChanged(Q3ListBoxItem *)),this,SLOT(redirect_currentChanged(Q3ListBoxItem *)));
+ connect(this,SIGNAL(clicked(Q3ListBoxItem *)),this,SLOT(redirect_clicked(Q3ListBoxItem *)));
+ connect(this,SIGNAL(clicked(Q3ListBoxItem *,const QPoint &)),this,SLOT(redirect_clicked(Q3ListBoxItem *,const QPoint &)));
+ connect(this,SIGNAL(pressed(Q3ListBoxItem *)),this,SLOT(redirect_pressed(Q3ListBoxItem *)));
+ connect(this,SIGNAL(pressed(Q3ListBoxItem *,const QPoint &)),this,SLOT(redirect_pressed(Q3ListBoxItem *,const QPoint &)));
+ connect(this,SIGNAL(doubleClicked(Q3ListBoxItem *)),this,SLOT(redirect_doubleClicked(Q3ListBoxItem *)));
+ connect(this,SIGNAL(returnPressed(Q3ListBoxItem *)),this,SLOT(redirect_returnPressed(Q3ListBoxItem *)));
+ connect(this,SIGNAL(rightButtonClicked(Q3ListBoxItem *, const QPoint &)),this,SLOT(redirect_rightButtonClicked(Q3ListBoxItem *, const QPoint &)));
+ connect(this,SIGNAL(rightButtonPressed(Q3ListBoxItem *, const QPoint &)),this,SLOT(redirect_rightButtonPressed(Q3ListBoxItem *, const QPoint &)));
+ connect(this,SIGNAL(mouseButtonPressed(int,Q3ListBoxItem *,const QPoint &)),this,SLOT(redirect_mouseButtonPressed(int,Q3ListBoxItem *,const QPoint &)));
+ connect(this,SIGNAL(mouseButtonClicked(int,Q3ListBoxItem *,const QPoint &)),this,SLOT(redirect_mouseButtonClicked(int,Q3ListBoxItem *,const QPoint &)));
+ connect(this,SIGNAL(contextMenuRequested(Q3ListBoxItem *,const QPoint &)),this,SLOT(redirect_contextMenuRequested(Q3ListBoxItem *,const QPoint &)));
+ connect(this,SIGNAL(onItem(Q3ListBoxItem *)),this,SLOT(redirect_onItem(Q3ListBoxItem *)));
+ }
+
+ void KviTalListBox::redirect_highlighted(Q3ListBoxItem *item)
+ {
+ emit highlighted((KviTalListBoxItem *)item);
+ }
+
+ void KviTalListBox::redirect_selected(Q3ListBoxItem *item)
+ {
+ emit selected((KviTalListBoxItem *)item);
+ }
+
+ void KviTalListBox::redirect_selectionChanged(Q3ListBoxItem * item)
+ {
+ emit selectionChanged((KviTalListBoxItem *)item);
+ }
+
+ void KviTalListBox::redirect_currentChanged(Q3ListBoxItem * item)
+ {
+ emit currentChanged((KviTalListBoxItem *)item);
+ }
+
+ void KviTalListBox::redirect_clicked(Q3ListBoxItem * item)
+ {
+ emit clicked((KviTalListBoxItem *)item);
+ }
+
+ void KviTalListBox::redirect_clicked(Q3ListBoxItem * item,const QPoint & pnt)
+ {
+ emit clicked((KviTalListBoxItem *)item,pnt);
+ }
+
+ void KviTalListBox::redirect_pressed(Q3ListBoxItem * item)
+ {
+ emit pressed((KviTalListBoxItem *)item);
+ }
+
+ void KviTalListBox::redirect_pressed(Q3ListBoxItem * item,const QPoint & pnt)
+ {
+ emit pressed((KviTalListBoxItem *)item,pnt);
+ }
+
+ void KviTalListBox::redirect_doubleClicked(Q3ListBoxItem * item)
+ {
+ emit doubleClicked((KviTalListBoxItem *)item);
+ }
+
+ void KviTalListBox::redirect_returnPressed(Q3ListBoxItem * item)
+ {
+ emit returnPressed((KviTalListBoxItem *)item);
+ }
+
+ void KviTalListBox::redirect_rightButtonClicked(Q3ListBoxItem * item, const QPoint &pnt)
+ {
+ emit rightButtonClicked((KviTalListBoxItem *)item,pnt);
+ }
+
+ void KviTalListBox::redirect_rightButtonPressed(Q3ListBoxItem * item, const QPoint &pnt)
+ {
+ emit rightButtonPressed((KviTalListBoxItem *)item,pnt);
+ }
+
+ void KviTalListBox::redirect_mouseButtonPressed(int button,Q3ListBoxItem * item,const QPoint & pos)
+ {
+ emit mouseButtonPressed(button,(KviTalListBoxItem *)item,pos);
+ }
+
+ void KviTalListBox::redirect_mouseButtonClicked(int button,Q3ListBoxItem * item,const QPoint & pos)
+ {
+ emit mouseButtonClicked(button,(KviTalListBoxItem *)item,pos);
+ }
+
+ void KviTalListBox::redirect_contextMenuRequested(Q3ListBoxItem * item,const QPoint & pos)
+ {
+ emit contextMenuRequested((KviTalListBoxItem *)item,pos);
+ }
+
+ void KviTalListBox::redirect_onItem(Q3ListBoxItem * i)
+ {
+ emit onItem((KviTalListBoxItem *)i);
+ }
+
+ KviTalListBoxText::KviTalListBoxText(KviTalListBox *listbox, const QString &text)
+ :KviTalListBoxItem(listbox)
+ {
+ setText(text);
+ }
+
+ KviTalListBoxText::KviTalListBoxText(const QString &text)
+ :KviTalListBoxItem()
+ {
+ setText(text);
+ }
+
+ KviTalListBoxText::KviTalListBoxText(KviTalListBox* listbox, const QString &text, KviTalListBoxItem *after)
+ : KviTalListBoxItem(listbox, after)
+ {
+ setText(text);
+ }
+
+ KviTalListBoxText::~KviTalListBoxText()
+ {
+ }
+
+ void KviTalListBoxText::paint(QPainter *painter)
+ {
+ int itemHeight = height(listBox());
+ QFontMetrics fm = painter->fontMetrics();
+ int yPos = ((itemHeight - fm.height()) / 2) + fm.ascent();
+ painter->drawText(3, yPos, text());
+ }
+
+ int KviTalListBoxText::height(const KviTalListBox* lb) const
+ {
+ int h = lb ? lb->fontMetrics().lineSpacing() + 2 : 0;
+ return qMax(h, QApplication::globalStrut().height());
+ }
+
+ int KviTalListBoxText::width(const KviTalListBox* lb) const
+ {
+ int w = lb ? lb->fontMetrics().width(text()) + 6 : 0;
+ return qMax(w, QApplication::globalStrut().width());
+ }
+
+ int KviTalListBoxText::rtti() const
+ {
+ return RTTI;
+ }
+
+ KviTalListBoxPixmap::KviTalListBoxPixmap(KviTalListBox* listbox, const QPixmap &pixmap)
+ : KviTalListBoxItem(listbox)
+ {
+ pm = pixmap;
+ }
+
+ KviTalListBoxPixmap::KviTalListBoxPixmap(const QPixmap &pixmap)
+ : KviTalListBoxItem()
+ {
+ pm = pixmap;
+ }
+
+ KviTalListBoxPixmap::KviTalListBoxPixmap(KviTalListBox* listbox, const QPixmap &pixmap, KviTalListBoxItem *after)
+ : KviTalListBoxItem(listbox, after)
+ {
+ pm = pixmap;
+ }
+
+ KviTalListBoxPixmap::~KviTalListBoxPixmap()
+ {
+ }
+
+ KviTalListBoxPixmap::KviTalListBoxPixmap(KviTalListBox* listbox, const QPixmap &pix, const QString& text)
+ : KviTalListBoxItem(listbox)
+ {
+ pm = pix;
+ setText(text);
+ }
+
+ KviTalListBoxPixmap::KviTalListBoxPixmap(const QPixmap & pix, const QString& text)
+ : KviTalListBoxItem()
+ {
+ pm = pix;
+ setText(text);
+ }
+
+ KviTalListBoxPixmap::KviTalListBoxPixmap(KviTalListBox* listbox, const QPixmap & pix, const QString& text,
+ KviTalListBoxItem *after)
+ : KviTalListBoxItem(listbox, after)
+ {
+ pm = pix;
+ setText(text);
+ }
+
+ void KviTalListBoxPixmap::paint(QPainter *painter)
+ {
+ int itemHeight = height(listBox());
+ int yPos;
+
+ const QPixmap *pm = pixmap();
+ if (pm && ! pm->isNull()) {
+ yPos = (itemHeight - pm->height()) / 2;
+ painter->drawPixmap(3, yPos, *pm);
+ }
+
+ if (!text().isEmpty()) {
+ QFontMetrics fm = painter->fontMetrics();
+ yPos = ((itemHeight - fm.height()) / 2) + fm.ascent();
+ painter->drawText(pm->width() + 5, yPos, text());
+ }
+ }
+
+ int KviTalListBoxPixmap::height(const KviTalListBox* lb) const
+ {
+ int h;
+ if (text().isEmpty())
+ h = pm.height();
+ else
+ h = qMax(pm.height(), lb->fontMetrics().lineSpacing() + 2);
+ return qMax(h, QApplication::globalStrut().height());
+ }
+
+ int KviTalListBoxPixmap::width(const KviTalListBox* lb) const
+ {
+ if (text().isEmpty())
+ return qMax(pm.width() + 6, QApplication::globalStrut().width());
+ return qMax(pm.width() + lb->fontMetrics().width(text()) + 6,
+ QApplication::globalStrut().width());
+ }
+
+ int KviTalListBoxPixmap::rtti() const
+ {
+ return RTTI;
+ }
+
+
+ #include "kvi_tal_listbox_qt4.moc"
+#else
+ #include <qpainter.h>
+ #include <qstyle.h>
+ #include <qapplication.h>
+
+
+ KviTalListBox::KviTalListBox(QWidget * pParent,Qt::WFlags f)
+ : QListBox(pParent,0,f)
+ {
+ connect(this,SIGNAL(highlighted(QListBoxItem *)),this,SLOT(redirect_highlighted(QListBoxItem *)));
+ connect(this,SIGNAL(selected(QListBoxItem *)),this,SLOT(redirect_selected(QListBoxItem *)));
+ connect(this,SIGNAL(selectionChanged(QListBoxItem *)),this,SLOT(redirect_selectionChanged(QListBoxItem *)));
+ connect(this,SIGNAL(currentChanged(QListBoxItem *)),this,SLOT(redirect_currentChanged(QListBoxItem *)));
+ connect(this,SIGNAL(clicked(QListBoxItem *)),this,SLOT(redirect_clicked(QListBoxItem *)));
+ connect(this,SIGNAL(clicked(QListBoxItem *,const QPoint &)),this,SLOT(redirect_clicked(QListBoxItem *,const QPoint &)));
+ connect(this,SIGNAL(pressed(QListBoxItem *)),this,SLOT(redirect_pressed(QListBoxItem *)));
+ connect(this,SIGNAL(pressed(QListBoxItem *,const QPoint &)),this,SLOT(redirect_pressed(QListBoxItem *,const QPoint &)));
+ connect(this,SIGNAL(doubleClicked(QListBoxItem *)),this,SLOT(redirect_doubleClicked(QListBoxItem *)));
+ connect(this,SIGNAL(returnPressed(QListBoxItem *)),this,SLOT(redirect_returnPressed(QListBoxItem *)));
+ connect(this,SIGNAL(rightButtonClicked(QListBoxItem *, const QPoint &)),this,SLOT(redirect_rightButtonClicked(QListBoxItem *, const QPoint &)));
+ connect(this,SIGNAL(rightButtonPressed(QListBoxItem *, const QPoint &)),this,SLOT(redirect_rightButtonPressed(QListBoxItem *, const QPoint &)));
+ connect(this,SIGNAL(mouseButtonPressed(int,QListBoxItem *,const QPoint &)),this,SLOT(redirect_mouseButtonPressed(int,QListBoxItem *,const QPoint &)));
+ connect(this,SIGNAL(mouseButtonClicked(int,QListBoxItem *,const QPoint &)),this,SLOT(redirect_mouseButtonClicked(int,QListBoxItem *,const QPoint &)));
+ connect(this,SIGNAL(contextMenuRequested(QListBoxItem *,const QPoint &)),this,SLOT(redirect_contextMenuRequested(QListBoxItem *,const QPoint &)));
+ connect(this,SIGNAL(onItem(QListBoxItem *)),this,SLOT(redirect_onItem(QListBoxItem *)));
+ }
+
+ void KviTalListBox::redirect_highlighted(QListBoxItem *item)
+ {
+ emit highlighted((KviTalListBoxItem *)item);
+ }
+
+ void KviTalListBox::redirect_selected(QListBoxItem *item)
+ {
+ emit selected((KviTalListBoxItem *)item);
+ }
+
+ void KviTalListBox::redirect_selectionChanged(QListBoxItem * item)
+ {
+ emit selectionChanged((KviTalListBoxItem *)item);
+ }
+
+ void KviTalListBox::redirect_currentChanged(QListBoxItem * item)
+ {
+ emit currentChanged((KviTalListBoxItem *)item);
+ }
+
+ void KviTalListBox::redirect_clicked(QListBoxItem * item)
+ {
+ emit clicked((KviTalListBoxItem *)item);
+ }
+
+ void KviTalListBox::redirect_clicked(QListBoxItem * item,const QPoint & pnt)
+ {
+ emit clicked((KviTalListBoxItem *)item,pnt);
+ }
+
+ void KviTalListBox::redirect_pressed(QListBoxItem * item)
+ {
+ emit pressed((KviTalListBoxItem *)item);
+ }
+
+ void KviTalListBox::redirect_pressed(QListBoxItem * item,const QPoint & pnt)
+ {
+ emit pressed((KviTalListBoxItem *)item,pnt);
+ }
+
+ void KviTalListBox::redirect_doubleClicked(QListBoxItem * item)
+ {
+ emit doubleClicked((KviTalListBoxItem *)item);
+ }
+
+ void KviTalListBox::redirect_returnPressed(QListBoxItem * item)
+ {
+ emit returnPressed((KviTalListBoxItem *)item);
+ }
+
+ void KviTalListBox::redirect_rightButtonClicked(QListBoxItem * item, const QPoint &pnt)
+ {
+ emit rightButtonClicked((KviTalListBoxItem *)item,pnt);
+ }
+
+ void KviTalListBox::redirect_rightButtonPressed(QListBoxItem * item, const QPoint &pnt)
+ {
+ emit rightButtonPressed((KviTalListBoxItem *)item,pnt);
+ }
+
+ void KviTalListBox::redirect_mouseButtonPressed(int button,QListBoxItem * item,const QPoint & pos)
+ {
+ emit mouseButtonPressed(button,(KviTalListBoxItem *)item,pos);
+ }
+
+ void KviTalListBox::redirect_mouseButtonClicked(int button,QListBoxItem * item,const QPoint & pos)
+ {
+ emit mouseButtonClicked(button,(KviTalListBoxItem *)item,pos);
+ }
+
+ void KviTalListBox::redirect_contextMenuRequested(QListBoxItem * item,const QPoint & pos)
+ {
+ emit contextMenuRequested((KviTalListBoxItem *)item,pos);
+ }
+
+ void KviTalListBox::redirect_onItem(QListBoxItem * i)
+ {
+ emit onItem((KviTalListBoxItem *)i);
+ }
+
+ KviTalListBoxText::KviTalListBoxText( KviTalListBox *listbox, const QString &text )
+ :KviTalListBoxItem( listbox )
+ {
+ setText( text );
+ }
+
+ KviTalListBoxText::KviTalListBoxText( const QString &text )
+ :KviTalListBoxItem()
+ {
+ setText( text );
+ }
+
+ KviTalListBoxText::KviTalListBoxText( KviTalListBox* listbox, const QString &text, KviTalListBoxItem *after )
+ : KviTalListBoxItem( listbox, after )
+ {
+ setText( text );
+ }
+
+ KviTalListBoxText::~KviTalListBoxText()
+ {
+ }
+
+ void KviTalListBoxText::paint( QPainter *painter )
+ {
+ int itemHeight = height( listBox() );
+ QFontMetrics fm = painter->fontMetrics();
+ int yPos = ( ( itemHeight - fm.height() ) / 2 ) + fm.ascent();
+ painter->drawText( 3, yPos, text() );
+ }
+
+ int KviTalListBoxText::height( const KviTalListBox* lb ) const
+ {
+ int h = lb ? lb->fontMetrics().lineSpacing() + 2 : 0;
+ return QMAX( h, QApplication::globalStrut().height() );
+ }
+
+ int KviTalListBoxText::width( const KviTalListBox* lb ) const
+ {
+ int w = lb ? lb->fontMetrics().width( text() ) + 6 : 0;
+ return QMAX( w, QApplication::globalStrut().width() );
+ }
+
+ int KviTalListBoxText::RTTI = 1;
+
+ int KviTalListBoxText::rtti() const
+ {
+ return RTTI;
+ }
+
+ KviTalListBoxPixmap::KviTalListBoxPixmap( KviTalListBox* listbox, const QPixmap &pixmap )
+ : KviTalListBoxItem( listbox )
+ {
+ pm = pixmap;
+ }
+
+ KviTalListBoxPixmap::KviTalListBoxPixmap( const QPixmap &pixmap )
+ : KviTalListBoxItem()
+ {
+ pm = pixmap;
+ }
+
+ KviTalListBoxPixmap::KviTalListBoxPixmap( KviTalListBox* listbox, const QPixmap &pixmap, KviTalListBoxItem *after )
+ : KviTalListBoxItem( listbox, after )
+ {
+ pm = pixmap;
+ }
+
+ KviTalListBoxPixmap::~KviTalListBoxPixmap()
+ {
+ }
+
+ KviTalListBoxPixmap::KviTalListBoxPixmap( KviTalListBox* listbox, const QPixmap &pix, const QString& text)
+ : KviTalListBoxItem( listbox )
+ {
+ pm = pix;
+ setText( text );
+ }
+
+ KviTalListBoxPixmap::KviTalListBoxPixmap( const QPixmap & pix, const QString& text)
+ : KviTalListBoxItem()
+ {
+ pm = pix;
+ setText( text );
+ }
+
+ KviTalListBoxPixmap::KviTalListBoxPixmap( KviTalListBox* listbox, const QPixmap & pix, const QString& text,
+ KviTalListBoxItem *after )
+ : KviTalListBoxItem( listbox, after )
+ {
+ pm = pix;
+ setText( text );
+ }
+
+ void KviTalListBoxPixmap::paint( QPainter *painter )
+ {
+ int itemHeight = height( listBox() );
+ int yPos;
+
+ const QPixmap *pm = pixmap();
+ if ( pm && ! pm->isNull() ) {
+ yPos = ( itemHeight - pm->height() ) / 2;
+ painter->drawPixmap( 3, yPos, *pm);
+ }
+
+ if ( !text().isEmpty() ) {
+ QFontMetrics fm = painter->fontMetrics();
+ yPos = ( ( itemHeight - fm.height() ) / 2 ) + fm.ascent();
+ painter->drawText( pm->width() + 5, yPos, text() );
+ }
+ }
+
+ int KviTalListBoxPixmap::height( const KviTalListBox* lb ) const
+ {
+ int h;
+ if ( text().isEmpty() )
+ h = pm.height();
+ else
+ h = QMAX( pm.height(), lb->fontMetrics().lineSpacing() + 2 );
+ return QMAX( h, QApplication::globalStrut().height() );
+ }
+
+ int KviTalListBoxPixmap::width( const KviTalListBox* lb ) const
+ {
+ if ( text().isEmpty() )
+ return QMAX( pm.width() + 6, QApplication::globalStrut().width() );
+ return QMAX( pm.width() + lb->fontMetrics().width( text() ) + 6,
+ QApplication::globalStrut().width() );
+ }
+
+ int KviTalListBoxPixmap::RTTI = 2;
+
+ int KviTalListBoxPixmap::rtti() const
+ {
+ return RTTI;
+ }
+
+ #include "kvi_tal_listbox_qt3.moc"
+#endif
+
diff --git a/src/kvilib/tal/kvi_tal_listbox.h b/src/kvilib/tal/kvi_tal_listbox.h
new file mode 100644
index 00000000..18594539
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_listbox.h
@@ -0,0 +1,50 @@
+#ifndef _KVI_TAL_LISTBOX_H_
+#define _KVI_TAL_LISTBOX_H_
+
+//=============================================================================
+//
+// File : kvi_tal_listbox.h
+// Creation date : Mon Jan 22 2007 11:25:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+//
+// This is the only reasonable CROSS-QT3-QT4-COMPATIBLE implementation
+// of QListBox I've been able to find.
+// Note that using macros for the items will NOT work since moc
+// doesn't expand them. Note also that KviTalListBoxText must
+// be fully reimplemented and not be inherited from QListBoxText
+// to build up a consistent item object hierarchy. To complete
+// the obscenity, we need TWO COMPLETE implementations: one for Qt3
+// and one for Qt4... bleah :D
+//
+// The code for KviTalListBoxText is adapted from qlistbox.h/cpp
+// present in qt 3.3.6 AND in qt 4.1.2.
+//
+
+#ifdef COMPILE_USE_QT4
+ #include "kvi_tal_listbox_qt4.h"
+#else
+ #include "kvi_tal_listbox_qt3.h"
+#endif
+
+#endif // _KVI_TAL_LISTBOX_H_
diff --git a/src/kvilib/tal/kvi_tal_listbox_qt3.h b/src/kvilib/tal/kvi_tal_listbox_qt3.h
new file mode 100644
index 00000000..d65b7929
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_listbox_qt3.h
@@ -0,0 +1,157 @@
+#ifndef _KVI_TAL_LISTBOX_QT3_H_
+#define _KVI_TAL_LISTBOX_QT3_H_
+
+//=============================================================================
+//
+// File : kvi_tal_listbox_qt3.h
+// Creation date : Mon Jan 22 2007 11:25:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include <qlistbox.h>
+
+class KviTalListBoxItem;
+
+class KVILIB_API KviTalListBox : public QListBox
+{
+ Q_OBJECT
+public:
+ KviTalListBox(QWidget * pParent,Qt::WFlags f = 0);
+ virtual ~KviTalListBox() {};
+public:
+ KviTalListBoxItem * firstItem() const { return (KviTalListBoxItem *)QListBox::firstItem(); };
+ KviTalListBoxItem * selectedItem() const { return (KviTalListBoxItem *)QListBox::selectedItem(); };
+ KviTalListBoxItem * item(int iIndex) const { return (KviTalListBoxItem *)QListBox::item(iIndex); };
+signals:
+ void highlighted(KviTalListBoxItem *);
+ void selected(KviTalListBoxItem *);
+ void selectionChanged(KviTalListBoxItem * item);
+ void currentChanged(KviTalListBoxItem * item);
+ void clicked(KviTalListBoxItem * item);
+ void clicked(KviTalListBoxItem * item,const QPoint & pnt);
+ void pressed(KviTalListBoxItem * item);
+ void pressed(KviTalListBoxItem * item,const QPoint & pnt);
+ void doubleClicked(KviTalListBoxItem * item);
+ void returnPressed(KviTalListBoxItem * item);
+ void rightButtonClicked(KviTalListBoxItem *, const QPoint &);
+ void rightButtonPressed(KviTalListBoxItem *, const QPoint &);
+ void mouseButtonPressed(int button,KviTalListBoxItem * item,const QPoint & pos);
+ void mouseButtonClicked(int button,KviTalListBoxItem * item,const QPoint & pos);
+ void contextMenuRequested(KviTalListBoxItem * item,const QPoint & pos);
+ void onItem(KviTalListBoxItem * i);
+protected slots:
+ void redirect_highlighted(QListBoxItem *item);
+ void redirect_selected(QListBoxItem *item);
+ void redirect_selectionChanged(QListBoxItem * item);
+ void redirect_currentChanged(QListBoxItem * item);
+ void redirect_clicked(QListBoxItem * item);
+ void redirect_clicked(QListBoxItem * item,const QPoint & pnt);
+ void redirect_pressed(QListBoxItem * item);
+ void redirect_pressed(QListBoxItem * item,const QPoint & pnt);
+ void redirect_doubleClicked(QListBoxItem * item);
+ void redirect_returnPressed(QListBoxItem * item);
+ void redirect_rightButtonClicked(QListBoxItem * item, const QPoint &pnt);
+ void redirect_rightButtonPressed(QListBoxItem * item, const QPoint &pnt);
+ void redirect_mouseButtonPressed(int button,QListBoxItem * item,const QPoint & pos);
+ void redirect_mouseButtonClicked(int button,QListBoxItem * item,const QPoint & pos);
+ void redirect_contextMenuRequested(QListBoxItem * item,const QPoint & pos);
+ void redirect_onItem(QListBoxItem * i);
+};
+
+class KVILIB_API KviTalListBoxItem : public QListBoxItem
+{
+public:
+ KviTalListBoxItem()
+ : QListBoxItem() {};
+ KviTalListBoxItem(KviTalListBox * pParent)
+ : QListBoxItem(pParent) {};
+ KviTalListBoxItem(KviTalListBox * pParent,KviTalListBoxItem * pAfter)
+ : QListBoxItem(pParent,pAfter) {};
+ virtual ~KviTalListBoxItem() {};
+public:
+ KviTalListBoxItem * next() const { return (KviTalListBoxItem *)QListBoxItem::next(); };
+ KviTalListBoxItem * prev() const { return (KviTalListBoxItem *)QListBoxItem::prev(); };
+ KviTalListBox * listBox() const { return (KviTalListBox *)QListBoxItem::listBox(); };
+ virtual int height(const KviTalListBox *) const { return 0; };
+ int height(const QListBox *lb) const { return height((KviTalListBox *)lb); };
+ virtual int width(const KviTalListBox *) const { return 0; };
+ int width(const QListBox *lb) const { return width((KviTalListBox *)lb); };
+};
+
+class KVILIB_API KviTalListBoxText : public KviTalListBoxItem
+{
+public:
+ KviTalListBoxText( KviTalListBox* listbox, const QString & text=QString::null );
+ KviTalListBoxText( const QString & text=QString::null );
+ KviTalListBoxText( KviTalListBox* listbox, const QString & text, KviTalListBoxItem *after );
+ ~KviTalListBoxText();
+
+ int height( const KviTalListBox * ) const;
+ int width( const KviTalListBox * ) const;
+
+ int rtti() const;
+ static int RTTI;
+
+protected:
+ virtual void paint( QPainter * );
+
+private: // Disabled copy constructor and operator=
+#if defined(Q_DISABLE_COPY)
+ KviTalListBoxText( const KviTalListBoxText & );
+ KviTalListBoxText &operator=( const KviTalListBoxText & );
+#endif
+};
+
+
+class KVILIB_API KviTalListBoxPixmap : public KviTalListBoxItem
+{
+public:
+ KviTalListBoxPixmap( KviTalListBox* listbox, const QPixmap & );
+ KviTalListBoxPixmap( const QPixmap & );
+ KviTalListBoxPixmap( KviTalListBox* listbox, const QPixmap & pix, KviTalListBoxItem *after );
+ KviTalListBoxPixmap( KviTalListBox* listbox, const QPixmap &, const QString& );
+ KviTalListBoxPixmap( const QPixmap &, const QString& );
+ KviTalListBoxPixmap( KviTalListBox* listbox, const QPixmap & pix, const QString&, KviTalListBoxItem *after );
+ ~KviTalListBoxPixmap();
+
+ const QPixmap *pixmap() const { return &pm; }
+
+ int height( const KviTalListBox * ) const;
+ int width( const KviTalListBox * ) const;
+
+ int rtti() const;
+ static int RTTI;
+
+protected:
+ virtual void paint( QPainter * );
+
+private:
+ QPixmap pm;
+private: // Disabled copy constructor and operator=
+#if defined(Q_DISABLE_COPY)
+ KviTalListBoxPixmap( const KviTalListBoxPixmap & );
+ KviTalListBoxPixmap &operator=( const KviTalListBoxPixmap & );
+#endif
+};
+
+
+#endif // _KVI_TAL_LISTBOX_QT3_H_
diff --git a/src/kvilib/tal/kvi_tal_listbox_qt4.h b/src/kvilib/tal/kvi_tal_listbox_qt4.h
new file mode 100644
index 00000000..dcb92f4d
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_listbox_qt4.h
@@ -0,0 +1,152 @@
+#ifndef _KVI_TAL_LISTBOX_QT4_H_
+#define _KVI_TAL_LISTBOX_QT4_H_
+
+//=============================================================================
+//
+// File : kvi_tal_listbox_qt4.h
+// Creation date : Mon Jan 22 2007 11:25:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#include <q3listbox.h>
+
+class KviTalListBoxItem;
+
+
+class KVILIB_API KviTalListBox : public Q3ListBox
+{
+ Q_OBJECT
+public:
+ KviTalListBox(QWidget * pParent,Qt::WFlags f = 0);
+ virtual ~KviTalListBox() {};
+public:
+ KviTalListBoxItem * firstItem() const { return (KviTalListBoxItem *)Q3ListBox::firstItem(); };
+ KviTalListBoxItem * selectedItem() const { return (KviTalListBoxItem *)Q3ListBox::selectedItem(); };
+ KviTalListBoxItem * item(int iIndex) const { return (KviTalListBoxItem *)Q3ListBox::item(iIndex); };
+signals:
+ void highlighted(KviTalListBoxItem *);
+ void selected(KviTalListBoxItem *);
+ void selectionChanged(KviTalListBoxItem * item);
+ void currentChanged(KviTalListBoxItem * item);
+ void clicked(KviTalListBoxItem * item);
+ void clicked(KviTalListBoxItem * item,const QPoint & pnt);
+ void pressed(KviTalListBoxItem * item);
+ void pressed(KviTalListBoxItem * item,const QPoint & pnt);
+ void doubleClicked(KviTalListBoxItem * item);
+ void returnPressed(KviTalListBoxItem * item);
+ void rightButtonClicked(KviTalListBoxItem *, const QPoint &);
+ void rightButtonPressed(KviTalListBoxItem *, const QPoint &);
+ void mouseButtonPressed(int button,KviTalListBoxItem * item,const QPoint & pos);
+ void mouseButtonClicked(int button,KviTalListBoxItem * item,const QPoint & pos);
+ void contextMenuRequested(KviTalListBoxItem * item,const QPoint & pos);
+ void onItem(KviTalListBoxItem * i);
+protected slots:
+ void redirect_highlighted(Q3ListBoxItem *);
+ void redirect_selected(Q3ListBoxItem *);
+ void redirect_selectionChanged(Q3ListBoxItem * item);
+ void redirect_currentChanged(Q3ListBoxItem * item);
+ void redirect_clicked(Q3ListBoxItem * item);
+ void redirect_clicked(Q3ListBoxItem * item,const QPoint & pnt);
+ void redirect_pressed(Q3ListBoxItem * item);
+ void redirect_pressed(Q3ListBoxItem * item,const QPoint & pnt);
+ void redirect_doubleClicked(Q3ListBoxItem * item);
+ void redirect_returnPressed(Q3ListBoxItem *);
+ void redirect_rightButtonClicked(Q3ListBoxItem *, const QPoint &);
+ void redirect_rightButtonPressed(Q3ListBoxItem *, const QPoint &);
+ void redirect_mouseButtonPressed(int button,Q3ListBoxItem * item,const QPoint & pos);
+ void redirect_mouseButtonClicked(int button,Q3ListBoxItem * item,const QPoint & pos);
+ void redirect_contextMenuRequested(Q3ListBoxItem * item,const QPoint & pos);
+ void redirect_onItem(Q3ListBoxItem * i);
+};
+
+class KVILIB_API KviTalListBoxItem : public Q3ListBoxItem
+{
+public:
+ KviTalListBoxItem()
+ : Q3ListBoxItem() {};
+ KviTalListBoxItem(KviTalListBox * pParent)
+ : Q3ListBoxItem(pParent) {};
+ KviTalListBoxItem(KviTalListBox * pParent,KviTalListBoxItem * pAfter)
+ : Q3ListBoxItem(pParent,pAfter) {};
+ virtual ~KviTalListBoxItem() {};
+public:
+ KviTalListBoxItem * next() const { return (KviTalListBoxItem *)Q3ListBoxItem::next(); };
+ KviTalListBoxItem * prev() const { return (KviTalListBoxItem *)Q3ListBoxItem::prev(); };
+ KviTalListBox * listBox() const { return (KviTalListBox *)Q3ListBoxItem::listBox(); };
+ virtual int height(const KviTalListBox *) const { return 0; };
+ int height(const Q3ListBox *lb) const { return height((KviTalListBox *)lb); };
+ virtual int width(const KviTalListBox *) const { return 0; };
+ int width(const Q3ListBox *lb) const { return width((KviTalListBox *)lb); };
+};
+
+
+class KVILIB_API KviTalListBoxText : public KviTalListBoxItem
+{
+public:
+ KviTalListBoxText(KviTalListBox* listbox, const QString & text=QString());
+ KviTalListBoxText(const QString & text=QString());
+ KviTalListBoxText(KviTalListBox* listbox, const QString & text, KviTalListBoxItem *after);
+ ~KviTalListBoxText();
+
+ int height(const KviTalListBox *) const;
+ int width(const KviTalListBox *) const;
+
+ int rtti() const;
+ enum { RTTI = 1 };
+
+protected:
+ virtual void paint(QPainter *);
+
+private:
+ Q_DISABLE_COPY(KviTalListBoxText)
+};
+
+
+class KVILIB_API KviTalListBoxPixmap : public KviTalListBoxItem
+{
+public:
+ KviTalListBoxPixmap(KviTalListBox* listbox, const QPixmap &);
+ KviTalListBoxPixmap(const QPixmap &);
+ KviTalListBoxPixmap(KviTalListBox* listbox, const QPixmap & pix, KviTalListBoxItem *after);
+ KviTalListBoxPixmap(KviTalListBox* listbox, const QPixmap &, const QString&);
+ KviTalListBoxPixmap(const QPixmap &, const QString&);
+ KviTalListBoxPixmap(KviTalListBox* listbox, const QPixmap & pix, const QString&, KviTalListBoxItem *after);
+ ~KviTalListBoxPixmap();
+
+ const QPixmap *pixmap() const { return &pm; }
+
+ int height(const KviTalListBox *) const;
+ int width(const KviTalListBox *) const;
+
+ int rtti() const;
+ enum { RTTI = 2 };
+
+protected:
+ virtual void paint(QPainter *);
+
+private:
+ Q_DISABLE_COPY(KviTalListBoxPixmap)
+
+ QPixmap pm;
+};
+
+#endif // _KVI_TAL_LISTBOX_QT4_H_
diff --git a/src/kvilib/tal/kvi_tal_listview.cpp b/src/kvilib/tal/kvi_tal_listview.cpp
new file mode 100644
index 00000000..01b253b3
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_listview.cpp
@@ -0,0 +1,1542 @@
+//=============================================================================
+//
+// File : kvi_tal_listview.cpp
+// Creation date : Mon Jan 22 2007 11:25:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+#include "kvi_tal_listview.h"
+
+#include "kvi_pointerhashtable.h"
+
+
+#ifdef COMPILE_USE_QT4
+ #include <qpainter.h>
+ #include <qstyle.h>
+ #include <q3header.h>
+ #include <qapplication.h>
+ #include <qhash.h>
+ #include <qstyleoption.h>
+ #include <qaccessible.h>
+
+ static QStyleOptionQ3ListView getStyleOption(const Q3ListView *lv, const Q3ListViewItem *item)
+ {
+ QStyleOptionQ3ListView opt;
+ opt.init(lv);
+ opt.subControls = QStyle::SC_None;
+ opt.activeSubControls = QStyle::SC_None;
+ QWidget *vp = lv->viewport();
+ opt.viewportPalette = vp->palette();
+ opt.viewportBGRole = vp->backgroundRole();
+ opt.itemMargin = lv->itemMargin();
+ opt.sortColumn = 0;
+ opt.treeStepSize = lv->treeStepSize();
+ opt.rootIsDecorated = lv->rootIsDecorated();
+ bool firstItem = true;
+ while (item) {
+ QStyleOptionQ3ListViewItem lvi;
+ lvi.height = item->height();
+ lvi.totalHeight = item->totalHeight();
+ lvi.itemY = item->itemPos();
+ lvi.childCount = item->childCount();
+ lvi.features = QStyleOptionQ3ListViewItem::None;
+ lvi.state = QStyle::State_None;
+ if (item->isEnabled())
+ lvi.state |= QStyle::State_Enabled;
+ if (item->isOpen())
+ lvi.state |= QStyle::State_Open;
+ if (item->isExpandable())
+ lvi.features |= QStyleOptionQ3ListViewItem::Expandable;
+ if (item->multiLinesEnabled())
+ lvi.features |= QStyleOptionQ3ListViewItem::MultiLine;
+ if (item->isVisible())
+ lvi.features |= QStyleOptionQ3ListViewItem::Visible;
+ if (item->parent() && item->parent()->rtti() == 1
+ && static_cast<Q3CheckListItem *>(item->parent())->type() == Q3CheckListItem::Controller)
+ lvi.features |= QStyleOptionQ3ListViewItem::ParentControl;
+ opt.items.append(lvi);
+ if (!firstItem) {
+ item = item->nextSibling();
+ } else {
+ firstItem = false;
+ item = item->firstChild();
+ }
+ }
+ return opt;
+ }
+
+ KviTalListView::KviTalListView(QWidget * pParent)
+ : Q3ListView(pParent)
+ {
+ connect(this,SIGNAL(selectionChanged(Q3ListViewItem *)),this,SLOT(redirect_selectionChanged(Q3ListViewItem *)));
+ connect(this,SIGNAL(currentChanged(Q3ListViewItem *)),this,SLOT(redirect_currentChanged(Q3ListViewItem *)));
+ connect(this,SIGNAL(clicked(Q3ListViewItem *)),this,SLOT(redirect_clicked(Q3ListViewItem *)));
+ connect(this,SIGNAL(clicked(Q3ListViewItem *,const QPoint &,int)),this,SLOT(redirect_clicked(Q3ListViewItem *,const QPoint &,int)));
+ connect(this,SIGNAL(pressed(Q3ListViewItem *)),this,SLOT(redirect_pressed(Q3ListViewItem *)));
+ connect(this,SIGNAL(pressed(Q3ListViewItem *,const QPoint &,int)),this,SLOT(redirect_pressed(Q3ListViewItem *,const QPoint &,int)));
+ connect(this,SIGNAL(doubleClicked(Q3ListViewItem *)),this,SLOT(redirect_doubleClicked(Q3ListViewItem *)));
+ connect(this,SIGNAL(doubleClicked(Q3ListViewItem *,const QPoint &,int)),this,SLOT(redirect_doubleClicked(Q3ListViewItem *,const QPoint &,int)));
+ connect(this,SIGNAL(returnPressed(Q3ListViewItem *)),this,SLOT(redirect_returnPressed(Q3ListViewItem *)));
+ connect(this,SIGNAL(spacePressed(Q3ListViewItem *)),this,SLOT(redirect_spacePressed(Q3ListViewItem *)));
+ connect(this,SIGNAL(rightButtonClicked(Q3ListViewItem *,const QPoint &,int)),this,SLOT(redirect_rightButtonClicked(Q3ListViewItem *,const QPoint &,int)));
+ connect(this,SIGNAL(rightButtonPressed(Q3ListViewItem *,const QPoint &,int)),this,SLOT(redirect_rightButtonPressed(Q3ListViewItem *,const QPoint &,int)));
+ connect(this,SIGNAL(mouseButtonClicked(int,Q3ListViewItem *,const QPoint &,int)),this,SLOT(redirect_mouseButtonClicked(int,Q3ListViewItem *,const QPoint &,int)));
+ connect(this,SIGNAL(mouseButtonPressed(int,Q3ListViewItem *,const QPoint &,int)),this,SLOT(redirect_mouseButtonPressed(int,Q3ListViewItem *,const QPoint &,int)));
+ connect(this,SIGNAL(contextMenuRequested(Q3ListViewItem *,const QPoint &,int)),this,SLOT(redirect_contextMenuRequested(Q3ListViewItem *,const QPoint &,int)));
+ connect(this,SIGNAL(onItem(Q3ListViewItem *)),this,SLOT(redirect_onItem(Q3ListViewItem *)));
+ connect(this,SIGNAL(expanded(Q3ListViewItem *)),this,SLOT(redirect_expanded(Q3ListViewItem *)));
+ connect(this,SIGNAL(collapsed(Q3ListViewItem *)),this,SLOT(redirect_collapsed(Q3ListViewItem *)));
+ }
+
+ void KviTalListView::redirect_selectionChanged(Q3ListViewItem * pItem)
+ {
+ emit selectionChanged((KviTalListViewItem *)pItem);
+ }
+
+ void KviTalListView::redirect_currentChanged(Q3ListViewItem * pItem)
+ {
+ emit currentChanged((KviTalListViewItem *)pItem);
+ }
+
+ void KviTalListView::redirect_clicked(Q3ListViewItem * pItem)
+ {
+ emit clicked((KviTalListViewItem *)pItem);
+ }
+
+ void KviTalListView::redirect_clicked(Q3ListViewItem * pItem,const QPoint &pnt,int uColumn)
+ {
+ emit clicked((KviTalListViewItem *)pItem,pnt,uColumn);
+ }
+
+ void KviTalListView::redirect_pressed(Q3ListViewItem * pItem)
+ {
+ emit pressed((KviTalListViewItem *)pItem);
+ }
+
+ void KviTalListView::redirect_pressed(Q3ListViewItem * pItem,const QPoint &pnt,int uColumn)
+ {
+ emit pressed((KviTalListViewItem *)pItem,pnt,uColumn);
+ }
+
+ void KviTalListView::redirect_doubleClicked(Q3ListViewItem * pItem)
+ {
+ emit doubleClicked((KviTalListViewItem *)pItem);
+ }
+
+ void KviTalListView::redirect_doubleClicked(Q3ListViewItem * pItem,const QPoint &pnt,int uColumn)
+ {
+ emit doubleClicked((KviTalListViewItem *)pItem,pnt,uColumn);
+ }
+
+ void KviTalListView::redirect_returnPressed(Q3ListViewItem * pItem)
+ {
+ emit returnPressed((KviTalListViewItem *)pItem);
+ }
+
+ void KviTalListView::redirect_spacePressed(Q3ListViewItem * pItem)
+ {
+ emit spacePressed((KviTalListViewItem *)pItem);
+ }
+
+ void KviTalListView::redirect_rightButtonClicked(Q3ListViewItem * pItem,const QPoint &pnt,int uColumn)
+ {
+ emit rightButtonClicked((KviTalListViewItem *)pItem,pnt,uColumn);
+ }
+
+ void KviTalListView::redirect_rightButtonPressed(Q3ListViewItem * pItem,const QPoint &pnt,int uColumn)
+ {
+ emit rightButtonPressed((KviTalListViewItem *)pItem,pnt,uColumn);
+ }
+
+ void KviTalListView::redirect_mouseButtonClicked(int iButton,Q3ListViewItem * pItem,const QPoint &pnt,int uColumn)
+ {
+ emit mouseButtonClicked(iButton,(KviTalListViewItem *)pItem,pnt,uColumn);
+ }
+
+ void KviTalListView::redirect_mouseButtonPressed(int iButton,Q3ListViewItem * pItem,const QPoint &pnt,int uColumn)
+ {
+ emit mouseButtonPressed(iButton,(KviTalListViewItem *)pItem,pnt,uColumn);
+ }
+
+ void KviTalListView::redirect_contextMenuRequested(Q3ListViewItem * pItem,const QPoint &pnt,int uColumn)
+ {
+ emit contextMenuRequested((KviTalListViewItem *)pItem,pnt,uColumn);
+ }
+
+ void KviTalListView::redirect_onItem(Q3ListViewItem * pItem)
+ {
+ emit onItem((KviTalListViewItem *)pItem);
+ }
+
+ void KviTalListView::redirect_expanded(Q3ListViewItem * pItem)
+ {
+ emit expanded((KviTalListViewItem *)pItem);
+ }
+
+ void KviTalListView::redirect_collapsed(Q3ListViewItem * pItem)
+ {
+ emit collapsed((KviTalListViewItem *)pItem);
+ }
+
+
+ struct KviTalCheckListItemPrivate
+ {
+ KviTalCheckListItemPrivate():
+ exclusive(0),
+ currentState(KviTalCheckListItem::Off),
+ tristate(false) {}
+
+ KviTalCheckListItem *exclusive;
+ KviTalCheckListItem::ToggleState currentState;
+ QHash<KviTalCheckListItem *, KviTalCheckListItem::ToggleState> statesDict;
+ bool tristate;
+ };
+
+ KviTalCheckListItem::KviTalCheckListItem(KviTalCheckListItem *parent, const QString &text,
+ Type tt)
+ : KviTalListViewItem(parent, text, QString())
+ {
+ myType = tt;
+ init();
+ if (myType == RadioButton) {
+ if (parent->type() != RadioButtonController)
+ qWarning("KviTalCheckListItem::KviTalCheckListItem(), radio button must be "
+ "child of a controller");
+ else
+ d->exclusive = parent;
+ }
+ }
+
+ KviTalCheckListItem::KviTalCheckListItem(KviTalCheckListItem *parent, KviTalListViewItem *after,
+ const QString &text, Type tt)
+ : KviTalListViewItem(parent, after, text)
+ {
+ myType = tt;
+ init();
+ if (myType == RadioButton) {
+ if (parent->type() != RadioButtonController)
+ qWarning("KviTalCheckListItem::KviTalCheckListItem(), radio button must be "
+ "child of a controller");
+ else
+ d->exclusive = parent;
+ }
+ }
+
+ KviTalCheckListItem::KviTalCheckListItem(KviTalListViewItem *parent, const QString &text,
+ Type tt)
+ : KviTalListViewItem(parent, text, QString())
+ {
+ myType = tt;
+ if (myType == RadioButton) {
+ qWarning("KviTalCheckListItem::KviTalCheckListItem(), radio button must be "
+ "child of a KviTalCheckListItem");
+ }
+ init();
+ }
+
+ KviTalCheckListItem::KviTalCheckListItem(KviTalListViewItem *parent, KviTalListViewItem *after,
+ const QString &text, Type tt)
+ : KviTalListViewItem(parent, after, text)
+ {
+ myType = tt;
+ if (myType == RadioButton) {
+ qWarning("KviTalCheckListItem::KviTalCheckListItem(), radio button must be "
+ "child of a KviTalCheckListItem");
+ }
+ init();
+ }
+
+ KviTalCheckListItem::KviTalCheckListItem(KviTalListView *parent, const QString &text,
+ Type tt)
+ : KviTalListViewItem(parent, text)
+ {
+ myType = tt;
+ if (tt == RadioButton)
+ qWarning("KviTalCheckListItem::KviTalCheckListItem(), radio button must be "
+ "child of a KviTalCheckListItem");
+ init();
+ }
+
+ KviTalCheckListItem::KviTalCheckListItem(KviTalListView *parent, KviTalListViewItem *after,
+ const QString &text, Type tt)
+ : KviTalListViewItem(parent, after, text)
+ {
+ myType = tt;
+ if (tt == RadioButton)
+ qWarning("KviTalCheckListItem::KviTalCheckListItem(), radio button must be "
+ "child of a KviTalCheckListItem");
+ init();
+ }
+
+ int KviTalCheckListItem::rtti() const
+ {
+ return RTTI;
+ }
+
+ KviTalCheckListItem::KviTalCheckListItem(KviTalListView *parent, const QString &text,
+ const QPixmap & p)
+ : KviTalListViewItem(parent, text)
+ {
+ myType = RadioButtonController;
+ setPixmap(0, p);
+ init();
+ }
+
+ KviTalCheckListItem::KviTalCheckListItem(KviTalListViewItem *parent, const QString &text,
+ const QPixmap & p)
+ : KviTalListViewItem(parent, text)
+ {
+ myType = RadioButtonController;
+ setPixmap(0, p);
+ init();
+ }
+
+ void KviTalCheckListItem::init()
+ {
+ d = new KviTalCheckListItemPrivate();
+ on = false; // ### remove on ver 4
+ // CheckBoxControllers by default have tristate set to true
+ if (myType == CheckBoxController)
+ setTristate(true);
+ }
+
+ KviTalCheckListItem::~KviTalCheckListItem()
+ {
+ if (myType == RadioButton
+ && d->exclusive && d->exclusive->d
+ && d->exclusive->d->exclusive == this)
+ d->exclusive->turnOffChild();
+ d->exclusive = 0; // so the children won't try to access us.
+ delete d;
+ d = 0;
+ }
+
+ void KviTalCheckListItem::setTristate(bool b)
+ {
+ if ((myType != CheckBoxController) && (myType != CheckBox)) {
+ qWarning("KviTalCheckListItem::setTristate(), has no effect on RadioButton "
+ "or RadioButtonController.");
+ return;
+ }
+ d->tristate = b;
+ }
+
+ bool KviTalCheckListItem::isTristate() const
+ {
+ return d->tristate;
+ }
+
+ KviTalCheckListItem::ToggleState KviTalCheckListItem::state() const
+ {
+ if (!isTristate() && internalState() == NoChange)
+ return Off;
+ else
+ return d->currentState;
+ }
+
+ KviTalCheckListItem::ToggleState KviTalCheckListItem::internalState() const
+ {
+ return d->currentState;
+ }
+
+ void KviTalCheckListItem::setState(ToggleState s)
+ {
+ if (myType == CheckBoxController && state() == NoChange)
+ updateStoredState(this);
+ setState(s, true, true);
+ }
+
+ void KviTalCheckListItem::setState(ToggleState s, bool update, bool store)
+ {
+
+ if (s == internalState())
+ return;
+
+ if (myType == CheckBox) {
+ setCurrentState(s);
+ stateChange(state());
+ if (update && parent() && parent()->rtti() == 1
+ && ((KviTalCheckListItem*)parent())->type() == CheckBoxController)
+ ((KviTalCheckListItem*)parent())->updateController(update, store);
+ } else if (myType == CheckBoxController) {
+ if (s == NoChange && childCount()) {
+ restoreState(this);
+ } else {
+ KviTalListViewItem *item = firstChild();
+ int childCount = 0;
+ while(item) {
+ if (item->rtti() == 1 &&
+ (((KviTalCheckListItem*)item)->type() == CheckBox ||
+ ((KviTalCheckListItem*)item)->type() == CheckBoxController)) {
+ KviTalCheckListItem *checkItem = (KviTalCheckListItem*)item;
+ checkItem->setState(s, false, false);
+ childCount++;
+ }
+ item = item->nextSibling();
+ }
+ if (update) {
+ if (childCount > 0) {
+ ToggleState oldState = internalState();
+ updateController(false, false);
+ if (oldState != internalState() &&
+ parent() && parent()->rtti() == 1 &&
+ ((KviTalCheckListItem*)parent())->type() == CheckBoxController)
+ ((KviTalCheckListItem*)parent())->updateController(update, store);
+
+ updateController(update, store);
+ } else {
+ // if there are no children we simply set the CheckBoxController and update its parent
+ setCurrentState(s);
+ stateChange(state());
+ if (parent() && parent()->rtti() == 1
+ && ((KviTalCheckListItem*)parent())->type() == CheckBoxController)
+ ((KviTalCheckListItem*)parent())->updateController(update, store);
+ }
+ } else {
+ setCurrentState(s);
+ stateChange(state());
+ }
+
+ }
+ } else if (myType == RadioButton) {
+ if (s == On) {
+ if (d->exclusive && d->exclusive->d->exclusive != this)
+ d->exclusive->turnOffChild();
+ setCurrentState(s);
+ if (d->exclusive)
+ d->exclusive->d->exclusive = this;
+ } else {
+ if (d->exclusive && d->exclusive->d->exclusive == this)
+ d->exclusive->d->exclusive = 0;
+ setCurrentState(Off);
+ }
+ stateChange(state());
+ }
+ repaint();
+ }
+
+ void KviTalCheckListItem::setCurrentState(ToggleState s)
+ {
+ ToggleState old = d->currentState;
+ d->currentState = s;
+ if (d->currentState == On)
+ on = true;
+ else
+ on = false;
+
+ //#ifndef QT_NO_ACCESSIBILITY
+ // if (old != d->currentState && listView())
+ // QAccessible::updateAccessibility(listView()->viewport(), indexOfItem(this), QAccessible::StateChanged);
+ //#else
+ // Q_UNUSED(old);
+ //#endif
+ }
+
+ void KviTalCheckListItem::setStoredState(ToggleState newState, KviTalCheckListItem *key)
+ {
+ if (myType == CheckBox || myType == CheckBoxController)
+ d->statesDict[key] = newState;
+ }
+
+ KviTalCheckListItem::ToggleState KviTalCheckListItem::storedState(KviTalCheckListItem *key) const
+ {
+ QHash<KviTalCheckListItem *, KviTalCheckListItem::ToggleState>::Iterator it = d->statesDict.find(key);
+ if (it != d->statesDict.end())
+ return it.value();
+ else
+ return Off;
+ }
+
+ void KviTalCheckListItem::turnOffChild()
+ {
+ if (myType == RadioButtonController && d->exclusive)
+ d->exclusive->setOn(false);
+ }
+
+ void KviTalCheckListItem::activate()
+ {
+ KviTalListView * lv = listView();
+
+ if (lv && !lv->isEnabled() || !isEnabled())
+ return;
+
+ QPoint pos;
+ int boxsize = lv->style()->pixelMetric(QStyle::PM_CheckListButtonSize, 0, lv);
+ if (activatedPos(pos)) {
+ bool parentControl = false;
+ if (parent() && parent()->rtti() == 1 &&
+ ((KviTalCheckListItem*) parent())->type() == RadioButtonController)
+ parentControl = true;
+
+ int x = parentControl ? 0 : 3;
+ int align = lv->columnAlignment(0);
+ int marg = lv->itemMargin();
+ int y = 0;
+
+ if (align & Qt::AlignVCenter)
+ y = ((height() - boxsize) / 2) + marg;
+ else
+ y = (lv->fontMetrics().height() + 2 + marg - boxsize) / 2;
+
+ QRect r(x, y, boxsize-3, boxsize-3);
+ // columns might have been swapped
+ r.moveBy(lv->header()->sectionPos(0), 0);
+ if (!r.contains(pos))
+ return;
+ }
+ if ((myType == CheckBox) || (myType == CheckBoxController)) {
+ //lv->d->startEdit = FALSE;
+ switch (internalState()) {
+ case On:
+ setState(Off);
+ break;
+ case Off:
+ if (!isTristate() && myType == CheckBox) {
+ setState(On);
+ } else {
+ setState(NoChange);
+ if (myType == CheckBoxController && internalState() != NoChange)
+ setState(On);
+ }
+ break;
+ case NoChange:
+ setState(On);
+ break;
+ }
+ ignoreDoubleClick();
+ } else if (myType == RadioButton) {
+ setOn(true);
+ ignoreDoubleClick();
+ }
+ }
+
+ void KviTalCheckListItem::setOn(bool b )
+ {
+ if (b)
+ setState(On , true, true);
+ else
+ setState(Off , true, true);
+ }
+
+ void KviTalCheckListItem::stateChange(bool)
+ {
+ }
+
+ void KviTalCheckListItem::stateChange(ToggleState s)
+ {
+ stateChange(s == On);
+ }
+
+ void KviTalCheckListItem::restoreState(KviTalCheckListItem *key, int depth)
+ {
+ switch (type()) {
+ case CheckBox:
+ setCurrentState(storedState(key));
+ stateChange(state());
+ repaint();
+ break;
+ case CheckBoxController: {
+ KviTalListViewItem *item = firstChild();
+ int childCount = 0;
+ while (item) {
+ // recursively calling restoreState for children of type CheckBox and CheckBoxController
+ if (item->rtti() == 1 &&
+ (((KviTalCheckListItem*)item)->type() == CheckBox ||
+ ((KviTalCheckListItem*)item)->type() == CheckBoxController)) {
+ ((KviTalCheckListItem*)item)->restoreState(key , depth+1);
+ childCount++;
+ }
+ item = item->nextSibling();
+ }
+ if (childCount > 0) {
+ if (depth == 0)
+ updateController(true);
+ else
+ updateController(false);
+ } else {
+ // if there are no children we retrieve the CheckBoxController state directly.
+ setState(storedState(key), true, false);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ void KviTalCheckListItem::updateController(bool update , bool store)
+ {
+ if (myType != CheckBoxController)
+ return;
+
+ KviTalCheckListItem *controller = 0;
+ // checks if this CheckBoxController has another CheckBoxController as parent
+ if (parent() && parent()->rtti() == 1
+ && ((KviTalCheckListItem*)parent())->type() == CheckBoxController)
+ controller = (KviTalCheckListItem*)parent();
+
+ ToggleState theState = Off;
+ bool first = true;
+ KviTalListViewItem *item = firstChild();
+ while(item && theState != NoChange) {
+ if (item->rtti() == 1 &&
+ (((KviTalCheckListItem*)item)->type() == CheckBox ||
+ ((KviTalCheckListItem*)item)->type() == CheckBoxController)) {
+ KviTalCheckListItem *checkItem = (KviTalCheckListItem*)item;
+ if (first) {
+ theState = checkItem->internalState();
+ first = false;
+ } else {
+ if (checkItem->internalState() == NoChange ||
+ theState != checkItem->internalState())
+ theState = NoChange;
+ else
+ theState = checkItem->internalState();
+ }
+ }
+ item = item->nextSibling();
+ }
+ if (internalState() != theState) {
+ setCurrentState(theState);
+ if (store && (internalState() == On || internalState() == Off))
+ updateStoredState(this);
+ stateChange(state());
+ if (update && controller) {
+ controller->updateController(update, store);
+ }
+ repaint();
+ }
+ }
+
+ void KviTalCheckListItem::updateStoredState(KviTalCheckListItem *key)
+ {
+ if (myType != CheckBoxController)
+ return;
+
+ KviTalListViewItem *item = firstChild();
+ while(item) {
+ if (item->rtti() == 1) {
+ KviTalCheckListItem *checkItem = (KviTalCheckListItem*)item;
+ if (checkItem->type() == CheckBox)
+ checkItem->setStoredState(checkItem->internalState(), key);
+ else if (checkItem->type() == CheckBoxController)
+ checkItem->updateStoredState(key);
+ }
+ item = item->nextSibling();
+ }
+ // this state is only needed if the CheckBoxController has no CheckBox / CheckBoxController children.
+ setStoredState(internalState() , key);
+ }
+
+ void KviTalCheckListItem::setup()
+ {
+ KviTalListViewItem::setup();
+ int h = height();
+ KviTalListView *lv = listView();
+ if (lv)
+ h = qMax(lv->style()->pixelMetric(QStyle::PM_CheckListButtonSize, 0, lv),
+ h);
+ h = qMax(h, QApplication::globalStrut().height());
+ setHeight(h);
+ }
+
+ int KviTalCheckListItem::width(const QFontMetrics& fm, const KviTalListView* lv, int column) const
+ {
+ int r = KviTalListViewItem::width(fm, lv, column);
+ if (column == 0) {
+ r += lv->itemMargin();
+ if (myType == RadioButtonController && pixmap(0)) {
+ // r += 0;
+ } else {
+ r += lv->style()->pixelMetric(QStyle::PM_CheckListButtonSize, 0, lv) + 4;
+ }
+ }
+ return qMax(r, QApplication::globalStrut().width());
+ }
+
+ void KviTalCheckListItem::paintCell(QPainter * p, const QColorGroup & cg,
+ int column, int width, int align)
+ {
+ if (!p)
+ return;
+
+ KviTalListView *lv = listView();
+ if (!lv)
+ return;
+
+ const QPalette::ColorRole crole = lv->foregroundRole();
+ if (cg.brush(crole) != lv->palette().brush(crole))
+ p->fillRect(0, 0, width, height(), cg.brush(crole));
+ else
+ lv->paintEmptyArea(p, QRect(0, 0, width, height()));
+
+ if (column != 0) {
+ // The rest is text, or for subclasses to change.
+ KviTalListViewItem::paintCell(p, cg, column, width, align);
+ return;
+ }
+
+ bool parentControl = false;
+ if (parent() && parent()->rtti() == 1 &&
+ ((KviTalCheckListItem*) parent())->type() == RadioButtonController)
+ parentControl = true;
+
+ QFontMetrics fm(lv->fontMetrics());
+ int boxsize = lv->style()->pixelMetric(myType == RadioButtonController ? QStyle::PM_CheckListControllerSize :
+ QStyle::PM_CheckListButtonSize, 0, lv);
+ int marg = lv->itemMargin();
+ int r = marg;
+
+ // Draw controller / checkbox / radiobutton ---------------------
+ QStyle::State styleflags = QStyle::State_None;
+ if (internalState() == On) {
+ styleflags |= QStyle::State_On;
+ } else if (internalState() == NoChange) {
+ if (myType == CheckBoxController && !isTristate())
+ styleflags |= QStyle::State_Off;
+ else
+ styleflags |= QStyle::State_NoChange;
+ } else {
+ styleflags |= QStyle::State_Off;
+ }
+ if (isSelected())
+ styleflags |= QStyle::State_Selected;
+ if (isEnabled() && lv->isEnabled())
+ styleflags |= QStyle::State_Enabled;
+ if (lv->window()->isActiveWindow())
+ styleflags |= QStyle::State_Active;
+
+ if (myType == RadioButtonController) {
+ int x = 0;
+ if(!parentControl)
+ x += 3;
+ if (!pixmap(0)) {
+ QStyleOptionQ3ListView opt = getStyleOption(lv, this);
+ opt.rect.setRect(x, 0, boxsize, fm.height() + 2 + marg);
+ opt.palette = cg;
+ opt.state = styleflags;
+ lv->style()->drawPrimitive(QStyle::PE_Q3CheckListController, &opt, p, lv);
+ r += boxsize + 4;
+ }
+ } else {
+ Q_ASSERT(lv); //###
+ int x = 0;
+ int y = 0;
+ if (!parentControl)
+ x += 3;
+ if (align & Qt::AlignVCenter)
+ y = ((height() - boxsize) / 2) + marg;
+ else
+ y = (fm.height() + 2 + marg - boxsize) / 2;
+
+ QStyleOptionQ3ListView opt = getStyleOption(lv, this);
+ opt.rect.setRect(x, y, boxsize, fm.height() + 2 + marg);
+ opt.palette = cg;
+ opt.state = styleflags;
+ lv->style()->drawPrimitive((myType == CheckBox || myType == CheckBoxController)
+ ? QStyle::PE_Q3CheckListIndicator
+ : QStyle::PE_Q3CheckListExclusiveIndicator, &opt, p, lv);
+ r += boxsize + 4;
+ }
+
+ // Draw text ----------------------------------------------------
+ p->translate(r, 0);
+ p->setPen(QPen(cg.text()));
+ KviTalListViewItem::paintCell(p, cg, column, width - r, align);
+ }
+
+ void KviTalCheckListItem::paintFocus(QPainter *p, const QColorGroup & cg,
+ const QRect & r)
+ {
+ bool intersect = true;
+ KviTalListView *lv = listView();
+ if (lv && lv->header()->mapToActual(0) != 0) {
+ int xdepth = lv->treeStepSize() * (depth() + (lv->rootIsDecorated() ? 1 : 0)) + lv->itemMargin();
+ int p = lv->header()->cellPos(lv->header()->mapToActual(0));
+ xdepth += p;
+ intersect = r.intersects(QRect(p, r.y(), xdepth - p + 1, r.height()));
+ }
+ bool parentControl = false;
+ if (parent() && parent()->rtti() == 1 &&
+ ((KviTalCheckListItem*) parent())->type() == RadioButtonController)
+ parentControl = true;
+ if (myType != RadioButtonController && intersect &&
+ (lv->rootIsDecorated() || myType == RadioButton ||
+ (myType == CheckBox && parentControl))) {
+ QRect rect;
+ int boxsize = lv->style()->pixelMetric(QStyle::PM_CheckListButtonSize, 0, lv);
+ if (lv->columnAlignment(0) == Qt::AlignCenter) {
+ QFontMetrics fm(lv->font());
+ int bx = (lv->columnWidth(0) - (boxsize + fm.width(text())))/2 + boxsize;
+ if (bx < 0) bx = 0;
+ rect.setRect(r.x() + bx + 5, r.y(), r.width() - bx - 5,
+ r.height());
+ } else
+ rect.setRect(r.x() + boxsize + 5, r.y(), r.width() - boxsize - 5,
+ r.height());
+ KviTalListViewItem::paintFocus(p, cg, rect);
+ } else {
+ KviTalListViewItem::paintFocus(p, cg, r);
+ }
+ }
+
+
+ #include "kvi_tal_listview_qt4.moc"
+#else
+ #include <qpainter.h>
+ #include <qstyle.h>
+ #include <qheader.h>
+ #include <qapplication.h>
+
+ KviTalListView::KviTalListView(QWidget * pParent)
+ : QListView(pParent)
+ {
+ connect(this,SIGNAL(selectionChanged(QListViewItem *)),this,SLOT(redirect_selectionChanged(QListViewItem *)));
+ connect(this,SIGNAL(currentChanged(QListViewItem *)),this,SLOT(redirect_currentChanged(QListViewItem *)));
+ connect(this,SIGNAL(clicked(QListViewItem *)),this,SLOT(redirect_clicked(QListViewItem *)));
+ connect(this,SIGNAL(clicked(QListViewItem *,const QPoint &,int)),this,SLOT(redirect_clicked(QListViewItem *,const QPoint &,int)));
+ connect(this,SIGNAL(pressed(QListViewItem *)),this,SLOT(redirect_pressed(QListViewItem *)));
+ connect(this,SIGNAL(pressed(QListViewItem *,const QPoint &,int)),this,SLOT(redirect_pressed(QListViewItem *,const QPoint &,int)));
+ connect(this,SIGNAL(doubleClicked(QListViewItem *)),this,SLOT(redirect_doubleClicked(QListViewItem *)));
+ connect(this,SIGNAL(doubleClicked(QListViewItem *,const QPoint &,int)),this,SLOT(redirect_doubleClicked(QListViewItem *,const QPoint &,int)));
+ connect(this,SIGNAL(returnPressed(QListViewItem *)),this,SLOT(redirect_returnPressed(QListViewItem *)));
+ connect(this,SIGNAL(spacePressed(QListViewItem *)),this,SLOT(redirect_spacePressed(QListViewItem *)));
+ connect(this,SIGNAL(rightButtonClicked(QListViewItem *,const QPoint &,int)),this,SLOT(redirect_rightButtonClicked(QListViewItem *,const QPoint &,int)));
+ connect(this,SIGNAL(rightButtonPressed(QListViewItem *,const QPoint &,int)),this,SLOT(redirect_rightButtonPressed(QListViewItem *,const QPoint &,int)));
+ connect(this,SIGNAL(mouseButtonClicked(int,QListViewItem *,const QPoint &,int)),this,SLOT(redirect_mouseButtonClicked(int,QListViewItem *,const QPoint &,int)));
+ connect(this,SIGNAL(mouseButtonPressed(int,QListViewItem *,const QPoint &,int)),this,SLOT(redirect_mouseButtonPressed(int,QListViewItem *,const QPoint &,int)));
+ connect(this,SIGNAL(contextMenuRequested(QListViewItem *,const QPoint &,int)),this,SLOT(redirect_contextMenuRequested(QListViewItem *,const QPoint &,int)));
+ connect(this,SIGNAL(onItem(QListViewItem *)),this,SLOT(redirect_onItem(QListViewItem *)));
+ connect(this,SIGNAL(expanded(QListViewItem *)),this,SLOT(redirect_expanded(QListViewItem *)));
+ connect(this,SIGNAL(collapsed(QListViewItem *)),this,SLOT(redirect_collapsed(QListViewItem *)));
+ }
+
+ void KviTalListView::redirect_selectionChanged(QListViewItem * pItem)
+ {
+ emit selectionChanged((KviTalListViewItem *)pItem);
+ }
+
+ void KviTalListView::redirect_currentChanged(QListViewItem * pItem)
+ {
+ emit currentChanged((KviTalListViewItem *)pItem);
+ }
+
+ void KviTalListView::redirect_clicked(QListViewItem * pItem)
+ {
+ emit clicked((KviTalListViewItem *)pItem);
+ }
+
+ void KviTalListView::redirect_clicked(QListViewItem * pItem,const QPoint &pnt,int uColumn)
+ {
+ emit clicked((KviTalListViewItem *)pItem,pnt,uColumn);
+ }
+
+ void KviTalListView::redirect_pressed(QListViewItem * pItem)
+ {
+ emit pressed((KviTalListViewItem *)pItem);
+ }
+
+ void KviTalListView::redirect_pressed(QListViewItem * pItem,const QPoint &pnt,int uColumn)
+ {
+ emit pressed((KviTalListViewItem *)pItem,pnt,uColumn);
+ }
+
+ void KviTalListView::redirect_doubleClicked(QListViewItem * pItem)
+ {
+ emit doubleClicked((KviTalListViewItem *)pItem);
+ }
+
+ void KviTalListView::redirect_doubleClicked(QListViewItem * pItem,const QPoint &pnt,int uColumn)
+ {
+ emit doubleClicked((KviTalListViewItem *)pItem,pnt,uColumn);
+ }
+
+ void KviTalListView::redirect_returnPressed(QListViewItem * pItem)
+ {
+ emit returnPressed((KviTalListViewItem *)pItem);
+ }
+
+ void KviTalListView::redirect_spacePressed(QListViewItem * pItem)
+ {
+ emit spacePressed((KviTalListViewItem *)pItem);
+ }
+
+ void KviTalListView::redirect_rightButtonClicked(QListViewItem * pItem,const QPoint &pnt,int uColumn)
+ {
+ emit rightButtonClicked((KviTalListViewItem *)pItem,pnt,uColumn);
+ }
+
+ void KviTalListView::redirect_rightButtonPressed(QListViewItem * pItem,const QPoint &pnt,int uColumn)
+ {
+ emit rightButtonPressed((KviTalListViewItem *)pItem,pnt,uColumn);
+ }
+
+ void KviTalListView::redirect_mouseButtonClicked(int iButton,QListViewItem * pItem,const QPoint &pnt,int uColumn)
+ {
+ emit mouseButtonClicked(iButton,(KviTalListViewItem *)pItem,pnt,uColumn);
+ }
+
+ void KviTalListView::redirect_mouseButtonPressed(int iButton,QListViewItem * pItem,const QPoint &pnt,int uColumn)
+ {
+ emit mouseButtonPressed(iButton,(KviTalListViewItem *)pItem,pnt,uColumn);
+ }
+
+ void KviTalListView::redirect_contextMenuRequested(QListViewItem * pItem,const QPoint &pnt,int uColumn)
+ {
+ emit contextMenuRequested((KviTalListViewItem *)pItem,pnt,uColumn);
+ }
+
+ void KviTalListView::redirect_onItem(QListViewItem * pItem)
+ {
+ emit onItem((KviTalListViewItem *)pItem);
+ }
+
+ void KviTalListView::redirect_expanded(QListViewItem * pItem)
+ {
+ emit expanded((KviTalListViewItem *)pItem);
+ }
+
+ void KviTalListView::redirect_collapsed(QListViewItem * pItem)
+ {
+ emit collapsed((KviTalListViewItem *)pItem);
+ }
+
+ struct KviTalCheckListItemPrivate
+ {
+ KviTalCheckListItemPrivate():
+ exclusive( 0 ),
+ currentState( KviTalCheckListItem::Off ),
+ statesDict( 0 ),
+ tristate( FALSE ) {}
+
+ KviTalCheckListItem *exclusive;
+ KviTalCheckListItem::ToggleState currentState;
+ KviPointerHashTable<void *,KviTalCheckListItem::ToggleState> *statesDict;
+ bool tristate;
+ };
+
+ // ### obscenity is warranted.
+
+ KviTalCheckListItem::KviTalCheckListItem( KviTalCheckListItem *parent, const QString &text,
+ Type tt )
+ : KviTalListViewItem( parent, text, QString::null )
+ {
+ myType = tt;
+ init();
+ if ( myType == RadioButton ) {
+ if ( parent->type() != RadioButtonController )
+ qWarning( "KviTalCheckListItem::KviTalCheckListItem(), radio button must be "
+ "child of a controller" );
+ else
+ d->exclusive = parent;
+ }
+ }
+
+ KviTalCheckListItem::KviTalCheckListItem( KviTalCheckListItem *parent, KviTalListViewItem *after,
+ const QString &text, Type tt )
+ : KviTalListViewItem( parent, after, text )
+ {
+ myType = tt;
+ init();
+ if ( myType == RadioButton ) {
+ if ( parent->type() != RadioButtonController )
+ qWarning( "KviTalCheckListItem::KviTalCheckListItem(), radio button must be "
+ "child of a controller" );
+ else
+ d->exclusive = parent;
+ }
+ }
+
+ KviTalCheckListItem::KviTalCheckListItem( KviTalListViewItem *parent, const QString &text,
+ Type tt )
+ : KviTalListViewItem( parent, text, QString::null )
+ {
+ myType = tt;
+ if ( myType == RadioButton ) {
+ qWarning( "KviTalCheckListItem::KviTalCheckListItem(), radio button must be "
+ "child of a KviTalCheckListItem" );
+ }
+ init();
+ }
+
+ KviTalCheckListItem::KviTalCheckListItem( KviTalListViewItem *parent, KviTalListViewItem *after,
+ const QString &text, Type tt )
+ : KviTalListViewItem( parent, after, text )
+ {
+ myType = tt;
+ if ( myType == RadioButton ) {
+ qWarning( "KviTalCheckListItem::KviTalCheckListItem(), radio button must be "
+ "child of a KviTalCheckListItem" );
+ }
+ init();
+ }
+
+ KviTalCheckListItem::KviTalCheckListItem( KviTalListView *parent, const QString &text,
+ Type tt )
+ : KviTalListViewItem( parent, text )
+ {
+ myType = tt;
+ if ( tt == RadioButton )
+ qWarning( "KviTalCheckListItem::KviTalCheckListItem(), radio button must be "
+ "child of a KviTalCheckListItem" );
+ init();
+ }
+
+ KviTalCheckListItem::KviTalCheckListItem( KviTalListView *parent, KviTalListViewItem *after,
+ const QString &text, Type tt )
+ : KviTalListViewItem( parent, after, text )
+ {
+ myType = tt;
+ if ( tt == RadioButton )
+ qWarning( "KviTalCheckListItem::KviTalCheckListItem(), radio button must be "
+ "child of a KviTalCheckListItem" );
+ init();
+ }
+
+
+ int KviTalCheckListItem::RTTI = 1;
+
+ int KviTalCheckListItem::rtti() const
+ {
+ return RTTI;
+ }
+
+ KviTalCheckListItem::KviTalCheckListItem( KviTalListView *parent, const QString &text,
+ const QPixmap & p )
+ : KviTalListViewItem( parent, text )
+ {
+ myType = RadioButtonController;
+ setPixmap( 0, p );
+ init();
+ }
+
+ KviTalCheckListItem::KviTalCheckListItem( KviTalListViewItem *parent, const QString &text,
+ const QPixmap & p )
+ : KviTalListViewItem( parent, text )
+ {
+ myType = RadioButtonController;
+ setPixmap( 0, p );
+ init();
+ }
+
+ void KviTalCheckListItem::init()
+ {
+ d = new KviTalCheckListItemPrivate();
+ on = FALSE; // ### remove on ver 4
+ if ( myType == CheckBoxController || myType == CheckBox ) {
+ d->statesDict = new KviPointerHashTable<void *,ToggleState>(101);
+ d->statesDict->setAutoDelete( TRUE );
+ }
+ // CheckBoxControllers by default have tristate set to TRUE
+ if ( myType == CheckBoxController )
+ setTristate( TRUE );
+ }
+
+ KviTalCheckListItem::~KviTalCheckListItem()
+ {
+ if ( myType == RadioButton
+ && d->exclusive && d->exclusive->d
+ && d->exclusive->d->exclusive == this )
+ d->exclusive->turnOffChild();
+ d->exclusive = 0; // so the children won't try to access us.
+ if ( d->statesDict )
+ delete d->statesDict;
+ delete d;
+ d = 0;
+ }
+
+ void KviTalCheckListItem::setTristate( bool b )
+ {
+ if ( ( myType != CheckBoxController ) && ( myType != CheckBox ) ) {
+ qWarning( "KviTalCheckListItem::setTristate(), has no effect on RadioButton "
+ "or RadioButtonController." );
+ return;
+ }
+ d->tristate = b;
+ }
+
+ bool KviTalCheckListItem::isTristate() const
+ {
+ return d->tristate;
+ }
+
+ KviTalCheckListItem::ToggleState KviTalCheckListItem::state() const
+ {
+ if ( !isTristate() && internalState() == NoChange )
+ return Off;
+ else
+ return d->currentState;
+ }
+
+ KviTalCheckListItem::ToggleState KviTalCheckListItem::internalState() const
+ {
+ return d->currentState;
+ }
+
+ void KviTalCheckListItem::setState( ToggleState s )
+ {
+ if ( myType == CheckBoxController && state() == NoChange )
+ updateStoredState( (void*) this );
+ setState( s, TRUE, TRUE );
+ }
+
+ void KviTalCheckListItem::setState( ToggleState s, bool update, bool store)
+ {
+
+ if ( s == internalState() )
+ return;
+
+ if ( myType == CheckBox ) {
+ setCurrentState( s );
+ stateChange( state() );
+ if ( update && parent() && parent()->rtti() == 1
+ && ((KviTalCheckListItem*)parent())->type() == CheckBoxController )
+ ((KviTalCheckListItem*)parent())->updateController( update, store );
+ } else if ( myType == CheckBoxController ) {
+ if ( s == NoChange && childCount()) {
+ restoreState( (void*) this );
+ } else {
+ KviTalListViewItem *item = firstChild();
+ int childCount = 0;
+ while( item ) {
+ if ( item->rtti() == 1 &&
+ ( ((KviTalCheckListItem*)item)->type() == CheckBox ||
+ ((KviTalCheckListItem*)item)->type() == CheckBoxController ) ) {
+ KviTalCheckListItem *checkItem = (KviTalCheckListItem*)item;
+ checkItem->setState( s, FALSE, FALSE );
+ childCount++;
+ }
+ item = item->nextSibling();
+ }
+ if ( update ) {
+ if ( childCount > 0 ) {
+ ToggleState oldState = internalState();
+ updateController( FALSE, FALSE );
+ if ( oldState != internalState() &&
+ parent() && parent()->rtti() == 1 &&
+ ((KviTalCheckListItem*)parent())->type() == CheckBoxController )
+ ((KviTalCheckListItem*)parent())->updateController( update, store );
+
+ updateController( update, store );
+ } else {
+ // if there are no children we simply set the CheckBoxController and update its parent
+ setCurrentState( s );
+ stateChange( state() );
+ if ( parent() && parent()->rtti() == 1
+ && ((KviTalCheckListItem*)parent())->type() == CheckBoxController )
+ ((KviTalCheckListItem*)parent())->updateController( update, store );
+ }
+ } else {
+ setCurrentState( s );
+ stateChange( state() );
+ }
+
+ }
+ } else if ( myType == RadioButton ) {
+ if ( s == On ) {
+ if ( d->exclusive && d->exclusive->d->exclusive != this )
+ d->exclusive->turnOffChild();
+ setCurrentState( s );
+ if ( d->exclusive )
+ d->exclusive->d->exclusive = this;
+ } else {
+ if ( d->exclusive && d->exclusive->d->exclusive == this )
+ d->exclusive->d->exclusive = 0;
+ setCurrentState( Off );
+ }
+ stateChange( state() );
+ }
+ repaint();
+ }
+
+ void KviTalCheckListItem::setCurrentState( ToggleState s )
+ {
+ ToggleState old = d->currentState;
+ d->currentState = s;
+ if (d->currentState == On)
+ on = TRUE;
+ else
+ on = FALSE;
+
+ #if defined(QT_ACCESSIBILITY_SUPPORT)
+ if ( old != d->currentState && listView() )
+ QAccessible::updateAccessibility( listView()->viewport(), indexOfItem( this ), QAccessible::StateChanged );
+ #else
+ Q_UNUSED( old );
+ #endif
+ }
+
+ void KviTalCheckListItem::setStoredState( ToggleState newState, void *key )
+ {
+ if ( myType == CheckBox || myType == CheckBoxController )
+ d->statesDict->replace( key, new ToggleState(newState) );
+ }
+
+ KviTalCheckListItem::ToggleState KviTalCheckListItem::storedState( void *key ) const
+ {
+ if ( !d->statesDict )
+ return Off;
+
+ ToggleState *foundState = d->statesDict->find( key );
+ if ( foundState )
+ return ToggleState( *foundState );
+ else
+ return Off;
+ }
+
+ void KviTalCheckListItem::turnOffChild()
+ {
+ if ( myType == RadioButtonController && d->exclusive )
+ d->exclusive->setOn( FALSE );
+ }
+
+ void KviTalCheckListItem::activate()
+ {
+ KviTalListView * lv = listView();
+
+ if ( lv && !lv->isEnabled() || !isEnabled() )
+ return;
+
+ QPoint pos;
+ int boxsize = lv->style().pixelMetric(QStyle::PM_CheckListButtonSize, lv);
+ if ( activatedPos( pos ) ) {
+ bool parentControl = FALSE;
+ if ( parent() && parent()->rtti() == 1 &&
+ ((KviTalCheckListItem*) parent())->type() == RadioButtonController )
+ parentControl = TRUE;
+
+ int x = parentControl ? 0 : 3;
+ int align = lv->columnAlignment( 0 );
+ int marg = lv->itemMargin();
+ int y = 0;
+
+ if ( align & AlignVCenter )
+ y = ( ( height() - boxsize ) / 2 ) + marg;
+ else
+ y = (lv->fontMetrics().height() + 2 + marg - boxsize) / 2;
+
+ QRect r( x, y, boxsize-3, boxsize-3 );
+ // columns might have been swapped
+ r.moveBy( lv->header()->sectionPos( 0 ), 0 );
+ if ( !r.contains( pos ) )
+ return;
+ }
+ if ( ( myType == CheckBox ) || ( myType == CheckBoxController) ) {
+ switch ( internalState() ) {
+ case On:
+ setState( Off );
+ break;
+ case Off:
+ if ( !isTristate() && myType == CheckBox ) {
+ setState( On );
+ } else {
+ setState( NoChange );
+ if ( myType == CheckBoxController && internalState() != NoChange )
+ setState( On );
+ }
+ break;
+ case NoChange:
+ setState( On );
+ break;
+ }
+ ignoreDoubleClick();
+ } else if ( myType == RadioButton ) {
+ setOn( TRUE );
+ ignoreDoubleClick();
+ }
+ }
+
+ void KviTalCheckListItem::setOn( bool b )
+ {
+ if ( b )
+ setState( On , TRUE, TRUE );
+ else
+ setState( Off , TRUE, TRUE );
+ }
+
+ void KviTalCheckListItem::stateChange( bool )
+ {
+ }
+
+ void KviTalCheckListItem::stateChange( ToggleState s )
+ {
+ stateChange( s == On );
+ }
+
+ void KviTalCheckListItem::restoreState( void *key, int depth )
+ {
+ switch ( type() ) {
+ case CheckBox:
+ setCurrentState( storedState( key ) );
+ stateChange( state() );
+ repaint();
+ break;
+ case CheckBoxController: {
+ KviTalListViewItem *item = firstChild();
+ int childCount = 0;
+ while ( item ) {
+ // recursively calling restoreState for children of type CheckBox and CheckBoxController
+ if ( item->rtti() == 1 &&
+ ( ((KviTalCheckListItem*)item)->type() == CheckBox ||
+ ((KviTalCheckListItem*)item)->type() == CheckBoxController ) ) {
+ ((KviTalCheckListItem*)item)->restoreState( key , depth+1 );
+ childCount++;
+ }
+ item = item->nextSibling();
+ }
+ if ( childCount > 0 ) {
+ if ( depth == 0 )
+ updateController( TRUE );
+ else
+ updateController( FALSE );
+ } else {
+ // if there are no children we retrieve the CheckBoxController state directly.
+ setState( storedState( key ), TRUE, FALSE );
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ void KviTalCheckListItem::updateController( bool update , bool store )
+ {
+ if ( myType != CheckBoxController )
+ return;
+
+ KviTalCheckListItem *controller = 0;
+ // checks if this CheckBoxController has another CheckBoxController as parent
+ if ( parent() && parent()->rtti() == 1
+ && ((KviTalCheckListItem*)parent())->type() == CheckBoxController )
+ controller = (KviTalCheckListItem*)parent();
+
+ ToggleState theState = Off;
+ bool first = TRUE;
+ KviTalListViewItem *item = firstChild();
+ while( item && theState != NoChange ) {
+ if ( item->rtti() == 1 &&
+ ( ((KviTalCheckListItem*)item)->type() == CheckBox ||
+ ((KviTalCheckListItem*)item)->type() == CheckBoxController ) ) {
+ KviTalCheckListItem *checkItem = (KviTalCheckListItem*)item;
+ if ( first ) {
+ theState = checkItem->internalState();
+ first = FALSE;
+ } else {
+ if ( checkItem->internalState() == NoChange ||
+ theState != checkItem->internalState() )
+ theState = NoChange;
+ else
+ theState = checkItem->internalState();
+ }
+ }
+ item = item->nextSibling();
+ }
+ if ( internalState() != theState ) {
+ setCurrentState( theState );
+ if ( store && ( internalState() == On || internalState() == Off ) )
+ updateStoredState( (void*) this );
+ stateChange( state() );
+ if ( update && controller ) {
+ controller->updateController( update, store );
+ }
+ repaint();
+ }
+ }
+
+ void KviTalCheckListItem::updateStoredState( void *key )
+ {
+ if ( myType != CheckBoxController )
+ return;
+
+ KviTalListViewItem *item = firstChild();
+ while( item ) {
+ if ( item->rtti() == 1 ) {
+ KviTalCheckListItem *checkItem = (KviTalCheckListItem*)item;
+ if ( checkItem->type() == CheckBox )
+ checkItem->setStoredState( checkItem->internalState(), key );
+ else if (checkItem->type() == CheckBoxController )
+ checkItem->updateStoredState( key );
+ }
+ item = item->nextSibling();
+ }
+ // this state is only needed if the CheckBoxController has no CheckBox / CheckBoxController children.
+ setStoredState( internalState() , key );
+ }
+
+ void KviTalCheckListItem::setup()
+ {
+ KviTalListViewItem::setup();
+ int h = height();
+ KviTalListView *lv = listView();
+ if ( lv )
+ h = QMAX( lv->style().pixelMetric(QStyle::PM_CheckListButtonSize, lv),
+ h );
+ h = QMAX( h, QApplication::globalStrut().height() );
+ setHeight( h );
+ }
+
+ int KviTalCheckListItem::width( const QFontMetrics& fm, const KviTalListView* lv, int column) const
+ {
+ int r = KviTalListViewItem::width( fm, lv, column );
+ if ( column == 0 ) {
+ r += lv->itemMargin();
+ if ( myType == RadioButtonController && pixmap( 0 ) ) {
+ // r += 0;
+ } else {
+ r += lv->style().pixelMetric(QStyle::PM_CheckListButtonSize, lv) + 4;
+ }
+ }
+ return QMAX( r, QApplication::globalStrut().width() );
+ }
+
+ void KviTalCheckListItem::paintCell( QPainter * p, const QColorGroup & cg,
+ int column, int width, int align )
+ {
+ if ( !p )
+ return;
+
+ KviTalListView *lv = listView();
+ if ( !lv )
+ return;
+
+ const BackgroundMode bgmode = lv->viewport()->backgroundMode();
+ const QColorGroup::ColorRole crole = QPalette::backgroundRoleFromMode( bgmode );
+ if ( cg.brush( crole ) != lv->colorGroup().brush( crole ) )
+ p->fillRect( 0, 0, width, height(), cg.brush( crole ) );
+ else
+ lv->paintEmptyArea( p, QRect( 0, 0, width, height() ) );
+
+ if ( column != 0 ) {
+ // The rest is text, or for subclasses to change.
+ KviTalListViewItem::paintCell( p, cg, column, width, align );
+ return;
+ }
+
+ bool parentControl = FALSE;
+ if ( parent() && parent()->rtti() == 1 &&
+ ((KviTalCheckListItem*) parent())->type() == RadioButtonController )
+ parentControl = TRUE;
+
+ QFontMetrics fm( lv->fontMetrics() );
+ int boxsize = lv->style().pixelMetric( myType == RadioButtonController ? QStyle::PM_CheckListControllerSize :
+ QStyle::PM_CheckListButtonSize, lv);
+ int marg = lv->itemMargin();
+ int r = marg;
+
+ // Draw controller / checkbox / radiobutton ---------------------
+ int styleflags = QStyle::Style_Default;
+ if ( internalState() == On ) {
+ styleflags |= QStyle::Style_On;
+ } else if ( internalState() == NoChange ) {
+ if ( myType == CheckBoxController && !isTristate() )
+ styleflags |= QStyle::Style_Off;
+ else
+ styleflags |= QStyle::Style_NoChange;
+ } else {
+ styleflags |= QStyle::Style_Off;
+ }
+ if ( isSelected() )
+ styleflags |= QStyle::Style_Selected;
+ if ( isEnabled() && lv->isEnabled() )
+ styleflags |= QStyle::Style_Enabled;
+
+ if ( myType == RadioButtonController ) {
+ int x = 0;
+ if(!parentControl)
+ x += 3;
+ if ( !pixmap( 0 ) ) {
+ lv->style().drawPrimitive(QStyle::PE_CheckListController, p,
+ QRect(x, 0, boxsize,
+ fm.height() + 2 + marg),
+ cg, styleflags, QStyleOption(this));
+ r += boxsize + 4;
+ }
+ } else {
+ Q_ASSERT( lv ); //###
+ int x = 0;
+ int y = 0;
+ if ( !parentControl )
+ x += 3;
+ if ( align & AlignVCenter )
+ y = ( ( height() - boxsize ) / 2 ) + marg;
+ else
+ y = (fm.height() + 2 + marg - boxsize) / 2;
+
+ if ( ( myType == CheckBox ) || ( myType == CheckBoxController ) ) {
+ lv->style().drawPrimitive(QStyle::PE_CheckListIndicator, p,
+ QRect(x, y, boxsize,
+ fm.height() + 2 + marg),
+ cg, styleflags, QStyleOption(this));
+ } else { //radio button look
+ lv->style().drawPrimitive(QStyle::PE_CheckListExclusiveIndicator,
+ p, QRect(x, y, boxsize,
+ fm.height() + 2 + marg),
+ cg, styleflags, QStyleOption(this));
+ }
+ r += boxsize + 4;
+ }
+
+ // Draw text ----------------------------------------------------
+ p->translate( r, 0 );
+ p->setPen( QPen( cg.text() ) );
+ KviTalListViewItem::paintCell( p, cg, column, width - r, align );
+ }
+
+ void KviTalCheckListItem::paintFocus( QPainter *p, const QColorGroup & cg,const QRect & r )
+ {
+ bool intersect = TRUE;
+ KviTalListView *lv = listView();
+ if ( lv && lv->header()->mapToActual( 0 ) != 0 ) {
+ int xdepth = lv->treeStepSize() * ( depth() + ( lv->rootIsDecorated() ? 1 : 0) ) + lv->itemMargin();
+ int p = lv->header()->cellPos( lv->header()->mapToActual( 0 ) );
+ xdepth += p;
+ intersect = r.intersects( QRect( p, r.y(), xdepth - p + 1, r.height() ) );
+ }
+ bool parentControl = FALSE;
+ if ( parent() && parent()->rtti() == 1 &&
+ ((KviTalCheckListItem*) parent())->type() == RadioButtonController )
+ parentControl = TRUE;
+ if ( myType != RadioButtonController && intersect &&
+ (lv->rootIsDecorated() || myType == RadioButton ||
+ (myType == CheckBox && parentControl) ) ) {
+ QRect rect;
+ int boxsize = lv->style().pixelMetric(QStyle::PM_CheckListButtonSize, lv);
+ if ( lv->columnAlignment(0) == AlignCenter ) {
+ QFontMetrics fm( lv->font() );
+ int bx = (lv->columnWidth(0) - (boxsize + fm.width(text())))/2 + boxsize;
+ if ( bx < 0 ) bx = 0;
+ rect.setRect( r.x() + bx + 5, r.y(), r.width() - bx - 5,
+ r.height() );
+ } else
+ rect.setRect( r.x() + boxsize + 5, r.y(), r.width() - boxsize - 5,
+ r.height() );
+ KviTalListViewItem::paintFocus(p, cg, rect);
+ } else {
+ KviTalListViewItem::paintFocus(p, cg, r);
+ }
+ }
+
+ #include "kvi_tal_listview_qt3.moc"
+#endif
+
+
+
diff --git a/src/kvilib/tal/kvi_tal_listview.h b/src/kvilib/tal/kvi_tal_listview.h
new file mode 100644
index 00000000..9b95e2f8
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_listview.h
@@ -0,0 +1,51 @@
+#ifndef _KVI_TAL_LISTVIEW_H_
+#define _KVI_TAL_LISTVIEW_H_
+
+//=============================================================================
+//
+// File : kvi_tal_listview.h
+// Creation date : Mon Jan 22 2007 11:25:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+
+//
+// This is the only reasonable CROSS-QT3-QT4-COMPATIBLE implementation
+// of QListView I've been able to find.
+// Note that using macros for the items will NOT work since moc
+// doesn't expand them. Note also that KviTalCheckListItem must
+// be fully reimplemented and not be inherited from QCheckListItem
+// to build up a consistent item object hierarchy. To complete
+// the obscenity, we need TWO COMPLETE implementations: one for Qt3
+// and one for Qt4... bleah :D
+//
+// The code for KviTalCheckListItem is adapted from qlistview.h/cpp
+// present in qt 3.3.6 AND in qt 4.1.2.
+//
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_USE_QT4
+ #include "kvi_tal_listview_qt4.h"
+#else
+ #include "kvi_tal_listview_qt3.h"
+#endif
+
+#endif // _KVI_TAL_LISTVIEW_H_
diff --git a/src/kvilib/tal/kvi_tal_listview_qt3.h b/src/kvilib/tal/kvi_tal_listview_qt3.h
new file mode 100644
index 00000000..4fe4a766
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_listview_qt3.h
@@ -0,0 +1,190 @@
+#ifndef _KVI_TAL_LISTVIEW_QT3_H_
+#define _KVI_TAL_LISTVIEW_QT3_H_
+
+//=============================================================================
+//
+// File : kvi_tal_listview_qt3.h
+// Creation date : Mon Jan 22 2007 11:25:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#include "kvi_qstring.h"
+
+#include <qlistview.h>
+
+class KviTalListViewItem;
+
+class KVILIB_API KviTalListView : public QListView
+{
+ friend class KviTalCheckListItem;
+ Q_OBJECT
+public:
+ KviTalListView(QWidget * pParent);
+ virtual ~KviTalListView() {};
+public:
+ // Shadow the internal Qt methods
+ KviTalListViewItem * firstChild() const { return (KviTalListViewItem *)QListView::firstChild(); };
+ KviTalListViewItem * lastItem() const { return (KviTalListViewItem *)QListView::lastItem(); };
+ KviTalListViewItem * selectedItem() const { return (KviTalListViewItem *)QListView::selectedItem(); };
+ KviTalListViewItem * currentItem() const { return (KviTalListViewItem *)QListView::currentItem(); };
+ KviTalListViewItem * itemAt(const QPoint &pnt) const { return (KviTalListViewItem *)QListView::itemAt(pnt); };
+signals:
+ void selectionChanged(KviTalListViewItem * pItem);
+ void currentChanged(KviTalListViewItem * pItem);
+ void clicked(KviTalListViewItem * pItem);
+ void clicked(KviTalListViewItem * pItem,const QPoint &pnt,int uColumn);
+ void pressed(KviTalListViewItem * pItem);
+ void pressed(KviTalListViewItem * pItem,const QPoint &pnt,int uColumn);
+ void doubleClicked(KviTalListViewItem * pItem);
+ void doubleClicked(KviTalListViewItem * pItem,const QPoint &pnt,int uColumn);
+ void returnPressed(KviTalListViewItem * pItem);
+ void spacePressed(KviTalListViewItem * pItem);
+ void rightButtonClicked(KviTalListViewItem * pItem,const QPoint &pnt,int uColumn);
+ void rightButtonPressed(KviTalListViewItem * pItem,const QPoint &pnt,int uColumn);
+ void mouseButtonClicked(int iButton,KviTalListViewItem * pItem,const QPoint &pnt,int uColumn);
+ void mouseButtonPressed(int iButton,KviTalListViewItem * pItem,const QPoint &pnt,int uColumn);
+ void contextMenuRequested(KviTalListViewItem * pItem,const QPoint &pnt,int uColumn);
+ void onItem(KviTalListViewItem * pItem);
+ void expanded(KviTalListViewItem * pItem);
+ void collapsed(KviTalListViewItem * pItem);
+protected slots:
+ void redirect_selectionChanged(QListViewItem * pItem);
+ void redirect_currentChanged(QListViewItem * pItem);
+ void redirect_clicked(QListViewItem * pItem);
+ void redirect_clicked(QListViewItem * pItem,const QPoint &pnt,int uColumn);
+ void redirect_pressed(QListViewItem * pItem);
+ void redirect_pressed(QListViewItem * pItem,const QPoint &pnt,int uColumn);
+ void redirect_doubleClicked(QListViewItem * pItem);
+ void redirect_doubleClicked(QListViewItem * pItem,const QPoint &pnt,int uColumn);
+ void redirect_returnPressed(QListViewItem * pItem);
+ void redirect_spacePressed(QListViewItem * pItem);
+ void redirect_rightButtonClicked(QListViewItem * pItem,const QPoint &pnt,int uColumn);
+ void redirect_rightButtonPressed(QListViewItem * pItem,const QPoint &pnt,int uColumn);
+ void redirect_mouseButtonClicked(int iButton,QListViewItem * pItem,const QPoint &pnt,int uColumn);
+ void redirect_mouseButtonPressed(int iButton,QListViewItem * pItem,const QPoint &pnt,int uColumn);
+ void redirect_contextMenuRequested(QListViewItem * pItem,const QPoint &pnt,int uColumn);
+ void redirect_onItem(QListViewItem * pItem);
+ void redirect_expanded(QListViewItem * pItem);
+ void redirect_collapsed(QListViewItem * pItem);
+};
+
+
+class KVILIB_API KviTalListViewItem : public QListViewItem
+{
+public:
+ KviTalListViewItem(KviTalListView * pParent)
+ : QListViewItem(pParent) {};
+ KviTalListViewItem(KviTalListViewItem * pParent)
+ : QListViewItem(pParent) {};
+ KviTalListViewItem(KviTalListView * pParent,KviTalListViewItem * pAfter)
+ : QListViewItem(pParent,pAfter) {};
+ KviTalListViewItem(KviTalListViewItem * pParent,KviTalListViewItem * pAfter)
+ : QListViewItem(pParent,pAfter) {};
+ KviTalListViewItem(KviTalListView * pParent,const QString &szLabel1,const QString &szLabel2 = KviQString::empty,const QString &szLabel3 = KviQString::empty,const QString &szLabel4 = KviQString::empty,const QString &szLabel5 = KviQString::empty)
+ : QListViewItem(pParent,szLabel1,szLabel2,szLabel3,szLabel4,szLabel5) {};
+ KviTalListViewItem(KviTalListView * pParent,KviTalListViewItem * pAfter,const QString &szLabel1,const QString &szLabel2 = KviQString::empty,const QString &szLabel3 = KviQString::empty,const QString &szLabel4 = KviQString::empty,const QString &szLabel5 = KviQString::empty)
+ : QListViewItem(pParent,pAfter,szLabel1,szLabel2,szLabel3,szLabel4,szLabel5) {};
+ KviTalListViewItem(KviTalListViewItem * pParent,const QString &szLabel1,const QString &szLabel2 = KviQString::empty,const QString &szLabel3 = KviQString::empty,const QString &szLabel4 = KviQString::empty)
+ : QListViewItem(pParent,szLabel1,szLabel2,szLabel3,szLabel4) {};
+ KviTalListViewItem(KviTalListViewItem * pParent,KviTalListViewItem * pAfter,const QString &szLabel1,const QString &szLabel2 = KviQString::empty,const QString &szLabel3 = KviQString::empty,const QString &szLabel4 = KviQString::empty)
+ : QListViewItem(pParent,pAfter,szLabel1,szLabel2,szLabel3,szLabel4) {};
+ virtual ~KviTalListViewItem() {};
+public:
+ // Shadow the internal Qt methods
+ KviTalListViewItem * firstChild() const { return (KviTalListViewItem *)QListViewItem::firstChild(); };
+ KviTalListViewItem * nextSibling() const { return (KviTalListViewItem *)QListViewItem::nextSibling(); };
+ KviTalListViewItem * parent() const { return (KviTalListViewItem *)QListViewItem::parent(); };
+ KviTalListView * listView() const { return (KviTalListView *)QListViewItem::listView(); };
+ KviTalListViewItem * itemAbove() { return (KviTalListViewItem *)QListViewItem::itemAbove(); };
+ KviTalListViewItem * itemBelow() { return (KviTalListViewItem *)QListViewItem::itemBelow(); };
+};
+
+struct KviTalCheckListItemPrivate;
+
+class KVILIB_API KviTalCheckListItem : public KviTalListViewItem
+{
+public:
+ enum Type {
+ RadioButton,
+ CheckBox,
+ Controller,
+ RadioButtonController=Controller,
+ CheckBoxController
+ };
+ enum ToggleState { Off, NoChange, On };
+
+ KviTalCheckListItem(KviTalCheckListItem *parent, const QString &text,Type = RadioButtonController);
+ KviTalCheckListItem(KviTalCheckListItem *parent, KviTalListViewItem *after,const QString &text, Type = RadioButtonController);
+ KviTalCheckListItem( KviTalListViewItem *parent, const QString &text,Type = RadioButtonController );
+ KviTalCheckListItem( KviTalListViewItem *parent, KviTalListViewItem *after,const QString &text, Type = RadioButtonController );
+ KviTalCheckListItem( KviTalListView *parent, const QString &text,Type = RadioButtonController );
+ KviTalCheckListItem( KviTalListView *parent, KviTalListViewItem *after,const QString &text, Type = RadioButtonController );
+ KviTalCheckListItem( KviTalListViewItem *parent, const QString &text,const QPixmap & );
+ KviTalCheckListItem( KviTalListView *parent, const QString &text,const QPixmap & );
+ ~KviTalCheckListItem();
+
+ void paintCell( QPainter *,const QColorGroup & cg,int column, int width, int alignment );
+ virtual void paintFocus( QPainter *, const QColorGroup & cg,
+ const QRect & r );
+ int width( const QFontMetrics&, const KviTalListView*, int column) const;
+ void setup();
+
+ virtual void setOn( bool ); // ### should be replaced by setChecked in ver4
+ bool isOn() const { return on; }
+ Type type() const { return myType; }
+ QString text() const { return KviTalListViewItem::text( 0 ); }
+ QString text( int n ) const { return KviTalListViewItem::text( n ); }
+
+ void setTristate( bool );
+ bool isTristate() const;
+ ToggleState state() const;
+ void setState( ToggleState s);
+
+ int rtti() const;
+ static int RTTI;
+
+protected:
+ void activate();
+ void turnOffChild();
+ virtual void stateChange( bool );
+
+private:
+ void init();
+ ToggleState internalState() const;
+ void setStoredState( ToggleState newState, void *key );
+ ToggleState storedState( void *key ) const;
+ void stateChange( ToggleState s );
+ void restoreState( void *key, int depth = 0 );
+ void updateController( bool update = TRUE , bool store = FALSE );
+ void updateStoredState( void *key );
+ void setState( ToggleState s, bool update, bool store );
+ void setCurrentState( ToggleState s );
+
+ Type myType;
+ bool on; // ### remove in ver4
+ KviTalCheckListItemPrivate *d;
+};
+
+
+#define KviTalListViewItemIterator QListViewItemIterator
+
+#endif // _KVI_TAL_LISTVIEW_QT3_H_
diff --git a/src/kvilib/tal/kvi_tal_listview_qt4.h b/src/kvilib/tal/kvi_tal_listview_qt4.h
new file mode 100644
index 00000000..e6ccc829
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_listview_qt4.h
@@ -0,0 +1,199 @@
+#ifndef _KVI_TAL_LISTVIEW_QT4_H_
+#define _KVI_TAL_LISTVIEW_QT4_H_
+
+//=============================================================================
+//
+// File : kvi_tal_listview_qt4.h
+// Creation date : Mon Jan 22 2007 11:25:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#include "kvi_qstring.h"
+
+#include <q3listview.h>
+
+class KviTalListViewItem;
+
+
+class KVILIB_API KviTalListView : public Q3ListView
+{
+ friend class KviTalCheckListItem;
+ Q_OBJECT
+public:
+ KviTalListView(QWidget * pParent);
+ virtual ~KviTalListView() {};
+public:
+ // Shadow the internal Qt methods
+ KviTalListViewItem * firstChild() const { return (KviTalListViewItem *)Q3ListView::firstChild(); };
+ KviTalListViewItem * lastItem() const { return (KviTalListViewItem *)Q3ListView::lastItem(); };
+ KviTalListViewItem * selectedItem() const { return (KviTalListViewItem *)Q3ListView::selectedItem(); };
+ KviTalListViewItem * currentItem() const { return (KviTalListViewItem *)Q3ListView::currentItem(); };
+ KviTalListViewItem * itemAt(const QPoint &pnt) const { return (KviTalListViewItem *)Q3ListView::itemAt(pnt); };
+signals:
+ void selectionChanged(KviTalListViewItem * pItem);
+ void currentChanged(KviTalListViewItem * pItem);
+ void clicked(KviTalListViewItem * pItem);
+ void clicked(KviTalListViewItem * pItem,const QPoint &pnt,int uColumn);
+ void pressed(KviTalListViewItem * pItem);
+ void pressed(KviTalListViewItem * pItem,const QPoint &pnt,int uColumn);
+ void doubleClicked(KviTalListViewItem * pItem);
+ void doubleClicked(KviTalListViewItem * pItem,const QPoint &pnt,int uColumn);
+ void returnPressed(KviTalListViewItem * pItem);
+ void spacePressed(KviTalListViewItem * pItem);
+ void rightButtonClicked(KviTalListViewItem * pItem,const QPoint &pnt,int uColumn);
+ void rightButtonPressed(KviTalListViewItem * pItem,const QPoint &pnt,int uColumn);
+ void mouseButtonClicked(int iButton,KviTalListViewItem * pItem,const QPoint &pnt,int uColumn);
+ void mouseButtonPressed(int iButton,KviTalListViewItem * pItem,const QPoint &pnt,int uColumn);
+ void contextMenuRequested(KviTalListViewItem * pItem,const QPoint &pnt,int uColumn);
+ void onItem(KviTalListViewItem * pItem);
+ void expanded(KviTalListViewItem * pItem);
+ void collapsed(KviTalListViewItem * pItem);
+protected slots:
+ void redirect_selectionChanged(Q3ListViewItem * pItem);
+ void redirect_currentChanged(Q3ListViewItem * pItem);
+ void redirect_clicked(Q3ListViewItem * pItem);
+ void redirect_clicked(Q3ListViewItem * pItem,const QPoint &pnt,int uColumn);
+ void redirect_pressed(Q3ListViewItem * pItem);
+ void redirect_pressed(Q3ListViewItem * pItem,const QPoint &pnt,int uColumn);
+ void redirect_doubleClicked(Q3ListViewItem * pItem);
+ void redirect_doubleClicked(Q3ListViewItem * pItem,const QPoint &pnt,int uColumn);
+ void redirect_returnPressed(Q3ListViewItem * pItem);
+ void redirect_spacePressed(Q3ListViewItem * pItem);
+ void redirect_rightButtonClicked(Q3ListViewItem * pItem,const QPoint &pnt,int uColumn);
+ void redirect_rightButtonPressed(Q3ListViewItem * pItem,const QPoint &pnt,int uColumn);
+ void redirect_mouseButtonClicked(int iButton,Q3ListViewItem * pItem,const QPoint &pnt,int uColumn);
+ void redirect_mouseButtonPressed(int iButton,Q3ListViewItem * pItem,const QPoint &pnt,int uColumn);
+ void redirect_contextMenuRequested(Q3ListViewItem * pItem,const QPoint &pnt,int uColumn);
+ void redirect_onItem(Q3ListViewItem * pItem);
+ void redirect_expanded(Q3ListViewItem * pItem);
+ void redirect_collapsed(Q3ListViewItem * pItem);
+
+};
+
+
+class KVILIB_API KviTalListViewItem : public Q3ListViewItem
+{
+public:
+ KviTalListViewItem(KviTalListView * pParent)
+ : Q3ListViewItem(pParent) {};
+ KviTalListViewItem(KviTalListViewItem * pParent)
+ : Q3ListViewItem(pParent) {};
+ KviTalListViewItem(KviTalListView * pParent,KviTalListViewItem * pAfter)
+ : Q3ListViewItem(pParent,pAfter) {};
+ KviTalListViewItem(KviTalListViewItem * pParent,KviTalListViewItem * pAfter)
+ : Q3ListViewItem(pParent,pAfter) {};
+ KviTalListViewItem(KviTalListView * pParent,const QString &szLabel1,const QString &szLabel2 = KviQString::empty,const QString &szLabel3 = KviQString::empty,const QString &szLabel4 = KviQString::empty,const QString &szLabel5 = KviQString::empty)
+ : Q3ListViewItem(pParent,szLabel1,szLabel2,szLabel3,szLabel4,szLabel5) {};
+ KviTalListViewItem(KviTalListView * pParent,KviTalListViewItem * pAfter,const QString &szLabel1,const QString &szLabel2 = KviQString::empty,const QString &szLabel3 = KviQString::empty,const QString &szLabel4 = KviQString::empty,const QString &szLabel5 = KviQString::empty)
+ : Q3ListViewItem(pParent,pAfter,szLabel1,szLabel2,szLabel3,szLabel4,szLabel5) {};
+ KviTalListViewItem(KviTalListViewItem * pParent,const QString &szLabel1,const QString &szLabel2 = KviQString::empty,const QString &szLabel3 = KviQString::empty,const QString &szLabel4 = KviQString::empty)
+ : Q3ListViewItem(pParent,szLabel1,szLabel2,szLabel3,szLabel4) {};
+ KviTalListViewItem(KviTalListViewItem * pParent,KviTalListViewItem * pAfter,const QString &szLabel1,const QString &szLabel2 = KviQString::empty,const QString &szLabel3 = KviQString::empty,const QString &szLabel4 = KviQString::empty)
+ : Q3ListViewItem(pParent,pAfter,szLabel1,szLabel2,szLabel3,szLabel4) {};
+public:
+ // Shadow the internal Qt methods
+ KviTalListViewItem * firstChild() const { return (KviTalListViewItem *)Q3ListViewItem::firstChild(); };
+ KviTalListViewItem * nextSibling() const { return (KviTalListViewItem *)Q3ListViewItem::nextSibling(); };
+ KviTalListViewItem * parent() const { return (KviTalListViewItem *)Q3ListViewItem::parent(); };
+ KviTalListView * listView() const { return (KviTalListView *)Q3ListViewItem::listView(); };
+ KviTalListViewItem * itemAbove() { return (KviTalListViewItem *)Q3ListViewItem::itemAbove(); };
+ KviTalListViewItem * itemBelow() { return (KviTalListViewItem *)Q3ListViewItem::itemBelow(); };
+};
+
+struct KviTalCheckListItemPrivate;
+
+class KVILIB_API KviTalCheckListItem : public KviTalListViewItem
+{
+public:
+ enum Type { RadioButton,
+ CheckBox,
+ Controller,
+ RadioButtonController=Controller,
+ CheckBoxController };
+
+ enum ToggleState { Off, NoChange, On };
+
+ KviTalCheckListItem(KviTalCheckListItem *parent, const QString &text,
+ Type = RadioButtonController);
+ KviTalCheckListItem(KviTalCheckListItem *parent, KviTalListViewItem *after,
+ const QString &text, Type = RadioButtonController);
+ KviTalCheckListItem(KviTalListViewItem *parent, const QString &text,
+ Type = RadioButtonController);
+ KviTalCheckListItem(KviTalListViewItem *parent, KviTalListViewItem *after,
+ const QString &text, Type = RadioButtonController);
+ KviTalCheckListItem(KviTalListView *parent, const QString &text,
+ Type = RadioButtonController);
+ KviTalCheckListItem(KviTalListView *parent, KviTalListViewItem *after,
+ const QString &text, Type = RadioButtonController);
+ KviTalCheckListItem(KviTalListViewItem *parent, const QString &text,
+ const QPixmap &);
+ KviTalCheckListItem(KviTalListView *parent, const QString &text,
+ const QPixmap &);
+ ~KviTalCheckListItem();
+
+ void paintCell(QPainter *, const QColorGroup & cg,
+ int column, int width, int alignment);
+ virtual void paintFocus(QPainter *, const QColorGroup &cg,
+ const QRect & r);
+ int width(const QFontMetrics&, const KviTalListView*, int column) const;
+ void setup();
+
+ virtual void setOn(bool);
+ bool isOn() const { return on; }
+ Type type() const { return myType; }
+ QString text() const { return KviTalListViewItem::text(0); }
+ QString text(int n) const { return KviTalListViewItem::text(n); }
+
+ void setTristate(bool);
+ bool isTristate() const;
+ ToggleState state() const;
+ void setState(ToggleState s);
+
+ int rtti() const;
+ enum { RTTI = 1 };
+
+protected:
+ void activate();
+ void turnOffChild();
+ virtual void stateChange(bool);
+
+private:
+ void init();
+ ToggleState internalState() const;
+ void setStoredState(ToggleState newState, KviTalCheckListItem *key);
+ ToggleState storedState(KviTalCheckListItem *key) const;
+ void stateChange(ToggleState s);
+ void restoreState(KviTalCheckListItem *key, int depth = 0);
+ void updateController(bool update = true , bool store = false);
+ void updateStoredState(KviTalCheckListItem *key);
+ void setState(ToggleState s, bool update, bool store);
+ void setCurrentState(ToggleState s);
+
+ Type myType;
+ bool on;
+ KviTalCheckListItemPrivate *d;
+};
+
+#define KviTalListViewItemIterator Q3ListViewItemIterator
+
+
+#endif // _KVI_TAL_LISTVIEW_QT4_H_
diff --git a/src/kvilib/tal/kvi_tal_mainwindow.cpp b/src/kvilib/tal/kvi_tal_mainwindow.cpp
new file mode 100644
index 00000000..c2e52b2d
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_mainwindow.cpp
@@ -0,0 +1,69 @@
+//
+// File : kvi_tal_mainwindow.coo
+// Creation date : Sun Aug 12 2001 04:40:24 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#define __KVILIB__
+
+
+#include "kvi_tal_mainwindow.h"
+
+#ifdef COMPILE_KDE_SUPPORT
+
+ KviTalMainWindow::KviTalMainWindow(QWidget * par,const char * nam)
+ : KMainWindow(par,nam)
+ {
+ }
+
+ #include "kvi_tal_mainwindow_kde.moc"
+
+#else
+
+ #ifdef COMPILE_USE_QT4
+ KviTalMainWindow::KviTalMainWindow(QWidget * par,const char * nam)
+ : QMainWindow(par,nam)
+ {
+ }
+
+ bool KviTalMainWindow::usesBigPixmaps()
+ {
+ return (iconSize().width() > 40);
+ }
+
+ void KviTalMainWindow::setUsesBigPixmaps(bool b)
+ {
+ if(b)setIconSize(QSize(48,48));
+ else setIconSize(QSize(24,24));
+ }
+ #include "kvi_tal_mainwindow_qt4.moc"
+ #else
+ KviTalMainWindow::KviTalMainWindow(QWidget * par,const char * nam)
+ : QMainWindow(par,nam)
+ {
+ }
+ #include "kvi_tal_mainwindow_qt3.moc"
+ #endif
+
+#endif
+
+KviTalMainWindow::~KviTalMainWindow()
+{
+}
+
diff --git a/src/kvilib/tal/kvi_tal_mainwindow.h b/src/kvilib/tal/kvi_tal_mainwindow.h
new file mode 100644
index 00000000..76a1a79c
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_mainwindow.h
@@ -0,0 +1,38 @@
+#ifndef _KVI_TAL_MAINWINDOW_H_
+#define _KVI_TAL_MAINWINDOW_H_
+
+//
+// File : kvi_tal_mainwindow.h
+// Creation date : Sun Aug 12 2001 04:41:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_KDE_SUPPORT
+ #include "kvi_tal_mainwindow_kde.h"
+#else
+ #ifdef COMPILE_USE_QT4
+ #include "kvi_tal_mainwindow_qt4.h"
+ #else
+ #include "kvi_tal_mainwindow_qt3.h"
+ #endif
+#endif
+
+#endif // _KVI_TAL_MAINWINDOW_H_
diff --git a/src/kvilib/tal/kvi_tal_mainwindow_kde.h b/src/kvilib/tal/kvi_tal_mainwindow_kde.h
new file mode 100644
index 00000000..9f38aede
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_mainwindow_kde.h
@@ -0,0 +1,36 @@
+#ifndef _KVI_TAL_MAINWINDOW_KDE_H_
+#define _KVI_TAL_MAINWINDOW_KDE_H_
+
+//
+// File : kvi_tal_mainwindow_kde.h
+// Creation date : Sun Aug 12 2001 04:41:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include <kmainwindow.h>
+
+class KVILIB_API KviTalMainWindow : public KMainWindow
+{
+ Q_OBJECT
+public:
+ KviTalMainWindow(QWidget * par,const char * nam);
+ ~KviTalMainWindow();
+};
+
+#endif // _KVI_TAL_MAINWINDOW_KDE_H_
diff --git a/src/kvilib/tal/kvi_tal_mainwindow_qt3.h b/src/kvilib/tal/kvi_tal_mainwindow_qt3.h
new file mode 100644
index 00000000..d328774f
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_mainwindow_qt3.h
@@ -0,0 +1,36 @@
+#ifndef _KVI_TAL_MAINWINDOW_QT_H_
+#define _KVI_TAL_MAINWINDOW_QT_H_
+
+//
+// File : kvi_tal_mainwindow_qt.h
+// Creation date : Sun Aug 12 2001 04:43:58 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include <qmainwindow.h>
+
+class KVILIB_API KviTalMainWindow : public QMainWindow
+{
+ Q_OBJECT
+public:
+ KviTalMainWindow(QWidget * par,const char * nam);
+ ~KviTalMainWindow();
+};
+
+#endif // _KVI_TAL_MAINWINDOW_QT_H_
diff --git a/src/kvilib/tal/kvi_tal_mainwindow_qt4.h b/src/kvilib/tal/kvi_tal_mainwindow_qt4.h
new file mode 100644
index 00000000..b6c2c1be
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_mainwindow_qt4.h
@@ -0,0 +1,39 @@
+#ifndef _KVI_TAL_MAINWINDOW_QT_H_
+#define _KVI_TAL_MAINWINDOW_QT_H_
+
+//
+// File : kvi_tal_mainwindow_qt.h
+// Creation date : Sun Aug 12 2001 04:43:58 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include <qmainwindow.h>
+
+class KVILIB_API KviTalMainWindow : public QMainWindow
+{
+ Q_OBJECT
+public:
+ KviTalMainWindow(QWidget * par,const char * nam);
+ ~KviTalMainWindow();
+public:
+ bool usesBigPixmaps();
+ void setUsesBigPixmaps(bool b);
+};
+
+#endif // _KVI_TAL_MAINWINDOW_QT_H_
diff --git a/src/kvilib/tal/kvi_tal_menubar.cpp b/src/kvilib/tal/kvi_tal_menubar.cpp
new file mode 100644
index 00000000..0fbb28be
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_menubar.cpp
@@ -0,0 +1,58 @@
+//
+// File : kvi_tal_menubar.cpp
+// Creation date : Sun Aug 12 06:35:18 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#define __KVILIB__
+
+
+#include "kvi_tal_menubar.h"
+
+#ifdef COMPILE_KDE_SUPPORT
+
+ KviTalMenuBar::KviTalMenuBar(QWidget * par,const char * nam)
+ : KMenuBar(par,nam)
+ {
+ }
+
+ KviTalMenuBar::~KviTalMenuBar()
+ {
+ }
+
+ #include "kvi_tal_menubar_kde.moc"
+
+#else
+
+ KviTalMenuBar::KviTalMenuBar(QWidget * par,const char * nam)
+#ifdef COMPILE_USE_QT4
+ : QMenuBar(par)
+#else
+ : QMenuBar(par,nam)
+#endif
+ {
+ }
+
+ KviTalMenuBar::~KviTalMenuBar()
+ {
+ }
+
+ #include "kvi_tal_menubar_qt.moc"
+
+#endif
diff --git a/src/kvilib/tal/kvi_tal_menubar.h b/src/kvilib/tal/kvi_tal_menubar.h
new file mode 100644
index 00000000..08016bb7
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_menubar.h
@@ -0,0 +1,33 @@
+#ifndef _KVI_TAL_MENUBAR_H_
+#define _KVI_TAL_MENUBAR_H_
+//
+// File : kvi_tal_menubar.h
+// Creation date : Sun Aug 12 06:35:15 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_KDE_SUPPORT
+ #include "kvi_tal_menubar_kde.h"
+#else
+ #include "kvi_tal_menubar_qt.h"
+#endif
+
+#endif //_KVI_TAL_MENUBAR_H_
diff --git a/src/kvilib/tal/kvi_tal_menubar_kde.h b/src/kvilib/tal/kvi_tal_menubar_kde.h
new file mode 100644
index 00000000..e345d221
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_menubar_kde.h
@@ -0,0 +1,35 @@
+#ifndef _KVI_TAL_MENUBAR_KDE_H_
+#define _KVI_TAL_MENUBAR_KDE_H_
+//
+// File : kvi_tal_menubar_kde.h
+// Creation date : Sun Aug 12 06:35:22 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include <kmenubar.h>
+
+class KVILIB_API KviTalMenuBar : public KMenuBar
+{
+ Q_OBJECT
+public:
+ KviTalMenuBar(QWidget * par,const char * nam);
+ ~KviTalMenuBar();
+};
+
+#endif //_KVI_TAL_MENUBAR_KDE_H_
diff --git a/src/kvilib/tal/kvi_tal_menubar_qt.h b/src/kvilib/tal/kvi_tal_menubar_qt.h
new file mode 100644
index 00000000..c42dab7f
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_menubar_qt.h
@@ -0,0 +1,35 @@
+#ifndef _KVI_TAL_MENUBAR_QT_H_
+#define _KVI_TAL_MENUBAR_QT_H_
+//
+// File : kvi_tal_menubar_qt.h
+// Creation date : Sun Aug 12 06:35:24 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include <qmenubar.h>
+
+class KVILIB_API KviTalMenuBar : public QMenuBar
+{
+ Q_OBJECT
+public:
+ KviTalMenuBar(QWidget * par,const char * nam);
+ ~KviTalMenuBar();
+};
+
+#endif //_KVI_TAL_MENUBAR_QT_H_
diff --git a/src/kvilib/tal/kvi_tal_popupmenu.cpp b/src/kvilib/tal/kvi_tal_popupmenu.cpp
new file mode 100644
index 00000000..ad3c8463
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_popupmenu.cpp
@@ -0,0 +1,33 @@
+//=============================================================================
+//
+// File : kvi_tal_popupmenu.cpp
+// Creation date : Mon Jan 22 2007 11:25:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+#include "kvi_tal_popupmenu.h"
+
+#ifdef COMPILE_USE_QT4
+ #include "kvi_tal_popupmenu_qt4.moc"
+#else
+ #include "kvi_tal_popupmenu_qt3.moc"
+#endif
+
diff --git a/src/kvilib/tal/kvi_tal_popupmenu.h b/src/kvilib/tal/kvi_tal_popupmenu.h
new file mode 100644
index 00000000..5035f031
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_popupmenu.h
@@ -0,0 +1,36 @@
+#ifndef _KVI_TAL_POPUPMENU_H_
+#define _KVI_TAL_POPUPMENU_H_
+
+//=============================================================================
+//
+// File : kvi_tal_popupmenu.h
+// Creation date : Mon Jan 22 2007 11:25:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_USE_QT4
+ #include "kvi_tal_popupmenu_qt4.h"
+#else
+ #include "kvi_tal_popupmenu_qt3.h"
+#endif
+
+#endif // _KVI_TAL_POPUPMENU_H_
diff --git a/src/kvilib/tal/kvi_tal_popupmenu_qt3.h b/src/kvilib/tal/kvi_tal_popupmenu_qt3.h
new file mode 100644
index 00000000..3340945b
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_popupmenu_qt3.h
@@ -0,0 +1,42 @@
+#ifndef _KVI_TAL_POPUPMENU_QT3_H_
+#define _KVI_TAL_POPUPMENU_QT3_H_
+
+//=============================================================================
+//
+// File : kvi_tal_popupmenu.h
+// Creation date : Mon Jan 22 2007 11:25:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+
+#include <qpopupmenu.h>
+
+class KVILIB_API KviTalPopupMenu : public QPopupMenu
+{
+ Q_OBJECT
+public:
+ KviTalPopupMenu(QWidget * pParent=0,const QString &szName = KviQString::empty)
+ : QPopupMenu(pParent,KviQString::toUtf8(szName).data()) {};
+ virtual ~KviTalPopupMenu() {};
+};
+
+#endif // _KVI_TAL_POPUPMENU_QT3_H_
diff --git a/src/kvilib/tal/kvi_tal_popupmenu_qt4.h b/src/kvilib/tal/kvi_tal_popupmenu_qt4.h
new file mode 100644
index 00000000..58da15ef
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_popupmenu_qt4.h
@@ -0,0 +1,89 @@
+#ifndef _KVI_TAL_POPUPMENU_QT4_H_
+#define _KVI_TAL_POPUPMENU_QT4_H_
+
+//=============================================================================
+//
+// File : kvi_tal_popupmenu_qt3.h
+// Creation date : Mon Jan 22 2007 11:25:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+
+#include <q3popupmenu.h>
+#include <qwidgetaction.h>
+
+class KVILIB_API KviTalPopupMenu : public Q3PopupMenu
+{
+ Q_OBJECT
+public:
+ KviTalPopupMenu(QWidget * pParent=0,const QString &szName = KviQString::empty)
+ : Q3PopupMenu(pParent)
+ {
+ setName(szName);
+ };
+ virtual ~KviTalPopupMenu() {};
+
+ int insertItem(const QString &szText)
+ {
+ return Q3PopupMenu::insertItem(szText);
+ }
+ int insertItem(const QPixmap &pix,const QString &szText)
+ {
+ return Q3PopupMenu::insertItem(QIcon(pix),szText,-1,-1);
+ }
+ int insertItem(const QString &szText,int id)
+ {
+ return Q3PopupMenu::insertItem(szText,id);
+ }
+ int insertItem(const QPixmap &pix,const QString &szText,int id)
+ {
+ return Q3PopupMenu::insertItem(QIcon(pix),szText,id,-1);
+ }
+ int insertItem(const QString &szText,const QObject * pReceiver,const char * szSlot)
+ {
+ return Q3PopupMenu::insertItem(szText,pReceiver,szSlot);
+ }
+ int insertItem(const QPixmap &pix,const QString &szText,const QObject * pReceiver,const char * szSlot)
+ {
+ return Q3PopupMenu::insertItem(QIcon(pix),szText,pReceiver,szSlot);
+ }
+ int insertItem(const QPixmap &pix,const QString &szText,QMenu *pMenu)
+ {
+ return Q3PopupMenu::insertItem(QIcon(pix),szText,pMenu,-1,-1);
+ }
+ int insertItem(const QString &szText,QMenu *pMenu)
+ {
+ return Q3PopupMenu::insertItem(szText,pMenu,-1,-1);
+ }
+ int insertItem(QWidget * pWidget)
+ {
+ // needs Qt 4.2
+ QWidgetAction * pAct = new QWidgetAction(this);
+ pAct->setDefaultWidget(pWidget);
+ addAction(pAct);
+ return 0;
+ }
+
+
+};
+
+#endif // _KVI_TAL_POPUPMENU_QT4_H_
diff --git a/src/kvilib/tal/kvi_tal_scrollview.cpp b/src/kvilib/tal/kvi_tal_scrollview.cpp
new file mode 100644
index 00000000..7e3e5eba
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_scrollview.cpp
@@ -0,0 +1,33 @@
+//=============================================================================
+//
+// File : kvi_tal_scrollview.cpp
+// Creation date : Mon Jan 22 2007 11:25:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+#include "kvi_tal_scrollview.h"
+
+#ifdef COMPILE_USE_QT4
+ #include "kvi_tal_scrollview_qt4.moc"
+#else
+ #include "kvi_tal_scrollview_qt3.moc"
+#endif
+
diff --git a/src/kvilib/tal/kvi_tal_scrollview.h b/src/kvilib/tal/kvi_tal_scrollview.h
new file mode 100644
index 00000000..ff27acf4
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_scrollview.h
@@ -0,0 +1,36 @@
+#ifndef _KVI_TAL_SCROLLVIEW_H_
+#define _KVI_TAL_SCROLLVIEW_H_
+
+//=============================================================================
+//
+// File : kvi_tal_scrollview.h
+// Creation date : Mon Jan 22 2007 11:25:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_USE_QT4
+ #include "kvi_tal_scrollview_qt4.h"
+#else
+ #include "kvi_tal_scrollview_qt3.h"
+#endif
+
+#endif // _KVI_TAL_SCROLLVIEW_H_
diff --git a/src/kvilib/tal/kvi_tal_scrollview_qt3.h b/src/kvilib/tal/kvi_tal_scrollview_qt3.h
new file mode 100644
index 00000000..da6141e1
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_scrollview_qt3.h
@@ -0,0 +1,41 @@
+#ifndef _KVI_TAL_SCROLLVIEW_QT3_H_
+#define _KVI_TAL_SCROLLVIEW_QT3_H_
+
+//=============================================================================
+//
+// File : kvi_tal_scrollview_qt3.h
+// Creation date : Mon Jan 22 2007 11:25:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#include <qscrollview.h>
+
+class KVILIB_API KviTalScrollView : public QScrollView
+{
+ Q_OBJECT
+public:
+ KviTalScrollView(QWidget * pParent)
+ : QScrollView(pParent) {};
+ virtual ~KviTalScrollView() {};
+};
+
+#endif // _KVI_TAL_SCROLLVIEW_QT3_H_
diff --git a/src/kvilib/tal/kvi_tal_scrollview_qt4.h b/src/kvilib/tal/kvi_tal_scrollview_qt4.h
new file mode 100644
index 00000000..c82f5723
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_scrollview_qt4.h
@@ -0,0 +1,41 @@
+#ifndef _KVI_TAL_SCROLLVIEW_QT4_H_
+#define _KVI_TAL_SCROLLVIEW_QT4_H_
+
+//=============================================================================
+//
+// File : kvi_tal_scrollview_qt4.h
+// Creation date : Mon Jan 22 2007 11:25:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#include <q3scrollview.h>
+
+class KVILIB_API KviTalScrollView : public Q3ScrollView
+{
+ Q_OBJECT
+public:
+ KviTalScrollView(QWidget * pParent)
+ : Q3ScrollView(pParent) {};
+ virtual ~KviTalScrollView() {};
+};
+
+#endif // _KVI_TAL_SCROLLVIEW_QT4_H_
diff --git a/src/kvilib/tal/kvi_tal_tabdialog.cpp b/src/kvilib/tal/kvi_tal_tabdialog.cpp
new file mode 100644
index 00000000..81bd5b39
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_tabdialog.cpp
@@ -0,0 +1,34 @@
+//=============================================================================
+//
+// File : kvi_tal_tabdialog.cpp
+// Creation date : Tue Feb 06 2007 14:35:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+#include "kvi_tal_tabdialog.h"
+
+
+#ifdef COMPILE_USE_QT4
+ #include "kvi_tal_tabdialog_qt4.moc"
+#else
+ #include "kvi_tal_tabdialog_qt3.moc"
+#endif
+
diff --git a/src/kvilib/tal/kvi_tal_tabdialog.h b/src/kvilib/tal/kvi_tal_tabdialog.h
new file mode 100644
index 00000000..46e09843
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_tabdialog.h
@@ -0,0 +1,36 @@
+#ifndef _KVI_TAL_TABDIALOG_H_
+#define _KVI_TAL_TABDIALOG_H_
+
+//=============================================================================
+//
+// File : kvi_tal_tabdialog.h
+// Creation date : Tue Feb 06 2007 14:35:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_USE_QT4
+ #include "kvi_tal_tabdialog_qt4.h"
+#else
+ #include "kvi_tal_tabdialog_qt3.h"
+#endif
+
+#endif // _KVI_TAL_TABDIALOG_H_
diff --git a/src/kvilib/tal/kvi_tal_tabdialog_qt3.h b/src/kvilib/tal/kvi_tal_tabdialog_qt3.h
new file mode 100644
index 00000000..061053a3
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_tabdialog_qt3.h
@@ -0,0 +1,39 @@
+#ifndef _KVI_TAL_TABDIALOG_QT3_H_
+#define _KVI_TAL_TABDIALOG_QT3_H_
+
+//=============================================================================
+//
+// File : kvi_tal_tabdialog_qt3.h
+// Creation date : Tue Feb 06 2007 14:35:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include <qtabdialog.h>
+
+class KVILIB_API KviTalTabDialog : public QTabDialog
+{
+ Q_OBJECT
+public:
+ KviTalTabDialog(QWidget * pParent = 0,const char * name = 0,bool bModal = false)
+ : QTabDialog(pParent,name,bModal) {};
+ ~KviTalTabDialog() {};
+};
+
+#endif // _KVI_TAL_TABDIALOG_QT3_H_
diff --git a/src/kvilib/tal/kvi_tal_tabdialog_qt4.h b/src/kvilib/tal/kvi_tal_tabdialog_qt4.h
new file mode 100644
index 00000000..c9e3eb0b
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_tabdialog_qt4.h
@@ -0,0 +1,39 @@
+#ifndef _KVI_TAL_TABDIALOG_QT4_H_
+#define _KVI_TAL_TABDIALOG_QT4_H_
+
+//=============================================================================
+//
+// File : kvi_tal_tabdialog_qt4.h
+// Creation date : Tue Feb 06 2007 14:35:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include <q3tabdialog.h>
+
+class KVILIB_API KviTalTabDialog : public Q3TabDialog
+{
+ Q_OBJECT
+public:
+ KviTalTabDialog(QWidget * pParent = 0,const char * name = 0,bool bModal = false)
+ : Q3TabDialog(pParent,name,bModal) {};
+ ~KviTalTabDialog() {};
+};
+
+#endif // _KVI_TAL_TABDIALOG_QT3_H_
diff --git a/src/kvilib/tal/kvi_tal_textedit.cpp b/src/kvilib/tal/kvi_tal_textedit.cpp
new file mode 100644
index 00000000..686c8cba
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_textedit.cpp
@@ -0,0 +1,34 @@
+//=============================================================================
+//
+// File : kvi_tal_textedit.cpp
+// Creation date : Tue Feb 06 2007 14:35:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+#include "kvi_tal_textedit.h"
+
+
+#ifdef COMPILE_USE_QT4
+ #include "kvi_tal_textedit_qt4.moc"
+#else
+ #include "kvi_tal_textedit_qt3.moc"
+#endif
+
diff --git a/src/kvilib/tal/kvi_tal_textedit.h b/src/kvilib/tal/kvi_tal_textedit.h
new file mode 100644
index 00000000..fb7381ae
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_textedit.h
@@ -0,0 +1,36 @@
+#ifndef _KVI_TAL_TEXTEDIT_H_
+#define _KVI_TAL_TEXTEDIT_H_
+
+//=============================================================================
+//
+// File : kvi_tal_textedit.h
+// Creation date : Tue Feb 06 2007 14:35:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_USE_QT4
+ #include "kvi_tal_textedit_qt4.h"
+#else
+ #include "kvi_tal_textedit_qt3.h"
+#endif
+
+#endif // _KVI_TAL_TEXTEDIT_H_
diff --git a/src/kvilib/tal/kvi_tal_textedit_qt3.h b/src/kvilib/tal/kvi_tal_textedit_qt3.h
new file mode 100644
index 00000000..b698f483
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_textedit_qt3.h
@@ -0,0 +1,39 @@
+#ifndef _KVI_TAL_TEXTEDIT_QT3_H_
+#define _KVI_TAL_TEXTEDIT_QT3_H_
+
+//=============================================================================
+//
+// File : kvi_tal_textedit_qt3.h
+// Creation date : Tue Feb 06 2007 14:35:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include <qtextedit.h>
+
+class KVILIB_API KviTalTextEdit : public QTextEdit
+{
+ Q_OBJECT
+public:
+ KviTalTextEdit(QWidget * pParent = 0,const char * name = 0)
+ : QTextEdit(pParent,name) {};
+ ~KviTalTextEdit() {};
+};
+
+#endif // _KVI_TAL_TEXTEDIT_QT3_H_
diff --git a/src/kvilib/tal/kvi_tal_textedit_qt4.h b/src/kvilib/tal/kvi_tal_textedit_qt4.h
new file mode 100644
index 00000000..a3403d7c
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_textedit_qt4.h
@@ -0,0 +1,39 @@
+#ifndef _KVI_TAL_TEXTEDIT_QT4_H_
+#define _KVI_TAL_TEXTEDIT_QT4_H_
+
+//=============================================================================
+//
+// File : kvi_tal_textedit_qt4.h
+// Creation date : Tue Feb 06 2007 14:35:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include <q3textedit.h>
+
+class KVILIB_API KviTalTextEdit : public Q3TextEdit
+{
+ Q_OBJECT
+public:
+ KviTalTextEdit(QWidget * pParent = 0,const char * name = 0)
+ : Q3TextEdit(pParent,name) {};
+ ~KviTalTextEdit() {};
+};
+
+#endif // _KVI_TAL_TEXTEDIT_QT4_H_
diff --git a/src/kvilib/tal/kvi_tal_toolbar.cpp b/src/kvilib/tal/kvi_tal_toolbar.cpp
new file mode 100644
index 00000000..f54dc973
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_toolbar.cpp
@@ -0,0 +1,107 @@
+//
+// File : kvi_tal_toolbar.cpp
+// Creation date : Mon Aug 13 05:05:45 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#define __KVILIB__
+
+
+#include "kvi_tal_toolbar.h"
+
+#ifdef COMPILE_KDE_SUPPORT
+
+ KviTalToolBar::KviTalToolBar(const QString &label,QMainWindow *w,QT_TOOLBARDOCK_TYPE dock,bool bNewLine,const char * nam)
+ : KToolBar(w,dock,bNewLine,nam)
+ {
+ setLabel(label);
+ }
+
+ KviTalToolBar::~KviTalToolBar()
+ {
+ }
+
+ #include "kvi_tal_toolbar_kde.moc"
+
+#else
+
+ #ifdef COMPILE_USE_QT4
+
+ KviTalToolBar::KviTalToolBar(const QString &label,QMainWindow *w,QT_TOOLBARDOCK_TYPE dock,bool bNewLine,const char * nam)
+ //: Q3ToolBar(label,w,dock,bNewLine,nam)
+ : QToolBar(label,w)
+ {
+ //setFrameStyle(QFrame::NoFrame);
+ setObjectName(nam);
+ if(!layout())
+ this->setLayout(new QBoxLayout(QBoxLayout::LeftToRight));
+ w->addToolBar(dock,this);
+ }
+ KviTalToolBar::KviTalToolBar(QMainWindow *w,const char * name)
+ : QToolBar(w)
+ {
+ //setFrameStyle(QFrame::NoFrame);
+ setObjectName(name);
+ if(!layout())
+ this->setLayout(new QBoxLayout(QBoxLayout::LeftToRight));
+ w->addToolBar(this);
+ }
+
+ QBoxLayout * KviTalToolBar::boxLayout()
+ {
+ return (QBoxLayout*)this->layout();
+ }
+
+ void KviTalToolBar::setBoxLayout(QBoxLayout * l)
+ {
+ this->setLayout(l);
+ }
+
+ bool KviTalToolBar::usesBigPixmaps()
+ {
+ return (iconSize().width() > 40);
+ }
+
+ void KviTalToolBar::setUsesBigPixmaps(bool b)
+ {
+ if(b)setIconSize(QSize(48,48));
+ else setIconSize(QSize(22,22));
+ }
+
+ #include "kvi_tal_toolbar_qt4.moc"
+
+ #else
+ KviTalToolBar::KviTalToolBar(const QString &label,QMainWindow *w,QT_TOOLBARDOCK_TYPE dock,bool bNewLine,const char * nam)
+ : QToolBar(label,w,dock,bNewLine,nam)
+ {
+ }
+ KviTalToolBar::KviTalToolBar(QMainWindow *w,const char * name)
+ : QToolBar(w,name)
+ {
+ }
+
+ #include "kvi_tal_toolbar_qt3.moc"
+ #endif
+
+ KviTalToolBar::~KviTalToolBar()
+ {
+ }
+
+
+#endif
diff --git a/src/kvilib/tal/kvi_tal_toolbar.h b/src/kvilib/tal/kvi_tal_toolbar.h
new file mode 100644
index 00000000..c5c9d5cc
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_toolbar.h
@@ -0,0 +1,37 @@
+#ifndef _KVI_TAL_TOOLBAR_H_
+#define _KVI_TAL_TOOLBAR_H_
+//
+// File : kvi_tal_toolbar.h
+// Creation date : Mon Aug 13 05:05:44 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_KDE_SUPPORT
+ #include "kvi_tal_toolbar_kde.h"
+#else
+ #ifdef COMPILE_USE_QT4
+ #include "kvi_tal_toolbar_qt4.h"
+ #else
+ #include "kvi_tal_toolbar_qt3.h"
+ #endif
+#endif
+
+#endif //_KVI_TAL_TOOLBAR_H_
diff --git a/src/kvilib/tal/kvi_tal_toolbar_kde.h b/src/kvilib/tal/kvi_tal_toolbar_kde.h
new file mode 100644
index 00000000..f6415f26
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_toolbar_kde.h
@@ -0,0 +1,37 @@
+#ifndef _KVI_TAL_TOOLBAR_KDE_H_
+#define _KVI_TAL_TOOLBAR_KDE_H_
+//
+// File : kvi_tal_toolbar_kde.h
+// Creation date : Mon Aug 13 05:05:52 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include <ktoolbar.h>
+
+#include "kvi_tal_toolbardocktype.h"
+
+class KVILIB_API KviTalToolBar : public KToolBar
+{
+ Q_OBJECT
+public:
+ KviTalToolBar(const QString &label,QMainWindow *w,QT_TOOLBARDOCK_TYPE dock = QT_DOCK_TOP,bool bNewLine = false,const char * nam = 0);
+ ~KviTalToolBar();
+};
+
+#endif //_KVI_TAL_TOOLBAR_KDE_H_
diff --git a/src/kvilib/tal/kvi_tal_toolbar_qt3.h b/src/kvilib/tal/kvi_tal_toolbar_qt3.h
new file mode 100644
index 00000000..a9b15b52
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_toolbar_qt3.h
@@ -0,0 +1,39 @@
+#ifndef _KVI_TAL_TOOLBAR_QT_H_
+#define _KVI_TAL_TOOLBAR_QT_H_
+//
+// File : kvi_tal_toolbar_qt.h
+// Creation date : Mon Aug 13 05:05:50 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include <qtoolbar.h>
+#include <qmainwindow.h>
+
+#include "kvi_tal_toolbardocktype.h"
+
+class KVILIB_API KviTalToolBar : public QToolBar
+{
+ Q_OBJECT
+public:
+ KviTalToolBar(const QString &label,QMainWindow *w,QT_TOOLBARDOCK_TYPE dock = QT_DOCK_TOP,bool bNewLine = false,const char * nam = 0);
+ KviTalToolBar(QMainWindow *w,const char * name=0);
+ ~KviTalToolBar();
+};
+
+#endif //_KVI_TAL_TOOLBAR_QT_H_
diff --git a/src/kvilib/tal/kvi_tal_toolbar_qt4.h b/src/kvilib/tal/kvi_tal_toolbar_qt4.h
new file mode 100644
index 00000000..753d5a5c
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_toolbar_qt4.h
@@ -0,0 +1,47 @@
+#ifndef _KVI_TAL_TOOLBAR_QT4_H_
+#define _KVI_TAL_TOOLBAR_QT4_H_
+//
+// File : kvi_tal_toolbar_qt4.h
+// Creation date : Wed Feb 1 2007 04:11:11 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+#include "kvi_tal_toolbardocktype.h"
+
+#include <QToolBar>
+#include <QMainWindow>
+#include <QBoxLayout>
+
+
+class KVILIB_API KviTalToolBar : public QToolBar
+{
+ Q_OBJECT
+public:
+ KviTalToolBar(const QString &label,QMainWindow *w,QT_TOOLBARDOCK_TYPE dock = QT_DOCK_TOP,bool bNewLine = false,const char * nam = 0);
+ KviTalToolBar(QMainWindow *w,const char * name=0);
+ ~KviTalToolBar();
+public:
+ QBoxLayout * boxLayout();
+ void setBoxLayout(QBoxLayout *l);
+ bool usesBigPixmaps();
+ void setUsesBigPixmaps(bool b);
+};
+
+#endif //_KVI_TAL_TOOLBAR_QT_H_
diff --git a/src/kvilib/tal/kvi_tal_toolbardocktype.h b/src/kvilib/tal/kvi_tal_toolbardocktype.h
new file mode 100644
index 00000000..a7c9697a
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_toolbardocktype.h
@@ -0,0 +1,71 @@
+#ifndef _KVI_TAL_TOOLBARDOCKTYPE_H_
+#define _KVI_TAL_TOOLBARDOCKTYPE_H_
+//
+// File : kvi_tal_toolbardocktype.h
+// Creation date : Tue Sep 17 02:11:28 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+//#define COMPILE_USE_QT4
+#ifdef COMPILE_USE_QT4
+/*
+ #define QT_TOOLBARDOCK_TYPE Qt::Dock
+ #define QT_DOCK_TOP Qt::DockTop
+ #define QT_DOCK_LEFT Qt::DockLeft
+ #define QT_DOCK_RIGHT Qt::DockRight
+ #define QT_DOCK_BOTTOM Qt::DockBottom
+ #define QT_DOCK_MINIMIZED Qt::DockMinimized
+ #define QT_DOCK_TORNOFF Qt::DockTornOff
+ #define QT_DOCK_UNMANAGED Qt::DockUnmanaged
+*/
+ // We will need these when we'll use the real QToolBar in Qt 4.x
+ #define QT_TOOLBARDOCK_TYPE Qt::ToolBarArea
+ #define QT_DOCK_TOP Qt::TopToolBarArea
+ #define QT_DOCK_LEFT Qt::LeftToolBarArea
+ #define QT_DOCK_RIGHT Qt::RightToolBarArea
+ #define QT_DOCK_BOTTOM Qt::BottomToolBarArea
+ // THESE ARE UNSUPPORTED UNDER QT4!
+ #define QT_DOCK_MINIMIZED Qt::TopToolBarArea
+ #define QT_DOCK_TORNOFF Qt::TopToolBarArea
+ #define QT_DOCK_UNMANAGED Qt::TopToolBarArea
+
+#else
+ #if QT_VERSION >= 300
+ #define QT_TOOLBARDOCK_TYPE Qt::Dock
+ #define QT_DOCK_TOP Qt::DockTop
+ #define QT_DOCK_LEFT Qt::DockLeft
+ #define QT_DOCK_RIGHT Qt::DockRight
+ #define QT_DOCK_BOTTOM Qt::DockBottom
+ #define QT_DOCK_MINIMIZED Qt::DockMinimized
+ #define QT_DOCK_TORNOFF Qt::DockTornOff
+ #define QT_DOCK_UNMANAGED Qt::DockUnmanaged
+ #else
+ #define QT_TOOLBARDOCK_TYPE QMainWindow::ToolBarDock
+ #define QT_DOCK_TOP QMainWindow::Top
+ #define QT_DOCK_LEFT QMainWindow::Left
+ #define QT_DOCK_RIGHT QMainWindow::Right
+ #define QT_DOCK_BOTTOM QMainWindow::Bottom
+ #define QT_DOCK_MINIMIZED QMainWindow::Minimized
+ #define QT_DOCK_TORNOFF QMainWindow::TornOff
+ #define QT_DOCK_UNMANAGED QMainWindow::Unmanaged
+ #endif
+#endif
+
+#endif //_KVI_TAL_TOOLBARDOCKTYPE_H_
diff --git a/src/kvilib/tal/kvi_tal_tooltip.cpp b/src/kvilib/tal/kvi_tal_tooltip.cpp
new file mode 100644
index 00000000..3bd384d2
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_tooltip.cpp
@@ -0,0 +1,125 @@
+//=============================================================================
+//
+// File : kvi_tal_tooltip.cpp
+// Creation date : Mon Jan 22 2007 11:25:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+#include "kvi_tal_tooltip.h"
+
+#include <qevent.h>
+
+KviTalToolTipHelper::KviTalToolTipHelper(KviTalToolTip * pToolTip,QWidget * pWidget)
+: QObject(pWidget)
+{
+#ifdef COMPILE_USE_QT4
+ m_pToolTip = pToolTip;
+ pWidget->installEventFilter(this);
+#endif
+}
+
+KviTalToolTipHelper::~KviTalToolTipHelper()
+{
+#ifdef COMPILE_USE_QT4
+ if(m_pToolTip)
+ {
+ m_pToolTip->helperDying();
+ delete m_pToolTip;
+ }
+#endif
+}
+
+void KviTalToolTipHelper::toolTipDying()
+{
+#ifdef COMPILE_USE_QT4
+ m_pToolTip = 0;
+#endif
+}
+
+bool KviTalToolTipHelper::eventFilter(QObject * pObject,QEvent * pEvent)
+{
+#ifdef COMPILE_USE_QT4
+ if((pEvent->type() == QEvent::ToolTip) && m_pToolTip)
+ {
+ debug("TOOL TIP EVENT WITH POSITION %d,%d",((QHelpEvent *)pEvent)->pos().x(),((QHelpEvent *)pEvent)->pos().y());
+ m_pToolTip->maybeTip(((QHelpEvent *)pEvent)->pos());
+ return true;
+ }
+#endif
+ return false;
+}
+
+
+KviTalToolTip::KviTalToolTip(QWidget * pParent)
+#ifndef COMPILE_USE_QT4
+: QToolTip(pParent)
+#endif
+{
+#ifdef COMPILE_USE_QT4
+ m_pHelper = new KviTalToolTipHelper(this,pParent);
+ m_pParent = pParent;
+#endif
+}
+
+KviTalToolTip::~KviTalToolTip()
+{
+#ifdef COMPILE_USE_QT4
+ if(m_pHelper)
+ {
+ m_pHelper->toolTipDying();
+ delete m_pHelper;
+ }
+#endif
+}
+
+#ifdef COMPILE_USE_QT4
+void KviTalToolTip::helperDying()
+{
+ m_pHelper = 0;
+}
+#endif
+
+#ifdef COMPILE_USE_QT4
+void KviTalToolTip::add(QWidget * widget,const QString & text)
+{
+ QToolTip::add(widget,text);
+}
+
+void KviTalToolTip::remove(QWidget * widget)
+{
+ QToolTip::remove(widget);
+}
+
+void KviTalToolTip::tip(const QRect & rect,const QString & text)
+{
+ debug("TOOL TIP AT %d,%d",rect.topLeft().x(),rect.topLeft().y());
+ QToolTip::showText(m_pParent->mapToGlobal(rect.topLeft()),text);
+}
+#endif
+
+void KviTalToolTip::maybeTip(const QPoint & p)
+{
+ // does nothing here.. and in Qt 4.x will even fail to work
+}
+
+#ifndef COMPILE_ON_WINDOWS
+ #include "kvi_tal_tooltip.moc"
+#endif
diff --git a/src/kvilib/tal/kvi_tal_tooltip.h b/src/kvilib/tal/kvi_tal_tooltip.h
new file mode 100644
index 00000000..91811c3c
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_tooltip.h
@@ -0,0 +1,79 @@
+#ifndef _KVI_TAL_TOOLTIP_H_
+#define _KVI_TAL_TOOLTIP_H_
+
+//=============================================================================
+//
+// File : kvi_tal_tooltip.h
+// Creation date : Mon Jan 22 2007 11:25:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#include <qtooltip.h>
+#include <qobject.h>
+
+class KviTalToolTip;
+
+// This is useful only with Qt4, but we put it here anyway
+// to have both a consistent API and make moc happy
+class KviTalToolTipHelper : public QObject
+{
+ friend class KviTalToolTip;
+ Q_OBJECT
+public:
+ KviTalToolTipHelper(KviTalToolTip * pToolTip,QWidget * pWidget);
+ ~KviTalToolTipHelper();
+protected:
+ KviTalToolTip * m_pToolTip;
+protected:
+ virtual bool eventFilter(QObject * pObject,QEvent * pEvent);
+ void toolTipDying();
+};
+
+
+class KVILIB_API KviTalToolTip
+#ifndef COMPILE_USE_QT4
+ : public QToolTip
+#endif
+{
+ friend class KviTalToolTipHelper;
+public:
+ KviTalToolTip(QWidget * pParent);
+ virtual ~KviTalToolTip();
+protected:
+#ifdef COMPILE_USE_QT4
+ KviTalToolTipHelper * m_pHelper;
+ QWidget * m_pParent;
+#endif
+public:
+#ifdef COMPILE_USE_QT4
+ static void add(QWidget * widget,const QString & text);
+ static void remove(QWidget * widget);
+ virtual void tip(const QRect & rect,const QString & text);
+#endif
+protected:
+ virtual void maybeTip(const QPoint & p);
+#ifdef COMPILE_USE_QT4
+ void helperDying();
+#endif
+};
+
+#endif // _KVI_TAL_TOOLTIP_H_
diff --git a/src/kvilib/tal/kvi_tal_vbox.cpp b/src/kvilib/tal/kvi_tal_vbox.cpp
new file mode 100644
index 00000000..5ef67152
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_vbox.cpp
@@ -0,0 +1,33 @@
+//=============================================================================
+//
+// File : kvi_tal_vbox.cpp
+// Creation date : Mon Jan 22 2007 11:25:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+#include "kvi_tal_vbox.h"
+
+#ifdef COMPILE_USE_QT4
+ #include "kvi_tal_vbox_qt4.moc"
+#else
+ #include "kvi_tal_vbox_qt3.moc"
+#endif
+
diff --git a/src/kvilib/tal/kvi_tal_vbox.h b/src/kvilib/tal/kvi_tal_vbox.h
new file mode 100644
index 00000000..a27df527
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_vbox.h
@@ -0,0 +1,36 @@
+#ifndef _KVI_TAL_VBOX_H_
+#define _KVI_TAL_VBOX_H_
+
+//=============================================================================
+//
+// File : kvi_tal_vbox.h
+// Creation date : Mon Jan 22 2007 11:25:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_USE_QT4
+ #include "kvi_tal_vbox_qt4.h"
+#else
+ #include "kvi_tal_vbox_qt3.h"
+#endif
+
+#endif // _KVI_TAL_VBOX_H_
diff --git a/src/kvilib/tal/kvi_tal_vbox_qt3.h b/src/kvilib/tal/kvi_tal_vbox_qt3.h
new file mode 100644
index 00000000..440a2436
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_vbox_qt3.h
@@ -0,0 +1,42 @@
+#ifndef _KVI_TAL_VBOX_QT3_H_
+#define _KVI_TAL_VBOX_QT3_H_
+
+//=============================================================================
+//
+// File : kvi_tal_vbox_qt3.h
+// Creation date : Mon Jan 22 2007 11:25:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#include <qvbox.h>
+
+class KVILIB_API KviTalVBox : public QVBox
+{
+ Q_OBJECT
+public:
+ KviTalVBox(QWidget * pParent)
+ : QVBox(pParent) {};
+ virtual ~KviTalVBox() {};
+};
+
+
+#endif // _KVI_TAL_VBOX_QT3_H_
diff --git a/src/kvilib/tal/kvi_tal_vbox_qt4.h b/src/kvilib/tal/kvi_tal_vbox_qt4.h
new file mode 100644
index 00000000..86de700d
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_vbox_qt4.h
@@ -0,0 +1,42 @@
+#ifndef _KVI_TAL_VBOX_QT4_H_
+#define _KVI_TAL_VBOX_QT4_H_
+
+//=============================================================================
+//
+// File : kvi_tal_vbox_qt4.h
+// Creation date : Mon Jan 22 2007 11:25:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#include <q3vbox.h>
+
+class KVILIB_API KviTalVBox : public Q3VBox
+{
+ Q_OBJECT
+public:
+ KviTalVBox(QWidget * pParent)
+ : Q3VBox(pParent) {};
+ virtual ~KviTalVBox() {};
+};
+
+
+#endif // _KVI_TAL_VBOX_QT4_H_
diff --git a/src/kvilib/tal/kvi_tal_widgetstack.cpp b/src/kvilib/tal/kvi_tal_widgetstack.cpp
new file mode 100644
index 00000000..1a99e3f9
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_widgetstack.cpp
@@ -0,0 +1,33 @@
+//=============================================================================
+//
+// File : kvi_tal_widgetstack.cpp
+// Creation date : Mon Jan 22 2007 11:17:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+#include "kvi_tal_widgetstack.h"
+
+#ifdef COMPILE_USE_QT4
+ #include "kvi_tal_widgetstack_qt4.moc"
+#else
+ #include "kvi_tal_widgetstack_qt3.moc"
+#endif
+
diff --git a/src/kvilib/tal/kvi_tal_widgetstack.h b/src/kvilib/tal/kvi_tal_widgetstack.h
new file mode 100644
index 00000000..7c9133c8
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_widgetstack.h
@@ -0,0 +1,36 @@
+#ifndef _KVI_TAL_WIDGETSTACK_H_
+#define _KVI_TAL_WIDGETSTACK_H_
+
+//=============================================================================
+//
+// File : kvi_tal_widgetstack.h
+// Creation date : Mon Jan 22 2007 11:17:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_USE_QT4
+ #include "kvi_tal_widgetstack_qt4.h"
+#else
+ #include "kvi_tal_widgetstack_qt3.h"
+#endif
+
+#endif // _KVI_TAL_WIDGETSTACK_H_
diff --git a/src/kvilib/tal/kvi_tal_widgetstack_qt3.h b/src/kvilib/tal/kvi_tal_widgetstack_qt3.h
new file mode 100644
index 00000000..cc0eb969
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_widgetstack_qt3.h
@@ -0,0 +1,42 @@
+#ifndef _KVI_TAL_WIDGETSTACK_QT3_H_
+#define _KVI_TAL_WIDGETSTACK_QT3_H_
+
+//=============================================================================
+//
+// File : kvi_tal_widgetstack_qt3.h
+// Creation date : Mon Jan 22 2007 11:17:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#include <qwidgetstack.h>
+
+
+class KVILIB_API KviTalWidgetStack : public QWidgetStack
+{
+ Q_OBJECT
+public:
+ KviTalWidgetStack(QWidget * pParent)
+ : QWidgetStack(pParent) {};
+ virtual ~KviTalWidgetStack() {};
+};
+
+#endif // _KVI_TAL_WIDGETSTACK_QT3_H_
diff --git a/src/kvilib/tal/kvi_tal_widgetstack_qt4.h b/src/kvilib/tal/kvi_tal_widgetstack_qt4.h
new file mode 100644
index 00000000..6d0cc53f
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_widgetstack_qt4.h
@@ -0,0 +1,42 @@
+#ifndef _KVI_TAL_WIDGETSTACK_QT4_H_
+#define _KVI_TAL_WIDGETSTACK_QT4_H_
+
+//=============================================================================
+//
+// File : kvi_tal_widgetstack_qt4.h
+// Creation date : Mon Jan 22 2007 11:17:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+//#include <qstackedwidget.h>
+#include <q3widgetstack.h>
+
+class KVILIB_API KviTalWidgetStack : public Q3WidgetStack
+{
+ Q_OBJECT
+public:
+ KviTalWidgetStack(QWidget * pParent)
+ : Q3WidgetStack(pParent) {};
+ virtual ~KviTalWidgetStack() {};
+};
+
+#endif // _KVI_TAL_WIDGETSTACK_QT4_H_
diff --git a/src/kvilib/tal/kvi_tal_windowstate.h b/src/kvilib/tal/kvi_tal_windowstate.h
new file mode 100644
index 00000000..9510ba4a
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_windowstate.h
@@ -0,0 +1,42 @@
+#ifndef _KVI_TAL_WINDOWSTATE_H_
+#define _KVI_TAL_WINDOWSTATE_H_
+
+//=============================================================================
+//
+// File : kvi_tal_windowstate.h
+// Creation date : Mon Jan 22 2007 11:25:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_USE_QT4
+ #define QT_WINDOWSTATE_FLAGS Qt::WindowState
+
+ #define QT_WINDOWSTATE_MAXIMIZED Qt::WindowMaximized
+ #define QT_WINDOWSTATE_MINIMIZED Qt::WindowMinimized
+#else
+ #define QT_WINDOWSTATE_FLAGS Qt::WidgetState
+
+ #define QT_WINDOWSTATE_MAXIMIZED Qt::WState_Maximized
+ #define QT_WINDOWSTATE_MINIMIZED Qt::WState_Minimized
+#endif
+
+#endif // _KVI_TAL_WINDOWSTATE_H_
diff --git a/src/kvilib/tal/kvi_tal_wizard.cpp b/src/kvilib/tal/kvi_tal_wizard.cpp
new file mode 100644
index 00000000..6f5f39da
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_wizard.cpp
@@ -0,0 +1,584 @@
+//=============================================================================
+//
+// File : kvi_tal_wizard.cpp
+// Creation date : Tue Feb 06 2007 14:35:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVILIB__
+#include "kvi_tal_wizard.h"
+#include "kvi_tal_hbox.h"
+#include "kvi_pointerlist.h"
+#include "kvi_locale.h"
+
+#ifdef COMPILE_USE_QT4
+ #include <QShowEvent>
+ #include <QLabel>
+ #include <QPushButton>
+ #include <QGridLayout>
+ #include <QFrame>
+ #include <QStackedWidget>
+ #include <QPalette>
+#else
+ #include <qlabel.h>
+ #include <qpushbutton.h>
+ #include <qlayout.h>
+ #include <qevent.h>
+ #include <qframe.h>
+ #include <qwidgetstack.h>
+ #include <qpalette.h>
+#endif
+
+
+class KviTalWizardPageData
+{
+public:
+ enum EnableFlags
+ {
+ EnableNext = 1,
+ EnableBack = 2,
+ EnableHelp = 4,
+ EnableCancel = 8,
+ EnableFinish = 16
+ };
+public:
+ QWidget * pWidget;
+ QString szTitle;
+ bool bEnabled;
+ int iEnableFlags;
+ int iVisibleIndex;
+};
+
+class KviTalWizardPrivate
+{
+public:
+ KviPointerList<KviTalWizardPageData> * pPageList;
+ int iEnabledPageCount;
+ KviTalWizardPageData * pCurrentPage;
+ QGridLayout * pLayout;
+ QLabel * pTitleLabel;
+ QLabel * pStepsLabel;
+ QPushButton * pBackButton;
+ QPushButton * pCancelButton;
+ QPushButton * pHelpButton;
+ QPushButton * pNextButton;
+ QWidget * pNextSpacer;
+ QPushButton * pFinishButton;
+ QWidget * pFinishSpacer;
+#ifdef COMPILE_USE_QT4
+ QStackedWidget * pWidgetStack;
+#else
+ QWidgetStack * pWidgetStack;
+#endif
+public:
+ KviTalWizardPageData * findPage(QWidget * pWidget)
+ {
+ for(KviTalWizardPageData * pData = pPageList->first();pData;pData = pPageList->next())
+ {
+ if(pData->pWidget == pWidget)
+ return pData;
+ }
+ return NULL;
+ }
+
+ KviTalWizardPageData * findFirstEnabledPage()
+ {
+ KviTalWizardPageData * pData;
+ for(pData = pPageList->first();pData;pData = pPageList->next())
+ {
+ if(pData->bEnabled)
+ return pData;
+ }
+ return NULL;
+ }
+
+ KviTalWizardPageData * findLastEnabledPage()
+ {
+ KviTalWizardPageData * pData;
+ for(pData = pPageList->last();pData;pData = pPageList->prev())
+ {
+ if(pData->bEnabled)
+ return pData;
+ }
+ return NULL;
+ }
+
+ KviTalWizardPageData * findNextEnabledPage(QWidget * pReference)
+ {
+ if(!pReference)
+ return findFirstEnabledPage();
+ KviTalWizardPageData * pData = findPage(pReference);
+ if(!pData)
+ return NULL;
+ for(pData = pPageList->next();pData;pData = pPageList->next())
+ {
+ if(pData->bEnabled)
+ return pData;
+ }
+ return NULL;
+ }
+
+ KviTalWizardPageData * findPrevEnabledPage(QWidget * pReference)
+ {
+ if(!pReference)
+ return findLastEnabledPage();
+ KviTalWizardPageData * pData = findPage(pReference);
+ if(!pData)
+ return NULL;
+ for(pData = pPageList->prev();pData;pData = pPageList->prev())
+ {
+ if(pData->bEnabled)
+ return pData;
+ }
+ return NULL;
+ }
+
+ int reindexPages()
+ {
+ int iEnabledCount = 0;
+ for(KviTalWizardPageData * pData = pPageList->next();pData;pData = pPageList->next())
+ {
+ if(pData->bEnabled)
+ {
+ iEnabledCount++;
+ pData->iVisibleIndex = iEnabledCount;
+ }
+ }
+ return iEnabledCount;
+ }
+};
+
+
+KviTalWizard::KviTalWizard(QWidget * pParent)
+: QDialog(pParent)
+{
+ m_p = new KviTalWizardPrivate;
+ m_p->pPageList = new KviPointerList<KviTalWizardPageData>;
+ m_p->pPageList->setAutoDelete(true);
+ m_p->pCurrentPage = NULL;
+ m_p->iEnabledPageCount = 0;
+ m_p->pLayout = new QGridLayout(this);
+
+ m_p->pTitleLabel = new QLabel(this);
+#ifdef COMPILE_USE_QT4
+ m_p->pLayout->addWidget(m_p->pTitleLabel,0,0,1,3);
+#else
+ m_p->pLayout->addMultiCellWidget(m_p->pTitleLabel,0,0,0,3);
+#endif
+ m_p->pStepsLabel = new QLabel(this);
+ m_p->pStepsLabel->setMinimumWidth(80);
+ m_p->pStepsLabel->setAlignment(Qt::AlignRight);
+#ifdef COMPILE_USE_QT4
+ m_p->pLayout->addWidget(m_p->pStepsLabel,0,4,1,3);
+#else
+ m_p->pLayout->addMultiCellWidget(m_p->pStepsLabel,0,0,4,6);
+#endif
+
+ QFrame * f1 = new QFrame(this);
+ f1->setFrameStyle(QFrame::Sunken | QFrame::HLine);
+#ifdef COMPILE_USE_QT4
+ m_p->pLayout->addWidget(f1,1,0,1,7);
+#else
+ m_p->pLayout->addMultiCellWidget(f1,1,1,0,6);
+#endif
+
+#ifdef COMPILE_USE_QT4
+ m_p->pWidgetStack = new QStackedWidget(this);
+ m_p->pLayout->addWidget(m_p->pWidgetStack,2,0,1,7);
+#else
+ m_p->pWidgetStack = new QWidgetStack(this);
+ m_p->pLayout->addMultiCellWidget(m_p->pWidgetStack,2,2,0,6);
+#endif
+
+ QFrame * f2 = new QFrame(this);
+ f2->setFrameStyle(QFrame::Sunken | QFrame::HLine);
+#ifdef COMPILE_USE_QT4
+ m_p->pLayout->addWidget(f2,3,0,1,7);
+#else
+ m_p->pLayout->addMultiCellWidget(f2,3,3,0,6);
+#endif
+
+ KviTalHBox * pButtonBox = new KviTalHBox(this);
+#ifdef COMPILE_USE_QT4
+ m_p->pLayout->addWidget(pButtonBox,4,0,1,7);
+#else
+ m_p->pLayout->addMultiCellWidget(pButtonBox,4,4,0,6);
+#endif
+
+ pButtonBox->setMargin(0);
+ pButtonBox->setSpacing(0);
+
+
+ m_p->pCancelButton = new QPushButton(__tr("Cancel"),pButtonBox);
+ m_p->pCancelButton->setMinimumWidth(80);
+ QObject::connect(
+ m_p->pCancelButton,
+ SIGNAL(clicked()),
+ this,
+ SLOT(cancelButtonClicked())
+ );
+
+ QWidget * pSpacer = new QWidget(pButtonBox);
+ pSpacer->setFixedWidth(4);
+
+ m_p->pHelpButton = new QPushButton(__tr("Help"),pButtonBox);
+ m_p->pHelpButton->setMinimumWidth(80);
+ QObject::connect(
+ m_p->pHelpButton,
+ SIGNAL(clicked()),
+ this,
+ SLOT(helpButtonClicked())
+ );
+
+ QWidget * pLargeSpacer = new QWidget(pButtonBox);
+ pLargeSpacer->setMinimumWidth(50);
+ pButtonBox->setStretchFactor(pLargeSpacer,100);
+
+ QString szText = "< ";
+ szText += __tr("Back");
+ m_p->pBackButton = new QPushButton(szText,pButtonBox);
+ m_p->pBackButton->setMinimumWidth(80);
+ QObject::connect(
+ m_p->pBackButton,
+ SIGNAL(clicked()),
+ this,
+ SLOT(backButtonClicked())
+ );
+
+ m_p->pNextSpacer = new QWidget(pButtonBox);
+ m_p->pNextSpacer->setFixedWidth(4);
+
+ szText = __tr("Next");
+ szText += " >";
+ m_p->pNextButton = new QPushButton(szText,pButtonBox);
+ m_p->pNextButton->setMinimumWidth(80);
+ QObject::connect(
+ m_p->pNextButton,
+ SIGNAL(clicked()),
+ this,
+ SLOT(nextButtonClicked())
+ );
+
+ m_p->pFinishSpacer = new QWidget(pButtonBox);
+ m_p->pFinishSpacer->setFixedWidth(4);
+
+ m_p->pFinishButton = new QPushButton(__tr("Finish"),pButtonBox);
+ m_p->pFinishButton->setMinimumWidth(80);
+ QObject::connect(
+ m_p->pFinishButton,
+ SIGNAL(clicked()),
+ this,
+ SLOT(finishButtonClicked())
+ );
+
+ m_p->pLayout->setMargin(8);
+ m_p->pLayout->setSpacing(4);
+ m_p->pLayout->setRowStretch(2,1);
+ m_p->pLayout->setColStretch(0,1);
+}
+
+KviTalWizard::~KviTalWizard()
+{
+ delete m_p->pPageList;
+ delete m_p;
+}
+
+void KviTalWizard::insertPage(QWidget * pWidget,const QString &szTitle,int iIndex)
+{
+ KviTalWizardPageData * pPageData = m_p->findPage(pWidget);
+ if(!pPageData)
+ {
+ pPageData = new KviTalWizardPageData;
+ pPageData->pWidget = pWidget;
+ pPageData->iEnableFlags = \
+ KviTalWizardPageData::EnableNext | \
+ KviTalWizardPageData::EnableCancel | \
+ KviTalWizardPageData::EnableBack;
+ if(iIndex < 0)
+ {
+ m_p->pPageList->append(pPageData);
+ m_p->iEnabledPageCount++;
+ pPageData->iVisibleIndex = m_p->iEnabledPageCount;
+ } else {
+ m_p->pPageList->insert(iIndex,pPageData);
+ m_p->iEnabledPageCount = m_p->reindexPages();
+ }
+ m_p->pWidgetStack->addWidget(pWidget);
+ }
+ pPageData->szTitle = szTitle;
+ pPageData->bEnabled = true;
+
+}
+
+void KviTalWizard::addPage(QWidget * pWidget,const QString &szTitle)
+{
+ insertPage(pWidget,szTitle,-1);
+}
+
+bool KviTalWizard::setPageEnabled(QWidget * pWidget,bool bEnabled)
+{
+ KviTalWizardPageData * pData = m_p->findPage(pWidget);
+ if(!pData)
+ return false;
+ pData->bEnabled = bEnabled;
+ m_p->iEnabledPageCount = m_p->reindexPages();
+ setCurrentPage(m_p->pCurrentPage);
+ return true;
+}
+
+bool KviTalWizard::setPageTitle(QWidget * pWidget,const QString &szTitle)
+{
+ KviTalWizardPageData * pData = m_p->findPage(pWidget);
+ if(!pData)
+ return false;
+ pData->szTitle = szTitle;
+ return true;
+}
+
+bool KviTalWizard::setCurrentPage(QWidget * pWidget)
+{
+ KviTalWizardPageData * pData = m_p->findPage(pWidget);
+ if(!pData)
+ return false;
+ setCurrentPage(pData);
+ return true;
+}
+
+QWidget * KviTalWizard::currentPage()
+{
+ if(!m_p->pCurrentPage)
+ return NULL;
+ return m_p->pCurrentPage->pWidget;
+}
+
+void KviTalWizard::setCurrentPage(KviTalWizardPageData * pData)
+{
+ m_p->pCurrentPage = pData;
+
+ bool bCancelEnabled = true;
+ bool bNextEnabled = false;
+ bool bBackEnabled = false;
+ bool bHelpEnabled = false;
+ bool bFinishEnabled = false;
+
+ QString szTitle;
+ QString szSteps;
+
+ if(pData)
+ {
+ bNextEnabled = (pData->iEnableFlags & KviTalWizardPageData::EnableNext) && m_p->findNextEnabledPage(pData->pWidget);
+ bBackEnabled = (pData->iEnableFlags & KviTalWizardPageData::EnableBack) && m_p->findPrevEnabledPage(pData->pWidget);
+ bCancelEnabled = (pData->iEnableFlags & KviTalWizardPageData::EnableCancel);
+ bFinishEnabled = (pData->iEnableFlags & KviTalWizardPageData::EnableFinish);
+ bHelpEnabled = (pData->iEnableFlags & KviTalWizardPageData::EnableHelp);
+#ifdef COMPILE_USE_QT4
+ m_p->pWidgetStack->setCurrentWidget(pData->pWidget);
+#else
+ m_p->pWidgetStack->raiseWidget(pData->pWidget);
+#endif
+ szTitle = "<b>";
+ szTitle += pData->szTitle;
+ szTitle += "</b>";
+ QPalette pal = m_p->pStepsLabel->palette();
+#ifdef COMPILE_USE_QT4
+ QColor clrWin = pal.color(QPalette::Normal,QPalette::Window);
+ QColor clrTxt = pal.color(QPalette::Normal,QPalette::WindowText);
+#else
+ QColor clrWin = pal.color(QPalette::Normal,QColorGroup::Foreground);
+ QColor clrTxt = pal.color(QPalette::Normal,QColorGroup::Background);
+#endif
+ QColor clrMid = qRgb(
+ (clrWin.red() + clrTxt.red()) / 2,
+ (clrWin.green() + clrTxt.green()) / 2,
+ (clrWin.blue() + clrTxt.blue()) / 2
+ );
+
+ szSteps = "<nobr><font color=\"";
+ szSteps += clrMid.name();
+ szSteps += "\"><b>[";
+ szSteps += QString("Step %1 of %2").arg(pData->iVisibleIndex).arg(m_p->iEnabledPageCount);
+ szSteps += "]</b></font></nobr>";
+ }
+
+ m_p->pTitleLabel->setText(szTitle);
+ m_p->pStepsLabel->setText(szSteps);
+
+ m_p->pNextButton->setEnabled(bNextEnabled);
+ if(bNextEnabled)
+ {
+ m_p->pNextButton->show();
+ m_p->pNextSpacer->show();
+ } else {
+ m_p->pNextButton->hide();
+ m_p->pNextSpacer->hide();
+ }
+ m_p->pBackButton->setEnabled(bBackEnabled);
+ m_p->pHelpButton->setEnabled(bHelpEnabled);
+ if(bHelpEnabled)
+ m_p->pHelpButton->show();
+ else
+ m_p->pHelpButton->hide();
+ m_p->pCancelButton->setEnabled(bCancelEnabled);
+ m_p->pFinishButton->setEnabled(bFinishEnabled);
+ if(bFinishEnabled)
+ {
+ m_p->pFinishButton->show();
+ m_p->pFinishSpacer->show();
+ } else {
+ m_p->pFinishButton->hide();
+ m_p->pFinishSpacer->hide();
+ }
+}
+
+void KviTalWizard::showEvent(QShowEvent * e)
+{
+ if(!(m_p->pCurrentPage))
+ {
+ // display the first page
+ KviTalWizardPageData * pData = m_p->findFirstEnabledPage();
+ if(pData)
+ setCurrentPage(pData->pWidget);
+ }
+ QDialog::showEvent(e);
+}
+
+void KviTalWizard::closeEvent(QCloseEvent * e)
+{
+ e->ignore();
+ cancelButtonClicked();
+}
+
+void KviTalWizard::backButtonClicked()
+{
+ if(!m_p->pCurrentPage)
+ return;
+ setCurrentPage(m_p->findPrevEnabledPage(m_p->pCurrentPage->pWidget));
+}
+
+void KviTalWizard::nextButtonClicked()
+{
+ setCurrentPage(m_p->findNextEnabledPage(m_p->pCurrentPage->pWidget));
+}
+
+void KviTalWizard::helpButtonClicked()
+{
+ emit helpClicked();
+}
+
+void KviTalWizard::cancelButtonClicked()
+{
+ reject();
+}
+
+void KviTalWizard::finishButtonClicked()
+{
+ accept();
+}
+
+void KviTalWizard::setHelpEnabled(QWidget * pWidget,bool bEnabled)
+{
+ KviTalWizardPageData * pData = m_p->findPage(pWidget);
+ if(!pData)
+ return;
+ if(bEnabled)
+ pData->iEnableFlags |= KviTalWizardPageData::EnableHelp;
+ else
+ pData->iEnableFlags &= ~KviTalWizardPageData::EnableHelp;
+ if(pData == m_p->pCurrentPage)
+ setCurrentPage(pData);
+}
+
+void KviTalWizard::setCancelEnabled(QWidget * pWidget,bool bEnabled)
+{
+ KviTalWizardPageData * pData = m_p->findPage(pWidget);
+ if(!pData)
+ return;
+ if(bEnabled)
+ pData->iEnableFlags |= KviTalWizardPageData::EnableCancel;
+ else
+ pData->iEnableFlags &= ~KviTalWizardPageData::EnableCancel;
+ if(pData == m_p->pCurrentPage)
+ setCurrentPage(pData);
+}
+
+void KviTalWizard::setFinishEnabled(QWidget * pWidget,bool bEnabled)
+{
+ KviTalWizardPageData * pData = m_p->findPage(pWidget);
+ if(!pData)
+ return;
+ if(bEnabled)
+ pData->iEnableFlags |= KviTalWizardPageData::EnableFinish;
+ else
+ pData->iEnableFlags &= ~KviTalWizardPageData::EnableFinish;
+ if(pData == m_p->pCurrentPage)
+ setCurrentPage(pData);
+}
+
+void KviTalWizard::setNextEnabled(QWidget * pWidget,bool bEnabled)
+{
+ KviTalWizardPageData * pData = m_p->findPage(pWidget);
+ if(!pData)
+ return;
+ if(bEnabled)
+ pData->iEnableFlags |= KviTalWizardPageData::EnableNext;
+ else
+ pData->iEnableFlags &= ~KviTalWizardPageData::EnableNext;
+ if(pData == m_p->pCurrentPage)
+ setCurrentPage(pData);
+}
+
+void KviTalWizard::setBackEnabled(QWidget * pWidget,bool bEnabled)
+{
+ KviTalWizardPageData * pData = m_p->findPage(pWidget);
+ if(!pData)
+ return;
+ if(bEnabled)
+ pData->iEnableFlags |= KviTalWizardPageData::EnableBack;
+ else
+ pData->iEnableFlags &= ~KviTalWizardPageData::EnableBack;
+ if(pData == m_p->pCurrentPage)
+ setCurrentPage(pData);
+}
+
+QPushButton * KviTalWizard::cancelButton()
+{
+ return m_p->pCancelButton;
+}
+
+QPushButton * KviTalWizard::helpButton()
+{
+ return m_p->pHelpButton;
+}
+
+QPushButton * KviTalWizard::finishButton()
+{
+ return m_p->pFinishButton;
+}
+
+QPushButton * KviTalWizard::nextButton()
+{
+ return m_p->pNextButton;
+}
+
+QPushButton * KviTalWizard::backButton()
+{
+ return m_p->pBackButton;
+}
+
diff --git a/src/kvilib/tal/kvi_tal_wizard.h b/src/kvilib/tal/kvi_tal_wizard.h
new file mode 100644
index 00000000..f84e3555
--- /dev/null
+++ b/src/kvilib/tal/kvi_tal_wizard.h
@@ -0,0 +1,169 @@
+#ifndef _KVI_TAL_WIZARD_H_
+#define _KVI_TAL_WIZARD_H_
+
+//=============================================================================
+//
+// File : kvi_tal_wizard.h
+// Creation date : Tue Feb 06 2007 14:35:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_USE_QT4
+ #include <QDialog>
+#else
+ #include <qdialog.h>
+#endif
+
+class QShowEvent;
+class QPushButton;
+class KviTalWizardPrivate;
+class KviTalWizardPageData;
+
+///
+/// \class KviTalWizard
+///
+/// \brief Provides a wizard-style dialog with steps
+///
+class KVILIB_API KviTalWizard : public QDialog
+{
+ Q_OBJECT
+public:
+ KviTalWizard(QWidget * pParent);
+ ~KviTalWizard();
+protected:
+ KviTalWizardPrivate * m_p;
+public:
+ ///
+ /// Adds a page to the wizard with the specified title.
+ /// The pages are displayed in order they're added.
+ /// Adding a page a second time is equivalent to calling
+ /// setPageTitle() and enabling the page.
+ ///
+ void addPage(QWidget * pWidget,const QString &szTitle);
+ ///
+ /// Adds a page to the wizard with the specified title
+ /// and in the specified position.
+ /// Adding a page a second time is equivalent to calling
+ /// setPageTitle() and enabling the page.
+ ///
+ void insertPage(QWidget * pWidget,const QString &szTitle,int iIndex);
+ ///
+ /// Enables or disables a page. A disabled page
+ /// is skipped when the user presses "Next" in the
+ /// previous page or "Back" in the page after.
+ /// Disabling the current page has no effect.
+ ///
+ /// Returns true on success or false if the pWidget
+ /// does not identify a page that has been added to this wizard.
+ ///
+ bool setPageEnabled(QWidget * pWidget,bool bEnabled);
+ ///
+ /// Changes a page title.
+ ///
+ /// Returns true on success or false if the pWidget
+ /// does not identify a page that has been added to this wizard.
+ ///
+ bool setPageTitle(QWidget * pWidget,const QString &szTitle);
+ ///
+ /// Switches the wizard to the specified page.
+ /// Please note that this class handles page switching
+ /// automatically so you usually don't need to call this function.
+ ///
+ /// Returns true on success or false if the pWidget
+ /// does not identify a page that has been added to this wizard.
+ ///
+ bool setCurrentPage(QWidget * pWidget);
+ ///
+ /// Returns a pointer to the current page
+ ///
+ QWidget * currentPage();
+ ///
+ /// Enables or disables the help button for the specified page.
+ /// By default the help button is always disabled.
+ ///
+ void setHelpEnabled(QWidget * pWidget,bool bEnabled);
+ ///
+ /// Enables or disables the cancel button for the specified page.
+ /// By default the cancel button is always enabled.
+ ///
+ void setCancelEnabled(QWidget * pWidget,bool bEnabled);
+ ///
+ /// Enables or disables the finish button for the specified page.
+ /// By default the finish button is always disabled.
+ ///
+ void setFinishEnabled(QWidget * pWidget,bool bEnabled);
+ ///
+ /// Enables or disables the next button for the specified page.
+ /// By default the next button is always enabled.
+ ///
+ void setNextEnabled(QWidget * pWidget,bool bEnabled);
+ ///
+ /// Enables or disables the prev button for the specified page.
+ /// By default the prev button is always enabled.
+ ///
+ void setBackEnabled(QWidget * pWidget,bool bEnabled);
+ ///
+ /// Returns a pointer to the cancel button displayed in the dialog.
+ ///
+ QPushButton * cancelButton();
+ ///
+ /// Returns a pointer to the help button displayed in the dialog.
+ ///
+ QPushButton * helpButton();
+ ///
+ /// Returns a pointer to the finish button displayed in the dialog.
+ ///
+ QPushButton * finishButton();
+ ///
+ /// Returns a pointer to the next button displayed in the dialog.
+ ///
+ QPushButton * nextButton();
+ ///
+ /// Returns a pointer to the back button displayed in the dialog.
+ ///
+ QPushButton * backButton();
+signals:
+ ///
+ /// Emitted when the help button is clicked.
+ ///
+ void helpClicked();
+protected:
+ ///
+ /// Displays the first page if no other page is shown yet.
+ ///
+ virtual void showEvent(QShowEvent * e);
+ ///
+ /// Handles redirects the close button to the "cancel" operation.
+ ///
+ virtual void closeEvent(QCloseEvent * e);
+protected:
+ void setCurrentPage(KviTalWizardPageData * pData);
+protected slots:
+ void backButtonClicked();
+ void nextButtonClicked();
+ void helpButtonClicked();
+ void cancelButtonClicked();
+ void finishButtonClicked();
+};
+
+
+#endif // _KVI_TAL_WIZARD_H_
diff --git a/src/kvilib/tal/moc_kvi_tal_wizard.cpp b/src/kvilib/tal/moc_kvi_tal_wizard.cpp
new file mode 100644
index 00000000..0ad29754
--- /dev/null
+++ b/src/kvilib/tal/moc_kvi_tal_wizard.cpp
@@ -0,0 +1,128 @@
+/****************************************************************************
+** KviTalWizard meta object code from reading C++ file 'kvi_tal_wizard.h'
+**
+** Created: Sun Mar 23 20:56:27 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_tal_wizard.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviTalWizard::className() const
+{
+ return "KviTalWizard";
+}
+
+QMetaObject *KviTalWizard::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviTalWizard( "KviTalWizard", &KviTalWizard::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviTalWizard::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviTalWizard", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviTalWizard::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviTalWizard", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviTalWizard::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = QDialog::staticMetaObject();
+ static const QUMethod slot_0 = {"backButtonClicked", 0, 0 };
+ static const QUMethod slot_1 = {"nextButtonClicked", 0, 0 };
+ static const QUMethod slot_2 = {"helpButtonClicked", 0, 0 };
+ static const QUMethod slot_3 = {"cancelButtonClicked", 0, 0 };
+ static const QUMethod slot_4 = {"finishButtonClicked", 0, 0 };
+ static const QMetaData slot_tbl[] = {
+ { "backButtonClicked()", &slot_0, QMetaData::Protected },
+ { "nextButtonClicked()", &slot_1, QMetaData::Protected },
+ { "helpButtonClicked()", &slot_2, QMetaData::Protected },
+ { "cancelButtonClicked()", &slot_3, QMetaData::Protected },
+ { "finishButtonClicked()", &slot_4, QMetaData::Protected }
+ };
+ static const QUMethod signal_0 = {"helpClicked", 0, 0 };
+ static const QMetaData signal_tbl[] = {
+ { "helpClicked()", &signal_0, QMetaData::Public }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviTalWizard", parentObject,
+ slot_tbl, 5,
+ signal_tbl, 1,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviTalWizard.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviTalWizard::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviTalWizard" ) )
+ return this;
+ return QDialog::qt_cast( clname );
+}
+
+// SIGNAL helpClicked
+void KviTalWizard::helpClicked()
+{
+ activate_signal( staticMetaObject()->signalOffset() + 0 );
+}
+
+bool KviTalWizard::qt_invoke( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->slotOffset() ) {
+ case 0: backButtonClicked(); break;
+ case 1: nextButtonClicked(); break;
+ case 2: helpButtonClicked(); break;
+ case 3: cancelButtonClicked(); break;
+ case 4: finishButtonClicked(); break;
+ default:
+ return QDialog::qt_invoke( _id, _o );
+ }
+ return TRUE;
+}
+
+bool KviTalWizard::qt_emit( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->signalOffset() ) {
+ case 0: helpClicked(); break;
+ default:
+ return QDialog::qt_emit(_id,_o);
+ }
+ return TRUE;
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviTalWizard::qt_property( int id, int f, QVariant* v)
+{
+ return QDialog::qt_property( id, f, v);
+}
+
+bool KviTalWizard::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvirc/Makefile.am b/src/kvirc/Makefile.am
new file mode 100644
index 00000000..e65e65cf
--- /dev/null
+++ b/src/kvirc/Makefile.am
@@ -0,0 +1,5 @@
+###############################################################################
+# KVirc IRC client Makefile - 16.12.98 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+SUBDIRS = build include kernel kvs module sparser ui
diff --git a/src/kvirc/build/Makefile.am b/src/kvirc/build/Makefile.am
new file mode 100644
index 00000000..44db487e
--- /dev/null
+++ b/src/kvirc/build/Makefile.am
@@ -0,0 +1,537 @@
+########################################################################################################################
+#
+# KVIrc executable Makefile
+# Szymon Stefanek 21.09.2001
+#
+########################################################################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+kvirc_LDFLAGS = -export-dynamic $(SS_LDFLAGS) $(SS_LIBDIRS) $(SS_RPATH)
+kvirc_LDADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+bin_PROGRAMS = kvirc
+
+#
+# Command useful to find out all the sources
+# SRC=`find ../ -name *.cpp | sort`
+# echo $SRC
+#
+
+nodist_kvirc_SOURCES = ../kernel/moc_kvi_action.cpp \
+../kernel/moc_kvi_actionmanager.cpp \
+../kernel/moc_kvi_coreactions.cpp \
+../kernel/moc_kvi_filetransfer.cpp \
+../kernel/moc_kvi_ircconnection.cpp \
+../kernel/moc_kvi_irccontext.cpp \
+../kernel/moc_kvi_irclink.cpp \
+../kernel/moc_kvi_ircsocket.cpp \
+../kernel/moc_kvi_ircconnectiontargetresolver.cpp \
+../kvs/moc_kvi_kvs_action.cpp \
+../kvs/moc_kvi_kvs_asyncdnsoperation.cpp \
+../kvs/moc_kvi_kvs_asyncoperation.cpp \
+../kvs/moc_kvi_kvs_dnsmanager.cpp \
+../kvs/moc_kvi_kvs_timermanager.cpp \
+../kvs/moc_kvi_kvs_object.cpp \
+../kvs/moc_kvi_kvs_popupmenu.cpp \
+../kvs/moc_kvi_kvs_processmanager.cpp \
+../kvs/moc_kvi_kvs_useraction.cpp \
+../module/moc_kvi_mexlinkfilter.cpp \
+../module/moc_kvi_mexserverimport.cpp \
+../module/moc_kvi_mextoolbar.cpp \
+../module/moc_kvi_modulemanager.cpp \
+../ui/moc_kvi_actiondrawer.cpp \
+../ui/moc_kvi_customtoolbar.cpp \
+../ui/moc_kvi_debugwindow.cpp \
+../ui/moc_kvi_htmldialog.cpp \
+../ui/moc_kvi_imagedialog.cpp \
+../ui/moc_kvi_ircviewtools.cpp \
+../ui/moc_kvi_mdicaption.cpp \
+../ui/moc_kvi_mdichild.cpp \
+../ui/moc_kvi_mdimanager.cpp \
+../ui/moc_kvi_statusbar.cpp \
+../ui/moc_kvi_statusbarapplet.cpp \
+../ui/moc_kvi_toolwindows_container.cpp \
+../ui/moc_kvi_listview.cpp
+
+kvirc_SOURCES = ../kernel/kvi_action.cpp \
+../kernel/kvi_actionmanager.cpp \
+../kernel/kvi_app.cpp \
+../kernel/kvi_coreactions.cpp \
+../kernel/kvi_filetransfer.cpp \
+../kernel/kvi_app_fs.cpp \
+../kernel/kvi_app_setup.cpp \
+../kernel/kvi_asynchronousconnectiondata.cpp \
+../kernel/kvi_customtoolbardescriptor.cpp \
+../kernel/kvi_customtoolbarmanager.cpp \
+../kernel/kvi_iconmanager.cpp \
+../kernel/kvi_internalcmd.cpp \
+../kernel/kvi_ipc.cpp \
+../kernel/kvi_ircdatastreammonitor.cpp \
+../kernel/kvi_ircconnection.cpp \
+../kernel/kvi_ircconnectionantictcpflooddata.cpp \
+../kernel/kvi_ircconnectionasyncwhoisdata.cpp \
+../kernel/kvi_ircconnectionnetsplitdetectordata.cpp \
+../kernel/kvi_ircconnectiontarget.cpp \
+../kernel/kvi_ircconnectiontargetresolver.cpp \
+../kernel/kvi_ircconnectionserverinfo.cpp \
+../kernel/kvi_ircconnectionstatedata.cpp \
+../kernel/kvi_ircconnectionstatistics.cpp \
+../kernel/kvi_ircconnectionuserinfo.cpp \
+../kernel/kvi_irccontext.cpp \
+../kernel/kvi_irclink.cpp \
+../kernel/kvi_ircsocket.cpp \
+../kernel/kvi_ircurl.cpp \
+../kernel/kvi_main.cpp \
+../kernel/kvi_lagmeter.cpp \
+../kernel/kvi_notifylist.cpp \
+../kernel/kvi_options.cpp \
+../kernel/kvi_sslmaster.cpp \
+../kernel/kvi_texticonmanager.cpp \
+../kernel/kvi_theme.cpp \
+../kernel/kvi_useraction.cpp \
+../kernel/kvi_userinput.cpp \
+../kvs/kvi_kvs.cpp \
+../kvs/kvi_kvs_action.cpp \
+../kvs/kvi_kvs_aliasmanager.cpp \
+../kvs/kvi_kvs_array.cpp \
+../kvs/kvi_kvs_arraycast.cpp \
+../kvs/kvi_kvs_asyncdnsoperation.cpp \
+../kvs/kvi_kvs_asyncoperation.cpp \
+../kvs/kvi_kvs_callbackobject.cpp \
+../kvs/kvi_kvs_corecallbackcommands.cpp \
+../kvs/kvi_kvs_corefunctions.cpp \
+../kvs/kvi_kvs_corefunctions_af.cpp \
+../kvs/kvi_kvs_corefunctions_gl.cpp \
+../kvs/kvi_kvs_corefunctions_mr.cpp \
+../kvs/kvi_kvs_corefunctions_sz.cpp \
+../kvs/kvi_kvs_coresimplecommands.cpp \
+../kvs/kvi_kvs_coresimplecommands_af.cpp \
+../kvs/kvi_kvs_coresimplecommands_gl.cpp \
+../kvs/kvi_kvs_coresimplecommands_mr.cpp \
+../kvs/kvi_kvs_coresimplecommands_sz.cpp \
+../kvs/kvi_kvs_dnsmanager.cpp \
+../kvs/kvi_kvs_event.cpp \
+../kvs/kvi_kvs_eventhandler.cpp \
+../kvs/kvi_kvs_eventmanager.cpp \
+../kvs/kvi_kvs_eventtable.cpp \
+../kvs/kvi_kvs_hash.cpp \
+../kvs/kvi_kvs_kernel.cpp \
+../kvs/kvi_kvs_moduleinterface.cpp \
+../kvs/kvi_kvs_object.cpp \
+../kvs/kvi_kvs_object_class.cpp \
+../kvs/kvi_kvs_object_controller.cpp \
+../kvs/kvi_kvs_object_functioncall.cpp \
+../kvs/kvi_kvs_object_functionhandler.cpp \
+../kvs/kvi_kvs_object_functionhandlerimpl.cpp \
+../kvs/kvi_kvs_parameterprocessor.cpp \
+../kvs/kvi_kvs_parser.cpp \
+../kvs/kvi_kvs_parser_command.cpp \
+../kvs/kvi_kvs_parser_comment.cpp \
+../kvs/kvi_kvs_parser_dollar.cpp \
+../kvs/kvi_kvs_parser_expression.cpp \
+../kvs/kvi_kvs_parser_lside.cpp \
+../kvs/kvi_kvs_parser_specialcommands.cpp \
+../kvs/kvi_kvs_popupmanager.cpp \
+../kvs/kvi_kvs_popupmenu.cpp \
+../kvs/kvi_kvs_processmanager.cpp \
+../kvs/kvi_kvs_report.cpp \
+../kvs/kvi_kvs_runtimecall.cpp \
+../kvs/kvi_kvs_runtimecontext.cpp \
+../kvs/kvi_kvs_rwevaluationresult.cpp \
+../kvs/kvi_kvs_script.cpp \
+../kvs/kvi_kvs_scriptaddonmanager.cpp \
+../kvs/kvi_kvs_switchlist.cpp \
+../kvs/kvi_kvs_timermanager.cpp \
+../kvs/kvi_kvs_treenode_aliasfunctioncall.cpp \
+../kvs/kvi_kvs_treenode_aliassimplecommand.cpp \
+../kvs/kvi_kvs_treenode_arraycount.cpp \
+../kvs/kvi_kvs_treenode_arrayelement.cpp \
+../kvs/kvi_kvs_treenode_arrayorhashelement.cpp \
+../kvs/kvi_kvs_treenode_arrayreferenceassert.cpp \
+../kvs/kvi_kvs_treenode_base.cpp \
+../kvs/kvi_kvs_treenode_baseobjectfunctioncall.cpp \
+../kvs/kvi_kvs_treenode_callbackcommand.cpp \
+../kvs/kvi_kvs_treenode_command.cpp \
+../kvs/kvi_kvs_treenode_commandevaluation.cpp \
+../kvs/kvi_kvs_treenode_commandwithparameters.cpp \
+../kvs/kvi_kvs_treenode_compositedata.cpp \
+../kvs/kvi_kvs_treenode_constantdata.cpp \
+../kvs/kvi_kvs_treenode_corecallbackcommand.cpp \
+../kvs/kvi_kvs_treenode_corefunctioncall.cpp \
+../kvs/kvi_kvs_treenode_coresimplecommand.cpp \
+../kvs/kvi_kvs_treenode_data.cpp \
+../kvs/kvi_kvs_treenode_datalist.cpp \
+../kvs/kvi_kvs_treenode_expression.cpp \
+../kvs/kvi_kvs_treenode_expressionreturn.cpp \
+../kvs/kvi_kvs_treenode_extendedscopevariable.cpp \
+../kvs/kvi_kvs_treenode_functioncall.cpp \
+../kvs/kvi_kvs_treenode_globalvariable.cpp \
+../kvs/kvi_kvs_treenode_hashcount.cpp \
+../kvs/kvi_kvs_treenode_hashelement.cpp \
+../kvs/kvi_kvs_treenode_hashreferenceassert.cpp \
+../kvs/kvi_kvs_treenode_indirectdata.cpp \
+../kvs/kvi_kvs_treenode_instruction.cpp \
+../kvs/kvi_kvs_treenode_instructionblock.cpp \
+../kvs/kvi_kvs_treenode_localvariable.cpp \
+../kvs/kvi_kvs_treenode_modulecallbackcommand.cpp \
+../kvs/kvi_kvs_treenode_modulefunctioncall.cpp \
+../kvs/kvi_kvs_treenode_modulesimplecommand.cpp \
+../kvs/kvi_kvs_treenode_multipleparameteridentifier.cpp \
+../kvs/kvi_kvs_treenode_objectfield.cpp \
+../kvs/kvi_kvs_treenode_objectfunctioncall.cpp \
+../kvs/kvi_kvs_treenode_operation.cpp \
+../kvs/kvi_kvs_treenode_parameterreturn.cpp \
+../kvs/kvi_kvs_treenode_rebindingswitch.cpp \
+../kvs/kvi_kvs_treenode_scopeoperator.cpp \
+../kvs/kvi_kvs_treenode_simplecommand.cpp \
+../kvs/kvi_kvs_treenode_singleparameteridentifier.cpp \
+../kvs/kvi_kvs_treenode_specialcommand.cpp \
+../kvs/kvi_kvs_treenode_specialcommandbreak.cpp \
+../kvs/kvi_kvs_treenode_specialcommandclass.cpp \
+../kvs/kvi_kvs_treenode_specialcommanddefpopup.cpp \
+../kvs/kvi_kvs_treenode_specialcommanddo.cpp \
+../kvs/kvi_kvs_treenode_specialcommandfor.cpp \
+../kvs/kvi_kvs_treenode_specialcommandforeach.cpp \
+../kvs/kvi_kvs_treenode_specialcommandif.cpp \
+../kvs/kvi_kvs_treenode_specialcommandswitch.cpp \
+../kvs/kvi_kvs_treenode_specialcommandunset.cpp \
+../kvs/kvi_kvs_treenode_specialcommandwhile.cpp \
+../kvs/kvi_kvs_treenode_stringcast.cpp \
+../kvs/kvi_kvs_treenode_switchlist.cpp \
+../kvs/kvi_kvs_treenode_thisobjectfunctioncall.cpp \
+../kvs/kvi_kvs_treenode_variable.cpp \
+../kvs/kvi_kvs_useraction.cpp \
+../kvs/kvi_kvs_variant.cpp \
+../kvs/kvi_kvs_variantlist.cpp \
+../kvs/kvi_kvs_treenode_voidfunctioncall.cpp \
+../module/kvi_mexlinkfilter.cpp \
+../module/kvi_mexserverimport.cpp ../module/kvi_mextoolbar.cpp \
+../module/kvi_module.cpp ../module/kvi_moduleextension.cpp ../module/kvi_modulemanager.cpp \
+../sparser/kvi_antispam.cpp ../sparser/kvi_ircmessage.cpp ../sparser/kvi_sparser.cpp \
+../sparser/kvi_sp_ctcp.cpp ../sparser/kvi_sp_literal.cpp ../sparser/kvi_sp_numeric.cpp \
+../sparser/kvi_sp_tables.cpp \
+../ui/kvi_actiondrawer.cpp \
+../ui/kvi_channel.cpp \
+../ui/kvi_colorwin.cpp \
+../ui/kvi_console.cpp \
+../ui/kvi_cryptcontroller.cpp \
+../ui/kvi_ctcppagedialog.cpp \
+../ui/kvi_customtoolbar.cpp \
+../ui/kvi_debugwindow.cpp \
+../ui/kvi_dynamictooltip.cpp \
+../ui/kvi_filedialog.cpp \
+../ui/kvi_frame.cpp \
+../ui/kvi_historywin.cpp \
+../ui/kvi_htmldialog.cpp \
+../ui/kvi_imagedialog.cpp \
+../ui/kvi_input.cpp \
+../ui/kvi_ipeditor.cpp \
+../ui/kvi_irctoolbar.cpp \
+../ui/kvi_ircview.cpp \
+../ui/kvi_ircviewtools.cpp \
+../ui/kvi_listview.cpp \
+../ui/kvi_maskeditor.cpp \
+../ui/kvi_mdicaption.cpp \
+../ui/kvi_mdichild.cpp \
+../ui/kvi_mdimanager.cpp \
+../ui/kvi_menubar.cpp \
+../ui/kvi_modeeditor.cpp \
+../ui/kvi_modew.cpp \
+../ui/kvi_msgbox.cpp \
+../ui/kvi_optionswidget.cpp \
+../ui/kvi_query.cpp \
+../ui/kvi_scriptbutton.cpp\
+../ui/kvi_scripteditor.cpp \
+../ui/kvi_selectors.cpp \
+../ui/kvi_splash.cpp \
+../ui/kvi_statusbar.cpp \
+../ui/kvi_statusbarapplet.cpp \
+../ui/kvi_taskbar.cpp \
+../ui/kvi_texticonwin.cpp \
+../ui/kvi_themedlabel.cpp \
+../ui/kvi_toolbar.cpp \
+../ui/kvi_toolwindows_container.cpp \
+../ui/kvi_topicw.cpp \
+../ui/kvi_styled_controls.cpp \
+../ui/kvi_userlistview.cpp \
+../ui/kvi_window.cpp
+
+#
+# Command useful to find out all the headers
+# rm -f ../include/*.h
+# SRC=`find ../ -name *.h | sort`
+# echo $SRC
+#
+
+
+headers_HEADERS = ../kernel/kvi_action.h \
+../kernel/kvi_actionmanager.h \
+../kernel/kvi_app.h \
+../kernel/kvi_asynchronousconnectiondata.h \
+../kernel/kvi_coreactions.h \
+../kernel/kvi_coreactionnames.h \
+../kernel/kvi_customtoolbardescriptor.h \
+../kernel/kvi_customtoolbarmanager.h \
+../kernel/kvi_filetransfer.h \
+../kernel/kvi_iconmanager.h \
+../kernel/kvi_internalcmd.h \
+../kernel/kvi_ipc.h \
+../kernel/kvi_ircdatastreammonitor.h \
+../kernel/kvi_ircconnection.h \
+../kernel/kvi_ircconnectionantictcpflooddata.h \
+../kernel/kvi_ircconnectionasyncwhoisdata.h \
+../kernel/kvi_ircconnectionnetsplitdetectordata.h \
+../kernel/kvi_ircconnectiontarget.h \
+../kernel/kvi_ircconnectiontargetresolver.h \
+../kernel/kvi_ircconnectionserverinfo.h \
+../kernel/kvi_ircconnectionstatedata.h \
+../kernel/kvi_ircconnectionstatistics.h \
+../kernel/kvi_ircconnectionuserinfo.h \
+../kernel/kvi_irccontext.h \
+../kernel/kvi_irclink.h \
+../kernel/kvi_ircsocket.h \
+../kernel/kvi_ircurl.h \
+../kernel/kvi_lagmeter.h \
+../kernel/kvi_notifylist.h \
+../kernel/kvi_options.h \
+../kernel/kvi_out.h \
+../kernel/kvi_sslmaster.h \
+../kernel/kvi_texticonmanager.h \
+../kernel/kvi_theme.h \
+../sparser/kvi_antispam.h \
+../sparser/kvi_ircmessage.h \
+../kernel/kvi_useraction.h \
+../kernel/kvi_userinput.h \
+../kvs/kvi_kvs.h \
+../kvs/kvi_kvs_action.h \
+../kvs/kvi_kvs_aliasmanager.h \
+../kvs/kvi_kvs_array.h \
+../kvs/kvi_kvs_arraycast.h \
+../kvs/kvi_kvs_asyncdnsoperation.h \
+../kvs/kvi_kvs_asyncoperation.h \
+../kvs/kvi_kvs_callbackobject.h \
+../kvs/kvi_kvs_corecallbackcommands.h \
+../kvs/kvi_kvs_corefunctions.h \
+../kvs/kvi_kvs_coresimplecommands.h \
+../kvs/kvi_kvs_dnsmanager.h \
+../kvs/kvi_kvs_event.h \
+../kvs/kvi_kvs_eventhandler.h \
+../kvs/kvi_kvs_eventmanager.h \
+../kvs/kvi_kvs_eventtriggers.h \
+../kvs/kvi_kvs_eventtable.h \
+../kvs/kvi_kvs_hash.h \
+../kvs/kvi_kvs_kernel.h \
+../kvs/kvi_kvs_moduleinterface.h \
+../kvs/kvi_kvs_object.h \
+../kvs/kvi_kvs_object_class.h \
+../kvs/kvi_kvs_object_controller.h \
+../kvs/kvi_kvs_object_functioncall.h \
+../kvs/kvi_kvs_object_functionhandler.h \
+../kvs/kvi_kvs_object_functionhandlerimpl.h \
+../kvs/kvi_kvs_parameterprocessor.h \
+../kvs/kvi_kvs_parser.h \
+../kvs/kvi_kvs_parser_macros.h \
+../kvs/kvi_kvs_popupmanager.h \
+../kvs/kvi_kvs_popupmenu.h \
+../kvs/kvi_kvs_processmanager.h \
+../kvs/kvi_kvs_report.h \
+../kvs/kvi_kvs_runtimecall.h \
+../kvs/kvi_kvs_runtimecontext.h \
+../kvs/kvi_kvs_rwevaluationresult.h \
+../kvs/kvi_kvs_script.h \
+../kvs/kvi_kvs_scriptaddonmanager.h \
+../kvs/kvi_kvs_switchlist.h \
+../kvs/kvi_kvs_timermanager.h \
+../kvs/kvi_kvs_treenode.h \
+../kvs/kvi_kvs_treenode_aliasfunctioncall.h \
+../kvs/kvi_kvs_treenode_aliassimplecommand.h \
+../kvs/kvi_kvs_treenode_arraycount.h \
+../kvs/kvi_kvs_treenode_arrayelement.h \
+../kvs/kvi_kvs_treenode_arrayorhashelement.h \
+../kvs/kvi_kvs_treenode_arrayreferenceassert.h \
+../kvs/kvi_kvs_treenode_base.h \
+../kvs/kvi_kvs_treenode_baseobjectfunctioncall.h \
+../kvs/kvi_kvs_treenode_callbackcommand.h \
+../kvs/kvi_kvs_treenode_command.h \
+../kvs/kvi_kvs_treenode_commandevaluation.h \
+../kvs/kvi_kvs_treenode_commandwithparameters.h \
+../kvs/kvi_kvs_treenode_compositedata.h \
+../kvs/kvi_kvs_treenode_constantdata.h \
+../kvs/kvi_kvs_treenode_corecallbackcommand.h \
+../kvs/kvi_kvs_treenode_corefunctioncall.h \
+../kvs/kvi_kvs_treenode_coresimplecommand.h \
+../kvs/kvi_kvs_treenode_data.h \
+../kvs/kvi_kvs_treenode_datalist.h \
+../kvs/kvi_kvs_treenode_expression.h \
+../kvs/kvi_kvs_treenode_expressionreturn.h \
+../kvs/kvi_kvs_treenode_extendedscopevariable.h \
+../kvs/kvi_kvs_treenode_functioncall.h \
+../kvs/kvi_kvs_treenode_globalvariable.h \
+../kvs/kvi_kvs_treenode_hashcount.h \
+../kvs/kvi_kvs_treenode_hashelement.h \
+../kvs/kvi_kvs_treenode_hashreferenceassert.h \
+../kvs/kvi_kvs_treenode_indirectdata.h \
+../kvs/kvi_kvs_treenode_instruction.h \
+../kvs/kvi_kvs_treenode_instructionblock.h \
+../kvs/kvi_kvs_treenode_localvariable.h \
+../kvs/kvi_kvs_treenode_modulecallbackcommand.h \
+../kvs/kvi_kvs_treenode_modulefunctioncall.h \
+../kvs/kvi_kvs_treenode_modulesimplecommand.h \
+../kvs/kvi_kvs_treenode_multipleparameteridentifier.h \
+../kvs/kvi_kvs_treenode_objectfield.h \
+../kvs/kvi_kvs_treenode_objectfunctioncall.h \
+../kvs/kvi_kvs_treenode_operation.h \
+../kvs/kvi_kvs_treenode_parameterreturn.h \
+../kvs/kvi_kvs_treenode_rebindingswitch.h \
+../kvs/kvi_kvs_treenode_scopeoperator.h \
+../kvs/kvi_kvs_treenode_simplecommand.h \
+../kvs/kvi_kvs_treenode_singleparameteridentifier.h \
+../kvs/kvi_kvs_treenode_specialcommand.h \
+../kvs/kvi_kvs_treenode_specialcommandbreak.h \
+../kvs/kvi_kvs_treenode_specialcommandclass.h \
+../kvs/kvi_kvs_treenode_specialcommanddefpopup.h \
+../kvs/kvi_kvs_treenode_specialcommanddo.h \
+../kvs/kvi_kvs_treenode_specialcommandfor.h \
+../kvs/kvi_kvs_treenode_specialcommandforeach.h \
+../kvs/kvi_kvs_treenode_specialcommandif.h \
+../kvs/kvi_kvs_treenode_specialcommandswitch.h \
+../kvs/kvi_kvs_treenode_specialcommandunset.h \
+../kvs/kvi_kvs_treenode_specialcommandwhile.h \
+../kvs/kvi_kvs_treenode_stringcast.h \
+../kvs/kvi_kvs_treenode_switchlist.h \
+../kvs/kvi_kvs_treenode_thisobjectfunctioncall.h \
+../kvs/kvi_kvs_treenode_variable.h \
+../kvs/kvi_kvs_treenode_voidfunctioncall.h \
+../kvs/kvi_kvs_types.h \
+../kvs/kvi_kvs_useraction.h \
+../kvs/kvi_kvs_variant.h \
+../kvs/kvi_kvs_variantlist.h \
+../module/kvi_mexlinkfilter.h ../module/kvi_mexserverimport.h ../module/kvi_mextoolbar.h \
+../module/kvi_module.h ../module/kvi_moduleextension.h ../module/kvi_modulemanager.h \
+../sparser/kvi_numeric.h \
+../sparser/kvi_sparser.h \
+../ui/kvi_actiondrawer.h \
+../ui/kvi_channel.h \
+../ui/kvi_colorwin.h \
+../ui/kvi_console.h \
+../ui/kvi_cryptcontroller.h \
+../ui/kvi_ctcppagedialog.h \
+../ui/kvi_customtoolbar.h \
+../ui/kvi_debugwindow.h \
+../ui/kvi_dynamictooltip.h \
+../ui/kvi_filedialog.h \
+../ui/kvi_frame.h \
+../ui/kvi_historywin.h \
+../ui/kvi_htmldialog.h \
+../ui/kvi_imagedialog.h \
+../ui/kvi_input.h \
+../ui/kvi_ipeditor.h \
+../ui/kvi_irctoolbar.h \
+../ui/kvi_ircview.h \
+../ui/kvi_ircviewprivate.h \
+../ui/kvi_ircviewtools.h \
+../ui/kvi_listview.h \
+../ui/kvi_maskeditor.h \
+../ui/kvi_mdicaption.h \
+../ui/kvi_mdichild.h \
+../ui/kvi_mdimanager.h \
+../ui/kvi_menubar.h \
+../ui/kvi_modeeditor.h \
+../ui/kvi_msgbox.h \
+../ui/kvi_optionswidget.h \
+../ui/kvi_query.h \
+../ui/kvi_scriptbutton.h \
+../ui/kvi_scripteditor.h \
+../ui/kvi_selectors.h \
+../ui/kvi_splash.h \
+../ui/kvi_statusbar.h \
+../ui/kvi_statusbarapplet.h \
+../ui/kvi_taskbar.h ../ui/kvi_texticonwin.h ../ui/kvi_themedlabel.h \
+../ui/kvi_toolbar.h ../ui/kvi_topicw.h ../ui/kvi_userlistview.h \
+../ui/kvi_window.h \
+../ui/kvi_modew.h \
+../ui/kvi_styled_controls.h \
+../ui/kvi_toolwindows_container.h
+
+%.moc: %.h
+ $(SS_QT_MOC) $(SS_QT_MOC_FLAGS) $< -o $@
+
+# Command useful to find the moc dependancies
+# DIRS="kernel sparser ui uparser"
+# for dire in $DIRS; do grep "\.moc" ../$dire/*.cpp | sort | sed -e 's/[[:space:]]*#include//' | sed -e s/\\\"/..\\\/$dire\\\// | sed -e 's/\"//'; done
+
+../kernel/kvi_app.cpp: ../kernel/kvi_app.moc
+../kernel/kvi_iconmanager.cpp: ../kernel/kvi_iconmanager.moc
+../kernel/kvi_ipc.cpp: ../kernel/kvi_ipc.moc
+../kernel/kvi_lagmeter.cpp: ../kernel/kvi_lagmeter.moc
+../kernel/kvi_notifylist.cpp: ../kernel/kvi_notifylist.moc
+../kernel/kvi_texticonmanager.cpp: ../kernel/kvi_texticonmanager.moc
+../sparser/kvi_sparser.cpp: ../sparser/kvi_sparser.moc
+../ui/kvi_channel.cpp: ../ui/kvi_channel.moc
+../ui/kvi_colorwin.cpp: ../ui/kvi_colorwin.moc
+../ui/kvi_console.cpp: ../ui/kvi_console.moc
+../ui/kvi_cryptcontroller.cpp: ../ui/kvi_cryptcontroller.moc
+../ui/kvi_ctcppagedialog.cpp: ../ui/kvi_ctcppagedialog.moc
+../ui/kvi_dynamictooltip.cpp: ../ui/kvi_dynamictooltip.moc
+../ui/kvi_filedialog.cpp: ../ui/kvi_filedialog.moc
+../ui/kvi_frame.cpp: ../ui/kvi_frame.moc
+../ui/kvi_historywin.cpp: ../ui/kvi_historywin.moc
+../ui/kvi_input.cpp: ../ui/kvi_input.moc
+../ui/kvi_ipeditor.cpp: ../ui/kvi_ipeditor.moc
+../ui/kvi_irctoolbar.cpp: ../ui/kvi_irctoolbar.moc
+../ui/kvi_ircview.cpp: ../ui/kvi_ircview.moc
+../ui/kvi_maskeditor.cpp: ../ui/kvi_maskeditor.moc
+../ui/kvi_menubar.cpp: ../ui/kvi_menubar.moc
+../ui/kvi_modeeditor.cpp: ../ui/kvi_modeeditor.moc
+../ui/kvi_optionswidget.cpp: ../ui/kvi_optionswidget.moc
+../ui/kvi_query.cpp: ../ui/kvi_query.moc
+../ui/kvi_scriptbutton.cpp: ../ui/kvi_scriptbutton.moc
+../ui/kvi_scripteditor.cpp: ../ui/kvi_scripteditor.moc
+../ui/kvi_selectors.cpp: ../ui/kvi_selectors.moc
+../ui/kvi_splash.cpp: ../ui/kvi_splash.moc
+../ui/kvi_taskbar.cpp: ../ui/kvi_taskbar.moc
+../ui/kvi_texticonwin.cpp: ../ui/kvi_texticonwin.moc
+../ui/kvi_themedlabel.cpp: ../ui/kvi_themedlabel.moc
+../ui/kvi_toolbar.cpp: ../ui/kvi_toolbar.moc
+../ui/kvi_topicw.cpp: ../ui/kvi_topicw.moc
+../ui/kvi_modew.cpp: ../ui/kvi_modew.moc
+../ui/kvi_styled_controls.cpp: ../ui/kvi_styled_controls.moc
+../ui/kvi_userlistview.cpp: ../ui/kvi_userlistview.moc
+../ui/kvi_window.cpp: ../ui/kvi_window.moc
+
+
+../kvs/moc_%.cpp: ../kvs/%.h
+ $(SS_QT_MOC) $(SS_QT_MOC_FLAGS) $< -o $@
+
+../kernel/moc_%.cpp: ../kernel/%.h
+ $(SS_QT_MOC) $(SS_QT_MOC_FLAGS) $< -o $@
+
+../module/moc_%.cpp: ../module/%.h
+ $(SS_QT_MOC) $(SS_QT_MOC_FLAGS) $< -o $@
+
+../ui/moc_%.cpp: ../ui/%.h
+ $(SS_QT_MOC) $(SS_QT_MOC_FLAGS) $< -o $@
+
+
+#
+# All the cpp files depend on symlinks beging up-to-date
+#
+
+../*/kvi_*.cpp: symlinks
+../*/*/kvi_*.cpp: symlinks
+
+#
+# Symlinks depend on all the header files: symlink is rebuilt whenewer an *.h file changes
+#
+
+symlinks: ../kernel/*.h ../kvs/*.h ../module/*h ../sparser/*.h ../ui/*.h
+ cd ../include; for i in kvi_*.h; do if [ ! -f $$i ]; then rm -f $$i; fi; done; for i in $(SS_TOPSRCDIR)/src/kvirc/*/kvi_*.h; do $(LN_S) $$i . >/dev/null 2>&1; echo "Created link to $$i"; done
+ touch symlinks
+
+#
+# When cleaning...remove also the symlinks
+#
+
+CLEANFILES = ../include/*.h symlinks ../*/*.moc ../*/moc_kvi_*.cpp
diff --git a/src/kvirc/include/Makefile.am b/src/kvirc/include/Makefile.am
new file mode 100644
index 00000000..6847f085
--- /dev/null
+++ b/src/kvirc/include/Makefile.am
@@ -0,0 +1,3 @@
+###############################################################################
+# KVirc IRC client Makefile - 16.12.98 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
diff --git a/src/kvirc/kernel/Makefile.am b/src/kvirc/kernel/Makefile.am
new file mode 100644
index 00000000..c84487eb
--- /dev/null
+++ b/src/kvirc/kernel/Makefile.am
@@ -0,0 +1,5 @@
+###############################################################################
+# KVirc IRC client Makefile - 16.12.98 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+EXTRA_DIST = *.cpp *.h
diff --git a/src/kvirc/kernel/kvi_action.cpp b/src/kvirc/kernel/kvi_action.cpp
new file mode 100644
index 00000000..4764fcfd
--- /dev/null
+++ b/src/kvirc/kernel/kvi_action.cpp
@@ -0,0 +1,434 @@
+//=============================================================================
+//
+// File : kvi_action.cpp
+// Created on Sun 21 Nov 2004 03:36:34 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_action.h"
+#include "kvi_customtoolbar.h"
+#include "kvi_frame.h"
+#include "kvi_irccontext.h"
+#include "kvi_ircconnection.h"
+#include "kvi_iconmanager.h"
+#include "kvi_app.h"
+#include "kvi_window.h"
+#include "kvi_channel.h"
+#include "kvi_console.h"
+#include "kvi_query.h"
+#include "kvi_styled_controls.h"
+
+#include <qtoolbutton.h>
+#include "kvi_tal_popupmenu.h"
+
+
+KviAction::~KviAction()
+{
+ if(m_pWidgetList)
+ {
+ for(QWidget * b = m_pWidgetList->first();b;b = m_pWidgetList->next())
+ disconnect(b,SIGNAL(destroyed()),this,SLOT(widgetDestroyed()));
+ m_pWidgetList->setAutoDelete(true);
+ delete m_pWidgetList;
+ }
+}
+
+const QString & KviAction::visibleName()
+{
+ return m_szVisibleName;
+}
+
+const QString & KviAction::description()
+{
+ return m_szDescription;
+}
+
+bool KviAction::isKviUserActionNeverOverrideThis()
+{
+ return false;
+}
+
+void KviAction::registerAccelerator()
+{
+ if(!m_szKeySequence.isEmpty())
+ m_iAccelId = g_pFrame->registerAccelerator(m_szKeySequence,this,SLOT(activate()));
+}
+
+void KviAction::unregisterAccelerator()
+{
+ if(m_iAccelId != 0)
+ {
+ if(g_pFrame)
+ g_pFrame->unregisterAccelerator(m_iAccelId);
+ m_iAccelId = 0;
+ }
+}
+
+void KviAction::setEnabled(bool bEnabled)
+{
+ if(bEnabled)
+ m_uInternalFlags |= KVI_ACTION_FLAG_ENABLED;
+ else
+ m_uInternalFlags &= ~KVI_ACTION_FLAG_ENABLED;
+
+ if(m_pWidgetList)
+ {
+ if(bEnabled)
+ {
+ for(QWidget * t = m_pWidgetList->first();t;t = m_pWidgetList->next())
+ if(!t->isEnabled())t->setEnabled(true);
+ } else {
+ for(QWidget * t = m_pWidgetList->first();t;t = m_pWidgetList->next())
+ if(t->isEnabled())t->setEnabled(false);
+ }
+ }
+}
+
+int KviAction::validateFlags(int iFlagsToValidate)
+{
+ if(iFlagsToValidate & EnableAtLogin)
+ iFlagsToValidate |= NeedsConnection;
+ if(iFlagsToValidate & NeedsConnection)
+ iFlagsToValidate |= NeedsContext;
+ if(iFlagsToValidate & WindowOnlyIfUsersSelected)
+ {
+ if(!(iFlagsToValidate & InternalWindowMask))
+ iFlagsToValidate &= ~WindowOnlyIfUsersSelected;
+ }
+ return iFlagsToValidate;
+}
+
+QPixmap * KviAction::smallIcon()
+{
+ if(m_iSmallIconId != 0)return g_pIconManager->getSmallIcon(m_iSmallIconId);
+ return 0;
+}
+
+QPixmap * KviAction::bigIcon()
+{
+ return g_pIconManager->getBigIcon(m_szBigIcon);
+}
+
+void KviAction::setup()
+{
+ connect(g_pApp,SIGNAL(reloadImages()),this,SLOT(reloadImages()));
+ if(m_uFlags & InternalWindowMask)
+ {
+ connect(g_pFrame,SIGNAL(activeWindowChanged()),this,SLOT(activeWindowChanged()));
+ if((m_uFlags & WindowOnlyIfUsersSelected) && (m_uFlags & (WindowChannel | WindowConsole | WindowQuery)))
+ connect(g_pFrame,SIGNAL(activeWindowSelectionStateChanged(bool)),this,SLOT(activeWindowSelectionStateChanged(bool)));
+ activeWindowChanged();
+ } else {
+ if(m_uFlags & NeedsConnection)
+ {
+ connect(g_pFrame,SIGNAL(activeContextChanged()),this,SLOT(activeContextChanged()));
+ connect(g_pFrame,SIGNAL(activeContextStateChanged()),this,SLOT(activeContextStateChanged()));
+ KviIrcContext * c = g_pFrame->activeContext();
+ if(!c)setEnabled(false);
+ else {
+ switch(c->state())
+ {
+ case KviIrcContext::LoggingIn:
+ setEnabled(m_uFlags & EnableAtLogin);
+ break;
+ case KviIrcContext::Connected:
+ setEnabled(true);
+ break;
+ default:
+ setEnabled(false);
+ break;
+ }
+ }
+ } else {
+ if(m_uFlags & NeedsContext)
+ {
+ connect(g_pFrame,SIGNAL(activeContextChanged()),this,SLOT(activeContextChanged()));
+ if(!g_pFrame->activeContext())setEnabled(false);
+ else setEnabled(true);
+ }
+ }
+ }
+
+ m_uInternalFlags |= KVI_ACTION_FLAG_SETUPDONE;
+}
+
+
+void KviAction::reloadImages()
+{
+ if(!m_pWidgetList)return;
+ QPixmap * p = bigIcon();
+ for(QWidget * b = m_pWidgetList->first();b;b = m_pWidgetList->next())
+ {
+ if(b->inherits("QToolButton"))
+ ((QToolButton *)b)->setIconSet(p ? *p : QPixmap());
+ }
+}
+
+void KviAction::activeWindowChanged()
+{
+ if(m_uFlags & NeedsContext)
+ {
+ if(!g_pFrame->activeContext())
+ {
+ if(isEnabled())setEnabled(false);
+ return;
+ }
+ }
+
+ if(m_uFlags & NeedsConnection)
+ {
+ switch(g_pFrame->activeContext()->state())
+ {
+ case KviIrcContext::LoggingIn:
+ if(!(m_uFlags & EnableAtLogin))
+ {
+ if(isEnabled())setEnabled(false);
+ return;
+ }
+ break;
+ case KviIrcContext::Connected:
+ // this is ok
+ break;
+ default:
+ if(isEnabled())setEnabled(false);
+ return;
+ break;
+ }
+ }
+
+ if(!g_pActiveWindow)
+ {
+ if(isEnabled())setEnabled(false);
+ return;
+ }
+
+ switch(g_pActiveWindow->type())
+ {
+ case KVI_WINDOW_TYPE_CONSOLE:
+ if(m_uFlags & WindowConsole)
+ {
+ if(m_uFlags & WindowOnlyIfUsersSelected)
+ {
+ bool bEnabled = ((KviConsole *)g_pActiveWindow)->selectedCount() > 0;
+ if(bEnabled != isEnabled())setEnabled(bEnabled);
+ } else {
+ if(!isEnabled())setEnabled(true);
+ }
+ } else {
+ if(isEnabled())setEnabled(false);
+ }
+ break;
+ case KVI_WINDOW_TYPE_CHANNEL:
+ if(m_uFlags & WindowChannel)
+ {
+ if(m_uFlags & WindowOnlyIfUsersSelected)
+ {
+ bool bEnabled = ((KviChannel *)g_pActiveWindow)->selectedCount() > 0;
+ if(bEnabled != isEnabled())setEnabled(bEnabled);
+ } else {
+ if(!isEnabled())setEnabled(true);
+ }
+ } else {
+ if(isEnabled())setEnabled(false);
+ }
+ break;
+ case KVI_WINDOW_TYPE_QUERY:
+ if(m_uFlags & WindowQuery)
+ {
+ if(m_uFlags & WindowOnlyIfUsersSelected)
+ {
+ bool bEnabled = ((KviQuery *)g_pActiveWindow)->selectedCount() > 0;
+ if(bEnabled != isEnabled())setEnabled(bEnabled);
+ } else {
+ if(!isEnabled())setEnabled(true);
+ }
+ } else {
+ if(isEnabled())setEnabled(false);
+ }
+ break;
+ case KVI_WINDOW_TYPE_DCCCHAT:
+ if(m_uFlags & WindowDccChat)
+ {
+ if(!isEnabled())setEnabled(true);
+ } else {
+ if(isEnabled())setEnabled(false);
+ }
+ break;
+ default:
+ if(m_uFlags & InternalWindowMask)
+ if(isEnabled())setEnabled(false);
+ else
+ if(!isEnabled())setEnabled(true);
+ break;
+ }
+}
+
+
+void KviAction::activeWindowSelectionStateChanged(bool bSelectedNow)
+{
+ // we jump here ONLY if m_uFlags & WindowOnlyIfUsersSelected
+ // and thus also m_uFlags & InternalWindowMask
+ switch(g_pActiveWindow->type())
+ {
+ case KVI_WINDOW_TYPE_CONSOLE:
+ if(m_uFlags & WindowConsole)
+ {
+ if(bSelectedNow != isEnabled())setEnabled(bSelectedNow);
+ } else {
+ if(isEnabled())setEnabled(false);
+ }
+ break;
+ case KVI_WINDOW_TYPE_CHANNEL:
+ if(m_uFlags & WindowChannel)
+ {
+ if(bSelectedNow != isEnabled())setEnabled(bSelectedNow);
+ } else {
+ if(isEnabled())setEnabled(false);
+ }
+ break;
+ case KVI_WINDOW_TYPE_QUERY:
+ if(m_uFlags & WindowQuery)
+ {
+ if(bSelectedNow != isEnabled())setEnabled(bSelectedNow);
+ } else {
+ if(isEnabled())setEnabled(false);
+ }
+ break;
+ case KVI_WINDOW_TYPE_DCCCHAT:
+ if(m_uFlags & WindowDccChat)
+ {
+ if(!isEnabled())setEnabled(true);
+ } else {
+ if(isEnabled())setEnabled(false);
+ }
+ break;
+ default:
+ if(isEnabled())setEnabled(false);
+ break;
+ }
+}
+
+
+void KviAction::activeContextChanged()
+{
+ // works only if NeedsContext is specified!
+ KviIrcContext * c = g_pFrame->activeContext();
+ if(c)
+ {
+ if(m_uFlags & NeedsConnection)
+ activeContextStateChanged();
+ else
+ if(!isEnabled())setEnabled(true);
+ } else {
+ if(isEnabled())setEnabled(false);
+ }
+}
+
+void KviAction::activeContextStateChanged()
+{
+ KviIrcContext * c = g_pFrame->activeContext();
+ if(c)
+ {
+ switch(c->state())
+ {
+ case KviIrcContext::Idle:
+ case KviIrcContext::Connecting:
+ if(isEnabled())setEnabled(false);
+ break;
+ case KviIrcContext::LoggingIn:
+ if(m_uFlags & EnableAtLogin)
+ {
+ if(!isEnabled())setEnabled(true);
+ } else {
+ if(isEnabled())setEnabled(false);
+ }
+ break;
+ case KviIrcContext::Connected:
+ if(!isEnabled())setEnabled(true);
+ break;
+ default:
+ if(isEnabled())setEnabled(false);
+ break;
+ }
+ } else {
+ if(isEnabled())setEnabled(false);
+ }
+}
+
+bool KviAction::addToPopupMenu(KviTalPopupMenu *pMenu)
+{
+ if(!setupDone())setup();
+ QPixmap * p = smallIcon();
+ int id;
+ QString t = visibleName();
+ if(!m_szKeySequence.isEmpty())t += '\t' + m_szKeySequence;
+ if(p)
+ {
+ id = pMenu->insertItem(*p,t,this,SLOT(activate()));
+ } else {
+ id = pMenu->insertItem(t,this,SLOT(activate()));
+ }
+ if(!isEnabled())pMenu->setItemEnabled(id,false);
+ return true;
+}
+
+void KviAction::widgetDestroyed()
+{
+ if(!m_pWidgetList)return;
+ QWidget * b = (QWidget *)sender();
+ m_pWidgetList->removeRef(b);
+}
+
+void KviAction::registerWidget(QWidget * b)
+{
+ connect(b,SIGNAL(destroyed()),this,SLOT(widgetDestroyed()));
+ if(!m_pWidgetList)
+ {
+ m_pWidgetList = new KviPointerList<QWidget>;
+ m_pWidgetList->setAutoDelete(false);
+ }
+ m_pWidgetList->append(b);
+}
+
+QWidget * KviAction::addToCustomToolBar(KviCustomToolBar *pParentToolBar)
+{
+ if(!setupDone())setup();
+ QPixmap * p = bigIcon();
+ QToolButton * b = new KviStyledToolButton(
+ p ? *p : QPixmap(),
+ visibleName(),
+ visibleName(),
+ this,SLOT(activate()),pParentToolBar,m_szName);
+#ifdef COMPILE_USE_QT4
+ pParentToolBar->addWidget(b);
+#endif
+ if(!isEnabled())b->setEnabled(false);
+ registerWidget(b);
+ return b;
+}
+
+void KviAction::activate()
+{
+ if(isEnabled())
+ emit activated();
+}
+
diff --git a/src/kvirc/kernel/kvi_action.h b/src/kvirc/kernel/kvi_action.h
new file mode 100644
index 00000000..18669634
--- /dev/null
+++ b/src/kvirc/kernel/kvi_action.h
@@ -0,0 +1,157 @@
+#ifndef _KVI_ACTION_H_
+#define _KVI_ACTION_H_
+//=============================================================================
+//
+// File : kvi_action.h
+// Created on Sun 21 Nov 2004 03:36:34 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_pointerlist.h"
+
+#include <qobject.h>
+#include <qstring.h>
+
+// The action name is INTERNAL: it should be never shown to the user
+// if it contains a dot then the part before the dot is considered to
+// be a module name to be loaded when the
+
+// Known categories are: general (or empty), irc, script
+//
+
+class KviTalPopupMenu;
+class QWidget;
+class KviCustomToolBar;
+class QPixmap;
+class KviKvsScript;
+
+class KVIRC_API KviActionCategory
+{
+protected:
+ QString m_szName;
+ QString m_szVisibleName;
+ QString m_szDescription;
+public:
+ KviActionCategory(const QString &szName,const QString &szVisibleName,const QString &szDescription)
+ : m_szName(szName), m_szVisibleName(szVisibleName), m_szDescription(szDescription) {};
+ ~KviActionCategory(){};
+public:
+ const QString & name(){ return m_szName; };
+ const QString & visibleName(){ return m_szVisibleName; };
+ const QString & description(){ return m_szDescription; };
+};
+
+// these flags are INTERNAL
+#define KVI_ACTION_FLAG_ENABLED 1
+#define KVI_ACTION_FLAG_SETUPDONE 2
+
+class KVIRC_API KviAction : public QObject
+{
+ friend class KviActionManager;
+ Q_OBJECT
+protected:
+ QString m_szName; // the internal name of the action, must be in form [module.]name
+ QString m_szVisibleName;
+ QString m_szDescription;
+ KviActionCategory * m_pCategory; // may be 0, not owned!
+ QString m_szBigIcon;
+ int m_iSmallIconId;
+ KviPointerList<QWidget> * m_pWidgetList;
+ unsigned short int m_uInternalFlags;
+ unsigned int m_uFlags;
+ QString m_szKeySequence;
+ int m_iAccelId;
+public:
+ enum Flags {
+ NeedsContext = 1,
+ NeedsConnection = 2, // implies NeedsContext
+ WindowConsole = 4,
+ WindowChannel = 8,
+ WindowQuery = 16,
+ WindowDccChat = 32,
+ InternalWindowMask = WindowConsole | WindowChannel | WindowQuery | WindowDccChat,
+ EnableAtLogin = 64, // implies NeedsConnection
+ WindowOnlyIfUsersSelected = 128 // implies at least one of WindowConsole | WindowChannel | WindowQuery
+ };
+public:
+ KviAction(QObject * pParent, // can be 0, but using a QObject will help in deleting this action :)
+ const QString &szName, // internal name of this action, in form [module.]name
+ const QString &szVisibleName, // permanent visible name, visible at least in the action drawer
+ const QString &szDescription, // what this action does ?
+ KviActionCategory * pCategory = 0, // one of KviActionManager::category*() or 0 (default category)
+ const QString &szBigIcon = QString::null,
+ int iSmallIconId = 0,
+ unsigned int uFlags = 0,
+ const QString &szKeySequence = QString::null)
+ : QObject(pParent),
+ m_szName(szName),
+ m_szVisibleName(szVisibleName),
+ m_szDescription(szDescription),
+ m_pCategory(pCategory),
+ m_szBigIcon(szBigIcon),
+ m_iSmallIconId(iSmallIconId),
+ m_pWidgetList(0),
+ m_uInternalFlags(KVI_ACTION_FLAG_ENABLED),
+ m_uFlags(uFlags),
+ m_szKeySequence(szKeySequence),
+ m_iAccelId(0) {}
+ virtual ~KviAction();
+public:
+ static int validateFlags(int iFlagsToValidate);
+ const QString & name() const { return m_szName; };
+ virtual const QString & visibleName();
+ virtual const QString & description();
+ const QString & keySequence() const { return m_szKeySequence; };
+ const QString & bigIconString() const { return m_szBigIcon; };
+ KviActionCategory * category() const { return m_pCategory; };
+ bool isEnabled() const { return (m_uInternalFlags & KVI_ACTION_FLAG_ENABLED); };
+ unsigned int flags(){ return m_uFlags; };
+ virtual bool isKviUserActionNeverOverrideThis();
+ virtual void setEnabled(bool bEnabled);
+ virtual QPixmap * smallIcon();
+ virtual QPixmap * bigIcon();
+ virtual bool addToPopupMenu(KviTalPopupMenu *pMenu);
+ virtual QWidget * addToCustomToolBar(KviCustomToolBar *pParentToolBar);
+ void suicide() { delete this; };
+protected:
+ // called once before the FIRST button or menu item is created
+ bool setupDone() const { return (m_uInternalFlags & KVI_ACTION_FLAG_SETUPDONE); };
+ virtual void setup();
+ KviPointerList<QWidget> * widgetList(){ return m_pWidgetList; };
+ void registerAccelerator();
+ void unregisterAccelerator();
+ void registerWidget(QWidget * b);
+protected slots:
+ virtual void widgetDestroyed();
+ virtual void reloadImages();
+ virtual void activeContextChanged();
+ virtual void activeContextStateChanged();
+ virtual void activeWindowChanged();
+ virtual void activeWindowSelectionStateChanged(bool bSelectedNow);
+public slots:
+ virtual void activate();
+signals:
+ void activated();
+};
+
+
+
+#endif //!_KVI_ACTION_H_
diff --git a/src/kvirc/kernel/kvi_actionmanager.cpp b/src/kvirc/kernel/kvi_actionmanager.cpp
new file mode 100644
index 00000000..3a325a6e
--- /dev/null
+++ b/src/kvirc/kernel/kvi_actionmanager.cpp
@@ -0,0 +1,321 @@
+//=============================================================================
+//
+// File : kvi_actionmanager.cpp
+// Created on Sun 21 Nov 2004 03:37:57 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_actionmanager.h"
+#include "kvi_modulemanager.h"
+#include "kvi_coreactions.h"
+#include "kvi_customtoolbar.h"
+#include "kvi_customtoolbarmanager.h"
+#include "kvi_app.h"
+#include "kvi_locale.h"
+#include "kvi_kvs_useraction.h"
+#include "kvi_config.h"
+#include "kvi_qstring.h"
+#include "kvi_frame.h"
+
+KviActionManager * KviActionManager::m_pInstance = 0;
+KviActionCategory * KviActionManager::m_pCategoryIrc = 0;
+KviActionCategory * KviActionManager::m_pCategoryGeneric = 0;
+KviActionCategory * KviActionManager::m_pCategorySettings = 0;
+KviActionCategory * KviActionManager::m_pCategoryScripting = 0;
+KviActionCategory * KviActionManager::m_pCategoryGUI = 0;
+KviActionCategory * KviActionManager::m_pCategoryChannel = 0;
+KviActionCategory * KviActionManager::m_pCategoryTools = 0;
+bool KviActionManager::m_bCustomizingToolBars = false;
+KviCustomToolBar * KviActionManager::m_pCurrentToolBar = 0;
+// kvi_coreactions.cpp
+extern void register_core_actions(KviActionManager *);
+
+KviActionManager::KviActionManager()
+: QObject()
+{
+ m_pActions = new KviPointerHashTable<QString,KviAction>(101);
+ m_pActions->setAutoDelete(false);
+
+ m_pCategories = new KviPointerHashTable<QString,KviActionCategory>(17,false);
+ m_pCategories->setAutoDelete(true);
+
+#define CATEGORY(__var,__name,__vname,__descr) \
+ __var = new KviActionCategory(__name,__vname,__descr); \
+ m_pCategories->replace(__name,__var)
+
+ CATEGORY(m_pCategoryIrc,"irc",__tr2qs("IRC"),__tr2qs("IRC Context related actions"));
+ CATEGORY(m_pCategoryGeneric,"generic",__tr2qs("Generic"),__tr2qs("Generic actions"));
+ CATEGORY(m_pCategorySettings,"settings",__tr2qs("Settings"),__tr2qs("Actions related to settings"));
+ CATEGORY(m_pCategoryScripting,"scripting",__tr2qs("Scripting"),__tr2qs("Scripting related actions"));
+ CATEGORY(m_pCategoryGUI,"gui",__tr2qs("GUI"),__tr2qs("Actions related to the Graphic User Interface"));
+ CATEGORY(m_pCategoryChannel,"channel",__tr2qs("Channel"),__tr2qs("IRC Channel related actions"));
+ CATEGORY(m_pCategoryTools,"tools",__tr2qs("Tools"),__tr2qs("Actions that will appear in the \"Tools\" menu"));
+
+ m_bCustomizingToolBars = false;
+ m_pCurrentToolBar = 0;
+ m_bCoreActionsRegistered = false;
+}
+
+KviActionManager::~KviActionManager()
+{
+ // the customizeToolBars dialog has been already
+ // destroyed since the module manager has already
+ // killed all the modules at this point...
+ //KviActionDialog::cleanup();
+
+ KviPointerHashTableIterator<QString,KviAction> it(*m_pActions);
+ while(KviAction * a = it.current())
+ {
+ disconnect(a,SIGNAL(destroyed()),this,SLOT(actionDestroyed()));
+ ++it;
+ }
+ delete m_pActions;
+
+ delete m_pCategories;
+}
+
+void KviActionManager::load(const QString &szFileName)
+{
+ KviConfig cfg(szFileName,KviConfig::Read);
+
+ KviConfigIterator it(*(cfg.dict()));
+ while(it.current())
+ {
+ cfg.setGroup(it.currentKey());
+ KviKvsUserAction * a = new KviKvsUserAction(this);
+ if(a->load(&cfg))registerAction(a);
+ else delete a;
+ ++it;
+ }
+}
+
+void KviActionManager::save(const QString &szFileName)
+{
+ KviConfig cfg(szFileName,KviConfig::Write);
+ cfg.clear();
+
+ KviPointerHashTableIterator<QString,KviAction> it(*m_pActions);
+ while(KviAction * a = it.current())
+ {
+ if(a->isKviUserActionNeverOverrideThis())
+ {
+ cfg.setGroup(a->name());
+ ((KviKvsUserAction *)a)->save(&cfg);
+ }
+ ++it;
+ }
+}
+
+void KviActionManager::killAllKvsUserActions()
+{
+ KviPointerList<KviKvsUserAction> dying;
+ dying.setAutoDelete(true);
+
+ KviPointerHashTableIterator<QString,KviAction> it(*m_pActions);
+ while(KviAction * a = it.current())
+ {
+ if(a->isKviUserActionNeverOverrideThis())
+ {
+ dying.append(((KviKvsUserAction *)a));
+ }
+ ++it;
+ }
+
+ dying.clear(); // bye :)
+}
+
+
+bool KviActionManager::coreActionExists(const QString &szName)
+{
+ KviAction *a = m_pActions->find(szName);
+ if(a)return (!a->isKviUserActionNeverOverrideThis());
+ return false;
+}
+
+QString KviActionManager::nameForAutomaticAction(const QString &szTemplate)
+{
+ QString ret;
+
+ int i = 1;
+ do {
+ KviQString::sprintf(ret,"%Q%d",&szTemplate,i);
+ i++;
+ } while(m_pActions->find(ret));
+
+ return ret;
+}
+
+void KviActionManager::emitRemoveActionsHintRequest()
+{
+ emit removeActionsHintRequest();
+}
+
+KviActionCategory * KviActionManager::category(const QString &szName)
+{
+ if(!szName.isEmpty())
+ {
+ KviActionCategory * c = m_pCategories->find(szName);
+ if(c)return c;
+ }
+ return m_pCategoryGeneric;
+}
+
+void KviActionManager::customizeToolBarsDialogCreated()
+{
+ m_bCustomizingToolBars = true;
+ m_pCurrentToolBar = KviCustomToolBarManager::instance()->firstExistingToolBar();
+ if(m_pCurrentToolBar)m_pCurrentToolBar->update();
+ emit beginCustomizeToolBars();
+}
+
+void KviActionManager::customizeToolBarsDialogDestroyed()
+{
+ m_bCustomizingToolBars = false;
+ emit endCustomizeToolBars();
+ if(m_pCurrentToolBar)
+ {
+ m_pCurrentToolBar->update();
+ m_pCurrentToolBar = 0;
+ }
+ g_pApp->saveToolBars();
+}
+
+void KviActionManager::setCurrentToolBar(KviCustomToolBar * t)
+{
+ if(m_pCurrentToolBar == t)return;
+ KviCustomToolBar * old = m_pCurrentToolBar;
+ m_pCurrentToolBar = t;
+ if(old)old->update();
+ if(!m_pCurrentToolBar && m_bCustomizingToolBars)
+ m_pCurrentToolBar = KviCustomToolBarManager::instance()->firstExistingToolBar();
+ if(m_pCurrentToolBar)m_pCurrentToolBar->update();
+ emit currentToolBarChanged();
+}
+
+void KviActionManager::loadAllAvailableActions()
+{
+ // make sure that the core actions are registered now
+ if(!KviActionManager::instance()->m_bCoreActionsRegistered)
+ {
+ register_core_actions(KviActionManager::instance());
+ KviActionManager::instance()->m_bCoreActionsRegistered = true;
+ }
+ g_pModuleManager->loadModulesByCaps("action");
+}
+
+void KviActionManager::init()
+{
+ if(!m_pInstance)m_pInstance = new KviActionManager();
+}
+
+void KviActionManager::done()
+{
+ if(m_pInstance)
+ {
+ delete m_pInstance;
+ m_pInstance = 0;
+ }
+}
+
+void KviActionManager::delayedRegisterAccelerators()
+{
+ KviPointerHashTableIterator<QString,KviAction> it(*m_pActions);
+ while(KviAction * a = it.current())
+ {
+ a->registerAccelerator();
+ ++it;
+ }
+}
+
+bool KviActionManager::registerAction(KviAction * a)
+{
+ if(m_pActions->find(a->name()))return false;
+ connect(a,SIGNAL(destroyed()),this,SLOT(actionDestroyed()));
+ m_pActions->insert(a->name(),a);
+ if(g_pFrame)a->registerAccelerator(); // otherwise it is delayed!
+ return true;
+}
+
+void KviActionManager::actionDestroyed()
+{
+ KviAction * a = (KviAction *)sender();
+ m_pActions->remove(a->name());
+}
+
+bool KviActionManager::unregisterAction(const QString &szName)
+{
+ KviAction * a = m_pActions->find(szName);
+ if(!a)return false;
+ disconnect(a,SIGNAL(destroyed()),this,SLOT(actionDestroyed()));
+ a->unregisterAccelerator();
+ return m_pActions->remove(szName);
+}
+
+KviAction * KviActionManager::getAction(const QString &szName)
+{
+ KviAction * a = m_pActions->find(szName);
+ if(a)return a;
+ int idx = szName.find('.');
+ if(idx < 0)
+ {
+ // backward compatibility: try to lookup the name with the kvirc. prefix
+ QString s = "kvirc.";
+ s += szName;
+ return m_pActions->find(s);
+ }
+ if((idx == 5) && (!m_bCoreActionsRegistered))
+ {
+ // the core actions are all like kvirc.name
+ // so the dot is at poisition 5 (6th char)
+ // the first requested core action will trigger this
+ // the nice thing is that we will probably already have a frame when
+ // the core actions are registered thus stuff like mdiManager() can be accessed...
+ if(szName.left(5) == "kvirc")
+ {
+ register_core_actions(this);
+ m_bCoreActionsRegistered = true;
+ a = m_pActions->find(szName);
+ return a;
+ }
+ }
+ // try to preload the module that might register this action...
+ QString szModule = szName.left(idx);
+ if(!g_pModuleManager->getModule(szModule))return 0;
+ return m_pActions->find(szName);
+}
+
+void KviActionManager::listActionsByCategory(const QString &szCatName,KviPointerList<KviAction> * pBuffer)
+{
+ loadAllAvailableActions();
+ KviActionCategory * pCat = category(szCatName);
+ pBuffer->setAutoDelete(false);
+ pBuffer->clear();
+ if(!pCat)return;
+ KviPointerHashTableIterator<QString,KviAction> it(*m_pActions);
+ while(KviAction * a = it.current())
+ {
+ if(a->category() == pCat)
+ pBuffer->append(a);
+ ++it;
+ }
+}
+
diff --git a/src/kvirc/kernel/kvi_actionmanager.h b/src/kvirc/kernel/kvi_actionmanager.h
new file mode 100644
index 00000000..c68e3f82
--- /dev/null
+++ b/src/kvirc/kernel/kvi_actionmanager.h
@@ -0,0 +1,118 @@
+#ifndef _KVI_ACTIONMANAGER_H_
+#define _KVI_ACTIONMANAGER_H_
+//=============================================================================
+//
+// File : kvi_actionmanager.h
+// Created on Sun 21 Nov 2004 03:37:57 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_action.h"
+
+#include <qobject.h>
+#include "kvi_pointerhashtable.h"
+
+class KviActionDrawer;
+class KviCustomToolBar;
+
+class KVIRC_API KviActionManager : public QObject
+{
+ friend class KviActionDrawer;
+ friend class KviCustomizeToolBarsDialog;
+ friend class KviCustomToolBar;
+ friend class KviFrame;
+ Q_OBJECT
+public:
+ KviActionManager();
+ ~KviActionManager();
+protected:
+ static KviActionManager * m_pInstance;
+ KviPointerHashTable<QString,KviAction> * m_pActions;
+ KviPointerHashTable<QString,KviActionCategory> * m_pCategories;
+ static bool m_bCustomizingToolBars;
+
+ // action categories
+ static KviActionCategory * m_pCategoryIrc;
+ static KviActionCategory * m_pCategoryGeneric;
+ static KviActionCategory * m_pCategorySettings;
+ static KviActionCategory * m_pCategoryScripting;
+ static KviActionCategory * m_pCategoryGUI;
+ static KviActionCategory * m_pCategoryChannel;
+ static KviActionCategory * m_pCategoryTools;
+ // internal , current toolbar to be edited (only when customizing)
+ static KviCustomToolBar * m_pCurrentToolBar;
+ bool m_bCoreActionsRegistered;
+public:
+ static void init();
+ static void done();
+ static KviActionManager * instance(){ return m_pInstance; };
+ static void loadAllAvailableActions();
+ static bool customizingToolBars(){ return m_bCustomizingToolBars; };
+ static KviActionCategory * categoryIrc(){ return m_pCategoryIrc; };
+ static KviActionCategory * categoryGeneric(){ return m_pCategoryGeneric; };
+ static KviActionCategory * categorySettings(){ return m_pCategorySettings; };
+ static KviActionCategory * categoryScripting(){ return m_pCategoryScripting; };
+ static KviActionCategory * categoryGUI(){ return m_pCategoryGUI; };
+ static KviActionCategory * categoryChannel(){ return m_pCategoryChannel; };
+ static KviActionCategory * categoryTools(){ return m_pCategoryTools; };
+
+ KviPointerHashTable<QString,KviAction> * actions(){ return m_pActions; };
+ KviActionCategory * category(const QString &szName);
+ KviPointerHashTable<QString,KviActionCategory> * categories(){ return m_pCategories; };
+
+ void killAllKvsUserActions();
+
+ static KviCustomToolBar * currentToolBar(){ return m_pCurrentToolBar; };
+ KviAction * getAction(const QString &szName);
+ void listActionsByCategory(const QString &szCatName,KviPointerList<KviAction> * pBuffer);
+ QString nameForAutomaticAction(const QString &szTemplate);
+ bool coreActionExists(const QString &szName);
+
+ void load(const QString &szFileName);
+ void save(const QString &szFileName);
+
+ bool registerAction(KviAction * a);
+ bool unregisterAction(const QString &szName);
+
+ void emitRemoveActionsHintRequest();
+protected:
+ void setCurrentToolBar(KviCustomToolBar * t);
+ KviAction * findAction(const QString &szName){ return m_pActions->find(szName); };
+ void customizeToolBarsDialogCreated();
+ void customizeToolBarsDialogDestroyed();
+ void tryFindCurrentToolBar();
+ void delayedRegisterAccelerators(); // this is called ONCE by KviFrame, at startup
+protected slots:
+ void actionDestroyed();
+signals:
+ void beginCustomizeToolBars();
+ void endCustomizeToolBars();
+ void currentToolBarChanged(); // emitted only when customizing!
+ void removeActionsHintRequest(); // connected by the KviCustomToolBarDialog to flash the trashcan
+ // when the user tries to remove an action from the toolbar
+ // and it fails to drag it on the trashcan
+};
+
+#define ACTION_POPUP_ITEM(__name,__popup) \
+ { KviAction * a = KviActionManager::instance()->getAction(__name); if(a)a->addToPopupMenu(__popup); }
+
+
+#endif //!_KVI_ACTIONMANAGER_H_
diff --git a/src/kvirc/kernel/kvi_app.cpp b/src/kvirc/kernel/kvi_app.cpp
new file mode 100644
index 00000000..2e66d2ba
--- /dev/null
+++ b/src/kvirc/kernel/kvi_app.cpp
@@ -0,0 +1,2074 @@
+//=============================================================================
+//
+// File : kvi_app.cpp
+// Creation date : Sun Jun 18 2000 12:39:45 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#define _KVI_APP_CPP_
+
+#include "kvi_socket.h"
+#include "kvi_app.h"
+#include "kvi_debug.h"
+#include "kvi_frame.h"
+#include "kvi_msgbox.h"
+#include "kvi_iconmanager.h"
+#include "kvi_input.h"
+#include "kvi_config.h"
+#include "kvi_colorwin.h"
+#include "kvi_window.h"
+#include "kvi_ircserverdb.h"
+#include "kvi_proxydb.h"
+#include "kvi_menubar.h"
+#include "kvi_options.h"
+#include "kvi_sparser.h"
+#include "kvi_modulemanager.h"
+#include "kvi_mediatype.h"
+#include "kvi_regusersdb.h"
+#include "kvi_thread.h"
+#include "kvi_sharedfiles.h"
+#include "kvi_confignames.h"
+#include "kvi_taskbar.h"
+#include "kvi_defaults.h"
+#include "kvi_locale.h"
+#include "kvi_out.h"
+#include "kvi_splash.h"
+#include "kvi_nickserv.h"
+#include "kvi_xlib.h"
+#include "kvi_garbage.h"
+#include "kvi_texticonmanager.h"
+#include "kvi_texticonwin.h"
+#include "kvi_historywin.h"
+#include "kvi_ctcppagedialog.h"
+#include "kvi_regchan.h"
+#include "kvi_moduleextension.h"
+#include "kvi_internalcmd.h"
+#include "kvi_filetransfer.h"
+#include "kvi_kvs.h"
+#include "kvi_ircurl.h"
+#include "kvi_avatarcache.h"
+#include "kvi_actionmanager.h"
+#include "kvi_customtoolbarmanager.h"
+#include "kvi_fileutils.h"
+#include "kvi_time.h"
+#include "kvi_doublebuffer.h"
+#include "kvi_stringconversion.h"
+#include "kvi_useridentity.h"
+
+#ifndef COMPILE_NO_IPC
+ #include "kvi_ipc.h"
+#endif
+
+#include "kvi_kvs_script.h"
+#include "kvi_kvs_popupmanager.h"
+#include "kvi_kvs_kernel.h"
+#include "kvi_kvs_object_controller.h"
+#include "kvi_kvs_eventtriggers.h"
+#include "kvi_sourcesdate.h"
+
+#include "kvi_tal_popupmenu.h"
+#include <qsplitter.h>
+#include <qstringlist.h>
+#include "kvi_pointerhashtable.h"
+#include <qmime.h>
+#ifdef COMPILE_USE_QT4
+ #include <q3mimefactory.h>
+#endif
+#include "kvi_tal_listbox.h"
+#include <qclipboard.h>
+#include <qmessagebox.h>
+#include <qtextcodec.h>
+#include <qmetaobject.h>
+
+#ifdef COMPILE_SSL_SUPPORT
+ #include "kvi_ssl.h"
+#endif
+
+#ifdef COMPILE_USE_QT4
+#ifdef COMPILE_ON_WINDOWS
+#include <QPluginLoader>
+#endif
+#endif
+
+#ifdef COMPILE_USE_QT4
+ #include <QTextDocument>
+#else
+ #include <qstylesheet.h>
+#endif
+
+KVIRC_API KviApp * g_pApp = 0; // global application pointer
+
+KviConfig * g_pWinPropertiesConfig = 0;
+KVIRC_API KviIrcServerDataBase * g_pIrcServerDataBase = 0;
+KVIRC_API KviProxyDataBase * g_pProxyDataBase = 0;
+
+// Global windows
+
+KVIRC_API KviColorWindow * g_pColorWindow = 0;
+KVIRC_API KviTextIconWindow * g_pTextIconWindow = 0;
+KVIRC_API KviTalPopupMenu * g_pInputPopup = 0;
+KVIRC_API QStringList * g_pRecentTopicList = 0;
+//KVIRC_API QStringList * g_pBookmarkList = 0;
+KVIRC_API KviPointerHashTable<const char *,KviWindow> * g_pGlobalWindowDict = 0;
+KVIRC_API KviMediaManager * g_pMediaManager = 0;
+//KVIRC_API KviRegisteredUserDataBase * g_pRegisteredUserDataBase = 0;
+KVIRC_API KviSharedFilesManager * g_pSharedFilesManager = 0;
+KVIRC_API KviNickServRuleSet * g_pNickServRuleSet = 0;
+//KVIRC_API KviTimerManager * g_pTimerManager = 0;
+KVIRC_API KviGarbageCollector * g_pGarbageCollector = 0;
+KVIRC_API KviCtcpPageDialog * g_pCtcpPageDialog = 0;
+KVIRC_API KviRegisteredChannelDataBase * g_pRegisteredChannelDataBase = 0;
+KVIRC_API KviInputHistory * g_pInputHistory = 0;
+KVIRC_API KviHistoryWindow * g_pHistoryWindow = 0;
+
+
+KVIRC_API int g_iIdentDaemonRunningUsers = 0; // this is eventually set by libkviident
+
+KVIRC_API KviSplashScreen * g_pSplashScreen = 0;
+
+
+// Loaded and destroyed by KviIconManager
+QPixmap * g_pUserChanStatePixmap = 0;
+QPixmap * g_pActivityMeterPixmap = 0;
+
+
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+
+ #ifdef COMPILE_KDE_SUPPORT
+ #include <ksharedpixmap.h>
+ #include <netwm.h>
+ #include <kimageeffect.h>
+ #include <dcopclient.h>
+ #include <qdatastream.h>
+ #include <qcstring.h>
+
+ KSharedPixmap * g_pKdeDesktopBackground = 0; // the shared pixmap that we get from KWin
+ #endif
+
+ #include <qimage.h>
+
+ KVIRC_API QPixmap * g_pShadedParentGlobalDesktopBackground = 0; // the pixmap that we use for MdiManager
+ KVIRC_API QPixmap * g_pShadedChildGlobalDesktopBackground = 0; // the pixmap that we use for MdiChild
+#endif
+
+#ifdef COMPILE_CRYPT_SUPPORT
+ #include "kvi_crypt.h"
+ KVIRC_API KviCryptEngineManager * g_pCryptEngineManager = 0; // global crypt engine manager
+#endif
+
+KviApp::KviApp(int &argc,char ** argv)
+: KviTalApplication(argc,argv)
+{
+ // Ok...everything begins here
+ g_pApp = this;
+ m_szConfigFile = QString::null;
+ m_bCreateConfig = false;
+ m_bShowSplashScreen = true;
+ m_bUpdateGuiPending = false;
+ m_pPendingAvatarChanges = 0;
+ m_pRecentChannelsDict = 0;
+ m_pIpcSentinel = 0;
+ m_iHeartbeatTimerId = -1;
+ // next step is setup()
+ m_bSetupDone = false;
+ kvi_socket_flushTrafficCounters();
+}
+
+void KviApp::setup()
+{
+ // Here we start up all the substystems.
+ // This is a really critical phase since in general subsystems depend
+ // on each other and we must activate them in the right order.
+ // Don't move stuff around unless you really know what you're doing.
+
+#ifdef COMPILE_ON_WINDOWS
+ // setup winsock.dll
+ WSADATA w;
+ WSAStartup(MAKELONG((unsigned short)2,(unsigned short)0),&w);
+#endif
+
+#ifndef COMPILE_NO_IPC
+ // Create this very early
+ // FIXME: this is still not early enough... we actually HAVE race conditions (should use a file for locking this ?)
+ createIpcSentinel();
+#endif
+
+ // Initialize the thread manager early
+ KviThreadManager::globalInit();
+
+#ifdef COMPILE_SSL_SUPPORT
+ KviSSL::globalInit();
+#endif
+
+ // Setup our filesystem and initalize locale
+ loadDirectories();
+ KviStringConversion::init(m_szGlobalKvircDir,m_szLocalKvircDir);
+
+#ifdef COMPILE_USE_QT4
+#ifdef COMPILE_ON_WINDOWS
+ //need to load image plugins:(
+ QString szPluginsDir;
+ getGlobalKvircDirectory(szPluginsDir,None,"qt-plugins/");
+ setLibraryPaths(QStringList(szPluginsDir));
+ //KviMessageBox::information(libraryPaths().join(";"));
+ //debug("%1",loader.isLoaded());
+#endif
+#endif
+
+ // check if we want to permanently disable the splash screen
+ // we do it once for every version: the user should see the new splash screens at least once
+
+ QString szSplashDisableFile;
+ getLocalKvircDirectory(szSplashDisableFile,Pics,"disable-splash." KVI_VERSION);
+
+ if(KviFileUtils::fileExists(szSplashDisableFile))
+ m_bShowSplashScreen = false;
+
+ // Now we can create the splash screen (we can locate the splash image)
+ if(m_bShowSplashScreen)
+ createSplashScreen();
+
+ KVI_SPLASH_SET_PROGRESS(0)
+
+ // Make sure that the C strings are translated to utf8
+ // This is a fallback solution anyway: we should use the appropriate
+ // encoding every time.
+ QTextCodec::setCodecForCStrings(KviLocale::codecForName("UTF-8"));
+
+ // Set the default help files search path
+ QStringList list;
+ QString tmp;
+ getLocalKvircDirectory(tmp,Help); // localized help/lang or help if help/lang doesn't exist
+ list.append(tmp);
+ getLocalKvircDirectory(tmp,HelpEN); // help/en
+ list.append(tmp);
+ getLocalKvircDirectory(tmp,HelpNoIntl); // just help/
+ list.append(tmp);
+ getGlobalKvircDirectory(tmp,Help);
+ list.append(tmp);
+ getGlobalKvircDirectory(tmp,HelpEN);
+ list.append(tmp);
+ getGlobalKvircDirectory(tmp,HelpNoIntl);
+ list.append(tmp);
+#ifdef COMPILE_USE_QT4
+ Q3MimeSourceFactory::defaultFactory()->setFilePath(list);
+#else
+ QMimeSourceFactory::defaultFactory()->setFilePath(list);
+#endif
+
+ KVI_SPLASH_SET_PROGRESS(1)
+
+ // Initialize the scripting engine
+ KviKvs::init();
+
+ KVI_SPLASH_SET_PROGRESS(2)
+
+ // Initialize the action manager
+ KviActionManager::init();
+
+ KVI_SPLASH_SET_PROGRESS(3)
+
+ // Create the module manager early: so the other managers can load modules
+ g_pModuleExtensionManager = new KviModuleExtensionManager();
+ g_pModuleManager = new KviModuleManager();
+
+ KVI_SPLASH_SET_PROGRESS(4);
+
+ g_pIconManager = new KviIconManager();
+
+ KVI_SPLASH_SET_PROGRESS(5)
+
+ if(getReadOnlyConfigPath(tmp,KVI_CONFIGFILE_USERACTIONS))
+ KviActionManager::instance()->load(tmp);
+
+ KVI_SPLASH_SET_PROGRESS(8);
+
+ // Initialize and load the identities
+ KviUserIdentityManager::init();
+
+ KVI_SPLASH_SET_PROGRESS(9);
+
+ if(getReadOnlyConfigPath(tmp,KVI_CONFIGFILE_IDENTITIES))
+ KviUserIdentityManager::instance()->load(tmp);
+
+ KVI_SPLASH_SET_PROGRESS(12);
+
+ // Load the remaining configuration
+ // Note that loadOptions() assumes that the current progress is 12 and
+ // will bump it up to 45 in small steps
+ loadOptions();
+
+ KVI_SPLASH_SET_PROGRESS(47)
+
+ // set the global font if needed
+ updateApplicationFont();
+
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ updatePseudoTransparency();
+#endif
+
+ KVI_SPLASH_SET_PROGRESS(48)
+
+ // Load the win properties config
+ getLocalKvircDirectory(tmp,Config,KVI_CONFIGFILE_WINPROPERTIES);
+ g_pWinPropertiesConfig = new KviConfig(tmp,KviConfig::ReadWrite);
+
+ KVI_SPLASH_SET_PROGRESS(50)
+
+ // Load the server database
+ g_pIrcServerDataBase = new KviIrcServerDataBase();
+ if(getReadOnlyConfigPath(tmp,KVI_CONFIGFILE_SERVERDB))
+ g_pIrcServerDataBase->load(tmp);
+
+ KVI_SPLASH_SET_PROGRESS(53)
+
+ // Load the proxy database
+ g_pProxyDataBase = new KviProxyDataBase();
+ if(getReadOnlyConfigPath(tmp,KVI_CONFIGFILE_PROXYDB))
+ g_pProxyDataBase->load(tmp);
+
+ KVI_SPLASH_SET_PROGRESS(54)
+
+ // Event manager
+ if(getReadOnlyConfigPath(tmp,KVI_CONFIGFILE_EVENTS))
+ KviKvs::loadAppEvents(tmp);
+
+ KVI_SPLASH_SET_PROGRESS(59)
+
+ if(getReadOnlyConfigPath(tmp,KVI_CONFIGFILE_RAWEVENTS))
+ KviKvs::loadRawEvents(tmp);
+
+ KVI_SPLASH_SET_PROGRESS(62)
+
+ // Popup manager
+ if(getReadOnlyConfigPath(tmp,KVI_CONFIGFILE_POPUPS))
+ KviKvs::loadPopups(tmp);
+
+ KVI_SPLASH_SET_PROGRESS(67)
+
+ KviCustomToolBarManager::init();
+ if(getReadOnlyConfigPath(tmp,KVI_CONFIGFILE_CUSTOMTOOLBARS))
+ KviCustomToolBarManager::instance()->load(tmp);
+ // THIS IS A COMPATIBILITY ENTRY ADDED AT 3.0.2 TIME THAT SHOULD BE DROPPED IN A COUPLE OF VERSION BUMPS!
+ getLocalKvircDirectory(tmp,Config,KVI_CONFIGFILE_SCRIPTTOOLBARS);
+ if(KviFileUtils::fileExists(tmp))
+ KviCustomToolBarManager::instance()->loadScripttoolbarsCompat(tmp);
+ // EOF COMPATIBILITY
+
+ KVI_SPLASH_SET_PROGRESS(70)
+
+ // Alias manager
+ if(getReadOnlyConfigPath(tmp,KVI_CONFIGFILE_ALIASES))
+ KviKvs::loadAliases(tmp);
+
+ KVI_SPLASH_SET_PROGRESS(75)
+
+ // Script addons manager (this in fact has delayed loading, so we don't even care
+ // about showing up an entry in the splash screen)
+ if(getReadOnlyConfigPath(tmp,KVI_CONFIGFILE_SCRIPTADDONS))
+ KviKvs::loadScriptAddons(tmp);
+
+ KVI_SPLASH_SET_PROGRESS(77)
+
+ g_pTextIconManager = new KviTextIconManager();
+ g_pTextIconManager->load();
+
+ KVI_SPLASH_SET_PROGRESS(80)
+
+ // load the recent data lists
+ g_pRecentTopicList = new QStringList();
+ //g_pBookmarkList = new QStringList();
+ loadRecentEntries();
+
+ KVI_SPLASH_SET_PROGRESS(81)
+
+ // media manager
+ g_pMediaManager = new KviMediaManager();
+ g_pMediaManager->lock();
+ if(getReadOnlyConfigPath(tmp,KVI_CONFIGFILE_MEDIATYPES))
+ g_pMediaManager->load(tmp);
+ g_pMediaManager->unlock();
+
+
+ KVI_SPLASH_SET_PROGRESS(82)
+
+ // registered user data base
+ g_pRegisteredUserDataBase = new KviRegisteredUserDataBase();
+ if(getReadOnlyConfigPath(tmp,KVI_CONFIGFILE_REGUSERDB))
+ g_pRegisteredUserDataBase->load(tmp);
+
+ KVI_SPLASH_SET_PROGRESS(84)
+
+ // registered channel data base
+ g_pRegisteredChannelDataBase = new KviRegisteredChannelDataBase();
+ if(getReadOnlyConfigPath(tmp,KVI_CONFIGFILE_REGCHANDB))
+ g_pRegisteredChannelDataBase->load(tmp);
+
+ KVI_SPLASH_SET_PROGRESS(85)
+
+ // file trader
+ g_pSharedFilesManager = new KviSharedFilesManager();
+ if(getReadOnlyConfigPath(tmp,KVI_CONFIGFILE_SHAREDFILES))
+ g_pSharedFilesManager->load(tmp);
+
+ KVI_SPLASH_SET_PROGRESS(86)
+
+ // nick serv data base
+ g_pNickServRuleSet = new KviNickServRuleSet();
+ if(getReadOnlyConfigPath(tmp,KVI_CONFIGFILE_NICKSERVDATABASE))
+ g_pNickServRuleSet->load(tmp);
+
+ KVI_SPLASH_SET_PROGRESS(88)
+
+ g_pInputHistory = new KviInputHistory();
+ if(getReadOnlyConfigPath(tmp,KVI_CONFIGFILE_INPUTHISTORY))
+ g_pInputHistory->load(tmp);
+
+ KVI_SPLASH_SET_PROGRESS(89)
+ KviAvatarCache::init();
+ if(getReadOnlyConfigPath(tmp,KVI_CONFIGFILE_AVATARCACHE))
+ KviAvatarCache::instance()->load(tmp);
+
+ KVI_SPLASH_SET_PROGRESS(90)
+
+ // Eventually initialize the crypt engine manager
+#ifdef COMPILE_CRYPT_SUPPORT
+ g_pCryptEngineManager = new KviCryptEngineManager();
+#endif
+
+ g_pGarbageCollector = new KviGarbageCollector();
+
+ // and the input popup
+ g_pInputPopup = new KviTalPopupMenu();
+
+ // create the server parser
+ g_pServerParser = new KviServerParser();
+
+ KVI_SPLASH_SET_PROGRESS(91)
+
+ // Global window dictionary
+ g_pGlobalWindowDict = new KviPointerHashTable<const char *,KviWindow>(41);
+ g_pGlobalWindowDict->setAutoDelete(false);
+ // Script object controller
+ //g_pScriptObjectController = new KviScriptObjectController(); gone
+
+ KVI_SPLASH_SET_PROGRESS(92)
+
+ KviDoubleBuffer::init();
+
+#ifdef COMPILE_USE_QT4
+ QString szStylesheetFile;
+ getGlobalKvircDirectory(szStylesheetFile,Config,"style.css");
+ if(KviFileUtils::fileExists(szStylesheetFile))
+ {
+ QString szStyleData;
+ KviFileUtils::readFile(szStylesheetFile,szStyleData);
+ szStyleData.replace("global://",m_szGlobalKvircDir);
+ szStyleData.replace("local://",m_szLocalKvircDir);
+ setStyleSheet(szStyleData);
+ }
+#endif
+
+ // create the frame window, we're almost up and running...
+ createFrame();
+
+ // ok, we also have an UI now
+
+ // check if this is the first time this version of KVIrc runs...
+ if(firstTimeRun())
+ {
+ // Finish the setup...
+ setupFinish();
+ }
+
+ // hello world!
+ m_bSetupDone = true;
+
+ // We're REALLY up and running!
+ // kill the splash screen
+
+ KVI_SPLASH_SET_PROGRESS(100)
+ //KVI_SPLASH_SET_TEXT(__tr2qs("Have fun! :)"))
+
+ if(KVI_OPTION_BOOL(KviOption_boolShowServersConnectDialogOnStart))
+ g_pFrame->executeInternalCommand(KVI_INTERNALCOMMAND_SERVERSJOIN_OPEN);
+
+ destroySplashScreen();
+
+ // check if we're in trouble...
+ checkSuggestRestoreDefaultScript();
+
+ // start our heartbeat now
+ m_iHeartbeatTimerId = startTimer(1000);
+}
+
+void KviApp::frameDestructorCallback()
+{
+ // here we should kill anything that depends on g_pFrame , g_pActiveWindow and related being non zero...
+
+ // kill all the objects, while we have windows...
+ if(KviKvsKernel::instance())
+ {
+ if(KviKvsKernel::instance()->objectController())
+ {
+ KviKvsKernel::instance()->objectController()->clearInstances();
+ }
+ }
+}
+
+
+
+KviApp::~KviApp()
+{
+ // Another critical phase.
+ // We shutdown our subsystems in the right order here.
+
+#ifndef COMPILE_NO_IPC
+ destroyIpcSentinel();
+#endif
+
+ if(g_pSplashScreen)delete g_pSplashScreen;
+ if(g_pCtcpPageDialog)delete g_pCtcpPageDialog;
+
+ // if we still have a frame: kill it
+ if(g_pFrame)delete g_pFrame;
+ g_pActiveWindow = 0; // .. but it should be already 0 anyway
+
+ // execute pending deletes (this may still contain some UI elements)
+ delete g_pGarbageCollector;
+
+ if(!m_bSetupDone)return; // killed with IPC (nothing except the m_pFrameList was created yet)
+
+ KviFileTransferManager::cleanup();
+
+ // No more events are triggered from now on and no KVS commands are executed
+
+ // Dangerous part.... we're unloading all the modules
+ // We need to unload them early since they may use other subsystems
+ // that we are going to kill now.
+ delete g_pModuleManager;
+ delete g_pModuleExtensionManager;
+ // No more external modules exist: all that happens from now is generated
+ // from inside the kvirc core.
+
+ // We should have almost no UI here: only certain dialogs or popup windows may
+ // still exist: they should be harmless tough.
+ saveOptions();
+ saveIdentities();
+ KviUserIdentityManager::done();
+ if(m_pRecentChannelsDict) delete m_pRecentChannelsDict;
+ // now kill the stuff that the frame depends on
+ saveIrcServerDataBase();
+ delete g_pIrcServerDataBase;
+ saveProxyDataBase();
+ delete g_pProxyDataBase;
+ delete g_pWinPropertiesConfig;
+ saveTextIcons();
+ if(g_pTextIconWindow)delete g_pTextIconWindow;
+ delete g_pTextIconManager;
+ delete g_pIconManager;
+ delete g_pServerParser;
+ saveMediaTypes();
+ delete g_pMediaManager;
+ saveRecentEntries();
+ saveAvatarCache();
+ KviAvatarCache::done();
+ //delete g_pBookmarkList;
+ delete g_pRecentTopicList;
+ saveRegisteredUsers();
+ delete g_pRegisteredUserDataBase;
+ saveRegisteredChannels();
+ delete g_pRegisteredChannelDataBase;
+ saveNickServ();
+ delete g_pNickServRuleSet;
+ saveSharedFiles();
+ delete g_pSharedFilesManager;
+ saveAppEvents();
+ saveRawEvents();
+ saveToolBars();
+ KviCustomToolBarManager::done();
+ savePopups();
+ saveAliases();
+ delete g_pGlobalWindowDict;
+ saveScriptAddons();
+ // kill the remaining resources
+ delete g_pColorWindow;
+ if(g_pHistoryWindow)delete g_pHistoryWindow;
+ saveInputHistory();
+ delete g_pInputHistory;
+ delete g_pInputPopup;
+ //delete g_pScriptObjectController;
+#ifdef COMPILE_CRYPT_SUPPORT
+ delete g_pCryptEngineManager;
+#endif
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ destroyPseudoTransparency();
+#endif
+ KviDoubleBuffer::done();
+ if(m_pPendingAvatarChanges)delete m_pPendingAvatarChanges;
+ // Kill the thread manager.... all the slave threads should have been already terminated ...
+#ifdef COMPILE_SSL_SUPPORT
+ KviSSL::globalDestroy();
+#endif
+ KviThreadManager::globalDestroy();
+ // kill the scripting engine
+ KviKvs::done();
+ // shut up the action manager
+ saveActions();
+ KviActionManager::done();
+
+#ifdef COMPILE_ON_WINDOWS
+ WSACleanup();
+#endif
+
+ KviLocale::done(this);
+
+ // goodbye cruel world...
+}
+
+static int g_iGloballyUniqueId = 0;
+
+int KviApp::getGloballyUniqueId()
+{
+ g_iGloballyUniqueId++;
+ return g_iGloballyUniqueId;
+}
+
+typedef struct _NotifierMessageSupaDupaParameterStruct
+{
+ KviWindow * pWindow;
+ QString szIcon;
+ QString szMessage;
+ unsigned int uMessageLifetime; // 0 means no hide
+} NotifierMessageSupaDupaParameterStruct;
+
+void KviApp::notifierMessage(KviWindow * pWnd,int iIconId,const QString &szMsg,unsigned int uMessageLifetime)
+{
+ KviModule * m = g_pModuleManager->getModule("notifier");
+ if(!m)return;
+
+ NotifierMessageSupaDupaParameterStruct s;
+ s.pWindow = pWnd;
+ s.szIcon.sprintf("%d",iIconId);
+ s.szMessage = szMsg;
+ s.uMessageLifetime = uMessageLifetime;
+
+ m->ctrl("notifier::message",(void *)&s);
+}
+
+QTextCodec * KviApp::defaultTextCodec()
+{
+ QTextCodec * c = 0;
+ if(!KVI_OPTION_STRING(KviOption_stringDefaultTextEncoding).isEmpty())
+ {
+ c = KviLocale::codecForName(KVI_OPTION_STRING(KviOption_stringDefaultTextEncoding).latin1());
+ if(c)return c;
+ }
+ c = QTextCodec::codecForLocale();
+ if(c)return c;
+ c = KviLocale::codecForName("UTF-8");
+ if(!c)debug("KviApp::defaultTextCodec(): cannot find a suitable text codec for locale :/");
+ return c;
+}
+
+void KviApp::contextSensitiveHelp()
+{
+ // this stuff doesn't work with Qt 4.x
+#ifndef COMPILE_USE_QT4
+ // the F1 Key has been pressed
+ // try to pass it to the active widget or one of its parents
+ QWidget * w = g_pApp->focusWidget();
+ while(w)
+ {
+ //QVariant v = w->property("contextSensitiveHelp"); <-- this prints a lot of warnings: this is a QT BUG
+ QMetaObject * o = w->metaObject();
+ if(o)
+ {
+ int i = o->findProperty("contextSensitiveHelp",true);
+ if(i != -1)
+ {
+ QVariant v = w->property("contextSensitiveHelp");
+ if(v.isValid() && v.toBool())
+ return; // done!
+ }
+ }
+ w = w->parentWidget();
+ }
+ // no way
+ // FIXME: just show up simple plain online help
+ //debug("No way: found no focus widget for that...");
+#endif
+}
+
+
+void KviApp::collectGarbage(QObject * garbage)
+{
+// if(!g_pGarbageCollector)debug("Ops... no garbage collector ?");
+ g_pGarbageCollector->collect(garbage);
+}
+
+void KviApp::loadDefaultScript()
+{
+ QString cmd;
+ getGlobalKvircDirectory(cmd,KviApp::DefScript,"default.kvs");
+ cmd.prepend("parse \"");
+ cmd.append("\"");
+#ifdef COMPILE_ON_WINDOWS
+ cmd.replace("\\","\\\\");
+#endif
+ KviKvsScript::run(cmd,g_pFrame->firstConsole());
+ // now line up the toolbars (they may get messed while loading the script)
+#ifndef COMPILE_USE_QT4
+ g_pFrame->lineUpDockWindows(); // missing on Qt 4.x
+#endif
+}
+
+// 07.01.2005 06:01: Got this curious gcc error while writing
+// the functions below...
+// The problem is gone by simply typing make again.
+// Memory/Disk transfer error ?
+//
+// if g++ -DHAVE_CONFIG_H -I. -I. -I../../../src -I/usr/build/kvirccvs/kvirc/src/kvilib/include/ -I/usr/build/kvirccvs/kvirc/src/kvirc/include/ -I/opt/qt/include -I/usr/X11R6/include -I/usr/X11R6/include -I/opt/kde/include -D_REENTRANT -DREENTRANT -I/usr/X11R6/include -DGLOBAL_KVIRC_DIR=\"/usr/local/share/kvirc/3.0.1.99\" -g -MT kvi_ircconnection.o -MD -MP -MF ".deps/kvi_ircconnection.Tpo"
+// -c -o kvi_ircconnection.o `test -f '../kernel/kvi_ircconnection.cpp' || echo './'`../kernel/kvi_ircconnection.cpp;
+// then mv -f ".deps/kvi_ircconnection.Tpo" ".deps/kvi_ircconnection.Po";
+// else rm -f ".deps/kvi_ircconnection.Tpo"; exit 1;
+// fi
+// /opt/qt/include/qstringlist.h:62: sorry, not implemented: `
+// expr_with_file_location' not supported by dump_decl
+// /opt/qt/include/qstringlist.h: In function `<declaration error>':
+// /opt/qt/include/qstringlist.h:62: internal error: Segmentation fault
+// Please submit a full bug report,
+// with preprocessed source if appropriate.
+// See <URL:http://bugzilla.redhat.com/bugzilla/> for instructions.
+
+
+void KviApp::checkSuggestRestoreDefaultScript()
+{
+ static bool bSuggestedOnce = false;
+ if(KVI_OPTION_BOOL(KviOption_boolDoNotSuggestRestoreDefaultScript))return;
+ if(bSuggestedOnce)return; // already suggested in this kvirc session
+
+ int score = 0;
+
+ if(KviCustomToolBarManager::instance()->descriptorCount() < 1)score += 100; // straight suggest
+ else if(KviKvsPopupManager::instance()->popupCount() < 1)score += 100; // straight suggest
+ else {
+ // other stuff is not that critical
+ if(!KviKvsEventManager::instance()->hasAppHandlers(KviEvent_OnChannelNickPopupRequest))score += 80;
+ if(!KviKvsEventManager::instance()->hasAppHandlers(KviEvent_OnDCCChatPopupRequest))score += 20;
+ if(!KviKvsEventManager::instance()->hasAppHandlers(KviEvent_OnConsolePopupRequest))score += 20;
+ if(!KviKvsEventManager::instance()->hasAppHandlers(KviEvent_OnChannelPopupRequest))score += 20;
+ if(!KviKvsEventManager::instance()->hasAppHandlers(KviEvent_OnChannelNickPopupRequest))score += 20;
+ if(!KviKvsEventManager::instance()->hasAppHandlers(KviEvent_OnQueryPopupRequest))score += 20;
+ if(!KviKvsEventManager::instance()->hasAppHandlers(KviEvent_OnQueryNickPopupRequest))score += 20;
+ if(KviCustomToolBarManager::instance()->descriptorCount() < 4)score += 20;
+ if(KviKvsPopupManager::instance()->popupCount() < 3)score += 20;
+ if(KviCustomToolBarManager::instance()->visibleToolBarCount() < 2)
+ {
+ score += 20;
+ if(KviCustomToolBarManager::instance()->visibleToolBarCount() < 1)score += 20;
+ }
+ }
+
+ if(score < 100)return;
+
+ bSuggestedOnce = true;
+
+ switch(QMessageBox::question(0,__tr2qs("Installation problems ?"),
+ __tr2qs("<b>Ooops...</b><br><br>" \
+ "<b>There are some reasons that make me think that your KVIrc installation is incomplete.</b><br><br>" \
+ "I might be wrong, but you seem to miss some of the features that the default KVIrc script provides." \
+ "This may happen because you have upgraded to an unstable cvs version, " \
+ "because you have accidentally deleted or damaged your configuration files, " \
+ "because you have installed an incomplete script " \
+ "or because you have hit a bug in KVIrc.<br><br>" \
+ "I can repeat the installation of the default script in order " \
+ "to restore the missing features.<br>" \
+ "<b>Do you want the default script to be restored ?</b><br><br>" \
+ "<font size=\"-1\">Hint: If you're a scripter and have intentionally removed some of the scripting features " \
+ "then you may safely click on \"No and Don't Ask Me Again\", otherwise it might be " \
+ "a good idea to click \"Yes\". If you still want to choose \"No\" you can always restore the " \
+ "default script by choosing the appropriate entry from the \"Scripting\" menu.</font>"),
+ __tr2qs("No and Don't Ask Me Again"),
+ __tr2qs("No"),
+ __tr2qs("Yes"),
+ 1,
+ 1))
+ {
+ case 0:
+ KVI_OPTION_BOOL(KviOption_boolDoNotSuggestRestoreDefaultScript) = true;
+ return;
+ break;
+ case 1:
+ return;
+ break;
+ default:
+ restoreDefaultScript();
+ break;
+ }
+}
+
+
+
+void KviApp::restoreDefaultScript()
+{
+ if(QMessageBox::warning(0,__tr2qs("Restore Default Script - KVIrc"),
+ __tr2qs("You are about to restore the default script.<br>This will erase any script changes you have made.<br>Do you wish to proceed?"),
+ QMessageBox::Yes,QMessageBox::No|QMessageBox::Default|QMessageBox::Escape) != QMessageBox::Yes)return;
+
+ KviKvs::clearAliases();
+ KviKvs::clearAppEvents();
+ KviKvs::clearRawEvents();
+ KviKvs::clearPopups();
+ KviKvs::clearScriptAddons();
+
+ KviActionManager::instance()->killAllKvsUserActions();
+ KviCustomToolBarManager::instance()->clear();
+
+ loadDefaultScript();
+
+ // and save settings to be sure...
+ saveOptions();
+}
+
+#ifndef COMPILE_NO_IPC
+
+
+void KviApp::createIpcSentinel()
+{
+ m_pIpcSentinel = new KviIpcSentinel();
+}
+
+void KviApp::destroyIpcSentinel()
+{
+ if(m_pIpcSentinel)delete m_pIpcSentinel;
+ m_pIpcSentinel = 0;
+}
+
+void KviApp::ipcMessage(char * message)
+{
+ if(!g_pFrame)return;
+ KviConsole * cns = g_pFrame->firstConsole();
+ if(!cns)return;
+ if(_OUTPUT_VERBOSE)
+ {
+ KviStr cmd = message;
+ if(cmd.len() > 30)cmd.cutRight(cmd.len() - 30);
+ int idx = cmd.findFirstIdx('\n');
+ if(idx != -1)cmd.cutRight(cmd.len() - (idx + 1));
+ cns->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Remote command received (%s ...)"),cmd.ptr());
+ }
+ KviKvsScript::run(message,cns);
+}
+
+#endif // COMPILE_NO_IPC
+
+
+void KviApp::createSplashScreen()
+{
+ g_pSplashScreen = new KviSplashScreen();
+ g_pSplashScreen->show();
+}
+
+void KviApp::destroySplashScreen()
+{
+ if(g_pSplashScreen)g_pSplashScreen->die();
+}
+
+
+QString KviApp::getClipboardText()
+{
+ /*
+ QString buffer;
+#if QT_VERSION >= 300
+ bool bOldMode = clipboard()->selectionModeEnabled();
+ clipboard()->setSelectionMode(false);
+#endif
+ buffer = clipboard()->text();
+#if QT_VERSION >= 300
+ if(buffer.isEmpty())
+ {
+ // lookup the global clipboard
+ clipboard()->setSelectionMode(true);
+ buffer = clipboard()->text();
+ }
+ clipboard()->setSelectionMode(bOldMode);
+#endif
+ return buffer;
+ */
+
+ QString buffer = clipboard()->text(QClipboard::Clipboard);
+ if(buffer.isEmpty())return clipboard()->text(QClipboard::Selection);
+ return buffer;
+}
+
+
+void KviApp::getClipboardText(KviStr &buffer)
+{
+ buffer = getClipboardText();
+}
+
+void KviApp::setClipboardText(const QString &str)
+{
+ /*
+#if QT_VERSION >= 300
+ if(clipboard()->supportsSelection())
+ {
+ bool bOldMode = clipboard()->selectionModeEnabled();
+ clipboard()->setSelectionMode(true);
+ clipboard()->setText(str);
+ clipboard()->setSelectionMode(false);
+ clipboard()->setText(str);
+ clipboard()->setSelectionMode(bOldMode);
+ } else {
+#endif
+ clipboard()->setText(str);
+#if QT_VERSION >= 300
+ }
+#endif*/
+ clipboard()->setText(str,QClipboard::Clipboard);
+ clipboard()->setText(str,QClipboard::Selection);
+}
+
+void KviApp::setClipboardText(const KviStr &str)
+{
+ debug("WARNING : KviApp::setClipboardText(const KviStr &) is deprecated!");
+ setClipboardText(QString(str.ptr()));
+}
+
+void KviApp::setAvatarFromOptions()
+{
+ KviPointerHashTableIterator<const char *,KviWindow> it(*g_pGlobalWindowDict);
+
+ while(it.current())
+ {
+ if(it.current()->type() == KVI_WINDOW_TYPE_CONSOLE)
+ {
+ ((KviConsole *)it.current())->setAvatarFromOptions();
+ }
+ ++it;
+ }
+
+}
+
+void KviApp::setAvatarOnFileReceived(KviConsole * pConsole,const QString &szRemoteUrl,const QString &szNick,const QString &szUser,const QString &szHost)
+{
+ if(!m_pPendingAvatarChanges)
+ {
+ m_pPendingAvatarChanges = new KviPointerList<KviPendingAvatarChange>;
+ m_pPendingAvatarChanges->setAutoDelete(true);
+ }
+
+ if(m_pPendingAvatarChanges->count() >= KVI_MAX_PENDING_AVATARS) // can't be...
+ {
+ m_pPendingAvatarChanges->removeFirst(); // kill the first entry
+ }
+
+ KviPendingAvatarChange * p = new KviPendingAvatarChange;
+ p->pConsole = pConsole;
+ p->szRemoteUrl = szRemoteUrl;
+ p->szNick = szNick;
+ p->szUser = szUser;
+ p->szHost = szHost;
+
+ m_pPendingAvatarChanges->append(p);
+}
+
+KviPendingAvatarChange * KviApp::findPendingAvatarChange(KviConsole * pConsole,const QString &szNick,const QString &szRemoteUrl)
+{
+ if(!m_pPendingAvatarChanges)return 0;
+
+ KviPendingAvatarChange * p;
+
+ for(p = m_pPendingAvatarChanges->first();p;p = m_pPendingAvatarChanges->next())
+ {
+ if(!pConsole || (p->pConsole == pConsole))
+ {
+ if(szNick.isNull() || (szNick == p->szNick))
+ {
+ if(szRemoteUrl == p->szRemoteUrl)return p;
+ }
+ }
+ }
+
+ return 0;
+}
+
+void KviApp::fileDownloadTerminated(bool bSuccess,const QString &szRemoteUrl,const QString &szLocalFileName,const QString &szNick,const QString &szError,bool bQuiet)
+{
+
+ KviPendingAvatarChange * p;
+
+ if(m_pPendingAvatarChanges)p = findPendingAvatarChange(0,szNick,szRemoteUrl);
+ else p = 0;
+
+ if(!p)
+ {
+ // signal dcc completion only for NON-avatars
+ // FIXME: This option is misnamed and misplaced in the options dialog :(
+ // it seems to refer only to DCC while it refers to any file transfer
+ if(KVI_OPTION_BOOL(KviOption_boolNotifyDccSendSuccessInNotifier) && (!bQuiet))
+ {
+ if(!g_pActiveWindow)return;
+ if(g_pActiveWindow->hasAttention())return;
+ QString szMsg;
+ int iIconId;
+ if(!bSuccess)
+ {
+ iIconId = KVI_SMALLICON_DCCERROR;
+ if(szNick.isEmpty())
+ szMsg = __tr2qs("File download failed");
+ else
+ szMsg = __tr2qs("File download from %1 failed").arg(szNick);
+ szMsg += ": ";
+ szMsg += szError;
+ szMsg += " (";
+ szMsg += szLocalFileName;
+ szMsg += ")";
+ } else {
+ iIconId = KVI_SMALLICON_DCCMSG;
+ if(szNick.isEmpty())
+ szMsg = __tr2qs("File download successfully complete");
+ else
+ szMsg = __tr2qs("File download from %1 successfully complete").arg(szNick);
+ szMsg += " (";
+ szMsg += szLocalFileName;
+ szMsg += ")";
+ }
+#ifdef COMPILE_USE_QT4
+ notifierMessage(0,iIconId,Qt::escape(szMsg),30);
+#else
+ notifierMessage(0,iIconId,QStyleSheet::escape(szMsg),30);
+#endif
+ }
+ return;
+ }
+
+ if(bSuccess)
+ {
+ if(windowExists(p->pConsole))
+ {
+ p->pConsole->setAvatar(p->szNick,p->szUser,p->szHost,
+ szLocalFileName,KviQString::equalCIN("http://",szRemoteUrl,7) ? szRemoteUrl : QString::null);
+ }
+ } else {
+ if((!_OUTPUT_MUTE) && (!bQuiet))
+ {
+ p->pConsole->output(KVI_OUT_AVATAR,__tr2qs("Avatar download failed for %Q!%Q@%Q and url %Q: %Q"),
+ &(p->szNick),&(p->szUser),&(p->szHost),&(szRemoteUrl),&(szError));
+ }
+ }
+
+ m_pPendingAvatarChanges->removeRef(p);
+
+ if(m_pPendingAvatarChanges->count() == 0)
+ {
+ delete m_pPendingAvatarChanges;
+ m_pPendingAvatarChanges = 0;
+ }
+}
+
+
+
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+
+ #ifdef COMPILE_KDE_SUPPORT
+
+ #include <netwm.h>
+
+ void KviApp::downloadKdeRootPixmap()
+ {
+ if(g_pKdeDesktopBackground)
+ {
+ delete g_pKdeDesktopBackground;
+ g_pKdeDesktopBackground = 0;
+ // this signal shouldn't be connected ,but well.. let's make sure
+ disconnect(this,SIGNAL(backgroundChanged(int)),this,SLOT(kdeRootPixmapChanged(int)));
+ }
+ g_pKdeDesktopBackground = 0;
+
+ // This has been extracted from the KDELIBS KRootPixmap interface
+#if 0
+ #warning "The following warning will disappear soon..."
+ // FIXME: this form should be used starting from KDE 3.2
+ unsigned long l = NET::CurrentDesktop;
+ NETRootInfo rinfo( qt_xdisplay(), &l ,1 ,-1,true);
+#else
+ NETRootInfo rinfo(qt_xdisplay(),NET::CurrentDesktop);
+#endif
+ rinfo.activate();
+
+ QString name = QString("DESKTOP%1").arg(rinfo.currentDesktop());
+
+ g_pKdeDesktopBackground = new KSharedPixmap();
+ connect(g_pKdeDesktopBackground,SIGNAL(done(bool)),this,SLOT(kdeRootPixmapDownloadComplete(bool)));
+
+ if(!(g_pKdeDesktopBackground->isAvailable(name)))
+ {
+ // Pixmap not available!!!
+ delete g_pKdeDesktopBackground;
+ g_pKdeDesktopBackground = 0;
+ if(m_bUpdatePseudoTransparencyPending)return; // Already sent a request....
+ // Send a request to kdesktop....
+ DCOPClient *client = kapp->dcopClient();
+ if(!client->isAttached())client->attach();
+ QByteArray data;
+ QDataStream args(data,IO_WriteOnly);
+ args << 1;
+ client->send("kdesktop","KBackgroundIface","setExport(int)",data);
+ m_bUpdatePseudoTransparencyPending = true;
+ // Now wait a while and try again....
+ QTimer::singleShot(500,this,SLOT(updatePseudoTransparency()));
+ return;
+ }
+
+ if(!g_pKdeDesktopBackground->loadFromShared(QString("DESKTOP%1").arg(rinfo.currentDesktop())))
+ {
+ debug("Can't load the KDE root background image...");
+ delete g_pKdeDesktopBackground;
+ g_pKdeDesktopBackground = 0;
+ } //else {
+ // debug("Root pixmap downalod initiated");
+ //}
+ }
+
+ #endif //COMPILE_KDE_SUPPORT
+
+ void KviApp::destroyPseudoTransparency()
+ {
+#ifdef COMPILE_KDE_SUPPORT
+ if(g_pKdeDesktopBackground)
+ {
+ delete g_pKdeDesktopBackground;
+ g_pKdeDesktopBackground = 0;
+ }
+ // forget the backgroundChanged signal (will do nothing if it is not connected)
+ disconnect(this,SIGNAL(backgroundChanged(int)),this,SLOT(kdeRootPixmapChanged(int)));
+#endif //COMPILE_KDE_SUPPORT
+ if(g_pShadedParentGlobalDesktopBackground)
+ {
+ delete g_pShadedParentGlobalDesktopBackground;
+ g_pShadedParentGlobalDesktopBackground = 0;
+ }
+ if(g_pShadedChildGlobalDesktopBackground)
+ {
+ delete g_pShadedChildGlobalDesktopBackground;
+ g_pShadedChildGlobalDesktopBackground = 0;
+ }
+ }
+
+ void KviApp::triggerUpdatePseudoTransparency()
+ {
+ if(m_bUpdatePseudoTransparencyPending)return;
+ m_bUpdatePseudoTransparencyPending = true;
+ QTimer::singleShot(0,this,SLOT(updatePseudoTransparency()));
+ }
+
+#ifdef COMPILE_KDE_SUPPORT
+
+ #define kimageeffect_fade KImageEffect::fade
+
+#else //!COMPILE_KDE_SUPPORT
+
+ //
+ // This function is taken from the KDE kimageeffect.cpp
+ // The authors listed at the top of the file are :)
+ // Copyright (C) 1998, 1999 Christian Tibirna <ctibirna@total.net>
+ // (C) 1998, 1999 Daniel M. Duley <mosfet@kde.org>
+ // (C) 1998, 1999 Dirk A. Mueller <mueller@kde.org>
+ // (C) 2000 Josef Weidendorfer <weidendo@in.tum.de>
+ //
+
+ QImage& kimageeffect_fade(QImage &img,float val,const QColor &color)
+ {
+ if(img.width() == 0 || img.height() == 0)return img;
+
+ // We don't handle bitmaps
+ if (img.depth() == 1)return img;
+
+ unsigned char tbl[256];
+ for (int i=0; i<256; i++)tbl[i] = (int) (val * i + 0.5);
+
+ int red = color.red();
+ int green = color.green();
+ int blue = color.blue();
+
+ QRgb col;
+ int r, g, b, cr, cg, cb;
+
+ if (img.depth() <= 8)
+ {
+ // pseudo color
+ for(int i=0; i<img.numColors(); i++)
+ {
+ col = img.color(i);
+ cr = qRed(col); cg = qGreen(col); cb = qBlue(col);
+ if (cr > red)r = cr - tbl[cr - red];
+ else r = cr + tbl[red - cr];
+ if (cg > green)g = cg - tbl[cg - green];
+ else g = cg + tbl[green - cg];
+ if (cb > blue)b = cb - tbl[cb - blue];
+ else b = cb + tbl[blue - cb];
+ img.setColor(i, qRgb(r, g, b));
+ }
+ } else {
+ // truecolor
+ for(int y=0; y<img.height(); y++)
+ {
+ QRgb *data = (QRgb *) img.scanLine(y);
+ for (int x=0; x<img.width(); x++)
+ {
+ col = *data;
+ cr = qRed(col); cg = qGreen(col); cb = qBlue(col);
+ if (cr > red)r = cr - tbl[cr - red];
+ else r = cr + tbl[red - cr];
+ if (cg > green)g = cg - tbl[cg - green];
+ else g = cg + tbl[green - cg];
+ if (cb > blue)b = cb - tbl[cb - blue];
+ else b = cb + tbl[blue - cb];
+ *data++ = qRgb(r, g, b);
+ }
+ }
+ }
+ return img;
+ }
+
+#endif //!COMPILE_KDE_SUPPORT
+
+ void KviApp::createGlobalBackgrounds(QPixmap * pix)
+ {
+ // create shaded copies...
+ if(g_pShadedParentGlobalDesktopBackground)delete g_pShadedParentGlobalDesktopBackground;
+ if(g_pShadedChildGlobalDesktopBackground)delete g_pShadedChildGlobalDesktopBackground;
+ g_pShadedParentGlobalDesktopBackground = new QPixmap();
+ g_pShadedChildGlobalDesktopBackground = new QPixmap();
+ QImage img = pix->convertToImage();
+ // play with the fade factors
+ KVI_OPTION_UINT(KviOption_uintGlobalTransparencyParentFadeFactor) %= 100;
+ if(KVI_OPTION_UINT(KviOption_uintGlobalTransparencyParentFadeFactor) > 0)
+ {
+ g_pShadedParentGlobalDesktopBackground->convertFromImage(
+ kimageeffect_fade(img,
+ (float)((float)KVI_OPTION_UINT(KviOption_uintGlobalTransparencyParentFadeFactor) / (float)100),
+ KVI_OPTION_COLOR(KviOption_colorGlobalTransparencyFade)),0);
+ }
+ KVI_OPTION_UINT(KviOption_uintGlobalTransparencyChildFadeFactor) %= 100;
+ if(KVI_OPTION_UINT(KviOption_uintGlobalTransparencyChildFadeFactor) > 0)
+ {
+ g_pShadedChildGlobalDesktopBackground->convertFromImage(
+ kimageeffect_fade(img,
+ (float)((float)KVI_OPTION_UINT(KviOption_uintGlobalTransparencyChildFadeFactor) / (float)100),
+ KVI_OPTION_COLOR(KviOption_colorGlobalTransparencyFade)),0);
+ }
+ if(g_pFrame)g_pFrame->updatePseudoTransparency();
+ }
+
+#endif //COMPILE_PSEUDO_TRANSPARENCY
+
+void KviApp::kdeRootPixmapChanged(int iDesktop)
+{
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ #ifdef COMPILE_KDE_SUPPORT
+ if(!KVI_OPTION_BOOL(KviOption_boolUpdateKdeBackgroundOnChange))return;
+ NETRootInfo rinfo(qt_xdisplay(),NET::CurrentDesktop);
+ rinfo.activate();
+ if(iDesktop == rinfo.currentDesktop())
+ updatePseudoTransparency();
+ #endif
+#endif //COMPILE_PSEUDO_TRANSPARENCY
+}
+
+void KviApp::kdeRootPixmapDownloadComplete(bool bSuccess)
+{
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ #ifdef COMPILE_KDE_SUPPORT
+ if(!bSuccess)
+ {
+ debug("Failed to download the KDE root background image...");
+ } else {
+ // downloaded!
+ // create shaded copies...
+ createGlobalBackgrounds(g_pKdeDesktopBackground);
+ // make sure that this signal is not connected twice
+ disconnect(this,SIGNAL(backgroundChanged(int)),this,SLOT(kdeRootPixmapChanged(int)));
+ // connect it
+ connect(this,SIGNAL(backgroundChanged(int)),this,SLOT(kdeRootPixmapChanged(int)));
+ }
+ delete g_pKdeDesktopBackground;
+ g_pKdeDesktopBackground = 0;
+ #endif //COMPILE_KDE_SUPPORT
+#endif //COMPILE_PSEUDO_TRANSPARENCY
+}
+
+
+void KviApp::updatePseudoTransparency()
+{
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ m_bUpdatePseudoTransparencyPending = false;
+ if(KVI_OPTION_BOOL(KviOption_boolUseGlobalPseudoTransparency))
+ {
+#ifdef COMPILE_KDE_SUPPORT
+ if(KVI_OPTION_BOOL(KviOption_boolObtainGlobalBackgroundFromKde))
+ {
+ downloadKdeRootPixmap();
+ } else {
+#endif //COMPILE_KDE_SUPPORT
+ if(KVI_OPTION_PIXMAP(KviOption_pixmapGlobalTransparencyBackground).pixmap())
+ {
+ createGlobalBackgrounds(KVI_OPTION_PIXMAP(KviOption_pixmapGlobalTransparencyBackground).pixmap());
+ } else {
+ destroyPseudoTransparency();
+ KVI_OPTION_BOOL(KviOption_boolUseGlobalPseudoTransparency) = false;
+ }
+#ifdef COMPILE_KDE_SUPPORT
+ }
+#endif //COMPILE_KDE_SUPPORT
+ } else {
+ destroyPseudoTransparency();
+ if(g_pFrame)g_pFrame->updatePseudoTransparency();
+ }
+#endif //COMPILE_PSEUDO_TRANSPARENCY
+}
+
+
+void KviApp::triggerUpdateGui()
+{
+ if(m_bUpdateGuiPending)return;
+ m_bUpdateGuiPending = true;
+ QTimer::singleShot(0,this,SLOT(updateGui()));
+}
+
+void KviApp::updateGui()
+{
+ m_bUpdateGuiPending = false;
+ g_pFrame->applyOptions();
+}
+
+void KviApp::updateApplicationFont()
+{
+ if(KVI_OPTION_BOOL(KviOption_boolUseGlobalApplicationFont))
+ {
+ if(font() != KVI_OPTION_FONT(KviOption_fontApplication))
+ setFont(KVI_OPTION_FONT(KviOption_fontApplication),true);
+ }
+ // FIXME: #warning "And what if this option is turned off ?...a reboot only"
+}
+
+void KviApp::loadRecentEntries()
+{
+ QString tmp;
+ getLocalKvircDirectory(tmp,Config,KVI_CONFIGFILE_RECENT);
+ KviConfig cfg(tmp,KviConfig::Read);
+ *g_pRecentTopicList = cfg.readStringListEntry("RecentTopicList",QStringList());
+ //*g_pBookmarkList = cfg.readStringListEntry("Bookmarks",QStringList());
+}
+void KviApp::saveRecentEntries()
+{
+ QString tmp;
+ getLocalKvircDirectory(tmp,Config,KVI_CONFIGFILE_RECENT);
+ KviConfig cfg(tmp,KviConfig::Write);
+ cfg.writeEntry("RecentTopicList",*g_pRecentTopicList);
+ //cfg.writeEntry("Bookmarks",*g_pBookmarkList);
+}
+
+void KviApp::saveAvatarCache()
+{
+ QString tmp;
+ getLocalKvircDirectory(tmp,Config,KVI_CONFIGFILE_AVATARCACHE);
+ KviAvatarCache::instance()->save(tmp);
+}
+
+
+void KviApp::saveToolBars()
+{
+ QString tmp;
+ getLocalKvircDirectory(tmp,Config,KVI_CONFIGFILE_CUSTOMTOOLBARS);
+ KviCustomToolBarManager::instance()->save(tmp);
+}
+
+void KviApp::savePopups()
+{
+ QString tmp;
+ getLocalKvircDirectory(tmp,Config,KVI_CONFIGFILE_POPUPS);
+ KviKvs::savePopups(tmp);
+}
+
+void KviApp::saveInputHistory()
+{
+ if(!KVI_OPTION_BOOL(KviOption_boolDisableInputHistory))
+ {
+ QString tmp;
+ getLocalKvircDirectory(tmp,Config,KVI_CONFIGFILE_INPUTHISTORY);
+ g_pInputHistory->save(tmp);
+ }
+}
+
+
+void KviApp::saveAliases()
+{
+ QString tmp;
+ getLocalKvircDirectory(tmp,Config,KVI_CONFIGFILE_ALIASES);
+ KviKvs::saveAliases(tmp);
+}
+
+void KviApp::saveScriptAddons()
+{
+ QString tmp;
+ getLocalKvircDirectory(tmp,Config,KVI_CONFIGFILE_SCRIPTADDONS);
+ KviKvs::saveScriptAddons(tmp);
+}
+
+void KviApp::saveTextIcons()
+{
+ g_pTextIconManager->save();
+}
+
+void KviApp::saveAppEvents()
+{
+ QString tmp;
+ getLocalKvircDirectory(tmp,Config,KVI_CONFIGFILE_EVENTS);
+ KviKvs::saveAppEvents(tmp);
+}
+
+void KviApp::saveRawEvents()
+{
+ QString tmp;
+ getLocalKvircDirectory(tmp,Config,KVI_CONFIGFILE_RAWEVENTS);
+ KviKvs::saveRawEvents(tmp);
+}
+
+void KviApp::saveMediaTypes()
+{
+ QString tmp;
+ getLocalKvircDirectory(tmp,Config,KVI_CONFIGFILE_MEDIATYPES);
+ g_pMediaManager->lock();
+ g_pMediaManager->save(tmp);
+ g_pMediaManager->unlock();
+}
+
+void KviApp::saveIrcServerDataBase()
+{
+ QString tmp;
+ getLocalKvircDirectory(tmp,Config,KVI_CONFIGFILE_SERVERDB);
+ g_pIrcServerDataBase->save(tmp);
+}
+
+void KviApp::saveProxyDataBase()
+{
+ QString tmp;
+ getLocalKvircDirectory(tmp,Config,KVI_CONFIGFILE_PROXYDB);
+ g_pProxyDataBase->save(tmp);
+}
+
+void KviApp::saveRegisteredUsers()
+{
+ QString tmp;
+ getLocalKvircDirectory(tmp,Config,KVI_CONFIGFILE_REGUSERDB);
+ g_pRegisteredUserDataBase->save(tmp);
+}
+
+void KviApp::saveRegisteredChannels()
+{
+ QString tmp;
+ getLocalKvircDirectory(tmp,Config,KVI_CONFIGFILE_REGCHANDB);
+ g_pRegisteredChannelDataBase->save(tmp);
+}
+
+void KviApp::saveNickServ()
+{
+ QString tmp;
+ getLocalKvircDirectory(tmp,Config,KVI_CONFIGFILE_NICKSERVDATABASE);
+ g_pNickServRuleSet->save(tmp);
+}
+
+void KviApp::saveSharedFiles()
+{
+ QString tmp;
+ getLocalKvircDirectory(tmp,Config,KVI_CONFIGFILE_SHAREDFILES);
+ g_pSharedFilesManager->save(tmp);
+}
+
+void KviApp::saveActions()
+{
+ QString tmp;
+ getLocalKvircDirectory(tmp,Config,KVI_CONFIGFILE_USERACTIONS);
+ KviActionManager::instance()->save(tmp);
+}
+
+void KviApp::saveIdentities()
+{
+ QString tmp;
+ getLocalKvircDirectory(tmp,Config,KVI_CONFIGFILE_IDENTITIES);
+ KviUserIdentityManager::instance()->save(tmp);
+}
+
+void KviApp::saveConfiguration()
+{
+ // this is NOT called when the application is closing down
+ KviCustomToolBarManager::instance()->storeVisibilityState();
+ saveOptions();
+ saveIdentities();
+ saveActions();
+ saveIrcServerDataBase();
+ saveProxyDataBase();
+ saveRecentEntries();
+ saveAvatarCache();
+ saveAppEvents();
+ saveRawEvents();
+ saveMediaTypes();
+ saveRegisteredUsers();
+ saveRegisteredChannels();
+ saveNickServ();
+ saveSharedFiles();
+ savePopups();
+ saveToolBars();
+ saveAliases();
+ saveTextIcons();
+ saveInputHistory();
+ saveScriptAddons();
+ KviKvs::flushUserClasses();
+ g_pWinPropertiesConfig->sync();
+}
+
+void KviApp::autoConnectToServers()
+{
+ KviPointerList<KviIrcServer> * l = g_pIrcServerDataBase->autoConnectOnStartupServers();
+ if(l)
+ {
+ for(KviIrcServer * s = l->first();s;s = l->next())
+ {
+ QString szCommand = "server -u \"id:";
+ if(s->id().isEmpty())s->generateUniqueId();
+ szCommand += s->id();
+ szCommand += "\"";
+ KviKvsScript::run(szCommand,activeConsole());
+ }
+ g_pIrcServerDataBase->clearAutoConnectOnStartupServers();
+ }
+
+ KviPointerList<KviIrcServerDataBaseRecord> * lr = g_pIrcServerDataBase->autoConnectOnStartupNetworks();
+ if(lr)
+ {
+ for(KviIrcServerDataBaseRecord * r = lr->first();r;r = lr->next())
+ {
+ QString szCommandx = "server -u \"net:";
+ szCommandx += r->network()->name();
+ szCommandx += "\"";
+ KviKvsScript::run(szCommandx,activeConsole());
+ }
+ g_pIrcServerDataBase->clearAutoConnectOnStartupNetworks();
+ }
+}
+
+
+void KviApp::createFrame()
+{
+ if(g_pFrame)debug("WARNING: Creating the main frame twice!");
+ g_pFrame = new KviFrame();
+ g_pFrame->createNewConsole(true);
+
+ if(m_szExecAfterStartup.hasData())
+ {
+ // FIXME , this should be a QString
+ KviKvsScript::run(m_szExecAfterStartup.ptr(),g_pFrame->firstConsole());
+ m_szExecAfterStartup = "";
+ }
+
+ // auto connect to servers if needed
+ if(g_pIrcServerDataBase->autoConnectOnStartupServers() || g_pIrcServerDataBase->autoConnectOnStartupNetworks())
+ {
+ autoConnectToServers();
+ }
+
+ if(KVI_OPTION_BOOL(KviOption_boolShowDockExtension))
+ g_pFrame->executeInternalCommand(KVI_INTERNALCOMMAND_DOCKWIDGET_SHOW);
+
+ if(KVI_OPTION_BOOL(KviOption_boolStartupMinimized))
+ {
+ if(KVI_OPTION_BOOL(KviOption_boolMinimizeInTray) && KVI_OPTION_BOOL(KviOption_boolShowDockExtension))
+ {
+ g_pFrame->hide();
+ } else {
+ g_pFrame->showMinimized();
+ }
+ } else {
+ g_pFrame->show();
+ }
+}
+
+void KviApp::destroyFrame()
+{
+ if(g_pFrame)delete g_pFrame;
+ g_pActiveWindow = 0;
+ quit();
+}
+
+bool KviApp::connectionExists(KviIrcConnection *cnn)
+{
+ KviPointerHashTableIterator<const char *,KviWindow> it(*g_pGlobalWindowDict);
+
+ while(it.current())
+ {
+ if(it.current()->connection() == cnn)return true;
+ ++it;
+ }
+ return false;
+}
+
+
+bool KviApp::windowExists(KviWindow *wnd)
+{
+ KviPointerHashTableIterator<const char *,KviWindow> it(*g_pGlobalWindowDict);
+
+ while(it.current())
+ {
+ if(it.current() == wnd)return true;
+ ++it;
+ }
+ return false;
+}
+
+unsigned int KviApp::windowCount()
+{
+ return g_pGlobalWindowDict->count();
+}
+
+KviConsole * KviApp::findConsole(QString &server,QString &nick)
+{
+ KviPointerHashTableIterator<const char *,KviWindow> it(*g_pGlobalWindowDict);
+
+ while(it.current())
+ {
+ if(it.current()->type() == KVI_WINDOW_TYPE_CONSOLE)
+ {
+ if(((KviConsole *)it.current())->isConnected())
+ {
+ if(!server.isEmpty())
+ {
+ if(KviQString::equalCI(server,
+ ((KviConsole *)it.current())->connection()->currentServerName()))
+ {
+ if(!nick.isEmpty())
+ {
+ if(KviQString::equalCI(nick,
+ ((KviConsole *)it.current())->connection()->currentNickName()))
+ return ((KviConsole *)it.current());
+ } else return ((KviConsole *)it.current());
+ }
+ } else {
+ if(!nick.isEmpty())
+ {
+ if(KviQString::equalCI(nick,
+ ((KviConsole *)it.current())->connection()->currentNickName()))
+ return ((KviConsole *)it.current());
+ }
+ }
+ }
+ }
+ ++it;
+ }
+ return 0;
+}
+
+KviConsole * KviApp::findConsole(KviStr &server,KviStr &nick)
+{
+ // DEPRECATED: TO BE KILLED (if nobody is using it)
+ QString s = server.ptr();
+ QString n = nick.ptr();
+ return findConsole(s,n);
+}
+
+void KviApp::restartLagMeters()
+{
+ KviPointerHashTableIterator<const char *,KviWindow> it(*g_pGlobalWindowDict);
+
+ while(it.current())
+ {
+ if(it.current()->type() == KVI_WINDOW_TYPE_CONSOLE)
+ {
+ if(((KviConsole *)it.current())->connection())
+ ((KviConsole *)it.current())->connection()->restartLagMeter();
+ }
+ ++it;
+ }
+}
+
+void KviApp::restartNotifyLists()
+{
+ KviPointerHashTableIterator<const char *,KviWindow> it(*g_pGlobalWindowDict);
+
+ while(it.current())
+ {
+ if(it.current()->type() == KVI_WINDOW_TYPE_CONSOLE)
+ {
+ if(((KviConsole *)it.current())->connection())
+ ((KviConsole *)it.current())->connection()->restartNotifyList();
+ }
+ ++it;
+ }
+}
+
+void KviApp::resetAvatarForMatchingUsers(KviRegisteredUser * u)
+{
+ KviPointerHashTableIterator<const char *,KviWindow> it(*g_pGlobalWindowDict);
+
+ while(it.current())
+ {
+ if(it.current()->type() == KVI_WINDOW_TYPE_CONSOLE)
+ {
+ ((KviConsole *)it.current())->resetAvatarForMatchingUsers(u);
+ }
+ ++it;
+ }
+}
+
+KviConsole * KviApp::findConsole(unsigned int ircContextId)
+{
+ KviPointerHashTableIterator<const char *,KviWindow> it(*g_pGlobalWindowDict);
+
+ while(it.current())
+ {
+ if(it.current()->type() == KVI_WINDOW_TYPE_CONSOLE)
+ {
+ if(((KviConsole *)it.current())->ircContextId() == ircContextId)
+ return ((KviConsole *)it.current());
+ }
+ ++it;
+ }
+ return 0;
+}
+
+
+
+KviConsole * KviApp::topmostConnectedConsole()
+{
+ // check the foreground window console
+
+ KviConsole * c = activeConsole();
+ if(!c)return 0;
+ if(c->isConnected())return c;
+
+ // try ANY connected console
+
+ KviPointerHashTableIterator<const char *,KviWindow> it(*g_pGlobalWindowDict);
+
+ while(it.current())
+ {
+ if(it.current()->type() == KVI_WINDOW_TYPE_CONSOLE)
+ {
+ if(((KviConsole *)it.current())->isConnected())return (KviConsole *)(it.current());
+ }
+ ++it;
+ }
+
+ return 0;
+}
+
+KviWindow * KviApp::findWindow(const char * windowId)
+{
+ return g_pGlobalWindowDict->find(windowId);
+}
+
+KviWindow * KviApp::findWindowByCaption(const QString &windowCaption,int iContextId)
+{
+ KviPointerHashTableIterator<const char *,KviWindow> it(*g_pGlobalWindowDict);
+
+ while(it.current())
+ {
+ if(KviQString::equalCI(windowCaption,it.current()->plainTextCaption()) &&
+ (iContextId==-1 || it.current()->context()->id() == iContextId))
+ return it.current();
+ ++it;
+ }
+ return 0;
+}
+
+void KviApp::registerWindow(KviWindow *wnd)
+{
+ g_pGlobalWindowDict->insert(wnd->id(),wnd);
+}
+
+void KviApp::unregisterWindow(KviWindow *wnd)
+{
+ g_pGlobalWindowDict->remove(wnd->id());
+}
+
+
+KviConsole * KviApp::activeConsole()
+{
+ if(!g_pFrame)return 0;
+ if(g_pActiveWindow)
+ {
+ if(g_pActiveWindow->console())return g_pActiveWindow->console();
+ }
+ return g_pFrame->firstConsole();
+}
+
+
+/////////////////// RECENT STUFF LISTS & POPUPS HANDLING
+
+// Helper for KviApp::addRecent*()
+static void merge_to_stringlist_option(const QString &item,int iOption,int iMaxEntries)
+{
+ for(QStringList::Iterator it = KVI_OPTION_STRINGLIST(iOption).begin();
+ it != KVI_OPTION_STRINGLIST(iOption).end(); ++it)
+ {
+ // Do a case-insensitive search (for nicknames, servers, and channels)
+ if(!QString::compare(item.lower(),(*it).lower()))
+ {
+ // In the recent list, remove and put as first so more recent items
+ // are always first
+ it = KVI_OPTION_STRINGLIST(iOption).remove(it);
+ --it;
+ }
+ }
+ while(KVI_OPTION_STRINGLIST(iOption).count() >= (unsigned int)iMaxEntries)
+ {
+ KVI_OPTION_STRINGLIST(iOption).remove(KVI_OPTION_STRINGLIST(iOption).fromLast());
+ }
+ KVI_OPTION_STRINGLIST(iOption).prepend(item);
+}
+
+void KviApp::addRecentUrl(const QString& text)
+{
+ merge_to_stringlist_option(text,KviOption_stringlistRecentIrcUrls,50);
+ emit(recentUrlsChanged());
+}
+
+void KviApp::addRecentNickname(const char * newNick)
+{
+ QString nk(newNick);
+ merge_to_stringlist_option(nk,KviOption_stringlistRecentNicknames,KVI_MAX_RECENT_NICKNAMES);
+}
+
+void KviApp::addRecentNickname(const QString& newNick)
+{
+ merge_to_stringlist_option(newNick,KviOption_stringlistRecentNicknames,KVI_MAX_RECENT_NICKNAMES);
+}
+
+void KviApp::addRecentChannel(const QString& szChan,const QString& net)
+{
+ if(!m_pRecentChannelsDict)
+ buildRecentChannels();
+ QStringList* pList=m_pRecentChannelsDict->find(net.utf8().data());
+ if(pList)
+ {
+ if(!pList->contains(szChan)) pList->append(szChan);
+ }
+ else
+ {
+ pList=new QStringList(szChan);
+ m_pRecentChannelsDict->insert(net.utf8().data(),pList);
+ }
+}
+
+void KviApp::buildRecentChannels()
+{
+ if(m_pRecentChannelsDict)
+ delete m_pRecentChannelsDict;
+ m_pRecentChannelsDict = new KviPointerHashTable<const char *,QStringList>;
+ m_pRecentChannelsDict->setAutoDelete(TRUE);
+ QString szChan,szNet;
+ for (
+ QStringList::Iterator it = KVI_OPTION_STRINGLIST(KviOption_stringlistRecentChannels).begin();
+ it != KVI_OPTION_STRINGLIST(KviOption_stringlistRecentChannels).end();
+ ++it
+ )
+ {
+ if(!(*it).isEmpty())
+ {
+ szChan = (*it).section( KVI_RECENT_CHANNELS_SEPARATOR, 0, 0 );
+ szNet = (*it).section( KVI_RECENT_CHANNELS_SEPARATOR, 1 );
+ if(!szNet.isEmpty())
+ {
+ QStringList* pList=m_pRecentChannelsDict->find(szNet.utf8().data());
+ if(pList)
+ {
+ if(!pList->contains(szChan)) pList->append(szChan);
+ }
+ else
+ {
+ pList=new QStringList(szChan);
+ m_pRecentChannelsDict->insert(szNet.utf8().data(),pList);
+ }
+ }
+ }
+ }
+}
+
+void KviApp::saveRecentChannels()
+{
+ if(!m_pRecentChannelsDict) return;
+ QString szTmp;
+ KVI_OPTION_STRINGLIST(KviOption_stringlistRecentChannels).clear();
+ KviPointerHashTableIterator<const char *,QStringList> it( *m_pRecentChannelsDict );
+ for( ; it.current(); ++it )
+ {
+ for ( QStringList::Iterator it_str = it.current()->begin(); it_str != it.current()->end(); ++it_str ) {
+ szTmp=*it_str;
+ szTmp.append(KVI_RECENT_CHANNELS_SEPARATOR);
+ szTmp.append(it.currentKey());
+ KVI_OPTION_STRINGLIST(KviOption_stringlistRecentChannels).append(szTmp);
+ }
+ }
+}
+
+QStringList* KviApp::getRecentChannels(const QString& net)
+{
+ if(!m_pRecentChannelsDict) buildRecentChannels();
+ return m_pRecentChannelsDict->find(net.utf8().data());
+}
+
+
+void KviApp::addRecentServer(const QString& server)
+{
+ merge_to_stringlist_option(server,KviOption_stringlistRecentServers,KVI_MAX_RECENT_SERVERS);
+}
+
+void KviApp::fillRecentServersPopup(KviTalPopupMenu * m)
+{
+// FIXME: #warning "MAYBE DISABLE THE SERVERS THAT WE ARE ALREADY CONNECTED TO ?"
+ m->clear();
+ for(QStringList::Iterator it = KVI_OPTION_STRINGLIST(KviOption_stringlistRecentServers).begin(); it != KVI_OPTION_STRINGLIST(KviOption_stringlistRecentServers).end(); ++it)
+ {
+ m->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_SERVER)),*it);
+ }
+}
+
+void KviApp::fillRecentNicknamesPopup(KviTalPopupMenu * m,KviConsole * pConsole)
+{
+ m->clear();
+ int id;
+ bool bAlreadyFound = false;
+ for(QStringList::Iterator it = KVI_OPTION_STRINGLIST(KviOption_stringlistRecentNicknames).begin(); it != KVI_OPTION_STRINGLIST(KviOption_stringlistRecentNicknames).end(); ++it)
+ {
+ id = m->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_NICK)),*it);
+ if(!pConsole->isConnected())m->setItemEnabled(id,false);
+ else {
+ if(!bAlreadyFound)
+ {
+ bool bIsCurrent = KviQString::equalCS(pConsole->connection()->currentNickName(),*it);
+ m->setItemEnabled(id,!bIsCurrent);
+ if(bIsCurrent)bAlreadyFound = true;
+ }
+ }
+ }
+}
+
+void KviApp::fillRecentChannelsPopup(KviTalPopupMenu * m,KviConsole * pConsole)
+{
+ m->clear();
+ int id;
+ QStringList* pList=getRecentChannels(pConsole->currentNetworkName());
+ if(pList)
+ {
+ for(QStringList::Iterator it = pList->begin(); it != pList->end(); ++it)
+ {
+ id = m->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CHANNEL)),*it);
+ if(!pConsole->isConnected())m->setItemEnabled(id,false);
+ else {
+ m->setItemEnabled(id,!(pConsole->connection()->findChannel(*it)));
+ }
+ }
+ }
+}
+
+
+/*
+void KviApp::fillRecentServersListBox(KviTalListBox * l)
+{
+ l->clear();
+ for(QStringList::Iterator it = KVI_OPTION_STRINGLIST(KviOption_stringlistRecentServers).begin(); it != KVI_OPTION_STRINGLIST(KviOption_stringlistRecentServers).end(); ++it)
+ l->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_SERVER)),*it);
+}
+*/
+
+
+
+
+bool KviApp::playFile(const char * filename,KviStr &error,KviWindow * w)
+{
+ g_pMediaManager->lock();
+ KviMediaType * m = g_pMediaManager->findMediaType(filename);
+ if(m)
+ {
+ KviStr szCommandline = m->szCommandline;
+ KviStr szDescription = m->szDescription;
+ g_pMediaManager->unlock();
+ if(szCommandline.hasData())
+ {
+ KviKvsVariantList l;
+ l.append(new KviKvsVariant(QString(filename)));
+
+ if(!KviKvsScript::run(szCommandline.ptr(),w ? w : g_pActiveWindow,&l))
+ {
+ error.sprintf(__tr("The commandline for media type '%s' seems to be broken"),szDescription.ptr());
+ return false;
+ }
+ } else {
+ error.sprintf(__tr("Media type of file %s matched to '%s' but no commandline specified"),filename,szDescription.ptr());
+ return false;
+ }
+ } else {
+ g_pMediaManager->unlock();
+ error.sprintf(__tr("No idea on how to play file %s (no media type match)"),filename);
+ return false;
+ }
+ return true;
+}
+
+void KviApp::heartbeat(kvi_time_t tNow)
+{
+ if(g_pApp->topmostConnectedConsole())
+ {
+ // FIXME: this has huge precision problems...
+ KVI_OPTION_UINT(KviOption_uintTotalConnectionTime)++;
+ }
+
+ // the line below is an approximation of (tNow / 120) == 0
+ // we don't need a really great precision here, so 128 is still ok
+ if(!(tNow & 0x7f))
+ KviDoubleBuffer::heartbeat();
+}
+
+void KviApp::timerEvent(QTimerEvent *e)
+{
+ if(e->timerId() != m_iHeartbeatTimerId)
+ {
+ QObject::timerEvent(e);
+ return;
+ }
+
+ // our heartbeat
+
+ kvi_time_t tNow = kvi_unixTime();
+
+ heartbeat(tNow);
+}
+
+// qvariant.h uses this , and it is included by the qt generated moc file for Qt >= 3.0.0
+#ifdef Bool
+ #undef Bool
+#endif
+
+
+#include "kvi_app.moc"
diff --git a/src/kvirc/kernel/kvi_app.h b/src/kvirc/kernel/kvi_app.h
new file mode 100644
index 00000000..d31bd401
--- /dev/null
+++ b/src/kvirc/kernel/kvi_app.h
@@ -0,0 +1,344 @@
+#ifndef _KVI_APP_H_
+#define _KVI_APP_H_
+
+//=============================================================================
+//
+// File : kvi_app.h
+// Creation date : Sun Jun 18 2000 12:40:00 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_string.h"
+#include "kvi_qstring.h"
+#include "kvi_tal_application.h"
+#include "kvi_pointerlist.h"
+#include "kvi_time.h"
+#include "kvi_pointerhashtable.h" // ?
+
+#define KVI_RECENT_CHANNELS_SEPARATOR ":"
+
+#ifdef COMPILE_ON_WINDOWS
+ // The brain damaged MSVC compiler can't instantiate templates without this
+ #include "kvi_frame.h"
+ #include "kvi_window.h"
+#else // !COMPILE_ON_WINDOWS
+ class KviFrame;
+ class KviWindow;
+#endif // !COMPILE_ON_WINDOWS
+
+#ifndef COMPILE_NO_IPC
+ class KviIpcSentinel;
+#endif // !COMPILE_NO_IPC
+
+class KviTalPopupMenu;
+class QPixmap;
+class KviTalListBox;
+class QTextCodec;
+class QDomElement;
+
+class KviConsole;
+class KviConfig;
+class KviRegisteredUser;
+class KviIrcConnection;
+class KviIrcServerDataBase;
+
+typedef struct _KviPendingAvatarChange
+{
+ KviConsole * pConsole;
+ QString szRemoteUrl;
+ QString szNick;
+ QString szUser;
+ QString szHost;
+} KviPendingAvatarChange;
+
+#ifdef Unsorted
+ #undef Unsorted
+#endif
+#ifdef None
+ #undef None
+#endif
+
+class KVIRC_API KviApp : public KviTalApplication
+{
+ friend class KviFrame;
+ friend class KviWindow;
+ friend class KviSetupWizard; // this resides in a module!
+ Q_OBJECT
+public:
+ KviApp(int &argc,char ** argv);
+ ~KviApp();
+
+protected:
+ // directories
+ QString m_szGlobalKvircDir;
+ QString m_szLocalKvircDir;
+ int m_iHeartbeatTimerId;
+ bool m_bFirstTimeRun;
+ KviWindow * m_pActiveWindow;
+ bool m_bUpdateGuiPending;
+ KviPointerList<KviPendingAvatarChange> * m_pPendingAvatarChanges;
+ bool m_bSetupDone;
+ KviPointerHashTable<const char *,QStringList> * m_pRecentChannelsDict;
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ bool m_bUpdatePseudoTransparencyPending;
+#endif
+#ifndef COMPILE_NO_IPC
+ KviIpcSentinel * m_pIpcSentinel;
+#endif
+public:
+ // setup stuff (accessed from kvi_main.cpp: consider private othwerise)
+ QString m_szConfigFile; // setup
+ bool m_bCreateConfig; // setup
+ KviStr m_szExecAfterStartup;
+ bool m_bShowSplashScreen;
+public:
+ // FIXME: "Plugins" and "ConfigPlugins" should become "Modules" and "ConfigModules"
+ enum KvircSubdir
+ {
+ None, Pics, Config ,
+ Help, HelpEN, HelpNoIntl,
+ Log, Incoming, Audio,
+ Scripts, Plugins, ConfigPlugins,
+ Trash, MsgColors, Charmaps,
+ Avatars, DefScript, License,
+ Modules, ConfigScripts, Filters,
+ Tmp, Locale, Themes,
+ Classes, SmallIcons, EasyPlugins
+ };
+
+public:
+
+ void getClipboardText(KviStr &buffer);
+ void setClipboardText(const KviStr &str);
+
+ QString getClipboardText();
+ void setClipboardText(const QString &str);
+
+
+ void collectGarbage(QObject * garbage);
+
+ void destroyFrame();
+ void setup(); // THIS SHOULD BE PRIVATE! (but is accessed from kvi_main.cpp)
+
+#ifndef COMPILE_NO_IPC
+ void ipcMessage(char * message);
+#endif
+
+ //static QTextCodec * defaultTextCodec();
+ //static const char * defaultTextEncoding();
+
+ static int getGloballyUniqueId(); // returns an unique integer identifier across the application
+
+ bool firstTimeRun(){ return m_bFirstTimeRun; };
+ void setupBegin();
+ void setupFinish();
+ inline void emitRecentUrlsChanged() { emit(recentUrlsChanged()); };
+
+ // kvi_app.cpp (Saving options)
+ void saveIrcServerDataBase();
+ void saveProxyDataBase();
+ void saveRecentEntries();
+ void saveAppEvents();
+ void saveRawEvents();
+ void saveMediaTypes();
+ void saveRegisteredUsers();
+ void saveSharedFiles();
+ void savePopups();
+ void saveAliases();
+ void saveNickServ();
+ void saveTextIcons();
+ void saveRegisteredChannels();
+ void saveInputHistory();
+ void saveAvatarCache();
+ void saveToolBars();
+ void saveActions();
+ void saveScriptAddons();
+ void saveIdentities();
+
+ // kvi_options.cpp : Options saving and loading (kvi.main.conf))
+ void loadOptions();
+ void saveOptions();
+
+ void listAvailableOptions(KviWindow *wnd);
+ bool getOptionString(const char * optName,QString &buffer);
+ bool setOptionValue(const char * optName,const QString &value);
+ void optionResetUpdate(int flags);
+
+ void contextSensitiveHelp();
+
+ // kvi_app_fs.cpp : Filesystem thingies
+ void getGlobalKvircDirectory(QString &szData,KvircSubdir dir,const QString &appendFile = QString::null);
+ void getGlobalKvircDirectory(KviStr &szData,KvircSubdir dir,const QString &appendFile = QString::null);
+ void getLocalKvircDirectory(KviStr &szData,KvircSubdir dir,const QString &appendFile = QString::null,bool bCreateIfNeeded = true);
+ void getLocalKvircDirectory(QString &szData,KvircSubdir dir,const QString &appendFile = QString::null,bool bCreateIfNeeded = true);
+ void getTmpFileName(QString &szBuffer,const QString &szEndingFileName = QString::null);
+ bool trashFile(const char *filename);
+ void getChannelDumpLogFileName(QString &str);
+
+ static QTextCodec * defaultTextCodec();
+
+ // if the mediatype can be guessed ,it is looked up in the media type save path
+ // if found , true is returned
+ // if not found or the mediatype can't be guessed then false is returned
+ bool findFileByMediaType(KviStr &szRetPath,const char * filename);
+
+ bool findImageInImageSearchPath(KviStr &szRetPath,const char * filename);
+ bool findImageInImageSearchPath(QString &szRetPath,const char * filename);
+
+ bool findUserFile(KviStr &szRetPath,const char *filename);
+
+ bool findImage(KviStr &szRetPath,const char *filename);
+ bool findImage(QString &szRetPath,const char *filename);
+ bool findImageThemeOnlyCompat(QString &szRetPath,const char *filename); // temporary compat, will be removed soon (do not use)
+ bool findSmallIcon(QString &szRetPath,const char *filename);
+ // tries to map the full path filename to one of the KVIrc's mapped directories
+ // if it doesn't succeed it just returns the complete filename in szRetPath
+ bool mapImageFile(KviStr &szRetPath,const char * filename);
+ bool mapImageFile(QString &szRetPath,const char * filename);
+
+ //void getDefaultDccSaveFilePath(KviStr &path,const char *filename);
+ void completeDirectory(const QString &word,KviPointerList<QString> * matches);
+ //
+ // Returns a config path suitable for reading (at least)
+ // First lookups the user local config directory,
+ // if no config file is found, it earches in the global one
+ // returns false if no config file has been found
+ // If bNoFail is true, the buffer is filled with the file name even
+ // if no config file has been found: in this case the local config
+ // directory is used
+ //
+ bool getReadOnlyConfigPath(KviStr &buffer,const char *config_name,KvircSubdir sbd = Config,bool bNoFail = false);
+ bool getReadOnlyConfigPath(QString &buffer,const char *config_name,KvircSubdir sbd = Config,bool bNoFail = false);
+
+ // kvi_app.cpp : Window stuff
+ KviWindow * findWindow(const char * windowId);
+ KviWindow * findWindowByCaption(const QString &windowCaption,int iContextId=-1);
+ KviConsole * findConsole(unsigned int ircContextId);
+ KviConsole * findConsole(KviStr & server,KviStr & nick);
+ KviConsole * findConsole(QString & servr,QString & nick);
+ KviConsole * topmostConnectedConsole();
+ KviConsole * activeConsole();
+ bool windowExists(KviWindow *wnd);
+ bool connectionExists(KviIrcConnection *cnn);
+ unsigned int windowCount();
+
+ // kvi_app.cpp : Utilities
+ void resetAvatarForMatchingUsers(KviRegisteredUser * u);
+ void restartNotifyLists();
+ void restartLagMeters();
+ void triggerUpdateGui();
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ void triggerUpdatePseudoTransparency();
+#endif
+
+ // kvi_app.cpp : DCC (and CTCP AVATAR & SOUND) related stuff
+ void setAvatarOnFileReceived(KviConsole * pConsole,const QString &szRemoteUrl,const QString &szNick,const QString &szUser,const QString &szHost);
+ KviPendingAvatarChange * findPendingAvatarChange(KviConsole * pConsole,const QString &szNick,const QString &szRemoteUrl);
+ void fileDownloadTerminated(bool bSuccess,const QString &szRemoteUrl,const QString &szLocalFileName,const QString &szNick = QString::null,const QString &szError = QString::null,bool bQuiet = false);
+
+ void setAvatarFromOptions();
+
+ bool playFile(const char * filename,KviStr &error,KviWindow * w = 0);
+
+ // uMessageLifetime is in seconds! and 0 means "forever"
+ void notifierMessage(KviWindow * pWnd,int iIconId,const QString &szMsg,unsigned int uMessageLifetime);
+
+
+ void addRecentNickname(const char * newNick);
+ void addRecentNickname(const QString& newNick);
+ void addRecentChannel(const QString& chan,const QString& net);
+ QStringList* getRecentChannels(const QString& net);
+
+ void addRecentServer(const QString& server);
+ void fillRecentServersPopup(KviTalPopupMenu * m);
+ void fillRecentNicknamesPopup(KviTalPopupMenu * m,KviConsole * pConsole);
+ void fillRecentChannelsPopup(KviTalPopupMenu * m,KviConsole * pConsole);
+
+ void autoConnectToServers();
+
+ void checkSuggestRestoreDefaultScript();
+
+ void loadDefaultScript();
+protected:
+ void buildRecentChannels();
+ void saveRecentChannels();
+ // kvi_app.cpp : KviWindow global database
+ void registerWindow(KviWindow *wnd);
+ void unregisterWindow(KviWindow *wnd);
+ void frameDestructorCallback();
+ void heartbeat(kvi_time_t tNow);
+ virtual void timerEvent(QTimerEvent *e);
+public slots:
+ // kvi_app.cpp : Slots
+ void saveConfiguration();
+ void updateGui();
+ void kdeRootPixmapDownloadComplete(bool bSuccess);
+ void kdeRootPixmapChanged(int iDesktop);
+ void updatePseudoTransparency();
+ void restoreDefaultScript();
+ void addRecentUrl(const QString& text);
+private:
+ void createSplashScreen();
+ void destroySplashScreen();
+
+ // kvi_app_setup.cpp : Setup stuff
+ void loadDirectories();
+ void findGlobalKvircDirectory();
+ bool findLocalKvircDirectory();
+ bool checkGlobalKvircDirectory(const QString);
+ bool checkLocalKvircDirectory(const QString);
+ bool checkFileAssociations();
+ void setupFileAssociations();
+
+ bool checkUriAssociations(char * proto);
+ void setupUriAssociations(char * proto);
+
+ void saveKvircDirectory();
+
+ // kvi_app.cpp : GUI stuff
+ void updateApplicationFont();
+
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ void createGlobalBackgrounds(QPixmap * pix);
+ void destroyPseudoTransparency();
+ #ifdef COMPILE_KDE_SUPPORT
+ void downloadKdeRootPixmap();
+ #endif //COMPILE_KDE_SUPPORT
+#endif //COMPILE_PSEUDO_TRANSPARENCY
+private:
+ // kvi_app.cpp : parts of setup()
+ void loadRecentEntries();
+#ifndef COMPILE_NO_IPC
+ void createIpcSentinel();
+ void destroyIpcSentinel();
+#endif //!COMPILE_NO_IPC
+ void createFrame();
+signals:
+ void reloadImages();
+ void recentUrlsChanged();
+};
+
+#ifndef _KVI_APP_CPP_
+ extern KVIRC_API KviApp * g_pApp;
+ extern KVIRC_API KviIrcServerDataBase * g_pIrcServerDataBase;
+#endif
+
+#endif //_KVI_APP_H_
diff --git a/src/kvirc/kernel/kvi_app_fs.cpp b/src/kvirc/kernel/kvi_app_fs.cpp
new file mode 100644
index 00000000..ee5eacd3
--- /dev/null
+++ b/src/kvirc/kernel/kvi_app_fs.cpp
@@ -0,0 +1,726 @@
+//=============================================================================
+//
+// File : kvi_app_fs.cpp
+// Creation date : Thu Dec 24 1998 04:05:26 by Szymon Stefanek
+//
+// This file is part of the Kvirc irc client distribution
+// Copyright (C) 1998-2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_debug.h"
+#include "kvi_app.h"
+#include "kvi_locale.h"
+#include "kvi_fileutils.h"
+#include "kvi_mediatype.h"
+#include "kvi_env.h"
+#include "kvi_time.h"
+#include "kvi_options.h"
+#include "kvi_defaults.h"
+#include "kvi_iconmanager.h"
+
+#include <qdir.h>
+#include <qfileinfo.h>
+#include <qdatetime.h>
+
+extern KviMediaManager * g_pMediaManager;
+
+//============ getGlobalKvircDirectory ================//
+
+void KviApp::getGlobalKvircDirectory(QString &szData,KvircSubdir dir,const QString &appendFile)
+{
+ szData=m_szGlobalKvircDir;
+ KviQString::ensureLastCharIs(szData,KVI_PATH_SEPARATOR_CHAR);
+
+ switch(dir)
+ {
+ case None : break;
+ case Pics : szData.append("pics"); break;
+
+ // Local hack for Debian
+ case Modules :
+ case Plugins : szData = "/opt/kde3/lib/kvirc/" KVI_VERSION_BRANCH "/modules"; break;
+
+ case EasyPlugins : szData.append("easyplugins"); break;
+ case ConfigPlugins : KviQString::appendFormatted(szData,"config%smodules",KVI_PATH_SEPARATOR); break;
+ case ConfigScripts : KviQString::appendFormatted(szData,"config%sscripts",KVI_PATH_SEPARATOR); break;
+ case Help :
+ szData.append("help");
+ {
+ // Localized help
+ QString tmp(KviLocale::localeName().ptr());
+ tmp.prepend(KVI_PATH_SEPARATOR_CHAR);
+ tmp.prepend(szData);
+ if(KviFileUtils::directoryExists(tmp))szData = tmp;
+ else {
+ tmp = szData; KviQString::appendFormatted(tmp,"%sen",KVI_PATH_SEPARATOR);
+ if(KviFileUtils::directoryExists(tmp))szData = tmp;
+ }
+ }
+ break;
+ case HelpEN : KviQString::appendFormatted(szData,"help%sen",KVI_PATH_SEPARATOR); break;
+ case HelpNoIntl : szData.append("help"); break;
+ case Log : debug("WARNING Global log directory requested!"); break;
+ case Incoming : debug("WARNING Global incoming directory requested!"); break;
+ case Trash : debug("WARNING Global trash directory requested!"); break;
+ case Config : szData.append("config"); break;
+ case Audio : szData.append("audio"); break;
+ case Scripts : szData.append("scripts"); break;
+ case MsgColors : szData.append("msgcolors"); break;
+ case Charmaps : szData.append("charmaps"); break;
+ case Avatars : szData.append("avatars"); break;
+ case DefScript : szData.append("defscript"); break;
+ case License : szData.append("license"); break;
+ case Filters : szData.append("filters"); break;
+ case Locale : szData.append("locale"); break;
+ case Tmp : debug("WARNING Global tmp directory requested!"); break;
+ case Themes : szData.append("themes"); break;
+ case Classes : szData.append("classes"); break;
+ case SmallIcons : szData.append("pics"KVI_PATH_SEPARATOR KVI_SMALLICONS_SUBDIRECTORY); break;
+ }
+
+ if(!appendFile.isEmpty())
+ {
+ KviQString::ensureLastCharIs(szData,KVI_PATH_SEPARATOR_CHAR);
+ szData.append(appendFile);
+ }
+
+ KviFileUtils::adjustFilePath(szData);
+}
+
+void KviApp::getLocalKvircDirectory(QString &szData,KvircSubdir dir,const QString & appendFile,bool bCreateIfNeeded)
+{
+ szData=m_szLocalKvircDir;
+ KviQString::ensureLastCharIs(szData,KVI_PATH_SEPARATOR_CHAR);
+
+ switch(dir)
+ {
+ case None : break;
+ case Pics : szData.append("pics"); break;
+ case EasyPlugins : szData.append("easyplugins"); break;
+ case Config : szData.append("config"); break;
+ case ConfigPlugins : szData.append("config"KVI_PATH_SEPARATOR"modules"); break;
+ case ConfigScripts : szData.append("config"KVI_PATH_SEPARATOR"scripts"); break;
+ case Log : szData.append("log"); break;
+ case Incoming :
+ szData = KVI_OPTION_STRING(KviOption_stringIncomingPath);
+ // we should take special care here
+ // the user is likely to mess the path behind our back
+ // try to recover from most common problems
+ while(KviQString::lastCharIs(szData,KVI_PATH_SEPARATOR_CHAR))
+ szData = szData.remove(szData.length()-1,1);
+ if(szData.isEmpty())
+ {
+ // unset ?
+ KVI_OPTION_STRING(KviOption_stringIncomingPath) = QDir::homeDirPath();
+ if(!KVI_OPTION_STRING(KviOption_stringIncomingPath).endsWith(QString(QChar(KVI_PATH_SEPARATOR_CHAR))))
+ KVI_OPTION_STRING(KviOption_stringIncomingPath).append(KVI_PATH_SEPARATOR_CHAR);
+ KVI_OPTION_STRING(KviOption_stringIncomingPath).append(KVI_DEFAULT_INCOMING_SUBDIRECTORY_NAME);
+ }
+ break;
+ case Help :
+ szData.append("help");
+ {
+ // Localized help
+ QString tmp = KviLocale::localeName().ptr();
+ tmp.prepend(KVI_PATH_SEPARATOR_CHAR);
+ tmp.prepend(szData);
+ if(KviFileUtils::directoryExists(tmp))szData = tmp;
+ else {
+ tmp = szData; tmp.append(KVI_PATH_SEPARATOR"en");
+ if(KviFileUtils::directoryExists(tmp))szData = tmp;
+ }
+ }
+ break;
+ case HelpEN : szData.append("help"KVI_PATH_SEPARATOR"en"); break;
+ case HelpNoIntl : szData.append("help"); break;
+ case Audio : szData.append("audio"); break;
+ case Scripts : szData.append("scripts"); break;
+ case Modules :
+ case Plugins : szData.append("modules"); break;
+ case Trash : szData.append("trash"); break;
+ case MsgColors : szData.append("msgcolors"); break;
+ case Charmaps : szData.append("charmaps"); break;
+ case Avatars : szData.append("avatars"); break;
+ case License : szData.append("license"); break;
+ case Filters : szData.append("filters"); break;
+ case Tmp : szData.append("tmp"); break;
+ case Locale : szData.append("locale"); break;
+ case Themes : szData.append("themes"); break;
+ case DefScript : szData.append("defscript"); /* should never happen! */ break;
+ case Classes : szData.append("classes"); break;
+ case SmallIcons : szData.append("pics"KVI_PATH_SEPARATOR KVI_SMALLICONS_SUBDIRECTORY); break;
+ }
+ if(bCreateIfNeeded)KviFileUtils::makeDir(szData);
+
+ if(!appendFile.isEmpty())
+ {
+ KviQString::ensureLastCharIs(szData,KVI_PATH_SEPARATOR_CHAR);
+ szData.append(appendFile);
+ }
+
+ KviFileUtils::adjustFilePath(szData);
+}
+
+
+void KviApp::getGlobalKvircDirectory(KviStr &szData,KvircSubdir dir,const QString &appendFile)
+{
+ QString szBuffer = szData.ptr();
+ getGlobalKvircDirectory(szBuffer,dir,appendFile);
+ szData=szBuffer;
+
+}
+
+//=============== getLocalKvircDirectory ================//
+
+void KviApp::getLocalKvircDirectory(KviStr &szData,KvircSubdir dir,const QString &appendFile,bool bCreateIfNeeded)
+{
+ QString szBuffer = szData.ptr();
+ getLocalKvircDirectory(szBuffer,dir,appendFile,bCreateIfNeeded);
+ szData=szBuffer;
+}
+
+void KviApp::getTmpFileName(QString &szBuffer,const QString &szEndingFileName)
+{
+ QString tmp;
+ getLocalKvircDirectory(tmp,Tmp);
+ KviQString::ensureLastCharIs(tmp,KVI_PATH_SEPARATOR_CHAR);
+
+ struct timeval tmv;
+ kvi_gettimeofday(&tmv,0);
+
+ QString szFileName = szEndingFileName.isNull() ? QString("file.tmp") : szEndingFileName;
+ do {
+ szBuffer = tmp;
+ KviQString::appendFormatted(szBuffer,"kvirc_%d_%Q",tmv.tv_usec,&szFileName);
+ tmv.tv_usec++;
+ } while(KviFileUtils::fileExists(szBuffer));
+}
+
+//====================== trashFile ====================//
+//
+// Moves a file to the local trash directory
+//
+
+bool KviApp::trashFile(const char *filename)
+{
+ // Exists ?
+ QFileInfo fi = QFileInfo(QString::fromUtf8(filename));
+ if( !fi.exists() ) return false; // nothing to trash
+
+ // Build the filename
+ KviStr lastPart = filename;
+ lastPart.cutToLast(KVI_PATH_SEPARATOR_CHAR); // need only the filename
+ lastPart.append(".bak_");
+ QDateTime tm(QDateTime::currentDateTime());
+ lastPart.append(tm.toString());
+ lastPart.replaceAll(' ',"_");
+ // Ok...have lastPart.bak_Dec_11_31_1999
+ // Find the thrash directory (make it if necessary)
+ KviStr trashFile;
+ getLocalKvircDirectory(trashFile,Trash,lastPart.ptr(),true);
+ // Check if a such file already exists
+ fi.setFile(trashFile.ptr());
+ while(fi.exists())
+ {
+ trashFile.append(".rnm");
+ fi.setFile(trashFile.ptr());
+ }
+ // rename the file
+ return KviFileUtils::renameFile(filename,trashFile.ptr());
+}
+
+void KviApp::completeDirectory(const QString &word,KviPointerList<QString> * matches)
+{
+ QString szDir = word;
+ QString szFile = word;
+ KviQString::cutToLast(szFile,KVI_PATH_SEPARATOR_CHAR);
+ KviQString::cutFromLast(szDir,KVI_PATH_SEPARATOR_CHAR);
+ KviFileUtils::adjustFilePath(szDir);
+ KviQString::ensureLastCharIs(szDir,KVI_PATH_SEPARATOR_CHAR);
+ QDir d(szDir);
+
+ // FIXME: maybe check timestamps ? (old modules)
+ QStringList sl = d.entryList(QDir::Dirs);
+ QStringList::Iterator it;
+
+ for(it = sl.begin();it != sl.end();++it)
+ {
+ QString * t = new QString(*it);
+ if(KviQString::equalCS(*t,".") || KviQString::equalCS(*t,".."))
+ {
+ delete t;
+ } else {
+#ifdef COMPILE_ON_WINDOWS
+ if(KviQString::equalCIN(szFile,*t,szFile.length()))
+#else //!COMPILE_ON_WINDOWS
+ if(KviQString::equalCSN(szFile,*t,szFile.length()))
+#endif //COMPILE_ON_WINDOWS
+ {
+ t->prepend(szDir);
+ t->append(KVI_PATH_SEPARATOR_CHAR);
+ matches->append(t);
+ } else {
+ delete t;
+ }
+ }
+ }
+
+ sl = d.entryList(QDir::Files);
+
+ for(it = sl.begin();it != sl.end();++it)
+ {
+ QString * t = new QString(*it);
+#ifdef COMPILE_ON_WINDOWS
+ if(KviQString::equalCIN(szFile,*t,szFile.length()))
+#else //!COMPILE_ON_WINDOWS
+ if(KviQString::equalCSN(szFile,*t,szFile.length()))
+#endif //COMPILE_ON_WINDOWS
+ {
+ t->prepend(szDir);
+ matches->append(t);
+ } else {
+ delete t;
+ }
+ }
+}
+
+
+//============= getChannelDumpLogFileName ==============//
+//
+// Returns a valid filename for the channel dump log
+//
+
+void KviApp::getChannelDumpLogFileName(QString &str)
+{
+ unsigned int logN = 0;
+ QString fPrefix="kick_";
+ do{
+ QString fName;
+ KviQString::sprintf(fName,"%Q%u.log",&fPrefix,logN);
+ getLocalKvircDirectory(str,Log,fName);
+ logN++;
+ if(logN > 9999)
+ {
+ // Time to clear logs! :)
+ fPrefix+="x";
+ logN = 0;
+ }
+ } while(KviFileUtils::fileExists(str));
+ KviFileUtils::adjustFilePath(str);
+}
+
+bool KviApp::findFileByMediaType(KviStr &szRetPath,const char * filename)
+{
+ g_pMediaManager->lock();
+ KviMediaType * m = g_pMediaManager->findMediaType(filename,false);
+
+ if(m)
+ {
+ if(m->szSavePath.hasData())
+ {
+ szRetPath = m->szSavePath;
+ szRetPath.ensureLastCharIs(KVI_PATH_SEPARATOR_CHAR);
+ szRetPath.append(filename);
+ if(KviFileUtils::fileExists(szRetPath.ptr()))
+ {
+ // check again the media type... check the magic too
+ KviMediaType * mt = g_pMediaManager->findMediaType(szRetPath.ptr());
+ if(mt == m)
+ {
+ g_pMediaManager->unlock();
+ //if(retMediaType)*retMediaType = mt;
+ QString szTmp = szRetPath.ptr(); // FIXME
+ KviFileUtils::adjustFilePath(szTmp);
+ szRetPath = szTmp;
+ return true;
+ } // else mime type not matched...we should not be looking there!
+ }
+ }
+ }
+
+ g_pMediaManager->unlock();
+ return false;
+}
+
+//===================== findUserFile =====================//
+//
+// Looks for an user file in the standard directories
+//
+
+bool KviApp::findUserFile(KviStr &szRetPath,const char *filename)
+{
+ static KviApp::KvircSubdir localsubdirs[5]={ Avatars , Incoming , Pics , Audio , Log };
+ static KviApp::KvircSubdir globalsubdirs[3]={ Avatars , Pics , Audio };
+
+ // Absolute paths can not be "found"... they are obvious
+ if(kvi_isAbsolutePath(filename))
+ {
+ szRetPath=filename;
+ QString szTmp = szRetPath.ptr(); // FIXME
+ KviFileUtils::adjustFilePath(szTmp);
+ szRetPath = szTmp;
+ return KviFileUtils::fileExists(filename);
+ }
+
+ // FIXME: #warning "Use the user defined path ?"
+
+ // lookup the magic by name match only...
+
+ if(findFileByMediaType(szRetPath,filename))return true;
+
+ int i;
+
+ for(i= 0;i<5; i++)
+ {
+ getLocalKvircDirectory(szRetPath,localsubdirs[i],filename);
+ if(KviFileUtils::fileExists(szRetPath.ptr()))return true;
+ }
+
+ for(i= 0;i<3; i++)
+ {
+ getGlobalKvircDirectory(szRetPath,globalsubdirs[i],filename);
+ if(KviFileUtils::fileExists(szRetPath.ptr()))return true;
+ }
+
+ if(findImageInImageSearchPath(szRetPath,filename))return true;
+
+ // Last resort ...
+ szRetPath = QDir::homeDirPath();
+ szRetPath.ensureLastCharIs(KVI_PATH_SEPARATOR_CHAR);
+ szRetPath.append(filename);
+ if(KviFileUtils::fileExists(szRetPath.ptr()))return true;;
+
+ szRetPath = filename;
+ //if(retMediaType)*retMediaType = m;
+ return false;
+
+//gotit:
+ //if(retMediaType)*retMediaType = g_pMediaManager->findMediaType(szRetPath.ptr());
+// return true;
+}
+
+//========================= findImage ===========================//
+//
+// Find a file inside the default "Image" directories
+// This should be thread safe (and in fact IS used by other threads)
+// This function should be used only for finding the INTERNAL
+// pixmaps... (so we expect them to be in the pics directory or
+// Eventually in user's $HOME
+//
+
+// FIXME: #warning "Check WHEN findImage is used and when findUserFile is used...we have a mess here"
+
+bool KviApp::findImageInImageSearchPath(KviStr &szRetPath,const char * filename)
+{
+ // first lookup the user defined paths
+ for(QStringList::Iterator it = KVI_OPTION_STRINGLIST(KviOption_stringlistImageSearchPaths).begin();
+ it != KVI_OPTION_STRINGLIST(KviOption_stringlistImageSearchPaths).end();++it)
+ {
+ szRetPath = *it;
+ szRetPath.ensureLastCharIs(KVI_PATH_SEPARATOR_CHAR);
+ szRetPath.append(filename);
+ //debug("LOOK FOR %s",szRetPath.ptr());
+ if(KviFileUtils::fileExists(szRetPath.ptr()))return true;
+ }
+
+ return false;
+}
+
+bool KviApp::findImageInImageSearchPath(QString &szRetPath,const char * filename)
+{
+ // first lookup the user defined paths
+ for(QStringList::Iterator it = KVI_OPTION_STRINGLIST(KviOption_stringlistImageSearchPaths).begin();
+ it != KVI_OPTION_STRINGLIST(KviOption_stringlistImageSearchPaths).end();++it)
+ {
+ szRetPath = *it;
+ KviQString::ensureLastCharIs(szRetPath,KVI_PATH_SEPARATOR_CHAR);
+ szRetPath.append(filename);
+ //debug("LOOK FOR %s",szRetPath.ptr());
+ if(KviFileUtils::fileExists(szRetPath))return true;
+ }
+
+ return false;
+}
+
+static KviApp::KvircSubdir pics_localsubdirs[2]={ KviApp::Pics , KviApp::Avatars };
+static KviApp::KvircSubdir pics_globalsubdirs[2]={ KviApp::Pics , KviApp::Avatars };
+
+bool KviApp::mapImageFile(KviStr &szRetPath,const char * filename)
+{
+ QString buff;
+ bool ret=mapImageFile(buff,filename);
+ szRetPath=buff;
+ return ret;
+}
+
+bool KviApp::mapImageFile(QString &szRetPath,const char * filename)
+{
+ szRetPath = filename;
+ // can't map non absolute paths
+ if(!kvi_isAbsolutePath(filename))return false;
+ // can't map non existing paths
+ if(!KviFileUtils::fileExists(filename))return false;
+
+ QFileInfo fi = QFileInfo(QString::fromUtf8(filename));
+
+ unsigned int size = fi.size();
+
+ KviStr szBestMatch;
+
+ while(szRetPath.find(KVI_PATH_SEPARATOR) != -1)
+ {
+ KviQString::cutToFirst(szRetPath,KVI_PATH_SEPARATOR);
+
+ if(szRetPath.isEmpty())break;
+
+ KviStr szBuffer;
+
+ int i;
+
+ for(i=0;i<2;i++)
+ {
+ getLocalKvircDirectory(szBuffer,pics_localsubdirs[i],szRetPath);
+ if(KviFileUtils::fileExists(szBuffer.ptr()))
+ {
+ QFileInfo fi2(QString::fromUtf8(szBuffer.ptr()));
+ if(size == fi2.size())
+ {
+ // probably the same file
+ szBestMatch = szRetPath;
+ }
+ }
+ }
+
+ for(i=0;i<2;i++)
+ {
+ getGlobalKvircDirectory(szBuffer,pics_globalsubdirs[i],szRetPath);
+ //debug("CHECK %s",szBuffer.ptr());
+ if(KviFileUtils::fileExists(szBuffer.ptr()))
+ {
+ QFileInfo fi2(QString::fromUtf8(szBuffer.ptr()));
+ if(size == fi2.size())
+ {
+ // probably the same file
+ szBestMatch = szRetPath;
+ }
+ }
+ }
+
+ // Last resort
+ szBuffer = QDir::homeDirPath();
+ szBuffer.ensureLastCharIs(KVI_PATH_SEPARATOR_CHAR);
+ szBuffer.append(szRetPath);
+ if(KviFileUtils::fileExists(szBuffer.ptr()))
+ {
+ QFileInfo fi2(QString::fromUtf8(szBuffer.ptr()));
+ if(size == fi2.size())
+ {
+ // prolly the same file
+ szBestMatch = szRetPath;
+ }
+ }
+ }
+
+ if(szBestMatch.hasData())
+ {
+ szRetPath = szBestMatch;
+ return true;
+ }
+
+
+ // no way to map it :/
+ szRetPath = filename;
+ return false;
+}
+
+
+bool KviApp::findImage(KviStr &szRetPath,const char *filename)
+{
+ QString buff;
+ bool ret=findImage(buff,filename);
+ szRetPath=buff;
+ return ret;
+}
+
+bool KviApp::findImage(QString &szRetPath,const char *filename)
+{
+ // Find an user file...
+ if(kvi_isAbsolutePath(filename))
+ {
+ szRetPath=filename;
+ return KviFileUtils::fileExists(filename);
+ }
+
+ // if we have a theme, look it up as first
+ if(!KVI_OPTION_STRING(KviOption_stringIconThemeSubdir).isEmpty())
+ {
+ QString szTmp = KVI_OPTION_STRING(KviOption_stringIconThemeSubdir);
+ szTmp.append(KVI_PATH_SEPARATOR_CHAR);
+ szTmp.append(filename);
+
+ getLocalKvircDirectory(szRetPath,KviApp::Themes,szTmp);
+ if(KviFileUtils::fileExists(szRetPath))return true;
+
+ getGlobalKvircDirectory(szRetPath,KviApp::Themes,szTmp);
+ if(KviFileUtils::fileExists(szRetPath))return true;
+ }
+
+ int i;
+
+ for(i=0;i<2;i++)
+ {
+ getLocalKvircDirectory(szRetPath,pics_localsubdirs[i],filename);
+ if(KviFileUtils::fileExists(szRetPath))return true;
+ }
+
+ for(i=0;i<2;i++)
+ {
+ getGlobalKvircDirectory(szRetPath,pics_globalsubdirs[i],filename);
+ if(KviFileUtils::fileExists(szRetPath))return true;
+ }
+
+ if(findImageInImageSearchPath(szRetPath,filename))return true;
+
+ // Last resort
+ szRetPath = QDir::homeDirPath();
+ KviQString::ensureLastCharIs(szRetPath,KVI_PATH_SEPARATOR_CHAR);
+ szRetPath.append(filename);
+ if(KviFileUtils::fileExists(szRetPath))return true;
+
+ szRetPath = filename;
+
+ return false;
+}
+
+bool KviApp::findImageThemeOnlyCompat(QString &szRetPath,const char *filename)
+{
+ // if we have a theme, look it up as first
+ if(!KVI_OPTION_STRING(KviOption_stringIconThemeSubdir).isEmpty())
+ {
+ QString szTmp = KVI_OPTION_STRING(KviOption_stringIconThemeSubdir);
+ szTmp.append(KVI_PATH_SEPARATOR_CHAR);
+ szTmp.append(filename);
+
+ getLocalKvircDirectory(szRetPath,KviApp::Themes,szTmp);
+ if(KviFileUtils::fileExists(szRetPath))return true;
+
+ getGlobalKvircDirectory(szRetPath,KviApp::Themes,szTmp);
+ if(KviFileUtils::fileExists(szRetPath))return true;
+ }
+
+ getLocalKvircDirectory(szRetPath,KviApp::Pics,filename);
+ if(KviFileUtils::fileExists(szRetPath))return true;
+
+
+ if(findImageInImageSearchPath(szRetPath,filename))return true;
+
+ szRetPath = filename;
+
+ return false;
+}
+
+bool KviApp::findSmallIcon(QString &szRetPath,const char *filename)
+{
+ // this is a bit optimized for the small builtin icons
+ // looks up less places.
+
+ //if(kvi_isAbsolutePath(filename))
+ //{
+ // BUG!.. we should never
+ //szRetPath=filename;
+ //return KviFileUtils::fileExists(filename);
+ //}
+
+ // if we have a theme, look it up as first
+ if(!KVI_OPTION_STRING(KviOption_stringIconThemeSubdir).isEmpty())
+ {
+ QString szTmp = KVI_OPTION_STRING(KviOption_stringIconThemeSubdir);
+ szTmp.append(KVI_PATH_SEPARATOR_CHAR);
+ szTmp.append(KVI_SMALLICONS_SUBDIRECTORY);
+ szTmp.append(KVI_PATH_SEPARATOR_CHAR);
+ szTmp.append(filename);
+
+ getLocalKvircDirectory(szRetPath,KviApp::Themes,szTmp);
+ if(KviFileUtils::fileExists(szRetPath))return true;
+
+ getGlobalKvircDirectory(szRetPath,KviApp::Themes,szTmp);
+ if(KviFileUtils::fileExists(szRetPath))return true;
+ }
+
+ int i;
+
+ // unlikely
+ getLocalKvircDirectory(szRetPath,KviApp::SmallIcons,filename);
+ if(KviFileUtils::fileExists(szRetPath))return true;
+
+ getLocalKvircDirectory(szRetPath,KviApp::Pics,filename);
+ if(KviFileUtils::fileExists(szRetPath))return true;
+
+ // likely
+ getGlobalKvircDirectory(szRetPath,KviApp::SmallIcons,filename);
+ if(KviFileUtils::fileExists(szRetPath))return true;
+
+ if(findImageInImageSearchPath(szRetPath,filename))return true;
+
+ // Last resort... bleah :/
+ szRetPath = QDir::homeDirPath();
+ KviQString::ensureLastCharIs(szRetPath,KVI_PATH_SEPARATOR_CHAR);
+ szRetPath.append(filename);
+ if(KviFileUtils::fileExists(szRetPath))return true;
+
+ szRetPath = filename;
+
+ return false;
+}
+
+
+//================== getReadOnlyConfigPath ====================//
+//
+// We want to READ a config file...find it
+//
+
+bool KviApp::getReadOnlyConfigPath(KviStr &buffer,const char *config_name,KvircSubdir sbd,bool bNoFail)
+{
+ // DEPRECATED
+ QString tmp;
+ bool bRet = getReadOnlyConfigPath(tmp,config_name,sbd,bNoFail);
+ buffer = tmp;
+ return bRet;
+}
+
+bool KviApp::getReadOnlyConfigPath(QString &buffer,const char *config_name,KvircSubdir sbd,bool bNoFail)
+{
+ // Take a look in the local directory....
+ getLocalKvircDirectory(buffer,sbd,config_name);
+ //debug("%s %s %i |%s| %i",__FILE__,__FUNCTION__,__LINE__,buffer.ptr(),KviFileUtils::fileExists(buffer.ptr()));
+ if(!KviFileUtils::fileExists(buffer))
+ {
+ // No saved config yet... check for defaults
+ QString tmp;
+ getGlobalKvircDirectory(tmp,sbd,config_name);
+ if(!KviFileUtils::fileExists(tmp))
+ {
+ // No defaults...no such config file at all.
+ if(bNoFail)getLocalKvircDirectory(buffer,sbd,config_name);
+ return false;
+ } else buffer = tmp; // get the defaults this time
+ } // else file exists...
+ return true;
+}
diff --git a/src/kvirc/kernel/kvi_app_setup.cpp b/src/kvirc/kernel/kvi_app_setup.cpp
new file mode 100644
index 00000000..1c9f3886
--- /dev/null
+++ b/src/kvirc/kernel/kvi_app_setup.cpp
@@ -0,0 +1,864 @@
+//=============================================================================
+//
+// File : kvi_app_setup.cpp
+// Creation date : Fri Apr 2 1999 02:38:05 by Szymon Stefanek
+//
+// This file is part of the Kvirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+//#define _KVI_DEBUG_CHECK_RANGE_
+//#include "kvi_debug.h"
+
+#include <qtextcodec.h>
+
+#include "kvi_settings.h"
+#include "kvi_defaults.h"
+
+#include "kvi_window.h"
+#include "kvi_frame.h"
+
+#include "kvi_app.h"
+
+#include "kvi_fileutils.h"
+#include "kvi_locale.h"
+#include "kvi_msgbox.h"
+#include "kvi_library.h"
+#include "kvi_sourcesdate.h"
+#include "kvi_iconmanager.h"
+#include "kvi_config.h"
+
+#ifndef COMPILE_ON_WINDOWS
+
+ #include <stdlib.h> // for getenv()
+ #include <unistd.h> // for symlink() <-- unused ?
+
+ #ifdef COMPILE_KDE_SUPPORT
+ #include <kconfig.h>
+ #include <kstddirs.h>
+ #endif
+
+#else
+
+ #include <shlwapi.h>
+ #include <windows.h> // at least for GetModuleFileName and *PrivateProfileString
+
+#endif //COMPILE_ON_WINDOWS
+
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qdir.h>
+
+
+
+
+//
+// Things launched at startup:
+// - Attempt to find the global Kvirc directory
+// - Attempt to find the local Kvirc directory
+// and if it is not found , ask the user to choose one
+//
+
+bool KviApp::checkGlobalKvircDirectory(const QString dir)
+{
+ //First check if the help subdir exists
+ QString szDir2 = dir;
+ szDir2+=KVI_PATH_SEPARATOR"help";
+ if(!KviFileUtils::directoryExists(szDir2))return false;
+ //Then check if the pics subdir exists
+ QString szDir = dir;
+ szDir+=KVI_PATH_SEPARATOR"pics";
+ if(!KviFileUtils::directoryExists(szDir))return false;
+ //Now make sure that it is the dir that we're looking for.
+ //Check for an image file that we need.
+ szDir.append(KVI_PATH_SEPARATOR);
+ szDir.append(KVI_ACTIVITYMETER_IMAGE_NAME);
+ return KviFileUtils::isReadable(szDir);
+}
+
+bool KviApp::checkLocalKvircDirectory(const QString szDir)
+{
+ //First check if the dir exists
+ if(!KviFileUtils::directoryExists(szDir))return false;
+ if(!QFileInfo(szDir).isWritable()) return false;
+
+ QString szBuff;
+ getLocalKvircDirectory(szBuff,Config);
+ if(!KviFileUtils::directoryExists(szBuff)) return false;
+
+ return true;
+}
+
+bool KviApp::checkFileAssociations()
+{
+#ifdef COMPILE_ON_WINDOWS
+#define QUERY_BUFFER 2048
+ char* buffer;
+ DWORD len = QUERY_BUFFER;
+ DWORD err;
+ buffer = (char*)malloc(len*sizeof(char));
+ HKEY hKey;
+
+ if(RegOpenKeyEx(HKEY_CLASSES_ROOT,".kvs",0,KEY_READ,&hKey) != ERROR_SUCCESS )
+ return false;
+
+ if( (err=RegQueryValueEx( hKey,0,0,0,(LPBYTE)buffer,&len)) != ERROR_SUCCESS)
+ {
+ free(buffer);
+ return false;
+ } else {
+ if(!kvi_strEqualCIN("KVIrcScript",buffer,11)){
+ free(buffer);
+ return false;
+ }
+ }
+
+ len = QUERY_BUFFER;
+ if(RegOpenKeyEx(HKEY_CLASSES_ROOT,"KVIrcScript",0,KEY_READ,&hKey) != ERROR_SUCCESS )
+ return false;
+
+ if( (err=RegQueryValueEx( hKey,0,0,0,(LPBYTE)buffer,&len)) != ERROR_SUCCESS)
+ {
+ free(buffer);
+ return false;
+ } else {
+ if(!kvi_strEqualCI(__tr2qs("KVIrc KVS Script").local8Bit().data(),buffer)){
+ free(buffer);
+ return false;
+ }
+ }
+
+ len = QUERY_BUFFER;
+ if(RegOpenKeyEx(HKEY_CLASSES_ROOT,"KVIrcScript\\DefaultIcon",0,KEY_READ,&hKey) != ERROR_SUCCESS )
+ return false;
+
+ if( RegQueryValueEx( hKey,0,0,0,(LPBYTE)buffer,&len) != ERROR_SUCCESS)
+ {
+ free(buffer);
+ return false;
+ } else {
+ QString szIcon = applicationFilePath()+",1";
+ szIcon.replace('/',"\\");
+ if(!kvi_strEqualCI(szIcon.local8Bit().data(),buffer)){
+ free(buffer);
+ return false;
+ }
+ }
+
+ len = QUERY_BUFFER;
+ if(RegOpenKeyEx(HKEY_CLASSES_ROOT,"KVIrcScript\\Shell\\Parse",0,KEY_READ,&hKey) != ERROR_SUCCESS )
+ return false;
+
+ if( RegQueryValueEx( hKey,0,0,0,(LPBYTE)buffer,&len) != ERROR_SUCCESS)
+ {
+ free(buffer);
+ return false;
+ } else {
+ if(!kvi_strEqualCI(__tr2qs("Run KVS Script").local8Bit().data(),buffer)){
+ free(buffer);
+ return false;
+ }
+ }
+
+ len = QUERY_BUFFER;
+ if(RegOpenKeyEx(HKEY_CLASSES_ROOT,"KVIrcScript\\Shell\\Parse\\command",0,KEY_READ,&hKey) != ERROR_SUCCESS )
+ return false;
+
+ if( RegQueryValueEx( hKey,0,0,0,(LPBYTE)buffer,&len) != ERROR_SUCCESS)
+ {
+ free(buffer);
+ return false;
+ } else {
+ QString szCmd = applicationFilePath()+" \"%1\"";
+ szCmd.replace('/',"\\");
+ if(!kvi_strEqualCI(szCmd.local8Bit().data(),buffer)) {
+ free(buffer);
+ return false;
+ }
+ }
+
+ //Config
+
+ if(RegOpenKeyEx(HKEY_CLASSES_ROOT,".kvc",0,KEY_READ,&hKey) != ERROR_SUCCESS )
+ return false;
+
+ if( (err=RegQueryValueEx( hKey,0,0,0,(LPBYTE)buffer,&len)) != ERROR_SUCCESS)
+ {
+ free(buffer);
+ return false;
+ } else {
+ if(!kvi_strEqualCIN("KVIrcConfig",buffer,11)){
+ free(buffer);
+ return false;
+ }
+ }
+
+ len = QUERY_BUFFER;
+ if(RegOpenKeyEx(HKEY_CLASSES_ROOT,"KVIrcConfig",0,KEY_READ,&hKey) != ERROR_SUCCESS )
+ return false;
+
+ //Addon
+ if(RegOpenKeyEx(HKEY_CLASSES_ROOT,".kva",0,KEY_READ,&hKey) != ERROR_SUCCESS )
+ return false;
+
+ if( (err=RegQueryValueEx( hKey,0,0,0,(LPBYTE)buffer,&len)) != ERROR_SUCCESS)
+ {
+ free(buffer);
+ return false;
+ } else {
+ if(!kvi_strEqualCIN("KVIrcAddon",buffer,11)){
+ free(buffer);
+ return false;
+ }
+ }
+
+ len = QUERY_BUFFER;
+ if(RegOpenKeyEx(HKEY_CLASSES_ROOT,"KVIrcAddon",0,KEY_READ,&hKey) != ERROR_SUCCESS )
+ return false;
+ //Theme
+ if(RegOpenKeyEx(HKEY_CLASSES_ROOT,".kvt",0,KEY_READ,&hKey) != ERROR_SUCCESS )
+ return false;
+
+ if( (err=RegQueryValueEx( hKey,0,0,0,(LPBYTE)buffer,&len)) != ERROR_SUCCESS)
+ {
+ free(buffer);
+ return false;
+ } else {
+ if(!kvi_strEqualCIN("KVIrcTheme",buffer,11)){
+ free(buffer);
+ return false;
+ }
+ }
+
+ len = QUERY_BUFFER;
+ if(RegOpenKeyEx(HKEY_CLASSES_ROOT,"KVIrcTheme",0,KEY_READ,&hKey) != ERROR_SUCCESS )
+ return false;
+
+ free(buffer);
+#endif
+ return true;
+
+}
+
+
+bool KviApp::checkUriAssociations(char * proto)
+{
+#ifdef COMPILE_ON_WINDOWS
+#define QUERY_BUFFER 2048
+ char* buffer;
+ DWORD len = QUERY_BUFFER;
+ DWORD err;
+ buffer = (char*)malloc(len*sizeof(char));
+ HKEY hKey;
+
+ KviStr storedKey = proto;
+
+ KviStr key=storedKey;
+
+ len = QUERY_BUFFER;
+ if(RegOpenKeyEx(HKEY_CLASSES_ROOT,key,0,KEY_READ,&hKey) != ERROR_SUCCESS )
+ return false;
+
+ if( (err=RegQueryValueEx( hKey,0,0,0,(LPBYTE)buffer,&len)) != ERROR_SUCCESS)
+ {
+ free(buffer);
+ return false;
+ } else {
+ if(!kvi_strEqualCI(__tr2qs("URL:IRC Protocol").local8Bit().data(),buffer)){
+ free(buffer);
+ return false;
+ }
+ }
+
+ len = QUERY_BUFFER;
+ if( (err=RegQueryValueEx( hKey,"URL Protocol",0,0,(LPBYTE)buffer,&len)) != ERROR_SUCCESS)
+ {
+ free(buffer);
+ return false;
+ }
+
+ key = storedKey+"\\DefaultIcon";
+ len = QUERY_BUFFER;
+ if(RegOpenKeyEx(HKEY_CLASSES_ROOT,key,0,KEY_READ,&hKey) != ERROR_SUCCESS )
+ return false;
+
+ if( RegQueryValueEx( hKey,0,0,0,(LPBYTE)buffer,&len) != ERROR_SUCCESS)
+ {
+ free(buffer);
+ return false;
+ } else {
+ QString szIcon = applicationFilePath()+",0";
+ szIcon.replace('/',"\\");
+ if(!kvi_strEqualCI(szIcon.local8Bit().data(),buffer)){
+ free(buffer);
+ return false;
+ }
+ }
+
+ len = QUERY_BUFFER;
+ key = storedKey+"\\Shell\\open";
+ if(RegOpenKeyEx(HKEY_CLASSES_ROOT,key,0,KEY_READ,&hKey) != ERROR_SUCCESS )
+ return false;
+
+ if( RegQueryValueEx( hKey,0,0,0,(LPBYTE)buffer,&len) != ERROR_SUCCESS)
+ {
+ free(buffer);
+ return false;
+ } else {
+ if(!kvi_strEqualCI(__tr2qs("Open with KVIrc").local8Bit().data(),buffer)){
+ free(buffer);
+ return false;
+ }
+ }
+
+ len = QUERY_BUFFER;
+ key = storedKey+"\\Shell\\open\\command";
+ if(RegOpenKeyEx(HKEY_CLASSES_ROOT,key,0,KEY_READ,&hKey) != ERROR_SUCCESS )
+ return false;
+
+ if( RegQueryValueEx( hKey,0,0,0,(LPBYTE)buffer,&len) != ERROR_SUCCESS)
+ {
+ free(buffer);
+ return false;
+ } else {
+ QString szCmd = applicationFilePath()+" \"%1\"";
+ szCmd.replace('/',"\\");
+ if(!kvi_strEqualCI(szCmd.local8Bit().data(),buffer)) {
+ free(buffer);
+ return false;
+ }
+ }
+
+ free(buffer);
+#endif
+ return true;
+
+}
+
+
+void KviApp::setupUriAssociations(char * proto)
+{
+#ifdef COMPILE_ON_WINDOWS
+ HKEY hKey;
+ DWORD err;
+
+ KviStr storedKey = proto;
+
+ KviStr key=storedKey;
+
+ KviQCString tmp;
+ QString appPath = applicationFilePath();
+ appPath.replace('/',"\\");
+
+ SHDeleteKey(HKEY_CLASSES_ROOT,key);
+
+ err=RegCreateKeyEx(HKEY_CLASSES_ROOT,key,0,0,0,KEY_WRITE,0,&hKey,0);
+ RegSetValueEx( hKey,0,0,REG_SZ,(LPBYTE)"URL:IRC Protocol",16);
+ RegSetValueEx( hKey,"URL Protocol",0,REG_SZ,(LPBYTE)"",0);
+
+ key=storedKey+"\\DefaultIcon";
+ RegCreateKeyEx(HKEY_CLASSES_ROOT,key,0,0,0,KEY_WRITE,0,&hKey,0);
+ tmp=QString(appPath+",0").local8Bit();
+ RegSetValueEx( hKey,0,0,REG_SZ,(LPBYTE)tmp.data(),tmp.length());
+
+ key=storedKey+"\\Shell\\open";
+ RegCreateKeyEx(HKEY_CLASSES_ROOT,key,0,0,0,KEY_WRITE,0,&hKey,0);
+ tmp=__tr2qs("Open with KVIrc").local8Bit();
+ RegSetValueEx( hKey,0,0,REG_SZ,(LPBYTE)tmp.data(),tmp.length());
+
+ key=storedKey+"\\Shell\\open\\command";
+ RegCreateKeyEx(HKEY_CLASSES_ROOT,key,0,0,0,KEY_WRITE,0,&hKey,0);
+ tmp=QString(appPath+" \"%1\"").local8Bit();
+ RegSetValueEx( hKey,0,0,REG_SZ,(LPBYTE)tmp.data(),tmp.length());
+
+#endif
+}
+
+void KviApp::setupFileAssociations()
+{
+#ifdef COMPILE_ON_WINDOWS
+ HKEY hKey;
+ DWORD err;
+
+ KviQCString tmp;
+ QString appPath = applicationFilePath();
+ appPath.replace('/',"\\");
+
+ SHDeleteKey(HKEY_CLASSES_ROOT,".kvs");
+
+ err=RegCreateKeyEx(HKEY_CLASSES_ROOT,".kvs",0,0,0,KEY_WRITE,0,&hKey,0);
+ RegSetValueEx( hKey,0,0,REG_SZ,(LPBYTE)"KVIrcScript",11);
+
+
+ SHDeleteKey(HKEY_CLASSES_ROOT,"KVIrcScript");
+ RegCreateKeyEx(HKEY_CLASSES_ROOT,"KVIrcScript",0,0,0,KEY_WRITE,0,&hKey,0);
+ tmp = __tr2qs("KVIrc KVS Script").local8Bit();
+ RegSetValueEx( hKey,0,0,REG_SZ,(LPBYTE)tmp.data(),tmp.length());
+
+ RegCreateKeyEx(HKEY_CLASSES_ROOT,"KVIrcScript\\DefaultIcon",0,0,0,KEY_WRITE,0,&hKey,0);
+ tmp=QString(appPath+",1").local8Bit();
+ RegSetValueEx( hKey,0,0,REG_SZ,(LPBYTE)tmp.data(),tmp.length());
+
+ RegCreateKeyEx(HKEY_CLASSES_ROOT,"KVIrcScript\\Shell\\Parse",0,0,0,KEY_WRITE,0,&hKey,0);
+ tmp=__tr2qs("Run KVS Script").local8Bit();
+ RegSetValueEx( hKey,0,0,REG_SZ,(LPBYTE)tmp.data(),tmp.length());
+
+ RegCreateKeyEx(HKEY_CLASSES_ROOT,"KVIrcScript\\Shell\\Parse\\command",0,0,0,KEY_WRITE,0,&hKey,0);
+ tmp=QString(appPath+" \"%1\"").local8Bit();
+ RegSetValueEx( hKey,0,0,REG_SZ,(LPBYTE)tmp.data(),tmp.length());
+
+ //Configs
+ SHDeleteKey(HKEY_CLASSES_ROOT,".kvc");
+
+ err=RegCreateKeyEx(HKEY_CLASSES_ROOT,".kvc",0,0,0,KEY_WRITE,0,&hKey,0);
+ RegSetValueEx( hKey,0,0,REG_SZ,(LPBYTE)"KVIrcConfig",11);
+
+
+ SHDeleteKey(HKEY_CLASSES_ROOT,"KVIrcConfig");
+ RegCreateKeyEx(HKEY_CLASSES_ROOT,"KVIrcConfig",0,0,0,KEY_WRITE,0,&hKey,0);
+ tmp = __tr2qs("KVIrc Configuration File").local8Bit();
+ RegSetValueEx( hKey,0,0,REG_SZ,(LPBYTE)tmp.data(),tmp.length());
+
+ RegCreateKeyEx(HKEY_CLASSES_ROOT,"KVIrcConfig\\DefaultIcon",0,0,0,KEY_WRITE,0,&hKey,0);
+ tmp=QString(appPath+",2").local8Bit();
+ RegSetValueEx( hKey,0,0,REG_SZ,(LPBYTE)tmp.data(),tmp.length());
+
+ // Themes
+
+ SHDeleteKey(HKEY_CLASSES_ROOT,".kvt");
+
+ err=RegCreateKeyEx(HKEY_CLASSES_ROOT,".kvt",0,0,0,KEY_WRITE,0,&hKey,0);
+ RegSetValueEx( hKey,0,0,REG_SZ,(LPBYTE)"KVIrcTheme",11);
+
+
+ SHDeleteKey(HKEY_CLASSES_ROOT,"KVIrcTheme");
+ RegCreateKeyEx(HKEY_CLASSES_ROOT,"KVIrcTheme",0,0,0,KEY_WRITE,0,&hKey,0);
+ tmp = __tr2qs("KVIrc Theme Package").local8Bit();
+ RegSetValueEx( hKey,0,0,REG_SZ,(LPBYTE)tmp.data(),tmp.length());
+
+ RegCreateKeyEx(HKEY_CLASSES_ROOT,"KVIrcTheme\\DefaultIcon",0,0,0,KEY_WRITE,0,&hKey,0);
+ tmp=QString(appPath+",3").local8Bit();
+ RegSetValueEx( hKey,0,0,REG_SZ,(LPBYTE)tmp.data(),tmp.length());
+
+ RegCreateKeyEx(HKEY_CLASSES_ROOT,"KVIrcTheme\\Shell\\Install",0,0,0,KEY_WRITE,0,&hKey,0);
+ tmp=__tr2qs("Install Theme Package").local8Bit();
+ RegSetValueEx( hKey,0,0,REG_SZ,(LPBYTE)tmp.data(),tmp.length());
+
+ RegCreateKeyEx(HKEY_CLASSES_ROOT,"KVIrcTheme\\Shell\\Install\\command",0,0,0,KEY_WRITE,0,&hKey,0);
+ tmp=QString(appPath+" \"%1\"").local8Bit();
+ RegSetValueEx( hKey,0,0,REG_SZ,(LPBYTE)tmp.data(),tmp.length());
+
+ //Addons
+
+ SHDeleteKey(HKEY_CLASSES_ROOT,".kva");
+
+ err=RegCreateKeyEx(HKEY_CLASSES_ROOT,".kva",0,0,0,KEY_WRITE,0,&hKey,0);
+ RegSetValueEx( hKey,0,0,REG_SZ,(LPBYTE)"KVIrcAddon",11);
+
+
+ SHDeleteKey(HKEY_CLASSES_ROOT,"KVIrcAddon");
+ RegCreateKeyEx(HKEY_CLASSES_ROOT,"KVIrcAddon",0,0,0,KEY_WRITE,0,&hKey,0);
+ tmp = __tr2qs("KVIrc Addon Package").local8Bit();
+ RegSetValueEx( hKey,0,0,REG_SZ,(LPBYTE)tmp.data(),tmp.length());
+
+ RegCreateKeyEx(HKEY_CLASSES_ROOT,"KVIrcAddon\\DefaultIcon",0,0,0,KEY_WRITE,0,&hKey,0);
+ tmp=QString(appPath+",4").local8Bit();
+ RegSetValueEx( hKey,0,0,REG_SZ,(LPBYTE)tmp.data(),tmp.length());
+
+ RegCreateKeyEx(HKEY_CLASSES_ROOT,"KVIrcAddon\\Shell\\Install",0,0,0,KEY_WRITE,0,&hKey,0);
+ tmp=__tr2qs("Install Package").local8Bit();
+ RegSetValueEx( hKey,0,0,REG_SZ,(LPBYTE)tmp.data(),tmp.length());
+
+ RegCreateKeyEx(HKEY_CLASSES_ROOT,"KVIrcAddon\\Shell\\Install\\command",0,0,0,KEY_WRITE,0,&hKey,0);
+ tmp=QString(appPath+" \"%1\"").local8Bit();
+ RegSetValueEx( hKey,0,0,REG_SZ,(LPBYTE)tmp.data(),tmp.length());
+
+#endif
+}
+
+//#ifdef BRAIN_DAMAGED_AUTHOR_PARANOIA
+//#define I_DO_NOT_WANT_TO_HEAR_IT_ANYMORE_THAT_KVIRC_CAN_NOT_FIND_THE_BASE_PIXMAPS
+
+// search paths for Unix-like platforms
+#ifndef COMPILE_ON_WINDOWS
+ const char * usualKvircGlobalPrePath[]=
+ {
+ "/usr/local", "/opt/kde", "/usr",
+ "/usr/local/lib", "/opt/kde3", "/usr/lib",
+ "/usr/local/kde", "/opt", "/usr/etc",
+ "/usr/local/kde3", "/usr/lib/X11R6", "/usr/X11R6",
+ "/usr/local/X11R6", "/lib/X11", "/usr/kde",
+ "/usr/local/X11", "/etc", "/usr/kde3",
+ "/usr/local/etc", "/lib", "/usr/X11",
+ "/etc/X11", "/home", "/home/kvirc",
+ 0
+ };
+
+ const char * usualKvircGlobalDir[]=
+ {
+ "/share/kvirc/", "/share/apps/kvirc/",
+ "/apps/kvirc/", "/kvirc/",
+ "/kvirc/share/apps/kvirc/", "/kvirc/share/kvirc/", //<------ ???!!!???
+ "/kvirc/share/", 0
+ };
+
+#endif //!COMPILE_ON_WINDOWS
+
+//#endif //BRAIN_DAMAGED_AUTHOR_PARANOIA
+
+void KviApp::findGlobalKvircDirectory()
+{
+ // Look for the installation directory
+ // with the image and help files inside
+#ifdef GLOBAL_KVIRC_DIR
+ m_szGlobalKvircDir = GLOBAL_KVIRC_DIR;
+ KviFileUtils::adjustFilePath(m_szGlobalKvircDir);
+ if(checkGlobalKvircDirectory(m_szGlobalKvircDir))return;
+#endif //GLOBAL_KVIRC_DIR
+
+#ifdef COMPILE_ON_WINDOWS
+
+ m_szGlobalKvircDir = applicationDirPath();
+ KviFileUtils::adjustFilePath(m_szGlobalKvircDir);
+ if(checkGlobalKvircDirectory(m_szGlobalKvircDir))return;
+
+ KviMessageBox::warning("Unable to find the shared Kvirc directory.\n"\
+ "The usual path for this directory is c:\\kvirc\\" KVI_VERSION_BRANCH "\\.\n"\
+ "I have tried %Q, but it seemed to fail\n" \
+ "Trying to run anyway...\n",&m_szGlobalKvircDir);
+#else // !COMPILE_ON_WINDOWS
+
+ // Since I had many problems with it
+ // because of strange distributions or KDEDIRS
+ // I do it in that way...
+ #ifdef COMPILE_KDE_SUPPORT
+ // KDE compilation ...
+ // The things usually go installed into $KDEDIR/share/apps/kvirc/$KVI_VERSION_BRANCH
+ // Look in the main KDE directory
+ KStandardDirs * d = dirs();
+ if(d)
+ {
+ m_szGlobalKvircDir = locate("appdata","");
+ if(checkGlobalKvircDirectory(m_szGlobalKvircDir))return;
+ #ifdef HAVE_GETENV
+ //KDEDIR sanity check...
+ m_szGlobalKvircDir = getenv("KDEDIR");
+ m_szGlobalKvircDir+="/share/apps/kvirc/" KVI_VERSION_BRANCH;
+ if(checkGlobalKvircDirectory(m_szGlobalKvircDir))return;
+ #endif
+ }
+ // FAILED ? Check the usual way...
+ #endif //COMPILE_WITH_KDE
+
+ // Non KDE compilation , or not found under $KDEDIR/share/apps/kvirc/$KVI_VERSION_BRANCH
+
+ // Check for MacOS X Bundle compilation
+ #ifdef Q_OS_MACX
+ m_szGlobalKvircDir = applicationDirPath();
+ m_szGlobalKvircDir+= "/../Resources/kvirc/";
+ m_szGlobalKvircDir+= KVI_VERSION_BRANCH;
+ if(checkGlobalKvircDirectory(m_szGlobalKvircDir))return;
+ #endif //Q_OS_MACX
+
+ // Check usual directories...
+ for(int j=0;usualKvircGlobalPrePath[j] != 0;j++){
+ for(int i=0;usualKvircGlobalDir[i] != 0;i++){
+ m_szGlobalKvircDir = usualKvircGlobalPrePath[j];
+ m_szGlobalKvircDir+= usualKvircGlobalDir[i];
+ m_szGlobalKvircDir+= KVI_VERSION_BRANCH;
+ if(checkGlobalKvircDirectory(m_szGlobalKvircDir))return;
+ }
+ }
+
+ //Last resource , try $HOME and $HOME/.kde
+ for(int k=0;usualKvircGlobalDir[k] != 0;k++){
+ m_szGlobalKvircDir = QDir::homeDirPath();
+ m_szGlobalKvircDir+= usualKvircGlobalDir[k];
+ m_szGlobalKvircDir+= KVI_VERSION_BRANCH;
+ if(checkGlobalKvircDirectory(m_szGlobalKvircDir))return;
+ }
+
+ #ifdef COMPILE_KDE_SUPPORT
+ for(int k=0;usualKvircGlobalDir[k] != 0;k++){
+ m_szGlobalKvircDir = QDir::homeDirPath();
+ m_szGlobalKvircDir+= "/.kde";
+ m_szGlobalKvircDir+= usualKvircGlobalDir[k];
+ m_szGlobalKvircDir+= KVI_VERSION_BRANCH;
+ if(checkGlobalKvircDirectory(m_szGlobalKvircDir))return;
+ }
+ #endif //COMPILE_KDE_SUPPORT
+
+ m_szGlobalKvircDir="";
+
+ // DO NOT TRANSLATE THIS
+ // THE TRANSLATION DIRECTORY WAS NOT FOUND YET
+ // AND THE LOCALE IS NOT INITIALIZED AT ALL
+
+ #ifdef COMPILE_KDE_SUPPORT
+ KviMessageBox::warning("Unable to find the shared Kvirc directory.\n"\
+ "The usual path for this directory is $KDEDIR/share/apps/kvirc.\n"\
+ "Are you sure that 'make install' worked correctly ?\n"\
+ "Please make sure that you have the read permission to that directory\n"\
+ "and you have set KDEDIR correctly. You may also try to rerun 'make install'.\n"\
+ "A detailed explaination of the Kvirc directory system is in the INSTALL document\n"\
+ "shipped with the kvirc source dirstribution.\n"\
+ "Trying to run anyway...");
+ #elif defined(Q_OS_MACX)
+ KviMessageBox::warning("Unable to find the shared Kvirc directory.\n"\
+ "The usual path for this directory is ./Contents/Resources/kvirc within your application bundle.\n"\
+ "Something went wrong during the bundle creation.\n"\
+ "Please read the documentation and make sure to set proper paths for --prefix, -bindir, -libdir and --datadir during the configure run.\n"\
+ "Trying to run anyway...\n");
+ #else //!defined(COMPILE_KDE_SUPPORT) && !defined(Q_OS_MACX)
+ KviMessageBox::warning("Unable to find the shared Kvirc directory.\n"\
+ "The usual path for this directory is /usr/local/share/kvirc.\n"\
+ "Are you sure that 'make install' worked correctly ?\n"\
+ "Please make sure that you have the read permission to that directory.\n"\
+ "You may also need to rerun 'make install'.\n"\
+ "A detailed explaination of the Kvirc directory system is in the INSTALL document\n"\
+ "shipped with the kvirc source dirstribution.\n"\
+ "Trying to run anyway...\n");
+ #endif //!Q_OS_MACX
+#endif //!COMPILE_ON_WINDOWS
+}
+
+
+bool KviApp::findLocalKvircDirectory()
+{
+ // Here we check if we already did the setup
+ // and we have the kvirc local directory saved somewhere
+#ifdef COMPILE_KDE_SUPPORT
+ if(m_szConfigFile.isEmpty())
+ { // don't do that if user supplied a config file :)
+ KConfig * cfg = config();
+ if(cfg)
+ {
+ if(cfg->getConfigState() == KConfig::ReadWrite)
+ {
+ cfg->setGroup("Main");
+ m_szLocalKvircDir = cfg->readEntry("LocalKvircDirectory","");
+
+ unsigned int uSourcesDate = cfg->readUnsignedNumEntry("SourcesDate",0);
+ if(uSourcesDate < KVI_SOURCES_DATE_NUMERIC_FORCE_SETUP)
+ return false; // we force a setup anyway
+
+ // If we have it , ok...done
+ if(checkLocalKvircDirectory(m_szLocalKvircDir))return true;
+ }
+ }
+ }
+#endif //COMPILE_KDE_SUPPORT
+
+#ifdef COMPILE_ON_WINDOWS
+ if(KviFileUtils::fileExists(g_pApp->applicationDirPath()+KVI_PATH_SEPARATOR_CHAR+"portable")) {
+ m_szLocalKvircDir=g_pApp->applicationDirPath()+KVI_PATH_SEPARATOR_CHAR+"Settings";
+ if(checkLocalKvircDirectory(m_szLocalKvircDir)) return true;
+ }
+#endif
+ //Check if we have a special .kvirc.rc in $HOME
+ QString szF = QDir::homeDirPath();
+
+ if(!m_szConfigFile.isEmpty())
+ {
+ QString szConfig = m_szConfigFile;
+ if(QDir::isRelativePath(szConfig))
+ {
+ szF+=KVI_PATH_SEPARATOR;
+ szF+=szConfig;
+ } else {
+ szF=szConfig;
+ }
+ } else {
+ szF+=KVI_PATH_SEPARATOR;
+ szF+=KVI_HOME_CONFIG_FILE_NAME;
+ }
+ //If the file exists , read the first non empty line.
+ //FIXME: LOCALE BROKEN!!!
+ KviConfig cfgx(szF,KviConfig::Read);
+
+ cfgx.setGroup("Main");
+ m_szLocalKvircDir = cfgx.readEntry("LocalKvircDirectory","");
+
+ unsigned int uSourcesDate = cfgx.readUIntEntry("SourcesDate",0);
+ if(uSourcesDate < KVI_SOURCES_DATE_NUMERIC_FORCE_SETUP)
+ return false; // we force a setup anyway
+
+ // If we have it , ok...done
+ if(checkLocalKvircDirectory(m_szLocalKvircDir))return true;
+ return false;
+}
+
+void KviApp::loadDirectories()
+{
+ // First find the global (readable) one...
+ findGlobalKvircDirectory();
+ // Init locale
+ QString szLocalePath = m_szGlobalKvircDir;
+ szLocalePath.append(KVI_PATH_SEPARATOR);
+ szLocalePath.append("locale");
+ szLocalePath.append(KVI_PATH_SEPARATOR);
+
+ KviLocale::init(this,szLocalePath);
+
+ //__debug_1arg("Global Kvirc directory is %s",m_szGlobalKvircDir.ptr());
+ // Now look for the local (writable) one
+ m_bFirstTimeRun = !findLocalKvircDirectory();
+
+ if(m_bFirstTimeRun)setupBegin();
+ if(!checkFileAssociations()) setupFileAssociations();
+ if(!checkUriAssociations("irc")) setupUriAssociations("irc");
+ if(!checkUriAssociations("ircs")) setupUriAssociations("ircs");
+ if(!checkUriAssociations("irc6")) setupUriAssociations("irc6");
+ if(!checkUriAssociations("ircs6")) setupUriAssociations("ircs6");
+}
+
+static kvi_library_t g_hSetupLibrary = 0;
+
+
+void KviApp::setupBegin()
+{
+ //We must do the setup...ask the user..
+ QString szSetupLib;
+ getGlobalKvircDirectory(szSetupLib,KviApp::Modules);
+ KviQString::ensureLastCharIs(szSetupLib,KVI_PATH_SEPARATOR_CHAR);
+#ifdef COMPILE_ON_WINDOWS
+ szSetupLib.append("kvisetup.dll");
+#else
+ szSetupLib.append("libkvisetup.so");
+#endif
+ g_hSetupLibrary = kvi_library_open(szSetupLib.local8Bit().data());
+ if(!g_hSetupLibrary)
+ {
+ KviMessageBox::warning(__tr2qs("Ops...it looks like I can't load modules on this sytem.\n" \
+ "I have been looking for the %s library but I haven't been able to load it\n" \
+ "due to the following error: \"%s\"\nAborting."),szSetupLib.utf8().data(),kvi_library_error());
+#ifdef COMPILE_ON_WINDOWS
+ ExitProcess(-1);
+#else
+ ::exit(-1);
+#endif
+ }
+
+ bool (*sfunc)() = (bool(*)())kvi_library_symbol(g_hSetupLibrary,"setup_begin");
+ if(!sfunc)
+ {
+ KviMessageBox::warning(__tr2qs("Ops...it looks like you have a broken distribution.\n" \
+ "The setup module does not export the \"setup_begin\" function.\n" \
+ "Aborting!"));
+#ifdef COMPILE_ON_WINDOWS
+ ExitProcess(-1);
+#else
+ ::exit(-1);
+#endif
+ }
+
+ bool bRet = sfunc();
+
+ if(!bRet)
+ {
+ KviMessageBox::warning(__tr2qs("Setup aborted"));
+#ifdef COMPILE_ON_WINDOWS
+ ExitProcess(-1);
+#else //!COMPILE_ON_WINDOWS
+ ::exit(-1);
+#endif //!COMPILE_ON_WINDOWS
+ }
+
+ // Now save it
+ //Let it be done by setup function
+// saveKvircDirectory();
+}
+
+
+void KviApp::setupFinish()
+{
+ if(!g_hSetupLibrary)
+ {
+ debug("Oops... lost the setup library ?");
+ return;
+ }
+
+ void (*sfunc)() = (void(*)())kvi_library_symbol(g_hSetupLibrary,"setup_finish");
+ if(!sfunc)
+ {
+ KviMessageBox::warning(__tr2qs("Ops...it looks like you have a broken distribution.\n" \
+ "The setup module does not export the \"setup_finish\" function.\n" \
+ "Trying to continue anyway..."));
+ }
+
+ sfunc();
+
+ kvi_library_close(g_hSetupLibrary);
+ g_hSetupLibrary = 0;
+}
+
+
+void KviApp::saveKvircDirectory()
+{
+/*
+#ifdef COMPILE_ON_WINDOWS
+ KviStr szKey(KviStr::Format,"LocalKvircDirectory%s",KVI_VERSION_BRANCH);
+ WritePrivateProfileString("kvirc",szKey.ptr(),m_szLocalKvircDir.ptr(),KVI_HOME_CONFIG_FILE_NAME);
+#else //!COMPILE_ON_WINDOWS
+*/
+ // Here we save the local directory path
+#ifdef COMPILE_KDE_SUPPORT
+ // In KDE we use the application config file
+ if(m_szConfigFile.isEmpty())
+ { // not if user supplied a config file
+ KConfig * cfg = config();
+ if(cfg)
+ {
+ if(cfg->getConfigState() == KConfig::ReadWrite)
+ {
+ cfg->setGroup("Main");
+ cfg->writeEntry("LocalKvircDirectory",m_szLocalKvircDir);
+ cfg->writeEntry("SourcesDate",KVI_SOURCES_DATE_NUMERIC);
+ cfg->sync();
+ return;
+ }
+ }
+ }
+#endif //COMPILE_KDE_SUPPORT
+ // In NON-KDE we use $HOME/.kvirc.rc or $HOME/kvirc.ini
+
+ QString szF = QDir::homeDirPath();
+ if(!m_szConfigFile.isEmpty())
+ {//Must be changed from QString::fromLocal8Bit to QTextCodec::codecForLocale()
+ QString szConfig = m_szConfigFile;
+ if(QDir::isRelativePath(szConfig))
+ {
+ szF+=KVI_PATH_SEPARATOR;
+ szF+=szConfig;
+ } else {
+ szF=szConfig;
+ }
+ } else {
+ szF+=KVI_PATH_SEPARATOR;
+ szF+=KVI_HOME_CONFIG_FILE_NAME;
+ }
+ //FIXME: LOCALE BROKEN!!!
+
+ KviConfig cfgx(szF,KviConfig::Write);
+
+ cfgx.setGroup("Main");
+ cfgx.writeEntry("LocalKvircDirectory",m_szLocalKvircDir);
+ cfgx.writeEntry("SourcesDate",KVI_SOURCES_DATE_NUMERIC);
+}
diff --git a/src/kvirc/kernel/kvi_asynchronousconnectiondata.cpp b/src/kvirc/kernel/kvi_asynchronousconnectiondata.cpp
new file mode 100644
index 00000000..a97f4d3a
--- /dev/null
+++ b/src/kvirc/kernel/kvi_asynchronousconnectiondata.cpp
@@ -0,0 +1,39 @@
+//=============================================================================
+//
+// File : kvi_asynchronousconnectiondata.cpp
+// Created on Sun 04 Jul 2004 16:22:25 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_asynchronousconnectiondata.h"
+
+KviAsynchronousConnectionData::KviAsynchronousConnectionData()
+: KviHeapObject()
+{
+ m_pReconnectInfo=0;
+ bUseLastServerInContext = false;
+}
+
+KviAsynchronousConnectionData::~KviAsynchronousConnectionData()
+{
+}
+
diff --git a/src/kvirc/kernel/kvi_asynchronousconnectiondata.h b/src/kvirc/kernel/kvi_asynchronousconnectiondata.h
new file mode 100644
index 00000000..35c41ed3
--- /dev/null
+++ b/src/kvirc/kernel/kvi_asynchronousconnectiondata.h
@@ -0,0 +1,54 @@
+#ifndef _KVI_ASYNCHRONOUSCONNECTIONDATA_H_
+#define _KVI_ASYNCHRONOUSCONNECTIONDATA_H_
+//=============================================================================
+//
+// File : kvi_asynchronousconnectiondata.h
+// Created on Sun 04 Jul 2004 16:22:25 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_heapobject.h"
+#include "kvi_ircserver.h"
+
+class KviAsynchronousConnectionData : public KviHeapObject
+{
+public:
+ KviAsynchronousConnectionData();
+ ~KviAsynchronousConnectionData();
+public:
+ QString szServer;
+ bool bUseLastServerInContext; // this is checked ONLY if szServer is empty
+ kvi_u32_t uPort;
+ bool bPortIsOk;
+ bool bUseIpV6;
+ bool bUseSSL;
+ QString szBindAddress; // ip address (or interface name) to bind the connection to
+ QString szCommandToExecAfterConnect;
+ QString szLinkFilter;
+ QString szPass;
+ QString szNick;
+ QString szInitUMode;
+ KviIrcServerReconnectInfo * m_pReconnectInfo;
+};
+
+#endif //!_KVI_ASYNCHRONOUSCONNECTIONDATA_H_
diff --git a/src/kvirc/kernel/kvi_coreactionnames.h b/src/kvirc/kernel/kvi_coreactionnames.h
new file mode 100644
index 00000000..7309e286
--- /dev/null
+++ b/src/kvirc/kernel/kvi_coreactionnames.h
@@ -0,0 +1,69 @@
+#ifndef _KVI_COREACTIONNAMES_H_
+#define _KVI_COREACTIONNAMES_H_
+//=============================================================================
+//
+// File : kvi_coreactionnames.h
+// Created on Mon 22 Nov 2004 02:30:47 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define KVI_COREACTION_NAME_PREFIX "kvirc."
+
+#define KVI_COREACTION_SERVEROPTIONS (KVI_COREACTION_NAME_PREFIX "serveroptions")
+#define KVI_COREACTION_IDENTITYOPTIONS (KVI_COREACTION_NAME_PREFIX "identityoptions")
+#define KVI_COREACTION_SOCKETSPY (KVI_COREACTION_NAME_PREFIX "socketspy")
+#define KVI_COREACTION_NETWORKLINKS (KVI_COREACTION_NAME_PREFIX "networklinks")
+#define KVI_COREACTION_CHANNELLIST (KVI_COREACTION_NAME_PREFIX "channellist")
+#define KVI_COREACTION_GENERALOPTIONS (KVI_COREACTION_NAME_PREFIX "generaloptions")
+#define KVI_COREACTION_TOOLBAREDITOR (KVI_COREACTION_NAME_PREFIX "toolbareditor")
+#define KVI_COREACTION_JOINCHANNELS (KVI_COREACTION_NAME_PREFIX "joinchannels")
+#define KVI_COREACTION_ACTIONEDITOR (KVI_COREACTION_NAME_PREFIX "actioneditor")
+#define KVI_COREACTION_ALIASEDITOR (KVI_COREACTION_NAME_PREFIX "aliaseditor")
+#define KVI_COREACTION_EVENTEDITOR (KVI_COREACTION_NAME_PREFIX "eventeditor")
+#define KVI_COREACTION_POPUPEDITOR (KVI_COREACTION_NAME_PREFIX "popupeditor")
+#define KVI_COREACTION_RAWEDITOR (KVI_COREACTION_NAME_PREFIX "raweditor")
+#define KVI_COREACTION_CODETESTER (KVI_COREACTION_NAME_PREFIX "codetester")
+#define KVI_COREACTION_EXECUTEKVS (KVI_COREACTION_NAME_PREFIX "executekvs")
+#define KVI_COREACTION_CASCADEWINDOWS (KVI_COREACTION_NAME_PREFIX "cascadewindows")
+#define KVI_COREACTION_TILEWINDOWS (KVI_COREACTION_NAME_PREFIX "tilewindows")
+#define KVI_COREACTION_MINIMIZEALLWINDOWS (KVI_COREACTION_NAME_PREFIX "minimizeallwindows")
+#define KVI_COREACTION_NEWIRCCONTEXT (KVI_COREACTION_NAME_PREFIX "newirccontext")
+#define KVI_COREACTION_QUITKVIRC (KVI_COREACTION_NAME_PREFIX "quitkvirc")
+#define KVI_COREACTION_IRCCONTEXTDISPLAY (KVI_COREACTION_NAME_PREFIX "irccontextdisplay")
+#define KVI_COREACTION_SEPARATOR (KVI_COREACTION_NAME_PREFIX "separator")
+#define KVI_COREACTION_CONNECT (KVI_COREACTION_NAME_PREFIX "connect")
+#define KVI_COREACTION_CHANNELMENU (KVI_COREACTION_NAME_PREFIX "channelmenu")
+#define KVI_COREACTION_NICKNAMEMENU (KVI_COREACTION_NAME_PREFIX "nicknamemenu")
+#define KVI_COREACTION_SERVERMENU (KVI_COREACTION_NAME_PREFIX "servermenu")
+#define KVI_COREACTION_USERMODEMENU (KVI_COREACTION_NAME_PREFIX "usermodemenu")
+#define KVI_COREACTION_AWAYBACK (KVI_COREACTION_NAME_PREFIX "awayback")
+#define KVI_COREACTION_IRCTOOLS (KVI_COREACTION_NAME_PREFIX "irctools")
+#define KVI_COREACTION_IRCACTIONS (KVI_COREACTION_NAME_PREFIX "ircactions")
+#define KVI_COREACTION_HELPINDEX (KVI_COREACTION_NAME_PREFIX "helpindex")
+#define KVI_COREACTION_KVIRCMAILINGLIST (KVI_COREACTION_NAME_PREFIX "kvircmailinglist")
+#define KVI_COREACTION_KVIRCHOMEPAGE (KVI_COREACTION_NAME_PREFIX "kvirchomepage")
+#define KVI_COREACTION_KVIRCRUHOMEPAGE (KVI_COREACTION_NAME_PREFIX "kvircruhomepage")
+#define KVI_COREACTION_EDITREGUSERS (KVI_COREACTION_NAME_PREFIX "editregusers")
+#define KVI_COREACTION_MANAGEADDONS (KVI_COREACTION_NAME_PREFIX "manageaddons")
+#define KVI_COREACTION_THEMEOPTIONS (KVI_COREACTION_NAME_PREFIX "themeoptions")
+#define KVI_COREACTION_MANAGETHEMES (KVI_COREACTION_NAME_PREFIX "managethemes")
+#define KVI_COREACTION_SCREENSHOT (KVI_COREACTION_NAME_PREFIX "screenshot")
+
+#endif //!_KVI_COREACTIONNAMES_H_
diff --git a/src/kvirc/kernel/kvi_coreactions.cpp b/src/kvirc/kernel/kvi_coreactions.cpp
new file mode 100644
index 00000000..071f4ac9
--- /dev/null
+++ b/src/kvirc/kernel/kvi_coreactions.cpp
@@ -0,0 +1,1206 @@
+//=============================================================================
+//
+// File : kvi_coreactions.cpp
+// Created on Mon 22 Nov 2004 02:30:47 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_coreactions.h"
+#include "kvi_frame.h"
+#include "kvi_locale.h"
+#include "kvi_irccontext.h"
+#include "kvi_iconmanager.h"
+#include "kvi_app.h"
+#include "kvi_customtoolbar.h"
+#include "kvi_actiondrawer.h"
+#include "kvi_actionmanager.h"
+#include "kvi_kvs_action.h"
+#include "kvi_mdimanager.h"
+#include "kvi_irctoolbar.h"
+#include "kvi_locale.h"
+#include "kvi_ircurl.h"
+#include "kvi_ircconnection.h"
+#include "kvi_ircconnectionuserinfo.h"
+#include "kvi_coreactionnames.h"
+#include "kvi_ircconnectionserverinfo.h"
+#include "kvi_styled_controls.h"
+
+#include "kvi_kvs_script.h"
+
+#include "kvi_tal_popupmenu.h"
+#include <qobject.h>
+
+
+// Ctrl+Alt+A : KviGoAwayAction
+// Ctrl+Alt+C : Connect/Disconnect
+// Ctrl+Alt+S : Servers dialog
+// Ctrl+Alt+I : Identity dialog
+// Ctrl+Alt+O : General options
+// Ctrl+Alt+T : Theme options
+// Ctrl+Alt+J : Join Channels
+// Ctrl+Alt+X : Execute script
+// Ctrl+Alt+N : New irc context
+// Ctrl+Alt+1 : Action editor
+// Ctrl+Alt+2 : Alias editor
+// Ctrl+Alt+3 : Event editor
+// Ctrl+Alt+4 : Popup editor
+// Ctrl+Alt+5 : Raw event editor
+// Ctrl+Alt+6 : Customize toolbars
+// Ctrl+Alt+H : Show help index
+// Ctrl+Alt+R : Edit regusers
+// Ctrl+Alt+M : Manage Script Addons
+// Ctrl+Alt+L : Manage Themes
+
+void register_core_actions(KviActionManager * m)
+{
+ m->registerAction(new KviConnectAction(m)); // this as parent will destroy it on exit!
+ m->registerAction(new KviSeparatorAction(m));
+ m->registerAction(new KviIrcContextDisplayAction(m));
+ m->registerAction(new KviJoinChannelAction(m));
+ m->registerAction(new KviChangeNickAction(m));
+ m->registerAction(new KviConnectToServerAction(m));
+ m->registerAction(new KviChangeUserModeAction(m));
+ m->registerAction(new KviGoAwayAction(m));
+ m->registerAction(new KviIrcToolsAction(m));
+ m->registerAction(new KviIrcOperationsAction(m));
+
+ KviAction * a;
+
+#define SCRIPT_ACTION(__name,__code,__visible,__description,__category,__icon,__smallicon,__flags,__accel) \
+ a = new KviKvsAction(m, \
+ QString(__name), \
+ QString(__code), \
+ QString(__visible), \
+ QString(__description), \
+ __category, \
+ QString(__icon), \
+ __smallicon, \
+ __flags, \
+ __accel); \
+ m->registerAction(a)
+
+#define SLOT_ACTION(__name,__object,__slot,__visible,__description,__category,__icon,__smallicon,__flags,__accel) \
+ a = new KviAction(m, \
+ QString(__name), \
+ QString(__visible), \
+ QString(__description), \
+ __category, \
+ QString(__icon), \
+ __smallicon, \
+ __flags, \
+ __accel); \
+ QObject::connect(a,SIGNAL(activated()),__object,__slot); \
+ m->registerAction(a)
+
+ SCRIPT_ACTION(
+ KVI_COREACTION_SERVEROPTIONS,
+ "options.edit KviServerOptionsWidget",
+ __tr2qs("Configure Servers..."),
+ __tr2qs("Allows you to configure the servers and eventually to connect to them"),
+ KviActionManager::categorySettings(),
+ "kvi_bigicon_servers.png",
+ KVI_SMALLICON_SERVER,
+ 0,
+ "Ctrl+Alt+S");
+
+ SCRIPT_ACTION(
+ KVI_COREACTION_MANAGEADDONS,
+ "addon.dialog",
+ __tr2qs("Manage Addons..."),
+ __tr2qs("Allows you to manage the script-based addons"),
+ KviActionManager::categorySettings(),
+ "kvi_bigicon_addons.png",
+ KVI_SMALLICON_ADDONS,
+ 0,
+ "Ctrl+Alt+M");
+
+ SCRIPT_ACTION(
+ KVI_COREACTION_EDITREGUSERS,
+ "reguser.edit -t",
+ __tr2qs("Configure Registered Users..."),
+ __tr2qs("Shows a dialog that allows editing the registered user entries"),
+ KviActionManager::categorySettings(),
+ "kvi_bigicon_regusers.png",
+ KVI_SMALLICON_REGUSERS,
+ 0,
+ "Ctrl+Alt+R");
+
+ SCRIPT_ACTION(
+ KVI_COREACTION_IDENTITYOPTIONS,
+ "options.edit KviIdentityOptionsWidget",
+ __tr2qs("Configure Identity..."),
+ __tr2qs("Allows you to configure nickname, username, avatar etc..."),
+ KviActionManager::categorySettings(),
+ "kvi_bigicon_identity.png",
+ KVI_SMALLICON_WHO,
+ 0,
+ "Ctrl+Alt+I");
+
+ SCRIPT_ACTION(
+ KVI_COREACTION_SOCKETSPY,
+ "socketspy.open",
+ __tr2qs("Show SocketSpy..."),
+ __tr2qs("Shows a window that allows monitoring the socket traffic"),
+ KviActionManager::categoryScripting(),
+ "kvi_bigicon_socketspy.png",
+ KVI_SMALLICON_SPY,
+ KviAction::NeedsContext,
+ QString::null);
+
+ SCRIPT_ACTION(
+ KVI_COREACTION_NETWORKLINKS,
+ "links.open",
+ __tr2qs("Get Network Links"),
+ __tr2qs("Shows a window that allows viewing the network links"),
+ KviActionManager::categoryIrc(),
+ "kvi_bigicon_networklinks.png",
+ KVI_SMALLICON_LINKS,
+ KviAction::NeedsContext,
+ QString::null);
+
+ SCRIPT_ACTION(
+ KVI_COREACTION_CHANNELLIST,
+ "list.open",
+ __tr2qs("Get Channel List"),
+ __tr2qs("Shows a window that allows listing the network channels"),
+ KviActionManager::categoryIrc(),
+ "kvi_bigicon_channellist.png",
+ KVI_SMALLICON_LIST,
+ KviAction::NeedsContext,
+ QString::null);
+
+ SCRIPT_ACTION(
+ KVI_COREACTION_GENERALOPTIONS,
+ "options.dialog",
+ __tr2qs("Configure KVIrc..."),
+ __tr2qs("Shows the general options dialog"),
+ KviActionManager::categorySettings(),
+ "kvi_bigicon_settings.png",
+ KVI_SMALLICON_OPTIONS,
+ 0,
+ "Ctrl+Alt+O");
+
+ SCRIPT_ACTION(
+ KVI_COREACTION_THEMEOPTIONS,
+ "options.dialog theme",
+ __tr2qs("Configure Theme..."),
+ __tr2qs("Shows the theme options dialog"),
+ KviActionManager::categorySettings(),
+ "kvi_bigicon_themeoptions.png",
+ KVI_SMALLICON_THEMEOPTIONS,
+ 0,
+ "Ctrl+Alt+T");
+
+ SCRIPT_ACTION(
+ KVI_COREACTION_MANAGETHEMES,
+ "theme.dialog",
+ __tr2qs("Manage Themes..."),
+ __tr2qs("Allows you to manage the themes"),
+ KviActionManager::categorySettings(),
+ "kvi_bigicon_theme.png",
+ KVI_SMALLICON_THEME,
+ 0,
+ "Ctrl+Alt+L");
+
+ SCRIPT_ACTION(
+ KVI_COREACTION_TOOLBAREDITOR,
+ "toolbareditor.open",
+ __tr2qs("Customize Toolbars..."),
+ __tr2qs("Shows a window that allows editing script toolbars"),
+ KviActionManager::categorySettings(),
+ "kvi_bigicon_toolbareditor.png",
+ KVI_SMALLICON_TOOLBAR,
+ 0,
+ "Ctrl+Alt+6");
+
+
+ SCRIPT_ACTION(
+ KVI_COREACTION_JOINCHANNELS,
+ "channelsjoin.open",
+ __tr2qs("Join Channels..."),
+ __tr2qs("Shows a dialog that allows you joing channels"),
+ KviActionManager::categoryIrc(),
+ "kvi_bigicon_channels.png",
+ KVI_SMALLICON_CHANNEL,
+ KviKvsAction::NeedsConnection | KviKvsAction::NeedsContext,
+ "Ctrl+Alt+J");
+
+
+ SCRIPT_ACTION(
+ KVI_COREACTION_ACTIONEDITOR,
+ "actioneditor.open",
+ __tr2qs("Edit Actions..."),
+ __tr2qs("Shows a window that allows editing actions"),
+ KviActionManager::categoryScripting(),
+ "kvi_bigicon_actioneditor.png",
+ KVI_SMALLICON_SCRIPTACTION,
+ 0,
+ "Ctrl+Alt+1");
+
+ SCRIPT_ACTION(
+ KVI_COREACTION_ALIASEDITOR,
+ "aliaseditor.open",
+ __tr2qs("Edit Aliases..."),
+ __tr2qs("Shows a window that allows editing aliases"),
+ KviActionManager::categoryScripting(),
+ "kvi_bigicon_aliaseditor.png",
+ KVI_SMALLICON_ALIAS,
+ 0,
+ "Ctrl+Alt+2");
+
+ SCRIPT_ACTION(
+ KVI_COREACTION_EVENTEDITOR,
+ "eventeditor.open",
+ __tr2qs("Edit Events..."),
+ __tr2qs("Shows a window that allows editing script events"),
+ KviActionManager::categoryScripting(),
+ "kvi_bigicon_eventeditor.png",
+ KVI_SMALLICON_EVENT,
+ 0,
+ "Ctrl+Alt+3");
+
+ SCRIPT_ACTION(
+ KVI_COREACTION_POPUPEDITOR,
+ "popupeditor.open",
+ __tr2qs("Edit Popups..."),
+ __tr2qs("Shows a window that allows editing popup menus"),
+ KviActionManager::categoryScripting(),
+ "kvi_bigicon_popupeditor.png",
+ KVI_SMALLICON_POPUP,
+ 0,
+ "Ctrl+Alt+4");
+
+ SCRIPT_ACTION(
+ KVI_COREACTION_RAWEDITOR,
+ "raweditor.open",
+ __tr2qs("Edit Raw Events..."),
+ __tr2qs("Shows a window that allows editing raw scripting events"),
+ KviActionManager::categoryScripting(),
+ "kvi_bigicon_raweditor.png",
+ KVI_SMALLICON_RAWEVENT,
+ 0,
+ "Ctrl+Alt+5");
+
+ SCRIPT_ACTION(
+ KVI_COREACTION_CODETESTER,
+ "codetester.open",
+ __tr2qs("New Script Tester"),
+ __tr2qs("Creates an embedded editor for long scripts"),
+ KviActionManager::categoryScripting(),
+ "kvi_bigicon_codetester.png",
+ KVI_SMALLICON_BOMB,
+ 0,
+ QString::null);
+
+ SCRIPT_ACTION(
+ KVI_COREACTION_EXECUTEKVS,
+ "dialog.file(open,$tr(\"Select a Script File\")){ if(!$str.isEmpty($0))parse $0; }",
+ __tr2qs("Execute Script..."),
+ __tr2qs("Allows executing a KVS script from file"),
+ KviActionManager::categoryScripting(),
+ "kvi_bigicon_folder.png",
+ KVI_SMALLICON_FOLDER,
+ 0,
+ "Ctrl+Alt+X");
+
+ SCRIPT_ACTION(
+ KVI_COREACTION_HELPINDEX,
+ "help",
+ __tr2qs("Help Index"),
+ __tr2qs("Shows the documentation index"),
+ KviActionManager::categoryGeneric(),
+ "kvi_bigicon_help.png",
+ KVI_SMALLICON_HELP,
+ 0,
+ "Ctrl+Alt+H");
+
+ SCRIPT_ACTION(
+ KVI_COREACTION_KVIRCMAILINGLIST,
+ "openurl http://www.kvirc.net/?id=mailinglist",
+ __tr2qs("Subscribe to the Mailing List"),
+ __tr2qs("Allows subscribing to the KVIrc mailing list"),
+ KviActionManager::categoryGeneric(),
+ "kvi_bigicon_mailinglist.png",
+ KVI_SMALLICON_MESSAGE,
+ 0,
+ QString::null);
+
+ SCRIPT_ACTION(
+ KVI_COREACTION_KVIRCHOMEPAGE,
+ "openurl http://www.kvirc.net",
+ __tr2qs("KVIrc WWW"),
+ __tr2qs("Opens the KVIrc homepage"),
+ KviActionManager::categoryGeneric(),
+ "kvi_bigicon_kvircwww.png",
+ KVI_SMALLICON_KVIRC,
+ 0,
+ QString::null);
+
+ SCRIPT_ACTION(
+ KVI_COREACTION_KVIRCRUHOMEPAGE,
+ "openurl http://www.kvirc.ru",
+ __tr2qs("KVIrc Russian WWW"),
+ __tr2qs("Opens the KVIrc homepage in russian"),
+ KviActionManager::categoryGeneric(),
+ "kvi_bigicon_kvircwww.png",
+ KVI_SMALLICON_KVIRC,
+ 0,
+ QString::null);
+
+ SCRIPT_ACTION(
+ KVI_COREACTION_SCREENSHOT,
+ "theme.screenshot",
+ __tr2qs("Acquire Screenshot"),
+ __tr2qs("Acquires a Screenshot of the KVIrc main window"),
+ KviActionManager::categoryGeneric(),
+ "kvi_bigicon_screenshot.png",
+ KVI_SMALLICON_SCREENSHOT,
+ 0,
+ QString::null);
+
+
+ SLOT_ACTION(
+ KVI_COREACTION_CASCADEWINDOWS,
+ g_pFrame->mdiManager(),
+ SLOT(cascadeMaximized()),
+ __tr2qs("Cascade windows"),
+ __tr2qs("Arranges the MDI windows in a maximized-cascade fashion"),
+ KviActionManager::categoryGUI(),
+ "kvi_bigicon_cascadewindows.png",
+ KVI_SMALLICON_CASCADEWINDOWS,
+ 0,
+ QString::null);
+
+ SLOT_ACTION(
+ KVI_COREACTION_TILEWINDOWS,
+ g_pFrame->mdiManager(),
+ SLOT(tile()),
+ __tr2qs("Tile windows"),
+ __tr2qs("Tiles the MDI windows with the currently selected tile method"),
+ KviActionManager::categoryGUI(),
+ "kvi_bigicon_tilewindows.png",
+ KVI_SMALLICON_TILEWINDOWS,
+ 0,
+ QString::null);
+
+ SLOT_ACTION(
+ KVI_COREACTION_MINIMIZEALLWINDOWS,
+ g_pFrame->mdiManager(),
+ SLOT(minimizeAll()),
+ __tr2qs("Minimize all windows"),
+ __tr2qs("Minimized all the currently visible MDI windows"),
+ KviActionManager::categoryGUI(),
+ "kvi_bigicon_minimizeallwindows.png",
+ KVI_SMALLICON_MINIMIZE,
+ 0,
+ QString::null);
+
+ SLOT_ACTION(
+ KVI_COREACTION_NEWIRCCONTEXT,
+ g_pFrame,
+ SLOT(newConsole()),
+ __tr2qs("New IRC Context"),
+ __tr2qs("Creates a new IRC context console"),
+ KviActionManager::categoryIrc(),
+ "kvi_bigicon_newirccontext.png",
+ KVI_SMALLICON_CONSOLE,
+ 0,
+ "Ctrl+Alt+N");
+
+ SLOT_ACTION(
+ KVI_COREACTION_QUITKVIRC,
+ g_pApp,
+ SLOT(quit()),
+ __tr2qs("Quit KVIrc"),
+ __tr2qs("Quits KVIrc closing all the current connections"),
+ KviActionManager::categoryGeneric(),
+ "kvi_bigicon_quit.png",
+ KVI_SMALLICON_QUITAPP,
+ 0,
+ QString::null);
+}
+
+
+
+
+KviIrcContextDisplayAction::KviIrcContextDisplayAction(QObject * pParent)
+: KviAction(pParent,
+ QString(KVI_COREACTION_IRCCONTEXTDISPLAY),
+ __tr2qs("IRC Context Display"),
+ __tr2qs("Shows a small display with IRC context informations"),
+ KviActionManager::categoryIrc(),
+ "kvi_bigicon_irccontextdisplay.png",
+ KVI_SMALLICON_NONE,
+ NeedsContext | NeedsConnection)
+{
+}
+
+void KviIrcContextDisplayAction::setup()
+{
+ KviAction::setup();
+ connect(g_pFrame,SIGNAL(activeConnectionServerInfoChanged()),this,SLOT(activeContextStateChanged()));
+ connect(g_pFrame,SIGNAL(activeConnectionNickNameChanged()),this,SLOT(activeContextStateChanged()));
+ connect(g_pFrame,SIGNAL(activeConnectionUserModeChanged()),this,SLOT(activeContextStateChanged()));
+ connect(g_pFrame,SIGNAL(activeConnectionAwayStateChanged()),this,SLOT(activeContextStateChanged()));
+ connect(g_pFrame,SIGNAL(activeConnectionLagChanged()),this,SLOT(activeContextStateChanged()));
+}
+
+bool KviIrcContextDisplayAction::addToPopupMenu(KviTalPopupMenu *p)
+{
+ // QT4SUX: Widgets can be no longer added to popup menus.. what about labels ?
+#ifndef COMPILE_USE_QT4
+ if(!setupDone())setup();
+ KviIrcContextDisplay * w = new KviIrcContextDisplay(p,"kvirc.irccontextdisplay");
+ registerWidget(w);
+ p->insertItem(w);
+#endif
+ return true;
+}
+
+QWidget * KviIrcContextDisplayAction::addToCustomToolBar(KviCustomToolBar *t)
+{
+ if(!setupDone())setup();
+ KviIrcContextDisplay * w = new KviIrcContextDisplay(t,"kvirc.irccontextdisplay");
+#ifdef COMPILE_USE_QT4
+ t->addWidget(w);
+#endif
+ registerWidget(w);
+ return w;
+}
+
+void KviIrcContextDisplayAction::activeContextChanged()
+{
+ if(m_pWidgetList)
+ {
+ for(QWidget * w = m_pWidgetList->first();w;w = m_pWidgetList->next())
+ w->update();
+ }
+}
+
+void KviIrcContextDisplayAction::activeContextStateChanged()
+{
+ if(m_pWidgetList)
+ {
+ for(QWidget * w = m_pWidgetList->first();w;w = m_pWidgetList->next())
+ w->update();
+ }
+}
+
+void KviIrcContextDisplayAction::setEnabled(bool)
+{
+ // does nothing here : always enabled!
+}
+
+
+
+
+KviSeparatorAction::KviSeparatorAction(QObject * pParent)
+: KviAction(pParent,
+ QString(KVI_COREACTION_SEPARATOR),
+ __tr2qs("Separator"),
+ __tr2qs("Acts as a separator for other items: performs no action"),
+ KviActionManager::categoryGeneric(),
+ KVI_BIGICON_SEPARATOR,
+ KVI_SMALLICON_NONE,
+ 0)
+{
+}
+
+
+bool KviSeparatorAction::addToPopupMenu(KviTalPopupMenu *p)
+{
+ if(!setupDone())setup();
+ p->insertSeparator();
+ return true;
+}
+
+QWidget * KviSeparatorAction::addToCustomToolBar(KviCustomToolBar *t)
+{
+ if(!setupDone())setup();
+ QWidget * w = new KviCustomToolBarSeparator(t,"kvirc.separator");
+ registerWidget(w);
+#ifdef COMPILE_USE_QT4
+ t->addWidget(w);
+#endif
+ return w;
+}
+
+
+
+
+
+KviConnectAction::KviConnectAction(QObject * pParent)
+: KviAction(pParent,
+ QString(KVI_COREACTION_CONNECT),
+ __tr2qs("Connect/Disconnect"),
+ __tr2qs("Allows you to connect to a server or to terminate the current connection"),
+ KviActionManager::categoryIrc(),
+ KVI_BIGICON_CONNECTED,
+ KVI_SMALLICON_NONE, // no small icon for now
+ NeedsContext | NeedsConnection,
+ QString("Ctrl+Alt+C"))
+{
+}
+
+
+void KviConnectAction::reloadImages()
+{
+ activeContextStateChanged();
+}
+
+void KviConnectAction::activeContextChanged()
+{
+ activeContextStateChanged();
+}
+
+void KviConnectAction::activeContextStateChanged()
+{
+
+ KviPointerList<QWidget> * bl = widgetList();
+ if(!bl)return;
+
+ QPixmap * p;
+ QString txt;
+ KviIrcContext * c = g_pFrame->activeContext();
+ if(c)
+ {
+ switch(c->state())
+ {
+ case KviIrcContext::Idle:
+ p = g_pIconManager->getBigIcon(KVI_BIGICON_DISCONNECTED);
+ txt = m_szConnectString;
+ break;
+ case KviIrcContext::Connecting:
+ case KviIrcContext::LoggingIn:
+ p = g_pIconManager->getBigIcon(KVI_BIGICON_CONNECTING);
+ txt = m_szAbortConnectionString;
+ break;
+ case KviIrcContext::Connected:
+ p = g_pIconManager->getBigIcon(KVI_BIGICON_CONNECTED);
+ txt = m_szDisconnectString;
+ break;
+ default:
+ p = 0;
+ break;
+ }
+ } else {
+ p = 0;
+ }
+
+ if(p)
+ {
+ for(QToolButton * b = (QToolButton *)bl->first();b;b =(QToolButton *)bl->next())
+ {
+ if(!b->isEnabled())b->setEnabled(true);
+ b->setPixmap(*p);
+ b->setTextLabel(txt);
+ }
+ } else {
+ for(QToolButton * b = (QToolButton *)bl->first();b;b = (QToolButton *)bl->next())
+ {
+ if(b->isEnabled())b->setEnabled(false);
+ }
+ }
+}
+
+void KviConnectAction::setup()
+{
+ KviAction::setup();
+ m_szConnectString = __tr2qs("Connect");
+ m_szAbortConnectionString = __tr2qs("Abort Connection");
+ m_szDisconnectString = __tr2qs("Disconnect");
+}
+
+void KviConnectAction::activate()
+{
+ KviIrcContext * c = g_pFrame->activeContext();
+ if(c)c->connectOrDisconnect();
+}
+
+bool KviConnectAction::addToPopupMenu(KviTalPopupMenu *p)
+{
+ if(!setupDone())setup();
+ KviIrcContext * c = g_pFrame->activeContext();
+ int id;
+
+
+ QString t;
+ if(c)
+ {
+ switch(c->state())
+ {
+ case KviIrcContext::Idle:
+ t = m_szConnectString;
+ if(!m_szKeySequence.isEmpty())t += '\t' + m_szKeySequence;
+ p->insertItem(t,this,SLOT(activate()));
+ break;
+ case KviIrcContext::Connecting:
+ case KviIrcContext::LoggingIn:
+ t = m_szAbortConnectionString;
+ if(!m_szKeySequence.isEmpty())t += '\t' + m_szKeySequence;
+ p->insertItem(t,this,SLOT(activate()));
+ break;
+ case KviIrcContext::Connected:
+ t = m_szDisconnectString;
+ if(!m_szKeySequence.isEmpty())t += '\t' + m_szKeySequence;
+ p->insertItem(t,this,SLOT(activate()));
+ break;
+ default:
+ t = m_szConnectString;
+ if(!m_szKeySequence.isEmpty())t += '\t' + m_szKeySequence;
+ id = p->insertItem(t,this,SLOT(activate()));
+ p->setItemEnabled(id,false);
+ break;
+ }
+ } else {
+ t = m_szConnectString;
+ if(!m_szKeySequence.isEmpty())t += '\t' + m_szKeySequence;
+ id = p->insertItem(t,this,SLOT(activate()));
+ p->setItemEnabled(id,false);
+ }
+ return true;
+}
+
+QWidget * KviConnectAction::addToCustomToolBar(KviCustomToolBar *t)
+{
+ if(!setupDone())setup();
+ QToolButton * b = new KviStyledToolButton(
+ *(g_pIconManager->getBigIcon(KVI_BIGICON_DISCONNECTED)),
+ m_szConnectString,
+ m_szConnectString,
+ this,SLOT(activate()),t,name());
+ registerWidget(b);
+#ifdef COMPILE_USE_QT4
+ t->addWidget(b);
+#endif
+ activeContextStateChanged();
+ return b;
+}
+
+
+
+
+
+
+
+KviSubmenuAction::KviSubmenuAction(QObject * pParent,
+ const QString &szName,
+ const QString &szScriptCode,
+ const QString &szVisibleName,
+ const QString &szDescription,
+ KviActionCategory * pCategory,
+ const QString &szBigIcon,
+ int iSmallIconId,
+ unsigned int uFlags)
+ : KviKvsAction(pParent,
+ szName,
+ szScriptCode,
+ szVisibleName,
+ szDescription,
+ pCategory,
+ szBigIcon,
+ iSmallIconId,
+ uFlags)
+{
+ m_pPopup = 0;
+}
+
+KviSubmenuAction::~KviSubmenuAction()
+{
+ if(m_pPopup)delete m_pPopup;
+}
+
+void KviSubmenuAction::setup()
+{
+ KviKvsAction::setup();
+ if(!m_pPopup)
+ {
+ m_pPopup = new KviTalPopupMenu();
+ connect(m_pPopup,SIGNAL(aboutToShow()),this,SLOT(popupAboutToShow()));
+ connect(m_pPopup,SIGNAL(activated(int)),this,SLOT(popupActivated(int)));
+ }
+}
+
+void KviSubmenuAction::popupAboutToShow()
+{
+}
+
+void KviSubmenuAction::popupActivated(int)
+{
+}
+
+bool KviSubmenuAction::addToPopupMenu(KviTalPopupMenu *p)
+{
+ if(!setupDone())setup();
+ int id = p->insertItem(*(smallIcon()),visibleName(),m_pPopup);
+ if(!isEnabled())p->setItemEnabled(id,false);
+ return true;
+}
+
+QWidget * KviSubmenuAction::addToCustomToolBar(KviCustomToolBar *t)
+{
+ if(!setupDone())setup();
+ KviStyledToolButton * b = new KviStyledToolButton(
+ *(bigIcon()),
+ visibleName(),
+ visibleName(),
+ this,SLOT(activate()),t,name());
+ b->setPopup(m_pPopup);
+
+#ifdef COMPILE_USE_QT4
+ b->setPopupMode( scriptCode().isEmpty() ? QToolButton::InstantPopup : QToolButton::MenuButtonPopup);
+ t->addWidget(b);
+#else
+ b->setShowSubmenuIndicator(true);
+ b->setPopupDelay(1);
+#endif
+ registerWidget(b);
+ if(!isEnabled())b->setEnabled(false);
+ return b;
+}
+
+
+
+
+
+
+KviJoinChannelAction::KviJoinChannelAction(QObject * pParent)
+: KviSubmenuAction(pParent,
+ QString(KVI_COREACTION_CHANNELMENU),
+ QString("channelsjoin.open"),
+ __tr2qs("Join Channel"),
+ __tr2qs("Shows a popup menu that allows quickly selecting a channel to join"),
+ KviActionManager::categoryIrc(),
+ "kvi_bigicon_channelspopup.png",
+ KVI_SMALLICON_CHANNEL,
+ NeedsConnection | NeedsContext)
+{
+}
+
+void KviJoinChannelAction::popupAboutToShow()
+{
+ KviConsole * c = g_pActiveWindow->console();
+ if(!c)return;
+
+ g_pApp->fillRecentChannelsPopup(m_pPopup,c);
+
+ m_pPopup->insertSeparator();
+ m_pPopup->insertItem(*(smallIcon()),__tr2qs("Other..."));
+}
+
+void KviJoinChannelAction::popupActivated(int id)
+{
+ KviConsole * c = g_pActiveWindow->console();
+ if(!c)return;
+
+ QString text = m_pPopup->text(id);
+ if(!text.isEmpty())
+ {
+ QString szText;
+ if(__tr2qs("Other...") == text)szText = "channelsjoin.open";
+ else {
+ szText = text;
+ szText.prepend("join ");
+ }
+ KviKvsScript::run(szText,c);
+ }
+}
+
+
+
+KviChangeNickAction::KviChangeNickAction(QObject * pParent)
+: KviSubmenuAction(pParent,
+ QString(KVI_COREACTION_NICKNAMEMENU),
+ QString("dialog.textinput(\"Change Nickname\",\"Please enter the new nickname\",\"Cancel\",\"default=OK\"){ if($0 == 1)nick $1; }"),
+ __tr2qs("Change Nickname"),
+ __tr2qs("Shows a popup menu that allows quickly changing the nickname"),
+ KviActionManager::categoryIrc(),
+ "kvi_bigicon_nickpopup.png",
+ KVI_SMALLICON_NICK,
+ NeedsConnection | NeedsContext)
+{
+}
+
+void KviChangeNickAction::popupAboutToShow()
+{
+ KviConsole * c = g_pActiveWindow->console();
+ if(!c)return;
+
+ g_pApp->fillRecentNicknamesPopup(m_pPopup,c);
+
+ m_pPopup->insertSeparator();
+ m_pPopup->insertItem(*(smallIcon()),__tr2qs("Other..."));
+}
+
+void KviChangeNickAction::popupActivated(int id)
+{
+ KviConsole * c = g_pActiveWindow->console();
+ if(!c)return;
+
+ QString text = m_pPopup->text(id);
+ if(!text.isEmpty())
+ {
+ QString szText;
+ if(__tr2qs("Other...") == text)
+ {
+ activate();
+ } else {
+ szText = text;
+ szText.prepend("nick ");
+ KviKvsScript::run(szText,c);
+ }
+ }
+}
+
+
+
+
+
+
+KviConnectToServerAction::KviConnectToServerAction(QObject * pParent)
+: KviSubmenuAction(pParent,
+ QString(KVI_COREACTION_SERVERMENU),
+ QString("options.edit KviServerOptionsWidget"),
+ __tr2qs("Connect To"),
+ __tr2qs("Shows a popup menu that allows quickly connecting to a server"),
+ KviActionManager::categoryIrc(),
+ "kvi_bigicon_server.png",
+ KVI_SMALLICON_SERVER,
+ NeedsContext)
+{
+}
+
+void KviConnectToServerAction::popupAboutToShow()
+{
+ g_pApp->fillRecentServersPopup(m_pPopup);
+ m_pPopup->insertSeparator();
+ m_pPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_SERVER)),__tr2qs("Other..."));
+}
+
+void KviConnectToServerAction::popupActivated(int id)
+{
+ KviConsole * c = g_pActiveWindow->console();
+ if(!c)return;
+
+ QString text = m_pPopup->text(id);
+ if(!text.isEmpty())
+ {
+ if(__tr2qs("Other...") == text)
+ {
+ activate();
+ } else {
+ KviStr szCommand;
+ KviStr szText = text;
+ if(KviIrcUrl::parse(szText.ptr(),szCommand,KVI_IRCURL_CONTEXT_THIS))
+ {
+ KviKvsScript::run(szCommand.ptr(),c);
+ }
+ }
+ }
+}
+
+
+
+
+
+KviChangeUserModeAction::KviChangeUserModeAction(QObject * pParent)
+: KviSubmenuAction(pParent,
+ QString(KVI_COREACTION_USERMODEMENU),
+ QString(""),
+ __tr2qs("User Mode"),
+ __tr2qs("Shows a popup menu that allows quickly changing user modes"),
+ KviActionManager::categoryIrc(),
+ "kvi_bigicon_usermode.png",
+ KVI_SMALLICON_MODE,
+ NeedsContext | NeedsConnection)
+{
+}
+
+void KviChangeUserModeAction::popupAboutToShow()
+{
+ KviConsole * c = g_pActiveWindow->console();
+ if(!c)return;
+
+ m_pPopup->clear();
+ int id;
+ QString szModes = g_pActiveWindow->console()->connection()->serverInfo()->supportedUserModes();
+
+ id = m_pPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_WALLOPS)),__tr2qs("Wallops (+w)"));
+ m_pPopup->setItemChecked(id,c->connection()->userInfo()->hasUserMode('w'));
+ id = m_pPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_SERVERNOTICE)),__tr2qs("Server Notices (+s)"));
+ m_pPopup->setItemChecked(id,c->connection()->userInfo()->hasUserMode('s'));
+ id = m_pPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_INVISIBLE)),__tr2qs("Invisible (+i)"));
+ m_pPopup->setItemChecked(id,c->connection()->userInfo()->hasUserMode('i'));
+
+ szModes.replace("w","");
+ szModes.replace("s","");
+ szModes.replace("i","");
+ while(!szModes.isEmpty())
+ {
+ QChar ccc = szModes[0];
+ szModes.remove(0,1);
+ id = m_pPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_MODE)),QString("+%1 Mode").arg(ccc));
+ m_pPopup->setItemChecked(id,c->connection()->userInfo()->hasUserMode(ccc.latin1()));
+ }
+}
+
+void KviChangeUserModeAction::popupActivated(int id)
+{
+ KviConsole * c = g_pActiveWindow->console();
+ if(!c)return;
+
+ QString text = m_pPopup->text(id);
+ if(!c->isConnected())return;
+ if(!text.isEmpty())
+ {
+ int idx = text.find('+');
+ if(idx != -1)
+ {
+ idx++;
+ if(idx < text.length())
+ {
+ QChar m = text[idx];
+ QString command = "mode ";
+ command.append(c->connection()->userInfo()->nickName());
+ command.append(c->connection()->userInfo()->hasUserMode(m) ? " -" : " +");
+ command.append(m);
+ KviKvsScript::run(command,c);
+ }
+ }
+ }
+}
+
+
+KviGoAwayAction::KviGoAwayAction(QObject * pParent)
+: KviKvsAction(pParent,
+ QString(KVI_COREACTION_AWAYBACK),
+ QString("if($away())back; else away;"),
+ __tr2qs("Away/Back"),
+ __tr2qs("Allows entering and leaving away state"),
+ KviActionManager::categoryIrc(),
+ "kvi_bigicon_nokeyboard.png",
+ KVI_SMALLICON_NOTAWAY,
+ KviKvsAction::NeedsContext | KviKvsAction::NeedsConnection,
+ "Ctrl+Alt+A")
+{
+}
+
+void KviGoAwayAction::reloadImages()
+{
+ activeContextStateChanged();
+}
+
+void KviGoAwayAction::activeContextChanged()
+{
+ activeContextStateChanged();
+}
+
+void KviGoAwayAction::activeContextStateChanged()
+{
+ KviPointerList<QWidget> * bl = widgetList();
+ if(!bl)return;
+
+ QPixmap * p;
+ QString txt;
+ KviIrcContext * c = g_pFrame->activeContext();
+ if(c)
+ {
+ if(c->state() == KviIrcContext::Connected)
+ {
+ if(c->connection()->userInfo()->isAway())
+ {
+ p = g_pIconManager->getBigIcon("kvi_bigicon_keyboard.png");
+ txt = m_szBackString;
+ } else {
+ p = g_pIconManager->getBigIcon("kvi_bigicon_nokeyboard.png");
+ txt = m_szAwayString;
+ }
+ } else {
+ p = 0;
+ }
+ } else {
+ p = 0;
+ }
+
+ if(p)
+ {
+ for(QToolButton * b = (QToolButton *)bl->first();b;b =(QToolButton *)bl->next())
+ {
+ if(!b->isEnabled())b->setEnabled(true);
+ b->setPixmap(*p);
+ b->setTextLabel(txt);
+ }
+ m_uInternalFlags |= KVI_ACTION_FLAG_ENABLED;
+ setEnabled(true);
+ } else {
+ for(QToolButton * b = (QToolButton *)bl->first();b;b = (QToolButton *)bl->next())
+ {
+ if(b->isEnabled())b->setEnabled(false);
+ }
+ m_uInternalFlags &= ~KVI_ACTION_FLAG_ENABLED;
+ setEnabled(true);
+ }
+}
+
+void KviGoAwayAction::setup()
+{
+ KviKvsAction::setup();
+ m_szAwayString = __tr2qs("Enter Away Mode");
+ m_szBackString = __tr2qs("Leave Away Mode");
+ connect(g_pFrame,SIGNAL(activeConnectionAwayStateChanged()),this,SLOT(activeContextStateChanged()));
+}
+
+bool KviGoAwayAction::addToPopupMenu(KviTalPopupMenu *p)
+{
+ if(!setupDone())setup();
+ KviIrcContext * c = g_pFrame->activeContext();
+ int id;
+ QString t;
+ if(c)
+ {
+ if(c->state() == KviIrcContext::Connected)
+ {
+ if(c->connection()->userInfo()->isAway())
+ {
+ t = m_szBackString;
+ if(!m_szKeySequence.isEmpty())t += '\t' + m_szKeySequence;
+ p->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_AWAY)),t,this,SLOT(activate()));
+ } else {
+ t = m_szAwayString;
+ if(!m_szKeySequence.isEmpty())t += '\t' + m_szKeySequence;
+ p->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_NOTAWAY)),t,this,SLOT(activate()));
+ }
+ } else {
+ t = m_szAwayString;
+ if(!m_szKeySequence.isEmpty())t += '\t' + m_szKeySequence;
+ id = p->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_NOTAWAY)),t,this,SLOT(activate()));
+ p->setItemEnabled(id,false);
+ }
+ } else {
+ t = m_szAwayString;
+ if(!m_szKeySequence.isEmpty())t += '\t' + m_szKeySequence;
+ id = p->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_NOTAWAY)),t,this,SLOT(activate()));
+ p->setItemEnabled(id,false);
+ }
+ return true;
+}
+
+QWidget * KviGoAwayAction::addToCustomToolBar(KviCustomToolBar *t)
+{
+ if(!setupDone())setup();
+ QToolButton * b = new KviStyledToolButton(
+ *(g_pIconManager->getBigIcon("kvi_bigicon_nokeyboard.png")),
+ m_szAwayString,
+ m_szAwayString,
+ this,SLOT(activate()),t,name());
+ registerWidget(b);
+#ifdef COMPILE_USE_QT4
+ t->addWidget(b);
+#endif
+ activeContextStateChanged();
+ return b;
+}
+
+
+
+
+
+
+
+
+
+
+
+KviIrcToolsAction::KviIrcToolsAction(QObject * pParent)
+: KviSubmenuAction(pParent,
+ QString(KVI_COREACTION_IRCTOOLS),
+ QString(""),
+ __tr2qs("Irc Tools"),
+ __tr2qs("Shows a popup menu with some IRC Tools"),
+ KviActionManager::categoryIrc(),
+ "kvi_bigicon_tools.png",
+ KVI_SMALLICON_NONE,
+ NeedsConnection | NeedsContext)
+{
+}
+
+void KviIrcToolsAction::popupAboutToShow()
+{
+ m_pPopup->clear();
+ KviAction * a;
+ a = KviActionManager::instance()->getAction(KVI_COREACTION_SOCKETSPY);
+ if(a)a->addToPopupMenu(m_pPopup);
+ a = KviActionManager::instance()->getAction(KVI_COREACTION_SEPARATOR);
+ if(a)a->addToPopupMenu(m_pPopup);
+ a = KviActionManager::instance()->getAction(KVI_COREACTION_CHANNELLIST);
+ if(a)a->addToPopupMenu(m_pPopup);
+ a = KviActionManager::instance()->getAction(KVI_COREACTION_NETWORKLINKS);
+ if(a)a->addToPopupMenu(m_pPopup);
+}
+
+void KviIrcToolsAction::popupActivated(int id)
+{
+}
+
+
+
+
+
+
+KviIrcOperationsAction::KviIrcOperationsAction(QObject * pParent)
+: KviSubmenuAction(pParent,
+ QString(KVI_COREACTION_IRCACTIONS),
+ QString(""),
+ __tr2qs("Irc Actions"),
+ __tr2qs("Shows a popup menu with some IRC Actions"),
+ KviActionManager::categoryIrc(),
+ "kvi_bigicon_actions.png",
+ KVI_SMALLICON_NONE,
+ NeedsConnection | NeedsContext)
+{
+}
+
+void KviIrcOperationsAction::popupAboutToShow()
+{
+ m_pPopup->clear();
+ KviAction * a;
+ a = KviActionManager::instance()->getAction(KVI_COREACTION_AWAYBACK);
+ if(a)a->addToPopupMenu(m_pPopup);
+ a = KviActionManager::instance()->getAction(KVI_COREACTION_USERMODEMENU);
+ if(a)a->addToPopupMenu(m_pPopup);
+ a = KviActionManager::instance()->getAction(KVI_COREACTION_SEPARATOR);
+ if(a)a->addToPopupMenu(m_pPopup);
+ a = KviActionManager::instance()->getAction(KVI_COREACTION_CHANNELMENU);
+ if(a)a->addToPopupMenu(m_pPopup);
+ a = KviActionManager::instance()->getAction(KVI_COREACTION_NICKNAMEMENU);
+ if(a)a->addToPopupMenu(m_pPopup);
+ a = KviActionManager::instance()->getAction(KVI_COREACTION_SEPARATOR);
+ if(a)a->addToPopupMenu(m_pPopup);
+ a = KviActionManager::instance()->getAction(KVI_COREACTION_SERVERMENU);
+ if(a)a->addToPopupMenu(m_pPopup);
+}
+
+void KviIrcOperationsAction::popupActivated(int id)
+{
+}
+
+
diff --git a/src/kvirc/kernel/kvi_coreactions.h b/src/kvirc/kernel/kvi_coreactions.h
new file mode 100644
index 00000000..4e79fd3a
--- /dev/null
+++ b/src/kvirc/kernel/kvi_coreactions.h
@@ -0,0 +1,188 @@
+#ifndef _KVI_COREACTIONS_H_
+#define _KVI_COREACTIONS_H_
+//=============================================================================
+//
+// File : kvi_coreactions.h
+// Created on Mon 22 Nov 2004 02:30:47 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_action.h"
+#include "kvi_kvs_action.h"
+#include "kvi_pointerlist.h"
+
+#include <qtoolbutton.h>
+
+class KviConnectAction : public KviAction
+{
+ Q_OBJECT
+public:
+ KviConnectAction(QObject * pParent);
+protected:
+ QString m_szConnectString;
+ QString m_szAbortConnectionString;
+ QString m_szDisconnectString;
+public:
+ virtual bool addToPopupMenu(KviTalPopupMenu *p);
+ virtual QWidget * addToCustomToolBar(KviCustomToolBar *t);
+protected:
+ virtual void setup();
+ virtual void reloadImages();
+ virtual void activate();
+ virtual void activeContextChanged();
+ virtual void activeContextStateChanged();
+};
+
+class KviSeparatorAction : public KviAction
+{
+ Q_OBJECT
+public:
+ KviSeparatorAction(QObject * pParent);
+public:
+ virtual bool addToPopupMenu(KviTalPopupMenu *p);
+ virtual QWidget * addToCustomToolBar(KviCustomToolBar *t);
+};
+
+class KviTalPopupMenu;
+
+class KviSubmenuAction : public KviKvsAction
+{
+ Q_OBJECT
+public:
+ KviSubmenuAction(QObject * pParent,
+ const QString &szName,
+ const QString &szScriptCode,
+ const QString &szVisibleName,
+ const QString &szDescription,
+ KviActionCategory * pCategory = 0,
+ const QString &szBigIcon = QString::null,
+ int iSmallIconId = 0,
+ unsigned int uFlags = 0);
+ ~KviSubmenuAction();
+protected:
+ KviTalPopupMenu * m_pPopup;
+protected:
+ virtual void setup();
+public:
+ virtual bool addToPopupMenu(KviTalPopupMenu *p);
+ virtual QWidget * addToCustomToolBar(KviCustomToolBar *t);
+protected slots:
+ virtual void popupAboutToShow();
+ virtual void popupActivated(int id);
+};
+
+class KviJoinChannelAction : public KviSubmenuAction
+{
+ Q_OBJECT
+public:
+ KviJoinChannelAction(QObject * pParent);
+protected slots:
+ virtual void popupAboutToShow();
+ virtual void popupActivated(int);
+};
+
+class KviChangeNickAction : public KviSubmenuAction
+{
+ Q_OBJECT
+public:
+ KviChangeNickAction(QObject * pParent);
+protected slots:
+ void popupAboutToShow();
+ void popupActivated(int);
+};
+
+class KviConnectToServerAction : public KviSubmenuAction
+{
+ Q_OBJECT
+public:
+ KviConnectToServerAction(QObject * pParent);
+protected slots:
+ void popupAboutToShow();
+ void popupActivated(int);
+};
+
+class KviChangeUserModeAction : public KviSubmenuAction
+{
+ Q_OBJECT
+public:
+ KviChangeUserModeAction(QObject * pParent);
+protected slots:
+ void popupAboutToShow();
+ void popupActivated(int);
+};
+
+class KviIrcToolsAction : public KviSubmenuAction
+{
+ Q_OBJECT
+public:
+ KviIrcToolsAction(QObject * pParent);
+protected slots:
+ void popupAboutToShow();
+ void popupActivated(int);
+};
+
+
+class KviIrcOperationsAction : public KviSubmenuAction
+{
+ Q_OBJECT
+public:
+ KviIrcOperationsAction(QObject * pParent);
+protected slots:
+ void popupAboutToShow();
+ void popupActivated(int);
+};
+
+#include "kvi_irctoolbar.h"
+
+class KviIrcContextDisplayAction : public KviAction
+{
+ Q_OBJECT
+public:
+ KviIrcContextDisplayAction(QObject * pParent);
+public:
+ virtual bool addToPopupMenu(KviTalPopupMenu *p);
+ virtual QWidget * addToCustomToolBar(KviCustomToolBar *t);
+ virtual void activeContextStateChanged();
+ virtual void activeContextChanged();
+ virtual void setEnabled(bool);
+ virtual void setup();
+};
+
+
+class KviGoAwayAction : public KviKvsAction
+{
+ Q_OBJECT
+public:
+ KviGoAwayAction(QObject * pParent);
+protected:
+ QString m_szAwayString;
+ QString m_szBackString;
+public:
+ virtual bool addToPopupMenu(KviTalPopupMenu *p);
+ virtual QWidget * addToCustomToolBar(KviCustomToolBar *t);
+protected:
+ virtual void setup();
+ virtual void reloadImages();
+ virtual void activeContextChanged();
+ virtual void activeContextStateChanged();
+};
+
+#endif //!_KVI_COREACTIONS_H_
diff --git a/src/kvirc/kernel/kvi_customtoolbardescriptor.cpp b/src/kvirc/kernel/kvi_customtoolbardescriptor.cpp
new file mode 100644
index 00000000..d8c246b9
--- /dev/null
+++ b/src/kvirc/kernel/kvi_customtoolbardescriptor.cpp
@@ -0,0 +1,278 @@
+//=============================================================================
+//
+// File : kvi_customtoolbardescriptor.cpp
+// Created on Sun 05 Dec 2004 18:20:58 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_customtoolbardescriptor.h"
+#include "kvi_customtoolbar.h"
+#include "kvi_config.h"
+#include "kvi_action.h"
+#include "kvi_actionmanager.h"
+#include "kvi_app.h"
+#include "kvi_locale.h"
+#include "kvi_kvs_script.h"
+#include "kvi_window.h"
+
+KviCustomToolBarDescriptor::KviCustomToolBarDescriptor(const QString &szId,const QString &szLabelCode)
+{
+ m_iInternalId = g_pApp->getGloballyUniqueId();
+ m_szId = szId;
+ m_pActions = new KviPointerList<QString>;
+ m_pActions->setAutoDelete(true);
+ m_pToolBar = 0;
+ m_bVisibleAtStartup = false;
+ createLabelScript(szLabelCode);
+}
+
+KviCustomToolBarDescriptor::~KviCustomToolBarDescriptor()
+{
+ if(m_pToolBar)delete m_pToolBar; // first kill the toolbar (so eventually leave it sync the actions)
+ delete m_pActions; // THEN kill the actions
+ delete m_pLabelScript;
+}
+
+void KviCustomToolBarDescriptor::createLabelScript(const QString &szLabelCode)
+{
+ QString szTmp = "toolbar::";
+ szTmp += m_szId;
+ szTmp += "::label";
+ m_pLabelScript = new KviKvsScript(szTmp,szLabelCode,KviKvsScript::Parameter);
+}
+
+const QString & KviCustomToolBarDescriptor::label()
+{
+ if(!m_pLabelScript->run(g_pActiveWindow,0,m_szParsedLabel))m_szParsedLabel = m_pLabelScript->code();
+ return m_szParsedLabel;
+}
+
+const QString & KviCustomToolBarDescriptor::labelCode()
+{
+ return m_pLabelScript->code();
+}
+
+bool KviCustomToolBarDescriptor::addAction(const QString &szAction)
+{
+ KviAction *a = KviActionManager::instance()->getAction(szAction);
+ if(a)
+ {
+ m_pActions->append(new QString(szAction));
+ if(m_pToolBar)a->addToCustomToolBar(m_pToolBar);
+ return true;
+ }
+ return false;
+}
+
+bool KviCustomToolBarDescriptor::removeAction(unsigned int iAction)
+{
+ if(iAction >= m_pActions->count())return false;
+ if(!m_pActions->remove(iAction))return false;
+ if(m_pToolBar)
+ {
+ // need to refill it :/
+ m_pToolBar->clear();
+ fillToolBar();
+ }
+ return true;
+}
+
+bool KviCustomToolBarDescriptor::removeAction(const QString &szAction)
+{
+ for(QString *s = m_pActions->first();s;s = m_pActions->next())
+ {
+ if(*s == szAction)
+ {
+ m_pActions->removeRef(s);
+ if(m_pToolBar)
+ {
+ // need to refill it :/
+ m_pToolBar->clear();
+ fillToolBar();
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+void KviCustomToolBarDescriptor::updateToolBar()
+{
+ if(!m_pToolBar)return;
+ m_pToolBar->clear();
+ fillToolBar();
+}
+
+
+void KviCustomToolBarDescriptor::fillToolBar()
+{
+ if(m_pActions->count() == 0)
+ {
+ // force layout of the toolbar
+ QApplication::postEvent(m_pToolBar,new QEvent(QEvent::LayoutHint));
+ } else {
+ KviPointerList<QString> dying;
+ dying.setAutoDelete(false);
+ for(QString *p = m_pActions->first();p;p = m_pActions->next())
+ {
+ KviAction *a = KviActionManager::instance()->getAction(*p);
+ if(a)a->addToCustomToolBar(m_pToolBar);
+ else dying.append(p);
+ }
+ for(QString *d = dying.first();d;d = dying.next())
+ m_pActions->removeRef(d);
+ }
+}
+
+KviCustomToolBar * KviCustomToolBarDescriptor::createToolBar()
+{
+ if(!m_pToolBar)
+ {
+ m_pToolBar = new KviCustomToolBar(this,label(),QT_DOCK_TOP,false,id().utf8().data());
+ fillToolBar();
+ }
+ return m_pToolBar;
+}
+
+void KviCustomToolBarDescriptor::registerToolBar(KviCustomToolBar * t)
+{
+ m_pToolBar = t;
+}
+
+void KviCustomToolBarDescriptor::unregisterToolBar(KviCustomToolBar * t)
+{
+ m_pToolBar = 0;
+}
+
+void KviCustomToolBarDescriptor::rename(const QString &szNewLabelCode)
+{
+ delete m_pLabelScript;
+ createLabelScript(szNewLabelCode);
+ if(m_pToolBar)m_pToolBar->setLabel(label());
+}
+
+void KviCustomToolBarDescriptor::clear()
+{
+ m_pActions->clear();
+ if(m_pToolBar)
+ {
+ delete m_pToolBar;
+ m_pToolBar = 0;
+ }
+}
+
+#ifdef SCRIPTTOOLBARDESCRIPTOR_COMPAT
+// THIS IS A COMPATIBILITY ENTRY ADDED AT 3.0.2 TIME THAT SHOULD BE DROPPED IN A COUPLE OF VERSION BUMPS!
+#include "kvi_kvs_useraction.h"
+#include "kvi_string.h"
+
+bool KviCustomToolBarDescriptor::loadScripttoolbarCompat(const char * szPrefix,KviConfig * cfg)
+{
+ m_pActions->clear();
+ KviStr tmp;
+ tmp.sprintf("%s_Name",szPrefix);
+ m_szId = cfg->readQStringEntry(tmp.ptr(),"");
+ tmp.sprintf("%s_Label",szPrefix);
+ QString szLabelCode = cfg->readQStringEntry(tmp.ptr(),"");
+ if(szLabelCode.isEmpty())szLabelCode = "$tr(Unnamed)";
+ delete m_pLabelScript;
+ createLabelScript(szLabelCode);
+
+ tmp.sprintf("%s_Visible",szPrefix);
+ m_bVisibleAtStartup = (cfg->readIntEntry(tmp.ptr(),0) > 0);
+ tmp.sprintf("%s_Count",szPrefix);
+ unsigned int cnt = cfg->readUIntEntry(tmp.ptr(),0);
+ for(unsigned int i=0;i<cnt;i++)
+ {
+ tmp.sprintf("%s_%d",szPrefix,i);
+ KviStr tmp2;
+ tmp2.sprintf("%s_Type",tmp.ptr());
+ tmp2 = cfg->readEntry(tmp2.ptr(),"separator");
+ if(kvi_strEqualCI(tmp2.ptr(),"button"))
+ {
+ tmp2.sprintf("%s_Name",tmp.ptr());
+ QString szName = cfg->readQStringEntry(tmp2.ptr(),"");
+ tmp2.sprintf("%s_Code",tmp.ptr());
+ QString szCode = cfg->readQStringEntry(tmp2.ptr(),"");
+ tmp2.sprintf("%s_Icon",tmp.ptr());
+ QString szIcon = cfg->readQStringEntry(tmp2.ptr(),"");
+ tmp2.sprintf("%s_Text",tmp.ptr());
+ QString szText = cfg->readQStringEntry(tmp2.ptr(),"");
+ //tmp2.sprintf("%s_Enabled",tmp.ptr());
+ //bool bEnabled = cfg->readBoolEntry(tmp2.ptr(),true);
+
+ if(KviAction * old = KviActionManager::instance()->getAction(szName))
+ {
+ if(!old->isKviUserActionNeverOverrideThis())
+ szName = KviActionManager::instance()->nameForAutomaticAction(szName);
+ }
+ KviKvsUserAction * a = new KviKvsUserAction(KviActionManager::instance(),
+ szName,szCode,szText,
+ __tr2qs("Backward compatibility action for toolbar.define"),
+ "generic",szIcon,szIcon,0);
+ KviActionManager::instance()->registerAction(a);
+ m_pActions->append(new QString(szName));
+ } else {
+ m_pActions->append(new QString("separator"));
+ }
+ }
+ return true;
+}
+#endif
+
+bool KviCustomToolBarDescriptor::load(KviConfig * cfg)
+{
+ m_pActions->clear();
+ m_szId = cfg->group();
+ QString szLabelCode = cfg->readQStringEntry("Label");
+ if(szLabelCode.isEmpty())szLabelCode = "$tr(Unnamed)";
+ delete m_pLabelScript;
+ createLabelScript(szLabelCode);
+ m_szIconId = cfg->readQStringEntry("IconId","");
+ unsigned int n = cfg->readUIntEntry("Count",0);
+ QString tmp;
+ for(unsigned int i=0;i<n;i++)
+ {
+ tmp.setNum(i);
+ QString * p = new QString(cfg->readQStringEntry(tmp));
+ if(p->isEmpty())delete p;
+ else m_pActions->append(p);
+ }
+ return true;
+}
+
+void KviCustomToolBarDescriptor::save(KviConfig * cfg)
+{
+ cfg->setGroup(m_szId);
+ cfg->writeEntry("Label",m_pLabelScript->code());
+ cfg->writeEntry("Count",m_pActions->count());
+ if(!m_szIconId.isEmpty())cfg->writeEntry("IconId",m_szIconId);
+ int i = 0;
+ QString tmp;
+ for(QString * p = m_pActions->first();p;p = m_pActions->next())
+ {
+ tmp.setNum(i);
+ cfg->writeEntry(tmp,*p);
+ i++;
+ }
+}
+
diff --git a/src/kvirc/kernel/kvi_customtoolbardescriptor.h b/src/kvirc/kernel/kvi_customtoolbardescriptor.h
new file mode 100644
index 00000000..f900d63a
--- /dev/null
+++ b/src/kvirc/kernel/kvi_customtoolbardescriptor.h
@@ -0,0 +1,86 @@
+#ifndef _KVI_CUSTOMTOOLBARDESCRIPTOR_H_
+#define _KVI_CUSTOMTOOLBARDESCRIPTOR_H_
+//=============================================================================
+//
+// File : kvi_customtoolbardescriptor.h
+// Created on Sun 05 Dec 2004 18:20:58 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_pointerlist.h"
+
+class KviCustomToolBar;
+class KviConfig;
+class KviKvsScript;
+
+
+// THIS IS A COMPATIBILITY ENTRY ADDED AT 3.0.2 TIME THAT SHOULD BE DROPPED IN A COUPLE OF VERSION BUMPS!
+#define SCRIPTTOOLBARDESCRIPTOR_COMPAT 1
+
+class KVIRC_API KviCustomToolBarDescriptor
+{
+ friend class KviCustomToolBar;
+ friend class KviCustomToolBarManager;
+protected:
+ KviCustomToolBarDescriptor(const QString &szId,const QString &szLabelCode);
+public:
+ ~KviCustomToolBarDescriptor();
+protected:
+ QString m_szId;
+ QString m_szIconId;
+ QString m_szParsedLabel;
+ KviPointerList<QString> * m_pActions;
+ KviCustomToolBar * m_pToolBar;
+ int m_iInternalId;
+ bool m_bVisibleAtStartup;
+ KviKvsScript * m_pLabelScript;
+public:
+ const QString & iconId(){ return m_szIconId; };
+ const QString & label();
+ const QString & labelCode();
+ const QString & id(){ return m_szId; };
+ int internalId(){ return m_iInternalId; }; // useful only for KviFrame
+ KviCustomToolBar * toolBar(){ return m_pToolBar; };
+ KviCustomToolBar * createToolBar();
+ void setIconId(const QString &szIconId){ m_szIconId = szIconId; };
+ bool addAction(const QString &szAction);
+ bool removeAction(const QString &szAction);
+ bool removeAction(unsigned int iAction);
+ void clear();
+ void rename(const QString &szNewName);
+ KviPointerList<QString> * actions(){ return m_pActions; };
+ void updateToolBar();
+protected:
+ void createLabelScript(const QString &szNewLabelCode);
+ void fillToolBar();
+ bool load(KviConfig * cfg);
+#ifdef SCRIPTTOOLBARDESCRIPTOR_COMPAT
+// THIS IS A COMPATIBILITY ENTRY ADDED AT 3.0.2 TIME THAT SHOULD BE DROPPED IN A COUPLE OF VERSION BUMPS!
+ bool loadScripttoolbarCompat(const char * prefix,KviConfig * cfg);
+#endif
+ void save(KviConfig * cfg);
+ void registerToolBar(KviCustomToolBar * t);
+ void unregisterToolBar(KviCustomToolBar * t);
+};
+
+
+#endif //!_KVI_CUSTOMTOOLBARDESCRIPTOR_H_
diff --git a/src/kvirc/kernel/kvi_customtoolbarmanager.cpp b/src/kvirc/kernel/kvi_customtoolbarmanager.cpp
new file mode 100644
index 00000000..62ea6cac
--- /dev/null
+++ b/src/kvirc/kernel/kvi_customtoolbarmanager.cpp
@@ -0,0 +1,239 @@
+//=============================================================================
+//
+// File : kvi_customtoolbarmanager.cpp
+// Created on Sun 05 Dec 2004 18:20:18 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_customtoolbarmanager.h"
+#include "kvi_customtoolbardescriptor.h"
+#include "kvi_config.h"
+#include "kvi_locale.h"
+
+KviCustomToolBarManager * KviCustomToolBarManager::m_pInstance = 0;
+
+KviCustomToolBarManager::KviCustomToolBarManager()
+{
+ m_pDescriptors = new KviPointerHashTable<QString,KviCustomToolBarDescriptor>(17,false);
+ m_pDescriptors->setAutoDelete(true);
+}
+
+KviCustomToolBarManager::~KviCustomToolBarManager()
+{
+ delete m_pDescriptors;
+}
+
+KviCustomToolBar * KviCustomToolBarManager::firstExistingToolBar()
+{
+ KviPointerHashTableIterator<QString,KviCustomToolBarDescriptor> it(*m_pDescriptors);
+ while(KviCustomToolBarDescriptor * d = it.current())
+ {
+ if(d->toolBar())return d->toolBar();
+ ++it;
+ }
+ return 0;
+}
+
+void KviCustomToolBarManager::init()
+{
+ if(!m_pInstance)m_pInstance = new KviCustomToolBarManager();
+}
+
+void KviCustomToolBarManager::done()
+{
+ if(m_pInstance)
+ {
+ delete m_pInstance;
+ m_pInstance = 0;
+ }
+}
+
+QString KviCustomToolBarManager::idForNewToolBar(const QString &szTemplate)
+{
+ QString s;
+ QString szTT = szTemplate.lower();
+ szTT.remove(" ");
+ szTT.remove("$tr");
+ szTT.remove("(");
+ szTT.remove(")");
+ szTT.remove("\"");
+ int idx = 0;
+ for(;;)
+ {
+ s = szTT;
+ if(idx > 0)
+ {
+ QString tmp;
+ tmp.setNum(idx);
+ s += tmp;
+ }
+ if(!m_pDescriptors->find(s))return s;
+ idx++;
+ }
+ return s;
+}
+
+KviCustomToolBarDescriptor * KviCustomToolBarManager::findDescriptorByInternalId(int id)
+{
+ KviPointerHashTableIterator<QString,KviCustomToolBarDescriptor> it(*m_pDescriptors);
+ while(KviCustomToolBarDescriptor * d = it.current())
+ {
+ if(d->internalId() == id)return d;
+ ++it;
+ }
+ return 0;
+}
+
+bool KviCustomToolBarManager::renameDescriptor(const QString &szId,const QString &szNewId,const QString &szNewLabelCode)
+{
+ KviCustomToolBarDescriptor * d = m_pDescriptors->find(szId);
+ if(!d)return false;
+ d->rename(szNewLabelCode);
+ if(szId == szNewId)return true; // already done
+ m_pDescriptors->setAutoDelete(false);
+ m_pDescriptors->remove(szId);
+ m_pDescriptors->replace(szNewId,d);
+ m_pDescriptors->setAutoDelete(true);
+ return true;
+}
+
+bool KviCustomToolBarManager::destroyDescriptor(const QString &szId)
+{
+ KviCustomToolBarDescriptor * d = m_pDescriptors->find(szId);
+ if(!d)return false;
+ m_pDescriptors->remove(szId); // will delete it too!
+ return true;
+}
+
+void KviCustomToolBarManager::clear()
+{
+ m_pDescriptors->clear(); // bye!
+}
+
+KviCustomToolBarDescriptor * KviCustomToolBarManager::create(const QString &szId,const QString &szLabelCode)
+{
+ KviCustomToolBarDescriptor * d = m_pDescriptors->find(szId);
+ if(d)return d;
+ d = new KviCustomToolBarDescriptor(szId,szLabelCode);
+ m_pDescriptors->replace(szId,d);
+ return d;
+}
+
+void KviCustomToolBarManager::storeVisibilityState()
+{
+ KviPointerHashTableIterator<QString,KviCustomToolBarDescriptor> it(*m_pDescriptors);
+ while(KviCustomToolBarDescriptor * d = it.current())
+ {
+ d->m_bVisibleAtStartup = d->toolBar() != 0;
+ ++it;
+ }
+
+}
+
+int KviCustomToolBarManager::visibleToolBarCount()
+{
+ int cnt = 0;
+ KviPointerHashTableIterator<QString,KviCustomToolBarDescriptor> it(*m_pDescriptors);
+ while(KviCustomToolBarDescriptor * d = it.current())
+ {
+ if(d->toolBar() != 0)cnt++;
+ ++it;
+ }
+ return cnt;
+}
+
+void KviCustomToolBarManager::createToolBarsVisibleAtStartup()
+{
+ KviPointerHashTableIterator<QString,KviCustomToolBarDescriptor> it(*m_pDescriptors);
+ while(KviCustomToolBarDescriptor * d = it.current())
+ {
+ if(d->m_bVisibleAtStartup && (!d->toolBar()))
+ d->createToolBar();
+ ++it;
+ }
+}
+
+void KviCustomToolBarManager::updateVisibleToolBars()
+{
+ KviPointerHashTableIterator<QString,KviCustomToolBarDescriptor> it(*m_pDescriptors);
+ while(KviCustomToolBarDescriptor * d = it.current())
+ {
+ if(d->toolBar())d->updateToolBar();
+ ++it;
+ }
+}
+
+void KviCustomToolBarManager::load(const QString &szFileName)
+{
+ KviConfig cfg(szFileName,KviConfig::Read);
+
+ KviConfigIterator it(*(cfg.dict()));
+ while(it.current())
+ {
+ cfg.setGroup(it.currentKey());
+ KviCustomToolBarDescriptor * d = new KviCustomToolBarDescriptor(it.currentKey(),QString::null);
+ d->m_bVisibleAtStartup = (cfg.readIntEntry("Visible",0) > 0);
+ if(!d->load(&cfg))delete d;
+ else m_pDescriptors->replace(it.currentKey(),d);
+ ++it;
+ }
+}
+
+void KviCustomToolBarManager::save(const QString &szFileName)
+{
+ KviConfig cfg(szFileName,KviConfig::Write);
+ KviPointerHashTableIterator<QString,KviCustomToolBarDescriptor> it(*m_pDescriptors);
+ while(KviCustomToolBarDescriptor * d = it.current())
+ {
+ cfg.setGroup(d->id());
+ cfg.writeEntry("Visible",d->m_bVisibleAtStartup ? 1 : 0);
+ d->save(&cfg);
+ ++it;
+ }
+}
+
+
+// THIS IS A COMPATIBILITY ENTRY ADDED AT 3.0.2 TIME THAT SHOULD BE DROPPED IN A COUPLE OF VERSION BUMPS!
+#ifdef SCRIPTTOOLBAR_COMPAT
+
+#include <qdir.h>
+void KviCustomToolBarManager::loadScripttoolbarsCompat(const QString &szFileName)
+{
+ KviConfig cfg(szFileName,KviConfig::Read);
+
+ unsigned int cnt = cfg.readUIntEntry("Count",0);
+ KviStr tmp;
+
+ for(unsigned int i=0;i<cnt;i++)
+ {
+ tmp.sprintf("%d",i);
+ KviCustomToolBarDescriptor * d = new KviCustomToolBarDescriptor(QString::null,QString::null);
+ if(!d->loadScripttoolbarCompat(tmp.ptr(),&cfg))delete d;
+ else m_pDescriptors->replace(d->id(),d);
+ }
+
+ // get rid of the file now...
+ QString szNewFileName = szFileName + ".old";
+ QDir d;
+ d.rename(szFileName,szNewFileName);
+}
+#endif
diff --git a/src/kvirc/kernel/kvi_customtoolbarmanager.h b/src/kvirc/kernel/kvi_customtoolbarmanager.h
new file mode 100644
index 00000000..eec1921b
--- /dev/null
+++ b/src/kvirc/kernel/kvi_customtoolbarmanager.h
@@ -0,0 +1,76 @@
+#ifndef _KVI_CUSTOMTOOLBARMANAGER_H_
+#define _KVI_CUSTOMTOOLBARMANAGER_H_
+//=============================================================================
+//
+// File : kvi_customtoolbarmanager.h
+// Created on Sun 05 Dec 2004 18:20:18 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_pointerhashtable.h"
+
+#ifdef COMPILE_ON_WINDOWS
+ #include "kvi_customtoolbardescriptor.h"
+#else
+ class KviCustomToolBarDescriptor;
+#endif
+
+class KviCustomToolBar;
+
+// THIS IS A COMPATIBILITY ENTRY ADDED AT 3.0.2 TIME THAT SHOULD BE DROPPED IN A COUPLE OF VERSION BUMPS!
+#define SCRIPTTOOLBAR_COMPAT 1
+
+class KVIRC_API KviCustomToolBarManager
+{
+protected:
+ KviCustomToolBarManager();
+ ~KviCustomToolBarManager();
+protected:
+ static KviCustomToolBarManager * m_pInstance;
+ KviPointerHashTable<QString,KviCustomToolBarDescriptor> * m_pDescriptors;
+public:
+ static KviCustomToolBarManager * instance(){ return m_pInstance; };
+ static void init();
+ static void done();
+ void clear();
+ int descriptorCount(){ return m_pDescriptors->count(); };
+ int visibleToolBarCount();
+ QString idForNewToolBar(const QString &szTemplate);
+ KviPointerHashTable<QString,KviCustomToolBarDescriptor> * descriptors(){ return m_pDescriptors; };
+ KviCustomToolBar * firstExistingToolBar();
+ KviCustomToolBarDescriptor * create(const QString &szId,const QString &szLabelCode);
+ KviCustomToolBarDescriptor * find(const QString &szId){ return m_pDescriptors->find(szId); };
+ KviCustomToolBarDescriptor * findDescriptorByInternalId(int id);
+ void updateVisibleToolBars();
+ void createToolBarsVisibleAtStartup();
+ void storeVisibilityState();
+ bool renameDescriptor(const QString &szId,const QString &szNewId,const QString &szNewLabelCode);
+ bool destroyDescriptor(const QString &szId);
+ void load(const QString &szFileName);
+ // THIS IS A COMPATIBILITY ENTRY ADDED AT 3.0.2 TIME THAT SHOULD BE DROPPED IN A COUPLE OF VERSION BUMPS!
+#ifdef SCRIPTTOOLBAR_COMPAT
+ void loadScripttoolbarsCompat(const QString &szFileName);
+#endif
+ void save(const QString &szFileName);
+};
+
+
+#endif //!_KVI_CUSTOMTOOLBARMANAGER_H_
diff --git a/src/kvirc/kernel/kvi_filetransfer.cpp b/src/kvirc/kernel/kvi_filetransfer.cpp
new file mode 100644
index 00000000..507c96f2
--- /dev/null
+++ b/src/kvirc/kernel/kvi_filetransfer.cpp
@@ -0,0 +1,190 @@
+//=============================================================================
+//
+// File : kvi_filetransfer.cpp
+// Creation date : Mon Apr 21 22:14:31 2003 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+#define __KVIRC__
+#include "kvi_filetransfer.h"
+#include "kvi_moduleextension.h"
+#include "kvi_window.h"
+
+#include "kvi_app.h"
+
+#include "kvi_tal_listview.h"
+#include "kvi_tal_popupmenu.h"
+
+static KviFileTransferManager * g_pFileTransferManager = 0;
+
+
+KviFileTransferManager::KviFileTransferManager()
+: QObject()
+{
+ m_pTransferList = 0;
+ m_pTransferWindow = 0;
+}
+
+KviFileTransferManager::~KviFileTransferManager()
+{
+ killAllTransfers();
+}
+
+KviFileTransferManager * KviFileTransferManager::instance()
+{
+ if(!g_pFileTransferManager)g_pFileTransferManager = new KviFileTransferManager();
+ return g_pFileTransferManager;
+}
+
+void KviFileTransferManager::cleanup()
+{
+ if(!g_pFileTransferManager)return;
+ delete g_pFileTransferManager;
+ g_pFileTransferManager = 0;
+}
+
+void KviFileTransferManager::killAllTransfers()
+{
+ while(m_pTransferList)
+ {
+ KviFileTransfer * t = m_pTransferList->first();
+ t->die();
+ }
+}
+
+void KviFileTransferManager::killTerminatedTransfers()
+{
+ if(!m_pTransferList)return;
+
+ KviPointerList<KviFileTransfer> l;
+ l.setAutoDelete(false);
+
+ for(KviFileTransfer * f = m_pTransferList->first();f;f = m_pTransferList->next())
+ {
+ if(f->terminated())l.append(f);
+ }
+
+ for(KviFileTransfer * d = l.first();d;d = l.next())
+ d->die();
+}
+
+void KviFileTransferManager::invokeTransferWindow(KviWindow * pWnd,bool bCreateMinimized,bool bNoRaise)
+{
+ if(!m_pTransferWindow)
+ {
+ KviPointerHashTable<QString,QVariant> d(7,false);
+ d.setAutoDelete(true);
+ d.replace("bCreateMinimized",new QVariant(bCreateMinimized,0));
+ d.replace("bNoRaise",new QVariant(bNoRaise,0));
+
+ KviModuleExtensionManager::instance()->allocateExtension(
+ "tool",
+ KVI_FILE_TRANSFER_WINDOW_EXTENSION_NAME,
+ pWnd,&d,0,
+ "filetransferwindow");
+ }
+}
+
+void KviFileTransferManager::registerTransfer(KviFileTransfer * t)
+{
+ if(!m_pTransferList)
+ {
+ m_pTransferList = new KviPointerList<KviFileTransfer>;
+ m_pTransferList->setAutoDelete(false);
+ }
+
+ m_pTransferList->append(t);
+
+ emit transferRegistered(t);
+}
+
+void KviFileTransferManager::unregisterTransfer(KviFileTransfer * t)
+{
+ if(!m_pTransferList)
+ {
+ debug("Ops: unregistering transfer with no transfer list!");
+ return;
+ }
+
+ emit transferUnregistering(t);
+
+ m_pTransferList->removeRef(t);
+ if(m_pTransferList->isEmpty())
+ {
+ delete m_pTransferList;
+ m_pTransferList = 0;
+ }
+}
+
+
+
+KviFileTransfer::KviFileTransfer()
+: QObject()
+{
+ m_pDisplayItem = 0;
+ m_iId = g_pApp->getGloballyUniqueId();
+ manager()->registerTransfer(this);
+}
+
+KviFileTransfer::~KviFileTransfer()
+{
+ manager()->unregisterTransfer(this);
+}
+
+KviWindow * KviFileTransfer::outputWindow()
+{
+ KviWindow * o = transferWindow();
+ if(o)return o;
+ return g_pActiveWindow;
+}
+
+void KviFileTransfer::invokeTransferWindow(KviWindow * pWnd,bool bCreateMinimized,bool bNoRaise)
+{
+ manager()->invokeTransferWindow(pWnd,bCreateMinimized,bNoRaise);
+}
+
+QString KviFileTransfer::localFileName()
+{
+ return QString::null;
+}
+
+QString KviFileTransfer::retryCommand()
+{
+ return QString::null;
+}
+
+bool KviFileTransfer::terminated()
+{
+ return !active();
+}
+
+QString KviFileTransfer::tipText()
+{
+ return QString::null;
+}
+
+int KviFileTransfer::displayHeight(int iLineSpacing)
+{
+ return iLineSpacing * 2;
+}
+
+void KviFileTransfer::displayUpdate()
+{
+ if(m_pDisplayItem)m_pDisplayItem->repaint();
+}
diff --git a/src/kvirc/kernel/kvi_filetransfer.h b/src/kvirc/kernel/kvi_filetransfer.h
new file mode 100644
index 00000000..e6071ff1
--- /dev/null
+++ b/src/kvirc/kernel/kvi_filetransfer.h
@@ -0,0 +1,116 @@
+#ifndef _KVI_FILETRANSFER_H_
+#define _KVI_FILETRANSFER_H_
+
+//=============================================================================
+//
+// File : kvi_filetransfer.h
+// Creation date : Mon Apr 21 22:14:31 2003 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#include <qobject.h>
+
+#include "kvi_pointerlist.h"
+#include "kvi_tal_listview.h"
+
+class KviFileTransfer;
+class KviWindow;
+class KviTalPopupMenu;
+class QPainter;
+
+// This is for the external extension
+#define KVI_FILE_TRANSFER_WINDOW_EXTENSION_NAME "File transfer extension"
+
+
+class KVIRC_API KviFileTransferManager : public QObject
+{
+ friend class KviApp;
+ friend class KviFileTransfer;
+ friend class KviFileTransferWindow;
+ Q_OBJECT
+public:
+ KviFileTransferManager();
+ ~KviFileTransferManager();
+protected:
+ KviPointerList<KviFileTransfer> * m_pTransferList;
+ KviWindow * m_pTransferWindow;
+protected:
+ static void cleanup();
+ void registerTransfer(KviFileTransfer * t);
+ void unregisterTransfer(KviFileTransfer * t);
+ void setTransferWindow(KviWindow * wnd){ m_pTransferWindow = wnd; };
+public:
+ // might be zero!
+ KviWindow * transferWindow(){ return m_pTransferWindow; };
+ static KviFileTransferManager * instance();
+ KviPointerList<KviFileTransfer> * transferList(){ return m_pTransferList; };
+ void invokeTransferWindow(KviWindow * pWnd = 0,bool bCreateMinimized = false,bool bNoRaise = false);
+ void killAllTransfers();
+ void killTerminatedTransfers();
+signals:
+ void transferRegistered(KviFileTransfer *t);
+ void transferUnregistering(KviFileTransfer *t);
+};
+
+#define COLUMN_TRANSFERTYPE 0
+#define COLUMN_FILEINFO 1
+#define COLUMN_PROGRESS 2
+
+
+class KVIRC_API KviFileTransfer : public QObject
+{
+ Q_OBJECT
+public:
+ KviFileTransfer();
+ ~KviFileTransfer();
+protected:
+ int m_iId;
+ KviTalListViewItem * m_pDisplayItem;
+public:
+ // This is called by KviFileTransferItem at any time
+ void setDisplayItem(KviTalListViewItem * i){ m_pDisplayItem = i; };
+ int id(){ return m_iId; };
+ // this is just a convenience function : it's equivalent to !active()
+ bool terminated();
+ // This may be used to invoke the transfer window
+ void invokeTransferWindow(KviWindow * pWnd = 0,bool bCreateMinimized = false,bool bNoRaise = false);
+ KviFileTransferManager * manager(){ return KviFileTransferManager::instance(); };
+ // this returns the pointer to the transfer window : may be 0!
+ KviWindow * transferWindow(){ return manager()->transferWindow(); };
+ // this returns transferWindow() if not 0 , otherwise the application's active window
+ KviWindow * outputWindow();
+
+ // this may be called by the transfers to update the display when the state changes
+ void displayUpdate();
+
+ // this must be implemented by the transfer
+ virtual bool active() = 0;
+ virtual void displayPaint(QPainter * p,int column,int width,int height) = 0;
+ virtual QString tipText();
+ virtual QString localFileName();
+ virtual QString retryCommand();
+ virtual int displayHeight(int iLineSpacing);
+ virtual void fillContextPopup(KviTalPopupMenu * m,int column) = 0;
+ virtual void die() = 0;
+};
+
+#endif //! _KVI_FILETRANSFER_H_
diff --git a/src/kvirc/kernel/kvi_iconmanager.cpp b/src/kvirc/kernel/kvi_iconmanager.cpp
new file mode 100644
index 00000000..1876b115
--- /dev/null
+++ b/src/kvirc/kernel/kvi_iconmanager.cpp
@@ -0,0 +1,924 @@
+//================================================================================
+//
+// File : kvi_iconmanager.cpp
+// Creation date : Sat Jun 24 2000 14:50:11 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//================================================================================
+
+#define __KVIRC__
+
+#define _KVI_ICONMANAGER_CPP_
+
+#include "kvi_iconmanager.h"
+
+#include "kvi_imagelib.h"
+#include "kvi_app.h"
+#include "kvi_settings.h"
+#include "kvi_defaults.h"
+#include "kvi_locale.h"
+#include "kvi_fileutils.h"
+#include "kvi_options.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+
+#ifndef COMPILE_USE_QT4
+ // In Qt.4 we need to use QMimeData ?
+ #include <qdragobject.h>
+#endif
+#include <qcursor.h>
+
+#ifdef COMPILE_USE_QT4
+ #include <qevent.h>
+#endif
+
+// kvi_app.cpp
+extern QPixmap * g_pUserChanStatePixmap;
+extern QPixmap * g_pActivityMeterPixmap;
+
+KviIconManager * g_pIconManager = 0;
+
+static const char * g_szIconNames[KVI_NUM_SMALL_ICONS]=
+{
+ "none", // 0
+ "close", // 1
+ "maximize", // 2
+ "minimize", // 3
+ "restore", // 4
+ "default", // 5
+ "dock", // 6
+ "undock", // 7
+ "quitapp", // 8
+ "console", // 9
+ "floppy", // 10
+ "parsererror", // 11
+ "parserwarning", // 12
+ "server", // 13
+ "world", // 14
+ "proxy", // 15
+ "kvirc", // 16
+ "cut", // 17
+ "copy", // 18
+ "paste", // 19
+ "options", // 20
+ "socketmessage", // 21
+ "socketwarning", // 22
+ "socketerror", // 23
+ "systemerror", // 24
+ "raw", // 25
+ "systemwarning", // 26
+ "systemmessage", // 27
+ "unhandled", // 28
+ "serverinfo", // 29
+ "motd", // 30
+ "channel", // 31
+ "hidedoubleview", // 32
+ "showdoubleview", // 33
+ "op", // 34
+ "voice", // 35
+ "serverping", // 36
+ "showlistview", // 37
+ "hidelistview", // 38
+ "join", // 39
+ "part", // 40
+ "unrecognized", // 41
+ "topic", // 42
+ "accept", // 43
+ "discard", // 44
+ "ownprivmsg", // 45
+ "chanprivmsg", // 46
+ "query", // 48
+ "queryprivmsg", // 49
+ "help", // 49
+ "mdihelp", // 50
+ "ctcpreply", // 51
+ "ctcprequestreplied", // 52
+ "ctcprequestignored", // 53
+ "ctcprequestflood", // 54
+ "ctcprequestunknown", // 55
+ "action", // 56
+ "avatar", // 57
+ "quit", // 58
+ "split", // 59
+ "quitsplit", // 60
+ "nick", // 61
+ "deop", // 62
+ "devoice", // 63
+ "mode", // 64
+ "key", // 65
+ "limit", // 66
+ "ban", // 67
+ "unban", // 68
+ "banexcept", // 69
+ "banunexcept", // 70
+ "inviteexcept", // 71
+ "inviteunexcept", // 72
+ "chanmode", // 73
+ "chanmodehide", // 74
+ "who", // 75
+ "editor", // 76
+ "dccrequest", // 77
+ "dccmsg", // 78
+ "dccerror", // 79
+ "iconmanager", // 80
+ "scriptcenter", // 81
+ "bomb", // 82
+ "event", // 83
+ "eventnohandlers", // 84
+ "handler", // 85
+ "handlerdisabled", // 86
+ "nicknameproblem", // 87
+ "whoisuser", // 88
+ "whoischannels", // 89
+ "whoisidle", // 90
+ "whoisserver", // 91
+ "whoisother", // 92
+ "time", // 93
+ "notifyonline", // 94
+ "notifyoffline", // 95
+ "locked", // 96
+ "unlocked", // 97
+ "lockedoff", // 98
+ "unlockedoff", // 99
+ "ownprivmsgcrypted", // 100
+ "chanprivmsgcrypted", // 101
+ "queryprivmsgcrypted", // 102
+ "dccchatmsg", // 103
+ "dccchatmsgcrypted", // 104
+ "irc", // 105
+ "folder", // 106
+ "home", // 107
+ "bookmarks", // 108
+ "spy", // 109
+ "kick", // 110
+ "linux", // 111
+ "links", // 112
+ "regusers", // 113
+ "dockwidget", // 114
+ "cascadewindows", // 115
+ "maxvertical", // 116
+ "maxhorizontal", // 117
+ "tilewindows", // 118
+ "log", // 119
+ "spam", // 120
+ "file", // 121
+ "icq", // 122
+ "icqyellow", // 123
+ "icqred", // 124
+ "icqblue", // 125
+ "icqlightgreen", // 126
+ "icqlightyellow", // 127
+ "message", // 128
+ "messagesent", // 129
+ "bluesquare", // 130
+ "violetsquare", // 131
+ "yellowsquare", // 132
+ "greensquare", // 133
+ "blacksquare", // 134
+ "redsquare", // 135
+ "cyansquare", // 136
+ "dkgreensquare", // 137
+ "terminal", // 138
+ "wallops", // 139
+ "invisible", // 140
+ "servernotice", // 141
+ "gnutella", // 142
+ "search", // 143
+ "files", // 144
+ "transfer", // 145
+ "package", // 146
+ "retry", // 147
+ "idea", // 148
+ "colors", // 149
+ "gui", // 150
+ "ircview", // 151
+ "alias", // 152
+ "channelnotice",// 153
+ "channelnoticecrypted", // 154
+ "querynotice", // 155
+ "querynoticecrypted", // 156
+ "servnotice", // 157
+ "popup", // 158
+ "prologue", // 159
+ "epilogue", // 160
+ "sharedfiles", // 161
+ "ctcpreplyunknown", // 162
+ "canvas", // 163
+ "nickserv", // 164
+ "chanserv", // 165
+ "dccvoice", // 166
+ "play", // 167
+ "record", // 168
+ "autotilewindows", // 169
+ "away", // 170
+ "ident", // 171
+ "homepage", // 172
+ "list", // 173
+ "halfop", // 174
+ "halfdeop", // 175
+ "invite", // 176
+ "multimedia", // 177
+ "look", // 178
+ "input", // 179
+ "messages", // 180
+ "querytrace", // 181
+ "nochannel", // 182
+ "broadcastprivmsg", // 183
+ "broadcastnotice", // 184
+ "url", // 185
+ "rawevent", // 186
+ "raweventnohandlers", // 187
+ "mekick", // 188
+ "meop", // 189
+ "mevoice", // 190
+ "medeop", // 191
+ "medevoice", // 192
+ "mehalfop", // 193
+ "medehalfop", // 194
+ "meban", // 195
+ "meunban", // 196
+ "mebanexcept", // 197
+ "mebanunexcept", // 198
+ "meinviteexcept", // 199
+ "meinviteunexcept", // 200
+ "classictaskbar", // 201
+ "treetaskbar", // 202
+ "ignore", // 203
+ "userlist",// 204
+ "stats", // 205
+ "popupmenu", // 206
+ "xy", // 207
+ "irc0", // 208
+ "irc1", // 209
+ "irc2", // 210
+ "irc3", // 211
+ "irc4", // 212
+ "irc5", // 213
+ "heart", // 214
+ "heartbroken", // 215
+ "rose", // 215
+ "biggrin", // 217
+ "biggringlasses", // 218
+ "biggrineyes", // 219
+ "textexclamative", // 220
+ "textpoints", // 221
+ "kiss", // 222
+ "surprised1", // 223
+ "ugly", // 224
+ "angry", // 225
+ "surprised2", // 226
+ "smile", // 227
+ "tongue", // 228
+ "ssl", // 229
+ "cry", // 230
+ "eye", // 231
+ "deadchannel", // 232
+ "deadquery", // 233
+ "sound", // 234
+ "toolbar", // 235
+ "textencoding",// 236
+ "newitem", // 237
+ "newitembywizard", // 238
+ "deleteitem", // 239
+ "edititem", // 240
+ "filetransfer", // 241
+ "chanadmin", // 242
+ "chanunadmin", // 243
+ "mechanadmin", // 244
+ "mechanunadmin", // 245
+ "userop", // 246
+ "deuserop", // 247
+ "meuserop", // 248
+ "medeuserop", // 249
+ "applet", // 250
+ "caption", // 251
+ "transparent", // 252
+ "alert", // 253
+ "userwindow", // 254
+ "statusbar", // 255
+ "notaway", // 256
+ "plus", // 257
+ "minus", // 258
+ "binarytext", // 259
+ "chanowner", // 260
+ "chanunowner", // 261
+ "mechanowner", // 262
+ "mechanunowner", // 263
+ "afraid", // 264
+ "tongue2", // 265
+ "sayicon", // 266
+ "saycolors", // 267
+ "finger", // 268
+ "scriptaction", // 269
+ "tearsmile", // 270
+ "shy", // 271
+ "servererror", // 272
+ "cafe", // 273
+ "addons", // 274
+ "chanowneraway", // 275
+ "opaway", // 276
+ "voiceaway", // 277
+ "chanadminaway", // 278
+ "useropaway", // 279
+ "halfopaway", // 280
+ "aliashighlighted", // 281
+ "demoralized", // 282
+ "slurp", // 283
+ "namespace", // 284
+ "saysmile", // 285
+ "saykvs", // 286
+ "themeoptions", // 287
+ "bug", // 288
+ "refresh", //289
+ "theme", // 290
+ "screenshot" // 291
+};
+
+KviIconWidget::KviIconWidget()
+#ifdef COMPILE_USE_QT4
+: QWidget(0,"global_icon_widget" /*,WType_TopLevel | WStyle_Customize | WStyle_Title | WStyle_StaysOnTop | WStyle_DialogBorder | WStyle_SysMenu | WStyle_Minimize*/)
+#else
+: QWidget(0,"global_icon_widget",WType_TopLevel | WStyle_Customize | WStyle_Title | WStyle_StaysOnTop | WStyle_DialogBorder | WStyle_SysMenu | WStyle_Minimize)
+#endif
+{
+ init();
+}
+
+KviIconWidget::KviIconWidget(QWidget * par)
+: QWidget(par,"global_icon_widget")
+{
+ init();
+}
+
+void KviIconWidget::init()
+{
+ setCaption(__tr2qs("Icon Table"));
+ setIcon(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_ICONMANAGER)));
+
+ int rows = KVI_NUM_SMALL_ICONS / 10;
+ if((rows * 10) < KVI_NUM_SMALL_ICONS)rows++;
+ QGridLayout * g = new QGridLayout(this,rows + 1,11,0,2);
+ int i;
+ for(i = 0;i < 10;i++)
+ {
+ KviStr tmp(KviStr::Format,"%d",i);
+ QLabel * l = new QLabel(tmp.ptr(),this);
+ g->addWidget(l,0,i + 1);
+ }
+ for(i = 0;i < rows;i++)
+ {
+ KviStr tmp(KviStr::Format,"%d",i * 10);
+ QLabel * l = new QLabel(tmp.ptr(),this);
+ g->addWidget(l,i + 1,0);
+ }
+ for(i = 0;i < KVI_NUM_SMALL_ICONS;i++)
+ {
+ KviStr tmp(KviStr::Format,"%d",i);
+ QLabel * l = new QLabel(this,tmp.ptr());
+ l->setPixmap(*(g_pIconManager->getSmallIcon(i)));
+ g->addWidget(l,(i / 10) + 1,(i % 10) + 1);
+ l->installEventFilter(this);
+ l->setAcceptDrops(true);
+ }
+}
+
+KviIconWidget::~KviIconWidget()
+{
+}
+
+void KviIconWidget::closeEvent(QCloseEvent * e)
+{
+ e->ignore();
+ emit closed();
+}
+
+bool KviIconWidget::eventFilter(QObject * o,QEvent *e)
+{
+ if(e->type() == QEvent::MouseButtonPress)
+ {
+ if(o->inherits("QLabel"))
+ {
+ KviStr szName = ((QLabel *)o)->name();
+ bool bOk;
+ int iVal = szName.toInt(&bOk);
+ if(bOk)emit selected(iVal);
+
+ if(parentWidget() && isVisible() && parentWidget()->inherits("KviTalPopupMenu"))
+ {
+ parentWidget()->close();
+ return true;
+ } else {
+ if(const QPixmap * pix = ((QLabel *)o)->pixmap())
+ {
+// FIXME: In Qt 4.x this stuff needs to be ported to a different api.. which one ?
+#ifndef COMPILE_USE_QT4
+ QDragObject * drobj = new QTextDrag(o->name(),this);
+ drobj->setPixmap(*pix,((QLabel *)o)->mapFromGlobal(QCursor::pos()));
+ drobj->dragCopy();
+#endif
+ return true;
+ }
+ }
+ }
+ } else if(e->type() == QEvent::DragEnter)
+ {
+ ((QDragEnterEvent *)e)->accept(true);
+ return true;
+ }
+ return QWidget::eventFilter(o,e);
+}
+
+
+
+KviCachedPixmap::KviCachedPixmap(QPixmap * ptr,const QString &szPath)
+{
+ m_szPath = szPath;
+ m_tLastAccess = kvi_unixTime();
+ m_pPixmap = ptr;
+ m_uSize = m_pPixmap->width() * m_pPixmap->height() * (m_pPixmap->depth() / 8);
+}
+
+KviCachedPixmap::~KviCachedPixmap()
+{
+ delete m_pPixmap;
+}
+
+void KviCachedPixmap::updateLastAccessTime()
+{
+ m_tLastAccess = kvi_unixTime();
+}
+
+
+
+
+KviIconManager::KviIconManager()
+{
+ int i=0;
+ for(i=0;i<KVI_NUM_SMALL_ICONS;i++)m_smallIcons[i] = 0;
+
+ //loadSmallIcons();
+
+ m_pCachedImages = new KviPointerHashTable<QString,KviCachedPixmap>(21,true);
+ m_pCachedImages->setAutoDelete(true);
+
+ m_uCacheTotalSize = 0;
+ m_uCacheMaxSize = 1024 * 1024; // 1 MB
+
+ m_pIconWidget = 0;
+
+ KviStr buffer;
+
+ // Load the userchanstate image
+ g_pApp->findImage(buffer,KVI_USERCHANSTATE_IMAGE_NAME);
+ g_pUserChanStatePixmap = new QPixmap(buffer.ptr());
+
+ g_pApp->findImage(buffer,KVI_ACTIVITYMETER_IMAGE_NAME);
+ g_pActivityMeterPixmap = new QPixmap(buffer.ptr());
+
+ m_pIconNames = 0;
+
+ // TEMP
+
+ /*
+ for(i=0;i<KVI_NUM_SMALL_ICONS;i++)
+ {
+ QPixmap * tmp = getSmallIcon(i);
+ QString nnn = "/home/pragma/kvismallicons/kcs_";
+ nnn += g_szIconNames[i];
+ nnn += ".png";
+ if(tmp->isNull())
+ {
+ debug("OPS, %s is NULL",nnn.latin1());
+ }
+ if(!tmp->save(nnn,"PNG",90))
+ {
+ debug("FAILED TO SAVE %s",nnn.latin1());
+ }
+ }
+ */
+}
+
+KviIconManager::~KviIconManager()
+{
+ delete g_pUserChanStatePixmap;
+ delete g_pActivityMeterPixmap;
+
+ if(m_pIconWidget)delete m_pIconWidget;
+ int i;
+
+ for(i=0;i<KVI_NUM_SMALL_ICONS;i++)
+ {
+ if(m_smallIcons[i])delete m_smallIcons[i];
+ }
+ delete m_pCachedImages;
+ if(m_pIconNames)delete m_pIconNames;
+}
+
+const char * KviIconManager::getSmallIconName(int idx)
+{
+ return g_szIconNames[idx];
+}
+
+int KviIconManager::getSmallIconIdFromName(const QString &szName)
+{
+ if(!m_pIconNames)
+ {
+ m_pIconNames = new KviPointerHashTable<QString,int>(257,false);
+ m_pIconNames->setAutoDelete(true);
+
+ for(int i=0;i<KVI_NUM_SMALL_ICONS;i++)
+ {
+ int * pInt = new int;
+ *pInt = i;
+ m_pIconNames->replace(QString(g_szIconNames[i]),pInt);
+ }
+ }
+ int * pInt = m_pIconNames->find(szName);
+ if(!pInt)return 0;
+ return *pInt;
+}
+
+
+void KviIconManager::showIconWidget()
+{
+ if(!m_pIconWidget)
+ {
+ m_pIconWidget = new KviIconWidget();
+ connect(m_pIconWidget,SIGNAL(closed()),this,SLOT(iconWidgetClosed()));
+ }
+ m_pIconWidget->show();
+ m_pIconWidget->raise();
+ m_pIconWidget->setFocus();
+}
+
+void KviIconManager::iconWidgetClosed()
+{
+ delete m_pIconWidget;
+ m_pIconWidget = 0;
+}
+
+/*
+ @doc: image_id
+ @title:
+ The image identifier
+ @keyterms:
+ image identifier, using builtin images, how kvirc locates image files
+ @type:
+ language
+ @short:
+ Semantics of the <image_id> parameter
+ @body:
+ Some KVIrc commands and functions accept
+ the <image_id> as a parameter.
+ The <image_id> indicates an image to be displayed
+ by some gui element. Since KVIrc has a set of
+ builtin icons, we want the user to be able to use it :).[br]
+ The <image_id> can be either a signed integer number
+ or a filename.[br]
+ If it is a signed integer it is interpreted as
+ index of the internal KVIrc image to use:
+ positive integers (starting at 0) indicate
+ small (16x16) icons (the ones used in the view widget).[br]
+ If <image_id> is anything else than a signed integer,
+ it is interpreted as a filename.
+ The filename can be an absolute file path or a relative one.
+ In this last case KVIrc will look for the file in a predefined set
+ of directories: First in the local "pics" directory (usually
+ in ~/kvirc-version/pics/), then in the local "incoming" directory,
+ then in the global "pics" directory , then in the user home (~)
+ and in the current directory.[br]
+*/
+
+KviCachedPixmap * KviIconManager::getPixmapWithCache(const QString &szName)
+{
+ if(szName.isEmpty())return 0;
+
+ KviCachedPixmap * p = m_pCachedImages->find(szName);
+
+ if(p)
+ {
+ p->updateLastAccessTime();
+ return p;
+ }
+
+ QPixmap * pix = 0;
+
+ QString szRetPath;
+
+ if(g_pApp->findImage(szRetPath,szName))
+ {
+ pix = new QPixmap(szRetPath);
+ if(pix->isNull())
+ {
+ delete pix; // it is not an valid image!!! (really bad situation...)
+ pix = 0;
+ return 0;
+ }
+ } else {
+ return 0;
+ }
+
+ p = new KviCachedPixmap(pix,QString(szRetPath));
+ addToCache(szName,p);
+
+ return p;
+}
+
+KviCachedPixmap * KviIconManager::getPixmapWithCacheScaleOnLoad(const QString &szName,int iMaxWidth,int iMaxHeight)
+{
+ if(szName.isEmpty())return 0;
+
+ KviCachedPixmap * p = m_pCachedImages->find(szName);
+
+ if(p)
+ {
+ p->updateLastAccessTime();
+ return p;
+ }
+
+ QPixmap * pix = 0;
+
+ QString szRetPath;
+
+ if(g_pApp->findImage(szRetPath,szName))
+ {
+ pix = new QPixmap(szRetPath);
+ if(pix->isNull())
+ {
+ delete pix; // it is not an valid image!!! (really bad situation...)
+ pix = 0;
+ return 0;
+ }
+ if((pix->width() > iMaxWidth) || (pix->height() > iMaxHeight))
+ {
+ // scale to fit
+ int scaleW = iMaxWidth;
+ int scaleH;
+ scaleH = (pix->height() * iMaxWidth) / pix->width();
+ if(scaleH > iMaxHeight)
+ {
+ scaleH = iMaxHeight;
+ scaleW = (scaleH * pix->width()) / pix->height();
+ }
+
+ QImage img = pix->convertToImage();
+ pix->convertFromImage(img.smoothScale(scaleW,scaleH));
+ }
+ } else {
+ return 0;
+ }
+
+ p = new KviCachedPixmap(pix,QString(szRetPath));
+ addToCache(szName,p);
+
+ return p;
+}
+
+
+void KviIconManager::addToCache(const QString &szName,KviCachedPixmap * p)
+{
+ if((m_uCacheTotalSize + p->size()) >= m_uCacheMaxSize)cacheCleanup();
+
+ m_pCachedImages->insert(szName,p);
+ m_uCacheTotalSize += p->size();
+}
+
+QPixmap * KviIconManager::getImage(const char * id,bool bCanBeNumber,QString* pRetPath)
+{
+ if(!id)return 0;
+ if(bCanBeNumber)
+ {
+ bool bOk;
+ QString tmp = id;
+ int idx = tmp.toInt(&bOk);
+ if(bOk)
+ {
+ // was a number : this is not a filename
+ if(idx >= 0)return getSmallIcon(idx % KVI_NUM_SMALL_ICONS);
+ }
+ }
+
+ KviCachedPixmap * p = getPixmapWithCache(id);
+ if(!p)return 0;
+ if(pRetPath)*pRetPath = p->path();
+ return p->pixmap();
+}
+
+
+
+QPixmap * KviIconManager::getBigIcon(const QString &szName)
+{
+ QPixmap * p = getPixmap(szName);
+ if(p)return p;
+
+ bool bOk;
+ int idx = szName.toInt(&bOk);
+ if(bOk && (idx >= 0))
+ {
+ // was a number : this is not a filename
+ // it was a small icon: scale it and cache it
+ QString tmpName = szName;
+ tmpName += ".scaled16to32";
+ p = getPixmap(tmpName);
+ if(p)return p;
+ p = getSmallIcon(idx % KVI_NUM_SMALL_ICONS);
+ if(p)
+ {
+ QImage tmpi = p->convertToImage();
+ QImage tmp2 = tmpi.smoothScale(32,32);
+ KviCachedPixmap * cp = new KviCachedPixmap(new QPixmap(tmp2),QString::null);
+ addToCache(tmpName,cp);
+ return cp->pixmap();
+ }
+ }
+
+ p = getPixmap("kvi_bigicon_unknown.png");
+ if(p)return p;
+ KviCachedPixmap * cp = new KviCachedPixmap(new QPixmap(32,32),QString::null);
+ addToCache(szName,cp);
+ return cp->pixmap();
+}
+
+void KviIconManager::urlToCachedFileName(KviStr &szFName)
+{
+ szFName.replaceAll(':',"_");
+ szFName.replaceAll(';',"_");
+ szFName.replaceAll('/',"_");
+ szFName.replaceAll('\\',"_");
+ szFName.replaceAll("\"","_");
+ szFName.replaceAll("\'","_");
+ szFName.replaceAll("(","_");
+ szFName.replaceAll(")","_");
+ szFName.replaceAll("?","_");
+ szFName.replaceAll("___",".");
+}
+
+void KviIconManager::urlToCachedFileName(QString &szFName)
+{
+ szFName.replace(":","_");
+ szFName.replace(";","_");
+ szFName.replace("/","_");
+ szFName.replace("\\","_");
+ szFName.replace("\"","_");
+ szFName.replace("\'","_");
+ szFName.replace("(","_");
+ szFName.replace(")","_");
+ szFName.replace("?","_");
+ szFName.replace("___",".");
+}
+
+KviAvatar * KviIconManager::getAvatar(const QString &szLocalPath,const QString &szName)
+{
+ QString szP,szN;
+
+ if(szLocalPath.isEmpty())
+ {
+ if(szName.isEmpty())return 0;
+ if(KviQString::equalCIN("http://",szName,7))
+ {
+ szN = szName;
+ szP = szName;
+ urlToCachedFileName(szP);
+ } else {
+ szN = KviFileUtils::extractFileName(szName);
+ szP = szName;
+ }
+ } else if(szName.isEmpty())
+ {
+ if(szLocalPath.isEmpty())return 0;
+ szP = szLocalPath;
+ szN = KviFileUtils::extractFileName(szLocalPath);
+ } else {
+ szP = szLocalPath;
+ szN = szName;
+ }
+
+ // avatars bigger than 1024x768 just sux: they can't be seen on tooltips anyway
+ KviCachedPixmap * p = KVI_OPTION_BOOL(KviOption_boolScaleAvatarsOnLoad) ? getPixmapWithCacheScaleOnLoad(szP,
+ KVI_OPTION_UINT(KviOption_uintScaleAvatarsOnLoadWidth)
+ ,KVI_OPTION_UINT(KviOption_uintScaleAvatarsOnLoadHeight)) : getPixmapWithCache(szP);
+ if(!p)return 0;
+
+ return new KviAvatar(p->path(),szN,new QPixmap(*(p->pixmap())));
+}
+
+void KviIconManager::clearCache()
+{
+ m_pCachedImages->clear();
+}
+
+void KviIconManager::reloadImages()
+{
+ clearCache();
+ for(int i=0;i<KVI_NUM_SMALL_ICONS;i++)
+ {
+ if(m_smallIcons[i])delete m_smallIcons[i];
+ m_smallIcons[i] = 0;
+ }
+}
+
+
+QPixmap * KviIconManager::loadSmallIcon(int idx)
+{
+ if(idx >= KVI_NUM_SMALL_ICONS)return 0;
+ if(idx < 0)return 0;
+
+
+ // COMPATIBILITY ENTRY: To be removed in some time.
+ // This part loads the old smallicon library format kvi_smallicon_*.png
+ // to preserve backward compatibility with old themes.
+ // We lookup such files ONLY in the themes directories.
+
+ QString szFileName = KVI_SMALLICONS_IMAGELIB_PREFIX;
+
+ int fileidx = idx / 16;
+
+ if(fileidx >= 10)KviQString::appendFormatted(szFileName,"%d.png",fileidx);
+ else KviQString::appendFormatted(szFileName,"0%d.png",fileidx);
+
+ QString buffer;
+ if(g_pApp->findImageThemeOnlyCompat(buffer,szFileName))
+ {
+ KviImageLibrary l1(buffer,16,16);
+
+ int offset = fileidx * 16;
+
+ for(int i=0;i<16;i++)
+ {
+ int io = i + offset;
+ if(io >= KVI_NUM_SMALL_ICONS)break;
+ if(m_smallIcons[io])delete m_smallIcons[io];
+ m_smallIcons[io] = new QPixmap(l1.getImage(i));
+ }
+
+ return m_smallIcons[idx];
+ }
+
+ // otherwise we use the NEW method: separate small icons in the "coresmall" subdirectory.
+ QString szPath;
+ KviQString::sprintf(szPath,KVI_SMALLICONS_PREFIX "%s.png",g_szIconNames[idx]);
+
+ g_pApp->findSmallIcon(buffer,szPath);
+ m_smallIcons[idx] = new QPixmap(buffer);
+
+ //if(m_smallIcon[idx]->isNull())
+ //{
+ // // load an "unknown" image ?.. but should never happen
+ //}
+ return m_smallIcons[idx];
+}
+
+void KviIconManager::cacheCleanup()
+{
+ QStringList l;
+
+ KviPointerHashTableIterator<QString,KviCachedPixmap> it(*m_pCachedImages);
+
+
+//#warning "IMPLEMENT CLEANUP"
+/*
+ while(it.current())
+ {
+ kvi_time_t curTime = kvi_unixTime();
+
+ if((((unsigned int)it.current()->timestamp) - ((unsigned int)curTime)) > 120)
+ {
+ // unused since 2 minutes
+ // time to cleanup it...
+ l.append(new KviStr(it.currentKey()));
+ }
+ ++it;
+ }
+
+ for(QStringList::Iterator it = l.begin();it != l.end();++it)
+ {
+ m_pCachedImages->remove(*it);
+ }
+*/
+/*
+ for(KviStr * p =l.first();p;p = l.next())
+ {
+ m_pCachedImages->remove(p->ptr());
+ }
+ if(m_pCachedImages->isEmpty())m_pCleanupTimer->stop();
+*/
+}
+
+#include "kvi_iconmanager.moc"
diff --git a/src/kvirc/kernel/kvi_iconmanager.h b/src/kvirc/kernel/kvi_iconmanager.h
new file mode 100644
index 00000000..d8f2abb9
--- /dev/null
+++ b/src/kvirc/kernel/kvi_iconmanager.h
@@ -0,0 +1,501 @@
+#ifndef _KVI_ICONMANAGER_H_
+#define _KVI_ICONMANAGER_H_
+
+//=============================================================================
+//
+// File : kvi_iconmanager.h
+// Creation date : Sat Jun 24 2000 14:49:24 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_string.h"
+#include "kvi_avatar.h"
+#include "kvi_time.h"
+
+#include <qpixmap.h>
+#include <qobject.h>
+#include <qwidget.h>
+#include "kvi_pointerhashtable.h"
+
+
+
+#define KVI_SMALLICON_NONE 0
+#define KVI_SMALLICON_CLOSE 1
+#define KVI_SMALLICON_MAXIMIZE 2
+#define KVI_SMALLICON_MINIMIZE 3
+#define KVI_SMALLICON_RESTORE 4
+#define KVI_SMALLICON_DEFAULTICON 5
+#define KVI_SMALLICON_DOCK 6
+#define KVI_SMALLICON_UNDOCK 7
+#define KVI_SMALLICON_QUITAPP 8
+#define KVI_SMALLICON_CONSOLE 9
+#define KVI_SMALLICON_FLOPPY 10
+#define KVI_SMALLICON_PARSERERROR 11
+#define KVI_SMALLICON_PARSERWARNING 12
+#define KVI_SMALLICON_SERVER 13
+#define KVI_SMALLICON_WORLD 14
+#define KVI_SMALLICON_PROXY 15
+#define KVI_SMALLICON_KVIRC 16
+#define KVI_SMALLICON_CUT 17
+#define KVI_SMALLICON_COPY 18
+#define KVI_SMALLICON_PASTE 19
+#define KVI_SMALLICON_OPTIONS 20
+#define KVI_SMALLICON_SOCKETMESSAGE 21
+#define KVI_SMALLICON_SOCKETWARNING 22
+#define KVI_SMALLICON_SOCKETERROR 23
+#define KVI_SMALLICON_SYSTEMERROR 24
+#define KVI_SMALLICON_RAW 25
+#define KVI_SMALLICON_SYSTEMWARNING 26
+#define KVI_SMALLICON_SYSTEMMESSAGE 27
+#define KVI_SMALLICON_UNHANDLED 28
+#define KVI_SMALLICON_SERVERINFO 29
+#define KVI_SMALLICON_MOTD 30
+#define KVI_SMALLICON_CHANNEL 31
+#define KVI_SMALLICON_HIDEDOUBLEVIEW 32
+#define KVI_SMALLICON_SHOWDOUBLEVIEW 33
+#define KVI_SMALLICON_OP 34
+#define KVI_SMALLICON_VOICE 35
+#define KVI_SMALLICON_SERVERPING 36
+#define KVI_SMALLICON_SHOWLISTVIEW 37
+#define KVI_SMALLICON_HIDELISTVIEW 38
+#define KVI_SMALLICON_JOIN 39
+#define KVI_SMALLICON_PART 40
+#define KVI_SMALLICON_UNRECOGNIZED 41
+#define KVI_SMALLICON_TOPIC 42
+#define KVI_SMALLICON_ACCEPT 43
+#define KVI_SMALLICON_DISCARD 44
+#define KVI_SMALLICON_OWNPRIVMSG 45
+#define KVI_SMALLICON_CHANPRIVMSG 46
+#define KVI_SMALLICON_QUERY 47
+#define KVI_SMALLICON_QUERYPRIVMSG 48
+#define KVI_SMALLICON_HELP 49
+#define KVI_SMALLICON_MDIHELP 50
+#define KVI_SMALLICON_CTCPREPLY 51
+#define KVI_SMALLICON_CTCPREQUESTREPLIED 52
+#define KVI_SMALLICON_CTCPREQUESTIGNORED 53
+#define KVI_SMALLICON_CTCPREQUESTFLOOD 54
+#define KVI_SMALLICON_CTCPREQUESTUNKNOWN 55
+#define KVI_SMALLICON_ACTION 56
+#define KVI_SMALLICON_AVATAR 57
+#define KVI_SMALLICON_QUIT 58
+#define KVI_SMALLICON_SPLIT 59
+#define KVI_SMALLICON_QUITSPLIT 60
+#define KVI_SMALLICON_NICK 61
+#define KVI_SMALLICON_DEOP 62
+#define KVI_SMALLICON_DEVOICE 63
+#define KVI_SMALLICON_MODE 64
+#define KVI_SMALLICON_KEY 65
+#define KVI_SMALLICON_LIMIT 66
+#define KVI_SMALLICON_BAN 67
+#define KVI_SMALLICON_UNBAN 68
+#define KVI_SMALLICON_BANEXCEPT 69
+#define KVI_SMALLICON_BANUNEXCEPT 70
+#define KVI_SMALLICON_INVITEEXCEPT 71
+#define KVI_SMALLICON_INVITEUNEXCEPT 72
+#define KVI_SMALLICON_CHANMODE 73
+#define KVI_SMALLICON_CHANMODEHIDE 74
+#define KVI_SMALLICON_WHO 75
+#define KVI_SMALLICON_EDITOR 76
+#define KVI_SMALLICON_DCCREQUEST 77
+#define KVI_SMALLICON_DCCMSG 78
+#define KVI_SMALLICON_DCCERROR 79
+#define KVI_SMALLICON_ICONMANAGER 80
+#define KVI_SMALLICON_SCRIPTCENTER 81
+#define KVI_SMALLICON_BOMB 82
+#define KVI_SMALLICON_EVENT 83
+#define KVI_SMALLICON_EVENTNOHANDLERS 84
+#define KVI_SMALLICON_HANDLER 85
+#define KVI_SMALLICON_HANDLERDISABLED 86
+#define KVI_SMALLICON_NICKNAMEPROBLEM 87
+#define KVI_SMALLICON_WHOISUSER 88
+#define KVI_SMALLICON_WHOISCHANNELS 89
+#define KVI_SMALLICON_WHOISIDLE 90
+#define KVI_SMALLICON_WHOISSERVER 91
+#define KVI_SMALLICON_WHOISOTHER 92
+#define KVI_SMALLICON_TIME 93
+#define KVI_SMALLICON_NOTIFYONLINE 94
+#define KVI_SMALLICON_NOTIFYOFFLINE 95
+#define KVI_SMALLICON_LOCKED 96
+#define KVI_SMALLICON_UNLOCKED 97
+#define KVI_SMALLICON_LOCKEDOFF 98
+#define KVI_SMALLICON_UNLOCKEDOFF 99
+#define KVI_SMALLICON_OWNPRIVMSGCRYPTED 100
+#define KVI_SMALLICON_CHANPRIVMSGCRYPTED 101
+#define KVI_SMALLICON_QUERYPRIVMSGCRYPTED 102
+#define KVI_SMALLICON_DCCCHATMSG 103
+#define KVI_SMALLICON_DCCCHATMSGCRYPTED 104
+#define KVI_SMALLICON_IRC 105
+#define KVI_SMALLICON_FOLDER 106
+#define KVI_SMALLICON_HOME 107
+#define KVI_SMALLICON_BOOKMARKS 108
+#define KVI_SMALLICON_SPY 109
+#define KVI_SMALLICON_KICK 110
+#define KVI_SMALLICON_LINUX 111
+#define KVI_SMALLICON_LINKS 112
+#define KVI_SMALLICON_REGUSERS 113
+#define KVI_SMALLICON_DOCKWIDGET 114
+#define KVI_SMALLICON_CASCADEWINDOWS 115
+#define KVI_SMALLICON_MAXVERTICAL 116
+#define KVI_SMALLICON_MAXHORIZONTAL 117
+#define KVI_SMALLICON_TILEWINDOWS 118
+#define KVI_SMALLICON_LOG 119
+#define KVI_SMALLICON_SPAM 120
+#define KVI_SMALLICON_FILE 121
+#define KVI_SMALLICON_ICQ 122
+#define KVI_SMALLICON_ICQYELLOW 123
+#define KVI_SMALLICON_ICQRED 124
+#define KVI_SMALLICON_ICQBLUE 125
+#define KVI_SMALLICON_ICQLIGHTGREEN 126
+#define KVI_SMALLICON_ICQLIGHTYELLOW 127
+#define KVI_SMALLICON_MESSAGE 128
+#define KVI_SMALLICON_MESSAGESENT 129
+#define KVI_SMALLICON_BLUESQUARE 130
+#define KVI_SMALLICON_VIOLETSQUARE 131
+#define KVI_SMALLICON_YELLOWSQUARE 132
+#define KVI_SMALLICON_GREENSQUARE 133
+#define KVI_SMALLICON_BLACKSQUARE 134
+#define KVI_SMALLICON_REDSQUARE 135
+#define KVI_SMALLICON_CYANSQUARE 136
+#define KVI_SMALLICON_DKGREENSQUARE 137
+#define KVI_SMALLICON_TERMINAL 138
+#define KVI_SMALLICON_WALLOPS 139
+#define KVI_SMALLICON_INVISIBLE 140
+#define KVI_SMALLICON_SERVERNOTICE 141
+#define KVI_SMALLICON_GNUTELLA 142
+#define KVI_SMALLICON_SEARCH 143
+#define KVI_SMALLICON_FILES 144
+#define KVI_SMALLICON_TRANSFER 145
+#define KVI_SMALLICON_PACKAGE 146
+#define KVI_SMALLICON_RETRY 147
+#define KVI_SMALLICON_IDEA 148
+#define KVI_SMALLICON_COLORS 149
+#define KVI_SMALLICON_GUI 150
+#define KVI_SMALLICON_IRCVIEW 151
+#define KVI_SMALLICON_ALIAS 152
+#define KVI_SMALLICON_CHANNELNOTICE 153
+#define KVI_SMALLICON_CHANNELNOTICECRYPTED 154
+#define KVI_SMALLICON_QUERYNOTICE 155
+#define KVI_SMALLICON_QUERYNOTICECRYPTED 156
+// FIXME: rename the icon 157: it was colliding with 141
+#define KVI_SMALLICON_SERVNOTICE 157
+#define KVI_SMALLICON_POPUP 158
+#define KVI_SMALLICON_PROLOGUE 159
+#define KVI_SMALLICON_EPILOGUE 160
+#define KVI_SMALLICON_SHAREDFILES 161
+#define KVI_SMALLICON_CTCPREPLYUNKNOWN 162
+#define KVI_SMALLICON_CANVAS 163
+#define KVI_SMALLICON_NICKSERV 164
+#define KVI_SMALLICON_CHANSERV 165
+#define KVI_SMALLICON_DCCVOICE 166
+#define KVI_SMALLICON_PLAY 167
+#define KVI_SMALLICON_RECORD 168
+#define KVI_SMALLICON_AUTOTILEWINDOWS 169
+#define KVI_SMALLICON_AWAY 170
+#define KVI_SMALLICON_IDENT 171
+#define KVI_SMALLICON_HOMEPAGE 172
+#define KVI_SMALLICON_LIST 173
+#define KVI_SMALLICON_HALFOP 174
+#define KVI_SMALLICON_HALFDEOP 175
+#define KVI_SMALLICON_INVITE 176
+#define KVI_SMALLICON_MULTIMEDIA 177
+#define KVI_SMALLICON_LOOK 178
+#define KVI_SMALLICON_INPUT 179
+#define KVI_SMALLICON_MESSAGES 180
+#define KVI_SMALLICON_QUERYTRACE 181
+#define KVI_SMALLICON_NOCHANNEL 182
+#define KVI_SMALLICON_BROADCASTPRIVMSG 183
+#define KVI_SMALLICON_BROADCASTNOTICE 184
+#define KVI_SMALLICON_URL 185
+#define KVI_SMALLICON_RAWEVENT 186
+#define KVI_SMALLICON_RAWEVENTNOHANDLERS 187
+#define KVI_SMALLICON_MEKICK 188
+#define KVI_SMALLICON_MEOP 189
+#define KVI_SMALLICON_MEVOICE 190
+#define KVI_SMALLICON_MEDEOP 191
+#define KVI_SMALLICON_MEDEVOICE 192
+#define KVI_SMALLICON_MEHALFOP 193
+#define KVI_SMALLICON_MEDEHALFOP 194
+#define KVI_SMALLICON_MEBAN 195
+#define KVI_SMALLICON_MEUNBAN 196
+#define KVI_SMALLICON_MEBANEXCEPT 197
+#define KVI_SMALLICON_MEBANUNEXCEPT 198
+#define KVI_SMALLICON_MEINVITEEXCEPT 199
+#define KVI_SMALLICON_MEINVITEUNEXCEPT 200
+#define KVI_SMALLICON_CLASSICTASKBAR 201
+#define KVI_SMALLICON_TREETASKBAR 202
+#define KVI_SMALLICON_IGNORE 203
+#define KVI_SMALLICON_USERLIST 204
+#define KVI_SMALLICON_STATS 205
+#define KVI_SMALLICON_POPUPMENU 206
+#define KVI_SMALLICON_XY 207
+#define KVI_SMALLICON_IRC0 208
+#define KVI_SMALLICON_IRC1 209
+#define KVI_SMALLICON_IRC2 210
+#define KVI_SMALLICON_IRC3 211
+#define KVI_SMALLICON_IRC4 212
+#define KVI_SMALLICON_IRC5 213
+#define KVI_SMALLICON_HEART 214
+#define KVI_SMALLICON_HEARTBROKEN 215
+#define KVI_SMALLICON_ROSE 216
+#define KVI_SMALLICON_BIGGRIN 217
+#define KVI_SMALLICON_BIGGRINGLASSES 218
+#define KVI_SMALLICON_BIGGRINEYES 219
+#define KVI_SMALLICON_TEXTEXCLAMATIVE 220
+#define KVI_SMALLICON_TEXTPOINTS 221
+#define KVI_SMALLICON_KISS 222
+#define KVI_SMALLICON_SURPRISED1 223
+#define KVI_SMALLICON_UGLY 224
+#define KVI_SMALLICON_ANGRY 225
+#define KVI_SMALLICON_SURPRISED2 226
+#define KVI_SMALLICON_SMILE 227
+#define KVI_SMALLICON_TONGUE 228
+#define KVI_SMALLICON_SSL 229
+#define KVI_SMALLICON_CRY 230
+#define KVI_SMALLICON_EYE 231
+#define KVI_SMALLICON_DEADCHANNEL 232
+#define KVI_SMALLICON_DEADQUERY 233
+#define KVI_SMALLICON_SOUND 234
+#define KVI_SMALLICON_TOOLBAR 235
+#define KVI_SMALLICON_TEXTENCODING 236
+#define KVI_SMALLICON_NEWITEM 237
+#define KVI_SMALLICON_NEWITEMBYWIZARD 238
+#define KVI_SMALLICON_DELETEITEM 239
+#define KVI_SMALLICON_EDITITEM 240
+#define KVI_SMALLICON_FILETRANSFER 241
+#define KVI_SMALLICON_CHANADMIN 242
+#define KVI_SMALLICON_CHANUNADMIN 243
+#define KVI_SMALLICON_MECHANADMIN 244
+#define KVI_SMALLICON_MECHANUNADMIN 245
+#define KVI_SMALLICON_USEROP 246
+#define KVI_SMALLICON_DEUSEROP 247
+#define KVI_SMALLICON_MEUSEROP 248
+#define KVI_SMALLICON_MEDEUSEROP 249
+#define KVI_SMALLICON_APPLET 250
+#define KVI_SMALLICON_CAPTION 251
+#define KVI_SMALLICON_TRANSPARENT 252
+#define KVI_SMALLICON_ALERT 253
+#define KVI_SMALLICON_USERWINDOW 254
+#define KVI_SMALLICON_STATUSBAR 255
+#define KVI_SMALLICON_NOTAWAY 256
+#define KVI_SMALLICON_PLUS 257
+#define KVI_SMALLICON_MINUS 258
+#define KVI_SMALLICON_BINARYTEXT 259
+#define KVI_SMALLICON_CHANOWNER 260
+#define KVI_SMALLICON_CHANUNOWNER 261
+#define KVI_SMALLICON_MECHANOWNER 262
+#define KVI_SMALLICON_MECHANUNOWNER 263
+#define KVI_SMALLICON_AFRAID 264
+#define KVI_SMALLICON_TONGUE2 265
+#define KVI_SMALLICON_SAYICON 266
+#define KVI_SMALLICON_SAYCOLORS 267
+#define KVI_SMALLICON_FINGER 268
+#define KVI_SMALLICON_SCRIPTACTION 269
+#define KVI_SMALLICON_TEARSMILE 270
+#define KVI_SMALLICON_SHY 271
+#define KVI_SMALLICON_SERVERERROR 272
+#define KVI_SMALLICON_CAFE 273
+#define KVI_SMALLICON_ADDONS 274
+#define KVI_SMALLICON_CHANOWNERAWAY 275
+#define KVI_SMALLICON_OPAWAY 276
+#define KVI_SMALLICON_VOICEAWAY 277
+#define KVI_SMALLICON_CHANADMINAWAY 278
+#define KVI_SMALLICON_USEROPAWAY 279
+#define KVI_SMALLICON_HALFOPAWAY 280
+#define KVI_SMALLICON_ALIASHIGHLIGHTED 281
+#define KVI_SMALLICON_DEMORALIZED 282
+#define KVI_SMALLICON_SLURP 283
+#define KVI_SMALLICON_NAMESPACE 284
+#define KVI_SMALLICON_SAYSMILE 285
+#define KVI_SMALLICON_SAYKVS 286
+#define KVI_SMALLICON_THEMEOPTIONS 287
+#define KVI_SMALLICON_BUG 288
+#define KVI_SMALLICON_REFRESH 289
+#define KVI_SMALLICON_THEME 290
+#define KVI_SMALLICON_SCREENSHOT 291
+
+#define KVI_NUM_SMALL_ICONS 292
+
+
+#define KVI_BIGICON_DISCONNECTED "kvi_bigicon_disconnected.png"
+#define KVI_BIGICON_CONNECTING "kvi_bigicon_connecting.png"
+#define KVI_BIGICON_CONNECTED "kvi_bigicon_connected.png"
+#define KVI_BIGICON_TOOLS "kvi_bigicon_tools.png"
+#define KVI_BIGICON_ACTIONS "kvi_bigicon_actions.png"
+#define KVI_BIGICON_FOLDER "kvi_bigicon_folder.png"
+#define KVI_BIGICON_UNKNOWN "kvi_bigicon_unknown.png"
+#define KVI_BIGICON_SEPARATOR "kvi_bigicon_separator.png"
+#define KVI_BIGICON_KVS "kvi_bigicon_kvs.png"
+#define KVI_BIGICON_THEME "kvi_bigicon_theme.png"
+#define KVI_BIGICON_ADDONS "kvi_bigicon_addons.png"
+
+#define KVI_BIGICON_HELPINDEX "kvi_bigicon_helpindex.png"
+#define KVI_BIGICON_HELPBACK "kvi_bigicon_helpback.png"
+#define KVI_BIGICON_HELPFORWARD "kvi_bigicon_helpforward.png"
+#define KVI_BIGICON_HELPCLOSE "kvi_bigicon_helpclose.png"
+#define KVI_BIGICON_HELPSEARCH "kvi_bigicon_helpsearch.png"
+
+#define KVI_BIGICON_OPEN "kvi_bigicon_open.png"
+#define KVI_BIGICON_SAVE "kvi_bigicon_save.png"
+#define KVI_BIGICON_REMOVE "kvi_bigicon_remove.png"
+#define KVI_BIGICON_WWW "kvi_bigicon_www.png"
+#define KVI_BIGICON_PACK "kvi_bigicon_pack.png"
+#define KVI_BIGICON_SCREENSHOT "kvi_bigicon_screenshot.png"
+#define KVI_BIGICON_REGUSERS "kvi_bigicon_regusers.png"
+
+#define KVI_SMALLICONS_SUBDIRECTORY "coresmall"
+#define KVI_SMALLICONS_PREFIX "kcs_"
+
+// FIXME: this should be removed
+#define KVI_SMALLICONS_IMAGELIB_PREFIX "kvi_smallicon_"
+
+#define KVI_USERCHANSTATE_IMAGE_NAME "kvi_userchanstate.png"
+#define KVI_ACTIVITYMETER_IMAGE_NAME "kvi_activitymeter.png"
+
+#define KVI_REFRESH_IMAGE_NAME "kvi_icon_refresh.png"
+
+class KviIconManager;
+
+class KVIRC_API KviCachedPixmap
+{
+public:
+ // the pixmap MUST be allocated with new QPixmap()
+ // this calss takes the ownership
+ KviCachedPixmap(QPixmap * ptr,const QString &szPath);
+ ~KviCachedPixmap();
+private:
+ QString m_szPath;
+ kvi_time_t m_tLastAccess;
+ QPixmap * m_pPixmap;
+ unsigned int m_uSize;
+public:
+ QPixmap * pixmap(){ return m_pPixmap; };
+ const QString & path(){ return m_szPath; };
+ unsigned int size(){ return m_uSize; };
+ kvi_time_t lastAccessTime(){ return m_tLastAccess; };
+ void updateLastAccessTime();
+};
+
+class KVIRC_API KviIconWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ KviIconWidget();
+ KviIconWidget(QWidget * par);
+ ~KviIconWidget();
+protected:
+ void init();
+ virtual void closeEvent(QCloseEvent *e);
+ virtual bool eventFilter(QObject * o,QEvent *e);
+signals:
+ void closed();
+ void selected(int iIcon);
+};
+
+
+
+//
+// This class manages the images used by KVIrc.
+//
+// We handle three types of images: builtin small icons, builtin big icons and generic images.
+//
+// The builtin small icons are in the pics/coresmall directory (this is to optimize the directory size
+// since it's a linear search...), are 16x16 in size and are indexed by numbers in a way that their
+// access is really fast. The icons used here are used mostly in KviIrcView (but not exclusively).
+//
+// The generic images are just "any" image that the underlying Qt engine
+// is able to load. They are loaded by (relative) path and
+// cached by name.
+//
+// The builtin big icons are (actually) just generic images
+// that are eventually scaled to 32x32 if needed. One can request
+// a builtin small icon indexed by number to be scaled
+// to the size of 32x32 as a big icon too.
+//
+
+class KVIRC_API KviIconManager : public QObject
+{
+ Q_OBJECT
+public:
+ KviIconManager();
+ ~KviIconManager();
+private:
+ QPixmap * m_smallIcons[KVI_NUM_SMALL_ICONS];
+ KviIconWidget * m_pIconWidget;
+
+ KviPointerHashTable<QString,KviCachedPixmap> * m_pCachedImages;
+ KviPointerHashTable<QString,int> * m_pIconNames;
+ unsigned int m_uCacheTotalSize;
+ unsigned int m_uCacheMaxSize;
+public:
+ // WARNING: Don't store this pointer!
+ // id == filename | number that indicates an internal pixmap
+ // 0 stands for "any"
+ QPixmap * getImage(const char * id,bool bCanBeNumber = true,QString* pRetPath = 0);
+
+ // The returned pointer is owned by the icon manager
+ // and can be deleted at any time : so don't store it
+ KviCachedPixmap * getPixmapWithCache(const QString &szName);
+
+ // The returned pointer is owned by the icon manager
+ // and can be deleted at any time : so don't store it
+ KviCachedPixmap * getPixmapWithCacheScaleOnLoad(const QString &szName,int iMaxWidth,int iMaxHeight);
+
+ // The returned pointer is owned by the icon manager
+ // and can be deleted at any time : so don't store it
+ QPixmap * getPixmap(const QString &szName)
+ { KviCachedPixmap * p = getPixmapWithCache(szName); return p ? p->pixmap() : 0; };
+
+ // this one never fails... if the image can't be found
+ // a default 32x32 image is returned
+ QPixmap * getBigIcon(const QString &szName);
+
+ // this one never fails... if the icon isn't there
+ // then a default 16x16 image is returned
+ QPixmap * getSmallIcon(int idx){ return idx < KVI_NUM_SMALL_ICONS ? (m_smallIcons[idx] ? m_smallIcons[idx] : loadSmallIcon(idx) ) : 0; };
+
+ const char * getSmallIconName(int idx);
+ int getSmallIconIdFromName(const QString &szName);
+
+ // if szLocalPath is empty then szName can be the identification
+ // string for the avatar
+ // if szName is empty then it is found from szLocalPath
+ KviAvatar * getAvatar(const QString &szLocalPath,const QString &szName);
+
+ void urlToCachedFileName(KviStr &szFName);
+ void urlToCachedFileName(QString &szFName);
+
+ void clearCache();
+ void reloadImages();
+
+ void cacheCleanup();
+protected:
+ void addToCache(const QString &szName,KviCachedPixmap * p);
+ //void loadSmallIcons();
+ QPixmap * loadSmallIcon(int idx);
+public slots:
+ void showIconWidget();
+protected slots:
+ void iconWidgetClosed();
+};
+
+extern KVIRC_API KviIconManager * g_pIconManager;
+
+#endif //_KVI_ICONMANAGER_H_
diff --git a/src/kvirc/kernel/kvi_internalcmd.cpp b/src/kvirc/kernel/kvi_internalcmd.cpp
new file mode 100644
index 00000000..61c9f165
--- /dev/null
+++ b/src/kvirc/kernel/kvi_internalcmd.cpp
@@ -0,0 +1,81 @@
+//
+// File : kvi_internalcmd.cpp
+// Creation date : Sun Aug 13 2000 19:22:45 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+#define __KVIRC__
+#define _KVI_INTERNALCMD_CPP_
+
+#include "kvi_internalcmd.h"
+
+// FIXME: #warning "LOCALIZE THIS!"
+
+static char * internalCommandTable[KVI_NUM_INTERNAL_COMMANDS]=
+{
+ "echo INTERNAL COMMAND ERROR: INDEX OUT OF RANGE",
+ "help.open -n -m index.html",
+ "help.open -n index.html",
+ "about.kvirc",
+ "if($option(boolShowGeneralOptionsDialogAsToplevel))options.dialog -t; else options.dialog",
+ "codetester.open",
+ "socketspy.open",
+ "links.open",
+ "if($option(boolShowRegisteredUsersDialogAsToplevel))reguser.edit -t; else reguser.edit",
+ "dockwidget.show",
+ "dockwidget.hide",
+ "toolbareditor.open",
+ "aliaseditor.open",
+ "term.open -m",
+ "eventeditor.open",
+ "dirbrowser.open -m",
+ "dirbrowser.open",
+ "ident.start",
+ "ident.stop",
+ "tip.open" ,
+ "openurl http://www.kvirc.net",
+ "list.open",
+ "if($option(boolShowChannelsJoinDialogAsToplevel))channelsjoin.open -t;else channelsjoin.open",
+ "if($option(boolShowServersConnectDialogAsToplevel))options.edit -t KviServerOptionsWidget;else options.edit KviServerOptionsWidget",
+ "url.list",
+ "openurl http://www.kvirc.net/?id=themes",
+ "openurl http://www.kvirc.net/?id=mailinglist",
+ "openurl https://svn.kvirc.de/kvirc/newticket",
+ "raweditor.open",
+ "popupeditor.open",
+ "dialog.file(open,\"Select a Script File\"){ if(!$str.isEmpty($0))parse $0; }",
+ "actioneditor.open",
+ "quit",
+ "openurl http://www.kvirc.ru",
+ "openurl irc://freenode/kvirc",
+ "openurl irc://ircnet/kvirc",
+ "openurl irc://azzurra/kvirc.net",
+ "openurl http://kvirc-fr.info",
+ "openurl irc://freenode/kvirc-fr",
+ "openurl irc://irc.europnet.org/kvirc"
+};
+
+
+char * kvi_getInternalCommandBuffer(int idx)
+{
+ if(idx > 0 && idx < KVI_NUM_INTERNAL_COMMANDS)
+ {
+ return internalCommandTable[idx];
+ }
+ return internalCommandTable[0];
+}
diff --git a/src/kvirc/kernel/kvi_internalcmd.h b/src/kvirc/kernel/kvi_internalcmd.h
new file mode 100644
index 00000000..533dfc05
--- /dev/null
+++ b/src/kvirc/kernel/kvi_internalcmd.h
@@ -0,0 +1,72 @@
+#ifndef _KVI_INTERNALCMD_H_
+#define _KVI_INTERNALCMD_H_
+//
+// File : kvi_internalcmd.h
+// Creation date : Sun Aug 13 2000 19:21:12 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+
+#define KVI_INTERNALCOMMAND_ECHO_INTERNALERROR 0
+#define KVI_INTERNALCOMMAND_HELP_NEWMDIWINDOW 1
+#define KVI_INTERNALCOMMAND_HELP_NEWSTATICWINDOW 2
+#define KVI_INTERNALCOMMAND_ABOUT_ABOUTKVIRC 3
+#define KVI_INTERNALCOMMAND_OPTIONS_DIALOG 4
+#define KVI_INTERNALCOMMAND_CODETESTER_OPEN 5
+#define KVI_INTERNALCOMMAND_SOCKETSPY_OPEN 6
+#define KVI_INTERNALCOMMAND_LINKS_OPEN 7
+#define KVI_INTERNALCOMMAND_REGUSER_EDIT 8
+#define KVI_INTERNALCOMMAND_DOCKWIDGET_SHOW 9
+#define KVI_INTERNALCOMMAND_DOCKWIDGET_HIDE 10
+#define KVI_INTERNALCOMMAND_TOOLBAREDITOR_OPEN 11
+#define KVI_INTERNALCOMMAND_ALIASEDITOR_OPEN 12
+#define KVI_INTERNALCOMMAND_TERM_OPEN 13
+#define KVI_INTERNALCOMMAND_EVENTEDITOR_OPEN 14
+#define KVI_INTERNALCOMMAND_BROWSER_OPEN_MDI 15
+#define KVI_INTERNALCOMMAND_BROWSER_OPEN 16
+#define KVI_INTERNALCOMMAND_IDENT_START 17
+#define KVI_INTERNALCOMMAND_IDENT_STOP 18
+#define KVI_INTERNALCOMMAND_TIP_OPEN 19
+#define KVI_INTERNALCOMMAND_KVIRC_HOMEPAGE 20
+#define KVI_INTERNALCOMMAND_LIST_OPEN 21
+#define KVI_INTERNALCOMMAND_CHANNELSJOIN_OPEN 22
+#define KVI_INTERNALCOMMAND_SERVERSJOIN_OPEN 23
+#define KVI_INTERNALCOMMAND_URL_OPEN 24
+#define KVI_INTERNALCOMMAND_OPENURL_KVIRC_THEMES 25
+#define KVI_INTERNALCOMMAND_OPENURL_KVIRC_MAILINGLIST 26
+#define KVI_INTERNALCOMMAND_OPENURL_KVIRC_BUGTRACK 27
+#define KVI_INTERNALCOMMAND_RAWEDITOR_OPEN 28
+#define KVI_INTERNALCOMMAND_POPUPEDITOR_OPEN 29
+#define KVI_INTERNALCOMMAND_EXECUTE_SCRIPT_FROM_DISK 30
+#define KVI_INTERNALCOMMAND_ACTIONEDITOR_OPEN 31
+#define KVI_INTERNALCOMMAND_QUIT 32
+#define KVI_INTERNALCOMMAND_KVIRC_HOMEPAGE_RU 33
+#define KVI_INTERNALCOMMAND_OPENURL_KVIRC_ON_FREENODE 34
+#define KVI_INTERNALCOMMAND_OPENURL_KVIRC_ON_IRCNET 35
+#define KVI_INTERNALCOMMAND_OPENURL_KVIRC_IT_ON_AZZURRA 36
+#define KVI_INTERNALCOMMAND_KVIRC_HOMEPAGE_FR 37
+#define KVI_INTERNALCOMMAND_OPENURL_KVIRC_FR_ON_FREENODE 38
+#define KVI_INTERNALCOMMAND_OPENURL_KVIRC_FR_ON_EUROPNET 39
+
+#define KVI_NUM_INTERNAL_COMMANDS 40
+
+extern KVIRC_API char * kvi_getInternalCommandBuffer(int idx);
+
+#endif //_KVI_INTERNALCMD_H_
diff --git a/src/kvirc/kernel/kvi_ipc.cpp b/src/kvirc/kernel/kvi_ipc.cpp
new file mode 100644
index 00000000..3927f275
--- /dev/null
+++ b/src/kvirc/kernel/kvi_ipc.cpp
@@ -0,0 +1,269 @@
+//=============================================================================
+//
+// File : kvi_ipc.hcpp
+// Creation date : Tue Apr 10 2001 15:04:45 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+
+#include "kvi_ipc.h"
+
+
+#ifndef COMPILE_NO_IPC
+
+ #include "kvi_memmove.h"
+ #include "kvi_app.h"
+ #include "kvi_qstring.h"
+
+#ifdef COMPILE_ON_WINDOWS
+
+ static HWND kvi_win_findIpcSentinel()
+ {
+ HWND hWnd = ::FindWindow("QWidget","[Non-Commercial] - kvirc_ipc_sentinel");
+ if(hWnd)return hWnd;
+ hWnd = ::FindWindow("QWidget","[Freeware] - kvirc_ipc_sentinel");
+ if(hWnd)return hWnd;
+ hWnd = ::FindWindow("QWidget","kvirc_ipc_sentinel");
+ return hWnd;
+ }
+
+#else //!COMPILE_ON_WINDOWS
+
+ #ifndef COMPILE_NO_X
+ #include <X11/Xatom.h>
+
+ #include <unistd.h> // for getuid
+ #include <sys/types.h> // for getuid
+
+ #ifdef COMPILE_USE_QT4
+ #include <qx11info_x11.h>
+ #define kvi_ipc_get_xdisplay QX11Info::display
+ #define kvi_ipc_get_xrootwin QX11Info::appRootWindow
+ #else
+ #define kvi_ipc_get_xdisplay qt_xdisplay
+ #define kvi_ipc_get_xrootwin qt_xrootwin
+ #endif
+
+ static Atom kvi_atom_ipc_sentinel_window;
+ static Atom kvi_atom_ipc_remote_command;
+ static Atom kvi_atom_ipc_remote_message;
+ static KviStr kvi_sentinel_id;
+ static bool g_bIpcAtomsLoaded = false;
+
+ static void kvi_ipcLoadAtoms()
+ {
+ if(g_bIpcAtomsLoaded)return;
+ g_bIpcAtomsLoaded = true;
+ kvi_sentinel_id.sprintf("tonno e mistero - %d",getuid());
+ kvi_atom_ipc_sentinel_window = XInternAtom(kvi_ipc_get_xdisplay(),"XA_KVI_IPC_SENTINEL_WINDOW",False);
+ kvi_atom_ipc_remote_command = XInternAtom(kvi_ipc_get_xdisplay(),"XA_KVI_IPC_REMOTE_COMMAND",False);
+ kvi_atom_ipc_remote_message = XInternAtom(kvi_ipc_get_xdisplay(),"XA_KVI_IPC_REMOTE_MESSAGE",False);
+ }
+
+ static void kvi_ipcSetRemoteCommand(Window w,const char * command)
+ {
+ XChangeProperty(kvi_ipc_get_xdisplay(),w,kvi_atom_ipc_remote_command,
+ XA_STRING,8,PropModeReplace,(const unsigned char *)command,kvi_strLen(command) + 1);
+ }
+
+ static Window kvi_x11_findIpcSentinel(Window win)
+ {
+ Atom type;
+ int format;
+ unsigned long nItems,after;
+ unsigned char * data = 0;
+ if(XGetWindowProperty(kvi_ipc_get_xdisplay(),win,kvi_atom_ipc_sentinel_window,0,32,FALSE,XA_STRING,
+ &type,&format,&nItems,&after,&data) == Success)
+ {
+ if((type == XA_STRING) && (format == 8))
+ {
+ if((nItems == ((unsigned long)(kvi_sentinel_id.len()))) && data)
+ {
+ if(kvi_strEqualCSN((const char *)data,kvi_sentinel_id.ptr(),kvi_sentinel_id.len()))
+ {
+ XFree((char *)data);
+ return win;
+ }
+ }
+ }
+ }
+
+ Window root,parent;
+ Window * children;
+ unsigned int nChildren;
+
+ if(!XQueryTree(kvi_ipc_get_xdisplay(),win,&root,&parent,&children,&nChildren))
+ {
+ if(children)XFree((char *)children);
+ return 0;
+ }
+
+ Window found = 0;
+
+ for(int i=nChildren-1;(!found) && (i >= 0);i--)
+ found = kvi_x11_findIpcSentinel(children[i]);
+
+ if(children)XFree((char *)children);
+
+ return found;
+ }
+ #endif //!COMPILE_NO_X
+
+#endif //!COMPILE_ON_WINDOWS
+
+
+ #define KVI_WINDOWS_IPC_MESSAGE 0x2FACE5
+
+ bool kvi_sendIpcMessage(const char * message)
+ {
+#ifdef COMPILE_ON_WINDOWS
+ HWND hSentinel = kvi_win_findIpcSentinel();
+ if(hSentinel != NULL)
+ {
+ COPYDATASTRUCT cpd;
+ cpd.cbData = strlen(message)+1;
+ cpd.dwData = KVI_WINDOWS_IPC_MESSAGE;
+ cpd.lpData = (void *)message;
+ DWORD dwResult;
+ debug(message);
+ ::SendMessageTimeout(hSentinel,WM_COPYDATA,(WPARAM)NULL,(LPARAM)&cpd,SMTO_BLOCK,1000,&dwResult);
+ return true;
+ }
+#else //!COMPILE_ON_WINDOWS
+ #ifndef COMPILE_NO_X
+
+ kvi_ipcLoadAtoms();
+
+ Window sentinel = kvi_x11_findIpcSentinel(kvi_ipc_get_xrootwin());
+ if(sentinel != 0)
+ {
+// XChangeProperty(kvi_ipc_get_xdisplay(),sentinel,kvi_atom_ipc_remote_command,XA_STRING,8,
+// PropModeReplace,(const unsigned char *)message,kvi_strLen(message));
+ kvi_ipcSetRemoteCommand(sentinel,message);
+
+ XEvent e;
+ kvi_memset(&e,0,sizeof(XEvent));
+ e.type = ClientMessage;
+ e.xclient.display = kvi_ipc_get_xdisplay();
+ e.xclient.window = sentinel;
+ e.xclient.message_type = kvi_atom_ipc_remote_message;
+ e.xclient.format = 8;
+
+ XSendEvent(kvi_ipc_get_xdisplay(),sentinel,False,0,&e);
+
+ return true;
+ }
+ #endif //!COMPILE_NO_X
+#endif //!COMPILE_ON_WINDOWS
+ return false;
+ }
+
+
+ //////////////////////////////////////////////////////////////////////
+ // class KviIpcSentinel
+ //
+ // hidden sentinel of ipc messages
+ //
+ //////////////////////////////////////////////////////////////////////
+
+ KviIpcSentinel::KviIpcSentinel()
+ : QWidget(0,"kvirc_ipc_sentinel")
+ {
+#ifdef COMPILE_ON_WINDOWS
+ setCaption("kvirc_ipc_sentinel");
+#else //!COMPILE_ON_WINDOWS
+ #ifndef COMPILE_NO_X
+ kvi_ipcLoadAtoms();
+
+ XChangeProperty(kvi_ipc_get_xdisplay(),winId(),kvi_atom_ipc_sentinel_window,XA_STRING,8,
+ PropModeReplace,(const unsigned char *)kvi_sentinel_id.ptr(),kvi_sentinel_id.len());
+
+ kvi_ipcSetRemoteCommand(winId(),"");
+ #endif //!COMPILE_NO_X
+#endif //!COMPILE_ON_WINDOWS
+
+ move(-50,-50);
+ resize(1,1);
+ hide();
+
+ }
+
+ KviIpcSentinel::~KviIpcSentinel()
+ {
+ }
+
+#ifdef COMPILE_ON_WINDOWS
+
+ bool KviIpcSentinel::winEvent(MSG * msg)
+ {
+ if(msg->message == WM_COPYDATA)
+ {
+ COPYDATASTRUCT * cpd = (COPYDATASTRUCT *)msg->lParam;
+ if(cpd)
+ {
+ if(cpd->dwData == KVI_WINDOWS_IPC_MESSAGE)
+ {
+ debug((char *)(cpd->lpData));
+ if(g_pApp)g_pApp->ipcMessage((char *)(cpd->lpData));
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+#else //!COMPILE_ON_WINDOWS
+ #ifndef COMPILE_NO_X
+ bool KviIpcSentinel::x11Event(XEvent *e)
+ {
+ if(e->type == ClientMessage)
+ {
+ if((e->xclient.message_type = kvi_atom_ipc_remote_message) && (e->xclient.format == 8))
+ {
+ Atom type;
+ int format;
+ unsigned long nItems,after;
+ unsigned char * data = 0;
+ KviStr szData;
+ if(XGetWindowProperty(kvi_ipc_get_xdisplay(),winId(),kvi_atom_ipc_remote_command,0,1024,FALSE,XA_STRING,
+ &type,&format,&nItems,&after,&data) == Success)
+ {
+ if((type == XA_STRING) && (format == 8) && (nItems > 0) && data)
+ {
+ szData = (char *)data;
+ XFree((char *)data);
+ }
+ }
+ kvi_ipcSetRemoteCommand(winId(),"");
+
+ if(g_pApp)g_pApp->ipcMessage(szData.ptr());
+ return true;
+ }
+ }
+ return false;
+ }
+ #endif //!COMPILE_NO_X
+#endif //!COMPILE_ON_WINDOWS
+
+ #include "kvi_ipc.moc"
+
+#endif
diff --git a/src/kvirc/kernel/kvi_ipc.h b/src/kvirc/kernel/kvi_ipc.h
new file mode 100644
index 00000000..432c2615
--- /dev/null
+++ b/src/kvirc/kernel/kvi_ipc.h
@@ -0,0 +1,75 @@
+#ifndef _KVI_IPC_H_
+#define _KVI_IPC_H_
+//=============================================================================
+//
+// File : kvi_ipc.h
+// Creation date : Tue Apr 10 2001 15:04:45 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+
+#ifndef COMPILE_NO_IPC
+
+ #include "kvi_string.h"
+
+ #include <qwidget.h>
+
+#ifdef COMPILE_ON_WINDOWS
+ #include <winsock2.h>
+ #include <windows.h>
+#else //!COMPILE_ON_WINDOWS
+ #ifndef COMPILE_NO_X
+ #ifdef COMPILE_USE_QT4
+ // We need this to be included BEFORE X11/Xlib.h
+ // because of preprocessor constant collisions...
+ #include <qcoreevent.h>
+ #endif
+ #include "kvi_xlib.h" // for XEvent
+ #endif //!COMPILE_NO_X
+#endif //!COMPILE_ON_WINDOWS
+
+ //////////////////////////////////////////////////////////////////////
+ // class KviIpcSentinel
+ //
+ //////////////////////////////////////////////////////////////////////
+
+ class KVIRC_API KviIpcSentinel : public QWidget
+ {
+ Q_OBJECT
+ public:
+ KviIpcSentinel();
+ ~KviIpcSentinel();
+ protected: // protected members
+#ifdef COMPILE_ON_WINDOWS
+ virtual bool winEvent(MSG * msg);
+#else //!COMPILE_ON_WINDOWS
+ #ifndef COMPILE_NO_X
+ virtual bool x11Event(XEvent *e);
+ #endif //!COMPILE_NO_X
+#endif //!COMPILE_ON_WINDOWS
+ };
+
+#endif //!COMPILE_NO_IPC
+
+
+
+#endif //_KVI_IPC_H_
diff --git a/src/kvirc/kernel/kvi_ircconnection.cpp b/src/kvirc/kernel/kvi_ircconnection.cpp
new file mode 100644
index 00000000..4bf59055
--- /dev/null
+++ b/src/kvirc/kernel/kvi_ircconnection.cpp
@@ -0,0 +1,1354 @@
+//=============================================================================
+//
+// File : kvi_ircconnection.cpp
+// Created on Mon 03 May 2004 01:45:42 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_ircconnection.h"
+#include "kvi_ircconnectiontarget.h"
+#include "kvi_ircconnectionuserinfo.h"
+#include "kvi_ircconnectionserverinfo.h"
+#include "kvi_ircconnectionstatedata.h"
+#include "kvi_ircconnectionantictcpflooddata.h"
+#include "kvi_ircconnectionnetsplitdetectordata.h"
+#include "kvi_ircconnectionasyncwhoisdata.h"
+#include "kvi_ircconnectionstatistics.h"
+#include "kvi_irclink.h"
+#include "kvi_ircsocket.h"
+#include "kvi_locale.h"
+#include "kvi_ircserverdb.h"
+#include "kvi_proxydb.h"
+#include "kvi_error.h"
+#include "kvi_out.h"
+#include "kvi_options.h"
+#include "kvi_console.h"
+#include "kvi_netutils.h"
+#include "kvi_internalcmd.h"
+#include "kvi_frame.h"
+#include "kvi_mexlinkfilter.h"
+#include "kvi_garbage.h"
+#include "kvi_malloc.h"
+#include "kvi_memmove.h"
+#include "kvi_debug.h"
+#include "kvi_channel.h"
+#include "kvi_query.h"
+#include "kvi_app.h"
+#include "kvi_databuffer.h"
+#include "kvi_notifylist.h"
+#include "kvi_dns.h"
+#include "kvi_defaults.h"
+#include "kvi_sparser.h"
+#include "kvi_ircdatastreammonitor.h"
+#include "kvi_databuffer.h"
+#include "kvi_lagmeter.h"
+#include "kvi_kvs_eventtriggers.h"
+#include "kvi_kvs_script.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_useridentity.h"
+
+#include <qtimer.h>
+#include <qtextcodec.h>
+
+extern KVIRC_API KviIrcServerDataBase * g_pIrcServerDataBase;
+extern KVIRC_API KviProxyDataBase * g_pProxyDataBase;
+extern KVIRC_API KviGarbageCollector * g_pGarbageCollector;
+
+KviIrcConnection::KviIrcConnection(KviIrcContext * pContext,KviIrcConnectionTarget * pTarget,KviUserIdentity * pIdentity)
+: QObject()
+{
+ m_bIdentdAttached = false;
+ m_pContext = pContext;
+ m_pConsole = pContext->console();
+ m_pFrame = m_pConsole->frame();
+ m_pTarget = pTarget;
+ m_pUserIdentity = pIdentity;
+ m_pChannelList = new KviPointerList<KviChannel>;
+ m_pChannelList->setAutoDelete(false);
+ m_pQueryList = new KviPointerList<KviQuery>;
+ m_pQueryList->setAutoDelete(false);
+ m_pLink = new KviIrcLink(this);
+ m_pUserDataBase = new KviIrcUserDataBase();
+ m_pUserInfo = new KviIrcConnectionUserInfo();
+ m_pServerInfo = new KviIrcConnectionServerInfo();
+ m_pStateData = new KviIrcConnectionStateData();
+ m_pAntiCtcpFloodData = new KviIrcConnectionAntiCtcpFloodData();
+ m_pNetsplitDetectorData = new KviIrcConnectionNetsplitDetectorData();
+ m_pAsyncWhoisData = new KviIrcConnectionAsyncWhoisData();
+ m_pStatistics = new KviIrcConnectionStatistics();
+ m_pNotifyListTimer = 0;
+ m_pNotifyListManager = 0;
+ m_pLocalhostDns = 0;
+ m_pLagMeter = 0;
+ m_eState = Idle;
+ setupTextCodec();
+}
+
+KviIrcConnection::~KviIrcConnection()
+{
+ if(m_bIdentdAttached) g_pFrame->executeInternalCommand(KVI_INTERNALCOMMAND_IDENT_STOP);
+ m_bIdentdAttached = false;
+ if(m_pLocalhostDns)
+ {
+ QObject::disconnect(m_pLocalhostDns,SIGNAL(lookupDone(KviDns *)),0,0);
+ if(m_pLocalhostDns->isRunning())
+ {
+ g_pGarbageCollector->collect(m_pLocalhostDns);
+ } else {
+ delete m_pLocalhostDns;
+ }
+ }
+
+
+ if(m_pNotifyListTimer)
+ {
+ delete m_pNotifyListTimer;
+ m_pNotifyListTimer = 0;
+ }
+ if(m_pNotifyListManager)
+ {
+ delete m_pNotifyListManager; // destroy this before the userDb
+ m_pNotifyListManager = 0;
+ }
+ if(m_pLagMeter)
+ {
+ delete m_pLagMeter;
+ m_pLagMeter = 0;
+ }
+ delete m_pLink; // <-- this MAY trigger a linkTerminated() or something like this!
+ delete m_pChannelList;
+ delete m_pQueryList;
+ delete m_pTarget;
+ delete m_pUserDataBase;
+ delete m_pUserInfo;
+ delete m_pServerInfo;
+ delete m_pStateData;
+ delete m_pAntiCtcpFloodData;
+ delete m_pNetsplitDetectorData;
+ delete m_pAsyncWhoisData;
+ delete m_pStatistics;
+ delete m_pUserIdentity;
+}
+
+void KviIrcConnection::setEncoding(const QString &szEncoding)
+{
+ QTextCodec * c = KviLocale::codecForName(szEncoding.latin1());
+ if(c == m_pTextCodec)return;
+ if(!c)
+ {
+ m_pConsole->output(KVI_OUT_SYSTEMERROR,__tr2qs("Failed to set the encoding to %Q: mapping not available."),&szEncoding);
+ return;
+ }
+ QString tmp = c->name();
+ for(KviChannel * ch = m_pChannelList->first();ch;ch = m_pChannelList->next())
+ {
+ if((ch->textCodec() != c) && (ch->textCodec() != ch->defaultTextCodec())) // actually not using the default!
+ {
+ ch->forceTextCodec(c);
+ if(_OUTPUT_VERBOSE)ch->output(KVI_OUT_VERBOSE,__tr2qs("Changed text encoding to %Q"),&tmp);
+ }
+ }
+ for(KviQuery * q = m_pQueryList->first();q;q = m_pQueryList->next())
+ {
+ if((q->textCodec() != c) && (q->textCodec() != q->defaultTextCodec())) // actually not using the default!
+ {
+ q->forceTextCodec(c);
+ if(_OUTPUT_VERBOSE)q->output(KVI_OUT_VERBOSE,__tr2qs("Changed text encoding to %Q"),&tmp);
+ }
+ }
+ m_pTextCodec = c;
+ m_pConsole->setTextEncoding(szEncoding);
+}
+
+void KviIrcConnection::setupTextCodec()
+{
+ // grab the codec: first look it up in the server data
+ m_pTextCodec = 0;
+ if(!m_pTarget->server()->encoding().isEmpty())
+ {
+ m_pTextCodec = KviLocale::codecForName(m_pTarget->server()->encoding().latin1());
+ if(!m_pTextCodec)debug("KviIrcConnection: can't find QTextCodec for encoding %s",m_pTarget->server()->encoding().utf8().data());
+ }
+ if(!m_pTextCodec)
+ {
+ // try the network
+ if(!m_pTarget->network()->encoding().isEmpty())
+ {
+ m_pTextCodec = KviLocale::codecForName(m_pTarget->network()->encoding().latin1());
+ if(!m_pTextCodec)debug("KviIrcConnection: can't find QTextCodec for encoding %s",m_pTarget->network()->encoding().utf8().data());
+ }
+ }
+ if(!m_pTextCodec)
+ {
+ m_pTextCodec = KviApp::defaultTextCodec();
+ }
+ m_pConsole->setTextEncoding(QString(m_pTextCodec->name()));
+}
+
+KviQCString KviIrcConnection::encodeText(const QString &szText)
+{
+ if(!m_pTextCodec)return szText.utf8();
+ return m_pTextCodec->fromUnicode(szText);
+}
+
+QString KviIrcConnection::decodeText(const char * szText)
+{
+ if(!m_pTextCodec)return QString(szText);
+ return m_pTextCodec->toUnicode(szText);
+}
+
+void KviIrcConnection::serverInfoReceived(const QString &szServerName,const QString &szUserModes,const QString &szChanModes)
+{
+ serverInfo()->setName(szServerName);
+ serverInfo()->setSupportedUserModes(szUserModes);
+ serverInfo()->setSupportedChannelModes(szChanModes);
+ m_pConsole->updateCaption(); // for server name
+ m_pFrame->childConnectionServerInfoChange(this);
+}
+
+const QString & KviIrcConnection::currentServerName()
+{
+ return serverInfo()->name();
+}
+
+const QString & KviIrcConnection::currentNickName()
+{
+ return userInfo()->nickName();
+}
+
+const QString & KviIrcConnection::currentUserName()
+{
+ return userInfo()->userName();
+}
+
+KviIrcServer * KviIrcConnection::server()
+{
+ return m_pTarget->server();
+}
+
+KviProxy * KviIrcConnection::proxy()
+{
+ return m_pTarget->proxy();
+}
+
+const QString & KviIrcConnection::networkName()
+{
+ return m_pTarget->networkName();
+}
+
+KviIrcSocket * KviIrcConnection::socket()
+{
+ return m_pLink->socket();
+}
+
+void KviIrcConnection::abort()
+{
+ // this WILL trigger linkAttemptFailed() or linkTerminated()
+ m_pLink->abort();
+}
+
+void KviIrcConnection::start()
+{
+ m_eState = Connecting;
+ if(KVI_OPTION_BOOL(KviOption_boolUseIdentService) && KVI_OPTION_BOOL(KviOption_boolUseIdentServiceOnlyOnConnect))
+ {
+ g_pFrame->executeInternalCommand(KVI_INTERNALCOMMAND_IDENT_START);
+ m_bIdentdAttached=true;
+ }
+ m_pLink->start();
+}
+
+void KviIrcConnection::linkEstabilished()
+{
+ m_eState = Connected;
+
+ // setup reasonable defaults before notifying anyone
+ m_pStatistics->setConnectionStartTime(kvi_unixTime());
+ m_pStatistics->setLastMessageTime(kvi_unixTime());
+ m_pServerInfo->setName(target()->server()->m_szHostname);
+
+ if(KviPointerList<KviIrcDataStreamMonitor> * l = context()->monitorList())
+ {
+ for(KviIrcDataStreamMonitor *m =l->first();m;m =l->next())
+ m->connectionInitiated();
+ }
+
+ context()->connectionEstabilished();
+
+ // Ok...we're loggin in now
+ resolveLocalHost();
+ loginToIrcServer();
+}
+
+void KviIrcConnection::linkTerminated()
+{
+ if(m_bIdentdAttached)
+ {
+ g_pFrame->executeInternalCommand(KVI_INTERNALCOMMAND_IDENT_STOP);
+ m_bIdentdAttached=false;
+ }
+ m_eState = Idle;
+
+ if(m_pNotifyListManager)
+ {
+ delete m_pNotifyListManager;
+ m_pNotifyListManager = 0;
+ }
+
+ if(m_pLagMeter)
+ {
+ delete m_pLagMeter;
+ m_pLagMeter = 0;
+ }
+
+ if(KviPointerList<KviIrcDataStreamMonitor> * l = context()->monitorList())
+ {
+ for(KviIrcDataStreamMonitor *m =l->first();m;m =l->next())
+ m->connectionTerminated();
+ }
+
+ // Prepare data for an eventual reconnect
+ context()->connectionTerminated();
+}
+
+void KviIrcConnection::linkAttemptFailed(int iError)
+{
+ if(m_bIdentdAttached)
+ {
+ g_pFrame->executeInternalCommand(KVI_INTERNALCOMMAND_IDENT_STOP);
+ m_bIdentdAttached=false;
+ }
+ m_eState = Idle;
+ context()->connectionFailed(iError);
+}
+
+KviChannel * KviIrcConnection::findChannel(const QString &name)
+{
+ for(KviChannel * c = m_pChannelList->first();c;c = m_pChannelList->next())
+ {
+ if(KviQString::equalCI(name,c->windowName()))return c;
+ }
+ return 0;
+}
+
+int KviIrcConnection::getCommonChannels(const QString &nick,QString &szChansBuffer,bool bAddEscapeSequences)
+{
+ int count = 0;
+ for(KviChannel * c = m_pChannelList->first();c;c = m_pChannelList->next())
+ {
+ if(c->isOn(nick))
+ {
+ if(!szChansBuffer.isEmpty())szChansBuffer.append(", ");
+ char uFlag = c->getUserFlag(nick);
+ if(uFlag)
+ {
+ KviQString::appendFormatted(szChansBuffer,bAddEscapeSequences ? "%c\r!c\r%Q\r" : "%c%Q",uFlag,&(c->windowName()));
+ } else {
+ if(bAddEscapeSequences)KviQString::appendFormatted(szChansBuffer,"\r!c\r%Q\r",&(c->windowName()));
+ else szChansBuffer.append(c->windowName());
+ }
+ count++;
+ }
+ }
+ return count;
+}
+
+void KviIrcConnection::unhighlightAllChannels()
+{
+ for(KviChannel * c = m_pChannelList->first();c;c = m_pChannelList->next())
+ c->unhighlight();
+}
+
+void KviIrcConnection::unhighlightAllQueries()
+{
+ for(KviQuery * c = m_pQueryList->first();c;c = m_pQueryList->next())
+ c->unhighlight();
+}
+
+void KviIrcConnection::partAllChannels()
+{
+ for(KviChannel * c = m_pChannelList->first();c;c = m_pChannelList->next())
+ {
+ c->close();
+ }
+}
+
+void KviIrcConnection::closeAllChannels()
+{
+ while(m_pChannelList->first())
+ {
+ m_pFrame->closeWindow(m_pChannelList->first());
+ }
+}
+
+void KviIrcConnection::closeAllQueries()
+{
+ while(m_pQueryList->first())
+ {
+ m_pFrame->closeWindow(m_pQueryList->first());
+ }
+}
+
+KviChannel * KviIrcConnection::createChannel(const QString &szName)
+{
+ KviChannel * c = m_pContext->findDeadChannel(szName);
+ if(c)
+ {
+ c->setAliveChan();
+ if(!KVI_OPTION_BOOL(KviOption_boolCreateMinimizedChannels))
+ {
+ c->raise();
+ c->setFocus();
+ }
+ } else {
+ c = new KviChannel(m_pFrame,m_pConsole,szName);
+ m_pFrame->addWindow(c,!KVI_OPTION_BOOL(KviOption_boolCreateMinimizedChannels));
+ if(KVI_OPTION_BOOL(KviOption_boolCreateMinimizedChannels)) c->minimize();
+ }
+ return c;
+}
+
+KviQuery * KviIrcConnection::createQuery(const QString &szNick)
+{
+ KviQuery * q = m_pContext->findDeadQuery(szNick);
+ if(!q)
+ {
+ q = findQuery(szNick);
+ if(q)return q; // hm ?
+ }
+ if(q)
+ {
+ q->setAliveQuery();
+ if(!KVI_OPTION_BOOL(KviOption_boolCreateMinimizedQuery))
+ {
+ q->raise();
+ q->setFocus();
+ }
+ } else {
+ q = new KviQuery(m_pFrame,m_pConsole,szNick);
+ m_pFrame->addWindow(q,!KVI_OPTION_BOOL(KviOption_boolCreateMinimizedQuery));
+ if(KVI_OPTION_BOOL(KviOption_boolCreateMinimizedQuery))q->minimize();
+ }
+ return q;
+}
+
+KviQuery * KviIrcConnection::findQuery(const QString &name)
+{
+ for(KviQuery * c = m_pQueryList->first();c;c = m_pQueryList->next())
+ {
+ if(KviQString::equalCI(name,c->windowName()))return c;
+ }
+ return 0;
+}
+
+void KviIrcConnection::registerChannel(KviChannel * c)
+{
+ m_pChannelList->append(c);
+ if(KVI_OPTION_BOOL(KviOption_boolLogChannelHistory))
+ g_pApp->addRecentChannel(c->windowName(),m_pTarget->networkName());
+ emit(channelRegistered(c));
+ emit(chanListChanged());
+}
+
+void KviIrcConnection::unregisterChannel(KviChannel * c)
+{
+ m_pChannelList->removeRef(c);
+ emit(channelUnregistered(c));
+ emit(chanListChanged());
+}
+
+void KviIrcConnection::registerQuery(KviQuery * c)
+{
+ m_pQueryList->append(c);
+}
+
+
+void KviIrcConnection::unregisterQuery(KviQuery * c)
+{
+ if(m_pQueryList->removeRef(c))return;
+}
+
+void KviIrcConnection::keepChannelsOpenAfterDisconnect()
+{
+ while(KviChannel * c = m_pChannelList->first())
+ {
+ c->outputNoFmt(KVI_OUT_SOCKETERROR,__tr2qs("Connection to server lost"));
+ c->setDeadChan();
+ }
+}
+
+void KviIrcConnection::keepQueriesOpenAfterDisconnect()
+{
+ while(KviQuery * q = m_pQueryList->first())
+ {
+ q->outputNoFmt(KVI_OUT_SOCKETERROR,__tr2qs("Connection to server lost"));
+ q->setDeadQuery();
+ }
+}
+
+void KviIrcConnection::resurrectDeadQueries()
+{
+ while(KviQuery * q = m_pContext->firstDeadQuery())
+ {
+ q->outputNoFmt(KVI_OUT_SOCKETMESSAGE,__tr2qs("Connection to server established"));
+ q->setAliveQuery();
+ }
+}
+
+
+//=== Message send stuff ====================================================//
+// Max buffer that can be sent to an IRC server is 512 bytes
+// including CRLF. (ircd simply 'cuts' messages to 512 bytes
+// and discards the remainig part)
+// Note that 510 bytes of data is a reasonably long message :)
+//
+// 01234567890123456789012345678901234567890123456789
+// 01234567890123456789012345678901234567890123456789
+// 01234567890123456789012345678901234567890123456789
+// 01234567890123456789012345678901234567890123456789
+// 01234567890123456789012345678901234567890123456789
+// 01234567890123456789012345678901234567890123456789
+// 01234567890123456789012345678901234567890123456789
+// 01234567890123456789012345678901234567890123456789
+// 01234567890123456789012345678901234567890123456789
+// 01234567890123456789012345678901234567890123456789
+// 0123456789\r\n
+//
+// We keep a list of data to send , and flush it as soon as we can.
+//
+
+bool KviIrcConnection::sendFmtData(const char *fmt,...)
+{
+ KviDataBuffer * pData = new KviDataBuffer(512);
+ kvi_va_list(list);
+ kvi_va_start(list,fmt);
+ bool bTruncated;
+ //sprintf the buffer up to 512 chars (adds a CRLF too)
+ int iLen = kvi_irc_vsnprintf((char *)(pData->data()),fmt,list,&bTruncated);
+ kvi_va_end(list);
+ //adjust the buffer size
+ if(iLen < 512)pData->resize(iLen);
+ if(bTruncated)
+ {
+ if(!_OUTPUT_MUTE)
+ m_pConsole->outputNoFmt(KVI_OUT_SOCKETWARNING,__tr2qs("[LINK WARNING]: Socket message truncated to 512 bytes."));
+ }
+
+ // notify the monitors
+ if(KviPointerList<KviIrcDataStreamMonitor> * l = context()->monitorList())
+ {
+ for(KviIrcDataStreamMonitor *m = l->first();m;m = l->next())
+ m->outgoingMessage((const char *)(pData->data()),iLen - 2);
+ }
+
+ return m_pLink->sendPacket(pData);
+}
+
+bool KviIrcConnection::sendData(const char *buffer,int buflen)
+{
+ if(buflen < 0)buflen = (int)strlen(buffer);
+ if(buflen > 510)
+ {
+ buflen = 510;
+ if(!_OUTPUT_MUTE)
+ m_pConsole->outputNoFmt(KVI_OUT_SOCKETWARNING,__tr2qs("[LINK WARNING]: Socket message truncated to 512 bytes."));
+ }
+ KviDataBuffer * pData = new KviDataBuffer(buflen + 2);
+ kvi_memmove(pData->data(),buffer,buflen);
+ *(pData->data()+buflen)='\r';
+ *(pData->data()+buflen+1)='\n';
+
+ // notify the monitors
+ if(KviPointerList<KviIrcDataStreamMonitor> * l = context()->monitorList())
+ {
+ for(KviIrcDataStreamMonitor *m = l->first();m;m = l->next())
+ m->outgoingMessage((const char *)(pData->data()),buflen);
+ }
+
+ return m_pLink->sendPacket(pData);
+}
+
+//==============================================================================================
+// notify list management
+//==============================================================================================
+
+void KviIrcConnection::delayedStartNotifyList()
+{
+ // start the notify list in 15 seconds
+ // We have this delay to wait an eventual RPL_PROTOCTL from the server
+ // telling us that the WATCH notify list method is supported
+ __range_invalid(m_pNotifyListTimer);
+
+ if(m_pNotifyListTimer)delete m_pNotifyListTimer;
+ m_pNotifyListTimer = new QTimer();
+ connect(m_pNotifyListTimer,SIGNAL(timeout()),this,SLOT(restartNotifyList()));
+ m_pNotifyListTimer->start(15000,true);
+
+ // This delay is large enough to fire after the MOTD has been sent,
+ // even on the weirdest network.
+ // If there is no MOTD, this timer will fire after 15 secs,
+ // If there is a MOTD , restartNotifyList() will be triggered by RPL_ENDOFMOTD and
+ // will kill the timer before it has fired.
+}
+
+void KviIrcConnection::endOfMotdReceived()
+{
+ // if the timer is still there running then just
+ if(m_pNotifyListTimer)restartNotifyList();
+}
+
+void KviIrcConnection::restartNotifyList()
+{
+ if(m_pNotifyListTimer)
+ {
+ delete m_pNotifyListTimer;
+ m_pNotifyListTimer = 0;
+ }
+
+ // clear it
+ if(m_pNotifyListManager)
+ {
+ m_pNotifyListManager->stop(); // may need to remove watch entries
+ delete m_pNotifyListManager;
+ m_pNotifyListManager = 0;
+ }
+
+ if(!KVI_OPTION_BOOL(KviOption_boolUseNotifyList))return;
+
+ if(serverInfo()->supportsWatchList() && KVI_OPTION_BOOL(KviOption_boolUseWatchListIfAvailable))
+ {
+ if(_OUTPUT_VERBOSE)
+ m_pConsole->output(KVI_OUT_VERBOSE,__tr2qs("The server seems to support the WATCH notify list method, will try to use it"));
+ m_pNotifyListManager = new KviWatchNotifyListManager(this);
+ } else {
+ if(KVI_OPTION_BOOL(KviOption_boolUseIntelligentNotifyListManager))
+ {
+ m_pNotifyListManager = new KviIsOnNotifyListManager(this);
+ } else {
+ m_pNotifyListManager = new KviStupidNotifyListManager(this);
+ }
+ }
+ m_pNotifyListManager->start();
+}
+
+void KviIrcConnection::restartLagMeter()
+{
+ if(m_pLagMeter)
+ {
+ delete m_pLagMeter;
+ m_pLagMeter = 0;
+ }
+ if(!KVI_OPTION_BOOL(KviOption_boolUseLagMeterEngine))return;
+ m_pLagMeter = new KviLagMeter(this);
+}
+
+void KviIrcConnection::resolveLocalHost()
+{
+ QString szIp;
+
+ if(!socket()->getLocalHostIp(szIp,server()->isIpV6()))
+ {
+ bool bGotIp = false;
+ if(!KVI_OPTION_STRING(KviOption_stringLocalHostIp).isEmpty())
+ {
+#ifdef COMPILE_IPV6_SUPPORT
+ if(server()->isIpV6())
+ {
+ if(KviNetUtils::isValidStringIp_V6(KVI_OPTION_STRING(KviOption_stringLocalHostIp)))bGotIp = true;
+ } else {
+#endif
+ if(KviNetUtils::isValidStringIp(KVI_OPTION_STRING(KviOption_stringLocalHostIp)))bGotIp = true;
+#ifdef COMPILE_IPV6_SUPPORT
+ }
+#endif
+ }
+ if(bGotIp)
+ {
+ m_pUserInfo->setLocalHostIp(KVI_OPTION_STRING(KviOption_stringLocalHostIp));
+ if(!_OUTPUT_MUTE)
+ m_pConsole->output(KVI_OUT_SYSTEMWARNING,__tr2qs("Can't resolve local host address, using user supplied one (%Q)"),
+ &(m_pUserInfo->localHostIp()));
+
+ } else {
+ // FIXME : Maybe check for IPv6 here too ?
+ m_pUserInfo->setLocalHostIp("127.0.0.1");
+ if(!_OUTPUT_MUTE)
+ m_pConsole->output(KVI_OUT_SYSTEMWARNING,__tr2qs("Can't resolve local host address, using default 127.0.0.1"),
+ &(m_pUserInfo->localHostIp()));
+ }
+ } else {
+ m_pUserInfo->setLocalHostIp(szIp);
+ if(!_OUTPUT_QUIET)
+ m_pConsole->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Local host address is %Q"),
+ &(m_pUserInfo->localHostIp()));
+ }
+
+ // For now this is the only we know
+ m_pUserInfo->setHostName(m_pUserInfo->localHostIp());
+ m_pUserInfo->setHostIp(m_pUserInfo->localHostIp());
+}
+
+void KviIrcConnection::changeAwayState(bool bAway)
+{
+ if(bAway)m_pUserInfo->setAway();
+ else m_pUserInfo->setBack();
+
+ m_pConsole->updateCaption();
+ m_pFrame->childConnectionAwayStateChange(this);
+
+ emit awayStateChanged();
+}
+
+void KviIrcConnection::userInfoReceived(const QString &szUserName,const QString &szHostName)
+{
+ userInfo()->setUserName(szUserName);
+ QString szUnmaskedHost = m_pUserInfo->unmaskedHostName();
+ // Update the user entry
+ KviIrcUserEntry * e = userDataBase()->find(userInfo()->nickName());
+ if(e) // should be there! (we have the permanent entry in the notify list view)
+ {
+ e->setUser(szUserName);
+ if(!szHostName.isEmpty())e->setHost(szHostName);
+ } // else buuug
+
+ if(szHostName.isEmpty())return; // nothing to do anyway
+
+ if(KviQString::equalCS(m_pUserInfo->hostName(),szHostName))return; // again nothing to do
+
+ static bool warned_once = false;
+
+ if(!warned_once)
+ {
+ if(!(m_pUserInfo->hostName().isEmpty() || KviQString::equalCS(m_pUserInfo->hostName(),m_pUserInfo->localHostIp())))
+ {
+ // ok, something weird is probably going on
+ // is is non-empty and it is NOT the IP address we have set
+ // at connection startup...
+ // ...the server (or more likely the bouncer) must have changed his mind...
+ if(!_OUTPUT_MUTE)
+ {
+ m_pConsole->output(KVI_OUT_SYSTEMWARNING,__tr2qs("The server seems to have changed the idea about the local hostname"));
+ m_pConsole->output(KVI_OUT_SYSTEMWARNING,__tr2qs("You're probably using a broken bouncer or maybe something weird is happening on the IRC server"));
+ }
+ warned_once = true;
+ }
+ }
+
+ // set it
+ m_pUserInfo->setHostName(szHostName);
+
+ bool bChangeIp = true;
+
+ // if we don't have any routable IP yet, then it is worth to lookup the new hostname
+
+#ifdef COMPILE_IPV6_SUPPORT
+ if((KviNetUtils::isValidStringIp(m_pUserInfo->hostIp()) &&
+ KviNetUtils::isRoutableIpString(m_pUserInfo->hostIp())) ||
+ KviNetUtils::isValidStringIp_V6(m_pUserInfo->hostIp()))
+#else
+ if((KviNetUtils::isValidStringIp(m_pUserInfo->hostIp()) &&
+ KviNetUtils::isRoutableIpString(m_pUserInfo->hostIp())))
+#endif
+ {
+ if(KVI_OPTION_BOOL(KviOption_boolDccGuessIpFromServerWhenLocalIsUnroutable) &&
+ KVI_OPTION_BOOL(KviOption_boolDccBrokenBouncerHack))
+ {
+ if(!_OUTPUT_MUTE)
+ m_pConsole->outputNoFmt(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Here goes your \"broken bouncer hack\": The server has changed the hostname but I'll ignore the IP address change"));
+ bChangeIp = false;
+ }
+ }
+
+ if(bChangeIp)
+ {
+ // lookup the new hostname then...
+#ifdef COMPILE_IPV6_SUPPORT
+ if(KviNetUtils::isValidStringIp(szHostName) || KviNetUtils::isValidStringIp_V6(szHostName))
+#else
+ if(KviNetUtils::isValidStringIp(szHostName))
+#endif
+ {
+ if(!_OUTPUT_MUTE)
+ m_pConsole->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("The local IP address as seen by the IRC server is %Q"),&szHostName);
+ m_pUserInfo->setHostIp(szHostName);
+ } else
+#ifdef COMPILE_IPV6_SUPPORT
+ if(KviNetUtils::isValidStringIp(szUnmaskedHost) || KviNetUtils::isValidStringIp_V6(szUnmaskedHost))
+#else
+ if(KviNetUtils::isValidStringIp(szUnmaskedHost))
+#endif
+ {
+ if(!_OUTPUT_MUTE)
+ m_pConsole->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("The local IP address as seen by the IRC server is %Q"),&szUnmaskedHost);
+ m_pUserInfo->setHostIp(szUnmaskedHost);
+
+ } else {
+ // look it up too
+ if(m_pLocalhostDns)delete m_pLocalhostDns; // it could be only another local host lookup
+ m_pLocalhostDns = new KviDns();
+ connect(m_pLocalhostDns,SIGNAL(lookupDone(KviDns *)),this,SLOT(hostNameLookupTerminated(KviDns *)));
+
+ if(!m_pLocalhostDns->lookup(szHostName,KviDns::Any))
+ {
+ if(!_OUTPUT_MUTE)
+ {
+ // don't change the string to aid the translators
+ QString szTmp = __tr2qs("Can't start the DNS slave thread");
+ m_pConsole->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Unable to resolve the local hostname as seen by the IRC server: %Q"),&szTmp);
+ }
+ delete m_pLocalhostDns;
+ m_pLocalhostDns = 0;
+ } else {
+ if(!_OUTPUT_MUTE)
+ m_pConsole->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Looking up the local hostname as seen by the IRC server (%Q)"),&szHostName);
+ }
+ }
+ }
+}
+
+void KviIrcConnection::hostNameLookupTerminated(KviDns *pDns)
+{
+ //
+ // This is called when our hostname lookup terminates
+ //
+ if(!m_pLocalhostDns)
+ {
+ debug("Something weird is happening: pDns != 0 but m_pLocalhostDns == 0 :/");
+ return;
+ }
+
+ if(m_pLocalhostDns->state() != KviDns::Success)
+ {
+ QString szErr = KviError::getDescription(m_pLocalhostDns->error());
+ if(!m_pUserInfo->hostIp().isEmpty())
+ m_pConsole->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Unable to resolve the local hostname as seen by the IRC server: %Q, using previously resolved %Q"),
+ &szErr,&(m_pUserInfo->hostIp()));
+ else
+ m_pConsole->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Unable to resolve the local hostname as seen by the IRC server: %Q"),
+ &szErr);
+ } else {
+ QString szIpAddr = m_pLocalhostDns->firstIpAddress();
+ m_pConsole->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Local hostname as seen by the IRC server resolved to %Q"),&szIpAddr);
+ m_pUserInfo->setHostIp(m_pLocalhostDns->firstIpAddress());
+ }
+
+ delete m_pLocalhostDns;
+ m_pLocalhostDns = 0;
+}
+
+void KviIrcConnection::loginToIrcServer()
+{
+ KviIrcServer * pServer = target()->server();
+ KviIrcNetwork * pNet = target()->network();
+
+ // Username
+ pServer->m_szUser.stripWhiteSpace();
+ if(!pServer->m_szUser.isEmpty())
+ {
+ if(!_OUTPUT_MUTE)
+ m_pConsole->output(KVI_OUT_VERBOSE,__tr2qs("Using server specific username (%Q)"),&(pServer->m_szUser));
+ } else {
+ if(!pNet->userName().isEmpty())
+ {
+ if(!_OUTPUT_MUTE)
+ m_pConsole->output(KVI_OUT_VERBOSE,__tr2qs("Using network specific username (%Q)"),&(pNet->userName()));
+ pServer->m_szUser = pNet->userName();
+ } else {
+ pServer->m_szUser = KVI_OPTION_STRING(KviOption_stringUsername);
+ }
+ }
+
+ pServer->m_szUser.stripWhiteSpace();
+ if(pServer->m_szUser.isEmpty())pServer->m_szUser = KVI_DEFAULT_USERNAME;
+
+ // For now this is the only we know
+ m_pUserInfo->setUserName(pServer->m_szUser);
+ m_pServerInfo->setName(pServer->m_szHostname);
+
+ // Nick stuff
+ pServer->m_szNick.stripWhiteSpace();
+ if(pServer->m_pReconnectInfo)
+ {
+ if(!_OUTPUT_MUTE)
+ m_pConsole->output(KVI_OUT_VERBOSE,__tr2qs("Using reconnect specific nickname (%Q)"),&(pServer->m_pReconnectInfo->m_szNick));
+ m_pUserInfo->setNickName(pServer->m_pReconnectInfo->m_szNick);
+ m_pStateData->setLoginNickIndex(0);
+ }else if(!pServer->m_szNick.isEmpty())
+ {
+ if(!_OUTPUT_MUTE)
+ m_pConsole->output(KVI_OUT_VERBOSE,__tr2qs("Using server specific nickname (%Q)"),&(pServer->m_szNick));
+ m_pUserInfo->setNickName(pServer->m_szNick);
+ m_pStateData->setLoginNickIndex(0);
+ } else {
+ if(!pNet->nickName().isEmpty())
+ {
+ if(!_OUTPUT_MUTE)
+ m_pConsole->output(KVI_OUT_VERBOSE,__tr2qs("Using network specific nickname (%Q)"),&(pNet->nickName()));
+ m_pUserInfo->setNickName(pNet->nickName());
+ m_pStateData->setLoginNickIndex(0);
+ } else {
+ KVI_OPTION_STRING(KviOption_stringNickname1).stripWhiteSpace();
+ if(KVI_OPTION_STRING(KviOption_stringNickname1).isEmpty())
+ KVI_OPTION_STRING(KviOption_stringNickname1) = KVI_DEFAULT_NICKNAME1;
+ m_pUserInfo->setNickName(KVI_OPTION_STRING(KviOption_stringNickname1));
+ m_pStateData->setLoginNickIndex(1);
+ }
+ }
+
+ // Real name
+ pServer->m_szRealName.stripWhiteSpace();
+ if(!pServer->m_szRealName.isEmpty())
+ {
+ if(!_OUTPUT_MUTE)
+ m_pConsole->output(KVI_OUT_VERBOSE,__tr2qs("Using server specific real name (%Q)"),
+ &(pServer->m_szRealName));
+ m_pUserInfo->setRealName(pServer->m_szRealName);
+ } else {
+ if(!pNet->realName().isEmpty())
+ {
+ if(!_OUTPUT_MUTE)
+ m_pConsole->output(KVI_OUT_VERBOSE,__tr2qs("Using network specific real name (%Q)"),
+ &(pNet->realName()));
+ m_pUserInfo->setRealName(pNet->realName());
+ } else {
+ m_pUserInfo->setRealName(KVI_OPTION_STRING(KviOption_stringRealname));
+ }
+ }
+
+ // FIXME: The server's encoding!
+ setupTextCodec();
+ KviQCString szNick = encodeText(m_pUserInfo->nickName()); // never empty
+ KviQCString szUser = encodeText(m_pUserInfo->userName()); // never empty
+ KviQCString szReal = encodeText(m_pUserInfo->realName()); // may be empty
+
+ if(!szReal.data())szReal = "";
+
+ if(!_OUTPUT_MUTE)
+ m_pConsole->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Logging in as %Q!%Q :%Q"),
+ &(m_pUserInfo->nickName()),&(m_pUserInfo->userName()),&(m_pUserInfo->realName()));
+
+
+ // spity, 27.03.2005: follow the RFC2812 suggested order for connection registration
+ // first the PASS, then NICK and then USER
+
+ // The pass ?
+ pServer->m_szPass.stripWhiteSpace();
+ if(!pServer->m_szPass.isEmpty())
+ {
+ KviStr szHidden;
+ int pLen = pServer->m_szPass.length();
+ for(int i=0;i<pLen;i++)szHidden.append('*');
+
+ if(!_OUTPUT_MUTE)
+ m_pConsole->output(KVI_OUT_VERBOSE,__tr2qs("Sending %s as password"),szHidden.ptr());
+
+ // The colon should allow user to use passwords with whitespaces.
+ // Non-whitespace passwords are unaffected.
+ if(!sendFmtData("PASS :%s",encodeText(pServer->m_szPass).data()))
+ {
+ // disconnected in the meantime
+ return;
+ }
+ }
+
+
+ if(!sendFmtData("NICK %s",szNick.data()))
+ {
+ // disconnected :(
+ return;
+ }
+
+ QString szGenderTag;
+ if(KVI_OPTION_BOOL(KviOption_boolPrependGenderInfoToRealname) && !KVI_OPTION_STRING(KviOption_stringCtcpUserInfoGender).isEmpty())
+ {
+ szGenderTag.append(KVI_TEXT_COLOR);
+ if(KVI_OPTION_STRING(KviOption_stringCtcpUserInfoGender).startsWith("m",false))
+ {
+ szGenderTag.append("1");
+ } else if(KVI_OPTION_STRING(KviOption_stringCtcpUserInfoGender).startsWith("f",false))
+ {
+ szGenderTag.append("2");
+ }
+ szGenderTag.append(KVI_TEXT_RESET);
+ szReal.prepend(KviQString::toUtf8(szGenderTag));
+ }
+
+ if(!sendFmtData("USER %s 0 %s :%s",szUser.data(),
+ KviQString::toUtf8(pServer->m_szHostname).data(),szReal.data()))
+ {
+ // disconnected in the meantime!
+ return;
+ }
+
+ // permanent info in the user database
+ m_pConsole->notifyListView()->join(m_pUserInfo->nickName(),"*","*");
+
+ // set own avatar if we have it
+ KviIrcUserEntry * e = userDataBase()->find(userInfo()->nickName());
+ if(e) // should be there!
+ {
+ if(!e->avatar())
+ {
+ KviAvatar * av = m_pConsole->defaultAvatarFromOptions();
+ if(av)
+ {
+ e->setAvatar(av);
+ m_pConsole->notifyListView()->avatarChanged(userInfo()->nickName());
+ }
+ }
+ } // else buuug
+
+ if(KVI_OPTION_STRING(KviOption_stringCtcpUserInfoGender).startsWith("m",false)){
+ e->setGender(KviIrcUserEntry::Male);
+ } else if(KVI_OPTION_STRING(KviOption_stringCtcpUserInfoGender).startsWith("f",false)){
+ e->setGender(KviIrcUserEntry::Female);
+ }
+
+ // on connect stuff ?
+
+ QString tmp = pNet->onConnectCommand();
+ tmp.stripWhiteSpace();
+ if(!tmp.isEmpty())
+ {
+ if(_OUTPUT_VERBOSE)
+ m_pConsole->output(KVI_OUT_VERBOSE,__tr2qs("Executing scheduled network specific \"on connect\" commands"));
+ KviKvsScript::run(tmp,m_pConsole);
+ }
+
+ tmp = pServer->onConnectCommand();
+ tmp.stripWhiteSpace();
+ if(!tmp.isEmpty())
+ {
+ if(_OUTPUT_VERBOSE)
+ m_pConsole->output(KVI_OUT_VERBOSE,__tr2qs("Executing scheduled server specific \"on connect\" commands"));
+ KviKvsScript::run(tmp,m_pConsole);
+ }
+
+ tmp = m_pUserIdentity->onConnectCommand();
+ tmp.stripWhiteSpace();
+ if(!tmp.isEmpty())
+ {
+ if(_OUTPUT_VERBOSE)
+ m_pConsole->output(KVI_OUT_VERBOSE,__tr2qs("Executing scheduled identity specific \"on connect\" commands"));
+ KviKvsScript::run(tmp,m_pConsole);
+ }
+
+ // and wait for the server to agree...
+}
+
+void KviIrcConnection::nickChange(const QString &szNewNick)
+{
+ // FIXME: should the new nickname be decoded in some way ?
+ m_pConsole->notifyListView()->nickChange(m_pUserInfo->nickName(),szNewNick);
+ m_pUserInfo->setNickName(szNewNick);
+ m_pConsole->output(KVI_OUT_NICK,__tr2qs("You have changed your nickname to %Q"),&szNewNick);
+ m_pConsole->updateCaption();
+ m_pFrame->childConnectionNickNameChange(this);
+ emit nickNameChanged();
+ g_pApp->addRecentNickname(szNewNick);
+}
+
+bool KviIrcConnection::changeUserMode(char mode,bool bSet)
+{
+ __range_valid(m_pConnectionInfo);
+ if(bSet)
+ {
+ if(m_pUserInfo->hasUserMode(mode))return false;
+ m_pUserInfo->addUserMode(mode);
+ } else {
+ if(!m_pUserInfo->hasUserMode(mode))return false;
+ m_pUserInfo->removeUserMode(mode);
+ }
+ m_pConsole->updateCaption();
+ m_pFrame->childConnectionUserModeChange(this);
+ emit userModeChanged();
+ return true;
+}
+
+void KviIrcConnection::loginComplete(const QString &szNickName)
+{
+ if(context()->state() == KviIrcContext::Connected)return;
+
+ context()->loginComplete();
+
+ if(m_bIdentdAttached)
+ {
+ g_pFrame->executeInternalCommand(KVI_INTERNALCOMMAND_IDENT_STOP);
+ m_bIdentdAttached=false;
+ }
+
+ if(szNickName != m_pUserInfo->nickName())
+ {
+ m_pConsole->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("The server refused the suggested nickname (%s) and named you %s instead"),
+ m_pUserInfo->nickName().utf8().data(),szNickName.utf8().data());
+ m_pConsole->notifyListView()->nickChange(m_pUserInfo->nickName(),szNickName);
+ m_pUserInfo->setNickName(szNickName);
+ }
+
+ g_pApp->addRecentNickname(szNickName);
+
+ bool bHaltOutput = false;
+ bHaltOutput = KVS_TRIGGER_EVENT_0_HALTED(KviEvent_OnIrc,m_pConsole);
+
+ if(!bHaltOutput)
+ m_pConsole->outputNoFmt(KVI_OUT_IRC,__tr2qs("Login operations complete, happy ircing!"));
+
+ resurrectDeadQueries();
+
+ // on connect stuff ?
+ QString tmp = target()->network()->onLoginCommand();
+ tmp.stripWhiteSpace();
+ if(!tmp.isEmpty())
+ {
+ if(_OUTPUT_VERBOSE)
+ m_pConsole->output(KVI_OUT_VERBOSE,__tr2qs("Executing scheduled network specific \"on login\" commands"));
+ KviKvsScript::run(tmp,m_pConsole);
+ }
+
+ tmp = target()->server()->onLoginCommand();
+ tmp.stripWhiteSpace();
+ if(!tmp.isEmpty())
+ {
+ if(_OUTPUT_VERBOSE)
+ m_pConsole->output(KVI_OUT_VERBOSE,__tr2qs("Executing scheduled server specific \"on login\" commands"));
+ KviKvsScript::run(tmp,m_pConsole);
+ }
+
+ tmp = m_pUserIdentity->onLoginCommand();
+ tmp.stripWhiteSpace();
+ if(!tmp.isEmpty())
+ {
+ if(_OUTPUT_VERBOSE)
+ m_pConsole->output(KVI_OUT_VERBOSE,__tr2qs("Executing scheduled identity specific \"on login\" commands"));
+ KviKvsScript::run(tmp,m_pConsole);
+ }
+
+ // Set the configured umode
+ KviStr modeStr = server()->initUMode();
+
+ if(modeStr.isEmpty())modeStr = KVI_OPTION_STRING(KviOption_stringDefaultUserMode);
+
+ if(!modeStr.isEmpty())
+ {
+ if(_OUTPUT_VERBOSE)
+ m_pConsole->output(KVI_OUT_VERBOSE,__tr2qs("Setting configured user mode"));
+ sendFmtData("MODE %s +%s",encodeText(QString(m_pUserInfo->nickName())).data(),modeStr.ptr());
+ }
+
+ delayedStartNotifyList();
+ restartLagMeter();
+
+ if(KVI_OPTION_BOOL(KviOption_boolShowChannelsJoinOnIrc))
+ m_pFrame->executeInternalCommand(KVI_INTERNALCOMMAND_CHANNELSJOIN_OPEN);
+
+
+ // join saved channels
+ QString szChannels,szProtectedChannels,szPasswords,szCurPass,szCurChan;
+
+ if(!(m_pStateData->commandToExecAfterConnect().isEmpty()))
+ {
+ KviStr tmp = m_pStateData->commandToExecAfterConnect();
+ KviKvsScript::run(tmp.ptr(),m_pConsole);
+ }
+
+ if(target()->server()->m_pReconnectInfo)
+ {
+ if(!target()->server()->m_pReconnectInfo->m_szJoinChannels.isEmpty())
+ sendFmtData("JOIN %s",encodeText(target()->server()->m_pReconnectInfo->m_szJoinChannels).data());
+
+ KviQuery * query;
+
+ for(QStringList::Iterator it = target()->server()->m_pReconnectInfo->m_szOpenQueryes.begin();
+ it != target()->server()->m_pReconnectInfo->m_szOpenQueryes.end();it++)
+ {
+ QString szNick = *it;
+ query = findQuery(szNick);
+ if(!query) {
+ query = createQuery(szNick);
+ QString user;
+ QString host;
+ KviIrcUserDataBase * db = userDataBase();
+ if(db)
+ {
+ KviIrcUserEntry * e = db->find(szNick);
+ if(e)
+ {
+ user = e->user();
+ host = e->host();
+ }
+ }
+ query->setTarget(szNick,user,host);
+ }
+ query->autoRaise();
+ query->setFocus();
+ }
+ delete target()->server()->m_pReconnectInfo;
+ target()->server()->m_pReconnectInfo=0;
+ }else {
+ if(target()->network()->autoJoinChannelList())
+ {
+ if(_OUTPUT_VERBOSE)
+ m_pConsole->output(KVI_OUT_VERBOSE,__tr2qs("Auto-joining network specific channels"));
+
+ QStringList * l = target()->network()->autoJoinChannelList();
+ if(l->count()!=0)
+ {
+ for ( QStringList::Iterator it = l->begin(); it != l->end(); ++it ) {
+
+ szCurPass=(*it).section(':',1);
+ if(szCurPass.isEmpty())
+ {
+ if(!szChannels.isEmpty())
+ szChannels.append(",");
+ szCurChan = (*it).section(':',0,0);
+ if(!(szCurChan[0]=='#' || szCurChan[0]=='&' || szCurChan[0]=='!'))
+ szCurChan.prepend('#');
+ szChannels.append(szCurChan);
+ } else {
+ if(!szProtectedChannels.isEmpty())
+ szProtectedChannels.append(",");
+ szCurChan = (*it).section(':',0,0);
+ if(!(szCurChan[0]=='#' || szCurChan[0]=='&' || szCurChan[0]=='!'))
+ szCurChan.prepend('#');
+ szProtectedChannels.append(szCurChan);
+ if(!szPasswords.isEmpty())
+ szPasswords.append(",");
+ szPasswords.append(szCurPass);
+ }
+ }
+ }
+ }
+
+ if(server()->autoJoinChannelList())
+ {
+ if(_OUTPUT_VERBOSE)
+ m_pConsole->output(KVI_OUT_VERBOSE,__tr2qs("Auto-joining server specific channels"));
+
+ QStringList * l = server()->autoJoinChannelList();
+ if(l->count()!=0)
+ {
+ for ( QStringList::Iterator it = l->begin(); it != l->end(); ++it ) {
+ szCurPass=(*it).section(':',1);
+ if(szCurPass.isEmpty())
+ {
+ if(!szChannels.isEmpty())
+ szChannels.append(",");
+ szCurChan = (*it).section(':',0,0);
+ if(!(szCurChan[0]=='#' || szCurChan[0]=='&' || szCurChan[0]=='!'))
+ szCurChan.prepend(':');
+ szChannels.append(szCurChan);
+ } else {
+ if(!szProtectedChannels.isEmpty())
+ szProtectedChannels.append(",");
+ szCurChan = (*it).section(':',0,0);
+ if(!(szCurChan[0]=='#' || szCurChan[0]=='&' || szCurChan[0]=='!'))
+ szCurChan.prepend('#');
+ szProtectedChannels.append(szCurChan);
+ if(!szPasswords.isEmpty())
+ szPasswords.append(",");
+ szPasswords.append(szCurPass);
+ }
+ }
+ }
+ }
+
+ QString szCommand;
+ if( (!szChannels.isEmpty()) || (!szProtectedChannels.isEmpty()) )
+ {
+ szCommand.append(szProtectedChannels);
+ if(!szProtectedChannels.isEmpty() && !szChannels.isEmpty())
+ szCommand.append(',');
+ szCommand.append(szChannels);
+ szCommand.append(" ");
+ szCommand.append(szPasswords);
+
+ sendFmtData("JOIN %s",encodeText(szCommand).data());
+ }
+ }
+ // minimize after connect
+ if(KVI_OPTION_BOOL(KviOption_boolMinimizeConsoleAfterConnect))
+ m_pConsole->minimize();
+}
+
+void KviIrcConnection::incomingMessage(const char * message)
+{
+ // A message has arrived from the current server
+ // First of all , notify the monitors
+ if(KviPointerList<KviIrcDataStreamMonitor> * l = context()->monitorList())
+ {
+ for(KviIrcDataStreamMonitor *m = l->first();m;m = l->next())
+ {
+ m->incomingMessage(message);
+ }
+ }
+ // set the last message time
+ m_pStatistics->setLastMessageTime(kvi_unixTime());
+ // and pass it to the server parser for processing
+ g_pServerParser->parseMessage(message,this);
+}
+
+void KviIrcConnection::heartbeat(kvi_time_t tNow)
+{
+ if(m_eState == Connected)
+ {
+ if(!KVI_OPTION_BOOL(KviOption_boolDisableAwayListUpdates))
+ {
+ // update the channel WHO lists (fixes users away state)
+ // first of all, we send our request not more often than every 50 secs
+ if((tNow - stateData()->lastSentChannelWhoRequest()) > 50)
+ {
+ // we also make sure that the last sent request is older than
+ // the last received reply
+ if(stateData()->lastSentChannelWhoRequest() <= stateData()->lastReceivedChannelWhoReply())
+ {
+ // find the channel that has the older list now
+ kvi_time_t tOldest = tNow;
+ KviChannel * pOldest = 0;
+ for(KviChannel * pChan = m_pChannelList->first();pChan;pChan = m_pChannelList->next())
+ {
+ if(pChan->lastReceivedWhoReply() < tOldest)
+ {
+ pOldest = pChan;
+ tOldest = pChan->lastReceivedWhoReply();
+ }
+ }
+ // if the oldest chan who list is older than 150 secs, update it
+ if((tNow - tOldest) > 150)
+ {
+ // ok, sent the request for this channel
+ stateData()->setLastSentChannelWhoRequest(tNow);
+ QString szChanName = encodeText(pOldest->name());
+ if(_OUTPUT_PARANOIC)
+ console()->output(KVI_OUT_VERBOSE,__tr2qs("Updating away state for channel %Q"),&szChanName);
+ if(lagMeter())
+ {
+ KviStr tmp(KviStr::Format,"WHO %s",pOldest->name());
+ lagMeter()->lagCheckRegister(tmp.ptr(),70);
+ }
+ pOldest->setSentSyncWhoRequest();
+ if(!sendFmtData("WHO %s",encodeText(QString(pOldest->name())).data()))return;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/kvirc/kernel/kvi_ircconnection.h b/src/kvirc/kernel/kvi_ircconnection.h
new file mode 100644
index 00000000..fc6acf25
--- /dev/null
+++ b/src/kvirc/kernel/kvi_ircconnection.h
@@ -0,0 +1,282 @@
+#ifndef _KVI_IRCCONNECTION_H_
+#define _KVI_IRCCONNECTION_H_
+//=============================================================================
+//
+// File : kvi_ircconnection.h
+// Created on Mon 03 May 2004 01:45:42 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_qcstring.h"
+#include "kvi_pointerlist.h"
+#include "kvi_time.h"
+#include <qobject.h>
+
+class KviConsole;
+class KviIrcNetworkData;
+class KviIrcServer;
+class KviProxy;
+class KviIrcSocket;
+class KviIrcLink;
+class KviDataBuffer;
+class KviIrcContext;
+class KviFrame;
+class KviChannel;
+class KviQuery;
+class KviIrcConnectionTarget;
+class KviIrcUserDataBase;
+class KviIrcConnectionUserInfo;
+class KviIrcConnectionServerInfo;
+class KviIrcConnectionStateData;
+class KviIrcConnectionAntiCtcpFloodData;
+class KviIrcConnectionNetsplitDetectorData;
+class KviIrcConnectionAsyncWhoisData;
+class KviIrcConnectionStatistics;
+class KviLagMeter;
+class KviNotifyListManager;
+class KviDns;
+class KviUserIdentity;
+
+class QTimer;
+class QTextCodec;
+
+
+class KVIRC_API KviIrcConnection : public QObject
+{
+ friend class KviConsole;
+ friend class KviIrcContext;
+ friend class KviIrcLink;
+ friend class KviServerParser;
+ Q_OBJECT
+public:
+ // only KviConsole can create this
+ // pContext must NOT be null
+ // pTarget must NOT be null and must be allocated with new! this class takes the ownership
+ KviIrcConnection(KviIrcContext * pContext,KviIrcConnectionTarget * pTarget,KviUserIdentity * pIdentity);
+ ~KviIrcConnection();
+public:
+ enum State { Idle, Connecting, Connected };
+private:
+ KviFrame * m_pFrame; // shallow, never null
+ KviConsole * m_pConsole; // shallow, never null
+ KviIrcContext * m_pContext; // shallow, never null
+
+ State m_eState;
+ bool m_bIdentdAttached;
+
+ KviIrcConnectionTarget * m_pTarget; // owned, never null
+
+ KviIrcLink * m_pLink; // owned, never null
+
+ // The initial informations about the user we'll send out to the server
+ // Note that the ACTUAL user informations are in m_pUserInfo instead
+ KviUserIdentity * m_pUserIdentity; // owned, never null
+
+ // The ACTUAL user informations
+ KviIrcConnectionUserInfo * m_pUserInfo; // owned, never null
+ // The ACTUAL server informations
+ KviIrcConnectionServerInfo * m_pServerInfo; // owned, never null
+
+ KviIrcConnectionStateData * m_pStateData; // owned, never null
+
+ KviPointerList<KviChannel> * m_pChannelList; // owned, never null, elements shallow
+ KviPointerList<KviQuery> * m_pQueryList; // owned, never null, elements shallow
+
+ KviIrcUserDataBase * m_pUserDataBase; // owned, never null
+
+ KviNotifyListManager * m_pNotifyListManager; // owned, see restartNotifyList()
+ QTimer * m_pNotifyListTimer; // delayed startup timer for the notify lists
+
+ KviLagMeter * m_pLagMeter; // owned, may be null (when not running)
+
+ KviIrcConnectionAntiCtcpFloodData * m_pAntiCtcpFloodData; // owned, never null
+ KviIrcConnectionNetsplitDetectorData * m_pNetsplitDetectorData; // owned, never null
+ KviIrcConnectionAsyncWhoisData * m_pAsyncWhoisData; // owned, never null
+
+ KviIrcConnectionStatistics * m_pStatistics; // owned, never null
+
+ KviDns * m_pLocalhostDns; // FIXME: this should go to an aux structure
+
+ QTextCodec * m_pTextCodec; // connection codec: never null
+public:
+ // returns a pointer to the owning console
+ // the pointer is NEVER null
+ KviConsole * console(){ return m_pConsole; };
+ // never null
+ KviFrame * frame(){ return m_pFrame; };
+ // never null
+ KviIrcContext * context(){ return m_pContext; };
+ // forwarder from KviIrcConnectionTarget, never null
+ KVI_DEPRECATED KviIrcServer * server();
+ // forwarder from KviIrcConnectionTarget, may be null
+ KVI_DEPRECATED KviProxy * proxy();
+ // never null!
+ KviIrcConnectionTarget * target(){ return m_pTarget; };
+ // never null!
+ KviIrcLink * link(){ return m_pLink; };
+ // this should not be used...
+ KviIrcSocket * socket() KVI_DEPRECATED;
+ // the current state
+ State state(){ return m_eState; };
+ // forwarder from KviIrcConnectionTarget, always non-empty string
+ const QString & networkName();
+ // never null!
+ KviIrcUserDataBase * userDataBase(){ return m_pUserDataBase; };
+ // never null. Use #include "kvi_ircconnectionuserinfo.h"
+ KviIrcConnectionUserInfo * userInfo(){ return m_pUserInfo; };
+ // never null. Use #include "kvi_ircconnectionserverinfo.h"
+ KviIrcConnectionServerInfo * serverInfo(){ return m_pServerInfo; };
+ // never null. Use #include "kvi_ircconnectionstatedata.h"
+ KviIrcConnectionStateData * stateData(){ return m_pStateData; };
+ // never null. Use #include "kvi_ircconnectionantictcpflooddata.h"
+ KviIrcConnectionAntiCtcpFloodData * antiCtcpFloodData(){ return m_pAntiCtcpFloodData; };
+ // never null. Use #include "kvi_ircconnectionnetsplitdetectordata.h"
+ KviIrcConnectionNetsplitDetectorData * netsplitDetectorData(){ return m_pNetsplitDetectorData; };
+ // never null. Use #include "kvi_ircconnectionasyncwhoisdata.h"
+ KviIrcConnectionAsyncWhoisData * asyncWhoisData(){ return m_pAsyncWhoisData; };
+ // never null. Use #include "kvi_ircconnectionstatistics.h"
+ KviIrcConnectionStatistics * statistics(){ return m_pStatistics; };
+ // may be null
+ KviNotifyListManager * notifyListManager(){ return m_pNotifyListManager; };
+ // may be null (when not running)
+ KviLagMeter * lagMeter(){ return m_pLagMeter; };
+ // should be never null.. but if really everything goes wrong, it might be...
+ QTextCodec * textCodec(){ return m_pTextCodec; };
+public:
+ // helper (really common access to userInfo()->nickName())
+ const QString & currentNickName();
+ // helper (really common access to userInfo()->userName())
+ const QString & currentUserName();
+ // helper (really common access to serverInfo()->name())
+ const QString & currentServerName();
+
+ // world interface: the following three functions use m_pLink->sendPacket()
+ bool sendData(const char *buffer,int buflen = -1);
+ bool sendFmtData(const char *fmt,...);
+ //
+ // channel management
+ //
+ // ----> KviChannelManager ?
+ KviChannel * findChannel(const QString &name);
+ KviPointerList<KviChannel> * channelList(){ return m_pChannelList; };
+ int getCommonChannels(const QString &nick,QString &szChansBuffer,bool bAddEscapeSequences = true);
+ KviChannel * createChannel(const QString &name);
+ void registerChannel(KviChannel *c);
+ void unregisterChannel(KviChannel *c);
+ void keepChannelsOpenAfterDisconnect();
+ void closeAllChannels();
+ void setEncoding(const QString &szEncoding);
+public slots:
+ void partAllChannels();
+ void unhighlightAllChannels();
+ void unhighlightAllQueries();
+ void restartNotifyList();
+ void closeAllQueries();
+public:
+ //
+ // query management
+ //
+ // ----> KviQueryManager ?
+ KviQuery * findQuery(const QString &nick);
+ KviPointerList<KviQuery> * queryList(){ return m_pQueryList; };
+ KviQuery * createQuery(const QString &nick);
+ void registerQuery(KviQuery *q);
+ void unregisterQuery(KviQuery *q);
+ void keepQueriesOpenAfterDisconnect();
+ void resurrectDeadQueries();
+ void restartLagMeter();
+protected:
+ //
+ // notify list management
+ //
+ void delayedStartNotifyList();
+ //
+ // login operations
+ //
+ void resolveLocalHost();
+ void loginToIrcServer();
+protected:
+ //
+ // KviServerParser interface
+ //
+ // called to start the notify lists when RPL_ENDOFMOTD is received
+ void endOfMotdReceived();
+ // called when RPL_SERVINFO (004) is received
+ void serverInfoReceived(const QString &szServerName,const QString &szUserModes,const QString &szChanModes);
+ // called to update the away state
+ void changeAwayState(bool bAway);
+ // called on each JOIN (but meaningful almost only on the first one) (FIXME: call it also on other messages ?)
+ void userInfoReceived(const QString &szUserName,const QString &szHostName);
+ // called when NICK is received
+ void nickChange(const QString &szNewNick);
+ // called when MODE is received for each mode character
+ bool changeUserMode(char mode,bool bSet);
+ // called on the first numerics received from server
+ void loginComplete(const QString &szNickName);
+private slots:
+ void hostNameLookupTerminated(KviDns * pDns);
+protected:
+ //
+ // KviIrcContext interface
+ //
+ // this starts an asynchronous connection attempt
+ // you must return control to the qt core for the connection
+ // operations to be initiated
+ void start();
+ // kills any running connection or attempt
+ void abort();
+ // called once in a while (every 5 secs at the moment)
+ void heartbeat(kvi_time_t tNow);
+protected:
+ //
+ // KviIrcLink interface (down)
+ //
+ // this signals that the connection attempt has failed
+ void linkAttemptFailed(int iError);
+ // called by KviIrcLink when the socket state changes to Connected
+ void linkEstabilished();
+ // called by KviIrcLink when the socket state changes to Ready
+ void linkTerminated();
+public:
+ // this is called by KviIrcLink OR KviMexLinkFilter when a message is arriving from the server
+ // needs to be public because subclasses of KviMexLinkFilter may call it.
+ void incomingMessage(const char * message);
+signals:
+ void awayStateChanged();
+ void userModeChanged();
+ void nickNameChanged();
+ void channelRegistered(KviChannel*);
+ void channelUnregistered(KviChannel*);
+ void chanListChanged();
+public:
+ QString decodeText(const char * szText);
+ KviQCString encodeText(const QString &szText);
+private:
+ void setupTextCodec();
+};
+
+
+// TODO: KviIdentity
+
+
+#endif //!_KVI_IRCCONNECTION_H_
+
diff --git a/src/kvirc/kernel/kvi_ircconnectionantictcpflooddata.cpp b/src/kvirc/kernel/kvi_ircconnectionantictcpflooddata.cpp
new file mode 100644
index 00000000..edf42391
--- /dev/null
+++ b/src/kvirc/kernel/kvi_ircconnectionantictcpflooddata.cpp
@@ -0,0 +1,38 @@
+//=============================================================================
+//
+// File : kvi_ircconnectionantictcpflooddata.cpp
+// Created on Sat 26 Jun 2004 18:09:42 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_ircconnectionantictcpflooddata.h"
+
+KviIrcConnectionAntiCtcpFloodData::KviIrcConnectionAntiCtcpFloodData()
+{
+ m_tLastCtcp = 0;
+ m_uCtcpCount = 0;
+}
+
+KviIrcConnectionAntiCtcpFloodData::~KviIrcConnectionAntiCtcpFloodData()
+{
+}
+
diff --git a/src/kvirc/kernel/kvi_ircconnectionantictcpflooddata.h b/src/kvirc/kernel/kvi_ircconnectionantictcpflooddata.h
new file mode 100644
index 00000000..e691a806
--- /dev/null
+++ b/src/kvirc/kernel/kvi_ircconnectionantictcpflooddata.h
@@ -0,0 +1,48 @@
+#ifndef _KVI_IRCCONNECTIONANTICTCPFLOODDATA_H_
+#define _KVI_IRCCONNECTIONANTICTCPFLOODDATA_H_
+//=============================================================================
+//
+// File : kvi_ircconnectionantictcpflooddata.h
+// Created on Sat 26 Jun 2004 18:09:42 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_time.h"
+
+class KVIRC_API KviIrcConnectionAntiCtcpFloodData
+{
+public:
+ KviIrcConnectionAntiCtcpFloodData();
+ ~KviIrcConnectionAntiCtcpFloodData();
+protected:
+ // ctcp antiflood mechanism
+ kvi_time_t m_tLastCtcp; // the time we have received the last "may flood" ctcp request
+ unsigned int m_uCtcpCount; // the ctcp counter for the antiflooder
+public:
+ kvi_time_t lastCtcpTime(){ return m_tLastCtcp; };
+ unsigned int ctcpCount(){ return m_uCtcpCount; };
+ void setLastCtcpTime(kvi_time_t tLastCtcp){ m_tLastCtcp = tLastCtcp; };
+ void increaseCtcpCount(){ m_uCtcpCount++; };
+ void setCtcpCount(unsigned int uCtcpCount){ m_uCtcpCount = uCtcpCount; };
+};
+
+
+#endif //!_KVI_IRCCONNECTIONANTICTCPFLOODDATA_H_
diff --git a/src/kvirc/kernel/kvi_ircconnectionasyncwhoisdata.cpp b/src/kvirc/kernel/kvi_ircconnectionasyncwhoisdata.cpp
new file mode 100644
index 00000000..fce0a23e
--- /dev/null
+++ b/src/kvirc/kernel/kvi_ircconnectionasyncwhoisdata.cpp
@@ -0,0 +1,81 @@
+//=============================================================================
+//
+// File : kvi_ircconnectionasyncwhoisdata.cpp
+// Created on Sat 26 Jun 2004 19:40:20 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_ircconnectionasyncwhoisdata.h"
+#include "kvi_kvs_script.h"
+
+KviAsyncWhoisInfo::KviAsyncWhoisInfo()
+{
+ pCallback = 0;
+ pMagic = 0;
+}
+
+KviAsyncWhoisInfo::~KviAsyncWhoisInfo()
+{
+ if(pCallback)delete pCallback;
+ if(pMagic)delete pMagic;
+}
+
+KviIrcConnectionAsyncWhoisData::KviIrcConnectionAsyncWhoisData()
+{
+ m_pWhoisInfoList = 0;
+}
+
+KviIrcConnectionAsyncWhoisData::~KviIrcConnectionAsyncWhoisData()
+{
+ if(m_pWhoisInfoList)delete m_pWhoisInfoList;
+}
+
+void KviIrcConnectionAsyncWhoisData::add(KviAsyncWhoisInfo * i)
+{
+ if(!m_pWhoisInfoList)
+ {
+ m_pWhoisInfoList = new KviPointerList<KviAsyncWhoisInfo>;
+ m_pWhoisInfoList->setAutoDelete(true);
+ }
+ m_pWhoisInfoList->append(i);
+}
+
+KviAsyncWhoisInfo * KviIrcConnectionAsyncWhoisData::lookup(const QString &nick)
+{
+ if(!m_pWhoisInfoList)return 0;
+ for(KviAsyncWhoisInfo * i = m_pWhoisInfoList->first();i;i = m_pWhoisInfoList->next())
+ {
+ if(KviQString::equalCI(nick,i->szNick))return i;
+ }
+ return 0;
+}
+
+void KviIrcConnectionAsyncWhoisData::remove(KviAsyncWhoisInfo * i)
+{
+ if(!m_pWhoisInfoList)return;
+ m_pWhoisInfoList->removeRef(i);
+ if(m_pWhoisInfoList->isEmpty())
+ {
+ delete m_pWhoisInfoList;
+ m_pWhoisInfoList = 0;
+ }
+}
diff --git a/src/kvirc/kernel/kvi_ircconnectionasyncwhoisdata.h b/src/kvirc/kernel/kvi_ircconnectionasyncwhoisdata.h
new file mode 100644
index 00000000..c623f64e
--- /dev/null
+++ b/src/kvirc/kernel/kvi_ircconnectionasyncwhoisdata.h
@@ -0,0 +1,72 @@
+#ifndef _KVI_IRCCONNECTIONASYNCWHOISDATA_H_
+#define _KVI_IRCCONNECTIONASYNCWHOISDATA_H_
+//=============================================================================
+//
+// File : kvi_ircconnectionasyncwhoisdata.h
+// Created on Sat 26 Jun 2004 19:40:20 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_pointerlist.h"
+
+class KviWindow;
+class KviKvsScript;
+class KviKvsVariant;
+
+class KVIRC_API KviAsyncWhoisInfo
+{
+public:
+ QString szNick;
+ QString szUser;
+ QString szHost;
+ QString szReal;
+ QString szServer;
+ QString szIdle;
+ QString szSignon;
+ QString szChannels;
+ QString szSpecial;
+ KviKvsScript * pCallback;
+ KviKvsVariant * pMagic;
+ QString szCode; // <-- kill this when KVS is hardwired!
+ QString szMagic; // <-- kill this when KVS is hardwired!
+ KviWindow * pWindow;
+public:
+ KviAsyncWhoisInfo();
+ ~KviAsyncWhoisInfo();
+};
+
+
+
+class KVIRC_API KviIrcConnectionAsyncWhoisData
+{
+public:
+ KviIrcConnectionAsyncWhoisData();
+ ~KviIrcConnectionAsyncWhoisData();
+protected:
+ KviPointerList<KviAsyncWhoisInfo> * m_pWhoisInfoList; // awhois pending stuff
+public:
+ void add(KviAsyncWhoisInfo * i);
+ KviAsyncWhoisInfo * lookup(const QString &nick);
+ void remove(KviAsyncWhoisInfo * i);
+};
+
+#endif //!_KVI_IRCCONNECTIONASYNCWHOISDATA_H_
diff --git a/src/kvirc/kernel/kvi_ircconnectionnetsplitdetectordata.cpp b/src/kvirc/kernel/kvi_ircconnectionnetsplitdetectordata.cpp
new file mode 100644
index 00000000..10771328
--- /dev/null
+++ b/src/kvirc/kernel/kvi_ircconnectionnetsplitdetectordata.cpp
@@ -0,0 +1,37 @@
+//=============================================================================
+//
+// File : kvi_ircconnectionnetsplitdetectordata.cpp
+// Created on Sat 26 Jun 2004 18:20:58 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_ircconnectionnetsplitdetectordata.h"
+
+KviIrcConnectionNetsplitDetectorData::KviIrcConnectionNetsplitDetectorData()
+{
+ m_tLastNetsplitOnQuit = 0;
+}
+
+KviIrcConnectionNetsplitDetectorData::~KviIrcConnectionNetsplitDetectorData()
+{
+}
+
diff --git a/src/kvirc/kernel/kvi_ircconnectionnetsplitdetectordata.h b/src/kvirc/kernel/kvi_ircconnectionnetsplitdetectordata.h
new file mode 100644
index 00000000..3aa96528
--- /dev/null
+++ b/src/kvirc/kernel/kvi_ircconnectionnetsplitdetectordata.h
@@ -0,0 +1,46 @@
+#ifndef _KVI_IRCCONNECTIONNETSPLITDETECTORDATA_H_
+#define _KVI_IRCCONNECTIONNETSPLITDETECTORDATA_H_
+//=============================================================================
+//
+// File : kvi_ircconnectionnetsplitdetectordata.h
+// Created on Sat 26 Jun 2004 18:20:58 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_time.h"
+
+class KVIRC_API KviIrcConnectionNetsplitDetectorData
+{
+public:
+ KviIrcConnectionNetsplitDetectorData();
+ ~KviIrcConnectionNetsplitDetectorData();
+protected:
+ QString m_szLastNetsplitOnQuitReason;
+ kvi_time_t m_tLastNetsplitOnQuit;
+public:
+ const QString & lastNetsplitOnQuitReason(){ return m_szLastNetsplitOnQuitReason; };
+ void setLastNetsplitOnQuitReason(const QString &szReason){ m_szLastNetsplitOnQuitReason = szReason; };
+ kvi_time_t lastNetsplitOnQuitTime(){ return m_tLastNetsplitOnQuit; };
+ void setLastNetsplitOnQuitTime(kvi_time_t t){ m_tLastNetsplitOnQuit = t; };
+};
+
+#endif //!_KVI_IRCCONNECTIONNETSPLITDETECTORDATA_H_
diff --git a/src/kvirc/kernel/kvi_ircconnectionserverinfo.cpp b/src/kvirc/kernel/kvi_ircconnectionserverinfo.cpp
new file mode 100644
index 00000000..e057aa09
--- /dev/null
+++ b/src/kvirc/kernel/kvi_ircconnectionserverinfo.cpp
@@ -0,0 +1,285 @@
+//=============================================================================
+//
+// File : kvi_ircconnectionserverinfo.cpp
+// Created on Tue 22 Jun 2004 03:57:32 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_ircconnectionserverinfo.h"
+#include "kvi_locale.h"
+#include "kvi_malloc.h"
+#include "kvi_ircuserdb.h"
+
+KviIrcConnectionServerInfo::KviIrcConnectionServerInfo()
+{
+ // default assumptions
+ m_szSupportedChannelTypes = "#&!+";
+ m_szSupportedModePrefixes = "@+";
+ m_szSupportedModeFlags = "ov";
+ m_pModePrefixTable = 0;
+ buildModePrefixTable();
+ m_bSupportsModesIe = true;
+ m_bSupportsWatchList = false;
+ m_bSupportsCodePages = false;
+ m_iMaxTopicLen=-1;
+ m_szListModes="";
+ m_szPlainModes="";
+ m_iMaxModeChanges=3;
+ m_pServInfo = new KviBasicIrcServerInfo();
+}
+
+KviIrcConnectionServerInfo::~KviIrcConnectionServerInfo()
+{
+ if(m_pServInfo) delete m_pServInfo;
+ if(m_pModePrefixTable) kvi_free(m_pModePrefixTable);
+}
+
+void KviIrcConnectionServerInfo::setSupportedChannelModes(const QString &szSupportedChannelModes)
+{
+ int pos=-1;
+
+ pos=szSupportedChannelModes.find(',');
+ if(pos>=0) m_szListModes=szSupportedChannelModes.left(pos);
+
+ pos=szSupportedChannelModes.findRev(',');
+ if(pos>=0) m_szPlainModes=szSupportedChannelModes.right(szSupportedChannelModes.length()+pos-1);
+
+ m_szSupportedChannelModes = szSupportedChannelModes;
+ m_bSupportsModesIe = (szSupportedChannelModes.contains('e') && szSupportedChannelModes.contains('I'));
+
+ QChar* aux=(QChar*)szSupportedChannelModes.ucs2();
+ while(aux->unicode())
+ {
+ if(!m_szSupportedChannelModes.contains(*aux))
+ m_szSupportedChannelModes.append(*aux);
+ aux++;
+ }
+}
+
+void KviIrcConnectionServerInfo::setSupportedModePrefixes(const QString &szSupportedModePrefixes,const QString &szSupportedModeFlags)
+{
+ m_szSupportedModeFlags = szSupportedModeFlags;
+ m_szSupportedModePrefixes = szSupportedModePrefixes;
+ buildModePrefixTable();
+}
+
+void KviIrcConnectionServerInfo::buildModePrefixTable()
+{
+ if(m_pModePrefixTable) kvi_free(m_pModePrefixTable);
+ const QChar * cPrefix = KviQString::nullTerminatedArray(m_szSupportedModePrefixes);
+ const QChar * cFlag = KviQString::nullTerminatedArray(m_szSupportedModeFlags);
+ if(!cPrefix || !cFlag)return; // eh ?
+
+ m_uPrefixes=QMIN(m_szSupportedModePrefixes.length(),m_szSupportedModePrefixes.length());
+ m_pModePrefixTable=(kvi_u32_t*)kvi_malloc(sizeof(kvi_u32_t)*3*m_uPrefixes);
+
+ unsigned short uPrefix,uFlag;
+
+ // Pragma: FIXME: The whole mode handling needs rethinking!
+ // Alexey: FIXED: rethinked:)
+ // Pragma: LOL :DDDD
+ int i=0;
+ while( (uPrefix = cPrefix->unicode()) && (uFlag = cFlag->unicode()) && i<m_uPrefixes*3)
+ {
+ m_pModePrefixTable[i]=uPrefix;
+ m_pModePrefixTable[i+1]=uFlag;
+ switch(uFlag)
+ {
+ case 'o': m_pModePrefixTable[i+2] = KVI_USERFLAG_OP;
+ break;
+ case 'v': m_pModePrefixTable[i+2] = KVI_USERFLAG_VOICE;
+ break;
+ case 'h': m_pModePrefixTable[i+2] = KVI_USERFLAG_HALFOP;
+ break;
+ case 'a': m_pModePrefixTable[i+2] = KVI_USERFLAG_CHANADMIN;
+ break;
+ case 'u': m_pModePrefixTable[i+2] = KVI_USERFLAG_USEROP;
+ break;
+ case 'q': m_pModePrefixTable[i+2] = KVI_USERFLAG_CHANOWNER;
+ break;
+ default:
+ m_pModePrefixTable[i+2]=0;
+ break;
+ }
+ i+=3;
+ cPrefix++;
+ cFlag++;
+ }
+}
+
+bool KviIrcConnectionServerInfo::isSupportedModePrefix(QChar c)
+{
+ if(!m_pModePrefixTable) return false;
+ for(int i=0;i<m_uPrefixes;i++)
+ {
+ if(m_pModePrefixTable[i*3]==c.unicode()) return true;
+ }
+ return false;
+}
+
+bool KviIrcConnectionServerInfo::isSupportedModeFlag(QChar c)
+{
+ if(!m_pModePrefixTable) return false;
+ for(int i=0;i<m_uPrefixes;i++)
+ {
+ if(m_pModePrefixTable[(i*3)+1]==c.unicode()) return true;
+ }
+ return false;
+}
+
+QChar KviIrcConnectionServerInfo::modePrefixChar(kvi_u32_t flag)
+{
+ if(!m_pModePrefixTable) return QChar(0);
+ for(int i=0;i<m_uPrefixes;i++)
+ {
+ if(m_pModePrefixTable[i*3+2] & flag) return QChar(m_pModePrefixTable[i*3]);
+ }
+ return QChar(0);
+}
+
+QChar KviIrcConnectionServerInfo::modeFlagChar(kvi_u32_t flag)
+{
+ if(!m_pModePrefixTable) return QChar(0);
+ for(int i=0;i<m_uPrefixes;i++)
+ {
+ if(m_pModePrefixTable[i*3+2] & flag ) return QChar(m_pModePrefixTable[i*3+1]);
+ }
+ return QChar(0);
+}
+
+kvi_u32_t KviIrcConnectionServerInfo::modeFlagFromPrefixChar(QChar c)
+{
+ if(!m_pModePrefixTable) return 0;
+ for(int i=0;i<m_uPrefixes;i++)
+ {
+ if(m_pModePrefixTable[i*3]==c.unicode()) return m_pModePrefixTable[i*3+2];
+ }
+ return 0;
+}
+
+kvi_u32_t KviIrcConnectionServerInfo::modeFlagFromModeChar(QChar c)
+{
+ if(!m_pModePrefixTable) return 0;
+ for(int i=0;i<m_uPrefixes;i++)
+ {
+ if(m_pModePrefixTable[i*3+1]==c.unicode()) return m_pModePrefixTable[i*3+2];
+ }
+ return 0;
+}
+
+void KviIrcConnectionServerInfo::setServerVersion(const QString & version)
+{
+ if(m_pServInfo) delete m_pServInfo;
+ if(version.contains("unreal",false))
+ m_pServInfo = new KviUnrealIrcServerInfo(version);
+ else if(version.contains("bahamut",false))
+ m_pServInfo = new KviBahamutIrcServerInfo(version);
+ else if(version.contains("hyperion",false))
+ m_pServInfo = new KviHyperionIrcServerInfo(version);
+ else
+ m_pServInfo = new KviBasicIrcServerInfo(version);
+}
+
+
+KviBasicIrcServerInfo::KviBasicIrcServerInfo(const QString & version)
+{
+ m_szServerVersion = version;
+}
+
+KviBasicIrcServerInfo::~KviBasicIrcServerInfo()
+{
+}
+
+const QString & KviBasicIrcServerInfo::getChannelModeDescription(QChar mode)
+{
+ QString tmp=getCustomChannelModeDescription(mode);
+ if(tmp.isNull()) return getBasicChannelModeDescription(mode);
+ return KviQString::empty;
+}
+
+const QString & KviBasicIrcServerInfo::getUserModeDescription(QChar mode)
+{
+ QString tmp=getCustomUserModeDescription(mode);
+ if(tmp.isNull()) return getBasicUserModeDescription(mode);
+ return KviQString::empty;
+}
+
+const QString & KviBasicIrcServerInfo::getBasicChannelModeDescription(QChar mode)
+{
+ switch(mode.unicode())
+ {
+ case 'o': return __tr2qs("Channel operators"); break;
+ case 'v': return __tr2qs("Voiced users"); break;
+ case 'h': return __tr2qs("Half-operators");break;
+ case 'b': return __tr2qs("Ban masks"); break;
+ case 'c': return __tr2qs("Color free (no ANSI colors)"); break;
+ case 'e': return __tr2qs("Ban exception masks"); break;
+ case 'I': return __tr2qs("Invite exception masks or forbid /INVITE"); break;
+ case 's': return __tr2qs("Secret"); break;
+ case 'p': return __tr2qs("Private"); break;
+ case 't': return __tr2qs("Topic change restricted"); break;
+ case 'i': return __tr2qs("Invite only"); break;
+ case 'n': return __tr2qs("No external messages"); break;
+ case 'a': return __tr2qs("Anonymous or protected user"); break;
+ case 'q': return __tr2qs("Quiet or channel owner"); break;
+ case 'l': return __tr2qs("Limited number of users"); break;
+ case 'k': return __tr2qs("Key"); break;
+ case 'm': return __tr2qs("Moderated"); break;
+ case 'r': return __tr2qs("Registered"); break;
+ case 'G': return __tr2qs("Censor swear words"); break;
+ case 'M': return __tr2qs("Impossible to speak and change nick if not authenticated with NickServ"); break;
+ case 'N': return __tr2qs("Impossible to change nick if not authenticated with NickServ"); break;
+ case 'R': return __tr2qs("Only registered nicks can join"); break;
+ case 'Q': return __tr2qs("No kicks able (unless U-Line)"); break;
+ case 'O': return __tr2qs("IRC-Op only channel"); break;
+ case 'A': return __tr2qs("Server/Network/Tech Admin only channel"); break;
+ case 'K': return __tr2qs("Forbid /KNOCK"); break;
+ case 'S': return __tr2qs("Strip colors"); break;
+ case 'L': return __tr2qs("Redirect on channel full"); break;
+ case 'C': return __tr2qs("Forbid channel CTCPs"); break;
+ case 'u': return __tr2qs("User-operators OR Auditorium: /NAMES and /WHO show only ops"); break;
+ case '7': return __tr2qs("Only 7-bit letters in nicknames allowed"); break;
+ case 'x': return __tr2qs("Impossible to use both 7-bit and 8-bit letters in nicknames"); break;
+ }
+ return KviQString::empty;
+}
+
+const QString & KviBasicIrcServerInfo::getBasicUserModeDescription(QChar mode)
+{
+ switch(mode.unicode())
+ {
+ case 'o': return __tr2qs("o: IRC operator (OPER)"); break;
+ case 'O': return __tr2qs("O: Local IRC operator (LOCOP)"); break;
+ case 'i': return __tr2qs("i: Invisible"); break;
+ case 'w': return __tr2qs("w: Recipient for WALLOPS messages"); break;
+ case 'r': return __tr2qs("r: User with restricted connection (or recipient for messages about rejected bots)"); break;
+ case 's': return __tr2qs("s: Recipient for server notices"); break;
+ case 'z': return __tr2qs("z: Recipient for oper wallop messages"); break;
+ case 'c': return __tr2qs("c: Recipient for cconn messages"); break;
+ case 'k': return __tr2qs("k: Recipient for server kill messages"); break;
+ case 'f': return __tr2qs("f: Recipient for full server notices"); break;
+ case 'y': return __tr2qs("y: Spy :)"); break;
+ case 'd': return __tr2qs("d: Obscure 'DEBUG' flag"); break;
+ case 'n': return __tr2qs("n: Recipient for nick changes"); break;
+ }
+ return KviQString::empty;
+}
diff --git a/src/kvirc/kernel/kvi_ircconnectionserverinfo.h b/src/kvirc/kernel/kvi_ircconnectionserverinfo.h
new file mode 100644
index 00000000..8ab89434
--- /dev/null
+++ b/src/kvirc/kernel/kvi_ircconnectionserverinfo.h
@@ -0,0 +1,141 @@
+#ifndef _KVI_IRCCONNECTIONSERVERINFO_H_
+#define _KVI_IRCCONNECTIONSERVERINFO_H_
+//=============================================================================
+//
+// File : kvi_ircconnectionserverinfo.h
+// Created on Tue 22 Jun 2004 03:57:32 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_inttypes.h"
+
+class KVIRC_API KviBasicIrcServerInfo
+{
+protected:
+ QString m_szServerVersion;
+public:
+ KviBasicIrcServerInfo(const QString & version = KviQString::empty);
+ ~KviBasicIrcServerInfo();
+protected:
+ virtual const QString & getCustomChannelModeDescription(QChar mode) { return KviQString::empty; };
+ virtual const QString & getCustomUserModeDescription(QChar mode) { return KviQString::empty; };
+private:
+ const QString & getBasicChannelModeDescription(QChar mode);
+ const QString & getBasicUserModeDescription(QChar mode);
+public:
+ const QString & getChannelModeDescription(QChar mode);
+ const QString & getUserModeDescription(QChar mode);
+ virtual char getRegisterModeChar() { return 0; };
+};
+
+class KVIRC_API KviUnrealIrcServerInfo : public KviBasicIrcServerInfo
+{
+public:
+ KviUnrealIrcServerInfo(const QString & version = KviQString::empty)
+ :KviBasicIrcServerInfo(version) {;};
+ virtual char getRegisterModeChar() { return 'r'; };
+};
+
+class KVIRC_API KviBahamutIrcServerInfo : public KviBasicIrcServerInfo
+{
+public:
+ KviBahamutIrcServerInfo(const QString & version = KviQString::empty)
+ :KviBasicIrcServerInfo(version) {;};
+ virtual char getRegisterModeChar() { return 'r'; };
+};
+
+class KVIRC_API KviHyperionIrcServerInfo : public KviBasicIrcServerInfo
+{
+public:
+ KviHyperionIrcServerInfo(const QString & version = KviQString::empty)
+ :KviBasicIrcServerInfo(version) {;};
+ virtual char getRegisterModeChar() { return 'e'; };
+};
+
+class KVIRC_API KviIrcConnectionServerInfo
+{
+ friend class KviConsole; // for now
+ friend class KviServerParser;
+ friend class KviIrcConnection;
+protected:
+ KviIrcConnectionServerInfo();
+ ~KviIrcConnectionServerInfo();
+private:
+ KviBasicIrcServerInfo * m_pServInfo;
+ QString m_szName; // the most actual server name (may be the one we specify or the one that the server wants to be known as)
+ QString m_szSupportedUserModes; // the supported user modes
+ QString m_szSupportedChannelModes; // the supported channel modes
+ QString m_szSupportedModePrefixes; // the actually used mode prefixes @+
+ kvi_u32_t * m_pModePrefixTable; // the mode prefixes above in a table
+ unsigned int m_uPrefixes;
+ QString m_szSupportedModeFlags; // the actually used mode flags ov
+ QString m_szSupportedChannelTypes; // the supported channel types
+ bool m_bSupportsModesIe; // supports the channel modes I and e ?
+ bool m_bSupportsWatchList; // supports the watch list ?
+ bool m_bSupportsCodePages; // supports the /CODEPAGE command ?
+ int m_iMaxTopicLen;
+ int m_iMaxModeChanges;
+ QString m_szListModes;
+ QString m_szPlainModes;
+public:
+ char registerModeChar() { return m_pServInfo ? m_pServInfo->getRegisterModeChar() : 0; };
+ const QString & name(){ return m_szName; };
+ const QString & supportedUserModes(){ return m_szSupportedUserModes; };
+ const QString & supportedChannelModes(){ return m_szSupportedChannelModes; };
+ const QString & supportedChannelTypes(){ return m_szSupportedChannelTypes; };
+ const QString & supportedModePrefixes(){ return m_szSupportedModePrefixes; };
+ const QString & supportedModeFlags(){ return m_szSupportedModeFlags; };
+ const QString & supportedListModes(){ return m_szListModes; };
+ const QString & supportedPlainModes(){ return m_szPlainModes; };
+ bool supportsModesIe(){ return m_bSupportsModesIe; };
+ bool supportsWatchList(){ return m_bSupportsWatchList; };
+ bool supportsCodePages(){ return m_bSupportsCodePages; };
+
+ int maxTopicLen() { return m_iMaxTopicLen; };
+ int maxModeChanges() { return m_iMaxModeChanges; };
+
+ void setServerVersion(const QString & version);
+
+ const QString & getChannelModeDescription(QChar mode) { return m_pServInfo->getChannelModeDescription(mode); };
+ const QString & getUserModeDescription(QChar mode) { return m_pServInfo->getUserModeDescription(mode); };
+
+ bool isSupportedModePrefix(QChar c);
+ bool isSupportedModeFlag(QChar c);
+ QChar modePrefixChar(kvi_u32_t flag);
+ QChar modeFlagChar(kvi_u32_t flag);
+ kvi_u32_t modeFlagFromPrefixChar(QChar c);
+ kvi_u32_t modeFlagFromModeChar(QChar c);
+protected:
+ void setName(const QString &szName){ m_szName = szName; };
+ void setSupportedUserModes(const QString &szSupportedUserModes){ m_szSupportedUserModes = szSupportedUserModes; };
+ void setSupportedChannelModes(const QString &szSupportedChannelModes);
+ void setSupportedModePrefixes(const QString &szSupportedModePrefixes,const QString &szSupportedModeFlags);
+ void setSupportedChannelTypes(const QString &szSupportedChannelTypes){ m_szSupportedChannelTypes = szSupportedChannelTypes; };
+ void setSupportsWatchList(bool bSupportsWatchList){ m_bSupportsWatchList = bSupportsWatchList; };
+ void setSupportsCodePages(bool bSupportsCodePages){ m_bSupportsCodePages = bSupportsCodePages; };
+ void setMaxTopicLen( int iTopLen ) { m_iMaxTopicLen=iTopLen; };
+ void setMaxModeChanges(int iModes ) { m_iMaxModeChanges=iModes; };
+private:
+ void buildModePrefixTable();
+};
+
+#endif //!_KVI_IRCCONNECTIONSERVERINFO_H_
diff --git a/src/kvirc/kernel/kvi_ircconnectionstatedata.cpp b/src/kvirc/kernel/kvi_ircconnectionstatedata.cpp
new file mode 100644
index 00000000..2226775a
--- /dev/null
+++ b/src/kvirc/kernel/kvi_ircconnectionstatedata.cpp
@@ -0,0 +1,42 @@
+//=============================================================================
+//
+// File : kvi_ircconnectionstatedata.cpp
+// Created on Sat 26 Jun 2004 09:31:52 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_ircconnectionstatedata.h"
+
+KviIrcConnectionStateData::KviIrcConnectionStateData()
+{
+ m_bSentQuit = false;
+ m_uLoginNickIndex = 0;
+ m_bSimulateUnexpectedDisconnect = false;
+ m_tLastReceivedChannelWhoReply = kvi_unixTime();
+ m_tLastSentChannelWhoRequest = m_tLastReceivedChannelWhoReply;
+ m_tLastReceivedWhoisReply = 0;
+}
+
+KviIrcConnectionStateData::~KviIrcConnectionStateData()
+{
+}
+
diff --git a/src/kvirc/kernel/kvi_ircconnectionstatedata.h b/src/kvirc/kernel/kvi_ircconnectionstatedata.h
new file mode 100644
index 00000000..3a70c749
--- /dev/null
+++ b/src/kvirc/kernel/kvi_ircconnectionstatedata.h
@@ -0,0 +1,77 @@
+#ifndef _KVI_IRCCONNECTIONSTATEDATA_H_
+#define _KVI_IRCCONNECTIONSTATEDATA_H_
+//=============================================================================
+//
+// File : kvi_ircconnectionstatedata.h
+// Created on Sat 26 Jun 2004 09:31:52 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_time.h"
+#include "kvi_qstring.h"
+
+//
+// This class is used as container for miscelaneous connection state variables
+// that do not have a class for their own.
+// If you need to add some "minor" variable to the connection state then
+// this is the right place for it.
+//
+
+class KVIRC_API KviIrcConnectionStateData
+{
+ friend class KviIrcConnection;
+ friend class KviServerParser;
+ friend class KviUserParser;
+public:
+ KviIrcConnectionStateData();
+ ~KviIrcConnectionStateData();
+protected:
+ bool m_bSentQuit; // have we sent the quit message for this connection ?
+ unsigned int m_uLoginNickIndex; // the index of the identity nicknames used until now (see KviIrcConnection::loginToIrcServer())
+ QString m_szCommandToExecAfterConnect; // yes.. this is a special command to execute after connection
+ bool m_bSimulateUnexpectedDisconnect; // this is set to true if we have to simulate an unexpected disconnect even if we have sent a normal quit message
+ kvi_time_t m_tLastReceivedChannelWhoReply; // the time that we have received our last channel who reply
+ kvi_time_t m_tLastSentChannelWhoRequest; // the time that we have sent our last channel who request
+ kvi_time_t m_tLastReceivedWhoisReply; // the time that we have received the last whois reply, reset to 0 when we receive an /END OF WHOIS
+public:
+ bool sentQuit(){ return m_bSentQuit; };
+ void setSentQuit(){ m_bSentQuit = true; };
+
+ kvi_time_t lastReceivedChannelWhoReply(){ return m_tLastReceivedChannelWhoReply; };
+ void setLastReceivedChannelWhoReply(kvi_time_t tTime){ m_tLastReceivedChannelWhoReply = tTime; };
+
+ kvi_time_t lastSentChannelWhoRequest(){ return m_tLastSentChannelWhoRequest; };
+ void setLastSentChannelWhoRequest(kvi_time_t tTime){ m_tLastSentChannelWhoRequest = tTime; };
+
+ kvi_time_t lastReceivedWhoisReply(){ return m_tLastReceivedWhoisReply; };
+ void setLastReceivedWhoisReply(kvi_time_t tTime){ m_tLastReceivedWhoisReply = tTime; };
+
+ bool simulateUnexpectedDisconnect(){ return m_bSimulateUnexpectedDisconnect; };
+ void setSimulateUnexpectedDisconnect(){ m_bSimulateUnexpectedDisconnect = true; };
+
+ unsigned int loginNickIndex(){ return m_uLoginNickIndex; };
+ void setLoginNickIndex(unsigned int uNickIdx){ m_uLoginNickIndex = uNickIdx; };
+
+ const QString & commandToExecAfterConnect(){ return m_szCommandToExecAfterConnect; };
+ void setCommandToExecAfterConnect(const QString &szCmd){ m_szCommandToExecAfterConnect = szCmd; };
+};
+
+#endif //!_KVI_IRCCONNECTIONSTATEDATA_H_
diff --git a/src/kvirc/kernel/kvi_ircconnectionstatistics.cpp b/src/kvirc/kernel/kvi_ircconnectionstatistics.cpp
new file mode 100644
index 00000000..6397e798
--- /dev/null
+++ b/src/kvirc/kernel/kvi_ircconnectionstatistics.cpp
@@ -0,0 +1,38 @@
+//=============================================================================
+//
+// File : kvi_ircconnectionstatistics.cpp
+// Created on Sun 27 Jun 2004 21:13:48 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_ircconnectionstatistics.h"
+
+KviIrcConnectionStatistics::KviIrcConnectionStatistics()
+{
+ m_tConnectionStart = 0;
+ m_tLastMessage = 0;
+}
+
+KviIrcConnectionStatistics::~KviIrcConnectionStatistics()
+{
+}
+
diff --git a/src/kvirc/kernel/kvi_ircconnectionstatistics.h b/src/kvirc/kernel/kvi_ircconnectionstatistics.h
new file mode 100644
index 00000000..e277e77e
--- /dev/null
+++ b/src/kvirc/kernel/kvi_ircconnectionstatistics.h
@@ -0,0 +1,50 @@
+#ifndef _KVI_IRCCONNECTIONSTATISTICS_H_
+#define _KVI_IRCCONNECTIONSTATISTICS_H_
+//=============================================================================
+//
+// File : kvi_ircconnectionstatistics.h
+// Created on Sun 27 Jun 2004 21:13:48 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_time.h"
+
+
+class KVIRC_API KviIrcConnectionStatistics
+{
+ friend class KviConsole; // to be removed
+ friend class KviIrcConnection;
+public:
+ KviIrcConnectionStatistics();
+ ~KviIrcConnectionStatistics();
+protected:
+ kvi_time_t m_tConnectionStart; // (valid only when Connected or LoggingIn)
+ kvi_time_t m_tLastMessage; // last message received from server
+public:
+ kvi_time_t connectionStartTime(){ return m_tConnectionStart; };
+ kvi_time_t lastMessageTime(){ return m_tLastMessage; };
+protected:
+ void setLastMessageTime(kvi_time_t t){ m_tLastMessage = t; };
+ void setConnectionStartTime(kvi_time_t t){ m_tConnectionStart = t; };
+};
+
+#endif //!_KVI_IRCCONNECTIONSTATISTICS_H_
diff --git a/src/kvirc/kernel/kvi_ircconnectiontarget.cpp b/src/kvirc/kernel/kvi_ircconnectiontarget.cpp
new file mode 100644
index 00000000..1c7e3bbb
--- /dev/null
+++ b/src/kvirc/kernel/kvi_ircconnectiontarget.cpp
@@ -0,0 +1,66 @@
+//=============================================================================
+//
+// File : kvi_ircconnectiontarget.cpp
+// Created on Tue 08 Jun 2004 14:11:59 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_ircconnectiontarget.h"
+#include "kvi_ircserver.h"
+#include "kvi_proxydb.h"
+
+KviIrcConnectionTarget::KviIrcConnectionTarget(const KviIrcNetwork * pNetwork,
+ const KviIrcServer * pServer,
+ const KviProxy * pProxy,
+ const QString &szBindAddress)
+{
+ m_pNetwork = new KviIrcNetwork(*pNetwork);
+ m_pServer = new KviIrcServer(*pServer);
+ m_pProxy = pProxy ? new KviProxy(*pProxy) : 0;
+ m_szBindAddress = szBindAddress;
+}
+
+KviIrcConnectionTarget::~KviIrcConnectionTarget()
+{
+ delete m_pNetwork;
+ delete m_pServer;
+ if(m_pProxy)delete m_pProxy;
+}
+
+const QString & KviIrcConnectionTarget::networkName()
+{
+ return m_pNetwork->name();
+}
+
+void KviIrcConnectionTarget::setNetworkName(const QString &szNetName)
+{
+ m_pNetwork->setName(szNetName);
+}
+
+
+void KviIrcConnectionTarget::clearProxy()
+{
+ if(!m_pProxy)return;
+ delete m_pProxy;
+ m_pProxy = 0;
+}
+
diff --git a/src/kvirc/kernel/kvi_ircconnectiontarget.h b/src/kvirc/kernel/kvi_ircconnectiontarget.h
new file mode 100644
index 00000000..31e179da
--- /dev/null
+++ b/src/kvirc/kernel/kvi_ircconnectiontarget.h
@@ -0,0 +1,69 @@
+#ifndef _KVI_IRCCONNECTIONTARGET_H_
+#define _KVI_IRCCONNECTIONTARGET_H_
+//=============================================================================
+//
+// File : kvi_ircconnectiontarget.h
+// Created on Tue 08 Jun 2004 14:11:59 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_heapobject.h"
+
+class KviIrcNetwork;
+class KviIrcServer;
+class KviProxy;
+
+class KVIRC_API KviIrcConnectionTarget : public KviHeapObject
+{
+ friend class KviIrcConnectionTargetResolver;
+public:
+ // pServer is a shallow pointer: this class makes a copy of it internally, must NOT be null
+ // pProxy may be null if a proxy is not desired. this class makes a copy of it internally
+ KviIrcConnectionTarget(const KviIrcNetwork * pNetwork,
+ const KviIrcServer * pServer,
+ const KviProxy * pProxy = 0,
+ const QString &szBindAddress = QString::null);
+ ~KviIrcConnectionTarget();
+private:
+ KviIrcNetwork * m_pNetwork; // owned, never null
+ KviIrcServer * m_pServer; // owned, never null
+ KviProxy * m_pProxy; // owned, may be null
+ QString m_szBindAddress; // forced bind address
+public:
+ KviIrcServer * server(){ return m_pServer; };
+ KviIrcNetwork * network(){ return m_pNetwork; };
+ KviProxy * proxy(){ return m_pProxy; };
+ const QString & bindAddress(){ return m_szBindAddress; };
+ bool hasBindAddress(){ return (!m_szBindAddress.isEmpty()); };
+ const QString & networkName();
+ // this allows to force the network name: it should be used only by KviConsole
+ // but it's KviServerParser (kvi_sp_numeric.cpp) that first
+ // gets the new network name... thus we make it public
+ // to remove one level of indirection.
+ void setNetworkName(const QString &szNetName);
+protected:
+ // this is for KviIrcConnectionTargetResolver only
+ void clearProxy();
+ void setBindAddress(const QString &szBindAddress){ m_szBindAddress = szBindAddress; };
+};
+
+#endif //!_KVI_IRCCONNECTIONTARGET_H_
diff --git a/src/kvirc/kernel/kvi_ircconnectiontargetresolver.cpp b/src/kvirc/kernel/kvi_ircconnectiontargetresolver.cpp
new file mode 100644
index 00000000..824993bb
--- /dev/null
+++ b/src/kvirc/kernel/kvi_ircconnectiontargetresolver.cpp
@@ -0,0 +1,555 @@
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// File : kvi_ircconnectiontargetresolver.cpp
+// Creation date : Fri May 11 23:24:18 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#define __KVIRC__
+
+#include "kvi_ircconnectiontargetresolver.h"
+#include "kvi_dns.h"
+#include "kvi_locale.h"
+#include "kvi_ircserverdb.h"
+#include "kvi_proxydb.h"
+#include "kvi_error.h"
+#include "kvi_out.h"
+#include "kvi_options.h"
+#include "kvi_ircsocket.h"
+#include "kvi_console.h"
+#include "kvi_netutils.h"
+#include "kvi_internalcmd.h"
+#include "kvi_frame.h"
+#include "kvi_mexlinkfilter.h"
+#include "kvi_garbage.h"
+#include "kvi_malloc.h"
+#include "kvi_memmove.h"
+#include "kvi_debug.h"
+#include "kvi_ircconnection.h"
+#include "kvi_ircconnectiontarget.h"
+#include "kvi_ircsocket.h"
+#include "kvi_error.h"
+
+#define __KVI_DEBUG__
+#include "kvi_debug.h"
+
+#include <qtimer.h>
+
+extern KVIRC_API KviIrcServerDataBase * g_pIrcServerDataBase;
+extern KVIRC_API KviProxyDataBase * g_pProxyDataBase;
+extern KVIRC_API KviGarbageCollector * g_pGarbageCollector;
+
+
+
+KviIrcConnectionTargetResolver::KviIrcConnectionTargetResolver(KviIrcConnection * pConnection)
+: QObject()
+{
+ m_pConnection = pConnection;
+ m_pTarget = 0;
+ m_pConsole = m_pConnection->console();
+
+ m_pStartTimer = 0;
+ m_pProxyDns = 0;
+ m_pServerDns = 0;
+
+ m_eState = Idle;
+ m_eStatus = Success;
+
+ m_iLastError = KviError_success;
+}
+
+KviIrcConnectionTargetResolver::~KviIrcConnectionTargetResolver()
+{
+ cleanup();
+}
+
+void KviIrcConnectionTargetResolver::cleanup()
+{
+ if(m_pProxyDns)
+ {
+ if(m_pProxyDns->isRunning())
+ {
+ // deleting a running dns may block
+ // thus garbage-collect it and delete later
+ g_pGarbageCollector->collect(m_pProxyDns);
+ } else {
+ // can't block : just delete it
+ delete m_pProxyDns;
+ }
+ m_pProxyDns = 0;
+ }
+ if(m_pServerDns)
+ {
+ if(m_pServerDns->isRunning())
+ {
+ // deleting a running dns may block
+ // thus garbage-collect it and delete later
+ g_pGarbageCollector->collect(m_pServerDns);
+ } else {
+ // can't block : just delete it
+ delete m_pServerDns;
+ }
+ m_pServerDns = 0;
+ }
+ if(m_pStartTimer)
+ {
+ delete m_pStartTimer;
+ m_pStartTimer = 0;
+ }
+}
+
+void KviIrcConnectionTargetResolver::start(KviIrcConnectionTarget * t)
+{
+ __ASSERT(m_eState == Idle);
+
+ m_eState = Running;
+
+ if(m_pStartTimer) // this should never happen I guess
+ {
+ delete m_pStartTimer;
+ m_pStartTimer = 0;
+ }
+ m_pStartTimer = new QTimer(this);
+ connect(m_pStartTimer,SIGNAL(timeout()),this,SLOT(asyncStartResolve()));
+
+ m_pTarget = t;
+
+ m_pStartTimer->start(0);
+}
+
+void KviIrcConnectionTargetResolver::abort()
+{
+ cleanup(); // do a cleanup to kill the timers and dns slaves
+
+ if(m_eState == Terminated)return;
+
+ m_pConsole->outputNoFmt(KVI_OUT_SYSTEMERROR,__tr2qs("Hostname resolution aborted"));
+ terminate(Error,KviError_operationAborted);
+}
+
+void KviIrcConnectionTargetResolver::asyncStartResolve()
+{
+ if(m_pStartTimer)
+ {
+ delete m_pStartTimer;
+ m_pStartTimer = 0;
+ }
+
+ m_pConsole->output(KVI_OUT_SYSTEMMESSAGE,
+ __tr2qs("Attempting %Q to %Q (%Q) on port %u"),
+ m_pTarget->server()->useSSL() ? &(__tr2qs("secure connection")) : &(__tr2qs("connection")),
+ &(m_pTarget->server()->m_szHostname),
+ &(m_pTarget->networkName()),
+ m_pTarget->server()->m_uPort);
+
+ if(m_pTarget->proxy())
+ {
+ m_pConsole->output(KVI_OUT_SYSTEMMESSAGE,
+ __tr2qs("Attempting to 'bounce' on proxy %s on port %u (protocol %s)"),
+ m_pTarget->proxy()->m_szHostname.ptr(),
+ m_pTarget->proxy()->m_uPort,
+ m_pTarget->proxy()->protocolName());
+
+ lookupProxyHostname();
+ } else {
+ lookupServerHostname();
+ }
+}
+
+void KviIrcConnectionTargetResolver::lookupProxyHostname()
+{
+ bool bValidIp;
+#ifdef COMPILE_IPV6_SUPPORT
+ if(m_pTarget->proxy()->isIpV6())
+ {
+ bValidIp = kvi_isValidStringIp_V6(m_pTarget->proxy()->m_szIp.ptr());
+ } else {
+#endif
+ bValidIp = kvi_isValidStringIp(m_pTarget->proxy()->m_szIp.ptr());
+#ifdef COMPILE_IPV6_SUPPORT
+ }
+#endif
+
+ if(bValidIp)
+ {
+ if(!_OUTPUT_QUIET)
+ m_pConsole->output(KVI_OUT_SYSTEMMESSAGE,
+ __tr2qs("Using cached proxy IP address (%s)"),
+ m_pTarget->proxy()->m_szIp.ptr());
+ if(m_pTarget->proxy()->protocol() != KviProxy::Http
+ && m_pTarget->proxy()->protocol() != KviProxy::Socks5)
+ lookupServerHostname();
+ else terminate(Success,KviError_success);
+ } else {
+#ifdef COMPILE_IPV6_SUPPORT
+ if(m_pTarget->proxy()->isIpV6())
+ {
+ bValidIp = kvi_isValidStringIp_V6(m_pTarget->proxy()->m_szHostname.ptr());
+ } else {
+#endif
+ bValidIp = kvi_isValidStringIp(m_pTarget->proxy()->m_szHostname.ptr());
+#ifdef COMPILE_IPV6_SUPPORT
+ }
+#endif
+ if(bValidIp)
+ {
+ m_pTarget->proxy()->m_szIp=m_pTarget->proxy()->m_szHostname;
+ if(m_pTarget->proxy()->protocol() != KviProxy::Http &&
+ m_pTarget->proxy()->protocol() != KviProxy::Socks5)
+ {
+ lookupServerHostname();
+ } else {
+ terminate(Success,KviError_success);
+ }
+ } else {
+
+ if(m_pProxyDns)
+ {
+ debug("Something weird is happening, m_pProxyDns is non-zero in lookupProxyHostname()");
+ delete m_pProxyDns;
+ m_pProxyDns = 0;
+ }
+
+ m_pProxyDns = new KviDns();
+ connect(m_pProxyDns,SIGNAL(lookupDone(KviDns *)),this,SLOT(proxyLookupTerminated(KviDns *)));
+
+ if(!m_pProxyDns->lookup(m_pTarget->proxy()->m_szHostname.ptr(),
+ m_pTarget->proxy()->isIpV6() ? KviDns::IpV6 : KviDns::IpV4))
+ {
+ m_pConsole->outputNoFmt(KVI_OUT_SYSTEMWARNING,
+ __tr2qs("Unable to look up the IRC proxy hostname: Can't start the DNS slave"));
+ m_pConsole->outputNoFmt(KVI_OUT_SYSTEMWARNING,
+ __tr2qs("Resuming direct server connection"));
+ // FIXME: #warning "Option for resuming direct connection or not ?"
+ delete m_pProxyDns;
+ m_pProxyDns = 0;
+ m_pTarget->clearProxy();
+ lookupServerHostname();
+ } else {
+ if(!_OUTPUT_MUTE)
+ m_pConsole->output(KVI_OUT_SYSTEMMESSAGE,
+ __tr2qs("Looking up the proxy hostname (%s)..."),
+ m_pTarget->proxy()->m_szHostname.ptr());
+ }
+ }
+ }
+}
+
+void KviIrcConnectionTargetResolver::proxyLookupTerminated(KviDns *)
+{
+ if(m_pProxyDns->state() != KviDns::Success)
+ {
+ QString szErr = KviError::getDescription(m_pProxyDns->error());
+ m_pConsole->output(KVI_OUT_SYSTEMERROR,
+ __tr2qs("Can't find the proxy IP address: %Q"),
+ &szErr);
+ // FIXME: #warning "Option to resume the direct connection if proxy failed ?"
+ m_pConsole->output(KVI_OUT_SYSTEMERROR,
+ __tr2qs("Resuming direct server connection"));
+ m_pTarget->clearProxy();
+ } else {
+ QString szFirstIpAddress = m_pProxyDns->firstIpAddress();
+ if(!_OUTPUT_MUTE)
+ m_pConsole->output(KVI_OUT_SYSTEMMESSAGE,
+ __tr2qs("Proxy hostname resolved to %Q"),&szFirstIpAddress);
+
+ m_pTarget->proxy()->m_szIp = m_pProxyDns->firstIpAddress();
+ g_pProxyDataBase->updateProxyIp(m_pTarget->proxy()->m_szIp.ptr(),szFirstIpAddress);
+
+ if(m_pProxyDns->hostnameCount() > 1)
+ {
+ QString szFirstHostname = m_pProxyDns->firstHostname();
+
+ for(QString * addr = m_pProxyDns->hostnameList()->next();addr;addr = m_pProxyDns->hostnameList()->next())
+ {
+ if(!_OUTPUT_QUIET)
+ m_pConsole->output(KVI_OUT_SYSTEMMESSAGE,
+ __tr2qs("Proxy %Q has a nickname: %Q"),&szFirstHostname,addr);
+ }
+ }
+ }
+
+ delete m_pProxyDns;
+ m_pProxyDns = 0;
+ if(m_pTarget->proxy())
+ {
+ if(m_pTarget->proxy()->protocol() == KviProxy::Http
+ || m_pTarget->proxy()->protocol() == KviProxy::Socks5)
+ {
+ terminate(Success,KviError_success);
+ return;
+ }
+ }
+ lookupServerHostname();
+}
+
+void KviIrcConnectionTargetResolver::lookupServerHostname()
+{
+ bool bValidIp;
+
+#ifdef COMPILE_IPV6_SUPPORT
+ if(m_pTarget->server()->isIpV6())
+ {
+ bValidIp = KviNetUtils::isValidStringIp_V6(m_pTarget->server()->m_szIp);
+ } else {
+#endif
+ bValidIp = KviNetUtils::isValidStringIp(m_pTarget->server()->m_szIp);
+#ifdef COMPILE_IPV6_SUPPORT
+ }
+#endif
+
+ if(bValidIp && m_pTarget->server()->cacheIp())
+ {
+ if(!_OUTPUT_QUIET)
+ m_pConsole->output(KVI_OUT_SYSTEMMESSAGE,
+ __tr2qs("Using cached server IP address (%s)"),
+ m_pTarget->server()->m_szIp.utf8().data());
+ haveServerIp();
+ } else {
+#ifdef COMPILE_IPV6_SUPPORT
+ if(m_pTarget->server()->isIpV6())
+ {
+ bValidIp = KviNetUtils::isValidStringIp_V6(m_pTarget->server()->m_szHostname);
+ } else {
+#endif
+ bValidIp = KviNetUtils::isValidStringIp(m_pTarget->server()->m_szHostname);
+#ifdef COMPILE_IPV6_SUPPORT
+ }
+#endif
+ if(bValidIp)
+ {
+ m_pTarget->server()->m_szIp=m_pTarget->server()->m_szHostname;
+ haveServerIp();
+ } else {
+ if(m_pServerDns)
+ {
+ debug("Something weird is happening, m_pServerDns is non-zero in lookupServerHostname()");
+ delete m_pServerDns;
+ m_pServerDns = 0;
+ }
+ m_pServerDns = new KviDns();
+ connect(m_pServerDns,SIGNAL(lookupDone(KviDns *)),this,
+ SLOT(serverLookupTerminated(KviDns *)));
+ if(!m_pServerDns->lookup(m_pTarget->server()->m_szHostname,
+ m_pTarget->server()->isIpV6() ? KviDns::IpV6 : KviDns::IpV4))
+ {
+ m_pConsole->outputNoFmt(KVI_OUT_SYSTEMERROR,
+ __tr2qs("Unable to look up the server hostname: Can't start the DNS slave"));
+ terminate(Error,KviError_internalError);
+ } else {
+ if(!_OUTPUT_MUTE)
+ m_pConsole->output(KVI_OUT_SYSTEMMESSAGE,
+ __tr2qs("Looking up the server hostname (%s)..."),
+ m_pTarget->server()->m_szHostname.utf8().data());
+ }
+ }
+ }
+}
+
+
+void KviIrcConnectionTargetResolver::serverLookupTerminated(KviDns *)
+{
+ if(m_pServerDns->state() != KviDns::Success)
+ {
+ QString szErr = KviError::getDescription(m_pServerDns->error());
+ m_pConsole->output(KVI_OUT_SYSTEMERROR,
+ __tr2qs("Can't find the server IP address: %Q"),
+ &szErr);
+
+#ifdef COMPILE_IPV6_SUPPORT
+ if(!(m_pTarget->server()->isIpV6()))
+ {
+ m_pConsole->output(KVI_OUT_SYSTEMERROR,
+ __tr2qs("If this server is an IPv6 one, try /server -i %Q"),
+ &(m_pTarget->server()->m_szHostname));
+ }
+#endif
+ terminate(Error,m_pServerDns->error());
+ return;
+ }
+ QString szFirstIpAddress = m_pServerDns->firstIpAddress();
+ if(!_OUTPUT_MUTE)
+ m_pConsole->output(KVI_OUT_SYSTEMMESSAGE,
+ __tr2qs("Server hostname resolved to %Q"),
+ &szFirstIpAddress);
+ g_pIrcServerDataBase->updateServerIp(m_pTarget->server(),szFirstIpAddress);
+
+ QString szFirstHostname = m_pServerDns->firstHostname();
+
+ if(!KviQString::equalCI(m_pTarget->server()->m_szHostname,m_pServerDns->firstHostname()))
+ {
+ if(!_OUTPUT_QUIET)
+ m_pConsole->output(KVI_OUT_SYSTEMMESSAGE,
+ __tr2qs("Real hostname for %Q is %Q"),
+ &(m_pTarget->server()->m_szHostname),
+ &szFirstHostname);
+ m_pTarget->server()->m_szHostname = szFirstHostname;
+ }
+
+ m_pTarget->server()->m_szIp = m_pServerDns->firstIpAddress();
+
+ if(m_pServerDns->hostnameCount() > 1)
+ {
+ for(QString * addr = m_pServerDns->hostnameList()->next();addr;addr = m_pServerDns->hostnameList()->next())
+ {
+ if(!_OUTPUT_QUIET)
+ m_pConsole->output(KVI_OUT_SYSTEMMESSAGE,
+ __tr2qs("Server %Q has a nickname: %Q"),
+ &szFirstHostname,addr);
+ }
+ }
+
+ delete m_pServerDns;
+ m_pServerDns = 0;
+ haveServerIp();
+}
+
+bool KviIrcConnectionTargetResolver::validateLocalAddress(const QString &szAddress,QString &szBuffer)
+{
+ // szAddress may be an ip address or an interface name
+#ifdef COMPILE_IPV6_SUPPORT
+ if(m_pTarget->server()->isIpV6())
+ {
+ if(KviNetUtils::isValidStringIp_V6(szAddress))
+ {
+ szBuffer = szAddress;
+ return true;
+ }
+ } else {
+#endif
+ if(KviNetUtils::isValidStringIp(szAddress))
+ {
+ szBuffer = szAddress;
+ return true;
+ }
+#ifdef COMPILE_IPV6_SUPPORT
+ }
+#endif
+
+ // is it an interface name ?
+ return KviNetUtils::getInterfaceAddress(szAddress,szBuffer);
+}
+
+
+void KviIrcConnectionTargetResolver::haveServerIp()
+{
+ if(KVI_OPTION_BOOL(KviOption_boolUseIdentService) && !KVI_OPTION_BOOL(KviOption_boolUseIdentServiceOnlyOnConnect))
+ m_pConsole->frame()->executeInternalCommand(KVI_INTERNALCOMMAND_IDENT_START);
+
+ QString bindAddress;
+
+ if(m_pTarget->hasBindAddress())
+ {
+ if(!validateLocalAddress(m_pTarget->bindAddress(),bindAddress))
+ {
+ QString szBindAddress = m_pTarget->bindAddress();
+ if((szBindAddress.find('.') != -1) ||
+ (szBindAddress.find(':') != -1))
+ {
+ if(!_OUTPUT_MUTE)
+ m_pConsole->output(KVI_OUT_SYSTEMWARNING,
+ __tr2qs("The specified bind address (%Q) is not valid"),
+ &szBindAddress);
+ } else {
+ if(!_OUTPUT_MUTE)
+ m_pConsole->output(KVI_OUT_SYSTEMWARNING,
+ __tr2qs("The specified bind address (%Q) is not valid (the interface it refers to might be down)"),
+ &(szBindAddress));
+ }
+ }
+ } else {
+ // the options specify a bind address ?
+#ifdef COMPILE_IPV6_SUPPORT
+ if(m_pTarget->server()->isIpV6())
+ {
+ if(KVI_OPTION_BOOL(KviOption_boolBindIrcIpV6ConnectionsToSpecifiedAddress))
+ {
+ if(!KVI_OPTION_STRING(KviOption_stringIpV6ConnectionBindAddress).isEmpty())
+ {
+ if(!validateLocalAddress(KVI_OPTION_STRING(KviOption_stringIpV6ConnectionBindAddress),bindAddress))
+ {
+ // if it is not an interface name , kill it for now and let the user correct the address
+ if(KVI_OPTION_STRING(KviOption_stringIpV6ConnectionBindAddress).find(':') != -1)
+ {
+ if(!_OUTPUT_MUTE)
+ m_pConsole->output(KVI_OUT_SYSTEMWARNING,
+ __tr2qs("The system-wide IPv6 bind address (%s) is not valid"),
+ KVI_OPTION_STRING(KviOption_stringIpV6ConnectionBindAddress).utf8().data());
+ KVI_OPTION_BOOL(KviOption_boolBindIrcIpV6ConnectionsToSpecifiedAddress) = false;
+ } else {
+ // this is an interface address: might be down
+ if(!_OUTPUT_MUTE)
+ m_pConsole->output(KVI_OUT_SYSTEMWARNING,
+ __tr2qs("The system-wide IPv6 bind address (%s) is not valid (the interface it refers to might be down)"),
+ KVI_OPTION_STRING(KviOption_stringIpV6ConnectionBindAddress).utf8().data());
+ }
+ }
+ } else {
+ // empty address....kill it
+ KVI_OPTION_BOOL(KviOption_boolBindIrcIpV6ConnectionsToSpecifiedAddress) = false;
+ }
+ }
+ } else {
+#endif
+ if(KVI_OPTION_BOOL(KviOption_boolBindIrcIpV4ConnectionsToSpecifiedAddress))
+ {
+ if(!KVI_OPTION_STRING(KviOption_stringIpV4ConnectionBindAddress).isEmpty())
+ {
+ if(!validateLocalAddress(KVI_OPTION_STRING(KviOption_stringIpV4ConnectionBindAddress),bindAddress))
+ {
+ // if it is not an interface name , kill it for now and let the user correct the address
+ if(KVI_OPTION_STRING(KviOption_stringIpV4ConnectionBindAddress).find(':') != -1)
+ {
+ if(!_OUTPUT_MUTE)
+ m_pConsole->output(KVI_OUT_SYSTEMWARNING,
+ __tr2qs("The system-wide IPv4 bind address (%s) is not valid"),
+ KVI_OPTION_STRING(KviOption_stringIpV4ConnectionBindAddress).utf8().data());
+ KVI_OPTION_BOOL(KviOption_boolBindIrcIpV4ConnectionsToSpecifiedAddress) = false;
+ } else {
+ // this is an interface address: might be down
+ if(!_OUTPUT_MUTE)
+ m_pConsole->output(KVI_OUT_SYSTEMWARNING,
+ __tr2qs("The system-wide IPv4 bind address (%s) is not valid (the interface it refers to might be down)"),
+ KVI_OPTION_STRING(KviOption_stringIpV4ConnectionBindAddress).utf8().data());
+ }
+ }
+ } else {
+ // empty address....kill it
+ KVI_OPTION_BOOL(KviOption_boolBindIrcIpV4ConnectionsToSpecifiedAddress) = false;
+ }
+ }
+#ifdef COMPILE_IPV6_SUPPORT
+ }
+#endif
+ }
+
+ m_pTarget->setBindAddress(bindAddress);
+ terminate(Success,KviError_success);
+}
+
+void KviIrcConnectionTargetResolver::terminate(Status s,int iLastError)
+{
+ __ASSERT(m_eState != Terminated);
+ cleanup(); // do a cleanup anyway
+ m_eState = Terminated;
+ m_eStatus = s;
+ m_iLastError = iLastError;
+ emit terminated();
+}
diff --git a/src/kvirc/kernel/kvi_ircconnectiontargetresolver.h b/src/kvirc/kernel/kvi_ircconnectiontargetresolver.h
new file mode 100644
index 00000000..947cc711
--- /dev/null
+++ b/src/kvirc/kernel/kvi_ircconnectiontargetresolver.h
@@ -0,0 +1,88 @@
+#ifndef _KVI_IRCCONNECTIONTARGETRESOLVER_H_
+#define _KVI_IRCCONNECTIONTARGETRESOLVER_H_
+//=============================================================================
+//
+// File : kvi_ircconnectiontargetresolver.h
+// Created on Fri 11 May 2004 23:17:42 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include <qobject.h>
+
+class KviConsole;
+class KviDns;
+class KviIrcConnection;
+class KviIrcConnectionTarget;
+
+class QTimer;
+
+class KVIRC_API KviIrcConnectionTargetResolver : public QObject
+{
+ friend class KviIrcLink; // upper protocol in the stack
+ Q_OBJECT
+protected:
+ KviIrcConnectionTargetResolver(KviIrcConnection * pConnection);
+ ~KviIrcConnectionTargetResolver();
+public:
+ enum Status { Success, Error };
+ enum State { Idle, Running, Terminated };
+private:
+ KviIrcConnection * m_pConnection; // shallow, never null
+ KviIrcConnectionTarget * m_pTarget; // shallow, never null
+ KviConsole * m_pConsole; // shallow, never null
+ Status m_eStatus;
+ State m_eState;
+
+ // Auxiliary stuff
+ QTimer * m_pStartTimer; // timer used to start the connection
+ KviDns * m_pProxyDns; // the dns object for the proxy hostnames
+ KviDns * m_pServerDns; // the dns object for the server hostnames
+
+ char * m_pReadBuffer;
+ unsigned int m_uReadBufferLen;
+ unsigned int m_uReadPackets;
+
+ int m_iLastError;
+public:
+ void start(KviIrcConnectionTarget * t);
+ // valid only after the terminated() signal
+ Status status(){ return m_eStatus; };
+ int lastError(){ return m_iLastError; };
+ // causes the resolver to terminate with iLastError == KviError_operationAborted
+ // the terminated() signal is emitted.
+ void abort();
+protected slots:
+ void asyncStartResolve();
+ void serverLookupTerminated(KviDns *);
+ void proxyLookupTerminated(KviDns *);
+private:
+ void cleanup();
+ void lookupProxyHostname();
+ void lookupServerHostname();
+ void haveServerIp();
+ bool validateLocalAddress(const QString &szAddress,QString &szBuffer);
+ void terminate(Status s,int iLastError);
+signals:
+ void terminated();
+};
+
+#endif //!_KVI_IRCCONNECTIONTARGETRESOLVER_H_
diff --git a/src/kvirc/kernel/kvi_ircconnectionuserinfo.cpp b/src/kvirc/kernel/kvi_ircconnectionuserinfo.cpp
new file mode 100644
index 00000000..f4d0ae4c
--- /dev/null
+++ b/src/kvirc/kernel/kvi_ircconnectionuserinfo.cpp
@@ -0,0 +1,65 @@
+//=============================================================================
+//
+// File : kvi_ircconnectionuserinfo.cpp
+// Created on Sun 20 Jun 2004 01:45:42 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_ircconnectionuserinfo.h"
+
+KviIrcConnectionUserInfo::KviIrcConnectionUserInfo()
+{
+ m_bAway = false;
+}
+
+bool KviIrcConnectionUserInfo::hasUserMode(const QChar &m)
+{
+ return m_szUserMode.contains(m) > 0;
+}
+
+bool KviIrcConnectionUserInfo::addUserMode(const QChar &m)
+{
+ if(hasUserMode(m))return false;
+ m_szUserMode.append(m);
+ return true;
+}
+
+bool KviIrcConnectionUserInfo::removeUserMode(const QChar &m)
+{
+ int idx = m_szUserMode.find(m,0);
+ if(idx == -1)return false;
+ m_szUserMode.replace(m,QString(""));
+ return true;
+}
+
+void KviIrcConnectionUserInfo::setAway()
+{
+ m_szNickBeforeAway = m_szNickName;
+ m_tAway = kvi_unixTime();
+ m_bAway = true;
+}
+
+void KviIrcConnectionUserInfo::setBack()
+{
+ m_szNickBeforeAway = "";
+ m_bAway = false;
+}
diff --git a/src/kvirc/kernel/kvi_ircconnectionuserinfo.h b/src/kvirc/kernel/kvi_ircconnectionuserinfo.h
new file mode 100644
index 00000000..fbb66ffd
--- /dev/null
+++ b/src/kvirc/kernel/kvi_ircconnectionuserinfo.h
@@ -0,0 +1,88 @@
+#ifndef _KVI_IRCCONNECTIONUSERINFO_H_
+#define _KVI_IRCCONNECTIONUSERINFO_H_
+//=============================================================================
+//
+// File : kvi_ircconnectionuserinfo.h
+// Created on Sun 20 Jun 2004 01:45:42 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_time.h"
+
+class KVIRC_API KviIrcConnectionUserInfo
+{
+ friend class KviIrcConnection;
+ friend class KviServerParser;
+ friend class KviConsole;
+protected:
+ KviIrcConnectionUserInfo();
+ ~KviIrcConnectionUserInfo(){};
+private:
+ QString m_szRealName; // the actual real name sent from the server
+ QString m_szNickName; // the actual nick name acknowledged by the server
+ QString m_szUserMode; // the actual user mode
+ QString m_szUserName; // user name with ident char
+ QString m_szLocalHostIp; // the local host ip as found by resolveLocalHost() at connection startup
+ QString m_szHostName; // the local host name that the server reports
+ QString m_szHostIp; // the host name above resolved, if possible
+ QString m_szAwayReason;
+ bool m_bAway; // is the user away ?
+ kvi_time_t m_tAway; // time at that the user went away
+ QString m_szNickBeforeAway; // the nickname that the user had just before going away
+ // From bugtrack:
+ // On many IRC networks the host is masked or hashed, and if one also is connected through a LAN,
+ // it is basically impossible to initiate DCC transfers, as 192.168.0.13 or similar will be sent as IP.
+ // But IRC servers usually (at least in my experience) send the unmasked host in the 001 raw event
+ // with something like ":Welcome to the Internet Relay Chat network, nick!ident@host". I think
+ // it'd be a good idea to just grab the IP from that event and use it for DCC transfers by default.
+ QString m_szUnmaskedHostName;
+public:
+ const QString & realName(){ return m_szRealName; };
+ const QString & nickName(){ return m_szNickName; };
+ const QString & userMode(){ return m_szUserMode; };
+ const QString & userName(){ return m_szUserName; };
+ const QString & localHostIp(){ return m_szLocalHostIp; };
+ const QString & hostName(){ return m_szHostName; };
+ const QString & unmaskedHostName(){ return m_szUnmaskedHostName; };
+ const QString & hostIp(){ return m_szHostIp; };
+ const QString & awayReason() { return m_szAwayReason; };
+ bool hasUserMode(const QChar & m);
+ bool isAway(){ return m_bAway; };
+ time_t awayTime(){ return m_tAway; };
+ const QString & nickNameBeforeAway(){ return m_szNickBeforeAway; };
+protected:
+ void setRealName(const QString &szRealName){ m_szRealName = szRealName; };
+ void setNickName(const QString &szNickName){ m_szNickName = szNickName; };
+ void setUserMode(const QString &szUserMode){ m_szUserMode = szUserMode; };
+ void setUserName(const QString &szUserName){ m_szUserName = szUserName; };
+ void setHostName(const QString &szHostName){ m_szHostName = szHostName; };
+ void setUnmaskedHostName(const QString &szHostName){ m_szUnmaskedHostName = szHostName; };
+ void setHostIp(const QString &szHostIp){ m_szHostIp = szHostIp; };
+ void setLocalHostIp(const QString &szLocalHostIp){ m_szLocalHostIp = szLocalHostIp; };
+ bool addUserMode(const QChar &m); // returns false if the mode was already there
+ bool removeUserMode(const QChar &m); // returns fales if the mode was not there
+ void setAwayReason(const QString& szReazon) { m_szAwayReason=szReazon; };
+ void setAway();
+ void setBack();
+};
+
+#endif //!_KVI_IRCCONNECTIONUSERINFO_H_
diff --git a/src/kvirc/kernel/kvi_irccontext.cpp b/src/kvirc/kernel/kvi_irccontext.cpp
new file mode 100644
index 00000000..34257588
--- /dev/null
+++ b/src/kvirc/kernel/kvi_irccontext.cpp
@@ -0,0 +1,906 @@
+//=============================================================================
+//
+// File : kvi_irccontext.cpp
+// Created on Sun 09 May 2004 20:37:46 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_irccontext.h"
+#include "kvi_console.h"
+#include "kvi_channel.h"
+#include "kvi_query.h"
+#include "kvi_frame.h"
+#include "kvi_debug.h"
+#include "kvi_sparser.h"
+#include "kvi_ircconnection.h"
+#include "kvi_ircconnectiontarget.h"
+#include "kvi_asynchronousconnectiondata.h"
+#include "kvi_ircconnectionstatedata.h"
+#include "kvi_ircconnectionuserinfo.h"
+#include "kvi_irctoolbar.h"
+#include "kvi_out.h"
+#include "kvi_ircserverdb.h"
+#include "kvi_proxydb.h"
+#include "kvi_options.h"
+#include "kvi_locale.h"
+#include "kvi_ircdatastreammonitor.h"
+#include "kvi_error.h"
+#include "kvi_thread.h" // for KviThread::msleep()
+#include "kvi_app.h"
+#include "kvi_kvs_eventtriggers.h"
+#include "kvi_kvs_script.h"
+#include "kvi_netutils.h"
+#include "kvi_ircurl.h"
+#include "kvi_qcstring.h"
+#include "kvi_useridentity.h"
+
+#define __KVI_DEBUG__
+#include "kvi_debug.h"
+
+#include <qtimer.h>
+
+// the irc context identifiers start from 1
+static unsigned int g_uNextIrcContextId = 1;
+
+extern KVIRC_API KviIrcServerDataBase * g_pIrcServerDataBase;
+extern KVIRC_API KviProxyDataBase * g_pProxyDataBase;
+
+
+KviIrcContext::KviIrcContext(KviConsole * pConsole)
+: QObject(0)
+{
+ m_uId = g_uNextIrcContextId;
+ g_uNextIrcContextId++;
+
+ m_pConsole = pConsole;
+
+ m_pConnection = 0;
+
+ m_pFrame = m_pConsole->frame();
+
+ m_pDeadChannels = 0;
+ m_pDeadQueries = 0;
+ m_pContextWindows = 0;
+
+ m_pLinksWindow = 0;
+ m_pListWindow = 0;
+
+ m_eState = Idle;
+
+ m_pAsynchronousConnectionData = 0;
+ m_pSavedAsynchronousConnectionData = 0;
+ m_uConnectAttemptCount = 0;
+ m_pMonitorList = 0;
+ m_pReconnectTimer = 0;
+
+ m_uConnectAttemptCount = 1;
+
+ m_iHeartbeatTimerId = startTimer(5000);
+}
+
+KviIrcContext::~KviIrcContext()
+{
+ killTimer(m_iHeartbeatTimerId);
+
+ while(m_pMonitorList)
+ {
+ KviIrcDataStreamMonitor * m = m_pMonitorList->first();
+ if(m)m->die();
+ else {
+ delete m_pMonitorList;
+ m_pMonitorList = 0;
+ }
+ }
+
+ if(m_pReconnectTimer)delete m_pReconnectTimer;
+
+ if(m_pLinksWindow)m_pLinksWindow->die();
+ if(m_pListWindow)m_pListWindow->die();
+
+ closeAllDeadChannels();
+ closeAllDeadQueries();
+ closeAllContextWindows();
+
+ destroyConnection();
+ if(m_pAsynchronousConnectionData)delete m_pAsynchronousConnectionData;
+ if(m_pSavedAsynchronousConnectionData)delete m_pSavedAsynchronousConnectionData;
+}
+
+void KviIrcContext::unhighlightAllWindows()
+{
+ m_pFrame->unhighlightWindowsOfContext(this);
+}
+
+void KviIrcContext::registerDataStreamMonitor(KviIrcDataStreamMonitor * m)
+{
+ if(!m_pMonitorList)
+ {
+ m_pMonitorList = new KviPointerList<KviIrcDataStreamMonitor>;
+ m_pMonitorList->setAutoDelete(false);
+ }
+ m_pMonitorList->append(m);
+}
+
+void KviIrcContext::unregisterDataStreamMonitor(KviIrcDataStreamMonitor *m)
+{
+ if(!m_pMonitorList)return;
+ m_pMonitorList->removeRef(m);
+ if(m_pMonitorList->isEmpty())
+ {
+ delete m_pMonitorList;
+ m_pMonitorList = 0;
+ }
+}
+
+
+void KviIrcContext::closeAllDeadChannels()
+{
+ while(m_pDeadChannels)
+ {
+ KviChannel * c = m_pDeadChannels->first();
+ if(c)m_pFrame->closeWindow(c);
+ else {
+ // ops....
+ delete m_pDeadChannels;
+ m_pDeadChannels = 0;
+ }
+ }
+}
+
+void KviIrcContext::closeAllDeadQueries()
+{
+ while(m_pDeadQueries)
+ {
+ KviQuery * q = m_pDeadQueries->first();
+ if(q)m_pFrame->closeWindow(q);
+ else {
+ // ops....
+ delete m_pDeadQueries;
+ m_pDeadQueries = 0;
+ }
+ }
+}
+
+void KviIrcContext::closeAllContextWindows()
+{
+ while(m_pContextWindows)
+ {
+ KviWindow * w = m_pContextWindows->first();
+ if(w)m_pFrame->closeWindow(w);
+ else {
+ // ops...
+ delete m_pContextWindows;
+ m_pContextWindows = 0;
+ }
+ }
+}
+
+KviChannel * KviIrcContext::findDeadChannel(const QString &name)
+{
+ if(!m_pDeadChannels)return 0;
+ for(KviChannel * c = m_pDeadChannels->first();c;c = m_pDeadChannels->next())
+ {
+ __range_valid(c->isDeadChan());
+ if(KviQString::equalCI(name,c->windowName()))return c;
+ }
+ return 0;
+}
+
+KviQuery * KviIrcContext::findDeadQuery(const QString &name)
+{
+ if(!m_pDeadQueries)return 0;
+ for(KviQuery * c = m_pDeadQueries->first();c;c = m_pDeadQueries->next())
+ {
+ __range_valid(c->isDeadQuery());
+ if(KviQString::equalCI(name,c->windowName()))return c;
+ }
+ return 0;
+}
+
+KviQuery * KviIrcContext::firstDeadQuery()
+{
+ if(!m_pDeadQueries)return 0;
+ return m_pDeadQueries->first();
+}
+
+void KviIrcContext::registerContextWindow(KviWindow * pWnd)
+{
+ if(!m_pContextWindows)
+ {
+ m_pContextWindows = new KviPointerList<KviWindow>;
+ m_pContextWindows->setAutoDelete(false);
+ }
+ m_pContextWindows->append(pWnd);
+}
+
+void KviIrcContext::registerDeadChannel(KviChannel * c)
+{
+ if(!m_pDeadChannels)
+ {
+ m_pDeadChannels = new KviPointerList<KviChannel>;
+ m_pDeadChannels->setAutoDelete(false);
+ }
+ m_pDeadChannels->append(c);
+}
+
+void KviIrcContext::registerDeadQuery(KviQuery * q)
+{
+ if(!m_pDeadQueries)
+ {
+ m_pDeadQueries = new KviPointerList<KviQuery>;
+ m_pDeadQueries->setAutoDelete(false);
+ }
+ m_pDeadQueries->append(q);
+}
+
+bool KviIrcContext::unregisterDeadChannel(KviChannel * c)
+{
+ // was a dead channel ?
+ if(!m_pDeadChannels)return false;
+ if(!m_pDeadChannels->removeRef(c))
+ {
+ return false;
+ }
+ if(m_pDeadChannels->isEmpty())
+ {
+ delete m_pDeadChannels;
+ m_pDeadChannels = 0;
+ }
+ return true;
+}
+
+bool KviIrcContext::unregisterContextWindow(KviWindow * pWnd)
+{
+ if(!m_pContextWindows)return false;
+ if(!m_pContextWindows->removeRef(pWnd))
+ {
+ return false;
+ }
+ if(m_pContextWindows->isEmpty())
+ {
+ delete m_pContextWindows;
+ m_pContextWindows = 0;
+ }
+ return true;
+}
+
+bool KviIrcContext::unregisterDeadQuery(KviQuery * q)
+{
+ if(!m_pDeadQueries)return false;
+ if(!m_pDeadQueries->removeRef(q))
+ {
+ return false;
+ }
+ if(m_pDeadQueries->isEmpty())
+ {
+ delete m_pDeadQueries;
+ m_pDeadQueries = 0;
+ }
+ return true;
+}
+
+void KviIrcContext::createLinksWindow()
+{
+ if(m_pLinksWindow)return;
+ KviKvsScript::run("links.open",m_pConsole);
+}
+
+void KviIrcContext::createListWindow()
+{
+ if(m_pListWindow)return;
+ KviKvsScript::run("list.open",m_pConsole);
+}
+
+void KviIrcContext::destroyConnection()
+{
+ if(!m_pConnection)return;
+ m_pConnection->closeAllChannels();
+ m_pConnection->closeAllQueries();
+
+ if(m_pLinksWindow)m_pLinksWindow->control(EXTERNAL_SERVER_DATA_PARSER_CONTROL_RESET);
+ if(m_pListWindow)m_pListWindow->control(EXTERNAL_SERVER_DATA_PARSER_CONTROL_RESET);
+
+ m_pConsole->connectionDetached();
+
+ // make sure that m_pConnection is already 0 in any
+ // event triggered by KviIrcConnection destructor
+ KviIrcConnection * pTmp = m_pConnection;
+ m_pConnection = 0;
+ delete pTmp;
+}
+
+void KviIrcContext::setState(State eState)
+{
+ if(m_eState == eState)return;
+ m_eState = eState;
+
+ m_pFrame->childContextStateChange(this);
+
+ emit stateChanged();
+
+ if(eState == KviIrcContext::Idle)destroyConnection();
+
+ m_pConsole->updateCaption();
+}
+
+void KviIrcContext::setAsynchronousConnectionData(KviAsynchronousConnectionData * d)
+{
+ if(m_pAsynchronousConnectionData)delete m_pAsynchronousConnectionData;
+ m_pAsynchronousConnectionData = d;
+}
+
+void KviIrcContext::destroyAsynchronousConnectionData()
+{
+ if(!m_pAsynchronousConnectionData)return;
+ delete m_pAsynchronousConnectionData;
+ m_pAsynchronousConnectionData = 0;
+}
+
+void KviIrcContext::loginComplete()
+{
+ setState(Connected);
+}
+
+void KviIrcContext::connectButtonClicked()
+{
+ if(!connection())
+ {
+ if(m_pReconnectTimer)
+ {
+ // reconnection was in progress...
+ delete m_pReconnectTimer;
+ m_pReconnectTimer = 0;
+ destroyAsynchronousConnectionData();
+
+ m_pConsole->outputNoFmt(KVI_OUT_SYSTEMERROR,
+ __tr2qs("Reconnect attempt aborted"));
+
+ return;
+ }
+
+ // No connections in progress
+ m_uConnectAttemptCount = 1;
+ connectToCurrentServer();
+ } else {
+ // Sth is going on
+ terminateConnectionRequest(false);
+ }
+}
+
+void KviIrcContext::connectToCurrentServer()
+{
+ if(m_pReconnectTimer)
+ {
+ delete m_pReconnectTimer;
+ m_pReconnectTimer = 0;
+ }
+
+ m_pConsole->outputNoFmt(KVI_OUT_SYSTEMMESSAGE," "); // spacer
+
+ if(!m_pAsynchronousConnectionData)
+ {
+ // No connection target specified.
+ // If we have a saved target, reuse it
+
+ if(m_pSavedAsynchronousConnectionData)
+ {
+ m_pAsynchronousConnectionData = m_pSavedAsynchronousConnectionData;
+ m_pSavedAsynchronousConnectionData = 0;
+ }
+ }
+
+ if(m_pAsynchronousConnectionData)
+ {
+ // we have a specified connection target (either from outside or saved)
+ if(m_pAsynchronousConnectionData->szServer.isEmpty())
+ {
+ // an empty server might mean "reuse the last server in context"
+ if(m_pAsynchronousConnectionData->bUseLastServerInContext)
+ {
+ if(m_pSavedAsynchronousConnectionData)
+ {
+ // reuse the saved connection data
+ // the server for sure
+ m_pAsynchronousConnectionData->szServer = m_pSavedAsynchronousConnectionData->szServer;
+ m_pAsynchronousConnectionData->uPort = m_pSavedAsynchronousConnectionData->uPort;
+ m_pAsynchronousConnectionData->bPortIsOk = true;
+ m_pAsynchronousConnectionData->bUseIpV6 = m_pSavedAsynchronousConnectionData->bUseIpV6;
+ m_pAsynchronousConnectionData->bUseSSL = m_pSavedAsynchronousConnectionData->bUseSSL;
+ m_pAsynchronousConnectionData->m_pReconnectInfo = m_pSavedAsynchronousConnectionData->m_pReconnectInfo;
+ // and the other info, only if not overridden by the user
+ if(m_pAsynchronousConnectionData->szBindAddress.isEmpty())
+ m_pAsynchronousConnectionData->szBindAddress = m_pSavedAsynchronousConnectionData->szBindAddress;
+ if(m_pAsynchronousConnectionData->szCommandToExecAfterConnect.isEmpty())
+ m_pAsynchronousConnectionData->szCommandToExecAfterConnect = m_pSavedAsynchronousConnectionData->szCommandToExecAfterConnect;
+ if(m_pAsynchronousConnectionData->szLinkFilter.isEmpty())
+ m_pAsynchronousConnectionData->szLinkFilter = m_pSavedAsynchronousConnectionData->szLinkFilter;
+ if(m_pAsynchronousConnectionData->szPass.isEmpty())
+ m_pAsynchronousConnectionData->szPass = m_pSavedAsynchronousConnectionData->szPass;
+ if(m_pAsynchronousConnectionData->szNick.isEmpty())
+ m_pAsynchronousConnectionData->szNick = m_pSavedAsynchronousConnectionData->szNick;
+ if(m_pAsynchronousConnectionData->szInitUMode.isEmpty())
+ m_pAsynchronousConnectionData->szInitUMode = m_pSavedAsynchronousConnectionData->szInitUMode;
+ } else
+ m_pConsole->outputNoFmt(KVI_OUT_SYSTEMWARNING,__tr2qs("This is the first connection in this IRC context: using the global server setting"));
+ } // else it just means "do connect" to the globally selected irc server in the options dialog
+ }
+
+ if(!(m_pAsynchronousConnectionData->szServer.isEmpty()))
+ {
+ // ok , have a server to look for in the db
+ // FIXME: this is a bit ugly... could it be managed in some completly different and nicer way ?
+ KviIrcServerDefinition d;
+ d.szServer = m_pAsynchronousConnectionData->szServer;
+ d.bPortIsValid = m_pAsynchronousConnectionData->bPortIsOk;
+ d.uPort = m_pAsynchronousConnectionData->uPort;
+ d.bIpV6 = m_pAsynchronousConnectionData->bUseIpV6;
+ d.bSSL = m_pAsynchronousConnectionData->bUseSSL;
+ d.szLinkFilter = m_pAsynchronousConnectionData->szLinkFilter;
+ d.szPass = m_pAsynchronousConnectionData->szPass;
+ d.szNick = m_pAsynchronousConnectionData->szNick;
+ d.szInitUMode = m_pAsynchronousConnectionData->szInitUMode;
+ QString szError;
+ if(!g_pIrcServerDataBase->makeCurrentServer(&d,szError))
+ {
+ m_pConsole->outputNoFmt(KVI_OUT_SYSTEMERROR,szError);
+ destroyAsynchronousConnectionData();
+ return;
+ }
+ } // else we just connect to the globally selected irc server in the options dialog
+ }
+
+ KviIrcServerDataBaseRecord * rec = g_pIrcServerDataBase->currentRecord();
+
+ KviIrcNetwork * net;
+ KviIrcServer * srv;
+
+ net = rec ? rec->network() : 0;
+ srv = net ? rec->currentServer() : 0;
+
+ KviProxy * prx = 0;
+
+ if(!srv)
+ {
+ m_pConsole->outputNoFmt(KVI_OUT_SYSTEMERROR,__tr2qs("No servers available. Check the options dialog or use the /SERVER command"));
+ destroyAsynchronousConnectionData();
+ return;
+ }
+
+ if(!net)
+ {
+ // BUG
+ m_pConsole->outputNoFmt(KVI_OUT_SYSTEMERROR,__tr2qs("Ooops.. you've hit a bug in the servers database... I have found a server but not a network..."));
+ destroyAsynchronousConnectionData();
+ return;
+ }
+
+
+ prx = srv->proxyServer(g_pProxyDataBase);
+
+ if(!prx && (srv->proxy()!=-1) && KVI_OPTION_BOOL(KviOption_boolUseProxyHost))
+ {
+ prx = g_pProxyDataBase->currentProxy();
+ if(!prx)
+ {
+ m_pConsole->outputNoFmt(KVI_OUT_SYSTEMWARNING,__tr2qs("No proxy hosts available, resuming direct connection"));
+ }
+ }
+
+ KviStr szBindAddress;
+
+ if(m_pAsynchronousConnectionData)
+ {
+ szBindAddress = m_pAsynchronousConnectionData->szBindAddress;
+ srv->m_pReconnectInfo=m_pAsynchronousConnectionData->m_pReconnectInfo;
+ }
+
+ // Find out the identity we'll be using in this connection
+ // First check the server for one
+
+ const KviUserIdentity * pIdentity = 0;
+
+ QString szUserIdentityId = srv->userIdentityId();
+ if(!szUserIdentityId.isEmpty())
+ pIdentity = KviUserIdentityManager::instance()->findIdentity(szUserIdentityId);
+
+ // If not found, look in the network instead
+ if(!pIdentity)
+ szUserIdentityId = net->userIdentityId();
+
+ if(!szUserIdentityId.isEmpty())
+ pIdentity = KviUserIdentityManager::instance()->findIdentity(szUserIdentityId);
+
+ // If not found, get the default identity (this is GRANTED to be never null, eventually filled up with defaults)
+ pIdentity = KviUserIdentityManager::instance()->defaultIdentity();
+
+
+ if(m_pConnection)delete m_pConnection;
+ m_pConnection = new KviIrcConnection(
+ this,
+ new KviIrcConnectionTarget(
+ net,
+ srv,
+ prx,
+ szBindAddress.ptr()
+ ),
+ new KviUserIdentity(*pIdentity)
+ );
+
+ setState(Connecting);
+
+
+ if(m_pAsynchronousConnectionData)
+ {
+ m_pConnection->stateData()->setCommandToExecAfterConnect(m_pAsynchronousConnectionData->szCommandToExecAfterConnect);
+ destroyAsynchronousConnectionData();
+ }
+
+ m_pConsole->connectionAttached();
+
+ // save stuff for later
+
+ // FIXME: this management of "next" connection should be reviewed a bit anyway
+ if(m_pSavedAsynchronousConnectionData)delete m_pSavedAsynchronousConnectionData;
+ m_pSavedAsynchronousConnectionData = new KviAsynchronousConnectionData();
+ m_pSavedAsynchronousConnectionData->szServer = srv->m_szHostname;
+ m_pSavedAsynchronousConnectionData->uPort = srv->port();
+ m_pSavedAsynchronousConnectionData->bPortIsOk = true;
+ m_pSavedAsynchronousConnectionData->bUseIpV6 = srv->isIpV6();
+ m_pSavedAsynchronousConnectionData->bUseSSL = srv->useSSL();
+ m_pSavedAsynchronousConnectionData->szPass = srv->password();
+ m_pSavedAsynchronousConnectionData->szInitUMode = srv->m_szInitUMode;
+ m_pSavedAsynchronousConnectionData->m_pReconnectInfo=srv->m_pReconnectInfo;
+
+ // this never fails!
+ m_pConnection->start();
+}
+
+void KviIrcContext::connectionFailed(int iError)
+{
+ if(!m_pConnection)return; // this may happen in the destructor!
+
+ m_pConsole->output(KVI_OUT_SYSTEMERROR,
+ __tr2qs("Connection attempt failed [%s]"),
+ m_pConnection->target()->server()->m_szHostname.utf8().data());
+
+ // if the connection has been aborted by the user then just go idle
+ if(iError == KviError_operationAborted)
+ goto enter_idle_state;
+
+ // FIXME: this should stop on critical errors !
+ if(KVI_OPTION_BOOL(KviOption_boolAutoReconnectOnUnexpectedDisconnect))
+ {
+ if((!KVI_OPTION_UINT(KviOption_uintMaxAutoReconnectAttempts) ||
+ (m_uConnectAttemptCount < KVI_OPTION_UINT(KviOption_uintMaxAutoReconnectAttempts))))
+ {
+ m_uConnectAttemptCount++;
+ //FIXME: Multiply the delay by (m_uConnectAttemptCount / 2) so later connects are less frequent.
+ if(!_OUTPUT_MUTE)
+ {
+ QString tmp;
+ KviQString::sprintf(tmp,__tr2qs("Will attempt to reconnect in %d seconds"),KVI_OPTION_UINT(KviOption_uintAutoReconnectDelay));
+ QString num;
+
+ if(!KVI_OPTION_UINT(KviOption_uintMaxAutoReconnectAttempts))
+ KviQString::sprintf(num,__tr2qs("%d"),m_uConnectAttemptCount);
+ else
+ KviQString::sprintf(num,__tr2qs("%d of %d"),
+ m_uConnectAttemptCount,KVI_OPTION_UINT(KviOption_uintMaxAutoReconnectAttempts));
+ tmp += " [" + num + "]";
+ m_pConsole->outputNoFmt(KVI_OUT_SYSTEMMESSAGE,tmp);
+ }
+
+ KviIrcServer oldServer(*(connection()->server()));
+ QString oldNickname = connection()->userInfo()->isAway() ? connection()->userInfo()->nickNameBeforeAway() : connection()->userInfo()->nickName();
+
+ KviAsynchronousConnectionData * d = new KviAsynchronousConnectionData();
+ d->szServer = oldServer.m_szHostname;
+ d->uPort = oldServer.port();
+ d->bPortIsOk = true;
+ d->bUseIpV6 = oldServer.isIpV6();
+ d->bUseSSL = oldServer.useSSL();
+ d->szPass = oldServer.password();
+ d->szNick = oldNickname;
+ d->szInitUMode = oldServer.m_szInitUMode;
+ d->szCommandToExecAfterConnect = "";
+ setAsynchronousConnectionData(d);
+ beginAsynchronousConnect(1000 * KVI_OPTION_UINT(KviOption_uintAutoReconnectDelay));
+
+ setState(Idle); // destroy the actual connection
+
+ return;
+ } else {
+ if(!_OUTPUT_MUTE)
+ m_pConsole->output(KVI_OUT_SYSTEMERROR,__tr2qs("Maximum number of reconnect attempts reached (%d): giving up"),KVI_OPTION_UINT(KviOption_uintMaxAutoReconnectAttempts));
+ }
+ }
+
+ // reset the attempt count
+ m_uConnectAttemptCount = 1;
+
+ if(connection()->server()->cacheIp())
+ {
+ if((((int)iError) == KviError_connectionTimedOut) ||
+ (((int)iError) == KviError_connectionRefused) ||
+ (((int)iError) == KviError_networkUnreachable) ||
+ (((int)iError) == KviError_hostUnreachable))
+ {
+ m_pConsole->output(KVI_OUT_SYSTEMWARNING,__tr2qs("The connection attempt failed while using a cached IP address for the current server"));
+ m_pConsole->output(KVI_OUT_SYSTEMWARNING,__tr2qs("The problem *might* be caused by an updated DNS entry"));
+ m_pConsole->output(KVI_OUT_SYSTEMWARNING,__tr2qs("Try reconnecting with caching disabled"));
+ }
+ }
+
+enter_idle_state:
+ setState(Idle);
+}
+
+void KviIrcContext::connectionEstabilished()
+{
+ //
+ // The connection has been estabilished, the
+ // KviIrcConnection will attempt to login now
+ //
+ m_uConnectAttemptCount = 1;
+
+ bool bStopOutput = false;
+
+ setState(LoggingIn); // this must be set in order for $server and other functions to return the correct values
+
+ bStopOutput = KVS_TRIGGER_EVENT_0_HALTED(KviEvent_OnIrcConnectionEstabilished,m_pConsole);
+
+ if(!bStopOutput)
+ {
+ m_pConsole->output(KVI_OUT_CONNECTION,__tr2qs("%Q established [%s (%s:%u)]"),
+ connection()->socket()->usingSSL() ? &(__tr2qs("Secure connection")) : &(__tr2qs("Connection")),
+ connection()->server()->m_szHostname.utf8().data(),
+ connection()->server()->m_szIp.utf8().data(),
+ connection()->server()->m_uPort);
+ }
+
+ // Add to recent server list (build the url of type irc[6]://<server>:<port>
+ QString url;
+ KviIrcUrl::join(url,connection()->server());
+ g_pApp->addRecentServer(url);
+
+ // save the last server this console used
+ //if(m_pLastIrcServer)delete m_pLastIrcServer;
+ //m_pLastIrcServer = new KviIrcServer(*(connection()->server()));
+}
+
+void KviIrcContext::connectionTerminated()
+{
+ if(!m_pConnection)return; // this may happen in the destructor!
+
+ KviIrcServer oldServer(*(connection()->server()));
+ if(oldServer.m_pReconnectInfo) delete oldServer.m_pReconnectInfo;
+ KviIrcServerReconnectInfo* pInfo = new KviIrcServerReconnectInfo();
+ pInfo->m_szNick = connection()->userInfo()->isAway() ? connection()->userInfo()->nickNameBeforeAway() : connection()->userInfo()->nickName();
+ pInfo->m_bIsAway=connection()->userInfo()->isAway();
+ pInfo->m_szAwayReason=connection()->userInfo()->awayReason();
+
+ // we consider it unexpected when we haven't sent a QUIT message and we're connected
+ // or alternatively when a simulation of such a termination is requested (this is used to keep the queries open etc..)
+ bool bUnexpectedDisconnect = (!(connection()->stateData()->sentQuit())) && (m_eState == KviIrcContext::Connected) ||
+ connection()->stateData()->simulateUnexpectedDisconnect();
+
+ QString szChannels,szProtectedChannels,szPasswords,szCurPass,szCurChan;
+
+ if(bUnexpectedDisconnect)
+ {
+ if(KVI_OPTION_BOOL(KviOption_boolAutoReconnectOnUnexpectedDisconnect))
+ {
+ if(KVI_OPTION_BOOL(KviOption_boolRejoinChannelsAfterReconnect))
+ {
+ // FIXME: THIS SHOULD BE A KviIrcConnection FUNCTION
+ int idx = 0;
+ KviChannel * c;
+ QString szChannels,szProtectedChannels,szPasswords,szCurPass,szCurChan;
+ // first only chans without key, in groups of 4
+ for(c = connection()->channelList()->first();c;c = connection()->channelList()->next())
+ {
+ szCurPass=c->channelKey();
+ szCurChan = c->windowName();
+ if(szCurPass.isEmpty())
+ {
+ if(!szChannels.isEmpty())
+ szChannels.append(",");
+ szChannels.append(szCurChan);
+ } else {
+ if(!szProtectedChannels.isEmpty())
+ szProtectedChannels.append(",");
+ szProtectedChannels.append(szCurChan);
+ if(!szPasswords.isEmpty())
+ szPasswords.append(",");
+ szPasswords.append(szCurPass);
+ }
+ }
+ if( (!szChannels.isEmpty()) || (!szProtectedChannels.isEmpty()) )
+ {
+ pInfo->m_szJoinChannels.append(szProtectedChannels);
+ if(!szProtectedChannels.isEmpty() && !szChannels.isEmpty())
+ pInfo->m_szJoinChannels.append(',');
+ pInfo->m_szJoinChannels.append(szChannels);
+ pInfo->m_szJoinChannels.append(" ");
+ pInfo->m_szJoinChannels.append(szPasswords);
+ }
+ }
+
+
+ if(KVI_OPTION_BOOL(KviOption_boolReopenQueriesAfterReconnect))
+ {
+ for(KviQuery * q = connection()->queryList()->first();q;q = connection()->queryList()->next())
+ {
+ pInfo->m_szOpenQueryes.append(q->target());
+ }
+ }
+ }
+
+ if(KVI_OPTION_BOOL(KviOption_boolKeepChannelsOpenOnUnexpectedDisconnect) || KVI_OPTION_BOOL(KviOption_boolKeepChannelsOpenOnDisconnect))
+ connection()->keepChannelsOpenAfterDisconnect();
+
+ if(KVI_OPTION_BOOL(KviOption_boolKeepQueriesOpenOnUnexpectedDisconnect) || KVI_OPTION_BOOL(KviOption_boolKeepQueriesOpenOnDisconnect))
+ connection()->keepQueriesOpenAfterDisconnect();
+ } else {
+ if(KVI_OPTION_BOOL(KviOption_boolKeepChannelsOpenOnDisconnect))
+ connection()->keepChannelsOpenAfterDisconnect();
+
+ if(KVI_OPTION_BOOL(KviOption_boolKeepQueriesOpenOnDisconnect))
+ connection()->keepQueriesOpenAfterDisconnect();
+ }
+
+ setState(Idle);
+
+ bool bStopOutput = false;
+
+ bStopOutput = KVS_TRIGGER_EVENT_0_HALTED(KviEvent_OnIrcConnectionTerminated,m_pConsole);
+
+ if(!bStopOutput)
+ {
+ m_pConsole->output(KVI_OUT_CONNECTION,__tr2qs("Connection terminated [%s (%s:%u)]"),
+ oldServer.hostName().utf8().data(),
+ oldServer.ip().utf8().data(),
+ oldServer.port());
+ }
+
+ // do reconnect
+
+ if(bUnexpectedDisconnect && KVI_OPTION_BOOL(KviOption_boolAutoReconnectOnUnexpectedDisconnect))
+ {
+ //m_uConnectAttemptCount = 1;
+ if(!_OUTPUT_MUTE)
+ m_pConsole->output(KVI_OUT_CONNECTION,__tr2qs("The connection terminated unexpectedly. Trying to reconnect..."));
+ KviAsynchronousConnectionData * d = new KviAsynchronousConnectionData();
+ d->szServer = oldServer.m_szHostname;
+ d->uPort = oldServer.port();
+ d->bPortIsOk = true;
+ d->bUseIpV6 = oldServer.isIpV6();
+ d->bUseSSL = oldServer.useSSL();
+ d->szPass = oldServer.password();
+ d->szInitUMode = oldServer.m_szInitUMode;
+ d->m_pReconnectInfo = pInfo;
+ setAsynchronousConnectionData(d);
+
+ beginAsynchronousConnect(1000 * KVI_OPTION_UINT(KviOption_uintAutoReconnectDelay));
+ }
+}
+
+void KviIrcContext::beginAsynchronousConnect(unsigned int uDelayInMSecs)
+{
+ if(m_pReconnectTimer)delete m_pReconnectTimer;
+ m_pReconnectTimer = new QTimer(this);
+ connect(m_pReconnectTimer,SIGNAL(timeout()),this,SLOT(asynchronousConnect()));
+ m_pReconnectTimer->start(uDelayInMSecs);
+}
+
+
+void KviIrcContext::asynchronousConnect()
+{
+ if(m_pReconnectTimer)
+ {
+ delete m_pReconnectTimer;
+ m_pReconnectTimer = 0;
+ }
+
+ if(state() != Idle) // need a brutal disconnect here
+ terminateConnectionRequest(true,"Changing server...");
+
+ connectToCurrentServer();
+}
+
+
+void KviIrcContext::terminateConnectionRequest(bool bForce,const QString &szQuitMsg,bool bSimulateUnexpectedDisconnect)
+{
+ if(!connection())return; // hm ?
+
+ if(bSimulateUnexpectedDisconnect)connection()->stateData()->setSimulateUnexpectedDisconnect();
+
+ switch(m_eState)
+ {
+ case Connected:
+ {
+ // was connected : send a quit and abort the connection
+ bool bWasSentQuit = true;
+ if(!connection()->stateData()->sentQuit())
+ {
+ KVS_TRIGGER_EVENT_0(KviEvent_OnDisconnectRequest,m_pConsole);
+ QString szQuit = szQuitMsg;
+ if(szQuit.isEmpty())szQuit = KVI_OPTION_STRING(KviOption_stringQuitMessage);
+ szQuit.replace(";","\\;");
+ szQuit.replace("\n"," ");
+ QString buffer;
+ KviKvsVariant ret;
+ if(KviKvsScript::evaluate(szQuit,console(),0,&ret))
+ ret.asString(buffer);
+ else
+ buffer = szQuit;
+ KviQCString dat = console()->encodeText(buffer);
+ bWasSentQuit = false;
+ connection()->stateData()->setSentQuit();
+ connection()->sendFmtData("QUIT :%s",dat.data() ? dat.data() : ""); // here theoretically we COULD get disconnected
+ } // else it was already sent anyway
+
+ if(KVI_OPTION_BOOL(KviOption_boolForceBrutalQuit) || bWasSentQuit || bForce)
+ {
+ if(!bWasSentQuit)
+ {
+ // idle for some milliseconds in order to allow the quit message to reach
+ // the remote end without breaking the connection
+ KviThread::msleep(100);
+ }
+ // and brutally abort the connection (if it still exists!!!)
+ if(connection())connection()->abort();
+ } else {
+ if(!bWasSentQuit)
+ m_pConsole->outputNoFmt(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Sent QUIT, waiting for the server to close the connection..."));
+ // else it was already sent anyway
+ }
+ }
+ break;
+ case Connecting:
+ case LoggingIn:
+ // was waiting for connection or login, just abort it: it will trigger an error anyway
+ connection()->abort();
+ break;
+ default:
+ // should never end here!
+ __ASSERT(false);
+ break;
+ }
+}
+
+void KviIrcContext::timerEvent(QTimerEvent *e)
+{
+ if(e->timerId() != m_iHeartbeatTimerId)
+ {
+ QObject::timerEvent(e);
+ return;
+ }
+
+ // our heartbeat
+
+ kvi_time_t tNow = kvi_unixTime();
+
+ if(m_pConnection)
+ m_pConnection->heartbeat(tNow);
+}
+
diff --git a/src/kvirc/kernel/kvi_irccontext.h b/src/kvirc/kernel/kvi_irccontext.h
new file mode 100644
index 00000000..07c6ef97
--- /dev/null
+++ b/src/kvirc/kernel/kvi_irccontext.h
@@ -0,0 +1,188 @@
+#ifndef _KVI_IRCCONTEXT_H_
+#define _KVI_IRCCONTEXT_H_
+//=============================================================================
+//
+// File : kvi_irccontext.h
+// Created on Sun 09 May 2004 20:37:46 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_pointerlist.h"
+#include <qobject.h>
+
+class KviChannel;
+class KviQuery;
+class KviQuery;
+class KviFrame;
+class KviIrcConnection;
+class KviExternalServerDataParser;
+class KviAsynchronousConnectionData;
+class KviIrcDataStreamMonitor;
+class KviWindow;
+class QTimer;
+class KviConsole;
+class KviIrcNetwork;
+class KviIrcServer;
+/*
+ KviIrcContext is the structure that groups the objects and resources
+ usable for a single irc connection: a console, a set of channels and queries,
+ and a KviIrcConnection object.
+
+ The objects grouped here are mostly permanent across connections.
+
+ Each irc context has its own unique numeric identifier. The identifiers start
+ from 1 so 0 is an invalid irc context id (this is useful in the scripting engine).
+
+ The irc context is created in the KviConsole constructor and destroyed
+ in the KviConsole destructor. No other class can allocate KviIrcContext objects.
+*/
+
+class KVIRC_API KviIrcContext : public QObject
+{
+ friend class KviConsole;
+ friend class KviChannel;
+ friend class KviQuery;
+ friend class KviIrcConnection;
+ friend class KviIrcContextToolBar;
+ Q_OBJECT
+protected:
+ KviIrcContext(KviConsole * pConsole); // only KviConsole can create this
+public:
+ ~KviIrcContext();
+public:
+ enum State
+ {
+ Idle, // connection() == 0
+ Connecting, // connection() != 0
+ LoggingIn, // connection() != 0
+ Connected // connection() != 0
+ };
+protected:
+ KviConsole * m_pConsole; // shallow, never null
+ KviIrcConnection * m_pConnection;
+
+ unsigned int m_uId; // this irc context id
+
+ State m_eState; // this context state
+
+ // helper pointers
+ KviFrame * m_pFrame; // the owning frame, shallow, never null
+
+ // permanent links and list window
+ KviExternalServerDataParser * m_pLinksWindow;
+ KviExternalServerDataParser * m_pListWindow;
+
+ KviAsynchronousConnectionData * m_pAsynchronousConnectionData; // owned, may be null
+ KviAsynchronousConnectionData * m_pSavedAsynchronousConnectionData; // owned, may be null, this is used to reconnect to the last server in this context
+
+ unsigned int m_uConnectAttemptCount;
+ QTimer * m_pReconnectTimer;
+
+ KviPointerList<KviIrcDataStreamMonitor> * m_pMonitorList; // owned, may be null
+
+ // dead channels and queries
+ KviPointerList<KviChannel> * m_pDeadChannels;
+ KviPointerList<KviQuery> * m_pDeadQueries;
+ // other context bound windows
+ KviPointerList<KviWindow> * m_pContextWindows;
+
+ int m_iHeartbeatTimerId;
+public:
+ unsigned int id(){ return m_uId; };
+ // never null and always the same!
+ KviConsole * console(){ return m_pConsole; };
+ // never null and always the same
+ KviFrame * frame(){ return m_pFrame; };
+ // may be null and may change!
+ KviIrcConnection * connection(){ return m_pConnection; };
+ // state
+ State state(){ return m_eState; };
+ bool isConnected(){ return m_eState == Connected; };
+ bool isLoggingIn(){ return m_eState == LoggingIn; };
+ // dead channels and queries
+ void closeAllDeadChannels();
+ void closeAllDeadQueries();
+ bool unregisterDeadChannel(KviChannel * c);
+ bool unregisterDeadQuery(KviQuery * q);
+ void registerDeadChannel(KviChannel * c);
+ void registerDeadQuery(KviQuery * q);
+ KviChannel * findDeadChannel(const QString &name);
+ KviQuery * findDeadQuery(const QString &nick);
+ KviQuery * firstDeadQuery();
+ // other windows bound to the context
+ void closeAllContextWindows();
+ void registerContextWindow(KviWindow * pWnd);
+ bool unregisterContextWindow(KviWindow * pWnd);
+
+ KviPointerList<KviIrcDataStreamMonitor> * monitorList(){ return m_pMonitorList; };
+
+ // links window
+ void createLinksWindow();
+ void setLinksWindowPointer(KviExternalServerDataParser * l){ m_pLinksWindow = l; };
+ KviExternalServerDataParser * linksWindow(){ return m_pLinksWindow; };
+
+ // list window
+ void createListWindow();
+ void setListWindowPointer(KviExternalServerDataParser * l){ m_pListWindow = l; };
+ KviExternalServerDataParser * listWindow(){ return m_pListWindow; };
+
+ void setAsynchronousConnectionData(KviAsynchronousConnectionData * d);
+ KviAsynchronousConnectionData * asynchronousConnectionData(){ return m_pAsynchronousConnectionData; };
+ void destroyAsynchronousConnectionData();
+ // used by KviConsole (for now) and KviUserParser
+ void connectToCurrentServer();
+
+ void beginAsynchronousConnect(unsigned int uDelayInMSecs);
+
+ void registerDataStreamMonitor(KviIrcDataStreamMonitor * m);
+ void unregisterDataStreamMonitor(KviIrcDataStreamMonitor *m);
+
+ void terminateConnectionRequest(bool bForce,const QString &szQuitMessage = QString::null,bool bSimulateUnexpectedDisconnect = false);
+
+protected:
+ // called by KviIrcContextToolBar: this will DIE in favor of connectOrDisconnect()
+ void connectButtonClicked();
+ // used by KviConsole (for now)
+ void destroyConnection();
+ // for KviConsole (for now) . later will be used only internally
+ void setState(State eState);
+ // called by KviIrcConnection
+ void loginComplete();
+ // our heartbeat timer event
+ virtual void timerEvent(QTimerEvent *e);
+public:
+ void connectOrDisconnect(){ connectButtonClicked(); };
+protected:
+ //
+ // KviIrcConnection interface
+ //
+ void connectionFailed(int iError);
+ void connectionEstabilished();
+ void connectionTerminated();
+signals:
+ void stateChanged();
+protected slots:
+ void asynchronousConnect();
+ void unhighlightAllWindows();
+};
+
+
+#endif //!_KVI_IRCCONTEXT_H_
diff --git a/src/kvirc/kernel/kvi_ircdatastreammonitor.cpp b/src/kvirc/kernel/kvi_ircdatastreammonitor.cpp
new file mode 100644
index 00000000..c4b43fc1
--- /dev/null
+++ b/src/kvirc/kernel/kvi_ircdatastreammonitor.cpp
@@ -0,0 +1,41 @@
+//=============================================================================
+//
+// File : kvi_ircdatastreammonitor.cpp
+// Created on Sun 04 Jul 2004 21:27:22 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_ircdatastreammonitor.h"
+#include "kvi_irccontext.h"
+
+KviIrcDataStreamMonitor::KviIrcDataStreamMonitor(KviIrcContext * pContext)
+: KviHeapObject()
+{
+ m_pMyContext = pContext;
+ m_pMyContext->registerDataStreamMonitor(this);
+}
+
+KviIrcDataStreamMonitor::~KviIrcDataStreamMonitor()
+{
+ m_pMyContext->unregisterDataStreamMonitor(this);
+}
+
diff --git a/src/kvirc/kernel/kvi_ircdatastreammonitor.h b/src/kvirc/kernel/kvi_ircdatastreammonitor.h
new file mode 100644
index 00000000..90a10d22
--- /dev/null
+++ b/src/kvirc/kernel/kvi_ircdatastreammonitor.h
@@ -0,0 +1,50 @@
+#ifndef _KVI_IRCDATASTREAMMONITOR_H_
+#define _KVI_IRCDATASTREAMMONITOR_H_
+//=============================================================================
+//
+// File : kvi_ircdatastreammonitor.h
+// Created on Sun 04 Jul 2004 21:27:22 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_heapobject.h"
+
+class KviIrcContext;
+
+class KVIRC_API KviIrcDataStreamMonitor : public KviHeapObject
+{
+public:
+ KviIrcDataStreamMonitor(KviIrcContext * pContext);
+ virtual ~KviIrcDataStreamMonitor();
+protected:
+ KviIrcContext * m_pMyContext;
+public:
+ // message is null terminated
+ virtual void incomingMessage(const char * message){};
+ // message is NOT null terminated! For proxy connections it might spit out binary data!
+ virtual void outgoingMessage(const char * message,int len){};
+ virtual void connectionInitiated(){};
+ virtual void connectionTerminated(){};
+ virtual void die(){ delete this; };
+};
+
+
+#endif //!_KVI_IRCDATASTREAMMONITOR_H_
diff --git a/src/kvirc/kernel/kvi_irclink.cpp b/src/kvirc/kernel/kvi_irclink.cpp
new file mode 100644
index 00000000..8c79507c
--- /dev/null
+++ b/src/kvirc/kernel/kvi_irclink.cpp
@@ -0,0 +1,406 @@
+//=============================================================================
+//
+// File : kvi_irclink.cpp
+// Created on Mon 03 May 2004 01:45:42 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_irclink.h"
+#include "kvi_dns.h"
+#include "kvi_locale.h"
+#include "kvi_ircserverdb.h"
+#include "kvi_proxydb.h"
+#include "kvi_error.h"
+#include "kvi_out.h"
+#include "kvi_options.h"
+#include "kvi_ircsocket.h"
+#include "kvi_console.h"
+#include "kvi_netutils.h"
+#include "kvi_internalcmd.h"
+#include "kvi_frame.h"
+#include "kvi_mexlinkfilter.h"
+#include "kvi_garbage.h"
+#include "kvi_malloc.h"
+#include "kvi_memmove.h"
+#include "kvi_ircconnection.h"
+#include "kvi_ircconnectiontarget.h"
+#include "kvi_ircconnectiontargetresolver.h"
+#include "kvi_ircsocket.h"
+#include "kvi_databuffer.h"
+
+#define __KVI_DEBUG__
+#include "kvi_debug.h"
+
+#include <qtimer.h>
+
+extern KVIRC_API KviIrcServerDataBase * g_pIrcServerDataBase;
+extern KVIRC_API KviProxyDataBase * g_pProxyDataBase;
+extern KVIRC_API KviGarbageCollector * g_pGarbageCollector;
+
+
+
+KviIrcLink::KviIrcLink(KviIrcConnection * pConnection)
+: QObject()
+{
+ m_pConnection = pConnection;
+ m_pTarget = pConnection->target();
+ m_pConsole = m_pConnection->console();
+ m_pSocket = 0;
+
+ m_pLinkFilter = 0;
+
+ m_pResolver = 0;
+
+ m_pReadBuffer = 0; // incoming data buffer
+ m_uReadBufferLen = 0; // incoming data buffer length
+ m_uReadPackets = 0; // total packets read per session
+
+ m_eState = Idle;
+}
+
+KviIrcLink::~KviIrcLink()
+{
+ if(m_pResolver)delete m_pResolver;
+ destroySocket();
+ if(m_pReadBuffer)kvi_free(m_pReadBuffer);
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// KviIrcSocket management
+//
+
+void KviIrcLink::linkFilterDestroyed()
+{
+ // ops.. the link filter has been destroyed without permission :D
+ // this should NEVER happen (?)
+
+ m_pLinkFilter = 0;
+ m_pConsole->output(KVI_OUT_SYSTEMWARNING,
+ __tr2qs("Ops... for some reason the link filter object has been destroyed"));
+
+}
+
+void KviIrcLink::destroySocket()
+{
+ if(m_pLinkFilter)
+ {
+ QObject::disconnect(m_pLinkFilter,0,this,0);
+ // the module extension server links must be destroyed in the module that provided it
+ m_pLinkFilter->die();
+ m_pLinkFilter = 0;
+ }
+
+ if(m_pSocket)
+ {
+ delete m_pSocket;
+ m_pSocket = 0;
+ }
+}
+
+void KviIrcLink::createSocket(const QString &szLinkFilterName)
+{
+ destroySocket(); // make sure we do not leak memory
+
+ m_pSocket = new KviIrcSocket(this);
+
+ if(szLinkFilterName.isEmpty())return;
+
+ if(KviQString::equalCI(szLinkFilterName,"irc"))return;
+
+ m_pLinkFilter = (KviMexLinkFilter *)g_pModuleExtensionManager->allocateExtension("linkfilter",
+ szLinkFilterName.utf8().data(),m_pConsole,0,this,szLinkFilterName.utf8().data());
+
+ if(m_pLinkFilter)
+ {
+ connect(m_pLinkFilter,SIGNAL(destroyed()),this,SLOT(linkFilterDestroyed()));
+ m_pConsole->output(KVI_OUT_SYSTEMMESSAGE,
+ __tr2qs("Using filtered IRC protocol: Link filter is \"%Q\""),&szLinkFilterName);
+ return;
+ }
+
+ m_pConsole->output(KVI_OUT_SYSTEMWARNING,
+ __tr2qs("Failed to set up the link filter \"%Q\", will try with plain IRC"),&szLinkFilterName);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Connection related operations
+//
+
+void KviIrcLink::abort()
+{
+ if(m_pSocket)
+ {
+ m_pSocket->abort();
+ return;
+ }
+ if(m_pResolver)
+ {
+ m_pResolver->abort();
+ return;
+ }
+}
+
+void KviIrcLink::start()
+{
+ m_eState = Connecting;
+ if(m_pResolver)delete m_pResolver; // this should never happen
+ m_pResolver = new KviIrcConnectionTargetResolver(m_pConnection);
+ connect(m_pResolver,SIGNAL(terminated()),this,SLOT(resolverTerminated()));
+ m_pResolver->start(m_pTarget);
+}
+
+void KviIrcLink::resolverTerminated()
+{
+ if(!m_pResolver)
+ {
+ debug("Oops... resoverTerminated() triggered without a resolver ?");
+ return;
+ }
+
+ if(m_pResolver->status() != KviIrcConnectionTargetResolver::Success)
+ {
+ m_eState = Idle;
+ m_pConnection->linkAttemptFailed(m_pResolver->lastError());
+ return;
+ }
+
+ // resolver terminated succesfully
+ delete m_pResolver;
+ m_pResolver = 0;
+
+ createSocket(m_pTarget->server()->linkFilter());
+
+ int iErr = m_pSocket->startConnection(m_pTarget->server(),m_pTarget->proxy(),
+ m_pTarget->bindAddress().isEmpty() ? 0 : m_pTarget->bindAddress().utf8().data());
+
+ if(iErr != KviError_success)
+ {
+ QString strDescription(KviError::getDescription(iErr));
+ m_pConsole->output(KVI_OUT_SYSTEMERROR,
+ __tr2qs("Failed to start the connection: %Q"),
+ &strDescription);
+// &(KviError::getDescription(iErr)));
+
+ m_eState = Idle;
+ m_pConnection->linkAttemptFailed(iErr);
+ }
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Incoming data processing
+//
+
+void KviIrcLink::processData(char * buffer,int len)
+{
+ if(m_pLinkFilter)
+ {
+ m_pLinkFilter->processData(buffer,len);
+ return;
+ }
+
+ register char *p=buffer;
+ char *beginOfCurData = buffer;
+ int bufLen = 0;
+ char *messageBuffer = (char *)kvi_malloc(1);
+
+ while(*p)
+ {
+ if((*p == '\r' )||(*p == '\n'))
+ {
+ //found a CR or LF...
+ //prepare a message buffer
+ bufLen = p - beginOfCurData;
+ //check for previous unterminated data
+ if(m_uReadBufferLen > 0)
+ {
+ __range_valid(m_pReadBuffer);
+ messageBuffer = (char *)kvi_realloc(messageBuffer,bufLen + m_uReadBufferLen + 1);
+ kvi_memmove(messageBuffer,m_pReadBuffer,m_uReadBufferLen);
+ kvi_memmove((void *)(messageBuffer + m_uReadBufferLen),beginOfCurData,bufLen);
+ *(messageBuffer + bufLen + m_uReadBufferLen) = '\0';
+ m_uReadBufferLen = 0;
+ kvi_free(m_pReadBuffer);
+ m_pReadBuffer = 0;
+ } else {
+ __range_invalid(m_pReadBuffer);
+ messageBuffer = (char *)kvi_realloc(messageBuffer,bufLen + 1);
+ kvi_memmove(messageBuffer,beginOfCurData,bufLen);
+ *(messageBuffer + bufLen) = '\0';
+ }
+ m_uReadPackets++;
+
+ // FIXME: actually it can happen that the socket gets disconnected
+ // in a incomingMessage() call.
+ // The problem might be that some other parts of kvirc assume
+ // that the irc context still exists after a failed write to the socket
+ // (some parts don't even check the return value!)
+ // If the problem presents itself again then the solution is:
+ // disable queue flushing for the "incomingMessage" call
+ // and just call queue_insertMessage()
+ // then after the call terminates flush the queue (eventually detecting
+ // the disconnect and thus destroying the irc context).
+ // For now we try to rely on the remaining parts to handle correctly
+ // such conditions. Let's see...
+ if(strlen(messageBuffer)>0)
+ m_pConnection->incomingMessage(messageBuffer);
+
+ if(m_pSocket->state() != KviIrcSocket::Connected)
+ {
+ // Disconnected in KviConsole::incomingMessage() call.
+ // This may happen for several reasons (local event loop
+ // with the user hitting the disconnect button, a scripting
+ // handler event that disconnects explicitly)
+ //
+ // We handle it by simply returning control to readData() which
+ // will return immediately (and safely) control to Qt
+ kvi_free(messageBuffer);
+ return;
+ }
+
+ while(*p && ((*p=='\r')||(*p=='\n')) )p++;
+ beginOfCurData = p;
+
+ } else p++;
+ }
+
+ //now *p == '\0'
+ //beginOfCurData points to '\0' if we have
+ //no more stuff to parse , or points to something
+ //different than '\r' or '\n'...
+ if(*beginOfCurData)
+ {
+ //Have remaining data...in the local buffer
+ bufLen = p - beginOfCurData;
+ if(m_uReadBufferLen > 0)
+ {
+ //and there was more stuff saved... (really slow connection)
+ __range_valid(m_pReadBuffer);
+ m_pReadBuffer =(char *)kvi_realloc(m_pReadBuffer,m_uReadBufferLen + bufLen);
+ kvi_memmove((void *)(m_pReadBuffer+m_uReadBufferLen),beginOfCurData,bufLen);
+ m_uReadBufferLen += bufLen;
+ } else {
+ //
+ __range_invalid(m_pReadBuffer);
+ m_uReadBufferLen = bufLen;
+ m_pReadBuffer =(char *)kvi_malloc(m_uReadBufferLen);
+ kvi_memmove(m_pReadBuffer,beginOfCurData,m_uReadBufferLen);
+ }
+ //The m_pReadBuffer contains at max 1 irc message...
+ //that can not be longer than 510 bytes (the message is not CRLF terminated)
+ // FIXME: Is this limit *really* valid on all servers ?
+ if(m_uReadBufferLen > 510)debug("WARNING : Receiving an invalid irc message from server.");
+ }
+ kvi_free(messageBuffer);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Outgoing data processing
+//
+
+bool KviIrcLink::sendPacket(KviDataBuffer * pData)
+{
+ if(!m_pSocket)
+ {
+ delete pData;
+ pData = 0;
+ return false;
+ }
+
+ // if we have a filter, let it do its job
+ if(m_pLinkFilter)
+ return m_pLinkFilter->sendPacket(pData);
+
+ return m_pSocket->sendPacket(pData);
+}
+
+void KviIrcLink::socketStateChange()
+{
+ switch(m_pSocket->state())
+ {
+ case KviIrcSocket::Connected:
+ m_eState = Connected;
+ m_pConnection->linkEstabilished();
+ break;
+ case KviIrcSocket::Idle:
+ {
+ State old = m_eState;
+ m_eState = Idle;
+ switch(old)
+ {
+ case Connecting:
+ m_pConnection->linkAttemptFailed(m_pSocket->lastError());
+ break;
+ case Connected:
+ m_pConnection->linkTerminated();
+ break;
+ default: // currently can be only Idle
+ debug("Ooops... got a KviIrcSocket::Idle state change when KviIrcLink::m_eState was Idle");
+ break;
+ }
+ }
+ break;
+ case KviIrcSocket::Connecting:
+ m_pConsole->output(KVI_OUT_CONNECTION,__tr2qs("Contacting %Q %s (%s) on port %u"),
+ connection()->proxy() ? &(__tr2qs("proxy host")) : &(__tr2qs("IRC server")),
+ connection()->proxy() ? connection()->proxy()->m_szHostname.ptr() : connection()->server()->m_szHostname.utf8().data(),
+ connection()->proxy() ? connection()->proxy()->m_szIp.ptr() : connection()->server()->m_szIp.utf8().data(),
+ connection()->proxy() ? connection()->proxy()->m_uPort : connection()->server()->m_uPort);
+ break;
+ case KviIrcSocket::SSLHandshake:
+ m_pConsole->output(KVI_OUT_CONNECTION,__tr2qs("Low-level transport connection established [%s (%s:%u)]"),
+ connection()->proxy() ? connection()->proxy()->m_szHostname.ptr() : connection()->server()->m_szHostname.utf8().data(),
+ connection()->proxy() ? connection()->proxy()->m_szIp.ptr() : connection()->server()->m_szIp.utf8().data(),
+ connection()->proxy() ? connection()->proxy()->m_uPort : connection()->server()->m_uPort);
+ m_pConsole->outputNoFmt(KVI_OUT_CONNECTION,__tr2qs("Starting Secure Socket Layer handshake"));
+ break;
+ case KviIrcSocket::ProxyLogin:
+ m_pConsole->output(KVI_OUT_CONNECTION,__tr2qs("%Q established [%s (%s:%u)]"),
+ connection()->socket()->usingSSL() ? &(__tr2qs("Secure proxy connection")) : &(__tr2qs("Proxy connection")),
+ connection()->proxy()->m_szHostname.ptr(),
+ connection()->proxy()->m_szIp.ptr(),
+ connection()->proxy()->m_uPort);
+ m_pConsole->outputNoFmt(KVI_OUT_CONNECTION,__tr2qs("Negotiating relay information"));
+ break;
+ case KviIrcSocket::ProxyFinalV4:
+ m_pConsole->outputNoFmt(KVI_OUT_CONNECTION,__tr2qs("Sent connection request, waiting for acknowledgement"));
+ break;
+ case KviIrcSocket::ProxyFinalV5:
+ m_pConsole->outputNoFmt(KVI_OUT_CONNECTION,__tr2qs("Sent target host data, waiting for acknowledgement"));
+ break;
+ case KviIrcSocket::ProxySelectAuthMethodV5:
+ m_pConsole->outputNoFmt(KVI_OUT_CONNECTION,__tr2qs("Sent auth method request, waiting for acknowledgement"));
+ break;
+ case KviIrcSocket::ProxyUserPassV5:
+ m_pConsole->outputNoFmt(KVI_OUT_CONNECTION,__tr2qs("Sent username and password, waiting for acknowledgement"));
+ break;
+ case KviIrcSocket::ProxyFinalHttp:
+ m_pConsole->outputNoFmt(KVI_OUT_CONNECTION,__tr2qs("Sent connection request, waiting for \"HTTP 200\" acknowledgement"));
+ break;
+ }
+}
+
diff --git a/src/kvirc/kernel/kvi_irclink.h b/src/kvirc/kernel/kvi_irclink.h
new file mode 100644
index 00000000..bb220ecf
--- /dev/null
+++ b/src/kvirc/kernel/kvi_irclink.h
@@ -0,0 +1,122 @@
+#ifndef _KVI_IRCLINK_H_
+#define _KVI_IRCLINK_H_
+//=============================================================================
+//
+// File : kvi_irclink.h
+// Created on Mon 03 May 2004 01:45:42 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include <qobject.h>
+
+class KviConsole;
+class KviIrcServer;
+class KviProxy;
+class KviIrcSocket;
+class KviDns;
+class KviIrcConnection;
+class KviIrcConnectionTarget;
+class KviIrcConnectionTargetResolver;
+class KviDataBuffer;
+class KviMexLinkFilter;
+
+
+class KVIRC_API KviIrcLink : public QObject
+{
+ friend class KviIrcConnection; // upper protocol in the stack
+ friend class KviIrcSocket; // lower protocol in the stack
+ Q_OBJECT
+public:
+ enum State { Idle, Connecting, Connected };
+protected:
+ // only KviConsole can create this
+ // pConsole must NOT be null
+ // pServer is a shallow pointer: Connection makes a copy of it internally, must NOT be null
+ // pProxy may be null if a proxy is not desicred. Connection makes a copy of it internally
+ KviIrcLink(KviIrcConnection * pConnection);
+ ~KviIrcLink();
+private:
+ KviIrcConnection * m_pConnection; // shallow, never null
+ KviIrcConnectionTarget * m_pTarget; // shallow, never null
+ KviConsole * m_pConsole; // shallow, never null
+ KviIrcSocket * m_pSocket; // owned, may be null!
+ KviMexLinkFilter * m_pLinkFilter; // owned, may be null!
+
+ State m_eState;
+
+ char * m_pReadBuffer;
+ unsigned int m_uReadBufferLen;
+ unsigned int m_uReadPackets;
+
+ KviIrcConnectionTargetResolver * m_pResolver; // owned
+public:
+ // da socket(): may be null!
+ KviIrcSocket * socket(){ return m_pSocket; };
+ // da connection: never null
+ KviIrcConnection * connection(){ return m_pConnection; };
+ // da console: never null
+ KviConsole * console(){ return m_pConsole; };
+ State state(){ return m_eState; };
+protected:
+ //
+ // interface for KviIrcConnection (up)
+ //
+
+ // This is used by KviIrcConnection::send*()
+ // This should be used to intercept the outgoing packets
+ // when implementing a new protocol
+ virtual bool sendPacket(KviDataBuffer * pData);
+ // this aborts any connection or attempt
+ void abort();
+protected:
+ //
+ // local overridables (called internally)
+ //
+
+ // This is the function used to start a connection attempt.
+ // It starts the server or proxy DNS lookup
+ // The function MUST be asynchronous: it must return succesfully
+ // and report any error by using m_pConnection->linkAttemptFailed()
+ void start();
+protected:
+ //
+ // interface for KviIrcSocket (down)
+ //
+
+ // This is called by KviIrcSocket to process a packet
+ // of raw data from the server. The buffer is iLength+1
+ // bytes long and contains a null terminator
+ void processData(char * buffer,int iLength);
+ // this is called at each state change
+ void socketStateChange();
+protected slots:
+ void linkFilterDestroyed();
+private:
+ void destroySocket();
+ void createSocket(const QString &szLinkFilterName);
+signals:
+ void connectionFailed(); // the connection attempt has failed
+private slots:
+ void resolverTerminated();
+};
+
+#endif //!_KVI_IRCLINK_H_
diff --git a/src/kvirc/kernel/kvi_ircsocket.cpp b/src/kvirc/kernel/kvi_ircsocket.cpp
new file mode 100644
index 00000000..45df5617
--- /dev/null
+++ b/src/kvirc/kernel/kvi_ircsocket.cpp
@@ -0,0 +1,1910 @@
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// File : kvi_ircsocket.cpp
+// Creation date : Tue Jul 30 19:25:18 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#define __KVIRC__
+
+#include "kvi_ircsocket.h"
+#include "kvi_ircserver.h"
+#include "kvi_proxydb.h"
+#include "kvi_netutils.h"
+#include "kvi_settings.h"
+#include "kvi_error.h"
+#include "kvi_locale.h"
+#include "kvi_malloc.h"
+#include "kvi_debug.h"
+#include "kvi_string.h"
+#include "kvi_options.h"
+#include "kvi_memmove.h"
+#include "kvi_socket.h"
+#include "kvi_console.h"
+#include "kvi_out.h"
+#include "kvi_irclink.h"
+#include "kvi_ircconnection.h"
+#include "kvi_databuffer.h"
+
+#ifdef COMPILE_SSL_SUPPORT
+ #include "kvi_sslmaster.h"
+#endif
+
+#include <qtimer.h>
+#include <qsocketnotifier.h>
+
+#ifndef COMPILE_ON_WINDOWS
+ #include <unistd.h> //for gettimeofday()
+#endif
+//#include <fcntl.h>
+//#include <errno.h>
+
+// FIXME: #warning "Lag-o-meter"
+
+unsigned int g_uNextIrcLinkId = 1;
+
+
+
+KviIrcSocket::KviIrcSocket(KviIrcLink * pLink)
+: QObject()
+{
+ m_uId = g_uNextIrcLinkId;
+ g_uNextIrcLinkId++;
+
+ m_pLink = pLink;
+ m_pConsole = m_pLink->console();
+
+ m_state = Idle; // current socket state
+
+ m_pRsn = 0; // read socket notifier
+ m_pWsn = 0; // write socket notifier
+ m_sock = KVI_INVALID_SOCKET; // socket
+
+ m_pIrcServer = 0; // current server data
+ m_pProxy = 0; // current proxy data
+
+ m_pTimeoutTimer = 0; // timeout for connect()
+
+ m_uReadBytes = 0; // total read bytes per session
+ m_uSentBytes = 0; // total sent bytes per session
+ m_uSentPackets = 0; // total packets sent per session
+
+ m_pSendQueueHead = 0; // data queue
+ m_pSendQueueTail = 0; //
+
+ m_iLastError = KviError_success;
+
+#ifdef COMPILE_SSL_SUPPORT
+ m_pSSL = 0;
+#endif
+
+ m_tAntiFloodLastMessageTime.tv_sec = 0;
+ m_tAntiFloodLastMessageTime.tv_usec = 0;
+
+ if(KVI_OPTION_UINT(KviOption_uintSocketQueueFlushTimeout) < 100)
+ KVI_OPTION_UINT(KviOption_uintSocketQueueFlushTimeout) = 100; // this is our minimum , we don't want to lag the app
+
+ m_bInProcessData = false;
+
+ m_pFlushTimer = new QTimer(); // queue flush timer
+ connect(m_pFlushTimer,SIGNAL(timeout()),this,SLOT(flushSendQueue()));
+}
+
+KviIrcSocket::~KviIrcSocket()
+{
+ reset();
+ delete m_pFlushTimer;
+}
+
+
+void KviIrcSocket::reset()
+{
+#ifdef COMPILE_SSL_SUPPORT
+ if(m_pSSL)
+ {
+ KviSSLMaster::freeSSL(m_pSSL);
+ m_pSSL = 0;
+ }
+#endif
+ if(m_pIrcServer)
+ {
+ delete m_pIrcServer;
+ m_pIrcServer = 0;
+ }
+ if(m_pProxy)
+ {
+ delete m_pProxy;
+ m_pProxy = 0;
+ }
+ if(m_pRsn)
+ {
+ delete m_pRsn;
+ m_pRsn = 0;
+ }
+ if(m_pWsn)
+ {
+ delete m_pWsn;
+ m_pWsn = 0;
+ }
+ if(kvi_socket_isValid(m_sock))
+ {
+ kvi_socket_destroy(m_sock);
+ m_sock = KVI_INVALID_SOCKET;
+ }
+ if(m_pTimeoutTimer)
+ {
+ m_pTimeoutTimer->stop();
+ delete m_pTimeoutTimer;
+ m_pTimeoutTimer = 0;
+ }
+
+ m_bInProcessData = false;
+
+ m_uReadBytes = 0;
+ m_uSentBytes = 0;
+ m_uSentPackets = 0;
+ m_tAntiFloodLastMessageTime.tv_sec = 0;
+ m_tAntiFloodLastMessageTime.tv_usec = 0;
+
+ m_bInProcessData = false;
+
+ if(m_pFlushTimer->isActive())m_pFlushTimer->stop();
+ queue_removeAllMessages();
+
+ setState(Idle);
+}
+
+void KviIrcSocket::outputSSLMessage(const QString &szMsg)
+{
+ m_pConsole->output(KVI_OUT_SSL,__tr2qs("[SSL]: %Q"),&szMsg);
+}
+
+void KviIrcSocket::outputSSLError(const QString &szMsg)
+{
+ m_pConsole->output(KVI_OUT_SSL,__tr2qs("[SSL ERROR]: %Q"),&szMsg);
+}
+
+void KviIrcSocket::outputProxyMessage(const QString &szMsg)
+{
+ QStringList list=QStringList::split("\n",szMsg);
+ for(QStringList::Iterator it = list.begin(); it != list.end(); ++it)
+ {
+ QString szTemporary = (*it).stripWhiteSpace();
+ m_pConsole->output(KVI_OUT_SOCKETMESSAGE,__tr2qs("[PROXY]: %Q"),&(szTemporary));
+ }
+}
+
+void KviIrcSocket::outputProxyError(const QString &szMsg)
+{
+ QStringList list=QStringList::split("\n",szMsg);
+ for(QStringList::Iterator it = list.begin(); it != list.end(); ++it)
+ {
+ QString szTemporary = (*it).stripWhiteSpace();
+ m_pConsole->output(KVI_OUT_SOCKETERROR,__tr2qs("[PROXY ERROR]: %Q"),&(szTemporary));
+ }
+
+}
+
+void KviIrcSocket::outputSocketMessage(const QString &szMsg)
+{
+ m_pConsole->output(KVI_OUT_SOCKETMESSAGE,__tr2qs("[SOCKET]: %Q"),&szMsg);
+}
+
+void KviIrcSocket::outputSocketError(const QString &szMsg)
+{
+ m_pConsole->output(KVI_OUT_SOCKETERROR,__tr2qs("[SOCKET ERROR]: %Q"),&szMsg);
+}
+
+
+void KviIrcSocket::outputSocketWarning(const QString &szMsg)
+{
+ m_pConsole->output(KVI_OUT_SOCKETWARNING,__tr2qs("[SOCKET WARNING]: %Q"),&szMsg);
+}
+
+void KviIrcSocket::setState(SocketState st)
+{
+ if(st != m_state)
+ {
+ m_state = st;
+ m_pLink->socketStateChange();
+ }
+}
+
+void KviIrcSocket::raiseError(int iError)
+{
+ m_iLastError = iError;
+ //m_pConsole->socketError(iError);
+ if( (m_iLastError==KviError_remoteEndClosedConnection) && ( m_state == ProxyHttpError) )
+ outputSocketMessage(KviError::getDescription(iError));
+ else
+ outputSocketError(KviError::getDescription(iError));
+}
+
+int KviIrcSocket::startConnection(KviIrcServer *srv,KviProxy * prx,const char * bindAddress)
+{
+ // Attempts to estabilish an IRC connection
+ // to the server specified by *srv.
+ // Uses the proxy *prx if not 0
+ if(m_state != Idle)return KviError_anotherConnectionInProgress;
+
+ // Coherent state, thnx.
+ reset();
+
+ if(srv->useSSL())
+ {
+#ifndef COMPILE_SSL_SUPPORT
+ return KviError_noSSLSupport;
+#endif //!COMPILE_SSL_SUPPORT
+ }
+
+ // Copy the server
+ m_pIrcServer = new KviIrcServer(*srv);
+
+ bool bTargetIpV6 = false;
+ bool bNeedServerIp = !prx;
+ if(prx) bNeedServerIp = (
+ prx->protocol() != KviProxy::Http && prx->protocol() != KviProxy::Socks5
+ );
+
+ // We're going to check the addresses now
+
+ // check the proxy stuff...
+ if(prx)
+ {
+ // Yeah...here comes the proxy
+ m_pProxy = new KviProxy(*prx);
+ // check the proxy IP address
+ if(m_pProxy->isIpV6())
+ {
+ // IpV6 proxy :) (STILL QUITE UNTESTED ?)
+#ifdef COMPILE_IPV6_SUPPORT
+ bTargetIpV6 = true;
+ if(!kvi_isValidStringIp_V6(m_pProxy->ip()))return KviError_invalidProxyAddress;
+ // SOCKSV4 does not support IPV6 addresses
+ if(m_pProxy->protocol() == KviProxy::Socks4)return KviError_socksV4LacksIpV6Support;
+#else
+ return KviError_noIpV6Support;
+#endif
+ } else {
+ // IpV4 proxy
+ if(!kvi_isValidStringIp(m_pProxy->ip()))return KviError_invalidProxyAddress;
+ }
+ }
+
+ if(bNeedServerIp)
+ {
+ // check the irc host ip
+#ifdef COMPILE_IPV6_SUPPORT
+ if(m_pIrcServer->isIpV6())
+ {
+ // We have an IpV6 server host (Interesting if proxy is IpV4)
+ if( !KviNetUtils::isValidStringIp_V6(m_pIrcServer->ip()) )return KviError_invalidIpAddress;
+ if(!m_pProxy)bTargetIpV6 = true; // otherwise the proxy rules
+ } else {
+#endif
+ // We have an IpV4 server host
+ if(!KviNetUtils::isValidStringIp(m_pIrcServer->ip())) return KviError_invalidIpAddress;
+#ifdef COMPILE_IPV6_SUPPORT
+ }
+#endif
+ }
+
+ KviSockaddr sa(prx ? m_pProxy->ip() : m_pIrcServer->ip().utf8().data(),prx ? m_pProxy->port() : m_pIrcServer->port(),bTargetIpV6);
+
+ if(!sa.socketAddress())return KviError_invalidIpAddress;
+
+ // create the socket
+#ifdef COMPILE_IPV6_SUPPORT
+ m_sock = kvi_socket_create(bTargetIpV6 ? KVI_SOCKET_PF_INET6 : KVI_SOCKET_PF_INET,KVI_SOCKET_TYPE_STREAM,KVI_SOCKET_PROTO_TCP);
+#else
+ m_sock = kvi_socket_create(KVI_SOCKET_PF_INET,KVI_SOCKET_TYPE_STREAM,KVI_SOCKET_PROTO_TCP);
+#endif
+
+ if(m_sock < 0)return KviError_socketCreationFailed;
+
+ if(bindAddress)
+ {
+ // we have to bind the socket to a local address
+ KviSockaddr localSa(bindAddress,0,bTargetIpV6);
+ bool bBindOk = localSa.socketAddress();
+
+ if(bBindOk)
+ {
+ bBindOk = kvi_socket_bind(m_sock,localSa.socketAddress(),((int)(localSa.addressLength())));
+ }
+
+ QString tmp;
+ if(bBindOk)
+ {
+ if(_OUTPUT_VERBOSE)
+ KviQString::sprintf(tmp,__tr2qs("Binding to local address %s"),bindAddress);
+ outputSocketMessage(tmp);
+ } else {
+ if(_OUTPUT_VERBOSE)
+ KviQString::sprintf(tmp,__tr2qs("Binding to local address %s failed: the kernel will choose the correct interface"),bindAddress);
+ outputSocketWarning(tmp);
+ }
+ }
+
+ // make it non blocking
+ if(!kvi_socket_setNonBlocking(m_sock))
+ {
+ reset();
+ return KviError_asyncSocketFailed;
+ }
+
+ if(!kvi_socket_connect(m_sock,sa.socketAddress(),((int)(sa.addressLength()))))
+ {
+ // ops...
+ int err = kvi_socket_error();
+
+ if(!kvi_socket_recoverableConnectError(err))
+ {
+ // Ops...
+ int sockError=err;
+ if(sockError==0)
+ {
+ // Zero error ?...let's look closer
+ int iSize=sizeof(int);
+ if(!kvi_socket_getsockopt(m_sock,SOL_SOCKET,SO_ERROR,(void *)&sockError,&iSize))sockError=0;
+ }
+ // die :(
+ reset();
+ // And declare problems :)
+ if(sockError)return KviError::translateSystemError(sockError);
+ else return KviError_unknownError; //Error 0 ?
+ }
+ }
+
+ // and setup the WRITE notifier...
+ m_pWsn = new QSocketNotifier((int)m_sock,QSocketNotifier::Write);
+ QObject::connect(m_pWsn,SIGNAL(activated(int)),this,SLOT(writeNotifierFired(int)));
+ m_pWsn->setEnabled(true);
+
+ // set the timer
+ if(KVI_OPTION_UINT(KviOption_uintIrcSocketTimeout) < 5)KVI_OPTION_UINT(KviOption_uintIrcSocketTimeout) = 5;
+ m_pTimeoutTimer = new QTimer();
+ QObject::connect(m_pTimeoutTimer,SIGNAL(timeout()),this,SLOT(connectionTimedOut()));
+ m_pTimeoutTimer->start(KVI_OPTION_UINT(KviOption_uintIrcSocketTimeout) * 1000,true);
+
+ // and wait for connect
+ setState(Connecting);
+
+ return KviError_success;
+}
+
+void KviIrcSocket::connectionTimedOut()
+{
+ // the m_pTimeoutTimer fired :(
+ raiseError(KviError_connectionTimedOut);
+ reset();
+}
+
+void KviIrcSocket::writeNotifierFired(int)
+{
+ // kill the timeout timer
+ if(m_pTimeoutTimer)
+ {
+ delete m_pTimeoutTimer;
+ m_pTimeoutTimer = 0;
+ }
+
+ // Check for errors...
+ int sockError;
+ int iSize=sizeof(int);
+ if(!kvi_socket_getsockopt(m_sock,SOL_SOCKET,SO_ERROR,(void *)&sockError,&iSize))sockError = -1;
+ //sockError = 0;
+ if(sockError != 0)
+ {
+ //failed
+ if(sockError > 0)sockError = KviError::translateSystemError(sockError);
+ else sockError = KviError_unknownError; //Error 0 ?
+ raiseError(sockError);
+ reset();
+ return;
+ }
+
+ // kill the write notifier
+ delete m_pWsn;
+ m_pWsn = 0;
+
+ //Succesfully connected...
+ connectionEstabilished();
+}
+
+void KviIrcSocket::connectionEstabilished()
+{
+ // the connection with a remote end has been estabilished
+ // if it is a proxy we need to perform the login operations
+ // otherwise we're connected to the irc server
+ if(m_sock == KVI_INVALID_SOCKET)return; // ops...disconnected in setState() ????
+
+ if(m_pProxy)connectedToProxy();
+ else connectedToIrcServer();
+}
+
+void KviIrcSocket::connectedToProxy()
+{
+ if(!m_pProxy)debug("WARNING: connectedToProxy() without a m_pProxy!");
+
+ // FIXME: Do we want to support SSL proxies ?
+ // it would be just a matter of SSL handshaking
+ // with the proxy
+
+ setState(ProxyLogin);
+
+ if(m_pRsn)
+ {
+ delete m_pRsn;
+ m_pRsn = 0;
+ }
+
+ m_pRsn = new QSocketNotifier((int)m_sock,QSocketNotifier::Read);
+
+ QObject::connect(m_pRsn,SIGNAL(activated(int)),this,SLOT(readProxyData(int)));
+
+ switch(m_pProxy->protocol())
+ {
+ case KviProxy::Http:
+ proxyLoginHttp();
+ break;
+ case KviProxy::Socks5:
+ proxyLoginV5();
+ break;
+ default:
+ proxyLoginV4();
+ break;
+ }
+}
+
+void KviIrcSocket::readHttpProxyErrorData(int)
+{
+ char buffer[256];
+ int readLength;
+
+ readLength = kvi_socket_recv(m_sock,buffer,255);
+ if(readLength <= 0)
+ {
+ handleInvalidSocketRead(readLength);
+ return;
+ }
+
+ outputProxyMessage(m_pConsole->decodeText(buffer));
+}
+
+void KviIrcSocket::connectedToIrcServer()
+{
+#ifdef COMPILE_SSL_SUPPORT
+ if(m_pIrcServer->useSSL())
+ {
+ m_pSSL = KviSSLMaster::allocSSL(m_pConsole,m_sock,KviSSL::Client);
+ if(!m_pSSL)
+ {
+ raiseSSLError();
+ raiseError(KviError_SSLError);
+ reset();
+ return;
+ }
+ setState(SSLHandshake);
+ doSSLHandshake(0);
+ return;
+ }
+#endif
+ linkUp();
+}
+
+
+void KviIrcSocket::readProxyData(int)
+{
+ char buffer[256];
+
+ int readLength;
+/*
+ // THIS IS WORKING CODE THAT SUPPORTS SSL PROXIES!
+#ifdef COMPILE_SSL_SUPPORT
+ if(m_pSSL)
+ {
+ readLength = m_pSSL->read(buffer,256);
+ if(readLength <= 0)
+ {
+ // ssl error....?
+ switch(m_pSSL->getProtocolError(readLength))
+ {
+ case KviSSL::ZeroReturn:
+ readLength = 0;
+ break;
+ case KviSSL::WantRead:
+ case KviSSL::WantWrite:
+ // hmmm...
+ return;
+ break;
+ case KviSSL::SyscallError:
+ {
+ int iE = m_pSSL->getLastError(true);
+ if(iE != 0)
+ {
+ raiseSSLError();
+ raiseError(KviError_SSLError);
+ reset();
+ return;
+ }
+ }
+ break;
+ case KviSSL::SSLError:
+ raiseSSLError();
+ raiseError(KviError_SSLError);
+ reset();
+ return;
+ break;
+ default:
+ raiseError(KviError_SSLError);
+ reset();
+ return;
+ break;
+
+ }
+ handleInvalidSocketRead(readLength);
+ return;
+ }
+ } else {
+#endif
+*/
+ readLength = kvi_socket_recv(m_sock,buffer,255);
+ if(readLength <= 0)
+ {
+ handleInvalidSocketRead(readLength);
+ return;
+ }
+/*
+#ifdef COMPILE_SSL_SUPPORT
+ }
+#endif
+*/
+ // we need at least two bytes...
+ if(readLength < 2)
+ {
+ // a single byte of reply means:
+ // - connection through a 1 bps modem
+ // - a totally blocked network
+ // - remote host is not a SOCKS/HTTP server
+ // Anyway....it is always a meaningless reply
+ // better to try again later :)
+ raiseError(KviError_unrecognizedProxyReply);
+ reset();
+ return;
+ }
+ // handle the reply
+ switch(m_state)
+ {
+ case ProxyFinalV4:
+ //V4 final reply
+ proxyHandleV4FinalReply((unsigned char)buffer[1]);
+ break;
+ case ProxySelectAuthMethodV5:
+ //V5 method selection reply
+ proxyHandleV5MethodReply((unsigned char)buffer[1]);
+ break;
+ case ProxyUserPassV5:
+ //V5 user and pass reply
+ proxyHandleV5AuthReply((unsigned char)buffer[1]);
+ break;
+ case ProxyFinalV5:
+ //V5 final reply
+ proxyHandleV5FinalReply((unsigned char)buffer[1]);
+ break;
+ case ProxyFinalHttp:
+ //Http final reply
+ buffer[readLength] = '\0';
+ proxyHandleHttpFinalReply(buffer,readLength);
+ break;
+ default:
+ // what ?
+ raiseError(KviError_unrecognizedProxyReply);
+ reset();
+ break;
+ }
+}
+
+
+
+void KviIrcSocket::proxyLoginHttp()
+{
+ // Well..this is just plain and easy: connect to the proxy machine
+ // and say "CONNECT <irc.server>:<port> HTTP/<version>\n\n"
+ // if it requires auth than say Proxy-Authorization: Basic user:passwd
+ // Then expect a server reply header (2 newlines)
+ // HTTP 200 = Success
+ // HTTP Anything else = Failure
+
+ if(_OUTPUT_VERBOSE)
+ outputProxyMessage(__tr2qs("Using HTTP protocol."));
+
+ setState(ProxyFinalHttp);
+ KviStr tmp(KviStr::Format,"CONNECT %s:%u HTTP/1.0\r\n",m_pIrcServer->hostName().utf8().data(),(unsigned int)(m_pIrcServer->port()));
+ if(m_pProxy->hasUser())
+ {
+ KviStr auth(KviStr::Format,"%s:%s",m_pProxy->user(),m_pProxy->pass());
+ KviStr encoded;
+ encoded.bufferToBase64(auth.ptr(),auth.len());
+ tmp.append(KviStr::Format,"Proxy-Authorization: Basic %s\r\n\r\n",encoded.ptr());
+ } else {
+ tmp.append("\r\n");
+ }
+// debug(tmp.ptr());
+ sendRawData(tmp.ptr(),tmp.len());
+}
+
+void KviIrcSocket::proxyLoginV4()
+{
+ // SOCKSV4 protocol
+ //
+ // 1) CONNECT
+ //
+ // The client connects to the SOCKS server and sends a CONNECT request when
+ // it wants to establish a connection to an application server. The client
+ // includes in the request packet the IP address and the port number of the
+ // destination host, and userid, in the following format.
+ //
+ // +----+----+----+----+----+----+----+----+----+----+....+----+
+ // | VN | CD | DSTPORT | DSTIP | USERID |NULL|
+ // +----+----+----+----+----+----+----+----+----+----+....+----+
+ // # of bytes: 1 1 2 4 variable 1
+ //
+ // VN is the SOCKS protocol version number and should be 4. CD is the
+ // SOCKS command code and should be 1 for CONNECT request. NULL is a byte
+ // of all zero bits.
+ //
+ // The SOCKS server checks to see whether such a request should be granted
+ // based on any combination of source IP address, destination IP address,
+ // destination port number, the userid, and information it may obtain by
+ // consulting IDENT, cf. RFC 1413. If the request is granted, the SOCKS
+ // server makes a connection to the specified port of the destination host.
+ // A reply packet is sent to the client when this connection is established,
+ // or when the request is rejected or the operation fails.
+ //
+ if(_OUTPUT_VERBOSE)
+ outputProxyMessage(__tr2qs("Using SOCKSV4 protocol."));
+
+ m_pProxy->normalizeUserAndPass();
+ // the protocol does not specify the "userid" format...
+ // so build an userid from the pass and/or username...
+
+ KviStr szUserAndPass=m_pProxy->user();
+ if(m_pProxy->hasPass()){
+ if(szUserAndPass.hasData())szUserAndPass.append(' ');
+ szUserAndPass.append(m_pProxy->pass());
+ }
+ int iLen = szUserAndPass.len()+9;
+ // build the request packet
+ char *bufToSend = new char[iLen];
+ bufToSend[0]=(unsigned char)4; //Version 4
+ bufToSend[1]=(unsigned char)1; //Connect
+ Q_UINT16 port=(Q_UINT16)htons(m_pIrcServer->port());
+ kvi_memmove((void *)(bufToSend+2),(void *)&port,2);
+
+ struct in_addr ircInAddr;
+
+ if(!kvi_stringIpToBinaryIp(m_pIrcServer->ip(),&ircInAddr))
+ debug("SOCKET INTERNAL ERROR IN IPV4 (SOCKS4) ADDR CONVERSION");
+
+ Q_UINT32 host=(Q_UINT32)ircInAddr.s_addr;
+ kvi_memmove((void *)(bufToSend+4),(void *)&host,4);
+ kvi_memmove((void *)(bufToSend+8),(void *)(szUserAndPass.ptr()),szUserAndPass.len());
+ // send it into hyperspace...
+ setState(ProxyFinalV4);
+ sendRawData(bufToSend,iLen);
+ delete[] bufToSend;
+ // and wait for reply...
+}
+
+void KviIrcSocket::proxyLoginV5()
+{
+ // SOCKSV5 protocol.
+ //
+ // When a TCP-based client wishes to establish a connection to an object
+ // that is reachable only via a firewall (such determination is left up
+ // to the implementation), it must open a TCP connection to the
+ // appropriate SOCKS port on the SOCKS server system. The SOCKS service
+ // is conventionally located on TCP port 1080. If the connection
+ // request succeeds, the client enters a negotiation for the
+ // authentication method to be used, authenticates with the chosen
+ // method, then sends a relay request. The SOCKS server evaluates the
+ // request, and either establishes the appropriate connection or denies
+ // it.
+ //
+ // The client connects to the server, and sends a version
+ // identifier/method selection message:
+ //
+ // +----+----------+----------+
+ // |VER | NMETHODS | METHODS |
+ // +----+----------+----------+
+ // | 1 | 1 | 1 to 255 |
+ // +----+----------+----------+
+ //
+ // The VER field is set to X'05' for this version of the protocol. The
+ // NMETHODS field contains the number of method identifier octets that
+ // appear in the METHODS field.
+ // The values currently defined for METHOD are:
+ //
+ // o X'00' NO AUTHENTICATION REQUIRED
+ // o X'01' GSSAPI
+ // o X'02' USERNAME/PASSWORD
+ // o X'03' CHAP
+ // o X'04' to X'7F' IANA ASSIGNED
+ // o X'80' to X'FE' RESERVED FOR PRIVATE METHODS
+ // o X'FF' NO ACCEPTABLE METHODS
+ //
+
+ if(_OUTPUT_VERBOSE)
+ outputProxyMessage(__tr2qs("Using SOCKSv5 protocol."));
+
+ m_pProxy->normalizeUserAndPass();
+ // the protocol does not specify the "userid" format...
+ // so build an userid from the pass and/or username...
+
+ char bufToSend[4];
+ bufToSend[0]=(unsigned char)5; //use version 5
+ int sendLen = 3;
+ if(!(m_pProxy->hasUser() || m_pProxy->hasPass()))
+ {
+ // no auth needed.
+ bufToSend[1]=(unsigned char)1; //select one method
+ bufToSend[2]=(unsigned char)0; //select method 0 : no auth
+ if(_OUTPUT_VERBOSE)
+ outputProxyMessage(__tr2qs("We can accept auth method 0 (no auth)"));
+ } else {
+ // we can provide a password and username if needed...
+ bufToSend[1]=(unsigned char)2; //select from two methods
+ bufToSend[2]=(unsigned char)0; //method 0 or
+ bufToSend[3]=(unsigned char)2; //method 2 username/pass auth
+ sendLen = 4;
+ if(_OUTPUT_VERBOSE)
+ outputProxyMessage(__tr2qs("We can accept auth method 0 (no auth) or 2 (user/pass)"));
+ }
+ // notify the user before sending...since we may get disconnected
+ setState(ProxySelectAuthMethodV5);
+ sendRawData(bufToSend,sendLen);
+ // and wait for response
+}
+
+void KviIrcSocket::proxyAuthUserPassV5()
+{
+ // Once the SOCKS V5 server has started, and the client has selected the
+ // Username/Password Authentication protocol, the Username/Password
+ // subnegotiation begins. This begins with the client producing a
+ // Username/Password request:
+ //
+ // +----+------+----------+------+----------+
+ // |VER | ULEN | UNAME | PLEN | PASSWD |
+ // +----+------+----------+------+----------+
+ // | 1 | 1 | 1 to 255 | 1 | 1 to 255 |
+ // +----+------+----------+------+----------+
+ //
+ // The VER field contains the current version of the subnegotiation,
+ // which is X'01'. The ULEN field contains the length of the UNAME field
+ // that follows. The UNAME field contains the username as known to the
+ // source operating system. The PLEN field contains the length of the
+ // PASSWD field that follows. The PASSWD field contains the password
+ // association with the given UNAME.
+ //
+ unsigned int lPass=(unsigned int)m_pProxy->passLen();
+ if(lPass>255)lPass=255;
+ unsigned int lUser=(unsigned int)m_pProxy->userLen();
+ if(lUser>255)lUser=255;
+ int iLen=lPass+lUser+3;
+ char *bufToSend=new char[iLen];
+ bufToSend[0]=(unsigned char)1; //version x'01'
+ bufToSend[1]=(unsigned char)lUser; //length of the username
+ kvi_memmove((void *)(bufToSend+2),(void *)m_pProxy->user(),lUser); //username
+ bufToSend[2+lUser]=(unsigned char)lPass; //length of the password
+ kvi_memmove((void *)(bufToSend+3+lUser),(void *)m_pProxy->pass(),lPass);
+ // spit out the buffer and wait
+ setState(ProxyUserPassV5);
+ sendRawData(bufToSend,iLen);
+ delete[] bufToSend;
+ // and wait for response...
+}
+
+void KviIrcSocket::proxySendTargetDataV5()
+{
+ // Once the method-dependent subnegotiation has completed, the client
+ // sends the request details. If the negotiated method includes
+ // encapsulation for purposes of integrity checking and/or
+ // confidentiality, these requests MUST be encapsulated in the method-
+ // dependent encapsulation.
+ //
+ // The SOCKS request is formed as follows:
+ //
+ // +----+-----+------+------+----------+----------+
+ // |VER | CMD | FLAG | ATYP | DST.ADDR | DST.PORT |
+ // +----+-----+------+------+----------+----------+
+ // | 1 | 1 | 1 | 1 | Variable | 2 |
+ // +----+-----+------+------+----------+----------+
+ //
+ // Where:
+ //
+ // o VER protocol version: X'05'
+ // o CMD
+ // o CONNECT X'01'
+ // o BIND X'02'
+ // o UDP ASSOCIATE X'03'
+ // o X'04' to X'7F' IANA ASSIGNED
+ // o X'80' to X'FF' RESERVED FOR PRIVATE METHODS
+ // o FLAG command dependent flag (defaults to X'00')
+ // o ATYP address type of following address
+ // o IP V4 address: X'01'
+ // o DOMAINNAME: X'03'
+ // o IP V6 address: X'04'
+ // o DST.ADDR desired destination address
+ // o DST.PORT desired destination port in network octet
+ // order
+ //
+ // The SOCKS server will typically evaluate the request based on
+ // source and destination addresses, and return one or more reply
+ // messages, as appropriate for the request type.
+ //
+ // In an address field (DST.ADDR, BND.ADDR), the ATYP field specifies
+ // the type of address contained within the field:
+ //
+ // o X'01'
+ //
+ // The address is a version-4 IP address, with a length of 4 octets.
+ //
+ // o X'03'
+ //
+ // The address field contains a fully-qualified domain name. The first
+ // octet of the address field contains the number of octets of name that
+ // follow, there is no terminating NUL octet.
+ //
+ // o X'04'
+ //
+ // The address is a version-6 IP address, with a length of 16 octets.
+ bool bRemoteDns=!(
+
+ (
+ KviNetUtils::isValidStringIp(m_pIrcServer->ip())
+ #ifdef COMPILE_IPV6_SUPPORT
+ || KviNetUtils::isValidStringIp_V6(m_pIrcServer->ip())
+ #endif
+ )
+
+ && m_pIrcServer->cacheIp()
+ );
+ int bufLen = bRemoteDns ? 4 + 1 + m_pIrcServer->hostName().utf8().length() + 2
+ : (m_pIrcServer->isIpV6() ? 22 : 10);
+ char * bufToSend = (char *)kvi_malloc(sizeof(char) * bufLen);
+ bufToSend[0]=(unsigned char)5; //Proto 5
+ bufToSend[1]=(unsigned char)1; //CONNECT
+ bufToSend[2]=(unsigned char)0; //RSV
+
+ if(bRemoteDns)
+ {
+ bRemoteDns=true;
+ bufToSend[3]=3;
+ bufToSend[4]=m_pIrcServer->hostName().utf8().length();
+ } else {
+ bufToSend[3]=(unsigned char)m_pIrcServer->isIpV6() ? 4 : 1; // IPV6 : IPV4
+ }
+
+ if(bRemoteDns)
+ {
+ kvi_memmove((void *)(bufToSend + 5),
+ (void *)(m_pIrcServer->hostName().utf8().data()),
+ m_pIrcServer->hostName().utf8().length());
+ Q_UINT16 port = (Q_UINT16)htons(m_pIrcServer->port());
+ kvi_memmove((void *)(bufToSend + 4 + 1 + m_pIrcServer->hostName().utf8().length()),(void *)&port,2);
+ } else if(m_pIrcServer->isIpV6()) {
+#ifdef COMPILE_IPV6_SUPPORT
+ struct in6_addr ircInAddr;
+
+ if(!kvi_stringIpToBinaryIp_V6(m_pIrcServer->ip(),&ircInAddr))debug("SOCKET INTERNAL ERROR IN IPV6 ADDR CONVERSION");
+ kvi_memmove((void *)(bufToSend + 4),(void *)(&ircInAddr),4);
+ Q_UINT16 port = (Q_UINT16)htons(m_pIrcServer->port());
+ kvi_memmove((void *)(bufToSend + 20),(void *)&port,2);
+#endif
+ } else {
+ struct in_addr ircInAddr;
+
+ if(!kvi_stringIpToBinaryIp(m_pIrcServer->ip(),&ircInAddr))debug("SOCKET INTERNAL ERROR IN IPV4 ADDR CONVERSION");
+ Q_UINT32 host = (Q_UINT32)ircInAddr.s_addr;
+ kvi_memmove((void *)(bufToSend + 4),(void *)&host,4);
+ Q_UINT16 port = (Q_UINT16)htons(m_pIrcServer->port());
+ kvi_memmove((void *)(bufToSend + 8),(void *)&port,2);
+ }
+
+ // send it into hyperspace...
+ setState(ProxyFinalV5);
+ sendRawData(bufToSend,bufLen);
+ kvi_free(bufToSend);
+ // and wait for reply...
+}
+
+
+void KviIrcSocket::proxyHandleV5AuthReply(unsigned char reply)
+{
+ // The server verifies the supplied UNAME and PASSWD, and sends the
+ // following response:
+ //
+ // +----+--------+
+ // |VER | STATUS |
+ // +----+--------+
+ // | 1 | 1 |
+ // +----+--------+
+ //
+ // A STATUS field of X'00' indicates success. If the server returns a
+ // `failure' (STATUS value other than X'00') status, it MUST close the
+ // connection.
+ //
+ if(reply == 0)
+ {
+ if(_OUTPUT_VERBOSE)
+ outputProxyMessage(__tr2qs("Proxy response: auth OK: access granted"));
+ proxySendTargetDataV5();
+ return;
+ }
+ raiseError(KviError_proxyAuthFailed);
+ reset();
+}
+
+void KviIrcSocket::proxyHandleV5MethodReply(unsigned char reply)
+{
+ // The server selects from one of the methods given in METHODS, and
+ // sends a METHOD selection message:
+ //
+ // +----+--------+
+ // |VER | METHOD |
+ // +----+--------+
+ // | 1 | 1 |
+ // +----+--------+
+ //
+ // If the selected METHOD is X'FF', none of the methods listed by the
+ // client are acceptable, and the client MUST close the connection.
+ //
+ // The values currently defined for METHOD are:
+ //
+ // o X'00' NO AUTHENTICATION REQUIRED
+ // o X'01' GSSAPI
+ // o X'02' USERNAME/PASSWORD
+ // o X'03' CHAP
+ // o X'04' to X'7F' IANA ASSIGNED
+ // o X'80' to X'FE' RESERVED FOR PRIVATE METHODS
+ // o X'FF' NO ACCEPTABLE METHODS
+ //
+ if(reply == 0)
+ {
+ if(_OUTPUT_VERBOSE)
+ outputProxyMessage(__tr2qs("Proxy response: Auth method OK: using method 0 (no auth)"));
+ proxySendTargetDataV5();
+ return;
+ }
+ if(reply == 2)
+ {
+ if(_OUTPUT_VERBOSE)
+ outputProxyMessage(__tr2qs("Proxy response: Auth method OK: using method 2 (user/pass)"));
+ proxyAuthUserPassV5();
+ return;
+ }
+ //Request rejected
+ if(reply == 0xFF)
+ {
+ raiseError(KviError_proxyNoAcceptableAuthMethod);
+ reset();
+ } else {
+ // unrecognized...
+ raiseError(KviError_unrecognizedProxyReply);
+ reset();
+ }
+}
+
+void KviIrcSocket::proxyHandleV5FinalReply(unsigned char reply)
+{
+ //
+ // The SOCKS request information is sent by the client as soon as it has
+ // established a connection to the SOCKS server, and completed the
+ // authentication negotiations. The server evaluates the request, and
+ // returns a reply formed as follows:
+ //
+ // +----+-----+------+------+----------+----------+
+ // |VER | REP | FLAG | ATYP | BND.ADDR | BND.PORT |
+ // +----+-----+------+------+----------+----------+
+ // | 1 | 1 | 1 | 1 | Variable | 2 |
+ // +----+-----+------+------+----------+----------+
+ //
+ // Where:
+ // o VER protocol version: X'05'
+ // o REP Reply field:
+ // o X'00' succeeded
+ // o X'01' general SOCKS server failure
+ // o X'02' connection not allowed by ruleset
+ // o X'03' Network unreachable
+ // o X'04' Host unreachable
+ // o X'05' Connection refused
+ // o X'06' TTL expired
+ // o X'07' Command not supported
+ // o X'08' Address type not supported
+ // o X'09' Invalid address
+ // o X'0A' to X'FF' unassigned
+ // o FLAG command dependent flag
+ // o ATYP address type of following address
+ // o IP V4 address: X'01'
+ // o DOMAINNAME: X'03'
+ // o IP V6 address: X'04'
+ // o BND.ADDR server bound address
+ // o BND.PORT server bound port in network octet order
+ //
+ if(reply==0)
+ {
+ // Request granted
+ if(_OUTPUT_VERBOSE)
+ outputProxyMessage(__tr2qs("Proxy response: target data OK: request granted"));
+ connectedToIrcServer();
+ } else {
+ //Request rejected
+ int err;
+ switch(reply)
+ {
+ case 1: err = KviError_proxyReply01GeneralSOCKSFailure; break;
+ case 2: err = KviError_proxyReply02ConnectionNotAllowed; break;
+ case 3: err = KviError_proxyReply03NetworkUnreachable; break;
+ case 4: err = KviError_proxyReply04HostUnreachable; break;
+ case 5: err = KviError_proxyReply05ConnectionRefused; break;
+ case 6: err = KviError_proxyReply06TTLExpired; break;
+ case 7: err = KviError_proxyReply07CommandNotSupported; break;
+ case 8: err = KviError_proxyReply08AddressTypeNotSupported; break;
+ case 9: err = KviError_proxyReply09InvalidAddress; break;
+ default: err = KviError_unrecognizedProxyReply; break;
+ }
+ raiseError(err);
+ reset();
+ }
+}
+
+void KviIrcSocket::proxyHandleV4FinalReply(unsigned char reply)
+{
+ // If the request is granted, the SOCKS
+ // server makes a connection to the specified port of the destination host.
+ // A reply packet is sent to the client when this connection is established,
+ // or when the request is rejected or the operation fails.
+ //
+ //
+ // +----+----+----+----+----+----+----+----+
+ // | VN | CD | DSTPORT | DSTIP |
+ // +----+----+----+----+----+----+----+----+
+ // # of bytes: 1 1 2 4
+ //
+ // VN is the version of the reply code and should be 0. CD is the result
+ // code with one of the following values:
+ //
+ // 90: request granted
+ // 91: request rejected or failed
+ // 92: request rejected becasue SOCKS server cannot connect to
+ // identd on the client
+ // 93: request rejected because the client program and identd
+ // report different user-ids
+ //
+ // The remaining fields are ignored.
+ //
+ // The SOCKS server closes its connection immediately after notifying
+ // the client of a failed or rejected request. For a successful request,
+ // the SOCKS server gets ready to relay traffic on both directions. This
+ // enables the client to do I/O on its connection as if it were directly
+ // connected to the application server.
+ if(reply==90)
+ {
+ // Request granted
+ if(_OUTPUT_VERBOSE)
+ outputProxyMessage(__tr2qs("Proxy response: target data OK: request granted"));
+ connectedToIrcServer();
+ } else {
+ //Request rejected
+ int err;
+ switch(reply)
+ {
+ case 91: err = KviError_proxyReply91RequestFailed; break;
+ case 92: err = KviError_proxyReply92IdentFailed; break;
+ case 93: err = KviError_proxyReply93IdentNotMatching; break;
+ default: err = KviError_unrecognizedProxyReply; break;
+ }
+ raiseError(err);
+ reset();
+ }
+ // Just looked out of the window...
+ // Hmmmm...strange light outside...
+ // Looked at the clock...6:34 !
+ // I think I'll go sleep.... :)
+}
+
+void KviIrcSocket::proxyHandleHttpFinalReply(const char * buffer,int bufLen)
+{
+ // Escape character is '^]'.
+ // CONNECT warszawa.irc.pl:6667 HTTP/1.0
+ //
+ // HTTP/1.0 200 Connection established
+
+ KviStr tmp = buffer;
+ // FIXME: #warning "We could even show the proxy output here...!"
+ tmp.cutFromFirst('\n');
+ tmp.stripWhiteSpace();
+
+ if(kvi_strEqualCIN(tmp.ptr(),"HTTP",4))
+ {
+ int idx = tmp.findFirstIdx(" 200 ");
+ if(idx != -1)
+ {
+ if(idx == tmp.findFirstIdx(' '))
+ {
+ QString msg = __tr2qs("Proxy response: ");
+ msg += tmp.ptr();
+ if(_OUTPUT_VERBOSE)
+ outputProxyMessage(msg);
+ connectedToIrcServer();
+ return;
+ }
+ }
+
+ }
+
+ outputProxyError(__tr2qs("Proxy said something about: \n"));
+ outputProxyMessage(m_pConsole->decodeText(buffer));
+
+ //Read HTTP error page and show it
+
+ if(m_pWsn)
+ {
+ delete m_pWsn;
+ m_pWsn = 0;
+ }
+
+ if(m_pRsn)
+ {
+ delete m_pRsn;
+ m_pRsn = 0;
+ }
+
+ m_pRsn = new QSocketNotifier((int)m_sock,QSocketNotifier::Read);
+ QObject::connect(m_pRsn,SIGNAL(activated(int)),this,SLOT(readHttpProxyErrorData(int)));
+ m_pRsn->setEnabled(true);
+
+ setState(ProxyHttpError);
+
+// raiseError(KviError_proxyHttpFailure);
+// reset();
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// SSL HANDSHAKE
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+#ifdef COMPILE_SSL_SUPPORT
+
+void KviIrcSocket::printSSLPeerCertificate()
+{
+ KviSSLCertificate * c = m_pSSL->getPeerCertificate();
+ if(c)
+ {
+ //m_pConsole->socketEvent(SSLCertificate,(void *)c);
+ if(_OUTPUT_VERBOSE)
+ KviSSLMaster::printSSLCertificate(m_pConsole,__tr("Server X509 certificate"),c);
+ delete c;
+ } else {
+ if(_OUTPUT_VERBOSE)
+ outputSSLMessage(__tr2qs("The server didn't provide a certificate"));
+ }
+}
+
+void KviIrcSocket::printSSLCipherInfo()
+{
+ KviSSLCipherInfo * ci = m_pSSL->getCurrentCipherInfo();
+ if(ci)
+ {
+ //m_pConsole->socketEvent(SSLCipherInfo,(void *)ci);
+ KviSSLMaster::printSSLCipherInfo(m_pConsole,__tr2qs("Current transmission cipher"),ci);
+ delete ci;
+ } else {
+ if(_OUTPUT_VERBOSE)
+ outputSSLMessage(__tr2qs("Unable to determine the current cipher"));
+ }
+}
+
+void KviIrcSocket::raiseSSLError()
+{
+ KviStr buffer;
+ while(m_pSSL->getLastErrorString(buffer))
+ {
+ outputSSLError(buffer.ptr());
+ }
+}
+
+#endif
+
+
+void KviIrcSocket::doSSLHandshake(int)
+{
+#ifdef COMPILE_SSL_SUPPORT
+ __range_valid(m_pSSL);
+
+ if(m_pRsn)
+ {
+ delete m_pRsn;
+ m_pRsn = 0;
+ }
+ if(m_pWsn)
+ {
+ delete m_pWsn;
+ m_pWsn = 0;
+ }
+
+ if(!m_pSSL)
+ {
+ debug("Ops... I've lost the SSL class ?");
+ reset();
+ return; // ops ?
+ }
+
+ switch(m_pSSL->connect())
+ {
+ case KviSSL::Success:
+ // done!
+ printSSLCipherInfo();
+ printSSLPeerCertificate();
+ linkUp();
+ break;
+ case KviSSL::WantRead:
+ m_pRsn = new QSocketNotifier((int)m_sock,QSocketNotifier::Read);
+ QObject::connect(m_pRsn,SIGNAL(activated(int)),this,SLOT(doSSLHandshake(int)));
+ m_pRsn->setEnabled(true);
+ break;
+ case KviSSL::WantWrite:
+ m_pWsn = new QSocketNotifier((int)m_sock,QSocketNotifier::Write);
+ QObject::connect(m_pWsn,SIGNAL(activated(int)),this,SLOT(doSSLHandshake(int)));
+ m_pWsn->setEnabled(true);
+ break;
+ case KviSSL::RemoteEndClosedConnection:
+ raiseError(KviError_remoteEndClosedConnection);
+ reset();
+ break;
+ case KviSSL::SSLError:
+ raiseSSLError();
+ raiseError(KviError_SSLError);
+ reset();
+ break;
+ case KviSSL::SyscallError:
+ {
+ // syscall problem
+ int err = kvi_socket_error();
+ if(!kvi_socket_recoverableError(err))
+ {
+ // Declare problems :)
+ raiseError((err ? KviError::translateSystemError(err) : KviError_unknownError));
+ } else {
+ // can recover ? (EAGAIN , EINTR ?)
+ m_pWsn = new QSocketNotifier((int)m_sock,QSocketNotifier::Write);
+ QObject::connect(m_pWsn,SIGNAL(activated(int)),this,SLOT(doSSLHandshake(int)));
+ m_pWsn->setEnabled(true);
+ return;
+ }
+ reset();
+ }
+ break;
+ default:
+ raiseError(KviError_SSLError);
+ reset();
+ break;
+ }
+
+#else //!COMPILE_SSL_SUPPORT
+ debug("Ops.. ssl handshake without ssl support!...aborting!");
+ exit(-1);
+#endif //!COMPILE_SSL_SUPPORT
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// LINK UP
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void KviIrcSocket::linkUp()
+{
+ setState(Connected);
+
+ // the last check
+ if(m_sock == KVI_INVALID_SOCKET)return; // ops...disconnected in setState() ????
+
+ // ok.. it seems that we're really up and running now!
+ if(m_pWsn)
+ {
+ delete m_pWsn;
+ m_pWsn = 0;
+ }
+
+ if(m_pRsn)
+ {
+ delete m_pRsn;
+ m_pRsn = 0;
+ }
+
+ m_pRsn = new QSocketNotifier((int)m_sock,QSocketNotifier::Read);
+ QObject::connect(m_pRsn,SIGNAL(activated(int)),this,SLOT(readData(int)));
+ m_pRsn->setEnabled(true);
+
+ // yahoo!
+}
+
+void KviIrcSocket::readData(int)
+{
+ //read data
+ char buffer[1025];
+ int readLength;
+#ifdef COMPILE_SSL_SUPPORT
+ if(m_pSSL)
+ {
+ readLength = m_pSSL->read(buffer,1024);
+ if(readLength <= 0)
+ {
+ // ssl error....?
+ switch(m_pSSL->getProtocolError(readLength))
+ {
+ case KviSSL::ZeroReturn:
+ readLength = 0;
+ break;
+ case KviSSL::WantRead:
+ case KviSSL::WantWrite:
+ // hmmm...
+ return;
+ break;
+ case KviSSL::SyscallError:
+ {
+ int iE = m_pSSL->getLastError(true);
+ if(iE != 0)
+ {
+ raiseSSLError();
+ raiseError(KviError_SSLError);
+ reset();
+ return;
+ }
+ }
+ break;
+ case KviSSL::SSLError:
+ raiseSSLError();
+ raiseError(KviError_SSLError);
+ reset();
+ return;
+ break;
+ default:
+ raiseError(KviError_SSLError);
+ reset();
+ return;
+ break;
+
+ }
+ handleInvalidSocketRead(readLength);
+ return;
+ }
+ } else {
+#endif
+ readLength = kvi_socket_recv(m_sock,buffer,1024);
+ if(readLength <= 0)
+ {
+ handleInvalidSocketRead(readLength);
+ return;
+ }
+#ifdef COMPILE_SSL_SUPPORT
+ }
+#endif
+
+
+ //terminate our buffer
+ (*(buffer+readLength))='\0';
+
+ m_uReadBytes += readLength;
+
+ // Shut up the socket notifier
+ // in case that we enter in a local loop somewhere
+ // while processing data...
+ m_pRsn->setEnabled(false);
+ // shut also the flushing of the message queue
+ // in this way we prevent disconnect detection
+ // during the processing of a message effectively
+ // making it always an asynchronous event.
+ m_bInProcessData = true;
+
+ m_pLink->processData(buffer,readLength);
+ // after this line there should be nothing that relies
+ // on the "connected" state of this socket.
+ // It may happen that it has been reset() in the middle of the processData() call
+ // and (unverified) it might have been even deleted.
+
+ // re-enable the socket notifier... (if it's still there)
+ if(m_pRsn)m_pRsn->setEnabled(true);
+ // and the message queue flushing
+ m_bInProcessData = false;
+ // and flush the queue too!
+ if(m_pSendQueueHead)flushSendQueue();
+}
+
+/*
+void KviIrcSocket::processData(char * buffer,int)
+{
+ register char *p=buffer;
+ char *beginOfCurData = buffer;
+ int bufLen = 0;
+ char *messageBuffer = (char *)kvi_malloc(1);
+
+ // Shut up the socket notifier
+ // in case that we enter in a local loop somewhere
+ // while processing data...
+ m_pRsn->setEnabled(false);
+ // shut also the flushing of the message queue
+ // in this way we prevent disconnect detection
+ // during the processing of a message effectively
+ // making it always an asynchronous event.
+ m_bInProcessData = true;
+
+ while(*p)
+ {
+ if((*p == '\r' )||(*p == '\n'))
+ {
+ //found a CR or LF...
+ //prepare a message buffer
+ bufLen = p - beginOfCurData;
+ //check for previous unterminated data
+ if(m_uReadBufferLen > 0){
+ __range_valid(m_pReadBuffer);
+ messageBuffer = (char *)kvi_realloc(messageBuffer,bufLen + m_uReadBufferLen + 1);
+ kvi_memmove(messageBuffer,m_pReadBuffer,m_uReadBufferLen);
+ kvi_memmove((void *)(messageBuffer + m_uReadBufferLen),beginOfCurData,bufLen);
+ *(messageBuffer + bufLen + m_uReadBufferLen) = '\0';
+ m_uReadBufferLen = 0;
+ kvi_free(m_pReadBuffer);
+ m_pReadBuffer = 0;
+ } else {
+ __range_invalid(m_pReadBuffer);
+ messageBuffer = (char *)kvi_realloc(messageBuffer,bufLen + 1);
+ kvi_memmove(messageBuffer,beginOfCurData,bufLen);
+ *(messageBuffer + bufLen) = '\0';
+ }
+ m_uReadPackets++;
+
+ // FIXME: actually it can happen that the socket gets disconnected
+ // in a incomingMessage() call.
+ // The problem might be that some other parts of kvirc assume
+ // that the irc context still exists after a failed write to the socket
+ // (some parts don't even check the return value!)
+ // If the problem presents itself again then the solution is:
+ // disable queue flushing for the "incomingMessage" call
+ // and just call queue_insertMessage()
+ // then after the call terminates flush the queue (eventually detecting
+ // the disconnect and thus destroying the irc context).
+ // For now we try to rely on the remaining parts to handle correctly
+ // such conditions. Let's see...
+
+ m_pConsole->incomingMessage(messageBuffer);
+
+ if(m_state != Connected)
+ {
+ // Disconnected in KviConsole::incomingMessage() call.
+ // This may happen for several reasons (local event loop
+ // with the user hitting the disconnect button, a scripting
+ // handler event that disconnects explicitly)
+ //
+ // We handle it by simply returning control to readData() which
+ // will return immediately (and safely) control to Qt
+ kvi_free(messageBuffer);
+ m_bInProcessData = false;
+ return;
+ }
+
+ while(*p && ((*p=='\r')||(*p=='\n')) )p++;
+ beginOfCurData = p;
+
+ } else p++;
+ }
+
+ //now *p == '\0'
+ //beginOfCurData points to '\0' if we have
+ //no more stuff to parse , or points to something
+ //different than '\r' or '\n'...
+ if(*beginOfCurData)
+ {
+ //Have remaining data...in the local buffer
+ bufLen = p - beginOfCurData;
+ if(m_uReadBufferLen > 0){
+ //and there was more stuff saved... (really slow connection)
+ __range_valid(m_pReadBuffer);
+ m_pReadBuffer =(char *)kvi_realloc(m_pReadBuffer,m_uReadBufferLen + bufLen);
+ kvi_memmove((void *)(m_pReadBuffer+m_uReadBufferLen),beginOfCurData,bufLen);
+ m_uReadBufferLen += bufLen;
+ } else {
+ //
+ __range_invalid(m_pReadBuffer);
+ m_uReadBufferLen = bufLen;
+ m_pReadBuffer =(char *)kvi_malloc(m_uReadBufferLen);
+ kvi_memmove(m_pReadBuffer,beginOfCurData,m_uReadBufferLen);
+ }
+ //The m_pReadBuffer contains at max 1 irc message...
+ //that can not be longer than 510 bytes (the message is not CRLF terminated)
+ // FIXME: Is this limit *really* valid on all servers ?
+ if(m_uReadBufferLen > 510)debug("WARNING : Receiving an invalid irc message from server.");
+ }
+ kvi_free(messageBuffer);
+
+ // re-enable the socket notifier...
+ m_pRsn->setEnabled(true);
+ // and the message queue flushing
+ m_bInProcessData = false;
+ // and flush the queue too!
+ if(m_pSendQueueHead)flushSendQueue();
+}
+*/
+
+void KviIrcSocket::abort()
+{
+ // flush the send queue if possible (and if not yet disconnected in fact)
+ if(m_state == Connected)flushSendQueue();
+ if(m_state != Idle)
+ raiseError(KviError_operationAborted);
+ // and reset
+ reset();
+}
+
+//=== handleInvalidSocketRead ===============================================//
+//
+// Checks if the socket error is a transient error
+// If it is not a transient error it resets the socket
+// and fires the appropriate event.
+// Otherwise it does nothing.
+//
+void KviIrcSocket::handleInvalidSocketRead(int readedLength)
+{
+ __range_valid(readedLength <= 0);
+ if(readedLength==0)
+ {
+ raiseError(KviError_remoteEndClosedConnection);
+ reset();
+ } else {
+ //check for transmission errors
+ int err = kvi_socket_error();
+#ifdef COMPILE_ON_WINDOWS
+ if((err != EAGAIN) && (err != EINTR) && (err != WSAEWOULDBLOCK))
+#else
+ if((err != EAGAIN) && (err != EINTR))
+#endif
+ {
+ if(err > 0)raiseError((KviError::translateSystemError(err)));
+ else raiseError(KviError_remoteEndClosedConnection);
+ reset();
+ } //else transient error...wait again...
+ }
+}
+//=== data queue functions ==================================================//
+//
+// queue_insertMessage : appends a KviIrcSocketMsgEntry to the tail of
+// the message queue. The next_ptr for this message is set to 0.
+// queue_removeMessage : removes a message from the head of the queue.
+//
+
+void KviIrcSocket::queue_insertMessage(KviIrcSocketMsgEntry *msg_ptr)
+{
+ __range_valid(msg_ptr);
+ __range_valid(msg_ptr->data_ptr);
+ __range_valid(msg_ptr->data_len);
+ msg_ptr->next_ptr = 0;
+ if(m_pSendQueueHead)
+ {
+ m_pSendQueueTail->next_ptr = msg_ptr;
+ m_pSendQueueTail = msg_ptr;
+ } else {
+ m_pSendQueueHead = msg_ptr;
+ m_pSendQueueTail = msg_ptr;
+ }
+}
+
+void KviIrcSocket::free_msgEntry(KviIrcSocketMsgEntry * e)
+{
+ if(e->pData)delete e->pData;
+ e->pData = 0;
+ kvi_free(e);
+}
+
+bool KviIrcSocket::queue_removeMessage()
+{
+ __range_valid(m_pSendQueueTail);
+ __range_valid(m_pSendQueueHead);
+ if(m_pSendQueueHead->pData)delete m_pSendQueueHead->pData;
+ KviIrcSocketMsgEntry *aux_ptr = m_pSendQueueHead;
+ m_pSendQueueHead = aux_ptr->next_ptr;
+ kvi_free((void *)aux_ptr);
+ if(m_pSendQueueHead == 0)
+ {
+ m_pSendQueueTail = 0;
+ return false;
+ } else return true;
+}
+
+void KviIrcSocket::queue_removeAllMessages()
+{
+ if(m_pSendQueueHead)while(queue_removeMessage());
+}
+
+//=== flushSendQueue ========================================================//
+//
+// Attempts to send as much as possible to the server
+// If fails (happens only on really lagged servers)
+// calls itself with a QTimer shot after KVI_OPTION_UINT(KviOption_uintSocketQueueFlushTimeout) ms
+// to retry again...
+//
+void KviIrcSocket::flushSendQueue()
+{
+ // If we're called from the flush timer , stop it
+ if(m_pFlushTimer->isActive())m_pFlushTimer->stop();
+
+ // Ok...have something to send...
+ __range_valid(m_state != Idle);
+
+ struct timeval curTime;
+
+ while(m_pSendQueueHead)
+ {
+ if(KVI_OPTION_BOOL(KviOption_boolLimitOutgoingTraffic))
+ {
+ kvi_gettimeofday(&curTime,0);
+
+ int timeDiff = curTime.tv_usec - m_tAntiFloodLastMessageTime.tv_usec;
+ timeDiff += (curTime.tv_sec - m_tAntiFloodLastMessageTime.tv_sec) * 1000000;
+
+
+ if(((unsigned int)timeDiff) < KVI_OPTION_UINT(KviOption_uintOutgoingTrafficLimitUSeconds))
+ {
+ // need to wait for a while....
+ m_pFlushTimer->start(((KVI_OPTION_UINT(KviOption_uintOutgoingTrafficLimitUSeconds) - timeDiff) / 1000) + 1);
+ return;
+ } // else can send
+ }
+ // Write one data buffer...
+ int result;
+#ifdef COMPILE_SSL_SUPPORT
+ if(m_pSSL)
+ {
+ result = m_pSSL->write((char *)(m_pSendQueueHead->pData->data()),m_pSendQueueHead->pData->size());
+ } else {
+#endif
+ result = kvi_socket_send(m_sock,(char *)(m_pSendQueueHead->pData->data()),m_pSendQueueHead->pData->size());
+#ifdef COMPILE_SSL_SUPPORT
+ }
+#endif
+ if(result == (int)m_pSendQueueHead->pData->size())
+ {
+ // Succesfull send...remove this data buffer
+ m_uSentPackets++;
+ m_uSentBytes += result;
+ //if(m_pConsole->hasMonitors())outgoingMessageNotifyMonitors((char *)(m_pSendQueueHead->pData->data()),result);
+ queue_removeMessage();
+ if(KVI_OPTION_BOOL(KviOption_boolLimitOutgoingTraffic))
+ {
+ m_tAntiFloodLastMessageTime.tv_sec = curTime.tv_sec;
+ m_tAntiFloodLastMessageTime.tv_usec = curTime.tv_usec;
+ }
+ // And try next buffer...
+ continue;
+ } else {
+ // Something wrong ?
+#ifdef COMPILE_SSL_SUPPORT
+ if(result <= 0)
+ {
+ if(m_pSSL)
+ {
+ // ops...might be an SSL error
+ switch(m_pSSL->getProtocolError(result))
+ {
+ case KviSSL::WantWrite:
+ case KviSSL::WantRead:
+ // Async continue...
+ m_pFlushTimer->start(KVI_OPTION_UINT(KviOption_uintSocketQueueFlushTimeout));
+ return;
+ break;
+ case KviSSL::SyscallError:
+ if(result == 0)
+ {
+ raiseSSLError();
+ raiseError(KviError_remoteEndClosedConnection);
+ reset();
+ return;
+ } else {
+ int iSSLErr = m_pSSL->getLastError(true);
+ if(iSSLErr != 0)
+ {
+ raiseSSLError();
+ raiseError(KviError_SSLError);
+ reset();
+ return;
+ } else {
+ goto handle_system_error;
+ }
+ }
+ break;
+ case KviSSL::SSLError:
+ raiseSSLError();
+ raiseError(KviError_SSLError);
+ reset();
+ return;
+ break;
+ default:
+ raiseError(KviError_SSLError);
+ reset();
+ return;
+ break;
+ }
+ }
+ } else {
+#else //!COMPILE_SSL_SUPPORT
+ if(result >= 0)
+ {
+ if(result > 0)
+ {
+#endif //!COMPILE_SSL_SUPPORT
+
+ // Partial send...need to finish it later
+ m_pSendQueueHead->pData->remove(result);
+
+ m_uSentBytes += result;
+ if(_OUTPUT_VERBOSE)
+ outputSocketWarning(__tr2qs("Partial socket write: packet broken into smaller pieces."));
+#ifndef COMPILE_SSL_SUPPORT
+ }
+#endif //!COMPILE_SSL_SUPPORT
+ // Async continue...
+ m_pFlushTimer->start(KVI_OPTION_UINT(KviOption_uintSocketQueueFlushTimeout));
+ return;
+ }
+
+handle_system_error:
+ // Oops...error ?
+ int err = kvi_socket_error();
+#ifdef COMPILE_ON_WINDOWS
+ if((err == EAGAIN) || (err == EINTR) || (err == WSAEWOULDBLOCK))
+#else
+ if((err == EAGAIN)||(err == EINTR))
+#endif
+ {
+ // Transient error...partial send as before...
+ if(_OUTPUT_VERBOSE)
+ outputSocketWarning(__tr2qs("Partial socket write: packet broken into smaller pieces."));
+ // Async continue...
+ m_pFlushTimer->start(KVI_OPTION_UINT(KviOption_uintSocketQueueFlushTimeout));
+ return;
+ } else {
+ // Disconnected... :(
+ raiseError((KviError::translateSystemError(err)));
+ reset();
+ return;
+ }
+ }
+ }
+ //flushed completely ...
+}
+
+bool KviIrcSocket::getLocalHostIp(QString &szIp,bool bIpV6)
+{
+ if(m_state != Connected)return false;
+
+ if(bIpV6)
+ {
+#ifdef COMPILE_IPV6_SUPPORT
+ struct sockaddr_in6 name;
+ int len = sizeof(name);
+ if(!kvi_socket_getsockname(m_sock, (struct sockaddr *)&name,&len))return false;
+ //I assume that getsockname returns data in Network byte order...
+ //The man page misses to specify that...
+ if(!kvi_binaryIpToStringIp_V6(name.sin6_addr,szIp))return false;
+ return true;
+#else
+ return false; // no support
+#endif
+ }
+ struct sockaddr_in name;
+ int len = sizeof(name);
+ if(!kvi_socket_getsockname(m_sock, (struct sockaddr *)&name,&len))return false;
+ //I assume that getsockname returns data in Network byte order...
+ //The man page misses to specify that...
+ if(!kvi_binaryIpToStringIp(name.sin_addr,szIp))return false;
+ return true;
+}
+
+
+
+
+
+
+/*
+bool KviIrcSocket::sendFmtData(const char *fmt,...)
+{
+ if(m_state != Connected)return false;
+ //new buffer
+ KviIrcSocketMsgEntry *ptr = (KviIrcSocketMsgEntry *)kvi_malloc(sizeof(KviIrcSocketMsgEntry));
+ ptr->pData = new KviDataBuffer(512);
+ kvi_va_list(list);
+ kvi_va_start(list,fmt);
+ bool bTruncated;
+ //sprintf the buffer up to 512 chars (adds a CRLF too)
+ int iLen = kvi_irc_vsnprintf((char *)(ptr->pData->data()),fmt,list,&bTruncated);
+ kvi_va_end(list);
+ //adjust the buffer size
+ if(iLen < 512)ptr->pData->resize(iLen);
+ if(bTruncated)
+ {
+ if(_OUTPUT_VERBOSE)
+ outputSocketWarning(__tr2qs("Socket message truncated to 512 bytes."));
+ }
+
+ queue_insertMessage(ptr);
+ if(!m_bInProcessData)flushSendQueue();
+ return (m_state != Idle);
+}
+*/
+/*
+bool KviIrcSocket::sendData(const char *buffer,int buflen)
+{
+ if(m_state != Connected)return false;
+ //new buffer
+ KviIrcSocketMsgEntry *ptr = (KviIrcSocketMsgEntry *)kvi_malloc(sizeof(KviIrcSocketMsgEntry));
+ if(buflen < 0)buflen = strlen(buffer);
+ if(buflen > 510)
+ {
+ buflen = 510;
+ if(_OUTPUT_VERBOSE)
+ outputSocketWarning(__tr2qs("Socket message truncated to 512 bytes."));
+ }
+ ptr->pData = new KviDataBuffer(buflen + 2);
+ kvi_memmove(ptr->pData->data(),buffer,buflen);
+ *(ptr->pData->data()+buflen)='\r';
+ *(ptr->pData->data()+buflen+1)='\n';
+
+ queue_insertMessage(ptr);
+ if(!m_bInProcessData)flushSendQueue();
+ return (m_state != Idle);
+}
+*/
+
+bool KviIrcSocket::sendRawData(const char *buffer,int buflen)
+{
+ if((m_state == Idle) || (m_state == Connecting))return false;
+ //new buffer
+ KviIrcSocketMsgEntry *ptr = (KviIrcSocketMsgEntry *)kvi_malloc(sizeof(KviIrcSocketMsgEntry));
+ ptr->pData = new KviDataBuffer(buflen);
+ kvi_memmove(ptr->pData->data(),buffer,buflen);
+ queue_insertMessage(ptr);
+ if(!m_bInProcessData)flushSendQueue();
+ return (m_state != Idle);
+}
+
+bool KviIrcSocket::sendPacket(KviDataBuffer * pData)
+{
+ if(m_state != Connected)
+ {
+ delete pData;
+ pData = 0;
+ return false;
+ }
+ KviIrcSocketMsgEntry *ptr = (KviIrcSocketMsgEntry *)kvi_malloc(sizeof(KviIrcSocketMsgEntry));
+ ptr->pData = pData;
+ queue_insertMessage(ptr);
+ if(!m_bInProcessData)flushSendQueue();
+ return (m_state != Idle);
+}
diff --git a/src/kvirc/kernel/kvi_ircsocket.h b/src/kvirc/kernel/kvi_ircsocket.h
new file mode 100644
index 00000000..4946fd28
--- /dev/null
+++ b/src/kvirc/kernel/kvi_ircsocket.h
@@ -0,0 +1,174 @@
+#ifndef _KVI_IRCSOCKET_H_
+#define _KVI_IRCSOCKET_H_
+//==========================================================================================
+//
+// File : kvi_ircsocket.h
+// Creation date : Tue Jul 30 19:25:17 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//==========================================================================================
+
+#include "kvi_settings.h"
+#include "kvi_string.h"
+#include "kvi_sockettype.h"
+#include "kvi_time.h"
+#include "kvi_pointerlist.h"
+
+#include <qobject.h>
+
+class KviIrcServer;
+class KviProxy;
+class KviIrcConnection;
+class KviIrcConnectionTarget;
+class KviIrcLink;
+class KviSSL;
+class KviConsole;
+class KviDataBuffer;
+
+class QTimer;
+class QSocketNotifier;
+
+//
+// This class is the lowest level of the KVIrc networking stack
+// it sends and receives raw data packets from the underlying system
+// socket.
+// It should output only verbose "progress" messages.
+//
+
+typedef struct _KviIrcSocketMsgEntry
+{
+ KviDataBuffer * pData;
+ struct _KviIrcSocketMsgEntry * next_ptr;
+} KviIrcSocketMsgEntry;
+
+
+class KVIRC_API KviIrcSocket : public QObject
+{
+ Q_OBJECT
+public:
+ KviIrcSocket(KviIrcLink * pLink);
+ ~KviIrcSocket();
+public:
+ enum SocketState {
+ Idle ,
+ Connecting ,
+ ProxyLogin ,
+ ProxyHttpError,
+ Connected ,
+ ProxyFinalV4 ,
+ ProxyFinalV5 ,
+ ProxySelectAuthMethodV5 ,
+ ProxyUserPassV5 ,
+ ProxyFinalHttp ,
+ SSLHandshake
+ };
+protected:
+ unsigned int m_uId;
+ KviIrcLink * m_pLink;
+ KviConsole * m_pConsole;
+ kvi_socket_t m_sock;
+ SocketState m_state;
+ QSocketNotifier * m_pWsn;
+ QSocketNotifier * m_pRsn;
+ KviIrcServer * m_pIrcServer;
+ KviProxy * m_pProxy;
+ QTimer * m_pTimeoutTimer;
+ unsigned int m_uReadBytes;
+ unsigned int m_uSentBytes;
+ int m_iLastError;
+ unsigned int m_uSentPackets;
+ KviIrcSocketMsgEntry * m_pSendQueueHead;
+ KviIrcSocketMsgEntry * m_pSendQueueTail;
+ QTimer * m_pFlushTimer;
+ struct timeval m_tAntiFloodLastMessageTime;
+ bool m_bInProcessData;
+#ifdef COMPILE_SSL_SUPPORT
+ KviSSL * m_pSSL;
+#endif
+public:
+ int lastError(){ return m_iLastError; };
+ unsigned int id(){ return m_uId; };
+ KviConsole * console(){ return m_pConsole; };
+ KviIrcLink * link(){ return m_pLink; };
+#ifdef COMPILE_SSL_SUPPORT
+ bool usingSSL(){ return m_pSSL; };
+#else
+ bool usingSSL(){ return false; };
+#endif
+ unsigned int readBytes(){ return m_uReadBytes; };
+ unsigned int sentBytes(){ return m_uSentBytes; };
+ //unsigned int readPackets(){ return m_uReadPackets; };
+ unsigned int sentPackets(){ return m_uSentPackets; };
+ SocketState state(){ return m_state; };
+ bool isConnected(){ return m_state == Connected; };
+ int startConnection(KviIrcServer * srv,KviProxy * prx = 0,const char * bindAddress = 0);
+
+ //bool sendData(const char *buffer,int buflen = -1) KVI_DEPRECATED;
+ //bool sendFmtData(const char *fmt,...) KVI_DEPRECATED;
+ bool sendPacket(KviDataBuffer * pData);
+ void abort();
+ bool getLocalHostIp(QString &szIp,bool bIpV6);
+protected slots:
+ void connectionTimedOut();
+ void writeNotifierFired(int);
+ void readData(int);
+ void readProxyData(int);
+ void readHttpProxyErrorData(int);
+ void flushSendQueue();
+ void doSSLHandshake(int);
+protected:
+#ifdef COMPILE_SSL_SUPPORT
+ void raiseSSLError();
+ void printSSLPeerCertificate();
+ void printSSLCipherInfo();
+#endif
+ bool sendRawData(const char *buffer,int buflen);
+ void raiseError(int iError);
+ void connectionEstabilished();
+ void connectedToProxy();
+ void connectedToIrcServer();
+ void proxyLoginHttp();
+ void proxyLoginV4();
+ void proxyLoginV5();
+ void proxyAuthUserPassV5();
+ void proxySendTargetDataV5();
+ void proxyHandleV5AuthReply(unsigned char reply);
+ void proxyHandleV5MethodReply(unsigned char reply);
+ void proxyHandleV5FinalReply(unsigned char reply);
+ void proxyHandleV4FinalReply(unsigned char reply);
+ void proxyHandleHttpFinalReply(const char * buffer,int bufLen);
+ void linkUp();
+ void handleInvalidSocketRead(int readedLength);
+ virtual void reset();
+ void free_msgEntry(KviIrcSocketMsgEntry * e);
+ bool queue_removeMessage();
+ void queue_removeAllMessages();
+ virtual void queue_insertMessage(KviIrcSocketMsgEntry *msg_ptr);
+ virtual void setState(SocketState st);
+private:
+ void outputSSLMessage(const QString &szMsg);
+ void outputSSLError(const QString &szMsg);
+ void outputProxyMessage(const QString &szMsg);
+ void outputProxyError(const QString &szMsg);
+ void outputSocketMessage(const QString &szMsg);
+ void outputSocketWarning(const QString &szMsg);
+ void outputSocketError(const QString &szMsg);
+};
+
+#endif //_KVI_IRCSOCKET_H_
diff --git a/src/kvirc/kernel/kvi_ircurl.cpp b/src/kvirc/kernel/kvi_ircurl.cpp
new file mode 100644
index 00000000..5b443103
--- /dev/null
+++ b/src/kvirc/kernel/kvi_ircurl.cpp
@@ -0,0 +1,363 @@
+//
+// File : kvi_ircurl.cpp
+// Creation date : Sun Mar 04 2001 14:20:12 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+#define __KVIRC__
+#include "kvi_string.h"
+#include "kvi_inttypes.h"
+#include "kvi_qstring.h"
+#include "kvi_ircserver.h"
+#include "kvi_kvs_script.h"
+#include "kvi_msgbox.h"
+#include "kvi_channel.h"
+#include "kvi_app.h"
+#include "kvi_locale.h"
+#include "kvi_ircconnectiontarget.h"
+#include "kvi_ircconnection.h"
+#include "kvi_irccontext.h"
+#include "kvi_console.h"
+#include "kvi_frame.h"
+
+#define _KVI_IRCURL_CPP_
+#include "kvi_ircurl.h"
+
+
+bool KviIrcUrl::parse(const char * url,KviStr &cmdBuffer,int contextSpec)
+{
+ // irc[6]://<server>[:<port>][/<channel>[?<pass>]]
+ KviStr szUrl = url;
+ //szUrl.replaceAll("$","\\$");
+ //szUrl.replaceAll(";","\\;");
+ bool bIpV6 = false;
+ bool bSSL = false;
+ KviStr szServer;
+ kvi_u32_t uPort = 0;
+ bool bGotPort = false;
+ if(kvi_strEqualCIN(szUrl.ptr(),"irc://",6))
+ {
+ szUrl.cutLeft(6);
+ } else if(kvi_strEqualCIN(szUrl.ptr(),"irc6://",7))
+ {
+ bIpV6 = true;
+ szUrl.cutLeft(7);
+ } else if(kvi_strEqualCIN(szUrl.ptr(),"ircs://",7))
+ {
+ bSSL = true;
+ szUrl.cutLeft(7);
+ } else if(kvi_strEqualCIN(szUrl.ptr(),"ircs6://",8))
+ {
+ bIpV6 = true;
+ bSSL = true;
+ szUrl.cutLeft(8);
+ } else return false;
+
+ KviStr szServerAndPort;
+
+ int idx = szUrl.findFirstIdx('/');
+ if(idx != -1)
+ {
+ szServerAndPort = szUrl.left(idx);
+ szUrl.cutLeft(idx + 1);
+ } else {
+ szServerAndPort = szUrl;
+ szUrl = "";
+ }
+
+ if(szServerAndPort.isEmpty())return false;
+
+ idx = szServerAndPort.findFirstIdx(':');
+
+ if(idx != -1)
+ {
+ szServer = szServerAndPort.left(idx);
+ szServerAndPort.cutLeft(idx + 1);
+ bool bOk;
+ uPort = szServerAndPort.toUInt(&bOk);
+ if(!bOk)uPort = 6667;
+ bGotPort = true;
+ } else {
+ szServer = szServerAndPort;
+ }
+
+ cmdBuffer = "server ";
+ switch(contextSpec)
+ {
+ case KVI_IRCURL_CONTEXT_FIRSTFREE:
+ cmdBuffer.append("-u ");
+ break;
+ case KVI_IRCURL_CONTEXT_NEW:
+ cmdBuffer.append("-n ");
+ break;
+ }
+ if(bIpV6)cmdBuffer.append(" -i ");
+ if(bSSL)cmdBuffer.append(" -s ");
+
+ if(szUrl.hasData())
+ {
+ KviStr szChannel;
+ KviStr szPass;
+
+ idx = szUrl.findFirstIdx('?');
+ if(idx != -1)
+ {
+ szChannel = szUrl.left(idx);
+ szUrl.cutLeft(idx + 1);
+ szPass = szUrl;
+ } else {
+ szChannel = szUrl;
+ szPass = "";
+ }
+
+ if(!(szChannel.firstCharIs('#') || szChannel.firstCharIs('!') || szChannel.firstCharIs('&')))
+ szChannel.prepend('#');
+
+ if(szPass.isEmpty())cmdBuffer.append(KviStr::Format," -c=\"join %s\" ",szChannel.ptr());
+ else cmdBuffer.append(KviStr::Format," -c=\"join %s %s\" ",szChannel.ptr(),szPass.ptr());
+
+ }
+
+ cmdBuffer.append(szServer);
+ if(bGotPort)cmdBuffer.append(KviStr::Format," %d",uPort);
+
+ cmdBuffer.append(';');
+
+ return true;
+}
+
+void KviIrcUrl::split(QString url, KviIrcUrlParts& result)
+{
+ // irc[s][6]://<server>[:<port>][/<channel>[?<pass>]][[,<channel>[?<pass>]]
+
+ //defaults
+ result.bSsl=false;
+ result.bIpV6=false;
+ result.iPort = 6667;
+ result.iError=0;
+
+ int iProtoLen = url.find("://");
+ if(iProtoLen!=-1) {
+ if(KviQString::equalCIN(url,"irc",3)) {
+ // OK, seems to be a valid proto;
+ url = url.right(url.length()-3);
+ if(KviQString::equalCIN(url,"s",1)) {
+ result.bSsl=true;
+ url = url.right(url.length()-1);
+ }
+ if(KviQString::equalCIN(url,"6",1)) {
+ result.bIpV6=true;
+ url = url.right(url.length()-1);
+ }
+ if(!KviQString::equalCIN(url,"://",3)) {
+ //irc(???):// proto??
+ result.iError |= InvalidProtocol;
+ }
+ iProtoLen = url.find("://");
+ url = url.right(url.length()-iProtoLen-3);
+ } else {
+ result.iError |= InvalidProtocol;
+ }
+ }
+ //Ok, we understand a protocol.. Now we shuld find a server name:)
+ int iTmp;
+ iTmp = url.find(':');
+ if(iTmp!=-1) {
+ result.szHost = url.left(iTmp);
+ url = url.right(url.length()-iTmp-1);
+ // Accepted, now the time for the port:)
+ bool bOk;
+ if( (iTmp = url.find('/')) != -1) { // any channels pending?
+ result.iPort = url.left(iTmp).toUInt(&bOk);
+ if(!bOk) {
+ result.iPort = 6667;
+ result.iError |= InvalidPort;
+ }
+ url = url.right(url.length()-iTmp-1);
+ } else {
+ result.iPort = url.toUInt(&bOk);
+ if(!bOk) {
+ result.iPort = 6667;
+ result.iError |= InvalidPort;
+ }
+ url = "";
+ }
+ } else if( (iTmp = url.find('/')) != -1) { // have channels??
+ result.szHost = url.left(iTmp);
+ url = url.right(url.length()-iTmp-1);
+ } else {
+ result.szHost = url;
+ url = "";
+ }
+
+ //and, finally, channels:D
+
+ result.chanList = QStringList::split(',',url);
+
+}
+
+void KviIrcUrl::join(QString &uri, KviIrcServer* server)
+{
+ if(server)
+ {
+ uri="irc";
+
+ if(server->useSSL()) uri.append("s");
+ if(server->isIpV6()) uri.append("6");
+
+ uri.append("://");
+ uri.append(server->hostName());
+ if(server->port()!=6667) uri.append(QString(":%1").arg(server->port()));
+ uri.append("/");
+ }
+}
+
+void KviIrcUrl::makeJoinCmd(const QStringList& chans, QString& szJoinCommand)
+{
+ QString szChannels,szProtectedChannels,szPasswords,szCurPass,szCurChan;
+ if(chans.count()!=0)
+ {
+
+ for ( QStringList::ConstIterator it = chans.begin(); it != chans.end(); ++it ) {
+
+ szCurPass=(*it).section('?',1);
+ if(szCurPass.isEmpty())
+ {
+ if(!szChannels.isEmpty())
+ szChannels.append(",");
+ szCurChan = (*it).section('?',0,0);
+ if(!(szCurChan[0]=='#' || szCurChan[0]=='&' || szCurChan[0]=='!'))
+ szCurChan.prepend('#');
+ szChannels.append(szCurChan);
+ } else {
+ if(!szProtectedChannels.isEmpty())
+ szProtectedChannels.append(",");
+ szCurChan = (*it).section('?',0,0);
+ if(!(szCurChan[0]=='#' || szCurChan[0]=='&' || szCurChan[0]=='!'))
+ szCurChan.prepend('#');
+ szProtectedChannels.append(szCurChan);
+ if(!szPasswords.isEmpty())
+ szPasswords.append(",");
+ szPasswords.append(szCurPass);
+ }
+ }
+ szJoinCommand = "JOIN ";
+ szJoinCommand.append(szProtectedChannels);
+ if(!szProtectedChannels.isEmpty() && !szChannels.isEmpty())
+ szJoinCommand.append(',');
+ szJoinCommand.append(szChannels);
+ szJoinCommand.append(" ");
+ szJoinCommand.append(szPasswords);
+ }
+}
+
+int KviIrcUrl::run(const QString& text,int contextSpec,KviConsole* pConsole)
+{
+ KviIrcUrlParts parts;
+ KviIrcUrl::split(text,parts);
+ QString cmdBuffer;
+
+ if( (contextSpec & CurrentContext) && !pConsole) {
+ contextSpec = FirstFreeContext;
+ }
+
+ if( (contextSpec & TryCurrentContext) && !pConsole) {
+ contextSpec = FirstFreeContext;
+ }
+
+ if(contextSpec & FirstFreeContext) {
+ if(pConsole) {
+ if(pConsole->connectionInProgress())
+ {
+ pConsole = g_pFrame->firstNotConnectedConsole();
+ if(!pConsole) {
+ pConsole = g_pFrame->createNewConsole();
+ }
+ }
+ } else {
+ pConsole = g_pFrame->firstNotConnectedConsole();
+ if(!pConsole) {
+ pConsole = g_pFrame->createNewConsole();
+ }
+ }
+ }
+
+ if(!(parts.iError & KviIrcUrl::InvalidProtocol)) {
+ g_pApp->addRecentUrl(text);
+
+ QString szJoinCommand;
+ makeJoinCmd(parts.chanList,szJoinCommand);
+ QString szCommand("server ");
+ if(parts.bSsl) szCommand.append("-s ");
+ if(parts.bIpV6) szCommand.append("-i ");
+ if(!szJoinCommand.isEmpty()){
+ szCommand.append("-c=\"");
+ szCommand.append(szJoinCommand);
+ szCommand.append("\" ");
+ }
+ szCommand.append(QString("%1 %2 ").arg(parts.szHost).arg(parts.iPort));
+
+ if(pConsole->connection()) {
+ KviIrcServer* server = pConsole->connection()->target()->server();
+ if(
+ ( server->hostName() != parts.szHost ) ||
+ ( server->port() != parts.iPort ) ||
+ ( server->useSSL() != parts.bSsl ) ||
+ ( server->isIpV6() != parts.bIpV6) )
+ { // New server, try to reconnect
+ KviKvsScript::run(szCommand,(contextSpec & TryCurrentContext) ? g_pFrame->createNewConsole() : pConsole);
+ return parts.iError;
+ } else {
+ // the same server, but probably new chanlist
+ QString tmp;
+ QString toPart;
+ for(KviChannel * c = pConsole->connection()->channelList()->first();c;c = pConsole->connection()->channelList()->next())
+ {
+ tmp=c->name();
+ if(c->hasChannelKey()) {
+ tmp.append("?");
+ tmp.append(c->channelKey());
+ }
+ if(!parts.chanList.remove(tmp))
+ {
+ toPart.append(c->name());
+ toPart.append(",");
+ }
+ }
+ if(!(contextSpec & DoNotPartChans))
+ {
+ makeJoinCmd(parts.chanList,szJoinCommand);
+ if(!toPart.isEmpty())
+ {
+ toPart.prepend("part ");
+ KviKvsScript::run(toPart,pConsole);
+ }
+ }
+ if(!szJoinCommand.isEmpty())
+ {
+ pConsole->connection()->sendData(pConsole->connection()->encodeText(szJoinCommand).data());
+ }
+ return parts.iError;
+ }
+ }
+ // New server
+ KviKvsScript::run(szCommand,pConsole);
+ }
+ //!invalid proto
+ return parts.iError;
+}
diff --git a/src/kvirc/kernel/kvi_ircurl.h b/src/kvirc/kernel/kvi_ircurl.h
new file mode 100644
index 00000000..f3a8f10c
--- /dev/null
+++ b/src/kvirc/kernel/kvi_ircurl.h
@@ -0,0 +1,78 @@
+#ifndef _KVI_IRCURL_H_
+#define _KVI_IRCURL_H_
+
+//
+// File : kvi_ircurl.h
+// Creation date : Sun Mar 04 2001 14:22:55 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+#include "kvi_string.h"
+#include "kvi_inttypes.h"
+
+class KviIrcServer;
+class KviConsole;
+
+#include <qstringlist.h>
+
+// Create /server -u <server> commands (first free context)
+#define KVI_IRCURL_CONTEXT_FIRSTFREE 0
+// Create /server -n <server> commands (new irc context)
+#define KVI_IRCURL_CONTEXT_NEW 1
+// Create /server <server> commands (this irc context)
+#define KVI_IRCURL_CONTEXT_THIS 2
+
+typedef struct _KviIrcUrlParts {
+ QString szHost;
+ kvi_u32_t iPort;
+ bool bIpV6;
+ bool bSsl;
+ QStringList chanList;
+ int iError;
+ } KviIrcUrlParts;
+
+namespace KviIrcUrl
+{
+
+ enum KviIrcUrlParserError {
+ InvalidProtocol = 1,
+ InvalidPort = 2,
+ NeedNewContext = 4
+ };
+
+ enum KviIrcUrlContextSpec {
+ FirstFreeContext = 1,
+ NewContext = 2,
+ CurrentContext = 4,
+ TryCurrentContext = 8,
+
+ DoNotPartChans = 16
+ };
+
+ extern KVIRC_API bool parse(const char * url,KviStr &cmdBuffer,int contextSpec = KVI_IRCURL_CONTEXT_FIRSTFREE);
+
+ extern KVIRC_API int run(const QString& url,int contextSpec = FirstFreeContext,KviConsole* pConsole = 0);
+
+ extern KVIRC_API void split(QString url, KviIrcUrlParts& parts);
+ extern KVIRC_API void join(QString &url, KviIrcServer* server);
+ extern KVIRC_API void makeJoinCmd(const QStringList& chans, QString& szJoinCommand);
+}
+
+#endif // _KVI_IRCURL_H_
diff --git a/src/kvirc/kernel/kvi_lagmeter.cpp b/src/kvirc/kernel/kvi_lagmeter.cpp
new file mode 100644
index 00000000..5e7a4abe
--- /dev/null
+++ b/src/kvirc/kernel/kvi_lagmeter.cpp
@@ -0,0 +1,266 @@
+//=============================================================================
+//
+// File : kvi_lagmeter.cpp
+// Creation date : Fri Oct 18 13:31:36 CEST 2002 by Juanjo �varez
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_lagmeter.h"
+#include "kvi_options.h"
+#include "kvi_kvs_eventtriggers.h"
+#include "kvi_parameterlist.h"
+#include "kvi_ircconnection.h"
+#include "kvi_irccontext.h"
+#include "kvi_frame.h"
+#include "kvi_console.h"
+#include "kvi_time.h"
+#include "kvi_ircconnectionuserinfo.h"
+#include "kvi_ircconnectionserverinfo.h"
+#include "kvi_out.h"
+#include "kvi_locale.h"
+
+KviLagMeter::KviLagMeter(KviIrcConnection * c)
+: QObject()
+{
+ m_pConnection = c;
+ m_pCheckList = new KviPointerList<KviLagCheck>;
+ m_pCheckList->setAutoDelete(true);
+ m_uLag = 0;
+ m_uLastEmittedLag = 0;
+ m_uLastReliability = 0;
+ m_tLastCompleted = 0;
+ m_tLastOwnCheck = 0;
+ m_tFirstOwnCheck = 0;
+ m_bOnAlarm = false;
+ m_pDeletionSignal = 0;
+
+ // FIXME: We could use the KviIrcConnection::heartbeat() here!
+ if(KVI_OPTION_UINT(KviOption_uintLagMeterHeartbeat) < 2000)
+ KVI_OPTION_UINT(KviOption_uintLagMeterHeartbeat) = 2000; // kinda absurd
+
+ if(KVI_OPTION_UINT(KviOption_uintLagMeterHeartbeat) > 10000)
+ KVI_OPTION_UINT(KviOption_uintLagMeterHeartbeat) = 10000; // kinda absurd
+
+ startTimer(KVI_OPTION_UINT(KviOption_uintLagMeterHeartbeat)); // 5 seconds by default
+}
+
+KviLagMeter::~KviLagMeter()
+{
+ if(m_pDeletionSignal)*m_pDeletionSignal = true;
+#ifndef COMPILE_USE_QT4
+ killTimers();
+#endif
+ delete m_pCheckList;
+}
+
+unsigned int KviLagMeter::secondsSinceLastCompleted()
+{
+ struct timeval tv;
+ kvi_gettimeofday(&tv,0);
+ return tv.tv_sec - m_tLastCompleted;
+}
+
+void KviLagMeter::timerEvent(QTimerEvent *)
+{
+ if(m_pConnection->state() != KviIrcConnection::Connected)return; // do nothing atm
+
+ // If the lag has changed emit our signals
+ if((m_uLag / 10) != (m_uLastEmittedLag / 10))
+ {
+ m_uLastEmittedLag = m_uLag;
+ g_pFrame->childConnectionLagChange(m_pConnection);
+
+ KviStr szLag(KviStr::Format,"%u",m_uLag);
+
+ bool bDeletionSignal = false;
+ m_pDeletionSignal = &bDeletionSignal;
+
+ if((!m_bOnAlarm) && (m_uLag > KVI_OPTION_UINT(KviOption_uintLagAlarmTime)))
+ {
+ KVS_TRIGGER_EVENT_2_HALTED(KviEvent_OnLagAlarmTimeUp,
+ m_pConnection->console(),m_pConnection->serverInfo()->name(),QString(szLag.ptr()));
+ if(bDeletionSignal)return; // killed , probably by a quit -f -u
+ m_bOnAlarm = true;
+ } else if(m_bOnAlarm)
+ {
+ KVS_TRIGGER_EVENT_2_HALTED(KviEvent_OnLagAlarmTimeDown,
+ m_pConnection->console(),m_pConnection->serverInfo()->name(),QString(szLag.ptr()));
+ if(bDeletionSignal)return; // killed , probably by a quit -f -u
+ m_bOnAlarm = false;
+ }
+
+ KVS_TRIGGER_EVENT_2_HALTED(KviEvent_OnLagCheck,
+ m_pConnection->console(),m_pConnection->serverInfo()->name(),QString(szLag.ptr()));
+ if(bDeletionSignal)return; // killed , probably by a quit -f -u
+
+ m_pDeletionSignal = 0;
+ }
+
+ // get current time
+ struct timeval tv;
+ kvi_gettimeofday(&tv,0);
+ unsigned int uDiff = tv.tv_sec - m_tLastCompleted;
+ unsigned int uHeartbeat = KVI_OPTION_UINT(KviOption_uintLagMeterHeartbeat) / 1000;
+ if(uHeartbeat < 2)uHeartbeat = 2;
+ // we keep the last lag value for an amount of time
+ // depending on its reliability.
+ // Since reliability ranges from 10 to 100 we keep the lags
+ // for (hrtbt * 4) + (reliability / 2) seconds (which means from 25 to 70 seconds by default)
+ if(uDiff <= ((uHeartbeat * 4) + (m_uLastReliability / 2)))return; // nothing to do, the actual value is accurate
+
+ // the last completed check has been completed a lot of time ago
+ // do we have some checks on the queue ?
+ if(m_pCheckList->count() > 0)
+ {
+ // if the first registered check is not too outdated
+ // we wait a little more for it to return
+ KviLagCheck * c = m_pCheckList->first();
+ if(c)
+ {
+ if((tv.tv_sec - c->lSecs) <= 10)return;
+ }
+ // the first check was registered more than 10 secs before
+ if(m_tLastOwnCheck > 0)
+ {
+ // hm.. we have already sent our own (reliable) check after the last completed
+ // make the lag grow (we're pretty sure it's growing)
+ uDiff = (tv.tv_sec - m_tFirstOwnCheck) * 1000;
+ if(m_uLag < uDiff)m_uLag = uDiff; // the lag grows for sure
+ uDiff = tv.tv_sec - m_tLastOwnCheck;
+ if(uDiff < (uHeartbeat * 4))return; // wait a bit...send own checks only every 20 secs (by default) at this point
+ }
+ }
+ // or we have no checks in the queue at all
+ // or it's really time to do something...
+ if(m_tFirstOwnCheck == 0)
+ {
+ if(_OUTPUT_PARANOIC)
+ m_pConnection->console()->output(KVI_OUT_VERBOSE,__tr2qs("Sending out PING based lag probe"));
+
+ // this is the first our own lag check since the last succesfull one: use the ping
+ lagCheckRegister("@ping@",70); // the ping may be fooled easily
+ m_pConnection->sendFmtData("PING %s %s",
+ m_pConnection->encodeText( m_pConnection->userInfo()->nickName() ).data(),
+ m_pConnection->encodeText( m_pConnection->serverInfo()->name() ).data() );
+ m_tFirstOwnCheck = tv.tv_sec;
+ } else {
+ if(_OUTPUT_PARANOIC)
+ m_pConnection->console()->output(KVI_OUT_VERBOSE,__tr2qs("Sending out CTCP based lag probe"));
+
+ // we have already sent a ping but we got no reply
+ // try with another method... even if this will reset our idle time
+ KviStr tmp(KviStr::Format,"%d%d-yeah-:)",tv.tv_sec,tv.tv_usec);
+ lagCheckRegister(tmp.ptr(),100); // almost impossible to fool
+ m_pConnection->sendFmtData("NOTICE %s :%cLAGCHECK %s%c",
+ m_pConnection->encodeText( m_pConnection->userInfo()->nickName() ).data(),
+ 0x01,
+ tmp.ptr(),
+ 0x01);
+ }
+ m_tLastOwnCheck = tv.tv_sec;
+}
+
+void KviLagMeter::lagCheckRegister(const char * key,unsigned int uReliability)
+{
+ if(uReliability < 10)return; // what the heck of a lag check is this ?
+ // store the lagcheck structure and just return
+
+ if(_OUTPUT_PARANOIC)
+ m_pConnection->console()->output(KVI_OUT_VERBOSE,__tr2qs("Registered lag check with reliability %u (%s)"),uReliability,key);
+
+ KviLagCheck * c = new KviLagCheck;
+ c->szKey = key;
+ struct timeval tv;
+ kvi_gettimeofday(&tv,0);
+ c->lSecs = tv.tv_sec;
+ c->lUSecs = tv.tv_usec;
+ c->uReliability = uReliability <= 100 ? uReliability : 100;
+ m_pCheckList->append(c);
+ while(m_pCheckList->count() > 30)
+ {
+ // we're fried :/
+ // either our ping mechanism is not working
+ // or the server is stoned...
+ m_pCheckList->removeFirst();
+ }
+}
+
+bool KviLagMeter::lagCheckComplete(const char * key)
+{
+ // find this lag check
+ KviLagCheck * c;
+ for(c = m_pCheckList->first();c;c = m_pCheckList->next())
+ {
+ if(kvi_strEqualCS(c->szKey.ptr(),key))break;
+ }
+ if(!c)return false; // not found
+ // kill any earlier lag checks (IRC is a sequential proto)
+ while(m_pCheckList->first() != c)m_pCheckList->removeFirst();
+
+ if(_OUTPUT_PARANOIC)
+ m_pConnection->console()->output(KVI_OUT_VERBOSE,__tr2qs("Lag check completed (%s)"),key);
+
+ struct timeval tv;
+ kvi_gettimeofday(&tv,0);
+
+ unsigned int uLag = ((tv.tv_sec - c->lSecs) * 1000);
+ if(tv.tv_usec < c->lUSecs)uLag -= ((c->lUSecs - tv.tv_usec) / 1000);
+ else uLag += ((tv.tv_usec - c->lUSecs) / 1000);
+
+ // now check the reliability
+
+ if(m_uLastReliability > c->uReliability)
+ {
+ // the actual data is more reliable than the new one :/
+ // change the real lag only by a certain amount
+ // c->uRel : 100 = uLag : m_uLag
+ m_uLag = ((uLag * c->uReliability) + (m_uLag * m_uLastReliability)) / (c->uReliability + m_uLastReliability);
+ } else {
+ // the actual data is less reliable than the new one
+ m_uLag = uLag;
+ }
+
+ m_tLastCompleted = tv.tv_sec; // now
+ m_tLastOwnCheck = 0;
+ m_tFirstOwnCheck = 0;
+ m_uLastReliability = c->uReliability;
+
+ m_pCheckList->removeFirst();
+
+ return true;
+}
+
+void KviLagMeter::lagCheckAbort(const char * key)
+{
+ KviPointerList<KviLagCheck> l;
+ l.setAutoDelete(false);
+ KviLagCheck * c;
+
+ if(_OUTPUT_PARANOIC)
+ m_pConnection->console()->output(KVI_OUT_VERBOSE,__tr2qs("Lag check aborted (%s)"),key);
+
+ for(c = m_pCheckList->first();c;c = m_pCheckList->next())
+ if(kvi_strEqualCS(c->szKey.ptr(),key))l.append(c);
+ for(c = l.first();c;c = l.next())m_pCheckList->removeRef(c);
+}
+
+#include "kvi_lagmeter.moc"
diff --git a/src/kvirc/kernel/kvi_lagmeter.h b/src/kvirc/kernel/kvi_lagmeter.h
new file mode 100644
index 00000000..6fb68ae5
--- /dev/null
+++ b/src/kvirc/kernel/kvi_lagmeter.h
@@ -0,0 +1,74 @@
+#ifndef _KVI_LAGMETER_H_
+#define _KVI_LAGMETER_H_
+//=============================================================================
+//
+// File : kvi_lagmeter.h
+// Creation date : Fri Oct 18 13:30:26 CEST 2002 by Juanjo lvarez
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_string.h"
+#include "kvi_pointerlist.h"
+
+#include <qobject.h>
+
+class KviIrcConnection;
+
+class KviLagCheck
+{
+public:
+ KviStr szKey;
+ long lSecs; // since epoch
+ long lUSecs;
+ unsigned int uReliability; // [0-100]
+};
+
+class KVIRC_API KviLagMeter : public QObject
+{
+ Q_OBJECT
+ friend class KviIrcConnection;
+protected:
+ KviLagMeter(KviIrcConnection * c);
+ ~KviLagMeter();
+protected:
+ KviIrcConnection * m_pConnection;
+ unsigned int m_uLag; // last computed lag
+ unsigned int m_uLastEmittedLag; // last emitted lag
+ long m_tLastCompleted; // time when the last lag was completed (gettimeofday!)
+ unsigned int m_uLastReliability; // how much reliable was the last completed check ?
+ KviPointerList<KviLagCheck> * m_pCheckList;
+ long m_tFirstOwnCheck; // time when the first ping after a completed check was sent
+ long m_tLastOwnCheck; // time when the last ping was sent
+ bool m_bOnAlarm;
+ bool * m_pDeletionSignal; // we use this to signal our own delete
+public:
+ // lag checks should be done only against the user's server
+ // please make SURE that the key is unique!
+ void lagCheckRegister(const char * key,unsigned int uReliability = 50);
+ bool lagCheckComplete(const char * key);
+ void lagCheckAbort(const char * key);
+ unsigned int lag(){ return m_uLag; };
+ unsigned int secondsSinceLastCompleted();
+protected:
+ virtual void timerEvent(QTimerEvent * e);
+};
+
+#endif // _KVI_LAGMETER_H_
diff --git a/src/kvirc/kernel/kvi_main.cpp b/src/kvirc/kernel/kvi_main.cpp
new file mode 100644
index 00000000..90518b63
--- /dev/null
+++ b/src/kvirc/kernel/kvi_main.cpp
@@ -0,0 +1,412 @@
+//=============================================================================
+//
+// File : kvi_main.cpp
+// Creation date : Sun Jun 18 2000 12:38:45 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_app.h"
+#include "kvi_string.h"
+#include "kvi_settings.h"
+#include "kvi_ircurl.h"
+#include "kvi_defaults.h"
+#include "kvi_sourcesdate.h"
+#include "kvi_msgbox.h"
+
+#ifndef COMPILE_NO_IPC
+ extern bool kvi_sendIpcMessage(const char * message); // kvi_ipc.cpp
+#endif
+
+#include <qglobal.h> //for debug()
+
+#include <qmessagebox.h>
+
+#define KVI_ARGS_RETCODE_OK 0
+#define KVI_ARGS_RETCODE_ERROR 1
+#define KVI_ARGS_RETCODE_STOP 2
+
+typedef struct _ParseArgs
+{
+ int argc;
+ char ** argv;
+ char * configFile;
+ bool createFile;
+ bool bForceNewSession;
+ bool bShowPopup;
+ bool bShowSplashScreen;
+ bool bExecuteCommandAndClose;
+ KviStr szExecCommand;
+ KviStr szExecRemoteCommand;
+} ParseArgs;
+
+int parseArgs(ParseArgs * a)
+{
+ KviStr szServer;
+ KviStr szPort;
+ int idx;
+
+ if(a->argc < 2)return KVI_ARGS_RETCODE_OK;
+
+ for(idx = 1;idx < a->argc;idx++)
+ {
+ QString szMessage;
+ char * p = a->argv[idx];
+
+ if((kvi_strLen(p) > 3) && (*p == '-') && (*(p+1) == '-'))p++;
+
+ if(kvi_strEqualCI("-v",p) || kvi_strEqualCI("-version",p))
+ {
+ KviQString::appendFormatted(szMessage,"KVIrc %s '%s'\n",KVI_VERSION,KVI_RELEASE_NAME);
+ KviQString::appendFormatted(szMessage,"Sources date: %s\n",KVI_SOURCES_DATE);
+ KviQString::appendFormatted(szMessage,"Build date: %s\n",KVI_BUILD_DATE);
+ KviQString::appendFormatted(szMessage,"Home page: http://www.kvirc.net/\n");
+
+#ifdef COMPILE_ON_WINDOWS
+ MessageBox(0,szMessage.local8Bit().data(),"KVIrc",0);
+#else
+ debug(szMessage);
+#endif
+
+ return KVI_ARGS_RETCODE_STOP;
+ }
+
+ if(kvi_strEqualCI("-h",p) || kvi_strEqualCI("-help",p))
+ {
+ KviQString::appendFormatted(szMessage,"Usage:\n");
+ KviQString::appendFormatted(szMessage," %s [options] [server [port]] [ircurl [ircurl [...]]]\n",a->argv[0]);
+ KviQString::appendFormatted(szMessage," \n");
+ KviQString::appendFormatted(szMessage,"Available options:\n");
+ KviQString::appendFormatted(szMessage," -h, --help : Print this help and exit\n");
+ KviQString::appendFormatted(szMessage," -v, --version: Print version information and exit\n");
+ KviQString::appendFormatted(szMessage," -c <file> : Use <file> as config file instead of ~/%s\n",KVI_HOME_CONFIG_FILE_NAME);
+ KviQString::appendFormatted(szMessage," (defaults to $HOME/%s if <file> does not exist)\n",KVI_HOME_CONFIG_FILE_NAME);
+ KviQString::appendFormatted(szMessage," -n <file> : Use <file> as config file instead of $HOME/%s\n",KVI_HOME_CONFIG_FILE_NAME);
+ KviQString::appendFormatted(szMessage," (create <file> if it does not exist)\n");
+#ifdef COMPILE_NO_IPC
+ KviQString::appendFormatted(szMessage," -f : Accepted but ignored (for compatibility)\n");
+#else
+ KviQString::appendFormatted(szMessage," -f : Force a new KVIrc session, even if there is already\n");
+ KviQString::appendFormatted(szMessage," a running one.\n");
+#endif
+ KviQString::appendFormatted(szMessage," -e <commands>: If a KVIrc session is already running, execute\n");
+ KviQString::appendFormatted(szMessage," the <commands> in that session, otherwise start up\n");
+ KviQString::appendFormatted(szMessage," normally and execute <commands>\n");
+ KviQString::appendFormatted(szMessage," <commands> must be a single shell token.\n");
+ KviQString::appendFormatted(szMessage," You can eventually use this switch more than once\n");
+ KviQString::appendFormatted(szMessage," -x <commands>: If a KVIrc session is already running, execute\n");
+ KviQString::appendFormatted(szMessage," the <commands> in that session, otherwise exit from application without doing anything/\n");
+ KviQString::appendFormatted(szMessage," <commands> must be a single shell token.\n");
+ KviQString::appendFormatted(szMessage," You can eventually use this switch more than once\n");
+ KviQString::appendFormatted(szMessage," -r <commands>: If a KVIrc session is already running, execute the <commands>\n");
+ KviQString::appendFormatted(szMessage," in that session, otherwise start up normally (do not execute).\n");
+ KviQString::appendFormatted(szMessage," <commands> must be a single shell token.\n");
+ KviQString::appendFormatted(szMessage," You can eventually use this switch more than once\n");
+ KviQString::appendFormatted(szMessage," -m : If a KVIrc session is already running, show an informational\n");
+ KviQString::appendFormatted(szMessage," popup dialog instead of writing to the console");
+ KviQString::appendFormatted(szMessage," --nosplash : Do not show the splash screen at startup\n");
+ KviQString::appendFormatted(szMessage," [server] : Connect to this server after startup\n");
+ KviQString::appendFormatted(szMessage," [port] : Use this port for connection\n");
+ KviQString::appendFormatted(szMessage," [ircurl] : URL in the following form:\n");
+ KviQString::appendFormatted(szMessage," irc[6]://<server>[:<port>][/<channel>[?<pass>]]\n");
+
+#ifdef COMPILE_ON_WINDOWS
+ MessageBox(0,szMessage.local8Bit().data(),"KVIrc",0);
+#else
+ debug(szMessage);
+#endif
+ return KVI_ARGS_RETCODE_STOP;
+ }
+
+ if(kvi_strEqualCI("-c",p))
+ {
+ idx++;
+ if(idx >= a->argc)
+ {
+ debug("Option -c requires a config file name");
+ return KVI_ARGS_RETCODE_ERROR;
+ }
+ p = a->argv[idx];
+ a->configFile = p;
+ debug("Using file %s as config",p);
+ continue;
+ }
+
+ if(kvi_strEqualCI("-e",p))
+ {
+ idx++;
+ if(idx >= a->argc)
+ {
+ debug("Option -e requires a command");
+ return KVI_ARGS_RETCODE_ERROR;
+ }
+ p = a->argv[idx];
+ if(a->szExecCommand.hasData())a->szExecCommand.append("\n");
+ a->szExecCommand.append(p);
+ continue;
+ }
+
+ if(kvi_strEqualCI("-x",p))
+ {
+ idx++;
+ if(idx >= a->argc)
+ {
+ debug("Option -x requires a command");
+ return KVI_ARGS_RETCODE_ERROR;
+ }
+ p = a->argv[idx];
+ if(a->szExecCommand.hasData())a->szExecCommand.append("\n");
+ a->szExecCommand.append(p);
+ a->bExecuteCommandAndClose=true;
+ continue;
+ }
+
+ if(kvi_strEqualCI("-r",p))
+ {
+ idx++;
+ if(idx >= a->argc)
+ {
+ debug("Option -r requires a command");
+ return KVI_ARGS_RETCODE_ERROR;
+ }
+ p = a->argv[idx];
+ if(a->szExecRemoteCommand.hasData())a->szExecRemoteCommand.append("\n");
+ a->szExecRemoteCommand.append(p);
+ continue;
+ }
+
+ if(kvi_strEqualCI("-m",p))
+ {
+ a->bShowPopup = true;
+ continue;
+ }
+
+ if(kvi_strEqualCI("-n",p))
+ {
+ idx++;
+ if(idx >= a->argc)
+ {
+ debug("Option -n requires a config file name");
+ return KVI_ARGS_RETCODE_ERROR;
+ }
+ p = a->argv[idx];
+ a->configFile = p;
+ a->createFile=true;
+ debug("Using file %s as config",p);
+ continue;
+ }
+
+ if(kvi_strEqualCI("-nosplash",p))
+ {
+ a->bShowSplashScreen = false;
+ continue;
+ }
+
+ if(kvi_strEqualCI("-f",p))
+ {
+ a->bForceNewSession = true;
+ continue;
+ }
+
+ if(kvi_strEqualCI("-session",p)||kvi_strEqualCI("-display",p))
+ {
+ // Qt apps are supposed to handle the params to these switches, but we'll skip arg for now
+ idx++;
+ continue;
+ }
+
+ if(*p != '-')
+ {
+ // no dash
+ if(kvi_strEqualCIN(p,"irc://",6) || kvi_strEqualCIN(p,"irc6://",7) || kvi_strEqualCIN(p,"ircs://",7) || kvi_strEqualCIN(p,"ircs6://",8))
+ {
+ KviStr tmp = QString::fromLocal8Bit(p);
+ if(a->szExecCommand.hasData())a->szExecCommand.append('\n');
+ a->szExecCommand.append("openurl ");
+ tmp.replaceAll("$",""); // the urls can't contain $ signs
+ tmp.replaceAll(";",""); // the urls can't contain ; signs
+ a->szExecCommand.append(tmp);
+ } else {
+ QString tmp = QString::fromLocal8Bit(p);
+ bool bOk;
+ tmp.toUInt(&bOk);
+ if(bOk)szPort = tmp;
+ else {
+ QString ri = tmp.right(4);
+ if(KviQString::equalCI(ri,".kvs"))
+ {
+ if(a->szExecCommand.hasData())a->szExecCommand.append('\n');
+ a->szExecCommand.append("parse \"");
+ tmp.replace('$',"\\$");
+ tmp.replace('\\',"\\\\");
+ a->szExecCommand.append(tmp);
+ a->szExecCommand.append('"');
+ } else if(KviQString::equalCI(ri,".kvt"))
+ {
+ if(a->szExecCommand.hasData())a->szExecCommand.append('\n');
+ a->szExecCommand.append("theme.install \"");
+ tmp.replace('$',"\\$");
+ tmp.replace('\\',"\\\\");
+ a->szExecCommand.append(tmp);
+ a->szExecCommand.append('"');
+ } else
+ szServer = tmp; // assume a plain server name
+ }
+ }
+ }
+ }
+
+ if(szServer.hasData())
+ {
+ if(a->szExecCommand.hasData())a->szExecCommand.append('\n');
+ a->szExecCommand.append("server -u ");
+ a->szExecCommand.append(szServer);
+ if(szPort.hasData())
+ {
+ a->szExecCommand.append(' ');
+ a->szExecCommand.append(szPort);
+ }
+ }
+
+ return KVI_ARGS_RETCODE_OK;
+}
+
+#if defined(Q_OS_MACX) && (__GNUC__ == 3 && __GNUC_MINOR__ == 3)
+// Repair broken colour definitions due to "lazy" static object initialization
+void repair_colors(void)
+{
+ if(Qt::white.red() == 0)
+ {
+ Qt::color0 = (qRgb(255,255,255 ),0);
+ Qt::color1 = (qRgb(0,0,0),1);
+ Qt::black.setRgb(0,0,0);
+ Qt::white.setRgb(255,255,255);
+ Qt::darkGray.setRgb(128,128,128);
+ Qt::gray.setRgb(160,160,164);
+ Qt::lightGray.setRgb(192,192,192);
+ Qt::red.setRgb(255,0,0);
+ Qt::green.setRgb(0,255,0);
+ Qt::blue.setRgb(0,0,255);
+ Qt::cyan.setRgb(0,255,255);
+ Qt::magenta.setRgb(255,0,255);
+ Qt::yellow.setRgb(255,255,0);
+ Qt::darkRed.setRgb(128,0,0);
+ Qt::darkGreen.setRgb(0,128,0);
+ Qt::darkBlue.setRgb(0,0,128);
+ Qt::darkCyan.setRgb(0,128,128);
+ Qt::darkMagenta.setRgb(128,0,128);
+ Qt::darkYellow.setRgb(128,128,0);
+ }
+}
+#endif //Q_OS_MACX
+
+int main(int argc,char ** argv)
+{
+
+#if defined(Q_OS_MACX) && (__GNUC__ == 3 && __GNUC_MINOR__ == 3)
+ repair_colors();
+#endif //Q_OS_MACX
+
+ ParseArgs a;
+ a.argc = argc;
+ a.argv = argv;
+ a.configFile = 0;
+ a.createFile = false;
+ a.bForceNewSession = false;
+ a.bShowPopup = false,
+ a.bShowSplashScreen = true;
+ a.bExecuteCommandAndClose = false;
+
+ int retCode = parseArgs(&a);
+
+ if(retCode != KVI_ARGS_RETCODE_OK)return ((retCode == KVI_ARGS_RETCODE_ERROR) ? (-1) : 0);
+
+ // Need to have the X socket open before IPC startup
+ KviApp * theApp = new KviApp(argc,argv);
+
+ KviStr szRemoteCommand = a.szExecCommand;
+ if(a.szExecRemoteCommand.hasData())
+ {
+ if(szRemoteCommand.hasData())szRemoteCommand.append('\n');
+ szRemoteCommand.append(a.szExecRemoteCommand);
+ }
+
+ /*
+ FIXME: There is a race condition in the IPC mechanism.
+ If one starts two instances of kvirc one immediately after another
+ then both instances may run through kvi_sendIpcMessage
+ without finding the sentinel window and thus both may decide
+ to start.
+ A weak file locking mechanism should be used too...
+
+#ifdef COMPILE_ON_WINDOWS
+ QString szLock = convertSeparators(cleanDirPath(QDir::homeDirPath() + "/.kvirc.lock"));
+#else
+ QString szLock = convertSeparators(cleanDirPath(QDir::homeDirPath() + "/.kvirc.lock"));
+#endif
+
+ QFileInfo inf(szLock);
+ bool bLocked = false;
+ if(inf.exists())
+ {
+ iLocked = inf.lastModified().secsTo(QDateTime::currentDateTime());
+ }
+ */
+
+#ifndef COMPILE_NO_IPC
+ if(!a.bForceNewSession)
+ {
+ // here we could use CreateMutex on win and semget() on linux
+ // in order to get a shared semaphore to ensure instance unicity.
+
+ if(kvi_sendIpcMessage(szRemoteCommand.ptr()))
+ {
+ if(szRemoteCommand.isEmpty())
+ {
+ KviStr tmp(KviStr::Format,"Another KVIrc session is already running on this display and with this user id.\nUse %s -f if you want to force a new session.",argv[0]);
+ if(a.bShowPopup)
+ QMessageBox::information(0,"Session - KVIrc",tmp.ptr(),QMessageBox::Ok);
+ else
+ debug(tmp.ptr());
+ }
+ delete theApp;
+ return 0;
+ } else if(a.bExecuteCommandAndClose) {
+ delete theApp;
+ return 0;
+ }
+ }
+#endif
+
+ theApp->m_bCreateConfig = a.createFile;
+ theApp->m_szConfigFile = a.configFile;
+ theApp->m_szExecAfterStartup = a.szExecCommand;
+ theApp->m_bShowSplashScreen = a.bShowSplashScreen;
+ theApp->setup();
+
+ // YEAH!
+ int retVal = theApp->exec();
+ // :)
+
+ delete theApp;
+ theApp = 0;
+ return retVal;
+}
diff --git a/src/kvirc/kernel/kvi_notifylist.cpp b/src/kvirc/kernel/kvi_notifylist.cpp
new file mode 100644
index 00000000..bee7fd43
--- /dev/null
+++ b/src/kvirc/kernel/kvi_notifylist.cpp
@@ -0,0 +1,1277 @@
+//=============================================================================
+//
+// File : kvi_notifylist.cpp
+// Creation date : Fri Oct 27 2000 23:41:01 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+
+#include "kvi_debug.h"
+#include "kvi_notifylist.h"
+#include "kvi_console.h"
+#include "kvi_ircsocket.h"
+#include "kvi_regusersdb.h"
+#include "kvi_userlistview.h"
+#include "kvi_channel.h"
+#include "kvi_options.h"
+#include "kvi_window.h"
+#include "kvi_locale.h"
+#include "kvi_out.h"
+#include "kvi_sparser.h"
+#include "kvi_ircmask.h"
+#include "kvi_numeric.h"
+#include "kvi_parameterlist.h"
+#include "kvi_ircconnection.h"
+#include "kvi_app.h"
+#include "kvi_qstring.h"
+#include "kvi_lagmeter.h"
+#include "kvi_kvs_eventtriggers.h"
+#include "kvi_qcstring.h"
+
+#include <qstringlist.h>
+
+// FIXME: #warning "Finish this doc!"
+
+/*
+ @doc: notify_list
+ @title:
+ Notify lists
+ @short:
+ Tracking users on IRC
+ @keyterms:
+ notify property, watch property, notify lists
+ @body:
+ The notify list is a means of keeping track of users on IRC.[br]
+ Once connected to an IRC server, you can tell KVIrc to check
+ periodically if your friends are online.[br]
+ This is basically achieved by setting a property in the [doc:registered_users]registered users database[/doc]
+ entry.[br]
+ The property is called "notify", and you have to set it to the nickname
+ that you want to look for.[br]
+ So for example, assume to register a frend of yours like Szymon:[br]
+ [example]
+ [cmd:reguser.add]reguser.add[/cmd] Szymon
+ [cmd:reguser.addmask]reguser.addmask[/cmd] Szymon Pragma!*@*.it
+ [/example]
+ And then want it in the notify list; nothing easier, just set
+ hist "notify" property to the nickname that you want him to be "looked for":[br]
+ [example]
+ [cmd:reguser.setproperty]reguser.setproperty[/cmd] Szymon notify Pragma
+ [/example]
+ In this way, once in a while, KVIrc will send to the server an ISON message
+ with the nickname Pragma. If Szymon is online, you will be notified with a message:[br]
+ "Pragma [someuser@somehost.it] is on IRC".[br]
+ If Szymon uses often "[Pragma]" as his secondary nickname , you can do the following:[br]
+ [example]
+ [cmd:reguser.addmask]reguser.addmask[/cmd] Szymon [Pragma]*@*.it
+ [cmd:reguser.setproperty]reguser.setproperty[/cmd] Szymon notify "Pragma [Pragma]"
+ [/example]
+ KVIrc will then look for both nicknames getting online.[br]
+ KVIrc supports three notify lists management methods:[br]
+ The "stupid ISON method", the "intelligent ISON method" and the "WATCH method".[br]
+ The "stupid ISON method" will assume that Szymon is online if any user with nickname
+ Pragma (or [Pragma] in the second example) gets online; this means that also Pragma!someuser@somehost.com will be
+ assumed to be "Szymon" and will be shown in the notify list.[br]
+ This might be a false assumption (since somehod.com does not even match *.it),
+ but it is the best result that the "stupid ISON method" can achieve.[br]
+ The "intelligent ISON method" will also check the Pragma's username and hostname
+ and match it in the registered masks; so in the example above, you will be notified if
+ any user that matches Pragma!*@*.it gets online; (but you will NOT be notified if
+ (for example) Pragma!someuser@somehost.com gets online).[br]
+ So what's the point in including a stupid method? :) Well...the intelligent
+ method "eats" some of your IRC bandwidth; it has to send USERHOST messages
+ for every group of 5 users in the notify list. If you have a lot of users
+ in the notify list, it might become slow and eventually cause a
+ client to server flood.[br]
+ So finally, the intelligent method is the default. If you have "flood" problems,
+ or if you think that the notify list is quite slow , try the "stupid" method:
+ it is not that bad after all.[br]
+ The third notify list management method is the "WATCH method".[br]
+ It uses a totally different (and better) approach to the notify lists management,
+ and can be used only on the networks that support the WATCH notify method (DALnet, WebNet, etc.).[br]
+ KVIrc will attempt to guess if the server you're currently using supports the WATCH command
+ and eventually use this last method.[br]
+ The WATCH method uses the "notify" property to get the nicknames that have to be
+ sent to the server in the /WATCH commands.
+*/
+
+// Basic NotifyListManager: this does completely nothing
+
+KviNotifyListManager::KviNotifyListManager(KviIrcConnection * pConnection)
+: QObject(0,"notify_list_manager")
+{
+ m_pConnection = pConnection;
+ m_pConsole = pConnection->console();
+}
+
+KviNotifyListManager::~KviNotifyListManager()
+{
+}
+
+void KviNotifyListManager::start()
+{
+}
+
+void KviNotifyListManager::stop()
+{
+}
+
+bool KviNotifyListManager::handleUserhost(KviIrcMessage *)
+{
+ return false;
+}
+
+bool KviNotifyListManager::handleIsOn(KviIrcMessage *)
+{
+ return false;
+}
+
+bool KviNotifyListManager::handleWatchReply(KviIrcMessage *)
+{
+ return false;
+}
+
+void KviNotifyListManager::notifyOnLine(const QString &nick,const QString &user,const QString &host,const QString &szReason,bool bJoin)
+{
+ if(bJoin)
+ m_pConsole->notifyListView()->join(nick,user,host);
+
+ KviWindow * out = KVI_OPTION_BOOL(KviOption_boolNotifyListChangesToActiveWindow) ? m_pConsole->activeWindow() : m_pConsole;
+ if(KVS_TRIGGER_EVENT_1_HALTED(KviEvent_OnNotifyOnLine,out,nick))return;
+
+ QString szWho;
+ QString szMsg;
+
+ if(!(user.isEmpty() || host.isEmpty()))
+ KviQString::sprintf(szWho,"\r!n\r%Q\r [%Q@\r!h\r%Q\r]",&nick,&user,&host);
+ else
+ KviQString::sprintf(szWho,"\r!n\r%Q\r",&nick);
+
+ KviPointerHashTable<QString,KviRegisteredUser> * d = g_pRegisteredUserDataBase->userDict();
+ KviPointerHashTableIterator<QString,KviRegisteredUser> it(*d);
+ QString szNotify;
+
+ while(KviRegisteredUser * u = it.current())
+ {
+ if(QStringList::split(",",u->getProperty("notify")).findIndex(nick)!=-1)
+ {
+ QString szComment=u->getProperty("comment");
+ if(!szComment.isEmpty())
+ KviQString::sprintf(szMsg,"%Q (%Q), Group \"%Q\" is on IRC as (%Q)",&(u->name()),&szComment,&(u->group()),&szWho);
+ else
+ KviQString::sprintf(szMsg,"%Q, Group \"%Q\" is on IRC as (%Q)",&(u->name()),&(u->group()),&szWho);
+ break;
+ }
+ ++it;
+ }
+ QString szFmt = __tr2qs("%Q is on IRC");
+
+ if(szMsg.isEmpty())
+ KviQString::sprintf(szMsg,szFmt,&szWho);
+
+ if((!szReason.isEmpty()) && (_OUTPUT_VERBOSE))
+ {
+ szMsg += "(";
+ szMsg += szReason;
+ szMsg += ")";
+ }
+
+ out->outputNoFmt(KVI_OUT_NOTIFYONLINE,szMsg);
+
+ if(!(out->hasAttention()))
+ {
+ if(KVI_OPTION_BOOL(KviOption_boolFlashWindowOnNotifyOnLine))
+ out->demandAttention();
+ if(KVI_OPTION_BOOL(KviOption_boolPopupNotifierOnNotifyOnLine))
+ {
+ szWho = "<b>";
+ szWho += nick;
+ szWho += "</b>";
+ KviQString::sprintf(szMsg,szFmt,&szWho);
+ g_pApp->notifierMessage(0,KVI_OPTION_MSGTYPE(KVI_OUT_NOTIFYONLINE).pixId(),szMsg,15);
+ }
+ }
+}
+
+void KviNotifyListManager::notifyOffLine(const QString &nick,const QString &user,const QString &host,const QString &szReason)
+{
+ KviWindow * out = KVI_OPTION_BOOL(KviOption_boolNotifyListChangesToActiveWindow) ? m_pConsole->activeWindow() : m_pConsole;
+ if(!KVS_TRIGGER_EVENT_1_HALTED(KviEvent_OnNotifyOffLine,out,nick))
+ {
+ QString szWho;
+
+ if(!(user.isEmpty() || host.isEmpty()))
+ KviQString::sprintf(szWho,"\r!n\r%Q\r [%Q@\r!h\r%Q\r]",&nick,&user,&host);
+ else
+ KviQString::sprintf(szWho,"\r!n\r%Q\r",&nick);
+
+ QString szMsg;
+
+ KviPointerHashTable<QString,KviRegisteredUser> * d = g_pRegisteredUserDataBase->userDict();
+ KviPointerHashTableIterator<QString,KviRegisteredUser> it(*d);
+ QString szNotify;
+
+ while(KviRegisteredUser * u = it.current())
+ {
+ if(QStringList::split(",",u->getProperty("notify")).findIndex(nick)!=-1)
+ {
+ QString szComment=u->getProperty("comment");
+ if(!szComment.isEmpty())
+ KviQString::sprintf(szMsg,"%Q (%Q), Group \"%Q\" has left IRC as (%Q)",&(u->name()),&szComment,&(u->group()),&szWho);
+ else
+ KviQString::sprintf(szMsg,"%Q, Group \"%Q\" has left IRC as (%Q)",&(u->name()),&(u->group()),&szWho);
+ break;
+ }
+ ++it;
+ }
+
+ if(szMsg.isEmpty())
+ KviQString::sprintf(szMsg,__tr2qs("%Q has left IRC"),&szWho);
+
+ if((!szReason.isEmpty()) && (_OUTPUT_VERBOSE))
+ {
+ szMsg += "(";
+ szMsg += szReason;
+ szMsg += ")";
+ }
+
+ out->outputNoFmt(KVI_OUT_NOTIFYOFFLINE,szMsg);
+ }
+
+ m_pConsole->notifyListView()->part(nick);
+}
+
+
+
+//
+// INTELLIGENT NOTIFY LIST MANAGER: NOTIFY PROCESS:
+//
+// start() stop()
+// | ^
+// buildRegUserDict() |
+// | |
+// m_pRegUserDict->isEmpty() ? -- YES ---------->+
+// | |
+// NO |
+// | |
+// newNotifySession()<------- TIMER ---------------- delayedNotifySession() --------------------------------+
+// | (can be stopped here) | ^ |
+// | | ^ |
+// buildNotifyList() | | YES
+// | | | |
+// m_pNotifyList->isEmpty() ? - YES ->+ | |
+// | | |
+// NO | |
+// | | |
+// newIsOnSession()<------------- TIMER -------------------- delayedIsOnSession() -- NO - m_pNotifyList->isEmpty() ?
+// | (can be stopped here) | |
+// | | |
+// buildIsOnList() | |
+// | | |
+// m_pIsOnList->isEmpty() ? -- YES ---------->+ |
+// | |
+// NO |
+// | |
+// sendIsOn() - - - - - - - - - - - -> handleIsOn() |
+// | |
+// (build m_pOnlineList) |
+// | |
+// m_pOnlineList->isEmpty() ? - YES ----------------------->+
+// | |
+// NO YES
+// | |
+// delayedUserhostSession()<--------------- NO - m_pOnlineList->isEmpty() ?
+// | ^
+// TIMER (can be stopped here) |
+// | |
+// newUserhostSession() |
+// | |
+// buildUserhostList() |
+// | |
+// m_pUserhostList->isEmpty() ? - YES --->+
+// | ^^^ |
+// | (unexpected!)||| |
+// NO |
+// | |
+// sendUserhost() - - - - - - - - > handleUserhost()
+//
+
+
+KviIsOnNotifyListManager::KviIsOnNotifyListManager(KviIrcConnection * pConnection)
+: KviNotifyListManager(pConnection)
+{
+ m_pRegUserDict = new KviPointerHashTable<QString,QString>(17,false); // case insensitive , copy keys
+ m_pRegUserDict->setAutoDelete(true);
+ m_pNotifyList = new KviPointerList<QString>;
+ m_pNotifyList->setAutoDelete(true);
+ m_pIsOnList = new KviPointerList<QString>;
+ m_pIsOnList->setAutoDelete(true);
+ m_pOnlineList = new KviPointerList<QString>;
+ m_pOnlineList->setAutoDelete(true);
+ m_pUserhostList = new KviPointerList<QString>;
+ m_pUserhostList->setAutoDelete(true);
+ m_pDelayedNotifyTimer = new QTimer();
+ connect(m_pDelayedNotifyTimer,SIGNAL(timeout()),this,SLOT(newNotifySession()));
+ m_pDelayedIsOnTimer = new QTimer();
+ connect(m_pDelayedIsOnTimer,SIGNAL(timeout()),this,SLOT(newIsOnSession()));
+ m_pDelayedUserhostTimer = new QTimer();
+ connect(m_pDelayedUserhostTimer,SIGNAL(timeout()),this,SLOT(newUserhostSession()));
+ m_bRunning = false;
+}
+
+
+KviIsOnNotifyListManager::~KviIsOnNotifyListManager()
+{
+ if(m_bRunning)stop();
+ delete m_pDelayedNotifyTimer;
+ delete m_pDelayedIsOnTimer;
+ delete m_pDelayedUserhostTimer;
+ delete m_pRegUserDict;
+ delete m_pOnlineList;
+ delete m_pNotifyList;
+ delete m_pIsOnList;
+ delete m_pUserhostList;
+}
+
+void KviIsOnNotifyListManager::start()
+{
+ if(m_bRunning)stop();
+ m_bRunning = true;
+ m_pConsole->notifyListView()->partAllButOne(m_pConnection->currentNickName());
+
+ m_bExpectingIsOn = false;
+ m_bExpectingUserhost = false;
+
+ buildRegUserDict();
+ if(m_pRegUserDict->isEmpty())
+ {
+ if(_OUTPUT_VERBOSE)
+ m_pConsole->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Notify list: No users to check for, quitting"));
+ stop();
+ return;
+ }
+ newNotifySession();
+}
+
+void KviIsOnNotifyListManager::buildRegUserDict()
+{
+ m_pRegUserDict->clear();
+
+ const KviPointerHashTable<QString,KviRegisteredUser> * d = g_pRegisteredUserDataBase->userDict();
+ KviPointerHashTableIterator<QString,KviRegisteredUser> it(*d);
+ while(KviRegisteredUser * u = it.current())
+ {
+ QString notify;
+ if(u->getProperty("notify",notify))
+ {
+ notify.stripWhiteSpace();
+ while(!notify.isEmpty())
+ {
+ int idx = notify.find(' ');
+ if(idx > 0)
+ {
+ QString single = notify.left(idx);
+ m_pRegUserDict->replace(single,new QString(u->name()));
+ notify.remove(0,idx+1);
+ } else {
+ m_pRegUserDict->replace(notify,new QString(u->name()));
+ notify = "";
+ }
+ }
+ }
+ ++it;
+ }
+}
+
+void KviIsOnNotifyListManager::delayedNotifySession()
+{
+ unsigned int iTimeout = KVI_OPTION_UINT(KviOption_uintNotifyListCheckTimeInSecs);
+ if(iTimeout < 15)
+ {
+ // life first of all.
+ // don't allow the user to suicide
+ if(_OUTPUT_VERBOSE)
+ m_pConsole->output(KVI_OUT_SYSTEMWARNING,
+ __tr2qs("Notify list: Timeout (%d sec) is too short, resetting to something more reasonable (15 sec)"),
+ iTimeout);
+ iTimeout = 15;
+ KVI_OPTION_UINT(KviOption_uintNotifyListCheckTimeInSecs) = 15;
+ }
+ m_pDelayedNotifyTimer->start(iTimeout * 1000,true);
+}
+
+void KviIsOnNotifyListManager::newNotifySession()
+{
+ buildNotifyList();
+ if(m_pNotifyList->isEmpty())
+ {
+ if(_OUTPUT_VERBOSE)
+ m_pConsole->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Notify list: Notify list empty, quitting"));
+ stop();
+ return;
+ }
+ newIsOnSession();
+}
+
+void KviIsOnNotifyListManager::buildNotifyList()
+{
+ m_pNotifyList->clear();
+ KviPointerHashTableIterator<QString,QString> it(*m_pRegUserDict);
+ while(it.current())
+ {
+ m_pNotifyList->append(new QString(it.currentKey()));
+ ++it;
+ }
+}
+
+void KviIsOnNotifyListManager::delayedIsOnSession()
+{
+ unsigned int iTimeout = KVI_OPTION_UINT(KviOption_uintNotifyListIsOnDelayTimeInSecs);
+ if(iTimeout < 5)
+ {
+ // life first of all.
+ // don't allow the user to suicide
+ if(_OUTPUT_VERBOSE)
+ m_pConsole->output(KVI_OUT_SYSTEMWARNING,
+ __tr2qs("Notify list: ISON delay (%d sec) is too short, resetting to something more reasonable (5 sec)"),
+ iTimeout);
+ iTimeout = 5;
+ KVI_OPTION_UINT(KviOption_uintNotifyListIsOnDelayTimeInSecs) = 5;
+ }
+ m_pDelayedIsOnTimer->start(iTimeout * 1000,true);
+}
+
+void KviIsOnNotifyListManager::newIsOnSession()
+{
+ buildIsOnList();
+ if(m_pIsOnList->isEmpty())delayedNotifySession();
+ else sendIsOn();
+}
+
+void KviIsOnNotifyListManager::buildIsOnList()
+{
+ m_pIsOnList->clear();
+ m_szIsOnString = "";
+ m_pNotifyList->setAutoDelete(false);
+ while(QString * s = m_pNotifyList->first())
+ {
+ if(((m_szIsOnString.length() + s->length()) + 1) < 504)
+ {
+ if(!m_szIsOnString.isEmpty())m_szIsOnString.append(' ');
+ m_szIsOnString.append(*s);
+ m_pIsOnList->append(s);
+ m_pNotifyList->removeFirst();
+ } else break;
+ }
+ m_pNotifyList->setAutoDelete(true);
+}
+
+void KviIsOnNotifyListManager::sendIsOn()
+{
+ if(_OUTPUT_PARANOIC)
+ m_pConsole->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Notify list: Checking for: %Q"),&m_szIsOnString);
+ KviQCString szDec = m_pConnection->encodeText(m_szIsOnString);
+ m_pConnection->sendFmtData("ISON %s",szDec.data());
+ if(m_pConnection->lagMeter())
+ m_pConnection->lagMeter()->lagCheckRegister("@notify_ison",40); // not that reliable
+ m_szIsOnString = "";
+ m_bExpectingIsOn = true;
+ // FIXME: #warning "And if can't send ?"
+}
+
+
+bool KviIsOnNotifyListManager::handleIsOn(KviIrcMessage *msg)
+{
+ if(!m_bExpectingIsOn)return false;
+
+ // Check if it is our ISON
+ // all the nicks must be on the IsOnList
+
+ KviPointerList<QString> tmplist;
+ tmplist.setAutoDelete(false);
+
+ KviStr nk;
+ const char * aux = msg->trailing();
+
+ while(*aux)
+ {
+ nk = "";
+ aux = kvi_extractToken(nk,aux,' ');
+ if(nk.hasData())
+ {
+ bool bGotIt = false;
+ QString dnk = m_pConnection->decodeText(nk.ptr());
+ for(QString * s = m_pIsOnList->first();s && (!bGotIt);s = m_pIsOnList->next())
+ {
+ if(KviQString::equalCI(*s,dnk))
+ {
+ tmplist.append(s);
+ bGotIt = true;
+ }
+ }
+ if(!bGotIt)
+ {
+ // ops...not my userhost!
+ if(_OUTPUT_VERBOSE)
+ m_pConsole->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Notify list: Hey! You've used ISON behind my back? (I might be confused now...)"));
+ return false;
+ }
+ }
+ }
+
+ // Ok...looks to be my ison (still not sure at 100% , but can't do better)
+ if(m_pConnection->lagMeter())
+ m_pConnection->lagMeter()->lagCheckComplete("@notify_ison");
+
+ m_bExpectingIsOn = false;
+
+ m_pOnlineList->clear();
+
+ m_pIsOnList->setAutoDelete(false);
+
+ // Ok...we have an IsOn reply here
+ // The nicks in the IsOnList that are also in the reply are online , and go to the OnlineList
+ // the remaining in the IsOnList are offline
+
+ QString * s;
+
+ for(s = tmplist.first();s;s = tmplist.next())
+ {
+ m_pIsOnList->removeRef(s);
+ m_pOnlineList->append(s);
+ }
+
+ m_pIsOnList->setAutoDelete(true);
+ // Ok...all the users that are online , are on the OnlineList
+ // the remaining users are in the m_pIsOnList , and are no longer online
+
+ // first the easy step: remove the users that have just left irc or have never been online
+ // we're clearling the m_pIsOnList
+ while((s = m_pIsOnList->first()))
+ {
+ if(m_pConsole->notifyListView()->findEntry(*s))
+ {
+ // has just left IRC... make him part
+ notifyOffLine(*s);
+ } // else has never been here
+
+ m_pIsOnList->removeFirst(); // autodelete is true
+ }
+
+ // ok... complex step now: the remaining users in the userhost list are online
+ // if they have been online before, just remove them from the list
+ // otherwise they must be matched for masks
+ // and eventually inserted in the notify view later
+
+ KviIrcUserDataBase * db = console()->connection()->userDataBase();
+
+ KviPointerList<QString> l;
+ l.setAutoDelete(false);
+
+ for(s = m_pOnlineList->first();s;s = m_pOnlineList->next())
+ {
+ if(KviUserListEntry * ent = m_pConsole->notifyListView()->findEntry(*s))
+ {
+ // the user was online from a previous notify session
+ // might the mask have been changed ? (heh...this is tricky, maybe too much even)
+ if(KVI_OPTION_BOOL(KviOption_boolNotifyListSendUserhostForOnlineUsers))
+ {
+ // user wants to be sure about online users....
+ // check if he is on some channels
+ if(ent->globalData()->nRefs() > 1)
+ {
+ // mmmh...we have more than one ref , so the user is at least in one query or channel
+ // look him up on channels , if we find his entry , we can be sure that he is
+ // still the right user
+ KviPointerList<KviChannel> * chlist = m_pConsole->connection()->channelList();
+ for(KviChannel * ch = chlist->first();ch;ch = chlist->next())
+ {
+ if(KviUserListEntry * le = ch->findEntry(*s))
+ {
+ l.append(s); // ok...found on a channel...we don't need an userhost to match him
+ KviIrcMask mk(*s,le->globalData()->user(),le->globalData()->host());
+ if(!doMatchUser(*s,mk))return true; // critical problems = have to restart!!!
+ break;
+ }
+ }
+ } // else Only one ref...we need an userhost to be sure (don't remove from the list)
+ } else {
+ // user wants no userhost for online users...we "hope" that everything will go ok.
+ l.append(s);
+ }
+ //l.append(s); // we will remove him from the list
+ } else {
+ // the user was not online!
+ // check if we have a cached mask
+ if(db)
+ {
+ if(KviIrcUserEntry * ue = db->find(*s))
+ {
+ // already in the db... do we have a mask ?
+ if(ue->hasUser() && ue->hasHost())
+ {
+ // yup! we have a complete mask to match on
+ KviIrcMask mk(*s,ue->user(),ue->host());
+ // lookup the user's name in the m_pRegUserDict
+ if(!doMatchUser(*s,mk))return true; // critical problems = have to restart!!!
+ l.append(s); // remove anyway
+ }
+ }
+ }
+ }
+ }
+
+ for(s = l.first();s;s = l.next())
+ {
+ m_pOnlineList->removeRef(s); // autodelete is true
+ }
+
+ if(m_pOnlineList->isEmpty())
+ {
+ if(m_pNotifyList->isEmpty())delayedNotifySession();
+ else delayedIsOnSession();
+ } else delayedUserhostSession();
+
+ return true;
+}
+
+// FIXME: #warning "Nickname escapes (links) in the notifylist messages!"
+
+bool KviIsOnNotifyListManager::doMatchUser(const QString &notifyString,const KviIrcMask & mask)
+{
+ QString * nam = m_pRegUserDict->find(notifyString);
+ if(nam)
+ {
+ // ok...find the user
+ if(KviRegisteredUser * u = g_pRegisteredUserDataBase->findUserByName(*nam))
+ {
+ // ok ... match the user
+ if(u->matchesFixed(mask))
+ {
+ // new user online
+ if(!(m_pConsole->notifyListView()->findEntry(mask.nick())))
+ {
+ notifyOnLine(mask.nick(),mask.user(),mask.host());
+ } // else already online , and matching...all ok
+ } else {
+ // not matched.... has he been online before ?
+ if(m_pConsole->notifyListView()->findEntry(mask.nick()))
+ {
+ // has been online just a sec ago , but now the mask does not match
+ // either reguserdb has changed , or the user went offline and another one got his nick
+ // in the meantime... (ugly situation anyway)
+ notifyOffLine(mask.nick(),mask.user(),mask.host(),__tr2qs("registration mask changed, or nickname is being used by someone else"));
+ } else {
+ // has never been online
+ if(_OUTPUT_VERBOSE)
+ m_pConsole->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Notify list: \r!n\r%Q\r appears to be online, but the mask [%Q@\r!h\r%Q\r] does not match (registration mask does not match, or nickname is being used by someone else)"),&(mask.nick()),&(mask.user()),&(mask.host()));
+ }
+ }
+ } else {
+ // ops... unexpected inconsistency .... reguser db modified ?
+ m_pConsole->output(KVI_OUT_SYSTEMWARNING,__tr2qs("Notify list: Unexpected inconsistency, registered user DB modified? (restarting)"));
+ stop();
+ start();
+ return false; // critical ... exit from the call stack
+ }
+ } else {
+ // ops...unexpected inconsistency
+ m_pConsole->output(KVI_OUT_SYSTEMWARNING,__tr2qs("Notify list: Unexpected inconsistency, expected \r!n\r%Q\r in the registered user DB"),&notifyString);
+ }
+ return true;
+}
+
+void KviIsOnNotifyListManager::delayedUserhostSession()
+{
+ unsigned int iTimeout = KVI_OPTION_UINT(KviOption_uintNotifyListUserhostDelayTimeInSecs);
+ if(iTimeout < 5)
+ {
+ // life first of all.
+ // don't allow the user to suicide
+ if(_OUTPUT_VERBOSE)
+ m_pConsole->output(KVI_OUT_SYSTEMWARNING,
+ __tr2qs("Notify list: USERHOST delay (%d sec) is too short, resetting to something more reasonable (5 sec)"),
+ iTimeout);
+ iTimeout = 5;
+ KVI_OPTION_UINT(KviOption_uintNotifyListUserhostDelayTimeInSecs) = 5;
+ }
+ m_pDelayedUserhostTimer->start(iTimeout * 1000,true);
+}
+
+void KviIsOnNotifyListManager::newUserhostSession()
+{
+ buildUserhostList();
+ if(m_pUserhostList->isEmpty())
+ {
+ // this is unexpected!
+ m_pConsole->output(KVI_OUT_SYSTEMWARNING,__tr2qs("Notify list: Unexpected inconsistency, userhost list is empty!"));
+ if(m_pOnlineList->isEmpty())
+ {
+ if(m_pNotifyList->isEmpty())delayedNotifySession();
+ else delayedIsOnSession();
+ } else delayedUserhostSession();
+ return;
+ }
+ sendUserhost();
+}
+
+#define MAX_USERHOST_ENTRIES 5
+
+void KviIsOnNotifyListManager::buildUserhostList()
+{
+ m_szUserhostString = "";
+ m_pUserhostList->clear();
+
+ m_pOnlineList->setAutoDelete(false);
+ int i = 0;
+ QString * s;
+ while((s = m_pOnlineList->first()) && (i < MAX_USERHOST_ENTRIES))
+ {
+ if(!m_szUserhostString.isEmpty())m_szUserhostString.append(' ');
+ m_szUserhostString.append(*s);
+ m_pUserhostList->append(s);
+ m_pOnlineList->removeFirst();
+ i++;
+ }
+ m_pOnlineList->setAutoDelete(true);
+}
+
+void KviIsOnNotifyListManager::sendUserhost()
+{
+ if(_OUTPUT_PARANOIC)
+ m_pConsole->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Notify list: Checking userhost for: %Q"),&m_szUserhostString);
+ KviQCString ccc = m_pConnection->encodeText(m_szUserhostString);
+ m_pConnection->sendFmtData("USERHOST %s",ccc.data());
+ if(m_pConnection->lagMeter())
+ m_pConnection->lagMeter()->lagCheckRegister("@notify_userhost",50);
+ m_szUserhostString = "";
+ m_bExpectingUserhost = true;
+// FIXME: #warning "And if can't send ?"
+}
+
+bool KviIsOnNotifyListManager::handleUserhost(KviIrcMessage *msg)
+{
+ if(!m_bExpectingUserhost)return false;
+ // first check for consistency: all the replies must be on the USERHOST list
+ KviPointerList<KviIrcMask> tmplist;
+ tmplist.setAutoDelete(true);
+
+ KviStr nk;
+ const char * aux = msg->trailing();
+
+ while(*aux)
+ {
+ nk = "";
+ aux = kvi_extractToken(nk,aux,' ');
+ if(nk.hasData())
+ {
+ // split it in a mask
+ KviStr nick;
+ KviStr user;
+ KviStr host;
+
+ int idx = nk.findFirstIdx('=');
+ if(idx != -1)
+ {
+ nick = nk.left(idx);
+ if(nick.lastCharIs('*'))nick.cutRight(1);
+ nk.cutLeft(idx + 1);
+ if(nk.firstCharIs('+') || nk.firstCharIs('-'))nk.cutLeft(1);
+
+ idx = nk.findFirstIdx('@');
+ if(idx != -1)
+ {
+ user = nk.left(idx);
+ nk.cutLeft(idx + 1);
+ host = nk;
+ } else {
+ user = "*";
+ host = nk;
+ }
+
+ bool bGotIt = false;
+ QString szNick = m_pConnection->decodeText(nick.ptr());
+ QString szUser = m_pConnection->decodeText(user.ptr());
+ QString szHost = m_pConnection->decodeText(host.ptr());
+
+ for(QString * s = m_pUserhostList->first();s && (!bGotIt);s = m_pUserhostList->next())
+ {
+ if(KviQString::equalCI(*s,szNick))
+ {
+ KviIrcMask * mk = new KviIrcMask(szNick,szUser,szHost);
+ tmplist.append(mk);
+ bGotIt = true;
+ m_pUserhostList->removeRef(s);
+ }
+ }
+
+ if(!bGotIt)
+ {
+ // ops...not my userhost!
+ if(_OUTPUT_VERBOSE)
+ m_pConsole->output(KVI_OUT_SYSTEMWARNING,__tr2qs("Notify list: Hey! You've used USERHOST behind my back? (I might be confused now...)"));
+ return false;
+ }
+ } else {
+ if(_OUTPUT_VERBOSE)
+ m_pConsole->output(KVI_OUT_SYSTEMWARNING,__tr2qs("Notify list: Broken USERHOST reply from the server? (%s)"),nk.ptr());
+ }
+ }
+ }
+
+ // Ok...looks to be my usershot (still not sure at 100% , but can't do better)
+
+ if(m_pConnection->lagMeter())
+ m_pConnection->lagMeter()->lagCheckComplete("@notify_userhost");
+
+
+ m_bExpectingUserhost = false;
+
+ for(KviIrcMask * mk = tmplist.first();mk;mk = tmplist.next())
+ {
+ if(!doMatchUser(mk->nick(),*mk))return true; // have to restart!!!
+ }
+
+ if(!(m_pUserhostList->isEmpty()))
+ {
+ // ops...someone is no longer online ?
+ while(QString * s = m_pUserhostList->first())
+ {
+ if(_OUTPUT_VERBOSE)
+ m_pConsole->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Notify list: \r!n\r%Q\r appears to have gone offline before USERHOST reply was received, will recheck in the next loop"),s);
+ m_pUserhostList->removeFirst();
+ }
+
+ }
+
+ if(m_pOnlineList->isEmpty())
+ {
+ if(m_pNotifyList->isEmpty())delayedNotifySession();
+ else delayedIsOnSession();
+ } else delayedUserhostSession();
+
+ return true;
+}
+
+void KviIsOnNotifyListManager::stop()
+{
+ if(!m_bRunning)return;
+
+ if(m_pConnection->lagMeter())
+ m_pConnection->lagMeter()->lagCheckAbort("@notify_userhost");
+ if(m_pConnection->lagMeter())
+ m_pConnection->lagMeter()->lagCheckAbort("@notify_ison");
+
+ m_pDelayedNotifyTimer->stop();
+ m_pDelayedIsOnTimer->stop();
+ m_pDelayedUserhostTimer->stop();
+ m_pConsole->notifyListView()->partAllButOne(m_pConnection->currentNickName());
+ m_pRegUserDict->clear();
+ m_pNotifyList->clear();
+ m_pIsOnList->clear();
+ m_pOnlineList->clear();
+ m_pUserhostList->clear();
+ m_szIsOnString = "";
+ m_szUserhostString = "";
+ m_bRunning = false;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Stupid notify list manager
+//
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+KviStupidNotifyListManager::KviStupidNotifyListManager(KviIrcConnection * pConnection)
+: KviNotifyListManager(pConnection)
+{
+ m_pNickList = new KviPointerList<QString>;
+ m_pNickList->setAutoDelete(true);
+ m_iRestartTimer = 0;
+}
+
+KviStupidNotifyListManager::~KviStupidNotifyListManager()
+{
+ if(m_iRestartTimer)
+ {
+ killTimer(m_iRestartTimer);
+ m_iRestartTimer = 0;
+ }
+ delete m_pNickList;
+}
+
+void KviStupidNotifyListManager::start()
+{
+ if(m_iRestartTimer)
+ {
+ killTimer(m_iRestartTimer);
+ m_iRestartTimer = 0;
+ }
+ if(_OUTPUT_VERBOSE)
+ m_pConsole->outputNoFmt(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Starting notify list"));
+ buildNickList();
+ if(m_pNickList->isEmpty())
+ {
+ if(_OUTPUT_VERBOSE)
+ m_pConsole->outputNoFmt(KVI_OUT_SYSTEMMESSAGE,__tr2qs("No users in the notify list"));
+ return; // Ok...no nicknames in the list
+ }
+ m_iNextNickToCheck = 0;
+ m_pConsole->notifyListView()->partAllButOne(m_pConnection->currentNickName());
+ sendIsOn();
+}
+
+void KviStupidNotifyListManager::sendIsOn()
+{
+ m_szLastIsOnMsg = "";
+ QString * nick = m_pNickList->at(m_iNextNickToCheck);
+ __range_valid(nick);
+
+ int i = 0;
+ while(nick && ((nick->length() + 5 + m_szLastIsOnMsg.length()) < 510))
+ {
+ KviQString::appendFormatted(m_szLastIsOnMsg," %Q",nick);
+ nick = m_pNickList->next();
+ i++;
+ }
+ if(_OUTPUT_PARANOIC)
+ m_pConsole->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Notify list: Checking for:%Q"),&m_szLastIsOnMsg);
+ KviQCString dat = m_pConnection->encodeText(m_szLastIsOnMsg);
+ m_pConnection->sendFmtData("ISON%s",dat.data());
+
+ if(m_pConnection->lagMeter())
+ m_pConnection->lagMeter()->lagCheckRegister("@notify_naive",20);
+
+ m_iNextNickToCheck += i;
+}
+
+bool KviStupidNotifyListManager::handleIsOn(KviIrcMessage * msg)
+{
+ if(m_pConnection->lagMeter())
+ m_pConnection->lagMeter()->lagCheckComplete("@notify_naive");
+
+ KviStr nk;
+ const char * aux = msg->trailing();
+ while(*aux)
+ {
+ nk = "";
+ aux = kvi_extractToken(nk,aux,' ');
+ if(nk.hasData())
+ {
+ QString nkd = m_pConnection->decodeText(nk.ptr());
+ QString nksp = " " + nkd;
+ m_szLastIsOnMsg.replace(nksp,"",false);
+ if(!(m_pConsole->notifyListView()->findEntry(nkd)))
+ {
+ // not yet notified
+ notifyOnLine(nkd);
+ }
+ }
+ }
+ // ok...check the users that have left irc now...
+ QStringList sl = QStringList::split(' ',m_szLastIsOnMsg);
+
+ for(QStringList::Iterator it = sl.begin();it != sl.end();++it)
+ {
+ if(m_pConsole->notifyListView()->findEntry(*it))
+ {
+ // has just left irc
+ notifyOffLine(*it);
+ } // else has never been here...
+ }
+
+ if(((unsigned int)m_iNextNickToCheck) >= m_pNickList->count())
+ {
+ // have to restart
+ unsigned int iTimeout = KVI_OPTION_UINT(KviOption_uintNotifyListCheckTimeInSecs);
+ if(iTimeout < 5)
+ {
+ // life first of all.
+ // don't allow the user to suicide
+ if(_OUTPUT_VERBOSE)
+ m_pConsole->output(KVI_OUT_SYSTEMWARNING,
+ __tr2qs("Notify list: Timeout (%d sec) is too short, resetting to something more reasonable (5 sec)"),
+ iTimeout);
+ iTimeout = 5;
+ KVI_OPTION_UINT(KviOption_uintNotifyListCheckTimeInSecs) = 5;
+ }
+ m_iRestartTimer = startTimer(iTimeout * 1000);
+ } else sendIsOn();
+ return true;
+}
+
+void KviStupidNotifyListManager::timerEvent(QTimerEvent *e)
+{
+ if(e->timerId() == m_iRestartTimer)
+ {
+ killTimer(m_iRestartTimer);
+ m_iRestartTimer = 0;
+ m_iNextNickToCheck = 0;
+ sendIsOn();
+ return;
+ }
+ QObject::timerEvent(e);
+}
+
+void KviStupidNotifyListManager::stop()
+{
+ if(m_pConnection->lagMeter())
+ m_pConnection->lagMeter()->lagCheckAbort("@notify_naive");
+
+ if(m_iRestartTimer)
+ {
+ killTimer(m_iRestartTimer);
+ m_iRestartTimer = 0;
+ }
+ m_pConsole->notifyListView()->partAllButOne(m_pConnection->currentNickName());
+
+ // The ISON Method needs no stopping
+}
+
+void KviStupidNotifyListManager::buildNickList()
+{
+ const KviPointerHashTable<QString,KviRegisteredUser> * d = g_pRegisteredUserDataBase->userDict();
+ KviPointerHashTableIterator<QString,KviRegisteredUser> it(*d);
+ m_pNickList->clear();
+ while(it.current())
+ {
+ QString notify;
+ if(it.current()->getProperty("notify",notify))
+ {
+ m_pNickList->append(new QString(notify));
+ }
+ ++it;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Watch notify list manager
+//
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+KviWatchNotifyListManager::KviWatchNotifyListManager(KviIrcConnection * pConnection)
+: KviNotifyListManager(pConnection)
+{
+ m_pRegUserDict = new KviPointerHashTable<QString,QString>(17,false);
+ m_pRegUserDict->setAutoDelete(true);
+}
+
+KviWatchNotifyListManager::~KviWatchNotifyListManager()
+{
+ delete m_pRegUserDict;
+}
+
+void KviWatchNotifyListManager::buildRegUserDict()
+{
+ m_pRegUserDict->clear();
+
+ const KviPointerHashTable<QString,KviRegisteredUser> * d = g_pRegisteredUserDataBase->userDict();
+ KviPointerHashTableIterator<QString,KviRegisteredUser> it(*d);
+ while(KviRegisteredUser * u = it.current())
+ {
+ QString notify;
+ if(u->getProperty("notify",notify))
+ {
+ notify.stripWhiteSpace();
+ QStringList sl = QStringList::split(' ',notify);
+ for(QStringList::Iterator it = sl.begin();it != sl.end();++it)
+ {
+ m_pRegUserDict->replace(*it,new QString(u->name()));
+ }
+ }
+ ++it;
+ }
+}
+
+void KviWatchNotifyListManager::start()
+{
+ m_pConsole->notifyListView()->partAllButOne(m_pConnection->currentNickName());
+
+ buildRegUserDict();
+
+ QString watchStr;
+
+ KviPointerHashTableIterator<QString,QString> it(*m_pRegUserDict);
+ while(it.current())
+ {
+ QString nk = it.currentKey();
+ if(nk.find('*') == -1)
+ {
+ if((watchStr.length() + nk.length() + 2) > 501)
+ {
+ KviQCString dat = m_pConnection->encodeText(watchStr);
+ m_pConnection->sendFmtData("WATCH%s",dat.data());
+ if(_OUTPUT_VERBOSE)
+ m_pConsole->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Notify list: Adding watch entries for%Q"),&watchStr);
+ watchStr = "";
+ }
+ KviQString::appendFormatted(watchStr," +%Q",&nk);
+ }
+ ++it;
+ }
+
+ if(!watchStr.isEmpty())
+ {
+ KviQCString dat = m_pConnection->encodeText(watchStr);
+ m_pConnection->sendFmtData("WATCH%s",dat.data());
+ if(_OUTPUT_VERBOSE)
+ m_pConsole->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Notify list: Adding watch entries for%Q"),&watchStr);
+ }
+}
+void KviWatchNotifyListManager::stop()
+{
+ m_pConsole->notifyListView()->partAllButOne(m_pConnection->currentNickName());
+ m_pConnection->sendFmtData("WATCH clear");
+ m_pRegUserDict->clear();
+}
+
+bool KviWatchNotifyListManager::doMatchUser(KviIrcMessage * msg,const QString &notifyString,const KviIrcMask & mask)
+{
+ QString * nam = m_pRegUserDict->find(notifyString);
+
+ if(nam)
+ {
+ // ok...find the user
+ if(KviRegisteredUser * u = g_pRegisteredUserDataBase->findUserByName(*nam))
+ {
+ // ok ... match the user
+ if(u->matchesFixed(mask))
+ {
+ // new user online
+ if(!(m_pConsole->notifyListView()->findEntry(mask.nick())))
+ {
+ notifyOnLine(mask.nick(),mask.user(),mask.host(),"watch");
+ } else {
+ // else already online , and matching...all ok
+ if(msg->numeric() == RPL_NOWON)
+ {
+ // This is a reply to a /watch +something (should not happen, unless the user is messing) or to /watch l (user requested)
+ notifyOnLine(mask.nick(),mask.user(),mask.host(),
+ __tr2qs("watch entry listing requested by user"),false);
+ } else {
+ // This is a RPL_LOGON....we're desynched ?
+ notifyOnLine(mask.nick(),mask.user(),mask.host(),
+ __tr2qs("possible watch list desync"),false);
+ }
+ }
+ } else {
+ // not matched.... has he been online before ?
+ if(m_pConsole->notifyListView()->findEntry(mask.nick()))
+ {
+ // has been online just a sec ago , but now the mask does not match
+ // prolly the reguserdb has been changed
+ notifyOffLine(mask.nick(),mask.user(),mask.host(),
+ __tr2qs("registration mask changed or desync with the watch service"));
+ } else {
+ // has never been online
+ if(_OUTPUT_VERBOSE)
+ m_pConsole->output(KVI_OUT_SYSTEMMESSAGE,
+ __tr("Notify list: \r!n\r%Q\r appears to be online, but the mask [%Q@\r!h\r%Q\r] does not match (watch: registration mask does not match, or nickname is being used by someone else)"),
+ &(mask.nick()),&(mask.user()),&(mask.host()));
+ }
+ }
+ } else {
+ // ops... unexpected inconsistency .... reguser db modified ?
+ m_pConsole->output(KVI_OUT_SYSTEMWARNING,
+ __tr2qs("Notify list: Unexpected inconsistency, registered user DB modified? (watch: restarting)"));
+ stop();
+ start();
+ return false; // critical ... exit from the call stack
+ }
+ } else {
+ // not in our dictionary
+ // prolly someone used /WATCH behind our back... bad boy!
+ if(!(m_pConsole->notifyListView()->findEntry(mask.nick())))
+ {
+ notifyOnLine(mask.nick(),mask.user(),mask.host(),__tr2qs("watch entry added by user"));
+ }
+ }
+ return true;
+}
+
+// FIXME: #warning "DEDICATED WATCH LIST VERBOSITY FLAG ? (To allow the user to use /WATCH l and manual /WATCH)"
+
+bool KviWatchNotifyListManager::handleWatchReply(KviIrcMessage *msg)
+{
+ // 600: RPL_LOGON
+ // :prefix 600 <target> <nick> <user> <host> <logintime> :logged online
+ // 601: RPL_LOGON
+ // :prefix 601 <target> <nick> <user> <host> <logintime> :logged offline
+ // 604: PRL_NOWON
+ // :prefix 604 <target> <nick> <user> <host> <logintime> :is online
+ // 605: PRL_NOWOFF
+ // :prefix 605 <target> <nick> <user> <host> 0 :is offline
+
+// FIXME: #warning "Use the logintime in some way ?"
+
+ const char * nk = msg->safeParam(1);
+ const char * us = msg->safeParam(2);
+ const char * ho = msg->safeParam(3);
+ QString dnk = m_pConnection->decodeText(nk);
+ QString dus = m_pConnection->decodeText(us);
+ QString dho = m_pConnection->decodeText(ho);
+
+ if((msg->numeric() == RPL_LOGON) || (msg->numeric() == RPL_NOWON))
+ {
+ KviIrcMask m(dnk,dus,dho);
+ doMatchUser(msg,dnk,m);
+ return true;
+
+ } else if(msg->numeric() == RPL_WATCHOFF)
+ {
+ if(m_pConsole->notifyListView()->findEntry(dnk))
+ {
+ notifyOffLine(dnk,dus,dho,__tr2qs("removed from watch list"));
+ } else {
+ if(_OUTPUT_VERBOSE)
+ m_pConsole->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Notify list: Stopped watching for \r!n\r%Q\r"),&dnk);
+ }
+ if(m_pRegUserDict->find(dnk))m_pRegUserDict->remove(dnk); // kill that
+
+ return true;
+
+ } else if((msg->numeric() == RPL_LOGOFF) || (msg->numeric() == RPL_NOWOFF))
+ {
+ if(m_pConsole->notifyListView()->findEntry(dnk))
+ {
+ notifyOffLine(dnk,dus,dho,__tr2qs("watch"));
+ } else {
+ if(msg->numeric() == RPL_NOWOFF)
+ {
+ // This is a reply to a /watch +something
+ if(_OUTPUT_VERBOSE)
+ m_pConsole->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Notify list: \r!n\r%Q\r is offline (watch)"),&dnk);
+ } else {
+ // This is a RPL_LOGOFF for an user that has not matched the reg-mask
+ notifyOffLine(dnk,dus,dho,__tr2qs("unmatched watch list entry"));
+ }
+ }
+ return true;
+ }
+
+ return false;
+}
+
+
+#include "kvi_notifylist.moc"
diff --git a/src/kvirc/kernel/kvi_notifylist.h b/src/kvirc/kernel/kvi_notifylist.h
new file mode 100644
index 00000000..8484f3f7
--- /dev/null
+++ b/src/kvirc/kernel/kvi_notifylist.h
@@ -0,0 +1,161 @@
+#ifndef _KVI_NOTIFYLIST_H_
+#define _KVI_NOTIFYLIST_H_
+
+//=============================================================================
+//
+// File : kvi_notifylist.h
+// Creation date : Fri Oct 27 2000 23:39:09 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+
+#include "kvi_settings.h"
+
+#include <qobject.h>
+#include "kvi_pointerlist.h"
+#include "kvi_pointerhashtable.h"
+#include <qtimer.h>
+
+#include "kvi_qstring.h"
+
+class KviConsole;
+class KviIrcMessage;
+class KviIrcMask;
+class KviIrcConnection;
+
+class KVIRC_API KviNotifyListManager : public QObject
+{
+ friend class KviConsole;
+ friend class KviConnectionInfo;
+ friend class KviServerParser;
+ friend class KviIrcConnection;
+ Q_OBJECT
+protected:
+ KviNotifyListManager(KviIrcConnection * pConnection);
+ ~KviNotifyListManager();
+protected:
+ KviConsole * m_pConsole;
+ KviIrcConnection * m_pConnection;
+protected:
+ virtual void start();
+ virtual void stop();
+ virtual bool handleUserhost(KviIrcMessage * msg);
+ virtual bool handleIsOn(KviIrcMessage * msg);
+ virtual bool handleWatchReply(KviIrcMessage *msg);
+ void notifyOnLine(const QString &nick,const QString &user = QString::null,const QString &host = QString::null,const QString &szReason = QString::null,bool bJoin=true);
+ void notifyOffLine(const QString &nick,const QString &user = QString::null,const QString &host = QString::null,const QString &szReason = QString::null);
+public:
+ KviConsole * console(){ return m_pConsole; };
+};
+
+class KVIRC_API KviIsOnNotifyListManager : public KviNotifyListManager
+{
+ friend class KviConsole;
+ friend class KviServerParser;
+ friend class KviIrcConnection;
+ Q_OBJECT
+protected:
+ KviIsOnNotifyListManager(KviIrcConnection * pConnection);
+ ~KviIsOnNotifyListManager();
+private:
+ KviPointerHashTable<QString,QString> * m_pRegUserDict; // dict notifystring->reguser name
+ KviPointerList<QString> * m_pNotifyList; // list of notifystring (total)
+ KviPointerList<QString> * m_pIsOnList; // list of notifystring (one session)
+ QString m_szIsOnString; // m_pIsOnList in form of a string
+ KviPointerList<QString> * m_pOnlineList; //
+ KviPointerList<QString> * m_pUserhostList;
+ QString m_szUserhostString;
+ bool m_bExpectingIsOn;
+ bool m_bExpectingUserhost;
+ QTimer * m_pDelayedIsOnTimer;
+ QTimer * m_pDelayedNotifyTimer;
+ QTimer * m_pDelayedUserhostTimer;
+ bool m_bRunning;
+protected:
+ virtual void start();
+ virtual void stop();
+ virtual bool handleUserhost(KviIrcMessage *msg);
+ virtual bool handleIsOn(KviIrcMessage *msg);
+private:
+ void delayedNotifySession();
+ void delayedIsOnSession();
+ void delayedUserhostSession();
+private slots:
+ void newNotifySession();
+ void newIsOnSession();
+ void newUserhostSession();
+
+ void buildRegUserDict();
+ void buildIsOnList();
+ void buildUserhostList();
+ void buildNotifyList();
+ void sendIsOn();
+ void sendUserhost();
+ bool doMatchUser(const QString &notifyString,const KviIrcMask & mask);
+
+};
+
+
+class KVIRC_API KviStupidNotifyListManager : public KviNotifyListManager
+{
+ friend class KviConsole;
+ friend class KviServerParser;
+ friend class KviIrcConnection;
+ Q_OBJECT
+protected:
+ KviStupidNotifyListManager(KviIrcConnection * pConnection);
+ ~KviStupidNotifyListManager();
+protected:
+ KviPointerList<QString> * m_pNickList;
+ QString m_szLastIsOnMsg;
+ int m_iNextNickToCheck;
+ int m_iRestartTimer;
+protected:
+ virtual void start();
+ virtual void stop();
+ virtual bool handleIsOn(KviIrcMessage *msg);
+protected:
+ virtual void timerEvent(QTimerEvent *e);
+private:
+ void buildNickList();
+ void sendIsOn();
+};
+
+class KVIRC_API KviWatchNotifyListManager : public KviNotifyListManager
+{
+ friend class KviConsole;
+ friend class KviServerParser;
+ friend class KviIrcConnection;
+ Q_OBJECT
+public:
+ KviWatchNotifyListManager(KviIrcConnection * pConnection);
+ ~KviWatchNotifyListManager();
+protected:
+ KviPointerHashTable<QString,QString> * m_pRegUserDict; // dict notifystring->reguser name
+protected:
+ void buildRegUserDict();
+ virtual void start();
+ virtual void stop();
+ virtual bool handleWatchReply(KviIrcMessage *msg);
+ bool doMatchUser(KviIrcMessage *msg,const QString &notifyString,const KviIrcMask & mask);
+
+};
+
+#endif //_KVI_NOTIFYLIST_H_
diff --git a/src/kvirc/kernel/kvi_options.cpp b/src/kvirc/kernel/kvi_options.cpp
new file mode 100644
index 00000000..84bf4500
--- /dev/null
+++ b/src/kvirc/kernel/kvi_options.cpp
@@ -0,0 +1,1381 @@
+//=============================================================================
+//
+// File : kvi_options.cpp
+// Creation date : Tue Jun 20 2000 11:42:00 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#define _KVI_OPTIONS_CPP_
+
+#include "kvi_options.h"
+#include "kvi_defaults.h"
+#include "kvi_config.h"
+#include "kvi_app.h"
+#include "kvi_iconmanager.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_locale.h"
+#include "kvi_confignames.h"
+#include "kvi_window.h"
+#include "kvi_out.h"
+#include "kvi_stringconversion.h"
+#include "kvi_settings.h"
+#include "kvi_splash.h"
+#include "kvi_frame.h"
+#include "kvi_internalcmd.h"
+#include "kvi_theme.h"
+#include <qmessagebox.h>
+#include <qregexp.h>
+//#include "kvi_textencoding.h"
+
+//xml parser
+#include <qdom.h>
+//!xml parser
+
+#include <zlib.h>
+#include <qtextcodec.h>
+
+#include "kvi_fileutils.h"
+
+#include <qdir.h>
+#include <qstringlist.h>
+
+// kvi_app.cpp
+extern KVIRC_API int g_iIdentDaemonRunningUsers;
+
+
+#define RECT_OPTION(_txt,_val,_flags) KviRectOption(KVI_RECT_OPTIONS_PREFIX _txt, _val , _flags)
+
+KviRectOption g_rectOptionsTable[KVI_NUM_RECT_OPTIONS]=
+{
+ RECT_OPTION("FrameGeometry",QRect(0,0,10,10),KviOption_sectFlagGeometry),
+ RECT_OPTION("GeneralOptionsDialogGeometry",QRect(50,50,600,450),KviOption_sectFlagGeometry),
+ RECT_OPTION("RegisteredUsersDialogGeometry",QRect(50,50,600,450),KviOption_sectFlagGeometry)
+};
+
+#define BOOL_OPTION(_txt,_val,_flags) KviBoolOption(KVI_BOOL_OPTIONS_PREFIX _txt,_val,_flags)
+
+KviBoolOption g_boolOptionsTable[KVI_NUM_BOOL_OPTIONS]=
+{
+ BOOL_OPTION("WindowsRememberProperties",true,KviOption_sectFlagWindows),
+ BOOL_OPTION("IrcViewShowImages",false,KviOption_sectFlagIrcView | KviOption_resetUpdateGui | KviOption_groupTheme),
+ BOOL_OPTION("IrcViewTimestamp",true,KviOption_sectFlagIrcView),
+ BOOL_OPTION("IrcViewUrlHighlighting",true,KviOption_sectFlagIrcView | KviOption_groupTheme),
+ BOOL_OPTION("IrcViewWrapMargin",true,KviOption_sectFlagIrcView | KviOption_resetUpdateGui | KviOption_groupTheme),
+ BOOL_OPTION("InputHistoryCursorAtEnd",true,KviOption_sectFlagInput),
+
+ BOOL_OPTION("AvoidParserWarnings",false,KviOption_sectFlagUserParser),
+ BOOL_OPTION("UseProxyHost",false,KviOption_sectFlagConnection),
+ BOOL_OPTION("ShowGeneralOptionsDialogAsToplevel",true,KviOption_sectFlagFrame),
+ BOOL_OPTION("ForceBrutalQuit",false,KviOption_sectFlagIrcSocket),
+ BOOL_OPTION("ShowPingPong",true,KviOption_sectFlagConnection),
+ BOOL_OPTION("PopupNotifierOnNewQueryMessages",true,KviOption_sectFlagFrame),
+ BOOL_OPTION("ShowExtendedServerInfo",false,KviOption_sectFlagConnection),
+ BOOL_OPTION("EchoNumericTopic",true,KviOption_sectFlagConnection),
+ BOOL_OPTION("ShowOwnParts",true,KviOption_sectFlagConnection),
+ BOOL_OPTION("UseAntiSpamOnPrivmsg",false,KviOption_sectFlagAntiSpam),
+ BOOL_OPTION("UseExtendedPrivmsgView",false,KviOption_sectFlagIrcView | KviOption_groupTheme),
+ BOOL_OPTION("ShowUserAndHostInPrivmsgView",false,KviOption_sectFlagIrcView | KviOption_groupTheme),
+ BOOL_OPTION("UseWordHighlighting",true,KviOption_sectFlagIrcView), /* _ALL_ newbie users, with who i was taling asks me where can they switch on */
+ BOOL_OPTION("UseBigIcons",false,KviOption_sectFlagFrame), /* Almost all users asks me "How to decrease icon size?" */
+ BOOL_OPTION("CleanupUnusedModules",true,KviOption_sectFlagModules),
+ BOOL_OPTION("IgnoreCtcpPing",false,KviOption_sectFlagCtcp),
+ BOOL_OPTION("IgnoreCtcpVersion",false,KviOption_sectFlagCtcp),
+ BOOL_OPTION("UseCtcpFloodProtection",true,KviOption_sectFlagCtcp),
+ BOOL_OPTION("DisableBrokenEventHandlers",true,KviOption_sectFlagUserParser),
+ BOOL_OPTION("IgnoreCtcpClientinfo",false,KviOption_sectFlagCtcp),
+ BOOL_OPTION("IgnoreCtcpUserinfo",false,KviOption_sectFlagCtcp),
+ BOOL_OPTION("IgnoreCtcpFinger",false,KviOption_sectFlagCtcp),
+ BOOL_OPTION("IgnoreCtcpSource",false,KviOption_sectFlagCtcp),
+ BOOL_OPTION("IgnoreCtcpTime",false,KviOption_sectFlagCtcp),
+ BOOL_OPTION("RequestMissingAvatars",true,KviOption_sectFlagAvatar),
+ BOOL_OPTION("ShowCompactModeChanges",true,KviOption_sectFlagConnection),
+ BOOL_OPTION("IgnoreCtcpDcc",false,KviOption_sectFlagDcc),
+ BOOL_OPTION("AutoAcceptDccChat",false,KviOption_sectFlagDcc),
+ BOOL_OPTION("AutoAcceptDccSend",false,KviOption_sectFlagDcc),
+ BOOL_OPTION("SendZeroAckInDccRecv",false,KviOption_sectFlagDcc),
+ BOOL_OPTION("UseFastDccSend",true,KviOption_sectFlagDcc),
+ BOOL_OPTION("ObtainGlobalBackgroundFromKde",false,KviOption_sectFlagGui | KviOption_resetUpdatePseudoTransparency | KviOption_groupTheme),
+ BOOL_OPTION("UseTaskBarIrcContextIndicator",false,KviOption_sectFlagTaskBar | KviOption_resetUpdateGui),
+ BOOL_OPTION("UseGlobalApplicationFont",false,KviOption_sectFlagGui | KviOption_resetUpdateAppFont | KviOption_groupTheme),
+ BOOL_OPTION("AlwaysQuitKVIrcClosingLastConsole",false,KviOption_sectFlagFrame),
+ BOOL_OPTION("AlwaysDisconnectClosingConnectedConsole",false,KviOption_sectFlagFrame),
+ BOOL_OPTION("FlashWindowOnHighlightedMessages",true,KviOption_sectFlagFrame),
+ BOOL_OPTION("PopupNotifierOnHighlightedMessages",true,KviOption_sectFlagFrame),
+ BOOL_OPTION("FlashWindowOnNotifyOnLine",true,KviOption_sectFlagConnection),
+ BOOL_OPTION("IrcViewTimestampUTC",false,KviOption_sectFlagIrcView),
+ BOOL_OPTION("UseGlobalPseudoTransparency",false,KviOption_sectFlagGui | KviOption_resetUpdatePseudoTransparency | KviOption_groupTheme),
+ BOOL_OPTION("UseNotifyList",false,KviOption_sectFlagConnection | KviOption_resetRestartNotifyList),
+ BOOL_OPTION("NotifyListChangesToActiveWindow",true,KviOption_sectFlagConnection),
+ BOOL_OPTION("AutoResumeDccSendWhenAutoAccepted",true,KviOption_sectFlagDcc),
+ BOOL_OPTION("LimitOutgoingTraffic",false,KviOption_sectFlagIrcSocket),
+ BOOL_OPTION("SendUnknownCommandsAsRaw",true,KviOption_sectFlagUserParser),
+ BOOL_OPTION("UserListViewDrawGrid",true,KviOption_sectFlagUserListView | KviOption_resetUpdateGui | KviOption_groupTheme),
+ BOOL_OPTION("ShowChannelSyncTime",true,KviOption_sectFlagConnection),
+ BOOL_OPTION("RejoinChannelOnKick",true,KviOption_sectFlagConnection),
+ BOOL_OPTION("KeepChannelOpenOnKick",true,KviOption_sectFlagConnection),
+ BOOL_OPTION("AutoCloseDccSendOnSuccess",false,KviOption_sectFlagDcc),
+ BOOL_OPTION("NotifyDccSendSuccessInConsole",false,KviOption_sectFlagDcc),
+ BOOL_OPTION("CreateMinimizedDccSend",false,KviOption_sectFlagDcc),
+ BOOL_OPTION("CreateMinimizedDccChat",false,KviOption_sectFlagDcc),
+ BOOL_OPTION("AutoAcceptIncomingAvatars",false,KviOption_sectFlagDcc),
+ BOOL_OPTION("UseNickCompletionPostfixForFirstWordOnly",true,KviOption_sectFlagInput),
+ BOOL_OPTION("UseTaskBarIcons",true,KviOption_sectFlagTaskBar | KviOption_resetUpdateGui),
+ BOOL_OPTION("CreateMinimizedDccSendWhenAutoAccepted",true,KviOption_sectFlagDcc),
+ BOOL_OPTION("CreateMinimizedDccChatWhenAutoAccepted",true,KviOption_sectFlagDcc),
+ BOOL_OPTION("DccGuessIpFromServerWhenLocalIsUnroutable",true,KviOption_sectFlagDcc),
+ BOOL_OPTION("ShowRegisteredUsersDialogAsToplevel",true,KviOption_sectFlagFrame),
+ BOOL_OPTION("AutoLogQueries",true,KviOption_sectFlagLogging),/* this options enabled by default in mIRC,XChat and irssi. People are confused while they want to see logs, but see empty dir*/
+ BOOL_OPTION("AutoLogChannels",true,KviOption_sectFlagLogging),
+ BOOL_OPTION("AutoLogDccChat",false,KviOption_sectFlagLogging),
+ BOOL_OPTION("AutoLogConsole",false,KviOption_sectFlagLogging),
+
+ BOOL_OPTION("SilentAntiSpam",false,KviOption_sectFlagAntiSpam),
+ BOOL_OPTION("UseIncomingDccMediaTypeSavePath",true,KviOption_sectFlagDcc),
+ BOOL_OPTION("NotifyListSendUserhostForOnlineUsers",true,KviOption_sectFlagConnection),
+ BOOL_OPTION("UseIntelligentNotifyListManager",true,KviOption_sectFlagConnection | KviOption_resetRestartNotifyList),
+ BOOL_OPTION("UseWatchListIfAvailable",true,KviOption_sectFlagConnection),
+ BOOL_OPTION("UseTreeWindowListTaskBar",true,KviOption_sectFlagTaskBar | KviOption_resetUpdateTaskBar | KviOption_groupTheme),
+ BOOL_OPTION("BindIrcIpV4ConnectionsToSpecifiedAddress",false,KviOption_sectFlagConnection),
+ BOOL_OPTION("BindIrcIpV6ConnectionsToSpecifiedAddress",false,KviOption_sectFlagConnection),
+ BOOL_OPTION("UseAntiSpamOnNotice",false,KviOption_sectFlagAntiSpam),
+ BOOL_OPTION("SetLastAvatarAsDefaultForRegisteredUsers",true,KviOption_sectFlagAvatar),
+ BOOL_OPTION("CantAcceptIncomingDccConnections",false,KviOption_sectFlagDcc),
+ BOOL_OPTION("IgnoreCtcpAvatar",false,KviOption_sectFlagCtcp),
+ BOOL_OPTION("CtcpRepliesToActiveWindow",true,KviOption_sectFlagCtcp),
+ BOOL_OPTION("AutoAcceptDccCanvas",false,KviOption_sectFlagDcc),
+ BOOL_OPTION("NotifyDccSendSuccessInNotifier",true,KviOption_sectFlagDcc),
+ BOOL_OPTION("KillBrokenTimers",true,KviOption_sectFlagUserParser),
+ BOOL_OPTION("DccVoiceVolumeSliderControlsPCM", true, KviOption_sectFlagDcc),
+ BOOL_OPTION("DccVoiceForceHalfDuplex", false, KviOption_sectFlagDcc),
+ BOOL_OPTION("AutoAcceptDccVoice", false, KviOption_sectFlagDcc),
+ BOOL_OPTION("CreateMinimizedDccVoice", false, KviOption_sectFlagDcc),
+ BOOL_OPTION("CreateMinimizedDccVoiceWhenAutoAccepted",true,KviOption_sectFlagDcc),
+#ifdef COMPILE_ON_WINDOWS
+ BOOL_OPTION("UseIdentService",true,KviOption_sectFlagConnection | KviOption_resetRestartIdentd),
+#else
+ BOOL_OPTION("UseIdentService",false,KviOption_sectFlagConnection | KviOption_resetRestartIdentd),
+#endif
+ BOOL_OPTION("ShowTipAtStartup",false,KviOption_sectFlagFrame),
+ BOOL_OPTION("IdentdEnableIpV6",false,KviOption_sectFlagConnection | KviOption_resetRestartIdentd),
+#ifdef COMPILE_ON_WINDOWS
+ BOOL_OPTION("IdentdIpV6ContainsIpV4",false,KviOption_sectFlagConnection | KviOption_resetRestartIdentd),
+#else
+ BOOL_OPTION("IdentdIpV6ContainsIpV4",true,KviOption_sectFlagConnection | KviOption_resetRestartIdentd),
+#endif
+ BOOL_OPTION("ScaleAvatars",true,KviOption_sectFlagAvatar | KviOption_resetUpdateGui | KviOption_groupTheme),
+ BOOL_OPTION("ColorNicks",false,KviOption_sectFlagIrcView | KviOption_groupTheme),
+ BOOL_OPTION("BoldedNicks",true,KviOption_sectFlagIrcView | KviOption_groupTheme),
+ BOOL_OPTION("DccListenOnSpecifiedInterfaceByDefault",false,KviOption_sectFlagDcc),
+ BOOL_OPTION("ChangeNickAway", false, KviOption_sectFlagConnection),
+ BOOL_OPTION("AutoGeneratedAwayNick",false,KviOption_sectFlagConnection), /* only ircnet uses 9-symbol nicks */
+ BOOL_OPTION("ExitAwayOnInput",false,KviOption_sectFlagConnection),
+ BOOL_OPTION("AlwaysHighlightNick",true,KviOption_sectFlagIrcView),
+ BOOL_OPTION("ShowChannelsJoinOnIrc",true,KviOption_sectFlagFrame),
+ BOOL_OPTION("ShowChannelsJoinDialogAsToplevel",true,KviOption_sectFlagFrame),
+ BOOL_OPTION("UserDefinedPortRange",false,KviOption_sectFlagDcc),
+ BOOL_OPTION("CreateQueryOnPrivmsg",true,KviOption_sectFlagConnection),
+ BOOL_OPTION("CreateQueryOnNotice",false,KviOption_sectFlagConnection),
+ BOOL_OPTION("CreateMinimizedQuery",false,KviOption_sectFlagConnection),
+ BOOL_OPTION("AutoJoinOnInvite",false,KviOption_sectFlagConnection),
+ BOOL_OPTION("ShowServersConnectDialogOnStart",true, KviOption_sectFlagFrame),
+ BOOL_OPTION("ShowServersConnectDialogAsToplevel",true,KviOption_sectFlagFrame),
+ BOOL_OPTION("AcceptBrokenFileNameDccResumeRequests",true,KviOption_sectFlagFrame),
+ BOOL_OPTION("AutoReconnectOnUnexpectedDisconnect",true,KviOption_sectFlagFrame),
+ BOOL_OPTION("RejoinChannelsAfterReconnect",true,KviOption_sectFlagFrame),
+ BOOL_OPTION("ReopenQueriesAfterReconnect",true,KviOption_sectFlagFrame),
+ BOOL_OPTION("EnableQueryTracing",true,KviOption_sectFlagConnection),
+ BOOL_OPTION("OperatorMessagesToActiveWindow",false,KviOption_sectFlagConnection),
+ BOOL_OPTION("InviteToActiveWindow",true,KviOption_sectFlagConnection),
+ BOOL_OPTION("ShowChannelUserFlagInPrivmsgView",true,KviOption_sectFlagConnection),
+ BOOL_OPTION("DccSendFakeAddressByDefault",false,KviOption_sectFlagDcc),
+ BOOL_OPTION("UseTaskBarActivityMeter",false,KviOption_sectFlagTaskBar | KviOption_resetUpdateGui | KviOption_groupTheme),
+ BOOL_OPTION("CloseServerWidgetAfterConnect",false,KviOption_sectFlagFrame),
+ BOOL_OPTION("ShowIdentityDialogAsToplevel",true,KviOption_sectFlagFrame),
+ BOOL_OPTION("ShowUserChannelIcons",true,KviOption_sectFlagUserListView | KviOption_resetUpdateGui | KviOption_groupTheme),
+ BOOL_OPTION("ShowUserChannelState",false,KviOption_sectFlagUserListView | KviOption_resetUpdateGui | KviOption_groupTheme),
+ BOOL_OPTION("EnableIgnoreOnPrivMsg",true,KviOption_sectFlagConnection),
+ BOOL_OPTION("VerboseIgnore",true,KviOption_sectFlagConnection),
+ BOOL_OPTION("EnableIgnoreOnNotice",true,KviOption_sectFlagConnection),
+ BOOL_OPTION("NotifyFailedDccHandshakes",true,KviOption_sectFlagDcc),
+ BOOL_OPTION("AutoTileWindows",false,KviOption_sectFlagMdi),
+ BOOL_OPTION("DrawEmoticons",false,KviOption_sectFlagIrcView | KviOption_groupTheme),
+ BOOL_OPTION("IgnoreCtcpPage",false,KviOption_sectFlagCtcp),
+ BOOL_OPTION("ShowDialogOnCtcpPage",true,KviOption_sectFlagCtcp),
+ BOOL_OPTION("BashLikeNickCompletion",false,KviOption_sectFlagInput),
+ BOOL_OPTION("UseSSLCertificate",false,KviOption_sectFlagConnection),
+ BOOL_OPTION("UseSSLPrivateKey",false,KviOption_sectFlagConnection),
+ BOOL_OPTION("WarnAboutPastingMultipleLines",true,KviOption_sectFlagFrame),
+ BOOL_OPTION("KeepChannelsOpenOnUnexpectedDisconnect",false,KviOption_sectFlagFrame),
+ BOOL_OPTION("KeepQueriesOpenOnUnexpectedDisconnect",false,KviOption_sectFlagFrame),
+ BOOL_OPTION("UseLagMeterEngine",true,KviOption_sectFlagConnection | KviOption_resetRestartLagMeter),
+ BOOL_OPTION("ShowLagOnContextDisplay",true,KviOption_sectFlagFrame),
+ BOOL_OPTION("DisableBanListRequestOnJoin",false,KviOption_sectFlagConnection),
+ BOOL_OPTION("DisableBanExceptionListRequestOnJoin",true,KviOption_sectFlagConnection),
+ BOOL_OPTION("DisableInviteListRequestOnJoin",true,KviOption_sectFlagConnection),
+ BOOL_OPTION("DisableWhoRequestOnJoin",false,KviOption_sectFlagConnection),
+ BOOL_OPTION("ShowDockExtension",true,KviOption_sectFlagFrame),
+ BOOL_OPTION("GotAdressForDccByDnsMyNick",false,KviOption_sectFlagFrame),
+ BOOL_OPTION("MinimizeConsoleAfterConnect",false,KviOption_sectFlagFrame),
+ BOOL_OPTION("HighlightOnlyNormalMsg",false,KviOption_sectFlagFrame),
+ BOOL_OPTION("HighlightOnlyNormalMsgQueryToo",false,KviOption_sectFlagFrame),
+ BOOL_OPTION("HighlightOnlyNormalMsgNickinChanToo",false,KviOption_sectFlagFrame),
+ BOOL_OPTION("HighlightOnlyAtCustomHighlightLevel",false,KviOption_sectFlagFrame),
+ BOOL_OPTION("MdiManagerInSdiMode",true,KviOption_sectFlagFrame),
+ BOOL_OPTION("DccBrokenBouncerHack",false,KviOption_sectFlagDcc),
+ BOOL_OPTION("ExternalMessagesToActiveWindow",true,KviOption_sectFlagConnection),
+ BOOL_OPTION("IgnoreChannelAvatarRequestsWhenNoAvatarSet",true,KviOption_sectFlagAvatar),
+ BOOL_OPTION("FlashQueryWindowOnNewMessages",true,KviOption_sectFlagFrame),
+ BOOL_OPTION("ConfirmCloseWhenThereAreConnections",true,KviOption_sectFlagFrame),
+ BOOL_OPTION("UpdateKdeBackgroundOnChange",false,KviOption_sectFlagFrame),
+ BOOL_OPTION("CtcpRequestsToActiveWindow",false,KviOption_sectFlagConnection),
+ BOOL_OPTION("ServerRepliesToActiveWindow",true,KviOption_sectFlagConnection),
+ BOOL_OPTION("ServerNoticesToActiveWindow",false,KviOption_sectFlagConnection),
+ BOOL_OPTION("ServicesNoticesToActiveWindow",false,KviOption_sectFlagConnection),
+ BOOL_OPTION("SortTaskBarItemsByName",true,KviOption_sectFlagConnection),
+ BOOL_OPTION("ShowTaskBarToolTips",true,KviOption_sectFlagConnection),
+ BOOL_OPTION("ShowUserListViewToolTips",true,KviOption_sectFlagConnection),
+ BOOL_OPTION("WhoisRepliesToActiveWindow",true,KviOption_sectFlagConnection),
+ BOOL_OPTION("PopupNotifierOnNotifyOnLine",true,KviOption_sectFlagConnection),
+ BOOL_OPTION("ForciblyDisableNotifier",false,KviOption_sectFlagConnection),
+ BOOL_OPTION("DccSendForceIdleStep",false,KviOption_sectFlagDcc),
+ BOOL_OPTION("StatusBarVisible",true,KviOption_sectFlagFrame),
+ BOOL_OPTION("TrackLastReadTextViewLine",true,KviOption_sectFlagFrame),
+ BOOL_OPTION("KeepChannelOpenOnPart",false,KviOption_sectFlagFrame),
+ BOOL_OPTION("StripMircColorsInUserMessages",false,KviOption_sectFlagFrame | KviOption_groupTheme),
+ BOOL_OPTION("DoNotSuggestRestoreDefaultScript",false,KviOption_sectFlagFrame),
+ BOOL_OPTION("LimitDccSendSpeed",false,KviOption_sectFlagDcc),
+ BOOL_OPTION("LimitDccRecvSpeed",false,KviOption_sectFlagDcc),
+ BOOL_OPTION("IgnoreModuleVersions",false,KviOption_sectFlagFrame),
+ BOOL_OPTION("DisableInputHistory",false,KviOption_sectFlagInput | KviOption_resetUpdateGui),
+ BOOL_OPTION("UseSpecialColorForTimestamp",true,KviOption_sectFlagIrcView | KviOption_resetUpdateGui | KviOption_groupTheme),
+ BOOL_OPTION("DisableAwayListUpdates",false,KviOption_sectFlagFrame),
+ BOOL_OPTION("DisableAvatars",false,KviOption_sectFlagIrcView | KviOption_resetUpdateGui | KviOption_groupTheme),
+ BOOL_OPTION("DisableUserListLabel",false,KviOption_sectFlagIrcView | KviOption_resetUpdateGui | KviOption_groupTheme),
+ BOOL_OPTION("DisablePopupIcons",false,KviOption_sectFlagIrcView | KviOption_resetUpdateGui | KviOption_groupTheme),
+ BOOL_OPTION("ScriptErrorsToDebugWindow",false,KviOption_sectFlagFrame),
+ BOOL_OPTION("ShowMinimizedDebugWindow",true,KviOption_sectFlagFrame),
+ BOOL_OPTION("ShowExtendedInfoInQueryLabel",true,KviOption_resetUpdateGui),
+ BOOL_OPTION("UseUserListColorsAsNickColors",true,KviOption_sectFlagIrcView | KviOption_groupTheme),
+ BOOL_OPTION("GzipLogs",false,KviOption_sectFlagLogging),
+ BOOL_OPTION("MinimizeInTray",false,KviOption_resetUpdateGui),
+ BOOL_OPTION("DisableNotifierFlashing",false,KviOption_sectFlagFrame),
+ BOOL_OPTION("CommandlineInUserFriendlyModeByDefault",false,KviOption_sectFlagFrame), // this confuses existing users and is not mentioned in the docs where there are commandline examples : we need it to be off by default for now
+ BOOL_OPTION("EnableVisualEffects",true,KviOption_resetUpdateGui),
+ BOOL_OPTION("DCCFileTransferReplaceOutgoingSpacesWithUnderscores",true,KviOption_sectFlagDcc),
+ BOOL_OPTION("DoNotStretchAvatars",true,KviOption_sectFlagIrcView | KviOption_resetUpdateGui ),
+ BOOL_OPTION("UseDifferentColorForOwnNick",false,KviOption_sectFlagIrcView | KviOption_resetUpdateGui | KviOption_groupTheme),
+ BOOL_OPTION("CloseInTray",false,KviOption_sectFlagFrame | KviOption_resetUpdateGui),
+ BOOL_OPTION("StartupMinimized",false,KviOption_sectFlagFrame),
+ BOOL_OPTION("SortReceivedByDccFilesByNicks",false,KviOption_sectFlagDcc),
+ BOOL_OPTION("LogChannelHistory",true,KviOption_sectFlagConnection),
+ BOOL_OPTION("ClassicTaskBarSetMaximumButtonWidth",true,KviOption_groupTheme | KviOption_sectFlagGeometry | KviOption_resetUpdateGui),
+ BOOL_OPTION("KeepChannelsOpenOnDisconnect",false,KviOption_sectFlagFrame),
+ BOOL_OPTION("KeepQueriesOpenOnDisconnect",false,KviOption_sectFlagFrame),
+ BOOL_OPTION("HideWindowToolButtons",true,KviOption_sectFlagFrame),
+ BOOL_OPTION("HideInputToolButtons",true,KviOption_sectFlagFrame),
+ BOOL_OPTION("StripControlCodesInLogs",false,KviOption_sectFlagLogging),
+ BOOL_OPTION("EnableTrayIconFlashing",true,KviOption_sectFlagFrame),
+ BOOL_OPTION("UseFlatClassicTaskbarButtons",false,KviOption_sectFlagTaskBar | KviOption_resetUpdateGui | KviOption_groupTheme),
+ BOOL_OPTION("ShowTreeTaskbarHeader",false,KviOption_sectFlagTaskBar | KviOption_resetUpdateGui | KviOption_groupTheme),
+ BOOL_OPTION("UseLevelBasedTrayNotification",false,KviOption_sectFlagFrame),
+ BOOL_OPTION("MuteAllSounds",false,KviOption_sectFlagFrame),
+ BOOL_OPTION("CreateMinimizedChannels",false,KviOption_sectFlagFrame),
+ BOOL_OPTION("ShowNetworkNameForConsoleTaskBarEntry",true,KviOption_sectFlagFrame | KviOption_resetUpdateGui),
+ BOOL_OPTION("DrawGenderIcons",true,KviOption_sectFlagFrame | KviOption_resetUpdateGui | KviOption_groupTheme),
+ BOOL_OPTION("PrependGenderInfoToRealname",true,KviOption_sectFlagConnection),
+ BOOL_OPTION("UseIdentServiceOnlyOnConnect",true,KviOption_sectFlagConnection | KviOption_resetRestartIdentd),
+ BOOL_OPTION("UseSystemUrlHandlers",true,KviOption_sectFlagUrl),
+ BOOL_OPTION("ScaleAvatarsOnLoad",true,KviOption_sectFlagAvatar),
+ BOOL_OPTION("DisableNotifierFadein",false,KviOption_sectFlagFrame),
+ BOOL_OPTION("UseAntiAliasing",true,KviOption_sectFlagGui | KviOption_resetUpdateGui),
+};
+
+#define STRING_OPTION(_txt,_val,_flags) KviStringOption(KVI_STRING_OPTIONS_PREFIX _txt,_val,_flags)
+
+// FIXME: #warning "Remove the unused string options here!"
+
+#ifdef COMPILE_ON_WINDOWS
+ #define RUN_THE_BROWSER "run \"cmd.exe /c start \\\"\\\" \\\"$0\\\"\""
+#else
+ #ifdef COMPILE_KDE_SUPPORT
+ #define RUN_THE_BROWSER "run kfmclient openURL $0"
+ #else
+ #ifdef Q_OS_MACX
+ #define RUN_THE_BROWSER "run open $0"
+ #else
+ #define RUN_THE_BROWSER "run kvi_run_netscape $0"
+ #endif
+ #endif
+#endif
+
+KviStringOption g_stringOptionsTable[KVI_NUM_STRING_OPTIONS]=
+{
+ STRING_OPTION("UNUSED:FrameCaption","",KviOption_sectFlagFrame),
+ STRING_OPTION("Nickname1",KVI_DEFAULT_NICKNAME1,KviOption_sectFlagUser),
+ STRING_OPTION("Nickname2",KVI_DEFAULT_NICKNAME2,KviOption_sectFlagUser),
+ STRING_OPTION("Nickname3",KVI_DEFAULT_NICKNAME3,KviOption_sectFlagUser),
+ STRING_OPTION("Nickname4",KVI_DEFAULT_NICKNAME4,KviOption_sectFlagUser),
+ STRING_OPTION("Username",KVI_DEFAULT_USERNAME,KviOption_sectFlagUser),
+ STRING_OPTION("Realname",KVI_DEFAULT_REALNAME,KviOption_sectFlagUser),
+ STRING_OPTION("LocalHostIp","127.0.0.1",KviOption_sectFlagIrcSocket),
+ STRING_OPTION("PartMessage",KVI_DEFAULT_PART_MESSAGE,KviOption_sectFlagConnection),
+ STRING_OPTION("QuitMessage",KVI_DEFAULT_QUIT_MESSAGE,KviOption_sectFlagConnection),
+ STRING_OPTION("UrlHttpCommand",RUN_THE_BROWSER,KviOption_sectFlagUrl),
+ STRING_OPTION("ExtendedPrivmsgPrefix","[",KviOption_sectFlagIrcView | KviOption_groupTheme),
+ STRING_OPTION("ExtendedPrivmsgPostfix","] ",KviOption_sectFlagIrcView | KviOption_groupTheme),
+ STRING_OPTION("CtcpVersionPostfix","",KviOption_sectFlagCtcp),
+ STRING_OPTION("CtcpUserInfoOther",KVI_DEFAULT_CTCP_USERINFO_REPLY,KviOption_sectFlagUser),
+ STRING_OPTION("CtcpSourcePostfix","",KviOption_sectFlagCtcp),
+ STRING_OPTION("UrlFtpCommand",RUN_THE_BROWSER,KviOption_sectFlagUrl),
+ STRING_OPTION("UrlHttpsCommand",RUN_THE_BROWSER,KviOption_sectFlagUrl),
+ STRING_OPTION("UrlMailtoCommand",RUN_THE_BROWSER,KviOption_sectFlagUrl),
+ STRING_OPTION("PreferredMediaPlayer","auto",KviOption_sectFlagFrame),
+ STRING_OPTION("UrlFileCommand","play $0",KviOption_sectFlagUrl),
+ STRING_OPTION("NickCompletionPostfix",": ",KviOption_sectFlagInput),
+ STRING_OPTION("UrlUnknownCommand",RUN_THE_BROWSER,KviOption_sectFlagUrl),
+ STRING_OPTION("IpV4ConnectionBindAddress","",KviOption_sectFlagConnection),
+ STRING_OPTION("IpV6ConnectionBindAddress","",KviOption_sectFlagConnection),
+ STRING_OPTION("DccVoiceSoundDevice", "/dev/dsp",KviOption_sectFlagDcc),
+ STRING_OPTION("DccVoiceMixerDevice", "/dev/mixer",KviOption_sectFlagDcc),
+ STRING_OPTION("AwayMessage",KVI_DEFAULT_AWAY_MESSAGE,KviOption_sectFlagConnection),
+ STRING_OPTION("IdentdUser","kvirc",KviOption_sectFlagConnection | KviOption_resetRestartIdentd),
+ STRING_OPTION("DccListenDefaultInterface","ppp0",KviOption_sectFlagDcc),
+ STRING_OPTION("CustomAwayNick", KVI_DEFAULT_AWAY_NICK,KviOption_sectFlagConnection),
+ STRING_OPTION("DefaultDccFakeAddress","",KviOption_sectFlagDcc),
+ STRING_OPTION("CtcpPageReply",KVI_DEFAULT_CTCP_PAGE_REPLY,KviOption_sectFlagCtcp),
+ STRING_OPTION("SSLCertificatePath","",KviOption_sectFlagConnection | KviOption_encodePath),
+ STRING_OPTION("SSLCertificatePass","",KviOption_sectFlagConnection),
+ STRING_OPTION("SSLPrivateKeyPath","",KviOption_sectFlagConnection | KviOption_encodePath),
+ STRING_OPTION("SSLPrivateKeyPass","",KviOption_sectFlagConnection),
+ STRING_OPTION("SoundSystem","unknown",KviOption_sectFlagFrame),
+ STRING_OPTION("DefaultUserMode", "", KviOption_sectFlagUser),
+ STRING_OPTION("LastImageDialogPath","",KviOption_sectFlagUser | KviOption_encodePath),
+ STRING_OPTION("IconThemeSubdir","",KviOption_sectFlagUser | KviOption_groupTheme | KviOption_resetReloadImages | KviOption_encodePath),
+ STRING_OPTION("IncomingPath","",KviOption_sectFlagUser | KviOption_encodePath),
+ STRING_OPTION("MyAvatar","",KviOption_sectFlagUser),
+ STRING_OPTION("DefaultTextEncoding","",KviOption_sectFlagFrame),
+ STRING_OPTION("WinampTextEncoding","",KviOption_sectFlagFrame),
+ STRING_OPTION("Mp3TagsEncoding","",KviOption_sectFlagFrame),
+ STRING_OPTION("CtcpUserInfoAge","",KviOption_sectFlagUser),
+ STRING_OPTION("CtcpUserInfoGender","",KviOption_sectFlagUser),
+ STRING_OPTION("CtcpUserInfoLocation","",KviOption_sectFlagUser),
+ STRING_OPTION("CtcpUserInfoLanguages","",KviOption_sectFlagUser),
+ STRING_OPTION("WordSplitters",",\"';:|.%^~!\\$#()",KviOption_sectFlagIrcView),
+ STRING_OPTION("OnNewQueryOpenedSound","",KviOption_sectFlagFrame),
+ STRING_OPTION("OnHighlightedMessageSound","",KviOption_sectFlagFrame),
+ STRING_OPTION("OnMeKickedSound","",KviOption_sectFlagFrame),
+ STRING_OPTION("OnQueryMessageSound","",KviOption_sectFlagFrame),
+ STRING_OPTION("IrcViewTimestampFormat","[hh:mm:ss]",KviOption_sectFlagIrcView),
+ STRING_OPTION("PreferredTorrentClient","auto",KviOption_sectFlagFrame)
+};
+
+#define STRINGLIST_OPTION(_txt,_flags) \
+ KviStringListOption(KVI_STRINGLIST_OPTIONS_PREFIX _txt,QStringList(),_flags)
+
+#define STRINGLIST_OPTION_WITHDEFAULT(_txt,_flags,_def) \
+ KviStringListOption(KVI_STRINGLIST_OPTIONS_PREFIX _txt,QStringList(_def),_flags)
+
+
+KviStringListOption g_stringlistOptionsTable[KVI_NUM_STRINGLIST_OPTIONS]=
+{
+ STRINGLIST_OPTION("HighlightWords",KviOption_sectFlagIrcView),
+ STRINGLIST_OPTION("SpamWords",KviOption_sectFlagAntiSpam),
+ STRINGLIST_OPTION_WITHDEFAULT("RecentChannels",KviOption_sectFlagRecent,"#kvirc"),
+ STRINGLIST_OPTION("RecentServers",KviOption_sectFlagRecent),
+ STRINGLIST_OPTION("RecentNicknames",KviOption_sectFlagRecent),
+ STRINGLIST_OPTION("ModuleExtensionToolbars",KviOption_sectFlagFrame),
+ STRINGLIST_OPTION("ImageSearchPaths",KviOption_sectFlagFrame | KviOption_encodePath),
+ STRINGLIST_OPTION("RecentIrcUrls",KviOption_sectFlagRecent)
+};
+
+#define MIRC_COLOR_OPTION(_num,_red,_green,_blue) \
+ KviColorOption(KVI_MIRCCOLOR_OPTIONS_PREFIX _num,QColor(_red,_green,_blue), \
+ KviOption_sectFlagMircColor | KviOption_resetUpdateGui | KviOption_groupTheme)
+
+KviColorOption g_mirccolorOptionsTable[KVI_NUM_MIRCCOLOR_OPTIONS]=
+{
+ MIRC_COLOR_OPTION("0",255,255,255),
+ MIRC_COLOR_OPTION("1",0,0,0),
+ MIRC_COLOR_OPTION("2",0,0,140),
+ MIRC_COLOR_OPTION("3",0,100,0),
+ MIRC_COLOR_OPTION("4",230,0,0),
+ MIRC_COLOR_OPTION("5",150,0,0),
+ MIRC_COLOR_OPTION("6",80,0,80),
+ MIRC_COLOR_OPTION("7",255,90,0),
+ MIRC_COLOR_OPTION("8",255,255,0),
+ MIRC_COLOR_OPTION("9",0,255,0),
+ MIRC_COLOR_OPTION("10",0,150,180),
+ MIRC_COLOR_OPTION("11",170,170,255),
+ MIRC_COLOR_OPTION("12",15,15,255),
+ MIRC_COLOR_OPTION("13",200,0,200),
+ MIRC_COLOR_OPTION("14",80,80,80),
+ MIRC_COLOR_OPTION("15",170,170,170)
+};
+
+#define COLOR_OPTION(_name,_red,_green,_blue,_flags) \
+ KviColorOption(KVI_COLOR_OPTIONS_PREFIX _name, \
+ QColor(_red,_green,_blue), \
+ _flags | KviOption_resetUpdateGui | KviOption_groupTheme)
+
+KviColorOption g_colorOptionsTable[KVI_NUM_COLOR_OPTIONS]=
+{
+ COLOR_OPTION("MdiBackground",0,0,0,KviOption_sectFlagMdi),
+ COLOR_OPTION("TaskBarNormalText",0,0,0,KviOption_sectFlagTaskBar),
+ COLOR_OPTION("TaskBarMinimizedText",60,60,60,KviOption_sectFlagTaskBar),
+ COLOR_OPTION("TaskBarHighlight1Text",0,16,144,KviOption_sectFlagTaskBar),
+ COLOR_OPTION("TaskBarHighlight2Text",32,0,255,KviOption_sectFlagTaskBar),
+ COLOR_OPTION("TaskBarProgressBar",180,180,180,KviOption_sectFlagTaskBar),
+ COLOR_OPTION("MdiCaptionActive",113,125,190,KviOption_sectFlagMdi),
+ COLOR_OPTION("MdiCaptionInactive",180,180,180,KviOption_sectFlagMdi),
+ COLOR_OPTION("CaptionTextActive",255,255,255,KviOption_sectFlagWindows),
+ COLOR_OPTION("CaptionTextActive2",255,30,30,KviOption_sectFlagWindows),
+ COLOR_OPTION("CaptionTextInactive",0,0,0,KviOption_sectFlagWindows),
+ COLOR_OPTION("CaptionTextInactive2",30,30,30,KviOption_sectFlagWindows),
+ COLOR_OPTION("IrcViewBackground",255,255,255,KviOption_sectFlagIrcView),
+ COLOR_OPTION("InputBackgroundColor",255,255,255,KviOption_sectFlagInput),
+ COLOR_OPTION("InputSelectionBackground",0,0,0,KviOption_sectFlagInput),
+ COLOR_OPTION("InputSelectionForeground",255,255,255,KviOption_sectFlagInput),
+ COLOR_OPTION("InputCursor",0,0,0,KviOption_sectFlagInput),
+ COLOR_OPTION("InputControl",200,100,0,KviOption_sectFlagInput),
+ COLOR_OPTION("InputForeground",0,0,0,KviOption_sectFlagInput),
+ COLOR_OPTION("UserListViewBackground",255,255,255,KviOption_sectFlagUserListView),
+ COLOR_OPTION("UserListViewOpForeground",200,0,0,KviOption_sectFlagUserListView),
+ COLOR_OPTION("UserListViewVoiceForeground",0,0,200,KviOption_sectFlagUserListView),
+ COLOR_OPTION("UserListViewNormalForeground",0,0,0,KviOption_sectFlagUserListView),
+ COLOR_OPTION("UserListViewSelectionBackground",0,0,0,KviOption_sectFlagUserListView),
+ COLOR_OPTION("UserListViewSelectionForeground",255,255,255,KviOption_sectFlagUserListView),
+ COLOR_OPTION("LabelBackground",255,255,255,KviOption_sectFlagLabel),
+ COLOR_OPTION("LabelForeground",0,0,0,KviOption_sectFlagLabel),
+ COLOR_OPTION("GlobalTransparencyFade",255,255,255,KviOption_sectFlagGui | KviOption_resetUpdatePseudoTransparency),
+ COLOR_OPTION("IrcToolBarAppletBackground",255,255,255,KviOption_sectFlagIrcToolBar),
+ COLOR_OPTION("IrcToolBarAppletForegroundLowContrast",180,180,180,KviOption_sectFlagIrcToolBar),
+ COLOR_OPTION("IrcToolBarAppletForegroundMidContrast",110,110,110,KviOption_sectFlagIrcToolBar),
+ COLOR_OPTION("IrcToolBarAppletForegroundHighContrastInactive1",40,40,40,KviOption_sectFlagIrcToolBar),
+ COLOR_OPTION("IrcToolBarAppletForegroundHighContrastInactive2",40,40,40,KviOption_sectFlagIrcToolBar),
+ COLOR_OPTION("IrcToolBarAppletForegroundHighContrastActive1",0,0,0,KviOption_sectFlagIrcToolBar),
+ COLOR_OPTION("IrcToolBarAppletForegroundHighContrastActive2",0,60,0,KviOption_sectFlagIrcToolBar),
+ COLOR_OPTION("TreeTaskBarBackground",255,255,255,KviOption_sectFlagTaskBar),
+ COLOR_OPTION("TreeTaskBarActiveBackground",200,200,200,KviOption_sectFlagTaskBar),
+ COLOR_OPTION("TreeTaskBarForeground",0,0,0,KviOption_sectFlagTaskBar),
+ COLOR_OPTION("TreeTaskBarActiveForeground",0,0,0,KviOption_sectFlagTaskBar),
+ COLOR_OPTION("TreeTaskBarHighlight1Foreground",0,16,144,KviOption_sectFlagTaskBar),
+ COLOR_OPTION("TreeTaskBarHighlight2Foreground",32,0,255,KviOption_sectFlagTaskBar),
+ COLOR_OPTION("TreeTaskBarProgress",150,150,150,KviOption_sectFlagTaskBar),
+ COLOR_OPTION("UserListViewHalfOpForeground",119,0,178,KviOption_sectFlagUserListView),
+ COLOR_OPTION("TaskBarHighlight3Text",128,20,255,KviOption_sectFlagTaskBar),
+ COLOR_OPTION("TaskBarHighlight4Text",220,0,255,KviOption_sectFlagTaskBar),
+ COLOR_OPTION("TaskBarHighlight5Text",255,0,0,KviOption_sectFlagTaskBar),
+ COLOR_OPTION("TreeTaskBarHighlight3Foreground",128,0,255,KviOption_sectFlagTaskBar),
+ COLOR_OPTION("TreeTaskBarHighlight4Foreground",220,0,255,KviOption_sectFlagTaskBar),
+ COLOR_OPTION("TreeTaskBarHighlight5Foreground",255,0,0,KviOption_sectFlagTaskBar),
+ COLOR_OPTION("UserListViewChanAdminForeground",83,54,5,KviOption_sectFlagUserListView),
+ COLOR_OPTION("UserListViewUserOpForeground",0,127,178,KviOption_sectFlagUserListView),
+ COLOR_OPTION("UserListViewGrid",110,110,110,KviOption_sectFlagUserListView),
+ COLOR_OPTION("UserListViewChanOwnerForeground",81,87,111,KviOption_sectFlagUserListView),
+ COLOR_OPTION("IrcViewMarkLine",40,40,40,KviOption_sectFlagIrcView),
+ COLOR_OPTION("UserListViewAwayForeground",143,143,143,KviOption_sectFlagUserListView),
+ COLOR_OPTION("UserListViewOwnForeground",255,255,0,KviOption_sectFlagUserListView)
+};
+
+
+#define IC_COLOR_OPTION(_num,_red,_green,_blue) \
+ KviColorOption( \
+ KVI_ICCOLOR_OPTIONS_PREFIX _num, \
+ QColor(_red,_green,_blue), \
+ KviOption_sectFlagTaskBar | KviOption_resetUpdateGui | KviOption_groupTheme)
+
+KviColorOption g_iccolorOptionsTable[KVI_NUM_ICCOLOR_OPTIONS]=
+{
+ IC_COLOR_OPTION("0",250,250,0),
+ IC_COLOR_OPTION("1",0,0,0),
+ IC_COLOR_OPTION("2",0,0,200),
+ IC_COLOR_OPTION("3",200,0,0),
+ IC_COLOR_OPTION("4",255,255,255),
+ IC_COLOR_OPTION("5",0,150,190),
+ IC_COLOR_OPTION("6",0,130,0),
+ IC_COLOR_OPTION("7",150,0,170)
+};
+
+#define PIXMAP_OPTION(_name,_flags) \
+ KviPixmapOption( \
+ KVI_PIXMAP_OPTIONS_PREFIX _name , \
+ KviPixmap(), \
+ _flags | KviOption_resetUpdateGui)
+
+KviPixmapOption g_pixmapOptionsTable[KVI_NUM_PIXMAP_OPTIONS]=
+{
+ PIXMAP_OPTION("MdiBackground",KviOption_sectFlagMdi | KviOption_groupTheme),
+ PIXMAP_OPTION("IrcViewBackground",KviOption_sectFlagIrcView | KviOption_groupTheme),
+ PIXMAP_OPTION("InputBackground",KviOption_sectFlagInput | KviOption_groupTheme),
+ PIXMAP_OPTION("UserListViewBackground",KviOption_sectFlagUserListView | KviOption_groupTheme),
+ PIXMAP_OPTION("LabelBackground",KviOption_sectFlagLabel | KviOption_groupTheme),
+ PIXMAP_OPTION("MyAvatar",KviOption_sectFlagUser),
+ PIXMAP_OPTION("IrcToolBarAppletBackground",KviOption_sectFlagIrcToolBar | KviOption_groupTheme),
+ PIXMAP_OPTION("TreeTaskBarBackground",KviOption_sectFlagTaskBar | KviOption_groupTheme),
+ PIXMAP_OPTION("GlobalTransparencyBackground",KviOption_sectFlagGui | KviOption_resetUpdatePseudoTransparency | KviOption_groupTheme)
+};
+
+//#define INT_OPTION(_name,_value,_flags)
+// {
+// KVI_INT_OPTIONS_PREFIX _name ,
+// _value ,
+// _flags
+// }
+//
+//KviIntOption g_intOptionsTable[KVI_NUM_INT_OPTIONS]=
+//{
+// INT_OPTION("IrcViewMaxBufferSize",KVI_IRCVIEW_MAX_LINES,KviOption_sectFlagIrcView),
+// INT_OPTION("IrcViewTollTipTimeoutInMsec",1800,KviOption_sectFlagIrcView),
+// INT_OPTION("IrcViewToolTipHideTimeoutInMsec",10000,KviOption_sectFlagIrcView)
+//};
+
+#define UINT_OPTION(_name,_value,_flags) \
+ KviUIntOption( \
+ KVI_UINT_OPTIONS_PREFIX _name , \
+ _value , \
+ _flags \
+ )
+
+KviUIntOption g_uintOptionsTable[KVI_NUM_UINT_OPTIONS]=
+{
+ UINT_OPTION("IrcSocketTimeout",60,KviOption_sectFlagIrcSocket),
+ UINT_OPTION("ModuleCleanupTimerInterval",90,KviOption_sectFlagModules),
+ UINT_OPTION("ModuleCleanupTimeout",180,KviOption_sectFlagModules),
+ UINT_OPTION("MaxCtcpRequests",5,KviOption_sectFlagCtcp),
+ UINT_OPTION("CtcpFloodCheckInterval",10,KviOption_sectFlagCtcp),
+ UINT_OPTION("TotalConnectionTime",0,0),
+ UINT_OPTION("DccSocketTimeout",360,KviOption_sectFlagDcc),
+ UINT_OPTION("DccSendIdleStepInMSec",30,KviOption_sectFlagDcc),
+ UINT_OPTION("DccSendPacketSize",4096,KviOption_sectFlagDcc),
+ UINT_OPTION("GlobalTransparencyParentFadeFactor",10,KviOption_sectFlagGui | KviOption_resetUpdatePseudoTransparency | KviOption_groupTheme),
+ UINT_OPTION("GlobalTransparencyChildFadeFactor",50,KviOption_sectFlagGui | KviOption_resetUpdatePseudoTransparency | KviOption_groupTheme),
+ UINT_OPTION("NotifyListCheckTimeInSecs",180,KviOption_sectFlagConnection),
+ UINT_OPTION("SocketQueueFlushTimeout",500,KviOption_sectFlagIrcSocket),
+ UINT_OPTION("OutgoingTrafficLimitUSeconds",2000000,KviOption_sectFlagIrcSocket),
+ UINT_OPTION("NotifyListIsOnDelayTimeInSecs",6,KviOption_sectFlagConnection),
+ UINT_OPTION("NotifyListUserhostDelayTimeInSecs",6,KviOption_sectFlagConnection),
+ UINT_OPTION("TreeTaskBarMinimumWidth",24,KviOption_sectFlagTaskBar | KviOption_resetUpdateTaskBar),
+ UINT_OPTION("AvatarOfferTimeoutInSecs",60,KviOption_sectFlagAvatar),
+ UINT_OPTION("IrcViewMaxBufferSize",1024,KviOption_sectFlagIrcView),
+ UINT_OPTION("IrcViewToolTipTimeoutInMsec",1200,KviOption_sectFlagIrcView),
+ UINT_OPTION("IrcViewToolTipHideTimeoutInMsec",12000,KviOption_sectFlagIrcView),
+ UINT_OPTION("DccVoicePreBufferSize",32000,KviOption_sectFlagDcc),
+ UINT_OPTION("IdentdPort",113,KviOption_sectFlagConnection | KviOption_resetRestartIdentd),
+ UINT_OPTION("AvatarScaleWidth",80,KviOption_sectFlagAvatar | KviOption_resetUpdateGui),
+ UINT_OPTION("AvatarScaleHeight",80,KviOption_sectFlagAvatar | KviOption_resetUpdateGui),
+ UINT_OPTION("DccMinPort",30000,KviOption_sectFlagDcc),
+ UINT_OPTION("DccMaxPort",31000,KviOption_sectFlagDcc),
+ UINT_OPTION("SoundOfferTimeoutInSecs",60,KviOption_sectFlagConnection),
+ UINT_OPTION("MaximumRequestedAvatarSize",256000,KviOption_sectFlagAvatar),
+ UINT_OPTION("TreeTaskBarMaximumWidth",200,KviOption_sectFlagTaskBar | KviOption_resetUpdateTaskBar),
+ UINT_OPTION("PasteDelay",2000,KviOption_sectFlagInput),
+ UINT_OPTION("MaxDccSendTransfers",10,KviOption_sectFlagDcc),
+ UINT_OPTION("MaxDccSlots",64,KviOption_sectFlagDcc),
+ UINT_OPTION("TileMethod",5,KviOption_sectFlagMdi),
+ UINT_OPTION("LagMeterHeartbeat",5000,KviOption_sectFlagConnection | KviOption_resetRestartLagMeter),
+ UINT_OPTION("LagAlarmTime",120000,KviOption_sectFlagConnection),
+ UINT_OPTION("UNUSED",0,KviOption_sectFlagFrame),
+ UINT_OPTION("TaskBarButtonMinWidth",100,KviOption_sectFlagTaskBar),
+ UINT_OPTION("OutputVerbosityLevel",KVI_VERBOSITY_LEVEL_NORMAL,KviOption_sectFlagFrame),
+ UINT_OPTION("IrcContextAppletWidth",160,KviOption_sectFlagFrame),
+ UINT_OPTION("MinHighlightLevel",0,KviOption_uintMinHighlightLevel),
+ UINT_OPTION("UserListViewGridType",3,KviOption_sectFlagUserListView | KviOption_resetUpdateGui | KviOption_groupTheme),
+ UINT_OPTION("TaskBarMaximumRows",2,KviOption_sectFlagFrame),
+ UINT_OPTION("MaxAutoReconnectAttempts",15,KviOption_sectFlagFrame),
+ UINT_OPTION("AutoReconnectDelay",10,KviOption_sectFlagFrame),
+ UINT_OPTION("MaxDccSendSpeed",0,KviOption_sectFlagFrame),
+ UINT_OPTION("MaxDccRecvSpeed",0,KviOption_sectFlagFrame),
+ UINT_OPTION("TimeStampForeground",KVI_DARKGRAY,KviOption_sectFlagIrcView | KviOption_resetUpdateGui | KviOption_groupTheme),
+ UINT_OPTION("TimeStampBackground",KVI_TRANSPARENT,KviOption_sectFlagIrcView | KviOption_resetUpdateGui | KviOption_groupTheme),
+ UINT_OPTION("UserExperienceLevel",1,KviOption_sectFlagUser),
+ UINT_OPTION("ClassicTaskBarMaximumButtonWidth",100,KviOption_sectFlagGeometry | KviOption_resetUpdateGui | KviOption_groupTheme),
+ UINT_OPTION("DefaultBanType",7,KviOption_sectFlagIrcSocket),
+ UINT_OPTION("IrcViewPixmapAlign",0,KviOption_sectFlagIrcView | KviOption_groupTheme),
+ UINT_OPTION("UserListPixmapAlign",0,KviOption_sectFlagFrame | KviOption_groupTheme),
+ UINT_OPTION("ToolBarAppletPixmapAlign",0,KviOption_sectFlagFrame | KviOption_groupTheme),
+ UINT_OPTION("TreeTaskBarPixmapAlign",0,KviOption_sectFlagFrame | KviOption_groupTheme),
+ UINT_OPTION("InputPixmapAlign",0,KviOption_sectFlagFrame | KviOption_groupTheme),
+ UINT_OPTION("AutoFlushLogs",30,KviOption_sectFlagFrame ),
+ UINT_OPTION("MinTrayLowLevelMessage",1,KviOption_sectFlagFrame ),
+ UINT_OPTION("MinTrayHighLevelMessage",4,KviOption_sectFlagFrame ),
+ UINT_OPTION("IdentdOutputMode",KviIdentdOutputMode::Quiet,KviOption_sectFlagConnection ),
+ UINT_OPTION("ScaleAvatarsOnLoadHeight",600,KviOption_sectFlagAvatar ),
+ UINT_OPTION("ScaleAvatarsOnLoadWidth",800,KviOption_sectFlagAvatar ),
+ UINT_OPTION("NotifierActiveTransparency",90,KviOption_sectFlagFrame ),
+ UINT_OPTION("NotifierInactiveTransparency",40,KviOption_sectFlagFrame )
+};
+
+#define FONT_OPTION(_name,_face,_size,_flags) \
+ KviFontOption( \
+ KVI_FONT_OPTIONS_PREFIX _name , \
+ QFont(_face,_size) , \
+ _flags | KviOption_groupTheme \
+ )
+
+KviFontOption g_fontOptionsTable[KVI_NUM_FONT_OPTIONS]=
+{
+#ifdef COMPILE_ON_WINDOWS
+ FONT_OPTION("IrcView","Arial",9,KviOption_sectFlagIrcView | KviOption_resetUpdateGui),
+ FONT_OPTION("Input","Arial",12,KviOption_sectFlagInput | KviOption_resetUpdateGui),
+ FONT_OPTION("UserListView","Arial",9,KviOption_sectFlagUserListView | KviOption_resetUpdateGui),
+ FONT_OPTION("Label","Arial",9,KviOption_sectFlagLabel | KviOption_resetUpdateGui),
+ FONT_OPTION("Application","Arial",9,KviOption_sectFlagGui | KviOption_resetUpdateAppFont),
+ FONT_OPTION("IrcToolBarApplet","Arial",9,KviOption_sectFlagIrcToolBar | KviOption_resetUpdateGui),
+ FONT_OPTION("Taskbar","Arial",9,KviOption_sectFlagTaskBar | KviOption_resetUpdateTaskBar)
+#else
+ #if QT_VERSION >= 300
+ FONT_OPTION("IrcView","Monospace",10,KviOption_sectFlagIrcView | KviOption_resetUpdateGui),
+ FONT_OPTION("Input","Sans Serif",12,KviOption_sectFlagInput | KviOption_resetUpdateGui),
+ FONT_OPTION("UserListView","Sans Serif",10,KviOption_sectFlagUserListView | KviOption_resetUpdateGui),
+ FONT_OPTION("Label","Sans Serif",10,KviOption_sectFlagLabel | KviOption_resetUpdateGui),
+ FONT_OPTION("Application","Sans Serif",10,KviOption_sectFlagGui | KviOption_resetUpdateAppFont),
+ FONT_OPTION("IrcToolBarApplet","Sans Serif",10,KviOption_sectFlagIrcToolBar | KviOption_resetUpdateGui),
+ FONT_OPTION("Taskbar","Sans Serif",10,KviOption_sectFlagTaskBar | KviOption_resetUpdateTaskBar)
+ #else
+ FONT_OPTION("IrcView","Monospace",12,KviOption_sectFlagIrcView | KviOption_resetUpdateGui),
+ FONT_OPTION("Input","Sans Serif",16,KviOption_sectFlagInput | KviOption_resetUpdateGui),
+ FONT_OPTION("UserListView","Sans Serif",12,KviOption_sectFlagUserListView | KviOption_resetUpdateGui),
+ FONT_OPTION("Label","Sans Serif",12,KviOption_sectFlagLabel | KviOption_resetUpdateGui),
+ FONT_OPTION("Application","Sans Serif",12,KviOption_sectFlagGui | KviOption_resetUpdateAppFont),
+ FONT_OPTION("IrcToolBarApplet","Sans Serif",10,KviOption_sectFlagIrcToolBar | KviOption_resetUpdateGui),
+ FONT_OPTION("Taskbar","Sans Serif",10,KviOption_sectFlagTaskBar | KviOption_resetUpdateTaskBar)
+ #endif
+#endif
+};
+
+#define MSGTYPE_OPTION(_name,_text,_icon,_levl) \
+ KviMsgTypeOption( \
+ KVI_MSGTYPE_OPTIONS_PREFIX _name , \
+ KviMsgType(_text,_icon,KVI_BLACK,KVI_TRANSPARENT,true,_levl), \
+ KviOption_sectFlagMsgType | KviOption_groupTheme \
+ )
+
+#define MSGTYPE_OPTION_SPEC(_name,_text,_icon,_fore,_back,_levl) \
+ KviMsgTypeOption( \
+ KVI_MSGTYPE_OPTIONS_PREFIX _name , \
+ KviMsgType(_text,_icon,_fore,_back,true,_levl), \
+ KviOption_sectFlagMsgType | KviOption_groupTheme \
+ )
+
+
+
+// FIXME: #warning "FIX THE ICONS HERE!!!"
+
+KviMsgTypeOption g_msgtypeOptionsTable[KVI_NUM_MSGTYPE_OPTIONS]=
+{
+ MSGTYPE_OPTION("Echo",__tr_no_lookup("Normal text"),KVI_SMALLICON_NONE,KVI_MSGTYPE_LEVEL_1),
+ MSGTYPE_OPTION_SPEC("Selection",__tr_no_lookup("Selection"),KVI_SMALLICON_NONE,KVI_WHITE,KVI_BLACK,KVI_MSGTYPE_LEVEL_1),
+ MSGTYPE_OPTION_SPEC("Highlight",__tr_no_lookup("Highlighted text"),KVI_SMALLICON_ALERT,KVI_WHITE,KVI_BLACK,KVI_MSGTYPE_LEVEL_5),
+ MSGTYPE_OPTION_SPEC("Url",__tr_no_lookup("URL foreground"),KVI_SMALLICON_NONE,KVI_BLUE,KVI_TRANSPARENT,KVI_MSGTYPE_LEVEL_1),
+ MSGTYPE_OPTION_SPEC("Link",__tr_no_lookup("Link overlay foreground"),KVI_SMALLICON_NONE,KVI_BLUE,KVI_TRANSPARENT,KVI_MSGTYPE_LEVEL_1),
+ MSGTYPE_OPTION_SPEC("ParserError",__tr_no_lookup("Parser error"),KVI_SMALLICON_PARSERERROR,KVI_RED,KVI_TRANSPARENT,KVI_MSGTYPE_LEVEL_2),
+ MSGTYPE_OPTION_SPEC("ParserWarning",__tr_no_lookup("Parser warning"),KVI_SMALLICON_PARSERWARNING,KVI_RED,KVI_TRANSPARENT,KVI_MSGTYPE_LEVEL_2),
+ MSGTYPE_OPTION("HostLookup",__tr_no_lookup("Host lookup result"),KVI_SMALLICON_SERVER,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("SocketMessage",__tr_no_lookup("Socket message"),KVI_SMALLICON_SOCKETMESSAGE,KVI_MSGTYPE_LEVEL_1),
+ MSGTYPE_OPTION("SocketWarning",__tr_no_lookup("Socket warning"),KVI_SMALLICON_SOCKETWARNING,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION_SPEC("SocketError",__tr_no_lookup("Socket error"),KVI_SMALLICON_SOCKETERROR,KVI_RED,KVI_TRANSPARENT,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION_SPEC("SystemError",__tr_no_lookup("System error"),KVI_SMALLICON_SYSTEMERROR,KVI_RED,KVI_TRANSPARENT,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("Raw",__tr_no_lookup("Raw data to server"),KVI_SMALLICON_RAW,KVI_MSGTYPE_LEVEL_1),
+ MSGTYPE_OPTION("Connection",__tr_no_lookup("Connection status"),KVI_SMALLICON_WORLD,KVI_MSGTYPE_LEVEL_1),
+ MSGTYPE_OPTION("SystemWarning",__tr_no_lookup("System warning"),KVI_SMALLICON_SYSTEMWARNING,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("SystemMessage",__tr_no_lookup("System message"),KVI_SMALLICON_SYSTEMMESSAGE,KVI_MSGTYPE_LEVEL_1),
+ MSGTYPE_OPTION("UnhandledReply",__tr_no_lookup("Unhandled server reply"),KVI_SMALLICON_UNHANDLED,KVI_MSGTYPE_LEVEL_1),
+ MSGTYPE_OPTION("ServerInfo",__tr_no_lookup("Server information"),KVI_SMALLICON_SERVERINFO,KVI_MSGTYPE_LEVEL_1),
+ MSGTYPE_OPTION("Motd",__tr_no_lookup("Server Message of the Day"),KVI_SMALLICON_MOTD,KVI_MSGTYPE_LEVEL_1),
+ MSGTYPE_OPTION("ServerPing",__tr_no_lookup("Server ping"),KVI_SMALLICON_SERVERPING,KVI_MSGTYPE_LEVEL_1),
+ MSGTYPE_OPTION("Join",__tr_no_lookup("Join message"),KVI_SMALLICON_JOIN,KVI_MSGTYPE_LEVEL_1),
+ MSGTYPE_OPTION("Part",__tr_no_lookup("Part message"),KVI_SMALLICON_PART,KVI_MSGTYPE_LEVEL_1),
+ MSGTYPE_OPTION("Unrecognized",__tr_no_lookup("Unrecognized/broken message"),KVI_SMALLICON_UNRECOGNIZED,KVI_MSGTYPE_LEVEL_2),
+ MSGTYPE_OPTION("Topic",__tr_no_lookup("Topic message"),KVI_SMALLICON_TOPIC,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("OwnPrivateMessage",__tr_no_lookup("Own private message"),KVI_SMALLICON_OWNPRIVMSG,KVI_MSGTYPE_LEVEL_1),
+ MSGTYPE_OPTION("ChannelPrivateMessage",__tr_no_lookup("Channel private message"),KVI_SMALLICON_CHANPRIVMSG,KVI_MSGTYPE_LEVEL_4),
+ MSGTYPE_OPTION("QueryPrivateMessage",__tr_no_lookup("Query private message"),KVI_SMALLICON_QUERYPRIVMSG,KVI_MSGTYPE_LEVEL_4),
+ MSGTYPE_OPTION("CtcpReply",__tr_no_lookup("CTCP reply"),KVI_SMALLICON_CTCPREPLY,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("CtcpRequestReplied",__tr_no_lookup("CTCP request replied"),KVI_SMALLICON_CTCPREQUESTREPLIED,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("CtcpRequestIgnored",__tr_no_lookup("CTCP request ignored"),KVI_SMALLICON_CTCPREQUESTIGNORED,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("CtcpRequestFlood",__tr_no_lookup("CTCP request flood warning"),KVI_SMALLICON_CTCPREQUESTFLOOD,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("CtcpRequestUnknown",__tr_no_lookup("CTCP request unknown"),KVI_SMALLICON_CTCPREQUESTUNKNOWN,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("Action",__tr_no_lookup("User action"),KVI_SMALLICON_ACTION,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("AvatarChange",__tr_no_lookup("Avatar change"),KVI_SMALLICON_AVATAR,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("Quit",__tr_no_lookup("Quit message"),KVI_SMALLICON_QUIT,KVI_MSGTYPE_LEVEL_1),
+ MSGTYPE_OPTION("Split",__tr_no_lookup("Split message"),KVI_SMALLICON_SPLIT,KVI_MSGTYPE_LEVEL_2),
+ MSGTYPE_OPTION("QuitSplit",__tr_no_lookup("Quit on netsplit message"),KVI_SMALLICON_QUITSPLIT,KVI_MSGTYPE_LEVEL_2),
+ MSGTYPE_OPTION("Nick",__tr_no_lookup("Nick changes"),KVI_SMALLICON_NICK,KVI_MSGTYPE_LEVEL_2),
+ MSGTYPE_OPTION("Op",__tr_no_lookup("+o mode change"),KVI_SMALLICON_OP,KVI_MSGTYPE_LEVEL_2),
+ MSGTYPE_OPTION("Deop",__tr_no_lookup("-o mode change"),KVI_SMALLICON_DEOP,KVI_MSGTYPE_LEVEL_2),
+ MSGTYPE_OPTION("Voice",__tr_no_lookup("+v mode change"),KVI_SMALLICON_VOICE,KVI_MSGTYPE_LEVEL_2),
+ MSGTYPE_OPTION("Devoice",__tr_no_lookup("-v mode change"),KVI_SMALLICON_DEVOICE,KVI_MSGTYPE_LEVEL_2),
+ MSGTYPE_OPTION("Mode",__tr_no_lookup("Multiple user mode change"),KVI_SMALLICON_MODE,KVI_MSGTYPE_LEVEL_2),
+ MSGTYPE_OPTION("Key",__tr_no_lookup("Channel key change"),KVI_SMALLICON_KEY,KVI_MSGTYPE_LEVEL_2),
+ MSGTYPE_OPTION("Limit",__tr_no_lookup("Channel limit change"),KVI_SMALLICON_LIMIT,KVI_MSGTYPE_LEVEL_2),
+ MSGTYPE_OPTION("Ban",__tr_no_lookup("+b mode change"),KVI_SMALLICON_BAN,KVI_MSGTYPE_LEVEL_2),
+ MSGTYPE_OPTION("Unban",__tr_no_lookup("-b mode change"),KVI_SMALLICON_UNBAN,KVI_MSGTYPE_LEVEL_2),
+ MSGTYPE_OPTION("BanExcept",__tr_no_lookup("+e mode change"),KVI_SMALLICON_BANEXCEPT,KVI_MSGTYPE_LEVEL_2),
+ MSGTYPE_OPTION("BanUnexcept",__tr_no_lookup("-e mode change"),KVI_SMALLICON_BANUNEXCEPT,KVI_MSGTYPE_LEVEL_2),
+ MSGTYPE_OPTION("InviteExcept",__tr_no_lookup("+I mode change"),KVI_SMALLICON_INVITEEXCEPT,KVI_MSGTYPE_LEVEL_2),
+ MSGTYPE_OPTION("InviteUnexcept",__tr_no_lookup("-I mode change"),KVI_SMALLICON_INVITEUNEXCEPT,KVI_MSGTYPE_LEVEL_2),
+ MSGTYPE_OPTION("ChanMode",__tr_no_lookup("Multiple channel mode change"),KVI_SMALLICON_CHANMODE,KVI_MSGTYPE_LEVEL_2),
+ MSGTYPE_OPTION("Who",__tr_no_lookup("Who reply"),KVI_SMALLICON_WHO,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("DccRequest",__tr_no_lookup("DCC request"),KVI_SMALLICON_DCCREQUEST,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("DccMsg",__tr_no_lookup("DCC message"),KVI_SMALLICON_DCCMSG,KVI_MSGTYPE_LEVEL_2),
+ MSGTYPE_OPTION("DccError",__tr_no_lookup("DCC error"),KVI_SMALLICON_DCCERROR,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("NicknameProblem",__tr_no_lookup("Nickname problem"),KVI_SMALLICON_NICKNAMEPROBLEM,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("WhoisUser",__tr_no_lookup("Whois user reply"),KVI_SMALLICON_WHOISUSER,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("WhoisChannels",__tr_no_lookup("Whois channels reply"),KVI_SMALLICON_WHOISCHANNELS,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("WhoisIdle",__tr_no_lookup("Whois idle reply"),KVI_SMALLICON_WHOISIDLE,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("WhoisServer",__tr_no_lookup("Whois server reply"),KVI_SMALLICON_WHOISSERVER,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("WhoisOther",__tr_no_lookup("Whois other reply"),KVI_SMALLICON_WHOISOTHER,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("CreationTime",__tr_no_lookup("Channel creation time reply"),KVI_SMALLICON_TIME,KVI_MSGTYPE_LEVEL_1),
+ MSGTYPE_OPTION("NotifyOnLine",__tr_no_lookup("Notify list joins"),KVI_SMALLICON_NOTIFYONLINE,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("NotifyOffLine",__tr_no_lookup("Notify list leaves"),KVI_SMALLICON_NOTIFYOFFLINE,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("OwnPrivmsgCrypted",__tr_no_lookup("Own encrypted private message"),KVI_SMALLICON_OWNPRIVMSGCRYPTED,KVI_MSGTYPE_LEVEL_1),
+ MSGTYPE_OPTION("ChanPrivmsgCrypted",__tr_no_lookup("Channel encrypted private message"),KVI_SMALLICON_CHANPRIVMSGCRYPTED,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("QueryPrivmsgCrypted",__tr_no_lookup("Query encrypted private message"),KVI_SMALLICON_QUERYPRIVMSGCRYPTED,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("DccChatMsg",__tr_no_lookup("DCC chat message"),KVI_SMALLICON_DCCCHATMSG,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("DccChatMsgCrypted",__tr_no_lookup("Encrypted DCC chat message"),KVI_SMALLICON_DCCCHATMSGCRYPTED,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("Irc",__tr_no_lookup("Login operations completed"),KVI_SMALLICON_IRC,KVI_MSGTYPE_LEVEL_1),
+ MSGTYPE_OPTION("Kick",__tr_no_lookup("Kick action"),KVI_SMALLICON_KICK,KVI_MSGTYPE_LEVEL_2),
+ MSGTYPE_OPTION("Links",__tr_no_lookup("Links reply"),KVI_SMALLICON_LINKS,KVI_MSGTYPE_LEVEL_1),
+ MSGTYPE_OPTION("Spam",__tr_no_lookup("Spam report"),KVI_SMALLICON_SPAM,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("Icq",__tr_no_lookup("ICQ message"),KVI_SMALLICON_ICQ,KVI_MSGTYPE_LEVEL_1),
+ MSGTYPE_OPTION("IcqMessage",__tr_no_lookup("ICQ user-message"),KVI_SMALLICON_MESSAGE,KVI_MSGTYPE_LEVEL_1),
+ MSGTYPE_OPTION("IcqMessageSent",__tr_no_lookup("Outgoing ICQ user-message"),KVI_SMALLICON_MESSAGESENT,KVI_MSGTYPE_LEVEL_1),
+ MSGTYPE_OPTION("ChannelNotice",__tr_no_lookup("Channel notice"),KVI_SMALLICON_CHANNELNOTICE,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("ChannelNoticeCrypted",__tr_no_lookup("Encrypted channel notice"),KVI_SMALLICON_CHANNELNOTICECRYPTED,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("QueryNotice",__tr_no_lookup("Query notice"),KVI_SMALLICON_QUERYNOTICE,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("QueryNoticeCrypted",__tr_no_lookup("Encrypted query notice"),KVI_SMALLICON_QUERYNOTICECRYPTED,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("ServerNotice",__tr_no_lookup("Server notice"),KVI_SMALLICON_SERVERNOTICE,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("HalfOp",__tr_no_lookup("Halfop mode change"),KVI_SMALLICON_HALFOP,KVI_MSGTYPE_LEVEL_2),
+ MSGTYPE_OPTION("CtcpReplyUnknown",__tr_no_lookup("Unknown CTCP reply"),KVI_SMALLICON_CTCPREPLYUNKNOWN,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("NickServ",__tr_no_lookup("NickServ message"),KVI_SMALLICON_NICKSERV,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("ChanServ",__tr_no_lookup("ChanServ message"),KVI_SMALLICON_CHANSERV,KVI_MSGTYPE_LEVEL_1),
+ MSGTYPE_OPTION("Away",__tr_no_lookup("Away message"),KVI_SMALLICON_AWAY,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("Ident",__tr_no_lookup("Ident message"),KVI_SMALLICON_IDENT,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("List",__tr_no_lookup("Channel list message"),KVI_SMALLICON_LIST,KVI_MSGTYPE_LEVEL_1),
+ MSGTYPE_OPTION("HalfDeOp",__tr_no_lookup("Half-deop mode change"),KVI_SMALLICON_HALFDEOP,KVI_MSGTYPE_LEVEL_2),
+ MSGTYPE_OPTION("Invite",__tr_no_lookup("Invite message"),KVI_SMALLICON_INVITE,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("Multimedia",__tr_no_lookup("Multimedia message"),KVI_SMALLICON_MULTIMEDIA,KVI_MSGTYPE_LEVEL_2),
+ MSGTYPE_OPTION("QueryTrace",__tr_no_lookup("Query trace message"),KVI_SMALLICON_QUERYTRACE,KVI_MSGTYPE_LEVEL_1),
+ MSGTYPE_OPTION("Wallops",__tr_no_lookup("Wallops message"),KVI_SMALLICON_WALLOPS,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("JoinError",__tr_no_lookup("Join error message"),KVI_SMALLICON_NOCHANNEL,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("BroadcastPrivmsg",__tr_no_lookup("Broadcast private message"),KVI_SMALLICON_BROADCASTPRIVMSG,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("BroadcastNotice",__tr_no_lookup("Broadcast notice"),KVI_SMALLICON_BROADCASTNOTICE,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("MeKick",__tr_no_lookup("Am kicked"),KVI_SMALLICON_MEKICK,KVI_MSGTYPE_LEVEL_5),
+ MSGTYPE_OPTION("MeOp",__tr_no_lookup("Am op'd"),KVI_SMALLICON_MEOP,KVI_MSGTYPE_LEVEL_5),
+ MSGTYPE_OPTION("MeVoice",__tr_no_lookup("Am voiced"),KVI_SMALLICON_MEVOICE,KVI_MSGTYPE_LEVEL_5),
+ MSGTYPE_OPTION("MeDeOp",__tr_no_lookup("Am deop'd"),KVI_SMALLICON_MEDEOP,KVI_MSGTYPE_LEVEL_5),
+ MSGTYPE_OPTION("MeDeVoice",__tr_no_lookup("Am devoiced"),KVI_SMALLICON_MEDEVOICE,KVI_MSGTYPE_LEVEL_5),
+ MSGTYPE_OPTION("MeHalfOp",__tr_no_lookup("Am halfop'd"),KVI_SMALLICON_MEHALFOP,KVI_MSGTYPE_LEVEL_5),
+ MSGTYPE_OPTION("MeDeHalfOp",__tr_no_lookup("Am de-halfop'd"),KVI_SMALLICON_MEDEHALFOP,KVI_MSGTYPE_LEVEL_5),
+ MSGTYPE_OPTION("MeBan",__tr_no_lookup("Ban matching my mask"),KVI_SMALLICON_MEBAN,KVI_MSGTYPE_LEVEL_5),
+ MSGTYPE_OPTION("MeUnban",__tr_no_lookup("Unban matching my mask"),KVI_SMALLICON_MEUNBAN,KVI_MSGTYPE_LEVEL_5),
+ MSGTYPE_OPTION("MeBanExcept",__tr_no_lookup("Ban exception matching my mask"),KVI_SMALLICON_MEBANEXCEPT,KVI_MSGTYPE_LEVEL_5),
+ MSGTYPE_OPTION("MeBanUnExcept",__tr_no_lookup("Ban unexception matching my mask"),KVI_SMALLICON_MEBANUNEXCEPT,KVI_MSGTYPE_LEVEL_5),
+ MSGTYPE_OPTION("MeInviteExcept",__tr_no_lookup("Invite exception matching my mask"),KVI_SMALLICON_MEINVITEEXCEPT,KVI_MSGTYPE_LEVEL_5),
+ MSGTYPE_OPTION("MeInviteUnexcept",__tr_no_lookup("Invite unexception matching my mask"),KVI_SMALLICON_MEINVITEUNEXCEPT,KVI_MSGTYPE_LEVEL_5),
+ MSGTYPE_OPTION("Ignore",__tr_no_lookup("Ignored user message"),KVI_SMALLICON_IGNORE,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("Stats",__tr_no_lookup("Server statistics"),KVI_SMALLICON_STATS,KVI_MSGTYPE_LEVEL_1),
+ MSGTYPE_OPTION("SSL",__tr_no_lookup("SSL message"),KVI_SMALLICON_SSL,KVI_MSGTYPE_LEVEL_1),
+ MSGTYPE_OPTION("Search",__tr_no_lookup("Search"),KVI_SMALLICON_SEARCH,KVI_MSGTYPE_LEVEL_1),
+ MSGTYPE_OPTION("GenericSuccess",__tr_no_lookup("Generic success"),KVI_SMALLICON_CYANSQUARE,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION("GenericStatus",__tr_no_lookup("Generic status"),KVI_SMALLICON_GREENSQUARE,KVI_MSGTYPE_LEVEL_2),
+ MSGTYPE_OPTION("GenericVerbose",__tr_no_lookup("Generic verbose message"),KVI_SMALLICON_DKGREENSQUARE,KVI_MSGTYPE_LEVEL_1),
+ MSGTYPE_OPTION("GenericWarning",__tr_no_lookup("Generic warning"),KVI_SMALLICON_YELLOWSQUARE,KVI_MSGTYPE_LEVEL_3),
+ MSGTYPE_OPTION_SPEC("GenericError",__tr_no_lookup("Generic error"),KVI_SMALLICON_REDSQUARE,KVI_RED,KVI_TRANSPARENT,KVI_MSGTYPE_LEVEL_5),
+ MSGTYPE_OPTION_SPEC("GenericCritical",__tr_no_lookup("Generic critical error"),KVI_SMALLICON_BLACKSQUARE,KVI_RED,KVI_TRANSPARENT,KVI_MSGTYPE_LEVEL_5),
+ MSGTYPE_OPTION("ChanAdmin",__tr_no_lookup("Chan admin status set"),KVI_SMALLICON_CHANADMIN,KVI_MSGTYPE_LEVEL_5),
+ MSGTYPE_OPTION("ChanUnAdmin",__tr_no_lookup("Chan admin status unset"),KVI_SMALLICON_CHANUNADMIN,KVI_MSGTYPE_LEVEL_5),
+ MSGTYPE_OPTION("MeChanAdmin",__tr_no_lookup("Own chan admin status set"),KVI_SMALLICON_MECHANADMIN,KVI_MSGTYPE_LEVEL_5),
+ MSGTYPE_OPTION("MeChanUnAdmin",__tr_no_lookup("Own chan admin status unset"),KVI_SMALLICON_MECHANUNADMIN,KVI_MSGTYPE_LEVEL_5),
+ MSGTYPE_OPTION("UserOp",__tr_no_lookup("Userop mode change"),KVI_SMALLICON_USEROP,KVI_MSGTYPE_LEVEL_2),
+ MSGTYPE_OPTION("UserDeOp",__tr_no_lookup("User-deop mode change"),KVI_SMALLICON_DEUSEROP,KVI_MSGTYPE_LEVEL_2),
+ MSGTYPE_OPTION("MeUserOp",__tr_no_lookup("Am userop'd"),KVI_SMALLICON_MEUSEROP,KVI_MSGTYPE_LEVEL_5),
+ MSGTYPE_OPTION("MeDeUserOp",__tr_no_lookup("Am de-userop'd"),KVI_SMALLICON_MEDEUSEROP,KVI_MSGTYPE_LEVEL_5),
+ MSGTYPE_OPTION_SPEC("Verbose",__tr_no_lookup("Verbose/Debug"),KVI_SMALLICON_BINARYTEXT,KVI_DARKGRAY,KVI_TRANSPARENT,KVI_MSGTYPE_LEVEL_1),
+ MSGTYPE_OPTION("ChanOwner",__tr_no_lookup("Chan owner status set"),KVI_SMALLICON_CHANOWNER,KVI_MSGTYPE_LEVEL_5),
+ MSGTYPE_OPTION("ChanUnOwner",__tr_no_lookup("Chan owner status unset"),KVI_SMALLICON_CHANUNOWNER,KVI_MSGTYPE_LEVEL_5),
+ MSGTYPE_OPTION("MeChanOwner",__tr_no_lookup("Own chan owner status set"),KVI_SMALLICON_MECHANOWNER,KVI_MSGTYPE_LEVEL_5),
+ MSGTYPE_OPTION("MeChanUnOwner",__tr_no_lookup("Own chan owner status unset"),KVI_SMALLICON_MECHANUNOWNER,KVI_MSGTYPE_LEVEL_5),
+ MSGTYPE_OPTION_SPEC("ServerError",__tr_no_lookup("Server error"),KVI_SMALLICON_SERVERERROR,KVI_RED,KVI_TRANSPARENT,KVI_MSGTYPE_LEVEL_5),
+ MSGTYPE_OPTION_SPEC("Help",__tr_no_lookup("Help"),KVI_SMALLICON_HELP,KVI_DARKGREEN,KVI_TRANSPARENT,KVI_MSGTYPE_LEVEL_1),
+ MSGTYPE_OPTION("TextEncoding",__tr_no_lookup("Text Encoding Server message"),KVI_SMALLICON_TEXTENCODING,KVI_MSGTYPE_LEVEL_1),
+ // TODO: add icon and check what level means
+ // Pragma: the message level is a warning level that is rendered in the taskbar
+ // messages with higher level are rendered with more visible color (i.e. red)
+ // messages with very high level might flash the tray and end up in the notifier
+ // level 1 or 2 for standard torrent messages is ok
+ MSGTYPE_OPTION("BitTorrent",__tr_no_lookup("BitTorrent message"),KVI_SMALLICON_MULTIMEDIA,KVI_MSGTYPE_LEVEL_2)
+};
+
+static const char * options_section_table[KVI_NUM_OPTION_SECT_FLAGS] =
+{
+ "None", "Frame", "Mdi", "Windows",
+ "TaskBar", "IrcView", "MsgType", "MircColor",
+ "Input", "UserParser", "Connection", "IrcSocket",
+ "User", "UserListView","Label", "Modules",
+ "Ctcp", "Dcc", "Gui", "IrcToolBar",
+ "Logging", "AntiSpam", "Avatar", "Url",
+ "Recent", "Geometry"
+};
+
+
+static void config_set_section(int flag,KviConfig * cfg)
+{
+ int index = flag & KviOption_sectMask;
+ if((index < KVI_NUM_OPTION_SECT_FLAGS) && (index >= 0))
+ {
+ cfg->setGroup(options_section_table[index]);
+ } else cfg->setGroup(""); // Default group
+}
+
+void KviApp::loadOptions()
+{
+ KviStr buffer;
+ if(getReadOnlyConfigPath(buffer,KVI_CONFIGFILE_MAIN))
+ {
+ KviConfig cfg(buffer.ptr(),KviConfig::Read);
+
+ int prg = 12;
+ int i;
+
+ #define READ_OPTIONS(_num,_table,_readFnc) \
+ for(i=0;i<_num;i++) \
+ { \
+ config_set_section(_table[i].flags,&cfg); \
+ _table[i].option = cfg._readFnc(_table[i].name,_table[i].option); \
+ } \
+ prg += 3; \
+ KVI_SPLASH_SET_PROGRESS(prg)
+
+ READ_OPTIONS(KVI_NUM_RECT_OPTIONS,g_rectOptionsTable,readRectEntry)
+ READ_OPTIONS(KVI_NUM_BOOL_OPTIONS,g_boolOptionsTable,readBoolEntry)
+ READ_OPTIONS(KVI_NUM_STRING_OPTIONS,g_stringOptionsTable,readQStringEntry)
+ READ_OPTIONS(KVI_NUM_COLOR_OPTIONS,g_colorOptionsTable,readColorEntry)
+ READ_OPTIONS(KVI_NUM_PIXMAP_OPTIONS,g_pixmapOptionsTable,readPixmapEntry)
+ READ_OPTIONS(KVI_NUM_UINT_OPTIONS,g_uintOptionsTable,readUIntEntry)
+ READ_OPTIONS(KVI_NUM_FONT_OPTIONS,g_fontOptionsTable,readFontEntry)
+ READ_OPTIONS(KVI_NUM_MSGTYPE_OPTIONS,g_msgtypeOptionsTable,readMsgTypeEntry)
+ READ_OPTIONS(KVI_NUM_STRINGLIST_OPTIONS,g_stringlistOptionsTable,readStringListEntry)
+ READ_OPTIONS(KVI_NUM_MIRCCOLOR_OPTIONS,g_mirccolorOptionsTable,readColorEntry)
+ READ_OPTIONS(KVI_NUM_ICCOLOR_OPTIONS,g_iccolorOptionsTable,readColorEntry)
+
+ for(i=0;i<KVI_NUM_STRING_OPTIONS;i++)
+ {
+ if(g_stringOptionsTable[i].flags & KviOption_encodePath)
+ KviStringConversion::decodePath(g_stringOptionsTable[i].option);
+ }
+
+ for(i=0;i<KVI_NUM_STRINGLIST_OPTIONS;i++)
+ {
+ if(g_stringlistOptionsTable[i].flags & KviOption_encodePath)
+ KviStringConversion::decodePath(g_stringlistOptionsTable[i].option);
+ }
+
+ #undef READ_OPTIONS
+ } // else already have the defaults
+}
+
+void KviApp::saveOptions()
+{
+ QString buffer;
+
+ saveRecentChannels();
+
+ getLocalKvircDirectory(buffer,Config,KVI_CONFIGFILE_MAIN);
+ KviConfig cfg(buffer,KviConfig::Write);
+
+ int i;
+
+ #define WRITE_OPTIONS(_num,_table) \
+ for(i=0;i<_num;i++) \
+ { \
+ config_set_section(_table[i].flags,&cfg); \
+ cfg.writeEntry(_table[i].name,_table[i].option); \
+ }
+
+ WRITE_OPTIONS(KVI_NUM_RECT_OPTIONS,g_rectOptionsTable)
+ WRITE_OPTIONS(KVI_NUM_BOOL_OPTIONS,g_boolOptionsTable)
+ for(i=0;i<KVI_NUM_STRING_OPTIONS;i++)
+ {
+ if(g_stringOptionsTable[i].flags & KviOption_encodePath)
+ KviStringConversion::encodePath(g_stringOptionsTable[i].option);
+ }
+ WRITE_OPTIONS(KVI_NUM_STRING_OPTIONS,g_stringOptionsTable)
+ for(i=0;i<KVI_NUM_STRING_OPTIONS;i++)
+ {
+ if(g_stringOptionsTable[i].flags & KviOption_encodePath)
+ KviStringConversion::decodePath(g_stringOptionsTable[i].option);
+ }
+ WRITE_OPTIONS(KVI_NUM_COLOR_OPTIONS,g_colorOptionsTable)
+ WRITE_OPTIONS(KVI_NUM_PIXMAP_OPTIONS,g_pixmapOptionsTable)
+ WRITE_OPTIONS(KVI_NUM_UINT_OPTIONS,g_uintOptionsTable)
+ WRITE_OPTIONS(KVI_NUM_FONT_OPTIONS,g_fontOptionsTable)
+ WRITE_OPTIONS(KVI_NUM_MSGTYPE_OPTIONS,g_msgtypeOptionsTable)
+ for(i=0;i<KVI_NUM_STRINGLIST_OPTIONS;i++)
+ {
+ if(g_stringlistOptionsTable[i].flags & KviOption_encodePath)
+ KviStringConversion::encodePath(g_stringlistOptionsTable[i].option);
+ }
+ WRITE_OPTIONS(KVI_NUM_STRINGLIST_OPTIONS,g_stringlistOptionsTable)
+ for(i=0;i<KVI_NUM_STRINGLIST_OPTIONS;i++)
+ {
+ if(g_stringlistOptionsTable[i].flags & KviOption_encodePath)
+ KviStringConversion::decodePath(g_stringlistOptionsTable[i].option);
+ }
+ WRITE_OPTIONS(KVI_NUM_MIRCCOLOR_OPTIONS,g_mirccolorOptionsTable)
+ WRITE_OPTIONS(KVI_NUM_ICCOLOR_OPTIONS,g_iccolorOptionsTable)
+
+ #undef WRITE_OPTIONS
+}
+
+
+#undef WRITE_OPTIONS
+
+#define WRITE_OPTIONS(_num,_table) \
+ for(i=0;i<_num;i++) \
+ { \
+ if(_table[i].flags & KviOption_groupTheme) \
+ cfg.writeEntry(_table[i].name,_table[i].option); \
+ }
+
+namespace KviTheme
+{
+ // utility functions for the KviTheme namespace (kvi_theme.h)
+ // that are implemented here for convenience (in saving the options)
+ bool save(KviThemeInfo &options)
+ {
+ QString szD = options.absoluteDirectory();
+
+ if(szD.isEmpty())
+ {
+ options.setLastError(__tr2qs("Missing absolute directory for the theme information"));
+ return false;
+ }
+
+ if(!KviFileUtils::directoryExists(szD))
+ {
+ if(!KviFileUtils::makeDir(szD))
+ {
+ options.setLastError(__tr2qs("Failed to create the theme directory"));
+ return false;
+ }
+ }
+
+ szD.append(KVI_PATH_SEPARATOR_CHAR);
+ szD.append(KVI_THEMEINFO_FILE_NAME);
+
+ if(!options.save(szD))
+ {
+ return false;
+ }
+
+ szD = options.absoluteDirectory();
+ szD.append(KVI_PATH_SEPARATOR_CHAR);
+ szD.append(KVI_THEMEDATA_FILE_NAME);
+
+ KviConfig cfg(szD,KviConfig::Write);
+
+ cfg.setGroup(KVI_THEMEDATA_CONFIG_GROUP);
+
+ int i;
+
+ WRITE_OPTIONS(KVI_NUM_RECT_OPTIONS,g_rectOptionsTable)
+ WRITE_OPTIONS(KVI_NUM_BOOL_OPTIONS,g_boolOptionsTable)
+ WRITE_OPTIONS(KVI_NUM_STRING_OPTIONS,g_stringOptionsTable)
+ WRITE_OPTIONS(KVI_NUM_COLOR_OPTIONS,g_colorOptionsTable)
+ WRITE_OPTIONS(KVI_NUM_UINT_OPTIONS,g_uintOptionsTable)
+ WRITE_OPTIONS(KVI_NUM_FONT_OPTIONS,g_fontOptionsTable)
+ WRITE_OPTIONS(KVI_NUM_MSGTYPE_OPTIONS,g_msgtypeOptionsTable)
+ WRITE_OPTIONS(KVI_NUM_STRINGLIST_OPTIONS,g_stringlistOptionsTable)
+ WRITE_OPTIONS(KVI_NUM_MIRCCOLOR_OPTIONS,g_mirccolorOptionsTable)
+ WRITE_OPTIONS(KVI_NUM_ICCOLOR_OPTIONS,g_iccolorOptionsTable)
+
+ #undef WRITE_OPTIONS
+
+ // the pixmap options need special processing
+ for(i=0;i<KVI_NUM_PIXMAP_OPTIONS;i++)
+ {
+ if(g_pixmapOptionsTable[i].flags & KviOption_groupTheme)
+ {
+ if(g_pixmapOptionsTable[i].option.pixmap())
+ {
+ QString szPixPath = options.absoluteDirectory();
+ szPixPath.append(KVI_PATH_SEPARATOR_CHAR);
+ QString szPixName = g_pixmapOptionsTable[i].name;
+ szPixName += ".png";
+ szPixPath += szPixName;
+
+ if(g_pixmapOptionsTable[i].option.pixmap()->save(szPixPath,"PNG"))
+ {
+ cfg.writeEntry(g_pixmapOptionsTable[i].name,szPixName);
+ } else {
+ // we ignore this error for now
+ debug("failed to save %s",szPixPath.utf8().data());
+ cfg.writeEntry(g_pixmapOptionsTable[i].name,"");
+ }
+ } else {
+ cfg.writeEntry(g_pixmapOptionsTable[i].name,"");
+ }
+ }
+ }
+
+ cfg.writeEntry("stringIconThemeSubdir",options.subdirectory());
+
+ // find all the "kvi_bigicon" images that we can find in the main pics directory
+ QString szPicsPath;
+
+ g_pApp->getGlobalKvircDirectory(szPicsPath,KviApp::Pics);
+ QDir d(szPicsPath);
+ QStringList sl = d.entryList("kvi_bigicon_*.png",QDir::Files);
+
+ for(QStringList::Iterator it=sl.begin();it != sl.end();it++)
+ {
+ KviCachedPixmap * p = g_pIconManager->getPixmapWithCache(*it);
+ if(p)
+ {
+ QString szPixPath = options.absoluteDirectory();
+ szPixPath.append(KVI_PATH_SEPARATOR_CHAR);
+ szPixPath += *it;
+
+ if(!KviFileUtils::copyFile(p->path(),szPixPath))
+ {
+ options.setLastError(__tr2qs("Failed to save one of the theme images"));
+ return false;
+ }
+ }
+ }
+
+
+ szD = options.absoluteDirectory();
+ szD.append(KVI_PATH_SEPARATOR_CHAR);
+ szD.append(KVI_SMALLICONS_SUBDIRECTORY);
+
+ if(!KviFileUtils::makeDir(szD))
+ {
+ options.setLastError(__tr2qs("Failed to create the theme subdirectory"));
+ return false;
+ }
+
+ // We actually need to *save* the small icons since
+ // we have a compatibility mode that can load them from
+ // the old format kvi_smallicon_XY.png multiimage libraries.
+
+ for(int j=0;j<KVI_NUM_SMALL_ICONS;j++)
+ {
+ QPixmap * pix = g_pIconManager->getSmallIcon(j);
+
+ QString szPixPath = options.absoluteDirectory();
+ szPixPath.append(KVI_PATH_SEPARATOR_CHAR);
+ szPixPath.append(KVI_SMALLICONS_SUBDIRECTORY);
+ szPixPath.append(KVI_PATH_SEPARATOR_CHAR);
+ szPixPath.append("kcs_");
+ szPixPath.append(g_pIconManager->getSmallIconName(j));
+ szPixPath.append(".png");
+
+ if(!pix->save(szPixPath,"PNG",90))
+ {
+ options.setLastError(__tr2qs("Failed to save one of the theme images"));
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ bool load(const QString &themeDir,KviThemeInfo &buffer)
+ {
+ if(!buffer.loadFromDirectory(themeDir))
+ return false; // makes sure that themedata exists too
+
+ // reset the current theme subdir
+ KVI_OPTION_STRING(KviOption_stringIconThemeSubdir) = "";
+
+ // reset the splash screen pointer
+ QString szPointerFile;
+ g_pApp->getLocalKvircDirectory(szPointerFile,KviApp::Themes,"current-splash");
+ KviFileUtils::removeFile(szPointerFile);
+
+ QString szD = themeDir;
+ KviQString::ensureLastCharIs(szD,KVI_PATH_SEPARATOR_CHAR);
+ szD.append(KVI_THEMEDATA_FILE_NAME);
+
+ KviConfig cfg(szD,KviConfig::Read);
+
+ cfg.setGroup(KVI_THEMEDATA_CONFIG_GROUP);
+
+ int i;
+ int iResetFlags = 0;
+
+ #undef READ_OPTIONS
+
+ #define READ_OPTIONS(_num,_table,_readFnc) \
+ for(i=0;i<_num;i++) \
+ { \
+ if(_table[i].flags & KviOption_groupTheme) \
+ { \
+ if(cfg.hasKey(_table[i].name)) \
+ { \
+ iResetFlags |= (_table[i].flags & KviOption_resetMask); \
+ _table[i].option = cfg._readFnc(_table[i].name,_table[i].option); \
+ } \
+ } \
+ }
+
+ #define READ_ALL_OPTIONS(_num,_table,_readFnc) \
+ for(i=0;i<_num;i++) \
+ { \
+ if(cfg.hasKey(_table[i].name)) \
+ { \
+ iResetFlags |= (_table[i].flags & KviOption_resetMask); \
+ _table[i].option = cfg._readFnc(_table[i].name,_table[i].option); \
+ } \
+ }
+
+ READ_OPTIONS(KVI_NUM_RECT_OPTIONS,g_rectOptionsTable,readRectEntry)
+ READ_OPTIONS(KVI_NUM_BOOL_OPTIONS,g_boolOptionsTable,readBoolEntry)
+ READ_OPTIONS(KVI_NUM_STRING_OPTIONS,g_stringOptionsTable,readQStringEntry)
+ READ_OPTIONS(KVI_NUM_COLOR_OPTIONS,g_colorOptionsTable,readColorEntry)
+ READ_OPTIONS(KVI_NUM_UINT_OPTIONS,g_uintOptionsTable,readUIntEntry)
+ READ_OPTIONS(KVI_NUM_FONT_OPTIONS,g_fontOptionsTable,readFontEntry)
+ READ_ALL_OPTIONS(KVI_NUM_MSGTYPE_OPTIONS,g_msgtypeOptionsTable,readMsgTypeEntry)
+ READ_OPTIONS(KVI_NUM_STRINGLIST_OPTIONS,g_stringlistOptionsTable,readStringListEntry)
+ READ_OPTIONS(KVI_NUM_MIRCCOLOR_OPTIONS,g_mirccolorOptionsTable,readColorEntry)
+ READ_OPTIONS(KVI_NUM_ICCOLOR_OPTIONS,g_iccolorOptionsTable,readColorEntry)
+
+ #undef READ_OPTIONS
+ #undef READ_ALL_OPTIONS
+ KVI_OPTION_STRING(KviOption_stringIconThemeSubdir).stripWhiteSpace();
+
+
+ // the pixmap options need special processing
+ for(i=0;i<KVI_NUM_PIXMAP_OPTIONS;i++)
+ {
+ if(g_pixmapOptionsTable[i].flags & KviOption_groupTheme)
+ {
+ if(cfg.hasKey(g_pixmapOptionsTable[i].name))
+ {
+ QString szVal = cfg.readQStringEntry(g_pixmapOptionsTable[i].name,"");
+ szVal.stripWhiteSpace();
+ QString szBuffer;
+ if(!szVal.isEmpty())
+ {
+ g_pApp->findImage(szBuffer,szVal);
+ } else {
+ szBuffer = szVal;
+ }
+
+ KviStringConversion::fromString(szBuffer,g_pixmapOptionsTable[i].option);
+
+ // reset anyway
+ iResetFlags |= g_pixmapOptionsTable[i].flags & KviOption_resetMask;
+ }
+ }
+ }
+
+ // create the splash screen pointer if this theme has some pixmaps in it
+ if(!KVI_OPTION_STRING(KviOption_stringIconThemeSubdir).isEmpty())
+ KviFileUtils::writeFile(szPointerFile,KVI_OPTION_STRING(KviOption_stringIconThemeSubdir));
+
+ // force reloading of images anyway
+ g_pApp->optionResetUpdate(iResetFlags | KviOption_resetReloadImages);
+
+ return true;
+ }
+};
+
+void KviApp::listAvailableOptions(KviWindow *wnd)
+{
+ int i;
+
+ #define LIST_OPTIONS(__txt,__num,__table) \
+ wnd->output(KVI_OUT_SYSTEMMESSAGE,"%c%s%c",KVI_TEXT_BOLD,__txt,KVI_TEXT_BOLD); \
+ for(i = 0;i < __num;i++)wnd->outputNoFmt(KVI_OUT_SYSTEMMESSAGE,__table[i].name);
+
+ LIST_OPTIONS(__tr("Boolean options (1/0)"),KVI_NUM_BOOL_OPTIONS,g_boolOptionsTable)
+ LIST_OPTIONS(__tr("Rectangle options (x,y,width,height)"),KVI_NUM_RECT_OPTIONS,g_rectOptionsTable)
+ LIST_OPTIONS(__tr("String options (string value)"),KVI_NUM_STRING_OPTIONS,g_stringOptionsTable)
+ LIST_OPTIONS(__tr("Color options (#RRGGBB)"),KVI_NUM_COLOR_OPTIONS,g_colorOptionsTable)
+ LIST_OPTIONS(__tr("Mirccolor options (#RRGGBB)"),KVI_NUM_MIRCCOLOR_OPTIONS,g_mirccolorOptionsTable)
+ LIST_OPTIONS(__tr("Irc context color options (#RRGGBB)"),KVI_NUM_ICCOLOR_OPTIONS,g_iccolorOptionsTable)
+ LIST_OPTIONS(__tr("Pixmap options (image path)"),KVI_NUM_PIXMAP_OPTIONS,g_pixmapOptionsTable)
+ LIST_OPTIONS(__tr("Unsigned integer options (unsigned integer constant)"),KVI_NUM_UINT_OPTIONS,g_uintOptionsTable)
+ LIST_OPTIONS(__tr("Font options (family,pointsize,style,charset,weight,flags (biusf))"),KVI_NUM_FONT_OPTIONS,g_fontOptionsTable)
+ LIST_OPTIONS(__tr("Message color options (image_id,foreground,background,logFlag (0/1))"),KVI_NUM_MSGTYPE_OPTIONS,g_msgtypeOptionsTable)
+ LIST_OPTIONS(__tr("String list options (comma separated list of strings)"),KVI_NUM_STRINGLIST_OPTIONS,g_stringlistOptionsTable)
+
+ #undef LIST_OPTIONS
+}
+
+//using namespace KviStringConversion;
+
+bool KviApp::getOptionString(const char * optName,QString &buffer)
+{
+
+ #define GET_OPTION_STRING(__numOpt,__table,__prefix,__prefixLen) \
+ if(kvi_strEqualCIN(optName,__prefix,__prefixLen)) \
+ { \
+ for(int i=0;i < __numOpt;i++) \
+ { \
+ if(kvi_strEqualCI(optName,__table[i].name)) \
+ { \
+ KviStringConversion::toString(__table[i].option,buffer); \
+ return true; \
+ } \
+ } \
+ return false; \
+ }
+
+ // WARNING : stringlist prefix must go BEFORE the string prefix (otherwise it will match)
+
+ GET_OPTION_STRING(KVI_NUM_BOOL_OPTIONS,g_boolOptionsTable,KVI_BOOL_OPTIONS_PREFIX,KVI_BOOL_OPTIONS_PREFIX_LEN)
+ GET_OPTION_STRING(KVI_NUM_RECT_OPTIONS,g_rectOptionsTable,KVI_BOOL_OPTIONS_PREFIX,KVI_BOOL_OPTIONS_PREFIX_LEN)
+ GET_OPTION_STRING(KVI_NUM_STRINGLIST_OPTIONS,g_stringlistOptionsTable,KVI_STRINGLIST_OPTIONS_PREFIX,KVI_STRINGLIST_OPTIONS_PREFIX_LEN)
+ GET_OPTION_STRING(KVI_NUM_STRING_OPTIONS,g_stringOptionsTable,KVI_STRING_OPTIONS_PREFIX,KVI_STRING_OPTIONS_PREFIX_LEN)
+ GET_OPTION_STRING(KVI_NUM_COLOR_OPTIONS,g_colorOptionsTable,KVI_COLOR_OPTIONS_PREFIX,KVI_COLOR_OPTIONS_PREFIX_LEN)
+ GET_OPTION_STRING(KVI_NUM_MIRCCOLOR_OPTIONS,g_mirccolorOptionsTable,KVI_MIRCCOLOR_OPTIONS_PREFIX,KVI_MIRCCOLOR_OPTIONS_PREFIX_LEN)
+ GET_OPTION_STRING(KVI_NUM_ICCOLOR_OPTIONS,g_iccolorOptionsTable,KVI_ICCOLOR_OPTIONS_PREFIX,KVI_ICCOLOR_OPTIONS_PREFIX_LEN)
+ GET_OPTION_STRING(KVI_NUM_PIXMAP_OPTIONS,g_pixmapOptionsTable,KVI_PIXMAP_OPTIONS_PREFIX,KVI_PIXMAP_OPTIONS_PREFIX_LEN)
+ GET_OPTION_STRING(KVI_NUM_UINT_OPTIONS,g_uintOptionsTable,KVI_UINT_OPTIONS_PREFIX,KVI_UINT_OPTIONS_PREFIX_LEN)
+ GET_OPTION_STRING(KVI_NUM_FONT_OPTIONS,g_fontOptionsTable,KVI_FONT_OPTIONS_PREFIX,KVI_FONT_OPTIONS_PREFIX_LEN)
+ GET_OPTION_STRING(KVI_NUM_MSGTYPE_OPTIONS,g_msgtypeOptionsTable,KVI_MSGTYPE_OPTIONS_PREFIX,KVI_MSGTYPE_OPTIONS_PREFIX_LEN)
+ return false;
+
+ #undef GET_OPTION_STRING
+}
+
+void KviApp::optionResetUpdate(int flags)
+{
+ if(flags & KviOption_resetReloadImages)
+ {
+ g_pIconManager->reloadImages();
+ emit reloadImages();
+ }
+
+ if(flags & KviOption_resetUpdateAppFont)
+ {
+ updateApplicationFont();
+ }
+
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ if(flags & KviOption_resetUpdatePseudoTransparency)
+ {
+ triggerUpdatePseudoTransparency();
+ }
+#endif
+
+ if(flags & KviOption_resetRestartIdentd)
+ {
+ if(g_iIdentDaemonRunningUsers)
+ g_pFrame->executeInternalCommand(KVI_INTERNALCOMMAND_IDENT_STOP);
+
+ if(KVI_OPTION_BOOL(KviOption_boolUseIdentService) && !KVI_OPTION_BOOL(KviOption_boolUseIdentServiceOnlyOnConnect))
+ g_pFrame->executeInternalCommand(KVI_INTERNALCOMMAND_IDENT_START);
+ }
+
+ if(flags & KviOption_resetUpdateGui)
+ {
+ triggerUpdateGui();
+ }
+
+ if(flags & KviOption_resetUpdateTaskBar)
+ {
+ g_pFrame->recreateTaskBar();
+ }
+
+ if(flags & KviOption_resetRestartNotifyList)
+ {
+ g_pApp->restartNotifyLists();
+ }
+
+ if(flags & KviOption_resetRestartLagMeter)
+ {
+ g_pApp->restartLagMeters();
+ }
+
+ if(flags & KviOption_resetRecentChannels)
+ {
+ g_pApp->buildRecentChannels();
+ }
+}
+
+bool KviApp::setOptionValue(const char * optName,const QString &value)
+{
+
+ #define SET_OPTION_VALUE(__numOpt,__table,__prefix,__prefixLen) \
+ if(kvi_strEqualCIN(optName,__prefix,__prefixLen)) \
+ { \
+ for(int i=0;i < __numOpt;i++) \
+ { \
+ if(kvi_strEqualCI(optName,__table[i].name)) \
+ { \
+ if(!KviStringConversion::fromString(value,__table[i].option))return false; \
+ optionResetUpdate(__table[i].flags); \
+ return true; \
+ } \
+ } \
+ return false; \
+ }
+
+ SET_OPTION_VALUE(KVI_NUM_BOOL_OPTIONS,g_boolOptionsTable,KVI_BOOL_OPTIONS_PREFIX,KVI_BOOL_OPTIONS_PREFIX_LEN)
+ SET_OPTION_VALUE(KVI_NUM_RECT_OPTIONS,g_rectOptionsTable,KVI_BOOL_OPTIONS_PREFIX,KVI_BOOL_OPTIONS_PREFIX_LEN)
+ SET_OPTION_VALUE(KVI_NUM_STRINGLIST_OPTIONS,g_stringlistOptionsTable,KVI_STRINGLIST_OPTIONS_PREFIX,KVI_STRINGLIST_OPTIONS_PREFIX_LEN)
+ SET_OPTION_VALUE(KVI_NUM_STRING_OPTIONS,g_stringOptionsTable,KVI_STRING_OPTIONS_PREFIX,KVI_STRING_OPTIONS_PREFIX_LEN)
+ SET_OPTION_VALUE(KVI_NUM_COLOR_OPTIONS,g_colorOptionsTable,KVI_COLOR_OPTIONS_PREFIX,KVI_COLOR_OPTIONS_PREFIX_LEN)
+ SET_OPTION_VALUE(KVI_NUM_MIRCCOLOR_OPTIONS,g_mirccolorOptionsTable,KVI_MIRCCOLOR_OPTIONS_PREFIX,KVI_MIRCCOLOR_OPTIONS_PREFIX_LEN)
+ SET_OPTION_VALUE(KVI_NUM_ICCOLOR_OPTIONS,g_iccolorOptionsTable,KVI_ICCOLOR_OPTIONS_PREFIX,KVI_ICCOLOR_OPTIONS_PREFIX_LEN)
+// SET_OPTION_VALUE(KVI_NUM_PIXMAP_OPTIONS,g_pixmapOptionsTable,KVI_PIXMAP_OPTIONS_PREFIX,KVI_PIXMAP_OPTIONS_PREFIX_LEN)
+ SET_OPTION_VALUE(KVI_NUM_UINT_OPTIONS,g_uintOptionsTable,KVI_UINT_OPTIONS_PREFIX,KVI_UINT_OPTIONS_PREFIX_LEN)
+ SET_OPTION_VALUE(KVI_NUM_FONT_OPTIONS,g_fontOptionsTable,KVI_FONT_OPTIONS_PREFIX,KVI_FONT_OPTIONS_PREFIX_LEN)
+ SET_OPTION_VALUE(KVI_NUM_MSGTYPE_OPTIONS,g_msgtypeOptionsTable,KVI_MSGTYPE_OPTIONS_PREFIX,KVI_MSGTYPE_OPTIONS_PREFIX_LEN)
+
+ if(kvi_strEqualCI(optName,"stringlistRecentChannels"))
+ buildRecentChannels();
+ // The pixmap options have special treating
+ if(kvi_strEqualCIN(optName,KVI_PIXMAP_OPTIONS_PREFIX,KVI_PIXMAP_OPTIONS_PREFIX_LEN))
+ {
+ // We lookup the image path (so we allow also relative paths for this option type)
+ QString szVal = value;
+ szVal.stripWhiteSpace();
+ QString szBuffer;
+ if(!szVal.isEmpty())
+ {
+ findImage(szBuffer,szVal);
+ } else {
+ szBuffer = szVal;
+ }
+
+ for(int i=0;i < KVI_NUM_PIXMAP_OPTIONS;i++)
+ {
+ if(kvi_strEqualCI(optName,g_pixmapOptionsTable[i].name))
+ {
+ if(!KviStringConversion::fromString(szBuffer,g_pixmapOptionsTable[i].option))return false;
+ optionResetUpdate(g_pixmapOptionsTable[i].flags);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ return false;
+
+ #undef SET_OPTION_VALUE
+}
diff --git a/src/kvirc/kernel/kvi_options.h b/src/kvirc/kernel/kvi_options.h
new file mode 100644
index 00000000..1bd264e9
--- /dev/null
+++ b/src/kvirc/kernel/kvi_options.h
@@ -0,0 +1,737 @@
+#ifndef _KVI_OPTIONS_H_
+#define _KVI_OPTIONS_H_
+
+//=============================================================================
+//
+// File : kvi_options.h
+// Creation date : Tue Jun 20 2000 12:42:07 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_string.h"
+#include "kvi_pixmap.h"
+#include "kvi_msgtype.h"
+
+#include <qrect.h>
+#include <qpixmap.h>
+#include <qcolor.h>
+#include <qfont.h>
+#include <qstringlist.h>
+
+// option structures
+
+
+#define DECLARE_OPTION_STRUCT(_cname,_type) \
+ class _cname \
+ { \
+ public: \
+ const char * name; \
+ _type option; \
+ int flags; \
+ public: \
+ _cname(const char * n,_type o,int f) \
+ : name(n) , option(o) , flags(f) {}; \
+ ~_cname() {}; \
+ };
+
+DECLARE_OPTION_STRUCT(KviBoolOption,bool)
+DECLARE_OPTION_STRUCT(KviRectOption,QRect)
+DECLARE_OPTION_STRUCT(KviStringOption,QString)
+DECLARE_OPTION_STRUCT(KviColorOption,QColor)
+DECLARE_OPTION_STRUCT(KviFontOption,QFont)
+DECLARE_OPTION_STRUCT(KviPixmapOption,KviPixmap)
+//DECLARE_OPTION_STRUCT(KviIntOption,int)
+DECLARE_OPTION_STRUCT(KviUIntOption,unsigned int)
+DECLARE_OPTION_STRUCT(KviMsgTypeOption,KviMsgType)
+DECLARE_OPTION_STRUCT(KviStringListOption,QStringList)
+
+#define KVI_COLOR_EXT_USER_OP 50
+#define KVI_COLOR_EXT_USER_HALFOP 51
+#define KVI_COLOR_EXT_USER_ADMIN 52
+#define KVI_COLOR_EXT_USER_OWNER 53
+#define KVI_COLOR_EXT_USER_VOICE 54
+#define KVI_COLOR_EXT_USER_USEROP 55
+#define KVI_COLOR_EXT_USER_NORMAL 56
+#define KVI_COLOR_CUSTOM 255
+#define KVI_COLOR_OWN 254
+
+// option entry indexes
+
+#define KVI_RECT_OPTIONS_PREFIX "rect"
+#define KVI_RECT_OPTIONS_PREFIX_LEN 4
+
+#define KviOption_rectFrameGeometry 0 /* internal */
+/* FIXME: this should be in the options module (local config) ? */
+#define KviOption_rectGeneralOptionsDialogGeometry 1 /* internal */
+/* FIXME: this should be in the regusers module (local config) ? */
+#define KviOption_rectRegisteredUsersDialogGeometry 2 /* internal */
+
+#define KVI_NUM_RECT_OPTIONS 3
+
+
+
+#define KVI_BOOL_OPTIONS_PREFIX "bool"
+#define KVI_BOOL_OPTIONS_PREFIX_LEN 4
+
+#define KviOption_boolWindowsRememberProperties 0 /* interface::features::global */
+#define KviOption_boolIrcViewShowImages 1 /* interface::features::components::ircview */
+#define KviOption_boolIrcViewTimestamp 2 /* interface::features::components::ircview */
+#define KviOption_boolIrcViewUrlHighlighting 3 /* interface::features::components::ircview */
+#define KviOption_boolIrcViewWrapMargin 4 /* interface::features::components::ircview */
+#define KviOption_boolInputHistoryCursorAtEnd 5 /* interface::features::components::input */
+#define KviOption_boolAvoidParserWarnings 6 /* ircengine::uparser */
+#define KviOption_boolUseProxyHost 7 /* transport */
+#define KviOption_boolShowGeneralOptionsDialogAsToplevel 8 /* interface::features::global */
+#define KviOption_boolForceBrutalQuit 9 /* irc */
+#define KviOption_boolShowPingPong 10 /* ircoutput */
+#define KviOption_boolPopupNotifierOnNewQueryMessages 11 /* query */
+#define KviOption_boolShowExtendedServerInfo 12 /* ircoutput */
+#define KviOption_boolEchoNumericTopic 13 /* ircoutput */
+#define KviOption_boolShowOwnParts 14 /* ircoutput */
+#define KviOption_boolUseAntiSpamOnPrivmsg 15 /* ircengine::outputcontrol::antispam */
+#define KviOption_boolUseExtendedPrivmsgView 16 /* ircengine::outputcontrol::privmsg */
+#define KviOption_boolShowUserAndHostInPrivmsgView 17 /* ircengine::outputcontrol::privmsg */
+#define KviOption_boolUseWordHighlighting 18 /* ircengine::outputcontrol::highlighting */
+#define KviOption_boolUseBigIcons 19 /* internal */
+#define KviOption_boolCleanupUnusedModules 20 /* uparser ? */
+#define KviOption_boolIgnoreCtcpPing 21 /* ctcp */
+#define KviOption_boolIgnoreCtcpVersion 22 /* ctcp */
+#define KviOption_boolUseCtcpFloodProtection 23 /* ctcp */
+#define KviOption_boolDisableBrokenEventHandlers 24 /* ircengine::uparser */
+#define KviOption_boolIgnoreCtcpClientinfo 25 /* ctcp */
+#define KviOption_boolIgnoreCtcpUserinfo 26 /* ctcp */
+#define KviOption_boolIgnoreCtcpFinger 27 /* ctcp */
+#define KviOption_boolIgnoreCtcpSource 28 /* ctcp */
+#define KviOption_boolIgnoreCtcpTime 29 /* ctcp */
+#define KviOption_boolRequestMissingAvatars 30 /* ctcp::avatar */
+#define KviOption_boolShowCompactModeChanges 31 /* ircoutput */
+#define KviOption_boolIgnoreCtcpDcc 32 /* ctcp */
+#define KviOption_boolAutoAcceptDccChat 33 /* dcc::chat */
+#define KviOption_boolAutoAcceptDccSend 34 /* dcc::send */
+#define KviOption_boolSendZeroAckInDccRecv 35 /* dcc::send */
+#define KviOption_boolUseFastDccSend 36 /* dcc::send */
+#define KviOption_boolObtainGlobalBackgroundFromKde 37 /* interface::look::global */
+#define KviOption_boolUseTaskBarIrcContextIndicator 38 /* interface::features::global */
+#define KviOption_boolUseGlobalApplicationFont 39 /* interface::look::global */
+#define KviOption_boolAlwaysQuitKVIrcClosingLastConsole 40 /* internal */
+#define KviOption_boolAlwaysDisconnectClosingConnectedConsole 41 /* internal */
+#define KviOption_boolFlashWindowOnHighlightedMessages 42 /* highlighting */
+#define KviOption_boolPopupNotifierOnHighlightedMessages 43 /* highlighting */
+#define KviOption_boolFlashWindowOnNotifyOnLine 44 /* notify */
+#define KviOption_boolIrcViewTimestampUTC 45 /* interface::features::components::ircview */
+#define KviOption_boolUseGlobalPseudoTransparency 46 /* interface::look::global */
+#define KviOption_boolUseNotifyList 47 /* ircengine::notifylist */
+#define KviOption_boolNotifyListChangesToActiveWindow 48 /* ircengine::notifylist */
+#define KviOption_boolAutoResumeDccSendWhenAutoAccepted 49 /* dcc::send */
+#define KviOption_boolLimitOutgoingTraffic 50 /* transport */
+#define KviOption_boolSendUnknownCommandsAsRaw 51 /* ircengine::uparser */
+#define KviOption_boolUserListViewDrawGrid 52 /* look & feel::interface look::userlist */
+#define KviOption_boolShowChannelSyncTime 53 /* ircoutput */
+#define KviOption_boolRejoinChannelOnKick 54 /* irc */
+#define KviOption_boolKeepChannelOpenOnKick 55 /* irc */
+#define KviOption_boolAutoCloseDccSendOnSuccess 56 /* dcc::send */
+#define KviOption_boolNotifyDccSendSuccessInConsole 57 /* dcc::send */
+#define KviOption_boolCreateMinimizedDccSend 58 /* dcc::send */
+#define KviOption_boolCreateMinimizedDccChat 59 /* dcc::chat */
+#define KviOption_boolAutoAcceptIncomingAvatars 60 /* irc::ctcp::avatar */
+#define KviOption_boolUseNickCompletionPostfixForFirstWordOnly 61
+#define KviOption_boolUseTaskBarIcons 62 /* interface::features */
+#define KviOption_boolCreateMinimizedDccSendWhenAutoAccepted 63 /* dcc::send */
+#define KviOption_boolCreateMinimizedDccChatWhenAutoAccepted 64 /* dcc::chat */
+#define KviOption_boolDccGuessIpFromServerWhenLocalIsUnroutable 65 /* dcc */
+#define KviOption_boolShowRegisteredUsersDialogAsToplevel 66 /* interface::features::global */
+#define KviOption_boolAutoLogQueries 67 /* ircengine::logging */
+#define KviOption_boolAutoLogChannels 68 /* ircendine::logging */
+#define KviOption_boolAutoLogDccChat 69 /* ircengine::logging */
+#define KviOption_boolAutoLogConsole 70 /* ircengine::logging */
+#define KviOption_boolSilentAntiSpam 71 /* ircengine::antispam */
+#define KviOption_boolUseIncomingDccMediaTypeSavePath 72 /* dcc::send */
+#define KviOption_boolNotifyListSendUserhostForOnlineUsers 73 /* ircengine::notifylist */
+#define KviOption_boolUseIntelligentNotifyListManager 74 /* ircengine::notifylist */
+#define KviOption_boolUseWatchListIfAvailable 75 /* ircengine::notifylist */
+#define KviOption_boolUseTreeWindowListTaskBar 76 /* interface::features::global */
+#define KviOption_boolBindIrcIpV4ConnectionsToSpecifiedAddress 77 /* connection::transport */
+#define KviOption_boolBindIrcIpV6ConnectionsToSpecifiedAddress 78 /* connection::transport */
+#define KviOption_boolUseAntiSpamOnNotice 79 /* ircengine::antispam */
+#define KviOption_boolSetLastAvatarAsDefaultForRegisteredUsers 80 /* irc::ctcp::avatar */
+#define KviOption_boolCantAcceptIncomingDccConnections 81 /* dcc::general */
+#define KviOption_boolIgnoreCtcpAvatar 82 /* irc::ctcp::floodprotection */
+#define KviOption_boolCtcpRepliesToActiveWindow 83 /* ctcp */
+#define KviOption_boolAutoAcceptDccCanvas 84
+#define KviOption_boolNotifyDccSendSuccessInNotifier 85 /* dcc::send */
+#define KviOption_boolKillBrokenTimers 86 /* ircengine::uparser */
+#define KviOption_boolDccVoiceVolumeSliderControlsPCM 87 /* dcc::voice */
+#define KviOption_boolDccVoiceForceHalfDuplex 88 /* dcc::voice */
+#define KviOption_boolAutoAcceptDccVoice 89 /* dcc::voice */
+#define KviOption_boolCreateMinimizedDccVoice 90 /* dcc::voice */
+#define KviOption_boolCreateMinimizedDccVoiceWhenAutoAccepted 91 /* dcc::voice */
+#define KviOption_boolUseIdentService 92 /* connection::ident */
+#define KviOption_boolShowTipAtStartup 93 /* internal */
+#define KviOption_boolIdentdEnableIpV6 94 /* connection::ident */
+#define KviOption_boolIdentdIpV6ContainsIpV4 95 /* connection::ident */
+#define KviOption_boolScaleAvatars 96 /* ctcp::avatar */
+#define KviOption_boolColorNicks 97 /* interface::features::components::ircview */
+#define KviOption_boolBoldedNicks 98 /* interface::features::components::ircview */
+#define KviOption_boolDccListenOnSpecifiedInterfaceByDefault 99 /* dcc */
+#define KviOption_boolChangeNickAway 100 /* ircengine::away */
+#define KviOption_boolAutoGeneratedAwayNick 101 /* ircengine::away */
+#define KviOption_boolExitAwayOnInput 102 /* ircengine::away */
+#define KviOption_boolAlwaysHighlightNick 103 /* ircengine::outputcontrol::highlighting */
+#define KviOption_boolShowChannelsJoinOnIrc 104 /* internal */
+#define KviOption_boolShowChannelsJoinDialogAsToplevel 105 /* FIXME: internal ??? */
+#define KviOption_boolUserDefinedPortRange 106 /* dcc */
+#define KviOption_boolCreateQueryOnPrivmsg 107 /* irc::query */
+#define KviOption_boolCreateQueryOnNotice 108 /* irc::query */
+#define KviOption_boolCreateMinimizedQuery 109 /* irc::query */
+#define KviOption_boolAutoJoinOnInvite 110 /* irc */
+#define KviOption_boolShowServersConnectDialogOnStart 111 /* connection::ircservers */
+#define KviOption_boolShowServersConnectDialogAsToplevel 112 /* FIXME: internal ?? */
+#define KviOption_boolAcceptBrokenFileNameDccResumeRequests 113 /* dcc::send */
+#define KviOption_boolAutoReconnectOnUnexpectedDisconnect 114 /* connection */
+#define KviOption_boolRejoinChannelsAfterReconnect 115 /* connection */
+#define KviOption_boolReopenQueriesAfterReconnect 116 /* connection */
+#define KviOption_boolEnableQueryTracing 117 /* irc::query */
+#define KviOption_boolOperatorMessagesToActiveWindow 118 /* irc::output */
+#define KviOption_boolInvitesToActiveWindow 119 /* irc::output */
+#define KviOption_boolShowChannelUserFlagInPrivmsgView 120 /* ircengine::outputcontrol::privmsg */
+#define KviOption_boolDccSendFakeAddressByDefault 121 /* dcc::general */
+#define KviOption_boolUseTaskBarActivityMeter 122 /* irc::output */
+#define KviOption_boolCloseServerWidgetAfterConnect 123 /* IMPLEMENTATION NEEDED !!! */
+#define KviOption_boolShowIdentityDialogAsToplevel 124 /* ??? */
+#define KviOption_boolShowUserChannelIcons 125 /* look & feel::interface features::userlist */
+#define KviOption_boolShowUserChannelState 126 /* look & feel::interface features::userlist */
+#define KviOption_boolEnableIgnoreOnPrivMsg 127 /* irc::ignore */
+#define KviOption_boolVerboseIgnore 128 /* irc::ignore */
+#define KviOption_boolEnableIgnoreOnNotice 129 /* irc::ignore */
+#define KviOption_boolNotifyFailedDccHandshakes 130
+#define KviOption_boolAutoTileWindows 131 /* internal ? */
+#define KviOption_boolDrawEmoticons 132 /* look::interface::features::output */
+#define KviOption_boolIgnoreCtcpPage 133 /* irc::ctcp::floodprotection */
+#define KviOption_boolShowDialogOnCtcpPage 134
+#define KviOption_boolBashLikeNickCompletion 135
+#define KviOption_boolUseSSLCertificate 136 /* ssl */
+#define KviOption_boolUseSSLPrivateKey 137 /* ssl */
+#define KviOption_boolWarnAboutPastingMultipleLines 138 /* internal */
+#define KviOption_boolKeepChannelsOpenOnUnexpectedDisconnect 139 /* connection */
+#define KviOption_boolKeepQueriesOpenOnUnexpectedDisconnect 140 /* connection */
+#define KviOption_boolUseLagMeterEngine 141 /* irc::lag */
+#define KviOption_boolShowLagOnContextDisplay 142 /* irc::lag */
+#define KviOption_boolDisableBanListRequestOnJoin 143 /* irc::output */
+#define KviOption_boolDisableBanExceptionListRequestOnJoin 144 /* irc::output */
+#define KviOption_boolDisableInviteListRequestOnJoin 145 /* irc::output */
+#define KviOption_boolDisableWhoRequestOnJoin 146 /* irc::output */
+#define KviOption_boolShowDockExtension 147 /* internal ? */
+#define KviOption_boolDccAddressByIrcDns 148 /* irc::general */
+#define KviOption_boolMinimizeConsoleAfterConnect 149 /* irc::connection */
+#define KviOption_boolHighlightOnlyNormalMsg 150 /* irc::output::highlight */
+#define KviOption_boolHighlightOnlyNormalMsgQueryToo 151 /* irc::output::highlight */
+#define KviOption_boolHighlightOnlyNormalMsgHighlightInChanToo 152 /* irc::output::highlight */
+#define KviOption_boolHighlightOnlyAtCostumHighlightLevel 153 /* irc::output::highlight */
+#define KviOption_boolMdiManagerInSdiMode 154 /* internal */
+#define KviOption_boolDccBrokenBouncerHack 155 /* dcc */
+#define KviOption_boolExternalMessagesToActiveWindow 156 /* irc::output */
+#define KviOption_boolIgnoreChannelAvatarRequestsWhenNoAvatarSet 157 /* ctcp */
+#define KviOption_boolFlashQueryWindowOnNewMessages 158 /* query */
+#define KviOption_boolConfirmCloseWhenThereAreConnections 159 /* interface features */
+#define KviOption_boolUpdateKdeBackgroundOnChange 160 /* themes::general */
+#define KviOption_boolCtcpRequestsToActiveWindow 161 /* irc::output */
+#define KviOption_boolServerRepliesToActiveWindow 162 /* irc::output */
+#define KviOption_boolServerNoticesToActiveWindow 163 /* irc::output */
+#define KviOption_boolServicesNoticesToActiveWindow 164 /* irc::output */
+#define KviOption_boolSortTaskBarItemsByName 165 /* interface::features::global */
+#define KviOption_boolShowTaskBarToolTips 166 /* interface::features::global */
+#define KviOption_boolShowUserListViewToolTips 167 /* interface::features::global */
+#define KviOption_boolWhoisRepliesToActiveWindow 168 /* irc::output */
+#define KviOption_boolPopupNotifierOnNotifyOnLine 169 /* notify */
+#define KviOption_boolForciblyDisableNotifier 170 /* notifier */
+#define KviOption_boolDccSendForceIdleStep 171 /* dcc */
+#define KviOption_boolStatusBarVisible 172 /* internal */
+#define KviOption_boolTrackLastReadTextViewLine 173 /* ircview::features */
+#define KviOption_boolKeepChannelOpenOnPart 174 /* irc */
+#define KviOption_boolStripMircColorsInUserMessages 175 /* irc::output */
+#define KviOption_boolDoNotSuggestRestoreDefaultScript 176 /* internal */
+#define KviOption_boolLimitDccSendSpeed 177 /* dcc::file transfers */
+#define KviOption_boolLimitDccRecvSpeed 178 /* dcc::file transfers */
+#define KviOption_boolIgnoreModuleVersions 179
+#define KviOption_boolDisableInputHistory 180 /* interface::input */
+#define KviOption_boolUseSpecialColorForTimestamp 181 /* interface::output */
+#define KviOption_boolDisableAwayListUpdates 182 /* irc::output */
+#define KviOption_boolDisableAvatars 183 /* interface::userlist */
+#define KviOption_boolDisableUserListLabel 184 /* interface::userlist */
+#define KviOption_boolDisablePopupIcons 185 /* themes::general */
+#define KviOption_boolScriptErrorsToDebugWindow 186 /* parser */
+#define KviOption_boolShowMinimizedDebugWindow 187 /* parser */
+#define KviOption_boolShowExtendedInfoInQueryLabel 188 /* irc::query */
+#define KviOption_boolUseUserListColorsAsNickColors 189 /* irc::usermessages */
+#define KviOption_boolGzipLogs 190 /* ircengine::logging */
+#define KviOption_boolMinimizeInTray 191 /* interface */
+#define KviOption_boolDisableNotifierFlashing 192 /* interface::notifier */
+#define KviOption_boolCommandlineInUserFriendlyModeByDefault 193 /* interface::input */
+#define KviOption_boolEnableVisualEffects 194 /* interface */
+#define KviOption_boolDCCFileTransferReplaceOutgoingSpacesWithUnderscores 195
+#define KviOption_boolDoNotStretchAvatars 196
+#define KviOption_boolUseDifferentColorForOwnNick 197 /* interface */
+#define KviOption_boolCloseInTray 198 /* interface */
+#define KviOption_boolStartupMinimized 199 /* interface */
+#define KviOption_boolSortReceivedByDccFilesByNicks 200 /* dcc */
+#define KviOption_boolLogChannelHistory 201 /* irc */
+#define KviOption_boolClassicTaskBarSetMaximumButtonWidth 202
+#define KviOption_boolKeepChannelsOpenOnDisconnect 203 /* connection */
+#define KviOption_boolKeepQueriesOpenOnDisconnect 204 /* connection */
+#define KviOption_boolHideWindowToolButtons 205 /* interface */
+#define KviOption_boolHideInputToolButtons 206 /* interface */
+#define KviOption_boolStripControlCodesInLogs 207 /* log */
+#define KviOption_boolEnableTrayIconFlashing 208
+#define KviOption_boolUseFlatClassicTaskbarButtons 209
+#define KviOption_boolShowTreeTaskbarHeader 210
+#define KviOption_boolUseLevelBasedTrayNotification 211
+#define KviOption_boolMuteAllSounds 212
+#define KviOption_boolCreateMinimizedChannels 213
+#define KviOption_boolShowNetworkNameForConsoleTaskBarEntry 214
+#define KviOption_boolDrawGenderIcons 215
+#define KviOption_boolPrependGenderInfoToRealname 216
+#define KviOption_boolUseIdentServiceOnlyOnConnect 217 /* connection::ident */
+#define KviOption_boolUseSystemUrlHandlers 218 /* Windoze only*/
+#define KviOption_boolScaleAvatarsOnLoad 219
+#define KviOption_boolDisableNotifierFadein 220 /* interface::notifier */
+#define KviOption_boolUseAntiAliasing 221 /* qt4 only! */
+
+
+#define KVI_NUM_BOOL_OPTIONS 222
+
+
+
+#define KVI_STRING_OPTIONS_PREFIX "string"
+#define KVI_STRING_OPTIONS_PREFIX_LEN 6
+
+//UNUSED ! #define KviOption_stringFrameCaption 0 /* interfacelookglobal */
+#define KviOption_stringNickname1 1 /* identity */
+#define KviOption_stringNickname2 2 /* identity */
+#define KviOption_stringNickname3 3 /* identity */
+#define KviOption_stringNickname4 4 /* identity */
+#define KviOption_stringUsername 5 /* identity */
+#define KviOption_stringRealname 6 /* identity */
+#define KviOption_stringLocalHostIp 7 /* ?????? This is a fallback one */
+#define KviOption_stringPartMessage 8 /* ircengine::defaultmessages */
+#define KviOption_stringQuitMessage 9 /* ircengine::defaultmessages */
+#define KviOption_stringUrlHttpCommand 10 /* urlhandlers */
+#define KviOption_stringExtendedPrivmsgPrefix 11 /* ircengine::outputcontrol::privmsg */
+#define KviOption_stringExtendedPrivmsgPostfix 12 /* ircengine::outputcontrol::privmsg */
+#define KviOption_stringCtcpVersionPostfix 13 /* ircengine::ctcp::replies */
+#define KviOption_stringCtcpUserInfoOther 14 /* identity */
+#define KviOption_stringCtcpSourcePostfix 15 /* ircengine::ctcp::replies */
+#define KviOption_stringUrlFtpCommand 16 /* urlhandlers */
+#define KviOption_stringUrlHttpsCommand 17 /* urlhandlers */
+#define KviOption_stringUrlMailtoCommand 18 /* urlhandlers */
+#define KviOption_stringPreferredMediaPlayer 19 /* still missing in options ! */
+#define KviOption_stringUrlFileCommand 20 /* urlhandlers */
+#define KviOption_stringNickCompletionPostfix 21
+#define KviOption_stringUrlUnknownCommand 22 /* urlhandlers */
+#define KviOption_stringIpV4ConnectionBindAddress 23 /* connection::transport */
+#define KviOption_stringIpV6ConnectionBindAddress 24 /* connection::transport */
+#define KviOption_stringDccVoiceSoundDevice 25 /* dcc::voice */
+#define KviOption_stringDccVoiceMixerDevice 26 /* dcc::voice */
+#define KviOption_stringAwayMessage 27 /* irc::away */
+#define KviOption_stringIdentdUser 28 /* connection::ident */
+#define KviOption_stringDccListenDefaultInterface 29 /* dcc::general */
+#define KviOption_stringCustomAwayNick 30 /* ircengine::away */
+#define KviOption_stringDefaultDccFakeAddress 31 /* dcc::general */
+#define KviOption_stringCtcpPageReply 32 /* ircengine::ctcp::replies */
+#define KviOption_stringSSLCertificatePath 33 /* ssl */
+#define KviOption_stringSSLCertificatePass 34 /* ssl */
+#define KviOption_stringSSLPrivateKeyPath 35 /* ssl */
+#define KviOption_stringSSLPrivateKeyPass 36 /* ssl */
+#define KviOption_stringSoundSystem 37 /* sound */
+#define KviOption_stringDefaultUserMode 38
+#define KviOption_stringLastImageDialogPath 39 /* internal */
+#define KviOption_stringIconThemeSubdir 40
+#define KviOption_stringIncomingPath 41 /* folders */
+#define KviOption_stringMyAvatar 42
+// empty string means guess from locale
+#define KviOption_stringDefaultTextEncoding 43 /* text encoding */
+
+#define KviOption_stringWinampTextEncoding 44
+#define KviOption_stringMp3TagsEncoding 45
+
+#define KviOption_stringCtcpUserInfoAge 46 /* identity */
+#define KviOption_stringCtcpUserInfoGender 47 /* identity */
+#define KviOption_stringCtcpUserInfoLocation 48 /* identity */
+#define KviOption_stringCtcpUserInfoLanguages 49 /* identity */
+#define KviOption_stringWordSplitters 50 /* highlight */
+#define KviOption_stringOnNewQueryOpenedSound 51 /* sounds */
+#define KviOption_stringOnHighlightedMessageSound 52 /* sounds */
+#define KviOption_stringOnMeKickedSound 53 /* sounds */
+#define KviOption_stringOnQueryMessageSound 54 /* sounds */
+#define KviOption_stringIrcViewTimestampFormat 55
+#define KviOption_stringPreferredTorrentClient 56 /* still missing in options ! */
+
+#define KVI_NUM_STRING_OPTIONS 57
+
+
+
+#define KVI_STRINGLIST_OPTIONS_PREFIX "stringlist"
+#define KVI_STRINGLIST_OPTIONS_PREFIX_LEN 10
+
+#define KviOption_stringlistHighlightWords 0 /* ircengine::outputcontrol::highlighting */
+#define KviOption_stringlistSpamWords 1 /* ircengine::outputcontrol::antispam */
+#define KviOption_stringlistRecentChannels 2 /* internal */
+#define KviOption_stringlistRecentServers 3 /* internal */
+#define KviOption_stringlistRecentNicknames 4 /* internal */
+#define KviOption_stringlistModuleExtensionToolbars 5 /* internal */
+#define KviOption_stringlistImageSearchPaths 6 /* ??? */
+#define KviOption_stringlistRecentIrcUrls 7 /* internal */
+
+#define KVI_NUM_STRINGLIST_OPTIONS 8
+
+
+
+#define KVI_COLOR_OPTIONS_PREFIX "color"
+#define KVI_COLOR_OPTIONS_PREFIX_LEN 5
+
+#define KviOption_colorMdiBackground 0 /* ?? look & feel : gui elements : mdi manager */
+#define KviOption_colorTaskBarNormalText 1 /* look & feel::interface look::taskbar::classic taskbar */
+#define KviOption_colorTaskBarMinimizedText 2 /* look & feel::interface look::taskbar::classic taskbar */
+#define KviOption_colorTaskBarHighlight1Text 3 /* look & feel::interface look::taskbar::classic taskbar */
+#define KviOption_colorTaskBarHighlight2Text 4 /* look & feel::interface look::taskbar::classic taskbar */
+#define KviOption_colorTaskBarProgressBar 5 /* look & feel::interface look::taskbar::classic taskbar */
+#define KviOption_colorMdiCaptionActive 6 /* theme::mdicaptions */
+#define KviOption_colorMdiCaptionInactive 7 /* theme::mdicaptions */
+#define KviOption_colorCaptionTextActive 8 /* theme::mdicaptions */
+#define KviOption_colorCaptionTextActive2 9 /* theme::mdicaptions */
+#define KviOption_colorCaptionTextInactive 10 /* theme::mdicaptions */
+#define KviOption_colorCaptionTextInactive2 11 /* theme::mdicaptions */
+#define KviOption_colorIrcViewBackground 12 /* look & feel::interface look::ircview */
+#define KviOption_colorInputBackground 13 /* look & feel::interface look::input */
+#define KviOption_colorInputSelectionBackground 14 /* look & feel::interface look::input */
+#define KviOption_colorInputSelectionForeground 15 /* look & feel::interface look::input */
+#define KviOption_colorInputCursor 16 /* look & feel::interface look::input */
+#define KviOption_colorInputControl 17 /* look & feel::interface look::input */
+#define KviOption_colorInputForeground 18 /* look & feel::interface look::input */
+#define KviOption_colorUserListViewBackground 19 /* look & feel::interface look::userlist */
+#define KviOption_colorUserListViewOpForeground 20 /* look & feel::interface look::userlist */
+#define KviOption_colorUserListViewVoiceForeground 21 /* look & feel::interface look::userlist */
+#define KviOption_colorUserListViewNormalForeground 22 /* look & feel::interface look::userlist */
+#define KviOption_colorUserListViewSelectionBackground 23 /* look & feel::interface look::userlist */
+#define KviOption_colorUserListViewSelectionForeground 24 /* look & feel::interface look::userlist */
+#define KviOption_colorLabelBackground 25 /* look & feel::interface look::topic label */
+#define KviOption_colorLabelForeground 26 /* look & feel::interface look::topic label */
+#define KviOption_colorGlobalTransparencyFade 27 /* look & feel::interface look */
+#define KviOption_colorIrcToolBarAppletBackground 28 /* theme::tool bar applets */
+#define KviOption_colorIrcToolBarAppletForegroundLowContrast 29 /* theme::tool bar applets */
+#define KviOption_colorIrcToolBarAppletForegroundMidContrast 30 /* theme::tool bar applets */
+#define KviOption_colorIrcToolBarAppletForegroundHighContrastInactive1 31 /* theme::tool bar applets */
+#define KviOption_colorIrcToolBarAppletForegroundHighContrastInactive2 32 /* theme::tool bar applets */
+#define KviOption_colorIrcToolBarAppletForegroundHighContrastActive1 33 /* theme::tool bar applets */
+#define KviOption_colorIrcToolBarAppletForegroundHighContrastActive2 34 /* theme::tool bar applets */
+#define KviOption_colorTreeTaskBarBackground 35 /* look & feel::interface look::taskbar::tree taskbar */
+#define KviOption_colorTreeTaskBarActiveBackground 36 /* look & feel::interface look::taskbar::tree taskbar */
+#define KviOption_colorTreeTaskBarForeground 37 /* look & feel::interface look::taskbar::tree taskbar */
+#define KviOption_colorTreeTaskBarActiveForeground 38 /* look & feel::interface look::taskbar::tree taskbar */
+#define KviOption_colorTreeTaskBarHighlight1Foreground 39 /* look & feel::interface look::taskbar::tree taskbar */
+#define KviOption_colorTreeTaskBarHighlight2Foreground 40 /* look & feel::interface look::taskbar::tree taskbar */
+#define KviOption_colorTreeTaskBarProgress 41 /* look & feel::interface look::taskbar::tree taskbar */
+#define KviOption_colorUserListViewHalfOpForeground 42 /* look & feel::interface look::userlist */
+#define KviOption_colorTaskBarHighlight3Text 43 /* look & feel::interface look::taskbar::classic taskbar */
+#define KviOption_colorTaskBarHighlight4Text 44 /* look & feel::interface look::taskbar::classic taskbar */
+#define KviOption_colorTaskBarHighlight5Text 45 /* look & feel::interface look::taskbar::classic taskbar */
+#define KviOption_colorTreeTaskBarHighlight3Foreground 46 /* look & feel::interface look::taskbar::tree taskbar */
+#define KviOption_colorTreeTaskBarHighlight4Foreground 47 /* look & feel::interface look::taskbar::tree taskbar */
+#define KviOption_colorTreeTaskBarHighlight5Foreground 48 /* look & feel::interface look::taskbar::tree taskbar */
+#define KviOption_colorUserListViewChanAdminForeground 49 /* look & feel::interface look::userlist */
+#define KviOption_colorUserListViewUserOpForeground 50 /* look & feel::interface look::userlist */
+#define KviOption_colorUserListViewGrid 51 /* look & feel::interface look::userlist */
+#define KviOption_colorUserListViewChanOwnerForeground 52 /* look & feel::interface look::userlist */
+#define KviOption_colorIrcViewMarkLine 53 /* look & feel::interface look::ircvew */
+#define KviOption_colorUserListViewAwayForeground 54 /* look & feel::interface look::userlist */
+#define KviOption_colorUserListViewOwnForeground 55 /* look & feel::interface look::userlist */
+
+#define KVI_NUM_COLOR_OPTIONS 56
+
+
+
+#define KVI_PIXMAP_OPTIONS_PREFIX "pixmap"
+#define KVI_PIXMAP_OPTIONS_PREFIX_LEN 6
+
+#define KviOption_pixmapMdiBackground 0
+#define KviOption_pixmapIrcViewBackground 1 /* interface::look::components::ircview */
+#define KviOption_pixmapInputBackground 2 /* interface::look::components::input */
+#define KviOption_pixmapUserListViewBackground 3 /* look & feel::interface look::userlist */
+#define KviOption_pixmapLabelBackground 4 /* look & feel::interface look::topic label */
+#define KviOption_pixmapMyAvatar 5 /* identity */
+#define KviOption_pixmapIrcToolBarAppletBackground 6 /* theme::tool bar applets */
+#define KviOption_pixmapTreeTaskBarBackground 7 /* look & feel::interface look::taskbar::tree taskbar */
+#define KviOption_pixmapGlobalTransparencyBackground 8 /* theme::transparency */
+
+#define KVI_NUM_PIXMAP_OPTIONS 9
+
+
+
+
+#define KVI_UINT_OPTIONS_PREFIX "uint"
+#define KVI_UINT_OPTIONS_PREFIX_LEN 4
+
+#define KviOption_uintIrcSocketTimeout 0 /* connection::transport */
+#define KviOption_uintModuleCleanupTimerInterval 1
+#define KviOption_uintModuleCleanupTimeout 2
+#define KviOption_uintMaxCtcpRequests 3 /* ircengine::ctcp */
+#define KviOption_uintCtcpFloodCheckInterval 4 /* ircengine::ctcp */
+#define KviOption_uintTotalConnectionTime 5
+#define KviOption_uintDccSocketTimeout 6 /* dcc::general */
+#define KviOption_uintDccSendIdleStepInMSec 7 /* dcc::send */
+#define KviOption_uintDccSendPacketSize 8 /* dcc::send */
+#define KviOption_uintGlobalTransparencyParentFadeFactor 9 /* interface::look::general */
+#define KviOption_uintGlobalTransparencyChildFadeFactor 10 /* interface::look::general */
+#define KviOption_uintNotifyListCheckTimeInSecs 11 /* notify */
+#define KviOption_uintSocketQueueFlushTimeout 12 /* connection::transport */
+#define KviOption_uintOutgoingTrafficLimitUSeconds 13 /* connection::transport */
+#define KviOption_uintNotifyListIsOnDelayTimeInSecs 14 /* notify */
+#define KviOption_uintNotifyListUserhostDelayTimeInSecs 15 /* notify */
+#define KviOption_uintTreeTaskBarMinimumWidth 16 /* ?? interface::general ?? */
+#define KviOption_uintAvatarOfferTimeoutInSecs 17 /* irc::ctcp::avatar */
+#define KviOption_uintIrcViewMaxBufferSize 18 /* interface::features::components::ircview */
+#define KviOption_uintIrcViewToolTipTimeoutInMsec 19 /* interface::features::components::ircview */
+#define KviOption_uintIrcViewToolTipHideTimeoutInMsec 20 /* interface::features::components::ircview */
+#define KviOption_uintDccVoicePreBufferSize 21 /* dcc::voice */
+#define KviOption_uintIdentdPort 22 /* connection::ident */
+#define KviOption_uintAvatarScaleWidth 23 /* ctcp::avatar */
+#define KviOption_uintAvatarScaleHeight 24 /* ctcp::avatar */
+#define KviOption_uintDccMinPort 25 /* dcc::general */
+#define KviOption_uintDccMaxPort 26 /* dcc::general */
+#define KviOption_uintSoundOfferTimeoutInSecs 27
+#define KviOption_uintMaximumRequestedAvatarSize 28 /* ctcp::avatar */
+// FIXME: THIS IS NO LONGER NEEDED ?
+#define KviOption_uintTreeTaskBarMaximumWidth 29
+#define KviOption_uintPasteDelay 30
+// 0 = unlimited!
+#define KviOption_uintMaxDccSendTransfers 31
+// 0 = unlimited slots = windows
+#define KviOption_uintMaxDccSlots 32
+#define KviOption_uintTileMethod 33 /* internal ? */
+#define KviOption_uintLagMeterHeartbeat 34
+#define KviOption_uintLagAlarmTime 35
+// KVI_TEXT_ENCODING_UNKNOWN = KviLocale::defaultTextEncoding() <-- guessed from locale
+//#define KviOption_uintDefaultTextEncoding 36 /* textencoding */
+#define KviOption_uintTaskBarButtonMinWidth 37 /* interface::look::taskbar::classic taskbar */
+// follows the verbosity constants defined below
+#define KviOption_uintOutputVerbosityLevel 38
+#define KviOption_uintIrcContextAppletWidth 39 /* internal */
+#define KviOption_uintMinHighlightLevel 40 /* look::interface::features::output */
+#define KviOption_uintUserListViewGridType 41 /* look&feel::ircview */
+#define KviOption_uintTaskBarMaximumRows 42 /* interface::look::taskbar::classic taskbar */
+// 0 = unlimited attempts
+#define KviOption_uintMaxAutoReconnectAttempts 43 /* connection */
+#define KviOption_uintAutoReconnectDelay 44 /* connection */
+#define KviOption_uintMaxDccSendSpeed 45 /* dcc::file transfers */
+#define KviOption_uintMaxDccRecvSpeed 46 /* dcc::file transfers */
+#define KviOption_uintTimeStampForeground 47
+#define KviOption_uintTimeStampBackground 48
+#define KviOption_uintUserExperienceLevel 49
+#define KviOption_uintClassicTaskBarMaximumButtonWidth 50
+#define KviOption_uintDefaultBanType 51
+#define KviOption_uintIrcViewPixmapAlign 52
+#define KviOption_uintUserListPixmapAlign 53
+#define KviOption_uintToolBarAppletPixmapAlign 54
+#define KviOption_uintTreeTaskBarPixmapAlign 55
+#define KviOption_uintInputPixmapAlign 56
+#define KviOption_uintAutoFlushLogs 57
+#define KviOption_uintMinTrayLowLevelMessage 58
+#define KviOption_uintMinTrayHighLevelMessage 59
+#define KviOption_uintIdentdOutputMode 60
+#define KviOption_uintScaleAvatarsOnLoadHeight 61
+#define KviOption_uintScaleAvatarsOnLoadWidth 62
+#define KviOption_uintNotifierActiveTransparency 63
+#define KviOption_uintNotifierInactiveTransparency 64
+
+#define KVI_NUM_UINT_OPTIONS 65
+
+namespace KviIdentdOutputMode {
+ enum Mode {
+ Quiet = 0,
+ ToConsole = 1,
+ ToActiveWindow = 2
+ };
+}
+
+
+#define KVI_FONT_OPTIONS_PREFIX "font"
+#define KVI_FONT_OPTIONS_PREFIX_LEN 4
+
+#define KviOption_fontIrcView 0 /* interface::look::components::ircview */
+#define KviOption_fontInput 1 /* interface::look::components::input */
+#define KviOption_fontUserListView 2 /* look & feel::interface look::userlist */
+#define KviOption_fontLabel 3 /* look & feel::interface look::topic label */
+#define KviOption_fontApplication 4 /* interface::look::global */
+#define KviOption_fontIrcToolBarApplet 5 /* theme::tool bar applet */
+#define KviOption_fontTaskbar 6 /* interface::look::taskbar::classic taskbar */
+
+/* fixme: taskbar font ? */
+
+#define KVI_NUM_FONT_OPTIONS 7
+
+
+
+
+#define KVI_ICCOLOR_OPTIONS_PREFIX "iccolor"
+#define KVI_ICCOLOR_OPTIONS_PREFIX_LEN 7
+
+#define KVI_NUM_ICCOLOR_OPTIONS 8
+
+
+// indices declared in kvi_out.h
+
+#define KVI_MSGTYPE_OPTIONS_PREFIX "msgtype"
+#define KVI_MSGTYPE_OPTIONS_PREFIX_LEN 7
+
+#define KVI_NUM_MSGTYPE_OPTIONS 137
+
+
+
+#define KVI_MIRCCOLOR_OPTIONS_PREFIX "mirccolor"
+#define KVI_MIRCCOLOR_OPTIONS_PREFIX_LEN 9
+
+#define KVI_NUM_MIRCCOLOR_OPTIONS 16
+
+
+// external declaration of the tables
+extern KVIRC_API KviBoolOption g_boolOptionsTable[KVI_NUM_BOOL_OPTIONS];
+extern KVIRC_API KviRectOption g_rectOptionsTable[KVI_NUM_RECT_OPTIONS];
+extern KVIRC_API KviStringOption g_stringOptionsTable[KVI_NUM_STRING_OPTIONS];
+extern KVIRC_API KviColorOption g_colorOptionsTable[KVI_NUM_COLOR_OPTIONS];
+extern KVIRC_API KviPixmapOption g_pixmapOptionsTable[KVI_NUM_PIXMAP_OPTIONS];
+// extern KviIntOption g_intOptionsTable[KVI_NUM_INT_OPTIONS];
+extern KVIRC_API KviUIntOption g_uintOptionsTable[KVI_NUM_UINT_OPTIONS];
+extern KVIRC_API KviFontOption g_fontOptionsTable[KVI_NUM_FONT_OPTIONS];
+extern KVIRC_API KviMsgTypeOption g_msgtypeOptionsTable[KVI_NUM_MSGTYPE_OPTIONS];
+extern KVIRC_API KviColorOption g_mirccolorOptionsTable[KVI_NUM_MIRCCOLOR_OPTIONS];
+extern KVIRC_API KviColorOption g_iccolorOptionsTable[KVI_NUM_ICCOLOR_OPTIONS];
+extern KVIRC_API KviStringListOption g_stringlistOptionsTable[KVI_NUM_STRINGLIST_OPTIONS];
+
+// __this is how we access the options from outside
+#define KVI_OPTION_BOOL(_idx) g_boolOptionsTable[_idx].option
+#define KVI_OPTION_RECT(_idx) g_rectOptionsTable[_idx].option
+#define KVI_OPTION_STRING(_idx) g_stringOptionsTable[_idx].option
+#define KVI_OPTION_COLOR(_idx) g_colorOptionsTable[_idx].option
+#define KVI_OPTION_PIXMAP(_idx) g_pixmapOptionsTable[_idx].option
+#define KVI_OPTION_UINT(_idx) g_uintOptionsTable[_idx].option
+#define KVI_OPTION_FONT(_idx) g_fontOptionsTable[_idx].option
+#define KVI_OPTION_MSGTYPE(_idx) g_msgtypeOptionsTable[_idx].option
+#define KVI_OPTION_MIRCCOLOR(_idx) g_mirccolorOptionsTable[_idx].option
+#define KVI_OPTION_STRINGLIST(_idx) g_stringlistOptionsTable[_idx].option
+#define KVI_OPTION_ICCOLOR(_idx) g_iccolorOptionsTable[_idx].option
+
+
+// Verbosity constants
+
+#define KVI_VERBOSITY_LEVEL_MUTE 0
+#define KVI_VERBOSITY_LEVEL_QUIET 1
+#define KVI_VERBOSITY_LEVEL_NORMAL 2
+#define KVI_VERBOSITY_LEVEL_VERBOSE 3
+#define KVI_VERBOSITY_LEVEL_PARANOIC 4
+
+#define _OUTPUT_PARANOIC (KVI_OPTION_UINT(KviOption_uintOutputVerbosityLevel) >= KVI_VERBOSITY_LEVEL_PARANOIC)
+#define _OUTPUT_VERBOSE (KVI_OPTION_UINT(KviOption_uintOutputVerbosityLevel) >= KVI_VERBOSITY_LEVEL_VERBOSE)
+#define _OUTPUT_QUIET (KVI_OPTION_UINT(KviOption_uintOutputVerbosityLevel) <= KVI_VERBOSITY_LEVEL_QUIET)
+#define _OUTPUT_MUTE (KVI_OPTION_UINT(KviOption_uintOutputVerbosityLevel) <= KVI_VERBOSITY_LEVEL_MUTE)
+
+#ifdef COMPILE_USE_QT4
+ #define START_TABLE_BOLD_ROW "<tr><td style=\"background-color: rgb(0,0,0); font-weight: bold; color: rgb(200,200,255); text-indent: 5px;\"><nobr>"
+ #define END_TABLE_BOLD_ROW "</nobr></td></tr>"
+
+ #define START_TABLE_NORMAL_ROW "<tr><td>"
+
+ #define SET_ANTI_ALIASING(p) \
+ (p).setRenderHint(QPainter::Antialiasing, KVI_OPTION_BOOL(KviOption_boolUseAntiAliasing)); \
+ (p).setRenderHint(QPainter::TextAntialiasing, KVI_OPTION_BOOL(KviOption_boolUseAntiAliasing));
+#else
+ #define START_TABLE_BOLD_ROW "<tr><td bgcolor=\"#303030\">" \
+ "<font color=\"#FFFFFF\"><nobr><b>"
+ #define END_TABLE_BOLD_ROW "</b></nobr></font></td></tr>"
+
+ #define START_TABLE_NORMAL_ROW "<tr><td bgcolor=\"#F0F0F0\">"
+
+ #define SET_ANTI_ALIASING(p)
+#endif
+
+
+#if defined(_KVI_OPTIONS_CPP_) || defined(_WANT_OPTION_FLAGS_)
+
+ // flag definitions
+
+ // section of the config file (rightmost 8 bits)
+ #define KviOption_sectFlagNone 0
+ #define KviOption_sectFlagFrame 1
+ #define KviOption_sectFlagMdi 2
+ #define KviOption_sectFlagTaskBar 3
+ #define KviOption_sectFlagWindows 4
+ #define KviOption_sectFlagIrcView 5
+ #define KviOption_sectFlagMsgType 6
+ #define KviOption_sectFlagMircColor 7
+ #define KviOption_sectFlagInput 8
+ #define KviOption_sectFlagUserParser 9
+ #define KviOption_sectFlagConnection 10
+ #define KviOption_sectFlagIrcSocket 11
+ #define KviOption_sectFlagUser 12
+ #define KviOption_sectFlagUserListView 13
+ #define KviOption_sectFlagLabel 14
+ #define KviOption_sectFlagModules 15
+ #define KviOption_sectFlagCtcp 16
+ #define KviOption_sectFlagDcc 17
+ #define KviOption_sectFlagGui 18
+ #define KviOption_sectFlagIrcToolBar 19
+ #define KviOption_sectFlagLogging 20
+ #define KviOption_sectFlagAntiSpam 21
+ #define KviOption_sectFlagAvatar 22
+ #define KviOption_sectFlagUrl 23
+ #define KviOption_sectFlagRecent 24
+ #define KviOption_sectFlagGeometry 25
+
+ #define KVI_NUM_OPTION_SECT_FLAGS 26
+
+ #define KviOption_sectMask 255
+
+ // other logical groupings of options
+ #define KviOption_groupTheme (1 << 8)
+
+ #define KviOption_groupMask (255 << 8)
+
+
+
+ // actions to take when an option is set
+ #define KviOption_resetNone 0
+ //#define KviOption_resetUpdateCaption (1 << 16) UNUSED!
+ #define KviOption_resetUpdateGui (1 << 17)
+ #define KviOption_resetUpdateTaskBar (1 << 18)
+ #define KviOption_resetUpdateAppFont (1 << 19)
+ #define KviOption_resetUpdatePseudoTransparency (1 << 20)
+ #define KviOption_resetRestartNotifyList (1 << 21)
+ #define KviOption_resetRestartIdentd (1 << 22)
+ #define KviOption_resetReloadImages (1 << 23)
+ #define KviOption_resetRestartLagMeter (1 << 24)
+ #define KviOption_resetRecentChannels (1 << 25)
+
+ #define KviOption_resetMask (~(KviOption_sectMask | KviOption_groupMask))
+
+ //for file pathes
+ #define KviOption_encodePath (1 << 25)
+
+#endif
+
+#endif //_KVI_OPTIONS_H_
diff --git a/src/kvirc/kernel/kvi_out.h b/src/kvirc/kernel/kvi_out.h
new file mode 100644
index 00000000..f73a4f69
--- /dev/null
+++ b/src/kvirc/kernel/kvi_out.h
@@ -0,0 +1,169 @@
+#ifndef _KVI_OUT_H_
+#define _KVI_OUT_H_
+
+//
+// File : kvi_out.h
+// Creation date : Fri Jun 30 2000 14:13:21 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+#define KVI_OUT_NONE 0
+#define KVI_OUT_SELECT 1
+#define KVI_OUT_HIGHLIGHT 2
+#define KVI_OUT_URL 3
+#define KVI_OUT_LINK 4
+#define KVI_OUT_PARSERERROR 5
+#define KVI_OUT_PARSERWARNING 6
+#define KVI_OUT_HOSTLOOKUP 7
+#define KVI_OUT_SOCKETMESSAGE 8
+#define KVI_OUT_SOCKETWARNING 9
+#define KVI_OUT_SOCKETERROR 10
+#define KVI_OUT_SYSTEMERROR 11
+#define KVI_OUT_RAW 12
+#define KVI_OUT_CONNECTION 13
+#define KVI_OUT_SYSTEMWARNING 14
+#define KVI_OUT_SYSTEMMESSAGE 15
+#define KVI_OUT_UNHANDLED 16
+#define KVI_OUT_SERVERINFO 17
+#define KVI_OUT_MOTD 18
+#define KVI_OUT_SERVERPING 19
+#define KVI_OUT_JOIN 20
+#define KVI_OUT_PART 21
+#define KVI_OUT_UNRECOGNIZED 22
+#define KVI_OUT_TOPIC 23
+#define KVI_OUT_OWNPRIVMSG 24
+#define KVI_OUT_CHANPRIVMSG 25
+#define KVI_OUT_QUERYPRIVMSG 26
+#define KVI_OUT_CTCPREPLY 27
+#define KVI_OUT_CTCPREQUESTREPLIED 28
+#define KVI_OUT_CTCPREQUESTIGNORED 29
+#define KVI_OUT_CTCPREQUESTFLOOD 30
+#define KVI_OUT_CTCPREQUESTUNKNOWN 31
+#define KVI_OUT_ACTION 32
+#define KVI_OUT_AVATAR 33
+#define KVI_OUT_QUIT 34
+#define KVI_OUT_SPLIT 35
+#define KVI_OUT_QUITSPLIT 36
+#define KVI_OUT_NICK 37
+#define KVI_OUT_OP 38
+#define KVI_OUT_DEOP 39
+#define KVI_OUT_VOICE 40
+#define KVI_OUT_DEVOICE 41
+#define KVI_OUT_MODE 42
+#define KVI_OUT_KEY 43
+#define KVI_OUT_LIMIT 44
+#define KVI_OUT_BAN 45
+#define KVI_OUT_UNBAN 46
+#define KVI_OUT_BANEXCEPT 47
+#define KVI_OUT_BANUNEXCEPT 48
+#define KVI_OUT_INVITEEXCEPT 49
+#define KVI_OUT_INVITEUNEXCEPT 50
+#define KVI_OUT_CHANMODE 51
+#define KVI_OUT_WHO 52
+#define KVI_OUT_DCCREQUEST 53
+#define KVI_OUT_DCCMSG 54
+#define KVI_OUT_DCCERROR 55
+#define KVI_OUT_NICKNAMEPROBLEM 56
+#define KVI_OUT_WHOISUSER 57
+#define KVI_OUT_WHOISCHANNELS 58
+#define KVI_OUT_WHOISIDLE 59
+#define KVI_OUT_WHOISSERVER 60
+#define KVI_OUT_WHOISOTHER 61
+#define KVI_OUT_CREATIONTIME 62
+#define KVI_OUT_NOTIFYONLINE 63
+#define KVI_OUT_NOTIFYOFFLINE 64
+#define KVI_OUT_OWNPRIVMSGCRYPTED 65
+#define KVI_OUT_CHANPRIVMSGCRYPTED 66
+#define KVI_OUT_QUERYPRIVMSGCRYPTED 67
+#define KVI_OUT_DCCCHATMSG 68
+#define KVI_OUT_DCCCHATMSGCRYPTED 69
+#define KVI_OUT_IRC 70
+#define KVI_OUT_KICK 71
+#define KVI_OUT_LINKS 72
+#define KVI_OUT_SPAM 73
+#define KVI_OUT_ICQ 74
+#define KVI_OUT_ICQMESSAGE 75
+#define KVI_OUT_ICQMESSAGESENT 76
+#define KVI_OUT_CHANNELNOTICE 77
+#define KVI_OUT_CHANNELNOTICECRYPTED 78
+#define KVI_OUT_QUERYNOTICE 79
+#define KVI_OUT_QUERYNOTICECRYPTED 80
+#define KVI_OUT_SERVERNOTICE 81
+#define KVI_OUT_HALFOP 82
+#define KVI_OUT_CTCPREPLYUNKNOWN 83
+#define KVI_OUT_NICKSERV 84
+#define KVI_OUT_CHANSERV 85
+#define KVI_OUT_AWAY 86
+#define KVI_OUT_IDENT 87
+#define KVI_OUT_LIST 88
+#define KVI_OUT_HALFDEOP 89
+#define KVI_OUT_INVITE 90
+#define KVI_OUT_MULTIMEDIA 91
+#define KVI_OUT_QUERYTRACE 92
+#define KVI_OUT_WALLOPS 93
+#define KVI_OUT_JOINERROR 94
+#define KVI_OUT_BROADCASTPRIVMSG 95
+#define KVI_OUT_BROADCASTNOTICE 96
+#define KVI_OUT_MEKICK 97
+#define KVI_OUT_MEOP 98
+#define KVI_OUT_MEVOICE 99
+#define KVI_OUT_MEDEOP 100
+#define KVI_OUT_MEDEVOICE 101
+#define KVI_OUT_MEHALFOP 102
+#define KVI_OUT_MEDEHALFOP 103
+#define KVI_OUT_MEBAN 104
+#define KVI_OUT_MEUNBAN 105
+#define KVI_OUT_MEBANEXCEPT 106
+#define KVI_OUT_MEBANUNEXCEPT 107
+#define KVI_OUT_MEINVITEEXCEPT 108
+#define KVI_OUT_MEINVITEUNEXCEPT 109
+#define KVI_OUT_IGNORE 110
+#define KVI_OUT_STATS 111
+#define KVI_OUT_SSL 112
+#define KVI_OUT_SEARCH 113
+#define KVI_OUT_GENERICSUCCESS 114
+#define KVI_OUT_GENERICSTATUS 115
+#define KVI_OUT_GENERICVERBOSE 116
+#define KVI_OUT_GENERICWARNING 117
+#define KVI_OUT_GENERICERROR 118
+#define KVI_OUT_GENERICCRITICAL 119
+#define KVI_OUT_CHANADMIN 120
+#define KVI_OUT_DECHANADMIN 121
+#define KVI_OUT_MECHANADMIN 122
+#define KVI_OUT_MEDECHANADMIN 123
+#define KVI_OUT_USEROP 124
+#define KVI_OUT_USERDEOP 125
+#define KVI_OUT_MEUSEROP 126
+#define KVI_OUT_MEDEUSEROP 127
+#define KVI_OUT_VERBOSE 128
+#define KVI_OUT_MECHANOWNER 129
+#define KVI_OUT_CHANOWNER 130
+#define KVI_OUT_MEDECHANOWNER 131
+#define KVI_OUT_DECHANOWNER 132
+#define KVI_OUT_SERVERERROR 133
+#define KVI_OUT_HELP 134
+#define KVI_OUT_TEXTENCODING 135
+#define KVI_OUT_TORRENT 136
+
+//#define KVI_NUM_MSGTYPE_OPTIONS 136
+// UPDATE THE TOTAL COUNT IN kvi_options.h !!!!
+
+
+#endif //_KVI_OPTIONS_H_
diff --git a/src/kvirc/kernel/kvi_sslmaster.cpp b/src/kvirc/kernel/kvi_sslmaster.cpp
new file mode 100644
index 00000000..20630486
--- /dev/null
+++ b/src/kvirc/kernel/kvi_sslmaster.cpp
@@ -0,0 +1,168 @@
+//
+// File : kvi_sslmanager.cpp
+// Creation date : Mon Jun 17 2002 20:34:00 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+#define __KVIRC__
+
+#include "kvi_sslmaster.h"
+
+#ifdef COMPILE_SSL_SUPPORT
+
+#include "kvi_window.h"
+#include "kvi_options.h"
+#include "kvi_out.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_locale.h"
+
+namespace KviSSLMaster
+{
+
+KVIRC_API void printSSLCipherInfo(KviWindow * wnd,const char * description,KviSSLCipherInfo * c)
+{
+ wnd->output(KVI_OUT_SSL,__tr2qs("[SSL]: %c%s"),KVI_TEXT_BOLD,description);
+ wnd->output(KVI_OUT_SSL,__tr2qs("[SSL]: Cipher: %c%s"),KVI_TEXT_BOLD,c->name());
+ wnd->output(KVI_OUT_SSL,__tr2qs("[SSL]: Version: %c%s"),KVI_TEXT_BOLD,c->version());
+ wnd->output(KVI_OUT_SSL,__tr2qs("[SSL]: Bits: %c%d (%d used)"),KVI_TEXT_BOLD,c->bits(),c->bitsUsed());
+// wnd->output(KVI_OUT_SSL,__tr2qs("[SSL]: Description: %c%s"),KVI_TEXT_BOLD,c->description());
+}
+
+KVIRC_API void printSSLCertificate(KviWindow * wnd,const char * description,KviSSLCertificate * c)
+{
+ wnd->output(KVI_OUT_SSL,__tr2qs("[SSL]: %c%s"),KVI_TEXT_BOLD,description);
+ wnd->output(KVI_OUT_SSL,__tr2qs("[SSL]: Version: %c%d"),KVI_TEXT_BOLD,c->version());
+ wnd->output(KVI_OUT_SSL,__tr2qs("[SSL]: Serial number: %c%d"),KVI_TEXT_BOLD,c->serialNumber());
+ wnd->output(KVI_OUT_SSL,__tr2qs("[SSL]: Subject:"));
+ wnd->output(KVI_OUT_SSL,__tr2qs("[SSL]: Common name: %c%s"),KVI_TEXT_BOLD,c->subjectCommonName());
+ wnd->output(KVI_OUT_SSL,__tr2qs("[SSL]: Organization: %c%s"),KVI_TEXT_BOLD,c->subjectOrganization());
+ wnd->output(KVI_OUT_SSL,__tr2qs("[SSL]: Organizational unit: %c%s"),KVI_TEXT_BOLD,c->subjectOrganizationalUnit());
+ wnd->output(KVI_OUT_SSL,__tr2qs("[SSL]: Country: %c%s"),KVI_TEXT_BOLD,c->subjectCountry());
+ wnd->output(KVI_OUT_SSL,__tr2qs("[SSL]: State or province: %c%s"),KVI_TEXT_BOLD,c->subjectStateOrProvince());
+ wnd->output(KVI_OUT_SSL,__tr2qs("[SSL]: Locality: %c%s"),KVI_TEXT_BOLD,c->subjectLocality());
+ wnd->output(KVI_OUT_SSL,__tr2qs("[SSL]: Issuer:"));
+ wnd->output(KVI_OUT_SSL,__tr2qs("[SSL]: Common name: %c%s"),KVI_TEXT_BOLD,c->issuerCommonName());
+ wnd->output(KVI_OUT_SSL,__tr2qs("[SSL]: Organization: %c%s"),KVI_TEXT_BOLD,c->issuerOrganization());
+ wnd->output(KVI_OUT_SSL,__tr2qs("[SSL]: Organizational unit: %c%s"),KVI_TEXT_BOLD,c->issuerOrganizationalUnit());
+ wnd->output(KVI_OUT_SSL,__tr2qs("[SSL]: Country: %c%s"),KVI_TEXT_BOLD,c->issuerCountry());
+ wnd->output(KVI_OUT_SSL,__tr2qs("[SSL]: State or province: %c%s"),KVI_TEXT_BOLD,c->issuerStateOrProvince());
+ wnd->output(KVI_OUT_SSL,__tr2qs("[SSL]: Locality: %c%s"),KVI_TEXT_BOLD,c->issuerLocality());
+ wnd->output(KVI_OUT_SSL,__tr2qs("[SSL]: Public key: %c%s (%d bits)"),KVI_TEXT_BOLD,c->publicKeyType(),c->publicKeyBits());
+ wnd->output(KVI_OUT_SSL,__tr2qs("[SSL]: Signature type: %c%s"),KVI_TEXT_BOLD,c->signatureType());
+ KviStr tmp = c->signatureContents();
+ if(tmp.len() > 40)
+ {
+ tmp.cutRight(tmp.len() - 40);
+ tmp.append("...");
+ }
+ wnd->output(KVI_OUT_SSL,__tr2qs("[SSL]: Signature contents: %c%s"),KVI_TEXT_BOLD,tmp.ptr());
+
+}
+
+KVIRC_API void printSSLConnectionInfo(KviWindow * wnd,KviSSL * s)
+{
+ KviSSLCertificate * sc = s->getPeerCertificate();
+ if(sc)
+ {
+ QString tmp(__tr2qs("Peer X509 certificate"));
+ KviSSLMaster::printSSLCertificate(wnd,tmp,sc);
+ delete sc;
+ } else wnd->outputNoFmt(KVI_OUT_SSL,__tr2qs("[SSL]: The peer didn't provide a certificate"));
+ KviSSLCipherInfo * ci = s->getCurrentCipherInfo();
+ if(ci)
+ {
+ QString tmp(__tr2qs("Current transmission cipher"));
+ KviSSLMaster::printSSLCipherInfo(wnd,tmp,ci);
+ delete ci;
+ } else wnd->outputNoFmt(KVI_OUT_SSL,__tr2qs("[SSL]: Can't find out the current cipher info"));
+}
+
+KVIRC_API KviSSL * allocSSL(KviWindow * wnd,kvi_socket_t sock,KviSSL::Method m,const char * contextString)
+{
+ KviSSL * s = new KviSSL();
+ if(!s->initContext(m))
+ {
+ delete s;
+ return 0;
+ }
+
+ if(!contextString)contextString = KviStr::emptyString().ptr();
+
+ if(KVI_OPTION_BOOL(KviOption_boolUseSSLCertificate))
+ {
+ switch(s->useCertificateFile(
+ KVI_OPTION_STRING(KviOption_stringSSLCertificatePath).utf8().data(),
+ KVI_OPTION_STRING(KviOption_stringSSLCertificatePass).utf8().data()))
+ {
+ case KviSSL::Success:
+ if(wnd)wnd->output(KVI_OUT_SSL,__tr2qs("[%s]: [SSL]: Using certificate file %s"),contextString,KVI_OPTION_STRING(KviOption_stringSSLCertificatePath).utf8().data());
+ break;
+ case KviSSL::FileIoError:
+ if(wnd)wnd->output(KVI_OUT_SSL,__tr2qs("[%s]: [SSL ERROR]: File I/O error while trying to use the certificate file %s"),contextString,KVI_OPTION_STRING(KviOption_stringSSLCertificatePath).utf8().data());
+ break;
+ default:
+ {
+ KviStr buffer;
+ while(s->getLastErrorString(buffer))
+ {
+ if(wnd)wnd->output(KVI_OUT_SSL,__tr2qs("[%s]: [SSL ERROR]: %s"),contextString,buffer.ptr());
+ }
+ }
+ break;
+ }
+ }
+ if(KVI_OPTION_BOOL(KviOption_boolUseSSLPrivateKey))
+ {
+ switch(s->usePrivateKeyFile(
+ KVI_OPTION_STRING(KviOption_stringSSLPrivateKeyPath).utf8().data(),
+ KVI_OPTION_STRING(KviOption_stringSSLPrivateKeyPass).utf8().data()))
+ {
+ case KviSSL::Success:
+ if(wnd)wnd->output(KVI_OUT_SSL,__tr2qs("[%s]: [SSL]: Using private key file %s"),contextString,KVI_OPTION_STRING(KviOption_stringSSLPrivateKeyPath).utf8().data());
+ break;
+ case KviSSL::FileIoError:
+ if(wnd)wnd->output(KVI_OUT_SSL,__tr2qs("[%s]: [SSL ERROR]: File I/O error while trying to use the private key file %s"),contextString,KVI_OPTION_STRING(KviOption_stringSSLPrivateKeyPath).utf8().data());
+ break;
+ default:
+ {
+ KviStr buffer;
+ while(s->getLastErrorString(buffer))
+ {
+ if(wnd)wnd->output(KVI_OUT_SSL,__tr2qs("[%s]: [SSL ERROR]: %s"),contextString,buffer.ptr());
+ }
+ }
+ break;
+ }
+ }
+
+ if(!s->initSocket(sock))
+ {
+ delete s;
+ return 0;
+ }
+
+ return s;
+}
+
+KVIRC_API void freeSSL(KviSSL * s)
+{
+ delete s;
+}
+
+};
+#endif
diff --git a/src/kvirc/kernel/kvi_sslmaster.h b/src/kvirc/kernel/kvi_sslmaster.h
new file mode 100644
index 00000000..7518d160
--- /dev/null
+++ b/src/kvirc/kernel/kvi_sslmaster.h
@@ -0,0 +1,47 @@
+#ifndef _KVI_SSLMASTER_H_
+#define _KVI_SSLMASTER_H_
+//
+// File : kvi_sslmaster.h
+// Creation date : Mon Jun 17 2002 20:34:00 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+#include "kvi_settings.h"
+
+#ifdef COMPILE_SSL_SUPPORT
+
+#include "kvi_ssl.h"
+#include "kvi_sockettype.h"
+
+class KviWindow;
+
+namespace KviSSLMaster
+{
+ extern KVIRC_API void printSSLCipherInfo(KviWindow * wnd,const char * description,KviSSLCipherInfo * c);
+ extern KVIRC_API void printSSLCertificate(KviWindow * wnd,const char * description,KviSSLCertificate * c);
+
+ extern KVIRC_API void printSSLConnectionInfo(KviWindow * wnd,KviSSL * s);
+
+ extern KVIRC_API KviSSL * allocSSL(KviWindow * wnd,kvi_socket_t sock,KviSSL::Method m,const char * contextString = 0);
+ extern KVIRC_API void freeSSL(KviSSL * s);
+}
+
+#endif
+
+
+#endif //_KVI_SSLMASTER_H_
diff --git a/src/kvirc/kernel/kvi_texticonmanager.cpp b/src/kvirc/kernel/kvi_texticonmanager.cpp
new file mode 100644
index 00000000..e15496bc
--- /dev/null
+++ b/src/kvirc/kernel/kvi_texticonmanager.cpp
@@ -0,0 +1,254 @@
+//=============================================================================
+//
+// File : kvi_texticonmanager.cpp
+// Creation date : Thu 15 May 2002 12:04:12 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+
+#define __KVIRC__
+
+#define _KVI_TEXTICONMANAGER_CPP_
+
+#include "kvi_iconmanager.h"
+#include "kvi_texticonmanager.h"
+#include "kvi_string.h"
+#include "kvi_pointerlist.h"
+#include "kvi_config.h"
+#include "kvi_app.h"
+#include "kvi_confignames.h"
+
+#include <qpixmap.h>
+#include <qfile.h>
+
+KVIRC_API KviTextIconManager * g_pTextIconManager = 0;
+
+KviTextIcon::KviTextIcon(KviTextIcon* icon)
+{
+ m_iId=icon->id();
+ m_szFilename=icon->m_szFilename;
+}
+
+void KviTextIcon::setId(int id)
+{
+ m_iId=id;
+ m_szFilename=QString::null;
+}
+
+void KviTextIcon::setFilename(QString filename)
+{
+ m_iId=-1;
+ m_szFilename=filename;
+}
+
+QPixmap * KviTextIcon::pixmap()
+{
+ if(m_iId>=0)
+ {
+ return g_pIconManager->getSmallIcon(m_iId);
+ } else {
+ // This is actually wrong (at least for the current implementation).
+ // Users of this class expect the pointer to be permanent while
+ // g_pIconManager returns temporary pointers.
+ // KviIrcView will happily crash dereferencing a hollow pointer sooner or later
+ return g_pIconManager->getPixmap(m_szFilename);
+ }
+}
+
+KviTextIconManager::KviTextIconManager()
+: QObject()
+{
+ m_pTextIconDict = new KviPointerHashTable<QString,KviTextIcon>(47,false);
+ m_pTextIconDict->setAutoDelete(true);
+}
+
+KviTextIconManager::~KviTextIconManager()
+{
+ delete m_pTextIconDict;
+}
+
+void KviTextIconManager::clear()
+{
+ m_pTextIconDict->clear();
+}
+
+void KviTextIconManager::insert(const QString &name,int id)
+{
+ m_pTextIconDict->replace(name,new KviTextIcon(id));
+ emit changed();
+}
+
+void KviTextIconManager::insert(const QString &name,KviTextIcon& icon)
+{
+ m_pTextIconDict->replace(name,new KviTextIcon(&icon));
+ emit changed();
+}
+
+typedef struct _KviTextIconAssocEntry
+{
+ const char * name;
+ int iVal;
+} KviTextIconAssocEntry;
+
+static KviTextIconAssocEntry default_associations[]=
+{
+ { ":)" , KVI_SMALLICON_SMILE },
+ { ":*" , KVI_SMALLICON_KISS },
+ { ":D" , KVI_SMALLICON_BIGGRIN },
+ { ":(" , KVI_SMALLICON_UGLY },
+ { ":/" , KVI_SMALLICON_ANGRY },
+ { ":O" , KVI_SMALLICON_SURPRISED2 },
+ { ":P" , KVI_SMALLICON_TONGUE },
+ { ";)" , KVI_SMALLICON_EYE },
+ { ":°)" , KVI_SMALLICON_TEARSMILE },
+ { ":°" , KVI_SMALLICON_CRY },
+ { ":S" , KVI_SMALLICON_AFRAID },
+ { ":|" , KVI_SMALLICON_DEMORALIZED },
+ { ":P°" , KVI_SMALLICON_SLURP },
+ { 0 , 0 }
+};
+
+void KviTextIconManager::checkDefaultAssociations()
+{
+ for(int i=0;default_associations[i].name;i++)
+ {
+ if(!m_pTextIconDict->find(default_associations[i].name))
+ insert(QString::fromUtf8(default_associations[i].name),default_associations[i].iVal);
+ }
+ emit changed();
+}
+
+// this MUST match the ConfigUpdate entry in the configuration
+// file shipped with KVIrc.
+#define TEXTICONMANAGER_CURRENT_CONFIG_UPDATE 3
+
+void KviTextIconManager::load()
+{
+ KviStr tmps;
+ int upd = 0;
+ if(g_pApp->getReadOnlyConfigPath(tmps,KVI_CONFIGFILE_TEXTICONS))
+ {
+ upd = load(tmps.ptr(),false);
+ }
+
+ if(upd == TEXTICONMANAGER_CURRENT_CONFIG_UPDATE)return;
+
+ // do a merge of the texticons if we have a new config version
+ QString tmp;
+ g_pApp->getGlobalKvircDirectory(tmp,KviApp::Config,KVI_CONFIGFILE_TEXTICONS);
+ if(QFile::exists(tmp))load(tmp,true);
+}
+
+void KviTextIconManager::save()
+{
+ QString tmp;
+ g_pApp->getLocalKvircDirectory(tmp,KviApp::Config,KVI_CONFIGFILE_TEXTICONS);
+ save(tmp);
+}
+
+// returns the config update
+int KviTextIconManager::load(const QString &filename,bool bMerge)
+{
+ if(!bMerge)m_pTextIconDict->clear();
+ KviConfig cfg(filename,KviConfig::Read);
+
+ cfg.setGroup("Manager");
+ int upd = cfg.readIntEntry("ConfigUpdate",0);
+
+ KviConfigGroup * dict = cfg.dict()->find("TextIcons");
+ if(dict)
+ {
+ KviConfigGroupIterator it(*dict);
+
+ KviPointerList<QString> names;
+ names.setAutoDelete(true);
+
+ while(it.current())
+ {
+ names.append(new QString(it.currentKey()));
+ ++it;
+ }
+
+ cfg.setGroup("TextIcons");
+
+ for(QString * s = names.first();s;s = names.next())
+ {
+ int id = cfg.readIntEntry(*s,-1);
+ QString szTmp;
+ QPixmap * pix=0;
+// debug("%s %s %i %i",__FILE__,__FUNCTION__,__LINE__,id);
+ if(id!=-1)
+ pix = g_pIconManager->getSmallIcon(id);
+ else {
+ szTmp=cfg.readEntry(*s);
+ pix=g_pIconManager->getPixmap(szTmp);
+ if(!pix)
+ {
+ id=KVI_SMALLICON_HELP;
+ pix = g_pIconManager->getSmallIcon(id);
+ }
+ }
+ if(pix)
+ {
+ if(bMerge)
+ {
+ if(!m_pTextIconDict->find(*s))
+ if(id!=-1)
+ m_pTextIconDict->replace(*s,new KviTextIcon(id));
+ else
+ m_pTextIconDict->replace(*s,new KviTextIcon(szTmp));
+ } else {
+ if(id!=-1)
+ m_pTextIconDict->replace(*s,new KviTextIcon(id));
+ else
+ m_pTextIconDict->replace(*s,new KviTextIcon(szTmp));
+ }
+ }
+ }
+ }
+
+ checkDefaultAssociations();
+ emit changed();
+
+ return upd;
+}
+
+void KviTextIconManager::save(const QString &filename)
+{
+ KviConfig cfg(filename,KviConfig::Write);
+
+ cfg.setGroup("Manager");
+ cfg.writeEntry("ConfigUpdate",TEXTICONMANAGER_CURRENT_CONFIG_UPDATE);
+
+
+ cfg.setGroup("TextIcons");
+
+ KviPointerHashTableIterator<QString,KviTextIcon> it(*m_pTextIconDict);
+ while(KviTextIcon * i = it.current())
+ {
+ if(i->id()!=-1)
+ cfg.writeEntry(it.currentKey(),i->id());
+ else
+ cfg.writeEntry(it.currentKey(),i->filename());
+ ++it;
+ }
+}
+
+#include "kvi_texticonmanager.moc"
diff --git a/src/kvirc/kernel/kvi_texticonmanager.h b/src/kvirc/kernel/kvi_texticonmanager.h
new file mode 100644
index 00000000..5f76697c
--- /dev/null
+++ b/src/kvirc/kernel/kvi_texticonmanager.h
@@ -0,0 +1,85 @@
+#ifndef _KVI_TEXTICONMANAGER_H_
+#define _KVI_TEXTICONMANAGER_H_
+
+//=============================================================================
+//
+// File : kvi_texticonmanager.h
+// Creation date : Thu 15 May 2002 12:04:12 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#include <qpixmap.h>
+#include "kvi_pointerhashtable.h"
+
+
+class KVIRC_API KviTextIcon
+{
+protected:
+ int m_iId;
+ QString m_szFilename;
+public:
+ KviTextIcon(int id)
+ : m_iId(id) {};
+ KviTextIcon(QString szFile)
+ : m_iId(-1),m_szFilename(szFile) {};
+ KviTextIcon(KviTextIcon* icon);
+ ~KviTextIcon(){};
+public:
+ int id(){ return m_iId; };
+ void setId(int id);
+ void setFilename(QString filename);
+ QString filename(){ return m_szFilename; };
+ QPixmap * pixmap();
+};
+
+class KVIRC_API KviTextIconManager : public QObject
+{
+ friend class KviTextIconWindow;
+ friend class KviTextIconsOptionsWidget;
+ Q_OBJECT
+public:
+ KviTextIconManager();
+ ~KviTextIconManager();
+private:
+ KviPointerHashTable<QString,KviTextIcon> * m_pTextIconDict;
+signals:
+ void changed();
+public:
+ KviPointerHashTable<QString,KviTextIcon> * textIconDict(){ return m_pTextIconDict; };
+ void checkDefaultAssociations();
+ void clear();
+ void insert(const QString &name,int id);
+ void insert(const QString &name,KviTextIcon& icon);
+ KviTextIcon * lookupTextIcon(const QString &name){ return m_pTextIconDict->find(name); };
+ void load();
+ void save();
+protected:
+ void save(const QString &filename);
+ int load(const QString &filename,bool bMerge = false);
+};
+
+#ifndef _KVI_TEXTICONMANAGER_CPP_
+ extern KVIRC_API KviTextIconManager * g_pTextIconManager;
+#endif
+
+
+#endif //_KVI_TEXTICONMANAGER_H_
diff --git a/src/kvirc/kernel/kvi_theme.cpp b/src/kvirc/kernel/kvi_theme.cpp
new file mode 100644
index 00000000..e9ac22ec
--- /dev/null
+++ b/src/kvirc/kernel/kvi_theme.cpp
@@ -0,0 +1,299 @@
+//=============================================================================
+//
+// File : kvi_themeinfo.cpp
+// Creation date : Mon Jan 08 2007 03:23:00 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+#include "kvi_theme.h"
+#include "kvi_fileutils.h"
+#include "kvi_config.h"
+#include "kvi_locale.h"
+#include "kvi_miscutils.h"
+#include "kvi_sourcesdate.h"
+
+#include <qimage.h>
+
+#define KVI_THEME_SMALL_SCREENSHOT_NAME "screenshot_small.png"
+#define KVI_THEME_MEDIUM_SCREENSHOT_NAME "screenshot_medium.png"
+#define KVI_THEME_LARGE_SCREENSHOT_NAME "screenshot.png"
+
+#ifdef COMPILE_USE_QT4
+ #define QIMAGE_SCALE_MIN Qt::KeepAspectRatio
+#else
+ #define QIMAGE_SCALE_MIN QImage::ScaleMin
+#endif
+
+KviThemeInfo::KviThemeInfo()
+: KviHeapObject()
+{
+}
+
+KviThemeInfo::~KviThemeInfo()
+{
+}
+
+
+
+bool KviThemeInfo::load(const QString &szThemeFileName)
+{
+ if(!KviFileUtils::fileExists(szThemeFileName))
+ {
+ m_szLastError = __tr2qs("The theme information file does not exist");
+ return false;
+ }
+
+ KviConfig cfg(szThemeFileName,KviConfig::Read);
+
+ cfg.setGroup(KVI_THEMEINFO_CONFIG_GROUP);
+
+ m_szThemeEngineVersion = cfg.readQStringEntry("ThemeEngineVersion","1.0.0");
+ if(KviMiscUtils::compareVersions(m_szThemeEngineVersion,KVI_CURRENT_THEME_ENGINE_VERSION) < 0)
+ {
+ KviQString::sprintf(m_szLastError,__tr2qs("This KVIrc executable is too old for this theme (minimum theme engine version required is %Q while this theme engine has version %s)"),&m_szThemeEngineVersion,KVI_CURRENT_THEME_ENGINE_VERSION);
+ return false; // incompatible theme engine (will not work)
+ }
+
+ // mandatory fields
+ m_szName = cfg.readQStringEntry("Name","");
+
+ if(m_szName.isEmpty())
+ {
+ m_szLastError = __tr2qs("Theme information file is not valid");
+ return false;
+ }
+
+ // optional fields
+ m_szVersion = cfg.readQStringEntry("Version","");
+ if(m_szVersion.isEmpty())
+ m_szVersion = "?.?.?";
+ m_szAuthor = cfg.readQStringEntry("Author","");
+ QString szUnknown = __tr2qs("Unknown");
+ if(m_szAuthor.isEmpty())
+ m_szAuthor = szUnknown;
+ m_szDescription = cfg.readQStringEntry("Description","");
+ m_szDate = cfg.readQStringEntry("Date","");
+ if(m_szDate.isEmpty())
+ m_szDate = szUnknown;
+ m_szApplication = cfg.readQStringEntry("Application","");
+ if(m_szApplication.isEmpty())
+ m_szApplication = szUnknown;
+
+ return true;
+}
+
+bool KviThemeInfo::save(const QString &szThemeFileName)
+{
+ KviConfig inf(szThemeFileName,KviConfig::Write);
+
+ inf.clear();
+
+ inf.setGroup(KVI_THEMEINFO_CONFIG_GROUP);
+
+ inf.writeEntry("Name",m_szName);
+ inf.writeEntry("Version",m_szVersion);
+ inf.writeEntry("Author",m_szAuthor);
+ inf.writeEntry("Description",m_szDescription);
+ inf.writeEntry("Date",m_szDate);
+ inf.writeEntry("ThemeEngineVersion",KVI_CURRENT_THEME_ENGINE_VERSION);
+ inf.writeEntry("Application","KVIrc " KVI_VERSION "." KVI_SOURCES_DATE);
+
+ return true;
+}
+
+bool KviThemeInfo::loadFromDirectory(const QString &szThemeDirectory,bool bIgnoreThemeData)
+{
+ QString szD = szThemeDirectory;
+ szD.append(KVI_PATH_SEPARATOR_CHAR);
+ szD.append(KVI_THEMEINFO_FILE_NAME);
+
+ if(!load(szD))
+ return false; // loading failed for some reason
+
+ m_szAbsoluteDirectory = szThemeDirectory;
+
+ if(bIgnoreThemeData)
+ return true; // assume success
+
+ // check if themedata file exists
+ szD = szThemeDirectory;
+ szD.append(KVI_PATH_SEPARATOR_CHAR);
+ szD.append(KVI_THEMEDATA_FILE_NAME);
+
+ return KviFileUtils::fileExists(szD);
+}
+
+QString KviThemeInfo::smallScreenshotPath()
+{
+ QString ret;
+ if(!m_szAbsoluteDirectory.isEmpty())
+ {
+ ret = m_szAbsoluteDirectory;
+ KviQString::ensureLastCharIs(ret,KVI_PATH_SEPARATOR_CHAR);
+ ret.append(KVI_THEME_SMALL_SCREENSHOT_NAME);
+ }
+ return ret;
+}
+
+const QPixmap & KviThemeInfo::smallScreenshot()
+{
+ if(!m_pixScreenshotSmall.isNull())return m_pixScreenshotSmall;
+
+ if(!m_szAbsoluteDirectory.isEmpty())
+ {
+ QString szFileName = m_szAbsoluteDirectory;
+ KviQString::ensureLastCharIs(szFileName,KVI_PATH_SEPARATOR_CHAR);
+ szFileName.append(KVI_THEME_SMALL_SCREENSHOT_NAME);
+ QPixmap pix(szFileName);
+ if(!pix.isNull())
+ {
+ m_pixScreenshotSmall = pix;
+ return m_pixScreenshotSmall;
+ }
+ // try to scale it from the large one (and save it by the way)
+ pix = mediumScreenshot();
+ if(pix.isNull())return m_pixScreenshotSmall;
+
+ if(pix.width() > 300 || pix.height() > 225)
+ {
+ QImage sbri = pix.convertToImage();
+ pix.convertFromImage(sbri.smoothScale(300,225,QIMAGE_SCALE_MIN));
+ }
+
+ pix.save(szFileName,"PNG");
+
+ m_pixScreenshotSmall = pix;
+ return m_pixScreenshotSmall;
+ }
+
+ return m_pixScreenshotSmall;
+}
+
+const QPixmap & KviThemeInfo::mediumScreenshot()
+{
+ if(!m_pixScreenshotMedium.isNull())return m_pixScreenshotMedium;
+
+ if(!m_szAbsoluteDirectory.isEmpty())
+ {
+ QString szFileName = m_szAbsoluteDirectory;
+ KviQString::ensureLastCharIs(szFileName,KVI_PATH_SEPARATOR_CHAR);
+ szFileName.append(KVI_THEME_MEDIUM_SCREENSHOT_NAME);
+ QPixmap pix(szFileName);
+ if(!pix.isNull())
+ {
+ m_pixScreenshotMedium = pix;
+ return m_pixScreenshotMedium;
+ }
+ // try to scale it from the large one (and save it by the way)
+ pix = largeScreenshot();
+ if(pix.isNull())return m_pixScreenshotMedium;
+
+ if(pix.width() > 600 || pix.height() > 450)
+ {
+ QImage sbri = pix.convertToImage();
+ pix.convertFromImage(sbri.smoothScale(600,450,QIMAGE_SCALE_MIN));
+ }
+
+ pix.save(szFileName,"PNG");
+
+ m_pixScreenshotMedium = pix;
+ return m_pixScreenshotMedium;
+ }
+
+ return m_pixScreenshotMedium;
+}
+
+const QPixmap & KviThemeInfo::largeScreenshot()
+{
+ if(!m_pixScreenshotLarge.isNull())return m_pixScreenshotLarge;
+
+ if(!m_szAbsoluteDirectory.isEmpty())
+ {
+ QString szFileName = m_szAbsoluteDirectory;
+ KviQString::ensureLastCharIs(szFileName,KVI_PATH_SEPARATOR_CHAR);
+ szFileName.append(KVI_THEME_LARGE_SCREENSHOT_NAME);
+ QPixmap pix(szFileName);
+ if(pix.isNull())return m_pixScreenshotLarge;
+ m_pixScreenshotLarge = pix;
+ }
+ return m_pixScreenshotLarge;
+}
+
+
+namespace KviTheme
+{
+ bool saveScreenshots(KviThemeInfo &options,const QString &szOriginalScreenshotPath)
+ {
+ QImage pix(szOriginalScreenshotPath);
+ if(pix.isNull())
+ {
+ options.setLastError(__tr2qs("Failed to load the specified screenshot image"));
+ return false;
+ }
+
+ QPixmap out;
+
+ QString szScreenshotFileName = options.absoluteDirectory();
+ if(szScreenshotFileName.isEmpty())
+ {
+ options.setLastError(__tr2qs("Invalid option"));
+ return false;
+ }
+
+ KviQString::ensureLastCharIs(szScreenshotFileName,KVI_PATH_SEPARATOR_CHAR);
+ szScreenshotFileName.append(KVI_THEME_LARGE_SCREENSHOT_NAME);
+ if(!pix.save(szScreenshotFileName,"PNG"))
+ {
+ options.setLastError(__tr2qs("Failed to save the screenshot image"));
+ return false;
+ }
+
+ if(pix.width() > 600 || pix.height() > 450)
+ out.convertFromImage(pix.smoothScale(600,450,QIMAGE_SCALE_MIN));
+ else
+ out.convertFromImage(pix);
+
+ szScreenshotFileName = options.absoluteDirectory();
+ KviQString::ensureLastCharIs(szScreenshotFileName,KVI_PATH_SEPARATOR_CHAR);
+ szScreenshotFileName.append(KVI_THEME_MEDIUM_SCREENSHOT_NAME);
+ if(!out.save(szScreenshotFileName,"PNG"))
+ {
+ options.setLastError(__tr2qs("Failed to save the screenshot image"));
+ return false;
+ }
+
+ if(pix.width() > 300 || pix.height() > 225)
+ out.convertFromImage(pix.smoothScale(300,225,QIMAGE_SCALE_MIN));
+ else
+ out.convertFromImage(pix);
+
+ szScreenshotFileName = options.absoluteDirectory();
+ KviQString::ensureLastCharIs(szScreenshotFileName,KVI_PATH_SEPARATOR_CHAR);
+ szScreenshotFileName.append(KVI_THEME_SMALL_SCREENSHOT_NAME);
+ if(!out.save(szScreenshotFileName,"PNG"))
+ {
+ options.setLastError(__tr2qs("Failed to save the screenshot image"));
+ return false;
+ }
+
+ return true;
+ }
+};
diff --git a/src/kvirc/kernel/kvi_theme.h b/src/kvirc/kernel/kvi_theme.h
new file mode 100644
index 00000000..2545e51e
--- /dev/null
+++ b/src/kvirc/kernel/kvi_theme.h
@@ -0,0 +1,171 @@
+#ifndef _KVI_THEME_H_
+#define _KVI_THEME_H_
+
+//=============================================================================
+//
+// File : kvi_theme.h
+// Creation date : Mon Jan 08 2007 03:23:00 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_heapobject.h"
+
+#include "kvi_fileextensions.h"
+
+#include <qpixmap.h>
+
+#define KVI_THEMEINFO_FILE_NAME "themeinfo." KVI_FILEEXTENSION_CONFIG
+#define KVI_THEMEDATA_FILE_NAME "themedata." KVI_FILEEXTENSION_CONFIG
+#define KVI_THEMEINFO_CONFIG_GROUP "ThemeInfo"
+#define KVI_THEMEDATA_CONFIG_GROUP "ThemeData"
+
+///
+/// The current theme engine version: bump up if you make INCOMPATIBLE
+/// changes in the method of saving the theme.
+///
+#define KVI_CURRENT_THEME_ENGINE_VERSION "1.0.0"
+
+///
+/// \class KviThemeInfo
+///
+/// \brief A set of informations about a KVIrc theme
+///
+/// This object contains a set of informations about
+/// a theme that can be read and stored to a standard
+/// KVIrc configuration file (which is usually named
+/// themeinfo.kvc but this is not strictly necessary).
+///
+class KVIRC_API KviThemeInfo : public KviHeapObject
+{
+public:
+ KviThemeInfo();
+ ~KviThemeInfo();
+protected:
+ QString m_szName; //< name of the theme
+ QString m_szVersion; //< version of the theme
+ QString m_szSubdirectory; //< subdirectory of $LOCALKVIRCDIR/themes where the theme is saved to (not always used)
+ QString m_szAbsoluteDirectory; //< absolute directory where the theme should be saved to (or is loaded from)
+ QString m_szAuthor; //< author of the theme
+ QString m_szDescription; //< description of the theme
+ QString m_szDate; //< theme creation date
+ QString m_szApplication; //< theme creation (KVIrc) version
+ QString m_szThemeEngineVersion; //< the theme engine version that saved this theme
+
+ QString m_szLastError; //< reported when some function fails
+
+ QPixmap m_pixScreenshotLarge; //< the large screenshot pixmap
+ QPixmap m_pixScreenshotMedium; //< the medium screenshot pixmap
+ QPixmap m_pixScreenshotSmall; //< the small screenshot pixmap
+public:
+ ///
+ /// load data from a specified theme config file
+ ///
+ bool load(const QString &szThemeFileName);
+ ///
+ /// save the currently defined theme configuration in the specified file
+ ///
+ bool save(const QString &szThemeFileName);
+
+ const QString & lastError(){ return m_szLastError; };
+ void setLastError(const QString &szLastError){ m_szLastError = szLastError; };
+ const QString & name(){ return m_szName; };
+ void setName(const QString &szName){ m_szName = szName; };
+ const QString & version(){ return m_szVersion; };
+ void setVersion(const QString &szVersion){ m_szVersion = szVersion; };
+ const QString & subdirectory(){ return m_szSubdirectory; };
+ void setSubdirectory(const QString &szSubdirectory){ m_szSubdirectory = szSubdirectory; };
+ const QString & absoluteDirectory(){ return m_szAbsoluteDirectory; };
+ void setAbsoluteDirectory(const QString &szAbsoluteDirectory){ m_szAbsoluteDirectory = szAbsoluteDirectory; }
+ const QString & author(){ return m_szAuthor; };
+ void setAuthor(const QString &szAuthor){ m_szAuthor = szAuthor; };
+ const QString & description(){ return m_szDescription; };
+ void setDescription(const QString &szDescription){ m_szDescription = szDescription; };
+ const QString & date(){ return m_szDate; };
+ void setDate(const QString &szDate){ m_szDate = szDate; };
+ const QString & application(){ return m_szApplication; };
+ void setApplication(const QString &szApplication){ m_szApplication = szApplication; };
+ const QString & themeEngineVersion(){ return m_szThemeEngineVersion; };
+ void setThemeEngineVersion(const QString &szThemeEngineVersion){ m_szThemeEngineVersion = szThemeEngineVersion; };
+
+ ///
+ /// Attempt to load a themeinfo.kvc file present in the specified directory.
+ /// This function will fail if the directory contains a valid themeinfo.kvc
+ /// file but no themedata.kvc file unless bIgnoreThemeData is set to true
+ ///
+ bool loadFromDirectory(const QString &szThemeDirectory,bool bIgnoreThemeData = false);
+
+ ///
+ /// Attempt to load the theme screenshot from THEMEDIR/screenshot_*.png
+ /// This function will work only if the absoluteDirectory() of the theme
+ /// has been set, otherwise the returned pixmap will be null.
+ ///
+ const QPixmap & smallScreenshot();
+ ///
+ /// Attempt to load the theme screenshot from THEMEDIR/screenshot_*.png
+ /// This function will work only if the absoluteDirectory() of the theme
+ /// has been set, otherwise the returned pixmap will be null.
+ ///
+ const QPixmap & mediumScreenshot();
+ ///
+ /// Attempt to load the theme screenshot from THEMEDIR/screenshot_*.png
+ /// This function will work only if the absoluteDirectory() of the theme
+ /// has been set, otherwise the returned pixmap will be null.
+ ///
+ const QPixmap & largeScreenshot();
+ ///
+ /// Attempt to load the theme screenshot from THEMEDIR/screenshot_*.png
+ /// This function will work only if the absoluteDirectory() of the theme
+ /// has been set, otherwise the returned pixmap will be null.
+ ///
+ QString smallScreenshotPath();
+};
+
+namespace KviTheme
+{
+ ///
+ /// Attempt to load (apply) a theme in the specified directory
+ /// Will return true on success and false on failure.
+ /// On success this function will return the theme informations in the buffer.
+ /// On failure this function will also set buffer.lastError() to a meaningful value
+ /// Note that for convenience this function is implemented in kvi_options.cpp
+ ///
+ bool KVIRC_API load(const QString &szThemeDir,KviThemeInfo &buffer);
+ ///
+ /// Save a theme given the specified options.
+ /// Will return true on success and false on failure.
+ /// On failure this function will also set options.lastError() to a meaningful value
+ /// This function requires both absoluteDirectory() and subdirectory() to be
+ /// set to the right values. In theory this function could save a theme
+ /// in a directory different than $KVIRC_LOCAL_DIR/themes/subdirectory
+ /// but this feature is actually unused.
+ /// Note that for convenience this function is implemented in kvi_options.cpp
+ ///
+ bool KVIRC_API save(KviThemeInfo &options);
+ ///
+ /// Save the theme screenshots in the given EXISTING directory and given
+ /// an existing screenshot on disk (usually in the tmp directory).
+ ///
+ bool KVIRC_API saveScreenshots(KviThemeInfo &options,const QString &szOriginalScreenshotPath);
+};
+
+
+#endif //_KVI_THEME_H_
diff --git a/src/kvirc/kernel/kvi_useraction.cpp b/src/kvirc/kernel/kvi_useraction.cpp
new file mode 100644
index 00000000..15a02bcf
--- /dev/null
+++ b/src/kvirc/kernel/kvi_useraction.cpp
@@ -0,0 +1,46 @@
+//=============================================================================
+//
+// File : kvi_userlistview.cpp
+// Creation date : Tue Mar 18 2003 13:36:12 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_useraction.h"
+
+static int useraction_table[KVI_NUM_USERACTION_TYPES]=
+{
+ 25, // ACTION (typically human)
+ 25, // PRIVMSG
+ 25, // NOTICE
+ 20, // TOPIC
+ 5, // KICK
+ -5, // NICK
+ -20, // CHANMODE
+ -25, // JOIN
+ -25 // PART (this works only for channels and not for single users on channels)
+};
+
+int kvi_getUserActionTemperature(unsigned int uIdx)
+{
+ return useraction_table[uIdx];
+}
+
diff --git a/src/kvirc/kernel/kvi_useraction.h b/src/kvirc/kernel/kvi_useraction.h
new file mode 100644
index 00000000..648264e5
--- /dev/null
+++ b/src/kvirc/kernel/kvi_useraction.h
@@ -0,0 +1,83 @@
+#ifndef _KVI_USERACTION_H_
+#define _KVI_USERACTION_H_
+
+//=============================================================================
+//
+// File : kvi_userlistview.h
+// Creation date : Tue Mar 18 2003 13:36:12 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+// This file defines the user action "temperatures".
+// The more "hot" is an action, the more humanity is in it
+
+#define KVI_USERACTION_ACTION 0
+#define KVI_USERACTION_PRIVMSG 1
+#define KVI_USERACTION_NOTICE 2
+#define KVI_USERACTION_TOPIC 3
+#define KVI_USERACTION_KICK 4
+#define KVI_USERACTION_NICK 5
+#define KVI_USERACTION_CHANMODE 6
+#define KVI_USERACTION_JOIN 7
+#define KVI_USERACTION_PART 8
+
+#define KVI_NUM_USERACTION_TYPES 9
+
+
+extern KVIRC_API int kvi_getUserActionTemperature(unsigned int uIdx);
+
+
+//
+// ACTION 30
+// NOTICE 25
+// PRIVMSG 25
+// TOPIC 20
+// KICK 10
+// OP 5
+// VOICE 5
+// DEOP -5
+// DEVOICE -5
+// UNBAN -15
+// BAN -20
+// CHANMODE -25
+// NICK -30
+// JOIN -30
+//
+
+// These are the temperature levels for a single user on a channel
+
+// Maximum : can't go above this
+#define KVI_MAX_TEMPERATURE 150
+// Hot : human
+#define KVI_HOT_TEMPERATURE 100
+// Half hot : signs of humanity
+#define KVI_HALF_HOT_TEMPERATURE 40
+// Mid : uncertain
+#define KVI_MID_TEMPERATURE 0
+// Half cold : automa ?
+#define KVI_HALF_COLD_TEMPERATURE -40
+// Cold : bot
+#define KVI_COLD_TEMPERATURE -100
+// Minimum : can't drop below this
+#define KVI_MIN_TEMPERATURE -150
+
+#endif // _KVI_USERACTION_H_
diff --git a/src/kvirc/kernel/kvi_userinput.cpp b/src/kvirc/kernel/kvi_userinput.cpp
new file mode 100644
index 00000000..134d4256
--- /dev/null
+++ b/src/kvirc/kernel/kvi_userinput.cpp
@@ -0,0 +1,148 @@
+//=============================================================================
+//
+// File : kvi_userinput.cpp
+// Created on Sun 25 Sep 2005 05:27:57 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_userinput.h"
+#include "kvi_kvs_variantlist.h"
+#include "kvi_console.h"
+#include "kvi_kvs_script.h"
+#include "kvi_locale.h"
+#include "kvi_ircconnection.h"
+#include "kvi_ircconnectionuserinfo.h"
+#include "kvi_out.h"
+#include "kvi_options.h"
+#include "kvi_kvs_eventtriggers.h"
+
+namespace KviUserInput
+{
+ bool parse(QString &szData,KviWindow * pWindow,const QString &szContext,bool bUserFriendlyCommandline)
+ {
+ const QChar * b = KviQString::nullTerminatedArray(szData);
+ const QChar * c = b;
+ if(!c)return true; // empty
+
+ while(c->isSpace())c++;
+ if(!c->unicode())return true; // empty
+
+ if(c->unicode() == '\\')
+ {
+ c++;
+ if(c->unicode() != '/')c--;
+ } else {
+ if(c->unicode() == '/')
+ {
+ c++;
+ if(c->unicode() != '/')
+ {
+ szData.remove(0,c-b);
+ return parseCommand(szData,pWindow,szContext,bUserFriendlyCommandline);
+ } else {
+ // C++ comment, probably
+ c--;
+ }
+ }
+ }
+
+ if(KVS_TRIGGER_EVENT_1_HALTED(KviEvent_OnTextInput,pWindow,szData))
+ return true; // halted
+
+ if(c != b)szData.remove(0,c-b);
+ parseNonCommand(szData,pWindow);
+ return true;
+ }
+
+ bool parseCommand(const QString &szData,KviWindow * pWindow,const QString &szContext,bool bUserFriendlyCommandline)
+ {
+ if(bUserFriendlyCommandline)
+ {
+ static QString szUserFriendlyCommandlineContext(__tr2qs("commandline::userfriendly"));
+ QString szCmd=szData;
+ // escape any -$;\%(
+ szCmd.replace("\\","\\\\");
+ szCmd.replace("\"","\\\"");
+ szCmd.replace("$","\\$");
+ szCmd.replace("%","\\%");
+ szCmd.replace("(","\\(");
+ szCmd.replace(";","\\;");
+ szCmd.replace("-","\\-");
+ szCmd.replace("+","\\+");
+ KviKvsScript kvs(szContext.isEmpty() ? szUserFriendlyCommandlineContext : szContext,szCmd);
+ return (kvs.run(pWindow,0,0) != KviKvsScript::Error);
+ } else {
+ static QString szCommandlineContext(__tr2qs("commandline::kvs"));
+ KviKvsScript kvs(szContext.isEmpty() ? szCommandlineContext : szContext,szData);
+ return (kvs.run(pWindow,0,0/*,KviKvsScript::AssumeLocals*/) != KviKvsScript::Error);
+ }
+ }
+
+ void parseNonCommand(QString &szData,KviWindow * pWindow)
+ {
+ const QChar * aux = KviQString::nullTerminatedArray(szData);
+ const QChar * beg = aux;
+ if(!beg)return; // empty
+
+ while(aux->unicode())
+ {
+ while(aux->unicode() && (aux->unicode() != '\n'))aux++;
+ QString buf(beg,aux-beg);
+ if(aux->unicode() == '\n')aux++;
+ beg = aux;
+
+ if(buf.isEmpty())buf = " "; // avoid "No text to send" (d3vah)
+
+ switch(pWindow->type())
+ {
+ case KVI_WINDOW_TYPE_CONSOLE:
+ if(pWindow->connection())
+ {
+ KviQCString data = pWindow->connection()->encodeText(buf);
+ if(((KviConsole *)pWindow)->connection()->sendData(data.data()))
+ {
+ pWindow->output(KVI_OUT_RAW,"[RAW]: %Q",&buf);
+ return;
+ }
+ }
+ pWindow->output(KVI_OUT_PARSERERROR,__tr2qs("You are not connected to a server"));
+ break;
+ case KVI_WINDOW_TYPE_CHANNEL:
+ case KVI_WINDOW_TYPE_QUERY:
+ if(pWindow->connection())
+ {
+ if(KVI_OPTION_BOOL(KviOption_boolExitAwayOnInput))
+ if(pWindow->connection()->userInfo()->isAway())
+ parseCommand("back",pWindow->console());
+ }
+ pWindow->ownMessage(buf);
+ break;
+ case KVI_WINDOW_TYPE_DCCCHAT:
+ pWindow->ownMessage(buf);
+ break;
+ default:
+ // FIXME: Should pass the message somewhere ?.. a KviWindow handler ?
+ break;
+ }
+ }
+ }
+};
diff --git a/src/kvirc/kernel/kvi_userinput.h b/src/kvirc/kernel/kvi_userinput.h
new file mode 100644
index 00000000..08dac61e
--- /dev/null
+++ b/src/kvirc/kernel/kvi_userinput.h
@@ -0,0 +1,43 @@
+#ifndef _KVI_USERINPUT_H_
+#define _KVI_USERINPUT_H_
+//=============================================================================
+//
+// File : kvi_userinput.h
+// Created on Sun 25 Sep 2005 05:27:57 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_window.h"
+
+namespace KviUserInput
+{
+ // WARNING: May destroy szData
+ // returns false if szData is a command and it fails to run
+ KVIRC_API bool parse(QString &szData,KviWindow * pWindow,const QString &szContext = KviQString::empty,bool bUserFriendlyCommandline = false);
+
+ KVIRC_API bool parseCommand(const QString &szData,KviWindow * pWindow,const QString &szContext = KviQString::empty,bool bUserFriendlyCommandline = false);
+ //bool parseCommandWithSingleArgument(const QString &szData,KviWindow * pWindow,const QString &szContext = KviQString::empty);
+ KVIRC_API void parseNonCommand(QString &szData,KviWindow * pWindow);
+};
+
+
+#endif //!_KVI_USERINPUT_H_
diff --git a/src/kvirc/kernel/moc_kvi_action.cpp b/src/kvirc/kernel/moc_kvi_action.cpp
new file mode 100644
index 00000000..673a52d5
--- /dev/null
+++ b/src/kvirc/kernel/moc_kvi_action.cpp
@@ -0,0 +1,137 @@
+/****************************************************************************
+** KviAction meta object code from reading C++ file 'kvi_action.h'
+**
+** Created: Mon Feb 25 00:11:38 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_action.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviAction::className() const
+{
+ return "KviAction";
+}
+
+QMetaObject *KviAction::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviAction( "KviAction", &KviAction::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviAction::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviAction", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviAction::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviAction", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviAction::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = QObject::staticMetaObject();
+ static const QUMethod slot_0 = {"widgetDestroyed", 0, 0 };
+ static const QUMethod slot_1 = {"reloadImages", 0, 0 };
+ static const QUMethod slot_2 = {"activeContextChanged", 0, 0 };
+ static const QUMethod slot_3 = {"activeContextStateChanged", 0, 0 };
+ static const QUMethod slot_4 = {"activeWindowChanged", 0, 0 };
+ static const QUParameter param_slot_5[] = {
+ { "bSelectedNow", &static_QUType_bool, 0, QUParameter::In }
+ };
+ static const QUMethod slot_5 = {"activeWindowSelectionStateChanged", 1, param_slot_5 };
+ static const QUMethod slot_6 = {"activate", 0, 0 };
+ static const QMetaData slot_tbl[] = {
+ { "widgetDestroyed()", &slot_0, QMetaData::Protected },
+ { "reloadImages()", &slot_1, QMetaData::Protected },
+ { "activeContextChanged()", &slot_2, QMetaData::Protected },
+ { "activeContextStateChanged()", &slot_3, QMetaData::Protected },
+ { "activeWindowChanged()", &slot_4, QMetaData::Protected },
+ { "activeWindowSelectionStateChanged(bool)", &slot_5, QMetaData::Protected },
+ { "activate()", &slot_6, QMetaData::Public }
+ };
+ static const QUMethod signal_0 = {"activated", 0, 0 };
+ static const QMetaData signal_tbl[] = {
+ { "activated()", &signal_0, QMetaData::Public }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviAction", parentObject,
+ slot_tbl, 7,
+ signal_tbl, 1,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviAction.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviAction::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviAction" ) )
+ return this;
+ return QObject::qt_cast( clname );
+}
+
+// SIGNAL activated
+void KviAction::activated()
+{
+ activate_signal( staticMetaObject()->signalOffset() + 0 );
+}
+
+bool KviAction::qt_invoke( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->slotOffset() ) {
+ case 0: widgetDestroyed(); break;
+ case 1: reloadImages(); break;
+ case 2: activeContextChanged(); break;
+ case 3: activeContextStateChanged(); break;
+ case 4: activeWindowChanged(); break;
+ case 5: activeWindowSelectionStateChanged((bool)static_QUType_bool.get(_o+1)); break;
+ case 6: activate(); break;
+ default:
+ return QObject::qt_invoke( _id, _o );
+ }
+ return TRUE;
+}
+
+bool KviAction::qt_emit( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->signalOffset() ) {
+ case 0: activated(); break;
+ default:
+ return QObject::qt_emit(_id,_o);
+ }
+ return TRUE;
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviAction::qt_property( int id, int f, QVariant* v)
+{
+ return QObject::qt_property( id, f, v);
+}
+
+bool KviAction::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvirc/kernel/moc_kvi_actionmanager.cpp b/src/kvirc/kernel/moc_kvi_actionmanager.cpp
new file mode 100644
index 00000000..9a8f581a
--- /dev/null
+++ b/src/kvirc/kernel/moc_kvi_actionmanager.cpp
@@ -0,0 +1,143 @@
+/****************************************************************************
+** KviActionManager meta object code from reading C++ file 'kvi_actionmanager.h'
+**
+** Created: Mon Feb 25 00:11:40 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_actionmanager.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviActionManager::className() const
+{
+ return "KviActionManager";
+}
+
+QMetaObject *KviActionManager::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviActionManager( "KviActionManager", &KviActionManager::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviActionManager::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviActionManager", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviActionManager::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviActionManager", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviActionManager::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = QObject::staticMetaObject();
+ static const QUMethod slot_0 = {"actionDestroyed", 0, 0 };
+ static const QMetaData slot_tbl[] = {
+ { "actionDestroyed()", &slot_0, QMetaData::Protected }
+ };
+ static const QUMethod signal_0 = {"beginCustomizeToolBars", 0, 0 };
+ static const QUMethod signal_1 = {"endCustomizeToolBars", 0, 0 };
+ static const QUMethod signal_2 = {"currentToolBarChanged", 0, 0 };
+ static const QUMethod signal_3 = {"removeActionsHintRequest", 0, 0 };
+ static const QMetaData signal_tbl[] = {
+ { "beginCustomizeToolBars()", &signal_0, QMetaData::Protected },
+ { "endCustomizeToolBars()", &signal_1, QMetaData::Protected },
+ { "currentToolBarChanged()", &signal_2, QMetaData::Protected },
+ { "removeActionsHintRequest()", &signal_3, QMetaData::Protected }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviActionManager", parentObject,
+ slot_tbl, 1,
+ signal_tbl, 4,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviActionManager.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviActionManager::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviActionManager" ) )
+ return this;
+ return QObject::qt_cast( clname );
+}
+
+// SIGNAL beginCustomizeToolBars
+void KviActionManager::beginCustomizeToolBars()
+{
+ activate_signal( staticMetaObject()->signalOffset() + 0 );
+}
+
+// SIGNAL endCustomizeToolBars
+void KviActionManager::endCustomizeToolBars()
+{
+ activate_signal( staticMetaObject()->signalOffset() + 1 );
+}
+
+// SIGNAL currentToolBarChanged
+void KviActionManager::currentToolBarChanged()
+{
+ activate_signal( staticMetaObject()->signalOffset() + 2 );
+}
+
+// SIGNAL removeActionsHintRequest
+void KviActionManager::removeActionsHintRequest()
+{
+ activate_signal( staticMetaObject()->signalOffset() + 3 );
+}
+
+bool KviActionManager::qt_invoke( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->slotOffset() ) {
+ case 0: actionDestroyed(); break;
+ default:
+ return QObject::qt_invoke( _id, _o );
+ }
+ return TRUE;
+}
+
+bool KviActionManager::qt_emit( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->signalOffset() ) {
+ case 0: beginCustomizeToolBars(); break;
+ case 1: endCustomizeToolBars(); break;
+ case 2: currentToolBarChanged(); break;
+ case 3: removeActionsHintRequest(); break;
+ default:
+ return QObject::qt_emit(_id,_o);
+ }
+ return TRUE;
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviActionManager::qt_property( int id, int f, QVariant* v)
+{
+ return QObject::qt_property( id, f, v);
+}
+
+bool KviActionManager::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvirc/kernel/moc_kvi_coreactions.cpp b/src/kvirc/kernel/moc_kvi_coreactions.cpp
new file mode 100644
index 00000000..73f14280
--- /dev/null
+++ b/src/kvirc/kernel/moc_kvi_coreactions.cpp
@@ -0,0 +1,927 @@
+/****************************************************************************
+** KviConnectAction meta object code from reading C++ file 'kvi_coreactions.h'
+**
+** Created: Mon Feb 25 00:11:42 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_coreactions.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviConnectAction::className() const
+{
+ return "KviConnectAction";
+}
+
+QMetaObject *KviConnectAction::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviConnectAction( "KviConnectAction", &KviConnectAction::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviConnectAction::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviConnectAction", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviConnectAction::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviConnectAction", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviConnectAction::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = KviAction::staticMetaObject();
+ metaObj = QMetaObject::new_metaobject(
+ "KviConnectAction", parentObject,
+ 0, 0,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviConnectAction.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviConnectAction::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviConnectAction" ) )
+ return this;
+ return KviAction::qt_cast( clname );
+}
+
+bool KviConnectAction::qt_invoke( int _id, QUObject* _o )
+{
+ return KviAction::qt_invoke(_id,_o);
+}
+
+bool KviConnectAction::qt_emit( int _id, QUObject* _o )
+{
+ return KviAction::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviConnectAction::qt_property( int id, int f, QVariant* v)
+{
+ return KviAction::qt_property( id, f, v);
+}
+
+bool KviConnectAction::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
+
+
+const char *KviSeparatorAction::className() const
+{
+ return "KviSeparatorAction";
+}
+
+QMetaObject *KviSeparatorAction::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviSeparatorAction( "KviSeparatorAction", &KviSeparatorAction::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviSeparatorAction::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviSeparatorAction", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviSeparatorAction::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviSeparatorAction", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviSeparatorAction::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = KviAction::staticMetaObject();
+ metaObj = QMetaObject::new_metaobject(
+ "KviSeparatorAction", parentObject,
+ 0, 0,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviSeparatorAction.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviSeparatorAction::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviSeparatorAction" ) )
+ return this;
+ return KviAction::qt_cast( clname );
+}
+
+bool KviSeparatorAction::qt_invoke( int _id, QUObject* _o )
+{
+ return KviAction::qt_invoke(_id,_o);
+}
+
+bool KviSeparatorAction::qt_emit( int _id, QUObject* _o )
+{
+ return KviAction::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviSeparatorAction::qt_property( int id, int f, QVariant* v)
+{
+ return KviAction::qt_property( id, f, v);
+}
+
+bool KviSeparatorAction::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
+
+
+const char *KviSubmenuAction::className() const
+{
+ return "KviSubmenuAction";
+}
+
+QMetaObject *KviSubmenuAction::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviSubmenuAction( "KviSubmenuAction", &KviSubmenuAction::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviSubmenuAction::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviSubmenuAction", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviSubmenuAction::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviSubmenuAction", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviSubmenuAction::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = KviKvsAction::staticMetaObject();
+ static const QUMethod slot_0 = {"popupAboutToShow", 0, 0 };
+ static const QUParameter param_slot_1[] = {
+ { "id", &static_QUType_int, 0, QUParameter::In }
+ };
+ static const QUMethod slot_1 = {"popupActivated", 1, param_slot_1 };
+ static const QMetaData slot_tbl[] = {
+ { "popupAboutToShow()", &slot_0, QMetaData::Protected },
+ { "popupActivated(int)", &slot_1, QMetaData::Protected }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviSubmenuAction", parentObject,
+ slot_tbl, 2,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviSubmenuAction.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviSubmenuAction::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviSubmenuAction" ) )
+ return this;
+ return KviKvsAction::qt_cast( clname );
+}
+
+bool KviSubmenuAction::qt_invoke( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->slotOffset() ) {
+ case 0: popupAboutToShow(); break;
+ case 1: popupActivated((int)static_QUType_int.get(_o+1)); break;
+ default:
+ return KviKvsAction::qt_invoke( _id, _o );
+ }
+ return TRUE;
+}
+
+bool KviSubmenuAction::qt_emit( int _id, QUObject* _o )
+{
+ return KviKvsAction::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviSubmenuAction::qt_property( int id, int f, QVariant* v)
+{
+ return KviKvsAction::qt_property( id, f, v);
+}
+
+bool KviSubmenuAction::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
+
+
+const char *KviJoinChannelAction::className() const
+{
+ return "KviJoinChannelAction";
+}
+
+QMetaObject *KviJoinChannelAction::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviJoinChannelAction( "KviJoinChannelAction", &KviJoinChannelAction::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviJoinChannelAction::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviJoinChannelAction", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviJoinChannelAction::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviJoinChannelAction", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviJoinChannelAction::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = KviSubmenuAction::staticMetaObject();
+ static const QUMethod slot_0 = {"popupAboutToShow", 0, 0 };
+ static const QUParameter param_slot_1[] = {
+ { 0, &static_QUType_int, 0, QUParameter::In }
+ };
+ static const QUMethod slot_1 = {"popupActivated", 1, param_slot_1 };
+ static const QMetaData slot_tbl[] = {
+ { "popupAboutToShow()", &slot_0, QMetaData::Protected },
+ { "popupActivated(int)", &slot_1, QMetaData::Protected }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviJoinChannelAction", parentObject,
+ slot_tbl, 2,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviJoinChannelAction.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviJoinChannelAction::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviJoinChannelAction" ) )
+ return this;
+ return KviSubmenuAction::qt_cast( clname );
+}
+
+bool KviJoinChannelAction::qt_invoke( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->slotOffset() ) {
+ case 0: popupAboutToShow(); break;
+ case 1: popupActivated((int)static_QUType_int.get(_o+1)); break;
+ default:
+ return KviSubmenuAction::qt_invoke( _id, _o );
+ }
+ return TRUE;
+}
+
+bool KviJoinChannelAction::qt_emit( int _id, QUObject* _o )
+{
+ return KviSubmenuAction::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviJoinChannelAction::qt_property( int id, int f, QVariant* v)
+{
+ return KviSubmenuAction::qt_property( id, f, v);
+}
+
+bool KviJoinChannelAction::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
+
+
+const char *KviChangeNickAction::className() const
+{
+ return "KviChangeNickAction";
+}
+
+QMetaObject *KviChangeNickAction::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviChangeNickAction( "KviChangeNickAction", &KviChangeNickAction::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviChangeNickAction::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviChangeNickAction", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviChangeNickAction::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviChangeNickAction", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviChangeNickAction::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = KviSubmenuAction::staticMetaObject();
+ static const QUMethod slot_0 = {"popupAboutToShow", 0, 0 };
+ static const QUParameter param_slot_1[] = {
+ { 0, &static_QUType_int, 0, QUParameter::In }
+ };
+ static const QUMethod slot_1 = {"popupActivated", 1, param_slot_1 };
+ static const QMetaData slot_tbl[] = {
+ { "popupAboutToShow()", &slot_0, QMetaData::Protected },
+ { "popupActivated(int)", &slot_1, QMetaData::Protected }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviChangeNickAction", parentObject,
+ slot_tbl, 2,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviChangeNickAction.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviChangeNickAction::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviChangeNickAction" ) )
+ return this;
+ return KviSubmenuAction::qt_cast( clname );
+}
+
+bool KviChangeNickAction::qt_invoke( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->slotOffset() ) {
+ case 0: popupAboutToShow(); break;
+ case 1: popupActivated((int)static_QUType_int.get(_o+1)); break;
+ default:
+ return KviSubmenuAction::qt_invoke( _id, _o );
+ }
+ return TRUE;
+}
+
+bool KviChangeNickAction::qt_emit( int _id, QUObject* _o )
+{
+ return KviSubmenuAction::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviChangeNickAction::qt_property( int id, int f, QVariant* v)
+{
+ return KviSubmenuAction::qt_property( id, f, v);
+}
+
+bool KviChangeNickAction::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
+
+
+const char *KviConnectToServerAction::className() const
+{
+ return "KviConnectToServerAction";
+}
+
+QMetaObject *KviConnectToServerAction::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviConnectToServerAction( "KviConnectToServerAction", &KviConnectToServerAction::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviConnectToServerAction::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviConnectToServerAction", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviConnectToServerAction::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviConnectToServerAction", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviConnectToServerAction::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = KviSubmenuAction::staticMetaObject();
+ static const QUMethod slot_0 = {"popupAboutToShow", 0, 0 };
+ static const QUParameter param_slot_1[] = {
+ { 0, &static_QUType_int, 0, QUParameter::In }
+ };
+ static const QUMethod slot_1 = {"popupActivated", 1, param_slot_1 };
+ static const QMetaData slot_tbl[] = {
+ { "popupAboutToShow()", &slot_0, QMetaData::Protected },
+ { "popupActivated(int)", &slot_1, QMetaData::Protected }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviConnectToServerAction", parentObject,
+ slot_tbl, 2,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviConnectToServerAction.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviConnectToServerAction::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviConnectToServerAction" ) )
+ return this;
+ return KviSubmenuAction::qt_cast( clname );
+}
+
+bool KviConnectToServerAction::qt_invoke( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->slotOffset() ) {
+ case 0: popupAboutToShow(); break;
+ case 1: popupActivated((int)static_QUType_int.get(_o+1)); break;
+ default:
+ return KviSubmenuAction::qt_invoke( _id, _o );
+ }
+ return TRUE;
+}
+
+bool KviConnectToServerAction::qt_emit( int _id, QUObject* _o )
+{
+ return KviSubmenuAction::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviConnectToServerAction::qt_property( int id, int f, QVariant* v)
+{
+ return KviSubmenuAction::qt_property( id, f, v);
+}
+
+bool KviConnectToServerAction::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
+
+
+const char *KviChangeUserModeAction::className() const
+{
+ return "KviChangeUserModeAction";
+}
+
+QMetaObject *KviChangeUserModeAction::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviChangeUserModeAction( "KviChangeUserModeAction", &KviChangeUserModeAction::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviChangeUserModeAction::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviChangeUserModeAction", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviChangeUserModeAction::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviChangeUserModeAction", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviChangeUserModeAction::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = KviSubmenuAction::staticMetaObject();
+ static const QUMethod slot_0 = {"popupAboutToShow", 0, 0 };
+ static const QUParameter param_slot_1[] = {
+ { 0, &static_QUType_int, 0, QUParameter::In }
+ };
+ static const QUMethod slot_1 = {"popupActivated", 1, param_slot_1 };
+ static const QMetaData slot_tbl[] = {
+ { "popupAboutToShow()", &slot_0, QMetaData::Protected },
+ { "popupActivated(int)", &slot_1, QMetaData::Protected }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviChangeUserModeAction", parentObject,
+ slot_tbl, 2,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviChangeUserModeAction.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviChangeUserModeAction::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviChangeUserModeAction" ) )
+ return this;
+ return KviSubmenuAction::qt_cast( clname );
+}
+
+bool KviChangeUserModeAction::qt_invoke( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->slotOffset() ) {
+ case 0: popupAboutToShow(); break;
+ case 1: popupActivated((int)static_QUType_int.get(_o+1)); break;
+ default:
+ return KviSubmenuAction::qt_invoke( _id, _o );
+ }
+ return TRUE;
+}
+
+bool KviChangeUserModeAction::qt_emit( int _id, QUObject* _o )
+{
+ return KviSubmenuAction::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviChangeUserModeAction::qt_property( int id, int f, QVariant* v)
+{
+ return KviSubmenuAction::qt_property( id, f, v);
+}
+
+bool KviChangeUserModeAction::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
+
+
+const char *KviIrcToolsAction::className() const
+{
+ return "KviIrcToolsAction";
+}
+
+QMetaObject *KviIrcToolsAction::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviIrcToolsAction( "KviIrcToolsAction", &KviIrcToolsAction::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviIrcToolsAction::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviIrcToolsAction", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviIrcToolsAction::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviIrcToolsAction", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviIrcToolsAction::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = KviSubmenuAction::staticMetaObject();
+ static const QUMethod slot_0 = {"popupAboutToShow", 0, 0 };
+ static const QUParameter param_slot_1[] = {
+ { 0, &static_QUType_int, 0, QUParameter::In }
+ };
+ static const QUMethod slot_1 = {"popupActivated", 1, param_slot_1 };
+ static const QMetaData slot_tbl[] = {
+ { "popupAboutToShow()", &slot_0, QMetaData::Protected },
+ { "popupActivated(int)", &slot_1, QMetaData::Protected }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviIrcToolsAction", parentObject,
+ slot_tbl, 2,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviIrcToolsAction.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviIrcToolsAction::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviIrcToolsAction" ) )
+ return this;
+ return KviSubmenuAction::qt_cast( clname );
+}
+
+bool KviIrcToolsAction::qt_invoke( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->slotOffset() ) {
+ case 0: popupAboutToShow(); break;
+ case 1: popupActivated((int)static_QUType_int.get(_o+1)); break;
+ default:
+ return KviSubmenuAction::qt_invoke( _id, _o );
+ }
+ return TRUE;
+}
+
+bool KviIrcToolsAction::qt_emit( int _id, QUObject* _o )
+{
+ return KviSubmenuAction::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviIrcToolsAction::qt_property( int id, int f, QVariant* v)
+{
+ return KviSubmenuAction::qt_property( id, f, v);
+}
+
+bool KviIrcToolsAction::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
+
+
+const char *KviIrcOperationsAction::className() const
+{
+ return "KviIrcOperationsAction";
+}
+
+QMetaObject *KviIrcOperationsAction::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviIrcOperationsAction( "KviIrcOperationsAction", &KviIrcOperationsAction::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviIrcOperationsAction::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviIrcOperationsAction", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviIrcOperationsAction::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviIrcOperationsAction", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviIrcOperationsAction::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = KviSubmenuAction::staticMetaObject();
+ static const QUMethod slot_0 = {"popupAboutToShow", 0, 0 };
+ static const QUParameter param_slot_1[] = {
+ { 0, &static_QUType_int, 0, QUParameter::In }
+ };
+ static const QUMethod slot_1 = {"popupActivated", 1, param_slot_1 };
+ static const QMetaData slot_tbl[] = {
+ { "popupAboutToShow()", &slot_0, QMetaData::Protected },
+ { "popupActivated(int)", &slot_1, QMetaData::Protected }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviIrcOperationsAction", parentObject,
+ slot_tbl, 2,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviIrcOperationsAction.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviIrcOperationsAction::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviIrcOperationsAction" ) )
+ return this;
+ return KviSubmenuAction::qt_cast( clname );
+}
+
+bool KviIrcOperationsAction::qt_invoke( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->slotOffset() ) {
+ case 0: popupAboutToShow(); break;
+ case 1: popupActivated((int)static_QUType_int.get(_o+1)); break;
+ default:
+ return KviSubmenuAction::qt_invoke( _id, _o );
+ }
+ return TRUE;
+}
+
+bool KviIrcOperationsAction::qt_emit( int _id, QUObject* _o )
+{
+ return KviSubmenuAction::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviIrcOperationsAction::qt_property( int id, int f, QVariant* v)
+{
+ return KviSubmenuAction::qt_property( id, f, v);
+}
+
+bool KviIrcOperationsAction::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
+
+
+const char *KviIrcContextDisplayAction::className() const
+{
+ return "KviIrcContextDisplayAction";
+}
+
+QMetaObject *KviIrcContextDisplayAction::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviIrcContextDisplayAction( "KviIrcContextDisplayAction", &KviIrcContextDisplayAction::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviIrcContextDisplayAction::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviIrcContextDisplayAction", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviIrcContextDisplayAction::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviIrcContextDisplayAction", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviIrcContextDisplayAction::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = KviAction::staticMetaObject();
+ metaObj = QMetaObject::new_metaobject(
+ "KviIrcContextDisplayAction", parentObject,
+ 0, 0,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviIrcContextDisplayAction.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviIrcContextDisplayAction::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviIrcContextDisplayAction" ) )
+ return this;
+ return KviAction::qt_cast( clname );
+}
+
+bool KviIrcContextDisplayAction::qt_invoke( int _id, QUObject* _o )
+{
+ return KviAction::qt_invoke(_id,_o);
+}
+
+bool KviIrcContextDisplayAction::qt_emit( int _id, QUObject* _o )
+{
+ return KviAction::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviIrcContextDisplayAction::qt_property( int id, int f, QVariant* v)
+{
+ return KviAction::qt_property( id, f, v);
+}
+
+bool KviIrcContextDisplayAction::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
+
+
+const char *KviGoAwayAction::className() const
+{
+ return "KviGoAwayAction";
+}
+
+QMetaObject *KviGoAwayAction::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviGoAwayAction( "KviGoAwayAction", &KviGoAwayAction::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviGoAwayAction::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviGoAwayAction", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviGoAwayAction::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviGoAwayAction", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviGoAwayAction::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = KviKvsAction::staticMetaObject();
+ metaObj = QMetaObject::new_metaobject(
+ "KviGoAwayAction", parentObject,
+ 0, 0,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviGoAwayAction.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviGoAwayAction::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviGoAwayAction" ) )
+ return this;
+ return KviKvsAction::qt_cast( clname );
+}
+
+bool KviGoAwayAction::qt_invoke( int _id, QUObject* _o )
+{
+ return KviKvsAction::qt_invoke(_id,_o);
+}
+
+bool KviGoAwayAction::qt_emit( int _id, QUObject* _o )
+{
+ return KviKvsAction::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviGoAwayAction::qt_property( int id, int f, QVariant* v)
+{
+ return KviKvsAction::qt_property( id, f, v);
+}
+
+bool KviGoAwayAction::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvirc/kernel/moc_kvi_filetransfer.cpp b/src/kvirc/kernel/moc_kvi_filetransfer.cpp
new file mode 100644
index 00000000..b395379f
--- /dev/null
+++ b/src/kvirc/kernel/moc_kvi_filetransfer.cpp
@@ -0,0 +1,212 @@
+/****************************************************************************
+** KviFileTransferManager meta object code from reading C++ file 'kvi_filetransfer.h'
+**
+** Created: Mon Feb 25 00:11:45 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_filetransfer.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviFileTransferManager::className() const
+{
+ return "KviFileTransferManager";
+}
+
+QMetaObject *KviFileTransferManager::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviFileTransferManager( "KviFileTransferManager", &KviFileTransferManager::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviFileTransferManager::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviFileTransferManager", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviFileTransferManager::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviFileTransferManager", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviFileTransferManager::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = QObject::staticMetaObject();
+ static const QUParameter param_signal_0[] = {
+ { "t", &static_QUType_ptr, "KviFileTransfer", QUParameter::In }
+ };
+ static const QUMethod signal_0 = {"transferRegistered", 1, param_signal_0 };
+ static const QUParameter param_signal_1[] = {
+ { "t", &static_QUType_ptr, "KviFileTransfer", QUParameter::In }
+ };
+ static const QUMethod signal_1 = {"transferUnregistering", 1, param_signal_1 };
+ static const QMetaData signal_tbl[] = {
+ { "transferRegistered(KviFileTransfer*)", &signal_0, QMetaData::Public },
+ { "transferUnregistering(KviFileTransfer*)", &signal_1, QMetaData::Public }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviFileTransferManager", parentObject,
+ 0, 0,
+ signal_tbl, 2,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviFileTransferManager.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviFileTransferManager::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviFileTransferManager" ) )
+ return this;
+ return QObject::qt_cast( clname );
+}
+
+#include <qobjectdefs.h>
+#include <qsignalslotimp.h>
+
+// SIGNAL transferRegistered
+void KviFileTransferManager::transferRegistered( KviFileTransfer* t0 )
+{
+ if ( signalsBlocked() )
+ return;
+ QConnectionList *clist = receivers( staticMetaObject()->signalOffset() + 0 );
+ if ( !clist )
+ return;
+ QUObject o[2];
+ static_QUType_ptr.set(o+1,t0);
+ activate_signal( clist, o );
+}
+
+// SIGNAL transferUnregistering
+void KviFileTransferManager::transferUnregistering( KviFileTransfer* t0 )
+{
+ if ( signalsBlocked() )
+ return;
+ QConnectionList *clist = receivers( staticMetaObject()->signalOffset() + 1 );
+ if ( !clist )
+ return;
+ QUObject o[2];
+ static_QUType_ptr.set(o+1,t0);
+ activate_signal( clist, o );
+}
+
+bool KviFileTransferManager::qt_invoke( int _id, QUObject* _o )
+{
+ return QObject::qt_invoke(_id,_o);
+}
+
+bool KviFileTransferManager::qt_emit( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->signalOffset() ) {
+ case 0: transferRegistered((KviFileTransfer*)static_QUType_ptr.get(_o+1)); break;
+ case 1: transferUnregistering((KviFileTransfer*)static_QUType_ptr.get(_o+1)); break;
+ default:
+ return QObject::qt_emit(_id,_o);
+ }
+ return TRUE;
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviFileTransferManager::qt_property( int id, int f, QVariant* v)
+{
+ return QObject::qt_property( id, f, v);
+}
+
+bool KviFileTransferManager::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
+
+
+const char *KviFileTransfer::className() const
+{
+ return "KviFileTransfer";
+}
+
+QMetaObject *KviFileTransfer::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviFileTransfer( "KviFileTransfer", &KviFileTransfer::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviFileTransfer::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviFileTransfer", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviFileTransfer::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviFileTransfer", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviFileTransfer::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = QObject::staticMetaObject();
+ metaObj = QMetaObject::new_metaobject(
+ "KviFileTransfer", parentObject,
+ 0, 0,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviFileTransfer.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviFileTransfer::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviFileTransfer" ) )
+ return this;
+ return QObject::qt_cast( clname );
+}
+
+bool KviFileTransfer::qt_invoke( int _id, QUObject* _o )
+{
+ return QObject::qt_invoke(_id,_o);
+}
+
+bool KviFileTransfer::qt_emit( int _id, QUObject* _o )
+{
+ return QObject::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviFileTransfer::qt_property( int id, int f, QVariant* v)
+{
+ return QObject::qt_property( id, f, v);
+}
+
+bool KviFileTransfer::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvirc/kernel/moc_kvi_ircconnection.cpp b/src/kvirc/kernel/moc_kvi_ircconnection.cpp
new file mode 100644
index 00000000..dbe025a5
--- /dev/null
+++ b/src/kvirc/kernel/moc_kvi_ircconnection.cpp
@@ -0,0 +1,202 @@
+/****************************************************************************
+** KviIrcConnection meta object code from reading C++ file 'kvi_ircconnection.h'
+**
+** Created: Mon Feb 25 00:11:48 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_ircconnection.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviIrcConnection::className() const
+{
+ return "KviIrcConnection";
+}
+
+QMetaObject *KviIrcConnection::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviIrcConnection( "KviIrcConnection", &KviIrcConnection::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviIrcConnection::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviIrcConnection", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviIrcConnection::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviIrcConnection", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviIrcConnection::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = QObject::staticMetaObject();
+ static const QUMethod slot_0 = {"partAllChannels", 0, 0 };
+ static const QUMethod slot_1 = {"unhighlightAllChannels", 0, 0 };
+ static const QUMethod slot_2 = {"unhighlightAllQueries", 0, 0 };
+ static const QUMethod slot_3 = {"restartNotifyList", 0, 0 };
+ static const QUMethod slot_4 = {"closeAllQueries", 0, 0 };
+ static const QUParameter param_slot_5[] = {
+ { "pDns", &static_QUType_ptr, "KviDns", QUParameter::In }
+ };
+ static const QUMethod slot_5 = {"hostNameLookupTerminated", 1, param_slot_5 };
+ static const QMetaData slot_tbl[] = {
+ { "partAllChannels()", &slot_0, QMetaData::Public },
+ { "unhighlightAllChannels()", &slot_1, QMetaData::Public },
+ { "unhighlightAllQueries()", &slot_2, QMetaData::Public },
+ { "restartNotifyList()", &slot_3, QMetaData::Public },
+ { "closeAllQueries()", &slot_4, QMetaData::Public },
+ { "hostNameLookupTerminated(KviDns*)", &slot_5, QMetaData::Private }
+ };
+ static const QUMethod signal_0 = {"awayStateChanged", 0, 0 };
+ static const QUMethod signal_1 = {"userModeChanged", 0, 0 };
+ static const QUMethod signal_2 = {"nickNameChanged", 0, 0 };
+ static const QUParameter param_signal_3[] = {
+ { 0, &static_QUType_ptr, "KviChannel", QUParameter::In }
+ };
+ static const QUMethod signal_3 = {"channelRegistered", 1, param_signal_3 };
+ static const QUParameter param_signal_4[] = {
+ { 0, &static_QUType_ptr, "KviChannel", QUParameter::In }
+ };
+ static const QUMethod signal_4 = {"channelUnregistered", 1, param_signal_4 };
+ static const QUMethod signal_5 = {"chanListChanged", 0, 0 };
+ static const QMetaData signal_tbl[] = {
+ { "awayStateChanged()", &signal_0, QMetaData::Public },
+ { "userModeChanged()", &signal_1, QMetaData::Public },
+ { "nickNameChanged()", &signal_2, QMetaData::Public },
+ { "channelRegistered(KviChannel*)", &signal_3, QMetaData::Public },
+ { "channelUnregistered(KviChannel*)", &signal_4, QMetaData::Public },
+ { "chanListChanged()", &signal_5, QMetaData::Public }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviIrcConnection", parentObject,
+ slot_tbl, 6,
+ signal_tbl, 6,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviIrcConnection.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviIrcConnection::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviIrcConnection" ) )
+ return this;
+ return QObject::qt_cast( clname );
+}
+
+// SIGNAL awayStateChanged
+void KviIrcConnection::awayStateChanged()
+{
+ activate_signal( staticMetaObject()->signalOffset() + 0 );
+}
+
+// SIGNAL userModeChanged
+void KviIrcConnection::userModeChanged()
+{
+ activate_signal( staticMetaObject()->signalOffset() + 1 );
+}
+
+// SIGNAL nickNameChanged
+void KviIrcConnection::nickNameChanged()
+{
+ activate_signal( staticMetaObject()->signalOffset() + 2 );
+}
+
+#include <qobjectdefs.h>
+#include <qsignalslotimp.h>
+
+// SIGNAL channelRegistered
+void KviIrcConnection::channelRegistered( KviChannel* t0 )
+{
+ if ( signalsBlocked() )
+ return;
+ QConnectionList *clist = receivers( staticMetaObject()->signalOffset() + 3 );
+ if ( !clist )
+ return;
+ QUObject o[2];
+ static_QUType_ptr.set(o+1,t0);
+ activate_signal( clist, o );
+}
+
+// SIGNAL channelUnregistered
+void KviIrcConnection::channelUnregistered( KviChannel* t0 )
+{
+ if ( signalsBlocked() )
+ return;
+ QConnectionList *clist = receivers( staticMetaObject()->signalOffset() + 4 );
+ if ( !clist )
+ return;
+ QUObject o[2];
+ static_QUType_ptr.set(o+1,t0);
+ activate_signal( clist, o );
+}
+
+// SIGNAL chanListChanged
+void KviIrcConnection::chanListChanged()
+{
+ activate_signal( staticMetaObject()->signalOffset() + 5 );
+}
+
+bool KviIrcConnection::qt_invoke( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->slotOffset() ) {
+ case 0: partAllChannels(); break;
+ case 1: unhighlightAllChannels(); break;
+ case 2: unhighlightAllQueries(); break;
+ case 3: restartNotifyList(); break;
+ case 4: closeAllQueries(); break;
+ case 5: hostNameLookupTerminated((KviDns*)static_QUType_ptr.get(_o+1)); break;
+ default:
+ return QObject::qt_invoke( _id, _o );
+ }
+ return TRUE;
+}
+
+bool KviIrcConnection::qt_emit( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->signalOffset() ) {
+ case 0: awayStateChanged(); break;
+ case 1: userModeChanged(); break;
+ case 2: nickNameChanged(); break;
+ case 3: channelRegistered((KviChannel*)static_QUType_ptr.get(_o+1)); break;
+ case 4: channelUnregistered((KviChannel*)static_QUType_ptr.get(_o+1)); break;
+ case 5: chanListChanged(); break;
+ default:
+ return QObject::qt_emit(_id,_o);
+ }
+ return TRUE;
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviIrcConnection::qt_property( int id, int f, QVariant* v)
+{
+ return QObject::qt_property( id, f, v);
+}
+
+bool KviIrcConnection::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvirc/kernel/moc_kvi_ircconnectiontargetresolver.cpp b/src/kvirc/kernel/moc_kvi_ircconnectiontargetresolver.cpp
new file mode 100644
index 00000000..89aa1bc6
--- /dev/null
+++ b/src/kvirc/kernel/moc_kvi_ircconnectiontargetresolver.cpp
@@ -0,0 +1,128 @@
+/****************************************************************************
+** KviIrcConnectionTargetResolver meta object code from reading C++ file 'kvi_ircconnectiontargetresolver.h'
+**
+** Created: Mon Feb 25 00:11:55 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_ircconnectiontargetresolver.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviIrcConnectionTargetResolver::className() const
+{
+ return "KviIrcConnectionTargetResolver";
+}
+
+QMetaObject *KviIrcConnectionTargetResolver::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviIrcConnectionTargetResolver( "KviIrcConnectionTargetResolver", &KviIrcConnectionTargetResolver::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviIrcConnectionTargetResolver::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviIrcConnectionTargetResolver", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviIrcConnectionTargetResolver::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviIrcConnectionTargetResolver", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviIrcConnectionTargetResolver::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = QObject::staticMetaObject();
+ static const QUMethod slot_0 = {"asyncStartResolve", 0, 0 };
+ static const QUParameter param_slot_1[] = {
+ { 0, &static_QUType_ptr, "KviDns", QUParameter::In }
+ };
+ static const QUMethod slot_1 = {"serverLookupTerminated", 1, param_slot_1 };
+ static const QUParameter param_slot_2[] = {
+ { 0, &static_QUType_ptr, "KviDns", QUParameter::In }
+ };
+ static const QUMethod slot_2 = {"proxyLookupTerminated", 1, param_slot_2 };
+ static const QMetaData slot_tbl[] = {
+ { "asyncStartResolve()", &slot_0, QMetaData::Protected },
+ { "serverLookupTerminated(KviDns*)", &slot_1, QMetaData::Protected },
+ { "proxyLookupTerminated(KviDns*)", &slot_2, QMetaData::Protected }
+ };
+ static const QUMethod signal_0 = {"terminated", 0, 0 };
+ static const QMetaData signal_tbl[] = {
+ { "terminated()", &signal_0, QMetaData::Private }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviIrcConnectionTargetResolver", parentObject,
+ slot_tbl, 3,
+ signal_tbl, 1,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviIrcConnectionTargetResolver.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviIrcConnectionTargetResolver::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviIrcConnectionTargetResolver" ) )
+ return this;
+ return QObject::qt_cast( clname );
+}
+
+// SIGNAL terminated
+void KviIrcConnectionTargetResolver::terminated()
+{
+ activate_signal( staticMetaObject()->signalOffset() + 0 );
+}
+
+bool KviIrcConnectionTargetResolver::qt_invoke( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->slotOffset() ) {
+ case 0: asyncStartResolve(); break;
+ case 1: serverLookupTerminated((KviDns*)static_QUType_ptr.get(_o+1)); break;
+ case 2: proxyLookupTerminated((KviDns*)static_QUType_ptr.get(_o+1)); break;
+ default:
+ return QObject::qt_invoke( _id, _o );
+ }
+ return TRUE;
+}
+
+bool KviIrcConnectionTargetResolver::qt_emit( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->signalOffset() ) {
+ case 0: terminated(); break;
+ default:
+ return QObject::qt_emit(_id,_o);
+ }
+ return TRUE;
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviIrcConnectionTargetResolver::qt_property( int id, int f, QVariant* v)
+{
+ return QObject::qt_property( id, f, v);
+}
+
+bool KviIrcConnectionTargetResolver::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvirc/kernel/moc_kvi_irccontext.cpp b/src/kvirc/kernel/moc_kvi_irccontext.cpp
new file mode 100644
index 00000000..2319d11f
--- /dev/null
+++ b/src/kvirc/kernel/moc_kvi_irccontext.cpp
@@ -0,0 +1,119 @@
+/****************************************************************************
+** KviIrcContext meta object code from reading C++ file 'kvi_irccontext.h'
+**
+** Created: Mon Feb 25 00:11:50 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_irccontext.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviIrcContext::className() const
+{
+ return "KviIrcContext";
+}
+
+QMetaObject *KviIrcContext::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviIrcContext( "KviIrcContext", &KviIrcContext::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviIrcContext::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviIrcContext", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviIrcContext::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviIrcContext", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviIrcContext::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = QObject::staticMetaObject();
+ static const QUMethod slot_0 = {"asynchronousConnect", 0, 0 };
+ static const QUMethod slot_1 = {"unhighlightAllWindows", 0, 0 };
+ static const QMetaData slot_tbl[] = {
+ { "asynchronousConnect()", &slot_0, QMetaData::Protected },
+ { "unhighlightAllWindows()", &slot_1, QMetaData::Protected }
+ };
+ static const QUMethod signal_0 = {"stateChanged", 0, 0 };
+ static const QMetaData signal_tbl[] = {
+ { "stateChanged()", &signal_0, QMetaData::Protected }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviIrcContext", parentObject,
+ slot_tbl, 2,
+ signal_tbl, 1,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviIrcContext.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviIrcContext::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviIrcContext" ) )
+ return this;
+ return QObject::qt_cast( clname );
+}
+
+// SIGNAL stateChanged
+void KviIrcContext::stateChanged()
+{
+ activate_signal( staticMetaObject()->signalOffset() + 0 );
+}
+
+bool KviIrcContext::qt_invoke( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->slotOffset() ) {
+ case 0: asynchronousConnect(); break;
+ case 1: unhighlightAllWindows(); break;
+ default:
+ return QObject::qt_invoke( _id, _o );
+ }
+ return TRUE;
+}
+
+bool KviIrcContext::qt_emit( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->signalOffset() ) {
+ case 0: stateChanged(); break;
+ default:
+ return QObject::qt_emit(_id,_o);
+ }
+ return TRUE;
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviIrcContext::qt_property( int id, int f, QVariant* v)
+{
+ return QObject::qt_property( id, f, v);
+}
+
+bool KviIrcContext::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvirc/kernel/moc_kvi_irclink.cpp b/src/kvirc/kernel/moc_kvi_irclink.cpp
new file mode 100644
index 00000000..1bf804e4
--- /dev/null
+++ b/src/kvirc/kernel/moc_kvi_irclink.cpp
@@ -0,0 +1,119 @@
+/****************************************************************************
+** KviIrcLink meta object code from reading C++ file 'kvi_irclink.h'
+**
+** Created: Mon Feb 25 00:11:51 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_irclink.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviIrcLink::className() const
+{
+ return "KviIrcLink";
+}
+
+QMetaObject *KviIrcLink::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviIrcLink( "KviIrcLink", &KviIrcLink::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviIrcLink::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviIrcLink", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviIrcLink::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviIrcLink", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviIrcLink::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = QObject::staticMetaObject();
+ static const QUMethod slot_0 = {"linkFilterDestroyed", 0, 0 };
+ static const QUMethod slot_1 = {"resolverTerminated", 0, 0 };
+ static const QMetaData slot_tbl[] = {
+ { "linkFilterDestroyed()", &slot_0, QMetaData::Protected },
+ { "resolverTerminated()", &slot_1, QMetaData::Private }
+ };
+ static const QUMethod signal_0 = {"connectionFailed", 0, 0 };
+ static const QMetaData signal_tbl[] = {
+ { "connectionFailed()", &signal_0, QMetaData::Private }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviIrcLink", parentObject,
+ slot_tbl, 2,
+ signal_tbl, 1,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviIrcLink.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviIrcLink::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviIrcLink" ) )
+ return this;
+ return QObject::qt_cast( clname );
+}
+
+// SIGNAL connectionFailed
+void KviIrcLink::connectionFailed()
+{
+ activate_signal( staticMetaObject()->signalOffset() + 0 );
+}
+
+bool KviIrcLink::qt_invoke( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->slotOffset() ) {
+ case 0: linkFilterDestroyed(); break;
+ case 1: resolverTerminated(); break;
+ default:
+ return QObject::qt_invoke( _id, _o );
+ }
+ return TRUE;
+}
+
+bool KviIrcLink::qt_emit( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->signalOffset() ) {
+ case 0: connectionFailed(); break;
+ default:
+ return QObject::qt_emit(_id,_o);
+ }
+ return TRUE;
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviIrcLink::qt_property( int id, int f, QVariant* v)
+{
+ return QObject::qt_property( id, f, v);
+}
+
+bool KviIrcLink::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvirc/kernel/moc_kvi_ircsocket.cpp b/src/kvirc/kernel/moc_kvi_ircsocket.cpp
new file mode 100644
index 00000000..b4863f82
--- /dev/null
+++ b/src/kvirc/kernel/moc_kvi_ircsocket.cpp
@@ -0,0 +1,134 @@
+/****************************************************************************
+** KviIrcSocket meta object code from reading C++ file 'kvi_ircsocket.h'
+**
+** Created: Mon Feb 25 00:11:53 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_ircsocket.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviIrcSocket::className() const
+{
+ return "KviIrcSocket";
+}
+
+QMetaObject *KviIrcSocket::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviIrcSocket( "KviIrcSocket", &KviIrcSocket::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviIrcSocket::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviIrcSocket", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviIrcSocket::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviIrcSocket", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviIrcSocket::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = QObject::staticMetaObject();
+ static const QUMethod slot_0 = {"connectionTimedOut", 0, 0 };
+ static const QUParameter param_slot_1[] = {
+ { 0, &static_QUType_int, 0, QUParameter::In }
+ };
+ static const QUMethod slot_1 = {"writeNotifierFired", 1, param_slot_1 };
+ static const QUParameter param_slot_2[] = {
+ { 0, &static_QUType_int, 0, QUParameter::In }
+ };
+ static const QUMethod slot_2 = {"readData", 1, param_slot_2 };
+ static const QUParameter param_slot_3[] = {
+ { 0, &static_QUType_int, 0, QUParameter::In }
+ };
+ static const QUMethod slot_3 = {"readProxyData", 1, param_slot_3 };
+ static const QUParameter param_slot_4[] = {
+ { 0, &static_QUType_int, 0, QUParameter::In }
+ };
+ static const QUMethod slot_4 = {"readHttpProxyErrorData", 1, param_slot_4 };
+ static const QUMethod slot_5 = {"flushSendQueue", 0, 0 };
+ static const QUParameter param_slot_6[] = {
+ { 0, &static_QUType_int, 0, QUParameter::In }
+ };
+ static const QUMethod slot_6 = {"doSSLHandshake", 1, param_slot_6 };
+ static const QMetaData slot_tbl[] = {
+ { "connectionTimedOut()", &slot_0, QMetaData::Protected },
+ { "writeNotifierFired(int)", &slot_1, QMetaData::Protected },
+ { "readData(int)", &slot_2, QMetaData::Protected },
+ { "readProxyData(int)", &slot_3, QMetaData::Protected },
+ { "readHttpProxyErrorData(int)", &slot_4, QMetaData::Protected },
+ { "flushSendQueue()", &slot_5, QMetaData::Protected },
+ { "doSSLHandshake(int)", &slot_6, QMetaData::Protected }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviIrcSocket", parentObject,
+ slot_tbl, 7,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviIrcSocket.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviIrcSocket::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviIrcSocket" ) )
+ return this;
+ return QObject::qt_cast( clname );
+}
+
+bool KviIrcSocket::qt_invoke( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->slotOffset() ) {
+ case 0: connectionTimedOut(); break;
+ case 1: writeNotifierFired((int)static_QUType_int.get(_o+1)); break;
+ case 2: readData((int)static_QUType_int.get(_o+1)); break;
+ case 3: readProxyData((int)static_QUType_int.get(_o+1)); break;
+ case 4: readHttpProxyErrorData((int)static_QUType_int.get(_o+1)); break;
+ case 5: flushSendQueue(); break;
+ case 6: doSSLHandshake((int)static_QUType_int.get(_o+1)); break;
+ default:
+ return QObject::qt_invoke( _id, _o );
+ }
+ return TRUE;
+}
+
+bool KviIrcSocket::qt_emit( int _id, QUObject* _o )
+{
+ return QObject::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviIrcSocket::qt_property( int id, int f, QVariant* v)
+{
+ return QObject::qt_property( id, f, v);
+}
+
+bool KviIrcSocket::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvirc/kvs/Makefile.am b/src/kvirc/kvs/Makefile.am
new file mode 100644
index 00000000..c84487eb
--- /dev/null
+++ b/src/kvirc/kvs/Makefile.am
@@ -0,0 +1,5 @@
+###############################################################################
+# KVirc IRC client Makefile - 16.12.98 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+EXTRA_DIST = *.cpp *.h
diff --git a/src/kvirc/kvs/kvi_kvs.cpp b/src/kvirc/kvs/kvi_kvs.cpp
new file mode 100644
index 00000000..9c36a34c
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs.cpp
@@ -0,0 +1,144 @@
+//=============================================================================
+//
+// File : kvi_kvs.cpp
+// Creation date : Wed 1 Oct 2003 01.38 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs.h"
+#include "kvi_kvs_kernel.h"
+#include "kvi_kvs_aliasmanager.h"
+#include "kvi_kvs_dnsmanager.h"
+#include "kvi_kvs_timermanager.h"
+#include "kvi_kvs_popupmanager.h"
+#include "kvi_kvs_eventmanager.h"
+#include "kvi_kvs_scriptaddonmanager.h"
+#include "kvi_kvs_object_controller.h"
+
+namespace KviKvs
+{
+ void init()
+ {
+ KviKvsKernel::init();
+ KviKvsAliasManager::init();
+ KviKvsPopupManager::init();
+ KviKvsEventManager::init();
+ // FIXME: Could we delay the init of these objects ?
+ // It could be delayed to the first *::instance() call
+ KviKvsScriptAddonManager::init();
+ KviKvsTimerManager::init();
+ KviKvsDnsManager::init();
+ }
+
+ void done()
+ {
+ //KviKvsScriptManager::done();
+ KviKvsEventManager::done();
+ KviKvsPopupManager::done();
+ KviKvsAliasManager::done();
+ KviKvsScriptAddonManager::done();
+ KviKvsTimerManager::done();
+ KviKvsDnsManager::done();
+ KviKvsKernel::done();
+ }
+
+ void loadPopups(const QString &szFileName)
+ {
+ KviKvsPopupManager::instance()->load(szFileName);
+ }
+
+ void savePopups(const QString &szFileName)
+ {
+ KviKvsPopupManager::instance()->save(szFileName);
+ }
+
+ void clearPopups()
+ {
+ KviKvsPopupManager::instance()->clear();
+ }
+
+ void loadAliases(const QString &szFileName)
+ {
+ KviKvsAliasManager::instance()->load(szFileName);
+ }
+
+ void saveAliases(const QString &szFileName)
+ {
+ KviKvsAliasManager::instance()->save(szFileName);
+ }
+
+ void clearAliases()
+ {
+ KviKvsAliasManager::instance()->clear();
+ }
+
+ void loadAppEvents(const QString &szFileName)
+ {
+ KviKvsEventManager::instance()->loadAppEvents(szFileName);
+ }
+
+ void saveAppEvents(const QString &szFileName)
+ {
+ KviKvsEventManager::instance()->saveAppEvents(szFileName);
+ }
+
+ void clearAppEvents()
+ {
+ KviKvsEventManager::instance()->removeAllScriptAppHandlers();
+ }
+
+ void loadRawEvents(const QString &szFileName)
+ {
+ KviKvsEventManager::instance()->loadRawEvents(szFileName);
+ }
+
+ void saveRawEvents(const QString &szFileName)
+ {
+ KviKvsEventManager::instance()->saveRawEvents(szFileName);
+ }
+
+ void clearRawEvents()
+ {
+ KviKvsEventManager::instance()->removeAllScriptRawHandlers();
+ }
+
+ void loadScriptAddons(const QString &szFileName)
+ {
+ KviKvsScriptAddonManager::instance()->load(szFileName);
+ }
+
+ void saveScriptAddons(const QString &szFileName)
+ {
+ KviKvsScriptAddonManager::instance()->save(szFileName);
+ }
+
+ void clearScriptAddons()
+ {
+ KviKvsScriptAddonManager::instance()->clear();
+ }
+
+ void flushUserClasses()
+ {
+ KviKvsKernel::instance()->objectController()->flushUserClasses();
+ }
+};
+
diff --git a/src/kvirc/kvs/kvi_kvs.h b/src/kvirc/kvs/kvi_kvs.h
new file mode 100644
index 00000000..bb92a300
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs.h
@@ -0,0 +1,59 @@
+#ifndef _KVI_KVS_H_
+#define _KVI_KVS_H_
+//=============================================================================
+//
+// File : kvi_kvs.h
+// Creation date : Wed 1 Oct 2003 01.37 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+// this header contains ALL the stuff that the user should see
+#include "kvi_kvs_script.h"
+
+namespace KviKvs
+{
+ void init(); // this never fails
+ void done(); // this never fails
+
+ void loadAliases(const QString &szFileName);
+ void saveAliases(const QString &szFileName);
+ void clearAliases();
+
+ void loadPopups(const QString &szFileName);
+ void savePopups(const QString &szFileName);
+ void clearPopups();
+
+ void loadAppEvents(const QString &szFileName);
+ void saveAppEvents(const QString &szFileName);
+ void clearAppEvents();
+
+ void loadRawEvents(const QString &szFileName);
+ void saveRawEvents(const QString &szFileName);
+ void clearRawEvents();
+
+ void loadScriptAddons(const QString &szFileName);
+ void saveScriptAddons(const QString &szFileName);
+ void clearScriptAddons();
+
+ void flushUserClasses();
+};
+
+
+#endif //!_KVI_KVS_H_
diff --git a/src/kvirc/kvs/kvi_kvs_action.cpp b/src/kvirc/kvs/kvi_kvs_action.cpp
new file mode 100644
index 00000000..08291145
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_action.cpp
@@ -0,0 +1,66 @@
+//=============================================================================
+//
+// File : kvi_kvs_action.cpp
+// Created on Sat 04 Dec 2004 04:22:12 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_action.h"
+#include "kvi_kvs_script.h"
+#include "kvi_window.h"
+
+KviKvsAction::KviKvsAction(QObject * pParent,
+ const QString &szName,
+ const QString &szScriptCode,
+ const QString &szVisibleName,
+ const QString &szDescription,
+ KviActionCategory * pCategory,
+ const QString &szBigIcon,
+ int iSmallIconId,
+ unsigned int uFlags,
+ const QString &szKeySequence)
+ : KviAction(pParent,szName,szVisibleName,szDescription,pCategory,szBigIcon,iSmallIconId,uFlags,szKeySequence)
+{
+ QString tmp = KVI_KVS_ACTION_SCRIPT_NAME_PREFIX;
+ tmp += szName;
+ m_pScript = new KviKvsScript(tmp,szScriptCode);
+}
+
+
+KviKvsAction::~KviKvsAction()
+{
+ unregisterAccelerator();
+ delete m_pScript;
+}
+
+const QString & KviKvsAction::scriptCode()
+{
+ return m_pScript->code();
+}
+
+void KviKvsAction::activate()
+{
+ // at the moment it executes externally!
+ // FIXME!
+ if(!isEnabled())return; // no way
+ m_pScript->run(g_pActiveWindow); // FIXME: complain more in case of error ?
+}
diff --git a/src/kvirc/kvs/kvi_kvs_action.h b/src/kvirc/kvs/kvi_kvs_action.h
new file mode 100644
index 00000000..0a33569e
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_action.h
@@ -0,0 +1,59 @@
+#ifndef _KVI_KVSACTION_H_
+#define _KVI_KVSACTION_H_
+//=============================================================================
+//
+// File : kvi_kvs_action.h
+// Created on Sat 04 Dec 2004 04:22:12 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_action.h"
+
+class KviKvsScript;
+
+#define KVI_KVS_ACTION_SCRIPT_NAME_PREFIX "action::"
+
+class KVIRC_API KviKvsAction : public KviAction
+{
+ Q_OBJECT
+protected:
+ KviKvsScript * m_pScript;
+public:
+ KviKvsAction(QObject * pParent,
+ const QString &szName,
+ const QString &szScriptCode,
+ const QString &szVisibleName,
+ const QString &szDescription,
+ KviActionCategory * pCategory = 0,
+ const QString &szBigIcon = QString::null,
+ int iSmallIconId = 0,
+ unsigned int uFlags = 0,
+ const QString &szKeySequence = QString::null);
+ ~KviKvsAction();
+public:
+ const QString & scriptCode();
+ virtual void activate();
+};
+
+
+
+
+#endif //!_KVI_KVSACTION_H_
diff --git a/src/kvirc/kvs/kvi_kvs_aliasmanager.cpp b/src/kvirc/kvs/kvi_kvs_aliasmanager.cpp
new file mode 100644
index 00000000..257b6cf8
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_aliasmanager.cpp
@@ -0,0 +1,121 @@
+//=============================================================================
+//
+// File : kvi_kvs_aliasmanager.cpp
+// Created on Mon 15 Dec 2003 02:11:41 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_aliasmanager.h"
+#include "kvi_config.h"
+
+KviKvsAliasManager * KviKvsAliasManager::m_pAliasManager = 0;
+
+KviKvsAliasManager::KviKvsAliasManager()
+{
+ m_pAliasManager = this;
+ m_pAliasDict = new KviPointerHashTable<QString,KviKvsScript>(51,false);
+ m_pAliasDict->setAutoDelete(true);
+}
+
+KviKvsAliasManager::~KviKvsAliasManager()
+{
+ delete m_pAliasDict;
+}
+
+void KviKvsAliasManager::init()
+{
+ if(KviKvsAliasManager::instance())
+ {
+ debug("WARNING: Trying to create the KviKvsAliasManager twice!");
+ return;
+ }
+ (void)new KviKvsAliasManager();
+}
+
+void KviKvsAliasManager::done()
+{
+ if(!KviKvsAliasManager::instance())
+ {
+ debug("WARNING: Trying to destroy the KviKvsAliasManager twice!");
+ return;
+ }
+ delete KviKvsAliasManager::instance();
+}
+
+void KviKvsAliasManager::completeCommand(const QString &word,KviPointerList<QString> * matches)
+{
+ KviPointerHashTableIterator<QString,KviKvsScript> it(*m_pAliasDict);
+ while(it.current())
+ {
+ if(KviQString::equalCIN(word,it.current()->name(),word.length()))
+ matches->append(new QString(it.current()->name()));
+ ++it;
+ }
+}
+
+// FIXME: #warning "A binary config would work better and faster here!"
+
+void KviKvsAliasManager::save(const QString & filename)
+{
+ KviConfig cfg(filename,KviConfig::Write);
+ cfg.clear();
+
+ KviPointerHashTableIterator<QString,KviKvsScript> it(*m_pAliasDict);
+
+ while(it.current())
+ {
+ cfg.setGroup(it.current()->name());
+ cfg.writeEntry("_Buffer",it.current()->code());
+ ++it;
+ }
+}
+
+void KviKvsAliasManager::load(const QString & filename)
+{
+ m_pAliasDict->clear();
+ KviConfig cfg(filename,KviConfig::Read);
+
+ KviConfigIterator it(*(cfg.dict()));
+
+ KviPointerList<QString> l;
+ l.setAutoDelete(true);
+
+ while(it.current())
+ {
+ l.append(new QString(it.currentKey()));
+ ++it;
+ }
+
+ for(QString * s = l.first();s;s = l.next())
+ {
+ cfg.setGroup(*s);
+ QString szCode = cfg.readQStringEntry("_Buffer","");
+ if(!szCode.isEmpty())
+ {
+ KviKvsScript * m = new KviKvsScript(*s,szCode);
+ m_pAliasDict->insert(*s,m);
+ }
+ ++it;
+ }
+}
+
+
diff --git a/src/kvirc/kvs/kvi_kvs_aliasmanager.h b/src/kvirc/kvs/kvi_kvs_aliasmanager.h
new file mode 100644
index 00000000..6f25eccb
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_aliasmanager.h
@@ -0,0 +1,67 @@
+#ifndef _KVI_KVS_ALIASMANAGER_H_
+#define _KVI_KVS_ALIASMANAGER_H_
+//=============================================================================
+//
+// File : kvi_kvs_aliasmanager.h
+// Created on Mon 15 Dec 2003 02:11:41 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_pointerhashtable.h"
+
+#include "kvi_pointerlist.h"
+#include "kvi_qstring.h"
+
+#include "kvi_kvs_script.h"
+
+class KVIRC_API KviKvsAliasManager
+{
+protected: // it only can be created and destroyed by KviKvsAliasManager::init()/done()
+ KviKvsAliasManager();
+ ~KviKvsAliasManager();
+protected:
+ KviPointerHashTable<QString,KviKvsScript> * m_pAliasDict;
+ static KviKvsAliasManager * m_pAliasManager;
+public:
+ static KviKvsAliasManager * instance()
+ { return m_pAliasManager; };
+ static void init(); // called by KviKvs::init()
+ static void done(); // called by KviKvs::done()
+
+ KviPointerHashTable<QString,KviKvsScript> * aliasDict(){ return m_pAliasDict; };
+ const KviKvsScript * lookup(const QString & szName)
+ { return m_pAliasDict->find(szName); };
+ void add(const QString &szName,KviKvsScript * pAlias)
+ { m_pAliasDict->replace(szName,pAlias); };
+ bool remove(const QString & szName)
+ { return m_pAliasDict->remove(szName); };
+ void clear()
+ { m_pAliasDict->clear(); };
+
+ void save(const QString & filename);
+ void load(const QString & filename);
+
+ void completeCommand(const QString &word,KviPointerList<QString> * matches);
+};
+
+// namespaces are handled completly in the editing!
+
+#endif //!_KVI_KVS_ALIASMANAGER_H_
diff --git a/src/kvirc/kvs/kvi_kvs_array.cpp b/src/kvirc/kvs/kvi_kvs_array.cpp
new file mode 100644
index 00000000..545d8285
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_array.cpp
@@ -0,0 +1,227 @@
+//=============================================================================
+//
+// File : kvi_kvs_array.cpp
+// Created on Tue 07 Oct 2003 01:07:31 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_array.h"
+#include "kvi_malloc.h"
+
+#include <stdlib.h>
+
+#define KVI_KVS_ARRAY_ALLOC_CHUNK 8
+
+KviKvsArray::KviKvsArray()
+: KviHeapObject()
+{
+ m_pData = 0;
+ m_uSize = 0;
+ m_uAllocSize = 0;
+}
+
+KviKvsArray::KviKvsArray(const KviKvsArray &a)
+: KviHeapObject()
+{
+ m_uSize = a.m_uSize;
+ m_uAllocSize = a.m_uAllocSize;
+ if(m_uAllocSize > 0)
+ {
+ m_pData = (KviKvsVariant **)kvi_malloc((sizeof(KviKvsVariant *)) * m_uAllocSize);
+ kvs_uint_t i;
+ for(i=0;i<m_uSize;i++)
+ if(a.m_pData[i])m_pData[i] = new KviKvsVariant(*(a.m_pData[i]));
+ else m_pData[i] = 0;
+ } else {
+ m_pData = 0;
+ }
+}
+
+KviKvsArray::~KviKvsArray()
+{
+ if(m_pData)
+ {
+ for(kvs_uint_t i=0;i<m_uSize;i++)
+ if(m_pData[i])delete m_pData[i];
+ kvi_free(m_pData);
+ }
+}
+
+static int kvs_array_reverse_compare_func(const void * v1,const void * v2)
+{
+ if(*((KviKvsVariant **)v1))return (*((KviKvsVariant **)v1))->compare(*((KviKvsVariant **)v2));
+ if(*((KviKvsVariant **)v2))return -(*((KviKvsVariant **)v2))->compare(*((KviKvsVariant **)v1));
+ return 0;
+}
+
+static int kvs_array_compare_func(const void * v1,const void * v2)
+{
+ if(*((KviKvsVariant **)v1))return -(*((KviKvsVariant **)v1))->compare(*((KviKvsVariant **)v2));
+ if(*((KviKvsVariant **)v2))return (*((KviKvsVariant **)v2))->compare(*((KviKvsVariant **)v1));
+ return 0;
+}
+
+
+void KviKvsArray::sort()
+{
+ if(m_uSize < 2)return; // already sorted
+ qsort(m_pData,m_uSize,sizeof(KviKvsVariant *),kvs_array_compare_func);
+ findNewSize();
+}
+
+void KviKvsArray::rsort()
+{
+ if(m_uSize < 2)return; // already sorted
+ qsort(m_pData,m_uSize,sizeof(KviKvsVariant *),kvs_array_reverse_compare_func);
+ findNewSize();
+}
+
+void KviKvsArray::unset(kvs_uint_t uIdx)
+{
+ if(uIdx >= m_uSize)return;
+
+ if(m_pData[uIdx])
+ {
+ delete m_pData[uIdx];
+ m_pData[uIdx] = 0;
+ }
+
+ if(uIdx == (m_uSize - 1))
+ {
+ findNewSize();
+ }
+}
+
+void KviKvsArray::findNewSize()
+{
+ // find the new size
+ if(m_uSize == 0)return;
+ kvs_uint_t u = m_uSize - 1;
+ while(u > 0)
+ {
+ if(m_pData[u])break;
+ u--;
+ }
+ if(m_pData[u])m_uSize = u + 1;
+ else {
+ // u == 0, and there is no data in there
+ m_uSize = 0;
+ }
+ // need to shrink ?
+
+ if((m_uAllocSize - m_uSize) > KVI_KVS_ARRAY_ALLOC_CHUNK)
+ {
+ m_uAllocSize = m_uSize;
+ // m_pData is non-zero here since was m_uSize > 0 initally
+ if(m_uSize > 0)
+ {
+ m_pData = (KviKvsVariant **)kvi_realloc(m_pData,(sizeof(KviKvsVariant *)) * m_uAllocSize);
+ } else {
+ kvi_free(m_pData);
+ m_pData = 0;
+ }
+ }
+}
+
+void KviKvsArray::set(kvs_uint_t uIdx,KviKvsVariant * pVal)
+{
+ if(uIdx >= m_uSize)
+ {
+ if(uIdx == m_uSize)
+ {
+ m_uAllocSize += KVI_KVS_ARRAY_ALLOC_CHUNK; // sequential set
+ } else {
+ m_uAllocSize = uIdx + 1;
+ }
+ if(m_pData)
+ m_pData = (KviKvsVariant **)kvi_realloc(m_pData,(sizeof(KviKvsVariant *)) * m_uAllocSize);
+ else
+ m_pData = (KviKvsVariant **)kvi_malloc((sizeof(KviKvsVariant *)) * m_uAllocSize);
+ for(kvs_uint_t u=m_uSize;u<uIdx;u++)
+ m_pData[u] = 0;
+ m_uSize = uIdx+1;
+ m_pData[uIdx] = pVal;
+ } else {
+ if(m_pData[uIdx])delete m_pData[uIdx];
+ m_pData[uIdx] = pVal;
+ }
+}
+
+KviKvsVariant * KviKvsArray::getAt(kvs_uint_t uIdx)
+{
+ if(uIdx >= m_uSize)
+ {
+ if(uIdx == m_uSize)
+ {
+ m_uAllocSize += KVI_KVS_ARRAY_ALLOC_CHUNK; // sequential set
+ } else {
+ m_uAllocSize = uIdx + 1;
+ }
+ if(m_pData)
+ m_pData = (KviKvsVariant **)kvi_realloc(m_pData,(sizeof(KviKvsVariant *)) * m_uAllocSize);
+ else
+ m_pData = (KviKvsVariant **)kvi_malloc((sizeof(KviKvsVariant *)) * m_uAllocSize);
+ for(kvs_uint_t u=m_uSize;u<uIdx;u++)
+ m_pData[u] = 0;
+ m_uSize = uIdx+1;
+ m_pData[uIdx] = new KviKvsVariant();
+ } else {
+ if(!m_pData[uIdx])
+ m_pData[uIdx] = new KviKvsVariant();
+ }
+ return m_pData[uIdx];
+}
+
+void KviKvsArray::serialize(QString& result)
+{
+ QString tmpBuffer;
+ result="[";
+ kvs_uint_t u = 0;
+ bool bNeedComma = false;
+ while(u < m_uSize)
+ {
+ if(bNeedComma)result.append(',');
+ else bNeedComma = true;
+ if(m_pData[u]) {
+ m_pData[u]->serialize(tmpBuffer);
+ result.append(tmpBuffer);
+ } else {
+ result.append("null");
+ }
+ u++;
+ }
+ result.append(']');
+}
+
+void KviKvsArray::appendAsString(QString &szBuffer)
+{
+ kvs_uint_t u = 0;
+ bool bNeedComma = false;
+ while(u < m_uSize)
+ {
+ if(bNeedComma)szBuffer.append(',');
+ else bNeedComma = true;
+ if(m_pData[u])m_pData[u]->appendAsString(szBuffer);
+ u++;
+ }
+}
+
diff --git a/src/kvirc/kvs/kvi_kvs_array.h b/src/kvirc/kvs/kvi_kvs_array.h
new file mode 100644
index 00000000..6c6ca463
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_array.h
@@ -0,0 +1,63 @@
+#ifndef _KVI_KVS_ARRAY_H_
+#define _KVI_KVS_ARRAY_H_
+//=============================================================================
+//
+// File : kvi_kvs_array.h
+// Created on Tue 07 Oct 2003 01:07:31 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#include "kvi_qstring.h"
+#include "kvi_kvs_variant.h"
+#include "kvi_heapobject.h"
+
+
+// This class must not have virtual funcitons nor destructor
+// Otherwise it will happily crash on windows when it is
+// allocated in modules and destroyed anywhere else around...
+class KVIRC_API KviKvsArray : public KviHeapObject
+{
+public:
+ KviKvsArray();
+ KviKvsArray(const KviKvsArray &a);
+ ~KviKvsArray();
+protected:
+ KviKvsVariant ** m_pData;
+ kvs_uint_t m_uSize;
+ kvs_uint_t m_uAllocSize;
+public:
+ void unset(kvs_uint_t uIdx);
+ void set(kvs_uint_t uIdx,KviKvsVariant * pVal);
+ KviKvsVariant * at(kvs_uint_t uIdx) const { return (uIdx < m_uSize) ? m_pData[uIdx] : 0; };
+ KviKvsVariant * getAt(kvs_uint_t uIdx);
+ bool isEmpty(){ return m_uSize == 0; };
+ kvs_uint_t size(){ return m_uSize; };
+ void appendAsString(QString &szBuffer);
+ void serialize(QString& result);
+ void sort();
+ void rsort();
+protected:
+ void findNewSize();
+};
+
+
+#endif //!_KVI_KVS_ARRAY_H_
diff --git a/src/kvirc/kvs/kvi_kvs_arraycast.cpp b/src/kvirc/kvs/kvi_kvs_arraycast.cpp
new file mode 100644
index 00000000..0c2e610e
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_arraycast.cpp
@@ -0,0 +1,44 @@
+//=============================================================================
+//
+// File : kvi_kvs_arraycast.cpp
+// Created on Tue 10 May 2005 00:05:50 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_arraycast.h"
+
+KviKvsArrayCast::~KviKvsArrayCast()
+{
+ if(m_pArray)
+ if(m_bOwned)
+ delete m_pArray;
+}
+
+void KviKvsArrayCast::clear()
+{
+ if(m_pArray)
+ {
+ if(m_bOwned)
+ delete m_pArray;
+ m_pArray = 0;
+ }
+}
diff --git a/src/kvirc/kvs/kvi_kvs_arraycast.h b/src/kvirc/kvs/kvi_kvs_arraycast.h
new file mode 100644
index 00000000..81059e27
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_arraycast.h
@@ -0,0 +1,50 @@
+#ifndef _KVI_KVS_ARRAYCAST_H_
+#define _KVI_KVS_ARRAYCAST_H_
+//=============================================================================
+//
+// File : kvi_kvs_arraycast.h
+// Created on Tue 10 May 2005 00:05:50 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_kvs_array.h"
+
+class KVIRC_API KviKvsArrayCast
+{
+protected:
+ KviKvsArray * m_pArray;
+ bool m_bOwned;
+public:
+ KviKvsArrayCast()
+ : m_pArray(0) {};
+ ~KviKvsArrayCast();
+public:
+ void clear();
+ KviKvsArray * array()
+ { return m_pArray; };
+ void release()
+ { m_bOwned = false; };
+ void set(KviKvsArray * pArry,bool bOwned)
+ { m_pArray = pArry; m_bOwned = bOwned; };
+};
+
+
+#endif //!_KVI_KVS_ARRAYCAST_H_
diff --git a/src/kvirc/kvs/kvi_kvs_asyncdnsoperation.cpp b/src/kvirc/kvs/kvi_kvs_asyncdnsoperation.cpp
new file mode 100644
index 00000000..e7e2b626
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_asyncdnsoperation.cpp
@@ -0,0 +1,122 @@
+//=============================================================================
+//
+// File : kvi_kvs_asyncdnsoperation.cpp
+// Created on Sun 10 Jul 2005 04:36:15 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_asyncdnsoperation.h"
+#include "kvi_dns.h"
+#include "kvi_kvs_script.h"
+#include "kvi_kvs_variant.h"
+#include "kvi_app.h"
+#include "kvi_out.h"
+#include "kvi_locale.h"
+#include "kvi_error.h"
+#include "kvi_kvs_variantlist.h"
+
+#include <qtimer.h>
+
+
+KviKvsAsyncDnsOperation::KviKvsAsyncDnsOperation(KviWindow * pWnd,QString &szQuery,KviDns::QueryType eType,KviKvsScript * pCallback,KviKvsVariant * pMagic)
+: KviKvsAsyncOperation(pWnd)
+{
+ m_pDns = new KviDns();
+ m_szQuery = szQuery;
+ m_eType = eType;
+ m_pCallback = pCallback;
+ m_pMagic = pMagic;
+ connect(m_pDns,SIGNAL(lookupDone(KviDns *)),this,SLOT(lookupTerminated(KviDns *)));
+ if(!m_pDns->lookup(szQuery,eType))
+ QTimer::singleShot(10,this,SLOT(dnsStartFailed()));
+}
+
+KviKvsAsyncDnsOperation::~KviKvsAsyncDnsOperation()
+{
+ if(m_pDns)delete m_pDns;
+ if(m_pMagic)delete m_pMagic;
+ if(m_pCallback)delete m_pCallback;
+}
+
+void KviKvsAsyncDnsOperation::dnsStartFailed()
+{
+ lookupTerminated(m_pDns);
+}
+
+void KviKvsAsyncDnsOperation::lookupTerminated(KviDns *)
+{
+ KviWindow * pWnd = window();
+ if(!g_pApp->windowExists(pWnd))pWnd = g_pActiveWindow;
+
+ if(m_pCallback)
+ {
+ KviKvsVariantList params;
+ params.setAutoDelete(true);
+ if(m_pDns->state() == KviDns::Failure)
+ {
+ params.append(new KviKvsVariant(m_szQuery));
+ params.append(new KviKvsVariant((kvs_int_t)0));
+ params.append(new KviKvsVariant(KviError::getDescription(m_pDns->error())));
+ params.append(new KviKvsVariant());
+ params.append(new KviKvsVariant(*m_pMagic));
+ } else {
+ QString * fh = m_pDns->hostnameList()->first();
+ QString * fi = m_pDns->ipAddressList()->first();
+
+ params.append(new KviKvsVariant(m_szQuery));
+ params.append(new KviKvsVariant((kvs_int_t)1));
+ params.append(new KviKvsVariant(fi ? *fi : QString("?.?.?.?")));
+ params.append(new KviKvsVariant(fh ? *fh : QString("?.?")));
+ params.append(new KviKvsVariant(*m_pMagic));
+ }
+
+ m_pCallback->run(pWnd,&params,0,KviKvsScript::PreserveParams);
+
+ delete this;
+ return;
+ }
+
+ // we have no callback : output the results
+ QString szQuery = m_pDns->query();
+ pWnd->output(KVI_OUT_HOSTLOOKUP,__tr2qs("DNS Lookup result for query \"%Q\""),&szQuery);
+
+ if(m_pDns->state() == KviDns::Failure)
+ {
+ QString strDescription(KviError::getDescription(m_pDns->error()));
+ pWnd->output(KVI_OUT_HOSTLOOKUP,__tr2qs("Error: %Q"),&strDescription);
+ } else {
+ int idx = 1;
+ for(QString * h = m_pDns->hostnameList()->first();h;h = m_pDns->hostnameList()->next())
+ {
+ pWnd->output(KVI_OUT_HOSTLOOKUP,__tr2qs("Hostname %d: %Q"),idx,h);
+ idx++;
+ }
+ idx = 1;
+ for(QString * a = m_pDns->ipAddressList()->first();a;a = m_pDns->ipAddressList()->next())
+ {
+ pWnd->output(KVI_OUT_HOSTLOOKUP,__tr2qs("IP address %d: %Q"),idx,a);
+ idx++;
+ }
+ }
+
+ delete this;
+}
diff --git a/src/kvirc/kvs/kvi_kvs_asyncdnsoperation.h b/src/kvirc/kvs/kvi_kvs_asyncdnsoperation.h
new file mode 100644
index 00000000..4e2046c6
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_asyncdnsoperation.h
@@ -0,0 +1,53 @@
+#ifndef _KVI_KVS_ASYNCDNSOPERATION_H_
+#define _KVI_KVS_ASYNCDNSOPERATION_H_
+//=============================================================================
+//
+// File : kvi_kvs_asyncdnsoperation.h
+// Created on Sun 10 Jul 2005 04:36:15 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_kvs_asyncoperation.h"
+#include "kvi_qstring.h"
+#include "kvi_dns.h"
+
+class KviWindow;
+class KviKvsScript;
+class KviKvsVariant;
+
+class KVIRC_API KviKvsAsyncDnsOperation : public KviKvsAsyncOperation
+{
+ Q_OBJECT
+public:
+ KviKvsAsyncDnsOperation(KviWindow * pWnd,QString &szQuery,KviDns::QueryType eType,KviKvsScript * pCallback = 0,KviKvsVariant * pMagic = 0);
+ virtual ~KviKvsAsyncDnsOperation();
+protected:
+ KviDns * m_pDns;
+ KviDns::QueryType m_eType;
+ KviKvsVariant * m_pMagic;
+ KviKvsScript * m_pCallback;
+ QString m_szQuery;
+protected slots:
+ void lookupTerminated(KviDns *);
+ void dnsStartFailed();
+};
+
+#endif //!_KVI_KVS_ASYNCDNSOPERATION_H_
diff --git a/src/kvirc/kvs/kvi_kvs_asyncoperation.cpp b/src/kvirc/kvs/kvi_kvs_asyncoperation.cpp
new file mode 100644
index 00000000..549627ed
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_asyncoperation.cpp
@@ -0,0 +1,66 @@
+//=============================================================================
+//
+// File : kvi_kvs_asyncoperation.cpp
+// Created on Sat 09 Jul 2005 04:54:24 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_asyncoperation.h"
+#include "kvi_kvs_kernel.h"
+#include "kvi_window.h"
+
+KviKvsAsyncOperation::KviKvsAsyncOperation(KviWindow * pWnd)
+: QObject()
+{
+ m_pWnd = pWnd;
+ KviKvsKernel::instance()->asyncOperationManager()->registerOperation(this);
+}
+
+KviKvsAsyncOperation::~KviKvsAsyncOperation()
+{
+ KviKvsKernel::instance()->asyncOperationManager()->unregisterOperation(this);
+}
+
+
+KviKvsAsyncOperationManager::KviKvsAsyncOperationManager()
+{
+ m_pOperationList = new KviPointerList<KviKvsAsyncOperation>;
+ m_pOperationList->setAutoDelete(false);
+}
+
+KviKvsAsyncOperationManager::~KviKvsAsyncOperationManager()
+{
+ while(m_pOperationList->first())
+ delete m_pOperationList->first();
+ delete m_pOperationList;
+}
+
+void KviKvsAsyncOperationManager::registerOperation(KviKvsAsyncOperation * o)
+{
+ m_pOperationList->append(o);
+}
+
+void KviKvsAsyncOperationManager::unregisterOperation(KviKvsAsyncOperation * o)
+{
+ m_pOperationList->removeRef(o);
+}
+
diff --git a/src/kvirc/kvs/kvi_kvs_asyncoperation.h b/src/kvirc/kvs/kvi_kvs_asyncoperation.h
new file mode 100644
index 00000000..2b5641bd
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_asyncoperation.h
@@ -0,0 +1,59 @@
+#ifndef _KVI_KVS_ASYNCOPERATION_H_
+#define _KVI_KVS_ASYNCOPERATION_H_
+//=============================================================================
+//
+// File : kvi_kvs_asyncoperation.h
+// Created on Sat 09 Jul 2005 04:54:24 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_pointerlist.h"
+#include <qobject.h>
+
+class KviWindow;
+
+class KVIRC_API KviKvsAsyncOperation : public QObject
+{
+ Q_OBJECT
+public:
+ KviKvsAsyncOperation(KviWindow * pWnd);
+ virtual ~KviKvsAsyncOperation();
+protected:
+ KviWindow * m_pWnd;
+public:
+ KviWindow * window(){ return m_pWnd; };
+};
+
+
+class KVIRC_API KviKvsAsyncOperationManager
+{
+ friend class KviKvsAsyncOperation;
+public:
+ KviKvsAsyncOperationManager();
+ ~KviKvsAsyncOperationManager();
+protected:
+ KviPointerList<KviKvsAsyncOperation> * m_pOperationList;
+protected:
+ void registerOperation(KviKvsAsyncOperation * o);
+ void unregisterOperation(KviKvsAsyncOperation * o);
+};
+
+#endif //!_KVI_KVS_ASYNCOPERATION_H_
diff --git a/src/kvirc/kvs/kvi_kvs_callbackobject.cpp b/src/kvirc/kvs/kvi_kvs_callbackobject.cpp
new file mode 100644
index 00000000..7f304245
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_callbackobject.cpp
@@ -0,0 +1,108 @@
+//=============================================================================
+//
+// File : kvi_kvs_callbackobject.cpp
+// Created on Mon 21 Nov 2005 01:46:51 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_callbackobject.h"
+#include "kvi_console.h"
+#include "kvi_app.h"
+
+
+KviKvsCallbackObject::KviKvsCallbackObject(const QString &szCallbackName,KviWindow * pTargetWindow,const QString &szCallbackCode,KviKvsVariantList * pMagicParams,unsigned int uFlags)
+: KviHeapObject()
+{
+ m_uFlags = uFlags;
+ m_pTargetWindow = pTargetWindow;
+ if(pTargetWindow)
+ m_pTargetConsole = pTargetWindow->console();
+ else
+ m_pTargetConsole = 0;
+ m_pMagicParams = new KviKvsVariantList();
+ if(pMagicParams)
+ for(KviKvsVariant * v = pMagicParams->first();v;v = pMagicParams->next())
+ m_pMagicParams->append(new KviKvsVariant(*v));
+ QString szName;
+ szName = szCallbackName;
+ szName += "::";
+ szName += "callback";
+ m_pScript = new KviKvsScript(szName,szCallbackCode);
+}
+
+KviKvsCallbackObject::~KviKvsCallbackObject()
+{
+ delete m_pScript;
+ delete m_pMagicParams;
+}
+
+KviKvsCallbackObject::CallbackStatus KviKvsCallbackObject::execute(KviKvsVariantList * pParams,KviKvsVariant * pRetVal)
+{
+ // first of all check the window
+ if(!m_pTargetWindow)
+ m_pTargetWindow = g_pApp->activeConsole();
+ if(!g_pApp->windowExists(m_pTargetWindow))
+ {
+ // target window dead
+ if(m_uFlags & OnlyIfWindowExists)
+ return TargetWindowDead;
+ // rebind
+ m_pTargetWindow = m_pTargetConsole;
+ if(!m_pTargetWindow)
+ {
+ m_pTargetWindow = g_pApp->activeConsole();
+ if(!m_pTargetWindow)
+ return Error; // ooops...
+ } else {
+ if(!g_pApp->windowExists(m_pTargetWindow))
+ {
+ m_pTargetWindow = g_pApp->activeConsole();
+ if(!m_pTargetWindow)
+ return Error; // ooops...
+ }
+ }
+ }
+ // ok, got the window
+ // now take care of the params
+ KviKvsVariantList params;
+ params.setAutoDelete(false);
+ KviKvsVariant * v;
+
+ if(pParams)
+ for(v = pParams->first();v;v = pParams->next())
+ params.append(v);
+
+ for(v = m_pMagicParams->first();v;v = m_pMagicParams->next())
+ params.append(v);
+
+ unsigned int uRet = m_pScript->run(m_pTargetWindow,&params,pRetVal,KviKvsScript::PreserveParams);
+
+ if(uRet)
+ {
+ if(uRet & KviKvsScript::HaltEncountered)
+ return HaltEncountered;
+ return Success;
+ }
+
+ // ooops... error
+ return Error;
+}
diff --git a/src/kvirc/kvs/kvi_kvs_callbackobject.h b/src/kvirc/kvs/kvi_kvs_callbackobject.h
new file mode 100644
index 00000000..fb6e7090
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_callbackobject.h
@@ -0,0 +1,84 @@
+#ifndef _KVI_KVS_CALLBACKOBJECT_H_
+#define _KVI_KVS_CALLBACKOBJECT_H_
+//=============================================================================
+//
+// File : kvi_kvs_callbackobject.h
+// Created on Mon 21 Nov 2005 01:46:51 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_heapobject.h"
+
+#include "kvi_window.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_variantlist.h"
+#include "kvi_kvs_script.h"
+
+
+//
+// This is a simple callback object useful in stuff like dialog.message(){}
+// You derive a class from KviKvsCallbackObject, pass the callback data (code,window and magic params)
+// and when the time comes ask it to execute the callback (maybe by passing some special parameters)
+//
+//
+
+class KVIRC_API KviKvsCallbackObject : public KviHeapObject
+{
+public:
+ enum CallbackFlags {
+ // Execute the callback only if the target window exists
+ // If this flag is not used then if the target window dies
+ // the callback is executed in another window (the associated console, if possible, otherwise the first available console)
+ OnlyIfWindowExists = 1
+ };
+ enum CallbackStatus {
+ // succesfull execution
+ Success,
+ // error in command
+ Error,
+ // succesfull execution, but halt encountered
+ HaltEncountered,
+ // execution aborted since OnlyIfWindowExists was passed and the target window is dead
+ TargetWindowDead
+ };
+public:
+ KviKvsCallbackObject(
+ const QString &szCallbackSource, // the name of this callback (should identify its source, like "dialog.message"): displayed in error messages
+ KviWindow * pTargetWindow, // the window that this callback should be triggered in (can be zero: to execute in the first available console)
+ const QString &szCallbackCode, // the callback code (may be empty!)
+ KviKvsVariantList * pMagicParams, // magic parameters that should be passed to the callback (this class makes a copy of them)
+ unsigned int uFlags = 0 // a combination of CallbackFlags
+ );
+ virtual ~KviKvsCallbackObject();
+protected:
+ KviKvsScript * m_pScript; // the callback script
+ KviWindow * m_pTargetWindow;
+ KviWindow * m_pTargetConsole;
+ KviKvsVariantList * m_pMagicParams;
+ unsigned int m_uFlags;
+protected:
+ // the parameter list is always shallow!
+ CallbackStatus execute(KviKvsVariantList * pParams = 0,KviKvsVariant * pRetVal = 0);
+};
+
+
+
+#endif //!_KVI_KVS_CALLBACKOBJECT_H_
diff --git a/src/kvirc/kvs/kvi_kvs_corecallbackcommands.cpp b/src/kvirc/kvs/kvi_kvs_corecallbackcommands.cpp
new file mode 100644
index 00000000..308ac8d8
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_corecallbackcommands.cpp
@@ -0,0 +1,1187 @@
+//=============================================================================
+//
+// File : kvi_kvs_corecallbackcommands.cpp
+// Created on Fri 31 Oct 2003 04:07:58 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_corecallbackcommands.h"
+
+#include "kvi_kvs_kernel.h"
+#include "kvi_kvs_timermanager.h"
+#include "kvi_kvs_aliasmanager.h"
+#include "kvi_kvs_variantlist.h"
+#include "kvi_kvs_asyncdnsoperation.h"
+#include "kvi_kvs_eventmanager.h"
+#include "kvi_kvs_processmanager.h"
+#include "kvi_kvs_object_controller.h"
+
+#include "kvi_cmdformatter.h"
+#include "kvi_ircconnectionasyncwhoisdata.h"
+#include "kvi_ircconnection.h"
+#include "kvi_scriptbutton.h"
+#include "kvi_iconmanager.h"
+#include "kvi_locale.h"
+
+#include <qregexp.h>
+#include "kvi_tal_tooltip.h"
+
+namespace KviKvsCoreCallbackCommands
+{
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: ahost
+ @type:
+ command
+ @title:
+ host
+ @syntax:
+ ahost [-i] [-a] (<dnsquery:string>[,<magicdata:variant>]){ <callback command> }
+ @short:
+ DNS lookup
+ @switches:
+ !sw: --ipv6 | -i
+ Causes the command to run in IPv6 mode
+ !sw: --any | -a
+ Causes the command to run in unspecified mode and lookup both IPv4 and IPv6 addresses
+ @description:
+ Starts a DNS lookup for the <dnsquery> and reports the
+ results by calling the callback routine.
+ The -i switch causes the command to execute
+ in IpV6 mode (and lookup ONLY IpV6 hosts!).[br]
+ The -a switch causes the command to run in "unspecified" mode
+ and return any available address: IpV4 or Ipv6.[br]
+ This command also performs reverse lookups (if you pass an IP address as <hostname>).[br]
+ The callback command gets passed five parameters:[br]
+ $0 contains the query string (<dnsquery> in fact)[br]
+ $1 contains the value 1 if the query was succesfull.[br]
+ In that case the remaining parameters are set as follows:[br]
+ $2 contains the first ip address associated to the <dnsquery>[br]
+ $3 contains the hostname associated to the <dnsquery>[br]
+ $4 contains the eventual <magicdata> passed.[br]
+ If $1 contains the value 0 then the query has failed and[br]
+ $2 contains an error message explaining the failure.[br]
+ $3 is empty[br]
+ $4 contains the eventual <magicdata> passed.[br]
+ Please note that if the dns query fails to even start for some
+ reason then your callback MAY be called even before ahost() returns.[br]
+ @switches:
+ !sw: -i
+ Causes the command to execute in IpV6 mode (and lookup ONLY IpV6 hosts!).
+ !sw: -a
+ The -a switch causes the command to run in "unspecified" mode
+ and return any available address: IpV4 or Ipv6.
+ @examples:
+ [example]
+ ahost("localhost")
+ {
+ [cmd]echo[/cmd] "Lookup: "$0;
+ if($1)
+ {
+ [cmd]echo[/cmd] "Ip address: "$2;
+ [cmd]echo[/cmd] "Hostname: "$3;
+ } else {
+ [cmd]echo[/cmd] "Error: $2";
+ }
+ }
+ ahost -i ("irc.flashnet.it","Hello :)")
+ {
+ [cmd]echo[/cmd] "Lookup: "$0;
+ [cmd]echo[/cmd] "Magic: $3";
+ if($1)
+ {
+ [cmd]echo[/cmd] "Ip address: "$2;
+ [cmd]echo[/cmd] "Hostname: "$3;
+ } else {
+ [cmd]echo[/cmd] "Error: $2";
+ }
+ }
+ ahost -a ("cafe:babe::dead:beef")
+ {
+ [cmd]echo[/cmd] "Lookup: "$0;
+ [cmd]echo[/cmd] "Magic: $3";
+ if($1)
+ {
+ [cmd]echo[/cmd] "Ip address: "$2;
+ [cmd]echo[/cmd] "Hostname: "$3;
+ } else {
+ [cmd]echo[/cmd] "Error: $2";
+ }
+ }
+ [/example]
+ @seealso:
+ [cmd]host[/cmd]
+ */
+
+ KVSCCC(ahost)
+ {
+ QString szQuery;
+ KviKvsVariant * pMagicPtr;
+ KVSCCC_PARAMETERS_BEGIN
+ KVSCCC_PARAMETER("dnsquery",KVS_PT_NONEMPTYSTRING,0,szQuery)
+ KVSCCC_PARAMETER("magic",KVS_PT_VARIANT,KVS_PF_OPTIONAL,pMagicPtr)
+ KVSCCC_PARAMETERS_END
+
+ KviDns::QueryType queryType = KviDns::IpV4;
+ if(KVSCCC_pSwitches->find('i',"ipv6"))queryType = KviDns::IpV6;
+ if(KVSCCC_pSwitches->find('a',"any"))queryType = KviDns::Any;
+
+ KviKvsVariant * pMagic = pMagicPtr ? new KviKvsVariant(*pMagicPtr) : new KviKvsVariant();
+
+ KviKvsAsyncDnsOperation * op = new KviKvsAsyncDnsOperation(
+ KVSCCC_pContext->window(),
+ szQuery,
+ queryType,
+ new KviKvsScript(*KVSCCC_pCallback),
+ pMagic);
+
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: alias
+ @title:
+ alias
+ @type:
+ command
+ @short:
+ Adds a new alias or modifies an existing one
+ @syntax:
+ alias [-q] (<alias_name>) <implementation>
+ alias [-q] (<alias_name>){}
+ @switches:
+ !sw: -q | --quiet
+ Causes the command to run quietly
+ @description:
+ Adds the alias <alias_name> with the specified <implementation> code.
+ The implementation code can be either a single KVS instruction
+ or an instruction block (instruction list enclosed in braces).[br]
+ If the alias was already existing, it is replaced with the
+ new implementation.[br]
+ If the <implementation> is empty (eg. "{}" or just a ";")
+ the alias <alias_name> is removed instead of being added.
+ If the "remove" form is used but the specified <alias_name> is
+ not existing in the alias store then a warning is printed unless
+ the -q (--quiet) switch is used.
+ If <alias_name> contains a "<name>::" prefix, then the alias
+ is created in the namespace specified by <name>.
+ If the namespace is not existing, it is created.
+ Any alias without the "<name>::" prefix is created in the root
+ namespace. Namespaces are useful to avoid collisions in alias names
+ between scripts. Only really common aliases should be created
+ in the root namespace: all your script internal functionality
+ should be hidden in your own namespace.
+ @examples:
+ [example]
+ [comment]# Add the alias j[/comment]
+ alias(j)
+ {
+ [cmd]join[/cmd] $0;
+ }
+ [comment]# Remove the alias j[/comment]
+ alias(j){}
+ [comment]# Add the alias j in namespace letters[/comments]
+ alias(letters::j)
+ {
+ [cmd]echo[/cmd] "j"
+ }
+ [/example]
+ @seealso:
+ [doc:kvs_aliasesandfunctions]Aliases and functions[/doc]
+ */
+
+ /*
+ @doc: function
+ @title:
+ function
+ @type:
+ command
+ @short:
+ A synomim for alias
+ @syntax:
+ function [-q] (<function_name>) <implementation>
+ function [-q] (<function_name>){}
+ @switches:
+ !sw: -q | --quiet
+ Causes the command to run quietly
+ @description:
+ This command is a synonim for [cmd]alias[/cmd].
+ @seealso:
+ [doc:kvs_aliasesandfunctions]Aliases and functions[/doc]
+ */
+
+
+ KVSCCC(alias)
+ {
+ KviKvsVariant * vName = KVSCCC_pParams->first();
+
+ if(!vName || vName->isEmpty())
+ {
+ KVSCCC_pContext->error(__tr2qs("Missing alias name"));
+ return false;
+ }
+
+ QString szName;
+ vName->asString(szName);
+
+ // we allow only [\w:]+
+ QRegExp re("[\\w:]+");
+ if(!re.exactMatch(szName))
+ {
+ KVSCCC_pContext->error(__tr2qs("Alias names can contain only letters, digits, underscores and '::' namespace separators"));
+ return false;
+ }
+
+ // make sure that we have only doubled "::" and not ":" or ":::..."
+ QString tmp = szName;
+ tmp.replace("::","@"); // @ is not allowed by the rule above
+ if(tmp.find(":") != -1)
+ {
+ KVSCCC_pContext->error(__tr2qs("Stray ':' character in alias name: did you mean ...<namespace>::<name> ?"));
+ return false;
+ }
+
+ if(tmp.find("@@") != -1)
+ {
+ KVSCCC_pContext->error(__tr2qs("Found an empty namespace in alias name"));
+ return false;
+ }
+
+ if(KVSCCC_pCallback->code().isEmpty())
+ {
+ if(!KviKvsAliasManager::instance()->remove(szName))
+ {
+ if(!KVSCCC_pSwitches->find('q',"quiet"))
+ KVSCCC_pContext->warning(__tr2qs("The alias %Q is not existing"),&szName);
+ }
+ } else {
+ KviKvsScript * pScript = new KviKvsScript(*KVSCCC_pCallback);
+ pScript->setName(szName);
+ KviKvsAliasManager::instance()->add(szName,pScript);
+ }
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: awhois
+ @type:
+ command
+ @title:
+ awhois
+ @syntax:
+ awhois [-i] (<nickname:string>[,<magic:variant>])
+ {
+ <callback command>
+ }
+ @short:
+ Asynchronous WHOIS
+ @switches:
+ !sw: -i | --idle-time
+ Ask the whois informations to the server that <nickname> is
+ connected to, effectively returning the user's idle time.
+ @description:
+ AWHOIS stands for Asynchronous WHOIS. It is used to obtain data for a specified
+ irc user (designated by <nickname>). This command sends a WHOIS query to the
+ server and silently awaits the sequence of replies. When the "End of WHOIS" message
+ is received from server the <callback command> is executed passing the WHOIS
+ information as positional parameters.[br]
+ The <magic> string is an optional string to be evaluated at AWHOIS execution time.
+ It is passed as the last positional parameter.[br]
+ Callback command parameters:[br]
+ $0 = nickname[br]
+ $1 = username[br]
+ $2 = hostname[br]
+ $3 = realname (may be empty)[br]
+ $4 = server[br]
+ $5 = idle time (may be empty)[br]
+ $6 = signon time (may be empty)[br]
+ $7 = channels (may be empty)[br]
+ $8 = server that provided the information[br]
+ $9 = special information (may be empty)[br]
+ $10 = magic string evaluated at awhois call (may be empty)[br]
+ If the -i switch is specified , the whois message is sent to the server
+ that the <nickname> user is connected to; in this way you will probably
+ get the idle time of the user too.[br]
+ If the server replies with a "No such nick/channel error message" the
+ <callback command> will be still triggered , but will have all the parameters
+ empty with the exception of $0.[br]
+ If the connection gets interrupted before all the information have been received,
+ the <callback command> will never be triggered.[br]
+ This command is [doc:connection_dependant_commands]connection dependant[/doc].[br]
+ @examples:
+ [example]
+ awhois(pragma){ echo $0-; }
+ [/example]
+ */
+
+ KVSCCC(awhois)
+ {
+ QString szNick;
+ KviKvsVariant * pMagic;
+ KVSCCC_PARAMETERS_BEGIN
+ KVSCCC_PARAMETER("nickname",KVS_PT_NONEMPTYSTRING,0,szNick)
+ KVSCCC_PARAMETER("magic",KVS_PT_VARIANT,KVS_PF_OPTIONAL,pMagic)
+ KVSCCC_PARAMETERS_END
+
+ KVSCCC_REQUIRE_CONNECTION
+
+ KviQCString szN = KVSCCC_pConnection->encodeText(szNick);
+
+ KviAsyncWhoisInfo * info = new KviAsyncWhoisInfo();
+ info->pCallback = new KviKvsScript(*KVSCCC_pCallback);
+ info->pMagic = pMagic ? new KviKvsVariant(*pMagic) : new KviKvsVariant();
+ info->szNick = szNick;
+ info->pWindow = KVSCCC_pWindow;
+
+ KVSCCC_pConnection->asyncWhoisData()->add(info);
+
+ if(KVSCCC_pSwitches->find('i',"idle-time"))KVSCCC_pConnection->sendFmtData("WHOIS %s %s",szN.data(),szN.data());
+ else KVSCCC_pConnection->sendFmtData("WHOIS %s",szN.data());
+
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: button
+ @title:
+ button
+ @type:
+ command
+ @short:
+ Adds/removes/changes user definable buttons
+ @syntax:
+ button [-d] [-q] (<type_unused:variant>,<name:string>[,<image_id:string>[,<label_text:string>]])
+ {
+ <callback_code>
+ }
+ @switches:
+ !sw: -d | --disabled
+ Creates the button as disabled
+ !sw: -q | --quiet
+ Run quietly, print no warnings
+ @description:
+ Adds a new user defined button with the specified <name>.[br]
+ [br]
+ The <type_unused> parameter is ignored and is present only for
+ backward compatibility.
+ [br]
+ The button image is specified by the [doc:image_id]<image_id>[/doc].[br]
+ The optional button text is specified by <label_text>.[br]
+ The <callback_code> will be executed as reaction to a button press.[br]
+ [br]
+ The "window" type button can be added only to the windows that have a button container: this
+ actually includes at least console , channels and queries.[br]
+ The button is added to the current window; if you want to add it to a different
+ window , use the [doc:command_rebinding]standard -r command rebinding[/doc] switch.[br]
+ The <callback_code> will be executed as reaction to a button press; the
+ code execution will be bound to the window that the button is attacched to.[br]
+ If a button with <name> already exists in the current window, its parameters are changed
+ according to the passed values (<image_id>, <label_text> and <callback_code>).[br]
+ [br]
+ Passing an empty <callback_value> removes the button.[br]
+ The callback parameters $0 and $1 will contain the screen coordinates of the bottom-left
+ corner of the button: this is useful for showing a popup menu in response to the click.[br]
+ If the -q switch is used , this command prints no warnings.[br]
+ The -d switch causes the button to be disabled (grayed).[br]
+ @examples:
+ [example]
+ button(w,test,-1,Test button){ echo Test!; }
+ button(w,test){}
+ [/example]
+
+ */
+
+ KVSCCC(button)
+ {
+ KviKvsVariant * pUnused;
+ QString szName,szIcon,szLabel;
+ KVSCCC_PARAMETERS_BEGIN
+ KVSCCC_PARAMETER("type_unused",KVS_PT_VARIANT,0,pUnused)
+ KVSCCC_PARAMETER("name",KVS_PT_NONEMPTYSTRING,0,szName)
+ KVSCCC_PARAMETER("icon",KVS_PT_NONEMPTYSTRING,KVS_PF_OPTIONAL,szIcon)
+ KVSCCC_PARAMETER("label",KVS_PT_NONEMPTYSTRING,KVS_PF_OPTIONAL,szLabel)
+ KVSCCC_PARAMETERS_END
+
+ KviScriptUserButton * pButton = 0;
+
+ if(!KVSCCC_pWindow->buttonContainer())
+ {
+ if(!KVSCCC_pSwitches->find('q',"quiet"))
+ KVSCCC_pContext->warning(__tr2qs("The specified window has no button containers"));
+ return true;
+ }
+
+ pButton = (KviScriptUserButton *)(KVSCCC_pWindow->buttonContainer())->child(szName,"KviWindowScriptButton");
+
+ if(KVSCCC_pCallback->code().isEmpty())
+ {
+ if(pButton)delete pButton;
+ else {
+ if(!KVSCCC_pSwitches->find('q',"quiet"))
+ KVSCCC_pContext->warning(__tr2qs("Window button '%Q' not found"),&szName);
+ }
+ return true;
+ }
+
+ if(!pButton)
+ {
+ pButton = new KviWindowScriptButton(KVSCCC_pWindow->buttonContainer(),KVSCCC_pWindow,szName);
+ pButton->show();
+ }
+
+ KviTalToolTip::remove(pButton);
+ if(!szLabel.isEmpty())
+ {
+ pButton->setButtonText(szLabel);
+ KviTalToolTip::add(pButton,szLabel);
+ }
+
+ pButton->setButtonCode(new KviKvsScript(*KVSCCC_pCallback));
+
+ if(!szIcon.isEmpty())
+ {
+ QPixmap * pix = g_pIconManager->getImage(szIcon);
+ if(pix)
+ {
+ pButton->setButtonPixmap(*pix);
+ } else {
+ if(!KVSCCC_pSwitches->find('q',"quiet"))
+ KVSCCC_pContext->warning(__tr2qs("Can't find the icon '%Q'"),&szIcon);
+ }
+ }
+
+ pButton->setEnabled(!(KVSCCC_pSwitches->find('d',"disabled")));
+
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: event
+ @title:
+ event
+ @type:
+ command
+ @short:
+ Adds a new event handler
+ @syntax:
+ event [-q] (<event_name>,<handler_name>)
+ {
+ <implementation>
+ }
+ @switches:
+ !sw: -q | --quiet
+ Do not print any warnings
+ @description:
+ Adds the handler <handler_name> with <implementation> to
+ the list of handlers for the event <event_name>.[br]
+ If the <implementation> is empty
+ the handler <handler_name> is removed from the handler
+ list instead of being added.[br]
+ The <event_name> may be one of the kvirc-builtin event names
+ or a numeric code (from 0 to 999) of a raw server message.[br]
+ If the -q switch is specified then the command runs in quiet mode.
+ @seealso:
+ [cmd]eventctl[/cmd]
+ */
+
+ KVSCCC(event)
+ {
+ QString szEventName,szHandlerName;
+ KVSCCC_PARAMETERS_BEGIN
+ KVSCCC_PARAMETER("event_name",KVS_PT_NONEMPTYSTRING,0,szEventName)
+ KVSCCC_PARAMETER("handler_name",KVS_PT_NONEMPTYSTRING,0,szHandlerName)
+ KVSCCC_PARAMETERS_END
+
+ bool bOk;
+ int iNumber = szEventName.toInt(&bOk);
+ bool bIsRaw = (bOk && (iNumber >= 0) && (iNumber < 1000));
+
+ if(bIsRaw)
+ {
+ if(!KviKvsEventManager::instance()->isValidRawEvent(iNumber))
+ {
+ if(!KVSCCC_pSwitches->find('q',"quiet"))
+ KVSCCC_pContext->warning(__tr2qs("No such event (%Q)"),&szEventName);
+ return true;
+ }
+ } else {
+ iNumber = KviKvsEventManager::instance()->findAppEventIndexByName(szEventName);
+ if(!KviKvsEventManager::instance()->isValidAppEvent(iNumber))
+ {
+ if(!KVSCCC_pSwitches->find('q',"quiet"))
+ KVSCCC_pContext->warning(__tr2qs("No such event (%Q)"),&szEventName);
+ return true;
+ }
+ }
+
+ if(KVSCCC_pCallback->code().isEmpty())
+ {
+ if(bIsRaw)
+ {
+ if(!KviKvsEventManager::instance()->removeScriptRawHandler(iNumber,szHandlerName))
+ {
+ if(!KVSCCC_pSwitches->find('q',"quiet"))
+ KVSCCC_pContext->warning(__tr2qs("No handler '%Q' for raw numeric event '%d'"),&szHandlerName,iNumber);
+ }
+ } else {
+ if(!KviKvsEventManager::instance()->removeScriptAppHandler(iNumber,szHandlerName))
+ {
+ if(!KVSCCC_pSwitches->find('q',"quiet"))
+ KVSCCC_pContext->warning(__tr2qs("No handler '%Q' for event '%Q'"),&szHandlerName,&szEventName);
+ }
+ }
+ } else {
+ if(bIsRaw)
+ {
+ // remove the old handler
+ KviKvsEventManager::instance()->removeScriptRawHandler(iNumber,szHandlerName);
+ QString contextName;
+ KviQString::sprintf(contextName,"RawEvent%d::%Q",iNumber,&szHandlerName);
+ KviKvsScriptEventHandler * pHandler = new KviKvsScriptEventHandler(szHandlerName,contextName,KVSCCC_pCallback->code());
+ KviKvsEventManager::instance()->addRawHandler(iNumber,pHandler);
+ } else {
+ // remove the old handler
+ KviKvsEventManager::instance()->removeScriptAppHandler(iNumber,szHandlerName);
+ QString contextName;
+ KviQString::sprintf(contextName,"%Q::%Q",&szEventName,&szHandlerName);
+ KviKvsScriptEventHandler * pHandler = new KviKvsScriptEventHandler(szHandlerName,contextName,KVSCCC_pCallback->code());
+ KviKvsEventManager::instance()->addAppHandler(iNumber,pHandler);
+ }
+ }
+
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: exec
+ @type:
+ command
+ @title:
+ exec
+ @syntax:
+ exec [switches] (<commandline:string>[,<magic data:variant>])
+ {
+ <callback command>
+ }
+ @short:
+ Asynchronous execution of external programs
+ @switches:
+ !sw: -q | --quiet
+ Quiet: do not print any warnings
+ !sw: -t | --trigger-termination
+ Trigger the termination event
+ !sw: -x | --trigger-startup
+ Trigger the startup event
+ !sw: -n | --no-stdout
+ Do NOT trigger any stdout events
+ !sw: -e | --trigger-stderr
+ Trigger stderr events
+ !sw: -b | --output-block
+ Trigger the <callback comand> with the stdout and stderr events exactly once,
+ passing the complete block of process output. The events are triggered even
+ if the process output is empty.
+ !sw: -k=<maximum run time> | --kill-after=<maximum run time>
+ Kill the process unconditionally after <maximum run time> milliseconds.
+ If the -t switch is used then the termination event will be
+ triggered just after the process has been killed.
+ !sw: -p=<timeout> | --trigger-ping=<timeout>
+ Trigger <callback command> with "ping" events every <timeout> milliseconds.
+ !sw: -w | --bind-to-window
+ Kill the process if the current window is closed. In this case the
+ termination event is NOT triggered (since the parent window has been lost).
+ If this switch is not used then the process is rebound to
+ the active console window and continues running.
+ !sw: -s=<interpreter command> | --shell=<interpreter command>
+ Use <interpreter command> instead of the default interpreter "sh -c".
+ The <interpreter command> should be able to launch the interpeter
+ and should contain the necessary arguments in order to allow
+ KVirc to pass the "commandline" by appending it as the last parameter.
+ !sw: -d | --direct
+ Use no command interpreter at all: run the command directly.
+ Takes precedence over -s.
+ !sw: -q | --quiet
+ Run quietly
+ @description:
+ [b]Overview[/b][br]
+ Executes the <commandline> by passing it to a command interpreter.
+ The <commandline> is executed asynchronously: this means that
+ when exec returns the control to the next command, <commandline>
+ may be still running.[br]
+ [br]
+ [b]The callback[/b][br]
+ The <callback command> is triggered on several events related to the
+ child process and it gets passed the following parameters:[br]
+ $0 = <event cause>[br]
+ $1 = <event parameter>[br]
+ $2 = <magic data>[br]
+ The first parameter specifies the event cause and contains one of the
+ following strings: "stdout","stderr","terminated","started" and "ping".
+ [b]By default (if no switches are used) only "stdout" type events are triggered[/b].
+ The second parameter depends on the event cause and contains data sensible
+ to each event type. The third parameter is the eventual <magic data>
+ passed to the exec command call.[br]
+ [br]
+ [b]Interacting with the process[/b][br]
+ If you use [cmd]halt[/cmd] to terminate
+ the callback then the slave process is killed immediately and
+ no other callback events are triggered.[br] If you return some non empty string
+ then this string will be written to the process stdin stream. This trick
+ can be used to control interactive processes. Please note that you must
+ include all the relevant carriage returns and newlines in the return value
+ (see [fnc]$cr[/fnc] and [fnc]$lf[/fnc]).[br]
+ [br]
+ [b]Startup event[/b][br]
+ If the -x switch is used then the startup event is triggered
+ just after the process has been succesfully launched.
+ The $0 parameter passed to the callback contains the string "started".
+ Parameter $1 contains the pid of the slave process.[br]
+ [br]
+ [b]Stdout data event[/b][br]
+ The stdout data event is triggered when the process prints some output
+ on its stdout stream. This event is triggered by default and to disable
+ it you must use the -n switch. $0 contains the string "stdout".
+ If the -b switch is not used then $1 contains a single line of process
+ output with the trailing carriage return and/or line feed stripped.
+ If -b is used then $1 contains the whole process output
+ block (eventually empty) with all the cr/lf pairs.[br]
+ [br]
+ [b]Stderr data event[/b][br]
+ The stderr data event is similar to the stdout one but there are three differences.
+ The first one is that the stderr event is NOT triggered by default: you must
+ use the -e switch to enable it. The second difference is that $0
+ contains "stderr" instead of "stdout". The last difference is that $1 contains data
+ coming from the slave process stderr stream.[br]
+ [br]
+ [b]Termination event[/b][br]
+ The termination event is triggered after the slave process has terminated its
+ execution. You must use the -t switch to enable it since it is
+ disabled by default. $0 contains the string "terminated". $1 contains the process exit
+ status value. (Note that if the process has crashed or has been terminated
+ by an external singnal then this value will be 0).[br]
+ [br]
+ [b]Ping event[/b][br]
+ The ping event is triggered only if the -p=<timeout> switch is passed.[br]
+ This event may be useful to monitor the process status while it is not
+ emitting any output, to write data to its stdin stream (by the means of [cmd]return[/cmd])
+ or simply to give some feedback to the user while the slave process is
+ doing a long computation.[br]
+ [br]
+ [b]The extended scope variables[/b][br]
+ The <callback command> has a set of [doc:data_types]extended scope variables[/doc]
+ that conserve their value during the whole life time of the slave process.[br]
+ These variables can be accessed through the %:<varname> syntax and are
+ useful to store process private data between multiple <callback command> calls.[br]
+ [b]Some words about the switches[/b][br]
+ If the -b switch is used then the <callback command> is called only once
+ for the events stdout and stderr (if enabled) with the complete output block from the process.
+ With the -b switch the events stdout and stderr are triggered once even if the process
+ emits no output.
+ The -s=<interpreter> switch may be used to specify the path of the command interpreter
+ that is "sh -c" by default on unix machines and "cmd.exe /c" on windows.
+ The interpreter executable is searched on the system PATH.
+ If the process can't be started then a warning message is printed in the current window
+ unless the -q (quiet) flag is used.[br]
+ [br]
+ @examples:
+ [example]
+ [comment]# Really simple example: print only the stdout of a slave process[/comment]
+ exec("cat /proc/cpuinfo"){ echo $1; };
+ [comment]# Now print only stderr: enable stderr and disable stdout[/comment]
+ exec -e -n ("sed -senseless"){ echo $1; };
+ [comment]# Do it another way: enable stderr and filter out stdout[/comment]
+ exec -e ("sed -senseless"){ if($0 == "stderr")echo $1; }
+ [comment]# Now enable all (almost) events and print them[/comment]
+ exec -e -t -s ("cat /proc/cpuinfo && sed -senseless"){ echo [event:$0] $1; }
+ [comment]# Now see what happens if -b is used[/comment]
+ exec -b -e -t -s ("cat /proc/cpuinfo && sed -senseless"){ echo [event:$0] $1; }
+ [comment]# Run an iterative script and kill it after 20 seconds[/comment]
+ exec -k=20000 ("while true; do sleep 1; echo \"Tic\"; done"){ echo [event:$0] $1; }
+ [comment]# Run a blocking process, kill it after 20 seconds[/comment]
+ [comment]# and give feedback to the user by the means of ping[/comment]
+ exec -k=20000 -p=1000 -t ("cat")
+ {
+ if($0 == "ping")echo "[event:$0] Please wait while doing a huge computation ..."
+ else if($0 == "terminated")echo "[event:$0] Ok, done :)"
+ }
+ [comment]# Do the same but this time use the extended scope vars[/comment]
+ [comment]# Use also a nicer syntax[/comment]
+ exec -k=20000 -p=1000 -t ("cat")
+ {
+ switch($0)
+ {
+ case("ping"):
+ {
+ if(%:x == 1)
+ {
+ %:x = 0;
+ echo "Tic!"
+ } else {
+ %:x = 1;
+ echo "Tac!"
+ }
+ }
+ break;
+ case("terminated"):
+ {
+ echo "Ok, done :)"
+ }
+ break;
+ }
+ }
+ [comment]# Again do the same but kill the process explicitly[/comment]
+ exec -x -p=1000 -t ("cat")
+ {
+ switch($0)
+ {
+ case("started"):
+ {
+ [comment]# Initialize the counter[/comment]
+ %:x = 10;
+ }
+ break;
+ case("ping"):
+ {
+ echo %:x
+ %:x--
+ [comment]# When the counter reaches zero, kill the process with halt[/comment]
+ if(%:x == 0)halt;
+ }
+ break;
+ case("terminated"):
+ {
+ echo "Boom!"
+ }
+ break;
+ }
+ }
+ [comment]# Now play with an interactive process[/comment]
+ [comment]# WARNING: Please note that spam is illegal and generates bad karma[/comment]
+ [comment]# Try it only with your own e-mail address as recipient[/comment]
+ exec -s -k=60000 -t ("telnet my.mail.server.com 25")
+ {
+ if($0 == "started")
+ {
+ %:state = 0
+ [comment]# Returning an empty string does not write to stdin[/comment]
+ return
+ }
+
+ if($1 == "stderr")
+ {
+ echo "[stderr] $1"
+ return
+ }
+
+ if($1 == "terminated")
+ {
+ echo "[process terminated]"
+ return
+ }
+
+ echo "[stdout] $1"
+
+ switch(%:state)
+ {
+ case(0):
+ {
+ [comment]# Waiting for 220 (ready)[/comment]
+ if($str.match("220*",$1))
+ {
+ %:state++
+ echo "Sending HELO..."
+ return "HELO myhostname$cr$lf";
+ }
+ }
+ break
+ case(1):
+ {
+ [comment]# Waiting for 250 (after the HELO)[/comment]
+ if($str.match("250*",$1))
+ {
+ %:state++
+ echo "Sending MAIL..."
+ return "MAIL From: <myname@mydomain.com>$cr$lf"
+ } else {
+ echo "HELO command not accepted: $1"
+ halt
+ }
+ }
+ break;
+ case(2):
+ {
+ [comment]# Waiting for another 250 (MAIL accepted)[/comment]
+ if($str.match("250*",$1))
+ {
+ %:state++
+ echo "Sending RCPT..."
+ return "RCPT To: <me@myself.org>$cr$lf"
+ } else {
+ echo "MAIL command not accepted: $1"
+ halt
+ }
+ }
+ break;
+ case(3):
+ {
+ [comment]# Waiting for another 250 (RCPT accepted)[/comment]
+ if($str.match("250*",$1))
+ {
+ %:state++
+ echo "Sending DATA..."
+ return "DATA$cr$lf"
+ } else {
+ echo "RCPT not accepted: $1"
+ halt
+ }
+ }
+ break;
+ case(4):
+ {
+ [comment]# Waiting for 354 (ok, go on)[/comment]
+ if($str.match("354*",$1))
+ {
+ %:state++
+ echo "Sending body..."
+ return "This is a test message :)$cr$lf$cr$lf.$cr$lf"
+ } else {
+ echo "Mail body not accepted: $1"
+ halt
+ }
+ }
+ break;
+ case(5):
+ {
+ [comment]# We don't wait anymore :)[/comment]
+ %:state++
+ echo "Sending QUIT..."
+ return "QUIT$cr$lf"
+ }
+ break;
+ default:
+ {
+ [comment]# Usually the mail server closes the connection[/comment]
+ %:state++
+ if(%:state > 10)
+ {
+ [comment]# But if it does not in few messages[/comment]
+ [comment]# Then force the process to die[/comment]
+ halt
+ }
+ }
+ }
+ }
+ [/example]
+ */
+
+ KVSCCC(exec)
+ {
+ QString szCommandline;
+ KviKvsVariant * pMagic;
+ KVSCCC_PARAMETERS_BEGIN
+ KVSCCC_PARAMETER("commandline",KVS_PT_NONEMPTYSTRING,0,szCommandline)
+ KVSCCC_PARAMETER("magic",KVS_PT_VARIANT,KVS_PF_OPTIONAL,pMagic)
+ KVSCCC_PARAMETERS_END
+
+ int f = 0;
+
+ if(KVSCCC_pSwitches->find('t',"trigger-termination") != 0)f |= KVI_KVS_PROCESSDESCRIPTOR_TRIGGERTERMINATED;
+ if(KVSCCC_pSwitches->find('n',"no-stdout") == 0)f |= KVI_KVS_PROCESSDESCRIPTOR_TRIGGERSTDOUT;
+ if(KVSCCC_pSwitches->find('e',"trigger-stderr") != 0)f |= KVI_KVS_PROCESSDESCRIPTOR_TRIGGERSTDERR;
+ if(KVSCCC_pSwitches->find('x',"trigger-startup") != 0)f |= KVI_KVS_PROCESSDESCRIPTOR_TRIGGERSTARTED;
+ if(KVSCCC_pSwitches->find('b',"output-block") != 0)f |= KVI_KVS_PROCESSDESCRIPTOR_OUTPUTBYBLOCKS;
+ if(KVSCCC_pSwitches->find('w',"bind-to-window") != 0)f |= KVI_KVS_PROCESSDESCRIPTOR_KILLIFNOWINDOW;
+ if(KVSCCC_pSwitches->find('d',"direct") != 0)f |= KVI_KVS_PROCESSDESCRIPTOR_NOSHELL;
+
+ QString szShell;
+ KVSCCC_pSwitches->getAsStringIfExisting('s',"shell",szShell);
+
+ kvs_int_t iPingTime = 0;
+ kvs_int_t iMaxRunTime = 0;
+
+ KviKvsVariant * pPing = KVSCCC_pSwitches->find('p',"trigger-ping");
+ if(pPing)
+ {
+ if(!(pPing->asInteger(iPingTime) && iPingTime > 0))
+ {
+ KVSCCC_pContext->warning(__tr2qs("The specified ping time is invalid: assuming zero (no ping)"));
+ iPingTime = 0;
+ }
+ }
+
+ KviKvsVariant * pKill = KVSCCC_pSwitches->find('k',"kill-after");
+ if(pKill)
+ {
+ if(!(pKill->asInteger(iMaxRunTime) && iMaxRunTime > 0))
+ {
+ KVSCCC_pContext->warning(__tr2qs("The specified maximum run time is invalid: assuming zero (infinite)"));
+ iMaxRunTime = 0;
+ }
+ }
+
+ KviKvsProcessDescriptorData * d = new KviKvsProcessDescriptorData;
+
+ d->szCommandline = szCommandline;
+ d->szShell = szShell;
+ d->pWnd = KVSCCC_pContext->window();
+ d->pMagic =pMagic ? new KviKvsVariant(*pMagic) : 0;
+ d->iFlags = f;
+ d->pCallback = new KviKvsScript(*KVSCCC_pCallback);
+ d->iMaxRunTime = iMaxRunTime;
+ d->iPingTimeout = iPingTime;
+
+ KviKvsProcessAsyncOperation * op = new KviKvsProcessAsyncOperation(d);
+ if(!op->start())
+ {
+ if(KVSCCC_pSwitches->find('q',"quiet") == 0)KVSCCC_pContext->warning(__tr2qs("Failed to start the process"));
+ delete op;
+ }
+
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: privateimpl
+ @title:
+ privateimpl
+ @type:
+ command
+ @short:
+ Adds a private implementation of a function
+ @syntax:
+ privateimpl(<object_handle>,<function_name>)<implementation>
+ @description:
+ Adds a private implementation of function <function_name> to the
+ existing object designed by <object_handle>.
+ <implementation> must be a valid command sequence.[br]
+ Side note:[br]
+ This command can not succesfully implement
+ the "constructor" function since it must be called
+ after this one has already been executed.[br]
+ To implement a constructor you MUST write your own class definition.[br]
+ @seealso:
+ [cmd]class[/cmd],
+ [doc:objects]Objects documentation[/doc]
+ */
+
+ KVSCCC(privateimpl)
+ {
+ kvs_hobject_t hObject;
+ QString szFunctionName;
+ KVSCCC_PARAMETERS_BEGIN
+ KVSCCC_PARAMETER("object_handle",KVS_PT_HOBJECT,0,hObject)
+ KVSCCC_PARAMETER("function_name",KVS_PT_NONEMPTYSTRING,0,szFunctionName)
+ KVSCCC_PARAMETERS_END
+
+ KviKvsObject * o = KviKvsKernel::instance()->objectController()->lookupObject(hObject);
+ if(!o)
+ {
+ KVSCCC_pContext->error(__tr2qs("The specified object does not exist"));
+ return false;
+ }
+
+ o->registerPrivateImplementation(szFunctionName,KVSCCC_pCallback->code());
+
+ return true;
+ }
+
+
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: timer
+ @title:
+ timer
+ @type:
+ command
+ @short:
+ Starts a timer
+ @syntax:
+ timer [-s] [-p] (<name>,<delay_in_msecs>[,<callback_param1>[,<callback_param2>[,...]]])
+ {
+ <callback_command>
+ }
+ @switches:
+ !sw: -s | --single-shot
+ Causes the timer to trigger only once (single shot timer)
+ !sw: -p | --persistent
+ Creates a persistent timer bound to any existing window
+ @description:
+ Starts a new timer named <name> with the specified delay (in milliseconds).[br]
+ The timer periodically calls the specified <callback_command> code passing the
+ eventual <callback_param> strings as positional parameters.[br]
+ If a timer with the same name already exists, it is replaced by this one.[br]
+ [b]The <callback_command> is evaluated at timer "shot" time and NOT while
+ this command is being parsed. This means that the identifiers that you put
+ inside <callback_command> will NOT have the current values.[/b]
+ The values will be assigned at timer "shot" time.[br]
+ This is a common scripters error and problem: if it is not clear, look at the examples below.[br]
+ The timer is bound to the window in that this command is executed in.[br]
+ If the window gets destroyed, the timer is stopped; unless the -p switch is used.[br]
+ The -p switch causes the timer to be persistent across the application and exists until
+ the last window has been closed: it is basically rebound to another (random) window when the
+ original window is destroyed.[br]
+ The -s switch cuases this timer to trigger only once: it will be automatically destroyed after that.[br]
+ The time has an associated set of [doc:data_structures]extended scope variables[/doc]:
+ the variables that begin with "%:" have their life extended to the whole "life" of the timer.[br]
+ Using a very low delay is a common method to perform some background processing: you
+ basically split a huge job in small slices and execute them when the timer is triggered
+ until you run out of slices. A delay of 0 will cause the timer to be called whenever
+ KVIrc has some "idle time" to spend.
+ On the other hand, remember that timers are precious resources: many timers running
+ with a very low delay will cause KVIrc to slow down.[br]
+ Since all the kvirc timers share the same namespace it is a good idea to use
+ descriptive timer names: a timer named "a" is likely to be used by two or more scripts
+ at once causing one (or both) of them to fail.[br]
+ A timer can be stopped at any time by using the [cmd]killtimer[/cmd] command.
+ @seealso:
+ [cmd]killtimer[/cmd]
+ @examples:
+ [example]
+ [comment]# Just a plain timer[/comment]
+ timer(test,1000){ echo "Hello!"; }
+ [comment]# Now watch the timer running[/comment]
+ killtimer test
+ [comment]# Single shot timer[/comment]
+ timer -s (test,1000){ echo "This will fire only once!"; }
+ [comment]# The call above is equivalent to[/comment]
+ timer(test,1000){ echo "This will file only once!"; killtimer test; }
+ [comment]# Callback parameters: consider the following code[/comment]
+ %parameter = "some string value"
+ echo "Before calling /timer \%parameter is \"%parameter\""
+ timer -s (test,1000,%parameter){ echo "inside the callback \%parameter is \"%parameter\" but \$0 is \"$0\""; }
+ [comment]# watch the timer running , and note the behaviour of the %parameter variable[/comment]
+ killtimer test
+ [comment]# Use the extended scope timer variables[/comment]
+ timer(test,1000)
+ {
+ [comment]# Use the extended scope %:count variable to keep track[/comment]
+ [comment]# of the times that this timer has been called[/comment]
+ [cmd]if[/cmd]("%:count" == "")%:count = 1
+ else %:count++
+ [cmd]echo[/cmd] "This timer has fired %:count times"
+ if(%:count == 10)
+ {
+ # This will kill the current timer, we don't need to specify the name
+ [cmd]killtimer[/cmd]
+ }
+ }
+ [comment]# Use isTimer to check if the timer exists[/comment]
+ [cmd]echo[/cmd] [fnc]$isTimer[/fnc](test)
+ [comment]# Repeat the command above after the 10th timeout...[/comment]
+ [/example]
+ */
+
+ KVSCCC(timer)
+ {
+ KviKvsVariant * vName = KVSCCC_pParams->first();
+ KviKvsVariant * vDelay = KVSCCC_pParams->next();
+
+ if(!vName || vName->isEmpty())
+ {
+ KVSCCC_pContext->error(__tr2qs("Missing timer name"));
+ return false;
+ }
+
+ QString szName;
+ vName->asString(szName);
+
+ if(!vDelay)
+ {
+ KVSCCC_pContext->error(__tr2qs("Missing timeout delay"));
+ return false;
+ }
+
+ kvs_int_t iDelay;
+ if(!vDelay->asInteger(iDelay))
+ {
+ KVSCCC_pContext->error(__tr2qs("The timeout delay didn't evaluate to an integer"));
+ return false;
+ }
+
+ KviKvsTimer::Lifetime lt;
+
+ if(KVSCCC_pSwitches->find('s',"single-shot"))lt = KviKvsTimer::SingleShot;
+ else if(KVSCCC_pSwitches->find('p',"persistent"))lt = KviKvsTimer::Persistent;
+ else lt = KviKvsTimer::WindowLifetime;
+
+ // prepare the callback parameters
+ KviKvsVariantList * l = new KviKvsVariantList();
+ l->setAutoDelete(true);
+
+ KviKvsVariant * v = KVSCCC_pParams->next();
+ while(v)
+ {
+ l->append(new KviKvsVariant(*v)); // copy
+ v = KVSCCC_pParams->next();
+ }
+
+ if(!KviKvsTimerManager::instance()->addTimer(szName,lt,KVSCCC_pContext->window(),iDelay,new KviKvsScript(*KVSCCC_pCallback),l))
+ {
+ KVSCCC_pContext->error(__tr2qs("Unable to add the timer: insufficient system resources"));
+ return false;
+ }
+
+ return true;
+ }
+
+
+ void init()
+ {
+ KviKvsKernel * pKern = KviKvsKernel::instance();
+
+#define _REGCMD(__cmdName,__routine) \
+ { \
+ KviKvsCoreCallbackCommandExecRoutine * r = new KviKvsCoreCallbackCommandExecRoutine; \
+ r->proc = KVI_PTR2MEMBER(KviKvsCoreCallbackCommands::__routine); \
+ pKern->registerCoreCallbackCommandExecRoutine(QString(__cmdName),r); \
+ }
+
+#ifdef COMPILE_NEW_KVS
+ _REGCMD("ahost",ahost);
+ _REGCMD("awhois",awhois);
+#endif
+ _REGCMD("alias",alias);
+#ifdef COMPILE_NEW_KVS
+ _REGCMD("button",button);
+ _REGCMD("event",event);
+ _REGCMD("exec",exec);
+ _REGCMD("privateimpl",privateimpl);
+#endif
+ _REGCMD("function",alias);
+ _REGCMD("timer",timer);
+
+#undef _REGCMD
+ }
+};
diff --git a/src/kvirc/kvs/kvi_kvs_corecallbackcommands.h b/src/kvirc/kvs/kvi_kvs_corecallbackcommands.h
new file mode 100644
index 00000000..ce77ec6d
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_corecallbackcommands.h
@@ -0,0 +1,78 @@
+#ifndef _KVI_KVS_CORECALLBACKCOMMANDS_H_
+#define _KVI_KVS_CORECALLBACKCOMMANDS_H_
+//=============================================================================
+//
+// File : kvi_kvs_corecallbackcommands.h
+// Created on Fri 31 Oct 2003 04:07:58 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_kvs_runtimecontext.h"
+#include "kvi_kvs_variantlist.h"
+#include "kvi_kvs_switchlist.h"
+#include "kvi_kvs_script.h"
+#include "kvi_kvs_parameterprocessor.h"
+
+
+#define KVSCCC(_name) bool _name(KviKvsRunTimeContext * __pContext,KviKvsVariantList * __pParams,KviKvsSwitchList * __pSwitches,const KviKvsScript * __pCallback)
+
+#define KVSCCC_pContext __pContext
+#define KVSCCC_pParams __pParams
+#define KVSCCC_pSwitches __pSwitches
+#define KVSCCC_pCallback __pCallback
+
+#define KVSCCC_PARAMETER(a,b,c,d) KVS_PARAMETER(a,b,c,d)
+
+#define KVSCCC_PARAMETERS_BEGIN \
+ KVS_PARAMETERS_BEGIN(parameter_format_list)
+
+#define KVSCCC_PARAMETERS_END \
+ KVS_PARAMETERS_END \
+ if(!KviKvsParameterProcessor::process(KVSCCC_pParams,KVSCCC_pContext,parameter_format_list))return false;
+
+#define KVSCCC_REQUIRE_CONNECTION \
+ if(!KVSCCC_pContext->window()->context())return KVSCCC_pContext->errorNoIrcContext(); \
+ if(!KVSCCC_pContext->window()->connection())return KVSCCC_pContext->warningNoIrcConnection();
+
+#define KVSCCC_pWindow __pContext->window()
+#define KVSCCC_pConnection __pContext->window()->connection()
+#define KVSCCC_pIrcContext __pContext->context()
+
+
+namespace KviKvsCoreCallbackCommands
+{
+#ifdef COMPILE_NEW_KVS
+ KVSCCC(ahost);
+ KVSCCC(awhois);
+#endif
+ KVSCCC(alias);
+#ifdef COMPILE_NEW_KVS
+ KVSCCC(button);
+ KVSCCC(event);
+ KVSCCC(exec);
+ KVSCCC(privateimpl);
+#endif
+ KVSCCC(timer);
+
+ void init();
+};
+
+#endif //!_KVI_KVS_CORECALLBACKCOMMANDS_H_
diff --git a/src/kvirc/kvs/kvi_kvs_corefunctions.cpp b/src/kvirc/kvs/kvi_kvs_corefunctions.cpp
new file mode 100644
index 00000000..74aa4565
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_corefunctions.cpp
@@ -0,0 +1,156 @@
+//=============================================================================
+//
+// File : kvi_kvs_corefunctions.cpp
+// Created on Fri 31 Oct 2003 01:52:04 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_corefunctions.h"
+
+#include "kvi_kvs_kernel.h"
+#include "kvi_kvs_object.h"
+
+#include "kvi_locale.h"
+
+namespace KviKvsCoreFunctions
+{
+ void init()
+ {
+ KviKvsKernel * pKern = KviKvsKernel::instance();
+
+#define _REGFNC(__fncName,__routine) \
+ { \
+ KviKvsCoreFunctionExecRoutine * r = new KviKvsCoreFunctionExecRoutine; \
+ r->proc = KVI_PTR2MEMBER(KviKvsCoreFunctions::__routine); \
+ pKern->registerCoreFunctionExecRoutine(QString(__fncName),r); \
+ }
+
+ // a_f
+ _REGFNC("active",active)
+ _REGFNC("array",array)
+ _REGFNC("ascii",unicode)
+ _REGFNC("asciiToHex",asciiToHex)
+ _REGFNC("asciiToBase64",asciiToBase64)
+ _REGFNC("away",away)
+ _REGFNC("b",b)
+ _REGFNC("base64ToAscii",base64ToAscii)
+ _REGFNC("bool",boolean)
+ _REGFNC("boolean",boolean)
+ _REGFNC("channel",channel)
+ _REGFNC("char",charCKEYWORDWORKAROUND)
+ _REGFNC("classDefined",classDefined)
+ _REGFNC("console",console)
+ _REGFNC("context",context)
+ _REGFNC("cr",cr)
+ _REGFNC("date",date)
+ _REGFNC("false",falseCKEYWORDWORKAROUND)
+ _REGFNC("features",features)
+ _REGFNC("firstConnectedConsole",firstConnectedConsole)
+ _REGFNC("flatten",flatten)
+ _REGFNC("fmtlink",fmtlink)
+ // g_l
+ _REGFNC("hash",hash);
+// _REGFNC("inputText",inputText);
+ _REGFNC("hexToAscii",hexToAscii);
+ _REGFNC("hostname",hostname);
+ _REGFNC("hptimestamp",hptimestamp);
+ _REGFNC("ic",context);
+ _REGFNC("icon",icon);
+ _REGFNC("iconName",iconName);
+ _REGFNC("int",integer)
+ _REGFNC("integer",integer)
+ _REGFNC("isEmpty",isEmpty)
+ _REGFNC("isEventEnabled",isEventEnabled)
+ _REGFNC("isMainWindowActive",isMainWindowActive)
+ _REGFNC("isMainWindowMinimized",isMainWindowMinimized)
+ _REGFNC("isNumeric",isNumeric)
+ _REGFNC("isSet",isSet)
+ _REGFNC("isTimer",isTimer)
+ _REGFNC("isWellKnown",isWellKnown)
+ _REGFNC("k",k)
+ _REGFNC("keys",keys)
+ _REGFNC("lag",lag)
+ _REGFNC("lang",lang)
+ _REGFNC("length",length)
+ _REGFNC("lf",lf)
+ // m_r
+ _REGFNC("mask",mask)
+ _REGFNC("me",me)
+ _REGFNC("msgtype",msgtype)
+ _REGFNC("new",newCKEYWORDWORKAROUND)
+ _REGFNC("nothing",nothing)
+ _REGFNC("null",nullCKEYWORDWORKAROUND)
+ _REGFNC("o",o)
+ _REGFNC("option",option)
+ _REGFNC("query",query)
+ _REGFNC("r",r)
+ _REGFNC("rand",rand)
+ _REGFNC("real",real)
+ _REGFNC("receivedBytes",receivedBytes)
+ _REGFNC("rsort",rsort)
+ // s_z
+ _REGFNC("selected",selected)
+ _REGFNC("sentBytes",sentBytes)
+ _REGFNC("serialize",serialize)
+ _REGFNC("server",server)
+ _REGFNC("sort",sort)
+ _REGFNC("string",string)
+ _REGFNC("sw",sw)
+ _REGFNC("target",target)
+ _REGFNC("this",thisCKEYWORDWORKAROUND)
+ _REGFNC("tr",tr)
+ _REGFNC("true",trueCKEYWORDWORKAROUND)
+ _REGFNC("typeof",typeofCKEYWORDWORKAROUND)
+ _REGFNC("u",u)
+ _REGFNC("unicode",unicode)
+ _REGFNC("unixtime",unixtime)
+ _REGFNC("unserialize",unserialize)
+ _REGFNC("username",username)
+ _REGFNC("version",version)
+ _REGFNC("window",window)
+ _REGFNC("$",thisCKEYWORDWORKAROUND)
+ _REGFNC("@",strayAt)
+ _REGFNC("@?",mightBeStrayAtOrThis)
+#undef _REGCMD
+ }
+
+ static QString g_szStaticStrayConstantAt("@");
+
+ KVSCF(strayAt)
+ {
+ KVSCF_pRetBuffer->setString(g_szStaticStrayConstantAt);
+ return true;
+ }
+
+ KVSCF(mightBeStrayAtOrThis)
+ {
+ KviKvsObject * o = KVSCF_pContext->thisObject();
+ if(o)
+ {
+ KVSCF_pRetBuffer->setHObject(o->handle());
+ } else {
+ KVSCF_pRetBuffer->setString(g_szStaticStrayConstantAt);
+ }
+ return true;
+ }
+};
+
diff --git a/src/kvirc/kvs/kvi_kvs_corefunctions.h b/src/kvirc/kvs/kvi_kvs_corefunctions.h
new file mode 100644
index 00000000..9fd25eaf
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_corefunctions.h
@@ -0,0 +1,148 @@
+#ifndef _KVI_KVS_COREFUNCTIONS_H_
+#define _KVI_KVS_COREFUNCTIONS_H_
+//=============================================================================
+//
+// File : kvi_kvs_corefunctions.h
+// Created on Fri 31 Oct 2003 01:52:04 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_kvs_runtimecontext.h"
+#include "kvi_kvs_variantlist.h"
+#include "kvi_kvs_variant.h"
+#include "kvi_kvs_parameterprocessor.h"
+
+
+#define KVSCF(_name) bool _name(KviKvsRunTimeContext * __pContext,KviKvsVariantList * __pParams,KviKvsVariant * __pRetBuffer)
+
+#define KVSCF_pContext __pContext
+#define KVSCF_pParams __pParams
+#define KVSCF_pRetBuffer __pRetBuffer
+
+#define KVSCF_PARAMETER(a,b,c,d) KVS_PARAMETER(a,b,c,d)
+
+#define KVSCF_PARAMETERS_BEGIN \
+ KVS_PARAMETERS_BEGIN(parameter_format_list)
+
+#define KVSCF_PARAMETERS_END \
+ KVS_PARAMETERS_END \
+ if(!KviKvsParameterProcessor::process(KVSCF_pParams,KVSCF_pContext,parameter_format_list))return false;
+
+
+namespace KviKvsCoreFunctions
+{
+ // a_f
+ KVSCF(active);
+ KVSCF(array);
+ KVSCF(asciiToBase64);
+ KVSCF(asciiToHex);
+ KVSCF(avatar);
+ KVSCF(away);
+ KVSCF(b);
+ KVSCF(base64ToAscii);
+ KVSCF(boolean);
+ KVSCF(channel);
+ KVSCF(charCKEYWORDWORKAROUND);
+ KVSCF(classDefined);
+ KVSCF(console);
+ KVSCF(context);
+ KVSCF(cr);
+ KVSCF(date);
+ KVSCF(falseCKEYWORDWORKAROUND);
+ KVSCF(features);
+ KVSCF(firstConnectedConsole);
+ KVSCF(flatten);
+ KVSCF(fmtlink);
+
+ // g_l
+ KVSCF(hash);
+ KVSCF(inputText);
+ KVSCF(hexToAscii);
+ KVSCF(hostname);
+ KVSCF(hptimestamp);
+ KVSCF(icon);
+ KVSCF(iconName);
+ KVSCF(integer);
+ KVSCF(isAnyConsoleConnected);
+ KVSCF(isEmpty);
+ KVSCF(isEventEnabled);
+ KVSCF(isNumeric);
+ KVSCF(isMeOp);
+ KVSCF(isMeUserOp);
+ KVSCF(isMeHalfOp);
+ KVSCF(isMeVoice);
+ KVSCF(isMainWindowActive);
+ KVSCF(isMainWindowMinimized);
+ KVSCF(isSet);
+ KVSCF(isTimer);
+ KVSCF(isWellKnown);
+ KVSCF(k);
+ KVSCF(keys);
+ KVSCF(lag);
+ KVSCF(lang);
+ KVSCF(length);
+ KVSCF(lf);
+ // m_r
+ KVSCF(mask);
+ KVSCF(me);
+ KVSCF(msgtype);
+ KVSCF(newCKEYWORDWORKAROUND);
+ KVSCF(nothing);
+ KVSCF(nullCKEYWORDWORKAROUND);
+ KVSCF(o);
+ KVSCF(option);
+ KVSCF(query);
+ KVSCF(r);
+ KVSCF(rand);
+ KVSCF(real);
+ KVSCF(receivedBytes);
+ KVSCF(rsort);
+ // s_z
+ KVSCF(selected);
+ KVSCF(sentBytes);
+ KVSCF(serialize);
+ KVSCF(server);
+ KVSCF(sort);
+ KVSCF(split);
+ KVSCF(string);
+ KVSCF(sw);
+ KVSCF(target);
+ KVSCF(thisCKEYWORDWORKAROUND);
+ KVSCF(timeCFUNCTIONWORKAROUND);
+ KVSCF(tr);
+ KVSCF(trueCKEYWORDWORKAROUND);
+ KVSCF(typeofCKEYWORDWORKAROUND);
+ KVSCF(u);
+ KVSCF(unicode);
+ KVSCF(unixtime);
+ KVSCF(unserialize);
+ KVSCF(username);
+ KVSCF(version);
+ KVSCF(window);
+ // specials
+ KVSCF(strayAt);
+ KVSCF(mightBeStrayAtOrThis);
+ //bool redirectToModule(const QString &szFrom,const QString &szModName,const QString &szFuncName
+
+ void init();
+};
+
+#endif //!_KVI_KVS_COREFUNCTIONS_H_
diff --git a/src/kvirc/kvs/kvi_kvs_corefunctions_af.cpp b/src/kvirc/kvs/kvi_kvs_corefunctions_af.cpp
new file mode 100644
index 00000000..0fba8d70
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_corefunctions_af.cpp
@@ -0,0 +1,1131 @@
+//=============================================================================
+//
+// File : kvi_kvs_corefunctions_af.cpp
+// Created on Fri 31 Oct 2003 01:52:04 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_corefunctions.h"
+
+#include "kvi_kvs_kernel.h"
+#include "kvi_kvs_object_controller.h"
+
+#include "kvi_locale.h"
+#include "kvi_app.h"
+#include "kvi_channel.h"
+#include "kvi_console.h"
+#include "kvi_ircconnection.h"
+#include "kvi_ircconnectionuserinfo.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_avatar.h"
+#include "kvi_ircuserdb.h"
+#include "kvi_time.h"
+
+namespace KviKvsCoreFunctions
+{
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: active
+ @type:
+ function
+ @title:
+ $active
+ @short:
+ Retrieves the window ID of the active window
+ @syntax:
+ <integer> $active[(<irc context id:integer>)]
+ @description:
+ Returns the [b]window ID[/b] of the active window
+ bound to the IRC context specified by <irc context id>.
+ If no window matches the specified IRC context, and invalid
+ window ID is returned (0).[br]
+ If no <irc context id> is specified, then
+ the application active window is returned (the window
+ that currently has the input focus). Note that in this
+ case the returned window may also belong to another IRC
+ context or be not bound to any IRC context at all.
+ In some extreme cases you may even get a window that
+ has no output widget and thus has its output redirected.
+ Using the "global" active window should be used only
+ for communicating something REALLY urgent (and maybe
+ unrelated to a specific IRC connection) to the user.
+ @seealso:
+ [fnc]$window[/fnc]
+ */
+
+ KVSCF(active)
+ {
+ kvs_uint_t uContextId;
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("context_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uContextId)
+ KVSCF_PARAMETERS_END
+
+ KviWindow * wnd;
+ KviConsole * cons;
+ if(KVSCF_pParams->count() > 0)
+ {
+ cons = g_pApp->findConsole(uContextId);
+ if(cons)wnd = cons->activeWindow();
+ else wnd = 0;
+ } else {
+ wnd = g_pActiveWindow;
+ }
+
+ KVSCF_pRetBuffer->setInteger((kvs_int_t)(wnd ? wnd->numericId() : 0));
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: ascii
+ @type:
+ function
+ @title:
+ $ascii
+ @short:
+ Returns the UNICODE code of a character
+ @syntax:
+ <variant> $ascii(<char:string>)
+ @description:
+ This function has been renamed to $unicode and is present
+ only for backward compatibility.
+ @seealso:
+ [fnc]$cr[/fnc], [fnc]$lf[/fnc], [fnc]$char[/fnc]
+ */
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: asciiToBase64
+ @type:
+ function
+ @title:
+ $asciiToBase64
+ @short:
+ Returns an encoded base64 string
+ @syntax:
+ $asciiToBase64(<ascii_string>)
+ @description:
+ Encodes an ASCII string to its base64 encoded rappresentation
+ Please note that since KVS is UNICODE based, this function
+ will first encode the string in UTF8 and then base64-encode.
+ This means that it is substantially only 7bit safe (ASCII codes below 128).
+ @examples:
+ [cmd]echo[/cmd] $asciiToBase64("Hello!")
+ @seealso:
+ [fnc]$base64toascii[/fnc]
+ */
+
+ KVSCF(asciiToBase64)
+ {
+ QString szAscii;
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("ascii_string",KVS_PT_STRING,0,szAscii)
+ KVSCF_PARAMETERS_END
+
+ KviStr tmp1(szAscii);
+ if(tmp1.len() > 0)
+ {
+ KviStr tmp2;
+ tmp2.bufferToBase64(tmp1.ptr(),tmp1.len());
+ KVSCF_pRetBuffer->setString(QString(tmp2.ptr()));
+ } else {
+ KVSCF_pRetBuffer->setString(QString::null);
+ }
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: asciiToHex
+ @type:
+ function
+ @title:
+ $asciiToHex
+ @short:
+ Returns an encoded hex string
+ @syntax:
+ <string> $asciiToHex(<ascii_string:string>)
+ @description:
+ Encodes an ASCII string to its hex encoded rappresentation.
+ Please note that since KVS is UNICODE based, this function
+ will first encode the string in UTF8 and then hex-encode.
+ This means that it is substantially only 7bit safe (ASCII codes below 128).
+ @examples:
+ [cmd]echo[/cmd] $asciiToHex("Hello!")
+ @seealso:
+ [fnc]$hextoascii[/fnc]
+ */
+
+ KVSCF(asciiToHex)
+ {
+ QString szAscii;
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("ascii_string",KVS_PT_STRING,0,szAscii)
+ KVSCF_PARAMETERS_END
+
+ KviStr tmp1(szAscii);
+ if(tmp1.len() > 0)
+ {
+ KviStr tmp2;
+ tmp2.bufferToHex(tmp1.ptr(),tmp1.len());
+ KVSCF_pRetBuffer->setString(QString(tmp2.ptr()));
+ } else {
+ KVSCF_pRetBuffer->setString(QString::null);
+ }
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: array
+ @type:
+ function
+ @title:
+ $array
+ @short:
+ Explicitly creates an array
+ @syntax:
+ <array> $array(<item:variant>,<item:variant>,<item:variant>,....);
+ @description:
+ Returns an array with the specified items. The items are indexed starting from 0.
+ This is just an explicit way of creating an array with a defined set of items,
+ useful for increasing readability.
+ @examples:
+ [example]
+ [cmd]alias[/cmd](test) {
+ [cmd]return[/cmd] $array(1,2,3);
+ }
+ %x = $test();
+ [cmd]foreach[/cmd](%y,%x) {
+ [cmd]echo[/cmd] %y;
+ }
+ [/example]
+ @seealso:
+ [fnc]$hash[/fnc]
+ */
+
+ KVSCF(array)
+ {
+#ifdef COMPILE_NEW_KVS
+ KviKvsArray * a = new KviKvsArray();
+ kvs_int_t idx = 0;
+
+ for(KviKvsVariant * v = KVSCF_pParams->first();v;v = KVSCF_pParams->next())
+ {
+ a->set(idx,new KviKvsVariant(*v));
+ idx++;
+ }
+
+ KVSCF_pRetBuffer->setArray(a);
+#endif
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: away
+ @type:
+ function
+ @title:
+ $away
+ @short:
+ Returns true if the current user is away
+ @syntax:
+ <boolean> $away
+ @description:
+ Returns true if the current user is away, else false.
+ If the current IRC context is not connected at all, this function returns false.
+ */
+
+ KVSCF(away)
+ {
+ kvs_uint_t uCntx;
+
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("irc_context_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uCntx)
+ KVSCF_PARAMETERS_END
+
+ KviConsole * cns;
+
+ if(KVSCF_pParams->count() > 0)
+ {
+ cns = g_pApp->findConsole(uCntx);
+ if(cns)
+ {
+ if(cns->context()->isConnected())
+ KVSCF_pRetBuffer->setBoolean(cns->connection()->userInfo()->isAway());
+ else
+ KVSCF_pRetBuffer->setNothing();
+ } else {
+ KVSCF_pRetBuffer->setNothing();
+ }
+ } else {
+ if(KVSCF_pContext->window()->console())
+ {
+ cns = KVSCF_pContext->window()->console();
+ if(cns->context()->isConnected())
+ KVSCF_pRetBuffer->setBoolean(cns->connection()->userInfo()->isAway());
+ else
+ KVSCF_pRetBuffer->setNothing();
+ } else {
+ KVSCF_pContext->warning(__tr2qs("This window has no associated IRC context"));
+ KVSCF_pRetBuffer->setNothing();
+ }
+ }
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: b
+ @type:
+ function
+ @title:
+ $b
+ @short:
+ Returns the BOLD mIRC control character
+ @syntax:
+ <string> $b
+ @description:
+ Returns the BOLD mIRC control character (CTRL+B).[br]
+ @seealso:
+ [fnc]$k[/fnc], [fnc]$u[/fnc]
+ */
+
+ KVSCF(b)
+ {
+ KVSCF_pRetBuffer->setString(QString(QChar(KVI_TEXT_BOLD)));
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: base64toAscii
+ @type:
+ function
+ @title:
+ $base64ToAscii
+ @short:
+ Returns a decoded base64 string
+ @syntax:
+ <string> $base64ToAscii(<base_64_encoded_string:string>)
+ @description:
+ Decodes a base64 encoded string.
+ @seealso:
+ [fnc]$asciiToBase64[/fnc]
+ */
+
+ KVSCF(base64ToAscii)
+ {
+ QString szBase64;
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("base64_encoded_string",KVS_PT_STRING,0,szBase64)
+ KVSCF_PARAMETERS_END
+
+ KviStr tmp1(szBase64);
+ char * buf;
+ int len = tmp1.base64ToBuffer(&buf,true);
+ KVSCF_pRetBuffer->setString(QString(buf));
+ KviStr::freeBuffer(buf);
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: boolean
+ @type:
+ function
+ @title:
+ $boolean
+ @short:
+ Casts a variable to a boolean
+ @syntax:
+ <integer> $boolean(<data:variant>)
+ @description:
+ Forces <data> to be a boolean data type by first casting
+ to integer (see [fnc]$int[/fnc]()) and then comparing the result against zero.
+ A zero integer will result in a false value while a non-zero one
+ will result in a true value.
+ This function is similar to the C++ (bool) cast and is internally
+ aliased to [fnc]$bool[/fnc] too.
+ Note that since KVIrc does most of the casting work automatically
+ you shouldn't need to use this function.
+ @seealso:
+ [fnc]$real[/fnc]
+ [fnc]$integer[/fnc]
+ */
+
+ /*
+ @doc: bool
+ @type:
+ function
+ @title:
+ $bool
+ @short:
+ Casts a variable to a boolean
+ @syntax:
+ <integer> $bool(<data:variant>)
+ @description:
+ This is an internal alias to [fnc]$boolean[/fnc]().
+ @seealso:
+ [fnc]$real[/fnc]
+ [fnc]$integer[/fnc]
+ */
+
+ KVSCF(boolean)
+ {
+ KviKvsVariant * v;
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("data",KVS_PT_VARIANT,0,v)
+ KVSCF_PARAMETERS_END
+
+ kvs_int_t iVal;
+ v->castToInteger(iVal);
+ KVSCF_pRetBuffer->setBoolean(iVal);
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: channel
+ @type:
+ function
+ @title:
+ $channel
+ @short:
+ Retrieves the window ID of a specified channel
+ @syntax:
+ $channel[(<channel name>[,<irc context id>])]
+ @description:
+ Returns the [b]window ID[/b] of channel matching the
+ <channel name> and bound to the connection specified by
+ <irc context id>[br]
+ If no window matches the specified name or connection, an invalid
+ window ID is returned (0).[br]
+ If no <irc context id> is specified, this function looks for
+ the channel in the current connection context (if any).[br]
+ If no <channel name> is specified, this function returns the current
+ channel window ID, if executed in a channel, else 0.[br]
+ @seealso:
+ [fnc]$window[/fnc],
+ [fnc]$query[/fnc],
+ [fnc]$console[/fnc],
+ [doc:window_naming_conventions]Window naming conventions[/doc]
+ */
+
+ KVSCF(channel)
+ {
+ QString szName;
+ kvs_uint_t uContextId;
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("channel_name",KVS_PT_NONEMPTYSTRING,KVS_PF_OPTIONAL,szName)
+ KVSCF_PARAMETER("context_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uContextId)
+ KVSCF_PARAMETERS_END
+
+ KviWindow * wnd = 0;
+ if(KVSCF_pParams->count() > 0)
+ {
+ if(KVSCF_pParams->count() > 1)
+ {
+ KviConsole * cons = g_pApp->findConsole(uContextId);
+ if(!cons)KVSCF_pContext->warning(__tr2qs("No such IRC context (%u)"),uContextId);
+ else {
+ if(cons->connection())
+ wnd = cons->connection()->findChannel(szName);
+ else
+ wnd = 0;
+ }
+ } else {
+ if(KVSCF_pContext->window()->connection())wnd = KVSCF_pContext->window()->connection()->findChannel(szName);
+ else {
+ if(!KVSCF_pContext->window()->console())
+ KVSCF_pContext->warning(__tr2qs("This window is not associated to an IRC context"));
+ wnd = 0;
+ }
+ }
+ } else {
+ if(KVSCF_pContext->window()->type() == KVI_WINDOW_TYPE_CHANNEL)wnd = KVSCF_pContext->window();
+ }
+
+ KVSCF_pRetBuffer->setInteger((kvs_int_t)(wnd ? wnd->numericId() : 0));
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: char
+ @type:
+ function
+ @title:
+ $char
+ @short:
+ Returns a character specified by unicode
+ @syntax:
+ <string> $char(<unicode_value:integer>)
+ @description:
+ Returns a character corresponding to the UNICODE code <unicode_value>.[br]
+ This function can not return NUL character (UNICODE 0). Basically
+ you should never need it: if you do, drop me a mail.[br]
+ If the <unicode_code> is not a valid UNICODE code (or is 0), this function returns
+ an empty string.[br]
+ @seealso:
+ [fnc]$cr[/fnc], [fnc]$lf[/fnc], [fnc]$unicode[/fnc]
+ */
+
+ KVSCF(charCKEYWORDWORKAROUND)
+ {
+ kvs_uint_t ac;
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("unicode_value",KVS_PT_UINT,0,ac)
+ KVSCF_PARAMETERS_END
+
+ if(ac != 0 && ac < 65536)
+ KVSCF_pRetBuffer->setString(QString(QChar((unsigned short)ac)));
+ else
+ KVSCF_pRetBuffer->setString(QString::null);
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: classdefined
+ @type:
+ function
+ @title:
+ $classdefined
+ @short:
+ Checks if a class is defined
+ @syntax:
+ $classdefined(<class_name>)
+ @description:
+ Returns 1 if the class <class_name> is defined, else 0.
+ */
+
+ KVSCF(classDefined)
+ {
+ // prologue: parameter handling
+ QString szClassName;
+
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("className",KVS_PT_NONEMPTYSTRING,0,szClassName)
+ KVSCF_PARAMETERS_END
+ KVSCF_pRetBuffer->setBoolean(KviKvsKernel::instance()->objectController()->lookupClass(szClassName) != 0);
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: console
+ @type:
+ function
+ @title:
+ $console
+ @short:
+ Retrieves the window ID of a specified console
+ @syntax:
+ $console[(<irc context id>)]
+ @description:
+ Returns the [b]window ID[/b] of the console bound
+ to the IRC context specified by <irc context id>.
+ If no window matches the specified IRC context, an invalid
+ window ID is returned (0).[br]
+ If no <irc context id> is specified, this function looks for
+ the console in the current IRC context (if any).[br]
+ @seealso:
+ [fnc]$window[/fnc],
+ [fnc]$channel[/fnc],
+ [fnc]$query[/fnc],
+ [doc:window_naming_conventions]Window naming conventions[/doc]
+ */
+
+ KVSCF(console)
+ {
+ kvs_uint_t uContextId;
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("context_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uContextId)
+ KVSCF_PARAMETERS_END
+
+ KviConsole * cons;
+ if(KVSCF_pParams->count() > 0)
+ {
+ cons = g_pApp->findConsole(uContextId);
+ } else {
+ cons = KVSCF_pContext->window()->console();
+ if(!cons)KVSCF_pContext->warning(__tr2qs("This window is not associated to an IRC context"));
+ }
+
+ KVSCF_pRetBuffer->setInteger((kvs_int_t)(cons ? cons->numericId() : 0));
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: context
+ @type:
+ function
+ @title:
+ $context
+ @short:
+ Retrieves the ID of the specified IRC context
+ @syntax:
+ $context[(<server>,<nickname>)]
+ @description:
+ Returns the [b]IRC context ID[/b] of the IRC context that uses
+ the specified <server> and local user's <nickname>.[br] This function can
+ find only connected IRC contexts.
+ If no context matches the server and nickname, and invalid
+ [b]IRC context ID[/b] is returned (0).[br]
+ If <server> is an empty string, the first context that matches
+ the specified nickname is returned. If <nickname> is an empty string
+ the first context that uses the specified server is returned.
+ If both parameters are missing this function returns the
+ id of the current IRC context, or '0' if the
+ window in that this call is executed is not bound to any IRC context.
+ Please note that in this last case you may find an [b]IRC context[/b]
+ that is 'not connected'.
+ This can only happen if the current window is a console that is
+ in "idle" state, with no connection established yet.[br]
+ It is a good idea to take a look at the
+ [doc:window_naming_conventions]window naming conventions[/doc].
+ This identifier is equivalent to [fnc]$ic[/fnc].[br]
+ @seealso:
+ [fnc]$window.context[/fnc]
+ */
+
+ KVSCF(context)
+ {
+ QString szServer,szNick;
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("server",KVS_PT_STRING,KVS_PF_OPTIONAL,szServer)
+ KVSCF_PARAMETER("nick",KVS_PT_STRING,KVS_PF_OPTIONAL,szNick)
+ KVSCF_PARAMETERS_END
+
+ KviConsole * cons;
+ if(!(szServer.isEmpty() && szNick.isEmpty()))
+ {
+ cons = g_pApp->findConsole(szServer,szNick);
+ } else {
+ cons = KVSCF_pContext->window()->console();
+ }
+
+ KVSCF_pRetBuffer->setInteger(cons ? cons->ircContextId() : 0);
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: cr
+ @type:
+ function
+ @title:
+ $cr
+ @short:
+ Returns a carriage return character
+ @syntax:
+ <string> $cr
+ @description:
+ Returns a carriage return character
+ @seealso:
+ [fnc]$lf[/fnc], [fnc]$ascii[/fnc], [fnc]$char[/fnc]
+ */
+
+ KVSCF(cr)
+ {
+ KVSCF_pRetBuffer->setString(QString(QChar('\r')));
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: date
+ @type:
+ function
+ @title:
+ $date
+ @short:
+ Returns a date/time string using a specified format
+ @syntax:
+ <string> $date(<format:string>[,<unixtime:integer>])
+ @description:
+ Returns the string representation of <unixtime> or
+ of the current time if <unixtime> is not given,
+ based on <format>.[br]
+ The <format string> should contain a set of characters
+ that will be transformed according to the following rules:[br]
+ [br]
+ [table]
+ [tr][td][b]a[/b][/td][td]The abbreviated weekday name according to the current locale.[/td][/tr]
+ [tr][td][b]A[/b][/td][td]The full weekday name according to the current locale.[/td][/tr]
+ [tr][td][b]b[/b][/td][td]The abbreviated month name according to the current locale.[/td][/tr]
+ [tr][td][b]B[/b][/td][td]The full month name according to the current locale.[/td][/tr]
+ [tr][td][b]c[/b][/td][td]The preferred date and time representation for the current locale.[/td][/tr]
+ [tr][td][b]C[/b][/td][td]The century number (year/100) as a 2-digit integer. (SU)[/td][/tr]
+ [tr][td][b]d[/b][/td][td]The day of the month as a decimal number (range 01 to 31).[/td][/tr]
+ [tr][td][b]D[/b][/td][td]Equivalent to m/d/y.[/td][/tr]
+ [tr][td][b]e[/b][/td][td]Like d, the day of the month as a decimal number, but a leading
+ zero is replaced by a space. (SU)[/td][/tr]
+ [tr][td][b]E[/b][/td][td]Modifier: use alternative format, see below. (SU)[/td][/tr]
+ [tr][td][b]F[/b][/td][td]Equivalent to Y-m-d (the ISO 8601 date format). (C99)[/td][/tr]
+ [tr][td][b]G[/b][/td][td]The ISO 8601 year with century as a decimal number. The 4-digit
+ year corresponding to the ISO week number (see V). This has the
+ same format and value as y, except that if the ISO week number
+ belongs to the previous or next year, that year is used instead.[/td][/tr]
+ [tr][td][b]g[/b][/td][td]Like G, but without century, i.e., with a 2-digit year (00-99).[/td][/tr]
+ [tr][td][b]h[/b][/td][td]Equivalent to b.[/td][/tr]
+ [tr][td][b]H[/b][/td][td]The hour as a decimal number using a 24-hour clock (range 00 to 23).[/td][/tr]
+ [tr][td][b]I[/b][/td][td]The hour as a decimal number using a 12-hour clock (range 01 to 12).[/td][/tr]
+ [tr][td][b]j[/b][/td][td]The day of the year as a decimal number (range 001 to 366).[/td][/tr]
+ [tr][td][b]k[/b][/td][td]The hour (24-hour clock) as a decimal number (range 0 to 23); sin-
+ gle digits are preceded by a blank. (See also H.)[/td][/tr]
+ [tr][td][b]l[/b][/td][td]The hour (12-hour clock) as a decimal number (range 1 to 12); sin-
+ gle digits are preceded by a blank. (See also I.)[/td][/tr]
+ [tr][td][b]m[/b][/td][td]The month as a decimal number (range 01 to 12).[/td][/tr]
+ [tr][td][b]M[/b][/td][td]The minute as a decimal number (range 00 to 59).[/td][/tr]
+ [tr][td][b]n[/b][/td][td]A newline character. (SU)[/td][/tr]
+ [tr][td][b]p[/b][/td][td]Either `AM' or `PM' according to the given time value, or the cor-
+ responding strings for the current locale. Noon is treated as `pm' and midnight as `am'.[/td][/tr]
+ [tr][td][b]r[/b][/td][td]The time in a.m. or p.m. notation. In the POSIX locale this is
+ equivalent to `I:M:S p'.[/td][/tr]
+ [tr][td][b]s[/b][/td][td]The number of seconds since the Epoch, i.e., since 1970-01-01
+ 00:00:00 UTC.[/td][/tr]
+ [tr][td][b]S[/b][/td][td]The second as a decimal number (range 00 to 60). (The range is up
+ to 60 to allow for occasional leap seconds.)[/td][/tr]
+ [tr][td][b]t[/b][/td][td]A tab character.[/td][/tr]
+ [tr][td][b]T[/b][/td][td]The time in 24-hour notation (H:M:S). (SU)[/td][/tr]
+ [tr][td][b]u[/b][/td][td]The day of the week as a decimal, range 1 to 7, Monday being 1.
+ See also w.[/td][/tr]
+ [tr][td][b]U[/b][/td][td]The week number of the current year as a decimal number, range 00
+ to 53, starting with the first Sunday as the first day of week 01. See also V and W.[/td][/tr]
+ [tr][td][b]V[/b][/td][td]The ISO 8601:1988 week number of the current year as a decimal num-
+ ber, range 01 to 53, where week 1 is the first week that has at
+ least 4 days in the current year, and with Monday as the first day
+ of the week. See also U and W.[/td][/tr]
+ [tr][td][b]w[/b][/td][td]The day of the week as a decimal, range 0 to 6, Sunday being 0.[/td][/tr]
+ [tr][td][b]W[/b][/td][td]The week number of the current year as a decimal number, range 00
+ to 53, starting with the first Monday as the first day of week 01.[/td][/tr]
+ [tr][td][b]x[/b][/td][td]The preferred date representation for the current locale without
+ the time.[/td][/tr]
+ [tr][td][b]X[/b][/td][td]The preferred time representation for the current locale without
+ the date.[/td][/tr]
+ [tr][td][b]y[/b][/td][td]The year as a decimal number without a century (range 00 to 99).[/td][/tr]
+ [tr][td][b]Y[/b][/td][td]The year as a decimal number including the century.[/td][/tr]
+ [tr][td][b]z[/b][/td][td]The time-zone as hour offset from GMT. Required to emit
+ RFC822-conformant dates (using "a, d b Y H:M:S z").[/td][/tr]
+ [tr][td][b]Z[/b][/td][td]The time zone or name or abbreviation.[/td][/tr]
+ [tr][td][b]+[/b][/td][td]The date and time in date(1) format. (TZ)[/td][/tr]
+ [/table]
+ WARNING: Please note that this list is taken from the unix version of the strftime
+ function and not all the escape codes may be supported by other platforms.
+ @examples:
+ [example]
+ [cmd]echo[/cmd] $date("d/m/Y H:M:S")
+ [/example]
+ @seealso:
+ [fnc]$time[/fnc], [fnc]$unixtime[/fnc]
+ */
+
+ KVSCF(date)
+ {
+ QString szFormat;
+ kvs_int_t iTime;
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("format",KVS_PT_NONEMPTYSTRING,0,szFormat)
+ KVSCF_PARAMETER("unixtime",KVS_PT_INT,KVS_PF_OPTIONAL,iTime)
+ KVSCF_PARAMETERS_END
+
+ KviStr tmpFormat("");
+
+ #ifdef COMPILE_ON_WINDOWS
+ QString szAllowedCharacters;
+ //windows version of strftime()
+ //kvirc crashes if other then these characters get an % character in front of them
+ szAllowedCharacters = "AaBbcdHIjMmpSUWwXxYyZz";
+ #endif
+
+ const QChar * c = KviQString::nullTerminatedArray(szFormat);
+ if(c)
+ {
+ while(c->unicode())
+ {
+ //Check for right Characters
+ #ifdef COMPILE_ON_WINDOWS
+ if (szAllowedCharacters.find((char)(c->unicode()),0,true) >= 0) tmpFormat += '%';
+ #else
+ if (c->isLetter()) tmpFormat += '%';
+ #endif
+ tmpFormat += (char)(c->unicode());
+ c++;
+ }
+ }
+
+ kvi_time_t t;
+ if(KVSCF_pParams->count() > 1)
+ t = (kvi_time_t)iTime;
+ else
+ t = kvi_unixTime();
+
+ char buf[256];
+ if(strftime(buf,255,tmpFormat.ptr(),localtime(&t))> 0)
+ {
+ KviStr tmp = buf;
+ if(tmp.lastCharIs('\n'))tmp.cutRight(1);
+ KVSCF_pRetBuffer->setString(QString(buf));
+ } else {
+ KVSCF_pContext->warning(__tr2qs("The specified format string wasn't accepted by the underlying system time formatting function"));
+ }
+
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: false
+ @type:
+ function
+ @title:
+ $false
+ @short:
+ The boolean false constant
+ @syntax:
+ <boolean> $false
+ @description:
+ Evaluates to the false boolean constant. True
+ is equivalent to the integer 0 too. This function/constant
+ is useful to keep your code readable: when you
+ have a variable that can assume boolean values it's
+ nicer to use [fnc]$true[/fnc] and $false instead of
+ the integer constants 1 and 0. The reader will
+ undestand immediately that the variable simply can't
+ assume any other value.
+ @examples:
+ [example]
+ %a = $false
+ [cmd]echo[/cmd] $typeof(%a)
+ [cmd]echo[/cmd] $(%a + 1)
+ [/example]
+ @seealso:
+ [fnc]$true[/fnc]
+ */
+
+ KVSCF(falseCKEYWORDWORKAROUND)
+ {
+#ifdef COMPILE_NEW_KVS
+ KVSCF_pRetBuffer->setBoolean(false);
+#endif
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: features
+ @type:
+ function
+ @title:
+ $features
+ @short:
+ Returns the features that KVIrc supports
+ @syntax:
+ <array> $features()
+ <boolean> $features(<test_feature:string>)
+ @description:
+ The parameterless form returns an array of feature descripton strings that this KVIrc executable supports.[br]
+ This function is useful when some part of your script depends on
+ an optional KVIrc feature (like SSL support or IPV6 support).[br]
+ The returned value may be assigned to a dictionary too: it will be used to simulate an array.[br]
+ The form with the [test_feature] parameter returns true if and only if [test_feature] is available.[br]
+ @examples:
+ [example]
+ %myfeats[] = $features
+ [cmd]echo[/cmd] %myfeats[]
+ %i = %myfeats[]#
+ [cmd]while[/cmd](%i > 0)
+ {
+ [cmd]echo[/cmd] "Supporting feature %myfeats[%i]"
+ %i--;
+ }
+ [/example]
+ Nearly the same loop, just really shorter:
+ [example]
+ [cmd]foreach[/cmd](%f,$features)
+ [cmd]echo[/cmd] "Supporting feature %myfeats[%i]"
+ [/example]
+ You can test for a specific feature in the following way:
+ [example]
+ [cmd]if[/cmd]($features("SSL"))[cmd]echo[/cmd] "Yes! SSL is available";
+ [/example]
+ If used in "non-array" context it returns just a comma separated list of entries:[br]
+ [example]
+ [cmd]echo[/cmd] $features
+ [/example]
+ @seealso:
+ [fnc]$version[/fnc]
+ */
+
+ KVSCF(features)
+ {
+ QString szFeature;
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("test_feature",KVS_PT_STRING,KVS_PF_OPTIONAL,szFeature)
+ KVSCF_PARAMETERS_END
+
+ static const char * feature_array[]=
+ {
+ "IRC",
+ #ifdef COMPILE_IPV6_SUPPORT
+ "IPv6",
+ #endif
+ #ifdef COMPILE_CRYPT_SUPPORT
+ "Crypt",
+ #endif
+ #ifdef COMPILE_SSL_SUPPORT
+ "SSL",
+ #endif
+ #ifdef COMPILE_GET_INTERFACE_ADDRESS
+ "IfAddr",
+ #endif
+ #ifndef COMPILE_NO_IPC
+ "IPC",
+ #endif
+ #ifdef COMPILE_KDE_SUPPORT
+ "KDE",
+ #endif
+ #ifdef COMPILE_OSS_SUPPORT
+ "OSS",
+ #endif
+ #ifdef COMPILE_ARTS_SUPPORT
+ "ARTS",
+ #endif
+ #ifdef COMPILE_ESD_SUPPORT
+ "ESD",
+ #endif
+ #ifdef COMPILE_AUDIOFILE_SUPPORT
+ "Audiofile",
+ #endif
+ #ifdef COMPILE_PSEUDO_TRANSPARENCY
+ "Transparency",
+ #endif
+ #ifdef COMPILE_ix86_ASM
+ "ix86-ASM",
+ #endif
+ #ifdef COMPILE_SCRIPTTOOLBAR
+ "ScriptToolBar",
+ #endif // COMPILE_SCRIPTTOOLBAR
+ #ifdef COMPILE_USE_QT4
+ "Qt4",
+ #else
+ "Qt3",
+ #endif
+ #ifdef COMPILE_NEW_KVS
+ "KVS",
+ #endif
+ 0
+ };
+
+ if(!szFeature.isEmpty())
+ {
+ for(int i=0;feature_array[i];i++)
+ {
+ if(KviQString::equalCI(feature_array[i],szFeature))
+ {
+ KVSCF_pRetBuffer->setBoolean(true);
+ return true;
+ }
+ }
+ KVSCF_pRetBuffer->setBoolean(false);
+ } else {
+ KviKvsArray * a = new KviKvsArray();
+ int id = 0;
+ for(int i=0;feature_array[i];i++)a->set(i,new KviKvsVariant(QString(feature_array[i])));
+ KVSCF_pRetBuffer->setArray(a);
+ }
+
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: firstconnectedconsole
+ @type:
+ function
+ @title:
+ $firstConnectedConsole
+ @short:
+ Returns the window id of the first connected console
+ @syntax:
+ <uint> $firstConnectedConsole()
+ @description:
+ Returns the window id of the first connected console
+ or 0 if no console is actually connected.
+ */
+
+ KVSCF(firstConnectedConsole)
+ {
+ KviConsole * c = g_pApp->topmostConnectedConsole();
+ // FIXME: The window id's should be numeric!!!
+ KVSCF_pRetBuffer->setString(c ? c->id() : "0");
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: flatten
+ @type:
+ function
+ @title:
+ $flatten
+ @short:
+ Returns a flattened array of items
+ @syntax:
+ <array> $flatten(<data1:variant>[,<data2:variant>[,...]])
+ @description:
+ Returns an array of items built from the passed arguments
+ with the following rules:[br]
+ [ul]
+ [li]If an argument is a scalar value then the argument itself
+ is appended to the result.[/li]
+ [li]If an argument is an array then each contained item
+ is appended to the result.[/li]
+ [li]If an argument is a hash then each contained value
+ is appended to the result.[/li]
+ [/ul]
+ A simple example of usage is to merge N arrays into a new one.
+ (Please note that for merging one array into another the
+ [doc:arrayconcatenation]<+ operator[/doc] is more efficient).
+ */
+
+ KVSCF(flatten)
+ {
+ KviKvsArray * a = new KviKvsArray();
+ KVSCF_pRetBuffer->setArray(a);
+ unsigned int uIdx = 0;
+ for(KviKvsVariant * v = KVSCF_pParams->first();v;v = KVSCF_pParams->next())
+ {
+ switch(v->type())
+ {
+ case KviKvsVariantData::Array:
+ {
+ KviKvsArray * z = v->array();
+ unsigned int uSize = z->size();
+ unsigned int uIdx2 = 0;
+ while(uIdx2 < uSize)
+ {
+ KviKvsVariant * pInternal = z->at(uIdx2);
+ if(pInternal)
+ a->set(uIdx,new KviKvsVariant(*pInternal));
+ // else
+ // don't set anything: just leave empty entry (nothing)
+ uIdx++;
+ uIdx2++;
+ }
+ }
+ break;
+ case KviKvsVariantData::Hash:
+ {
+ KviKvsHash * h = v->hash();
+ KviKvsHashIterator it(*(h->dict()));
+ while(KviKvsVariant * pInternal = it.current())
+ {
+ a->set(uIdx,new KviKvsVariant(*pInternal));
+ uIdx++;
+ ++it;
+ }
+ }
+ break;
+ default:
+ a->set(uIdx,new KviKvsVariant(*v));
+ uIdx++;
+ break;
+ }
+ }
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: fmtlink
+ @type:
+ function
+ @title:
+ $fmtlink
+ @short:
+ Returns a formatted link buffer
+ @syntax:
+ <string> $fmtlink(<link_text:string>,<double_click_command:string>[,<tooltip_text:string>])
+ @description:
+ Returns a link formatted for the [cmd]echo[/cmd] command.[br]
+ If you pass the returned string to the echo command, the string will be displayed
+ as a link and will be highlighted when the user moves the mouse over it.[br]
+ If the user will leave the mouse for a few seconds over the link, the <tooltip_text>
+ will be displayed in a small tooltip window. If <tooltip_text> is not given,
+ then no tooltip will be shown.[br]
+ The <double_click_command> will be executed when the user will double click on the link.[br]
+ Please remember that if <double_click_command> contains identifiers
+ that must be evaluated at double-click time, you MUST escape them in the $fmtlink() call
+ to prevent the evaluation.[br]
+ You might also take a look at [doc:escape_sequences]the escape sequences documentation[/doc]
+ to learn more about how the links are implemented and how to create more powerful links (add
+ right and middle button actions, use predefined kvirc links etc...)
+ @seealso:
+ [doc:escape_sequences]the escape sequences documentation[/doc]
+ */
+
+ KVSCF(fmtlink)
+ {
+ QString szLinkText,szCmd,szToolTip;
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("link_text",KVS_PT_NONEMPTYSTRING,0,szLinkText)
+ KVSCF_PARAMETER("double_click_command",KVS_PT_STRING,0,szCmd)
+ KVSCF_PARAMETER("tooltip_text",KVS_PT_STRING,KVS_PF_OPTIONAL,szToolTip)
+ KVSCF_PARAMETERS_END
+
+ QString szPart;
+ KviQString::sprintf(szPart,"[!dbl]%Q",&szCmd);
+ if(!szToolTip.isEmpty())KviQString::appendFormatted(szPart,"[!txt]%Q",&szToolTip);
+ QString szLink;
+ KviQString::sprintf(szLink,"\r!%Q\r%Q\r",&szPart,&szLinkText);
+ KVSCF_pRetBuffer->setString(szLink);
+ return true;
+ }
+
+};
+
diff --git a/src/kvirc/kvs/kvi_kvs_corefunctions_gl.cpp b/src/kvirc/kvs/kvi_kvs_corefunctions_gl.cpp
new file mode 100644
index 00000000..ce8728d1
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_corefunctions_gl.cpp
@@ -0,0 +1,888 @@
+//=============================================================================
+//
+// File : kvi_kvs_corefunctions_gl.cpp
+// Created on Fri 31 Oct 2003 01:52:04 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003-2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_corefunctions.h"
+
+#include "kvi_kvs_kernel.h"
+
+#include "kvi_kvs_timermanager.h"
+#include "kvi_kvs_arraycast.h"
+#include "kvi_locale.h"
+#include "kvi_input.h"
+#include "kvi_app.h"
+#include "kvi_channel.h"
+#include "kvi_console.h"
+#include "kvi_iconmanager.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_frame.h"
+#include "kvi_time.h"
+#include "kvi_kvs_eventmanager.h"
+#include "kvi_kvs_eventhandler.h"
+#include <qregexp.h>
+#include "kvi_lagmeter.h"
+
+namespace KviKvsCoreFunctions
+{
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: hash
+ @type:
+ function
+ @title:
+ $hash
+ @short:
+ Explicitly creates a hash
+ @syntax:
+ <hash> $hash([<key:string>,<value:variant>,[<key:string>,<value:variant>]],...)
+ @description:
+ Returns a hash with the specified items. Each <value> is indexed by the preceeding <key>.
+ This is just an explicit way of creating a hash with a defined set of items,
+ useful for increasing readability.
+ @examples:
+ [example]
+ [cmd]alias[/cmd](test){ [cmd]return[/cmd] $hash(1,X,2,Y,3,Z); };
+ %x = $test();
+ [cmd]foreach[/cmd](%y,%x)
+ {
+ [cmd]echo[/cmd] %y;
+ }
+ [cmd]foreach[/cmd](%y,[fnc]$keys[/fnc](%x))
+ {
+ [cmd]echo[/cmd] %y
+ }
+ [/example]
+ @seealso:
+ [fnc]$array[/fnc]
+ */
+
+ KVSCF(hash)
+ {
+#ifdef COMPILE_NEW_KVS
+ KviKvsHash * a = new KviKvsHash();
+
+ for(KviKvsVariant * key = KVSCF_pParams->first();key;key = KVSCF_pParams->next())
+ {
+ KviKvsVariant * val = KVSCF_pParams->next();
+ if(!val)break;
+ QString sz;
+ key->asString(sz);
+ a->set(sz,new KviKvsVariant(*val));
+ }
+
+ KVSCF_pRetBuffer->setHash(a);
+#endif
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: hextoAscii
+ @type:
+ function
+ @title:
+ $hexToAscii
+ @short:
+ Returns a decoded hex string
+ @syntax:
+ $hexToAscii(<hex_encoded_string>)
+ @description:
+ Decodes the <hex_encoded_string> to its ASCII representation.
+ @examples:
+ [example]
+ [cmd]echo[/cmd] $hexToAscii(6B76697263)
+ [/example]
+ @seealso:
+ [fnc]$asciiToHex[/fnc]
+ */
+
+ KVSCF(hexToAscii)
+ {
+ QString szHex;
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("hex_encoded_string",KVS_PT_STRING,0,szHex)
+ KVSCF_PARAMETERS_END
+
+ KviStr tmp1(szHex);
+ char * buf;
+ int len = tmp1.hexToBuffer(&buf,true);
+ KVSCF_pRetBuffer->setString(QString(KviQCString(buf,len+1)));
+ KviStr::freeBuffer(buf);
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: hostname
+ @type:
+ function
+ @title:
+ $hostname
+ @short:
+ Returns the hostname of the specified user
+ @syntax:
+ <string> $hostname(<nickname:string>)
+ @description:
+ Returns the hostname of the specified IRC user IF it is known.[br]
+ The hostname is known if [fnc]$isWellKnown[/fnc] returns 1.[br]
+ The hostname is generally known if the user is on a channel with you
+ or has an open query with you.[br]
+ Detailed explaination:[br]
+ KVIrc has an internal database of users that are currently
+ visible by *this client*: this includes users on open channels
+ and queries.[br] The other IRC users are NOT in the database:
+ this means that KVIrc knows NOTHING about them and can't return
+ any information immediately. In this case this function will return
+ an EMPTY string.[br]
+ If a user is in the database, at least his nickname is known.[br]
+ The username and hostname are known only if the server provides that information
+ spontaneously or after a KVIrc request.[br]
+ KVIrc requests user information for all the users in open queries
+ and channels. This information takes some time to be retrieved,
+ in this interval of time KVIrc knows only the user's nickname.
+ This function will return the string "*" in this case.[br]
+ @seealso:
+ [fnc]$isWellKnown[/fnc], [fnc]$username[/fnc], [cmd]awhois[/cmd]
+ */
+
+ KVSCF(hostname)
+ {
+ QString szNick;
+
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("nick",KVS_PT_NONEMPTYSTRING,0,szNick)
+ KVSCF_PARAMETERS_END
+
+ if(KVSCF_pContext->window()->console())
+ {
+ if(KVSCF_pContext->window()->console()->isConnected())
+ {
+ KviIrcUserEntry * e = KVSCF_pContext->window()->connection()->userDataBase()->find(szNick);
+ if(e)
+ {
+ KVSCF_pRetBuffer->setString(e->host());
+ return true;
+ }
+ }
+ }
+
+ KVSCF_pRetBuffer->setNothing();
+ return true;
+ }
+
+ //-------------------------------------------------
+ /*
+ @doc: lag
+ @type:
+ function
+ @title:
+ $lag
+ @short:
+ Returns the lag on the current server
+ @syntax:
+ <integer> lag
+ @description:
+ This function returns the lag in the current server, in milliseconds.[br]
+ */
+
+ KVSCF(lag)
+ {
+ if(!KVSCF_pContext->window()->console()) return KVSCF_pContext->errorNoIrcContext();
+ if(!KVSCF_pContext->window()->console()->connection()) return KVSCF_pContext->warningNoIrcConnection();
+ if(!KVSCF_pContext->window()->console()->connection()->lagMeter())
+ {
+ KVSCF_pContext->warning(__tr2qs("Lag meter was not enabled"));
+ return false;
+ }
+
+ KVSCF_pRetBuffer->setInteger( KVSCF_pContext->window()->console()->connection()->lagMeter()->lag());
+ return true;
+ }
+ /////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: hptimestamp
+ @type:
+ function
+ @title:
+ $hptimestamp
+ @short:
+ Returns a high precision timestamp
+ @syntax:
+ <float> $hptimestamp
+ @description:
+ Returns a high precision timestamp as a floaint point value.
+ The timestamp rappresent the number of seconds elapsed since
+ a certain moment in the past. The number of seconds
+ contains a "high precision" fractional part. The "certain moment" definition
+ depends on the platform KVIrc is executed. This means that
+ this timestamp is totally useless to rappresent a time value
+ but is useful to compute time intervals with sub-second precision.
+ @examples:
+ [example]
+ %tmp = $hptimestamp
+ [cmd]echo[/cmd] $($hptimestamp - %tmp)
+ [/example]
+ @seealso:
+ [fnc]$unixTime[/fnc], [fnc]$date[/fnc]
+ */
+
+ KVSCF(hptimestamp)
+ {
+ struct timeval tv;
+ kvi_gettimeofday(&tv,0);
+ kvs_real_t dTimestamp = (kvs_real_t)(tv.tv_sec);
+ dTimestamp += (((kvs_real_t)(tv.tv_usec)) / 1000000.0);
+ KVSCF_pRetBuffer->setReal(dTimestamp);
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: icon
+ @type:
+ function
+ @title:
+ $icon
+ @short:
+ Returns the ID of an icon
+ @syntax:
+ <integer> $icon(<iconname:string>)
+ @description:
+ Returns the ID of the icon <iconname>.
+ You should always use this function where an <image_id> is required
+ and you want to use an internal icon.
+ See [fnc]$iconname[/fnc] for a list of the icon names supported by kvirc.[br]
+ @examples:
+ [example]
+ [cmd]echo[/cmd] $icon(linux)
+ [/example]
+ @seealso:
+ [fnc]$iconName[/fnc]
+ */
+
+ KVSCF(icon)
+ {
+ QString szName;
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("iconName",KVS_PT_NONEMPTYSTRING,0,szName)
+ KVSCF_PARAMETERS_END
+
+ KVSCF_pRetBuffer->setInteger(g_pIconManager->getSmallIconIdFromName(szName));
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: iconname
+ @type:
+ function
+ @title:
+ $iconname
+ @short:
+ Returns the name of an icon
+ @syntax:
+ $iconname(<iconid>)
+ @description:
+ Returns the name of a builtin icon given an <iconid>.
+ The <iconid> is returned by the function [fnc]$icon[/fnc].
+ If the <iconid> is not valid, an empty name is returned.[br]
+ The following code will list all the available icon names:[br]
+ [example]
+ %i = 0
+ [cmd]do[/cmd] {
+ %name = $iconname(%i)
+ echo The icon by ID %i is named %name
+ %i++
+ } [cmd]while[/cmd](%name != "")
+ [/example]
+ @examples:
+ [example]
+ [cmd]echo[/cmd] $iconname(24)
+ [cmd]echo[/cmd] $iconname([fnc]$icon[/fnc](linux))
+ [/example]
+ @seealso:
+ [fnc]$iconName[/fnc]
+ */
+
+ KVSCF(iconName)
+ {
+ kvs_uint_t uIco;
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("iconid",KVS_PT_UINT,0,uIco)
+ KVSCF_PARAMETERS_END
+
+ if(uIco < KVI_NUM_SMALL_ICONS)
+ {
+ KVSCF_pRetBuffer->setString(g_pIconManager->getSmallIconName(uIco));
+ } else {
+ KVSCF_pRetBuffer->setNothing();
+ }
+ return true;
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: integer
+ @type:
+ function
+ @title:
+ $integer
+ @short:
+ Casts a variable to an integer
+ @syntax:
+ <integer> $integer(<data:variant>)
+ @description:
+ Forces <data> to be an integer data type with the following
+ semantics:[br]
+ [ul]
+ [li]If <data> is an integer, <data> itself is returned.[/li]
+ [li]If <data> is a boolean, its numeric value is returned (either 1 or 0).[/li]
+ [li]If <data> is a real, its integer part is returned.[/li]
+ [li]If <data> is an array, the count of its items is returned.[/li]
+ [li]If <data> is a hash, the count of its items is returned.[/li]
+ [li]If <data> is a string, its length is returned.[/li]
+ [li]If <data> is an object, 0 is returned if the reference is null (invalid) and 1 otherwise[/li]
+ [/ul]
+ This function is similar to the C (int) cast and is internally
+ aliased to [fnc]$int[/fnc]() too.
+ Note that since KVIrc does most of the casting work automatically
+ you shouldn't need to use this function.
+ @seealso:
+ [fnc]$real[/fnc]
+ [fnc]$boolean[/fnc]
+ */
+
+ /*
+ @doc: int
+ @type:
+ function
+ @title:
+ $int
+ @short:
+ Casts a variable to an integer
+ @syntax:
+ <integer> $int(<data:variant>)
+ @description:
+ This is an internal alias to [fnc]$integer[/fnc]().
+ @seealso:
+ [fnc]$real[/fnc]
+ [fnc]$boolean[/fnc]
+ */
+
+ KVSCF(integer)
+ {
+ KviKvsVariant * v;
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("data",KVS_PT_VARIANT,0,v)
+ KVSCF_PARAMETERS_END
+
+ kvs_int_t iVal;
+ v->castToInteger(iVal);
+ KVSCF_pRetBuffer->setInteger(iVal);
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: isMainWindowActive
+ @type:
+ function
+ @title:
+ $isMainWindowActive
+ @short:
+ Checks if main KVirc window is active
+ @syntax:
+ <boolean> $isMainWindowActive()
+ @description:
+ Returns true if the KVIrc's window is currently
+ the active window on the current desktop.
+ */
+
+ KVSCF(isMainWindowActive)
+ {
+ KVSCF_pRetBuffer->setBoolean(g_pFrame->isActiveWindow());
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: isMainWindowMinimized
+ @type:
+ function
+ @title:
+ $isMainWindowMinimized
+ @short:
+ Checks if main KVirc window is minimized
+ @syntax:
+ <boolean> $isMainWindowMinimized()
+ @description:
+ Returns true if main KVirc window is minimized and false otherwise.
+ */
+
+ KVSCF(isMainWindowMinimized)
+ {
+ KVSCF_pRetBuffer->setBoolean(g_pFrame->isMinimized());
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: isempty
+ @type:
+ function
+ @title:
+ $isEmpty
+ @short:
+ Checks if a variable is set (empty or non empty)
+ @syntax:
+ <boolean> $isEmpty(<data:variant>)
+ @description:
+ Returns 0 if <data> is actually set to some non-empty value
+ and 1 otherwise. Since KVIrc treats unset variables as empty
+ ones then this function is the exact opposite of [fnc]$isSet[/fnc].
+ @seealso:
+ [fnc]$isSet[/fnc]
+ */
+
+ KVSCF(isEmpty)
+ {
+#ifdef COMPILE_NEW_KVS
+ KviKvsVariant * v;
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("data",KVS_PT_VARIANT,0,v)
+ KVSCF_PARAMETERS_END
+
+ KVSCF_pRetBuffer->setBoolean(v->isEmpty());
+#endif
+ return true;
+ }
+ //FIXME: documentation
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: iseventenabled
+ @type:
+ function
+ @title:
+ $isEventEnabled
+ @short:
+ Checks if an event enabled
+ @syntax:
+ <boolean> $isEventEnabled(<event_name:string>,<handler_name:string>)
+ @description:
+ Returns 1 if the event handler enabled
+ */
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ KVSCF(isEventEnabled)
+ {
+ QString szEventName,szHandlerName;
+ KviKvsScriptEventHandler *h=0;
+
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("event_name",KVS_PT_NONEMPTYSTRING,0,szEventName)
+ KVSCF_PARAMETER("handler_name",KVS_PT_NONEMPTYSTRING,0,szHandlerName)
+ KVSCF_PARAMETERS_END
+
+ bool bOk;
+ int iNumber = szEventName.toInt(&bOk);
+ bool bIsRaw = (bOk && (iNumber >= 0) && (iNumber < 1000));
+
+ if(bIsRaw)
+ {
+ if(!KviKvsEventManager::instance()->isValidRawEvent(iNumber))
+ {
+ KVSCF_pContext->warning(__tr2qs("No such event (%Q)"),&szEventName);
+ } else {
+ h=KviKvsEventManager::instance()->findScriptRawHandler(iNumber,szHandlerName);
+ }
+ } else {
+ iNumber = KviKvsEventManager::instance()->findAppEventIndexByName(szEventName);
+ if(!KviKvsEventManager::instance()->isValidAppEvent(iNumber))
+ {
+ KVSCF_pContext->warning(__tr2qs("No such event (%Q)"),&szEventName);
+ } else {
+ h=KviKvsEventManager::instance()->findScriptAppHandler(iNumber,szHandlerName);
+ }
+ }
+ if(h)
+ KVSCF_pRetBuffer->setBoolean(h->isEnabled());
+ else
+ KVSCF_pContext->warning(__tr2qs("No such event handler (%Q) for event %Q"),&szHandlerName,&szEventName);
+
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: isnumeric
+ @type:
+ function
+ @title:
+ $isNumeric
+ @syntax:
+ <boolean> $isNumeric(<data:variant>)
+ @short:
+ Finds whether a variable contains a rappresentation of a number
+ @description:
+ Returns 1 if the <data> is an integer or a real number, 0 otherwise.
+ */
+
+ KVSCF(isNumeric)
+ {
+#ifdef COMPILE_NEW_KVS
+ KviKvsVariant * v;
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("data",KVS_PT_VARIANT,0,v)
+ KVSCF_PARAMETERS_END
+
+ KviKvsNumber n;
+ KVSCF_pRetBuffer->setBoolean(v->asNumber(n));
+#endif
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: isset
+ @type:
+ function
+ @title:
+ $isSet
+ @short:
+ Checks if a variable is set (non-empty)
+ @syntax:
+ <boolean> $isSet(<data:variant>)
+ @description:
+ Returns 1 if <data> is actually set to some non-empty value
+ and 0 otherwise. If <data> is a variable , then this function
+ simply checks if the variable is set. If <data> is a constant
+ then this function checks if the constant is non empty.
+ Since KVIrc treats empty strings as "unset" values then
+ this function could be also called "isNonEmpty" and it is
+ the perfect opposite of [fnc]$isEmpty[/fnc]
+ @seealso:
+ [fnc]$isEmpty[/fnc], [cmd]unset[/cmd]
+ */
+
+ KVSCF(isSet)
+ {
+#ifdef COMPILE_NEW_KVS
+ KviKvsVariant * v;
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("data",KVS_PT_VARIANT,0,v)
+ KVSCF_PARAMETERS_END
+
+ KVSCF_pRetBuffer->setBoolean(!v->isEmpty());
+#endif
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: istimer
+ @type:
+ function
+ @title:
+ $isTimer
+ @short:
+ Checks for a timer existence
+ @syntax:
+ <boolean> $istimer(<name:string>)
+ @description:
+ Returns 1 if the timer named <name> is actually running, else 0
+ @seealso:
+ [cmd]timer[/cmd], [cmd]killtimer[/cmd]
+ */
+
+ KVSCF(isTimer)
+ {
+ QString szName;
+
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("timerName",KVS_PT_NONEMPTYSTRING,0,szName)
+ KVSCF_PARAMETERS_END
+ KVSCF_pRetBuffer->setBoolean(KviKvsTimerManager::instance()->timerExists(szName));
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: iswellknown
+ @type:
+ function
+ @title:
+ $isWellKnown
+ @short:
+ Returns $true if the specified user is well known
+ @syntax:
+ <bool> $isWellKnown(<nickname:string>)
+ @description:
+ Returns 1 if KVIrc has the basic user information about the specified <nickname>.[br]
+ The basic information include the username and hostname.[br]
+ This is almost always true if the user is on a channel with you or
+ you have an open query with him.[br]
+ If $isWellKnown returns 0, [fnc]$username[/fnc] and [fnc]$hostname[/fnc]
+ will return empty strings.[br]
+ In this case you must use [cmd]awhois[/cmd] to obtain the user basic information.[br]
+ */
+
+ KVSCF(isWellKnown)
+ {
+ QString szNick;
+
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("nick",KVS_PT_NONEMPTYSTRING,0,szNick)
+ KVSCF_PARAMETERS_END
+
+ if(KVSCF_pContext->window()->console())
+ {
+ if(KVSCF_pContext->window()->console()->isConnected())
+ {
+ KviIrcUserEntry * e = KVSCF_pContext->window()->connection()->userDataBase()->find(szNick);
+ if(e)
+ {
+ KVSCF_pRetBuffer->setBoolean(e->hasHost() && e->hasUser());
+ return true;
+ }
+ }
+ }
+
+ KVSCF_pRetBuffer->setBoolean(false);
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: k
+ @type:
+ function
+ @title:
+ $k
+ @short:
+ Returns the COLOR mIRC control character
+ @syntax:
+ <string> $k(<foreground:integer>[,<background:integer>])
+ <string> $k
+ @description:
+ Returns the COLOR mIRC control character (Qt::CTRL+K).[br]
+ If <foreground> and <background> are passed, a standard mIRC
+ color escape is returned.[br]
+ @seealso:
+ [fnc]$b[/fnc]
+ */
+
+ KVSCF(k)
+ {
+ kvs_uint_t iFore,iBack;
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("foreground",KVS_PT_UINT,KVS_PF_OPTIONAL,iFore)
+ KVSCF_PARAMETER("background",KVS_PT_UINT,KVS_PF_OPTIONAL,iBack)
+ KVSCF_PARAMETERS_END
+
+ QString szRet = QChar(KVI_TEXT_COLOR);
+ if(KVSCF_pParams->count() > 0)
+ {
+ KviQString::appendFormatted(szRet,"%u",iFore);
+ if(KVSCF_pParams->count() > 1)
+ KviQString::appendFormatted(szRet,",%u",iBack);
+ }
+ KVSCF_pRetBuffer->setString(szRet);
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: keys
+ @type:
+ function
+ @title:
+ $keys
+ @short:
+ Returns the array of keys of a hash
+ @syntax:
+ <array> $keys(<hash_value:hash>)
+ @description:
+ Returns an array with the keys of the <hash> parameter.
+ <hash> must be obviously a hash (or eventually an empty variable
+ that is treated as an empty hash).
+ @seealso:
+ [cmd]foreach[/cmd]
+ */
+
+ KVSCF(keys)
+ {
+#ifdef COMPILE_NEW_KVS
+ KviKvsHash * pHash;
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("hash",KVS_PT_HASH,0,pHash)
+ KVSCF_PARAMETERS_END
+
+ KviKvsArray * a = new KviKvsArray();
+ kvs_int_t idx = 0;
+ KviKvsHashIterator it(*(pHash->dict()));
+ while(it.current())
+ {
+ a->set(idx,new KviKvsVariant(it.currentKey()));
+ idx++;
+ ++it;
+ }
+ KVSCF_pRetBuffer->setArray(a);
+#endif
+ return true;
+ }
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: lang
+ @type:
+ function
+ @title:
+ $lang
+ @short:
+ Returns name of currently used language
+ @syntax:
+ <string> $lang([<type:string>])
+ @description:
+ Returns the short name of currently used language
+ Type <type> should be one of: [br]
+ "full" - returns full locale name, such as ru_RU.UTF-8 (default)
+ "lang" - return language name, such as "ru_RU"
+ "short" - returns only language group such as "ru"
+ */
+
+ KVSCF(lang)
+ {
+ QString szType;
+
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("type",KVS_PT_NONEMPTYSTRING,KVS_PF_OPTIONAL,szType)
+ KVSCF_PARAMETERS_END
+
+ QString szLocale(KviLocale::localeName().ptr());
+ if(szType=="lang") KVSCF_pRetBuffer->setString(szLocale.left(5));
+ else if(szType=="short") KVSCF_pRetBuffer->setString(szLocale.left(2));
+ else KVSCF_pRetBuffer->setString(szLocale);
+ return true;
+ }
+
+
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: length
+ @type:
+ function
+ @title:
+ $length
+ @short:
+ Returns the length of a variable
+ @syntax:
+ <integer> $length(<value:variant>)
+ @description:
+ When <value> is an array or a hash, it returns the number
+ of its elements. When <value> is an object reference it returns 0.
+ In all the other cases <value> is interpreted
+ as a string and its length is returned.
+ @seealso:
+ [fnc]$str.len[/fnc]
+ */
+
+ KVSCF(length)
+ {
+ KviKvsVariant * pVar;
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("value",KVS_PT_VARIANT,0,pVar)
+ KVSCF_PARAMETERS_END
+
+ switch(pVar->type())
+ {
+ case KviKvsVariantData::Array:
+ KVSCF_pRetBuffer->setInteger(pVar->array()->size());
+ break;
+ case KviKvsVariantData::Hash:
+ KVSCF_pRetBuffer->setInteger(pVar->hash()->size());
+ break;
+ case KviKvsVariantData::HObject:
+ KVSCF_pRetBuffer->setInteger(0);
+ break;
+ default:
+ {
+ QString tmp;
+ pVar->asString(tmp);
+ KVSCF_pRetBuffer->setInteger(tmp.length());
+ }
+ break;
+ }
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: lf
+ @type:
+ function
+ @title:
+ $lf
+ @short:
+ Returns a line feed character
+ @syntax:
+ <string> $lf
+ @description:
+ Returns a line feed character
+ @seealso:
+ [fnc]$cr[/fnc], [fnc]$ascii[/fnc], [fnc]$char[/fnc]
+ */
+
+ KVSCF(lf)
+ {
+ KVSCF_pRetBuffer->setString(QString(QChar('\n')));
+ return true;
+ }
+
+};
+
diff --git a/src/kvirc/kvs/kvi_kvs_corefunctions_mr.cpp b/src/kvirc/kvs/kvi_kvs_corefunctions_mr.cpp
new file mode 100644
index 00000000..6316f1d7
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_corefunctions_mr.cpp
@@ -0,0 +1,679 @@
+//=============================================================================
+//
+// File : kvi_kvs_corefunctions_mr.cpp
+// Created on Fri 31 Oct 2003 01:52:04 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_corefunctions.h"
+
+#include "kvi_kvs_kernel.h"
+#include "kvi_kvs_arraycast.h"
+#include "kvi_kvs_object_controller.h"
+
+#include "kvi_locale.h"
+#include "kvi_ircconnection.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_options.h"
+#include "kvi_console.h"
+#include "kvi_ircuserdb.h"
+#include "kvi_ircmask.h"
+#include "kvi_socket.h"
+#include "kvi_app.h"
+#include "kvi_query.h"
+
+#include <stdlib.h> // rand & srand
+
+namespace KviKvsCoreFunctions
+{
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: mask
+ @type:
+ function
+ @title:
+ $mask
+ @short:
+ Retrieves the host mask of a user
+ @syntax:
+ $mask[(<nickname>[,<mask_type>])]
+ @description:
+ Returns the specified type of mask for the user with <nickname>.[br]
+ If the host or username are not known, the mask may contain less information
+ than requested.[br]
+ If the <nickname> is not given it is assumed to be the current nickname.[br]
+ If <mask_type> is not given or is invalid, it is assumed to be 0.[br]
+ Available mask types:[br]
+ 0 : nick!user@machine.host.top (nick!user@XXX.XXX.XXX.XXX) (default)[br]
+ 1 : nick!user@*.abc.host.top (nick!user@XXX.XXX.XXX.*)[br]
+ 2 : nick!user@*[br]
+ 3 : nick!*@machine.host.top (nick!user@XXX.XXX.XXX.XXX)[br]
+ 4 : nick!*@*.abc.host.top (nick!user@XXX.XXX.XXX.*)[br]
+ 5 : nick!*@*[br]
+ 6 : *!user@machine.host.top (*!user@XXX.XXX.XXX.XX)[br]
+ 7 : *!user@*.abc.host.top (*!user@XXX.XXX.XXX.*)[br]
+ 8 : *!user@*[br]
+ 9 : *!*@machine.host.top (*!*@XXX.XXX.XXX.XXX)[br]
+ 10: *!*@*.abc.host.top (*!*@XXX.XXX.XXX.*)[br]
+ 11: nick!*user@machine.host.top (nick!*user@XXX.XXX.XXX.XXX)[br]
+ 12: nick!*user@*.abc.host.top (nick!*user@XXX.XXX.XXX.*)[br]
+ 13: nick!*user@*[br]
+ 14: *!*user@machine.host.top (*!*user@XXX.XXX.XXX.XXX)[br]
+ 15: *!*user@*.abc.host.top (*!*user@XXX.XXX.XXX.*)[br]
+ 16: *!*user@*[br]
+ 17: nick!~user@*.host.top (nick!~user@XXX.XXX.*)[br]
+ 18: nick!*@*.host.top (nick!*@XXX.XXX.*)[br]
+ 19: *!~user@*.host.top (*!~user@XXX.XXX.*)[br]
+ 20: nick!*user@*.host.top (nick!*user@XXX.XXX.*)[br]
+ 21: *!*user@*.host.top (*!user@*XXX.XXX.*)[br]
+ 22: nick!~user@*.host.top (nick!~user@XXX.XXX.*)[br]
+ 23: nick!*@*.host.top (nick!*@XXX.XXX.*)[br]
+ 24: *!~user@*.host.top (*!~user@XXX.XXX.*)[br]
+ 25: nick!*user@*.host.top (nick!*user@XXX.XXX.*)[br]
+ 26: *!*user@*.host.top (*!user@*XXX.XXX.*)[br]
+ If some data is missing, these types may change:[br]
+ For example, if the hostname is missing, the mask type 3 or 4 may be reduced to type 5.[br]
+ If the user with <nickname> is not found in the current IRC context user database,
+ an empty string is returned.[br]
+ The masks 22-26 are the smart versions of the masks 17-21 that try take care of masked ip addresses
+ in the form xxx.xxx.INVALID-TOP-MASK. If a masked ip address is found then
+ the XXX.XXX.* or XXX.* host mask is returned instead of the (wrong) *.INVALID-TOP-MASK
+ @examples:
+ @seealso:
+ */
+
+ KVSCF(mask)
+ {
+ QString szNick;
+ kvs_uint_t maskType;
+
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("nickname",KVS_PT_STRING,KVS_PF_OPTIONAL,szNick)
+ KVSCF_PARAMETER("maskType",KVS_PT_UINT,KVS_PF_OPTIONAL,maskType)
+ KVSCF_PARAMETERS_END
+
+ if(maskType > 26) maskType = 0;
+
+ if(KVSCF_pContext->window()->console())
+ {
+ if(KVSCF_pContext->window()->console()->isConnected())
+ {
+ KviIrcUserEntry * e = KVSCF_pContext->window()->connection()->userDataBase()->find(szNick.isEmpty() ? KVSCF_pContext->window()->connection()->currentNickName() : szNick);
+ if(e)
+ {
+ KviIrcMask u;
+ u.setNick(szNick);
+ u.setUsername(e->user());
+ u.setHost(e->host());
+
+ QString tmp;
+ u.mask(tmp,(KviIrcMask::MaskType)maskType);
+ KVSCF_pRetBuffer->setString(tmp);
+ return true;
+ }
+ }
+ }
+ KVSCF_pRetBuffer->setNothing();
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: me
+ @type:
+ function
+ @title:
+ $me
+ @short:
+ Returns the current nickname
+ @syntax:
+ <string> $me[(<irc_context_id:uint>)]
+ @description:
+ Returns the current nickname used in the specified IRC context.[br]
+ If no <irc_context_id> is specified, the current IRC context is used.[br]
+ If you are not connected to a server, this function will return a null string.[br]
+ If the current window is a DCC chat and no irc_context is specified,
+ the local nickname is returned.[br]
+ If the current window does not belong to any IRC context, no irc_context_id
+ is specified, and the current window is not a DCC chat, a warning is printed.[br]
+ */
+
+ KVSCF(me)
+ {
+ kvs_uint_t uCntx;
+
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("irc_context_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uCntx)
+ KVSCF_PARAMETERS_END
+
+ KviConsole * cns;
+
+ if(KVSCF_pParams->count() > 0)
+ {
+ cns = g_pApp->findConsole(uCntx);
+ if(cns)
+ {
+ if(cns->isConnected())
+ KVSCF_pRetBuffer->setString(cns->connection()->currentNickName());
+ else
+ KVSCF_pRetBuffer->setNothing();
+ } else {
+ KVSCF_pRetBuffer->setNothing();
+ }
+ } else {
+ if(KVSCF_pContext->window()->console())
+ {
+ cns = KVSCF_pContext->window()->console();
+ if(cns->isConnected())
+ KVSCF_pRetBuffer->setString(cns->connection()->currentNickName());
+ else
+ KVSCF_pRetBuffer->setNothing();
+ } else {
+ if(KVSCF_pContext->window()->type() == KVI_WINDOW_TYPE_DCCCHAT)
+ {
+ KVSCF_pRetBuffer->setString(KVSCF_pContext->window()->localNick());
+ } else {
+ KVSCF_pContext->warning(__tr2qs("This window has no associated IRC context and is not a DCC chat"));
+ KVSCF_pRetBuffer->setNothing();
+ }
+ }
+ }
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: msgtype
+ @type:
+ function
+ @title:
+ $msgtype
+ @short:
+ Returns the id of a message type color set
+ @syntax:
+ $msgtype(<message type color set name>)
+ @description:
+ Returns the id of a message type color set used by the [cmd]echo[/cmd] command.
+ You can take a look at the options dialog section related to the
+ message output to see the list of available message type names.
+ @examples:
+ [example]
+ [cmd]echo[/cmd] -i=$msgtype(Highlight) Highlighted text!
+ [/example]
+ @seealso:
+ [cmd]echo[/cmd]
+ */
+
+ KVSCF(msgtype)
+ {
+ QString szName;
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("msg_type_color_set_name",KVS_PT_NONEMPTYSTRING,0,szName)
+ KVSCF_PARAMETERS_END
+
+ KviStr tmp(szName);
+ for(int i=0;i< KVI_NUM_MSGTYPE_OPTIONS;i++)
+ {
+ if(kvi_strEqualCI(tmp.ptr(),(g_msgtypeOptionsTable[i].name + 7)))
+ {
+ KVSCF_pRetBuffer->setInteger(i);
+ return true;
+ }
+ }
+ KVSCF_pRetBuffer->setInteger(0);
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: new
+ @type:
+ function
+ @title:
+ $new
+ @short:
+ Creates a new object
+ @syntax:
+ $new(<className>,[<parentHandle> [,<name>[,<param>[,<param>[...]]]])
+ @description:
+ Creates a new instance of the object <class> with
+ the parent object <parent_id> and the specified <name>.[br]
+ <name> and <parent_id> are optional: if not specified, <name>
+ is assumed to be an empty string and <parent_id> default to 0 (parentless object).[br]
+ Please see the [doc:objects]objects documentation[/doc] for more information.[br]
+ @examples:
+ [example]
+ %myobj = $new(widget,0,pippo)
+ [/example]
+ @seealso:
+ [doc:objects]Objects documentation[/doc], [cmd]delete[/cmd]
+ */
+
+ KVSCF(newCKEYWORDWORKAROUND)
+ {
+ // prologue: parameter handling
+ QString szClassName;
+ QString szName;
+ kvs_hobject_t hParent;
+ KviKvsVariantList vList;
+
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("className",KVS_PT_NONEMPTYSTRING,0,szClassName)
+ KVSCF_PARAMETER("parentHandle",KVS_PT_HOBJECT,KVS_PF_OPTIONAL,hParent)
+ KVSCF_PARAMETER("name",KVS_PT_STRING,KVS_PF_OPTIONAL,szName)
+ KVSCF_PARAMETER("parameterList",KVS_PT_VARIANTLIST,KVS_PF_OPTIONAL,vList)
+ KVSCF_PARAMETERS_END
+
+ KviKvsObjectClass * pClass = KviKvsKernel::instance()->objectController()->lookupClass(szClassName);
+ if(!pClass)
+ {
+ KVSCF_pContext->error(__tr2qs("Class \"%Q\" is not defined"),&szClassName);
+ return false;
+ }
+
+ KviKvsObject * pParent;
+ if(hParent != (kvs_hobject_t)0)
+ {
+ pParent = KviKvsKernel::instance()->objectController()->lookupObject(hParent);
+ if(!pParent)
+ {
+ KVSCF_pContext->error(__tr2qs("The specified parent object does not exist"));
+ return false;
+ }
+ } else {
+ pParent = 0;
+ }
+
+ KviKvsObject * pObject = pClass->allocateInstance(pParent,szName,KVSCF_pContext,&vList);
+
+ // epilogue: set the return value
+ KVSCF_pRetBuffer->setHObject(pObject ? pObject->handle() : (kvs_hobject_t)0);
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: nothing
+ @type:
+ function
+ @title:
+ $nothing
+ @short:
+ Evaluates to an empty variable
+ @syntax:
+ <nothing> $nothing
+ @description:
+ Evaluates to an empty variable. This is a special value somewhat similar
+ to the [fnc]$null[/fnc] object: it is used to denote absence
+ of information. For example, a function might decide to return
+ a meaningful value when the input parameters are correct and
+ $nothing when the input parameters are wrong.
+ @seealso:
+ [fnc]$null[/fnc]
+ */
+
+ KVSCF(nothing)
+ {
+ KVSCF_pRetBuffer->setNothing();
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+
+ /*
+ @doc: null
+ @type:
+ function
+ @title:
+ $null
+ @short:
+ Evaluates to the null object handle.
+ @syntax:
+ <hobject> $null
+ @description:
+ Evaluates to the null object handle. This is a special
+ object handle that is returned by some functions.
+ Please note that writing $null is semantically equivalent to writing 0
+ or even [fnc]$nothing[/fnc] in place of the handle, but $null increases code readability.
+ @seealso:
+ [fnc]$new[/fnc], [fnc]$nothing[/fnc]
+ */
+
+ KVSCF(nullCKEYWORDWORKAROUND)
+ {
+ KVSCF_pRetBuffer->setHObject(0);
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: o
+ @type:
+ function
+ @title:
+ $o
+ @short:
+ Returns the RESET mIRC control character
+ @syntax:
+ <string> $o
+ @description:
+ Returns the RESET mIRC control character (CTRL+O).[br]
+ @seealso:
+ [fnc]$k[/fnc], [fnc]$b[/fnc], [fnc]$u[/fnc], [fnc]$r[/fnc]
+ */
+
+ KVSCF(o)
+ {
+ KVSCF_pRetBuffer->setString(QString(QChar(KVI_TEXT_RESET)));
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: option
+ @type:
+ function
+ @title:
+ $option
+ @short:
+ Returns the value of an option
+ @syntax:
+ <string> $option(<optionName:string>)
+ @description:
+ Returns the current value of the internal option named <optionName>.
+ See the [cmd]option[/cmd] command documentation for more info about options.
+ @examples:
+ [example]
+ [cmd]echo[/cmd] $option(fontIrcView)
+ [/example]
+ @seealso:
+ [cmd]option[/cmd],
+ */
+
+ KVSCF(option)
+ {
+ QString szOpt;
+ // FIXME: This should return a variant in general
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("optionName",KVS_PT_NONEMPTYSTRING,0,szOpt)
+ KVSCF_PARAMETERS_END
+ QString tmp;
+ if(g_pApp->getOptionString(szOpt,tmp))KVSCF_pRetBuffer->setString(tmp);
+ else {
+ KVSCF_pContext->warning(__tr2qs("There is no option named '%Q'"),&szOpt);
+ KVSCF_pRetBuffer->setNothing();
+ }
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: query
+ @type:
+ function
+ @title:
+ $query
+ @short:
+ Retrieves the window ID of a specified query
+ @syntax:
+ $query[(<target>[,<irc context id>])]
+ @description:
+ Returns the [b]window ID[/b] of the query that has <target>
+ in the list of targets and is bound to the connection specified by
+ <irc context id>[br]
+ If no window matches the specified target or context, and invalid
+ window ID is returned (0).[br]
+ If no <irc context id> is specified, this function looks for
+ the query in the current connection context (if any).[br]
+ If no <target> is specified, this function returns the current
+ query window ID, if executed in a query, else 0.[br]
+ @examples:
+ [example]
+ [/example]
+ @seealso:
+ [fnc]$window[/fnc],
+ [fnc]$channel[/fnc],
+ [fnc]$console[/fnc]
+ [doc:window_naming_conventions]Window naming conventions[/doc]
+ */
+
+ KVSCF(query)
+ {
+ QString szName;
+ kvs_uint_t uContextId;
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("query_name",KVS_PT_NONEMPTYSTRING,KVS_PF_OPTIONAL,szName)
+ KVSCF_PARAMETER("context_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uContextId)
+ KVSCF_PARAMETERS_END
+
+ KviWindow * wnd;
+ if(KVSCF_pParams->count() > 0)
+ {
+ if(KVSCF_pParams->count() > 1)
+ {
+ KviConsole * cons = g_pApp->findConsole(uContextId);
+ if(!cons)KVSCF_pContext->warning(__tr2qs("No such IRC context (%u)"),uContextId);
+ else {
+ if(cons->connection())
+ wnd = cons->connection()->findQuery(szName);
+ else
+ wnd = 0;
+ }
+ } else {
+ if(KVSCF_pContext->window()->connection())wnd = KVSCF_pContext->window()->connection()->findQuery(szName);
+ else {
+ if(!KVSCF_pContext->window()->console())
+ KVSCF_pContext->warning(__tr2qs("This window is not associated to an IRC context"));
+ wnd = 0;
+ }
+ }
+ } else {
+ if(KVSCF_pContext->window()->type() == KVI_WINDOW_TYPE_QUERY)wnd = KVSCF_pContext->window();
+ }
+
+ KVSCF_pRetBuffer->setInteger((kvs_int_t)(wnd ? wnd->numericId() : 0));
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: r
+ @type:
+ function
+ @title:
+ $r
+ @short:
+ Returns the REVERSE mIRC control character
+ @syntax:
+ <string> $r
+ @description:
+ Returns the REVERSE mIRC control character (CTRL+R).[br]
+ @seealso:
+ [fnc]$k[/fnc], [fnc]$b[/fnc], [fnc]$u[/fnc], [fnc]$o[/fnc]
+ */
+
+ KVSCF(r)
+ {
+ KVSCF_pRetBuffer->setString(QString(QChar(KVI_TEXT_REVERSE)));
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: rand
+ @type:
+ function
+ @title:
+ $rand
+ @short:
+ Generates a random number
+ @syntax:
+ $rand(<max>)
+ @description:
+ Returns a random integer number from 0 to max inclusive.
+ You can repeat sequences of random numbers by calling [cmd]srand[/cmd]
+ with the same seed value. If [cmd]srand[/cmd] has not been called
+ $rand is automatically seeded with value of 1.
+ If no <max> is specified, this function returns an integer between
+ 0 and RAND_MAX that is system dependant.
+ @examples:
+ [example]
+ [/example]
+ @seealso:
+ [cmd]srand[/cmd]
+ */
+
+ KVSCF(rand)
+ {
+ // prologue: parameter handling
+ kvs_uint_t uMax;
+
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("max",KVS_PT_UINT,KVS_PF_OPTIONAL,uMax)
+ KVSCF_PARAMETERS_END
+ if(KVSCF_pParams->count() > 0)
+ {
+ KVSCF_pRetBuffer->setInteger(::rand() % (uMax+1));
+ } else {
+ KVSCF_pRetBuffer->setInteger(::rand());
+ }
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: real
+ @type:
+ function
+ @title:
+ $real
+ @short:
+ Casts a variable to a real
+ @syntax:
+ <real> $real(<data:variant>)
+ @description:
+ Forces <data> to be a "real" data type with the following
+ semantics:[br]
+ [ul]
+ [li]If <data> is a real, <data> itself is returned.[/li]
+ [li]If <data> is an integer, <data> itself is returned, in its real form.[/li]
+ [li]If <data> is a boolean, its numeric value is returned (either 1.0 or 0.0).[/li]
+ [li]If <data> is an array, the count of its items is returned.[/li]
+ [li]If <data> is a hash, the count of its items is returned.[/li]
+ [li]If <data> is a string, its length is returned.[/li]
+ [li]If <data> is an object, 0.0 is returned if the reference is null (invalid) and 1.0 otherwise[/li]
+ [/ul]
+ This function is similar to the C (double) cast.[br]
+ Note that since KVIrc does most of the casting work automatically
+ you shouldn't need to use this function.
+ @seealso:
+ [fnc]$int[/fnc]
+ */
+
+ KVSCF(real)
+ {
+ KviKvsVariant * v;
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("data",KVS_PT_VARIANT,0,v)
+ KVSCF_PARAMETERS_END
+
+ kvs_real_t dVal;
+ if(v->asReal(dVal))
+ KVSCF_pRetBuffer->setReal(dVal);
+ else {
+ kvs_int_t iVal;
+ v->castToInteger(iVal);
+ KVSCF_pRetBuffer->setReal((double)iVal);
+ }
+ return true;
+ }
+
+ /*
+ @doc: receivedBytes
+ @type:
+ function
+ @title:
+ $receivedBytes
+ @short:
+ Returns total received bytes
+ @syntax:
+ <uint> $receivedBytes()
+ @description:
+ Returns total received bytes
+ @seealso:
+ [fnc]$sentBytes[/fnc]
+ */
+
+ KVSCF(receivedBytes)
+ {
+ KVSCF_pRetBuffer->setInteger(g_uIncomingTraffic);
+ return true;
+ }
+
+ /*
+ @doc: rsort
+ @type:
+ function
+ @title:
+ $rsort
+ @short:
+ Sorts an array in reverse order
+ @syntax:
+ <array> $rsort(<data:array>)
+ @description:
+ Sorts an array in descending order.
+ @seealso:
+ [fnc]$sort[/fnc]
+ */
+
+ KVSCF(rsort)
+ {
+ KviKvsArrayCast a;
+
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("data",KVS_PT_ARRAYCAST,0,a)
+ KVSCF_PARAMETERS_END
+
+ if(a.array())
+ {
+ KviKvsArray * arry = new KviKvsArray(*(a.array()));
+ arry->rsort();
+ KVSCF_pRetBuffer->setArray(arry);
+ } else {
+ KVSCF_pRetBuffer->setArray(new KviKvsArray());
+ }
+ return true;
+ }
+};
+
diff --git a/src/kvirc/kvs/kvi_kvs_corefunctions_sz.cpp b/src/kvirc/kvs/kvi_kvs_corefunctions_sz.cpp
new file mode 100644
index 00000000..64b16c0d
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_corefunctions_sz.cpp
@@ -0,0 +1,1109 @@
+//=============================================================================
+//
+// File : kvi_kvs_corefunctions_sz.cpp
+// Created on Fri 31 Oct 2003 01:52:04 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_corefunctions.h"
+
+#include "kvi_kvs_kernel.h"
+#include "kvi_kvs_arraycast.h"
+#include "kvi_kvs_object_controller.h"
+
+#include "kvi_window.h"
+#include "kvi_out.h"
+#include "kvi_locale.h"
+#include "kvi_app.h"
+#include "kvi_options.h"
+#include "kvi_channel.h"
+#include "kvi_console.h"
+#include "kvi_time.h"
+#include "kvi_ircuserdb.h"
+#include "kvi_modulemanager.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_sourcesdate.h"
+#include "kvi_socket.h"
+
+#include <stdlib.h> // rand & srand
+
+/*
+ Data types:
+
+ <variant>
+ <nothing>
+ <scalar>
+ <boolean>
+ <string>
+ <numeric>
+ <integer>
+ <real>
+ <array>
+ <hash>
+ <object>
+
+ $isEmpty(<nothing>) == $true
+
+ <nothing> == <empty string>
+ <null> == <null object>
+
+
+*/
+
+namespace KviKvsCoreFunctions
+{
+ /////////////////////////////////////////////////////////////////////////////////////////
+
+ // FIXME: #warning "THIS HAS TO WORK FOR QUERIES TOO!"
+ /*
+ @doc: selected
+ @type:
+ function
+ @title:
+ $selected
+ @short:
+ Returns the list of selected nicknames in the channel
+ @syntax:
+ <array> $selected
+ <array> $selected(<window id:string>)
+ @description:
+ The form with the <window id> parameter returns an array of the selected
+ nicknames in the channel designated by <window id>.
+ The form without parameters returns an array of the selected nicknames
+ in the current window (assuming that it is a channel),
+ thus it is equivalent to calling $selected([fnc]$window[/fnc])
+ The returned value may be assigned to a dictionary too: it will be used to simulate an array.[br]
+ In a non-array/dictionary context it returns the selected nicknames as a comma separated list.
+ @examples:
+ [example]
+ [cmd]echo[/cmd] $selected
+ [cmd]foreach[/cmd](%i,$selected)[cmd]echo[/cmd] %i
+ [/example]
+ @seealso:
+ [fnc]$window[/fnc],
+ [fnc]$channel[/fnc],
+ [doc:window_naming_conventions]Window naming conventions[/doc]
+ */
+
+ KVSCF(selected)
+ {
+ QString winId;
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("winId",KVS_PT_NONEMPTYSTRING,KVS_PF_OPTIONAL,winId)
+ KVSCF_PARAMETERS_END
+
+ KviWindow * wnd;
+ if(KVSCF_pParams->count() > 0)
+ {
+ wnd = g_pApp->findWindow(winId.utf8().data());
+ if(!wnd)
+ {
+ KVSCF_pContext->warning(__tr2qs("Window with ID '%s' not found, returning empty string"),winId.utf8().data());
+ KVSCF_pRetBuffer->setNothing();
+ return true;
+ }
+ } else {
+ wnd = KVSCF_pContext->window();
+ }
+
+ if(wnd->type() != KVI_WINDOW_TYPE_CHANNEL)
+ {
+ KVSCF_pContext->warning(__tr2qs("The specified window is not a channel"));
+ KVSCF_pRetBuffer->setNothing();
+ return true;
+ }
+
+ KviKvsArray * a = new KviKvsArray();
+
+ kvs_int_t i = 0;
+ for(QString * s = ((KviChannel *)wnd)->firstSelectedNickname();s;s = ((KviChannel *)wnd)->nextSelectedNickname())
+ {
+ a->set(i,new KviKvsVariant(*s));
+ i++;
+ }
+
+ KVSCF_pRetBuffer->setArray(a);
+ return true;
+ }
+
+
+ /*
+ @doc: sentBytes
+ @type:
+ function
+ @title:
+ $sentBytes
+ @short:
+ Returns total sent bytes
+ @syntax:
+ <uint> $sentBytes()
+ @description:
+ Returns total sent bytes
+ @seealso:
+ [fnc]$receivedBytes[/fnc]
+ */
+
+ KVSCF(sentBytes)
+ {
+ KVSCF_pRetBuffer->setInteger(g_uOutgoingTraffic);
+ return true;
+ }
+
+ /*
+ @doc: serialize
+ @type:
+ function
+ @title:
+ <string> $serialize(<data:mixed>)
+ @short:
+ Encodes variable to JSON string
+ @syntax:
+ <string> $serialize(<data:mixed>)
+ @description:
+ Decodes JSON-encoded string
+ $serialize() returns a string containing a byte-stream representation of value that can be stored anywhere.
+ @seealso:
+ [fnc]$serialize[/fnc]
+ */
+ KVSCF(serialize)
+ {
+ KviKvsVariant *pVar = 0;
+ QString szBuffer;
+
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("data",KVS_PT_VARIANT,0,pVar)
+ KVSCF_PARAMETERS_END
+
+ if(!pVar) return false;
+ pVar->serialize(szBuffer);
+ KVSCF_pRetBuffer->setString(szBuffer);
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: server
+ @type:
+ function
+ @title:
+ $server
+ @short:
+ Returns the current server name (if any)
+ @syntax:
+ <string> $server[(irc_context_id:uint)]
+ @description:
+ Returns the current server name of the specified IRC context.[br]
+ If no <irc_context_id> is specified, the current IRC context is used.[br]
+ If you are not connected to a server, this function will return an empty string.[br]
+ If the current window does not belong to any IRC context and no irc_context_id
+ is specified, this function prints a warning and also returns an empty string.[br]
+ */
+
+ KVSCF(server)
+ {
+ kvs_uint_t uCntx;
+
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("irc_context_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uCntx)
+ KVSCF_PARAMETERS_END
+
+ KviConsole * cns;
+
+ if(KVSCF_pParams->count() > 0)
+ {
+ cns = g_pApp->findConsole(uCntx);
+ if(cns)
+ {
+ if(cns->context()->isConnected() || cns->context()->isLoggingIn())
+ KVSCF_pRetBuffer->setString(cns->connection()->currentServerName());
+ else
+ KVSCF_pRetBuffer->setNothing();
+ } else {
+ KVSCF_pRetBuffer->setNothing();
+ }
+ } else {
+ if(KVSCF_pContext->window()->console())
+ {
+ cns = KVSCF_pContext->window()->console();
+ if(cns->context()->isConnected() || cns->context()->isLoggingIn())
+ KVSCF_pRetBuffer->setString(cns->connection()->currentServerName());
+ else
+ KVSCF_pRetBuffer->setNothing();
+ } else {
+ KVSCF_pContext->warning(__tr2qs("This window has no associated IRC context"));
+ KVSCF_pRetBuffer->setNothing();
+ }
+ }
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: sort
+ @type:
+ function
+ @title:
+ $sort
+ @short:
+ Sorts an array
+ @syntax:
+ <array> $sort(<data:array>)
+ @description:
+ Sorts an array in ascending order.
+ @seealso:
+ [fnc]$rsort[/fnc]
+ */
+
+ KVSCF(sort)
+ {
+ KviKvsArrayCast a;
+
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("data",KVS_PT_ARRAYCAST,0,a)
+ KVSCF_PARAMETERS_END
+
+ if(a.array())
+ {
+ KviKvsArray * arry = new KviKvsArray(*(a.array()));
+ arry->sort();
+ KVSCF_pRetBuffer->setArray(arry);
+ } else {
+ KVSCF_pRetBuffer->setArray(new KviKvsArray());
+ }
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: string
+ @type:
+ function
+ @title:
+ $string
+ @short:
+ Casts a variable to a string
+ @syntax:
+ <integer> $string(<data:variant>)
+ @description:
+ Forces <data> to be a string data type with the following semantics:
+ [ul]
+ [li]If <data> is a string then <data> itself is returned.[/li]
+ [li]If <data> is an integer then its decimal rappresentation is returned.[/li]
+ [li]If <data> is a real then its decimal floating-point rappresentation is returned.[/li]
+ [li]If <data> is a boolean then the string "1" is returned for a true value and the string "0" for a false value.[/li]
+ [li]If <data> is nothing (unset) then an empty string is returned[/li]
+ [li]If <data> is an array then a string with all the items converted to strings and separated by commas is returned[/li]
+ [li]If <data> is a hash then a string with all the values converted to strings and separated by commas is returned[/li]
+ [li]If <data> is a hobject then the string "object" is returned[/li]
+ [/ul]
+ Note that since KVIrc does most of the casting work automatically
+ you shouldn't need to use this function.
+ @seealso:
+ [fnc]$real[/fnc]
+ [fnc]$integer[/fnc]
+ */
+
+ KVSCF(string)
+ {
+ KviKvsVariant * v;
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("data",KVS_PT_VARIANT,0,v)
+ KVSCF_PARAMETERS_END
+
+ QString szVal;
+ v->asString(szVal);
+ KVSCF_pRetBuffer->setString(szVal);
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: sw
+ @type:
+ function
+ @title:
+ $sw
+ @short:
+ Returns the value of a switch for an alias
+ @syntax:
+ <variant> $sw(<switch_name:string>[,<long_switch_name:string>])
+ @description:
+ This function is valid and useful only in aliases.
+ It allows an alias to handle switches just like any other
+ KVIrc command. If a switch in the form -<letter> was
+ passed to the current alias then $sw(<letter>)
+ returns 1 (true). If a switch in the form -<letter>=<value>
+ was passed to the current alias then <value> is returned.
+ If the switch was not present at all then this function
+ returns an empty string (that evaluates to false in an expression).
+ A warning is printed if this function is used non-alias code.
+ @examples:
+ [example]
+ [cmd]alias[/cmd](test){
+ if($sw(a,append)) [cmd]echo[/cmd] "Switch -a was passed"
+ %x = $sw(x);
+ if(%x) [cmd]echo[/cmd] "Switch -x=%x was passed"
+ }
+ test -a
+ test -x
+ test --append -x
+ test -a -x
+ test -a -x=test
+ test -a=10 -x=test
+ [/example]
+ */
+
+ KVSCF(sw)
+ {
+ QString szSwitch;
+ QString szLongSwitch;
+
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("switch_name",KVS_PT_STRING,0,szSwitch)
+ KVSCF_PARAMETER("long_name",KVS_PT_STRING | KVS_PF_OPTIONAL ,0,szLongSwitch)
+ KVSCF_PARAMETERS_END
+
+ KviKvsSwitchList * sl = KVSCF_pContext->aliasSwitchList();
+ if(!sl)
+ {
+ KVSCF_pContext->warning(__tr2qs("The $sw() function can be used only in aliases"));
+ return true;
+ }
+
+ KviKvsVariant * v;
+
+
+ if(szSwitch.length() > 1)
+ {
+ if(szLongSwitch.isEmpty())
+ v = sl->find(szSwitch);
+ else
+ v = sl->find(szSwitch[0].unicode(),szLongSwitch);
+ }else {
+ if(szLongSwitch.isEmpty())
+ v = sl->find(szSwitch[0]);
+ else
+ v = sl->find(szSwitch[0].unicode(),szLongSwitch);
+ }
+
+ if(v)KVSCF_pRetBuffer->copyFrom(*v);
+ else KVSCF_pRetBuffer->setNothing();
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: target
+ @type:
+ function
+ @title:
+ $target
+ @short:
+ Returns the target of the current window
+ @syntax:
+ <string> $target
+ <string> $target(<window id>)
+ @description:
+ The form with the <window id> parameter returns the target
+ of the channel,query or dcc that has the specified ID.
+ The form without parameters returns the target of the current window,
+ thus it is equivalent to calling $target([fnc]$window[/fnc]).
+ For channel windows the target is the channel name,
+ for query windows it is the list of the "queried" users, for the
+ dcc windows it is the remote end of the connection.
+ The other windows have an empty target.
+ @examples:
+ [example]
+ [cmd]echo[/cmd] $target
+ [/example]
+ @seealso:
+ [fnc]$window[/fnc],
+ [fnc]$console[/fnc],
+ [fnc]$channel[/fnc],
+ [fnc]$query[/fnc],
+ [doc:window_naming_conventions]Window naming conventions[/doc]
+ */
+
+ KVSCF(target)
+ {
+ QString winId;
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("winId",KVS_PT_NONEMPTYSTRING,KVS_PF_OPTIONAL,winId)
+ KVSCF_PARAMETERS_END
+
+ KviWindow * wnd;
+ if(KVSCF_pParams->count() > 0)
+ {
+ wnd = g_pApp->findWindow(winId.utf8().data());
+ if(!wnd)
+ {
+ KVSCF_pContext->warning(__tr2qs("Window with ID '%s' not found, returning empty string"),winId.utf8().data());
+ KVSCF_pRetBuffer->setNothing();
+ return true;
+ }
+ } else {
+ wnd = KVSCF_pContext->window();
+ }
+
+ //debug("CALLING $target on window %s",wnd->name());
+ QString szTa = wnd->target();
+
+
+ KVSCF_pRetBuffer->setString(wnd->target());
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: this
+ @type:
+ function
+ @title:
+ $this
+ @short:
+ Retrieves the ID of the current object
+ @syntax:
+ $this
+ @description:
+ Returns the ID of the current object or ('0') if there is
+ none. This function has a "quick" version with syntax:
+ [b]$$[/b][br]
+ */
+
+ /*
+ @doc: $
+ @type:
+ function
+ @title:
+ $$
+ @short:
+ Retrieves the ID of the current object
+ @syntax:
+ $$
+ @description:
+ Returns the ID of the current object or ('0') if there is
+ none. This function has equivalent to [fnc]$this[/fnc]
+ */
+
+ KVSCF(thisCKEYWORDWORKAROUND)
+ {
+ // prologue: parameter handling
+ KviKvsObject * o = KVSCF_pContext->thisObject();
+ KVSCF_pRetBuffer->setHObject(o ? o->handle() : ((kvs_hobject_t)0));
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: script_localization
+ @type:
+ generic
+ @title:
+ Localization of scripts
+ @short:
+ Explains how to add translation capabilities to your scripts
+ @body:
+ [p]
+ [big]Introduction[/big]
+ [/p]
+ [p]
+ Adding the translated versions of the strings adds a great
+ value to your scripts. The process of translating a part of
+ software is called localization. KVIrc offers some commands
+ and functions for this purpose and this document explains
+ briefly how to use them.
+ [/p]
+
+ [p]
+ [big]The big picture[/big]
+ [/p]
+ [p]
+ All of the strings in your script are written in a "primary language".
+ The most common "primary language" is english, but theoretically
+ it can be any language of your choice.
+ [/p]
+ [p]
+ By the means of the gettext package programs you extract
+ the strings from your script and produce a translation file.
+ [/p]
+ [p]
+ The translation file is then effectively translated in another
+ language and later compiled in a binary form.
+ [/p]
+ [p]
+ The binary form translations are then loaded in the KVIrc
+ executable at runtime and a function is used to look up the
+ translations.
+ [/p]
+
+ [p]
+ [big]How to translate scripts[/big]
+ [/p]
+ [p]
+ Your strings should be surrounded by the [fnc]$tr[/fnc]() function in the following way:
+ [example]
+ [fnc]$tr[/fnc]("your default language text")
+ [/example]
+ [/p]
+ [p]
+ Then you should run the xgettext command on your script files.
+ This is done by a shell commandline similar to the following:[br]
+ [pre]xgettext -o myscript.pot -ktr mykvsfile1.kvs mykvsfile2.kvs ...[/pre]
+ [/p]
+ [p]
+ Copy the translation file obtained in the following way:[br]
+ [pre]cp myscript.pot myscript_XX.pot[/pre]
+ Where the XX is your country/language code. For example, for Italian
+ it would be:[br]
+ [pre]cp myscript.pot myscript_it.po[/pre]
+ [/p]
+ [p]
+ Translate mytranslation_it.po. The format of the po file is straightforward.
+ There are msgid lines with the original english text and immediately
+ following msgstr lines that must be filled with the corresponding translation.
+ For example in Italian you would translate:[br]
+ msgid "your default language text"
+ msgstr "il tuo testo in linguaggio predefinito"
+ [/p]
+ [p]
+ Compile your translation to binary form with the following command:[br]
+ [pre]msgfmt -o myscript_it.mo myscript_it.po[/pre]
+ [/p]
+ [p]
+ Copy the generated *.mo file to the "locale" subdirectory
+ in the KVIrc's local directory (usually $HOME/.kvirc/locale/).
+ [/p]
+ [p]
+ Set the system language to the XX above with the following command:[br]
+ [pre]export LANG="XX"[/pre][br]
+ For Italian it would be:[br]
+ [pre]export LANG="it"[/pre][br]
+ [/p]
+ [p]
+ Start KVIrc and type in the commandline:
+ [example]
+ [cmd]echo[/cmd] [fnc]$tr[/fnc]("your default language text","myscript")
+ [/example]
+ If you did everything well, you should see the translated
+ text echoed in the window :)[br]
+ [/p]
+ [p]
+ Obviously if you don't set LANG="XX", the same command will
+ output the original string unchanged.
+ [/p]
+ [p]
+ You can manage translations in several languages by producing
+ several *.mo files all with the proper language/country code appended.
+ The right *.mo file will be magically loaded by KVIrc that
+ will look up the user's LANG variable. (If you don't want
+ to use LANG, you can use KVIRC_LANG instead, it will still work).
+ [/p]
+
+ [big]Caveats[/big]
+ [/p]
+ [p]
+ You should NEVER use variables or identifiers inside the $tr() function.
+ This because the translation files are generated offline,
+ when the string is not evaluated yet (i.e variables ad identifiers
+ are not substituted by their actual return values).
+ The translation process, instead, happens at runtime, when
+ the variables and identifiers have been substituted by their
+ actual values. This would lead to a mismatch between the
+ string you look up in the translation catalogue and the
+ effectively translated one. If you need to include variables
+ in your strings you should compose the string with smaller pieces
+ [example]
+ [cmd]echo[/cmd] [fnc]$tr[/fnc]("On this channel") %number [fnc]$tr[/fnc]("users are operators")
+ [/example]
+ [/p]
+ [p]
+ The translation process can be realized only if your
+ scripts are written in external files. This makes sense since
+ if you're translating the script then you will probably want to
+ distribute it and the only way to distribute it is on files.
+ But well.. this is a caveat.
+ [/p]
+ */
+
+ /*
+ @doc: tr
+ @type:
+ function
+ @title:
+ $tr
+ @short:
+ Translates an english string to the current language
+ @syntax:
+ <string> $tr(<default_language_string:string>[,<catalogue:string>])
+ @description:
+ This function searches for the translation of <default_language_string>
+ in the specified translation <catalogue> or in the main
+ KVIrc translation file if <catalogue> is omitted.[br]
+ If no translation is found then <english_string> is returned.[br]
+ <default_language_string> is a string in your script default
+ language (which should probably be english since it is the
+ most common language spoken by the translators...).[br]
+ If the <catalogue> is not loaded yet, KVIrc will attempt to load it,
+ but only the first time that the catalogue is accessed (i.e. a load
+ failure will cause the catalogue to be ignored completly until [cmd]trunload[/cmd]
+ is explicitly used.[br]
+ KVIrc will search the catalogue only in [fnc]$file.localdir[/fnc]/locale/
+ and in [fnc]$file.globaldir[/fnc]/locale/. If your catalogues are
+ in some other place then you must load them explicitly by the
+ means of [cmd]trload[/cmd].
+ For more informations see the documentation about [doc:script_localization]script localization[/doc].
+ @examples:
+ [example]
+ [cmd]echo[/cmd] $tr("Hello World!")
+ [/example]
+ @seealso:
+ [cmd]trload[/cmd], [cmd]trunload[/cmd]
+ */
+
+ KVSCF(tr)
+ {
+ // prologue: parameter handling
+ QString szString;
+ QString szCatalogue;
+
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("default_language_string",KVS_PT_STRING,0,szString)
+ KVSCF_PARAMETER("catalogue",KVS_PT_STRING,KVS_PF_OPTIONAL,szCatalogue)
+ KVSCF_PARAMETERS_END
+ if(szString.isEmpty()) return true;
+ // body: the real job
+ QString translation;
+
+ if(!szCatalogue.isEmpty())
+ {
+ KviMessageCatalogue * pCat = KviLocale::getLoadedCatalogue(szCatalogue);
+ if(pCat)
+ {
+ translation = pCat->translateToQString(szString);
+ } else {
+ // attempt to load it automatically
+ QString szDir;
+ g_pApp->getLocalKvircDirectory(szDir,KviApp::Locale);
+ if(!KviLocale::loadCatalogue(szCatalogue,szDir))
+ {
+ g_pApp->getGlobalKvircDirectory(szDir,KviApp::Locale);
+ KviLocale::loadCatalogue(szCatalogue,szDir);
+ }
+ // If the code above fails to load the catalogue
+ // then __tr2qs_ctx_no_xgettext will place
+ // a dummy catalogue in its place
+ // This means that the next call to getLoadedCatalogue will
+ // not fail unless /trunload is explicitly used
+ // This will avoid trashing the user's disk too much
+ // when a catalogue for a given language is not available
+ translation = __tr2qs_ctx_no_xgettext(szString,szCatalogue);
+ }
+ } else {
+ translation = __tr2qs_no_xgettext(szString);
+ }
+
+ // epilogue: set the return value
+ KVSCF_pRetBuffer->setString(translation);
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: true
+ @type:
+ function
+ @title:
+ $true
+ @short:
+ The boolean true constant
+ @syntax:
+ <boolean> $true
+ @description:
+ Evaluates to the true boolean constant. True
+ is equivalent to the integer 1 too. This function/constant
+ is useful to keep your code readable: when you
+ have a variable that can assume boolean values it's
+ nicer to use $true and [fnc]$false[/fnc] instead of
+ the integer constants 1 and 0. The reader will
+ undestand immediately that the variable simply can't
+ assume any other value.
+ @examples:
+ [example]
+ %a = $true
+ [cmd]echo[/cmd] $typeof(%a)
+ [cmd]echo[/cmd] $(%a + 1)
+ [/example]
+ @seealso:
+ [fnc]$false[/fnc]
+ */
+
+ KVSCF(trueCKEYWORDWORKAROUND)
+ {
+#ifdef COMPILE_NEW_KVS
+ KVSCF_pRetBuffer->setBoolean(true);
+#endif
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: typeof
+ @type:
+ function
+ @title:
+ $typeof
+ @short:
+ Returns the internal data type of a variable
+ @syntax:
+ <string> $typeof(<data:variant>)
+ @description:
+ Returns the internal data type of the <data>.
+ @examples:
+ [example]
+ [cmd]echo[/cmd] $typeof("test")
+ %a = "test"
+ [cmd]echo[/cmd] $typeof(%a)
+ %a = 1
+ [cmd]echo[/cmd] $typeof(%a)
+ %a = $(1 + 2)
+ [cmd]echo[/cmd] $typeof(%a)
+ [cmd]echo[/cmd] $typeof($typeof(%a))
+ [/example]
+ */
+
+ KVSCF(typeofCKEYWORDWORKAROUND)
+ {
+#ifdef COMPILE_NEW_KVS
+ KviKvsVariant * v;
+
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("data",KVS_PT_VARIANT,0,v)
+ KVSCF_PARAMETERS_END
+
+ QString szType;
+ v->getTypeName(szType);
+ KVSCF_pRetBuffer->setString(szType);
+#endif
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: u
+ @type:
+ function
+ @title:
+ $u
+ @short:
+ Returns the UNDERLINE mIRC control character
+ @syntax:
+ <string> $u
+ @description:
+ Returns the UNDERLINE mIRC control character (CTRL+U).[br]
+ @seealso:
+ [fnc]$k[/fnc], [fnc]$b[/fnc], [fnc]$r[/fnc], [fnc]$o[/fnc]
+ */
+
+ KVSCF(u)
+ {
+ KVSCF_pRetBuffer->setString(QString(QChar(KVI_TEXT_UNDERLINE)));
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: unicode
+ @type:
+ function
+ @title:
+ $unicode
+ @short:
+ Returns the UNICODE code of a sets of characters
+ @syntax:
+ <variant> $unicode(<char:string>)
+ @description:
+ If <char> is composed only of a single character
+ then returns its UNICODE code point as an integer.
+ If <char> is composed of more than one character
+ then an array of UNICODE code points is returned.
+ @seealso:
+ [fnc]$cr[/fnc], [fnc]$lf[/fnc], [fnc]$char[/fnc]
+ */
+
+ KVSCF(unicode)
+ {
+ QString sz;
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("char",KVS_PT_NONEMPTYSTRING,0,sz)
+ KVSCF_PARAMETERS_END
+
+ if(sz.length() > 1)
+ {
+ KviKvsArray * a = new KviKvsArray();
+ for(kvs_int_t i=0;i<sz.length();i++)
+ a->set(i,new KviKvsVariant((kvs_int_t)(sz[(int)i].unicode())));
+ KVSCF_pRetBuffer->setArray(a);
+ } else {
+ KVSCF_pRetBuffer->setInteger((kvs_int_t)(sz[0].unicode()));
+ }
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: unixtime
+ @type:
+ function
+ @title:
+ $unixTime
+ @short:
+ Returns the current UNIX time
+ @syntax:
+ <integer> $unixtime
+ @description:
+ Returns the time since the Epoch (00:00:00 UTC, January 1, 1970),
+ measured in seconds.
+ @seealso:
+ [fnc]$date[/fnc], [fnc]$hpTimeStamp[/fnc]
+ */
+
+ KVSCF(unixtime)
+ {
+ KVSCF_pRetBuffer->setInteger((kvs_int_t)(time(0)));
+ return true;
+ }
+
+ /*
+ @doc: unserialize
+ @type:
+ function
+ @title:
+ <mixed> $unserialize(<data:string>)
+ @short:
+ Decodes JSON-encoded string
+ @syntax:
+ <mixed> $unserialize(<data:string>)
+ @description:
+ Decodes JSON-encoded string
+ @seealso:
+ [fnc]$serialize[/fnc]
+ */
+
+ KVSCF(unserialize)
+ {
+ QString szData;
+
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("data",KVS_PT_NONEMPTYSTRING,0,szData)
+ KVSCF_PARAMETERS_END
+
+ KviKvsVariant *pVar = KviKvsVariant::unserialize(szData);
+ if(pVar)
+ KVSCF_pRetBuffer->copyFrom(pVar);
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: username
+ @type:
+ function
+ @title:
+ $username
+ @short:
+ Returns the username of the specified user
+ @syntax:
+ <string> $username(<nickname:string>)
+ @description:
+ Returns the username of the specified IRC user IF it is known.[br]
+ The username is known if [fnc]$isWellKnown[/fnc] returns 1.[br]
+ The username is generally known if the user is on a channel with you
+ or has an open query with you.[br]
+ Detailed explaination:[br]
+ KVIrc has an internal database of users that are currently
+ visible by *this client*: this includes users on open channels
+ and queries.[br] The other IRC users are NOT in the database:
+ this means that KVIrc knows NOTHING about them and can't return
+ any information immediately. In this case this function will return
+ an EMPTY string.[br]
+ If a user is in the database, at least his nickname is known.[br]
+ The username and hostname are known only if the server provides that information
+ spontaneously or after a KVIrc request.[br]
+ KVIrc requests user information for all the users in open queries
+ and channels. This information takes some time to be retrieved,
+ in this interval of time KVIrc knows only the user's nickname.
+ This function will return the string "*" in this case.[br]
+ @seealso:
+ [fnc]$isWellKnown[/fnc], [$fnc]$hostname[/fnc], [cmd]awhois[/cmd]
+ */
+
+ KVSCF(username)
+ {
+ QString szNick;
+
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("nick",KVS_PT_NONEMPTYSTRING,0,szNick)
+ KVSCF_PARAMETERS_END
+
+ if(KVSCF_pContext->window()->console())
+ {
+ if(KVSCF_pContext->window()->console()->isConnected())
+ {
+ KviIrcUserEntry * e = KVSCF_pContext->window()->connection()->userDataBase()->find(szNick);
+ if(e)
+ {
+ KVSCF_pRetBuffer->setString(e->user());
+ return true;
+ }
+ }
+ }
+
+ KVSCF_pRetBuffer->setNothing();
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: version
+ @type:
+ function
+ @title:
+ $version
+ @short:
+ Returns informations about the version of KVIrc.
+ @syntax:
+ <string> $version()
+ <string> $version(<type:string>)
+ @description:
+ Returns informations about the version of the currently running KVIrc.[br]
+ Type can be one of:[br]
+ [ul]
+ [li]v: return the current numeric version[/li]
+ [li]s: return the current sources date[/li]
+ [li]r: return the release name[/li]
+ [li]b: return the build date in human readable form[/li]
+ [/ul]
+ If <type> is omitted then v is assumed.[br]
+ @examples:
+ [example]
+ [cmd]echo[/cmd] $version $version(r)
+ [/example]
+ @seealso:
+ [fnc]$features[/fnc]
+ */
+
+ KVSCF(version)
+ {
+ QString szType;
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("type",KVS_PT_STRING,KVS_PF_OPTIONAL,szType)
+ KVSCF_PARAMETERS_END
+
+ if(szType.isEmpty())
+ KVSCF_pRetBuffer->setString(KVI_VERSION);
+ else {
+ if(szType.find('r') != -1)KVSCF_pRetBuffer->setString(KVI_RELEASE_NAME);
+ else if(szType.find('s') != -1)KVSCF_pRetBuffer->setString(KVI_SOURCES_DATE);
+ else if(szType.find('b') != -1)KVSCF_pRetBuffer->setString(KVI_BUILD_DATE);
+ else KVSCF_pRetBuffer->setString(KVI_VERSION);
+ }
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: window
+ @type:
+ function
+ @title:
+ $window
+ @short:
+ Retrieve the id of a specified window.
+ @syntax:
+ <string> $window
+ <string> $window([<caption_text:hash>[,<context_id:uint>]])
+ @description:
+ Returns the [b]window id[/b] of the first window that
+ has the specified <caption text>.[br]
+ If no window matches the specified <caption text>, and invalid
+ window id is returned (0).[br]
+ If no <caption text> is specified , this function returns the id
+ of the current window.[br]
+ <context_id> restricts search in only one irc context.
+ @examples:
+ [example]
+ [cmd]echo[/cmd] This is the window with id $window
+ [/example]
+ @seealso:
+ [fnc]$channel[/fnc],
+ [fnc]$query[/fnc],
+ [fnc]$console[/fnc],
+ [doc:window_naming_conventions]Window naming conventions[/doc]
+ */
+
+ KVSCF(window)
+ {
+ //#warning "FIXME: the window identifiers could be numbers!"
+ QString szCaption;
+ kvs_int_t iContextId; // kvs_int_t is 64bit while int is 32 (and thus KVSCF_PARAMETER() crashes)
+
+ KVSCF_PARAMETERS_BEGIN
+ KVSCF_PARAMETER("caption_text",KVS_PT_STRING,KVS_PF_OPTIONAL,szCaption)
+ KVSCF_PARAMETER("context_id",KVS_PT_INTEGER,KVS_PF_OPTIONAL,iContextId)
+ KVSCF_PARAMETERS_END
+
+ if(KVSCF_pParams->count() < 2)
+ iContextId = -1;
+
+ KviWindow * pWnd;
+ if(szCaption.isEmpty())
+ {
+ pWnd = KVSCF_pContext->window();
+ } else {
+ pWnd = g_pApp->findWindowByCaption(szCaption,iContextId);
+ if(!pWnd)
+ {
+ //follow the documented behaviour
+ KVSCF_pRetBuffer->setInteger(0);
+ return true;
+ }
+ }
+ KVSCF_pRetBuffer->setInteger(pWnd->numericId());
+ return true;
+ }
+};
+
diff --git a/src/kvirc/kvs/kvi_kvs_coresimplecommands.cpp b/src/kvirc/kvs/kvi_kvs_coresimplecommands.cpp
new file mode 100644
index 00000000..a5979631
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_coresimplecommands.cpp
@@ -0,0 +1,237 @@
+//=============================================================================
+//
+// File : kvi_kvs_coresimplecommands.cpp
+// Created on Fri 31 Oct 2003 00:04:25 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_ircconnectionserverinfo.h"
+
+#include "kvi_kvs_coresimplecommands.h"
+
+#include "kvi_kvs_kernel.h"
+#include "kvi_options.h"
+#include "kvi_ircconnection.h"
+#include "kvi_locale.h"
+#include "kvi_kvs_treenode_command.h"
+
+#include <qregexp.h>
+#include <qstringlist.h>
+
+namespace KviKvsCoreSimpleCommands
+{
+ void init()
+ {
+ KviKvsKernel * pKern = KviKvsKernel::instance();
+
+#define _REGCMD(__cmdName,__routine) \
+ { \
+ KviKvsCoreSimpleCommandExecRoutine * r = new KviKvsCoreSimpleCommandExecRoutine; \
+ r->proc = KVI_PTR2MEMBER(KviKvsCoreSimpleCommands::__routine); \
+ pKern->registerCoreSimpleCommandExecRoutine(QString(__cmdName),r); \
+ }
+ // a_f
+ _REGCMD("admin",rfc2812wrapper)
+ _REGCMD("away",away)
+ _REGCMD("back",back)
+ _REGCMD("ban",ban)
+ _REGCMD("beep",beep)
+ _REGCMD("buttonctl",buttonctl)
+ _REGCMD("codepage",rfc2812wrapper)
+ _REGCMD("ctcp",ctcp)
+ _REGCMD("debug",debug)
+ _REGCMD("delete",deleteCKEYWORDWORKAROUND)
+ _REGCMD("delpopupitem",delpopupitem)
+ _REGCMD("destroy",deleteCKEYWORDWORKAROUND)
+ _REGCMD("deop",deop)
+ _REGCMD("devoice",devoice)
+ _REGCMD("die",error)
+ _REGCMD("echoprivmsg",echoprivmsg)
+ _REGCMD("echo",echo)
+ _REGCMD("error",error)
+ _REGCMD("eval",eval)
+ _REGCMD("eventctl",eventctl)
+ _REGCMD("exit",exit)
+ // g_l
+ _REGCMD("halt",halt)
+ _REGCMD("help",help)
+ _REGCMD("host",host)
+ _REGCMD("include",parse)
+ _REGCMD("info",rfc2812wrapper)
+ _REGCMD("invite",rfc2812wrapper)
+ _REGCMD("join",join)
+ _REGCMD("kick",kick)
+ _REGCMD("killtimer",killtimer)
+ _REGCMD("leave",part)
+ _REGCMD("links",rfc2812wrapper)
+ _REGCMD("list",rfc2812wrapper)
+ _REGCMD("listtimers",listtimers)
+ _REGCMD("lusers",rfc2812wrapper)
+ // m_r
+ _REGCMD("me",me)
+ _REGCMD("mode",mode)
+ _REGCMD("motd",rfc2812wrapper)
+ _REGCMD("msg",privmsg)
+ _REGCMD("nick",nick)
+ _REGCMD("notice",notice)
+ _REGCMD("op",op)
+ _REGCMD("openurl",openurl)
+ _REGCMD("oper",rfc2812wrapper)
+ _REGCMD("option",option)
+ _REGCMD("parse",parse)
+ _REGCMD("part",part)
+ _REGCMD("pass",rfc2812wrapper)
+ _REGCMD("play",play)
+ _REGCMD("popup",popup)
+ _REGCMD("privmsg",privmsg)
+ _REGCMD("query",query)
+ _REGCMD("quit",quit)
+ _REGCMD("quote",raw)
+ _REGCMD("raise",raise)
+ _REGCMD("raw",raw)
+ _REGCMD("return",returnCKEYWORDWORKAROUND)
+ _REGCMD("rebind",rebind)
+ // s_z
+ _REGCMD("run",run)
+ _REGCMD("say",say)
+ _REGCMD("server",server)
+ _REGCMD("service",rfc2812wrapper)
+ _REGCMD("setmenu",setmenu)
+ _REGCMD("setreturn",setreturn)
+ _REGCMD("sockets",rfc2812wrapper)
+ _REGCMD("squery",rfc2812wrapper)
+ _REGCMD("squit",rfc2812wrapper)
+ _REGCMD("srand",srand)
+ _REGCMD("stats",rfc2812wrapper)
+ _REGCMD("time",rfc2812wrapper)
+ _REGCMD("topic",topic)
+ _REGCMD("trace",rfc2812wrapper)
+ _REGCMD("trload",trload)
+ _REGCMD("trunload",trunload)
+ _REGCMD("unban",unban)
+ _REGCMD("version",rfc2812wrapper)
+ _REGCMD("voice",voice)
+ _REGCMD("warning",warning)
+ _REGCMD("who",rfc2812wrapper)
+ _REGCMD("whois",whois)
+ _REGCMD("whowas",whowas)
+
+#undef _REGCMD
+ }
+
+
+ bool multipleModeCommand(KviKvsRunTimeContext * __pContext,KviKvsVariantList * __pParams,KviKvsSwitchList * __pSwitches,char plusminus,char flag)
+ {
+ QString szTokens;
+ KVSCSC_PARAMETERS_BEGIN
+ KVSCSC_PARAMETER("tokens",KVS_PT_STRING,KVS_PF_APPENDREMAINING,szTokens)
+ KVSCSC_PARAMETERS_END
+
+ KVSCSC_REQUIRE_CONNECTION
+
+ if(KVSCSC_pWindow->type() != KVI_WINDOW_TYPE_CHANNEL)
+ {
+ KVSCSC_pContext->warning(__tr2qs("This is not a channel"));
+ return true;
+ }
+
+ QStringList sl = QStringList::split(QRegExp("[, ]+"),szTokens,false);
+
+ KviQCString szFlags;
+ KviQCString szTarget = KVSCSC_pConnection->encodeText(KVSCSC_pWindow->windowName());
+ KviQCString szMessage;
+
+ int i = 0;
+ for(QStringList::Iterator it = sl.begin();it != sl.end();++it)
+ {
+ KviQCString szTxt = KVSCSC_pConnection->encodeText(*it);
+ if(!szTxt.isEmpty())
+ {
+ szFlags += flag;
+ if(szMessage.length() > 0)szMessage += " ";
+ szMessage += szTxt;
+ i++;
+ if(i >= KVSCSC_pConnection->serverInfo()->maxModeChanges())
+ {
+ if(!KVSCSC_pConnection->sendFmtData("MODE %s %c%s %s",szTarget.data(),plusminus,szFlags.data(),szMessage.data()))
+ return KVSCSC_pContext->warningNoIrcConnection();
+ i = 0;
+ szFlags = "";
+ szMessage = "";
+ }
+ }
+ }
+
+ if(i > 0)
+ {
+ if(!KVSCSC_pConnection->sendFmtData("MODE %s %c%s %s",szTarget.data(),plusminus,szFlags.data(),szMessage.data()))
+ return KVSCSC_pContext->warningNoIrcConnection();
+ }
+
+ return true;
+ }
+
+ /*
+ @doc: rfc2821wrappers
+ @title:
+ RFC2821 Wrappers
+ @type:
+ generic
+ @short:
+ Wrappers for rfc2821 commands
+ @body:
+ Some less used KVIrc commands are implemented as simple wrappers
+ around the standard [doc]rfc2821[/doc] commands.[br]
+ For example, the /OPER command will be used only by server operators
+ and probably only once per connection.[br]
+ These commands should only be needed by experienced IRC users.
+ Due to this fact, these commands have no special kind of parsing performed by KVIrc;
+ the parameters are extracted, the identifiers are parsed normally
+ and are sent to the server without any semantic check.[br]
+ This means that while OPER requires two parameters, KVIrc will not
+ complain if you send a single parameter only or use ten parameters.[br]
+ The exact parameter syntax/semantic checking is left to you.[br]
+ This also means that if some of these commands accept parameters with spaces,
+ it is left to you to add the leading ':' before the last parameter.[br]
+ You should refer to [doc]rfc2812[/doc] if any of these commands do not work properly for you.[br]
+ */
+
+ KVSCSC(rfc2812wrapper)
+ {
+ QString szText;
+ KVSCSC_PARAMETERS_BEGIN
+ KVSCSC_PARAMETER("text",KVS_PT_STRING,KVS_PF_OPTIONAL | KVS_PF_APPENDREMAINING,szText)
+ KVSCSC_PARAMETERS_END
+
+ KVSCSC_REQUIRE_CONNECTION
+
+ KviQCString txt = KVSCSC_pConnection->encodeText(szText);
+ KviQCString cmd = KVSCSC_pConnection->encodeText(((KviKvsTreeNodeCommand *)(KVSCSC_pContext->defaultReportLocation()))->commandName());
+
+ if(!KVSCSC_pConnection->sendFmtData("%s %s",cmd.data(),txt.data() ? txt.data() : ""))
+ return KVSCSC_pContext->warningNoIrcConnection();
+
+ return true;
+ }
+
+};
+
diff --git a/src/kvirc/kvs/kvi_kvs_coresimplecommands.h b/src/kvirc/kvs/kvi_kvs_coresimplecommands.h
new file mode 100644
index 00000000..94acbdc6
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_coresimplecommands.h
@@ -0,0 +1,126 @@
+#ifndef _KVI_KVS_CORESIMPLECOMMANDS_H_
+#define _KVI_KVS_CORESIMPLECOMMANDS_H_
+//=============================================================================
+//
+// File : kvi_kvs_coresimplecommands.h
+// Created on Fri 31 Oct 2003 00:04:25 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_kvs_runtimecontext.h"
+#include "kvi_kvs_variantlist.h"
+#include "kvi_kvs_switchlist.h"
+#include "kvi_kvs_parameterprocessor.h"
+
+
+#define KVSCSC(_name) bool _name(KviKvsRunTimeContext * __pContext,KviKvsVariantList * __pParams,KviKvsSwitchList * __pSwitches)
+
+#define KVSCSC_pContext __pContext
+#define KVSCSC_pParams __pParams
+#define KVSCSC_pSwitches __pSwitches
+
+#define KVSCSC_PARAMETER(a,b,c,d) KVS_PARAMETER(a,b,c,d)
+
+#define KVSCSC_PARAMETERS_BEGIN \
+ KVS_PARAMETERS_BEGIN(parameter_format_list)
+
+#define KVSCSC_PARAMETERS_END \
+ KVS_PARAMETERS_END \
+ if(!KviKvsParameterProcessor::process(KVSCSC_pParams,KVSCSC_pContext,parameter_format_list))return false;
+
+#define KVSCSC_REQUIRE_CONNECTION \
+ if(!KVSCSC_pContext->window()->context())return KVSCSC_pContext->errorNoIrcContext(); \
+ if(!KVSCSC_pContext->window()->connection())return KVSCSC_pContext->warningNoIrcConnection();
+
+#define KVSCSC_pWindow __pContext->window()
+#define KVSCSC_pConnection __pContext->window()->connection()
+#define KVSCSC_pIrcContext __pContext->context()
+
+namespace KviKvsCoreSimpleCommands
+{
+ // a_f
+ KVSCSC(away);
+ KVSCSC(back);
+ KVSCSC(ban);
+ KVSCSC(beep);
+ KVSCSC(buttonctl);
+ KVSCSC(ctcp);
+ KVSCSC(debug);
+ KVSCSC(deleteCKEYWORDWORKAROUND);
+ KVSCSC(delpopupitem);
+ KVSCSC(deop);
+ KVSCSC(devoice);
+ KVSCSC(echoprivmsg);
+ KVSCSC(echo);
+ KVSCSC(error);
+ KVSCSC(eval);
+ KVSCSC(eventctl);
+ KVSCSC(exit);
+ // g_l
+ KVSCSC(halt);
+ KVSCSC(help);
+ KVSCSC(host);
+ KVSCSC(join);
+ KVSCSC(kick);
+ KVSCSC(killtimer);
+ KVSCSC(listtimers);
+ // m_r
+ KVSCSC(me);
+ KVSCSC(mode);
+ KVSCSC(nick);
+ KVSCSC(notice);
+ KVSCSC(op);
+ KVSCSC(openurl);
+ KVSCSC(option);
+ KVSCSC(parse);
+ KVSCSC(part);
+ KVSCSC(play);
+ KVSCSC(popup);
+ KVSCSC(privmsg);
+ KVSCSC(query);
+ KVSCSC(quit);
+ KVSCSC(raise);
+ KVSCSC(raw);
+ KVSCSC(returnCKEYWORDWORKAROUND);
+ KVSCSC(rebind);
+ KVSCSC(rfc2812wrapper);
+ KVSCSC(run);
+ // s_z
+ KVSCSC(say);
+ KVSCSC(server);
+ KVSCSC(setmenu);
+ KVSCSC(setreturn);
+ KVSCSC(srand);
+ KVSCSC(topic);
+ KVSCSC(trload);
+ KVSCSC(trunload);
+ KVSCSC(unban);
+ KVSCSC(voice);
+ KVSCSC(warning);
+ KVSCSC(whois);
+ KVSCSC(whowas);
+
+ bool multipleModeCommand(KviKvsRunTimeContext * __pContext,KviKvsVariantList * __pParams,KviKvsSwitchList * __pSwitches,char plusminus,char flag);
+
+ void init();
+};
+
+#endif //!_KVI_KVS_CORESIMPLECOMMANDS_H_
diff --git a/src/kvirc/kvs/kvi_kvs_coresimplecommands_af.cpp b/src/kvirc/kvs/kvi_kvs_coresimplecommands_af.cpp
new file mode 100644
index 00000000..c3911a30
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_coresimplecommands_af.cpp
@@ -0,0 +1,1277 @@
+//=============================================================================
+//
+// File : kvi_kvs_coresimplecommands_af.cpp
+// Created on Fri 31 Oct 2003 00:04:25 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_coresimplecommands.h"
+
+
+#include "kvi_window.h"
+#include "kvi_out.h"
+#include "kvi_locale.h"
+#include "kvi_app.h"
+#include "kvi_options.h"
+#include "kvi_ircview.h" // this is only for KviIrcView::NoTimestamp
+#include "kvi_debugwindow.h"
+#include "kvi_console.h"
+#include "kvi_scriptbutton.h"
+#include "kvi_iconmanager.h"
+
+#include "kvi_kvs_popupmanager.h"
+#include "kvi_kvs_eventmanager.h"
+#include "kvi_kvs_kernel.h"
+#include "kvi_kvs_object_controller.h"
+
+#ifndef COMPILE_NO_X_BELL
+ #include "kvi_xlib.h" // XBell : THIS SHOULD BE INCLUDED AS LAST!
+ #include <unistd.h> // for usleep();
+
+ #ifdef COMPILE_USE_QT4
+ #include <qx11info_x11.h>
+ #define get_xdisplay QX11Info::display
+ #else
+ #define get_xdisplay qt_xdisplay
+ #endif
+
+#endif
+
+#include "kvi_tal_tooltip.h"
+
+// kvi_app.cpp
+extern KviPointerHashTable<const char *,KviWindow> * g_pGlobalWindowDict;
+
+namespace KviKvsCoreSimpleCommands
+{
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: admin
+ @type:
+ command
+ @title:
+ admin
+ @syntax:
+ admin [target server]
+ @short:
+ Requests the admin info from a server
+ @description:
+ Requests admin information from the specified server or the current server if no [target server] is specified.[br]
+ This command is a [doc:rfc2821wrappers]RFC2821 command wrapper[/doc]; see that document for more information.[br]
+ */
+ // RFC2821 wrapper
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: away
+ @type:
+ command
+ @title:
+ away
+ @syntax:
+ away [-a | --all-networks] [<reason:string>]
+ @short:
+ Puts you into 'away' state
+ @switches:
+ !sw: -a | --all-networks
+ Set away on all networks
+ @description:
+ Puts you into 'away' state in the connection associated to the
+ current [b]IRC context[/b].[br] This command is "server based";
+ this means that the effects will be visible only after the
+ server has acknowledged the change.[br]
+ When you use this command, other people will know that you are
+ away from the keyboard, and they will know why you're not here.[br]
+ To return from being away you must use [cmd]back[/cmd].[br]
+ This command is [doc:connection_dependant_commands]connection dependant[/doc].[br]
+ @examples:
+ [example]
+ away I'm asleep. Don't wake me up.
+ [/example]
+ */
+
+ KVSCSC(away)
+ {
+ QString szReason;
+ KVSCSC_PARAMETERS_BEGIN
+ KVSCSC_PARAMETER("reason",KVS_PT_STRING,KVS_PF_OPTIONAL | KVS_PF_APPENDREMAINING,szReason)
+ KVSCSC_PARAMETERS_END
+
+ KVSCSC_REQUIRE_CONNECTION
+
+ if(szReason.isEmpty())szReason = KVI_OPTION_STRING(KviOption_stringAwayMessage);
+
+ if(KVSCSC_pSwitches->find('a',"all-networks"))
+ {
+ KviPointerHashTableIterator<const char *,KviWindow> it(*g_pGlobalWindowDict);
+ while(KviWindow * wnd = it.current())
+ {
+ if(wnd->type()==KVI_WINDOW_TYPE_CONSOLE)
+ {
+ KviConsole* pConsole=(KviConsole*)wnd;
+ if(pConsole->isConnected())
+ pConsole->connection()->sendFmtData("AWAY :%s",
+ pConsole->connection()->encodeText(szReason).data()
+ );
+ }
+ ++it;
+ }
+ } else {
+ KviQCString szR = KVSCSC_pConnection->encodeText(szReason);
+ if(!(KVSCSC_pConnection->sendFmtData("AWAY :%s",szR.data())))
+ return KVSCSC_pContext->warningNoIrcConnection();
+ }
+
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: back
+ @type:
+ command
+ @title:
+ back
+ @syntax:
+ back [-a | --all-networks]
+ @switches:
+ !sw: -a | --all-networks
+ Set back on all networks
+ @short:
+ Allows you to return from being away
+ @description:
+ Using this command makes you return from being [cmd]away[/cmd] in the connection associated to the
+ current [b]IRC context[/b].[br] This command is "server based";
+ this means that the effects will be visible only after the
+ server has acknowledged the change.[br]
+ This command is [doc:connection_dependant_commands]connection dependant[/doc].[br]
+ @examples:
+ [example]
+ back
+ [/example]
+ */
+
+ KVSCSC(back)
+ {
+
+ if(KVSCSC_pSwitches->find('a',"all-networks"))
+ {
+ KviPointerHashTableIterator<const char *,KviWindow> it(*g_pGlobalWindowDict);
+ while(KviWindow * wnd = it.current())
+ {
+ if(wnd->type()==KVI_WINDOW_TYPE_CONSOLE)
+ {
+ KviConsole* pConsole=(KviConsole*)wnd;
+ if(pConsole->isConnected())
+ pConsole->connection()->sendFmtData("AWAY");
+ }
+ ++it;
+ }
+ } else {
+ KVSCSC_REQUIRE_CONNECTION
+
+ if(!(KVSCSC_pConnection->sendFmtData("AWAY")))
+ return KVSCSC_pContext->warningNoIrcConnection();
+ }
+
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: ban
+ @type:
+ command
+ @title:
+ ban
+ @syntax:
+ ban <mask_list>
+ @short:
+ Sets ban masks for the channel
+ @description:
+ Sets the ban masks specified in the <mask_list>,
+ which is a comma separated list of nicknames.
+ This command works only if executed in a channel window.
+ The command is translated to a set of MODE messages containing
+ a variable number of +b flags.
+ This command is [doc:connection_dependant_commands]connection dependant[/doc].
+ @examples:
+ [example]
+ ban Maxim,Gizmo!*@*,*!root@*
+ [/example]
+ @seealso:
+ [cmd]op[/cmd],
+ [cmd]deop[/cmd],
+ [cmd]voice[/cmd],
+ [cmd]devoice[/cmd],
+ [cmd]unban[/cmd]
+ */
+
+ KVSCSC(ban)
+ {
+ return multipleModeCommand(__pContext,__pParams,__pSwitches,'+','b');
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: beep
+ @type:
+ command
+ @title:
+ beep
+ @syntax:
+ beep [-p=<pitch:uint>] [-d=<duration:uint>] [-s] [volume:uint]
+ @short:
+ Beep beep!
+ @switches:
+ !sw: -p=<pitch:uint> | --pitch=<pitch:uint>
+ Sets the bell to the specified pitch, if possible
+ !sw: -d=<duration:uint> | --duration=<duration:uint>
+ Sets the duration of the beep to <duration> milliseconds
+ !sw: -s | --synchronous
+ Causes KVIrc to wait for completion of the beeping before
+ returning from this command
+ @description:
+ Beeps (when possible :D)[br]
+ ...[br]
+ No , really..[br]
+ This command rings the bell on the keyboard (the PC speaker).
+ The volume must be in range 0-100; the default is 100.[br]
+ The pitch is specified in Hz and must be positive.[br]
+ The duration is specified in milliseconds.[br]
+ An invalid (or unspecified) pitch, volume or duration
+ makes KVIrc to use the default values set by the system.[br]
+ The duration of the bell is only indicative and
+ can be shortened by a subsequent call to /beep (that
+ will override the currently playing one).[br]
+ On Windows, the bell is always synchronous and it is not
+ event granted that the bell will be a bell at all... you might
+ get the system default sound instead.. so be careful if you
+ want to write portable scripts :)[br]
+ If the -s switch is specified the bell becomes synchronous:
+ KVIrc waits the bell to complete before continuing.[br]
+ Obviously -s is senseless on Windows.[br]
+ (WARNING : the main KVIrc thread is stopped in that case
+ so if you play long notes (duration > 100)
+ the entire application will appear to freeze for a while).[br]
+ The precision of the bell pitch, duration and
+ volume is strongly dependant on the system and the underlying hardware.[br]
+ */
+
+ KVSCSC(beep)
+ {
+ kvs_uint_t uVolume;
+ KVSCSC_PARAMETERS_BEGIN
+ KVSCSC_PARAMETER("volume",KVS_PT_UINT,KVS_PF_OPTIONAL,uVolume)
+ KVSCSC_PARAMETERS_END
+
+ kvs_int_t pitch = -1;
+ kvs_int_t duration = -1;
+ bool bSync = (KVSCSC_pSwitches->find('s',"sync") != 0);
+ bool bOk = false;
+
+ KviKvsVariant * pPitch = KVSCSC_pSwitches->find('p',"pitch");
+ if(pPitch)
+ {
+ if(!pPitch->asInteger(pitch))
+ {
+ KVSCSC_pContext->warning(__tr2qs("Invalid pitch value: using default"));
+ pitch = -1;
+ }
+ }
+
+ KviKvsVariant * pDuration = KVSCSC_pSwitches->find('d',"duration");
+ if(pDuration)
+ {
+ if(!pDuration->asInteger(duration))
+ {
+ KVSCSC_pContext->warning(__tr2qs("Invalid duration value: using default"));
+ duration = -1;
+ }
+ }
+
+ if((uVolume > 100) || (uVolume < 1))uVolume = 100;
+
+#ifdef COMPILE_ON_WINDOWS
+ Beep(pitch,duration);
+#else
+ #ifndef COMPILE_NO_X_BELL
+
+
+
+ XKeyboardState st;
+ XKeyboardControl ctl;
+
+ XGetKeyboardControl(get_xdisplay(),&st);
+
+ unsigned long mask = KBBellPercent;
+ ctl.bell_percent = uVolume;
+ if(pitch >= 0)
+ {
+ ctl.bell_pitch = pitch;
+ mask |= KBBellPitch;
+ }
+ if(duration >= 0)
+ {
+ ctl.bell_duration = duration;
+ mask |= KBBellDuration;
+ }
+ XChangeKeyboardControl(get_xdisplay(),mask,&ctl);
+
+ XBell(get_xdisplay(),100);
+
+ if(bSync)
+ {
+ if(duration >= 0)usleep(duration * 1000);
+ else usleep(st.bell_duration * 1000);
+ }
+
+ ctl.bell_pitch = st.bell_pitch;
+ ctl.bell_duration = st.bell_duration;
+ ctl.bell_percent = st.bell_percent;
+
+ XChangeKeyboardControl(get_xdisplay(),mask,&ctl);
+
+ #endif //COMPILE_NO_X_BELL
+#endif
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: buttonctl
+ @title:
+ buttonctl
+ @type:
+ command
+ @short:
+ changes user definable buttons
+ @syntax:
+ buttonctl [-q] <type:string> <name:string> <operation:string> [parameter:string]
+ @switches:
+ !sw: -q | --quiet
+ Run quietly
+ @description:
+ Changes an existing user defined button.[br]
+ <type_unused> is ignored and present only for backward compatibility.[br]
+ <name> is the name of the button.[br]
+ <operation> may be one of the constant strings "enable", "disable", "image",
+ "text".[br]
+ Operations "enable" and "disable" do not require the fourth [parameter] and have
+ the obvious meaning.[br] Operation "image" requires the [parameter] to be
+ a valid [doc:image_id]image_id[/doc] and sets the button image.[br]
+ Operation "text" requires the [parameter] (and in fact all the following ones)
+ to be a string containing the button text label.[br]
+ The <operation> constants may be abbreviated, even to the single letters 'e','d','i' and 't'.[br]
+ The -q switch causes the command to be quiet about errors and warnings.[br]
+ @seealso:
+ [cmd]button[/cmd]
+ */
+
+//#warning "ALSO /HELP must NOT interpret the identifiers!"
+//#warning "ALSO /DEBUG that relays to the DEBUG WINDOW"
+
+ KVSCSC(buttonctl)
+ {
+ QString tbTypeUnused,tbName,tbOp,tbPar;
+ KVSCSC_PARAMETERS_BEGIN
+ KVSCSC_PARAMETER("type",KVS_PT_STRING,0,tbTypeUnused)
+ KVSCSC_PARAMETER("name",KVS_PT_STRING,0,tbName)
+ KVSCSC_PARAMETER("operation",KVS_PT_STRING,0,tbOp)
+ KVSCSC_PARAMETER("parameter",KVS_PT_STRING,KVS_PF_OPTIONAL,tbPar)
+ KVSCSC_PARAMETERS_END
+
+ KviScriptUserButton * pButton = 0;
+
+ if(!KVSCSC_pWindow->buttonContainer())
+ {
+ if(!KVSCSC_pSwitches->find('q',"quiet"))KVSCSC_pContext->warning(__tr2qs("The specified window has no button containers"));
+ return true;
+ }
+
+ pButton = (KviScriptUserButton *)(KVSCSC_pWindow->buttonContainer())->child(tbName,"KviWindowScriptButton");
+
+ if(!pButton)
+ {
+ if(!KVSCSC_pSwitches->find('q',"quiet"))KVSCSC_pContext->warning(__tr2qs("No button with type %Q named %Q"),&tbTypeUnused,&tbName);
+ return true;
+ }
+ QChar o;
+ if (tbOp.length() > 0) o=tbOp[0];
+ else o=QChar('x');
+
+ // QChar o = tbOp.length() > 0 ? tbOp[0] : QChar('x');
+
+ switch(o.unicode())
+ {
+ case 't':
+ KviTalToolTip::remove(pButton);
+ KviTalToolTip::add(pButton,tbPar);
+ pButton->setButtonText(tbPar);
+ break;
+ case 'i':
+ if(!tbPar.isEmpty())
+ {
+ QPixmap * pix = g_pIconManager->getImage(tbPar);
+ if(pix)
+ {
+ pButton->setButtonPixmap(*pix);
+ } else {
+ if(!KVSCSC_pSwitches->find('q',"quiet"))KVSCSC_pContext->warning(__tr2qs("Can't find the icon '%Q'"),&tbPar);
+ }
+ }
+ break;
+ case 'e':
+ pButton->setEnabled(true);
+ break;
+ case 'd':
+ pButton->setEnabled(false);
+ break;
+ }
+ return true;
+
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: codepage
+ @type:
+ command
+ @title:
+ codepage
+ @syntax:
+ codepage <encoding name>
+ @short:
+ Tries to set the codepage on server
+ @description:
+ This is a not-widely implemented extension
+ that allows the user to set the codepage mapping
+ on server.
+ This command is a [doc:rfc2821wrappers]RFC2821 command wrapper[/doc]; see that document for more information.[br]
+ */
+ // RFC2821 wrapper
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: ctcp
+ @type:
+ command
+ @title:
+ ctcp
+ @syntax:
+ ctcp [-n] <target:string> <ctcp_data:string>
+ @short:
+ Sends a CTCP message
+ @description:
+ Sends a CTCP message to the specified <target>.[br]
+ The target may be a nickname , a channel, or a comma separated list of nicknames.[br]
+ The <ctcp_data> is a string containing the ctcp type followed by the ctcp parameters.[br]
+ For more info take a look at the [doc:ctcp_handling]ctcp protocol implementation notes[/doc].[br]
+ The CTCP message will be a request (sent through a PRIVMSG) unless the -n switch
+ specified: in that case it will be a reply (sent through a NOTICE).[br]
+ If <ctcp_data> is the single string "ping" then a trailing time string argument
+ is added in order to determine the round trip time when the ping reply comes back.
+ To override this behaviour simply specify your own time string parameter.[br]
+ This command is [doc:connection_dependant_commands]connection dependant[/doc].[br]
+ @examples:
+ [example]
+ ctcp Pragma VERSION
+ [/example]
+ */
+
+ KVSCSC(ctcp)
+ {
+ QString szTarget,szCtcpData;
+ KVSCSC_PARAMETERS_BEGIN
+ KVSCSC_PARAMETER("target",KVS_PT_NONEMPTYSTRING,0,szTarget)
+ KVSCSC_PARAMETER("ctcp_data",KVS_PT_STRING,KVS_PF_OPTIONAL | KVS_PF_APPENDREMAINING,szCtcpData)
+ KVSCSC_PARAMETERS_END
+
+ KVSCSC_REQUIRE_CONNECTION
+
+ if(KviQString::equalCI(szCtcpData,"PING"))
+ {
+ struct timeval tv;
+ kvi_gettimeofday(&tv,0);
+ KviQString::appendFormatted(szCtcpData," %d.%d",tv.tv_sec,tv.tv_usec);
+ }
+
+ KviQCString szT = KVSCSC_pConnection->encodeText(szTarget);
+ KviQCString szD = KVSCSC_pConnection->encodeText(szCtcpData);
+
+ if(!(KVSCSC_pConnection->sendFmtData("%s %s :%c%s%c",
+ KVSCSC_pSwitches->find('n',"notice") ? "NOTICE" : "PRIVMSG",szT.data(),0x01,szD.data(),0x01)))
+ return KVSCSC_pContext->warningNoIrcConnection();
+
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: debug
+ @type:
+ command
+ @title:
+ debug
+ @syntax:
+ debug <text>
+ @short:
+ Outputs text to the debug window
+ @switches:
+ @description:
+ Outputs the &lt;text&gt; to the debug window.[br]
+ @seealso:
+ */
+
+ KVSCSC(debug)
+ {
+ QString szAll;
+ KVSCSC_pParams->allAsString(szAll);
+ KviWindow * pWnd = KviDebugWindow::getInstance();
+ pWnd->outputNoFmt(KVI_OUT_NONE,szAll);
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: delete
+ @type:
+ command
+ @title:
+ delete
+ @syntax:
+ delete [-q] [-i] <objectHandle>
+ @short:
+ Destroys an object
+ @switches:
+ !sw: -q | --quiet
+ Causes the command to run quietly
+ !sw: -i | --immediate
+ Causes the object to be destroyed immediately
+ instead of simply scheduling its later deletion.
+ @description:
+ Schedules for destruction the object designed by <objectHandle>.
+ This command is internally aliased to [cmd]destroy[/cmd].
+ Please note that the object is NOT immediately destroyed:
+ it will be destroyed when KVIrc returns to the main event loop,
+ so after the current script code part has been executed.
+ This behaviour makes the object destruction safe in any
+ part of the script, but may lead to problems when
+ using signals and slots.[br]
+ For example, when you delete an object that emits some signals,
+ the signals may be still emitted after the delete call.
+ You have to disconnect the signals explicitly if you don't want it
+ to happen.[br]
+ Alternatively you can use the -i switch: it causes the object
+ to be destructed immediately but is intrinsicly unsafe:
+ in complex script scenarios it may lead to a SIGSEGV;
+ usually when called from one of the deleted object function
+ handlers, or from a slot connected to one of the deleted object
+ signals. Well, it actually does not SIGSEGV, but I can't guarantee it;
+ so, if use the -i switch, test your script 10 times before releasing it.
+ The -q switch causes the command to run a bit more silently: it still
+ complains if the parameter passed is not an object reference, but
+ it fails silently if the reference just points to an inexisting object (or is null).
+ @examples:
+ [example]
+ [/example]
+ */
+
+ /*
+ @doc: destroy
+ @type:
+ command
+ @title:
+ destroy
+ @syntax:
+ destroy [-q] [-i] <objectHandle>
+ @short:
+ Destroys an object
+ @description:
+ This is a builtin alias for the command [cmd]delete[/cmd]
+ */
+
+ KVSCSC(deleteCKEYWORDWORKAROUND)
+ {
+ kvs_hobject_t hObject;
+ KVSCSC_PARAMETERS_BEGIN
+ KVSCSC_PARAMETER("objectHandle",KVS_PT_HOBJECT,0,hObject)
+ KVSCSC_PARAMETERS_END
+ if(hObject == (kvs_hobject_t)0)
+ {
+ if(!KVSCSC_pSwitches->find('q',"quiet"))
+ KVSCSC_pContext->warning(__tr2qs("Can't delete a null object reference"));
+ } else {
+ KviKvsObject * o = KviKvsKernel::instance()->objectController()->lookupObject(hObject);
+ if(!o)
+ {
+ if(!KVSCSC_pSwitches->find('q',"quiet"))
+ KVSCSC_pContext->warning(__tr2qs("Can't delete an inexisting object"));
+ } else {
+ if(KVSCSC_pSwitches->find('i',"immediate"))
+ o->dieNow();
+ else
+ o->die();
+ }
+ }
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: delpopupitem
+ @type:
+ command
+ @title:
+ delpopupitem
+ @syntax:
+ delpopupitem [-d] [-q] <popupname:string> <item_id:string>
+ @short:
+ Deletes an item from a popup
+ @switches:
+ !sw: -q | --quiet
+ Run quietly
+ !sw: -d | --deep
+ Search the whole popup tree instead of only the first level
+ @description:
+ Deletes the item specified by <id> from the poup <popupname>.
+ If the -d flag is specified then the item with the specified
+ <id> is seached in the whole popup tree (containing submenus)
+ otherwise it is searched only in the first level.[br]
+ If the -q flag is specified the command does not complain
+ about inexisting items or inexisting popup menus.[br]
+ See [cmd]defpopup[/cmd] for more informations.[br]
+ @seealso:
+ [cmd]defpopup[/cmd], [cmd]popup[/cmd]
+ */
+ // FIXME: #warning "Separator should have the expression too ?"
+
+
+ KVSCSC(delpopupitem)
+ {
+ QString szPopupName,szItemId;
+ KVSCSC_PARAMETERS_BEGIN
+ KVSCSC_PARAMETER("popupname",KVS_PT_NONEMPTYSTRING,0,szPopupName)
+ KVSCSC_PARAMETER("item_id",KVS_PT_NONEMPTYSTRING,0,szItemId)
+ KVSCSC_PARAMETERS_END
+
+ KviKvsPopupMenu * p = KviKvsPopupManager::instance()->lookup(szPopupName);
+ if(!p)
+ {
+ if(!KVSCSC_pSwitches->find('q',"quiet"))
+ KVSCSC_pContext->warning(__tr2qs("Inexisting popup \"%Q\""),&szPopupName);
+ return true;
+ }
+
+ if(p->isLocked())
+ {
+ KVSCSC_pContext->error(__tr2qs("Popup menu self-modification is not allowed (the popup is probably open)"));
+ return false;
+ }
+
+ if(!p->removeItemByName(szItemId,KVSCSC_pSwitches->find('d',"deep")))
+ {
+ if(!KVSCSC_pSwitches->find('q',"quiet"))
+ KVSCSC_pContext->warning(__tr2qs("The menu item with id \"%Q\" does not exist in popup \"%Q\""),&szItemId,&szPopupName);
+ }
+
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: deop
+ @type:
+ command
+ @title:
+ deop
+ @syntax:
+ deop <nickname_list>
+ @short:
+ Removes chanop status from the specified users
+ @description:
+ Removes channel operator status to the users specified in <nickname_list>,
+ which is a comma separated list of nicknames.
+ This command works only if executed in a channel window.
+ The command is translated to a set of MODE messages containing
+ a variable number of -o flags.
+ This command is [doc:connection_dependant_commands]connection dependant[/doc].
+ @examples:
+ [example]
+ deop Pragma,Crocodile
+ [/example]
+ @seealso:
+ [cmd]op[/cmd], [cmd]voice[/cmd], [cmd]devoice[/cmd]
+ */
+
+ KVSCSC(deop)
+ {
+ return multipleModeCommand(__pContext,__pParams,__pSwitches,'-','o');
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: devoice
+ @type:
+ command
+ @title:
+ devoice
+ @syntax:
+ devoice <nickname_list>
+ @short:
+ Removes voice flag for the specified users
+ @description:
+ Removes the voice flag for the users specified in <nickname_list>,
+ which is a comma separated list of nicknames.
+ This command works only if executed in a channel window.
+ The command is translated to a set of MODE messages containing
+ a variable number of -v flags.
+ This command is [doc:connection_dependant_commands]connection dependant[/doc].
+ @examples:
+ [example]
+ devoice Pragma,Crocodile
+ [/example]
+ @seealso:
+ [cmd]op[/cmd], [cmd]deop[/cmd], [cmd]voice[/cmd]
+ */
+
+ KVSCSC(devoice)
+ {
+ return multipleModeCommand(__pContext,__pParams,__pSwitches,'-','v');
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: die
+ @type:
+ command
+ @title:
+ die
+ @syntax:
+ die <message:text>
+ @short:
+ Prints an error message and stops the script
+ @description:
+ Prints an error message and stops the current script
+ This command is equivalent to [cmd]error[/cmd]
+ */
+ // Internally aliased to error
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: echo
+ @type:
+ command
+ @title:
+ echo
+ @syntax:
+ echo [-d] [-w=<window_id>] [-i=<icon_number>] [-n] <text>
+ @short:
+ Outputs text to a KVirc window
+ @switches:
+ !sw: -w=<window_id> | --window=<window_id>
+ Causes the output to be redirected to the window specified by &lt;window_id&gt
+ !sw: -i=<icon_number> | --icon=<icon_number>
+ Causes the output to use the icon & color scheme specified by &lt;icon_number&gt
+ !sw: -n | --no-timestamp
+ Disables the message timestamping
+ !sw: -d | --debug
+ Send the output to the debug window (takes precedence over -w)
+ @description:
+ Outputs the &lt;text&gt; to the current window.[br]
+ If the 'w' switch is present , outputs the &lt;text&gt;
+ to the specified window instead of the current one.
+ The <window_id&> parameter is the [doc:window_naming_conventions]global ID[/doc] of the window
+ that has to be used.[br]
+ If the 'i' switch is given , it uses the specified
+ icon scheme (icon and colors) , otherwise it uses
+ the default one (0).[br]
+ If the -d switch is used then the output is sent to a special
+ window called "Debug" (the window is created if not existing yet).
+ This is useful for script debugging purposes (you get the output
+ in Debug regardless of the window that the executed command is attacched to).
+ The KVIrc view widgets support clickable links that can be realized by using special [doc:escape_sequences]escape sequences[/doc].[br]
+ The 'n' switch disables timestamping so you can output your own timestamp
+ or not timestamp at all.[br]
+ @examples:
+ [example]
+ echo Hey! this is my first echo test!
+ echo -i=10 This text has a specified icon and colors
+ echo --icon=[fnc]$icon[/fnc](parser error) this has the colors of the parser error messages
+ [/example]
+ @seealso:
+ [fnc]$window[/fnc],
+ [doc:window_naming_conventions]window naming conventions documentation[/doc]
+ */
+
+ KVSCSC(echo)
+ {
+ QString szAll;
+ KVSCSC_pParams->allAsString(szAll);
+
+ kvs_int_t iMsgType = KVI_OUT_NONE;
+ KviWindow * pWnd = KVSCSC_pContext->window();
+
+ if(!KVSCSC_pSwitches->isEmpty())
+ {
+ KviKvsVariant * v;
+ if((v = KVSCSC_pSwitches->find('w',"window")))
+ {
+ QString szWnd;
+ v->asString(szWnd);
+ //#warning "FIXME: the window database is not unicode! (we even could keep integer window id's at this point!)"
+ pWnd = g_pApp->findWindow(szWnd.utf8().data());
+ if(!pWnd)
+ {
+ KVSCSC_pContext->warning(__tr2qs("The argument of the -w switch did not evaluate to a valid window id: using default"));
+ pWnd = KVSCSC_pContext->window();
+ }
+ }
+
+ if((v = KVSCSC_pSwitches->find('i',"icon")))
+ {
+ if(!v->asInteger(iMsgType))
+ {
+ KVSCSC_pContext->warning(__tr2qs("The argument of the i switch did not evaluate to a number: using default"));
+ iMsgType = KVI_OUT_NONE;
+ } else {
+ iMsgType = iMsgType % KVI_NUM_MSGTYPE_OPTIONS;
+ }
+ }
+
+ if(KVSCSC_pSwitches->find('d',"debug"))
+ {
+ pWnd = KviDebugWindow::getInstance();
+ }
+ }
+
+ int iFlags = KVSCSC_pSwitches->find('n',"no-timestamp") ? KviIrcView::NoTimestamp : 0;
+ pWnd->outputNoFmt(iMsgType,szAll,iFlags);
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: echoprivmsg
+ @type:
+ command
+ @title:
+ echoprivmsg
+ @syntax:
+ echoprivmsg [switches] <nick:string> <user:string> <host:string> <text:string>
+ @short:
+ Outputs text to a KVIrc window
+ @switches:
+ !sw: -p[=<nick_prefix>] | --prefix[=<prefix>]
+ The message is printed with the specified custom nickname prefix.
+ If <nick_prefix> is omitted then an empty string is assumed.
+ !sw: -s[=<nick_suffix>] | --suffix[=<nicksuffix>]
+ The message is printed with the specified custom nickname suffix.
+ If <nick_suffix> is omitted then an empty string is assumed.
+ !sw: -w=<window_id> | --window=<window_id>
+ The message is printed to the window specified by [doc:window_naming_conventions]window_id[/doc]
+ !sw: -i=<color_set> | --color-set=<color_set>
+ Causes the message to use the specified icon scheme (icon and colors).
+ !sw: -n | --no-highlighting
+ Do not apply the highlighting rules
+ !sw: -x | --no-notifier
+ Never cause the notifier window to pop up
+ !sw: -f | --no-flashing
+ Never cause the window taskbar entry to flash (this works only on some platforms)
+ @description:
+ Outputs a <text> to the current window in the privmsg format.[br]
+ The <nick> <user> and <host> parameters are formatted
+ as specified by the user preferences (for example
+ the nick may use smart colorisation).
+ If you don't know the username and host then just use '*' for
+ that parameters.
+ The message will also get the highlighting rules applied.
+ If the 'w' switch is present, outputs <text>
+ to the specified window instead of the current one.
+ The <window_id> parameter is the [doc:window_naming_conventions]global ID[/doc] of the window
+ that has to be used.[br]
+ Please note that this is not the same as the standard
+ [doc:command_rebinding]-r rebinding switch[/doc]:
+ -w causes the specified window to be used only for output,
+ but the command parameters are evaluated in the current window.[br]
+ If the 'i' switch is given , it uses the specified
+ icon scheme (icon and colors) , otherwise it uses
+ the default one (0).[br]
+ If the -n switch is present then the highlighting rules
+ are not applied.[br]
+ If the -x switch is present then the message will never cause
+ the notifier window to be popped up.[br]
+ If the -f switch is present then the message will never cause
+ the system taskbar to flash.[br]
+ Actually -x and -f have a sense only if highlighting is used and thus -n is not present.[br]
+ For more informations about the icon/color schemes see [fnc]$msgtype[/fnc].
+ The KVIrc view widgets support clickable sockets that can be realized by using special [doc:escape_sequences]escape sequences[/doc].[br]
+ @examples:
+ [example]
+ echoprivmsg Test * * This is a test message
+ echoprivmsg -i=$msgtype(ChanPrivmsgCrypted) Pragma pragma staff.kvirc.net Hi people! :)
+ [/example]
+ @seealso:
+ [fnc]$window[/fnc],
+ [fnc]$window.caption[/fnc],
+ [fnc]$msgtype[/fnc],
+ [cmd]echo[/cmd],
+ [doc:window_naming_conventions]Window Naming Conventions[/doc]
+ */
+
+ KVSCSC(echoprivmsg)
+ {
+ QString szNick,szUser,szHost,szText;
+ KVSCSC_PARAMETERS_BEGIN
+ KVSCSC_PARAMETER("nick",KVS_PT_NONEMPTYSTRING,0,szNick)
+ KVSCSC_PARAMETER("user",KVS_PT_STRING,0,szUser)
+ KVSCSC_PARAMETER("host",KVS_PT_STRING,0,szHost)
+ KVSCSC_PARAMETER("text",KVS_PT_STRING,KVS_PF_OPTIONAL | KVS_PF_APPENDREMAINING,szText)
+ KVSCSC_PARAMETERS_END
+
+ int type = KVI_OUT_NONE;
+ KviWindow * pWnd = KVSCSC_pWindow;
+ KviConsole * pConsole = pWnd->console();
+ if(!pConsole)pConsole = g_pApp->activeConsole();
+
+ KviKvsVariant * v;
+
+ if(v = KVSCSC_pSwitches->find('i',"color-set"))
+ {
+ kvs_int_t msgType;
+ if(v->asInteger(msgType))
+ {
+ if(msgType < 0)msgType = -msgType;
+ type = (int)(msgType % KVI_NUM_MSGTYPE_OPTIONS);
+ } else KVSCSC_pContext->warning(__tr2qs("Invalid color-set specification, using default"));
+ }
+
+ if(v = KVSCSC_pSwitches->find('w',"window"))
+ {
+ QString szWin;
+ v->asString(szWin);
+ KviStr window = szWin;
+ pWnd = g_pApp->findWindow(window.ptr());
+ if(!pWnd)
+ {
+ KVSCSC_pContext->warning(__tr2qs("Window '%s' not found, using current one"),window.ptr());
+ pWnd = KVSCSC_pWindow;
+ }
+ }
+
+ QString szPrefix,szSuffix;
+ bool bPrefix = false;
+ bool bSuffix = false;
+
+ if(v = KVSCSC_pSwitches->find('p',"prefix"))
+ {
+ v->asString(szPrefix);
+ bPrefix = true;
+ }
+ if(v = KVSCSC_pSwitches->find('s',"suffix"))
+ {
+ v->asString(szSuffix);
+ bSuffix = true;
+ }
+
+ int iFlags = 0;
+ if(KVSCSC_pSwitches->find('n',"no-highlighting"))iFlags |= KviConsole::NoHighlighting;
+ if(KVSCSC_pSwitches->find('f',"no-flashing"))iFlags |= KviConsole::NoWindowFlashing;
+ if(KVSCSC_pSwitches->find('x',"no-notifier"))iFlags |= KviConsole::NoNotifier;
+
+ pConsole->outputPrivmsg(pWnd,type,
+ szNick,szUser,szHost,szText,
+ iFlags,
+ bPrefix ? szPrefix : QString::null,bSuffix ? szSuffix : QString::null);
+
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: error
+ @type:
+ command
+ @title:
+ error
+ @syntax:
+ error <message:text>
+ @short:
+ Prints an error message and stops the script
+ @description:
+ Prints an error message and stops the current script
+ This command is equivalent to [cmd]die[/cmd]
+ @seealso:
+ [cmd]warning[/cmd]
+ */
+
+ KVSCSC(error)
+ {
+#ifdef COMPILE_NEW_KVS
+ QString szAll;
+ KVSCSC_pParams->allAsString(szAll);
+ KVSCSC_pContext->error("%Q",&szAll);
+#endif
+ return false;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: eval
+ @type:
+ command
+ @title:
+ eval
+ @syntax:
+ eval [-q] [-r=<window>] <command>
+ @switches:
+ !sw: -q | --quiet
+ Disable any error output
+ !sw: -f | --force
+ Continue execution even if <command> fails with an error
+ @short:
+ Change the behaviour of a set of commands
+ @description:
+ This command is useful to execute variable command sequences.[br]
+ <command> is first evaluated as a normal parameter (thus identifiers
+ and variables are substituted) then the evaluated string is executed
+ as a command sequence.[br]
+ -q causes eval to run quietly and don't display any errors in the inner command.[br]
+ -f causes eval to ignore the errors inside <command> and continue execution.[br]
+ This command may be used to rebind the <command> to a specified window.
+ <command> shares the local variables with this command scope so you
+ can easily exchange data with it.
+ Remember that <command> is still a normal parameter and it must be
+ enclosed in quotes if youwant it to be a complex command sequence.
+ eval propagates the <command> return value.[br]
+ @examples:
+ [example]
+ [comment]# evaluate a variable command[/comment]
+ [cmd]if[/cmd](%somecondition)%tmp = "echo yeah"
+ else %tmp = "echo -i=10 yeah"
+ eval %tmp
+ [comment]# Rebind the command to the #linux channel to get the user list[/comment]
+ eval -r=[fnc]$channel[/fnc](#linux) "%Nicks[]=$chan.array;"
+ [comment]# A nice alias that allows iterating commands through all the consoles[/comment]
+ [comment]# This is by LatinSuD :)[/comment]
+ [cmd]alias[/cmd](iterate)
+ {
+ %ctxt[]=[fnc]$window.list[/fnc](console,all)
+ [cmd]for[/cmd](%i=0;%i<%ctxt[]#;%i++)
+ {
+ [cmd]eval[/cmd] -r=%ctxt[%i] $0-
+ }
+ }
+ iterate [cmd]echo[/cmd] Hi ppl! :)
+ [comment]# A little bit shorter (but less "colorful") version might be...[/comment]
+ [cmd]alias[/cmd](iterate)
+ {
+ [cmd]foreach[/cmd](%x,[fnc]$window.list[/fnc](console,all))
+ [cmd]eval[/cmd] -r=%x $0-;
+ }
+ iterate [cmd]echo[/cmd] Hi again!
+ [comment]# Evaluate a command block[/comment]
+ eval "{ echo First command!; echo Second command!; }"
+ [/example]
+ */
+
+ KVSCSC(eval)
+ {
+ QString szCommands;
+ KVSCSC_PARAMETERS_BEGIN
+ KVSCSC_PARAMETER("commands",KVS_PT_STRING,KVS_PF_APPENDREMAINING,szCommands)
+ KVSCSC_PARAMETERS_END
+
+ KviKvsScript s("eval::inner",szCommands);
+ int iRunFlags = 0;
+ if(KVSCSC_pContext->reportingDisabled() || KVSCSC_pSwitches->find('q',"quiet"))
+ iRunFlags |= KviKvsScript::Quiet;
+ bool bRet = s.run(KVSCSC_pContext,iRunFlags) ? true : false;
+ if(!bRet)
+ {
+ if(!KVSCSC_pSwitches->find('f',"force"))
+ return false;
+ KVSCSC_pContext->clearError();
+ }
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: eventctl
+ @title:
+ eventctl
+ @type:
+ command
+ @short:
+ Controls the execution of event handlers
+ @syntax:
+ eventctl [-u] [-e] [-d] [-q] <event_name:string> <handler_name:string> [parameters]
+ @switches:
+ !sw: -u | --unregister
+ Unregisters the specified handler
+ !sw: -e | --enable
+ Enables the specified handler
+ !sw: -d | --disable
+ Disables the specified handler
+ !sw: -q | --quiet
+ Do not print any warnings
+ @description:
+ Performs control actions on the handler <handler_name> for
+ the event <event_name>.
+ Without any switch it triggers the handler for testing purposes,
+ eventually passing [parameters].[br]
+ With the -u switch the handler <handler_name> is unregistered.[br]
+ With the -d swtich is is disabled (so it is never executed)
+ and with -e is enabled again.[br]
+ The <event_name> may be one of the kvirc-builtin event names
+ or a numeric code (from 0 to 999) of a raw server message.[br]
+ @seealso:
+ [cmd]event[/cmd]
+ */
+ KVSCSC(eventctl)
+ {
+ QString szEventName,szHandlerName;
+ KviKvsVariantList vList;
+ KVSCSC_PARAMETERS_BEGIN
+ KVSCSC_PARAMETER("event_name",KVS_PT_NONEMPTYSTRING,0,szEventName)
+ KVSCSC_PARAMETER("handler_name",KVS_PT_NONEMPTYSTRING,0,szHandlerName)
+ KVSCSC_PARAMETER("parameters",KVS_PT_VARIANTLIST,KVS_PF_OPTIONAL,vList)
+ KVSCSC_PARAMETERS_END
+
+ bool bOk;
+ int iNumber = szEventName.toInt(&bOk);
+ bool bIsRaw = (bOk && (iNumber >= 0) && (iNumber < 1000));
+
+ if(bIsRaw)
+ {
+ if(!KviKvsEventManager::instance()->isValidRawEvent(iNumber))
+ {
+ if(!KVSCSC_pSwitches->find('q',"quiet"))
+ KVSCSC_pContext->warning(__tr2qs("No such event (%Q)"),&szEventName);
+ return true;
+ }
+ } else {
+ iNumber = KviKvsEventManager::instance()->findAppEventIndexByName(szEventName);
+ if(!KviKvsEventManager::instance()->isValidAppEvent(iNumber))
+ {
+ if(!KVSCSC_pSwitches->find('q',"quiet"))
+ KVSCSC_pContext->warning(__tr2qs("No such event (%Q)"),&szEventName);
+ return true;
+ }
+ }
+
+ if(KVSCSC_pSwitches->find('u',"unregister"))
+ {
+ // unregister it
+ if(bIsRaw)
+ {
+ if(!KviKvsEventManager::instance()->removeScriptRawHandler(iNumber,szHandlerName))
+ if(!KVSCSC_pSwitches->find('q',"quiet"))
+ KVSCSC_pContext->warning(__tr2qs("No handler '%Q' for raw numeric event '%d'"),&szHandlerName,iNumber);
+ } else {
+ if(!KviKvsEventManager::instance()->removeScriptAppHandler(iNumber,szHandlerName))
+ if(!KVSCSC_pSwitches->find('q',"quiet"))
+ KVSCSC_pContext->warning(__tr2qs("No handler '%Q' for event '%Q'"),&szHandlerName,&szEventName);
+ }
+ } else if(KVSCSC_pSwitches->find('e',"enable") || KVSCSC_pSwitches->find('d',"disable"))
+ {
+ // enable it
+ if(bIsRaw)
+ {
+ if(!KviKvsEventManager::instance()->enableScriptRawHandler(iNumber,szHandlerName,KVSCSC_pSwitches->find('e',"enable")))
+ if(!KVSCSC_pSwitches->find('q',"quiet"))
+ KVSCSC_pContext->warning(__tr2qs("No handler '%Q' for raw numeric event '%d'"),&szHandlerName,iNumber);
+ } else {
+ if(!KviKvsEventManager::instance()->enableScriptAppHandler(iNumber,szHandlerName,KVSCSC_pSwitches->find('e',"enable")))
+ if(!KVSCSC_pSwitches->find('q',"quiet"))
+ KVSCSC_pContext->warning(__tr2qs("No handler '%Q' for event '%Q'"),&szHandlerName,&szEventName);
+ }
+ } else {
+ // trigger it
+ KviKvsScriptEventHandler * h;
+ QString code;
+
+ if(bIsRaw)
+ {
+ h = KviKvsEventManager::instance()->findScriptRawHandler(iNumber,szHandlerName);
+ } else {
+ h = KviKvsEventManager::instance()->findScriptAppHandler(iNumber,szHandlerName);
+ }
+
+ if(h)
+ {
+ KviKvsScript * s = h->script();
+ KviKvsScript copy(*s);
+ KviKvsVariant retVal;
+ copy.run(KVSCSC_pWindow,&vList,0,KviKvsScript::PreserveParams);
+ } else {
+ if(!KVSCSC_pSwitches->find('q',"quiet"))
+ KVSCSC_pContext->warning(__tr2qs("No handler '%Q' for event '%Q'"),&szHandlerName,&szEventName);
+ }
+ }
+
+ return true;
+ }
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: exit
+ @type:
+ command
+ @title:
+ exit
+ @syntax:
+ exit
+ @switches:
+ @short:
+ Closes KVIrc
+ @description:
+ It closes KVirc application
+ */
+
+ KVSCSC(exit)
+ {
+ g_pApp->quit();
+ return true;
+ }
+
+};
diff --git a/src/kvirc/kvs/kvi_kvs_coresimplecommands_gl.cpp b/src/kvirc/kvs/kvi_kvs_coresimplecommands_gl.cpp
new file mode 100644
index 00000000..a43a33cf
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_coresimplecommands_gl.cpp
@@ -0,0 +1,693 @@
+//=============================================================================
+//
+// File : kvi_kvs_coresimplecommands_gl.cpp
+// Created on Fri 31 Oct 2003 00:04:25 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_coresimplecommands.h"
+
+#include "kvi_kvs_timermanager.h"
+#include "kvi_kvs_asyncdnsoperation.h"
+#include "kvi_kvs_script.h"
+
+#include "kvi_fileutils.h"
+#include "kvi_ircconnection.h"
+#include "kvi_ircconnectionserverinfo.h"
+#include "kvi_locale.h"
+
+#include "kvi_out.h"
+
+#ifdef COMPILE_USE_QT4
+ #include <q3mimefactory.h>
+#endif
+
+namespace KviKvsCoreSimpleCommands
+{
+ /*
+ @doc: halt
+ @type:
+ command
+ @title:
+ halt
+ @syntax:
+ halt
+ @short:
+ Stops the execution of the current script
+ @description:
+ Stops the execution of the current script.[br]
+ Note that this is different from [cmd]return[/cmd]: halt doesn't
+ set the return value (use [cmd]setreturn[/cmd] for that) and
+ in the event handlers this command may have additional semantics:
+ refer to the specific event documentation for more info.[br]
+ In fact , this command should be used [b]only[/b] in the event handlers,
+ use [cmd]return[/cmd] in any other context.[br]
+ */
+
+ KVSCSC(halt)
+ {
+#ifdef COMPILE_NEW_KVS
+ KVSCSC_pContext->setHaltCalled();
+#endif
+ return false;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: help
+ @type:
+ command
+ @title:
+ help
+ @syntax:
+ help [-s] <topic>
+ @short:
+ Shows a help page
+ @description:
+ Shows a help page about <topic>.[br]
+ <topic> can be a command name , or an identifier.[br]
+ If <topic> starts with a slash , it is assumed to be a full path
+ to a html file to be displayed in the help browser.[br]
+ This command is a shortcut for the [cmd]help.open[/cmd] module command.[br]
+ @examples:
+ [example]
+ help run
+ help help
+ help index
+ help $mask
+ help /home/pragma/myfile.html
+ [/example]
+ */
+
+ static bool file_in_path(QStringList &pathlist,QString &file)
+ {
+ for(QStringList::Iterator it = pathlist.begin();it != pathlist.end();++it)
+ {
+ QString tmp = *it;
+ tmp.append('/');
+ tmp.append(file);
+ KviFileUtils::adjustFilePath(tmp);
+ if(KviFileUtils::fileExists(tmp))return true;
+ }
+ return false;
+ }
+
+ KVSCSC(help)
+ {
+ QString szTopic;
+ KVSCSC_PARAMETERS_BEGIN
+ KVSCSC_PARAMETER("topic",KVS_PT_STRING,KVS_PF_OPTIONAL | KVS_PF_APPENDREMAINING,szTopic)
+ KVSCSC_PARAMETERS_END
+
+ szTopic.stripWhiteSpace();
+ if(szTopic.endsWith(";"))
+ {
+ szTopic.truncate(szTopic.length() - 1);
+ szTopic.stripWhiteSpace();
+ }
+
+ QString szCommand;
+ if(szTopic.isEmpty())szCommand = "help.open index.html";
+ else {
+ bool bWasFunc = false;
+ if(szTopic[0] == QChar('$'))
+ {
+ bWasFunc = true;
+ szTopic.remove(0,1);
+ }
+
+ QString szOriginal = szTopic;
+
+ QString topik = szTopic;
+#ifdef COMPILE_USE_QT4
+ QStringList pl = Q3MimeSourceFactory::defaultFactory()->filePath();
+#else
+ QStringList pl = QMimeSourceFactory::defaultFactory()->filePath();
+#endif
+
+ bool bLowCaseTried = false;
+ bool bFound = KviFileUtils::fileExists(szTopic);
+
+try_again:
+ if((!bFound) && bWasFunc)
+ {
+ topik = szTopic;
+ topik += ".html";
+ topik.prepend("fnc_");
+ bFound = file_in_path(pl,topik);
+ }
+
+ if(!bFound)
+ {
+ topik = szTopic;
+ bFound = file_in_path(pl,topik);
+ }
+
+ if(!bFound)
+ {
+ topik = szTopic;
+ topik += ".html";
+ bFound = file_in_path(pl,topik);
+ }
+
+ if(!bFound)
+ {
+ topik = szTopic;
+ topik += ".html";
+ topik.prepend("cmd_");
+ bFound = file_in_path(pl,topik);
+ }
+
+ if(!bFound)
+ {
+ topik = szTopic;
+ topik += ".html";
+ topik.prepend("doc_");
+ bFound = file_in_path(pl,topik);
+ }
+
+ if(!bFound)
+ {
+ topik = szTopic;
+ topik += ".html";
+ topik.prepend("event_");
+ bFound = file_in_path(pl,topik);
+ }
+
+ if(!bFound)
+ {
+ topik = szTopic;
+ topik += ".html";
+ topik.prepend("module_");
+ bFound = file_in_path(pl,topik);
+ }
+
+ if(!bFound)
+ {
+ topik = szTopic;
+ topik += ".html";
+ topik.prepend("widget_");
+ bFound = file_in_path(pl,topik);
+ }
+
+ if(!bFound)
+ {
+ topik = szTopic;
+ topik += ".html";
+ topik.prepend("class_");
+ bFound = file_in_path(pl,topik);
+ }
+
+ if(!bFound && !bLowCaseTried)
+ {
+ // try again with lowercase
+ szTopic = szTopic.lower();
+ bLowCaseTried = true;
+ goto try_again;
+ }
+
+ if(!bFound)
+ {
+ // let the help.open function decide...
+ topik = szOriginal;
+ topik += ".html";
+ }
+
+ szCommand = "help.open ";
+ szCommand += topik;
+ }
+
+ // We don't care about the return value...
+ KviKvsScript s("help",szCommand);
+ s.run(KVSCSC_pContext->window());
+
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: host
+ @type:
+ command
+ @title:
+ host
+ @syntax:
+ host [-i] [-a] <dnsquery:string>
+ @short:
+ DNS lookup
+ @switches:
+ !sw: --ipv6 | -i
+ Causes the command to run in IPv6 mode
+ !sw: --any | -a
+ Causes the command to run in unspecified mode and lookup both IPv4 and IPv6 addresses
+ @description:
+ Starts a DNS lookup for the <dnsquery> (hostname) and prints
+ the results in the current window.[br]
+ The -i switch causes the command to execute
+ in IpV6 mode (and lookup ONLY IpV6 hosts!).[br]
+ The -a switch causes the command to run in "unspecified" mode
+ and return any available address: IpV4 or Ipv6.[br]
+ This command also performs reverse lookups (if you pass an IP address as <hostname>).[br]
+ @examples:
+ [example]
+ host localhost
+ host irc.flashnet.it
+ host -i irc.flashnet.it
+ host -i A0E0:FFFF:::1010:1111:E0E0:A0A0
+ host -a 127.0.0.1
+ host 255.41.31.23
+ host -a irc.stealth.net
+ [/example]
+ @seealso:
+ [cmd]ahost[/cmd]
+ */
+
+ KVSCSC(host)
+ {
+ QString szQuery;
+ KVSCSC_PARAMETERS_BEGIN
+ KVSCSC_PARAMETER("dnsquery",KVS_PT_NONEMPTYSTRING,0,szQuery)
+ KVSCSC_PARAMETERS_END
+
+ KviDns::QueryType queryType = KviDns::IpV4;
+ if(KVSCSC_pSwitches->find('i',"ipv6"))queryType = KviDns::IpV6;
+ if(KVSCSC_pSwitches->find('a',"any"))queryType = KviDns::Any;
+
+ KviKvsAsyncDnsOperation * op = new KviKvsAsyncDnsOperation(
+ KVSCSC_pContext->window(),
+ szQuery,
+ queryType);
+
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: include
+ @type:
+ command
+ @title:
+ include
+ @syntax:
+ include [-q] [-e] [-f] [-r] <filename:string> [<parameter1:variant> [<parameter2:variant> [...]]]
+ @short:
+ A builtin alias for parse
+ @description:
+ This is a builtin alias for [cmd]parse[/cmd] that gives scripts a "more C-ish" look :)
+ @seealso:
+ [cmd]parse[/cmd]
+ */
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: info
+ @type:
+ command
+ @title:
+ info
+ @syntax:
+ info [target server]
+ @short:
+ Requests the server daemon info from a server
+ @description:
+ Requests server daemon information from the specified server or the current server if no [target server] is specified.[br]
+ This command is a [doc:rfc2821wrappers]RFC2821 command wrapper[/doc]; see that document for more information.[br]
+ */
+ // RFC2821 wrapper
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: invite
+ @type:
+ command
+ @title:
+ invite
+ @syntax:
+ invite <nickname> <channel>
+ @short:
+ Invites an user to a channel
+ @description:
+ Invites the specified user to the <channel>.[br]
+ This command is a [doc:rfc2821wrappers]RFC2821 command wrapper[/doc]; see that document for more information.[br]
+ */
+ // RCF2821 wrapper
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: join
+ @type:
+ command
+ @title:
+ join
+ @syntax:
+ join <channel list> [key list]
+ @short:
+ Joins the specified channels
+ @description:
+ Joins the channels specified in <channel list> by using the
+ optional keys in the [key list].[br]
+ This command is "server based"; you will see its results only
+ after the server acknowledges it.[br]
+ This command is [doc:connection_dependant_commands]connection dependant[/doc].[br]
+ @examples:
+ [example]
+ join #kvirc
+ join #linux-it,#xmms,#kde linus
+ [/example]
+ */
+
+ KVSCSC(join)
+ {
+ QString szChans,szKeys;
+ KVSCSC_PARAMETERS_BEGIN
+ KVSCSC_PARAMETER("chans",KVS_PT_NONEMPTYSTRING,0,szChans)
+ KVSCSC_PARAMETER("keys",KVS_PT_STRING,KVS_PF_OPTIONAL,szKeys)
+ KVSCSC_PARAMETERS_END
+
+ KVSCSC_REQUIRE_CONNECTION
+
+ QStringList slChans = QStringList::split(",",szChans);
+
+ QString szChanTypes = KVSCSC_pConnection->serverInfo()->supportedChannelTypes();
+ for(QStringList::Iterator it=slChans.begin();it != slChans.end();++it)
+ {
+ if(!(*it).isEmpty())
+ {
+ bool bFound = false;
+ int id = 0;
+ QChar f = (*it)[0];
+ while((id < szChanTypes.length()) && !bFound)
+ {
+ if(f == szChanTypes[id])bFound = true;
+ id++;
+ }
+ if(!bFound)
+ (*it).prepend("#");
+ }
+ }
+
+ szChans = slChans.join(",");
+ KviQCString szEncodedChans = KVSCSC_pConnection->encodeText(szChans);
+
+ if(szKeys.isEmpty())
+ {
+ if(!(KVSCSC_pConnection->sendFmtData("JOIN %s",szEncodedChans.data())))
+ return KVSCSC_pContext->warningNoIrcConnection();
+ } else {
+ KviQCString szEncodedKeys = KVSCSC_pConnection->encodeText(szKeys);
+ if(!(KVSCSC_pConnection->sendFmtData("JOIN %s %s",szEncodedChans.data(),szEncodedKeys.data())))
+ return KVSCSC_pContext->warningNoIrcConnection();
+ }
+
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: kick
+ @type:
+ command
+ @title:
+ kick
+ @syntax:
+ kick <user:string> [reason:string]
+ @short:
+ Kicks an user from a channel
+ @description:
+ Kicks the specified <user> from the current channel.[br]
+ This command is a simple wrapper over the IRC KICK command.
+ This command is [doc:connection_dependant_commands]connection dependant[/doc].
+ @examples:
+ [example]
+ kick Pragma Go coding in Pascal!
+ [/example]
+ */
+
+ KVSCSC(kick)
+ {
+ QString szUser;
+ QString szReason;
+ KVSCSC_PARAMETERS_BEGIN
+ KVSCSC_PARAMETER("user",KVS_PT_NONEMPTYSTRING,0,szUser)
+ KVSCSC_PARAMETER("reason",KVS_PT_STRING,KVS_PF_OPTIONAL | KVS_PF_APPENDREMAINING,szReason)
+ KVSCSC_PARAMETERS_END
+
+ KVSCSC_REQUIRE_CONNECTION
+
+ if(KVSCSC_pWindow->type() != KVI_WINDOW_TYPE_CHANNEL)
+ {
+ KVSCSC_pContext->warning(__tr2qs("The current window is not a channel"));
+ return false;
+ }
+
+ KviQCString szC = KVSCSC_pConnection->encodeText(KVSCSC_pWindow->target());
+ KviQCString szU = KVSCSC_pConnection->encodeText(szUser);
+ KviQCString szR = KVSCSC_pConnection->encodeText(szReason);
+
+ if(szR.isEmpty())
+ {
+ if(!KVSCSC_pConnection->sendFmtData("KICK %s %s",szC.data(),szU.data()))
+ return KVSCSC_pContext->warningNoIrcConnection();
+ } else {
+ if(!KVSCSC_pConnection->sendFmtData("KICK %s %s :%s",szC.data(),szU.data(),szR.data()))
+ return KVSCSC_pContext->warningNoIrcConnection();
+ }
+
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: killtimer
+ @title:
+ killtimer
+ @type:
+ command
+ @short:
+ Stops a timer
+ @syntax:
+ killtimer [-a]
+ killtimer [-q] [name]
+ @switches:
+ !sw: -a | --active
+ Requests to kill all the active timers
+ !sw: -q | --quiet
+ Does not print warnings if the specified timer is not running
+ @description:
+ The first version (with -a) kill all the running timers.[br]
+ The second verdion kills a running timer named [name].[br]
+ The timer has been started by the [cmd]timer[/cmd].[br]
+ [name] can be omitted if this command is called from a [cmd]timer[/cmd] callback:
+ in this case the current timer will be scheduled for killing immediately
+ after it has returned control to KVIrc.
+ @seealso:
+ [cmd]timer[/cmd], [fnc]$isTimer[/fnc], [cmd]listtimers[/cmd]
+ */
+
+ KVSCSC(killtimer)
+ {
+ QString szName;
+ KVSCSC_PARAMETERS_BEGIN
+ KVSCSC_PARAMETER("name",KVS_PT_STRING,KVS_PF_OPTIONAL,szName)
+ KVSCSC_PARAMETERS_END
+
+ if(KVSCSC_pSwitches->find('a',"active"))
+ {
+ KviKvsTimerManager::instance()->deleteAllTimers();
+ return true;
+ }
+
+ if(szName.isEmpty())
+ {
+ if(!KviKvsTimerManager::instance()->deleteCurrentTimer())
+ {
+ if(!KVSCSC_pSwitches->find('q',"quiet"))
+ KVSCSC_pContext->warning(__tr2qs("Timer name omitted but there is not current timer (this is not a timer callback)"));
+ }
+ } else {
+ if(!KviKvsTimerManager::instance()->deleteTimer(szName))
+ {
+ if(!KVSCSC_pSwitches->find('q',"quiet"))
+ KVSCSC_pContext->warning(__tr2qs("Can't kill the timer '%Q' since it is not running"),&szName);
+ }
+ }
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: leave
+ @type:
+ command
+ @title:
+ leave
+ @syntax:
+ leave [-k] [-q] [-s] <channel list> [part message]
+ @short:
+ Alias for part
+ @description:
+ Builtin alias for the command [cmd]part[/cmd].
+ */
+ // Internally aliased to leave
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: links
+ @type:
+ command
+ @title:
+ links
+ @syntax:
+ links
+ @short:
+ Lists server links
+ @description:
+ List server links.[br]
+ The syntax of the parameters of this command is different on many servers.[br]
+ This command is a [doc:rfc2821wrappers]RFC2821 command wrapper[/doc]; see that document for more information.[br]
+ */
+ // RFC2821 wrapper
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: list
+ @type:
+ command
+ @title:
+ list
+ @syntax:
+ list [ <channel> *( "," <channel> ) [ <target> ] ]
+ @short:
+ Lists channels
+ @description:
+ List channels.[br]
+ The syntax of the parameters of this command is different on many servers.[br]
+ This command is a [doc:rfc2821wrappers]RFC2821 command wrapper[/doc]; see that document for more information.[br]
+ */
+ // RFC2821 wrapper
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: listtimers
+ @title:
+ listtimers
+ @type:
+ command
+ @short:
+ Lists the active timers
+ @syntax:
+ listtimers
+ @description:
+ Lists the currently active timers
+ @seealso:
+ [cmd]timer[/cmd], [fnc]$isTimer[/fnc], [cmd]killtimer[/cmd]
+ */
+
+ KVSCSC(listtimers)
+ {
+ KviPointerHashTable<QString,KviKvsTimer> * pTimerDict = KviKvsTimerManager::instance()->timerDict();
+
+ if(!pTimerDict)
+ return true;
+
+ KviPointerHashTableIterator<QString,KviKvsTimer> it(*pTimerDict);
+
+ KVSCSC_pContext->window()->outputNoFmt(KVI_OUT_VERBOSE,__tr2qs("List of active timers"));
+
+ unsigned int uCnt = 0;
+
+ while(KviKvsTimer * pTimer = it.current())
+ {
+ QString szName = pTimer->name();
+ QString szLifetime;
+ switch(pTimer->lifetime())
+ {
+ case KviKvsTimer::Persistent:
+ szLifetime = __tr2qs("Persistent");
+ break;
+ case KviKvsTimer::WindowLifetime:
+ szLifetime = __tr2qs("WindowLifetime");
+ break;
+ case KviKvsTimer::SingleShot:
+ szLifetime = __tr2qs("SingleShot");
+ break;
+ default:
+ szLifetime = __tr2qs("Unknown");
+ break;
+ }
+ QString szDelay;
+ szDelay.setNum(pTimer->delay());
+ QString szWindow;
+ szWindow = pTimer->window() ? pTimer->window()->id() : __tr2qs("None");
+
+ KVSCSC_pContext->window()->output(KVI_OUT_VERBOSE,
+ "Timer \"%Q\": Lifetime: %Q, Delay: %Q, Window: %Q",
+ &szName,&szLifetime,&szDelay,&szWindow
+ );
+
+ uCnt++;
+ ++it;
+ }
+
+ KVSCSC_pContext->window()->output(KVI_OUT_VERBOSE,__tr2qs("Total: %u timers running"),uCnt);
+
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: lusers
+ @type:
+ command
+ @title:
+ lusers
+ @syntax:
+ lusers [ <mask> [ <target> ] ]
+ @short:
+ Requests statistics about users on IRC
+ @description:
+ The LUSERS command is used to get statistics about the size of the
+ IRC network.[br]If no parameter is given, the reply will be about the
+ whole net.[br]If a <mask> is specified, then the reply will only
+ concern the part of the network formed by the servers matching the
+ mask.[br]Finally, if the <target> parameter is specified, the request
+ is forwarded to that server which will generate the reply.[br]
+ This command is a [doc:rfc2821wrappers]RFC2821 command wrapper[/doc]; see that document for more information.[br]
+ */
+ // RFC2821 wrapper
+
+
+};
+
diff --git a/src/kvirc/kvs/kvi_kvs_coresimplecommands_mr.cpp b/src/kvirc/kvs/kvi_kvs_coresimplecommands_mr.cpp
new file mode 100644
index 00000000..e0ac9174
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_coresimplecommands_mr.cpp
@@ -0,0 +1,1335 @@
+//=============================================================================
+//
+// File : kvi_kvs_coresimplecommands_mr.cpp
+// Created on Fri 31 Oct 2003 00:04:25 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_coresimplecommands.h"
+
+#include "kvi_window.h"
+#include "kvi_console.h"
+#include "kvi_query.h"
+#include "kvi_ircuserdb.h"
+#include "kvi_out.h"
+#include "kvi_locale.h"
+#include "kvi_app.h"
+#include "kvi_options.h"
+#include "kvi_fileutils.h"
+#include "kvi_filedialog.h"
+#include "kvi_ircconnection.h"
+#include "kvi_channel.h"
+#include "kvi_ircurl.h"
+#include "kvi_frame.h"
+#include "kvi_modulemanager.h"
+#include "kvi_kvs_moduleinterface.h"
+
+#include "kvi_kvs_variantlist.h"
+#include "kvi_kvs_script.h"
+#include "kvi_kvs_popupmanager.h"
+
+#include <qcursor.h>
+#include <qprocess.h>
+#include <qtimer.h>
+
+namespace KviKvsCoreSimpleCommands
+{
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: me
+ @type:
+ command
+ @title:
+ me
+ @syntax:
+ me <text:string>
+ @short:
+ Sends a CTCP ACTION
+ @description:
+ Sends a CTCP ACTION to the current channel, query or dcc chat.[br]
+ If you execute it in any other window type, you will get an error.[br]
+ If you want to use this command in a window that is not a channel
+ query or dcc chat, you may use the [doc:command_rebinding]standard -r switch[/doc].
+ @examples:
+ [example]
+ me is Hungry!
+ [/example]
+ */
+
+ KVSCSC(me)
+ {
+ QString szText;
+ KVSCSC_PARAMETERS_BEGIN
+ KVSCSC_PARAMETER("text",KVS_PT_STRING,KVS_PF_OPTIONAL | KVS_PF_APPENDREMAINING,szText)
+ KVSCSC_PARAMETERS_END
+
+ KVSCSC_REQUIRE_CONNECTION
+
+ switch(KVSCSC_pWindow->type())
+ {
+ case KVI_WINDOW_TYPE_CHANNEL:
+ case KVI_WINDOW_TYPE_QUERY:
+ case KVI_WINDOW_TYPE_DCCCHAT:
+ KVSCSC_pWindow->ownAction(szText);
+ break;
+ default:
+ KVSCSC_pContext->warning(__tr2qs("/me can be used only in channels, queries and DCC chat windows"));
+ break;
+ }
+
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: mode
+ @type:
+ command
+ @title:
+ mode
+ @syntax:
+ mode <target> <modeflags> [mode parameters]
+ @short:
+ Sends a MODE irc message
+ @description:
+ Sends a MODE irc message to the server of the current IRC context.[br]
+ The parameters are not modified in any way by KVIrc: so
+ you should use the RFC1459 syntax.[br]
+ This command is [doc:connection_dependant_commands]connection dependant[/doc].
+ @examples:
+ [example]
+ mode #kvirc +oo-b Pragma Buti *!*root@*
+ [/example]
+ */
+
+ KVSCSC(mode)
+ {
+ QString szText;
+ KVSCSC_PARAMETERS_BEGIN
+ KVSCSC_PARAMETER("text",KVS_PT_STRING,KVS_PF_APPENDREMAINING,szText)
+ KVSCSC_PARAMETERS_END
+
+ KVSCSC_REQUIRE_CONNECTION
+
+ KviQCString szTxt = KVSCSC_pConnection->encodeText(szText);
+
+ if(!szTxt.isEmpty())
+ {
+ if(!KVSCSC_pConnection->sendFmtData("MODE %s",szTxt.data()))
+ return KVSCSC_pContext->warningNoIrcConnection();
+ }
+
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: motd
+ @type:
+ command
+ @title:
+ motd
+ @syntax:
+ motd [target server]
+ @short:
+ Requests the Message of the day
+ @description:
+ Requests the Message of the day from the specified server or the current server if no [target server] is specified.[br]
+ This command is a [doc:rfc2821wrappers]RFC2821 command wrapper[/doc]; see that document for more information.[br]
+ */
+ // RCF2821 wrapper
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: msg
+ @type:
+ command
+ @title:
+ msg
+ @syntax:
+ msg [-q] <target:string> <text:string>
+ @short:
+ Alias for privmsg
+ @switches:
+ !sw: -q | --quiet
+ Do not print any output
+ @description:
+ Sends a private message to the specified <target>.
+ <target> may be any PRIVMSG target allowed by the underlying
+ IRC protocol (see RFC1459).
+ This is really similar to [cmd]privmsg[/cmd] but also outputs the
+ message locally (unless the [-q] switch is used).[br]
+ This command is [doc:connection_dependant_commands]connection dependant[/doc].[br]
+ */
+ // Internally aliased to privmsg
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: nick
+ @type:
+ command
+ @title:
+ nick
+ @syntax:
+ nick <new nickname:string>
+ @short:
+ Changes your nickname
+ @description:
+ Changes your nickname in the connection associated to the
+ current [b]IRC context[/b].[br] This command is "server based";
+ this means that the effects will be visible only after the
+ server has acknowledged the change.[br]
+ This command is [doc:connection_dependant_commands]connection dependant[/doc].[br]
+ @examples:
+ [example]
+ nick Pragma
+ [/example]
+ */
+
+ KVSCSC(nick)
+ {
+ QString szNick;
+ KVSCSC_PARAMETERS_BEGIN
+ KVSCSC_PARAMETER("nickname",KVS_PT_NONEMPTYSTRING,0,szNick)
+ KVSCSC_PARAMETERS_END
+
+ KVSCSC_REQUIRE_CONNECTION
+
+ KviQCString szData = KVSCSC_pConnection->encodeText(szNick);
+ if(!szData.data())szData = "";
+
+ if(!KVSCSC_pConnection->sendFmtData("NICK %s",szData.data()))
+ return KVSCSC_pContext->warningNoIrcConnection();
+
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: notice
+ @type:
+ command
+ @title:
+ notice
+ @syntax:
+ notice [-q] <target:string> <text:string>
+ @short:
+ Sends a private notice
+ @switches:
+ !sw: -q | --quiet
+ Do not print any output
+ @description:
+ Sends a private notice to the specified <target>.
+ <target> may be any NOTICE target allowed by the underlying
+ IRC protocol (see RFC1459).
+ If the [-q] switch is specified, no output is printed.
+ This command is [doc:connection_dependant_commands]connection dependant[/doc].[br]
+ @examples:
+ [example]
+ notice Pragma Hello!
+ notice Pragma,Crocodile Hello to you both!
+ notice #kvirc Hello from outside!
+ [/example]
+ */
+
+ KVSCSC(notice)
+ {
+ QString szTarget,szText;
+ KVSCSC_PARAMETERS_BEGIN
+ KVSCSC_PARAMETER("target",KVS_PT_NONEMPTYSTRING,0,szTarget)
+ KVSCSC_PARAMETER("text",KVS_PT_STRING,KVS_PF_OPTIONAL | KVS_PF_APPENDREMAINING,szText)
+ KVSCSC_PARAMETERS_END
+
+ KVSCSC_REQUIRE_CONNECTION
+
+ KviWindow * w = KVSCSC_pConnection->findChannel(szTarget);
+ if(!w)w = KVSCSC_pConnection->findQuery(szTarget);
+
+ KviQCString szT = KVSCSC_pConnection->encodeText(szTarget);
+ KviQCString szD = w ? w->encodeText(szText) : KVSCSC_pConnection->encodeText(szText);
+ if(!szT.data())szT = ""; // encoding problems ?
+ if(!szD.data())szD = ""; // encoding problems ?
+
+ if(!(KVSCSC_pConnection->sendFmtData("NOTICE %s :%s",szT.data(),szD.data())))
+ return KVSCSC_pContext->warningNoIrcConnection();
+
+ if(!KVSCSC_pSwitches->find('q',"quiet"))
+ KVSCSC_pWindow->output(KVI_OUT_OWNPRIVMSG,"[NOTICE >>> %Q]: %Q",&szTarget,&szText);
+
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: op
+ @type:
+ command
+ @title:
+ op
+ @syntax:
+ op <nickname_list>
+ @short:
+ Sets chanop status to the specified users
+ @description:
+ Sets channel operator status to the users specified in <nickname_list>,
+ which is a comma separated list of nicknames.
+ This command works only if executed in a channel window.
+ The command is translated to a set of MODE messages containing
+ a variable number of +o flags.
+ This command is [doc:connection_dependant_commands]connection dependant[/doc].
+ @examples:
+ [example]
+ op Pragma,Crocodile
+ [/example]
+ @seealso:
+ [cmd]deop[/cmd], [cmd]voice[/cmd], [cmd]devoice[/cmd]
+ */
+
+ KVSCSC(op)
+ {
+ return multipleModeCommand(__pContext,__pParams,__pSwitches,'+','o');
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: openurl
+ @type:
+ command
+ @title:
+ openurl
+ @syntax:
+ openurl <url:string>
+ @short:
+ Opens an url
+ @description:
+ Opens the specified <url> with an appropriate handler.<br>
+ The handlers for the supported url types are specified in the options dialog.<br>
+ Each handler is a kvirc commandline that the url will be passed to as the first parameter ($0).<br>
+ The supported url types are:<br>
+ HTTP: http://&lt;url&gt; or sth that begins with "www." <br>
+ HTTPS: https://&lt;url&gt;<br>
+ FILE: file://&lt;url&gt;<br>
+ IRC: irc[s][6]://<server>[:<port>][/<channel>[?<pass>]] (Handled internally)<br>
+ FTP: ftp://<url> or sth that begins with "ftp."<br>
+ MAIL: mailto:<mailaddress><br>
+ @examples:
+ [example]
+ openurl http://www.kvirc.net
+ openurl https://www.secure.net
+ openurl file://home/pragma/pippo.txt
+ openurl irc://irc.eu.dal.net:6667
+ openurl irc6://irc.ircd.it/#kvirc
+ openurl ircs://crypto.azzurra.org:9999
+ openurl ircs6://ngnet.azzurra.org:9999
+ openurl ftp://ftp.localhost.net/pub/kvirc/
+ openurl mailto:users@domain.extension
+ [/example]
+ */
+
+ KVSCSC(openurl)
+ {
+ QString szUrl;
+ KVSCSC_PARAMETERS_BEGIN
+ KVSCSC_PARAMETER("url",KVS_PT_NONEMPTYSTRING,KVS_PF_APPENDREMAINING,szUrl)
+ KVSCSC_PARAMETERS_END
+
+ QString szCommand;
+ if(KviQString::equalCIN(szUrl,"www.",4))
+ {
+ szCommand = KVI_OPTION_STRING(KviOption_stringUrlHttpCommand);
+ szUrl.prepend("http://");
+ } else if(KviQString::equalCIN(szUrl,"http:",5))
+ {
+ szCommand = KVI_OPTION_STRING(KviOption_stringUrlHttpCommand);
+ } else if(KviQString::equalCIN(szUrl,"https:",6))
+ {
+ szCommand = KVI_OPTION_STRING(KviOption_stringUrlHttpsCommand);
+ } else if(KviQString::equalCIN(szUrl,"ftp",3))
+ {
+ szCommand = KVI_OPTION_STRING(KviOption_stringUrlFtpCommand);
+ if(KviQString::equalCIN(szUrl,"ftp.",4))szUrl.prepend("ftp://");
+ } else if(KviQString::equalCIN(szUrl,"file",4))
+ {
+ szCommand = KVI_OPTION_STRING(KviOption_stringUrlFileCommand);
+ } else if(KviQString::equalCIN(szUrl,"irc",3))
+ {
+ if(KviIrcUrl::run(szUrl,KviIrcUrl::FirstFreeContext,KVSCSC_pContext->console()) & KviIrcUrl::InvalidProtocol)
+ {
+ KVSCSC_pContext->warning(__tr2qs("Invalid IRC url (%Q)"),&szUrl);
+ }
+ return true;
+ } else if(KviQString::equalCIN(szUrl,"mailto",6))
+ {
+ szCommand = KVI_OPTION_STRING(KviOption_stringUrlMailtoCommand);
+ }
+#ifdef COMPILE_ON_WINDOWS
+ if(KVI_OPTION_BOOL(KviOption_boolUseSystemUrlHandlers))
+ {
+ ShellExecute(NULL, "open", szUrl.local8Bit().data(),
+ NULL, NULL, SW_SHOWNORMAL);
+ } else {
+#endif
+ if(szCommand.isEmpty())szCommand = KVI_OPTION_STRING(KviOption_stringUrlUnknownCommand);
+
+ if(!szCommand.isEmpty())
+ {
+ KviKvsVariantList vList;
+ vList.append(new KviKvsVariant(szUrl));
+
+ QString szName = "openurl::handler";
+ KviKvsScript script(szName,szCommand);
+
+ if(!script.run(KVSCSC_pWindow,&vList,0,KviKvsScript::PreserveParams))
+ KVSCSC_pContext->warning(__tr2qs("The commandline for this url type seems to be broken (%Q)"),&szUrl);
+
+ } else KVSCSC_pContext->warning(__tr2qs("No commandline specified for this type of url (%Q)"),&szUrl);
+#ifdef COMPILE_ON_WINDOWS
+ }
+#endif
+
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+ /*
+ @doc: oper
+ @type:
+ command
+ @title:
+ oper
+ @syntax:
+ oper <name> <password>
+ @short:
+ Requests IRC operator status
+ @description:
+ Requests IRC operator status.[br]
+ This command is a [doc:rfc2821wrappers]RFC2821 command wrapper[/doc]; see that document for more information.[br]
+ */
+ // RFC2821 wrapper
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: option
+ @type:
+ command
+ @title:
+ option
+ @syntax:
+ option [<optName:string> <optValue:string>]
+ @short:
+ Sets an internal option
+ @description:
+ Sets an internal option named <optName> to the value <optValue>. The value
+ must be appropriate for the type of option that you're going to set.[br]
+ With no parameters this command lists all the available option names
+ sorted by option type.[br] The possible option types are:[br]
+ [b]Boolean[/b]: <optValue> must be "1" or "0"[br]
+ [b]String[/b]: <optValue> can be any string[br]
+ [b]StringList[/b]: <optValue> must be a comma separated list of strings (eventually empty)[br]
+ [b]Color[/b]: <optValue> must have the format #RRGGBB where R G and B are hex digits[br]
+ [b]Font[/b]: <optValue> is a comma separated list of font properties:
+ <family>,<pointsize>,<style>,<charset>,<weight>,<flags>. <family> is the font face name
+ ("arial" , "helvetica" etc..), <pointsize> is more or less the indicator of the size of the font
+ (try sth like 12,14), <style> is an integer that indicates the font style (fixed for example),
+ <charset> is an integer that indicates the charset of the font (maybe one day I'll document it better),
+ <weight> indicates the (ehm) weight of the font (50,100,150...matches Bold,DemiBold etc..),
+ <flags> is a combination of 'b','i','u','s,' and 'f' that match respectively bold,italic
+ underline,strikeout and fixed.[br]
+ [b]MessageType[/b]: <optValue> is a comma separated list of message type properties:
+ <icon>,<foreground>,<background>,<logBoolean>,<level>: <icon> is the index of the internal
+ small icon that has to be shown with the message type, <foreground> is an integer
+ indicating the mirc color to be used for the message type text (0-15),
+ <background> is similar to foreground and accepts also the value of 100 that means transparent.
+ <logBoolean> is a boolean value (0/1) that indicates wheter this message type has to be logged or not.
+ <level> is the message level (actually from 0 to 5).[br]
+ [b]Rectangle[/b]: <optValue> is a comma separated list of integer values that indicate <x>,<y>,<width> and <height>.[br]
+ [b]Pixmap[/b]: <optValue> must be an ABSOLUTE path of the image that you want to load.[br]
+ [b]Int[/b]: <optValue> must be an integer.[br]
+ [b]Uint[/b]: <optValue> must be an UNSIGNED positive integer.[br]
+ Almost all the options available in the option dialog can be set by this command.[br]
+ Some GUI options might require a KVIrc restart to work properly (altough I've tried to avoid that when possible).
+ @examples:
+ [example]
+ [comment]# List available options[/comment]
+ option
+ [comment]# Set the mdi mananger background image[/comment]
+ option pixmapMdiBackground /home/pragma/myback1.png
+ [comment]# Set the frame caption text[/comment]
+ option stringFrameCaption KVIrc rulez!
+ [comment]# Enable verbose mode[/comment]
+ option boolBeVerbose 1
+ [comment]# Set the irc view font[/comment]
+ option fontIrcView helvetica,24,5,1,50
+ [/example]
+ @seealso:
+ [fnc]$option[/fnc]
+ */
+
+ KVSCSC(option)
+ {
+ QString szName;
+ QString szValue;
+ KVSCSC_PARAMETERS_BEGIN
+ KVSCSC_PARAMETER("optName",KVS_PT_STRING,KVS_PF_OPTIONAL,szName)
+ KVSCSC_PARAMETER("optValue",KVS_PT_STRING,KVS_PF_OPTIONAL | KVS_PF_APPENDREMAINING,szValue)
+ KVSCSC_PARAMETERS_END
+
+ if(szName.isEmpty())
+ {
+ // list available options
+ g_pApp->listAvailableOptions(KVSCSC_pWindow);
+ } else {
+ if(!g_pApp->setOptionValue(szName,szValue))KVSCSC_pContext->warning(__tr2qs("Option setting error: Unknown option or invalid value for option type"));
+ }
+
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: parse
+ @type:
+ command
+ @title:
+ parse
+ @syntax:
+ parse [-q] [-e] [-f] [-r] <filename:string> [<parameter1:variant> [<parameter2:variant> [...]]]
+ @short:
+ Executes commands from a file
+ @switches:
+ !sw: -e | --fail-on-load
+ Causes the command to terminate with an error when the file
+ can't be loaded: the error termination stops the parsing
+ of the current script too. If the -e switch is not used then
+ file load failures are eventually reported only as a warning
+ or not reported at all (if -q is used).
+ !sw: -f | --fail-on-error
+ Causes the command to terminate with an error when the execution
+ of the script loaded from disk generates an error.
+ This error termination stops the parsing of the current script too.
+ If the -f switch is not used then the loaded script errors
+ do not stop the current script.
+ !sw: -q | --quiet
+ Causes the command to run quietly without printing warnings about
+ empty <filename> and file loading errors.
+ !sw: -r | --propagate-return
+ Causes the return value of the script to be propagated to the
+ calling context. This allows the usage of ${ } trick to extract
+ this return value. See the examples section for a sample usage.
+ @description:
+ Executes commands from the external file <filename>.[br]
+ <filename> can be an absolute or relative path.[br]
+ If it is a relative path then KVIrc will try to look it up
+ in the path of the calling script (if any) and in the current
+ KVIrc working directory.
+ The file must be utf8-encoded (see below).
+ [parameters] is a space separated string of parameters to be
+ passed to the script. The parameter $0 will contain the
+ path of the file being parsed, the other parameters will
+ be available starting from $1.[br]
+ If <filename> is an existing directory name a file dialog
+ will pop up, allowing you to choose a file to parse.
+ The file dialog will start in the directory specified by <filename>.
+ If you don't know the name of an existing directory, just pass "."
+ or "/". The command just prints a warning if the file cannot be loaded for
+ some reason. If you want the command to stop with an error in
+ this case then use the -e switch.[br]
+ This command has a builtin alias called [cmd]include[/cmd].
+ [br][br]
+ Note that script files, especially the ones that you distribute,
+ MUST be encoded in utf8. Any other encoding (especially the exotic
+ ones like KOI8R or Shift-JIS) may screw things up.
+ The reason for such a constraint is simple: KVIrc has no means
+ of knowing the encoding that one or other scripter uses to
+ edit his files. Unlike other languages (like HTML, for example)
+ there is no "external" metadata that will allow for
+ encoding detection before the data is actually decoded.
+ UTF8 is the right way (tm). Use it.
+ @examples:
+ [example]
+ parse /home/pragma/myscript.kvs
+ [/example]
+ [example]
+ [comment]# Here we are assuming that fetchdata.kvs returns a string[/comment]
+ [comment]# We evaluate the return value thru ${} and echo it[/comment]
+ echo ${ parse -r /home/pragma/fetchdata.kvs; };
+ [/example]
+ */
+
+ KVSCSC(parse)
+ {
+ QString szFileName;
+ KviKvsVariantList vList;
+ KVSCSC_PARAMETERS_BEGIN
+ KVSCSC_PARAMETER("filename",KVS_PT_NONEMPTYSTRING,0,szFileName)
+ KVSCSC_PARAMETER("params",KVS_PT_VARIANTLIST,KVS_PF_OPTIONAL,vList)
+ KVSCSC_PARAMETERS_END
+
+ KviFileUtils::adjustFilePath(szFileName);
+
+ if(KviFileUtils::directoryExists(szFileName))
+ {
+ QString szTmp;
+ KVSCSC_pContext->enterBlockingSection();
+
+ bool bResult = KviFileDialog::askForOpenFileName(szTmp,__tr2qs("Choose a file to parse"),szFileName.utf8().data(),"*.kvs");
+
+ if(!KVSCSC_pContext->leaveBlockingSection())return false; // need to stop immediately
+ if(!bResult)return true;
+
+ szFileName = szTmp;
+
+ if(szFileName.isEmpty())return true; // done
+ KviFileUtils::adjustFilePath(szFileName);
+ } else {
+ QFileInfo inf(szFileName);
+ if(inf.isRelative())
+ {
+ if(QString * pszPath = KVSCSC_pContext->scriptFilePath())
+ {
+ QFileInfo inf2(*pszPath);
+ QString szCheckFileName = inf2.dirPath();
+ KviQString::ensureLastCharIs(szCheckFileName,KVI_PATH_SEPARATOR_CHAR);
+ szCheckFileName += szFileName;
+ if(KviFileUtils::fileExists(szCheckFileName))
+ szFileName = szCheckFileName;
+ }
+ }
+ }
+
+ QFileInfo infz(szFileName);
+ szFileName = infz.absFilePath();
+
+ QString szBuffer;
+ if(!KviFileUtils::loadFile(szFileName,szBuffer,true)) // <-- scripts SHOULD be shipped in utf8 format
+ {
+ if(KVSCSC_pSwitches->find('e',"fail-on-load"))
+ {
+ KVSCSC_pContext->error(__tr2qs("Failed to load the file '%Q' for parsing"),&szFileName);
+ return false;
+ } else {
+ if(!KVSCSC_pSwitches->find('q',"quiet"))
+ KVSCSC_pContext->warning(__tr2qs("Failed to load the file '%Q' for parsing"),&szFileName);
+ return true;
+ }
+ }
+
+ KviKvsScript s(szFileName,szBuffer);
+
+ KviKvsVariant * pRetVal = KVSCSC_pSwitches->find('r',"propagate-return") ? KVSCSC_pContext->returnValue() : 0;
+ KviKvsVariant vFileName(szFileName);
+ vList.prepend(&vFileName);
+
+ KviKvsExtendedRunTimeData rtd(&szFileName);
+
+ if(!s.run(KVSCSC_pContext->window(),&vList,pRetVal,KviKvsScript::PreserveParams,&rtd))
+ {
+ if(KVSCSC_pSwitches->find('f',"fail-on-error"))return false;
+ }
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: part
+ @type:
+ command
+ @title:
+ part
+ @syntax:
+ part [-k] [-q] [-s] [<channel list> [part message]]
+ @short:
+ Leaves the specified channels
+ @switches:
+ !sw: -k | --keep
+ Keeps the channel windows open after the part.
+ !sw: -q | --quiet
+ Runs the command in quiet mode (no warnings printed)
+ !sw: -s | --silent
+ Does not show the part message in the channel window
+ @description:
+ Leaves the channels specified in the <channel list>.
+ If no channels are specified, the current channel is used.
+ This command is "server based"; you will see its results only
+ after the server acknowledges it.[br]
+ If the -k switch is specified then the channel windows are left open
+ after the part (the channels become dead channels).[br]
+ If the -s switch is specified then the part message is not shown
+ in the channel window.[br]
+ This command is [doc:connection_dependant_commands]connection dependant[/doc].[br]
+ This command is equivalent to [cmd]leave[/cmd]
+ @examples:
+ [example]
+ part #kvirc Byez!
+ part #linux-it,#xmms,#kde Time to sleep
+ [/example]
+ */
+
+ KVSCSC(part)
+ {
+ QString szChans,szMsg;
+ KVSCSC_PARAMETERS_BEGIN
+ KVSCSC_PARAMETER("chans",KVS_PT_STRING,KVS_PF_OPTIONAL,szChans)
+ KVSCSC_PARAMETER("part_message",KVS_PT_STRING,KVS_PF_OPTIONAL | KVS_PF_APPENDREMAINING,szMsg)
+ KVSCSC_PARAMETERS_END
+
+ KVSCSC_REQUIRE_CONNECTION
+
+ if(szChans.isEmpty())
+ {
+ if(KVSCSC_pWindow->type() == KVI_WINDOW_TYPE_CHANNEL)
+ szChans = KVSCSC_pWindow->target();
+ else {
+ if(!KVSCSC_pSwitches->find('q',"quiet"))KVSCSC_pContext->warning(__tr2qs("Missing channel list"));
+ return true;
+ }
+ }
+
+ KviQCString szEncodedChans = KVSCSC_pConnection->encodeText(szChans);
+
+ QStringList sl = QStringList::split(",",szChans);
+
+ if(!szMsg.isEmpty())
+ {
+ KviQCString szText;
+ if(sl.count() == 1)
+ {
+ // single chan , use channel encoding if possible
+ KviChannel * ch = KVSCSC_pConnection->findChannel(szChans);
+ if(ch)
+ szText = ch->encodeText(szMsg);
+ else
+ szText = KVSCSC_pConnection->encodeText(szMsg);
+ } else {
+ // multiple chans, use connection encoding
+ szText = KVSCSC_pConnection->encodeText(szMsg);
+ }
+ if(!(KVSCSC_pConnection->sendFmtData("PART %s :%s",szEncodedChans.data(),szText.data())))
+ return KVSCSC_pContext->warningNoIrcConnection();
+ } else {
+ if(!(KVSCSC_pConnection->sendFmtData("PART %s",szEncodedChans.data())))
+ return KVSCSC_pContext->warningNoIrcConnection();
+ }
+
+ for(QStringList::Iterator it=sl.begin();it != sl.end();it++)
+ {
+ KviChannel * ch = KVSCSC_pConnection->findChannel(*it);
+ if(ch)
+ {
+ ch->partMessageSent(!KVSCSC_pSwitches->find('k',"keep"),!KVSCSC_pSwitches->find('s',"silent"));
+ } else {
+ if(!KVSCSC_pSwitches->find('q',"quiet"))KVSCSC_pContext->warning(__tr2qs("You don't appear to be on channel %s"),(*it).utf8().data());
+ }
+ }
+
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: pass
+ @type:
+ command
+ @title:
+ pass
+ @syntax:
+ pass <password>
+ @short:
+ Sends a password to the server
+ @description:
+ Sends a password to the server: usually KVIrc takes care of it , but well.. this is useful with bouncers.[br]
+ This command is a [doc:rfc2821wrappers]RFC2821 command wrapper[/doc]; see that document for more information.[br]
+ */
+ // RFC2821 wrapper
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: play
+ @type:
+ command
+ @title:
+ play
+ @syntax:
+ play <filename:string>
+ @short:
+ DEPRECATED: Use $snd.play instead!
+ @description:
+ This command has been moved to the snd module.
+ See [cmd]snd.play[/cmd]
+ */
+
+ KVSCSC(play)
+ {
+ // cool, no ?
+
+ KviModule * m = g_pModuleManager->getModule("snd");
+ if(!m)
+ {
+ KVSCSC_pContext->error(__tr2qs("Module command call failed: can't load the module 'snd'"));
+ return false;
+ }
+
+ KviKvsModuleSimpleCommandExecRoutine * proc = m->kvsFindSimpleCommand("play");
+ if(!proc)
+ {
+ KVSCSC_pContext->error(__tr2qs("Module command call failed: the module 'snd' doesn't export a command named 'play'"));
+ return false;
+ }
+
+ KviKvsModuleCommandCall call(m,KVSCSC_pContext,KVSCSC_pParams,KVSCSC_pSwitches);
+
+ return (*proc)(&call);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: popup
+ @type:
+ command
+ @title:
+ popup
+ @syntax:
+ popup [-p=<screen_coordinates:string>] <popup_name:string> [<parameter1:variant> [<parameter2:variant> [...]]]
+ @short:
+ Shows a popup menu
+ @switches:
+ !sw: -p=<screen_coordinates:string> | --point=<screen_coordinates:string>
+ @description:
+ Shows the popup menu <popup_name> at the current cursor position,
+ eventually passing the [parameters]. Please note that you can't
+ use this command inside one of the [cmd]defpopup[/cmd] command
+ handlers for <popup_name>. In other words, you can't "popup
+ a popup" while it is being popped up. :) (This would
+ be an endless recursive behaviour).[br]
+ If the -p switch is used , then <screen_coordinates> must be
+ in the form <x>,<y> and will be used as screen coordinates
+ for the placement of the popup (instead of the current cursor position).[br]
+ @seealso:
+ [cmd]defpopup[/cmd]
+ */
+
+ KVSCSC(popup)
+ {
+ QString szPopupName;
+ KVSCSC_PARAMETERS_BEGIN
+ KVSCSC_PARAMETER("popup_name",KVS_PT_NONEMPTYSTRING,0,szPopupName)
+ KVSCSC_PARAMETERS_END
+
+ // copy parameters
+ KviKvsVariantList * pPopupParams = new KviKvsVariantList();
+ KVSCSC_pParams->first();
+ while(KviKvsVariant * v = KVSCSC_pParams->next())pPopupParams->append(new KviKvsVariant(*v));
+
+ KviKvsPopupMenu * pMenu = KviKvsPopupManager::instance()->lookup(szPopupName);
+
+ if(!pMenu)
+ {
+ delete pPopupParams;
+ pPopupParams = 0;
+ KVSCSC_pContext->error(__tr2qs("Popup %Q is not defined"),&szPopupName);
+ return false;
+ }
+
+ if(pMenu->isLocked())
+ {
+ delete pPopupParams;
+ pPopupParams = 0;
+ KVSCSC_pContext->error(__tr2qs("A popup menu cannot be popped up twice"));
+ return false;
+ }
+
+ QPoint pnt = QCursor::pos();
+
+ KviKvsVariant * pCoords = KVSCSC_pSwitches->find('p',"point");
+ if(pCoords)
+ {
+ QString szCoords;
+ pCoords->asString(szCoords);
+
+ int idx = szCoords.find(',');
+ bool bCoordsOk = true;
+ if(idx == -1)bCoordsOk = false;
+ else {
+ QString szX = szCoords.left(idx);
+ szCoords.remove(0,idx + 1);
+ bool bOk1,bOk2;
+ int iX = szX.toInt(&bOk1);
+ int iY = szCoords.toInt(&bOk2);
+ if(bOk1 && bOk2)pnt = QPoint(iX,iY);
+ else bCoordsOk = false;
+ }
+
+ if(!bCoordsOk)KVSCSC_pContext->warning(__tr2qs("Invalid syntax for screen coordinates, using cursor position"));
+ }
+
+ pMenu->doPopup(pnt,KVSCSC_pContext->window(),pPopupParams);
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: privmsg
+ @type:
+ command
+ @title:
+ privmsg
+ @syntax:
+ privmsg <target:string> <text:string>
+ @short:
+ Sends a private message
+ @switches:
+ !sw: -q | --quiet
+ Do not print any output
+ @description:
+ Sends a private message to the specified <target>.
+ <target> may be any PRIVMSG target allowed by the underlying
+ IRC protocol (see RFC1459).
+ This command is really similar to [cmd]msg[/cmd] but it does not
+ output the message locally.[br]
+ This command is [doc:connection_dependant_commands]connection dependant[/doc].[br]
+ This command is equivalent to [cmd]msg[/cmd]
+ @examples:
+ [example]
+ privmsg Pragma Hello!
+ privmsg Pragma,Crocodile Hello to you both!
+ privmsg #kvirc Hello from outside!
+ [/example]
+ */
+
+ KVSCSC(privmsg)
+ {
+ QString szTarget,szText;
+ KVSCSC_PARAMETERS_BEGIN
+ KVSCSC_PARAMETER("target",KVS_PT_NONEMPTYSTRING,0,szTarget)
+ KVSCSC_PARAMETER("text",KVS_PT_STRING,KVS_PF_OPTIONAL | KVS_PF_APPENDREMAINING,szText)
+ KVSCSC_PARAMETERS_END
+
+ KVSCSC_REQUIRE_CONNECTION
+
+ KviWindow * w = KVSCSC_pConnection->findChannel(szTarget);
+ if(!w)w = KVSCSC_pConnection->findQuery(szTarget);
+
+ if(w)w->ownMessage(szText);
+ else {
+
+ KviQCString szT = KVSCSC_pConnection->encodeText(szTarget);
+ KviQCString szD = w ? w->encodeText(szText) : KVSCSC_pConnection->encodeText(szText);
+ if(!szT.data())szT = ""; // encoding problems ?
+ if(!szD.data())szD = ""; // encoding problems ?
+
+ if(!(KVSCSC_pConnection->sendFmtData("PRIVMSG %s :%s",szT.data(),szD.data())))
+ return KVSCSC_pContext->warningNoIrcConnection();
+
+ if(!KVSCSC_pSwitches->find('q',"quiet"))
+ KVSCSC_pWindow->output(KVI_OUT_OWNPRIVMSG,"[PRIVMSG >>> %Q]: %Q",&szTarget,&szText);
+ }
+
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: query
+ @type:
+ command
+ @title:
+ query
+ @syntax:
+ query <nickname list> [text]
+ @short:
+ Opens one or more query windows
+ @description:
+ Opens a query window for each user specified in <nickname list>
+ which is a [b]comma separated[/b] list of nicknames.[br]
+ If [text] is speficied, it is sent to the
+ query window just as it would have been written in the query itself.
+ If a query with one of the specified targets already exists,
+ it is simply focused and the [text] is sent to the target.[br]
+ This command is [doc:connection_dependant_commands]connection dependant[/doc].[br]
+ @examples:
+ [example]
+ [comment]# Open a single query to Pragma[/comment]
+ query Pragma
+ [comment]# Open a query to Pragma and to Crocodile , say "Hello!" in both windows[/comment]
+ query Pragma,Crocodile Hello !
+ [/example]
+ */
+
+ KVSCSC(query)
+ {
+ QString szTargets,szText;
+ KVSCSC_PARAMETERS_BEGIN
+ KVSCSC_PARAMETER("targets",KVS_PT_NONEMPTYSTRING,0,szTargets)
+ KVSCSC_PARAMETER("text",KVS_PT_STRING,KVS_PF_OPTIONAL | KVS_PF_APPENDREMAINING,szText)
+ KVSCSC_PARAMETERS_END
+
+ KVSCSC_REQUIRE_CONNECTION
+
+ KviQuery * query;
+
+ QStringList sl = QStringList::split(",",szTargets);
+ for(QStringList::Iterator it = sl.begin();it != sl.end();it++)
+ {
+ QString szNick = *it;
+ if(szNick.isEmpty())KVSCSC_pContext->warning(__tr2qs("Empty target specified"));
+ else {
+ query = KVSCSC_pWindow->console()->connection()->findQuery(szNick);
+ if(!query) {
+ query = KVSCSC_pWindow->console()->connection()->createQuery(szNick);
+ QString user;
+ QString host;
+ KviIrcUserDataBase * db = KVSCSC_pWindow->connection()->userDataBase();
+ if(db)
+ {
+ KviIrcUserEntry * e = db->find(szNick);
+ if(e)
+ {
+ user = e->user();
+ host = e->host();
+ }
+ }
+ query->setTarget(szNick,user,host);
+ }
+ query->autoRaise();
+ query->setFocus();
+ if(!szText.isEmpty())query->ownMessage(szText);
+ }
+ }
+
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: quit
+ @type:
+ command
+ @title:
+ quit
+ @syntax:
+ quit [-f] [-u] [quit-message:string]
+ quit -q
+ @short:
+ Terminates the current IRC connection or the entier application
+ @switches:
+ !sw: -q | --quit
+ Terminates this KVIrc application instance
+ !sw: -f | --force
+ Forces the immediate termination of the current IRC session (The QUIT message may be not sent)
+ !sw: -u | --unexpected
+ Simulates an "unexpected disconnection"
+ @description:
+ Terminates the current IRC session.[br]
+ By default this command sends a QUIT message
+ and waits for the server to close the connection.[br]
+ If you want to force KVIrc to close the connection
+ immediately after sending the QUIT message you must use the -f switch.[br]
+ Forcing the connection may cause your quit message to not be
+ displayed to the other IRC users: most likely it will be replaced
+ by a 'Connection reset by peer' or a 'EOF from client'.[br]
+ If the -u switch is specified then an "unexpected disconnection" will be simulated
+ and all the related options will be applied (e.g. automatic reconnection,
+ channels and queries kept open etc..). The QUIT message will be still sent unless
+ the -f switch is used. You can control all the "unexpected
+ disconnection" options in the options dialog.
+ If the -q switch is specified , this command terminates KVIrc immediately.[br]
+ @examples:
+ [example]
+ quit Time to sleep
+ [/example]
+ */
+
+ KVSCSC(quit)
+ {
+ QString szReason;
+ KVSCSC_PARAMETERS_BEGIN
+ KVSCSC_PARAMETER("reason",KVS_PT_STRING,KVS_PF_OPTIONAL | KVS_PF_APPENDREMAINING,szReason)
+ KVSCSC_PARAMETERS_END
+
+ if(KVSCSC_pSwitches->find('q',"quit"))
+ {
+ QTimer::singleShot(0,g_pApp,SLOT(quit()));
+ } else {
+ KVSCSC_REQUIRE_CONNECTION
+ KVSCSC_pWindow->context()->terminateConnectionRequest(KVSCSC_pSwitches->find('f',"force"),szReason,KVSCSC_pSwitches->find('u',"unexpected"));
+ }
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: quote
+ @type:
+ command
+ @title:
+ quote
+ @syntax:
+ quote [-q] <raw command:string>
+ @short:
+ Builtin alias for raw
+ @switches:
+ !sw: -q | --quiet
+ Be quiet: do echo the raw data.
+ @description:
+ Builtin alias for the command [cmd]raw[/cmd].
+ */
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: raise
+ @type:
+ command
+ @title:
+ raise
+ @syntax:
+ raise
+ @short:
+ Raises a KVIrc frame window
+ @description:
+ Raises and activates the current KVIrc frame window....assuming that your window manager supports it.[br]
+ */
+
+ KVSCSC(raise)
+ {
+ if(!KVSCSC_pWindow->frame()->isVisible())KVSCSC_pWindow->frame()->show();
+ KVSCSC_pWindow->frame()->raise();
+ //KVSCSC_pWindow->frame()->setActiveWindow();
+ //KVSCSC_pWindow->frame()->setFocus();
+ ((KviTalMainWindow *)KVSCSC_pWindow->frame())->setActiveWindow();
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: raw
+ @type:
+ command
+ @title:
+ raw
+ @syntax:
+ raw [-q] <raw command:string>
+ @short:
+ Sends raw data to the server
+ @switches:
+ !sw: -q | --quiet
+ Be quiet: do echo the raw data.
+ @description:
+ Sends a raw data string to the server of the current [b]IRC context[/b].[br]
+ If the -q switch (quiet) is specified, no output is printed.
+ This command is [doc:connection_dependant_commands]connection dependant[/doc].[br]
+ This command is equivalent to [cmd]quote[/cmd].
+ @examples:
+ [example]
+ [comment]# Send a private message "by hand"[/comment]
+ raw PRIVMSG Pragma :hello!
+ [comment]# Send a private message thru another connection[/comment]
+ raw -r=[fnc]$console[/fnc]([fnc]$ic[/fnc](irc.otherserver.com,othernick)) PRIVMSG Pragma :heya on this side!
+ [/example]
+ */
+
+ KVSCSC(raw)
+ {
+ QString szRawCommand;
+ KVSCSC_PARAMETERS_BEGIN
+ KVSCSC_PARAMETER("raw_command",KVS_PT_STRING,KVS_PF_APPENDREMAINING,szRawCommand)
+ KVSCSC_PARAMETERS_END
+
+ KVSCSC_REQUIRE_CONNECTION
+
+ KviQCString szData = KVSCSC_pConnection->encodeText(szRawCommand);
+ if(!szData.data())szData = "";
+
+ if(!KVSCSC_pConnection->sendData(szData.data()))
+ return KVSCSC_pContext->warningNoIrcConnection();
+
+ if(!KVSCSC_pSwitches->find('q',"quiet"))
+ KVSCSC_pWindow->output(KVI_OUT_RAW,__tr2qs("[RAW]: %Q"),&szRawCommand);
+
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: rebind
+ @type:
+ command
+ @title:
+ rebind:
+ @syntax:
+ rebind [-q] <window_id:string>
+ @short:
+ Rebinds a command sequence to a specified window
+ @switches:
+ !sw: -q | --quiet
+ Causes the command to run quietly, print no warnings
+ and don't fail when the window identifier passed is empty.
+ @description:
+ Rebinds the current command sequence to the window specified by <window_id>.[br]
+ The new window will be inherited by all the subcommands and aliases called.[br]
+ -q causes the command to run quietly.[br]
+ [b]Handle with care.[/b]
+ @examples:
+ [comment]# Try this example in a channel or query window[/comment]
+ [comment]# Remember the current window id[/comment]
+ %winid = $window
+ [comment]# Rebind to the console of the current irc context[/comment]
+ rebind $console
+ echo "Hello from the console :)"
+ echo "Hello again.. still in the console"
+ [comment]# Rebind back[/comment]
+ rebind %winid
+ echo "Again in this window :)"
+ */
+
+ KVSCSC(rebind)
+ {
+ QString szWinId;
+ KVSCSC_PARAMETERS_BEGIN
+ KVSCSC_PARAMETER("window_id",KVS_PT_NONEMPTYSTRING,0,szWinId)
+ KVSCSC_PARAMETERS_END
+
+ KviWindow * pAux = g_pApp->findWindow(szWinId.utf8().data());
+ if(pAux)KVSCSC_pContext->setWindow(pAux);
+ else {
+ if(!KVSCSC_pSwitches->find('q',"quiet"))
+ KVSCSC_pContext->warning(__tr2qs("Window with id %Q not found: no rebinding performed"),&szWinId);
+ }
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: return
+ @type:
+ command
+ @title:
+ return
+ @syntax:
+ return <value:variant>
+ @short:
+ Returns from the current command sequence and sets it return value
+ @description:
+ Sets the return value of the current command sequence to <string>
+ and stops the execution.[br]
+ This is more or less equivalent to calling [cmd]setreturn[/cmd] <string>
+ and then [cmd]halt[/cmd], but has no additional semantics in events.[br]
+ Starting from version 3.0.0 of kvirc you can also return
+ arrays and hashes just like any other variable types.
+ @examples:
+ return $array(item1,item2,3213,itemX);
+ @seealso:
+ [cmd]setreturn[/cmd], [cmd]break[/cmd], [cmd]halt[/cmd]
+ */
+
+ KVSCSC(returnCKEYWORDWORKAROUND)
+ {
+ if(KVSCSC_pParams->count() == 0)
+ {
+ KVSCSC_pContext->returnValue()->setNothing();
+ return false;
+ }
+ if(KVSCSC_pParams->count() == 1)
+ {
+ KVSCSC_pContext->returnValue()->copyFrom(*(KVSCSC_pParams->first()));
+ return false;
+ }
+
+ QString all;
+ KVSCSC_pParams->allAsString(all);
+ KVSCSC_pContext->returnValue()->setString(all);
+ return false;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: run
+ @type:
+ command
+ @title:
+ run
+ @syntax:
+ run <commandline:string>
+ @short:
+ Runs an external process
+ @description:
+ Runs an external process. This command does not allow
+ any other interaction with the process started. If you want
+ to grab the process output you probably need to use [cmd]exec[/cmd].
+ Run doesn't spawn a subshell in order to execute the <commandline>
+ and thus if you need shell substitutions to be made you must invoke
+ the shell by yourself (probably by passing the real command as the -c argument).
+ @examples:
+ [example]
+ run xterm
+ run xmessage -center *
+ [comment]# note the difference in * processing[/comment]
+ run /bin/bash -c "xmessage -center *"
+ [/example]
+ */
+
+ KVSCSC(run)
+ {
+ QString szCommand;
+ QStringList l;
+ KVSCSC_PARAMETERS_BEGIN
+ KVSCSC_PARAMETER("command",KVS_PT_STRING,0,szCommand)
+ KVSCSC_PARAMETER("parameters",KVS_PT_STRINGLIST,KVS_PF_OPTIONAL,l)
+ KVSCSC_PARAMETERS_END
+
+#ifdef COMPILE_USE_QT4
+ QProcess proc;
+ proc.start(szCommand,l);
+ // FIXME: KVSCSC_pContext->warning(__tr2qs("Failed to execute command '%Q'"),&szCommand);
+#else
+ QProcess proc(szCommand);
+ for ( QStringList::Iterator it = l.begin(); it != l.end(); ++it ) proc.addArgument(*it);
+ if(!proc.start())KVSCSC_pContext->warning(__tr2qs("Failed to execute command '%Q'"),&szCommand);
+#endif
+ return true;
+ }
+};
+
diff --git a/src/kvirc/kvs/kvi_kvs_coresimplecommands_sz.cpp b/src/kvirc/kvs/kvi_kvs_coresimplecommands_sz.cpp
new file mode 100644
index 00000000..1dfc4549
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_coresimplecommands_sz.cpp
@@ -0,0 +1,975 @@
+// //=============================================================================
+//
+// File : kvi_kvs_coresimplecommands_sz.cpp
+// Created on Fri 31 Oct 2003 00:04:25 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_coresimplecommands.h"
+
+#include "kvi_kvs_popupmanager.h"
+#include "kvi_kvs_script.h"
+
+#include "kvi_ircconnection.h"
+#include "kvi_console.h"
+#include "kvi_locale.h"
+#include "kvi_app.h"
+#include "kvi_asynchronousconnectiondata.h"
+#include "kvi_frame.h"
+#include "kvi_netutils.h"
+#include "kvi_menubar.h"
+#include "kvi_userinput.h"
+#include <cstdlib>
+
+namespace KviKvsCoreSimpleCommands
+{
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: say
+ @type:
+ command
+ @title:
+ say
+ @syntax:
+ say [-x] [-q] [-r=<window_id>] <text:string>
+ @switches:
+ !sw: -q | --quiet
+ Run quietly
+ !sw: -r=<window_id> | --rebind=<window_id>
+ Standard command rebinding switch
+ !sw: -x | --allow-exec
+ Allow the execution of commands by interpreting the leading slash in th <text>
+ @short:
+ Type text in a window
+ @description:
+ This command is more or less equivalent to typing text in the input
+ entry of the current window. If the -r switch is used
+ then the command is rebound to the window specified by <window_id>.
+ The main difference is that the variables and identifiers in <text>
+ are always parsed (when typing this happen only if the text is a command).[br]
+ With -x you can also use this command to execute "variable" commands too:
+ if <text> begins with a slash then it will be treated as a command
+ to be executed (after parsing the identifiers etc.).[br]
+ Please note that using /say -x with a <text> that isn't a constant
+ in the script but comes from some unidentified external source (e.g. the network)
+ is a potential security flaw: don't do it.
+ When the -x switch is not used, the text is never interpreted as command.
+ -q causes the command to run quietly.[br]
+ Please note that /say will also trigger the [event:ontextinput]OnTextInput[/event] event.
+ [b]Handle with care.[/b]
+ */
+
+ KVSCSC(say)
+ {
+ QString szText;
+ KVSCSC_PARAMETERS_BEGIN
+ KVSCSC_PARAMETER("text",KVS_PT_STRING,KVS_PF_APPENDREMAINING,szText)
+ KVSCSC_PARAMETERS_END
+
+ if(KVSCSC_pSwitches->find('x',"allow-exec"))
+ {
+ // allow execution of commands
+ if(!KviUserInput::parse(szText,KVSCSC_pWindow,__tr2qs("say: injected commandline")))
+ {
+ if(!KVSCSC_pSwitches->find('q',"quiet"))
+ KVSCSC_pContext->warning(__tr2qs("Say parse error: Broken command"));
+ }
+ } else {
+ KviUserInput::parseNonCommand(szText,KVSCSC_pWindow);
+ }
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: server
+ @type:
+ command
+ @title:
+ server
+ @syntax:
+ server [switches] [<server:string> [<port:uint>]]
+ @keyterms:
+ connecting to a server
+ @short:
+ Connects to the specified server
+ @switches:
+ !sw: -b=<local address:string> | --bind-address=<local address:string>
+ Bind the outgoing connection to <local address>. The <local address> must be
+ the IP address of a local interface suitable for contacting the remote <server>:
+ this means that if you're going to use the -i switch, the <local address>
+ must be an IPV6 address.
+ On most systems it is also possible to use a local interface name as <local address>;
+ in this way the interface address can be resolved at runtime by the KVIrc network engine.
+
+ !sw: -c=<command sequence:string> | --command=<command sequence:string>
+ The <command sequence> will be executed just after the login operations
+ have been completed.
+
+ !sw: -f=<socket filter:string> | --filter=<socket filter:string>
+ Activates <socket filter> on the connection.
+ A socket filter is a plugin that can adapt the IRC protocol to other existing protocols such as OpenNap.
+ For plain IRC it is not needed.
+
+ !sw: -i | --ipv6
+ Makes the connection by using the IPV6 protocol
+ (if supported by the executable)
+
+ !sw: -n | --new-context
+ Forces the connection to be attempted in a new IRC context instead of the current one.
+
+ !sw: -p=<password:string> | --password=<password:string>
+ Uses <password> to login to the server (the password will be stored in the server
+ entry too).
+
+ !sw: -q=<nick:string> | --nickname=<nick:string>
+ Uses <nick> to login to the server (the nicknames will be stored in the server
+ entry too).
+
+ !sw: -s | --ssl
+ Activates the SSL support for this connection
+
+ !sw: -u | --unused-context
+ Forces the connection to be attempted in the first IRC context that has
+ no connection in progress. If all the IRC contexts have connections in progress
+ then a new one is created.
+
+ !sw: -l | --last
+ When <server> and <port> are empty use the last
+ @description:
+ Attempts a connection to the specified <server>
+ on the specified <port>. If no <port> is specified
+ the default 6667 is used. If no <server> is specified,
+ the currently selected server from the server list is used
+ unless the -l switch is passed: in this case the last server
+ that was used in the IRC context is re-used.
+ If the <server> is a valid IPV6 address, the -i switch is implied.[br]
+ The <server> is added to the server list (if not already
+ there) and set as current.[br]
+ [br]
+ If <server> is in the form "id:<some_string>" then <some_string>
+ is interpreted as the server's internal id (specified in the options dialog).
+ This is useful when you need to force kvirc to choose between multiple
+ server entries with the same hostname and port stored in the database.[br]
+ Please note that this form causes most of the switches to have no effect
+ since the entry in the database will override them. If no server
+ entry with the specified identifier is found then an error will be generated
+ and the connection attempt will stop.
+ [br]
+ If <server> doesn't seem to be a valid ip address or hostname (i.e. it contains no dots)
+ and it doesn't look to be in the form "id:<some_string>" then
+ it is assumed to be a network name and if such a network is found
+ in the server list then the best server for that network is contacted.
+ (KVIrc tries to guess the round-robin (random) servers first).[br]
+ This behaviour can be forced by adding the "net:" prefix to the <server>
+ (so it will work even if the network name contains a dot).[br]
+ [br]
+ The connection is attempted in the current IRC context. If there is already
+ a connection in progress then it is "brutally" terminated.[br]
+ @examples:
+ [example]
+ server irc.tin.it
+ server -i irc6.ircd.it
+ server -i ircd.stealth.net 6667
+ server irc.undernet.org 6665
+ server -n irc.openprojects.net
+ server -c="join #kvirc" irc.stealth.net 6665
+ server -b=ppp0 irc.tin.it
+ server undernet
+ server id:mybouncerwithusername1
+ server id:mybouncerwithusername2
+ server net:under.net
+ [/example]
+ */
+
+ KVSCSC(server)
+ {
+ QString szServer;
+ kvs_uint_t uPort;
+ KVSCSC_PARAMETERS_BEGIN
+ KVSCSC_PARAMETER("server",KVS_PT_STRING,KVS_PF_OPTIONAL,szServer)
+ KVSCSC_PARAMETER("port",KVS_PT_UINT,KVS_PF_OPTIONAL,uPort)
+ KVSCSC_PARAMETERS_END
+
+ KviConsole * console = 0;
+ if(KVSCSC_pSwitches->find('n',"new-context"))console = KVSCSC_pWindow->frame()->createNewConsole();
+ else {
+ if(KVSCSC_pSwitches->find('u',"unused-context"))
+ {
+ // first try the current console
+ console = KVSCSC_pWindow->console();
+ if(console)
+ {
+ // if there is a connection in progress, proceed in searching
+ if(console->connectionInProgress())
+ {
+ console = 0;
+ }
+ }
+ if(!console)
+ {
+ // yep , have to search
+ console = KVSCSC_pWindow->frame()->firstNotConnectedConsole();
+ if(!console)
+ {
+ console = KVSCSC_pWindow->frame()->createNewConsole();
+ }
+ }
+ } else console = KVSCSC_pWindow->console();
+ }
+
+ QString szCmd,szBindAddress,szSocketFilter,szPassword,szNick;
+ KVSCSC_pSwitches->getAsStringIfExisting('c',"command",szCmd);
+ KVSCSC_pSwitches->getAsStringIfExisting('b',"bind-address",szBindAddress);
+ KVSCSC_pSwitches->getAsStringIfExisting('f',"filter",szSocketFilter);
+ KVSCSC_pSwitches->getAsStringIfExisting('p',"password",szPassword);
+ KVSCSC_pSwitches->getAsStringIfExisting('q',"nickname",szNick);
+
+ if(!console)
+ {
+ KVSCSC_pContext->error(__tr2qs("Couldn't find a suitable IRC context for the connection, try using -n or -u"));
+ return false;
+ }
+
+ if(szServer.isEmpty())
+ {
+ // just as hitting "connect"
+ if(console->connectionInProgress())
+ {
+ KVSCSC_pContext->error(__tr2qs("Another connection is already in progress in the selected IRC context"));
+ return false;
+ } else {
+ KviAsynchronousConnectionData * d = new KviAsynchronousConnectionData();
+ d->bUseLastServerInContext = KVSCSC_pSwitches->find('l',"last") != 0;
+ d->szCommandToExecAfterConnect = szCmd;
+ d->szBindAddress = szBindAddress;
+ d->szPass = szPassword;
+ d->szNick = szNick;
+ d->szLinkFilter = szSocketFilter;
+ console->context()->setAsynchronousConnectionData(d);
+ console->context()->connectToCurrentServer();
+ }
+ } else {
+ // server is not empty.
+ KviAsynchronousConnectionData * d = new KviAsynchronousConnectionData();
+ d->bUseSSL = (KVSCSC_pSwitches->find('s',"ssl") != 0);
+ d->szServer = szServer;
+ d->uPort = (kvi_u32_t)uPort;
+ d->szLinkFilter = szSocketFilter;
+ d->bPortIsOk = (uPort > 0);
+#ifdef COMPILE_IPV6_SUPPORT
+ d->bUseIpV6 = (KVSCSC_pSwitches->find('i',"ipv6") != 0) || KviNetUtils::isValidStringIp_V6(szServer);
+#else
+ d->bUseIpV6 = false;
+#endif
+ d->szCommandToExecAfterConnect = szCmd;
+ d->szBindAddress = szBindAddress;
+ d->szPass = szPassword;
+ d->szNick = szNick;
+ console->context()->setAsynchronousConnectionData(d);
+ console->context()->beginAsynchronousConnect(0);
+ }
+
+ return true;
+ };
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: service
+ @type:
+ command
+ @title:
+ service
+ @syntax:
+ service <nickname> <reserved> <distribution> <type> <reserved> [:]<info>
+ @short:
+ Registers a new service
+ @description:
+ Registers a new IRC service: this is for IRC operators only.[br]
+ This command is a [doc:rfc2821wrappers]RFC2821 command wrapper[/doc]; see that document for more information.[br]
+ WARNING: the <info> parameter may contain spaces: in that case you MUST add the leading ':' character.[br]
+ */
+ // RFC2921 wrapper
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: setmenu
+ @type:
+ command
+ @title:
+ setmenu
+ @syntax:
+ setmenu [-q] [-i=<index:integer>] <visible_text:string> [menu_name:string]
+ @short:
+ Adds a popup menu to the menu bar
+ @switches:
+ !sw: -q | --quiet
+ Run quietly: do not print any warnings
+ !sw: -i=<index:integer> | --index=<index:integer>
+ Place the popup menu on the left of the existing menubar item at the specified index
+ @description:
+ Adds an [b]existing[/b] popup menu to the current frame's menu bar.[br]
+ <visible_text> is used as menu identification and obviously as the visible
+ menu bar text for the new popup.[br]
+ If a popup menu with the same <visible_text> already exists in the current frame
+ it is removed first.[br]
+ <visible_text> can optionally contain the "&" character to identify
+ the popup menu accelerator.[br]
+ [menu_name] , if given , must be avalid name of a popup menu created earlier
+ with [cmd]defpopup[/cmd] (or the script center).[br]
+ If [menu_name] is not given , the popup menu identified by <visible_text> is removed.[br]
+ If the -i switch is used , <index> is a [b]zero based index[/b] of the default
+ menu-bar text item: the new popup menu will be placed on the left of that default item.[br]
+ If -q is used , this command prints no warnings (so you can safely use it to remove
+ popup menus without being sure that they actually are in there).
+ The warning itself serves to debugging purposes for the scripter.[br]
+ @seealso:
+ [cmd]defpopup[/cmd]
+ @examples:
+ setmenu -q -i=2 Test apopup
+ setmenu Test
+ setmenu ThisDoesNotExist
+ setmenu -q ThisDoesNotExist
+ */
+
+ KVSCSC(setmenu)
+ {
+ QString szVisibleText,szPopupName;
+ KVSCSC_PARAMETERS_BEGIN
+ KVSCSC_PARAMETER("visible_text",KVS_PT_NONEMPTYSTRING,0,szVisibleText)
+ KVSCSC_PARAMETER("popup_name",KVS_PT_STRING,KVS_PF_OPTIONAL,szPopupName)
+ KVSCSC_PARAMETERS_END
+
+ if(szPopupName.isEmpty())
+ {
+ if(!(KVSCSC_pWindow->frame()->mainMenuBar()->removeMenu(szVisibleText)))
+ {
+ if(!KVSCSC_pSwitches->find('q',"quiet"))KVSCSC_pContext->warning(__tr2qs("No menu bar item with text '%Q'"),&szPopupName);
+ }
+ return true;
+ }
+
+ KviKvsPopupMenu * p = KviKvsPopupManager::instance()->lookup(szPopupName);
+ int idx = -1;
+ if(KviKvsVariant * pIdx = KVSCSC_pSwitches->find('i',"index"))
+ {
+ kvs_int_t iIdx;
+ if(pIdx->asInteger(iIdx))
+ idx = iIdx;
+ else {
+ if(!KVSCSC_pSwitches->find('q',"quiet"))
+ KVSCSC_pContext->warning(__tr2qs("Invalid index specified: ignored"));
+ }
+ }
+ KVSCSC_pWindow->frame()->mainMenuBar()->removeMenu(szVisibleText);
+
+ idx = KVSCSC_pWindow->frame()->mainMenuBar()->getDefaultItemRealIndex(idx);
+
+ if(p)KVSCSC_pWindow->frame()->mainMenuBar()->addMenu(szVisibleText,p,idx);
+ else {
+ if(!KVSCSC_pSwitches->find('q',"quiet"))KVSCSC_pContext->warning(__tr2qs("The popup '%Q' is not defined"),&szPopupName);
+ }
+
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: setreturn
+ @type:
+ command
+ @title:
+ setreturn
+ @syntax:
+ setreturn <string>
+ @short:
+ Sets the return value of the current command sequence
+ @description:
+ Sets the return value of the current command sequence to <string>.
+ You can call this command multiple times in a command sequence
+ (so in fact use it as a write-only variable).
+ @examples:
+ @seealso:
+ [cmd]return[/cmd]
+ */
+
+ KVSCSC(setreturn)
+ {
+ if(KVSCSC_pParams->count() == 0)
+ {
+ KVSCSC_pContext->returnValue()->setNothing();
+ return false;
+ }
+ if(KVSCSC_pParams->count() == 1)
+ {
+ KVSCSC_pContext->returnValue()->copyFrom(*(KVSCSC_pParams->first()));
+ return false;
+ }
+
+ QString all;
+ KVSCSC_pParams->allAsString(all);
+ KVSCSC_pContext->returnValue()->setString(all);
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: sockets
+ @type:
+ command
+ @title:
+ sockets
+ @syntax:
+ sockets [[remote server] server mask]
+ @short:
+ Requests the sockets info from a server
+ @description:
+ Requests the sockets information from the specified server or the current server if no [remote server] is specified.[br]
+ The reply can be filtered by <server mask>.[br]
+ This command is a [doc:rfc2821wrappers]RFC2821 command wrapper[/doc]; see that document for more information.[br]
+ */
+ // RFC2821 wrapper
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: squery
+ @type:
+ command
+ @title:
+ squery
+ @syntax:
+ squery <target> :<text>
+ @short:
+ Sends a message to a service
+ @description:
+ Sends a message to a service in a form similar to [cmd]privmsg[/cmd].[br]
+ This command is a [doc:rfc2821wrappers]RFC2821 command wrapper[/doc]; see that document for more information.[br]
+ */
+ // RFC2821 wrapper
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: squit
+ @type:
+ command
+ @title:
+ squit
+ @syntax:
+ squit <server> [:]<comment>
+ @short:
+ Disconnects a server socket (ircops only)
+ @description:
+ Disconnects a server socket: this is for IRC operators only.[br]
+ This command is a [doc:rfc2821wrappers]RFC2821 command wrapper[/doc]; see that document for more information.[br]
+ WARNING: the <comment> parameter may contain spaces: in that case you MUST add the leading ':' character
+ before.[br]
+ */
+ // RFC2821 wrapper
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: srand
+ @type:
+ command
+ @title:
+ srand
+ @syntax:
+ srand <seed:integer>
+ @short:
+ Initializes the random number generator
+ @description:
+ Initializes the random number generator "seeding" it with
+ <seed> which must be an integer. If no <seed> is passed it defaults to 1.
+ Sequences of random numbers can be repeated by using the
+ same <seed> value.
+ @examples:
+ */
+
+ KVSCSC(srand)
+ {
+ kvs_int_t iSeed;
+ KVSCSC_PARAMETERS_BEGIN
+ KVSCSC_PARAMETER("seed",KVS_PT_INT,KVS_PF_OPTIONAL,iSeed)
+ KVSCSC_PARAMETERS_END
+ if(KVSCSC_pParams->count() < 1)iSeed = 1;
+ ::srand(iSeed);
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: stats
+ @type:
+ command
+ @title:
+ stats
+ @syntax:
+ stats [query [target server]]
+ @short:
+ Requests the stats info from a server
+ @description:
+ Requests the stats information from the specified server or the current server if no [target server] is specified.[br]
+ The query parameter is usually a letter indicating the type of the query requested: some query letters
+ are defined by [doc]rfc2812[/doc] and some others are server implementation dependant.[br]
+ This command is a [doc:rfc2821wrappers]RFC2821 command wrapper[/doc]; see that document for more information.[br]
+ */
+ // RFC2821 wrapper
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: time
+ @type:
+ command
+ @title:
+ time
+ @syntax:
+ time [target server]
+ @short:
+ Requests the current local time info from a server
+ @description:
+ Requests time information from the specified server or the current server if no [target server] is specified.[br]
+ This command is a [doc:rfc2821wrappers]RFC2821 command wrapper[/doc]; see that document for more information.[br]
+ */
+ // RFC2821 wrapper
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: topic
+ @type:
+ command
+ @title:
+ topic
+ @syntax:
+ topic [<channel:string> [topic text:string]]
+ @short:
+ Changes topic for the specified channel
+ @description:
+ Changes the topic for the specified <channel> to <topic text>.
+ If no topic is specified, the current channel topic will be returned.[br]
+ This command is "server based"; you will see its results only
+ after the server acknowledges it.[br]
+ This command is [doc:connection_dependant_commands]connection dependant[/doc].
+ @examples:
+ [example]
+ topic #kvirc KVIrc 3.4.0 has been released!
+ [/example]
+ */
+
+ KVSCSC(topic)
+ {
+ QString szChannel;
+ QString szTopic;
+ KVSCSC_PARAMETERS_BEGIN
+ KVSCSC_PARAMETER("channel",KVS_PT_NONEMPTYSTRING,KVS_PF_OPTIONAL,szChannel)
+ KVSCSC_PARAMETER("topic",KVS_PT_STRING,KVS_PF_OPTIONAL | KVS_PF_APPENDREMAINING,szTopic)
+ KVSCSC_PARAMETERS_END
+
+ KVSCSC_REQUIRE_CONNECTION
+
+ if(szChannel.isEmpty())
+ {
+ if(KVSCSC_pWindow->type() == KVI_WINDOW_TYPE_CHANNEL)
+ szChannel = KVSCSC_pWindow->target();
+ else {
+ KVSCSC_pContext->error(__tr2qs("No target channel specified and the current window is not a channel"));
+ return false;
+ }
+ }
+
+ KviQCString szC = KVSCSC_pConnection->encodeText(szChannel);
+ KviQCString szT = KVSCSC_pConnection->encodeText(szTopic);
+ if(szTopic.isEmpty())
+ {
+ if(!KVSCSC_pConnection->sendFmtData("TOPIC %s",szC.data()))
+ return KVSCSC_pContext->warningNoIrcConnection();
+ } else {
+ if(!KVSCSC_pConnection->sendFmtData("TOPIC %s :%s",szC.data(),szT.data()))
+ return KVSCSC_pContext->warningNoIrcConnection();
+ }
+
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: trace
+ @type:
+ command
+ @title:
+ trace
+ @syntax:
+ trace <target>
+ @short:
+ Requests trace information about a specified machine in the network
+ @description:
+ Requests trace information about a specified machine in the network.[br]
+ This command is a [doc:rfc2821wrappers]RFC2821 command wrapper[/doc]; see that document for more information.[br]
+ */
+ // RFC2821 wrapper
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: trload
+ @type:
+ command
+ @title:
+ trload
+ @syntax:
+ trload [-v] <catalogue:string> [<catalogue_dir:string>]
+ @switches:
+ !sw: -v | --verbose
+ Warn if a catalogue for the current language cannot be found
+ @short:
+ Loads a translation catalogue
+ @description:
+ Loads the specified translation <catalogue> in the current user language.[br]
+ The translation catalogues are *.mo files compiled with the standard
+ msgfmt program from the gettext package.[br]
+ The syntax of the catalogue names is:[br]
+ [b]<catalogue_dir>/<catalogue>_<language>.mo[/b][br]
+ KVIrc looks for the catalogues in <catalogue_dir> (if specified)
+ and in the locale subdirectory of the global and local KVIrc directories.[br]
+ <language> is choose automatically by KVIrc depending on the user's locale.[br]
+ Catalogues MUST be in UTF8 encoding.[br]
+ After a translation catalogue has been loaded you can
+ access its strings by the means of [fnc]$tr[/fnc].[br]
+ This function doesn't print any warning unless -v is specified.[br]
+ Please note that KVIrc attempts to load the <catalogue> automatically
+ when $tr() is used but it looks only in [fnc]$file.localdir[/fnc]/locale/
+ and in [fnc]$file.globaldir[/fnc]/locale/. This command is then useful
+ to load catalogues that reside in different directories.[br]
+ [b]NOTE[/b][br]
+ This feature is currently work in progress: the scripting engine
+ is not yet fully unicode and thus some more exotic translations may still suffer...
+ @seealso:
+ [fnc]$tr[/fnc], [cmd]trunload[/cmd]
+ */
+
+ KVSCSC(trload)
+ {
+ QString szCatalogue,szDir;
+ KVSCSC_PARAMETERS_BEGIN
+ KVSCSC_PARAMETER("catalogue",KVS_PT_NONEMPTYSTRING,0,szCatalogue)
+ KVSCSC_PARAMETER("catalogueDir",KVS_PT_STRING,KVS_PF_OPTIONAL,szDir)
+ KVSCSC_PARAMETERS_END
+
+ if(!szDir.isEmpty())
+ {
+ if(KviLocale::loadCatalogue(szCatalogue,szDir))
+ return true;
+ }
+
+ g_pApp->getLocalKvircDirectory(szDir,KviApp::Locale);
+
+ if(KviLocale::loadCatalogue(szCatalogue,szDir))
+ return true;
+
+ g_pApp->getGlobalKvircDirectory(szDir,KviApp::Locale);
+
+ if(KviLocale::loadCatalogue(szCatalogue,szDir))
+ return true;
+
+ if(KVSCSC_pSwitches->find('v',"verbose"))
+ KVSCSC_pContext->warning(__tr2qs("No catalogue %Q for the current language found"),&szCatalogue);
+
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: trunload
+ @type:
+ command
+ @title:
+ trunload
+ @syntax:
+ trunload [-v] <catalogue:string>
+ @switches:
+ !sw: -v | --verbose
+ Warn if the specified catalogue wasn't loaded at all
+ @short:
+ Unloads a translation catalogue
+ @description:
+ Unloads a specified translation catalogue.[br]
+ When you no longer need the translation strings contained in the
+ catalogue just unload it to free memory.[br]
+ This command prints no warnings unload -v is used.[br]
+ @seealso:
+ [fnc]$tr[/fnc], [cmd]trload[/cmd]
+ */
+
+ KVSCSC(trunload)
+ {
+ QString szCatalogue;
+ KVSCSC_PARAMETERS_BEGIN
+ KVSCSC_PARAMETER("catalogue",KVS_PT_NONEMPTYSTRING,0,szCatalogue)
+ KVSCSC_PARAMETERS_END
+
+ if(!KviLocale::unloadCatalogue(szCatalogue))
+ {
+ if(KVSCSC_pSwitches->find('v',"verbose"))
+ KVSCSC_pContext->warning(__tr2qs("The catalogue %Q was not loaded"),&szCatalogue);
+ }
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: unban
+ @type:
+ command
+ @title:
+ unban
+ @syntax:
+ unban <mask_list>
+ @short:
+ Unsets ban masks for the channel
+ @description:
+ Removes the ban masks specified in the <mask_list>,
+ which is a comma separated list of nicknames.
+ This command works only if executed in a channel window.
+ The command is translated to a set of MODE messages containing
+ a variable number of -b flags.
+ This command is [doc:connection_dependant_commands]connection dependant[/doc].
+ @examples:
+ [example]
+ # Unban people on the current channel (say #kvirc)
+ unban Maxim,Gizmo!*@*,*!root@*
+ # Do the same but from another window belongin to this IRC context
+ unban -r=[fnc]$channel[/fnc](#kvirc) Maxim,Gizmo!*@*,*!root@*
+ # Do the same from any window
+ unban -r=[fnc]$channel[/fnc](#kvirc,[fnc]$context[/fnc](irc.myirc.net,Pragma)) Maxim,Gizmo!*@*,*!root*@*
+ [/example]
+ @seealso:
+ [cmd]op[/cmd],
+ [cmd]deop[/cmd],
+ [cmd]voice[/cmd],
+ [cmd]devoice[/cmd],
+ [cmd]ban[/cmd]
+ */
+
+ KVSCSC(unban)
+ {
+ return multipleModeCommand(__pContext,__pParams,__pSwitches,'-','b');
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: version
+ @type:
+ command
+ @title:
+ version
+ @syntax:
+ version [target server]
+ @short:
+ Requests the version of a server
+ @description:
+ Requests the version information from the specified server or the current server if no [target server] is specified.[br]
+ This command is a [doc:rfc2821wrappers]RFC2821 command wrapper[/doc]; see that document for more information.[br]
+ */
+ // RFC2821 wrapper
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: voice
+ @type:
+ command
+ @title:
+ voice
+ @syntax:
+ voice <nickname_list>
+ @short:
+ Sets voice flag for the specified users
+ @description:
+ Sets the voice flag for the users specified in <nickname_list>,
+ which is a comma separated list of nicknames.
+ This command works only if executed in a channel window.
+ The command is translated to a set of MODE messages containing
+ a variable number of +v flags.
+ This command is [doc:connection_dependant_commands]connection dependant[/doc].
+ @examples:
+ [example]
+ voice Pragma,Crocodile
+ [/example]
+ @seealso:
+ [cmd]op[/cmd], [cmd]deop[/cmd], [cmd]devoice[/cmd]
+ */
+
+ KVSCSC(voice)
+ {
+ return multipleModeCommand(__pContext,__pParams,__pSwitches,'+','v');
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: warning
+ @type:
+ command
+ @title:
+ warning
+ @syntax:
+ warning <message:text>
+ @short:
+ Prints a warning message
+ @description:
+ Prints a warning message with the appropriate color and message type.
+ It doesn't alter the execution of the current script.
+ @seealso:
+ [cmd]error[/cmd]
+ */
+
+ KVSCSC(warning)
+ {
+ QString szAll;
+ KVSCSC_pParams->allAsString(szAll);
+ KVSCSC_pContext->warning("%Q",&szAll);
+
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: who
+ @type:
+ command
+ @title:
+ who
+ @syntax:
+ who {[mask] | [channel]}
+ @short:
+ Requests WHO information
+ @description:
+ Requests WHO information about the specified user or channel.[br]
+ This command is a [doc:rfc2821wrappers]RFC2821 command wrapper[/doc]; see that document for more information.[br]
+ */
+ // RFC2821 wrapper
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: whois
+ @type:
+ command
+ @title:
+ whois
+ @syntax:
+ whois [server] <nickname>
+ @short:
+ Requests user information
+ @description:
+ Requests information about an irc user specified by <nickname>.[br]
+ If [server] is specified, the request is directed to that one. [server]
+ may be a nickname so that the request is redirected to the server that
+ the user with that nickname is connected to.[br]
+ An useful trick is to use the following syntax:[br]
+ whois <nickname> <nickname>[br]
+ This will requests information about the user <nickname> to the server that he is currently
+ connected to; returning the idle time among the other common information.[br]
+ This command is [doc:connection_dependant_commands]connection dependant[/doc].
+ @examples:
+ [example]
+ [comment]# Query info about Pragma[/comment]
+ whois Pragma
+ [comment]# Get the Pragma idle time[/comment]
+ whois Pragma Pragma
+ [/example]
+ @seealso:
+ [cmd]whowas[/cmd]
+ */
+
+ KVSCSC(whois)
+ {
+ QString szNick;
+ KVSCSC_PARAMETERS_BEGIN
+ KVSCSC_PARAMETER("nickname",KVS_PT_NONEMPTYSTRING,KVS_PF_APPENDREMAINING,szNick)
+ KVSCSC_PARAMETERS_END
+
+ KviQCString szData = KVSCSC_pContext->window()->encodeText(szNick);
+
+ if(!KVSCSC_pContext->connection())return KVSCSC_pContext->warningNoIrcConnection();
+ if(!KVSCSC_pContext->connection()->sendFmtData("WHOIS %s",szData.data()))return KVSCSC_pContext->warningNoIrcConnection();
+
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ @doc: whowas
+ @type:
+ command
+ @title:
+ whowas
+ @syntax:
+ whowas <nickname>
+ @short:
+ Requests user information
+ @description:
+ Requests information about an irc user specified by <nickname>.[br]
+ Whowas requests "history" records. See [doc:rfc2812]RFC2812[/doc] for more info.[br]
+ This command is [doc:connection_dependant_commands]connection dependant[/doc].
+ @examples:
+ [example]
+ [comment]# Query past info about Pragma[/comment]
+ whowas Pragma
+ [/example]
+ @seealso:
+ [cmd]whois[/cmd]
+ */
+
+ KVSCSC(whowas)
+ {
+ QString szNick;
+ KVSCSC_PARAMETERS_BEGIN
+ KVSCSC_PARAMETER("nickname",KVS_PT_NONEMPTYSTRING,KVS_PF_APPENDREMAINING,szNick)
+ KVSCSC_PARAMETERS_END
+
+ KviQCString szData = KVSCSC_pContext->window()->encodeText(szNick);
+
+ if(!KVSCSC_pContext->connection())return KVSCSC_pContext->warningNoIrcConnection();
+ if(!KVSCSC_pContext->connection()->sendFmtData("WHOWAS %s",szData.data()))return KVSCSC_pContext->warningNoIrcConnection();
+
+ return true;
+ }
+
+};
diff --git a/src/kvirc/kvs/kvi_kvs_dnsmanager.cpp b/src/kvirc/kvs/kvi_kvs_dnsmanager.cpp
new file mode 100644
index 00000000..ec1efde6
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_dnsmanager.cpp
@@ -0,0 +1,180 @@
+//=============================================================================
+//
+// File : kvi_kvs_dnsmanager.cpp
+// Created on Wed 04 Aug 2004 04:38:31 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_dnsmanager.h"
+#include "kvi_dns.h"
+#include "kvi_app.h"
+#include "kvi_window.h"
+#include "kvi_out.h"
+#include "kvi_iconmanager.h"
+#include "kvi_kvs_script.h"
+#include "kvi_kvs_variantlist.h"
+#include "kvi_string.h"
+#include "kvi_locale.h"
+#include "kvi_error.h"
+
+KviKvsDnsManager * KviKvsDnsManager::m_pInstance = 0;
+
+
+KviKvsDnsObject::KviKvsDnsObject(KviDns * pDns,KviWindow * pWnd,const QString &szQuery,bool bRebindOnWindowClose,KviKvsScript * pCallback,KviKvsVariantList * pParameterList)
+{
+ m_pDns = pDns;
+ m_pWindow = pWnd;
+ m_szQuery = szQuery;
+ m_pCallback = pCallback;
+ m_pParameterList = pParameterList;
+ m_bRebindOnWindowClose = bRebindOnWindowClose;
+}
+
+KviKvsDnsObject::~KviKvsDnsObject()
+{
+ QObject::disconnect(m_pDns,0,0,0);
+ if(m_pDns->isRunning())
+ {
+ g_pApp->collectGarbage(m_pDns);
+ } else {
+ delete m_pDns;
+ }
+ if(m_pCallback)delete m_pCallback;
+ if(m_pParameterList)delete m_pParameterList;
+}
+
+
+KviKvsDnsManager::KviKvsDnsManager()
+: QObject()
+{
+ m_pDnsObjects = 0;
+}
+
+KviKvsDnsManager::~KviKvsDnsManager()
+{
+ if(m_pDnsObjects)delete m_pDnsObjects;
+}
+
+void KviKvsDnsManager::init()
+{
+ if(KviKvsDnsManager::m_pInstance)
+ {
+ debug("Trying to double init() the dns manager!");
+ return;
+ }
+ KviKvsDnsManager::m_pInstance = new KviKvsDnsManager();
+}
+
+void KviKvsDnsManager::done()
+{
+ if(!KviKvsDnsManager::m_pInstance)
+ {
+ debug("Trying to call done() on a non existing dns manager!");
+ return;
+ }
+ delete KviKvsDnsManager::m_pInstance;
+ KviKvsDnsManager::m_pInstance = 0;
+}
+
+void KviKvsDnsManager::addDns(KviKvsDnsObject * pObject)
+{
+ if(!m_pDnsObjects)
+ {
+ m_pDnsObjects = new KviPointerHashTable<void *,KviKvsDnsObject>;
+ m_pDnsObjects->setAutoDelete(true);
+ }
+ m_pDnsObjects->replace(pObject->dns(),pObject);
+ connect(pObject->dns(),SIGNAL(lookupDone(KviDns *)),this,SLOT(dnsLookupTerminated(KviDns *)));
+}
+
+void KviKvsDnsManager::dnsLookupTerminated(KviDns * pDns)
+{
+ KviKvsDnsObject * o = m_pDnsObjects->find(pDns);
+ if(!o)
+ {
+ debug("KviKvsDnsManager::dnsLookupTerminated(): can't find the KviKvsDnsObject structure");
+ return;
+ }
+
+ if(!g_pApp->windowExists(o->window()))
+ {
+ if(o->rebindOnWindowClose())
+ {
+ o->setWindow(g_pActiveWindow);
+ } else {
+ // just kill it
+ m_pDnsObjects->remove(pDns);
+ return;
+ }
+ }
+
+ if(o->callback())
+ {
+ KviKvsScript copy(*(o->callback()));
+ if(!o->parameterList())
+ o->setParameterList(new KviKvsVariantList());
+
+ if(o->dns()->state() == KviDns::Failure)
+ {
+ // $4... is the magic data
+ o->parameterList()->prepend(new KviKvsVariant()); // $3
+ o->parameterList()->prepend(new KviKvsVariant(KviError::getDescription(o->dns()->error()))); // $2
+ o->parameterList()->prepend(new KviKvsVariant((kvs_int_t)0)); // $1
+ } else {
+ QString * fh = o->dns()->hostnameList()->first();
+ QString * fi = o->dns()->ipAddressList()->first();
+
+ // $4... is the magic data
+ o->parameterList()->prepend(new KviKvsVariant(fh ? *fh : QString("?.?"))); // $3
+ o->parameterList()->prepend(new KviKvsVariant(fi ? *fi : QString("?.?.?.?"))); // $2
+ o->parameterList()->prepend(new KviKvsVariant((kvs_int_t)1)); // $1
+ }
+ o->parameterList()->prepend(new KviKvsVariant(o->query())); // $0
+
+ copy.run(o->window(),o->parameterList(),0,KviKvsScript::PreserveParams);
+
+ } else {
+ QString szQuery = o->dns()->query();
+ o->window()->output(KVI_OUT_HOSTLOOKUP,__tr2qs("DNS Lookup result for query \"%Q\""),&szQuery);
+
+ if(o->dns()->state() == KviDns::Failure)
+ {
+ QString szErr = KviError::getDescription(o->dns()->error());
+ o->window()->output(KVI_OUT_HOSTLOOKUP,__tr2qs("Error: %Q"),&szErr);
+ } else {
+ int idx = 1;
+ for(QString * h = o->dns()->hostnameList()->first();h;h = o->dns()->hostnameList()->next())
+ {
+ o->window()->output(KVI_OUT_HOSTLOOKUP,__tr2qs("Hostname %d: %Q"),idx,h);
+ idx++;
+ }
+ idx = 1;
+ for(QString * a = o->dns()->ipAddressList()->first();a;a = o->dns()->ipAddressList()->next())
+ {
+ o->window()->output(KVI_OUT_HOSTLOOKUP,__tr2qs("IP address %d: %Q"),idx,a);
+ idx++;
+ }
+ }
+ }
+
+ m_pDnsObjects->remove(pDns);
+}
diff --git a/src/kvirc/kvs/kvi_kvs_dnsmanager.h b/src/kvirc/kvs/kvi_kvs_dnsmanager.h
new file mode 100644
index 00000000..69d152c5
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_dnsmanager.h
@@ -0,0 +1,86 @@
+#ifndef _KVI_KVS_DNSMANAGER_H_
+#define _KVI_KVS_DNSMANAGER_H_
+//=============================================================================
+//
+// File : kvi_kvs_dnsmanager.h
+// Created on Wed 04 Aug 2004 04:38:31 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include <qobject.h>
+#include "kvi_pointerhashtable.h"
+#include <qstring.h>
+
+class KviDns;
+class KviWindow;
+class KviKvsScript;
+class KviKvsVariantList;
+
+class KviKvsDnsObject
+{
+public:
+ KviKvsDnsObject(KviDns * pDns,
+ KviWindow * pWnd,
+ const QString &szQuery,
+ bool bRebindOnWindowClose = true,
+ KviKvsScript * pCallback = 0,
+ KviKvsVariantList * pParameterList = 0);
+ ~KviKvsDnsObject();
+protected:
+ KviDns * m_pDns;
+ KviWindow * m_pWindow;
+ QString m_szQuery;
+ KviKvsScript * m_pCallback; // callback to be executed when the dns terminates
+ KviKvsVariantList * m_pParameterList; // parameter list (magic)
+ bool m_bRebindOnWindowClose; // should we trigger the callback even if m_pWindow no longer exists ?
+public:
+ KviDns * dns(){ return m_pDns; };
+ KviWindow * window(){ return m_pWindow; };
+ KviKvsScript * callback(){ return m_pCallback; };
+ KviKvsVariantList * parameterList(){ return m_pParameterList; };
+ const QString & query(){ return m_szQuery; };
+ bool rebindOnWindowClose(){ return m_bRebindOnWindowClose; };
+ void setWindow(KviWindow * pWnd){ m_pWindow = pWnd; };
+ void setParameterList(KviKvsVariantList * pList){ m_pParameterList = pList; };
+};
+
+class KviKvsDnsManager : public QObject
+{
+ Q_OBJECT
+public:
+ KviKvsDnsManager();
+ ~KviKvsDnsManager();
+protected:
+ static KviKvsDnsManager * m_pInstance;
+ KviPointerHashTable<void *,KviKvsDnsObject> * m_pDnsObjects;
+public:
+ static KviKvsDnsManager * instance(){ return m_pInstance; };
+ static void init();
+ static void done();
+
+ void addDns(KviKvsDnsObject * pObject);
+protected slots:
+ void dnsLookupTerminated(KviDns * pDns);
+private:
+ void abortAll();
+};
+
+#endif //!_KVI_KVS_DNSMANAGER_H_
diff --git a/src/kvirc/kvs/kvi_kvs_event.cpp b/src/kvirc/kvs/kvi_kvs_event.cpp
new file mode 100644
index 00000000..4692eff0
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_event.cpp
@@ -0,0 +1,80 @@
+//=============================================================================
+//
+// File : kvi_kvs_event.cpp
+// Created on Mon 23 Feb 2004 03:00:02 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_event.h"
+
+
+KviKvsEvent::~KviKvsEvent()
+{
+ clear();
+}
+
+void KviKvsEvent::clear()
+{
+ if(m_pHandlers)delete m_pHandlers;
+ m_pHandlers = 0;
+}
+
+void KviKvsEvent::removeHandler(KviKvsEventHandler * h)
+{
+ m_pHandlers->removeRef(h);
+ if(m_pHandlers->isEmpty())
+ {
+ delete m_pHandlers;
+ m_pHandlers = 0;
+ }
+}
+
+void KviKvsEvent::addHandler(KviKvsEventHandler * h)
+{
+ if(!m_pHandlers)
+ {
+ m_pHandlers = new KviPointerList<KviKvsEventHandler>();
+ m_pHandlers->setAutoDelete(true);
+ }
+ m_pHandlers->append(h);
+}
+
+void KviKvsEvent::clearScriptHandlers()
+{
+ if(!m_pHandlers)return;
+ KviPointerList<KviKvsEventHandler> dl;
+ dl.setAutoDelete(false);
+ KviKvsEventHandler * e;
+ for(e = m_pHandlers->first();e;e = m_pHandlers->next())
+ {
+ if(e->type() == KviKvsEventHandler::Script)dl.append(e);
+ }
+ for(e = dl.first();e;e = dl.next())
+ {
+ m_pHandlers->removeRef(e);
+ }
+ if(m_pHandlers->isEmpty())
+ {
+ delete m_pHandlers;
+ m_pHandlers = 0;
+ }
+}
diff --git a/src/kvirc/kvs/kvi_kvs_event.h b/src/kvirc/kvs/kvi_kvs_event.h
new file mode 100644
index 00000000..663777be
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_event.h
@@ -0,0 +1,54 @@
+#ifndef _KVI_KVS_EVENT_H_
+#define _KVI_KVS_EVENT_H_
+//=============================================================================
+//
+// File : kvi_kvs_event.h
+// Created on Mon 23 Feb 2004 03:00:02 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_pointerlist.h"
+
+#include "kvi_kvs_eventhandler.h"
+
+class KVIRC_API KviKvsEvent
+{
+protected:
+ QString m_szName;
+ QString m_szParameterDescription;
+ KviPointerList<KviKvsEventHandler> * m_pHandlers;
+public:
+ // the event name and the parameter description are NOT translated
+ KviKvsEvent(const char * szEventName,const char * szParameterDescription)
+ : m_szName(szEventName), m_szParameterDescription(szParameterDescription), m_pHandlers(0) {};
+ ~KviKvsEvent();
+ void clear();
+ void clearScriptHandlers();
+ bool hasHandlers(){ return m_pHandlers != 0; };
+ KviPointerList<KviKvsEventHandler> * handlers(){ return m_pHandlers; };
+ void addHandler(KviKvsEventHandler * h);
+ void removeHandler(KviKvsEventHandler * h);
+ const QString & name(){ return m_szName; };
+ const QString & parameterDescription(){ return m_szParameterDescription; };
+};
+
+#endif //!_KVI_KVS_EVENT_H_
diff --git a/src/kvirc/kvs/kvi_kvs_eventhandler.cpp b/src/kvirc/kvs/kvi_kvs_eventhandler.cpp
new file mode 100644
index 00000000..f6e311f0
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_eventhandler.cpp
@@ -0,0 +1,78 @@
+//=============================================================================
+//
+// File : kvi_kvs_eventhandler.cpp
+// Created on Mon 23 Feb 2004 03:04:58 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_eventhandler.h"
+
+KviKvsEventHandler::KviKvsEventHandler(Type t)
+: KviHeapObject(), m_type(t)
+{
+}
+
+KviKvsEventHandler::~KviKvsEventHandler()
+{
+}
+
+
+
+KviKvsScriptEventHandler::KviKvsScriptEventHandler(const QString &szHandlerName,const QString &szContextName,const QString &szCode,bool bEnabled)
+: KviKvsEventHandler(KviKvsEventHandler::Script), m_szName(szHandlerName), m_bEnabled(bEnabled)
+{
+ m_pScript = new KviKvsScript(szContextName,szCode);
+}
+
+KviKvsScriptEventHandler::~KviKvsScriptEventHandler()
+{
+ delete m_pScript;
+}
+
+KviKvsScriptEventHandler * KviKvsScriptEventHandler::createInstance(const QString &szHandlerName,const QString &szContextName,const QString &szCode,bool bEnabled)
+{
+ return new KviKvsScriptEventHandler(szHandlerName,szContextName,szCode,bEnabled);
+}
+
+
+KviKvsModuleEventHandler::KviKvsModuleEventHandler(KviKvsModuleInterface * m,KviKvsModuleEventHandlerRoutine proc)
+: KviKvsEventHandler(KviKvsEventHandler::Module), m_pModule(m)
+{
+ m_pProc = new KviKvsModuleEventHandlerRoutine(proc);
+}
+
+KviKvsModuleEventHandler::~KviKvsModuleEventHandler()
+{
+ delete m_pProc;
+}
+
+
+/*
+KviKvsOldModuleEventHandler::KviKvsOldModuleEventHandler(KviModuleEventParseProc p,KviModule * m)
+: KviKvsEventHandler(KviKvsEventHandler::OldModule), m_pModule(m), m_proc(p)
+{
+}
+
+KviKvsOldModuleEventHandler::~KviKvsOldModuleEventHandler()
+{
+}
+*/
diff --git a/src/kvirc/kvs/kvi_kvs_eventhandler.h b/src/kvirc/kvs/kvi_kvs_eventhandler.h
new file mode 100644
index 00000000..f8124b68
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_eventhandler.h
@@ -0,0 +1,106 @@
+#ifndef _KVI_KVS_EVENTHANDLER_H_
+#define _KVI_KVS_EVENTHANDLER_H_
+//=============================================================================
+//
+// File : kvi_kvs_eventhandler.h
+// Created on Mon 23 Feb 2004 03:04:58 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_kvs_script.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_moduleinterface.h"
+#include "kvi_heapobject.h"
+
+class KVIRC_API KviKvsEventHandler : public KviHeapObject
+{
+public:
+ enum Type { Script , Module };
+protected:
+ Type m_type;
+public:
+ KviKvsEventHandler(Type t);
+ virtual ~KviKvsEventHandler();
+public:
+ Type type(){ return m_type; };
+};
+
+
+class KVIRC_API KviKvsScriptEventHandler : public KviKvsEventHandler
+{
+public:
+ // the event handler becomes the owned of pszCode!
+ KviKvsScriptEventHandler(const QString &szHandlerName,const QString &szContextName,const QString &szCode,bool bEnabled = true);
+ virtual ~KviKvsScriptEventHandler();
+protected:
+ QString m_szName;
+ KviKvsScript * m_pScript;
+ bool m_bEnabled;
+public:
+ KviKvsScript * script(){ return m_pScript; };
+ const QString & name(){ return m_szName; };
+ const QString & code(){ return m_pScript->code(); };
+
+ bool isEnabled(){ return m_bEnabled; };
+ void setEnabled(bool bEnabled){ m_bEnabled = bEnabled; };
+
+ // Static allocator function.
+ // This MUST be used by the modules to allocate event structures
+ // instead of the new operator.
+ // See kvi_heapobject.cpp for an explaination.
+ static KviKvsScriptEventHandler * createInstance(const QString &szHandlerName,const QString &szContextName,const QString &szCode,bool bEnabled = true);
+};
+
+
+class KVIRC_API KviKvsModuleEventHandler : public KviKvsEventHandler
+{
+protected:
+ KviKvsModuleInterface * m_pModule;
+ KviKvsModuleEventHandlerRoutine * m_pProc;
+public:
+ KviKvsModuleEventHandler(KviKvsModuleInterface * m,KviKvsModuleEventHandlerRoutine proc);
+ virtual ~KviKvsModuleEventHandler();
+public:
+ KviKvsModuleInterface * moduleInterface(){ return m_pModule; };
+ KviKvsModuleEventHandlerRoutine * handlerRoutine(){ return m_pProc; };
+};
+
+
+/*
+#include "kvi_module.h"
+
+class KVIRC_API KviKvsOldModuleEventHandler : public KviKvsEventHandler
+{
+protected:
+ KviModule * m_pModule;
+ KviModuleEventParseProc m_proc;
+public:
+ KviKvsOldModuleEventHandler(KviModuleEventParseProc p,KviModule * m);
+ virtual ~KviKvsOldModuleEventHandler();
+public:
+ KviModule * module(){ return m_pModule; };
+ void setModule(KviModule * m){ m_pModule = m; };
+ KviModuleEventParseProc proc(){ return m_proc; };
+ void setProc(KviModuleEventParseProc p){ m_proc = p; };
+};
+
+*/
+#endif //!_KVI_KVS_EVENTHANDLER_H_
diff --git a/src/kvirc/kvs/kvi_kvs_eventmanager.cpp b/src/kvirc/kvs/kvi_kvs_eventmanager.cpp
new file mode 100644
index 00000000..1a2131c0
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_eventmanager.cpp
@@ -0,0 +1,678 @@
+//=============================================================================
+//
+// File : kvi_kvs_eventmanager.cpp
+// Created on Thu Aug 17 2000 13:59:12 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2000-2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_eventmanager.h"
+#include "kvi_config.h"
+#include "kvi_kvs_script.h"
+#include "kvi_kvs_variant.h"
+#include "kvi_options.h"
+#include "kvi_locale.h"
+#include "kvi_out.h"
+#include "kvi_module.h"
+#include "kvi_window.h"
+#include "kvi_kvs_variantlist.h"
+
+/*
+ @doc: events
+ @type:
+ language
+ @keyterms:
+ events,event handlers,event
+ @title:
+ Events
+ @short:
+ Events: user reactions
+ @body:
+ KVIrc triggers an event when a particular situation occurs (hehe :D).[br]
+ You can define a set of event handlers for each event type.[br]
+ An event handler is a snippet of user-defined code that gets executed when the event is triggered.[br]
+ Event handlers can be created or destroyed by using the scriptcenter (graphic interface)
+ or even from the commandline (or script) by using the [cmd]event[/cmd] command.[br]
+ For example, the [event:onirc]OnIRC[/event] is triggered when the login operations have
+ been terminated and you can consider yourself "completely" on IRC. For example , you might
+ want to "auto-join" some channels. Nothing easier! The following snippet of code
+ adds a handler to the OnIRC event that joins three channels:[br]
+ [example]
+ [cmd]event[/cmd](OnIRC,autojoin)
+ {
+ [cmd]echo[/cmd] Auto-joining my preferred channels...
+ [cmd]join[/cmd] #kvirc,#siena,#linux
+ }
+ [/example]
+ Now try to connect to a server and you'll see that it joins automatically the three channels!.[br]
+ You might also want to do some other actions just after the connection has been established,
+ for example you might want to look immediately for a friend of yours by issuing a [cmd]whois[/cmd]
+ to the server (well.. you could use the notify list for that, but well, this is an example).[br]
+ You can add the [cmd]whois[/cmd] request to the handler above or just create a new one:[br]
+ [example]
+ [cmd]event[/cmd](OnIRC,lookforfred)
+ {
+ [cmd]echo[/cmd] Looking for fred...
+ [cmd]whois[/cmd] fred
+ }
+ [/example]
+ (An even nicer idea would be to use the [cmd]awhois[/cmd] command...but that's left to the reader as exercise.[br]
+ To remove an event handler you still use the [cmd]event[/cmd] command , but with an empty code block:[br]
+ [example]
+ [cmd]event[/cmd](OnIRC,lookforfred){}[br]
+ [/example]
+ [br]
+ Certain events will pass you some data in the positional parameters.[br]
+ For example, when you are being banned from a channel, KVIrc triggers the [event:onmeban]OnMeBan[/event]
+ event: you might be interested in WHO has banned you. KVIrc will pass the "ban source" informations
+ in the positional parameters $0,$1 and $2.[br]
+ (Please note that the parameters started from $1 in KVIrc versions older than 3.0.0!).[br]
+ You may take a look at the list of available [doc:event_index_all]events[/doc].[br]
+*/
+
+
+KviKvsEventManager * KviKvsEventManager::m_pInstance = 0;
+
+KviKvsEventManager::KviKvsEventManager()
+{
+ m_pInstance = this;
+ for(int i=0;i<KVI_KVS_NUM_RAW_EVENTS;i++)
+ m_rawEventTable[i] = 0;
+}
+
+KviKvsEventManager::~KviKvsEventManager()
+{
+ clear();
+}
+
+void KviKvsEventManager::init()
+{
+ if(KviKvsEventManager::instance())
+ {
+ debug("WARNING: Trying to create KviKvsEventManager twice!");
+ return;
+ }
+ (void) new KviKvsEventManager();
+}
+
+void KviKvsEventManager::done()
+{
+ if(!KviKvsEventManager::instance())
+ {
+ debug("WARNING: Trying to destroy the KviKvsEventManager twice!");
+ return;
+ }
+ delete KviKvsEventManager::instance();
+}
+
+unsigned int KviKvsEventManager::findAppEventIndexByName(const QString &szName)
+{
+ for(unsigned int u = 0;u < KVI_KVS_NUM_APP_EVENTS;u++)
+ {
+ if(KviQString::equalCI(szName,m_appEventTable[u].name()))return u;
+ //Backwards compatibility >_<
+ if((u == 4) && KviQString::equalCI(szName,"OnIrcConnectionEstabilished"))
+ return u;
+ }
+ return KVI_KVS_NUM_APP_EVENTS; // <-- invalid event number
+}
+
+KviKvsEvent * KviKvsEventManager::findAppEventByName(const QString &szName)
+{
+ for(unsigned int u = 0;u < KVI_KVS_NUM_APP_EVENTS;u++)
+ {
+ if(KviQString::equalCI(szName,m_appEventTable[u].name()))return &(m_appEventTable[u]);
+ //Backwards compatibility >_<
+ if((u == 4) && KviQString::equalCI(szName,"OnIrcConnectionEstabilished"))
+ return &(m_appEventTable[u]);
+ }
+ return 0;
+}
+
+bool KviKvsEventManager::addAppHandler(unsigned int uEvIdx,KviKvsEventHandler * h)
+{
+ if(uEvIdx >= KVI_KVS_NUM_APP_EVENTS)return false;
+ m_appEventTable[uEvIdx].addHandler(h);
+ return true;
+}
+
+bool KviKvsEventManager::addRawHandler(unsigned int uRawIdx,KviKvsEventHandler * h)
+{
+ if(uRawIdx >= KVI_KVS_NUM_RAW_EVENTS)return false;
+ if(!m_rawEventTable[uRawIdx])
+ {
+ m_rawEventTable[uRawIdx] = new KviPointerList<KviKvsEventHandler>();
+ m_rawEventTable[uRawIdx]->setAutoDelete(true);
+ }
+ m_rawEventTable[uRawIdx]->append(h);
+ return true;
+}
+
+bool KviKvsEventManager::removeScriptAppHandler(unsigned int uEvIdx,const QString &szName)
+{
+ if(uEvIdx >= KVI_KVS_NUM_APP_EVENTS)return false;
+ KviKvsEventHandler * h;
+ if(!(m_appEventTable[uEvIdx].handlers()))return false;
+ for(h = m_appEventTable[uEvIdx].handlers()->first();h;h = m_appEventTable[uEvIdx].handlers()->next())
+ {
+ if(h->type() == KviKvsEventHandler::Script)
+ {
+ if(KviQString::equalCI(((KviKvsScriptEventHandler *)h)->name(),szName))
+ {
+ m_appEventTable[uEvIdx].removeHandler(h);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+KviKvsScriptEventHandler * KviKvsEventManager::findScriptRawHandler(unsigned int uEvIdx,const QString &szName)
+{
+ if(uEvIdx >= KVI_KVS_NUM_RAW_EVENTS)return 0;
+ if(!m_rawEventTable[uEvIdx])return 0;
+ KviKvsEventHandler * h;
+ for(h = m_rawEventTable[uEvIdx]->first();h;h = m_rawEventTable[uEvIdx]->next())
+ {
+ if(h->type() == KviKvsEventHandler::Script)
+ {
+ if(KviQString::equalCI(((KviKvsScriptEventHandler *)h)->name(),szName))
+ {
+ return (KviKvsScriptEventHandler *)h;
+ }
+ }
+ }
+ return 0;
+}
+
+KviKvsScriptEventHandler * KviKvsEventManager::findScriptAppHandler(unsigned int uEvIdx,const QString &szName)
+{
+ if(uEvIdx >= KVI_KVS_NUM_APP_EVENTS)return 0;
+ KviKvsEventHandler * h;
+ if(!(m_appEventTable[uEvIdx].handlers()))return 0;
+ for(h = m_appEventTable[uEvIdx].handlers()->first();h;h = m_appEventTable[uEvIdx].handlers()->next())
+ {
+ if(h->type() == KviKvsEventHandler::Script)
+ {
+ if(KviQString::equalCI(((KviKvsScriptEventHandler *)h)->name(),szName))
+ {
+ return (KviKvsScriptEventHandler *)h;
+ }
+ }
+ }
+ return 0;
+}
+
+bool KviKvsEventManager::enableScriptAppHandler(unsigned int uEvIdx,const QString &szName,bool bEnable)
+{
+ KviKvsScriptEventHandler * h = findScriptAppHandler(uEvIdx,szName);
+ if(!h)return false;
+ h->setEnabled(bEnable);
+ return true;
+}
+
+
+bool KviKvsEventManager::removeModuleAppHandler(unsigned int uEvIdx,KviKvsModuleInterface *i)
+{
+ if(uEvIdx >= KVI_KVS_NUM_APP_EVENTS)return false;
+ KviKvsEventHandler * h;
+ if(!(m_appEventTable[uEvIdx].handlers()))return false;
+ for(h = m_appEventTable[uEvIdx].handlers()->first();h;h = m_appEventTable[uEvIdx].handlers()->next())
+ {
+ if(h->type() == KviKvsEventHandler::Module)
+ {
+ if(((KviKvsModuleEventHandler *)h)->moduleInterface() == i)
+ {
+ m_appEventTable[uEvIdx].removeHandler(h);
+ return true;
+ }
+ }
+ // COMPAT
+ /*
+ } else if(h->type() == KviKvsEventHandler::OldModule)
+ {
+ if(((KviKvsOldModuleEventHandler *)h)->module() == i)
+ {
+ m_appEventTable[uEvIdx].removeHandler(h);
+ return true;
+ }
+ }
+ */
+ // END COMPAT
+ }
+ return false;
+}
+
+void KviKvsEventManager::removeAllModuleAppHandlers(KviKvsModuleInterface *pIface)
+{
+ KviKvsEventHandler * h;
+ for(unsigned int i =0;i< KVI_KVS_NUM_APP_EVENTS;i++)
+ {
+ if(!m_appEventTable[i].handlers())continue;
+
+ KviPointerList<KviKvsEventHandler> l;
+ l.setAutoDelete(false);
+ for(h = m_appEventTable[i].handlers()->first();h;h = m_appEventTable[i].handlers()->next())
+ {
+ if(h->type() == KviKvsEventHandler::Module)
+ {
+ if(((KviKvsModuleEventHandler *)h)->moduleInterface() == pIface)
+ {
+ l.append(h);
+ }
+ }
+ // COMPAT
+ /*
+ } else if(h->type() == KviKvsEventHandler::OldModule)
+ {
+ if(((KviKvsOldModuleEventHandler *)h)->module() == pIface)
+ {
+ l.append(h);
+ }
+ }
+ */
+ // END COMPAT
+
+ }
+ for(h = l.first();h;h = l.next())m_appEventTable[i].removeHandler(h);
+ }
+}
+
+void KviKvsEventManager::removeAllModuleRawHandlers(KviKvsModuleInterface *pIface)
+{
+ KviKvsEventHandler * h;
+ for(unsigned int i =0;i< KVI_KVS_NUM_RAW_EVENTS;i++)
+ {
+ if(!m_rawEventTable[i])continue;
+
+ KviPointerList<KviKvsEventHandler> l;
+ l.setAutoDelete(false);
+ for(h = m_rawEventTable[i]->first();h;h = m_rawEventTable[i]->next())
+ {
+ if(h->type() == KviKvsEventHandler::Module)
+ {
+ if(((KviKvsModuleEventHandler *)h)->moduleInterface() == pIface)
+ {
+ l.append(h);
+ }
+ }
+ // COMPAT
+ /*
+ } else if(h->type() == KviKvsEventHandler::OldModule)
+ {
+ if(((KviKvsOldModuleEventHandler *)h)->module() == pIface)
+ {
+ l.append(h);
+ }
+ }
+ */
+ // END COMPAT
+
+ }
+ for(h = l.first();h;h = l.next())m_rawEventTable[i]->removeRef(h);
+ if(m_rawEventTable[i]->isEmpty())
+ {
+ delete m_rawEventTable[i];
+ m_rawEventTable[i] = 0;
+ }
+ }
+}
+
+bool KviKvsEventManager::removeScriptRawHandler(unsigned int uEvIdx,const QString &szName)
+{
+ if(uEvIdx >= KVI_KVS_NUM_RAW_EVENTS)return false;
+ if(!m_rawEventTable[uEvIdx])return false;
+ KviKvsEventHandler * h;
+ for(h = m_rawEventTable[uEvIdx]->first();h;h = m_rawEventTable[uEvIdx]->next())
+ {
+ if(h->type() == KviKvsEventHandler::Script)
+ {
+ if(KviQString::equalCI(((KviKvsScriptEventHandler *)h)->name(),szName))
+ {
+ m_rawEventTable[uEvIdx]->removeRef(h);
+ if(m_rawEventTable[uEvIdx]->isEmpty())
+ {
+ delete m_rawEventTable[uEvIdx];
+ m_rawEventTable[uEvIdx] = 0;
+ }
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+
+bool KviKvsEventManager::enableScriptRawHandler(unsigned int uEvIdx,const QString &szName,bool bEnable)
+{
+ KviKvsScriptEventHandler * h = findScriptRawHandler(uEvIdx,szName);
+ if(!h)return false;
+ h->setEnabled(bEnable);
+ return true;
+}
+
+
+bool KviKvsEventManager::removeModuleRawHandler(unsigned int uRawIdx,KviKvsModuleInterface *i)
+{
+ if(uRawIdx >= KVI_KVS_NUM_RAW_EVENTS)return false;
+ if(!m_rawEventTable[uRawIdx])return false;
+ KviKvsEventHandler * h;
+ for(h = m_rawEventTable[uRawIdx]->first();h;h = m_rawEventTable[uRawIdx]->next())
+ {
+ if(h->type() == KviKvsEventHandler::Module)
+ {
+ if(((KviKvsModuleEventHandler *)h)->moduleInterface() == i)
+ {
+ m_rawEventTable[uRawIdx]->removeRef(h);
+ if(m_rawEventTable[uRawIdx]->isEmpty())
+ {
+ delete m_rawEventTable[uRawIdx];
+ m_rawEventTable[uRawIdx] = 0;
+ }
+ return true;
+ }
+ }
+ // COMPAT
+ /*
+ } else if(h->type() == KviKvsEventHandler::OldModule)
+ {
+ if(((KviKvsOldModuleEventHandler *)h)->module() == i)
+ {
+ m_rawEventTable[uRawIdx]->removeRef(h);
+ if(m_rawEventTable[uRawIdx]->isEmpty())
+ {
+ delete m_rawEventTable[uRawIdx];
+ m_rawEventTable[uRawIdx] = 0;
+ }
+ return true;
+ }
+ }
+ */
+ // END COMPAT
+
+ }
+ return false;
+}
+
+void KviKvsEventManager::removeAllModuleHandlers(KviKvsModuleInterface * pIface)
+{
+ removeAllModuleAppHandlers(pIface);
+ removeAllModuleRawHandlers(pIface);
+}
+
+void KviKvsEventManager::removeAllScriptAppHandlers()
+{
+ for(int i=0;i< KVI_KVS_NUM_APP_EVENTS;i++)
+ {
+ m_appEventTable[i].clearScriptHandlers();
+ }
+}
+
+void KviKvsEventManager::removeAllScriptRawHandlers()
+{
+ for(int i=0;i< KVI_KVS_NUM_RAW_EVENTS;i++)
+ {
+ if(m_rawEventTable[i])
+ {
+ KviPointerList<KviKvsEventHandler> dl;
+ dl.setAutoDelete(false);
+ KviKvsEventHandler * e;
+ for(e = m_rawEventTable[i]->first();e;e = m_rawEventTable[i]->next())
+ {
+ if(e->type() == KviKvsEventHandler::Script)dl.append(e);
+ }
+
+ for(e = dl.first();e;e = dl.next())
+ {
+ m_rawEventTable[i]->removeRef(e);
+ }
+
+ if(m_rawEventTable[i]->isEmpty())
+ {
+ delete m_rawEventTable[i];
+ m_rawEventTable[i] = 0;
+ }
+ }
+ }
+}
+
+void KviKvsEventManager::clearRawEvents()
+{
+ for(int i=0;i<KVI_KVS_NUM_RAW_EVENTS;i++)
+ {
+ if(m_rawEventTable[i])delete m_rawEventTable[i];
+ m_rawEventTable[i] = 0;
+ }
+}
+
+void KviKvsEventManager::clearAppEvents()
+{
+ for(int i=0;i<KVI_KVS_NUM_APP_EVENTS;i++)
+ {
+ m_appEventTable[i].clear();
+ }
+}
+
+void KviKvsEventManager::clear()
+{
+ clearRawEvents();
+ clearAppEvents();
+}
+
+bool KviKvsEventManager::triggerHandlers(KviPointerList<KviKvsEventHandler> * pHandlers,KviWindow *pWnd,KviKvsVariantList *pParams)
+{
+ if(!pHandlers)return false;
+
+ bool bGotHalt = false;
+ for(KviKvsEventHandler * h = pHandlers->first();h;h = pHandlers->next())
+ {
+ switch(h->type())
+ {
+ case KviKvsEventHandler::Script:
+ {
+ if(((KviKvsScriptEventHandler *)h)->isEnabled())
+ {
+ KviKvsScript * s = ((KviKvsScriptEventHandler *)h)->script();
+ KviKvsScript copy(*s);
+ KviKvsVariant retVal;
+ int iRet = copy.run(pWnd,pParams,&retVal,KviKvsScript::PreserveParams);
+ if(!iRet)
+ {
+ // error! disable the handler if it's broken
+ if(KVI_OPTION_BOOL(KviOption_boolDisableBrokenEventHandlers))
+ {
+ ((KviKvsScriptEventHandler *)h)->setEnabled(false);
+ pWnd->output(KVI_OUT_PARSERERROR,__tr2qs("Event handler %Q is broken: disabling"),&(s->name()));
+ }
+ }
+ if(!bGotHalt)bGotHalt = (iRet & KviKvsScript::HaltEncountered);
+ }
+ }
+ break;
+ case KviKvsEventHandler::Module:
+ {
+ KviModule * m = (KviModule *)((KviKvsModuleEventHandler *)h)->moduleInterface();
+ KviKvsModuleEventHandlerRoutine * proc = ((KviKvsModuleEventHandler *)h)->handlerRoutine();
+ KviKvsVariant retVal;
+ KviKvsRunTimeContext ctx(0,pWnd,pParams,&retVal);
+ KviKvsModuleEventCall call(m,&ctx,pParams);
+ if(!(*proc)(&call))bGotHalt = true;
+ }
+ break;
+ }
+ }
+ return bGotHalt;
+}
+
+
+void KviKvsEventManager::loadRawEvents(const QString &szFileName)
+{
+ KviConfig cfg(szFileName,KviConfig::Read);
+ removeAllScriptRawHandlers();
+ int i;
+
+ for(i=0;i<KVI_KVS_NUM_RAW_EVENTS;i++)
+ {
+ QString tmp;
+ KviQString::sprintf(tmp,"RAW%d",i);
+ if(cfg.hasGroup(tmp))
+ {
+ cfg.setGroup(tmp);
+ unsigned int nHandlers = cfg.readUIntEntry("NHandlers",0);
+ if(nHandlers)
+ {
+ m_rawEventTable[i] = new KviPointerList<KviKvsEventHandler>();
+ m_rawEventTable[i]->setAutoDelete(true);
+ for(unsigned int index = 0;index < nHandlers;index++)
+ {
+ KviQString::sprintf(tmp,"Name%u",index);
+ QString szName = cfg.readQStringEntry(tmp,"unnamed");
+ KviQString::sprintf(tmp,"Buffer%u",index);
+ QString szCode = cfg.readQStringEntry(tmp,"");
+ KviQString::sprintf(tmp,"RawEvent%u::%Q",index,&szName);
+ KviKvsScriptEventHandler * s = new KviKvsScriptEventHandler(szName,tmp,szCode);
+ KviQString::sprintf(tmp,"Enabled%u",index);
+ s->setEnabled(cfg.readBoolEntry(tmp,false));
+ m_rawEventTable[i]->append(s);
+ }
+ }
+ }
+ }
+}
+
+void KviKvsEventManager::saveRawEvents(const QString &szFileName)
+{
+ KviConfig cfg(szFileName,KviConfig::Write);
+ cfg.clear();
+ int i;
+
+ for(i=0;i<KVI_KVS_NUM_RAW_EVENTS;i++)
+ {
+ if(m_rawEventTable[i])
+ {
+ QString tmp;
+ KviQString::sprintf(tmp,"RAW%d",i);
+ cfg.setGroup(tmp);
+
+ int index = 0;
+ for(KviKvsEventHandler * s = m_rawEventTable[i]->first();s; s = m_rawEventTable[i]->next())
+ {
+ if(s->type() == KviKvsEventHandler::Script)
+ {
+ KviQString::sprintf(tmp,"Name%d",index);
+ cfg.writeEntry(tmp,((KviKvsScriptEventHandler *)s)->name());
+ KviQString::sprintf(tmp,"Buffer%d",index);
+ cfg.writeEntry(tmp,((KviKvsScriptEventHandler *)s)->code());
+ KviQString::sprintf(tmp,"Enabled%d",index);
+ cfg.writeEntry(tmp,((KviKvsScriptEventHandler *)s)->isEnabled());
+ index++;
+ }
+ }
+ cfg.writeEntry("NHandlers",index);
+ }
+ }
+
+}
+
+void KviKvsEventManager::loadAppEvents(const QString &szFileName)
+{
+ KviConfig cfg(szFileName,KviConfig::Read);
+ removeAllScriptAppHandlers();
+
+ int i;
+ for(i=0;i<KVI_KVS_NUM_APP_EVENTS;i++)
+ {
+ QString szEventName(m_appEventTable[i].name());
+ // Backwards compatibility >_<
+ if((i == 4) && !cfg.hasGroup(szEventName))
+ szEventName = "OnIrcConnectionEstabilished";
+ if(cfg.hasGroup(szEventName))
+ {
+ cfg.setGroup(szEventName);
+ unsigned int nHandlers = cfg.readUIntEntry("NHandlers",0);
+ if(nHandlers)
+ {
+ for(unsigned int index = 0;index < nHandlers;index++)
+ {
+ QString tmp;
+ KviQString::sprintf(tmp,"Name%u",index);
+ QString szName = cfg.readQStringEntry(tmp,"unnamed");
+ KviQString::sprintf(tmp,"Buffer%u",index);
+ QString szCode = cfg.readQStringEntry(tmp,"");
+ KviQString::sprintf(tmp,"Enabled%u",index);
+ bool bEnabled = cfg.readBoolEntry(tmp,false);
+ QString szCntx;
+ KviQString::sprintf(szCntx,"%Q::%Q",&(m_appEventTable[i].name()),&szName);
+ KviKvsScriptEventHandler *s = new KviKvsScriptEventHandler(szName,szCntx,szCode,bEnabled);
+ m_appEventTable[i].addHandler(s);
+ }
+ }
+ }
+ }
+
+}
+
+void KviKvsEventManager::saveAppEvents(const QString &szFileName)
+{
+ KviConfig cfg(szFileName,KviConfig::Write);
+ cfg.clear();
+ int i;
+ bool bCompat = FALSE;
+
+ for(i=0;i<KVI_KVS_NUM_APP_EVENTS;i++)
+ {
+ if(m_appEventTable[i].hasHandlers())
+ {
+ QString szEventName(m_appEventTable[i].name());
+ // Backwards compatibility >_<
+ if((i == 4) && cfg.hasGroup(szEventName))
+ {
+ szEventName = "OnIRCConnectionEstabilished";
+ bCompat = TRUE;
+ }
+ cfg.setGroup(szEventName);
+ int index = 0;
+ for(KviKvsEventHandler* s = m_appEventTable[i].handlers()->first();s; s = m_appEventTable[i].handlers()->next())
+ {
+ if(s->type() == KviKvsEventHandler::Script)
+ {
+ QString tmp;
+ KviQString::sprintf(tmp,"Name%d",index);
+ cfg.writeEntry(tmp,((KviKvsScriptEventHandler *)s)->name());
+ KviQString::sprintf(tmp,"Buffer%d",index);
+ cfg.writeEntry(tmp,((KviKvsScriptEventHandler *)s)->code());
+ KviQString::sprintf(tmp,"Enabled%d",index);
+ cfg.writeEntry(tmp,((KviKvsScriptEventHandler *)s)->isEnabled());
+ index++;
+ }
+ }
+ cfg.writeEntry("NHandlers",index);
+
+ // Backwards compatibility >_<
+ if((i == 4) && !bCompat)
+ i--;
+ }
+ }
+}
+
+
+
+
diff --git a/src/kvirc/kvs/kvi_kvs_eventmanager.h b/src/kvirc/kvs/kvi_kvs_eventmanager.h
new file mode 100644
index 00000000..d31d2197
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_eventmanager.h
@@ -0,0 +1,120 @@
+#ifndef _KVI_KVS_EVENTMANAGER_H_
+#define _KVI_KVS_EVENTMANAGER_H_
+//=============================================================================
+//
+// File : kvi_kvs_eventmanager.h
+// Created on Thu Aug 17 2000 13:59:12 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2000-2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#include "kvi_kvs_event.h"
+#include "kvi_pointerlist.h"
+#include "kvi_kvs_eventtable.h"
+
+class KviWindow;
+class KviKvsModuleInterface;
+class KviKvsVariantList;
+
+#define KVI_KVS_NUM_RAW_EVENTS 1000
+
+class KVIRC_API KviKvsEventManager
+{
+ friend class KviModule; // compatibility only!
+protected: // it only can be created and destroyed by KviKvsAliasManager::init()/done()
+ KviKvsEventManager();
+ ~KviKvsEventManager();
+protected:
+ static KviKvsEventManager * m_pInstance;
+
+ static KviKvsEvent m_appEventTable[KVI_KVS_NUM_APP_EVENTS];
+ KviPointerList<KviKvsEventHandler> * m_rawEventTable[KVI_KVS_NUM_RAW_EVENTS];
+public:
+ static KviKvsEventManager * instance(){ return m_pInstance; };
+ static void init(); // called by KviKvs::init()
+ static void done(); // called by KviKvs::done()
+
+ KviKvsEvent * appEvent(unsigned int uEvIdx){ return &(m_appEventTable[uEvIdx]); };
+
+ bool hasAppHandlers(unsigned int uEvIdx){ return m_appEventTable[uEvIdx].hasHandlers(); };
+ KviPointerList<KviKvsEventHandler> * appHandlers(unsigned int uEvIdx){ return m_appEventTable[uEvIdx].handlers(); };
+
+ bool hasRawHandlers(unsigned int uEvIdx){ return m_rawEventTable[uEvIdx]; };
+ KviPointerList<KviKvsEventHandler> * rawHandlers(unsigned int uEvIdx){ return m_rawEventTable[uEvIdx]; };
+
+ KviKvsEvent * findAppEventByName(const QString &szName);
+ unsigned int findAppEventIndexByName(const QString &szName);
+ bool isValidAppEvent(unsigned int uEvIdx){ return (uEvIdx < KVI_KVS_NUM_APP_EVENTS); };
+
+ bool isValidRawEvent(unsigned int uEvIdx){ return (uEvIdx < KVI_KVS_NUM_RAW_EVENTS); };
+
+ bool addAppHandler(unsigned int uEvIdx,KviKvsEventHandler * h);
+ bool addRawHandler(unsigned int uRawIdx,KviKvsEventHandler * h);
+
+ bool removeScriptAppHandler(unsigned int uEvIdx,const QString &szName);
+ bool removeScriptRawHandler(unsigned int uEvIdx,const QString &szName);
+
+ bool enableScriptAppHandler(unsigned int uEvIdx,const QString &szName,bool bEnable);
+ bool enableScriptRawHandler(unsigned int uEvIdx,const QString &szName,bool bEnable);
+
+ bool removeModuleAppHandler(unsigned int uEvIdx,KviKvsModuleInterface *i);
+ bool removeModuleRawHandler(unsigned int uRawIdx,KviKvsModuleInterface *i);
+
+ void removeAllModuleAppHandlers(KviKvsModuleInterface *i);
+ void removeAllModuleRawHandlers(KviKvsModuleInterface *i);
+
+ void removeAllModuleHandlers(KviKvsModuleInterface * i);
+
+ KviKvsScriptEventHandler * findScriptRawHandler(unsigned int uEvIdx,const QString &szName);
+ KviKvsScriptEventHandler * findScriptAppHandler(unsigned int uEvIdx,const QString &szName);
+
+ // returns true if further processing should be stopped
+ // none of these functions takes params ownership, so be sure to delete them !
+ bool triggerHandlers(KviPointerList<KviKvsEventHandler> * pHandlers,KviWindow *pWnd,KviKvsVariantList *pParams);
+ bool trigger(unsigned int uEvIdx,KviWindow * pWnd,KviKvsVariantList * pParams)
+ { return triggerHandlers(m_appEventTable[uEvIdx].handlers(),pWnd,pParams); };
+ bool triggerRaw(unsigned int uEvIdx,KviWindow *pWnd,KviKvsVariantList * pParams)
+ { return triggerHandlers(m_rawEventTable[uEvIdx],pWnd,pParams); };
+
+ // this is the only that takes parameter ownership and deletes them
+ bool triggerDeleteParams(unsigned int uEvIdx,KviWindow * pWnd,KviKvsVariantList * pParams)
+ {
+ bool bRet = triggerHandlers(m_appEventTable[uEvIdx].handlers(),pWnd,pParams);
+ delete pParams;
+ return bRet;
+ };
+
+ void removeAllScriptAppHandlers();
+ void removeAllScriptRawHandlers();
+
+ void clearAppEvents();
+ void clearRawEvents();
+ void clear();
+
+ void loadAppEvents(const QString &szFileName);
+ void saveAppEvents(const QString &szFileName);
+ void loadRawEvents(const QString &szFileName);
+ void saveRawEvents(const QString &szFileName);
+};
+
+
+
+#endif //!_KVI_KVS_EVENTMANAGER_H_
diff --git a/src/kvirc/kvs/kvi_kvs_eventtable.cpp b/src/kvirc/kvs/kvi_kvs_eventtable.cpp
new file mode 100644
index 00000000..4b8c8c98
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_eventtable.cpp
@@ -0,0 +1,3147 @@
+//=============================================================================
+//
+// File : kvi_kvs_eventtable.cpp
+// Created on Mon 23 Feb 2004 03:23:18 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_event.h"
+#include "kvi_kvs_eventtable.h"
+#include "kvi_kvs_eventmanager.h"
+
+#define EVENT(_name,_parm) KviKvsEvent(_name,_parm)
+
+KviKvsEvent KviKvsEventManager::m_appEventTable[KVI_NUM_SCRIPT_EVENTS]=
+{
+ /*
+ @doc: onkvircstartup
+ @type:
+ event
+ @title:
+ OnKVIrcStartup
+ @short:
+ Triggered on KVIrc startup
+ @parameters:
+ None
+ @window:
+ Console of the first IRC context
+ @description:
+ This event is triggered on KVIrc startup.
+ It is bound to the console of the first created IRC context.
+ This is a little tricky, since this event is triggered
+ before the related [event:onirccontextcreated]OnIRCContextCreated[/event] event.
+ This is to make OnApplicationStartup be the absolutely first
+ event triggered at all.
+ This event is a good place to load your script configuration
+ and eventually initialize your variables.
+ @seealso:
+ [event:onkvircshutdown]OnKVIrcShutdown[/event]
+ */
+ EVENT("OnKVIrcStartup",""),
+ /*
+ @doc: onkvircshutdown
+ @type:
+ event
+ @title:
+ OnKVIrcShutdown
+ @short:
+ Triggered on KVIrc shutdown
+ @parameters:
+ None
+ @window:
+ Console of the last IRC context
+ @description:
+ This event is triggered on KVIrc shutdown.
+ It is bound to the console of the last existing IRC context.
+ This is a little tricky, since this event is triggered
+ immediately after the on [event:onirccontextdestroyed]OnIRCContextDestroyed[/event] event,
+ so in theory the console should be already destroyed.
+ This is to make OnApplicationShutdown be the absolutely last event
+ triggered at all.
+ This event is a good place to save your script configuration.
+ @seealso:
+ [event:onkvircstartup]OnKVIrcStartup[/event]
+ */
+ EVENT("OnKVIrcShutdown",""),
+ /*
+ @doc: onirccontextcreated
+ @type:
+ event
+ @title:
+ OnIRCContextCreated
+ @short:
+ Triggered when a new IRC context is created
+ @parameters:
+ None
+ @window:
+ Console of the created IRC context
+ @description:
+ This event is triggered when a new IRC context is created.
+ It is bound to the console of the related IRC context,
+ that is the first window that is created.
+ @seealso:
+ [event:onirccontextdestroyed]OnIRCContextDestroyed[/event]
+ */
+ EVENT("OnIRCContextCreated",""),
+ /*
+ @doc: onirccontextdestroyed
+ @type:
+ event
+ @title:
+ OnIRCContextDestroyed
+ @short:
+ Triggered when an IRC context is destroyed
+ @parameters:
+ None
+ @window:
+ Console of the destroyed IRC context
+ @description:
+ This event is triggered when an IRC context is being destroyed.
+ It is bound to the console of the related IRC context,
+ that is the last window of the context that is destroyed.
+ @seealso:
+ [event:onirccontextcreated]OnIRCContextCreated[/event]
+ */
+ EVENT("OnIRCContextDestroyed",""),
+ /*
+ @doc: onircconnectionestablished
+ @type:
+ event
+ @title:
+ OnIRCConnectionEstablished
+ @short:
+ Triggered when a new IRC connection has been established
+ @parameters:
+ None
+ @window:
+ Console of the related IRC context
+ @description:
+ This event is triggered immediately after an IRC connection
+ has been established. No data has been sent to the server yet
+ and you have not logged in: it is not a good idea
+ attempting to send data to the server (READ: [b]This is NOT
+ a good place for joining channels[/b]).
+ Your nickname is still "undefined" too.
+ If you're looking for the appropriate moment for sending
+ data to the server look at the [event:onirc]OnIRC[/event] event.
+ This event is a good place for initializing connection related
+ variables. By calling [cmd]halt[/cmd] in this event you will stop the
+ "Connection established" output.
+ @seealso:
+ [event:onircconnectionterminated]OnIRCConnectionTerminated[/event]
+ */
+ EVENT("OnIRCConnectionEstablished",""),
+ /*
+ @doc: onircconnectionterminated
+ @type:
+ event
+ @title:
+ OnIRCConnectionTerminated
+ @short:
+ Triggered when an IRC connection has been terminated
+ @parameters:
+ None
+ @window:
+ Console of the related IRC context
+ @description:
+ This event is triggered immediately after an IRC connection
+ has been terminated. The socket is already closed, so you
+ can't send data to the server. You can still read
+ the connection parameters like the server name or
+ network name. By calling [cmd]halt[/cmd] in this
+ event you will stop the "Connection terminated..." output.
+ @seealso:
+ [event:onircconnectionestablished]OnIRCConnectionEstablished[/event]
+ */
+ EVENT("OnIRCConnectionTerminated",""),
+ /*
+ @doc: onirc
+ @type:
+ event
+ @title:
+ OnIRC
+ @short:
+ Triggered when the login operations are terminated
+ @parameters:
+ None
+ @window:
+ Console of the related IRC context
+ @description:
+ This event is triggered immediately after the login
+ operations have been terminated. From now on you are
+ "completely on IRC": your nickname has been defined
+ and the server is ready to accept commands from you.
+ This is a good place to join the "preferred channels".
+ By calling [cmd]halt[/cmd] in this event you will
+ stop the "Login operations complete..." output.
+ @seealso:
+ [event:onircconnectionestablished]OnIRCConnectionEstablished[/event]
+ [event:onircconnectionterminated]OnIRCConnectionTerminated[/event]
+ */
+ EVENT("OnIRC",""),
+ /*
+ @doc: onchannelnickpopuprequest
+ @type:
+ event
+ @title:
+ OnChannelNickPopupRequest
+ @short:
+ Allows customization of the nick-on-channel context popup
+ @parameters:
+ $0 = nick list
+ @window:
+ Channel window
+ @description:
+ This event is triggered when the user right-clicks in the channel user list
+ or on a nickname link in the channel text view.[br]
+ The first parameter ($0) contains a comma separated list of selected nicknames (if it is an user list click)
+ or a single nickname (if it is a link).[br]
+ In both cases all the nicknames are currently on the channel.[br]
+ You should popup a popup-menu with a set of possible channel-related actions,
+ like op/deop , voice/devoice , whois etc...
+ @seealso:
+ [event:onchannelnickdefaultactionrequest]OnChannelNickDefaultActionRequest[/event]
+ */
+ EVENT("OnChannelNickPopupRequest","$0 = nick list"),
+ /*
+ @doc: onchannelnickdefaultactionrequest
+ @type:
+ event
+ @title:
+ OnChannelNickDefaultActionRequest
+ @short:
+ Allows customization of the double click on nicknames
+ @parameters:
+ $0 = nick list
+ @window:
+ Channel window
+ @description:
+ @seealso:
+ [event:onchannelnickpopuprequest]OnChannelNickPopupRequest[/event]
+ */
+ EVENT("OnChannelNickDefaultActionRequest","$0 = nick list"),
+ /*
+ @doc: onframewindowcreated
+ @type:
+ event
+ @title:
+ OnFrameWindowCreated
+ @short:
+ Triggered when a new frame window is opened
+ @parameters:
+ None
+ @window:
+ First console in the frame window
+ @description:
+ This event is triggered in the first console of a new frame window.
+ A frame window is the toplevel window that contains the consoles
+ and the other MDI children windows.
+ @seealso:
+ [event:onframewindowdestroyed]OnFrameWindowDestroyed[/event]
+ */
+ EVENT("OnFrameWindowCreated",""),
+ /*
+ @doc: onframewindowdestroyed
+ @type:
+ event
+ @title:
+ OnFrameWindowDestroyed
+ @short:
+ Triggered when a frame window is being destroyed
+ @parameters:
+ None
+ @window:
+ Last console in the frame window
+ @description:
+ This event is triggered in the last console of a frame window that is
+ being destroyed. In fact the frame window is not destroyed yet, but it
+ is going to: there would be no way to trigger this event after the
+ last frame window destruction.
+ @seealso:
+ [event:onframewindowcreated]OnFrameWindowCreated[/event]
+ */
+ EVENT("OnFrameWindowDestroyed",""),
+ /*
+ @doc: onchannelpopuprequest
+ @type:
+ event
+ @title:
+ OnChannelPopupRequest
+ @short:
+ Triggered when the channel text view is right-clicked
+ @parameters:
+ None
+ @window:
+ Channel window
+ @description:
+ This event is triggered when the user clicks the channel
+ text view with the right mouse button. It is a good place
+ to activate a [cmd]popup[/cmd] menu :)
+ @seealso:
+ [event:ondccchatpopuprequest]OnDCCChatPopupRequest[/event],
+ [event:onconsolepopuprequest]OnConsolePopupRequest[/event],
+ [event:onquerypopuprequest]OnQueryPopupRequest[/event]
+ */
+ EVENT("OnChannelPopupRequest",""),
+ /*
+ @doc: onconsolepopuprequest
+ @type:
+ event
+ @title:
+ OnConsolePopupRequest
+ @short:
+ Triggered when the console text view is right-clicked
+ @parameters:
+ None
+ @window:
+ Console window
+ @description:
+ This event is triggered when the user clicks the console
+ text view with the right mouse button. It is a good place
+ to activate a [cmd]popup[/cmd] menu :)
+ @seealso:
+ [event:ondccchatpopuprequest]OnDCCChatPopupRequest[/event],
+ [event:onchannelpopuprequest]OnChannelPopupRequest[/event],
+ [event:onquerypopuprequest]OnQueryPopupRequest[/event]
+ */
+ EVENT("OnConsolePopupRequest",""),
+ /*
+ @doc: onquerypopuprequest
+ @type:
+ event
+ @title:
+ OnQueryPopupRequest
+ @short:
+ Triggered when the query text view is right-clicked
+ @parameters:
+ None
+ @window:
+ Query
+ @description:
+ This event is triggered when the user clicks the query
+ text view with the right mouse button. It is a good place
+ to activate a [cmd]popup[/cmd] menu :)
+ @seealso:
+ [event:ondccchatpopuprequest]OnDCCChatPopupRequest[/event],
+ [event:onconsolepopuprequest]OnConsolePopupRequest[/event],
+ [event:onchannelpopuprequest]OnChannelPopupRequest[/event],
+ */
+ EVENT("OnQueryPopupRequest",""),
+ /*
+ @doc: onchannelsync
+ @type:
+ event
+ @title:
+ OnChannelSync
+ @short:
+ Triggered when all the channel informations have been received
+ @parameters:
+ $0 = channel sync time in milliseconds
+ @window:
+ Channel
+ @description:
+ This event is triggered after you have joined a channel
+ and all the informations have been received.[br]
+ This includes the channel users list, the ban list,
+ the channel mode, the topic and eventually
+ the invite and ban exception lists.[br]
+ Calling halt in this even stops the "channel synchronized" output.[br]
+ (the output will be halted anyway if [fnc]$option[/fnc](boolShowChannelSyncTime) evaluates to false)
+ @seealso:
+ [event:ondccchatpopuprequest]OnDCCChatPopupRequest[/event],
+ [event:onconsolepopuprequest]OnConsolePopupRequest[/event],
+ [event:onchannelpopuprequest]OnChannelPopupRequest[/event]
+ */
+ EVENT("OnChannelSync","$0 = Channel sync time in milliseconds"),
+ /*
+ @doc: onurl
+ @type:
+ event
+ @title:
+ OnURL
+ @short:
+ Triggered when an URL appears in one of the output windows
+ @parameters:
+ $0 = URL
+ @window:
+ The window that the URL appeared in
+ @description:
+ This event is triggered every time that an URL is going to appear
+ in a KVIrc window output widget. You cannot stop it or modify it.
+ This event is good for implementing an URL catcher.[br]
+ WARNING: If you attempt to "echo $0" inside this event, you will cause an infinite loop.
+ */
+ EVENT("OnURL","$0 = URL"),
+ /*
+ @doc: onwindowpopuprequest
+ @type:
+ event
+ @title:
+ OnWindowPopupRequest
+ @short:
+ Triggered when the user middle-clicks in a text view (or right-clicks with the CTRL key pressed).
+ @parameters:
+ none
+ @window:
+ The window that the user has clicked in.
+ @description:
+ This event is here to allow easy customization of the window popup (it was builtin in KVIrc version prior to 3.0.0).[br]
+ Actually it is triggered when the user middle-clicks in a text view (or right-clicks with the CTRL key pressed).[br]
+ You should use it to popup your own version of the window popup that should interface the logging and window-behaviour functions.
+ */
+ EVENT("OnWindowPopupRequest",""),
+ /*
+ @doc: onhostlinkpopuprequest
+ @type:
+ event
+ @title:
+ OnHostLinkPopupRequest
+ @short:
+ Triggered when an user right clicks on a hostname link in the text view.
+ @parameters:
+ $0 = actual name
+ $1 - visible name
+ $2 - command name
+ @window:
+ The window that the user has clicked in.
+ @description:
+ This event is triggered when an user has right clicked on a hostname link in the text view.
+ The double click link action is builtin and it causes KVIrc to perform a DNS query on the hostname.
+ This is a good place to show a popup menu with some operations that can be done on the hostname like
+ "telnet", "traceroute", some special kind of DNS lookup (maybe an xterm with nslookup or sth).
+ */
+ EVENT("OnHostLinkPopupRequest","$0 = actual name\n$1 - visible name\n$2 - command name"),
+ /*
+ @doc: onurllinkpopuprequest
+ @type:
+ event
+ @title:
+ OnURLLinkPopupRequest
+ @short:
+ URL link popup customization
+ @parameters:
+ $0 = actual name
+ $1 - visible name
+ $2 - command name
+ @window:
+ The window that the user has clicked in
+ @description:
+ Actual name is equal to the command name if command name is not null.
+ Visible name is the link text (as it shown by user)
+ Command name is set if the visible name differs with the actual link target(probably contains mIRC colors,etc). It is equal to the actual target name.
+ This event is triggered when an user has right clicked on an URL link in
+ the text view. The double click link action is builtin and it causes KVIrc
+ to open the URL with a browser (konqueror in KDE compilation mode or netscape).[br]
+ This is a good place to show a [cmd]popup[/cmd] menu with some operations
+ that can be performed with the URL , like bookmarking in some way or opening
+ with a specific browser.[br]
+ */
+ EVENT("OnURLLinkPopupRequest","$0 = actual name\n$1 - visible name\n$2 - command name"),
+ /*
+ @doc: onserverlinkpopuprequest
+ @type:
+ event
+ @title:
+ OnServerLinkPopupRequest
+ @short:
+ Server link popup customization
+ @parameters:
+ $0 = actual name
+ $1 - visible name
+ $2 - command name
+ @window:
+ The window that the user has clicked in
+ @description:
+ Actual name is equal to the command name if command name is not null.
+ Visible name is the link text (as it shown by user)
+ Command name is set if the visible name differs with the actual link target(probably contains mIRC colors,etc). It is equal to the actual target name.
+ This event is triggered when an user has right clicked on an server name link in
+ the text view. The double click link action is builtin and it causes KVIrc
+ to query the MOTD of the server.[br]
+ This is a good place to show a [cmd]popup[/cmd] menu with some operations
+ that can be performed with the server name , like querying stats or links.[br]
+ Please note that the server name is generally NOT a hostname: some parts of
+ it are often hidden. The name of the server is generally valid only within
+ the IRC network that you are connected to.[br]
+ */
+ EVENT("OnServerLinkPopupRequest","$0 = actual name\n$1 - visible name\n$2 - command name"),
+ /*
+ @doc: onchannellinkpopuprequest
+ @type:
+ event
+ @title:
+ OnChannelLinkPopupRequest
+ @short:
+ Channel link popup customization
+ @parameters:
+ $0 = actual name
+ $1 - visible name
+ $2 - command name
+ @window:
+ The window that the user has clicked in
+ @description:
+ Actual name is equal to the command name if command name is not null.
+ Visible name is the link text (as it shown by user)
+ Command name is set if the visible name differs with the actual link target(probably contains mIRC colors,etc). It is equal to the actual target name.
+ This event is triggered when an user has right clicked on an channel link in
+ the text view. The double click link action is builtin and it causes KVIrc
+ to join the channel (unless the user is already on).[br]
+ This is a good place to show a [cmd]popup[/cmd] menu with some operations
+ that can be performed with the channel name like bookmarking, joining with a password,
+ performing a [cmd]who[/cmd] etc...
+ */
+ EVENT("OnChannelLinkPopupRequest","$0 = actual name\n$1 - visible name\n$2 - command name"),
+ /*
+ @doc: onnicklinkpopuprequest
+ @type:
+ event
+ @title:
+ OnNickLinkPopupRequest
+ @short:
+ Nick link popup customization
+ @parameters:
+ $0 = actual name
+ $1 - visible name
+ $2 - command name
+ @window:
+ The window that the user has clicked in
+ @description:
+ Actual name is equal to the command name if command name is not null.
+ Visible name is the link text (as it shown by user)
+ Command name is set if the visible name differs with the actual link target(probably contains mIRC colors,etc). It is equal to the actual target name.
+ This event is triggered when an user has right clicked on an "unknown" nickname link in
+ the text view.[br]
+ This is a good place to show a [cmd]popup[/cmd] menu with some operations
+ that can be performed with the nickname like querying , sending a file by dcc or opening a dcc.chat.
+ Please note that NOT ALL the nickname links will receive this event.[br]
+ The nickname links that appear in the text view of the channel that they are actually in
+ are handled by the [event:onchannelnickpopuprequest]OnChannelNickPopupRequest[/event] event.[br]
+ The nickname links that appear in the text view of the query in that they are a remote end
+ are handled by the [event:onquerynickpopuprequest]OnQueryNickPopupRequest[/event] event.[br]
+ */
+ EVENT("OnNickLinkPopupRequest","$0 = actual name\n$1 - visible name\n$2 - command name"),
+ /*
+ @doc: onquerynickpopuprequest
+ @type:
+ event
+ @title:
+ OnQueryNickPopupRequest
+ @short:
+ Query nicklist popup customization
+ @parameters:
+ $0 = actual name
+ $1 - visible name
+ $2 - command name
+ @window:
+ The window that the user has clicked in
+ @description:
+ Actual name is equal to the command name if command name is not null.
+ Visible name is the link text (as it shown by user)
+ Command name is set if the visible name differs with the actual link target(probably contains mIRC colors,etc). It is equal to the actual target name.
+ This event is triggered when an user has right clicked on a set of nicknames in
+ the query target list.[br]
+ This is a good place to show a [cmd]popup[/cmd] menu with some operations
+ that can be performed with the nickname like sending a file by dcc, opening a dcc.chat or
+ performing a whois.[br]
+ */
+ EVENT("OnQueryNickPopupRequest","$0 = actual name\n$1 - visible name\n$2 - command name"),
+ /*
+ @doc: onquerynickdefaultactionrequest
+ @type:
+ event
+ @title:
+ OnQueryNickDefaultActionRequest
+ @short:
+ Query double click customization
+ @parameters:
+ $0 = actual name
+ $1 - visible name
+ $2 - command name
+ @window:
+ The window that the user has clicked in
+ @description:
+ Actual name is equal to the command name if command name is not null.
+ Visible name is the link text (as it shown by user)
+ Command name is set if the visible name differs with the actual link target(probably contains mIRC colors,etc). It is equal to the actual target name.
+ This event is triggered when an user has double clicked on a nickname in
+ the query target list.[br]
+ You should use this event to do some significant action associated with the double click.[br]
+ A good example might be a [cmd]whois[/cmd] query or a [cmd]dcc.chat[/cmd]
+ */
+ EVENT("OnQueryNickDefaultActionRequest","$0 = actual name\n$1 - visible name\n$2 - command name"),
+ /*
+ @doc: onnicklinkdefaultactionrequest
+ @type:
+ event
+ @title:
+ OnNickLinkDefaultActionRequest
+ @short:
+ Nick link double click customization
+ @parameters:
+ $0 = actual name
+ $1 - visible name
+ $2 - command name
+ @window:
+ The window that the user has clicked in
+ @description:
+ Actual name is equal to the command name if command name is not null.
+ Visible name is the link text (as it shown by user)
+ Command name is set if the visible name differs with the actual link target(probably contains mIRC colors,etc). It is equal to the actual target name.
+ This event is triggered when an user has double clicked on a nickname link.[br]
+ You should use this event to perform some significant action associated with the double click.[br]
+ A good example might be a [cmd]whois[/cmd] or a [cmq]query[/cmd] call.[br]
+ Please note that NOT ALL nickname links will cause this event to be triggered: some nickname
+ links default actions are actually handled by the
+ [event:onquerynickdefaultactionrequest]OnQueryNickDefaultActionRequest[/event] and
+ [event:onchannelnickdefatulactionrequest]OnChannelNickDefaultActionRequest[/event] events.[br]
+ */
+ EVENT("OnNickLinkDefaultActionRequest","$0 = actual name\n$1 - visible name\n$2 - command name"),
+ /*
+ @doc: ontextviewdoublecliked
+ @type:
+ event
+ @title:
+ OnTextViewDoubleClicked
+ @short:
+ Text view link double click customization
+ @parameters:
+ $0 = actual name
+ $1 - visible name
+ $2 - command name
+ @window:
+ The window that the user has clicked in
+ @description:
+ Actual name is equal to the command name if command name is not null.
+ Visible name is the link text (as it shown by user).
+ Command name is set if the visible name differs with the actual link target (probably contains mIRC colors,etc). It is equal to the actual target name.
+ This event is triggered when an user has double clicked on a text view and has not hit any link.[br]
+ I have no idea what you can do in this event....maybe some sort of channel-central dialog? :)
+ */
+ EVENT("OnTextViewDoubleClicked",""),
+ /*
+ @doc: onnotifylistdefaultactionrequest
+ @type:
+ event
+ @title:
+ OnNotifyListDefaultActionRequest
+ @short:
+ Notify list double click customization
+ @parameters:
+ $0 = nickname
+ @window:
+ The window that the user has clicked in
+ @description:
+ This event is triggered when an user has double clicked on a nickname in
+ the notify list (console window).[br]
+ You should use this event to do some significant action associated with the double click.[br]
+ A good example might be a [cmd]whois[/cmd] query or a [cmd]dcc.chat[/cmd]
+ */
+ EVENT("OnNotifyListDefaultActionRequest","$0 = nickname"),
+ /*
+ @doc: onnotifylistpopuprequest
+ @type:
+ event
+ @title:
+ OnNotifyListPopupRequest
+ @short:
+ Notify list context popup customization
+ @parameters:
+ $0 = nickname list
+ @window:
+ The window that the user has clicked in
+ @description:
+ This event is triggered when an user has right clicked on a list of nicknames in
+ the notify list (console window).[br]
+ This is a good place to show a [cmd]popup[/cmd] with some actions that can be performed
+ on the nicknames like querying , performing a whois lookup or sth similar.[br]
+ */
+ EVENT("OnNotifyListPopupRequest","$0 = nickname list"),
+ /*
+ @doc: onping
+ @type:
+ event
+ @title:
+ OnPing
+ @short:
+ Server ping handler
+ @parameters:
+ $0 = server
+ $1 = ping message parameters
+ @window:
+ Console
+ @description:
+ Triggered when a PING message was received from a server.[br]
+ Calling 'halt' in this event will stop the informational message about 'ping->pong'.[br]
+ */
+ EVENT("OnPing","$0 = server\n$1 = message parameters"),
+ /*
+ @doc: onmejoin
+ @type:
+ event
+ @title:
+ OnMeJoin
+ @short:
+ Local user joining a channel
+ @parameters:
+ None
+ @window:
+ Channel
+ @description:
+ Triggered just after the local user has joined a channel.[br]
+ Sine this event is triggered in the chanel window,
+ you can get the channel name by using the [fnc]$target[/fnc] function.[br]
+ Calling 'halt' in this event will stop the join message output.[br]
+ @seealso:
+ [event:onjoin]OnJoin[/event]
+ */
+ EVENT("OnMeJoin",""),
+ /*
+ @doc: onjoin
+ @type:
+ event
+ @title:
+ OnJoin
+ @short:
+ Non-local user joining a channel
+ @parameters:
+ $0 = nickname
+ $1 = username
+ $2 = hostname
+ @window:
+ Channel
+ @description:
+ Triggered just after a non-local user has joined a channel.[br]
+ Sine this event is triggered in the chanel window,
+ you can get the channel name by using the [fnc]$target[/fnc] function.[br]
+ Calling 'halt' in this event will stop the join message output.[br]
+ @seealso:
+ [event:onmejoin]OnMeJoin[/event]
+ */
+ EVENT("OnJoin","$0 = nickname\n$1 = username\n$2 = hostname"),
+ /*
+ @doc: ontopic
+ @type:
+ event
+ @title:
+ OnTopic
+ @short:
+ Topic change on a channel
+ @parameters:
+ $0 = nickname
+ $1 = username
+ $2 = hostname
+ $3 = new topic string
+ @window:
+ Channel
+ @description:
+ Triggered when a TOPIC message is received for a given channel.[br]
+ The topic change has not been executed effectively in the current window
+ so you can still access the old topic by the channel functions.[br]
+ The new topic is passed as fourth parameter and will effectively
+ become the current topic just after this event handler has been executed.[br]
+ Sine this event is triggered in the chanel window,
+ you can get the channel name by using the [fnc]$target[/fnc] function.[br]
+ Calling 'halt' in this event will stop the topic message output.[br]
+ @seealso:
+ [event:onmejoin]OnMeJoin[/event]
+ */
+ EVENT("OnTopic","$0 = nickname\n$1 = username\n$2 = hostname\n$3 = topic"),
+ /*
+ @doc: onmepart
+ @type:
+ event
+ @title:
+ OnMePart
+ @short:
+ Local user is leaving a channel
+ @parameters:
+ $0 = part message
+ @window:
+ Channel
+ @description:
+ Triggered when the local user is leaving a channel.[br]
+ The PART message has already been processed by the server , so
+ the user is effectively no longer on the channel.
+ On the other side, it might be useful to access the channel data from
+ this event, thus the handler is called effectively just BEFORE the
+ user effectively leaves the channel (and thus BEFORE the channel window gets
+ destroyed).[br]
+ Sine this event is triggered in the chanel window,
+ you can get the channel name by using the [fnc]$target[/fnc] function.[br]
+ Calling 'halt' in this event will stop the part message output.[br]
+ @seealso:
+ [event:onmejoin]OnMeJoin[/event], [event:OnJoin]OnJoin[/event],
+ [event:onpart]OnPart[/event]
+ */
+ EVENT("OnMePart","$0 = part message"),
+ /*
+ @doc: onpart
+ @type:
+ event
+ @title:
+ OnPart
+ @short:
+ Non-local user is leaving a channel
+ @parameters:
+ $0 = nickname
+ $1 = username
+ $2 = hostname
+ $3 = part message
+ @window:
+ Channel
+ @description:
+ Triggered when a NON-local user is leaving a channel.[br]
+ The PART message has already been processed by the server , so
+ the user is effectively no longer on the channel.
+ On the other side, it might be useful to access the user-related channel data from
+ this event, thus the handler is called effectively just BEFORE the
+ user effectively leaves the channel (and thus BEFORE the user-related channel data gets
+ destroyed).[br]
+ Since this event is triggered in the chanel window,
+ you can get the channel name by using the [fnc]$target[/fnc] function.[br]
+ Calling 'halt' in this event will stop the part message output.[br]
+ @seealso:
+ [event:onmejoin]OnMeJoin[/event], [event:OnJoin]OnJoin[/event],
+ [event:onmepart]OnMePart[/event]
+ */
+ EVENT("OnPart","$0 = nickname\n$1 = username\n$2 = host\n$3 = part message"),
+ /*
+ @doc: onquit
+ @type:
+ event
+ @title:
+ OnQuit
+ @short:
+ An user is leaving a channel
+ @parameters:
+ $0 = nickname
+ $1 = username
+ $2 = hostname
+ $3 = quit message
+ $4 = channels
+ @window:
+ Console
+ @description:
+ Triggered when an user is quitting IRC.[br]
+ The QUIT message has already been processed by the server , so
+ the user is effectively no longer on IRC.
+ On the other side, it might be useful to access the user-related data from
+ this event, thus the handler is called effectively just BEFORE the
+ user is effectively removed from the IRC user list (and thus from the channels and query windows).[br]
+ The fifth parameter ($4) contains the list of channels on that the user was
+ just before quitting.
+ Calling 'halt' in this event will stop the quit message output (in ALL the windows!).[br]
+ @seealso:
+ [event:onpart]OnPart[/event],
+ [event:onmepart]OnMePart[/event]
+ @examples:
+ [example]
+ foreach(%cname,$4)echo -r=$channel(%cname) User $0 is quitting...
+ [/example]
+ */
+ EVENT("OnQuit","$0 = nickname\n$1 = username\n$2 = host\n$3 = part message\n$4 = channels"),
+ /*
+ @doc: onusermode
+ @type:
+ event
+ @title:
+ OnUserMode
+ @short:
+ The local user has changed mode
+ @parameters:
+ $0 = mode flags
+ @window:
+ Console
+ @description:
+ Triggered when the local user has changed his user mode.[br]
+ The first parameter is the changed mode flag with a leading '+' or '-' sign:
+ if the mode was removed it will be something like "-x" , otherwise something like "+x".[br]
+ Calling 'halt' in this event will stop the "mode" message output.[br]
+ */
+ EVENT("OnUserModeChanged","$0 = mode flags"),
+ /*
+ @doc: onmekick
+ @type:
+ event
+ @title:
+ OnMeKick
+ @short:
+ Local user is being kicked from a channel
+ @parameters:
+ $0 = source nickname
+ $1 = source username
+ $2 = source hostname
+ $3 = kick reason
+ @window:
+ Channel
+ @description:
+ Triggered when the local user has been kicked from a channel.[br]
+ The KICK message has already been processed by the server , so
+ the user is effectively no longer on the channel.
+ On the other side, it might be useful to access the user-related channel data from
+ this event, thus the handler is called effectively just BEFORE the
+ user is effectively removed from the channel internal structures
+ (and thus BEFORE the channel data itself gets destroyed).[br]
+ Sine this event is triggered in the chanel window,
+ you can get the channel name by using the [fnc]$target[/fnc] function.[br]
+ Calling 'halt' in this event will stop the kick message output.[br]
+ @seealso:
+ [event:onkick]OnKick[/event]
+ */
+ EVENT("OnMeKick","$0 = source nick\n$1 = source username\n$2 = source hostname\n$3 = reason"),
+ /*
+ @doc: onkick
+ @type:
+ event
+ @title:
+ OnKick
+ @short:
+ Non-local user is being kicked from a channel
+ @parameters:
+ $0 = source nickname
+ $1 = source username
+ $2 = source hostname
+ $3 = kicked nickname
+ $4 = kick reason
+ @window:
+ Channel
+ @description:
+ Triggered when a non-local user is being kicked from a channel.[br]
+ The KICK message has already been processed by the server , so
+ the user is effectively no longer on the channel.
+ On the other side, it might be useful to access the user-related channel data from
+ this event, thus the handler is called effectively just BEFORE the
+ user is effectively removed from the channel internal structures.[br]
+ Sine this event is triggered in the chanel window,
+ you can get the channel name by using the [fnc]$target[/fnc] function.[br]
+ Calling 'halt' in this event will stop the kick message output.[br]
+ @seealso:
+ [event:onmekick]OnMeKick[/event]
+ */
+ EVENT("OnKick","$0 = source nick\n$1 = source username\n$2 = source hostname\n$3 = kicked nick\n$4 = reason"),
+ /*
+ @doc: onmeaway
+ @type:
+ event
+ @title:
+ OnMeAway
+ @short:
+ Local user sets the AWAY status
+ @parameters:
+ $0 = server message trailing
+ @window:
+ Console
+ @description:
+ Triggered when the local user enters the AWAY state.
+ Calling 'halt' in this event disables the server "You have been marked as being away" message.[br]
+ @seealso:
+ [event:onmeback]OnMeBack[/event]
+ */
+ EVENT("OnMeAway","$0- = server message trailing"),
+ /*
+ @doc: onmeback
+ @type:
+ event
+ @title:
+ OnMeBack
+ @short:
+ Local user cancels the AWAY status
+ @parameters:
+ $0 = away start time
+ $1- = server message trailing
+ @window:
+ Console
+ @description:
+ Triggered when the local user leaves the AWAY state.[br]
+ The $0 parameter contains the [b]unix time[/b] of the away status start.[br]
+ You can obtain the current [b]unix time[/b] from the function [fnc]$unixtime[/fnc].[br]
+ Calling 'halt' in this event disables the server "You are no longer marked as being away" message.[br]
+ @seealso:
+ [event:onmeaway]OnMeAway[/event]
+ */
+ EVENT("OnMeBack","$0 = away start time\n$1- = server message trailing"),
+ /*
+ @doc: onchannelwindowcreated
+ @type:
+ event
+ @title:
+ OnChannelWindowCreated
+ @short:
+ A channel window has just been opened
+ @parameters:
+ none
+ @window:
+ Channel window
+ @description:
+ Triggered when a channel window has just been created
+ Note that the channel is still empty: no users have joined it.
+ @seealso:
+ [event:onquerywindowcreated]OnQueryWindowCreated[/event]
+ */
+ EVENT("OnChannelWindowCreated",""),
+ /*
+ @doc: onquerywindowcreated
+ @type:
+ event
+ @title:
+ OnQueryWindowCreated
+ @short:
+ A query window has just been opened
+ @parameters:
+ none
+ @window:
+ Query window
+ @description:
+ Triggered when a query window has just been created
+ Note that the query is still empty: it has no targets.
+ If you want to trigger some events in response to a query
+ creation by some remote user then you probably need
+ [event:onquerywindowrequest]OnQueryWindowRequest[/event] or
+ [event:onquerytargetadded]OnQueryTargetAdded[/event].
+ @seealso:
+ [event:onchannelwindowcreated]OnChannelWindowCreated[/event]
+ [event:onquerywindowrequest]OnQueryWindowRequest[/event]
+ [event:onquerytargetadded]OnQueryTargetAdded[/event]
+ */
+ EVENT("OnQueryWindowCreated",""),
+ /*
+ @doc: onban
+ @type:
+ event
+ @title:
+ OnBan
+ @short:
+ Someone has set a +b flag on the channel
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source hostname
+ $3 = ban mask
+ @window:
+ Channel window
+ @description:
+ Triggered when someone sets a +b flag on the channel
+ @seealso:
+ [event:onunban]OnUnban[/event]
+ */
+ EVENT("OnBan","$0 = source nick\n$1 = source username\n$2 = source hostname\n$3 = ban mask"),
+ /*
+ @doc: onunban
+ @type:
+ event
+ @title:
+ OnUnban
+ @short:
+ Someone has set a -b flag on the channel
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source hostname
+ $3 = unban mask
+ @window:
+ Channel window
+ @description:
+ Triggered when someone sets a -b flag on the channel
+ @seealso:
+ [event:onban]OnBan[/event]
+ */
+ EVENT("OnUnBan","$0 = source nick\n$1 = source username\n$2 = source hostname\n$3 = ban mask"),
+ /*
+ @doc: onmeban
+ @type:
+ event
+ @title:
+ OnMeBan
+ @short:
+ Local user is being banned in a channel
+ @parameters:
+ $0 = source nickname
+ $1 = source username
+ $2 = source hostname
+ $3 = ban mask
+ @window:
+ Channel
+ @description:
+ Triggered when someone has set a +b flag that matches your mask (bans you) in the channel.[br]
+ @seealso:
+ [event:onmeunban]OnMeUnban[/event]
+ */
+ EVENT("OnMeBan","$0 = source nick\n$1 = source username\n$2 = source hostname\n$3 = ban mask"),
+ /*
+ @doc: onmeunban
+ @type:
+ event
+ @title:
+ OnMeUnban
+ @short:
+ Local user is being de-banned in a channel
+ @parameters:
+ $0 = source nickname
+ $1 = source username
+ $2 = source hostname
+ $3 = ban mask
+ @window:
+ Channel
+ @description:
+ Triggered when someone has set a -b flag that matches your mask (debans you) in the channel.[br]
+ @seealso:
+ [event:onmeban]OnMeBan[/event]
+ */
+EVENT("OnMeUnban","$0 = source nick\n$1 = source username\n$2 = source hostname\n$3 = ban mask"),
+ /*
+ @doc: onbanexception
+ @type:
+ event
+ @title:
+ OnBanException
+ @short:
+ Someone has set a +e flag on the channel
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source hostname
+ $3 = banexception mask
+ @window:
+ Channel window
+ @description:
+ Triggered when someone sets a +e (Ban Exception) flag on the channel
+ @seealso:
+ [event:onbanexceptionremove]OnBanExceptionRemove[/event]
+ */
+
+ EVENT("OnBanException","$0 = source nick\n$1 = source username\n$2 = source hostname\n$3 = ban exception mask"),
+ /*
+ @doc: onbanexceptionremove
+ @type:
+ event
+ @title:
+ OnBanExceptionRemove
+ @short:
+ Someone has set a -e flag on the channel
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source hostname
+ $3 = unban mask
+ @window:
+ Channel window
+ @description:
+ Triggered when someone sets a -e (Removed a Ban Exception) flag on the channel
+ @seealso:
+ [event:onbanexception]OnBanException[/event]
+ */
+ EVENT("OnBanExceptionRemove","$0 = source nick\n$1 = source username\n$2 = source hostname\n$3 = ban exception mask"),
+ /*
+ @doc: onmebanexception
+ @type:
+ event
+ @title:
+ OnMeBanException
+ @short:
+ Someone has set a +e flag on the local user
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source hostname
+ $3 = mask
+ @window:
+ Channel window
+ @description:
+ Triggered when someone sets a +e (puts a Ban Exception) flag on the local user in the active
+channel
+ @seealso:
+ [event:onmebanexceptionremove]OnMeBanExceptionRemove[/event]
+ */
+ EVENT("OnMeBanException","$0 = source nick\n$1 = source username\n$2 = source hostname\n$3 = mask"),
+ /*
+ @doc: onmebanexceptionremove
+ @type:
+ event
+ @title:
+ OnMeBanExceptionRemove
+ @short:
+ Someone has set a -e flag on the local user
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source hostname
+ $3 = mask
+ @window:
+ Channel window
+ @description:
+ Triggered when someone sets a -e (removes a Ban Exception) flag on the local user in the active channel
+ @seealso:
+ [event:onmebanexception]OnMeBanException[/event]
+ */
+ EVENT("OnMeBanExceptionRemove","$0 = source nick\n$1 = source username\n$2 = source hostname\n$3 = mask"),
+ /*
+ @doc: onop
+ @type:
+ event
+ @title:
+ OnOp
+ @short:
+ Someone has given a user the +o flag
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source host
+ $3 = opped nick
+ @window:
+ Channels window
+ @description:
+ Triggered when someone sets a +o (has made Op) flag on a user of the active channel.
+ @seealso:
+ [event:ondeop]OnDeOp[/event]
+ */
+ EVENT("OnOp","$0 = source nick\n$1 = source username\n$2 = source hostname\n$3 = opped nick"),
+ /*
+ @doc: ondeop
+ @type:
+ event
+ @title:
+ OnDeOp
+ @short:
+ Someone has given a user the -o flag
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source host
+ $3 = deopped nick
+ @window:
+ Channels window
+ @description:
+ Triggered when someone sets a -o (DeOp) flag on a user in the active channel.
+ @seealso:
+ [event:onop]OnOp[/event]
+ */
+ EVENT("OnDeOp","$0 = source nick\n$1 = source username\n$2 = source hostname\n$3 = deopped nick"),
+ /*
+ @doc: onmeop
+ @type:
+ event
+ @title:
+ OnMeOp
+ @short:
+ Someone has given the +o flag to the local user
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source host
+ @window:
+ Channels window
+ @description:
+ Triggered when someone sets a +o (has made Op) flag on the local user in the active channel.
+ @seealso:
+ [event:onmedeop]OnMeDeOp[/event]
+ */
+ EVENT("OnMeOp","$0 = source nick\n$1 = source username\n$2 = source hostname"),
+ /*
+ @doc: onmedeop
+ @type:
+ event
+ @title:
+ OnMeDeOp
+ @short:
+ Someone has given the -o flag to the local user
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source host
+ @window:
+ Channels window
+ @description:
+ Triggered when someone sets a -o (has deoped) flag on the local user in the active channel.
+ @seealso:
+ [event:onmeop]OnMeOp[/event]
+ */
+ EVENT("OnMeDeOp","$0 = source nick\n$1 = source username\n$2 = source hostname"),
+ /*
+ @doc: onlimitset
+ @type:
+ event
+ @title:
+ OnLimitSet
+ @short:
+ The channel users limit has been set
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source host
+ $3 = limit
+ @window:
+ Channels window
+ @description:
+ Triggered when someone change or sets the active channel user limit (+l)
+ @seealso:
+ [event:onlimitunset]OnLimitUnset[/event]
+ */
+ EVENT("OnLimitSet","$0 = source nick\n$1 = source username\n$2 = source hostname\n$3 = limit"),
+ /*
+ @doc: onlimitunset
+ @type:
+ event
+ @title:
+ OnLimitUnSet
+ @short:
+ The channel users limit has been unset
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source host
+ @window:
+ Channels window
+ @description:
+ Triggered when someone unsets the active channel user limit (-l)
+ @seealso:
+ [event:onlimitunset]OnLimitUnset[/event]
+ */
+ EVENT("OnLimitUnset","$0 = source nick\n$1 = source username\n$2 = source hostname"),
+ /*
+ @doc: onkeyset
+ @type:
+ event
+ @title:
+ OnKeySet
+ @short:
+ The channel users key has been set
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source host
+ $3 = key
+ @window:
+ Channels window
+ @description:
+ Triggered when someone change or sets the active channel access key (+k)
+ @seealso:
+ [event:onkeyunset]OnKeyUnset[/event]
+ */
+ EVENT("OnKeySet","$0 = source nick\n$1 = source username\n$2 = source hostname\n$3 = key"),
+ /*
+ @doc: onkeyunset
+ @type:
+ event
+ @title:
+ OnKeyUnset
+ @short:
+ The channel users key has been unset
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source host
+ @window:
+ Channels window
+ @description:
+ Triggered when someone unsets the active channel access key (-k)
+ @seealso:
+ [event:onkeyunset]OnKeyUnset[/event]
+ */
+ EVENT("OnKeyUnset","$0 = source nick\n$1 = source username\n$2 = source hostname"),
+ /*
+ @doc: oninvite
+ @type:
+ event
+ @title:
+ OnInvite
+ @short:
+ The local user has received an invitation
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source host
+ $3 = channel
+ @window:
+ Active window/console
+ @description:
+ Triggered when someone invites the local user to join a channel
+ */
+ EVENT("OnInvite","$0 = source nick\n$1 = source username\n$2 = source hostname\n$3 = channel"),
+ /*
+ @doc: onchannelmessage
+ @type:
+ event
+ @title:
+ OnChannelMessage
+ @short:
+ A message has been received from the channel
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source host
+ $3 = message
+ $4 = [target mode prefixes]
+ @window:
+ Channels window
+ @description:
+ Triggered when a channel message is received
+ $0!$1@$2 is the source of the message, $3 is the message text
+ and $4 are the eventual mode prefixes added to the target channel (i.e:
+ if the message is only for channel operators then you will get the string @ in $4).
+ @seealso:
+ [event:onquerymessage]OnQueryMessage[/event]
+ [event:ondccchatmessage]OnDCCChatMessage[/event]
+ */
+ EVENT("OnChannelMessage","$0 = source nick\n$1 = source username\n$2 = source hostname\n$3 = message\n$4 = target mode prefixes"),
+ /*
+ @doc: onquerymessage
+ @type:
+ event
+ @title:
+ OnQueryMessage
+ @short:
+ A message has been received from a query
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source host
+ $3 = message
+ @window:
+ Query or console window.
+ @description:
+ Triggered when a query message is received.[br]
+ If you [cmd]return[/cmd] [fnc]$false[/fnc] in this event, the message output will be stopped.[br]
+ This event is triggered in the query window associated to the source nick, or in
+ the IRC context console window if the query window has not been created for some reason.
+ Note that you can't stop the query window creation with this event: you must
+ use [event:onquerywindowrequest]OnQueryWindowRequest[/event] for that purpose.
+ Note also that you may not receive this event if the anti-spam option is in use and
+ KVIrc has detected that this might be a spam message. This is usually not an issue
+ but if you care about it then write to pragma at kvirc dot net asking to add a OnSpam event.
+ @seealso:
+ [event:onquerywindowrequest]OnQueryWindowRequest[/event]
+ [event:onquerywindowcreated]OnQueryWindowCreated[/event]
+ [event:onquerytargetadded]OnQueryTargetAdded[/event]
+ [event:onchannelmessage]OnChannelMessage[/event]
+ [event:ondccchatmessage]OnDCCChatMessage[/event]
+ */
+ EVENT("OnQueryMessage","$0 = source nick\n$1 = source username\n$2 = source hostname\n$3 = message"),
+ /*
+ @doc: onvoice
+ @type:
+ event
+ @title:
+ OnVoice
+ @short:
+ Someone has given a user the +v flag
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source host
+ $3 = voiced nick
+ @window:
+ Channels window
+ @description:
+ Triggered when someone sets a +v (voice) flag to someone in the active channel.
+ @seealso:
+ [event:ondevoice]OnDeVoice[/event]
+ */
+ EVENT("OnVoice","$0 = source nick\n$1 = source username\n$2 = source hostname\n$3 = voiced nick"),
+ /*
+ @doc: ondevoice
+ @type:
+ event
+ @title:
+ OnDeVoice
+ @short:
+ Someone has given a user the -v flag
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source host
+ $3 = devoiced nick
+ @window:
+ Channels window
+ @description:
+ Triggered when someone sets a -v (devoice) flag to someone in the active channel.
+ @seealso:
+ [event:ondevoice]OnDeVoice[/event]
+ */
+ EVENT("OnDeVoice","$0 = source nick\n$1 = source username\n$2 = source hostname\n$3 = voiced nick"),
+ /*
+ @doc: onmevoice
+ @type:
+ event
+ @title:
+ OnMeVoice
+ @short:
+ Someone has give the local user a +v flag
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source host
+ @window:
+ Channels window
+ @description:
+ Triggered when someone sets a +v (devoice) flag for the local user in the active channel.
+ @seealso:
+ [event:onmedevoice]OnMeDeVoice[/event]
+ */
+ EVENT("OnMeVoice","$0 = source nick\n$1 = source username\n$2 = source hostname"),
+ /*
+ @doc: onmedevoice
+ @type:
+ event
+ @title:
+ OnMeDeVoice
+ @short:
+ Someone has give the local user a -v flag
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source host
+ @window:
+ Channels window
+ @description:
+ Triggered when someone sets a -v (devoice) flag for the local user in the active channel.
+ @seealso:
+ [event:onmevoice]OnMeVoice[/event]
+ */
+ EVENT("OnMeDeVoice","$0 = source nick\n$1 = source username\n$2 = source hostname"),
+ /*
+ @doc: onnickchange
+ @type:
+ event
+ @title:
+ OnNickChange
+ @short:
+ Someone has changed his nickname
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source host
+ $3 = new nickname
+ @window:
+ Console window
+ @description:
+ Triggered when someone has changed his nickname.
+ The change has already been processed by the server, but not by the
+ local KVIrc database.
+ @seealso:
+ [event:onmenickchange]OnMeNickChange[/event]
+ */
+ EVENT("OnNickChange","$0 = source nick\n$1 = source username\n$2 = source hostname\n$3 = new nickname"),
+ /*
+ @doc: onmenickchange
+ @type:
+ event
+ @title:
+ OnMeNickChange
+ @short:
+ The local user has changed his nickname
+ @parameters:
+ $0 = old nick
+ $1 = new nickname
+ @window:
+ Console window
+ @description:
+ Triggered when the local user is going to change his nickname.
+ The change has already been processed by the server, but not by the
+ local KVIrc database.
+ @seealso:
+ [event:onnickchange]OnNickChange[/event]
+ */
+ EVENT("OnMeNickChange","$0 = old nick\n$1 = new nick"),
+ /*
+ @doc: onctcprequest
+ @type:
+ event
+ @title:
+ OnCTCPRequest
+ @short:
+ A CTCP request has been received
+ @parameters:
+ $0 = source nick
+ $1 = source user
+ $2 = source host
+ $3 = target
+ $4 = ctcp type
+ $5- = ctcp parameters
+ @window:
+ Console window
+ @description:
+ A CTCP request has been received.[br]
+ If you call [cmd]halt[/cmd] in this event, you will stop the further
+ processing of the CTCP (thus, you can disable some of the KVIrc features).
+ Be careful when using this.
+ @seealso:
+ [event:onctcpreply]OnCTCPReply[/event]
+ */
+ EVENT("OnCTCPRequest","$0 = source nick\n$1 = source user\n$2 = source host\n$3 = target\n$4 = ctcp type\n$5- = ctcp parameters"),
+ /*
+ @doc: onctcpreply
+ @type:
+ event
+ @title:
+ OnCTCPReply
+ @short:
+ A CTCP reply has been received
+ @parameters:
+ $0 = source nick
+ $1 = source user
+ $2 = source host
+ $3 = target
+ $4 = ctcp type
+ $5- = ctcp parameters
+ @window:
+ Console window
+ @description:
+ A CTCP reply has been received.[br]
+ If you call [cmd]halt[/cmd] in this event, you will stop the further
+ processing of the CTCP (thus, you can disable some of the KVIrc features).
+ Be careful when using this.
+ @seealso:
+ [event:onctcpreply]OnCTCPReply[/event]
+ */
+ EVENT("OnCTCPReply","$0 = source nick\n$1 = source user\n$2 = source host\n$3 = target\n$4 = ctcp type\n$5- = ctcp parameters"),
+ /*
+ @doc: onunhandledliteral
+ @type:
+ event
+ @title:
+ OnUnhandledLiteral
+ @short:
+ An unhandled literal server message has been received
+ @parameters:
+ $0 = source mask
+ $1 = message (literal)
+ $2- = parameters
+ @window:
+ Console window
+ @description:
+ An unhandled/unrecognized literal server message has been received.[br]
+ The KVIrc core code hasn't been able to recognize it nor handle it
+ in any way.[br]
+ If you call [cmd]halt[/cmd] you will stop the standard or warning message output.[br]
+ For server numerics there is no "unhandled" event, you should use the
+ raw numeric events to handle them.[br]
+ @seealso:
+ */
+ EVENT("OnUnhandledLiteral","$0 = source mask\n$1 = message\n$2- parameters"),
+ /*
+ @doc: onmehalfop
+ @type:
+ event
+ @title:
+ OnMeHalfOp
+ @short:
+ Someone has given the local user the +h flag
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source host
+ @window:
+ Channels window
+ @description:
+ Triggered when someone sets a +h (halfop) flag for the local user in the active channel.
+ @seealso:
+ [event:onmedehalfop]OnMeDeHalfOp[/event]
+ */
+ EVENT("OnMeHalfOp","$0 = source nick\n$1 = source username\n$2 = source hostname"),
+ /*
+ @doc: onmedehalfop
+ @type:
+ event
+ @title:
+ OnMeDeHalfOp
+ @short:
+ Someone has given the local user the -h flag
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source host
+ @window:
+ Channels window
+ @description:
+ Triggered when someone sets a -h (dehalfop) flag for the local user in the active channel.
+ @seealso:
+ [event:onmehalfop]OnMeHalfOp[/event]
+ */
+ EVENT("OnMeDeHalfOp","$0 = source nick\n$1 = source username\n$2 = source hostname"),
+ /*
+ @doc: onhalfop
+ @type:
+ event
+ @title:
+ OnHalfOp
+ @short:
+ Someone has given a user the +h flag
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source host
+ $3 = halfopped nick
+ @window:
+ Channels window
+ @description:
+ Triggered when someone sets a +h flag on a user of the active channel.
+ @seealso:
+ [event:ondehalfop]OnDeHalfOp[/event]
+ */
+ EVENT("OnHalfOp","$0 = source nick\n$1 = source username\n$2 = source hostname\n$3 = halfopped nick"),
+ /*
+ @doc: ondehalfop
+ @type:
+ event
+ @title:
+ OnDeHalfOp
+ @short:
+ Someone has given a user the -h flag
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source host
+ $3 = dehalfopped nick
+ @window:
+ Channels window
+ @description:
+ Triggered when someone sets a -h (dehalfop) flag on a user in the active channel.
+ @seealso:
+ [event:onhalfop]OnHalfOp[/event]
+ */
+ EVENT("OnDeHalfOp","$0 = source nick\n$1 = source username\n$2 = source hostname\n$3 = dehalfopped nick"),
+ /*
+ @doc: oninviteexception
+ @type:
+ event
+ @title:
+ OnInviteException
+ @short:
+ A +I mode has been set
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source host
+ $3 = target mask
+ @window:
+ Channels window
+ @description:
+ Someone has set mode +I on a channel
+ @seealso:
+ [event:oninviteexceptionremove]OnInviteExceptionRemove[/event]
+ */
+ EVENT("OnInviteException","$0 = source nick\n$1 = source username\n$2 = source hostname\n$3 = target mask"),
+ /*
+ @doc: oninviteexceptionremove
+ @type:
+ event
+ @title:
+ OnInviteExceptionRemove
+ @short:
+ Move -I has been set
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source host
+ $3 = target mask
+ @window:
+ Channels window
+ @description:
+ Someone has set mode -I on a channel
+ @seealso:
+ [event:oninviteexceptionremove]OnInviteExceptionRemove[/event]
+ */
+ EVENT("OnInviteExceptionRemove","$0 = source nick\n$1 = source username\n$2 = source hostname\n$3 = target mask"),
+ /*
+ @doc: onmeinviteexception
+ @type:
+ event
+ @title:
+ OnMeInviteException
+ @short:
+ A +I mode has been set
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source host
+ $3 = mask
+ @window:
+ Channels window
+ @description:
+ Someone has set mode +I on a channel with a target mask that matches
+ the local user mask
+ @seealso:
+ [event:onmeinviteexceptionremove]OnMeInviteExceptionRemove[/event]
+ */
+ EVENT("OnMeInviteException","$0 = source nick\n$1 = source username\n$2 = source hostname\n$3 = mask"),
+ /*
+ @doc: onmeinviteexceptionremove
+ @type:
+ event
+ @title:
+ OnMeInviteExceptionRemove
+ @short:
+ Move -I has been set
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source host
+ $3 = mask
+ @window:
+ Channels window
+ @description:
+ Someone has set mode -I on a channel with a target mask that matches
+ the local user mask
+ @seealso:
+ [event:onmeinviteexceptionremove]OnMeInviteExceptionRemove[/event]
+ */
+ EVENT("OnMeInviteExceptionRemove","$0 = source nick\n$1 = source username\n$2 = source hostname\n$3 = mask"),
+ /*
+ @doc: onaction
+ @type:
+ event
+ @title:
+ OnAction
+ @short:
+ Someone issued a CTCP ACTION
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source host
+ $3 = message target
+ $4 = action message text
+ @window:
+ Channels and query windows
+ @description:
+ This event is triggered when a remote user issues a CTCP ACTION.[br]
+ (The CTCP ACTION is usually triggered by the /me command).[br]
+ The parameters $0-$2 identify the source user.[br]
+ $3 identifies the message target and can be one of the following:[br]
+ - The local user nickname : this is a private CTCP ACTION and is triggered inside a query window.[br]
+ - A channel name : this is a channel CTCP ACTION and is triggered in the channel window.[br]
+ - Any other string : this is either a broadcast CTCP ACTION (sent by a privileged user
+ to a subset of clients) or a sign of the server brain damage :D In this
+ case the event is triggered in the console window.[br]
+ Calling [cmd]halt[/cmd] in this event stops the message output.[br]
+ */
+
+ EVENT("OnAction", \
+ "$0 = source nick\n" \
+ "$1 = source username\n" \
+ "$2 = source hostname\n" \
+ "$3 = message target\n" \
+ "$4 = action message text"),
+ /*
+ @doc: onctcpflood
+ @type:
+ event
+ @title:
+ OnCTCPFlood
+ @short:
+ Someone tried to flood you with CTCP requests
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source hostname
+ $3 = target
+ $4 = ctcp type
+ $5- = ctcp parameters
+ @window:
+ Console window
+ @description:
+ On IRC there is a kind of attack called 'CTCP Flood'. It consist of a lot of CTCP request in a short period of time, trying to made your client reply to them and made the server kick you. This event is triggered when one of such attacks is detected.
+ @seealso:
+ [event:onctcprequest]OnCTCPRequest[/event]
+ [event:onctcpreply]OnCTCPReply[/event]
+ */
+ EVENT("OnCTCPFlood", "$0 = source nick\n$1 = source username\n$2 = source hostname\n$3 = target\n$4 = ctcp type\n$5- = ctcp parameters"),
+ /*
+ @doc: onchannelnotice
+ @type:
+ event
+ @title:
+ OnChannelNotice
+ @short:
+ A NOTICE have been issued to a channel
+ @parameters:
+ $0 = source nick
+ $1 = message
+ $2 = target
+ @window:
+ Channel window
+ @description:
+ Someone has issued a NOTICE with a channel as his target
+ For normal channel notices $2 parameter will only a channel name.
+ For channel op or channel voice notices it will contain also the leading '@' or '+' flag.
+ Please note that this convention is different from the one used in [event:onchannelprivmsg]OnChannelPrivmsg[/event]:
+ the incompatibility is here for historical reasons: it is not a big deal so we're not fighting it :)
+ @seealso:
+ [event:onservernotice]OnServerNotice[/event]
+ */
+ EVENT("OnChannelNotice", "$0 = source nick\n$1 = message,\n$2 = target"),
+ /*
+ @doc: onservernotice
+ @type: event
+ @title:
+ OnServerNotice
+ @short:
+ A server NOTICE have been issued.
+ @parameters:
+ $0 = source nick
+ $1 = message
+ @window:
+ Console window
+ @description:
+ Someone has issued a server NOTICE.
+ @seealso:
+ [event:onchannelnotice]OnChannelNotice[/event]
+ */
+ EVENT("OnServerNotice", "$0 = source nick\n$1 = message"),
+ /*
+ @doc: ondccchatwindowcreated
+ @type: event
+ @title:
+ OnDCCChatWindowCreated
+ @short:
+ A dcc chat window has been just created
+ @parameters:
+ $0 = DCC session ID
+ @window:
+ DCC Chat
+ @description:
+ A DCC Chat window has been just created.
+ The [module:dcc]dcc[/module] module functions
+ can be used to retrieve the informations about the
+ window and the data transfer.
+ The DCC Chat connection attempt starts from here:
+ you can get [event:ondccchatterminated]OnDCCChatError[/event]
+ in any moment
+ @seealso:
+ [event:ondccchatterminated]OnDCCChatTerminated[/event]
+ */
+ EVENT("OnDCCChatWindowCreated", "$0 = DCC session ID"),
+ /*
+ @doc: ondccchatconnectioninprogress
+ @type:
+ event
+ @title:
+ OnDCCChatConnectionInProgress
+ @short:
+ A DCC Chat connection has just been started
+ @parameters:
+ $0 = DCC session ID
+ @window:
+ DCC Chat
+ @description:
+ A DCC Chat connection has just been started succesfully.
+ The [module:dcc]dcc[/module] module functions
+ can be used to retrieve the informations about the
+ window and the data transfer.
+ In case of a passive DCC Chat, the local ip and port
+ are known from the moment that this event triggers.
+ @seealso:
+ */
+ EVENT("OnDCCChatConnectionInProgress","$0 = DCC session ID"),
+ /*
+ @doc: ondccchatconnected
+ @type:
+ event
+ @title:
+ OnDCCChatConnected
+ @short:
+ A DCC Chat connection has been established
+ @parameters:
+ $0 = DCC session ID
+ @window:
+ DCC Chat
+ @description:
+ A DCC Chat connection has just been established.
+ The [module:dcc]dcc[/module] module functions
+ can be used to retrieve the informations about the
+ window and the data transfer.
+ @seealso:
+ */
+ EVENT("OnDCCChatConnected","$0 = DCC session ID"),
+ /*
+ @doc: ondccchatmessage
+ @type:
+ event
+ @title:
+ OnDCCChatMessage
+ @short:
+ A DCC Chat message has just been received
+ @parameters:
+ $0 = message text
+ $1 = DCC session ID
+ @window:
+ DCC Chat
+ @description:
+ A DCC Chat message has just been received.
+ The [module:dcc]dcc[/module] module functions
+ can be used to retrieve the informations about the
+ window and the data transfer.
+ @seealso:
+ */
+ EVENT("OnDCCChatMessage","$0 = text\n$1 = DCC session ID"),
+ /*
+ @doc: ondccchaterror
+ @type:
+ event
+ @title:
+ OnDCCChatError
+ @short:
+ A DCC Chat error has just been triggered
+ @parameters:
+ $0 = error message
+ $1 = DCC session ID
+ @window:
+ DCC Chat
+ @description:
+ A DCC Chat error has just been triggered
+ The [module:dcc]dcc[/module] module functions
+ can be used to retrieve the informations about the
+ window and the data transfer.
+ A DCC Chat can terminate because an error has
+ interrupted the connection or because
+ the local user has closed the window forcibly.
+ The remote end closing the connection is considered
+ an error.
+ @seealso:
+ */
+ EVENT("OnDCCChatError","$0 = error message,$1 = DCC session ID"),
+ /*
+ @doc: ondccchatdisconnected
+ @type:
+ event
+ @title:
+ OnDCCChatDisconnected
+ @short:
+ A DCC Chat has been just disconnected
+ @parameters:
+ $0 = DCC session ID
+ @window:
+ DCC Chat
+ @description:
+ A DCC Chat has just been disconnected for some reason.
+ The [module:dcc]dcc[/module] module functions
+ can be used to retrieve the informations about the
+ window and the data transfer.
+ @seealso:
+ */
+ EVENT("OnDCCChatDisconnected","$0 = DCC session ID"),
+ /*
+ @doc: ondccchatwindowclosing
+ @type:
+ event
+ @title:
+ OnDCCChatWindowClosing
+ @short:
+ A DCC Chat is going to be closed
+ @parameters:
+ $0 = DCC session ID
+ @window:
+ DCC Chat
+ @description:
+ A DCC Chat window is going to be closed.
+ The [module:dcc]dcc[/module] module functions
+ can be used to retrieve the informations about the
+ window and the data transfer.
+ @seealso:
+ */
+ EVENT("OnDCCChatWindowClosing","$0 = DCC session ID"),
+ /*
+ @doc: onaccelkeypressed
+ @type:
+ event
+ @title:
+ OnAccelKeyPressed
+ @short:
+ An accelerator key was pressed
+ @parameters:
+ $0 = keys
+ @window:
+ Active window
+ @description:
+ An accelerator key has been pressed by the user.[br]
+ The key sequence that the user has pressed is passed in $0 as a
+ human readable string.[br]
+ The keys that actually work with KVIrc are:[br]
+ F2 to F12, F1 to F12 with SHIFT key pressed, 0 to 9 with CTRL key pressed.[br]
+ This means that you can set up 33 "quick" aliases...that's really more than
+ an user can remember.[br]
+ If you need more keys , mail me , I'll see what I can do :)[br]
+ */
+ EVENT("OnAccelKeyPressed", "$0 = keys"),
+ /*
+ @doc: onhighlight
+ @type:
+ event
+ @title:
+ OnHighlight
+ @short:
+ A channel or query message is going to be highlighted
+ @parameters:
+ $0 = talker nick
+ $1 = target username
+ $2 = target hostname
+ $3 = message
+ $4 = highlight word
+ $5 = message type
+ $6 = is action
+ @window:
+ Channel or query window
+ @description:
+ A channel or query message is going to be highlighted.[br]
+ The message may be either a PRIVMSG, a NOTICE or a CTCP ACTION.[br]
+ The highlight may be either caused by a "highlight word" or by your own nickname
+ (if that option was specified).[br]
+ $5 contains the original color/icon set of the message that depends on
+ the type of the message itself.[br]
+ Since the CTCP ACTION messages generally have different format of output
+ then for your convenience $6 contains 1 if the message was caused by a
+ CTCP ACTION and 0 otherwise.[br]
+ If you call [cmd]halt[/cmd] in this event the message output will be completely disabled
+ (thus, KVIrc assumes that YOU have provided the necessary output and feedback to the user).[br]
+ A common error here is to call halt and re-echo the unmodified output; [b]this
+ can cause another OnHighlight event to be triggered and create an infinite loop![/b].
+ [cmd]echoprivmsg[/cmd] [b]-n[/b] is the command you probably want.
+ */
+ EVENT("OnHighlight", "$0 = source nick\n$1 = source username\n$2 = source hostname\n$3 = message\n$4 = highlight word"),
+ /*
+ @doc: onwindowactivated
+ @type:
+ event
+ @title:
+ OnWindowActivated
+ @short:
+ A window has just been activated
+ @parameters:
+ none
+ @window:
+ Any window
+ @description:
+ This event is triggered when a KVIrc MDI window gets activated.[br]
+ This might be a good place to update your toolbar button status (for example).[br]
+ */
+ EVENT("OnWindowActivated",""),
+ /*
+ @doc: onnotifyonline
+ @type:
+ event
+ @title:
+ OnNotifyOnline
+ @short:
+ An user in the notify list is on-line
+ @parameters:
+ $0 = nickname
+ @window:
+ Console or active window of the IRC context
+ @description:
+ This event is triggered when one of the users in your [doc:notify_list]notify[/doc] lists
+ is detected to be ON-Line.[br]
+ The event is triggered in the console window or the active window of the IRC context depending
+ on the user options.[br]
+ (Note: If you call [cmd]halt[/cmd] in this event , you will stop the "Nick is on irc" output,
+ but this is rather a bad idea since KVIrc gives a lot of additional informations to the
+ user with some notify-methods).[br]
+ This is a good place to play a sound or attract the user attention in some other way.[br]
+
+ */
+ EVENT("OnNotifyOnline","$0 = nickname"),
+ /*
+ @doc: onnotifyoffline
+ @type:
+ event
+ @title:
+ OnNotifyOffline
+ @short:
+ An user in the notify list went off-line
+ @parameters:
+ $0 = nickname
+ @window:
+ Console or active window of the IRC context
+ @description:
+ This event is triggered when one of the users in your [doc:notify_list]notify[/doc] lists
+ has just left IRC.[br]
+ The event is triggered in the console window or the active window of the IRC context depending
+ on the user options.[br]
+ (Note: If you call [cmd]halt[/cmd] in this event , you will stop the "Nick has left irc" output,
+ but this is rather a bad idea since KVIrc gives a lot of additional informations to the
+ user with some notify-methods).[br]
+ This is a good place to play a sound or attract the user attention in some other way.[br]
+ */
+ EVENT("OnNotifyOffline","$0 = nickname"),
+ /*
+ @doc: onpong
+ @type:
+ event
+ @title:
+ OnPong
+ @short:
+ Server pong handler
+ @parameters:
+ $0 = server
+ $1 = pong message parameters
+ @window:
+ Console
+ @description:
+ Triggered when a PONG message was received from a server.[br]
+ Calling 'halt' in this event will stop the informational message about the pong'.[br]
+ */
+ EVENT("OnPong", "$0 = server\n$1 = pong message parameters"),
+ /*
+ @doc: onlagalarmtimeup
+ @type:
+ event
+ @title:
+ OnLagAlarmTimeUp
+ @short:
+ High-Lag Alarm Started
+ @parameters:
+ $0 = server
+ $1 = Lag value in miliseconds
+ @window:
+ Console
+ @description:
+ Triggered when the Lag on the server tied to this console is higher than the[br]
+ configured Lag-Alarm time.
+ */
+ EVENT("OnLagAlarmTimeUp", "$0 = server\n$1 = lag time in miliseconds"),
+ /*
+ @doc: onlagalarmtimedown
+ @type:
+ event
+ @title:
+ OnLagAlarmTimeDown
+ @short:
+ High-Lag Alarm Stopped
+ @parameters:
+ $0 = server
+ $1 = Lag value in miliseconds
+ @window:
+ Console
+ @description:
+ Triggered when the Lag on the server tied to this console is lower than the[br]
+ configured Lag-Alarm time but was higher in the previous lag check.
+ */
+ EVENT("OnLagAlarmTimeDown", "$0 = server\n$1 = lag time in miliseconds"),
+ /*
+ @doc: onlagcheck
+ @type:
+ event
+ @title:
+ OnLagCheck
+ @short:
+ The lag metering engine has checked the lag
+ @parameters:
+ $0 = server
+ $1 = Lag value in miliseconds
+ @window:
+ Console
+ @description:
+ Triggered when the lag metering engine calculate a new current lag.[br]
+ */
+ EVENT("OnLagCheck", "$0 = server\n$1 = lag time in miliseconds"),
+ /*
+ @doc: onquerynotice
+ @type:
+ event
+ @title:
+ OnQueryNotice
+ @short:
+ A private notice has been received
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source host
+ $3 = message
+ @window:
+ Query window or console
+ @description:
+ Triggered when a private notice is received.[br]
+ If you call [cmd]halt[/cmd] in this event, the message output will be stopped
+ and if the message was going to cause a query window creation, the window will NOT be created.[br]
+ @seealso:
+ [event:onchannelmessage]OnChannelMessage[/event]
+ [event:onchannelnotice]OnChannelNotice[/event]
+ */
+ EVENT("OnQueryNotice", "$0 = source nick\n$1 = source username\n$2 = source host\n$3 = message"),
+ /*
+ @doc: onchanservnotice
+ @type:
+ event
+ @title:
+ OnChanServNotice
+ @short:
+ A notice from ChanServ has been received
+ @parameters:
+ $0 = ChanServ nick
+ $1 = ChanServ username
+ $2 = ChanServ host
+ $3 = message
+ @window:
+ console
+ @description:
+ Triggered when a notice is received and the source user is recognized as
+ the ChanServ service.<br>
+ Calling [cmd]halt[/cmd] stops the message output.
+ @seealso:
+ [event:onquerynotice]OnQueryNotice[/event]
+ [event:onnickservnotice]OnNickServNotice[/event]
+ */
+ EVENT("OnChanServNotice", "$0 = ChanServ nick\n$1 = ChanServ username\n$2 = ChanServ host\n$3 = message"),
+ /*
+ @doc: onnickservnotice
+ @type:
+ event
+ @title:
+ OnNickServNotice
+ @short:
+ A notice from NickServ has been received
+ @parameters:
+ $0 = NickServ nick
+ $1 = NickServ username
+ $2 = NickServ host
+ $3 = message
+ @window:
+ console
+ @description:
+ Triggered when a notice is received and the source user is recognized as
+ the NickServ service.<br>
+ Calling [cmd]halt[/cmd] stops the message output.
+ @seealso:
+ [event:onquerynotice]OnQueryNotice[/event]
+ [event:onchanservnotice]OnChanServNotice[/event]
+ */
+ EVENT("OnNickServNotice", "$0 = NickServ nick\n$1 = NickServ username\n$2 = NickServ host\n$3 = message"),
+ /*
+ @doc: onchanadmin
+ @type:
+ event
+ @title:
+ OnChanAdmin
+ @short:
+ Someone has given a user the +a flag
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source host
+ $3 = target nick
+ @window:
+ Channels window
+ @description:
+ Triggered when someone sets a +a (has made Channel Administrator) flag on a user of the active channel.
+ @seealso:
+ [event:ondechanadmin]OnDeChanAdmin[/event]
+ */
+ EVENT("OnChanAdmin","$0 = source nick\n$1 = source username\n$2 = source hostname\n$3 = target nick"),
+ /*
+ @doc: ondechanadmin
+ @type:
+ event
+ @title:
+ OnDeChanAdmin
+ @short:
+ Someone has given a user the -a flag
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source host
+ $3 = target nick
+ @window:
+ Channels window
+ @description:
+ Triggered when someone sets a -a (DeChanAdmin) flag on a user in the active channel.
+ @seealso:
+ [event:onchanadmin]OnChanAdmin[/event]
+ */
+ EVENT("OnDeChanAdmin","$0 = source nick\n$1 = source username\n$2 = source hostname\n$3 = target nick"),
+ /*
+ @doc: onmechanadmin
+ @type:
+ event
+ @title:
+ OnMeChanAdmin
+ @short:
+ Someone has given the +a flag to the local user
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source host
+ @window:
+ Channels window
+ @description:
+ Triggered when someone sets a +a (has made Channel administrator) flag on the local user in the active channel.
+ @seealso:
+ [event:onmedeop]OnMeDeChanAdmin[/event]
+ */
+ EVENT("OnMeChanAdmin","$0 = source nick\n$1 = source username\n$2 = source hostname"),
+ /*
+ @doc: onmedechanadmin
+ @type:
+ event
+ @title:
+ OnMeDeChanAdmin
+ @short:
+ Someone has given the -a flag to the local user
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source host
+ @window:
+ Channels window
+ @description:
+ Triggered when someone sets a -a (has removed channel admin status) flag on the local user in the active channel.
+ @seealso:
+ [event:onmeop]OnMeOp[/event]
+ */
+ EVENT("OnMeDeChanAdmin","$0 = source nick\n$1 = source username\n$2 = source hostname"),
+ /*
+ @doc: onmeuserop
+ @type:
+ event
+ @title:
+ OnMeUserOp
+ @short:
+ Someone has given the local user the +u flag
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source host
+ @window:
+ Channels window
+ @description:
+ Triggered when someone sets a +u (userop) flag for the local user in the active channel.
+ @seealso:
+ [event:onmedeuserop]OnMeDeUserOp[/event]
+ */
+ EVENT("OnMeUserOp","$0 = source nick\n$1 = source username\n$2 = source hostname"),
+ /*
+ @doc: onmedeuserop
+ @type:
+ event
+ @title:
+ OnMeDeUserOp
+ @short:
+ Someone has given the local user the -u flag
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source host
+ @window:
+ Channels window
+ @description:
+ Triggered when someone sets a -u (deuserop) flag for the local user in the active channel.
+ @seealso:
+ [event:onmeuserop]OnMeUserOp[/event]
+ */
+ EVENT("OnMeDeUserOp","$0 = source nick\n$1 = source username\n$2 = source hostname"),
+ /*
+ @doc: onuserop
+ @type:
+ event
+ @title:
+ OnUserOp
+ @short:
+ Someone has given a user the +u flag
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source host
+ $3 = useropped nick
+ @window:
+ Channels window
+ @description:
+ Triggered when someone sets a +u flag on a user of the active channel.
+ @seealso:
+ [event:ondeuserop]OnDeUserOp[/event]
+ */
+ EVENT("OnUserOp","$0 = source nick\n$1 = source username\n$2 = source hostname\n$3 = useropped nick"),
+ /*
+ @doc: ondeuserop
+ @type:
+ event
+ @title:
+ OnDeUserOp
+ @short:
+ Someone has given a user a -u flag
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source host
+ $3 = deuseropped nick
+ @window:
+ Channels window
+ @description:
+ Triggered when someone sets a -u (deuserop) flag on a user in the active channel.
+ @seealso:
+ [event:onuserop]OnUserOp[/event]
+ */
+ EVENT("OnDeUserOp","$0 = source nick\n$1 = source username\n$2 = source hostname\n$3 = deuseropped nick"),
+ /*
+ @doc: onquerywindowrequest
+ @type:
+ event
+ @title:
+ OnQueryWindowRequest
+ @short:
+ A new query window is going to be opened because a remote message has been received
+ @parameters:
+ $0 = source nickname
+ $1 = source username
+ $2 = source host
+ $3 = message
+ @window:
+ console window
+ @description:
+ Triggered when a PRIVMSG or NOTICE has been received from a remote user and a query
+ for that user doesn't exist yet. KVIrc has already checked its internal conditions
+ and you have the last word on the query creation. If you call halt in this event
+ you will prevent the creation of the query window, in all other cases the window
+ will be created. This is useful for filtering out spam messages that popup unwanted
+ windows in front of the user. You have also the option of creating the query window
+ yourself (by calling [cmd]query[/cmd]). This may be useful if you want to create
+ the query windows in a particular state (minimized, positioned in some special place
+ or maybe undocked if some conditions are verified).
+ The next event you will catch related to this query window will be
+ [event:onquerywindowcreated]OnQueryWindowCreated[/event] and [event:onquerytargetadded]OnQueryTargetAdded[/event].
+ After that you will get [event:onquerymessage]OnQueryMessage[/event] with exactly
+ the parameters passed to this event.
+ */
+ EVENT("OnQueryWindowRequest","$0 = source nick\n$1 = source user\n$2 = source host\n$3 = message"),
+ /*
+ @doc: onquerytargetadded
+ @type:
+ event
+ @title:
+ OnQueryTargetAdded
+ @short:
+ A new query target has been added
+ @parameters:
+ $0 = nickname
+ $1 = username (may be *)
+ $2 = host (may be *)
+ @window:
+ query window
+ @description:
+ Triggered when a new remote target has been added to a query window.
+ This is the event to catch when you want to perform some specific actions
+ when someone queries you.
+ KVIrc supports multiple target queries and thus, this event is triggered also
+ when a new query target is added by using [cmd]addtarget[/cmd].[br]
+ */
+ EVENT("OnQueryTargetAdded","$0 = nick\n$1 = username (may be *)\n$2 = hostname (may be *)"),
+ /*
+ @doc: onnetsplit
+ @type:
+ event
+ @title:
+ OnNetsplit
+ @short:
+ A netsplit has been detected
+ @parameters:
+ $0 = server1
+ $1 = server2
+ @window:
+ console
+ @description:
+ Triggered when KVIrc detects a netsplit by looking at an user's quit message.
+ The two parameters passed are the two servers that lost the link and were
+ signaled in that particular quit message.[br]
+ The actual netsplit detector in the KVIrc core uses the following rule
+ (extracted from the eggdrop bot code): "determine if signoff string matches "%.% %.%",
+ and only one space".[br]
+ [b]Note that this may be not accurate and KVIrc CAN be fooled by specially
+ formatted quit messages that aren't really netsplits.[/b][br]
+ KVIrc tries to avoid duplicate netsplit warnings thus this event will NOT
+ be triggered for EVERY quit in a netsplit: you will get it once for every
+ different set of servers that lost the link.[br]
+ Determining where the network link has been exactly broken may be a hard
+ task since the quit messages you see may not involve
+ the servers on the split boundary.
+ */
+ EVENT("OnNetsplit","$0 = server1\n$1 = server2"),
+ /*
+ @doc: ondccsessioncreated
+ @type:
+ event
+ @title:
+ OnDCCSessionCreated
+ @short:
+ A new DCC session has just been created
+ @parameters:
+ $0 = DCC session ID
+ @window:
+ console
+ @description:
+ Triggered when a new DCC session has just been created.
+ You can retrieve the session information by calling the [module:dcc]dcc[/module].*
+ module functions.
+ */
+ EVENT("OnDCCSessionCreated","$0 = DCC session ID"),
+ /*
+ @doc: ondccsessiondestroyed
+ @type:
+ event
+ @title:
+ OnDCCSessionDestroyed
+ @short:
+ A new DCC session has just been destroyed
+ @parameters:
+ $0 = DCC session ID
+ @window:
+ console
+ @description:
+ Triggered when a new DCC session has just been destroyed.
+ You can retrieve the session information by calling the [module:dcc]dcc[/module].*
+ module functions and by passing the DCC session ID parameter.
+ */
+ EVENT("OnDCCSessionDestroyed","$0 = DCC session ID"),
+ /*
+ @doc: ontextinput
+ @type:
+ event
+ @title:
+ OnTextInput
+ @short:
+ The user has just entered some text in the text input
+ @parameters:
+ $0 = text
+ @window:
+ window in that the text is entered
+ @description:
+ Triggered when the user enters some text in the text input
+ window and presses return.
+ Calling [cmd]halt[/cmd] will stop the automatic text processing
+ and the result depends on the window the text is typed in.
+ In channel/query and console windows the text will NOT be sent to
+ the IRC server. This event might be useful for performing
+ substitutions in the text sent to the server. If you stop the
+ text processing in a channel or query window then the local
+ echo of the message will be omitted too. You might want to
+ realize the echo by the means of the [cmd]echoprivmsg[/cmd] command.
+ This event is NOT triggered when the user enters a command
+ in the input window.
+ @seealso:
+ [cmd]echoprivmsg[/cmd]
+ */
+ EVENT("OnTextInput","$0 = text"),
+ /*
+ @doc: ondccchatpopuprequest
+ @type:
+ event
+ @title:
+ OnDCCChatPopupRequest
+ @short:
+ Triggered when the DCC chat text view is right-clicked
+ @parameters:
+ $0 = DCC session ID
+ @window:
+ DCC Chat window
+ @description:
+ This event is triggered when the user clicks the DCC chat
+ text view with the right mouse button. It is a good place
+ to activate a [cmd]popup[/cmd] menu :)
+ You can retrieve the session information by calling the [module:dcc]dcc[/module].*
+ module functions and by passing the DCC session ID parameter.
+ @seealso:
+ [event:onconsolepuprequest]OnConsolePopupRequest[/event],
+ [event:onchannelpopuprequest]OnChannelPopupRequest[/event],
+ [event:onquerypopuprequest]OnQueryPopupRequest[/event]
+ */
+ EVENT("OnDCCChatPopupRequest","$0 = DCC session ID"),
+ /*
+ @doc: ondccfiletransferconnectioninprogress
+ @type:
+ event
+ @title:
+ OnDCCFileTransferConnectionInProgress
+ @short:
+ Triggered when a DCC File transfer is waiting for a connection
+ @parameters:
+ $0 = DCC session ID
+ @window:
+ unspecified
+ @description:
+ Triggered when a DCC File transfer has been set up and
+ is waiting for the connection to be established.[br]
+ Note that the real data transfer is not started until
+ [event:ondccfiletransferbegin]OnDCCFileTransferBegin[/event] is triggered
+ but from this moment on you will be notified of success
+ or failure by the means of [event:ondccfiletransfersuccess]OnDCCFileTransferSuccess[/event]
+ or [event:ondccfiletransferfailed]OnDCCFileTransferFailed[/event].[br]
+ You can retrieve the session information by calling the [module:dcc]dcc[/module].*
+ module functions and by passing the DCC session ID parameter.
+ @seealso:
+ [event:ondccfiletransferfailed]OnDCCFileTransferFailed[/event],
+ [event:ondccfiletransfersuccess]OnDCCFileTransferSuccess[/event],
+ [event:ondccfiletransferbegin]OnDCCFileTransferBegin[/event]
+ */
+ EVENT("OnDCCFileTransferConnectionInProgress","$0 = DCC session ID"),
+ /*
+ @doc: ondccfiletransferbegin
+ @type:
+ event
+ @title:
+ OnDCCFileTransferBegin
+ @short:
+ Triggered when a DCC File transfer begins
+ @parameters:
+ $0 = DCC session ID
+ @window:
+ unspecified
+ @description:
+ Triggered when a DCC file transfer connection is established
+ and the real data transfer starts.[br]
+ You can retrieve the session information by calling the [module:dcc]dcc[/module].*
+ module functions and by passing the DCC session ID parameter.
+ @seealso:
+ [event:ondccfiletransferconnectioninprogress]OnDCCFileTransferConnectionInProgress[/event],
+ [event:ondccfiletransfersuccess]OnDCCFileTransferSuccess[/event],
+ [event:ondccfiletransferfailed]OnDCCFileTransferFailed[/event]
+ */
+ EVENT("OnDCCFileTransferBegin","$0 = DCC session ID"),
+ /*
+ @doc: ondccfiletransfersuccess
+ @type:
+ event
+ @title:
+ OnDCCFileTransferSuccess
+ @short:
+ Triggered when a DCC File transfer succeeds
+ @parameters:
+ $0 = bytes transferred
+ $1 = DCC session ID
+ @window:
+ unspecified
+ @description:
+ Triggered when a DCC File transfer terminates succesfully.[br]
+ $0 contains the number of bytes transferred in the session.[br]
+ You can retrieve the session information by calling the [module:dcc]dcc[/module].*
+ module functions and by passing the DCC session ID parameter.
+ @seealso:
+ [event:ondccfiletransferconnectioninprogress]OnDCCFileTransferConnectionInProgress[/event],
+ [event:ondccfiletransferfailed]OnDCCFileTransferFailed[/event],
+ [event:ondccfiletransferbegin]OnDCCFileTransferBegin[/event]
+ */
+ EVENT("OnDCCFileTransferSuccess","$0 = bytes transferred\n$1 = DCC session ID"),
+ /*
+ @doc: ondccfiletransferfailed
+ @type:
+ event
+ @title:
+ OnDCCFileTransferFailed
+ @short:
+ Triggered when a DCC File transfer fails
+ @parameters:
+ $0 = failure reason message
+ $1 = bytes transferred
+ $2 = DCC session ID
+ @window:
+ unspecified
+ @description:
+ Triggered when a DCC File transfer fails. $0 contains a message
+ explaining the reason of the failure.[br]
+ $1 contains the number of bytes transferred in the session, eventually 0.[br]
+ You can retrieve the session information by calling the [module:dcc]dcc[/module].*
+ module functions and by passing the DCC session ID parameter.
+ @seealso:
+ [event:ondccfiletransferconnectioninprogress]OnDCCFileTransferConnectionInProgress[/event],
+ [event:ondccfiletransfersuccess]OnDCCFileTransferSuccess[/event],
+ [event:ondccfiletransferbegin]OnDCCFileTransferBegin[/event]
+ */
+ EVENT("OnDCCFileTransferFailed","$0 = failure reason\n$1 = bytes transferred\n$2 = DCC session ID"),
+ /*
+ @doc: onwallops
+ @type:
+ event
+ @title:
+ OnWallops
+ @short:
+ Triggered when a WALLOPS message is received from the server
+ @parameters:
+ $0 = source nick
+ $1 = source user
+ $2 = source host
+ $3 = message text
+ @window:
+ channel
+ @description:
+ Triggered when a WALLOPS message is received from the server.
+ If you call [cmd]halt[/cmd] the message output will be stopped.
+ @seealso:
+ */
+ EVENT("OnWallops","$0 = nick\n$1 = user\n$2 = host\n$3 = message text"),
+ /*
+ @doc: ondisconnectrequest
+ @type:
+ event
+ @title:
+ OnDisconnectRequest
+ @short:
+ Triggered when the user requests a disconnection
+ @parameters:
+ none
+ @window:
+ console
+ @description:
+ Triggered when the user requests a disconnection from
+ a server by pressing the "disconnect", by closing
+ the console or closing KVIrc. It is your last chance
+ to send some meaningful data to the server before the QUIT message
+ is sent. You can't prevent the user from disconnecting: [cmd]halt [/cmd]does nothing here.[br]
+ This event is useful to either give a salute to all the users
+ you were talking with or maybe to send some commands to the
+ bouncer you're connected to. Note that you can override the QUIT
+ message sent by KVIrc by sending it by youself first.[br]
+ @seealso:
+ */
+ EVENT("OnDisconnectRequest","none"),
+ /*
+ @doc: onchanowner
+ @type:
+ event
+ @title:
+ OnChanOwner
+ @short:
+ Someone has given a user the +q flag
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source host
+ $3 = target nick
+ @window:
+ Channels window
+ @description:
+ Triggered when someone sets a +q (has made Channel Owner) flag on a user of the active channel.
+ @seealso:
+ [event:ondechanowner]OnDeChanOwner[/event]
+ */
+ EVENT("OnChanOwner","$0 = source nick\n$1 = source username\n$2 = source hostname\n$3 = target nick"),
+ /*
+ @doc: ondechanowner
+ @type:
+ event
+ @title:
+ OnDeChanOwner
+ @short:
+ Someone has given a user the -q flag
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source host
+ $3 = target nick
+ @window:
+ Channels window
+ @description:
+ Triggered when someone sets a -q (DeChanOwner) flag on a user in the active channel.
+ @seealso:
+ [event:onchanowner]OnChanOwner[/event]
+ */
+ EVENT("OnDeChanOwner","$0 = source nick\n$1 = source username\n$2 = source hostname\n$3 = target nick"),
+ /*
+ @doc: onmechanowner
+ @type:
+ event
+ @title:
+ OnMeChanOwner
+ @short:
+ Someone has given the +q flag to the local user
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source host
+ @window:
+ Channels window
+ @description:
+ Triggered when someone sets a +q (has made Channel owner) flag on the local user in the active channel.
+ @seealso:
+ [event:onmedechanowner]OnMeDeChanOwner[/event]
+ */
+ EVENT("OnMeChanOwner","$0 = source nick\n$1 = source username\n$2 = source hostname"),
+ /*
+ @doc: onmedechanowner
+ @type:
+ event
+ @title:
+ OnMeDeChanOwner
+ @short:
+ Someone has given the -q flag to the local user
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source host
+ @window:
+ Channels window
+ @description:
+ Triggered when someone sets a -q (has removed channel owner status) flag on the local user in the active channel.
+ @seealso:
+ [event:onmechanowner]OnMeChanOwner[/event]
+ */
+ EVENT("OnMeDeChanOwner","$0 = source nick\n$1 = source username\n$2 = source hostname"),
+ /*
+ @doc: onerror
+ @type:
+ event
+ @title:
+ OnError
+ @short:
+ Server ERROR message received
+ @parameters:
+ $0 = message source
+ $1 = error reason
+ @window:
+ Console
+ @description:
+ Triggered when an ERROR message is received from the server.[br]
+ $0 is the message (server) source but be aware that it often happens to be empty.[br]
+ Calling 'halt' in this event will stop the default output.[br]
+ */
+ EVENT("OnError","$0 = message source\n$1 = error reason"),
+ /*
+ @doc: OnQueryFileDropped
+ @type:
+ event
+ @title:
+ OnQueryFileDropped
+ @short:
+ Drop in query
+ @parameters:
+ $0 = source nick
+ $1 = filedropped
+ @window:
+ Query
+ @description:
+ Triggered when a file is dropped in a query window.[br]
+ $target is the nick.[br]
+ $0 is the dropped file.[br]
+ */
+ EVENT("OnQueryFileDropped","$0 = nick\n$1 = filedropped"), //-|Grifisx & Noldor|-
+ /*
+ @doc: OnHTTPGetTerminated
+ @type:
+ event
+ @title:
+ OnHTTPGetTerminated
+ @short:
+ A http.get command has terminated execution
+ @parameters:
+ $0 = status
+ $1 = remote url
+ $2 = local file
+ $3 = magic identifier
+ @window:
+ Console
+ @description:
+ Triggered when a [cmd]http.get[/cmd] file download has terminated execution.
+ If the transfer has been succesfull then $0 will contain the value 1 (true),
+ otherwise will contain the value 0. $1 contains the remote url and $2 the local
+ path on disk of the saved file. $3 contains the magic identifier passed to
+ the http.get command by the means of the -i switch.
+ */
+ EVENT("OnHTTPGetTerminated","$0 = status\n$1 = remote url\n$2 = local file\n$3 = magic identifier"),
+ /*
+ @doc: OnChannelModeChange
+ @type:
+ event
+ @title:
+ OnChannelModeChange
+ @short:
+ The channel mode has been changed
+ @parameters:
+ $0 = source nick
+ $1 = source user
+ $2 = source host
+ $3 = modeflags
+ $4 = mode parameter string
+ @window:
+ channel
+ @description:
+ Triggered when a channel mode has been changed, AFTER all the mode specific events
+ were triggered. $3 contains the unparsed mode flags (-o+b...) and $4 contains
+ the unparsed mode parameter string (you need to split it!).
+ */
+ EVENT("OnChannelModeChange","$0 = sourcenick\n$1 = sourceusername\n$2 = sourcehost\n$3 = modeflags\n$4 = mode params"),
+ /*
+ @doc: OnChannelNickLinkClick
+ @type:
+ event
+ @title:
+ OnChannelNickLinkClick
+ @short:
+ Clicked on nick in channel
+ @parameters:
+ $0 = nick list
+ @window:
+ channel
+ @description:
+ Triggered when user clicks on nickname in channel window
+ It will be triggered only at the left mouse button click
+ */
+ EVENT("OnChannelNickLinkClick",""),
+ /*
+ @doc: OnQueryNickLinkClick
+ @type:
+ event
+ @title:
+ OnQueryNickLinkClick
+ @short:
+ Triggered when user clicks on nickname in query window
+ @parameters:
+ $0 = nickname list
+ @window:
+ query
+ @description:
+ Triggered when user clicks on nickname in query window
+ It will be triggered only at the left mouse button click
+ */
+ EVENT("OnQueryNickLinkClick","$0 = nickname list"),
+ /*
+ @doc: OnConsoleNickLinkClick
+ @type:
+ event
+ @title:
+ OnConsoleNickLinkClick
+ @short:
+ Triggered when user clicks on nickname in console window
+ @parameters:
+ $0 = nickname
+ @window:
+ console
+ @description:
+ Triggered when user clicks on nickname in console window
+ It will be triggered only at the left mouse button click
+ */
+ EVENT("OnConsoleNickLinkClick","$0 = nickname"),
+ /*
+ @doc: OnHostLinkClick
+ @type:
+ event
+ @title:
+ OnHostLinkClick
+ @short:
+ Triggered when user clicks on any hostname in any window
+ @parameters:
+ $0 = host name
+ @window:
+ any
+ @description:
+ Triggered when user clicks on any hostname in any window
+ It will be triggered only at the left mouse button click
+ */
+ EVENT("OnHostLinkClick","$0 = host name")
+ , /*
+ @doc: OnUrlLinkClick
+ @type:
+ event
+ @title:
+ OnUrlLinkClick
+ @short:
+ Triggered when user clicks on any URL link in any window
+ @parameters:
+ $0 = url
+ @window:
+ any
+ @description:
+ Triggered when user clicks on any URL link in any window
+ It will be triggered only at the left mouse button click
+ */
+ EVENT("OnUrlLinkClick","$0 = url"),
+ /*
+ @doc: OnChannelLinkClick
+ @type:
+ event
+ @title:
+ OnChannelLinkClick
+ @short:
+ Triggered when user clicks on any channel name in any window
+ @parameters:
+ $0 = channel name
+ @window:
+ any
+ @description:
+ Triggered when user clicks on any channel name in any window
+ It will be triggered only at the left mouse button click
+ */
+ EVENT("OnChannelLinkClick","$0 = channel name"),
+ /*
+ @doc: OnServerLinkClick
+ @type:
+ event
+ @title:
+ OnServerLinkClick
+ @short:
+ Triggered when user clicks on server name in any window
+ @parameters:
+ $0 = server name
+ @window:
+ any
+ @description:
+ Triggered when user clicks on server name in any window
+ It will be triggered only at the left mouse button click
+ */
+ EVENT("OnServerLinkClick","$0 = server name"),
+ /*
+ @doc: OnIgnoredMessage
+ @type:
+ event
+ @title:
+ OnIgnoredMessage
+ @short:
+ Triggered when a message is ignored.
+ @parameters:
+ $0 = source nick
+ $1 = source username
+ $2 = source host
+ $3 = message target
+ $4 = message
+ @window:
+ any
+ @description:
+ Triggered when a message is ignored.
+ */
+ EVENT("OnIgnoredMessage","$0 = source nick\n$1 = source username\n$2 = source host\n$3 = message target\n$4 = message"),
+ /*
+ @doc: OnNickServAuth
+ @type:
+ event
+ @title:
+ OnNickServAuth
+ @short:
+ Triggered when ircd sets a registered user mode.
+ @parameters:
+ @window:
+ any
+ @description:
+ Triggered when ircd sets a registered user mode.
+ */
+ EVENT("OnNickServAuth",""),
+ /*
+ @doc: onmeaction
+ @type:
+ event
+ @title:
+ OnMeAction
+ @short:
+ User issued a CTCP ACTION
+ @parameters:
+ $0 = action message text
+ @window:
+ Channels and query windows
+ @description:
+ This event is triggered when user issues a CTCP ACTION.[br]
+ (The CTCP ACTION is usually triggered by the /me command).[br]
+ */
+
+ EVENT("OnMeAction","$0 = action message text")
+};
+
diff --git a/src/kvirc/kvs/kvi_kvs_eventtable.h b/src/kvirc/kvs/kvi_kvs_eventtable.h
new file mode 100644
index 00000000..af00e8da
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_eventtable.h
@@ -0,0 +1,212 @@
+#ifndef _KVI_KVS_EVENTTABLE_H_
+#define _KVI_KVS_EVENTTABLE_H_
+//=============================================================================
+//
+// File : kvi_kvs_eventtable.h
+// Created on Mon 23 Feb 2004 03:23:18 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+// Application
+#define KviEvent_OnKVIrcStartup 0
+#define KviEvent_OnKVIrcShutdown 1
+// Irc Context
+#define KviEvent_OnIrcContextCreated 2
+#define KviEvent_OnIrcContextDestroyed 3
+// Irc connection
+#define KviEvent_OnIrcConnectionEstabilished 4
+#define KviEvent_OnIrcConnectionTerminated 5
+// Login complete
+#define KviEvent_OnIrc 6
+// Channel userlist clicks
+#define KviEvent_OnChannelNickPopupRequest 7
+#define KviEvent_OnChannelNickDefaultActionRequest 8
+// Frame window
+#define KviEvent_OnFrameWindowCreated 9
+#define KviEvent_OnFrameWindowDestroyed 10
+// Text view
+#define KviEvent_OnChannelPopupRequest 11
+#define KviEvent_OnConsolePopupRequest 12
+#define KviEvent_OnQueryPopupRequest 13
+
+#define KviEvent_OnChannelSync 14
+
+#define KviEvent_OnUrl 15
+
+#define KviEvent_OnWindowPopupRequest 16
+
+#define KviEvent_OnHostLinkPopupRequest 17
+#define KviEvent_OnUrlLinkPopupRequest 18
+#define KviEvent_OnServerLinkPopupRequest 19
+#define KviEvent_OnChannelLinkPopupRequest 20
+#define KviEvent_OnNickLinkPopupRequest 21
+// Query nick clicks
+#define KviEvent_OnQueryNickPopupRequest 22
+#define KviEvent_OnQueryNickDefaultActionRequest 23
+
+#define KviEvent_OnNickLinkDefaultActionRequest 24
+#define KviEvent_OnTextViewDoubleClicked 25
+
+#define KviEvent_OnNotifyListDefaultActionRequest 26
+#define KviEvent_OnNotifyListPopupRequest 27
+
+#define KviEvent_OnPing 28
+
+#define KviEvent_OnMeJoin 29
+#define KviEvent_OnJoin 30
+
+#define KviEvent_OnTopic 31
+
+#define KviEvent_OnMePart 32
+#define KviEvent_OnPart 33
+
+#define KviEvent_OnQuit 34
+
+#define KviEvent_OnUserMode 35
+
+#define KviEvent_OnMeKick 36
+#define KviEvent_OnKick 37
+
+#define KviEvent_OnMeAway 38
+#define KviEvent_OnMeBack 39
+
+#define KviEvent_OnChannelWindowCreated 40
+#define KviEvent_OnQueryWindowCreated 41
+#define KviEvent_OnBan 42
+#define KviEvent_OnUnban 43
+#define KviEvent_OnMeBan 44
+#define KviEvent_OnMeUnban 45
+#define KviEvent_OnBanException 46
+#define KviEvent_OnBanExceptionRemove 47
+#define KviEvent_OnMeBanException 48
+#define KviEvent_OnMeBanExceptionRemove 49
+#define KviEvent_OnOp 50
+#define KviEvent_OnDeOp 51
+#define KviEvent_OnMeOp 52
+#define KviEvent_OnMeDeOp 53
+#define KviEvent_OnLimitSet 54
+#define KviEvent_OnLimitUnset 55
+#define KviEvent_OnKeySet 56
+#define KviEvent_OnKeyUnset 57
+#define KviEvent_OnInvite 58
+#define KviEvent_OnChannelMessage 59
+#define KviEvent_OnQueryMessage 60
+#define KviEvent_OnVoice 61
+#define KviEvent_OnDeVoice 62
+#define KviEvent_OnMeVoice 63
+#define KviEvent_OnMeDeVoice 64
+#define KviEvent_OnNickChange 65
+#define KviEvent_OnMeNickChange 66
+#define KviEvent_OnCtcpRequest 67
+#define KviEvent_OnCtcpReply 68
+#define KviEvent_OnUnhandledLiteral 69
+#define KviEvent_OnMeHalfOp 70
+#define KviEvent_OnMeDeHalfOp 71
+#define KviEvent_OnHalfOp 72
+#define KviEvent_OnDeHalfOp 73
+#define KviEvent_OnInviteException 74
+#define KviEvent_OnInviteExceptionRemove 75
+#define KviEvent_OnMeInviteException 76
+#define KviEvent_OnMeInviteExceptionRemove 77
+#define KviEvent_OnAction 78
+#define KviEvent_OnCtcpFlood 79
+#define KviEvent_OnChannelNotice 80
+#define KviEvent_OnServerNotice 81
+#define KviEvent_OnDCCChatWindowCreated 82
+#define KviEvent_OnDCCChatConnectionInProgress 83
+#define KviEvent_OnDCCChatConnected 84
+#define KviEvent_OnDCCChatMessage 85
+#define KviEvent_OnDCCChatError 86
+#define KviEvent_OnDCCChatDisconnected 87
+#define KviEvent_OnDCCChatWindowClosing 88
+#define KviEvent_OnAccelKeyPressed 89
+#define KviEvent_OnHighlight 90
+#define KviEvent_OnWindowActivated 91
+#define KviEvent_OnNotifyOnLine 92
+#define KviEvent_OnNotifyOffLine 93
+#define KviEvent_OnPong 94
+#define KviEvent_OnLagAlarmTimeUp 95
+#define KviEvent_OnLagAlarmTimeDown 96
+#define KviEvent_OnLagCheck 97
+
+#define KviEvent_OnQueryNotice 98
+#define KviEvent_OnChanServNotice 99
+#define KviEvent_OnNickServNotice 100
+
+#define KviEvent_OnChanAdmin 101
+#define KviEvent_OnDeChanAdmin 102
+#define KviEvent_OnMeChanAdmin 103
+#define KviEvent_OnMeDeChanAdmin 104
+
+#define KviEvent_OnMeUserOp 105
+#define KviEvent_OnMeDeUserOp 106
+#define KviEvent_OnUserOp 107
+#define KviEvent_OnDeUserOp 108
+
+#define KviEvent_OnQueryWindowRequest 109
+#define KviEvent_OnQueryTargetAdded 110
+
+#define KviEvent_OnNetsplit 111
+
+#define KviEvent_OnDCCSessionCreated 112
+#define KviEvent_OnDCCSessionDestroyed 113
+
+#define KviEvent_OnTextInput 114
+
+#define KviEvent_OnDCCChatPopupRequest 115
+
+#define KviEvent_OnDCCFileTransferConnectionInProgress 116
+#define KviEvent_OnDCCFileTransferBegin 117
+#define KviEvent_OnDCCFileTransferSuccess 118
+#define KviEvent_OnDCCFileTransferFailed 119
+
+#define KviEvent_OnWallops 120
+
+#define KviEvent_OnDisconnectRequest 121
+
+#define KviEvent_OnChanOwner 122
+#define KviEvent_OnDeChanOwner 123
+#define KviEvent_OnMeChanOwner 124
+#define KviEvent_OnMeDeChanOwner 125
+#define KviEvent_OnError 126
+#define KviEvent_OnQueryFileDropped 127
+
+#define KviEvent_OnHTTPGetTerminated 128
+
+#define KviEvent_OnChannelModeChange 129
+
+#define KviEvent_OnChannelNickLinkClick 130
+#define KviEvent_OnQueryNickLinkClick 131
+#define KviEvent_OnConsoleNickLinkClick 132
+#define KviEvent_OnHostLinkClick 133
+#define KviEvent_OnUrlLinkClick 134
+#define KviEvent_OnChannelLinkClick 135
+#define KviEvent_OnServerLinkClick 136
+#define KviEvent_OnIgnoredMessage 137
+
+#define KviEvent_OnNickServAuth 138
+
+#define KviEvent_OnMeAction 139
+
+#define KVI_KVS_NUM_APP_EVENTS 140
+// compat
+#define KVI_NUM_SCRIPT_EVENTS KVI_KVS_NUM_APP_EVENTS
+
+#endif //!_KVI_KVS_EVENTTABLE_H_
diff --git a/src/kvirc/kvs/kvi_kvs_eventtriggers.h b/src/kvirc/kvs/kvi_kvs_eventtriggers.h
new file mode 100644
index 00000000..97a4d6b8
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_eventtriggers.h
@@ -0,0 +1,289 @@
+#ifndef _KVI_KVS_EVENTTRIGGERS_H_
+#define _KVI_KVS_EVENTTRIGGERS_H_
+//=============================================================================
+//
+// File : kvi_kvs_eventtriggers.h
+// Created on Thu Oct 22 2005 04:57:12 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#include "kvi_kvs_eventtable.h"
+#include "kvi_kvs_eventmanager.h"
+#include "kvi_kvs_variantlist.h"
+
+//
+// KVS Macros for triggering events
+//
+// KviKvsVariantList vParams;
+// vParams.append(bSomething);
+// vParams.append(iSomething);
+// vParams.append(szSomething);
+// KVS_TRIGGER_EVENT(KviEvent_OnSomething,pSomeWindow,&vParams)
+//
+// if(KVS_TRIGGER_EVENT_HALTED(KviEvent_OnSomething,pSomeWindow,&vParams))
+// msg->haltOutput()
+//
+//
+
+// THESE TWO ARE SLOW, but allow reusing the params
+#define KVS_TRIGGER_EVENT(__idx,__wnd,__parms) \
+ if(KviKvsEventManager::instance()->hasAppHandlers(__idx)) \
+ KviKvsEventManager::instance()->trigger(__idx,__wnd,__parms);
+
+#define KVS_TRIGGER_EVENT_HALTED(__idx,__wnd,__parms) \
+ (KviKvsEventManager::instance()->hasAppHandlers(__idx) ? \
+ KviKvsEventManager::instance()->trigger(__idx,__wnd,__parms) : false)
+
+
+// FAST CALLING MACROS
+#define KVS_TRIGGER_EVENT_0(__idx,__wnd) \
+ if(KviKvsEventManager::instance()->hasAppHandlers(__idx)) \
+ { \
+ KviKvsVariantList _vLocalParamList; \
+ KviKvsEventManager::instance()->trigger(__idx,__wnd,&_vLocalParamList); \
+ }
+
+#define KVS_TRIGGER_EVENT_1(__idx,__wnd,__param1) \
+ if(KviKvsEventManager::instance()->hasAppHandlers(__idx)) \
+ { \
+ KviKvsVariantList _vLocalParamList( \
+ new KviKvsVariant(__param1) \
+ ); \
+ KviKvsEventManager::instance()->trigger(__idx,__wnd,&_vLocalParamList); \
+ }
+
+#define KVS_TRIGGER_EVENT_2(__idx,__wnd,__param1,__param2) \
+ if(KviKvsEventManager::instance()->hasAppHandlers(__idx)) \
+ { \
+ KviKvsVariantList _vLocalParamList( \
+ new KviKvsVariant(__param1), \
+ new KviKvsVariant(__param2) \
+ ); \
+ KviKvsEventManager::instance()->trigger(__idx,__wnd,&_vLocalParamList); \
+ }
+
+#define KVS_TRIGGER_EVENT_3(__idx,__wnd,__param1,__param2,__param3) \
+ if(KviKvsEventManager::instance()->hasAppHandlers(__idx)) \
+ { \
+ KviKvsVariantList _vLocalParamList( \
+ new KviKvsVariant(__param1), \
+ new KviKvsVariant(__param2), \
+ new KviKvsVariant(__param3) \
+ ); \
+ KviKvsEventManager::instance()->trigger(__idx,__wnd,&_vLocalParamList); \
+ }
+
+#define KVS_TRIGGER_EVENT_4(__idx,__wnd,__param1,__param2,__param3,__param4) \
+ if(KviKvsEventManager::instance()->hasAppHandlers(__idx)) \
+ { \
+ KviKvsVariantList _vLocalParamList( \
+ new KviKvsVariant(__param1), \
+ new KviKvsVariant(__param2), \
+ new KviKvsVariant(__param3), \
+ new KviKvsVariant(__param4) \
+ ); \
+ KviKvsEventManager::instance()->trigger(__idx,__wnd,&_vLocalParamList); \
+ }
+
+#define KVS_TRIGGER_EVENT_5(__idx,__wnd,__param1,__param2,__param3,__param4,__param5) \
+ if(KviKvsEventManager::instance()->hasAppHandlers(__idx)) \
+ { \
+ KviKvsVariantList _vLocalParamList( \
+ new KviKvsVariant(__param1), \
+ new KviKvsVariant(__param2), \
+ new KviKvsVariant(__param3), \
+ new KviKvsVariant(__param4), \
+ new KviKvsVariant(__param5) \
+ ); \
+ KviKvsEventManager::instance()->trigger(__idx,__wnd,&_vLocalParamList); \
+ }
+
+#define KVS_TRIGGER_EVENT_6(__idx,__wnd,__param1,__param2,__param3,__param4,__param5,__param6) \
+ if(KviKvsEventManager::instance()->hasAppHandlers(__idx)) \
+ { \
+ KviKvsVariantList _vLocalParamList( \
+ new KviKvsVariant(__param1), \
+ new KviKvsVariant(__param2), \
+ new KviKvsVariant(__param3), \
+ new KviKvsVariant(__param4), \
+ new KviKvsVariant(__param5), \
+ new KviKvsVariant(__param6) \
+ ); \
+ KviKvsEventManager::instance()->trigger(__idx,__wnd,&_vLocalParamList); \
+ }
+
+#define KVS_TRIGGER_EVENT_7(__idx,__wnd,__param1,__param2,__param3,__param4,__param5,__param6,__param7) \
+ if(KviKvsEventManager::instance()->hasAppHandlers(__idx)) \
+ { \
+ KviKvsVariantList _vLocalParamList( \
+ new KviKvsVariant(__param1), \
+ new KviKvsVariant(__param2), \
+ new KviKvsVariant(__param3), \
+ new KviKvsVariant(__param4), \
+ new KviKvsVariant(__param5), \
+ new KviKvsVariant(__param6), \
+ new KviKvsVariant(__param7) \
+ ); \
+ KviKvsEventManager::instance()->trigger(__idx,__wnd,&_vLocalParamList); \
+ }
+
+
+#define KVS_TRIGGER_EVENT_0_HALTED(__idx,__wnd) \
+ ( \
+ KviKvsEventManager::instance()->hasAppHandlers(__idx) \
+ ? \
+ KviKvsEventManager::instance()->triggerDeleteParams( \
+ __idx, \
+ __wnd, \
+ new KviKvsVariantList() \
+ ) \
+ : \
+ false \
+ )
+
+#define KVS_TRIGGER_EVENT_1_HALTED(__idx,__wnd,__param1) \
+ ( \
+ KviKvsEventManager::instance()->hasAppHandlers(__idx) \
+ ? \
+ KviKvsEventManager::instance()->triggerDeleteParams( \
+ __idx, \
+ __wnd, \
+ new KviKvsVariantList( \
+ new KviKvsVariant(__param1) \
+ ) \
+ ) \
+ : \
+ false \
+ )
+
+#define KVS_TRIGGER_EVENT_2_HALTED(__idx,__wnd,__param1,__param2) \
+ ( \
+ KviKvsEventManager::instance()->hasAppHandlers(__idx) \
+ ? \
+ KviKvsEventManager::instance()->triggerDeleteParams( \
+ __idx, \
+ __wnd, \
+ new KviKvsVariantList( \
+ new KviKvsVariant(__param1), \
+ new KviKvsVariant(__param2) \
+ ) \
+ ) \
+ : \
+ false \
+ )
+
+#define KVS_TRIGGER_EVENT_3_HALTED(__idx,__wnd,__param1,__param2,__param3) \
+ ( \
+ KviKvsEventManager::instance()->hasAppHandlers(__idx) \
+ ? \
+ KviKvsEventManager::instance()->triggerDeleteParams( \
+ __idx, \
+ __wnd, \
+ new KviKvsVariantList( \
+ new KviKvsVariant(__param1), \
+ new KviKvsVariant(__param2), \
+ new KviKvsVariant(__param3) \
+ ) \
+ ) \
+ : \
+ false \
+ )
+
+#define KVS_TRIGGER_EVENT_4_HALTED(__idx,__wnd,__param1,__param2,__param3,__param4) \
+ ( \
+ KviKvsEventManager::instance()->hasAppHandlers(__idx) \
+ ? \
+ KviKvsEventManager::instance()->triggerDeleteParams( \
+ __idx, \
+ __wnd, \
+ new KviKvsVariantList( \
+ new KviKvsVariant(__param1), \
+ new KviKvsVariant(__param2), \
+ new KviKvsVariant(__param3), \
+ new KviKvsVariant(__param4) \
+ ) \
+ ) \
+ : \
+ false \
+ )
+
+#define KVS_TRIGGER_EVENT_5_HALTED(__idx,__wnd,__param1,__param2,__param3,__param4,__param5) \
+ ( \
+ KviKvsEventManager::instance()->hasAppHandlers(__idx) \
+ ? \
+ KviKvsEventManager::instance()->triggerDeleteParams( \
+ __idx, \
+ __wnd, \
+ new KviKvsVariantList( \
+ new KviKvsVariant(__param1), \
+ new KviKvsVariant(__param2), \
+ new KviKvsVariant(__param3), \
+ new KviKvsVariant(__param4), \
+ new KviKvsVariant(__param5) \
+ ) \
+ ) \
+ : \
+ false \
+ )
+
+#define KVS_TRIGGER_EVENT_6_HALTED(__idx,__wnd,__param1,__param2,__param3,__param4,__param5,__param6) \
+ ( \
+ KviKvsEventManager::instance()->hasAppHandlers(__idx) \
+ ? \
+ KviKvsEventManager::instance()->triggerDeleteParams( \
+ __idx, \
+ __wnd, \
+ new KviKvsVariantList( \
+ new KviKvsVariant(__param1), \
+ new KviKvsVariant(__param2), \
+ new KviKvsVariant(__param3), \
+ new KviKvsVariant(__param4), \
+ new KviKvsVariant(__param5), \
+ new KviKvsVariant(__param6) \
+ ) \
+ ) \
+ : \
+ false \
+ )
+
+#define KVS_TRIGGER_EVENT_7_HALTED(__idx,__wnd,__param1,__param2,__param3,__param4,__param5,__param6,__param7) \
+ ( \
+ KviKvsEventManager::instance()->hasAppHandlers(__idx) \
+ ? \
+ KviKvsEventManager::instance()->triggerDeleteParams( \
+ __idx, \
+ __wnd, \
+ new KviKvsVariantList( \
+ new KviKvsVariant(__param1), \
+ new KviKvsVariant(__param2), \
+ new KviKvsVariant(__param3), \
+ new KviKvsVariant(__param4), \
+ new KviKvsVariant(__param5), \
+ new KviKvsVariant(__param6), \
+ new KviKvsVariant(__param7) \
+ ) \
+ ) \
+ : \
+ false \
+ )
+
+#endif //!_KVI_KVS_EVENTTRIGGERS_H_
diff --git a/src/kvirc/kvs/kvi_kvs_hash.cpp b/src/kvirc/kvs/kvi_kvs_hash.cpp
new file mode 100644
index 00000000..3c391fcd
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_hash.cpp
@@ -0,0 +1,96 @@
+//=============================================================================
+//
+// File : kvi_kvs_hash.cpp
+// Created on Tue 07 Oct 2003 01:22:37 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_hash.h"
+
+KviKvsHash::KviKvsHash()
+{
+ m_pDict = new KviPointerHashTable<QString,KviKvsVariant>(17,false);
+ m_pDict->setAutoDelete(true);
+}
+
+KviKvsHash::KviKvsHash(const KviKvsHash &h)
+{
+ m_pDict = new KviPointerHashTable<QString,KviKvsVariant>();
+ m_pDict->setAutoDelete(true);
+ KviPointerHashTableIterator<QString,KviKvsVariant> it(*(h.m_pDict));
+ while(it.current())
+ {
+ m_pDict->replace(it.currentKey(),new KviKvsVariant(*(it.current())));
+ ++it;
+ }
+}
+
+KviKvsHash::~KviKvsHash()
+{
+ delete m_pDict;
+}
+
+void KviKvsHash::appendAsString(QString &szBuffer) const
+{
+ KviPointerHashTableIterator<QString,KviKvsVariant> it(*m_pDict);
+ bool bNeedComma = false;
+ while(KviKvsVariant * s = it.current())
+ {
+ if(bNeedComma)szBuffer.append(',');
+ else bNeedComma = true;
+ s->appendAsString(szBuffer);
+ ++it;
+ }
+}
+
+void KviKvsHash::serialize(QString& result)
+{
+ QString tmpBuffer;
+ result="{";
+ KviPointerHashTableIterator<QString,KviKvsVariant> it(*m_pDict);
+ bool bNeedComma = false;
+ while(KviKvsVariant * s = it.current())
+ {
+ if(bNeedComma)result.append(',');
+ else bNeedComma = true;
+
+ tmpBuffer = it.currentKey();
+ KviKvsVariant::serializeString(tmpBuffer);
+ result.append(tmpBuffer);
+
+ result.append(":");
+ s->serialize(tmpBuffer);
+ result.append(tmpBuffer);
+
+ ++it;
+ }
+ result.append('}');
+}
+
+KviKvsVariant * KviKvsHash::get(const QString &szKey)
+{
+ KviKvsVariant * v = m_pDict->find(szKey);
+ if(v)return v;
+ v = new KviKvsVariant();
+ m_pDict->replace(szKey,v);
+ return v;
+}
diff --git a/src/kvirc/kvs/kvi_kvs_hash.h b/src/kvirc/kvs/kvi_kvs_hash.h
new file mode 100644
index 00000000..e0b2d865
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_hash.h
@@ -0,0 +1,64 @@
+#ifndef _KVI_KVS_HASH_H_
+#define _KVI_KVS_HASH_H_
+//=============================================================================
+//
+// File : kvi_kvs_hash.h
+// Created on Tue 07 Oct 2003 01:22:37 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#include "kvi_pointerhashtable.h"
+#include "kvi_qstring.h"
+
+#include "kvi_kvs_variant.h"
+#include "kvi_heapobject.h"
+
+typedef KVIRC_API KviPointerHashTableIterator<QString,KviKvsVariant> KviKvsHashIterator;
+
+// This class must not have virtual funcitons nor destructor
+// Otherwise it will happily crash on windows when it is
+// allocated in modules and destroyed anywhere else around...
+class KVIRC_API KviKvsHash : public KviHeapObject
+{
+public:
+ KviKvsHash();
+ KviKvsHash(const KviKvsHash &h);
+ ~KviKvsHash();
+protected:
+ KviPointerHashTable<QString,KviKvsVariant> * m_pDict;
+public:
+ void unset(const QString &szKey){ m_pDict->remove(szKey); };
+ void set(const QString &szKey,KviKvsVariant * pVal){ m_pDict->replace(szKey,pVal); };
+ KviKvsVariant * find(const QString &szKey) const { return m_pDict->find(szKey); };
+ KviKvsVariant * get(const QString &szKey);
+
+ bool isEmpty() const { return m_pDict->isEmpty(); };
+ kvs_uint_t size() const { return m_pDict->count(); };
+
+ void appendAsString(QString &szBuffer) const;
+
+ const KviPointerHashTable<QString,KviKvsVariant> * dict(){ return m_pDict; };
+
+ void serialize(QString& result);
+};
+
+#endif //!_KVI_KVS_HASH_H_
diff --git a/src/kvirc/kvs/kvi_kvs_kernel.cpp b/src/kvirc/kvs/kvi_kvs_kernel.cpp
new file mode 100644
index 00000000..9c709fe0
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_kernel.cpp
@@ -0,0 +1,221 @@
+//=============================================================================
+//
+// File : kvi_kvs_kernel.cpp
+// Creation date : Tue 30 Sep 2003 05.12 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_kernel.h"
+#include "kvi_kvs_parser.h"
+#include "kvi_kvs_hash.h"
+#include "kvi_kvs_aliasmanager.h"
+#include "kvi_kvs_coresimplecommands.h"
+#include "kvi_kvs_corefunctions.h"
+#include "kvi_kvs_corecallbackcommands.h"
+#include "kvi_kvs_switchlist.h"
+#include "kvi_kvs_variantlist.h"
+#include "kvi_kvs_script.h"
+#include "kvi_kvs_object_controller.h"
+#include "kvi_kvs_asyncoperation.h"
+#include "kvi_modulemanager.h"
+
+KviKvsKernel * KviKvsKernel::m_pKvsKernel = 0;
+
+////////////////////////////////////////////////////////////////////////////////
+// CONSTRUCTION AND DESTRUCTION
+
+KviKvsKernel::KviKvsKernel()
+{
+ m_pKvsKernel = this;
+
+ m_pSpecialCommandParsingRoutineDict = new KviPointerHashTable<QString,KviKvsSpecialCommandParsingRoutine>(17,false);
+ m_pSpecialCommandParsingRoutineDict->setAutoDelete(true);
+ m_pCoreSimpleCommandExecRoutineDict = new KviPointerHashTable<QString,KviKvsCoreSimpleCommandExecRoutine>(51,false);
+ m_pCoreSimpleCommandExecRoutineDict->setAutoDelete(true);
+ m_pCoreFunctionExecRoutineDict = new KviPointerHashTable<QString,KviKvsCoreFunctionExecRoutine>(51,false);
+ m_pCoreFunctionExecRoutineDict->setAutoDelete(true);
+ m_pCoreCallbackCommandExecRoutineDict = new KviPointerHashTable<QString,KviKvsCoreCallbackCommandExecRoutine>(17,false);
+ m_pCoreCallbackCommandExecRoutineDict->setAutoDelete(true);
+
+ m_pGlobalVariables = new KviKvsHash();
+ m_pEmptyParameterList = new KviKvsVariantList();
+ m_pObjectController = new KviKvsObjectController();
+ m_pObjectController->init();
+ m_pAsyncOperationManager = new KviKvsAsyncOperationManager();
+
+ KviKvsParser::init();
+
+ KviKvsCoreSimpleCommands::init();
+ KviKvsCoreFunctions::init();
+ KviKvsCoreCallbackCommands::init();
+}
+
+KviKvsKernel::~KviKvsKernel()
+{
+ delete m_pAsyncOperationManager;
+ delete m_pObjectController;
+ delete m_pEmptyParameterList;
+ delete m_pGlobalVariables;
+
+ delete m_pSpecialCommandParsingRoutineDict;
+ delete m_pCoreSimpleCommandExecRoutineDict;
+ delete m_pCoreFunctionExecRoutineDict;
+ delete m_pCoreCallbackCommandExecRoutineDict;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// INSTANCE MANAGEMENT
+
+void KviKvsKernel::init()
+{
+ if(!m_pKvsKernel)m_pKvsKernel = new KviKvsKernel();
+}
+
+void KviKvsKernel::done()
+{
+ if(m_pKvsKernel)
+ {
+ delete m_pKvsKernel;
+ m_pKvsKernel = 0;
+ }
+}
+
+#define COMPLETE_COMMAND_BY_DICT(__type,__dict) \
+ { \
+ KviPointerHashTableIterator<QString,__type> it(*__dict); \
+ int l = szCommandBegin.length(); \
+ while(it.current()) \
+ { \
+ if(KviQString::equalCIN(szCommandBegin,it.currentKey(),l)) \
+ pMatches->append(new QString(it.currentKey())); \
+ ++it; \
+ } \
+ }
+
+
+void KviKvsKernel::completeCommand(const QString &szCommandBegin,KviPointerList<QString> * pMatches)
+{
+ int idx = szCommandBegin.find(QChar('.'));
+ if(idx == -1)
+ {
+ // no module name inside
+ COMPLETE_COMMAND_BY_DICT(KviKvsCoreSimpleCommandExecRoutine,m_pCoreSimpleCommandExecRoutineDict)
+ COMPLETE_COMMAND_BY_DICT(KviKvsSpecialCommandParsingRoutine,m_pSpecialCommandParsingRoutineDict)
+ COMPLETE_COMMAND_BY_DICT(KviKvsCoreCallbackCommandExecRoutine,m_pCoreCallbackCommandExecRoutineDict)
+
+ KviPointerList<QString> lModules;
+ lModules.setAutoDelete(true);
+ g_pModuleManager->completeModuleNames(szCommandBegin,&lModules);
+ QString szEmpty = "";
+ for(QString * pszModuleName = lModules.first();pszModuleName;pszModuleName = lModules.next())
+ completeModuleCommand(*pszModuleName,szEmpty,pMatches);
+
+ KviKvsAliasManager::instance()->completeCommand(szCommandBegin,pMatches);
+ } else {
+ // contains a module name
+ QString szModuleName = szCommandBegin.left(idx);
+ QString szRight = szCommandBegin.right(szCommandBegin.length() - (idx+1));
+ completeModuleCommand(szModuleName,szRight,pMatches);
+ }
+}
+
+void KviKvsKernel::completeModuleCommand(const QString &szModuleName,const QString &szCommandBegin,KviPointerList<QString> * pMatches)
+{
+ KviModule * pModule = g_pModuleManager->getModule(szModuleName.latin1());
+ if(!pModule)return;
+
+ KviPointerList<QString> lModuleMatches;
+ lModuleMatches.setAutoDelete(true);
+ pModule->completeCommand(szCommandBegin,&lModuleMatches);
+ for(QString * pszModuleMatch = lModuleMatches.first();pszModuleMatch;pszModuleMatch = lModuleMatches.next())
+ {
+ QString * pszMatch = new QString(*pszModuleMatch);
+ pszMatch->prepend(".");
+ pszMatch->prepend(szModuleName);
+ pMatches->append(pszMatch);
+ }
+}
+
+void KviKvsKernel::completeFunction(const QString &szFunctionBegin,KviPointerList<QString> * pMatches)
+{
+ int idx = szFunctionBegin.find(QChar('.'));
+ if(idx == -1)
+ {
+ // no module name inside
+
+ KviPointerHashTableIterator<QString,KviKvsCoreFunctionExecRoutine> it(*m_pCoreFunctionExecRoutineDict);
+ int l = szFunctionBegin.length();
+ while(it.current())
+ {
+ if(KviQString::equalCIN(szFunctionBegin,it.currentKey(),l))
+ {
+ QString * pMatch = new QString(it.currentKey());
+ //pMatch->prepend("$");
+ pMatches->append(pMatch);
+ }
+ ++it;
+ }
+
+ KviPointerList<QString> lModules;
+ lModules.setAutoDelete(true);
+ g_pModuleManager->completeModuleNames(szFunctionBegin,&lModules);
+ QString szEmpty = "";
+ for(QString * pszModuleName = lModules.first();pszModuleName;pszModuleName = lModules.next())
+ completeModuleFunction(*pszModuleName,szEmpty,pMatches);
+
+ KviPointerList<QString> lAliases;
+ lAliases.setAutoDelete(true);
+
+ KviKvsAliasManager::instance()->completeCommand(szFunctionBegin,&lAliases);
+ for(QString * pszAlias = lAliases.first();pszAlias;pszAlias = lAliases.next())
+ {
+ QString * pszAliasMatch = new QString(*pszAlias);
+ //pszAliasMatch->prepend("$");
+ pMatches->append(pszAliasMatch);
+ }
+ } else {
+ // contains a module name
+ QString szModuleName = szFunctionBegin.left(idx);
+ QString szRight = szFunctionBegin.right(szFunctionBegin.length() - (idx+1));
+ completeModuleFunction(szModuleName,szRight,pMatches);
+ }
+
+
+}
+
+void KviKvsKernel::completeModuleFunction(const QString &szModuleName,const QString &szCommandBegin,KviPointerList<QString> * pMatches)
+{
+ KviModule * pModule = g_pModuleManager->getModule(szModuleName.latin1());
+ if(!pModule)return;
+
+ KviPointerList<QString> lModuleMatches;
+ lModuleMatches.setAutoDelete(true);
+ pModule->completeFunction(szCommandBegin,&lModuleMatches);
+ for(QString * pszModuleMatch = lModuleMatches.first();pszModuleMatch;pszModuleMatch = lModuleMatches.next())
+ {
+ QString * pszMatch = new QString(*pszModuleMatch);
+ pszMatch->prepend(".");
+ pszMatch->prepend(szModuleName);
+ //pszMatch->prepend("$");
+ pMatches->append(pszMatch);
+ }
+}
diff --git a/src/kvirc/kvs/kvi_kvs_kernel.h b/src/kvirc/kvs/kvi_kvs_kernel.h
new file mode 100644
index 00000000..a6f8eb2c
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_kernel.h
@@ -0,0 +1,134 @@
+#ifndef _KVI_KVS_KERNEL_H_
+#define _KVI_KVS_KERNEL_H_
+//=============================================================================
+//
+// File : kvi_kvs_kernel.h
+// Creation date : Tue 30 Sep 2003 13.46 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#include "kvi_kvs_parser.h"
+#include "kvi_pointerlist.h"
+#include "kvi_qstring.h"
+
+#include "kvi_pointerhashtable.h"
+
+class KviKvsTreeNodeSpecialCommand;
+class KviKvsObjectController;
+class KviKvsAsyncOperationManager;
+class KviKvsRunTimeContext;
+class KviKvsVariantList;
+class KviKvsSwitchList;
+class KviKvsVariant;
+class KviKvsScript;
+class KviKvsHash;
+
+
+typedef KviKvsTreeNodeCommand * (KviKvsParser::*specialCommandParsingRoutine)();
+typedef struct _KviKvsSpecialCommandParsingRoutine
+{
+ specialCommandParsingRoutine proc;
+} KviKvsSpecialCommandParsingRoutine;
+
+typedef bool (*coreSimpleCommandExecRoutine)(KviKvsRunTimeContext * c,KviKvsVariantList * pParams,KviKvsSwitchList * pSwitches);
+typedef struct _KviKvsCoreSimpleCommandExecRoutine
+{
+ coreSimpleCommandExecRoutine proc;
+} KviKvsCoreSimpleCommandExecRoutine;
+
+typedef bool (*coreFunctionExecRoutine)(KviKvsRunTimeContext * c,KviKvsVariantList * pParams,KviKvsVariant * pRetBuffer);
+typedef struct _KviKvsCoreFunctionExecRoutine
+{
+ coreFunctionExecRoutine proc;
+} KviKvsCoreFunctionExecRoutine;
+
+typedef bool (*coreCallbackCommandExecRoutine)(KviKvsRunTimeContext * c,KviKvsVariantList * pParams,KviKvsSwitchList * pSwitches,const KviKvsScript * pCallback);
+typedef struct _KviKvsCoreCallbackCommandExecRoutine
+{
+ coreCallbackCommandExecRoutine proc;
+} KviKvsCoreCallbackCommandExecRoutine;
+
+
+class KVIRC_API KviKvsKernel
+{
+public:
+ KviKvsKernel();
+ ~KviKvsKernel();
+private:
+ static KviKvsKernel * m_pKvsKernel; // global kernel object
+
+ KviPointerHashTable<QString,KviKvsSpecialCommandParsingRoutine> * m_pSpecialCommandParsingRoutineDict;
+
+ KviPointerHashTable<QString,KviKvsCoreSimpleCommandExecRoutine> * m_pCoreSimpleCommandExecRoutineDict;
+ KviPointerHashTable<QString,KviKvsCoreCallbackCommandExecRoutine> * m_pCoreCallbackCommandExecRoutineDict;
+ KviPointerHashTable<QString,KviKvsCoreFunctionExecRoutine> * m_pCoreFunctionExecRoutineDict;
+
+ KviKvsHash * m_pGlobalVariables;
+ KviKvsVariantList * m_pEmptyParameterList;
+
+ KviKvsObjectController * m_pObjectController;
+ KviKvsAsyncOperationManager * m_pAsyncOperationManager;
+public:
+ static void init();
+ static void done();
+ static KviKvsKernel * instance(){ return m_pKvsKernel; };
+
+ KviKvsVariantList * emptyParameterList(){ return m_pEmptyParameterList; };
+
+ KviKvsHash * globalVariables(){ return m_pGlobalVariables; };
+
+ KviKvsObjectController * objectController(){ return m_pObjectController; };
+
+ KviKvsAsyncOperationManager * asyncOperationManager(){ return m_pAsyncOperationManager; };
+
+ void registerSpecialCommandParsingRoutine(const QString &szCmdName,KviKvsSpecialCommandParsingRoutine * r)
+ { m_pSpecialCommandParsingRoutineDict->replace(szCmdName,r); };
+ KviKvsSpecialCommandParsingRoutine * findSpecialCommandParsingRoutine(const QString &szCmdName)
+ { return m_pSpecialCommandParsingRoutineDict->find(szCmdName); };
+
+ void registerCoreSimpleCommandExecRoutine(const QString &szCmdName,KviKvsCoreSimpleCommandExecRoutine * r)
+ { m_pCoreSimpleCommandExecRoutineDict->replace(szCmdName,r); };
+ KviKvsCoreSimpleCommandExecRoutine * findCoreSimpleCommandExecRoutine(const QString &szCmdName)
+ { return m_pCoreSimpleCommandExecRoutineDict->find(szCmdName); };
+
+ void registerCoreFunctionExecRoutine(const QString &szFncName,KviKvsCoreFunctionExecRoutine * r)
+ { m_pCoreFunctionExecRoutineDict->replace(szFncName,r); };
+ KviKvsCoreFunctionExecRoutine * findCoreFunctionExecRoutine(const QString &szFncName)
+ { return m_pCoreFunctionExecRoutineDict->find(szFncName); };
+
+ void registerCoreCallbackCommandExecRoutine(const QString &szCmdName,KviKvsCoreCallbackCommandExecRoutine * r)
+ { m_pCoreCallbackCommandExecRoutineDict->replace(szCmdName,r); };
+ KviKvsCoreCallbackCommandExecRoutine * findCoreCallbackCommandExecRoutine(const QString &szCmdName)
+ { return m_pCoreCallbackCommandExecRoutineDict->find(szCmdName); };
+
+ void completeCommand(const QString &szCommandBegin,KviPointerList<QString> * pMatches);
+ void completeFunction(const QString &szFunctionBegin,KviPointerList<QString> * pMatches);
+ void completeModuleCommand(const QString &szModuleName,const QString &szCommandBegin,KviPointerList<QString> * matches);
+ void completeModuleFunction(const QString &szModuleName,const QString &szFunctionBegin,KviPointerList<QString> * matches);
+/*
+ KviPointerList<QString> * completeCommandAllocateResult(const QString &szCommandBegin);
+ KviPointerList<QString> * completeFunctionAllocateResult(const QString &szFunctionBegin);
+ void freeCompletionResult(KviPointerList<QString> * l);
+*/
+};
+
+#endif //!_KVI_KVS_KERNEL_H_
diff --git a/src/kvirc/kvs/kvi_kvs_moduleinterface.cpp b/src/kvirc/kvs/kvi_kvs_moduleinterface.cpp
new file mode 100644
index 00000000..911eb8c0
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_moduleinterface.cpp
@@ -0,0 +1,180 @@
+//=============================================================================
+//
+// File : kvi_kvs_moduleinterface.cpp
+// Created on Tue 16 Dec 2003 00:27:54 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003-2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_moduleinterface.h"
+#include "kvi_kvs_eventmanager.h"
+#include "kvi_module.h"
+#include "kvi_modulemanager.h"
+#include "kvi_locale.h"
+#include "kvi_kvs_treenode_data.h"
+#include "kvi_kvs_treenode_datalist.h"
+
+bool KviKvsModuleCallbackCommandCall::getParameterCode(unsigned int uParamIdx,QString &szParamBuffer)
+{
+ if(!m_pParameterDataList)return false;
+ KviKvsTreeNodeData * d = m_pParameterDataList->item(uParamIdx);
+ if(!d)return false;
+ const QChar * pBegin = d->location();
+ const QChar * pEnd = d->endingLocation();
+ if(!(pBegin && pEnd))return false;
+ szParamBuffer.setUnicode(pBegin,pEnd - pBegin);
+ szParamBuffer.stripWhiteSpace();
+ return true;
+}
+
+
+KviKvsModuleInterface::KviKvsModuleInterface()
+{
+ m_pModuleSimpleCommandExecRoutineDict = new KviPointerHashTable<QString,KviKvsModuleSimpleCommandExecRoutine>(17,false);
+ m_pModuleSimpleCommandExecRoutineDict->setAutoDelete(true);
+ m_pModuleFunctionExecRoutineDict = new KviPointerHashTable<QString,KviKvsModuleFunctionExecRoutine>(17,false);
+ m_pModuleFunctionExecRoutineDict->setAutoDelete(true);
+ m_pModuleCallbackCommandExecRoutineDict = new KviPointerHashTable<QString,KviKvsModuleCallbackCommandExecRoutine>(17,false);
+ m_pModuleCallbackCommandExecRoutineDict->setAutoDelete(true);
+}
+
+KviKvsModuleInterface::~KviKvsModuleInterface()
+{
+ kvsUnregisterAllEventHandlers();
+ delete m_pModuleSimpleCommandExecRoutineDict;
+ delete m_pModuleFunctionExecRoutineDict;
+ delete m_pModuleCallbackCommandExecRoutineDict;
+}
+
+#define COMPLETE_WORD_BY_DICT(__word,__list,__type,__dict) \
+ { \
+ KviPointerHashTableIterator<QString,__type> it(*__dict); \
+ int l = __word.length(); \
+ while(it.current()) \
+ { \
+ if(KviQString::equalCIN(__word,it.currentKey(),l)) \
+ __list->append(new QString(it.currentKey())); \
+ ++it; \
+ } \
+ }
+
+void KviKvsModuleInterface::completeCommand(const QString &szCommandBegin,KviPointerList<QString> * pMatches)
+{
+ COMPLETE_WORD_BY_DICT(szCommandBegin,pMatches,KviKvsModuleSimpleCommandExecRoutine,m_pModuleSimpleCommandExecRoutineDict)
+ COMPLETE_WORD_BY_DICT(szCommandBegin,pMatches,KviKvsModuleCallbackCommandExecRoutine,m_pModuleCallbackCommandExecRoutineDict)
+}
+
+void KviKvsModuleInterface::completeFunction(const QString &szFunctionBegin,KviPointerList<QString> * pMatches)
+{
+ COMPLETE_WORD_BY_DICT(szFunctionBegin,pMatches,KviKvsModuleFunctionExecRoutine,m_pModuleFunctionExecRoutineDict)
+}
+
+
+void KviKvsModuleInterface::kvsRegisterSimpleCommand(const QString &szCommand,KviKvsModuleSimpleCommandExecRoutine r)
+{
+ m_pModuleSimpleCommandExecRoutineDict->replace(szCommand,new KviKvsModuleSimpleCommandExecRoutine(r));
+}
+
+void KviKvsModuleInterface::kvsRegisterCallbackCommand(const QString &szCommand,KviKvsModuleCallbackCommandExecRoutine r)
+{
+ m_pModuleCallbackCommandExecRoutineDict->replace(szCommand,new KviKvsModuleCallbackCommandExecRoutine(r));
+}
+
+void KviKvsModuleInterface::kvsRegisterFunction(const QString &szFunction,KviKvsModuleFunctionExecRoutine r)
+{
+ m_pModuleFunctionExecRoutineDict->replace(szFunction,new KviKvsModuleFunctionExecRoutine(r));
+}
+
+
+bool KviKvsModuleInterface::kvsRegisterAppEventHandler(unsigned int iEventIdx,KviKvsModuleEventHandlerRoutine r)
+{
+ KviKvsModuleEventHandler * h = new KviKvsModuleEventHandler(this,r);
+ if(!KviKvsEventManager::instance()->addAppHandler(iEventIdx,h))
+ {
+ delete h;
+ return false;
+ }
+ return true;
+}
+
+bool KviKvsModuleInterface::kvsRegisterRawEventHandler(unsigned int iRawIdx,KviKvsModuleEventHandlerRoutine r)
+{
+ KviKvsModuleEventHandler * h = new KviKvsModuleEventHandler(this,r);
+ if(!KviKvsEventManager::instance()->addRawHandler(iRawIdx,h))
+ {
+ delete h;
+ return false;
+ }
+ return true;
+}
+
+void KviKvsModuleInterface::kvsUnregisterAppEventHandler(unsigned int uEventIdx)
+{
+ KviKvsEventManager::instance()->removeModuleAppHandler(uEventIdx,this);
+}
+
+void KviKvsModuleInterface::kvsUnregisterRawEventHandler(unsigned int uRawIdx)
+{
+ KviKvsEventManager::instance()->removeModuleRawHandler(uRawIdx,this);
+}
+
+void KviKvsModuleInterface::kvsUnregisterAllAppEventHandlers()
+{
+ KviKvsEventManager::instance()->removeAllModuleAppHandlers(this);
+}
+
+void KviKvsModuleInterface::kvsUnregisterAllRawEventHandlers()
+{
+ KviKvsEventManager::instance()->removeAllModuleRawHandlers(this);
+}
+
+void KviKvsModuleInterface::kvsUnregisterAllEventHandlers()
+{
+ kvsUnregisterAllAppEventHandlers();
+ kvsUnregisterAllRawEventHandlers();
+}
+
+static bool default_module_kvs_cmd_load(KviKvsModuleCommandCall *)
+{
+ return true;
+}
+
+static bool default_module_kvs_cmd_unload(KviKvsModuleCommandCall *c)
+{
+ if(c->module()->isLocked())
+ {
+ if(!c->switches()->find('f',"force"))
+ {
+ c->warning(__tr2qs("Can't unload the module: it has locked itself in memory"));
+ return true;
+ }
+ }
+ g_pModuleManager->unloadModule(c->module()->name());
+ return true;
+}
+
+void KviKvsModuleInterface::registerDefaultCommands()
+{
+ kvsRegisterSimpleCommand("load",default_module_kvs_cmd_load);
+ kvsRegisterSimpleCommand("unload",default_module_kvs_cmd_unload);
+}
+
+
diff --git a/src/kvirc/kvs/kvi_kvs_moduleinterface.h b/src/kvirc/kvs/kvi_kvs_moduleinterface.h
new file mode 100644
index 00000000..ccfbaca7
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_moduleinterface.h
@@ -0,0 +1,228 @@
+#ifndef _KVI_KVS_MODULEINTERFACE_H_
+#define _KVI_KVS_MODULEINTERFACE_H_
+//=============================================================================
+//
+// File : kvi_kvs_moduleinterface.h
+// Created on Tue 16 Dec 2003 00:27:54 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+
+#include "kvi_settings.h"
+
+#include "kvi_pointerhashtable.h"
+
+#include "kvi_kvs_runtimecall.h"
+#include "kvi_kvs_parameterprocessor.h"
+#include "kvi_kvs_switchlist.h"
+#include "kvi_kvs_script.h"
+#include "kvi_pointerlist.h"
+#include "kvi_qstring.h"
+
+class KviModule;
+class KviKvsTreeNodeDataList;
+
+class KVIRC_API KviKvsModuleRunTimeCall : public KviKvsRunTimeCall
+{
+protected:
+ KviModule * m_pModule;
+public:
+ KviKvsModuleRunTimeCall(KviModule * pModule,
+ KviKvsRunTimeContext * pContext,
+ KviKvsVariantList * pParams)
+ : KviKvsRunTimeCall(pContext,pParams), m_pModule(pModule) {}
+ ~KviKvsModuleRunTimeCall(){};
+public:
+ KviModule * module(){ return m_pModule; };
+};
+
+class KVIRC_API KviKvsModuleEventCall : public KviKvsModuleRunTimeCall
+{
+public:
+ KviKvsModuleEventCall(KviModule * pModule,
+ KviKvsRunTimeContext * pContext,
+ KviKvsVariantList * pParams)
+ : KviKvsModuleRunTimeCall(pModule,pContext,pParams){};
+ ~KviKvsModuleEventCall(){};
+};
+
+class KVIRC_API KviKvsModuleCommandCall : public KviKvsModuleRunTimeCall
+{
+protected:
+ KviKvsSwitchList * m_pSwitchList;
+public:
+ KviKvsModuleCommandCall(KviModule * pModule,
+ KviKvsRunTimeContext * pContext,
+ KviKvsVariantList * pParams,
+ KviKvsSwitchList * pSwitches)
+ : KviKvsModuleRunTimeCall(pModule,pContext,pParams), m_pSwitchList(pSwitches){};
+ ~KviKvsModuleCommandCall(){};
+public:
+ KviKvsSwitchList * switches(){ return m_pSwitchList; };
+ KviKvsSwitchList * switchList(){ return m_pSwitchList; };
+
+ // forwarders for the switch list
+ bool hasSwitch(unsigned short u,const QString &szSwitch){ return (m_pSwitchList->find(u,szSwitch) != 0); };
+ KviKvsVariant * getSwitch(unsigned short u,const QString &szSwitch){ return m_pSwitchList->find(u,szSwitch); };
+};
+
+class KVIRC_API KviKvsModuleCallbackCommandCall : public KviKvsModuleCommandCall
+{
+protected:
+ const KviKvsScript * m_pCallback;
+ KviKvsTreeNodeDataList * m_pParameterDataList; // core subtree that rappresents the parameter list
+public:
+ KviKvsModuleCallbackCommandCall(KviModule * pModule,
+ KviKvsRunTimeContext * pContext,
+ KviKvsVariantList * pParams,
+ KviKvsSwitchList * pSwitches,
+ const KviKvsScript * pCallback,
+ KviKvsTreeNodeDataList * pDataList)
+ : KviKvsModuleCommandCall(pModule,pContext,pParams,pSwitches), m_pCallback(pCallback), m_pParameterDataList(pDataList) {};
+ ~KviKvsModuleCallbackCommandCall(){};
+public:
+ // Never NULL, but may have empty code
+ const KviKvsScript * callback(){ return m_pCallback; };
+ virtual bool getParameterCode(unsigned int uParamIdx,QString &szParamBuffer);
+};
+
+
+class KVIRC_API KviKvsModuleFunctionCall : public KviKvsModuleRunTimeCall
+{
+ friend class KviKvsTreeNodeModuleFunctionCall;
+protected:
+ KviKvsVariant * m_pResult;
+public:
+ KviKvsModuleFunctionCall(KviModule * pModule,
+ KviKvsRunTimeContext * pContext,
+ KviKvsVariantList * pParams,
+ KviKvsVariant * pResult)
+ : KviKvsModuleRunTimeCall(pModule,pContext,pParams), m_pResult(pResult)
+ {};
+ ~KviKvsModuleFunctionCall(){};
+public:
+ KviKvsVariant * returnValue(){ return m_pResult; };
+};
+
+
+
+typedef bool (*KviKvsModuleSimpleCommandExecRoutine)(KviKvsModuleCommandCall * c);
+typedef bool (*KviKvsModuleFunctionExecRoutine)(KviKvsModuleFunctionCall * c);
+typedef bool (*KviKvsModuleCallbackCommandExecRoutine)(KviKvsModuleCallbackCommandCall * c);
+typedef bool (*KviKvsModuleEventHandlerRoutine)(KviKvsModuleEventCall * c);
+
+
+
+class KVIRC_API KviKvsModuleInterface
+{
+ friend class KviKvsModuleManager;
+public:
+ KviKvsModuleInterface();
+ ~KviKvsModuleInterface();
+protected:
+ KviPointerHashTable<QString,KviKvsModuleSimpleCommandExecRoutine> * m_pModuleSimpleCommandExecRoutineDict;
+ KviPointerHashTable<QString,KviKvsModuleFunctionExecRoutine> * m_pModuleFunctionExecRoutineDict;
+ KviPointerHashTable<QString,KviKvsModuleCallbackCommandExecRoutine> * m_pModuleCallbackCommandExecRoutineDict;
+public:
+ void kvsRegisterSimpleCommand(const QString &szCommand,KviKvsModuleSimpleCommandExecRoutine r);
+ void kvsRegisterCallbackCommand(const QString &szCommand,KviKvsModuleCallbackCommandExecRoutine r);
+ void kvsRegisterFunction(const QString &szFunction,KviKvsModuleFunctionExecRoutine r);
+ bool kvsRegisterAppEventHandler(unsigned int iEventIdx,KviKvsModuleEventHandlerRoutine r);
+ bool kvsRegisterRawEventHandler(unsigned int iRawIdx,KviKvsModuleEventHandlerRoutine r);
+
+ void kvsUnregisterSimpleCommand(const QString &szCommand)
+ { m_pModuleSimpleCommandExecRoutineDict->remove(szCommand); };
+ void kvsUnregisterCallbackCommand(const QString &szCommand)
+ { m_pModuleCallbackCommandExecRoutineDict->remove(szCommand); };
+ void kvsUnregisterFunction(const QString &szFunction)
+ { m_pModuleFunctionExecRoutineDict->remove(szFunction); };
+ void kvsUnregisterAppEventHandler(unsigned int iEventIdx);
+ void kvsUnregisterRawEventHandler(unsigned int iRawIdx);
+
+ void kvsUnregisterAllSimpleCommands()
+ { m_pModuleSimpleCommandExecRoutineDict->clear(); };
+ void kvsUnregisterAllCallbackCommands()
+ { m_pModuleCallbackCommandExecRoutineDict->clear(); };
+ void kvsUnregisterAllFunctions()
+ { m_pModuleFunctionExecRoutineDict->clear(); };
+ void kvsUnregisterAllAppEventHandlers();
+ void kvsUnregisterAllRawEventHandlers();
+ void kvsUnregisterAllEventHandlers();
+
+ KviKvsModuleSimpleCommandExecRoutine * kvsFindSimpleCommand(const QString &szCommand)
+ { return m_pModuleSimpleCommandExecRoutineDict->find(szCommand); };
+ KviKvsModuleCallbackCommandExecRoutine * kvsFindCallbackCommand(const QString &szCommand)
+ { return m_pModuleCallbackCommandExecRoutineDict->find(szCommand); };
+ KviKvsModuleFunctionExecRoutine * kvsFindFunction(const QString &szFunction)
+ { return m_pModuleFunctionExecRoutineDict->find(szFunction); };
+
+ void completeCommand(const QString &cmd,KviPointerList<QString> * matches);
+ void completeFunction(const QString &cmd,KviPointerList<QString> * matches);
+protected:
+ void registerDefaultCommands();
+};
+
+
+
+#define KVSM_REGISTER_SIMPLE_COMMAND(_pModule,_szCmd,_procname) \
+ _pModule->kvsRegisterSimpleCommand(_szCmd,_procname);
+
+#define KVSM_UNREGISTER_SIMPLE_COMMAND(_pModule,_szCmd) \
+ _pModule->kvsUnregisterSimpleCommand(_szCmd);
+
+#define KVSM_REGISTER_CALLBACK_COMMAND(_pModule,_szCmd,_procname) \
+ _pModule->kvsRegisterCallbackCommand(_szCmd,_procname);
+
+#define KVSM_UNREGISTER_CALLBACK_COMMAND(_pModule,_szCmd) \
+ _pModule->kvsUnregisterCallbackCommand(_szCmd);
+
+#define KVSM_REGISTER_FUNCTION(_pModule,_szFnc,_procname) \
+ _pModule->kvsRegisterFunction(_szFnc,_procname); \
+
+#define KVSM_UNREGISTER_FUNCTION(_pModule,_szFnc) \
+ _pModule->kvsUnregisterFunction(_szFnc);
+
+#define KVSM_UNREGISTER_ALL_SIMPLE_COMMANDS(_pModule) \
+ _pModule->kvsUnregisterAllSimpleCommands();
+
+#define KVSM_UNREGISTER_ALL_CALLBACK_COMMANDS(_pModule) \
+ _pModule->kvsUnregisterAllCallbackCommands();
+
+#define KVSM_UNREGISTER_ALL_FUNCTIONS(_pModule) \
+ _pModule->kvsUnregisterAllFunctions();
+
+
+#define KVSM_PARAMETER(a,b,c,d) KVS_PARAMETER(a,b,c,d)
+#define KVSM_PARAMETER_IGNORED(a) KVS_PARAMETER_IGNORED(a)
+
+#define KVSM_PARAMETERS_BEGIN(pCall) \
+ KVS_PARAMETERS_BEGIN(parameter_format_list)
+
+#define KVSM_PARAMETERS_END(pCall) \
+ KVS_PARAMETERS_END \
+ if(!KviKvsParameterProcessor::process(pCall->params(),pCall->context(),parameter_format_list))return false;
+
+#define KVSM_REQUIRE_CONNECTION(pCall) \
+ if(!pCall->window()->context())return c->context()->errorNoIrcContext(); \
+ if(!pCall->window()->connection())return c->context()->warningNoIrcConnection();
+
+
+
+#endif //!_KVI_KVS_MODULEINTERFACE_H_
diff --git a/src/kvirc/kvs/kvi_kvs_object.cpp b/src/kvirc/kvs/kvi_kvs_object.cpp
new file mode 100644
index 00000000..0447cfd9
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_object.cpp
@@ -0,0 +1,1743 @@
+//=============================================================================
+//
+// File : kvi_kvs_object.cpp
+// Created on Wed 08 Oct 2003 02:31:57 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_object.h"
+#include "kvi_kvs_hash.h"
+#include "kvi_kvs_kernel.h"
+#include "kvi_window.h"
+#include "kvi_app.h"
+
+#include "kvi_modulemanager.h"
+#include "kvi_console.h"
+#include "kvi_locale.h"
+#include "kvi_error.h"
+#include "kvi_out.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_iconmanager.h"
+#include "kvi_malloc.h"
+
+#include "kvi_kvs_object_controller.h"
+#include "kvi_kvs_object_functioncall.h"
+#include "kvi_kvs_object_functionhandlerimpl.h"
+
+#include <qmetaobject.h>
+#include <qtimer.h>
+#include <time.h>
+#include <qiconset.h>
+
+
+
+/*
+ @doc: objects
+ @title:
+ Object scripting
+ @short:
+ Object scripting overview
+ @keyterms:
+ objects , object scripting , complex data structures
+ @body:
+ [big]Introduction[/big]
+
+ The KVIrc scripting language is not object oriented in nature.
+ Anyway , objects are a highlevel abstraction that allow
+ to write complex code in a "clean" way.
+ So I've added at least some pseudo-object support.[br][br]
+
+ [big]Basic concepts[/big]
+
+ Objects are arranged in tree structures.
+ Each object that you create is either toplevel object or a children
+ of another object. A toplevel object is a parentless one.
+ Obviously all objects can have children objects.[br][br]
+
+ When an object is destroyed , all its children are also destroyed.
+ The toplevel objects are automatically destroyed when KVIrc quits.
+ The objects are global to the entire application (this is different
+ from previous KVIrc releases where the objects were local
+ to the current frame window and arranged in a single tree
+ with a builtin root object).[br][br]
+
+ Each object is an instance of a class that defines its features.
+ Each object has also a name , that is not necessary unique and is assigned
+ by the programmer; the name is just a mnemonic expedient, and
+ you may also not need it.[br][br]
+
+ Each object is identified by an [b]OPAQUE UNIQUE ID[/b].
+ The ID is assigned by KVIrc and can be held in any variable.
+ You can think the object id as a "handle for the object" or the object's pointer.
+ Any action performed on the object will require its ID.[br][br]
+
+ [big]Creation and destruction[/big]
+
+ To create an object you must use the [fnc]$new[/fnc]()
+ function. [fnc]$new[/fnc]() requires three parameters:[br]
+ - The object class (more about object classes later in this document)[br]
+ - The ID of the parent object , (that can be 0 for toplevel objects).[br]
+ - The object name (eventually empty)[br]
+ [example]
+ %myobject = [fnc]$new[/fnc]([class]object[/class],0,theName)
+ [/example]
+ [fnc]$new[/fnc]() returns the ID of the newly created object, or
+ the STRING "0" if the object creation fails
+ (it is a string because the object id's are generally strings, and 0 is an "invalid object id").
+ In well written scripts it is not common that the object creation fails, anyway
+ you can check if the creation has failed in the following way:[br]
+ [example]
+ [cmd]if[/cmd](%myobject)[cmd]echo[/cmd] "Object created!"
+ else [cmd]echo[/cmd] "Object creation failed!"
+ [/example]
+ You can also test the object ID's for equality:[br]
+ [example]
+ [cmd]if[/cmd](%myobject == %anotherobject)[cmd]echo[/cmd] "This is the same object!";
+ [/example]
+ The parent object id is optional, if not specified it is assumed to be 0.
+ The object name is optional , but it may help you later in finding the object.[br][br]
+
+ To destroy an object use the [cmd]delete[/cmd] command. (In previous versions
+ this command was named "destroy" and delete is currently aliased to that name too).[br]
+ [example]
+ [cmd]delete[/cmd] %myobject
+ [/example]
+ If the destroyed object has children objects , these are destroyed too.[br][br]
+
+ [big]Fields : objects as pseudo-structures[/big]
+
+ All the objects can contain variable fields.
+ You can set an object's field by using the object scope operator "->":[br]
+ [example]
+ %myobject-&gt;%fieldVariable = dataString
+ [/example]
+ To unset a field set it with empty data string (just like with a normal variable).
+ To retrieve the field data use the object scope operator in the same way:[br]
+ [example]
+ [cmd]echo[/cmd] %myobject->%fieldVariable
+ [/example]
+ The '-&gt;' operator has been stolen from the C language.
+ In the KVIrc scripting language it switches from the global namespace
+ to the object's one.[br]
+ So in the above example %fieldVariable is owned by the object.[br]
+ The first character of the variable name has no special meaning in the
+ object namespace (in the global namespace the variables starting
+ with an uppercase letter are global to the application , the other ones are local
+ to the command sequence). The variable names are completely case insensitive.[br][br]
+
+ Any [doc:operators]operator[/doc] can be used with the object field variables:[br]
+ [example]
+ %myobject-&gt;%fieldVariable = 0
+ %myobject-&gt;%fieldVarialbe ++
+ [cmd]if[/cmd]0(%myobject->%fieldVariable != 1)[cmd]echo[/cmd] KVIrc is drunk , maybe a reboot will help ?
+ [/example]
+ You can simulate C structures "on the fly" by using objects and fields:[br]
+ [example]
+ # Create an user description on the fly
+ %myobj = [fnc]$new[/fnc]([class]object[/class],0,userDescription)
+ # Set the fields
+ %myobj-&gt;%nickname = Pragma
+ %myobj-&gt;%username = daemon
+ %myobj-&gt;%hostname = pippo.pragma.org
+ %myobj-&gt;%info = Pragma goes always sleep too late
+ %myobj-&gt;%info [doc:operators]&lt;&lt;[/doc] and wakes up too late too!
+ # Call an (user defined) alias that stores the data to a file
+ storetofile %myobj
+ # Destroy the object
+ [cmd]delete[/cmd] %myobj
+ [/example]
+ The field variables can be also dictionaries:[br]
+ [example]
+ %theobj-&gt;%field[key] = something
+ [/example]
+ Unlike in C , there is no need to declare object fields.
+ Any object can have any field variable ; an "unset" field is equivalent to an "empty" field.[br]
+ Note:[br]
+ The KVIrc scripting language is not typed.
+ Any object class (be patient...I'll explain classes in a while) identifier can be stored in any KVIrc variable:
+ it is not possible to find out the object features by "examining" its identifier.
+ This may make the usage of objects a bit "unclear";
+ Howewer , with some experience you will be able to use the objects in a very powerful way.
+ The type-safety can be also simulated by a careful usage of object names;
+ in the above example , the %myobj object was created with the "userDescription" name.
+ The storetofile alias could check the passed object's name and refuse to work
+ if that does not match "userDescription".[br][br]
+
+ A more complex use of fields will be described later in this document.[br][br]
+
+ [big]Member functions[/big]
+
+ Just like in C++ , the objects have member functions.
+ For example , the "object" class (again...read on) objects export the [classfnc:object]$name[/classfnc]()
+ and [classfnc:object]$className[/classfnc]() functions.[br]
+ [example]
+ %tmp = [fnc]$new[/fnc]([class]object[/class],0,myobject)
+ [cmd]echo[/cmd] The object's name is %tmp->[classfnc:object]$name[/classfnc]() , the class name is %tmp->[classfnc:object]$className[/classfnc]()
+ # Destroy the object
+ [cmd]delete[/cmd] %tmp
+ [/example]
+ Another cool function exported by the [class:object]object[/class] class is the
+ [classfnc:object]$children[/classfnc]() function.
+ It returns a comma separated list of children identifiers.[br]
+ [example]
+ %tmp = [fnc]$new[/fnc]([class]object[/class],0,myobject)
+ %tmpchild = [fnc]$new[/fnc]([class]object[/class],%tmp,child1)
+ %tmpchild = [fnc]$new[/fnc]([class]object[/class],%tmp,child2)
+ %tmpchild = [fnc]$new[/fnc]([class]object[/class],%tmp,child3)
+ [cmd]echo[/cmd] The object's children list is : %tmp->[classfnc:object]$children[/classfnc]()
+ # Destroy the object and the children
+ [cmd]delete[/cmd] %tmp
+ [/example]
+ There are two special functions for each objects: the "constructor" and the "destructor".
+ You will find more informations on constructors and destructors later in this document,
+ for now it's enough that you know that these functions are called automatically by KVirc:
+ the constructor is called when the object is created and the destructor is called when the
+ object is being destroyed with [cmd]delete[/cmd].[br][br]
+
+ The object functions can be reimplemented on-the-fly
+ by using the [cmd]privateimpl[/cmd] command: you can simply modify the behaviour of the function
+ by writing your own function body.
+ (This is an uncommon feature: unlike many other languages , you can reimplement object
+ functions at run-time, when the object has been already created.)[br][br]
+
+ A more complex example[br]
+ [example]
+ %tmp = [fnc]$new[/fnc]([class]object[/class],0,myobject)
+ [cmd]foreach[/cmd](%i,1,2,3)
+ {
+ %tmpchild = [fnc]$new[/fnc]([class]object[/class],%tmp,child%i)
+ [cmd]privateimpl[/cmd](%tmpchild,destructor){ [cmd]echo[/cmd] Object [fnc]$this[/fnc] ([fnc]$this[/fnc]-&gt;[classfnc:object]$name[/classfnc]()) destroyed; }
+ }
+ [cmd]privateimpl[/cmd](%tmp,destructor)
+ {
+ %count = 0;
+ [cmd]foreach[/cmd](%t,[fnc]$this[/fnc]-&gt;[classfnc:object]$children[/classfnc]())
+ {
+ [cmd]echo[/cmd] Children : %t-&gt;[classfnc:object]$name[/classfnc]() with class %t-&gt;[classfnc:object]$class[/classfnc]()
+ %count++
+ }
+ [cmd]echo[/cmd] Just before destroying my %count children.
+ }
+ # Destroy the object and the children
+ [cmd]delete[/cmd] %tmp
+ [/example]
+
+ In the example above four objects have been created.
+ A "parent" object named "myobject" , and three children objects.
+ The destructor has been reimplemented for each child object,
+ to make it "say" its name (Please note the usage of [fnc]$this[/fnc]).
+ In the parent destructor the children have been counted and listed.[br]
+ Then the parent object is destroyed causing to:[br]
+ - trigger the parent destructor.[br]
+ - destroy all the children (and conseguently trigger all the "individual" destructors).[br][br]
+
+ Not all the object functions must return a value:
+ If a function does not return a meaningful value , or you just want to ignore it , you can call it in the following way:[br]
+ [example]
+ %anyobject-&gt;$functionname()
+ [/example]
+ [br]
+
+ [big]Classes[/big]
+ As said before , all objects are instances of a specific class.
+ This concept is common to almost all object oriented languages.
+ A class is a collection of methods that define an object's behaviour.
+ Hehe...it is not easy to explain it , so I'll try with an example:[br]
+ [example]
+ class HostAddress
+ {
+ field hostname
+ function ipnumber()
+ function isLocalhost()
+ }
+ [/example]
+ The above class is a rappresentation of a host address.
+ You create an [b]instance of this class[/b] and set the hostname field, for example,
+ to www.kernel.org.
+ The object is now able to give you informations about the hostname in a transparent way:
+ You can call the ipnumber() function, and the object will return you the
+ digits and dots rappresentation of www.kernel.org.
+ The isLocalhost() function will return true if the hostname refers to the local machine
+ The object internal job is hidden from the user , but probably it will be a huge job.
+ To obtain the IP number from the hostname , the object will probably have to perform a DNS call (usually a complex task).
+ To check if the hostname references the local machine , the object will have to obtain the local hostname
+ from the system (in some "unspecified" way) and then compare it with the given "hostname" field.[br][br]
+
+ The internal job of the object is defined by the "implementation of the class".
+ Obviously , the programmer that creates the class has to write that implementation.[br]
+
+ [example]
+ class HostAddress
+ {
+ field hostname
+ function ipnumber()
+ {
+ find the nearest DNS server
+ make the dns call
+ wait for the response
+ decode the response
+ }
+ function isLocalhost()
+ {
+ query the kernel for the local hostname
+ compare the obtained hostname with the hostname field
+ }
+ }
+ [/example]
+ In the above example I have "implemented" the two functions by using a "fantastic" language.[br][br]
+
+ Let's go back to the real world.[br][br]
+
+ KVirc contains a [doc:classes]set of built-in ready-to-use classes[/doc].
+ The basic class is [class]object[/class]: all the other classes are derived from this (more about
+ object inheritance later in this doc).[br][br]
+
+ Another available class is [class]socket[/class] that is an interface to the real system sockets.
+ An instance of the [class]socket[/class] class can connect and communicate with other hosts on the net.[br][br]
+
+ The [b]class definitions are GLOBAL to the entire application[/b]: all server windows share them.[br][br]
+
+ So now we can say that in KVIrc
+ [b]a CLASS is a collection of features that define the behaviour of an object.
+ The user interface to the class are the member functions and the events.[/b][br][br]
+
+ [big]Inheritance[/big]
+
+ Someone asked for derived classes ?[br]
+ Here we go:[br]
+ The [cmd]class[/cmd] command allows you to define new object classes.
+ In KVI++, A new class must be always derived from some other class: the lowest possible
+ level of inheritance is 1: deriving from class [class]object[/class].[br]
+ [example]
+ [cmd]class[/cmd](helloworld,object)
+ {
+ sayhello()
+ {
+ [cmd]echo[/cmd] Hello world!
+ }
+ }
+ [/example]
+
+ The above class is named "helloworld". It inherits the [class]object[/class] class.
+ This means that it acquires all the [class]object[/class] fuunctions: [classfnc:object]$name[/classfnc]() ,
+ [classfnc:object]$class[/class]() , [classfnc:object]$children[/classfnc]()...
+ Additionally , it has the $sayhello() function, that "echoes Hello world" to the console.
+ Now you can create an instance of this class:
+ [example]
+ %instance = [fnc]$new[/fnc](helloworld)
+ %instance->$sayhello()
+ [/example]
+ You should see "Hello world" printed in the console.
+ Easy job...let's make the things a bit more complex now:
+ derive another class from helloworld and make it say "hello" in two different languages:[br]
+ [example]
+ [cmd]class[/cmd](localizedhelloworld,helloworld)
+ {
+ [comment]# define the setlanguage function[/comment]
+ [comment]# note that <$0 = language> is just a programmer reminder[/comment]
+ setlanguage(<$0 = language>)
+ {
+ [cmd]if[/cmd](($0 == english) || ($0 == italian))
+ {
+ [fnc:$this]$$[/fnc]->%lang = $0
+ [cmd]return[/cmd] 1
+ } else {
+ [cmd]echo[/cmd] I don't know that language ($0)
+ [cmd]echo[/cmd] defaulting to english
+ [fnc:$this]$$[/fnc]->%lang = english
+ [cmd]return[/cmd] 0
+ }
+ }
+
+ sayhello()
+ {
+ [cmd]if[/cmd]([fnc:$this]$$[/fnc]->%lang == italian)[cmd]echo[/cmd] Ciao mondo!
+ else [fnc:$this]$$[/fnc]->$helloworld:sayhello()
+ }
+ }
+ [/example]
+ Now you can call:[br]
+ [example]
+ %m = [fnc]$new[/fnc](localizedhelloworld)
+ %m->$setLanguage(italian)
+ %m->$sayhello()
+ %m->$setLanguage(english)
+ %m->$sayhello()
+ %m->$setLanguage(turkish)
+ %m->$sayhello()
+ [cmd]delete[/cmd] %myobj
+ [/example]
+ The class defined above is inherited from the previously defined helloworld class:
+ so it inherits the "object" class functions and events and the sayhello function from "helloworld".
+ In addition a setlanguage function is defined that stores in a variable the language name passed
+ as a parameter (after checking its validity). ($0 evaluates to the first parameter passed)
+ If the language is unknown the setlanguage function will return 0 (false).
+ Now we want to be able to say "hello world" in italian and english.
+ So we [b]override[/b] the inherited sayhello function.
+ "To override" means "to reimplement" : if you call %object->$sayhello() and %object
+ contains the ID of an instance of class "localizedhelloworld" , the new implementation of that function willl be called (executed).
+ The inherited sayhello was able to say "hello world" only in english , so we can still use it in the new implementation
+ without rewriting its contents. So if the language set is "not italian" we assume that it is english and
+ call the [b]base class implementation[/b].[br]
+ [example]
+ [fnc]$this/[fnc]->$helloworld:sayhello()
+ [comment]# equivalent to $$->$helloworld:sayhello(),[/comment]
+ [comment]# to $this->$helloworld::sayhello(),[/comment]
+ [comment]# and to $$->$helloworld::sayhello()[/comment]
+ [/example]
+ otherwise the language is italian and we say "hello" in italian :).
+ So , to call a base class implementation of a function we "prepend" the base class name before the function name in the call.
+ The base class name could be also [class]object[/class] in this case , but the [class]object[/class] class has no "sayhello" function defined
+ so it would result in an error.[br][br]
+ In the above example , all the values of [fnc]$this[/fnc]</a>-&gt;%language
+ that are not equal to "italian" are assumed to be "english".
+ This is not always true , for example , just after the object creation the %language variable field
+ is effectively empty. The above class works correctly in this case , but we might want to have always
+ a coherent state of the field variables , so we need another concept: the class [b]constructor[/b]
+ that will be discussed in the next paragraph.[br][br]
+
+ Note: multiple inheritance (inheritance from more than one base class) is not implemented , KVIrc is not a compiler :)[br][br]
+
+ Objects are much more powerful....[br][br]
+
+ Do a [cmd]clearobjects[/cmd] to cleanup the old class definitions , and read on.[br][br]
+
+ [big]Constructors and destructors[/big]
+
+ The class constructor is a [b]function[/b] that is called automatically just after the object
+ has been created internally by KVIrc and just before the [fnc]$new[/fnc]
+ function returns. It should be used to setup the internal object state.[br]
+ Unlike in C++ , in KVIrc , the constructor CAN return a value:[br]
+ If it returns 0 it signals the object creation failure : the object
+ is immediately destroyed and [fnc]$new[/fnc]() returns 0 to the caller.
+ Any other return value is treated as success , so the object is effectively
+ created and [fnc]$new[/fnc]() returns its ID to the caller.[br]
+ All the builtin classes have a constructor defined that will almost never fail (only if we run out of memory),
+ so you can avoid to check the [fnc]$new[/fnc]() return value
+ when creating the instances of the built-in classes.[br][br]
+
+ In derived classes you can override the constructor to setup your object's state.[br]
+ You should [b]always call the base class constructor[/b] in your overridden one , to setup
+ the base class state , and propagate its return value (eventually modified if the base class
+ constructor is succesfull but your derived class initialization fails).[br]
+ In practice , the builtin class constructors do nothing other than setting the return
+ value to 1 so you can even avoid to call them, but in any other case you must do it.[br][br]
+
+ This is different from C (for example), where the constructors are called (more or less)
+ automatically.[br][br]
+
+ [big]Signals and slots[/big]
+
+ The signals and slots are a powerful mean of inter-object communication.
+ A signal is emitted by an object to notify a change in its state.
+ For example , the [class:button]button class[/class] emits the
+ [classsignal:button]clicked[/classsignal] signal when the user clicks the button.[br][br]
+ A signal is emitted by an object and can be received and handled by any other existing object
+ (including the object that emits the signal).[br]
+ The handler function for a signal is called "slot".[br]
+ It is just a convention : in fact , a slot is a normal object function (and any object function can be a slot).
+ More than one slot can be connected to a single signal , and more signals can be connected to a single slot.[br]
+ In this way , many objects can be notified of a change in a single object , as well as a single object
+ can easily handle state-changes for many objects.[br]
+ The signal / slot behaviour could be easily implemented by a careful usage of object functions.
+ [b]So why signals and slots ?[/b][br]
+ Because signals are much more powerful in many situations.
+ The signals have no equivalent in C/C++...but they have been implemented in many highlevel
+ C/C++ libraries and development kits (including the system-wide signal/handler mechanism implemented
+ by all the modern kernels and used in inter-process communication).[br]
+*/
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////
+
+/*
+ @doc: object
+ @keyterms:
+ object class, object, class
+ @title:
+ object class
+ @type:
+ class
+ @short:
+ Base class for all the KVIrc objects
+ @inherits:
+ none
+ @description:
+ This is the base class for all the builtin KVirc object classes.
+ It exports the functions to retrieve the object name, to iterate
+ through children objects and to lookup a child object by name or class.
+ Additionally , this class provides the builtin timer functionality.
+ The [classfnc]$constructor[/classfnc] and [classfnc]$destructor[/classfnc]
+ functions are empty implementations that all the other classes inherit.
+ @functions:
+ !fn: $constructor()
+ Constructor for this object class.
+ The default implementation does nothing.
+ !fn: $destructor()
+ Destructor for this object class.
+ The default implementation emits the signal "[classsignal]destroyed[/classsignal]".
+ !fn: $name()
+ Returns the name of this object.
+ !fn: $parent()
+ Returns the parent object of this object or 0 if this object has no parent.
+ !fn: $timerEvent(<timerId>)
+ Handler for the timer events.
+ The default implementation does nothing.
+ See also [classfnc]$startTimer[/classfnc]()
+ and [classfnc]$killTimer[/classfnc]().
+ !fn: $startTimer(<timeout>)
+ Starts a builtin timer for this object and returns its timer id
+ as a string or '-1' if the <timeout> was invalid.
+ The [classfnc]$timerEvent[/classfnc]() handler function
+ will be called at each <timeout>. The <timeout> is in milliseconds.
+ !fn: $killTimer(<timer id>)
+ Stops the timer specified by <timer id>.
+ !fn: $killTimers()
+ Stops all the builtin timers running.
+ !fn: $className()
+ Returns the class name of this object instance
+ !fn: $findChild(<class>,<name>)
+ Returns the first child that matches <class> and <name>.
+ If <class> is an empty string, any class matches,
+ if <name> is an empty string, any name matches.
+ This function traverses the entire tree of children
+ but is NOT recursive.
+ !fn: $childCount()
+ Returns the number of children objects
+ !fn: $emit(<signal_name>[,parameters])
+ Emits the signal <signal_name> passing the optional [parameters].
+ See the [doc:objects]objects documentation[/doc] for an overview of signals and slots.
+ !fn: $children()
+ Returns an array of children object identifiers.
+ !fn: $signalSender()
+ Returns the current signal sender when in a slot connected to a signal.
+ In other contexts this function returns an empty string.
+ You can safely use it to test if the current function has been
+ triggered directly or from a signal emission.
+ !fn: $signalName()
+ Returns the name of the signal last signal that has triggered
+ one of this object's slots.
+ This means that in a slot handler it returns the name of the signal
+ that has triggered it.
+ !fn: $property(<Qt property name>[,bNowarning:boolean])
+ This is for really advanced scripting.[br]
+ All KVIrc widgets are based on the Qt library ones.[br]
+ The Qt library allow to set and read special properties.[br]
+ You will have to take a look at the Qt documentation for each widget type
+ to see the available property names.[br]
+ The supported property types are: Rect, Size, Point, Color, String, CString,
+ Int, UInt, Bool and enumeration types.[br]
+ For example, the widget's x coordinate can be retrieved by using the [classfnc]$x[/classfnc]()
+ function or by calling $property(x).[br]
+ There are many properties that are available ony through the [classfnc]$property()[classfnc]" call:[br]
+ For example, you can find out if the widget accepts drops by calling [classfnc]$property(acceptDrops)[classfnc].[br]
+ This function will be mainly useful in the [class]wrapper[/class] class.
+ !fn: $setProperty(<Qt property>,<property value>)
+ Sets a qt property for this widget.[br]
+ This is for advanced scripting, and can control really many features of the Qt widgets.[br]
+ For example, the [class]multilineedit[/class] widgets can be set to
+ the "password" echo mode only by using this function call:[br]
+ [example]
+ %X=$new(lineedit, 0, a_name)
+ %X->$show()
+ %X->$setProperty(echoMode,Password)
+ [/example]
+ The available properties to be set are listed by [classfnc]$listProperties[/classfnc]()[br]
+ and must appear in the list as writeable.[br]
+ This function will be mainly useful in the [class]wrapper[/class] class.
+ !fn: $listProperties([bArray])
+ Lists the properties of this object.[br]
+ If <bArray> is $true then the function returns the properties
+ as an array of descriptive strings, otherwise the properties are dumped to the
+ active window. If <bArray> is not passed then it is assumed to be $false.
+ This function will be mainly useful in the [class]wrapper[/class] class.
+ @signals:
+ !sg: destroyed()
+ Emitted by the default implementation of [classfnc]$destructor[/classfnc].
+ If you reimplement [classfnc]$destructor[/classfnc] in one of the derived
+ classes (or as a private implementation), and still want this signal
+ to be emitted you must emit it by yourself, or (better) call the base class
+ destructor.
+*/
+
+// we use a char * pointer just to store a number
+// we don't use void * just because incrementing a void pointer doesn't look that good
+static char * g_hNextObjectHandle = (char *)0;
+
+
+KviKvsObject::KviKvsObject(KviKvsObjectClass * pClass,KviKvsObject * pParent,const QString &szName)
+: QObject(pParent)
+{
+ if(g_hNextObjectHandle == 0)g_hNextObjectHandle++; // make sure it's never 0
+ m_hObject = (kvs_hobject_t)g_hNextObjectHandle;
+ g_hNextObjectHandle++;
+
+ m_pObject = 0;
+ m_bObjectOwner = true; // true by default
+
+ m_szName = szName;
+
+ m_pClass = pClass;
+
+ m_pChildList = new KviPointerList<KviKvsObject>;
+ m_pChildList->setAutoDelete(false);
+
+ m_pDataContainer = new KviKvsHash();
+
+ m_pFunctionHandlers = 0; // no local function handlers yet!
+
+ m_bInDelayedDeath = false;
+
+ m_pSignalDict = 0; // no signals connected to remote slots
+ m_pConnectionList = 0; // no local slots connected to remote signals
+
+ if(pParent)pParent->registerChild(this);
+
+ KviKvsKernel::instance()->objectController()->registerObject(this);
+
+// debug("Hello world!");
+// [root@localhost cvs3]# kvirc
+// Hello world!
+// [root@localhost cvs3]# date
+// Tue Sep 5 21:53:54 CEST 2000
+// [root@localhost cvs3]#
+
+// Ported to KVS on 29.04.2005
+}
+
+KviKvsObject::~KviKvsObject()
+{
+ m_bInDelayedDeath = true;
+
+ callFunction(this,"destructor");
+
+ while(m_pChildList->first())delete m_pChildList->first();
+ delete m_pChildList;
+
+#if 0
+ // Disconnect all the signals
+ if(m_pSignalDict)
+ {
+ KviPointerHashTableIterator<QString,KviKvsObjectConnectionList> it(*m_pSignalDict);
+
+ while(it.current())
+ {
+ KviKvsObjectConnectionListIterator cit(*(it.current()));
+ while(cit.current())
+ {
+ disconnectSignal(it.currentKey(),cit.current());
+ // ++cit // NO!...we point to the next now!
+ }
+ // the iterator should automatically point to the next now
+ //if(m_pSignalDict)++it;
+ }
+ }
+
+ // Disconnect all the slots
+ if(m_pConnectionList)
+ {
+ KviKvsObjectConnectionListIterator cit(*m_pConnectionList);
+ while(cit.current())
+ {
+ QString szSig = cit.current()->szSignal;
+ cit.current()->pSourceObject->disconnectSignal(szSig,cit.current());
+ //++cit;// NO!... we point to the next now!
+ }
+ }
+#else
+ // Disconnect all the signals
+ for(;;)
+ {
+ if(!m_pSignalDict)break;
+ KviPointerHashTableEntry<QString,KviKvsObjectConnectionList> * pSignalList = m_pSignalDict->firstEntry();
+ if(!pSignalList)break;
+ KviKvsObjectConnection * pConnection = pSignalList->data()->first();
+ if(!pConnection)break;
+ disconnectSignal(pSignalList->key(),pConnection);
+ }
+
+ // Disconnect all the slots
+ for(;;)
+ {
+ if(!m_pConnectionList)break;
+ KviKvsObjectConnection * pConnection = m_pConnectionList->first();
+ if(!pConnection)break;
+ QString szSignalCopy = pConnection->szSignal; // we need this since pConnection is deleted inside disconnectSignal() and pConnection->szSignal dies too (but is referenced after the connection delete)
+ pConnection->pSourceObject->disconnectSignal(szSignalCopy,pConnection);
+ }
+#endif
+
+ KviKvsKernel::instance()->objectController()->unregisterObject(this);
+
+ if(parentObject())parentObject()->unregisterChild(this);
+
+ if(m_pObject)
+ {
+ disconnect(m_pObject,SIGNAL(destroyed()),this,SLOT(objectDestroyed()));
+ if(m_bObjectOwner)delete m_pObject;
+ }
+
+ delete m_pDataContainer;
+ if(m_pFunctionHandlers)delete m_pFunctionHandlers;
+}
+
+bool KviKvsObject::init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams)
+{
+ return true;
+}
+
+QWidget * KviKvsObject::parentScriptWidget()
+{
+ if(parentObject())
+ {
+ if(parentObject()->object())
+ {
+ if(parentObject()->object()->isWidgetType())
+ return (QWidget *)(parentObject()->object());
+ }
+ }
+ return 0;
+}
+
+void KviKvsObject::unregisterChild(KviKvsObject *pChild)
+{
+ m_pChildList->removeRef(pChild);
+}
+
+void KviKvsObject::registerChild(KviKvsObject *pChild)
+{
+ m_pChildList->append(pChild);
+}
+
+// SIGNAL/SLOT stuff
+
+bool KviKvsObject::connectSignal(const QString &sigName,KviKvsObject * pTarget,const QString &slotName)
+{
+ if(!pTarget->lookupFunctionHandler(slotName))return false; // no such slot
+
+ if(!m_pSignalDict)
+ {
+ m_pSignalDict = new KviPointerHashTable<QString,KviKvsObjectConnectionList>(7,false);
+ m_pSignalDict->setAutoDelete(true);
+ }
+
+ KviKvsObjectConnectionList * l = m_pSignalDict->find(sigName);
+ if(!l)
+ {
+ l = new KviKvsObjectConnectionList;
+ l->setAutoDelete(true);
+ m_pSignalDict->insert(sigName,l);
+ }
+
+ KviKvsObjectConnection * con = new KviKvsObjectConnection;
+
+ con->pSourceObject = this;
+ con->pTargetObject = pTarget;
+ con->szSignal = sigName;
+ con->szSlot = slotName;
+
+ l->append(con);
+ pTarget->registerConnection(con);
+ return true;
+}
+
+void KviKvsObject::registerConnection(KviKvsObjectConnection *pConnection)
+{
+ if(!m_pConnectionList)
+ {
+ m_pConnectionList = new KviKvsObjectConnectionList;
+ m_pConnectionList->setAutoDelete(false);
+ }
+ m_pConnectionList->append(pConnection);
+}
+
+bool KviKvsObject::disconnectSignal(const QString &sigName,KviKvsObject * pTarget,const QString &slotName)
+{
+ if(!m_pSignalDict)return false; //no such signal to disconnect
+
+ KviKvsObjectConnectionList * l = m_pSignalDict->find(sigName);
+ if(!l)return false;
+
+ KviKvsObjectConnectionListIterator it(*l);
+
+ while(KviKvsObjectConnection * sl = it.current())
+ {
+ if(sl->pTargetObject == pTarget)
+ {
+ if(KviQString::equalCI(sl->szSlot,slotName))
+ {
+ pTarget->unregisterConnection(sl);
+ l->removeRef(sl);
+ if(l->isEmpty())m_pSignalDict->remove(sigName);
+ if(m_pSignalDict->isEmpty())
+ {
+ delete m_pSignalDict;
+ m_pSignalDict = 0;
+ }
+ return true;
+ }
+ }
+ ++it;
+ }
+ return false;
+}
+
+bool KviKvsObject::disconnectSignal(const QString &sigName,KviKvsObjectConnection * pConnection)
+{
+ if(!m_pSignalDict)return false;
+ KviKvsObjectConnectionList * l = m_pSignalDict->find(sigName);
+ //__range_valid(l);
+ if(!l)return false;
+ pConnection->pTargetObject->unregisterConnection(pConnection);
+ //__range_valid(l->findRef(pConnection) > -1);
+ l->removeRef(pConnection);
+ if(l->isEmpty())m_pSignalDict->remove(sigName);
+ if(m_pSignalDict->isEmpty())
+ {
+ delete m_pSignalDict;
+ m_pSignalDict = 0;
+ }
+ return true;
+}
+
+bool KviKvsObject::unregisterConnection(KviKvsObjectConnection * pConnection)
+{
+ if(!m_pConnectionList)return false;
+ bool bOk = m_pConnectionList->removeRef(pConnection); // no auto delete !
+ if(!bOk)return false;
+ if(m_pConnectionList->isEmpty())
+ {
+ delete m_pConnectionList;
+ m_pConnectionList = 0;
+ }
+ return true;
+}
+
+int KviKvsObject::emitSignal(const QString &sigName,KviKvsObjectFunctionCall * pOuterCall,KviKvsVariantList * pParams)
+{
+ if(!m_pSignalDict)return 0;
+
+ KviKvsObjectConnectionList * l = m_pSignalDict->find(sigName);
+ if(!l)return 0; // no slots registered
+
+ KviKvsVariant retVal;
+
+ // The objects we're going to disconnect
+ KviPointerList<KviKvsObjectConnection> * pDis = 0;
+
+ kvs_int_t emitted = 0;
+
+ KviKvsObjectConnectionListIterator it(*l);
+
+ while(KviKvsObjectConnection * s = it.current())
+ {
+ // save it , since s may be destroyed in the call!
+ KviKvsObject * pTarget = s->pTargetObject;
+
+ emitted++;
+
+ kvs_hobject_t hTarget = pTarget->handle();
+ kvs_hobject_t hOld = pTarget->signalSender();
+
+ pTarget->setSignalSender(m_hObject);
+ pTarget->setSignalName(sigName);
+
+ if(!pTarget->callFunction(this,s->szSlot,QString::null,pOuterCall->context(),&retVal,pParams))
+ {
+ if(KviKvsKernel::instance()->objectController()->lookupObject(hTarget) && it.current())
+ {
+ pOuterCall->warning(
+ __tr2qs("Broken slot '%Q' in target object '%Q::%Q' while emitting signal '%Q' from object '%Q::%Q': disconnecting"),
+ &(s->szSlot),
+ &(s->pTargetObject->getClass()->name()),
+ &(s->pTargetObject->getName()),
+ &(sigName),
+ &(getClass()->name()),
+ &m_szName);
+
+ if(!pDis)
+ {
+ pDis = new KviPointerList<KviKvsObjectConnection>;
+ pDis->setAutoDelete(false);
+ }
+ pDis->append(s);
+ } else {
+ // else destroyed in the call! (already disconnected)
+
+ pOuterCall->warning(
+ __tr2qs("Slot target object destroyed while emitting signal '%Q' from object '%Q::%Q'"),
+ &(sigName),
+ &(getClass()->name()),
+ &m_szName);
+ }
+ }
+
+ if(KviKvsKernel::instance()->objectController()->lookupObject(hTarget))
+ {
+ pTarget->setSignalSender(hOld);
+ }
+
+ ++it;
+ }
+
+ if(pDis)
+ {
+ // we have some signals to disconnect (because they're broken)
+ for(KviKvsObjectConnection * con = pDis->first();con;con = pDis->next())
+ disconnectSignal(sigName,con);
+ delete pDis;
+ }
+
+ return emitted;
+}
+
+bool KviKvsObject::function_name(KviKvsObjectFunctionCall * c)
+{
+ c->returnValue()->setString(getName());
+ return true;
+}
+
+bool KviKvsObject::function_parent(KviKvsObjectFunctionCall * c)
+{
+ KviKvsObject * o = parentObject();
+ c->returnValue()->setHObject(o ? o->handle() : (kvs_hobject_t)0);
+ return true;
+}
+
+bool KviKvsObject::function_className(KviKvsObjectFunctionCall * c)
+{
+ c->returnValue()->setString(getClass()->name());
+ return true;
+}
+
+bool KviKvsObject::function_childCount(KviKvsObjectFunctionCall * c)
+{
+ c->returnValue()->setInteger((kvs_int_t)(m_pChildList->count()));
+ return true;
+}
+
+bool KviKvsObject::function_signalSender(KviKvsObjectFunctionCall * c)
+{
+ c->returnValue()->setHObject(m_hSignalSender);
+ return true;
+}
+
+bool KviKvsObject::function_signalName(KviKvsObjectFunctionCall * c)
+{
+ c->returnValue()->setString(m_szSignalName);
+ return true;
+}
+
+bool KviKvsObject::function_destructor(KviKvsObjectFunctionCall * c)
+{
+ emitSignal("destroyed",c);
+ return true;
+}
+
+bool KviKvsObject::function_children(KviKvsObjectFunctionCall * c)
+{
+ KviKvsArray * a = new KviKvsArray();
+ int id=0;
+ for(KviKvsObject * o = m_pChildList->first();o;o = m_pChildList->next())
+ {
+ a->set(id,new KviKvsVariant(o->handle()));
+ id++;
+ }
+ c->returnValue()->setArray(a);
+ return true;
+}
+bool KviKvsObject::function_findChild(KviKvsObjectFunctionCall * c)
+{
+ QString szClass,szName;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("className",KVS_PT_STRING,KVS_PF_OPTIONAL,szClass)
+ KVSO_PARAMETER("objectName",KVS_PT_STRING,KVS_PF_OPTIONAL,szName)
+ KVSO_PARAMETERS_END(c)
+
+ KviKvsObject * o = findChild(szClass,szName);
+ c->returnValue()->setHObject(o ? o->handle() : (kvs_hobject_t)0);
+
+ return true;
+}
+
+bool KviKvsObject::function_emit(KviKvsObjectFunctionCall * c)
+{
+ QString szSignal;
+ KviKvsVariantList vList;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("signal",KVS_PT_NONEMPTYSTRING,0,szSignal)
+ KVSO_PARAMETER("params",KVS_PT_VARIANTLIST,KVS_PF_OPTIONAL,vList)
+ KVSO_PARAMETERS_END(c)
+
+ emitSignal(szSignal,c,&vList);
+ return true;
+}
+
+bool KviKvsObject::function_startTimer(KviKvsObjectFunctionCall * c)
+{
+ kvs_int_t timeout;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("timeout",KVS_PT_UINT,0,timeout)
+ KVSO_PARAMETERS_END(c)
+
+ c->returnValue()->setInteger((kvs_int_t)(startTimer(timeout)));
+ return true;
+}
+
+bool KviKvsObject::function_killTimer(KviKvsObjectFunctionCall * c)
+{
+ kvs_int_t id;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("timerId",KVS_PT_INT,0,id)
+ KVSO_PARAMETERS_END(c)
+ killTimer(id);
+ return true;
+}
+
+bool KviKvsObject::function_killTimers(KviKvsObjectFunctionCall * c)
+{
+ // FIXME: QT4 does not seem to have QObject::killTimers()
+#ifndef COMPILE_USE_QT4
+ killTimers();
+#endif
+ return true;
+}
+
+bool KviKvsObject::function_listProperties(KviKvsObjectFunctionCall * c)
+{
+ bool bArray;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bArray",KVS_PT_BOOL,KVS_PF_OPTIONAL,bArray)
+ KVSO_PARAMETERS_END(c)
+
+ c->returnValue()->setNothing();
+
+ KviKvsArray * a = bArray ? new KviKvsArray() : 0;
+
+ KviWindow * w = c->context()->window();
+
+ if(!bArray)
+ w->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Listing Qt properties for object named \"%Q\" of KVS class %Q"),&m_szName,&(m_pClass->name()));
+ kvs_int_t cnt = 0;
+ if(m_pObject)
+ {
+ const QMetaObject *o = m_pObject->metaObject();
+ if(!bArray)
+ w->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Properties for Qt class %s"),o->className());
+#ifndef COMPILE_USE_QT4
+ while(o)
+ {
+#endif
+ kvs_int_t idx = 0;
+ #ifdef COMPILE_USE_QT4
+ QMetaProperty prop = o->property(idx);
+ const QMetaProperty *p = &prop;
+ #else
+ const QMetaProperty *p = o->property(idx);
+ #endif
+
+ while(p)
+ {
+ QString szOut;
+ QString szName = p->name();
+ #ifdef COMPILE_USE_QT4
+ QString szType = p->typeName();
+ #else
+ QString szType = p->type();
+ #endif
+ if(bArray)
+ KviQString::sprintf(szOut,"%Q, %Q",&szName,&szType);
+ else {
+ KviQString::sprintf(szOut,__tr2qs("Property: %c%Q%c, type %Q"),KVI_TEXT_BOLD,&szName,KVI_TEXT_BOLD,&szType);
+ szOut.prepend(" ");
+ }
+
+ if(p->isEnumType())
+ {
+ szOut += ", enum(";
+#ifndef COMPILE_USE_QT4
+ // FIXME: Qt 4.x needs QMetaEnum for this loop
+ QStrList le = p->enumKeys();
+ int i = 0;
+ for(char *c2 = le.first(); c2; c2 = le.next())
+ {
+ if(i == 0)
+ i++;
+ else
+ szOut.append(", ");
+ szOut.append(c2);
+ }
+#endif
+ szOut += ")";
+ }
+
+
+#ifdef COMPILE_USE_QT4
+ // FIXME: QT4 Need to read better the docs and check the changes: there seem to be too many
+ // for me to fix now. Actually I need to get the whole executable working...
+ if(p->isWritable())szOut += ", writable";
+#else
+ if(p->isSetType())szOut += ", set";
+ if(p->writable())szOut += ", writable";
+#endif
+ if(bArray)
+ a->set(cnt,new KviKvsVariant(szOut));
+ else
+ w->outputNoFmt(KVI_OUT_SYSTEMMESSAGE,szOut);
+#ifdef COMPILE_USE_QT4
+ idx++;
+ if (idx<o->propertyCount()){
+ prop = o->property(idx);
+ p = &prop;
+ }
+ else p=0;
+#else
+ p = o->property(idx);
+ idx++;
+#endif
+
+ cnt++;
+ }
+#ifndef COMPILE_USE_QT4
+ o = o->superClass();
+ }
+#endif
+
+ }
+
+ if(bArray)
+ c->returnValue()->setArray(a);
+ else
+ w->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("%d properties listed"),cnt);
+ return true;
+}
+
+
+// rewritten using the new KVS features :)
+bool KviKvsObject::function_setProperty(KviKvsObjectFunctionCall * c)
+{
+ QString szName;
+ KviKvsVariant * v;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("propertyName",KVS_PT_NONEMPTYSTRING,0,szName)
+ KVSO_PARAMETER("propertyValue",KVS_PT_VARIANT,0,v)
+ KVSO_PARAMETERS_END(c)
+
+ c->returnValue()->setNothing();
+
+ if(!m_pObject)
+ {
+ // there are no Qt properties at all
+ c->warning(__tr2qs("The object named \"%Q\" of class %Q has no Qt properties"),&m_szName,&(m_pClass->name()));
+ return true;
+ }
+
+#ifdef COMPILE_USE_QT4
+ int idx = m_pObject->metaObject()->indexOfProperty(szName);
+#else
+ int idx = m_pObject->metaObject()->findProperty(szName,true);
+#endif
+ if(idx < 0)
+ {
+ c->warning(__tr2qs("No Qt property named \"%Q\" for object named \"%Q\" of class %Q"),&szName,&m_szName,&(m_pClass->name()));
+ return true;
+ }
+#ifdef COMPILE_USE_QT4
+ QMetaProperty prop = m_pObject->metaObject()->property(idx);
+ const QMetaProperty * p = &prop;
+#else
+ const QMetaProperty * p = m_pObject->metaObject()->property(idx,true);
+#endif
+ if(!p)
+ {
+ c->warning(__tr2qs("Can't find property named \"%Q\" for object named \"%Q\" of class %Q: the property is indexed but it doesn't really exist"),&szName,&m_szName,&(m_pClass->name()));
+ return true;
+ }
+
+ QVariant vv = m_pObject->property(szName);
+ if(!vv.isValid())
+ {
+ c->warning(__tr2qs("Can't find property named \"%Q\" for object named \"%Q\" of class %Q: the property is indexed and defined but the returned variant is not valid"),&szName,&m_szName,&(m_pClass->name()));
+ return true;
+ }
+
+ if(p->isEnumType())
+ {
+ QString szKey;
+ v->asString(szKey);
+#ifdef COMPILE_USE_QT4
+ int val = p->enumerator().keyToValue(szKey);
+#else
+ int val = p->keyToValue(szKey);
+#endif
+ QVariant var(val);
+ m_pObject->setProperty(szName,var);
+ return true;
+ }
+
+#define WRONG_TYPE(__therighttype) \
+ { \
+ c->warning(__tr2qs("The property is of type %s but the supplied argument can't be converted to that type (expecting \"%s\")"),p->type(),__therighttype); \
+ return true; \
+ }
+
+ switch(vv.type())
+ {
+ case QVariant::Int:
+ {
+ kvs_int_t i;
+ if(!v->asInteger(i))WRONG_TYPE("integer")
+ m_pObject->setProperty(szName,QVariant((int)i));
+ }
+ break;
+ case QVariant::UInt:
+ {
+ kvs_int_t i;
+ if(!v->asInteger(i))WRONG_TYPE("unsigned integer")
+ if(i < 0)WRONG_TYPE("unsigned integer")
+ m_pObject->setProperty(szName,QVariant((unsigned int)i));
+ }
+ break;
+ case QVariant::Bool:
+ m_pObject->setProperty(szName,QVariant(v->asBoolean()));
+ break;
+ case QVariant::String:
+ {
+ QString s;
+ v->asString(s);
+ m_pObject->setProperty(szName,QVariant(s));
+ }
+ break;
+ case QVariant::CString:
+ {
+ QString s;
+ v->asString(s);
+ m_pObject->setProperty(szName,QVariant(s.utf8()));
+ }
+ break;
+ case QVariant::Point:
+ {
+ if(!v->isArray())WRONG_TYPE("array(integer,integer)")
+ KviKvsArray * a = v->array();
+ KviKvsVariant * x = a->at(0);
+ KviKvsVariant * y = a->at(1);
+ if(!x || !y)WRONG_TYPE("array(integer,integer)")
+ kvs_int_t iX,iY;
+ if(!x->asInteger(iX) || !y->asInteger(iY))WRONG_TYPE("array(integer,integer)")
+ m_pObject->setProperty(szName,QVariant(QPoint(iX,iY)));
+ }
+ break;
+ case QVariant::Size:
+ {
+ if(!v->isArray())WRONG_TYPE("array(integer,integer)")
+ KviKvsArray * a = v->array();
+ KviKvsVariant * w = a->at(0);
+ KviKvsVariant * h = a->at(1);
+ if(!w || !h)WRONG_TYPE("array(integer,integer)")
+ kvs_int_t iW,iH;
+ if(!w->asInteger(iW) || !h->asInteger(iH))WRONG_TYPE("array(integer,integer)")
+ m_pObject->setProperty(szName,QVariant(QSize(iW,iH)));
+ }
+ break;
+ case QVariant::Rect:
+ {
+ if(!v->isArray())WRONG_TYPE("array(integer,integer,integer,integer)")
+ KviKvsArray * a = v->array();
+ KviKvsVariant * x = a->at(0);
+ KviKvsVariant * y = a->at(1);
+ KviKvsVariant * w = a->at(2);
+ KviKvsVariant * h = a->at(3);
+ if(!x || !y || !w || !h)WRONG_TYPE("array(integer,integer,integer,integer)")
+ kvs_int_t iX,iY,iW,iH;
+ if(!x->asInteger(iX) || !y->asInteger(iY) || !w->asInteger(iW) || !h->asInteger(iH))WRONG_TYPE("array(integer,integer,integer,integer)")
+ m_pObject->setProperty(szName,QVariant(QRect(iX,iY,iW,iH)));
+ }
+ break;
+#ifndef COMPILE_USE_QT4
+ // FIXME: QT4 ????
+ case QVariant::Color:
+ {
+ if(!v->isArray())WRONG_TYPE("array(integer,integer,integer)")
+ KviKvsArray * a = v->array();
+ KviKvsVariant * r = a->at(0);
+ KviKvsVariant * g = a->at(1);
+ KviKvsVariant * b = a->at(3);
+ if(!r || !g || !b)WRONG_TYPE("array(integer,integer,integer)")
+ kvs_int_t iR,iG,iB;
+ if(!r->asInteger(iR) || !g->asInteger(iG) || !b->asInteger(iB))WRONG_TYPE("array(integer,integer,integer)")
+ m_pObject->setProperty(szName,QVariant(QColor(iR,iG,iB)));
+ }
+ break;
+ case QVariant::Font:
+ {
+ if(!v->isArray())WRONG_TYPE("array(string,integer,string)")
+ KviKvsArray * a = v->array();
+ KviKvsVariant * ff = a->at(0);
+ KviKvsVariant * ps = a->at(1);
+ KviKvsVariant * fl = a->at(3);
+ if(!ff || !ps)WRONG_TYPE("array(string,integer,string)")
+ kvs_int_t iPs;
+ if(!ps->asInteger(iPs))WRONG_TYPE("array(string,integer,string)")
+ QString szFf,szFl;
+ ff->asString(szFf);
+ if(fl)fl->asString(szFl);
+ QFont fnt;
+ fnt.setFamily(szFf);
+ fnt.setPointSize(iPs);
+ if(szFl.find('b') != -1)fnt.setBold(true);
+ if(szFl.find('i') != -1)fnt.setItalic(true);
+ if(szFl.find('u') != -1)fnt.setUnderline(true);
+ if(szFl.find('o') != -1)fnt.setOverline(true);
+ if(szFl.find('f') != -1)fnt.setFixedPitch(true);
+ if(szFl.find('s') != -1)fnt.setStrikeOut(true);
+ m_pObject->setProperty(szName,QVariant(fnt));
+ }
+ break;
+ case QVariant::Pixmap:
+ case QVariant::IconSet:
+ {
+ if(v->isHObject())
+ {
+ if(v->hobject() == (kvs_hobject_t)0)
+ {
+ // null pixmap
+ if(vv.type() == QVariant::Pixmap)
+ m_pObject->setProperty(szName,QVariant(QPixmap()));
+ else
+ m_pObject->setProperty(szName,QVariant(QIconSet()));
+ } else {
+ KviKvsObject * pix = KviKvsKernel::instance()->objectController()->lookupObject(v->hobject());
+ if(!pix->inherits("KviScriptPixmapObject"))
+ c->warning(__tr2qs("A pixmap object, an image_id or an image file path is required for this property"));
+ else {
+ QVariant pixv = pix->property("pixmap");
+ if(vv.type() == QVariant::Pixmap)
+ m_pObject->setProperty(szName,pixv);
+ else
+ m_pObject->setProperty(szName,QVariant(QIconSet(pixv.toPixmap())));
+ }
+ }
+ } else {
+ QString szStr;
+ v->asString(szStr);
+ QPixmap * pPix = g_pIconManager->getImage(szStr);
+ if(pPix)
+ {
+ if(vv.type() == QVariant::Pixmap)
+ m_pObject->setProperty(szName,QVariant(*pPix));
+ else
+ m_pObject->setProperty(szName,QVariant(QIconSet(*pPix)));
+ }
+ else
+ c->warning(__tr2qs("Can't find the requested image"));
+ }
+ }
+ break;
+#endif
+ default:
+ c->warning(__tr2qs("Property \"%Q\" for object named \"%Q\" of class %Q has an unsupported data type"),&szName,&m_szName,&(m_pClass->name()));
+ c->returnValue()->setNothing();
+ break;
+ }
+ return true;
+}
+
+bool KviKvsObject::function_property(KviKvsObjectFunctionCall * c)
+{
+ QString szName;
+ bool bNoerror;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("propertyName",KVS_PT_NONEMPTYSTRING,0,szName)
+ KVSO_PARAMETER("bNowarning",KVS_PT_BOOL,KVS_PF_OPTIONAL,bNoerror)
+ KVSO_PARAMETERS_END(c)
+
+ if(!m_pObject)
+ {
+ // there are no Qt properties at all
+ if (bNoerror) c->returnValue()->setString("No Qt properties");
+ else
+ {
+ c->warning(__tr2qs("The object named \"%Q\" of class %Q has no Qt properties"),&m_szName,&(m_pClass->name()));
+ c->returnValue()->setNothing();
+ }
+ return true;
+ }
+
+#ifdef COMPILE_USE_QT4
+ int idx = m_pObject->metaObject()->indexOfProperty(szName);
+#else
+ int idx = m_pObject->metaObject()->findProperty(szName,true);
+#endif
+ if(idx < 0)
+ {
+ if (bNoerror) c->returnValue()->setString("No Qt properties");
+ else
+ {
+ c->warning(__tr2qs("No Qt property named \"%Q\" for object named \"%Q\" of class %Q"),&szName,&m_szName,&(m_pClass->name()));
+ c->returnValue()->setNothing();
+ }
+ return true;
+ }
+#ifdef COMPILE_USE_QT4
+ QMetaProperty prop = m_pObject->metaObject()->property(idx);
+ const QMetaProperty * p = &prop;
+#else
+ const QMetaProperty * p = m_pObject->metaObject()->property(idx,true);
+#endif
+ if(!p)
+ {
+ c->warning(__tr2qs("Can't find property named \"%Q\" for object named \"%Q\" of class %Q: the property is indexed but it doesn't really exist"),&szName,&m_szName,&(m_pClass->name()));
+ c->returnValue()->setNothing();
+ return true;
+ }
+
+ QVariant v = m_pObject->property(szName);
+ if(!v.isValid())
+ {
+ c->warning(__tr2qs("Can't find property named \"%Q\" for object named \"%Q\" of class %Q: the property is indexed and defined but the returned variant is not valid"),&szName,&m_szName,&(m_pClass->name()));
+ c->returnValue()->setNothing();
+ return true;
+ }
+
+ if(p->isEnumType())
+ {
+#ifdef COMPILE_USE_QT4
+ c->returnValue()->setString(p->enumerator().valueToKey(v.toInt()));
+#else
+ c->returnValue()->setString(p->valueToKey(v.toInt()));
+#endif
+ return true;
+ }
+
+ switch(v.type())
+ {
+ case QVariant::Int:
+ c->returnValue()->setInteger((kvs_int_t)v.toInt());
+ break;
+ case QVariant::UInt:
+ c->returnValue()->setInteger((kvs_int_t)v.toUInt());
+ break;
+ case QVariant::Bool:
+ c->returnValue()->setBoolean(v.toBool());
+ break;
+ case QVariant::String:
+ c->returnValue()->setString(v.toString());
+ break;
+ case QVariant::CString:
+ c->returnValue()->setString(QString::fromUtf8(v.toCString().data()));
+ break;
+ case QVariant::Point:
+ {
+ QPoint p = v.toPoint();
+ KviKvsArray * a = new KviKvsArray();
+ a->set(0,new KviKvsVariant((kvs_int_t)p.x()));
+ a->set(1,new KviKvsVariant((kvs_int_t)p.y()));
+ c->returnValue()->setArray(a);
+ }
+ break;
+ case QVariant::Size:
+ {
+ QSize p = v.toSize();
+ KviKvsArray * a = new KviKvsArray();
+ a->set(0,new KviKvsVariant((kvs_int_t)p.width()));
+ a->set(1,new KviKvsVariant((kvs_int_t)p.height()));
+ c->returnValue()->setArray(a);
+ }
+ break;
+ case QVariant::Rect:
+ {
+ QRect p = v.toRect();
+ KviKvsArray * a = new KviKvsArray();
+ a->set(0,new KviKvsVariant((kvs_int_t)p.x()));
+ a->set(1,new KviKvsVariant((kvs_int_t)p.y()));
+ a->set(2,new KviKvsVariant((kvs_int_t)p.width()));
+ a->set(3,new KviKvsVariant((kvs_int_t)p.height()));
+ c->returnValue()->setArray(a);
+ }
+ break;
+#ifndef COMPILE_USE_QT4
+ // FIXME: QT4 ?
+ case QVariant::Color:
+ {
+ QColor clr = v.toColor();
+ KviKvsArray * a = new KviKvsArray();
+ a->set(0,new KviKvsVariant((kvs_int_t)clr.red()));
+ a->set(1,new KviKvsVariant((kvs_int_t)clr.green()));
+ a->set(2,new KviKvsVariant((kvs_int_t)clr.blue()));
+ c->returnValue()->setArray(a);
+ }
+ break;
+ case QVariant::Font:
+ {
+ QFont f = v.toFont();
+ KviKvsArray * a = new KviKvsArray();
+ a->set(0,new KviKvsVariant(f.family()));
+ a->set(1,new KviKvsVariant((kvs_int_t)f.pointSize()));
+ QString szFlags;
+ if(f.bold())szFlags += "b";
+ if(f.underline())szFlags += "u";
+ if(f.overline())szFlags += "o";
+ if(f.strikeOut())szFlags += "s";
+ if(f.fixedPitch())szFlags += "f";
+ if(f.italic())szFlags += "i";
+ a->set(2,new KviKvsVariant(szFlags));
+ c->returnValue()->setString(szFlags);
+ }
+ break;
+#endif
+ default:
+ if (bNoerror) c->returnValue()->setString("Unsupported_data_type");
+ else
+ {
+ c->warning(__tr2qs("Property \"%Q\" for object named \"%Q\" of class %Q has an unsupported data type"),&szName,&m_szName,&(m_pClass->name()));
+ c->returnValue()->setNothing();
+ }
+ break;
+ }
+ return true;
+}
+
+void KviKvsObject::killAllChildrenWithClass(KviKvsObjectClass *cl)
+{
+ KviPointerList<KviKvsObject> l;
+ l.setAutoDelete(true);
+ for(KviKvsObject * o=m_pChildList->first();o;o=m_pChildList->next())
+ {
+ if(o->getClass() == cl)
+ {
+ l.append(o);
+ } else o->killAllChildrenWithClass(cl);
+ }
+}
+
+bool KviKvsObject::inheritsClass(KviKvsObjectClass * pClass)
+{
+ if(pClass == m_pClass)return true;
+ KviKvsObjectClass * cl = m_pClass->m_pParentClass;
+ while(cl)
+ {
+ if(cl == pClass)return true;
+ else cl = cl->m_pParentClass;
+ }
+ return false;
+}
+
+KviKvsObjectClass * KviKvsObject::getClass(const QString & classOverride)
+{
+ if(classOverride.isEmpty())return m_pClass;
+ KviKvsObjectClass * cl = m_pClass; // class override can be also THIS class
+ // if object->$function() is a local override, class::object->$function()
+ // is the class member function (not the local override)
+ while(cl)
+ {
+ if(KviQString::equalCI(cl->name(),classOverride))break;
+ else cl = cl->m_pParentClass;
+ }
+ return cl;
+}
+
+KviKvsObjectFunctionHandler * KviKvsObject::lookupFunctionHandler(const QString & funcName,const QString & classOverride)
+{
+ KviKvsObjectFunctionHandler * h = 0;
+
+ if(classOverride.isEmpty() && m_pFunctionHandlers)
+ {
+ // lookup the local overrides
+ h = m_pFunctionHandlers->find(funcName);
+ }
+
+ if(!h)
+ {
+ // not a local override function... lookup in the class
+ KviKvsObjectClass * cl = getClass(classOverride);
+ if(cl)return cl->lookupFunctionHandler(funcName);
+ }
+
+ return h;
+}
+
+
+bool KviKvsObject::die()
+{
+ if(m_bInDelayedDeath)return false;
+ m_bInDelayedDeath = true;
+ QTimer::singleShot(0,this,SLOT(delayedDie()));
+ return true;
+}
+
+bool KviKvsObject::dieNow()
+{
+ if(m_bInDelayedDeath)return false;
+ m_bInDelayedDeath = true;
+ delete this;
+ return true;
+}
+
+void KviKvsObject::delayedDie()
+{
+ delete this; // byez!
+}
+
+void KviKvsObject::setObject(QObject * o,bool bIsOwned)
+{
+ //__range_invalid(m_pObject);
+ m_bObjectOwner = bIsOwned;
+ m_pObject = o;
+ o->installEventFilter(this);
+ connect(m_pObject,SIGNAL(destroyed()),this,SLOT(objectDestroyed()));
+}
+
+void KviKvsObject::objectDestroyed()
+{
+ m_pObject = 0;
+ die();
+}
+
+bool KviKvsObject::eventFilter(QObject *o,QEvent *e)
+{
+ return false; // do not stop
+}
+
+void KviKvsObject::timerEvent(QTimerEvent *e)
+{
+ KviKvsVariant * v = new KviKvsVariant();
+ v->setInteger(e->timerId());
+ KviKvsVariantList parms(v);
+
+ callFunction(this,"timerEvent",&parms);
+}
+
+bool KviKvsObject::callFunction(KviKvsObject * pCaller,const QString &fncName,KviKvsVariant * pRetVal,KviKvsVariantList * pParams)
+{
+ KviKvsVariant rv;
+ if(!pRetVal)pRetVal = &rv;
+ KviKvsRunTimeContext ctx(0,g_pApp->activeConsole(),KviKvsKernel::instance()->emptyParameterList(),pRetVal,0);
+ if(!pParams)pParams = KviKvsKernel::instance()->emptyParameterList();
+ return callFunction(pCaller,fncName,QString::null,&ctx,pRetVal,pParams);
+}
+
+
+bool KviKvsObject::callFunction(KviKvsObject * pCaller,const QString &fncName,KviKvsVariantList * pParams)
+{
+ KviKvsVariant fakeRetVal;
+ return callFunction(pCaller,fncName,&fakeRetVal,pParams);
+}
+
+bool KviKvsObject::callFunction(
+ KviKvsObject * pCaller,
+ const QString & fncName,
+ const QString & classOverride,
+ KviKvsRunTimeContext * pContext,
+ KviKvsVariant * pRetVal,
+ KviKvsVariantList * pParams)
+{
+ KviKvsObjectFunctionHandler * h = lookupFunctionHandler(fncName,classOverride);
+
+ if(!h)
+ {
+ if(classOverride.isEmpty())
+ pContext->error(__tr2qs("Cannot find object function $%Q for object named \"%Q\" of class %Q"),&fncName,&m_szName,&(getClass()->name()));
+ else
+ pContext->error(__tr2qs("Cannot find object function $%Q::%Q for object named \"%Q\" of class %Q"),&classOverride,&fncName,&m_szName,&(getClass()->name()));
+ return false;
+ }
+
+ if(h->flags() & KviKvsObjectFunctionHandler::Internal)
+ {
+ if(pCaller != this)
+ {
+ pContext->error(__tr2qs("Cannot call internal object function $%Q (for object named \"%Q\" of class %Q) from this context"),&fncName,&m_szName,&(getClass()->name()));
+ return false;
+ }
+ }
+
+ KviKvsObjectFunctionCall fc(pContext,pParams,pRetVal);
+
+ return h->call(this,&fc);
+
+ // Not only gcc spits out compiler errors:
+ // 25.09.2001 , at this point in file
+
+ // c:\programmi\microsoft visual studio\myprojects\kvirc3\src\kvirc\uparser\kvi_scriptobject.cpp(1234) : fatal error C1001: INTERNAL COMPILER ERROR
+ // (compiler file 'E:\8168\vc98\p2\src\P2\main.c', line 494)
+ // Please choose the Technical Support command on the Visual C++
+ // Help menu, or open the Technical Support help file for more information
+}
+
+
+
+void KviKvsObject::registerPrivateImplementation(const QString &szFunctionName,const QString &szCode)
+{
+ if(szCode.isEmpty())
+ {
+ if(m_pFunctionHandlers)
+ {
+ m_pFunctionHandlers->remove(szFunctionName);
+ if(m_pFunctionHandlers->isEmpty())
+ {
+ delete m_pFunctionHandlers;
+ m_pFunctionHandlers = 0;
+ }
+ }
+ } else {
+ if(!m_pFunctionHandlers)
+ {
+ m_pFunctionHandlers = new KviPointerHashTable<QString,KviKvsObjectFunctionHandler>(7,false);
+ m_pFunctionHandlers->setAutoDelete(true);
+ }
+
+ QString szContext = m_pClass->name();
+ szContext += "[privateimpl]::";
+ szContext += szFunctionName;
+
+ m_pFunctionHandlers->replace(szFunctionName,new KviKvsObjectScriptFunctionHandler(szContext,szCode));
+ }
+}
+
+
+KviKvsObject * KviKvsObject::findChild(const QString &szClass,const QString &szName)
+{
+ for(KviKvsObject * o = m_pChildList->first();o;o= m_pChildList->next())
+ {
+ if(szClass.isEmpty())
+ {
+ // any class matches
+ if(szName.isEmpty())return o; // any name matches
+ // name must match
+ if(KviQString::equalCI(szName,o->name()))return o;
+ } else {
+ if(KviQString::equalCI(szClass,o->getClass()->name()))
+ {
+ if(szName.isEmpty())return o; // any name matches
+ // name must match
+ if(KviQString::equalCI(szName,o->name()))return o;
+ }
+ }
+ KviKvsObject * c = o->findChild(szClass,szName);
+ if(c)return c;
+ }
+ return 0;
+}
+
+
diff --git a/src/kvirc/kvs/kvi_kvs_object.h b/src/kvirc/kvs/kvi_kvs_object.h
new file mode 100644
index 00000000..7cd64682
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_object.h
@@ -0,0 +1,192 @@
+#ifndef _KVI_KVS_OBJECT_H_
+#define _KVI_KVS_OBJECT_H_
+//=============================================================================
+//
+// File : kvi_kvs_object.h
+// Created on Wed 08 Oct 2003 02:31:57 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_pointerlist.h"
+#include "kvi_kvs_runtimecall.h"
+#include "kvi_kvs_parameterprocessor.h"
+#include "kvi_kvs_object_functionhandler.h"
+#include "kvi_kvs_types.h"
+
+#include <qobject.h>
+
+
+class KviKvsObjectFunctionCall;
+
+typedef struct _KviKvsObjectConnection
+{
+ KviKvsObject * pSourceObject; // source object (owner of the struct)
+ KviKvsObject * pTargetObject; // target object
+ QString szSignal; // source signal name
+ QString szSlot; // target slot function
+} KviKvsObjectConnection;
+
+typedef KviPointerList<KviKvsObjectConnection> KviKvsObjectConnectionList;
+typedef KviPointerListIterator<KviKvsObjectConnection> KviKvsObjectConnectionListIterator;
+
+class KVIRC_API KviKvsObject : public QObject
+{
+ friend class KviKvsObjectController;
+ friend class KviKvsObjectClass;
+ Q_OBJECT
+public:
+ KviKvsObject(KviKvsObjectClass * pClass,KviKvsObject * pParent,const QString &szName);
+ virtual ~KviKvsObject();
+protected:
+ // main data
+ QString m_szName; // object name
+ kvs_hobject_t m_hObject; // global object handle
+ KviKvsObjectClass * m_pClass; // the class definition
+
+ KviKvsHash * m_pDataContainer; // member variables
+
+ KviPointerList<KviKvsObject> * m_pChildList;
+
+ KviPointerHashTable<QString,KviKvsObjectFunctionHandler> * m_pFunctionHandlers; // our function handlers
+
+ KviPointerHashTable<QString,KviKvsObjectConnectionList> * m_pSignalDict; // our signals connected to other object functions
+
+ KviKvsObjectConnectionList * m_pConnectionList; // signals connected to this object functions
+
+ // this is valid when processing one of our slots
+ kvs_hobject_t m_hSignalSender;
+ QString m_szSignalName;
+
+ // if this object wraps a qt one, it is here
+ QObject * m_pObject;
+ bool m_bObjectOwner; // do we have to destroy it ?
+
+ // internal stuff for die()
+ bool m_bInDelayedDeath;
+public:
+ kvs_hobject_t handle(){ return m_hObject; };
+
+ // the wrapped Qt object (may be 0!)
+ QObject * object() const { return m_pObject; };
+ void setObject(QObject * o,bool bIsOwned = true);
+
+ const QString & getName(){ return m_szName; };
+
+ KviKvsObject * parentObject(){ return (KviKvsObject *)parent(); };
+ QWidget * parentScriptWidget();
+
+ bool connectSignal(const QString &sigName,KviKvsObject * target,const QString &slotName);
+ bool disconnectSignal(const QString &sigName,KviKvsObjectConnection * con);
+ bool disconnectSignal(const QString &sigName,KviKvsObject * target,const QString & slotName);
+
+ // Emits a signal by calling all the attacched slots in an unspecified order.
+ // Returns the number of slots called (may be 0, if no slot is connected)
+ // The parameters are preserved.
+ // this is intended to be called from other function calls (the parameters are copied from pOuterCall)
+ // since we should NEVER emit totally spontaneous signals: all of them
+ // should be generated inside object functions (either from scripting or by core calls)
+ int emitSignal(const QString &sigName,KviKvsObjectFunctionCall * pOuterCall,KviKvsVariantList * pParams = 0);
+
+ void setSignalSender(kvs_hobject_t hObject){ m_hSignalSender = hObject; };
+ kvs_hobject_t signalSender(){ return m_hSignalSender; };
+ void setSignalName(const QString &szSigName){ m_szSignalName = szSigName; };
+
+ KviPointerHashTable<QString,KviKvsObjectFunctionHandler> * functionHandlers(){ return m_pFunctionHandlers; };
+
+ KviKvsHash * dataContainer(){ return m_pDataContainer; };
+
+ bool die();
+ bool dieNow();
+
+ KviKvsObjectClass * getExactClass(){ return m_pClass; };
+ KviKvsObjectClass * getClass(const QString & classOverride = QString::null);
+ bool inheritsClass(KviKvsObjectClass * pClass);
+ KviKvsObjectFunctionHandler * lookupFunctionHandler(const QString & funcName,const QString & classOverride = QString::null);
+
+ // Registers a private implementation of a function
+ // The function may or may not be already registered in the class
+ // If szCode is empty the the private implementation is removed instead
+ void registerPrivateImplementation(const QString &szFunctionName,const QString &szCode);
+
+ // ONLY pCaller can be zero here!
+ // please use one of the wrappers, if possible
+ bool callFunction(
+ KviKvsObject * pCaller, // calling object, can be zero (used for the "internal" access list verification)
+ const QString & fncName, // name of the function to call
+ const QString & classOverride, // eventual class override for the functon call, may be QString::null
+ KviKvsRunTimeContext * pContext, // calling runtime context (you'll have problems with instantiating this... :P )
+ KviKvsVariant * pRetVal, // the return value
+ KviKvsVariantList * pParams); // the parameters for the call
+ // a nice and simple wrapper: it accepts a parameter list only (eventually 0)
+ bool callFunction(KviKvsObject * pCaller,const QString &fncName,KviKvsVariantList * pParams = 0);
+ // this one gets a non null ret val too
+ bool callFunction(KviKvsObject * pCaller,const QString &fncName,KviKvsVariant * pRetVal,KviKvsVariantList * pParams = 0);
+
+ KviKvsObject * findChild(const QString &szClass,const QString &szName);
+ void killAllChildrenWithClass(KviKvsObjectClass *cl);
+protected:
+ void registerConnection(KviKvsObjectConnection * con);
+ bool unregisterConnection(KviKvsObjectConnection * con);
+
+ virtual bool init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams);
+
+ void registerChild(KviKvsObject * c);
+ void unregisterChild(KviKvsObject *c);
+
+ virtual bool eventFilter(QObject *o,QEvent *e); //necessary ?
+ virtual void timerEvent(QTimerEvent *e);
+protected:
+ bool function_name(KviKvsObjectFunctionCall *c);
+ bool function_startTimer(KviKvsObjectFunctionCall *c);
+ bool function_killTimer(KviKvsObjectFunctionCall *c);
+ bool function_killTimers(KviKvsObjectFunctionCall *c);
+ bool function_className(KviKvsObjectFunctionCall *c);
+ bool function_findChild(KviKvsObjectFunctionCall *c);
+ bool function_childCount(KviKvsObjectFunctionCall *c);
+ bool function_emit(KviKvsObjectFunctionCall *c);
+ bool function_children(KviKvsObjectFunctionCall *c);
+ bool function_signalSender(KviKvsObjectFunctionCall *c);
+ bool function_signalName(KviKvsObjectFunctionCall *c);
+ bool function_destructor(KviKvsObjectFunctionCall *c);
+ bool function_parent(KviKvsObjectFunctionCall *c);
+ bool function_property(KviKvsObjectFunctionCall *c);
+ bool function_setProperty(KviKvsObjectFunctionCall *c);
+ bool function_listProperties(KviKvsObjectFunctionCall *c);
+protected slots:
+ void delayedDie();
+ void objectDestroyed();
+};
+
+
+#define KVSO_PARAMETER(a,b,c,d) KVS_PARAMETER(a,b,c,d)
+
+#define KVSO_PARAMETERS_BEGIN(pCall) \
+ KVS_PARAMETERS_BEGIN(parameter_format_list)
+
+#define KVSO_PARAMETERS_END(pCall) \
+ KVS_PARAMETERS_END \
+ if(!KviKvsParameterProcessor::process(pCall->params(),pCall->context(),parameter_format_list))return false;
+
+
+
+
+#endif //!_KVI_KVS_OBJECT_H_
diff --git a/src/kvirc/kvs/kvi_kvs_object_class.cpp b/src/kvirc/kvs/kvi_kvs_object_class.cpp
new file mode 100644
index 00000000..312fcb46
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_object_class.cpp
@@ -0,0 +1,234 @@
+//=============================================================================
+//
+// File : kvi_kvs_objectclass.cpp
+// Created on Sat 23 Apr 2005 20:31:32 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_object_class.h"
+#include "kvi_kvs_object_controller.h"
+#include "kvi_kvs_object.h"
+#include "kvi_kvs_kernel.h"
+#include "kvi_kvs_object_functionhandlerimpl.h"
+#include "kvi_kvs_object_functioncall.h"
+#include "kvi_kvs_runtimecontext.h"
+#include "kvi_kvs_variantlist.h"
+#include "kvi_kvs_script.h"
+#include "kvi_fileutils.h"
+#include "kvi_window.h"
+#include "kvi_cmdformatter.h"
+
+KviKvsObjectClass::KviKvsObjectClass(
+ KviKvsObjectClass * pParent,
+ const QString &szName,
+ KviKvsObjectAllocateInstanceProc pProc,
+ bool bBuiltin)
+{
+ m_pParentClass = pParent;
+ if(m_pParentClass)
+ m_pParentClass->registerChildClass(this);
+ m_szName = szName;
+ m_bBuiltin = bBuiltin;
+ m_bDirty = !bBuiltin;
+ m_pFunctionHandlers = new KviPointerHashTable<QString,KviKvsObjectFunctionHandler>(17,false);
+ m_pFunctionHandlers->setAutoDelete(true);
+ m_pChildClasses = new KviPointerList<KviKvsObjectClass>;
+ m_pChildClasses->setAutoDelete(false);
+ m_allocProc = pProc ? pProc : pParent->m_allocProc;
+
+ // inherit everything from the class above
+ if(pParent)
+ {
+ KviPointerHashTableIterator<QString,KviKvsObjectFunctionHandler> it(*(pParent->functionHandlers()));
+ while(KviKvsObjectFunctionHandler * fh = it.current())
+ {
+ m_pFunctionHandlers->insert(it.currentKey(),fh->clone());
+ ++it;
+ }
+ }
+
+ // "object" class is automatically registered in the controller constructor
+ KviKvsKernel::instance()->objectController()->registerClass(this);
+}
+
+KviKvsObjectClass::~KviKvsObjectClass()
+{
+ // order here is critical
+
+ // first of all kill our child classes
+ while(m_pChildClasses->first())delete m_pChildClasses->first();
+ // then kill all objects that belong to our class
+ KviKvsKernel::instance()->objectController()->killAllObjectsWithClass(this);
+ // now we're quite clean: should have no object depending on us alive
+ // unregister from the parent, if any
+ if(m_pParentClass)m_pParentClass->unregisterChildClass(this);
+ // unregister from the object controller
+ KviKvsKernel::instance()->objectController()->unregisterClass(this);
+ // and start effectively dying
+ delete m_pFunctionHandlers;
+ // this is empty now
+ delete m_pChildClasses;
+}
+
+void KviKvsObjectClass::registerFunctionHandler(const QString & szFunctionName,KviKvsObjectFunctionHandlerProc pProc,unsigned int uFlags)
+{
+ m_pFunctionHandlers->replace(szFunctionName,new KviKvsObjectCoreCallFunctionHandler(pProc,uFlags));
+}
+
+void KviKvsObjectClass::registerFunctionHandler(const QString & szFunctionName,const QString &szBuffer,unsigned int uFlags)
+{
+ QString szContext = m_szName;
+ szContext += "::";
+ szContext += szFunctionName;
+ m_pFunctionHandlers->replace(szFunctionName,new KviKvsObjectScriptFunctionHandler(szContext,szBuffer,uFlags));
+}
+
+void KviKvsObjectClass::registerStandardNothingReturnFunctionHandler(const QString &szFunctionName)
+{
+ m_pFunctionHandlers->replace(szFunctionName,new KviKvsObjectStandardNothingReturnFunctionHandler());
+}
+
+void KviKvsObjectClass::registerStandardTrueReturnFunctionHandler(const QString &szFunctionName)
+{
+ m_pFunctionHandlers->replace(szFunctionName,new KviKvsObjectStandardTrueReturnFunctionHandler());
+}
+
+void KviKvsObjectClass::registerStandardFalseReturnFunctionHandler(const QString &szFunctionName)
+{
+ m_pFunctionHandlers->replace(szFunctionName,new KviKvsObjectStandardFalseReturnFunctionHandler());
+}
+
+
+KviKvsObject * KviKvsObjectClass::allocateInstance(KviKvsObject * pParent,const QString &szName,KviKvsRunTimeContext * pContext,KviKvsVariantList * pParams)
+{
+ if(!m_allocProc)return 0;
+ KviKvsObject * pObject = m_allocProc(this,pParent,szName);
+ if(!pObject)return 0;
+
+ KviKvsVariant * v=pParams->first(); // FIXME: what the hell is this ?
+ if(!pObject->init(pContext,pParams))
+ {
+ // internal init failure : abort
+ delete pObject;
+ return 0;
+ }
+
+ KviKvsVariant ret;
+ KviKvsVariantList copy;
+ copy.setAutoDelete(false);
+ while(v)
+ {
+ copy.append(v);
+ v = pParams->next();
+ }
+
+ if(!pObject->callFunction(pObject,"constructor",QString::null,pContext,&ret,&copy))
+ {
+ // ops...constructor failed (script error!)
+ delete pObject;
+ return 0;
+ } else {
+ if(ret.isInteger())
+ {
+ if(ret.integer() == 0)
+ {
+ // implementation failure...
+ delete pObject;
+ return 0;
+ }
+ } else if(ret.isHObject())
+ {
+ if(ret.hobject() == (kvs_hobject_t)0)
+ {
+ // implementation failure...
+ delete pObject;
+ return 0;
+ }
+ }
+ }
+
+ return pObject;
+}
+
+void KviKvsObjectClass::registerChildClass(KviKvsObjectClass *pClass)
+{
+ m_pChildClasses->append(pClass);
+}
+
+void KviKvsObjectClass::unregisterChildClass(KviKvsObjectClass *pClass)
+{
+ m_pChildClasses->removeRef(pClass);
+}
+
+bool KviKvsObjectClass::save(const QString &szFileName)
+{
+ if(!m_pParentClass)return false;
+ if(isBuiltin())return false;
+
+
+ QString szBuffer;
+ QString szParentName = m_pParentClass->name();
+
+ KviQString::sprintf(szBuffer,
+ "# Automatically generated KVS class dump\n\n" \
+ "class(\"%Q\",\"%Q\")\n" \
+ "{\n",
+ &m_szName,&szParentName);
+
+ KviPointerHashTableIterator<QString,KviKvsObjectFunctionHandler> it(*m_pFunctionHandlers);
+
+ while(KviKvsObjectFunctionHandler * h = it.current())
+ {
+ if(h->isScriptHandler())
+ {
+ szBuffer += " ";
+ if(h->flags() & KviKvsObjectFunctionHandler::Internal)
+ szBuffer += "internal ";
+ szBuffer += "function ";
+ szBuffer += it.currentKey();
+ szBuffer += "()\n";
+ QString szCode = h->scriptHandlerCode();
+ KviCommandFormatter::blockFromBuffer(szCode);
+ KviCommandFormatter::indent(szCode);
+ szBuffer += szCode;
+ szBuffer += "\n";
+ }
+ ++it;
+ }
+
+ szBuffer += "}\n";
+
+ return KviFileUtils::writeFile(szFileName,szBuffer);
+}
+void KviKvsObjectClass::getFunctionCode(QString &szCode,KviKvsObjectFunctionHandler &h)
+{
+ szCode=h.scriptHandlerCode();
+}
+
+
+
+bool KviKvsObjectClass::load(const QString &szFileName)
+{
+ QString szBuffer;
+ if(!KviFileUtils::readFile(szFileName,szBuffer,0xffffff))return false;
+ return KviKvsScript::run(szBuffer,g_pActiveWindow);
+}
diff --git a/src/kvirc/kvs/kvi_kvs_object_class.h b/src/kvirc/kvs/kvi_kvs_object_class.h
new file mode 100644
index 00000000..44b093a1
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_object_class.h
@@ -0,0 +1,102 @@
+#ifndef _KVI_KVS_OBJECTCLASS_H_
+#define _KVI_KVS_OBJECTCLASS_H_
+//=============================================================================
+//
+// File : kvi_kvs_objectclass.h
+// Created on Sat 23 Apr 2005 20:31:32 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_pointerlist.h"
+
+#include "kvi_pointerhashtable.h"
+
+#include "kvi_kvs_object_functionhandler.h"
+
+class KviKvsObject;
+class KviKvsObjectClass;
+class KviKvsRunTimeContext;
+class KviKvsVariantList;
+
+// Object allocation function
+// parameters are: the class, the parent object (eventually 0), the object name (eventually empty)
+typedef KviKvsObject * (*KviKvsObjectAllocateInstanceProc)(KviKvsObjectClass *,KviKvsObject *,const QString &);
+
+// An object function callback
+typedef bool (KviKvsObject::*KviKvsObjectFunctionHandlerProc)(KviKvsObjectFunctionCall * pCall);
+
+
+// The descriptor of a kvirc object class
+
+class KVIRC_API KviKvsObjectClass
+{
+ friend class KviKvsObject;
+ friend class KviKvsObjectController;
+public:
+ KviKvsObjectClass(
+ KviKvsObjectClass * pParent, // parent class
+ const QString & szName, // class name
+ KviKvsObjectAllocateInstanceProc proc, // intance allocation proc
+ bool bBuiltin = true // this is a builtin or script based class ?
+ );
+ ~KviKvsObjectClass();
+protected:
+ KviKvsObjectClass * m_pParentClass; // the parent (base) class
+ QString m_szName; // the class name
+ bool m_bBuiltin; // is this a builtin or script based class ?
+ KviPointerHashTable<QString,KviKvsObjectFunctionHandler> * m_pFunctionHandlers; // all our function handlers
+ KviPointerList<KviKvsObjectClass> * m_pChildClasses; //
+ KviKvsObjectAllocateInstanceProc m_allocProc;
+ bool m_bDirty; // not yet flushed to disk (only for not builtin classes)
+protected:
+ void registerChildClass(KviKvsObjectClass *pClass);
+ void unregisterChildClass(KviKvsObjectClass *pClass);
+ KviPointerHashTable<QString,KviKvsObjectFunctionHandler> * functionHandlers(){ return m_pFunctionHandlers; };
+public:
+ void clearDirtyFlag(){ m_bDirty = false; };
+ bool isDirty(){ return m_bDirty; };
+ bool isBuiltin(){ return m_bBuiltin; };
+ const QString & name(){ return m_szName; };
+ KviKvsObjectClass * parentClass(){ return m_pParentClass; };
+ // pProc CAN'T be zero here!
+ void registerFunctionHandler(const QString & szFunctionName,KviKvsObjectFunctionHandlerProc pProc,unsigned int uFlags = 0);
+ void registerFunctionHandler(const QString & szFunctionName,const QString &szBuffer,unsigned int uFlags = 0);
+
+ // registers an empty handler that returns "nothing"
+ void registerStandardNothingReturnFunctionHandler(const QString & szFunc);
+ // retisters an empty handler that returns $true
+ void registerStandardTrueReturnFunctionHandler(const QString & szFunc);
+ // retisters an empty handler that returns $false
+ void registerStandardFalseReturnFunctionHandler(const QString & szFunc);
+
+ KviKvsObjectFunctionHandler * lookupFunctionHandler(const QString & szFunc){ return m_pFunctionHandlers->find(szFunc); };
+ KviKvsObject * allocateInstance(KviKvsObject * pParent,const QString &szName,KviKvsRunTimeContext * pContext,KviKvsVariantList * pParams);
+
+ bool save(const QString &szFileName);
+ static bool load(const QString &szFileName);
+ void getFunctionCode(QString &szCode,KviKvsObjectFunctionHandler &h);
+ KviPointerHashTable<QString,KviKvsObjectFunctionHandler> * getHandlers(){return m_pFunctionHandlers;};
+
+};
+
+
+#endif //!_KVI_KVS_OBJECTCLASS_H_
diff --git a/src/kvirc/kvs/kvi_kvs_object_controller.cpp b/src/kvirc/kvs/kvi_kvs_object_controller.cpp
new file mode 100644
index 00000000..c13b068c
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_object_controller.cpp
@@ -0,0 +1,229 @@
+//=============================================================================
+//
+// File : kvi_kvs_object_controller.cpp
+// Created on Sun 24 Apr 2005 05:23:04 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2005-2006 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_object_controller.h"
+#include "kvi_modulemanager.h"
+#include "kvi_fileutils.h"
+#include "kvi_app.h"
+
+////////////////////////////////////////////////////////////////////////////////////////
+
+static KviKvsObject * objectClassCreateInstance(KviKvsObjectClass *pClass,KviKvsObject *pParent,const QString &szName)
+{
+ return new KviKvsObject(pClass,pParent,szName);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+
+KviKvsObjectController::KviKvsObjectController()
+{
+ m_pTopLevelObjectList = new KviPointerList<KviKvsObject>;
+ m_pTopLevelObjectList->setAutoDelete(false);
+ m_pObjectDict = new KviPointerHashTable<void *,KviKvsObject>(101);
+ m_pObjectDict->setAutoDelete(false);
+ m_pClassDict = new KviPointerHashTable<QString,KviKvsObjectClass>(31,false);
+ m_pClassDict->setAutoDelete(false);
+}
+
+KviKvsObjectController::~KviKvsObjectController()
+{
+ flushUserClasses();
+ while(m_pTopLevelObjectList->first())delete m_pTopLevelObjectList->first();
+ delete m_pTopLevelObjectList; // empty list
+ delete m_pObjectDict; // empty dict
+ m_pObjectDict = 0;
+ delete m_pObjectClass; // delete the class tree
+ delete m_pClassDict; // empty dict
+}
+
+void KviKvsObjectController::init()
+{
+ // allocate the "object" builtin class
+ // this is the only one that is always in core memory
+ m_pObjectClass = new KviKvsObjectClass(0,"object",objectClassCreateInstance,true);
+
+ m_pObjectClass->registerFunctionHandler("name",KVI_PTR2MEMBER(KviKvsObject::function_name));
+ m_pObjectClass->registerFunctionHandler("startTimer",KVI_PTR2MEMBER(KviKvsObject::function_startTimer));
+ m_pObjectClass->registerFunctionHandler("killTimer",KVI_PTR2MEMBER(KviKvsObject::function_killTimer));
+ m_pObjectClass->registerFunctionHandler("killTimers",KVI_PTR2MEMBER(KviKvsObject::function_killTimers));
+ m_pObjectClass->registerFunctionHandler("className",KVI_PTR2MEMBER(KviKvsObject::function_className));
+ m_pObjectClass->registerFunctionHandler("findChild",KVI_PTR2MEMBER(KviKvsObject::function_findChild));
+ m_pObjectClass->registerFunctionHandler("childCount",KVI_PTR2MEMBER(KviKvsObject::function_childCount));
+ m_pObjectClass->registerFunctionHandler("emit",KVI_PTR2MEMBER(KviKvsObject::function_emit));
+ m_pObjectClass->registerFunctionHandler("children",KVI_PTR2MEMBER(KviKvsObject::function_children));
+ m_pObjectClass->registerFunctionHandler("signalSender",KVI_PTR2MEMBER(KviKvsObject::function_signalSender));
+ m_pObjectClass->registerFunctionHandler("signalName",KVI_PTR2MEMBER(KviKvsObject::function_signalName));
+ m_pObjectClass->registerFunctionHandler("destructor",KVI_PTR2MEMBER(KviKvsObject::function_destructor));
+ m_pObjectClass->registerFunctionHandler("parent",KVI_PTR2MEMBER(KviKvsObject::function_parent));
+ m_pObjectClass->registerFunctionHandler("property",KVI_PTR2MEMBER(KviKvsObject::function_property));
+ m_pObjectClass->registerFunctionHandler("setProperty",KVI_PTR2MEMBER(KviKvsObject::function_setProperty));
+ m_pObjectClass->registerFunctionHandler("listProperties",KVI_PTR2MEMBER(KviKvsObject::function_listProperties));
+
+ m_pObjectClass->registerStandardNothingReturnFunctionHandler("constructor");
+ m_pObjectClass->registerStandardNothingReturnFunctionHandler("timerEvent");
+
+ m_pClassDict->insert("object",m_pObjectClass);
+}
+
+void KviKvsObjectController::killAllObjectsWithClass(KviKvsObjectClass * pClass)
+{
+ if(!m_pObjectDict)return; // no more objects at all...
+ KviPointerList<KviKvsObject> l;
+ l.setAutoDelete(true);
+
+ for(KviKvsObject * o = m_pTopLevelObjectList->first();o;o = m_pTopLevelObjectList->next())
+ {
+ if(o->getClass() == pClass)l.append(o);
+ else o->killAllChildrenWithClass(pClass);
+ }
+}
+
+void KviKvsObjectController::clearUserClasses()
+{
+ flushUserClasses();
+ KviPointerHashTableIterator<QString,KviKvsObjectClass> it(*m_pClassDict);
+ KviPointerList<KviKvsObjectClass> l;
+ l.setAutoDelete(true);
+ while(it.current())
+ {
+ if(!(it.current()->isBuiltin()))
+ {
+ l.append(it.current());
+ }
+ ++it;
+ }
+}
+
+void KviKvsObjectController::clearInstances()
+{
+ while(m_pTopLevelObjectList->first())delete m_pTopLevelObjectList->first();
+ delete m_pTopLevelObjectList; // empty list
+ delete m_pObjectDict; // empty dict
+ m_pTopLevelObjectList = new KviPointerList<KviKvsObject>;
+ m_pTopLevelObjectList->setAutoDelete(false);
+ m_pObjectDict = new KviPointerHashTable<void *,KviKvsObject>(101);
+ m_pObjectDict->setAutoDelete(false);
+}
+
+void KviKvsObjectController::registerClass(KviKvsObjectClass *pClass)
+{
+ m_pClassDict->insert(pClass->name(),pClass);
+}
+
+void KviKvsObjectController::unregisterClass(KviKvsObjectClass *pClass)
+{
+ if(!pClass->isBuiltin())
+ {
+ if(pClass->isDirty())flushUserClasses();
+ }
+ m_pClassDict->remove(pClass->name());
+}
+
+void KviKvsObjectController::registerObject(KviKvsObject *pObject)
+{
+ m_pObjectDict->insert(pObject->handle(),pObject);
+ if(pObject->parent() == 0)m_pTopLevelObjectList->append(pObject);
+}
+
+void KviKvsObjectController::unregisterObject(KviKvsObject *pObject)
+{
+ m_pObjectDict->remove(pObject->handle());
+ if(pObject->parent() == 0)m_pTopLevelObjectList->removeRef(pObject);
+}
+
+void KviKvsObjectController::flushUserClasses()
+{
+ KviPointerHashTableIterator<QString,KviKvsObjectClass> it(*m_pClassDict);
+ while(KviKvsObjectClass * c = it.current())
+ {
+ if(!c->isBuiltin())
+ {
+ if(c->isDirty())
+ {
+ QString szPath;
+ QString szFileName = c->name().lower();
+ szFileName += ".kvs";
+ szFileName.replace("::","--");
+ g_pApp->getLocalKvircDirectory(szPath,KviApp::Classes,szFileName);
+ if(c->save(szPath))
+ c->clearDirtyFlag();
+ else
+ debug("Oops.. failed to save the object class %s",c->name().latin1());
+ }
+ }
+ ++it;
+ }
+}
+
+KviKvsObjectClass * KviKvsObjectController::lookupClass(const QString &szClass,bool bBuiltinOnly)
+{
+ KviKvsObjectClass * pC = m_pClassDict->find(szClass);
+ if(!pC)
+ {
+ // maybe we need to load the object library ?
+ KviModule * pModule = g_pModuleManager->getModule("objects");
+ if(!pModule)
+ {
+ debug("ops...something wrong with the libkviobjects module!");
+ return 0;
+ } else pC = m_pClassDict->find(szClass);
+ if(!pC)
+ {
+ if(bBuiltinOnly)return 0;
+ // maybe we need to load it from permanent storage...
+ QString szPath;
+ QString szFileName = szClass.lower();
+ szFileName += ".kvs";
+ szFileName.replace("::","--");
+ g_pApp->getLocalKvircDirectory(szPath,KviApp::Classes,szFileName);
+ if(!KviFileUtils::fileExists(szPath))
+ g_pApp->getGlobalKvircDirectory(szPath,KviApp::Classes,szFileName);
+ if(!KviFileUtils::fileExists(szPath))return 0;
+ if(!KviKvsObjectClass::load(szPath))return 0;
+ pC = m_pClassDict->find(szClass);
+ if(pC)pC->clearDirtyFlag(); // just loaded from disk: no need to sync it
+ }
+ } else {
+ if(bBuiltinOnly)
+ {
+ if(!pC->isBuiltin())return 0;
+ }
+ }
+ return pC;
+};
+
+
+void KviKvsObjectController::deleteClass(KviKvsObjectClass * pClass)
+{
+ QString szPath;
+ QString szFileName = pClass->name().lower();
+ szFileName += ".kvs";
+ szFileName.replace("::","--");
+ g_pApp->getLocalKvircDirectory(szPath,KviApp::Classes,szFileName);
+ KviFileUtils::removeFile(szPath);
+ delete pClass;
+}
+
diff --git a/src/kvirc/kvs/kvi_kvs_object_controller.h b/src/kvirc/kvs/kvi_kvs_object_controller.h
new file mode 100644
index 00000000..3df0daad
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_object_controller.h
@@ -0,0 +1,70 @@
+#ifndef _KVI_KVS_OBJECT_CONTROLLER_H_
+#define _KVI_KVS_OBJECT_CONTROLLER_H_
+//=============================================================================
+//
+// File : kvi_kvs_object_controller.h
+// Created on Sun 24 Apr 2005 05:23:04 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+
+#include "kvi_settings.h"
+
+#include "kvi_qstring.h"
+#include "kvi_pointerlist.h"
+
+#include "kvi_pointerhashtable.h"
+#include "kvi_pointerhashtable.h"
+
+#include "kvi_kvs_object.h"
+#include "kvi_kvs_object_class.h"
+
+class KVIRC_API KviKvsObjectController
+{
+ friend class KviKvsObject;
+ friend class KviKvsObjectClass;
+public:
+ KviKvsObjectController();
+ ~KviKvsObjectController();
+protected:
+ KviPointerList<KviKvsObject> * m_pTopLevelObjectList;
+ KviPointerHashTable<void *,KviKvsObject> * m_pObjectDict;
+ KviPointerHashTable<QString,KviKvsObjectClass> * m_pClassDict;
+ KviKvsObjectClass * m_pObjectClass; //base class
+protected:
+ // the classes and the objects register themselves with the controller
+ void registerObject(KviKvsObject *pObject);
+ void unregisterObject(KviKvsObject *pObject);
+ void registerClass(KviKvsObjectClass *pClass);
+ void unregisterClass(KviKvsObjectClass *pClass);
+public:
+ void init();
+ void deleteClass(KviKvsObjectClass * pClass);
+ void clearInstances();
+ void clearUserClasses();
+ void flushUserClasses();
+ void killAllObjectsWithClass(KviKvsObjectClass * pClass);
+ KviKvsObjectClass * lookupClass(const QString &szClass,bool bBuiltinOnly = false);
+ KviKvsObject * lookupObject(kvs_hobject_t hObject){ return m_pObjectDict->find(hObject); };
+ KviPointerHashTable<void *,KviKvsObject> * objectDict(){ return m_pObjectDict; };
+ KviPointerHashTable<QString,KviKvsObjectClass> * classDict(){ return m_pClassDict; };
+};
+
+#endif //!_KVI_KVS_OBJECT_CONTROLLER_H_
diff --git a/src/kvirc/kvs/kvi_kvs_object_functioncall.cpp b/src/kvirc/kvs/kvi_kvs_object_functioncall.cpp
new file mode 100644
index 00000000..35143a60
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_object_functioncall.cpp
@@ -0,0 +1,28 @@
+//=============================================================================
+//
+// File : kvi_kvs_object_functioncall.cpp
+// Created on Sun 24 Apr 2005 04:05:54 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_object_functioncall.h"
+
diff --git a/src/kvirc/kvs/kvi_kvs_object_functioncall.h b/src/kvirc/kvs/kvi_kvs_object_functioncall.h
new file mode 100644
index 00000000..a5a87f5c
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_object_functioncall.h
@@ -0,0 +1,49 @@
+#ifndef _KVI_KVS_OBJECT_FUNCTIONCALL_H_
+#define _KVI_KVS_OBJECT_FUNCTIONCALL_H_
+//=============================================================================
+//
+// File : kvi_kvs_object_functioncall.h
+// Created on Sun 24 Apr 2005 04:05:54 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#include "kvi_kvs_runtimecall.h"
+#include "kvi_kvs_variantlist.h"
+#include "kvi_kvs_variant.h"
+
+
+class KVIRC_API KviKvsObjectFunctionCall : public KviKvsRunTimeCall
+{
+protected:
+ KviKvsVariant * m_pResult;
+public:
+ KviKvsObjectFunctionCall(KviKvsRunTimeContext * pContext,
+ KviKvsVariantList * pParams,
+ KviKvsVariant * pResult)
+ : KviKvsRunTimeCall(pContext,pParams), m_pResult(pResult)
+ {};
+ ~KviKvsObjectFunctionCall(){};
+public:
+ KviKvsVariant * returnValue(){ return m_pResult; };
+};
+
+#endif //!_KVI_KVS_OBJECT_FUNCTIONCALL_H_
diff --git a/src/kvirc/kvs/kvi_kvs_object_functionhandler.cpp b/src/kvirc/kvs/kvi_kvs_object_functionhandler.cpp
new file mode 100644
index 00000000..9dbf541c
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_object_functionhandler.cpp
@@ -0,0 +1,50 @@
+//=============================================================================
+//
+// File : kvi_kvs_object_functionhandler.cpp
+// Created on Sat 23 Apr 2005 21:53:23 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_object_functionhandler.h"
+
+KviKvsObjectFunctionHandler::KviKvsObjectFunctionHandler(unsigned int uFlags)
+: m_uFlags(uFlags)
+{
+}
+
+KviKvsObjectFunctionHandler::~KviKvsObjectFunctionHandler()
+{
+}
+
+bool KviKvsObjectFunctionHandler::isScriptHandler()
+{
+ return false;
+}
+
+QString KviKvsObjectFunctionHandler::scriptHandlerCode()
+{
+ return QString::null;
+}
+
+
+
+
diff --git a/src/kvirc/kvs/kvi_kvs_object_functionhandler.h b/src/kvirc/kvs/kvi_kvs_object_functionhandler.h
new file mode 100644
index 00000000..6b241e28
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_object_functionhandler.h
@@ -0,0 +1,57 @@
+#ifndef _KVI_KVS_OBJECT_FUNCTIONHANDLER_H_
+#define _KVI_KVS_OBJECT_FUNCTIONHANDLER_H_
+//=============================================================================
+//
+// File : kvi_kvs_object_functionhandler.h
+// Created on Sat 23 Apr 2005 21:53:23 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+
+class KviKvsObjectClass;
+class KviKvsObjectFunctionCall;
+class KviKvsObject;
+
+
+class KVIRC_API KviKvsObjectFunctionHandler
+{
+ friend class KviKvsObject;
+ friend class KviKvsObjectClass;
+public:
+ enum Flags { Internal = 1 };
+protected:
+ unsigned int m_uFlags;
+protected:
+ KviKvsObjectFunctionHandler(unsigned int uFlags = 0);
+public:
+ virtual ~KviKvsObjectFunctionHandler();
+public:
+ unsigned int flags(){ return m_uFlags; };
+protected:
+ virtual bool isScriptHandler();
+ virtual QString scriptHandlerCode();
+ virtual KviKvsObjectFunctionHandler * clone() = 0;
+ virtual bool call(KviKvsObject * pObject,KviKvsObjectFunctionCall * pCall) = 0;
+};
+
+
+#endif //!_KVI_KVS_OBJECT_FUNCTIONHANDLER_H_
diff --git a/src/kvirc/kvs/kvi_kvs_object_functionhandlerimpl.cpp b/src/kvirc/kvs/kvi_kvs_object_functionhandlerimpl.cpp
new file mode 100644
index 00000000..77c41019
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_object_functionhandlerimpl.cpp
@@ -0,0 +1,148 @@
+//=============================================================================
+//
+// File : kvi_kvs_object_functionhandlerimpl.cpp
+// Created on Sun 24 Apr 2005 04:01:14 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_object_functionhandlerimpl.h"
+#include "kvi_kvs_object_functioncall.h"
+#include "kvi_kvs_script.h"
+
+
+
+KviKvsObjectFunctionHandler * KviKvsObjectStandardTrueReturnFunctionHandler::clone()
+{
+ return new KviKvsObjectStandardTrueReturnFunctionHandler();
+}
+
+bool KviKvsObjectStandardTrueReturnFunctionHandler::call(KviKvsObject * pObject,KviKvsObjectFunctionCall * pCall)
+{
+ pCall->returnValue()->setBoolean(true);
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+KviKvsObjectFunctionHandler * KviKvsObjectStandardFalseReturnFunctionHandler::clone()
+{
+ return new KviKvsObjectStandardFalseReturnFunctionHandler();
+}
+
+bool KviKvsObjectStandardFalseReturnFunctionHandler::call(KviKvsObject * pObject,KviKvsObjectFunctionCall * pCall)
+{
+ pCall->returnValue()->setBoolean(false);
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+KviKvsObjectFunctionHandler * KviKvsObjectStandardNothingReturnFunctionHandler::clone()
+{
+ return new KviKvsObjectStandardNothingReturnFunctionHandler();
+}
+
+bool KviKvsObjectStandardNothingReturnFunctionHandler::call(KviKvsObject * pObject,KviKvsObjectFunctionCall * pCall)
+{
+ pCall->returnValue()->setNothing();
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+KviKvsObjectCoreCallFunctionHandler::KviKvsObjectCoreCallFunctionHandler(KviKvsObjectFunctionHandlerProc pProc,unsigned int uFlags)
+: KviKvsObjectFunctionHandler(uFlags)
+{
+ m_pProc = pProc;
+}
+
+KviKvsObjectCoreCallFunctionHandler::KviKvsObjectCoreCallFunctionHandler(const KviKvsObjectCoreCallFunctionHandler &h)
+: KviKvsObjectFunctionHandler(h.m_uFlags)
+{
+ m_pProc = h.m_pProc;
+}
+
+KviKvsObjectCoreCallFunctionHandler::~KviKvsObjectCoreCallFunctionHandler()
+{
+}
+
+KviKvsObjectFunctionHandler * KviKvsObjectCoreCallFunctionHandler::clone()
+{
+ return new KviKvsObjectCoreCallFunctionHandler(*this);
+}
+
+bool KviKvsObjectCoreCallFunctionHandler::call(KviKvsObject * pObject,KviKvsObjectFunctionCall * pCall)
+{
+ // Actually m_pProc can't be 0: if it's zero then it's a BUG and should be traced down: we just crash
+ //if(m_pProc)
+ return (pObject->*m_pProc)(pCall);
+ //else {
+ // empty handler
+ //pCall->returnValue()->setNothing();
+ //return true;
+ //}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+KviKvsObjectScriptFunctionHandler::KviKvsObjectScriptFunctionHandler(const QString &szScriptContext,const QString &szCode,unsigned int uFlags)
+: KviKvsObjectFunctionHandler(uFlags)
+{
+ m_pHandler = new KviKvsScript(szScriptContext,szCode,KviKvsScript::InstructionList);
+}
+
+KviKvsObjectScriptFunctionHandler::KviKvsObjectScriptFunctionHandler(const KviKvsObjectScriptFunctionHandler &h)
+: KviKvsObjectFunctionHandler(h.m_uFlags)
+{
+ // ref
+ m_pHandler = new KviKvsScript(*(h.m_pHandler));
+}
+
+KviKvsObjectScriptFunctionHandler::~KviKvsObjectScriptFunctionHandler()
+{
+ delete m_pHandler;
+}
+
+bool KviKvsObjectScriptFunctionHandler::isScriptHandler()
+{
+ return true;
+}
+
+QString KviKvsObjectScriptFunctionHandler::scriptHandlerCode()
+{
+ return m_pHandler->code();
+}
+
+
+
+
+KviKvsObjectFunctionHandler * KviKvsObjectScriptFunctionHandler::clone()
+{
+ return new KviKvsObjectScriptFunctionHandler(*this);
+}
+
+bool KviKvsObjectScriptFunctionHandler::call(KviKvsObject * pObject,KviKvsObjectFunctionCall * pCall)
+{
+ KviKvsExtendedRunTimeData rd(pObject);
+ return m_pHandler->run(pCall->window(),pCall->params(),pCall->returnValue(),KviKvsScript::PreserveParams,&rd);
+}
+
diff --git a/src/kvirc/kvs/kvi_kvs_object_functionhandlerimpl.h b/src/kvirc/kvs/kvi_kvs_object_functionhandlerimpl.h
new file mode 100644
index 00000000..37f506a9
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_object_functionhandlerimpl.h
@@ -0,0 +1,115 @@
+#ifndef _KVI_KVS_OBJECT_FUNCTIONHANDLERIMPL_H_
+#define _KVI_KVS_OBJECT_FUNCTIONHANDLERIMPL_H_
+//=============================================================================
+//
+// File : kvi_kvs_object_functionhandlerimpl.h
+// Created on Sun 24 Apr 2005 04:01:14 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+
+#include "kvi_settings.h"
+#include "kvi_kvs_object.h"
+#include "kvi_kvs_object_class.h"
+#include "kvi_kvs_object_functionhandler.h"
+#include "kvi_qstring.h"
+
+class KviKvsObjectClass;
+class KviKvsScript;
+class KviKvsObjectFunctionCall;
+
+
+class KVIRC_API KviKvsObjectCoreCallFunctionHandler : public KviKvsObjectFunctionHandler
+{
+ friend class KviKvsObject;
+ friend class KviKvsObjectClass;
+protected:
+ KviKvsObjectCoreCallFunctionHandler(KviKvsObjectFunctionHandlerProc pProc,unsigned int uFlags = 0);
+ KviKvsObjectCoreCallFunctionHandler(const KviKvsObjectCoreCallFunctionHandler &h);
+public:
+ virtual ~KviKvsObjectCoreCallFunctionHandler();
+protected:
+ KviKvsObjectFunctionHandlerProc m_pProc;
+protected:
+ virtual KviKvsObjectFunctionHandler * clone();
+ virtual bool call(KviKvsObject * pObject,KviKvsObjectFunctionCall * pCall);
+};
+
+class KVIRC_API KviKvsObjectScriptFunctionHandler : public KviKvsObjectFunctionHandler
+{
+ friend class KviKvsObject;
+ friend class KviKvsObjectClass;
+protected:
+ KviKvsObjectScriptFunctionHandler(const QString &szScriptContext,const QString &szCode,unsigned int uFlags = 0);
+ KviKvsObjectScriptFunctionHandler(const KviKvsObjectScriptFunctionHandler &h);
+public:
+ virtual ~KviKvsObjectScriptFunctionHandler();
+protected:
+ KviKvsScript * m_pHandler;
+protected:
+ virtual bool isScriptHandler();
+ virtual QString scriptHandlerCode();
+ virtual KviKvsObjectFunctionHandler * clone();
+ virtual bool call(KviKvsObject * pObject,KviKvsObjectFunctionCall * pCall);
+};
+
+class KVIRC_API KviKvsObjectStandardTrueReturnFunctionHandler : public KviKvsObjectFunctionHandler
+{
+ friend class KviKvsObject;
+ friend class KviKvsObjectClass;
+protected:
+ KviKvsObjectStandardTrueReturnFunctionHandler()
+ : KviKvsObjectFunctionHandler() {};
+public:
+ virtual ~KviKvsObjectStandardTrueReturnFunctionHandler(){};
+protected:
+ virtual KviKvsObjectFunctionHandler * clone();
+ virtual bool call(KviKvsObject * pObject,KviKvsObjectFunctionCall * pCall);
+};
+
+class KVIRC_API KviKvsObjectStandardFalseReturnFunctionHandler : public KviKvsObjectFunctionHandler
+{
+ friend class KviKvsObject;
+ friend class KviKvsObjectClass;
+protected:
+ KviKvsObjectStandardFalseReturnFunctionHandler()
+ : KviKvsObjectFunctionHandler() {};
+public:
+ virtual ~KviKvsObjectStandardFalseReturnFunctionHandler(){};
+protected:
+ virtual KviKvsObjectFunctionHandler * clone();
+ virtual bool call(KviKvsObject * pObject,KviKvsObjectFunctionCall * pCall);
+};
+
+class KVIRC_API KviKvsObjectStandardNothingReturnFunctionHandler : public KviKvsObjectFunctionHandler
+{
+ friend class KviKvsObject;
+ friend class KviKvsObjectClass;
+protected:
+ KviKvsObjectStandardNothingReturnFunctionHandler()
+ : KviKvsObjectFunctionHandler() {};
+public:
+ virtual ~KviKvsObjectStandardNothingReturnFunctionHandler(){};
+protected:
+ virtual KviKvsObjectFunctionHandler * clone();
+ virtual bool call(KviKvsObject * pObject,KviKvsObjectFunctionCall * pCall);
+};
+
+#endif //!_KVI_KVS_OBJECT_FUNCTIONHANDLERIMPL_H_
diff --git a/src/kvirc/kvs/kvi_kvs_parameterprocessor.cpp b/src/kvirc/kvs/kvi_kvs_parameterprocessor.cpp
new file mode 100644
index 00000000..fdd0639f
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_parameterprocessor.cpp
@@ -0,0 +1,371 @@
+//=============================================================================
+//
+// File : kvi_kvs_parameterprocessor.cpp
+// Created on Sun 17 Apr 2005 16:47:09 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_parameterprocessor.h"
+#include "kvi_kvs_variantlist.h"
+#include "kvi_kvs_runtimecontext.h"
+#include "kvi_kvs_variantlist.h"
+#include "kvi_kvs_array.h"
+#include "kvi_kvs_arraycast.h"
+#include "kvi_kvs_hash.h"
+#include "kvi_kvs_object.h"
+
+#include "kvi_qstring.h"
+#include "kvi_locale.h"
+#include "kvi_pointerlist.h"
+
+
+#include <qstringlist.h>
+
+namespace KviKvsParameterProcessor
+{
+ void setDefaultValue(KviKvsParameterProcessor::ParameterFormat * pFmtArray)
+ {
+#ifdef COMPILE_NEW_KVS
+ switch(pFmtArray->uType)
+ {
+ case KVS_PT_STRING:
+ case KVS_PT_NONEMPTYSTRING:
+ *((QString *)(pFmtArray->pContainer)) = QString::null;
+ break;
+ case KVS_PT_INT:
+ *((kvs_int_t *)(pFmtArray->pContainer)) = 0;
+ break;
+ case KVS_PT_UINT:
+ *((kvs_uint_t *)(pFmtArray->pContainer)) = 0;
+ break;
+ case KVS_PT_DOUBLE:
+ *((kvs_real_t *)(pFmtArray->pContainer)) = 0.0;
+ break;
+ case KVS_PT_BOOL:
+ *((bool *)(pFmtArray->pContainer)) = false;
+ break;
+ case KVS_PT_HASH:
+ *((KviKvsHash **)(pFmtArray->pContainer)) = 0;
+ break;
+ case KVS_PT_ARRAY:
+ *((KviKvsArray **)(pFmtArray->pContainer)) = 0;
+ break;
+ case KVS_PT_ARRAYCAST:
+ ((KviKvsArrayCast *)(pFmtArray->pContainer))->clear();
+ break;
+ case KVS_PT_VARIANT:
+ *((KviKvsVariant **)(pFmtArray->pContainer)) = 0;
+ break;
+ case KVS_PT_CSTRING:
+ case KVS_PT_NONEMPTYCSTRING:
+ *((KviQCString *)(pFmtArray->pContainer)) = 0;
+ break;
+ case KVS_PT_STRINGLIST:
+ ((QStringList *)(pFmtArray->pContainer))->clear();
+ break;
+ case KVS_PT_VARIANTLIST:
+ ((KviKvsVariantList *)(pFmtArray->pContainer))->clear();
+ ((KviKvsVariantList *)(pFmtArray->pContainer))->setAutoDelete(false);
+ break;
+ case KVS_PT_HOBJECT:
+ *((kvs_hobject_t *)(pFmtArray->pContainer)) = (kvs_hobject_t)0;
+ break;
+ case KVS_PT_IGNORE:
+ // ignore :)
+ break;
+ default:
+ debug("Internal error in KviKvsParameterProcessor::setDefaultValue(): unknown parameter type %d",pFmtArray->uType);
+ break;
+ }
+#endif
+ }
+
+ bool handleParameterTypeError(KviKvsRunTimeContext * pContext,KviKvsParameterProcessor::ParameterFormat * pFmtArray,KviKvsVariant * v,const char * szExpectedType)
+ {
+ if(pFmtArray->uFlags & KVS_PF_OPTIONAL)
+ {
+ if(v->isEmpty())
+ {
+ setDefaultValue(pFmtArray);
+ return true; // empty optional
+ }
+ }
+
+ QString szError;
+ KviQString::sprintf(szError,__tr2qs("Invalid data type for parameter \"%s\""),pFmtArray->szName);
+ szError += ": ";
+
+ if(v->isString())
+ {
+ QString tmp = v->string();
+ if(tmp.isEmpty())
+ {
+ KviQString::appendFormatted(szError,__tr2qs("found empty string where type '%s' was expected"),&tmp,szExpectedType);
+ } else {
+ if(tmp.length() > 15)
+ {
+ tmp.truncate(15);
+ tmp.append("...");
+ }
+ KviQString::appendFormatted(szError,__tr2qs("found string value \"%Q\" where type '%s' was expected"),&tmp,szExpectedType);
+ }
+ } else {
+ QString tmp;
+ v->getTypeName(tmp);
+ KviQString::appendFormatted(szError,__tr2qs("found type %Q where type '%s' was expected"),&tmp,szExpectedType);
+ }
+ pContext->error(szError);
+ return false;
+ }
+
+ bool process(KviKvsVariantList * pVariantList,KviKvsRunTimeContext * pContext,KviKvsParameterProcessor::ParameterFormat * pFmtArray)
+ {
+ KviKvsVariant * v = pVariantList->first();
+
+ while(pFmtArray->szName)
+ {
+ if(!v)
+ {
+ // parameter not present
+ // it MUST be optional
+ if(!(pFmtArray->uFlags & KVS_PF_OPTIONAL))
+ {
+ // bad luck
+ QString szError;
+ KviQString::sprintf(szError,__tr2qs("Missing non-optional parameter \"%s\""),pFmtArray->szName);
+ pContext->error(szError);
+ return false;
+ }
+ // ok, missing but optional (all the following are implicitly optional too)
+ // set to default values
+ do {
+ setDefaultValue(pFmtArray);
+ pFmtArray++;
+ } while(pFmtArray->szName);
+ return true;
+ }
+ // here we do only "light" casts: hard ones must be done explicitly by the user
+ switch(pFmtArray->uType)
+ {
+ case KVS_PT_STRING:
+ v->asString(*((QString *)(pFmtArray->pContainer)));
+ if(pFmtArray->uFlags & KVS_PF_APPENDREMAINING)
+ {
+ v = pVariantList->next();
+ while(v)
+ {
+ *((QString *)(pFmtArray->pContainer)) += QChar(' ');
+ v->appendAsString(*((QString *)(pFmtArray->pContainer)));
+ v = pVariantList->next();
+ }
+ return true;
+ }
+ break;
+ case KVS_PT_STRINGLIST:
+ {
+ ((QStringList *)(pFmtArray->pContainer))->clear();
+ QString pSz;
+ v->asString(pSz);
+ ((QStringList *)(pFmtArray->pContainer))->append(pSz);
+ v = pVariantList->next();
+ while(v)
+ {
+ v->asString(pSz);
+ ((QStringList *)(pFmtArray->pContainer))->append(pSz);
+ v = pVariantList->next();
+ }
+ return true;
+ }
+ break;
+ case KVS_PT_VARIANTLIST:
+ {
+ ((KviKvsVariantList *)(pFmtArray->pContainer))->clear();
+ ((KviKvsVariantList *)(pFmtArray->pContainer))->setAutoDelete(false);
+ ((KviKvsVariantList *)(pFmtArray->pContainer))->append(v);
+ v = pVariantList->next();
+ while(v)
+ {
+ ((KviKvsVariantList *)(pFmtArray->pContainer))->append(v);
+ v = pVariantList->next();
+ }
+ return true;
+ }
+ break;
+ case KVS_PT_NONEMPTYSTRING:
+ {
+ v->asString(*((QString *)(pFmtArray->pContainer)));
+ bool bDoReturn = false;
+ if(pFmtArray->uFlags & KVS_PF_APPENDREMAINING)
+ {
+ v = pVariantList->next();
+ while(v)
+ {
+ *((QString *)(pFmtArray->pContainer)) += QChar(' ');
+ v->appendAsString(*((QString *)(pFmtArray->pContainer)));
+ v = pVariantList->next();
+ }
+ bDoReturn = true;
+ }
+ if(((QString *)(pFmtArray->pContainer))->isEmpty())
+ {
+ QString szError;
+ KviQString::sprintf(szError,__tr2qs("Invalid data type for parameter \"%s\""),pFmtArray->szName);
+ szError += ": ";
+ KviQString::sprintf(szError,__tr2qs("found empty string while a non empty one was expected"));
+ pContext->error(szError);
+ return false;
+ }
+ if(bDoReturn)return true;
+ }
+ break;
+ case KVS_PT_CSTRING:
+ {
+ QString tmp;
+ v->asString(tmp);
+ if(pFmtArray->uFlags & KVS_PF_APPENDREMAINING)
+ {
+ v = pVariantList->next();
+ while(v)
+ {
+ *((KviQCString *)(pFmtArray->pContainer)) += ' ';
+ v->appendAsString(tmp);
+ v = pVariantList->next();
+ }
+ *((KviQCString *)(pFmtArray->pContainer)) = tmp.utf8();
+ return true;
+ }
+ *((KviQCString *)(pFmtArray->pContainer)) = tmp.utf8();
+ }
+ break;
+ case KVS_PT_NONEMPTYCSTRING:
+ {
+ QString tmp;
+ v->asString(tmp);
+ bool bDoReturn = false;
+ if(pFmtArray->uFlags & KVS_PF_APPENDREMAINING)
+ {
+ v = pVariantList->next();
+ while(v)
+ {
+ *((KviQCString *)(pFmtArray->pContainer)) += ' ';
+ v->appendAsString(tmp);
+ v = pVariantList->next();
+ }
+ *((KviQCString *)(pFmtArray->pContainer)) = tmp.utf8();
+ bDoReturn = true;
+ }
+ *((KviQCString *)(pFmtArray->pContainer)) = tmp.utf8();
+ if(((KviQCString *)(pFmtArray->pContainer))->isEmpty())
+ {
+ QString szError;
+ KviQString::sprintf(szError,__tr2qs("Invalid data type for parameter \"%s\""),pFmtArray->szName);
+ szError += ": ";
+ KviQString::sprintf(szError,__tr2qs("found empty string while a non empty one was expected"));
+ pContext->error(szError);
+ return false;
+ }
+ if(bDoReturn)return true;
+ }
+ break;
+ case KVS_PT_INT:
+ if(!v->asInteger(*((kvs_int_t *)(pFmtArray->pContainer))))
+ {
+ if(!handleParameterTypeError(pContext,pFmtArray,v,"integer"))
+ return false;
+ }
+ break;
+ case KVS_PT_UINT:
+ {
+ kvs_int_t iTmp;
+ if(!v->asInteger(iTmp))
+ {
+ if(!handleParameterTypeError(pContext,pFmtArray,v,"unsigned integer"))
+ return false;
+ }
+ if(iTmp < 0)
+ {
+ QString szError;
+ KviQString::sprintf(szError,__tr2qs("Invalid data type for parameter \"%s\""),pFmtArray->szName);
+ szError += ": ";
+ KviQString::sprintf(szError,__tr2qs("found signed integer \"%d\" where type 'unsigned integer' was expected"),iTmp);
+ pContext->error(szError);
+ return false;
+ }
+ *((kvs_uint_t *)(pFmtArray->pContainer)) = (kvs_uint_t)iTmp;
+ }
+ break;
+ case KVS_PT_DOUBLE:
+ if(!v->asReal(*((kvs_real_t *)(pFmtArray->pContainer))))
+ {
+ if(!handleParameterTypeError(pContext,pFmtArray,v,"real"))
+ return false;
+ }
+ break;
+ case KVS_PT_HASH:
+ if(!v->isHash())
+ {
+ if(!handleParameterTypeError(pContext,pFmtArray,v,"hash"))
+ return false;
+ } else {
+ *((KviKvsHash **)(pFmtArray->pContainer)) = v->hash();
+ }
+ break;
+ case KVS_PT_ARRAYCAST:
+ v->castToArray((KviKvsArrayCast *)(pFmtArray->pContainer));
+ break;
+ case KVS_PT_ARRAY:
+ if(!v->isArray())
+ {
+ if(!handleParameterTypeError(pContext,pFmtArray,v,"array"))
+ return false;
+ } else {
+ *((KviKvsArray **)(pFmtArray->pContainer)) = v->array();
+ }
+ case KVS_PT_BOOL:
+ // this never fails: anything is converted to a boolean
+ *((bool *)(pFmtArray->pContainer)) = v->asBoolean();
+ break;
+ case KVS_PT_VARIANT:
+ *((KviKvsVariant **)(pFmtArray->pContainer)) = v;
+ break;
+ case KVS_PT_HOBJECT:
+ if(!v->asHObject(*((kvs_hobject_t *)(pFmtArray->pContainer))))
+ {
+ if(!handleParameterTypeError(pContext,pFmtArray,v,"hobject"))
+ return false;
+ }
+ break;
+ case KVS_PT_IGNORE:
+ // ignore
+ break;
+ default:
+ debug("Internal error in KviKvsParameterProcessor::processAsParameters(): unknown parameter type %d",pFmtArray->uType);
+ return false;
+ break;
+ }
+ pFmtArray++;
+ v = pVariantList->next();
+ }
+ return true;
+ }
+
+};
diff --git a/src/kvirc/kvs/kvi_kvs_parameterprocessor.h b/src/kvirc/kvs/kvi_kvs_parameterprocessor.h
new file mode 100644
index 00000000..3d8483f9
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_parameterprocessor.h
@@ -0,0 +1,140 @@
+#ifndef _KVI_KVS_PARAMETERPROCESSOR_H_
+#define _KVI_KVS_PARAMETERPROCESSOR_H_
+//=============================================================================
+//
+// File : kvi_kvs_parameterprocessor.h
+// Created on Sun 17 Apr 2005 16:47:09 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+
+// Data type: QString
+// Default: QString::null
+#define KVS_PT_STRING 0
+
+// Data type: QString
+// Default: QString::null
+#define KVS_PT_NONEMPTYSTRING 1
+
+// Data type: kvs_int_t
+// Default: 0
+#define KVS_PT_INT 2
+ #define KVS_PT_INTEGER 2
+
+// Data type: kvs_uint_t
+// Default: 0
+#define KVS_PT_UINT 3
+ #define KVS_PT_UNSIGNEDINTEGER 3
+
+// Data type: kvs_real_t
+// default: 0.0
+#define KVS_PT_DOUBLE 4
+ #define KVS_PT_REAL 4
+
+// Data type: bool
+// default: false
+#define KVS_PT_BOOL 5
+ #define KVS_PT_BOOLEAN 5
+
+// Data type: KviKvsHash *
+// default: 0
+#define KVS_PT_HASH 6
+
+// Data type: KviKvsArrayCast
+// default empty cast
+#define KVS_PT_ARRAYCAST 7
+
+// Data type: KviKvsVariant *
+// default: 0
+#define KVS_PT_VARIANT 8
+
+// Data type: QCString
+// default null string (0)
+#define KVS_PT_CSTRING 9
+
+// Data type: QCString
+// default null string (0)
+#define KVS_PT_NONEMPTYCSTRING 10
+
+// Data type: QStringList
+// default: list cleared
+// This eats all the remaining params in the list!
+#define KVS_PT_STRINGLIST 11
+
+// Data type: KviKvsVariantList
+// default: list cleared
+// This eats all the remaining params in the list!
+// The list has autodelete set to off since the copies are SHALLOW!
+#define KVS_PT_VARIANTLIST 12
+
+// Data type: kvs_hobjec_t
+// default: (kvs_hobject_t)0
+#define KVS_PT_HOBJECT 13
+
+// Data type: KviKvsArray *
+// default 0
+#define KVS_PT_ARRAY 14
+
+// Data type: ignored
+#define KVS_PT_IGNORE 15
+
+// If omitted, set to default
+#define KVS_PF_OPTIONAL 1
+// Valid only for string types: it's the last parameter that eats all the remaining ones
+#define KVS_PF_APPENDREMAINING 2
+
+class KviKvsVariantList;
+class KviKvsRunTimeContext;
+
+namespace KviKvsParameterProcessor
+{
+ class KVIRC_API ParameterFormat
+ {
+ public:
+ const char * szName;
+ const unsigned char uType;
+ const unsigned char uFlags;
+ void * pContainer;
+ public:
+ ParameterFormat(const char * n,const unsigned char t,const unsigned char f,void * p)
+ : szName(n), uType(t), uFlags(f), pContainer(p) {};
+ };
+
+ KVIRC_API bool process(KviKvsVariantList * pVariantList,KviKvsRunTimeContext * pContext,KviKvsParameterProcessor::ParameterFormat * pFmtArray);
+};
+
+
+#define KVS_PARAMETERS_BEGIN(__name) \
+ KviKvsParameterProcessor::ParameterFormat __name[] = \
+ {
+
+#define KVS_PARAMETERS_END \
+ KviKvsParameterProcessor::ParameterFormat(0,0,0,0) \
+ };
+
+#define KVS_PARAMETER(__name,__type,__flags,__void) \
+ KviKvsParameterProcessor::ParameterFormat(__name,__type,__flags,((void *)(&(__void)))),
+
+#define KVS_PARAMETER_IGNORED(__name) \
+ KviKvsParameterProcessor::ParameterFormat(__name,KVS_PT_IGNORE,0,0),
+
+#endif //!_KVI_KVS_PARAMETERPROCESSOR_H_
diff --git a/src/kvirc/kvs/kvi_kvs_parser.cpp b/src/kvirc/kvs/kvi_kvs_parser.cpp
new file mode 100644
index 00000000..37e462c0
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_parser.cpp
@@ -0,0 +1,3827 @@
+//=============================================================================
+//
+// File : kvi_kvs_parser.cpp
+// Creation date : Thu 25 Sep 2003 05.12 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+
+#include "kvi_kvs_parser.h"
+
+#include "kvi_kvs_treenode.h"
+
+#include "kvi_kvs_report.h"
+#include "kvi_kvs_kernel.h"
+
+#include "kvi_kvs_script.h"
+
+#include "kvi_kvs_parser_macros.h"
+
+#include "kvi_locale.h"
+
+#include "kvi_options.h"
+
+//FIXME: @ == $$-> == $this->
+
+KviKvsParser::KviKvsParser(KviKvsScript * pScript,KviWindow * pOutputWindow)
+{
+ // no need to initialize m_pBuffer
+ // no need to initialize m_ptr
+ // no need to initialize m_bError
+ m_pGlobals = 0;
+ m_pScript = pScript;
+ m_pWindow = pOutputWindow;
+}
+
+KviKvsParser::~KviKvsParser()
+{
+ if(m_pGlobals)delete m_pGlobals;
+}
+
+
+
+
+void KviKvsParser::init()
+{
+ KviKvsKernel * pKern = KviKvsKernel::instance();
+
+#define _REG_CNTRL_CMD(__cntrlCmdName,__parsingRoutine) \
+ { \
+ KviKvsSpecialCommandParsingRoutine * r = new KviKvsSpecialCommandParsingRoutine; \
+ r->proc = KVI_PTR2MEMBER(KviKvsParser::__parsingRoutine); \
+ pKern->registerSpecialCommandParsingRoutine(QString(__cntrlCmdName),r); \
+ }
+
+ _REG_CNTRL_CMD("if",parseSpecialCommandIf);
+ _REG_CNTRL_CMD("global",parseSpecialCommandGlobal);
+ _REG_CNTRL_CMD("while",parseSpecialCommandWhile);
+ _REG_CNTRL_CMD("break",parseSpecialCommandBreak);
+ _REG_CNTRL_CMD("do",parseSpecialCommandDo);
+ _REG_CNTRL_CMD("for",parseSpecialCommandFor);
+ _REG_CNTRL_CMD("foreach",parseSpecialCommandForeach);
+ _REG_CNTRL_CMD("switch",parseSpecialCommandSwitch);
+ _REG_CNTRL_CMD("defpopup",parseSpecialCommandDefpopup);
+ _REG_CNTRL_CMD("unset",parseSpecialCommandUnset);
+ _REG_CNTRL_CMD("class",parseSpecialCommandClass);
+ _REG_CNTRL_CMD("help",parseSpecialCommandHelp);
+
+#undef _REG_CNTRL_CMD
+}
+
+void KviKvsParser::report(bool bError,const QChar * pLocation,const QString &szMsgFmt,kvi_va_list va)
+{
+ QString szMsg;
+ KviQString::vsprintf(szMsg,szMsgFmt,va);
+
+ KviPointerList<QString> * pCodeListing = 0;
+ QString szLocation;
+
+ if(pLocation)
+ {
+ pCodeListing = new KviPointerList<QString>;
+ pCodeListing->setAutoDelete(true);
+
+ int iLine,iCol;
+
+ KviKvsReport::findLineColAndListing(m_pBuffer,pLocation,iLine,iCol,pCodeListing);
+
+ KviQString::sprintf(szLocation,__tr2qs("line %d, near character %d"),iLine,iCol);
+ } else {
+ szLocation = __tr2qs("beginning of input");
+ }
+
+ KviKvsReport rep(bError ? KviKvsReport::ParserError : KviKvsReport::ParserWarning,m_pScript->name(),szMsg,szLocation,m_pWindow);
+ if(pCodeListing)rep.setCodeListing(pCodeListing);
+
+ KviKvsReport::report(&rep,m_pWindow);
+}
+
+void KviKvsParser::errorBadChar(const QChar * pLocation,char cExpected,const char * szCommandName)
+{
+ if(pLocation->unicode())
+ error(pLocation,__tr2qs("Found character '%q' (unicode 0x%x) where '%c' was expected: see \"/help %s\" for the command syntax"),
+ pLocation,pLocation->unicode(),cExpected,szCommandName);
+ else
+ error(pLocation,__tr2qs("Found end of input where character '%c' was expected: see \"/help %s\" for the command syntax"),
+ cExpected,szCommandName);
+}
+
+void KviKvsParser::error(const QChar * pLocation,const QString &szMsgFmt,...)
+{
+ m_bError = true;
+
+ kvi_va_list va;
+ kvi_va_start_by_reference(va,szMsgFmt);
+ report(true,pLocation,szMsgFmt,va);
+ kvi_va_end(va);
+}
+
+void KviKvsParser::warning(const QChar * pLocation,const QString &szMsgFmt,...)
+{
+ kvi_va_list va;
+ kvi_va_start_by_reference(va,szMsgFmt);
+ report(false,pLocation,szMsgFmt,va);
+ kvi_va_end(va);
+}
+
+KviKvsTreeNodeInstruction * KviKvsParser::parse(const QChar * pBuffer,int iFlags)
+{
+ m_iFlags = iFlags;
+
+ m_bError = false;
+ if(m_pGlobals)m_pGlobals->clear(); // this shouldn't be needed since this is a one time parser
+
+ m_pBuffer = pBuffer;
+ m_ptr = pBuffer;
+
+ if(!pBuffer)
+ {
+ error(0,__tr2qs("Empty script"));
+ return 0;
+ }
+ return parseInstructionList();
+}
+
+KviKvsTreeNodeInstruction * KviKvsParser::parseAsExpression(const QChar * pBuffer,int iFlags)
+{
+ m_iFlags = iFlags;
+
+ m_bError = false;
+ if(m_pGlobals)m_pGlobals->clear(); // this shouldn't be needed since this is a one time parser
+
+ m_pBuffer = pBuffer;
+ m_ptr = pBuffer;
+
+ if(!pBuffer)
+ {
+ error(0,__tr2qs("Empty script"));
+ return 0;
+ }
+
+ KviKvsTreeNodeExpression * expr = parseExpression(0);
+ if(!expr)return 0;
+ return new KviKvsTreeNodeExpressionReturn(pBuffer,expr);
+}
+
+KviKvsTreeNodeInstruction * KviKvsParser::parseAsParameter(const QChar * pBuffer,int iFlags)
+{
+ m_iFlags = iFlags;
+
+ m_bError = false;
+ if(m_pGlobals)m_pGlobals->clear(); // this shouldn't be needed since this is a one time parser
+
+ m_pBuffer = pBuffer;
+ m_ptr = pBuffer;
+
+ if(!pBuffer)
+ {
+ error(0,__tr2qs("Empty script"));
+ return 0;
+ }
+
+ KviKvsTreeNodeDataList * l = parseCommandParameterList();
+ if(!l)return 0;
+
+ return new KviKvsTreeNodeParameterReturn(pBuffer,l);
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// THE REAL KVS
+//
+// <script> ::= <instruction list> '\0'
+//
+// <instruction list> ::= <instruction> [ <instruction list> ]
+// <instruction> ::= <instruction block> | <command> | <operation> | <comment>
+// <instruction block> ::= '{' <instruction list> '}'
+//
+// <comment> ::= <bash style line comment> | <c++ style comment> | <c style comment>
+// <bash style comment> ::='#' <any char not including newline or null> <newline or null>
+// <c++ style comment> ::= '//' <any char not including newline or null> <newline or null>
+// <c style comment> ::= '/*' <any char not including null or the sequence */> '*/'
+//
+// <command> ::= <simple command> | <callback command> | <control command>
+// <simple command> ::= <core command> | <module command> | <alias command>
+// <core command> ::= <command identifier> <switch list> <command parameter list> <command terminator>
+// <switch list> ::= '-'<switch body> [<switch list>]
+// <command parameter list> ::= <command parameter>[<space><command parameter>]
+// <command parameter> ::= <command parameter part>[<command parameter>]
+// <command parameter part> ::= <command literal parameter> | <string parameter> | <data evaluation>
+// <command literal parameter> ::= <anything except space , null , newline , ; , " , $ or %>
+// <string parameter> ::= '"'<string parameter body>'"'
+// <string parameter body> ::= <anything except '"' or null>...
+// <command terminator> ::= ';' | '\n' | '\0'
+
+// <data> ::=
+// <data_reference> ::= <function_call> | <structured_data>
+// <structured_data> ::= <data_structure> | <variable> | <pointer_data>
+// <data_structure> ::= <array> | <hash>
+// <array> ::= '%'<identifier>'[]'
+// <hash> ::= '%'<identifier>'{}'
+// <variable> ::= '%'<identifier> | <array_element> | <hash_element>
+// <array_element> ::= '%'<identifier>'['<expression>']'
+// <hash_element> ::= '%'<identifier>'{'<key>'}'
+// <function_call> ::= <simple_function_call> | <pointer_function_call>
+// <simple_function_call> ::= '$'<identifier>'('<function_parameter_list>')'
+// <pointer_function_call> ::= <variable>'->'<function_call> | <simple_function_call>'->'<function_call>
+// <pointer_data> ::= <variable>'->'<data>' | <simple_function_call>'->'<data>
+
+
+//
+// This must evaluate SCOPE OBJECT operators!
+// thus...first evaluate the <data> or <simple_function_call>
+// If it was <simple_function_call> or <data> evaluation results in returning a <variable>
+// then check if there is a scope operator
+// if there is then take it as the top of the tree, the <variable> or <simple_function_call>
+// go at the left param of the scope operator and re-evaluate the right side <data> or <simple_function_call>
+//
+
+
+
+
+
+
+
+/*
+ @doc: kvs_introduction
+ @type:
+ language
+ @keyterms:
+ kvs, compilation
+ @title:
+ KVIrc scripting language introduction
+ @short:
+ KVIrc scripting language introduction
+ @body:
+ [p]
+ [b]KVS[/b] is the [b]KV[/b]irc [b]S[/b]cripting language.
+ It was inspired by C++,sh,perl,php and mIrc scripting language implementations.
+ It is a compromise between flexibility and speed, a 'workaround' for many intrinsic
+ problems of an IRC-oriented scripting language.
+ [/p]
+ [p]
+ KVS is semi-interpreted: the execution is done in two main stages.
+ The first stage is the compilation where a syntactic tree is built.
+ The second stage is the real execution and is performed by visiting the tree
+ in the proper order. The syntactic trees are cached in memory so
+ the next executions can jump directly into the second stage.
+ This two-stage approach has been introduced in version 3.0.0, the previous
+ versions of the language used a single-stage on-the-fly interpreter.
+ [/p]
+ [p]
+ KVS allows you to:[br]
+ [ul]
+ [li]Implement automated reactions to the events generated by an IRC network[/li]
+ [li]Add new complex commands[/li]
+ [li]Add interface elements like popups, toolbars, buttons...[/li]
+ [li]Add advanced interface elements like complete dialogs or even widgets integrated in KVIrc[/li]
+ [/ul]
+ [/p]
+ [p]
+ KVS contains all the common constructs of structured programming.
+ You will find almost all the C control commands, sh/perl-like variables, arrays and and functions.
+ There are also some object-oriented characteristics: you will find C++ like
+ objects with constructors, destructors and class inheritance.
+ There are also more exotic concepts like the signal-slots interobject-communication.
+ Obviously you will also find most of the RFC1459 IRC commands and
+ other tools to "play" with an IRC connection.
+ [/p]
+ [p]
+ I'll try to explain the language by using examples
+ instead of strict syntactic rules. (Actually I have even
+ tried to write the rules...take a look [doc:syntactic_rules]here[/doc][br][br]
+ And please...forgive me for my "fantastic" english :)
+ [/p]
+ Szymon Stefanek
+*/
+
+/*
+ @doc: kvs_basicconcepts
+ @type:
+ language
+ @keyterms:
+ script
+ @title:
+ KVS basic concepts
+ @short:
+ KVS basic concepts
+ @body:
+ [big]Scripts[/big]
+ [p]
+ You use KVS to implement [b]scripts[/b].
+ A script is basically a finite list of KVS instructions.
+ When you type a command in the KVIrc input window you in fact
+ execute a small one-line script. You can store
+ longer scripts in KVIrc memory and execute them at later time.
+ Scripts can be also read from external files by the means of the
+ [cmd]parse[/cmd] command.
+ [/p]
+ [p]
+ There is an issue with the word [i]script[/i] that is worth clearing here.
+ It is common usage to call [i]script[/i] a thing that is something more
+ that a finite list of (some scripting language) instructions.
+ In fact a set of scripts, documentation files, graphics or other multimedia
+ files and sometimes executable binaries is still called a [i]script[/i]...just like
+ the "PrincoScript" or "dynamirc" (tough this last one should be categorized as "malware" instead).
+ In KVIrc such a collection of items is called [i]addon[/i], but be prepared
+ for both usages of the word in this documentation and around the web.
+ [/p]
+ [p]
+ More about addons in this [doc:addons]document[/doc]
+ [/p]
+
+ [big]Hello world![/big]
+ [p]
+ This documentation contains a lot of script examples.
+ They will appear like the following block of code:
+ [example]
+ [cmd]echo[/cmd] Hello world!
+ [/example]
+ The best way to experiment is to execute the scripts from an external file.
+ Try to copy & paste the example above to a file and save it in
+ a known place. Then in the command input window type
+ [example]
+ [b]/[/b][cmd]parse[/cmd] <filename>
+ [/example]
+ where <filename> stands for the name of the file you just have saved.
+ Some simple examples (like the one above) can be also typed
+ directly in the command input window.
+ You must remember that the command input window needs
+ a leading slash ('/') character to recognize a script.
+ The command input window can also be put in multiline mode by clicking
+ on the button on the right.
+ Another alternative for testing scripts is the code tester window.
+ You can access it by selecting "New code tester" from the Scripting menu
+ at the top of the KVIrc window. You will soon have the opportunity to
+ experiment with all the methods. Read on.
+ [/p]
+
+ [big]Basic syntax[/big]
+ [p]
+ A script contains a list of instructions separated by newlines or ';' characters.
+ Placing an instruction per line does not require a terminating character,
+ placing more instructions in a single line require them to be separated by ';'.
+ The most common instructions in KVS are [b]commands[/b]. A command is basically
+ a keyword followed by a list of space separater parameters.
+ The simplest (and the most useful) command in KVS is [cmd]echo[/cmd]; it prints
+ all its parameters to a KVIrc window.[br]
+ The following is an example of a valid script that uses only [cmd]echo[/cmd] commands.
+ [example]
+ echo "This is the first line"
+ ECHO This is the second line;
+ echo "This is the third line"; echo This is still on the third line;
+ eChO "This is the fourth line"; Echo "This is still on the fourth line"
+ [/example]
+ You have probably noticed that the terminating ';' character is optional
+ when the command is the last in a line.
+ The commands are [b]case insensitive[/b]; 'echo' is equivalent to 'Echo',
+ to 'ECHO' and to 'eChO'. In fact, most of KVS is case insensitive.
+ (There are obvious unavoidable exceptions for this rule; for example,
+ on UNIX systems file names are case sensitive and this must be
+ also reflected in KVS).
+ Another interesting thing is that when you execute the script you
+ don't see the enclosing quotes around the printed text: more about this
+ in the following sections.[br]
+ [note]
+ Cryptic note (you may skip it for now):[br]
+ Yes, the command terminator is a problem for those that want to use ';)' at the end
+ of IRC commands like [cmd]msg[/cmd]. It is almost unavoidable (read: the cost for
+ avoiding it is too high). Note that using '|' or any other character as command terminator
+ will NOT solve the problem: if the terminator is too difficult to type it will annoy the
+ scripters (and me), if it is too easy then there will be always someone that wants to use it
+ at the end (or in the middle) of a command with the original meaning.
+ The solution is to escape the ';' character:
+ [example]
+ [cmd]echo[/cmd] You can do it now \;)
+ [/example]
+ [/note]
+ [/p]
+
+ [big]Parameter processing[/big]
+ [p]
+ Most of the commands accept (and sometimes require) a list of parameters.
+ For example, the [cmd]join[/cmd] command (that is used to join an IRC channel)
+ accepts two parameters: the first one is the channel to join and the second is
+ the password. The simplified syntax for join is:
+ [example]
+ [cmd]join[/cmd] <channel> [password]
+ [/example]
+ The line above is an example of syntax specification. All the commands
+ are described by such syntax lines. [cmd]join[/cmd] is the command and it stands exactly
+ for the literal string "join" typed in a script. <channel> is in angular parenthesis
+ and rappresents a mandatory parameter: you must substitute a real channel name in its place
+ otherwise the command will fail and KVIrc will probably complain too.
+ [password] is still a parameter but the square parentheses indicate that it is
+ optional: if you specify it, then it will be interpreted as the channel password,
+ if you don't then no password will be used.
+ [note]
+ The syntax is written in a simplified BNF. I say simplified because it is not
+ totally strict around the KVIrc documentation. I just prefer the syntax to be
+ clear and easy to read instead of being formally perfect.
+ [/note]
+ You can finally join a channel by writing:
+ [example]
+ [cmd]join[/cmd] #kvirc kvircrocks
+ [/example]
+ or , since #kvirc usually has no password , by writing:
+ [example]
+ [cmd]join[/cmd] #kvirc
+ [/example]
+ In the example above the optional parameter [password] is omitted.
+ [note]
+ In fact it is not really omitted: KVIrc interprets it as an empty string that later
+ means "do not send the password to the server".
+ Empty strings are equivalent to omitted ones.
+ [/note]
+ [/p]
+
+ [big]Parameters, spaces and quotes[/big]
+ [p]
+ From the examples above is obvious that KVS command parameters are separated by spaces.
+ What is not totally obvious is that multiple spaces are allowed but KVIrc
+ will automatically reduce them to exactly one (just like HTML parsers or the shell
+ interpreters do). This is an useful behaviour in an IRC client since spaces usually
+ carry no information and in text oriented protocols make the parsing really harder (:D).
+ [/p]
+ [p]
+ The spaces are simplified in normal processing but there are ways to force KVIrc
+ to interpret the spaces just as they are.
+ The first method are the quotation marks: all the spaces enclosed in quotation marks
+ will be preserved.
+ [example]
+ [cmd]echo[/cmd] This &nbsp; &nbsp; text &nbsp; &nbsp; will &nbsp; &nbsp; have &nbsp; &nbsp; spaces &nbsp; &nbsp; simplified
+ [cmd]echo[/cmd] But &nbsp; &nbsp; "this &nbsp; &nbsp; &nbsp; one &nbsp; &nbsp; not"
+ [/example]
+ The first example will print out with spaces simplified but the second not.
+ The quotes are also a nice trick to embed spaces into a single parameter that
+ would be obviously splitted in two or more.
+ [example]
+ [cmd]echo[/cmd] Parameter1 Parameter2 "Parameter 3 ( with spaces )" Parameter4
+ [/example]
+ By running the examples above you may have noticed that the spaces are preserved but the
+ quotes are then stripped! Yes, this is another tricky behaviour. But don't be afraid:
+ it is really easier to use than to explain.
+ There is obviously a method to preserve the quotes too and it is also another
+ method to preserve the spaces but that leads us to the next paragraph.
+ [/p]
+
+ [big]Escape character[/big]
+ [p]
+ You may have already noticed that KVS treats some characters in a special way.
+ For example the double-quote characters can be used to enclose strings
+ and are stripped by the parser.
+ Another example of a special character is the command terminator (';'):
+ it has the "special" meaning of terminating a command.
+ If you want to enclose a literal quote in your text, you need to [b]escape[/b] it.
+ Like in most other programming languages, the escaping character is the backslash ('\').
+ [example]
+ [cmd]echo[/cmd] You can smile this way too! \;)
+ [/example]
+ The above example will treat the ';' as a part of the parameters and print it.[br]
+ In some languages the action of "escaping" a character is called "quoting".
+ Altough there is some confusion in this term, the meaning is to either use quotes
+ or to use the escape character to remove special meaning from some characters.
+ By quoting the spaces you can include them in a parameter, by escaping the quotes
+ you can include them in a command.
+ [example]
+ [cmd]echo[/cmd] "And he said \"Hello world!\""
+ [/example]
+ The example above will have the internal quotes preserved.
+ You can use the escape backslash to escape a newline:
+ [example]
+ [cmd]echo[/cmd] This text will be \
+ &nbsp; &nbsp; printed on a single line!
+ [/example]
+ After an escaped newline all the leading space and tab characters are skipped,
+ so you must include the needed spaces [b]before[/b] the escape character.
+ The previous example will be printed as:[br][br]
+ [i]This text will be printed on a single line[/i][br]
+ Another example:[br]
+ [example]
+ [cmd]echo[/cmd] "The new kvirc &nbsp; &nbsp; &nbsp \
+ &nbsp; &nbsp; IS OUT!"
+ [cmd]echo[/cmd] Check it out at http://www.kvi\
+ &nbsp; &nbsp; rc.net!
+ [/example]
+ This will be printed as:[br][br]
+ [i]
+ The new kvirc &nbsp; &nbsp; &nbsp; IS OUT![br]
+ Check it out at http://www.kvirc.net!
+ [/i][br]
+ Finally, you can escape an escape character to include it literally in a parameter (and
+ this is really the end of these tricks :)
+ Later we will discover other common usages of the backslash escape, such
+ as preventing KVIrc from interpreting a literal percent character as a variable
+ or separating variable names from the text.
+ [/p]
+
+ [big]Command switches[/big]
+ [p]
+ Many commands accept switch parameters.
+ [b]A switch modifies the behaviour of a command.[/b]
+ Any switch can optionally accept a parameter, that must
+ be specified after an equal ('=') sign.
+ [example]
+ [cmd]echo[/cmd] [b]-i = 2[/b] This text uses a specific color scheme
+ [/example]
+ The -i switch (just for example) changes the attributes
+ and the icon of the printed text.
+ [b]The switch must be specified immediately after the command keyword.[/b]
+ [example]
+ [cmd]echo[/cmd] This -i = 2 will obviously not work...
+ [/example]
+ If you want to start the first parameter of a command (that is not a switch)
+ with a literal '-' you must again escape it:
+ [example]
+ [cmd]echo[/cmd] \--- This text has three minus signs on the left
+ [/example]
+ or use the quotes:
+ [example]
+ [cmd]echo[/cmd] "--- This text has three minus signs on the left"
+ [/example]
+ [/p]
+
+ [big]Command blocks[/big]
+ [p]
+ Commands can be 'grouped' in blocks by using the classic C++ braces.
+ Here is a single line example:[br]
+ [example]
+ { [cmd]echo[/cmd] First command; [cmd]echo[/cmd] Second command; } [cmd]echo[/cmd] Third command
+ [/example]
+ Multi line example:[br]
+ [example]
+ {
+ [cmd]echo[/cmd] First command
+ [cmd]echo[/cmd] Second command
+ }
+ [cmd]echo[/cmd] Third command
+ [/example]
+ [note]
+ Reminder : copy the example above to a text file
+ and then use /[cmd]parse[/cmd] &lt;filename&gt;
+ [/note]
+ In this case the command block has no special meaning
+ other than making the code more readable , but command blocks
+ will be useful later (see [cmd]if[/cmd],[cmd]while[/cmd]...).[br]
+ [note]
+ Unlike in C or C++, the braces do NOT automatically define a variable scope
+ (with few exceptions to this rule ... just to complicate the things a bit more).
+ You will recall this last assertion later, when reading about [doc:data_structures]data structures[/doc].
+ [/note]
+ [/p]
+
+ [big]Comments[/big]
+ [p]
+ KVIrc supports comments in command sequences.[br]
+ A comment starts with the character '#' and terminates with a newline.
+ You can start a comment anywhere a command can start.[br]
+ [example]
+ # This is a comment , it occupies the whole line
+ [cmd]echo[/cmd] After the comment!; # This is an end-line comment
+ [/example]
+ You can't escape newline characters in this case.
+ (or better: escape characters have no meaning in comments...
+ maybe one day I'll implement it).[br]
+ Starting from version 3.0.0 kvirc supports also C++ single line and C multiline comments.[br]
+ A C++ comment starts with two slashes '//' and terminates with a newline.
+ A multiline C comment starts with '/*' and ends at the first '* /' encountered.
+ Since KVIrc has no pre-processor, the C/C++ comments usually can't be placed in the middle of a command:
+ they must start where a command would start and end before the begin of another command.[br]
+ [/p]
+
+ [big]Indentation[/big]
+ [p]
+ You [b]should[/b] use spaces or [b]tabs[/b] to [b]indent[/b] your code. Note that the [b]should[/b]
+ word is written in bold characters: I mean that you really should indent your code.
+ Indenting helps both you (the script writer) and the reader (any other user that will
+ read your script). A good indenting practice is the first step to become a great programmer :)
+ [note]
+ Please note that the command parameters should be separated by
+ space characters (ascii 32). Tabs are not granted to work as parameter separators.[br]
+ [/note]
+ [example]
+ {
+ &lt;tab&gt;[cmd]echo[/cmd] Indented command
+ &lt;tab&gt;{
+ &lt;tab&gt;&lt;tab&gt;# Comment
+ &lt;tab&gt;&lt;tab&gt;[cmd]echo[/cmd] Really Really long indented \
+ &lt;tab&gt;&lt;tab&gt;&lt;tab&gt;command
+ &lt;tab&gt;}
+ }
+ [/example]
+ Tabs behave better than spaces as indentation characters since other users can
+ adjust the tab size to match their taste. I personally prefer 4 character tabs
+ while most text/code editors usually come with 8 characters as default.
+ [/p]
+
+ [big]And now ?[/big]
+ [p]
+ You're now ready to really start experimenting with KVS. You can take
+ a look at the [doc:commands]command index[/doc] and start trying to use them
+ while keeping in mind the rules described in this document.
+ The next suggested lecture is the documentation about [doc:kvs_aliasesandfunctions]the aliases and the functions[/doc].
+ Have fun :)
+ [/p]
+*/
+
+/*
+ @doc: kvs_aliasesandfunctions
+ @type:
+ language
+ @keyterms:
+ aliases, functions
+ @title:
+ KVS Functions and aliases
+ @short:
+ KVS Functions and aliases
+ @body:
+ [big]Introduction[/big]
+ [p]
+ Since you're here, you should already have readed about the [doc:kvs_basicconcepts]KVS basic concepts[/doc]
+ and have visited the [doc:commands]command index[/doc]. If you feel ready to take the next step
+ then read on.
+ [/p]
+
+ [big]Functions[/big][br]
+ [p]
+ KVS has many internal [doc]functions[/doc] that can be used as command parameters.[br]
+ [b]All the function names start with a literal '$' character.[/b][br]
+ [example]
+ [cmd]echo[/cmd] This window caption is [fnc]$window.caption[/fnc]
+ [/example]
+ The [fnc]$window.caption[/fnc] [doc:functions]function[/doc]
+ is evaluated before the command executes,
+ and it is changed into the current window caption text.[br]
+ The [doc]functions[/doc] can be used also as switch parameters.[br]
+ [example]
+ [cmd]echo[/cmd] -w = [fnc]$window[/fnc] This text will be surely \
+ &nbsp; &nbsp; printed in the current window
+ [/example]
+ The -w switch allows to redirect the echo text to a specified window --- in this
+ case the one that you are typing in.[br]
+ [i](Surprise: in this case the -w switch is useless ,
+ since echo prints text to the current window by default...
+ but it will work correctly. :)[/i]
+ [/p]
+ [p]
+ Normal function names can be made of "anycase" letters, digits and underscores,
+ with the restriction that the first character is not a digit.[br]
+ Some kind of functions can contain a dot '.' character inside the name
+ and these are assumed to be module references (see [doc:modules]the modules documentation[/doc]).[br]
+ [/p]
+ [p]
+ By now we have seen only simple functions, but there's more...[br]
+ The functions can accept parameters; the general syntax for a function call is:[br]
+ [b]$<function name>['('<parameter_list>')'][/b][br]
+ where <parameter_list> is a list of comma separated parameters,
+ eventually empty.
+ [example]
+ [cmd]echo[/cmd] The word 'neural' is [fnc]$str.len[/fnc](neural) characters long
+ [/example]
+ The function [fnc]$str.len[/fnc] accepts a single parameter and returns the
+ length in characters of the parameter string. The returned value is always
+ a string: in this case it can be also interpreted as a number.[br]
+ When passing an empty list you can avoid the parenthesis.
+ (And you have found the "simple" functions shown above).
+ So the followind two calls are equal:[br]
+ [example]
+ [cmd]echo[/cmd] [fnc]$window.caption[/fnc]
+ [cmd]echo[/cmd] [fnc]$window.caption()[/fnc]
+ [/example]
+ If you want to pass an "empty" string as the first parameter you have to use
+ the following syntax:[br]
+ [example]
+ [cmd]echo[/cmd] [fnc]$str.len[/fnc]("")
+ [/example]
+ Obviously a function is valid as a function parameter.[br]
+ [example]
+ [cmd]echo[/cmd] [fnc]$str.len[/fnc]([fnc]$window.caption[/fnc])
+ [/example]
+ If you want to place a literal '(' or ')' in the function parameters
+ you must escape it.
+ A special case for when you want to use 'matching' parentheses:
+ an opened '(' corresponds to a closed ')'.
+ In this case you can omit the 'escape' character.[br]
+ [example]
+ [cmd]echo[/cmd] The length of '(a+b)' is : [fnc]$str.len[/fnc]( (a+b) )
+ [/example]
+ This is useful for algebraic and boolean expressions , like the ones
+ accepted by the special function $() (see next paragraphs).[br]
+ [/p]
+
+
+ [big]Aliases[/big][br]
+ An alias is an user defined command. It can be used to rename the builtin kvirc commands or functions,
+ to automatize complex tasks or as structured programming mean.
+ Aliases can be created or destroyed by using the scriptcenter (graphic interface)
+ or from the commandline (or script) by using the [cmd]alias[/cmd] command.
+ Once created, an alias remains stored permanently in the KVIrc configuration files
+ until it is explicitly deleted.
+ A couple of examples will make the things clear.
+ join is a really commonly used command. It might be a good idea to rename it to
+ simply "j" .. just to type it faster.
+ Nothing easier in KVirc: just try this commandline:
+ [example]
+ [cmd]alias[/cmd](j){ [cmd]join[/cmd] $0-; };
+ [/example]
+
+ This will create the alias "j". From this moment you can use /j as it was a normal command.
+ [example]
+ j #kvirc
+ [/example]
+ You may have notices the strange $0- function in the alias body: it stands for
+ "all parameters passed to the alias". This means that when you call
+ [example]
+ j #kvirc testpassword
+ [/example]
+ then both the parameters (#kvirc and testpassword) are passed to the join command.
+ The $N functions are special functions that return the positional parameters passed
+ to the current script context. In an alias the script context is the script body and
+ it is the alias caller that generates the parameters.
+ $N (where N is a digit) returns the (N-1)-th positional parameter passed by the caller.
+ It returns the parameter numbered N-1 and not N since the parameters are indexed starting
+ from zero ($0 is the first parameter!).
+ $N-M returns the parameters from (N-1)-th to the (M-1)-th (a parameter range) and $N- returns
+ all the parameters from (N-1)-th to the last one. In the example above $0- stands for
+ all the parameters starting from the first one.
+ [/p]
+ [p]
+ To remove an alias use again the alias command with an empty body:
+ [example]
+ [cmd]alias[/cmd](j){}
+ [/example]
+ This will remove the alias "j" defined above.
+ [/p]
+ [p]
+ A common task in channel management is the kick & ban action.
+ You first ban an user from the channel and then eventually kick him
+ (obviously assuming that he is actually on the channel).
+ This involves using two commands: ban and then kick.
+ It could be a nice idea to have a single "kb" command to perform this action.
+ Well...easy:
+ [example]
+ [cmd]alias[/cmd](kb){ [cmd]ban[/cmd] $0; [cmd]kick[/cmd] $0-; };
+ [/example]
+ This adds the "kb" alias: it can be called as a normal command:
+ [example]
+ kb spammer You're not welcome here!
+ [/example]
+ This will first execute "ban spammer" and then "kick spammer You're not welcome here".
+ Our kb is a really simple example... it doesn't check for the validity of the parameters:
+ the server will warn us if the parameters passed to kb were empty.
+ [/p]
+ [p]
+ The alias can be modified at any time by re-using the alias command.
+ Let's make our "kb" a bit more intelligent and add a check for the parameters.
+ TIP: It is a good idea to write the following examples in a text file and then use /parse <filename> to execute it.
+ [example]
+ [cmd]alias[/cmd](kb)
+ {
+ [cmd]if[/cmd]("$0" == "")
+ {
+ [cmd]echo[/cmd] "Usage: /kb <nickname> <kick reason>"
+ [cmd]return[/cmd]
+ }
+ [cmd]ban[/cmd] $0
+ %reason = $1-
+ [cmd]if[/cmd]("%reason" == "")%reason = "You're not welcome here!"
+ [cmd]kick[/cmd] $0 %reason
+ }
+ [/example]
+ The example above will first check the validity of the <nickname> passed to kb:
+ if no nickname was passed , it will warn the user and stop.
+ The next step will be the "ban <nickname>" call. Another enchancement is the "default reason":
+ we first assign the remaining parameters ($1- means "from $1 to the end") to a temporary variable,
+ if the variable is empty , a default kick reason is assigned.
+ Finally the "kick <nickname> <reason>" will be executed.
+ Get used to looking at the single command documentation pages, they will give
+ you the hints necessary to fully understand the above piece of code.
+ [/p]
+ [p]
+ Aliases can be used as a mean for structured programming.
+ In large scripts you will SURELY have "common tasks" to perform (like having specially
+ colored output or calculating a value from a set of other values)...
+ Aliases are the way of writing the common tasks: they are equivalent to the "procedures"
+ or "functions" in many high-level programming languages.
+ The alias as a procedure (subroutine or sub-task) has been shown in the "kb" example above:
+ it might be commonly called from complexier scripts or other aliases in case that a
+ kick & ban action is needed.
+ [/p]
+ [p]
+ The aliases can be used also as functions.
+ Assume that you need really often to calculate the sum of three numbers: a function-alias is the way.
+ [example]
+ [cmd]alias[/cmd](sum3){ [cmd]return[/cmd] $($0 + $1 + $2); };
+ [/example]
+ This will add the alias "sum3" and make it available both as a command and a function.
+ The "return" command sets the return value of a sequence of commands
+ (an alias is a sequence of commands...remember ?) and terminates the execution (by returning
+ the control to the caller).
+ So return $($0 + $1 + $2); will set the return value of the alias to the value
+ computed by $($0 + $1 + $2) that actually is the sum of the first three parameters passed.
+ You will then use it in the following way:
+ [example]
+ ...
+ %myfirstsum = $sum3(%somevalue,%someothervalue,4)
+ %anothersum = $sum3(12,%somevalue,%anothervalue)
+ ...
+ [/example]
+ Ops.. I've used some variables without actually explaining them... hehe.. please forgive me and read on.
+ This example is again really simple , but you might have complexier function-aliases.
+ The function-aliases are also normal aliases.... you can use it as a command:
+ [example]
+ /sum3 1 2 3
+ [/example]
+ Is a perfectly valid call.... it's just that it will have no visible results
+ (just because a command call implies ignoring the return value.
+ In fact there is no difference al all between function-aliases and normal-aliases:
+ the caller makes the difference: by calling an alias as a command the return value
+ just disappears in hyperspace, by calling an alias as a function , the return value
+ is propagated (and in fact "used").
+ (There are some "nice" exceptions to this rule...but you don't need to care about it, for now).
+ If return is not called inside an alias body , the return value will be just a null value.
+ [/p]
+ [p]
+ Aliases can accept switches just like any other command. The [fnc]$sw[/fnc] is there
+ exactly for that purpose. Check it out.
+ [/p]
+
+ [big]Special functions[/big]
+ [p]
+ We have already seen the positional parameter functions.
+ The functions of type [b]$N[-[M]][/b] (where N and M are positive
+ numbers starting from 0 and N < M) evaluate to the sequence of
+ [b]positional parameters[/b] from Nth to Mth."[br]
+ If M is omitted , the function evaluate to the sequence of [b]positional
+ parameters[/b] from Nth to the last one. If the whole -M block is omitted
+ the function evaluate to the Nth positional parameter.
+ We will discover more on the [b]positional parameters[/b] when talking
+ of aliases and events.[br]
+ [example]
+ $0 evaluates to the 1st positional parameter
+ $0-4 evaluates to the parameters from first to 5th
+ $41- evaluates to the parameters from 41st to the last avaiable
+ [/example]
+ The function [b]$#[/b] evaluates to the number of positional parameters available.
+ The [b]positional parameter[/b] functions do not accept parameters.[br]
+ The special function [b]$(<expression>)[/b] returns the result
+ of the evaluation of the <expression>. In previous versions of KVIrc this
+ function was called [fnc]$calc[/fnc].[br]
+ [example]
+ [cmd]echo[/cmd] $(2 + (3 ^ 7) <= 1 * (3 && 2))
+ [/example]
+ The special function [b]${<command sequence>}[/b] evaluates to the
+ return value of the <command sequence>.[br]
+ The special function [b]$$[/b] evaluates to the current object id,
+ but it is too early to explain it here...[br]
+*/
+
+/*
+ @doc: command_rebinding
+ @type:
+ language
+ @keyterms:
+ Rebinding commands to another window
+ @title:
+ Standard rebinding switch
+ @short:
+ Standard rebinding switch
+ @syntax:
+ <command> -r=<window_id> <parameters>
+ @body:
+ The -r switch is standardized along all the commands. It rebinds a command
+ to the windows specified by <window_id>. It is useful to launch commands
+ in windows that are not the current one. For example, you might want to
+ say something in a specific channel while processing an event bound to
+ a console, or say something in all the channels bound to the current irc context.
+ The examples below will make everything clear.
+ @examples:
+ [example]
+ [comment]# Run a command in the console of the current IRC context[/comment]
+ [cmd]echo[/cmd] -r=$console This command is executed in the console ($window.caption)
+ [comment]# Say something to all the channels of the current IRC context[/comment]
+ [cmd]foreach[/cmd](%w,[fnc]$window.list[/fnc](channel))[cmd]say[/cmd] -r=%w Hi ppl on [fnc]$chan.name[/fnc]
+ [/example]
+*/
+
+ /*
+ @doc: window_naming_conventions
+ @type:
+ language
+ @title:
+ Window naming conventions
+ @keyterms:
+ IRC context,window ID,frame window,connection ID
+ @short:
+ KVIrc window structure and the window naming conventions
+ @body:
+ [big]Introduction[/big][br]
+ Starting from the release 3.0.0 KVIrc window structure has
+ grown in complexity. Older releases allowed one connetion
+ per "frame window" and thus had a dedicated command parser
+ for each connection. Finding a window in that scenario
+ was quite easy: it was enough to designate it by "name"
+ (that was exactly the text displayed in the window caption).
+ It was sufficient to have an "unique" name for ever window;
+ condition that was granted by the underlying IRC protocol
+ and by the KVIrc core design.[br]
+ In this version, the unique window names are impossible to be granted.[br]
+ [big]Scenario[/big][br]
+ The command parser is now "global" to the application.
+ There can be two or more consoles in each frame and the user
+ is able to join the same channel with two different nicknames
+ using two separate connections.
+ [ul]
+ [li]
+ Application (Unique command parser)
+ [ul]
+ [li]
+ Frame X
+ [ul]
+ [li]
+ Console M (IRC context)
+ [ul]
+ [li]Channel windows[/li]
+ [li]Query windows[/li]
+ [li]Other connection related windows[/li]
+ [/ul]
+ [/li]
+ [li]
+ Console N (IRC context)
+ [ul]
+ [li]Channel windows[/li]
+ [li]Query windows[/li]
+ [li]Other connection related windows[/li]
+ [/ul]
+ [/li]
+ [li]
+ Other windows
+ [/li]
+ [li]
+ ...
+ [/li]
+ [/ul]
+ [/li]
+ [li]
+ Frame Y
+ [ul]
+ [li]
+ Console O (IRC context)
+ [ul]
+ [li]Channel windows[/li]
+ [li]Query windows[/li]
+ [li]Other connection related windows[/li]
+ [/ul]
+ [/li]
+ [li]
+ Console P (IRC context)
+ [ul]
+ [li]Channel windows[/li]
+ [li]Query windows[/li]
+ [li]Other connection related windows[/li]
+ [/ul]
+ [/li]
+ [li]
+ Other windows
+ [/li]
+ [li]
+ ...
+ [/li]
+ [/ul]
+ [/li]
+ [li]
+ ...
+ [/li]
+ [/ul]
+ [/li]
+ [/ul]
+ [br]
+ A naming convention has becomed necessary to resolve ambiguities.[br]
+ [big]Basic assumptions[/big]
+ Every KVIrc window has four main properties:[br]
+ -[b]an unique numeric identifier[/b][br]
+ -[b]the logical name[/b][br]
+ -[b]the type identifier[/b][br]
+ -[b]the caption text[/b][br]
+ The [b]numeric identifier[/b] is unique to the whole application,
+ and is the one returned by the [fnc]$window[/fnc] function.[br]
+ The identifier is assigned by KVIrc when the window is created
+ and is not changed until the window is destroyed.
+ This identifier will be referred as [b]window ID[/b].[br]
+ The [b]logical name[/b] is a property of some kind of windows.
+ It usually corresponds to the first part of the window caption.
+ For example, for channel windows it is the channel name, for
+ queries it is the list of the targets. For some other windows
+ the logical name corresponds to the caption text. This will be discussed later.[br]
+ The [b]type identifier[/b] describes the properties of a certain window.
+ For channel windows the type identifier is "channel" , for query windows is "query" ,
+ for console windows it is "console", etc..[br]
+
+ [big]Irc contexts[/big][br]
+ The KVIrc frame windows are numbered starting from 0 and named
+ "frame_<number>". Each frame can contain an unlimited number of consoles.[br]
+ Each console is bound to an [b]IRC context[/b]. (The part "is bound to" could
+ be substituted by "defines" or "is contained in").[br]
+ [i]An [b]IRC context[/b] is a set of resources that can deal with a single
+ IRC connection.[/i][br]
+ The association between an [b]IRC context[/b]
+ and a console is bijective: each [b]IRC context[/b] is associated
+ to a single console window.[br]
+ An [b]IRC context[/b] can be in connected or not-connected state.
+ When in connected state, it contains a set of windows beside the console:
+ mainly channels and query windows.
+ The channels and query windows can exist ONLY if the associated
+ [b]IRC context[/b] exists.[br]
+ Channels and queries have unique names inside a connection so
+ there is no way to confuse it. (Theoretically there can
+ be more than one query window with the same name, but in fact
+ all the windows refer to the same target so they are instances
+ of the same resource).
+ All this creates a sort of namespace: the channels and queries can be identified
+ as "bound" to a specific [b]IRC context[/b].[br]
+ An [b]IRC context[/b] can "contain" other windows, such as the "sockets"
+ window or the "list" window. KVIrc takes care of making them
+ unique inside the [b]IRC context[/b] namespace.[br]
+ Each [b]IRC context[/b] has its own unique [b]IRC context ID[/b] (see [fnc]$context[/fnc]).[br]
+ Since to a single [b]IRC context[/b] may correspond only a single irc connection,
+ when in connected state, the [b]IRC context[/b] may be referred also as [b]connection[/b]
+ or [b]connection context[/b], and the associated [b]IRC context Id[/b] can be
+ referred as [b]connection ID[/b] or [b]connection context ID[/b].[br]
+ There are classes of windows that are not bound to any [b]IRC context[/b]:
+ this includes user created windows, DCC windows, browsers etc.[br]
+ KVIrc will try to keep that windows with unique logical names.[br]
+ [big]How to identify a window[/big][br]
+ So what we have until now is:[br]
+ [ul]
+ [li]Each window has its own unique [b]window ID[/b]: we
+ will refer windows always using this identifier.[/li]
+ [li]Each window has a set of properties including:
+ window type, logical name.[/li]
+ [li]Subsets of windows are bound to a single [b]IRC context[/b][/li]
+ [/ul]
+ The simplest (but also the less significant) method of looking for
+ a window is to finding it by caption.[br]
+ The [fnc]$window[/fnc] function finds the first KVIrc window matching
+ the "caption text" and returns its [b]window ID[/b].[br]
+ This method will likely fail when there are more windows with the same
+ caption text; for this reason several specific functions
+ have been added to allow finding the correct window.[br]
+ The [fnc]$console[/fnc] finds a console window bound to a specified
+ [b]IRC context[/b].[br]
+ The [fnc]$channel[/fnc] finds a channel window matching the specified
+ name and bound to a specified [b]IRC context[/b].[br]
+ The [fnc]$query[/fnc] finds a query window that has a specified target
+ and is bound to a specified [b]IRC context[/b].[br]
+ */
+
+
+ /*
+ @doc: connection_dependant_commands
+ @type:
+ language
+ @title:
+ Connection dependant commands
+ @keyterms:
+ IRC context, connection dependant commands
+ @body:
+ Many KVIrc commands are connection dependant:
+ you need an IRC connection to succesfully execute them;
+ usually because some data needs to be sent to the server.
+ This includes commands like [cmd]whois[/cmd],[cmd]raw[/cmd],[cmd]query[/cmd],
+ [cmd]msg[/cmd],[cmd]notice[/cmd],[cmd]op[/cmd],[cmd]ctcp[/cmd]...[br]
+ These commands must be executed in a window that is bound to a
+ [b]connected [doc:window_naming_conventions]IRC context[/doc][/b].
+ You will obviously get an error message if you try to use them in a window
+ that has no associated IRC connection.[br]
+ For instance: [cmd]whois[/cmd] will work only if you execute it
+ in a console , channel or query window.[br]
+ If you want to use these commands in a window that is not associated to
+ any IRC context you may use the [doc:command_rebinding]standard -r switch[/doc].
+ You can use the same switch to execute a command in an [b]IRC context[/b] that is
+ not the current one.
+ */
+
+
+/*
+ @doc: aliases
+ @type:
+ language
+ @keyterms:
+ aliases
+ @title:
+ Aliases
+ @short:
+ Aliases : user definable command sequences
+ @body:
+ An alias is an user defined command. It can be used to rename the builtin kvirc commands or functions,
+ to automatize complex tasks or as structured programming mean.
+ Aliases can be created or destroyed by using the scriptcenter (graphic interface)
+ or from the commandline (or script) by using the [cmd]alias[/cmd] command.
+ Once created, an alias remains stored permanently in the KVIrc configuration files
+ until it is explicitly deleted.
+ A couple of examples will make the things clear.
+ join is a really commonly used command. It might be a good idea to rename it to
+ simply "j" .. just to type it faster.
+ Nothing easier in KVirc: just try this commandline:
+ [example]
+ [cmd]alias[/cmd](j){ [cmd]join[/cmd] $0-; };
+ [/example]
+
+ This will create the alias "j". From this moment you can use /j as it was a normal command.
+ [example]
+ j #kvirc
+ [/example]
+ You may have notices the strange $0- function in the alias body: it stands for
+ "all parameters passed to the alias". This means that when you call
+ [example]
+ j #kvirc testpassword
+ [/example]
+ then both the parameters (#kvirc and testpassword) are passed to the join command.
+ The $N functions are special functions that return the positional parameters passed
+ to the current script context. In an alias the script context is the script body and
+ it is the alias caller that generates the parameters.
+ $N (where N is a digit) returns the (N-1)-th positional parameter passed by the caller.
+ It returns the parameter numbered N-1 and not N since the parameters are indexed starting
+ from zero ($0 is the first parameter!).
+ $N-M returns the parameters from (N-1)-th to the (M-1)-th (a parameter range) and $N- returns
+ all the parameters from (N-1)-th to the last one. In the example above $0- stands for
+ all the parameters starting from the first one.
+ [/p]
+ [p]
+ To remove an alias use again the alias command with an empty body:
+ [example]
+ [cmd]alias[/cmd](j){}
+ [/example]
+ This will remove the alias "j" defined above.
+ [/p]
+ [p]
+ A common task in channel management is the kick & ban action.
+ You first ban an user from the channel and then eventually kick him
+ (obviously assuming that he is actually on the channel).
+ This involves using two commands: ban and then kick.
+ It could be a nice idea to have a single "kb" command to perform this action.
+ Well...easy:
+ [example]
+ [cmd]alias[/cmd](kb){ [cmd]ban[/cmd] $0; [cmd]kick[/cmd] $0-; };
+ [/example]
+ This adds the "kb" alias: it can be called as a normal command:
+ [example]
+ kb spammer You're not welcome here!
+ [/example]
+ This will first execute "ban spammer" and then "kick spammer You're not welcome here".
+ Our kb is a really simple example... it doesn't check for the validity of the parameters:
+ the server will warn us if the parameters passed to kb were empty.
+ [/p]
+ [p]
+ The alias can be modified at any time by re-using the alias command.
+ Let's make our "kb" a bit more intelligent and add a check for the parameters.
+ TIP: It is a good idea to write the following examples in a text file and then use /parse <filename> to execute it.
+ [example]
+ [cmd]alias[/cmd](kb)
+ {
+ [cmd]if[/cmd]("$0" == "")
+ {
+ [cmd]echo[/cmd] "Usage: /kb <nickname> <kick reason>"
+ [cmd]return[/cmd]
+ }
+ [cmd]ban[/cmd] $0
+ %reason = $1-
+ [cmd]if[/cmd]("%reason" == "")%reason = "You're not welcome here!"
+ [cmd]kick[/cmd] $0 %reason
+ }
+ [/example]
+ The example above will first check the validity of the <nickname> passed to kb:
+ if no nickname was passed , it will warn the user and stop.
+ The next step will be the "ban <nickname>" call. Another enchancement is the "default reason":
+ we first assign the remaining parameters ($1- means "from $1 to the end") to a temporary variable,
+ if the variable is empty , a default kick reason is assigned.
+ Finally the "kick <nickname> <reason>" will be executed.
+ Get used to looking at the single command documentation pages, they will give
+ you the hints necessary to fully understand the above piece of code.
+ [/p]
+ [p]
+ Aliases can be used as a mean for structured programming.
+ In large scripts you will SURELY have "common tasks" to perform (like having specially
+ colored output or calculating a value from a set of other values)...
+ Aliases are the way of writing the common tasks: they are equivalent to the "procedures"
+ or "functions" in many high-level programming languages.
+ The alias as a procedure (subroutine or sub-task) has been shown in the "kb" example above:
+ it might be commonly called from complexier scripts or other aliases in case that a
+ kick & ban action is needed.
+ [/p]
+ [p]
+ The aliases can be used also as functions.
+ Assume that you need really often to calculate the sum of three numbers: a function-alias is the way.
+ [example]
+ [cmd]alias[/cmd](sum3){ [cmd]return[/cmd] $($0 + $1 + $2); };
+ [/example]
+ This will add the alias "sum3" and make it available both as a command and a function.
+ The "return" command sets the return value of a sequence of commands
+ (an alias is a sequence of commands...remember ?) and terminates the execution (by returning
+ the control to the caller).
+ So return $($0 + $1 + $2); will set the return value of the alias to the value
+ computed by $($0 + $1 + $2) that actually is the sum of the first three parameters passed.
+ You will then use it in the following way:
+ [example]
+ ...
+ %myfirstsum = $sum3(%somevalue,%someothervalue,4)
+ %anothersum = $sum3(12,%somevalue,%anothervalue)
+ ...
+ [/example]
+ Ops.. I've used some variables without actually explaining them... hehe.. please forgive me and read on.
+ This example is again really simple , but you might have complexier function-aliases.
+ The function-aliases are also normal aliases.... you can use it as a command:
+ [example]
+ /sum3 1 2 3
+ [/example]
+ Is a perfectly valid call.... it's just that it will have no visible results
+ (just because a command call implies ignoring the return value.
+ In fact there is no difference al all between function-aliases and normal-aliases:
+ the caller makes the difference: by calling an alias as a command the return value
+ just disappears in hyperspace, by calling an alias as a function , the return value
+ is propagated (and in fact "used").
+ (There are some "nice" exceptions to this rule...but you don't need to care about it, for now).
+ If return is not called inside an alias body , the return value will be just a null value.
+ [/p]
+ [p]
+ Aliases can accept switches just like any other command. The [fnc]$sw[/fnc] is there
+ exactly for that purpose. Check it out.
+ [/p]
+*/
+
+
+/*
+ @doc: kvs_addons
+ @type:
+ language
+ @keyterms:
+ addons, addon
+ @title:
+ The KVIrc addon system
+ @short:
+ Writing KVIrc addons
+ @body:
+ [big]Introduction[/big]
+ [p]
+ An addon is basically a set of KVS scripts, multimedia, documentation
+ and accessory files that implement a KVIrc feature.
+ It might be a simple automatic-away subsystem, a GUI newsticker or a complex file sharing
+ service (commonly called "fserve"). Addons are sometimes called "scripts".
+ In fact a KVIrc addon is usually made of more than one KVS script.
+ [/p]
+ [p]
+ KVIrc has a builtin addon management system that allows the users
+ to install, configure and uninstall features with a nice graphical interface.
+ The management system allows the addons to have documentation integrated in the
+ KVIrc help and to be translated in several languages.
+ [/p]
+
+ [big]Addon installation[/big]
+ [p]
+ The addons are usually shipped in compressed archives (such as tar.gz "tarballs" or
+ zip files). Once uncompressed they should contain a KVS script file called "install.kvs".
+ KVIrc will look for and execute this file when the user will ask for your addon to
+ be installed. The install.kvs will usually contain the code for the [b]registration[/b]
+ of your addon and will [cmd]include[/cmd] all the other necessary source files.
+ [/p]
+
+ [big]The minimal addon[/big]
+ [p]
+ The smallest addon that you can write is the one that does nothing.
+ It just need to be writte in a file named install.kvs and contain code
+ similar to the following:
+ [example]
+ [cmd]addon.register[/cmd]("myaddon", \
+ "1.0.0", \
+ "My First Addon", \
+ "An addon that is really cool but does simply nothing", \
+ "3.2.0.99.20051230")
+ {
+ }
+ [/example]
+ The code above does nothing but registers the "myaddon" addon.
+ [/p]
+ [p]
+ The first parameter is the internal addon id which can be used to identify
+ your addon inside KVIrc. The id must be unique: two addons that share the same
+ name cannot be installed. The second parameter is the addon version. It should
+ be expressed in the classic format [major].[minor].[pathlevel] or something
+ really similar (in fact KVIrc just expects the version to be a string composed
+ of numbers separated by dots). The version is compared when an addon is installed
+ and KVIrc complains if the user tries to downgrade an addon (that is to install
+ a less recent version over a more recent one). The third parameter
+ is the visible name of your addon: it will be displayed to the user in the
+ addon management dialog. It can contain the [fnc]$tr[/fnc] function so you
+ can have it translated to several languages. The fourth parameter
+ is a short description of the feature that the addon implements; it can contain
+ the $tr() function too. The fifth parameter is the minimal KVIrc version
+ required to run the addon. There is also a sixth parameter (the icon) and
+ some switches that can be used to fiddle a little bit more :)
+ [/p]
+ [p]
+ The callback instruction that follows the registration command is the
+ uninstallation code. KVIrc will invoke it when the user will ask for
+ your addon to be uninstalled. Don't assume that your addon will be never uninstalled:
+ sooner or later it will be. For example, when upgrading an addon KVIrc
+ will first uninstall the existing version and after that install the new one.
+ The uninstallation process is a very important requisite for any program (in any
+ programming language). In the example above there is nothing to uninstall (yet)
+ so the callback code is empty, but if you continue reading we will soon fill it.
+ [/p]
+
+ [big]A typical addon layout[/big]
+ [p]
+ As stated above, the addons are usually shipped in a compressed archive.
+ Once uncompressed, the archive will expand into a small directory tree
+ containing the addon code and all the related files.
+ In order to have uniformity I encourage you to use the following directory structure.
+ [/p]
+ [p]
+ [pre]
+ &nbsp; &nbsp; [b]addonId-version/[/b]
+ &nbsp; &nbsp; &nbsp; &nbsp; install.kvs
+ &nbsp; &nbsp; &nbsp; &nbsp; INSTALL
+ &nbsp; &nbsp; &nbsp; &nbsp; [b]src[/b]
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; source1.kvs
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; source2.kvs
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; source3.kvs
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ...
+ &nbsp; &nbsp; &nbsp; &nbsp; [b]pics[/b]
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; addonId_pic1.png
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; addonId_pic2.png
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; addonId_pic3.png
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ...
+ &nbsp; &nbsp; &nbsp; &nbsp; [b]audio[/b]
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; addonId_audio1.png
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; addonId_audio2.png
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; addonId_audio3.png
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ...
+ &nbsp; &nbsp; &nbsp; &nbsp; [b]help[/b]
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; en
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; index.html
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; hints.html
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ...
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; it
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; index.html
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; hints.html
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ...
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ...
+ &nbsp; &nbsp; &nbsp; &nbsp; [b]locale[/b]
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; addonId_it.mo
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; addonId_ru.mo
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; addonId_de.mo
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ...
+ &nbsp; &nbsp; &nbsp; &nbsp; [b]...[/b]
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ...
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ...
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ...
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ...
+ [/pre]
+ [/p]
+ [p]
+ The entries in [b]bold[/b] are directories while the other are files.
+ Please note that this is a general layout for a huge and rather complex
+ addon: you might not need all of these directories. Remember: the minimal
+ addon has only an install.kvs file. Anyway, a really cool addon
+ will probably have all of them and maybe some more.
+ [/p]
+ [p]
+ The toplevel directory should be named with your addonId and version.
+ Try to use no spaces in the directory entries (this will make the things
+ simplier for people that want to use your addon). The toplevel
+ directory should contain your install.kvs script and a file with
+ a small description and the basic installation instructions.
+ This file can be named INSTALL or README.
+ [/p]
+ [p]
+ Hint: Remember that your addon is going to be installed on different platforms
+ (at least linux, macosx and windows based).
+ The poor windows notepad has serious problems with reading text
+ files that contain only linefeeds as line separators. Keep it in mind...
+ [/p]
+ [p]
+ The main source directory for your addon should be named "src" and
+ should contain the implementation of the feature(s) you're going to provide.
+ These files should be executed by the means of the [cmd]parse[/cmd]
+ command (or [cmd]include[/cmd] if you like the C/C++ style) from install.kvs.
+ [/p]
+ [p]
+ The "pics" and "audio" (if relevant) directories should contain your
+ multimedia files. It is a good idea to prefix the filenames with your addon id
+ in order to avoid collisions with other addons. The install.kvs script
+ should copy these files to the appropriate locations under the KVIrc local
+ directory returned by [fnc]$file.localdir[/fnc]().
+ [/p]
+ [p]
+ The "help" directory should contain subdirectories for each language that
+ your help files are written in. The languages dirs should be named
+ with the language code also used for the translation files (like "en","it" etc...).
+ Please note that english is the default language and KVIrc will
+ fallback to the "en" subdirectory when no other language is found around...
+ The help files (and subdirectories) should be copied to the "help" subdirectory of the KVIrc local
+ directory returned by [fnc]$file.localdir[/fnc]().
+ Since there will be many help files inside the language dirs, it is a good idea
+ to either prefix your help files with your addon id or (better) to create
+ a subdirectory named agains your addon inside the help language directory.
+ For an english file this would lead to something like...
+ [example]
+ file.copy index.html $file.localdir("help/en/myaddon")
+ [/example]
+ [/p]
+ [p]
+ The "locale" directory should contain the *.mo files for your tranlations.
+ The localization process of a script is explained in [doc:localization]this document[/doc].
+ The *.mo files should be copied to the "locale" subdirectory of the KVIrc local
+ directory returned by [fnc]$file.localdir[/fnc]().
+ Your *.mo filenames should be prefixed by your addon id (again to avoid collisions).
+ [/p]
+
+ [big]The help and configuration callbacks[/big]
+ [p]
+ Each addon can have a help and a configuration callback. These are set
+ respectively by [cmd]addon.sethelpcallback[/cmd] and [cmd]addon.setconfigurecallback[/cmd].
+ [/p]
+ [p]
+ The help callback will be invoked by KVIrc when the user will ask help for your addon (mainly
+ from the addon management dialog, but not necessairly). It should call [cmd]help.open[/cmd]
+ with the name of your documentation index html file (it should be relative
+ to the help language directory: help.open myaddon/index.html will automatically
+ lookup the right language). If you provide no help callback, the buttons
+ for requesting help will be simply disabled. (A good an relatively complex addon
+ *should* have at least a minimal help file explaining the features).
+ [/p]
+ [p]
+ The configuration callback will be invoked when the user will try to configure
+ your addon from the addon management dialog. This callback is useful
+ mainly for complexier graphical scripts that can show up a dialog
+ that allows configuring all of the addon features. To use this callback
+ you will probably need some object scripting.
+ [/p]
+
+ [big]The real addon work[/big]
+ [p]
+ The real addon work is done by the scripts contained in the src directory.
+ They will likely add aliases (maybe in a nice namespace named agains your addon),
+ register event handlers, create actions, timers, toolbars and object classes.
+ You should install all of this stuff from your addon source files.
+ Remember that your source files will NOT be parsed every time KVIrc starts up:
+ your stuff must be registered in KVIrc and be able to startup itself, if needed.
+ Remember that you must clean up [b]everything[/b] in your uninstallation callback.
+ This means that you must remove the aliases, unregister the event handlers,
+ destroy the actions, kill the timers and the object classes you've created.
+ Be a clean coder :)
+ [/p]
+
+ [big]Where to start[/big]
+ [p]
+ It is a good idea to start on the KVIrc web site. There are surely
+ several addons to look at. Pick one that seems simple and analyze its
+ layout and code (wow... the free software!). It will be easier to do than it was to explain it :D
+ [/p]
+ [p]
+ Have fun! :)
+ [/p]
+*/
+
+
+/*
+ @doc: kvs_codingtips
+ @type:
+ generic
+ @title:
+ Coding tips
+ @keyterms:
+ indentation,indent,readability
+ @short:
+ Generic coding tips for scripters (and not only)
+ @body:
+ Here comes a small list of "coding tips".[br]
+ These apply to programming in general , not only to KVIrc scripting.[br]
+ [br]
+ 1. [b]Comment your code[/b][br]
+ A well commented code is easy to mantain, and easy to read by others.[br]
+ [br]
+ 2. [b]Indent your code[/b][br]
+ Indentation increases the code readability; this is again for you and
+ other developers that will be going to read your code.[br]
+ [br]
+ 3. [b]Use TABS to indent your code[/b][br]
+ ...and use ONLY TABS to indent.[br]
+ Tabs are better than space since most code editors allow you
+ to set the tab sice and thus to have the indentation steps smaller or bigger.[br]
+ This is really important since the indentation size is really a matter of personal taste.[br]
+ Mixing spaces and tabs is Evil (tm), since it makes the code look really
+ ugly in editors that have the tab size different than yours; in some cases the
+ code gets really unreadable.[br]
+ [br]
+ 4. [b]Use descriptive variable names[/b][br]
+ Using 'foo' as variable name implies tracing its semantic the next
+ time that you're going to read the code that uses it.[br]
+ This is really annoying and time-consuming, especially if the project
+ is getting large.[br]
+ Obviously using "thisIsACounterVariable" as name for a simple counter
+ is also a suicide.[br]
+ A good convention on variable names can speed up writing , debugging and mantaining code.[br]
+ Encoding the type of the variable in the variable name might be also a good idea,
+ but this is a matter of taste; personally I feel really well with that.[br]
+ Just as example, here go my fundamental convention rules for C++:[br]
+ [br]
+ - The type of the variable is encoded at the beginning of the variable name:[br]
+ [br]
+ - b prefix for the boolean varables[br]
+ - i prefix for signed integers[br]
+ - u prefix for unsigned integers[br]
+ - f and d prefixes for floating point stuff[br]
+ - sz prefix for strings (this is rather for string classes)[br]
+ - ...[br]
+ [br]
+ - Pointers have a "p" prefix prepended[br]
+ - Global variables start with a "g_" prefix[br]
+ - Member variables start with a "m_" prefix[br]
+ - Exception comes for local variables with obvious semantics[br]
+ [br]
+ - i,j,k,l for local loop counters[br]
+ - "aux" and "tmp" for local obvious short-term temporary variables[br]
+ [br]
+ So actually by ONLY reading "g_pszQuitMessage" I know that this is a global pointer to a string variable
+ containing a quit message. :)[br]
+ [/p]
+*/
+
+// FIXME: #warning "FINISH THE SYNTACTIC RULES DOC"
+
+/*
+ @doc: syntactic_rules
+ @type:
+ language
+ @keyterms:
+ productions
+ @title:
+ Syntactic rules
+ @short:
+ Syntactic rules of the KVIrc scripting language
+ @body:
+
+ In the following table you can find a good part of the
+ KVIrc scripting language syntactic rules.[br]
+ [br]
+ <entity> indicates a ENTITY THAT CAN APPEAR EXACTLY ONE TIME.[br]
+ [<entity>] indicates an OPTIONAL ENTITY.[br]
+ {<entity>} indicates an ENTITY THAT CAN APPEAR ONE OR MORE TIMES.[br]
+ 'entity' indicates a LITERAL ENTITY: written exactly as it is.[br]
+ <entity1>|<entity2> indicates mutually exclusive choices.[br]
+ The mutually exclusive choices are often separated in two or more
+ rules (productions), to improve readability.[br]
+ [table]
+ [tr]
+ [td]<command buffer>[/td]
+ [td][<whitespace>][<command block>]{<command buffer>}[/td]
+ [/tr]
+ [tr]
+ [td]<command buffer>[/td]
+ [td][<whitespace>][<single command>]{<command buffer>}[/td]
+ [/tr]
+ [tr]
+ [td]<whitespace>[/td]
+ [td]{<space>|<tab>|<newline>}['\'<newline>][<whitespace>][/td]
+ [/tr]
+ [tr]
+ [td]<space>[/td]
+ [td]' '['\'<newline>][<space>] (Ascii space character)[/td]
+ [/tr]
+ [tr]
+ [td]<tab>[/td]
+ [td]'\t' (Ascii horizontal tabulation character)[/td]
+ [/tr]
+ [tr]
+ [td]<newline>[/td]
+ [td]'\n' (Ascii line feed (LF) character)[/td]
+ [/tr]
+ [tr]
+ [td]<command block>[/td]
+ [td]'{' <command buffer>[<whitespace>] '}'[/td]
+ [/tr]
+ [tr]
+ [td]<single command>[/td]
+ [td]<comment>[/td]
+ [/tr]
+ [tr]
+ [td]<single command>[/td]
+ [td]<lvalue command> <command terminator>[/td]
+ [/tr]
+ [tr]
+ [td]<single command>[/td]
+ [td]<rvalue command> <command terminator>[/td]
+ [/tr]
+ [tr]
+ [td]<comment>[/td]
+ [td]'#' {<non comment terminator>} <comment terminator>[/td]
+ [/tr]
+ [tr]
+ [td]<comment terminator>[/td]
+ [td]<newline> | <end of string>[/td]
+ [/tr]
+ [tr]
+ [td]<end of string>[/td]
+ [td]No character (internally Ascii character 0)[/td]
+ [/tr]
+ [tr]
+ [td]<command terminator>[/td]
+ [td]<newline> | <end of string> | ';'[/td]
+ [/tr]
+ [tr]
+ [td]<non comment-terminator>[/td]
+ [td]Any Ascii character except <newline> and <end of string>[/td]
+ [/tr]
+ [tr]
+ [td]<simple command>[/td]
+ [td][<module name>'.']<command name>[<switch list>]{<space>}<command dependant part>[/td]
+ [/tr]
+ [tr]
+ [td]<lvalue command>[/td]
+ [td]<variable>[<space>]<operation>[/td]
+ [/tr]
+ [tr]
+ [td]<lvalue command>[/td]
+ [td]<variable>'->'<object command>[/td]
+ [/tr]
+ [tr]
+ [td]<lvalue command>[/td]
+ [td]<identifier>'->'<object command>[/td]
+ [/tr]
+ [tr]
+ [td]<operation>[/td]
+ [td]<one op operator>[/td]
+ [/tr]
+ [tr]
+ [td]<operation>[/td]
+ [td]<two op operator>[<space>]<param string>[/td]
+ [/tr]
+ [tr]
+ [td]<switch list>[/td]
+ [td]{<space>}'-'<alpha char>[{<space>}'='<single parameter>][<switch list>][/td]
+ [/tr]
+ [tr]
+ [td]<command name>[/td]
+ [td]<alphanumeric char>{<alphanumeric char>}[/td]
+ [/tr]
+ [tr]
+ [td]<module name>[/td]
+ [td]<alphanumeric char>{<alphanumeric char>}[/td]
+ [/tr]
+ [tr]
+ [td]<alphanumeric char>[/td]
+ [td]Ascii characters 'A' to 'Z' , 'a' to 'z' , '0' to '9' and '_'[/td]
+ [/tr]
+ [tr]
+ [td]<variable>[/td]
+ [td]<global variable> | <local variable>[/td]
+ [/tr]
+ [tr]
+ [td]<global variable>[/td]
+ [td]'%' <uppercase letter> [<alphanumeric char>]['['<param string>']'][/td]
+ [/tr]
+ [tr]
+ [td]<local variable>[/td]
+ [td]'%' <lowercase letter> [<alphanumeric char>]['['<param string>']'][/td]
+ [/tr]
+ [tr]
+ [td]<param string>[/td]
+ [td][<single parameter>][<space>[<param string>]][/td]
+ [/tr]
+ [tr]
+ [td]<single parameter>[/td]
+ [td]<variable> | <identifier> | <nonterminator token> | <string>[/td]
+ [/tr]
+ [tr]
+ [td]<nonterminator token>[/td]
+ [td]<nonterminator char>['\'<newline><nonterminator char>][/td]
+ [/tr]
+ [tr]
+ [td]<nonterminator char>[/td]
+ [td]Any ascii character except <space> and <command terminator>[/td]
+ [/tr]
+ [tr]
+ [td]<command dependant part>[/td]
+ [td][b]Production in each command help page[/b][/td]
+ [/tr]
+ [/table]
+ To be continued...
+*/
+
+/*
+ @doc: command_rebinding
+ @type:
+ language
+ @keyterms:
+ Not supported
+ @title:
+ Standard -r switch no longer supported
+ @short:
+ Standard -r switch no longer supported
+ @body:
+ Starting from version 3.0.0 the standard -r switch to commands is no longer supported.
+ You should rebind your command sequences with [cmd]rebind[/cmd]
+*/
+
+/*
+ @doc: kvs_datatypes
+ @type:
+ language
+ @keyterms:
+ global variable, global variables, local variable, local variables,
+ variables, variable, array, hash, dictionary, global variables, local variables,variable evaluation,
+ associative arrays, scalars, data types, percent sign, extended scope
+ @title:
+ Variables and Data types
+ @short:
+ All about the KVS variable and datatype management
+ @body:
+ [title]Basic syntax[/title]
+
+ [p]
+ A variable identifier is composed by a '%' (percent) sign followed
+ by a sequence of letters, digits or underscores.
+ Examples of valid variable names are:
+ [/p]
+
+ [example]
+ %i
+ %variable
+ %MyVar
+ %1
+ %thisisavar
+ %2ndName
+ %_hidden
+ [/example]
+
+ [p]
+ Variables are created when you assign something to them: there is no need
+ for a declaration (unlike other languages such as C/C++, Java or VB).
+ [/p]
+
+ [example]
+ [comment]# create a variable named %X by assigning the value 10 to it[/comment]
+ %X = 10
+ [comment]# use the variable[/comment]
+ echo "The value of X is" %X
+ [/example]
+
+ [title]Local and global variables[/title]
+
+ [p]
+ Variables can be local or global.
+ Local variables preserve their contents only inside the [b]scope[/b] of a single script.
+ Global variables are shared between all the scripts and preserve their contents
+ until they are explicitly unset or until KVIrc quits.
+ [/p]
+
+ [p]
+ Local variables start with a [b]lowercase letter[/b] while the global ones with an [b]uppercase letter[/b].
+ [/p]
+
+ [example]
+ %var = 10; [comment]# this is a local variable[/comment]
+ %Var = 10; [comment]# this is a global variable[/comment]
+ [/example]
+
+ [p]
+ You can also force a variable that start with a lowercase letter to be global
+ by predeclaring it with the [cmd]global[/cmd] keyword.[br]
+ [/p]
+
+ [example]
+ [comment]# copy this script to a file and run /[cmd]parse[/cmd] <filename>[/comment]
+ global %a
+ %a = "The contents of the variable a"
+ %b = "The contents of the variable b"
+ [comment]# %a is a global variable now : all the other scripts can see its value[/comment]
+ [comment]# %b is a local variable and no other scripts can see its value[/comment]
+ [/example]
+
+ [p]
+ If you have executed the example above from a file (by the means of [cmd]parse[/cmd])
+ then now you can type
+ [/p]
+
+ [example]
+ [cmd]echo[/cmd] %a
+ [/example]
+
+ [p]
+ in the commandline to see the contents of the variable %a.
+ If you also try
+ [/p]
+
+ [example]
+ [cmd]echo[/cmd] %b
+ [/example]
+
+ [p]
+ you will see nothing printed since %b was local to the parsed script.
+ [/p]
+
+ [title]Data types[/title]
+
+ [p]
+ KVS has three main categories of data types: scalars, arrays and associative
+ arrays (also known as dictionaries or hashes).
+ [/p]
+
+ [subtitle]Scalars[/subtitle]
+
+ [p]
+ The scalars are simple variables containing a single value (a string or an integer).
+ [/p]
+
+ [example]
+ [comment]# %a is a scalar variable[/comment]
+ %a = "This is a string"
+ [cmd]echo[/cmd] %a
+ %a = 24.5
+ [cmd]echo[/cmd] %a
+ [/example]
+
+ [subtitle]Arrays[/subtitle]
+
+ [p]
+ Arrays are collections of items indexed by integers. The array items
+ are selected by placing the index in square brackets just after the array name.
+ [/p]
+
+ [example]
+ %arrayName[index]
+ [/example]
+
+ [p]
+ An easy way to create an array is to use the [fnc]$array[/fnc] function.
+ [/p]
+
+ [example]
+ %a = $array("element1","element2","element3"); [comment]# Create an array with 3 items[/comment]
+ [cmd]for[/cmd](%i=0;%i<3;%i++)
+ {
+ echo %a[%i]; [comment]# Accessing the %i'th element of the array[/comment]
+ }
+ [/example]
+
+ [p]
+ Note that in the example above %a refers to the whole array while %a[%i] refers
+ to one of its elements, in particular the one with index %i.
+ You also create an array by explicitly assigning to one of its elements:
+ [/p]
+
+ [example]
+ %a[9] = "This is an array element";
+ [/example]
+
+ [p]
+ Array indexes are zero-based so in the example above you have created an array
+ with 10 items. You can find out an array's length with the [fnc]$length[/fnc]() function.
+ [/p]
+
+ [example]
+ %a[9] = "This is an array element";
+ echo $length(%a)
+ [/example]
+
+ [p]
+ Be aware that by making such an assignment you implicitly consume some memory for
+ all the preceeding array items (even if they are unset). This means that
+ a simple instruction like the following may eat a huge amount of memory at once:
+ [/p]
+
+ [example]
+ %a[1000000] = "An array element faaaaaar away...";
+ echo $length(%a)
+ [/example]
+
+ [note]
+ [p]
+ Food for thoughts:
+ [/p]
+ [p]
+ KVIrc allocates a pointer for each item in the array. The pointer is
+ empty when the item is unset and points to an additional block
+ of memory when the item is set. The size of a pointer is platform
+ dependant: on the platforms supported by KVIrc it's either 32 or 64 bit.
+ The size of the additional block depends both on the platform
+ and on the contents of the item... it's average value may
+ be around 16 bytes. The array size is determined by the last SET element index.
+ All this this means that in the worst case (64 bit assumption) an array in
+ that the highest indexed item set is N eats up at least N*8+16 bytes of memory.
+ [/p]
+ [/note]
+
+ [p]
+ Besides the traditional indexed looping method you
+ can also use the [cmd]foreach[/cmd] command to iterate the items of an array.
+ Be aware that [cmd]foreach[/cmd] will NOT iterate over unset items in the
+ array unless you use the -a switch.
+ [/p]
+
+ [example]
+ %Array[0]=Pippo
+ %Array[1]=Pluto
+ %Array[2]=Paperino
+ %Array[5]=Prova
+ [cmd]foreach[/cmd](%item,%Array)[cmd]echo[/cmd] Got Item: %item
+ [/example]
+
+ [p]
+ Note that the items 3 and 4 are simply skipped.
+ [/p]
+
+ [subtitle]Hashes[/subtitle]
+
+ [p]
+ The hashes are collections of items indexed by strings: the word "hash"
+ is in fact a shortcut for "hashtable". In literature hashes are also called
+ "associative arrays", "dictionaries" or "key-value pair sets".
+ The hash items are selected by placing the key in curly brackets
+ just after the hash name.
+ [/p]
+
+ [example]
+ %hashName{key}
+ [/example]
+
+ [p]
+ An easy way to create a hash is to use the [fnc]$hash[/fnc] function.
+ [/p]
+ [example]
+ %a = $hash("key1","value1","key2","value2","key3","value3")
+ [cmd]foreach[/cmd](%key,[fnc]$keys[/fnc](%a))
+ {
+ echo "KEY:" %key "VALUE:" %a{%key};
+ }
+ [/example]
+
+ [p]
+ Note that in the example above %a refers to the whole hash while %a{%i} refers
+ to one of its elements, in particular the one with the key %key.
+ You also create a hash by explicitly assigning to one of its elements:
+ [/p]
+
+ [example]
+ %a{"MyKey"} = "MyValue"
+ [/example]
+
+ [p]
+ You may have already noticed that the [fnc]$key[/fnc]() function returns
+ the array of the hash keys: it is useful to iterate over the hash items.
+ [/p]
+
+ [title]Mutability of variables[/title]
+
+ [p]
+ KVS is not strictly typed: any variable can assume different type identities at different times,
+ even in the same script.
+ [/p]
+
+ [example]
+ [comment]# %a is a scalar[/comment]
+ %a = "This is a string"
+ [comment]# %a becomes an array with 3 elements[/comment]
+ %a = $array("element1","element2","element3");
+ [comment]# %a becomes a hash with two values[/comment]
+ %a = $hash("key1","value1","key2","value2");
+ [/example]
+
+ [p]
+ In literature this kind of variable is called [b]variant[/b] and this is the
+ term that you will find all around the documentation when an explicit
+ data type is not requested.
+ [/p]
+
+ [p]
+ Note that array and hash items are variants too. This means that you can have arrays
+ of arrays, hashes of arrays of hashes and any other multidimensional combination you like.
+ However remember that hash keys are strings and not variants so you can't use an array as hash key.
+ [/p]
+
+ [example]
+ [comment]# here we eat 256 locations of memory at once :)[/comment]
+ %a[16][16] = 10
+ [comment]# a hash of hashes: here we eat just two memory locations[/comment]
+ %a{"16"}{"16"} = 10
+ [/example]
+
+
+ [p]
+ In most cases the KVS engine manages automatically the conversion between data types.
+ For example, when you put an array in a place where a scalar is requested, KVIrc
+ automatically transforms it to a scalar string by joining all the items with a comma.
+ [/p]
+
+ [example]
+ %a = $array("element1","element2","element3");
+ echo %a; [comment]# echo expects its arguments to be scalar[/comment]
+ [/example]
+
+ [p]
+ Conversely, when you put a scalar in place of an array, KVIrc automatically
+ transforms it to an array with a single item. In this way a function like
+ [fnc]$sort[/fnc] works also with a scalar.
+ [/p]
+
+ [p]
+ In literature the conversions between data types are called [b]casts[/b]. When
+ the conversion is automatic the cast is said to be [b]implicit[/b].
+ [/p]
+
+ [p]
+ KVS handles also the other possible implicit casts: scalar->hash,hash->scalar,array->hash,hash->array.
+ Experiment with it.
+ [/p]
+
+ [title]More about scalars[/title]
+
+ [p]
+ Internally KVS is implicitly typed: the "scalar" data type is in fact
+ a set of types that KVIrc manages silently. The types are: integer, string, real, boolean and hobject.
+ [/p]
+
+ [p]
+ Integers are non-floating point numbers. Their allowable range depends on the underlying
+ platform integer size: usually 32 or 64 bit.
+ [/p]
+
+ [p]
+ Reals are floating point numbers. Their allowable range and precision depends on the underlying
+ platform.
+ [/p]
+
+ [p]
+ Booleans are either true or false values.
+ [/p]
+
+ [p]
+ Hobject stands for Handle to Object and it is a sort of a C++ pointer.
+ Detailed description of objects is in [doc:objects]this document[/doc].
+ [/p]
+
+ [p]
+ Basically anything else fails in the "string" category.
+ [/p]
+
+ [p]
+ In most cases KVS manages all the conversions between data types automatically.
+ For example an integer becomes a true boolean when it's non zero and a false boolean
+ otherwise, a real becomes an integer by truncating it's fractional part...
+ [/p]
+
+ [p]
+ You can find out the type of a specified variable by using the [fnc]$typeof[/fnc]() function.
+ [/p]
+
+ [example]
+ %a = 1
+ echo $typeof(%a)
+ %a = 1.1
+ echo $typeof(%a)
+ %a = $true
+ echo $typeof(%a)
+ %a = "test"
+ echo $typeof(%a)
+ [/example]
+
+ [p]
+ There is also another subtle type of scalar called "nothing". It stands for an
+ empty (unset) variable.
+ [/p]
+
+ [example]
+ %a = $nothing
+ echo $typeof(%a)
+ [/example]
+
+ [p]
+ Nothing is something in between a data type and a special value for all the other data types:
+ it rappresents absence of information.
+ This may look a bit confusing but realize that all the unreferenced KVS variable are in fact of type "nothing":
+ they just don't exist. This means that you can use [fnc]$nothing[/fnc]() to effectively
+ unset a variable.
+ [p]
+
+ [p]
+ Again, when possible, the conversion between nothing and the other data types is
+ performed automatically. Nothing becomes an empty string, a null object handle or an empty array.
+ [/p]
+
+
+ [title]Explicit casts[/title]
+
+ [p]
+ You can make explicit conversions between some data types by using the casting functions.
+ [fnc]$integer[/fnc]() will attempt to convert the variant parameter to an integer, [fnc]$real[/fnc]()
+ will cast to a floating point value, [fnc]$boolean[/fnc]() will convert to a
+ true/false value, [fnc]$string[/fnc]() will explicitly convert to a string,
+ [fnc]$array[/fnc]() will convert to an array and [fnc]$hash[/fnc] will return
+ a dictionary. By assigning the special [fnc]$nothing[/fnc]() value you will
+ convert to the nothing data type (or simply unset the variable).
+ The only explicit conversion that is not possible is to hobject.
+ [/p]
+
+ [p]
+ As stated several times in this document, KVS tries to manage the casts automatically
+ so you usually don't need to care about it. The explicit casts are provided for
+ the very few cases where an automatic conversion would lead to an unexpected value (for your script)
+ and for writer's clarity.
+ [/p]
+
+ [title]More about variables lifecycle[/title]
+
+ [p]
+ As stated above variables start their existence when you assign something to them.
+ After a variable has been created it persists until it goes out of his scope (remember
+ about local and global variables ?) or you explicitly destroy it. You will usually
+ not care about it and just leave the KVS engine to do his cleaning job but it's still worth
+ knowing that you actually can force KVIrc to free the memory used by a variable.
+ [/p]
+
+ [p]
+ The first method to explicitly destroy a variable is to call [cmd]unset[/cmd] on it.
+ [cmd]unset[/cmd] in fact accepts a list of variables so you can destroy more variables at once.
+ [/p]
+
+ [example]
+ %a = [fnc]$array[/fnc]("data","for","a","really","huge","array","of","items")
+ %b = 10
+ %c = "just a string that eats memory"
+ [cmd]unset[/cmd] %a,%b,%c
+ [/example]
+
+ [p]
+ The KVS engine treats unset variables just like empty strings. The opposite is also valid: empty
+ strings behave like empty (unset) variables. This means that you can assign an empty string
+ to a variable to unset it.
+ [/p]
+
+ [example]
+ %a = "test"; [comment]# %a starts his existence[/comment]
+ %b = "test2";
+ %a = ""; [comment]# %a is in fact unset[/comment]
+ %b = ; [comment]# syntactically this is just the same as above[/comment]
+ [/example]
+
+ [p]
+ Note that because of mutability of variables (explained above) you can use the empty string
+ assignment also to free arrays and hashes.
+ [/p]
+
+ [title]Extended scope variables[/title]
+
+ [p]
+ Beside local and global variables there is a third family of them.
+ Variables that have a ':' character just after the leading '%' are [b]extended scope[/b] variables.
+ "%:index" , "%:Hello" , "%:something.else" are all valid special scope variable names.
+ They're actually used in popups and in timers (but later I might find other usages as well :).
+ "Extended scope" means that these variables are somewhere in the middle between
+ global and local variables. They normally act as local , but in some cases their [b]lifetime[/b] and [b]visibility[/b]
+ may be extended.
+ [/p]
+
+ [p]
+ For example , in the popups , all the special scope variables
+ are visible during all the "lifetime" of a popup (so from the prologue code call to
+ the moment when the user selects an item and the corresponding code is executed).
+ This allows you to pre-calculate some data or conditions in the popup prologue
+ and use this data in the popup item conditions and item handlers.
+ [/p]
+
+ [title]Variable evaluation[/title]
+
+ [p]
+ A variable can appear in every place where a parameter
+ is expected: so after the command name, after a switch or inside
+ an identifier parameters. The KVS parser will try to extract the longest possible variable
+ name after a literal percent '%' sign everywhere in the parameter string. So the command sequence
+ [/p]
+ [example]
+ %number = 1st; echo this is my %number variable test
+ [/example]
+ [p]
+ will first assign "1st" to the variable "%number" and then execute
+ "echo this is my 1st variable test". The following example will NOT work as expected.
+ [/p]
+ [example]
+ %number = 1; echo this is my %numberst variable test
+ [/example]
+ [p]
+ KVS will assign "1" to %number in this case but the next variable
+ name extracted will be "%numberst" that is actually empty; so finally
+ "echo this is my variable test" will be executed.
+ To avoid this problem you can use the backslash escape character:
+ [/p]
+ [example]
+ %number = 1; echo this is my %number\st variable test
+ [/example]
+
+ [title]Putting it all together[/title]
+
+ [p]
+ Variables can be either local, global or have an extended scope. Their start to exist
+ when you first assign something to them and they disappear when they go out of their
+ scope or you explicitly destroy them.
+ [/p]
+
+ [p]
+ KVS has 8 builtin data types: string, integer, real, boolean, hobject, nothing, array and hash.
+ The first 6 are scalar data types while the last two are not.
+ [/p]
+
+ [p]
+ When possible, KVS manages all the conversions between data types silently.
+ In the few cases in that an implicit conversion is not possible you have to manage the conversion
+ manually otherwise KVS will complain.
+ [/p]
+*/
+
+
+
+void KviKvsParser::skipSpaces()
+{
+ while((KVSP_curCharUnicode == ' ') || (KVSP_curCharUnicode == '\t'))
+ {
+ KVSP_skipChar;
+ }
+
+ if(KVSP_curCharUnicode == '\\')
+ {
+ KVSP_skipChar;
+ if(KVSP_curCharUnicode == '\n')
+ {
+ KVSP_skipChar;
+ skipSpaces();
+ return;
+ } else if(KVSP_curCharUnicode == '\r')
+ {
+ KVSP_skipChar;
+ if(KVSP_curCharUnicode == '\n')
+ {
+ KVSP_skipChar;
+ skipSpaces();
+ return;
+ } else {
+ KVSP_backChar;
+ KVSP_backChar;
+ }
+ } else {
+ KVSP_backChar;
+ }
+ }
+}
+
+
+
+bool KviKvsParser::skipSpacesAndNewlines()
+{
+ while((KVSP_curCharUnicode == ' ') || (KVSP_curCharUnicode == '\t') || (KVSP_curCharUnicode == '\n') || (KVSP_curCharUnicode == '\r'))
+ {
+ KVSP_skipChar;
+ }
+
+ switch(KVSP_curCharUnicode)
+ {
+ case '\\':
+ KVSP_skipChar;
+ if(KVSP_curCharUnicode == '\n')
+ {
+ KVSP_skipChar;
+ return skipSpacesAndNewlines();
+ } else if(KVSP_curCharUnicode == '\r')
+ {
+ KVSP_skipChar;
+ if(KVSP_curCharUnicode == '\n')
+ {
+ KVSP_skipChar;
+ return skipSpacesAndNewlines();
+ } else {
+ KVSP_backChar;
+ KVSP_backChar;
+ }
+ } else {
+ KVSP_backChar;
+ }
+ break;
+ case '#':
+ case '/':
+ // we allow comments too!
+ (void)parseComment(); // this will return 0 anyway (and never trigger an error here)
+ if(error())return false;
+ return skipSpacesAndNewlines();
+ break;
+ }
+ return true;
+}
+
+void KviKvsParser::skipToNextLine()
+{
+ while((KVSP_curCharUnicode != 0) && (KVSP_curCharUnicode != '\n'))
+ KVSP_skipChar;
+
+ if(KVSP_curCharUnicode == '\n')KVSP_skipChar;
+}
+
+
+KviKvsTreeNodeInstruction * KviKvsParser::parseInstructionList()
+{
+ KviKvsTreeNodeInstructionBlock * l = new KviKvsTreeNodeInstructionBlock(KVSP_curCharPointer);
+
+
+ for(;;)
+ {
+ if(!skipSpacesAndNewlines())
+ {
+ delete l;
+ return 0;
+ }
+
+ if(KVSP_curCharUnicode != 0)
+ {
+ // instruction
+ KviKvsTreeNodeInstruction * i = parseInstruction();
+ if(i)l->addInstruction(i);
+ else {
+ if(error())
+ {
+ // ops...
+ delete l;
+ return 0;
+ } // else empty instruction
+ }
+ } else {
+ if(l->instructionCount() == 1)
+ {
+ // return the single instruction instead
+ KviKvsTreeNodeInstruction * i = l->releaseFirst();
+ delete l;
+ return i;
+ }
+ // end of buffer
+ return l;
+ }
+ }
+
+ // never here
+ KVSP_ASSERT(false);
+ return 0;
+}
+
+
+
+
+KviKvsTreeNodeData * KviKvsParser::parseParameterPercentOrDollar()
+{
+ KVSP_ASSERT((KVSP_curCharUnicode == '%') || (KVSP_curCharUnicode == '$') || (KVSP_curCharUnicode == '@'));
+
+ if(KVSP_curCharUnicode == '%')
+ {
+ KVSP_skipChar;
+ if(!KVSP_curCharIsLetter && (KVSP_curCharUnicode != ':'))
+ {
+ // be flexible : allow an "alone" '%' char
+ return new KviKvsTreeNodeConstantData(KVSP_curCharPointer - 1,new KviKvsVariant(QString("%")));
+ }
+ // this is surely a variable or function
+ KVSP_backChar;
+ } else if(KVSP_curCharUnicode == '$')
+ {
+ KVSP_skipChar;
+ if(!KVSP_curCharIsFunctionStart)
+ {
+ // be flexible : allow an "alone" '$' char
+ return new KviKvsTreeNodeConstantData(KVSP_curCharPointer - 1,new KviKvsVariant(QString("$")));
+ }
+ // this is surely a variable or function
+ KVSP_backChar;
+ }
+
+ return parsePercentOrDollar();
+}
+
+
+
+KviKvsTreeNodeData * KviKvsParser::parsePercentOrDollar(bool bInObjScope)
+{
+ KVSP_ASSERT((KVSP_curCharUnicode == '%') || (KVSP_curCharUnicode == '$') || (KVSP_curCharUnicode == '@'));
+
+ KviKvsTreeNodeData * r;
+ const QChar * pBegin;
+
+ if(KVSP_curCharUnicode == '%')
+ {
+ r = parsePercent(bInObjScope);
+ if(!r)return 0;
+ } else if(KVSP_curCharUnicode == '$')
+ {
+ r = parseDollar(bInObjScope);
+ if(!r)return 0;
+ } else {
+ // this is @
+ static QString szStrayAtRoutineName("@");
+ static QString szMightBeStrayAtOrThisRoutineName("@?");
+
+ pBegin = KVSP_curCharPointer;
+
+ KVSP_skipChar;
+
+ if(bInObjScope || ((KVSP_curCharUnicode != '$') && (KVSP_curCharUnicode != '%')))
+ {
+ // we're sure this is just a stray @
+ // we use a trick here: when @ is not supposed to be an object scope call
+ // then we create a function that will return the @ itself as a string
+ KviKvsCoreFunctionExecRoutine * pRoutine = KviKvsKernel::instance()->findCoreFunctionExecRoutine(szStrayAtRoutineName);
+ r = new KviKvsTreeNodeCoreFunctionCall(KVSP_curCharPointer,szStrayAtRoutineName,pRoutine,new KviKvsTreeNodeDataList(KVSP_curCharPointer));
+ //KVSP_skipChar;
+ return r;
+ }
+ // we're not in object scope and cur char is either $ or %
+ // check for the common syntax $0!$1@$2 seen in hostmasks
+ // @$<digit> is non valid anyway
+ if(KVSP_curCharUnicode == '$')
+ {
+ KVSP_skipChar;
+ if(KVSP_curCharIsNumber)
+ {
+ // again a stray @
+ KVSP_backChar;
+ KviKvsCoreFunctionExecRoutine * pRoutine = KviKvsKernel::instance()->findCoreFunctionExecRoutine(szStrayAtRoutineName);
+ r = new KviKvsTreeNodeCoreFunctionCall(KVSP_curCharPointer,szStrayAtRoutineName,pRoutine,new KviKvsTreeNodeDataList(KVSP_curCharPointer));
+ return r;
+ }
+ KVSP_backChar;
+ }
+
+ // now we're unsure: we will be able to decide only at runtime if it is a stray @ or the shortcut for $this
+ // this design was a bit ugly.. I must admit it... but it is really useful when writing object classes...
+ KviKvsCoreFunctionExecRoutine * pRoutine = KviKvsKernel::instance()->findCoreFunctionExecRoutine(szMightBeStrayAtOrThisRoutineName);
+ // MUST BE THERE!
+ // core function call
+ r = new KviKvsTreeNodeCoreFunctionCall(pBegin,szMightBeStrayAtOrThisRoutineName,pRoutine,new KviKvsTreeNodeDataList(pBegin));
+
+ skipSpaces();
+
+ goto handle_scope_operator;
+ }
+
+ pBegin = KVSP_curCharPointer;
+
+ while((KVSP_curCharUnicode == '[') || (KVSP_curCharUnicode == '{'))
+ {
+ if(KVSP_curCharUnicode == '[')
+ {
+ // array index
+ KVSP_skipChar;
+ skipSpaces();
+ if(KVSP_curCharUnicode == ']')
+ {
+ KVSP_skipChar;
+ if(KVSP_curCharUnicode == '#')
+ {
+ // count
+ KVSP_skipChar;
+ return new KviKvsTreeNodeArrayCount(pBegin,r);
+ } else {
+ // a hash reference assert
+ return new KviKvsTreeNodeArrayReferenceAssert(pBegin,r);
+ }
+ }
+
+ KviKvsTreeNodeExpression * e = parseExpression(']');
+ if(!e)
+ {
+ delete r;
+ return 0;
+ }
+
+ r = new KviKvsTreeNodeArrayElement(pBegin,r,e);
+ } else {
+ // hash key
+ KVSP_skipChar;
+ skipSpaces();
+
+ if(KVSP_curCharUnicode == '}')
+ {
+ // entire hash ?
+ KVSP_skipChar;
+ if(KVSP_curCharUnicode == '#')
+ {
+ KVSP_skipChar;
+ return new KviKvsTreeNodeHashCount(pBegin,r);
+ }
+ return new KviKvsTreeNodeHashReferenceAssert(pBegin,r);
+ }
+
+ KviKvsTreeNodeData * i = parseHashKey();
+ if(!i)
+ {
+ // error
+ delete r;
+ return 0;
+ }
+
+ KVSP_ASSERT(KVSP_curCharUnicode == '}');
+
+ KVSP_skipChar;
+
+ r = new KviKvsTreeNodeHashElement(pBegin,r,i);
+ }
+ }
+
+ if(KVSP_curCharUnicode != '-')
+ {
+ return r;
+ }
+
+ if(!r->canEvaluateToObjectReference())return r; // FIXME: maybe print a warning ?
+
+ // might be a scope operator
+
+ KVSP_skipChar;
+ if(KVSP_curCharUnicode != '>')
+ {
+ KVSP_backChar;
+ return r;
+ }
+
+
+ KVSP_skipChar;
+ skipSpaces();
+
+ if((KVSP_curCharUnicode != '$') && (KVSP_curCharUnicode != '%'))
+ {
+ KVSP_setCurCharPointer(pBegin);
+ return r;
+ }
+
+handle_scope_operator:
+
+ // hmmm... there really seems to be a scope operator there...
+ if(KVSP_curCharUnicode == '%')
+ {
+ KVSP_skipChar;
+ if(!KVSP_curCharIsLetter)
+ {
+ // be flexible : allow an "alone" '%' char
+ KVSP_setCurCharPointer(pBegin);
+ return r;
+ }
+ } else {
+ KVSP_skipChar;
+ if(!KVSP_curCharIsFunctionStart)
+ {
+ // be flexible : allow an "alone" '$' char
+ KVSP_setCurCharPointer(pBegin);
+ return r;
+ }
+ }
+
+ // ok : try the scope operator
+ KVSP_backChar;
+
+ pBegin = KVSP_curCharPointer;
+
+ KviKvsTreeNodeData * r2 = parsePercentOrDollar(true);
+
+ if(!r2)
+ {
+ // must be an error
+ delete r;
+ return 0;
+ }
+
+ if(!r2->canEvaluateInObjectScope())
+ {
+ // ops... it really wasn't
+ delete r2;
+ KVSP_setCurCharPointer(pBegin);
+ return r;
+ }
+
+ return new KviKvsTreeNodeScopeOperator(pBegin,r,r2);
+}
+
+
+
+
+
+KviKvsTreeNodeVariable * KviKvsParser::parsePercent(bool bInObjScope)
+{
+ KVSP_ASSERT(KVSP_curCharUnicode == '%');
+
+ const QChar * pBegin = KVSP_curCharPointer;
+
+ KVSP_skipChar;
+
+ bool bExtScope;
+
+ if(KVSP_curCharUnicode == ':')
+ {
+ bExtScope = true;
+ KVSP_skipChar;
+ } else {
+ bExtScope = false;
+ }
+
+ if(!((KVSP_curCharIsLetterOrNumber) || (KVSP_curCharUnicode == '_')))
+ {
+ error(KVSP_curCharPointer,__tr2qs("Syntax error after '%' variable prefix. If you want to use a plain '%' in the code you need to escape it"));
+ return 0;
+ }
+
+ const QChar * pIdBegin = KVSP_curCharPointer;
+
+ while((KVSP_curCharIsLetterOrNumber) || (KVSP_curCharUnicode == '_') || (KVSP_curCharUnicode == '.'))KVSP_skipChar;
+
+ QString szIdentifier(pIdBegin,KVSP_curCharPointer - pIdBegin);
+
+//#warning "ADD A KviKvsTreeNodeBuiltinCleanupVariablesCommand on this KviKvsParser object"
+//#warning "KviKvsParser will append it to the script"
+
+ if(bExtScope)
+ {
+ if(bInObjScope)
+ {
+ error(KVSP_curCharPointer,__tr2qs("Objects have no extended scope variables"));
+ return 0;
+ }
+ return new KviKvsTreeNodeExtendedScopeVariable(pBegin,szIdentifier);
+ }
+
+ if(bInObjScope)
+ return new KviKvsTreeNodeObjectField(pBegin,szIdentifier);
+
+ if(m_pGlobals)
+ {
+ if(m_pGlobals->find(szIdentifier))return new KviKvsTreeNodeGlobalVariable(pBegin,szIdentifier);
+ }
+
+ if(m_iFlags & AssumeLocals)
+ return new KviKvsTreeNodeLocalVariable(pBegin,szIdentifier);
+
+ if(pIdBegin->category() & QChar::Letter_Uppercase)
+ {
+ //if(m_iFlags & Pedantic)
+ // warning(pIdBegin,__tr2qs("Declaring global variables with an uppercase letter is deprecated. Global variables should be declared with 'global'"));
+ return new KviKvsTreeNodeGlobalVariable(pBegin,szIdentifier);
+ }
+
+ return new KviKvsTreeNodeLocalVariable(pBegin,szIdentifier);
+}
+
+KviKvsTreeNodeInstruction * KviKvsParser::parseInstruction()
+{
+ switch(KVSP_curCharUnicode)
+ {
+ case '#':
+ case '/':
+ (void)parseComment(); // this will return 0 anyway
+ return 0;
+ break;
+ case 0: // empty instruction
+ return 0;
+ break;
+ case '\n':
+ case '\r':
+ case ';': // empty instruction
+ KVSP_skipChar;
+ return 0;
+ break;
+ case '{': // command block
+ return parseInstructionBlock();
+ break;
+ case '$':
+ case '%':
+ case '@':
+ return parseVoidFunctionCallOrOperation();
+ break;
+ default:
+ if(KVSP_curCharIsLetter || (KVSP_curCharUnicode == '_'))
+ {
+ // must be a command
+ return parseCommand();
+ } else {
+ // what the heck is this ?
+ error(KVSP_curCharPointer,__tr2qs("Found character '%q' (unicode %x) where an instruction was expected"),KVSP_curCharPointer,KVSP_curCharUnicode);
+ return 0;
+ }
+ break;
+ }
+
+ // never here
+ KVSP_ASSERT(false);
+ return 0;
+}
+
+KviKvsTreeNodeInstruction * KviKvsParser::parseInstructionBlock()
+{
+ KVSP_ASSERT(KVSP_curCharUnicode == '{');
+
+ KVSP_skipChar;
+
+ const QChar * pBegin = KVSP_curCharPointer;
+
+ KviKvsTreeNodeInstructionBlock * b = new KviKvsTreeNodeInstructionBlock(pBegin - 1);
+
+ for(;;)
+ {
+ if(!skipSpacesAndNewlines())
+ {
+ delete b;
+ return 0;
+ }
+
+ switch(KVSP_curCharUnicode)
+ {
+ case 0:
+ delete b;
+ warning(pBegin,__tr2qs("Unterminated instruction block"));
+ error(KVSP_curCharPointer,__tr2qs("Unexpected end of script in instruction block (missing closing brace)"));
+ return 0;
+ break;
+ case '}':
+ KVSP_skipChar;
+ if(b->instructionCount() <= 1)
+ {
+ if(b->instructionCount() < 1)
+ {
+ delete b;
+ return 0; // just an empty block
+ }
+ // a single instruction
+ KviKvsTreeNodeInstruction * i = b->releaseFirst();
+ delete b;
+ return i;
+ }
+ return b;
+ break;
+ default:
+ // instruction
+ KviKvsTreeNodeInstruction * i = parseInstruction();
+ if(i)b->addInstruction(i);
+ else {
+ if(error())
+ {
+ // ops...
+ delete b;
+ return 0;
+ } // else empty instruction
+ }
+ break;
+ }
+ }
+ // never reached
+ return 0;
+}
+
+KviKvsTreeNodeSwitchList * KviKvsParser::parseCommandSwitchList()
+{
+ KVSP_ASSERT(KVSP_curCharUnicode == '-');
+
+ KviKvsTreeNodeSwitchList * sw = new KviKvsTreeNodeSwitchList(KVSP_curCharPointer);
+
+ while(KVSP_curCharUnicode == '-')
+ {
+ const QChar * pBegin = KVSP_curCharPointer;
+ KVSP_skipChar;
+
+ bool bLong = false;
+
+ if(KVSP_curCharUnicode == '-')
+ {
+ // long switch
+ pBegin = KVSP_curCharPointer;
+ KVSP_skipChar;
+ bLong = true;
+ }
+
+ skipSpaces();
+ if(!KVSP_curCharIsLetter)
+ {
+ if(KVSP_curCharIsNumber || KVSP_curCharIsEndOfCommand)
+ {
+ // a -digit : this is probably a negative number instead
+ // or just a single dash (or couple of dashes)
+ // go back to the initial dash and treat it as text...and return the current switch list
+ KVSP_setCurCharPointer(pBegin);
+ if(sw->isEmpty())
+ {
+ // not an error!
+ delete sw;
+ return 0;
+ }
+ return sw;
+ } else {
+ delete sw;
+ warning(pBegin,__tr2qs("The dash after a command should be followed by a letter (switch), by a digit (negative number) or be escaped"));
+
+ if(KVSP_curCharUnicode == 0)
+ {
+ error(KVSP_curCharPointer,__tr2qs("Unexpected character '%q' (unicode %x) after a switch dash"),KVSP_curCharPointer,KVSP_curCharUnicode);
+ } else {
+ error(KVSP_curCharPointer,__tr2qs("Unexpected end of script after a switch dash"));
+ }
+ return 0;
+ }
+ }
+
+ const QChar * pSw = KVSP_curCharPointer;
+
+ KVSP_skipChar;
+ while((KVSP_curCharIsLetterOrNumber) || (KVSP_curCharUnicode == '-'))KVSP_skipChar;
+
+ const QChar * pSwEnd = KVSP_curCharPointer;
+
+ skipSpaces();
+
+ if(KVSP_curCharUnicode == '=')
+ {
+ KVSP_skipChar;
+ skipSpaces();
+ KviKvsTreeNodeData * p = parseCommandParameter();
+ if(!p)
+ {
+ // must be an error :(
+ if(error())
+ {
+ error(pBegin,__tr2qs("The above problem might be related to the switch dash and the following equal sign"));
+ delete sw;
+ return 0;
+ } else {
+ // assume empty string
+ p = new KviKvsTreeNodeConstantData(KVSP_curCharPointer,new KviKvsVariant(QString("")));
+ }
+ }
+
+ skipSpaces();
+
+ if(bLong)
+ sw->addLong(QString(pSw,pSwEnd - pSw),p);
+ else
+ sw->addShort(pSw->lower().unicode(),p);
+ } else {
+ if(bLong)
+ sw->addLong(QString(pSw,pSwEnd - pSw),new KviKvsTreeNodeConstantData(KVSP_curCharPointer,new KviKvsVariant(true))); // empty param
+ else
+ sw->addShort(pSw->lower().unicode(),new KviKvsTreeNodeConstantData(KVSP_curCharPointer,new KviKvsVariant(true))); // empty param
+ }
+ }
+
+ return sw;
+}
+
+
+
+KviKvsTreeNodeDataList * KviKvsParser::parseCommandParameterList()
+{
+ KviKvsTreeNodeDataList * l = new KviKvsTreeNodeDataList(KVSP_curCharPointer);
+
+ for(;;)
+ {
+ skipSpaces();
+ switch(KVSP_curCharUnicode)
+ {
+ case 0:
+ return l;
+ break;
+ case '\r':
+ case '\n':
+ case ';':
+ KVSP_skipChar;
+ return l;
+ break;
+ default:
+ // anything else is a parameter
+ KviKvsTreeNodeData * p = parseCommandParameter();
+ if(!p)
+ {
+ // this is an error
+ delete l;
+ return 0;
+ }
+ l->addItem(p);
+ break;
+ }
+ }
+
+ // never here
+ KVSP_ASSERT(false);
+ return 0;
+}
+
+
+KviPointerList<QString> * KviKvsParser::parseCommaSeparatedParameterListNoTree()
+{
+ KviPointerList<QString> * l = new KviPointerList<QString>;
+ l->setAutoDelete(true);
+
+ KVSP_skipChar;
+
+ for(;;)
+ {
+ skipSpaces();
+ switch(KVSP_curCharUnicode)
+ {
+ case 0:
+ error(KVSP_curCharPointer,__tr2qs("Unexpected end of script in parameter list"));
+ delete l;
+ return 0;
+ break;
+ case '\r':
+ case '\n':
+ error(KVSP_curCharPointer,__tr2qs("Unexpected end of line in parameter list"));
+ delete l;
+ return 0;
+ break;
+ /*
+ case ',':
+ KVSP_skipChar;
+ break;
+ case ')':
+ KVSP_skipChar;
+ return l;
+ break;
+ */
+ default:
+ {
+ // anything else is a parameter
+ const QChar *pBegin = KVSP_curCharPointer;
+ KviKvsTreeNodeData * p = parseCommaSeparatedParameter();
+ if(!p)
+ {
+ // this is an error
+ delete l;
+ return 0;
+ }
+ delete p;
+ QString * s = new QString(pBegin,KVSP_curCharPointer - pBegin);
+ s->stripWhiteSpace();
+ l->append(s);
+
+ switch(KVSP_curCharUnicode)
+ {
+ case ',':
+ KVSP_skipChar;
+ break;
+ case ')':
+ KVSP_skipChar;
+ return l;
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ // never here
+ KVSP_ASSERT(false);
+ return 0;
+}
+
+
+KviKvsTreeNodeDataList * KviKvsParser::parseCommaSeparatedParameterList()
+{
+ KviKvsTreeNodeDataList * l = new KviKvsTreeNodeDataList(KVSP_curCharPointer);
+
+ KVSP_skipChar;
+
+ for(;;)
+ {
+ skipSpaces();
+ switch(KVSP_curCharUnicode)
+ {
+ case 0:
+ error(KVSP_curCharPointer,__tr2qs("Unexpected end of script in parameter list"));
+ delete l;
+ return 0;
+ break;
+ case '\r':
+ case '\n':
+ error(KVSP_curCharPointer,__tr2qs("Unexpected end of line in parameter list"));
+ delete l;
+ return 0;
+ break;
+ /*
+ case ',':
+ KVSP_skipChar;
+ break;
+ case ')':
+ KVSP_skipChar;
+ return l;
+ break;
+ */
+ default:
+ // anything else is a parameter
+ KviKvsTreeNodeData * p = parseCommaSeparatedParameter();
+ if(!p)
+ {
+ // this is an error
+ delete l;
+ return 0;
+ }
+ l->addItem(p);
+
+ switch(KVSP_curCharUnicode)
+ {
+ case ',':
+ KVSP_skipChar;
+ break;
+ case ')':
+ KVSP_skipChar;
+ return l;
+ break;
+ }
+ break;
+ }
+ }
+
+ // never here
+ KVSP_ASSERT(false);
+ return 0;
+}
+
+
+#define LITERAL_PARAM_PARSING_FUNCTION_BEGIN(__funcname) \
+KviKvsTreeNodeConstantData * KviKvsParser::__funcname() \
+{ \
+ QString szValue; \
+\
+ const QChar * pStart = KVSP_curCharPointer; \
+ const QChar * pBegin = KVSP_curCharPointer; \
+ int iLen = 0; \
+ int iNestedTerminators = 0; \
+ \
+ for(;;) \
+ { \
+ switch(KVSP_curCharUnicode) \
+ {
+
+#define LITERAL_PARAM_PARSING_FUNCTION_WARN_NESTED_TERMINATOR \
+ if(!_OUTPUT_MUTE) \
+ warning(KVSP_curCharPointer,__tr2qs("Nested character %q corresponding to expected terminator, this might confuse me a bit: it is a good idea to enclose it in quotes"),KVSP_curCharPointer); \
+ KVSP_skipChar; \
+ iNestedTerminators++; \
+ iLen++; \
+ break;
+
+#define LITERAL_PARAM_PARSING_FUNCTION_END_WITH_EXPECTED_TERMINATOR \
+ if(iNestedTerminators > 0) \
+ { \
+ if(!_OUTPUT_MUTE) \
+ warning(KVSP_curCharPointer,__tr2qs("Skipping nested terminator character %q"),KVSP_curCharPointer); \
+ KVSP_skipChar; \
+ iNestedTerminators--; \
+ iLen++; \
+ } else { \
+ if(iLen > 0)szValue.append(QString(pBegin,iLen)); \
+ { \
+ bool bOk; \
+ kvs_int_t iVal = szValue.toLong(&bOk); \
+ if(bOk)return new KviKvsTreeNodeConstantData(pBegin,new KviKvsVariant(iVal)); \
+ kvs_real_t dVal = szValue.toDouble(&bOk); \
+ if(bOk)return new KviKvsTreeNodeConstantData(pBegin,new KviKvsVariant(dVal)); \
+ } \
+ return new KviKvsTreeNodeConstantData(pBegin,new KviKvsVariant(szValue)); \
+ } \
+ break;
+
+#define LITERAL_PARAM_PARSING_FUNCTION_GENERIC_END \
+ if(iLen > 0) szValue.append(QString(pBegin,iLen)); \
+ return new KviKvsTreeNodeConstantData(pBegin,new KviKvsVariant(szValue)); \
+ break; \
+ case '\\': \
+ if(iLen > 0)szValue.append(QString(pBegin,iLen)); \
+ KVSP_skipChar; \
+ switch(KVSP_curCharUnicode) \
+ { \
+ case 0: \
+ warning(KVSP_curCharPointer - 1,__tr2qs("Stray backslash at the end of the script")); \
+ iLen = 0; \
+ break; \
+ case '\r': \
+ case '\n': \
+ KVSP_skipChar; \
+ pBegin = KVSP_curCharPointer; \
+ iLen = 0; \
+ break; \
+ case 'r': \
+ KVSP_skipChar; \
+ pBegin = KVSP_curCharPointer; \
+ szValue.append(QChar('\r')); \
+ iLen = 0; \
+ break; \
+ case 'n': \
+ KVSP_skipChar; \
+ pBegin = KVSP_curCharPointer; \
+ szValue.append(QChar('\n')); \
+ iLen = 0; \
+ break; \
+ case 't': \
+ KVSP_skipChar; \
+ pBegin = KVSP_curCharPointer; \
+ szValue.append(QChar('\t')); \
+ iLen = 0; \
+ break; \
+ default: \
+ pBegin = KVSP_curCharPointer; \
+ KVSP_skipChar; \
+ iLen = 1; \
+ break; \
+ } \
+ break; \
+ default: \
+ KVSP_skipChar; \
+ iLen++; \
+ break; \
+ } \
+ } \
+ KVSP_ASSERT(false); \
+ return 0; \
+}
+
+
+LITERAL_PARAM_PARSING_FUNCTION_BEGIN(parseCommandLiteralParameter)
+ case 0:
+ case '$':
+ case '%':
+ case '@':
+ case '\r':
+ case '\n':
+ case '"':
+ case ';':
+ case ' ':
+ case '\t':
+LITERAL_PARAM_PARSING_FUNCTION_GENERIC_END
+
+
+LITERAL_PARAM_PARSING_FUNCTION_BEGIN(parseStringLiteralParameter)
+ case 0:
+ case '$':
+ case '%':
+ case '@':
+ case '\r':
+ case '\n':
+ case '"':
+LITERAL_PARAM_PARSING_FUNCTION_GENERIC_END
+
+/*
+LITERAL_PARAM_PARSING_FUNCTION_BEGIN(parseArrayIndexLiteralParameter)
+ case '\t':
+ case ' ':
+ case ']':
+LITERAL_PARAM_PARSING_FUNCTION_END
+*/
+
+
+LITERAL_PARAM_PARSING_FUNCTION_BEGIN(parseHashKeyLiteralParameter)
+ case '{':
+LITERAL_PARAM_PARSING_FUNCTION_WARN_NESTED_TERMINATOR
+ case '}':
+LITERAL_PARAM_PARSING_FUNCTION_END_WITH_EXPECTED_TERMINATOR
+ case 0:
+ case '$':
+ case '%':
+ case '@':
+ case '\r':
+ case '\n':
+ case '"':
+ case '\t':
+ case ' ':
+LITERAL_PARAM_PARSING_FUNCTION_GENERIC_END
+
+
+LITERAL_PARAM_PARSING_FUNCTION_BEGIN(parseCommaSeparatedLiteralParameter)
+ case '(':
+LITERAL_PARAM_PARSING_FUNCTION_WARN_NESTED_TERMINATOR
+ case ')':
+LITERAL_PARAM_PARSING_FUNCTION_END_WITH_EXPECTED_TERMINATOR
+ case 0:
+ case '$':
+ case '%':
+ case '@':
+ case '\r':
+ case '\n':
+ case '"':
+ case ',':
+ case ' ':
+ case '\t':
+LITERAL_PARAM_PARSING_FUNCTION_GENERIC_END
+
+
+LITERAL_PARAM_PARSING_FUNCTION_BEGIN(parseSingleLiteralParameterInParenthesis)
+ case '(':
+LITERAL_PARAM_PARSING_FUNCTION_WARN_NESTED_TERMINATOR
+ case ')':
+LITERAL_PARAM_PARSING_FUNCTION_END_WITH_EXPECTED_TERMINATOR
+ case 0:
+ case '$':
+ case '%':
+ case '@':
+ case '\r':
+ case '\n':
+ case '"':
+ case ' ':
+ case '\t':
+LITERAL_PARAM_PARSING_FUNCTION_GENERIC_END
+
+LITERAL_PARAM_PARSING_FUNCTION_BEGIN(parseBindingOperationLiteralParameter)
+ case 0:
+ case '$':
+ case '%':
+ case '@':
+ case '\r':
+ case '\n':
+ case '"':
+ case '/':
+LITERAL_PARAM_PARSING_FUNCTION_GENERIC_END
+
+
+/*
+KviKvsTreeNodeData * KviKvsParser::parseArrayIndex()
+{
+ KviPointerList<KviKvsTreeNodeData> * l = new KviPointerList<KviKvsTreeNodeData>();
+ l->setAutoDelete(true);
+
+ const QChar * pBegin = KVSP_curCharPointer;
+
+ //KVSP_skipChar;
+
+ for(;;)
+ {
+ switch(KVSP_curCharUnicode)
+ {
+ case 0:
+ delete l;
+ warning(pBegin,__tr2qs("Unterminated array index"));
+ error(KVSP_curCharPointer,__tr2qs("Unexpected end of script in array index (missing ']' character ?)"));
+ return 0;
+ break;
+ case '\n':
+ delete l;
+ warning(pBegin,__tr2qs("Unterminated array index"));
+ error(KVSP_curCharPointer,__tr2qs("Unexpected end of line in array index (missing ']' character or unescaped newline)"));
+ return 0;
+ break;
+ case ' ':
+ case '\t':
+ skipSpaces();
+ if(KVSP_curCharUnicode != ']')
+ {
+ delete l;
+ warning(pBegin,__tr2qs("Unterminated array index"));
+ switch(KVSP_curCharUnicode)
+ {
+ case 0:
+ error(KVSP_curCharPointer,__tr2qs("Unexpected end of script in array index (missing ']' character ?)"));
+ break;
+ case '\n':
+ error(KVSP_curCharPointer,__tr2qs("Unexpected end of line in array index (missing ']' character or unescaped newline)"));
+ break;
+ default:
+ error(KVSP_curCharPointer,__tr2qs("Unexpected character '%q' (unicode %x) in array index: it should be already terminated"),KVSP_curCharPointer,KVSP_curCharUnicode);
+ break;
+ }
+ return 0;
+ }
+ goto end_of_the_array_index;
+ break;
+ case '$':
+ case '%':
+ {
+ // this may be a data reference
+ KviKvsTreeNodeData * p = parseParameterPercentOrDollar();
+ if(!p)
+ {
+ // this is an error
+ delete l;
+ return 0;
+ }
+ l->append(p);
+ }
+ break;
+ case ']':
+ {
+ // end of the array index
+ goto end_of_the_array_index;
+ }
+ break;
+ case '"':
+ {
+ // string (should we parse strings in array indexes anyway ?).. well "1"$count might be a valid one in the end
+ KviKvsTreeNodeData * p = parseStringParameter();
+ if(!p)
+ {
+ // error
+ delete l;
+ return 0;
+ }
+ l->append(p);
+ }
+ break;
+ default:
+ {
+ // anything else is a literal
+ l->append(parseArrayIndexLiteralParameter());
+ }
+ break;
+ }
+ }
+end_of_the_array_index:
+ if(l->count() > 1)
+ {
+ // complex parameter needed
+ return new KviKvsTreeNodeCompositeData(l);
+ } else {
+ // a single parameter in the list
+ l->setAutoDelete(false);
+ KviKvsTreeNodeData * p = l->first();
+ delete l;
+ return p;
+ }
+
+}
+*/
+
+
+
+
+
+KviKvsTreeNodeData * KviKvsParser::parseHashKey()
+{
+ KviPointerList<KviKvsTreeNodeData> * l = new KviPointerList<KviKvsTreeNodeData>();
+ l->setAutoDelete(true);
+
+ const QChar * pBegin = KVSP_curCharPointer;
+
+ //KVSP_skipChar;
+
+ for(;;)
+ {
+ switch(KVSP_curCharUnicode)
+ {
+ case 0:
+ delete l;
+ warning(pBegin,__tr2qs("Unterminated hash key"));
+ error(KVSP_curCharPointer,__tr2qs("Unexpected end of script in hash key (missing '}' character ?)"));
+ return 0;
+ break;
+ case '\r':
+ case '\n':
+ delete l;
+ warning(pBegin,__tr2qs("Unterminated hash key"));
+ error(KVSP_curCharPointer,__tr2qs("Unexpected end of line in hash key (missing '}' character or unescaped newline)"));
+ return 0;
+ break;
+ case ' ':
+ case '\t':
+ skipSpaces();
+ if(KVSP_curCharUnicode != '}')
+ {
+ // separate by single spaces
+ l->append(new KviKvsTreeNodeConstantData(KVSP_curCharPointer,new KviKvsVariant(QString(" "))));
+ } else {
+ goto end_of_the_hash_key;
+ }
+ break;
+ case '$':
+ case '%':
+ case '@':
+ {
+ // this may be a data reference
+ KviKvsTreeNodeData * p = parseParameterPercentOrDollar();
+ if(!p)
+ {
+ // this is an error
+ delete l;
+ return 0;
+ }
+ l->append(p);
+ }
+ break;
+ case '}':
+ {
+ // end of the array index
+ goto end_of_the_hash_key;
+ }
+ break;
+ case '"':
+ {
+ // string
+ KviKvsTreeNodeData * p = parseStringParameter();
+ if(!p)
+ {
+ // error
+ delete l;
+ return 0;
+ }
+ l->append(p);
+ }
+ break;
+ default:
+ {
+ // anything else is a literal
+ l->append(parseHashKeyLiteralParameter());
+ }
+ break;
+ }
+ }
+end_of_the_hash_key:
+ if(l->count() > 1)
+ {
+ // complex parameter needed
+ return new KviKvsTreeNodeCompositeData(pBegin,l);
+ } else {
+ // a single parameter in the list
+ l->setAutoDelete(false);
+ KviKvsTreeNodeData * p = l->first();
+ delete l;
+ return p;
+ }
+ // never reached
+ return 0;
+}
+
+/*
+PARENTHESIS_PARAMETER_PARSING_FUNCTION_BEGIN(parseCommaSeparatedParameter)
+ case 0:
+ case ',':
+ case ')':
+ case '\n':
+PARENTHESIS_PARAMETER_PARSING_FUNCTION_END()
+
+#define PARENTHESIS_PARAMETER_PARSING_FUNCTION_BEGIN(_name) \
+*/
+
+
+
+KviKvsTreeNodeData * KviKvsParser::parseCommaSeparatedParameter()
+{
+ KviPointerList<KviKvsTreeNodeData> * l = new KviPointerList<KviKvsTreeNodeData>;
+ l->setAutoDelete(true);
+
+ const QChar * pBegin = KVSP_curCharPointer;
+
+ for(;;)
+ {
+ switch(KVSP_curCharUnicode)
+ {
+ case 0:
+ case ',':
+ case ')':
+ case '\r':
+ case '\n':
+ // not a part of a parameter
+ goto end_of_function_parameter;
+ break;
+ case '$':
+ case '%':
+ case '@':
+ {
+ // this may be a data reference
+ KviKvsTreeNodeData * p = parseParameterPercentOrDollar();
+ if(!p)
+ {
+ // this is an error
+ delete l;
+ return 0;
+ }
+ l->append(p);
+ }
+ break;
+ case ' ':
+ case '\t':
+ skipSpaces();
+ if((KVSP_curCharUnicode != ')') && (KVSP_curCharUnicode != ','))
+ {
+ // separate by single spaces
+ l->append(new KviKvsTreeNodeConstantData(KVSP_curCharPointer,new KviKvsVariant(QString(" "))));
+ } else {
+ goto end_of_function_parameter;
+ }
+ break;
+ case '"':
+ {
+ // this is a string
+ KviKvsTreeNodeData * p = parseStringParameter();
+ if(!p)
+ {
+ // this is an error
+ delete l;
+ return 0;
+ }
+ l->append(p);
+ }
+ break;
+ default:
+ {
+ // anything else is a literal
+ l->append(parseCommaSeparatedLiteralParameter());
+ }
+ break;
+ }
+ }
+end_of_function_parameter:
+ if(l->count() > 1)
+ {
+ // complex parameter needed
+ KviKvsTreeNodeData * p = new KviKvsTreeNodeCompositeData(pBegin,l);
+ p->setEndingLocation(KVSP_curCharPointer);
+ return p;
+ } else {
+ // a single parameter in the list, or no params at all
+ l->setAutoDelete(false);
+ KviKvsTreeNodeData * p = l->first();
+ delete l;
+ if(!p)p = new KviKvsTreeNodeConstantData(KVSP_curCharPointer,new KviKvsVariant());
+ p->setEndingLocation(KVSP_curCharPointer);
+ return p;
+ }
+ // never reached
+ return 0;
+}
+
+
+KviKvsTreeNodeData * KviKvsParser::parseSingleParameterInParenthesis()
+{
+ KviPointerList<KviKvsTreeNodeData> * l = new KviPointerList<KviKvsTreeNodeData>;
+ l->setAutoDelete(true);
+
+ const QChar * pBegin = KVSP_curCharPointer;
+
+ for(;;)
+ {
+ switch(KVSP_curCharUnicode)
+ {
+ case ')':
+ // not a part of a parameter
+ KVSP_skipChar;
+ goto end_of_function_parameter;
+ break;
+ case 0:
+ case '\r':
+ case '\n':
+ // not a part of a parameter
+ goto end_of_function_parameter;
+ break;
+ case '$':
+ case '%':
+ case '@':
+ {
+ // this may be a data reference
+ KviKvsTreeNodeData * p = parseParameterPercentOrDollar();
+ if(!p)
+ {
+ // this is an error
+ delete l;
+ return 0;
+ }
+ l->append(p);
+ }
+ break;
+ case ' ':
+ case '\t':
+ skipSpaces();
+ if((KVSP_curCharUnicode != ')') && (KVSP_curCharUnicode != ','))
+ {
+ // separate by single spaces
+ l->append(new KviKvsTreeNodeConstantData(KVSP_curCharPointer,new KviKvsVariant(QString(" "))));
+ } else {
+ goto end_of_function_parameter;
+ }
+ break;
+ case '"':
+ {
+ // this is a string
+ KviKvsTreeNodeData * p = parseStringParameter();
+ if(!p)
+ {
+ // this is an error
+ delete l;
+ return 0;
+ }
+ l->append(p);
+ }
+ break;
+ default:
+ {
+ // anything else is a literal
+ l->append(parseSingleLiteralParameterInParenthesis());
+ }
+ break;
+ }
+ }
+end_of_function_parameter:
+ if(l->count() > 1)
+ {
+ // complex parameter needed
+ KviKvsTreeNodeData * p = new KviKvsTreeNodeCompositeData(pBegin,l);
+ p->setEndingLocation(KVSP_curCharPointer);
+ return p;
+ } else {
+ // a single parameter in the list or list empty at all
+ l->setAutoDelete(false);
+ KviKvsTreeNodeData * p = l->first();
+ if(p)p->setEndingLocation(KVSP_curCharPointer);
+ delete l;
+ return p;
+ }
+ // never reached
+ return 0;
+}
+
+
+KviKvsTreeNodeData * KviKvsParser::parseStringParameter()
+{
+ KVSP_ASSERT(KVSP_curCharUnicode == '"');
+
+ KviPointerList<KviKvsTreeNodeData> * l = new KviPointerList<KviKvsTreeNodeData>();
+ l->setAutoDelete(true);
+
+ const QChar * pBegin = KVSP_curCharPointer;
+
+ KVSP_skipChar;
+
+ for(;;)
+ {
+ switch(KVSP_curCharUnicode)
+ {
+ case 0:
+ delete l;
+ warning(pBegin,__tr2qs("Unterminated string constant"));
+ error(KVSP_curCharPointer,__tr2qs("Unexpected end of script in string constant (missing \" character ?)"));
+ return 0;
+ break;
+ case '\r':
+ case '\n':
+ delete l;
+ warning(pBegin,__tr2qs("Unterminated string constant"));
+ error(KVSP_curCharPointer,__tr2qs("Unexpected end of line in string constant (missing \" character or unescaped newline)"));
+ return 0;
+ break;
+ case '$':
+ case '%':
+ case '@':
+ {
+ // this may be a data reference
+ KviKvsTreeNodeData * p = parseParameterPercentOrDollar();
+ if(!p)
+ {
+ // this is an error
+ delete l;
+ return 0;
+ }
+ l->append(p);
+ }
+ break;
+ case '"':
+ {
+ // end of the string
+ KVSP_skipChar;
+ goto end_of_the_string;
+ }
+ break;
+ default:
+ {
+ // anything else is a literal
+ l->append(parseStringLiteralParameter());
+ }
+ break;
+ }
+ }
+end_of_the_string:
+ if(l->count() > 1)
+ {
+ // complex parameter needed
+ // it is also an implicit string cast
+ return new KviKvsTreeNodeCompositeData(pBegin,l);
+ } else {
+ if(l->count() > 0)
+ {
+ // a single parameter in the list
+ // we need an explicit string cast here (it is the most common cast)
+ l->setAutoDelete(false);
+ KviKvsTreeNodeData * p = l->first();
+ delete l;
+ return new KviKvsTreeNodeStringCast(pBegin,p);
+ } else {
+ // no parameters at all.. return straight empty string (no need to cast)
+ delete l;
+ return new KviKvsTreeNodeConstantData(pBegin,new KviKvsVariant(new QString()));
+ }
+ }
+ // never reached
+ return 0;
+}
+
+KviKvsTreeNodeData * KviKvsParser::parseCommandParameter(bool bPreferNumeric)
+{
+ KviPointerList<KviKvsTreeNodeData> * l = new KviPointerList<KviKvsTreeNodeData>;
+ l->setAutoDelete(true);
+
+ bool bGotLiteral = false;
+
+ const QChar * pBegin = KVSP_curCharPointer;
+
+ for(;;)
+ {
+ switch(KVSP_curCharUnicode)
+ {
+ case 0:
+ case ' ':
+ case '\t':
+ case '\r':
+ case '\n':
+ case ';':
+ // not a part of a parameter
+ goto jumpout;
+ break;
+ case '$':
+ case '%':
+ case '@':
+ {
+ // this may be a data reference
+ KviKvsTreeNodeData * p = parseParameterPercentOrDollar();
+ if(!p)
+ {
+ // this is an error
+ delete l;
+ return 0;
+ }
+ l->append(p);
+ }
+ break;
+ case '"':
+ {
+ // this is a string
+ KviKvsTreeNodeData * p = parseStringParameter();
+ if(!p)
+ {
+ // this is an error
+ delete l;
+ return 0;
+ }
+ l->append(p);
+ }
+ break;
+ default:
+ {
+ bGotLiteral = true;
+ // anything else is a literal
+ l->append(parseCommandLiteralParameter());
+ }
+ break;
+ }
+ }
+jumpout:
+ if(l->count() > 1)
+ {
+ // complex parameter needed
+ KviKvsTreeNodeData * p = new KviKvsTreeNodeCompositeData(pBegin,l);
+ p->setEndingLocation(KVSP_curCharPointer);
+ return p;
+ } else {
+ // a single parameter in the list or empty list at all
+ l->setAutoDelete(false);
+ KviKvsTreeNodeData * p = l->first();
+ delete l;
+ if(p)
+ {
+ if(bGotLiteral)
+ {
+ // a single literal parameter
+ if(bPreferNumeric)
+ {
+ // attempt to convert to a numeric format if this is a constant data item
+ p->convertStringConstantToNumeric();
+ }
+ }
+ p->setEndingLocation(KVSP_curCharPointer);
+ }
+ return p;
+ }
+ // never reached
+ return 0;
+}
+
diff --git a/src/kvirc/kvs/kvi_kvs_parser.h b/src/kvirc/kvs/kvi_kvs_parser.h
new file mode 100644
index 00000000..be98e960
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_parser.h
@@ -0,0 +1,300 @@
+#ifndef _KVI_KVS_PARSER_H_
+#define _KVI_KVS_PARSER_H_
+//=============================================================================
+//
+// File : kvi_kvs_parser.h
+// Creation date : Thu 25 Sep 2003 05.12 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_pointerlist.h"
+
+#include "kvi_pointerhashtable.h"
+
+class KviKvsTreeNode;
+
+class KviKvsTreeNodeInstruction;
+class KviKvsTreeNodeInstructionBlock;
+class KviKvsTreeNodeCommand;
+class KviKvsTreeNodeDataList;
+class KviKvsTreeNodeData;
+class KviKvsTreeNodeVariable;
+class KviKvsTreeNodeVariableReference;
+class KviKvsTreeNodeConstantData;
+class KviKvsTreeNodeSwitchList;
+class KviKvsTreeNodeSpecialCommand;
+class KviKvsTreeNodeExpression;
+class KviKvsTreeNodeExpressionBinaryOperator;
+class KviKvsTreeNodeFunctionCall;
+class KviKvsTreeNodeOperation;
+class KviKvsTreeNodeSpecialCommandDefpopupLabelPopup;
+
+class KviKvsScript;
+class KviKvsKernel;
+class KviWindow;
+
+// This is an ONE-TIME parser used by KviKvsScript
+
+class KVIRC_API KviKvsParser
+{
+ friend class KviKvsKernel;
+public:
+ KviKvsParser(KviKvsScript * pScript,KviWindow * pOutputWindow);
+ ~KviKvsParser();
+private:
+ const QChar * m_pBuffer; // the local pointer to the beginning of the buffer
+ const QChar * m_ptr; // the parsing pointer
+ // parsing state
+ KviPointerHashTable<QString,QString> * m_pGlobals; // the dict of the vars declared with global in this script
+ int m_iFlags; // the current parsing flags
+ bool m_bError; // error(..) was called ?
+ // this stuff is used only for reporting errors and warnings
+ KviKvsScript * m_pScript; // parent script
+ KviWindow * m_pWindow; // output window
+public: // public interface
+ enum Flags { AssumeLocals = 1, Pedantic = 2 };
+ // was there an error ?
+ bool error() const { return m_bError; };
+ // parses the buffer pointed by pBuffer and returns
+ // a syntax tree or 0 in case of failure
+ // if the parsing fails, the error code can be retrieved by calling error()
+ KviKvsTreeNodeInstruction * parse(const QChar * pBuffer,int iFlags = 0);
+ KviKvsTreeNodeInstruction * parseAsExpression(const QChar * pBuffer,int iFlags = 0);
+ KviKvsTreeNodeInstruction * parseAsParameter(const QChar * pBuffer,int iFlags = 0);
+private: // parsing helpers
+ // generic
+ void skipSpaces(); // skips only spaces and tabs (eventually with \)
+ bool skipSpacesAndNewlines(); // skips space and newlines
+ void skipToNextLine(); // skips up to a new line
+ // dedicated
+ void skipToEndOfCStyleComment();
+ // dedicated to parseSpecialCommandFor() : in kvi_kvs_parser_specialcommands.cpp
+ bool skipToEndOfForControlBlock();
+ // error handlers
+ void error(const QChar * pLocation,const QString &szMsgFmt,...);
+ void warning(const QChar * pLocation,const QString &szMsgFmt,...);
+ void errorBadChar(const QChar * pLocation,char cExpected,const char * szCommandName);
+
+protected:
+ // this is called by KviKvsKernel to register the parsing routines
+ static void init();
+private:
+ // returns 0 only in case of error
+ // starts on the first char of a buffer
+ // stops at the first null char encountered
+ KviKvsTreeNodeInstruction * parseInstructionList();
+ // may return 0 (empty instruction), check error() for error conditions
+ // starts on the first character of an instruction
+ // if the first char is ';' '\n' or null it just returns 0 without error
+ // stops after the ending char of the instruction
+ KviKvsTreeNodeInstruction * parseInstruction();
+ // may return 0 (empty block), check error() for error conditions
+ // starts at the leading '{' of the block
+ // stops after the trailing '}' of the block
+ KviKvsTreeNodeInstruction * parseInstructionBlock();
+ // returns 0 only in case of error
+ // starts on the first character of the parameters
+ // ends after the end of the command
+ KviKvsTreeNodeDataList * parseCommandParameterList();
+ // returns 0 only in case of error
+ // starts on the leading '(' or a ',' in the middle of the list
+ // ends after the trailing ')'
+ // if started in the middle of the list returns only the remaining
+ // parameters.
+ KviKvsTreeNodeDataList * parseCommaSeparatedParameterList();
+ KviPointerList<QString> * parseCommaSeparatedParameterListNoTree();
+ // returns 0 in case of error or if it starts on a terminating character (null parameter)
+ // check error() to see if there was an error condition (unless you already know that
+ // there was a valid first character)
+ // start on the first character of the parameter
+ // ends after the first character not included in the param (';','\n','\0',' ')
+ // If bPreferNumeric is true then when a single literal parameter
+ // is extracted an attempt to convert it to a numeric format is made.
+ // This optimizes assignments, self-sums etc...
+ KviKvsTreeNodeData * parseCommandParameter(bool bPreferNumeric = false);
+ // returns 0 only in case of error
+ // start on the first character of the parameter
+ // ends after the first character not included in the param (')','\n','\0',',')
+ KviKvsTreeNodeData * parseCommaSeparatedParameter();
+ // returns 0 only in case of error
+ // start on the first character of the parameter
+ // ends after the first character not included in the param (')','\n','\0')
+ KviKvsTreeNodeData * parseSingleParameterInParenthesis();
+ // never returns 0
+ KviKvsTreeNodeConstantData * parseCommandLiteralParameter();
+ // never returns 0
+ KviKvsTreeNodeConstantData * parseCommaSeparatedLiteralParameter();
+ // never returns 0
+ KviKvsTreeNodeConstantData * parseSingleLiteralParameterInParenthesis();
+ // returns 0 only in case of error
+ // starts at the leading '"'
+ // ends after the trailing '"'
+ KviKvsTreeNodeData * parseStringParameter();
+ // never returns 0
+ KviKvsTreeNodeConstantData * parseStringLiteralParameter();
+ // returns 0 in case of error or of an empty switch list (check the error code!)
+ // starts at the leading '-' of the first switch
+ // ends after the last switch
+ KviKvsTreeNodeSwitchList * parseCommandSwitchList();
+ // returns 0 only in case of error
+ // starts at '%' or '$'
+ // and ends after the end of the data reference
+ // or just after the '%' or '$' if this was only a ConstandData (not a var or func)
+ KviKvsTreeNodeData * parseParameterPercentOrDollar();
+ // returns 0 only in case of error
+ // starts at '%' or '$'
+ // ends after the end of the complete data reference (including scope operators!)
+ KviKvsTreeNodeData * parsePercentOrDollar(bool bInObjScope = false);
+ // returns 0 only in case of error
+ // starts at '%'
+ // ends after the end of the structured data
+ KviKvsTreeNodeVariable * parsePercent(bool bInObjectScope = false);
+ // returns 0 only in case of error
+ KviKvsTreeNodeData * parseHashKey();
+ // never returns 0
+ KviKvsTreeNodeConstantData * parseHashKeyLiteralParameter();
+
+ //
+ // kvi_kvs_parser_specialcommands.cpp
+ //
+
+ // return 0 only in case of error
+ // starts at the leading '(' of the if command (after the switches)
+ // and stops after the end of the else block
+ // if the first character is not '(' then this function fails with an error
+ KviKvsTreeNodeCommand * parseSpecialCommandIf();
+ // always returns 0
+ // check error() for error conditions
+ // starts after the switches of the "global" keyword
+ // and stops at the end of the command
+ // if the first character is not '%' of a variable then this function fails with an error
+ KviKvsTreeNodeCommand * parseSpecialCommandGlobal();
+ // returns 0 only in case of error
+ // starts at the leading '(' of the while command (after the switches)
+ // and stops after the end of the command block
+ // if the first character is not '(' then this function fails with an error
+ KviKvsTreeNodeCommand * parseSpecialCommandWhile();
+ // returns 0 only in case of error
+ // starts at the leading '(' of the while command (after the switches)
+ // and stops after the end of the command block
+ // if the first character is not '(' then this function fails with an error
+ KviKvsTreeNodeCommand * parseSpecialCommandDo();
+ // returns 0 only in case of error
+ // and stops after the end of the break command
+ KviKvsTreeNodeCommand * parseSpecialCommandBreak();
+ // returns 0 only in case of error
+ // and stops after the end of the for command block
+ KviKvsTreeNodeCommand * parseSpecialCommandFor();
+ // returns 0 only in case of error
+ // and stops after the end of the foreach command block
+ KviKvsTreeNodeCommand * parseSpecialCommandForeach();
+ // returns 0 only in case of error
+ // and stops after the end of the switch command block
+ KviKvsTreeNodeCommand * parseSpecialCommandSwitch();
+ // returns 0 only in case of error
+ // and stops after the end of the defpopup command block
+ KviKvsTreeNodeCommand * parseSpecialCommandUnset();
+ // returns 0 only in case of error
+ // and stops after the end of the defpopup command block
+ KviKvsTreeNodeCommand * parseSpecialCommandDefpopup();
+ KviKvsTreeNodeSpecialCommandDefpopupLabelPopup * parseSpecialCommandDefpopupLabelPopup();
+ // returns 0 only in case of error
+ // stops after the class command block
+ KviKvsTreeNodeCommand * parseSpecialCommandClass();
+ // returns 0 only in case of error
+ // stops after the perl.end statement
+ KviKvsTreeNodeCommand * parseSpecialCommandPerlBegin();
+ // returns 0 only in case of error
+ // and stops after the end of the help command
+ KviKvsTreeNodeCommand * parseSpecialCommandHelp();
+
+ //
+ // kvi_kvs_parser_command.cpp
+ //
+
+ // may return 0 (empty command), check error() for error conditions
+ // starts at the beginning of a command (can be non valid)
+ // ends after the ending char of the command
+ KviKvsTreeNodeCommand * parseCommand();
+
+
+ //
+ // kvi_kvs_parser_comment.cpp
+ //
+
+ // always returns 0, and it CAN be an error!
+ // starts at the beginning of a comment (must be '#' or '/')
+ // ends after the ending char of the comment
+ KviKvsTreeNode * parseComment();
+
+
+ //
+ // kvi_kvs_parser_dollar.cpp
+ //
+
+ // returns 0 only in case of error
+ // starts at '$'
+ // ends after the end of the function call
+ KviKvsTreeNodeData * parseDollar(bool bInObjScope = false);
+
+ // returns 0 only in case of error
+ // starts at '@'
+ // ends after the end of the function call
+ KviKvsTreeNodeData * parseAt(bool bInObjScope = false);
+
+ //
+ // kvi_kvs_parser_lside.cpp
+ //
+
+ // returns 0 only in case of error
+ // returns after the command terminator
+ KviKvsTreeNodeInstruction * parseVoidFunctionCallOrOperation();
+ // returns 0 only in case of error
+ // returns after the command terminator
+ KviKvsTreeNodeOperation * parseOperation();
+ // returns 0 only in case of error
+ // returns after the command terminator
+ // If bPreferNumeric is propagated to parseCommandParameter() function
+ KviKvsTreeNodeData * parseOperationRightSide(bool bPreferNumeric = false);
+ // return 0 only in case of error
+ // returns after the command terminator
+ KviKvsTreeNodeOperation * parseBindingOperation();
+ KviKvsTreeNodeConstantData * parseBindingOperationLiteralParameter();
+ KviKvsTreeNodeData * parseBindingOperationParameter();
+
+ //
+ // kvi_kvs_parser_expression.cpp
+ //
+
+ // returns 0 only in case of error
+ // starts AFTER the leading char of the expression
+ // ends afer the first terminator found
+ KviKvsTreeNodeExpression * parseExpression(char terminator);
+ KviKvsTreeNodeExpressionBinaryOperator * parseExpressionBinaryOperator();
+ KviKvsTreeNodeExpression * parseExpressionOperand(char terminator);
+ KviKvsTreeNodeExpression * parseExpressionOperandCore(char terminator);
+ bool parseExpressionMightPointToOperator();
+
+ void report(bool bError,const QChar * pLocation,const QString &szMsgFmt,kvi_va_list va);
+};
+
+#endif //!_KVI_KVS_PARSER_H_
diff --git a/src/kvirc/kvs/kvi_kvs_parser_command.cpp b/src/kvirc/kvs/kvi_kvs_parser_command.cpp
new file mode 100644
index 00000000..bd50d23f
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_parser_command.cpp
@@ -0,0 +1,339 @@
+//=============================================================================
+//
+// File : kvi_kvs_parser_command.cpp
+// Creation date : Thu 03 Nov 2003 13.23 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+
+#include "kvi_kvs_parser.h"
+
+#include "kvi_kvs_treenode.h"
+
+#include "kvi_kvs_report.h"
+#include "kvi_kvs_kernel.h"
+
+#include "kvi_kvs_parser_macros.h"
+
+#include "kvi_locale.h"
+
+#include "kvi_kvs_script.h"
+
+#include "kvi_cmdformatter.h"
+
+
+KviKvsTreeNodeCommand * KviKvsParser::parseCommand()
+{
+ KVSP_ASSERT(KVSP_curCharIsLetter || (KVSP_curCharUnicode == '_'));
+
+
+ const QChar * pIdentifier = KVSP_curCharPointer;
+
+ while(KVSP_curCharIsLetterOrNumber || (KVSP_curCharUnicode == '_'))KVSP_skipChar;
+
+ int iIdentifierLen = KVSP_curCharPointer - pIdentifier;
+
+ const QChar * pSecondPart = 0;
+ int iSecondPartLen = 0;
+
+ bool bHasNamespaceSoMustBeAlias = false;
+
+ if(KVSP_curCharUnicode == '.')
+ {
+ // a module command
+ KVSP_skipChar;
+
+ pSecondPart = KVSP_curCharPointer;
+
+ if(!KVSP_curCharIsLetter)
+ {
+ warning(KVSP_curCharPointer - 1,__tr2qs("Stray dot ('.') character or invalid following module command name"));
+ error(KVSP_curCharPointer,__tr2qs("Syntax error: malformed module command identifier"));
+ return 0;
+ }
+
+ KVSP_skipChar;
+ while(KVSP_curCharIsLetterOrNumber || (KVSP_curCharUnicode == '_'))KVSP_skipChar;
+
+ iSecondPartLen = KVSP_curCharPointer - pSecondPart;
+ } else while(KVSP_curCharUnicode == ':')
+ {
+ // an alias with namespace(s) ?
+
+ // here we allow the syntax of the form
+ // <namespace>::{<namespace>::}<alias_name>
+
+ bHasNamespaceSoMustBeAlias = true;
+
+ KVSP_skipChar;
+ if(KVSP_curCharUnicode == ':')
+ {
+ KVSP_skipChar;
+
+ if(!KVSP_curCharIsLetter)
+ {
+ warning(KVSP_curCharPointer - 1,__tr2qs("Stray '::' sequence or invalid following alias name"));
+ error(KVSP_curCharPointer,__tr2qs("Syntax error: malformed alias identifier"));
+ return 0;
+ }
+
+ KVSP_skipChar;
+ while(KVSP_curCharIsLetterOrNumber || (KVSP_curCharUnicode == '_'))KVSP_skipChar;
+ } else {
+ warning(KVSP_curCharPointer - 1,__tr2qs("Stray ':' character: did you mean '...<namespace>::<alias_name>' ?"));
+ error(KVSP_curCharPointer,__tr2qs("Syntax error: malformed (alias?) command identifier"));
+ return 0;
+ }
+
+ iIdentifierLen = KVSP_curCharPointer - pIdentifier;
+ }
+
+ QString szIdentifier(pIdentifier,iIdentifierLen);
+
+ skipSpaces();
+
+ KviKvsTreeNodeSwitchList * sw = 0;
+ KviKvsTreeNodeData * pRebindData;
+
+ if(KVSP_curCharUnicode == '-')
+ {
+ // extract the switch
+ sw = parseCommandSwitchList();
+ if(!sw)
+ {
+ if(error())
+ return 0;
+ // else it might be a negative number or something that does not seem
+ // to be a switch anyway
+ pRebindData = 0;
+ } else {
+ pRebindData = sw->getStandardRebindingSwitch();
+ }
+ } else {
+ pRebindData = 0;
+ }
+
+ KviKvsTreeNodeCommand * cmd;
+
+ if(!bHasNamespaceSoMustBeAlias)
+ {
+ // perl.begin has a *really* half special parsing routine
+ if(iIdentifierLen == 4)
+ {
+ if(pIdentifier->lower().unicode() == 'p')
+ {
+ if(KviQString::equalCI(szIdentifier,"perl"))
+ {
+ if(pSecondPart)
+ {
+ QString szSecondPart(pSecondPart,iSecondPartLen);
+ if(KviQString::equalCI(szSecondPart,"begin"))
+ {
+ // yep, that's perl.begin
+ cmd = parseSpecialCommandPerlBegin();
+ if(!cmd)
+ {
+ // might be an error , but might be not...
+ // it is an error only if error() returns true
+ // but since the caller will take care of it
+ // we just return 0
+ if(sw)delete sw;
+ if(pRebindData)delete pRebindData;
+ return 0;
+ }
+ cmd->setLocation(pIdentifier);
+ if(sw)
+ {
+ cmd->setSwitchList(sw);
+ // cmd becomes child of the rebinding switch
+ if(pRebindData)return new KviKvsTreeNodeRebindingSwitch(pRebindData->location(),pRebindData,cmd);
+ }
+ return cmd;
+ }
+ }
+ }
+ }
+ }
+
+ if(!pSecondPart)
+ {
+ // is this a special command ?
+
+ // Here theoretically we could also lookup special commands composed of two parts but we actually don't need it.
+
+ // Looking up only the first part if there is a second part, instead,
+ // is dangerous since it may generate infinite loops (help.open vs help)
+
+ KviKvsSpecialCommandParsingRoutine * ccpr = KviKvsKernel::instance()->findSpecialCommandParsingRoutine(szIdentifier);
+
+ if(ccpr)
+ {
+ cmd = (this->*(ccpr->proc))();
+ if(!cmd)
+ {
+ // might be an error , but might be not...
+ // it is an error only if error() returns true
+ // but since the caller will take care of it
+ // we just return 0
+ if(sw)delete sw;
+ if(pRebindData)delete pRebindData;
+ return 0;
+ }
+ cmd->setLocation(pIdentifier);
+ if(sw)
+ {
+ cmd->setSwitchList(sw);
+ // cmd becomes child of the rebinding switch
+ if(pRebindData)return new KviKvsTreeNodeRebindingSwitch(pRebindData->location(),pRebindData,cmd);
+ }
+ return cmd;
+ }
+ }
+
+ // is it a callback command ?
+ if(KVSP_curCharUnicode == '(')
+ {
+ // core callback command
+ // module callback command
+ KviKvsTreeNodeDataList * dl = parseCommaSeparatedParameterList();
+ if(!dl)
+ {
+ if(sw)delete sw;
+ if(pRebindData)delete pRebindData;
+ return 0;
+ }
+ if(!skipSpacesAndNewlines())
+ {
+ if(sw)delete sw;
+ if(pRebindData)delete pRebindData;
+ delete dl;
+ return 0;
+ }
+
+ const QChar * pClbkBegin = KVSP_curCharPointer;
+
+ KviKvsTreeNodeInstruction * ins = parseInstruction();
+ if(!ins)
+ {
+ if(error())
+ {
+ if(sw)delete sw;
+ if(pRebindData)delete pRebindData;
+ return 0;
+ }
+ // actually we need empty callbacks (for alias() at least)
+ // the single command implementations should take care of checking it
+ /*else {
+
+ warning(pIdentifier,__tr2qs("Callback command called with an empty callback instruction"));
+ error(KVSP_curCharPointer,__tr2qs("Callback commands must have a callback instruction"));
+ if(sw)delete sw;
+ delete dl;
+ return 0;
+
+ }*/
+ } else {
+ delete ins; // in fact we don't need it, it will be reparsed the first time it is called
+ // Q: Couldn't we actually use the already parsed tree ?
+ // A: No: the tree must be reparsed in a new parser context
+ // since we're keeping track of global and local variables...
+ // The locals of this context are NOT the same as the locals
+ // of the other context.
+ }
+
+ QString szCallbackName = szIdentifier;
+ szCallbackName += " callback";
+
+ QString szBlock(pClbkBegin,KVSP_curCharPointer - pClbkBegin);
+ KviCommandFormatter::bufferFromBlock(szBlock);
+
+ KviKvsScript * clbk = new KviKvsScript(szCallbackName,szBlock);
+
+ if(pSecondPart)
+ {
+ cmd = new KviKvsTreeNodeModuleCallbackCommand(pIdentifier,szIdentifier,QString(pSecondPart,iSecondPartLen),dl,clbk);
+ } else {
+ KviKvsCoreCallbackCommandExecRoutine * r = KviKvsKernel::instance()->findCoreCallbackCommandExecRoutine(szIdentifier);
+ if(r)
+ {
+ cmd = new KviKvsTreeNodeCoreCallbackCommand(pIdentifier,szIdentifier,dl,r,clbk);
+ } else {
+ error(KVSP_curCharPointer,__tr2qs("Unknown callback command \"%Q\""),&szIdentifier);
+ if(sw)delete sw;
+ if(pRebindData)delete pRebindData;
+ delete dl;
+ delete clbk;
+ return 0;
+ }
+ }
+
+ if(sw)
+ {
+ cmd->setSwitchList(sw);
+ // cmd becomes child of the rebinding switch
+ if(pRebindData)return new KviKvsTreeNodeRebindingSwitch(pRebindData->location(),pRebindData,cmd);
+ }
+
+ return cmd;
+ }
+ }
+
+ // must be core simple command, module simple command or alias
+ KviKvsTreeNodeDataList * pl = parseCommandParameterList();
+ if(!pl)
+ {
+ if(sw)delete sw;
+ if(pRebindData)delete pRebindData;
+ return 0; // this MUST be an error
+ }
+
+ if(bHasNamespaceSoMustBeAlias)
+ {
+ // alias for sure, bind at runtime
+ cmd = new KviKvsTreeNodeAliasSimpleCommand(pIdentifier,szIdentifier,pl);
+ } else {
+ if(pSecondPart)
+ {
+ cmd = new KviKvsTreeNodeModuleSimpleCommand(pIdentifier,szIdentifier,QString(pSecondPart,iSecondPartLen),pl);
+ } else {
+ KviKvsCoreSimpleCommandExecRoutine * r = KviKvsKernel::instance()->findCoreSimpleCommandExecRoutine(szIdentifier);
+ if(r)
+ {
+ cmd = new KviKvsTreeNodeCoreSimpleCommand(pIdentifier,szIdentifier,pl,r);
+ } else {
+ // must be an alias in root namespace, bind at runtime
+ cmd = new KviKvsTreeNodeAliasSimpleCommand(pIdentifier,szIdentifier,pl);
+ }
+ }
+ }
+
+ if(sw)
+ {
+ cmd->setSwitchList(sw);
+ // cmd becomes child of the rebinding switch
+ if(pRebindData)return new KviKvsTreeNodeRebindingSwitch(pRebindData->location(),pRebindData,cmd);
+ }
+
+ return cmd;
+}
+
+
diff --git a/src/kvirc/kvs/kvi_kvs_parser_comment.cpp b/src/kvirc/kvs/kvi_kvs_parser_comment.cpp
new file mode 100644
index 00000000..e731e2b1
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_parser_comment.cpp
@@ -0,0 +1,101 @@
+//=============================================================================
+//
+// File : kvi_kvs_parser_comment.cpp
+// Creation date : Thu 03 Nov 2003 13.23 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+
+#include "kvi_kvs_parser.h"
+
+#include "kvi_kvs_treenode.h"
+
+#include "kvi_kvs_report.h"
+#include "kvi_kvs_kernel.h"
+
+#include "kvi_kvs_parser_macros.h"
+
+#include "kvi_locale.h"
+
+
+
+KviKvsTreeNode * KviKvsParser::parseComment()
+{
+#ifdef COMPILE_NEW_KVS
+
+ KVSP_ASSERT((KVSP_curCharUnicode == '#') || (KVSP_curCharUnicode == '/'));
+
+ switch(KVSP_curCharUnicode)
+ {
+ case '#': // bash style
+ skipToNextLine();
+ break;
+ case '/':
+ KVSP_skipChar;
+ switch(KVSP_curCharUnicode)
+ {
+ case '/':
+ // c++ style
+ skipToNextLine();
+ break;
+ case '*':
+ {
+ const QChar * pBegin = KVSP_curCharPointer;
+ // c style , multiline
+ KVSP_skipChar;
+ for(;;)
+ {
+ switch(KVSP_curCharUnicode)
+ {
+ case 0:
+ warning(pBegin,__tr2qs("Unterminated c-style multiline comment"));
+ error(KVSP_curCharPointer,__tr2qs("Unexpected end of script in multiline comment"));
+ return 0;
+ break;
+ case '*':
+ KVSP_skipChar;
+ if(KVSP_curCharUnicode == '/')
+ {
+ KVSP_skipChar;
+ return 0;
+ }
+ break;
+ }
+ KVSP_skipChar;
+ }
+ }
+ break;
+ default:
+ error(KVSP_curCharPointer,__tr2qs("Unexpected character '%q' (unicode %x) after a slash (it is a typo or a malformed comment begin ?)"),KVSP_curCharPointer,KVSP_curCharUnicode);
+ return 0;
+ break;
+ }
+ break;
+ default:
+ // shouldn't be here :/
+ KVSP_ASSERT(false);
+ break;
+ }
+#endif
+ return 0;
+}
+
diff --git a/src/kvirc/kvs/kvi_kvs_parser_dollar.cpp b/src/kvirc/kvs/kvi_kvs_parser_dollar.cpp
new file mode 100644
index 00000000..0f304bd7
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_parser_dollar.cpp
@@ -0,0 +1,331 @@
+//=============================================================================
+//
+// File : kvi_kvs_parser_dollar.cpp
+// Creation date : Thu 5 Oct 2003 20.20 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+
+#include "kvi_kvs_parser.h"
+#include "kvi_kvs_treenode.h"
+
+#include "kvi_kvs_report.h"
+#include "kvi_kvs_kernel.h"
+
+#include "kvi_kvs_parser_macros.h"
+
+#include "kvi_locale.h"
+
+
+
+
+KviKvsTreeNodeData * KviKvsParser::parseDollar(bool bInObjScope)
+{
+ KVSP_ASSERT(KVSP_curCharUnicode == '$');
+
+ const QChar * pDollarBegin = KVSP_curCharPointer;
+ const QChar * pBegin = KVSP_curCharPointer;
+
+ KVSP_skipChar;
+
+ if(!KVSP_curCharIsFunctionStart)
+ {
+ if(KVSP_curCharUnicode == 0)warning(KVSP_curCharPointer,__tr2qs("Unexpected end of script after '$' function call prefix"));
+ else warning(KVSP_curCharPointer,__tr2qs("Unexpected character %q (unicode %x) after '$' function call prefix"),KVSP_curCharPointer,KVSP_curCharUnicode);
+ error(KVSP_curCharPointer,__tr2qs("Syntax error after '$' function call prefix. If you want to use a plain '$' in the code you need to escape it"));
+ return 0;
+ }
+
+ if(KVSP_curCharUnicode == '(')
+ {
+ // expression eval
+ if(bInObjScope)
+ {
+ error(KVSP_curCharPointer,__tr2qs("Invalid expression evaluation in object scope"));
+ return 0;
+ }
+
+ KVSP_skipChar;
+ skipSpaces();
+
+ return parseExpression(')');
+ }
+
+ if(KVSP_curCharUnicode == '{')
+ {
+ // command block eval <--- senseless ???
+ if(bInObjScope)
+ {
+ error(KVSP_curCharPointer,__tr2qs("Invalid command evaluation in object scope"));
+ return 0;
+ }
+
+ KviKvsTreeNodeInstruction * i = parseInstructionBlock();
+ if(!i)
+ {
+ if(error())return false;
+ // trigger an error anyway: this is abused syntax :D
+ error(KVSP_curCharPointer,__tr2qs("Empty instruction block for command evaluation"));
+ return false;
+ }
+
+ return new KviKvsTreeNodeCommandEvaluation(pDollarBegin,i);
+ }
+
+ if(KVSP_curCharIsNumber)
+ {
+ // this is a parameter identifier
+ // $1-4 $1- $3
+
+ if(bInObjScope)
+ {
+ error(KVSP_curCharPointer,__tr2qs("Parameter identifiers are forbidden in object scope (after the '->' operator)"));
+ return 0;
+ }
+
+ pBegin = KVSP_curCharPointer;
+
+ while(KVSP_curCharIsNumber)
+ KVSP_skipChar;
+
+ QString szNum1(pBegin,KVSP_curCharPointer - pBegin);
+ bool bOk;
+ int iNum1 = szNum1.toInt(&bOk);
+ if(!bOk)debug("Ops... a non-number made by numbers ?");
+
+ if(KVSP_curCharUnicode != '-')
+ {
+ // end
+ return new KviKvsTreeNodeSingleParameterIdentifier(pDollarBegin,iNum1);
+ }
+
+ // dash... make sure it's not $N->$something
+ KVSP_skipChar;
+ if(KVSP_curCharUnicode == '>')
+ {
+ // object scope operator in fact...
+ // go back to the - and return a single parameter identifier
+ KVSP_backChar;
+ return new KviKvsTreeNodeSingleParameterIdentifier(pDollarBegin,iNum1);
+ }
+
+ if(!KVSP_curCharIsNumber)
+ {
+ // from iNum1 to the end
+ return new KviKvsTreeNodeMultipleParameterIdentifier(pDollarBegin,iNum1,-1);
+ }
+
+ pBegin = KVSP_curCharPointer;
+ while(KVSP_curCharIsNumber)
+ KVSP_skipChar;
+
+ QString szNum2(pBegin,KVSP_curCharPointer - pBegin);
+ int iNum2 = szNum2.toInt(&bOk);
+ if(!bOk)debug("Ops... a non-number made by numbers (2) ?");
+
+ if(iNum1 < iNum2)return new KviKvsTreeNodeMultipleParameterIdentifier(pDollarBegin,iNum1,iNum2);
+ else {
+ warning(pBegin,__tr2qs("Ending index of a multiple parameter identifier is lower or equal to the starting index. This will evaluate to a single parameter identifier."));
+ return new KviKvsTreeNodeSingleParameterIdentifier(pDollarBegin,iNum1);
+ }
+ }
+
+ pBegin = KVSP_curCharPointer;
+
+ //KVSP_skipChar;
+
+ bool bHasNamespaceNotInObjScopeSoMustBeAlias = false; // ;D
+ bool bIsThis = false;
+
+ if(KVSP_curCharUnicode == '$')
+ {
+ if(bInObjScope)
+ {
+ error(KVSP_curCharPointer,__tr2qs("Syntax error: invalid $$ ($this) function call in object scope"));
+ return 0;
+ }
+ // handle $$
+ KVSP_skipChar;
+ } else {
+ while((KVSP_curCharIsLetterOrNumber) || (KVSP_curCharUnicode == '_'))KVSP_skipChar;
+ if(!bInObjScope)
+ {
+ while(KVSP_curCharUnicode == ':')
+ {
+ // check for namespaces
+
+ // here we allow the syntax of the form
+ // <namespace>::{<namespace>::}<alias_name>
+
+ bHasNamespaceNotInObjScopeSoMustBeAlias = true; // ;D
+
+ KVSP_skipChar;
+ if(KVSP_curCharUnicode == ':')
+ {
+ KVSP_skipChar;
+
+ if(!KVSP_curCharIsLetter)
+ {
+ warning(KVSP_curCharPointer - 1,__tr2qs("Stray '::' sequence or invalid following alias name"));
+ error(KVSP_curCharPointer,__tr2qs("Syntax error: malformed alias function call identifier"));
+ return 0;
+ }
+
+ KVSP_skipChar;
+ while(KVSP_curCharIsLetterOrNumber || (KVSP_curCharUnicode == '_'))KVSP_skipChar;
+ } else {
+ warning(KVSP_curCharPointer - 1,__tr2qs("Stray ':' character: did you mean '...<namespace>::<alias_name>' ?"));
+ error(KVSP_curCharPointer,__tr2qs("Syntax error: malformed (alias?) function call identifier"));
+ return 0;
+ }
+ }
+ }
+ }
+
+ QString szIdentifier1(pBegin,KVSP_curCharPointer - pBegin);
+
+ const QChar * pId2 = 0;
+ int iId2Len = 0;
+ bool bModuleFunctionCall = false;
+
+ if(!bHasNamespaceNotInObjScopeSoMustBeAlias)
+ {
+ if(!bInObjScope)
+ {
+ if(KVSP_curCharUnicode == '.')
+ {
+ KVSP_skipChar;
+ if(KVSP_curCharIsLetter)
+ {
+ pId2 = KVSP_curCharPointer;
+ while((KVSP_curCharIsLetterOrNumber) || (KVSP_curCharUnicode == '_'))
+ KVSP_skipChar;
+ iId2Len = KVSP_curCharPointer - pId2;
+ bModuleFunctionCall = true;
+ } else {
+ KVSP_backChar;
+ }
+ }
+ } else {
+ // object scope, check for "class name" namespace
+ // the class name namespace has the format "<namespace>::<namespace>::..::<classname>
+ // so the last :: is the delimiter of the function name
+ const QChar * pOriginalEndOfId1 = KVSP_curCharPointer;
+ const QChar * pEndOfId1 = pOriginalEndOfId1;
+
+ while(KVSP_curCharUnicode == ':')
+ {
+ const QChar * pEndOfId1 = KVSP_curCharPointer;
+ // base class function call ?
+ KVSP_skipChar;
+ if(KVSP_curCharUnicode == ':')
+ {
+ KVSP_skipChar;
+ if(KVSP_curCharIsLetter)
+ {
+ pId2 = KVSP_curCharPointer;
+ while((KVSP_curCharIsLetterOrNumber) || (KVSP_curCharUnicode == '_'))
+ KVSP_skipChar;
+ iId2Len = KVSP_curCharPointer - pId2;
+ } else {
+ KVSP_setCurCharPointer(pOriginalEndOfId1);
+ pId2 = 0;
+ iId2Len = 0;
+ break;
+ }
+ } else {
+ KVSP_setCurCharPointer(pOriginalEndOfId1);
+ pId2 = 0;
+ iId2Len = 0;
+ break;
+ }
+ }
+ if(pId2)
+ {
+ // yes, that's fine: reset it
+ szIdentifier1.setUnicode(pBegin,pEndOfId1 - pBegin);
+ }
+ }
+ }
+
+ KviKvsTreeNodeDataList * l;
+
+ if(KVSP_curCharUnicode != '(')
+ {
+ // no parameters passed
+ //KVSP_setCurCharPointer(pBegin);
+ // will get an empty data list
+ l = new KviKvsTreeNodeDataList(pDollarBegin);
+ } else {
+ // check for the special syntax ()
+ KVSP_skipChar;
+ if(KVSP_curCharUnicode == ')')
+ {
+ // $call(), assume no parameters passed
+ l = new KviKvsTreeNodeDataList(pDollarBegin);
+ KVSP_skipChar;
+ } else {
+ KVSP_backChar;
+ l = parseCommaSeparatedParameterList();
+ if(!l)return 0; // error
+ }
+ }
+
+ if(bHasNamespaceNotInObjScopeSoMustBeAlias)
+ {
+ // namespace::alias function call
+ return new KviKvsTreeNodeAliasFunctionCall(pDollarBegin,szIdentifier1,l);
+ } else if(bModuleFunctionCall)
+ {
+ // module function call
+ return new KviKvsTreeNodeModuleFunctionCall(pDollarBegin,szIdentifier1,QString(pId2,iId2Len),l);
+ } else {
+
+ if(bInObjScope)
+ {
+ // object function call (our parent will be a scope operator)
+ if(pId2)
+ {
+ // base class object function call
+ return new KviKvsTreeNodeBaseObjectFunctionCall(pDollarBegin,szIdentifier1,QString(pId2,iId2Len),l);
+ } else {
+ // plain object function call
+ return new KviKvsTreeNodeThisObjectFunctionCall(pDollarBegin,szIdentifier1,l);
+ }
+ } else {
+ // core or alias function call
+ KviKvsCoreFunctionExecRoutine * r = KviKvsKernel::instance()->findCoreFunctionExecRoutine(szIdentifier1);
+ if(r)
+ {
+ // core function call
+ return new KviKvsTreeNodeCoreFunctionCall(pDollarBegin,szIdentifier1,r,l);
+ } else {
+ // root namespace alias function call
+ return new KviKvsTreeNodeAliasFunctionCall(pDollarBegin,szIdentifier1,l);
+ }
+ }
+ }
+
+ // not reached
+ KVSP_ASSERT(false);
+ return 0;
+}
diff --git a/src/kvirc/kvs/kvi_kvs_parser_expression.cpp b/src/kvirc/kvs/kvi_kvs_parser_expression.cpp
new file mode 100644
index 00000000..832a814d
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_parser_expression.cpp
@@ -0,0 +1,636 @@
+//=============================================================================
+//
+// File : kvi_kvs_parser_expression.cpp
+// Creation date : Mon 6 Oct 2003 01.31 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+
+#include "kvi_kvs_parser.h"
+
+#include "kvi_kvs_treenode.h"
+
+#include "kvi_kvs_report.h"
+#include "kvi_kvs_kernel.h"
+
+#include "kvi_kvs_parser_macros.h"
+
+#include "kvi_locale.h"
+
+
+//#warning "FIXME: expression eval doc!"
+
+ /*
+ @doc: expressioneval
+ @type:
+ language
+ @title:
+ Expression evaluation identifier
+ @syntax:
+ $(<expression>)
+ @keyterms:
+ expressions
+ @short:
+ Expression evaluation identifier
+ @description:
+ Evaluates <expression> and returns its result.[br]
+ If <expression> is a single string, array or hash, it is returned unmodified.[br]
+ In any other case the expression evaluation returns a numeric value, either real or integer.[br]
+ The expressions are really close to the C ones and have some minor extensions.[br]
+ The supported operators are +,-,*,/,|,&,^,||,&&,^^,>>,<<,<,>,<=,>=,==,!= and <> (synonim for !=).[br]
+ The following table describes their meaning.[br]
+ [table]
+ [tr][td][b]Operator[/b][/td][td][b]Description[/b][/td][/tr]
+ [tr][td]a + b[/td][td]Arithmetic sum: valid only for numeric operands[/td][/tr]
+ [tr][td]a - b[/td][td]Arithmetic subtraction: valid only for numeric operands[/td][/tr]
+ [tr][td]a / b[/td][td]Arithmetic division: valid only for numeric operands[/td][/tr]
+ [tr][td]a * b[/td][td]Arithmetic multiplication: valid only for numeric operands[/td][/tr]
+ [tr][td]a % b[/td][td]Arithmetic modulus: valid only for numeric operands[/td][/tr]
+ [tr][td]a || b[/td][td]Logical or: valid only for boolean operands[/td][/tr]
+ [tr][td]a && b[/td][td]Logical and: valid only for boolean operands[/td][/tr]
+ [tr][td]a ^^ b[/td][td]Logical xor: valid only for boolean operands[/td][/tr]
+ [tr][td]a >> b[/td][td]Bitwise shift right: valid only for integer operands[/td][/tr]
+ [tr][td]a << b[/td][td]Bitwise shift left: valid only for integer operands[/td][/tr]
+ [tr][td]a | b[/td][td]Bitwise or: valid only for integer operands[/td][/tr]
+ [tr][td]a & b[/td][td]Bitwise and: valid only for integer operands[/td][/tr]
+ [tr][td]a ^ b[/td][td]Bitwise xor: valid only for integer operands[/td][/tr]
+ [tr][td]a > b[/td][td]Greater than: valid for numeric or string operands. Case sensitive[/td][/tr]
+ [tr][td]a < b[/td][td]Lower than: valid for numeric or string operands. Case sensitive[/td][/tr]
+ [tr][td]a >= b[/td][td]Greater or equal to: valid for numeric or string operands. Case sensitive[/td][/tr]
+ [tr][td]a <= b[/td][td]Lower or equal to: valid for numeric or string operands. Case sensitive[/td][/tr]
+ [tr][td]a != b[/td][td]Not equal to: valid for numeric or string operands. Case sensitive[/td][/tr]
+ [tr][td]a == b[/td][td]Equal to: valid for numeric or string operands. Case sensitive[/td][/tr]
+ [/table]
+ The expressions can contain integer, real or string constants and variable operands.[br]
+ The integer constants can be also specified as hexadecimal numbers by prefixing them by '0x'.[br]
+ The string constants should be enclosed in quotes.[br]
+ @examples:
+ [example]
+ echo $(10 + 5 * 100)
+ echo $(10 / 3)
+ echo $(10 / 3.0)
+ echo $(10.0 + 5 * 100)
+ echo $(145 & 2)
+ echo $("hello" > "ciao")
+ echo $(10 == "10")
+ %a = 100
+ %b = 50.3
+ %c = "test"
+ echo $(%a + %b)
+ echo $("%a%b" + 1)
+ echo $(%a + %b > %c)
+ echo $(-(10 + 20) * 3)
+ echo $(1 ^ 2)
+ echo $(1 ^ 1)
+ echo $(0xffff == 65535)
+ ...
+ [/example]
+ */
+
+
+
+
+KviKvsTreeNodeExpressionBinaryOperator * KviKvsParser::parseExpressionBinaryOperator()
+{
+ switch(KVSP_curCharUnicode)
+ {
+ case '=':
+ KVSP_skipChar;
+ if(KVSP_curCharUnicode == '=')
+ {
+ KVSP_skipChar;
+ return new KviKvsTreeNodeExpressionBinaryOperatorEqualTo(KVSP_curCharPointer);
+ } else {
+ error(KVSP_curCharPointer,__tr2qs("Unknown binary operator '=%q': did you mean '==' ?"),KVSP_curCharPointer);
+ }
+ break;
+ case '!':
+ KVSP_skipChar;
+ if(KVSP_curCharUnicode == '=')
+ {
+ KVSP_skipChar;
+ return new KviKvsTreeNodeExpressionBinaryOperatorNotEqualTo(KVSP_curCharPointer);
+ }
+ break;
+ case '+':
+ KVSP_skipChar;
+ return new KviKvsTreeNodeExpressionBinaryOperatorSum(KVSP_curCharPointer);
+ break;
+ case '-':
+ KVSP_skipChar;
+ return new KviKvsTreeNodeExpressionBinaryOperatorSubtraction(KVSP_curCharPointer);
+ break;
+ case '/':
+ KVSP_skipChar;
+ return new KviKvsTreeNodeExpressionBinaryOperatorDivision(KVSP_curCharPointer);
+ break;
+ case '%':
+ KVSP_skipChar;
+ return new KviKvsTreeNodeExpressionBinaryOperatorModulus(KVSP_curCharPointer);
+ break;
+ case '*':
+ KVSP_skipChar;
+ return new KviKvsTreeNodeExpressionBinaryOperatorMultiplication(KVSP_curCharPointer);
+ break;
+ case '&':
+ KVSP_skipChar;
+ if(KVSP_curCharUnicode == '&')
+ {
+ KVSP_skipChar;
+ return new KviKvsTreeNodeExpressionBinaryOperatorAnd(KVSP_curCharPointer);
+ }
+ return new KviKvsTreeNodeExpressionBinaryOperatorBitwiseAnd(KVSP_curCharPointer);
+ break;
+ case '|':
+ KVSP_skipChar;
+ if(KVSP_curCharUnicode == '|')
+ {
+ KVSP_skipChar;
+ return new KviKvsTreeNodeExpressionBinaryOperatorOr(KVSP_curCharPointer);
+ }
+ return new KviKvsTreeNodeExpressionBinaryOperatorBitwiseOr(KVSP_curCharPointer);
+ break;
+ case '^':
+ KVSP_skipChar;
+ if(KVSP_curCharUnicode == '^')
+ {
+ KVSP_skipChar;
+ return new KviKvsTreeNodeExpressionBinaryOperatorXor(KVSP_curCharPointer);
+ }
+ return new KviKvsTreeNodeExpressionBinaryOperatorBitwiseXor(KVSP_curCharPointer);
+ break;
+ case '>':
+ KVSP_skipChar;
+ switch(KVSP_curCharUnicode)
+ {
+ case '>':
+ KVSP_skipChar;
+ return new KviKvsTreeNodeExpressionBinaryOperatorShiftRight(KVSP_curCharPointer);
+ break;
+ case '=':
+ KVSP_skipChar;
+ return new KviKvsTreeNodeExpressionBinaryOperatorGreaterOrEqualTo(KVSP_curCharPointer);
+ break;
+ default:
+ return new KviKvsTreeNodeExpressionBinaryOperatorGreaterThan(KVSP_curCharPointer);
+ break;
+ }
+ break;
+ case '<':
+ KVSP_skipChar;
+ switch(KVSP_curCharUnicode)
+ {
+ case '>':
+ KVSP_skipChar;
+ return new KviKvsTreeNodeExpressionBinaryOperatorNotEqualTo(KVSP_curCharPointer);
+ break;
+ case '<':
+ KVSP_skipChar;
+ return new KviKvsTreeNodeExpressionBinaryOperatorShiftLeft(KVSP_curCharPointer);
+ break;
+ case '=':
+ KVSP_skipChar;
+ return new KviKvsTreeNodeExpressionBinaryOperatorLowerOrEqualTo(KVSP_curCharPointer);
+ break;
+ default:
+ return new KviKvsTreeNodeExpressionBinaryOperatorLowerThan(KVSP_curCharPointer);
+ break;
+ }
+ break;
+ }
+
+ error(KVSP_curCharPointer,__tr2qs("Unknown binary operator '%q'"),KVSP_curCharPointer);
+ return 0;
+}
+
+
+static unsigned char binary_operator_initial_char[256]=
+{
+ // 000 001 002 003 004 005 006 007 008 009 010 011 012 013 014 015
+ // NUL SOH STX ETX EOT ENQ ACK BEL BS HT LF VT FF CR SO SI
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+ // 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031
+ // DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+ // 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047
+ // ! " # $ % & ' ( ) * + , - . /
+ 0 ,1 ,0 ,0 ,0 ,1 ,1 ,0 ,0 ,0 ,1 ,1 ,0 ,1 ,0 ,1 ,
+ // 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063
+ // 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,1 ,1 ,1 ,0 ,
+ // 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079
+ // @ A B C D E F G H I J K L M N O
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+ // 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095
+ // P Q R S T U V W X Y Z [ \ ] ^ _
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,1 ,0 ,
+ // 096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111
+ // ` a b c d e f g h i j k l m n o
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+ // 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
+ // p q r s t u v w x y z { | } ~ 
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,1 ,0 ,0 ,0 ,
+ // 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
+ //
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+ // 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
+ //
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+ // 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
+ //
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+ // 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
+ //
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+ // 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
+ // � � � � � � � � � � � � � � � �
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+ // 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
+ // � � � � � � � � � � � � � � � �
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+ // 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
+ // � � � � � � � � � � � � � � � �
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+ // 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
+ // � � � � � � � �
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+};
+
+
+bool KviKvsParser::parseExpressionMightPointToOperator()
+{
+ if(KVSP_curCharUnicode == '%')
+ {
+ KVSP_skipChar;
+ if(KVSP_curCharIsLetter || (KVSP_curCharUnicode == '_'))
+ {
+ // a variable, probably
+ KVSP_backChar;
+ return false;
+ }
+ KVSP_backChar;
+ return true;
+ }
+ if(KVSP_curCharUnicode > 255)return false;
+ return binary_operator_initial_char[KVSP_curCharUnicode] != 0;
+}
+
+
+KviKvsTreeNodeExpression * KviKvsParser::parseExpressionOperand(char terminator)
+{
+ switch(KVSP_curCharUnicode)
+ {
+ case 0:
+ case '\r':
+ case '\n':
+ error(KVSP_curCharPointer,__tr2qs("Unexpected end of script in expression"));
+ return 0;
+ break;
+ case '(':
+ KVSP_skipChar;
+ skipSpaces();
+ return parseExpression(')'); // sub expression
+ break;
+ case '-':
+ {
+ KVSP_skipChar;
+ skipSpaces();
+ KviKvsTreeNodeExpression * d = parseExpressionOperand(terminator);
+ if(!d)return 0;
+ return new KviKvsTreeNodeExpressionUnaryOperatorNegate(d->location(),d);
+ }
+ break;
+ case '!':
+ {
+ KVSP_skipChar;
+ skipSpaces();
+ KviKvsTreeNodeExpression * d = parseExpressionOperand(terminator);
+ if(!d)return 0;
+ return new KviKvsTreeNodeExpressionUnaryOperatorLogicalNot(d->location(),d);
+ }
+ break;
+ case '~':
+ {
+ KVSP_skipChar;
+ skipSpaces();
+ KviKvsTreeNodeExpression * d = parseExpressionOperand(terminator);
+ if(!d)return 0;
+ return new KviKvsTreeNodeExpressionUnaryOperatorBitwiseNot(d->location(),d);
+ }
+ break;
+ default:
+ // anything else at this point is an operand core
+ return parseExpressionOperandCore(terminator);
+ break;
+ }
+
+ // not reached
+ KVSP_ASSERT(false);
+ return 0;
+}
+
+
+
+KviKvsTreeNodeExpression * KviKvsParser::parseExpressionOperandCore(char terminator)
+{
+ KviPointerList<KviKvsTreeNodeData> * pDataList = new KviPointerList<KviKvsTreeNodeData>;
+ pDataList->setAutoDelete(true);
+
+ static QString szStaticSingleSpace(" ");
+
+ const QChar * pOperandBegin = KVSP_curCharPointer;
+
+ bool bHaveVariable = false;
+
+ for(;;)
+ {
+ switch(KVSP_curCharUnicode)
+ {
+ case 0:
+ case '\r':
+ case '\n':
+ error(KVSP_curCharPointer,__tr2qs("Unexpected end of script in expression"));
+ delete pDataList;
+ return 0;
+ break;
+ case ' ':
+ case '\t':
+ skipSpaces();
+ if((KVSP_curCharUnicode == terminator) || parseExpressionMightPointToOperator())goto postprocess_operand;
+ // separate by single spaces
+ pDataList->append(new KviKvsTreeNodeConstantData(KVSP_curCharPointer,new KviKvsVariant(szStaticSingleSpace)));
+ break;
+ case '"':
+ {
+ // a string
+ bHaveVariable = true;
+ KviKvsTreeNodeData * d = parseStringParameter();
+ if(!d)
+ {
+ delete pDataList;
+ return 0;
+ }
+ pDataList->append(d);
+ }
+ break;
+ case '%':
+ case '$':
+ case '@':
+ {
+ bHaveVariable = true;
+ KviKvsTreeNodeData * d = parseParameterPercentOrDollar();
+ if(!d)
+ {
+ delete pDataList;
+ return 0;
+ }
+ pDataList->append(d);
+ }
+ break;
+ default:
+ // literal ?
+ if(KVSP_curCharIsLetterOrNumber || (KVSP_curCharUnicode == '.') || (KVSP_curCharUnicode == '_'))
+ {
+ const QChar * pBegin = KVSP_curCharPointer;
+ while(KVSP_curCharIsLetterOrNumber || (KVSP_curCharUnicode == '.') || (KVSP_curCharUnicode == '_'))KVSP_skipChar;
+ QString tmp(pBegin,KVSP_curCharPointer - pBegin);
+ bool bOk;
+ kvs_int_t iVal = tmp.toLong(&bOk);
+ if(bOk)
+ {
+ pDataList->append(new KviKvsTreeNodeConstantData(pBegin,new KviKvsVariant(iVal)));
+ } else {
+ // bOk is false
+ if(pBegin->unicode() == '0')
+ {
+ if(tmp.length() > 2)
+ {
+ if((tmp[1] == 'x') || (tmp[1] == 'X'))
+ {
+ // hexadecimal constant ?
+ QString hex = tmp.right(tmp.length() - 2);
+ iVal = hex.toLong(&bOk,16);
+ if(bOk)
+ {
+ pDataList->append(new KviKvsTreeNodeConstantData(pBegin,new KviKvsVariant(iVal)));
+ }
+ }
+ }
+ }
+ if(!bOk)
+ {
+ kvs_real_t dVal = tmp.toDouble(&bOk);
+ if(bOk)
+ {
+ pDataList->append(new KviKvsTreeNodeConstantData(pBegin,new KviKvsVariant(dVal)));
+ } else {
+ pDataList->append(new KviKvsTreeNodeConstantData(pBegin,new KviKvsVariant(tmp)));
+ }
+ }
+ }
+ } else {
+ error(KVSP_curCharPointer,__tr2qs("Unexpected character %q (unicode %h) in expression. If it meant to be a string use the quotes."),KVSP_curCharPointer,KVSP_curCharUnicode);
+ delete pDataList;
+ return 0;
+ }
+ break;
+ }
+
+ if((KVSP_curCharUnicode == terminator) || parseExpressionMightPointToOperator())break;
+ }
+
+postprocess_operand:
+
+ if(pDataList->count() == 0)
+ {
+ delete pDataList;
+ error(KVSP_curCharPointer,__tr2qs("Unexpected empty expression operand"));
+ return 0;
+ }
+
+ if(pDataList->count() > 1)
+ return new KviKvsTreeNodeExpressionVariableOperand(pOperandBegin,new KviKvsTreeNodeCompositeData(pOperandBegin,pDataList));
+
+ KviKvsTreeNodeData * pUniqueData = pDataList->first();
+
+ if(bHaveVariable)
+ {
+ pDataList->setAutoDelete(false);
+ delete pDataList;
+ return new KviKvsTreeNodeExpressionVariableOperand(pOperandBegin,pUniqueData);
+ }
+
+ // a single constant data element
+ KviKvsTreeNodeExpressionConstantOperand * op = new KviKvsTreeNodeExpressionConstantOperand(pOperandBegin,new KviKvsVariant(*(((KviKvsTreeNodeConstantData *)pUniqueData)->value())));
+ delete pDataList; // auto delete is true
+ return op;
+}
+
+
+KviKvsTreeNodeExpression * KviKvsParser::parseExpression(char terminator)
+{
+ // we're inside the expression now
+ skipSpaces();
+
+ if(KVSP_curCharUnicode == terminator)
+ {
+ // empty expression
+ // constant 0 ?
+ KVSP_skipChar;
+ return new KviKvsTreeNodeExpressionConstantOperand(KVSP_curCharPointer,new KviKvsVariant((kvs_int_t)0));
+ }
+
+ KviKvsTreeNodeExpression * left = parseExpressionOperand(terminator);
+ if(!left)return 0;
+ QString sz;
+ left->contextDescription(sz);
+
+ skipSpaces();
+
+ if(KVSP_curCharUnicode == terminator)
+ {
+ KVSP_skipChar;
+ return left;
+ }
+
+ // not a terminator... must be an operator (or an error , eventually)
+
+ KviKvsTreeNodeExpression * curTopOperator = parseExpressionBinaryOperator();
+ if(!curTopOperator)
+ {
+ delete left;
+ return 0; // error
+ }
+ curTopOperator->contextDescription(sz);
+
+ curTopOperator->setLeft(left);
+
+ // ok.. parse the right side
+
+ // Now curTopOperator has the left subtree (one node) set
+ // and it points to the TOP (=ROOT) node
+ // Evaluate the rest
+
+ KviKvsTreeNodeExpression * operand;
+ KviKvsTreeNodeExpression * incompleteOperator = curTopOperator;
+ KviKvsTreeNodeExpression * auxOperator;
+
+ for(;;)
+ {
+ skipSpaces();
+
+ operand = parseExpressionOperand(terminator);
+ if(!operand)
+ {
+ delete curTopOperator;
+ return 0;
+ }
+ operand->contextDescription(sz);
+
+ skipSpaces();
+
+ if(KVSP_curCharUnicode == terminator)
+ {
+ KVSP_skipChar;
+ incompleteOperator->setRight(operand);
+ return curTopOperator;
+ }
+
+ auxOperator = parseExpressionBinaryOperator();
+ if(!auxOperator)
+ {
+ delete curTopOperator;
+ delete operand;
+ return 0;
+ }
+
+ auxOperator->contextDescription(sz);
+
+
+ //now compare operators...
+ if(incompleteOperator->precedence() > auxOperator->precedence())
+ {
+ // This in fact means that incomplete has LOWER precedence than
+ // aux and thus aux should be done first.
+ incompleteOperator->setRight(auxOperator);
+ auxOperator->setLeft(operand);
+ } else {
+ // incomplete has GREATER precedence than aux and thus aux should be done first
+ incompleteOperator->setRight(operand); //right tree complete
+ // go up until we find an operator with lower precedence than auxOperator (>=)
+ KviKvsTreeNodeExpression * tempOperator = incompleteOperator->parentWithPrecedenceLowerThan(auxOperator->precedence());
+ if(tempOperator == 0)
+ {
+ auxOperator->setLeft(curTopOperator);
+ curTopOperator = auxOperator;
+ } else {
+ KVSP_ASSERT(tempOperator->right());
+ auxOperator->setLeft(tempOperator->right());
+ tempOperator->setRight(auxOperator);
+ }
+ }
+ incompleteOperator = auxOperator;
+ KVSP_ASSERT(incompleteOperator->right() == 0);
+ }
+
+ KVSP_ASSERT(false);
+
+ return 0; //newer here
+
+/*
+
+
+ KviKvsTreeNodeExpression * right = parseExpression(terminator);
+ if(!right)
+ {
+ delete op;
+ return 0;
+ }
+
+ // left * a + b
+
+ // *
+ // left +
+ // a b
+
+*/
+/*
+ // now.. the left side is a single operand for sure
+ // the right side might be a single operand or a sequence of operations
+ if(right->isOperator())
+ {
+ // if the operator has lower precedence than op then
+ if(right->precedence() < op->precedence())
+ {
+ right->attachHighPrecedenceOperator(op);
+ return right;
+ }
+ }
+*/
+/*
+ // a single operand or a greater precedence operator
+ op->setRight(right);
+
+ return op;
+ */
+}
+
diff --git a/src/kvirc/kvs/kvi_kvs_parser_lside.cpp b/src/kvirc/kvs/kvi_kvs_parser_lside.cpp
new file mode 100644
index 00000000..c9869567
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_parser_lside.cpp
@@ -0,0 +1,1196 @@
+//=============================================================================
+//
+// File : kvi_kvs_parser_lside.cpp
+// Creation date : Thu 03 Nov 2003 13.11 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+
+#include "kvi_kvs_parser.h"
+
+#include "kvi_kvs_treenode.h"
+
+#include "kvi_kvs_report.h"
+#include "kvi_kvs_kernel.h"
+
+#include "kvi_kvs_parser_macros.h"
+
+#include "kvi_locale.h"
+
+
+/*
+ @doc: operators
+ @title:
+ Operators
+ @keyterms:
+ operator,operators,assignment,assign
+ @type:
+ language
+ @short:
+ Variable operators , assignments & co.
+ @body:
+ Operator constructs are commands just like the other ones.
+ All the operators work on local or global variables and dictionaries.[br]
+ The generic operator syntax is:[br]
+ [br]
+ [b]<left_operand> <operator> [right_operand][/b][br]
+ [br]
+ where <left_operand> and [right_operand] depend on the <operator>.[br]
+ Some operators have no [right_operand] and these are called [b]unary operators[/b]:
+ they operate directly on <left_operand>.[br]
+
+ [br]
+ [big]= (Assignment)[/big][br]
+ [br]
+
+ The assignment is the "plainest" of the binary operators: it works just like in any other programming language.[br]
+ [br]
+ If the <left_operand> is a variable, then the <right_operand> is assigned to it;
+ if the variable doesn't exists yet , it is created.[br]
+ If <right_operand> evaluates to an empty value then the variable is unset.[br]
+ [example]
+ [comment]# Assigning a constant to the global variable %Tmp[/comment]
+ %Tmp = 1
+ [comment]# Assigning a string constant to the global variable %Tmp[/comment]
+ %Tmp = some string
+ [comment]# Assigning a string constant to the local variable %tmp[/comment]
+ %tmp = "some string with whitespace &nbsp; &nbsp; &nbsp; &nbsp; preserved"
+ [comment]# Assigning a variable to another variable copies its contents[/comment]
+ %tmp = %somevariable
+ [comment]# Assigning a variable string to the global variable %Z[/comment]
+ %Z = my eyes are %color
+ [comment]# Assigning a variable string (with a function call inside) to the local variable %x[/comment]
+ %x = the system os is [fnc]$system.osname[/fnc]
+ [comment]# Assigning an empty string to the local variable %y unsets %y[/comment]
+ %y =
+ [comment]# This is equivalent to the above[/comment]
+ %y = ""
+ [comment]# This is equivalent too, if $function evalutates to an empty string[/comment]
+ %y = $function()
+ [/example]
+ [br]
+ If the <left_operand> is a dictionary/array entry, then the <right_operand> is assigned to it;
+ if the dictionary/array entry doesn't exist (or the whole dictionary/array doesn't exists) it is created.[br]
+ If <right_operand> evaluates to an empty value then the dictionary/array entry (and eventually the whole
+ dictionary/array, if there are no other entries) is unset.[br]
+ [example]
+ [comment]# Assigning a variable string to a global dictionary entry[/comment]
+ %Dict[key] = [fnc]$system.osname[/fnc]\ian
+ [comment]# Unsetting a local dictionary entry[/comment]
+ %mydict[23] = ""
+ [/example]
+ [br]
+ If the <left_operand> is an array reference then the semantics depend on the <right_operand> type.
+ If <right_operand> is an array reference then its contents are copied to the <left_operand>.[br]
+ If <right_operand> is a dictionary (keys) reference then its values are copied to to <left_operand>.[br]
+ If <right_operand> is a scalar then the value is assigned to every entry of <left_operand>.[br]
+ This is an easy way of unsetting a whole array: just assign an empty string.[br]
+ If the <left_operand> is a dictionary reference then the semantics depend on the <right_operand> type.
+ If <right_operand> is a dictionary reference then its contents are copied to the <left_operand>.[br]
+ If <right_operand> is an array reference then its contents are copied to to <left_operand> using
+ the array indexes as keys.[br]
+ If <right_operand> is a dictionary key reference then the keys are copied to the <left_operand>
+ using numeric indexes starting from 0 as keys.[br]
+ If <right_operand> is a scalar then the value is assigned to every key of <left_operand>.[br]
+ This is an easy way of unsetting a whole dictionary: just assign an empty string to all its keys.[br]
+ (If you play with huge dictionaries/arrays it might be a good idea to unset them when no longer needed)
+ [example]
+ [comment]# Assigning a dictionary to another: %mydict[] becomes a copy of %anotherdict[][/comment]
+ %mydict[] = %anotherdict[]
+ [comment]# %mydict[] gets the values of the dict returned by $features[/comment]
+ %mydict[] = [fnc]$features[/fnc]
+ [comment]# Assigning a string to ALL the keys of %mydict[/comment]
+ %mydict[] = "some default value"
+ [comment]# Unsetting a whole dictionary[/comment]
+ %mydict[] =
+ %AnotherGlobalDict[] = ""
+ [/example]
+
+
+ [br]
+ [big]=~ (Binding operator)[/big][br]
+ [br]
+
+ This operator is a really ugly, poor and clueless attempt to reach at least 1% of the
+ power of the perl =~ operator :D[br]
+ It allows some complex string operations to be performed efficently by operating directly
+ on the left operand (in fact this is a lot faster in KVIrc since at least one step of parsing is skipped).[br]
+ Its basic syntax is:[br]
+ [b]<left_operand> =~ <operation>[parameters][/b][br]
+ Where <operation> may be one of 't','s' and parameters depend on it.[br]
+ <left_operand> is the target of the <operation>.[br]
+ If <left_operand> is an array or dictionary, the <operation> is executed on each item they contain.[br]
+ Operation 't' is the transliteration.[br]
+ The complete syntax with parameters is:[br]
+ [b]<left_operand> =~ t/<search characters>/<replacement characters>/[/b][br]
+ where <search characters> is a string of characters that are replaced with the corresponding
+ characters in <replacement characters>.[br]
+ This operation can be also named 'y' or 'tr' (to preserve some compatibility with other languages).[br]
+ [example]
+ %A=This is a test string
+ echo %A
+ %A=~ tr/abcdefghi/ABCDEFGHI/
+ echo %A
+ [/example]
+ Operation 's' is the substitution.[br]
+ The complete syntax with parameters is:[br]
+ [b]<left_operand> =~ s/<search pattern>/<replacement pattern>/[flags][/b][br]
+ where <search pattern> is an extended regular expression to be matched in the <left_operand>
+ and <replacement string> is a special pattern that will replace any occurence found.[br]
+ <search pattern> may contain parentheses to capture parts of the matched text.
+ <replacement string> can contain the escape sequences \\N where N is a number between 1 and 9
+ to be replaced by the captured text.[br]
+ (We use \\N because KVIrc will first unquote the string when parsing...)[br]
+ \\0 is a special escape that will be replaced by the entire match (is always valid!).[br]
+ WARNING: the "capture-text" feature is not available if KVIrc has been compiled
+ with qt older than 3.0.0. You can find out if the feature is available by
+ looking for the string "Qt3" in the array returned by [fnc]$features[/fnc].[br]
+ [flags] may be a combination of the letters 'g','i' and 'w'.[br]
+ 'g' causes the search to be global and not stop after the first occurence of <search pattern>.[br]
+ 'i' causes the search to be case insensitive.[br]
+ 'w' causes the search pattern to be interpreted as a simple wildcard regular expression.[br]
+ 'm' causes the matching to be "minimal" instead of "greedy" (default). Greedy matches
+ find the longest possible match in the string while minimal (non-greedy) matches the shortest possible.[br]
+ [example]
+ %A=This is a test string
+ echo %A
+ %A=~ s/([a-z])i([a-z])/\\1I\\2/
+ echo %A
+ %A=~ s/([a-z])i([a-z])/\\1@\\2/gi
+ echo %A
+ [/example]
+
+ [br]
+ [big]X= (Arithmetic Self-operators)[/big][br]
+ [br]
+
+ The general syntax is:[br]
+ [b]<left_operand> <operation> <right_operand>[/b][br]
+ Where <left_operand> and <right_operand> must evaluate to numbers.[br]
+ All these operators perform the operation on <left_operand> and <right_operand> and then
+ store the result in <left_operand> (which therefore must be a variable, an array entry or a dictionary entry).[br]
+ <operation> may be one of:[br]
+ += : sums the <right_operand> to <left_operand>[br]
+ -= : subtracts <right_operand> from <left_operand>[br]
+ *= : multiplies <left_operand> by <right_operand>[br]
+ %= : calculates <left_operand> modulus <right_operand>[br]
+ |= : calculates <left_operand> bitwise-or <right_operand>[br]
+ &= : calculates <left_operand> bitwise-and <right_operand>[br]
+ /= : divides <left_operand> by <right_operand>[br]
+
+ [br]
+ [big]++ and -- (Increment and Decrement)[/big][br]
+ [br]
+
+ These two operators work only on numeric operands.[br]
+ The general syntax is:[br]
+ [b]<left_operand> <operator>[/b][br]
+ There is no <right_operand>.[br]
+ ++ increments <left_operand> by one, -- decrements <left_operand> by one.[br]
+ These are equivalent to += 1 and -= 1.[br]
+
+ [br]
+ [big].= , << , <+ , <, (String concatenation operators)[/big][br]
+ [br]
+
+ All these operators work also on whole arrays and dictionaries.[br]
+ Operator [b].=[/b] : APPENDS the <right_operand> to the <left_operand>[br]
+ Operator [b]<+[/b] is a synonim for .= (backward compatibility)[br]
+ Operator [b]<<[/b] : appends <right_operand> to <left_operand>
+ separating the two strings by a single space if and only if <left_operand> and <right_operand>
+ are non-empty.[br]
+ Operator [b]<,[/b] : is similar to '<<' ; appends , separating with a single ',' with the same condition.[br]
+
+ @examples:
+ First set the variable %var
+ [example]
+ %var = Ciao ciao
+ [/example]
+ Then append a nickname...
+ [example]
+ %var << Pragma
+ [/example]
+ %var now contains "Ciao ciao Pragma"[br]
+ Append a '!' character
+ [example]
+ %var <+ !
+ [/example]
+ %var now contains "Ciao ciao Pragma!"
+ Now reset it.
+ [example]
+ %var =
+ [/example]
+ Now %var is unset.[br]
+ Reset it with a comma separated list of items
+ [example]
+ %var = Pragma,Diabl0,Arter|o
+ %var <, MalboroLi
+ [/example]
+ %var now contains "Pragma,Diabl0,Arter|o,MalboroLi"[br]
+ [br]
+ Now a longer example.
+ [example]
+ %var = l
+ [cmd]echo[/cmd] It's name starts with the letter %var!
+ %var &lt;+ inux
+ [cmd]echo[/cmd] Yes , it is %var!
+ %var &lt;&lt; OS
+ [cmd]echo[/cmd] Use %var!
+ %var &lt;, Mac OS
+ [cmd]echo[/cmd] There are two items in this list : %var
+ %var = [fnc]$strlen[/fnc](%var)
+ [cmd]echo[/cmd] And it is %var characters long (including the comma)
+ %var--
+ [cmd]echo[/cmd] Excluding the comma : %var
+ %var+=%var
+ [cmd]echo[/cmd] Now it is doubled : %var
+ %var =
+ [cmd]echo[/cmd] Now the var is unset (empty): (%var) !
+ [/example]
+*/
+
+
+KviKvsTreeNodeData * KviKvsParser::parseOperationRightSide(bool bPreferNumeric)
+{
+ KviPointerList<KviKvsTreeNodeData> * l = new KviPointerList<KviKvsTreeNodeData>();
+ l->setAutoDelete(true);
+
+ const QChar * pBegin = KVSP_curCharPointer;
+
+ for(;;)
+ {
+ switch(KVSP_curCharUnicode)
+ {
+ case 0:
+ goto end_of_the_param;
+ break;
+ case '\n':
+ case '\r':
+ case ';':
+ KVSP_skipChar;
+ goto end_of_the_param;
+ break;
+ case ' ':
+ case '\t':
+ skipSpaces();
+ if(KVSP_curCharIsEndOfCommand)
+ {
+ goto end_of_the_param;
+ } else {
+ // separate by single spaces
+ bPreferNumeric = false; // this can't be a number
+ l->append(new KviKvsTreeNodeConstantData(KVSP_curCharPointer,new KviKvsVariant(QString(" "))));
+ }
+ break;
+ default:
+ // anything else is a parameter
+ KviKvsTreeNodeData * p = parseCommandParameter(bPreferNumeric);
+ if(!p)
+ {
+ // this is an error
+ delete l;
+ return 0;
+ }
+ l->append(p);
+ break;
+ }
+ }
+
+end_of_the_param:
+ if(l->count() > 1)
+ {
+ // complex parameter needed
+ return new KviKvsTreeNodeCompositeData(pBegin,l);
+ } else {
+ if(l->count() > 0)
+ {
+ // a single parameter in the list
+ l->setAutoDelete(false);
+ KviKvsTreeNodeData * p = l->first();
+ delete l;
+ return p;
+ } else {
+ // empty (this should NEVER happen anyway)
+ delete l;
+ return new KviKvsTreeNodeConstantData(pBegin,new KviKvsVariant(QString("")));
+ }
+ }
+ // never reached
+ return 0;
+}
+
+/*
+ @doc: assignment
+ @title:
+ Assignment operation
+ @keyterms:
+ assignment
+ @type:
+ language
+ @short:
+ Assignment operation
+ @body:
+ The assignment is the "plainest" of the operators: it works just like in any other programming language.[br]
+ The syntax is:[br]
+ [br]
+ [b]<target> = <source>[/b]
+ [br]
+ <target> must be a variable, <source> can be any parameter.[br]
+ If the <target> variable doesn't exist, it is created.
+ If it already exists, it is eventually converted to the type of <souce> (scalar, hash or array).[br]
+ If <source> evaluates to an empty value then the <target> variable is unset.[br]
+ [example]
+ [comment]# Assigning a constant to the variable %Tmp[/comment]
+ %Tmp = 1
+ [cmd]echo[/cmd] %Tmp
+ [comment]# Assigning a string constant to the variable %Tmp[/comment]
+ %Tmp = some string
+ [cmd]echo[/cmd] %Tmp
+ [comment]# Assigning a string constant to the variable %Tmp[/comment]
+ %Tmp = "some string with whitespace &nbsp; &nbsp; &nbsp; &nbsp; preserved"
+ [cmd]echo[/cmd] %Tmp
+ [comment]# Assigning a variable to another variable copies its contents[/comment]
+ %Someothervariable = "Contents"
+ %Tmp = %Someothervariable
+ [cmd]echo[/cmd] %Tmp
+ [comment]# Assigning a variable string to the variable %z[/comment]
+ %color = blue
+ %z = my eyes are %color
+ [cmd]echo[/cmd] %z
+ [comment]# Assigning a variable string (with a function call inside) to the variable %x[/comment]
+ %x = the system os is [fnc]$system.osname[/fnc]
+ [cmd]echo[/cmd] %x
+ [comment]# Assigning an empty string to the local variable %y unsets %y[/comment]
+ %x =
+ [cmd]echo[/cmd] %y
+ [comment]# This is equivalent to the above[/comment]
+ %y = ""
+ [comment]# This is equivalent too, if $function evalutates to an empty string[/comment]
+ %y = $function()
+ [comment]# Assigning a variable string to a hash entry[/comment]
+ %Dict{key} = [fnc]$system.osname[/fnc]\ian
+ [comment]# Unsetting an array entry[/comment]
+ %mydict[23] = ""
+ [comment]# Assigning a hash to another: %mydict[] becomes a copy of %anotherdict[][/comment]
+ %anotherdict{"The key"} = "Some dummy value"
+ %mydict = %anotherdict
+ [cmd]echo[/cmd]%mydict{"The key"}
+ [comment]# This will convert %mydict to be a scalar variable (deleting all the %mydict contents!)[/comment]
+ %mydict = "some default value"
+ [comment]# Unsetting a whole hash[/comment]
+ %anotherdict =
+ [/example]
+ [/p]
+*/
+
+
+/*
+ @doc: incrementdecrement
+ @title:
+ Increment and decrement operations
+ @keyterms:
+ increment, decrement
+ @type:
+ language
+ @short:
+ Increment and decrement operations
+ @body:
+ These two operators work only on numeric operands.[br]
+ The syntax is:[br]
+ [br]
+ [b]<target>++[/b][br]
+ [b]<target>--[/b][br]
+ [br]
+ ++ increments <target> by one, -- decrements <target> by one.[br]
+ These are equivalent to += 1 and -= 1.[br]
+ <target> must be an existing variable and contain an integer value.[br]
+ If <target> contains a real value then the real is truncated to the nearest
+ integer and then incremented or decremented.[br]
+ @examples:
+ [example]
+ %a=10
+ [cmd]echo[/cmd] "Incrementing"
+ [cmd]while[/cmd](%a < 20)
+ {
+ [cmd]echo[/cmd] %a
+ [b]%a++[/b]
+ }
+ [cmd]echo[/cmd] "Decrementing"
+ [cmd]while[/cmd](%a > 10)
+ {
+ [cmd]echo[/cmd] %a
+ [b]%a--[/b]
+ }
+ [cmd]echo[/cmd] "Testing for loop"
+ [cmd]for[/cmd](%a=0;%a < 10;[b]%a++[/b])
+ {
+ [cmd]echo[/cmd] %a
+ }
+ [example]
+ @seealso:
+ [doc:operators]Operators[/doc]
+*/
+
+
+/*
+ @doc: selfarithmetic
+ @title:
+ Arithmetic self-operators
+ @type:
+ language
+ @short:
+ Arithmetic self-operators
+ @body:
+ These operators work only on numeric operands.[br]
+ The syntax is:[br]
+ [br]
+ [b]<target> += <right_operand>[/b][br]
+ [b]<target> -= <right_operand>[/b][br]
+ [b]<target> *= <right_operand>[/b][br]
+ [b]<target> /= <right_operand>[/b][br]
+ [b]<target> %= <right_operand>[/b][br]
+ [br]
+ <target> must be an existing variable and contain a numeric value.
+ <right_operand> must evaluate to a numeric value.
+ Note that if you want <right_operand> to be a result of an expression, you must
+ enclose it in the $(*) expression evaluation call.[br]
+ Operator += sums the <right_operand> value to the <target> value and stores the result in <target>.[br]
+ Operator -= subtracts <right_operand> from <target> and stores the result in <target>.[br]
+ Operator *= multiplies <target> by <right_operand> and stores the result in <target>.[br]
+ Operator /= divides <target> by <right_operand> and stores the result in <target>.[br]
+ Operator %= computes <target> modulus <right_operand> and stores the result in <target>.[br]
+ The division and modulus operators fail with an error if <right_operand> is 0.[br]
+ If both <target> and <right_operand> are integer values then the results of the division
+ and modulus are integers (truncated for the division).[br]
+ If <target> or <right_operand> or both are floating point values then the result is a floating point value.[br]
+ @examples:
+ [example]
+ %a=10
+ [cmd]echo[/cmd] %a
+ %a+=20
+ [cmd]echo[/cmd] %a
+ %a-=$(%a - 1)
+ [cmd]echo[/cmd] %a
+ %a *= 10
+ [cmd]echo[/cmd] %a
+ %a /= 21
+ [cmd]echo[/cmd] %a
+ %a *= 20
+ [cmd]echo[/cmd] %a
+ %a /= 21.0
+ [cmd]echo[/cmd] %a
+ %b = 10.0
+ %a %= %b
+ [cmd]echo[/cmd] %a
+ %a = 10
+ %b = 3
+ [comment]# nice trick[/comment]
+ %a /= %b.0
+ [cmd]echo[/cmd] %a
+ [example]
+ @seealso:
+ [doc:operators]Operators[/doc]
+*/
+
+
+/*
+ @doc: selfbitwise
+ @title:
+ Bitwise self-operators
+ @type:
+ language
+ @short:
+ Bitwise self-operators
+ @body:
+ These operators work only on integer operands.[br]
+ The syntax is:[br]
+ [br]
+ [b]<target> |= <right_operand>[/b][br]
+ [b]<target> &= <right_operand>[/b][br]
+ [b]<target> ^= <right_operand>[/b][br]
+ [b]<target> >>= <right_operand>[/b][br]
+ [b]<target> <<= <right_operand>[/b][br]
+ [br]
+ <target> must be an existing variable and contain a numeric value.
+ <right_operand> must evaluate to a numeric value.
+ If <target> or <right_operand> are floating point values then they are truncated
+ and converted to integers.[br]
+ Note that if you want <right_operand> to be a result of an expression, you must
+ enclose it in the $(*) expression evaluation call.[br]
+ Operator |= computes <target> bitwise-or <right_operand> and stores the result in <target>.[br]
+ Operator &= computes <target> bitwise-and <right_operand> and stores the result in <target>.[br]
+ Operator ^= computes <target> bitwise-xor <right_operand> and stores the result in <target>.[br]
+ Operator >>= shifts <target> <right_operand> bits to the right and stores the result int <target>.[br]
+ Operator <<= shifts <target> <right_operand> bits to the left and stores the result int <target>.[br]
+ Note that "!=" is not available. You must use %a = $(!%b) to implement it.[br]
+ For operators >>= and <<= <right_operand> must be a positive integer.[br]
+ @examples:
+ [example]
+ %a = 1
+ [cmd]echo[/cmd] %a
+ %a |= 2
+ [cmd]echo[/cmd] %a
+ %a &= 2
+ [cmd]echo[/cmd] %a
+ %a ^= 1
+ [cmd]echo[/cmd] %a
+ %a >>= 2
+ [cmd]echo[/cmd] %a
+ %a <<= 1
+ [cmd]echo[/cmd] %a
+ [example]
+ @seealso:
+ [doc:operators]Operators[/doc]
+*/
+
+
+/*
+ @doc: stringconcatenation
+ @title:
+ String concatenation operators
+ @type:
+ language
+ @short:
+ String concatenation operators
+ @body:
+ These operators concatenate strings.
+ The syntax is:[br]
+ [br]
+ [b]<target> .= <right_operand>[/b][br]
+ [b]<target> << <right_operand>[/b][br]
+ [b]<target> <, <right_operand>[/b][br]
+ [br]
+ Operator .= appends <right_operand> to <target>.
+ Operator << appends a space followed by <right_operand> to <target> if <target> is non empty,
+ otherwise sets <target> to <right_operand>.
+ Operator <, is similar to << but uses a comma to separate the two variable contents.
+ The last two operators are useful in creating space-separated or comma-separated lists.
+ @examples:
+ [example]
+ %a = ""
+ %a << free
+ [cmd]echo[/cmd] %a
+ %a .= bsd
+ [cmd]echo[/cmd] %a
+ %a << rox
+ [cmd]echo[/cmd] %a
+ %a <, but linux is better!
+ [cmd]echo[/cmd] %a
+ [example]
+ @seealso:
+ [doc:operators]Operators[/doc]
+*/
+
+
+/*
+ @doc: arrayconcatenation
+ @title:
+ Array concatenation operator
+ @type:
+ language
+ @short:
+ Array concatenation operator
+ @body:
+ This operator concatenates arrays
+ The syntax is:[br]
+ [br]
+ [b]<target> <+ <right_operand>[/b][br]
+ [br]
+ If <target> is not an array, it is converted to one first.
+ After that, if <right_operand> is a scalar then it is appended
+ to the end of the <target> array. If <right_operand> is an array
+ then all of its items are appended to the end of the <target> array.
+ If <right_operand> is a hash then all of its value items
+ are appended to the end of the <target> array.
+ @seealso:
+ [doc:operators]Operators[/doc]
+*/
+
+
+
+/*
+ @doc: binding
+ @title:
+ Binding operator
+ @type:
+ language
+ @short:
+ Binding operator
+ @body:
+ This operator is a really ugly, poor and clueless attempt to reach at least 1% of the
+ power of the perl =~ operator :D[br]
+ It allows some complex string operations to be performed efficently by operating directly
+ on the left operand (in fact this is a lot faster in KVIrc since at least one step of parsing is skipped).[br]
+ Its basic syntax is:[br]
+ [b]<left_operand> =~ <operation>[parameters][/b][br]
+ Where <operation> may be one of 't','s' and parameters depend on it.[br]
+ <left_operand> is the target of the <operation>.[br]
+ If <left_operand> is an array or dictionary, the <operation> is executed on each item they contain.[br]
+ Operation 't' is the transliteration.[br]
+ The complete syntax with parameters is:[br]
+ [b]<left_operand> =~ t/<search characters>/<replacement characters>/[/b][br]
+ where <search characters> is a string of characters that are replaced with the corresponding
+ characters in <replacement characters>.[br]
+ This operation can be also named 'y' or 'tr' (to preserve some compatibility with other languages).[br]
+ [example]
+ %A=This is a test string
+ echo %A
+ %A=~ tr/abcdefghi/ABCDEFGHI/
+ echo %A
+ [/example]
+ Operation 's' is the substitution.[br]
+ The complete syntax with parameters is:[br]
+ [b]<left_operand> =~ s/<search pattern>/<replacement pattern>/[flags][/b][br]
+ where <search pattern> is an extended regular expression to be matched in the <left_operand>
+ and <replacement string> is a special pattern that will replace any occurence found.[br]
+ <search pattern> may contain parentheses to capture parts of the matched text.
+ <replacement string> can contain the escape sequences \\N where N is a number between 1 and 9
+ to be replaced by the captured text.[br]
+ (We use \\N because KVIrc will first unquote the string when parsing...)[br]
+ \\0 is a special escape that will be replaced by the entire match (is always valid!).[br]
+ [flags] may be a combination of the letters 'g','i' and 'w'.[br]
+ 'g' causes the search to be global and not stop after the first occurence of <search pattern>.[br]
+ 'i' causes the search to be case insensitive.[br]
+ 'w' causes the search pattern to be interpreted as a simple wildcard regular expression.[br]
+ [example]
+ %A=This is a test string
+ echo %A
+ %A=~ s/([a-z])i([a-z])/\\1I\\2/
+ echo %A
+ %A=~ s/([a-z])i([a-z])/\\1@\\2/gi
+ echo %A
+ [/example]
+ @examples:
+ [example]
+ %a = ""
+ %a << free
+ [cmd]echo[/cmd] %a
+ %a .= bsd
+ [cmd]echo[/cmd] %a
+ %a << rox
+ [cmd]echo[/cmd] %a
+ %a <, but linux is better!
+ [cmd]echo[/cmd] %a
+ [example]
+ @seealso:
+ [doc:operators]Operators[/doc]
+*/
+
+
+
+/*
+ @doc: operators
+ @title:
+ Operators
+ @keyterms:
+ operator,operators,assignment
+ @type:
+ language
+ @short:
+ Variable operators , assignments & co.
+ @body:
+ [p]
+ Operator constructs are commands just like the other ones.
+ All the operators work on local or global variables.[br]
+ The generic operator syntax is:[br]
+ [br]
+ &nbsp; &nbsp; &nbsp; &nbsp; [b]<left_operand> <operator> [right_operand][/b][br]
+ [br]
+ where <left_operand> is a variable and [right_operand] is a variable , a constant or a complex expression.[br]
+ Some operators do not use [right_operand] and do their job directly on <left_operand>[br]
+ [/p]
+
+ [table]
+ [tr][td]Operator[/td][td]document[/td][/td]
+ [tr][td]=[/td][td][doc:assignment]assignment operator[/doc][/td][/tr]
+ [tr][td]++[/td][td][doc:incrementdecrement]Increment and decrement operators[/doc][/td][/tr]
+ [tr][td]--[/td][td][doc:incrementdecrement]Increment and decrement operators[/doc][/td][/tr]
+ [tr][td]+=[/td][td][doc:selfarithmetic]Arithmetic self-operators[/doc][/td][/tr]
+ [tr][td]-=[/td][td][doc:selfarithmetic]Arithmetic self-operators[/doc][/td][/tr]
+ [tr][td]*=[/td][td][doc:selfarithmetic]Arithmetic self-operators[/doc][/td][/tr]
+ [tr][td]/=[/td][td][doc:selfarithmetic]Arithmetic self-operators[/doc][/td][/tr]
+ [tr][td]%=[/td][td][doc:selfarithmetic]Arithmetic self-operators[/doc][/td][/tr]
+ [tr][td]|=[/td][td][doc:selfbitwise]Bitwise self-operators[/doc][/td][/tr]
+ [tr][td]&=[/td][td][doc:selfbitwise]Bitwise self-operators[/doc][/td][/tr]
+ [tr][td]^=[/td][td][doc:selfbitwise]Bitwise self-operators[/doc][/td][/tr]
+ [tr][td]<<=[/td][td][doc:selfbitwise]Bitwise self-operators[/doc][/td][/tr]
+ [tr][td]>>=[/td][td][doc:selfbitwise]Bitwise self-operators[/doc][/td][/tr]
+ [tr][td].=[/td][td][doc:stringconcatenation]String concatenation operators[/doc][/td][/tr]
+ [tr][td]<<[/td][td][doc:stringconcatenation]String concatenation operators[/doc][/td][/tr]
+ [tr][td]<,[/td][td][doc:stringconcatenation]String concatenation operators[/doc][/td][/tr]
+ [tr][td]<+[/td][td][doc:arrayconcatenation]Array concatenation[/doc][/td][/tr]
+ [tr][td]=~[/td][td][doc:binding]Binding operator[/doc][/td][/tr]
+ [/table]
+ */
+
+KviKvsTreeNodeData * KviKvsParser::parseBindingOperationParameter()
+{
+ KviPointerList<KviKvsTreeNodeData> * l = new KviPointerList<KviKvsTreeNodeData>;
+ l->setAutoDelete(true);
+
+ const QChar * pBegin = KVSP_curCharPointer;
+
+ for(;;)
+ {
+ switch(KVSP_curCharUnicode)
+ {
+ case 0:
+ case '/':
+ case '\n':
+ case '\r':
+ // not a part of a parameter
+ goto end_of_function_parameter;
+ break;
+ case '$':
+ case '%':
+ {
+ // this may be a data reference
+ KviKvsTreeNodeData * p = parseParameterPercentOrDollar();
+ if(!p)
+ {
+ // this is an error
+ delete l;
+ return 0;
+ }
+ l->append(p);
+ }
+ break;
+ case '"':
+ {
+ // this is a string
+ KviKvsTreeNodeData * p = parseStringParameter();
+ if(!p)
+ {
+ // this is an error
+ delete l;
+ return 0;
+ }
+ l->append(p);
+ }
+ break;
+ default:
+ {
+ // anything else is a literal
+ l->append(parseBindingOperationLiteralParameter());
+ }
+ break;
+ }
+ }
+end_of_function_parameter:
+ if(l->count() > 1)
+ {
+ // complex parameter needed
+ return new KviKvsTreeNodeCompositeData(pBegin,l);
+ } else {
+ // a single parameter in the list or empty list at all
+ l->setAutoDelete(false);
+ KviKvsTreeNodeData * p = l->first();
+ delete l;
+ if(!p)p = new KviKvsTreeNodeConstantData(KVSP_curCharPointer,new KviKvsVariant(QString("")));
+ return p;
+ }
+ // never reached
+ return 0;
+}
+
+
+
+KviKvsTreeNodeOperation * KviKvsParser::parseBindingOperation()
+{
+ // t or tr or y
+ // s
+ const QChar * pBegin = KVSP_curCharPointer;
+
+ while(KVSP_curCharIsLetter)KVSP_skipChar;
+
+ QString szOp = QString(pBegin,KVSP_curCharPointer - pBegin).lower();
+
+ skipSpaces();
+
+ if(KVSP_curCharUnicode != '/')
+ {
+ error(KVSP_curCharPointer,__tr2qs("Found character '%q' (unicode %x) where a slash '/' was expected"),KVSP_curCharPointer,KVSP_curCharUnicode);
+ return 0;
+ }
+
+ KVSP_skipChar;
+
+ KviKvsTreeNodeData * pFirst = parseBindingOperationParameter();
+ if(!pFirst)return 0;
+
+ if(KVSP_curCharIsEndOfCommand)
+ {
+ error(KVSP_curCharPointer,__tr2qs("Unexpected end of command in binding operation, at least two slashes are missing"));
+ delete pFirst;
+ return 0;
+ }
+
+ if(KVSP_curCharUnicode != '/')
+ {
+ error(KVSP_curCharPointer,__tr2qs("Found character '%q' (unicode %x) where a slash '/' was expected"),KVSP_curCharPointer,KVSP_curCharUnicode);
+ delete pFirst;
+ return 0;
+ }
+
+ KVSP_skipChar;
+
+ KviKvsTreeNodeData * pSecond = parseBindingOperationParameter();
+ if(!pSecond)
+ {
+ delete pFirst;
+ return 0;
+ }
+
+ if(KVSP_curCharIsEndOfCommand)
+ {
+ error(KVSP_curCharPointer,__tr2qs("Unexpected end of command in binding operation, at least one slash is missing"));
+ delete pFirst;
+ return 0;
+ }
+
+ if(KVSP_curCharUnicode != '/')
+ {
+ error(KVSP_curCharPointer,__tr2qs("Found character '%q' (unicode %x) where a slash '/' was expected"),KVSP_curCharPointer,KVSP_curCharUnicode);
+ delete pFirst;
+ return 0;
+ }
+
+ KVSP_skipChar;
+
+ KviKvsTreeNodeData * pThird = parseCommandParameter();
+ if(!pThird)
+ {
+ if(error())
+ {
+ delete pFirst;
+ delete pSecond;
+ return 0;
+ }
+
+ pThird = new KviKvsTreeNodeConstantData(KVSP_curCharPointer,new KviKvsVariant(QString("")));
+ }
+
+ while(!KVSP_curCharIsEndOfCommand)KVSP_skipChar;
+ if(!KVSP_curCharIsEndOfBuffer)KVSP_skipChar;
+
+ if((szOp == "t") || (szOp == "tr") || (szOp == "y"))
+ {
+ // transliteration tr/szFirst/szSecond/szFlags
+ return new KviKvsTreeNodeOperationStringTransliteration(pBegin,pFirst,pSecond,pThird);
+ } else if(szOp == "s")
+ {
+ // regexp substitution s/szFirst/szSecond/szFlags
+ return new KviKvsTreeNodeOperationStringSubstitution(pBegin,pFirst,pSecond,pThird);
+ }
+
+ error(KVSP_curCharPointer,__tr2qs("Unknown binding operation '%Q'"),&szOp);
+ return 0;
+}
+
+
+KviKvsTreeNodeOperation * KviKvsParser::parseOperation()
+{
+ // find the operator
+ const QChar * pBegin = KVSP_curCharPointer;
+
+ switch(KVSP_curCharUnicode)
+ {
+ case '=':
+ {
+ KVSP_skipChar;
+ if(KVSP_curCharUnicode == '~')
+ {
+ KVSP_skipChar;
+ skipSpaces();
+ if(KVSP_curCharIsEndOfCommand)
+ {
+ error(KVSP_curCharPointer,__tr2qs("Missing right side operand for the binding operator '=~'"));
+ return 0;
+ }
+ return parseBindingOperation();
+ } else {
+ skipSpaces();
+ KviKvsTreeNodeData * d = parseOperationRightSide(true);
+ if(!d)return 0; // error
+ return new KviKvsTreeNodeOperationAssignment(pBegin,d);
+ }
+ }
+ break;
+ case '+':
+ KVSP_skipChar;
+ switch(KVSP_curCharUnicode)
+ {
+ case '+':
+ // operator ++
+ KVSP_skipChar;
+ skipSpaces();
+ if(!KVSP_curCharIsEndOfCommand)
+ {
+ warning(KVSP_curCharPointer,__tr2qs("Trailing garbage ignored after operator '++'"));
+ }
+ while(!KVSP_curCharIsEndOfCommand)KVSP_skipChar;
+ if(!KVSP_curCharIsEndOfBuffer)KVSP_skipChar;
+ return new KviKvsTreeNodeOperationIncrement(pBegin);
+ break;
+ case '=':
+ // operator +=
+ KVSP_skipChar;
+ skipSpaces();
+ if(KVSP_curCharIsEndOfCommand)
+ {
+ error(KVSP_curCharPointer,__tr2qs("Missing right operand for operator '+='"));
+ return 0;
+ }
+ KviKvsTreeNodeData * d = parseOperationRightSide(true);
+ if(!d)return 0; // error
+ return new KviKvsTreeNodeOperationSelfSum(pBegin,d);
+ break;
+ }
+ break;
+ case '-':
+ KVSP_skipChar;
+ switch(KVSP_curCharUnicode)
+ {
+ case '-':
+ KVSP_skipChar;
+ // operator --
+ skipSpaces();
+ if(!KVSP_curCharIsEndOfCommand)
+ {
+ warning(KVSP_curCharPointer,__tr2qs("Trailing garbage ignored after operator '--'"));
+ }
+ while(!KVSP_curCharIsEndOfCommand)KVSP_skipChar;
+ if(!KVSP_curCharIsEndOfBuffer)KVSP_skipChar;
+ return new KviKvsTreeNodeOperationDecrement(pBegin);
+ break;
+ case '>':
+ warning(KVSP_curCharPointer,__tr2qs("This looks a lot like an object handle dereferencing operator '->' but in fact it isn't. Maybe you forgot a '$' just after ?"));
+ break;
+ case '=':
+ // operator -=
+ KVSP_skipChar;
+ skipSpaces();
+ if(KVSP_curCharIsEndOfCommand)
+ {
+ error(KVSP_curCharPointer,__tr2qs("Missing right operand for operator '-='"));
+ return 0;
+ }
+ KviKvsTreeNodeData * d = parseOperationRightSide(true);
+ if(!d)return 0; // error
+ return new KviKvsTreeNodeOperationSelfSubtraction(pBegin,d);
+ break;
+ }
+ break;
+ case '<':
+ KVSP_skipChar;
+ switch(KVSP_curCharUnicode)
+ {
+ case '<':
+ KVSP_skipChar;
+ if(KVSP_curCharUnicode == '=')
+ {
+ KVSP_skipChar;
+ skipSpaces();
+ if(KVSP_curCharIsEndOfCommand)
+ {
+ error(KVSP_curCharPointer,__tr2qs("Missing right operand for operator '<<='"));
+ return 0;
+ }
+ KviKvsTreeNodeData * d = parseOperationRightSide(true);
+ if(!d)return 0; // error
+ return new KviKvsTreeNodeOperationSelfShl(pBegin,d);
+ } else {
+ skipSpaces();
+ if(KVSP_curCharIsEndOfCommand)
+ {
+ error(KVSP_curCharPointer,__tr2qs("Missing right operand for operator '<<'"));
+ return 0;
+ }
+ KviKvsTreeNodeData * d = parseOperationRightSide();
+ if(!d)return 0; // error
+ return new KviKvsTreeNodeOperationStringAppendWithSpace(pBegin,d);
+ }
+ break;
+ case ',':
+ {
+ KVSP_skipChar;
+ skipSpaces();
+ if(KVSP_curCharIsEndOfCommand)
+ {
+ error(KVSP_curCharPointer,__tr2qs("Missing right operand for operator '<,'"));
+ return 0;
+ }
+ KviKvsTreeNodeData * d = parseOperationRightSide();
+ if(!d)return 0; // error
+ return new KviKvsTreeNodeOperationStringAppendWithComma(pBegin,d);
+ }
+ break;
+ case '+':
+ {
+ KVSP_skipChar;
+ skipSpaces();
+ if(KVSP_curCharIsEndOfCommand)
+ {
+ error(KVSP_curCharPointer,__tr2qs("Missing right operand for operator '<+'"));
+ return 0;
+ }
+ KviKvsTreeNodeData * d = parseOperationRightSide();
+ if(!d)return 0; // error
+ return new KviKvsTreeNodeOperationArrayAppend(pBegin,d);
+ }
+ break;
+ }
+ break;
+ case '>':
+ KVSP_skipChar;
+ switch(KVSP_curCharUnicode)
+ {
+ case '>':
+ KVSP_skipChar;
+ if(KVSP_curCharUnicode == '=')
+ {
+ KVSP_skipChar;
+ skipSpaces();
+ if(KVSP_curCharIsEndOfCommand)
+ {
+ error(KVSP_curCharPointer,__tr2qs("Missing right operand for operator '>>='"));
+ return 0;
+ }
+ KviKvsTreeNodeData * d = parseOperationRightSide(true);
+ if(!d)return 0; // error
+ return new KviKvsTreeNodeOperationSelfShr(pBegin,d);
+ }
+ break;
+ }
+ break;
+ case '.':
+ KVSP_skipChar;
+ switch(KVSP_curCharUnicode)
+ {
+ case '=':
+ KVSP_skipChar;
+ skipSpaces();
+ if(KVSP_curCharIsEndOfCommand)
+ {
+ error(KVSP_curCharPointer,__tr2qs("Missing right operand for operator '.='"));
+ return 0;
+ }
+ KviKvsTreeNodeData * d = parseOperationRightSide();
+ if(!d)return 0; // error
+ return new KviKvsTreeNodeOperationStringAppend(pBegin,d);
+ break;
+ }
+ break;
+#define SELF_OPERATOR(__opchar,__opstr,__class) \
+ case __opchar: \
+ KVSP_skipChar; \
+ switch(KVSP_curCharUnicode) \
+ { \
+ case '=': \
+ KVSP_skipChar; \
+ skipSpaces(); \
+ if(KVSP_curCharIsEndOfCommand) \
+ { \
+ error(KVSP_curCharPointer,__tr2qs("Missing right operand for operator '" __opstr "='")); \
+ return 0; \
+ } \
+ KviKvsTreeNodeData * d = parseOperationRightSide(true); \
+ if(!d)return 0; \
+ return new __class(pBegin,d); \
+ break; \
+ } \
+ break;
+ SELF_OPERATOR('*',"*",KviKvsTreeNodeOperationSelfMultiplication)
+ SELF_OPERATOR('/',"/",KviKvsTreeNodeOperationSelfDivision)
+ SELF_OPERATOR('%',"%",KviKvsTreeNodeOperationSelfModulus)
+ SELF_OPERATOR('|',"|",KviKvsTreeNodeOperationSelfOr)
+ SELF_OPERATOR('&',"&",KviKvsTreeNodeOperationSelfAnd)
+ SELF_OPERATOR('^',"^",KviKvsTreeNodeOperationSelfXor)
+ }
+
+ error(pBegin,__tr2qs("Unknown operator"));
+ return 0;
+}
+
+KviKvsTreeNodeInstruction * KviKvsParser::parseVoidFunctionCallOrOperation()
+{
+ KVSP_ASSERT((KVSP_curCharUnicode == '$') || (KVSP_curCharUnicode == '%') || (KVSP_curCharUnicode == '@'));
+
+ const QChar * pBegin = KVSP_curCharPointer;
+
+ KviKvsTreeNodeData * r = parsePercentOrDollar();
+
+ if(!r)
+ {
+ // must be an error
+ return 0;
+ }
+
+ skipSpaces();
+
+ if(KVSP_curCharIsEndOfCommand)
+ {
+ // the end of the command
+ if(!r->isFunctionCall())
+ {
+ if(r->isReadOnly())
+ {
+ warning(pBegin,__tr2qs("Unexpected (and senseless) read-only data evaluation"));
+ error(KVSP_curCharPointer,__tr2qs("Syntax error: confused by earlier errors: bailing out"));
+ } else {
+ error(KVSP_curCharPointer,__tr2qs("Unexpected end of script after a variable reference: expected operator"));
+ }
+ delete r;
+ return 0;
+ } else {
+ if(!KVSP_curCharIsEndOfBuffer)KVSP_skipChar;
+ return new KviKvsTreeNodeVoidFunctionCall(r->location(),(KviKvsTreeNodeFunctionCall *)r);
+ }
+ }
+
+ // not the end of a command : an operation
+ if(r->isReadOnly())
+ {
+ // must be followed by the end of a command
+ if(r->isFunctionCall())
+ {
+ error(KVSP_curCharPointer,__tr2qs("Unexpected character '%q' (unicode %x) after a void function call: end of instruction expected"),KVSP_curCharPointer,KVSP_curCharUnicode);
+ } else {
+ warning(pBegin,__tr2qs("Unexpected (and senseless) read-only data evaluation"));
+ warning(pBegin,__tr2qs("Unexpected character '%q' (unicode %x)"),KVSP_curCharPointer,KVSP_curCharUnicode);
+ error(KVSP_curCharPointer,__tr2qs("Syntax error: confused by earlier errors: bailing out"));
+ }
+ delete r;
+ return 0;
+ }
+
+ // ok.. parse the operation
+ KviKvsTreeNodeOperation * op = parseOperation();
+ if(!op)
+ {
+ delete r;
+ return 0;
+ }
+
+ op->setTargetVariableReference(r);
+ return op;
+}
diff --git a/src/kvirc/kvs/kvi_kvs_parser_macros.h b/src/kvirc/kvs/kvi_kvs_parser_macros.h
new file mode 100644
index 00000000..8de1f479
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_parser_macros.h
@@ -0,0 +1,47 @@
+#ifndef _KVI_KVS_PARSER_MACROS_H_
+#define _KVI_KVS_PARSER_MACROS_H_
+//=============================================================================
+//
+// File : kvi_kvs_parser_macros.h
+// Creation date : Sun 5 Ocr 2003 20.25 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define KVSP_skipChar m_ptr++
+#define KVSP_skipNChars(n) m_ptr += n
+#define KVSP_backChar m_ptr--
+#define KVSP_backNChars(n) m_ptr -= n
+
+#define KVSP_curCharUnicode (m_ptr->unicode())
+#define KVSP_curCharPointer m_ptr
+
+#define KVSP_curCharIsLetter (m_ptr->isLetter())
+#define KVSP_curCharIsNumber (m_ptr->isNumber())
+#define KVSP_curCharIsLetterOrNumber (m_ptr->isLetterOrNumber())
+#define KVSP_curCharIsFunctionStart (m_ptr->isLetterOrNumber() || (m_ptr->unicode() == '(') || (m_ptr->unicode() == '{') || (m_ptr->unicode() == '$'))
+#define KVSP_curCharIsEndOfCommand ((m_ptr->unicode() == ';') || (m_ptr->unicode() == 0) || (m_ptr->unicode() == '\n') || (m_ptr->unicode() == '\r'))
+#define KVSP_curCharIsEndOfBuffer (m_ptr->unicode() == 0)
+
+#define KVSP_setCurCharPointer(_ptr) m_ptr = _ptr
+
+#define KVSP_ASSERT(_x) if(!(_x))debug("WARNING : ASSERT FAILED: (%s) IS FALSE AT %s:%d",#_x,__FILE__,__LINE__);
+
+
+#endif //!_KVI_KVS_PARSER_MACROS_H_
diff --git a/src/kvirc/kvs/kvi_kvs_parser_specialcommands.cpp b/src/kvirc/kvs/kvi_kvs_parser_specialcommands.cpp
new file mode 100644
index 00000000..0dbc7816
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_parser_specialcommands.cpp
@@ -0,0 +1,1988 @@
+//=============================================================================
+//
+// File : kvi_kvs_parser_specialcommands.cpp
+// Creation date : Thu 06 Now 2003 14.14 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+
+#include "kvi_kvs_parser.h"
+
+#include "kvi_kvs_treenode.h"
+
+#include "kvi_kvs_report.h"
+#include "kvi_kvs_kernel.h"
+
+#include "kvi_kvs_parser_macros.h"
+#include "kvi_kvs_object_functionhandler.h"
+
+#include "kvi_locale.h"
+
+#include "kvi_cmdformatter.h"
+
+
+KviKvsTreeNodeCommand * KviKvsParser::parseSpecialCommandPerlBegin()
+{
+ // in fact this is not a fully special command
+ // it is special only in the sense of parsing.
+ // Once parsed, the command is routed to the perl module
+ // with the perl code as FIRST parameter and the other parameters
+ // of the command following.
+ // the help page for perl.begin is in the perl module
+
+ // perl.begin(context) <perl code> perl.end
+ //
+
+ const QChar * pBegin = KVSP_curCharPointer;
+
+ skipSpaces();
+ KviKvsTreeNodeDataList * dl;
+ if(KVSP_curCharUnicode == '(')
+ {
+ dl = parseCommaSeparatedParameterList();
+ if(!dl)return 0;
+ } else {
+ dl = new KviKvsTreeNodeDataList(pBegin);
+ }
+
+ //while(!KVSP_curCharIsEndOfCommand)KVSP_skipChar;
+ if(!KVSP_curCharIsEndOfBuffer)KVSP_skipChar;
+
+ if(!skipSpacesAndNewlines())
+ {
+ delete dl;
+ return 0;
+ }
+
+ // allow a ';' after perl.begin
+ if(KVSP_curCharIsEndOfCommand && !KVSP_curCharIsEndOfBuffer)
+ {
+ KVSP_skipChar;
+ if(!skipSpacesAndNewlines())
+ {
+ delete dl;
+ return 0;
+ }
+ }
+
+ const QChar * pPerlBegin = KVSP_curCharPointer;
+
+ // now look for perl.end[terminator]
+ static QString szPerlEnd("perl.end");
+ const QChar * pPerlEnd;
+ for(;;)
+ {
+ while(KVSP_curCharUnicode && (KVSP_curCharUnicode != 'p') && (KVSP_curCharUnicode != 'P'))
+ KVSP_skipChar;
+ if(KVSP_curCharIsEndOfBuffer)
+ {
+ delete dl;
+ error(KVSP_curCharPointer,__tr2qs("Unexpected end of command buffer while looking for the \"perl.end\" statement"));
+ return 0;
+ }
+ pPerlEnd = KVSP_curCharPointer;
+ if(KviQString::equalCIN(szPerlEnd,KVSP_curCharPointer,8))
+ {
+ KVSP_skipNChars(8);
+ if(KVSP_curCharIsEndOfCommand || (KVSP_curCharUnicode == ' ') || (KVSP_curCharUnicode == '\t'))
+ {
+ // yeah!
+ QString szPerl(pPerlBegin,pPerlEnd - pPerlBegin);
+ dl->prependItem(new KviKvsTreeNodeConstantData(pPerlBegin,new KviKvsVariant(szPerl)));
+ while(!KVSP_curCharIsEndOfCommand)KVSP_skipChar;
+ if(!KVSP_curCharIsEndOfBuffer)KVSP_skipChar;
+ break;
+ } else {
+ KVSP_backNChars(7);
+ }
+ } else {
+ KVSP_skipChar;
+ }
+ }
+
+ return new KviKvsTreeNodeModuleSimpleCommand(pBegin,"perl","begin",dl);
+}
+
+KviKvsTreeNodeCommand * KviKvsParser::parseSpecialCommandBreak()
+{
+ /*
+ @doc: break
+ @type:
+ command
+ @title:
+ break
+ @syntax:
+ break
+ @short:
+ Interrupts an iteration loop
+ @description:
+ Interrupts an iteration loop like [cmd]while[/cmd].[br]
+ This command always jumps out of a single code block.[br]
+ If called outside an iteration loop , will act just like [cmd]halt[/cmd]
+ has been called but has no additional semantics for events.[br]
+ */
+ const QChar * pBegin = KVSP_curCharPointer; // FIXME: this is not accurate at all : it may be even the end of the cmd
+ skipSpaces();
+ if(!KVSP_curCharIsEndOfCommand)
+ {
+ warning(KVSP_curCharPointer,__tr2qs("Trailing garbage at the end of the break command: ignored"));
+ }
+
+ while(!KVSP_curCharIsEndOfCommand)KVSP_skipChar;
+ if(!KVSP_curCharIsEndOfBuffer)KVSP_skipChar;
+ return new KviKvsTreeNodeSpecialCommandBreak(pBegin);
+}
+
+KviKvsTreeNodeCommand * KviKvsParser::parseSpecialCommandUnset()
+{
+ /*
+ @doc: unset
+ @type:
+ command
+ @title:
+ unset
+ @syntax:
+ unset <variable_list>
+ @keyterms:
+ unsetting variables
+ @short:
+ Unsets a set of variables
+ @description:
+ Unsets the specified list of comma separated variables.
+ It is equivalent to assigning the default empty value
+ to each variable on its own: just does it all at aonce.
+ Note that KVIrc automatically frees the local variable memory
+ when they go out of scope and the global variable memory
+ when KVIrc terminates.
+ @examples:
+ [example]
+ %a = pippo
+ %b = 1
+ [cmd]echo[/cmd] %a %b
+ unset %a %b
+ [cmd]echo[/cmd] %a %b
+ [/example]
+ */
+
+ const QChar * pCmdBegin = KVSP_curCharPointer;
+
+ KviPointerList<KviKvsTreeNodeVariable> * pVarList = new KviPointerList<KviKvsTreeNodeVariable>;
+ pVarList->setAutoDelete(true);
+
+ while(KVSP_curCharUnicode == '%')
+ {
+ KviKvsTreeNodeVariable * d = parsePercent();
+ if(!d)return 0;
+
+ pVarList->append(d);
+
+ skipSpaces();
+
+ if(KVSP_curCharUnicode == ',')
+ {
+ KVSP_skipChar;
+ skipSpaces();
+ }
+ }
+
+ if(!KVSP_curCharIsEndOfCommand)
+ {
+ warning(KVSP_curCharPointer,__tr2qs("The 'unset' command needs a variable list"));
+ error(KVSP_curCharPointer,__tr2qs("Found character %q (unicode %x) where a variable was expected"),KVSP_curCharPointer,KVSP_curCharUnicode);
+ return 0;
+ }
+
+ if(!KVSP_curCharIsEndOfBuffer)KVSP_skipChar;
+
+ if(pVarList->count() < 1)
+ {
+ delete pVarList;
+ warning(KVSP_curCharPointer,__tr2qs("'unset' command used without a variable list"));
+ return 0; // null unset ?
+ }
+ return new KviKvsTreeNodeSpecialCommandUnset(pCmdBegin,pVarList);
+}
+
+KviKvsTreeNodeCommand * KviKvsParser::parseSpecialCommandGlobal()
+{
+ /*
+ @doc: global
+ @type:
+ command
+ @title:
+ global
+ @syntax:
+ global <variable_list>
+ @keyterms:
+ explicitly declaring global variables
+ @short:
+ Explicitly declares global variables
+ @description:
+ Declares a list of global variables.
+ Once a variable has been declared as global
+ it refers to the global kvirc instance for the scope of the script.
+ Global variables are shared between scripts and keep their
+ value until they are explicitly unset or kvirc quits.
+ This command can be used to override the default behaviour of
+ declaring global variables by starting them with an uppercase letter
+ and declaring local variables by starting them with a lowercase one.
+ @examples:
+ global %a,%b,%c;
+ */
+ while(KVSP_curCharUnicode == '%')
+ {
+ KVSP_skipChar;
+ const QChar * pBegin = KVSP_curCharPointer;
+
+
+ while((KVSP_curCharIsLetterOrNumber) || (KVSP_curCharUnicode == '_'))KVSP_skipChar;
+
+ QString szIdentifier(pBegin,KVSP_curCharPointer - pBegin);
+
+ if(!m_pGlobals)
+ {
+ m_pGlobals = new KviPointerHashTable<QString,QString>(17,false);
+ m_pGlobals->setAutoDelete(true);
+ }
+ m_pGlobals->replace(szIdentifier,new QString());
+
+ skipSpaces();
+
+ if(KVSP_curCharUnicode == ',')
+ {
+ KVSP_skipChar;
+ skipSpaces();
+ }
+ }
+
+ if(!KVSP_curCharIsEndOfCommand)
+ {
+ warning(KVSP_curCharPointer,__tr2qs("The 'global' command needs a variable list"));
+ error(KVSP_curCharPointer,__tr2qs("Found character %q (unicode %x) where a variable was expected"),KVSP_curCharPointer,KVSP_curCharUnicode);
+ return 0;
+ }
+
+ if(!KVSP_curCharIsEndOfBuffer)KVSP_skipChar;
+ return 0;
+}
+
+KviKvsTreeNodeCommand * KviKvsParser::parseSpecialCommandClass()
+{
+ /*
+ @doc: class
+ @title:
+ class
+ @short:
+ Defines a new object class
+ @keyterms:
+ defining an object class
+ @type:
+ command
+ @syntax:
+ class(<classname:string>[,<base_class_name:string>])
+ {
+ [internal] [function] <function_name>[([<parameter reminder>])]
+ {
+ <function body>
+ }
+
+ ...
+ }
+ @description:
+ Defines a new implementation of the class <classname>.
+ If an implementation of that class was already existing
+ it is removed with all the derived classes (and all the instances of this class
+ and the derived ones are destroyed).
+ <base_class_name> is the name of the class that the
+ new class has to inherit from.[br]
+ If <base_class_name> is omitted, the new class inherits automatically
+ from [class:object]object[/class].[br]
+ Note:[br]
+ The keywords "function" and "event" that were used in KVIrc versions
+ previous to 3.0.0 have been removed since "useless".[br]
+ The function keyword, however, is still permitted.
+ The keyword "internal" is useful when you want to hide
+ certain function from the outside world. An internal function
+ cannot be called by anyone else but the object instance itself. Note that
+ this is different from the C++ "protected" or "private" keywords
+ that refer to the object's class instead of the object instance.
+ The <parameter reminder> part is an optional string
+ that can be used to sign the parameters that the function expects;
+ it acts as a programmer reminder or comment and it has no other
+ meaning in KVIrc scripting. The <parameter reminder> respects the syntax
+ of an expression, so it is terminated by a closed parenthesis.
+ It's rather dangerous to use this command inside an object
+ function handler: if the class definition <class> was already
+ existing and it is a parent of the object's class, you might
+ end up executing "inexisting" code.[br]
+ As a thumb rule, use this command only outside object function handlers.[br]
+ [br][br]
+ Only for the curious: implementing protected and private access
+ list on members would have a considerable runtime overhead because
+ of the strange nature of the KVS language. Object member calls
+ are resolved completly at runtime (and that permits a lot of funny tricks
+ like [cmd]privateimpl[/cmd]) but unfortunately this also forces us
+ to check access lists at runtime. Ok, this would be a relatively small footprint for the "private"
+ keyword where we need to run UP the called object inheritance hierarchy
+ but would have a significant performance footprint for the "protected"
+ keyword where we would need to traverse the WHOLE inheritance tree of the called and calling
+ objects... "internal" still allows hiding members in a lot of situations
+ and is really fast to verify at runtime: no inheritance tree traversal
+ is needed and only object pointers are compared.
+ @examples:
+ [example]
+ class(myclass,[class]object[/class])
+ {
+ constructor
+ {
+ [cmd]echo[/cmd] Hey this is my constructor
+ [cmd]echo[/cmd] I have been just created
+ }
+
+ destructor
+ {
+ [cmd]echo[/cmd] Ops...being destroyed
+ }
+
+ sayHello(this function expects no parameters)
+ {
+ [cmd]echo[/cmd] Hello world!
+ }
+ }
+ [/example]
+ @seealso:
+ [cmd]privateimpl[/cmd], [cmd]killclass[/cmd], [cmd]clearobjects[/cmd], [fnc]$classDefined[/fnc](),
+ [doc:objects]Objects documentation[/doc]
+ */
+
+ if(KVSP_curCharUnicode != '(')
+ {
+ error(KVSP_curCharPointer,__tr2qs("Found character %q (unicode %x) where an open parenthesis was expected"),KVSP_curCharPointer,KVSP_curCharUnicode);
+ return 0;
+ }
+
+ const QChar * pBegin = KVSP_curCharPointer;
+
+ KviKvsTreeNodeDataList * l = parseCommaSeparatedParameterList();
+ if(!l)return 0;
+
+ KviKvsTreeNodeSpecialCommandClass * pClass = new KviKvsTreeNodeSpecialCommandClass(pBegin,l);
+
+ if(!skipSpacesAndNewlines())
+ {
+ delete pClass;
+ return 0;
+ }
+
+ if(KVSP_curCharUnicode != '{')
+ {
+ errorBadChar(KVSP_curCharPointer,'{',"class");
+ delete pClass;
+ return 0;
+ }
+
+ KVSP_skipChar;
+
+ if(!skipSpacesAndNewlines())
+ {
+ delete pClass;
+ return 0;
+ }
+
+ while(KVSP_curCharUnicode != '}')
+ {
+ if((KVSP_curCharUnicode == '#') || (KVSP_curCharUnicode == '/'))
+ {
+ parseComment();
+ if(error())
+ {
+ delete pClass;
+ return 0;
+ }
+ if(!skipSpacesAndNewlines())
+ {
+ delete pClass;
+ return 0;
+ }
+ continue;
+ }
+
+ const QChar * pLabelBegin = KVSP_curCharPointer;
+
+ if(KVSP_curCharIsLetter)
+ {
+ KVSP_skipChar;
+ while(KVSP_curCharIsLetterOrNumber)KVSP_skipChar;
+ }
+
+ if(KVSP_curCharIsEndOfBuffer)
+ {
+ error(KVSP_curCharPointer,__tr2qs("Unexpected end of buffer in class definition"));
+ delete pClass;
+ return 0;
+ }
+
+ if(KVSP_curCharPointer == pLabelBegin)
+ {
+ error(KVSP_curCharPointer,__tr2qs("Found character %q (unicode %x) where a function name was expected"),KVSP_curCharPointer,KVSP_curCharUnicode);
+ delete pClass;
+ return 0;
+ }
+
+ QString szLabel(pLabelBegin,KVSP_curCharPointer - pLabelBegin);
+
+ unsigned int uHandlerFlags = 0;
+
+ if(szLabel.lower() == "internal")
+ {
+ uHandlerFlags |= KviKvsObjectFunctionHandler::Internal;
+ skipSpaces();
+ if(KVSP_curCharUnicode != '(')
+ {
+ pLabelBegin = KVSP_curCharPointer;
+
+ while(KVSP_curCharIsLetterOrNumber)KVSP_skipChar;
+
+ if(KVSP_curCharIsEndOfBuffer)
+ {
+ error(KVSP_curCharPointer,__tr2qs("Unexpected end of buffer in class definition"));
+ delete pClass;
+ return 0;
+ }
+
+ if(KVSP_curCharPointer == pLabelBegin)
+ {
+ error(KVSP_curCharPointer,__tr2qs("Found character %q (unicode %x) where a function name was expected"),KVSP_curCharPointer,KVSP_curCharUnicode);
+ delete pClass;
+ return 0;
+ }
+ szLabel = QString(pLabelBegin,KVSP_curCharPointer - pLabelBegin);
+ }
+ }
+
+
+ if(szLabel.lower() == "function")
+ {
+ skipSpaces();
+ if(KVSP_curCharUnicode != '(')
+ {
+ pLabelBegin = KVSP_curCharPointer;
+
+ while(KVSP_curCharIsLetterOrNumber)KVSP_skipChar;
+
+ if(KVSP_curCharIsEndOfBuffer)
+ {
+ error(KVSP_curCharPointer,__tr2qs("Unexpected end of buffer in class definition"));
+ delete pClass;
+ return 0;
+ }
+
+ if(KVSP_curCharPointer == pLabelBegin)
+ {
+ error(KVSP_curCharPointer,__tr2qs("Found character %q (unicode %x) where a function name was expected"),KVSP_curCharPointer,KVSP_curCharUnicode);
+ delete pClass;
+ return 0;
+ }
+ szLabel = QString(pLabelBegin,KVSP_curCharPointer - pLabelBegin);
+ }
+ }
+
+ if(!skipSpacesAndNewlines())
+ {
+ delete pClass;
+ return 0;
+ }
+
+ if(KVSP_curCharUnicode == '(')
+ {
+ while((!(KVSP_curCharIsEndOfBuffer)) && (KVSP_curCharUnicode != ')'))
+ KVSP_skipChar;
+
+ if(KVSP_curCharIsEndOfBuffer)
+ {
+ error(KVSP_curCharPointer,__tr2qs("Unexpected end of buffer in function parameter list reminder"));
+ delete pClass;
+ return 0;
+ }
+
+ KVSP_skipChar;
+
+ if(!skipSpacesAndNewlines())
+ {
+ delete pClass;
+ return 0;
+ }
+ }
+
+ if(KVSP_curCharIsEndOfBuffer)
+ {
+ error(KVSP_curCharPointer,__tr2qs("Unexpected end of buffer in class definition"));
+ delete pClass;
+ return 0;
+ }
+
+ if(KVSP_curCharUnicode != '{')
+ {
+ errorBadChar(KVSP_curCharPointer,'{',"class");
+ delete pClass;
+ return 0;
+ }
+
+ pBegin = KVSP_curCharPointer;
+ KviKvsTreeNodeInstruction * pInstruction = parseInstruction();
+ if(!pInstruction)
+ {
+ // may be an empty instruction
+ if(error())
+ {
+ delete pClass;
+ return 0;
+ }
+ }
+ delete pInstruction;
+ int iLen = KVSP_curCharPointer - pBegin;
+ QString szInstruction;
+ if(iLen > 0)
+ {
+ szInstruction = QString(pBegin,KVSP_curCharPointer - pBegin);
+ KviCommandFormatter::bufferFromBlock(szInstruction);
+ }
+
+ pClass->addFunctionDefinition(new KviKvsTreeNodeSpecialCommandClassFunctionDefinition(pLabelBegin,szLabel,szInstruction,uHandlerFlags));
+
+ if(!skipSpacesAndNewlines())
+ {
+ delete pClass;
+ return 0;
+ }
+ }
+
+ KVSP_skipChar;
+
+ return pClass;
+}
+
+
+KviKvsTreeNodeCommand * KviKvsParser::parseSpecialCommandWhile()
+{
+ /*
+ @doc: while
+ @type:
+ command
+ @title:
+ while
+ @syntax:
+ while (<condition>) <command>
+ @keyterms:
+ iteration commands, flow control commands
+ @short:
+ Iteration command
+ @description:
+ Executes <command> while the <condition> evaluates
+ to true (non zero result).[br]
+ <command> may be either a single command or a block of commands.[br]
+ It can contain the [cmd]break[/cmd] command: in that case the
+ execution of the <command> will be immediately interrupted and the control
+ transferred to the command following this while block.[br]
+ It is valid for <command> to be an empty command terminated with a ';'.
+ <condition> is an expression as the ones evaluated by [doc:expressioneval]$(*)[/doc]
+ with the following extensions:[br]
+ If <condition> is a string, its length is evaluated: in this way a non-empty string
+ causes the <condition> to be true, an empty string causes it to be false.[br]
+ If <condition> is an array, its size is evaluated: in this way a non-empty array
+ causes the <condition> to be true, an empty array causes it to be false.[br]
+ If <condition> is a hash, the number of its entries is evaluated: in this way a non-empty hash
+ causes the <condition> to be true, an empty hash causes it to be false.[br]
+ @examples:
+ [example]
+ %i = 0;
+ while(%i < 100)%i++
+ while(%i > 0)
+ {
+ %i -= 10
+ if(%i < 20)break;
+ }
+ echo %i
+ [/example]
+ */
+
+ if(KVSP_curCharUnicode != '(')
+ {
+ warning(KVSP_curCharPointer,__tr2qs("The while command needs an expression enclosed in parenthesis"));
+ error(KVSP_curCharPointer,__tr2qs("Found character %q (unicode %x) where an open parenthesis was expected"),KVSP_curCharPointer,KVSP_curCharUnicode);
+ return 0;
+ }
+
+ const QChar * pBegin = KVSP_curCharPointer;
+
+ KVSP_skipChar;
+
+ KviKvsTreeNodeExpression * e = parseExpression(')');
+ if(!e)
+ {
+ // must be an error
+ return 0;
+ }
+
+ if(!skipSpacesAndNewlines())
+ {
+ delete e;
+ return 0;
+ }
+
+ if(KVSP_curCharUnicode == 0)
+ {
+ warning(pBegin,__tr2qs("The last while command in the buffer has no conditional instructions: it's senseless"));
+ warning(KVSP_curCharPointer,__tr2qs("Unexpected end of script while looking for the instruction block of the while command"));
+ }
+
+ KviKvsTreeNodeInstruction * i = parseInstruction();
+ if(!i)
+ {
+ if(error())
+ {
+ delete e;
+ return 0;
+ }
+ } // else , just an empty instruction
+
+ return new KviKvsTreeNodeSpecialCommandWhile(pBegin,e,i);
+}
+
+KviKvsTreeNodeCommand * KviKvsParser::parseSpecialCommandDo()
+{
+ /*
+ @doc: do
+ @type:
+ command
+ @title:
+ do
+ @syntax:
+ do <command> while (<condition>)
+ @keyterms:
+ iteration commands, flow control commands
+ @short:
+ Iteration command
+ @description:
+ Executes <command> once then evaluates the <condition>.
+ If <condition> evaluates to true (non zero result) then repeats the execution again.[br]
+ <command> may be either a single command or a block of commands.[br]
+ It can contain the [cmd]break[/cmd] command: in that case the
+ execution of the <command> will be immediately interrupted and the control
+ transferred to the command following this while block.[br]
+ It is valid for <command> to be an empty command terminated with a ';'.
+ <condition> is an expression as the ones evaluated by [doc:expressioneval]$(*)[/doc]
+ with the following extensions:[br]
+ If <condition> is a string, its length is evaluated: in this way a non-empty string
+ causes the <condition> to be true, an empty string causes it to be false.[br]
+ If <condition> is an array, its size is evaluated: in this way a non-empty array
+ causes the <condition> to be true, an empty array causes it to be false.[br]
+ If <condition> is a hash, the number of its entries is evaluated: in this way a non-empty hash
+ causes the <condition> to be true, an empty hash causes it to be false.[br]
+ @examples:
+ [example]
+ %i = 0;
+ do %i++; while(%i < 100);
+ echo "After first execution: %i";
+ %i = 10
+ do {
+ echo "Executed!";
+ %i++;
+ } while(%i < 1)
+ echo "After second execution: %i";
+ [/example]
+ @seealso:
+ [cmd]while[/cmd]
+ */
+
+ const QChar * pBegin = KVSP_curCharPointer;
+
+ KviKvsTreeNodeInstruction * i = parseInstruction();
+ if(!i)
+ {
+ if(error())return 0;
+ }
+
+ if(!skipSpacesAndNewlines())
+ {
+ if(i)delete i;
+ return 0;
+ }
+
+ static const unsigned short while_chars[10] = { 'W','w','H','h','I','i','L','l','E','e' };
+
+ for(int j=0;j<10;j++)
+ {
+ if(KVSP_curCharUnicode != while_chars[j])
+ {
+ j++;
+ if(KVSP_curCharUnicode != while_chars[j])
+ {
+ if(KVSP_curCharIsEndOfBuffer)
+ error(KVSP_curCharPointer,__tr2qs("Unexpected end of command after the 'do' command block: expected 'while' keyword"));
+ else
+ error(KVSP_curCharPointer,__tr2qs("Found character %q (unicode %x) where a 'while' keyword was expected"),KVSP_curCharPointer,KVSP_curCharUnicode);
+ if(i)delete i;
+ return 0;
+ }
+ } else j++;
+ KVSP_skipChar;
+ }
+
+ if(!skipSpacesAndNewlines())
+ {
+ if(i)delete i;
+ return 0;
+ }
+
+ if(KVSP_curCharUnicode != '(')
+ {
+ warning(KVSP_curCharPointer,__tr2qs("The 'while' block of the 'do' command needs an expression enclosed in parenthesis"));
+ errorBadChar(KVSP_curCharPointer,'(',"do");
+ if(i)delete i;
+ return 0;
+ }
+
+ KVSP_skipChar;
+
+ KviKvsTreeNodeExpression * e = parseExpression(')');
+ if(!e)
+ {
+ // must be an error
+ if(i)delete i;
+ return 0;
+ }
+
+ skipSpaces();
+
+ if(!KVSP_curCharIsEndOfCommand)
+ {
+ warning(KVSP_curCharPointer,__tr2qs("Garbage string after the expression in 'do' command: ignored"));
+ while(!KVSP_curCharIsEndOfCommand)KVSP_skipChar;
+ }
+
+ if(!KVSP_curCharIsEndOfBuffer)KVSP_skipChar;
+
+ return new KviKvsTreeNodeSpecialCommandDo(pBegin,e,i);
+}
+
+
+
+
+KviKvsTreeNodeCommand * KviKvsParser::parseSpecialCommandIf()
+{
+ /*
+ @doc: if
+ @type:
+ command
+ @title:
+ if
+ @syntax:
+ if (<condition>) <command1> [else <command2>]
+ @keyterms:
+ conditional commands, flow control commands
+ @short:
+ Flow control command
+ @description:
+ Executes <command1> if the <condition> evaluates
+ to true (non zero result).
+ If the "else part" is given <command2> is executed
+ if the <condition> evaluates to false (result == '0')
+ <condition> is an expression as the ones evaluated by [doc:expressioneval]$(*)[/doc]
+ with the following extensions:[br]
+ If <condition> is a string, its length is evaluated: in this way a non-empty string
+ causes the <condition> to be true, an empty string causes it to be false.[br]
+ If <condition> is an array, its size is evaluated: in this way a non-empty array
+ causes the <condition> to be true, an empty array causes it to be false.[br]
+ If <condition> is a hash, the number of its entries is evaluated: in this way a non-empty hash
+ causes the <condition> to be true, an empty hash causes it to be false.[br]
+ @examples:
+ if(%a != 10)[cmd]echo[/cmd] \%a was != 10
+ else [cmd]echo[/cmd] \%a was 10!
+ */
+
+ if(KVSP_curCharUnicode != '(')
+ {
+ warning(KVSP_curCharPointer,__tr2qs("The 'if' command needs an expression enclosed in parenthesis"));
+ errorBadChar(KVSP_curCharPointer,'(',"if");
+ return 0;
+ }
+
+ const QChar * pBegin = KVSP_curCharPointer;
+
+ KVSP_skipChar;
+
+
+ KviKvsTreeNodeExpression * e = parseExpression(')');
+ if(!e)
+ {
+ // must be an error
+ return 0;
+ }
+
+ if(!skipSpacesAndNewlines())
+ {
+ delete e;
+ return 0;
+ }
+
+ if(KVSP_curCharUnicode == 0)
+ {
+ warning(pBegin,__tr2qs("The last if command in the buffer has no conditional instructions: it's senseless"));
+ warning(KVSP_curCharPointer,__tr2qs("Unexpected end of script while looking for the instruction block of the if command"));
+ }
+
+ KviKvsTreeNodeInstruction * i = parseInstruction();
+ if(!i)
+ {
+ if(error())
+ {
+ delete e;
+ return 0;
+ }
+ } // else , just an empty instruction
+
+ if(!skipSpacesAndNewlines())
+ {
+ if(i)delete i;
+ return 0;
+ }
+
+ const QChar * pElse = KVSP_curCharPointer;
+
+ if((KVSP_curCharUnicode != 'e') && (KVSP_curCharUnicode != 'E'))
+ return new KviKvsTreeNodeSpecialCommandIf(pBegin,e,i,0);
+ KVSP_skipChar;
+ if((KVSP_curCharUnicode != 'l') && (KVSP_curCharUnicode != 'L'))
+ {
+ KVSP_setCurCharPointer(pElse);
+ return new KviKvsTreeNodeSpecialCommandIf(pBegin,e,i,0);
+ }
+ KVSP_skipChar;
+ if((KVSP_curCharUnicode != 's') && (KVSP_curCharUnicode != 'S'))
+ {
+ KVSP_setCurCharPointer(pElse);
+ return new KviKvsTreeNodeSpecialCommandIf(pBegin,e,i,0);
+ }
+ KVSP_skipChar;
+ if((KVSP_curCharUnicode != 'e') && (KVSP_curCharUnicode != 'E'))
+ {
+ KVSP_setCurCharPointer(pElse);
+ return new KviKvsTreeNodeSpecialCommandIf(pBegin,e,i,0);
+ }
+ KVSP_skipChar;
+ if(KVSP_curCharIsLetterOrNumber)
+ {
+ if((KVSP_curCharUnicode == 'i') || (KVSP_curCharUnicode == 'I'))
+ {
+ KVSP_skipChar;
+ if((KVSP_curCharUnicode == 'f') || (KVSP_curCharUnicode == 'F'))
+ {
+ KVSP_skipChar;
+ if(!KVSP_curCharIsLetterOrNumber)
+ {
+ // this is an "elseif"
+ KVSP_backChar;
+ KVSP_backChar;
+ // point to if
+ goto handle_else_instruction;
+ }
+ KVSP_backChar;
+ }
+ KVSP_backChar;
+ }
+
+ KVSP_setCurCharPointer(pElse);
+ return new KviKvsTreeNodeSpecialCommandIf(pBegin,e,i,0);
+ }
+
+handle_else_instruction:
+ if(!skipSpacesAndNewlines())
+ {
+ delete e;
+ if(i)delete i;
+ return 0;
+ }
+
+ KviKvsTreeNodeInstruction * i2 = parseInstruction();
+ if(!i2)
+ {
+ if(error())
+ {
+ delete e;
+ if(i)delete i;
+ return 0;
+ }
+ } // else , just an empty instruction
+
+ return new KviKvsTreeNodeSpecialCommandIf(pBegin,e,i,i2);
+}
+
+bool KviKvsParser::skipToEndOfForControlBlock()
+{
+ bool bInString = false;
+ int iParLevel = 0;
+
+ for(;;)
+ {
+ switch(KVSP_curCharUnicode)
+ {
+ case '"':
+ bInString = !bInString;
+ KVSP_skipChar;
+ break;
+ case '(':
+ if(!bInString)iParLevel++;
+ KVSP_skipChar;
+ break;
+ case ')':
+ if(!bInString)
+ {
+ if(iParLevel == 0)return true;
+ else iParLevel--;
+ }
+ KVSP_skipChar;
+ break;
+ case 0:
+ error(KVSP_curCharPointer,__tr2qs("Unexpected end of buffer while looking for the closing ')' in the 'for' command"));
+ return false;
+ break;
+ //case '\n':
+ // that's ok.. it may have a parenthesis on the next line
+ //KVSP_skipChar;
+ //break;
+ default:
+ KVSP_skipChar;
+ break;
+ }
+ }
+ // not reached
+ KVSP_ASSERT(false);
+ return false;
+}
+
+KviKvsTreeNodeCommand * KviKvsParser::parseSpecialCommandFor()
+{
+ /*
+ @doc: for
+ @type:
+ command
+ @title:
+ for
+ @syntax:
+ for (<initialization>;<condition>;<update>) <command>
+ @keyterms:
+ iterational control commands
+ @short:
+ Iteration control command
+ @description:
+ Executes <initialization> once then runs the following iteration loop:
+ if <condition> evaluates to true then <command> is executed followed
+ by the <update> command. The iteration is repeated until <condition> evaluates to false.[br]
+ <condition> is an expression as the ones evaluated by [doc:expressioneval]$(*)[/doc]
+ with the following extensions:[br]
+ If <condition> is a string, its length is evaluated: in this way a non-empty string
+ causes the <condition> to be true, an empty string causes it to be false.[br]
+ If <condition> is an array, its size is evaluated: in this way a non-empty array
+ causes the <condition> to be true, an empty array causes it to be false.[br]
+ If <condition> is a hash, the number of its entries is evaluated: in this way a non-empty hash
+ causes the <condition> to be true, an empty hash causes it to be false.[br]
+ @examples:
+ for(%a = 0;%a < 100;%a++)echo %a
+ */
+
+ if(KVSP_curCharUnicode != '(')
+ {
+ warning(KVSP_curCharPointer,__tr2qs("The 'for' command needs an expression enclosed in parenthesis"));
+ errorBadChar(KVSP_curCharPointer,'(',"for");
+ return 0;
+ }
+
+ const QChar * pForBegin = KVSP_curCharPointer;
+
+ KVSP_skipChar;
+
+ skipSpaces();
+
+ KviKvsTreeNodeInstruction * i1 = parseInstruction();
+ if(!i1)
+ {
+ if(error())return 0;
+ } // else just empty instruction
+
+ skipSpaces();
+
+ KviKvsTreeNodeExpression * e = parseExpression(';');
+ if(!e)
+ {
+ if(error())
+ {
+ if(i1)delete i1;
+ return 0;
+ }
+ } // else just empty expression : assume true
+
+ skipSpaces();
+
+ // skip to the first non matching ')' that is not in a string
+
+ const QChar * pBegin = KVSP_curCharPointer;
+
+ if(!skipToEndOfForControlBlock())
+ {
+ if(error()) // <-- that's always true
+ {
+ if(i1)delete i1;
+ if(e)delete e;
+ return 0;
+ }
+ }
+
+
+ // HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK
+ // KVSP_curCharPointer is const!
+ // we shouldn't be able to modify it
+ QChar cSave = *(KVSP_curCharPointer);
+
+ QChar * pHack = (QChar *)KVSP_curCharPointer;
+ *pHack = QChar('\n');
+
+ KVSP_curCharPointer = pBegin;
+
+ KviKvsTreeNodeInstruction * i2 = parseInstruction();
+ *pHack = cSave;
+
+ KVSP_setCurCharPointer(pHack);
+ // EOF HACK EOF HACK EOF HACK EOF HACK EOF HACK EOF HACK EOF HACK
+
+
+ if(!i2)
+ {
+ if(error())
+ {
+ if(i1)delete i1;
+ if(e)delete e;
+ return 0;
+ }
+ } // else just empty instruction
+
+ skipSpaces();
+
+ if(KVSP_curCharUnicode != ')')
+ {
+ error(KVSP_curCharPointer,__tr2qs("Found char %q (unicode %x) while looking for the terminating ')' in 'for' command"),KVSP_curCharPointer,KVSP_curCharUnicode);
+ if(i1)delete i1;
+ if(e)delete e;
+ if(i2)delete i2;
+ return 0;
+ }
+
+ KVSP_skipChar;
+
+ if(!skipSpacesAndNewlines())
+ {
+ if(i1)delete i1;
+ if(e)delete e;
+ if(i2)delete i2;
+ return 0;
+ }
+
+ KviKvsTreeNodeInstruction * loop = parseInstruction();
+ if(!loop)
+ {
+ if(error())
+ {
+ if(i1)delete i1;
+ if(e)delete e;
+ if(i2)delete i2;
+ return 0;
+ }
+
+ if((!i1) && (!e) && (!i2))
+ {
+ error(pForBegin,__tr2qs("Empty infinite 'for' loop: fix the script"));
+ if(i1)delete i1;
+ if(e)delete e;
+ if(i2)delete i2;
+ return 0;
+ }
+ } // else just an empty instruction
+
+ return new KviKvsTreeNodeSpecialCommandFor(pForBegin,i1,e,i2,loop);
+}
+
+
+
+KviKvsTreeNodeCommand * KviKvsParser::parseSpecialCommandForeach()
+{
+ /*
+ @doc: foreach
+ @type:
+ command
+ @title:
+ foreach
+ @syntax:
+ foreach [-a] (<variable>,[<item>[,<item>[,<item>[...]]]) <command>
+ @keyterms:
+ iteration commands, flow control commands
+ @switches:
+ !sw: -a | --all
+ Include empty variables in the iteration loop.
+ @short:
+ Iteration command
+ @description:
+ Executed <command> while assigning to <variable> each <item>.[br]
+ <item> may be a constant , a variable , an array , a dictionary or a function returning
+ either a constant string an array reference or a dictionary reference.[br]
+ If <item> is an array , a dictionary or a function that returns a dictionary or array reference
+ the iteration is done through all the dictionary/array items.[br]
+ Please note that the iteration order of dictionary items is undefined.[br]
+ You can always break from the loop by using the [cmd]break[/cmd] command.[br]
+ foreach doesn't iterate over empty scalar variables (i.e. the ones set to [fnc]$nothing[/fnc])
+ unless you use the -a switch. (Note that an array with *some* empty entries is NOT empty so
+ the iteration is in fact done).
+ @examples:
+ [example]
+ foreach(%i,1,2,3,4,5,6,7,8,9)[cmd]echo[/cmd] %i
+ foreach(%chan,[fnc]$window.list[/fnc](channel))[cmd]me[/cmd] -r=%chan This is a test!
+ [comment]# This will work too, and will do the same job[/comment]
+ %windows[] = [fnc]$window.list[/fnc](channel)
+ foreach(%chan,%windows[])[cmd]me[/cmd] -r=%chan This is a test!
+ [comment]# And this too[/comment]
+ %windows[] = [fnc]$window.list[/fnc](channel)
+ foreach(%key,[fnc]$keys[/fnc](%windows[]))[cmd]me[/cmd] -r=%windows[%key] This is a test!
+ [comment]# Another interesting example[/comment]
+ [cmd]alias[/cmd](test){ [cmd]return[/cmd] [fnc]$hash[/fnc](1,a,2,b,3,c,4,d); };
+ foreach(%x,[fnc]$keys[/fnc]($test)){ [cmd]echo[/cmd] %x, $test{%x}; }
+ [/example]
+ */
+
+ if(KVSP_curCharUnicode != '(')
+ {
+ warning(KVSP_curCharPointer,__tr2qs("The 'foreach' command needs an expression enclosed in parenthesis"));
+ errorBadChar(KVSP_curCharPointer,'(',"foreach");
+ return 0;
+ }
+
+ const QChar * pForeachBegin = KVSP_curCharPointer;
+
+ KVSP_skipChar;
+
+ skipSpaces();
+
+
+ if((KVSP_curCharUnicode != '%') && (KVSP_curCharUnicode != '$') && (KVSP_curCharUnicode != '@'))
+ {
+ warning(KVSP_curCharPointer,__tr2qs("The 'foreach' command expects a writeable iteration variable as first parameter"));
+ error(KVSP_curCharPointer,__tr2qs("Found character '%q' (unicode %x) where '%' or '$' was expected: see /help foreach for the command syntax"),KVSP_curCharPointer,KVSP_curCharUnicode);
+ return 0;
+ }
+
+ KviKvsTreeNodeData * d = parsePercentOrDollar();
+ if(!d)return 0;
+
+ if(d->isFunctionCall() || d->isReadOnly())
+ {
+ warning(KVSP_curCharPointer,__tr2qs("The 'foreach' command expects a writeable iteration variable as first parameter"));
+ if(d->isFunctionCall())
+ error(KVSP_curCharPointer,__tr2qs("Unexpected function call as 'foreach' iteration variable"));
+ else
+ error(KVSP_curCharPointer,__tr2qs("Unexpected read-only variable as 'foreach' iteration variable"));
+ delete d;
+ return 0;
+ }
+
+ skipSpaces();
+ if(KVSP_curCharUnicode != ',')
+ {
+ if(KVSP_curCharUnicode == ')')
+ {
+ error(KVSP_curCharPointer,__tr2qs("Unexpected end of 'foreach' parameters: at least one iteration data argument must be given"));
+ delete d;
+ return 0;
+ }
+ warning(KVSP_curCharPointer,__tr2qs("The 'foreach' command expects a comma separated list of iteration data items after the first parameter"));
+ errorBadChar(KVSP_curCharPointer,',',"foreach");
+ return 0;
+ }
+
+ KviKvsTreeNodeDataList * l = parseCommaSeparatedParameterList();
+ if(!l)return 0;
+
+ if(!skipSpacesAndNewlines())
+ {
+ delete d;
+ delete l;
+ return 0;
+ }
+
+ const QChar * pLoopBegin = KVSP_curCharPointer;
+
+ KviKvsTreeNodeInstruction * loop = parseInstruction();
+ if(!loop)
+ {
+ if(error())return 0;
+ warning(pLoopBegin,__tr2qs("Found empty 'foreach' execution block: maybe you need to fix your script ?"));
+ loop = new KviKvsTreeNodeInstructionBlock(pLoopBegin);
+ }
+
+ return new KviKvsTreeNodeSpecialCommandForeach(pForeachBegin,d,l,loop);
+}
+
+
+KviKvsTreeNodeCommand * KviKvsParser::parseSpecialCommandSwitch()
+{
+ /*
+ @doc: switch
+ @type:
+ command
+ @title:
+ switch
+ @syntax:
+ switch(<expression>)
+ {
+ case(<value>)[:]<command>
+ [break]
+ case(<value>)[:]<command>
+ [break]
+ ....
+ match(<wildcard_expression>)[:]<command>
+ [break]
+ ....
+ regexp(<regular_expression>)[:]<command>
+ [break]
+ ....
+ case(<value>)[:]<command>
+ [break]
+ ....
+ default[:]<command>
+ [break]
+ }
+ @short:
+ Another flow control command
+ @description:
+ The switch command is based on the standard C 'switch' keyword.
+ It executes conditionally groups of commands choosen from
+ a larger set of command groups.[br]
+ First <expression> is evaluated (<expression> is any arithmetic or string expression).[br]
+ Then the 'match','regexp','case' and 'default' labels are evaluated sequentially
+ in the order of appearance.[br]
+ [b]case(<value>)[:]<command>[/b][br]
+ The <value> is evaluated and is compared against the result of <expression>.
+ The comparison is case insensitive (if the values are strings).[br]
+ If <value> is equal to <expression> then <command> is executed.
+ Please note that <command> must be either a single instruction or an instruction block [b]enclosed in braces[/b].
+ If <command> contains a [cmd]break[/cmd] statement inside or if [cmd]break[/cmd]
+ is specified just after the <command> then the execution of the switch is terminated
+ otherwise the nex label is evaluated.[br]
+ [b]match(<value>)[:]<command>[/b][br]
+ The <value> is expected to be a wildcard expression (containing '*' and '?' wildcards)
+ that is matched against <expression>.[br]
+ If there is a match (a complete case insensitive match!) then the related <command>
+ is executed. [cmd]brea[/cmd] is treated just like in the case label.[br]
+ [b]regexp(<value>)[:]<command>[/b][br]
+ The <value> is expected to be a complete standard regular expression
+ that is matched agains <expression>.[br]
+ If there is a match (a complete case insensitive match!) then the related <command>
+ is executed. [cmd]brea[/cmd] is treated just like in the case label.[br]
+ [b]default[:]<command>[/b][br]
+ The default label is executed unconditionally (unless there was a previous label
+ that terminated the execution with break).[br]
+ @examples:
+ [comment]# Try to change the 1 below to 2 or 3 to see the results[/comment]
+ %tmp = 1
+ switch(%tmp)
+ {
+ case(1):
+ echo \%tmp was 1!
+ break;
+ case(2)
+ echo \%tmp was 2!
+ break;
+ default:
+ echo \%tmp was not 1 nor 2: it was %tmp!
+ break;
+ }
+ [comment]# A complexier example: change the 1 in 2 or 3[/comment]
+ %tmp = 1
+ switch(%tmp)
+ {
+ case(1):
+ echo \%tmp was 1!
+ case(2)
+ echo \%tmp was 2!
+ break;
+ default:
+ echo \%tmp was either 1 or something different from 2 (%tmp)
+ break;
+ }
+ [comment]# An example with strings[/comment]
+ %tmp = "This is a test"
+ %tmp2 = "This is not a test"
+ switch(%tmp)
+ {
+ case(%tmp2)
+ echo \%tmp == \%tmp2
+ break;
+ case(%tmp)
+ {
+ # do not break here
+ echo "Yeah.. it's stupid.. \%tmp == \%tmp :D"
+ }
+ match("*TEST"):
+ echo "Matched *TEST"
+ regexp("[a-zA-Z ]*test"):
+ echo "Matched [a-zA-Z ]*text"
+ regexp("[a-zA-Z ]*not[a-zA-Z ]*"):
+ echo "Matched [a-zA-Z ]*not[a-zA-Z ]*"
+ default:
+ echo This is executed anyway (unless some break was called)
+ break;
+ }
+ */
+
+ if(KVSP_curCharUnicode != '(')
+ {
+ warning(KVSP_curCharPointer,__tr2qs("The 'switch' command needs an expression enclosed in parenthesis"));
+ errorBadChar(KVSP_curCharPointer,'(',"switch");
+ return 0;
+ }
+
+ const QChar * pBegin = KVSP_curCharPointer;
+
+ KVSP_skipChar;
+
+ KviKvsTreeNodeExpression * e = parseExpression(')');
+ if(!e)
+ {
+ // must be an error
+ return 0;
+ }
+
+ if(!skipSpacesAndNewlines())
+ {
+ delete e;
+ return 0;
+ }
+
+ if(KVSP_curCharUnicode != '{')
+ {
+ errorBadChar(KVSP_curCharPointer,'{',"switch");
+ delete e;
+ return 0;
+ }
+
+ KVSP_skipChar;
+
+ if(!skipSpacesAndNewlines())
+ {
+ delete e;
+ return 0;
+ }
+
+ KviKvsTreeNodeSpecialCommandSwitch * pSwitch = new KviKvsTreeNodeSpecialCommandSwitch(pBegin,e);
+
+ KviKvsTreeNodeSpecialCommandSwitchLabel * pLabel = 0;
+
+ while(KVSP_curCharUnicode != '}')
+ {
+ // look for a 'case','match','default' or 'regexpr' label
+
+ const QChar * pLabelBegin = KVSP_curCharPointer;
+ while(KVSP_curCharIsLetter)KVSP_skipChar;
+
+ if(KVSP_curCharIsEndOfBuffer)
+ {
+ error(KVSP_curCharPointer,__tr2qs("Unexpected end of buffer in switch condition block"));
+ delete pSwitch;
+ return 0;
+ }
+
+ if(KVSP_curCharPointer == pLabelBegin)
+ {
+ error(KVSP_curCharPointer,__tr2qs("Found character %q (unicode %x) where a 'case','match','regexp','default' or 'break' label was expected"),KVSP_curCharPointer,KVSP_curCharUnicode);
+ delete pSwitch;
+ return 0;
+ }
+
+ QString szLabel(pLabelBegin,KVSP_curCharPointer - pLabelBegin);
+ QString szLabelLow = szLabel.lower();
+
+ bool bNeedParam = true;
+
+ if(szLabelLow == "case")
+ {
+ pLabel = new KviKvsTreeNodeSpecialCommandSwitchLabelCase(pLabelBegin);
+ } else if(szLabelLow == "match")
+ {
+ pLabel = new KviKvsTreeNodeSpecialCommandSwitchLabelMatch(pLabelBegin);
+ } else if(szLabelLow == "regexp")
+ {
+ pLabel = new KviKvsTreeNodeSpecialCommandSwitchLabelRegexp(pLabelBegin);
+ } else if(szLabelLow == "default")
+ {
+ pLabel = new KviKvsTreeNodeSpecialCommandSwitchLabelDefault(pLabelBegin);
+ bNeedParam = false;
+ } else if(szLabelLow == "break")
+ {
+ if(pLabel)
+ {
+ pLabel->setTerminatingBreak(true);
+ skipSpaces();
+ if(KVSP_curCharUnicode == ';')KVSP_skipChar;
+ if(!skipSpacesAndNewlines())
+ {
+ delete pSwitch;
+ delete pLabel;
+ return 0;
+ }
+ continue;
+ } else {
+ error(pLabelBegin,__tr2qs("Found 'break' label where a 'case','match','regexp' or 'default' label was expected"));
+ delete pSwitch;
+ return 0;
+ }
+ } else {
+ error(pLabelBegin,__tr2qs("Found token '%Q' where a 'case','match','regexp','default' or 'break' label was expected"),&szLabel);
+ delete pSwitch;
+ return 0;
+ }
+
+ if(bNeedParam)
+ {
+ skipSpaces();
+ if(KVSP_curCharUnicode != '(')
+ {
+ errorBadChar(KVSP_curCharPointer,'(',"switch");
+ delete pSwitch;
+ delete pLabel;
+ return 0;
+ }
+ KVSP_skipChar;
+
+ KviKvsTreeNodeData * pParameter = parseSingleParameterInParenthesis();
+ if(!pParameter)
+ {
+ delete pSwitch;
+ delete pLabel;
+ return 0;
+ }
+
+ pLabel->setParameter(pParameter);
+ }
+
+ skipSpaces();
+ if(KVSP_curCharUnicode == ':')KVSP_skipChar;
+ if(!skipSpacesAndNewlines())
+ {
+ delete pSwitch;
+ delete pLabel;
+ return 0;
+ }
+
+ KviKvsTreeNodeInstruction * pInstruction = parseInstruction();
+ if(!pInstruction)
+ {
+ // may be an empty instruction
+ if(error())
+ {
+ delete pSwitch;
+ delete pLabel;
+ return 0;
+ }
+ }
+
+ pLabel->setInstruction(pInstruction);
+ pSwitch->addLabel(pLabel);
+
+ if(!skipSpacesAndNewlines())
+ {
+ delete pSwitch;
+ return 0;
+ }
+ }
+
+ KVSP_skipChar;
+
+ if(pSwitch->isEmpty())
+ {
+ error(pBegin,__tr2qs("Senseless empty switch command: fix the script"));
+ delete pSwitch;
+ return 0;
+ }
+
+ return pSwitch;
+}
+
+KviKvsTreeNodeSpecialCommandDefpopupLabelPopup * KviKvsParser::parseSpecialCommandDefpopupLabelPopup()
+{
+ if(KVSP_curCharUnicode != '{')
+ {
+ errorBadChar(KVSP_curCharPointer,'{',"defpopup");
+ return 0;
+ }
+
+ KviKvsTreeNodeSpecialCommandDefpopupLabelPopup * pPopup = new KviKvsTreeNodeSpecialCommandDefpopupLabelPopup(KVSP_curCharPointer);
+
+ KVSP_skipChar;
+
+ if(!skipSpacesAndNewlines())
+ {
+ delete pPopup;
+ return 0;
+ }
+
+ while(KVSP_curCharUnicode != '}')
+ {
+ // look for 'label', 'prologue', 'epilogue', 'popup', 'item', 'separator' or 'extpopup' label
+ const QChar * pLabelBegin = KVSP_curCharPointer;
+ while(KVSP_curCharIsLetter)KVSP_skipChar;
+
+ if(KVSP_curCharIsEndOfBuffer)
+ {
+ error(KVSP_curCharPointer,__tr2qs("Unexpected end of buffer in defpopup block"));
+ delete pPopup;
+ return 0;
+ }
+
+ if(KVSP_curCharPointer == pLabelBegin)
+ {
+ error(KVSP_curCharPointer,__tr2qs("Found character %q (unicode %x) where a 'prologue','separator','label','popup','item','extpopup' or 'epilogue' label was expected"),KVSP_curCharPointer,KVSP_curCharUnicode);
+ delete pPopup;
+ return 0;
+ }
+
+ QString szLabel(pLabelBegin,KVSP_curCharPointer - pLabelBegin);
+ QString szLabelLow = szLabel.lower();
+
+ KviPointerList<QString> * pParameters = 0;
+
+ QString szCondition;
+
+
+#define EXTRACT_POPUP_LABEL_PARAMETERS \
+ if(!skipSpacesAndNewlines()) \
+ { \
+ delete pPopup; \
+ return 0; \
+ } \
+ if(KVSP_curCharUnicode != '(') \
+ { \
+ errorBadChar(KVSP_curCharPointer,'(',"defpopup"); \
+ delete pPopup; \
+ return 0; \
+ } \
+ pParameters = parseCommaSeparatedParameterListNoTree(); \
+ if(!pParameters)return 0;
+
+
+#define EXTRACT_POPUP_LABEL_CONDITION \
+ if(!skipSpacesAndNewlines()) \
+ { \
+ delete pPopup; \
+ return 0; \
+ } \
+ if(KVSP_curCharUnicode == '(') \
+ { \
+ const QChar * pBegin = KVSP_curCharPointer; \
+ KVSP_skipChar; \
+ KviKvsTreeNodeExpression * pExpression = parseExpression(')'); \
+ if(!pExpression) \
+ { \
+ if(pParameters)delete pParameters; \
+ delete pPopup; \
+ return 0; \
+ } \
+ int cLen = (KVSP_curCharPointer - pBegin) - 2; \
+ if(cLen > 0) \
+ { \
+ szCondition.setUnicode(pBegin + 1,cLen); \
+ } \
+ delete pExpression; \
+ if(!skipSpacesAndNewlines()) \
+ { \
+ if(pParameters)delete pParameters; \
+ delete pPopup; \
+ return 0; \
+ } \
+ }
+
+
+
+ if((szLabelLow == "prologue") || (szLabelLow == "epilogue"))
+ {
+ /////////////////////////////////////////////////////////////////////////////////////////////////
+ bool bPrologue = (szLabelLow == "prologue");
+ if(!skipSpacesAndNewlines())
+ {
+ delete pPopup;
+ return 0;
+ }
+
+ if(KVSP_curCharUnicode == '(')
+ {
+ EXTRACT_POPUP_LABEL_PARAMETERS
+ if(!skipSpacesAndNewlines())
+ {
+ if(pParameters)delete pParameters;
+ delete pPopup;
+ return 0;
+ }
+ }
+ const QChar * pBegin = KVSP_curCharPointer;
+ KviKvsTreeNodeInstruction * pInstruction = parseInstruction();
+ if(pInstruction)
+ {
+ // in fact we don't need it at all, we just need the code buffer...
+ delete pInstruction;
+ } else {
+ // may be an empty instruction
+ if(error())
+ {
+ // error
+ if(pParameters)delete pParameters;
+ delete pPopup;
+ return 0;
+ }
+ // empty instruction
+ if(bPrologue)
+ warning(pBegin,__tr2qs("Found empty prologue block: maybe you need to fix the script?"));
+ else
+ warning(pBegin,__tr2qs("Found empty epilogue block: maybe you need to fix the script?"));
+ }
+ int iLen = KVSP_curCharPointer - pBegin;
+ if(iLen > 0)
+ {
+ QString szInstruction(pBegin,KVSP_curCharPointer - pBegin);
+ KviCommandFormatter::bufferFromBlock(szInstruction);
+ QString * pItemName = pParameters ? pParameters->first() : 0;
+ QString szItemName = pItemName ? *pItemName : QString::null;
+ if(bPrologue)
+ pPopup->addLabel(new KviKvsTreeNodeSpecialCommandDefpopupLabelPrologue(pLabelBegin,szInstruction,szItemName));
+ else
+ pPopup->addLabel(new KviKvsTreeNodeSpecialCommandDefpopupLabelEpilogue(pLabelBegin,szInstruction,szItemName));
+ } // else the instruction was empty anyway: we don't need it in fact
+ if(pParameters)delete pParameters;
+ } else if(szLabelLow == "separator")
+ {
+ // FIXME: Separators can't have labels here :(((((
+ /////////////////////////////////////////////////////////////////////////////////////////////////
+ EXTRACT_POPUP_LABEL_CONDITION
+ if(KVSP_curCharUnicode == ';')KVSP_skipChar;
+ QString szItemName = "dummySeparator"; // <------- FIXME!
+ pPopup->addLabel(new KviKvsTreeNodeSpecialCommandDefpopupLabelSeparator(pLabelBegin,szCondition,szItemName));
+
+ } else if(szLabelLow == "label")
+ {
+ /////////////////////////////////////////////////////////////////////////////////////////////////
+ EXTRACT_POPUP_LABEL_PARAMETERS
+ EXTRACT_POPUP_LABEL_CONDITION
+
+ QString * pText = pParameters->first();
+ if(!pText)
+ {
+ error(pLabelBegin,__tr2qs("Unexpected empty <text> field in label parameters. See /help defpopup for the syntax"));
+ delete pParameters;
+ delete pPopup;
+ return 0;
+ }
+ QString * pIcon = pParameters->next();
+ if(KVSP_curCharUnicode == ';')KVSP_skipChar;
+ QString * pItemName = pParameters->next();
+ pPopup->addLabel(new KviKvsTreeNodeSpecialCommandDefpopupLabelLabel(pLabelBegin,szCondition,*pText,pIcon ? *pIcon : QString::null,pItemName ? *pItemName : QString::null));
+ delete pParameters;
+ } else if(szLabelLow == "popup")
+ {
+ /////////////////////////////////////////////////////////////////////////////////////////////////
+ EXTRACT_POPUP_LABEL_PARAMETERS
+ EXTRACT_POPUP_LABEL_CONDITION
+
+ QString * pText = pParameters->first();
+ if(!pText)
+ {
+ error(pLabelBegin,__tr2qs("Unexpected empty <text> field in extpopup parameters. See /help defpopup for the syntax"));
+ delete pParameters;
+ delete pPopup;
+ return 0;
+ }
+ QString * pIcon = pParameters->next();
+ QString * pItemName = pParameters->next();
+
+ KviKvsTreeNodeSpecialCommandDefpopupLabelPopup * pSubPopup = parseSpecialCommandDefpopupLabelPopup();
+ if(!pSubPopup)
+ {
+ delete pParameters;
+ delete pPopup;
+ return 0;
+ }
+
+ pSubPopup->setCondition(szCondition);
+ pSubPopup->setText(*pText);
+ pSubPopup->setItemName(pItemName ? *pItemName : QString::null);
+ if(pIcon)pSubPopup->setIcon(*pIcon);
+ pPopup->addLabel(pSubPopup);
+ delete pParameters;
+ } else if(szLabelLow == "item")
+ {
+ /////////////////////////////////////////////////////////////////////////////////////////////////
+ EXTRACT_POPUP_LABEL_PARAMETERS
+ EXTRACT_POPUP_LABEL_CONDITION
+
+ QString * pText = pParameters->first();
+ if(!pText)
+ {
+ error(pLabelBegin,__tr2qs("Unexpected empty <text> field in extpopup parameters. See /help defpopup for the syntax"));
+ delete pParameters;
+ delete pPopup;
+ return 0;
+ }
+ QString * pIcon = pParameters->next();
+ QString * pItemName = pParameters->next();
+
+ const QChar * pBegin = KVSP_curCharPointer;
+ KviKvsTreeNodeInstruction * pInstruction = parseInstruction();
+ if(pInstruction)
+ {
+ // in fact we don't need it: we just need the code block
+ delete pInstruction;
+ } else {
+ // empty instruction or error ?
+ if(error())
+ {
+ // error
+ delete pParameters;
+ delete pPopup;
+ return 0;
+ }
+ // empty instruction
+ warning(pBegin,__tr2qs("Found empty instruction for popup item: maybe you need to fix the script?"));
+ }
+ int iLen = KVSP_curCharPointer - pBegin;
+ if(iLen > 0)
+ {
+ QString szInstruction(pBegin,KVSP_curCharPointer - pBegin);
+ KviCommandFormatter::bufferFromBlock(szInstruction);
+ pPopup->addLabel(new KviKvsTreeNodeSpecialCommandDefpopupLabelItem(pLabelBegin,szCondition,*pText,pIcon ? *pIcon : QString::null,szInstruction,pItemName ? *pItemName : QString::null));
+ } else {
+ // zero length instruction, but still add the item
+ QString szInstruction = "";
+ KviCommandFormatter::bufferFromBlock(szInstruction);
+ pPopup->addLabel(new KviKvsTreeNodeSpecialCommandDefpopupLabelItem(pLabelBegin,szCondition,*pText,pIcon ? *pIcon : QString::null,szInstruction,pItemName ? *pItemName : QString::null));
+ }
+ delete pParameters;
+ } else if(szLabelLow == "extpopup")
+ {
+ /////////////////////////////////////////////////////////////////////////////////////////////////
+ EXTRACT_POPUP_LABEL_PARAMETERS
+ EXTRACT_POPUP_LABEL_CONDITION
+
+ QString * pText = pParameters->first();
+ if(!pText)
+ {
+ error(pLabelBegin,__tr2qs("Unexpected empty <text> field in extpopup parameters. See /help defpopup for the syntax"));
+ delete pParameters;
+ delete pPopup;
+ return 0;
+ }
+ QString * pName = pParameters->next();
+ if(!pName)
+ {
+ error(pLabelBegin,__tr2qs("Unexpected empty <name> field in extpopup parameters. See /help defpopup for the syntax"));
+ delete pParameters;
+ delete pPopup;
+ return 0;
+ }
+ QString * pIcon = pParameters->next();
+ QString * pItemName = pParameters->next();
+ if(KVSP_curCharUnicode == ';')KVSP_skipChar;
+ pPopup->addLabel(new KviKvsTreeNodeSpecialCommandDefpopupLabelExtpopup(pLabelBegin,szCondition,*pText,pIcon ? *pIcon : QString::null,*pName,pItemName ? *pItemName : QString::null));
+ delete pParameters;
+ } else {
+ /////////////////////////////////////////////////////////////////////////////////////////////////
+ error(pLabelBegin,__tr2qs("Found token '%Q' where a 'prologue','separator','label','popup','item','extpopup' or 'epilogue' label was expected"),&szLabel);
+ delete pPopup;
+ return 0;
+ }
+
+ if(!skipSpacesAndNewlines())
+ {
+ delete pPopup;
+ return 0;
+ }
+ }
+
+ KVSP_skipChar;
+ return pPopup;
+}
+
+
+KviKvsTreeNodeCommand * KviKvsParser::parseSpecialCommandDefpopup()
+{
+ // FIXME: This SHOULD be renamed to popup.create (NOT popup.define!)
+ // and internally aliased to defpopup as backward compat
+ // There should be then also popup.destroy etc..
+
+ /*
+ @doc: defpopup
+ @type:
+ command
+ @title:
+ defpopup
+ @syntax:
+ defpopup [-m] (<popup_name>)
+ {
+ prologue[(<id>)] <prologue_command>
+
+ epilogue[(<id>)] <epilogue_command>
+
+ label(<text>[,<id>])[(<expression>)][;]
+
+ item(<text>[,<icon>[,<id>]])[(<expression>)]<command>
+
+ popup(<text>[,<icon>[,<id>]])[(<expression>)]
+ {
+ <popup body>
+ }
+
+ extpopup(<text>,<name>[,<icon>[,<id>]])[(<expression>)][;]
+
+ separator[(<expression>)][;]
+ ...
+ }
+ @short:
+ Defines a popup menu
+ @switches:
+ !sw: -m | --merge
+ Merges the new popup contents with an older popup version
+ @description:
+ Defines the popup menu <popup_name>. If the -m switch is NOT used
+ the previous contents of the popups are cleared, otherwise are preserved.[br]
+ The popup is generated 'on the fly' when the [cmd]popup[/cmd] command
+ is called.[br]
+ The 'item' keyword adds a menu item with visible <text> ,
+ the optional <icon> and <command> as code to be executed when the item
+ is clicked. <text> is a string that is evaluated at [cmd]popup[/cmd]
+ call time and may contain identifiers and variables. If <expression>
+ is given, it is evaluated at [cmd]popup[/cmd] call time and if the result
+ is 0, the item is not shown in the physical popup.[br]
+ The 'popup' keyword adds a submenu with visible <text> , the optional
+ <icon> and a popup body that follows exactly the same syntax
+ as the defpopup body. The <expression> has the same meaning as with the
+ 'item' keyword.[br]
+ The 'extpopup' keyword adds a submenu with visible <text> , the optional
+ icon and a popup body that is defined by the popup menu <name>. This
+ basically allows to nest popup menus and define their parts separately.
+ <icon> and <expression> have the same meaning as with the 'item' keyword.[br]
+ The 'separator' keyword adds a straight line between items (separator).[br]
+ The 'label' keywork adds a descriptive label that acts like a separator.[br]
+ The 'prologue' keyword adds a <prologue_command> to be executed
+ just before the popup is filled at [cmd]popup[/cmd] command call.[br]
+ The 'epilogue' keyword adds an <epilogue_command> to be executed
+ just after the popup has been filled at [cmd]popup[/cmd] command call.[br]
+ There can be multiple prologue and epilogue commands: their execution order
+ is undefined.[br]
+ <icon> is always an [doc:image_id]image identifier[/doc].[br]
+ <id> is an unique identifier that can be used to remove single items
+ by the means of [cmd]delpopupitem[/cmd]. If <id> is omitted
+ then it is automatically generated.
+ Please note that using this command inside the prologue , epilogue
+ or item code of the modified popup menu is forbidden.
+ In other words: self modification of popup menus is NOT allowed.[br]
+ To remove a popup menu use this command with an empty body:[br]
+ [example]
+ defpopup(test){}
+ [/example]
+ This will remove the popup 'test' and free its memory.
+ Popups have a special kind of local variables that have an extended lifetime:
+ these are called "extended scope variables" and are described in the [doc:data_structures]Data structures documentation[/doc].[br]
+ The syntax for these variables is:[br]
+ [b]%:<variable name>[/b][br]
+ These variables are visible during all the "visible lifetime" of the popup:
+ from the [cmd]popup[/cmd] command call to the moment in that the user selects an item
+ and the corresponding code is executed (substantially from a [cmd]popup[/cmd] call to the next one).[br]
+ This allows you to pre-calculate data and conditions in the porologue of the popup
+ and then use it in the item handlers or item conditions.[br]
+ @seealso:
+ [cmd]popup[/cmd]
+ @examples:
+ */
+
+ if(KVSP_curCharUnicode != '(')
+ {
+ warning(KVSP_curCharPointer,__tr2qs("The 'defpopup' command needs an expression enclosed in parenthesis"));
+ errorBadChar(KVSP_curCharPointer,'(',"defpopup");
+ return 0;
+ }
+
+ const QChar * pBegin = KVSP_curCharPointer;
+
+ KVSP_skipChar;
+
+ KviKvsTreeNodeData * pPopupName = parseSingleParameterInParenthesis();
+ if(!pPopupName)return 0;
+
+ if(!skipSpacesAndNewlines())
+ {
+ delete pPopupName;
+ return 0;
+ }
+
+ KviKvsTreeNodeSpecialCommandDefpopupLabelPopup * pMainPopup = parseSpecialCommandDefpopupLabelPopup();
+ if(!pMainPopup)
+ {
+ delete pPopupName;
+ return 0;
+ }
+
+ return new KviKvsTreeNodeSpecialCommandDefpopup(pBegin,pPopupName,pMainPopup);
+}
+
+
+KviKvsTreeNodeCommand * KviKvsParser::parseSpecialCommandHelp()
+{
+ // again not a fully special command: this routine just returns
+ // a CoreSimpleCommand but parses the parameters as constants
+
+ // we handle a single big parameter, with whitespace stripped
+ // This is because we want the identifiers to be preserved
+ // as unevaluated (i.e $function).
+
+ skipSpaces();
+
+ const QChar * pBegin = KVSP_curCharPointer;
+ while(!KVSP_curCharIsEndOfCommand)KVSP_skipChar;
+
+ if(!KVSP_curCharIsEndOfBuffer)KVSP_skipChar;
+
+ QString tmp(pBegin,KVSP_curCharPointer - pBegin);
+ tmp.stripWhiteSpace();
+
+ const QString szHelpName("help");
+
+ KviKvsCoreSimpleCommandExecRoutine * r = KviKvsKernel::instance()->findCoreSimpleCommandExecRoutine(szHelpName);
+ if(!r)return 0; // <--- internal error!
+
+ KviKvsTreeNodeDataList * p = new KviKvsTreeNodeDataList(pBegin);
+ p->addItem(new KviKvsTreeNodeConstantData(pBegin,new KviKvsVariant(tmp)));
+
+ return new KviKvsTreeNodeCoreSimpleCommand(pBegin,szHelpName,p,r);
+}
diff --git a/src/kvirc/kvs/kvi_kvs_popupmanager.cpp b/src/kvirc/kvs/kvi_kvs_popupmanager.cpp
new file mode 100644
index 00000000..f0d06740
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_popupmanager.cpp
@@ -0,0 +1,117 @@
+//=============================================================================
+//
+// File : kvi_kvs_popupmanager.cpp
+// Created on Tue 7 Jan 2004 02:11:41 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_popupmanager.h"
+#include "kvi_locale.h"
+#include "kvi_config.h"
+
+KviKvsPopupManager * KviKvsPopupManager::m_pInstance = 0;
+
+KviKvsPopupManager::KviKvsPopupManager()
+{
+ m_pInstance = this;
+ m_pPopupDict = new KviPointerHashTable<QString,KviKvsPopupMenu>(17,false);
+ m_pPopupDict->setAutoDelete(true);
+}
+
+KviKvsPopupManager::~KviKvsPopupManager()
+{
+ delete m_pPopupDict;
+}
+
+void KviKvsPopupManager::init()
+{
+ if(KviKvsPopupManager::instance())
+ {
+ debug("WARNING: Trying to create the KviKvsPopupManager twice!");
+ return;
+ }
+ (void)new KviKvsPopupManager();
+}
+
+void KviKvsPopupManager::done()
+{
+ if(!KviKvsPopupManager::instance())
+ {
+ debug("WARNING: Trying to destroy the KviKvsPopupManager twice!");
+ return;
+ }
+ delete KviKvsPopupManager::instance();
+}
+
+KviKvsPopupMenu * KviKvsPopupManager::get(const QString &szPopupName)
+{
+ KviKvsPopupMenu * m = lookup(szPopupName);
+ if(!m)
+ {
+ m = new KviKvsPopupMenu(szPopupName);
+ add(szPopupName,m);
+ }
+ return m;
+}
+
+void KviKvsPopupManager::load(const QString &szFileName)
+{
+ m_pPopupDict->clear();
+ KviConfig cfg(szFileName,KviConfig::Read);
+
+ KviConfigIterator it(*(cfg.dict()));
+
+ KviPointerList<QString> l;
+ l.setAutoDelete(true);
+
+ while(it.current())
+ {
+ l.append(new QString(it.currentKey()));
+ ++it;
+ }
+
+ for(QString * s = l.first();s;s = l.next())
+ {
+ cfg.setGroup(*s);
+ KviKvsPopupMenu * m = new KviKvsPopupMenu(*s);
+ m->load("",&cfg);
+ m_pPopupDict->insert(*s,m);
+ //++it;
+ }
+}
+
+void KviKvsPopupManager::save(const QString &szFileName)
+{
+ KviConfig cfg(szFileName,KviConfig::Write);
+ cfg.clear();
+
+ KviPointerHashTableIterator<QString,KviKvsPopupMenu> it(*m_pPopupDict);
+ while(it.current())
+ {
+ cfg.setGroup(it.current()->popupName());
+ it.current()->save("",&cfg);
+ ++it;
+ }
+}
+
+
+
diff --git a/src/kvirc/kvs/kvi_kvs_popupmanager.h b/src/kvirc/kvs/kvi_kvs_popupmanager.h
new file mode 100644
index 00000000..c9135b22
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_popupmanager.h
@@ -0,0 +1,57 @@
+#ifndef _KVI_KVS_POPUPMANAGER_H_
+#define _KVI_KVS_POPUPMANAGER_H_
+//=============================================================================
+//
+// File : kvi_kvs_popupmanager.h
+// Created on Tue 7 Jan 2004 02:11:41 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_kvs_popupmenu.h"
+
+class KVIRC_API KviKvsPopupManager
+{
+protected: // can only be created by init/done
+ KviKvsPopupManager();
+ ~KviKvsPopupManager();
+protected:
+ KviPointerHashTable<QString,KviKvsPopupMenu> * m_pPopupDict;
+ static KviKvsPopupManager * m_pInstance;
+public:
+ static KviKvsPopupManager * instance(){ return m_pInstance; };
+ static void init();
+ static void done();
+ int popupCount(){ return m_pPopupDict->count(); };
+
+ KviPointerHashTable<QString,KviKvsPopupMenu> * popupDict(){ return m_pPopupDict; };
+
+ KviKvsPopupMenu * lookup(const QString &szPopupName){ return m_pPopupDict->find(szPopupName); };
+ KviKvsPopupMenu * get(const QString &szPopupName);
+ void add(const QString &szPopupName,KviKvsPopupMenu * pPopup){ m_pPopupDict->replace(szPopupName,pPopup); };
+ void remove(const QString &szPopupName){ m_pPopupDict->remove(szPopupName); };
+ void clear(){ m_pPopupDict->clear(); };
+
+ void save(const QString & filename);
+ void load(const QString & filename);
+};
+
+
+#endif //!_KVI_KVS_POPUPMANAGER_H_
diff --git a/src/kvirc/kvs/kvi_kvs_popupmenu.cpp b/src/kvirc/kvs/kvi_kvs_popupmenu.cpp
new file mode 100644
index 00000000..10a26988
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_popupmenu.cpp
@@ -0,0 +1,1234 @@
+//=============================================================================
+//
+// File : kvi_kvs_popupmenu.cpp
+// Created on Wed 07 Jan 2004 05:02:57 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_popupmenu.h"
+#include "kvi_locale.h"
+#include "kvi_iconmanager.h"
+#include "kvi_out.h"
+#include "kvi_app.h"
+#include "kvi_kvs_popupmanager.h"
+#include "kvi_console.h"
+#include "kvi_config.h"
+#include "kvi_cmdformatter.h"
+#include "kvi_options.h"
+
+// popup names
+
+// rootname : the root popup
+// rootname.anonymousmenuX : child popups with no name
+// rootname.externalrootname : child popups copied from external menus
+// rootname.itemX : child items
+// rootname.separatorX : child separators
+// rootname.labelX : child labels
+
+
+KviKvsPopupMenuItem::KviKvsPopupMenuItem(Type t,const QString &szItemName,const QString &szCondition)
+{
+ m_szItemName = szItemName;
+ m_eType = t;
+ if(szCondition.isEmpty())
+ {
+ // true by default
+ m_pKvsCondition = 0;
+ } else {
+ QString szName = "condition callback for ";
+ szName += szItemName;
+ m_pKvsCondition = new KviKvsScript(szName,szCondition,KviKvsScript::Expression);
+ }
+}
+
+KviKvsPopupMenuItem::KviKvsPopupMenuItem(Type t,const QString &szItemName,const KviKvsScript * pCondition)
+{
+ m_szItemName = szItemName;
+ m_eType = t;
+ if(!pCondition)
+ {
+ // true by default
+ m_pKvsCondition = 0;
+ } else {
+ m_pKvsCondition = new KviKvsScript(*pCondition);
+ }
+}
+
+
+KviKvsPopupMenuItem::~KviKvsPopupMenuItem()
+{
+ if(m_pKvsCondition)delete m_pKvsCondition;
+}
+
+void KviKvsPopupMenuItem::clear()
+{
+}
+
+KviKvsScript * KviKvsPopupMenuItem::kvsIcon()
+{
+ return 0;
+}
+
+KviKvsScript * KviKvsPopupMenuItem::kvsText()
+{
+ return 0;
+}
+
+KviKvsScript * KviKvsPopupMenuItem::kvsCode()
+{
+ return 0;
+}
+
+bool KviKvsPopupMenuItem::evaluateCondition(KviKvsPopupMenuTopLevelData * pData)
+{
+ if(!m_pKvsCondition)return true;
+ KviKvsVariant vRet;
+
+ if(!m_pKvsCondition->run(pData->window(),
+ pData->parameters(),
+ &vRet,
+ KviKvsScript::PreserveParams,
+ pData->extendedRunTimeData()))
+ {
+ // broken condition
+ pData->window()->output(KVI_OUT_PARSERWARNING,__tr2qs("Broken condition in menu setup: assuming false"));
+ return false;
+ }
+ return vRet.asBoolean();
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+KviKvsPopupMenuItemSeparator::KviKvsPopupMenuItemSeparator(const QString &szItemName,const QString &szCondition)
+: KviKvsPopupMenuItem(KviKvsPopupMenuItem::Separator,szItemName,szCondition)
+{
+}
+
+KviKvsPopupMenuItemSeparator::KviKvsPopupMenuItemSeparator(const QString &szItemName,const KviKvsScript * pCondition)
+: KviKvsPopupMenuItem(KviKvsPopupMenuItem::Separator,szItemName,pCondition)
+{
+}
+
+KviKvsPopupMenuItemSeparator::~KviKvsPopupMenuItemSeparator()
+{
+}
+
+void KviKvsPopupMenuItemSeparator::fill(KviKvsPopupMenu * pMenu,KviKvsPopupMenuTopLevelData * pData,int iIdx)
+{
+ if(!evaluateCondition(pData))return;
+ pMenu->insertSeparator();
+}
+
+KviKvsPopupMenuItem * KviKvsPopupMenuItemSeparator::clone() const
+{
+ return new KviKvsPopupMenuItemSeparator(m_szItemName,m_pKvsCondition);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+KviKvsPopupMenuItemWithTextAndIcon::KviKvsPopupMenuItemWithTextAndIcon(KviKvsPopupMenuItem::Type t,const QString &szItemName,const QString &szText,const QString &szIcon,const QString &szCondition)
+: KviKvsPopupMenuItem(t,szItemName,szCondition)
+{
+ QString szName = "text callback for ";
+ szName += szItemName;
+ m_pKvsText = new KviKvsScript(szName,szText,KviKvsScript::Parameter);
+
+ if(szIcon.isEmpty())
+ {
+ m_pKvsIcon = 0;
+ } else {
+ szName = "icon callback for ";
+ szName += szItemName;
+ m_pKvsIcon = new KviKvsScript(szName,szIcon,KviKvsScript::Parameter);
+ }
+}
+
+KviKvsPopupMenuItemWithTextAndIcon::KviKvsPopupMenuItemWithTextAndIcon(KviKvsPopupMenuItem::Type t,const QString &szItemName,const KviKvsScript * pText,const KviKvsScript * pIcon,const KviKvsScript * pCondition)
+: KviKvsPopupMenuItem(t,szItemName,pCondition)
+{
+ if(pText)
+ {
+ m_pKvsText = new KviKvsScript(*pText);
+ } else {
+ // hum.. this should never happen anyway
+ QString szName = "text callback for ";
+ szName += szItemName;
+ m_pKvsText = new KviKvsScript(szName,"",KviKvsScript::Parameter);
+ }
+
+ if(!pIcon)
+ {
+ m_pKvsIcon = 0;
+ } else {
+ m_pKvsIcon = new KviKvsScript(*pIcon);
+ }
+}
+
+
+KviKvsPopupMenuItemWithTextAndIcon::~KviKvsPopupMenuItemWithTextAndIcon()
+{
+ delete m_pKvsText;
+ if(m_pKvsIcon)delete m_pKvsIcon;
+}
+
+
+KviKvsScript * KviKvsPopupMenuItemWithTextAndIcon::kvsIcon()
+{
+ return m_pKvsIcon;
+}
+
+KviKvsScript * KviKvsPopupMenuItemWithTextAndIcon::kvsText()
+{
+ return m_pKvsText;
+}
+
+QPixmap * KviKvsPopupMenuItemWithTextAndIcon::evaluateIcon(KviKvsPopupMenuTopLevelData * pData)
+{
+ if(KVI_OPTION_BOOL(KviOption_boolDisablePopupIcons))return 0;
+ if(!m_pKvsIcon)return 0;
+
+ KviKvsVariant vRet;
+ if(!m_pKvsIcon->run(pData->window(),
+ pData->parameters(),
+ &vRet,
+ KviKvsScript::PreserveParams,
+ pData->extendedRunTimeData()))
+ {
+ // broken text
+ pData->window()->output(KVI_OUT_PARSERWARNING,__tr2qs("Broken icon parameter: ignoring"));
+ return 0;
+ }
+
+ QString szRet;
+ vRet.asString(szRet);
+
+ QPixmap * p = g_pIconManager->getImage(szRet);
+ if(!p)pData->window()->output(KVI_OUT_PARSERWARNING,__tr2qs("Can't find the icon \"%Q\": ignoring"),&szRet);
+ return p;
+}
+
+QString KviKvsPopupMenuItemWithTextAndIcon::evaluateText(KviKvsPopupMenuTopLevelData *pData)
+{
+ QString szRet;
+ if(!m_pKvsText)return szRet;
+ KviKvsVariant vRet;
+ if(!m_pKvsText->run(pData->window(),
+ pData->parameters(),
+ &vRet,
+ KviKvsScript::PreserveParams,
+ pData->extendedRunTimeData()))
+ {
+ // broken text
+ pData->window()->output(KVI_OUT_PARSERWARNING,__tr2qs("Broken text parameter: assuming empty string"));
+ return szRet;
+ }
+ vRet.asString(szRet);
+ return szRet;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+KviKvsPopupMenuItemLabelHelper::KviKvsPopupMenuItemLabelHelper(KviKvsPopupMenuItemLabel * pItem)
+: QObject()
+{
+ m_pItem = pItem;
+}
+
+KviKvsPopupMenuItemLabelHelper::~KviKvsPopupMenuItemLabelHelper()
+{
+}
+
+void KviKvsPopupMenuItemLabelHelper::labelDestroyed()
+{
+ m_pItem->labelDestroyed();
+}
+
+KviKvsPopupMenuItemLabel::KviKvsPopupMenuItemLabel(const QString &szItemName,const QString &szText,const QString &szIcon,const QString &szCondition)
+: KviKvsPopupMenuItemWithTextAndIcon(KviKvsPopupMenuItem::Label,szItemName,szText,szIcon,szCondition)
+{
+ m_pLabel = 0;
+ m_pSignalRelay = new KviKvsPopupMenuItemLabelHelper(this);
+}
+
+KviKvsPopupMenuItemLabel::KviKvsPopupMenuItemLabel(const QString &szItemName,const KviKvsScript * pText,const KviKvsScript * pIcon,const KviKvsScript * pCondition)
+: KviKvsPopupMenuItemWithTextAndIcon(KviKvsPopupMenuItem::Label,szItemName,pText,pIcon,pCondition)
+{
+ m_pLabel = 0;
+ m_pSignalRelay = new KviKvsPopupMenuItemLabelHelper(this);
+}
+
+
+KviKvsPopupMenuItemLabel::~KviKvsPopupMenuItemLabel()
+{
+ if(m_pLabel)
+ {
+ QObject::disconnect(m_pLabel,SIGNAL(destroyed()),m_pSignalRelay,SLOT(labelDestroyed()));
+ delete m_pLabel;
+ }
+ delete m_pSignalRelay;
+}
+
+void KviKvsPopupMenuItemLabel::labelDestroyed()
+{
+ m_pLabel = 0; // someone (maybe qt, maybe us) has destroyed the label
+}
+
+
+KviKvsPopupMenuItem * KviKvsPopupMenuItemLabel::clone() const
+{
+ return new KviKvsPopupMenuItemLabel(m_szItemName,m_pKvsText,m_pKvsIcon,m_pKvsCondition);
+}
+
+void KviKvsPopupMenuItemLabel::clear()
+{
+ if(m_pLabel)
+ {
+ QObject::disconnect(m_pLabel,SIGNAL(destroyed()),m_pSignalRelay,SLOT(labelDestroyed()));
+ delete m_pLabel;
+ m_pLabel = 0;
+ }
+}
+
+void KviKvsPopupMenuItemLabel::fill(KviKvsPopupMenu * pMenu,KviKvsPopupMenuTopLevelData * pData,int iIdx)
+{
+ if(!evaluateCondition(pData))return;
+ QString szText = evaluateText(pData);
+ QPixmap * pPix = evaluateIcon(pData);
+ if(m_pLabel)
+ {
+ QObject::disconnect(m_pLabel,SIGNAL(destroyed()),m_pSignalRelay,SLOT(labelDestroyed()));
+ delete m_pLabel;
+ }
+ m_pLabel = new QLabel(szText,pMenu);
+ QObject::connect(m_pLabel,SIGNAL(destroyed()),m_pSignalRelay,SLOT(labelDestroyed()));
+#ifndef COMPILE_USE_QT4
+ // FIXME: QT4 Seems to not allow widgets as QMenu items
+ pMenu->insertItem(m_pLabel);
+#endif
+ m_pLabel->setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
+ if(pPix)m_pLabel->setPixmap(*pPix);
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+KviKvsPopupMenuItemItem::KviKvsPopupMenuItemItem(const QString &szItemName,const QString &szCode,const QString &szText,const QString &szIcon,const QString &szCondition)
+: KviKvsPopupMenuItemWithTextAndIcon(KviKvsPopupMenuItem::Item,szItemName,szText,szIcon,szCondition)
+{
+ QString szName = "click callback for ";
+ szName += szItemName;
+ m_pKvsCode = new KviKvsScript(szName,szCode);
+}
+
+KviKvsPopupMenuItemItem::KviKvsPopupMenuItemItem(const QString &szItemName,const KviKvsScript * pCode,const KviKvsScript * pText,const KviKvsScript * pIcon,const KviKvsScript * pCondition)
+: KviKvsPopupMenuItemWithTextAndIcon(KviKvsPopupMenuItem::Item,szItemName,pText,pIcon,pCondition)
+{
+ m_pKvsCode = new KviKvsScript(*pCode);
+}
+
+
+KviKvsPopupMenuItemItem::~KviKvsPopupMenuItemItem()
+{
+ delete m_pKvsCode;
+}
+
+void KviKvsPopupMenuItemItem::fill(KviKvsPopupMenu * pMenu,KviKvsPopupMenuTopLevelData * pData,int iIdx)
+{
+ if(!evaluateCondition(pData))return;
+ QString szText = evaluateText(pData);
+ QPixmap * pPix = evaluateIcon(pData);
+ int id;
+ if(pPix)id = pMenu->insertItem(*pPix,szText);
+ else id = pMenu->insertItem(szText);
+ pMenu->setItemParameter(id,iIdx);
+}
+
+KviKvsPopupMenuItem * KviKvsPopupMenuItemItem::clone() const
+{
+ return new KviKvsPopupMenuItemItem(m_szItemName,m_pKvsCode,m_pKvsText,m_pKvsIcon,m_pKvsCondition);
+}
+
+KviKvsScript * KviKvsPopupMenuItemItem::kvsCode()
+{
+ return m_pKvsCode;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+KviKvsPopupMenuItemMenu::KviKvsPopupMenuItemMenu(const QString &szItemName,KviKvsPopupMenu * pMenu,const QString &szText,const QString &szIcon,const QString &szCondition)
+: KviKvsPopupMenuItemWithTextAndIcon(KviKvsPopupMenuItem::Menu,szItemName,szText,szIcon,szCondition)
+{
+ m_pMenu = pMenu;
+}
+
+KviKvsPopupMenuItemMenu::KviKvsPopupMenuItemMenu(const QString &szItemName,KviKvsPopupMenu * pMenu,const KviKvsScript * pText,const KviKvsScript * pIcon,const KviKvsScript * pCondition)
+: KviKvsPopupMenuItemWithTextAndIcon(KviKvsPopupMenuItem::Menu,szItemName,pText,pIcon,pCondition)
+{
+ m_pMenu = pMenu;
+}
+
+
+KviKvsPopupMenuItemMenu::~KviKvsPopupMenuItemMenu()
+{
+ delete m_pMenu;
+}
+
+KviKvsPopupMenuItem * KviKvsPopupMenuItemMenu::clone() const
+{
+ KviKvsPopupMenu * copy = new KviKvsPopupMenu(m_pMenu->name());
+ copy->copyFrom(m_pMenu);
+ return new KviKvsPopupMenuItemMenu(m_szItemName,copy,m_pKvsText,m_pKvsIcon,m_pKvsCondition);
+}
+
+
+void KviKvsPopupMenuItemMenu::fill(KviKvsPopupMenu * pMenu,KviKvsPopupMenuTopLevelData * pData,int iIdx)
+{
+ if(!evaluateCondition(pData))return;
+ QString szText = evaluateText(pData);
+ QPixmap * pPix = evaluateIcon(pData);
+ int id;
+ m_pMenu->setParentPopup(pMenu);
+ if(pPix)id = pMenu->insertItem(*pPix,szText,m_pMenu);
+ else id = pMenu->insertItem(szText,m_pMenu);
+ pMenu->setItemParameter(id,iIdx);
+}
+
+void KviKvsPopupMenuItemMenu::clear()
+{
+ m_pMenu->clearMenuContents();
+}
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+KviKvsPopupMenuItemExtMenu::KviKvsPopupMenuItemExtMenu(const QString &szItemName,const QString &szMenuName,const QString &szText,const QString &szIcon,const QString &szCondition)
+: KviKvsPopupMenuItemWithTextAndIcon(KviKvsPopupMenuItem::ExtMenu,szItemName,szText,szIcon,szCondition)
+{
+ m_szMenuName = szMenuName;
+ if(m_szMenuName[0]=='"' && m_szMenuName[(int)(m_szMenuName.length()-1)]=='"')
+ {
+ m_szMenuName.remove(0,1);
+ m_szMenuName.remove(m_szMenuName.length()-1,1);
+ }
+ m_pMenu = 0;
+}
+
+KviKvsPopupMenuItemExtMenu::KviKvsPopupMenuItemExtMenu(const QString &szItemName,const QString &szMenuName,const KviKvsScript * pText,const KviKvsScript * pIcon,const KviKvsScript * pCondition)
+: KviKvsPopupMenuItemWithTextAndIcon(KviKvsPopupMenuItem::ExtMenu,szItemName,pText,pIcon,pCondition)
+{
+ m_szMenuName = szMenuName;
+ if(m_szMenuName[0]=='"' && m_szMenuName[(int)(m_szMenuName.length()-1)]=='"')
+ {
+ m_szMenuName.remove(0,1);
+ m_szMenuName.remove(m_szMenuName.length()-1,1);
+ }
+ m_pMenu = 0;
+}
+
+
+KviKvsPopupMenuItemExtMenu::~KviKvsPopupMenuItemExtMenu()
+{
+ if(m_pMenu)delete m_pMenu;
+}
+
+void KviKvsPopupMenuItemExtMenu::clear()
+{
+ if(m_pMenu)
+ {
+ delete m_pMenu;
+ m_pMenu = 0;
+ }
+}
+
+KviKvsPopupMenuItem * KviKvsPopupMenuItemExtMenu::clone() const
+{
+ return new KviKvsPopupMenuItemExtMenu(m_szItemName,m_szMenuName,m_pKvsText,m_pKvsIcon,m_pKvsCondition);
+}
+
+
+void KviKvsPopupMenuItemExtMenu::fill(KviKvsPopupMenu * pMenu,KviKvsPopupMenuTopLevelData * pData,int iIdx)
+{
+ if(!evaluateCondition(pData))return;
+ QString szText = evaluateText(pData);
+ QPixmap * pPix = evaluateIcon(pData);
+
+ KviKvsPopupMenu * source = KviKvsPopupManager::instance()->lookup(m_szMenuName);
+ if(source)
+ {
+ if(source->isLocked())
+ {
+ pData->window()->output(KVI_OUT_PARSERWARNING,__tr2qs("Recursive definition detected for popup '%Q': ignoring"),&(pMenu->popupName()));
+ return;
+ }
+ QString tmp;
+ KviQString::sprintf(tmp,"%Q.%Q",&(pMenu->popupName()),&m_szMenuName);
+ if(m_pMenu)delete m_pMenu;
+ m_pMenu = new KviKvsPopupMenu(tmp);
+ m_pMenu->copyFrom(source);
+ m_pMenu->setParentPopup(pMenu);
+ int id;
+ if(pPix)id = pMenu->insertItem(*pPix,szText,m_pMenu);
+ else id = pMenu->insertItem(szText,m_pMenu);
+ pMenu->setItemParameter(id,iIdx);
+ } else {
+ pData->window()->output(KVI_OUT_PARSERWARNING,__tr2qs("Can't find the external popup '%Q'; ignoring"),&m_szMenuName);
+ }
+}
+
+
+
+
+
+
+KviKvsPopupMenuTopLevelData::KviKvsPopupMenuTopLevelData(KviKvsVariantList * pParameters,KviWindow * pWindow)
+{
+ m_pExtendedRunTimeData = new KviKvsExtendedRunTimeData(new KviKvsHash(),TRUE);
+ m_pParameters = pParameters;
+ m_pWindow = pWindow;
+ m_bTestMode = false;
+ m_bLocked = false;
+}
+
+KviKvsPopupMenuTopLevelData::~KviKvsPopupMenuTopLevelData()
+{
+ delete m_pExtendedRunTimeData;
+ delete m_pParameters;
+}
+
+
+
+
+
+
+
+KviKvsPopupMenu::KviKvsPopupMenu(const QString &szName)
+:KviTalPopupMenu(0,szName)
+{
+ m_szName = szName;
+ m_pItemList = new KviPointerList<KviKvsPopupMenuItem>;
+ m_pItemList->setAutoDelete(true);
+ m_pPrologues = new KviPointerList<KviKvsScript>;
+ m_pPrologues->setAutoDelete(true);
+ m_pEpilogues = new KviPointerList<KviKvsScript>;
+ m_pEpilogues->setAutoDelete(true);
+ m_pParentPopup = 0;
+ m_pTopLevelData = 0;
+ m_pTempTopLevelData = 0;
+ m_bSetupDone = false;
+ connect(this,SIGNAL(activated(int)),this,SLOT(itemClicked(int)));
+ connect(this,SIGNAL(aboutToShow()),this,SLOT(setupMenuContents()));
+}
+
+
+KviKvsPopupMenu::~KviKvsPopupMenu()
+{
+ clearMenuContents();
+ delete m_pItemList;
+ delete m_pPrologues;
+ delete m_pEpilogues;
+ if(m_pTopLevelData)delete m_pTopLevelData;
+ if(m_pTempTopLevelData)delete m_pTempTopLevelData;
+}
+
+
+void KviKvsPopupMenu::copyFrom(const KviKvsPopupMenu * src)
+{
+ doClear();
+
+ for(KviKvsScript * se = src->m_pEpilogues->first();se;se = src->m_pEpilogues->next())
+ {
+ m_pEpilogues->append(new KviKvsScript(*se));
+ }
+
+ for(KviKvsScript * sp = src->m_pPrologues->first();sp;sp = src->m_pPrologues->next())
+ {
+ m_pPrologues->append(new KviKvsScript(*sp));
+ }
+
+
+ for(const KviKvsPopupMenuItem * it = src->m_pItemList->first();it;it = src->m_pItemList->next())
+ {
+ addItemInternal(it->clone());
+ }
+}
+
+void KviKvsPopupMenu::addPrologue(const QString &szItemName,const QString &szCode)
+{
+ // FIXME: translate this or not ?
+ QString szName = szItemName;
+ if(szName.isEmpty())
+ KviQString::sprintf(szName,"prologue_%u_for_%Q",m_pPrologues->count(),&m_szName);
+ m_pPrologues->append(new KviKvsScript(szName,szCode));
+}
+
+void KviKvsPopupMenu::addEpilogue(const QString &szItemName,const QString &szCode)
+{
+ // FIXME: translate this or not ?
+ QString szName = szItemName;
+ if(szName.isEmpty())
+ KviQString::sprintf(szName,"epilogue_%u_for_%Q",m_pPrologues->count(),&m_szName);
+ m_pEpilogues->append(new KviKvsScript(szName,szCode));
+}
+
+KviKvsPopupMenuTopLevelData * KviKvsPopupMenu::topLevelData()
+{
+ if(parentPopup())return parentPopup()->topLevelData();
+ return m_pTopLevelData;
+}
+
+bool KviKvsPopupMenu::removeItemByName(const QString &szItemName,bool bRecursive)
+{
+ KviKvsScript * se;
+
+ for(se = m_pEpilogues->first();se;se = m_pEpilogues->next())
+ {
+ if(KviQString::equalCI(szItemName,se->name()))
+ {
+ m_pEpilogues->removeRef(se);
+ return true;
+ }
+ }
+
+ for(se = m_pPrologues->first();se;se = m_pPrologues->next())
+ {
+ if(KviQString::equalCI(szItemName,se->name()))
+ {
+ m_pPrologues->removeRef(se);
+ return true;
+ }
+ }
+
+ for(KviKvsPopupMenuItem * it = m_pItemList->first();it;it = m_pItemList->next())
+ {
+ if(KviQString::equalCI(szItemName,it->name()))
+ {
+ m_pItemList->removeRef(it); // bye :)
+ return true;
+ }
+ }
+
+ if(bRecursive)
+ {
+ for(KviKvsPopupMenuItem * ii = m_pItemList->first();ii;ii = m_pItemList->next())
+ {
+ if(ii->isMenu())
+ {
+ if(((KviKvsPopupMenuItemMenu *)ii)->menu())
+ {
+ bool bRet = ((KviKvsPopupMenuItemMenu *)ii)->menu()->removeItemByName(szItemName,true);
+ if(bRet)return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+bool KviKvsPopupMenu::isLocked()
+{
+ if(topLevelPopup()->isVisible())return true;
+ KviKvsPopupMenuTopLevelData * d = topLevelData();
+ return d ? d->isLocked() : false;
+}
+
+
+KviKvsPopupMenu * KviKvsPopupMenu::topLevelPopup()
+{
+ if(parentPopup())return parentPopup();
+ return this;
+}
+
+
+KviKvsPopupMenu * KviKvsPopupMenu::addPopup(const QString &szItemName,const QString &szText,const QString &szIcon,const QString &szCondition)
+{
+ QString szName = szItemName;
+ if(szName.isEmpty())
+ KviQString::sprintf(szName,"%Q.subpopup%d",&m_szName,m_pItemList->count());
+ KviKvsPopupMenu * pNew = new KviKvsPopupMenu(szName);
+ pNew->setParentPopup(this);
+ addItemInternal(new KviKvsPopupMenuItemMenu(szName,pNew,szText,szIcon,szCondition));
+ return pNew;
+}
+
+void KviKvsPopupMenu::addSeparator(const QString &szItemName,const QString &szCondition)
+{
+ QString szName = szItemName;
+ if(szName.isEmpty())
+ KviQString::sprintf(szName,"%Q.separator%d",&m_szName,m_pItemList->count());
+ addItemInternal(new KviKvsPopupMenuItemSeparator(szName,szCondition));
+}
+
+void KviKvsPopupMenu::addLabel(const QString &szItemName,const QString &szText,const QString &szIcon,const QString &szCondition)
+{
+ QString szName = szItemName;
+ if(szName.isEmpty())
+ KviQString::sprintf(szName,"%Q.label%d",&m_szName,m_pItemList->count());
+ addItemInternal(new KviKvsPopupMenuItemLabel(szName,szText,szIcon,szCondition));
+}
+
+void KviKvsPopupMenu::addItem(const QString &szItemName,const QString &szCode,const QString &szText,const QString &szIcon,const QString &szCondition)
+{
+ QString szName = szItemName;
+ if(szName.isEmpty())
+ KviQString::sprintf(szName,"%Q.item%d",&m_szName,m_pItemList->count());
+ addItemInternal(new KviKvsPopupMenuItemItem(szName,szCode,szText,szIcon,szCondition));
+
+}
+
+void KviKvsPopupMenu::addExtPopup(const QString &szItemName,const QString &szPopupName,const QString szText,const QString &szIcon,const QString &szCondition)
+{
+ QString szName = szItemName;
+ if(szName.isEmpty())
+ KviQString::sprintf(szName,"%Q.%Q",&m_szName,&szName);
+ addItemInternal(new KviKvsPopupMenuItemExtMenu(szName,szPopupName,szText,szIcon,szCondition));
+
+}
+
+void KviKvsPopupMenu::addItemInternal(KviKvsPopupMenuItem * it)
+{
+ if(isLocked())debug("Ooops... KviKvsPopupMenu is locked in ::addItem()");
+ m_pItemList->append(it);
+}
+
+void KviKvsPopupMenu::doPopup(const QPoint & pnt,KviWindow * wnd,KviKvsVariantList * pParams,bool bTestMode)
+{
+ // This might be a compat problem later :(((((
+ // it is also an ugly trick
+ clearMenuContents();
+ m_pTempTopLevelData = new KviKvsPopupMenuTopLevelData(pParams,wnd);
+ m_pTempTopLevelData->setTestMode(bTestMode);
+ KviTalPopupMenu::popup(pnt);
+}
+
+void KviKvsPopupMenu::clearMenuContents()
+{
+ m_bSetupDone = false;
+
+ clear();
+
+ for(KviKvsPopupMenuItem * it = m_pItemList->first();it;it = m_pItemList->next())
+ {
+ it->clear();
+ }
+
+ if(m_pTopLevelData)
+ {
+ delete m_pTopLevelData;
+ m_pTopLevelData = 0;
+ }
+ if(m_pTempTopLevelData)
+ {
+ delete m_pTempTopLevelData;
+ m_pTempTopLevelData = 0;
+ }
+}
+
+void KviKvsPopupMenu::doClear()
+{
+ clear();
+ if(m_pTopLevelData)
+ {
+ delete m_pTopLevelData;
+ m_pTopLevelData = 0;
+ }
+ if(m_pTempTopLevelData)
+ {
+ delete m_pTempTopLevelData;
+ m_pTempTopLevelData = 0;
+ }
+ m_bSetupDone = false;
+ m_pItemList->clear();
+
+ m_pPrologues->clear();
+ m_pEpilogues->clear();
+}
+
+
+void KviKvsPopupMenu::lock(bool bLock)
+{
+ KviKvsPopupMenuTopLevelData * d = topLevelData();
+ if(!d)return;
+ d->setLocked(bLock);
+}
+
+
+void KviKvsPopupMenu::setupMenuContents()
+{
+ // This might be a compat problem later :((((
+ if(parentPopup() == 0)
+ {
+ if(m_pTempTopLevelData == 0)
+ {
+ // We have been called by a KviMenuBar!
+ // m_bSetupDone is not valid here
+ clearMenuContents();
+ m_pTopLevelData = new KviKvsPopupMenuTopLevelData(new KviKvsVariantList(),g_pActiveWindow);
+ } else {
+ if(m_bSetupDone)return;
+ // we have been called by doPopup
+ // the menu contents have been already cleared
+ if(m_pTopLevelData)debug("Ops.. something got messed in KviKvsPopupMenu activation system");
+ // Swap the top level data from temporary to the permanent
+ m_pTopLevelData = m_pTempTopLevelData;
+ m_pTempTopLevelData = 0;
+ }
+ } else {
+ if(m_bSetupDone)return;
+ }
+
+ m_bSetupDone = true;
+
+
+ // HACK...this is to remove the separator inserted by Qt when popup() is called and the popup is empty
+ clear();
+
+ KviKvsPopupMenuTopLevelData * d = topLevelData();
+ if(!d)
+ {
+ debug("Ops...menu contents changed behind my back!");
+ return;
+ }
+
+
+ lock(true);
+
+
+ if(!g_pApp->windowExists(d->window()))d->setWindow(g_pApp->activeConsole());
+
+ if(!d->testMode())
+ executePrologues(d);
+
+ // Fill this menu contents
+ int idx = 0;
+ for(KviKvsPopupMenuItem * it = m_pItemList->first();it;it = m_pItemList->next())
+ {
+ it->fill(this,d,idx);
+ ++idx;
+ }
+
+ if(!d->testMode())
+ executeEpilogues(d);
+
+ lock(false);
+
+}
+
+void KviKvsPopupMenu::executePrologues(KviKvsPopupMenuTopLevelData * pData)
+{
+ for(KviKvsScript * s = m_pPrologues->first();s;s = m_pPrologues->next())
+ {
+ if(!s->run(pData->window(),
+ pData->parameters(),
+ 0,
+ KviKvsScript::PreserveParams,
+ pData->extendedRunTimeData()))
+ {
+ pData->window()->output(KVI_OUT_PARSERWARNING,__tr2qs("Broken prologue in popup menu '%Q': ignoring"),&m_szName);
+ }
+ }
+}
+
+void KviKvsPopupMenu::executeEpilogues(KviKvsPopupMenuTopLevelData * pData)
+{
+ for(KviKvsScript * s = m_pEpilogues->first();s;s = m_pEpilogues->next())
+ {
+ if(!s->run(pData->window(),
+ pData->parameters(),
+ 0,
+ KviKvsScript::PreserveParams,
+ pData->extendedRunTimeData()))
+ {
+ pData->window()->output(KVI_OUT_PARSERWARNING,__tr2qs("Broken epilogue in popup menu '%Q': ignoring"),&m_szName);
+ }
+ }
+}
+
+
+void KviKvsPopupMenu::itemClicked(int itemId)
+{
+ int param = itemParameter(itemId);
+ KviKvsPopupMenuItem * it = m_pItemList->at(param);
+ KviKvsPopupMenuTopLevelData * d = topLevelData();
+ if(it && d)
+ {
+ if(it->isItem())
+ {
+ if(d->testMode())
+ {
+ emit testModeItemClicked(it);
+ } else {
+ // rebind if window is lost
+ if(!g_pApp->windowExists(d->window()))d->setWindow(g_pApp->activeConsole());
+ // FIXME: we could avoid locking since scripts can be shared now!
+ // see KviKvsTimerManager implementation
+ lock(true);
+ ((KviKvsPopupMenuItemItem *)it)->kvsCode()->run(
+ d->window(),
+ d->parameters(),
+ 0,
+ KviKvsScript::PreserveParams,
+ d->extendedRunTimeData());
+ // FIXME: should we print somethng if run() returns false ?
+ lock(false);
+ }
+ } else debug("oops....clicked something that is not an item at position %d",param);
+ // FIXME: #warning "Maybe tell that the window has changed"
+ } else debug("oops....no menu item at position %d",param);
+ // UGLY Qt 3.0.0.... we can't clear menu contents here :(
+//#if QT_VERSION < 300
+// topLevelPopup()->clearMenuContents();
+//#endif
+}
+
+
+void KviKvsPopupMenu::load(const QString &prefix,KviConfig * cfg)
+{
+ doClear();
+
+ int cnt;
+ int idx;
+
+ QString tmp = prefix;
+ tmp.append("_PrologueCount");
+
+ cnt = cfg->readIntEntry(tmp,0);
+
+ if(cnt > 0)
+ {
+ for(idx = 0;idx < cnt;idx++)
+ {
+ KviQString::sprintf(tmp,"%Q_Prologue%d",&(prefix),idx);
+ QString pr = cfg->readQStringEntry(tmp,"");
+ KviQString::sprintf(tmp,"%Q_PrologueId%d",&(prefix),idx);
+ QString itemName = cfg->readQStringEntry(tmp,"");
+ if(!pr.isEmpty())addPrologue(itemName,pr);
+ }
+ } else {
+ // Might be old version!
+ KviQString::sprintf(tmp,"%Q_Prologue",&(prefix));
+ QString pr = cfg->readQStringEntry(tmp,"");
+ if(!pr.isEmpty())addPrologue(QString::null,pr);
+ }
+
+ KviQString::sprintf(tmp,"%Q_EpilogueCount",&prefix);
+ cnt = cfg->readIntEntry(tmp,0);
+
+ if(cnt > 0)
+ {
+ for(idx = 0;idx < cnt;idx++)
+ {
+ KviQString::sprintf(tmp,"%Q_Epilogue%d",&prefix,idx);
+ QString ep = cfg->readQStringEntry(tmp,"");
+ KviQString::sprintf(tmp,"%Q_PrologueId%d",&(prefix),idx);
+ QString itemName = cfg->readQStringEntry(tmp,"");
+ if(!ep.isEmpty())addEpilogue(itemName,ep);
+ }
+ } else {
+ // Might be old version!
+ KviQString::sprintf(tmp,"%Q_Epilogue",&prefix);
+ QString ep = cfg->readQStringEntry(tmp,"");
+ if(!ep.isEmpty())addEpilogue(QString::null,ep);
+ }
+
+
+ KviQString::sprintf(tmp,"%Q_Count",&prefix);
+
+ cnt = cfg->readIntEntry(tmp,0);
+
+ for(idx = 0;idx < cnt;idx++)
+ {
+ QString pre;
+ KviQString::sprintf(pre,"%Q_%d",&prefix,idx);
+
+ KviQString::sprintf(tmp,"%Q_Id",&pre);
+ QString itemName = cfg->readQStringEntry(tmp,QString::null);
+ KviQString::sprintf(tmp,"%Q_Type",&pre);
+
+ int type = cfg->readIntEntry(tmp,3);
+ switch(type)
+ {
+ case 0: // separator
+ {
+ QString expr;
+ KviQString::sprintf(tmp,"%Q_Expr",&pre);
+ expr = cfg->readQStringEntry(tmp,"");
+ addSeparator(itemName,expr);
+ }
+ break;
+ case 1: // item
+ {
+ QString text,icon,code,expr;
+ KviQString::sprintf(tmp,"%Q_Text",&pre);
+ text = cfg->readQStringEntry(tmp,"Unnamed");
+ KviQString::sprintf(tmp,"%Q_Icon",&pre);
+ icon = cfg->readQStringEntry(tmp,"");
+ KviQString::sprintf(tmp,"%Q_Code",&pre);
+ code = cfg->readQStringEntry(tmp,"");
+ KviQString::sprintf(tmp,"%Q_Expr",&pre);
+ expr = cfg->readQStringEntry(tmp,"");
+ addItem(itemName,code,text,icon,expr);
+ }
+ break;
+ case 2: // menu
+ {
+ QString text,icon,expr;
+ KviQString::sprintf(tmp,"%Q_Text",&pre);
+ text = cfg->readQStringEntry(tmp,"Unnamed");
+ KviQString::sprintf(tmp,"%Q_Icon",&pre);
+ icon = cfg->readQStringEntry(tmp,"");
+ KviQString::sprintf(tmp,"%Q_Expr",&pre);
+ expr = cfg->readQStringEntry(tmp,"");
+ KviKvsPopupMenu * pop = addPopup(itemName,text,icon,expr);
+ pop->load(pre,cfg);
+ }
+ break;
+ case 3: // label
+ {
+ QString text,icon,expr;
+ KviQString::sprintf(tmp,"%Q_Text",&pre);
+ text = cfg->readQStringEntry(tmp,"Unnamed");
+ KviQString::sprintf(tmp,"%Q_Icon",&pre);
+ icon = cfg->readQStringEntry(tmp,"");
+ KviQString::sprintf(tmp,"%Q_Expr",&pre);
+ expr = cfg->readQStringEntry(tmp,"");
+ addLabel(itemName,text,icon,expr);
+ }
+ break;
+ case 4: // extmenu
+ {
+ QString text,icon,code,expr;
+ KviQString::sprintf(tmp,"%Q_Text",&pre);
+ text = cfg->readQStringEntry(tmp,"Unnamed");
+ KviQString::sprintf(tmp,"%Q_Icon",&pre);
+ icon = cfg->readQStringEntry(tmp,"");
+ KviQString::sprintf(tmp,"%Q_ExtName",&pre);
+ code = cfg->readQStringEntry(tmp,"");
+ KviQString::sprintf(tmp,"%Q_Expr",&pre);
+ expr = cfg->readQStringEntry(tmp,"");
+ addExtPopup(itemName,code,text,icon,expr);
+ }
+ break;
+ default: // ignore
+ break;
+ }
+ }
+
+}
+
+// FIXME: #warning "NOBODY EDITS THE POPUPS IN THE CONFIG!...A binary config would be faster and work better for sure here"
+
+void KviKvsPopupMenu::save(const QString & prefix,KviConfig * cfg)
+{
+ int idx;
+
+ KviKvsScript * s;
+ QString tmp;
+
+ KviQString::sprintf(tmp,"%Q_PrologueCount",&prefix);
+ cfg->writeEntry(tmp,m_pPrologues->count());
+
+ idx = 0;
+ for(s = m_pPrologues->first();s;s = m_pPrologues->next())
+ {
+ KviQString::sprintf(tmp,"%Q_Prologue%d",&prefix,idx);
+ cfg->writeEntry(tmp,s->code());
+ KviQString::sprintf(tmp,"%Q_PrologueId%d",&prefix,idx);
+ cfg->writeEntry(tmp,s->name());
+ idx++;
+ }
+
+ KviQString::sprintf(tmp,"%Q_EpilogueCount",&prefix);
+ cfg->writeEntry(tmp,m_pEpilogues->count());
+
+ idx = 0;
+ for(s = m_pEpilogues->first();s;s = m_pEpilogues->next())
+ {
+ KviQString::sprintf(tmp,"%Q_Epilogue%d",&prefix,idx);
+ cfg->writeEntry(tmp,s->code());
+ KviQString::sprintf(tmp,"%Q_EpilogueId%d",&prefix,idx);
+ cfg->writeEntry(tmp,s->name());
+ idx++;
+ }
+
+ KviQString::sprintf(tmp,"%Q_Count",&prefix);
+ cfg->writeEntry(tmp,m_pItemList->count());
+ idx = 0;
+
+
+ for(KviKvsPopupMenuItem * it = m_pItemList->first();it;it = m_pItemList->next())
+ {
+ QString pre;
+ KviQString::sprintf(pre,"%Q_%d",&prefix,idx);
+ KviQString::sprintf(tmp,"%Q_Type",&pre);
+ int typeCode = 0;
+ switch(it->type())
+ {
+ case KviKvsPopupMenuItem::Label: typeCode = 3; break;
+ case KviKvsPopupMenuItem::Separator: typeCode = 0; break;
+ case KviKvsPopupMenuItem::Menu: typeCode = 2; break;
+ case KviKvsPopupMenuItem::Item: typeCode = 1; break;
+ case KviKvsPopupMenuItem::ExtMenu: typeCode = 4; break;
+ }
+
+ cfg->writeEntry(tmp,typeCode);
+
+ KviQString::sprintf(tmp,"%Q_Id",&pre);
+ cfg->writeEntry(tmp,it->name());
+
+ s = it->kvsCondition();
+ if(s)
+ {
+ KviQString::sprintf(tmp,"%Q_Expr",&pre);
+ cfg->writeEntry(tmp,s->code());
+ }
+
+ s = it->kvsIcon();
+ if(s)
+ {
+ KviQString::sprintf(tmp,"%Q_Icon",&pre);
+ cfg->writeEntry(tmp,s->code());
+ }
+
+ s = it->kvsText();
+ if(s)
+ {
+ KviQString::sprintf(tmp,"%Q_Text",&pre);
+ cfg->writeEntry(tmp,s->code());
+ }
+
+ s = it->kvsCode();
+ if(s)
+ {
+ KviQString::sprintf(tmp,"%Q_Code",&pre);
+ cfg->writeEntry(tmp,s->code());
+ }
+
+ if(it->isMenu())
+ {
+ ((KviKvsPopupMenuItemMenu *)it)->menu()->save(pre,cfg);
+ } else if(it->isExtMenu())
+ {
+ KviQString::sprintf(tmp,"%Q_ExtName",&pre);
+ cfg->writeEntry(tmp,((KviKvsPopupMenuItemExtMenu *)it)->extName());
+ }
+
+ ++idx;
+ }
+}
+
+void KviKvsPopupMenu::generateDefPopupCore(QString &buffer)
+{
+
+ QString tmp;
+
+ buffer = "";
+
+ KviKvsScript * s;
+
+ for(s = m_pPrologues->first();s;s = m_pPrologues->next())
+ {
+ buffer.append("prologue\n");
+ tmp = s->code();
+ tmp.stripWhiteSpace();
+ KviCommandFormatter::blockFromBuffer(tmp);
+ buffer.append(tmp);
+ buffer.append('\n');
+ }
+
+ for(KviKvsPopupMenuItem * it = m_pItemList->first();it;it = m_pItemList->next())
+ {
+ switch(it->type())
+ {
+ case KviKvsPopupMenuItem::Item:
+ if(it->kvsIcon())KviQString::appendFormatted(buffer,"item(%Q,%Q)",&(it->kvsText()->code()),&(it->kvsIcon()->code()));
+ else KviQString::appendFormatted(buffer,"item(%Q)",&(it->kvsText()->code()));
+ if(it->kvsCondition())KviQString::appendFormatted(buffer," (%Q)",&(it->kvsCondition()->code()));
+ buffer.append("\n");
+ tmp = it->kvsCode()->code();
+ KviCommandFormatter::blockFromBuffer(tmp);
+ buffer.append(tmp);
+ buffer.append("\n");
+ break;
+ case KviKvsPopupMenuItem::Menu:
+ if(it->kvsIcon())KviQString::appendFormatted(buffer,"popup(%Q,%Q)",&(it->kvsText()->code()),&(it->kvsIcon()->code()));
+ else KviQString::appendFormatted(buffer,"popup(%Q)",&(it->kvsText()->code()));
+ if(it->kvsCondition())KviQString::appendFormatted(buffer," (%Q)",&(it->kvsCondition()->code()));
+ buffer.append("\n");
+ ((KviKvsPopupMenuItemMenu *)it)->menu()->generateDefPopupCore(tmp);
+ KviCommandFormatter::blockFromBuffer(tmp);
+ buffer.append(tmp);
+ buffer.append("\n");
+ break;
+ case KviKvsPopupMenuItem::Separator:
+ if(it->kvsCondition())KviQString::appendFormatted(buffer,"separator(%Q)\n\n",&(it->kvsCondition()->code()));
+ else buffer.append("separator\n\n");
+ break;
+ case KviKvsPopupMenuItem::Label:
+ if(it->kvsIcon())KviQString::appendFormatted(buffer,"label(%Q,%Q)",&(it->kvsText()->code()),&(it->kvsIcon()->code()));
+ else KviQString::appendFormatted(buffer,"label(%Q)",&(it->kvsText()->code()));
+ if(it->kvsCondition())KviQString::appendFormatted(buffer," (%Q)",&(it->kvsCondition()->code()));
+ buffer.append("\n\n");
+ break;
+ case KviKvsPopupMenuItem::ExtMenu:
+ if(it->kvsIcon())KviQString::appendFormatted(buffer,"extpopup(%Q,%Q,%Q)",&(it->kvsText()->code()),&(((KviKvsPopupMenuItemExtMenu *)it)->extName()),&(it->kvsIcon()->code()));
+ else KviQString::appendFormatted(buffer,"extpopup(%Q)",&(it->kvsText()->code()));
+ if(it->kvsCondition())KviQString::appendFormatted(buffer," (%Q)",&(it->kvsCondition()->code()));
+ buffer.append("\n\n");
+ break;
+ }
+ }
+
+ for(s = m_pEpilogues->first();s;s = m_pEpilogues->next())
+ {
+ buffer.append("epilogue\n");
+ tmp = s->code();
+ tmp.stripWhiteSpace();
+ KviCommandFormatter::blockFromBuffer(tmp);
+ buffer.append(tmp);
+ buffer.append('\n');
+ }
+
+}
+
+void KviKvsPopupMenu::generateDefPopup(QString &buffer)
+{
+ KviQString::sprintf(buffer,"defpopup(%s)\n",name());
+ QString core;
+
+ generateDefPopupCore(core);
+ KviCommandFormatter::blockFromBuffer(core);
+ buffer.append(core);
+}
+
+
+
+
+
+
diff --git a/src/kvirc/kvs/kvi_kvs_popupmenu.h b/src/kvirc/kvs/kvi_kvs_popupmenu.h
new file mode 100644
index 00000000..e658495a
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_popupmenu.h
@@ -0,0 +1,300 @@
+#ifndef _KVI_KVS_POPUPMENU_H_
+#define _KVI_KVS_POPUPMENU_H_
+//=============================================================================
+//
+// File : kvi_kvs_popupmenu.h
+// Created on Wed 07 Jan 2004 05:02:57 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_window.h"
+#include "kvi_kvs_hash.h"
+#include "kvi_kvs_variantlist.h"
+#include "kvi_kvs_script.h"
+#include "kvi_kvs_runtimecontext.h"
+
+#include "kvi_tal_popupmenu.h"
+#include <qlabel.h>
+#include <qpixmap.h>
+
+class KviKvsPopupMenu;
+
+class KVIRC_API KviKvsPopupMenuTopLevelData
+{
+ friend class KviKvsPopupMenu;
+public:
+ KviKvsPopupMenuTopLevelData(KviKvsVariantList * pParameters,KviWindow * pWindow);
+ ~KviKvsPopupMenuTopLevelData();
+protected:
+ KviKvsExtendedRunTimeData * m_pExtendedRunTimeData;
+ KviKvsVariantList * m_pParameters;
+ KviWindow * m_pWindow;
+ bool m_bLocked;
+ bool m_bTestMode;
+public:
+ KviKvsExtendedRunTimeData * extendedRunTimeData(){ return m_pExtendedRunTimeData; };
+ //KviKvsHash * extScopeVariables(){ return m_pExtScopeVariables; };
+ KviKvsVariantList * parameters(){ return m_pParameters; };
+ bool isLocked(){ return m_bLocked; };
+ void setLocked(bool bLocked){ m_bLocked = bLocked; };
+ KviWindow * window(){ return m_pWindow; };
+ void setWindow(KviWindow * pWindow){ m_pWindow = pWindow; };
+ bool testMode(){ return m_bTestMode; };
+ void setTestMode(bool bTestMode){ m_bTestMode = bTestMode; };
+};
+
+
+class KVIRC_API KviKvsPopupMenuItem
+{
+ friend class KviKvsPopupMenu;
+public:
+ enum Type { Item , Menu , Label , Separator , ExtMenu };
+protected:
+ KviKvsPopupMenuItem(Type t,const QString &szItemName,const QString &szCondition);
+ KviKvsPopupMenuItem(Type t,const QString &szItemName,const KviKvsScript * pCondition);
+public:
+ virtual ~KviKvsPopupMenuItem();
+protected:
+ QString m_szItemName;
+ Type m_eType;
+ KviKvsScript * m_pKvsCondition;
+public:
+ // this doesn't trigger errors, only warnings
+ bool evaluateCondition(KviKvsPopupMenuTopLevelData * pData);
+
+ KviKvsPopupMenuItem::Type type(){ return m_eType; };
+
+ const QString & name(){ return m_szItemName; };
+
+ bool isItem(){ return m_eType == Item; };
+ bool isSeparator(){ return m_eType == Separator; };
+ bool isLabel(){ return m_eType == Label; };
+ bool isExtMenu(){ return m_eType == ExtMenu; };
+ bool isMenu(){ return m_eType == Menu; };
+
+ KviKvsScript * kvsCondition(){ return m_pKvsCondition; };
+ virtual KviKvsScript * kvsIcon();
+ virtual KviKvsScript * kvsText();
+ virtual KviKvsScript * kvsCode();
+
+
+ virtual void fill(KviKvsPopupMenu * pMenu,KviKvsPopupMenuTopLevelData * pData,int iIdx) = 0;
+ virtual void clear();
+ virtual KviKvsPopupMenuItem * clone() const = 0;
+};
+
+
+class KVIRC_API KviKvsPopupMenuItemSeparator : public KviKvsPopupMenuItem
+{
+ friend class KviKvsPopupMenu;
+protected:
+ KviKvsPopupMenuItemSeparator(const QString &szItemName,const QString &szCondition);
+ KviKvsPopupMenuItemSeparator(const QString &szItemName,const KviKvsScript * pCondition);
+public:
+ virtual ~KviKvsPopupMenuItemSeparator();
+public:
+ virtual void fill(KviKvsPopupMenu * pMenu,KviKvsPopupMenuTopLevelData * pData,int iIdx);
+ virtual KviKvsPopupMenuItem * clone() const;
+};
+
+
+class KVIRC_API KviKvsPopupMenuItemWithTextAndIcon : public KviKvsPopupMenuItem
+{
+protected:
+ KviKvsPopupMenuItemWithTextAndIcon(KviKvsPopupMenuItem::Type t,const QString &szItemName,const QString &szText,const QString &szIcon,const QString &szCondition);
+ KviKvsPopupMenuItemWithTextAndIcon(KviKvsPopupMenuItem::Type t,const QString &szItemName,const KviKvsScript * pText,const KviKvsScript * pIcon,const KviKvsScript * pCondition);
+public:
+ virtual ~KviKvsPopupMenuItemWithTextAndIcon();
+protected:
+ KviKvsScript * m_pKvsText;
+ KviKvsScript * m_pKvsIcon;
+public:
+ virtual KviKvsScript * kvsIcon();
+ virtual KviKvsScript * kvsText();
+ // this just returns a string , eventually empty
+ QString evaluateText(KviKvsPopupMenuTopLevelData * pData);
+ // this just returns the icon , eventually
+ QPixmap * evaluateIcon(KviKvsPopupMenuTopLevelData * pData);
+};
+
+class KviKvsPopupMenuItemLabel;
+
+// this acts as signal relay
+class KVIRC_API KviKvsPopupMenuItemLabelHelper : public QObject
+{
+ Q_OBJECT
+ friend class KviKvsPopupMenuItemLabel;
+protected:
+ KviKvsPopupMenuItemLabelHelper(KviKvsPopupMenuItemLabel * pItem);
+ ~KviKvsPopupMenuItemLabelHelper();
+protected:
+ KviKvsPopupMenuItemLabel * m_pItem;
+protected slots:
+ void labelDestroyed();
+};
+
+class KVIRC_API KviKvsPopupMenuItemLabel : public KviKvsPopupMenuItemWithTextAndIcon
+{
+ friend class KviKvsPopupMenuItemLabelHelper;
+ friend class KviKvsPopupMenu;
+protected:
+ KviKvsPopupMenuItemLabel(const QString &szItemName,const QString &szText,const QString &szIcon,const QString &szCondition);
+ KviKvsPopupMenuItemLabel(const QString &szItemName,const KviKvsScript * pText,const KviKvsScript * pIcon,const KviKvsScript * pCondition);
+public:
+ virtual ~KviKvsPopupMenuItemLabel();
+protected:
+ QLabel * m_pLabel;
+ KviKvsPopupMenuItemLabelHelper * m_pSignalRelay;
+public:
+ virtual void fill(KviKvsPopupMenu * pMenu,KviKvsPopupMenuTopLevelData * pData,int iIdx);
+ virtual KviKvsPopupMenuItem * clone() const;
+ virtual void clear();
+protected:
+ void labelDestroyed();
+};
+
+
+class KVIRC_API KviKvsPopupMenuItemItem : public KviKvsPopupMenuItemWithTextAndIcon
+{
+ friend class KviKvsPopupMenu;
+protected:
+ KviKvsPopupMenuItemItem(const QString &szItemName,const QString &szCode,const QString &szText,const QString &szIcon,const QString &szCondition);
+ KviKvsPopupMenuItemItem(const QString &szItemName,const KviKvsScript * pCode,const KviKvsScript * pText,const KviKvsScript * pIcon,const KviKvsScript * pCondition);
+public:
+ virtual ~KviKvsPopupMenuItemItem();
+protected:
+ KviKvsScript * m_pKvsCode;
+protected:
+ virtual KviKvsScript * kvsCode();
+public:
+ virtual void fill(KviKvsPopupMenu * pMenu,KviKvsPopupMenuTopLevelData * pData,int iIdx);
+ virtual KviKvsPopupMenuItem * clone() const;
+};
+
+class KVIRC_API KviKvsPopupMenuItemMenu : public KviKvsPopupMenuItemWithTextAndIcon
+{
+ friend class KviKvsPopupMenu;
+protected:
+ KviKvsPopupMenuItemMenu(const QString &szItemName,KviKvsPopupMenu * pMenu,const QString &szText,const QString &szIcon,const QString &szCondition);
+ KviKvsPopupMenuItemMenu(const QString &szItemName,KviKvsPopupMenu * pMenu,const KviKvsScript * pText,const KviKvsScript * pIcon,const KviKvsScript * pCondition);
+public:
+ virtual ~KviKvsPopupMenuItemMenu();
+protected:
+ KviKvsPopupMenu * m_pMenu;
+public:
+ KviKvsPopupMenu * menu(){ return m_pMenu; };
+ virtual void fill(KviKvsPopupMenu * pMenu,KviKvsPopupMenuTopLevelData * pData,int iIdx);
+ virtual void clear();
+ virtual KviKvsPopupMenuItem * clone() const;
+};
+
+class KVIRC_API KviKvsPopupMenuItemExtMenu : public KviKvsPopupMenuItemWithTextAndIcon
+{
+ friend class KviKvsPopupMenu;
+protected:
+ KviKvsPopupMenuItemExtMenu(const QString &szItemName,const QString &szMenuName,const QString &szText,const QString &szIcon,const QString &szCondition);
+ KviKvsPopupMenuItemExtMenu(const QString &szItemName,const QString &szMenuName,const KviKvsScript * pText,const KviKvsScript * pIcon,const KviKvsScript * pCondition);
+public:
+ virtual ~KviKvsPopupMenuItemExtMenu();
+protected:
+ QString m_szMenuName;
+ KviKvsPopupMenu * m_pMenu; // owned!
+public:
+ const QString & extName(){ return m_szMenuName; };
+ virtual void fill(KviKvsPopupMenu * pMenu,KviKvsPopupMenuTopLevelData * pData,int iIdx);
+ virtual void clear();
+ virtual KviKvsPopupMenuItem * clone() const;
+};
+
+
+
+
+
+
+
+
+
+
+
+class KVIRC_API KviKvsPopupMenu : public KviTalPopupMenu
+{
+ friend class KviKvsPopupMenuItemMenu;
+ friend class KviKvsPopupManager;
+ friend class KviSinglePopupEditor;
+ Q_OBJECT
+public:
+ KviKvsPopupMenu(const QString &szName);
+ ~KviKvsPopupMenu();
+protected:
+ KviPointerList<KviKvsPopupMenuItem> * m_pItemList;
+private:
+ QString m_szName;
+ KviKvsPopupMenu * m_pParentPopup;
+ KviPointerList<KviKvsScript> * m_pPrologues;
+ KviPointerList<KviKvsScript> * m_pEpilogues;
+ KviKvsPopupMenuTopLevelData * m_pTopLevelData;
+ // this is a temporary used to hack-in the activation from KviMenuBar
+ KviKvsPopupMenuTopLevelData * m_pTempTopLevelData;
+ bool m_bSetupDone;
+public:
+ const QString & popupName(){ return m_szName; };
+ void setPopupName(const QString &szName){ m_szName = szName; };
+ void copyFrom(const KviKvsPopupMenu * src);
+ KviKvsPopupMenuTopLevelData * topLevelData();
+ KviKvsPopupMenu * topLevelPopup();
+ bool isLocked();
+ void lock(bool bLock);
+ KviKvsPopupMenu * addPopup(const QString &szItemName,const QString &szText,const QString &szIcon,const QString &szCondition);
+ void addSeparator(const QString &szItemName,const QString &szCondition);
+ void addLabel(const QString &szItemName,const QString &szText,const QString &szIcon,const QString &szCondition);
+ void addItem(const QString &szItemName,const QString &szCode,const QString &szText,const QString &szIcon,const QString &szCondition);
+ void addExtPopup(const QString &szItemName,const QString &szPopupName,const QString szText,const QString &szIcon,const QString &szCondition);
+ void doPopup(const QPoint & pnt,KviWindow * wnd,KviKvsVariantList * pParams,bool bTestMode = false);
+ bool isEmpty(){ return m_pItemList->isEmpty() && m_pPrologues->isEmpty() && m_pEpilogues->isEmpty(); };
+ void doClear();
+ void addPrologue(const QString &szItemName,const QString &szCode);
+ void addEpilogue(const QString &szItemName,const QString &szCode);
+ bool removeItemByName(const QString &szItemName,bool bRecursive);
+ KviPointerList<KviKvsScript> * epilogues(){ return m_pEpilogues; };
+ KviPointerList<KviKvsScript> * prologues(){ return m_pPrologues; };
+ KviKvsPopupMenu * parentPopup(){ return m_pParentPopup; };
+ void generateDefPopup(QString &buffer);
+ void setParentPopup(KviKvsPopupMenu * par){ m_pParentPopup = par; };
+ void generateDefPopupCore(QString &buffer);
+protected:
+ void addItemInternal(KviKvsPopupMenuItem * it);
+ void executePrologues(KviKvsPopupMenuTopLevelData * pData);
+ void executeEpilogues(KviKvsPopupMenuTopLevelData * pData);
+ void load(const QString &prefix,KviConfig * cfg);
+ void save(const QString &prefix,KviConfig * cfg);
+private slots:
+ void setupMenuContents();
+protected:
+ void clearMenuContents();
+protected slots:
+ void itemClicked(int itemId);
+signals:
+ void testModeItemClicked(KviKvsPopupMenuItem * it);
+};
+
+
+#endif //!_KVI_KVS_POPUPMENU_H_
diff --git a/src/kvirc/kvs/kvi_kvs_processmanager.cpp b/src/kvirc/kvs/kvi_kvs_processmanager.cpp
new file mode 100644
index 00000000..2c397c55
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_processmanager.cpp
@@ -0,0 +1,376 @@
+//=============================================================================
+//
+// File : kvi_kvs_processmanager.cpp
+// Created on Wed 07 Apr 2004 03:03:52 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004-2007 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_processmanager.h"
+#include "kvi_window.h"
+#include "kvi_out.h"
+#include "kvi_locale.h"
+#include "kvi_parameterlist.h"
+#include "kvi_app.h"
+#include "kvi_console.h"
+#include "kvi_kvs_script.h"
+//#include <QSysInfo>
+
+KviKvsProcessAsyncOperation::KviKvsProcessAsyncOperation(KviKvsProcessDescriptorData * d)
+: KviKvsAsyncOperation(d->pWnd)
+{
+ m_pData = d;
+ m_pProcess = 0;
+ m_pExtendedRunTimeData = new KviKvsExtendedRunTimeData(new KviKvsHash(),TRUE);
+ m_pPingTimer = 0;
+ m_pRunTimeTimer = 0;
+ m_bDeletePending = false;
+}
+
+KviKvsProcessAsyncOperation::~KviKvsProcessAsyncOperation()
+{
+ if(m_pPingTimer)delete m_pPingTimer;
+ if(m_pRunTimeTimer)delete m_pRunTimeTimer;
+ if(m_pProcess)
+ {
+ QObject::disconnect(m_pProcess,0,this,0);
+ m_pProcess->kill();
+ delete m_pProcess;
+ }
+ delete m_pExtendedRunTimeData;
+ if(m_pData->pCallback)delete m_pData->pCallback;
+ if(m_pData->pMagic)delete m_pData->pMagic;
+ delete m_pData;
+}
+
+bool KviKvsProcessAsyncOperation::start()
+{
+ QStringList args;
+
+ if(m_pData->iFlags & KVI_KVS_PROCESSDESCRIPTOR_NOSHELL)
+ {
+ args = QStringList::split(" ",m_pData->szCommandline);
+ } else {
+ QString szShell = m_pData->szShell;
+ if(szShell.isEmpty())
+ {
+#ifdef COMPILE_ON_WINDOWS
+ // [01:26:00] <PragmaOff> btw, what is qt_winunicode ?
+ // [01:26:12] <kode54> Qt export specific to win32
+ // [01:26:27] <kode54> bool which indicates whether system is Unicode (NT) or not
+ // [01:26:58] <kode54> not sure if that's documented, but it is a public export
+ //
+ // [02:50:21] <kode54> if ( QApplication::winVersion() & Qt::WV_NT_based )
+ // [02:50:41] <kode54> I see another implementation using that, maybe it is the official way of detecting that :[
+#ifdef COMPILE_USE_QT4
+ szShell = !(QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) ? "cmd.exe /c" : "command.com /c";
+#else
+ szShell = "command.com /c";
+#endif
+
+ // Thnx kode54 :)
+#else
+ szShell = "sh -c";
+#endif
+ }
+ args = QStringList::split(" ",szShell);
+ args.append(m_pData->szCommandline);
+ }
+
+ m_pProcess = new KviProcess(args);
+ int c = KviProcess::Stdin;
+
+ if(m_pData->iFlags & KVI_KVS_PROCESSDESCRIPTOR_TRIGGERSTDOUT)
+ {
+ connect(m_pProcess,SIGNAL(readyReadStdout()),this,SLOT(readStdout()));
+ c |= KviProcess::Stdout;
+ }
+
+ if(m_pData->iFlags & KVI_KVS_PROCESSDESCRIPTOR_TRIGGERSTDERR)
+ {
+ connect(m_pProcess,SIGNAL(readyReadStderr()),this,SLOT(readStderr()));
+ c |= KviProcess::Stderr;
+ }
+
+ m_pProcess->setCommunication(c);
+
+ connect(m_pProcess,SIGNAL(processExited()),this,SLOT(processExited()));
+
+ if(!m_pProcess->start())
+ {
+ return false;
+ }
+
+ if(m_pData->iFlags & KVI_KVS_PROCESSDESCRIPTOR_TRIGGERSTARTED)
+ {
+ QString szPid;
+ szPid.setNum((int)(m_pProcess->processIdentifier()));
+ if(trigger(EventStarted,szPid))
+ {
+ triggerSelfDelete();
+ return true;
+ }
+ }
+
+ if(m_pData->iMaxRunTime > 0)
+ {
+ m_pRunTimeTimer = new QTimer(this);
+ connect(m_pRunTimeTimer,SIGNAL(timeout()),this,SLOT(maxRunTimeExpired()));
+ m_pRunTimeTimer->start(m_pData->iMaxRunTime);
+ }
+
+ if(m_pData->iPingTimeout > 0)
+ {
+ m_pPingTimer = new QTimer(this);
+ connect(m_pPingTimer,SIGNAL(timeout()),this,SLOT(ping()));
+ m_pPingTimer->start(m_pData->iPingTimeout);
+ }
+
+ return true;
+}
+
+void KviKvsProcessAsyncOperation::ping()
+{
+ if(trigger(EventPing,QString::null))
+ {
+ triggerSelfDelete();
+ }
+}
+
+void KviKvsProcessAsyncOperation::triggerSelfDelete()
+{
+ if(m_bDeletePending)return;
+ m_bDeletePending = true;
+ QTimer::singleShot(m_pData->iMaxRunTime,this,SLOT(selfDelete()));
+}
+
+void KviKvsProcessAsyncOperation::selfDelete()
+{
+ delete this;
+}
+
+void KviKvsProcessAsyncOperation::maxRunTimeExpired()
+{
+ trigger(EventTerminated,"0");
+ triggerSelfDelete();
+}
+
+bool KviKvsProcessAsyncOperation::trigger(CallbackEvent e,const QString &szData)
+{
+ if(m_bDeletePending)return false;
+
+ if(!g_pApp->windowExists(m_pData->pWnd))
+ {
+ if(m_pData->iFlags & KVI_KVS_PROCESSDESCRIPTOR_KILLIFNOWINDOW)
+ {
+ return true;
+ }
+ m_pData->pWnd = g_pApp->activeConsole();
+ }
+
+ if(m_pData->pCallback)
+ {
+ KviKvsVariantList params;
+ params.setAutoDelete(true);
+
+ switch(e)
+ {
+ case EventStdout:
+ params.append(new KviKvsVariant(QString("stdout")));
+ break;
+ case EventStderr:
+ params.append(new KviKvsVariant(QString("stderr")));
+ break;
+ case EventTerminated:
+ params.append(new KviKvsVariant(QString("terminated")));
+ break;
+ case EventStarted:
+ params.append(new KviKvsVariant(QString("started")));
+ break;
+ case EventPing:
+ params.append(new KviKvsVariant(QString("ping")));
+ break;
+ default:
+ debug("Ops... unknown trigger() CallbackEvent parameter in KviProcessDescriptor::trigger()");
+ return false;
+ break;
+ }
+
+ params.append(new KviKvsVariant(szData));
+ if (m_pData->pMagic) params.append(m_pData->pMagic);
+
+ KviKvsVariant retVal;
+ int iRet = m_pData->pCallback->run(m_pData->pWnd,&params,&retVal,KviKvsScript::PreserveParams,m_pExtendedRunTimeData);
+ if(!iRet)
+ {
+ m_pData->pWnd->output(KVI_OUT_PARSERERROR,
+ __tr2qs("Error triggered from process callback handler: killing process"));
+ return true;
+ }
+
+ if(!retVal.isNothing())
+ {
+ QString sz;
+ retVal.asString(sz);
+ m_pProcess->writeToStdin(sz);
+ }
+
+ if(iRet & KviKvsScript::HaltEncountered)
+ {
+ // halt encountered: kill the process
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void KviKvsProcessAsyncOperation::readStdout()
+{
+ if(m_bDeletePending)return;
+ if(m_pData->iFlags & KVI_KVS_PROCESSDESCRIPTOR_OUTPUTBYBLOCKS)
+ {
+ QByteArray a = m_pProcess->readStdout();
+ if(a.size() > 0)
+ m_szStdoutBuffer += QString(a);
+ } else {
+ QString l = m_pProcess->readLineStdout();
+ bool bBreak = false;
+ while((!l.isNull()) && (!bBreak))
+ {
+ if(m_pData->iFlags & KVI_KVS_PROCESSDESCRIPTOR_TRIGGERSTDOUT)
+ {
+ if(trigger(EventStdout,l))
+ {
+ bBreak = true;
+ triggerSelfDelete();
+ }
+ }
+
+ l = m_pProcess->readLineStdout();
+ }
+ }
+}
+
+void KviKvsProcessAsyncOperation::readStderr()
+{
+ if(m_bDeletePending)return;
+ if(m_pData->iFlags & KVI_KVS_PROCESSDESCRIPTOR_OUTPUTBYBLOCKS)
+ {
+ QByteArray a = m_pProcess->readStderr();
+ if(a.size() > 0)
+ m_szStderrBuffer += QString(a);
+ } else {
+ QString l = m_pProcess->readLineStderr();
+ bool bBreak = false;
+ while((!l.isNull()) && (!bBreak))
+ {
+ if(m_pData->iFlags & KVI_KVS_PROCESSDESCRIPTOR_TRIGGERSTDERR)
+ {
+ if(trigger(EventStderr,l))
+ {
+ bBreak = true;
+ triggerSelfDelete();
+ }
+ }
+
+ l = m_pProcess->readLineStderr();
+ }
+ }
+}
+
+
+void KviKvsProcessAsyncOperation::processExited()
+{
+ if(m_bDeletePending)return;
+
+ readStdout(); // just to make sure
+ readStderr(); // just to make sure
+
+ if(m_pData->iFlags & KVI_KVS_PROCESSDESCRIPTOR_OUTPUTBYBLOCKS)
+ {
+ // trigger Stdout and Stderr once
+ if(m_pData->iFlags & KVI_KVS_PROCESSDESCRIPTOR_TRIGGERSTDOUT)
+ {
+ if(trigger(EventStdout,m_szStdoutBuffer))
+ {
+ triggerSelfDelete();
+ return;
+ }
+ }
+
+ if(m_pData->iFlags & KVI_KVS_PROCESSDESCRIPTOR_TRIGGERSTDERR)
+ {
+ if(trigger(EventStdout,m_szStderrBuffer))
+ {
+ triggerSelfDelete();
+ return;
+ }
+ }
+ }
+
+ if(m_pData->iFlags & KVI_KVS_PROCESSDESCRIPTOR_TRIGGERTERMINATED)
+ {
+ QString szRetVal;
+ szRetVal.setNum(m_pProcess->exitStatus());
+ trigger(EventTerminated,szRetVal);
+ }
+
+ triggerSelfDelete();
+}
+
+
+/*
+
+KviKvsProcessManager::KviKvsProcessManager()
+: QObject()
+{
+}
+
+KviKvsProcessManager::~KviKvsProcessManager()
+{
+}
+
+void KviKvsProcessManager::init()
+{
+ if(m_pInstance)return;
+ m_pInstance = new KviProcessManager();
+}
+
+void KviKvsProcessManager::done()
+{
+ if(!m_pInstance)return;
+ delete m_pInstance;
+ m_pInstance = 0;
+}
+
+bool KviKvsProcessManager::execute(KviKvsProcessAsyncOperationData * d)
+{
+ KviKvsProcessAsyncOperation * pd = new KviKvsProcessAsyncOperation(d,this);
+ if(!pd->start())
+ {
+ //delete d; <-- delete by KviKvsProcessAsyncOperation
+ delete pd;
+ return false;
+ }
+ return true;
+}
+*/
diff --git a/src/kvirc/kvs/kvi_kvs_processmanager.h b/src/kvirc/kvs/kvi_kvs_processmanager.h
new file mode 100644
index 00000000..50e52ace
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_processmanager.h
@@ -0,0 +1,105 @@
+#ifndef _KVI_KVS_PROCESSMANAGER_H_
+#define _KVI_KVS_PROCESSMANAGER_H_
+//=============================================================================
+//
+// File : kvi_kvs_processmanager.h
+// Created on Wed 07 Apr 2004 03:03:52 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004-2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_kvs_asyncoperation.h"
+#include "kvi_qstring.h"
+#include "kvi_window.h"
+#include "kvi_kvs_variant.h"
+#include "kvi_kvs_runtimecontext.h"
+#include "kvi_kvs_variant.h"
+
+#include "kvi_pointerhashtable.h"
+
+#ifdef Unsorted
+ #undef Unsorted
+#endif
+
+#include "kvi_process.h"
+
+#include <qtimer.h>
+
+#define KVI_KVS_PROCESSDESCRIPTOR_TRIGGERSTDOUT 1
+#define KVI_KVS_PROCESSDESCRIPTOR_TRIGGERSTDERR 2
+#define KVI_KVS_PROCESSDESCRIPTOR_TRIGGERTERMINATED 4
+#define KVI_KVS_PROCESSDESCRIPTOR_OUTPUTBYBLOCKS 8
+#define KVI_KVS_PROCESSDESCRIPTOR_TRIGGERSTARTED 16
+#define KVI_KVS_PROCESSDESCRIPTOR_NOSHELL 32
+#define KVI_KVS_PROCESSDESCRIPTOR_KILLIFNOWINDOW 64
+
+
+class KviWindow;
+class KviKvsScript;
+class KviKvsVariant;
+
+typedef struct _KviKvsProcessDescriptorData
+{
+ QString szShell;
+ QString szCommandline;
+ KviKvsScript * pCallback;
+ KviKvsVariant * pMagic;
+ KviWindow * pWnd;
+ int iFlags;
+ int iMaxRunTime; // 0 for no timeout
+ int iPingTimeout; // 0 for no ping timeout
+} KviKvsProcessDescriptorData;
+
+class KviKvsProcessManager;
+
+class KVIRC_API KviKvsProcessAsyncOperation : public KviKvsAsyncOperation
+{
+ friend class KviKvsProcessManager;
+ Q_OBJECT
+public:
+ KviKvsProcessAsyncOperation(KviKvsProcessDescriptorData * d);
+ ~KviKvsProcessAsyncOperation();
+protected:
+ enum CallbackEvent { EventStarted,EventTerminated,EventStdout,EventStderr,EventPing };
+private:
+ KviProcess * m_pProcess;
+ KviKvsExtendedRunTimeData * m_pExtendedRunTimeData;
+ QString m_szStdoutBuffer;
+ QString m_szStderrBuffer;
+ KviKvsProcessDescriptorData * m_pData;
+ QTimer * m_pPingTimer;
+ QTimer * m_pRunTimeTimer;
+ bool m_bDeletePending;
+public:
+ bool start();
+private slots:
+ void maxRunTimeExpired();
+ void ping();
+ void readStdout();
+ void readStderr();
+ void processExited();
+ void selfDelete();
+private:
+ bool trigger(CallbackEvent e,const QString &szData);
+ void triggerSelfDelete();
+};
+
+
+#endif //!_KVI_KVS_PROCESSMANAGER_H_
diff --git a/src/kvirc/kvs/kvi_kvs_report.cpp b/src/kvirc/kvs/kvi_kvs_report.cpp
new file mode 100644
index 00000000..ea05ba39
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_report.cpp
@@ -0,0 +1,262 @@
+//=============================================================================
+//
+// File : kvi_kvs_report.cpp
+// Creation date : Thu 25 Sep 2003 05.12 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_report.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_window.h"
+#include "kvi_out.h"
+#include "kvi_app.h"
+#include "kvi_locale.h"
+#include "kvi_debugwindow.h"
+#include "kvi_options.h"
+
+KviKvsReport::KviKvsReport(Type t,const QString &szContext,const QString &szMessage,const QString &szLocation,KviWindow * pWindow)
+: m_eType(t), m_szContext(szContext), m_szMessage(szMessage), m_szLocation(szLocation), m_pWindow(pWindow)
+{
+#ifdef COMPILE_NEW_KVS
+ m_pCallStack = 0;
+ m_pCodeListing = 0;
+#endif
+}
+
+KviKvsReport::~KviKvsReport()
+{
+#ifdef COMPILE_NEW_KVS
+ if(m_pCallStack)delete m_pCallStack;
+ if(m_pCodeListing)delete m_pCodeListing;
+#endif
+}
+
+void KviKvsReport::findLineAndCol(const QChar * pBegin,const QChar * pPoint,int &iLine,int &iCol)
+{
+#ifdef COMPILE_NEW_KVS
+ iLine = 1;
+
+ const QChar * pBufferBegin = pBegin;
+
+ const QChar * pPrevLine = 0;
+ const QChar * pLineBegin = pBegin;
+
+ unsigned short us = pBegin->unicode();
+
+ while(us && (pBegin < pPoint))
+ {
+ if(us == '\n')
+ {
+ pPrevLine = pLineBegin;
+ pBegin++;
+ pLineBegin = pBegin;
+ iLine++;
+ } else {
+ pBegin++;
+ }
+ us = pBegin->unicode();
+ }
+
+ iCol = (pBegin - pLineBegin) + 1;
+#endif
+}
+
+
+
+void KviKvsReport::findLineColAndListing(const QChar * pBegin,const QChar * pPoint,int &iLine,int &iCol,KviPointerList<QString> * pListing)
+{
+#ifdef COMPILE_NEW_KVS
+ iLine = 1;
+
+ const QChar * pBufferBegin = pBegin;
+
+ const QChar * pPrevLine = 0;
+ const QChar * pLineBegin = pBegin;
+
+ unsigned short us = pBegin->unicode();
+
+ while(us && (pBegin < pPoint))
+ {
+ if(us == '\n')
+ {
+ pPrevLine = pLineBegin;
+ pBegin++;
+ pLineBegin = pBegin;
+ iLine++;
+ } else {
+ pBegin++;
+ }
+ us = pBegin->unicode();
+ }
+
+ iCol = (pBegin - pLineBegin) + 1;
+
+ // previous line
+ if(pPrevLine)
+ {
+ // there would be yet another line before
+ if(pPrevLine > pBufferBegin)
+ {
+ QString * pListingStrZ = new QString();
+ KviQString::sprintf(*pListingStrZ,"%d ...",iLine - 2);
+ pListing->append(pListingStrZ);
+ }
+
+ QString * pListingStr = new QString();
+ KviQString::sprintf(*pListingStr,"%d ",iLine - 1);
+ *pListingStr += QString(pPrevLine,pLineBegin - pPrevLine);
+ pListingStr->replace("\n","");
+ pListing->append(pListingStr);
+ }
+
+ // current line
+ pBegin = pLineBegin;
+
+ us = pBegin->unicode();
+ while(us && (us != '\n'))
+ {
+ pBegin++;
+ us = pBegin->unicode();
+ }
+ if(us)pBegin++;
+
+ {
+ QString * pListingStr = new QString();
+ KviQString::sprintf(*pListingStr,"%c%d ",KVI_TEXT_BOLD,iLine);
+ *pListingStr += QString(pLineBegin,pBegin - pLineBegin);
+ pListingStr->replace("\n","");
+ pListing->append(pListingStr);
+ }
+
+ if(us)
+ {
+ // next line
+ pLineBegin = pBegin;
+
+ us = pBegin->unicode();
+ while(us && (us != '\n'))
+ {
+ pBegin++;
+ us = pBegin->unicode();
+ }
+ if(us)pBegin++;
+
+ {
+ QString * pListingStr = new QString();
+ KviQString::sprintf(*pListingStr,"%d ",iLine + 1);
+ *pListingStr += QString(pLineBegin,pBegin - pLineBegin);
+ pListingStr->replace("\n","");
+ pListing->append(pListingStr);
+ }
+
+ // there would be yet another line
+ if(us)
+ {
+ QString * pListingStr = new QString();
+ KviQString::sprintf(*pListingStr,"%d ...",iLine + 2);
+ pListing->append(pListingStr);
+ }
+ }
+#endif
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// ERROR REPORTING
+
+void KviKvsReport::report(KviKvsReport * r,KviWindow * pOutput)
+{
+#ifdef COMPILE_NEW_KVS
+ if(!pOutput)return; // ?
+ if(!g_pApp->windowExists(pOutput))
+ {
+ if(KVI_OPTION_BOOL(KviOption_boolScriptErrorsToDebugWindow))
+ {
+ // rethrow to the debug window
+ report(r,KviDebugWindow::getInstance());
+ } // else window lost: unrecoverable
+ return;
+ }
+
+ // make sure that the output window still exists!
+
+ int out;
+
+ switch(r->type())
+ {
+ case KviKvsReport::ParserWarning:
+ out = KVI_OUT_PARSERWARNING;
+ pOutput->output(out,__tr2qs("[KVS]%c Warning: %Q"),KVI_TEXT_BOLD,&(r->message()));
+ break;
+ case KviKvsReport::ParserError:
+ out = KVI_OUT_PARSERERROR;
+ pOutput->output(out,__tr2qs("[KVS]%c Compilation Error: %Q"),KVI_TEXT_BOLD,&(r->message()));
+ break;
+ case KviKvsReport::RunTimeWarning:
+ out = KVI_OUT_PARSERWARNING;
+ pOutput->output(out,__tr2qs("[KVS]%c Warning: %Q"),KVI_TEXT_BOLD,&(r->message()));
+ break;
+ case KviKvsReport::RunTimeError:
+ out = KVI_OUT_PARSERERROR;
+ pOutput->output(out,__tr2qs("[KVS]%c Runtime Error: %Q"),KVI_TEXT_BOLD,&(r->message()));
+ break;
+ }
+
+ if(r->location().isEmpty())
+ pOutput->output(out,__tr2qs("[KVS] in script context \"%Q\""),&(r->context()));
+ else
+ pOutput->output(out,__tr2qs("[KVS] in script context \"%Q\", %Q"),&(r->context()),&(r->location()));
+
+ if(pOutput == KviDebugWindow::instance())
+ {
+ KviPointerList<QString> * l;
+ if(l = r->codeListing())
+ {
+ pOutput->outputNoFmt(out,__tr2qs("[KVS] Code listing:"));
+ for(QString * s = l->first();s;s = l->next())
+ pOutput->output(out,"[KVS] %Q",s);
+ }
+
+ pOutput->output(out,__tr2qs("[KVS] Window:"));
+ if(g_pApp->windowExists(r->window()))
+ pOutput->output(out,"[KVS] %Q [id: %u]",&(r->window()->windowName()),r->window()->numericId());
+ else
+ pOutput->output(out,__tr2qs("[KVS] Destroyed window with pointer %x"),r->window());
+
+ if(l = r->callStack())
+ {
+ pOutput->outputNoFmt(out,__tr2qs("[KVS] Call stack:"));
+ for(QString * s = l->first();s;s = l->next())
+ pOutput->output(out,"[KVS] %Q",s);
+ }
+
+ pOutput->outputNoFmt(out,"[KVS]");
+ } else {
+ if(KVI_OPTION_BOOL(KviOption_boolScriptErrorsToDebugWindow))
+ {
+ // rethrow to the debug window
+ if(pOutput != KviDebugWindow::getInstance())
+ report(r,KviDebugWindow::getInstance());
+ }
+ }
+#endif
+}
+
diff --git a/src/kvirc/kvs/kvi_kvs_report.h b/src/kvirc/kvs/kvi_kvs_report.h
new file mode 100644
index 00000000..335733e0
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_report.h
@@ -0,0 +1,75 @@
+#ifndef _KVI_KVS_REPORT_H_
+#define _KVI_KVS_REPORT_H_
+//=============================================================================
+//
+// File : kvi_kvs_report.h
+// Creation date : Thu 25 Sep 2003 05.12 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_pointerlist.h"
+
+class KviWindow;
+
+class KVIRC_API KviKvsReport
+{
+public:
+ enum Type { RunTimeError, RunTimeWarning, ParserError, ParserWarning };
+public:
+ KviKvsReport(Type t,const QString &szContext,const QString &szMessage,const QString &szLocation,KviWindow * pWindow);
+ ~KviKvsReport();
+protected:
+ Type m_eType;
+
+ // mandatory
+ QString m_szContext; // context name (script name, usually)
+ QString m_szMessage; // report message, always present
+ QString m_szLocation; // line and col description (may be some thing like "at end of input")
+
+ KviWindow * m_pWindow; // the window that the script was attacched to
+
+ // optional
+ KviPointerList<QString> * m_pCodeListing; // code listing, if present, it is owned
+ KviPointerList<QString> * m_pCallStack; // call stack, if present, it is owned
+public:
+ Type type() const { return m_eType; };
+
+ KviWindow * window(){ return m_pWindow; };
+ const QString & context(){ return m_szContext; };
+ const QString & message(){ return m_szMessage; };
+ const QString & location(){ return m_szLocation; };
+ KviPointerList<QString> * codeListing(){ return m_pCodeListing; };
+ KviPointerList<QString> * callStack(){ return m_pCallStack; };
+
+ void setContext(const QString &szContext){ m_szContext = szContext; };
+ void setMessage(const QString &szMessage){ m_szMessage = szMessage; };
+ void setLocation(const QString &szLocation){ m_szLocation = szLocation; };
+ void setCodeListing(KviPointerList<QString> * pListing){ m_pCodeListing = pListing; };
+ void setCallStack(KviPointerList<QString> * pStack){ m_pCallStack = pStack; };
+
+ static void findLineAndCol(const QChar * pBegin,const QChar * pPoint,int &iLine,int &iCol);
+ static void findLineColAndListing(const QChar * pBegin,const QChar * pPoint,int &iLine,int &iCol,KviPointerList<QString> * pListing);
+
+ static void report(KviKvsReport * r,KviWindow * pOutput);
+};
+
+#endif //!_KVI_KVS_REPORT_H_
diff --git a/src/kvirc/kvs/kvi_kvs_runtimecall.cpp b/src/kvirc/kvs/kvi_kvs_runtimecall.cpp
new file mode 100644
index 00000000..faae03ad
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_runtimecall.cpp
@@ -0,0 +1,50 @@
+//=============================================================================
+//
+// File : kvi_kvs_runtimecall.cpp
+// Created on Sat 23 Apr 2005 18:19:38 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_runtimecall.h"
+
+
+void KviKvsRunTimeCall::warning(const QString &szFmt,...)
+{
+ kvi_va_list va;
+ kvi_va_start_by_reference(va,szFmt);
+ m_pContext->report(false,m_pContext->defaultReportLocation(),szFmt,va);
+ kvi_va_end(va);
+}
+
+bool KviKvsRunTimeCall::error(const QString &szFmt,...)
+{
+ kvi_va_list va;
+ kvi_va_start_by_reference(va,szFmt);
+ m_pContext->report(true,m_pContext->defaultReportLocation(),szFmt,va);
+ kvi_va_end(va);
+ return false;
+}
+
+bool KviKvsRunTimeCall::getParameterCode(unsigned int /*uParamIdx*/,QString & /*szParamBuffer*/)
+{
+ return false;
+}
diff --git a/src/kvirc/kvs/kvi_kvs_runtimecall.h b/src/kvirc/kvs/kvi_kvs_runtimecall.h
new file mode 100644
index 00000000..3ead6c3e
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_runtimecall.h
@@ -0,0 +1,82 @@
+#ifndef _KVI_KVS_RUNTIMECALL_H_
+#define _KVI_KVS_RUNTIMECALL_H_
+//=============================================================================
+//
+// File : kvi_kvs_runtimecall.h
+// Created on Sat 23 Apr 2005 18:19:38 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_kvs_runtimecontext.h"
+#include "kvi_kvs_variantlist.h"
+#include "kvi_kvs_variant.h"
+#include "kvi_window.h"
+
+
+class KVIRC_API KviKvsRunTimeCall
+{
+protected:
+ KviKvsRunTimeContext * m_pContext; // shallow
+ KviKvsVariantList * m_pParams; // shallow
+public:
+ KviKvsRunTimeCall(KviKvsRunTimeContext * pContext,KviKvsVariantList * pParams)
+ : m_pContext(pContext),m_pParams(pParams){};
+ virtual ~KviKvsRunTimeCall(){};
+public:
+ // the script runtime context, never zero
+ KviKvsRunTimeContext * context(){ return m_pContext; };
+
+ KviWindow * window(){ return m_pContext->window(); };
+
+ // parameter list access & helpers.. almost unused
+ // because of the KVSM_PARAMETER macros
+ KviKvsVariantList * parameterList(){ return m_pParams; };
+ KviKvsVariantList * params(){ return m_pParams; }; // the short version
+ unsigned int paramCount(){ return m_pParams->count(); };
+ unsigned int parameterCount(){ return m_pParams->count(); };
+ KviKvsVariant * firstParam(){ return m_pParams->first(); };
+ KviKvsVariant * nextParam(){ return m_pParams->next(); };
+
+ // This is virtual and returns false by default
+ // only few derived classes allow the parameter code to be
+ // extracted. This is mainly useful in module callback commands
+ // where a special parsing routine can not be implemented
+ // but parameter code is needed for later evaluation. (see /addon.register for example)
+ // Returns false if the parameter code cannot be extracted and true otherwise.
+ virtual bool getParameterCode(unsigned int uParamIdx,QString &szParamBuffer);
+
+ // forwarders from the context
+ // this MUST be called before any blocking call that might return to the main event loop
+ // and eventually quit kvirc or close the window that this command is associated to
+ // Actually this is a NO-OP but later may really do something that avoids kvirc to crash
+ void enterBlockingSection(){ m_pContext->enterBlockingSection(); };
+ // this MUST be called after exiting the blocking section above
+ // if this function returns false your parsing code MUST "return false" immediately:
+ // it means that something rather critical happened and the script
+ // execution cannot continue
+ bool leaveBlockingSection(){ return m_pContext->leaveBlockingSection(); };
+
+ // forwarders for context: they ease the porting
+ void warning(const QString &szFmt,...);
+ bool error(const QString &szFmt,...); // this ALWAYS returns false
+};
+
+#endif //!_KVI_KVS_RUNTIMECALL_H_
diff --git a/src/kvirc/kvs/kvi_kvs_runtimecontext.cpp b/src/kvirc/kvs/kvi_kvs_runtimecontext.cpp
new file mode 100644
index 00000000..47916f9f
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_runtimecontext.cpp
@@ -0,0 +1,206 @@
+//=============================================================================
+//
+// File : kvi_kvs_runtimecontext.cpp
+// Created on Tue 07 Oct 2003 01:49:40 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_runtimecontext.h"
+#include "kvi_kvs_script.h"
+#include "kvi_kvs_kernel.h"
+#include "kvi_kvs_report.h"
+#include "kvi_console.h"
+#include "kvi_kvs_treenode_base.h"
+#include "kvi_locale.h"
+#include "kvi_app.h"
+#include "kvi_kvs_object.h"
+
+KviKvsExtendedRunTimeData::~KviKvsExtendedRunTimeData()
+{
+ if(m_bAutoDelete)
+ {
+ if(m_pExtendedScopeVariables) delete m_pExtendedScopeVariables;
+ if(m_pAliasSwitchList) delete m_pAliasSwitchList;
+ if(m_pThisObject) delete m_pThisObject;
+ if(m_pScriptFilePath) delete m_pScriptFilePath;
+ }
+}
+
+KviKvsRunTimeContext::KviKvsRunTimeContext(KviKvsScript * pScript,KviWindow * pWnd,KviKvsVariantList * pParams,KviKvsVariant * pRetVal,KviKvsExtendedRunTimeData * pExtData)
+{
+ m_bError = false;
+ m_pScript = pScript;
+ m_pParameterList = pParams;
+ m_pWindow = pWnd;
+ m_pLocalVariables = new KviKvsHash();
+ m_pReturnValue = pRetVal;
+ m_uRunTimeFlags = 0;
+ m_pExtendedData = pExtData;
+ m_pDefaultReportLocation = 0;
+}
+
+KviKvsRunTimeContext::~KviKvsRunTimeContext()
+{
+ delete m_pLocalVariables;
+}
+
+KviKvsHash * KviKvsRunTimeContext::globalVariables()
+{
+ return KviKvsKernel::instance()->globalVariables();
+}
+
+void KviKvsRunTimeContext::enterBlockingSection()
+{
+ // actually a NO-OP
+}
+
+bool KviKvsRunTimeContext::leaveBlockingSection()
+{
+ if(g_pApp->closingDown())return false; // application quitting
+ if(!g_pApp->windowExists(m_pWindow))return false; // window lost
+ return true;
+}
+
+KviKvsVariant * KviKvsRunTimeContext::swapReturnValuePointer(KviKvsVariant * pNewPointer)
+{
+ KviKvsVariant * pAux = m_pReturnValue;
+ m_pReturnValue = pNewPointer;
+ return pAux;
+}
+
+void KviKvsRunTimeContext::report(bool bError,KviKvsTreeNode * pNode,const QString &szMsgFmt,kvi_va_list va)
+{
+ QString szMsg;
+ KviQString::vsprintf(szMsg,szMsgFmt,va);
+
+ KviPointerList<QString> * pCodeListing = 0;
+ KviPointerList<QString> * pCallStack = 0;
+ QString szLocation;
+
+ if(pNode)
+ {
+ if(pNode->location() && m_pScript)
+ {
+ pCodeListing = new KviPointerList<QString>;
+ pCodeListing->setAutoDelete(true);
+
+ int iLine,iCol;
+
+ KviKvsReport::findLineColAndListing(m_pScript->buffer(),pNode->location(),iLine,iCol,pCodeListing);
+
+ KviQString::sprintf(szLocation,__tr2qs("line %d, near character %d"),iLine,iCol);
+ }
+
+ // create the call stack
+ int iFrame = 0;
+
+ pCallStack = new KviPointerList<QString>;
+ pCallStack->setAutoDelete(true);
+
+ while(pNode && (iFrame < 12))
+ {
+ QString * pString = new QString();
+ QString szTmp;
+ pNode->contextDescription(szTmp);
+ KviQString::sprintf(*pString,"#%d %Q",iFrame,&szTmp);
+ if(pNode->location())
+ {
+ int iLine,iCol;
+ KviKvsReport::findLineAndCol(m_pScript->buffer(),pNode->location(),iLine,iCol);
+ QString tmpi;
+ KviQString::sprintf(tmpi," [line %d, near character %d]",iLine,iCol);
+ *pString += tmpi;
+ }
+ pCallStack->append(pString);
+ iFrame++;
+ pNode = pNode->parent();
+ }
+ if(pNode)
+ pCallStack->append(new QString("#12 ..."));
+ }
+
+ QString szContext = m_pScript ? m_pScript->name() : "kvirc core code";
+ KviKvsReport rep(bError ? KviKvsReport::RunTimeError : KviKvsReport::RunTimeWarning,szContext,szMsg,szLocation,m_pWindow);
+ if(pCodeListing)rep.setCodeListing(pCodeListing);
+ if(pCallStack)rep.setCallStack(pCallStack);
+
+ KviKvsReport::report(&rep,m_pWindow);
+}
+
+void KviKvsRunTimeContext::error(KviKvsTreeNode * pNode,const QString &szMsgFmt,...)
+{
+ m_bError = true;
+
+ kvi_va_list va;
+ kvi_va_start_by_reference(va,szMsgFmt);
+ report(true,pNode,szMsgFmt,va);
+ kvi_va_end(va);
+}
+
+void KviKvsRunTimeContext::warning(KviKvsTreeNode * pNode,const QString &szMsgFmt,...)
+{
+ kvi_va_list va;
+ kvi_va_start_by_reference(va,szMsgFmt);
+ report(false,pNode,szMsgFmt,va);
+ kvi_va_end(va);
+}
+
+void KviKvsRunTimeContext::error(const QString &szMsgFmt,...)
+{
+ m_bError = true;
+
+ kvi_va_list va;
+ kvi_va_start_by_reference(va,szMsgFmt);
+ report(true,m_pDefaultReportLocation,szMsgFmt,va);
+ kvi_va_end(va);
+}
+
+void KviKvsRunTimeContext::warning(const QString &szMsgFmt,...)
+{
+ kvi_va_list va;
+ kvi_va_start_by_reference(va,szMsgFmt);
+ report(false,m_pDefaultReportLocation,szMsgFmt,va);
+ kvi_va_end(va);
+}
+
+bool KviKvsRunTimeContext::errorNoIrcContext()
+{
+ error(m_pDefaultReportLocation,__tr2qs("This command can be used only in windows bound to an IRC context"));
+ return false;
+}
+
+bool KviKvsRunTimeContext::warningNoIrcConnection()
+{
+ warning(m_pDefaultReportLocation,__tr2qs("You're not connected to an IRC server"));
+ return true;
+}
+
+bool KviKvsRunTimeContext::warningMissingParameter()
+{
+ warning(m_pDefaultReportLocation,__tr2qs("Missing parameter"));
+ return true;
+}
+
+void KviKvsRunTimeContext::setDefaultReportLocation(KviKvsTreeNode * pNode)
+{
+ m_pDefaultReportLocation = pNode;
+}
diff --git a/src/kvirc/kvs/kvi_kvs_runtimecontext.h b/src/kvirc/kvs/kvi_kvs_runtimecontext.h
new file mode 100644
index 00000000..68fa8ebd
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_runtimecontext.h
@@ -0,0 +1,256 @@
+#ifndef _KVI_KVS_RUNTIMECONTEXT_H_
+#define _KVI_KVS_RUNTIMECONTEXT_H_
+//=============================================================================
+//
+// File : kvi_kvs_runtimecontext.h
+// Created on Tue 07 Oct 2003 01:49:40 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#include "kvi_window.h"
+
+#include "kvi_kvs_variant.h"
+#include "kvi_kvs_hash.h"
+#include "kvi_kvs_variantlist.h"
+#include "kvi_kvs_switchlist.h"
+
+class KviKvsScript;
+class KviConsole;
+class KviIrcContext;
+class KviIrcConnection;
+class KviKvsTreeNode;
+class KviKvsObject;
+class KviKvsReportHandler;
+
+class KVIRC_API KviKvsExtendedRunTimeData
+{
+ friend class KviKvsRunTimeContext;
+protected:
+ KviKvsHash * m_pExtendedScopeVariables; // extended scope vars, shallow, may be 0
+ KviKvsSwitchList * m_pAliasSwitchList; // switches for the aliases, shallow, may be 0
+ KviKvsObject * m_pThisObject; // the current object for object function calls
+ QString * m_pScriptFilePath; // the current script file path, shallow, may be 0
+ bool m_bAutoDelete;
+public:
+ // all shallow data, all may be 0
+ KviKvsExtendedRunTimeData()
+ : m_pExtendedScopeVariables(0),
+ m_pAliasSwitchList(0),
+ m_pThisObject(0),
+ m_pScriptFilePath(0),
+ m_bAutoDelete(FALSE)
+ {};
+ KviKvsExtendedRunTimeData(KviKvsHash * pExtScopeVariables,bool autoDelete=FALSE)
+ : m_pExtendedScopeVariables(pExtScopeVariables),
+ m_pAliasSwitchList(0),
+ m_pThisObject(0),
+ m_pScriptFilePath(0),
+ m_bAutoDelete(autoDelete)
+ {};
+ KviKvsExtendedRunTimeData(KviKvsSwitchList * pAliasSwitchList,bool autoDelete=FALSE)
+ : m_pExtendedScopeVariables(0),
+ m_pAliasSwitchList(pAliasSwitchList),
+ m_pThisObject(0),
+ m_pScriptFilePath(0),
+ m_bAutoDelete(autoDelete)
+ {};
+ KviKvsExtendedRunTimeData(KviKvsObject * pThisObject,bool autoDelete=FALSE)
+ : m_pExtendedScopeVariables(0),
+ m_pAliasSwitchList(0),
+ m_pThisObject(pThisObject),
+ m_pScriptFilePath(0),
+ m_bAutoDelete(autoDelete)
+ {};
+ KviKvsExtendedRunTimeData(QString * pScriptFilePath,bool autoDelete=FALSE)
+ : m_pExtendedScopeVariables(0),
+ m_pAliasSwitchList(0),
+ m_pThisObject(0),
+ m_pScriptFilePath(pScriptFilePath),
+ m_bAutoDelete(autoDelete)
+ {};
+ ~KviKvsExtendedRunTimeData();
+public:
+ KviKvsHash * extendedScopeVariables(){ return m_pExtendedScopeVariables; };
+ KviKvsSwitchList * aliasSwitchList(){ return m_pAliasSwitchList; };
+ KviKvsObject * thisObject(){ return m_pThisObject; };
+ QString * scriptFilePath(){ return m_pScriptFilePath; };
+};
+
+
+class KVIRC_API KviKvsRunTimeContext
+{
+ friend class KviKvsScript;
+ friend class KviKvsObject;
+ friend class KviKvsRunTimeCall;
+ friend class KviKvsEventManager;
+protected:
+ // only KviKvsScript, KviKvsEventManager and KviKvsObject can instantiate this class
+ KviKvsRunTimeContext(KviKvsScript * pScript,
+ KviWindow * pWnd,
+ KviKvsVariantList * pParams,
+ KviKvsVariant * pRetVal,
+ KviKvsExtendedRunTimeData * pExtData = 0);
+public:
+ ~KviKvsRunTimeContext();
+protected:
+ // stuff that is fixed in the whole script context
+ KviKvsScript * m_pScript; // shallow, may be 0!
+ KviKvsHash * m_pLocalVariables; // owned, never 0
+ KviKvsVariantList * m_pParameterList; // shallow, never 0
+ KviKvsVariant * m_pReturnValue; // shallow, never 0
+
+ // stuff that is generally global but sometimes may change
+ // during the execution of the script
+ KviWindow * m_pWindow; // shallow, never 0
+
+ enum RunTimeFlags { BreakPending = 1, HaltCalled = 2, DisableReporting = 4 };
+ unsigned int m_uRunTimeFlags; // a combination of RunTimeFlags
+
+ KviKvsExtendedRunTimeData * m_pExtendedData; // shallow, may be 0
+
+ // error handling
+ bool m_bError; // was error() ever called ?
+ KviKvsTreeNode * m_pDefaultReportLocation; // default report location for error()
+public:
+ // the window that this script is bound to (it MAY change during the script parsing)
+ KviWindow * window()
+ { return m_pWindow; };
+ // quick access to the irc context (it MAY be zero!)
+ KviIrcContext * context()
+ { return m_pWindow->context(); };
+ // quick access to the console that this script is bound to (it MAY be zero, if there is no console)
+ KviConsole * console()
+ { return m_pWindow->console(); };
+ // quick access to the connection: it MAY be zero!
+ KviIrcConnection * connection()
+ { return m_pWindow->connection(); };
+
+ // the local variables of this script
+ KviKvsHash * localVariables()
+ { return m_pLocalVariables; };
+ // the global application-wide variables
+ KviKvsHash * globalVariables();
+ // the parameters passed to this script
+ KviKvsVariantList * parameterList()
+ { return m_pParameterList; };
+
+ // parent script, may be 0!
+ KviKvsScript * script()
+ { return m_pScript; };
+
+ KviKvsVariant * returnValue()
+ { return m_pReturnValue; };
+
+ // this is the default error reporting location
+ // it is also used by rfc2812wrapper to find out the current command name!
+ KviKvsTreeNode * defaultReportLocation()
+ { return m_pDefaultReportLocation; };
+
+ // the extended stuff
+ KviKvsHash * extendedScopeVariables()
+ { return m_pExtendedData ? m_pExtendedData->extendedScopeVariables() : 0; };
+ KviKvsSwitchList * aliasSwitchList()
+ { return m_pExtendedData ? m_pExtendedData->aliasSwitchList() : 0; };
+ KviKvsObject * thisObject()
+ { return m_pExtendedData ? m_pExtendedData->thisObject() : 0; };
+ QString * scriptFilePath()
+ { return m_pExtendedData ? m_pExtendedData->scriptFilePath() : 0; };
+
+ // this MUST be called before any blocking call that might return to the main event loop
+ // and eventually quit kvirc or close the window that this command is associated to
+ // Actually this is a NO-OP but later may really do something that avoids kvirc to crash
+ void enterBlockingSection();
+ // this MUST be called after exiting the blocking section above
+ // if this function returns false your parsing code MUST "return false" immediately:
+ // it means that something rather critical happened and the script
+ // execution cannot continue
+ bool leaveBlockingSection();
+
+ // Error handling
+
+ // was error(...) ever called ?
+ bool error() const { return m_bError; };
+
+ void error(KviKvsTreeNode * pNode,const QString &szMsgFmt,...);
+ void warning(KviKvsTreeNode * pNode,const QString &szMsgFmt,...);
+ void error(const QString &szMsgFmt,...);
+ void warning(const QString &szMsgFmt,...);
+ void setDefaultReportLocation(KviKvsTreeNode * pNode);
+ bool errorNoIrcContext();
+ bool warningNoIrcConnection();
+ bool warningMissingParameter();
+
+//PRIVATE:
+ // tricky
+ // don't use it: it's only for the parser
+ void setWindow(KviWindow * pWnd)
+ { m_pWindow = pWnd; };
+
+ // returns the old pointer
+ KviKvsVariant * swapReturnValuePointer(KviKvsVariant * pNewPointer);
+ // the old pointer MUST be reset!
+
+ // this is called by the parser when a break is encountered
+ // the parser calls setBreakPending() and returns false
+ // the contexts that can handle a break should check breakPending()
+ // after an internal evaluation returned false.
+ // if breakPending() they should handle it with handleBreak() and
+ // return true instead.
+ void setBreakPending()
+ { m_uRunTimeFlags |= BreakPending; };
+ // this tells if a break command has been called
+ // it may return true if an execution() command has returned false
+ // (if breakPending() there should be no error()
+ bool breakPending()
+ { return (m_uRunTimeFlags & BreakPending); };
+ // this is called by the commands that can handle a break
+ void handleBreak()
+ { m_uRunTimeFlags &= ~BreakPending; };
+
+ // this is called by the parser when a halt is encountered
+ // the parser then returns false and all the stack frames
+ // above should do the same
+ void setHaltCalled()
+ { m_uRunTimeFlags |= HaltCalled; };
+ bool haltCalled()
+ { return (m_uRunTimeFlags & HaltCalled); };
+
+ // this is used by KviKvsScript to disable reporting when the Quiet flag is used
+ void disableReporting()
+ { m_uRunTimeFlags |= DisableReporting; };
+ bool reportingDisabled()
+ { return (m_uRunTimeFlags & DisableReporting); };
+ void enableReporting()
+ { m_uRunTimeFlags &= ~DisableReporting; };
+
+ // clears the error status on this context
+ // this is useful to continue execution after an error
+ // and probably used only in /eval
+ void clearError()
+ { m_bError = false; };
+ protected:
+
+ void report(bool bError,KviKvsTreeNode * pNode,const QString &szMsgFmt,kvi_va_list va);
+
+};
+
+#endif //!_KVI_KVS_RUNTIMECONTEXT_H_
diff --git a/src/kvirc/kvs/kvi_kvs_rwevaluationresult.cpp b/src/kvirc/kvs/kvi_kvs_rwevaluationresult.cpp
new file mode 100644
index 00000000..d51588f2
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_rwevaluationresult.cpp
@@ -0,0 +1,66 @@
+//=============================================================================
+//
+// File : kvi_kvs_rwevaluationresult.cpp
+// Created on Thu 11 Dec 2003 22:51:46 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_rwevaluationresult.h"
+#include "kvi_kvs_hash.h"
+#include "kvi_kvs_array.h"
+
+KviKvsRWEvaluationResult::KviKvsRWEvaluationResult(KviKvsRWEvaluationResult *pParent,KviKvsVariant *pVariant)
+{
+ m_pParent = pParent;
+ m_pVariant = pVariant;
+}
+
+KviKvsRWEvaluationResult::~KviKvsRWEvaluationResult()
+{
+}
+
+KviKvsArrayElement::KviKvsArrayElement(KviKvsRWEvaluationResult *pParent,KviKvsVariant *pVariant,KviKvsArray *pArray,int iKey)
+: KviKvsRWEvaluationResult(pParent,pVariant)
+{
+ m_pArray = pArray;
+ m_iKey = iKey;
+}
+
+KviKvsArrayElement::~KviKvsArrayElement()
+{
+ if(m_pVariant->isEmpty())m_pArray->unset(m_iKey);
+ if(m_pParent)delete m_pParent;
+}
+
+KviKvsHashElement::KviKvsHashElement(KviKvsRWEvaluationResult *pParent,KviKvsVariant *pVariant,KviKvsHash *pHash,const QString &szKey)
+: KviKvsRWEvaluationResult(pParent,pVariant)
+{
+ m_pHash = pHash;
+ m_szKey = szKey;
+}
+
+KviKvsHashElement::~KviKvsHashElement()
+{
+ if(m_pVariant->isEmpty())m_pHash->unset(m_szKey);
+ if(m_pParent)delete m_pParent;
+}
+
diff --git a/src/kvirc/kvs/kvi_kvs_rwevaluationresult.h b/src/kvirc/kvs/kvi_kvs_rwevaluationresult.h
new file mode 100644
index 00000000..9d91a1ba
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_rwevaluationresult.h
@@ -0,0 +1,70 @@
+#ifndef _KVI_KVS_RWEVALUATIONRESULT_H_
+#define _KVI_KVS_RWEVALUATIONRESULT_H_
+//=============================================================================
+//
+// File : kvi_kvs_rwevaluationresult.h
+// Created on Thu 11 Dec 2003 22:51:46 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_kvs_variant.h"
+
+class KVIRC_API KviKvsRWEvaluationResult
+{
+public:
+ // this result becomes the owner of the parent result!!!!
+ KviKvsRWEvaluationResult(KviKvsRWEvaluationResult *pParent,KviKvsVariant *pVariant);
+ // the destructor must do (in order):
+ // check if variant is empty and if it is then remove it from the container (destroy it)
+ // delete the m_pParent result
+ virtual ~KviKvsRWEvaluationResult();
+protected:
+ KviKvsRWEvaluationResult * m_pParent;
+ KviKvsVariant * m_pVariant;
+public:
+ KviKvsVariant * result(){ return m_pVariant; };
+};
+
+class KviKvsArray;
+
+class KVIRC_API KviKvsArrayElement : public KviKvsRWEvaluationResult
+{
+public:
+ KviKvsArrayElement(KviKvsRWEvaluationResult *pParent,KviKvsVariant *pVariant,KviKvsArray *pArray,int iKey);
+ ~KviKvsArrayElement();
+protected:
+ KviKvsArray * m_pArray;
+ int m_iKey;
+};
+
+class KviKvsHash;
+
+class KVIRC_API KviKvsHashElement : public KviKvsRWEvaluationResult
+{
+public:
+ KviKvsHashElement(KviKvsRWEvaluationResult *pParent,KviKvsVariant *pVariant,KviKvsHash *pHash,const QString &szKey);
+ ~KviKvsHashElement();
+protected:
+ KviKvsHash * m_pHash;
+ QString m_szKey;
+};
+
+#endif //!_KVI_KVS_RWEVALUATIONRESULT_H_
diff --git a/src/kvirc/kvs/kvi_kvs_script.cpp b/src/kvirc/kvs/kvi_kvs_script.cpp
new file mode 100644
index 00000000..e7a2bd60
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_script.cpp
@@ -0,0 +1,356 @@
+//=============================================================================
+//
+// File : kvi_kvs_script.cpp
+// Creation date : Thu 25 Sep 2003 05.12 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_script.h"
+#include "kvi_kvs_parser.h"
+#include "kvi_kvs_report.h"
+#include "kvi_kvs_runtimecontext.h"
+#include "kvi_kvs_treenode_instruction.h"
+#include "kvi_kvs_variantlist.h"
+#include "kvi_kvs_kernel.h"
+
+#include "kvi_locale.h"
+#include "kvi_out.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_window.h"
+#include "kvi_app.h"
+
+class KVIRC_API KviKvsScriptData
+{
+ friend class KviKvsScript;
+protected:
+ unsigned int m_uRefs; // Reference count for this structure
+
+ QString m_szName; // script context name
+ QString m_szBuffer; // NEVER TOUCH THIS
+ const QChar * m_pBuffer; // this points to m_szBuffer: use it to extract string data
+
+ KviKvsScript::ScriptType m_eType; // the type of the code in m_szBuffer
+
+ KviKvsTreeNodeInstruction * m_pTree; // syntax tree
+ unsigned int m_uLock; // this is increased while the script is being executed
+};
+
+//#warning "THERE IS SOME MESS WITH m_szBuffer and m_pBuffer : with some script copying we may get errors with negative char indexes!"
+
+KviKvsScript::KviKvsScript(const QString &szName,const QString &szBuffer,ScriptType eType)
+{
+ m_pData = new KviKvsScriptData;
+ m_pData->m_uRefs = 1;
+ m_pData->m_szName = szName;
+ m_pData->m_eType = eType;
+ m_pData->m_szBuffer = szBuffer;
+ if(m_pData->m_szBuffer.isNull())m_pData->m_szBuffer = "";
+ //KviQString::detach(*(m_pData->m_pszBuffer));
+ m_pData->m_pBuffer = KviQString::nullTerminatedArray(m_pData->m_szBuffer); // never 0
+ m_pData->m_uLock = 0;
+ m_pData->m_pTree = 0;
+}
+
+KviKvsScript::KviKvsScript(const QString &szName,const QString &szBuffer,KviKvsTreeNodeInstruction * pPreparsedTree,ScriptType eType)
+{
+ m_pData = new KviKvsScriptData;
+ m_pData->m_uRefs = 1;
+ m_pData->m_szName = szName;
+ m_pData->m_szBuffer = szBuffer;
+ m_pData->m_eType = eType;
+ if(m_pData->m_szBuffer.isNull())m_pData->m_szBuffer = "";
+ //KviQString::detach(*(m_pData->m_pszBuffer));
+ m_pData->m_pBuffer = KviQString::nullTerminatedArray(m_pData->m_szBuffer); // never 0
+ m_pData->m_uLock = 0;
+ m_pData->m_pTree = pPreparsedTree;
+}
+
+KviKvsScript::KviKvsScript(const KviKvsScript &src)
+{
+ m_pData = src.m_pData;
+ m_pData->m_uRefs++;
+}
+
+KviKvsScript::~KviKvsScript()
+{
+ if(m_pData->m_uRefs < 2)
+ {
+ if(m_pData->m_uLock)debug("WARNING: Destroying a locked KviKvsScript");
+ if(m_pData->m_pTree)delete m_pData->m_pTree;
+ delete m_pData;
+ } else {
+ m_pData->m_uRefs--;
+ }
+}
+
+void KviKvsScript::setName(const QString &szName)
+{
+ if(m_pData->m_uRefs > 1)detach();
+ m_pData->m_szName = szName;
+}
+
+const QString & KviKvsScript::name() const
+{
+ return m_pData->m_szName;
+}
+
+const QString & KviKvsScript::code() const
+{
+ return m_pData->m_szBuffer;
+}
+
+bool KviKvsScript::locked() const
+{
+ return m_pData->m_uLock > 0;
+}
+
+void KviKvsScript::dump(const char * prefix)
+{
+ if(m_pData->m_pTree)m_pData->m_pTree->dump(prefix);
+ else debug("%s KviKvsScript : no tree to dump",prefix);
+}
+
+void KviKvsScript::detach()
+{
+ if(m_pData->m_uRefs <= 1)return;
+ m_pData->m_uRefs--;
+ KviKvsScriptData * d = new KviKvsScriptData;
+ d->m_uRefs = 1;
+ d->m_eType = m_pData->m_eType;
+ d->m_szBuffer = m_pData->m_szBuffer;
+ if(d->m_szBuffer.isNull())d->m_szBuffer = "";
+ KviQString::detach(d->m_szBuffer);
+ d->m_pBuffer = KviQString::nullTerminatedArray(d->m_szBuffer); // never 0
+ d->m_uLock = 0;
+ d->m_pTree = 0;
+ m_pData = d;
+}
+
+const QChar * KviKvsScript::buffer() const
+{
+ return m_pData->m_pBuffer;
+}
+
+int KviKvsScript::run(const QString &szCode,KviWindow * pWindow,KviKvsVariantList * pParams,KviKvsVariant * pRetVal)
+{
+ // static helper
+ KviKvsScript s("kvirc::corecall(run)",szCode);
+ return s.run(pWindow,pParams,pRetVal,PreserveParams);
+}
+
+int KviKvsScript::evaluate(const QString &szCode,KviWindow * pWindow,KviKvsVariantList * pParams,KviKvsVariant * pRetVal)
+{
+ // static helper
+ KviKvsScript s("kvirc::corecall(evalutate)",szCode,Parameter);
+ return s.run(pWindow,pParams,pRetVal,PreserveParams);
+}
+
+int KviKvsScript::evaluateAsString(const QString &szCode,KviWindow * pWindow,KviKvsVariantList * pParams,QString &szRetVal)
+{
+ // static helper
+ KviKvsVariant ret;
+ KviKvsScript s("kvirc::corecall(evalutate)",szCode,Parameter);
+ int iRet = s.run(pWindow,pParams,&ret,PreserveParams);
+ ret.asString(szRetVal);
+ return iRet;
+}
+
+int KviKvsScript::run(KviWindow * pWnd,KviKvsVariantList * pParams,QString &szRetVal,int iRunFlags,KviKvsExtendedRunTimeData * pExtData)
+{
+ KviKvsVariant retVal;
+ int iRet = run(pWnd,pParams,&retVal,iRunFlags,pExtData);
+ retVal.asString(szRetVal);
+ return iRet;
+}
+
+//static long int g_iTreeCacheHits = 0;
+//static long int g_iTreeCacheMisses = 0;
+
+int KviKvsScript::run(KviWindow * pWnd,KviKvsVariantList * pParams,KviKvsVariant * pRetVal,int iRunFlags,KviKvsExtendedRunTimeData * pExtData)
+{
+ if(!m_pData->m_pTree)
+ {
+ //g_iTreeCacheMisses++;
+ //debug("CREATING TREE FOR SCRIPT %s",name().latin1());
+ //debug("TREE CACHE STATS: HITS=%d, MISSES=%d",g_iTreeCacheHits,g_iTreeCacheMisses);
+ if(!parse(pWnd,iRunFlags))
+ {
+ if(pParams && !(iRunFlags & PreserveParams))delete pParams;
+ return Error;
+ }
+ } else {
+ //g_iTreeCacheHits++;
+ //debug("USING A CACHED TREE FOR SCRIPT %s",name().latin1());
+ //debug("TREE CACHE STATS: HITS=%d, MISSES=%d",g_iTreeCacheHits,g_iTreeCacheMisses);
+ }
+
+ return execute(pWnd,pParams,pRetVal,iRunFlags,pExtData);
+}
+
+int KviKvsScript::run(KviKvsRunTimeContext * pContext,int iRunFlags)
+{
+ if(!m_pData->m_pTree)
+ {
+ //g_iTreeCacheMisses++;
+ //debug("CREATING TREE FOR SCRIPT %s",name().latin1());
+ //debug("TREE CACHE STATS: HITS=%d, MISSES=%d",g_iTreeCacheHits,g_iTreeCacheMisses);
+ if(!parse(pContext->window(),iRunFlags))
+ return Error;
+ } else {
+ //g_iTreeCacheHits++;
+ //debug("USING A CACHED TREE FOR SCRIPT %s",name().latin1());
+ //debug("TREE CACHE STATS: HITS=%d, MISSES=%d",g_iTreeCacheHits,g_iTreeCacheMisses);
+ }
+
+ int iRet;
+
+ if(iRunFlags & Quiet)
+ {
+ bool bMustReEnable = !(pContext->reportingDisabled());
+ pContext->disableReporting();
+ iRet = executeInternal(pContext);
+ if(bMustReEnable)pContext->enableReporting();
+ } else {
+ iRet = executeInternal(pContext);
+ }
+
+ return iRet;
+}
+
+
+bool KviKvsScript::parse(KviWindow * pOutput,int iRunFlags)
+{
+ if(m_pData->m_pTree)
+ {
+ // there is already a tree
+ // if we have more than one ref, detach!
+ if(m_pData->m_uRefs > 1)
+ {
+ // mmmh.. more than one ref! .. detach
+ detach();
+ } else {
+ // only a single ref: we're the owner of the tree
+ if(m_pData->m_uLock)
+ {
+ // ops... someone is locked in THIS script object
+ debug("WARNING: Trying to reparse a locked KviKvsScript!");
+ return false;
+ }
+ if(m_pData->m_pTree)delete m_pData->m_pTree;
+ m_pData->m_pTree = 0;
+ }
+ } // else there is no tree at all, nobody can be locked inside
+
+ KviKvsParser p(this,(iRunFlags & Quiet) ? 0 : pOutput);
+ // parse never blocks
+
+ int iFlags = iRunFlags & AssumeLocals ? KviKvsParser::AssumeLocals : 0;
+ if(iRunFlags & Pedantic)iFlags |= KviKvsParser::Pedantic;
+
+ switch(m_pData->m_eType)
+ {
+ case Expression:
+ m_pData->m_pTree = p.parseAsExpression(m_pData->m_pBuffer,iFlags);
+ break;
+ case Parameter:
+ m_pData->m_pTree = p.parseAsParameter(m_pData->m_pBuffer,iFlags);
+ break;
+ case InstructionList:
+ default:
+ m_pData->m_pTree = p.parse(m_pData->m_pBuffer,iFlags);
+ break;
+ }
+
+ //debug("\n\nDUMPING SCRIPT");
+ //dump("");
+ //debug("END OF SCRIPT DUMP\n\n");
+
+ return !p.error();
+}
+
+
+int KviKvsScript::executeInternal(KviKvsRunTimeContext * pContext)
+{
+ // lock this script
+ m_pData->m_uLock++;
+
+ int iRunStatus = Success;
+
+ if(!m_pData->m_pTree->execute(pContext))
+ {
+ if(pContext->error())iRunStatus = Error;
+ else {
+ // else just a halt, return or sth like that
+ if(pContext->haltCalled())
+ iRunStatus |= HaltEncountered;
+ }
+ }
+
+ // we can't block any longer: unlock
+ m_pData->m_uLock--;
+
+ return iRunStatus;
+}
+
+int KviKvsScript::execute(KviWindow * pWnd,KviKvsVariantList * pParams,KviKvsVariant * pRetVal,int iRunFlags,KviKvsExtendedRunTimeData * pExtData)
+{
+ bool bDeleteParams = !(iRunFlags & PreserveParams);
+
+ // do we have a parsed tree ?
+ if(!m_pData->m_pTree)
+ {
+ if(pParams && bDeleteParams)delete pParams;
+ // this is intended for developers only
+ pWnd->outputNoFmt(KVI_OUT_PARSERERROR,"[developer error]: you must succesfully call KviKvsScript::parse() before KviKvsScript::execute()");
+ return Error;
+ }
+ // do we need to pass dummy params ?
+ if(!pParams)
+ {
+ pParams = KviKvsKernel::instance()->emptyParameterList();
+ bDeleteParams = false;
+ }
+
+ bool bDeleteRetVal = false;
+
+ if(!pRetVal)
+ {
+ pRetVal = new KviKvsVariant();
+ bDeleteRetVal = true;
+ }
+
+ KviKvsRunTimeContext ctx(this,pWnd,pParams,pRetVal,pExtData);
+
+ if(iRunFlags & Quiet)
+ ctx.disableReporting();
+
+ int iRunStatus = executeInternal(&ctx);
+
+ // don't forget to delete the params
+ if(bDeleteParams)delete pParams;
+ if(bDeleteRetVal)delete pRetVal;
+ pParams = 0; pRetVal = 0;
+ return iRunStatus;
+}
+
+
+
diff --git a/src/kvirc/kvs/kvi_kvs_script.h b/src/kvirc/kvs/kvi_kvs_script.h
new file mode 100644
index 00000000..b9243878
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_script.h
@@ -0,0 +1,155 @@
+#ifndef _KVI_KVS_SCRIPT_H_
+#define _KVI_KVS_SCRIPT_H_
+//=============================================================================
+//
+// File : kvi_kvs_script.h
+// Creation date : Thu 25 Sep 2003 05.12 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_window.h"
+#include "kvi_pointerlist.h"
+#include "kvi_kvs_variant.h"
+#include "kvi_kvs_variantlist.h"
+#include "kvi_heapobject.h"
+
+class KviKvsTreeNodeInstruction;
+class KviKvsExtendedRunTimeData;
+class KviKvsScriptData;
+class KviKvsReport;
+class KviKvsRunTimeContext;
+
+// X defines this stuff: ugly :/
+#ifdef Error
+ #undef Error
+#endif
+#ifdef Success
+ #undef Success
+#endif
+
+class KVIRC_API KviKvsScript : public KviHeapObject
+{
+ friend class KviKvsObject;
+ friend class KviKvsParser;
+ friend class KviKvsRunTimeContext;
+public:
+ enum RunStatus {
+ // the script returned an error
+ Error = 0,
+ // the script ran succesfully
+ Success = 1,
+ // the script ran succesfully and halt was encountered
+ HaltEncountered = 2
+ };
+ enum ScriptType {
+ // the most common script type: a sequence of instructions
+ InstructionList,
+ // an expression to be evaluated as in a $() call (pRetVal should be always set!)
+ Expression,
+ // a parameter to be evaluated (pRetVal should be always set!)
+ Parameter
+ };
+protected:
+ // the name parameter is the name of the script context!
+ KviKvsScript(const QString &szName,const QString &szBuffer,KviKvsTreeNodeInstruction * pPreparsedTree,ScriptType eType = InstructionList);
+public:
+ // shallow copy of the script data
+ // useful when a script can be destroyed while running (like in timers)
+ KviKvsScript(const KviKvsScript &src);
+ KviKvsScript(const QString &szName,const QString &szBuffer,ScriptType eType=InstructionList);
+ ~KviKvsScript();
+private:
+ KviKvsScriptData * m_pData;
+public:
+ const QString & name() const;
+ const QString & code() const;
+ bool locked() const;
+
+ void setName(const QString &szName);
+
+ enum RunFlags {
+ // do not delete the eventual parameters passed (only execute() and run())
+ PreserveParams = 1,
+ // assume that the variables are local unless explicitly declared (flag used only for parse())
+ AssumeLocals = 2, // FIXME: This should be a global option, eventually
+ // be more pedantic: spit more warnings and sometimes more errors
+ Pedantic = 4, // FIXME: This should be a global option, eventually
+ // don't print any errors
+ Quiet = 8
+ };
+ // returns 0 (KviKvsScript::RunFailure) on error
+ // returns a nonzero combination of RunStatus flags on success
+ int run(KviWindow * pWnd, // window that the command has to be bound to
+ KviKvsVariantList * pParams = 0, // parameter list (0 if you don't pass params) ownership transferred if PreserverParams is not used
+ KviKvsVariant * pRetVal = 0, // return value buffer (0 if you ignore it)
+ int iRunFlags = 0, // a combination of run flags (usually default)
+ KviKvsExtendedRunTimeData * pExtData = 0); // extended data (usually 0) (if you need to pass extended scope variables or alias switch lists...)
+
+ // returns 0 (KviKvsScript::RunFailure) on error
+ // returns a nonzero combination of RunStatus flags on success
+ // this is probably used only in /eval
+ int run(KviKvsRunTimeContext * pContext,int iRunFlags = 0);
+
+ // same as run above, but gets a QString parameter as return buffer
+ // this is probably useful only for evaluating InstructionList scripts
+ int run(KviWindow * pWnd,
+ KviKvsVariantList * pParams,
+ QString &szRetVal,
+ int iRunFlags = 0,
+ KviKvsExtendedRunTimeData * pExtData = 0);
+
+ // static helpers for quick running
+ // returns a combination of RunStatus flags (nonzero on no error)
+ // does NOT take params ownership
+ static int run(const QString &szCode,KviWindow * pWindow,KviKvsVariantList * pParams = 0,KviKvsVariant * pRetVal = 0);
+
+ // static helper for quick evaluating parameters
+ // returns a combination of RunStatus flags (nonzero on no error)
+ // does NOT take params ownership
+ // pRetVal CAN'T be zero here since we're evaluating stuff here
+ static int evaluate(const QString &szCode,KviWindow * pWindow,KviKvsVariantList * pParams,KviKvsVariant * pRetVal);
+ static int evaluateAsString(const QString &szCode,KviWindow * pWindow,KviKvsVariantList * pParams,QString &szRetVal);
+public:
+ void dump(const char * prefix);
+protected:
+ // returns true after a succesfull parsing
+ // pOutput is useful only for printing errors
+ // if 0 , no errors are printed
+ bool parse(KviWindow * pOutput = 0,
+ int iRunFlags = 0);
+ // returns 0 (KviKvsScript::RunFailure) on error
+ // returns a nonzero combination of RunStatus flags on success
+ int execute(KviWindow * pWnd,
+ KviKvsVariantList * pParams = 0,
+ KviKvsVariant * pRetVal = 0,
+ int iRunFlags = 0,
+ KviKvsExtendedRunTimeData * pExtData = 0);
+ // returns 0 (KviKvsScript::RunFailure) on error
+ // returns a nonzero combination of RunStatus flags on success
+ int executeInternal(KviKvsRunTimeContext * pContext);
+ const QChar * buffer() const;
+ // detaches this script from any other shallow copies
+ void detach();
+};
+
+
+#endif //!_KVI_KVS_SCRIPT_H_
diff --git a/src/kvirc/kvs/kvi_kvs_scriptaddonmanager.cpp b/src/kvirc/kvs/kvi_kvs_scriptaddonmanager.cpp
new file mode 100644
index 00000000..aee138d4
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_scriptaddonmanager.cpp
@@ -0,0 +1,386 @@
+//=============================================================================
+//
+// File : kvi_kvs_scriptaddonmanager.cpp
+// Created on Thu 31 Mar 2005 01:21:23 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_scriptaddonmanager.h"
+#include "kvi_kvs_script.h"
+#include "kvi_config.h"
+#include "kvi_window.h"
+#include "kvi_iconmanager.h"
+
+KviKvsScriptAddonManager * KviKvsScriptAddonManager::m_pInstance = 0;
+
+
+
+
+KviKvsScriptAddon::KviKvsScriptAddon(
+ const QString &szName,
+ const QString &szVersion,
+ const QString &szVisibleNameCode,
+ const QString &szDescriptionCode,
+ const QString &szUninstallCallbackCode,
+ const QString &szIconId
+) : KviHeapObject(), m_szName(szName), m_szVersion(szVersion), m_szIconId(szIconId)
+{
+ allocateScripts(szVisibleNameCode,szDescriptionCode,szUninstallCallbackCode);
+ m_pConfigureCallback = 0;
+ m_pHelpCallback = 0;
+}
+
+KviKvsScriptAddon::KviKvsScriptAddon(const KviKvsScriptAddon &a)
+: KviHeapObject()
+{
+ m_szName = a.m_szName;
+ m_szVersion = a.m_szVersion;
+ m_szIconId = a.m_szIconId;
+ allocateScripts(a.m_pVisibleNameScript->code(),a.m_pDescriptionScript->code(),a.m_pUninstallCallback ? a.m_pUninstallCallback->code() : QString::null);
+ m_pConfigureCallback = 0;
+ setConfigureCallback(a.m_pConfigureCallback ? a.m_pConfigureCallback->code() : QString::null);
+ m_pHelpCallback = 0;
+ setHelpCallback(a.m_pHelpCallback ? a.m_pHelpCallback->code() : QString::null);
+}
+
+KviKvsScriptAddon::KviKvsScriptAddon()
+: KviHeapObject()
+{
+ m_pVisibleNameScript = 0;
+ m_pDescriptionScript = 0;
+ m_pUninstallCallback = 0;
+ m_pConfigureCallback = 0;
+ m_pHelpCallback = 0;
+}
+
+KviKvsScriptAddon::~KviKvsScriptAddon()
+{
+ if(m_pVisibleNameScript)delete m_pVisibleNameScript;
+ if(m_pDescriptionScript)delete m_pDescriptionScript;
+ if(m_pUninstallCallback)delete m_pUninstallCallback;
+ if(m_pConfigureCallback)delete m_pConfigureCallback;
+ if(m_pHelpCallback)delete m_pHelpCallback;
+}
+
+QPixmap * KviKvsScriptAddon::icon()
+{
+ return g_pIconManager->getBigIcon(m_szIconId.isEmpty() ? QString(KVI_BIGICON_KVS) : m_szIconId);
+}
+
+const QString & KviKvsScriptAddon::visibleName()
+{
+ if(!m_pVisibleNameScript)return m_szVisibleName;
+ if(!m_pVisibleNameScript->run(g_pActiveWindow,0,m_szVisibleName))m_szVisibleName = m_pVisibleNameScript->code();
+ return m_szVisibleName;
+}
+
+const QString & KviKvsScriptAddon::description()
+{
+ if(!m_pDescriptionScript)return m_szDescription;
+ if(!m_pDescriptionScript->run(g_pActiveWindow,0,m_szDescription))m_szDescription = m_pDescriptionScript->code();
+ return m_szDescription;
+}
+
+const QString & KviKvsScriptAddon::visibleNameCode()
+{
+ return m_pVisibleNameScript->code();
+}
+
+const QString & KviKvsScriptAddon::descriptionCode()
+{
+ return m_pDescriptionScript->code();
+}
+
+const QString & KviKvsScriptAddon::uninstallCallbackCode()
+{
+ return m_pUninstallCallback->code();
+}
+
+const QString & KviKvsScriptAddon::configureCallbackCode()
+{
+ if(m_pConfigureCallback)return m_pConfigureCallback->code();
+ return KviQString::empty;
+}
+
+const QString & KviKvsScriptAddon::helpCallbackCode()
+{
+ if(m_pHelpCallback)return m_pHelpCallback->code();
+ return KviQString::empty;
+}
+
+bool KviKvsScriptAddon::load(KviConfig * cfg,const QString &szName)
+{
+ m_szName = szName;
+ cfg->setGroup(m_szName);
+ m_szVersion = cfg->readQStringEntry("Version");
+ m_szIconId = cfg->readQStringEntry("IconId");
+ if(m_szVersion.isEmpty())return false;
+ QString tmp1,tmp2,tmp3;
+ tmp1 = cfg->readQStringEntry("VisibleNameCode");
+ tmp2 = cfg->readQStringEntry("DescriptionCode");
+ tmp3 = cfg->readQStringEntry("UninstallCallback");
+ if(tmp1.isEmpty())return false;
+ allocateScripts(tmp1,tmp2,tmp3);
+ tmp1 = cfg->readQStringEntry("ConfigureCallback");
+ if(!tmp1.isEmpty())
+ setConfigureCallback(tmp1);
+ tmp1 = cfg->readQStringEntry("HelpCallback");
+ if(!tmp1.isEmpty())
+ setHelpCallback(tmp1);
+ return true;
+}
+
+void KviKvsScriptAddon::setConfigureCallback(const QString &szConfigureCallbackCode)
+{
+ if(m_pConfigureCallback)delete m_pConfigureCallback;
+ if(szConfigureCallbackCode.isEmpty())
+ {
+ m_pConfigureCallback = 0;
+ return;
+ }
+
+ QString szKvsName = "addon::";
+ szKvsName += m_szName;
+
+ QString szTmp;
+
+ szTmp = szKvsName;
+ szTmp += "::configure";
+ m_pConfigureCallback = new KviKvsScript(szTmp,szConfigureCallbackCode,KviKvsScript::InstructionList);
+}
+
+void KviKvsScriptAddon::setHelpCallback(const QString &szHelpCallbackCode)
+{
+ if(m_pHelpCallback)delete m_pHelpCallback;
+ if(szHelpCallbackCode.isEmpty())
+ {
+ m_pHelpCallback = 0;
+ return;
+ }
+
+ QString szKvsName = "addon::";
+ szKvsName += m_szName;
+
+ QString szTmp;
+
+ szTmp = szKvsName;
+ szTmp += "::help";
+ m_pHelpCallback = new KviKvsScript(szTmp,szHelpCallbackCode,KviKvsScript::InstructionList);
+}
+
+void KviKvsScriptAddon::allocateScripts(const QString &szVisibleNameCode,const QString &szDescriptionCode,const QString &szUninstallCallbackCode)
+{
+ QString szKvsName = "addon::";
+ szKvsName += m_szName;
+
+ QString szTmp;
+
+ szTmp = szKvsName;
+ szTmp += "::name";
+ m_pVisibleNameScript = new KviKvsScript(szTmp,szVisibleNameCode,KviKvsScript::Parameter);
+ szTmp = szKvsName;
+ szTmp += "::description";
+ m_pDescriptionScript = new KviKvsScript(szTmp,szDescriptionCode,KviKvsScript::Parameter);
+ szTmp = szKvsName;
+ szTmp += "::uninstall";
+ m_pUninstallCallback = new KviKvsScript(szTmp,szUninstallCallbackCode,KviKvsScript::InstructionList);
+}
+
+void KviKvsScriptAddon::save(KviConfig * cfg)
+{
+ cfg->setGroup(m_szName);
+ cfg->writeEntry("Version",m_szVersion);
+ cfg->writeEntry("VisibleNameCode",visibleNameCode());
+ cfg->writeEntry("DescriptionCode",descriptionCode());
+ cfg->writeEntry("UninstallCallback",uninstallCallbackCode());
+ cfg->writeEntry("ConfigureCallback",configureCallbackCode());
+ cfg->writeEntry("HelpCallback",helpCallbackCode());
+ cfg->writeEntry("IconId",m_szIconId);
+}
+
+void KviKvsScriptAddon::executeUninstallCallback(KviWindow * pWnd)
+{
+ if(!m_pUninstallCallback)return;
+ m_pUninstallCallback->run(pWnd);
+}
+
+void KviKvsScriptAddon::executeConfigureCallback(KviWindow * pWnd)
+{
+ if(!m_pConfigureCallback)return;
+ m_pConfigureCallback->run(pWnd);
+}
+
+void KviKvsScriptAddon::executeHelpCallback(KviWindow * pWnd)
+{
+ if(!m_pHelpCallback)return;
+ m_pHelpCallback->run(pWnd);
+}
+
+
+
+
+
+KviKvsScriptAddonManager::KviKvsScriptAddonManager()
+{
+ m_pInstance = this;
+ m_bLoaded = false;
+ m_pAddonDict = new KviPointerHashTable<QString,KviKvsScriptAddon>(17,false);
+ m_pAddonDict->setAutoDelete(true);
+}
+
+KviKvsScriptAddonManager::~KviKvsScriptAddonManager()
+{
+ delete m_pAddonDict;
+}
+
+void KviKvsScriptAddonManager::init()
+{
+ if(KviKvsScriptAddonManager::instance())
+ {
+ debug("WARNING: Trying to create the KviKvsScriptAddonManager twice!");
+ return;
+ }
+ (void)new KviKvsScriptAddonManager();
+}
+
+void KviKvsScriptAddonManager::done()
+{
+ if(!KviKvsScriptAddonManager::instance())
+ {
+ debug("WARNING: Trying to destroy the KviKvsScriptAddonManager twice!");
+ return;
+ }
+ delete KviKvsScriptAddonManager::instance();
+}
+
+void KviKvsScriptAddonManager::load(const QString &szFileName)
+{
+ // in fact we implement delayed loading
+ // so this function only stores the filename
+ // from which we will load at the first request
+ m_szFileName = szFileName;
+ // this to make sure that we reload the addons
+ // if someone explicitly requests a load after we have already loaded
+ // (this does not happen in kvirc tough at the moment)
+ m_bLoaded = false;
+}
+
+void KviKvsScriptAddonManager::save(const QString &szFileName)
+{
+ if(!m_bLoaded)return; // nothing to store anyway
+ // we're stored here from now on...
+ m_szFileName = szFileName;
+
+ KviConfig cfg(szFileName,KviConfig::Write);
+
+ cfg.clear();
+
+ KviPointerHashTableIterator<QString,KviKvsScriptAddon> it(*m_pAddonDict);
+
+ while(KviKvsScriptAddon * a = it.current())
+ {
+ cfg.setGroup(a->name());
+ a->save(&cfg);
+ ++it;
+ }
+}
+
+void KviKvsScriptAddonManager::delayedLoad()
+{
+ if(m_bLoaded)return; // already loaded
+ m_bLoaded = true;
+ // ::load() might be never called if we don't have
+ // a scriptaddons.kvc file on disk, KviApp checks that.
+ // So finally m_szFileName may be empty here
+ if(m_szFileName.isEmpty())return;
+
+ KviConfig cfg(m_szFileName,KviConfig::Read);
+
+ KviPointerHashTable<QString,KviConfigGroup> * d = cfg.dict();
+ if(!d)return;
+
+ KviPointerHashTableIterator<QString,KviConfigGroup> it(*d);
+ while(it.current())
+ {
+ QString szName = it.currentKey();
+ KviKvsScriptAddon * a = new KviKvsScriptAddon();
+ if(a->load(&cfg,szName))
+ m_pAddonDict->replace(szName,a);
+ else
+ delete a;
+ ++it;
+ }
+}
+
+KviPointerHashTable<QString,KviKvsScriptAddon> * KviKvsScriptAddonManager::addonDict()
+{
+ if(!m_bLoaded)delayedLoad();
+ return m_pAddonDict;
+}
+
+
+
+
+
+bool KviKvsScriptAddonManager::registerAddon(KviKvsScriptAddonRegistrationData * d)
+{
+ if(findAddon(d->szName))return false;
+ KviKvsScriptAddon * a = new KviKvsScriptAddon(
+ d->szName,
+ d->szVersion,
+ d->szVisibleNameScript,
+ d->szDescriptionScript,
+ d->szUninstallCallbackScript,
+ d->szIconId);
+ m_pAddonDict->replace(d->szName,a);
+ return true;
+}
+
+KviKvsScriptAddon * KviKvsScriptAddonManager::findAddon(const QString &szName)
+{
+ if(!m_bLoaded)delayedLoad();
+ return m_pAddonDict->find(szName);
+}
+
+bool KviKvsScriptAddonManager::unregisterAddon(const QString &szName,KviWindow * pWnd,bool bExecuteUninstallCallback)
+{
+ KviKvsScriptAddon * a = findAddon(szName);
+ if(!a)return false;
+
+ // remove the addon before executing the uninstall callback
+ // so the user effectively can't call addon.unregister on itself in the uninstall callback code :D
+ m_pAddonDict->setAutoDelete(false);
+ m_pAddonDict->remove(szName);
+ m_pAddonDict->setAutoDelete(true);
+
+ if(bExecuteUninstallCallback)
+ a->executeUninstallCallback(pWnd);
+
+ delete a;
+ return true;
+}
+
+void KviKvsScriptAddonManager::clear()
+{
+ if(!m_bLoaded)delayedLoad();
+ m_pAddonDict->clear();
+}
diff --git a/src/kvirc/kvs/kvi_kvs_scriptaddonmanager.h b/src/kvirc/kvs/kvi_kvs_scriptaddonmanager.h
new file mode 100644
index 00000000..428ba58d
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_scriptaddonmanager.h
@@ -0,0 +1,129 @@
+#ifndef _KVI_KVS_SCRIPTADDONMANAGER_H_
+#define _KVI_KVS_SCRIPTADDONMANAGER_H_
+//=============================================================================
+//
+// File : kvi_kvs_scriptaddonmanager.h
+// Created on Thu 31 Mar 2005 01:21:23 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_heapobject.h"
+#include "kvi_qstring.h"
+#include "kvi_pointerhashtable.h"
+
+
+class KviConfig;
+class KviKvsScript;
+class KviWindow;
+class QPixmap;
+
+class KVIRC_API KviKvsScriptAddon : public KviHeapObject
+{
+ friend class KviKvsScriptAddonManager;
+protected:
+ KviKvsScriptAddon();
+ KviKvsScriptAddon(
+ const QString &szName,
+ const QString &szVersion,
+ const QString &szVisibleNameCode,
+ const QString &szDescriptionCode,
+ const QString &szUninstallCallbackCode,
+ const QString &szIconId
+ );
+public:
+ KviKvsScriptAddon(const KviKvsScriptAddon &a);
+public: // KviDict wants that... how to restrict the deletion to KviKvsScriptAddonManager only ?
+ ~KviKvsScriptAddon();
+protected:
+ QString m_szName; // the short name of the addon
+ QString m_szVersion; // x.y.z
+ KviKvsScript * m_pVisibleNameScript; // the visible name, possibly translated
+ KviKvsScript * m_pDescriptionScript; // the description, possibly translated
+ KviKvsScript * m_pUninstallCallback; // uninstall callback
+ KviKvsScript * m_pConfigureCallback; // configure callback
+ KviKvsScript * m_pHelpCallback; // help callback
+ QString m_szDescription; // parsed description
+ QString m_szVisibleName; // parsed visible name
+ QString m_szIconId;
+public:
+ const QString &name() const { return m_szName; };
+ const QString &version() const { return m_szVersion; };
+ const QString &visibleName();
+ const QString &description();
+ const QString &visibleNameCode();
+ const QString &descriptionCode();
+ const QString &uninstallCallbackCode();
+ const QString &configureCallbackCode();
+ const QString &helpCallbackCode();
+ const QString &iconId(){ return m_szIconId; };
+ QPixmap * icon();
+ void setConfigureCallback(const QString &szConfigureCallbackCode);
+ void setHelpCallback(const QString &szHelpCallbackCode);
+ void executeConfigureCallback(KviWindow * pWnd);
+ void executeHelpCallback(KviWindow * pWnd);
+protected:
+ bool load(KviConfig * cfg,const QString &szName);
+ void save(KviConfig * cfg);
+ void executeUninstallCallback(KviWindow * pWnd);
+ // this assumes that the script pointers are clean (i.e. not needing to be freed!)
+ void allocateScripts(const QString &sVisibleNameCode,const QString &szDescriptionCode,const QString &szUninstallCallbackCode);
+};
+
+class KVIRC_API KviKvsScriptAddonRegistrationData
+{
+public:
+ QString szName; // the addon name
+ QString szVersion; // the addon version in form x.y.z
+ QString szVisibleNameScript; // the code that evaluates to the visible name, possibly translated
+ QString szDescriptionScript; // the code that evaluates to the description, possibly translated
+ QString szUninstallCallbackScript; // the uninstall callback code, will be executed at uninstallation
+ QString szIconId; // the icon identifier (scaled to 32x32 atm)
+};
+
+class KVIRC_API KviKvsScriptAddonManager
+{
+public:
+ KviKvsScriptAddonManager();
+ ~KviKvsScriptAddonManager();
+protected:
+ static KviKvsScriptAddonManager * m_pInstance;
+ // this class implements delayed loading
+ QString m_szFileName; // the file name that we will load from
+ bool m_bLoaded; // have we loaded stuff from disk yet ?
+ KviPointerHashTable<QString,KviKvsScriptAddon> * m_pAddonDict; // all the registered addons
+public:
+ static KviKvsScriptAddonManager * instance(){ return m_pInstance; };
+ static void init(); // called by KviKvs::init()
+ static void done(); // called by KviKvs::done()
+
+ bool registerAddon(KviKvsScriptAddonRegistrationData * d);
+ KviKvsScriptAddon * findAddon(const QString &szName);
+ bool unregisterAddon(const QString &szName,KviWindow * pWnd,bool bExecuteUninstallCallback = true);
+ KviPointerHashTable<QString,KviKvsScriptAddon> * addonDict();
+
+ void clear();
+ void load(const QString &szFileName); // called in the KviKvs namespace
+ void save(const QString &szFileName); // called in the KViKvs namespace
+protected:
+ void delayedLoad();
+};
+
+#endif //!_KVI_KVS_SCRIPTADDONMANAGER_H_
diff --git a/src/kvirc/kvs/kvi_kvs_switchlist.cpp b/src/kvirc/kvs/kvi_kvs_switchlist.cpp
new file mode 100644
index 00000000..aa4ebdbd
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_switchlist.cpp
@@ -0,0 +1,75 @@
+//=============================================================================
+//
+// File : kvi_kvs_switchlist.cpp
+// Created on Mon 27 Oct 2003 03:47:48 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_switchlist.h"
+
+KviKvsSwitchList::KviKvsSwitchList()
+{
+ m_pShortSwitchDict = 0;
+ m_pLongSwitchDict = 0;
+}
+
+
+KviKvsSwitchList::~KviKvsSwitchList()
+{
+ if(m_pShortSwitchDict)delete m_pShortSwitchDict;
+ if(m_pLongSwitchDict)delete m_pLongSwitchDict;
+}
+
+void KviKvsSwitchList::clear()
+{
+ if(m_pShortSwitchDict)
+ {
+ delete m_pShortSwitchDict;
+ m_pShortSwitchDict = 0;
+ }
+ if(m_pLongSwitchDict)
+ {
+ delete m_pLongSwitchDict;
+ m_pLongSwitchDict = 0;
+ }
+}
+
+void KviKvsSwitchList::addShort(unsigned short uShortKey,KviKvsVariant * pVariant)
+{
+ if(!m_pShortSwitchDict)
+ {
+ m_pShortSwitchDict = new KviPointerHashTable<unsigned short,KviKvsVariant>(11);
+ m_pShortSwitchDict->setAutoDelete(true);
+ }
+ m_pShortSwitchDict->replace(uShortKey,pVariant);
+}
+
+void KviKvsSwitchList::addLong(const QString &szLongKey,KviKvsVariant * pVariant)
+{
+ if(!m_pLongSwitchDict)
+ {
+ m_pLongSwitchDict = new KviPointerHashTable<QString,KviKvsVariant>(11);
+ m_pLongSwitchDict->setAutoDelete(true);
+ }
+ m_pLongSwitchDict->replace(szLongKey,pVariant);
+}
+
diff --git a/src/kvirc/kvs/kvi_kvs_switchlist.h b/src/kvirc/kvs/kvi_kvs_switchlist.h
new file mode 100644
index 00000000..ea496b3e
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_switchlist.h
@@ -0,0 +1,87 @@
+#ifndef _KVI_KVS_SWITCHLIST_H_
+#define _KVI_KVS_SWITCHLIST_H_
+//=============================================================================
+//
+// File : kvi_kvs_switchlist.h
+// Created on Mon 27 Oct 2003 03:47:48 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_variant.h"
+
+#include "kvi_pointerhashtable.h"
+#include "kvi_pointerhashtable.h"
+
+class KVIRC_API KviKvsSwitchList
+{
+public:
+ KviKvsSwitchList();
+ ~KviKvsSwitchList();
+protected:
+ KviPointerHashTable<unsigned short,KviKvsVariant> * m_pShortSwitchDict;
+ KviPointerHashTable<QString,KviKvsVariant> * m_pLongSwitchDict;
+public:
+ void clear();
+ void addShort(unsigned short uShortKey,KviKvsVariant * pVariant);
+ void addLong(const QString &szLongKey,KviKvsVariant * pVariant);
+
+ bool isEmpty(){ return ((m_pShortSwitchDict == 0) && (m_pLongSwitchDict == 0)); };
+
+ KviKvsVariant * find(const QChar &c)
+ {
+ return m_pShortSwitchDict ? m_pShortSwitchDict->find(c.unicode()) : 0;
+ };
+
+ KviKvsVariant * find(unsigned short uShortKey)
+ {
+ return m_pShortSwitchDict ? m_pShortSwitchDict->find((int)uShortKey) : 0;
+ };
+
+ KviKvsVariant * find(const QString &szLongKey)
+ {
+ return m_pLongSwitchDict ? m_pLongSwitchDict->find(szLongKey) : 0;
+ };
+
+ KviKvsVariant * find(unsigned short uShortKey,const QString &szLongKey)
+ {
+ if(m_pLongSwitchDict)
+ {
+ KviKvsVariant * t;
+ t = m_pLongSwitchDict->find(szLongKey);
+ if(t)return t;
+ }
+ return m_pShortSwitchDict ? m_pShortSwitchDict->find((int)uShortKey) : 0;
+ };
+
+ bool getAsStringIfExisting(unsigned short uShortKey,const QString &szLongKey,QString &szBuffer)
+ {
+ KviKvsVariant * v = find(uShortKey,szLongKey);
+ if(v)
+ {
+ v->asString(szBuffer);
+ return true;
+ }
+ return false;
+ };
+};
+
+#endif //!_KVI_KVS_SWITCHLIST_H_
diff --git a/src/kvirc/kvs/kvi_kvs_timermanager.cpp b/src/kvirc/kvs/kvi_kvs_timermanager.cpp
new file mode 100644
index 00000000..91af693d
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_timermanager.cpp
@@ -0,0 +1,256 @@
+//=============================================================================
+//
+// File : kvi_kvs_timermanager.cpp
+// Created on Fri 19 Dec 2003 01:29:22 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_timermanager.h"
+
+#include "kvi_kvs_script.h"
+#include "kvi_kvs_variantlist.h"
+#include "kvi_kvs_runtimecontext.h"
+
+#include "kvi_app.h"
+#include "kvi_window.h"
+#include "kvi_console.h"
+#include "kvi_options.h"
+#include "kvi_locale.h"
+#include "kvi_out.h"
+
+
+KviKvsTimer::KviKvsTimer(const QString &szName,Lifetime l,KviWindow * pWnd,int iDelay,int iId,KviKvsScript * pCallback,KviKvsVariantList * pParams)
+{
+ m_szName = szName;
+ m_eLifetime = l;
+ m_pWnd = pWnd;
+ m_iDelay = iDelay;
+ m_iId = iId;
+ m_pCallback = pCallback;
+ //m_pVariables = new KviKvsHash();
+ m_pRunTimeData = new KviKvsExtendedRunTimeData(new KviKvsHash(),TRUE);
+ m_pParameterList = pParams;
+}
+
+KviKvsTimer::~KviKvsTimer()
+{
+ delete m_pRunTimeData;
+ delete m_pParameterList;
+ delete m_pCallback;
+}
+
+
+
+
+
+
+
+KviKvsTimerManager * KviKvsTimerManager::m_pInstance = 0;
+
+
+KviKvsTimerManager::KviKvsTimerManager()
+: QObject()
+{
+ m_pTimerDictById = new KviPointerHashTable<int,KviKvsTimer>(17);
+ m_pTimerDictById->setAutoDelete(false);
+ m_pTimerDictByName = new KviPointerHashTable<QString,KviKvsTimer>(17,false);
+ m_pTimerDictByName->setAutoDelete(false);
+ m_pKilledTimerList = 0;
+ m_iAssassinTimer = 0;
+ m_iCurrentTimer = 0;
+}
+
+KviKvsTimerManager::~KviKvsTimerManager()
+{
+ delete m_pTimerDictById;
+ m_pTimerDictByName->setAutoDelete(true);
+ delete m_pTimerDictByName;
+ if(m_pKilledTimerList)delete m_pKilledTimerList;
+}
+
+void KviKvsTimerManager::init()
+{
+ if(KviKvsTimerManager::m_pInstance)
+ {
+ debug("Trying to double init() the timer manager!");
+ return;
+ }
+ KviKvsTimerManager::m_pInstance = new KviKvsTimerManager();
+}
+
+void KviKvsTimerManager::done()
+{
+ if(!KviKvsTimerManager::m_pInstance)
+ {
+ debug("Trying to call done() on a non existing timer manager!");
+ return;
+ }
+ delete KviKvsTimerManager::m_pInstance;
+ KviKvsTimerManager::m_pInstance = 0;
+}
+
+bool KviKvsTimerManager::addTimer(const QString &szName,KviKvsTimer::Lifetime l,KviWindow * pWnd,int iDelay,KviKvsScript * pCallback,KviKvsVariantList * pParams)
+{
+ int iId = startTimer(iDelay);
+
+ if(iId <= 0)
+ {
+ delete pCallback;
+ pCallback = 0;
+ delete pParams;
+ pParams = 0;
+ return false;
+ }
+
+ KviKvsTimer * t = new KviKvsTimer(szName,l,pWnd,iDelay,iId,pCallback,pParams);
+ KviKvsTimer * old = m_pTimerDictByName->find(szName);
+ if(old)deleteTimer(old->id());
+ m_pTimerDictByName->insert(szName,t);
+ m_pTimerDictById->insert(t->id(),t);
+ return true;
+}
+
+bool KviKvsTimerManager::deleteTimer(const QString &szName)
+{
+ KviKvsTimer * t = m_pTimerDictByName->find(szName);
+ if(!t)return false;
+ killTimer(t->id());
+ m_pTimerDictById->remove(t->id());
+ m_pTimerDictByName->remove(szName);
+ scheduleKill(t);
+ return true;
+}
+
+bool KviKvsTimerManager::deleteTimer(int iId)
+{
+ KviKvsTimer * t = m_pTimerDictById->find(iId);
+ if(!t)return false;
+ killTimer(t->id());
+ m_pTimerDictById->remove(t->id());
+ m_pTimerDictByName->remove(t->name());
+ scheduleKill(t);
+ return true;
+}
+
+bool KviKvsTimerManager::deleteCurrentTimer()
+{
+ if(!m_iCurrentTimer)return false;
+ deleteTimer(m_iCurrentTimer);
+ m_iCurrentTimer = 0;
+ return true;
+}
+
+void KviKvsTimerManager::deleteAllTimers()
+{
+ if(m_pTimerDictById->isEmpty())return;
+ KviPointerHashTableIterator<int,KviKvsTimer> it(*m_pTimerDictById);
+ KviPointerList<KviKvsTimer> tl;
+ tl.setAutoDelete(false);
+ while(KviKvsTimer * t = it.current())
+ {
+ tl.append(t);
+ ++it;
+ }
+ for(KviKvsTimer * dying = tl.first();dying;dying = tl.next())
+ {
+ deleteTimer(dying->id());
+ }
+}
+
+void KviKvsTimerManager::scheduleKill(KviKvsTimer *t)
+{
+ if(!m_pKilledTimerList)
+ {
+ m_pKilledTimerList = new KviPointerList<KviKvsTimer>;
+ m_pKilledTimerList->setAutoDelete(true);
+ }
+ m_pKilledTimerList->append(t);
+
+ if(!m_iAssassinTimer)m_iAssassinTimer = startTimer(0);
+}
+
+
+void KviKvsTimerManager::timerEvent(QTimerEvent *e)
+{
+ int iId = e->timerId();
+
+ if(iId == m_iAssassinTimer)
+ {
+ if(!m_pKilledTimerList)
+ {
+ debug("ops.. assassing timer with no victims ?");
+ } else {
+ m_pKilledTimerList->clear();
+ }
+ killTimer(m_iAssassinTimer);
+ m_iAssassinTimer = 0;
+ return;
+ }
+
+ KviKvsTimer * t = m_pTimerDictById->find(iId);
+ if(!t)
+ {
+ debug("Internal error: got an nonexistant timer event");
+ return; // HUH ?
+ }
+
+ if(!g_pApp->windowExists(t->window()))
+ {
+ if(t->lifetime() != KviKvsTimer::Persistent)
+ {
+ deleteTimer(t->id());
+ return;
+ }
+
+ // rebind to an existing console
+ t->setWindow(g_pApp->activeConsole());
+ }
+
+ KviKvsScript copy(*(t->callback()));
+
+ m_iCurrentTimer = t->id();
+ bool bRet = copy.run(t->window(),
+ t->parameterList(),
+ 0,
+ KviKvsScript::PreserveParams,
+ t->runTimeData());
+
+ m_iCurrentTimer = 0;
+
+ if(!bRet)
+ {
+ // the timer may already have been scheduled for killing!
+ if(KVI_OPTION_BOOL(KviOption_boolKillBrokenTimers))
+ {
+ t->window()->output(KVI_OUT_PARSERERROR,__tr2qs("Timer '%Q' has a broken callback handler: killing the timer"),&(t->name()));
+ deleteTimer(t->id());
+ }
+ return;
+ }
+
+ // the timer may already have been scheduled for killing!
+
+ if(t->lifetime() == KviKvsTimer::SingleShot)
+ {
+ deleteTimer(t->id());
+ }
+}
diff --git a/src/kvirc/kvs/kvi_kvs_timermanager.h b/src/kvirc/kvs/kvi_kvs_timermanager.h
new file mode 100644
index 00000000..f8e20f10
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_timermanager.h
@@ -0,0 +1,123 @@
+#ifndef _KVI_KVS_TIMERMANAGER_H_
+#define _KVI_KVS_TIMERMANAGER_H_
+//=============================================================================
+//
+// File : kvi_kvs_timermanager.h
+// Created on Fri 19 Dec 2003 01:29:22 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+
+#include <qobject.h>
+#include "kvi_pointerhashtable.h"
+#include "kvi_pointerhashtable.h"
+#include "kvi_pointerlist.h"
+
+class KviKvsTimerManager;
+class KviKvsScript;
+class KviKvsHash;
+class KviKvsVariantList;
+class KviKvsExtendedRunTimeData;
+
+class KviWindow;
+
+// FIXME: This stuff could be moved to a module
+// called timer
+// timer.start(){}
+// timer.stop
+// timer.exists
+// timer.timeout
+// timer.suspend
+// etc...
+// Then we could remap timer.start to the old /timer call
+// by hardcoding it...
+
+class KVIRC_API KviKvsTimer
+{
+ friend class KviKvsTimerManager;
+public:
+ enum Lifetime { SingleShot, WindowLifetime, Persistent };
+protected:
+ KviKvsTimer(const QString &szName,Lifetime l,KviWindow * pWnd,int iDelay,int iId,KviKvsScript * pCallback,KviKvsVariantList * pParams);
+public:
+ ~KviKvsTimer();
+protected:
+ Lifetime m_eLifetime; // the type of this timer
+ KviWindow * m_pWnd; // the window that this timer is (currently) bound to
+ QString m_szName; // this timer name
+ KviKvsScript * m_pCallback; // callback to be executed at timer shots
+ int m_iDelay; // the timer delay in msecs
+ int m_iId; // the system id of this timer
+ KviKvsExtendedRunTimeData * m_pRunTimeData; // ext run time data for this timer object
+ KviKvsVariantList * m_pParameterList; // parameter list
+public:
+ KviWindow * window(){ return m_pWnd; };
+ const QString & name(){ return m_szName; };
+ const KviKvsScript * callback(){ return m_pCallback; };
+ Lifetime lifetime(){ return m_eLifetime; };
+ int delay(){ return m_iDelay; };
+ int id(){ return m_iId; };
+ //KviKvsHash * variables(){ return m_pVariables; };
+ KviKvsExtendedRunTimeData * runTimeData(){ return m_pRunTimeData; };
+ KviKvsVariantList * parameterList(){ return m_pParameterList; };
+protected:
+ void setWindow(KviWindow * pWnd){ m_pWnd = pWnd; };
+};
+
+
+class KVIRC_API KviKvsTimerManager : public QObject
+{
+ Q_OBJECT
+protected: // it only can be created and destroyed by KviKvsTimerManager::init()/done()
+ KviKvsTimerManager();
+ ~KviKvsTimerManager();
+private:
+ KviPointerHashTable<int,KviKvsTimer> * m_pTimerDictById; // stored by id
+ KviPointerHashTable<QString,KviKvsTimer> * m_pTimerDictByName; // stored by name
+ static KviKvsTimerManager * m_pInstance; // the one and only timer manager instance
+ KviPointerList<KviKvsTimer> * m_pKilledTimerList; // list of timers for that killing has been scheduled
+ int m_iAssassinTimer; // assassin timer id
+ int m_iCurrentTimer; // the timer currently executed
+public:
+ static KviKvsTimerManager * instance(){ return m_pInstance; };
+ static void init();
+ static void done();
+ // the pCallback and pParams are owned by the timer: they WILL be deleted
+ bool addTimer(const QString &szName,KviKvsTimer::Lifetime l,KviWindow * pWnd,int iDelay,KviKvsScript * pCallback,KviKvsVariantList * pParams);
+ bool deleteTimer(const QString &szName);
+ bool deleteTimer(int iId);
+ // the timer manager does not trigger timers concurrently
+ // this means that if this is called from a timer handler
+ // the current timer will be unique
+ bool deleteCurrentTimer();
+ void deleteAllTimers();
+ bool timerExists(const QString &szName){ return m_pTimerDictByName->find(szName); };
+ KviPointerHashTable<QString,KviKvsTimer> * timerDict()
+ { return m_pTimerDictByName; };
+protected:
+ void scheduleKill(KviKvsTimer * t);
+ virtual void timerEvent(QTimerEvent *e);
+};
+
+
+#endif //!_KVI_KVS_TIMERMANAGER_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode.h b/src/kvirc/kvs/kvi_kvs_treenode.h
new file mode 100644
index 00000000..0f9505ed
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode.h
@@ -0,0 +1,375 @@
+#ifndef _KVI_KVS_TREENODE_H_
+#define _KVI_KVS_TREENODE_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode.h
+// Creation date : Thu 25 Sep 2003 05.12 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_kvs_treenode_base.h"
+
+#include "kvi_kvs_treenode_aliasfunctioncall.h"
+#include "kvi_kvs_treenode_aliassimplecommand.h"
+#include "kvi_kvs_treenode_arraycount.h"
+#include "kvi_kvs_treenode_arrayelement.h"
+#include "kvi_kvs_treenode_arrayorhashelement.h"
+#include "kvi_kvs_treenode_arrayreferenceassert.h"
+#include "kvi_kvs_treenode_baseobjectfunctioncall.h"
+#include "kvi_kvs_treenode_callbackcommand.h"
+#include "kvi_kvs_treenode_command.h"
+#include "kvi_kvs_treenode_commandevaluation.h"
+#include "kvi_kvs_treenode_commandwithparameters.h"
+#include "kvi_kvs_treenode_compositedata.h"
+#include "kvi_kvs_treenode_constantdata.h"
+#include "kvi_kvs_treenode_corecallbackcommand.h"
+#include "kvi_kvs_treenode_corefunctioncall.h"
+#include "kvi_kvs_treenode_coresimplecommand.h"
+#include "kvi_kvs_treenode_data.h"
+#include "kvi_kvs_treenode_datalist.h"
+#include "kvi_kvs_treenode_expression.h"
+#include "kvi_kvs_treenode_expressionreturn.h"
+#include "kvi_kvs_treenode_extendedscopevariable.h"
+#include "kvi_kvs_treenode_functioncall.h"
+#include "kvi_kvs_treenode_globalvariable.h"
+#include "kvi_kvs_treenode_hashcount.h"
+#include "kvi_kvs_treenode_hashelement.h"
+#include "kvi_kvs_treenode_hashreferenceassert.h"
+#include "kvi_kvs_treenode_indirectdata.h"
+#include "kvi_kvs_treenode_instruction.h"
+#include "kvi_kvs_treenode_instructionblock.h"
+#include "kvi_kvs_treenode_localvariable.h"
+#include "kvi_kvs_treenode_modulecallbackcommand.h"
+#include "kvi_kvs_treenode_modulefunctioncall.h"
+#include "kvi_kvs_treenode_modulesimplecommand.h"
+#include "kvi_kvs_treenode_multipleparameteridentifier.h"
+#include "kvi_kvs_treenode_objectfield.h"
+#include "kvi_kvs_treenode_objectfunctioncall.h"
+#include "kvi_kvs_treenode_operation.h"
+#include "kvi_kvs_treenode_parameterreturn.h"
+#include "kvi_kvs_treenode_rebindingswitch.h"
+#include "kvi_kvs_treenode_scopeoperator.h"
+#include "kvi_kvs_treenode_simplecommand.h"
+#include "kvi_kvs_treenode_singleparameteridentifier.h"
+#include "kvi_kvs_treenode_specialcommand.h"
+#include "kvi_kvs_treenode_specialcommandbreak.h"
+#include "kvi_kvs_treenode_specialcommandclass.h"
+#include "kvi_kvs_treenode_specialcommanddefpopup.h"
+#include "kvi_kvs_treenode_specialcommanddo.h"
+#include "kvi_kvs_treenode_specialcommandfor.h"
+#include "kvi_kvs_treenode_specialcommandforeach.h"
+#include "kvi_kvs_treenode_specialcommandif.h"
+#include "kvi_kvs_treenode_specialcommandswitch.h"
+#include "kvi_kvs_treenode_specialcommandunset.h"
+#include "kvi_kvs_treenode_specialcommandwhile.h"
+#include "kvi_kvs_treenode_stringcast.h"
+#include "kvi_kvs_treenode_switchlist.h"
+#include "kvi_kvs_treenode_thisobjectfunctioncall.h"
+#include "kvi_kvs_treenode_variable.h"
+#include "kvi_kvs_treenode_voidfunctioncall.h"
+
+//
+// Hierarchy (the nodes that have some missing implementation have the leading '?' char)
+//
+//
+// TreeNode(OK) (never instantiated)
+// |
+// +--Instruction(OK) (never instantiated) (used as interface by InstructionBlock) : instruction has bool execute() = 0;
+// | |
+// | +--InstructionBlock(OK)
+// | |
+// | +--ExpressionReturn(OK)
+// | |
+// | +--ParameterReturn(OK)
+// | |
+// | |--Command(OK) (never instantiated)
+// | | |
+// | | +--RebindingSwitch(OK)
+// | | |
+// | | +--CommandWithParameters(OK) (never instantiated)
+// | | | |
+// | | | +--SimpleCommand(OK) (never instantiated)
+// | | | | |
+// | | | | +--CoreSimpleCommand(OK)
+// | | | | |
+// | | | | +--ModuleSimpleCommand(OK)
+// | | | | |
+// | | | | +--AliasSimpleCommand(OK)
+// | | | |
+// | | | +--CallbackCommand(OK) (never instantiated)
+// | | | |
+// | | | +--CoreCallbackCommand(OK)
+// | | | |
+// | | | +--ModuleCallbackCommand(OK)
+// | | |
+// | | +--SpecialCommand(OK) (never instantiated)
+// | | |
+// | | +--SpecialCommandIf(OK)
+// | | |
+// | | +--SpecialCommandWhile(OK)
+// | | |
+// | | +--SpecialCommandDo(OK)
+// | | |
+// | | +--SpecialCommandForeach(OK)
+// | | |
+// | | +--SpecialCommandFor(OK)
+// | | |
+// | | +--SpecialCommandBreak(OK)
+// | | |
+// | | +--SpecialCommandSwitch(OK)
+// | | |
+// | | +--SpecialCommandDefpopup(OK)
+// | | |
+// | | +--SpecialCommandClass(OK)
+// | |
+// | +--VoidFunctionCall(OK)
+// | |
+// | +--Operation(OK) : has a m_pTargetData pointer (never instantiated)
+// | |
+// | +--OperationAssignment(OK)
+// | |
+// | +--OperationIncrement(OK)
+// | |
+// | +--OperationDecrement(OK)
+// | |
+// | +--OperationSelfSum(OK)
+// | |
+// | +--OperationSelfSubtraction(OK)
+// | |
+// | +--OperationSelfDivision(OK)
+// | |
+// | +--OperationSelfMultiplication(OK)
+// | |
+// | +--OperationSelfModulus(OK)
+// | |
+// | +--OperationSelfOr(OK)
+// | |
+// | +--OperationSelfAnd(OK)
+// | |
+// | +--OperationSelfXor(OK)
+// | |
+// | +--OperationSelfShl(OK)
+// | |
+// | +--OperationSelfShr(OK)
+// | |
+// | +--OperationStringAppend(OK)
+// | |
+// | +--OperationStringAppendWithComma(OK)
+// | |
+// | +--OperationStringAppendWithSpace(OK)
+// | |
+// | +--OperationStringTransliteration(OK)
+// | |
+// | +--OperationStringSubstitution(OK)
+// |
+// +--Data(OK) data has
+// | | bool evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer) <-- this MUST be implemented
+// | | KviKvsVariant * evaluateReadWrite(KviKvsRunTimeContext * c) <-- this MUST be implemented if isReadOnly returns false
+// | |
+// | | This class is NEVER instantiated directly
+// | |
+// | | isReadOnly(); true by default
+// | | canEvaluateToObjectReference(); false by default
+// | | isFunctionCall(); false by default
+// | | canEvaluateInObjectScope(); false by default
+// | | (DEAD)canReleaseResult(); false by default (can the result be simply "taken" ?)
+// | |
+// | +--StringCast(OK) has some kind of data inside that is converted to string "on the fly"
+// | |
+// | +--ConstantData(OK) have real constant data
+// | | everything inherited from data
+// | | only evaluateReadOnly is implemented and it never fails
+// | |
+// | +--CompositeData(OK) have real data composed of constants, it is an implicit StringCast too (it isn't inherited from StringCast since it operates in a different way)
+// | | everything inherited from data
+// | | only evaluateReadOnly is implemented and it never fails
+// | |
+// | +--ScopeOperator( ) Has a left side that must evaluate to ob reference
+// | | Has a right side that must be a variable reference or function call
+// | | isReadOnly() depends on the right child
+// | | canEvaluateToObjectReference() depends on last child
+// | | isFunctionCall() depends on last child
+// | | canEvaluateInObjectScope() depends on last child
+// | | (DEAD)canReleaseResult() depends on last child
+// | |
+// | +--SingleParameterIdentifier(OK) this is $n
+// | | canEvaluateToObjectReference() = true
+// | |
+// | +--MultipleParameterIdentifier(OK) this is $n-[n]
+// | |
+// | +--CommandEvaluation(OK) this is ${ ... }
+// | | canEvaluateToObjectReference() = true
+// | |
+// | +--Variable(OK) this is something related to %xxx (never instantiated)
+// | | | canEvaluateInObjectScope() = true
+// | | | isReadOnly() = false
+// | | | canEvaluateToObjectReference() = true
+// | | |
+// | | +--LocalVariable(OK)
+// | | |
+// | | +--GlobalVariable(OK)
+// | | |
+// | | +--ExtendedScopeVariable(OK)
+// | | |
+// | | +--ObjectField(OK)
+// | |
+// | +--IndirectData(OK) takes a Data as source (never instantiated)
+// | | | canEvaluateInObjectScope() depends on the parameter data
+// | | |
+// | | +--ArrayOrHashElement(OK) isReadOnly() depends on the source data (never instantiated)
+// | | | | canEvaluateToObjectReference() = true
+// | | | |
+// | | | +--ArrayElement(OK) the source Data must evaluate to an array or be writeable in order to convert it
+// | | | | and an index that must evaluate to an integer (evaluate ok, result inherited ok)
+// | | | |
+// | | | +--HashElement(OK) the source Data must evaluate to a hash or be writeable in order to convert it
+// | | | and an index that must evaluate to a non-empty hash key (evaluate ok, result inherited ok)
+// | | |
+// | | +--HashCount(OK) the source Data must evaluate to a hash or be writeable in order to convert it
+// | | |
+// | | +--ArrayCount(OK) the source Data must evaluate to an array or be writeable in order to convert it
+// | | |
+// | | +--HashReferenceAssert(OK) the source Data must evaluate to a hash or be writeable in order to convert it (otherwise asserts)
+// | | | isReadOnly() depends on the parameter data
+// | | |
+// | | +--ArrayReferenceAssert(OK) the source Data must evaluate to an array or be writeable in order to convert it (otherwise asserts)
+// | | isReadOnly() depends on the parameter data
+// | |
+// | +--Expression(OK) (never instantiated)
+// | | |
+// | | +--ExpressionVariableOperand(OK) (evaluate and result ok)
+// | | |
+// | | +--ExpressionConstantOperand(OK) (evaluate and result ok)
+// | | |
+// | | +--ExpressionOperator(OK) (never instantiated)
+// | | |
+// | | +--ExpressionBinaryOperator(OK) (never instantiated)
+// | | | |
+// | | | +--ExpressionBinaryOperatorSum(OK) (evaluate and result ok)
+// | | | |
+// | | | +--ExpressionBinaryOperatorSubtraction(OK) (evaluate and result ok)
+// | | | |
+// | | | +--ExpressionBinaryOperatorMultiplication(OK) (evaluate and result ok)
+// | | | |
+// | | | +--ExpressionBinaryOperatorDivision(OK) (evaluate and result ok)
+// | | | |
+// | | | +--ExpressionBinaryOperatorBitwiseAnd(OK) (evaluate and result ok)
+// | | | |
+// | | | +--ExpressionBinaryOperatorBitwiseOr(OK) (evaluate and result ok)
+// | | | |
+// | | | +--ExpressionBinaryOperatorBitwiseXor(OK) (evaluate and result ok)
+// | | | |
+// | | | +--ExpressionBinaryOperatorShiftLeft(OK) (evaluate and result ok)
+// | | | |
+// | | | +--ExpressionBinaryOperatorShiftRight(OK) (evaluate and result ok)
+// | | | |
+// | | | +--ExpressionBinaryOperatorAnd(OK) (evaluate and result ok)
+// | | | |
+// | | | +--ExpressionBinaryOperatorOr(OK) (evaluate and result ok)
+// | | | |
+// | | | +--ExpressionBinaryOperatorXor(OK) (evaluate and result ok)
+// | | | |
+// | | | +--ExpressionBinaryOperatorLowerThan(OK) (evaluate and result ok)
+// | | | |
+// | | | +--ExpressionBinaryOperatorGreaterThan(OK) (evaluate and result ok)
+// | | | |
+// | | | +--ExpressionBinaryOperatorLowerOrEqualTo(OK) (evaluate and result ok)
+// | | | |
+// | | | +--ExpressionBinaryOperatorGreaterOrEqualTo(OK) (evaluate and result ok)
+// | | | |
+// | | | +--ExpressionBinaryOperatorEqualTo(OK) (evaluate and result ok)
+// | | | |
+// | | | +--ExpressionBinaryOperatorNotEqualTo(OK) (evaluate and result ok)
+// | | |
+// | | +--ExpressionUnaryOperator(OK) (never instantiated)
+// | | |
+// | | +--ExpressionUnaryOperatorNegate(OK) (evaluate and result ok)
+// | | |
+// | | +--ExpressionUnaryOperatorBitwiseNot(OK) (evaluate and result ok)
+// | | |
+// | | +--ExpressionUnaryOperatorLogicalNot(OK) (evaluate and result ok)
+// | |
+// | +--FunctionCall(OK) this is something like $xxx and has a name. Can be called as a void instruction
+// | | canEvaluateToObjectReference() = true
+// | | isFunctionCall() = true
+// | |
+// | +--ModuleFunctionCall(OK)
+// | |
+// | +--AliasFunctionCall(OK)
+// | |
+// | +--CoreFunctionCall(OK)
+// | |
+// | +--ObjectFunctionCall( ) this is the only function call type appended to a scope operator
+// | | canEvaluateInObjectScope() = true (never instantiated)
+// | |
+// | +--ThisObjectFunctionCall( )
+// | |
+// | +--BaseObjectFunctionCall( )
+// |
+// +--DataList(OK)
+// |
+// +--SwitchList(OK)
+// |
+// +--SpecialCommandSwitchLabel(Never instantiated)
+// | |
+// | +--SpecialCommandSwitchLabelCase(OK)
+// | |
+// | +--SpecialCommandSwitchLabelMatch(OK)
+// | |
+// | +--SpecialCommandSwitchLabelRegexp(OK)
+// | |
+// | +--SpecialCommandSwitchLabelDefault(OK)
+// |
+// +--SpecialCommandDefpopupLabel(Never instantiated)
+// |
+// +--SpecialCommandDefpopupLabelPrologue(OK)
+// |
+// +--SpecialCommandDefpopupLabelEpilogue(OK)
+// |
+// +--SpecialCommandDefpopupConditionalLabel(Never instantiated)
+// |
+// +--SpecialCommandDefpopupLabelSeparator(OK)
+// |
+// +--SpecialCommandDefpopupConditionalLabelWithTextAndIcon (Never instantiated)
+// |
+// +--SpecialCommandDefpopupLabelPopup(OK)
+// |
+// +--SpecialCommandDefpopupLabelExtpopup(OK)
+// |
+// +--SpecialCommandDefpopupLabelItem(OK)
+// |
+// +--SpecialCommandDefpopupLabelLabel(OK)
+//
+//
+//
+
+
+//
+// Tree morphology
+//
+// InstructionBlock
+// [Instruction]
+//
+// ScopeOperator
+// [Data]->[Data]
+//
+
+
+#endif //!_KVI_KVS_TREENODE_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_aliasfunctioncall.cpp b/src/kvirc/kvs/kvi_kvs_treenode_aliasfunctioncall.cpp
new file mode 100644
index 00000000..f864cea6
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_aliasfunctioncall.cpp
@@ -0,0 +1,84 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_aliasfunctioncall.cpp
+// Created on Tue 07 Oct 2003 03:21:23 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_aliasfunctioncall.h"
+#include "kvi_kvs_variantlist.h"
+#include "kvi_kvs_aliasmanager.h"
+#include "kvi_locale.h"
+#include "kvi_qstring.h"
+
+KviKvsTreeNodeAliasFunctionCall::KviKvsTreeNodeAliasFunctionCall(const QChar * pLocation,const QString &szAliasName,KviKvsTreeNodeDataList * pParams)
+: KviKvsTreeNodeFunctionCall(pLocation,szAliasName,pParams)
+{
+
+}
+
+KviKvsTreeNodeAliasFunctionCall::~KviKvsTreeNodeAliasFunctionCall()
+{
+}
+
+void KviKvsTreeNodeAliasFunctionCall::contextDescription(QString &szBuffer)
+{
+ KviQString::sprintf(szBuffer,"Alias Function Call \"%Q\"",&m_szFunctionName);
+}
+
+
+
+void KviKvsTreeNodeAliasFunctionCall::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s AliasFunctionCall(%s)",prefix,m_szFunctionName.utf8().data());
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pParams->dump(tmp.utf8().data());
+#endif
+}
+
+bool KviKvsTreeNodeAliasFunctionCall::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ KviKvsVariantList l;
+ if(!m_pParams->evaluate(c,&l))return false;
+
+ pBuffer->setNothing();
+
+ const KviKvsScript * s = KviKvsAliasManager::instance()->lookup(m_szFunctionName);
+ if(!s)
+ {
+ c->error(this,__tr2qs("Call to undefined function '%Q'"),&m_szFunctionName);
+ return false;
+ }
+
+ KviKvsScript copy(*s); // quick reference
+
+ if(!copy.run(c->window(),&l,pBuffer,KviKvsScript::PreserveParams))
+ {
+ c->error(this,__tr2qs("Error in inner alias function call '%Q', called from this context"),&m_szFunctionName);
+ return false;
+ }
+#endif
+ return true;
+}
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_aliasfunctioncall.h b/src/kvirc/kvs/kvi_kvs_treenode_aliasfunctioncall.h
new file mode 100644
index 00000000..04ca50a3
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_aliasfunctioncall.h
@@ -0,0 +1,45 @@
+#ifndef _KVI_KVS_TREENODE_ALIASFUNCTIONCALL_H_
+#define _KVI_KVS_TREENODE_ALIASFUNCTIONCALL_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_aliasfunctioncall.h
+// Created on Tue 07 Oct 2003 03:21:23 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_treenode_functioncall.h"
+#include "kvi_kvs_treenode_datalist.h"
+
+class KviKvsRunTimeContext;
+
+class KVIRC_API KviKvsTreeNodeAliasFunctionCall : public KviKvsTreeNodeFunctionCall
+{
+public:
+ KviKvsTreeNodeAliasFunctionCall(const QChar * pLocation,const QString &szAliasName,KviKvsTreeNodeDataList * pParams);
+ ~KviKvsTreeNodeAliasFunctionCall();
+public:
+ virtual void dump(const char * prefix);
+ virtual void contextDescription(QString &szBuffer);
+ virtual bool evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer);
+};
+
+#endif //!_KVI_KVS_TREENODE_ALIASFUNCTIONCALL_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_aliassimplecommand.cpp b/src/kvirc/kvs/kvi_kvs_treenode_aliassimplecommand.cpp
new file mode 100644
index 00000000..974ae941
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_aliassimplecommand.cpp
@@ -0,0 +1,120 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_aliassimplecommand.cpp
+// Created on Thu 09 Oct 2003 02:16:42 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_aliassimplecommand.h"
+#include "kvi_kvs_treenode_datalist.h"
+#include "kvi_kvs_treenode_switchlist.h"
+#include "kvi_kvs_aliasmanager.h"
+#include "kvi_locale.h"
+#include "kvi_options.h"
+#include "kvi_irccontext.h"
+#include "kvi_window.h"
+#include "kvi_ircconnection.h"
+#include "kvi_qcstring.h"
+#include "kvi_out.h"
+
+
+KviKvsTreeNodeAliasSimpleCommand::KviKvsTreeNodeAliasSimpleCommand(const QChar * pLocation,const QString &szCmdName,KviKvsTreeNodeDataList * params)
+: KviKvsTreeNodeSimpleCommand(pLocation,szCmdName,params)
+{
+}
+
+
+KviKvsTreeNodeAliasSimpleCommand::~KviKvsTreeNodeAliasSimpleCommand()
+{
+}
+
+void KviKvsTreeNodeAliasSimpleCommand::contextDescription(QString &szBuffer)
+{
+ KviQString::sprintf(szBuffer,"Alias Simple Command \"%Q\"",&m_szCmdName);
+}
+
+void KviKvsTreeNodeAliasSimpleCommand::dump(const char * prefix)
+{
+ debug("%s AliasSimpleCommand(%s)",prefix,m_szCmdName.utf8().data());
+ dumpSwitchList(prefix);
+ dumpParameterList(prefix);
+}
+
+bool KviKvsTreeNodeAliasSimpleCommand::execute(KviKvsRunTimeContext * c)
+{
+ KviKvsVariantList l;
+ if(!m_pParams->evaluate(c,&l))return false;
+
+ KviKvsSwitchList swl;
+ if(m_pSwitches)
+ {
+ if(!(m_pSwitches->evaluate(c,&swl)))return false;
+ }
+
+ const KviKvsScript * s = KviKvsAliasManager::instance()->lookup(m_szCmdName);
+ if(!s)
+ {
+ if(KVI_OPTION_BOOL(KviOption_boolSendUnknownCommandsAsRaw))
+ {
+ QString szAll;
+ l.allAsString(szAll);
+
+ if(!szAll.isEmpty())szAll.prepend(" ");
+ szAll.prepend(m_szCmdName);
+
+ KviQCString szData;
+
+ if(!c->window()->context())
+ goto no_way_to_send_as_raw;
+ if(!c->window()->connection())
+ goto no_way_to_send_as_raw;
+
+ szData = c->window()->connection()->encodeText(szAll);
+ if(!szData.data())szData = "";
+
+ if(!c->window()->connection()->sendData(szData.data()))
+ goto no_way_to_send_as_raw;
+
+ c->window()->output(KVI_OUT_RAW,__tr2qs("[RAW]: %Q"),&szAll);
+ return true;
+no_way_to_send_as_raw:
+ c->warning(this,__tr2qs("Failed to send an unknown command as /raw"));
+ c->error(this,__tr2qs("Call to undefined command '%Q'"),&m_szCmdName);
+ return false;
+ } else {
+ c->error(this,__tr2qs("Call to undefined command '%Q'"),&m_szCmdName);
+ return false;
+ }
+ }
+
+ KviKvsScript copy(*s); // quick reference
+ // FIXME: the ExtRTData could be a member structure
+ // it would avoid the constructor call each time
+ KviKvsExtendedRunTimeData extData(&swl);
+
+ if(!copy.run(c->window(),&l,0,KviKvsScript::PreserveParams,&extData))
+ {
+ c->error(this,__tr2qs("Error in inner alias command call '%Q', called from this context"),&m_szCmdName);
+ return false;
+ }
+ return true;
+}
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_aliassimplecommand.h b/src/kvirc/kvs/kvi_kvs_treenode_aliassimplecommand.h
new file mode 100644
index 00000000..0247e9be
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_aliassimplecommand.h
@@ -0,0 +1,47 @@
+#ifndef _KVI_KVS_TREENODE_ALIASSIMPLECOMMAND_H_
+#define _KVI_KVS_TREENODE_ALIASSIMPLECOMMAND_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_aliassimplecommand.h
+// Created on Thu 09 Oct 2003 02:16:42 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_treenode_simplecommand.h"
+
+class KviKvsTreeNodeDataList;
+class KviKvsRunTimeContext;
+
+class KVIRC_API KviKvsTreeNodeAliasSimpleCommand : public KviKvsTreeNodeSimpleCommand
+{
+public:
+ KviKvsTreeNodeAliasSimpleCommand(const QChar * pLocation,const QString &szCmdName,KviKvsTreeNodeDataList * params);
+ ~KviKvsTreeNodeAliasSimpleCommand();
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c);
+};
+
+
+
+#endif //!_KVI_KVS_TREENODE_ALIASSIMPLECOMMAND_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_arraycount.cpp b/src/kvirc/kvs/kvi_kvs_treenode_arraycount.cpp
new file mode 100644
index 00000000..1479fefe
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_arraycount.cpp
@@ -0,0 +1,86 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_arraycount.cpp
+// Created on Tue 07 Oct 2003 03:00:52 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_arraycount.h"
+#include "kvi_kvs_variant.h"
+#include "kvi_kvs_runtimecontext.h"
+#include "kvi_locale.h"
+#include "kvi_kvs_object.h"
+
+
+KviKvsTreeNodeArrayCount::KviKvsTreeNodeArrayCount(const QChar * pLocation,KviKvsTreeNodeData * pSource)
+: KviKvsTreeNodeIndirectData(pLocation,pSource)
+{
+}
+
+KviKvsTreeNodeArrayCount::~KviKvsTreeNodeArrayCount()
+{
+}
+
+void KviKvsTreeNodeArrayCount::contextDescription(QString &szBuffer)
+{
+ szBuffer = "Array Count Operator";
+}
+
+void KviKvsTreeNodeArrayCount::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s ArrayCount",prefix);
+#endif
+}
+
+bool KviKvsTreeNodeArrayCount::evaluateReadOnlyInObjectScope(KviKvsObject *o,KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ KviKvsVariant val;
+ if(o)
+ {
+ if(!m_pSource->evaluateReadOnlyInObjectScope(o,c,&val))return false;
+ } else {
+ if(!m_pSource->evaluateReadOnly(c,&val))return false;
+ }
+
+ if(!val.isArray())
+ {
+ if(!val.isNothing())
+ {
+ QString szType;
+ val.getTypeName(szType);
+ c->warning(this,__tr2qs("The argument of the array count '#' operator didn't evaluate to an array: automatic conversion from type '%Q' supplied"),&szType);
+ }
+ pBuffer->setInteger(0);
+ return true;
+ }
+
+ pBuffer->setInteger(val.array()->size());
+#endif
+ return true;
+}
+
+bool KviKvsTreeNodeArrayCount::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+ return evaluateReadOnlyInObjectScope(0,c,pBuffer);
+}
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_arraycount.h b/src/kvirc/kvs/kvi_kvs_treenode_arraycount.h
new file mode 100644
index 00000000..deae2588
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_arraycount.h
@@ -0,0 +1,47 @@
+#ifndef _KVI_KVS_TREENODE_ARRAYCOUNT_H_
+#define _KVI_KVS_TREENODE_ARRAYCOUNT_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_arraycount.h
+// Created on Tue 07 Oct 2003 03:00:52 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_treenode_indirectdata.h"
+
+class KviKvsRunTimeContext;
+class KviKvsVariant;
+class KviKvsObject;
+
+class KVIRC_API KviKvsTreeNodeArrayCount : public KviKvsTreeNodeIndirectData
+{
+public:
+ KviKvsTreeNodeArrayCount(const QChar * pLocation,KviKvsTreeNodeData * pSource);
+ ~KviKvsTreeNodeArrayCount();
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer);
+ virtual bool evaluateReadOnlyInObjectScope(KviKvsObject *o,KviKvsRunTimeContext * c,KviKvsVariant * pBuffer);
+};
+
+#endif //!_KVI_KVS_TREENODE_ARRAYCOUNT_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_arrayelement.cpp b/src/kvirc/kvs/kvi_kvs_treenode_arrayelement.cpp
new file mode 100644
index 00000000..ada9fd82
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_arrayelement.cpp
@@ -0,0 +1,161 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_arrayelement.cpp
+// Created on Tue 07 Oct 2003 02:58:41 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_arrayelement.h"
+#include "kvi_kvs_runtimecontext.h"
+#include "kvi_locale.h"
+#include "kvi_kvs_array.h"
+#include "kvi_kvs_object.h"
+
+KviKvsTreeNodeArrayElement::KviKvsTreeNodeArrayElement(const QChar * pLocation,KviKvsTreeNodeData * pSource,KviKvsTreeNodeExpression * pIndex)
+: KviKvsTreeNodeArrayOrHashElement(pLocation,pSource)
+{
+#ifdef COMPILE_NEW_KVS
+ m_pIndex = pIndex;
+ m_pIndex->setParent(this);
+#endif
+}
+
+
+KviKvsTreeNodeArrayElement::~KviKvsTreeNodeArrayElement()
+{
+#ifdef COMPILE_NEW_KVS
+ delete m_pIndex;
+#endif
+}
+
+void KviKvsTreeNodeArrayElement::contextDescription(QString &szBuffer)
+{
+ szBuffer = "Array Element Evaluation";
+}
+
+void KviKvsTreeNodeArrayElement::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s ArrayElement",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pSource->dump(tmp.utf8().data());
+ m_pIndex->dump(tmp.utf8().data());
+#endif
+}
+
+bool KviKvsTreeNodeArrayElement::evaluateIndex(KviKvsRunTimeContext *c,kvs_int_t &iVal)
+{
+ KviKvsVariant idx;
+ if(!m_pIndex->evaluateReadOnly(c,&idx))return false;
+
+ if(!idx.asInteger(iVal))
+ {
+ c->error(this,__tr2qs("Array index didn't evaluate to an integer"));
+ return false;
+ }
+
+ if(iVal < 0)
+ {
+ c->error(this,__tr2qs("Array index evaluated to a negative integer (non negative integer expected)"));
+ return false;
+ }
+ return true;
+}
+
+
+bool KviKvsTreeNodeArrayElement::evaluateReadOnlyInObjectScope(KviKvsObject * o,KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ kvs_int_t iVal;
+ if(!evaluateIndex(c,iVal))return false;
+
+ KviKvsVariant val;
+ if(o)
+ {
+ if(!m_pSource->evaluateReadOnlyInObjectScope(o,c,&val))return false;
+ } else {
+ if(!m_pSource->evaluateReadOnly(c,&val))return false;
+ }
+
+ if(!val.isArray())
+ {
+ if(!val.isNothing())
+ {
+ QString szType;
+ val.getTypeName(szType);
+ c->warning(this,__tr2qs("The argument of the [] subscript didn't evaluate to an array: automatic conversion from %Q supplied"),&szType);
+ }
+ pBuffer->setNothing();
+ return true;
+ }
+
+ KviKvsVariant * v = val.array()->at(iVal);
+ if(!v)
+ {
+ pBuffer->setNothing();
+ return true;
+ }
+
+ pBuffer->copyFrom(v);
+#endif
+ return true;
+}
+
+KviKvsRWEvaluationResult * KviKvsTreeNodeArrayElement::evaluateReadWriteInObjectScope(KviKvsObject *o,KviKvsRunTimeContext * c)
+{
+#ifdef COMPILE_NEW_KVS
+ kvs_int_t iVal;
+ if(!evaluateIndex(c,iVal))return false;
+
+ KviKvsRWEvaluationResult * result;
+ if(o)result = m_pSource->evaluateReadWriteInObjectScope(o,c);
+ else result = m_pSource->evaluateReadWrite(c);
+ if(!result)return 0;
+
+ if(!result->result()->isArray())
+ {
+ // convert to hash in some way
+ if(!result->result()->isNothing())
+ {
+ QString szType;
+ result->result()->getTypeName(szType);
+ c->warning(this,__tr2qs("The argument of the [] subscript didn't evaluate to an array: automatic conversion from type '%Q' supplied"),&szType);
+ }
+ result->result()->setArray(new KviKvsArray());
+ }
+ return new KviKvsArrayElement(result,result->result()->array()->getAt(iVal),result->result()->array(),iVal);
+#else
+ return 0;
+#endif
+}
+
+bool KviKvsTreeNodeArrayElement::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+ return evaluateReadOnlyInObjectScope(0,c,pBuffer);
+}
+
+KviKvsRWEvaluationResult * KviKvsTreeNodeArrayElement::evaluateReadWrite(KviKvsRunTimeContext * c)
+{
+ return evaluateReadWriteInObjectScope(0,c);
+}
+
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_arrayelement.h b/src/kvirc/kvs/kvi_kvs_treenode_arrayelement.h
new file mode 100644
index 00000000..9b23926b
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_arrayelement.h
@@ -0,0 +1,54 @@
+#ifndef _KVI_KVS_TREENODE_ARRAYELEMENT_H_
+#define _KVI_KVS_TREENODE_ARRAYELEMENT_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_arrayelement.h
+// Created on Tue 07 Oct 2003 02:58:41 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_treenode_expression.h"
+#include "kvi_kvs_treenode_arrayorhashelement.h"
+#include "kvi_kvs_types.h"
+
+class KviKvsObject;
+class KviKvsRunTimeContext;
+
+class KVIRC_API KviKvsTreeNodeArrayElement : public KviKvsTreeNodeArrayOrHashElement
+{
+public:
+ KviKvsTreeNodeArrayElement(const QChar * pLocation,KviKvsTreeNodeData * pSource,KviKvsTreeNodeExpression * pIndex);
+ ~KviKvsTreeNodeArrayElement();
+protected:
+ KviKvsTreeNodeExpression * m_pIndex; // can't be null
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer);
+ virtual KviKvsRWEvaluationResult * evaluateReadWrite(KviKvsRunTimeContext * c);
+ virtual bool evaluateReadOnlyInObjectScope(KviKvsObject *o,KviKvsRunTimeContext * c,KviKvsVariant * pBuffer);
+ virtual KviKvsRWEvaluationResult * evaluateReadWriteInObjectScope(KviKvsObject *o,KviKvsRunTimeContext * c);
+protected:
+ bool evaluateIndex(KviKvsRunTimeContext *c,kvs_int_t &iVal);
+};
+
+#endif //!_KVI_KVS_TREENODE_ARRAYELEMENT_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_arrayorhashelement.cpp b/src/kvirc/kvs/kvi_kvs_treenode_arrayorhashelement.cpp
new file mode 100644
index 00000000..d15d197c
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_arrayorhashelement.cpp
@@ -0,0 +1,45 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_arrayorhashelement.cpp
+// Created on Thu 16 Oct 2003 22:56:48 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_arrayorhashelement.h"
+
+KviKvsTreeNodeArrayOrHashElement::KviKvsTreeNodeArrayOrHashElement(const QChar * pLocation,KviKvsTreeNodeData * pSource)
+: KviKvsTreeNodeIndirectData(pLocation,pSource)
+{
+}
+
+KviKvsTreeNodeArrayOrHashElement::~KviKvsTreeNodeArrayOrHashElement()
+{
+}
+bool KviKvsTreeNodeArrayOrHashElement::isReadOnly()
+{
+ return m_pSource->isReadOnly();
+}
+
+bool KviKvsTreeNodeArrayOrHashElement::canEvaluateToObjectReference()
+{
+ return true;
+}
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_arrayorhashelement.h b/src/kvirc/kvs/kvi_kvs_treenode_arrayorhashelement.h
new file mode 100644
index 00000000..4f5d6793
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_arrayorhashelement.h
@@ -0,0 +1,42 @@
+#ifndef _KVI_KVS_TREENODE_ARRAYORHASHELEMENT_H_
+#define _KVI_KVS_TREENODE_ARRAYORHASHELEMENT_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_arrayorhashelement.h
+// Created on Thu 16 Oct 2003 22:56:48 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_treenode_indirectdata.h"
+#include "kvi_kvs_variant.h"
+
+class KVIRC_API KviKvsTreeNodeArrayOrHashElement : public KviKvsTreeNodeIndirectData
+{
+public:
+ KviKvsTreeNodeArrayOrHashElement(const QChar * pLocation,KviKvsTreeNodeData * pSource);
+ ~KviKvsTreeNodeArrayOrHashElement();
+public:
+ virtual bool isReadOnly();
+ virtual bool canEvaluateToObjectReference();
+};
+
+#endif //!_KVI_KVS_TREENODE_ARRAYORHASHELEMENT_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_arrayreferenceassert.cpp b/src/kvirc/kvs/kvi_kvs_treenode_arrayreferenceassert.cpp
new file mode 100644
index 00000000..698b95c7
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_arrayreferenceassert.cpp
@@ -0,0 +1,107 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_arrayreferenceassert.cpp
+// Created on Thu 16 Oct 2003 23:46:12 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_arrayreferenceassert.h"
+#include "kvi_kvs_rwevaluationresult.h"
+#include "kvi_kvs_runtimecontext.h"
+#include "kvi_kvs_variant.h"
+#include "kvi_locale.h"
+#include "kvi_kvs_object.h"
+
+KviKvsTreeNodeArrayReferenceAssert::KviKvsTreeNodeArrayReferenceAssert(const QChar * pLocation,KviKvsTreeNodeData * pSource)
+: KviKvsTreeNodeIndirectData(pLocation,pSource)
+{
+}
+
+KviKvsTreeNodeArrayReferenceAssert::~KviKvsTreeNodeArrayReferenceAssert()
+{
+}
+
+bool KviKvsTreeNodeArrayReferenceAssert::isReadOnly()
+{
+ return m_pSource->isReadOnly();
+}
+
+void KviKvsTreeNodeArrayReferenceAssert::contextDescription(QString &szBuffer)
+{
+ szBuffer = "Array Reference Assert";
+}
+
+
+void KviKvsTreeNodeArrayReferenceAssert::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s ArrayReferenceAssert",prefix);
+#endif
+}
+
+bool KviKvsTreeNodeArrayReferenceAssert::evaluateReadOnlyInObjectScope(KviKvsObject *o,KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ if(o)
+ {
+ if(!m_pSource->evaluateReadOnlyInObjectScope(o,c,pBuffer))return false;
+ } else {
+ if(!m_pSource->evaluateReadOnly(c,pBuffer))return false;
+ }
+
+ if(!pBuffer->isArray())
+ {
+ if(!pBuffer->isNothing())
+ {
+ QString szType;
+ pBuffer->getTypeName(szType);
+ c->error(this,__tr2qs("Array reference assert failed: the variable evaluated to type '%Q'"),&szType);
+ return false;
+ }
+ }
+#endif
+ return true;
+}
+
+KviKvsRWEvaluationResult * KviKvsTreeNodeArrayReferenceAssert::evaluateReadWriteInObjectScope(KviKvsObject *o,KviKvsRunTimeContext * c)
+{
+#ifdef COMPILE_NEW_KVS
+ KviKvsRWEvaluationResult * r;
+ if(o)r = m_pSource->evaluateReadWriteInObjectScope(o,c);
+ else r = m_pSource->evaluateReadWrite(c);
+ if(!r)return false;
+
+ return r;
+#else
+ return 0;
+#endif
+}
+
+bool KviKvsTreeNodeArrayReferenceAssert::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+ return evaluateReadOnlyInObjectScope(0,c,pBuffer);
+}
+
+KviKvsRWEvaluationResult * KviKvsTreeNodeArrayReferenceAssert::evaluateReadWrite(KviKvsRunTimeContext * c)
+{
+ return evaluateReadWriteInObjectScope(0,c);
+}
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_arrayreferenceassert.h b/src/kvirc/kvs/kvi_kvs_treenode_arrayreferenceassert.h
new file mode 100644
index 00000000..8827cf2f
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_arrayreferenceassert.h
@@ -0,0 +1,54 @@
+#ifndef _KVI_KVS_TREENODE_ARRAYREFERENCEASSERT_H_
+#define _KVI_KVS_TREENODE_ARRAYREFERENCEASSERT_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_arrayreferenceassert.h
+// Created on Thu 16 Oct 2003 23:46:12 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_treenode_indirectdata.h"
+
+class KviKvsRunTimeContext;
+class KviKvsVariant;
+class KviKvsRWEvaluationResult;
+class KviKvsObject;
+
+class KVIRC_API KviKvsTreeNodeArrayReferenceAssert : public KviKvsTreeNodeIndirectData
+{
+public:
+ KviKvsTreeNodeArrayReferenceAssert(const QChar * pLocation,KviKvsTreeNodeData * pSource);
+ ~KviKvsTreeNodeArrayReferenceAssert();
+protected:
+
+public:
+ virtual bool isReadOnly();
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer);
+ virtual KviKvsRWEvaluationResult * evaluateReadWrite(KviKvsRunTimeContext * c);
+ virtual bool evaluateReadOnlyInObjectScope(KviKvsObject *o,KviKvsRunTimeContext * c,KviKvsVariant * pBuffer);
+ virtual KviKvsRWEvaluationResult * evaluateReadWriteInObjectScope(KviKvsObject *o,KviKvsRunTimeContext * c);
+};
+
+
+#endif //!_KVI_KVS_TREENODE_ARRAYREFERENCEASSERT_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_base.cpp b/src/kvirc/kvs/kvi_kvs_treenode_base.cpp
new file mode 100644
index 00000000..ee19dd83
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_base.cpp
@@ -0,0 +1,37 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_base.cpp
+// Created on Tue 07 Oct 2003 02:00:28 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_base.h"
+
+KviKvsTreeNode::KviKvsTreeNode(const QChar * pLocation)
+{
+#ifdef COMPILE_NEW_KVS
+ m_pParent = 0;
+ m_pLocation = pLocation;
+#endif
+}
+
+
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_base.h b/src/kvirc/kvs/kvi_kvs_treenode_base.h
new file mode 100644
index 00000000..6f0178f9
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_base.h
@@ -0,0 +1,51 @@
+#ifndef _KVI_KVS_TREENODE_BASE_H_
+#define _KVI_KVS_TREENODE_BASE_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_base.h
+// Created on Tue 07 Oct 2003 02:00:28 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+
+class KVIRC_API KviKvsTreeNode
+{
+ friend class KviKvsParser;
+public:
+ KviKvsTreeNode(const QChar * pLocation);
+ virtual ~KviKvsTreeNode(){};
+protected:
+ KviKvsTreeNode * m_pParent;
+ const QChar * m_pLocation;
+public:
+ void setParent(KviKvsTreeNode * p){ m_pParent = p; };
+protected:
+ // this is called only by KviKvsParser
+ void setLocation(const QChar * pLocation){ m_pLocation = pLocation; };
+public:
+ KviKvsTreeNode * parent(){ return m_pParent; };
+ const QChar * location(){ return m_pLocation; };
+ virtual void dump(const char * prefix) = 0;
+ virtual void contextDescription(QString &szBuffer) = 0;
+};
+
+#endif //!_KVI_KVS_TREENODE_BASE_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_baseobjectfunctioncall.cpp b/src/kvirc/kvs/kvi_kvs_treenode_baseobjectfunctioncall.cpp
new file mode 100644
index 00000000..75feafc4
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_baseobjectfunctioncall.cpp
@@ -0,0 +1,72 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_baseobjectfunctioncall.cpp
+// Created on Tue 07 Oct 2003 03:30:10 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_baseobjectfunctioncall.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_object.h"
+#include "kvi_kvs_variant.h"
+
+KviKvsTreeNodeBaseObjectFunctionCall::KviKvsTreeNodeBaseObjectFunctionCall(const QChar * pLocation,const QString &szBaseClass,const QString &szFncName,KviKvsTreeNodeDataList * pParams)
+: KviKvsTreeNodeObjectFunctionCall(pLocation,szFncName,pParams)
+{
+#ifdef COMPILE_NEW_KVS
+ m_szBaseClass = szBaseClass;
+#endif
+}
+
+KviKvsTreeNodeBaseObjectFunctionCall::~KviKvsTreeNodeBaseObjectFunctionCall()
+{
+}
+
+void KviKvsTreeNodeBaseObjectFunctionCall::contextDescription(QString &szBuffer)
+{
+ KviQString::sprintf(szBuffer,"Base Object Function Call \"%s::%s\"",&m_szBaseClass,&m_szFunctionName);
+}
+
+void KviKvsTreeNodeBaseObjectFunctionCall::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s BaseObjectFunctionCall(%s::%s)",prefix,m_szBaseClass.utf8().data(),m_szFunctionName.utf8().data());
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pParams->dump(tmp.utf8().data());
+#endif
+}
+
+bool KviKvsTreeNodeBaseObjectFunctionCall::evaluateReadOnlyInObjectScope(KviKvsObject * o,KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ KviKvsVariantList l;
+ if(!m_pParams->evaluate(c,&l))return false;
+ pBuffer->setNothing();
+ c->setDefaultReportLocation(this);
+ return o->callFunction(c->thisObject(),m_szFunctionName,m_szBaseClass,c,pBuffer,&l);
+#else
+ return false;
+#endif
+}
+
+
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_baseobjectfunctioncall.h b/src/kvirc/kvs/kvi_kvs_treenode_baseobjectfunctioncall.h
new file mode 100644
index 00000000..d679c404
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_baseobjectfunctioncall.h
@@ -0,0 +1,50 @@
+#ifndef _KVI_KVS_TREENODE_BASEOBJECTFUNCTIONCALL_H_
+#define _KVI_KVS_TREENODE_BASEOBJECTFUNCTIONCALL_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_baseobjectfunctioncall.h
+// Created on Tue 07 Oct 2003 03:30:10 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_treenode_datalist.h"
+#include "kvi_kvs_treenode_objectfunctioncall.h"
+
+class KviKvsObject;
+class KviKvsVariant;
+class KviKvsRunTimeContext;
+
+class KVIRC_API KviKvsTreeNodeBaseObjectFunctionCall : public KviKvsTreeNodeObjectFunctionCall
+{
+public:
+ KviKvsTreeNodeBaseObjectFunctionCall(const QChar * pLocation,const QString &szBaseClass,const QString &szFncName,KviKvsTreeNodeDataList * pParams);
+ ~KviKvsTreeNodeBaseObjectFunctionCall();
+protected:
+ QString m_szBaseClass;
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+
+ virtual bool evaluateReadOnlyInObjectScope(KviKvsObject * o,KviKvsRunTimeContext * c,KviKvsVariant * pBuffer);
+};
+
+#endif //!_KVI_KVS_TREENODE_BASEOBJECTFUNCTIONCALL_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_callbackcommand.cpp b/src/kvirc/kvs/kvi_kvs_treenode_callbackcommand.cpp
new file mode 100644
index 00000000..cf4c5494
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_callbackcommand.cpp
@@ -0,0 +1,73 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_callbackcommand.cpp
+// Created on Thu 09 Oct 2003 02:02:42 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+
+#include "kvi_kvs_treenode_callbackcommand.h"
+#include "kvi_kvs_treenode_datalist.h"
+#include "kvi_kvs_script.h"
+
+
+
+KviKvsTreeNodeCallbackCommand::KviKvsTreeNodeCallbackCommand(const QChar * pLocation,const QString &szCmdName,KviKvsTreeNodeDataList * params,KviKvsScript * pCallback)
+: KviKvsTreeNodeCommandWithParameters(pLocation,szCmdName,params)
+{
+#ifdef COMPILE_NEW_KVS
+ m_pCallback = pCallback;
+#endif
+}
+
+
+KviKvsTreeNodeCallbackCommand::~KviKvsTreeNodeCallbackCommand()
+{
+#ifdef COMPILE_NEW_KVS
+ delete m_pCallback;
+#endif
+}
+
+void KviKvsTreeNodeCallbackCommand::contextDescription(QString &szBuffer)
+{
+ KviQString::sprintf(szBuffer,"Callback Command \"%s\"",&m_szCmdName);
+}
+
+void KviKvsTreeNodeCallbackCommand::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s CallbackCommand(%s)",prefix,m_szCmdName.utf8().data());
+ dumpSwitchList(prefix);
+ dumpParameterList(prefix);
+ dumpCallback(prefix);
+#endif
+}
+
+void KviKvsTreeNodeCallbackCommand::dumpCallback(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pCallback->dump(tmp.utf8().data());
+#endif
+}
+
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_callbackcommand.h b/src/kvirc/kvs/kvi_kvs_treenode_callbackcommand.h
new file mode 100644
index 00000000..dc061f64
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_callbackcommand.h
@@ -0,0 +1,48 @@
+#ifndef _KVI_KVS_TREENODE_CALLBACKCOMMAND_H_
+#define _KVI_KVS_TREENODE_CALLBACKCOMMAND_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_callbackcommand.h
+// Created on Thu 09 Oct 2003 02:02:42 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_treenode_commandwithparameters.h"
+
+class KviKvsTreeNodeDataList;
+class KviKvsScript;
+
+class KVIRC_API KviKvsTreeNodeCallbackCommand : public KviKvsTreeNodeCommandWithParameters
+{
+public:
+ KviKvsTreeNodeCallbackCommand(const QChar * pLocation,const QString &szCmdName,KviKvsTreeNodeDataList * params,KviKvsScript * pCallback);
+ ~KviKvsTreeNodeCallbackCommand();
+protected:
+ KviKvsScript * m_pCallback;
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ void dumpCallback(const char * prefix);
+};
+
+
+#endif //!_KVI_KVS_TREENODE_CALLBACKCOMMAND_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_command.cpp b/src/kvirc/kvs/kvi_kvs_treenode_command.cpp
new file mode 100644
index 00000000..4da19dfa
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_command.cpp
@@ -0,0 +1,80 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_command.cpp
+// Created on Thu 09 Oct 2003 01:49:40 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_command.h"
+#include "kvi_kvs_treenode_switchlist.h"
+
+KviKvsTreeNodeCommand::KviKvsTreeNodeCommand(const QChar * pLocation,const QString &szCmdName)
+: KviKvsTreeNodeInstruction(pLocation)
+{
+#ifdef COMPILE_NEW_KVS
+ m_szCmdName = szCmdName;
+ m_pSwitches = 0;
+#endif
+}
+
+KviKvsTreeNodeCommand::~KviKvsTreeNodeCommand()
+{
+#ifdef COMPILE_NEW_KVS
+ if(m_pSwitches)delete m_pSwitches;
+#endif
+}
+
+//#warning "All the dump() functions could be killed (or moved to print on the kvirc windows)"
+
+void KviKvsTreeNodeCommand::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ KviQString::sprintf(szBuffer,"Command \"%s\"",&m_szCmdName);
+#endif
+}
+
+void KviKvsTreeNodeCommand::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s Command(%s)",prefix,m_szCmdName.utf8().data());
+ dumpSwitchList(prefix);
+#endif
+}
+
+void KviKvsTreeNodeCommand::dumpSwitchList(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ if(!m_pSwitches)return;
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pSwitches->dump(tmp.utf8().data());
+#endif
+}
+
+void KviKvsTreeNodeCommand::setSwitchList(KviKvsTreeNodeSwitchList * sw)
+{
+#ifdef COMPILE_NEW_KVS
+ m_pSwitches = sw;
+ m_pSwitches->setParent(this);
+#endif
+}
+
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_command.h b/src/kvirc/kvs/kvi_kvs_treenode_command.h
new file mode 100644
index 00000000..cf58774e
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_command.h
@@ -0,0 +1,54 @@
+#ifndef _KVI_KVS_TREENODE_COMMAND_H_
+#define _KVI_KVS_TREENODE_COMMAND_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_command.h
+// Created on Thu 09 Oct 2003 01:49:40 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_treenode_instruction.h"
+
+class KviKvsParser;
+class KviKvsTreeNodeSwitchList;
+
+class KVIRC_API KviKvsTreeNodeCommand : public KviKvsTreeNodeInstruction
+{
+ // never instantiated
+ friend class KviKvsParser;
+public:
+ KviKvsTreeNodeCommand(const QChar * pLocation,const QString &szCmdName);
+ ~KviKvsTreeNodeCommand();
+protected:
+ QString m_szCmdName; // command visible name
+ KviKvsTreeNodeSwitchList * m_pSwitches; // MAY BE 0!
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ void dumpSwitchList(const char * prefix);
+ const QString & commandName(){ return m_szCmdName; };
+protected:
+ void setSwitchList(KviKvsTreeNodeSwitchList * sw);
+};
+
+
+#endif //!_KVI_KVS_TREENODE_COMMAND_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_commandevaluation.cpp b/src/kvirc/kvs/kvi_kvs_treenode_commandevaluation.cpp
new file mode 100644
index 00000000..1fc5b80b
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_commandevaluation.cpp
@@ -0,0 +1,60 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_commandevaluation.cpp
+// Created on Wed 05 Nov 2003 04:18:58 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_commandevaluation.h"
+
+#include "kvi_kvs_runtimecontext.h"
+#include "kvi_kvs_variant.h"
+
+KviKvsTreeNodeCommandEvaluation::KviKvsTreeNodeCommandEvaluation(const QChar * pLocation,KviKvsTreeNodeInstruction * pInstruction)
+: KviKvsTreeNodeData(pLocation)
+{
+#ifdef COMPILE_NEW_KVS
+ m_pInstruction = pInstruction;
+ m_pInstruction->setParent(this);
+#endif
+}
+
+KviKvsTreeNodeCommandEvaluation::~KviKvsTreeNodeCommandEvaluation()
+{
+#ifdef COMPILE_NEW_KVS
+ delete m_pInstruction;
+#endif
+}
+
+
+bool KviKvsTreeNodeCommandEvaluation::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ KviKvsVariant * pTmp = c->swapReturnValuePointer(pBuffer);
+ bool bRet = m_pInstruction->execute(c);
+ c->swapReturnValuePointer(pTmp);
+ return bRet;
+#else
+ return false;
+#endif
+}
+
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_commandevaluation.h b/src/kvirc/kvs/kvi_kvs_treenode_commandevaluation.h
new file mode 100644
index 00000000..3ff71555
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_commandevaluation.h
@@ -0,0 +1,46 @@
+#ifndef _KVI_KVS_TREENODE_COMMANDEVALUATION_H_
+#define _KVI_KVS_TREENODE_COMMANDEVALUATION_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_commandevaluation.h
+// Created on Wed 05 Nov 2003 04:18:58 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_treenode_data.h"
+#include "kvi_kvs_treenode_instruction.h"
+
+class KviKvsRunTimeContext;
+class KviKvsVariant;
+
+class KviKvsTreeNodeCommandEvaluation : public KviKvsTreeNodeData
+{
+public:
+ KviKvsTreeNodeCommandEvaluation(const QChar * pLocation,KviKvsTreeNodeInstruction * pInstruction);
+ ~KviKvsTreeNodeCommandEvaluation();
+protected:
+ KviKvsTreeNodeInstruction * m_pInstruction; // owned, never 0
+public:
+ virtual bool evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer);
+};
+
+#endif //!_KVI_KVS_TREENODE_COMMANDEVALUATION_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_commandwithparameters.cpp b/src/kvirc/kvs/kvi_kvs_treenode_commandwithparameters.cpp
new file mode 100644
index 00000000..dd0544ff
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_commandwithparameters.cpp
@@ -0,0 +1,66 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_commandwithparameters.cpp
+// Created on Thu 09 Oct 2003 01:57:10 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_commandwithparameters.h"
+#include "kvi_kvs_treenode_datalist.h"
+
+KviKvsTreeNodeCommandWithParameters::KviKvsTreeNodeCommandWithParameters(const QChar * pLocation,const QString &szCmdName,KviKvsTreeNodeDataList * params)
+: KviKvsTreeNodeCommand(pLocation,szCmdName)
+{
+ m_pParams = params;
+ m_pParams->setParent(this);
+}
+
+KviKvsTreeNodeCommandWithParameters::~KviKvsTreeNodeCommandWithParameters()
+{
+ delete m_pParams;
+}
+
+void KviKvsTreeNodeCommandWithParameters::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ KviQString::sprintf(szBuffer,"Command With Parameters \"%s\"",&m_szCmdName);
+#endif
+}
+
+
+void KviKvsTreeNodeCommandWithParameters::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s CommandWithParameters(%s)",prefix,m_szCmdName.utf8().data());
+ dumpSwitchList(prefix);
+ dumpParameterList(prefix);
+#endif
+}
+
+void KviKvsTreeNodeCommandWithParameters::dumpParameterList(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pParams->dump(tmp.utf8().data());
+#endif
+}
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_commandwithparameters.h b/src/kvirc/kvs/kvi_kvs_treenode_commandwithparameters.h
new file mode 100644
index 00000000..769e72f7
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_commandwithparameters.h
@@ -0,0 +1,49 @@
+#ifndef _KVI_KVS_TREENODE_COMMANDWITHPARAMETERS_H_
+#define _KVI_KVS_TREENODE_COMMANDWITHPARAMETERS_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_commandwithparameters.h
+// Created on Thu 09 Oct 2003 01:57:10 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_treenode_command.h"
+
+class KviKvsTreeNodeDataList;
+
+class KVIRC_API KviKvsTreeNodeCommandWithParameters : public KviKvsTreeNodeCommand
+{
+ // never instantiated
+public:
+ // params can't be 0!
+ KviKvsTreeNodeCommandWithParameters(const QChar * pLocation,const QString &szCmdName,KviKvsTreeNodeDataList * params);
+ ~KviKvsTreeNodeCommandWithParameters();
+protected:
+ KviKvsTreeNodeDataList * m_pParams; // never 0
+public:
+ KviKvsTreeNodeDataList * params(){ return m_pParams; };
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ void dumpParameterList(const char * prefix);
+};
+
+#endif //!_KVI_KVS_TREENODE_COMMANDWITHPARAMETERS_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_compositedata.cpp b/src/kvirc/kvs/kvi_kvs_treenode_compositedata.cpp
new file mode 100644
index 00000000..aae8a9cb
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_compositedata.cpp
@@ -0,0 +1,86 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_compositedata.cpp
+// Created on Tue 07 Oct 2003 02:24:33 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_compositedata.h"
+
+#include "kvi_qstring.h"
+
+#define DEBUGME
+
+KviKvsTreeNodeCompositeData::KviKvsTreeNodeCompositeData(const QChar * pLocation,KviPointerList<KviKvsTreeNodeData> * pSubData)
+: KviKvsTreeNodeData(pLocation)
+{
+#ifdef DEBUGME
+ if(pSubData->count() < 2)debug("KviKvsTreeNodeCompositeData constructor called with less than two children!");
+#endif
+ m_pSubData = pSubData;
+ m_pSubData->setAutoDelete(true);
+ for(KviKvsTreeNodeData * d = m_pSubData->first();d;d = m_pSubData->next())
+ d->setParent(this);
+}
+
+
+KviKvsTreeNodeCompositeData::~KviKvsTreeNodeCompositeData()
+{
+ delete m_pSubData;
+}
+
+bool KviKvsTreeNodeCompositeData::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+ QString * pS = new QString();
+
+ pBuffer->setString(pS);
+
+ KviKvsVariant res;
+
+ // we need to use an iterator to accomodate recursion
+ KviPointerListIterator<KviKvsTreeNodeData> it(*m_pSubData);
+
+ while(KviKvsTreeNodeData * d = it.current())
+ {
+ if(!d->evaluateReadOnly(c,&res))return false;
+ res.appendAsString(*pS);
+ ++it;
+ }
+ return true;
+}
+
+void KviKvsTreeNodeCompositeData::contextDescription(QString &szBuffer)
+{
+ szBuffer = "Composite Data Evaluation (Implicit String Cast)";
+}
+
+void KviKvsTreeNodeCompositeData::dump(const char * prefix)
+{
+ debug("%s CompositeData",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ for(KviKvsTreeNodeData * p = m_pSubData->first();p;p = m_pSubData->next())
+ {
+ p->dump(tmp.utf8().data());
+ }
+}
+
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_compositedata.h b/src/kvirc/kvs/kvi_kvs_treenode_compositedata.h
new file mode 100644
index 00000000..b9b549bd
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_compositedata.h
@@ -0,0 +1,48 @@
+#ifndef _KVI_KVS_TREENODE_COMPOSITEDATA_H_
+#define _KVI_KVS_TREENODE_COMPOSITEDATA_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_compositedata.h
+// Created on Tue 07 Oct 2003 02:24:33 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#include "kvi_pointerlist.h"
+
+#include "kvi_kvs_treenode_data.h"
+
+class KVIRC_API KviKvsTreeNodeCompositeData : public KviKvsTreeNodeData
+{
+public:
+ KviKvsTreeNodeCompositeData(const QChar * pLocation,KviPointerList<KviKvsTreeNodeData> * pSubData);
+ ~KviKvsTreeNodeCompositeData();
+protected:
+ KviPointerList<KviKvsTreeNodeData> * m_pSubData;
+public:
+ virtual bool evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer);
+ virtual void contextDescription(QString &szBuffer);
+
+ virtual void dump(const char * prefix);
+};
+
+
+#endif //!_KVI_KVS_TREENODE_COMPOSITEDATA_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_constantdata.cpp b/src/kvirc/kvs/kvi_kvs_treenode_constantdata.cpp
new file mode 100644
index 00000000..a52930eb
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_constantdata.cpp
@@ -0,0 +1,80 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_constantdata.cpp
+// Created on Tue 07 Oct 2003 02:21:59 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_constantdata.h"
+
+
+KviKvsTreeNodeConstantData::KviKvsTreeNodeConstantData(const QChar * pLocation,KviKvsVariant * v)
+: KviKvsTreeNodeData(pLocation)
+{
+ m_pValue = v;
+}
+
+
+KviKvsTreeNodeConstantData::~KviKvsTreeNodeConstantData()
+{
+ delete m_pValue;
+}
+
+void KviKvsTreeNodeConstantData::contextDescription(QString &szBuffer)
+{
+ szBuffer = "Constant Data Evaluation";
+}
+
+bool KviKvsTreeNodeConstantData::convertStringConstantToNumeric()
+{
+ if(m_pValue->isString())
+ {
+ kvs_int_t iVal;
+ if(m_pValue->asInteger(iVal))
+ {
+ m_pValue->setInteger(iVal);
+ return true;
+ }
+
+ kvs_real_t dVal;
+ if(m_pValue->asReal(dVal))
+ {
+ m_pValue->setReal(dVal);
+ return true;
+ }
+ }
+ return true;
+}
+
+void KviKvsTreeNodeConstantData::dump(const char * prefix)
+{
+ debug("%s ConstantData",prefix);
+ QString tmp = prefix;
+ tmp.prepend(" ");
+ m_pValue->dump(tmp.utf8().data());
+}
+
+bool KviKvsTreeNodeConstantData::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+ pBuffer->copyFrom(m_pValue);
+ return true;
+}
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_constantdata.h b/src/kvirc/kvs/kvi_kvs_treenode_constantdata.h
new file mode 100644
index 00000000..4cb0f947
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_constantdata.h
@@ -0,0 +1,52 @@
+#ifndef _KVI_KVS_TREENODE_CONSTANTDATA_H_
+#define _KVI_KVS_TREENODE_CONSTANTDATA_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_constantdata.h
+// Created on Tue 07 Oct 2003 02:21:59 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#include "kvi_qstring.h"
+
+#include "kvi_kvs_treenode_data.h"
+
+class KVIRC_API KviKvsTreeNodeConstantData : public KviKvsTreeNodeData
+{
+public:
+ KviKvsTreeNodeConstantData(const QChar * pLocation,KviKvsVariant * v);
+ ~KviKvsTreeNodeConstantData();
+protected:
+ KviKvsVariant * m_pValue; // literal value of the parameter
+public:
+ virtual bool evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant *pBuffer);
+ virtual void contextDescription(QString &szBuffer);
+
+ virtual void dump(const char * prefix);
+
+ virtual bool convertStringConstantToNumeric();
+
+ KviKvsVariant * value(){ return m_pValue; };
+};
+
+
+#endif //!_KVI_KVS_TREENODE_CONSTANTDATA_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_corecallbackcommand.cpp b/src/kvirc/kvs/kvi_kvs_treenode_corecallbackcommand.cpp
new file mode 100644
index 00000000..191a0f6c
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_corecallbackcommand.cpp
@@ -0,0 +1,72 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_corecallbackcommand.cpp
+// Created on Thu 09 Oct 2003 02:06:26 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_corecallbackcommand.h"
+#include "kvi_kvs_treenode_datalist.h"
+#include "kvi_kvs_treenode_switchlist.h"
+#include "kvi_kvs_script.h"
+#include "kvi_kvs_runtimecontext.h"
+
+
+KviKvsTreeNodeCoreCallbackCommand::KviKvsTreeNodeCoreCallbackCommand(const QChar * pLocation,const QString &szCmdName,KviKvsTreeNodeDataList * params,KviKvsCoreCallbackCommandExecRoutine * r,KviKvsScript * pCallback)
+: KviKvsTreeNodeCallbackCommand(pLocation,szCmdName,params,pCallback)
+{
+ m_pExecRoutine = r;
+}
+
+KviKvsTreeNodeCoreCallbackCommand::~KviKvsTreeNodeCoreCallbackCommand()
+{
+}
+
+void KviKvsTreeNodeCoreCallbackCommand::contextDescription(QString &szBuffer)
+{
+ KviQString::sprintf(szBuffer,"Core Callback Command \"%Q\"",&m_szCmdName);
+}
+
+void KviKvsTreeNodeCoreCallbackCommand::dump(const char * prefix)
+{
+ debug("%s CoreCallbackCommand(%s)",prefix,m_szCmdName.utf8().data());
+ dumpSwitchList(prefix);
+ dumpParameterList(prefix);
+ dumpCallback(prefix);
+}
+
+bool KviKvsTreeNodeCoreCallbackCommand::execute(KviKvsRunTimeContext * c)
+{
+ KviKvsVariantList l;
+ l.setAutoDelete(true);
+ if(!(m_pParams->evaluate(c,&l)))return false;
+
+ KviKvsSwitchList swl;
+ if(m_pSwitches)
+ {
+ if(!(m_pSwitches->evaluate(c,&swl)))return false;
+ }
+
+ c->setDefaultReportLocation(this);
+
+ return m_pExecRoutine->proc(c,&l,&swl,m_pCallback);
+}
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_corecallbackcommand.h b/src/kvirc/kvs/kvi_kvs_treenode_corecallbackcommand.h
new file mode 100644
index 00000000..fb514150
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_corecallbackcommand.h
@@ -0,0 +1,51 @@
+#ifndef _KVI_KVS_TREENODE_CORECALLBACKCOMMAND_H_
+#define _KVI_KVS_TREENODE_CORECALLBACKCOMMAND_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_corecallbackcommand.h
+// Created on Thu 09 Oct 2003 02:06:26 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_treenode_callbackcommand.h"
+
+#include "kvi_kvs_kernel.h"
+
+class KviKvsTreeNodeDataList;
+class KviKvsScript;
+class KviKvsRunTimeContext;
+
+class KVIRC_API KviKvsTreeNodeCoreCallbackCommand : public KviKvsTreeNodeCallbackCommand
+{
+public:
+ KviKvsTreeNodeCoreCallbackCommand(const QChar * pLocation,const QString &szCmdName,KviKvsTreeNodeDataList * params,KviKvsCoreCallbackCommandExecRoutine * r,KviKvsScript * pCallback);
+ ~KviKvsTreeNodeCoreCallbackCommand();
+protected:
+ KviKvsCoreCallbackCommandExecRoutine * m_pExecRoutine;
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c);
+};
+
+
+#endif //!_KVI_KVS_TREENODE_CORECALLBACKCOMMAND_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_corefunctioncall.cpp b/src/kvirc/kvs/kvi_kvs_treenode_corefunctioncall.cpp
new file mode 100644
index 00000000..713aa393
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_corefunctioncall.cpp
@@ -0,0 +1,62 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_corefunctioncall.cpp
+// Created on Tue 07 Oct 2003 03:23:59 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_corefunctioncall.h"
+#include "kvi_kvs_runtimecontext.h"
+
+KviKvsTreeNodeCoreFunctionCall::KviKvsTreeNodeCoreFunctionCall(const QChar * pLocation,const QString &szFncName,KviKvsCoreFunctionExecRoutine * r,KviKvsTreeNodeDataList * pParams)
+: KviKvsTreeNodeFunctionCall(pLocation,szFncName,pParams)
+{
+ m_pExecRoutine = r;
+}
+
+KviKvsTreeNodeCoreFunctionCall::~KviKvsTreeNodeCoreFunctionCall()
+{
+}
+
+void KviKvsTreeNodeCoreFunctionCall::contextDescription(QString &szBuffer)
+{
+ KviQString::sprintf(szBuffer,"Core Function Call \"%Q\"",&m_szFunctionName);
+}
+
+
+void KviKvsTreeNodeCoreFunctionCall::dump(const char * prefix)
+{
+ debug("%s CoreFunctionCall(%s)",prefix,m_szFunctionName.utf8().data());
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pParams->dump(tmp.utf8().data());
+}
+
+bool KviKvsTreeNodeCoreFunctionCall::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+ KviKvsVariantList l;
+ if(!m_pParams->evaluate(c,&l))return false;
+
+ pBuffer->setNothing();
+ c->setDefaultReportLocation(this);
+ return m_pExecRoutine->proc(c,&l,pBuffer);
+}
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_corefunctioncall.h b/src/kvirc/kvs/kvi_kvs_treenode_corefunctioncall.h
new file mode 100644
index 00000000..88d1f0d3
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_corefunctioncall.h
@@ -0,0 +1,48 @@
+#ifndef _KVI_KVS_TREENODE_COREFUNCTIONCALL_H_
+#define _KVI_KVS_TREENODE_COREFUNCTIONCALL_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_corefunctioncall.h
+// Created on Tue 07 Oct 2003 03:23:59 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_kernel.h"
+#include "kvi_kvs_treenode_datalist.h"
+#include "kvi_kvs_treenode_functioncall.h"
+
+class KviKvsRunTimeContext;
+
+class KVIRC_API KviKvsTreeNodeCoreFunctionCall : public KviKvsTreeNodeFunctionCall
+{
+public:
+ KviKvsTreeNodeCoreFunctionCall(const QChar * pLocation,const QString &szFncName,KviKvsCoreFunctionExecRoutine * r,KviKvsTreeNodeDataList * pParams);
+ ~KviKvsTreeNodeCoreFunctionCall();
+protected:
+ KviKvsCoreFunctionExecRoutine * m_pExecRoutine;
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer);
+};
+
+#endif //!_KVI_KVS_TREENODE_COREFUNCTIONCALL_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_coresimplecommand.cpp b/src/kvirc/kvs/kvi_kvs_treenode_coresimplecommand.cpp
new file mode 100644
index 00000000..55fcfc3b
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_coresimplecommand.cpp
@@ -0,0 +1,70 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_coresimplecommand.cpp
+// Created on Thu 09 Oct 2003 02:14:34 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_coresimplecommand.h"
+#include "kvi_kvs_treenode_datalist.h"
+#include "kvi_kvs_treenode_switchlist.h"
+#include "kvi_kvs_runtimecontext.h"
+
+KviKvsTreeNodeCoreSimpleCommand::KviKvsTreeNodeCoreSimpleCommand(const QChar * pLocation,const QString &szCmdName,KviKvsTreeNodeDataList * params,KviKvsCoreSimpleCommandExecRoutine * r)
+: KviKvsTreeNodeSimpleCommand(pLocation,szCmdName,params)
+{
+ m_pExecRoutine = r;
+}
+
+
+KviKvsTreeNodeCoreSimpleCommand::~KviKvsTreeNodeCoreSimpleCommand()
+{
+}
+
+void KviKvsTreeNodeCoreSimpleCommand::contextDescription(QString &szBuffer)
+{
+ KviQString::sprintf(szBuffer,"Core Simple Command \"%Q\"",&m_szCmdName);
+}
+
+void KviKvsTreeNodeCoreSimpleCommand::dump(const char * prefix)
+{
+ debug("%s CoreSimpleCommand(%s)",prefix,m_szCmdName.utf8().data());
+ dumpSwitchList(prefix);
+ dumpParameterList(prefix);
+}
+
+bool KviKvsTreeNodeCoreSimpleCommand::execute(KviKvsRunTimeContext * c)
+{
+ KviKvsVariantList l;
+ l.setAutoDelete(true);
+ if(!(m_pParams->evaluate(c,&l)))return false;
+
+ KviKvsSwitchList swl;
+ if(m_pSwitches)
+ {
+ if(!(m_pSwitches->evaluate(c,&swl)))return false;
+ }
+
+ c->setDefaultReportLocation(this);
+
+ return m_pExecRoutine->proc(c,&l,&swl);
+}
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_coresimplecommand.h b/src/kvirc/kvs/kvi_kvs_treenode_coresimplecommand.h
new file mode 100644
index 00000000..764914e0
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_coresimplecommand.h
@@ -0,0 +1,49 @@
+#ifndef _KVI_KVS_TREENODE_CORESIMPLECOMMAND_H_
+#define _KVI_KVS_TREENODE_CORESIMPLECOMMAND_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_coresimplecommand.h
+// Created on Thu 09 Oct 2003 02:14:34 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_treenode_simplecommand.h"
+#include "kvi_kvs_kernel.h"
+
+class KviKvsTreeNodeDataList;
+class KviKvsRunTimeContext;
+
+class KVIRC_API KviKvsTreeNodeCoreSimpleCommand : public KviKvsTreeNodeSimpleCommand
+{
+public:
+ KviKvsTreeNodeCoreSimpleCommand(const QChar * pLocation,const QString &szCmdName,KviKvsTreeNodeDataList * params,KviKvsCoreSimpleCommandExecRoutine * r);
+ ~KviKvsTreeNodeCoreSimpleCommand();
+private:
+ KviKvsCoreSimpleCommandExecRoutine * m_pExecRoutine; // shallow pointer!
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c);
+};
+
+
+#endif //!_KVI_KVS_TREENODE_CORESIMPLECOMMAND_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_data.cpp b/src/kvirc/kvs/kvi_kvs_treenode_data.cpp
new file mode 100644
index 00000000..6d5ad63b
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_data.cpp
@@ -0,0 +1,107 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_data.cpp
+// Creation date : Sun 05 Oct 2003 21.52 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_data.h"
+#include "kvi_locale.h"
+
+
+KviKvsTreeNodeData::KviKvsTreeNodeData(const QChar * pLocation)
+: KviKvsTreeNode(pLocation), m_pEndingLocation(0)
+{
+}
+
+
+KviKvsTreeNodeData::~KviKvsTreeNodeData()
+{
+}
+
+void KviKvsTreeNodeData::contextDescription(QString &szBuffer)
+{
+ szBuffer = "Data Evaluation";
+}
+
+void KviKvsTreeNodeData::dump(const char * prefix)
+{
+ debug("%s Data",prefix);
+}
+
+bool KviKvsTreeNodeData::isReadOnly()
+{
+ return true;
+}
+
+bool KviKvsTreeNodeData::canEvaluateToObjectReference()
+{
+ return false;
+}
+
+bool KviKvsTreeNodeData::canEvaluateInObjectScope()
+{
+ return false;
+}
+
+bool KviKvsTreeNodeData::isFunctionCall()
+{
+ return false;
+}
+
+bool KviKvsTreeNodeData::convertStringConstantToNumeric()
+{
+ return false;
+}
+
+/*
+bool KviKvsTreeNodeData::canReleaseResult()
+{
+ return false;
+}
+*/
+
+bool KviKvsTreeNodeData::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+ c->error(this,__tr2qs("Internal error: pure virtual evaluateReadOnly called"));
+ return false;
+}
+
+KviKvsRWEvaluationResult * KviKvsTreeNodeData::evaluateReadWrite(KviKvsRunTimeContext * c)
+{
+ c->error(this,__tr2qs("Internal error: trying to evaluate as read-write a read-only data location"));
+ return 0;
+}
+
+
+bool KviKvsTreeNodeData::evaluateReadOnlyInObjectScope(KviKvsObject * o,KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+ c->error(this,__tr2qs("Internal error: pure virtual evaluateReadOnlyInObjectScope called"));
+ return false;
+}
+
+KviKvsRWEvaluationResult * KviKvsTreeNodeData::evaluateReadWriteInObjectScope(KviKvsObject * o,KviKvsRunTimeContext * c)
+{
+ c->error(this,__tr2qs("Internal error: trying to evaluate as read-write a read-only data location"));
+ return 0;
+}
+
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_data.h b/src/kvirc/kvs/kvi_kvs_treenode_data.h
new file mode 100644
index 00000000..dd1e3c6a
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_data.h
@@ -0,0 +1,66 @@
+#ifndef _KVI_KVS_TREENODE_DATA_H_
+#define _KVI_KVS_TREENODE_DATA_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_data.h
+// Creation date : Sun 05 Oct 2003 21.42 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_kvs_treenode_base.h"
+#include "kvi_kvs_variant.h"
+#include "kvi_kvs_runtimecontext.h"
+#include "kvi_kvs_rwevaluationresult.h"
+
+class KviKvsObject;
+
+class KVIRC_API KviKvsTreeNodeData : public KviKvsTreeNode
+{
+public:
+ KviKvsTreeNodeData(const QChar * pLocation);
+ ~KviKvsTreeNodeData();
+protected:
+ const QChar * m_pEndingLocation; // note that this MIGHT be not set (it's set for sure for anything parsed by parseCommaSeparatedParameter()
+public:
+ void setEndingLocation(const QChar * pEndingLocation){ m_pEndingLocation = pEndingLocation; };
+ const QChar * endingLocation(){ return m_pEndingLocation; };
+
+ virtual bool evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer);
+ virtual KviKvsRWEvaluationResult * evaluateReadWrite(KviKvsRunTimeContext * c); // error by default
+
+ virtual bool evaluateReadOnlyInObjectScope(KviKvsObject * o,KviKvsRunTimeContext * c,KviKvsVariant * pBuffer); // error by default
+ virtual KviKvsRWEvaluationResult * evaluateReadWriteInObjectScope(KviKvsObject * o,KviKvsRunTimeContext * c); // error by default
+
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+
+ virtual bool isReadOnly(); // true by default
+ virtual bool canEvaluateToObjectReference(); // no by default
+ virtual bool isFunctionCall(); // no by default
+ virtual bool canEvaluateInObjectScope(); // no by default
+
+ virtual bool convertStringConstantToNumeric(); // this does nothing by default and is reimplemented only by KviKvsTreeNodeConstantData
+};
+
+
+
+
+
+#endif //!_KVI_KVS_TREENODE_DATA_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_datalist.cpp b/src/kvirc/kvs/kvi_kvs_treenode_datalist.cpp
new file mode 100644
index 00000000..18da8280
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_datalist.cpp
@@ -0,0 +1,110 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_datalist.cpp
+// Created on Tue 07 Oct 2003 02:03:41 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_datalist.h"
+#include "kvi_kvs_runtimecontext.h"
+
+#include "kvi_qstring.h"
+
+KviKvsTreeNodeDataList::KviKvsTreeNodeDataList(const QChar * pLocation)
+: KviKvsTreeNode(pLocation)
+{
+ m_pDataList = new KviPointerList<KviKvsTreeNodeData>();
+ m_pDataList->setAutoDelete(true);
+}
+
+KviKvsTreeNodeDataList::~KviKvsTreeNodeDataList()
+{
+ delete m_pDataList;
+}
+
+KviKvsTreeNodeData * KviKvsTreeNodeDataList::releaseFirst()
+{
+ KviKvsTreeNodeData * d = m_pDataList->first();
+ if(d)
+ {
+ m_pDataList->setAutoDelete(false);
+ m_pDataList->removeFirst();
+ m_pDataList->setAutoDelete(true);
+ }
+ return d;
+}
+
+KviKvsTreeNodeData * KviKvsTreeNodeDataList::item(unsigned int uIdx)
+{
+ if(uIdx >= m_pDataList->count())return 0;
+ return m_pDataList->at(uIdx);
+}
+
+
+void KviKvsTreeNodeDataList::contextDescription(QString &szBuffer)
+{
+ szBuffer = "Data List Evaluation";
+}
+
+void KviKvsTreeNodeDataList::dump(const char * prefix)
+{
+ debug("%s DataList",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ for(KviKvsTreeNodeData * t = m_pDataList->first();t;t = m_pDataList->next())
+ {
+ t->dump(tmp.utf8().data());
+ }
+}
+
+bool KviKvsTreeNodeDataList::evaluate(KviKvsRunTimeContext * c,KviKvsVariantList * pBuffer)
+{
+ pBuffer->clear();
+
+ // we use an iterator to accomodate recursion
+ KviPointerListIterator<KviKvsTreeNodeData> it(*m_pDataList);
+ while(KviKvsTreeNodeData * t = it.current())
+ {
+ KviKvsVariant * v = new KviKvsVariant();
+ if(!t->evaluateReadOnly(c,v))
+ {
+ delete v;
+ pBuffer->clear();
+ return false;
+ }
+ pBuffer->append(v);
+ ++it;
+ }
+ return true;
+}
+
+void KviKvsTreeNodeDataList::addItem(KviKvsTreeNodeData * p)
+{
+ m_pDataList->append(p);
+ p->setParent(this);
+}
+
+void KviKvsTreeNodeDataList::prependItem(KviKvsTreeNodeData * p)
+{
+ m_pDataList->prepend(p);
+ p->setParent(this);
+}
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_datalist.h b/src/kvirc/kvs/kvi_kvs_treenode_datalist.h
new file mode 100644
index 00000000..1a370a41
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_datalist.h
@@ -0,0 +1,57 @@
+#ifndef _KVI_KVS_TREENODE_DATALIST_H_
+#define _KVI_KVS_TREENODE_DATALIST_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_datalist.h
+// Created on Tue 07 Oct 2003 02:03:41 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#include "kvi_pointerlist.h"
+
+#include "kvi_kvs_variantlist.h"
+#include "kvi_kvs_treenode_base.h"
+#include "kvi_kvs_treenode_data.h"
+
+class KviKvsRunTimeContext;
+
+class KVIRC_API KviKvsTreeNodeDataList : public KviKvsTreeNode
+{
+ friend class KviKvsParser;
+public:
+ KviKvsTreeNodeDataList(const QChar * pLocation);
+ ~KviKvsTreeNodeDataList();
+protected:
+ KviPointerList<KviKvsTreeNodeData> * m_pDataList;
+protected:
+ void addItem(KviKvsTreeNodeData * p);
+ void prependItem(KviKvsTreeNodeData * p);
+public:
+ KviKvsTreeNodeData * item(unsigned int uIdx);
+ KviKvsTreeNodeData * releaseFirst();
+ bool evaluate(KviKvsRunTimeContext * c,KviKvsVariantList * pBuffer);
+ virtual void contextDescription(QString &szBuffer);
+
+ virtual void dump(const char * prefix);
+};
+
+#endif //!_KVI_KVS_TREENODE_DATALIST_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_expression.cpp b/src/kvirc/kvs/kvi_kvs_treenode_expression.cpp
new file mode 100644
index 00000000..ae3ec45b
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_expression.cpp
@@ -0,0 +1,776 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_expression.cpp
+// Creation date : Mon 06 Oct 2003 01.35 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_expression.h"
+#include "kvi_locale.h"
+
+#include <math.h>
+
+KviKvsTreeNodeExpression::KviKvsTreeNodeExpression(const QChar * pLocation)
+: KviKvsTreeNodeData(pLocation)
+{
+ m_pParentExpression = 0;
+}
+
+KviKvsTreeNodeExpression::~KviKvsTreeNodeExpression()
+{
+}
+
+
+void KviKvsTreeNodeExpression::contextDescription(QString &szBuffer)
+{
+ szBuffer = "Expression Evaluation";
+}
+
+void KviKvsTreeNodeExpression::dump(const char * prefix)
+{
+ debug("%s Expression",prefix);
+}
+
+int KviKvsTreeNodeExpression::precedence()
+{
+ return PREC_MAXIMUM;
+}
+
+KviKvsTreeNodeExpression * KviKvsTreeNodeExpression::left()
+{
+ debug("KviKvsTreeNodeExpression::left() : should never end up here!");
+ return 0;
+}
+
+KviKvsTreeNodeExpression * KviKvsTreeNodeExpression::right()
+{
+ debug("KviKvsTreeNodeExpression::right() : should never end up here!");
+ return 0;
+}
+
+void KviKvsTreeNodeExpression::setLeft(KviKvsTreeNodeExpression *)
+{
+ debug("KviKvsTreeNodeExpression::setLeft() : should never end up here!");
+}
+
+void KviKvsTreeNodeExpression::setRight(KviKvsTreeNodeExpression *)
+{
+ debug("KviKvsTreeNodeExpression::setRight() : should never end up here!");
+}
+
+KviKvsTreeNodeExpression * KviKvsTreeNodeExpression::parentWithPrecedenceLowerThan(int iPrec)
+{
+ if(precedence() > iPrec)return this;
+ if(!parentExpression())return 0;
+ return parentExpression()->parentWithPrecedenceLowerThan(iPrec);
+}
+
+int KviKvsTreeNodeExpression::firstBinaryOperator()
+{
+ if(!left())return precedence();
+ return left()->firstBinaryOperator();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+
+KviKvsTreeNodeExpressionVariableOperand::KviKvsTreeNodeExpressionVariableOperand(const QChar * pLocation,KviKvsTreeNodeData * pData)
+: KviKvsTreeNodeExpression(pLocation)
+{
+ m_pData = pData;
+ m_pData->setParent(this);
+}
+
+KviKvsTreeNodeExpressionVariableOperand::~KviKvsTreeNodeExpressionVariableOperand()
+{
+ delete m_pData;
+}
+
+void KviKvsTreeNodeExpressionVariableOperand::contextDescription(QString &szBuffer)
+{
+ szBuffer = "Expression Variable Operand Evaluation";
+}
+
+void KviKvsTreeNodeExpressionVariableOperand::dump(const char * prefix)
+{
+ debug("%s ExpressionVariableOperand",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pData->dump(tmp.utf8().data());
+}
+
+bool KviKvsTreeNodeExpressionVariableOperand::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+ return m_pData->evaluateReadOnly(c,pBuffer);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+KviKvsTreeNodeExpressionConstantOperand::KviKvsTreeNodeExpressionConstantOperand(const QChar * pLocation,KviKvsVariant * pConstant)
+: KviKvsTreeNodeExpression(pLocation)
+{
+#ifdef COMPILE_NEW_KVS
+ m_pConstant = pConstant;
+#endif
+}
+
+KviKvsTreeNodeExpressionConstantOperand::~KviKvsTreeNodeExpressionConstantOperand()
+{
+#ifdef COMPILE_NEW_KVS
+ delete m_pConstant;
+#endif
+}
+
+void KviKvsTreeNodeExpressionConstantOperand::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Expression Constant Operand Evaluation";
+#endif
+}
+
+
+void KviKvsTreeNodeExpressionConstantOperand::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s ExpressionConstantOperand",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pConstant->dump(tmp.utf8().data());
+#endif
+}
+
+bool KviKvsTreeNodeExpressionConstantOperand::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ pBuffer->copyFrom(m_pConstant);
+#endif
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+
+KviKvsTreeNodeExpressionOperator::KviKvsTreeNodeExpressionOperator(const QChar * pLocation)
+: KviKvsTreeNodeExpression(pLocation)
+{
+}
+
+KviKvsTreeNodeExpressionOperator::~KviKvsTreeNodeExpressionOperator()
+{
+}
+
+void KviKvsTreeNodeExpressionOperator::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Expression Operator Evaluation";
+#endif
+}
+
+
+void KviKvsTreeNodeExpressionOperator::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s ExpressionOperator",prefix);
+#endif
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+
+KviKvsTreeNodeExpressionUnaryOperator::KviKvsTreeNodeExpressionUnaryOperator(const QChar * pLocation,KviKvsTreeNodeExpression * pData)
+: KviKvsTreeNodeExpressionOperator(pLocation)
+{
+#ifdef COMPILE_NEW_KVS
+ m_pData = pData;
+ m_pData->setParent(this);
+ m_pData->setParentExpression(this);
+#endif
+}
+
+KviKvsTreeNodeExpressionUnaryOperator::~KviKvsTreeNodeExpressionUnaryOperator()
+{
+#ifdef COMPILE_NEW_KVS
+ delete m_pData;
+#endif
+}
+
+void KviKvsTreeNodeExpressionUnaryOperator::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Expression Unary Operator Evaluation";
+#endif
+}
+
+
+
+
+void KviKvsTreeNodeExpressionUnaryOperator::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s ExpressionUnaryOperator",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pData->dump(tmp.utf8().data());
+#endif
+}
+
+bool KviKvsTreeNodeExpressionUnaryOperator::evaluateOperand(KviKvsRunTimeContext * c)
+{
+#ifdef COMPILE_NEW_KVS
+ KviKvsVariant v;
+ if(!m_pData->evaluateReadOnly(c,&v))return false;
+
+ if(!v.asNumber(m_nData))
+ {
+ c->error(this,__tr2qs("Operand of unary operator didn't evaluate to a number"));
+ return false;
+ }
+#endif
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+
+KviKvsTreeNodeExpressionUnaryOperatorNegate::KviKvsTreeNodeExpressionUnaryOperatorNegate(const QChar * pLocation,KviKvsTreeNodeExpression * pData)
+: KviKvsTreeNodeExpressionUnaryOperator(pLocation,pData)
+{
+}
+
+KviKvsTreeNodeExpressionUnaryOperatorNegate::~KviKvsTreeNodeExpressionUnaryOperatorNegate()
+{
+}
+
+
+void KviKvsTreeNodeExpressionUnaryOperatorNegate::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Expression Unary Operator Negate";
+#endif
+}
+
+
+void KviKvsTreeNodeExpressionUnaryOperatorNegate::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s ExpressionUnaryOperatorNegate",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pData->dump(tmp.utf8().data());
+#endif
+}
+
+int KviKvsTreeNodeExpressionUnaryOperatorNegate::precedence()
+{
+ return PREC_OP_NEGATE;
+}
+
+bool KviKvsTreeNodeExpressionUnaryOperatorNegate::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ if(!evaluateOperand(c))return false;
+ if(m_nData.isReal())pBuffer->setReal(-m_nData.real());
+ else pBuffer->setInteger(-m_nData.integer());
+#endif
+ return true;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+
+KviKvsTreeNodeExpressionUnaryOperatorBitwiseNot::KviKvsTreeNodeExpressionUnaryOperatorBitwiseNot(const QChar * pLocation,KviKvsTreeNodeExpression * pData)
+: KviKvsTreeNodeExpressionUnaryOperator(pLocation,pData)
+{
+}
+
+KviKvsTreeNodeExpressionUnaryOperatorBitwiseNot::~KviKvsTreeNodeExpressionUnaryOperatorBitwiseNot()
+{
+}
+
+void KviKvsTreeNodeExpressionUnaryOperatorBitwiseNot::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Expression Unary Operator Bitwise Not";
+#endif
+}
+
+void KviKvsTreeNodeExpressionUnaryOperatorBitwiseNot::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s ExpressionUnaryOperatorBitwiseNot",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pData->dump(tmp.utf8().data());
+#endif
+}
+
+int KviKvsTreeNodeExpressionUnaryOperatorBitwiseNot::precedence()
+{
+ return PREC_OP_BITWISENOT;
+}
+
+bool KviKvsTreeNodeExpressionUnaryOperatorBitwiseNot::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ if(!evaluateOperand(c))return false;
+ if(m_nData.isReal())pBuffer->setInteger(~(int)(m_nData.real()));
+ else pBuffer->setInteger(~m_nData.integer());
+#endif
+ return true;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+
+KviKvsTreeNodeExpressionUnaryOperatorLogicalNot::KviKvsTreeNodeExpressionUnaryOperatorLogicalNot(const QChar * pLocation,KviKvsTreeNodeExpression * pData)
+: KviKvsTreeNodeExpressionUnaryOperator(pLocation,pData)
+{
+}
+
+KviKvsTreeNodeExpressionUnaryOperatorLogicalNot::~KviKvsTreeNodeExpressionUnaryOperatorLogicalNot()
+{
+}
+
+void KviKvsTreeNodeExpressionUnaryOperatorLogicalNot::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Expression Unary Operator Logical Not";
+#endif
+}
+
+void KviKvsTreeNodeExpressionUnaryOperatorLogicalNot::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s ExpressionUnaryOperatorLogicalNot",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pData->dump(tmp.utf8().data());
+#endif
+}
+
+int KviKvsTreeNodeExpressionUnaryOperatorLogicalNot::precedence()
+{
+ return PREC_OP_LOGICALNOT;
+}
+
+bool KviKvsTreeNodeExpressionUnaryOperatorLogicalNot::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ KviKvsVariant v;
+ if(!m_pData->evaluateReadOnly(c,&v))return false;
+//#warning "FIXME: We could use setNothing() for false and setInteger(1) for true: this would save memory allocations for false conditions"
+ pBuffer->setBoolean(!v.asBoolean());
+#endif
+ return true;
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+
+KviKvsTreeNodeExpressionBinaryOperator::KviKvsTreeNodeExpressionBinaryOperator(const QChar * pLocation)
+: KviKvsTreeNodeExpressionOperator(pLocation)
+{
+ m_pLeft = 0;
+ m_pRight = 0;
+}
+
+KviKvsTreeNodeExpressionBinaryOperator::~KviKvsTreeNodeExpressionBinaryOperator()
+{
+ if(m_pLeft)delete m_pLeft;
+ if(m_pRight)delete m_pRight;
+}
+
+bool KviKvsTreeNodeExpressionBinaryOperator::evaluateOperands(KviKvsRunTimeContext * c)
+{
+ KviKvsVariant v1;
+ if(!m_pLeft->evaluateReadOnly(c,&v1))return false;
+ if(!v1.asNumber(m_nLeft))
+ {
+ c->error(this,__tr2qs("Left operand didn't evaluate to a number"));
+ return false;
+ }
+ KviKvsVariant v2;
+ if(!m_pRight->evaluateReadOnly(c,&v2))return false;
+ if(!v2.asNumber(m_nRight))
+ {
+ c->error(this,__tr2qs("Right operand didn't evaluate to a number"));
+ return false;
+ }
+ return true;
+}
+
+KviKvsTreeNodeExpression * KviKvsTreeNodeExpressionBinaryOperator::left()
+{
+ return m_pLeft;
+}
+
+KviKvsTreeNodeExpression * KviKvsTreeNodeExpressionBinaryOperator::right()
+{
+ return m_pRight;
+}
+
+int KviKvsTreeNodeExpressionBinaryOperator::firstBinaryOperator()
+{
+ return precedence();
+}
+
+void KviKvsTreeNodeExpressionBinaryOperator::setLeft(KviKvsTreeNodeExpression * pLeft)
+{
+ m_pLeft = pLeft;
+ m_pLeft->setParent(this);
+ m_pLeft->setParentExpression(this);
+}
+
+void KviKvsTreeNodeExpressionBinaryOperator::setRight(KviKvsTreeNodeExpression * pRight)
+{
+ m_pRight = pRight;
+ m_pRight->setParent(this);
+ m_pRight->setParentExpression(this);
+}
+
+
+void KviKvsTreeNodeExpressionBinaryOperator::dumpOperands(const char * prefix)
+{
+ QString tmp = prefix;
+ tmp.append(" ");
+ if(m_pLeft)m_pLeft->dump(tmp.utf8().data());
+ if(m_pRight)m_pRight->dump(tmp.utf8().data());
+}
+
+void KviKvsTreeNodeExpressionBinaryOperator::contextDescription(QString &szBuffer)
+{
+ szBuffer = "Expression Binary Operator";
+}
+
+void KviKvsTreeNodeExpressionBinaryOperator::dump(const char * prefix)
+{
+ debug("%s ExpressionBinaryOperator",prefix);
+ dumpOperands(prefix);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+
+#define PREIMPLEMENT_BINARY_OPERATOR(__name,__stringname,__contextdescription,__precedence) \
+ __name::__name(const QChar * pLocation) \
+ : KviKvsTreeNodeExpressionBinaryOperator(pLocation){} \
+ __name::~__name(){} \
+ void __name::dump(const char * prefix){ debug("%s " __stringname,prefix); dumpOperands(prefix); } \
+ void __name::contextDescription(QString &szBuffer){ szBuffer = __contextdescription; } \
+ int __name::precedence(){ return __precedence; };
+
+PREIMPLEMENT_BINARY_OPERATOR(KviKvsTreeNodeExpressionBinaryOperatorSum,"ExpressionBinaryOperatorSum","Expression Binary Operator \"+\"",PREC_OP_SUM)
+
+bool KviKvsTreeNodeExpressionBinaryOperatorSum::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+ if(!evaluateOperands(c))return false;
+ if(m_nLeft.isInteger())
+ {
+ if(m_nRight.isInteger())pBuffer->setInteger(m_nLeft.integer() + m_nRight.integer());
+ else pBuffer->setReal(m_nLeft.integer() + m_nRight.real());
+ } else {
+ if(m_nRight.isInteger())pBuffer->setReal(m_nLeft.real() + m_nRight.integer());
+ else pBuffer->setReal(m_nLeft.real() + m_nRight.real());
+ }
+ return true;
+}
+
+PREIMPLEMENT_BINARY_OPERATOR(KviKvsTreeNodeExpressionBinaryOperatorSubtraction,"ExpressionBinaryOperatorSubtraction","Expression Binary Operator \"-\"",PREC_OP_SUBTRACTION)
+
+bool KviKvsTreeNodeExpressionBinaryOperatorSubtraction::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+ if(!evaluateOperands(c))return false;
+ if(m_nLeft.isInteger())
+ {
+ if(m_nRight.isInteger())pBuffer->setInteger(m_nLeft.integer() - m_nRight.integer());
+ else pBuffer->setReal(((kvs_real_t)(m_nLeft.integer())) - m_nRight.real());
+ } else {
+ if(m_nRight.isInteger())pBuffer->setReal(m_nLeft.real() - ((kvs_real_t)(m_nRight.integer())));
+ else pBuffer->setReal(m_nLeft.real() - m_nRight.real());
+ }
+ return true;
+}
+
+PREIMPLEMENT_BINARY_OPERATOR(KviKvsTreeNodeExpressionBinaryOperatorMultiplication,"ExpressionBinaryOperatorMultiplication","Expression Binary Operator \"*\"",PREC_OP_MULTIPLICATION)
+
+bool KviKvsTreeNodeExpressionBinaryOperatorMultiplication::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+ if(!evaluateOperands(c))return false;
+ if(m_nLeft.isInteger())
+ {
+ if(m_nRight.isInteger())pBuffer->setInteger(m_nLeft.integer() * m_nRight.integer());
+ else pBuffer->setReal(((kvs_real_t)(m_nLeft.integer())) * m_nRight.real());
+ } else {
+ if(m_nRight.isInteger())pBuffer->setReal(m_nLeft.real() * ((kvs_real_t)(m_nRight.integer())));
+ else pBuffer->setReal(m_nLeft.real() * m_nRight.real());
+ }
+ return true;
+}
+
+
+PREIMPLEMENT_BINARY_OPERATOR(KviKvsTreeNodeExpressionBinaryOperatorDivision,"ExpressionBinaryOperatorDivision","Expression Binary Operator \"/\"",PREC_OP_DIVISION)
+
+bool KviKvsTreeNodeExpressionBinaryOperatorDivision::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+ if(!evaluateOperands(c))return false;
+
+ if(m_nRight.isInteger())
+ {
+ if(m_nRight.integer() == 0)
+ {
+ c->error(this,__tr2qs("Division by zero"));
+ return false;
+ }
+ if(m_nLeft.isInteger())pBuffer->setInteger(m_nLeft.integer() / m_nRight.integer());
+ else pBuffer->setReal(m_nLeft.real() / ((kvs_real_t)(m_nRight.integer())));
+ } else {
+ if(m_nRight.real() == 0.0)
+ {
+ c->error(this,__tr2qs("Division by zero"));
+ return false;
+ }
+ if(m_nLeft.isInteger())pBuffer->setReal(((kvs_real_t)(m_nLeft.integer())) / m_nRight.real());
+ else pBuffer->setReal(m_nLeft.real() / m_nRight.real());
+ }
+ return true;
+}
+
+
+PREIMPLEMENT_BINARY_OPERATOR(KviKvsTreeNodeExpressionBinaryOperatorModulus,"ExpressionBinaryOperatorModulus","Expression Binary Operator \"modulus\"",PREC_OP_MODULUS)
+
+bool KviKvsTreeNodeExpressionBinaryOperatorModulus::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+ if(!evaluateOperands(c))return false;
+
+ if(m_nRight.isInteger())
+ {
+ if(m_nRight.integer() == 0)
+ {
+ c->error(this,__tr2qs("Division by zero"));
+ return false;
+ }
+ if(m_nLeft.isInteger())pBuffer->setInteger(m_nLeft.integer() % m_nRight.integer());
+ else pBuffer->setReal(fmod(m_nLeft.real(),((kvs_real_t)(m_nRight.integer()))));
+ } else {
+ if(m_nRight.real() == 0.0)
+ {
+ c->error(this,__tr2qs("Division by zero"));
+ return false;
+ }
+ if(m_nLeft.isInteger())pBuffer->setReal(fmod(((kvs_real_t)(m_nLeft.integer())),m_nRight.real()));
+ else pBuffer->setReal(fmod(m_nLeft.real(),m_nRight.real()));
+ }
+ return true;
+}
+
+PREIMPLEMENT_BINARY_OPERATOR(KviKvsTreeNodeExpressionBinaryOperatorBitwiseAnd,"ExpressionBinaryOperatorBitwiseAnd","Expression Binary Operator \"&\"",PREC_OP_BITWISEAND)
+
+bool KviKvsTreeNodeExpressionBinaryOperatorBitwiseAnd::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+ if(!evaluateOperands(c))return false;
+ int iLeft = m_nLeft.isInteger() ? m_nLeft.integer() : (kvs_int_t)m_nLeft.real();
+ int iRight = m_nRight.isInteger() ? m_nRight.integer() : (kvs_int_t)m_nRight.real();
+ pBuffer->setInteger(iLeft & iRight);
+ return true;
+}
+
+PREIMPLEMENT_BINARY_OPERATOR(KviKvsTreeNodeExpressionBinaryOperatorBitwiseOr,"ExpressionBinaryOperatorBitwiseOr","Expression Binary Operator \"|\"",PREC_OP_BITWISEOR)
+
+bool KviKvsTreeNodeExpressionBinaryOperatorBitwiseOr::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+ if(!evaluateOperands(c))return false;
+ int iLeft = m_nLeft.isInteger() ? m_nLeft.integer() : (kvs_int_t)m_nLeft.real();
+ int iRight = m_nRight.isInteger() ? m_nRight.integer() : (kvs_int_t)m_nRight.real();
+ pBuffer->setInteger(iLeft | iRight);
+ return true;
+}
+
+PREIMPLEMENT_BINARY_OPERATOR(KviKvsTreeNodeExpressionBinaryOperatorBitwiseXor,"ExpressionBinaryOperatorBitwiseXor","Expression Binary Operator \"^\"",PREC_OP_BITWISEXOR)
+
+bool KviKvsTreeNodeExpressionBinaryOperatorBitwiseXor::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+ if(!evaluateOperands(c))return false;
+ int iLeft = m_nLeft.isInteger() ? m_nLeft.integer() : (kvs_int_t)m_nLeft.real();
+ int iRight = m_nRight.isInteger() ? m_nRight.integer() : (kvs_int_t)m_nRight.real();
+ pBuffer->setInteger(iLeft ^ iRight);
+ return true;
+}
+
+PREIMPLEMENT_BINARY_OPERATOR(KviKvsTreeNodeExpressionBinaryOperatorShiftLeft,"ExpressionBinaryOperatorShiftLeft","Expression Binary Operator \"<<\"",PREC_OP_SHIFTLEFT)
+
+bool KviKvsTreeNodeExpressionBinaryOperatorShiftLeft::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+ if(!evaluateOperands(c))return false;
+ int iLeft = m_nLeft.isInteger() ? m_nLeft.integer() : (kvs_int_t)(m_nLeft.real());
+ int iRight = m_nRight.isInteger() ? m_nRight.integer() : (kvs_int_t)(m_nRight.real());
+ pBuffer->setInteger(iLeft << iRight);
+ return true;
+}
+
+PREIMPLEMENT_BINARY_OPERATOR(KviKvsTreeNodeExpressionBinaryOperatorShiftRight,"ExpressionBinaryOperatorShiftRight","Expression Binary Operator \">>\"",PREC_OP_SHIFTRIGHT)
+
+bool KviKvsTreeNodeExpressionBinaryOperatorShiftRight::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+ if(!evaluateOperands(c))return false;
+ int iLeft = m_nLeft.isInteger() ? m_nLeft.integer() : (kvs_int_t)(m_nLeft.real());
+ int iRight = m_nRight.isInteger() ? m_nRight.integer() : (kvs_int_t)(m_nRight.real());
+ pBuffer->setInteger(iLeft >> iRight);
+ return true;
+}
+
+PREIMPLEMENT_BINARY_OPERATOR(KviKvsTreeNodeExpressionBinaryOperatorAnd,"ExpressionBinaryOperatorAnd","Expression Binary Operator \"&&\"",PREC_OP_AND)
+
+bool KviKvsTreeNodeExpressionBinaryOperatorAnd::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+ KviKvsVariant v1;
+ KviKvsVariant v2;
+ if(!m_pLeft->evaluateReadOnly(c,&v1))return false;
+ //#warning "FIXME: We could use setNothing() as false: this would save memory allocations (and thus time)"
+ if(!v1.asBoolean())
+ {
+ pBuffer->setBoolean(false);
+ return true;
+ }
+ if(!m_pRight->evaluateReadOnly(c,&v2))return false;
+ pBuffer->setBoolean(v2.asBoolean());
+ return true;
+}
+
+
+PREIMPLEMENT_BINARY_OPERATOR(KviKvsTreeNodeExpressionBinaryOperatorOr,"ExpressionBinaryOperatorOr","Expression Binary Operator \"||\"",PREC_OP_OR)
+
+bool KviKvsTreeNodeExpressionBinaryOperatorOr::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+ KviKvsVariant v1;
+ KviKvsVariant v2;
+ if(!m_pLeft->evaluateReadOnly(c,&v1))return false;
+ //#warning "FIXME: We could use setNothing() as false: this would save memory allocations (and thus time)"
+ if(v1.asBoolean())
+ {
+ pBuffer->setBoolean(true);
+ return true;
+ }
+ if(!m_pRight->evaluateReadOnly(c,&v2))return false;
+ pBuffer->setBoolean(v2.asBoolean());
+ return true;
+}
+
+
+PREIMPLEMENT_BINARY_OPERATOR(KviKvsTreeNodeExpressionBinaryOperatorXor,"ExpressionBinaryOperatorXor","Expression Binary Operator \"^^\"",PREC_OP_XOR)
+
+bool KviKvsTreeNodeExpressionBinaryOperatorXor::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+ KviKvsVariant v1;
+ KviKvsVariant v2;
+ if(!m_pLeft->evaluateReadOnly(c,&v1))return false;
+ if(!m_pRight->evaluateReadOnly(c,&v2))return false;
+ //#warning "FIXME: We could use setNothing() as false: this would save memory allocations (and thus time)"
+ if(v1.asBoolean())
+ pBuffer->setBoolean(!v2.asBoolean());
+ else {
+ if(v2.asBoolean())
+ pBuffer->setBoolean(!v1.asBoolean());
+ else
+ pBuffer->setBoolean(false);
+ }
+ return true;
+}
+
+PREIMPLEMENT_BINARY_OPERATOR(KviKvsTreeNodeExpressionBinaryOperatorLowerThan,"ExpressionBinaryOperatorLowerThan","Expression Binary Operator \"<\"",PREC_OP_LOWERTHAN)
+
+bool KviKvsTreeNodeExpressionBinaryOperatorLowerThan::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+ KviKvsVariant v1;
+ KviKvsVariant v2;
+ if(!m_pLeft->evaluateReadOnly(c,&v1))return false;
+ if(!m_pRight->evaluateReadOnly(c,&v2))return false;
+ pBuffer->setBoolean(v1.compare(&v2,true) > 0);
+ return true;
+}
+
+PREIMPLEMENT_BINARY_OPERATOR(KviKvsTreeNodeExpressionBinaryOperatorGreaterThan,"ExpressionBinaryOperatorGreaterThan","Expression Binary Operator \">\"",PREC_OP_GREATERTHAN)
+
+bool KviKvsTreeNodeExpressionBinaryOperatorGreaterThan::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+ KviKvsVariant v1;
+ KviKvsVariant v2;
+ if(!m_pLeft->evaluateReadOnly(c,&v1))return false;
+ if(!m_pRight->evaluateReadOnly(c,&v2))return false;
+ pBuffer->setBoolean(v1.compare(&v2,true) < 0);
+ return true;
+}
+
+PREIMPLEMENT_BINARY_OPERATOR(KviKvsTreeNodeExpressionBinaryOperatorLowerOrEqualTo,"ExpressionBinaryOperatorLowerOrEqualTo","Expression Binary Operator \"<=\"",PREC_OP_LOWEROREQUALTO)
+
+bool KviKvsTreeNodeExpressionBinaryOperatorLowerOrEqualTo::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+ KviKvsVariant v1;
+ KviKvsVariant v2;
+ if(!m_pLeft->evaluateReadOnly(c,&v1))return false;
+ if(!m_pRight->evaluateReadOnly(c,&v2))return false;
+ pBuffer->setBoolean(v1.compare(&v2,true) >= 0);
+ return true;
+}
+
+PREIMPLEMENT_BINARY_OPERATOR(KviKvsTreeNodeExpressionBinaryOperatorGreaterOrEqualTo,"ExpressionBinaryOperatorGreaterOrEqualTo","Expression Binary Operator \">=\"",PREC_OP_GREATEROREQUALTO)
+
+bool KviKvsTreeNodeExpressionBinaryOperatorGreaterOrEqualTo::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+ KviKvsVariant v1;
+ KviKvsVariant v2;
+ if(!m_pLeft->evaluateReadOnly(c,&v1))return false;
+ if(!m_pRight->evaluateReadOnly(c,&v2))return false;
+ pBuffer->setBoolean(v1.compare(&v2,true) <= 0);
+ return true;
+}
+
+PREIMPLEMENT_BINARY_OPERATOR(KviKvsTreeNodeExpressionBinaryOperatorEqualTo,"ExpressionBinaryOperatorEqualTo","Expression Binary Operator \"==\"",PREC_OP_EQUALTO)
+
+bool KviKvsTreeNodeExpressionBinaryOperatorEqualTo::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+ KviKvsVariant v1;
+ KviKvsVariant v2;
+ if(!m_pLeft->evaluateReadOnly(c,&v1))return false;
+ if(!m_pRight->evaluateReadOnly(c,&v2))return false;
+ pBuffer->setBoolean(v1.compare(&v2,true) == 0);
+ return true;
+}
+
+
+PREIMPLEMENT_BINARY_OPERATOR(KviKvsTreeNodeExpressionBinaryOperatorNotEqualTo,"ExpressionBinaryOperatorNotEqualTo","Expression Binary Operator \"!=\"",PREC_OP_NOTEQUALTO)
+
+bool KviKvsTreeNodeExpressionBinaryOperatorNotEqualTo::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+ KviKvsVariant v1;
+ KviKvsVariant v2;
+ if(!m_pLeft->evaluateReadOnly(c,&v1))return false;
+ if(!m_pRight->evaluateReadOnly(c,&v2))return false;
+ pBuffer->setBoolean(v1.compare(&v2,true) != 0);
+ return true;
+}
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_expression.h b/src/kvirc/kvs/kvi_kvs_treenode_expression.h
new file mode 100644
index 00000000..948066d0
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_expression.h
@@ -0,0 +1,249 @@
+#ifndef _KVI_KVS_TREENODE_EXPRESSION_H_
+#define _KVI_KVS_TREENODE_EXPRESSION_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_expression.h
+// Creation date : Mon 06 Oct 2003 01.33 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_qstring.h"
+#include "kvi_kvs_variant.h"
+#include "kvi_kvs_treenode_data.h"
+
+
+// absolute precedence (~operand part)
+#define PREC_MAXIMUM -10
+
+
+#define PREC_OP_LOGICALNOT -3 /* ! */
+#define PREC_OP_BITWISENOT -2 /* ~ */
+#define PREC_OP_NEGATE -1 /* - */
+// high precedence
+#define PREC_OP_BITWISEAND 0 /* & */
+#define PREC_OP_BITWISEOR 1 /* | */
+#define PREC_OP_BITWISEXOR 2 /* ^ */
+
+#define PREC_OP_SHIFTRIGHT 3 /* >> */
+#define PREC_OP_SHIFTLEFT 3 /* << */
+
+#define PREC_OP_MULTIPLICATION 5 /* * */
+#define PREC_OP_DIVISION 5 /* / */
+#define PREC_OP_MODULUS 5 /* % */
+
+#define PREC_OP_SUM 8 /* + */
+#define PREC_OP_SUBTRACTION 8 /* - */
+
+#define PREC_OP_GREATERTHAN 11 /* > */ /* Case sensitive (normal for numbers) */
+#define PREC_OP_LOWERTHAN 11 /* < */ /* Case sensitive (normal for numbers) */
+
+#define PREC_OP_EQUALTO 12 /* == */ /* Case sensitive comparison for strings or normal comp.fr numbers */
+
+#define PREC_OP_GREATEROREQUALTO 14 /* >= */ /* Case sensitive (normal for numbers) */
+#define PREC_OP_LOWEROREQUALTO 14 /* <= */ /* Case sensitive (normal for numbers) */
+
+#define PREC_OP_NOTEQUALTO 15 /* != */ /* Case sensitive (normal for numbers) */
+
+#define PREC_OP_AND 16 /* && */
+#define PREC_OP_OR 17 /* || */
+#define PREC_OP_XOR 18 /* ^^ */
+// low precedence
+
+
+class KVIRC_API KviKvsTreeNodeExpression : public KviKvsTreeNodeData
+{
+ // this class is never instantiated
+public:
+ KviKvsTreeNodeExpression(const QChar * pLocation);
+ ~KviKvsTreeNodeExpression();
+protected:
+ KviKvsTreeNodeExpression * m_pParentExpression;
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual int precedence();
+ virtual KviKvsTreeNodeExpression * left();
+ virtual KviKvsTreeNodeExpression * right();
+ virtual void setLeft(KviKvsTreeNodeExpression * pLeft);
+ virtual void setRight(KviKvsTreeNodeExpression * pRight);
+ virtual int firstBinaryOperator();
+ KviKvsTreeNodeExpression * parentExpression(){ return m_pParentExpression; };
+ void setParentExpression(KviKvsTreeNodeExpression * pParent){ m_pParentExpression = pParent; };
+ virtual KviKvsTreeNodeExpression * parentWithPrecedenceLowerThan(int iPrec);
+};
+
+
+class KVIRC_API KviKvsTreeNodeExpressionVariableOperand : public KviKvsTreeNodeExpression
+{
+public:
+ KviKvsTreeNodeExpressionVariableOperand(const QChar * pLocation,KviKvsTreeNodeData * pData);
+ ~KviKvsTreeNodeExpressionVariableOperand();
+protected:
+ KviKvsTreeNodeData * m_pData; // can't be null
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pResult);
+};
+
+
+class KVIRC_API KviKvsTreeNodeExpressionConstantOperand : public KviKvsTreeNodeExpression
+{
+public:
+ KviKvsTreeNodeExpressionConstantOperand(const QChar * pLocation,KviKvsVariant * pConstant);
+ ~KviKvsTreeNodeExpressionConstantOperand();
+public:
+ KviKvsVariant * m_pConstant;
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pResult);
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+class KVIRC_API KviKvsTreeNodeExpressionOperator : public KviKvsTreeNodeExpression
+{
+public:
+ KviKvsTreeNodeExpressionOperator(const QChar * pLocation);
+ ~KviKvsTreeNodeExpressionOperator();
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+};
+
+class KVIRC_API KviKvsTreeNodeExpressionUnaryOperator : public KviKvsTreeNodeExpressionOperator
+{
+public:
+ KviKvsTreeNodeExpressionUnaryOperator(const QChar * pLocation,KviKvsTreeNodeExpression * pData);
+ ~KviKvsTreeNodeExpressionUnaryOperator();
+protected:
+ KviKvsTreeNodeExpression * m_pData; // can't be null!
+ KviKvsNumber m_nData; // result of the number evaluation
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ bool evaluateOperand(KviKvsRunTimeContext * c);
+};
+
+class KVIRC_API KviKvsTreeNodeExpressionUnaryOperatorNegate : public KviKvsTreeNodeExpressionUnaryOperator
+{
+public:
+ KviKvsTreeNodeExpressionUnaryOperatorNegate(const QChar * pLocation,KviKvsTreeNodeExpression * pData);
+ ~KviKvsTreeNodeExpressionUnaryOperatorNegate();
+public:
+ virtual int precedence();
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pResult);
+};
+
+class KVIRC_API KviKvsTreeNodeExpressionUnaryOperatorBitwiseNot : public KviKvsTreeNodeExpressionUnaryOperator
+{
+public:
+ KviKvsTreeNodeExpressionUnaryOperatorBitwiseNot(const QChar * pLocation,KviKvsTreeNodeExpression * pData);
+ ~KviKvsTreeNodeExpressionUnaryOperatorBitwiseNot();
+public:
+ virtual int precedence();
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pResult);
+};
+
+class KVIRC_API KviKvsTreeNodeExpressionUnaryOperatorLogicalNot : public KviKvsTreeNodeExpressionUnaryOperator
+{
+public:
+ KviKvsTreeNodeExpressionUnaryOperatorLogicalNot(const QChar * pLocation,KviKvsTreeNodeExpression * pData);
+ ~KviKvsTreeNodeExpressionUnaryOperatorLogicalNot();
+public:
+ virtual int precedence();
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pResult);
+};
+
+class KVIRC_API KviKvsTreeNodeExpressionBinaryOperator : public KviKvsTreeNodeExpressionOperator
+{
+public:
+ KviKvsTreeNodeExpressionBinaryOperator(const QChar * pLocation);
+ ~KviKvsTreeNodeExpressionBinaryOperator();
+protected:
+ KviKvsTreeNodeExpression * m_pLeft; // can be zero only during parsing (and thus when deleting)
+ KviKvsTreeNodeExpression * m_pRight; // can be zero only during parsing (and thus when deleting)
+ KviKvsNumber m_nLeft; // buffer used to evaluate numeric operands
+ KviKvsNumber m_nRight; // buffer used to evaluate numeric operands
+public:
+ virtual KviKvsTreeNodeExpression * left();
+ virtual KviKvsTreeNodeExpression * right();
+ void setLeft(KviKvsTreeNodeExpression * pLeft);
+ void setRight(KviKvsTreeNodeExpression * pRight);
+ virtual int firstBinaryOperator();
+public:
+ void dumpOperands(const char * prefix);
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+protected:
+ bool evaluateOperands(KviKvsRunTimeContext * c);
+};
+
+#define DECLARE_BINARY_OPERATOR(__name) \
+ class KVIRC_API __name : public KviKvsTreeNodeExpressionBinaryOperator \
+ { \
+ public: \
+ __name(const QChar * pLocation); \
+ ~__name(); \
+ public: \
+ virtual void contextDescription(QString &szBuffer); \
+ virtual void dump(const char * prefix); \
+ virtual bool evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pResult); \
+ virtual int precedence(); \
+ }
+
+DECLARE_BINARY_OPERATOR(KviKvsTreeNodeExpressionBinaryOperatorSum);
+DECLARE_BINARY_OPERATOR(KviKvsTreeNodeExpressionBinaryOperatorMultiplication);
+DECLARE_BINARY_OPERATOR(KviKvsTreeNodeExpressionBinaryOperatorSubtraction);
+DECLARE_BINARY_OPERATOR(KviKvsTreeNodeExpressionBinaryOperatorDivision);
+DECLARE_BINARY_OPERATOR(KviKvsTreeNodeExpressionBinaryOperatorModulus);
+DECLARE_BINARY_OPERATOR(KviKvsTreeNodeExpressionBinaryOperatorBitwiseAnd);
+DECLARE_BINARY_OPERATOR(KviKvsTreeNodeExpressionBinaryOperatorBitwiseOr);
+DECLARE_BINARY_OPERATOR(KviKvsTreeNodeExpressionBinaryOperatorBitwiseXor);
+DECLARE_BINARY_OPERATOR(KviKvsTreeNodeExpressionBinaryOperatorShiftLeft);
+DECLARE_BINARY_OPERATOR(KviKvsTreeNodeExpressionBinaryOperatorShiftRight);
+DECLARE_BINARY_OPERATOR(KviKvsTreeNodeExpressionBinaryOperatorAnd);
+DECLARE_BINARY_OPERATOR(KviKvsTreeNodeExpressionBinaryOperatorOr);
+DECLARE_BINARY_OPERATOR(KviKvsTreeNodeExpressionBinaryOperatorXor);
+DECLARE_BINARY_OPERATOR(KviKvsTreeNodeExpressionBinaryOperatorGreaterThan);
+DECLARE_BINARY_OPERATOR(KviKvsTreeNodeExpressionBinaryOperatorLowerThan);
+DECLARE_BINARY_OPERATOR(KviKvsTreeNodeExpressionBinaryOperatorGreaterOrEqualTo);
+DECLARE_BINARY_OPERATOR(KviKvsTreeNodeExpressionBinaryOperatorLowerOrEqualTo);
+DECLARE_BINARY_OPERATOR(KviKvsTreeNodeExpressionBinaryOperatorEqualTo);
+DECLARE_BINARY_OPERATOR(KviKvsTreeNodeExpressionBinaryOperatorNotEqualTo);
+
+#endif //!_KVI_KVS_TREENODE_EXPRESSION_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_expressionreturn.cpp b/src/kvirc/kvs/kvi_kvs_treenode_expressionreturn.cpp
new file mode 100644
index 00000000..28c41b16
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_expressionreturn.cpp
@@ -0,0 +1,68 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_expressionreturn.cpp
+// Created on Fri 30 Jan 2004 01:27:09 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+#include "kvi_kvs_treenode_expressionreturn.h"
+#include "kvi_kvs_treenode_expression.h"
+#include "kvi_kvs_runtimecontext.h"
+#include "kvi_locale.h"
+
+KviKvsTreeNodeExpressionReturn::KviKvsTreeNodeExpressionReturn(const QChar * pLocation,KviKvsTreeNodeExpression * pExpression)
+: KviKvsTreeNodeInstruction(pLocation)
+{
+#ifdef COMPILE_NEW_KVS
+ m_pExpression = pExpression;
+ m_pExpression->setParent(this);
+#endif
+}
+
+KviKvsTreeNodeExpressionReturn::~KviKvsTreeNodeExpressionReturn()
+{
+#ifdef COMPILE_NEW_KVS
+ delete m_pExpression;
+#endif
+}
+
+
+void KviKvsTreeNodeExpressionReturn::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Expression Return Evaluation";
+#endif
+}
+
+void KviKvsTreeNodeExpressionReturn::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s ExpressionReturn",prefix);
+ QString tmp = prefix;
+ tmp += " ";
+ m_pExpression->dump(tmp.utf8().data());
+#endif
+}
+
+bool KviKvsTreeNodeExpressionReturn::execute(KviKvsRunTimeContext * c)
+{
+ return m_pExpression->evaluateReadOnly(c,c->returnValue());
+}
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_expressionreturn.h b/src/kvirc/kvs/kvi_kvs_treenode_expressionreturn.h
new file mode 100644
index 00000000..8622da0e
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_expressionreturn.h
@@ -0,0 +1,45 @@
+#ifndef _KVI_KVS_TREENODE_EXPRESSIONRETURN_H_
+#define _KVI_KVS_TREENODE_EXPRESSIONRETURN_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_expressionreturn.h
+// Created on Fri 30 Jan 2004 01:27:09 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_kvs_treenode_instruction.h"
+
+class KviKvsTreeNodeExpression;
+
+class KVIRC_API KviKvsTreeNodeExpressionReturn : public KviKvsTreeNodeInstruction
+{
+public:
+ KviKvsTreeNodeExpressionReturn(const QChar * pLocation,KviKvsTreeNodeExpression * pExpression);
+ ~KviKvsTreeNodeExpressionReturn();
+protected:
+ KviKvsTreeNodeExpression * m_pExpression;
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c);
+};
+
+#endif //!_KVI_KVS_TREENODE_EXPRESSIONRETURN_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_extendedscopevariable.cpp b/src/kvirc/kvs/kvi_kvs_treenode_extendedscopevariable.cpp
new file mode 100644
index 00000000..49906741
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_extendedscopevariable.cpp
@@ -0,0 +1,79 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_extendedscopevariable.cpp
+// Created on Thu 16 Oct 2003 22:41:20 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_extendedscopevariable.h"
+#include "kvi_kvs_runtimecontext.h"
+#include "kvi_locale.h"
+
+KviKvsTreeNodeExtendedScopeVariable::KviKvsTreeNodeExtendedScopeVariable(const QChar * pLocation,const QString &szIdentifier)
+: KviKvsTreeNodeVariable(pLocation,szIdentifier)
+{
+}
+
+KviKvsTreeNodeExtendedScopeVariable::~KviKvsTreeNodeExtendedScopeVariable()
+{
+}
+
+void KviKvsTreeNodeExtendedScopeVariable::contextDescription(QString &szBuffer)
+{
+ szBuffer = "Extended Scope Variable \"";
+ szBuffer += m_szIdentifier;
+ szBuffer += "\"";
+}
+
+void KviKvsTreeNodeExtendedScopeVariable::dump(const char * prefix)
+{
+ debug("%s ExtendedScopeVariable(%s)",prefix,m_szIdentifier.utf8().data());
+}
+
+bool KviKvsTreeNodeExtendedScopeVariable::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+ if(!c->extendedScopeVariables())
+ {
+ c->error(this,__tr2qs("There are no extended scope variables in this scope"));
+ return false;
+ }
+
+ KviKvsVariant * v = c->extendedScopeVariables()->find(m_szIdentifier);
+ if(v)
+ {
+ pBuffer->copyFrom(v);
+ } else {
+ pBuffer->setNothing();
+ }
+ return true;
+}
+
+KviKvsRWEvaluationResult * KviKvsTreeNodeExtendedScopeVariable::evaluateReadWrite(KviKvsRunTimeContext * c)
+{
+ if(!c->extendedScopeVariables())
+ {
+ c->error(this,__tr2qs("There are no extended scope variables in this scope"));
+ return false;
+ }
+
+ return new KviKvsHashElement(0,c->extendedScopeVariables()->get(m_szIdentifier),c->extendedScopeVariables(),m_szIdentifier);
+}
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_extendedscopevariable.h b/src/kvirc/kvs/kvi_kvs_treenode_extendedscopevariable.h
new file mode 100644
index 00000000..06fba6e2
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_extendedscopevariable.h
@@ -0,0 +1,45 @@
+#ifndef _KVI_KVS_TREENODE_EXTENDEDSCOPEVARIABLE_H_
+#define _KVI_KVS_TREENODE_EXTENDEDSCOPEVARIABLE_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_extendedscopevariable.h
+// Created on Thu 16 Oct 2003 22:41:20 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_treenode_variable.h"
+
+class KviKvsRunTimeContext;
+
+class KVIRC_API KviKvsTreeNodeExtendedScopeVariable : public KviKvsTreeNodeVariable
+{
+public:
+ KviKvsTreeNodeExtendedScopeVariable(const QChar * pLocation,const QString &szIdentifier);
+ ~KviKvsTreeNodeExtendedScopeVariable();
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pResult);
+ virtual KviKvsRWEvaluationResult * evaluateReadWrite(KviKvsRunTimeContext * c);
+};
+
+#endif //!_KVI_KVS_TREENODE_EXTENDEDSCOPEVARIABLE_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_functioncall.cpp b/src/kvirc/kvs/kvi_kvs_treenode_functioncall.cpp
new file mode 100644
index 00000000..1f8403e5
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_functioncall.cpp
@@ -0,0 +1,62 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_functioncall.cpp
+// Created on Tue 07 Oct 2003 03:14:44 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_functioncall.h"
+
+
+KviKvsTreeNodeFunctionCall::KviKvsTreeNodeFunctionCall(const QChar * pLocation,const QString &szFunctionName,KviKvsTreeNodeDataList * pParams)
+: KviKvsTreeNodeData(pLocation)
+{
+ m_szFunctionName = szFunctionName;
+ m_pParams = pParams;
+ m_pParams->setParent(this);
+}
+
+KviKvsTreeNodeFunctionCall::~KviKvsTreeNodeFunctionCall()
+{
+ delete m_pParams;
+}
+
+void KviKvsTreeNodeFunctionCall::contextDescription(QString &szBuffer)
+{
+ szBuffer = "Function Call";
+}
+
+void KviKvsTreeNodeFunctionCall::dump(const char * prefix)
+{
+ debug("%s FunctionCall",prefix);
+}
+
+bool KviKvsTreeNodeFunctionCall::canEvaluateToObjectReference()
+{
+ return true;
+}
+
+bool KviKvsTreeNodeFunctionCall::isFunctionCall()
+{
+ return true;
+}
+
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_functioncall.h b/src/kvirc/kvs/kvi_kvs_treenode_functioncall.h
new file mode 100644
index 00000000..88d8250b
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_functioncall.h
@@ -0,0 +1,47 @@
+#ifndef _KVI_KVS_TREENODE_FUNCTIONCALL_H_
+#define _KVI_KVS_TREENODE_FUNCTIONCALL_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_functioncall.h
+// Created on Tue 07 Oct 2003 03:14:44 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_kvs_treenode_data.h"
+#include "kvi_kvs_treenode_datalist.h"
+
+class KVIRC_API KviKvsTreeNodeFunctionCall : public KviKvsTreeNodeData
+{
+public:
+ KviKvsTreeNodeFunctionCall(const QChar * pLocation,const QString &szFunctionName,KviKvsTreeNodeDataList * pParams);
+ ~KviKvsTreeNodeFunctionCall();
+protected:
+ QString m_szFunctionName;
+ KviKvsTreeNodeDataList * m_pParams; // never 0
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool canEvaluateToObjectReference(); // yes
+ virtual bool isFunctionCall(); // yes
+};
+
+
+#endif //!_KVI_KVS_TREENODE_FUNCTIONCALL_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_globalvariable.cpp b/src/kvirc/kvs/kvi_kvs_treenode_globalvariable.cpp
new file mode 100644
index 00000000..ea6bd031
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_globalvariable.cpp
@@ -0,0 +1,63 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_globalvariable.cpp
+// Created on Thu 16 Oct 2003 22:45:01 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_globalvariable.h"
+#include "kvi_kvs_runtimecontext.h"
+
+KviKvsTreeNodeGlobalVariable::KviKvsTreeNodeGlobalVariable(const QChar * pLocation,const QString &szIdentifier)
+: KviKvsTreeNodeVariable(pLocation,szIdentifier)
+{
+}
+
+KviKvsTreeNodeGlobalVariable::~KviKvsTreeNodeGlobalVariable()
+{
+}
+
+void KviKvsTreeNodeGlobalVariable::contextDescription(QString &szBuffer)
+{
+ szBuffer = "Global Variable \"";
+ szBuffer += m_szIdentifier;
+ szBuffer += "\"";
+}
+
+void KviKvsTreeNodeGlobalVariable::dump(const char * prefix)
+{
+ debug("%s GlobalVariable(%s)",prefix,m_szIdentifier.utf8().data());
+}
+
+
+bool KviKvsTreeNodeGlobalVariable::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+ KviKvsVariant * v = c->globalVariables()->find(m_szIdentifier);
+ if(v)pBuffer->copyFrom(v);
+ else pBuffer->setNothing();
+ return true;
+}
+
+KviKvsRWEvaluationResult * KviKvsTreeNodeGlobalVariable::evaluateReadWrite(KviKvsRunTimeContext * c)
+{
+ return new KviKvsHashElement(0,c->globalVariables()->get(m_szIdentifier),c->globalVariables(),m_szIdentifier);
+}
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_globalvariable.h b/src/kvirc/kvs/kvi_kvs_treenode_globalvariable.h
new file mode 100644
index 00000000..9f6bcf0a
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_globalvariable.h
@@ -0,0 +1,45 @@
+#ifndef _KVI_KVS_TREENODE_GLOBALVARIABLE_H_
+#define _KVI_KVS_TREENODE_GLOBALVARIABLE_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_globalvariable.h
+// Created on Thu 16 Oct 2003 22:45:01 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_treenode_variable.h"
+
+class KviKvsRunTimeContext;
+
+class KVIRC_API KviKvsTreeNodeGlobalVariable : public KviKvsTreeNodeVariable
+{
+public:
+ KviKvsTreeNodeGlobalVariable(const QChar * pLocation,const QString &szIdentifier);
+ ~KviKvsTreeNodeGlobalVariable();
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pResult);
+ virtual KviKvsRWEvaluationResult * evaluateReadWrite(KviKvsRunTimeContext * c);
+};
+
+#endif //!_KVI_KVS_TREENODE_GLOBALVARIABLE_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_hashcount.cpp b/src/kvirc/kvs/kvi_kvs_treenode_hashcount.cpp
new file mode 100644
index 00000000..3ecfaf52
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_hashcount.cpp
@@ -0,0 +1,88 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_hashcount.cpp
+// Created on Tue 07 Oct 2003 03:05:30 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_hashcount.h"
+#include "kvi_kvs_variant.h"
+#include "kvi_kvs_runtimecontext.h"
+#include "kvi_kvs_object.h"
+#include "kvi_locale.h"
+
+
+KviKvsTreeNodeHashCount::KviKvsTreeNodeHashCount(const QChar * pLocation,KviKvsTreeNodeData * pSource)
+: KviKvsTreeNodeIndirectData(pLocation,pSource)
+{
+}
+
+KviKvsTreeNodeHashCount::~KviKvsTreeNodeHashCount()
+{
+}
+
+void KviKvsTreeNodeHashCount::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Hash Count Operator";
+#endif
+}
+
+void KviKvsTreeNodeHashCount::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s HashCount",prefix);
+#endif
+}
+
+bool KviKvsTreeNodeHashCount::evaluateReadOnlyInObjectScope(KviKvsObject *o,KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ KviKvsVariant val;
+ if(o)
+ {
+ if(!m_pSource->evaluateReadOnlyInObjectScope(o,c,&val))return false;
+ } else {
+ if(!m_pSource->evaluateReadOnly(c,&val))return false;
+ }
+
+ if(!val.isHash())
+ {
+ if(!val.isNothing())
+ {
+ QString szType;
+ val.getTypeName(szType);
+ c->warning(this,__tr2qs("The argument of the hash count '#' operator didn't evaluate to a hash: automatic conversion from type '%Q' supplied"),&szType);
+ }
+ pBuffer->setInteger(0);
+ return true;
+ }
+
+ pBuffer->setInteger(val.hash()->size());
+#endif
+ return true;
+}
+bool KviKvsTreeNodeHashCount::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+ return evaluateReadOnlyInObjectScope(0,c,pBuffer);
+}
+
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_hashcount.h b/src/kvirc/kvs/kvi_kvs_treenode_hashcount.h
new file mode 100644
index 00000000..b59cf371
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_hashcount.h
@@ -0,0 +1,47 @@
+#ifndef _KVI_KVS_TREENODE_HASHCOUNT_H_
+#define _KVI_KVS_TREENODE_HASHCOUNT_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_hashcount.h
+// Created on Tue 07 Oct 2003 03:05:30 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_treenode_indirectdata.h"
+
+class KviKvsRunTimeContext;
+class KviKvsVariant;
+class KviKvsObject;
+
+class KVIRC_API KviKvsTreeNodeHashCount : public KviKvsTreeNodeIndirectData
+{
+public:
+ KviKvsTreeNodeHashCount(const QChar * pLocation,KviKvsTreeNodeData * pSource);
+ ~KviKvsTreeNodeHashCount();
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer);
+ virtual bool evaluateReadOnlyInObjectScope(KviKvsObject *o,KviKvsRunTimeContext * c,KviKvsVariant * pBuffer);
+};
+
+#endif //!_KVI_KVS_TREENODE_HASHCOUNT_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_hashelement.cpp b/src/kvirc/kvs/kvi_kvs_treenode_hashelement.cpp
new file mode 100644
index 00000000..645478f6
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_hashelement.cpp
@@ -0,0 +1,164 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_hashelement.cpp
+// Created on Tue 07 Oct 2003 03:04:18 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_hashelement.h"
+#include "kvi_kvs_runtimecontext.h"
+#include "kvi_locale.h"
+#include "kvi_kvs_hash.h"
+#include "kvi_kvs_object.h"
+
+KviKvsTreeNodeHashElement::KviKvsTreeNodeHashElement(const QChar * pLocation,KviKvsTreeNodeData * pSource,KviKvsTreeNodeData * pKey)
+: KviKvsTreeNodeArrayOrHashElement(pLocation,pSource)
+{
+#ifdef COMPILE_NEW_KVS
+ m_pKey = pKey;
+ m_pKey->setParent(this);
+#endif
+}
+
+
+KviKvsTreeNodeHashElement::~KviKvsTreeNodeHashElement()
+{
+#ifdef COMPILE_NEW_KVS
+ delete m_pKey;
+#endif
+}
+
+void KviKvsTreeNodeHashElement::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Hash Element Evaluation";
+#endif
+}
+
+void KviKvsTreeNodeHashElement::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s HashElement",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pSource->dump(tmp.utf8().data());
+ m_pKey->dump(tmp.utf8().data());
+#endif
+}
+
+
+bool KviKvsTreeNodeHashElement::evaluateReadOnlyInObjectScope(KviKvsObject *o,KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ KviKvsVariant key;
+ if(!m_pKey->evaluateReadOnly(c,&key))return false;
+
+ QString szKey;
+ key.asString(szKey);
+
+ if(szKey.isEmpty())
+ {
+ c->warning(this,__tr2qs("Hash key evaluated to empty string: fix the script"));
+ pBuffer->setNothing();
+ return true;
+ }
+
+ KviKvsVariant val;
+ if(o)
+ {
+ if(!m_pSource->evaluateReadOnlyInObjectScope(o,c,&val))return false;
+ } else {
+ if(!m_pSource->evaluateReadOnly(c,&val))return false;
+ }
+
+ if(!val.isHash())
+ {
+ if(!val.isNothing())
+ {
+ QString szType;
+ val.getTypeName(szType);
+ c->warning(this,__tr2qs("The argument of the {} subscript didn't evaluate to a hash: automatic conversion from type '%Q' supplied"),&szType);
+ }
+ pBuffer->setNothing();
+ return true;
+ }
+
+ KviKvsVariant * v = val.hash()->find(szKey);
+ if(!v)
+ {
+ pBuffer->setNothing();
+ return true;
+ }
+
+ pBuffer->copyFrom(v);
+#endif
+ return true;
+}
+
+KviKvsRWEvaluationResult * KviKvsTreeNodeHashElement::evaluateReadWriteInObjectScope(KviKvsObject *o,KviKvsRunTimeContext * c)
+{
+#ifdef COMPILE_NEW_KVS
+ KviKvsVariant key;
+ if(!m_pKey->evaluateReadOnly(c,&key))return 0;
+
+ QString szKey;
+ key.asString(szKey);
+
+ if(szKey.isEmpty())
+ {
+ c->warning(this,__tr2qs("Hash key evaluated to empty string: fix the script"));
+ }
+
+ KviKvsRWEvaluationResult * result;
+ if(o)result = m_pSource->evaluateReadWriteInObjectScope(o,c);
+ else result = m_pSource->evaluateReadWrite(c);
+ if(!result)return 0;
+
+ if(!result->result()->isHash())
+ {
+ // convert to hash in some way
+//#warning "Supply a *real* conversion from other types to array ?"
+ if(!result->result()->isNothing())
+ {
+ QString szType;
+ result->result()->getTypeName(szType);
+ c->warning(this,__tr2qs("The argument of the {} subscript didn't evaluate to a hash automatic conversion from %Q supplied"),&szType);
+ }
+ result->result()->setHash(new KviKvsHash());
+ }
+
+ return new KviKvsHashElement(result,result->result()->hash()->get(szKey),result->result()->hash(),szKey);
+#else
+ return 0;
+#endif
+}
+
+
+bool KviKvsTreeNodeHashElement::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+ return evaluateReadOnlyInObjectScope(0,c,pBuffer);
+}
+
+KviKvsRWEvaluationResult * KviKvsTreeNodeHashElement::evaluateReadWrite(KviKvsRunTimeContext * c)
+{
+ return evaluateReadWriteInObjectScope(0,c);
+}
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_hashelement.h b/src/kvirc/kvs/kvi_kvs_treenode_hashelement.h
new file mode 100644
index 00000000..5b46a7ec
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_hashelement.h
@@ -0,0 +1,52 @@
+#ifndef _KVI_KVS_TREENODE_HASHELEMENT_H_
+#define _KVI_KVS_TREENODE_HASHELEMENT_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_hashelement.h
+// Created on Tue 07 Oct 2003 03:04:18 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_treenode_data.h"
+#include "kvi_kvs_treenode_arrayorhashelement.h"
+
+class KviKvsRunTimeContext;
+class KviKvsObject;
+
+class KVIRC_API KviKvsTreeNodeHashElement : public KviKvsTreeNodeArrayOrHashElement
+{
+public:
+ KviKvsTreeNodeHashElement(const QChar * pLocation,KviKvsTreeNodeData * pSource,KviKvsTreeNodeData * pIndex);
+ ~KviKvsTreeNodeHashElement();
+protected:
+ KviKvsTreeNodeData * m_pKey; // can't be null
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer);
+ virtual KviKvsRWEvaluationResult * evaluateReadWrite(KviKvsRunTimeContext * c);
+ virtual bool evaluateReadOnlyInObjectScope(KviKvsObject *o,KviKvsRunTimeContext * c,KviKvsVariant * pBuffer);
+ virtual KviKvsRWEvaluationResult * evaluateReadWriteInObjectScope(KviKvsObject *o,KviKvsRunTimeContext * c);
+};
+
+
+#endif //!_KVI_KVS_TREENODE_HASHELEMENT_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_hashreferenceassert.cpp b/src/kvirc/kvs/kvi_kvs_treenode_hashreferenceassert.cpp
new file mode 100644
index 00000000..799cc1e5
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_hashreferenceassert.cpp
@@ -0,0 +1,107 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_hashreferenceassert.cpp
+// Created on Thu 16 Oct 2003 23:43:06 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_hashreferenceassert.h"
+#include "kvi_kvs_rwevaluationresult.h"
+#include "kvi_kvs_runtimecontext.h"
+#include "kvi_kvs_variant.h"
+#include "kvi_locale.h"
+
+KviKvsTreeNodeHashReferenceAssert::KviKvsTreeNodeHashReferenceAssert(const QChar * pLocation,KviKvsTreeNodeData * pSource)
+: KviKvsTreeNodeIndirectData(pLocation,pSource)
+{
+}
+
+KviKvsTreeNodeHashReferenceAssert::~KviKvsTreeNodeHashReferenceAssert()
+{
+}
+
+bool KviKvsTreeNodeHashReferenceAssert::isReadOnly()
+{
+ return m_pSource->isReadOnly();
+}
+
+void KviKvsTreeNodeHashReferenceAssert::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Hash Reference Assert";
+#endif
+}
+
+void KviKvsTreeNodeHashReferenceAssert::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s HashReferenceAssert",prefix);
+#endif
+}
+
+bool KviKvsTreeNodeHashReferenceAssert::evaluateReadOnlyInObjectScope(KviKvsObject *o,KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ if(o)
+ {
+ if(!m_pSource->evaluateReadOnlyInObjectScope(o,c,pBuffer))return false;
+ } else {
+ if(!m_pSource->evaluateReadOnly(c,pBuffer))return false;
+ }
+
+ if(!pBuffer->isHash())
+ {
+ if(!pBuffer->isNothing())
+ {
+ QString szType;
+ pBuffer->getTypeName(szType);
+ c->error(this,__tr2qs("Hash reference assert failed: the variable evaluated to type '%Q'"),&szType);
+ return false;
+ }
+ }
+#endif
+ return true;
+}
+
+KviKvsRWEvaluationResult * KviKvsTreeNodeHashReferenceAssert::evaluateReadWriteInObjectScope(KviKvsObject *o,KviKvsRunTimeContext * c)
+{
+#ifdef COMPILE_NEW_KVS
+ KviKvsRWEvaluationResult * r;
+ if(o)r = m_pSource->evaluateReadWriteInObjectScope(o,c);
+ else r = m_pSource->evaluateReadWrite(c);
+ if(!r)return false;
+
+ return r;
+#else
+ return 0;
+#endif
+}
+
+bool KviKvsTreeNodeHashReferenceAssert::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+ return evaluateReadOnlyInObjectScope(0,c,pBuffer);
+}
+
+KviKvsRWEvaluationResult * KviKvsTreeNodeHashReferenceAssert::evaluateReadWrite(KviKvsRunTimeContext * c)
+{
+ return evaluateReadWriteInObjectScope(0,c);
+}
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_hashreferenceassert.h b/src/kvirc/kvs/kvi_kvs_treenode_hashreferenceassert.h
new file mode 100644
index 00000000..43cb57c3
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_hashreferenceassert.h
@@ -0,0 +1,53 @@
+#ifndef _KVI_KVS_TREENODE_HASHREFERENCEASSERT_H_
+#define _KVI_KVS_TREENODE_HASHREFERENCEASSERT_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_hashreferenceassert.h
+// Created on Thu 16 Oct 2003 23:43:06 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_treenode_indirectdata.h"
+
+class KviKvsRunTimeContext;
+class KviKvsVariant;
+class KviKvsRWEvaluationResult;
+class KviKvsObject;
+
+class KVIRC_API KviKvsTreeNodeHashReferenceAssert : public KviKvsTreeNodeIndirectData
+{
+public:
+ KviKvsTreeNodeHashReferenceAssert(const QChar * pLocation,KviKvsTreeNodeData * pSource);
+ ~KviKvsTreeNodeHashReferenceAssert();
+protected:
+
+public:
+ virtual bool isReadOnly();
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer);
+ virtual KviKvsRWEvaluationResult * evaluateReadWrite(KviKvsRunTimeContext * c);
+ virtual bool evaluateReadOnlyInObjectScope(KviKvsObject *o,KviKvsRunTimeContext * c,KviKvsVariant * pBuffer);
+ virtual KviKvsRWEvaluationResult * evaluateReadWriteInObjectScope(KviKvsObject *o,KviKvsRunTimeContext * c);
+};
+
+#endif //!_KVI_KVS_TREENODE_HASHREFERENCEASSERT_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_indirectdata.cpp b/src/kvirc/kvs/kvi_kvs_treenode_indirectdata.cpp
new file mode 100644
index 00000000..285c9d91
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_indirectdata.cpp
@@ -0,0 +1,46 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_indirectdata.cpp
+// Created on Thu 16 Oct 2003 22:49:46 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_indirectdata.h"
+
+KviKvsTreeNodeIndirectData::KviKvsTreeNodeIndirectData(const QChar * pLocation,KviKvsTreeNodeData * pSource)
+: KviKvsTreeNodeData(pLocation)
+{
+ m_pSource = pSource;
+ m_pSource->setParent(this);
+}
+
+KviKvsTreeNodeIndirectData::~KviKvsTreeNodeIndirectData()
+{
+ delete m_pSource;
+}
+
+
+bool KviKvsTreeNodeIndirectData::canEvaluateInObjectScope()
+{
+ return m_pSource->canEvaluateInObjectScope();
+}
+
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_indirectdata.h b/src/kvirc/kvs/kvi_kvs_treenode_indirectdata.h
new file mode 100644
index 00000000..31a9410c
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_indirectdata.h
@@ -0,0 +1,42 @@
+#ifndef _KVI_KVS_TREENODE_INDIRECTDATA_H_
+#define _KVI_KVS_TREENODE_INDIRECTDATA_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_indirectdata.h
+// Created on Thu 16 Oct 2003 22:49:46 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_treenode_data.h"
+
+class KVIRC_API KviKvsTreeNodeIndirectData : public KviKvsTreeNodeData
+{
+public:
+ KviKvsTreeNodeIndirectData(const QChar * pLocation,KviKvsTreeNodeData * pSource);
+ ~KviKvsTreeNodeIndirectData();
+protected:
+ KviKvsTreeNodeData * m_pSource; // can't be null!
+public:
+ virtual bool canEvaluateInObjectScope();
+};
+
+#endif //!_KVI_KVS_TREENODE_INDIRECTDATA_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_instruction.cpp b/src/kvirc/kvs/kvi_kvs_treenode_instruction.cpp
new file mode 100644
index 00000000..37cb3d04
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_instruction.cpp
@@ -0,0 +1,43 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_instruction.cpp
+// Creation date : Mon 06 Sep 2003 03.47 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_instruction.h"
+
+void KviKvsTreeNodeInstruction::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Instruction";
+#endif
+}
+
+void KviKvsTreeNodeInstruction::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s Instruction",prefix);
+#endif
+}
+
+
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_instruction.h b/src/kvirc/kvs/kvi_kvs_treenode_instruction.h
new file mode 100644
index 00000000..1e0c09c3
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_instruction.h
@@ -0,0 +1,54 @@
+#ifndef _KVI_KVS_TREENODE_INSTRUCTION_H_
+#define _KVI_KVS_TREENODE_INSTRUCTION_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode.h
+// Creation date : Mon 06 Oct 2003 03.46 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_qstring.h"
+#include "kvi_kvs_treenode_base.h"
+
+class KviKvsRunTimeContext;
+
+
+class KVIRC_API KviKvsTreeNodeInstruction : public KviKvsTreeNode
+{
+public:
+ KviKvsTreeNodeInstruction(const QChar * pLocation)
+ : KviKvsTreeNode(pLocation){};
+ ~KviKvsTreeNodeInstruction(){};
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+
+ // execute() is the main entry point to the tree visit
+ // execute() returns false when the tree visiting has
+ // to be stopped and returns true when it has been
+ // succesfully completed. A false return value may
+ // signal an error but is also used by break, halt, return
+ // and similar. The error condition is signaled by
+ // KviKvsRunTimeContext::error().
+ virtual bool execute(KviKvsRunTimeContext * c) = 0;
+};
+
+
+#endif //!_KVI_KVS_TREENODE_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_instructionblock.cpp b/src/kvirc/kvs/kvi_kvs_treenode_instructionblock.cpp
new file mode 100644
index 00000000..75afd456
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_instructionblock.cpp
@@ -0,0 +1,88 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_instructionblock.cpp
+// Created on Thu 09 Oct 2003 01:44:31 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+
+#include "kvi_kvs_treenode_instructionblock.h"
+#include "kvi_kvs_runtimecontext.h"
+
+KviKvsTreeNodeInstructionBlock::KviKvsTreeNodeInstructionBlock(const QChar * pLocation)
+: KviKvsTreeNodeInstruction(pLocation)
+{
+ m_pInstructionList = new KviPointerList<KviKvsTreeNodeInstruction>;
+ m_pInstructionList->setAutoDelete(true);
+}
+
+KviKvsTreeNodeInstructionBlock::~KviKvsTreeNodeInstructionBlock()
+{
+ delete m_pInstructionList;
+}
+
+void KviKvsTreeNodeInstructionBlock::contextDescription(QString &szBuffer)
+{
+ szBuffer = "Instruction Block";
+}
+
+void KviKvsTreeNodeInstructionBlock::dump(const char * prefix)
+{
+ debug("%s InstructionBlock",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ for(KviKvsTreeNodeInstruction * i = m_pInstructionList->first();i;i = m_pInstructionList->next())
+ {
+ i->dump(tmp.utf8().data());
+ }
+}
+
+KviKvsTreeNodeInstruction * KviKvsTreeNodeInstructionBlock::releaseFirst()
+{
+ m_pInstructionList->setAutoDelete(false);
+ KviKvsTreeNodeInstruction * i = m_pInstructionList->first();
+ if(i)
+ {
+ i->setParent(0);
+ m_pInstructionList->removeFirst();
+ }
+ m_pInstructionList->setAutoDelete(true);
+ return i;
+}
+
+void KviKvsTreeNodeInstructionBlock::addInstruction(KviKvsTreeNodeInstruction * i)
+{
+ m_pInstructionList->append(i);
+ i->setParent(this);
+}
+
+bool KviKvsTreeNodeInstructionBlock::execute(KviKvsRunTimeContext * c)
+{
+ // to accomodate recursion we need to use an iterator here
+ KviPointerListIterator<KviKvsTreeNodeInstruction> it(*m_pInstructionList);
+ while(KviKvsTreeNodeInstruction * i = it.current())
+ {
+ if(!i->execute(c))return false;
+ ++it;
+ }
+ return true;
+}
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_instructionblock.h b/src/kvirc/kvs/kvi_kvs_treenode_instructionblock.h
new file mode 100644
index 00000000..f4aa32f4
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_instructionblock.h
@@ -0,0 +1,55 @@
+#ifndef _KVI_KVS_TREENODE_INSTRUCTIONBLOCK_H_
+#define _KVI_KVS_TREENODE_INSTRUCTIONBLOCK_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_instructionblock.h
+// Created on Thu 09 Oct 2003 01:44:31 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_pointerlist.h"
+
+#include "kvi_kvs_treenode_instruction.h"
+
+class KviKvsRunTimeContext;
+
+
+class KVIRC_API KviKvsTreeNodeInstructionBlock : public KviKvsTreeNodeInstruction
+{
+public:
+ KviKvsTreeNodeInstructionBlock(const QChar * pLocation);
+ ~KviKvsTreeNodeInstructionBlock();
+protected:
+ KviPointerList<KviKvsTreeNodeInstruction> * m_pInstructionList;
+public:
+ unsigned int instructionCount(){ return m_pInstructionList->count(); };
+ void addInstruction(KviKvsTreeNodeInstruction * i);
+ KviKvsTreeNodeInstruction * releaseFirst();
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+
+ virtual bool execute(KviKvsRunTimeContext * c);
+
+};
+
+
+#endif //!_KVI_KVS_TREENODE_INSTRUCTIONBLOCK_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_localvariable.cpp b/src/kvirc/kvs/kvi_kvs_treenode_localvariable.cpp
new file mode 100644
index 00000000..95221ca9
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_localvariable.cpp
@@ -0,0 +1,76 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_localvariable.cpp
+// Created on Thu 16 Oct 2003 22:41:20 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_localvariable.h"
+#include "kvi_kvs_runtimecontext.h"
+
+KviKvsTreeNodeLocalVariable::KviKvsTreeNodeLocalVariable(const QChar * pLocation,const QString &szIdentifier)
+: KviKvsTreeNodeVariable(pLocation,szIdentifier)
+{
+}
+
+KviKvsTreeNodeLocalVariable::~KviKvsTreeNodeLocalVariable()
+{
+}
+
+void KviKvsTreeNodeLocalVariable::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Local Variable \"";
+ szBuffer += m_szIdentifier;
+ szBuffer += "\"";
+#endif
+}
+
+void KviKvsTreeNodeLocalVariable::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s LocalVariable(%s)",prefix,m_szIdentifier.utf8().data());
+#endif
+}
+
+bool KviKvsTreeNodeLocalVariable::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ KviKvsVariant * v = c->localVariables()->find(m_szIdentifier);
+ if(v)
+ {
+ pBuffer->copyFrom(v);
+ } else {
+ pBuffer->setNothing();
+ }
+#endif
+ return true;
+}
+
+KviKvsRWEvaluationResult * KviKvsTreeNodeLocalVariable::evaluateReadWrite(KviKvsRunTimeContext * c)
+{
+#ifdef COMPILE_NEW_KVS
+ return new KviKvsHashElement(0,c->localVariables()->get(m_szIdentifier),c->localVariables(),m_szIdentifier);
+#else
+ return 0;
+#endif
+}
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_localvariable.h b/src/kvirc/kvs/kvi_kvs_treenode_localvariable.h
new file mode 100644
index 00000000..9f6998df
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_localvariable.h
@@ -0,0 +1,45 @@
+#ifndef _KVI_KVS_TREENODE_LOCALVARIABLE_H_
+#define _KVI_KVS_TREENODE_LOCALVARIABLE_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_localvariable.h
+// Created on Thu 16 Oct 2003 22:41:20 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_treenode_variable.h"
+
+class KviKvsRunTimeContext;
+
+class KVIRC_API KviKvsTreeNodeLocalVariable : public KviKvsTreeNodeVariable
+{
+public:
+ KviKvsTreeNodeLocalVariable(const QChar * pLocation,const QString &szIdentifier);
+ ~KviKvsTreeNodeLocalVariable();
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pResult);
+ virtual KviKvsRWEvaluationResult * evaluateReadWrite(KviKvsRunTimeContext * c);
+};
+
+#endif //!_KVI_KVS_TREENODE_LOCALVARIABLE_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_modulecallbackcommand.cpp b/src/kvirc/kvs/kvi_kvs_treenode_modulecallbackcommand.cpp
new file mode 100644
index 00000000..bc6b9c5b
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_modulecallbackcommand.cpp
@@ -0,0 +1,97 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_modulecallbackcommand.cpp
+// Created on Thu 09 Oct 2003 02:09:10 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_modulecallbackcommand.h"
+#include "kvi_kvs_treenode_datalist.h"
+#include "kvi_kvs_treenode_switchlist.h"
+
+#include "kvi_modulemanager.h"
+#include "kvi_locale.h"
+#include "kvi_kvs_moduleinterface.h"
+#include "kvi_kvs_runtimecontext.h"
+
+KviKvsTreeNodeModuleCallbackCommand::KviKvsTreeNodeModuleCallbackCommand(const QChar * pLocation,const QString &szModuleName,const QString &szCmdName,KviKvsTreeNodeDataList * params,KviKvsScript * pCallback)
+: KviKvsTreeNodeCallbackCommand(pLocation,szCmdName,params,pCallback)
+{
+ m_szModuleName = szModuleName;
+}
+
+
+KviKvsTreeNodeModuleCallbackCommand::~KviKvsTreeNodeModuleCallbackCommand()
+{
+}
+
+void KviKvsTreeNodeModuleCallbackCommand::contextDescription(QString &szBuffer)
+{
+ szBuffer = "Module Callback Command \"";
+ szBuffer += m_szModuleName;
+ szBuffer += ".";
+ szBuffer += m_szCmdName;
+ szBuffer += "\"";
+}
+
+void KviKvsTreeNodeModuleCallbackCommand::dump(const char * prefix)
+{
+ debug("%s ModuleCallbackCommand(%s.%s)",prefix,m_szModuleName.utf8().data(),m_szCmdName.utf8().data());
+ dumpSwitchList(prefix);
+ dumpParameterList(prefix);
+ dumpCallback(prefix);
+}
+
+bool KviKvsTreeNodeModuleCallbackCommand::execute(KviKvsRunTimeContext * c)
+{
+//#warning "FIXME: module names should be UNICODE!"
+ KviModule * m = g_pModuleManager->getModule(m_szModuleName.utf8().data());
+ if(!m)
+ {
+ QString szErr = g_pModuleManager->lastError().ptr(); // <-- fixme!
+ c->error(this,__tr2qs("Module command call failed: can't load the module '%Q': %Q"),&m_szModuleName,&szErr);
+ return false;
+ }
+
+ KviKvsModuleCallbackCommandExecRoutine * proc = m->kvsFindCallbackCommand(m_szCmdName);
+ if(!proc)
+ {
+ c->error(this,__tr2qs("Module command call failed: the module '%Q' doesn't export a callback command named '%Q'"),&m_szModuleName,&m_szCmdName);
+ return false;
+ }
+
+ KviKvsVariantList l;
+ l.setAutoDelete(true);
+ if(!(m_pParams->evaluate(c,&l)))return false;
+
+ KviKvsSwitchList swl;
+ if(m_pSwitches)
+ {
+ if(!(m_pSwitches->evaluate(c,&swl)))return false;
+ }
+
+ c->setDefaultReportLocation(this);
+
+ KviKvsModuleCallbackCommandCall call(m,c,&l,&swl,m_pCallback,m_pParams);
+
+ return (*proc)(&call);
+}
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_modulecallbackcommand.h b/src/kvirc/kvs/kvi_kvs_treenode_modulecallbackcommand.h
new file mode 100644
index 00000000..cc484f96
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_modulecallbackcommand.h
@@ -0,0 +1,50 @@
+#ifndef _KVI_KVS_TREENODE_MODULECALLBACKCOMMAND_H_
+#define _KVI_KVS_TREENODE_MODULECALLBACKCOMMAND_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_modulecallbackcommand.h
+// Created on Thu 09 Oct 2003 02:09:10 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_treenode_callbackcommand.h"
+
+class KviKvsTreeNodeDataList;
+class KviKvsScript;
+class KviKvsRunTimeContext;
+
+
+class KVIRC_API KviKvsTreeNodeModuleCallbackCommand : public KviKvsTreeNodeCallbackCommand
+{
+public:
+ KviKvsTreeNodeModuleCallbackCommand(const QChar * pLocation,const QString &szModuleName,const QString &szCmdName,KviKvsTreeNodeDataList * params,KviKvsScript * pCallback);
+ ~KviKvsTreeNodeModuleCallbackCommand();
+protected:
+ QString m_szModuleName;
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ bool execute(KviKvsRunTimeContext* c);
+};
+
+
+#endif //!_KVI_KVS_TREENODE_MODULECALLBACKCOMMAND_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_modulefunctioncall.cpp b/src/kvirc/kvs/kvi_kvs_treenode_modulefunctioncall.cpp
new file mode 100644
index 00000000..e7f0a466
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_modulefunctioncall.cpp
@@ -0,0 +1,90 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_modulefunctioncall.cpp
+// Created on Tue 07 Oct 2003 03:19:28 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_modulefunctioncall.h"
+#include "kvi_kvs_treenode_datalist.h"
+
+#include "kvi_modulemanager.h"
+#include "kvi_locale.h"
+#include "kvi_kvs_moduleinterface.h"
+#include "kvi_kvs_runtimecontext.h"
+
+
+KviKvsTreeNodeModuleFunctionCall::KviKvsTreeNodeModuleFunctionCall(const QChar * pLocation,const QString &szModuleName,const QString &szFncName,KviKvsTreeNodeDataList * pParams)
+: KviKvsTreeNodeFunctionCall(pLocation,szFncName,pParams)
+{
+ m_szModuleName = szModuleName;
+}
+
+KviKvsTreeNodeModuleFunctionCall::~KviKvsTreeNodeModuleFunctionCall()
+{
+}
+
+void KviKvsTreeNodeModuleFunctionCall::contextDescription(QString &szBuffer)
+{
+ szBuffer = "Module Function Call \"";
+ szBuffer += m_szModuleName;
+ szBuffer += ".";
+ szBuffer += m_szFunctionName;
+ szBuffer += "\"";
+}
+
+void KviKvsTreeNodeModuleFunctionCall::dump(const char * prefix)
+{
+ debug("%s ModuleFunctionCall(%s.%s)",prefix,m_szModuleName.utf8().data(),m_szFunctionName.utf8().data());
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pParams->dump(tmp.utf8().data());
+}
+
+bool KviKvsTreeNodeModuleFunctionCall::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+//#warning "FIXME: module names should be UNICODE!"
+ KviModule * m = g_pModuleManager->getModule(m_szModuleName.utf8().data());
+ if(!m)
+ {
+ QString szErr = g_pModuleManager->lastError().ptr(); // <-- fixme!
+ c->error(this,__tr2qs("Module function call failed: can't load the module '%Q': %Q"),&m_szModuleName,&szErr);
+ return false;
+ }
+
+ KviKvsModuleFunctionExecRoutine * proc = m->kvsFindFunction(m_szFunctionName);
+ if(!proc)
+ {
+ c->error(this,__tr2qs("Module function call failed: the module '%Q' doesn't export a function named '%Q'"),&m_szModuleName,&m_szFunctionName);
+ return false;
+ }
+
+ KviKvsVariantList l;
+ if(!m_pParams->evaluate(c,&l))return false;
+
+ pBuffer->setNothing();
+ c->setDefaultReportLocation(this);
+ KviKvsModuleFunctionCall call(m,c,&l,pBuffer);
+
+ return (*proc)(&call);
+}
+
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_modulefunctioncall.h b/src/kvirc/kvs/kvi_kvs_treenode_modulefunctioncall.h
new file mode 100644
index 00000000..9581d035
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_modulefunctioncall.h
@@ -0,0 +1,48 @@
+#ifndef _KVI_KVS_TREENODE_MODULEFUNCTIONCALL_H_
+#define _KVI_KVS_TREENODE_MODULEFUNCTIONCALL_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_modulefunctioncall.h
+// Created on Tue 07 Oct 2003 03:19:28 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_treenode_datalist.h"
+#include "kvi_kvs_treenode_functioncall.h"
+
+class KviKvsRunTimeContext;
+class KviKvsVariant;
+
+class KVIRC_API KviKvsTreeNodeModuleFunctionCall : public KviKvsTreeNodeFunctionCall
+{
+public:
+ KviKvsTreeNodeModuleFunctionCall(const QChar * pLocation,const QString &szModuleName,const QString &szFncName,KviKvsTreeNodeDataList * pParams);
+ ~KviKvsTreeNodeModuleFunctionCall();
+protected:
+ QString m_szModuleName;
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer);
+};
+
+#endif //!_KVI_KVS_TREENODE_MODULEFUNCTIONCALL_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_modulesimplecommand.cpp b/src/kvirc/kvs/kvi_kvs_treenode_modulesimplecommand.cpp
new file mode 100644
index 00000000..78b6f02c
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_modulesimplecommand.cpp
@@ -0,0 +1,97 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_modulesimplecommand.cpp
+// Created on Thu 09 Oct 2003 02:18:27 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_modulesimplecommand.h"
+#include "kvi_kvs_treenode_datalist.h"
+#include "kvi_kvs_treenode_switchlist.h"
+
+#include "kvi_modulemanager.h"
+#include "kvi_locale.h"
+#include "kvi_kvs_moduleinterface.h"
+#include "kvi_kvs_runtimecontext.h"
+
+KviKvsTreeNodeModuleSimpleCommand::KviKvsTreeNodeModuleSimpleCommand(const QChar * pLocation,const QString &szModuleName,const QString &szCmdName,KviKvsTreeNodeDataList * params)
+: KviKvsTreeNodeSimpleCommand(pLocation,szCmdName,params)
+{
+ m_szModuleName = szModuleName;
+}
+
+
+KviKvsTreeNodeModuleSimpleCommand::~KviKvsTreeNodeModuleSimpleCommand()
+{
+}
+
+void KviKvsTreeNodeModuleSimpleCommand::contextDescription(QString &szBuffer)
+{
+ szBuffer = "Module Callback Command \"";
+ szBuffer += m_szModuleName;
+ szBuffer += ".";
+ szBuffer += m_szCmdName;
+ szBuffer += "\"";
+}
+
+void KviKvsTreeNodeModuleSimpleCommand::dump(const char * prefix)
+{
+ debug("%s ModuleSimpleCommand(%s.%s)",prefix,m_szModuleName.utf8().data(),m_szCmdName.utf8().data());
+ dumpSwitchList(prefix);
+ dumpParameterList(prefix);
+}
+
+bool KviKvsTreeNodeModuleSimpleCommand::execute(KviKvsRunTimeContext * c)
+{
+ //#warning "FIXME: module names should be UNICODE!"
+ KviModule * m = g_pModuleManager->getModule(m_szModuleName.utf8().data());
+ if(!m)
+ {
+ QString szErr = g_pModuleManager->lastError().ptr(); // <-- fixme!
+ c->error(this,__tr2qs("Module command call failed: can't load the module '%Q': %Q"),&m_szModuleName,&szErr);
+ return false;
+ }
+
+ KviKvsModuleSimpleCommandExecRoutine * proc = m->kvsFindSimpleCommand(m_szCmdName);
+ if(!proc)
+ {
+ c->error(this,__tr2qs("Module command call failed: the module '%Q' doesn't export a command named '%Q'"),&m_szModuleName,&m_szCmdName);
+ return false;
+ }
+
+ KviKvsVariantList l;
+ l.setAutoDelete(true);
+
+ if(!(m_pParams->evaluate(c,&l)))return false;
+ KviKvsSwitchList swl;
+ if(m_pSwitches)
+ {
+ if(!(m_pSwitches->evaluate(c,&swl)))return false;
+ }
+
+ c->setDefaultReportLocation(this);
+
+ KviKvsModuleCommandCall call(m,c,&l,&swl);
+
+ return (*proc)(&call);
+}
+
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_modulesimplecommand.h b/src/kvirc/kvs/kvi_kvs_treenode_modulesimplecommand.h
new file mode 100644
index 00000000..2a6ee96d
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_modulesimplecommand.h
@@ -0,0 +1,48 @@
+#ifndef _KVI_KVS_TREENODE_MODULESIMPLECOMMAND_H_
+#define _KVI_KVS_TREENODE_MODULESIMPLECOMMAND_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_modulesimplecommand.h
+// Created on Thu 09 Oct 2003 02:18:27 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_treenode_simplecommand.h"
+
+class KviKvsTreeNodeDataList;
+class KviKvsRunTimeContext;
+
+class KVIRC_API KviKvsTreeNodeModuleSimpleCommand : public KviKvsTreeNodeSimpleCommand
+{
+public:
+ KviKvsTreeNodeModuleSimpleCommand(const QChar * pLocation,const QString &szModuleName,const QString &szCmdName,KviKvsTreeNodeDataList * params);
+ ~KviKvsTreeNodeModuleSimpleCommand();
+protected:
+ QString m_szModuleName;
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c);
+};
+
+
+#endif //!_KVI_KVS_TREENODE_MODULESIMPLECOMMAND_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_multipleparameteridentifier.cpp b/src/kvirc/kvs/kvi_kvs_treenode_multipleparameteridentifier.cpp
new file mode 100644
index 00000000..405575d0
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_multipleparameteridentifier.cpp
@@ -0,0 +1,89 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_multipleparameteridentifier.cpp
+// Created on Tue 07 Oct 2003 03:49:31 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_multipleparameteridentifier.h"
+#include "kvi_kvs_runtimecontext.h"
+#include "kvi_kvs_variant.h"
+
+
+KviKvsTreeNodeMultipleParameterIdentifier::KviKvsTreeNodeMultipleParameterIdentifier(const QChar * pLocation,int iStart,int iEnd)
+: KviKvsTreeNodeData(pLocation)
+{
+ m_iStart = iStart;
+ m_iEnd = iEnd;
+}
+
+KviKvsTreeNodeMultipleParameterIdentifier::~KviKvsTreeNodeMultipleParameterIdentifier()
+{
+}
+
+void KviKvsTreeNodeMultipleParameterIdentifier::contextDescription(QString &szBuffer)
+{
+ szBuffer = "Multiple Parameter Identifier \"$";
+ if(m_iEnd < m_iStart)KviQString::appendFormatted(szBuffer,"%d-",m_iStart);
+ else KviQString::appendFormatted(szBuffer,"%d-%d",m_iStart,m_iEnd);
+ szBuffer += "\"";
+}
+
+void KviKvsTreeNodeMultipleParameterIdentifier::dump(const char * prefix)
+{
+ if(m_iEnd < m_iStart)debug("%s MultipleParameterIdentifier(%d-)",prefix,m_iStart);
+ else debug("%s MultipleParameterIdentifier(%d-%d)",prefix,m_iStart,m_iEnd);
+}
+
+bool KviKvsTreeNodeMultipleParameterIdentifier::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+ KviKvsVariant * v = c->parameterList()->at(m_iStart);
+ if(!v)
+ {
+ pBuffer->setNothing();
+ return true;
+ }
+
+ QString sz;
+ v->asString(sz);
+
+ if(m_iEnd >= m_iStart)
+ {
+ // only up to m_iEnd
+ int idx = m_iStart;
+ for(v = c->parameterList()->next();v && (idx < m_iEnd);v = c->parameterList()->next())
+ {
+ sz += QChar(' ');
+ v->appendAsString(sz);
+ idx++;
+ }
+ } else {
+ // all up to the end of the list
+ for(v = c->parameterList()->next();v;v = c->parameterList()->next())
+ {
+ sz += QChar(' ');
+ v->appendAsString(sz);
+ }
+ }
+ pBuffer->setString(sz);
+ return true;
+}
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_multipleparameteridentifier.h b/src/kvirc/kvs/kvi_kvs_treenode_multipleparameteridentifier.h
new file mode 100644
index 00000000..ad3edbd4
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_multipleparameteridentifier.h
@@ -0,0 +1,49 @@
+#ifndef _KVI_KVS_TREENODE_MULTIPLEPARAMETERIDENTIFIER_H_
+#define _KVI_KVS_TREENODE_MULTIPLEPARAMETERIDENTIFIER_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_multipleparameteridentifier.h
+// Created on Tue 07 Oct 2003 03:49:31 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_treenode_data.h"
+
+class KviKvsRunTimeContext;
+class KviKvsVariant;
+
+class KVIRC_API KviKvsTreeNodeMultipleParameterIdentifier : public KviKvsTreeNodeData
+{
+public:
+ KviKvsTreeNodeMultipleParameterIdentifier(const QChar * pLocation,int iStart,int iEnd);
+ ~KviKvsTreeNodeMultipleParameterIdentifier();
+protected:
+ int m_iStart;
+ int m_iEnd; // the index of the last parameter wanted (may be -1: in that case all up to the end)
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer);
+};
+
+
+#endif //!_KVI_KVS_TREENODE_MULTIPLEPARAMETERIDENTIFIER_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_objectfield.cpp b/src/kvirc/kvs/kvi_kvs_treenode_objectfield.cpp
new file mode 100644
index 00000000..6ac81b9d
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_objectfield.cpp
@@ -0,0 +1,80 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_objectfield.cpp
+// Created on Thu 28 Apr 2005 17:12:14 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_objectfield.h"
+#include "kvi_kvs_runtimecontext.h"
+#include "kvi_kvs_object.h"
+#include "kvi_kvs_hash.h"
+
+KviKvsTreeNodeObjectField::KviKvsTreeNodeObjectField(const QChar * pLocation,const QString &szIdentifier)
+: KviKvsTreeNodeVariable(pLocation,szIdentifier)
+{
+}
+
+KviKvsTreeNodeObjectField::~KviKvsTreeNodeObjectField()
+{
+}
+
+void KviKvsTreeNodeObjectField::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Object Field \"";
+ szBuffer += m_szIdentifier;
+ szBuffer += "\"";
+#endif
+}
+
+void KviKvsTreeNodeObjectField::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s ObjectField(%s)",prefix,m_szIdentifier.utf8().data());
+#endif
+}
+
+bool KviKvsTreeNodeObjectField::canEvaluateInObjectScope()
+{
+ return true;
+}
+
+bool KviKvsTreeNodeObjectField::evaluateReadOnlyInObjectScope(KviKvsObject * o,KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ KviKvsVariant * v = o->dataContainer()->find(m_szIdentifier);
+ if(v)pBuffer->copyFrom(v);
+ else pBuffer->setNothing();
+#endif
+ return true;
+}
+
+KviKvsRWEvaluationResult * KviKvsTreeNodeObjectField::evaluateReadWriteInObjectScope(KviKvsObject * o,KviKvsRunTimeContext * c)
+{
+#ifdef COMPILE_NEW_KVS
+ return new KviKvsHashElement(0,o->dataContainer()->get(m_szIdentifier),o->dataContainer(),m_szIdentifier);
+#else
+ return 0;
+#endif
+}
+
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_objectfield.h b/src/kvirc/kvs/kvi_kvs_treenode_objectfield.h
new file mode 100644
index 00000000..ef56ca10
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_objectfield.h
@@ -0,0 +1,47 @@
+#ifndef _KVI_KVS_TREENODE_OBJECTFIELD_H_
+#define _KVI_KVS_TREENODE_OBJECTFIELD_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_objectfield.h
+// Created on Thu 28 Apr 2005 17:12:14 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_treenode_variable.h"
+
+class KviKvsRunTimeContext;
+class KviKvsObject;
+
+class KVIRC_API KviKvsTreeNodeObjectField : public KviKvsTreeNodeVariable
+{
+public:
+ KviKvsTreeNodeObjectField(const QChar * pLocation,const QString &szIdentifier);
+ ~KviKvsTreeNodeObjectField();
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool canEvaluateInObjectScope();
+ virtual bool evaluateReadOnlyInObjectScope(KviKvsObject * o,KviKvsRunTimeContext * c,KviKvsVariant * pResult);
+ virtual KviKvsRWEvaluationResult * evaluateReadWriteInObjectScope(KviKvsObject * o,KviKvsRunTimeContext * c);
+};
+
+#endif //!_KVI_KVS_TREENODE_OBJECTFIELD_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_objectfunctioncall.cpp b/src/kvirc/kvs/kvi_kvs_treenode_objectfunctioncall.cpp
new file mode 100644
index 00000000..d9d5f23d
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_objectfunctioncall.cpp
@@ -0,0 +1,60 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_objectfunctioncall.cpp
+// Created on Tue 07 Oct 2003 03:26:07 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_objectfunctioncall.h"
+
+KviKvsTreeNodeObjectFunctionCall::KviKvsTreeNodeObjectFunctionCall(const QChar * pLocation,const QString &szFncName,KviKvsTreeNodeDataList * pParams)
+: KviKvsTreeNodeFunctionCall(pLocation,szFncName,pParams)
+{
+}
+
+KviKvsTreeNodeObjectFunctionCall::~KviKvsTreeNodeObjectFunctionCall()
+{
+}
+
+void KviKvsTreeNodeObjectFunctionCall::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Object Function Call \"";
+ szBuffer += m_szFunctionName;
+ szBuffer += "\"";
+#endif
+}
+
+void KviKvsTreeNodeObjectFunctionCall::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s ObjectFunctionCall(%s)",prefix,m_szFunctionName.utf8().data());
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pParams->dump(tmp.utf8().data());
+#endif
+}
+
+bool KviKvsTreeNodeObjectFunctionCall::canEvaluateInObjectScope()
+{
+ return true;
+}
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_objectfunctioncall.h b/src/kvirc/kvs/kvi_kvs_treenode_objectfunctioncall.h
new file mode 100644
index 00000000..c1e80631
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_objectfunctioncall.h
@@ -0,0 +1,45 @@
+#ifndef _KVI_KVS_TREENODE_OBJECTFUNCTIONCALL_H_
+#define _KVI_KVS_TREENODE_OBJECTFUNCTIONCALL_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_objectfunctioncall.h
+// Created on Tue 07 Oct 2003 03:26:07 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_treenode_datalist.h"
+#include "kvi_kvs_treenode_functioncall.h"
+
+
+class KVIRC_API KviKvsTreeNodeObjectFunctionCall : public KviKvsTreeNodeFunctionCall
+{
+public:
+ KviKvsTreeNodeObjectFunctionCall(const QChar * pLocation,const QString &szFncName,KviKvsTreeNodeDataList * pParams);
+ ~KviKvsTreeNodeObjectFunctionCall();
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool canEvaluateInObjectScope();
+};
+
+
+#endif //!_KVI_KVS_TREENODE_OBJECTFUNCTIONCALL_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_operation.cpp b/src/kvirc/kvs/kvi_kvs_treenode_operation.cpp
new file mode 100644
index 00000000..179d50ef
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_operation.cpp
@@ -0,0 +1,1497 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_operation.cpp
+// Created on Thu 18 Dec 2003 22:36:00 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_operation.h"
+#include "kvi_kvs_treenode_data.h"
+#include "kvi_kvs_runtimecontext.h"
+#include "kvi_locale.h"
+
+#include <qregexp.h>
+
+#include <math.h>
+
+
+KviKvsTreeNodeOperation::KviKvsTreeNodeOperation(const QChar * pLocation)
+: KviKvsTreeNodeInstruction(pLocation)
+{
+ //m_pTargetData = 0; no need to set it
+}
+
+KviKvsTreeNodeOperation::~KviKvsTreeNodeOperation()
+{
+ delete m_pTargetData;
+}
+
+void KviKvsTreeNodeOperation::setTargetVariableReference(KviKvsTreeNodeData * r)
+{
+ m_pTargetData = r;
+ m_pTargetData->setParent(this);
+}
+
+void KviKvsTreeNodeOperation::contextDescription(QString &szBuffer)
+{
+ szBuffer = "Operation";
+}
+
+void KviKvsTreeNodeOperation::dump(const char * prefix)
+{
+ debug("%s Operation",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pTargetData->dump(tmp.utf8().data());
+}
+
+
+
+
+
+KviKvsTreeNodeOperationAssignment::KviKvsTreeNodeOperationAssignment(const QChar * pLocation,KviKvsTreeNodeData * pRightSide)
+: KviKvsTreeNodeOperation(pLocation)
+{
+ m_pRightSide = pRightSide;
+ m_pRightSide->setParent(this);
+}
+
+KviKvsTreeNodeOperationAssignment::~KviKvsTreeNodeOperationAssignment()
+{
+ delete m_pRightSide;
+}
+
+void KviKvsTreeNodeOperationAssignment::contextDescription(QString &szBuffer)
+{
+ szBuffer = "Assignment";
+}
+
+
+void KviKvsTreeNodeOperationAssignment::dump(const char * prefix)
+{
+ debug("%s OperationAssignment",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pTargetData->dump(tmp.utf8().data());
+ m_pRightSide->dump(tmp.utf8().data());
+}
+
+bool KviKvsTreeNodeOperationAssignment::execute(KviKvsRunTimeContext * c)
+{
+ KviKvsVariant v;
+ if(!m_pRightSide->evaluateReadOnly(c,&v))return false;
+
+ KviKvsRWEvaluationResult * target = m_pTargetData->evaluateReadWrite(c);
+ if(!target)return false;
+
+ target->result()->takeFrom(v);
+ delete target;
+ return true;
+}
+
+
+
+
+
+
+KviKvsTreeNodeOperationDecrement::KviKvsTreeNodeOperationDecrement(const QChar * pLocation)
+: KviKvsTreeNodeOperation(pLocation)
+{
+}
+
+KviKvsTreeNodeOperationDecrement::~KviKvsTreeNodeOperationDecrement()
+{
+}
+
+void KviKvsTreeNodeOperationDecrement::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Operator \"--\"";
+#endif
+}
+
+
+void KviKvsTreeNodeOperationDecrement::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s OperationDecrement",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pTargetData->dump(tmp.utf8().data());
+#endif
+}
+
+bool KviKvsTreeNodeOperationDecrement::execute(KviKvsRunTimeContext * c)
+{
+#ifdef COMPILE_NEW_KVS
+ KviKvsRWEvaluationResult * v = m_pTargetData->evaluateReadWrite(c);
+ if(!v)return false;
+
+ kvs_int_t iVal;
+ if(v->result()->asInteger(iVal))
+ {
+ v->result()->setInteger(iVal - 1);
+ delete v;
+ v = 0;
+ return true;
+ }
+
+ kvs_real_t dVal;
+ if(v->result()->asReal(dVal))
+ {
+ v->result()->setReal(dVal - 1.0);
+ delete v;
+ v = 0;
+ return true;
+ }
+
+ c->error(this,__tr2qs("The target variable didn't evaluate to an integer or real value"));
+ delete v;
+#endif
+ return false;
+}
+
+
+
+
+
+
+
+KviKvsTreeNodeOperationIncrement::KviKvsTreeNodeOperationIncrement(const QChar * pLocation)
+: KviKvsTreeNodeOperation(pLocation)
+{
+}
+
+KviKvsTreeNodeOperationIncrement::~KviKvsTreeNodeOperationIncrement()
+{
+}
+
+void KviKvsTreeNodeOperationIncrement::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Operator \"++\"";
+#endif
+}
+
+
+void KviKvsTreeNodeOperationIncrement::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s OperationIncrement",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pTargetData->dump(tmp.utf8().data());
+#endif
+}
+
+bool KviKvsTreeNodeOperationIncrement::execute(KviKvsRunTimeContext * c)
+{
+#ifdef COMPILE_NEW_KVS
+ KviKvsRWEvaluationResult * v = m_pTargetData->evaluateReadWrite(c);
+ if(!v)return false;
+
+ kvs_int_t iVal;
+ if(v->result()->asInteger(iVal))
+ {
+ v->result()->setInteger(iVal + 1);
+ delete v;
+ v = 0;
+ return true;
+ }
+
+ kvs_real_t dVal;
+ if(v->result()->asReal(dVal))
+ {
+ v->result()->setReal(dVal + 1.0);
+ delete v;
+ v = 0;
+ return true;
+ }
+ c->error(this,__tr2qs("The target variable didn't evaluate to an integer or real value"));
+ delete v;
+#endif
+ return false;
+}
+
+
+
+
+KviKvsTreeNodeOperationSelfAnd::KviKvsTreeNodeOperationSelfAnd(const QChar * pLocation,KviKvsTreeNodeData * pRightSide)
+: KviKvsTreeNodeOperation(pLocation)
+{
+#ifdef COMPILE_NEW_KVS
+ m_pRightSide = pRightSide;
+ m_pRightSide->setParent(this);
+#endif
+}
+
+KviKvsTreeNodeOperationSelfAnd::~KviKvsTreeNodeOperationSelfAnd()
+{
+#ifdef COMPILE_NEW_KVS
+ delete m_pRightSide;
+#endif
+}
+
+void KviKvsTreeNodeOperationSelfAnd::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Operator \"&=\"";
+#endif
+}
+
+
+void KviKvsTreeNodeOperationSelfAnd::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s OperationSelfAnd",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pTargetData->dump(tmp.utf8().data());
+ m_pRightSide->dump(tmp.utf8().data());
+#endif
+}
+
+bool KviKvsTreeNodeOperationSelfAnd::execute(KviKvsRunTimeContext * c)
+{
+#ifdef COMPILE_NEW_KVS
+ KviKvsVariant v;
+ if(!m_pRightSide->evaluateReadOnly(c,&v))return false;
+
+ kvs_int_t iRVal;
+
+ if(!v.asInteger(iRVal))
+ {
+ c->error(this,__tr2qs("The right side of operator '&=' didn't evaluate to an integer"));
+ return false;
+ }
+
+ KviKvsRWEvaluationResult * target = m_pTargetData->evaluateReadWrite(c);
+ if(!target)return false;
+
+ kvs_int_t iLVal;
+
+ if(!target->result()->asInteger(iLVal))
+ {
+ c->error(this,__tr2qs("The left side of operator '&=' didn't evaluate to an integer"));
+ delete target;
+ target = 0;
+ return false;
+ }
+
+ target->result()->setInteger(iLVal & iRVal);
+ delete target;
+#endif
+ return true;
+}
+
+
+
+KviKvsTreeNodeOperationSelfDivision::KviKvsTreeNodeOperationSelfDivision(const QChar * pLocation,KviKvsTreeNodeData * pRightSide)
+: KviKvsTreeNodeOperation(pLocation)
+{
+#ifdef COMPILE_NEW_KVS
+ m_pRightSide = pRightSide;
+ m_pRightSide->setParent(this);
+#endif
+}
+
+KviKvsTreeNodeOperationSelfDivision::~KviKvsTreeNodeOperationSelfDivision()
+{
+#ifdef COMPILE_NEW_KVS
+ delete m_pRightSide;
+#endif
+}
+
+void KviKvsTreeNodeOperationSelfDivision::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Operator \"/=\"";
+#endif
+}
+
+
+void KviKvsTreeNodeOperationSelfDivision::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s OperationSelfDivision",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pTargetData->dump(tmp.utf8().data());
+ m_pRightSide->dump(tmp.utf8().data());
+#endif
+}
+
+bool KviKvsTreeNodeOperationSelfDivision::execute(KviKvsRunTimeContext * c)
+{
+#ifdef COMPILE_NEW_KVS
+ KviKvsVariant v;
+ if(!m_pRightSide->evaluateReadOnly(c,&v))return false;
+
+ KviKvsNumber rnum;
+
+ if(!v.asNumber(rnum))
+ {
+ c->error(this,__tr2qs("The right side of operator '/=' didn't evaluate to a number"));
+ return false;
+ }
+
+ KviKvsNumber lnum;
+
+ KviKvsRWEvaluationResult * target = m_pTargetData->evaluateReadWrite(c);
+ if(!target)return false;
+
+ if(!target->result()->asNumber(lnum))
+ {
+ c->error(this,__tr2qs("The left side of operator '/=' didn't evaluate to a number"));
+ delete target;
+ target = 0;
+ return false;
+ }
+
+ if(rnum.isInteger())
+ {
+ if(rnum.integer() == 0)
+ {
+ c->error(this,__tr2qs("Division by zero"));
+ delete target;
+ target = 0;
+ return false;
+ }
+ if(lnum.isInteger())
+ target->result()->setInteger(lnum.integer() / rnum.integer());
+ else
+ target->result()->setReal(lnum.real() / (kvs_real_t)(rnum.integer()));
+ } else {
+ if(rnum.real() == 0.0)
+ {
+ c->error(this,__tr2qs("Division by zero"));
+ delete target;
+ target = 0;
+ return false;
+ }
+ if(lnum.isInteger())
+ target->result()->setReal(((kvs_real_t)(lnum.integer())) / rnum.real());
+ else
+ target->result()->setReal(lnum.real() / rnum.real());
+ }
+
+ delete target;
+#endif
+ return true;
+}
+
+KviKvsTreeNodeOperationSelfModulus::KviKvsTreeNodeOperationSelfModulus(const QChar * pLocation,KviKvsTreeNodeData * pRightSide)
+: KviKvsTreeNodeOperation(pLocation)
+{
+#ifdef COMPILE_NEW_KVS
+ m_pRightSide = pRightSide;
+ m_pRightSide->setParent(this);
+#endif
+}
+
+KviKvsTreeNodeOperationSelfModulus::~KviKvsTreeNodeOperationSelfModulus()
+{
+#ifdef COMPILE_NEW_KVS
+ delete m_pRightSide;
+#endif
+}
+
+void KviKvsTreeNodeOperationSelfModulus::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Operator \"Self Modulo\"";
+#endif
+}
+
+
+void KviKvsTreeNodeOperationSelfModulus::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s OperationSelfModulus",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pTargetData->dump(tmp.utf8().data());
+ m_pRightSide->dump(tmp.utf8().data());
+#endif
+}
+
+bool KviKvsTreeNodeOperationSelfModulus::execute(KviKvsRunTimeContext * c)
+{
+#ifdef COMPILE_NEW_KVS
+ KviKvsVariant v;
+ if(!m_pRightSide->evaluateReadOnly(c,&v))return false;
+ KviKvsNumber rnum;
+
+ if(!v.asNumber(rnum))
+ {
+ c->error(this,__tr2qs("The right side of operator '%=' didn't evaluate to a number"));
+ return false;
+ }
+
+ KviKvsNumber lnum;
+
+ KviKvsRWEvaluationResult * target = m_pTargetData->evaluateReadWrite(c);
+ if(!target)return false;
+
+ if(!target->result()->asNumber(lnum))
+ {
+ c->error(this,__tr2qs("The left side of operator '%=' didn't evaluate to a number"));
+ delete target;
+ target = 0;
+ return false;
+ }
+
+ if(rnum.isInteger())
+ {
+ if(rnum.integer() == 0)
+ {
+ c->error(this,__tr2qs("Division by zero"));
+ delete target;
+ target = 0;
+ return false;
+ }
+ if(lnum.isInteger())
+ target->result()->setInteger(lnum.integer() % rnum.integer());
+ else
+ target->result()->setReal(fmod(lnum.real(),(kvs_real_t)(rnum.integer())));
+ } else {
+ if(rnum.real() == 0.0)
+ {
+ c->error(this,__tr2qs("Division by zero"));
+ delete target;
+ target = 0;
+ return false;
+ }
+ if(lnum.isInteger())
+ target->result()->setReal(fmod(((kvs_real_t)(lnum.integer())),rnum.real()));
+ else
+ target->result()->setReal(fmod(lnum.real(),rnum.real()));
+ }
+#endif
+ return true;
+}
+
+
+
+
+
+KviKvsTreeNodeOperationSelfMultiplication::KviKvsTreeNodeOperationSelfMultiplication(const QChar * pLocation,KviKvsTreeNodeData * pRightSide)
+: KviKvsTreeNodeOperation(pLocation)
+{
+#ifdef COMPILE_NEW_KVS
+ m_pRightSide = pRightSide;
+ m_pRightSide->setParent(this);
+#endif
+}
+
+KviKvsTreeNodeOperationSelfMultiplication::~KviKvsTreeNodeOperationSelfMultiplication()
+{
+#ifdef COMPILE_NEW_KVS
+ delete m_pRightSide;
+#endif
+}
+
+void KviKvsTreeNodeOperationSelfMultiplication::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Operator \"*=\"";
+#endif
+}
+
+
+void KviKvsTreeNodeOperationSelfMultiplication::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s OperationSelfMultiplication",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pTargetData->dump(tmp.utf8().data());
+ m_pRightSide->dump(tmp.utf8().data());
+#endif
+}
+
+bool KviKvsTreeNodeOperationSelfMultiplication::execute(KviKvsRunTimeContext * c)
+{
+#ifdef COMPILE_NEW_KVS
+ KviKvsVariant v;
+ if(!m_pRightSide->evaluateReadOnly(c,&v))return false;
+ KviKvsNumber rnum;
+
+ if(!v.asNumber(rnum))
+ {
+ c->error(this,__tr2qs("The right side of operator '*=' didn't evaluate to a number"));
+ return false;
+ }
+
+ KviKvsNumber lnum;
+
+ KviKvsRWEvaluationResult * target = m_pTargetData->evaluateReadWrite(c);
+ if(!target)return false;
+
+ if(!target->result()->asNumber(lnum))
+ {
+ c->error(this,__tr2qs("The left side of operator '*=' didn't evaluate to a number"));
+ delete target;
+ return false;
+ }
+
+ if(rnum.isInteger())
+ {
+ if(lnum.isInteger())
+ target->result()->setInteger(lnum.integer() * rnum.integer());
+ else
+ target->result()->setReal(lnum.real() * (kvs_real_t)(rnum.integer()));
+ } else {
+ if(lnum.isInteger())
+ target->result()->setReal(((kvs_real_t)(lnum.integer())) * rnum.real());
+ else
+ target->result()->setReal(lnum.real() * rnum.real());
+ }
+#endif
+ return true;
+}
+
+
+
+
+KviKvsTreeNodeOperationSelfOr::KviKvsTreeNodeOperationSelfOr(const QChar * pLocation,KviKvsTreeNodeData * pRightSide)
+: KviKvsTreeNodeOperation(pLocation)
+{
+#ifdef COMPILE_NEW_KVS
+ m_pRightSide = pRightSide;
+ m_pRightSide->setParent(this);
+#endif
+}
+
+KviKvsTreeNodeOperationSelfOr::~KviKvsTreeNodeOperationSelfOr()
+{
+#ifdef COMPILE_NEW_KVS
+ delete m_pRightSide;
+#endif
+}
+
+void KviKvsTreeNodeOperationSelfOr::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Operator \"|=\"";
+#endif
+}
+
+
+void KviKvsTreeNodeOperationSelfOr::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s OperationSelfOr",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pTargetData->dump(tmp.utf8().data());
+ m_pRightSide->dump(tmp.utf8().data());
+#endif
+}
+
+bool KviKvsTreeNodeOperationSelfOr::execute(KviKvsRunTimeContext * c)
+{
+#ifdef COMPILE_NEW_KVS
+ KviKvsVariant v;
+ if(!m_pRightSide->evaluateReadOnly(c,&v))return false;
+
+ kvs_int_t iRVal;
+ if(!v.asInteger(iRVal))
+ {
+ c->error(this,__tr2qs("The right side of operator '|=' didn't evaluate to an integer"));
+ return false;
+ }
+
+ kvs_int_t iLVal;
+
+ KviKvsRWEvaluationResult * target = m_pTargetData->evaluateReadWrite(c);
+ if(!target)return false;
+
+ if(!target->result()->asInteger(iLVal))
+ {
+ c->error(this,__tr2qs("The left side of operator '|=' didn't evaluate to an integer"));
+ delete target;
+ target = 0;
+ return false;
+ }
+
+ target->result()->setInteger(iLVal | iRVal);
+ delete target;
+#endif
+ return true;
+}
+
+
+
+
+KviKvsTreeNodeOperationSelfShl::KviKvsTreeNodeOperationSelfShl(const QChar * pLocation,KviKvsTreeNodeData * pRightSide)
+: KviKvsTreeNodeOperation(pLocation)
+{
+#ifdef COMPILE_NEW_KVS
+ m_pRightSide = pRightSide;
+ m_pRightSide->setParent(this);
+#endif
+}
+
+KviKvsTreeNodeOperationSelfShl::~KviKvsTreeNodeOperationSelfShl()
+{
+#ifdef COMPILE_NEW_KVS
+ delete m_pRightSide;
+#endif
+}
+
+void KviKvsTreeNodeOperationSelfShl::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Operator \"<<=\"";
+#endif
+}
+
+
+void KviKvsTreeNodeOperationSelfShl::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s OperationSelfShl",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pTargetData->dump(tmp.utf8().data());
+ m_pRightSide->dump(tmp.utf8().data());
+#endif
+}
+
+bool KviKvsTreeNodeOperationSelfShl::execute(KviKvsRunTimeContext * c)
+{
+#ifdef COMPILE_NEW_KVS
+ KviKvsVariant v;
+ if(!m_pRightSide->evaluateReadOnly(c,&v))return false;
+
+ kvs_int_t iRVal;
+
+ if(!v.asInteger(iRVal))
+ {
+ c->error(this,__tr2qs("The right side of operator '<<=' didn't evaluate to an integer"));
+ return false;
+ }
+
+ kvs_int_t iLVal;
+
+ KviKvsRWEvaluationResult * target = m_pTargetData->evaluateReadWrite(c);
+ if(!target)return false;
+
+ if(!target->result()->asInteger(iLVal))
+ {
+ c->error(this,__tr2qs("The left side of operator '<<=' didn't evaluate to an integer"));
+ delete target;
+ target = 0;
+ return false;
+ }
+
+ target->result()->setInteger(iLVal << iRVal);
+ delete target;
+#endif
+ return true;
+}
+
+
+
+
+
+KviKvsTreeNodeOperationSelfShr::KviKvsTreeNodeOperationSelfShr(const QChar * pLocation,KviKvsTreeNodeData * pRightSide)
+: KviKvsTreeNodeOperation(pLocation)
+{
+#ifdef COMPILE_NEW_KVS
+ m_pRightSide = pRightSide;
+ m_pRightSide->setParent(this);
+#endif
+}
+
+KviKvsTreeNodeOperationSelfShr::~KviKvsTreeNodeOperationSelfShr()
+{
+#ifdef COMPILE_NEW_KVS
+ delete m_pRightSide;
+#endif
+}
+
+void KviKvsTreeNodeOperationSelfShr::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Operator \">>=\"";
+#endif
+}
+
+
+void KviKvsTreeNodeOperationSelfShr::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s OperationSelfShr",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pTargetData->dump(tmp.utf8().data());
+ m_pRightSide->dump(tmp.utf8().data());
+#endif
+}
+
+bool KviKvsTreeNodeOperationSelfShr::execute(KviKvsRunTimeContext * c)
+{
+#ifdef COMPILE_NEW_KVS
+ KviKvsVariant v;
+ if(!m_pRightSide->evaluateReadOnly(c,&v))return false;
+
+ kvs_int_t iRVal;
+
+ if(!v.asInteger(iRVal))
+ {
+ c->error(this,__tr2qs("The right side of operator '>>=' didn't evaluate to an integer"));
+ return false;
+ }
+
+ kvs_int_t iLVal;
+
+ KviKvsRWEvaluationResult * target = m_pTargetData->evaluateReadWrite(c);
+ if(!target)return false;
+
+ if(!target->result()->asInteger(iLVal))
+ {
+ c->error(this,__tr2qs("The left side of operator '>>=' didn't evaluate to an integer"));
+ delete target;
+ target = 0;
+ return false;
+ }
+
+ target->result()->setInteger(iLVal >> iRVal);
+ delete target;
+#endif
+ return true;
+}
+
+
+
+
+
+
+
+
+
+
+
+KviKvsTreeNodeOperationSelfSubtraction::KviKvsTreeNodeOperationSelfSubtraction(const QChar * pLocation,KviKvsTreeNodeData * pRightSide)
+: KviKvsTreeNodeOperation(pLocation)
+{
+#ifdef COMPILE_NEW_KVS
+ m_pRightSide = pRightSide;
+ m_pRightSide->setParent(this);
+#endif
+}
+
+KviKvsTreeNodeOperationSelfSubtraction::~KviKvsTreeNodeOperationSelfSubtraction()
+{
+#ifdef COMPILE_NEW_KVS
+ delete m_pRightSide;
+#endif
+}
+
+void KviKvsTreeNodeOperationSelfSubtraction::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Operator \"-=\"";
+#endif
+}
+
+
+void KviKvsTreeNodeOperationSelfSubtraction::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s OperationSelfSubtraction",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pTargetData->dump(tmp.utf8().data());
+ m_pRightSide->dump(tmp.utf8().data());
+#endif
+}
+
+bool KviKvsTreeNodeOperationSelfSubtraction::execute(KviKvsRunTimeContext * c)
+{
+#ifdef COMPILE_NEW_KVS
+ KviKvsVariant v;
+ if(!m_pRightSide->evaluateReadOnly(c,&v))return false;
+ KviKvsNumber rnum;
+
+ if(!v.asNumber(rnum))
+ {
+ c->error(this,__tr2qs("The right side of operator '-=' didn't evaluate to a number"));
+ return false;
+ }
+
+ KviKvsNumber lnum;
+
+ KviKvsRWEvaluationResult * target = m_pTargetData->evaluateReadWrite(c);
+ if(!target)return false;
+
+ if(!target->result()->asNumber(lnum))
+ {
+ c->error(this,__tr2qs("The left side of operator '-=' didn't evaluate to a number"));
+ delete target;
+ target = 0;
+ return false;
+ }
+
+ if(rnum.isInteger())
+ {
+ if(lnum.isInteger())
+ target->result()->setInteger(lnum.integer() - rnum.integer());
+ else
+ target->result()->setReal(lnum.real() - (kvs_real_t)(rnum.integer()));
+ } else {
+ if(lnum.isInteger())
+ target->result()->setReal(((kvs_real_t)(lnum.integer())) - rnum.real());
+ else
+ target->result()->setReal(lnum.real() - rnum.real());
+ }
+
+ delete target;
+#endif
+ return true;
+}
+
+
+
+
+
+KviKvsTreeNodeOperationSelfSum::KviKvsTreeNodeOperationSelfSum(const QChar * pLocation,KviKvsTreeNodeData * pRightSide)
+: KviKvsTreeNodeOperation(pLocation)
+{
+#ifdef COMPILE_NEW_KVS
+ m_pRightSide = pRightSide;
+ m_pRightSide->setParent(this);
+#endif
+}
+
+KviKvsTreeNodeOperationSelfSum::~KviKvsTreeNodeOperationSelfSum()
+{
+#ifdef COMPILE_NEW_KVS
+ delete m_pRightSide;
+#endif
+}
+
+void KviKvsTreeNodeOperationSelfSum::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Operator \"+=\"";
+#endif
+}
+
+
+void KviKvsTreeNodeOperationSelfSum::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s OperationSelfSum",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pTargetData->dump(tmp.utf8().data());
+ m_pRightSide->dump(tmp.utf8().data());
+#endif
+}
+
+bool KviKvsTreeNodeOperationSelfSum::execute(KviKvsRunTimeContext * c)
+{
+#ifdef COMPILE_NEW_KVS
+ KviKvsVariant v;
+ if(!m_pRightSide->evaluateReadOnly(c,&v))return false;
+ KviKvsNumber rnum;
+
+ if(!v.asNumber(rnum))
+ {
+ c->error(this,__tr2qs("The right side of operator '+=' didn't evaluate to a number"));
+ return false;
+ }
+
+ KviKvsNumber lnum;
+
+ KviKvsRWEvaluationResult * target = m_pTargetData->evaluateReadWrite(c);
+ if(!target)return false;
+
+ if(!target->result()->asNumber(lnum))
+ {
+ c->error(this,__tr2qs("The left side of operator '+=' didn't evaluate to a number"));
+ delete target;
+ target = 0;
+ return false;
+ }
+
+ if(rnum.isInteger())
+ {
+ if(lnum.isInteger())
+ target->result()->setInteger(lnum.integer() + rnum.integer());
+ else
+ target->result()->setReal(lnum.real() + (kvs_real_t)(rnum.integer()));
+ } else {
+ if(lnum.isInteger())
+ target->result()->setReal(((kvs_real_t)(lnum.integer())) + rnum.real());
+ else
+ target->result()->setReal(lnum.real() + rnum.real());
+ }
+
+ delete target;
+#endif
+ return true;
+}
+
+
+
+
+
+
+
+KviKvsTreeNodeOperationSelfXor::KviKvsTreeNodeOperationSelfXor(const QChar * pLocation,KviKvsTreeNodeData * pRightSide)
+: KviKvsTreeNodeOperation(pLocation)
+{
+#ifdef COMPILE_NEW_KVS
+ m_pRightSide = pRightSide;
+ m_pRightSide->setParent(this);
+#endif
+}
+
+KviKvsTreeNodeOperationSelfXor::~KviKvsTreeNodeOperationSelfXor()
+{
+#ifdef COMPILE_NEW_KVS
+ delete m_pRightSide;
+#endif
+}
+
+void KviKvsTreeNodeOperationSelfXor::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Operator \"^=\"";
+#endif
+}
+
+
+void KviKvsTreeNodeOperationSelfXor::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s OperationSelfXor",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pTargetData->dump(tmp.utf8().data());
+ m_pRightSide->dump(tmp.utf8().data());
+#endif
+}
+
+bool KviKvsTreeNodeOperationSelfXor::execute(KviKvsRunTimeContext * c)
+{
+#ifdef COMPILE_NEW_KVS
+ KviKvsVariant v;
+ if(!m_pRightSide->evaluateReadOnly(c,&v))return false;
+
+ kvs_int_t iRVal;
+
+ if(!v.asInteger(iRVal))
+ {
+ c->error(this,__tr2qs("The right side of operator '^=' didn't evaluate to an integer"));
+ return false;
+ }
+
+ kvs_int_t iLVal;
+
+ KviKvsRWEvaluationResult * target = m_pTargetData->evaluateReadWrite(c);
+ if(!target)return false;
+
+ if(!target->result()->asInteger(iLVal))
+ {
+ c->error(this,__tr2qs("The left side of operator '^=' didn't evaluate to an integer"));
+ delete target;
+ target = 0;
+ return false;
+ }
+
+ target->result()->setInteger(iLVal ^ iRVal);
+ delete target;
+#endif
+ return true;
+}
+
+
+
+
+
+
+
+KviKvsTreeNodeOperationStringAppend::KviKvsTreeNodeOperationStringAppend(const QChar * pLocation,KviKvsTreeNodeData * pRightSide)
+: KviKvsTreeNodeOperation(pLocation)
+{
+ m_pRightSide = pRightSide;
+ m_pRightSide->setParent(this);
+}
+
+KviKvsTreeNodeOperationStringAppend::~KviKvsTreeNodeOperationStringAppend()
+{
+ delete m_pRightSide;
+}
+
+void KviKvsTreeNodeOperationStringAppend::contextDescription(QString &szBuffer)
+{
+ szBuffer = "Operator \"<<\"";
+}
+
+
+void KviKvsTreeNodeOperationStringAppend::dump(const char * prefix)
+{
+ debug("%s OperationStringAppend",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pTargetData->dump(tmp.utf8().data());
+ m_pRightSide->dump(tmp.utf8().data());
+}
+
+bool KviKvsTreeNodeOperationStringAppend::execute(KviKvsRunTimeContext * c)
+{
+ KviKvsVariant v;
+ if(!m_pRightSide->evaluateReadOnly(c,&v))return false;
+ KviKvsRWEvaluationResult * target = m_pTargetData->evaluateReadWrite(c);
+ if(!target)return false;
+
+ QString sz1;
+ target->result()->asString(sz1);
+ v.appendAsString(sz1);
+ target->result()->setString(sz1);
+ delete target;
+ return true;
+}
+
+
+
+
+
+
+KviKvsTreeNodeOperationArrayAppend::KviKvsTreeNodeOperationArrayAppend(const QChar * pLocation,KviKvsTreeNodeData * pRightSide)
+: KviKvsTreeNodeOperation(pLocation)
+{
+ m_pRightSide = pRightSide;
+ m_pRightSide->setParent(this);
+}
+
+KviKvsTreeNodeOperationArrayAppend::~KviKvsTreeNodeOperationArrayAppend()
+{
+ delete m_pRightSide;
+}
+
+void KviKvsTreeNodeOperationArrayAppend::contextDescription(QString &szBuffer)
+{
+ szBuffer = "Operator \"<+\"";
+}
+
+
+void KviKvsTreeNodeOperationArrayAppend::dump(const char * prefix)
+{
+ debug("%s OperationArrayAppend",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pTargetData->dump(tmp.utf8().data());
+ m_pRightSide->dump(tmp.utf8().data());
+}
+
+bool KviKvsTreeNodeOperationArrayAppend::execute(KviKvsRunTimeContext * c)
+{
+ KviKvsVariant v;
+ if(!m_pRightSide->evaluateReadOnly(c,&v))return false;
+ KviKvsRWEvaluationResult * target = m_pTargetData->evaluateReadWrite(c);
+ if(!target)return false;
+
+ target->result()->convertToArray();
+ KviKvsArray * a = target->result()->array();
+
+ switch(v.type())
+ {
+ case KviKvsVariantData::Nothing:
+ // do nothing
+ break;
+ case KviKvsVariantData::Array:
+ {
+ KviKvsArray * s = v.array();
+ unsigned int uIdx = 0;
+ unsigned int uSize = s->size();
+ while(uIdx < uSize)
+ {
+ KviKvsVariant * pInternal = s->at(uIdx);
+ if(pInternal)
+ a->set(a->size(),new KviKvsVariant(*pInternal));
+ // else
+ // leave an empty entry
+ uIdx++;
+ }
+ }
+ break;
+ case KviKvsVariantData::Hash:
+ {
+ KviKvsHashIterator it(*(v.hash()->dict()));
+ while(KviKvsVariant * pInternal = it.current())
+ {
+ a->set(a->size(),new KviKvsVariant(*pInternal));
+ ++it;
+ }
+ }
+ break;
+ default:
+ a->set(a->size(),new KviKvsVariant(v));
+ break;
+ }
+ delete target;
+
+ return true;
+}
+
+
+
+
+
+
+
+KviKvsTreeNodeOperationStringAppendWithComma::KviKvsTreeNodeOperationStringAppendWithComma(const QChar * pLocation,KviKvsTreeNodeData * pRightSide)
+: KviKvsTreeNodeOperation(pLocation)
+{
+#ifdef COMPILE_NEW_KVS
+ m_pRightSide = pRightSide;
+ m_pRightSide->setParent(this);
+#endif
+}
+
+KviKvsTreeNodeOperationStringAppendWithComma::~KviKvsTreeNodeOperationStringAppendWithComma()
+{
+#ifdef COMPILE_NEW_KVS
+ delete m_pRightSide;
+#endif
+}
+
+void KviKvsTreeNodeOperationStringAppendWithComma::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Operator \"<,\"";
+#endif
+}
+
+
+void KviKvsTreeNodeOperationStringAppendWithComma::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s OperationStringAppendWithComma",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pTargetData->dump(tmp.utf8().data());
+ m_pRightSide->dump(tmp.utf8().data());
+#endif
+}
+
+bool KviKvsTreeNodeOperationStringAppendWithComma::execute(KviKvsRunTimeContext * c)
+{
+#ifdef COMPILE_NEW_KVS
+ KviKvsVariant v;
+ if(!m_pRightSide->evaluateReadOnly(c,&v))return false;
+ KviKvsRWEvaluationResult * target = m_pTargetData->evaluateReadWrite(c);
+ if(!target)return false;
+
+ QString sz1;
+ target->result()->asString(sz1);
+ if(sz1.isEmpty())
+ {
+ v.asString(sz1);
+ } else {
+ QString sz2;
+ v.asString(sz2);
+ sz1 += QChar(',');
+ sz1 += sz2;
+ }
+ target->result()->setString(sz1);
+ delete target;
+#endif
+ return true;
+}
+
+
+
+
+
+
+KviKvsTreeNodeOperationStringAppendWithSpace::KviKvsTreeNodeOperationStringAppendWithSpace(const QChar * pLocation,KviKvsTreeNodeData * pRightSide)
+: KviKvsTreeNodeOperation(pLocation)
+{
+#ifdef COMPILE_NEW_KVS
+ m_pRightSide = pRightSide;
+ m_pRightSide->setParent(this);
+#endif
+}
+
+KviKvsTreeNodeOperationStringAppendWithSpace::~KviKvsTreeNodeOperationStringAppendWithSpace()
+{
+#ifdef COMPILE_NEW_KVS
+ delete m_pRightSide;
+#endif
+}
+
+void KviKvsTreeNodeOperationStringAppendWithSpace::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Operator \"<+\"";
+#endif
+}
+
+
+void KviKvsTreeNodeOperationStringAppendWithSpace::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s OperationStringAppendWithSpace",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pTargetData->dump(tmp.utf8().data());
+ m_pRightSide->dump(tmp.utf8().data());
+#endif
+}
+
+bool KviKvsTreeNodeOperationStringAppendWithSpace::execute(KviKvsRunTimeContext * c)
+{
+#ifdef COMPILE_NEW_KVS
+ KviKvsVariant v;
+ if(!m_pRightSide->evaluateReadOnly(c,&v))return false;
+ KviKvsRWEvaluationResult * target = m_pTargetData->evaluateReadWrite(c);
+ if(!target)return false;
+
+ QString sz1;
+ target->result()->asString(sz1);
+ if(sz1.isEmpty())
+ {
+ v.asString(sz1);
+ } else {
+ QString sz2;
+ v.asString(sz2);
+ sz1 += QChar(' ');
+ sz1 += sz2;
+ }
+ target->result()->setString(sz1);
+ delete target;
+#endif
+ return true;
+}
+
+
+
+
+
+
+
+
+
+KviKvsTreeNodeOperationStringTransliteration::KviKvsTreeNodeOperationStringTransliteration(const QChar * pLocation,KviKvsTreeNodeData * pLeft,KviKvsTreeNodeData * pRight,KviKvsTreeNodeData * pFlags)
+: KviKvsTreeNodeOperation(pLocation)
+{
+#ifdef COMPILE_NEW_KVS
+ m_pLeft = pLeft;
+ m_pLeft->setParent(this);
+ m_pRight = pRight;
+ m_pRight->setParent(this);
+ m_pFlags = pFlags;
+ m_pFlags->setParent(this);
+#endif
+}
+
+KviKvsTreeNodeOperationStringTransliteration::~KviKvsTreeNodeOperationStringTransliteration()
+{
+#ifdef COMPILE_NEW_KVS
+ delete m_pLeft;
+ delete m_pRight;
+ delete m_pFlags;
+#endif
+}
+
+
+void KviKvsTreeNodeOperationStringTransliteration::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Binding Operator tr///";
+#endif
+}
+
+
+void KviKvsTreeNodeOperationStringTransliteration::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s OperationStringTransliteration",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pLeft->dump(tmp.utf8().data());
+ m_pRight->dump(tmp.utf8().data());
+ m_pFlags->dump(tmp.utf8().data());
+#endif
+}
+
+bool KviKvsTreeNodeOperationStringTransliteration::execute(KviKvsRunTimeContext * c)
+{
+#ifdef COMPILE_NEW_KVS
+ KviKvsVariant vl;
+ if(!m_pLeft->evaluateReadOnly(c,&vl))return false;
+ KviKvsVariant vr;
+ if(!m_pRight->evaluateReadOnly(c,&vr))return false;
+
+ // for now we don't use the flags at all here...
+ //KviKvsVariant vf;
+ //if(!m_pFlags->evaluateReadOnly(c,&vf))return false;
+ KviKvsRWEvaluationResult * target = m_pTargetData->evaluateReadWrite(c);
+ if(!target)return false;
+
+ QString szL,szR,szF;
+
+ vl.asString(szL);
+ vr.asString(szR);
+ //vf.asString(szF);
+
+ QString sz1;
+ target->result()->asString(sz1);
+ KviQString::transliterate(sz1,szL,szR);
+ target->result()->setString(sz1);
+ delete target;
+#endif
+ return true;
+}
+
+
+
+
+
+
+
+
+
+
+KviKvsTreeNodeOperationStringSubstitution::KviKvsTreeNodeOperationStringSubstitution(const QChar * pLocation,KviKvsTreeNodeData * pLeft,KviKvsTreeNodeData * pRight,KviKvsTreeNodeData * pFlags)
+: KviKvsTreeNodeOperation(pLocation)
+{
+#ifdef COMPILE_NEW_KVS
+ m_pLeft = pLeft;
+ m_pLeft->setParent(this);
+ m_pRight = pRight;
+ m_pRight->setParent(this);
+ m_pFlags = pFlags;
+ m_pFlags->setParent(this);
+#endif
+}
+
+KviKvsTreeNodeOperationStringSubstitution::~KviKvsTreeNodeOperationStringSubstitution()
+{
+#ifdef COMPILE_NEW_KVS
+ delete m_pLeft;
+ delete m_pRight;
+ delete m_pFlags;
+#endif
+}
+
+
+void KviKvsTreeNodeOperationStringSubstitution::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Binding Operator s///";
+#endif
+}
+
+
+void KviKvsTreeNodeOperationStringSubstitution::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s OperationStringSubstitution",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pLeft->dump(tmp.utf8().data());
+ m_pRight->dump(tmp.utf8().data());
+ m_pFlags->dump(tmp.utf8().data());
+#endif
+}
+
+bool KviKvsTreeNodeOperationStringSubstitution::execute(KviKvsRunTimeContext * c)
+{
+#ifdef COMPILE_NEW_KVS
+ KviKvsVariant vl;
+ if(!m_pLeft->evaluateReadOnly(c,&vl))return false;
+ KviKvsVariant vr;
+ if(!m_pRight->evaluateReadOnly(c,&vr))return false;
+ KviKvsVariant vf;
+ if(!m_pFlags->evaluateReadOnly(c,&vf))return false;
+ KviKvsRWEvaluationResult * target = m_pTargetData->evaluateReadWrite(c);
+ if(!target)return false;
+
+ QString szL,szR,szF;
+
+ vl.asString(szL);
+ vr.asString(szR);
+ vf.asString(szF);
+
+ QString str;
+ target->result()->asString(str);
+
+ bool bGlobal = szF.find('g',false) != -1;
+
+ QRegExp re(szL,szF.find('i',false) == -1,szF.find('w',false) != -1);
+ re.setMinimal(szF.find('m',false) != -1); // greedy or minimal ?
+
+ int idx = 0;
+
+ while((!str.isEmpty()) && (idx != -1))
+ {
+ int len;
+ idx = re.search(str,idx);
+ if(idx != -1)
+ {
+ len = re.matchedLength();
+ if(len == 0)
+ {
+ c->warning(this,__tr2qs("The regular expression matched a zero-length substring: this is not valid in the s/// operator, skipping"));
+ goto end_of_this_stuff;
+ }
+ str.remove(idx,len);
+
+ QString szReplaced;
+ const QChar * p2 = KviQString::nullTerminatedArray(szR);
+ const QChar * begin = p2;
+ while(p2->unicode())
+ {
+ if(p2->unicode() == '\\')
+ {
+ p2++;
+ if(p2->unicode() >= '0' && p2->unicode() <= '9')
+ {
+ szReplaced.append(QString(begin,(p2 - begin) - 1));
+ szReplaced.append(re.cap(p2->unicode() - '0'));
+ p2++;
+ begin = p2;
+ } else if(p2->unicode())p2++;
+ } else p2++;
+ }
+ if(begin != p2)szReplaced.append(QString(begin,p2 - begin));
+ str.insert(idx,szReplaced);
+ idx += szReplaced.length();
+
+ if(!bGlobal)goto end_of_this_stuff;
+ }
+ }
+end_of_this_stuff:
+ target->result()->setString(str);
+ delete target;
+#endif
+ return true;
+}
+
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_operation.h b/src/kvirc/kvs/kvi_kvs_treenode_operation.h
new file mode 100644
index 00000000..e4a4463d
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_operation.h
@@ -0,0 +1,296 @@
+#ifndef _KVI_KVS_TREENODE_OPERATION_H_
+#define _KVI_KVS_TREENODE_OPERATION_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_operation.h
+// Created on Thu 18 Dec 2003 22:36:00 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_treenode_instruction.h"
+
+class KviKvsTreeNodeData;
+class KviKvsRunTimeContext;
+
+class KVIRC_API KviKvsTreeNodeOperation : public KviKvsTreeNodeInstruction
+{
+public:
+ KviKvsTreeNodeOperation(const QChar * pLocation);
+ ~KviKvsTreeNodeOperation();
+protected:
+ KviKvsTreeNodeData * m_pTargetData; // can't be null
+public:
+ void setTargetVariableReference(KviKvsTreeNodeData * r);
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+};
+
+class KviKvsTreeNodeOperationAssignment : public KviKvsTreeNodeOperation
+{
+public:
+ KviKvsTreeNodeOperationAssignment(const QChar * pLocation,KviKvsTreeNodeData * pRightSide);
+ ~KviKvsTreeNodeOperationAssignment();
+protected:
+ KviKvsTreeNodeData * m_pRightSide; // can't be 0
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c);
+};
+
+class KviKvsTreeNodeOperationDecrement : public KviKvsTreeNodeOperation
+{
+public:
+ KviKvsTreeNodeOperationDecrement(const QChar * pLocation);
+ ~KviKvsTreeNodeOperationDecrement();
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c);
+};
+
+class KviKvsTreeNodeOperationIncrement : public KviKvsTreeNodeOperation
+{
+public:
+ KviKvsTreeNodeOperationIncrement(const QChar * pLocation);
+ ~KviKvsTreeNodeOperationIncrement();
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c);
+};
+
+class KviKvsTreeNodeOperationSelfAnd : public KviKvsTreeNodeOperation
+{
+public:
+ KviKvsTreeNodeOperationSelfAnd(const QChar * pLocation,KviKvsTreeNodeData * pRightSide);
+ ~KviKvsTreeNodeOperationSelfAnd();
+protected:
+ KviKvsTreeNodeData * m_pRightSide; // can't be 0
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c);
+};
+
+class KviKvsTreeNodeOperationSelfDivision : public KviKvsTreeNodeOperation
+{
+public:
+ KviKvsTreeNodeOperationSelfDivision(const QChar * pLocation,KviKvsTreeNodeData * pRightSide);
+ ~KviKvsTreeNodeOperationSelfDivision();
+protected:
+ KviKvsTreeNodeData * m_pRightSide; // can't be 0
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c);
+};
+
+class KviKvsTreeNodeOperationSelfModulus : public KviKvsTreeNodeOperation
+{
+public:
+ KviKvsTreeNodeOperationSelfModulus(const QChar * pLocation,KviKvsTreeNodeData * pRightSide);
+ ~KviKvsTreeNodeOperationSelfModulus();
+protected:
+ KviKvsTreeNodeData * m_pRightSide; // can't be 0
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c);
+};
+
+class KviKvsTreeNodeOperationSelfMultiplication : public KviKvsTreeNodeOperation
+{
+public:
+ KviKvsTreeNodeOperationSelfMultiplication(const QChar * pLocation,KviKvsTreeNodeData * pRightSide);
+ ~KviKvsTreeNodeOperationSelfMultiplication();
+protected:
+ KviKvsTreeNodeData * m_pRightSide; // can't be 0
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c);
+};
+
+class KviKvsTreeNodeOperationSelfOr : public KviKvsTreeNodeOperation
+{
+public:
+ KviKvsTreeNodeOperationSelfOr(const QChar * pLocation,KviKvsTreeNodeData * pRightSide);
+ ~KviKvsTreeNodeOperationSelfOr();
+protected:
+ KviKvsTreeNodeData * m_pRightSide; // can't be 0
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c);
+};
+
+class KviKvsTreeNodeOperationSelfShl : public KviKvsTreeNodeOperation
+{
+public:
+ KviKvsTreeNodeOperationSelfShl(const QChar * pLocation,KviKvsTreeNodeData * pRightSide);
+ ~KviKvsTreeNodeOperationSelfShl();
+protected:
+ KviKvsTreeNodeData * m_pRightSide; // can't be 0
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c);
+};
+
+class KviKvsTreeNodeOperationSelfShr : public KviKvsTreeNodeOperation
+{
+public:
+ KviKvsTreeNodeOperationSelfShr(const QChar * pLocation,KviKvsTreeNodeData * pRightSide);
+ ~KviKvsTreeNodeOperationSelfShr();
+protected:
+ KviKvsTreeNodeData * m_pRightSide; // can't be 0
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c);
+};
+
+class KviKvsTreeNodeOperationSelfSubtraction : public KviKvsTreeNodeOperation
+{
+public:
+ KviKvsTreeNodeOperationSelfSubtraction(const QChar * pLocation,KviKvsTreeNodeData * pRightSide);
+ ~KviKvsTreeNodeOperationSelfSubtraction();
+protected:
+ KviKvsTreeNodeData * m_pRightSide; // can't be 0
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c);
+};
+
+class KviKvsTreeNodeOperationSelfSum : public KviKvsTreeNodeOperation
+{
+public:
+ KviKvsTreeNodeOperationSelfSum(const QChar * pLocation,KviKvsTreeNodeData * pRightSide);
+ ~KviKvsTreeNodeOperationSelfSum();
+protected:
+ KviKvsTreeNodeData * m_pRightSide; // can't be 0
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c);
+};
+
+class KviKvsTreeNodeOperationSelfXor : public KviKvsTreeNodeOperation
+{
+public:
+ KviKvsTreeNodeOperationSelfXor(const QChar * pLocation,KviKvsTreeNodeData * pRightSide);
+ ~KviKvsTreeNodeOperationSelfXor();
+protected:
+ KviKvsTreeNodeData * m_pRightSide; // can't be 0
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c);
+};
+
+class KviKvsTreeNodeOperationStringAppend : public KviKvsTreeNodeOperation
+{
+public:
+ KviKvsTreeNodeOperationStringAppend(const QChar * pLocation,KviKvsTreeNodeData * pRightSide);
+ ~KviKvsTreeNodeOperationStringAppend();
+protected:
+ KviKvsTreeNodeData * m_pRightSide; // can't be 0
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c);
+};
+
+class KviKvsTreeNodeOperationArrayAppend : public KviKvsTreeNodeOperation
+{
+public:
+ KviKvsTreeNodeOperationArrayAppend(const QChar * pLocation,KviKvsTreeNodeData * pRightSide);
+ ~KviKvsTreeNodeOperationArrayAppend();
+protected:
+ KviKvsTreeNodeData * m_pRightSide; // can't be 0
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c);
+};
+
+class KviKvsTreeNodeOperationStringAppendWithComma : public KviKvsTreeNodeOperation
+{
+public:
+ KviKvsTreeNodeOperationStringAppendWithComma(const QChar * pLocation,KviKvsTreeNodeData * pRightSide);
+ ~KviKvsTreeNodeOperationStringAppendWithComma();
+protected:
+ KviKvsTreeNodeData * m_pRightSide; // can't be 0
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c);
+};
+
+class KviKvsTreeNodeOperationStringAppendWithSpace : public KviKvsTreeNodeOperation
+{
+public:
+ KviKvsTreeNodeOperationStringAppendWithSpace(const QChar * pLocation,KviKvsTreeNodeData * pRightSide);
+ ~KviKvsTreeNodeOperationStringAppendWithSpace();
+protected:
+ KviKvsTreeNodeData * m_pRightSide; // can't be 0
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c);
+};
+
+class KviKvsTreeNodeOperationStringTransliteration : public KviKvsTreeNodeOperation
+{
+public:
+ KviKvsTreeNodeOperationStringTransliteration(const QChar * pLocation,KviKvsTreeNodeData * pLeft,KviKvsTreeNodeData * pRight,KviKvsTreeNodeData * pFlags);
+ ~KviKvsTreeNodeOperationStringTransliteration();
+protected:
+ KviKvsTreeNodeData * m_pLeft; // can't be 0
+ KviKvsTreeNodeData * m_pRight; // can't be 0
+ KviKvsTreeNodeData * m_pFlags; // can't be 0
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c);
+};
+
+class KviKvsTreeNodeOperationStringSubstitution : public KviKvsTreeNodeOperation
+{
+public:
+ KviKvsTreeNodeOperationStringSubstitution(const QChar * pLocation,KviKvsTreeNodeData * pLeft,KviKvsTreeNodeData * pRight,KviKvsTreeNodeData * pFlags);
+ ~KviKvsTreeNodeOperationStringSubstitution();
+protected:
+ KviKvsTreeNodeData * m_pLeft; // can't be 0
+ KviKvsTreeNodeData * m_pRight; // can't be 0
+ KviKvsTreeNodeData * m_pFlags; // can't be 0
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c);
+};
+
+
+#endif //!_KVI_KVS_TREENODE_OPERATION_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_parameterreturn.cpp b/src/kvirc/kvs/kvi_kvs_treenode_parameterreturn.cpp
new file mode 100644
index 00000000..e4a1634c
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_parameterreturn.cpp
@@ -0,0 +1,88 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_parameterreturn.cpp
+// Created on Fri 30 Jan 2004 01:31:01 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+#include "kvi_kvs_treenode_parameterreturn.h"
+#include "kvi_kvs_treenode_datalist.h"
+#include "kvi_kvs_runtimecontext.h"
+#include "kvi_kvs_variantlist.h"
+#include "kvi_locale.h"
+
+KviKvsTreeNodeParameterReturn::KviKvsTreeNodeParameterReturn(const QChar * pLocation,KviKvsTreeNodeDataList * pDataList)
+: KviKvsTreeNodeInstruction(pLocation)
+{
+#ifdef COMPILE_NEW_KVS
+ m_pDataList = pDataList;
+ m_pDataList->setParent(this);
+#endif
+}
+
+KviKvsTreeNodeParameterReturn::~KviKvsTreeNodeParameterReturn()
+{
+#ifdef COMPILE_NEW_KVS
+ delete m_pDataList;
+#endif
+}
+
+void KviKvsTreeNodeParameterReturn::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Parameter Return Evaluation";
+#endif
+}
+
+
+void KviKvsTreeNodeParameterReturn::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s ParameterReturn",prefix);
+ QString tmp = prefix;
+ tmp += " ";
+ m_pDataList->dump(tmp.utf8().data());
+#endif
+}
+
+bool KviKvsTreeNodeParameterReturn::execute(KviKvsRunTimeContext * c)
+{
+#ifdef COMPILE_NEW_KVS
+ KviKvsVariantList lBuffer;
+ if(!m_pDataList->evaluate(c,&lBuffer))return false;
+ if(lBuffer.count() == 0)
+ {
+ c->returnValue()->setNothing();
+ return true;
+ }
+ if(lBuffer.count() == 1)
+ {
+ c->returnValue()->copyFrom(*(lBuffer.first()));
+ return true;
+ }
+
+ QString all;
+ lBuffer.allAsString(all);
+ c->returnValue()->setString(all);
+#endif
+ return true;
+}
+
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_parameterreturn.h b/src/kvirc/kvs/kvi_kvs_treenode_parameterreturn.h
new file mode 100644
index 00000000..4bd31275
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_parameterreturn.h
@@ -0,0 +1,45 @@
+#ifndef _KVI_KVS_TREENODE_PARAMETERRETURN_H_
+#define _KVI_KVS_TREENODE_PARAMETERRETURN_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_parameterreturn.h
+// Created on Fri 30 Jan 2004 01:31:01 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_kvs_treenode_instruction.h"
+
+class KviKvsTreeNodeDataList;
+
+class KVIRC_API KviKvsTreeNodeParameterReturn : public KviKvsTreeNodeInstruction
+{
+public:
+ KviKvsTreeNodeParameterReturn(const QChar * pLocation,KviKvsTreeNodeDataList * pDataList);
+ ~KviKvsTreeNodeParameterReturn();
+protected:
+ KviKvsTreeNodeDataList * m_pDataList;
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c);
+};
+
+#endif //!_KVI_KVS_TREENODE_PARAMETERRETURN_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_rebindingswitch.cpp b/src/kvirc/kvs/kvi_kvs_treenode_rebindingswitch.cpp
new file mode 100644
index 00000000..64e77690
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_rebindingswitch.cpp
@@ -0,0 +1,96 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_rebindingswitch.cpp
+// Created on Mon 15 Aug 2005 13:32:31 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_rebindingswitch.h"
+#include "kvi_kvs_treenode_data.h"
+#include "kvi_window.h"
+#include "kvi_app.h"
+#include "kvi_locale.h"
+#include "kvi_kvs_runtimecontext.h"
+
+KviKvsTreeNodeRebindingSwitch::KviKvsTreeNodeRebindingSwitch(const QChar * pLocation,KviKvsTreeNodeData * pTargetWindow,KviKvsTreeNodeCommand * pChildCommand)
+: KviKvsTreeNodeCommand(pLocation,pChildCommand->commandName())
+{
+ m_pTargetWindow = pTargetWindow;
+ m_pTargetWindow->setParent(this);
+ m_pChildCommand = pChildCommand;
+ m_pChildCommand->setParent(this);
+}
+
+KviKvsTreeNodeRebindingSwitch::~KviKvsTreeNodeRebindingSwitch()
+{
+ delete m_pTargetWindow;
+ delete m_pChildCommand;
+}
+
+
+void KviKvsTreeNodeRebindingSwitch::contextDescription(QString &szBuffer)
+{
+ szBuffer = "Window Rebinding Switch";
+}
+
+void KviKvsTreeNodeRebindingSwitch::dump(const char * prefix)
+{
+ debug("%sRebindingSwitch",prefix);
+ QString tmp = prefix;
+ tmp += " ";
+ m_pTargetWindow->dump(tmp.utf8().data());
+ m_pChildCommand->dump(tmp.utf8().data());
+}
+
+const QString & KviKvsTreeNodeRebindingSwitch::commandName()
+{
+ return m_pChildCommand->commandName();
+}
+
+bool KviKvsTreeNodeRebindingSwitch::execute(KviKvsRunTimeContext * c)
+{
+ KviKvsVariant vWindow;
+ if(!m_pTargetWindow->evaluateReadOnly(c,&vWindow))return false;
+
+ KviWindow * pNewWindow;
+
+ QString szWinId;
+ vWindow.asString(szWinId);
+ if(szWinId.isEmpty())
+ {
+ c->warning(this,__tr2qs("Empty window identifier specified in the standard rebinding switch: no rebinding performed"));
+ pNewWindow = 0;
+ } else {
+ pNewWindow = g_pApp->findWindow(szWinId.utf8().data());
+ }
+
+ pNewWindow = g_pApp->findWindow(szWinId.utf8().data());
+ KviWindow * pOldWindow = c->window();
+ if(pNewWindow)
+ c->setWindow(pNewWindow);
+ else
+ c->warning(this,__tr2qs("Invalid window specified in the standard rebinding switch: no rebinding performed"));
+ bool bRet = m_pChildCommand->execute(c);
+ c->setWindow(pOldWindow);
+ return bRet;
+}
+
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_rebindingswitch.h b/src/kvirc/kvs/kvi_kvs_treenode_rebindingswitch.h
new file mode 100644
index 00000000..c81dcd93
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_rebindingswitch.h
@@ -0,0 +1,49 @@
+#ifndef _KVI_KVS_TREENODE_REBINDINGSWITCH_H_
+#define _KVI_KVS_TREENODE_REBINDINGSWITCH_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_rebindingswitch.h
+// Created on Mon 15 Aug 2005 13:32:31 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_kvs_treenode_command.h"
+#include "kvi_qstring.h"
+
+class KviKvsTreeNodeData;
+class KviKvsRunTimeContext;
+
+class KVIRC_API KviKvsTreeNodeRebindingSwitch : public KviKvsTreeNodeCommand
+{
+public:
+ KviKvsTreeNodeRebindingSwitch(const QChar * pLocation,KviKvsTreeNodeData * pTargetWindow,KviKvsTreeNodeCommand * pChildCommand);
+ ~KviKvsTreeNodeRebindingSwitch();
+protected:
+ KviKvsTreeNodeData * m_pTargetWindow;
+ KviKvsTreeNodeCommand * m_pChildCommand;
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ const QString & commandName();
+ virtual bool execute(KviKvsRunTimeContext * c);
+};
+
+#endif //!_KVI_KVS_TREENODE_REBINDINGSWITCH_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_scopeoperator.cpp b/src/kvirc/kvs/kvi_kvs_treenode_scopeoperator.cpp
new file mode 100644
index 00000000..0d127611
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_scopeoperator.cpp
@@ -0,0 +1,148 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_scopeoperator.cpp
+// Created on Tue 07 Oct 2003 02:33:01 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_scopeoperator.h"
+
+#include "kvi_qstring.h"
+
+#include "kvi_kvs_variant.h"
+#include "kvi_kvs_runtimecontext.h"
+#include "kvi_kvs_kernel.h"
+#include "kvi_kvs_object.h"
+#include "kvi_kvs_object_controller.h"
+
+#include "kvi_locale.h"
+
+KviKvsTreeNodeScopeOperator::KviKvsTreeNodeScopeOperator(const QChar * pLocation,KviKvsTreeNodeData * pObject,KviKvsTreeNodeData * pData)
+: KviKvsTreeNodeData(pLocation)
+{
+ m_pObjectReference = pObject;
+ m_pObjectReference->setParent(this);
+ m_pRightSide = pData;
+ m_pRightSide->setParent(this);
+}
+
+KviKvsTreeNodeScopeOperator::~KviKvsTreeNodeScopeOperator()
+{
+ delete m_pObjectReference;
+ delete m_pRightSide;
+}
+
+void KviKvsTreeNodeScopeOperator::contextDescription(QString &szBuffer)
+{
+ szBuffer = "Scope Operator";
+}
+
+
+void KviKvsTreeNodeScopeOperator::dump(const char * prefix)
+{
+ debug("%s ScopeOperator",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pObjectReference->dump(tmp.utf8().data());
+ m_pRightSide->dump(tmp.utf8().data());
+}
+
+bool KviKvsTreeNodeScopeOperator::isReadOnly()
+{
+ return m_pRightSide->isReadOnly();
+}
+
+bool KviKvsTreeNodeScopeOperator::canEvaluateToObjectReference()
+{
+ return m_pRightSide->canEvaluateToObjectReference();
+}
+
+bool KviKvsTreeNodeScopeOperator::isFunctionCall()
+{
+ return m_pRightSide->isFunctionCall();
+}
+
+bool KviKvsTreeNodeScopeOperator::canEvaluateInObjectScope()
+{
+ return m_pObjectReference->canEvaluateInObjectScope();
+}
+
+KviKvsObject * KviKvsTreeNodeScopeOperator::objectFromVariant(KviKvsRunTimeContext * c,KviKvsVariant * v)
+{
+ kvs_hobject_t hObject;
+ if(!v->asHObject(hObject))
+ {
+ c->error(this,__tr2qs("The left side of the scope operator didn't evaluate as an object reference"));
+ return 0;
+ }
+
+ if(hObject == (kvs_hobject_t)0)
+ {
+ c->error(this,__tr2qs("The left side of the scope operator evaluated to a null object reference"));
+ return 0;
+ }
+
+ KviKvsObject * o = KviKvsKernel::instance()->objectController()->lookupObject(hObject);
+ if(!o)
+ {
+ c->error(this,__tr2qs("The left side of the scope operator evaluated to an invalid object reference (object doesn't exist)"));
+ return 0;
+ }
+ return o;
+}
+
+bool KviKvsTreeNodeScopeOperator::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+ KviKvsVariant ret;
+ if(!m_pObjectReference->evaluateReadOnly(c,&ret))return false;
+ KviKvsObject * o = objectFromVariant(c,&ret);
+ if(!o)return false;
+ return m_pRightSide->evaluateReadOnlyInObjectScope(o,c,pBuffer);
+}
+
+KviKvsRWEvaluationResult * KviKvsTreeNodeScopeOperator::evaluateReadWrite(KviKvsRunTimeContext * c)
+{
+ KviKvsVariant ret;
+ if(!m_pObjectReference->evaluateReadOnly(c,&ret))return 0;
+ KviKvsObject * o = objectFromVariant(c,&ret);
+ if(!o)return 0;
+ return m_pRightSide->evaluateReadWriteInObjectScope(o,c);
+}
+
+bool KviKvsTreeNodeScopeOperator::evaluateReadOnlyInObjectScope(KviKvsObject * o,KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+ KviKvsVariant ret;
+ if(!m_pObjectReference->evaluateReadOnlyInObjectScope(o,c,&ret))return false;
+ KviKvsObject * pObject = objectFromVariant(c,&ret);
+ if(!pObject)return false;
+ return m_pRightSide->evaluateReadOnlyInObjectScope(pObject,c,pBuffer);
+}
+
+KviKvsRWEvaluationResult * KviKvsTreeNodeScopeOperator::evaluateReadWriteInObjectScope(KviKvsObject * o,KviKvsRunTimeContext * c)
+{
+ KviKvsVariant ret;
+ if(!m_pObjectReference->evaluateReadOnlyInObjectScope(o,c,&ret))return 0;
+ KviKvsObject * pObject = objectFromVariant(c,&ret);
+ if(!pObject)return 0;
+ return m_pRightSide->evaluateReadWriteInObjectScope(pObject,c);
+}
+
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_scopeoperator.h b/src/kvirc/kvs/kvi_kvs_treenode_scopeoperator.h
new file mode 100644
index 00000000..30427266
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_scopeoperator.h
@@ -0,0 +1,58 @@
+#ifndef _KVI_KVS_TREENODE_SCOPEOPERATOR_H_
+#define _KVI_KVS_TREENODE_SCOPEOPERATOR_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_scopeoperator.h
+// Created on Tue 07 Oct 2003 02:33:01 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_kvs_treenode_data.h"
+
+class KviKvsObject;
+
+class KVIRC_API KviKvsTreeNodeScopeOperator : public KviKvsTreeNodeData
+{
+public:
+ KviKvsTreeNodeScopeOperator(const QChar * pLocation,KviKvsTreeNodeData * pObject,KviKvsTreeNodeData * pData);
+ ~KviKvsTreeNodeScopeOperator();
+public:
+ KviKvsTreeNodeData * m_pObjectReference; // can't be null
+ KviKvsTreeNodeData * m_pRightSide; // can't be null
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool isReadOnly(); // gets the m_pRightSide read only state
+ virtual bool canEvaluateToObjectReference(); // gets the m_pRightSide result
+ virtual bool isFunctionCall(); // gets the m_pRightSide result
+ virtual bool canEvaluateInObjectScope(); // gets the m_pObjectReference result
+ //virtual bool canReleaseResult(); // gets the m_pRightSide result
+
+ virtual bool evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer);
+ virtual KviKvsRWEvaluationResult * evaluateReadWrite(KviKvsRunTimeContext * c);
+ virtual bool evaluateReadOnlyInObjectScope(KviKvsObject * o,KviKvsRunTimeContext * c,KviKvsVariant * pBuffer);
+ virtual KviKvsRWEvaluationResult * evaluateReadWriteInObjectScope(KviKvsObject * o,KviKvsRunTimeContext * c);
+protected:
+ KviKvsObject * objectFromVariant(KviKvsRunTimeContext * c,KviKvsVariant * v);
+};
+
+
+#endif //!_KVI_KVS_TREENODE_SCOPEOPERATOR_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_simplecommand.cpp b/src/kvirc/kvs/kvi_kvs_treenode_simplecommand.cpp
new file mode 100644
index 00000000..dd055b9e
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_simplecommand.cpp
@@ -0,0 +1,58 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_simplecommand.cpp
+// Created on Thu 09 Oct 2003 02:12:18 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_simplecommand.h"
+#include "kvi_kvs_treenode_datalist.h"
+
+KviKvsTreeNodeSimpleCommand::KviKvsTreeNodeSimpleCommand(const QChar * pLocation,const QString &szCmdName,KviKvsTreeNodeDataList * params)
+: KviKvsTreeNodeCommandWithParameters(pLocation,szCmdName,params)
+{
+}
+
+KviKvsTreeNodeSimpleCommand::~KviKvsTreeNodeSimpleCommand()
+{
+}
+
+void KviKvsTreeNodeSimpleCommand::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Simple Command \"";
+ szBuffer += m_szCmdName;
+ szBuffer += "\"";
+#endif
+}
+
+
+void KviKvsTreeNodeSimpleCommand::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s SimpleCommand(%s)",prefix,m_szCmdName.utf8().data());
+ dumpSwitchList(prefix);
+ dumpParameterList(prefix);
+#endif
+}
+
+
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_simplecommand.h b/src/kvirc/kvs/kvi_kvs_treenode_simplecommand.h
new file mode 100644
index 00000000..d9aec78c
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_simplecommand.h
@@ -0,0 +1,43 @@
+#ifndef _KVI_KVS_TREENODE_SIMPLECOMMAND_H_
+#define _KVI_KVS_TREENODE_SIMPLECOMMAND_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_simplecommand.h
+// Created on Thu 09 Oct 2003 02:12:18 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_kvs_treenode_commandwithparameters.h"
+
+class KviKvsTreeNodeDataList;
+
+class KVIRC_API KviKvsTreeNodeSimpleCommand : public KviKvsTreeNodeCommandWithParameters
+{
+public:
+ KviKvsTreeNodeSimpleCommand(const QChar * pLocation,const QString &szCmdName,KviKvsTreeNodeDataList * params);
+ ~KviKvsTreeNodeSimpleCommand();
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+};
+
+
+#endif //!_KVI_KVS_TREENODE_SIMPLECOMMAND_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_singleparameteridentifier.cpp b/src/kvirc/kvs/kvi_kvs_treenode_singleparameteridentifier.cpp
new file mode 100644
index 00000000..d67c82bd
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_singleparameteridentifier.cpp
@@ -0,0 +1,74 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_singleparameteridentifier.cpp
+// Created on Tue 07 Oct 2003 03:47:11 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_singleparameteridentifier.h"
+#include "kvi_kvs_runtimecontext.h"
+#include "kvi_kvs_variant.h"
+
+KviKvsTreeNodeSingleParameterIdentifier::KviKvsTreeNodeSingleParameterIdentifier(const QChar * pLocation,int iStart)
+: KviKvsTreeNodeData(pLocation)
+{
+#ifdef COMPILE_NEW_KVS
+ m_iStart = iStart;
+#endif
+}
+
+KviKvsTreeNodeSingleParameterIdentifier::~KviKvsTreeNodeSingleParameterIdentifier()
+{
+}
+
+void KviKvsTreeNodeSingleParameterIdentifier::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Single Parameter Identifier \"$";
+ KviQString::appendFormatted(szBuffer,"%d",m_iStart);
+ szBuffer += "\"";
+#endif
+}
+
+
+void KviKvsTreeNodeSingleParameterIdentifier::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s SingleParameterIdentifier(%d)",prefix,m_iStart);
+#endif
+}
+
+bool KviKvsTreeNodeSingleParameterIdentifier::canEvaluateToObjectReference()
+{
+ return true;
+}
+
+bool KviKvsTreeNodeSingleParameterIdentifier::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ KviKvsVariant * v = c->parameterList()->at(m_iStart);
+ if(!v)pBuffer->setNothing();
+ else pBuffer->copyFrom(v);
+#endif
+ return true;
+}
+
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_singleparameteridentifier.h b/src/kvirc/kvs/kvi_kvs_treenode_singleparameteridentifier.h
new file mode 100644
index 00000000..fb7590c1
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_singleparameteridentifier.h
@@ -0,0 +1,50 @@
+#ifndef _KVI_KVS_TREENODE_SINGLEPARAMETERIDENTIFIER_H_
+#define _KVI_KVS_TREENODE_SINGLEPARAMETERIDENTIFIER_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_singleparameteridentifier.h
+// Created on Tue 07 Oct 2003 03:47:11 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_kvs_treenode_data.h"
+
+
+class KviKvsRunTimeContext;
+class KviKvsVariant;
+
+class KVIRC_API KviKvsTreeNodeSingleParameterIdentifier : public KviKvsTreeNodeData
+{
+public:
+ KviKvsTreeNodeSingleParameterIdentifier(const QChar * pLocation,int iStart);
+ ~KviKvsTreeNodeSingleParameterIdentifier();
+protected:
+ int m_iStart; // the index of the parameter wanted (always >= 0)
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+
+ virtual bool canEvaluateToObjectReference();
+ virtual bool evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer);
+};
+
+
+#endif //!_KVI_KVS_TREENODE_SINGLEPARAMETERIDENTIFIER_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_specialcommand.cpp b/src/kvirc/kvs/kvi_kvs_treenode_specialcommand.cpp
new file mode 100644
index 00000000..bfca30ac
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_specialcommand.cpp
@@ -0,0 +1,54 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_specialcommand.cpp
+// Created on Thu 09 Oct 2003 02:20:12 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_specialcommand.h"
+
+KviKvsTreeNodeSpecialCommand::KviKvsTreeNodeSpecialCommand(const QChar * pLocation,const QString &szCmdName)
+: KviKvsTreeNodeCommand(pLocation,szCmdName)
+{
+}
+
+KviKvsTreeNodeSpecialCommand::~KviKvsTreeNodeSpecialCommand()
+{
+}
+
+void KviKvsTreeNodeSpecialCommand::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Special Command \"";
+ szBuffer += m_szCmdName;
+ szBuffer += "\"";
+#endif
+}
+
+
+void KviKvsTreeNodeSpecialCommand::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s SpecialCommand(%s)",prefix,m_szCmdName.utf8().data());
+ dumpSwitchList(prefix);
+#endif
+}
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_specialcommand.h b/src/kvirc/kvs/kvi_kvs_treenode_specialcommand.h
new file mode 100644
index 00000000..9ac8867b
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_specialcommand.h
@@ -0,0 +1,41 @@
+#ifndef _KVI_KVS_TREENODE_SPECIALCOMMAND_H_
+#define _KVI_KVS_TREENODE_SPECIALCOMMAND_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_specialcommand.h
+// Created on Thu 09 Oct 2003 02:20:12 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_treenode_command.h"
+
+class KVIRC_API KviKvsTreeNodeSpecialCommand : public KviKvsTreeNodeCommand
+{
+public:
+ KviKvsTreeNodeSpecialCommand(const QChar * pLocation,const QString &szCmdName);
+ ~KviKvsTreeNodeSpecialCommand();
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+};
+
+#endif //!_KVI_KVS_TREENODE_SPECIALCOMMAND_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_specialcommandbreak.cpp b/src/kvirc/kvs/kvi_kvs_treenode_specialcommandbreak.cpp
new file mode 100644
index 00000000..ad750404
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_specialcommandbreak.cpp
@@ -0,0 +1,55 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_specialcommandbreak.cpp
+// Created on Thu 06 Nov 2003 12:15:00 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_specialcommandbreak.h"
+#include "kvi_kvs_runtimecontext.h"
+#include "kvi_locale.h"
+
+KviKvsTreeNodeSpecialCommandBreak::KviKvsTreeNodeSpecialCommandBreak(const QChar * pLocation)
+: KviKvsTreeNodeSpecialCommand(pLocation,"break")
+{
+}
+
+KviKvsTreeNodeSpecialCommandBreak::~KviKvsTreeNodeSpecialCommandBreak()
+{
+}
+
+void KviKvsTreeNodeSpecialCommandBreak::contextDescription(QString &szBuffer)
+{
+ szBuffer = "Special Command \"break\"";
+}
+
+
+void KviKvsTreeNodeSpecialCommandBreak::dump(const char * prefix)
+{
+ debug("%s SpecialCommandBreak",prefix);
+}
+
+bool KviKvsTreeNodeSpecialCommandBreak::execute(KviKvsRunTimeContext * c)
+{
+ c->setBreakPending();
+ return false;
+}
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_specialcommandbreak.h b/src/kvirc/kvs/kvi_kvs_treenode_specialcommandbreak.h
new file mode 100644
index 00000000..a4b061e1
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_specialcommandbreak.h
@@ -0,0 +1,45 @@
+#ifndef _KVI_KVS_TREENODE_SPECIALCOMMANDBREAK_H_
+#define _KVI_KVS_TREENODE_SPECIALCOMMANDBREAK_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_specialcommandbreak.h
+// Created on Thu 06 Nov 2003 12:15:00 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_treenode_specialcommand.h"
+
+class KviKvsRunTimeContext;
+
+class KVIRC_API KviKvsTreeNodeSpecialCommandBreak : public KviKvsTreeNodeSpecialCommand
+{
+public:
+ KviKvsTreeNodeSpecialCommandBreak(const QChar * pLocation);
+ ~KviKvsTreeNodeSpecialCommandBreak();
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c);
+};
+
+#endif //!_KVI_KVS_TREENODE_SPECIALCOMMANDBREAK_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_specialcommandclass.cpp b/src/kvirc/kvs/kvi_kvs_treenode_specialcommandclass.cpp
new file mode 100644
index 00000000..05d35edd
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_specialcommandclass.cpp
@@ -0,0 +1,157 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_specialcommandclass.cpp
+// Created on Fri 12 Aug 2005 03:23:31 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+#define __KVIRC__
+
+#include "kvi_locale.h"
+#include "kvi_kvs_variantlist.h"
+#include "kvi_kvs_variant.h"
+#include "kvi_kvs_treenode_specialcommandclass.h"
+#include "kvi_kvs_kernel.h"
+#include "kvi_kvs_object_controller.h"
+#include "kvi_kvs_object_class.h"
+
+KviKvsTreeNodeSpecialCommandClassFunctionDefinition::KviKvsTreeNodeSpecialCommandClassFunctionDefinition(const QChar * pLocation,const QString &szName,const QString &szBuffer,unsigned int uHandlerFlags)
+: KviKvsTreeNode(pLocation)
+{
+ m_uHandlerFlags = uHandlerFlags;
+ m_szName = szName;
+ m_szBuffer = szBuffer;
+}
+
+void KviKvsTreeNodeSpecialCommandClassFunctionDefinition::dump(const char * prefix)
+{
+ debug("%s SpecialCommandClassFunctionDefinition(%s)",prefix,m_szName.utf8().data());
+ debug("%s (command buffer with %d characters)",prefix,m_szBuffer.length());
+}
+
+void KviKvsTreeNodeSpecialCommandClassFunctionDefinition::contextDescription(QString &szBuffer)
+{
+ KviQString::sprintf(szBuffer,"Object Member Function Definition \"%Q\"",&m_szName);
+}
+
+KviKvsTreeNodeSpecialCommandClass::KviKvsTreeNodeSpecialCommandClass(const QChar * pLocation,KviKvsTreeNodeDataList * pParams)
+: KviKvsTreeNodeSpecialCommand(pLocation,"class")
+{
+ m_pParams = pParams;
+ m_pParams->setParent(this);
+ m_pFunctions = new KviPointerList<KviKvsTreeNodeSpecialCommandClassFunctionDefinition>;
+ m_pFunctions->setAutoDelete(true);
+}
+
+KviKvsTreeNodeSpecialCommandClass::~KviKvsTreeNodeSpecialCommandClass()
+{
+ delete m_pParams;
+ delete m_pFunctions;
+}
+
+void KviKvsTreeNodeSpecialCommandClass::addFunctionDefinition(KviKvsTreeNodeSpecialCommandClassFunctionDefinition * pDef)
+{
+ pDef->setParent(this);
+ m_pFunctions->append(pDef);
+}
+
+
+void KviKvsTreeNodeSpecialCommandClass::contextDescription(QString &szBuffer)
+{
+ szBuffer = "Special Command \"class\"";
+}
+
+void KviKvsTreeNodeSpecialCommandClass::dump(const char * prefix)
+{
+ debug("%s SpecialCommandClass",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pParams->dump(tmp.utf8().data());
+ for(KviKvsTreeNodeSpecialCommandClassFunctionDefinition * d = m_pFunctions->first();d;d = m_pFunctions->next())
+ d->dump(tmp.utf8().data());
+}
+
+bool KviKvsTreeNodeSpecialCommandClass::execute(KviKvsRunTimeContext * c)
+{
+ KviKvsVariantList l;
+ if(!m_pParams->evaluate(c,&l))return false;
+
+ KviKvsVariant * pClassName = l.first();
+ if(!pClassName)
+ {
+ c->error(this,__tr2qs("Missing class name"));
+ return false;
+ }
+ KviKvsVariant * pBaseClassName = l.next();
+
+ QString szClassName;
+ QString szBaseClassName;
+ pClassName->asString(szClassName);
+ if(pBaseClassName)
+ pBaseClassName->asString(szBaseClassName);
+
+ if(szClassName.isEmpty())
+ {
+ c->error(this,__tr2qs("Missing class name"));
+ return false;
+ }
+
+ if(szBaseClassName.isEmpty())szBaseClassName = "object";
+
+ // avoid infinite recursion in loading the base class
+ if(KviQString::equalCI(szBaseClassName,szClassName))
+ {
+ c->error(__tr2qs("A class can't be a subclass of itself"));
+ return false;
+ }
+
+ KviKvsObjectClass * pBaseClass = KviKvsKernel::instance()->objectController()->lookupClass(szBaseClassName);
+ if(!pBaseClass)
+ {
+ c->error(this,__tr2qs("Couln't find base class named \"%Q\""),&szBaseClassName);
+ return false;
+ }
+
+ // walk the inheritance tree of the base class in order to detect loops
+ KviKvsObjectClass * pClass = pBaseClass;
+ while(pClass)
+ {
+ if(KviQString::equalCI(pClass->name(),szClassName))
+ {
+ c->error(this,__tr2qs("Detected a loop in the inheritance tree of the base class \"%Q\": redefine that class first"),&szBaseClassName);
+ return false;
+ }
+ pClass = pClass->parentClass();
+ }
+
+ KviKvsObjectClass * pActualClass = KviKvsKernel::instance()->objectController()->lookupClass(szClassName,true);
+ if(pActualClass)
+ {
+ c->error(this,__tr2qs("Can't override the builtin class \"%Q\""),&szClassName);
+ return false;
+ }
+ pActualClass = new KviKvsObjectClass(pBaseClass,szClassName,0,false);
+
+ for(KviKvsTreeNodeSpecialCommandClassFunctionDefinition * d = m_pFunctions->first();d;d = m_pFunctions->next())
+ {
+ pActualClass->registerFunctionHandler(d->name(),d->buffer(),d->handlerFlags());
+ }
+ return true;
+}
+
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_specialcommandclass.h b/src/kvirc/kvs/kvi_kvs_treenode_specialcommandclass.h
new file mode 100644
index 00000000..0a8a69b5
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_specialcommandclass.h
@@ -0,0 +1,69 @@
+#ifndef _KVI_KVS_TREENODE_SPECIALCOMMANDCLASS_H_
+#define _KVI_KVS_TREENODE_SPECIALCOMMANDCLASS_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_specialcommandclass.h
+// Created on Fri 12 Aug 2005 03:23:31 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_treenode_specialcommand.h"
+#include "kvi_kvs_treenode_base.h"
+#include "kvi_kvs_treenode_datalist.h"
+
+class KviKvsRunTimeContext;
+
+class KVIRC_API KviKvsTreeNodeSpecialCommandClassFunctionDefinition : public KviKvsTreeNode
+{
+public:
+ KviKvsTreeNodeSpecialCommandClassFunctionDefinition(const QChar * pLocation,const QString &szName,const QString &szBuffer,unsigned int uHandlerFlags);
+ virtual ~KviKvsTreeNodeSpecialCommandClassFunctionDefinition(){};
+protected:
+ QString m_szName;
+ QString m_szBuffer;
+ unsigned int m_uHandlerFlags;
+public:
+ unsigned int handlerFlags(){ return m_uHandlerFlags; };
+ const QString & name(){ return m_szName; };
+ const QString & buffer(){ return m_szBuffer; };
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+};
+
+
+
+class KVIRC_API KviKvsTreeNodeSpecialCommandClass : public KviKvsTreeNodeSpecialCommand
+{
+public:
+ KviKvsTreeNodeSpecialCommandClass(const QChar * pLocation,KviKvsTreeNodeDataList * pParams);
+ virtual ~KviKvsTreeNodeSpecialCommandClass();
+protected:
+ KviKvsTreeNodeDataList * m_pParams;
+ KviPointerList<KviKvsTreeNodeSpecialCommandClassFunctionDefinition> * m_pFunctions;
+public:
+ void addFunctionDefinition(KviKvsTreeNodeSpecialCommandClassFunctionDefinition * pDef);
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c);
+};
+
+#endif //!_KVI_KVS_TREENODE_SPECIALCOMMANDCLASS_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_specialcommanddefpopup.cpp b/src/kvirc/kvs/kvi_kvs_treenode_specialcommanddefpopup.cpp
new file mode 100644
index 00000000..eea02bda
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_specialcommanddefpopup.cpp
@@ -0,0 +1,424 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_specialcommanddefpopup.cpp
+// Created on Fri 02 Jan 2004 14:09:00 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_specialcommanddefpopup.h"
+#include "kvi_kvs_treenode_expression.h"
+#include "kvi_kvs_treenode_instruction.h"
+#include "kvi_kvs_runtimecontext.h"
+#include "kvi_locale.h"
+#include "kvi_kvs_popupmanager.h"
+#include "kvi_kvs_popupmenu.h"
+#include "kvi_kvs_script.h"
+
+void KviKvsTreeNodeSpecialCommandDefpopupLabelExtpopup::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Label \"extpopup\" For Special Command \"defpopup\"";
+#endif
+}
+
+void KviKvsTreeNodeSpecialCommandDefpopupLabelExtpopup::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s SpecialCommandDefpopupLabelExtpopup",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ QString x = tmp;
+ x += "CONDITION: ";
+ x += m_szCondition;
+ debug("%s",x.utf8().data());
+ x = tmp;
+ x += "TEXT: ";
+ x += m_szText;
+ debug("%s",x.utf8().data());
+ x = tmp;
+ x += "NAME: ";
+ x += m_szName;
+ debug("%s",x.utf8().data());
+ x = tmp;
+ x += "ICON: ";
+ x += m_szIcon;
+ debug("%s",x.utf8().data());
+#endif
+}
+
+bool KviKvsTreeNodeSpecialCommandDefpopupLabelExtpopup::execute(KviKvsRunTimeContext * c,KviKvsPopupMenu * p)
+{
+#ifdef COMPILE_NEW_KVS
+ p->addExtPopup(m_szItemName,m_szName,m_szText,m_szIcon,m_szCondition);
+#endif
+ return true;
+}
+
+
+void KviKvsTreeNodeSpecialCommandDefpopupLabelItem::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Label \"item\" For Special Command \"defpopup\"";
+#endif
+}
+
+
+void KviKvsTreeNodeSpecialCommandDefpopupLabelItem::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s SpecialCommandDefpopupLabelItem",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ QString x = tmp;
+ x += "CONDITION: ";
+ x += m_szCondition;
+ debug("%s",x.utf8().data());
+ x = tmp;
+ x += "TEXT: ";
+ x += m_szText;
+ debug("%s",x.utf8().data());
+ x = tmp;
+ x += "ICON: ";
+ x += m_szIcon;
+ debug("%s",x.utf8().data());
+ x = tmp;
+ x += "INSTRUCTION: ";
+ x += m_szInstruction;
+ debug("%s",x.utf8().data());
+#endif
+}
+
+bool KviKvsTreeNodeSpecialCommandDefpopupLabelItem::execute(KviKvsRunTimeContext * c,KviKvsPopupMenu * p)
+{
+#ifdef COMPILE_NEW_KVS
+ p->addItem(m_szItemName,m_szInstruction,m_szText,m_szIcon,m_szCondition);
+#endif
+ return true;
+}
+
+void KviKvsTreeNodeSpecialCommandDefpopupLabelLabel::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Label \"label\" For Special Command \"defpopup\"";
+#endif
+}
+
+
+void KviKvsTreeNodeSpecialCommandDefpopupLabelLabel::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s SpecialCommandDefpopupLabelLabel",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ QString x = tmp;
+ x += "CONDITION: ";
+ x += m_szCondition;
+ debug("%s",x.utf8().data());
+ x = tmp;
+ x += "TEXT: ";
+ x += m_szText;
+ debug("%s",x.utf8().data());
+ x = tmp;
+ x += "ICON: ";
+ x += m_szIcon;
+ debug("%s",x.utf8().data());
+#endif
+}
+
+bool KviKvsTreeNodeSpecialCommandDefpopupLabelLabel::execute(KviKvsRunTimeContext * c,KviKvsPopupMenu * p)
+{
+#ifdef COMPILE_NEW_KVS
+ p->addLabel(m_szItemName,m_szText,m_szIcon,m_szCondition);
+#endif
+ return true;
+}
+
+
+
+
+void KviKvsTreeNodeSpecialCommandDefpopupLabelSeparator::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Label \"separator\" For Special Command \"defpopup\"";
+#endif
+}
+
+
+void KviKvsTreeNodeSpecialCommandDefpopupLabelSeparator::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s SpecialCommandDefpopupLabelSeparator",prefix);
+ QString tmp = prefix;
+ tmp.append(" CONDITION:");
+ tmp.append(m_szCondition);
+ debug("%s",tmp.utf8().data());
+#endif
+}
+
+bool KviKvsTreeNodeSpecialCommandDefpopupLabelSeparator::execute(KviKvsRunTimeContext * c,KviKvsPopupMenu * p)
+{
+#ifdef COMPILE_NEW_KVS
+ p->addSeparator(m_szItemName,m_szCondition);
+#endif
+ return true;
+}
+
+
+
+void KviKvsTreeNodeSpecialCommandDefpopupLabelEpilogue::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Label \"epilogue\" For Special Command \"defpopup\"";
+#endif
+}
+
+
+void KviKvsTreeNodeSpecialCommandDefpopupLabelEpilogue::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s SpecialCommandDefpopupLabelEpilogue",prefix);
+ QString tmp = prefix;
+ tmp.append(" INSTRUCTION: ");
+ tmp += m_szInstruction;
+ debug("%s",tmp.utf8().data());
+#endif
+}
+
+bool KviKvsTreeNodeSpecialCommandDefpopupLabelEpilogue::execute(KviKvsRunTimeContext * c,KviKvsPopupMenu * p)
+{
+#ifdef COMPILE_NEW_KVS
+ p->addEpilogue(m_szItemName,m_szInstruction);
+#endif
+ return true;
+}
+
+
+void KviKvsTreeNodeSpecialCommandDefpopupLabelPrologue::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Label \"prologue\" For Special Command \"defpopup\"";
+#endif
+}
+
+
+
+void KviKvsTreeNodeSpecialCommandDefpopupLabelPrologue::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s SpecialCommandDefpopupLabelPrologue",prefix);
+ QString tmp = prefix;
+ tmp.append(" INSTRUCTION: ");
+ tmp += m_szInstruction;
+ debug("%s",tmp.utf8().data());
+#endif
+}
+
+bool KviKvsTreeNodeSpecialCommandDefpopupLabelPrologue::execute(KviKvsRunTimeContext * c,KviKvsPopupMenu * p)
+{
+#ifdef COMPILE_NEW_KVS
+ p->addPrologue(m_szItemName,m_szInstruction);
+#endif
+ return true;
+}
+
+
+
+
+
+
+
+
+
+KviKvsTreeNodeSpecialCommandDefpopupLabelPopup::KviKvsTreeNodeSpecialCommandDefpopupLabelPopup(const QChar * pLocation)
+: KviKvsTreeNodeSpecialCommandDefpopupConditionalLabelWithTextAndIcon(pLocation,QString::null,QString::null,QString::null,QString::null)
+{
+#ifdef COMPILE_NEW_KVS
+ m_pLabels = new KviPointerList<KviKvsTreeNodeSpecialCommandDefpopupLabel>;
+ m_pLabels->setAutoDelete(true);
+#endif
+}
+
+KviKvsTreeNodeSpecialCommandDefpopupLabelPopup::~KviKvsTreeNodeSpecialCommandDefpopupLabelPopup()
+{
+#ifdef COMPILE_NEW_KVS
+ delete m_pLabels;
+#endif
+}
+
+void KviKvsTreeNodeSpecialCommandDefpopupLabelPopup::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Label \"popup\" For Special Command \"defpopup\"";
+#endif
+}
+
+
+void KviKvsTreeNodeSpecialCommandDefpopupLabelPopup::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s SpecialCommandDefpopupLabelPopup",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ QString x = tmp;
+ x += "CONDITION: ";
+ x += m_szCondition;
+ debug(x.utf8().data());
+ x = tmp;
+ x += "TEXT: ";
+ x += m_szText;
+ debug(x.utf8().data());
+ x = tmp;
+ x += "ICON: ";
+ x += m_szIcon;
+ debug(x.utf8().data());
+ for(KviKvsTreeNodeSpecialCommandDefpopupLabel * l = m_pLabels->first();l;l = m_pLabels->next())
+ l->dump(tmp.utf8().data());
+#endif
+}
+
+void KviKvsTreeNodeSpecialCommandDefpopupLabelPopup::addLabel(KviKvsTreeNodeSpecialCommandDefpopupLabel * pLabel)
+{
+#ifdef COMPILE_NEW_KVS
+ pLabel->setParent(this);
+ m_pLabels->append(pLabel);
+#endif
+}
+
+bool KviKvsTreeNodeSpecialCommandDefpopupLabelPopup::execute(KviKvsRunTimeContext * c,KviKvsPopupMenu * p)
+{
+#ifdef COMPILE_NEW_KVS
+ // the name will be reset anyway
+ KviKvsPopupMenu * pNew = p->addPopup(m_szItemName,m_szText,m_szIcon,m_szCondition);
+ return fill(c,pNew);
+#else
+ return false;
+#endif
+}
+
+bool KviKvsTreeNodeSpecialCommandDefpopupLabelPopup::fill(KviKvsRunTimeContext* c,KviKvsPopupMenu * p)
+{
+#ifdef COMPILE_NEW_KVS
+ for(KviKvsTreeNodeSpecialCommandDefpopupLabel * l = m_pLabels->first();l;l = m_pLabels->next())
+ {
+ if(!l->execute(c,p))return false;
+ }
+#endif
+ return true;
+}
+
+
+
+
+
+
+
+
+KviKvsTreeNodeSpecialCommandDefpopup::KviKvsTreeNodeSpecialCommandDefpopup(const QChar * pLocation,KviKvsTreeNodeData * pPopupName,KviKvsTreeNodeSpecialCommandDefpopupLabelPopup * pMainPopup)
+: KviKvsTreeNodeSpecialCommand(pLocation,"defpopup")
+{
+#ifdef COMPILE_NEW_KVS
+ m_pPopupName = pPopupName;
+ m_pPopupName->setParent(this);
+ m_pMainPopup = pMainPopup;
+ m_pMainPopup->setParent(this);
+#endif
+}
+
+KviKvsTreeNodeSpecialCommandDefpopup::~KviKvsTreeNodeSpecialCommandDefpopup()
+{
+#ifdef COMPILE_NEW_KVS
+ delete m_pPopupName;
+ delete m_pMainPopup;
+#endif
+}
+
+void KviKvsTreeNodeSpecialCommandDefpopup::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Special Command \"defpopup\"";
+#endif
+}
+
+
+void KviKvsTreeNodeSpecialCommandDefpopup::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s SpecialCommandDefpopup",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pPopupName->dump(tmp.utf8().data());
+ m_pMainPopup->dump(tmp.utf8().data());
+#endif
+}
+
+bool KviKvsTreeNodeSpecialCommandDefpopup::execute(KviKvsRunTimeContext * c)
+{
+#ifdef COMPILE_NEW_KVS
+ KviKvsVariant v;
+ if(!m_pPopupName->evaluateReadOnly(c,&v))return false;
+ QString szName;
+ v.asString(szName);
+
+ KviKvsSwitchList swl;
+ if(m_pSwitches)
+ {
+ if(!(m_pSwitches->evaluate(c,&swl)))return false;
+ }
+
+ KviKvsPopupMenu * pPopup = KviKvsPopupManager::instance()->lookup(szName);
+ bool bWasAlreadyThere;
+ if(!pPopup)
+ {
+ if(m_pMainPopup->isEmpty())return true; // we wanted to remove it anyway: exit silently
+ // we want to create it
+ pPopup = new KviKvsPopupMenu(szName);
+ KviKvsPopupManager::instance()->add(szName,pPopup);
+ bWasAlreadyThere = false;
+ } else {
+ bWasAlreadyThere = true;
+
+ if(pPopup->isLocked())
+ {
+ c->error(__tr2qs("The popup '%s' is actually locked: 'self-modifications' are not allowed"),&szName);
+ return false;
+ }
+
+ if(m_pMainPopup->isEmpty())
+ {
+ // we want to remove it
+ KviKvsPopupManager::instance()->remove(szName);
+ return true;
+ }
+ // we want to (re)create it
+
+ if(!swl.find('m',"--merge"))pPopup->doClear();
+ }
+
+
+ if(!m_pMainPopup->fill(c,pPopup))
+ {
+ if(!bWasAlreadyThere)KviKvsPopupManager::instance()->remove(szName);
+ return false;
+ }
+#endif
+ return true;
+}
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_specialcommanddefpopup.h b/src/kvirc/kvs/kvi_kvs_treenode_specialcommanddefpopup.h
new file mode 100644
index 00000000..53a02fbc
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_specialcommanddefpopup.h
@@ -0,0 +1,193 @@
+#ifndef _KVI_KVS_TREENODE_SPECIALCOMMANDDEFPOPUP_H_
+#define _KVI_KVS_TREENODE_SPECIALCOMMANDDEFPOPUP_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_specialcommanddefpopup.h
+// Created on Fri 02 Jan 2004 13:54:00 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_treenode.h"
+#include "kvi_kvs_treenode_specialcommand.h"
+
+class KviKvsTreeNodeExpression;
+class KviKvsTreeNodeInstruction;
+class KviKvsRunTimeContext;
+class KviKvsVariant;
+class KviKvsPopupMenu;
+
+
+class KVIRC_API KviKvsTreeNodeSpecialCommandDefpopupLabel : public KviKvsTreeNode
+{
+public:
+ QString m_szItemName;
+public:
+ KviKvsTreeNodeSpecialCommandDefpopupLabel(const QChar * pLocation,const QString &szItemName)
+ : KviKvsTreeNode(pLocation), m_szItemName(szItemName) {};
+ ~KviKvsTreeNodeSpecialCommandDefpopupLabel(){};
+public:
+ void setItemName(const QString &szItemName){ m_szItemName = szItemName; };
+ virtual bool execute(KviKvsRunTimeContext * c,KviKvsPopupMenu * p) = 0;
+};
+
+class KVIRC_API KviKvsTreeNodeSpecialCommandDefpopupConditionalLabel : public KviKvsTreeNodeSpecialCommandDefpopupLabel
+{
+protected:
+ QString m_szCondition; // may be null!
+public:
+ KviKvsTreeNodeSpecialCommandDefpopupConditionalLabel(const QChar * pLocation,const QString &szCondition,const QString &szItemName)
+ : KviKvsTreeNodeSpecialCommandDefpopupLabel(pLocation,szItemName), m_szCondition(szCondition) {};
+ ~KviKvsTreeNodeSpecialCommandDefpopupConditionalLabel(){};
+public:
+ void setCondition(const QString &szCondition){ m_szCondition = szCondition; };
+};
+
+class KVIRC_API KviKvsTreeNodeSpecialCommandDefpopupLabelSeparator : public KviKvsTreeNodeSpecialCommandDefpopupConditionalLabel
+{
+public:
+ KviKvsTreeNodeSpecialCommandDefpopupLabelSeparator(const QChar * pLocation,const QString &szCondition,const QString &szItemName)
+ : KviKvsTreeNodeSpecialCommandDefpopupConditionalLabel(pLocation,szCondition,szItemName){};
+ ~KviKvsTreeNodeSpecialCommandDefpopupLabelSeparator(){};
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c,KviKvsPopupMenu * p);
+};
+
+class KVIRC_API KviKvsTreeNodeSpecialCommandDefpopupConditionalLabelWithTextAndIcon : public KviKvsTreeNodeSpecialCommandDefpopupConditionalLabel
+{
+protected:
+ QString m_szText;
+ QString m_szIcon;
+public:
+ KviKvsTreeNodeSpecialCommandDefpopupConditionalLabelWithTextAndIcon(const QChar * pLocation,const QString &szCondition,const QString &szText,const QString &szIcon,const QString &szItemName)
+ : KviKvsTreeNodeSpecialCommandDefpopupConditionalLabel(pLocation,szCondition,szItemName), m_szText(szText), m_szIcon(szIcon){};
+ ~KviKvsTreeNodeSpecialCommandDefpopupConditionalLabelWithTextAndIcon(){};
+public:
+ void setText(const QString &szText){ m_szText = szText; };
+ void setIcon(const QString &szIcon){ m_szIcon = szIcon; };
+};
+
+class KVIRC_API KviKvsTreeNodeSpecialCommandDefpopupLabelExtpopup : public KviKvsTreeNodeSpecialCommandDefpopupConditionalLabelWithTextAndIcon
+{
+protected:
+ QString m_szName;
+public:
+ KviKvsTreeNodeSpecialCommandDefpopupLabelExtpopup(const QChar * pLocation,const QString &szCondition,const QString &szText,const QString &szIcon,const QString &szName,const QString &szItemName)
+ : KviKvsTreeNodeSpecialCommandDefpopupConditionalLabelWithTextAndIcon(pLocation,szCondition,szText,szIcon,szItemName), m_szName(szName){};
+ ~KviKvsTreeNodeSpecialCommandDefpopupLabelExtpopup(){};
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c,KviKvsPopupMenu * p);
+};
+
+class KVIRC_API KviKvsTreeNodeSpecialCommandDefpopupLabelItem : public KviKvsTreeNodeSpecialCommandDefpopupConditionalLabelWithTextAndIcon
+{
+protected:
+ QString m_szInstruction;
+public:
+ KviKvsTreeNodeSpecialCommandDefpopupLabelItem(const QChar * pLocation,const QString &szCondition,const QString &szText,const QString &szIcon,const QString &szInstruction,const QString &szItemName)
+ : KviKvsTreeNodeSpecialCommandDefpopupConditionalLabelWithTextAndIcon(pLocation,szCondition,szText,szIcon,szItemName), m_szInstruction(szInstruction) {};
+ ~KviKvsTreeNodeSpecialCommandDefpopupLabelItem(){};
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c,KviKvsPopupMenu * p);
+};
+
+
+class KVIRC_API KviKvsTreeNodeSpecialCommandDefpopupLabelLabel : public KviKvsTreeNodeSpecialCommandDefpopupConditionalLabelWithTextAndIcon
+{
+public:
+ KviKvsTreeNodeSpecialCommandDefpopupLabelLabel(const QChar * pLocation,const QString &szCondition,const QString &szText,const QString &szIcon,const QString &szItemName)
+ : KviKvsTreeNodeSpecialCommandDefpopupConditionalLabelWithTextAndIcon(pLocation,szCondition,szText,szIcon,szItemName){};
+ ~KviKvsTreeNodeSpecialCommandDefpopupLabelLabel(){};
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c,KviKvsPopupMenu * p);
+};
+
+
+
+class KVIRC_API KviKvsTreeNodeSpecialCommandDefpopupLabelPrologue : public KviKvsTreeNodeSpecialCommandDefpopupLabel
+{
+protected:
+ QString m_szInstruction;
+public:
+ KviKvsTreeNodeSpecialCommandDefpopupLabelPrologue(const QChar * pLocation,const QString &szInstruction,const QString &szItemName)
+ : KviKvsTreeNodeSpecialCommandDefpopupLabel(pLocation,szItemName), m_szInstruction(szInstruction){};
+ ~KviKvsTreeNodeSpecialCommandDefpopupLabelPrologue(){};
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c,KviKvsPopupMenu * p);
+};
+
+class KVIRC_API KviKvsTreeNodeSpecialCommandDefpopupLabelEpilogue : public KviKvsTreeNodeSpecialCommandDefpopupLabel
+{
+protected:
+ QString m_szInstruction;
+public:
+ KviKvsTreeNodeSpecialCommandDefpopupLabelEpilogue(const QChar * pLocation,const QString &szInstruction,const QString &szItemName)
+ : KviKvsTreeNodeSpecialCommandDefpopupLabel(pLocation,szItemName), m_szInstruction(szInstruction){};
+ ~KviKvsTreeNodeSpecialCommandDefpopupLabelEpilogue(){};
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c,KviKvsPopupMenu * p);
+};
+
+
+class KVIRC_API KviKvsTreeNodeSpecialCommandDefpopupLabelPopup : public KviKvsTreeNodeSpecialCommandDefpopupConditionalLabelWithTextAndIcon
+{
+public:
+ KviKvsTreeNodeSpecialCommandDefpopupLabelPopup(const QChar * pLocation);
+ ~KviKvsTreeNodeSpecialCommandDefpopupLabelPopup();
+protected:
+ KviPointerList<KviKvsTreeNodeSpecialCommandDefpopupLabel> * m_pLabels;
+public:
+ bool isEmpty(){ return m_pLabels->isEmpty(); };
+ void addLabel(KviKvsTreeNodeSpecialCommandDefpopupLabel * pLabel);
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c,KviKvsPopupMenu * p);
+ bool fill(KviKvsRunTimeContext * c,KviKvsPopupMenu * p);
+};
+
+
+class KVIRC_API KviKvsTreeNodeSpecialCommandDefpopup : public KviKvsTreeNodeSpecialCommand
+{
+public:
+ KviKvsTreeNodeSpecialCommandDefpopup(const QChar * pLocation,KviKvsTreeNodeData * pPopupName,KviKvsTreeNodeSpecialCommandDefpopupLabelPopup * pMainPopup);
+ ~KviKvsTreeNodeSpecialCommandDefpopup();
+private:
+ KviKvsTreeNodeData * m_pPopupName; // can't be zero
+ KviKvsTreeNodeSpecialCommandDefpopupLabelPopup * m_pMainPopup;
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c);
+};
+
+#endif //!_KVI_KVS_TREENODE_SPECIALCOMMANDDEFPOPUP_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_specialcommanddo.cpp b/src/kvirc/kvs/kvi_kvs_treenode_specialcommanddo.cpp
new file mode 100644
index 00000000..5b083c80
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_specialcommanddo.cpp
@@ -0,0 +1,87 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_specialcommanddo.cpp
+// Created on Thu 06 Nov 2003 14:09:53 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_specialcommanddo.h"
+#include "kvi_kvs_treenode_expression.h"
+#include "kvi_kvs_treenode_instruction.h"
+#include "kvi_kvs_runtimecontext.h"
+#include "kvi_locale.h"
+
+KviKvsTreeNodeSpecialCommandDo::KviKvsTreeNodeSpecialCommandDo(const QChar * pLocation,KviKvsTreeNodeExpression * e,KviKvsTreeNodeInstruction * i)
+: KviKvsTreeNodeSpecialCommand(pLocation,"do")
+{
+ m_pExpression = e;
+ m_pExpression->setParent(this);
+ m_pInstruction = i;
+ if(i)m_pInstruction->setParent(this);
+}
+
+KviKvsTreeNodeSpecialCommandDo::~KviKvsTreeNodeSpecialCommandDo()
+{
+ delete m_pExpression;
+ if(m_pInstruction)delete m_pInstruction;
+}
+
+void KviKvsTreeNodeSpecialCommandDo::contextDescription(QString &szBuffer)
+{
+ szBuffer = "Special Command \"do\"";
+}
+
+void KviKvsTreeNodeSpecialCommandDo::dump(const char * prefix)
+{
+ debug("%s SpecialCommandDo",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pExpression->dump(tmp);
+ if(m_pInstruction)m_pInstruction->dump(tmp);
+}
+
+bool KviKvsTreeNodeSpecialCommandDo::execute(KviKvsRunTimeContext * c)
+{
+ for(;;)
+ {
+ if(m_pInstruction)
+ {
+ if(!m_pInstruction->execute(c))
+ {
+ if(c->error())return false;
+
+ if(c->breakPending())
+ {
+ c->handleBreak();
+ return true;
+ }
+ return false;
+ }
+ }
+
+ KviKvsVariant v;
+ if(!m_pExpression->evaluateReadOnly(c,&v))return false;
+ if(!v.asBoolean())break;
+ }
+ return true;
+}
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_specialcommanddo.h b/src/kvirc/kvs/kvi_kvs_treenode_specialcommanddo.h
new file mode 100644
index 00000000..dde8d007
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_specialcommanddo.h
@@ -0,0 +1,51 @@
+#ifndef _KVI_KVS_TREENODE_SPECIALCOMMANDDO_H_
+#define _KVI_KVS_TREENODE_SPECIALCOMMANDDO_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_specialcommanddo.h
+// Created on Thu 06 Nov 2003 14:09:53 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_treenode_specialcommand.h"
+
+class KviKvsTreeNodeExpression;
+class KviKvsTreeNodeInstruction;
+class KviKvsRunTimeContext;
+
+class KVIRC_API KviKvsTreeNodeSpecialCommandDo : public KviKvsTreeNodeSpecialCommand
+{
+public:
+ KviKvsTreeNodeSpecialCommandDo(const QChar * pLocation,KviKvsTreeNodeExpression * e,KviKvsTreeNodeInstruction * i);
+ ~KviKvsTreeNodeSpecialCommandDo();
+private:
+ KviKvsTreeNodeExpression * m_pExpression; // can't be 0
+ KviKvsTreeNodeInstruction * m_pInstruction; // may be 0
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c);
+};
+
+
+#endif //!_KVI_KVS_TREENODE_SPECIALCOMMANDDO_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_specialcommandfor.cpp b/src/kvirc/kvs/kvi_kvs_treenode_specialcommandfor.cpp
new file mode 100644
index 00000000..82526bc6
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_specialcommandfor.cpp
@@ -0,0 +1,133 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_specialcommandfor.cpp
+// Created on Fri 07 Nov 2003 11:48:11 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_specialcommandfor.h"
+#include "kvi_kvs_treenode_expression.h"
+#include "kvi_kvs_treenode_instruction.h"
+#include "kvi_kvs_runtimecontext.h"
+#include "kvi_locale.h"
+
+KviKvsTreeNodeSpecialCommandFor::KviKvsTreeNodeSpecialCommandFor(const QChar * pLocation,KviKvsTreeNodeInstruction * pInit,KviKvsTreeNodeExpression * pCond,KviKvsTreeNodeInstruction * pUpd,KviKvsTreeNodeInstruction * pLoop)
+: KviKvsTreeNodeSpecialCommand(pLocation,"for")
+{
+ m_pInitialization = pInit;
+ if(m_pInitialization)m_pInitialization->setParent(this);
+ m_pCondition = pCond;
+ if(m_pCondition)m_pCondition->setParent(this);
+ m_pUpdate = pUpd;
+ if(m_pUpdate)m_pUpdate->setParent(this);
+ m_pLoop = pLoop;
+ if(m_pLoop)m_pLoop->setParent(this);
+}
+
+KviKvsTreeNodeSpecialCommandFor::~KviKvsTreeNodeSpecialCommandFor()
+{
+ if(m_pInitialization)delete m_pInitialization;
+ if(m_pCondition)delete m_pCondition;
+ if(m_pUpdate)delete m_pUpdate;
+ if(m_pLoop)delete m_pLoop;
+}
+
+void KviKvsTreeNodeSpecialCommandFor::contextDescription(QString &szBuffer)
+{
+ szBuffer = "Special Command \"for\"";
+}
+
+void KviKvsTreeNodeSpecialCommandFor::dump(const char * prefix)
+{
+ debug("%s SpecialCommandFor",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ if(m_pInitialization)m_pInitialization->dump(tmp.utf8().data());
+ if(m_pCondition)m_pCondition->dump(tmp.utf8().data());
+ if(m_pUpdate)m_pUpdate->dump(tmp.utf8().data());
+ if(m_pLoop)m_pLoop->dump(tmp.utf8().data());
+}
+
+bool KviKvsTreeNodeSpecialCommandFor::execute(KviKvsRunTimeContext * c)
+{
+ if(m_pInitialization)
+ {
+ if(!m_pInitialization->execute(c))
+ {
+ // break allowed also here
+ if(c->error())return false;
+
+ if(c->breakPending())
+ {
+ c->handleBreak();
+ return true;
+ }
+
+ return false; // propagate false ret value
+ }
+ }
+
+ for(;;)
+ {
+ if(m_pCondition)
+ {
+ KviKvsVariant v;
+ if(!m_pCondition->evaluateReadOnly(c,&v))return false;
+ if(!v.asBoolean())return true;
+ }
+
+ if(m_pLoop)
+ {
+ if(!m_pLoop->execute(c))
+ {
+ if(c->error())return false;
+
+ if(c->breakPending())
+ {
+ c->handleBreak();
+ return true;
+ }
+
+ return false; // propagate false ret value
+ }
+ }
+
+ if(m_pUpdate)
+ {
+ if(!m_pUpdate->execute(c))
+ {
+ // break allowed also here
+ if(c->error())return false;
+
+ if(c->breakPending())
+ {
+ c->handleBreak();
+ return true;
+ }
+
+ return false; // propagate false ret value
+ }
+ }
+ }
+ // not reached
+ return false;
+}
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_specialcommandfor.h b/src/kvirc/kvs/kvi_kvs_treenode_specialcommandfor.h
new file mode 100644
index 00000000..4c53f2cf
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_specialcommandfor.h
@@ -0,0 +1,53 @@
+#ifndef _KVI_KVS_TREENODE_SPECIALCOMMANDFOR_H_
+#define _KVI_KVS_TREENODE_SPECIALCOMMANDFOR_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_specialcommandfor.h
+// Created on Fri 07 Nov 2003 11:48:11 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_treenode_specialcommand.h"
+
+class KviKvsTreeNodeExpression;
+class KviKvsTreeNodeInstruction;
+class KviKvsRunTimeContext;
+
+class KVIRC_API KviKvsTreeNodeSpecialCommandFor : public KviKvsTreeNodeSpecialCommand
+{
+public:
+ KviKvsTreeNodeSpecialCommandFor(const QChar * pLocation,KviKvsTreeNodeInstruction * pInit,KviKvsTreeNodeExpression * pCond,KviKvsTreeNodeInstruction * pUpd,KviKvsTreeNodeInstruction * pLoop);
+ ~KviKvsTreeNodeSpecialCommandFor();
+private:
+ KviKvsTreeNodeInstruction * m_pInitialization; // can be 0
+ KviKvsTreeNodeExpression * m_pCondition; // can be 0
+ KviKvsTreeNodeInstruction * m_pUpdate; // can be 0
+ KviKvsTreeNodeInstruction * m_pLoop; // can be 0
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c);
+};
+
+
+#endif //!_KVI_KVS_TREENODE_SPECIALCOMMANDFOR_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_specialcommandforeach.cpp b/src/kvirc/kvs/kvi_kvs_treenode_specialcommandforeach.cpp
new file mode 100644
index 00000000..db98e39c
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_specialcommandforeach.cpp
@@ -0,0 +1,191 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_specialcommandforeach.cpp
+// Created on Fri 07 Nov 2003 11:48:11 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_specialcommandforeach.h"
+#include "kvi_kvs_treenode_data.h"
+#include "kvi_kvs_treenode_datalist.h"
+#include "kvi_kvs_treenode_instruction.h"
+#include "kvi_kvs_treenode_switchlist.h"
+#include "kvi_kvs_runtimecontext.h"
+#include "kvi_locale.h"
+
+KviKvsTreeNodeSpecialCommandForeach::KviKvsTreeNodeSpecialCommandForeach(const QChar * pLocation,KviKvsTreeNodeData * pVar,KviKvsTreeNodeDataList * pArgs,KviKvsTreeNodeInstruction * pLoop)
+: KviKvsTreeNodeSpecialCommand(pLocation,"foreach")
+{
+ m_pIterationVariable = pVar;
+ m_pIterationVariable->setParent(this);
+ m_pIterationData = pArgs;
+ m_pIterationData->setParent(this);
+ m_pLoop = pLoop;
+ m_pLoop->setParent(this);
+}
+
+KviKvsTreeNodeSpecialCommandForeach::~KviKvsTreeNodeSpecialCommandForeach()
+{
+ delete m_pIterationVariable;
+ delete m_pIterationData;
+ delete m_pLoop;
+}
+
+void KviKvsTreeNodeSpecialCommandForeach::contextDescription(QString &szBuffer)
+{
+ szBuffer = "Special Command \"foreach\"";
+}
+
+void KviKvsTreeNodeSpecialCommandForeach::dump(const char * prefix)
+{
+ debug("%s SpecialCommandForeach",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pIterationVariable->dump(tmp.utf8().data());
+ m_pIterationData->dump(tmp.utf8().data());
+ m_pLoop->dump(tmp.utf8().data());
+}
+
+bool KviKvsTreeNodeSpecialCommandForeach::execute(KviKvsRunTimeContext * c)
+{
+ KviKvsRWEvaluationResult * v = m_pIterationVariable->evaluateReadWrite(c);
+ if(!v)return false;
+
+ KviKvsVariantList l;
+ l.setAutoDelete(true);
+ if(!m_pIterationData->evaluate(c,&l))
+ {
+ delete v;
+ return false;
+ }
+
+ KviKvsSwitchList swl;
+ if(m_pSwitches)
+ {
+ if(!(m_pSwitches->evaluate(c,&swl)))return false;
+ }
+
+ bool bIncludeEmptyScalars = swl.find('a',"all") != 0;
+
+ for(KviKvsVariant * pArg = l.first();pArg;pArg = l.next())
+ {
+ switch(pArg->type())
+ {
+ case KviKvsVariantData::Array:
+ {
+ unsigned int uCnt = pArg->array()->size();
+ unsigned int idx = 0;
+ while(idx < uCnt)
+ {
+ KviKvsVariant * pOne = pArg->array()->at(idx);
+ if(pOne)
+ {
+ v->result()->copyFrom(*pOne);
+ } else {
+ v->result()->setNothing();
+ }
+
+ if(!m_pLoop->execute(c))
+ {
+ // break allowed!
+
+ if(c->error())
+ {
+ delete v;
+ return false;
+ }
+ // break allowed!
+ if(c->breakPending())
+ {
+ c->handleBreak();
+ delete v;
+ return true;
+ }
+ delete v;
+ return false; // propagate the false return value
+ }
+
+ idx++;
+ }
+ }
+ break;
+ case KviKvsVariantData::Hash:
+ {
+ KviKvsHashIterator it(*(pArg->hash()->dict()));
+ while(KviKvsVariant * pOne = it.current())
+ {
+ v->result()->copyFrom(*pOne);
+
+ if(!m_pLoop->execute(c))
+ {
+ // break allowed!
+
+ if(c->error())
+ {
+ delete v;
+ return false;
+ }
+ // break allowed!
+ if(c->breakPending())
+ {
+ c->handleBreak();
+ delete v;
+ return true;
+ }
+ delete v;
+ return false; // propagate the false return value
+ }
+
+ ++it;
+ }
+ }
+ break;
+ default:
+ if(bIncludeEmptyScalars || (!pArg->isNothing()))
+ {
+ v->result()->copyFrom(*pArg);
+ if(!m_pLoop->execute(c))
+ {
+ // break allowed!
+
+ if(c->error())
+ {
+ delete v;
+ return false;
+ }
+ // break allowed!
+ if(c->breakPending())
+ {
+ c->handleBreak();
+ delete v;
+ return true;
+ }
+ delete v;
+ return false; // propagate the false return value
+ }
+ }
+ break;
+ }
+ }
+ delete v;
+ return true;
+}
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_specialcommandforeach.h b/src/kvirc/kvs/kvi_kvs_treenode_specialcommandforeach.h
new file mode 100644
index 00000000..9f2e765b
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_specialcommandforeach.h
@@ -0,0 +1,53 @@
+#ifndef _KVI_KVS_TREENODE_SPECIALCOMMANDFOREACH_H_
+#define _KVI_KVS_TREENODE_SPECIALCOMMANDFOREACH_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_specialcommandforeach.h
+// Created on Fri 07 Nov 2003 11:48:11 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_treenode_specialcommand.h"
+
+class KviKvsTreeNodeData;
+class KviKvsTreeNodeDataList;
+class KviKvsTreeNodeInstruction;
+class KviKvsRunTimeContext;
+
+class KVIRC_API KviKvsTreeNodeSpecialCommandForeach : public KviKvsTreeNodeSpecialCommand
+{
+public:
+ KviKvsTreeNodeSpecialCommandForeach(const QChar * pLocation,KviKvsTreeNodeData * pVar,KviKvsTreeNodeDataList * pArgs,KviKvsTreeNodeInstruction * pLoop);
+ ~KviKvsTreeNodeSpecialCommandForeach();
+private:
+ KviKvsTreeNodeData * m_pIterationVariable; // can't be zero!
+ KviKvsTreeNodeDataList * m_pIterationData; // can't be zero!
+ KviKvsTreeNodeInstruction * m_pLoop; // can't be zero!
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c);
+};
+
+
+#endif //!_KVI_KVS_TREENODE_SPECIALCOMMANDFOREACH_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_specialcommandif.cpp b/src/kvirc/kvs/kvi_kvs_treenode_specialcommandif.cpp
new file mode 100644
index 00000000..bc9e31d0
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_specialcommandif.cpp
@@ -0,0 +1,94 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_specialcommandif.cpp
+// Created on Thu 09 Oct 2003 02:40:00 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_specialcommandif.h"
+#include "kvi_kvs_treenode_expression.h"
+#include "kvi_kvs_treenode_instruction.h"
+#include "kvi_kvs_runtimecontext.h"
+#include "kvi_locale.h"
+
+KviKvsTreeNodeSpecialCommandIf::KviKvsTreeNodeSpecialCommandIf(const QChar * pLocation,KviKvsTreeNodeExpression * e,KviKvsTreeNodeInstruction * pIf,KviKvsTreeNodeInstruction * pElse)
+: KviKvsTreeNodeSpecialCommand(pLocation,"if")
+{
+#ifdef COMPILE_NEW_KVS
+ m_pExpression = e;
+ m_pExpression->setParent(this);
+ m_pIfInstruction = pIf;
+ if(pIf)m_pIfInstruction->setParent(this);
+ m_pElseInstruction = pElse;
+ if(pElse)m_pElseInstruction->setParent(this);
+#endif
+}
+
+KviKvsTreeNodeSpecialCommandIf::~KviKvsTreeNodeSpecialCommandIf()
+{
+#ifdef COMPILE_NEW_KVS
+ delete m_pExpression;
+ if(m_pIfInstruction)delete m_pIfInstruction;
+ if(m_pElseInstruction)delete m_pElseInstruction;
+#endif
+}
+
+void KviKvsTreeNodeSpecialCommandIf::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Special Command \"if\"";
+#endif
+}
+
+void KviKvsTreeNodeSpecialCommandIf::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s SpecialCommandIf",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pExpression->dump(tmp);
+ if(m_pIfInstruction)m_pIfInstruction->dump(tmp);
+ if(m_pElseInstruction)m_pElseInstruction->dump(tmp);
+#endif
+}
+
+bool KviKvsTreeNodeSpecialCommandIf::execute(KviKvsRunTimeContext * c)
+{
+#ifdef COMPILE_NEW_KVS
+ KviKvsVariant v;
+ if(!m_pExpression->evaluateReadOnly(c,&v))return false;
+
+ if(v.asBoolean())
+ {
+ if(m_pIfInstruction)
+ {
+ return m_pIfInstruction->execute(c);
+ }
+ } else {
+ if(m_pElseInstruction)
+ {
+ return m_pElseInstruction->execute(c);
+ }
+ }
+#endif
+ return true;
+}
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_specialcommandif.h b/src/kvirc/kvs/kvi_kvs_treenode_specialcommandif.h
new file mode 100644
index 00000000..bc89af41
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_specialcommandif.h
@@ -0,0 +1,50 @@
+#ifndef _KVI_KVS_TREENODE_SPECIALCOMMANDIF_H_
+#define _KVI_KVS_TREENODE_SPECIALCOMMANDIF_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_specialcommandif.h
+// Created on Thu 09 Oct 2003 02:40:00 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_treenode_specialcommand.h"
+
+class KviKvsTreeNodeExpression;
+class KviKvsTreeNodeInstruction;
+class KviKvsRunTimeContext;
+
+class KVIRC_API KviKvsTreeNodeSpecialCommandIf : public KviKvsTreeNodeSpecialCommand
+{
+public:
+ KviKvsTreeNodeSpecialCommandIf(const QChar * pLocation,KviKvsTreeNodeExpression * e,KviKvsTreeNodeInstruction * pIf,KviKvsTreeNodeInstruction * pElse);
+ ~KviKvsTreeNodeSpecialCommandIf();
+private:
+ KviKvsTreeNodeExpression * m_pExpression; // can't be 0
+ KviKvsTreeNodeInstruction * m_pIfInstruction; // may be 0
+ KviKvsTreeNodeInstruction * m_pElseInstruction; // may be 0
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c);
+};
+
+#endif //!_KVI_KVS_TREENODE_SPECIALCOMMANDIF_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_specialcommandswitch.cpp b/src/kvirc/kvs/kvi_kvs_treenode_specialcommandswitch.cpp
new file mode 100644
index 00000000..28b7b1f5
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_specialcommandswitch.cpp
@@ -0,0 +1,349 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_specialcommandswitch.cpp
+// Created on Fri 02 Jan 2004 14:09:00 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_specialcommandswitch.h"
+#include "kvi_kvs_treenode_expression.h"
+#include "kvi_kvs_treenode_instruction.h"
+#include "kvi_kvs_runtimecontext.h"
+#include "kvi_locale.h"
+
+#include <qregexp.h>
+
+KviKvsTreeNodeSpecialCommandSwitchLabel::KviKvsTreeNodeSpecialCommandSwitchLabel(const QChar * pLocation)
+: KviKvsTreeNode(pLocation)
+{
+ m_pParameter = 0;
+ m_pInstruction = 0;
+ m_bHasTerminatingBreak = false;
+}
+
+KviKvsTreeNodeSpecialCommandSwitchLabel::~KviKvsTreeNodeSpecialCommandSwitchLabel()
+{
+ if(m_pParameter)delete m_pParameter;
+ if(m_pInstruction)delete m_pInstruction;
+}
+
+void KviKvsTreeNodeSpecialCommandSwitchLabel::setParameter(KviKvsTreeNodeData * pParameter)
+{
+ if(m_pParameter)delete m_pParameter;
+ m_pParameter = pParameter;
+ if(m_pParameter)m_pParameter->setParent(this);
+}
+
+void KviKvsTreeNodeSpecialCommandSwitchLabel::setInstruction(KviKvsTreeNodeInstruction * pInstruction)
+{
+ if(m_pInstruction)delete m_pInstruction;
+ m_pInstruction = pInstruction;
+ if(m_pInstruction)m_pInstruction->setParent(this);
+}
+
+
+
+
+
+KviKvsTreeNodeSpecialCommandSwitchLabelCase::KviKvsTreeNodeSpecialCommandSwitchLabelCase(const QChar * pLocation)
+: KviKvsTreeNodeSpecialCommandSwitchLabel(pLocation)
+{
+}
+
+KviKvsTreeNodeSpecialCommandSwitchLabelCase::~KviKvsTreeNodeSpecialCommandSwitchLabelCase()
+{
+}
+
+void KviKvsTreeNodeSpecialCommandSwitchLabelCase::contextDescription(QString &szBuffer)
+{
+ szBuffer = "Label \"case\" For Special Command \"switch\"";
+}
+
+void KviKvsTreeNodeSpecialCommandSwitchLabelCase::dump(const char * prefix)
+{
+ debug("%s SpecialCommandSwitchLabelCase",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ if(m_pParameter)m_pParameter->dump(tmp.utf8().data());
+ if(m_pInstruction)m_pInstruction->dump(tmp.utf8().data());
+}
+
+bool KviKvsTreeNodeSpecialCommandSwitchLabelCase::execute(KviKvsRunTimeContext * c,KviKvsVariant * pRealParameter)
+{
+ KviKvsVariant v;
+ if(!m_pParameter->evaluateReadOnly(c,&v))return false;
+
+ KviKvsNumber num;
+ if(pRealParameter->asNumber(num))
+ {
+ KviKvsNumber num2;
+ if(!v.asNumber(num2))return true; // a number an a non number can't match
+ if(num.isInteger())
+ {
+ if(num2.isInteger())
+ {
+ if(num.integer() != num2.integer())return true;
+ } else {
+ if(((double)(num.integer())) != num2.real())return true;
+ }
+ } else {
+ if(num2.isInteger())
+ {
+ if(num.real() != ((double)(num2.integer())))return true;
+ } else {
+ if(num.real() != num2.real())return true;
+ }
+ }
+ } else {
+ // string comparision, case insensitive
+ QString reg;
+ v.asString(reg);
+
+ QString val;
+ pRealParameter->asString(val);
+
+ if(reg.lower() != val.lower())return true;
+ }
+
+ if(m_pInstruction)
+ {
+ if(!m_pInstruction->execute(c))return false; // might be a break too
+ }
+ if(m_bHasTerminatingBreak)
+ {
+ c->setBreakPending();
+ return false;
+ }
+ return true;
+}
+
+
+
+
+KviKvsTreeNodeSpecialCommandSwitchLabelMatch::KviKvsTreeNodeSpecialCommandSwitchLabelMatch(const QChar * pLocation)
+: KviKvsTreeNodeSpecialCommandSwitchLabel(pLocation)
+{
+}
+
+KviKvsTreeNodeSpecialCommandSwitchLabelMatch::~KviKvsTreeNodeSpecialCommandSwitchLabelMatch()
+{
+}
+
+void KviKvsTreeNodeSpecialCommandSwitchLabelMatch::contextDescription(QString &szBuffer)
+{
+ szBuffer = "Label \"match\" For Special Command \"switch\"";
+}
+
+
+void KviKvsTreeNodeSpecialCommandSwitchLabelMatch::dump(const char * prefix)
+{
+ debug("%s SpecialCommandSwitchLabelMatch",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ if(m_pParameter)m_pParameter->dump(tmp.utf8().data());
+ if(m_pInstruction)m_pInstruction->dump(tmp.utf8().data());
+}
+
+bool KviKvsTreeNodeSpecialCommandSwitchLabelMatch::execute(KviKvsRunTimeContext * c,KviKvsVariant * pRealParameter)
+{
+ KviKvsVariant v;
+ if(!m_pParameter->evaluateReadOnly(c,&v))return false;
+
+ QString reg;
+ v.asString(reg);
+
+ QRegExp rx(reg,false,true);
+
+ QString val;
+ pRealParameter->asString(val);
+
+ if(!rx.exactMatch(val))return true; // no match
+
+ if(m_pInstruction)
+ {
+ if(!m_pInstruction->execute(c))return false; // might be a break too
+ }
+ if(m_bHasTerminatingBreak)
+ {
+ c->setBreakPending();
+ return false;
+ }
+ return true;
+}
+
+
+
+
+KviKvsTreeNodeSpecialCommandSwitchLabelRegexp::KviKvsTreeNodeSpecialCommandSwitchLabelRegexp(const QChar * pLocation)
+: KviKvsTreeNodeSpecialCommandSwitchLabel(pLocation)
+{
+}
+
+KviKvsTreeNodeSpecialCommandSwitchLabelRegexp::~KviKvsTreeNodeSpecialCommandSwitchLabelRegexp()
+{
+}
+
+void KviKvsTreeNodeSpecialCommandSwitchLabelRegexp::contextDescription(QString &szBuffer)
+{
+ szBuffer = "Label \"regexp\" For Special Command \"switch\"";
+}
+
+
+void KviKvsTreeNodeSpecialCommandSwitchLabelRegexp::dump(const char * prefix)
+{
+ debug("%s SpecialCommandSwitchLabelRegexp",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ if(m_pParameter)m_pParameter->dump(tmp.utf8().data());
+ if(m_pInstruction)m_pInstruction->dump(tmp.utf8().data());
+}
+
+bool KviKvsTreeNodeSpecialCommandSwitchLabelRegexp::execute(KviKvsRunTimeContext * c,KviKvsVariant * pRealParameter)
+{
+ KviKvsVariant v;
+ if(!m_pParameter->evaluateReadOnly(c,&v))return false;
+
+ QString reg;
+ v.asString(reg);
+
+ QRegExp rx(reg,false,false);
+
+ QString val;
+ pRealParameter->asString(val);
+
+ if(!rx.exactMatch(val))return true; // no match
+
+ if(m_pInstruction)
+ {
+ if(!m_pInstruction->execute(c))return false; // might be a break too
+ }
+ if(m_bHasTerminatingBreak)
+ {
+ c->setBreakPending();
+ return false;
+ }
+ return true;
+}
+
+
+
+
+
+
+KviKvsTreeNodeSpecialCommandSwitchLabelDefault::KviKvsTreeNodeSpecialCommandSwitchLabelDefault(const QChar * pLocation)
+: KviKvsTreeNodeSpecialCommandSwitchLabel(pLocation)
+{
+}
+
+KviKvsTreeNodeSpecialCommandSwitchLabelDefault::~KviKvsTreeNodeSpecialCommandSwitchLabelDefault()
+{
+}
+
+void KviKvsTreeNodeSpecialCommandSwitchLabelDefault::contextDescription(QString &szBuffer)
+{
+ szBuffer = "Label \"default\" For Special Command \"switch\"";
+}
+
+
+void KviKvsTreeNodeSpecialCommandSwitchLabelDefault::dump(const char * prefix)
+{
+ debug("%s SpecialCommandSwitchLabelDefault",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ if(m_pInstruction)m_pInstruction->dump(tmp.utf8().data());
+}
+
+bool KviKvsTreeNodeSpecialCommandSwitchLabelDefault::execute(KviKvsRunTimeContext * c,KviKvsVariant * pRealParameter)
+{
+ if(m_pInstruction)
+ {
+ if(!m_pInstruction->execute(c))return false; // might be a break too
+ }
+ if(m_bHasTerminatingBreak)
+ {
+ c->setBreakPending();
+ return false;
+ }
+ return true;
+}
+
+
+
+
+KviKvsTreeNodeSpecialCommandSwitch::KviKvsTreeNodeSpecialCommandSwitch(const QChar * pLocation,KviKvsTreeNodeExpression * e)
+: KviKvsTreeNodeSpecialCommand(pLocation,"switch")
+{
+ m_pExpression = e;
+ m_pExpression->setParent(this);
+ m_pLabels = new KviPointerList<KviKvsTreeNodeSpecialCommandSwitchLabel>;
+ m_pLabels->setAutoDelete(true);
+}
+
+KviKvsTreeNodeSpecialCommandSwitch::~KviKvsTreeNodeSpecialCommandSwitch()
+{
+ delete m_pExpression;
+ delete m_pLabels;
+}
+
+void KviKvsTreeNodeSpecialCommandSwitch::addLabel(KviKvsTreeNodeSpecialCommandSwitchLabel * l)
+{
+ m_pLabels->append(l);
+ l->setParent(this);
+}
+
+void KviKvsTreeNodeSpecialCommandSwitch::contextDescription(QString &szBuffer)
+{
+ szBuffer = "Special Command \"switch\"";
+}
+
+
+void KviKvsTreeNodeSpecialCommandSwitch::dump(const char * prefix)
+{
+ debug("%s SpecialCommandSwitch",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pExpression->dump(tmp.utf8().data());
+ for(KviKvsTreeNodeSpecialCommandSwitchLabel * l = m_pLabels->first();l;l = m_pLabels->next())
+ l->dump(tmp.utf8().data());
+}
+
+bool KviKvsTreeNodeSpecialCommandSwitch::execute(KviKvsRunTimeContext * c)
+{
+ KviKvsVariant v;
+ if(!m_pExpression->evaluateReadOnly(c,&v))return false;
+
+ for(KviKvsTreeNodeSpecialCommandSwitchLabel * l = m_pLabels->first();l;l = m_pLabels->next())
+ {
+ if(!l->execute(c,&v))
+ {
+ if(c->error())return false;
+ // break ?
+ if(c->breakPending())
+ {
+ c->handleBreak();
+ return true;
+ }
+ return false;
+ }
+ }
+ return true;
+}
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_specialcommandswitch.h b/src/kvirc/kvs/kvi_kvs_treenode_specialcommandswitch.h
new file mode 100644
index 00000000..ecad6e25
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_specialcommandswitch.h
@@ -0,0 +1,117 @@
+#ifndef _KVI_KVS_TREENODE_SPECIALCOMMANDSWITCH_H_
+#define _KVI_KVS_TREENODE_SPECIALCOMMANDSWITCH_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_specialcommandswitch.h
+// Created on Fri 02 Jan 2004 13:54:00 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_treenode.h"
+#include "kvi_kvs_treenode_specialcommand.h"
+
+class KviKvsTreeNodeExpression;
+class KviKvsTreeNodeInstruction;
+class KviKvsRunTimeContext;
+class KviKvsVariant;
+
+class KVIRC_API KviKvsTreeNodeSpecialCommandSwitchLabel : public KviKvsTreeNode
+{
+public:
+ KviKvsTreeNodeSpecialCommandSwitchLabel(const QChar * pLocation);
+ ~KviKvsTreeNodeSpecialCommandSwitchLabel();
+protected:
+ KviKvsTreeNodeData * m_pParameter;
+ KviKvsTreeNodeInstruction * m_pInstruction;
+ bool m_bHasTerminatingBreak;
+public:
+ void setParameter(KviKvsTreeNodeData * pParameter);
+ void setInstruction(KviKvsTreeNodeInstruction * pInstruction);
+ void setTerminatingBreak(bool b){ m_bHasTerminatingBreak = b; };
+ virtual bool execute(KviKvsRunTimeContext * c,KviKvsVariant * pRealParameter) = 0;
+};
+
+
+class KVIRC_API KviKvsTreeNodeSpecialCommandSwitchLabelCase : public KviKvsTreeNodeSpecialCommandSwitchLabel
+{
+public:
+ KviKvsTreeNodeSpecialCommandSwitchLabelCase(const QChar * pLocation);
+ ~KviKvsTreeNodeSpecialCommandSwitchLabelCase();
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c,KviKvsVariant * pRealParameter);
+};
+
+
+class KVIRC_API KviKvsTreeNodeSpecialCommandSwitchLabelMatch : public KviKvsTreeNodeSpecialCommandSwitchLabel
+{
+public:
+ KviKvsTreeNodeSpecialCommandSwitchLabelMatch(const QChar * pLocation);
+ ~KviKvsTreeNodeSpecialCommandSwitchLabelMatch();
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c,KviKvsVariant * pRealParameter);
+};
+
+class KVIRC_API KviKvsTreeNodeSpecialCommandSwitchLabelRegexp : public KviKvsTreeNodeSpecialCommandSwitchLabel
+{
+public:
+ KviKvsTreeNodeSpecialCommandSwitchLabelRegexp(const QChar * pLocation);
+ ~KviKvsTreeNodeSpecialCommandSwitchLabelRegexp();
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c,KviKvsVariant * pRealParameter);
+};
+
+class KVIRC_API KviKvsTreeNodeSpecialCommandSwitchLabelDefault : public KviKvsTreeNodeSpecialCommandSwitchLabel
+{
+public:
+ KviKvsTreeNodeSpecialCommandSwitchLabelDefault(const QChar * pLocation);
+ ~KviKvsTreeNodeSpecialCommandSwitchLabelDefault();
+public:
+ virtual void dump(const char * prefix);
+ virtual void contextDescription(QString &szBuffer);
+ virtual bool execute(KviKvsRunTimeContext * c,KviKvsVariant * pRealParameter);
+};
+
+
+
+class KVIRC_API KviKvsTreeNodeSpecialCommandSwitch : public KviKvsTreeNodeSpecialCommand
+{
+public:
+ KviKvsTreeNodeSpecialCommandSwitch(const QChar * pLocation,KviKvsTreeNodeExpression * e);
+ ~KviKvsTreeNodeSpecialCommandSwitch();
+private:
+ KviKvsTreeNodeExpression * m_pExpression; // can't be 0
+ KviPointerList<KviKvsTreeNodeSpecialCommandSwitchLabel> * m_pLabels; //can't be 0
+public:
+ void addLabel(KviKvsTreeNodeSpecialCommandSwitchLabel * l);
+ bool isEmpty(){ return m_pLabels->isEmpty(); };
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c);
+};
+
+#endif //!_KVI_KVS_TREENODE_SPECIALCOMMANDSWITCH_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_specialcommandunset.cpp b/src/kvirc/kvs/kvi_kvs_treenode_specialcommandunset.cpp
new file mode 100644
index 00000000..be7c5df2
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_specialcommandunset.cpp
@@ -0,0 +1,74 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_specialcommandunset.cpp
+// Created on Thu 14 Apr 2005 02:44:00 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_specialcommandunset.h"
+#include "kvi_kvs_runtimecontext.h"
+#include "kvi_kvs_rwevaluationresult.h"
+#include "kvi_locale.h"
+
+KviKvsTreeNodeSpecialCommandUnset::KviKvsTreeNodeSpecialCommandUnset(const QChar * pLocation,KviPointerList<KviKvsTreeNodeVariable> * pVariableList)
+: KviKvsTreeNodeSpecialCommand(pLocation,"unset")
+{
+ m_pVariableList = pVariableList;
+ for(KviKvsTreeNodeVariable * pVar = m_pVariableList->first();pVar;pVar = m_pVariableList->next())
+ {
+ pVar->setParent(this);
+ }
+}
+
+KviKvsTreeNodeSpecialCommandUnset::~KviKvsTreeNodeSpecialCommandUnset()
+{
+ delete m_pVariableList;
+}
+
+void KviKvsTreeNodeSpecialCommandUnset::contextDescription(QString &szBuffer)
+{
+ szBuffer = "Special Command \"unset\"";
+}
+
+void KviKvsTreeNodeSpecialCommandUnset::dump(const char * prefix)
+{
+ debug("%s SpecialCommandUnset",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ for(KviKvsTreeNodeVariable * pVar = m_pVariableList->first();pVar;pVar = m_pVariableList->next())
+ {
+ pVar->dump(tmp.utf8().data());
+ }
+}
+
+bool KviKvsTreeNodeSpecialCommandUnset::execute(KviKvsRunTimeContext * c)
+{
+ for(KviKvsTreeNodeVariable * pVar = m_pVariableList->first();pVar;pVar = m_pVariableList->next())
+ {
+ KviKvsRWEvaluationResult * r = pVar->evaluateReadWrite(c);
+ if(!r)return false;
+ r->result()->setNothing();
+ delete r; // this will remove the data from its container
+ }
+ return true;
+}
+
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_specialcommandunset.h b/src/kvirc/kvs/kvi_kvs_treenode_specialcommandunset.h
new file mode 100644
index 00000000..3d125065
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_specialcommandunset.h
@@ -0,0 +1,47 @@
+#ifndef _KVI_KVS_TREENODE_SPECIALCOMMANDUNSET_H_
+#define _KVI_KVS_TREENODE_SPECIALCOMMANDUNSET_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_specialcommandunset.h
+// Created on Thu 14 Apr 2005 02:44:00 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_treenode_specialcommand.h"
+#include "kvi_kvs_treenode_variable.h"
+
+class KviKvsRunTimeContext;
+
+class KVIRC_API KviKvsTreeNodeSpecialCommandUnset : public KviKvsTreeNodeSpecialCommand
+{
+public:
+ KviKvsTreeNodeSpecialCommandUnset(const QChar * pLocation,KviPointerList<KviKvsTreeNodeVariable> * pVarList);
+ ~KviKvsTreeNodeSpecialCommandUnset();
+private:
+ KviPointerList<KviKvsTreeNodeVariable> * m_pVariableList;
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c);
+};
+
+#endif //!_KVI_KVS_TREENODE_SPECIALCOMMANDUNSET_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_specialcommandwhile.cpp b/src/kvirc/kvs/kvi_kvs_treenode_specialcommandwhile.cpp
new file mode 100644
index 00000000..377921df
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_specialcommandwhile.cpp
@@ -0,0 +1,97 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_specialcommandwhile.cpp
+// Created on Thu 06 Nov 2003 11:58:43 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_specialcommandwhile.h"
+#include "kvi_kvs_treenode_expression.h"
+#include "kvi_kvs_treenode_instruction.h"
+#include "kvi_kvs_runtimecontext.h"
+#include "kvi_locale.h"
+
+KviKvsTreeNodeSpecialCommandWhile::KviKvsTreeNodeSpecialCommandWhile(const QChar * pLocation,KviKvsTreeNodeExpression * e,KviKvsTreeNodeInstruction * i)
+: KviKvsTreeNodeSpecialCommand(pLocation,"while")
+{
+#ifdef COMPILE_NEW_KVS
+ m_pExpression = e;
+ m_pExpression->setParent(this);
+ m_pInstruction = i;
+ if(i)m_pInstruction->setParent(this);
+#endif
+}
+
+KviKvsTreeNodeSpecialCommandWhile::~KviKvsTreeNodeSpecialCommandWhile()
+{
+#ifdef COMPILE_NEW_KVS
+ delete m_pExpression;
+ if(m_pInstruction)delete m_pInstruction;
+#endif
+}
+
+void KviKvsTreeNodeSpecialCommandWhile::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Special Command \"while\"";
+#endif
+}
+
+void KviKvsTreeNodeSpecialCommandWhile::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s SpecialCommandWhile",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pExpression->dump(tmp);
+ if(m_pInstruction)m_pInstruction->dump(tmp);
+#endif
+}
+
+bool KviKvsTreeNodeSpecialCommandWhile::execute(KviKvsRunTimeContext * c)
+{
+#ifdef COMPILE_NEW_KVS
+ for(;;)
+ {
+ KviKvsVariant v;
+ if(!m_pExpression->evaluateReadOnly(c,&v))return false;
+
+ if(!v.asBoolean())break;
+
+ if(m_pInstruction)
+ {
+ if(!m_pInstruction->execute(c))
+ {
+ if(c->error())return false;
+
+ if(c->breakPending())
+ {
+ c->handleBreak();
+ return true;
+ }
+ return false;
+ }
+ }
+ }
+#endif
+ return true;
+}
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_specialcommandwhile.h b/src/kvirc/kvs/kvi_kvs_treenode_specialcommandwhile.h
new file mode 100644
index 00000000..87b3b902
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_specialcommandwhile.h
@@ -0,0 +1,51 @@
+#ifndef _KVI_KVS_TREENODE_SPECIALCOMMANDWHILE_H_
+#define _KVI_KVS_TREENODE_SPECIALCOMMANDWHILE_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_specialcommandwhile.h
+// Created on Thu 06 Nov 2003 11:58:43 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_treenode_specialcommand.h"
+
+class KviKvsTreeNodeExpression;
+class KviKvsTreeNodeInstruction;
+class KviKvsRunTimeContext;
+
+class KVIRC_API KviKvsTreeNodeSpecialCommandWhile : public KviKvsTreeNodeSpecialCommand
+{
+public:
+ KviKvsTreeNodeSpecialCommandWhile(const QChar * pLocation,KviKvsTreeNodeExpression * e,KviKvsTreeNodeInstruction * i);
+ ~KviKvsTreeNodeSpecialCommandWhile();
+private:
+ KviKvsTreeNodeExpression * m_pExpression; // can't be 0
+ KviKvsTreeNodeInstruction * m_pInstruction; // may be 0
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c);
+};
+
+
+#endif //!_KVI_KVS_TREENODE_SPECIALCOMMANDWHILE_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_stringcast.cpp b/src/kvirc/kvs/kvi_kvs_treenode_stringcast.cpp
new file mode 100644
index 00000000..8c4f76c9
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_stringcast.cpp
@@ -0,0 +1,67 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_stringcast.cpp
+// Created on Mon 26 Jun 2006 15:17:33 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2006 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_stringcast.h"
+#include "kvi_qstring.h"
+
+KviKvsTreeNodeStringCast::KviKvsTreeNodeStringCast(const QChar * pLocation,KviKvsTreeNodeData * pChildData)
+: KviKvsTreeNodeData(pLocation)
+{
+ m_pChildData = pChildData;
+ m_pChildData->setParent(this);
+}
+
+
+KviKvsTreeNodeStringCast::~KviKvsTreeNodeStringCast()
+{
+ delete m_pChildData;
+}
+
+bool KviKvsTreeNodeStringCast::evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+ if(!m_pChildData->evaluateReadOnly(c,pBuffer))return false;
+ if(!pBuffer->isString())
+ {
+ QString tmp;
+ pBuffer->asString(tmp);
+ pBuffer->setString(tmp);
+ }
+ return true;
+}
+
+void KviKvsTreeNodeStringCast::contextDescription(QString &szBuffer)
+{
+ szBuffer = "String Cast";
+}
+
+void KviKvsTreeNodeStringCast::dump(const char * prefix)
+{
+ debug("%s StringCast",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pChildData->dump(tmp.utf8().data());
+}
+
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_stringcast.h b/src/kvirc/kvs/kvi_kvs_treenode_stringcast.h
new file mode 100644
index 00000000..af537f9a
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_stringcast.h
@@ -0,0 +1,45 @@
+#ifndef _KVI_KVS_TREENODE_STRINGCAST_H_
+#define _KVI_KVS_TREENODE_STRINGCAST_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_stringcast.h
+// Created on Mon 26 Jun 2006 15:17:33 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2006 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_kvs_treenode_data.h"
+
+class KVIRC_API KviKvsTreeNodeStringCast : public KviKvsTreeNodeData
+{
+public:
+ KviKvsTreeNodeStringCast(const QChar * pLocation,KviKvsTreeNodeData * pChildData);
+ ~KviKvsTreeNodeStringCast();
+protected:
+ KviKvsTreeNodeData * m_pChildData;
+public:
+ virtual bool evaluateReadOnly(KviKvsRunTimeContext * c,KviKvsVariant * pBuffer);
+ virtual void contextDescription(QString &szBuffer);
+
+ virtual void dump(const char * prefix);
+};
+
+
+#endif //!_KVI_KVS_TREENODE_STRINGCAST_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_switchlist.cpp b/src/kvirc/kvs/kvi_kvs_treenode_switchlist.cpp
new file mode 100644
index 00000000..c821529c
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_switchlist.cpp
@@ -0,0 +1,170 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_switchlist.cpp
+// Created on Tue 07 Oct 2003 02:06:53 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_switchlist.h"
+#include "kvi_kvs_runtimecontext.h"
+
+KviKvsTreeNodeSwitchList::KviKvsTreeNodeSwitchList(const QChar * pLocation)
+: KviKvsTreeNode(pLocation)
+{
+ m_pShortSwitchDict = 0;
+ m_pLongSwitchDict = 0;
+}
+
+KviKvsTreeNodeSwitchList::~KviKvsTreeNodeSwitchList()
+{
+ if(m_pShortSwitchDict)delete m_pShortSwitchDict;
+ if(m_pLongSwitchDict)delete m_pLongSwitchDict;
+}
+
+void KviKvsTreeNodeSwitchList::contextDescription(QString &szBuffer)
+{
+ szBuffer = "Switch List Evaluation";
+}
+
+
+void KviKvsTreeNodeSwitchList::dump(const char * prefix)
+{
+ debug("%s SwitchList",prefix);
+ if(m_pShortSwitchDict)
+ {
+ KviPointerHashTableIterator<int,KviKvsTreeNodeData> it(*m_pShortSwitchDict);
+ while(it.current())
+ {
+ QString tmp = prefix;
+ tmp.append(" Sw(");
+ QChar c((unsigned short)it.currentKey());
+ tmp.append(c);
+ tmp.append("): ");
+ it.current()->dump(tmp.utf8().data());
+ ++it;
+ }
+ }
+ if(m_pLongSwitchDict)
+ {
+ KviPointerHashTableIterator<QString,KviKvsTreeNodeData> it(*m_pLongSwitchDict);
+ while(it.current())
+ {
+ QString tmp = prefix;
+ tmp.append(" Sw(");
+ tmp.append(it.currentKey());
+ tmp.append("): ");
+ it.current()->dump(tmp.utf8().data());
+ ++it;
+ }
+ }
+}
+
+void KviKvsTreeNodeSwitchList::addShort(int iShortKey,KviKvsTreeNodeData * p)
+{
+ if(!m_pShortSwitchDict)
+ {
+ m_pShortSwitchDict = new KviPointerHashTable<int,KviKvsTreeNodeData>(11);
+ m_pShortSwitchDict->setAutoDelete(true);
+ }
+
+ m_pShortSwitchDict->replace(iShortKey,p);
+ p->setParent(this);
+}
+
+void KviKvsTreeNodeSwitchList::addLong(const QString &szLongKey,KviKvsTreeNodeData * p)
+{
+ if(!m_pLongSwitchDict)
+ {
+ m_pLongSwitchDict = new KviPointerHashTable<QString,KviKvsTreeNodeData>(11);
+ m_pLongSwitchDict->setAutoDelete(true);
+ }
+
+ m_pLongSwitchDict->replace(szLongKey,p);
+ p->setParent(this);
+}
+
+
+bool KviKvsTreeNodeSwitchList::evaluate(KviKvsRunTimeContext * c,KviKvsSwitchList * pSwList)
+{
+ pSwList->clear();
+
+ if(m_pShortSwitchDict)
+ {
+ KviPointerHashTableIterator<int,KviKvsTreeNodeData> it(*m_pShortSwitchDict);
+ while(KviKvsTreeNodeData * d = it.current())
+ {
+ KviKvsVariant * v = new KviKvsVariant();
+ if(!d->evaluateReadOnly(c,v))
+ {
+ delete v;
+ return false;
+ }
+ pSwList->addShort(it.currentKey(),v);
+ ++it;
+ }
+ }
+ if(m_pLongSwitchDict)
+ {
+ KviPointerHashTableIterator<QString,KviKvsTreeNodeData> it(*m_pLongSwitchDict);
+ while(KviKvsTreeNodeData * d = it.current())
+ {
+ KviKvsVariant * v = new KviKvsVariant();
+ if(!d->evaluateReadOnly(c,v))
+ {
+ delete v;
+ return false;
+ }
+ pSwList->addLong(it.currentKey(),v);
+ ++it;
+ }
+ }
+ return true;
+}
+
+KviKvsTreeNodeData * KviKvsTreeNodeSwitchList::getStandardRebindingSwitch()
+{
+ KviKvsTreeNodeData * d;
+ if(m_pShortSwitchDict)
+ {
+ d = m_pShortSwitchDict->find('r');
+ if(d)
+ {
+ m_pShortSwitchDict->setAutoDelete(false);
+ m_pShortSwitchDict->remove('r');
+ m_pShortSwitchDict->setAutoDelete(true);
+ return d;
+ }
+ }
+ if(m_pLongSwitchDict)
+ {
+ d = m_pLongSwitchDict->find("rebind");
+ if(d)
+ {
+ m_pLongSwitchDict->setAutoDelete(false);
+ m_pLongSwitchDict->remove("rebind");
+ m_pLongSwitchDict->setAutoDelete(true);
+ return d;
+ }
+ }
+ return 0;
+}
+
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_switchlist.h b/src/kvirc/kvs/kvi_kvs_treenode_switchlist.h
new file mode 100644
index 00000000..9e6510a4
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_switchlist.h
@@ -0,0 +1,61 @@
+#ifndef _KVI_KVS_TREENODE_SWITCHLIST_H_
+#define _KVI_KVS_TREENODE_SWITCHLIST_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_switchlist.h
+// Created on Tue 07 Oct 2003 02:06:53 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+
+#include "kvi_pointerhashtable.h"
+#include "kvi_pointerhashtable.h"
+
+#include "kvi_kvs_treenode_base.h"
+#include "kvi_kvs_treenode_data.h"
+#include "kvi_kvs_switchlist.h"
+
+class KviKvsRunTimeContext;
+
+class KVIRC_API KviKvsTreeNodeSwitchList : public KviKvsTreeNode
+{
+public:
+ KviKvsTreeNodeSwitchList(const QChar * pLocation);
+ ~KviKvsTreeNodeSwitchList();
+public:
+ KviPointerHashTable<int,KviKvsTreeNodeData> * m_pShortSwitchDict;
+ KviPointerHashTable<QString,KviKvsTreeNodeData> *m_pLongSwitchDict;
+public:
+ void addShort(int iShortKey,KviKvsTreeNodeData * p);
+ void addLong(const QString &szLongKey,KviKvsTreeNodeData * p);
+ bool isEmpty(){ return (m_pShortSwitchDict == 0) && (m_pLongSwitchDict == 0); };
+ virtual void dump(const char * prefix);
+ virtual void contextDescription(QString &szBuffer);
+
+ KviKvsTreeNodeData * getStandardRebindingSwitch();
+
+ bool evaluate(KviKvsRunTimeContext * c,KviKvsSwitchList * pSwList);
+};
+
+
+
+#endif //!_KVI_KVS_TREENODE_SWITCHLIST_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_thisobjectfunctioncall.cpp b/src/kvirc/kvs/kvi_kvs_treenode_thisobjectfunctioncall.cpp
new file mode 100644
index 00000000..6f3e7578
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_thisobjectfunctioncall.cpp
@@ -0,0 +1,73 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_thisobjectfunctioncall.cpp
+// Created on Tue 07 Oct 2003 03:28:10 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_thisobjectfunctioncall.h"
+#include "kvi_kvs_object.h"
+
+
+KviKvsTreeNodeThisObjectFunctionCall::KviKvsTreeNodeThisObjectFunctionCall(const QChar * pLocation,const QString &szFncName,KviKvsTreeNodeDataList * pParams)
+: KviKvsTreeNodeObjectFunctionCall(pLocation,szFncName,pParams)
+{
+}
+
+KviKvsTreeNodeThisObjectFunctionCall::~KviKvsTreeNodeThisObjectFunctionCall()
+{
+}
+
+void KviKvsTreeNodeThisObjectFunctionCall::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "\"This\" Object Function Call \"";
+ szBuffer += m_szFunctionName;
+ szBuffer += "\"";
+#endif
+}
+
+void KviKvsTreeNodeThisObjectFunctionCall::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s ThisObjectFunctionCall(%s)",prefix,m_szFunctionName.utf8().data());
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pParams->dump(tmp.utf8().data());
+#endif
+}
+
+
+bool KviKvsTreeNodeThisObjectFunctionCall::evaluateReadOnlyInObjectScope(KviKvsObject * o,KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ KviKvsVariantList l;
+ if(!m_pParams->evaluate(c,&l))return false;
+ pBuffer->setNothing();
+ c->setDefaultReportLocation(this);
+ return o->callFunction(c->thisObject(),m_szFunctionName,QString::null,c,pBuffer,&l);
+#else
+ return false;
+#endif
+}
+
+
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_thisobjectfunctioncall.h b/src/kvirc/kvs/kvi_kvs_treenode_thisobjectfunctioncall.h
new file mode 100644
index 00000000..2b245f50
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_thisobjectfunctioncall.h
@@ -0,0 +1,49 @@
+#ifndef _KVI_KVS_TREENODE_THISOBJECTFUNCTIONCALL_H_
+#define _KVI_KVS_TREENODE_THISOBJECTFUNCTIONCALL_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_thisobjectfunctioncall.h
+// Created on Tue 07 Oct 2003 03:28:10 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_treenode_datalist.h"
+#include "kvi_kvs_treenode_objectfunctioncall.h"
+
+
+class KviKvsObject;
+class KviKvsRunTimeContext;
+class KviKvsVariant;
+
+class KVIRC_API KviKvsTreeNodeThisObjectFunctionCall : public KviKvsTreeNodeObjectFunctionCall
+{
+public:
+ KviKvsTreeNodeThisObjectFunctionCall(const QChar * pLocation,const QString &szFncName,KviKvsTreeNodeDataList * pParams);
+ ~KviKvsTreeNodeThisObjectFunctionCall();
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool evaluateReadOnlyInObjectScope(KviKvsObject * o,KviKvsRunTimeContext * c,KviKvsVariant * pBuffer);
+};
+
+
+#endif //!_KVI_KVS_TREENODE_THISOBJECTFUNCTIONCALL_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_variable.cpp b/src/kvirc/kvs/kvi_kvs_treenode_variable.cpp
new file mode 100644
index 00000000..2d0f56e6
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_variable.cpp
@@ -0,0 +1,54 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_variable.cpp
+// Created on Thu 16 Oct 2003 22:34:59 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_variable.h"
+
+KviKvsTreeNodeVariable::KviKvsTreeNodeVariable(const QChar * pLocation,const QString &szIdentifier)
+: KviKvsTreeNodeData(pLocation)
+{
+#ifdef COMPILE_NEW_KVS
+ m_szIdentifier = szIdentifier;
+#endif
+}
+
+KviKvsTreeNodeVariable::~KviKvsTreeNodeVariable()
+{
+}
+
+bool KviKvsTreeNodeVariable::isReadOnly()
+{
+ return false;
+}
+
+bool KviKvsTreeNodeVariable::canEvaluateInObjectScope()
+{
+ return false;
+}
+
+bool KviKvsTreeNodeVariable::canEvaluateToObjectReference()
+{
+ return true;
+}
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_variable.h b/src/kvirc/kvs/kvi_kvs_treenode_variable.h
new file mode 100644
index 00000000..7368e680
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_variable.h
@@ -0,0 +1,47 @@
+#ifndef _KVI_KVS_TREENODE_VARIABLE_H_
+#define _KVI_KVS_TREENODE_VARIABLE_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_variable.h
+// Created on Thu 16 Oct 2003 22:34:59 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_treenode_data.h"
+#include "kvi_kvs_variant.h"
+
+class KviKvsRunTimeContext;
+
+class KVIRC_API KviKvsTreeNodeVariable : public KviKvsTreeNodeData
+{
+public:
+ KviKvsTreeNodeVariable(const QChar * pLocation,const QString &szIdentifier);
+ ~KviKvsTreeNodeVariable();
+protected:
+ QString m_szIdentifier;
+protected:
+ virtual bool isReadOnly();
+ virtual bool canEvaluateInObjectScope();
+ virtual bool canEvaluateToObjectReference();
+};
+
+#endif //!_KVI_KVS_TREENODE_VARIABLE_H_
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_voidfunctioncall.cpp b/src/kvirc/kvs/kvi_kvs_treenode_voidfunctioncall.cpp
new file mode 100644
index 00000000..0a788ef4
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_voidfunctioncall.cpp
@@ -0,0 +1,66 @@
+//=============================================================================
+//
+// File : kvi_kvs_treenode_voidfunctioncall.cpp
+// Created on Thu 09 Oct 2003 01:47:16 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_treenode_voidfunctioncall.h"
+#include "kvi_kvs_runtimecontext.h"
+
+KviKvsTreeNodeVoidFunctionCall::KviKvsTreeNodeVoidFunctionCall(const QChar * pLocation,KviKvsTreeNodeFunctionCall * r)
+: KviKvsTreeNodeInstruction(pLocation)
+{
+#ifdef COMPILE_NEW_KVS
+ m_pFunctionCall = r;
+#endif
+}
+
+KviKvsTreeNodeVoidFunctionCall::~KviKvsTreeNodeVoidFunctionCall()
+{
+#ifdef COMPILE_NEW_KVS
+ delete m_pFunctionCall;
+#endif
+}
+
+void KviKvsTreeNodeVoidFunctionCall::contextDescription(QString &szBuffer)
+{
+#ifdef COMPILE_NEW_KVS
+ szBuffer = "Void Function Call";
+#endif
+}
+
+void KviKvsTreeNodeVoidFunctionCall::dump(const char * prefix)
+{
+#ifdef COMPILE_NEW_KVS
+ debug("%s VoidFunctionCall",prefix);
+ QString tmp = prefix;
+ tmp.append(" ");
+ m_pFunctionCall->dump(tmp.utf8().data());
+#endif
+}
+
+bool KviKvsTreeNodeVoidFunctionCall::execute(KviKvsRunTimeContext * c)
+{
+ KviKvsVariant v;
+ return m_pFunctionCall->evaluateReadOnly(c,&v);
+}
diff --git a/src/kvirc/kvs/kvi_kvs_treenode_voidfunctioncall.h b/src/kvirc/kvs/kvi_kvs_treenode_voidfunctioncall.h
new file mode 100644
index 00000000..13b08ba4
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_treenode_voidfunctioncall.h
@@ -0,0 +1,47 @@
+#ifndef _KVI_KVS_TREENODE_VOIDFUNCTIONCALL_H_
+#define _KVI_KVS_TREENODE_VOIDFUNCTIONCALL_H_
+//=============================================================================
+//
+// File : kvi_kvs_treenode_voidfunctioncall.h
+// Created on Thu 09 Oct 2003 01:47:16 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#include "kvi_kvs_treenode_instruction.h"
+#include "kvi_kvs_treenode_functioncall.h"
+
+class KviKvsRunTimeContext;
+
+class KVIRC_API KviKvsTreeNodeVoidFunctionCall : public KviKvsTreeNodeInstruction
+{
+public:
+ KviKvsTreeNodeVoidFunctionCall(const QChar * pLocation,KviKvsTreeNodeFunctionCall * r);
+ ~KviKvsTreeNodeVoidFunctionCall();
+protected:
+ KviKvsTreeNodeFunctionCall * m_pFunctionCall; // may be scope operator or direct function call
+public:
+ virtual void contextDescription(QString &szBuffer);
+ virtual void dump(const char * prefix);
+ virtual bool execute(KviKvsRunTimeContext * c);
+};
+
+#endif //!_KVI_KVS_TREENODE_VOIDFUNCTIONCALL_H_
diff --git a/src/kvirc/kvs/kvi_kvs_types.h b/src/kvirc/kvs/kvi_kvs_types.h
new file mode 100644
index 00000000..bf2b04b1
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_types.h
@@ -0,0 +1,38 @@
+#ifndef _KVI_KVS_TYPES_H_
+#define _KVI_KVS_TYPES_H_
+//=============================================================================
+//
+// File : kvi_kvs_types.h
+// Creation date : Sun 29 May 2005 05.25 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_inttypes.h"
+
+// we want to have 64 bit arithmetics, if possible...
+
+typedef void * kvs_hobject_t;
+typedef kvi_i64_t kvs_int_t;
+typedef kvi_u64_t kvs_uint_t;
+typedef double kvs_real_t;
+
+
+#endif //!_KVI_KVS_TYPES_H_
diff --git a/src/kvirc/kvs/kvi_kvs_useraction.cpp b/src/kvirc/kvs/kvi_kvs_useraction.cpp
new file mode 100644
index 00000000..47a342a3
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_useraction.cpp
@@ -0,0 +1,277 @@
+//=============================================================================
+//
+// File : kvi_kvs_useraction.cpp
+// Created on Tue 07 Dec 2004 02:00:24 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_useraction.h"
+#include "kvi_kvs_script.h"
+#include "kvi_config.h"
+#include "kvi_iconmanager.h"
+#include "kvi_actionmanager.h"
+#include "kvi_kvs_script.h"
+#include "kvi_window.h"
+#include "kvi_cmdformatter.h"
+
+KviKvsUserAction::KviKvsUserAction(QObject * pParent,
+ const QString &szName,
+ const QString &szScriptCode,
+ const QString &szVisibleNameCode,
+ const QString &szDescriptionCode,
+ const QString &szCategory,
+ const QString &szBigIcon,
+ const QString &szSmallIcon,
+ unsigned int uFlags,
+ const QString &szKeySequence)
+ : KviKvsAction(pParent,szName,szScriptCode,szVisibleNameCode,szDescriptionCode,0,szBigIcon,0,uFlags,szKeySequence)
+{
+ m_szSmallIcon = szSmallIcon;
+
+ QString szKvsName = "action::";
+ szKvsName += szName;
+
+ QString szTmp = szKvsName;
+ szTmp += "::description";
+ m_pDescriptionScript = new KviKvsScript(szTmp,szDescriptionCode,KviKvsScript::Parameter);
+
+ szTmp = szKvsName;
+ szTmp += "::label";
+ m_pVisibleNameScript = new KviKvsScript(szTmp,szVisibleNameCode,KviKvsScript::Parameter);
+
+ m_szCategory = szCategory;
+ m_pCategory = KviActionManager::instance()->category(szCategory);
+}
+
+
+KviKvsUserAction::KviKvsUserAction(QObject * pParent)
+ : KviKvsAction(pParent,QString::null,QString::null,QString::null,QString::null)
+{
+ // needs loading!
+ m_pDescriptionScript = 0;
+ m_pVisibleNameScript = 0;
+}
+
+KviKvsUserAction::~KviKvsUserAction()
+{
+ if(m_pDescriptionScript)delete m_pDescriptionScript;
+ if(m_pVisibleNameScript)delete m_pVisibleNameScript;
+}
+
+KviKvsUserAction * KviKvsUserAction::createInstance(QObject * pParent,
+ const QString &szName,
+ const QString &szScriptCode,
+ const QString &szVisibleNameCode,
+ const QString &szDescriptionCode,
+ const QString &szCategory,
+ const QString &szBigIcon,
+ const QString &szSmallIcon,
+ unsigned int uFlags,
+ const QString &szKeySequence)
+{
+ return new KviKvsUserAction(pParent,szName,szScriptCode,szVisibleNameCode,szDescriptionCode,szCategory,szBigIcon,szSmallIcon,uFlags,szKeySequence);
+}
+
+
+void KviKvsUserAction::exportToKvs(QString &szBuffer)
+{
+ exportToKvs(szBuffer,m_szName,scriptCode(),visibleNameCode(),descriptionCode(),m_szCategory,m_szBigIcon,m_szSmallIcon,m_uFlags,m_szKeySequence);
+}
+
+void KviKvsUserAction::exportToKvs(QString &szBuffer,
+ const QString &szName,
+ const QString &szScriptCode,
+ const QString &szVisibleName,
+ const QString &szDescription,
+ const QString &szCategory,
+ const QString &szBigIcon,
+ const QString &szSmallIcon,
+ unsigned int uFlags,
+ const QString &szKeySequence)
+{
+ szBuffer += "action.create";
+ if(uFlags & NeedsContext)
+ {
+ szBuffer += " -i";
+ if(uFlags & NeedsConnection)
+ {
+ szBuffer += " -c";
+ if(uFlags & EnableAtLogin)szBuffer += " -l";
+ }
+ }
+ if(uFlags & InternalWindowMask)
+ {
+ QString szWins;
+ if(uFlags & WindowConsole)szWins += "x";
+ if(uFlags & WindowChannel)szWins += "c";
+ if(uFlags & WindowQuery)szWins += "q";
+ if(uFlags & WindowDccChat)szWins += "d";
+ szBuffer += " -w=";
+ szBuffer += szWins;
+ if(uFlags & (WindowConsole | WindowChannel | WindowQuery))
+ {
+ if(uFlags & WindowOnlyIfUsersSelected)
+ szBuffer += " -s";
+ }
+ }
+ if(!szCategory.isEmpty())
+ {
+ szBuffer += " -t=";
+ szBuffer += szCategory;
+ }
+ if(!szKeySequence.isEmpty())
+ {
+ szBuffer += " -k=\"";
+ szBuffer += szKeySequence;
+ szBuffer += "\"";
+ }
+ szBuffer += " (\"";
+ szBuffer += szName;
+ szBuffer += "\",";
+ QString tmp = szVisibleName;
+ if(tmp.contains('$'))
+ {
+ szBuffer += tmp;
+ szBuffer += ",";
+ } else {
+ tmp.replace("\"","\\\"");
+ szBuffer += "\"";
+ szBuffer += tmp;
+ szBuffer += "\",";
+ }
+ tmp = szDescription;
+ if(tmp.contains('$'))
+ {
+ szBuffer += tmp;
+ szBuffer += ",\"";
+ } else {
+ tmp.replace("\"","\\\"");
+ szBuffer += "\"";
+ szBuffer += tmp;
+ szBuffer += "\",\"";
+ }
+ szBuffer += szBigIcon;
+ szBuffer += "\",\"";
+ szBuffer += szSmallIcon;
+ szBuffer += "\")\n";
+ tmp = szScriptCode;
+ KviCommandFormatter::blockFromBuffer(tmp);
+ szBuffer += tmp;
+ szBuffer += "\n";
+}
+
+
+// FIXME: Cache this stuff ??
+
+const QString & KviKvsUserAction::visibleName()
+{
+ if(!m_pVisibleNameScript)return m_szVisibleName;
+ if(!m_pVisibleNameScript->run(g_pActiveWindow,0,m_szVisibleName))m_szVisibleName = m_pVisibleNameScript->code();
+ return m_szVisibleName;
+}
+
+const QString & KviKvsUserAction::description()
+{
+ if(!m_pDescriptionScript)return m_szDescription;
+ if(!m_pDescriptionScript->run(g_pActiveWindow,0,m_szDescription))m_szDescription = m_pDescriptionScript->code();
+ return m_szDescription;
+}
+
+const QString & KviKvsUserAction::visibleNameCode()
+{
+ if(!m_pVisibleNameScript)return m_szVisibleName;
+ return m_pVisibleNameScript->code();
+}
+
+const QString & KviKvsUserAction::descriptionCode()
+{
+ if(!m_pDescriptionScript)return m_szDescription;
+ return m_pDescriptionScript->code();
+}
+
+QPixmap * KviKvsUserAction::smallIcon()
+{
+ return g_pIconManager->getImage(m_szSmallIcon.utf8().data());
+}
+
+bool KviKvsUserAction::isKviUserActionNeverOverrideThis()
+{
+ return true;
+}
+
+bool KviKvsUserAction::load(KviConfig * cfg)
+{
+ m_szName = cfg->group();
+ if(m_szName.isEmpty())return false;
+ m_szVisibleName = cfg->readQStringEntry("VisibleName");
+ if(m_szVisibleName.isEmpty())return false;
+ QString szKvsName = "action::";
+ szKvsName += m_szName;
+ QString szTmp = szKvsName;
+ szTmp += "::label";
+
+ if(m_pVisibleNameScript)delete m_pVisibleNameScript;
+ m_pVisibleNameScript = new KviKvsScript(szTmp,m_szVisibleName,KviKvsScript::Parameter);
+
+ if(m_szVisibleName.isEmpty())return false;
+ m_szDescription = cfg->readQStringEntry("Description");
+ szTmp = szKvsName;
+ szTmp += "::description";
+
+ if(m_pDescriptionScript)delete m_pDescriptionScript;
+ m_pDescriptionScript = new KviKvsScript(szTmp,m_szDescription,KviKvsScript::Parameter);
+
+
+ m_szBigIcon = cfg->readQStringEntry("BigIcon");
+ m_szSmallIcon = cfg->readQStringEntry("SmallIcon");
+ m_szKeySequence = cfg->readQStringEntry("KeySequence");
+ m_szCategory = cfg->readQStringEntry("Category");
+ m_pCategory = KviActionManager::instance()->category(m_szCategory);
+ m_uFlags = cfg->readUIntEntry("Flags",0);
+
+ QString szCode = cfg->readQStringEntry("Code");
+ if(szCode.isEmpty())return false;
+
+ if(m_pScript)delete m_pScript;
+ QString tmp = KVI_KVS_ACTION_SCRIPT_NAME_PREFIX;
+ tmp += m_szName;
+ m_pScript = new KviKvsScript(tmp,szCode);
+
+ return true;
+}
+
+void KviKvsUserAction::save(KviConfig * cfg)
+{
+ cfg->setGroup(m_szName);
+ if(m_pVisibleNameScript)cfg->writeEntry("VisibleName",m_pVisibleNameScript->code());
+ if(m_pDescriptionScript)
+ {
+ if(!m_pDescriptionScript->code().isEmpty())cfg->writeEntry("Description",m_pDescriptionScript->code());
+ }
+ if(!m_szBigIcon.isEmpty())cfg->writeEntry("BigIcon",m_szBigIcon);
+ if(!m_szSmallIcon.isEmpty())cfg->writeEntry("SmallIcon",m_szSmallIcon);
+ if(!m_szCategory.isEmpty())cfg->writeEntry("Category",m_szCategory);
+ if(!m_szKeySequence.isEmpty())cfg->writeEntry("KeySequence",m_szKeySequence);
+ if(m_uFlags != 0)cfg->writeEntry("Flags",m_uFlags);
+ cfg->writeEntry("Code",m_pScript->code());
+}
+
diff --git a/src/kvirc/kvs/kvi_kvs_useraction.h b/src/kvirc/kvs/kvi_kvs_useraction.h
new file mode 100644
index 00000000..2edd0337
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_useraction.h
@@ -0,0 +1,97 @@
+#ifndef _KVI_KVS_USERACTION_H_
+#define _KVI_KVS_USERACTION_H_
+//=============================================================================
+//
+// File : kvi_kvs_useraction.h
+// Created on Tue 07 Dec 2004 02:00:24 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_kvs_action.h"
+
+class KviConfig;
+class KviKvsScript;
+
+class KVIRC_API KviKvsUserAction : public KviKvsAction
+{
+ friend class KviActionManager;
+ Q_OBJECT
+public:
+ KviKvsUserAction(QObject * pParent,
+ const QString &szName,
+ const QString &szScriptCode,
+ const QString &szVisibleNameCode,
+ const QString &szDescriptionCode,
+ const QString &szCategory,
+ const QString &szBigIcon,
+ const QString &szSmallIcon,
+ unsigned int uFlags,
+ const QString &szKeySequence = QString::null);
+ KviKvsUserAction(QObject * pParent);
+ ~KviKvsUserAction();
+
+ // Static allocator function.
+ // This MUST be used by the modules to allocate action structures
+ // instead of the new operator.
+ // See kvi_heapobject.cpp for an explaination.
+ static KviKvsUserAction * createInstance(QObject * pParent,
+ const QString &szName,
+ const QString &szScriptCode,
+ const QString &szVisibleNameCode,
+ const QString &szDescriptionCode,
+ const QString &szCategory,
+ const QString &szBigIcon,
+ const QString &szSmallIcon,
+ unsigned int uFlags,
+ const QString &szKeySequence = QString::null);
+ void suicide() { delete this; };
+protected:
+ QString m_szSmallIcon;
+ QString m_szCategory;
+ KviKvsScript * m_pDescriptionScript;
+ KviKvsScript * m_pVisibleNameScript;
+protected:
+ virtual bool isKviUserActionNeverOverrideThis();
+ bool load(KviConfig * cfg);
+ void save(KviConfig * cfg);
+public:
+ virtual const QString & visibleName();
+ virtual const QString & description();
+ const QString & visibleNameCode();
+ const QString & descriptionCode();
+ virtual QPixmap * smallIcon();
+ const QString & category(){ return m_szCategory; };
+ const QString & smallIconString(){ return m_szSmallIcon; };
+ static void exportToKvs(QString &szBuffer,
+ const QString &szName,
+ const QString &szScriptCode,
+ const QString &szVisibleName,
+ const QString &szDescription,
+ const QString &szCategory,
+ const QString &szBigIcon,
+ const QString &szSmallIcon,
+ unsigned int uFlags,
+ const QString &szKeySequence);
+ void exportToKvs(QString &szBuffer);
+};
+
+
+#endif //!_KVI_KVS_USERACTION_H_
diff --git a/src/kvirc/kvs/kvi_kvs_variant.cpp b/src/kvirc/kvs/kvi_kvs_variant.cpp
new file mode 100644
index 00000000..b21fd956
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_variant.cpp
@@ -0,0 +1,1615 @@
+//=============================================================================
+//
+// File : kvi_kvs_variant.cpp
+// Created on Tue 07 Oct 2003 04:01:19 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_variant.h"
+#include "kvi_kvs_arraycast.h"
+#include "kvi_kvs_hash.h"
+#include "kvi_kvs_array.h"
+
+#include <math.h>
+
+KviKvsVariant::KviKvsVariant()
+{
+ m_pData = 0;
+}
+
+KviKvsVariant::KviKvsVariant(QString * pString)
+{
+ m_pData = new KviKvsVariantData;
+ m_pData->m_eType = KviKvsVariantData::String;
+ m_pData->m_uRefs = 1;
+ m_pData->m_u.pString = pString;
+}
+
+KviKvsVariant::KviKvsVariant(const QString &szString)
+{
+ m_pData = new KviKvsVariantData;
+ m_pData->m_eType = KviKvsVariantData::String;
+ m_pData->m_uRefs = 1;
+ m_pData->m_u.pString = new QString(szString);
+}
+
+KviKvsVariant::KviKvsVariant(const char * szString)
+{
+ m_pData = new KviKvsVariantData;
+ m_pData->m_eType = KviKvsVariantData::String;
+ m_pData->m_uRefs = 1;
+ m_pData->m_u.pString = new QString(QString::fromUtf8(szString));
+}
+
+
+KviKvsVariant::KviKvsVariant(KviKvsArray * pArray)
+{
+ m_pData = new KviKvsVariantData;
+ m_pData->m_eType = KviKvsVariantData::Array;
+ m_pData->m_uRefs = 1;
+ m_pData->m_u.pArray = pArray;
+}
+
+KviKvsVariant::KviKvsVariant(KviKvsHash * pHash)
+{
+ m_pData = new KviKvsVariantData;
+ m_pData->m_eType = KviKvsVariantData::Hash;
+ m_pData->m_uRefs = 1;
+ m_pData->m_u.pHash = pHash;
+}
+
+KviKvsVariant::KviKvsVariant(kvs_real_t * pReal)
+{
+ m_pData = new KviKvsVariantData;
+ m_pData->m_eType = KviKvsVariantData::Real;
+ m_pData->m_uRefs = 1;
+ m_pData->m_u.pReal = pReal;
+}
+
+KviKvsVariant::KviKvsVariant(kvs_real_t dReal)
+{
+ m_pData = new KviKvsVariantData;
+ m_pData->m_eType = KviKvsVariantData::Real;
+ m_pData->m_uRefs = 1;
+ m_pData->m_u.pReal = new kvs_real_t;
+ *(m_pData->m_u.pReal) = dReal;
+}
+
+KviKvsVariant::KviKvsVariant(bool bBoolean)
+{
+ m_pData = new KviKvsVariantData;
+ m_pData->m_eType = KviKvsVariantData::Boolean;
+ m_pData->m_uRefs = 1;
+ m_pData->m_u.bBoolean = bBoolean;
+}
+
+KviKvsVariant::KviKvsVariant(kvs_int_t iInteger)
+{
+ m_pData = new KviKvsVariantData;
+ m_pData->m_eType = KviKvsVariantData::Integer;
+ m_pData->m_uRefs = 1;
+ m_pData->m_u.iInteger = iInteger;
+}
+
+KviKvsVariant::KviKvsVariant(kvs_hobject_t hObject)
+{
+ m_pData = new KviKvsVariantData;
+ m_pData->m_eType = KviKvsVariantData::HObject;
+ m_pData->m_uRefs = 1;
+ m_pData->m_u.hObject = hObject;
+}
+
+KviKvsVariant::KviKvsVariant(const KviKvsVariant &v)
+{
+ m_pData = v.m_pData;
+ if(m_pData)m_pData->m_uRefs++;
+}
+
+#define DELETE_VARIANT_CONTENTS \
+ switch(m_pData->m_eType) \
+ { \
+ case KviKvsVariantData::Array: delete m_pData->m_u.pArray; break; \
+ case KviKvsVariantData::Hash: delete m_pData->m_u.pHash; break; \
+ case KviKvsVariantData::String: delete m_pData->m_u.pString; break; \
+ case KviKvsVariantData::Real: delete m_pData->m_u.pReal; break; \
+ default: /* make gcc happy */ break; \
+ }
+
+#define DETACH_CONTENTS \
+ if(m_pData) \
+ { \
+ if(m_pData->m_uRefs <= 1) \
+ { \
+ DELETE_VARIANT_CONTENTS \
+ delete m_pData; \
+ } else { \
+ m_pData->m_uRefs--; \
+ } \
+ }
+
+#define RENEW_VARIANT_DATA \
+ if(m_pData) \
+ { \
+ if(m_pData->m_uRefs > 1) \
+ { \
+ m_pData->m_uRefs--; \
+ m_pData = new KviKvsVariantData; \
+ m_pData->m_uRefs = 1; \
+ } else { \
+ DELETE_VARIANT_CONTENTS \
+ } \
+ } else { \
+ m_pData = new KviKvsVariantData; \
+ m_pData->m_uRefs = 1; \
+ }
+
+KviKvsVariant::~KviKvsVariant()
+{
+ DETACH_CONTENTS
+}
+
+void KviKvsVariant::setString(QString * pString)
+{
+ RENEW_VARIANT_DATA
+ m_pData->m_eType = KviKvsVariantData::String;
+ m_pData->m_u.pString = pString;
+}
+
+void KviKvsVariant::setString(const QString &szString)
+{
+ RENEW_VARIANT_DATA
+ m_pData->m_eType = KviKvsVariantData::String;
+ m_pData->m_u.pString = new QString(szString);
+}
+
+void KviKvsVariant::setReal(kvs_real_t dReal)
+{
+ RENEW_VARIANT_DATA
+ m_pData->m_eType = KviKvsVariantData::Real;
+ m_pData->m_u.pReal = new kvs_real_t;
+ *(m_pData->m_u.pReal) = dReal;
+}
+
+void KviKvsVariant::setHObject(kvs_hobject_t hObject)
+{
+ RENEW_VARIANT_DATA
+ m_pData->m_eType = KviKvsVariantData::HObject;
+ m_pData->m_u.hObject = hObject;
+}
+
+void KviKvsVariant::setBoolean(bool bBoolean)
+{
+ RENEW_VARIANT_DATA
+ m_pData->m_eType = KviKvsVariantData::Boolean;
+ m_pData->m_u.bBoolean = bBoolean;
+}
+
+void KviKvsVariant::setReal(kvs_real_t * pReal)
+{
+ RENEW_VARIANT_DATA
+ m_pData->m_eType = KviKvsVariantData::Real;
+ m_pData->m_u.pReal = pReal;
+}
+
+void KviKvsVariant::setInteger(kvs_int_t iInteger)
+{
+ RENEW_VARIANT_DATA
+ m_pData->m_eType = KviKvsVariantData::Integer;
+ m_pData->m_u.iInteger = iInteger;
+}
+
+void KviKvsVariant::setArray(KviKvsArray * pArray)
+{
+ RENEW_VARIANT_DATA
+ m_pData->m_eType = KviKvsVariantData::Array;
+ m_pData->m_u.pArray = pArray;
+}
+
+void KviKvsVariant::setHash(KviKvsHash * pHash)
+{
+ RENEW_VARIANT_DATA
+ m_pData->m_eType = KviKvsVariantData::Hash;
+ m_pData->m_u.pHash = pHash;
+}
+
+void KviKvsVariant::setNothing()
+{
+ if(m_pData)
+ {
+ if(m_pData->m_uRefs <= 1)
+ {
+ DELETE_VARIANT_CONTENTS
+ delete m_pData;
+ } else {
+ // just detach
+ m_pData->m_uRefs--;
+ }
+ m_pData = 0;
+ }
+}
+
+bool KviKvsVariant::isEmpty() const
+{
+ if(!m_pData)return true;
+ switch(m_pData->m_eType)
+ {
+ case KviKvsVariantData::String: return m_pData->m_u.pString->isEmpty(); break;
+ case KviKvsVariantData::Array: return m_pData->m_u.pArray->isEmpty(); break;
+ case KviKvsVariantData::Hash: return m_pData->m_u.pHash->isEmpty(); break;
+ case KviKvsVariantData::HObject: return m_pData->m_u.hObject == 0; break;
+ default: /* make gcc happy */ break;
+ }
+ return false;
+}
+
+bool KviKvsVariant::asBoolean() const
+{
+ if(!m_pData)return false;
+ switch(m_pData->m_eType)
+ {
+ case KviKvsVariantData::Boolean: return m_pData->m_u.bBoolean; break;
+ case KviKvsVariantData::String:
+ {
+ if(m_pData->m_u.pString->isEmpty())return false;
+ // check integer or real values
+ bool bOk;
+ kvs_int_t iVal = (kvs_int_t)KviQString::toI64(*(m_pData->m_u.pString),&bOk);
+ if(bOk)return iVal;
+ kvs_real_t dVal = m_pData->m_u.pString->toDouble(&bOk);
+ if(bOk)return (dVal != 0.0);
+ // non number, non empty
+ return true;
+ }
+ break;
+ case KviKvsVariantData::Integer: return m_pData->m_u.iInteger; break;
+ case KviKvsVariantData::Real: return *(m_pData->m_u.pReal) != 0.0; break;
+ case KviKvsVariantData::Array: return !(m_pData->m_u.pArray->isEmpty()); break;
+ case KviKvsVariantData::Hash: return !(m_pData->m_u.pHash->isEmpty()); break;
+ case KviKvsVariantData::HObject: return m_pData->m_u.hObject; break;
+ default: /* make gcc happy */ break;
+ }
+ debug("WARNING: invalid variant type %d in KviKvsVariant::asBoolean()",m_pData->m_eType);
+ return false;
+}
+
+bool KviKvsVariant::asHObject(kvs_hobject_t &hObject) const
+{
+ if(!m_pData)
+ {
+ // nothing evaluates to a null object
+ hObject = 0;
+ return true;
+ }
+ switch(m_pData->m_eType)
+ {
+ case KviKvsVariantData::HObject:
+ hObject = m_pData->m_u.hObject;
+ return true;
+ break;
+ case KviKvsVariantData::Integer:
+ if(m_pData->m_u.iInteger == 0)
+ {
+ hObject = 0;
+ return true;
+ }
+ return false;
+ break;
+ case KviKvsVariantData::String:
+ if(*(m_pData->m_u.pString) == "0")
+ {
+ hObject = 0;
+ return true;
+ }
+ return false;
+ break;
+ case KviKvsVariantData::Boolean:
+ if(!(m_pData->m_u.bBoolean))
+ {
+ hObject = 0;
+ return true;
+ }
+ default: /* make gcc happy */ break;
+ }
+ return false;
+}
+
+
+bool KviKvsVariant::asNumber(KviKvsNumber &n) const
+{
+ if(!m_pData)return false;
+
+ if(isInteger())
+ {
+ n.m_u.iInteger = m_pData->m_u.iInteger;
+ n.m_type = KviKvsNumber::Integer;
+ return true;
+ }
+ if(isReal())
+ {
+ n.m_u.dReal = *(m_pData->m_u.pReal);
+ n.m_type = KviKvsNumber::Real;
+ return true;
+ }
+ if(asInteger(n.m_u.iInteger))
+ {
+ n.m_type = KviKvsNumber::Integer;
+ return true;
+ }
+ if(asReal(n.m_u.dReal))
+ {
+ n.m_type = KviKvsNumber::Real;
+ return true;
+ }
+ return false;
+}
+
+
+void KviKvsVariant::castToNumber(KviKvsNumber &n) const
+{
+ if(!m_pData)
+ {
+ n.m_u.iInteger = 0;
+ n.m_type = KviKvsNumber::Integer;
+ return;
+ }
+
+ if(isInteger())
+ {
+ n.m_u.iInteger = m_pData->m_u.iInteger;
+ n.m_type = KviKvsNumber::Integer;
+ return;
+ }
+ if(isReal())
+ {
+ n.m_u.dReal = *(m_pData->m_u.pReal);
+ n.m_type = KviKvsNumber::Real;
+ return;
+ }
+ if(asInteger(n.m_u.iInteger))
+ {
+ n.m_type = KviKvsNumber::Integer;
+ return;
+ }
+ if(asReal(n.m_u.dReal))
+ {
+ n.m_type = KviKvsNumber::Real;
+ return;
+ }
+ castToInteger(n.m_u.iInteger);
+ n.m_type = KviKvsNumber::Integer;
+}
+
+void KviKvsVariant::castToArray(KviKvsArrayCast *c) const
+{
+ if(!m_pData)
+ {
+ c->set(new KviKvsArray(),true);
+ return;
+ }
+
+ switch(m_pData->m_eType)
+ {
+ case KviKvsVariantData::Array:
+ c->set(m_pData->m_u.pArray,false);
+ break;
+ case KviKvsVariantData::Hash:
+ {
+ KviPointerHashTableIterator<QString,KviKvsVariant> it(*(m_pData->m_u.pHash->dict()));
+ KviKvsArray * a = new KviKvsArray();
+ kvs_int_t idx = 0;
+ while(KviKvsVariant * v = it.current())
+ {
+ a->set(idx,new KviKvsVariant(*v));
+ ++it;
+ idx++;
+ }
+ c->set(a,true);
+ }
+ break;
+ default:
+ {
+ // other scalars
+ KviKvsArray * a = new KviKvsArray();
+ a->set(0,new KviKvsVariant(*this));
+ c->set(a,true);
+ }
+ break;
+ }
+}
+
+void KviKvsVariant::convertToArray()
+{
+ if(!m_pData)
+ {
+ setArray(new KviKvsArray());
+ return;
+ }
+
+ switch(m_pData->m_eType)
+ {
+ case KviKvsVariantData::Array:
+ return;
+ break;
+ case KviKvsVariantData::Hash:
+ {
+ KviPointerHashTableIterator<QString,KviKvsVariant> it(*(m_pData->m_u.pHash->dict()));
+ KviKvsArray * a = new KviKvsArray();
+ kvs_int_t idx = 0;
+ while(KviKvsVariant * v = it.current())
+ {
+ a->set(idx,new KviKvsVariant(*v));
+ ++it;
+ idx++;
+ }
+ setArray(a);
+ }
+ break;
+ default:
+ {
+ // other scalars
+ KviKvsArray * a = new KviKvsArray();
+ a->set(0,new KviKvsVariant(*this));
+ setArray(a);
+ }
+ break;
+ }
+}
+
+bool KviKvsVariant::asInteger(kvs_int_t &iVal) const
+{
+ if(!m_pData)return false;
+ switch(m_pData->m_eType)
+ {
+ case KviKvsVariantData::Integer:
+ iVal = m_pData->m_u.iInteger;
+ return true;
+ break;
+ case KviKvsVariantData::String:
+ {
+ bool bOk;
+ iVal = (kvs_int_t)KviQString::toI64(*(m_pData->m_u.pString),&bOk);
+ return bOk;
+ }
+ break;
+ case KviKvsVariantData::Real:
+ // FIXME: this truncates the value!
+ iVal = (kvs_int_t)*(m_pData->m_u.pReal);
+ return true;
+ break;
+ case KviKvsVariantData::Boolean:
+ iVal = m_pData->m_u.bBoolean ? 1 : 0;
+ return true;
+ break;
+ //case KviKvsVariantData::HObject: <-- light casts from objects to integer are not valid
+ // iVal = m_pData->m_u.hObject ? 1 : 0;
+ // return true;
+ //break;
+ default: /* make gcc happy */
+ break;
+ }
+ return false;
+}
+
+void KviKvsVariant::castToInteger(kvs_int_t &iVal) const
+{
+ if(!m_pData)
+ {
+ iVal = 0;
+ return;
+ }
+ switch(m_pData->m_eType)
+ {
+ case KviKvsVariantData::Integer:
+ iVal = m_pData->m_u.iInteger;
+ break;
+ case KviKvsVariantData::Boolean:
+ iVal = m_pData->m_u.bBoolean ? 1 : 0;
+ break;
+ case KviKvsVariantData::HObject:
+ iVal = m_pData->m_u.hObject ? 1 : 0;
+ break;
+ case KviKvsVariantData::String:
+ {
+ bool bOk;
+ iVal = (kvs_int_t)KviQString::toI64(*(m_pData->m_u.pString),&bOk);
+ if(bOk)return;
+ iVal = m_pData->m_u.pString->length();
+ }
+ break;
+ case KviKvsVariantData::Real:
+ // FIXME: this truncates the value!
+ iVal = (kvs_int_t)*(m_pData->m_u.pReal);
+ break;
+ case KviKvsVariantData::Array:
+ iVal = m_pData->m_u.pArray->size();
+ break;
+ case KviKvsVariantData::Hash:
+ iVal = m_pData->m_u.pHash->size();
+ break;
+ default: /* make gcc happy */
+ iVal = 0;
+ break;
+ }
+}
+
+
+bool KviKvsVariant::asReal(kvs_real_t & dVal) const
+{
+ if(!m_pData)return false;
+ switch(m_pData->m_eType)
+ {
+ case KviKvsVariantData::Integer:
+ dVal = m_pData->m_u.iInteger;
+ return true;
+ break;
+ case KviKvsVariantData::String:
+ {
+ bool bOk;
+ dVal = m_pData->m_u.pString->toDouble(&bOk);
+ return bOk;
+ }
+ break;
+ case KviKvsVariantData::Real:
+ dVal = *(m_pData->m_u.pReal);
+ return true;
+ break;
+ case KviKvsVariantData::Boolean:
+ dVal = m_pData->m_u.bBoolean ? 1.0 : 0.0;
+ return true;
+ break;
+ default: /* by default we make gcc happy */ break;
+ }
+ return false;
+}
+
+void KviKvsVariant::asString(QString &szBuffer) const
+{
+ if(!m_pData)
+ {
+ szBuffer = QString::null;
+ return;
+ }
+ switch(m_pData->m_eType)
+ {
+ case KviKvsVariantData::String: szBuffer = *(m_pData->m_u.pString); break;
+ case KviKvsVariantData::Array: szBuffer = QString::null; m_pData->m_u.pArray->appendAsString(szBuffer); break;
+ case KviKvsVariantData::Hash: szBuffer = QString::null; m_pData->m_u.pHash->appendAsString(szBuffer); break;
+ case KviKvsVariantData::Integer: szBuffer.setNum(m_pData->m_u.iInteger); break;
+ case KviKvsVariantData::Real: szBuffer.setNum(*(m_pData->m_u.pReal)); break;
+ case KviKvsVariantData::Boolean: szBuffer.setNum(m_pData->m_u.bBoolean ? 1 : 0); break;
+ case KviKvsVariantData::HObject:
+ if(m_pData->m_u.hObject)
+ KviQString::sprintf(szBuffer,"object[%lx]",m_pData->m_u.hObject);
+ else
+ szBuffer = "null-object";
+ break;
+ default: /* make gcc happy */ break;
+ }
+}
+
+void KviKvsVariant::appendAsString(QString &szBuffer) const
+{
+ if(!m_pData)return;
+ switch(m_pData->m_eType)
+ {
+ case KviKvsVariantData::String: szBuffer.append(*(m_pData->m_u.pString)); break;
+ case KviKvsVariantData::Array: m_pData->m_u.pArray->appendAsString(szBuffer); break;
+ case KviKvsVariantData::Hash: m_pData->m_u.pHash->appendAsString(szBuffer); break;
+ case KviKvsVariantData::Integer: KviQString::appendNumber(szBuffer,m_pData->m_u.iInteger); break;
+ case KviKvsVariantData::Real: KviQString::appendNumber(szBuffer,*(m_pData->m_u.pReal)); break;
+ case KviKvsVariantData::Boolean: KviQString::appendNumber(szBuffer,m_pData->m_u.bBoolean ? 1 : 0); break;
+ case KviKvsVariantData::HObject: szBuffer.append(m_pData->m_u.hObject ? "object" : "null-object"); break;
+ default: /* make gcc happy */ break;
+ }
+}
+
+void KviKvsVariant::dump(const char * prefix) const
+{
+ if(!m_pData)
+ {
+ debug("%s Nothing [this=0x%lx]",prefix,this);
+ return;
+ }
+ switch(m_pData->m_eType)
+ {
+ case KviKvsVariantData::String: debug("%s String(%s) [this=0x%lx]",prefix,m_pData->m_u.pString->utf8().data(),this); break;
+ case KviKvsVariantData::Array: debug("%s Array(ptr=0x%lx) [this=0x%lx]",prefix,m_pData->m_u.pArray,this); break;
+ case KviKvsVariantData::Hash: debug("%s Hash(ptr=0x%lx,dict=0x%lx) [this=0x%lx]",prefix,m_pData->m_u.pHash,m_pData->m_u.pHash->dict(),this); break;
+ case KviKvsVariantData::Integer: debug("%s Integer(%d) [this=0x%lx]",prefix,m_pData->m_u.iInteger,this); break;
+ case KviKvsVariantData::Real: debug("%s Real(%f) [this=0x%lx]",prefix,*(m_pData->m_u.pReal),this); break;
+ case KviKvsVariantData::Boolean: debug("%s Boolean(%s) [this=0x%lx]",prefix,m_pData->m_u.bBoolean ? "true" : "false",this); break;
+ case KviKvsVariantData::HObject: debug("%s HObject(%lx) [this=0x%lx]",prefix,m_pData->m_u.hObject,this); break;
+ default: /* make gcc happy */ break;
+ }
+}
+
+void KviKvsVariant::copyFrom(const KviKvsVariant * v)
+{
+ DETACH_CONTENTS
+ m_pData = v->m_pData;
+ if(m_pData)m_pData->m_uRefs++;
+}
+
+void KviKvsVariant::copyFrom(const KviKvsVariant &v)
+{
+ DETACH_CONTENTS
+ m_pData = v.m_pData;
+ if(m_pData)m_pData->m_uRefs++;
+
+}
+
+void KviKvsVariant::takeFrom(KviKvsVariant * v)
+{
+ DETACH_CONTENTS
+ m_pData = v->m_pData;
+ v->m_pData = 0;
+}
+
+void KviKvsVariant::takeFrom(KviKvsVariant &v)
+{
+ DETACH_CONTENTS
+ m_pData = v.m_pData;
+ v.m_pData = 0;
+}
+
+void KviKvsVariant::getTypeName(QString &szBuffer) const
+{
+ if(!m_pData)
+ {
+ szBuffer = "nothing";
+ return;
+ }
+ switch(m_pData->m_eType)
+ {
+ case KviKvsVariantData::String: szBuffer = "string"; break;
+ case KviKvsVariantData::Hash: szBuffer = "hash"; break;
+ case KviKvsVariantData::Array: szBuffer = "array"; break;
+ case KviKvsVariantData::Real: szBuffer = "real"; break;
+ case KviKvsVariantData::Integer: szBuffer = "integer"; break;
+ case KviKvsVariantData::Boolean: szBuffer = "boolean"; break;
+ case KviKvsVariantData::HObject: szBuffer = "hobject"; break;
+ default: szBuffer = "internal_error"; break;
+ }
+}
+
+bool KviKvsVariant::isEqualToNothing() const
+{
+ if(!m_pData)return true;
+ switch(m_pData->m_eType)
+ {
+ case KviKvsVariantData::HObject:
+ return (m_pData->m_u.hObject == (kvs_hobject_t)0);
+ break;
+ case KviKvsVariantData::Integer:
+ return (m_pData->m_u.iInteger == 0);
+ break;
+ case KviKvsVariantData::Real:
+ return (*(m_pData->m_u.pReal) == 0.0);
+ break;
+ case KviKvsVariantData::String:
+ {
+ if(m_pData->m_u.pString->isEmpty())return true;
+ kvs_real_t dReal;
+ if(asReal(dReal))
+ return dReal == 0.0;
+ return false;
+ }
+ break;
+ case KviKvsVariantData::Boolean:
+ return !m_pData->m_u.bBoolean;
+ break;
+ case KviKvsVariantData::Hash:
+ return m_pData->m_u.pHash->isEmpty();
+ break;
+ case KviKvsVariantData::Array:
+ return m_pData->m_u.pArray->isEmpty();
+ break;
+ default:
+ break;
+ }
+
+ return false;
+}
+
+
+#define CMP_THISGREATER -1
+#define CMP_EQUAL 0
+#define CMP_OTHERGREATER 1
+
+class KviKvsVariantComparison
+{
+public:
+ static inline int compare_integer_string(const KviKvsVariant * v1,const KviKvsVariant * v2)
+ {
+ if(v1->m_pData->m_u.iInteger == 0)
+ {
+ if(v2->m_pData->m_u.pString->isEmpty())return CMP_EQUAL;
+ }
+ kvs_real_t dReal;
+ if(v2->asReal(dReal))
+ {
+ if(((kvs_real_t)v1->m_pData->m_u.iInteger) == dReal)return CMP_EQUAL;
+ if(((kvs_real_t)v1->m_pData->m_u.iInteger) > dReal)return CMP_THISGREATER;
+ return CMP_OTHERGREATER;
+ }
+ // compare as strings instead
+ QString szString;
+ v1->asString(szString);
+ return -1 * KviQString::cmpCI(szString,*(v2->m_pData->m_u.pString));
+ }
+
+ static inline int compare_integer_real(const KviKvsVariant * v1,const KviKvsVariant * v2)
+ {
+ if(((kvs_real_t)v1->m_pData->m_u.iInteger) == *(v2->m_pData->m_u.pReal))return CMP_EQUAL;
+ if(((kvs_real_t)v1->m_pData->m_u.iInteger) > *(v2->m_pData->m_u.pReal))return CMP_THISGREATER;
+ return CMP_OTHERGREATER;
+ }
+
+ static inline int compare_integer_boolean(const KviKvsVariant * v1,const KviKvsVariant * v2)
+ {
+ if(v1->m_pData->m_u.iInteger == 0)
+ return v2->m_pData->m_u.bBoolean ? CMP_OTHERGREATER : CMP_EQUAL;
+ return v2->m_pData->m_u.bBoolean ? CMP_EQUAL : CMP_THISGREATER;
+ }
+
+ static inline int compare_integer_hash(const KviKvsVariant * v1,const KviKvsVariant * v2)
+ {
+ if(v1->m_pData->m_u.iInteger == 0)
+ return v2->m_pData->m_u.pHash->isEmpty() ? CMP_EQUAL : CMP_OTHERGREATER;
+ return CMP_THISGREATER;
+ }
+
+ static inline int compare_integer_array(const KviKvsVariant * v1,const KviKvsVariant * v2)
+ {
+ if(v1->m_pData->m_u.iInteger == 0)
+ return v2->m_pData->m_u.pArray->isEmpty() ? CMP_EQUAL : CMP_OTHERGREATER;
+ return CMP_THISGREATER;
+ }
+
+ static inline int compare_integer_hobject(const KviKvsVariant * v1,const KviKvsVariant * v2)
+ {
+ if(v1->m_pData->m_u.iInteger == 0.0)
+ return (v2->m_pData->m_u.hObject == (kvs_hobject_t)0) ? CMP_EQUAL : CMP_THISGREATER;
+ return CMP_OTHERGREATER;
+ }
+
+ static inline int compare_real_hobject(const KviKvsVariant * v1,const KviKvsVariant * v2)
+ {
+ if(*(v1->m_pData->m_u.pReal) == 0.0)
+ return (v2->m_pData->m_u.hObject == (kvs_hobject_t)0) ? CMP_EQUAL : CMP_THISGREATER;
+ return CMP_OTHERGREATER;
+ }
+
+ static inline int compare_real_string(const KviKvsVariant * v1,const KviKvsVariant * v2)
+ {
+ if(*(v1->m_pData->m_u.pReal) == 0.0)
+ {
+ if(v2->m_pData->m_u.pString->isEmpty())return CMP_EQUAL;
+ }
+ kvs_real_t dReal;
+ if(v2->asReal(dReal))
+ {
+ if(*(v1->m_pData->m_u.pReal) == dReal)return CMP_EQUAL;
+ if(*(v1->m_pData->m_u.pReal) > dReal)return CMP_THISGREATER;
+ return CMP_OTHERGREATER;
+ }
+ // compare as strings instead
+ QString szString;
+ v1->asString(szString);
+ return -1 * KviQString::cmpCI(szString,*(v2->m_pData->m_u.pString));
+ }
+
+ static inline int compare_real_boolean(const KviKvsVariant * v1,const KviKvsVariant * v2)
+ {
+ if(*(v1->m_pData->m_u.pReal) == 0.0)
+ return v2->m_pData->m_u.bBoolean ? CMP_OTHERGREATER : CMP_EQUAL;
+ return v2->m_pData->m_u.bBoolean ? CMP_EQUAL : CMP_THISGREATER;
+ }
+
+ static inline int compare_real_hash(const KviKvsVariant * v1,const KviKvsVariant * v2)
+ {
+ if(*(v1->m_pData->m_u.pReal) == 0)
+ return v2->m_pData->m_u.pHash->isEmpty() ? CMP_EQUAL : CMP_OTHERGREATER;
+ return CMP_THISGREATER;
+ }
+
+ static inline int compare_real_array(const KviKvsVariant * v1,const KviKvsVariant * v2)
+ {
+ if(*(v1->m_pData->m_u.pReal) == 0)
+ return v2->m_pData->m_u.pArray->isEmpty() ? CMP_EQUAL : CMP_OTHERGREATER;
+ return CMP_THISGREATER;
+ }
+
+ static inline int compare_string_hash(const KviKvsVariant * v1,const KviKvsVariant * v2)
+ {
+ if(v1->m_pData->m_u.pString->isEmpty())
+ {
+ return v2->m_pData->m_u.pHash->isEmpty() ? CMP_EQUAL : CMP_OTHERGREATER;
+ }
+ return CMP_THISGREATER;
+ }
+
+ static inline int compare_string_array(const KviKvsVariant * v1,const KviKvsVariant * v2)
+ {
+ if(v1->m_pData->m_u.pString->isEmpty())
+ {
+ return v2->m_pData->m_u.pArray->isEmpty() ? CMP_EQUAL : CMP_OTHERGREATER;
+ }
+ return CMP_THISGREATER;
+ }
+
+ static inline int compare_string_hobject(const KviKvsVariant * v1,const KviKvsVariant * v2)
+ {
+ if(v2->m_pData->m_u.hObject == (kvs_hobject_t)0)
+ {
+ if(v1->m_pData->m_u.pString->isEmpty())
+ return CMP_EQUAL;
+ kvs_real_t dReal;
+ if(v1->asReal(dReal))
+ {
+ if(dReal == 0)return CMP_EQUAL;
+ }
+ }
+
+ return CMP_THISGREATER;
+ }
+
+ static inline int compare_boolean_string(const KviKvsVariant * v1,const KviKvsVariant * v2)
+ {
+ if(v2->isEqualToNothing())
+ {
+ return v1->m_pData->m_u.bBoolean ? CMP_THISGREATER : CMP_EQUAL;
+ } else {
+ return v1->m_pData->m_u.bBoolean ? CMP_EQUAL : CMP_THISGREATER;
+ }
+ }
+
+ static inline int compare_boolean_hash(const KviKvsVariant * v1,const KviKvsVariant * v2)
+ {
+ if(v1->m_pData->m_u.bBoolean)
+ return v2->m_pData->m_u.pHash->isEmpty() ? CMP_THISGREATER : CMP_EQUAL;
+ else
+ return v2->m_pData->m_u.pHash->isEmpty() ? CMP_EQUAL : CMP_OTHERGREATER;
+ }
+
+ static inline int compare_boolean_array(const KviKvsVariant * v1,const KviKvsVariant * v2)
+ {
+ if(v1->m_pData->m_u.bBoolean)
+ return v2->m_pData->m_u.pArray->isEmpty() ? CMP_THISGREATER : CMP_EQUAL;
+ else
+ return v2->m_pData->m_u.pArray->isEmpty() ? CMP_EQUAL : CMP_OTHERGREATER;
+ }
+
+ static inline int compare_boolean_hobject(const KviKvsVariant * v1,const KviKvsVariant * v2)
+ {
+ if(v1->m_pData->m_u.bBoolean)
+ return v2->m_pData->m_u.hObject == ((kvs_hobject_t)0) ? CMP_THISGREATER : CMP_EQUAL;
+ else
+ return v2->m_pData->m_u.hObject == ((kvs_hobject_t)0) ? CMP_EQUAL : CMP_OTHERGREATER;
+ }
+
+ static inline int compare_array_hash(const KviKvsVariant * v1,const KviKvsVariant * v2)
+ {
+ if(v1->m_pData->m_u.pArray->size() > v2->m_pData->m_u.pHash->size())return CMP_THISGREATER;
+ if(v1->m_pData->m_u.pArray->size() == v2->m_pData->m_u.pHash->size())return CMP_EQUAL;
+ return CMP_OTHERGREATER;
+ }
+
+ static inline int compare_hobject_hash(const KviKvsVariant * v1,const KviKvsVariant * v2)
+ {
+ if(v2->m_pData->m_u.pHash->isEmpty())
+ return v1->m_pData->m_u.hObject == ((kvs_hobject_t)0) ? CMP_EQUAL : CMP_OTHERGREATER;
+ return v1->m_pData->m_u.hObject == ((kvs_hobject_t)0) ? CMP_THISGREATER : CMP_EQUAL;
+ }
+
+ static inline int compare_hobject_array(const KviKvsVariant * v1,const KviKvsVariant * v2)
+ {
+ if(v2->m_pData->m_u.pArray->isEmpty())
+ return v1->m_pData->m_u.hObject == ((kvs_hobject_t)0) ? CMP_EQUAL : CMP_OTHERGREATER;
+ return v1->m_pData->m_u.hObject == ((kvs_hobject_t)0) ? CMP_THISGREATER : CMP_EQUAL;
+ }
+
+};
+void KviKvsVariant::serializeString(QString& buffer)
+{
+ buffer.replace('\\',"\\\\");
+ buffer.replace('\n',"\\n");
+ buffer.replace('\r',"\\r");
+ buffer.replace('\b',"\\b");
+ buffer.replace('\t',"\\t");
+ buffer.replace('\f',"\\f");
+ buffer.replace('/',"\\/");
+ buffer.replace('"',"\\\"");
+ buffer.prepend('"');
+ buffer.append('"');
+}
+
+void KviKvsVariant::serialize(QString& result)
+{
+ switch(m_pData->m_eType)
+ {
+ case KviKvsVariantData::HObject:
+ //can't serialize objects yet
+ break;
+ case KviKvsVariantData::Integer:
+ result.setNum(m_pData->m_u.iInteger);
+ break;
+ case KviKvsVariantData::Real:
+ result.setNum(*(m_pData->m_u.pReal));
+ break;
+ case KviKvsVariantData::String:
+ result = *(m_pData->m_u.pString);
+ serializeString(result);
+ break;
+ case KviKvsVariantData::Boolean:
+ result = m_pData->m_u.bBoolean ? "true" : "false";
+ break;
+ case KviKvsVariantData::Hash:
+ m_pData->m_u.pHash->serialize(result);
+ break;
+ case KviKvsVariantData::Array:
+ m_pData->m_u.pArray->serialize(result);
+ break;
+ case KviKvsVariantData::Nothing:
+ result="null";
+ break;
+ default: // just make gcc happy
+ break;
+ }
+}
+
+KviKvsVariant* KviKvsVariant::unserializeTrue(const QChar** aux)
+{
+ if(KviQString::equalCIN(QString("true"),*aux,4))
+ {
+ (*aux)+=4;
+ return new KviKvsVariant(true);
+ }
+ return 0;
+}
+
+KviKvsVariant* KviKvsVariant::unserializeFalse(const QChar** aux)
+{
+ if(KviQString::equalCIN(QString("false"),*aux,5))
+ {
+ (*aux)+=5;
+ return new KviKvsVariant(false);
+ }
+ return 0;
+}
+
+KviKvsVariant* KviKvsVariant::unserializeNull(const QChar** aux)
+{
+ if(KviQString::equalCIN(QString("null"),*aux,4))
+ {
+ (*aux)+=4;
+ return new KviKvsVariant();
+ }
+ return 0;
+}
+
+KviKvsVariant* KviKvsVariant::unserializeRealOrInteger(const QChar** aux)
+{
+ QString data;
+ if((*aux)->unicode() == '-')
+ {
+ data.append('-');
+ (*aux)++;
+ }
+ if(!(*aux)->isDigit())
+ {
+ return 0;
+ }
+ while((*aux)->isDigit())
+ {
+ data.append(**aux);
+ (*aux)++;
+ }
+ if((*aux)->unicode()=='.')
+ {
+ return unserializeReal(aux,data);
+ }
+ return unserializeInteger(aux,data);
+}
+
+KviKvsVariant* KviKvsVariant::unserializeReal(const QChar** aux,QString& data)
+{
+ QString exponent;
+ (*aux)++; //skip .
+ data.append('.');
+ while((*aux)->isDigit())
+ {
+ data.append(**aux);
+ (*aux)++;
+ }
+
+ if((*aux)->unicode() == 'e' || (*aux)->unicode() == 'E')
+ {
+ (*aux)++;
+ if((*aux)->unicode() == '-')
+ {
+ exponent.append('-');
+ (*aux)++;
+ } else {
+ if((*aux)->unicode() == '+')
+ {
+ exponent.append('+');
+ (*aux)++;
+ }
+ }
+
+ while((*aux)->isDigit())
+ {
+ exponent.append(**aux);
+ (*aux)++;
+ }
+ }
+
+
+
+ float value = data.toFloat();
+ if(!exponent.isNull())
+ {
+ value*=pow(10.0,exponent.toInt());
+ }
+ return new KviKvsVariant(value);
+}
+
+KviKvsVariant* KviKvsVariant::unserializeInteger(const QChar** aux,QString& data)
+{
+
+ QString exponent;
+
+ if((*aux)->unicode() == 'e' || (*aux)->unicode() == 'E')
+ {
+ (*aux)++;
+ if((*aux)->unicode() == '-')
+ {
+ exponent.append('-');
+ (*aux)++;
+ } else {
+ if((*aux)->unicode() == '+')
+ {
+ exponent.append('+');
+ (*aux)++;
+ }
+ }
+
+ while((*aux)->isDigit())
+ {
+ exponent.append(**aux);
+ (*aux)++;
+ }
+ }
+
+ kvs_int_t value = data.toInt();
+ if(!exponent.isNull())
+ {
+ value*=pow(10.0,exponent.toInt());
+ }
+ return new KviKvsVariant(value);
+}
+
+KviKvsVariant* KviKvsVariant::unserializeString(const QChar** aux)
+{
+ QString buffer;
+ unserializeString(aux,buffer);
+ return new KviKvsVariant(buffer);
+}
+
+void KviKvsVariant::unserializeString(const QChar** aux,QString& data)
+{
+ data="";
+ QString hex; //temp var
+ //skip leading "
+ (*aux)++;
+ while((*aux)->unicode())
+ {
+ switch((*aux)->unicode())
+ {
+ case '"':
+ //EOF
+ (*aux)++;
+ return;
+ break;
+ case '\\':
+ //Special
+ (*aux)++;
+ switch((*aux)->unicode())
+ {
+ case 't':
+ data.append('\t');
+ break;
+ case '\"':
+ data.append('\"');
+ break;
+ case '/':
+ data.append('/');
+ case 'b':
+ data.append('\b');
+ case 'f':
+ data.append('\f');
+ break;
+ case 'n':
+ data.append('\n');
+ break;
+ case 'r':
+ data.append('\r');
+ break;
+ case 'u':
+ //4 hexadecmical digits pending...
+ hex="";
+ (*aux)++;
+ for(int k=0;k<4 && (*aux)->unicode(); k++)
+ {
+ if((*aux)->isDigit() ||
+ ((*aux)->unicode() >='A' && (*aux)->unicode() <='F')|| //ABCDEF
+ ((*aux)->unicode() >='a' && (*aux)->unicode() <='f')) //abcdef
+ {
+ hex.append(**aux);
+ (*aux)++;
+ } else {
+ break;
+ }
+ }
+ (*aux)--;
+ data.append(QChar(hex.toUInt(0,16)));
+ break;
+ default:
+ //Fallback; incorrect escape
+ (*aux)--;
+ data.append('\\');
+ }
+ (*aux)++;
+ break;
+ default:
+ data.append(**aux);
+ (*aux)++;
+ break;
+ }
+ }
+}
+
+KviKvsVariant* KviKvsVariant::unserializeHash(const QChar** aux)
+{
+ KviKvsHash* pHash = new KviKvsHash();
+ QString szKey;
+ KviKvsVariant* pElement = 0;
+ //skip leading '{'
+ (*aux)++;
+ int i=0;
+ while(1)
+ {
+ //skip leading space
+ while((*aux)->isSpace())
+ (*aux)++;
+ //waiting for starting of string
+ if((*aux)->unicode()!='\"')
+ {
+ //strange characters
+ delete pHash;
+ return 0;
+ }
+ unserializeString(aux,szKey);
+ if(szKey.isEmpty())
+ {
+ //Strange element name
+ delete pHash;
+ return 0;
+ }
+
+ //skip leading space before ':'
+ while((*aux)->isSpace())
+ (*aux)++;
+ //waiting for name-value delimeter
+ if((*aux)->unicode()!=':')
+ {
+ //strange characters
+ delete pHash;
+ return 0;
+ }
+ (*aux)++;
+
+
+ //getting element
+ pElement = unserialize(aux);
+ if(pElement)
+ {
+ pHash->set(szKey,pElement);
+ i++;
+ while((*aux)->isSpace())
+ (*aux)++;
+ switch((*aux)->unicode())
+ {
+ case ',':
+ //goto next
+ (*aux)++;
+ break;
+ case '}':
+ //EOF array
+ (*aux)++;
+ return new KviKvsVariant(pHash);
+ break;
+ default:
+ delete pHash;
+ return 0;
+ break;
+ }
+ } else {
+ //error
+ delete pHash;
+ return 0;
+ }
+ }
+ return 0;
+}
+
+KviKvsVariant* KviKvsVariant::unserializeArray(const QChar** aux)
+{
+ KviKvsArray* pArray = new KviKvsArray();
+ KviKvsVariant* pElement = 0;
+ (*aux)++;
+ int i=0;
+ while(1)
+ {
+ pElement = unserialize(aux);
+ if(pElement)
+ {
+ pArray->set(i,pElement);
+ i++;
+ while((*aux)->isSpace())
+ (*aux)++;
+ switch((*aux)->unicode())
+ {
+ case ',':
+ //goto next
+ (*aux)++;
+ break;
+ case ']':
+ //EOF array
+ (*aux)++;
+ return new KviKvsVariant(pArray);
+ break;
+ default:
+ delete pArray;
+ return 0;
+ break;
+ }
+ } else {
+ //error
+ delete pArray;
+ return 0;
+ }
+ }
+ return 0;
+}
+
+KviKvsVariant* KviKvsVariant::unserialize(const QChar** aux)
+{
+ KviKvsVariant* pResult = 0;
+
+ while((*aux)->isSpace())
+ (*aux)++;
+
+ switch((*aux)->unicode())
+ {
+ case 't':
+ //true
+ pResult = unserializeTrue(aux);
+ break;
+ case 'f':
+ //false
+ pResult = unserializeFalse(aux);
+ break;
+ case 'n':
+ //null
+ pResult = unserializeNull(aux);
+ break;
+ case '[':
+ //array
+ pResult = unserializeArray(aux);
+ break;
+ case '{':
+ //hash
+ pResult = unserializeHash(aux);
+ break;
+ case '"':
+ //string
+ pResult = unserializeString(aux);
+ break;
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '0':
+ case '-':
+ //real or integer
+ pResult = unserializeRealOrInteger(aux);
+ break;
+ default:
+ //incorrect value
+ return 0;
+ }
+
+ while((*aux)->isSpace())
+ (*aux)++;
+
+ return pResult;
+}
+
+KviKvsVariant* KviKvsVariant::unserialize(const QString& data)
+{
+ KviKvsVariant* pResult = 0;
+
+#ifdef COMPILE_USE_QT4
+ const QChar * aux = (const QChar *)data.constData();
+#else
+ const QChar * aux = (const QChar *)data.ucs2();
+#endif
+
+ pResult = unserialize(&aux);
+
+ if(aux->unicode())
+ {
+ //strange extra characters?
+ if(pResult) delete pResult;
+ pResult = 0;
+ }
+
+ return pResult;
+}
+
+int KviKvsVariant::compare(const KviKvsVariant * pOther,bool bPreferNumeric) const
+{
+ // returns -1 if this variant is greater than pOther
+ // 0 if they are considered to be equal
+ // 1 if the other variant is greater
+
+ if(!pOther)
+ return isEqualToNothing() ? CMP_EQUAL : CMP_THISGREATER;
+ if(!pOther->m_pData)
+ return isEqualToNothing() ? CMP_EQUAL : CMP_THISGREATER;
+ if(!m_pData)
+ return pOther->isEqualToNothing() ? CMP_EQUAL : CMP_OTHERGREATER;
+
+ switch(m_pData->m_eType)
+ {
+ case KviKvsVariantData::HObject:
+ switch(pOther->m_pData->m_eType)
+ {
+ case KviKvsVariantData::HObject:
+ if(m_pData->m_u.hObject == pOther->m_pData->m_u.hObject)return CMP_EQUAL;
+ if(m_pData->m_u.hObject == ((kvs_hobject_t)0))return CMP_OTHERGREATER;
+ return CMP_THISGREATER;
+ break;
+ case KviKvsVariantData::Integer:
+ return -1 * KviKvsVariantComparison::compare_integer_hobject(pOther,this);
+ break;
+ case KviKvsVariantData::Real:
+ return -1 * KviKvsVariantComparison::compare_real_hobject(pOther,this);
+ break;
+ case KviKvsVariantData::String:
+ return -1 * KviKvsVariantComparison::compare_string_hobject(pOther,this);
+ break;
+ case KviKvsVariantData::Boolean:
+ return -1 * KviKvsVariantComparison::compare_boolean_hobject(pOther,this);
+ break;
+ case KviKvsVariantData::Hash:
+ return KviKvsVariantComparison::compare_hobject_hash(this,pOther);
+ break;
+ case KviKvsVariantData::Array:
+ return KviKvsVariantComparison::compare_hobject_array(this,pOther);
+ break;
+ default: // just make gcc happy
+ break;
+ }
+ break;
+ case KviKvsVariantData::Integer:
+ switch(pOther->m_pData->m_eType)
+ {
+ case KviKvsVariantData::HObject:
+ return KviKvsVariantComparison::compare_integer_hobject(this,pOther);
+ break;
+ case KviKvsVariantData::Integer:
+ if(m_pData->m_u.iInteger == pOther->m_pData->m_u.iInteger)return CMP_EQUAL;
+ if(m_pData->m_u.iInteger > pOther->m_pData->m_u.iInteger)return CMP_THISGREATER;
+ return CMP_OTHERGREATER;
+ break;
+ case KviKvsVariantData::Real:
+ return KviKvsVariantComparison::compare_integer_real(this,pOther);
+ break;
+ case KviKvsVariantData::String:
+ return KviKvsVariantComparison::compare_integer_string(this,pOther);
+ break;
+ case KviKvsVariantData::Boolean:
+ return KviKvsVariantComparison::compare_integer_boolean(this,pOther);
+ break;
+ case KviKvsVariantData::Hash:
+ return KviKvsVariantComparison::compare_integer_hash(this,pOther);
+ break;
+ case KviKvsVariantData::Array:
+ return KviKvsVariantComparison::compare_integer_array(this,pOther);
+ break;
+ default: // just make gcc happy
+ break;
+ }
+ break;
+ case KviKvsVariantData::Real:
+ switch(pOther->m_pData->m_eType)
+ {
+ case KviKvsVariantData::HObject:
+ return KviKvsVariantComparison::compare_real_hobject(this,pOther);
+ break;
+ case KviKvsVariantData::Integer:
+ return -1 * KviKvsVariantComparison::compare_integer_real(pOther,this);
+ break;
+ case KviKvsVariantData::Real:
+ if(*(m_pData->m_u.pReal) == *(pOther->m_pData->m_u.pReal))return CMP_EQUAL;
+ if(*(m_pData->m_u.pReal) > *(pOther->m_pData->m_u.pReal))return CMP_THISGREATER;
+ return CMP_OTHERGREATER;
+ break;
+ case KviKvsVariantData::String:
+ return KviKvsVariantComparison::compare_real_string(this,pOther);
+ break;
+ case KviKvsVariantData::Boolean:
+ return KviKvsVariantComparison::compare_real_boolean(this,pOther);
+ break;
+ case KviKvsVariantData::Hash:
+ return KviKvsVariantComparison::compare_real_hash(this,pOther);
+ break;
+ case KviKvsVariantData::Array:
+ return KviKvsVariantComparison::compare_real_array(this,pOther);
+ break;
+ default: // just make gcc happy
+ break;
+ }
+ break;
+ case KviKvsVariantData::String:
+ switch(pOther->m_pData->m_eType)
+ {
+ case KviKvsVariantData::String:
+ if(bPreferNumeric)
+ {
+ // prefer numeric comparison
+ double dReal1;
+ double dReal2;
+ if(asReal(dReal1))
+ {
+ if(pOther->asReal(dReal2))
+ {
+ if(dReal1 == dReal2)return CMP_EQUAL;
+ if(dReal1 > dReal2)return CMP_THISGREATER;
+ return CMP_OTHERGREATER;
+ }
+ }
+ }
+ return -1 * KviQString::cmpCI(*(m_pData->m_u.pString),*(pOther->m_pData->m_u.pString));
+ case KviKvsVariantData::Real:
+ return -1 * KviKvsVariantComparison::compare_real_string(pOther,this);
+ case KviKvsVariantData::Integer:
+ return -1 * KviKvsVariantComparison::compare_integer_string(pOther,this);
+ case KviKvsVariantData::Boolean:
+ return -1 * KviKvsVariantComparison::compare_boolean_string(pOther,this);
+ break;
+ case KviKvsVariantData::Hash:
+ return KviKvsVariantComparison::compare_string_hash(this,pOther);
+ break;
+ case KviKvsVariantData::Array:
+ return KviKvsVariantComparison::compare_string_array(this,pOther);
+ break;
+ case KviKvsVariantData::HObject:
+ return KviKvsVariantComparison::compare_string_hobject(this,pOther);
+ break;
+ }
+ break;
+ case KviKvsVariantData::Hash:
+ switch(pOther->m_pData->m_eType)
+ {
+ case KviKvsVariantData::String:
+ return -1 * KviKvsVariantComparison::compare_string_hash(pOther,this);
+ case KviKvsVariantData::Real:
+ return -1 * KviKvsVariantComparison::compare_real_hash(pOther,this);
+ break;
+ case KviKvsVariantData::Integer:
+ return -1 * KviKvsVariantComparison::compare_integer_hash(pOther,this);
+ break;
+ case KviKvsVariantData::Boolean:
+ return -1 * KviKvsVariantComparison::compare_boolean_hash(pOther,this);
+ break;
+ case KviKvsVariantData::Hash:
+ if(m_pData->m_u.pHash->size() > pOther->m_pData->m_u.pHash->size())return CMP_THISGREATER;
+ if(m_pData->m_u.pHash->size() == pOther->m_pData->m_u.pHash->size())return CMP_EQUAL;
+ return CMP_OTHERGREATER;
+ break;
+ case KviKvsVariantData::Array:
+ return -1 * KviKvsVariantComparison::compare_array_hash(pOther,this);
+ break;
+ case KviKvsVariantData::HObject:
+ return -1 * KviKvsVariantComparison::compare_hobject_hash(pOther,this);
+ break;
+ }
+ break;
+ case KviKvsVariantData::Array:
+ switch(pOther->m_pData->m_eType)
+ {
+ case KviKvsVariantData::String:
+ return -1 * KviKvsVariantComparison::compare_string_array(pOther,this);
+ case KviKvsVariantData::Real:
+ return -1 * KviKvsVariantComparison::compare_real_array(pOther,this);
+ case KviKvsVariantData::Integer:
+ return -1 * KviKvsVariantComparison::compare_integer_array(pOther,this);
+ case KviKvsVariantData::Boolean:
+ return -1 * KviKvsVariantComparison::compare_boolean_array(pOther,this);
+ break;
+ case KviKvsVariantData::Hash:
+ return KviKvsVariantComparison::compare_array_hash(this,pOther);
+ break;
+ case KviKvsVariantData::Array:
+ if(m_pData->m_u.pArray->size() > pOther->m_pData->m_u.pArray->size())return CMP_THISGREATER;
+ if(m_pData->m_u.pArray->size() == pOther->m_pData->m_u.pArray->size())return CMP_EQUAL;
+ return CMP_OTHERGREATER;
+ break;
+ case KviKvsVariantData::HObject:
+ return -1 * KviKvsVariantComparison::compare_hobject_array(pOther,this);
+ break;
+ }
+ break;
+ case KviKvsVariantData::Boolean:
+ switch(pOther->m_pData->m_eType)
+ {
+ case KviKvsVariantData::String:
+ return KviKvsVariantComparison::compare_boolean_string(this,pOther);
+ break;
+ case KviKvsVariantData::Real:
+ return -1 * KviKvsVariantComparison::compare_real_boolean(pOther,this);
+ break;
+ case KviKvsVariantData::Integer:
+ return -1 * KviKvsVariantComparison::compare_integer_boolean(pOther,this);
+ break;
+ case KviKvsVariantData::Boolean:
+ if(m_pData->m_u.bBoolean == pOther->m_pData->m_u.bBoolean)return CMP_EQUAL;
+ if(m_pData->m_u.bBoolean)return CMP_THISGREATER;
+ return CMP_OTHERGREATER;
+ break;
+ case KviKvsVariantData::Hash:
+ return KviKvsVariantComparison::compare_boolean_hash(this,pOther);
+ break;
+ case KviKvsVariantData::Array:
+ return KviKvsVariantComparison::compare_boolean_array(this,pOther);
+ break;
+ case KviKvsVariantData::HObject:
+ return KviKvsVariantComparison::compare_boolean_hobject(this,pOther);
+ break;
+ }
+ break;
+ default: // should never happen anyway
+ break;
+ }
+
+ return CMP_THISGREATER; // should never happen
+}
+
diff --git a/src/kvirc/kvs/kvi_kvs_variant.h b/src/kvirc/kvs/kvi_kvs_variant.h
new file mode 100644
index 00000000..99b64718
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_variant.h
@@ -0,0 +1,208 @@
+#ifndef _KVI_KVS_VARIANT_H_
+#define _KVI_KVS_VARIANT_H_
+//=============================================================================
+//
+// File : kvi_kvs_variant.h
+// Created on Tue 07 Oct 2003 04:01:19 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_heapobject.h"
+#include "kvi_kvs_types.h"
+
+
+class KviKvsVariant;
+class KviKvsArrayCast;
+
+class KVIRC_API KviKvsNumber
+{
+ friend class KviKvsVariant;
+public:
+ enum DataType { Real, Integer };
+protected:
+ union {
+ kvs_int_t iInteger;
+ kvs_real_t dReal;
+ } m_u;
+ DataType m_type;
+public:
+ DataType type() const { return m_type; };
+ bool isReal() const { return m_type == Real; };
+ bool isInteger() const { return m_type == Integer; };
+ kvs_real_t real() const { return m_u.dReal; };
+ kvs_int_t integer() const { return m_u.iInteger; };
+};
+
+// pre-declare.. the real declarations are included below
+class KviKvsHash;
+class KviKvsArray;
+
+class KviKvsVariantData
+{
+public:
+ enum Type {
+ Nothing = 0, // m_pData not initialized
+ String = 1, // QString (scalar)
+ Integer = 2, // long int (scalar)
+ Real = 4, // double (scalar)
+ Array = 8, // KviKvsArray
+ Hash = 16, // KviKvsHash
+ Boolean = 32, // bool (scalar)
+ HObject = 64 // object, shallow! (scalar)
+ };
+public:
+ unsigned int m_uRefs;
+ Type m_eType;
+ union {
+ kvs_int_t iInteger;
+ kvs_real_t * pReal;
+ QString * pString;
+ KviKvsArray * pArray;
+ KviKvsHash * pHash;
+ bool bBoolean;
+ kvs_hobject_t hObject;
+ } m_u;
+};
+
+// This class must not have virtual funcitons nor destructor
+// Otherwise it will happily crash on windows when it is
+// allocated in modules and destroyed anywhere else around...
+class KVIRC_API KviKvsVariant : public KviHeapObject
+{
+ friend class KviKvsVariantComparison;
+public:
+ KviKvsVariant();
+ KviKvsVariant(kvs_int_t iInteger);
+ KviKvsVariant(kvs_real_t dReal);
+ KviKvsVariant(kvs_real_t * pReal);
+ KviKvsVariant(bool bBoolean);
+ KviKvsVariant(const QString &szString);
+ KviKvsVariant(const char * szString); // without this gcc chooses the conversion (const char *)->(void *) instead of (const char *)->(QString) and obviously calls the wrong constructor
+ KviKvsVariant(QString * pString);
+ KviKvsVariant(KviKvsArray * pArray);
+ KviKvsVariant(KviKvsHash * pHash);
+ KviKvsVariant(kvs_hobject_t hObject);
+ KviKvsVariant(const KviKvsVariant &v);
+ ~KviKvsVariant();
+protected:
+ KviKvsVariantData * m_pData;
+public:
+ KviKvsVariantData::Type type(){ return m_pData ? m_pData->m_eType : KviKvsVariantData::Nothing; };
+
+ void setReal(kvs_real_t dReal);
+ void setReal(kvs_real_t * pReal);
+ void setInteger(kvs_int_t iInteger);
+ void setString(const QString &szString);
+ void setString(QString * pString);
+ void setArray(KviKvsArray * pArray);
+ void setHash(KviKvsHash * pHash);
+ void setBoolean(bool bBoolean);
+ void setHObject(kvs_hobject_t hObject);
+ void setNothing();
+ //void unset(){ setNothing(); };
+
+ void getTypeName(QString &szBuffer) const;
+
+ bool isNothing() const { return !m_pData; };
+ bool isInteger() const { return m_pData ? (m_pData->m_eType == KviKvsVariantData::Integer) : false; };
+ bool isReal() const { return m_pData ? (m_pData->m_eType == KviKvsVariantData::Real) : false; };
+ bool isNumeric() const { return m_pData ? (m_pData->m_eType & (KviKvsVariantData::Integer | KviKvsVariantData::Real)) : false; };
+ bool isString() const { return m_pData ? (m_pData->m_eType == KviKvsVariantData::String) : false; };
+ bool isScalar() const { return m_pData ? (m_pData->m_eType & (KviKvsVariantData::String | KviKvsVariantData::Integer | KviKvsVariantData::Real)) : false; };
+ bool isArray() const { return m_pData ? (m_pData->m_eType == KviKvsVariantData::Array) : false; };
+ bool isHash() const { return m_pData ? (m_pData->m_eType == KviKvsVariantData::Hash) : false; };
+ bool isBoolean() const { return m_pData ? (m_pData->m_eType == KviKvsVariantData::Boolean) : false; };
+ bool isHObject() const { return m_pData ? (m_pData->m_eType == KviKvsVariantData::HObject) : false; };
+
+ bool isEmpty() const;
+
+ // returns true if this variant is nothing, false, null, 0 or an empty string
+ bool isEqualToNothing() const;
+
+ // evaluates Integer, Real and String rappresenting an Integer
+ bool asInteger(kvs_int_t &iVal) const;
+ // evaluates Real, Integer and String rappresenting a Real
+ bool asReal(kvs_real_t &dVal) const;
+ // evaluates Real, Integer and String rappresenting a Real or integer
+ bool asNumber(KviKvsNumber &n) const;
+ // always evaluates to a boolean value
+ bool asBoolean() const;
+ // evaluates to an object handle
+ bool asHObject(kvs_hobject_t &hObject) const;
+ // evaluates anything to a string
+ void asString(QString &szBuffer) const;
+ void appendAsString(QString &szBuffer) const;
+
+ // always evaluates to some number...
+ void castToNumber(KviKvsNumber &n) const;
+ // always evaluates to an integer
+ void castToInteger(kvs_int_t &iVal) const;
+ // always evaluates to an array
+ void castToArray(KviKvsArrayCast *c) const;
+ // converts this variant to an array
+ void convertToArray();
+
+ kvs_int_t integer() const { return m_pData ? m_pData->m_u.iInteger : 0; };
+ kvs_real_t real() const { return m_pData ? *(m_pData->m_u.pReal) : 0.0; };
+ const QString & string() const { return m_pData ? *(m_pData->m_u.pString) : KviQString::empty; };
+ KviKvsArray * array() const { return m_pData ? m_pData->m_u.pArray : 0; };
+ KviKvsHash * hash() const { return m_pData ? m_pData->m_u.pHash : 0; };
+ bool boolean() const { return m_pData ? m_pData->m_u.bBoolean : false; };
+ kvs_hobject_t hobject() const { return m_pData ? m_pData->m_u.hObject : (kvs_hobject_t)0; };
+
+ void copyFrom(const KviKvsVariant * v);
+ void copyFrom(const KviKvsVariant & v);
+ void takeFrom(KviKvsVariant * v);
+ void takeFrom(KviKvsVariant &v);
+
+ void dump(const char * prefix) const;
+
+ // returns -1 if this variant is greater than the other, 0 if are equal, 1 if the other is greater
+ // if bPreferNumeric is true then when comparing strings a conversion to a numeric format
+ // is first attempted.
+ int compare(const KviKvsVariant * pOther,bool bPreferNumeric = false) const;
+
+ void operator = (const KviKvsVariant &v){ copyFrom(v); };
+
+ //JSON serialization
+ void serialize(QString& result);
+ static void serializeString(QString& buffer);
+ static KviKvsVariant* unserialize(const QString& buffer);
+private:
+ static KviKvsVariant* unserialize(const QChar** aux);
+ static KviKvsVariant* unserializeTrue(const QChar** aux);
+ static KviKvsVariant* unserializeFalse(const QChar** aux);
+ static KviKvsVariant* unserializeNull(const QChar** aux);
+ static KviKvsVariant* unserializeArray(const QChar** aux);
+ static KviKvsVariant* unserializeHash(const QChar** aux);
+ static void unserializeString(const QChar** aux,QString& buffer);
+ static KviKvsVariant* unserializeString(const QChar** aux);
+ static KviKvsVariant* unserializeRealOrInteger(const QChar** aux);
+ static KviKvsVariant* unserializeReal(const QChar** aux,QString& data);
+ static KviKvsVariant* unserializeInteger(const QChar** aux,QString& data);
+};
+
+#include "kvi_kvs_array.h"
+#include "kvi_kvs_hash.h"
+
+
+#endif //!_KVI_KVS_VARIANT_H_
diff --git a/src/kvirc/kvs/kvi_kvs_variantlist.cpp b/src/kvirc/kvs/kvi_kvs_variantlist.cpp
new file mode 100644
index 00000000..6c10a2a8
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_variantlist.cpp
@@ -0,0 +1,199 @@
+//=============================================================================
+//
+// File : kvi_kvs_variantlist.cpp
+// Created on Sat 11 Oct 2003 02:20:51 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_kvs_variantlist.h"
+
+KviKvsVariantList::KviKvsVariantList()
+{
+ m_pList = new KviPointerList<KviKvsVariant>();
+ m_pList->setAutoDelete(true);
+}
+
+KviKvsVariantList::KviKvsVariantList(KviKvsVariant * v1)
+{
+ m_pList = new KviPointerList<KviKvsVariant>();
+ m_pList->setAutoDelete(true);
+ m_pList->append(v1);
+}
+
+KviKvsVariantList::KviKvsVariantList(KviKvsVariant * v1,KviKvsVariant * v2)
+{
+ m_pList = new KviPointerList<KviKvsVariant>();
+ m_pList->setAutoDelete(true);
+ m_pList->append(v1);
+ m_pList->append(v2);
+}
+
+KviKvsVariantList::KviKvsVariantList(KviKvsVariant * v1,KviKvsVariant * v2,KviKvsVariant * v3)
+{
+ m_pList = new KviPointerList<KviKvsVariant>();
+ m_pList->setAutoDelete(true);
+ m_pList->append(v1);
+ m_pList->append(v2);
+ m_pList->append(v3);
+}
+
+KviKvsVariantList::KviKvsVariantList(KviKvsVariant * v1,KviKvsVariant * v2,KviKvsVariant * v3,KviKvsVariant * v4)
+{
+ m_pList = new KviPointerList<KviKvsVariant>();
+ m_pList->setAutoDelete(true);
+ m_pList->append(v1);
+ m_pList->append(v2);
+ m_pList->append(v3);
+ m_pList->append(v4);
+}
+
+KviKvsVariantList::KviKvsVariantList(KviKvsVariant * v1,KviKvsVariant * v2,KviKvsVariant * v3,KviKvsVariant * v4,KviKvsVariant * v5)
+{
+ m_pList = new KviPointerList<KviKvsVariant>();
+ m_pList->setAutoDelete(true);
+ m_pList->append(v1);
+ m_pList->append(v2);
+ m_pList->append(v3);
+ m_pList->append(v4);
+ m_pList->append(v5);
+}
+
+KviKvsVariantList::KviKvsVariantList(KviKvsVariant * v1,KviKvsVariant * v2,KviKvsVariant * v3,KviKvsVariant * v4,KviKvsVariant * v5,KviKvsVariant * v6)
+{
+ m_pList = new KviPointerList<KviKvsVariant>();
+ m_pList->setAutoDelete(true);
+ m_pList->append(v1);
+ m_pList->append(v2);
+ m_pList->append(v3);
+ m_pList->append(v4);
+ m_pList->append(v5);
+ m_pList->append(v6);
+}
+
+KviKvsVariantList::KviKvsVariantList(KviKvsVariant * v1,KviKvsVariant * v2,KviKvsVariant * v3,KviKvsVariant * v4,KviKvsVariant * v5,KviKvsVariant * v6,KviKvsVariant * v7)
+{
+ m_pList = new KviPointerList<KviKvsVariant>();
+ m_pList->setAutoDelete(true);
+ m_pList->append(v1);
+ m_pList->append(v2);
+ m_pList->append(v3);
+ m_pList->append(v4);
+ m_pList->append(v5);
+ m_pList->append(v6);
+ m_pList->append(v7);
+}
+
+KviKvsVariantList::KviKvsVariantList(QString * s1)
+{
+ m_pList = new KviPointerList<KviKvsVariant>();
+ m_pList->setAutoDelete(true);
+ m_pList->append(new KviKvsVariant(s1));
+}
+
+KviKvsVariantList::KviKvsVariantList(QString * s1,QString * s2)
+{
+ m_pList = new KviPointerList<KviKvsVariant>();
+ m_pList->setAutoDelete(true);
+ m_pList->append(new KviKvsVariant(s1));
+ m_pList->append(new KviKvsVariant(s2));
+}
+
+KviKvsVariantList::KviKvsVariantList(QString * s1,QString * s2,QString * s3)
+{
+ m_pList = new KviPointerList<KviKvsVariant>();
+ m_pList->setAutoDelete(true);
+ m_pList->append(new KviKvsVariant(s1));
+ m_pList->append(new KviKvsVariant(s2));
+ m_pList->append(new KviKvsVariant(s3));
+}
+
+KviKvsVariantList::KviKvsVariantList(QString * s1,QString * s2,QString * s3,QString * s4)
+{
+ m_pList = new KviPointerList<KviKvsVariant>();
+ m_pList->setAutoDelete(true);
+ m_pList->append(new KviKvsVariant(s1));
+ m_pList->append(new KviKvsVariant(s2));
+ m_pList->append(new KviKvsVariant(s3));
+ m_pList->append(new KviKvsVariant(s4));
+}
+
+KviKvsVariantList::KviKvsVariantList(QString * s1,QString * s2,QString * s3,QString * s4,QString * s5)
+{
+ m_pList = new KviPointerList<KviKvsVariant>();
+ m_pList->setAutoDelete(true);
+ m_pList->append(new KviKvsVariant(s1));
+ m_pList->append(new KviKvsVariant(s2));
+ m_pList->append(new KviKvsVariant(s3));
+ m_pList->append(new KviKvsVariant(s4));
+ m_pList->append(new KviKvsVariant(s5));
+}
+
+KviKvsVariantList::KviKvsVariantList(QString * s1,QString * s2,QString * s3,QString * s4,QString * s5,QString * s6)
+{
+ m_pList = new KviPointerList<KviKvsVariant>();
+ m_pList->setAutoDelete(true);
+ m_pList->append(new KviKvsVariant(s1));
+ m_pList->append(new KviKvsVariant(s2));
+ m_pList->append(new KviKvsVariant(s3));
+ m_pList->append(new KviKvsVariant(s4));
+ m_pList->append(new KviKvsVariant(s5));
+ m_pList->append(new KviKvsVariant(s6));
+}
+
+KviKvsVariantList::~KviKvsVariantList()
+{
+ delete m_pList;
+}
+
+
+void KviKvsVariantList::setAutoDelete(bool bAutoDelete)
+{
+ m_pList->setAutoDelete(bAutoDelete);
+}
+
+void KviKvsVariantList::allAsString(QString &szBuffer)
+{
+ szBuffer = QString::null;
+ bool bFirst = true;
+ for(KviKvsVariant * v = first();v;v = next())
+ {
+ if(bFirst)bFirst = false;
+ else szBuffer.append(' ');
+ v->appendAsString(szBuffer);
+ }
+}
+
+bool KviKvsVariantList::firstAsString(QString &szBuffer)
+{
+ KviKvsVariant * v = first();
+ if(!v)return false;
+ v->asString(szBuffer);
+ return true;
+}
+
+bool KviKvsVariantList::nextAsString(QString &szBuffer)
+{
+ KviKvsVariant * v = next();
+ if(!v)return false;
+ v->asString(szBuffer);
+ return true;
+}
diff --git a/src/kvirc/kvs/kvi_kvs_variantlist.h b/src/kvirc/kvs/kvi_kvs_variantlist.h
new file mode 100644
index 00000000..09a24986
--- /dev/null
+++ b/src/kvirc/kvs/kvi_kvs_variantlist.h
@@ -0,0 +1,81 @@
+#ifndef _KVI_KVS_VARIANTLIST_H_
+#define _KVI_KVS_VARIANTLIST_H_
+//=============================================================================
+//
+// File : kvi_kvs_variantlist.h
+// Created on Sat 11 Oct 2003 02:20:51 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_pointerlist.h"
+#include "kvi_kvs_variant.h"
+
+
+
+class KVIRC_API KviKvsVariantList
+{
+public:
+ KviKvsVariantList();
+ KviKvsVariantList(KviKvsVariant * v1);
+ KviKvsVariantList(KviKvsVariant * v1,KviKvsVariant * v2);
+ KviKvsVariantList(KviKvsVariant * v1,KviKvsVariant * v2,KviKvsVariant * v3);
+ KviKvsVariantList(KviKvsVariant * v1,KviKvsVariant * v2,KviKvsVariant * v3,KviKvsVariant * v4);
+ KviKvsVariantList(KviKvsVariant * v1,KviKvsVariant * v2,KviKvsVariant * v3,KviKvsVariant * v4,KviKvsVariant * v5);
+ KviKvsVariantList(KviKvsVariant * v1,KviKvsVariant * v2,KviKvsVariant * v3,KviKvsVariant * v4,KviKvsVariant * v5,KviKvsVariant * v6);
+ KviKvsVariantList(KviKvsVariant * v1,KviKvsVariant * v2,KviKvsVariant * v3,KviKvsVariant * v4,KviKvsVariant * v5,KviKvsVariant * v6,KviKvsVariant * v7);
+ KviKvsVariantList(QString * s1);
+ KviKvsVariantList(QString * s1,QString * s2);
+ KviKvsVariantList(QString * s1,QString * s2,QString * s3);
+ KviKvsVariantList(QString * s1,QString * s2,QString * s3,QString * s4);
+ KviKvsVariantList(QString * s1,QString * s2,QString * s3,QString * s4,QString * s5);
+ KviKvsVariantList(QString * s1,QString * s2,QString * s3,QString * s4,QString * s5,QString * s6);
+ ~KviKvsVariantList();
+protected:
+ KviPointerList<KviKvsVariant> * m_pList;
+public:
+ KviKvsVariant * first(){ return m_pList->first(); };
+ KviKvsVariant * next(){ return m_pList->next(); };
+ KviKvsVariant * at(int iIdx){ return m_pList->at(iIdx); };
+ unsigned int count(){ return m_pList->count(); };
+
+ void clear(){ m_pList->clear(); };
+
+ void append(const QString &szParam){ m_pList->append(new KviKvsVariant(szParam)); };
+ void append(kvs_int_t iInteger){ m_pList->append(new KviKvsVariant(iInteger)); };
+ void append(kvs_real_t dReal){ m_pList->append(new KviKvsVariant(dReal)); };
+ void append(bool bBoolean){ m_pList->append(new KviKvsVariant(bBoolean)); };
+ void append(kvs_hobject_t hObject){ m_pList->append(new KviKvsVariant(hObject)); };
+ void append(KviKvsArray * pArray){ m_pList->append(new KviKvsVariant(pArray)); };
+ void append(KviKvsHash * pHash){ m_pList->append(new KviKvsVariant(pHash)); };
+
+ void append(KviKvsVariant * v){ m_pList->append(v); };
+ void prepend(KviKvsVariant * v){ m_pList->prepend(v); };
+
+ void setAutoDelete(bool bAutoDelete); // this is TRUE by default
+
+ void allAsString(QString &szBuffer);
+ // returns true if there was a first parameter at all
+ bool firstAsString(QString &szBuffer);
+ // returns true if there was a next parameter at all
+ bool nextAsString(QString &szBuffer);
+};
+
+#endif //!_KVI_KVS_VARIANTLIST_H_
diff --git a/src/kvirc/kvs/moc_kvi_kvs_action.cpp b/src/kvirc/kvs/moc_kvi_kvs_action.cpp
new file mode 100644
index 00000000..25fafd8c
--- /dev/null
+++ b/src/kvirc/kvs/moc_kvi_kvs_action.cpp
@@ -0,0 +1,92 @@
+/****************************************************************************
+** KviKvsAction meta object code from reading C++ file 'kvi_kvs_action.h'
+**
+** Created: Mon Feb 25 00:11:56 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_kvs_action.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviKvsAction::className() const
+{
+ return "KviKvsAction";
+}
+
+QMetaObject *KviKvsAction::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviKvsAction( "KviKvsAction", &KviKvsAction::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviKvsAction::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviKvsAction", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviKvsAction::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviKvsAction", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviKvsAction::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = KviAction::staticMetaObject();
+ metaObj = QMetaObject::new_metaobject(
+ "KviKvsAction", parentObject,
+ 0, 0,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviKvsAction.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviKvsAction::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviKvsAction" ) )
+ return this;
+ return KviAction::qt_cast( clname );
+}
+
+bool KviKvsAction::qt_invoke( int _id, QUObject* _o )
+{
+ return KviAction::qt_invoke(_id,_o);
+}
+
+bool KviKvsAction::qt_emit( int _id, QUObject* _o )
+{
+ return KviAction::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviKvsAction::qt_property( int id, int f, QVariant* v)
+{
+ return KviAction::qt_property( id, f, v);
+}
+
+bool KviKvsAction::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvirc/kvs/moc_kvi_kvs_asyncdnsoperation.cpp b/src/kvirc/kvs/moc_kvi_kvs_asyncdnsoperation.cpp
new file mode 100644
index 00000000..0c436dde
--- /dev/null
+++ b/src/kvirc/kvs/moc_kvi_kvs_asyncdnsoperation.cpp
@@ -0,0 +1,107 @@
+/****************************************************************************
+** KviKvsAsyncDnsOperation meta object code from reading C++ file 'kvi_kvs_asyncdnsoperation.h'
+**
+** Created: Mon Feb 25 00:11:58 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_kvs_asyncdnsoperation.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviKvsAsyncDnsOperation::className() const
+{
+ return "KviKvsAsyncDnsOperation";
+}
+
+QMetaObject *KviKvsAsyncDnsOperation::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviKvsAsyncDnsOperation( "KviKvsAsyncDnsOperation", &KviKvsAsyncDnsOperation::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviKvsAsyncDnsOperation::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviKvsAsyncDnsOperation", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviKvsAsyncDnsOperation::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviKvsAsyncDnsOperation", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviKvsAsyncDnsOperation::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = KviKvsAsyncOperation::staticMetaObject();
+ static const QUParameter param_slot_0[] = {
+ { 0, &static_QUType_ptr, "KviDns", QUParameter::In }
+ };
+ static const QUMethod slot_0 = {"lookupTerminated", 1, param_slot_0 };
+ static const QUMethod slot_1 = {"dnsStartFailed", 0, 0 };
+ static const QMetaData slot_tbl[] = {
+ { "lookupTerminated(KviDns*)", &slot_0, QMetaData::Protected },
+ { "dnsStartFailed()", &slot_1, QMetaData::Protected }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviKvsAsyncDnsOperation", parentObject,
+ slot_tbl, 2,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviKvsAsyncDnsOperation.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviKvsAsyncDnsOperation::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviKvsAsyncDnsOperation" ) )
+ return this;
+ return KviKvsAsyncOperation::qt_cast( clname );
+}
+
+bool KviKvsAsyncDnsOperation::qt_invoke( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->slotOffset() ) {
+ case 0: lookupTerminated((KviDns*)static_QUType_ptr.get(_o+1)); break;
+ case 1: dnsStartFailed(); break;
+ default:
+ return KviKvsAsyncOperation::qt_invoke( _id, _o );
+ }
+ return TRUE;
+}
+
+bool KviKvsAsyncDnsOperation::qt_emit( int _id, QUObject* _o )
+{
+ return KviKvsAsyncOperation::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviKvsAsyncDnsOperation::qt_property( int id, int f, QVariant* v)
+{
+ return KviKvsAsyncOperation::qt_property( id, f, v);
+}
+
+bool KviKvsAsyncDnsOperation::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvirc/kvs/moc_kvi_kvs_asyncoperation.cpp b/src/kvirc/kvs/moc_kvi_kvs_asyncoperation.cpp
new file mode 100644
index 00000000..72b75b28
--- /dev/null
+++ b/src/kvirc/kvs/moc_kvi_kvs_asyncoperation.cpp
@@ -0,0 +1,92 @@
+/****************************************************************************
+** KviKvsAsyncOperation meta object code from reading C++ file 'kvi_kvs_asyncoperation.h'
+**
+** Created: Mon Feb 25 00:12:00 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_kvs_asyncoperation.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviKvsAsyncOperation::className() const
+{
+ return "KviKvsAsyncOperation";
+}
+
+QMetaObject *KviKvsAsyncOperation::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviKvsAsyncOperation( "KviKvsAsyncOperation", &KviKvsAsyncOperation::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviKvsAsyncOperation::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviKvsAsyncOperation", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviKvsAsyncOperation::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviKvsAsyncOperation", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviKvsAsyncOperation::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = QObject::staticMetaObject();
+ metaObj = QMetaObject::new_metaobject(
+ "KviKvsAsyncOperation", parentObject,
+ 0, 0,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviKvsAsyncOperation.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviKvsAsyncOperation::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviKvsAsyncOperation" ) )
+ return this;
+ return QObject::qt_cast( clname );
+}
+
+bool KviKvsAsyncOperation::qt_invoke( int _id, QUObject* _o )
+{
+ return QObject::qt_invoke(_id,_o);
+}
+
+bool KviKvsAsyncOperation::qt_emit( int _id, QUObject* _o )
+{
+ return QObject::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviKvsAsyncOperation::qt_property( int id, int f, QVariant* v)
+{
+ return QObject::qt_property( id, f, v);
+}
+
+bool KviKvsAsyncOperation::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvirc/kvs/moc_kvi_kvs_dnsmanager.cpp b/src/kvirc/kvs/moc_kvi_kvs_dnsmanager.cpp
new file mode 100644
index 00000000..27284122
--- /dev/null
+++ b/src/kvirc/kvs/moc_kvi_kvs_dnsmanager.cpp
@@ -0,0 +1,104 @@
+/****************************************************************************
+** KviKvsDnsManager meta object code from reading C++ file 'kvi_kvs_dnsmanager.h'
+**
+** Created: Mon Feb 25 00:12:02 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_kvs_dnsmanager.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviKvsDnsManager::className() const
+{
+ return "KviKvsDnsManager";
+}
+
+QMetaObject *KviKvsDnsManager::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviKvsDnsManager( "KviKvsDnsManager", &KviKvsDnsManager::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviKvsDnsManager::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviKvsDnsManager", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviKvsDnsManager::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviKvsDnsManager", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviKvsDnsManager::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = QObject::staticMetaObject();
+ static const QUParameter param_slot_0[] = {
+ { "pDns", &static_QUType_ptr, "KviDns", QUParameter::In }
+ };
+ static const QUMethod slot_0 = {"dnsLookupTerminated", 1, param_slot_0 };
+ static const QMetaData slot_tbl[] = {
+ { "dnsLookupTerminated(KviDns*)", &slot_0, QMetaData::Protected }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviKvsDnsManager", parentObject,
+ slot_tbl, 1,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviKvsDnsManager.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviKvsDnsManager::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviKvsDnsManager" ) )
+ return this;
+ return QObject::qt_cast( clname );
+}
+
+bool KviKvsDnsManager::qt_invoke( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->slotOffset() ) {
+ case 0: dnsLookupTerminated((KviDns*)static_QUType_ptr.get(_o+1)); break;
+ default:
+ return QObject::qt_invoke( _id, _o );
+ }
+ return TRUE;
+}
+
+bool KviKvsDnsManager::qt_emit( int _id, QUObject* _o )
+{
+ return QObject::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviKvsDnsManager::qt_property( int id, int f, QVariant* v)
+{
+ return QObject::qt_property( id, f, v);
+}
+
+bool KviKvsDnsManager::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvirc/kvs/moc_kvi_kvs_object.cpp b/src/kvirc/kvs/moc_kvi_kvs_object.cpp
new file mode 100644
index 00000000..a578edcf
--- /dev/null
+++ b/src/kvirc/kvs/moc_kvi_kvs_object.cpp
@@ -0,0 +1,104 @@
+/****************************************************************************
+** KviKvsObject meta object code from reading C++ file 'kvi_kvs_object.h'
+**
+** Created: Mon Feb 25 00:12:06 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_kvs_object.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviKvsObject::className() const
+{
+ return "KviKvsObject";
+}
+
+QMetaObject *KviKvsObject::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviKvsObject( "KviKvsObject", &KviKvsObject::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviKvsObject::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviKvsObject", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviKvsObject::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviKvsObject", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviKvsObject::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = QObject::staticMetaObject();
+ static const QUMethod slot_0 = {"delayedDie", 0, 0 };
+ static const QUMethod slot_1 = {"objectDestroyed", 0, 0 };
+ static const QMetaData slot_tbl[] = {
+ { "delayedDie()", &slot_0, QMetaData::Protected },
+ { "objectDestroyed()", &slot_1, QMetaData::Protected }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviKvsObject", parentObject,
+ slot_tbl, 2,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviKvsObject.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviKvsObject::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviKvsObject" ) )
+ return this;
+ return QObject::qt_cast( clname );
+}
+
+bool KviKvsObject::qt_invoke( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->slotOffset() ) {
+ case 0: delayedDie(); break;
+ case 1: objectDestroyed(); break;
+ default:
+ return QObject::qt_invoke( _id, _o );
+ }
+ return TRUE;
+}
+
+bool KviKvsObject::qt_emit( int _id, QUObject* _o )
+{
+ return QObject::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviKvsObject::qt_property( int id, int f, QVariant* v)
+{
+ return QObject::qt_property( id, f, v);
+}
+
+bool KviKvsObject::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvirc/kvs/moc_kvi_kvs_popupmenu.cpp b/src/kvirc/kvs/moc_kvi_kvs_popupmenu.cpp
new file mode 100644
index 00000000..d69f7227
--- /dev/null
+++ b/src/kvirc/kvs/moc_kvi_kvs_popupmenu.cpp
@@ -0,0 +1,217 @@
+/****************************************************************************
+** KviKvsPopupMenuItemLabelHelper meta object code from reading C++ file 'kvi_kvs_popupmenu.h'
+**
+** Created: Mon Feb 25 00:12:08 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_kvs_popupmenu.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviKvsPopupMenuItemLabelHelper::className() const
+{
+ return "KviKvsPopupMenuItemLabelHelper";
+}
+
+QMetaObject *KviKvsPopupMenuItemLabelHelper::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviKvsPopupMenuItemLabelHelper( "KviKvsPopupMenuItemLabelHelper", &KviKvsPopupMenuItemLabelHelper::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviKvsPopupMenuItemLabelHelper::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviKvsPopupMenuItemLabelHelper", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviKvsPopupMenuItemLabelHelper::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviKvsPopupMenuItemLabelHelper", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviKvsPopupMenuItemLabelHelper::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = QObject::staticMetaObject();
+ static const QUMethod slot_0 = {"labelDestroyed", 0, 0 };
+ static const QMetaData slot_tbl[] = {
+ { "labelDestroyed()", &slot_0, QMetaData::Protected }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviKvsPopupMenuItemLabelHelper", parentObject,
+ slot_tbl, 1,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviKvsPopupMenuItemLabelHelper.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviKvsPopupMenuItemLabelHelper::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviKvsPopupMenuItemLabelHelper" ) )
+ return this;
+ return QObject::qt_cast( clname );
+}
+
+bool KviKvsPopupMenuItemLabelHelper::qt_invoke( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->slotOffset() ) {
+ case 0: labelDestroyed(); break;
+ default:
+ return QObject::qt_invoke( _id, _o );
+ }
+ return TRUE;
+}
+
+bool KviKvsPopupMenuItemLabelHelper::qt_emit( int _id, QUObject* _o )
+{
+ return QObject::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviKvsPopupMenuItemLabelHelper::qt_property( int id, int f, QVariant* v)
+{
+ return QObject::qt_property( id, f, v);
+}
+
+bool KviKvsPopupMenuItemLabelHelper::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
+
+
+const char *KviKvsPopupMenu::className() const
+{
+ return "KviKvsPopupMenu";
+}
+
+QMetaObject *KviKvsPopupMenu::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviKvsPopupMenu( "KviKvsPopupMenu", &KviKvsPopupMenu::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviKvsPopupMenu::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviKvsPopupMenu", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviKvsPopupMenu::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviKvsPopupMenu", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviKvsPopupMenu::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = KviTalPopupMenu::staticMetaObject();
+ static const QUMethod slot_0 = {"setupMenuContents", 0, 0 };
+ static const QUParameter param_slot_1[] = {
+ { "itemId", &static_QUType_int, 0, QUParameter::In }
+ };
+ static const QUMethod slot_1 = {"itemClicked", 1, param_slot_1 };
+ static const QMetaData slot_tbl[] = {
+ { "setupMenuContents()", &slot_0, QMetaData::Private },
+ { "itemClicked(int)", &slot_1, QMetaData::Protected }
+ };
+ static const QUParameter param_signal_0[] = {
+ { "it", &static_QUType_ptr, "KviKvsPopupMenuItem", QUParameter::In }
+ };
+ static const QUMethod signal_0 = {"testModeItemClicked", 1, param_signal_0 };
+ static const QMetaData signal_tbl[] = {
+ { "testModeItemClicked(KviKvsPopupMenuItem*)", &signal_0, QMetaData::Protected }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviKvsPopupMenu", parentObject,
+ slot_tbl, 2,
+ signal_tbl, 1,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviKvsPopupMenu.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviKvsPopupMenu::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviKvsPopupMenu" ) )
+ return this;
+ return KviTalPopupMenu::qt_cast( clname );
+}
+
+#include <qobjectdefs.h>
+#include <qsignalslotimp.h>
+
+// SIGNAL testModeItemClicked
+void KviKvsPopupMenu::testModeItemClicked( KviKvsPopupMenuItem* t0 )
+{
+ if ( signalsBlocked() )
+ return;
+ QConnectionList *clist = receivers( staticMetaObject()->signalOffset() + 0 );
+ if ( !clist )
+ return;
+ QUObject o[2];
+ static_QUType_ptr.set(o+1,t0);
+ activate_signal( clist, o );
+}
+
+bool KviKvsPopupMenu::qt_invoke( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->slotOffset() ) {
+ case 0: setupMenuContents(); break;
+ case 1: itemClicked((int)static_QUType_int.get(_o+1)); break;
+ default:
+ return KviTalPopupMenu::qt_invoke( _id, _o );
+ }
+ return TRUE;
+}
+
+bool KviKvsPopupMenu::qt_emit( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->signalOffset() ) {
+ case 0: testModeItemClicked((KviKvsPopupMenuItem*)static_QUType_ptr.get(_o+1)); break;
+ default:
+ return KviTalPopupMenu::qt_emit(_id,_o);
+ }
+ return TRUE;
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviKvsPopupMenu::qt_property( int id, int f, QVariant* v)
+{
+ return KviTalPopupMenu::qt_property( id, f, v);
+}
+
+bool KviKvsPopupMenu::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvirc/kvs/moc_kvi_kvs_processmanager.cpp b/src/kvirc/kvs/moc_kvi_kvs_processmanager.cpp
new file mode 100644
index 00000000..6afd6682
--- /dev/null
+++ b/src/kvirc/kvs/moc_kvi_kvs_processmanager.cpp
@@ -0,0 +1,116 @@
+/****************************************************************************
+** KviKvsProcessAsyncOperation meta object code from reading C++ file 'kvi_kvs_processmanager.h'
+**
+** Created: Mon Feb 25 00:12:10 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_kvs_processmanager.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviKvsProcessAsyncOperation::className() const
+{
+ return "KviKvsProcessAsyncOperation";
+}
+
+QMetaObject *KviKvsProcessAsyncOperation::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviKvsProcessAsyncOperation( "KviKvsProcessAsyncOperation", &KviKvsProcessAsyncOperation::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviKvsProcessAsyncOperation::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviKvsProcessAsyncOperation", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviKvsProcessAsyncOperation::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviKvsProcessAsyncOperation", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviKvsProcessAsyncOperation::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = KviKvsAsyncOperation::staticMetaObject();
+ static const QUMethod slot_0 = {"maxRunTimeExpired", 0, 0 };
+ static const QUMethod slot_1 = {"ping", 0, 0 };
+ static const QUMethod slot_2 = {"readStdout", 0, 0 };
+ static const QUMethod slot_3 = {"readStderr", 0, 0 };
+ static const QUMethod slot_4 = {"processExited", 0, 0 };
+ static const QUMethod slot_5 = {"selfDelete", 0, 0 };
+ static const QMetaData slot_tbl[] = {
+ { "maxRunTimeExpired()", &slot_0, QMetaData::Private },
+ { "ping()", &slot_1, QMetaData::Private },
+ { "readStdout()", &slot_2, QMetaData::Private },
+ { "readStderr()", &slot_3, QMetaData::Private },
+ { "processExited()", &slot_4, QMetaData::Private },
+ { "selfDelete()", &slot_5, QMetaData::Private }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviKvsProcessAsyncOperation", parentObject,
+ slot_tbl, 6,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviKvsProcessAsyncOperation.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviKvsProcessAsyncOperation::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviKvsProcessAsyncOperation" ) )
+ return this;
+ return KviKvsAsyncOperation::qt_cast( clname );
+}
+
+bool KviKvsProcessAsyncOperation::qt_invoke( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->slotOffset() ) {
+ case 0: maxRunTimeExpired(); break;
+ case 1: ping(); break;
+ case 2: readStdout(); break;
+ case 3: readStderr(); break;
+ case 4: processExited(); break;
+ case 5: selfDelete(); break;
+ default:
+ return KviKvsAsyncOperation::qt_invoke( _id, _o );
+ }
+ return TRUE;
+}
+
+bool KviKvsProcessAsyncOperation::qt_emit( int _id, QUObject* _o )
+{
+ return KviKvsAsyncOperation::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviKvsProcessAsyncOperation::qt_property( int id, int f, QVariant* v)
+{
+ return KviKvsAsyncOperation::qt_property( id, f, v);
+}
+
+bool KviKvsProcessAsyncOperation::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvirc/kvs/moc_kvi_kvs_timermanager.cpp b/src/kvirc/kvs/moc_kvi_kvs_timermanager.cpp
new file mode 100644
index 00000000..05f81bcb
--- /dev/null
+++ b/src/kvirc/kvs/moc_kvi_kvs_timermanager.cpp
@@ -0,0 +1,92 @@
+/****************************************************************************
+** KviKvsTimerManager meta object code from reading C++ file 'kvi_kvs_timermanager.h'
+**
+** Created: Mon Feb 25 00:12:04 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_kvs_timermanager.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviKvsTimerManager::className() const
+{
+ return "KviKvsTimerManager";
+}
+
+QMetaObject *KviKvsTimerManager::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviKvsTimerManager( "KviKvsTimerManager", &KviKvsTimerManager::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviKvsTimerManager::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviKvsTimerManager", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviKvsTimerManager::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviKvsTimerManager", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviKvsTimerManager::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = QObject::staticMetaObject();
+ metaObj = QMetaObject::new_metaobject(
+ "KviKvsTimerManager", parentObject,
+ 0, 0,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviKvsTimerManager.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviKvsTimerManager::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviKvsTimerManager" ) )
+ return this;
+ return QObject::qt_cast( clname );
+}
+
+bool KviKvsTimerManager::qt_invoke( int _id, QUObject* _o )
+{
+ return QObject::qt_invoke(_id,_o);
+}
+
+bool KviKvsTimerManager::qt_emit( int _id, QUObject* _o )
+{
+ return QObject::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviKvsTimerManager::qt_property( int id, int f, QVariant* v)
+{
+ return QObject::qt_property( id, f, v);
+}
+
+bool KviKvsTimerManager::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvirc/kvs/moc_kvi_kvs_useraction.cpp b/src/kvirc/kvs/moc_kvi_kvs_useraction.cpp
new file mode 100644
index 00000000..b2bd5c6e
--- /dev/null
+++ b/src/kvirc/kvs/moc_kvi_kvs_useraction.cpp
@@ -0,0 +1,92 @@
+/****************************************************************************
+** KviKvsUserAction meta object code from reading C++ file 'kvi_kvs_useraction.h'
+**
+** Created: Mon Feb 25 00:12:12 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_kvs_useraction.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviKvsUserAction::className() const
+{
+ return "KviKvsUserAction";
+}
+
+QMetaObject *KviKvsUserAction::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviKvsUserAction( "KviKvsUserAction", &KviKvsUserAction::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviKvsUserAction::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviKvsUserAction", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviKvsUserAction::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviKvsUserAction", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviKvsUserAction::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = KviKvsAction::staticMetaObject();
+ metaObj = QMetaObject::new_metaobject(
+ "KviKvsUserAction", parentObject,
+ 0, 0,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviKvsUserAction.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviKvsUserAction::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviKvsUserAction" ) )
+ return this;
+ return KviKvsAction::qt_cast( clname );
+}
+
+bool KviKvsUserAction::qt_invoke( int _id, QUObject* _o )
+{
+ return KviKvsAction::qt_invoke(_id,_o);
+}
+
+bool KviKvsUserAction::qt_emit( int _id, QUObject* _o )
+{
+ return KviKvsAction::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviKvsUserAction::qt_property( int id, int f, QVariant* v)
+{
+ return KviKvsAction::qt_property( id, f, v);
+}
+
+bool KviKvsUserAction::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvirc/module/Makefile.am b/src/kvirc/module/Makefile.am
new file mode 100644
index 00000000..c84487eb
--- /dev/null
+++ b/src/kvirc/module/Makefile.am
@@ -0,0 +1,5 @@
+###############################################################################
+# KVirc IRC client Makefile - 16.12.98 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+EXTRA_DIST = *.cpp *.h
diff --git a/src/kvirc/module/kvi_mexlinkfilter.cpp b/src/kvirc/module/kvi_mexlinkfilter.cpp
new file mode 100644
index 00000000..58987389
--- /dev/null
+++ b/src/kvirc/module/kvi_mexlinkfilter.cpp
@@ -0,0 +1,35 @@
+//=============================================================================
+//
+// File : kvi_mexlinkfilter.cpp
+// Creation date : Wed Apr 11 2003 03:07 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003-2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+#include "kvi_mexlinkfilter.h"
+
+KviMexLinkFilter::KviMexLinkFilter(KviModuleExtensionDescriptor * d)
+: QObject(), KviModuleExtension(d)
+{
+}
+
+KviMexLinkFilter::~KviMexLinkFilter()
+{
+}
diff --git a/src/kvirc/module/kvi_mexlinkfilter.h b/src/kvirc/module/kvi_mexlinkfilter.h
new file mode 100644
index 00000000..aaf2a091
--- /dev/null
+++ b/src/kvirc/module/kvi_mexlinkfilter.h
@@ -0,0 +1,45 @@
+#ifndef _KVI_MEXLINKFILTER_H_
+#define _KVI_MEXLINKFILTER_H_
+//=============================================================================
+//
+// File : kvi_mexlinkfilter.h
+// Creation date : Wed Apr 11 2003 03:07 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003-2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_moduleextension.h"
+
+#include <qobject.h>
+
+class KviDataBuffer;
+
+class KVIRC_API KviMexLinkFilter : public QObject, public KviModuleExtension
+{
+ Q_OBJECT
+public:
+ KviMexLinkFilter(KviModuleExtensionDescriptor * d);
+ ~KviMexLinkFilter();
+public:
+ virtual void processData(char * buffer,int len) = 0;
+ virtual bool sendPacket(KviDataBuffer * pData) = 0;
+};
+
+#endif //!_KVI_MEXLINKFILTER_H_
diff --git a/src/kvirc/module/kvi_mexserverimport.cpp b/src/kvirc/module/kvi_mexserverimport.cpp
new file mode 100644
index 00000000..1dfc61eb
--- /dev/null
+++ b/src/kvirc/module/kvi_mexserverimport.cpp
@@ -0,0 +1,33 @@
+//
+// File : kvi_mexserverimport.cpp
+// Creation date : Wed Apr 9 2003 04:53 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#define __KVIRC__
+#include "kvi_mexserverimport.h"
+
+KviMexServerImport::KviMexServerImport(KviModuleExtensionDescriptor * d)
+: QObject() , KviModuleExtension(d)
+{
+}
+
+KviMexServerImport::~KviMexServerImport()
+{
+}
diff --git a/src/kvirc/module/kvi_mexserverimport.h b/src/kvirc/module/kvi_mexserverimport.h
new file mode 100644
index 00000000..f15ce7ae
--- /dev/null
+++ b/src/kvirc/module/kvi_mexserverimport.h
@@ -0,0 +1,45 @@
+#ifndef _KVI_MEXSERVERIMPORT_H_
+#define _KVI_MEXSERVERIMPORT_H_
+//=============================================================================
+//
+// File : kvi_mexserverimport.h
+// Creation date : Wed Apr 9 2003 04:53 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_ircserverdb.h"
+#include "kvi_moduleextension.h"
+#include <qobject.h>
+
+class KVIRC_API KviMexServerImport : public QObject, public KviModuleExtension
+{
+ Q_OBJECT
+public:
+ KviMexServerImport(KviModuleExtensionDescriptor * d);
+ ~KviMexServerImport();
+public:
+ virtual void start() = 0;
+ virtual void die() = 0;
+signals:
+ void server(const KviIrcServer &s,const char * network);
+};
+
+#endif //!_KVI_MEXSERVERIMPORT_H_
diff --git a/src/kvirc/module/kvi_mextoolbar.cpp b/src/kvirc/module/kvi_mextoolbar.cpp
new file mode 100644
index 00000000..4d868786
--- /dev/null
+++ b/src/kvirc/module/kvi_mextoolbar.cpp
@@ -0,0 +1,38 @@
+//
+// File : kvi_mextoolbar.cpp
+// Creation date : Thu Sep 12 22:11:47 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#define __KVIRC__
+
+#include "kvi_mextoolbar.h"
+#include "kvi_frame.h"
+
+KviMexToolBar::KviMexToolBar(KviModuleExtensionDescriptor * d,const QString &szName)
+: KviToolBar(szName,QT_DOCK_TOP) , KviModuleExtension(d)
+{
+ g_pFrame->registerModuleExtensionToolBar(this);
+}
+
+KviMexToolBar::~KviMexToolBar()
+{
+ g_pFrame->unregisterModuleExtensionToolBar(this);
+}
+
diff --git a/src/kvirc/module/kvi_mextoolbar.h b/src/kvirc/module/kvi_mextoolbar.h
new file mode 100644
index 00000000..d8176e87
--- /dev/null
+++ b/src/kvirc/module/kvi_mextoolbar.h
@@ -0,0 +1,38 @@
+#ifndef _KVI_MEXTOOLBAR_H_
+#define _KVI_MEXTOOLBAR_H_
+//
+// File : kvi_mextoolbar.h
+// Creation date : Thu Sep 12 22:11:45 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_moduleextension.h"
+#include "kvi_toolbar.h"
+
+class KviFrame;
+
+class KVIRC_API KviMexToolBar : public KviToolBar , public KviModuleExtension
+{
+ Q_OBJECT
+public:
+ KviMexToolBar(KviModuleExtensionDescriptor * d,const QString &szName);
+ ~KviMexToolBar();
+};
+
+#endif //_KVI_MEXTOOLBAR_H_
diff --git a/src/kvirc/module/kvi_module.cpp b/src/kvirc/module/kvi_module.cpp
new file mode 100644
index 00000000..f0e50d06
--- /dev/null
+++ b/src/kvirc/module/kvi_module.cpp
@@ -0,0 +1,379 @@
+//=============================================================================
+//
+// File : kvi_module.cpp
+// Creation date : Sat Aug 12 2000 20:30:29 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_module.h"
+#include "kvi_app.h"
+#include "kvi_settings.h"
+#include "kvi_kvs_eventmanager.h"
+#include "kvi_kvs_eventhandler.h"
+#include "kvi_modulemanager.h"
+
+#include <time.h>
+
+#if QT_VERSION < 300
+ #include <qobjectdict.h>
+#endif
+
+#ifdef COMPILE_CRYPT_SUPPORT
+ extern KviCryptEngineManager * g_pCryptEngineManager;
+#endif
+
+extern KVIRC_API KviModuleExtensionManager * g_pModuleExtensionManager;
+
+/*
+ @doc: modules
+ @type:
+ generic
+ @keyterms:
+ module loading, functions exported by modules, commands exported by modules,
+ module naming convention, module locking, plugins, functions exported by modules,
+ dots in command names,dots in function names
+ @title:
+ Loadable modules
+ @short:
+ KVIrc modules model
+ @body:
+ Starting from version 2.0.0, KVIrc included support for external plugins:
+ parts of code that can be loaded at runtime. The support was optional
+ and the main KVIrc functionality was indipendant of that support.
+ In version 3.0.0 the "modularity" has becomed one of the primary KVIrc features.
+ The pieces of external code are now named "modules". The module
+ support has been rewritten completely to extend the available features
+ and remove some "basic" problems that were present in 2.0.0.
+ This caused the old "plugins" to be binary incompatible with the new KVIrc
+ executable; anyway, most old "plugins" have been rewritten as "modules"
+ and included in the 3.0.0 distribution. Some of the basic KVIrc features
+ are based on modules now; for example, the help browser is now in an
+ external library called libkvihelp.so. This allows to keep the basic
+ KVIrc executable smaller and faster (in some phases).
+ Module loading is now "transparent" to the user. There are no
+ "load" and "unload" commands: the modules are automatically
+ loaded when the "core" requests them and unloaded after some (configurable) time
+ of inactivity.[br]
+
+ [big]Module naming convention[/big][br]
+ Every KVIrc module must have an "unique" name: the name is a single token,
+ made only of [b]lowercase[/b] letters , digits and underscores.
+ The real object file (library) is named "libkvi<name>.so".
+ This convention allows KVIrc to load modules when they are referenced
+ by name in the scripting code (the reference in the code is case insensitive
+ and remapped always to the lowercase version).[br]
+ [big]What a module can do[/big][br]
+ Basically, a module exports parts of the scripting language features.
+ For example, the module "about" exports the "aboutkvirc" command, that
+ shows the dialog that lists the KVIrc staff people. The dialog
+ will be effectively activated only few times (maybe only once) by a single
+ user: including it in a separate module allows keeping rarely used code out
+ of the KVIrc executable and saving some memory.
+ To activate the dialog you only need to execute the command:[br]
+ [example]
+ about.aboutkvirc
+ [/example]
+ That's all. KVIrc will load the necessary module, run the "aboutkvirc" command,
+ wait until the module is not used anymore and then unload it.[br]
+
+ [big]Transparent loading and unloading[/big][br]
+ Any command that has the form <name>.<command> is assumed to be
+ a module reference. KVIrc tries to locate the module named <name>, load it (if
+ not already in memory) and execute the <command>.
+ After the command execution KVIrc waits some user defined interval of time
+ (typically 2-3 minutes) and then check the module state: if the module
+ has not been referenced again, it is unloaded, otherwise it is kept in memory
+ for another period of time. To prevent accidentaly unloading a module
+ that has some windows or dialogs open, a module can lock itself in memory.
+ For example, the 'help' module lock itself when a help browser window is open
+ and unlocks itself when the last help browser window is closed.[br]
+ A module can export functions as well: the function names follow
+ exactly the same rule as the commands: $<name>.<function> is assumed
+ to be a reference to the <function> exported by module named <name>.
+
+ [big]Forced loading and unloading[/big]
+ All the modules export a "load" and a "unload" command.
+ [example]
+ about.load
+ [/example]
+ The example above will do nothing more than loading the "about"
+ module into the core memory.
+ [example]
+ about.unload
+ [/example]
+ The example above will forcibly unload the module from the core memory;
+ even if it is still locked.[br]
+ Please note that this can be dangerous in some situations...so
+ better check the KVIrc behaviour twice before making public any script
+ that uses this command.
+*/
+
+
+
+
+
+
+
+// FIXME: #warning "Move all the modules to the new locking method ?"
+
+
+KviModule::KviModule(kvi_library_t handle,KviModuleInfo * info,const char * name,const char * filename)
+: KviKvsModuleInterface()
+{
+ m_dlHandle = handle;
+ m_pModuleInfo = info;
+ m_szName = name;
+ m_szFileName = filename;
+// FIXME: this should become case insensitive and converted toUpper()
+ /*
+ m_pCommandDict = new KviPointerHashTable<const char *,KviModuleCommandParseProc>(17,false,true);
+ m_pCommandDict->setAutoDelete(true);
+ m_pFunctionDict = new KviPointerHashTable<const char *,KviModuleFunctionParseProc>(17,false,true);
+ m_pFunctionDict->setAutoDelete(true);
+ */
+ m_uLock = 0;
+ m_lastAccessTime = (long int)time(0);
+ /*
+ m_pGenericCommandParseProc = 0;
+ m_pGenericFunctionParseProc = 0;
+ */
+}
+
+KviModule::~KviModule()
+{
+#ifdef COMPILE_CRYPT_SUPPORT
+ unregisterCryptEngines();
+#endif
+ unregisterAllExtensions();
+ /*
+ unregisterAllEventHandlers();
+ delete m_pCommandDict;
+ delete m_pFunctionDict;
+ if(m_pGenericCommandParseProc)delete m_pGenericCommandParseProc;
+ if(m_pGenericFunctionParseProc)delete m_pGenericFunctionParseProc;
+ */
+}
+
+KviModuleExtensionDescriptor * KviModule::registerExtension(const KviStr &szType,const KviStr &szName,const QString &szVisibleName,KviModuleExtensionAllocRoutine r)
+{
+ QPixmap pix; // null
+ return g_pModuleExtensionManager->registerExtension(this,szType,szName,szVisibleName,r,pix);
+}
+
+KviModuleExtensionDescriptor * KviModule::registerExtension(const KviStr &szType,const KviStr &szName,const QString &szVisibleName,KviModuleExtensionAllocRoutine r,const QPixmap &icon)
+{
+ return g_pModuleExtensionManager->registerExtension(this,szType,szName,szVisibleName,r,icon);
+}
+
+KviModuleExtensionDescriptor * KviModule::findExtensionDescriptor(const KviStr &szType,const KviStr &szName)
+{
+ return g_pModuleExtensionManager->findExtensionDescriptor(szType,szName);
+}
+
+void KviModule::unregisterAllExtensions()
+{
+ g_pModuleExtensionManager->unregisterExtensionsByModule(this);
+}
+/*
+void KviModule::setGenericCommandParseProc(KviModuleCommandParseProc proc)
+{
+ if(m_pGenericCommandParseProc)delete m_pGenericCommandParseProc;
+ if(proc)
+ {
+ m_pGenericCommandParseProc = new KviModuleCommandParseProc(proc);
+ } else {
+ m_pGenericCommandParseProc = 0;
+ }
+}
+
+void KviModule::setGenericFunctionParseProc(KviModuleFunctionParseProc proc)
+{
+ if(m_pGenericFunctionParseProc)delete m_pGenericFunctionParseProc;
+ if(proc)
+ {
+ m_pGenericFunctionParseProc = new KviModuleFunctionParseProc(proc);
+ } else {
+ m_pGenericFunctionParseProc = 0;
+ }
+}
+
+void KviModule::completeCommand(const QString &cmd,KviPointerList<QString> * matches)
+{
+ KviPointerHashTableIterator<const char *,KviModuleCommandParseProc> it(*m_pCommandDict);
+
+ while(it.current())
+ {
+ if(KviQString::equalCIN(cmd,it.currentKey(),cmd.length()))
+ {
+ QString * s = new QString();
+ KviQString::sprintf(*s,"%s.%s",name(),it.currentKey());
+ matches->append(s);
+ }
+ ++it;
+ }
+}
+
+void KviModule::completeFunction(const QString &cmd,KviPointerList<QString> * matches)
+{
+ KviPointerHashTableIterator<const char *,KviModuleFunctionParseProc> it(*m_pFunctionDict);
+
+ while(it.current())
+ {
+ if(KviQString::equalCIN(cmd,it.currentKey(),cmd.length()))
+ {
+ QString * s = new QString();
+ KviQString::sprintf(*s,"%s.%s",name(),it.currentKey());
+ matches->append(s);
+ }
+ ++it;
+ }
+}
+
+
+void KviModule::unregisterMetaObject(const char * metaObjName)
+{
+#if QT_VERSION < 300
+// FIXME: #warning "We might need zeroing the d->slotAccess member of QMetaObject!"
+ if(!objectDict)return;
+ objectDict->remove(metaObjName);
+#endif
+}
+*/
+void KviModule::updateAccessTime()
+{
+ m_lastAccessTime = (long int)time(0);
+}
+
+unsigned int KviModule::secondsSinceLastAccess()
+{
+ return (unsigned int)(((long int)time(0)) - m_lastAccessTime);
+}
+/*
+void KviModule::registerCommand(const char * cmd,KviModuleCommandParseProc proc)
+{
+ if(m_pCommandDict->find(cmd))m_pCommandDict->remove(cmd);
+ m_pCommandDict->insert(cmd,new KviModuleCommandParseProc(proc));
+}
+
+void KviModule::unregisterCommand(const char * cmd)
+{
+ m_pCommandDict->remove(cmd);
+}
+
+void KviModule::unregisterAllCommands()
+{
+ delete m_pCommandDict;
+ m_pCommandDict = new KviPointerHashTable<const char *,KviModuleCommandParseProc>(17,false,true);
+ m_pCommandDict->setAutoDelete(true);
+}
+
+void KviModule::registerEventHandler(int evIdx,KviModuleEventParseProc proc)
+{
+ KviKvsOldModuleEventHandler * h = new KviKvsOldModuleEventHandler(proc,this);
+ KviKvsEventManager::instance()->addAppHandler(evIdx,h);
+}
+
+void KviModule::unregisterEventHandler(int evIdx)
+{
+ KviKvsEventManager::instance()->removeModuleAppHandler(evIdx,this);
+}
+
+void KviModule::registerRawNumericEventHandler(int evIdx,KviModuleEventParseProc proc)
+{
+ KviKvsOldModuleEventHandler * h = new KviKvsOldModuleEventHandler(proc,this);
+ KviKvsEventManager::instance()->addRawHandler(evIdx,h);
+}
+
+void KviModule::unregisterRawNumericEventHandler(int evIdx)
+{
+ KviKvsEventManager::instance()->removeModuleRawHandler(evIdx,this);
+}
+
+
+void KviModule::unregisterAllEventHandlers()
+{
+ KviKvsEventManager::instance()->removeAllModuleHandlers(this);
+}
+
+void KviModule::registerFunction(const char * fnc,KviModuleFunctionParseProc proc)
+{
+ if(m_pFunctionDict->find(fnc))m_pFunctionDict->remove(fnc);
+ m_pFunctionDict->insert(fnc,new KviModuleFunctionParseProc(proc));
+}
+
+void KviModule::unregisterFunction(const char * fnc)
+{
+ m_pFunctionDict->remove(fnc);
+}
+
+void KviModule::unregisterAllFunctions()
+{
+ delete m_pFunctionDict;
+ m_pFunctionDict = new KviPointerHashTable<const char *,KviModuleFunctionParseProc>(17,false,true);
+ m_pFunctionDict->setAutoDelete(true);
+}
+*/
+
+#ifdef COMPILE_CRYPT_SUPPORT
+
+void KviModule::registerCryptEngine(KviCryptEngineDescription * d)
+{
+ d->providerHandle = (void *)this;
+ g_pCryptEngineManager->registerEngine(d);
+}
+
+void KviModule::unregisterCryptEngine(const char * szName)
+{
+ g_pCryptEngineManager->unregisterEngine(szName);
+}
+
+void KviModule::unregisterCryptEngines()
+{
+ g_pCryptEngineManager->unregisterEngines((void *)this);
+}
+
+#endif
+
+void * KviModule::getSymbol(const char * symname)
+{
+ return kvi_library_symbol(handle(),symname);
+}
+
+void KviModule::getDefaultConfigFileName(KviStr &buffer)
+{
+ KviStr szName(KviStr::Format,"libkvi%s.kvc",m_szName.ptr());
+ g_pApp->getLocalKvircDirectory(buffer,KviApp::ConfigPlugins,szName.ptr());
+}
+
+void KviModule::getDefaultConfigFileName(QString &szBuffer)
+{
+ QString tmp = "libkvi";
+ tmp += m_szName.ptr();
+ tmp += ".kvc";
+ g_pApp->getLocalKvircDirectory(szBuffer,KviApp::ConfigPlugins,tmp);
+}
+
+bool KviModule::ctrl(const char * operation,void * param)
+{
+ if(!(m_pModuleInfo->ctrl_routine))return false;
+ return m_pModuleInfo->ctrl_routine(this,operation,param);
+}
diff --git a/src/kvirc/module/kvi_module.h b/src/kvirc/module/kvi_module.h
new file mode 100644
index 00000000..7c237643
--- /dev/null
+++ b/src/kvirc/module/kvi_module.h
@@ -0,0 +1,204 @@
+#ifndef _KVI_MODULE_H_
+#define _KVI_MODULE_H_
+
+//=============================================================================
+//
+// File : kvi_module.h
+// Creation date : Sat Aug 12 2000 18:34:22 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_string.h"
+//#include "kvi_command.h"
+#include "kvi_parameterlist.h"
+#include "kvi_library.h"
+#include "kvi_pointerlist.h"
+#include "kvi_moduleextension.h"
+#include "kvi_kvs_moduleinterface.h"
+
+#include "kvi_pointerhashtable.h"
+
+#ifdef COMPILE_CRYPT_SUPPORT
+ #include "kvi_crypt.h"
+#endif
+
+
+#ifdef COMPILE_ON_WINDOWS
+ #define KVIMODULEEXPORT extern "C" __declspec(dllexport)
+ #define KVIMODULEEXPORTDATA KVIMODULEEXPORT
+ #define KVIMODULEEXPORTFUNC KVIMODULEEXPORT
+#else
+ #define KVIMODULEEXPORT extern "C"
+ #define KVIMODULEEXPORTDATA
+ #define KVIMODULEEXPORTFUNC KVIMODULEEXPORT
+#endif
+
+class KviModule;
+
+
+typedef bool (*KviModuleSystemRoutine)(KviModule *);
+typedef bool (*KviModuleCtrlRoutine)(KviModule *,const char *,void *);
+
+
+typedef struct _KviModuleInfo
+{
+ const char * szKVIrcVersion; // must match KVI_VERSION if module version checking is in force
+ const char * szModuleName;
+ const char * szVersion;
+ const char * szCopyright;
+ const char * szDescription;
+ /*
+ * This routine is called when the module is loaded
+ */
+ KviModuleSystemRoutine init_routine;
+ /*
+ * This should return true if the module is actually
+ * not providing any service and can be unloaded from memory.
+ * Please note that this is not a mandatory lock: KVIrc may still unload
+ * the module even when this function returns false.
+ * The only assumption you can make is that KVIrc will not try
+ * to unload the module spontaneously: it will do it only if forced to
+ * (actually only by the user, but maybe later also by constrained resources).
+ * If this pointer is zero, KVIrc will assume that the module
+ * does not provide any service and will unload the module at the
+ * first spontaneous cleanup.
+ * There is a yet stronger locking method in KviModule::lock()
+ */
+ KviModuleSystemRoutine can_unload;
+ /*
+ * This is a generic control routine with prototype
+ * bool <name>(KviModule * m,const char * operation,void * param)
+ * KVIrc uses it to comunicate with bundled modules
+ * in most user-build modules this will be 0
+ */
+ KviModuleCtrlRoutine ctrl_routine;
+ /*
+ * This routine is called when the module is being unloaded
+ * Note that the module can be unloaded even if can_unload returns false:
+ * that's the user choice, KVIrc can only forcibly unload the module,
+ * so better cleanup everything here :)
+ */
+ KviModuleSystemRoutine cleanup_routine; // WARNING : g_pApp may be in the destructor and may have no frames open!
+} KviModuleInfo;
+
+// NOTE: The init and cleanup routines should NEVER rely on g_pApp existing!
+// so only "initialization and cleanup INTERNAL to the module" goes there!
+
+// A module should be prepared to be unloaded at ANY time, even if it is locked
+// or if can_unload returns false; locking is only a "suggestion" to the KVIrc core.
+
+// When unloaded, a module must ensure the destruction of all the resources that depend
+// on the module core code
+
+#define KVIRC_MODULE_STRUCTURE_SYMBOL "KVIrc_module_info"
+
+#define KVIRC_MODULE(_szModuleName,_szVersion,_szCopyright,_szDescription,_init_routine,_can_unload,_ctrl_routine,_cleanup_routine) \
+ \
+ KVIMODULEEXPORTDATA KviModuleInfo KVIrc_module_info= \
+ { \
+ KVI_VERSION, \
+ _szModuleName, \
+ _szVersion, \
+ _szCopyright, \
+ _szDescription, \
+ _init_routine, \
+ _can_unload, \
+ _ctrl_routine, \
+ _cleanup_routine \
+ };
+
+
+// old type parsing procedures
+/*
+typedef bool (*KviModuleCommandParseProc)(KviModule *,KviCommand *);
+typedef bool (*KviModuleFunctionParseProc)(KviModule *,KviCommand *,KviParameterList *,KviStr &);
+typedef bool (*KviModuleEventParseProc)(KviModule *,KviWindow *,KviParameterList *);
+*/
+
+
+class KVIRC_API KviModule : public KviKvsModuleInterface
+{
+ friend class KviPointerHashTable<const char *,KviModule>;
+ friend class KviModuleManager;
+ friend class KviUserParser;
+protected:
+ KviModule(kvi_library_t handle,KviModuleInfo * info,const char * name,const char * filename);
+public:
+ ~KviModule(); // must be public for KviPointerList
+private:
+ KviStr m_szName;
+ KviStr m_szFileName;
+ KviModuleInfo * m_pModuleInfo;
+ kvi_library_t m_dlHandle;
+ unsigned int m_uLock;
+ long int m_lastAccessTime;
+protected:
+ void updateAccessTime();
+ unsigned int secondsSinceLastAccess();
+public:
+ // name of this module: always low case , single word
+ const char * name(){ return m_szName.ptr(); };
+ // filename of this module (with NO path): formatted as "libkvi%s.so",name()
+ const char * filename(){ return m_szFileName.ptr(); };
+ kvi_library_t handle(){ return m_dlHandle; };
+ KviModuleInfo * moduleInfo(){ return m_pModuleInfo; };
+
+ //
+ // This is a locking method a bit stronger than the can_unload routine
+ // in the descriptor. It will behave in the same way plus
+ // the user will be unable to unload the module unless he will specify
+ // the -f switch to the <module>.unload command. Without the -f switch
+ // he will be just warned that the module is locked in memory and
+ // don't want to be unloaded.
+ // The usage of this method is encouraged
+ // only when you have blocking dialogs inside the module code, like the
+ // QMessageBox or QFileDialog static methods.
+ // In this case you're entering a modal event loop that you can't control
+ // and if some script will attempt to forcibly unload the module
+ // it will surely lead to a crash when the static method returns (jumping into no mans land).
+ // <module>.unload -f is in fact undocumented so people will substantially
+ // not use it (unless they are developers and they are reading this comment).
+ //
+ void lock(){ m_uLock++; };
+ void unlock(){ if(m_uLock > 0)m_uLock--; };
+ bool isLocked(){ return (m_uLock > 0); };
+
+ void * getSymbol(const char * symname);
+ bool ctrl(const char * operation,void * param);
+
+ void getDefaultConfigFileName(KviStr &buffer);
+ void getDefaultConfigFileName(QString &szBuffer);
+
+ static void unregisterMetaObject(const char * metaObjName);
+
+#ifdef COMPILE_CRYPT_SUPPORT
+ void registerCryptEngine(KviCryptEngineDescription * d);
+ void unregisterCryptEngine(const char * szName);
+ void unregisterCryptEngines();
+#endif
+
+ KviModuleExtensionDescriptor * registerExtension(const KviStr &szType,const KviStr &szName,const QString &szVisibleName,KviModuleExtensionAllocRoutine r);
+ KviModuleExtensionDescriptor * registerExtension(const KviStr &szType,const KviStr &szName,const QString &szVisibleName,KviModuleExtensionAllocRoutine r,const QPixmap &icon);
+ KviModuleExtensionDescriptor * findExtensionDescriptor(const KviStr &szType,const KviStr &szName);
+ void unregisterAllExtensions();
+};
+
+#endif //_KVI_MODULE_H_
diff --git a/src/kvirc/module/kvi_moduleextension.cpp b/src/kvirc/module/kvi_moduleextension.cpp
new file mode 100644
index 00000000..fb6a9ae6
--- /dev/null
+++ b/src/kvirc/module/kvi_moduleextension.cpp
@@ -0,0 +1,253 @@
+//
+// File : kvi_moduleextension.cpp
+// Creation date : Tue Sep 10 01:16:25 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#define __KVIRC__
+#define _KVI_MODULEEXTENSION_CPP_
+
+#include "kvi_moduleextension.h"
+#include "kvi_module.h"
+#include "kvi_modulemanager.h"
+#include "kvi_app.h"
+
+// created and destroyed in kvi_app.cpp
+KVIRC_API KviModuleExtensionManager * g_pModuleExtensionManager = 0;
+
+
+KviModuleExtensionDescriptor::KviModuleExtensionDescriptor(KviModule * m,const KviStr &szType,const KviStr &szName,const QString &szVisibleName,KviModuleExtensionAllocRoutine r,const QPixmap &pix)
+{
+ m_iId = KviApp::getGloballyUniqueId();
+
+ m_pModule = m;
+ m_szType = szType;
+ m_szName = szName;
+ m_szVisibleName = szVisibleName;
+ m_allocRoutine = r;
+ m_pObjectList = new KviPointerList<KviModuleExtension>;
+ m_pObjectList->setAutoDelete(false);
+ if(pix.isNull())m_pIcon = 0;
+ else m_pIcon = new QPixmap(pix);
+}
+
+KviModuleExtensionDescriptor::~KviModuleExtensionDescriptor()
+{
+ while(KviModuleExtension * e = m_pObjectList->first())e->die();
+ delete m_pObjectList;
+ if(m_pIcon)delete m_pIcon;
+}
+
+void KviModuleExtensionDescriptor::setIcon(const QPixmap &pix)
+{
+ if(m_pIcon)delete m_pIcon;
+ if(pix.isNull())m_pIcon = 0;
+ else m_pIcon = new QPixmap(pix);
+}
+
+KviModuleExtension * KviModuleExtensionDescriptor::allocate(KviWindow * pWnd,KviPointerHashTable<QString,QVariant> * pParams,void * pSpecial)
+{
+ KviModuleExtensionAllocStruct s;
+ s.pDescriptor = this;
+ s.pWindow = pWnd;
+ s.pParams = pParams;
+ s.pSpecial = pSpecial;
+ return m_allocRoutine(&s);
+}
+
+
+void KviModuleExtensionDescriptor::registerObject(KviModuleExtension * e)
+{
+ m_pObjectList->append(e);
+}
+
+void KviModuleExtensionDescriptor::unregisterObject(KviModuleExtension * e)
+{
+ m_pObjectList->removeRef(e);
+}
+
+
+
+
+
+
+
+
+KviModuleExtensionManager::KviModuleExtensionManager()
+{
+ m_pExtensionDict = new KviPointerHashTable<const char *,KviModuleExtensionDescriptorList>(17,false);
+ m_pExtensionDict->setAutoDelete(true);
+}
+
+KviModuleExtensionManager::~KviModuleExtensionManager()
+{
+ delete m_pExtensionDict;
+}
+
+KviModuleExtensionDescriptorList * KviModuleExtensionManager::getExtensionList(const KviStr &szType)
+{
+ g_pModuleManager->loadModulesByCaps(szType.ptr());
+ return m_pExtensionDict->find(szType.ptr());
+}
+
+KviModuleExtensionDescriptor * KviModuleExtensionManager::registerExtension(KviModule * m,const KviStr &szType,const KviStr &szName,const QString &szVisibleName,KviModuleExtensionAllocRoutine r,const QPixmap &icon)
+{
+ KviModuleExtensionDescriptor * d = new KviModuleExtensionDescriptor(m,szType,szName,szVisibleName,r,icon);
+ KviModuleExtensionDescriptorList * l = m_pExtensionDict->find(szType.ptr());
+ if(!l)
+ {
+ l = new KviModuleExtensionDescriptorList();
+ l->setAutoDelete(false);
+ m_pExtensionDict->insert(szType.ptr(),l);
+ }
+ l->append(d);
+ return d;
+}
+
+void KviModuleExtensionManager::unregisterExtensionsByModule(KviModule * m)
+{
+ KviPointerHashTableIterator<const char *,KviModuleExtensionDescriptorList> it(*m_pExtensionDict);
+ KviPointerList<KviStr> dying;
+ dying.setAutoDelete(true);
+ while(KviModuleExtensionDescriptorList * l = it.current())
+ {
+ KviPointerList<KviModuleExtensionDescriptor> dying2;
+ dying2.setAutoDelete(true);
+
+ for(KviModuleExtensionDescriptor * d = l->first();d;d = l->next())
+ {
+ if(d->module() == m)dying2.append(d);
+ }
+
+ for(KviModuleExtensionDescriptor * de = dying2.first();de;de = dying2.next())
+ {
+ l->removeRef(de);
+ }
+
+ if(l->isEmpty())dying.append(new KviStr(it.currentKey()));
+ ++it;
+ }
+ for(KviStr * li = dying.first();li;li = dying.next())
+ {
+ m_pExtensionDict->remove(li->ptr());
+ }
+}
+
+KviModuleExtensionDescriptorList * KviModuleExtensionManager::allocateExtensionGetDescriptorList(const KviStr &szType,const char * preloadModule)
+{
+ if(preloadModule)
+ {
+ KviModule * m = g_pModuleManager->getModule(preloadModule);
+ (void)m; // get rid of the unused warning :D
+ }
+
+ KviModuleExtensionDescriptorList * l = m_pExtensionDict->find(szType.ptr());
+ if(!l)
+ {
+ // retry : it might have been unloaded
+ g_pModuleManager->loadModulesByCaps(szType.ptr());
+ l = m_pExtensionDict->find(szType.ptr());
+ }
+
+ return l;
+}
+
+KviModuleExtensionDescriptor * KviModuleExtensionManager::findExtensionDescriptor(const KviStr &szType,const KviStr &szName)
+{
+ KviModuleExtensionDescriptorList * l = m_pExtensionDict->find(szType.ptr());
+ if(!l)return 0;
+
+ for(KviModuleExtensionDescriptor * d = l->first();d;d = l->next())
+ {
+ if(d->name().equalsCI(szName))return d;
+ }
+
+ return 0;
+}
+
+KviModuleExtension * KviModuleExtensionManager::allocateExtension(const KviStr &szType,const KviStr &szName,KviWindow * pWnd,KviPointerHashTable<QString,QVariant> * pParams,void * pSpecial,const char * preloadModule)
+{
+ KviModuleExtensionDescriptorList * l = allocateExtensionGetDescriptorList(szType,preloadModule);
+ if(!l)return 0;
+
+ KviModuleExtensionDescriptor * d;
+
+ for(d = l->first();d;d = l->next())
+ {
+ if(d->name().equalsCI(szName))return d->allocate(pWnd,pParams,pSpecial);
+ }
+
+ // uhm... not there ?
+ g_pModuleManager->loadModulesByCaps(szType.ptr());
+ // try again after loading the modules
+ // l = m_pExtensionDict->find(szType.ptr()); <--- this shouldn't change!
+ for(d = l->first();d;d = l->next())
+ {
+ if(d->name().equalsCI(szName))return d->allocate(pWnd,pParams,pSpecial);
+ }
+
+ // no way : no such extension
+
+ return 0;
+}
+
+
+KviModuleExtension * KviModuleExtensionManager::allocateExtension(const KviStr &szType,int id,KviWindow * pWnd,KviPointerHashTable<QString,QVariant> * pParams,void * pSpecial,const char * preloadModule)
+{
+ KviModuleExtensionDescriptorList * l = allocateExtensionGetDescriptorList(szType,preloadModule);
+ if(!l)return 0;
+
+ KviModuleExtensionDescriptor * d;
+ for(d = l->first();d;d = l->next())
+ {
+ if(d->id() == id)return d->allocate(pWnd,pParams,pSpecial);
+ }
+
+ // uhm... not there ?
+ g_pModuleManager->loadModulesByCaps(szType.ptr());
+ // try again after loading the modules
+ // l = m_pExtensionDict->find(szType.ptr()); <--- this shouldn't change!
+ for(d = l->first();d;d = l->next())
+ {
+ if(d->id() == id)return d->allocate(pWnd,pParams,pSpecial);
+ }
+ // no way : no such extension
+
+ return 0;
+}
+
+
+
+
+
+
+
+KviModuleExtension::KviModuleExtension(KviModuleExtensionDescriptor * d)
+: KviHeapObject()
+{
+ m_pDescriptor = d;
+ m_pDescriptor->registerObject(this);
+}
+
+KviModuleExtension::~KviModuleExtension()
+{
+ m_pDescriptor->unregisterObject(this);
+}
+
+
diff --git a/src/kvirc/module/kvi_moduleextension.h b/src/kvirc/module/kvi_moduleextension.h
new file mode 100644
index 00000000..0d1b2428
--- /dev/null
+++ b/src/kvirc/module/kvi_moduleextension.h
@@ -0,0 +1,143 @@
+#ifndef _KVI_MODULEEXTENSION_H_
+#define _KVI_MODULEEXTENSION_H_
+//
+// File : kvi_moduleextension.h
+// Creation date : Tue Sep 10 01:16:24 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+#include "kvi_string.h"
+#include "kvi_pointerlist.h"
+#include "kvi_heapobject.h"
+
+#include "kvi_pointerhashtable.h"
+#include <qpixmap.h>
+#include <qvariant.h>
+#include "kvi_pointerhashtable.h"
+
+class KviWindow;
+class KviModule;
+class KviModuleExtension;
+class KviModuleExtensionDescriptor;
+
+typedef struct _KviModuleExtensionAllocStructTag
+{
+ KviModuleExtensionDescriptor * pDescriptor; // module extension that this alloc routine refers to
+ KviWindow * pWindow; // may be 0!
+ KviPointerHashTable<QString,QVariant> * pParams; // parameter dict (may be 0!)
+ void * pSpecial; // special parameter passed to the alloc routine, may be 0
+} KviModuleExtensionAllocStruct;
+
+typedef KviModuleExtension * (*KviModuleExtensionAllocRoutine)(KviModuleExtensionAllocStruct *);
+
+class KVIRC_API KviModuleExtensionDescriptor
+{
+ friend class KviModuleExtension;
+ friend class KviModuleExtensionManager; // only the manager allocates and deallocates these structures
+protected:
+ KviModuleExtensionDescriptor(KviModule * m,const KviStr &szType,const KviStr &szName,const QString &szVisibleName,KviModuleExtensionAllocRoutine r,const QPixmap &pix);
+public: // this has to be public because of QPtrList... but should be protected
+ ~KviModuleExtensionDescriptor();
+private:
+ int m_iId; // unique id assigned at creation time
+ KviStr m_szType; // name of the service (toolbar , crypt engine...)
+ KviStr m_szName; // name of the extension
+ QString m_szVisibleName; // name that is VISIBLE and possibly translated
+ KviStr m_szAuthor; // Author (visible)
+ KviStr m_szDescription; // Description (visible!)
+ int m_iFlags; // Flags (0 if not applicable)
+ QPixmap * m_pIcon; // Icon (may be null!)
+ KviModuleExtensionAllocRoutine m_allocRoutine;
+ KviPointerList<KviModuleExtension> * m_pObjectList;
+
+ KviModule * m_pModule; // module pointer
+public:
+ // pParams ownership is NOT taken
+ KviModuleExtension * allocate(KviWindow * pWnd = 0,KviPointerHashTable<QString,QVariant> * pParams = 0,void * pSpecial = 0);
+
+ int id(){ return m_iId; };
+ KviModule * module(){ return m_pModule; };
+ const KviStr &type(){ return m_szType; };
+ const KviStr &name(){ return m_szName; };
+ const QString &visibleName(){ return m_szVisibleName; };
+ const KviStr &author(){ return m_szAuthor; };
+ const KviStr &description(){ return m_szDescription; };
+ const QPixmap * icon(){ return m_pIcon; };
+ int flags(){ return m_iFlags; };
+
+ void setAuthor(const KviStr &szAuthor){ m_szAuthor = szAuthor; };
+ void setDescription(const KviStr &szDescription){ m_szDescription = szDescription; };
+ void setVisibleName(const KviStr &szVisibleName){ m_szVisibleName = szVisibleName; };
+ void setFlags(int iFlags){ m_iFlags = iFlags; };
+ void setIcon(const QPixmap &pix);
+
+protected:
+ void registerObject(KviModuleExtension * e);
+ void unregisterObject(KviModuleExtension * e);
+};
+
+typedef KviPointerList<KviModuleExtensionDescriptor> KviModuleExtensionDescriptorList;
+
+class KviModuleExtensionManager;
+
+extern KVIRC_API KviModuleExtensionManager * g_pModuleExtensionManager;
+
+class KVIRC_API KviModuleExtensionManager
+{
+ friend class KviModule;
+ friend class KviApp;
+protected:
+ KviModuleExtensionManager(); // KviApp calls this
+ ~KviModuleExtensionManager(); // and this
+protected:
+ KviPointerHashTable<const char *,KviModuleExtensionDescriptorList> * m_pExtensionDict;
+protected:
+ // Only KviModule can call this
+ KviModuleExtensionDescriptor * registerExtension(KviModule * m,const KviStr &szType,const KviStr &szName,const QString &szVisibleName,KviModuleExtensionAllocRoutine r,const QPixmap &icon);
+ void unregisterExtensionsByModule(KviModule * m);
+public:
+ KviModuleExtensionDescriptor * findExtensionDescriptor(const KviStr &szType,const KviStr &szName);
+ static KviModuleExtensionManager * instance(){ return g_pModuleExtensionManager; };
+ KviModuleExtensionDescriptorList * getExtensionList(const KviStr &szType);
+ KviModuleExtension * allocateExtension(const KviStr &szType,const KviStr &szName,KviWindow * pWnd = 0,KviPointerHashTable<QString,QVariant> * pParams = 0,void * pSpecial = 0,const char * preloadModule = 0);
+ KviModuleExtension * allocateExtension(const KviStr &szType,int id,KviWindow * pWnd = 0,KviPointerHashTable<QString,QVariant> * pParams = 0,void * pSpecial = 0,const char * preloadModule = 0);
+private:
+ KviModuleExtensionDescriptorList * allocateExtensionGetDescriptorList(const KviStr &szType,const char * preloadModule);
+};
+
+
+
+class KVIRC_API KviModuleExtension : public KviHeapObject
+{
+public:
+ KviModuleExtension(KviModuleExtensionDescriptor * d);
+ virtual ~KviModuleExtension();
+private:
+ KviModuleExtensionDescriptor * m_pDescriptor;
+public:
+ static KviModuleExtensionManager * manager(){ return g_pModuleExtensionManager; };
+ KviModuleExtensionDescriptor * descriptor(){ return m_pDescriptor; };
+ // A module extension MUST implement die() as "delete this" <-- FIXME: this should be no longer necessary with KviHeapObject
+ virtual void die() = 0;
+};
+
+
+
+#endif //_KVI_MODULEEXTENSION_H_
diff --git a/src/kvirc/module/kvi_modulemanager.cpp b/src/kvirc/module/kvi_modulemanager.cpp
new file mode 100644
index 00000000..e13d2fd2
--- /dev/null
+++ b/src/kvirc/module/kvi_modulemanager.cpp
@@ -0,0 +1,369 @@
+//=============================================================================
+//
+// File : kvi_modulemanager.cpp
+// Creation date : Sat Aug 12 2000 20:32:11 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+#define __KVIRC__
+
+#define _KVI_MODULEMANAGER_CPP_
+
+#include "kvi_modulemanager.h"
+#include "kvi_fileutils.h"
+#include "kvi_app.h"
+#include "kvi_options.h"
+#include "kvi_frame.h"
+#include "kvi_console.h"
+#include "kvi_locale.h"
+#include "kvi_out.h"
+
+#include "kvi_library.h"
+
+#include <qdir.h>
+
+KviModuleManager * g_pModuleManager = 0;
+
+
+KviModuleManager::KviModuleManager()
+{
+ m_pModuleDict = new KviPointerHashTable<const char *,KviModule>(17,false);
+ m_pModuleDict->setAutoDelete(false);
+
+ m_pCleanupTimer = new QTimer(this);
+ connect(m_pCleanupTimer,SIGNAL(timeout()),this,SLOT(cleanupUnusedModules()));
+}
+
+KviModuleManager::~KviModuleManager()
+{
+ unloadAllModules();
+ delete m_pModuleDict;
+ delete m_pCleanupTimer;
+}
+
+
+void KviModuleManager::loadModulesByCaps(const char * caps,const char * dir)
+{
+ KviStr szCapsPath(KviStr::Format,"%s%ccaps%c%s%c",dir,KVI_PATH_SEPARATOR_CHAR,
+ KVI_PATH_SEPARATOR_CHAR,caps,KVI_PATH_SEPARATOR_CHAR);
+
+ QDir d(QString(szCapsPath.ptr()));
+
+ // FIXME: maybe check timestamps ? (old modules)
+
+ QStringList sl = d.entryList(QDir::Files | QDir::Readable | QDir::NoSymLinks);
+ for(QStringList::Iterator it = sl.begin();it != sl.end();++it)
+ {
+ KviStr modname = *it;
+ modname.cutToLast(KVI_PATH_SEPARATOR_CHAR);
+ getModule((*it).ascii());
+ }
+}
+
+void KviModuleManager::loadModulesByCaps(const char * caps)
+{
+ KviStr szDir;
+ g_pApp->getLocalKvircDirectory(szDir,KviApp::Plugins);
+ loadModulesByCaps(caps,szDir.ptr());
+ g_pApp->getGlobalKvircDirectory(szDir,KviApp::Plugins);
+ loadModulesByCaps(caps,szDir.ptr());
+}
+
+void KviModuleManager::completeModuleNames(const QString &path,const QString &word,KviPointerList<QString> * matches)
+{
+ QDir d(path);
+#ifdef COMPILE_ON_WINDOWS
+ d.setNameFilter("kvi*.dll");
+#else
+ d.setNameFilter("libkvi*.so");
+#endif
+ // FIXME: maybe check timestamps ? (old modules)
+
+ QStringList sl = d.entryList(QDir::Files | QDir::Readable | QDir::NoSymLinks);
+ for(QStringList::Iterator it = sl.begin();it != sl.end();++it)
+ {
+ QString * modname = new QString(*it);
+ KviQString::cutToLast(*modname,KVI_PATH_SEPARATOR_CHAR);
+ KviQString::cutToFirst(*modname,"kvi");
+ if(KviQString::equalCIN(word,*modname,word.length()))
+ {
+ KviQString::cutFromLast(*modname,".so");
+ if(!modname->isEmpty())
+ matches->append(modname);
+ else
+ delete modname;
+ } else delete modname;
+ }
+}
+
+void KviModuleManager::completeModuleNames(const QString &word,KviPointerList<QString> * matches)
+{
+ QString szDir;
+ // FIXME: Should check for duplicate names here!
+ g_pApp->getLocalKvircDirectory(szDir,KviApp::Plugins);
+ completeModuleNames(szDir,word,matches);
+ g_pApp->getGlobalKvircDirectory(szDir,KviApp::Plugins);
+ completeModuleNames(szDir,word,matches);
+}
+
+KviModule * KviModuleManager::findModule(const char * modName)
+{
+ KviModule * m = m_pModuleDict->find(modName);
+ if(m)m->updateAccessTime();
+ return m;
+}
+
+KviModule * KviModuleManager::getModule(const char * modName)
+{
+ KviModule * m = m_pModuleDict->find(modName);
+ if(!m)
+ {
+ if(!loadModule(modName)) return 0;
+ m = m_pModuleDict->find(modName);
+ }
+ if(m)m->updateAccessTime();
+ return m;
+}
+
+/*
+static bool default_module_cmd_load(KviModule *,KviCommand *)
+{
+ return true;
+}
+
+static bool default_module_cmd_unload(KviModule *m,KviCommand *)
+{
+ g_pModuleManager->unloadModule(m->name());
+ return true;
+}
+*/
+
+bool KviModuleManager::loadModule(const char * modName)
+{
+ if(findModule(modName))
+ {
+ //debug("MODULE %s ALREADY IN CORE MEMORY",modName);
+ return true;
+ }
+ QString tmp;
+ QString szName;
+#ifdef COMPILE_ON_WINDOWS
+ KviQString::appendFormatted(szName,"kvi%s.dll",modName);
+#else
+ KviQString::appendFormatted(szName,"libkvi%s.so",modName);
+#endif
+ szName=szName.lower();
+
+ g_pApp->getLocalKvircDirectory(tmp,KviApp::Plugins,szName);
+ if(!KviFileUtils::fileExists(tmp))
+ {
+ g_pApp->getGlobalKvircDirectory(tmp,KviApp::Plugins,szName);
+ }
+
+ if(!KviFileUtils::fileExists(tmp)) return false;
+ kvi_library_t handle = kvi_library_open(tmp.local8Bit().data());
+ if(!handle)
+ {
+ m_szLastError = kvi_library_error();
+ //debug("ERROR IN LOADING MODULE %s (%s): %s",modName,szName.ptr(),kvi_library_error());
+ return false;
+ }
+ KviModuleInfo * info = (KviModuleInfo *)kvi_library_symbol(handle,KVIRC_MODULE_STRUCTURE_SYMBOL);
+ if(!info)
+ {
+ m_szLastError = __tr2qs("No " KVIRC_MODULE_STRUCTURE_SYMBOL " symbol exported: not a kvirc module ?");
+ kvi_library_close(handle);
+ return false;
+ }
+ if(!info->szKVIrcVersion)
+ {
+ m_szLastError = __tr2qs("This module has no version informations: refusing to load it");
+ kvi_library_close(handle);
+ return false;
+ }
+ if(!KVI_OPTION_BOOL(KviOption_boolIgnoreModuleVersions))
+ {
+ if(!kvi_strEqualCS(info->szKVIrcVersion,KVI_VERSION))
+ {
+ m_szLastError = __tr2qs("This module was compiled for a different KVIrc version and can't be loaded");
+ m_szLastError += " (";
+ m_szLastError += info->szKVIrcVersion;
+ m_szLastError += ")";
+ kvi_library_close(handle);
+ return false;
+ }
+ }
+ KviModule * module = new KviModule(handle,info,modName,szName.utf8().data());
+
+ // the module is probably up.. the only thing can fail is the init_routine now
+ // load the message catalogue if any
+ KviStr szDir;
+ // it's more probable to have the translations in the global directory
+ // try it as first... (yes, catalogue overriding is impossible this way.. but , anybody cares ?)
+ g_pApp->getGlobalKvircDirectory(szDir,KviApp::Locale);
+
+ if(!KviLocale::loadCatalogue(modName,szDir.ptr()))
+ {
+ // try the local directory then
+ g_pApp->getLocalKvircDirectory(szDir,KviApp::Locale);
+ KviLocale::loadCatalogue(modName,szDir.ptr());
+ }
+
+ if(info->init_routine)
+ {
+ if(!((info->init_routine)(module)))
+ {
+ m_szLastError = __tr2qs("Failed to execute the init routine");
+ //debug("ERROR IN LOADING MODULE %s (%s): failed to execute the init routine",modName,szName.ptr());
+ kvi_library_close(handle);
+ delete module;
+ // kill the message catalogue too then
+ KviLocale::unloadCatalogue(modName);
+ return false;
+ }
+ }
+ m_pModuleDict->insert(modName,module);
+
+ /*
+ registerDefaultCommands(module);
+ */
+ module->registerDefaultCommands();
+
+ if(KVI_OPTION_BOOL(KviOption_boolCleanupUnusedModules))
+ {
+ if(!m_pCleanupTimer->isActive())
+ {
+ if(KVI_OPTION_UINT(KviOption_uintModuleCleanupTimerInterval) < 30)
+ KVI_OPTION_UINT(KviOption_uintModuleCleanupTimerInterval) = 30;
+ m_pCleanupTimer->start(KVI_OPTION_UINT(KviOption_uintModuleCleanupTimerInterval) * 1000);
+ }
+ }
+ // be verbose if needed....just make sure that we're not shutting down...
+ if(_OUTPUT_VERBOSE && !g_pApp->closingDown())
+ {
+ if(g_pFrame)g_pFrame->firstConsole()->output(KVI_OUT_VERBOSE,
+ __tr2qs("Loaded module '%s' (%s)"),modName,szName.utf8().data());
+ }
+ return true;
+}
+
+/*
+void KviModuleManager::registerDefaultCommands(KviModule * module)
+{
+ // Register the default commands
+ module->registerCommand("load",default_module_cmd_load);
+ module->registerCommand("unload",default_module_cmd_unload);
+}
+*/
+bool KviModuleManager::unloadModule(const char * modName)
+{
+ return unloadModule(findModule(modName));
+}
+
+bool KviModuleManager::unloadModule(KviModule * module)
+{
+ if(!module)return false;
+ moduleAboutToUnload(module);
+
+ if(module->moduleInfo()->cleanup_routine)
+ {
+ (module->moduleInfo()->cleanup_routine)(module);
+ }
+ KviStr szModName = module->name();
+ kvi_library_close(module->handle());
+ //debug("Closing module %s, dlclose returns %d",szModName.ptr(),dlclose(module->handle()));
+
+ m_pModuleDict->remove(szModName.ptr());
+ delete module;
+
+ // unload the message catalogues, if any
+ KviLocale::unloadCatalogue(szModName.ptr());
+
+ if(m_pModuleDict->isEmpty())
+ {
+ if(m_pCleanupTimer->isActive())m_pCleanupTimer->stop();
+ }
+
+ if(_OUTPUT_VERBOSE && !g_pApp->closingDown())
+ {
+ if(g_pFrame)g_pFrame->firstConsole()->output(KVI_OUT_VERBOSE,
+ __tr2qs("Unloaded module '%s'"),szModName.ptr());
+ }
+ return true;
+}
+
+bool KviModuleManager::hasLockedModules()
+{
+ KviPointerHashTableIterator<const char *,KviModule> it(*m_pModuleDict);
+ while(KviModule * m = it.current())
+ {
+ if(m->isLocked())return true;
+ ++it;
+ }
+ return false;
+}
+
+
+void KviModuleManager::cleanupUnusedModules()
+{
+ KviPointerHashTableIterator<const char *,KviModule> it(*m_pModuleDict);
+
+ KviPointerList<KviModule> lModulesToUnload;
+ lModulesToUnload.setAutoDelete(false);
+
+ while(it.current())
+ {
+ if(it.current()->secondsSinceLastAccess() > KVI_OPTION_UINT(KviOption_uintModuleCleanupTimeout))
+ {
+ if(it.current()->moduleInfo()->can_unload)
+ {
+ if((it.current()->moduleInfo()->can_unload)(it.current()))
+ lModulesToUnload.append(it.current());
+ else {
+ // the module don't want to be unloaded
+ // keep it memory for a while
+ it.current()->updateAccessTime();
+ }
+ } else {
+ if(!(it.current()->isLocked()))
+ lModulesToUnload.append(it.current());
+ }
+ }
+ ++it;
+ }
+
+ for(KviModule * pModule = lModulesToUnload.first();pModule;pModule = lModulesToUnload.next())
+ unloadModule(pModule);
+}
+
+void KviModuleManager::unloadAllModules()
+{
+ KviPointerHashTableIterator<const char *,KviModule> it(*m_pModuleDict);
+
+ KviPointerList<KviModule> lModulesToUnload;
+ lModulesToUnload.setAutoDelete(false);
+ while(KviModule * pModule = it.current())
+ {
+ lModulesToUnload.append(pModule);
+ ++it;
+ }
+
+ for(KviModule * pModule = lModulesToUnload.first();pModule;pModule = lModulesToUnload.next())
+ unloadModule(pModule);
+}
diff --git a/src/kvirc/module/kvi_modulemanager.h b/src/kvirc/module/kvi_modulemanager.h
new file mode 100644
index 00000000..bba3544e
--- /dev/null
+++ b/src/kvirc/module/kvi_modulemanager.h
@@ -0,0 +1,70 @@
+#ifndef _KVI_MODULEMANAGER_H_
+#define _KVI_MODULEMANAGER_H_
+
+//=============================================================================
+//
+// File : kvi_modulemanager.h
+// Creation date : Sat Aug 12 2000 20:31:17 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#include <qobject.h>
+#include "kvi_pointerhashtable.h"
+#include <qtimer.h>
+#include "kvi_pointerlist.h"
+
+#include "kvi_module.h"
+
+class KVIRC_API KviModuleManager : public QObject
+{
+ Q_OBJECT
+public:
+ KviModuleManager();
+ ~KviModuleManager();
+private:
+ KviPointerHashTable<const char *,KviModule> * m_pModuleDict;
+ QTimer * m_pCleanupTimer;
+ KviStr m_szLastError;
+public:
+ KviStr & lastError(){ return m_szLastError; };
+ KviModule * findModule(const char * modName);
+ KviModule * getModule(const char * modName);
+ bool loadModule(const char * modName);
+ bool unloadModule(const char * modName);
+ bool unloadModule(KviModule * module);
+ void unloadAllModules();
+ //void registerDefaultCommands(KviModule * module);
+ void loadModulesByCaps(const char * caps,const char * dir);
+ void loadModulesByCaps(const char * caps);
+ bool hasLockedModules();
+ void completeModuleNames(const QString &word,KviPointerList<QString> * matches);
+protected:
+ void completeModuleNames(const QString &path,const QString &work,KviPointerList<QString> * matches);
+public slots:
+ void cleanupUnusedModules();
+signals:
+ void moduleAboutToUnload(KviModule * m);
+};
+
+extern KVIRC_API KviModuleManager * g_pModuleManager;
+
+#endif //_KVI_MODULEMANAGER_H_
diff --git a/src/kvirc/module/moc_kvi_mexlinkfilter.cpp b/src/kvirc/module/moc_kvi_mexlinkfilter.cpp
new file mode 100644
index 00000000..17ee562a
--- /dev/null
+++ b/src/kvirc/module/moc_kvi_mexlinkfilter.cpp
@@ -0,0 +1,94 @@
+/****************************************************************************
+** KviMexLinkFilter meta object code from reading C++ file 'kvi_mexlinkfilter.h'
+**
+** Created: Mon Feb 25 00:12:13 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_mexlinkfilter.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviMexLinkFilter::className() const
+{
+ return "KviMexLinkFilter";
+}
+
+QMetaObject *KviMexLinkFilter::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviMexLinkFilter( "KviMexLinkFilter", &KviMexLinkFilter::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviMexLinkFilter::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviMexLinkFilter", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviMexLinkFilter::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviMexLinkFilter", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviMexLinkFilter::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = QObject::staticMetaObject();
+ metaObj = QMetaObject::new_metaobject(
+ "KviMexLinkFilter", parentObject,
+ 0, 0,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviMexLinkFilter.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviMexLinkFilter::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviMexLinkFilter" ) )
+ return this;
+ if ( !qstrcmp( clname, "KviModuleExtension" ) )
+ return (KviModuleExtension*)this;
+ return QObject::qt_cast( clname );
+}
+
+bool KviMexLinkFilter::qt_invoke( int _id, QUObject* _o )
+{
+ return QObject::qt_invoke(_id,_o);
+}
+
+bool KviMexLinkFilter::qt_emit( int _id, QUObject* _o )
+{
+ return QObject::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviMexLinkFilter::qt_property( int id, int f, QVariant* v)
+{
+ return QObject::qt_property( id, f, v);
+}
+
+bool KviMexLinkFilter::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvirc/module/moc_kvi_mexserverimport.cpp b/src/kvirc/module/moc_kvi_mexserverimport.cpp
new file mode 100644
index 00000000..1ef542ef
--- /dev/null
+++ b/src/kvirc/module/moc_kvi_mexserverimport.cpp
@@ -0,0 +1,124 @@
+/****************************************************************************
+** KviMexServerImport meta object code from reading C++ file 'kvi_mexserverimport.h'
+**
+** Created: Mon Feb 25 00:12:15 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_mexserverimport.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviMexServerImport::className() const
+{
+ return "KviMexServerImport";
+}
+
+QMetaObject *KviMexServerImport::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviMexServerImport( "KviMexServerImport", &KviMexServerImport::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviMexServerImport::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviMexServerImport", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviMexServerImport::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviMexServerImport", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviMexServerImport::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = QObject::staticMetaObject();
+ static const QUParameter param_signal_0[] = {
+ { "s", &static_QUType_ptr, "KviIrcServer", QUParameter::In },
+ { "network", &static_QUType_charstar, 0, QUParameter::In }
+ };
+ static const QUMethod signal_0 = {"server", 2, param_signal_0 };
+ static const QMetaData signal_tbl[] = {
+ { "server(const KviIrcServer&,const char*)", &signal_0, QMetaData::Public }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviMexServerImport", parentObject,
+ 0, 0,
+ signal_tbl, 1,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviMexServerImport.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviMexServerImport::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviMexServerImport" ) )
+ return this;
+ if ( !qstrcmp( clname, "KviModuleExtension" ) )
+ return (KviModuleExtension*)this;
+ return QObject::qt_cast( clname );
+}
+
+#include <qobjectdefs.h>
+#include <qsignalslotimp.h>
+
+// SIGNAL server
+void KviMexServerImport::server( const KviIrcServer& t0, const char* t1 )
+{
+ if ( signalsBlocked() )
+ return;
+ QConnectionList *clist = receivers( staticMetaObject()->signalOffset() + 0 );
+ if ( !clist )
+ return;
+ QUObject o[3];
+ static_QUType_ptr.set(o+1,&t0);
+ static_QUType_charstar.set(o+2,t1);
+ activate_signal( clist, o );
+}
+
+bool KviMexServerImport::qt_invoke( int _id, QUObject* _o )
+{
+ return QObject::qt_invoke(_id,_o);
+}
+
+bool KviMexServerImport::qt_emit( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->signalOffset() ) {
+ case 0: server((const KviIrcServer&)*((const KviIrcServer*)static_QUType_ptr.get(_o+1)),(const char*)static_QUType_charstar.get(_o+2)); break;
+ default:
+ return QObject::qt_emit(_id,_o);
+ }
+ return TRUE;
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviMexServerImport::qt_property( int id, int f, QVariant* v)
+{
+ return QObject::qt_property( id, f, v);
+}
+
+bool KviMexServerImport::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvirc/module/moc_kvi_mextoolbar.cpp b/src/kvirc/module/moc_kvi_mextoolbar.cpp
new file mode 100644
index 00000000..a537e3f4
--- /dev/null
+++ b/src/kvirc/module/moc_kvi_mextoolbar.cpp
@@ -0,0 +1,94 @@
+/****************************************************************************
+** KviMexToolBar meta object code from reading C++ file 'kvi_mextoolbar.h'
+**
+** Created: Mon Feb 25 00:12:16 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_mextoolbar.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviMexToolBar::className() const
+{
+ return "KviMexToolBar";
+}
+
+QMetaObject *KviMexToolBar::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviMexToolBar( "KviMexToolBar", &KviMexToolBar::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviMexToolBar::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviMexToolBar", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviMexToolBar::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviMexToolBar", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviMexToolBar::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = KviToolBar::staticMetaObject();
+ metaObj = QMetaObject::new_metaobject(
+ "KviMexToolBar", parentObject,
+ 0, 0,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviMexToolBar.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviMexToolBar::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviMexToolBar" ) )
+ return this;
+ if ( !qstrcmp( clname, "KviModuleExtension" ) )
+ return (KviModuleExtension*)this;
+ return KviToolBar::qt_cast( clname );
+}
+
+bool KviMexToolBar::qt_invoke( int _id, QUObject* _o )
+{
+ return KviToolBar::qt_invoke(_id,_o);
+}
+
+bool KviMexToolBar::qt_emit( int _id, QUObject* _o )
+{
+ return KviToolBar::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviMexToolBar::qt_property( int id, int f, QVariant* v)
+{
+ return KviToolBar::qt_property( id, f, v);
+}
+
+bool KviMexToolBar::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvirc/module/moc_kvi_modulemanager.cpp b/src/kvirc/module/moc_kvi_modulemanager.cpp
new file mode 100644
index 00000000..e9b815a0
--- /dev/null
+++ b/src/kvirc/module/moc_kvi_modulemanager.cpp
@@ -0,0 +1,129 @@
+/****************************************************************************
+** KviModuleManager meta object code from reading C++ file 'kvi_modulemanager.h'
+**
+** Created: Mon Feb 25 00:12:18 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_modulemanager.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviModuleManager::className() const
+{
+ return "KviModuleManager";
+}
+
+QMetaObject *KviModuleManager::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviModuleManager( "KviModuleManager", &KviModuleManager::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviModuleManager::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviModuleManager", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviModuleManager::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviModuleManager", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviModuleManager::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = QObject::staticMetaObject();
+ static const QUMethod slot_0 = {"cleanupUnusedModules", 0, 0 };
+ static const QMetaData slot_tbl[] = {
+ { "cleanupUnusedModules()", &slot_0, QMetaData::Public }
+ };
+ static const QUParameter param_signal_0[] = {
+ { "m", &static_QUType_ptr, "KviModule", QUParameter::In }
+ };
+ static const QUMethod signal_0 = {"moduleAboutToUnload", 1, param_signal_0 };
+ static const QMetaData signal_tbl[] = {
+ { "moduleAboutToUnload(KviModule*)", &signal_0, QMetaData::Public }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviModuleManager", parentObject,
+ slot_tbl, 1,
+ signal_tbl, 1,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviModuleManager.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviModuleManager::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviModuleManager" ) )
+ return this;
+ return QObject::qt_cast( clname );
+}
+
+#include <qobjectdefs.h>
+#include <qsignalslotimp.h>
+
+// SIGNAL moduleAboutToUnload
+void KviModuleManager::moduleAboutToUnload( KviModule* t0 )
+{
+ if ( signalsBlocked() )
+ return;
+ QConnectionList *clist = receivers( staticMetaObject()->signalOffset() + 0 );
+ if ( !clist )
+ return;
+ QUObject o[2];
+ static_QUType_ptr.set(o+1,t0);
+ activate_signal( clist, o );
+}
+
+bool KviModuleManager::qt_invoke( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->slotOffset() ) {
+ case 0: cleanupUnusedModules(); break;
+ default:
+ return QObject::qt_invoke( _id, _o );
+ }
+ return TRUE;
+}
+
+bool KviModuleManager::qt_emit( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->signalOffset() ) {
+ case 0: moduleAboutToUnload((KviModule*)static_QUType_ptr.get(_o+1)); break;
+ default:
+ return QObject::qt_emit(_id,_o);
+ }
+ return TRUE;
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviModuleManager::qt_property( int id, int f, QVariant* v)
+{
+ return QObject::qt_property( id, f, v);
+}
+
+bool KviModuleManager::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvirc/sparser/Makefile.am b/src/kvirc/sparser/Makefile.am
new file mode 100644
index 00000000..c84487eb
--- /dev/null
+++ b/src/kvirc/sparser/Makefile.am
@@ -0,0 +1,5 @@
+###############################################################################
+# KVirc IRC client Makefile - 16.12.98 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+EXTRA_DIST = *.cpp *.h
diff --git a/src/kvirc/sparser/kvi_antispam.cpp b/src/kvirc/sparser/kvi_antispam.cpp
new file mode 100644
index 00000000..e1eec8af
--- /dev/null
+++ b/src/kvirc/sparser/kvi_antispam.cpp
@@ -0,0 +1,122 @@
+//
+// File : kvi_antispam.cpp
+// Creation date : Sun Apr 18 1999 05:36:55 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+#define __KVIRC__
+#define _KVI_ANTISPAM_CPP_
+
+#include "kvi_antispam.h"
+#include "kvi_options.h"
+
+//[05:10:48] <Nataly19> :2http://www.extrababes.com5Go ahead punk, make my day !
+//[05:11:04] <treeman> :-`` -= for mp3's go to http://members.xoom.com/treemansmp3/start.htm
+// =- ```-
+//[05:10:51] <Suzi48498>:P*** **** squirms like CRAZY when **** licks between her ...
+//[05:12:11] <dea_> :Hi my name is **** and I just posted pics of myself and
+// other hot girls on my website at http://133.16.114.32/~guest/
+// tell me what you think!
+//[15:18:37] <JuL|aN^bZ> Join #Teens4eva...Have Fun PPl!!!
+//[15:19:37] <jkhnbn> Ciao, vai sul sito www.sitromba.3000.it ci sono un casino di
+// immagini e video porno gratisssssssssssssssss!!!!!
+//[15:19:46] <emjot``> zapraszam na kanal #poke super zabawa i opa za free !!!!!
+//[15:23:20] <AlExXxX> IMPORTANTE: Se cerchi foto e video HARD andate qu:
+// http://216.221.175.58/cgi-bin/affiliate/ad.cgi?id=m4rines [automsg]
+//[15:23:36] <Jane> hi..join #hard sex channel --Venom ScRipT-- SToRM iN THe DaRK!!
+//[15:23:47] <lovghgh> VISIT>> http://go.to/mp3andwarez/ << VISIT[15:23:47] <lovghgh> VISIT>> http://go.to/mp3andwarez/ << VISIT
+//[15:23:56] <PIMPOLO> HO le prove certe che si puo' far soldi dovendo solo ricevere sms pubblicitari sul cellulare.
+// Mi sono arrivati sms pubblicitari!!! Ti interessa ? ISCRIVITI CLICCANDO DIRETTAMENTE SU QUESTO SITO:
+// http://www.smscash.it/index.php3?pagid=reg&p_form=P&p_pres=0&cpre=95620&p_desc=1 (Messaggio Automatico) IRSimpson
+
+
+// Yes...it is really annoying when I join a channel and
+// i am flooded with all that messages.
+// On large-newbie-high-traffic channels I get lagged
+// with the Query windows popping up with all that stuff.
+// What I can do ? Ignore queries ?
+// mmmmh
+//
+// kvi_mayBeSpam : try to guess if text may be a spam message.
+// Ideas:
+// - A spam message is generally a single PRIVMSG <mynick> :<text>
+// so this function should be (and is) called when
+// a PRIVMSG is received from a person that has no QUERY
+// window open yet.
+// - 95% of spam messages contain an URL inside (http,ftp,www) or a channel name.
+// - The other 5% contain words like auto-msg , msg me or query <nickname>
+// - There are some really common words:
+// free , mp3 , sex , teen , porn , pics , girls , babe , pass , user... , hard , join
+//
+// In this way we can get rid of a good 70% of spam msgs.
+
+// Just a minor change. This allows to easily add more "banned" words.
+// Maybe there should be a config dialog for that ? Some people like to get
+// porno pics, but don't like mp3's for example ... ;-)))
+// -- Kristoff
+
+// Ok...made this completely configurable....
+// The default spam words get "installed" by the default script
+// 09-01-2001: Pragma
+
+/*
+ @doc: antispam
+ @title:
+ Anti-spam protection
+ @keyterms:
+ spam
+ @body:
+ KVIrc contains a small spam detector, and can help you in avoiding that annoying flood
+ of queries popping up when you join large channels full of lamers.[br]
+ The spam detector works in a rather simple way: when someone sends you a private message
+ containing one or more "special words", and that user has no open query window,
+ so the message is treated as spam and is redirected to the console window or is ignored completely
+ (if you enable that option).[br]
+ The spam words to check for, can be set by the means of [cmd]option[/cmd] stringlistSpamWords.[br]
+ The anti-spam engine can be enabled by setting [cmd]option[/cmd] boolUseAntiSpamOnPrivmsg and
+ [cmd]option[/cmd] boolUseAntiSpamOnNotice to 1.[br]
+ @examples:
+ [example]
+ [comment]# This will cause "new-query private messages" containing[/comment]
+ [comment]# words "http:","#" (channel name),"ftp:".... to be redirected to the console[/comment]
+ [cmd]option[/cmd] stringlistSpamWords http:,#,ftp:,sex,free,chat,join
+ [cmd]option[/cmd] boolUseAntiSpamOnPrivmsg 1
+ [comment]# This will cause these messages to be completely ignored[/comment]
+ [cmd]option[/cmd] boolSilentAntiSpam 1
+ [/example]
+*/
+
+bool kvi_mayBeSpam(KviStr * msg,KviStr &spamWord)
+{
+ for(QStringList::Iterator it = KVI_OPTION_STRINGLIST(KviOption_stringlistSpamWords).begin();
+ it != KVI_OPTION_STRINGLIST(KviOption_stringlistSpamWords).end() ; ++it)
+ {
+ // FIXME : This is SLOOOOOOOOW (QString -> ascii translation!!)
+
+ const char * aux = (*it).ascii();
+ if(aux)
+ {
+ if(msg->findFirstIdx(aux,false) != -1)
+ {
+ spamWord = aux;
+ return true;
+ }
+ }
+ }
+ return false;
+}
diff --git a/src/kvirc/sparser/kvi_antispam.h b/src/kvirc/sparser/kvi_antispam.h
new file mode 100644
index 00000000..2d4f1c0f
--- /dev/null
+++ b/src/kvirc/sparser/kvi_antispam.h
@@ -0,0 +1,31 @@
+#ifndef _KVI_ANTISPAM_H_
+#define _KVI_ANTISPAM_H_
+//
+// File : kvi_antispam.h
+// Creation date : Sun Apr 18 1999 05:36:55 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+#include "kvi_settings.h"
+
+#include "kvi_string.h"
+
+extern KVIRC_API bool kvi_mayBeSpam(KviStr * msg,KviStr &spamWord);
+
+
+#endif // _KVI_ANTISPAM_H_
diff --git a/src/kvirc/sparser/kvi_ircmessage.cpp b/src/kvirc/sparser/kvi_ircmessage.cpp
new file mode 100644
index 00000000..512f03e5
--- /dev/null
+++ b/src/kvirc/sparser/kvi_ircmessage.cpp
@@ -0,0 +1,179 @@
+//=============================================================================
+//
+// File : kvi_ircmessage.cpp
+// Creation date : Fri Aug 2 23:08:57 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_ircmessage.h"
+#include "kvi_ircconnection.h"
+#include "kvi_console.h"
+
+KviIrcMessage::KviIrcMessage(const char * message,KviIrcConnection * pConnection)
+{
+ m_pConnection = pConnection;
+ m_pConsole = pConnection->console();
+ m_iFlags = 0;
+
+ const char * aux;
+ m_ptr = message;
+
+ m_pParams = new KviPointerList<KviStr>;
+ m_pParams->setAutoDelete(true);
+
+ //m_pcParams = new KviPointerList<QCString>;
+ //m_pcParams->setAutoDelete(true);
+
+ while(*m_ptr == ' ')++m_ptr;
+ const char * allParams = m_ptr; // just to be sure
+ if(*m_ptr)
+ {
+ if(*m_ptr == ':')
+ {
+ aux = ++m_ptr;
+ while(*m_ptr && (*m_ptr != ' '))++m_ptr;
+ m_szPrefix.extractFromString(aux,m_ptr);
+ while(*m_ptr == ' ')++m_ptr;
+ }
+ aux = m_ptr;
+ while(*m_ptr && (*m_ptr != ' '))++m_ptr;
+ m_szCommand.extractFromString(aux,m_ptr);
+ while(*m_ptr == ' ')++m_ptr;
+ allParams = m_ptr;
+ while(*m_ptr)
+ {
+ if(*m_ptr == ':')
+ {
+ ++m_ptr;
+ m_pParams->append(new KviStr(m_ptr));
+ //m_pcParams->append(new QCString(m_ptr));
+ break; // this was the last
+ } else {
+ aux = m_ptr;
+ while(*m_ptr && (*m_ptr != ' '))++m_ptr;
+ m_pParams->append(new KviStr(aux,m_ptr));
+ //m_pcParams->append(new QCString(KviStr(aux,m_ptr).ptr()));
+ while(*m_ptr == ' ')++m_ptr;
+ }
+ }
+ }
+ m_ptr = allParams;
+
+ m_iNumericCommand = (*m_szCommand.ptr() - '0') * 100;
+
+ if((m_szCommand.len() == 3) && (m_iNumericCommand <= 900) && (m_iNumericCommand >= 0))
+ {
+ aux = m_szCommand.ptr();
+ aux++;
+ if((*aux >= '0') && (*aux <= '9'))
+ {
+ m_iNumericCommand += (*aux - '0') * 10;
+ aux++;
+ if((*aux >= '0') && (*aux <= '9'))
+ {
+ m_iNumericCommand += (*aux - '0');
+ } else {
+ m_iNumericCommand = -1;
+ m_szCommand.toUpper();
+ }
+ } else {
+ m_iNumericCommand = -1;
+ m_szCommand.toUpper();
+ }
+ } else {
+ m_iNumericCommand = -1;
+ m_szCommand.toUpper();
+ }
+ //m_SafeTrailingString=QCString(m_pParams->last()->ptr());
+}
+
+KviIrcMessage::~KviIrcMessage()
+{
+ delete m_pParams;
+}
+
+void KviIrcMessage::decodeAndSplitMask(char * b,QString &szNick,QString &szUser,QString &szHost)
+{
+ static QString szWild("*");
+ char * p = b;
+
+ while(*p && *p != '!')p++;
+ if(*p)
+ {
+ if(p != b)
+ {
+ *p = 0;
+ szNick = m_pConnection->decodeText(b);
+ *p = '!';
+ } else {
+ szNick = szWild; // ???
+ }
+ } else {
+ if(p != b)szNick = m_pConnection->decodeText(b);
+ else szNick = szWild; // ???
+ szUser = szWild;
+ szHost = szWild;
+ return;
+ }
+ p++;
+ b = p;
+ while(*p && *p != '@')p++;
+ if(*p)
+ {
+ if(p != b)
+ {
+ *p = 0;
+ szUser = m_pConnection->decodeText(b);
+ *p = '@';
+ } else {
+ szUser = szWild; // ???
+ }
+ } else {
+ if(p != b)szUser = m_pConnection->decodeText(b);
+ else szUser = szWild; // ???
+ szHost = szWild;
+ return;
+ }
+ p++;
+ szHost = p; // hostnames are NOT encoded (at the moment...)
+
+}
+
+void KviIrcMessage::decodeAndSplitPrefix(QString &szNick,QString &szUser,QString &szHost)
+{
+ char * b;
+ if(m_szPrefix.hasData())b = m_szPrefix.ptr();
+ else {
+ m_szPrefix = connection()->currentServerName();
+ b = m_szPrefix.ptr();
+ }
+ decodeAndSplitMask(b,szNick,szUser,szHost);
+}
+
+
+const char * KviIrcMessage::safePrefix()
+{
+ if(m_szPrefix.hasData())return m_szPrefix.ptr();
+ m_szPrefix = connection()->currentServerName();
+ return m_szPrefix.ptr();
+}
+
diff --git a/src/kvirc/sparser/kvi_ircmessage.h b/src/kvirc/sparser/kvi_ircmessage.h
new file mode 100644
index 00000000..b77946f2
--- /dev/null
+++ b/src/kvirc/sparser/kvi_ircmessage.h
@@ -0,0 +1,106 @@
+#ifndef _KVI_IRCMESSAGE_H_
+#define _KVI_IRCMESSAGE_H_
+//=============================================================================
+//
+// File : kvi_ircmessage.h
+// Creation date : Fri Aug 2 23:08:55 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002-2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_pointerlist.h"
+#include "kvi_string.h"
+#include "kvi_qstring.h"
+#include "kvi_console.h"
+
+class KviIrcConnection;
+class KviIrcContext;
+class KviConneciton;
+
+#define KVI_IRCMSG_FLAG_HALTOUTPUT 1
+#define KVI_IRCMSG_FLAG_UNRECOGNIZED 2
+
+//
+// This is a single IRC message received from the server.
+// The message is strictly associated to the connection it came from.
+//
+// The IRC protocol is strictly 8 bit and thus the strings
+// are all 8 bit strings. The decoding of these strings should
+// be done on the targeting context (mainly channel or query...)
+//
+
+class KVIRC_API KviIrcMessage
+{
+public:
+ KviIrcMessage(const char * message,KviIrcConnection * pConnection);
+ ~KviIrcMessage();
+private:
+ const char * m_ptr; // shallow! never null
+ KviStr m_szPrefix; // the extracted prefix string
+ KviStr m_szCommand; // the extracted command (may be numeric)
+ KviPointerList<KviStr> * m_pParams; // the list of parameters
+ KviConsole * m_pConsole; // the console we're attacched to
+ KviIrcConnection * m_pConnection; // the connection we're attacched to
+ int m_iNumericCommand; // the numeric of the command (0 if non numeric)
+ int m_iFlags; // yes.. flags :D
+public:
+ KviConsole * console(){ return m_pConsole; };
+ KviIrcConnection * connection(){ return m_pConsole->connection(); };
+
+ bool isNumeric(){ return (m_iNumericCommand >= 0); };
+ const char * command(){ return m_szCommand.ptr(); };
+ KviStr * commandPtr(){ return &m_szCommand; };
+ int numeric(){ return m_iNumericCommand; };
+
+ KviStr * prefixPtr(){ return &m_szPrefix; };
+ const char * prefix(){ return m_szPrefix.ptr(); };
+ const char * safePrefix();
+ bool hasPrefix(){ return m_szPrefix.hasData(); };
+
+ bool isEmpty(){ return (m_szPrefix.isEmpty() && m_szCommand.isEmpty() && m_pParams->isEmpty()); };
+
+ int paramCount(){ return m_pParams->count(); };
+
+ const char * param(unsigned int idx){ return (idx < m_pParams->count()) ? m_pParams->at(idx)->ptr() : 0; };
+
+ const char * safeParam(unsigned int idx){ return (idx < m_pParams->count()) ? m_pParams->at(idx)->ptr() : KviStr::emptyString().ptr(); };
+
+ KviStr * paramString(unsigned int idx){ return m_pParams->at(idx); };
+
+ const char * trailing(){ KviStr * tr = m_pParams->last(); return tr ? tr->ptr() : 0; };
+ KviStr * trailingString(){ return m_pParams->last(); };
+ KviStr & safeTrailingString(){ KviStr * tr = m_pParams->last(); return tr ? *tr : KviStr::emptyString(); };
+ const char * safeTrailing(){ KviStr * tr = m_pParams->last(); return tr ? tr->ptr() : KviStr::emptyString().ptr(); };
+
+ const char * allParams(){ return m_ptr; };
+
+ KviStr * firstParam(){ return m_pParams->first(); };
+ KviStr * nextParam(){ return m_pParams->next(); };
+
+ void setHaltOutput(){ m_iFlags |= KVI_IRCMSG_FLAG_HALTOUTPUT; };
+ bool haltOutput(){ return (m_iFlags & KVI_IRCMSG_FLAG_HALTOUTPUT); };
+ void setUnrecognized(){ m_iFlags |= KVI_IRCMSG_FLAG_UNRECOGNIZED; };
+ bool unrecognized(){ return (m_iFlags & KVI_IRCMSG_FLAG_UNRECOGNIZED); };
+
+ void decodeAndSplitPrefix(QString &szNick,QString &szUser,QString &szHost);
+ void decodeAndSplitMask(char * mask,QString &szNick,QString &szUser,QString &szHost);
+};
+
+#endif //_KVI_IRCMESSAGE_H_
diff --git a/src/kvirc/sparser/kvi_numeric.h b/src/kvirc/sparser/kvi_numeric.h
new file mode 100644
index 00000000..2f5adee2
--- /dev/null
+++ b/src/kvirc/sparser/kvi_numeric.h
@@ -0,0 +1,430 @@
+#ifndef _KVI_NUMERIC_H_
+#define _KVI_NUMERIC_H_
+
+//
+// IRC - Internet Relay Chat, include/numeric.h
+// Copyright (C) 1990 Jarkko Oikarinen
+//
+// 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+
+// Revisited by Szymon Stefanek 07 Jul 1998 (pragma at kvirc dot net)
+// Re-revisited again on 11 Feb 1999 (pragma at kvirc dot net)
+
+// We will need 4 digit replies for the new irc protocol
+// and then leave 50-100 numbers between logical groups...
+
+// In kvirc 3.0.0 this file is newer included (at least for now: 31.07.2000)
+// Today I have included it in kvi_sp_numeric.cpp (23.03.2001)
+
+// ==============================================================================================//
+//
+// E=EFnet hybrid 5.3p2
+// e=EFNet hybrid 5.3p2 with #ifdef
+// I=IRCnet 2.10.0p5
+// i=IRCnet, reserved according to Undernet (sic) numerics header
+// U=Undernet u2.10.04
+// u=Undernet u2.10.04 with #ifdef
+// D=DALnet 4.6.7.DF
+// d=DALnet 4.6.7.DF, redundant
+// O=openprojects (dancer ircd)
+//
+
+// = 000-199 ====================================================================================//
+//
+// Reserve numerics 000-099 for server-client connections where the client
+// is local to the server. If any server is passed a numeric in this range
+// from another server then it is remapped to 100-199. -avalon
+//
+
+
+#define RPL_WELCOME 1 /* :Welcome to the Internet Relay Network %s [I,E,U,D] # */
+#define RPL_YOURHOST 2 /* :Your host is %s, running version %s [I,E,U,D] # */
+#define RPL_CREATED 3 /* :This server was created %s [I,E,U,D] # */
+#define RPL_MYINFO 4 /* <server_name> <srv_version> <u_modes> <ch_modes> [I,E,U,D] # */
+#define RPL_BOUNCE 5 /* :Try server %s, port %d [I] # */
+#define RPL_PROTOCTL 5 /* %s :are available on this server [D] # */
+#define RPL_MAP 5 /* :%s%s [U] # */
+#define RPL_MAPMORE 6 /* :%s%s --> *more* [U] # */
+#define RPL_MAPEND 7 /* :End of /MAP [U] # */
+//[03:45:18] [dune.webchat.org][007] newbie dune.webchat.org 1037760291 :Tue, 19 Nov 2002 18:44:51 -0800
+
+#define RPL_SNOMASK 8 /* %d :: Server notice mask (%#x) [U] # */
+//[03:45:18] [dune.webchat.org][008] newbie -/NAJgAxq7HQPwnkK^ 124963541 :This is your Session ID and Session Key.
+
+#define RPL_STATMEMTOT 9 /* %u %u :Bytes Blocks [U] # */
+//[03:45:18] [dune.webchat.org][009] newbie ASCII :Current character mapping.
+
+#define RPL_STATMEM 10 /* %u %u %s [U] # */
+#define RPL_BOUNCENEW 10 /* :Try server %s, port %d [I-NEW] # */
+// RPL_???????? 11,12,13
+#define RPL_YOURCOOKIE 14 /* <cookie> :is your reconnection cookie [E,i?] # */
+
+#define RPL_CONNECTING 20 //:irc.dotsrc.org 020 * :Please wait while we process your connection.
+
+
+
+// = 200-399 ====================================================================================//
+//
+// Command replies
+//
+
+#define RPL_TRACELINK 200 /* [I,E,U,D] "Link <version> <destination> <next server> <next-server-TS-version><zflag> <link-time> <sendQ> <prev-server-sendQ>" [I,E,U,D] */
+#define RPL_TRACECONNECTING 201 /* [I,E,U,D] "Try. %d %s"*/
+#define RPL_TRACEHANDSHAKE 202 /* [I,E,U,D] "H.S. %d %s"*/
+#define RPL_TRACEUNKNOWN 203 /* [I,E,U,D] "???? %d %s %d"*/
+#define RPL_TRACEOPERATOR 204 /* [I,E,U,D] "Oper %d %s"*/
+#define RPL_TRACEUSER 205 /* [I,E,U,D] "User %d %s"*/
+#define RPL_TRACESERVER 206 /* [I,E,U,D] "Serv <class> <int>S <int>C <server> <nick!user|*!*>@<host|server> <TS-version><zflag>" [I,E,U,D] */
+#define RPL_TRACENEWTYPE 208 /* [I,E,U,D] "<newtype> 0 %s"*/
+#define RPL_TRACECLASS 209 /* [I,E,U,D] "Class %d %d"*/
+#define RPL_TRACERECONNECT 210 /* [I] ??? */
+#define RPL_STATSLINKINFO 211 /* [I,E,U,D] */
+#define RPL_STATSCOMMANDS 212 /* [I,E,U,D] "%s %u %u"*/
+#define RPL_STATSCLINE 213 /* [I,E,U,D] "%c %s * %s %d %d"*/
+#define RPL_STATSNLINE 214 /* [I,E,U,D] "%c %s * %s %d %d"*/
+#define RPL_STATSILINE 215 /* [I,E,U,D] "%c %s * %s %d %d"*/
+#define RPL_STATSKLINE 216 /* [I,E,U,D] */
+#define RPL_STATSPLINE 217 /* [U] */
+#define RPL_STATSQLINE 217 /* [I,E,U,D] */
+#define RPL_STATSYLINE 218 /* [I,E,U,D] */
+#define RPL_ENDOFSTATS 219 // [I,E,U,D] */
+// #define RPL_???? 220
+#define RPL_UMODEIS 221 /* <nick> <mode> [I,E,U,D] # */
+#define RPL_STATSBLINE 222 /* [E] */
+#define RPL_SQLINE_NICK 222 /* [D] */
+#define RPL_STATSELINE 223 /* [E] */
+#define RPL_STATSFLINE 224 /* [E] */
+#define RPL_STATSDLINE 225 /* [E] */
+// RPL_?????????? 226-230
+#define RPL_SERVICEINFO 231 /* [I,U,D] */
+#define RPL_ENDOFSERVICES 232 /* [I,U,D] */
+#define RPL_SERVICE 233 /* [I,U,D] */
+#define RPL_SERVLIST 234 /* [I,E,U,D] */
+#define RPL_SERVLISTEND 235 /* [I,E,U,D] */
+// RPL_?????????? 236-238
+#define RPL_STATSIAUTH 239 /* [I] # */
+#define RPL_STATSVLINE 240 /* [I] # */
+#define RPL_STATSLLINE 241 /* [I,E,U,D] # */
+#define RPL_STATSUPTIME 242 /* [I,E,U,D] # */
+#define RPL_STATSOLINE 243 /* [I,E,U,D] # */
+#define RPL_STATSHLINE 244 /* [I,E,U,D] # */
+#define RPL_STATSSLINE 245 /* [I,E,u,D] # */
+#define RPL_STATSPING 246 /* [I] # */
+#define RPL_STATSTLINE 246 /* [U] # */
+#define RPL_STATSBLINE_I 247 /* [I] # */
+#define RPL_STATSGLINE 247 /* [U] # */
+#define RPL_STATSXLINE 247 /* [D] # */
+#define RPL_STATSDEFINE 248 /* [I] # */
+#define RPL_STATSULINE 248 /* [U,D] # */
+#define RPL_STATSDEBUG 249 /* [I,E,U,D] # */
+#define RPL_STATSCONN 250 /* [e,U,D,O] # */
+#define RPL_STATSDLINE_I 250 /* [I] # */
+#define RPL_LUSERCLIENT 251 /* ":There are %d users and %d invisible on %d servers" [I,E,U,D,O] # */
+#define RPL_LUSEROP 252 /* "%d :IRC Operators online" [I,E,U,D,O] # */
+#define RPL_LUSERUNKNOWN 253 /* "%d :unknown connection(s)" [I,E,U,D,O] # */
+#define RPL_LUSERCHANNELS 254 /* "%d :channels formed" [I,E,U,D,O] # */
+#define RPL_LUSERME 255 /* ":I have %d clients and %d servers" [I,E,U,D,O] # */
+#define RPL_ADMINME 256 /* ":Administrative info about %s" [I,E,U,D] */
+#define RPL_ADMINLOC1 257 /* ":%s" [I,E,U,D] */
+#define RPL_ADMINLOC2 258 /* ":%s" [I,E,U,D] */
+#define RPL_ADMINEMAIL 259 /* ":%s" [I,E,U,D] */
+// RPL_????????? 260
+#define RPL_TRACELOG 261 /* [I,E,U,D] */
+#define RPL_TRACEEND 262 /* [I,E] */
+#define RPL_TRACEPING 262 /* [U] */
+//[14:28:51] [ircd.tin.it][263] [newbie] LINKS :Please wait a while and try again.
+#define RPL_TRYAGAIN 263 /* [I] */
+#define RPL_LOAD2HI 263 /* ":Server load is temporarily too heavy. Please wait a while and try again." [E] */
+// RPL_??????? 264
+#define RPL_LOCALUSERS 265 /* ":Current local users: %d Max: %s" [e,D,O] # */
+#define RPL_GLOBALUSERS 266 /* ":Current global users: %d Max: %d" [e,D,O] # */
+#define RPL_SHAREDUSERS 267 /* ":Current shared users: %d Max: %d" [I] # */
+// RPL_??????? 267-270
+#define RPL_SILELIST 271 /* [U,D] */
+#define RPL_ENDOFSILELIST 272 /* [U,D] */
+#define RPL_STATSDELTA 274 /* "<timedelta>" [i,E] */
+#define RPL_STATSDLINE_U 275 /* [U,D] */
+#define RPL_WHOISSSL 275 /* [AzzurraNET] %s :is using a secure connection (SSL) # */
+// RPL_??????? 276-279
+#define RPL_GLIST 280 /* [U] */
+#define RPL_ENDOFGLIST 281 /* [U] */
+// RPL_??????? 282-289
+#define RPL_HELPHDR 290 /* [D] */
+#define RPL_HELPOP 291 /* [D] */
+#define RPL_HELPTLR 292 /* [D] */
+#define RPL_HELPHLP 293 /* [D] */
+#define RPL_HELPFWD 294 /* [D] */
+#define RPL_HELPIGN 295 /* [D] */
+// RPL_??????? 296-299
+#define RPL_NONE 300 /* [I,E,U,D] */
+#define RPL_AWAY 301 /* ":fontana.openprojects.net 301 Pragma Nick :sleep :) [I,E,U,D] # */
+#define RPL_USERHOST 302 /* ":up to 5 userhost replies" [I,E,U,D] # */
+#define RPL_ISON 303 /* ":<list of present nicks>" [I,E,U,D] # */
+#define RPL_TEXT 304 /* [I,E,U,D] */
+#define RPL_UNAWAY 305 /* [I,E,U,D] # */
+#define RPL_NOWAWAY 306 /* [I,E,U,D] # */
+//#define RPL_USERIP 307 /* [U] */
+#define RPL_WHOISREGNICK 307 /* "???" [D] # */
+#define RPL_WHOISADMIN 308 /* "???" [d] # */
+#define RPL_WHOISSADMIN 309 /* "???" [d] # */
+#define RPL_WHOISHELPOP 310 /* "???" [D] # */
+
+#define RPL_WHOISUSER 311 /* "%s %s %s * :%s" [I,E,U,D] # */
+#define RPL_WHOISSERVER 312 /* "%s %s :%s" [I,E,U,D] # */
+#define RPL_WHOISOPERATOR 313 /* "%s :is an IRC Operator" [I,E,U,D] # */
+#define RPL_WHOWASUSER 314 /* "%s %s %s * :%s" [I,E,U,D] # */
+#define RPL_ENDOFWHO 315 /* "<channel> :End of /WHO list." [I,E,U,D] # */
+#define RPL_WHOISCHANOP 316 /* "???" [I,E,D] # */
+#define RPL_WHOISIDLE 317 /* "%s %ld %ld :seconds idle, signon time" [I,E,U,D] # */
+#define RPL_ENDOFWHOIS 318 /* "%s :End of /WHOIS list." [I,E,U,D] # */
+#define RPL_WHOISCHANNELS 319 /* "%s :%s" [I,E,U,D] # */
+#define RPL_WHOISIDENTIFIED 320 /* %s :is an identified user [O] # */
+#define RPL_LISTSTART 321 /* Channel :Users Name [I,E,U,D] # */
+#define RPL_LIST 322 /* <channel> <users> :<topic> [I,E,U,D] # */
+#define RPL_LISTEND 323 /* :End of /LIST [I,E,U,D] # */
+#define RPL_CHANNELMODEIS 324 /* "<channel> +<mode>" [I,E,U,D] # */
+#define RPL_CHANNELPASSIS 325 /* "<channel> <password>" [i] */
+#define RPL_NOCHANPASS 326 /* "<channel> :No channel password" [i] */
+#define RPL_CHPASSUNKNOWN 327 /* [i] */
+#define RPL_CHANURL 328 /* [D] [services.dal.net][328] Pragma #linux :http://dalnet.linuxguru.net */
+//[04:25:18] [services.dal.net][328] rettter #cebu :none.
+#define RPL_CREATIONTIME 329 /* "<channel> %lu" [E,U,D] # */
+#define RPL_WHOISAUTH 330 /* %s %s :is authed as .... [Quakenet] # */
+#define RPL_NOTOPIC 331 /* "<channel> :No topic is set." [I,E,U,D] # */
+#define RPL_TOPIC 332 /* "<channel> :%s" [I,E,U,D] # */
+#define RPL_TOPICWHOTIME 333 /* "<channel> <whoset> %lu" [e,U,D] # */
+#define RPL_LISTUSAGE 334 /* [U] */
+#define RPL_LISTSYNTAX 335 /* [D] */
+// RPL_?????????? 336-337
+#define RPL_CHANPASSOK 338 /* "<channel> :Channel password OK" [i] */
+#define RPL_BADCHANPASS 339 /* "<channel> :Invalid channel password" [i] */
+#define RPL_EQUALNICKS 339
+// RPL_?????????? 340
+#define RPL_INVITING 341 /* [I,E,U,D] */
+#define RPL_SUMMONING 342 /* [I,E,D] */
+// RPL_????????? 343-345
+#define RPL_INVITELIST 346 /* "<channel> <exceptionmask>" [I] # */
+#define RPL_ENDOFINVITELIST 347 /* "<channel> :End of Channel Invite List" [I] # */
+#define RPL_EXCEPTLIST 348 /* "<channel> <exceptionmask>" [I] # */
+#define RPL_ENDOFEXCEPTLIST 349 /* "<channel> :End of Channel Exception List" [I] # */
+// RPL_?????????? 350
+#define RPL_VERSION 351 /* "%s.%s %s :%s" [I,E,U,D] # */
+#define RPL_WHOREPLY 352 /* "<chn> <usr> <hst> <srv> <nck> <stat> :<hops> <real>"[I,E,U,D] # */
+#define RPL_NAMREPLY 353 /* "= <channel> :<space_separated_list_of_nicks>" [I,E,U,D] # */
+#define RPL_WHOSPCRPL 354 /* [U] */
+// RPL_????????? 355-360
+#define RPL_KILLDONE 361 /* [I,E,U,D] */
+#define RPL_CLOSING 362 /* [I,E,U,D] */
+#define RPL_CLOSEEND 363 /* [I,E,U,D] */
+#define RPL_LINKS 364 /* "<host> <parent> :<hops> <description>" [I,E,U,D] # */
+#define RPL_ENDOFLINKS 365 /* %s :End of /LINKS" [I,E,U,D] # */
+#define RPL_ENDOFNAMES 366 /* "%s :End of /NAMES list." [I,E,U,D] # */
+#define RPL_BANLIST 367 /* "<channel> <banmask>" [I,E,U,D] # */
+#define RPL_ENDOFBANLIST 368 /* "<channel> :End of channel Ban List" [I,E,U,D] # */
+#define RPL_ENDOFWHOWAS 369 /* "%s :END of /WHOWAS" [I,E,U,D] # */
+#define RPL_INFO 371 /* ":%s" [I,E,U,D] # */
+#define RPL_MOTD 372 /* ":- %s" [I,E,U,D] # */
+#define RPL_INFOSTART 373 /* ":Server INFO" [I,E,U,D] # */
+#define RPL_ENDOFINFO 374 /* ":End of /INFO list." [I,E,U,D] # */
+#define RPL_MOTDSTART 375 /* ":- %s Message of the Day - " [I,E,U,D] # */
+#define RPL_ENDOFMOTD 376 /* ":End of /MOTD command." [I,E,U,D] # */
+#define RPL_MOTD2 377 /* ":- %s" [?] # */
+#define RPL_MOTD3 378 /* ":- %s" [Austnet] # */
+// RPL_????????? 378-380
+#define RPL_YOUREOPER 381 /* [I,E,U,D] */
+#define RPL_REHASHING 382 /* [I,E,U,D] */
+#define RPL_YOURESERVICE 383 /* [I,D] */
+#define RPL_MYPORTIS 384 /* [I,E,U,D] */
+#define RPL_NOTOPERANYMORE 385 /* [I,E,U,D] */
+// RPL_????????? 386-390
+#define RPL_TIME 391 /* [I,E,U,D] */
+#define RPL_USERSSTART 392 /* [I,E,D] */
+#define RPL_USERS 393 /* [I,E,D] */
+#define RPL_ENDOFUSERS 394 /* [I,E,D] */
+#define RPL_NOUSERS 395 /* [I,E,D] */
+// RPL_????????? 396-399
+
+// = 400-599 ====================================================================================//
+//
+// Errors are in the range from 400-599 currently and are grouped by what
+// commands they come from.
+//
+
+// ERR_????????? 400
+#define ERR_NOSUCHNICK 401 /* "%s :No such nick/channel" [I,E,U,D] # */
+#define ERR_NOSUCHSERVER 402 /* "%s :No such server" [I,E,U,D] # */
+#define ERR_NOSUCHCHANNEL 403 /* "%s :No such channel" [I,E,U,D] */
+#define ERR_CANNOTSENDTOCHAN 404 /* "%s :Cannot send to channel" [I,E,U,D] */
+#define ERR_TOOMANYCHANNELS 405 /* "%s :You have joined too many channels" [I,E,U,D] */
+#define ERR_WASNOSUCHNICK 406 /* "%s :There was no such nickname [I,E,U,D] # */
+#define ERR_TOOMANYTARGETS 407 /* "%s :Duplicate recipients. No message delivered" [I,E,U,D] */
+#define ERR_NOSUCHSERVICE 408 /* "%s :No such service" [I,D] */
+#define ERR_NOORIGIN 409 /* ":No origin specified" [I,E,U,D] */
+// ERR_?????????? 410
+#define ERR_NORECIPIENT 411 /* ":No recipient given (%s)" [I,E,U,D] */
+#define ERR_NOTEXTTOSEND 412 /* ":No text to send" [I,E,U,D] */
+#define ERR_NOTOPLEVEL 413 /* "%s :No toplevel domain specified" [I,E,U,D] */
+#define ERR_WILDTOPLEVEL 414 /* "%s :Wildcard in toplevel Domain" [I,E,U,D] */
+#define ERR_BADMASK 415 /* ??? [I] */
+//#define ERR_TOOMANYTARGETS 416 /* Can not understand this ... but I've found it in some docs [I] */
+#define ERR_QUERYTOOLONG 416 /* "<target> <erroneous command> :Too many lines in the output, please restrict your query [U] */
+// ERR_?????????? 417-420
+#define ERR_UNKNOWNCOMMAND 421 /* "%s :Unknown command" [I,E,U,D] # */
+#define ERR_NOMOTD 422 /* ":MOTD File is missing" [I,E,U,D] */
+#define ERR_NOADMININFO 423 /* "%s :No administrative info available" [I,E,U,D] */
+#define ERR_FILEERROR 424 /* ":File error doing %s on %s" [I,E,U,D] */
+// ERR_?????????? 425-430
+#define ERR_NONICKNAMEGIVEN 431 /* ":No nickname given" [I,E,U,D] */
+#define ERR_ERRONEUSNICKNAME 432 /* "%s :Erroneus Nickname" [I,E,U,D] # */
+#define ERR_NICKNAMEINUSE 433 /* "%s :Nickname is already in use." [I,E,U,D] # */
+#define ERR_SERVICENAMEINUSE 434 /* ??? [I,D] */
+#define ERR_SERVICECONFUSED 435 /* ??? [I,D] */
+#define ERR_NICKCOLLISION 436 /* "%s :Nickname collision KILL" [I,E,U,D] # */
+#define ERR_UNAVAILRESOURCE 437 /* ??? [I] # */
+//#define ERR_BANNICKCHANGE 437 /* ??? duplicate [U,D] */
+#define ERR_NICKTOOFAST 438 /* ??? [U] # */
+//#define ERR_NCHANGETOOFAST 438 /* ??? duplicate [D] */
+#define ERR_TARGETTOOFAST 439 /* ??? [U,D] */
+#define ERR_SERVICESDOWN 440 /* ??? [D] */
+#define ERR_USERNOTINCHANNEL 441 /* "%s %s :They aren't on that channel" [I,E,U,D] */
+#define ERR_NOTONCHANNEL 442 /* "%s :You're not on that channel" [I,E,U,D] */
+#define ERR_USERONCHANNEL 443 /* "%s %s :is already on channel" [I,E,U,D] */
+#define ERR_NOLOGIN 444 /* "%s :User not logged in" [I,E,U,D] */
+#define ERR_SUMMONDISABLED 445 /* ":SUMMON has been removed/disabled" [I,E,U,D] */
+#define ERR_USERSDISABLED 446 /* ":USERS has been removed/disabled" [I,E,U,D] */
+// ERR_?????????? 447-450
+#define ERR_NOTREGISTERED 451 /* ":You have not registered" [I,E,U,D] */
+#define ERR_IDCOLLISION 452 /* ":ID collision KILL" [i,?] */
+#define ERR_NICKLOST 453 /* "<nick> :Nickname collision; please enter a new nick" [i,?] */
+// ERR_?????????? 454
+#define ERR_HOSTILENAME 455 /* ??? [D] */
+// ERR_?????????? 456-460
+#define ERR_NEEDMOREPARAMS 461 /* "%s :Not enough parameters" [I,E,U,D] */
+#define ERR_ALREADYREGISTRED 462 /* ":You may not reregister" [I,E,U,D] */
+#define ERR_NOPERMFORHOST 463 /* ":Your host isn't among the privileged" [I,E,U,D] */
+#define ERR_PASSWDMISMATCH 464 /* ":Password Incorrect" [I,E,U,D] */
+#define ERR_YOUREBANNEDCREEP 465 /* ":You are banned from this server- %s" [I,E,U,D] */
+//[04:42:04] [forever.va.us.mystical.net][465] Pragma :You have been Autokilled.
+#define ERR_YOUWILLBEBANNED 466 /* ??? [I,E,U,D] */
+#define ERR_KEYSET 467 /* "%s :Channel key already set" [I,E,U,D] */
+#define ERR_INVALIDUSERNAME 468 /* ??? [U,?] */
+//#define ERR_ONLYSERVERSCANCHANGE 468 /* ??? [D] */
+// ERR_??????????? 469-470
+#define ERR_CHANNELISFULL 471 /* "%s :Cannot join channel (+l)" [I,E,U,D] # */
+#define ERR_UNKNOWNMODE 472 /* "%c :is unknown mode char to me" [I,E,U,D] */
+#define ERR_INVITEONLYCHAN 473 /* "%s :Cannot join channel (+i)" [I,E,U,D] # */
+#define ERR_BANNEDFROMCHAN 474 /* "%s :Cannot join channel (+b)" [I,E,U,D] # */
+#define ERR_BADCHANNELKEY 475 /* "%s :Cannot join channel (+k)" [I,E,U,D] # */
+#define ERR_BADCHANMASK 476 /* "%s :Bad Channel Mask" [I,E,U,D] */
+#define ERR_MODELESS 477 /* ??? [U] */
+//#define ERR_???? 477 /* [irc.tin.it][477] [Pragma] 8 :Channel doesn't support modes [I] */
+#define ERR_NEEDREGGEDNICK 477 /* ??? [U] */
+//[03:48:45] [tiscali.uk.eu.dal.net][477] PragTest #italia :You need to identify to a registered nick to join that channel.
+#define ERR_BANLISTFULL 478 /* ??? [U,D] */
+// ERR_??????????? 479-480
+#define ERR_NOPRIVILEGES 481 /* ":Permission Denied- You're not an IRC operator" [I,E,U,D] */
+#define ERR_CHANOPRIVSNEEDED 482 /* "%s :You're not channel operator" [I,E,U,D] */
+#define ERR_CANTKILLSERVER 483 /* ":You cant kill a server!" [E,U,D] */
+#define ERR_DESYNC 484 /* ??? [E] */
+#define ERR_ISCHANSERVICE 484 /* ??? [U] */
+#define ERR_CHANTOORECENT 487 /* "<channel> :Channel created too recently" [i] */
+#define ERR_TSLESSCHAN 488 /* "<channel> :Mode <mode> not available on TS-less channel" [i] */
+// ERR_??????????? 489-490
+#define ERR_NOOPERHOST 491 /* ":Only few of mere mortals may try to enter the twilight zone" [I,E,U,D] */
+#define ERR_NOSERVICEHOST 492 /* ??? [I,D] */
+// ERR_??????????? 493-500
+#define ERR_UMODEUNKNOWNFLAG 501 /* ":Unknown MODE flag" [I,E,U,D] */
+#define ERR_USERSDONTMATCH 502 /* ":Cant change mode for other users" [I,E,U,D] */
+#define ERR_GHOSTEDCLIENT 503 /* ":Message could not be delivered to %s" [E] */
+#define ERR_LAST_ERR_MSG 504 /* ":Last Error Message" [E] */
+// ERR_??????????? 505-510
+#define ERR_SILELISTFULL 511 /* ??? [U,D] */
+#define ERR_NOSUCHGLINE 512 /* ??? [U] */
+#define ERR_TOOMANYWATCH 513 /* ??? [D] */
+#define ERR_BADPING 514 /* ??? [U] */
+#define ERR_NEEDPONG 515 /* ??? [D] */
+#define ERR_LISTSYNTAX 516 /* ??? [D] */
+// DalNet (excellent) extension that substitutes the ISON ping
+#define RPL_LOGON 600 /* <nick> <user> <host> <logintime> :logged online [D] # */
+#define RPL_LOGOFF 601 /* <nick> <user> <host> <logintime> :logged offline [D] # */
+#define RPL_WATCHOFF 602 /* <nick> <user> <host> <logintime> :stopped watching [D] # */
+#define RPL_WATCHSTAT 603 /* :You have <n> and are on <n> WATCH entries [D] # */
+#define RPL_NOWON 604 /* <nick> <user> <host> <logintime> :is online [D] # */
+#define RPL_NOWOFF 605 /* <nick> <user> <host> 0 :is offline [D] # */
+#define RPL_WATCHLIST 606 /* ? [D] # */
+#define RPL_ENDOFWATCH 607 /* :End of WATCH <char l=list s=stats> [D] # */
+// WeNet codepage extension
+#define RPL_CODEPAGESET 700 /* :irc.wenet.ru 700 Pragma CP1251 :is now your translation scheme # */
+#define RPL_WHOISSCHEME 703 /* :interdacom.vgd.wenet.ru 703 Alexey Begemot KOI8-R :translation scheme */
+
+///* 303 */ RPL_ISON, ":",
+///* 304 */ RPL_TEXT, (char *)NULL,
+///* 305 */ RPL_UNAWAY, ":You are no longer marked as being away",
+///* 306 */ RPL_NOWAWAY, ":You have been marked as being away",
+
+///* 321 */ RPL_LISTSTART, "Channel :Users Name",
+///* 322 */ RPL_LIST, "%s %d :%s",
+///* 323 */ RPL_LISTEND, ":End of /LIST",
+///* 324 */ RPL_CHANNELMODEIS, "%???"
+
+///* 334 */ 0, (char *)NULL,
+///* 341 */ RPL_INVITING, "%s %s",
+///* 342 */ RPL_SUMMONING, "%s :User summoned to irc",
+///* 352 */ RPL_WHOREPLY, ,
+///* 361 */ RPL_KILLDONE, (char *)NULL,
+///* 362 */ RPL_CLOSING, "%s :Closed. Status = %d",
+///* 363 */ RPL_CLOSEEND, "%d: Connections Closed",
+///* 364 */ RPL_LINKS, "%s %s :%d %s",
+///* 365 */ RPL_ENDOFLINKS, "%s :End of /LINKS list.",
+///* 367 */ RPL_BANLIST, "%s %s %s %lu",
+///* 367 */ RPL_BANLIST, "%s %s",
+///* 368 */ RPL_ENDOFBANLIST, "%s :End of Channel Ban List",
+///* 369 */ RPL_ENDOFWHOWAS, "%s :End of WHOWAS",
+///* 381 */ RPL_YOUREOPER, ":You have entered... the Twilight Zone!.",
+///* 382 */ RPL_REHASHING, "%s :Rehashing",
+///* 383 */ 0, (char *)NULL,
+///* 384 */ RPL_MYPORTIS, "%d :Port to local server is\r\n",
+///* 385 */ RPL_NOTOPERANYMORE, (char *)NULL,
+///* 391 */ RPL_TIME, "%s :%s",
+///* 392 */ RPL_USERSSTART, ":UserID Terminal Host",
+///* 393 */ RPL_USERS, ":%-8s %-9s %-8s",
+///* 394 */ RPL_ENDOFUSERS, ":End of Users",
+///* 395 */ RPL_NOUSERS, ":Nobody logged in.",
+///* 216 */ RPL_STATSKLINE, "%c %s * %s %s",
+///* 216 */ RPL_STATSKLINE, "%c %s %s %s %d %d",
+///* 217 */ RPL_STATSQLINE, "%c %s * %s %d %d",
+///* 218 */ RPL_STATSYLINE, "%c %d %d %d %d %ld",
+///* 219 */ RPL_ENDOFSTATS, "%c :End of /STATS report",
+///* 221 */ RPL_UMODEIS, "%s",
+///* 222 */ RPL_STATSBLINE, "%c %s * %s %d %d",
+///* 223 */ RPL_STATSELINE, "%c %s * %s %d %d",
+///* 224 */ RPL_STATSFLINE, "%c %s * %s %d %d",
+///* 225 */ RPL_STATSDLINE, "%c %s %s",
+///* 231 */ 0, (char *)NULL,
+///* 232 */ 0, (char *)NULL,
+///* 233 */ 0, (char *)NULL,
+///* 234 */ RPL_SERVLIST, (char *)NULL,
+///* 235 */ RPL_SERVLISTEND, (char *)NULL,
+///* 241 */ RPL_STATSLLINE, "%c %s * %s %d %d",
+///* 242 */ RPL_STATSUPTIME, ":Server Up %d days, %d:%02d:%02d",
+///* 243 */ RPL_STATSOLINE, "%c %s * %s %d %d",
+///* 244 */ RPL_STATSHLINE, "%c %s * %s %d %d",
+///* 245 */ RPL_STATSSLINE, "%c %s * %s %d %d",
+///* 250 */ RPL_STATSCONN,":Highest connection count: %d (%d clients)"
+///* 261 */ RPL_TRACELOG, "File %s %d",
+///* 262 */ RPL_ENDOFTRACE, "%s :End of TRACE",
+//[21:04:58] [oltrelinux.azzurra.org][275] Pragma Pragma :is using a secure connection (SSL)
+#endif // _KVI_NUMERIC_H_
diff --git a/src/kvirc/sparser/kvi_sp_ctcp.cpp b/src/kvirc/sparser/kvi_sp_ctcp.cpp
new file mode 100644
index 00000000..1e3736aa
--- /dev/null
+++ b/src/kvirc/sparser/kvi_sp_ctcp.cpp
@@ -0,0 +1,1855 @@
+//=============================================================================
+//
+// File : kvi_sp_ctcp.cpp
+// Creation date : Thu Aug 16 2000 13:34:42 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+// FIXME: #warning "CTCP BEEP == WAKEUP == AWAKE"
+// FIXME: #warning "CTCP AVATARREQ or QUERYAVATAR"
+
+#include "kvi_mirccntrl.h"
+#include "kvi_osinfo.h"
+#include "kvi_app.h"
+#include "kvi_sparser.h"
+#include "kvi_window.h"
+#include "kvi_out.h"
+#include "kvi_locale.h"
+#include "kvi_ircsocket.h"
+#include "kvi_channel.h"
+#include "kvi_defaults.h"
+#include "kvi_channel.h"
+#include "kvi_query.h"
+#include "kvi_ircuserdb.h"
+#include "kvi_iconmanager.h"
+#include "kvi_modulemanager.h"
+#include "kvi_sharedfiles.h"
+#include "kvi_time.h"
+#include "kvi_fileutils.h"
+#include "kvi_ctcppagedialog.h"
+#include "kvi_useraction.h"
+#include "kvi_options.h"
+#include "kvi_ircconnection.h"
+#include "kvi_ircconnectionuserinfo.h"
+#include "kvi_ircconnectionantictcpflooddata.h"
+#include "kvi_lagmeter.h"
+#include "kvi_kvs_eventtriggers.h"
+#include "kvi_kvs_script.h"
+#include "kvi_sourcesdate.h"
+#include "kvi_regusersdb.h"
+
+#include <stdlib.h>
+
+#include <qdatetime.h>
+
+#ifdef COMPILE_USE_QT4
+ #include <QTextDocument>
+#else
+ #include <qstylesheet.h>
+#endif
+
+
+
+extern KVIRC_API KviSharedFilesManager * g_pSharedFilesManager;
+extern KVIRC_API KviCtcpPageDialog * g_pCtcpPageDialog;
+
+/*
+ @doc: ctcp_handling
+ @title:
+ KVIrc and CTCP
+ @short:
+ For developers: Client-To-Client Protocol handling in KVIrc
+ @body:
+ [big]Introduction[/big][br]
+ Personally, I think that the CTCP specification is to
+ be symbolically printed & burned. It is really too complex
+ (you can go mad with the quoting specifications)
+ and NO IRC CLIENT supports it completely.
+ Here is my personal point of view on the CTCP protocol.[br]
+ [big]What is CTCP?[/big][br]
+ CTCP stands for Client-to-Client Protocol. It is designed
+ for exchanging almost arbitrary data between IRC clients;
+ the data is embedded into text messages of the underlying
+ IRC protocol.[br]
+ [big]Basic concepts[/big][br]
+ A CTCP message is sent as the <text> part of the PRIVMSG and
+ NOTICE IRC commands.[br]
+ To differentiate the CTCP message from a normal IRC message
+ text we use a delimiter character (ASCII char 1); we will
+ use the symbol <0x01> for this delimiter.
+ You may receive a CTCP message from server in one of the
+ following two ways:[br]
+ [b]:<source_mask> PRIVMSG <target> :<0x01><ctcp message><0x01>[/b][br]
+ [b]:<source_mask> NOTICE <target>:<0x01><ctcp message><0x01>[/b][br]
+ The PRIVMSG is used for CTCP REQUESTS, the NOTICE for CTCP REPLIES.
+ The NOTICE form should never generate an automatic reply.[br]
+ The two delimiters were used to begin and terminate the
+ CTCP message; The origial protocol allowed more than one CTCP
+ message inside a single IRC message. [b]Nobody sends more than
+ one message at once, no client can recognize it (since it
+ complicates the message parsing), it could be even dangerous (see below)[/b].
+ It makes no real sense unless we wanted to use the CTCP protocol to embed escape sequences
+ into IRC messages, which is not the case.[br]
+ Furthermore, sending more CTCP messages in a single IRC message could
+ be easily used to flood a client. Assuming 450 characters available for the IRC message
+ text part, you could include 50 CTCP messages containing "<0x01>VERSION<0x01>".[br]
+ Since the VERSION replies are usually long (there can be 3 or 4 replies per IRC message),
+ a client that has no CTCP flood protection (or has it disabled) will surely
+ be disconnected while sending the replies, after only
+ receiving a single IRC message (no flood for the sender).
+ From my personal point of view, only [b]one CTCP message per IRC message[/b]
+ should be allowed and theoretically the trailing <0x01> delimiter can be optional.[br]
+ [big]How to extract the CTCP message[/big][br]
+ The IRC messages do not allow the following characters to be sent:[br]
+ <NUL> (Ascii character 0), <CR> (Carriage return), <LF> (Line feed).[br]
+ So finally we have four characters that [b]cannot appear literally into a
+ CTCP message[/b]: <NUL>,<CR>,<LF>,<0x01>.[br]
+ To extract a <ctcp_message> from an IRC PRIVMSG or NOTICE command you
+ have to perform the following actions:[br]
+ Find the <trailing> part of the IRC message (the one just after the ':'
+ delimiter, or the last message token).[br]
+ Check if the first character of the <trailing> is a <0x01>, if it is
+ we have a <ctcp_message> beginning just after <0x01>.
+ The trailing (optional) <0x01> can be removed in this phase
+ or later, assuming that it is not a valid char in the <ctcp message>.[br]
+ In this document I will assume that you have stripped the trailing <0x01>
+ and thus from now on we will deal only with the <ctcp message> part.[br]
+
+ [big]Parsing a CTCP message: The quoting dilemma[/big][br]
+ Since there are characters that cannot appear in a <ctcp message>,
+ theoretically we should have to use a quoting mechanism.
+ Well, in fact, no actual CTCP message uses the quoting: there
+ is no need to include a <NUL>, a <CR> or <LF> inside the actually
+ defined messages (The only one could be CTCP SED, but I have never
+ seen it in action... is there any client that implements it?).
+ We could also leave the "quoting" to the "single message type semantic":
+ a message that needs to include "any character" could have its own
+ encoding method (Base64 for example). With the "one CTCP per IRC message"
+ convention we could even allow <0x01> inside messages. Only the leading
+ (and eventually trailing) <0x01> would be the delimiter, the other ones
+ would be valid characters. Finally, is there any CTCP type that needs
+ <0x01> inside a message? <0x01> is not printable (as well as <CR>,<LF> and <NUL>),
+ so only encoded messages (and again we can stick to the single message semantic)
+ messages or the ones including special parameters. Some machines might
+ allow <0x01> in filenames....well, a file with <0x01> in its name has something
+ broken inside, or the creator is a sort of "hacker" (so he also
+ knows how to rename a file...) :).[br]
+ Anyway, let's be pedantic, and define this quoting method.
+ Let's use the most intuitive method, adopted all around the world:[br]
+ The backslash character ('\') as escape.[br]
+ An escape sequence is formed by the backslash character and a number
+ of following ascii characters. We define the following two types of escape sequences:[br]
+ [b]'\XXX'[/b] (where XXX is an [b]octal number[/b] formed by three digits)
+ that indicates the ascii character with code that corresponds to the number.[br]
+ [b]'\C'[/b] (where C is a [b]CTCP valid ascii non digit character[/b]) that corresponds
+ literally to the character C discarding any other semantic that might be associated
+ with it (This will become clear later).
+ I've choosen the octal rappresentation just to follow a bit the old specification:
+ the authors seemed to like it. This point could be discussed in
+ some mailing list or sth. The '\C' sequence is useful to include the backslash
+ character (escape sequence '\\').[br]
+
+ [big]Let's mess a little more[/big][br]
+ A CTCP message is made of [b]space separated parameters[/b].[br]
+ The natural way of separating parameters is to use the space character.
+ We define a "token" as a sequence of valid CTCP characters not including literal space.
+ A <ctcp parameter> is usally a token, but not always;
+ filenames can contain spaces inside names (and it happens very often!).
+ So one of the parameters of CTCP DCC is not a space separated token.
+ How do we handle it? Again a standard is missing. Some clients simply change
+ the filename placing underscores instead of spaces, this is a reasonable solution if used with care.
+ Other clients attempt to "isolate" the filename token by surrounding it with some kind
+ of quotes, usually the '"' or ''' characters. This is also a good solution.
+ Another one that naturally comes into my mind is to use the previously defined
+ quoting to define a "non-breaking space" character, because a space after a backslash
+ could lose its original semantic. Better yet, use the backslash followed by
+ the octal rappresentation of the space character ('\040').
+ Anyway, to maintain compatibility with other popular IRC clients (such as mIRC),
+ let's include the '"' quotes in our standard: literal (unescaped) '"' quotes
+ define a single token string. To include a literal '"' character, escape it.
+ Additionally, the last parameter of a <ctcp message> may be made of multiple tokens.
+
+ [big]A CTCP parameter extracting example[/big][br]
+ A trivial example of a C "CTCP parameter extracting routine" follows.[br]
+ An IRC message is made of up to 510 useable characters.
+ When a CTCP is sent there is a PRIVMSG or NOTICE token that uses at least 6 characters,
+ at least two spaces and a target token (that can not be empty, so it is at least one character)
+ and finally one <0x01> escape character. This gives 500 characters as maximum size
+ for a complete <ctcp message> and thus for a <ctcp token>.
+ In fact, the <ctcp message> is always smaller than 500 characters; there are usually two
+ <0x01> chars, there is a message source part at the beginning of the IRC message
+ that is 10-15 characters long, and there is a ':' character before the trailing parameter.
+ Anyway, to really be on the "safe side", we use a 512 character buffer for each
+ <ctcp token>. Finally, I'll assume that you have already ensured that
+ the <ctcp message> that we are extracting from is shorter than 511 characters in all,
+ and have provided a buffer big enough to avoid this code segfaulting.
+ I'm assuming that msg_ptr points somewhere in the <ctcp message> and is null-terminated.[br]
+ (There are C++ style comments, you might want to remove them)
+ [example]
+ const char * decode_escape(const char * msg_ptr,char * buffer)
+ {
+ // This one decodes an escape sequence
+ // and returns the pointer "just after it"
+ // and should be called when *msg_ptr points
+ // just after a backslash
+ char c;
+ if((*msg_ptr >= '0') && (*msg_ptr < '8'))
+ {
+ // a digit follows the backslash
+ c = *msg_ptr - '0';
+ msg_ptr++;
+ if(*msg_ptr >= '0') && (*msg_ptr < '8'))
+ {
+ c = ((c << 3) + (*msg_ptr - '0'));
+ msg_ptr++;
+ if(*msg_ptr >= '0') && (*msg_ptr < '8'))
+ {
+ c = ((c << 3) + (*msg_ptr - '0'));
+ msg_ptr++;
+ } // else broken message, but let's be flexible
+ } // else it is broken, but let's be flexible
+ // append the character and return
+ *buffer = c;
+ return msg_ptr;
+ } else {
+ // simple escape: just append the following
+ // character (thus discarding its semantic)
+ *buffer = *msg_ptr;
+ return ++msg_ptr;
+ }
+ }
+
+ const char * extract_ctcp_parameter(const char * msg_ptr,char * buffer,int spaceBreaks)
+ {
+ // this one extracts the "next" ctcp parameter in msg_ptr
+ // it skips the leading and trailing spaces.
+ // spaceBreaks should be set to 0 if (and only if) the
+ // extracted parameter is the last in the CTCP message.
+ int inString = 0;
+ while(*msg_ptr == ' ')msg_ptr++;
+ while(*msg_ptr)
+ {
+ switch(*msg_ptr)
+ {
+ case '\\':
+ // backslash : escape sequence
+ msg_ptr++;
+ if(*msg_ptr)msg_ptr = decode_escape(msg_ptr,buffer);
+ else return msg_ptr; // senseless backslash
+ break;
+ case ' ':
+ // space : separate tokens?
+ if(inString || (!spaceBreaks))*buffer++ = *msg_ptr++;
+ else {
+ // not in string and space breaks: end of token
+ // skip trailing white space (this could be avoided)
+ // and return
+ while(*msg_ptr == ' ')msg_ptr++;
+ return msg_ptr;
+ }
+ break;
+ case '"':
+ // a string begin or end
+ inString = !inString;
+ msg_ptr++;
+ break;
+ default:
+ // any other char
+ *buffer++ = *msg_ptr++;
+ break;
+ }
+ }
+ return msg_ptr;
+ }
+ [/example][br]
+
+ [big]CTCP parameter semantics[/big][br]
+ The first <ctcp parameter> of a <ctcp message> is the <ctcp tag>: it defines
+ the semantic of the rest of the message.[br]
+ Altough it is a convention to specify the <ctcp tag> as uppercase letters,
+ and the original specification says that the whole <ctcp message> is
+ case sensitive, I'd prefer to follow the IRC message semantic (just to
+ have less "special cases") and treat the whole mssage as [b]case insensitive[/b].[br]
+ The remaining tokens depend on the <ctcp tag>. A description of known <ctcp tags>
+ and thus <ctcp messages> follows.[br]
+
+ [big]PING[/big][br]
+ [b]Syntax: <0x01>PING <data><0x01>[/b][br]
+ The PING request is used to check the round trip time from one client to another.
+ The receiving client should reply with exactly the same message but sent
+ through a NOTICE instead of a PRIVMSG. The <data> usually contains an unsigned
+ integer but not necessairly; it is not even mandatory for <data> to be a single token.
+ The receiver should ignore the semantic of <data>.[br]
+ The reply is intended to be processed by IRC clients.
+
+ [big]VERSION[/big][br]
+ [b]Syntax: <0x01>VERSION<0x01>[/b][br]
+ The VERSION request asks for informations about another user's IRC client program.
+ The reply should be sent thru a NOTICE with the following syntax:[br]
+ <0x01>VERSION <client_version_data><0x01>[br]
+ The preferred form for <client_version_data> is
+ "<client_name>:<client_version>:<client_enviroinement>", but historically
+ clients (and users) send a generic reply describing the client name, version
+ and eventually the used script name. This CTCP reply is intended to be human
+ readable, so any form is accepted.
+
+ [big]USERINFO[/big][br]
+ [b]Syntax: <0x01>USERINFO<0x01>[/b][br]
+ The USERINFO request asks for informations about another user.
+ The reply should be sent thru a NOTICE with the following syntax:[br]
+ <0x01>USERINFO <user_info_data><0x01>[br]
+ The <user_info_data> should be a human readable "user defined" string;
+
+ [big]CLIENTINFO[/big][br]
+ [b]Syntax: <0x01>CLIENTINFO<0x01>[/b][br]
+ The CLIENTINFO request asks for informations about another user's IRC client program.
+ While VERSION requests the client program name and version, CLIENTINFO requests
+ informations about CTCP capabilities.[br]
+ The reply should be sent thru a NOTICE with the following syntax:[br]
+ <0x01>CLIENTINFO <client_info_data><0x01>[br]
+ The <client_info_data> should contain a list of supported CTCP request tags.
+ The CLIENTINFO reply is intended to be human readable.
+
+ [big]FINGER[/big][br]
+ [b]Syntax: <0x01>FINGER<0x01>[/b][br]
+ The FINGER request asks for informations about another IRC user.
+ The reply should be sent thru a NOTICE with the following syntax:[br]
+ <0x01>FINGER <user_info_data><0x01>[br]
+ The <user_info_data> should be a human readable string containing
+ the system username and possibly the system idle time;
+
+ [big]SOURCE[/big][br]
+ [b]Syntax: <0x01>SOURCE<0x01>[/b][br]
+ The SOURCE request asks for the client homepage or ftp site informations.
+ The reply should be sent thru a NOTICE with the following syntax:[br]
+ <0x01>VERSION <homepage_url_data><0x01>[br]
+ This CTCP reply is intended to be human readable, so any form is accepted.
+
+ [big]TIME[/big][br]
+ [b]Syntax: <0x01>TIME<0x01>[/b][br]
+ The TIME request asks for the user local time.
+ The reply should be sent thru a NOTICE with the following syntax:[br]
+ <0x01>TIME <time and date string><0x01>[br]
+ This CTCP reply is intended to be human readable, so any form is accepted.
+
+ [big]ACTION[/big][br]
+ [b]Syntax: <0x01>ACTION<0x01>[/b][br]
+ The ACTION tag is used to describe an action.[br]
+ It should be sent through a NOTICE message and never generate a reply.[br]
+
+ [big]AVATAR (equivalent to ICON or FACE)[/big][br]
+ [b]Syntax: <0x01>AVATAR<0x01>[/b][br]
+ The AVATAR tag is used to query an user's avatar.[br]
+
+ [big]MULTIMEDIA (equivalent to MM or SOUND)[/big][br]
+ [b]Syntax: <0x01>MULTIMEDIA <filename><0x01>[/b][br]
+ The MULTIMEDIA tag is used to play a multimedia file on the receiver's side.[br]
+ The receiving client should locate the file associated to <filename>,
+ and play it. If the file can not be located
+ by the receiving client, and the MULTIMEDIA tag was sent through a PRIVMSG format CTCP,
+ the receiving client CAN request a [doc:dcc_connection]DCC GET[/doc] <filename> from the source user.
+ If the MULTIMEDIA tag was sent through a NOTICE message, the receiving client
+ should not generate any reply: the message should be notified to the receiving
+ client's user and then be discarded. The <filename> should never contain a leading
+ path. If any part of the <filename> appears to be a path component, it should be discarded.
+ The client may decide to drop the entire message too. Older clients (including
+ older releases of KVIrc) used to request the missing filenames by a particular
+ non-standard private message syntax. This convention should be dropped.[br]
+
+ [big]DCC[/big][br]
+ [b]Syntax: <0x01>DCC <type> <type dependant parameters><0x01>[/b][br]
+ The DCC tag is used to initiate a Direct Client Connection.
+ The known dcc types are:[br]
+ CHAT[br]
+ SEND[br]
+ TSEND[br]
+ GET[br]
+ TGET[br]
+ ACCEPT[br]
+ RESUME[br]
+
+*/
+
+
+
+void KviServerParser::encodeCtcpParameter(const char * param,KviStr &buffer,bool bSpaceBreaks)
+{
+ //
+ // This one encodes a single ctcp parameter with the simplest
+ // subset of rules and places it in the supplied buffer
+ //
+ if(!(*param))
+ {
+ // empty parameter: the only reason we REALLY need the double quotes
+ if(bSpaceBreaks)
+ buffer.append("\"\"");
+ return;
+ }
+
+ const char * begin = param;
+
+ bool bMustQuote = false;
+
+ while(*param)
+ {
+ switch(*param)
+ {
+ case ' ':
+ if(bSpaceBreaks)
+ {
+ if(param != begin)buffer.append(begin,param - begin);
+ buffer.append("\\040");
+ param++;
+ begin = param;
+ } else {
+ // space is non breaking (last parameter)
+ param++;
+ }
+ break;
+ case '\r':
+ if(param != begin)buffer.append(begin,param - begin);
+ buffer.append("\\015");
+ param++;
+ begin = param;
+ break;
+ case '\n':
+ if(param != begin)buffer.append(begin,param - begin);
+ buffer.append("\\012");
+ param++;
+ begin = param;
+ break;
+ case '"':
+ if(param != begin)buffer.append(begin,param - begin);
+ buffer.append("\\042");
+ param++;
+ begin = param;
+ break;
+ case '\\':
+ if(param != begin)buffer.append(begin,param - begin);
+ buffer.append("\\143");
+ param++;
+ begin = param;
+ break;
+ case 0x01:
+ if(param != begin)buffer.append(begin,param - begin);
+ buffer.append("\\001");
+ param++;
+ begin = param;
+ break;
+ default:
+ param++;
+ break;
+ }
+ }
+
+ if(param != begin)buffer.append(begin,param - begin);
+}
+
+void KviServerParser::encodeCtcpParameter(const char * parametr,QString &resultBuffer,bool bSpaceBreaks)
+{
+ //
+ // This one encodes a single ctcp parameter with the simplest
+ // subset of rules and places it in the supplied buffer
+ //
+ KviQCString buffer;
+ register const char* param=parametr;
+ if(!param)
+ {
+ if(bSpaceBreaks)
+ buffer.append("\"\"");
+ return;
+ }
+ if(!(*param))
+ {
+ // empty parameter: the only reason we REALLY need the double quotes
+ if(bSpaceBreaks)
+ buffer.append("\"\"");
+ return;
+ }
+
+ bool bMustQuote = false;
+
+ while(*param)
+ {
+ switch(*param)
+ {
+ case ' ':
+ if(bSpaceBreaks)
+ {
+ buffer.append("\\040");
+ param++;
+ } else {
+ buffer+=*param;
+ param++;
+ }
+ break;
+ case '\r':
+ buffer.append("\\015");
+ param++;
+ break;
+ case '\n':
+ buffer.append("\\012");
+ param++;
+ break;
+ case '"':
+ buffer.append("\\042");
+ param++;
+ break;
+ case '\\':
+ buffer.append("\\143");
+ param++;
+ break;
+ case 0x01:
+ buffer.append("\\001");
+ param++;
+ break;
+ default:
+ buffer+=*param;
+ param++;
+ break;
+ }
+ }
+ resultBuffer=buffer;
+}
+
+
+
+const char * KviServerParser::decodeCtcpEscape(const char * msg_ptr,KviStr &buffer)
+{
+ //
+ // This one decodes an octal sequence
+ // and returns the pointer "just after it".
+ // It should be called when *msg_ptr points
+ // just after a backslash.
+ // The decoded escape is appended to the buffer
+ //
+ // We're also assuming that *msg_ptr is not null here
+ //
+ char c;
+ if((*msg_ptr >= '0') && (*msg_ptr < '8'))
+ {
+ // a digit follows the backslash */
+ c = *msg_ptr - '0';
+ msg_ptr++;
+ if((*msg_ptr >= '0') && (*msg_ptr < '8'))
+ {
+ c = ((c << 3) + (*msg_ptr - '0'));
+ msg_ptr++;
+ if((*msg_ptr >= '0') && (*msg_ptr < '8'))
+ {
+ c = ((c << 3) + (*msg_ptr - '0'));
+ msg_ptr++;
+ } // else broken message, but let's be flexible
+ } // else it is broken, but let's be flexible
+ buffer.append(c);
+ return msg_ptr;
+ }
+
+ if(*msg_ptr == 'r')
+ {
+ buffer.append('\r');
+ return ++msg_ptr;
+ }
+
+ if(*msg_ptr == 'n')
+ {
+ buffer.append('\n');
+ return ++msg_ptr;
+ }
+
+ //
+ // null escape: just append the following
+ // character (thus discarding its semantics)
+ //
+
+ buffer.append(msg_ptr);
+ return ++msg_ptr;
+}
+
+
+const char * KviServerParser::decodeCtcpEscape(const char * msg_ptr,KviQCString &buffer)
+{
+ //
+ // This one decodes an octal sequence
+ // and returns the pointer "just after it".
+ // It should be called when *msg_ptr points
+ // just after a backslash.
+ // The decoded escape is appended to the buffer
+ //
+ // We're also assuming that *msg_ptr is not null here
+ //
+ char c;
+ if((*msg_ptr >= '0') && (*msg_ptr < '8'))
+ {
+ // a digit follows the backslash */
+ c = *msg_ptr - '0';
+ msg_ptr++;
+ if((*msg_ptr >= '0') && (*msg_ptr < '8'))
+ {
+ c = ((c << 3) + (*msg_ptr - '0'));
+ msg_ptr++;
+ if((*msg_ptr >= '0') && (*msg_ptr < '8'))
+ {
+ c = ((c << 3) + (*msg_ptr - '0'));
+ msg_ptr++;
+ } // else broken message, but let's be flexible
+ } // else it is broken, but let's be flexible
+ buffer+= (c ? c : ' ') ;
+ return msg_ptr;
+ }
+
+ if(*msg_ptr == 'r')
+ {
+ buffer+='\r';
+ return ++msg_ptr;
+ }
+ if(*msg_ptr == 'n')
+ {
+ buffer+='\n';
+ return ++msg_ptr;
+ }
+ //
+ // null escape: just append the following
+ // character (thus discarding its semantics)
+ //
+
+ buffer+=*msg_ptr;
+ return ++msg_ptr;
+}
+
+
+const char * KviServerParser::extractCtcpParameter(const char * msg_ptr,KviStr &buffer,bool bSpaceBreaks)
+{
+ //
+ // This one extracts the "next" ctcp parameter in msg_ptr
+ // and puts it in the supplied buffer.
+ // It is assumed that the leading and trailing CTCP
+ // tags have been already removed.
+ // Skips the leading and trailing spaces.
+ // bSpaceBreaks should be set to false if (and only if) the
+ // extracted parameter is the last in a positional parameter
+ // based CTCP message.
+ //
+
+ int bInString = 0;
+ if(!msg_ptr) return 0;
+ while(*msg_ptr == ' ')msg_ptr++; // skip leading spaces
+
+ if(*msg_ptr == '"')
+ {
+ // a quoted parameter
+ bInString = 1;
+ msg_ptr++;
+ }
+
+ const char * begin = msg_ptr;
+
+ while(*msg_ptr)
+ {
+ switch(*msg_ptr)
+ {
+ case '\\':
+ // backslash : escape sequence
+ if(msg_ptr != begin)buffer.append(begin,msg_ptr - begin);
+ msg_ptr++;
+ if(*msg_ptr)
+ {
+ // decode the escape
+ msg_ptr = decodeCtcpEscape(msg_ptr,buffer);
+ begin = msg_ptr;
+ }
+ // else it is a senseless trailing backslash.
+ // Just ignore and let the function
+ // return spontaneously.
+ break;
+ case ' ':
+ // space : separate tokens if not in string
+ if(bInString || (!bSpaceBreaks))msg_ptr++;
+ else {
+ // Not in string and space breaks: end of token
+ // skip trailing white space (this could be avoided)
+ // and return
+ if(msg_ptr != begin)buffer.append(begin,msg_ptr - begin);
+ while(*msg_ptr == ' ')msg_ptr++;
+ return msg_ptr;
+ }
+ break;
+ case '"':
+ if(bInString)
+ {
+ // A string terminator. We don't return
+ // immediately since if !bSpaceBreaks
+ // we must handle tokens until the end
+ // and otherwise we just run up to the
+ // next breaking space (but that's a bug anyway, heh).
+ if(msg_ptr != begin)buffer.append(begin,msg_ptr - begin);
+ bInString = 0;
+ msg_ptr++;
+ begin = msg_ptr;
+ } else {
+ // we don't begin a string here
+ // since we're in the middle of the token
+ // it is assumed to be simply a non encoded "
+ msg_ptr++;
+ }
+ break;
+ default:
+ // any other char
+ msg_ptr++;
+ break;
+ }
+ }
+ if(msg_ptr != begin)buffer.append(begin,msg_ptr - begin);
+ return msg_ptr;
+}
+
+const char * KviServerParser::extractCtcpParameter(const char * p_msg_ptr,QString &resultBuffer,bool bSpaceBreaks)
+{
+ //
+ // This one extracts the "next" ctcp parameter in p_msg_ptr
+ // and puts it in the supplied buffer.
+ // It is assumed that the leading and trailing CTCP
+ // tags have been already removed.
+ // Skips the leading and trailing spaces.
+ // bSpaceBreaks should be set to false if (and only if) the
+ // extracted parameter is the last in a positional parameter
+ // based CTCP message.
+ //
+
+ KviQCString buffer;
+ register const char* msg_ptr=p_msg_ptr;
+ int bInString = 0;
+ if(!msg_ptr) return 0;
+ while(*msg_ptr == ' ')msg_ptr++; // skip leading spaces
+
+ if(*msg_ptr == '"')
+ {
+ // a quoted parameter
+ bInString = 1;
+ msg_ptr++;
+ }
+
+ while(*msg_ptr)
+ {
+ switch(*msg_ptr)
+ {
+ case '\\':
+ // backslash : escape sequence
+ msg_ptr++;
+ if(*msg_ptr)
+ {
+ // decode the escape
+ msg_ptr = decodeCtcpEscape(msg_ptr,buffer);
+ }
+ // else it is a senseless trailing backslash.
+ // Just ignore and let the function
+ // return spontaneously.
+ break;
+ case ' ':
+ // space : separate tokens if not in string
+ if(bInString || (!bSpaceBreaks)) {
+ buffer+=*msg_ptr;
+ msg_ptr++;
+ }
+ else {
+ // Not in string and space breaks: end of token
+ // skip trailing white space (this could be avoided)
+ // and return
+ while(*msg_ptr == ' ')msg_ptr++;
+ resultBuffer=buffer;
+ return msg_ptr;
+ }
+ break;
+ case '"':
+ if(bInString)
+ {
+ // A string terminator. We don't return
+ // immediately since if !bSpaceBreaks
+ // we must handle tokens until the end
+ // and otherwise we just run up to the
+ // next breaking space (but that's a bug anyway, heh).
+ buffer+=*msg_ptr;
+ bInString = 0;
+ msg_ptr++;
+ } else {
+ // we don't begin a string here
+ // since we're in the middle of the token
+ // it is assumed to be simply a non encoded "
+ buffer+=*msg_ptr;
+ msg_ptr++;
+ }
+ break;
+ default:
+ // any other char
+ buffer+=*msg_ptr;
+ msg_ptr++;
+ break;
+ }
+ }
+ resultBuffer=buffer;
+ return msg_ptr;
+}
+
+
+
+
+
+void KviServerParser::parseCtcpRequest(KviCtcpMessage *msg)
+{
+ msg->pData = extractCtcpParameter(msg->pData,msg->szTag);
+
+ bool bDCCRequest = msg->szTag == "DCC" || msg->szTag == "XDCC" || msg->szTag == "TDCC";
+
+ bool bAction = (msg->szTag == "ACTION");
+
+ if (bDCCRequest)
+ {
+ if (KVI_OPTION_BOOL(KviOption_boolIgnoreCtcpDcc))
+ {
+ msg->msg->console()->output(KVI_OUT_IGNORE,__tr2qs("Ignoring DCC from \r!nc\r%s\r [%s@\r!h\r%s\r]"),
+ KviQString::toUtf8(msg->pSource->nick()).data(),
+ KviQString::toUtf8(msg->pSource->user()).data(),
+ KviQString::toUtf8(msg->pSource->host()).data()
+ );
+ return;
+ }
+ } else {
+ KviRegisteredUser * u = msg->msg->connection()->userDataBase()->registeredUser(msg->pSource->nick(),msg->pSource->user(),msg->pSource->host());
+ //Ignore it?
+ if(u)
+ {
+ if( (!bAction && u->isIgnoreEnabledFor(KviRegisteredUser::Ctcp)) ||
+ (bAction && u->isIgnoreEnabledFor(IS_ME(msg->msg,msg->szTarget) ? KviRegisteredUser::Query : KviRegisteredUser::Channel)) )
+ {
+ if (KVI_OPTION_BOOL(KviOption_boolVerboseIgnore))
+ {
+ msg->msg->console()->output(KVI_OUT_IGNORE,__tr2qs("Ignoring CTCP from \r!nc\r%s\r [%s@\r!h\r%s\r]"),
+ KviQString::toUtf8(msg->pSource->nick()).data(),
+ KviQString::toUtf8(msg->pSource->user()).data(),
+ KviQString::toUtf8(msg->pSource->host()).data()
+ );
+ }
+ return;
+ }
+ }
+ }
+
+ bool bCtcpVersion = KviQString::equalCI(msg->szTag,"VERSION");
+
+ for(int i=0;m_ctcpRequestParseProcTable[i].msgName;i++)
+ {
+ if(KviQString::equalCI(msg->szTag,m_ctcpRequestParseProcTable[i].msgName))
+ {
+ if(!(m_ctcpReplyParseProcTable[i].iFlags & KVI_CTCP_MESSAGE_PARSE_TRIGGERNOEVENT))
+ {
+ QString szData = msg->msg->connection()->decodeText(msg->pData);
+ //do not allow to make faked version reply
+ if(!(bCtcpVersion && KVI_OPTION_BOOL(KviOption_boolIgnoreCtcpVersion)))
+ {
+ if(KVS_TRIGGER_EVENT_6_HALTED(KviEvent_OnCtcpRequest, \
+ msg->msg->console(), \
+ msg->pSource->nick(), \
+ msg->pSource->user(), \
+ msg->pSource->host(), \
+ msg->szTarget, \
+ msg->szTag, \
+ szData) && !bCtcpVersion)return;
+ }
+ }
+ (this->*(m_ctcpRequestParseProcTable[i].proc))(msg);
+ return;
+ }
+ }
+
+ QString szData = msg->msg->connection()->decodeText(msg->pData);
+ // trigger the event on unrecognized requests too
+ if(KVS_TRIGGER_EVENT_6_HALTED(KviEvent_OnCtcpRequest, \
+ msg->msg->console(), \
+ msg->pSource->nick(), \
+ msg->pSource->user(), \
+ msg->pSource->host(), \
+ msg->szTarget, \
+ msg->szTag,
+ szData))
+ return;
+
+ // unknown
+ msg->bUnknown = true;
+ echoCtcpRequest(msg);
+}
+
+void KviServerParser::parseCtcpReply(KviCtcpMessage *msg)
+{
+ msg->pData = extractCtcpParameter(msg->pData,msg->szTag);
+
+ for(int i=0;m_ctcpReplyParseProcTable[i].msgName;i++)
+ {
+ if(KviQString::equalCI(msg->szTag,m_ctcpReplyParseProcTable[i].msgName))
+ {
+ if(!(m_ctcpReplyParseProcTable[i].iFlags & KVI_CTCP_MESSAGE_PARSE_TRIGGERNOEVENT))
+ {
+ QString szData = msg->msg->connection()->decodeText(msg->pData);
+ if(KVS_TRIGGER_EVENT_6_HALTED(KviEvent_OnCtcpReply, \
+ msg->msg->console(),msg->pSource->nick(),msg->pSource->user(), \
+ msg->pSource->host(),msg->szTarget,msg->szTag,szData))return;
+ }
+ (this->*(m_ctcpReplyParseProcTable[i].proc))(msg);
+ return;
+ }
+ }
+
+ QString szData = msg->msg->connection()->decodeText(msg->pData);
+ // trigger the event on unrecognized replies too
+ if(KVS_TRIGGER_EVENT_6_HALTED(KviEvent_OnCtcpReply, \
+ msg->msg->console(),msg->pSource->nick(),msg->pSource->user(), \
+ msg->pSource->host(),msg->szTarget,msg->szTag,szData))return;
+
+ // unknown
+ msg->bUnknown = true;
+ echoCtcpReply(msg);
+}
+
+
+// Ctcp message handlers
+
+bool KviServerParser::checkCtcpFlood(KviCtcpMessage *msg)
+{
+ if(!KVI_OPTION_BOOL(KviOption_boolUseCtcpFloodProtection))return false;
+
+ kvi_time_t tNow = kvi_unixTime();
+
+ KviIrcConnectionAntiCtcpFloodData * d = msg->msg->connection()->antiCtcpFloodData();
+
+ unsigned int interval = (unsigned int)(((unsigned int)tNow) - ((unsigned int)d->lastCtcpTime()));
+
+ if(interval < KVI_OPTION_UINT(KviOption_uintCtcpFloodCheckInterval))
+ {
+ d->increaseCtcpCount();
+ if(d->ctcpCount() > KVI_OPTION_UINT(KviOption_uintMaxCtcpRequests))
+ {
+ // This is flood
+ msg->bIsFlood = true;
+ return true;
+ }
+ } else {
+ d->setLastCtcpTime(tNow);
+ d->setCtcpCount(1);
+ }
+ return false;
+}
+
+
+void KviServerParser::replyCtcp(KviCtcpMessage *msg,const char * data)
+{
+ KviQCString szNick = msg->msg->connection()->encodeText(msg->pSource->nick());
+ msg->msg->connection()->sendFmtData("NOTICE %s :%c%s %s%c",
+ szNick.data(),0x01,msg->msg->connection()->encodeText(msg->szTag).data(),msg->msg->connection()->encodeText(data).data(),0x01);
+}
+
+void KviServerParser::echoCtcpReply(KviCtcpMessage * msg)
+{
+ if(!msg->msg->haltOutput())
+ {
+ KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolCtcpRepliesToActiveWindow) ? msg->msg->console()->activeWindow() : msg->msg->console();
+
+ bool bIsChannel = false;
+
+ if(!IS_ME(msg->msg,msg->szTarget))
+ {
+ // Channel ctcp request!
+ pOut = msg->msg->connection()->findChannel(msg->szTarget);
+ if(!pOut)
+ {
+ pOut = msg->msg->console();
+ pOut->output(KVI_OUT_SYSTEMWARNING,
+ __tr2qs("The following CTCP reply has unrecognized target %Q"),&(msg->szTarget));
+ } else bIsChannel = true;
+ }
+
+ QString szData = msg->msg->connection()->decodeText(msg->pData);
+
+ QString szWhat = bIsChannel ? __tr2qs("Channel CTCP") : QString("CTCP");
+
+ pOut->output(
+ msg->bUnknown ? KVI_OUT_CTCPREPLYUNKNOWN : KVI_OUT_CTCPREPLY,
+ __tr2qs("%Q %Q reply from \r!n\r%Q\r [%Q@\r!h\r%Q\r]: %Q"),
+ &szWhat,&(msg->szTag),&(msg->pSource->nick()),&(msg->pSource->user()),
+ &(msg->pSource->host()),&szData);
+ }
+}
+
+
+void KviServerParser::echoCtcpRequest(KviCtcpMessage *msg)
+{
+ // FIXME: #warning "DEDICATED CTCP WINDOW...MINIMIZED ?"
+ if(!msg->msg->haltOutput())
+ {
+ QString req = msg->szTag;
+ if(*(msg->pData)) {
+ req.append(" ");
+ req.append(msg->pData);
+ }
+
+ KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolCtcpRequestsToActiveWindow) ? msg->msg->console()->activeWindow() : msg->msg->console();
+
+ bool bIsChannel = false;
+
+ if(!IS_ME(msg->msg,msg->szTarget))
+ {
+ // Channel ctcp request!
+ pOut = msg->msg->connection()->findChannel(msg->szTarget);
+ if(!pOut)
+ {
+ pOut = msg->msg->console();
+ pOut->output(KVI_OUT_SYSTEMWARNING,
+ __tr2qs("The following CTCP request has unrecognized target %Q"),
+ &(msg->szTarget));
+ } else bIsChannel = true;
+ }
+
+ QString szRequest = pOut->decodeText(req);
+ QString szTag = pOut->decodeText(msg->szTag);
+ QString szWhat = bIsChannel ? __tr2qs("Channel CTCP") : QString("CTCP");
+
+ if(msg->bIsFlood)
+ {
+ QString szData = msg->msg->connection()->decodeText(msg->pData);
+ if(!KVS_TRIGGER_EVENT_6_HALTED(KviEvent_OnCtcpFlood,pOut,msg->pSource->nick(),msg->pSource->username(),msg->pSource->host(),msg->szTarget,msg->szTag,szData))
+ pOut->output(KVI_OUT_CTCPREQUESTFLOOD,
+ __tr2qs("%Q %Q%c request from \r!n\r%Q\r [%Q@\r!h\r%Q\r] (%Q), ignored (flood limit exceeded)"),
+ &szWhat,&szTag,KVI_TEXT_RESET,&(msg->pSource->nick()),
+ &(msg->pSource->user()),&(msg->pSource->host()),&szRequest);
+ } else {
+ QString szAction = msg->bUnknown ? __tr2qs("ignored (unrecognized)") :
+ (msg->bIgnored ? __tr2qs("ignored") : __tr2qs("replied"));
+ pOut->output(
+ msg->bUnknown ? KVI_OUT_CTCPREQUESTUNKNOWN :
+ (msg->bIgnored ? KVI_OUT_CTCPREQUESTIGNORED : KVI_OUT_CTCPREQUESTREPLIED),
+ __tr2qs("%Q %Q%c request from \r!n\r%Q\r [%Q@\r!h\r%Q\r] (%Q), %Q"),
+ &szWhat,&szTag,KVI_TEXT_RESET,&(msg->pSource->nick()),
+ &(msg->pSource->user()),&(msg->pSource->host()),&szRequest,&szAction);
+ }
+ }
+}
+
+
+
+void KviServerParser::parseCtcpRequestPing(KviCtcpMessage *msg)
+{
+ if(!checkCtcpFlood(msg))
+ {
+ if(!KVI_OPTION_BOOL(KviOption_boolIgnoreCtcpPing))
+ {
+ replyCtcp(msg,msg->pData);
+ } else msg->bIgnored = true;
+ }
+
+ echoCtcpRequest(msg);
+}
+
+void KviServerParser::parseCtcpReplyPing(KviCtcpMessage * msg)
+{
+ if(!msg->msg->haltOutput())
+ {
+ KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolCtcpRepliesToActiveWindow) ? msg->msg->console()->activeWindow() : msg->msg->console();
+
+ bool bIsChannel = false;
+
+ if(!IS_ME(msg->msg,msg->szTarget))
+ {
+ // Channel ctcp request!
+ pOut = msg->msg->connection()->findChannel(msg->szTarget);
+ if(!pOut)
+ {
+ pOut = msg->msg->console();
+ pOut->output(KVI_OUT_SYSTEMWARNING,
+ __tr2qs("The following CTCP PING reply has unrecognized target \"%Q\""),
+ &(msg->szTarget));
+ } else bIsChannel = true;
+ }
+
+ unsigned int uSecs;
+ unsigned int uMSecs = 0;
+
+ KviStr szTime;
+
+ struct timeval tv;
+ kvi_gettimeofday(&tv,0);
+
+ msg->pData = extractCtcpParameter(msg->pData,szTime,true);
+
+ bool bOk;
+
+ if(szTime.contains('.'))
+ {
+ KviStr szUSecs = szTime;
+ szUSecs.cutToFirst('.');
+ szTime.cutFromFirst('.');
+
+ uMSecs = szUSecs.toUInt(&bOk);
+ if(!bOk)
+ {
+ uMSecs = 0;
+ tv.tv_usec = 0;
+ }
+ } else tv.tv_usec = 0;
+
+
+ uSecs = szTime.toUInt(&bOk);
+ if(!bOk)pOut->output(KVI_OUT_SYSTEMWARNING,
+ __tr2qs("The following CTCP PING reply has a broken time identifier \"%S\", don't trust the displayed time"),&szTime);
+
+ unsigned int uDiffSecs = tv.tv_sec - uSecs;
+
+ //unsigned int uDiffMSecs = ((((unsigned int)tv.tv_usec) - uMSecs) / 1000) % 1000;
+ //if ((uMSecs / 1000000) <= uDiffSecs) uDiffSecs -= (uMSecs / 1000000)
+
+ while(uMSecs > 1000000)uMSecs /= 10; // precision too high?
+ if(((unsigned int)tv.tv_usec) < uMSecs)
+ {
+ tv.tv_usec += 1000000;
+ if(uDiffSecs > 0)uDiffSecs --;
+ }
+ unsigned int uDiffMSecs = (tv.tv_usec - uMSecs) / 1000;
+
+ QString szWhat = bIsChannel ? __tr2qs("Channel CTCP") : QString("CTCP");
+
+ pOut->output(
+ msg->bUnknown ? KVI_OUT_CTCPREPLYUNKNOWN : KVI_OUT_CTCPREPLY,
+ __tr2qs("%Q PING reply from \r!n\r%Q\r [%Q@\r!h\r%Q\r]: %u sec %u msec"),
+ &szWhat,&(msg->pSource->nick()),
+ &(msg->pSource->user()),&(msg->pSource->host()),uDiffSecs,uDiffMSecs);
+ }
+}
+
+
+void KviServerParser::parseCtcpRequestVersion(KviCtcpMessage *msg)
+{
+ if(!checkCtcpFlood(msg))
+ {
+ if(!KVI_OPTION_BOOL(KviOption_boolIgnoreCtcpVersion))
+ {
+ QString szVersion;
+#ifdef COMPILE_USE_QT4
+ #define QT4_TAG " (QT4) "
+#else
+ #define QT4_TAG
+#endif
+
+#ifdef COMPILE_ON_WINDOWS
+ szVersion = "KVIrc " KVI_VERSION QT4_TAG " '" KVI_RELEASE_NAME "' " KVI_SOURCES_DATE " - build " KVI_BUILD_DATE;
+ szVersion.append(QString(" - %1").arg(KviOsInfo::version()));
+#else
+ szVersion = "KVIrc " KVI_VERSION QT4_TAG " '" KVI_RELEASE_NAME "' " KVI_SOURCES_DATE " - build " KVI_BUILD_DATE " - " KVI_BUILD_FLAGS;
+ szVersion.append(QString(" - %1 (%2)").arg(KviOsInfo::name()).arg(KviOsInfo::release()));
+#endif
+ //szVersion.append(QString(" - QT Version: %1 - %2").arg(qVersion()).arg(__tr2qs("http://www.kvirc.net/")));
+ if(!KVI_OPTION_STRING(KviOption_stringCtcpVersionPostfix).isEmpty())
+ {
+ QString sz = KVI_OPTION_STRING(KviOption_stringCtcpVersionPostfix);
+ if(!sz.isEmpty())
+ {
+ szVersion.append(" :");
+ szVersion.append(sz);
+ }
+ }
+ replyCtcp(msg,szVersion.utf8().data());
+ } else msg->bIgnored = true;
+ }
+
+ echoCtcpRequest(msg);
+}
+
+void KviServerParser::parseCtcpRequestUserinfo(KviCtcpMessage *msg)
+{
+ if(!checkCtcpFlood(msg))
+ {
+ if(!KVI_OPTION_BOOL(KviOption_boolIgnoreCtcpUserinfo))
+ {
+ QString szReply;
+ if(!KVI_OPTION_STRING(KviOption_stringCtcpUserInfoAge).isEmpty())
+ {
+ szReply = "Age=";
+ szReply += KVI_OPTION_STRING(KviOption_stringCtcpUserInfoAge);
+ }
+ if(!KVI_OPTION_STRING(KviOption_stringCtcpUserInfoGender).isEmpty())
+ {
+ if(!szReply.isEmpty())szReply += "; ";
+ szReply += "Gender=";
+ szReply += KVI_OPTION_STRING(KviOption_stringCtcpUserInfoGender);
+ }
+ if(!KVI_OPTION_STRING(KviOption_stringCtcpUserInfoLocation).isEmpty())
+ {
+ if(!szReply.isEmpty())szReply += "; ";
+ szReply += "Location=";
+ szReply += KVI_OPTION_STRING(KviOption_stringCtcpUserInfoLocation);
+ }
+ if(!KVI_OPTION_STRING(KviOption_stringCtcpUserInfoLanguages).isEmpty())
+ {
+ if(!szReply.isEmpty())szReply += "; ";
+ szReply += "Languages=";
+ szReply += KVI_OPTION_STRING(KviOption_stringCtcpUserInfoLanguages);
+ }
+ if(!KVI_OPTION_STRING(KviOption_stringCtcpUserInfoOther).isEmpty())
+ {
+ if(!szReply.isEmpty())szReply += "; ";
+ szReply += KVI_OPTION_STRING(KviOption_stringCtcpUserInfoOther);
+ }
+ if(szReply.isEmpty())szReply = KVI_DEFAULT_CTCP_USERINFO_REPLY;
+ replyCtcp(msg,szReply.utf8().data());
+ } else msg->bIgnored = true;
+ }
+
+ echoCtcpRequest(msg);
+}
+
+// FIXME: CTCP SEX , AGE , LOCATION!!! <--- so we will be safe :)
+// FIXME: KEEP THIS TABLE UP TO DATE
+
+static const char * ctcpTagTable[][2]=
+{
+ { "PING" , "Returns given parameters without parsing them" },
+ { "VERSION" , "Returns the version of this client" },
+ { "CLIENTINFO" , "With no parameters, lists supported CTCP tags," \
+ " 'CLIENTINFO <tag>' describes <tag>" },
+ { "USERINFO" , "Returns personal information about the current user" },
+ { "FINGER" , "Returns information about the current user" },
+ { "SOURCE" , "Returns the client homepage URL" },
+ { "TIME" , "Returns the current local time" },
+ { "ACTION" , "Used to describe actions, generates no reply" },
+ { "AVATAR" , "Returns the current avatar (may trigger a DCC GET) or" \
+ " sets your own on this side if sent through a NOTICE" },
+ { "DCC" , "Initiates a DCC connection (XDCC,TDCC)" },
+ { "PAGE" , "Leaves a message for this user" },
+ { 0 , 0 }
+};
+
+void KviServerParser::parseCtcpRequestClientinfo(KviCtcpMessage *msg)
+{
+ // this is completely latin1
+ if(!checkCtcpFlood(msg))
+ {
+ if(!KVI_OPTION_BOOL(KviOption_boolIgnoreCtcpClientinfo))
+ {
+ KviStr szTag;
+ msg->pData = extractCtcpParameter(msg->pData,szTag,false);
+ szTag.stripWhiteSpace();
+ szTag.toUpper();
+ if(szTag.isEmpty())
+ {
+ KviStr reply("KVIrc " KVI_VERSION " '" KVI_RELEASE_NAME "' " KVI_SOURCES_DATE " - http://www.kvirc.net - Supported tags: ");
+ for(int i=0;ctcpTagTable[i][0];i++)
+ {
+ reply.append(ctcpTagTable[i][0]);
+ if(ctcpTagTable[i + 1][0])reply.append(',');
+ }
+ reply.append(" - Use 'CLIENTINFO <tag>' for a description of each tag");
+ replyCtcp(msg,reply.ptr());
+ } else {
+ bool bFound = false;
+ for(int i=0;ctcpTagTable[i][0] && !bFound;i++)
+ {
+ if(kvi_strEqualCS(ctcpTagTable[i][0],szTag.ptr()))
+ {
+ KviStr reply(KviStr::Format,"%s: %s",ctcpTagTable[i][0],ctcpTagTable[i][1]);
+ replyCtcp(msg,reply.ptr());
+ bFound = true;
+ }
+ }
+ if(!bFound)
+ {
+ msg->szTag= "ERRMSG";
+ KviStr reply(KviStr::Format,"Unsupported tag %s",szTag.ptr());
+ replyCtcp(msg,reply.ptr());
+ }
+ }
+ } else msg->bIgnored = true;
+ }
+
+ echoCtcpRequest(msg);
+}
+
+void KviServerParser::parseCtcpRequestFinger(KviCtcpMessage *msg)
+{
+ // completely latin1 atm
+ if(!checkCtcpFlood(msg))
+ {
+ if(!KVI_OPTION_BOOL(KviOption_boolIgnoreCtcpFinger))
+ {
+ KviStr username = getenv("USER");
+ if(username.isEmpty())username = getenv("LOGNAME");
+ if(username.isEmpty())username = msg->msg->connection()->userInfo()->userName();
+ // FIXME: #warning "UTSNAME ?...AND OTHER INFO ?...SYSTEM IDLE TIME ?...KVIRC IDLE TIME ?"
+ KviStr reply(KviStr::Format,"%s",username.ptr());
+ replyCtcp(msg,reply.ptr());
+ } else msg->bIgnored = true;
+ }
+
+ echoCtcpRequest(msg);
+}
+
+void KviServerParser::parseCtcpRequestSource(KviCtcpMessage *msg)
+{
+ if(!checkCtcpFlood(msg))
+ {
+ if(!KVI_OPTION_BOOL(KviOption_boolIgnoreCtcpSource))
+ {
+ QString version = "KVIrc " KVI_VERSION " '" KVI_RELEASE_NAME "' - http://www.kvirc.net/";
+ if(!KVI_OPTION_STRING(KviOption_stringCtcpSourcePostfix).isEmpty())
+ {
+ version+=" :";
+ version+= KVI_OPTION_STRING(KviOption_stringCtcpSourcePostfix);
+ }
+ replyCtcp(msg,version.utf8().data());
+ } else msg->bIgnored = true;
+ }
+
+ echoCtcpRequest(msg);
+}
+
+void KviServerParser::parseCtcpRequestTime(KviCtcpMessage *msg)
+{
+ if(!checkCtcpFlood(msg))
+ {
+ if(!KVI_OPTION_BOOL(KviOption_boolIgnoreCtcpTime))
+ {
+ replyCtcp(msg,QDateTime::currentDateTime().toString());
+ } else msg->bIgnored = true;
+ }
+
+ echoCtcpRequest(msg);
+}
+
+void KviServerParser::parseCtcpRequestPage(KviCtcpMessage *msg)
+{
+ if(!checkCtcpFlood(msg))
+ {
+ if(!KVI_OPTION_BOOL(KviOption_boolIgnoreCtcpPage))
+ {
+ KVI_OPTION_STRING(KviOption_stringCtcpPageReply).stripWhiteSpace();
+ if(KVI_OPTION_STRING(KviOption_stringCtcpPageReply).isEmpty())
+ {
+ KVI_OPTION_STRING(KviOption_stringCtcpPageReply) = KVI_DEFAULT_CTCP_PAGE_REPLY;
+ }
+ replyCtcp(msg,KVI_OPTION_STRING(KviOption_stringCtcpPageReply));
+ if(KVI_OPTION_BOOL(KviOption_boolShowDialogOnCtcpPage))
+ {
+ if(!g_pCtcpPageDialog)g_pCtcpPageDialog = new KviCtcpPageDialog();
+ KviStr szData8;
+ szData8 = msg->pData;
+ QString szData;
+ szData = msg->msg->connection()->decodeText(szData8.ptr());
+ g_pCtcpPageDialog->addPage(msg->pSource->nick(),msg->pSource->user(),msg->pSource->host(),szData);
+ g_pCtcpPageDialog->popup();
+ }
+ } else msg->bIgnored = true;
+ }
+
+ echoCtcpRequest(msg);
+}
+
+void KviServerParser::parseCtcpRequestAction(KviCtcpMessage *msg)
+{
+ KviStr szData8;
+ // CTCP ACTION is a special exception... most clients do not encode/decode it.
+ //msg->pData = extractCtcpParameter(msg->pData,szData8,false);
+ szData8 = msg->pData;
+
+ KviWindow * pOut = 0;
+ bool bIsChannel = !IS_ME(msg->msg,msg->szTarget);
+
+ QString szData;
+
+ if(bIsChannel)
+ {
+ pOut = (KviWindow *)msg->msg->connection()->findChannel(msg->szTarget);
+ if(pOut)szData = pOut->decodeText(szData8.ptr());
+ else szData = msg->msg->connection()->decodeText(szData8.ptr());
+ } else {
+ KviQuery * query = msg->msg->connection()->findQuery(msg->pSource->nick());
+ if(!query)
+ {
+ szData = msg->msg->connection()->decodeText(szData8.ptr());
+ // New query requested ?
+ // FIXME: #warning "CHECK FOR SPAM!"
+ if(KVI_OPTION_BOOL(KviOption_boolCreateQueryOnPrivmsg))
+ {
+ // We still want to create it
+ // Give the scripter a chance to filter it out again
+ if(KVS_TRIGGER_EVENT_4_HALTED(KviEvent_OnQueryWindowRequest,msg->msg->console(),
+ msg->pSource->nick(),
+ msg->pSource->username(),
+ msg->pSource->host(),
+ szData))
+ {
+ // check if the scripter hasn't created it
+ query = msg->msg->connection()->findQuery(msg->pSource->nick());
+ } else {
+ // no query yet, create it!
+ // this will trigger OnQueryWindowCreated
+ query = msg->msg->console()->connection()->createQuery(msg->pSource->nick());
+ query->setTarget(msg->pSource->nick(),msg->pSource->username(),msg->pSource->host());
+ }
+ }
+ }
+ pOut = (KviWindow *)query;
+ if(pOut)szData = pOut->decodeText(szData8.ptr());
+ else szData = msg->msg->connection()->decodeText(szData8.ptr());
+ }
+
+ bool bTargetFound = pOut;
+ if(!pOut)
+ {
+ pOut = KVI_OPTION_BOOL(KviOption_boolExternalMessagesToActiveWindow) ? msg->msg->console()->activeWindow() : msg->msg->console();
+ }
+
+ if(KVS_TRIGGER_EVENT_5_HALTED(KviEvent_OnAction,pOut,
+ msg->pSource->nick(),
+ msg->pSource->username(),
+ msg->pSource->host(),
+ msg->szTarget,
+ szData
+ ))
+ {
+ msg->msg->setHaltOutput();
+ return;
+ }
+
+ int type = msg->msg->console()->applyHighlighting(pOut,KVI_OUT_ACTION,msg->pSource->nick(),msg->pSource->user(),msg->pSource->host(),szData);
+
+ if(type < 0)return; // event stopped the message!
+ if(type == KVI_OUT_HIGHLIGHT)
+ {
+ if(!pOut->hasAttention())
+ {
+ if(KVI_OPTION_BOOL(KviOption_boolFlashWindowOnHighlightedMessages))
+ pOut->demandAttention();
+ if(KVI_OPTION_BOOL(KviOption_boolPopupNotifierOnHighlightedMessages))
+ {
+ QString szMsg = "<b>";
+ szMsg += msg->pSource->nick();
+ szMsg += "</b> ";
+ #ifdef COMPILE_USE_QT4
+ szMsg += Qt::escape(szData);
+ #else
+ szMsg += QStyleSheet::escape(szData);
+ #endif
+ //debug("kvi_sp_ctcp.cpp:975 debug: %s",szMsg.data());
+ g_pApp->notifierMessage(pOut,KVI_OPTION_MSGTYPE(KVI_OUT_ACTION).pixId(),szMsg,90);
+ }
+ }
+ }
+
+ if(bTargetFound)
+ {
+ QString szMsg = QString("\r!n\r%1\r ").arg(msg->pSource->nick());
+ szMsg += szData;
+ if(bIsChannel)
+ {
+ ((KviChannel *)pOut)->outputMessage(type,szMsg);
+ } else {
+ pOut->outputNoFmt(type,szMsg);
+ }
+ } else {
+ if(bIsChannel)
+ {
+ pOut->output(KVI_OUT_SYSTEMWARNING,
+ __tr2qs("The following CTCP ACTION has unrecognized target %Q"),
+ &(msg->szTarget));
+ }
+ KviStr buffer1,buffer2;
+ pOut->output(type,
+ __tr2qs("CTCP ACTION from \r!n\r%Q\r [%Q@\r!h\r%Q\r]: %Q"),
+ &(msg->pSource->nick()),&(msg->pSource->user()),
+ &(msg->pSource->host()),&szData);
+ }
+}
+
+// FIXME: #warning "UTSNAME ?...AND OTHER INFO ?...SYSTEM IDLE TIME ?...KVIRC IDLE TIME ?"
+
+void KviServerParser::parseCtcpRequestAvatar(KviCtcpMessage *msg)
+{
+ // AVATAR
+ if(!KVI_OPTION_BOOL(KviOption_boolIgnoreCtcpAvatar))
+ {
+ QString szGenderTag=" ";
+ if(KVI_OPTION_STRING(KviOption_stringCtcpUserInfoGender).startsWith("m",false)){
+ szGenderTag.append("M");
+ } else if(KVI_OPTION_STRING(KviOption_stringCtcpUserInfoGender).startsWith("f",false)){
+ szGenderTag.append("F");
+ } else {
+ szGenderTag.append("?");
+ }
+
+ KviAvatar * a = msg->msg->console()->currentAvatar();
+ if(a)
+ {
+ if(!checkCtcpFlood(msg))
+ {
+ // FIXME: #warning "OPTION FOR SETTING A FIXED BIND ADDRESS FOR OUTGOING DCC OFFERS"
+ QString szUserMask;
+ msg->pSource->mask(szUserMask);
+
+ QString szReply,szFileName;
+ szFileName=a->name();
+ if(KVI_OPTION_BOOL(KviOption_boolDCCFileTransferReplaceOutgoingSpacesWithUnderscores))
+ szFileName.replace(" ","_");
+
+ // escape the spaces with the right octal code
+ encodeCtcpParameter(szFileName,szReply);
+
+
+ if(!a->isRemote())
+ {
+ KviSharedFile * o;
+ if(!(o = g_pSharedFilesManager->addSharedFile(szFileName,a->localPath(),szUserMask,KVI_OPTION_UINT(KviOption_uintAvatarOfferTimeoutInSecs))))
+ {
+ // Don't delete o...it has been already deleted by g_pSharedFilesManager
+ msg->msg->console()->output(KVI_OUT_SYSTEMWARNING,__tr2qs("Unable to add file offer for file %Q (File not readable?)"),&(a->localPath()));
+ } else {
+ if(_OUTPUT_VERBOSE)
+ {
+ msg->msg->console()->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Added %d sec file offer for file %Q (%Q) to recipient %Q"),
+ KVI_OPTION_UINT(KviOption_uintAvatarOfferTimeoutInSecs),&(a->name()),&(a->localPath()),&szUserMask);
+ }
+ }
+ //if(o)szReply.append(QString(" %1").arg(o->fileSize()));
+ }
+
+ szReply.append(szGenderTag);
+ replyCtcp(msg,szReply.utf8().data());
+ }
+ } else {
+ // no avatar set.. ignore channel requests if the user wishes
+ if(!IS_ME(msg->msg,msg->szTarget))
+ {
+ // channel target
+ if(KVI_OPTION_BOOL(KviOption_boolIgnoreChannelAvatarRequestsWhenNoAvatarSet))msg->bIgnored = true;
+ }
+ if(!msg->bIgnored)replyCtcp(msg,"");
+ }
+ } else msg->bIgnored = true;
+
+ echoCtcpRequest(msg);
+}
+
+
+void KviServerParser::parseCtcpReplyAvatar(KviCtcpMessage *msg)
+{
+ QString szRemoteFile;
+ QString szGender;
+ QString decoded=msg->msg->console()->decodeText(msg->pData);
+
+ decoded = extractCtcpParameter(decoded.utf8().data(),szRemoteFile,true);
+ decoded = extractCtcpParameter(decoded.utf8().data(),szGender,true);
+ szRemoteFile.stripWhiteSpace();
+
+ bool bPrivate = IS_ME(msg->msg,msg->szTarget);
+
+ QString textLine;
+ KviAvatar * avatar = 0;
+
+ bool bResetAvatar = true;
+
+ QString nickLink;
+
+ KviQString::sprintf(nickLink,"\r!n\r%Q\r",&(msg->pSource->nick()));
+
+ KviIrcUserEntry * e = msg->msg->connection()->userDataBase()->find(msg->pSource->nick());
+ if(e){
+ if( (szGender=="m") || (szGender=="M") ) {
+ e->setGender(KviIrcUserEntry::Male);
+ } else if((szGender=="f") || (szGender=="F") ) {
+ e->setGender(KviIrcUserEntry::Female);
+ } else {
+ e->setGender(KviIrcUserEntry::Unknown);
+ }
+ }
+
+ QString szWhere = bPrivate ? __tr2qs("private") : __tr2qs("channel notification:");
+ QString szWhat = bPrivate ? __tr2qs("notification") : msg->szTarget;
+
+ if(szRemoteFile.isEmpty())
+ {
+ // avatar unset
+ KviQString::sprintf(textLine,__tr2qs("%Q unsets avatar"),
+ &nickLink);
+ if(_OUTPUT_VERBOSE)
+ KviQString::appendFormatted(textLine," (%Q %Q)",&szWhere,&szWhat);
+ } else {
+
+ // FIXME: #warning "The avatar should be the one with the requested size!!"
+ KviQString::sprintf(textLine,__tr2qs("%Q changes avatar to %s"),
+ &nickLink,szRemoteFile.utf8().data(),&szWhere,&szWhat);
+ if(_OUTPUT_VERBOSE)
+ KviQString::appendFormatted(textLine," (%Q %Q)",&szWhere,&szWhat);
+
+ bool bIsUrl = KviQString::equalCIN("http://",szRemoteFile,7) && (szRemoteFile.length() > 7);
+ if(!bIsUrl)
+ {
+ // no hacks
+ KviQString::cutToLast(szRemoteFile,'/');
+ KviQString::cutToLast(szRemoteFile,'\\');
+ }
+
+ avatar = g_pIconManager->getAvatar(QString::null,szRemoteFile);
+
+ if((avatar == 0) && e)
+ {
+ // we have no such file on our HD....
+ bResetAvatar = false;
+ // request DCC GET ?
+ if(KVI_OPTION_BOOL(KviOption_boolRequestMissingAvatars))
+ {
+ // FIXME: #warning "Request avatars only from registered users ?"
+ // FIXME: #warning "Ask before making the request ?"
+ if(bIsUrl)
+ {
+ KviStr szLocalFilePath;
+ KviStr szLocalFile = szRemoteFile;
+ g_pIconManager->urlToCachedFileName(szLocalFile);
+ g_pApp->getLocalKvircDirectory(szLocalFilePath,KviApp::Avatars,szLocalFile.ptr());
+ szLocalFilePath.replaceAll('\\',"\\\\"); // <-- this is especially for windows
+ QString szCommand = "http.get -w=nm ";
+ unsigned int uMaxSize = KVI_OPTION_UINT(KviOption_uintMaximumRequestedAvatarSize);
+ if(uMaxSize > 0)KviQString::appendFormatted(szCommand,"-m=%u ",uMaxSize);
+ szRemoteFile = szRemoteFile.replace(";","%3B");
+ szRemoteFile = szRemoteFile.replace("\"","%22");
+ szCommand += "\""+szRemoteFile+"\"";
+ szCommand += " \"";
+ szCommand += szLocalFilePath.ptr();
+ szCommand += "\"";
+
+ if(KviKvsScript::run(szCommand,msg->msg->console()))
+ {
+ if(_OUTPUT_VERBOSE)
+ {
+ KviQString::appendFormatted(textLine,
+ __tr2qs(": No valid local copy of avatar available, requesting one (HTTP GET %s)"),
+ szRemoteFile.utf8().data());
+ }
+ g_pApp->setAvatarOnFileReceived(msg->msg->console(),
+ szRemoteFile,msg->pSource->nick(),msg->pSource->username(),msg->pSource->host());
+ } else {
+ if(_OUTPUT_VERBOSE)
+ KviQString::appendFormatted(textLine,__tr2qs(": No valid local copy of avatar available; failed to start an HTTP transfer, ignoring"));
+ }
+ } else {
+ if(!checkCtcpFlood(msg))
+ {
+ if(_OUTPUT_VERBOSE)
+ {
+ KviQString::appendFormatted(textLine,
+ __tr2qs(": No valid local copy of avatar available, requesting one (DCC GET %s)"),
+ szRemoteFile.utf8().data());
+ }
+
+ QString szFName;
+ encodeCtcpParameter(szRemoteFile.utf8().data(),szFName);
+ msg->msg->connection()->sendFmtData("PRIVMSG %s :%cDCC GET %s%c",
+ msg->msg->connection()->encodeText(msg->pSource->nick()).data(),0x01,msg->msg->connection()->encodeText(szFName.utf8().data()).data(),0x01);
+ g_pApp->setAvatarOnFileReceived(msg->msg->console(),
+ szRemoteFile,msg->pSource->nick(),msg->pSource->username(),msg->pSource->host());
+ } else {
+ if(_OUTPUT_VERBOSE)
+ KviQString::appendFormatted(textLine,__tr2qs(": No valid local copy of avatar available; flood limit exceeded, ignoring"));
+ }
+ }
+ } else {
+ if(_OUTPUT_VERBOSE)
+ KviQString::appendFormatted(textLine,__tr2qs(": No valid local copy of avatar available, ignoring"));
+ }
+ }
+ }
+
+ if(!e)
+ {
+ if(_OUTPUT_VERBOSE)
+ KviQString::appendFormatted(textLine,__tr2qs(": No such nickname in the user database, ignoring the change"));
+ msg->msg->console()->outputNoFmt(KVI_OUT_AVATAR,textLine);
+ return;
+ }
+
+ if(bResetAvatar)e->setAvatar(avatar);
+
+ msg->msg->console()->avatarChanged(avatar,msg->pSource->nick(),msg->pSource->user(),msg->pSource->host(),
+ msg->msg->haltOutput() ? QString::null : textLine);
+}
+
+
+
+typedef void (*dccModuleCtcpDccParseRoutine)(KviDccRequest *par);
+
+
+
+void KviServerParser::parseCtcpRequestDcc(KviCtcpMessage *msg)
+{
+ KviDccRequest p;
+ KviStr aux = msg->pData;
+ msg->pData = extractCtcpParameter(msg->pData,p.szType);
+ msg->pData = extractCtcpParameter(msg->pData,p.szParam1);
+ msg->pData = extractCtcpParameter(msg->pData,p.szParam2);
+ msg->pData = extractCtcpParameter(msg->pData,p.szParam3);
+ msg->pData = extractCtcpParameter(msg->pData,p.szParam4);
+ msg->pData = extractCtcpParameter(msg->pData,p.szParam5);
+ p.ctcpMsg = msg;
+ p.bIpV6 = msg->msg->console()->isIpV6Connection();
+ p.pConsole = msg->msg->console();
+
+ KviRegisteredUser * u = msg->msg->connection()->userDataBase()->registeredUser(msg->pSource->nick(),msg->pSource->user(),msg->pSource->host());
+
+ if (u)
+ {
+ if (u->isIgnoreEnabledFor(KviRegisteredUser::Dcc))
+ {
+ if (KVI_OPTION_BOOL(KviOption_boolVerboseIgnore))
+ {
+ msg->msg->console()->output(KVI_OUT_DCCREQUEST,
+ __tr2qs("Ignoring DCC %S request from \r!n\r%Q\r [%Q@\r!h\r%Q\r] (%Q %S)"),
+ &p.szType,&(msg->pSource->nick()),
+ &(msg->pSource->user()),&(msg->pSource->host()),
+ &msg->szTag,&aux);
+ }
+ return;
+ }
+ }
+
+ /*if(KVI_OPTION_BOOL(KviOption_boolIgnoreCtcpDcc))
+ {
+ if(!msg->msg->haltOutput())
+ {
+ msg->msg->console()->output(KVI_OUT_DCCREQUEST,
+ __tr2qs("Ignoring DCC %S request from \r!n\r%Q\r [%Q@\r!h\r%Q\r] (%Q %S)"),
+ &p.szType,&(msg->pSource->nick()),
+ &(msg->pSource->user()),&(msg->pSource->host()),
+ &msg->szTag,&aux);
+ }
+ return;
+ }*/
+
+ bool bIsFlood = checkCtcpFlood(msg);
+
+ if(bIsFlood &&
+ ((kvi_strEqualCI(p.szType.ptr(),"SEND")) ||
+ (kvi_strEqualCI(p.szType.ptr(),"RSEND")) ||
+ (kvi_strEqualCI(p.szType.ptr(),"TSEND")) ||
+ (kvi_strEqualCI(p.szType.ptr(),"TRSEND"))
+ ))
+ {
+ // don't consider as flood the avatars we have requested
+ if(g_pApp->findPendingAvatarChange(msg->msg->console(),msg->pSource->nick(),p.szParam1.ptr()))
+ bIsFlood = false;
+ }
+
+ if(!bIsFlood)
+ {
+ if(!msg->msg->haltOutput())
+ {
+ QString decoded = msg->msg->console()->decodeText(p.szType.ptr());
+ msg->msg->console()->output(KVI_OUT_DCCREQUEST,
+ __tr2qs("Processing DCC %Q request from \r!n\r%Q\r [%Q@\r!h\r%Q\r] (%s %s)"),
+ &decoded,&(msg->pSource->nick()),
+ &(msg->pSource->user()),&(msg->pSource->host()),
+ msg->msg->console()->decodeText(msg->szTag).data(),
+ msg->msg->console()->decodeText(aux.ptr()).data());
+ }
+
+ KviModule * m = g_pModuleManager->getModule("dcc");
+ if(!m)
+ {
+ msg->msg->console()->output(KVI_OUT_DCCERROR,
+ __tr2qs("Unable to process the above request: Cannot load DCC module (%s)"),g_pModuleManager->lastError().ptr());
+ } else {
+ dccModuleCtcpDccParseRoutine proc = (dccModuleCtcpDccParseRoutine)m->getSymbol("dccModuleCtcpDccParseRoutine");
+ if(!proc)
+ {
+ msg->msg->console()->outputNoFmt(KVI_OUT_DCCERROR,
+ __tr2qs("Unable to process the above request: DCC module may be broken"));
+ } else {
+ proc(&p);
+ }
+ }
+ } else {
+ // That's flood
+ echoCtcpRequest(msg);
+ }
+}
+
+void KviServerParser::parseCtcpReplyUserinfo(KviCtcpMessage *msg)
+{
+ QString szRemoteFile;
+ QString szGender;
+ QString decoded=msg->msg->console()->decodeText(msg->pData);
+
+ bool bNeedToUpdateUserlist = false;
+ KviIrcUserEntry * e = msg->msg->connection()->userDataBase()->find(msg->pSource->nick());
+ if(e)
+ {
+ int pos = decoded.find("Gender=",0,false);
+
+ if(pos>=0)
+ {
+ QChar c = decoded[pos+7];
+ switch(c.unicode())
+ {
+ case 'F':
+ case 'f':
+ bNeedToUpdateUserlist = true;
+ e->setGender(KviIrcUserEntry::Female);
+ break;
+ case 'M':
+ case 'm':
+ bNeedToUpdateUserlist = true;
+ e->setGender(KviIrcUserEntry::Male);
+ break;
+ }
+ }
+ }
+
+ if(bNeedToUpdateUserlist)
+ {
+ if(KviQString::equalCS(g_pActiveWindow->className(),QString("KviChannel")))
+ {
+ ((KviChannel*)g_pActiveWindow)->userListView()->updateArea();
+ }
+
+ }
+
+ echoCtcpReply(msg);
+}
+
+void KviServerParser::parseCtcpReplyGeneric(KviCtcpMessage *msg)
+{
+ echoCtcpReply(msg);
+}
+
+
+void KviServerParser::parseCtcpReplyLagcheck(KviCtcpMessage * msg)
+{
+ // this is an internal CTCP used for checking lag
+ KviStr szTag;
+ msg->pData = extractCtcpParameter(msg->pData,szTag,true);
+ if(msg->msg->console()->connection()->lagMeter())
+ msg->msg->console()->connection()->lagMeter()->lagCheckComplete(szTag.ptr());
+}
+
+//ERRORMSG,ECHO,ERRMSG
+//SED,DCC,SOUND/MULTIMEDIA/MM,SCRIPT
diff --git a/src/kvirc/sparser/kvi_sp_literal.cpp b/src/kvirc/sparser/kvi_sp_literal.cpp
new file mode 100644
index 00000000..f6a63a5a
--- /dev/null
+++ b/src/kvirc/sparser/kvi_sp_literal.cpp
@@ -0,0 +1,1867 @@
+//====================================================================================
+//
+// File : kvi_sp_literal.cpp
+// Creation date : Thu Aug 3 2000 01:29:12 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//====================================================================================
+
+#define __KVIRC__
+
+#include "kvi_sparser.h"
+#include "kvi_window.h"
+#include "kvi_console.h"
+#include "kvi_out.h"
+#include "kvi_locale.h"
+#include "kvi_ircsocket.h"
+#include "kvi_options.h"
+#include "kvi_ircmask.h"
+#include "kvi_channel.h"
+#include "kvi_topicw.h"
+#include "kvi_frame.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_query.h"
+#include "kvi_userlistview.h"
+#include "kvi_antispam.h"
+#include "kvi_nickserv.h"
+#include "kvi_parameterlist.h"
+#include "kvi_ircuserdb.h"
+#include "kvi_app.h"
+#include "kvi_regusersdb.h"
+#include "kvi_debug.h"
+#include "kvi_time.h"
+#include "kvi_useraction.h"
+#include "kvi_ircconnection.h"
+#include "kvi_ircconnectionuserinfo.h"
+#include "kvi_ircconnectiontarget.h"
+#include "kvi_ircconnectionserverinfo.h"
+#include "kvi_ircconnectionstatedata.h"
+#include "kvi_ircconnectionnetsplitdetectordata.h"
+#include "kvi_iconmanager.h"
+#include "kvi_lagmeter.h"
+#include "kvi_ircserver.h"
+#include "kvi_kvs_eventtriggers.h"
+#include "kvi_qcstring.h"
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_CRYPT_SUPPORT
+ #include "kvi_crypt.h"
+ #include "kvi_cryptcontroller.h"
+#endif
+
+#include "kvi_kvs_script.h"
+
+//#include "kvi_regusersdb.h"
+//#include "kvi_iconmanager.h"
+#include <qdatetime.h>
+
+#ifdef COMPILE_USE_QT4
+ #include <QTextDocument>
+#else
+ #include <qstylesheet.h>
+#endif
+
+extern KviNickServRuleSet * g_pNickServRuleSet;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// PING
+//
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void KviServerParser::parseLiteralPing(KviIrcMessage *msg)
+{
+ // PING
+ // <optional_prefix> PING :<argument>
+ msg->connection()->sendFmtData("PONG %s",msg->console()->connection()->encodeText(msg->allParams()).data());
+
+ QString szPrefix = msg->connection()->decodeText(msg->safePrefix());
+ QString szAllParams = msg->connection()->decodeText(msg->allParams());
+
+ if(KVS_TRIGGER_EVENT_2_HALTED(KviEvent_OnPing,msg->console(),szPrefix,szAllParams))
+ msg->setHaltOutput();
+
+ if((!msg->haltOutput()) && KVI_OPTION_BOOL(KviOption_boolShowPingPong))
+ {
+ msg->console()->output(KVI_OUT_SERVERPING,
+ __tr2qs("Received ping from \r!s\r%Q\r (PING %Q), replied pong"),
+ &szPrefix,&szAllParams);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// PONG
+//
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void KviServerParser::parseLiteralPong(KviIrcMessage *msg)
+{
+ QString szPrefix = msg->connection()->decodeText(msg->safePrefix());
+ QString szAllParams = msg->connection()->decodeText(msg->allParams());
+
+ if(KVS_TRIGGER_EVENT_2_HALTED(KviEvent_OnPong,msg->console(),szPrefix,szAllParams))
+ msg->setHaltOutput();
+
+ if(msg->console()->connection()->lagMeter())
+ {
+ if(msg->console()->connection()->lagMeter()->lagCheckComplete("@ping@"))
+ msg->setHaltOutput(); // was internally generated!
+ }
+
+ if((!msg->haltOutput()) && KVI_OPTION_BOOL(KviOption_boolShowPingPong))
+ {
+ msg->console()->output(KVI_OUT_SERVERPING,
+ __tr2qs("Received pong from \r!s\r%s\r (PONG %s)"),msg->safePrefix(),msg->allParams());
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// ERROR
+//
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void KviServerParser::parseLiteralError(KviIrcMessage *msg)
+{
+ // ERROR
+ // <optional_prefix> ERROR :<argument>
+ // ERROR :Closing Link: phoenix.pragmaware.net (Ping timeout)
+
+ QString szPrefix = msg->connection()->decodeText(msg->safePrefix());
+ QString szParams = msg->connection()->decodeText(msg->allParams());
+
+ if(KVS_TRIGGER_EVENT_2_HALTED(KviEvent_OnError,msg->console(),szPrefix,szParams))
+ msg->setHaltOutput();
+
+ if(!msg->haltOutput())
+ {
+ msg->console()->output(KVI_OUT_SERVERERROR,
+ __tr2qs("Server ERROR: %Q"),&szParams);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// JOIN
+//
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void KviServerParser::parseLiteralJoin(KviIrcMessage *msg)
+{
+ // JOIN
+ // :<joiner_mask> JOIN :<channel>
+ QString szNick,szUser,szHost;
+ msg->decodeAndSplitPrefix(szNick,szUser,szHost);
+
+ const char * encodedChan = msg->safeTrailing();
+ QString channel = msg->connection()->decodeText(encodedChan);
+
+ if(channel.isEmpty())
+ {
+ // This is broken....
+ UNRECOGNIZED_MESSAGE(msg,__tr2qs("Missing channel parameter in join message"));
+ return;
+ }
+
+ // check for extended join syntax.
+ // it is used in splits only (AFAIK)
+ // nick!user@host JOIN :#channel\x07[o|v]
+ const QChar * pExt = KviQString::nullTerminatedArray(channel);
+ char chExtMode = 0;
+ while(pExt->unicode() && (pExt->unicode() != 0x07))pExt++;
+ if(pExt->unicode())
+ {
+ ++pExt;
+ if(pExt->unicode())
+ {
+ chExtMode = (char)pExt->unicode();
+ channel.remove(channel.length() - 2,2); // assuming that we're at the end (we should be)
+ } // else { senseless 0x07 in channel name ?
+ }
+
+ // Now lookup the channel
+ KviConsole * console = msg->console();
+ KviChannel * chan = msg->connection()->findChannel(channel);
+
+ bool bIsMe = IS_ME(msg,szNick);
+
+ if(!chan)
+ {
+ // This must be me...(or desync)
+ if(bIsMe)
+ {
+ msg->connection()->userInfoReceived(szUser,szHost);
+ chan = msg->connection()->createChannel(channel); // New channel (will resurrect an eventual dead one too!)
+ } else {
+ // Someone is joining an inexsisting channel!!!
+ UNRECOGNIZED_MESSAGE(msg,__tr("Received a join message for an unknown channel, possible desync"));
+ return;
+ }
+
+ int iFlags = 0;
+ iFlags = msg->connection()->serverInfo()->modeFlagFromModeChar(chExtMode);
+
+ KviUserListEntry * it = chan->join(szNick,szUser,szHost,iFlags);
+ if(iFlags)chan->updateCaption();
+
+ // FIXME: #warning "Trigger also OnMeVoice and OnMeOp here ?"
+ if(!(it->globalData()->avatar()))
+ {
+ KviAvatar * av = console->defaultAvatarFromOptions();
+ if(av)
+ {
+ it->globalData()->setAvatar(av);
+ console->avatarChanged(av,szNick,szUser,szHost,QString::null);
+ }
+ }
+
+ if(KVS_TRIGGER_EVENT_0_HALTED(KviEvent_OnMeJoin,chan))
+ msg->setHaltOutput();
+
+ // the channel requests must be sent AFTER we have created and accessed the chan
+ // since it MAY happen that a sendFmtData() call fails by detecting a disconnect
+ // and thus destroys the channel window!
+
+ // If this problem persists in other parts of the KVIrc core then
+ // we should disable disconnection detection during the parsing of a single
+ // message in KviIrcSocket. See the comment in KviIrcSocket::processData() for more info.
+
+ // FIXME: #warning "IF VERBOSE SAY THAT WE'RE REQUESTING MODES & BAN LIST" (Synching channel)
+
+ if(!msg->connection()->sendFmtData("MODE %s",encodedChan))return; // disconnected
+
+ if(msg->connection()->serverInfo()->supportsModesIe())
+ {
+ if(!KVI_OPTION_BOOL(KviOption_boolDisableBanExceptionListRequestOnJoin))
+ {
+ if(!msg->connection()->sendFmtData("MODE %s e",encodedChan))return; // disconnected
+ chan->setSentBanExceptionListRequest();
+ }
+ if(!KVI_OPTION_BOOL(KviOption_boolDisableInviteListRequestOnJoin))
+ {
+ if(!msg->connection()->sendFmtData("MODE %s I",encodedChan))return; // disconnected
+ chan->setSentInviteListRequest();
+ }
+ }
+
+ // MODE %s b MUST BE THE LAST AUTOMATIC CHANNEL QUERY
+ // so we get RPL_ENDOFBANLIST as the last reply
+ // and we know that the channel is in sync
+
+ if(!KVI_OPTION_BOOL(KviOption_boolDisableWhoRequestOnJoin))
+ {
+ msg->connection()->stateData()->setLastSentChannelWhoRequest(kvi_unixTime());
+ if(msg->connection()->lagMeter())
+ {
+ KviStr tmp(KviStr::Format,"WHO %s",encodedChan);
+ msg->connection()->lagMeter()->lagCheckRegister(tmp.ptr(),60);
+ }
+ if(!msg->connection()->sendFmtData("WHO %s",encodedChan))return; // disconnected
+ chan->setSentWhoRequest();
+ }
+ if(!KVI_OPTION_BOOL(KviOption_boolDisableBanListRequestOnJoin))
+ {
+ if(!msg->connection()->sendFmtData("MODE %s b",encodedChan))return; // disconnected
+ chan->setSentBanListRequest();
+ }
+
+ } else {
+ // This must be someone else...(or desync)
+ int iFlags = 0;
+ iFlags = msg->connection()->serverInfo()->modeFlagFromModeChar(chExtMode);
+
+ KviUserListEntry * it = chan->join(szNick,szUser,szHost,iFlags);
+
+ // FIXME: #warning "Trigger also OnVoice and OnOp here ?"
+ // Note: checkDefaultAvatar() makes a KviRegisteredUser lookup
+ // if later it is needed, make it return a pointer
+ if(!(it->globalData()->avatar()))console->checkDefaultAvatar(it->globalData(),szNick,szUser,szHost);
+
+ if(KVS_TRIGGER_EVENT_3_HALTED(KviEvent_OnJoin,chan,szNick,szUser,szHost))
+ msg->setHaltOutput();
+ // FIXME: #warning "WE COULD OPTIONALLY REQUEST A /WHO FOR THE USERS JOINING THAT WE DON'T KNOW THE HOST OF"
+ }
+
+ // Now say it to the world
+ if(!msg->haltOutput())
+ {
+ // FIXME: #warning "CHECK IF MESSAGES GO TO CONSOLE OR NOT"
+
+ if(chExtMode != 0)
+ {
+ chan->output(KVI_OUT_JOIN,
+ __tr2qs("\r!n\r%Q\r [%Q@\r!h\r%Q\r] has joined \r!c\r%Q\r [implicit +%c umode change]"),
+ &szNick,&szUser,&szHost,&channel,chExtMode);
+
+ } else {
+ chan->output(KVI_OUT_JOIN,
+ __tr2qs("\r!n\r%Q\r [%Q@\r!h\r%Q\r] has joined \r!c\r%Q\r"),
+ &szNick,&szUser,&szHost,&channel);
+ }
+ }
+
+ //if(!bisMe) deleted because we can open query with our nick
+ QString szChans;
+ int iChans = msg->connection()->getCommonChannels(szNick,szChans);
+ KviQuery * q = console->connection()->findQuery(szNick);
+ if(q)
+ {
+ if(KVI_OPTION_BOOL(KviOption_boolEnableQueryTracing))
+ {
+ q->output(KVI_OUT_QUERYTRACE,
+ __tr2qs("\r!n\r%Q\r [%Q@\r!h\r%Q\r] has just joined \r!c\r%Q\r"),&szNick,&szUser,
+ &szHost,&channel);
+ q->notifyCommonChannels(szNick,szUser,szHost,iChans,szChans);
+ } else {
+ q->updateLabelText();
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// PART
+//
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void KviServerParser::parseLiteralPart(KviIrcMessage *msg)
+{
+ // PART
+ // :<source_mask> PART <channel> :<part message>
+ QString szNick,szUser,szHost;
+ msg->decodeAndSplitPrefix(szNick,szUser,szHost);
+
+ QString szChan = msg->connection()->decodeText(msg->safeParam(0));
+
+ // Now lookup the channel
+ KviConsole * console = msg->console();
+ KviChannel * chan = msg->connection()->findChannel(szChan);
+
+ if(!chan)
+ {
+ //chan = msg->context()->findDeadChannel(msg->safeParam(0));
+ UNRECOGNIZED_MESSAGE(msg,__tr("Received a part message for an unknown channel, possible desync"));
+ return;
+ }
+
+ // always decode with the textEncoding of the channel
+ QString partMsg = msg->paramCount() > 1 ? chan->decodeText(msg->safeTrailing()) : QString::null;
+
+ if(IS_ME(msg,szNick))
+ {
+ if(KVS_TRIGGER_EVENT_1_HALTED(KviEvent_OnMePart,chan,partMsg))
+ msg->setHaltOutput();
+
+ KviWindow * pOut = console;
+
+ // It's me!
+ if(chan->closeOnPart() && !KVI_OPTION_BOOL(KviOption_boolKeepChannelOpenOnPart))
+ {
+ chan->frame()->closeWindow(chan); // <-- deleted path
+ } else {
+ chan->part(szNick); // this will trigger the action too
+ chan->setDeadChan();
+ pOut = chan;
+ }
+
+ if(!msg->haltOutput())
+ {
+ if(KVI_OPTION_BOOL(KviOption_boolShowOwnParts))
+ {
+ if(partMsg.isEmpty())
+ pOut->output(KVI_OUT_PART,__tr2qs("You have left channel \r!c\r%Q\r"),&szChan);
+ else
+ pOut->output(KVI_OUT_PART,__tr2qs("You have left channel \r!c\r%Q\r: %Q"),&szChan,&partMsg);
+ }
+ }
+
+ } else {
+ // Someone else
+
+ if(KVS_TRIGGER_EVENT_4_HALTED(KviEvent_OnPart,chan,szNick,szUser,szHost,partMsg))
+ msg->setHaltOutput();
+
+ chan->part(szNick);
+
+ if(!msg->haltOutput())
+ {
+ if(!partMsg.isEmpty())
+ chan->output(KVI_OUT_PART,
+ __tr2qs("\r!n\r%Q\r [%Q@\r!h\r%Q\r] has left \r!c\r%Q\r: %Q"),&szNick,&szUser,
+ &szHost,&szChan,&partMsg);
+ else
+ chan->output(KVI_OUT_PART,
+ __tr2qs("\r!n\r%Q\r [%Q@\r!h\r%Q\r] has left \r!c\r%Q\r"),&szNick,&szUser,
+ &szHost,&szChan);
+
+ }
+
+ if(KVI_OPTION_BOOL(KviOption_boolEnableQueryTracing))
+ {
+ QString szChans;
+ int iChans = console->connection()->getCommonChannels(szNick,szChans);
+ KviQuery * q = console->connection()->findQuery(szNick);
+ if(q)
+ {
+ if(!partMsg.isEmpty())
+ q->output(KVI_OUT_QUERYTRACE,
+ __tr2qs("\r!nc\r%Q\r [%Q@\r!h\r%Q\r] has just left \r!c\r%Q\r: %Q"),
+ &szNick,&szUser,&szHost,&szChan,&partMsg);
+ else
+ q->output(KVI_OUT_QUERYTRACE,
+ __tr2qs("\r!nc\r%Q\r [%Q@\r!h\r%Q\r] has just left \r!c\r%Q\r"),
+ &szNick,&szUser,&szHost,&szChan);
+ q->notifyCommonChannels(szNick,szUser,szHost,iChans,szChans);
+ }
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// QUIT
+//
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void KviServerParser::parseLiteralQuit(KviIrcMessage *msg)
+{
+ // QUIT
+ // :<source_mask> QUIT :<quit message>
+ QString szNick,szUser,szHost;
+ msg->decodeAndSplitPrefix(szNick,szUser,szHost);
+
+ KviConsole * console = msg->console();
+
+ // NETSPLIT DETECTION STUFF
+ // this doesn't need to be decoded for the moment
+ const char * aux = msg->safeTrailing();
+ bool bWasSplit = false;
+ //determine if signoff string matches "%.% %.%", and only one space (from eggdrop code)
+ char *p = (char *)strchr(aux, ' ');
+ if (p && (p == (char *)strrchr(aux,' ')))
+ {
+ char *daSpace = p;
+ // one space detected. go ahead
+ char *z1, *z2;
+ *p = 0;
+ z1 = (char *)strchr(p + 1, '.');
+ z2 = (char *)strchr(aux, '.');
+ if (z1 && z2 && (*(z1 + 1) > 47) && (z1 - 1 != p) && (z2 + 1 != p) && (z2 != aux) && console->connection())
+ {
+ // server split, or else it looked like it anyway
+ KviIrcConnectionNetsplitDetectorData * ndd = msg->connection()->netsplitDetectorData();
+ *p=' ';
+ bWasSplit = true;
+
+ time_t curTime = kvi_unixTime();
+ int diff = ((unsigned int)curTime) - ((unsigned int)ndd->lastNetsplitOnQuitTime());
+ bool bDuplicate = false;
+
+ QString szReason = aux;
+ if(diff < 6)
+ {
+ if(KviQString::equalCI(ndd->lastNetsplitOnQuitReason(),szReason))
+ {
+ bDuplicate = true;
+ }
+ }
+
+ ndd->setLastNetsplitOnQuitTime(curTime);
+ ndd->setLastNetsplitOnQuitReason(szReason);
+
+ if(!bDuplicate)
+ {
+ KviStr sz1(aux,daSpace - aux);
+ KviStr sz2(daSpace + 1);
+
+ QString szD1 = msg->connection()->decodeText(sz1.ptr());
+ QString szD2 = msg->connection()->decodeText(sz2.ptr());
+ if(!KVS_TRIGGER_EVENT_2_HALTED(KviEvent_OnNetsplit,console,szD1,szD2))
+ {
+ if(!msg->haltOutput())
+ console->output(KVI_OUT_SPLIT,__tr2qs("Netsplit detected: %s"),aux);
+ }
+ }
+ } else *p = ' ';
+ }
+
+ // FIXME: #warning "Add a netsplit parameter ?"
+
+ if(KviKvsEventManager::instance()->hasAppHandlers(KviEvent_OnQuit))
+ {
+ // compute the channel list
+ QString chanlist;
+ QString szReason = msg->connection()->decodeText(msg->safeTrailing());
+
+ for(KviChannel *daChan=console->channelList()->first();daChan;daChan=console->channelList()->next())
+ {
+ if(daChan->isOn(szNick))
+ {
+ if(chanlist.isEmpty())chanlist = daChan->windowName();
+ else {
+ chanlist.append(',');
+ chanlist.append(daChan->windowName());
+ }
+ }
+ }
+
+ KviKvsVariantList vList;
+ vList.append(szNick);
+ vList.append(szUser);
+ vList.append(szHost);
+ vList.append(szReason);
+ vList.append(chanlist);
+
+ if(KviKvsEventManager::instance()->trigger(KviEvent_OnQuit,console,&vList))
+ msg->setHaltOutput();
+ }
+
+
+ for(KviChannel *c=console->channelList()->first();c;c=console->channelList()->next())
+ {
+ if(c->part(szNick))
+ {
+ if(!msg->haltOutput())
+ {
+ QString quitMsg = c->decodeText(msg->safeTrailing());
+
+ if(bWasSplit)
+ {
+ quitMsg.prepend("NETSPLIT ");
+ }
+
+ if(!msg->haltOutput())c->output(KVI_OUT_QUIT,
+ __tr2qs("\r!n\r%Q\r [%Q@\r!h\r%Q\r] has quit IRC: %Q"),
+ &szNick,&szUser,&szHost,&quitMsg);
+ }
+ }
+ }
+
+ if(!msg->haltOutput())
+ {
+ KviQuery * q = msg->connection()->findQuery(szNick);
+ if(q)
+ {
+ QString quitMsg = q->decodeText(msg->safeTrailing());
+ if(bWasSplit)
+ {
+ quitMsg.prepend("NETSPLIT ");
+ }
+ q->output(KVI_OUT_QUIT,__tr2qs("\r!n\r%Q\r [%Q@\r!h\r%Q\r] has quit IRC: %Q"),
+ &szNick,&szUser,&szHost,&quitMsg);
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// KICK
+//
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void KviServerParser::parseLiteralKick(KviIrcMessage *msg)
+{
+ // KICK
+ // :<source_mask> KICK <channel> <nick> :<kick message>
+ QString szNick,szUser,szHost;
+ msg->decodeAndSplitPrefix(szNick,szUser,szHost);
+
+ QString szChan = msg->connection()->decodeText(msg->safeParam(0));
+ QString victim = msg->connection()->decodeText(msg->safeParam(1));
+
+ KviConsole * console = msg->console();
+ KviChannel * chan = msg->connection()->findChannel(szChan);
+
+ if(!chan){
+ // Ooops , desync with the server.
+ UNRECOGNIZED_MESSAGE(msg,__tr("Received a kick message for an unknown channel, possible desync"));
+ return;
+ }
+
+ QString szKickMsg = chan->decodeText(msg->safeTrailing());
+
+ if(IS_ME(msg,victim))
+ {
+ // ops...I have been kicked
+
+ if(KVS_TRIGGER_EVENT_4_HALTED(KviEvent_OnMeKick,chan,
+ szNick,szUser,szHost,szKickMsg))
+ msg->setHaltOutput();
+ if(!KVI_OPTION_STRING(KviOption_stringOnMeKickedSound).isEmpty()) KviKvsScript::run("snd.play $0",0,new KviKvsVariantList(new KviKvsVariant(KVI_OPTION_STRING(KviOption_stringOnMeKickedSound))));
+
+ QString szPass = chan->channelKey();
+
+ if(KVI_OPTION_BOOL(KviOption_boolKeepChannelOpenOnKick))
+ {
+ chan->userAction(szNick,szUser,szHost,KVI_USERACTION_KICK);
+ chan->part(victim);
+ chan->setDeadChan();
+
+ if(!msg->haltOutput())
+ {
+ // FIXME: #warning "OPTION FOR THIS TO GO TO THE CONSOLE!"
+ chan->output(KVI_OUT_MEKICK,
+ __tr2qs("You have been kicked from \r!c\r%Q\r by \r!n\r%Q\r [%Q@\r!h\r%Q\r]: %Q"),
+ &szChan,&szNick,&szUser,&szHost,&szKickMsg);
+ }
+ } else {
+ chan->frame()->closeWindow(chan); // <-- deleted path
+
+ if(!msg->haltOutput())
+ {
+ // FIXME: #warning "This could go also to the active window!"
+ console->output(KVI_OUT_MEKICK,
+ __tr2qs("You have been kicked from \r!c\r%Q\r by \r!n\r%Q\r [%Q@\r!h\r%Q\r]: %Q"),
+ &szChan,&szNick,&szUser,&szHost,&szKickMsg);
+ }
+ }
+ if(KVI_OPTION_BOOL(KviOption_boolRejoinChannelOnKick))
+ {
+ if(_OUTPUT_VERBOSE)
+ console->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Attempting to rejoin \r!c\r%Q\r..."),&szChan);
+ KviQCString szC = msg->connection()->encodeText(szChan);
+ if(!szPass.isEmpty())
+ {
+ KviQCString szP = msg->connection()->encodeText(szChan);
+ msg->connection()->sendFmtData("JOIN %s %s",szC.data(),szP.data());
+ } else msg->connection()->sendFmtData("JOIN %s",szC.data());
+ }
+ } else {
+ // ok...someone else has been kicked
+
+ if(KVS_TRIGGER_EVENT_5_HALTED(KviEvent_OnKick,chan,
+ szNick,szUser,szHost,victim,szKickMsg))
+ msg->setHaltOutput();
+
+ KviIrcUserEntry * e = msg->connection()->userDataBase()->find(victim);
+
+ QString szVHost;
+ QString szVUser;
+
+ if(e)
+ {
+ szVHost = e->host();
+ szVUser = e->user();
+ } else {
+ szVHost = "*";
+ szVUser = "*";
+ }
+
+ chan->userAction(szNick,szUser,szHost,KVI_USERACTION_KICK);
+
+ chan->part(victim);
+
+ if(!msg->haltOutput())
+ {
+// FIXME: #warning "OPTION FOR THIS TO GO TO THE CONSOLE!"
+ chan->output(KVI_OUT_KICK,
+ __tr2qs("\r!n\r%Q\r [%Q@\r!h\r%Q\r] has been kicked from \r!c\r%Q\r by \r!n\r%Q\r [%Q@\r!h\r%Q\r]: %Q"),
+ &victim,&szVUser,&szVHost,&szChan,&szNick,&szUser,&szHost,&szKickMsg);
+ }
+
+ if(KVI_OPTION_BOOL(KviOption_boolEnableQueryTracing))
+ {
+ KviQuery * q = console->connection()->findQuery(victim);
+ if(q)
+ {
+ QString szChans;
+ int iChans = console->connection()->getCommonChannels(victim,szChans);
+ q->output(KVI_OUT_QUERYTRACE,
+ __tr2qs("\r!n\r%Q\r [%Q@\r!h\r%Q\r] has just been kicked from \r!c\r%Q\r by \r!n\r%Q\r [%Q@\r!h\r%Q\r]: %Q"),
+ &victim,&szVUser,&szVHost,&szChan,
+ &szNick,&szUser,&szHost,&szKickMsg);
+ q->notifyCommonChannels(victim,szVUser,szVHost,iChans,szChans);
+ }
+ }
+ }
+}
+
+#ifdef COMPILE_CRYPT_SUPPORT
+ #define DECRYPT_IF_NEEDED(_target,_txt,_type,_type2,_buffer,_retptr,_retmsgtype) \
+ if(KviCryptSessionInfo * cinf = _target->cryptSessionInfo()){ \
+ if(cinf->bDoDecrypt){ \
+ switch(cinf->pEngine->decrypt(_txt,_buffer)) \
+ { \
+ case KviCryptEngine::DecryptOkWasEncrypted: \
+ _retptr = _buffer.ptr(); \
+ _retmsgtype = _type2; \
+ break; \
+ case KviCryptEngine::DecryptOkWasPlainText: \
+ case KviCryptEngine::DecryptOkWasEncoded: \
+ _retptr = _buffer.ptr(); \
+ _retmsgtype = _type; \
+ break; \
+ default: /* also case KviCryptEngine::DecryptError: */ \
+ { \
+ QString szEngineError = cinf->pEngine->lastError(); \
+ _target->output(KVI_OUT_SYSTEMERROR, \
+ __tr2qs("The following message appears to be encrypted, but the crypto engine failed to decode it: %Q"), \
+ &szEngineError); \
+ _retptr = _txt + 1; _retmsgtype=_type; \
+ } \
+ break; \
+ } \
+ } else _retptr = _txt, _retmsgtype=_type; \
+ } else _retptr = _txt, _retmsgtype=_type;
+#else //!COMPILE_CRYPT_SUPPORT
+ #define DECRYPT_IF_NEEDED(_target,_txt,_type,_type2,_buffer,_retptr,_retmsgtype) \
+ _retptr = _txt; _retmsgtype = _type;
+#endif //!COMPILE_CRYPT_SUPPORT
+
+
+
+void KviServerParser::parseLiteralPrivmsg(KviIrcMessage *msg)
+{
+ // PRIVMSG
+ // :source PRIVMSG <target> :<message>
+ QString szNick,szUser,szHost;
+ msg->decodeAndSplitPrefix(szNick,szUser,szHost);
+
+ QString szTarget = msg->connection()->decodeText(msg->safeParam(0));
+ QString szMsg = msg->connection()->decodeText(msg->safeTrailing());
+
+ KviConsole * console = msg->console();
+ KviRegisteredUser * u = msg->connection()->userDataBase()->registeredUser(szNick,szUser,szHost);
+ //Highlight it?
+
+ // FIXME: #warning "DEDICATED CTCP WINDOW ?"
+ KviStr * pTrailing = msg->trailingString();
+ if(pTrailing)
+ {
+ if(*(pTrailing->ptr()) == 0x01)
+ {
+ if(pTrailing->len() > 1)
+ {
+ if(pTrailing->lastCharIs(0x01))pTrailing->cutRight(1);
+ pTrailing->cutLeft(1);
+ KviCtcpMessage ctcp;
+ ctcp.msg = msg;
+ ctcp.pData = pTrailing->ptr();
+ KviIrcMask talker(szNick,szUser,szHost); // FIXME!
+ ctcp.pSource = &talker;
+ ctcp.szTarget = msg->connection()->decodeText(msg->safeParam(0));
+ ctcp.bIgnored = false;
+ ctcp.bIsFlood = false;
+ ctcp.bUnknown = false;
+ parseCtcpRequest(&ctcp);
+ return;
+ }
+ }
+ }
+
+ // Normal PRIVMSG
+ if(IS_ME(msg,szTarget))
+ {
+ //Ignore it?
+ if (u)
+ {
+ if (u->isIgnoreEnabledFor(KviRegisteredUser::Query))
+ {
+ if(KVS_TRIGGER_EVENT_5_HALTED(KviEvent_OnIgnoredMessage,msg->console(),szNick,szUser,szHost,szTarget,szMsg)) return;
+
+ if (KVI_OPTION_BOOL(KviOption_boolVerboseIgnore))
+ {
+ console->output(KVI_OUT_IGNORE,__tr2qs("Ignoring query-PRIVMSG from \r!nc\r%Q\r [%Q@\r!h\r%Q\r]: %Q"),&szNick,&szUser,&szHost,&szMsg);
+ }
+ return;
+ }
+ }
+ // FIXME: #warning "PROCESS MULTIMEDIA FILE REQUESTS"
+
+ // if(g_pOptions->m_bListenToMultimediaFileRequests)
+ // {
+ // if(*aux == '!')
+ // {
+ // const char *tmp = aux;
+ // tmp++;
+ // if(kvi_strEqualCI(tmp,m_pFrm->m_global.szCurrentNick.ptr()))
+ // {
+ // // A multimedia file request ?
+ // tmp += m_pFrm->m_global.szCurrentNick.len();
+ // if(((*tmp) == ' ') || ((*tmp) == '\t'))
+ // {
+ // while(((*tmp) == ' ') || ((*tmp) == '\t'))tmp++;
+ // if(*tmp)
+ // {
+ // KviStr file = tmp;
+ // KviStr filePath;
+ // m_pFrm->findMultimediaFileOffert(filePath,file);
+ // if(filePath.hasData())
+ // {
+ // m_pFrm->activeWindow()->output(KVI_OUT_INTERNAL,__tr("%s requests previously offered file %s: sending (%s)"),talker.nick(),file.ptr(),filePath.ptr());
+ // KviStr cmd(KviStr::Format,"DCC SEND %s %s",talker.nick(),filePath.ptr());
+ // m_pFrm->m_pUserParser->parseUserCommand(cmd,m_pConsole);
+ // return;
+
+ // } else {
+ // m_pFrm->activeWindow()->output(KVI_OUT_INTERNAL,__tr("%s requests file %s: no such file was offered , ignoring"),talker.nick(),file.ptr());
+ // return;
+ // }
+ // }
+ // }
+ // }
+ // }
+ // }
+
+ // A query request
+ // do we have a matching window ?
+ KviQuery * query = msg->connection()->findQuery(szNick);
+
+ if(!query)
+ {
+ // New query requested. Check if we really should create it or not
+
+ // first of all the anti spam , if desired.
+ // the antispam blocks anything else
+ // Eventually we could trigger a special event to notify the user of the
+ // spam message...
+ if(KVI_OPTION_BOOL(KviOption_boolUseAntiSpamOnPrivmsg))
+ {
+ KviStr * theMsg = msg->trailingString();
+ if(theMsg)
+ {
+ KviStr spamWord;
+ if(kvi_mayBeSpam(theMsg,spamWord))
+ {
+ // FIXME: OnSpam ?
+ if(!(msg->haltOutput() || KVI_OPTION_BOOL(KviOption_boolSilentAntiSpam)))
+ {
+ QString szMsg = msg->connection()->decodeText(msg->safeTrailing());
+ console->output(KVI_OUT_SPAM,
+ __tr2qs("Spam privmsg from \r!n\r%Q\r [%Q@\r!h\r%Q\r]: %Q (matching spamword \"%s\")"),
+ &szNick,&szUser,&szHost,&szMsg,spamWord.ptr());
+ }
+ return;
+ }
+ }
+ }
+
+ // this is not a spam, or at least it hasn't been recognized as spam
+
+ // user option ? (this should again override any script)
+ // if the scripters want really to force the query creation they can do
+ // it manually or they can set the option to true at KVIrc startup
+ if(KVI_OPTION_BOOL(KviOption_boolCreateQueryOnPrivmsg))
+ {
+ QString szMsg = msg->connection()->decodeText(msg->safeTrailing());
+ // We still want to create it
+ // Give the scripter a chance to filter it out again
+ if(KVS_TRIGGER_EVENT_4_HALTED(KviEvent_OnQueryWindowRequest,
+ console,szNick,szUser,szHost,szMsg))
+ {
+ // check if the scripter hasn't created it
+ query = msg->connection()->findQuery(szNick);
+ } else {
+ // no query yet, create it!
+ // this will trigger OnQueryWindowCreated
+ query = console->connection()->createQuery(szNick);
+ // and this will trigger OnQueryTargetAdded
+ query->setTarget(szNick,szUser,szHost);
+ }
+ }
+ }
+
+ // ok, now we either have a query or not
+ if(query)
+ {
+ // ok, we have the query. Trigger the user action anyway
+ query->userAction(szNick,szUser,szHost,KVI_USERACTION_PRIVMSG);
+ // decrypt the message if needed
+ KviStr szBuffer; const char * txtptr; int msgtype;
+ DECRYPT_IF_NEEDED(query,msg->safeTrailing(),KVI_OUT_QUERYPRIVMSG,KVI_OUT_QUERYPRIVMSGCRYPTED,szBuffer,txtptr,msgtype)
+ // trigger the script event and eventually kill the output
+ QString szMsgText = query->decodeText(txtptr);
+ if(KVS_TRIGGER_EVENT_4_HALTED(KviEvent_OnQueryMessage,query,szNick,szUser,szHost,szMsgText))
+ msg->setHaltOutput();
+
+ if(!KVI_OPTION_STRING(KviOption_stringOnQueryMessageSound).isEmpty() && query!=g_pActiveWindow)
+ {
+ // KviKvsScript does NOT take parameters ownership
+ KviKvsVariantList soundParams(new KviKvsVariant(KVI_OPTION_STRING(KviOption_stringOnQueryMessageSound)));
+ //KviKvsScript::run("snd.play $0",0,&soundParams); <-- we also should provide a window for the script: it's always a good idea
+ KviKvsScript::run("snd.play $0",query,&soundParams);
+ }
+
+ // spit out the message text
+ if(!msg->haltOutput())
+ {
+ int iFlags = 0;
+ if(!query->hasAttention())
+ {
+ if(KVI_OPTION_BOOL(KviOption_boolFlashQueryWindowOnNewMessages))
+ {
+ // avoid double window flashing
+ iFlags |= KviConsole::NoWindowFlashing;
+ query->demandAttention();
+ }
+ if(KVI_OPTION_BOOL(KviOption_boolPopupNotifierOnNewQueryMessages))
+ {
+ // don't send the message to the notifier twice
+ iFlags |= KviConsole::NoNotifier;
+ #ifdef COMPILE_USE_QT4
+ QString szMsg = Qt::escape(szMsgText);
+ #else
+ QString szMsg = QStyleSheet::escape(szMsgText);
+ #endif
+ //debug("kvi_sp_literal.cpp:908 debug: %s",szMsg.data());
+ g_pApp->notifierMessage(query,KVI_SMALLICON_QUERYPRIVMSG,szMsg,1800);
+ }
+ }
+ console->outputPrivmsg(query,msgtype,szNick,szUser,szHost,szMsgText,iFlags);
+ }
+ } else {
+ // no query creation: no decryption possible
+ // trigger the query message event in the console
+ QString szMsgText = msg->connection()->decodeText(msg->safeTrailing());
+ if(KVS_TRIGGER_EVENT_4_HALTED(KviEvent_OnQueryMessage,console,szNick,szUser,szHost,szMsgText))
+ msg->setHaltOutput();
+
+ // we don't have a query here!
+ //if(!KVI_OPTION_STRING(KviOption_stringOnQueryMessageSound).isEmpty() && query!=g_pActiveWindow)
+ if(!KVI_OPTION_STRING(KviOption_stringOnQueryMessageSound).isEmpty() && console!=g_pActiveWindow)
+ {
+ // same as above
+ KviKvsVariantList soundParams(new KviKvsVariant(KVI_OPTION_STRING(KviOption_stringOnQueryMessageSound)));
+ KviKvsScript::run("snd.play $0",console,&soundParams);
+ }
+ // spit the message text out
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolExternalMessagesToActiveWindow) ?
+ console->activeWindow() : (KviWindow *)(console);
+
+ if(KviIrcConnection * pConnection = console->connection())
+ {
+ KviWindow * aWin = console->activeWindow();
+ if((aWin->type() == KVI_WINDOW_TYPE_CHANNEL) && ((KviChannel *)aWin)->isOn(szNick))
+ pOut = aWin;
+ else {
+ for(KviChannel * c = pConnection->channelList()->first();c;c = pConnection->channelList()->next())
+ if(c->isOn(szNick))
+ {
+ pOut = (KviWindow *) c;
+ break;
+ }
+ }
+ }
+
+ pOut->output(KVI_OUT_QUERYPRIVMSG,"[PRIVMSG \r!nc\r%Q\r]: %Q",&szNick,&szMsgText);
+ }
+ }
+ } else {
+ // Channel PRIVMSG
+
+ KviChannel * chan = msg->connection()->findChannel(szTarget);
+
+ QString szOriginalTarget = szTarget;
+ QString szPrefixes;
+
+ //Ignore it?
+ if(u)
+ {
+ if(u->isIgnoreEnabledFor(KviRegisteredUser::Channel))
+ {
+ if(KVS_TRIGGER_EVENT_5_HALTED(KviEvent_OnIgnoredMessage,msg->console(),szNick,szUser,szHost,szTarget,szMsg))
+ return;
+
+ if (KVI_OPTION_BOOL(KviOption_boolVerboseIgnore))
+ {
+ console->output(KVI_OUT_IGNORE,__tr2qs("Ignoring channel-PRIVMSG from \r!nc\r%Q\r [%Q@\r!h\r%Q\r]: %Q"),&szNick,&szUser,&szHost,&szMsg);
+ }
+ return;
+ }
+ }
+
+ if(!chan)
+ {
+ // check if the channel has some leading mode prefixes
+ while((szTarget.length() > 0) && console->connection()->serverInfo()->isSupportedModePrefix(szTarget[0].unicode()))
+ {
+ szPrefixes += szTarget[0];
+ szTarget.remove(0,1);
+ }
+ chan = msg->connection()->findChannel(szTarget);
+ }
+
+ if(!chan)
+ {
+ if(!msg->haltOutput())
+ {
+ QString szMsgText = msg->connection()->decodeText(msg->safeTrailing());
+ KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolOperatorMessagesToActiveWindow) ?
+ console->activeWindow() : (KviWindow *)(console);
+ QString broad;
+ KviQString::sprintf(broad,"[>> %Q] %Q",&szOriginalTarget,&szMsgText);
+ console->outputPrivmsg(pOut,KVI_OUT_BROADCASTPRIVMSG,szNick,szUser,szHost,broad,0);
+ }
+ } else {
+ chan->userAction(szNick,szUser,szHost,KVI_USERACTION_PRIVMSG);
+
+ KviStr szBuffer; const char * txtptr; int msgtype;
+ DECRYPT_IF_NEEDED(chan,msg->safeTrailing(),KVI_OUT_CHANPRIVMSG,KVI_OUT_CHANPRIVMSGCRYPTED,szBuffer,txtptr,msgtype)
+
+ QString szMsgText = chan->decodeText(txtptr);
+
+ if(KVS_TRIGGER_EVENT_5_HALTED(KviEvent_OnChannelMessage,chan,szNick,szUser,szHost,szMsgText,szPrefixes))
+ msg->setHaltOutput();
+
+ if(!msg->haltOutput())
+ {
+ if(szPrefixes.length() > 0)
+ {
+ QString szBroad;
+ KviQString::sprintf(szBroad,"[>> %Q\r!c\r%Q\r] %Q",&szPrefixes,&szTarget,&szMsgText);
+ console->outputPrivmsg(chan,msgtype,szNick,szUser,szHost,szBroad,0);
+ } else {
+ console->outputPrivmsg(chan,msgtype,szNick,szUser,szHost,szMsgText,0);
+ }
+ }
+ }
+ }
+}
+
+
+void KviServerParser::parseLiteralNotice(KviIrcMessage *msg)
+{
+ // NOTICE
+ // :source NOTICE <target> :<message>
+ QString szNick,szUser,szHost;
+ msg->decodeAndSplitPrefix(szNick,szUser,szHost);
+
+ KviConsole * console = msg->console();
+
+ if(szHost == "*")
+ {
+ if(szUser == "*")
+ {
+ if(szNick.find('.') != -1)
+ {
+ // server notice
+ // FIXME: "Dedicated window for server notices ?"
+ QString szMsgText = msg->connection()->decodeText(msg->safeTrailing());
+ if(KVS_TRIGGER_EVENT_2_HALTED(KviEvent_OnServerNotice,console,szNick,szMsgText))
+ msg->setHaltOutput();
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolServerNoticesToActiveWindow) ?
+ console->activeWindow() : (KviWindow *)(console);
+ pOut->output(KVI_OUT_SERVERNOTICE,"[\r!s\r%Q\r]: %Q",&szNick,&szMsgText);
+ }
+ return;
+ }
+ }
+ }
+
+ // FIXME: "DEDICATED CTCP WINDOW ?"
+
+ KviStr * pTrailing = msg->trailingString();
+ if(pTrailing)
+ {
+ if(*(pTrailing->ptr()) == 0x01){
+ if(pTrailing->len() > 1)
+ {
+ if(pTrailing->lastCharIs(0x01))pTrailing->cutRight(1);
+ pTrailing->cutLeft(1);
+ KviCtcpMessage ctcp;
+ ctcp.msg = msg;
+ ctcp.pData = pTrailing->ptr();
+ KviIrcMask talker(szNick,szUser,szHost); // FIXME
+ ctcp.pSource = &talker;
+ ctcp.szTarget = msg->connection()->decodeText(msg->safeParam(0));
+ ctcp.bIgnored = false;
+ ctcp.bIsFlood = false;
+ ctcp.bUnknown = false;
+ parseCtcpReply(&ctcp);
+ return;
+ }
+ }
+ }
+
+ QString szTarget = msg->connection()->decodeText(msg->safeParam(0));
+
+ KviRegisteredUser * u = msg->connection()->userDataBase()->registeredUser(szNick,szUser,szHost);
+ //Ignore it?
+ if(u)
+ {
+ if(u->isIgnoreEnabledFor(KviRegisteredUser::Notice))
+ {
+ if(KVI_OPTION_BOOL(KviOption_boolVerboseIgnore))
+ {
+ QString szMsg = msg->connection()->decodeText(msg->safeTrailing());
+ console->output(KVI_OUT_IGNORE,__tr2qs("Ignoring Notice from \r!nc\r%Q\r [%Q@\r!h\r%Q\r]: %Q"),&szNick,&szUser,&szHost,&szMsg);
+ }
+ return;
+ }
+ }
+
+ // Normal NOTICE
+ if(IS_ME(msg,szTarget))
+ {
+ // FIXME: "The NickServ and ChanServ handling should be optional!"
+
+ if(KviQString::equalCI(szNick,"NickServ"))
+ {
+ QString szMsgText = msg->connection()->decodeText(msg->safeTrailing());
+ if(KVS_TRIGGER_EVENT_4_HALTED(KviEvent_OnNickServNotice,console,szNick,szUser,szHost,szMsgText))
+ msg->setHaltOutput();
+
+ // nickname service... does it ask for identification ?
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolServicesNoticesToActiveWindow) ?
+ console->activeWindow() : (KviWindow *)(console);
+ pOut->output(KVI_OUT_NICKSERV,"\r!n\r%Q\r [%Q@\r!h\r%Q\r]: %Q",&szNick,&szUser,&szHost,&szMsgText);
+ }
+
+ bool bAuthDone = false;
+ KviNickServRuleSet * r = msg->connection()->target()->network()->nickServRuleSet();
+ if(r)
+ {
+ if(r->isEnabled() && !r->isEmpty())
+ {
+ KviIrcMask talker(szNick,szUser,szHost);
+ KviNickServRule * rule = r->matchRule(msg->connection()->currentNickName(),&talker,szMsgText);
+ if(rule)
+ {
+ bAuthDone = true;
+ console->outputNoFmt(KVI_OUT_SYSTEMMESSAGE,__tr2qs("NickServ requests authentication, executing scheduled command"));
+ if(!KviKvsScript::run(rule->identifyCommand(),console))
+ {
+ console->outputNoFmt(KVI_OUT_SYSTEMERROR,__tr2qs("The scheduled NickServ identification command appears to be broken, please change the setting"));
+ }
+ }
+ }
+ }
+
+ if(!bAuthDone)
+ {
+ if(g_pNickServRuleSet->isEnabled() && !g_pNickServRuleSet->isEmpty())
+ {
+ KviIrcMask talker(szNick,szUser,szHost);
+ KviNickServRule * rule = g_pNickServRuleSet->matchRule(msg->connection()->currentNickName(),&talker,szMsgText,msg->connection()->currentServerName());
+ if(rule)
+ {
+ console->outputNoFmt(KVI_OUT_SYSTEMMESSAGE,__tr2qs("NickServ requests authentication, executing scheduled command"));
+ if(!KviKvsScript::run(rule->identifyCommand(),console))
+ {
+ console->outputNoFmt(KVI_OUT_SYSTEMERROR,__tr2qs("The scheduled NickServ identification command appears to be broken, please change the setting"));
+ }
+ }
+ }
+ }
+
+ return;
+ }
+
+ if(KviQString::equalCI(szNick,"ChanServ"))
+ {
+ QString szMsgText = msg->connection()->decodeText(msg->safeTrailing());
+ if(KVS_TRIGGER_EVENT_4_HALTED(KviEvent_OnChanServNotice,console,szNick,szUser,szHost,szMsgText))
+ msg->setHaltOutput();
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolServicesNoticesToActiveWindow) ?
+ console->activeWindow() : (KviWindow *)(console);
+ pOut->output(KVI_OUT_CHANSERV,"\r!n\r%Q\r [%Q@\r!h\r%Q\r]: %Q",&szNick,&szUser,&szHost,&szMsgText);
+ }
+ return;
+ }
+
+ // FIXME: PROCESS MULTIMEDIA FILE REQUESTS
+
+ // A query request
+ // do we have a matching window ?
+ KviQuery * query = msg->connection()->findQuery(szNick);
+
+ if(!query)
+ {
+ // New query requested. Check if we really should create it or not
+
+ // first of all the anti spam , if desired.
+ // the antispam blocks anything else
+ // Eventually we could trigger a special event to notify the user of the
+ // spam message...
+ if(KVI_OPTION_BOOL(KviOption_boolUseAntiSpamOnNotice))
+ {
+ KviStr * theMsg = msg->trailingString(); // FIXME
+ if(theMsg)
+ {
+ KviStr spamWord;
+ if(kvi_mayBeSpam(theMsg,spamWord))
+ {
+ // FIXME: OnSpam ?
+
+ if(!(msg->haltOutput() || KVI_OPTION_BOOL(KviOption_boolSilentAntiSpam)))
+ {
+ QString szMsgText = msg->connection()->decodeText(msg->safeTrailing());
+ QString szSpamWord = spamWord.ptr();
+ console->output(KVI_OUT_SPAM,__tr2qs("Spam notice from \r!n\r%Q\r [%Q@\r!h\r%Q\r]: %Q (matching spamword \"%Q\")"),
+ &szNick,&szUser,&szHost,&szMsgText,&szSpamWord);
+ }
+ return;
+ }
+ }
+ }
+
+ // this is not a spam, or at least it hasn't been recognized as spam
+
+ // user option ? (this should again override any script)
+ // if the scripters want really to force the query creation they can do
+ // it manually or they can set the option to true at KVIrc startup
+ if(KVI_OPTION_BOOL(KviOption_boolCreateQueryOnNotice))
+ {
+ QString szMsgText = msg->connection()->decodeText(msg->safeTrailing());
+ // We still want to create it
+ // Give the scripter a chance to filter it out again
+ if(KVS_TRIGGER_EVENT_4_HALTED(KviEvent_OnQueryWindowRequest,console,szNick,szUser,szHost,szMsgText))
+ {
+ // check if the scripter hasn't created it
+ query = msg->connection()->findQuery(szNick);
+ } else {
+ // no query yet, create it!
+ // this will trigger OnQueryWindowCreated
+ query = console->connection()->createQuery(szNick);
+ // and this will trigger OnQueryTargetAdded
+ query->setTarget(szNick,szUser,szHost);
+ }
+ }
+ }
+
+ // ok, now we either have a query or not
+ if(query)
+ {
+ // ok, we have the query. Trigger the user action anyway
+ query->userAction(szNick,szUser,szHost,KVI_USERACTION_NOTICE);
+ // decrypt it if needed
+ KviStr szBuffer; const char * txtptr; int msgtype;
+ DECRYPT_IF_NEEDED(query,msg->safeTrailing(),KVI_OUT_QUERYNOTICE,KVI_OUT_QUERYNOTICECRYPTED,szBuffer,txtptr,msgtype)
+ QString szMsgText = query->decodeText(txtptr);
+ // trigger the script event and eventually kill the output
+ if(KVS_TRIGGER_EVENT_4_HALTED(KviEvent_OnQueryNotice,query,szNick,szUser,szHost,szMsgText))
+ msg->setHaltOutput();
+ // spit out the message text
+ if(!msg->haltOutput())
+ {
+ int iFlags = 0;
+
+ if(!query->hasAttention())
+ {
+ if(KVI_OPTION_BOOL(KviOption_boolFlashQueryWindowOnNewMessages))
+ {
+ // avoid double window flashing
+ iFlags |= KviConsole::NoWindowFlashing;
+ query->demandAttention();
+ }
+ if(KVI_OPTION_BOOL(KviOption_boolPopupNotifierOnNewQueryMessages))
+ {
+ // don't send the message twice to the notifier
+ iFlags |= KviConsole::NoNotifier;
+ #ifdef COMPILE_USE_QT4
+ QString szMsg = Qt::escape(szMsgText);
+ #else
+ QString szMsg = QStyleSheet::escape(szMsgText);
+ #endif
+ //debug("kvi_sp_literal.cpp:908 debug: %s",szMsg.data());
+ g_pApp->notifierMessage(query,KVI_SMALLICON_QUERYNOTICE,szMsg,1800);
+ }
+ }
+
+ console->outputPrivmsg(query,msgtype,szNick,szUser,szHost,szMsgText,iFlags);
+ }
+ } else {
+ QString szMsgText = msg->connection()->decodeText(msg->safeTrailing());
+ // no query creation: no decryption possible
+ // trigger the query message event in the console
+ if(KVS_TRIGGER_EVENT_4_HALTED(KviEvent_OnQueryNotice,console,szNick,szUser,szHost,szMsgText))
+ msg->setHaltOutput();
+ // spit the message text out
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolExternalMessagesToActiveWindow) ?
+ console->activeWindow() : (KviWindow *)(console);
+
+ if(KviIrcConnection * pConnection = console->connection())
+ {
+ KviWindow * aWin = console->activeWindow();
+ if((aWin->type() == KVI_WINDOW_TYPE_CHANNEL) && ((KviChannel *)aWin)->isOn(szNick))
+ pOut = aWin;
+ else {
+ for(KviChannel * c = pConnection->channelList()->first();c;c = pConnection->channelList()->next())
+ if(c->isOn(szNick))
+ {
+ pOut = (KviWindow *) c;
+ break;
+ }
+ }
+ }
+
+ pOut->output(KVI_OUT_QUERYNOTICE,"*\r!n\r%Q\r* %Q",&szNick,&szMsgText);
+ }
+ }
+ return;
+ }
+
+ // Channel NOTICE
+ KviChannel * chan = msg->connection()->findChannel(szTarget);
+
+ QString szOriginalTarget = szTarget;
+ QString szPrefixes;
+
+ if(!chan)
+ {
+ // check if the channel has some leading mode prefixes
+ while((szTarget.length() > 0) && console->connection()->serverInfo()->isSupportedModePrefix(szTarget[0].unicode()))
+ {
+ szPrefixes += szTarget[0];
+ szTarget.remove(0,1);
+ }
+ chan = msg->connection()->findChannel(szTarget);
+ }
+
+ if(!chan)
+ {
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolOperatorMessagesToActiveWindow) ?
+ console->activeWindow() : (KviWindow *)(console);
+ QString szBroad;
+ QString szMsgText = msg->connection()->decodeText(msg->safeTrailing());
+ KviQString::sprintf(szBroad,"[>> %Q] %Q",&szOriginalTarget,&szMsgText);
+ console->outputPrivmsg(pOut,KVI_OUT_BROADCASTNOTICE,szNick,szUser,szHost,szBroad,0);
+ return;
+ }
+ } else {
+ chan->userAction(szNick,szUser,szHost,KVI_USERACTION_NOTICE);
+
+ KviStr szBuffer; const char * txtptr; int msgtype;
+ DECRYPT_IF_NEEDED(chan,msg->safeTrailing(),KVI_OUT_CHANNELNOTICE,KVI_OUT_CHANNELNOTICECRYPTED,szBuffer,txtptr,msgtype)
+ QString szMsgText = chan->decodeText(txtptr);
+
+ if(KVS_TRIGGER_EVENT_3_HALTED(KviEvent_OnChannelNotice,chan,szNick,szMsgText,szOriginalTarget))msg->setHaltOutput();
+
+ if(!msg->haltOutput())
+ {
+ if(szPrefixes.length() > 0)
+ {
+ QString szBroad;
+ KviQString::sprintf(szBroad,"[>> %Q\r!c\r%Q\r] %Q",&szPrefixes,&szTarget,&szMsgText);
+ console->outputPrivmsg(chan,msgtype,szNick,szUser,szHost,szBroad,0);
+ } else {
+ console->outputPrivmsg(chan,msgtype,szNick,szUser,szHost,szMsgText,0);
+ }
+ }
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// TOPIC
+//
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void KviServerParser::parseLiteralTopic(KviIrcMessage *msg)
+{
+ // TOPIC
+ // :<source_mask> TOPIC <channel> :<topic>
+ QString szNick,szUser,szHost;
+ msg->decodeAndSplitPrefix(szNick,szUser,szHost);
+ QString szTarget = msg->connection()->decodeText(msg->safeParam(0));
+
+ // Now lookup the channel
+ KviChannel * chan = msg->connection()->findChannel(szTarget);
+
+ if(!chan)
+ {
+ UNRECOGNIZED_MESSAGE(msg,__tr2qs("Received a topic message for an unknown channel, possible desync"));
+ return;
+ }
+
+ QString szTopic = chan->decodeText(msg->safeTrailing());
+
+ if(KVS_TRIGGER_EVENT_4_HALTED(KviEvent_OnTopic,chan,szNick,szUser,szHost,szTopic))
+ msg->setHaltOutput();
+
+ chan->topicWidget()->setTopic(szTopic);
+ chan->topicWidget()->setTopicSetBy(szNick);
+ QString tmp = QDateTime::currentDateTime().toString();
+ chan->topicWidget()->setTopicSetAt(tmp);
+
+ chan->userAction(szNick,szUser,szHost,KVI_USERACTION_TOPIC);
+
+ if(!msg->haltOutput())
+ {
+ chan->output(KVI_OUT_TOPIC,
+ __tr2qs("\r!n\r%Q\r [%Q@\r!h\r%Q\r] has changed topic to \"%Q%c\""),
+ &szNick,&szUser,&szHost,&szTopic,KVI_TEXT_RESET);
+ }
+}
+
+void KviServerParser::parseLiteralNick(KviIrcMessage *msg)
+{
+ // NICK
+ // :source NICK <newnick>
+ QString szNick,szUser,szHost;
+ msg->decodeAndSplitPrefix(szNick,szUser,szHost);
+ KviConsole * console = msg->console();
+ QString szNewNick = msg->connection()->decodeText(msg->safeTrailing());
+
+ bool bIsMe = IS_ME(msg,szNick);
+
+ if(bIsMe)
+ {
+ // We have changed our nick
+ msg->connection()->nickChange(szNewNick);
+
+ if(KVS_TRIGGER_EVENT_2_HALTED(KviEvent_OnMeNickChange,console,szNick,szNewNick))
+ msg->setHaltOutput();
+ } else {
+ if(KVS_TRIGGER_EVENT_4_HALTED(KviEvent_OnNickChange,console,szNick,szUser,szHost,szNewNick))
+ msg->setHaltOutput();
+ }
+
+ for(KviChannel * c = console->channelList()->first();c;c = console->channelList()->next())
+ {
+ if(c->nickChange(szNick,szNewNick))
+ {
+ if(!msg->haltOutput())
+ c->output(KVI_OUT_NICK,__tr2qs("\r!n\r%Q\r [%Q@\r!h\r%Q\r] is now known as \r!n\r%Q\r"),
+ &szNick,&szUser,&szHost,&szNewNick);
+ // FIXME if(bIsMe)output(YOU ARE now known as.. ?)
+ }
+ if(bIsMe)c->updateCaption();
+ }
+
+
+ // FIXME: #warning "NEW NICK MIGHT BE REGISTERED AND HAVE AN AVATAR!"
+
+ if(bIsMe)
+ {
+ // just update all the captions : we have changed OUR nick
+ for(KviQuery * q = console->queryList()->first();q;q = console->queryList()->next())
+ {
+ if(!msg->haltOutput())
+ q->output(KVI_OUT_NICK,__tr2qs("You have changed your nickname to %Q"),&szNewNick);
+ q->updateCaption();
+ }
+ }
+ KviQuery * q = console->connection()->findQuery(szNick);
+ // It CAN happen that szNewNick first queries us without being
+ // on any channel then he QUITS , he reconnects , he joins
+ // a channel with szNick , queries us and changes nick to szNewNick : gotcha!
+ // should merge the queries!
+ KviQuery * old = console->connection()->findQuery(szNewNick);
+ if(old && (old != q))
+ {
+ if(KVI_OPTION_BOOL(KviOption_boolEnableQueryTracing) && (!_OUTPUT_QUIET))
+ {
+ old->output(KVI_OUT_QUERYTRACE,
+ __tr2qs("The target of this query was lost and has been found when \r!n\r%Q\r [%Q@\r!h\r%Q\r] changed his nickname to \r!n\r%Q\r"),
+ &szNick,&szUser,&szHost,&szNewNick);
+ }
+ if(q)
+ {
+ bool bQWasActive = (q == g_pActiveWindow);
+ if(!_OUTPUT_MUTE)
+ {
+ old->output(KVI_OUT_SYSTEMWARNING,
+ __tr2qs("The recent nickname change from \r!n\r%Q\r to \r!n\r%Q\r caused a query collision: merging output"),
+ &szNick,&szNewNick);
+ }
+ old->mergeQuery(q);
+ q->frame()->closeWindow(q); // deleted path
+ if(!msg->haltOutput())
+ old->output(KVI_OUT_NICK,__tr2qs("\r!n\r%Q\r [%Q@\r!h\r%Q\r] is now known as \r!n\r%Q\r"),
+ &szNick,&szUser,&szHost,&szNewNick);
+ if(!_OUTPUT_MUTE)
+ old->output(KVI_OUT_SYSTEMWARNING,__tr2qs("End of merged output"));
+ old->userAction(szNewNick,szUser,szHost,KVI_USERACTION_NICK);
+ if(bQWasActive)old->delayedAutoRaise();
+ }
+ if(KVI_OPTION_BOOL(KviOption_boolEnableQueryTracing))
+ {
+ QString szChans;
+ int iChans = console->connection()->getCommonChannels(szNewNick,szChans);
+ old->notifyCommonChannels(szNewNick,szUser,szHost,iChans,szChans);
+ }
+ } else {
+ if(q)
+ {
+ // the target SHOULD have changed his nick here
+ if(!q->nickChange(szNick,szNewNick))
+ debug("Internal error: query %s failed to change nick from %s to s",szNick.utf8().data(),szNick.utf8().data(),szNewNick.utf8().data());
+ if(!msg->haltOutput())
+ q->output(KVI_OUT_NICK,__tr2qs("\r!n\r%Q\r [%Q@\r!h\r%Q\r] is now known as \r!n\r%Q\r"),
+ &szNick,&szUser,&szHost,&szNewNick);
+ q->userAction(szNewNick,szUser,szHost,KVI_USERACTION_NICK);
+ }
+ }
+
+// FIXME: #warning "UPDATE ALL THE OTHER CONNECTION RELATED WINDOW CAPTIONS WHEN bIsMe!!"
+}
+
+void KviServerParser::parseLiteralInvite(KviIrcMessage *msg)
+{
+ // INVITE
+ // :source INVITE <target> <channel>
+ QString szNick,szUser,szHost;
+ msg->decodeAndSplitPrefix(szNick,szUser,szHost);
+
+ QString szTarget = msg->connection()->decodeText(msg->safeParam(0));
+ QString szChannel = msg->connection()->decodeText(msg->safeParam(1));
+
+ KviConsole * console = msg->console();
+ KviRegisteredUser * u = msg->connection()->userDataBase()->registeredUser(szNick,szUser,szHost);
+ //Ignore it?
+ if(u)
+ {
+ if(u->isIgnoreEnabledFor(KviRegisteredUser::Invite))
+ {
+ if(KVI_OPTION_BOOL(KviOption_boolVerboseIgnore))
+ {
+ console->output(KVI_OUT_IGNORE,__tr2qs("Ignoring invite from \r!nc\r%Q\r [%Q@\r!h\r%Q\r]"),&szNick,&szUser,&szHost);
+ }
+ return;
+ }
+ }
+
+ if(IS_ME(msg,szTarget))
+ {
+ if(KVS_TRIGGER_EVENT_4_HALTED(KviEvent_OnInvite,msg->console(),szNick,szUser,szHost,szChannel))
+ msg->setHaltOutput();
+
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolInvitesToActiveWindow) ?
+ msg->console()->activeWindow() : (KviWindow *)(msg->console());
+ QString szAction = KVI_OPTION_BOOL(KviOption_boolAutoJoinOnInvite) ? __tr2qs("autojoining") : __tr2qs("double-click the channel name to join");
+ pOut->output(KVI_OUT_INVITE,__tr2qs("\r!n\r%Q\r [%Q@\r!h\r%Q\r] invites you to channel \r!c\r%Q\r (%Q)"),
+ &szNick,&szUser,&szHost,&szChannel,&szAction);
+ }
+
+ if(KVI_OPTION_BOOL(KviOption_boolAutoJoinOnInvite))
+ msg->connection()->sendFmtData("JOIN %s",msg->safeParam(1));
+
+ } else {
+ UNRECOGNIZED_MESSAGE(msg,__tr("Received an invite message directed to another nick, possible desync"));
+ }
+}
+
+void KviServerParser::parseLiteralWallops(KviIrcMessage *msg)
+{
+ // WALLOPS
+ // :source WALLOPS :msg
+ QString szNick,szUser,szHost;
+ msg->decodeAndSplitPrefix(szNick,szUser,szHost);
+
+ QString szMsg = msg->connection()->decodeText(msg->safeTrailing());
+
+ if(KVS_TRIGGER_EVENT_4_HALTED(KviEvent_OnWallops,msg->console(),szNick,szUser,szHost,szMsg))
+ msg->setHaltOutput();
+
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolOperatorMessagesToActiveWindow) ?
+ msg->console()->activeWindow() : (KviWindow *)(msg->console());
+ pOut->output(KVI_OUT_WALLOPS,__tr2qs("WALLOPS from \r!n\r%Q\r [%Q@\r!h\r%Q\r]: %Q"),
+ &szNick,&szUser,&szHost,&szMsg);
+ }
+}
+
+void KviServerParser::parseUserMode(KviIrcMessage *msg,const char * modeflptr)
+{
+ // changed my user mode
+ bool bSet = true;
+ while(*modeflptr)
+ {
+ switch(*modeflptr)
+ {
+ case '+': bSet = true; break;
+ case '-': bSet = false; break;
+ default:
+ if(msg->connection()->changeUserMode(*modeflptr,bSet))
+ {
+ if(msg->connection()->serverInfo()->registerModeChar()==*modeflptr)
+ {
+ KviKvsVariantList vList;
+ KviKvsEventManager::instance()->trigger(KviEvent_OnNickServAuth,msg->console(),&vList);
+ }
+ // There was a mode change
+ if(KviKvsEventManager::instance()->hasAppHandlers(KviEvent_OnUserMode))
+ {
+ QString szModeFlag(bSet ? QChar('+') : QChar('-'));
+ szModeFlag += QChar(*modeflptr);
+ KviKvsVariantList vList(new KviKvsVariant(szModeFlag));
+ if(KviKvsEventManager::instance()->trigger(KviEvent_OnUserMode,msg->console(),&vList))
+ msg->setHaltOutput();
+ }
+ }
+ break;
+ }
+ ++modeflptr;
+ }
+}
+
+
+
+void KviServerParser::parseLiteralMode(KviIrcMessage *msg)
+{
+ // NICK
+ // :source MODE target <params>
+ // :source MODE <me> +|-modeflag
+ // :source MODE <channel> +-modeflags [parameters]
+ QString szNick,szUser,szHost;
+ msg->decodeAndSplitPrefix(szNick,szUser,szHost);
+
+ // if(!source.hasHost())
+ // {
+ // // This is a server or a channel service
+ // KviStr snick = source.nick();
+ // if(snick.contains('.'))source.setHost(source.nick()); // this is a server
+ // }
+
+ QString szTarget = msg->connection()->decodeText(msg->safeParam(0));
+ KviStr modefl(msg->safeParam(1));
+
+ if(IS_ME(msg,szTarget))
+ {
+ parseUserMode(msg,modefl.ptr());
+ if(!msg->haltOutput())
+ msg->console()->output(KVI_OUT_MODE,__tr2qs("You have set user mode %s"),modefl.ptr());
+ } else {
+ // a channel mode
+ KviChannel * chan = msg->connection()->findChannel(szTarget);
+
+ if(!chan){
+ // Ooops , desync with the server.
+ UNRECOGNIZED_MESSAGE(msg,__tr("Received a mode change for an unknown channel, possible desync"));
+ return;
+ }
+
+ chan->userAction(szNick,szUser,szHost,KVI_USERACTION_CHANMODE);
+ parseChannelMode(szNick,szUser,szHost,chan,modefl,msg,2);
+ }
+}
+
+void KviServerParser::parseChannelMode(const QString &szNick,const QString &szUser,const QString &szHost,KviChannel * chan,KviStr &modefl,KviIrcMessage *msg,int curParam)
+{
+ // FIXME: freenode has two ugly incompatible extensions:
+ // mode e: that is NOT viewable (???)
+ // mode q that stands for "quiet-ban"
+ // mode #chan +q mask
+ // adds mask to the banlist with the prefix %
+ // and doesn't allow the users matching the mask to talk to the channel
+
+ bool bSet = true;
+ const char * aux = modefl.ptr();
+ QString aParam;
+
+ QString nickBuffer;
+ QString hostBuffer;
+
+ if(szHost != "*")
+ {
+ KviQString::sprintf(nickBuffer,"\r!n\r%Q\r",&szNick);
+ KviQString::sprintf(hostBuffer,"\r!h\r%Q\r",&szHost);
+ } else {
+ if(nickBuffer.find('.') != -1)
+ {
+ // This looks a lot like a server!
+ KviQString::sprintf(nickBuffer,"\r!s\r%Q\r",&szNick);
+ } else {
+ // Probably a service....whois should work
+ KviQString::sprintf(nickBuffer,"\r!n\r%Q\r",&szNick);
+ }
+ hostBuffer = szHost;
+ }
+
+ KviIrcMask * auxMask;
+
+ int curParamSave = curParam;
+ bool bIsMe;
+
+ //FIXME: Use PREFIX in 005 numeric instead of bServerSupportsModeIe - get rid of it altogether
+ //bool bModeIe = console->connection()->serverInfo()->supportsModesIe();
+
+
+ while(*aux)
+ {
+ switch(*aux)
+ {
+ case '+':
+ bSet = true;
+ break;
+ case '-':
+ bSet = false;
+ break;
+ case 'k':
+ if(bSet)aParam = msg->safeParam(curParam++);
+ else aParam = "";
+ chan->setChannelKey(aParam);
+
+ if(bSet) {
+ if(KVS_TRIGGER_EVENT_4_HALTED(KviEvent_OnKeySet,chan,szNick,szUser,szHost,aParam))
+ msg->setHaltOutput();
+ } else {
+ if(KVS_TRIGGER_EVENT_3_HALTED(KviEvent_OnKeyUnset,chan,szNick,szUser,szHost))
+ msg->setHaltOutput();
+ }
+
+ if(!(msg->haltOutput() || KVI_OPTION_BOOL(KviOption_boolShowCompactModeChanges)))
+ {
+ if(bSet)chan->output(KVI_OUT_KEY,
+ __tr2qs("%Q [%Q@%Q] has set channel key to \"\r!m-k\r%Q\r\""),
+ &nickBuffer,&szUser,&hostBuffer,&aParam);
+ else chan->output(KVI_OUT_KEY,
+ __tr2qs("%Q [%Q@%Q] has unset the channel key"),
+ &nickBuffer,&szUser,&hostBuffer);
+ }
+ break;
+ case 'l':
+ if(bSet)aParam = msg->safeParam(curParam++);
+ else aParam = "";
+ chan->setChannelLimit(aParam);
+
+ if(bSet) {
+ if(KVS_TRIGGER_EVENT_4_HALTED(KviEvent_OnLimitSet,chan,szNick,szUser,szHost,aParam))
+ msg->setHaltOutput();
+ } else {
+ if(KVS_TRIGGER_EVENT_3_HALTED(KviEvent_OnLimitUnset,chan,szNick,szUser,szHost))
+ msg->setHaltOutput();
+ }
+
+ if(!(msg->haltOutput() || KVI_OPTION_BOOL(KviOption_boolShowCompactModeChanges)))
+ {
+ if(bSet)chan->output(KVI_OUT_LIMIT,
+ __tr2qs("%Q [%Q@%Q] has set channel \r!m-l\rlimit to %Q\r"),
+ &nickBuffer,&szUser,&hostBuffer,&aParam);
+ else chan->output(KVI_OUT_LIMIT,
+ __tr2qs("%Q [%Q@%Q] has unset the channel limit"),
+ &nickBuffer,&szUser,&hostBuffer);
+ }
+ break;
+
+#define CHANUSER_MODE(__modechar,__chanfunc,__evmeset,__evmeunset,__evset,__evunset,__icomeset,__icomeunset,__icoset,__icounset) \
+ case __modechar: \
+ if(msg->connection()->serverInfo()->isSupportedModeFlag(__modechar)) \
+ { \
+ aParam = msg->connection()->decodeText(msg->safeParam(curParam++)); \
+ chan->__chanfunc(aParam,bSet); \
+ bIsMe = IS_ME(msg,aParam); \
+ if(bIsMe) \
+ { \
+ if(KVS_TRIGGER_EVENT_3_HALTED(bSet ? __evmeset : __evmeunset,chan,szNick,szUser,szHost))msg->setHaltOutput(); \
+ chan->updateCaption(); \
+ } else { \
+ if(KVS_TRIGGER_EVENT_4_HALTED(bSet ? __evset : __evunset,chan,szNick,szUser,szHost,aParam))msg->setHaltOutput(); \
+ } \
+ if(!(msg->haltOutput() || KVI_OPTION_BOOL(KviOption_boolShowCompactModeChanges))) \
+ { \
+ chan->output(bSet ? (bIsMe ? __icomeset : __icoset) : (bIsMe ? __icomeunset : __icounset), \
+ __tr2qs("%Q [%Q@%Q] has set mode %c%c \r!n\r%Q\r"), \
+ &nickBuffer,&szUser,&hostBuffer,bSet ? '+' : '-',__modechar,&aParam); \
+ } \
+ } else {\
+ chan->setChannelMode(__modechar,bSet);\
+ if(!(msg->haltOutput() || KVI_OPTION_BOOL(KviOption_boolShowCompactModeChanges)))\
+ {\
+ chan->output(KVI_OUT_CHANMODE,\
+ __tr2qs("%Q [%Q@%Q] has set channel \r!m%c%c\rmode %c%c\r"),\
+ &nickBuffer,&szUser,&hostBuffer,\
+ bSet ? '-' : '+',__modechar,bSet ? '+' : '-',__modechar);\
+ }\
+ }\
+ break;
+ CHANUSER_MODE('q',setChanOwner,KviEvent_OnMeChanOwner,KviEvent_OnMeDeChanOwner,KviEvent_OnChanOwner,KviEvent_OnDeChanOwner,KVI_OUT_MECHANOWNER,KVI_OUT_MEDECHANOWNER,KVI_OUT_CHANOWNER,KVI_OUT_DECHANOWNER)
+ CHANUSER_MODE('a',setChanAdmin,KviEvent_OnMeChanAdmin,KviEvent_OnMeDeChanAdmin,KviEvent_OnChanAdmin,KviEvent_OnDeChanAdmin,KVI_OUT_MECHANADMIN,KVI_OUT_MEDECHANADMIN,KVI_OUT_CHANADMIN,KVI_OUT_DECHANADMIN)
+ CHANUSER_MODE('o',op,KviEvent_OnMeOp,KviEvent_OnMeDeOp,KviEvent_OnOp,KviEvent_OnDeOp,KVI_OUT_MEOP,KVI_OUT_MEDEOP,KVI_OUT_OP,KVI_OUT_DEOP)
+ CHANUSER_MODE('h',halfop,KviEvent_OnMeHalfOp,KviEvent_OnMeDeHalfOp,KviEvent_OnHalfOp,KviEvent_OnDeHalfOp,KVI_OUT_MEHALFOP,KVI_OUT_MEDEHALFOP,KVI_OUT_HALFOP,KVI_OUT_HALFDEOP)
+ CHANUSER_MODE('v',voice,KviEvent_OnMeVoice,KviEvent_OnMeDeVoice,KviEvent_OnVoice,KviEvent_OnDeVoice,KVI_OUT_MEVOICE,KVI_OUT_MEDEVOICE,KVI_OUT_VOICE,KVI_OUT_DEVOICE)
+ CHANUSER_MODE('u',userop,KviEvent_OnMeUserOp,KviEvent_OnMeDeUserOp,KviEvent_OnUserOp,KviEvent_OnDeUserOp,KVI_OUT_MEUSEROP,KVI_OUT_MEDEUSEROP,KVI_OUT_USEROP,KVI_OUT_USERDEOP)
+
+#define CHANNEL_MODE(__modefl,__evmeset,__evmeunset,__evset,__evunset,__icomeset,__icomeunset,__icoset,__icounset) \
+ case __modefl: \
+ aParam = msg->connection()->decodeText(msg->safeParam(curParam++)); \
+ chan->setMask(*aux,aParam,bSet,msg->connection()->decodeText(msg->safePrefix()),QDateTime::currentDateTime().toTime_t()); \
+ auxMask = new KviIrcMask(aParam); \
+ bIsMe = auxMask->matchesFixed( \
+ msg->connection()->userInfo()->nickName(), \
+ msg->connection()->userInfo()->userName(), \
+ msg->connection()->userInfo()->hostName()); \
+ delete auxMask; \
+ if(bIsMe) \
+ { \
+ if(KVS_TRIGGER_EVENT_4_HALTED(bSet ? __evmeset : __evmeunset,chan,szNick,szUser,szHost,aParam))msg->setHaltOutput(); \
+ } else { \
+ if(KVS_TRIGGER_EVENT_4_HALTED(bSet ? __evset : __evunset,chan,szNick,szUser,szHost,aParam))msg->setHaltOutput(); \
+ } \
+ if(!(msg->haltOutput() || KVI_OPTION_BOOL(KviOption_boolShowCompactModeChanges))) \
+ { \
+ chan->output(bSet ? (bIsMe ? __icomeset : __icoset) : (bIsMe ? __icomeunset : __icounset), \
+ __tr2qs("%Q [%Q@%Q] has set mode %c%c \r!m%c%c\r%Q\r"), \
+ &nickBuffer,&szUser,&hostBuffer, \
+ bSet ? '+' : '-',__modefl,bSet ? '-' : '+',__modefl,&aParam); \
+ } \
+ break;
+
+ CHANNEL_MODE('b',KviEvent_OnMeBan,KviEvent_OnMeUnban,KviEvent_OnBan,KviEvent_OnUnban,KVI_OUT_MEBAN,KVI_OUT_MEUNBAN,KVI_OUT_BAN,KVI_OUT_UNBAN)
+ CHANNEL_MODE('I',KviEvent_OnMeInviteException,KviEvent_OnMeInviteExceptionRemove,KviEvent_OnInviteException,KviEvent_OnInviteExceptionRemove,KVI_OUT_MEINVITEEXCEPT,KVI_OUT_MEINVITEUNEXCEPT,KVI_OUT_INVITEEXCEPT,KVI_OUT_INVITEUNEXCEPT)
+ CHANNEL_MODE('e',KviEvent_OnMeBanException,KviEvent_OnMeBanExceptionRemove,KviEvent_OnBanException,KviEvent_OnBanExceptionRemove,KVI_OUT_MEBANEXCEPT,KVI_OUT_MEBANUNEXCEPT,KVI_OUT_BANEXCEPT,KVI_OUT_BANUNEXCEPT)
+
+ default:
+ chan->setChannelMode(*aux,bSet);
+ if(!(msg->haltOutput() || KVI_OPTION_BOOL(KviOption_boolShowCompactModeChanges)))
+ {
+ chan->output(KVI_OUT_CHANMODE,
+ __tr2qs("%Q [%Q@%Q] has set channel \r!m%c%c\rmode %c%c\r"),
+ &nickBuffer,&szUser,&hostBuffer,
+ bSet ? '-' : '+',*aux,bSet ? '+' : '-',*aux);
+ }
+ break;
+ }
+ ++aux;
+ }
+
+ QString param;
+ QString params;
+ param = msg->connection()->decodeText(msg->safeParam(curParamSave++));
+ while(!param.isEmpty())
+ {
+ if(!params.isEmpty())params.append(' ');
+ params.append(param);
+ param = msg->connection()->decodeText(msg->safeParam(curParamSave++));
+ }
+
+ if(KVS_TRIGGER_EVENT_5_HALTED(KviEvent_OnChannelModeChange,chan,szNick,szUser,szHost,modefl.ptr(),params))
+ msg->setHaltOutput();
+
+ if(KVI_OPTION_BOOL(KviOption_boolShowCompactModeChanges) && (!msg->haltOutput()) && (!kvi_strEqualCS(modefl.ptr(),"+")))
+ {
+ if(!params.isEmpty())
+ {
+ chan->output(KVI_OUT_CHANMODE,__tr2qs("%Q [%Q@%Q] has set mode %s %Q"),
+ &nickBuffer,&szUser,&hostBuffer,modefl.ptr(),&params);
+ } else {
+ chan->output(KVI_OUT_CHANMODE,__tr2qs("%Q [%Q@%Q] has set channel mode %s"),
+ &nickBuffer,&szUser,&hostBuffer,modefl.ptr());
+ }
+ }
+}
diff --git a/src/kvirc/sparser/kvi_sp_numeric.cpp b/src/kvirc/sparser/kvi_sp_numeric.cpp
new file mode 100644
index 00000000..a4481e88
--- /dev/null
+++ b/src/kvirc/sparser/kvi_sp_numeric.cpp
@@ -0,0 +1,2003 @@
+//=============================================================================
+//
+// File : kvi_sp_numeric.cpp
+// Creation date : Thu Aug 3 2000 01:30:45 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_sparser.h"
+#include "kvi_window.h"
+#include "kvi_query.h"
+#include "kvi_out.h"
+#include "kvi_locale.h"
+#include "kvi_ircsocket.h"
+#include "kvi_options.h"
+#include "kvi_channel.h"
+#include "kvi_topicw.h"
+#include "kvi_ircuserdb.h"
+#include "kvi_defaults.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_frame.h"
+#include "kvi_parameterlist.h"
+#include "kvi_app.h"
+#include "kvi_notifylist.h"
+#include "kvi_numeric.h"
+#include "kvi_ircconnection.h"
+#include "kvi_ircconnectionstatedata.h"
+#include "kvi_ircconnectionuserinfo.h"
+#include "kvi_ircconnectionserverinfo.h"
+#include "kvi_ircconnectionasyncwhoisdata.h"
+#include "kvi_ircconnectiontarget.h"
+#include "kvi_time.h"
+#include "kvi_lagmeter.h"
+#include "kvi_qcstring.h"
+
+#include <qpixmap.h>
+#include <qdatetime.h>
+#include <qtextcodec.h>
+#include <qregexp.h>
+
+#include "kvi_kvs_eventtriggers.h"
+#include "kvi_kvs_script.h"
+#include "kvi_kvs_variantlist.h"
+
+// #define IS_CHANNEL_TYPE_FLAG(_str) ((*(_str) == '#') || (*(_str) == '&') || (*(_str) == '!'))
+#define IS_CHANNEL_TYPE_FLAG(_qchar) (msg->connection()->serverInfo()->supportedChannelTypes().find(_qchar) != -1)
+#define IS_USER_MODE_PREFIX(_qchar) (msg->connection()->serverInfo()->supportedModePrefixes().find(_qchar) != -1)
+
+// Numeric message handlers
+
+// FIXME: #warning "IN ALL OUTPUT ADD ESCAPE SEQUENCES!!!!"
+// FIXME: #warning "parseErrorUnknownModeChar() for modes e and I , parseErrorUnknownCommand for WATCH"
+
+void KviServerParser::parseNumeric001(KviIrcMessage *msg)
+{
+ // 001: RPL_WELCOME
+ // :prefix 001 target :Welcome to the Internet Relay Network <usermask>
+ // FIXME: #warning "SET THE USERMASK FROM SERVER"
+ QString szText = msg->connection()->decodeText(msg->safeTrailing());
+ QRegExp rx( " ([^ ]+)!([^ ]+)@([^ ]+)$" );
+ if( rx.search(szText) != -1)
+ {
+ msg->connection()->userInfo()->setUnmaskedHostName(rx.cap(3));
+ msg->connection()->userInfo()->setNickName(rx.cap(1));
+ msg->connection()->userInfoReceived(rx.cap(2),rx.cap(3));
+ }
+ if(msg->connection()->context()->state() != KviIrcContext::Connected)
+ msg->connection()->loginComplete(msg->connection()->decodeText(msg->param(0)));
+ if(!msg->haltOutput())
+ msg->console()->outputNoFmt(KVI_OUT_SERVERINFO,szText);
+}
+
+void KviServerParser::parseNumeric002(KviIrcMessage *msg)
+{
+ // 002: RPL_YOURHOST [I,E,U,D]
+ // :prefix 002 target :Your host is <server name>, running version <server version>
+ if(msg->connection()->context()->state() != KviIrcContext::Connected)
+ msg->connection()->loginComplete(msg->connection()->decodeText(msg->param(0)));
+ if(!msg->haltOutput())msg->console()->outputNoFmt(KVI_OUT_SERVERINFO,msg->connection()->decodeText(msg->safeTrailing()));
+}
+
+void KviServerParser::parseNumeric003(KviIrcMessage *msg)
+{
+ // 003: RPL_CREATED [I,E,U,D]
+ // :prefix 003 target :This server was created <date>
+ if(msg->connection()->context()->state() != KviIrcContext::Connected)
+ msg->connection()->loginComplete(msg->connection()->decodeText(msg->param(0)));
+ if(!msg->haltOutput())msg->console()->outputNoFmt(KVI_OUT_SERVERINFO,msg->connection()->decodeText(msg->safeTrailing()));
+}
+
+void KviServerParser::parseNumeric004(KviIrcMessage *msg)
+{
+ // 004: RPL_MYINFO [I,E,U,D]
+ // :prefix 004 target <server_name> <srv_version> <u_modes> <ch_modes>
+ if(msg->connection()->context()->state() != KviIrcContext::Connected)
+ msg->connection()->loginComplete(msg->connection()->decodeText(msg->param(0)));
+
+ int uParams = msg->paramCount();
+ int uModeParam = 3;
+
+ if(uParams < 2)uParams = 2;
+
+ KviStr version = msg->safeParam(2);
+ msg->connection()->serverInfo()->setServerVersion(msg->safeParam(2));
+
+ KviStr umodes;
+ // skip version number (great, thanks WEBMASTER INCORPORATED -_-)
+ do
+ {
+ umodes = msg->safeParam(uModeParam);
+ } while (((umodes.contains('.')) || (umodes.contains('-'))) && uModeParam++ < uParams);
+
+ KviStr chanmodes = msg->safeParam(uModeParam+1);
+
+ if(uModeParam > 3)
+ {
+ version.append(' ');
+ version.append(msg->safeParam(3));
+ }
+
+ if((umodes.occurences('o') != 1) || (chanmodes.occurences('o') != 1) ||
+ (chanmodes.occurences('b') != 1) || (chanmodes.occurences('v') != 1) ||
+ (chanmodes.occurences('t') != 1) || (chanmodes.occurences('n') != 1) ||
+ (chanmodes.contains('.')) || (chanmodes.contains('-')) || (chanmodes.contains('(')))
+ {
+ if(!_OUTPUT_QUIET)
+ {
+ msg->console()->output(KVI_OUT_SYSTEMWARNING,__tr2qs(
+ "One or more standard mode flags are missing in the server available modes.\n" \
+ "This is caused either by a non RFC1459-compliant IRC daemon or a broken server reply.\n" \
+ "Server umodes seem to be '%s' and channel modes seem to be '%s'.\n" \
+ "Ignoring this reply and assuming that the basic set of modes is available.\n" \
+ "If you have strange problems, try changing the server."),umodes.ptr(),chanmodes.ptr());
+ }
+ umodes = "oiws"; // standard support
+ chanmodes = "obtkmlvsn"; // standard support
+ }
+
+ if(KVI_OPTION_BOOL(KviOption_boolShowExtendedServerInfo) && (!msg->haltOutput()))
+ {
+ if(umodes.hasData())msg->console()->outputNoFmt(KVI_OUT_SERVERINFO,__tr2qs("Available user modes:"));
+
+ const char * aux = umodes.ptr();
+ QString tmp;
+
+ while(*aux)
+ {
+ tmp = msg->connection()->serverInfo()->getUserModeDescription(*aux);
+ if(tmp.isEmpty())
+ {
+ QString tmp2 = __tr2qs(": Unknown user mode");
+ KviQString::sprintf(tmp,"%c: %Q",*aux,&tmp2);
+ }
+
+ msg->console()->outputNoFmt(KVI_OUT_SERVERINFO,tmp);
+ aux++;
+ }
+
+ if(chanmodes.hasData())msg->console()->outputNoFmt(KVI_OUT_SERVERINFO,__tr2qs("Available channel modes:"));
+
+ aux = chanmodes.ptr();
+
+ while(*aux)
+ {
+ KviQString::sprintf(tmp,"%c: %Q",*aux,&(msg->connection()->serverInfo()->getChannelModeDescription(*aux)));
+ msg->console()->outputNoFmt(KVI_OUT_SERVERINFO,tmp);
+ aux++;
+ }
+ }
+
+ QString szServer = msg->connection()->decodeText(msg->safeParam(1));
+
+ msg->connection()->serverInfoReceived(szServer,umodes.ptr(),chanmodes.ptr());
+
+ // FIXME: #warning "TO ACTIVE ? OR TO CONSOLE ?"
+ if(!_OUTPUT_MUTE)
+ {
+ if(!msg->haltOutput())msg->console()->output(KVI_OUT_SERVERINFO,
+ __tr2qs("Server %Q version %S supporting user modes '%S' and channel modes '%S'"),
+ &szServer,&version,&umodes,&chanmodes);
+ }
+}
+
+void KviServerParser::parseNumeric005(KviIrcMessage *msg)
+{
+ // 005: RPL_PROTOCTL [D]
+ // :prefix 005 target <proto> <proto> .... :are available/supported on this server
+ // 005: RPL_BOUNCE [?]
+ // :prefix 005 target :Try server <server>, port <port>
+ // 005: RPL_ISUPPORT
+ if(msg->connection()->context()->state() != KviIrcContext::Connected)
+ msg->connection()->loginComplete(msg->connection()->decodeText(msg->param(0)));
+
+ bool bUhNames = false;
+ bool bNamesx = false;
+
+ unsigned int count = msg->paramCount();
+ if(count > 2)
+ {
+ count--;
+ for(unsigned int i = 1;i < count;i++)
+ {
+ const char * p = msg->param(i);
+ if(kvi_strEqualCIN("PREFIX=(",p,8))
+ {
+ p+=8;
+ const char * pModes = p;
+ while(*p && (*p != ')'))p++;
+ KviStr szModeFlags(pModes,p-pModes);
+ if(*p)p++;
+ KviStr szModePrefixes = p;
+ if(szModePrefixes.hasData() && (szModePrefixes.len() == szModeFlags.len()))
+ {
+ msg->connection()->serverInfo()->setSupportedModePrefixes(szModePrefixes.ptr(),szModeFlags.ptr());
+ }
+ } else if(kvi_strEqualCIN("CHANTYPES=",p,10))
+ {
+ p+=10;
+ KviStr tmp = p;
+ if(tmp.hasData())msg->connection()->serverInfo()->setSupportedChannelTypes(tmp.ptr());
+ } else if(kvi_strEqualCI("WATCH",p) || kvi_strEqualCIN("WATCH=",p,6))
+ {
+ msg->connection()->serverInfo()->setSupportsWatchList(true);
+ if((!_OUTPUT_MUTE) && (!msg->haltOutput()) && KVI_OPTION_BOOL(KviOption_boolShowExtendedServerInfo))
+ {
+ msg->console()->outputNoFmt(KVI_OUT_SERVERINFO,__tr2qs("This server supports the WATCH notify list method, it will be used"));
+ }
+ } else if(kvi_strEqualCIN("TOPICLEN=",p,9))
+ {
+ p += 9;
+ QString tmp = p;
+ if(!tmp.isEmpty()) {
+ bool ok;
+ int len = tmp.toInt( &ok );
+ if(ok) msg->connection()->serverInfo()->setMaxTopicLen(len);
+ }
+ } else if(kvi_strEqualCIN("NETWORK=",p,8))
+ {
+ p += 8;
+ QString tmp = p;
+ if(!tmp.isEmpty())msg->console()->connection()->target()->setNetworkName(tmp);
+ if((!_OUTPUT_MUTE) && (!msg->haltOutput()) && KVI_OPTION_BOOL(KviOption_boolShowExtendedServerInfo))
+ {
+ msg->console()->output(KVI_OUT_SERVERINFO,__tr2qs("The current network is %Q"),&tmp);
+ }
+ } else if(kvi_strEqualCI("CODEPAGES",p))
+ {
+ msg->connection()->serverInfo()->setSupportsCodePages(true);
+ if((!_OUTPUT_MUTE) && (!msg->haltOutput()) && KVI_OPTION_BOOL(KviOption_boolShowExtendedServerInfo))
+ {
+ msg->console()->outputNoFmt(KVI_OUT_SERVERINFO,__tr2qs("This server supports the CODEPAGE command, it will be used"));
+ }
+
+ //msg->connection()->sendFmtData("CODEPAGE %s",msg->console()->textCodec()->name());
+
+ } else if(kvi_strEqualCIN("CHANMODES=",p,10))
+ {
+ p+=10;
+ QString tmp = p;
+ msg->connection()->serverInfo()->setSupportedChannelModes(tmp);
+ }else if(kvi_strEqualCIN("MODES=",p,6))
+ {
+ p+=6;
+ QString tmp = p;
+ bool bok;
+ int num=tmp.toUInt(&bok);
+ if(bok)
+ msg->connection()->serverInfo()->setMaxModeChanges(num);
+ } else if(kvi_strEqualCIN("NAMESX",p,6))
+ {
+ p+=6;
+ bNamesx=true;
+ } else if(kvi_strEqualCIN("UHNAMES",p,7))
+ {
+ p+=7;
+ bUhNames=true;
+ }else if(kvi_strEqualCIN("CHARSET=",p,8))
+ {
+ p+=8;
+ QString tmp = p;
+ msg->connection()->serverInfo()->setSupportsCodePages(true);
+
+ if((!_OUTPUT_MUTE) && (!msg->haltOutput()) && KVI_OPTION_BOOL(KviOption_boolShowExtendedServerInfo))
+ {
+ msg->console()->outputNoFmt(KVI_OUT_SERVERINFO,__tr2qs("This server supports the CODEPAGE command, it will be used"));
+ }
+
+ /*if( tmp.contains(msg->console()->textCodec()->name(),false) || tmp.contains("*",false) )
+ {
+ msg->connection()->sendFmtData("CODEPAGE %s",msg->console()->textCodec()->name());
+ }*/
+ }
+ }
+ if((!_OUTPUT_MUTE) && (!msg->haltOutput()))
+ {
+ const char * aux = msg->allParams();
+ while(*aux == ' ')aux++;
+ while(*aux && (*aux != ' '))aux++;
+ while(*aux == ' ')aux++;
+ if(*aux == ':')aux++;
+ if(!msg->haltOutput())msg->console()->output(KVI_OUT_SERVERINFO,__tr2qs("This server supports: %s"),msg->connection()->decodeText(aux).utf8().data());
+ if(bNamesx || bUhNames) {
+ msg->connection()->sendFmtData("PROTOCTL %s %s",bNamesx ? "NAMESX" : "", bUhNames ? "UHNAMES" : "");
+ }
+ }
+ } else {
+ QString inf = msg->connection()->decodeText(msg->safeTrailing());
+ if(!msg->haltOutput())msg->console()->outputNoFmt(KVI_OUT_SERVERINFO,inf);
+ }
+ // } else {
+ // // RPL_BOUNCE prolly
+ // if(!msg->haltOutput())msg->console()->outputNoFmt(KVI_OUT_SERVERINFO,msg->safeTrailing());
+ // }
+}
+
+void KviServerParser::parseNumericMotd(KviIrcMessage *msg)
+{
+ // 372: RPL_MOTD [I,E,U,D]
+ // :prefix 372 target : - <motd>
+ // 377: RPL_MOTD2 [?]
+ // :prefix 377 target : - <motd>
+ // 378: RPL_MOTD3 [Austnet]
+ // :prefix 377 target : - <motd>
+ // 375: RPL_MOTDSTART [I,E,U,D]
+ // :prefix 375 target : - <server> Message of the Day -
+ // 372: RPL_ENDOFMOTD [I,E,U,D]
+ // :prefix 376 target :End of /MOTD command.
+ // FIXME: #warning "SKIP MOTD , MOTD IN A SEPARATE WINDOW , SILENT ENDOFMOTD , MOTD IN ACTIVE WINDOW"
+ if(!msg->haltOutput())msg->console()->outputNoFmt(KVI_OUT_MOTD,msg->connection()->decodeText(msg->safeTrailing()));
+
+ if(msg->numeric() == RPL_ENDOFMOTD)
+ {
+ msg->connection()->endOfMotdReceived();
+ }
+}
+
+void KviServerParser::parseNumericEndOfNames(KviIrcMessage *msg)
+{
+ // 366: RPL_ENDOFNAMES [I,E,U,D]
+ // :prefix 366 target <channel> :End of /NAMES list.
+ QString szChan = msg->connection()->decodeText(msg->safeParam(1));
+ KviChannel * chan = msg->connection()->findChannel(szChan);
+ if(chan)
+ {
+ if(!chan->hasAllNames())
+ {
+ chan->setHasAllNames();
+ return;
+ }
+ }
+
+ if(!msg->haltOutput() && !_OUTPUT_MUTE)
+ {
+// FIXME: #warning "KVI_OUT_NAMES missing"
+ KviWindow * pOut = chan ? chan : KVI_OPTION_BOOL(KviOption_boolServerRepliesToActiveWindow) ?
+ msg->console()->activeWindow() : (KviWindow *)(msg->console());
+ pOut->output(KVI_OUT_UNHANDLED,__tr2qs("End of NAMES for \r!c\r%Q\r"),&szChan);
+ }
+}
+
+void KviServerParser::parseNumeric020(KviIrcMessage *msg)
+{
+ // 020: RPL_CONNECTING
+ //:irc.dotsrc.org 020 * :Please wait while we process your connection.
+ QString szServer;
+ if(!msg->haltOutput())
+ {
+ QString szWText = msg->console()->decodeText(msg->safeTrailing());
+ msg->console()->output(
+ KVI_OUT_CONNECTION,"%c\r!s\r%s\r%c: %Q",KVI_TEXT_BOLD,
+ msg->safePrefix(),KVI_TEXT_BOLD,&szWText);
+ }
+}
+
+void KviServerParser::parseNumericNames(KviIrcMessage *msg)
+{
+ // 353: RPL_NAMREPLY [I,E,U,D]
+ // :prefix 353 target [=|*|@] <channel> :<space_separated_list_of_nicks>
+
+ // [=|*|@] is the type of the channel:
+ // = --> public * --> private @ --> secret
+ // ...but we ignore it
+ //QString szChan = msg->connection()->decodeText(msg->cSafeParam(2)->data()); // <-- KviQCString::data() is implicitly unsafe: it CAN return 0
+ QString szChan = msg->connection()->decodeText(msg->safeParam(2));
+ KviChannel * chan = msg->connection()->findChannel(szChan);
+ // and run to the first nickname
+ char * aux = msg->safeTrailingString().ptr();
+ while((*aux) && (*aux == ' '))aux++;
+ // now check if we have that channel
+
+ char * trailing = aux;
+
+ bool bHalt = msg->haltOutput();
+
+ if(chan)
+ {
+ bHalt = bHalt || (!chan->hasAllNames());
+
+ // K...time to parse a lot of data
+ chan->enableUserListUpdates(false);
+
+ int iPrevFlags = chan->myFlags();
+
+ KviIrcConnectionServerInfo * pServerInfo = msg->connection()->serverInfo();
+
+ while(*aux)
+ {
+ int iFlags = 0;
+ // @ = op (+o), + = voiced (+v), % = halfop (+h), - = userop (+u), ^ = protected (+a?), * = chan owner (+q), !, & = channel admin (+a?)
+ // ^ +a is a weird mode: it also breaks nicknames on some networks!
+ // not a valid first char(s) of nickname, must be a mode prefix
+
+ bool bContinue = true;
+
+ while(pServerInfo->isSupportedModePrefix((unsigned char)(*aux)))
+ {
+ // leading umode flag(s)
+ iFlags |= pServerInfo->modeFlagFromPrefixChar(*aux);
+ aux++;
+ }
+
+ char * begin = aux;
+ while(*aux && (*aux != ' '))aux++;
+ char save = *aux;
+ *aux = 0;
+ // NAMESX + UHNAMES support
+ KviIrcMask mask(msg->connection()->decodeText(begin));
+ // and make it join
+ if(!mask.nick().isEmpty())chan->join(mask.nick(),
+ mask.hasUser() ? mask.user() : QString::null,
+ mask.hasHost() ? mask.host() : QString::null,
+ iFlags);
+ *aux = ' ';
+ *aux = save;
+ // run to the next nick (or the end)
+ while((*aux) && (*aux == ' '))aux++;
+ }
+
+ if(iPrevFlags != chan->myFlags())chan->updateCaption();
+
+ chan->enableUserListUpdates(true);
+ // finished a block
+ }
+
+ // So it is a result of a /NAMES command or a local desync
+ // We handle it in a cool way.
+
+ if(!bHalt)
+ {
+ // FIXME: #warning "KVI_OUT_NAMES missing"
+ KviWindow * pOut = chan ? chan : KVI_OPTION_BOOL(KviOption_boolServerRepliesToActiveWindow) ?
+ msg->console()->activeWindow() : (KviWindow *)(msg->console());
+ QString szTrailing = trailing ? msg->connection()->decodeText(trailing) : QString("");
+ pOut->output(KVI_OUT_UNHANDLED,__tr2qs("Names for \r!c\r%Q\r: %Q"),&szChan,&szTrailing);
+ }
+}
+
+void KviServerParser::parseNumericTopic(KviIrcMessage *msg)
+{
+ // 332: RPL_TOPIC [I,E,U,D]
+ // :prefix 332 target <channel> :<topic>
+ QString szChan = msg->connection()->decodeText(msg->safeParam(1));
+ KviChannel * chan = msg->connection()->findChannel(szChan);
+ if(chan)
+ {
+ QString szTopic = chan->decodeText(msg->safeTrailing());
+
+ chan->topicWidget()->setTopic(szTopic);
+ chan->topicWidget()->setTopicSetBy(__tr2qs("(unknown)"));
+ if(KVI_OPTION_BOOL(KviOption_boolEchoNumericTopic))
+ {
+ if(!msg->haltOutput())
+ chan->output(KVI_OUT_TOPIC,__tr2qs("Channel topic is: %Q"),&szTopic);
+ }
+ } else {
+ KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolServerRepliesToActiveWindow) ?
+ msg->console()->activeWindow() : (KviWindow *)(msg->console());
+
+ QString szTopic = msg->connection()->decodeText(msg->safeTrailing());
+ pOut->output(KVI_OUT_TOPIC,__tr2qs("Topic for \r!c\r%Q\r is: %Q"),
+ &szChan,&szTopic);
+ }
+
+}
+
+void KviServerParser::parseNumericNoTopic(KviIrcMessage *msg)
+{
+ // 331: RPL_NOTOPIC [I,E,U,D]
+ // :prefix 331 target <channel> :No topic is set
+ QString szChan = msg->connection()->decodeText(msg->safeParam(1));
+ KviChannel * chan = msg->connection()->findChannel(szChan);
+ if(chan)
+ {
+ chan->topicWidget()->setTopic("");
+ if(KVI_OPTION_BOOL(KviOption_boolEchoNumericTopic))
+ {
+ if(!msg->haltOutput())
+ chan->outputNoFmt(KVI_OUT_TOPIC,__tr2qs("No channel topic is set"));
+ }
+ } else {
+ KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolServerRepliesToActiveWindow) ?
+ msg->console()->activeWindow() : (KviWindow *)(msg->console());
+ pOut->output(KVI_OUT_TOPIC,__tr2qs("No topic is set for channel \r!c\r%Q\r"),
+ &szChan);
+ }
+}
+
+void KviServerParser::parseNumericTopicWhoTime(KviIrcMessage *msg)
+{
+ // 333: RPL_TOPICWHOTIME [e,U,D]
+ // :prefix 333 target <channel> <whoset> <time>
+
+ QString szChan = msg->connection()->decodeText(msg->safeParam(1));
+ KviChannel * chan = msg->connection()->findChannel(szChan);
+
+ KviStr tmp = msg->safeParam(3);
+ bool bOk = false;
+ unsigned long t = 0;
+ if(tmp.hasData())t = tmp.toUInt(&bOk);
+
+ QDateTime dt;
+ dt.setTime_t(t);
+
+ QString szDate = dt.toString();
+ QString szWho = msg->connection()->decodeText(msg->safeParam(2));
+ KviIrcMask who(szWho);
+ QString szDisplayableWho;
+ if( !(who.hasUser() && who.hasHost()) )
+ {
+ szDisplayableWho="\r!n\r"+szWho+"\r";
+ } else {
+ KviQString::sprintf(szDisplayableWho,"\r!n\r%Q\r!%Q@\r!h\r%Q\r",&(who.nick()),&(who.user()),&(who.host()));
+ }
+ if(chan)
+ {
+ chan->topicWidget()->setTopicSetBy(szWho);
+ if(bOk)chan->topicWidget()->setTopicSetAt(szDate);
+ if(KVI_OPTION_BOOL(KviOption_boolEchoNumericTopic))
+ {
+ if(!msg->haltOutput())
+ {
+ if(bOk)chan->output(KVI_OUT_TOPIC,__tr2qs("Topic was set by %Q on %Q"),&szDisplayableWho,&szDate);
+ else chan->output(KVI_OUT_TOPIC,__tr2qs("Topic was set by %Q"),&szDisplayableWho);
+ }
+ }
+ } else {
+ KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolServerRepliesToActiveWindow) ?
+ msg->console()->activeWindow() : (KviWindow *)(msg->console());
+ if(bOk)
+ {
+ pOut->output(KVI_OUT_TOPIC,__tr2qs("Topic for \r!c\r%Q\r was set by %Q on %Q"),
+ &szChan,&szDisplayableWho,&szDate);
+ } else {
+ pOut->output(KVI_OUT_TOPIC,__tr2qs("Topic for \r!c\r%Q\r was set by %Q"),
+ &szChan,&szDisplayableWho);
+ }
+ }
+}
+
+void KviServerParser::parseNumericChannelModeIs(KviIrcMessage *msg)
+{
+ // 324: RPL_CHANNELMODEIS [I,E,U,D]
+ // :prefix 324 target <channel> +<chanmode>
+ QString szSource = msg->connection()->decodeText(msg->safePrefix());
+ QString szChan = msg->connection()->decodeText(msg->safeParam(1));
+ KviChannel * chan = msg->connection()->findChannel(szChan);
+ KviStr modefl = msg->safeParam(2);
+ if(chan)parseChannelMode(szSource,"*","*",chan,modefl,msg,3);
+ else {
+ KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolServerRepliesToActiveWindow) ?
+ msg->console()->activeWindow() : (KviWindow *)(msg->console());
+ if((!szChan.isEmpty()) && IS_CHANNEL_TYPE_FLAG(szChan[0]))
+ {
+ pOut->output(KVI_OUT_CHANMODE,__tr2qs("Channel mode for \r!c\r%Q\r is %s"),
+ &szChan,msg->safeParam(2));
+ } else {
+ pOut->output(KVI_OUT_MODE,__tr2qs("User mode for \r!n\r%Q\r is %s"),
+ &szChan,msg->safeParam(2));
+ }
+ }
+}
+
+void getDateTimeStringFromCharTimeT(QString &buffer,const char *time_t_string)
+{
+ KviStr tmp=time_t_string;
+ bool bOk=false;
+ unsigned int uTime = tmp.toUInt(&bOk);
+ if(bOk){
+ QDateTime dt;
+ dt.setTime_t(uTime);
+ buffer = dt.toString();
+ } else buffer = __tr2qs("(Unknown)");
+}
+
+#define PARSE_NUMERIC_ENDOFLIST(__funcname,__setGotIt,__didSendRequest,__setDone,__daicon,__szWhatQString) \
+ void KviServerParser::__funcname(KviIrcMessage *msg) \
+ { \
+ QString szChan = msg->connection()->decodeText(msg->safeParam(1)); \
+ KviChannel * chan = msg->connection()->findChannel(szChan); \
+ if(chan) \
+ { \
+ chan->__setGotIt(); \
+ if(chan->__didSendRequest()) \
+ { \
+ chan->__setDone(); \
+ return; \
+ } \
+ } \
+ if(!msg->haltOutput()) \
+ { \
+ KviWindow * pOut = chan ? chan : KVI_OPTION_BOOL(KviOption_boolServerRepliesToActiveWindow) ? \
+ msg->console()->activeWindow() : (KviWindow *)(msg->console()); \
+ pOut->output(__daicon,__tr2qs("End of channel %Q for \r!c\r%Q\r"),&(__szWhatQString),&szChan); \
+ } \
+ }
+
+PARSE_NUMERIC_ENDOFLIST(parseNumericEndOfBanList,setHasBanList,sentBanListRequest,setBanListDone,KVI_OUT_BAN,__tr2qs("ban list"))
+PARSE_NUMERIC_ENDOFLIST(parseNumericEndOfInviteList,setHasInviteList,sentInviteListRequest,setInviteListDone,KVI_OUT_INVITEEXCEPT,__tr2qs("invite list"))
+PARSE_NUMERIC_ENDOFLIST(parseNumericEndOfExceptList,setHasBanExceptionList,sentBanExceptionListRequest,setBanExceptionListDone,KVI_OUT_BANEXCEPT,__tr2qs("ban exception list"))
+
+#define PARSE_NUMERIC_LIST(__funcname,__modechar,__sentRequest,__ico,__szWhatQString) \
+ void KviServerParser::__funcname(KviIrcMessage *msg) \
+ { \
+ QString szChan = msg->connection()->decodeText(msg->safeParam(1)); \
+ QString banmask = msg->connection()->decodeText(msg->safeParam(2)); \
+ QString bansetby = msg->connection()->decodeText(msg->safeParam(3)); \
+ QString bansetat; \
+ getDateTimeStringFromCharTimeT(bansetat,msg->safeParam(4)); \
+ if(bansetby.isEmpty())bansetby = __tr2qs("(Unknown)"); \
+ KviChannel * chan = msg->connection()->findChannel(szChan); \
+ if(chan) \
+ { \
+ chan->setMask(__modechar,banmask,true,bansetby,QString(msg->safeParam(4)).toUInt()); \
+ if(chan->__sentRequest())return; \
+ } \
+ if(!msg->haltOutput()) \
+ { \
+ KviWindow * pOut = chan ? chan : KVI_OPTION_BOOL(KviOption_boolServerRepliesToActiveWindow) ? \
+ msg->console()->activeWindow() : (KviWindow *)(msg->console()); \
+ pOut->output(__ico,__tr2qs("%Q for \r!c\r%Q\r: \r!m-%c\r%Q\r (set by %Q on %Q)"), \
+ &(__szWhatQString),&szChan,__modechar,&banmask,&bansetby,&bansetat); \
+ } \
+ }
+
+// 367: RPL_BANLIST [I,E,U,D]
+// :prefix 367 target <channel> <banmask> [bansetby] [bansetat]
+PARSE_NUMERIC_LIST(parseNumericBanList,'b',sentBanListRequest,KVI_OUT_BAN,__tr2qs("Ban listing"))
+// 346: RPL_INVITELIST [I,E,U,D]
+// :prefix 346 target <channel> <invitemask> [invitesetby] [invitesetat]
+PARSE_NUMERIC_LIST(parseNumericInviteList,'I',sentInviteListRequest,KVI_OUT_INVITEEXCEPT,__tr2qs("Invite listing"))
+// 346: RPL_EXCEPTLIST [I,E,U,D]
+// :prefix 346 target <channel> <banmask> [bansetby] [bansetat]
+PARSE_NUMERIC_LIST(parseNumericExceptList,'e',sentBanExceptionListRequest,KVI_OUT_BANEXCEPT,__tr2qs("Ban exception listing"));
+
+
+void KviServerParser::parseNumericWhoReply(KviIrcMessage *msg)
+{
+ // 352: RPL_WHOREPLY [I,E,U,D]
+ // :prefix 352 target <chan> <usr> <hst> <srv> <nck> <stat> :<hops> <real>
+
+ QString szChan = msg->connection()->decodeText(msg->safeParam(1));
+ QString szUser = msg->connection()->decodeText(msg->safeParam(2));
+ QString szHost = msg->connection()->decodeText(msg->safeParam(3));
+ QString szServ = msg->connection()->decodeText(msg->safeParam(4));
+ QString szNick = msg->connection()->decodeText(msg->safeParam(5));
+ QString szFlag = msg->connection()->decodeText(msg->safeParam(6));
+ bool bAway = szFlag.find('G') != -1;
+
+ KviStr trailing = msg->safeTrailing();
+ KviStr hops = trailing.getToken(' ');
+ bool bHopsOk = false;
+ int iHops = hops.toInt(&bHopsOk);
+
+ QString szReal = msg->connection()->decodeText(trailing.ptr());
+
+ // Update the user entry
+ KviIrcUserDataBase * db = msg->connection()->userDataBase();
+ KviIrcUserEntry * e = db->find(szNick);
+ if(e)
+ {
+ if(bHopsOk)e->setHops(iHops);
+ e->setUser(szUser);
+ e->setHost(szHost);
+ e->setServer(szServ);
+ e->setRealName(szReal);
+ e->setAway(bAway);
+ KviQuery * q = msg->connection()->findQuery(szNick);
+ if(q) q->updateLabelText();
+ if(!e->avatar())
+ {
+ // FIXME: #warning "THE AVATAR SHOULD BE RESIZED TO MATCH THE MAX WIDTH/HEIGHT"
+ // maybe now we can match this user ?
+ msg->console()->checkDefaultAvatar(e,szNick,szUser,szHost);
+ }
+ }
+
+ KviChannel * chan = msg->connection()->findChannel(szChan);
+ if(chan)
+ {
+ if(!chan->hasWhoList())
+ {
+ // FIXME: #warning "IF VERBOSE && SHOW INTERNAL WHO REPLIES...."
+ return;
+ }
+ if(chan->sentSyncWhoRequest())
+ {
+ // FIXME: #warning "IF VERBOSE && SHOW INTERNAL WHO REPLIES...."
+ return;
+ }
+ }
+
+ // FIXME: #warning "SYNC OP/VOICE on channel!!!"
+
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = chan ? chan : KVI_OPTION_BOOL(KviOption_boolServerRepliesToActiveWindow) ?
+ msg->console()->activeWindow() : (KviWindow *)(msg->console());
+
+ QString szAway = bAway ? __tr2qs("Yes") : __tr2qs("No");
+
+ pOut->output(KVI_OUT_WHO,
+ __tr2qs("WHO entry for %c\r!n\r%Q\r%c [%Q@\r!h\r%Q\r]: %cChannel%c: \r!c\r%Q\r, %cServer%c: \r!s\r%Q\r, %cHops%c: %d, %cFlags%c: %Q, %cAway%c: %Q, %cReal name%c: %Q"),
+ KVI_TEXT_BOLD,&szNick, KVI_TEXT_BOLD,
+ &szUser,&szHost,KVI_TEXT_UNDERLINE,
+ KVI_TEXT_UNDERLINE,&szChan,KVI_TEXT_UNDERLINE,
+ KVI_TEXT_UNDERLINE,&szServ,KVI_TEXT_UNDERLINE,
+ KVI_TEXT_UNDERLINE,iHops, KVI_TEXT_UNDERLINE, KVI_TEXT_UNDERLINE,
+ &szFlag, KVI_TEXT_UNDERLINE, KVI_TEXT_UNDERLINE,
+ &szAway, KVI_TEXT_UNDERLINE,
+ KVI_TEXT_UNDERLINE, &szReal);
+ }
+
+
+}
+
+void KviServerParser::parseNumericEndOfWho(KviIrcMessage *msg)
+{
+ // 315: RPL_ENDOFWHO [I,E,U,D]
+ // :prefix 315 target <channel/nick> :End of /WHO List.
+ QString szChan = msg->connection()->decodeText(msg->safeParam(1));
+ KviChannel * chan = msg->connection()->findChannel(szChan);
+ if(chan)
+ {
+ chan->userListView()->updateArea();
+ kvi_time_t tNow = kvi_unixTime();
+ msg->connection()->stateData()->setLastReceivedChannelWhoReply(tNow);
+ chan->setLastReceivedWhoReply(tNow);
+ if(msg->connection()->lagMeter())
+ {
+ KviStr tmp(KviStr::Format,"WHO %s",msg->safeParam(1));
+ msg->connection()->lagMeter()->lagCheckComplete(tmp.ptr());
+ }
+
+ if(!chan->hasWhoList())
+ {
+ // FIXME: #warning "IF VERBOSE && SHOW INTERNAL WHO REPLIES...."
+ chan->setHasWhoList();
+ return;
+ }
+
+ if(chan->sentSyncWhoRequest())
+ {
+ // FIXME: #warning "IF VERBOSE && SHOW INTERNAL WHO REPLIES...."
+ chan->clearSentSyncWhoRequest();
+ return;
+ }
+ }
+
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = chan ? chan : KVI_OPTION_BOOL(KviOption_boolServerRepliesToActiveWindow) ?
+ msg->console()->activeWindow() : (KviWindow *)(msg->console());
+ QString whoTarget = msg->connection()->decodeText(msg->safeParam(1));
+ if(IS_CHANNEL_TYPE_FLAG(whoTarget[0]))
+ whoTarget.prepend("\r!c\r");
+ else
+ whoTarget.prepend("\r!n\r");
+ whoTarget.append("\r");
+ pOut->output(KVI_OUT_WHO,__tr2qs("End of WHO list for %Q"),&whoTarget);
+ }
+}
+
+void KviServerParser::parseLoginNicknameProblem(KviIrcMessage *msg)
+{
+ // ops...not logged in yet...
+ QString nextNick;
+ unsigned int uNickCnt;
+ switch(msg->connection()->stateData()->loginNickIndex())
+ {
+ case 0:
+ // used a server specific nickname
+ KVI_OPTION_STRING(KviOption_stringNickname1).stripWhiteSpace();
+ if(KVI_OPTION_STRING(KviOption_stringNickname1).isEmpty())
+ KVI_OPTION_STRING(KviOption_stringNickname1) = KVI_DEFAULT_NICKNAME1;
+ nextNick = KVI_OPTION_STRING(KviOption_stringNickname1);
+ uNickCnt = 1;
+ case 1:
+ // used the first nickname of the identity
+ KVI_OPTION_STRING(KviOption_stringNickname2).stripWhiteSpace();
+ if(KVI_OPTION_STRING(KviOption_stringNickname2).isEmpty())
+ KVI_OPTION_STRING(KviOption_stringNickname2) = KVI_DEFAULT_NICKNAME2;
+ nextNick = KVI_OPTION_STRING(KviOption_stringNickname2);
+ uNickCnt = 2;
+ break;
+ case 2:
+ // used the second nickname of the identity
+ KVI_OPTION_STRING(KviOption_stringNickname3).stripWhiteSpace();
+ if(KVI_OPTION_STRING(KviOption_stringNickname3).isEmpty())
+ KVI_OPTION_STRING(KviOption_stringNickname3) = KVI_DEFAULT_NICKNAME3;
+ nextNick = KVI_OPTION_STRING(KviOption_stringNickname3);
+ uNickCnt = 3;
+ break;
+ default:
+ {
+ // used all the nicknames of the identity
+ // fall back to a random string...
+ nextNick = msg->safeParam(1);
+ nextNick.stripWhiteSpace();
+ if(nextNick.isEmpty())nextNick = KVI_DEFAULT_NICKNAME1;
+ nextNick = nextNick.left(7);
+ QString num;
+ num.setNum(msg->connection()->stateData()->loginNickIndex());
+ nextNick.append(num);
+ uNickCnt = msg->connection()->stateData()->loginNickIndex() + 1;
+ }
+ break;
+ }
+
+ QString szOldNick = msg->connection()->userInfo()->nickName();
+ msg->console()->notifyListView()->nickChange(szOldNick,nextNick);
+
+ msg->connection()->userInfo()->setNickName(nextNick);
+ msg->connection()->stateData()->setLoginNickIndex(uNickCnt);
+
+ if(uNickCnt > 7)
+ {
+ msg->console()->output(KVI_OUT_NICKNAMEPROBLEM,
+ __tr2qs("Something really weird is happening: the server is refusing all the login nicknames..."));
+
+ if(msg->connection()->stateData()->loginNickIndex() > 10)
+ {
+ msg->console()->output(KVI_OUT_NICKNAMEPROBLEM,
+ __tr2qs("The server is refusing all the login nicknames: giving up, you must send the nickname manually"));
+ return;
+ }
+ }
+
+ if(!msg->haltOutput())
+ {
+ QString szActual = msg->connection()->decodeText(msg->safeParam(1));
+ QString szWText = msg->connection()->decodeText(msg->safeTrailing());
+ msg->console()->output(KVI_OUT_NICKNAMEPROBLEM,
+ __tr2qs("No way to login as '\r!n\r%Q\r' (%d: %Q), trying '%Q'..."),
+ &szActual,msg->numeric(),&szWText,&nextNick);
+ }
+
+ KviQCString d = msg->connection()->encodeText(nextNick);
+ msg->connection()->sendFmtData("NICK %s",d.data());
+}
+
+void KviServerParser::parseNumericUnavailResource(KviIrcMessage *msg)
+{
+ // 437: ERR_UNAVAILRESOURCE [I]
+ // :prefix 437 <target> <nick/channel> :Nick/Channel is temporairly unavailable
+ if(!(msg->console()->isConnected()))
+ {
+ parseLoginNicknameProblem(msg);
+ } else {
+ // already connected... just say that we have problems
+ if(!msg->haltOutput())
+ {
+ QString szNk = msg->connection()->decodeText(msg->safeParam(1));
+ QString szWText = msg->connection()->decodeText(msg->safeTrailing());
+ msg->console()->output(KVI_OUT_NICKNAMEPROBLEM,
+ "\r!n\r%Q\r: %Q",&szNk,&szWText);
+ }
+ }
+}
+
+void KviServerParser::parseNumericCantJoinChannel(KviIrcMessage *msg)
+{
+ // 471: ERR_CHANNELISFULL [I,E,U,D]
+ // 473: ERR_INVITEONLYCHAN [I,E,U,D]
+ // 474: ERR_BANNEDFROMCHAN [I,E,U,D]
+ // 475: ERR_BADCHANNELKEY [I,E,U,D]
+ // :prefix 47* <target> <channel> :Can't join channel (+l/i/b/k)
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = (KviWindow *)(msg->connection()->findChannel(msg->safeParam(1)));
+ if(!pOut)pOut = (KviWindow *)(msg->console());
+ QString szChannel = msg->connection()->decodeText(msg->safeParam(1));
+ QString szWText = msg->connection()->decodeText(msg->safeTrailing());
+ pOut->output(KVI_OUT_JOINERROR,
+ "\r!c\r%Q\r: %Q",&szChannel,&szWText);
+ }
+}
+
+// Keep the source ordered: this should be named "parseOtherChannelError"
+
+void KviServerParser::otherChannelError(KviIrcMessage *msg)
+{
+ // 482: ERR_CHANOPRIVSNEEDED
+ // 467: ERR_KEYSET
+ // 472: ERR_UNKNOWNMODE
+ // :prefix 4?? <target> <channel> :error text
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = (KviWindow *)(msg->connection()->findChannel(msg->safeParam(1)));
+ if(!pOut)pOut = (KviWindow *)(msg->console());
+ QString szChannel = msg->connection()->decodeText(msg->safeParam(1));
+ QString szWText = msg->connection()->decodeText(msg->safeTrailing());
+ pOut->output(KVI_OUT_GENERICERROR,
+ "\r!c\r%Q\r: %Q",&szChannel,&szWText);
+ }
+}
+
+void KviServerParser::parseCommandSyntaxHelp(KviIrcMessage *msg)
+{
+ // 704 RPL_COMMANDSYNTAX
+ // :prefix 704 <target> <command> :text
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = (KviWindow *)(msg->console());
+ QString szCommand = msg->connection()->decodeText(msg->safeParam(1));
+ QString szWText = msg->connection()->decodeText(msg->safeTrailing());
+ pOut->output(KVI_OUT_HELP,
+ __tr2qs("Command syntax %Q: %Q"),&szCommand,&szWText); // Pragma: wheee..... that should be in english :D
+ }
+}
+
+void KviServerParser::parseCommandHelp(KviIrcMessage *msg)
+{
+ // 705 RPL_COMMANDHELP
+ // :prefix 705 <target> <command> :text
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = (KviWindow *)(msg->console());
+ QString szCommand = msg->connection()->decodeText(msg->safeParam(1));
+ QString szWText = msg->connection()->decodeText(msg->safeTrailing());
+ pOut->outputNoFmt(KVI_OUT_HELP,szWText);
+ }
+}
+
+void KviServerParser::parseChannelHelp(KviIrcMessage *msg)
+{
+ // 477 RPL_CHANNELHELP (freenode)
+ // :prefix 477 <target> <channel> :text
+ if(!msg->haltOutput())
+ {
+ QString szChan = msg->connection()->decodeText(msg->safeParam(1));
+ QString szText = msg->connection()->decodeText(msg->safeTrailing());
+ KviWindow * pOut = msg->connection()->findChannel(szChan);
+ if(pOut)
+ {
+ pOut->output(KVI_OUT_HELP,__tr2qs("Tip: %Q"),&szText);
+ } else {
+ pOut = (KviWindow *)(msg->console());
+ pOut->output(KVI_OUT_HELP,__tr2qs("Tip for %Q: %Q"),&szChan,&szText);
+ }
+
+ }
+}
+
+
+void KviServerParser::parseCommandEndOfHelp(KviIrcMessage *msg)
+{
+ // 704 RPL_COMMANDSYNTAX
+ // 705 RPL_COMMANDHELP
+ // :prefix 706 <target> <command> :End of /HELP.
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = (KviWindow *)(msg->console());
+ QString szCommand = msg->connection()->decodeText(msg->safeParam(1));
+ pOut->output(KVI_OUT_HELP,
+ __tr2qs("End of help about %Q"),&szCommand);
+ }
+}
+
+void KviServerParser::parseNumericNicknameProblem(KviIrcMessage *msg)
+{
+ // 433: ERR_NICKNAMEINUSE [I,E,U,D]
+ // :prefix 433 <target> <nick> :Nickname is already in use.
+ // 432: ERR_ERRONEUSNICKNAME [I,E,U,D]
+ // :prefix 433 <target> <nick> :Erroneous nickname
+
+ if(!(msg->console()->isConnected()))
+ {
+ parseLoginNicknameProblem(msg);
+ } else {
+ // already connected... just say that we have problems
+ if(!msg->haltOutput())
+ {
+ QString szNk = msg->connection()->decodeText(msg->safeParam(1));
+ QString szWText = msg->connection()->decodeText(msg->safeTrailing());
+ msg->console()->output(KVI_OUT_NICKNAMEPROBLEM,
+ "\r!n\r%Q\r: %Q",&szNk,&szWText);
+ }
+ }
+}
+
+void KviServerParser::parseNumericWhoisAway(KviIrcMessage * msg)
+{
+// FIXME: #warning "Need an icon here too: sth like KVI_OUT_WHOISSERVER, but with 'A' letter"
+ msg->connection()->stateData()->setLastReceivedWhoisReply(kvi_unixTime());
+
+ QString szNk = msg->connection()->decodeText(msg->safeParam(1));
+ KviIrcUserDataBase * db = msg->connection()->userDataBase();
+ KviIrcUserEntry * e = db->find(szNk);
+ if(e)e->setAway(true);
+ KviQuery * q = msg->connection()->findQuery(szNk);
+ if(q) q->updateLabelText();
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = (KviWindow *)(msg->connection()->findQuery(szNk));
+ QString szWText = pOut ? pOut->decodeText(msg->safeTrailing()) : msg->connection()->decodeText(msg->safeTrailing());
+
+ if(!pOut)pOut = KVI_OPTION_BOOL(KviOption_boolWhoisRepliesToActiveWindow) ?
+ msg->console()->activeWindow() : (KviWindow *)(msg->console());
+ pOut->output(KVI_OUT_WHOISUSER,__tr2qs("%c\r!n\r%Q\r%c is away: %Q"),
+ KVI_TEXT_BOLD,&szNk,KVI_TEXT_BOLD,&szWText);
+ }
+}
+
+void KviServerParser::parseNumericWhoisUser(KviIrcMessage *msg)
+{
+ // 311: RPL_WHOISUSER [I,E,U,D]
+ // :prefix 311 <target> <nick> <user> <host> * :<real_name>
+ msg->connection()->stateData()->setLastReceivedWhoisReply(kvi_unixTime());
+
+ QString szNick = msg->connection()->decodeText(msg->safeParam(1));
+ QString szUser = msg->connection()->decodeText(msg->safeParam(2));
+ QString szHost = msg->connection()->decodeText(msg->safeParam(3));
+ QString szReal = msg->connection()->decodeText(msg->safeTrailing());
+ KviIrcUserDataBase * db = msg->connection()->userDataBase();
+ KviIrcUserEntry * e = db->find(szNick);
+ if(e)
+ {
+ e->setUser(szUser);
+ e->setHost(szHost);
+ e->setRealName(szReal);
+ if(e->gender()!=KviIrcUserEntry::Unknown) {
+ if(KviQString::equalCS(g_pActiveWindow->className(),QString("KviChannel")))
+ {
+ ((KviChannel*)g_pActiveWindow)->userListView()->updateArea();
+ }
+ }
+ KviQuery * q = msg->connection()->findQuery(szNick);
+ if(q) q->updateLabelText();
+ if(!e->avatar())
+ {
+ // FIXME: #warning "THE AVATAR SHOULD BE RESIZED TO MATCH THE MAX WIDTH/HEIGHT"
+ // maybe now we can match this user ?
+ msg->console()->checkDefaultAvatar(e,szNick,szUser,szHost);
+ }
+ }
+
+ KviAsyncWhoisInfo * i = msg->connection()->asyncWhoisData()->lookup(szNick);
+ if(i)
+ {
+ i->szNick = szNick;
+ i->szUser = szUser;
+ i->szHost = szHost;
+ i->szReal = szReal;
+ return;
+ }
+
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolWhoisRepliesToActiveWindow) ?
+ msg->console()->activeWindow() : (KviWindow *)(msg->console());
+ pOut->output(
+ KVI_OUT_WHOISUSER,__tr2qs("%c\r!n\r%Q\r%c is %c\r!n\r%Q\r!%Q@\r!h\r%Q\r%c"),KVI_TEXT_BOLD,
+ &szNick,KVI_TEXT_BOLD,KVI_TEXT_UNDERLINE,&szNick,
+ &szUser,&szHost,KVI_TEXT_UNDERLINE);
+
+ pOut->output(
+ KVI_OUT_WHOISUSER,__tr2qs("%c\r!n\r%Q\r%c's real name: %Q"),KVI_TEXT_BOLD,
+ &szNick,KVI_TEXT_BOLD,&szReal);
+ }
+}
+
+void KviServerParser::parseNumericWhowasUser(KviIrcMessage * msg)
+{
+ // 314: RPL_WHOWASUSER [I,E,U,D]
+ // :prefix 314 <target> <nick> <user> <host> * :<real_name>
+
+ if(!msg->haltOutput())
+ {
+ QString szNick = msg->connection()->decodeText(msg->safeParam(1));
+ QString szUser = msg->connection()->decodeText(msg->safeParam(2));
+ QString szHost = msg->connection()->decodeText(msg->safeParam(3));
+ QString szReal = msg->connection()->decodeText(msg->safeTrailing());
+
+ KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolWhoisRepliesToActiveWindow) ?
+ msg->console()->activeWindow() : (KviWindow *)(msg->console());
+ pOut->output(
+ KVI_OUT_WHOISUSER,__tr2qs("%c\r!n\r%Q\r%c was %c\r!n\r%Q\r!%Q@\r!h\r%Q\r%c"),KVI_TEXT_BOLD,
+ &szNick,KVI_TEXT_BOLD,KVI_TEXT_UNDERLINE,&szNick,
+ &szUser,&szHost,KVI_TEXT_UNDERLINE);
+ pOut->output(
+ KVI_OUT_WHOISUSER,__tr2qs("%c\r!n\r%Q\r%c's real name was: %Q"),KVI_TEXT_BOLD,
+ &szNick,KVI_TEXT_BOLD,&szReal);
+ }
+}
+
+
+void KviServerParser::parseNumericWhoisChannels(KviIrcMessage *msg)
+{
+ // 319: RPL_WHOISCHANNELS [I,E,U,D]
+ // :prefix 319 <target> <nick> :<channel list>
+
+ msg->connection()->stateData()->setLastReceivedWhoisReply(kvi_unixTime());
+
+ QString szNick = msg->connection()->decodeText(msg->safeParam(1));
+ QString szChans = msg->connection()->decodeText(msg->safeTrailing());
+
+ KviAsyncWhoisInfo * i = msg->connection()->asyncWhoisData()->lookup(szNick);
+ if(i)
+ {
+ i->szChannels = szChans;
+ return;
+ }
+
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolWhoisRepliesToActiveWindow) ?
+ msg->console()->activeWindow() : (KviWindow *)(msg->console());
+
+ QStringList sl = QStringList::split(" ",szChans);
+ QString szChanList;
+
+ for(QStringList::Iterator it = sl.begin();it != sl.end();++it)
+ {
+ QString szCur = *it;
+ // deals with <flag>[#channel] and [##channel]
+ int len = szCur.length();
+ int i =0;
+ while(i < len)
+ {
+
+ if(IS_CHANNEL_TYPE_FLAG(szCur[i]) && (!IS_USER_MODE_PREFIX(szCur[i])))break;
+ i++;
+ }
+ if(i < len)
+ {
+ if(i > 0)
+ {
+ len = szCur.length() - i;
+ if(szChanList.length() > 0)szChanList.append(", ");
+ szChanList += szCur.left(i);
+ QString szR = szCur.right(len);
+ KviQString::appendFormatted(szChanList,"\r!c\r%Q\r",&szR);
+ } else {
+ if(szChanList.length() > 0)szChanList.append(", ");
+ KviQString::appendFormatted(szChanList,"\r!c\r%Q\r",&szCur);
+ }
+ } else {
+ // we dunno what is this.. just append
+ if(szChanList.length() > 0)szChanList.append(", ");
+ szChanList.append(szCur);
+ }
+ }
+
+ pOut->output(
+ KVI_OUT_WHOISCHANNELS,__tr2qs("%c\r!n\r%Q\r%c's channels: %Q"),KVI_TEXT_BOLD,
+ &szNick,KVI_TEXT_BOLD,&szChanList);
+ }
+}
+
+void KviServerParser::parseNumericWhoisIdle(KviIrcMessage *msg)
+{
+ // 317: RPL_WHOISIDLE [I,E,U,D]
+ // :prefix 317 <target> <nick> <number> <number> :seconds idle, signon time
+
+ // FIXME: #warning "and NICK LINKS"
+ msg->connection()->stateData()->setLastReceivedWhoisReply(kvi_unixTime());
+
+ QString szNick = msg->connection()->decodeText(msg->safeParam(1));
+
+ KviAsyncWhoisInfo * i = msg->connection()->asyncWhoisData()->lookup(szNick);
+ if(i)
+ {
+ i->szIdle = msg->safeParam(2);
+ i->szSignon = msg->safeParam(3);
+ bool bOk = false;
+ i->szSignon.toUInt(&bOk);
+ if(!bOk)i->szSignon = "";
+ return;
+ }
+
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolWhoisRepliesToActiveWindow) ?
+ msg->console()->activeWindow() : (KviWindow *)(msg->console());
+ KviStr idle = msg->safeParam(2); // shouldn't be encoded
+ KviStr sign = msg->safeParam(3); // shouldn't be encoded
+
+ bool bOk;
+ unsigned int uTime = idle.toUInt(&bOk);
+ if(!bOk)
+ {
+ UNRECOGNIZED_MESSAGE(msg,__tr2qs("Received a broken RPL_WHOISIDLE, can't evaluate the idle time"));
+ return;
+ }
+ unsigned int uDays = uTime / 86400;
+ uTime = uTime % 86400;
+ unsigned int uHours = uTime / 3600;
+ uTime = uTime % 3600;
+ unsigned int uMins = uTime / 60;
+ uTime = uTime % 60;
+ pOut->output(
+ KVI_OUT_WHOISIDLE,__tr2qs("%c\r!n\r%Q\r%c's idle time: %ud %uh %um %us"),KVI_TEXT_BOLD,
+ &szNick,KVI_TEXT_BOLD,uDays,uHours,uMins,uTime);
+
+ uTime = sign.toUInt(&bOk);
+ if(bOk)
+ {
+ QDateTime dt;
+ dt.setTime_t((time_t)uTime);
+ QString tmp = dt.toString();
+ pOut->output(
+ KVI_OUT_WHOISIDLE,__tr2qs("%c\r!n\r%Q\r%c's signon time: %Q"),KVI_TEXT_BOLD,
+ &szNick,KVI_TEXT_BOLD,&tmp);
+ }
+ }
+}
+
+void KviServerParser::parseNumericWhoisServer(KviIrcMessage *msg)
+{
+ // 312: RPL_WHOISSERVER [I,E,U,D] (sent also in response to WHOWAS)
+ // :prefix 312 <target> <nick> <server> :<server description / last whowas date>
+ msg->connection()->stateData()->setLastReceivedWhoisReply(kvi_unixTime());
+
+ QString szNick = msg->connection()->decodeText(msg->safeParam(1));
+ QString szServ = msg->connection()->decodeText(msg->safeParam(2));
+
+ KviIrcUserDataBase * db = msg->connection()->userDataBase();
+ KviIrcUserEntry * e = db->find(szNick);
+ if(e)e->setServer(szServ);
+ KviQuery * q = msg->connection()->findQuery(szNick);
+ if(q) q->updateLabelText();
+ KviAsyncWhoisInfo * i = msg->connection()->asyncWhoisData()->lookup(msg->safeParam(1));
+ if(i)
+ {
+ i->szServer = szServ;
+ return;
+ }
+
+ // FIXME: #warning "AWHOIS HERE.... and NICK LINKS"
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolWhoisRepliesToActiveWindow) ?
+ msg->console()->activeWindow() : (KviWindow *)(msg->console());
+ QString szWText = pOut->decodeText(msg->safeTrailing());
+ pOut->output(
+ KVI_OUT_WHOISSERVER,__tr2qs("%c\r!n\r%Q\r%c's server: \r!s\r%Q\r - %Q"),KVI_TEXT_BOLD,
+ &szNick,KVI_TEXT_BOLD,&szServ,&szWText);
+ }
+}
+
+void KviServerParser::parseNumericWhoisAuth(KviIrcMessage *msg)
+{
+ // :prefix RPL_WHOISAUTH <target> <nick> :is authed as
+ // actually seen only on Quakenet
+ msg->connection()->stateData()->setLastReceivedWhoisReply(kvi_unixTime());
+
+ QString szNick = msg->connection()->decodeText(msg->safeParam(1));
+ QString szAuth = msg->connection()->decodeText(msg->safeParam(2));
+
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolWhoisRepliesToActiveWindow) ?
+ msg->console()->activeWindow() : (KviWindow *)(msg->console());
+ pOut->output(
+ KVI_OUT_WHOISOTHER,__tr2qs("%c\r!n\r%Q\r%c is authenticated as %Q"),KVI_TEXT_BOLD,
+ &szNick,KVI_TEXT_BOLD,&szAuth);
+ }
+}
+
+void KviServerParser::parseNumericWhoisOther(KviIrcMessage *msg)
+{
+ // *: RPL_WHOIS* [?]
+ // :prefix * <target> <nick> :<description>
+ // used for RPL_WHOISCHANOP,RPL_WHOISADMIN,
+ // RPL_WHOISSADMIN,RPL_WHOISOPERATOR,RPL_WHOISREGNICK,RPL_WHOISSSL
+ // and all the other unrecognized codes that look really like a RPL_WHOIS*
+
+ msg->connection()->stateData()->setLastReceivedWhoisReply(kvi_unixTime());
+
+ QString szNick = msg->connection()->decodeText(msg->safeParam(1));
+ QString szOth = msg->connection()->decodeText(msg->safeTrailing());
+
+ KviAsyncWhoisInfo * i = msg->connection()->asyncWhoisData()->lookup(szNick);
+ if(i)
+ {
+ if(!(i->szServer.isEmpty()))i->szServer.append(',');
+ i->szServer.append(szOth);
+ return;
+ }
+
+ // FIXME: #warning "NICK LINKS"
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolWhoisRepliesToActiveWindow) ?
+ msg->console()->activeWindow() : (KviWindow *)(msg->console());
+ pOut->output(
+ KVI_OUT_WHOISOTHER,__tr2qs("%c\r!n\r%Q\r%c's info: %Q"),KVI_TEXT_BOLD,
+ &szNick,KVI_TEXT_BOLD,&szOth);
+ }
+}
+
+// FIXME: #warning "WHOWAS MISSING"
+
+void KviServerParser::parseNumericEndOfWhois(KviIrcMessage *msg)
+{
+ // 318: RPL_ENDOFWHOIS [I,E,U,D]
+ // :prefix 318 <target> <nick> :End of /WHOIS list
+
+ msg->connection()->stateData()->setLastReceivedWhoisReply(0);
+
+ QString szNick = msg->connection()->decodeText(msg->safeParam(1));
+
+ KviAsyncWhoisInfo * i = msg->connection()->asyncWhoisData()->lookup(szNick);
+ if(i)
+ {
+ if(!g_pApp->windowExists(i->pWindow))i->pWindow = msg->console();
+
+ // that's the new KVS engine!
+ KviKvsVariantList vl;
+ vl.setAutoDelete(true);
+ vl.append(new KviKvsVariant(i->szNick));
+ vl.append(new KviKvsVariant(i->szUser));
+ vl.append(new KviKvsVariant(i->szHost));
+ vl.append(new KviKvsVariant(i->szReal));
+ vl.append(new KviKvsVariant(i->szServer));
+ vl.append(new KviKvsVariant(i->szIdle));
+ vl.append(new KviKvsVariant(i->szSignon));
+ vl.append(new KviKvsVariant(i->szChannels));
+ vl.append(new KviKvsVariant(QString(msg->safePrefix())));
+ vl.append(new KviKvsVariant(i->szSpecial));
+ vl.append(new KviKvsVariant(*(i->pMagic)));
+ i->pCallback->run(i->pWindow,&vl,0,KviKvsScript::PreserveParams);
+ msg->connection()->asyncWhoisData()->remove(i);
+ return;
+ }
+
+ // FIXME: #warning "NICK LINKS"
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolWhoisRepliesToActiveWindow) ?
+ msg->console()->activeWindow() : (KviWindow *)(msg->console());
+ QString pref = msg->connection()->decodeText(msg->safePrefix());
+ pOut->output(
+ KVI_OUT_WHOISOTHER,__tr2qs("%c\r!n\r%Q\r%c WHOIS info from \r!s\r%Q\r"),KVI_TEXT_BOLD,
+ &szNick,KVI_TEXT_BOLD,&pref);
+ }
+}
+
+
+void KviServerParser::parseNumericEndOfWhowas(KviIrcMessage *msg)
+{
+ // 369: RPL_ENDOFWHOWAS [I,E,U,D]
+ // :prefix 369 <target> <nick> :End of /WHOWAS list
+ if(!msg->haltOutput())
+ {
+ QString szNick = msg->connection()->decodeText(msg->safeParam(1));
+ KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolWhoisRepliesToActiveWindow) ?
+ msg->console()->activeWindow() : (KviWindow *)(msg->console());
+ QString pref = msg->connection()->decodeText(msg->safePrefix());
+ pOut->output(
+ KVI_OUT_WHOISOTHER,__tr2qs("%c\r!n\r%Q\r%c WHOWAS info from \r!s\r%Q\r"),KVI_TEXT_BOLD,
+ &szNick,KVI_TEXT_BOLD,&pref);
+ }
+}
+
+void KviServerParser::parseNumericNoSuchNick(KviIrcMessage *msg)
+{
+ // 401: ERR_NOSUCHNICK [I,E,U,D]
+ // 406: ERR_WASNOSUCHNICK [I,E,U,D]
+ // :prefix 401 <target> <nick> :No such nick/channel
+ // :prefix 406 <target> <nick> :There was no such nickname
+ QString szNick = msg->connection()->decodeText(msg->safeParam(1));
+
+ if(msg->numeric() == ERR_NOSUCHNICK)
+ {
+ KviAsyncWhoisInfo * i = msg->connection()->asyncWhoisData()->lookup(szNick);
+ if(i)
+ {
+ if(!g_pApp->windowExists(i->pWindow))i->pWindow = msg->console();
+ // that's the new KVS engine!
+ KviKvsVariantList vl;
+ vl.setAutoDelete(true);
+ vl.append(new KviKvsVariant(i->szNick));
+ vl.append(new KviKvsVariant());
+ vl.append(new KviKvsVariant());
+ vl.append(new KviKvsVariant());
+ vl.append(new KviKvsVariant());
+ vl.append(new KviKvsVariant());
+ vl.append(new KviKvsVariant());
+ vl.append(new KviKvsVariant());
+ vl.append(new KviKvsVariant());
+ vl.append(new KviKvsVariant());
+ vl.append(new KviKvsVariant(*(i->pMagic)));
+ i->pCallback->run(i->pWindow,&vl,0,KviKvsScript::PreserveParams);
+ msg->connection()->asyncWhoisData()->remove(i);
+ return;
+ }
+ }
+ // FIXME: #warning "KVI_OUT_NOSUCHNICKCHANNEL ?"
+ // FIXME: #warning "QUERIES SHOULD REPORT NO TARGET HERE! (?)"
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = (KviWindow *)(msg->connection()->findQuery(szNick));
+ if(!pOut)
+ {
+ pOut = (KviWindow *)(msg->console()->activeWindow());
+ }
+ //} else {
+ // ((KviQuery *)pOut)->removeTarget(msg->safeParam(1));
+ //}
+ QString szWText = pOut->decodeText(msg->safeTrailing());
+ pOut->output(KVI_OUT_NICKNAMEPROBLEM,"\r!n\r%Q\r: %Q",
+ &szNick,&szWText);
+ }
+}
+
+void KviServerParser::parseNumericCreationTime(KviIrcMessage *msg)
+{
+ // 329: RPL_CREATIONTIME
+ // :prefix 329 <target> <channel> <creation_time>
+ QString szChan = msg->connection()->decodeText(msg->safeParam(1));
+ KviChannel * chan = msg->connection()->findChannel(szChan);
+ KviStr tmstr = msg->safeParam(2);
+ QDateTime dt;
+ dt.setTime_t((time_t)tmstr.toUInt());
+
+ if(!tmstr.isUnsignedNum())
+ {
+ UNRECOGNIZED_MESSAGE(msg,__tr2qs("Can't evaluate creation time"));
+ return;
+ }
+ QString szDate = dt.toString();
+ if(chan)
+ {
+ if(!msg->haltOutput())
+ {
+ chan->output(KVI_OUT_CREATIONTIME,__tr2qs("Channel was created at %Q"),&szDate);
+ }
+ } else {
+ KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolServerRepliesToActiveWindow) ?
+ msg->console()->activeWindow() : (KviWindow *)(msg->console());
+ pOut->output(KVI_OUT_CREATIONTIME,__tr2qs("Channel \r!c\r%Q\r was created at %Q"),
+ &szChan,&szDate);
+ }
+}
+
+void KviServerParser::parseNumericIsOn(KviIrcMessage *msg)
+{
+ // 303: RPL_ISON
+ // :prefix 303 <target> :<ison replies>
+ if(msg->connection()->notifyListManager())
+ {
+ if(msg->connection()->notifyListManager()->handleIsOn(msg))return;
+ }
+ // not handled...output it
+
+ // FIXME: #warning "OUTPUT IT! (In a suitable way)"
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolServerRepliesToActiveWindow) ?
+ msg->console()->activeWindow() : (KviWindow *)(msg->console());
+ QString szPrefix = msg->connection()->decodeText(msg->safePrefix());
+ QString szAllParms = msg->connection()->decodeText(msg->allParams());
+ pOut->output(KVI_OUT_UNHANDLED,
+ "[%Q][%s] %Q",&szPrefix,msg->command(),&szAllParms);
+ }
+}
+
+void KviServerParser::parseNumericUserhost(KviIrcMessage *msg)
+{
+ // 302: RPL_USERHOST
+ // :prefix 302 <target> :<userhost replies>
+ if(msg->connection()->notifyListManager())
+ {
+ if(msg->connection()->notifyListManager()->handleUserhost(msg))return;
+ }
+ // not handled...output it
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolServerRepliesToActiveWindow) ?
+ msg->console()->activeWindow() : (KviWindow *)(msg->console());
+ QString szUser = msg->connection()->decodeText(msg->safeTrailing());
+ pOut->output(KVI_OUT_WHOISUSER,__tr2qs("USERHOST info: %Q"),&szUser);
+ }
+}
+
+void KviServerParser::parseNumericListStart(KviIrcMessage *msg)
+{
+ // 321: RPL_LISTSTART [I,E,U,D]
+ // :prefix 321 <target> :Channel users name
+ if(msg->haltOutput())return; // stopped by raw
+
+ if(!(msg->console()->ircContext()->listWindow()))
+ {
+ // attempt to load the module...
+ msg->console()->ircContext()->createListWindow();
+ }
+
+ if(msg->console()->ircContext()->listWindow())
+ {
+ // module loaded
+ msg->console()->ircContext()->listWindow()->control(EXTERNAL_SERVER_DATA_PARSER_CONTROL_STARTOFDATA);
+ } else {
+ msg->console()->output(KVI_OUT_LIST,__tr2qs("Channel list begin: channel, users, topic"));
+ }
+}
+
+void KviServerParser::parseNumericList(KviIrcMessage *msg)
+{
+ // 322: RPL_LIST [I,E,U,D]
+ // :prefix 364 <target> <channel> <users> :<topic>
+ if(msg->haltOutput())return; // stopped by raw
+
+ if(!(msg->console()->ircContext()->listWindow()))
+ {
+ // attempt to load the module...
+ msg->console()->ircContext()->createListWindow();
+ if(msg->console()->ircContext()->listWindow())
+ {
+ msg->console()->ircContext()->listWindow()->control(EXTERNAL_SERVER_DATA_PARSER_CONTROL_STARTOFDATA);
+ }
+ }
+
+ if(msg->console()->ircContext()->listWindow())
+ {
+ // module loaded
+ msg->console()->ircContext()->listWindow()->processData(msg);
+ } else {
+ // ops...can't load the module...
+ QString szList = msg->connection()->decodeText(msg->allParams());
+ msg->console()->output(KVI_OUT_LIST,__tr2qs("List: %Q"),&szList);
+ }
+}
+
+void KviServerParser::parseNumericListEnd(KviIrcMessage *msg)
+{
+ // 323: RPL_LISTEND [I,E,U,D]
+ // :prefix 323 <target> :End of /LIST
+ if(msg->haltOutput())return; // stopped by raw
+
+ if(msg->console()->ircContext()->listWindow())
+ {
+ msg->console()->ircContext()->listWindow()->control(EXTERNAL_SERVER_DATA_PARSER_CONTROL_ENDOFDATA);
+ } else {
+ msg->console()->output(KVI_OUT_LIST,__tr2qs("End of LIST"));
+ }
+
+}
+
+void KviServerParser::parseNumericLinks(KviIrcMessage *msg)
+{
+ // 364: RPL_LINKS [I,E,U,D]
+ // :prefix 364 <target> <host> <parent> :<hops> <description>
+ if(!(msg->console()->ircContext()->linksWindow()))
+ {
+ // attempt to load the module...
+ msg->console()->ircContext()->createLinksWindow();
+ }
+
+ if(msg->console()->ircContext()->linksWindow())
+ {
+ // module loaded
+ msg->console()->ircContext()->linksWindow()->processData(msg);
+ } else {
+ // ops...can't load the module... or the event halted the window creation
+ if(!msg->haltOutput())
+ {
+ QString szList = msg->connection()->decodeText(msg->allParams());
+ msg->console()->output(KVI_OUT_LINKS,__tr2qs("Link: %Q"),&szList);
+ }
+ }
+}
+
+void KviServerParser::parseNumericEndOfLinks(KviIrcMessage *msg)
+{
+ // 365: RPL_ENDOFLINKS [I,E,U,D]
+ // :prefix 365 <target> :End of /LINKS
+ if(msg->console()->ircContext()->linksWindow())
+ {
+ msg->console()->ircContext()->linksWindow()->control(EXTERNAL_SERVER_DATA_PARSER_CONTROL_ENDOFDATA);
+ } else {
+ if(!msg->haltOutput())
+ {
+ msg->console()->output(KVI_OUT_LINKS,__tr2qs("End of LINKS"));
+ }
+ }
+}
+
+void KviServerParser::parseNumericBackFromAway(KviIrcMessage * msg)
+{
+ // 305: RPL_UNAWAY [I,E,U,D]
+ // :prefix 305 <target> :You are no longer away
+ bool bWasAway = msg->connection()->userInfo()->isAway();
+ QString szNickBeforeAway;
+ QString szWText = msg->connection()->decodeText(msg->safeTrailing());
+
+ if(bWasAway)szNickBeforeAway = msg->connection()->userInfo()->nickNameBeforeAway();
+ msg->connection()->changeAwayState(false);
+
+ // trigger the event
+ QString tmp;
+ KviQString::sprintf(tmp,"%u",bWasAway ? (unsigned int)(msg->connection()->userInfo()->awayTime()) : 0);
+ if(KVS_TRIGGER_EVENT_2_HALTED(KviEvent_OnMeBack,msg->console(),tmp,szWText))
+ msg->setHaltOutput();
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolServerRepliesToActiveWindow) ?
+ msg->console()->activeWindow() : (KviWindow *)(msg->console());
+
+ if(bWasAway)
+ {
+ int uTimeDiff = bWasAway ? (kvi_unixTime() - msg->connection()->userInfo()->awayTime()) : 0;
+ pOut->output(KVI_OUT_AWAY,__tr2qs("[Leaving away status after %ud %uh %um %us]: %Q"),
+ uTimeDiff / 86400,(uTimeDiff % 86400) / 3600,(uTimeDiff % 3600) / 60,uTimeDiff % 60,
+ &szWText);
+ } else {
+ pOut->output(KVI_OUT_AWAY,__tr2qs("[Leaving away status]: %Q"),&szWText);
+ }
+ }
+
+ if(KVI_OPTION_BOOL(KviOption_boolChangeNickAway) && bWasAway && (!(szNickBeforeAway.isEmpty())))
+ {
+ if(_OUTPUT_PARANOIC)
+ msg->console()->output(KVI_OUT_AWAY,__tr2qs("Restoring pre-away nickname (%Q)"),&szNickBeforeAway);
+ KviQCString szDat = msg->connection()->encodeText(szNickBeforeAway);
+ msg->connection()->sendFmtData("NICK %s",szDat.data());
+ }
+
+}
+
+void KviServerParser::parseNumericAway(KviIrcMessage * msg)
+{
+ // 306: RPL_NOWAWAY [I,E,U,D]
+ // :prefix 305 <target> :You're away man
+ msg->connection()->changeAwayState(true);
+ QString szWText = msg->connection()->decodeText(msg->safeTrailing());
+
+ if(KVS_TRIGGER_EVENT_1_HALTED(KviEvent_OnMeAway,msg->console(),szWText))msg->setHaltOutput();
+
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolServerRepliesToActiveWindow) ?
+ msg->console()->activeWindow() : (KviWindow *)(msg->console());
+ pOut->output(KVI_OUT_AWAY,__tr2qs("[Entering away status]: %Q"),&szWText);
+ }
+
+ if(KVI_OPTION_BOOL(KviOption_boolChangeNickAway))
+ {
+ QString nick = msg->connection()->decodeText(msg->safeParam(0));
+ QString szNewNick;
+ if(KVI_OPTION_BOOL(KviOption_boolAutoGeneratedAwayNick))
+ {
+ if(nick.length() > 5)szNewNick = nick.left(5);
+ else szNewNick = nick;
+ szNewNick.append("AWAY");
+ } else {
+ szNewNick = KVI_OPTION_STRING(KviOption_stringCustomAwayNick);
+ szNewNick.replace("%nick%",nick);
+ }
+
+ if(_OUTPUT_PARANOIC)
+ msg->console()->output(KVI_OUT_AWAY,__tr2qs("Setting away nickname (%Q)"),&szNewNick);
+ KviQCString dat = msg->connection()->encodeText(szNewNick);
+ msg->connection()->sendFmtData("NICK %s",dat.data());
+ }
+}
+
+void KviServerParser::parseNumericWatch(KviIrcMessage *msg)
+{
+ // 600: RPL_LOGON
+ // :prefix 600 <target> <nick> <user> <host> <logintime> :logged online
+ // 601: RPL_LOGON
+ // :prefix 601 <target> <nick> <user> <host> <logintime> :logged offline
+ // 602: RPL_WATCHOFF
+ // :prefix 602 <target> <nick> <user> <host> <logintime> :stopped watching
+ // 604: PRL_NOWON
+ // :prefix 604 <target> <nick> <user> <host> <logintime> :is online
+ // 605: PRL_NOWOFF
+ // :prefix 605 <target> <nick> <user> <host> 0 :is offline
+
+ if(msg->connection()->notifyListManager())
+ {
+ if(msg->connection()->notifyListManager()->handleWatchReply(msg))return;
+ }
+ // not handled...output it
+
+// FIXME: #warning "OUTPUT IT! (In a suitable way) (And handle 602 , 603 , 606 and 607 gracefully)"
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolServerRepliesToActiveWindow) ?
+ msg->console()->activeWindow() : (KviWindow *)(msg->console());
+ pOut->output(KVI_OUT_UNHANDLED,
+ "[%s][%s] %s",msg->prefix(),msg->command(),msg->allParams());
+ }
+}
+
+void KviServerParser::parseNumericStats(KviIrcMessage * msg)
+{
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = (KviWindow *)(msg->console());
+ if(msg->paramCount() > 2)
+ {
+ KviStr szParms;
+ KviStr *p = msg->firstParam();
+ for(p = msg->nextParam();p;p = msg->nextParam())
+ {
+ if(szParms.hasData())szParms.append(' ');
+ szParms.append(*p);
+ }
+ pOut->outputNoFmt(KVI_OUT_STATS,msg->connection()->decodeText(szParms).utf8().data());
+ } else {
+ pOut->outputNoFmt(KVI_OUT_STATS,msg->connection()->decodeText(msg->safeTrailing()).utf8().data());
+ }
+ }
+}
+
+void KviServerParser::parseNumericServerAdminInfoTitle(KviIrcMessage * msg)
+{
+ //RPL_ADMINME 256
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = (KviWindow *)(msg->console());
+ pOut->outputNoFmt(KVI_OUT_SERVERINFO,msg->connection()->decodeText(msg->safeTrailing()).utf8().data());
+ }
+}
+void KviServerParser::parseNumericServerAdminInfoServerName(KviIrcMessage * msg)
+{
+ //RPL_ADMINLOC1 257
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = (KviWindow *)(msg->console());
+ QString szInfo = msg->connection()->decodeText(msg->safeTrailing());
+ pOut->output(KVI_OUT_SERVERINFO,__tr2qs("%c\r!s\r%s\r%c's server info: %s"),KVI_TEXT_BOLD,msg->prefix(),KVI_TEXT_BOLD,szInfo.utf8().data());
+ }
+}
+
+void KviServerParser::parseNumericServerAdminInfoAdminName(KviIrcMessage * msg)
+{
+ //RPL_ADMINLOC2 258
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = (KviWindow *)(msg->console());
+ QString szInfo = msg->connection()->decodeText(msg->safeTrailing());
+ pOut->output(KVI_OUT_SERVERINFO,__tr2qs("%c\r!s\r%s\r%c's administrator is %s"),KVI_TEXT_BOLD,msg->prefix(),KVI_TEXT_BOLD,szInfo.utf8().data());
+ }
+}
+
+void KviServerParser::parseNumericServerAdminInfoAdminContact(KviIrcMessage * msg)
+{
+ //RPL_ADMINEMAIL 259
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = (KviWindow *)(msg->console());
+ QString szInfo = msg->connection()->decodeText(msg->safeTrailing());
+ pOut->output(KVI_OUT_SERVERINFO,__tr2qs("%c\r!s\r%s\r%c's contact adress is %s"),KVI_TEXT_BOLD,msg->prefix(),KVI_TEXT_BOLD,szInfo.utf8().data());
+ }
+}
+
+void KviServerParser::parseNumericCommandSyntax(KviIrcMessage * msg)
+{
+ //RPL_COMMANDSYNTAX 334
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = (KviWindow *)(msg->console());
+ pOut->outputNoFmt(KVI_OUT_STATS,msg->connection()->decodeText(msg->safeTrailing()));
+ }
+}
+
+void KviServerParser::parseNumericInviting(KviIrcMessage * msg)
+{
+ //RPL_INVITING 341
+ if(!msg->haltOutput())
+ {
+ QString szWho = msg->connection()->decodeText(msg->safeParam(0));
+ QString szTarget = msg->connection()->decodeText(msg->safeParam(1));
+ QString szChan = msg->connection()->decodeText(msg->safeParam(2));
+ KviChannel * chan = msg->connection()->findChannel(szChan);
+ if(chan)
+ {
+ chan->output(KVI_OUT_INVITE,__tr2qs("\r!n\r%Q\r invited %Q into channel %Q"),&szWho,&szTarget,&szChan);
+ } else {
+ KviWindow * pOut = (KviWindow *)(msg->console());
+ pOut->output(KVI_OUT_INVITE,__tr2qs("\r!n\r%Q\r invited %Q into channel %Q"),&szWho,&szTarget,&szChan);
+ }
+ }
+}
+
+void KviServerParser::parseNumericInfo(KviIrcMessage * msg)
+{
+ //RPL_INFO 371
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = (KviWindow *)(msg->console());
+ QString szInfo = msg->connection()->decodeText(msg->safeTrailing());
+ pOut->outputNoFmt(KVI_OUT_SERVERINFO,szInfo);
+ }
+}
+
+void KviServerParser::parseNumericInfoStart(KviIrcMessage * msg)
+{
+ //RPL_INFOSTART 373
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = (KviWindow *)(msg->console());
+ pOut->output(KVI_OUT_SERVERINFO,__tr2qs("%c\r!s\r%s\r%c's information:"),KVI_TEXT_BOLD,msg->prefix(),KVI_TEXT_BOLD);
+ }
+}
+
+void KviServerParser::parseNumericInfoEnd(KviIrcMessage * msg)
+{
+ //RPL_ENDOFINFO 374
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = (KviWindow *)(msg->console());
+ pOut->output(KVI_OUT_SERVERINFO,__tr2qs("End of %c\r!s\r%s\r%c's information"),KVI_TEXT_BOLD,msg->prefix(),KVI_TEXT_BOLD);
+ }
+}
+
+void KviServerParser::parseNumericTime(KviIrcMessage * msg)
+{
+ //RPL_TIME 391
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = (KviWindow *)(msg->console());
+ QString szInfo = msg->connection()->decodeText(msg->safeTrailing());
+ pOut->output(KVI_OUT_SERVERINFO,__tr2qs("%c\r!s\r%s\r%c's time is %Q"),KVI_TEXT_BOLD,msg->prefix(),KVI_TEXT_BOLD,&szInfo);
+ }
+}
+
+void KviServerParser::parseNumericNoSuchServer(KviIrcMessage * msg)
+{
+ //ERR_NOSUCHSERVER 402
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = (KviWindow *)(msg->console());
+ QString szWhat = msg->connection()->decodeText(msg->safeParam(1));
+ pOut->output(KVI_OUT_GENERICERROR,__tr2qs("%Q: no such server"),&szWhat);
+ }
+}
+
+void KviServerParser::parseNumericNoSuchChannel(KviIrcMessage * msg)
+{
+ // ERR_NOSUCHCHANNEL 403
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = (KviWindow *)(msg->console());
+ QString szWhat = msg->connection()->decodeText(msg->safeParam(1));
+ pOut->output(KVI_OUT_GENERICERROR,__tr2qs("%Q: no such channel"),&szWhat);
+ }
+}
+
+void KviServerParser::parseNumericCannotSendColor(KviIrcMessage * msg)
+{
+ // ERR_NOCOLORSONCHAN 408
+ if(!msg->haltOutput())
+ {
+ QString szChan = msg->connection()->decodeText(msg->safeParam(1));
+ QString szInfo = msg->connection()->decodeText(msg->safeTrailing());
+ KviChannel * chan = msg->connection()->findChannel(szChan);
+ if(chan)
+ {
+ chan->output(KVI_OUT_GENERICERROR,__tr2qs("Cannot sent to channel: %Q"),&szInfo);
+ } else {
+ KviWindow * pOut = (KviWindow *)(msg->console());
+ pOut->output(KVI_OUT_GENERICERROR,__tr2qs("Cannot sent text to channel %Q: %Q"),&szChan,&szInfo);
+ }
+ }
+}
+
+void KviServerParser::parseNumericCannotSend(KviIrcMessage * msg)
+{
+ // ERR_CANNOTSENDTOCHAN 404
+ if(!msg->haltOutput())
+ {
+ QString szChan = msg->connection()->decodeText(msg->safeParam(1));
+ QString szInfo = msg->connection()->decodeText(msg->safeTrailing());
+ KviChannel * chan = msg->connection()->findChannel(szChan);
+ if(chan)
+ {
+ chan->output(KVI_OUT_GENERICERROR,__tr2qs("Cannot sent to channel"));
+ } else {
+ KviWindow * pOut = (KviWindow *)(msg->console());
+ pOut->output(KVI_OUT_GENERICERROR,__tr2qs("Cannot sent text to channel %Q"),&szChan);
+ }
+ }
+}
+
+
+void KviServerParser::parseNumericCodePageSet(KviIrcMessage *msg)
+{
+ // a nice extension for irc.wenet.ru
+ // 700: RPL_CODEPAGESET
+ // :prefix 700 target <encoding> :is now your translation scheme
+
+ QString encoding = msg->connection()->decodeText(msg->safeParam(1));
+ if(msg->connection()->serverInfo()->supportsCodePages())
+ {
+ if(encoding=="NONE") encoding="KOI8-R"; //RusNet default codepage
+ msg->console()->output(KVI_OUT_TEXTENCODING,__tr2qs("Your encoding is now %Q"),&encoding);
+ msg->console()->setTextEncoding(encoding);
+ msg->connection()->setEncoding(encoding);
+ } else {
+ QString szMe = msg->connection()->decodeText(msg->safeParam(0));
+ if( (szMe==msg->connection()->currentNickName() || szMe == "*" ) //fix for pre-login codepage message
+ && KviLocale::codecForName(encoding.utf8().data()))
+ {
+ msg->console()->output(KVI_OUT_TEXTENCODING,__tr2qs("Your encoding is now %Q"),&encoding);
+ msg->console()->setTextEncoding(encoding);
+ msg->connection()->setEncoding(encoding);
+ } else if(!msg->haltOutput()) // simply unhandled
+ {
+ QString szWText = msg->connection()->decodeText(msg->allParams());
+ msg->connection()->console()->output(KVI_OUT_UNHANDLED,
+ "[%s][%s] %Q",msg->prefix(),msg->command(),&szWText);
+ }
+ }
+}
+
+void KviServerParser::parseNumericCodePageScheme(KviIrcMessage *msg)
+{
+ // a nice extension for irc.wenet.ru
+ // 703: RPL_WHOISSCHEME
+ // :prefix 703 <mynick> <nick> <encoding> :translation scheme
+
+ msg->connection()->stateData()->setLastReceivedWhoisReply(kvi_unixTime());
+
+ if(msg->connection()->serverInfo()->supportsCodePages())
+ {
+ QString szNick = msg->connection()->decodeText(msg->safeParam(1));
+ QString szCodepage = msg->connection()->decodeText(msg->safeParam(2));
+
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolWhoisRepliesToActiveWindow) ?
+ msg->console()->activeWindow() : (KviWindow *)(msg->console());
+ QString szWText = pOut->decodeText(msg->safeTrailing());
+ pOut->output(
+ KVI_OUT_WHOISOTHER,__tr2qs("%c\r!n\r%Q\r%c's codepage is %Q: %Q"),KVI_TEXT_BOLD,
+ &szNick,KVI_TEXT_BOLD,&szCodepage,&szWText);
+ }
+ } else {
+ // simply unhandled
+ if(!msg->haltOutput())
+ {
+ QString szWText = msg->connection()->decodeText(msg->allParams());
+ msg->connection()->console()->output(KVI_OUT_UNHANDLED,
+ "[%s][%s] %Q",msg->prefix(),msg->command(),&szWText);
+ }
+ }
+}
+
+void KviServerParser::parseNumericUserMode(KviIrcMessage *msg)
+{
+ // 321: RPL_UMODEIS [I,E,U,D]
+ // :prefix 221 <target> <modeflags>
+ parseUserMode(msg,msg->safeParam(1));
+
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolServerRepliesToActiveWindow) ?
+ msg->console()->activeWindow() : (KviWindow *)(msg->console());
+ pOut->output(KVI_OUT_MODE,__tr2qs("Your user mode is %s"),msg->safeParam(1));
+ }
+}
+
+void KviServerParser::parseNumericEndOfStats(KviIrcMessage *msg)
+{
+ if(!msg->haltOutput())
+ {
+ KviWindow * pOut = (KviWindow *)(msg->console());
+ QString szText = msg->connection()->decodeText(msg->safeTrailing());
+ pOut->outputNoFmt(KVI_OUT_STATS, szText);
+ }
+}
diff --git a/src/kvirc/sparser/kvi_sp_tables.cpp b/src/kvirc/sparser/kvi_sp_tables.cpp
new file mode 100644
index 00000000..948a5c0e
--- /dev/null
+++ b/src/kvirc/sparser/kvi_sp_tables.cpp
@@ -0,0 +1,1089 @@
+//
+// File : kvi_sp_tables.cpp
+// Creation date : Sun Jun 30 2000 18:10:19 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+#define __KVIRC__
+
+#include "kvi_sparser.h"
+
+// FIXME: #warning "Reorder this table!"
+#define PTM(__m) KVI_PTR2MEMBER(KviServerParser::__m)
+
+KviLiteralMessageParseStruct KviServerParser::m_literalParseProcTable[]=
+{
+ { "PRIVMSG" , PTM(parseLiteralPrivmsg)},
+ { "PING" , PTM(parseLiteralPing) },
+ { "MODE" , PTM(parseLiteralMode) },
+ { "TOPIC" , PTM(parseLiteralTopic) },
+ { "JOIN" , PTM(parseLiteralJoin) },
+ { "PART" , PTM(parseLiteralPart) },
+ { "QUIT" , PTM(parseLiteralQuit) },
+ { "NICK" , PTM(parseLiteralNick) },
+ { "KICK" , PTM(parseLiteralKick) },
+ { "NOTICE" , PTM(parseLiteralNotice) },
+ { "INVITE" , PTM(parseLiteralInvite) },
+ { "WALLOPS" , PTM(parseLiteralWallops)},
+ { "PONG" , PTM(parseLiteralPong) },
+ { "ERROR" , PTM(parseLiteralError) },
+ { 0 , 0 }
+};
+
+// FIXME: #warning "Merge these two tables into one"
+
+KviCtcpMessageParseStruct KviServerParser::m_ctcpRequestParseProcTable[]=
+{
+ { "PING" , PTM(parseCtcpRequestPing) , 0 },
+ { "VERSION" , PTM(parseCtcpRequestVersion) , 0 },
+ { "USERINFO" , PTM(parseCtcpRequestUserinfo) , 0 },
+ { "CLIENTINFO" , PTM(parseCtcpRequestClientinfo) , 0 },
+ { "FINGER" , PTM(parseCtcpRequestFinger) , 0 },
+ { "SOURCE" , PTM(parseCtcpRequestSource) , 0 },
+ { "TIME" , PTM(parseCtcpRequestTime) , 0 },
+ { "ACTION" , PTM(parseCtcpRequestAction) , 0 },
+ { "AVATAR" , PTM(parseCtcpRequestAvatar) , 0 },
+ { "DCC" , PTM(parseCtcpRequestDcc) , 0 },
+ { "TDCC" , PTM(parseCtcpRequestDcc) , 0 },
+ { "XDCC" , PTM(parseCtcpRequestDcc) , 0 },
+ { "PAGE" , PTM(parseCtcpRequestPage) , 0 },
+ { 0 , 0 , 0 }
+};
+
+KviCtcpMessageParseStruct KviServerParser::m_ctcpReplyParseProcTable[]=
+{
+ { "AVATAR" , PTM(parseCtcpReplyAvatar) , 0 },
+ { "ACTION" , PTM(parseCtcpRequestAction) , 0 },
+ { "DCC" , PTM(parseCtcpRequestDcc) , 0 },
+ { "TDCC" , PTM(parseCtcpRequestDcc) , 0 },
+ { "XDCC" , PTM(parseCtcpRequestDcc) , 0 },
+ { "VERSION" , PTM(parseCtcpReplyGeneric) , 0 },
+ { "USERINFO" , PTM(parseCtcpReplyUserinfo) , 0 },
+ { "CLIENTINFO" , PTM(parseCtcpReplyGeneric) , 0 },
+ { "FINGER" , PTM(parseCtcpReplyGeneric) , 0 },
+ { "TIME" , PTM(parseCtcpReplyGeneric) , 0 },
+ { "SOURCE" , PTM(parseCtcpReplyGeneric) , 0 },
+ { "PING" , PTM(parseCtcpReplyPing) , 0 },
+ { "PAGE" , PTM(parseCtcpReplyGeneric) , 0 },
+ { "LAGCHECK" , PTM(parseCtcpReplyLagcheck) , KVI_CTCP_MESSAGE_PARSE_TRIGGERNOEVENT },
+ { 0 , 0 , 0 }
+};
+
+messageParseProc KviServerParser::m_numericParseProcTable[1000]=
+{
+ 0, // 000
+ PTM(parseNumeric001) , // 001 RPL_WELCOME
+ PTM(parseNumeric002) , // 002 RPL_YOURHOST
+ PTM(parseNumeric003) , // 003 RPL_CREATED
+ PTM(parseNumeric004) , // 004 RPL_MYINFO
+ PTM(parseNumeric005) , // 005 RPL_BOUNCE, RPL_PROTOCTL
+ 0, // 006
+ 0, // 007
+ 0, // 008
+ 0, // 009
+ 0, // 010
+ 0, // 011
+ 0, // 012
+ 0, // 013
+ 0, // 014
+ 0, // 015
+ 0, // 016
+ 0, // 017
+ 0, // 018
+ 0, // 019
+ PTM(parseNumeric020) , // 020
+ 0, // 021
+ 0, // 022
+ 0, // 023
+ 0, // 024
+ 0, // 025
+ 0, // 026
+ 0, // 027
+ 0, // 028
+ 0, // 029
+ 0, // 030
+ 0, // 031
+ 0, // 032
+ 0, // 033
+ 0, // 034
+ 0, // 035
+ 0, // 036
+ 0, // 037
+ 0, // 038
+ 0, // 039
+ 0, // 040
+ 0, // 041
+ 0, // 042
+ 0, // 043
+ 0, // 044
+ 0, // 045
+ 0, // 046
+ 0, // 047
+ 0, // 048
+ 0, // 049
+ 0, // 050
+ 0, // 051
+ 0, // 052
+ 0, // 053
+ 0, // 054
+ 0, // 055
+ 0, // 056
+ 0, // 057
+ 0, // 058
+ 0, // 059
+ 0, // 060
+ 0, // 061
+ 0, // 062
+ 0, // 063
+ 0, // 064
+ 0, // 065
+ 0, // 066
+ 0, // 067
+ 0, // 068
+ 0, // 069
+ 0, // 070
+ 0, // 071
+ 0, // 072
+ 0, // 073
+ 0, // 074
+ 0, // 075
+ 0, // 076
+ 0, // 077
+ 0, // 078
+ 0, // 079
+ 0, // 080
+ 0, // 081
+ 0, // 082
+ 0, // 083
+ 0, // 084
+ 0, // 085
+ 0, // 086
+ 0, // 087
+ 0, // 088
+ 0, // 089
+ 0, // 090
+ 0, // 091
+ 0, // 092
+ 0, // 093
+ 0, // 094
+ 0, // 095
+ 0, // 096
+ 0, // 097
+ 0, // 098
+ 0, // 099
+ 0, // 100
+ 0, // 101
+ 0, // 102
+ 0, // 103
+ 0, // 104
+ 0, // 105
+ 0, // 106
+ 0, // 107
+ 0, // 108
+ 0, // 109
+ 0, // 110
+ 0, // 111
+ 0, // 112
+ 0, // 113
+ 0, // 114
+ 0, // 115
+ 0, // 116
+ 0, // 117
+ 0, // 118
+ 0, // 119
+ 0, // 120
+ 0, // 121
+ 0, // 122
+ 0, // 123
+ 0, // 124
+ 0, // 125
+ 0, // 126
+ 0, // 127
+ 0, // 128
+ 0, // 129
+ 0, // 130
+ 0, // 131
+ 0, // 132
+ 0, // 133
+ 0, // 134
+ 0, // 135
+ 0, // 136
+ 0, // 137
+ 0, // 138
+ 0, // 139
+ 0, // 140
+ 0, // 141
+ 0, // 142
+ 0, // 143
+ 0, // 144
+ 0, // 145
+ 0, // 146
+ 0, // 147
+ 0, // 148
+ 0, // 149
+ 0, // 150
+ 0, // 151
+ 0, // 152
+ 0, // 153
+ 0, // 154
+ 0, // 155
+ 0, // 156
+ 0, // 157
+ 0, // 158
+ 0, // 159
+ 0, // 160
+ 0, // 161
+ 0, // 162
+ 0, // 163
+ 0, // 164
+ 0, // 165
+ 0, // 166
+ 0, // 167
+ 0, // 168
+ 0, // 169
+ 0, // 170
+ 0, // 171
+ 0, // 172
+ 0, // 173
+ 0, // 174
+ 0, // 175
+ 0, // 176
+ 0, // 177
+ 0, // 178
+ 0, // 179
+ 0, // 180
+ 0, // 181
+ 0, // 182
+ 0, // 183
+ 0, // 184
+ 0, // 185
+ 0, // 186
+ 0, // 187
+ 0, // 188
+ 0, // 189
+ 0, // 190
+ 0, // 191
+ 0, // 192
+ 0, // 193
+ 0, // 194
+ 0, // 195
+ 0, // 196
+ 0, // 197
+ 0, // 198
+ 0, // 199
+ 0, // 200
+ 0, // 201
+ 0, // 202
+ 0, // 203
+ 0, // 204
+ 0, // 205
+ 0, // 206
+ 0, // 207
+ 0, // 208
+ 0, // 209
+ 0, // 210
+ 0, // 211
+ 0, // 212
+ 0, // 213
+ 0, // 214
+ 0, // 215
+ 0, // 216
+ 0, // 217
+ 0, // 218
+ PTM(parseNumericEndOfStats), // 219 RPL_ENDOFSTATS
+ 0, // 220
+ PTM(parseNumericUserMode) , // 221 RPL_UMODEIS
+ PTM(parseNumericCodePageSet), // 222 RusNet Codepage set
+ 0, // 223
+ 0, // 224
+ 0, // 225
+ 0, // 226
+ 0, // 227
+ 0, // 228
+ 0, // 229
+ 0, // 230
+ 0, // 231
+ 0, // 232
+ 0, // 233
+ 0, // 234
+ 0, // 235
+ 0, // 236
+ 0, // 237
+ 0, // 238
+ PTM(parseNumericStats) , // 239 RPL_STATSIAUTH
+ PTM(parseNumericStats) , // 240 RPL_STATSVLINE
+ PTM(parseNumericStats) , // 241 RPL_STATSLLINE
+ PTM(parseNumericStats) , // 242 RPL_STATSUPTIME
+ PTM(parseNumericStats) , // 243 RPL_STATSOLINE
+ PTM(parseNumericStats) , // 244 RPL_STATSHLINE
+ PTM(parseNumericStats) , // 245 RPL_STATSSLINE
+ PTM(parseNumericStats) , // 246 RPL_STATSPING RPL_STATSTLINE
+ PTM(parseNumericStats) , // 247 RPL_STATSBLINE_I RPL_STATSGLINE RPL_STATSXLINE
+ PTM(parseNumericStats) , // 248 RPL_STATSDEFINE RPL_STATSULINE
+ PTM(parseNumericStats) , // 249 RPL_STATSDEBUG
+ PTM(parseNumericStats) , // 250 RPL_STATSCONN RPL_STATSDLINE_I
+ PTM(parseNumericStats) , // 251 RPL_LUSERCLIENT
+ PTM(parseNumericStats) , // 252 RPL_LUSEROP
+ PTM(parseNumericStats) , // 253 RPL_LUSERUNKNOWN
+ PTM(parseNumericStats) , // 254 RPL_LUSERCHANNELS
+ PTM(parseNumericStats) , // 255 RPL_LUSERME
+ PTM(parseNumericServerAdminInfoTitle) , // 256 RPL_ADMINME
+ PTM(parseNumericServerAdminInfoServerName) , // 257 RPL_ADMINLOC1
+ PTM(parseNumericServerAdminInfoAdminName) , // 258 RPL_ADMINLOC2
+ PTM(parseNumericServerAdminInfoAdminContact) , // 259 RPL_ADMINEMAIL
+ 0, // 260
+ 0, // 261
+ 0, // 262
+ 0, // 263
+ 0, // 264
+ PTM(parseNumericStats) , // 265 RPL_LOCALUSERS
+ PTM(parseNumericStats) , // 266 RPL_GLOBALUSERS
+ PTM(parseNumericStats) , // 267 RPL_SHAREDUSERS
+ 0, // 268
+ 0, // 269
+ 0, // 270
+ 0, // 271
+ 0, // 272
+ 0, // 273
+ 0, // 274
+ PTM(parseNumericWhoisOther) , // 275 RPL_WHOISSSL
+ 0, // 276
+ 0, // 277
+ 0, // 278
+ 0, // 279
+ 0, // 280
+ 0, // 281
+ 0, // 282
+ 0, // 283
+ 0, // 284
+ 0, // 285
+ 0, // 286
+ 0, // 287
+ 0, // 288
+ 0, // 289
+ 0, // 290
+ 0, // 291
+ 0, // 292
+ 0, // 293
+ 0, // 294
+ 0, // 295
+ 0, // 296
+ 0, // 297
+ 0, // 298
+ 0, // 299
+ 0, // 300
+ PTM(parseNumericWhoisAway) , // 301
+ PTM(parseNumericUserhost) , // 302 RPL_USERHOST
+ PTM(parseNumericIsOn) , // 303 RPL_ISON
+ 0, // 304
+ PTM(parseNumericBackFromAway) , // 305 RPL_UNAWAY
+ PTM(parseNumericAway) , // 306 RPL_NOWAWAY
+ PTM(parseNumericWhoisOther) , // 307 RPL_WHOISREGNICK
+ PTM(parseNumericWhoisOther) , // 308 RPL_WHOISADMIN
+ PTM(parseNumericWhoisOther) , // 309 RPL_WHOISSADMIN
+ PTM(parseNumericWhoisOther) , // 310 RPL_WHOISHELPOP
+ PTM(parseNumericWhoisUser) , // 311 RPL_WHOISUSER
+ PTM(parseNumericWhoisServer) , // 312 RPL_WHOISSERVER
+ PTM(parseNumericWhoisOther) , // 313 RPL_WHOISOPERATOR
+ PTM(parseNumericWhowasUser) , // 314 RPL_WHOWASUSER
+ PTM(parseNumericEndOfWho) , // 315 RPL_ENDOFWHO
+ PTM(parseNumericWhoisOther) , // 316 RPL_WHOISCHANOP
+ PTM(parseNumericWhoisIdle) , // 317 RPL_WHOISIDLE
+ PTM(parseNumericEndOfWhois) , // 318 RPL_ENDOFWHOIS
+ PTM(parseNumericWhoisChannels) , // 319 RPL_WHOISCHANNELS
+ PTM(parseNumericWhoisOther) , // 320 RPL_WHOISIDENTIFIED
+ PTM(parseNumericListStart) , // 321 RPL_LISTSTART
+ PTM(parseNumericList) , // 322 RPL_LIST
+ PTM(parseNumericListEnd) , // 323 RPL_LISTEND
+ PTM(parseNumericChannelModeIs) , // 324 RPL_CHANNELMODEIS
+ 0, // 325
+ 0, // 326
+ 0, // 327
+ 0, // 328
+ PTM(parseNumericCreationTime) , // 329 RPL_CREATIONTIME
+ PTM(parseNumericWhoisAuth) , // 330 RPL_WHOISAUTH
+ PTM(parseNumericNoTopic) , // 331 RPL_NOTOPIC
+ PTM(parseNumericTopic) , // 332 RPL_TOPIC
+ PTM(parseNumericTopicWhoTime) , // 333 RPL_TOPICWHOTIME
+ PTM(parseNumericCommandSyntax) , // 334 RPL_COMMANDSYNTAX
+ 0, // 335
+ 0, // 336
+ 0, // 337
+ PTM(parseNumericWhoisOther), // 338 RPL_WHOISACTUALLY
+ PTM(parseNumericWhoisOther), // 339
+ 0, // 340
+ PTM(parseNumericInviting) , // 351 RPL_INVITING
+ 0, // 342
+ 0, // 343
+ 0, // 344
+ 0, // 345
+ PTM(parseNumericInviteList) , // 346 RPL_INVITELIST
+ PTM(parseNumericEndOfInviteList) , // 347 RPL_ENDOFINVITELIST
+ PTM(parseNumericExceptList) , // 348 RPL_EXCEPTLIST
+ PTM(parseNumericEndOfExceptList) , // 349 RPL_ENDOFEXCEPTLIST
+ 0, // 350
+ 0, // 351
+ PTM(parseNumericWhoReply) , // 352 RPL_WHOREPLY
+ PTM(parseNumericNames) , // 353 RPL_NAMREPLY
+ 0, // 354
+ 0, // 355
+ 0, // 356
+ 0, // 357
+ 0, // 358
+ 0, // 359
+ 0, // 360
+ 0, // 361
+ 0, // 362
+ 0, // 363
+ PTM(parseNumericLinks) , // 364 RPL_LINKS
+ PTM(parseNumericEndOfLinks) , // 365 RPL_ENDOFLINKS
+ PTM(parseNumericEndOfNames) , // 366 RPL_ENDOFNAMES
+ PTM(parseNumericBanList) , // 367 RPL_BANLIST
+ PTM(parseNumericEndOfBanList) , // 368 RPL_ENDOFBANLIST
+ PTM(parseNumericEndOfWhowas) , // 369 RPL_ENDOFWHOWAS
+ 0, // 370
+ PTM(parseNumericInfo) , // 371 RPL_INFO
+ PTM(parseNumericMotd) , // 372 RPL_MOTD
+ PTM(parseNumericInfoStart) , // 373 RPL_INFOSTART
+ PTM(parseNumericInfoEnd) , // 374 RPL_ENDOFINFO
+ PTM(parseNumericMotd) , // 375 RPL_MOTDSTART
+ PTM(parseNumericMotd) , // 376 RPL_ENDOFMOTD
+ PTM(parseNumericMotd) , // 377 RPL_MOTD2
+ PTM(parseNumericMotd) , // 378 RPL_MOTD3
+ 0, // 379
+ 0, // 380
+ 0, // 381
+ 0, // 382
+ 0, // 383
+ 0, // 384
+ 0, // 385
+ 0, // 386
+ 0, // 387
+ 0, // 388
+ 0, // 389
+ 0, // 390
+ PTM(parseNumericTime) , // 391 RPL_TIME
+ 0, // 392
+ 0, // 393
+ 0, // 394
+ 0, // 395
+ 0, // 396
+ 0, // 397
+ 0, // 398
+ 0, // 399
+ 0, // 400
+ PTM(parseNumericNoSuchNick) , // 401 ERR_NOSUCHNICK
+ PTM(parseNumericNoSuchServer) , // 402 ERR_NOSUCHSERVER
+ PTM(parseNumericNoSuchChannel) , // 403 ERR_NOSUCHCHANNEL
+ PTM(parseNumericCannotSend) , // 404 ERR_CANNOTSENDTOCHAN
+ 0, // 405
+ PTM(parseNumericNoSuchNick) , // 406 ERR_WASNOSUCHNICK
+ 0, // 407
+ PTM(parseNumericCannotSendColor) , // 408 ERR_NOCOLORSONCHAN
+ 0, // 409
+ 0, // 410
+ 0, // 411
+ 0, // 412
+ 0, // 413
+ 0, // 414
+ 0, // 415
+ 0, // 416
+ 0, // 417
+ 0, // 418
+ 0, // 419
+ 0, // 420
+ 0, // 421
+ 0, // 422
+ 0, // 423
+ 0, // 424
+ 0, // 425
+ 0, // 426
+ 0, // 427
+ 0, // 428
+ 0, // 429
+ 0, // 430
+ 0, // 431
+ PTM(parseNumericNicknameProblem) , // 432 ERR_ERRONEUSNICKNAME
+ PTM(parseNumericNicknameProblem) , // 433 ERR_NICKNAMEINUSE
+ 0, // 434
+ 0, // 435
+ 0, // 436
+ PTM(parseNumericUnavailResource) , // 437 ERR_UNAVAILRESOURCE
+ 0, // 438
+ 0, // 439
+ 0, // 440
+ 0, // 441
+ 0, // 442
+ 0, // 443
+ 0, // 444
+ 0, // 445
+ 0, // 446
+ 0, // 447
+ 0, // 448
+ 0, // 449
+ 0, // 450
+ 0, // 451
+ 0, // 452
+ 0, // 453
+ 0, // 454
+ 0, // 455
+ 0, // 456
+ 0, // 457
+ 0, // 458
+ 0, // 459
+ 0, // 460
+ 0, // 461
+ 0, // 462
+ 0, // 463
+ 0, // 464
+ 0, // 465
+ 0, // 466
+ PTM(otherChannelError), // 467 ERR_KEYSET
+ 0, // 468
+ 0, // 469
+ 0, // 470
+ PTM(parseNumericCantJoinChannel) , // 471 ERR_CHANNELISFULL
+ PTM(otherChannelError), // 472 ERR_UNKNOWNMODE
+ PTM(parseNumericCantJoinChannel) , // 473 ERR_INVITEONLYCHAN
+ PTM(parseNumericCantJoinChannel) , // 474 ERR_BANNEDFROMCHAN
+ PTM(parseNumericCantJoinChannel) , // 475 ERR_BADCHANNELKEY
+ 0, // 476
+ PTM(parseChannelHelp), // 477 RPL_CHANNELHELP
+ 0, // 478
+ 0, // 479
+ 0, // 480
+ 0, // 481
+ PTM(otherChannelError), // 482 ERR_CHANOPRIVSNEEDED
+ 0, // 483
+ 0, // 484
+ 0, // 485
+ 0, // 486
+ 0, // 487
+ 0, // 488
+ 0, // 489
+ 0, // 490
+ 0, // 491
+ 0, // 492
+ 0, // 493
+ 0, // 494
+ 0, // 495
+ 0, // 496
+ 0, // 497
+ 0, // 498
+ 0, // 499
+ 0, // 500
+ 0, // 501
+ 0, // 502
+ 0, // 503
+ 0, // 504
+ 0, // 505
+ 0, // 506
+ 0, // 507
+ 0, // 508
+ 0, // 509
+ 0, // 510
+ 0, // 511
+ 0, // 512
+ 0, // 513
+ 0, // 514
+ 0, // 515
+ 0, // 516
+ 0, // 517
+ 0, // 518
+ 0, // 519
+ 0, // 520
+ 0, // 521
+ 0, // 522
+ 0, // 523
+ 0, // 524
+ 0, // 525
+ 0, // 526
+ 0, // 527
+ 0, // 528
+ 0, // 529
+ 0, // 530
+ 0, // 531
+ 0, // 532
+ 0, // 533
+ 0, // 534
+ 0, // 535
+ 0, // 536
+ 0, // 537
+ 0, // 538
+ 0, // 539
+ 0, // 540
+ 0, // 541
+ 0, // 542
+ 0, // 543
+ 0, // 544
+ 0, // 545
+ 0, // 546
+ 0, // 547
+ 0, // 548
+ 0, // 549
+ 0, // 550
+ 0, // 551
+ 0, // 552
+ 0, // 553
+ 0, // 554
+ 0, // 555
+ 0, // 556
+ 0, // 557
+ 0, // 558
+ 0, // 559
+ 0, // 560
+ 0, // 561
+ 0, // 562
+ 0, // 563
+ 0, // 564
+ 0, // 565
+ 0, // 566
+ 0, // 567
+ 0, // 568
+ 0, // 569
+ 0, // 570
+ 0, // 571
+ 0, // 572
+ 0, // 573
+ 0, // 574
+ 0, // 575
+ 0, // 576
+ 0, // 577
+ 0, // 578
+ 0, // 579
+ 0, // 580
+ 0, // 581
+ 0, // 582
+ 0, // 583
+ 0, // 584
+ 0, // 585
+ 0, // 586
+ 0, // 587
+ 0, // 588
+ 0, // 589
+ 0, // 590
+ 0, // 591
+ 0, // 592
+ 0, // 593
+ 0, // 594
+ 0, // 595
+ 0, // 596
+ 0, // 597
+ 0, // 598
+ 0, // 599
+ PTM(parseNumericWatch) , // 600 RPL_LOGON
+ PTM(parseNumericWatch) , // 601 RPL_LOGOFF
+ PTM(parseNumericWatch) , // 602 RPL_WATCHOFF
+ 0, // 603 RPL_WATCHSTAT
+ PTM(parseNumericWatch) , // 604 RPL_NOWON
+ PTM(parseNumericWatch) , // 605 RPL_NOWOFF
+ 0, // 606 RPL_WATCHLIST
+ 0, // 607 RPL_ENDOFWATCH
+ 0, // 608
+ 0, // 609
+ 0, // 610
+ 0, // 611
+ 0, // 612
+ 0, // 613
+ 0, // 614
+ 0, // 615
+ 0, // 616
+ 0, // 617
+ 0, // 618
+ 0, // 619
+ 0, // 620
+ 0, // 621
+ 0, // 622
+ 0, // 623
+ 0, // 624
+ 0, // 625
+ 0, // 626
+ 0, // 627
+ 0, // 628
+ 0, // 629
+ 0, // 630
+ 0, // 631
+ 0, // 632
+ 0, // 633
+ 0, // 634
+ 0, // 635
+ 0, // 636
+ 0, // 637
+ 0, // 638
+ 0, // 639
+ 0, // 640
+ 0, // 641
+ 0, // 642
+ 0, // 643
+ 0, // 644
+ 0, // 645
+ 0, // 646
+ 0, // 647
+ 0, // 648
+ 0, // 649
+ 0, // 650
+ 0, // 651
+ 0, // 652
+ 0, // 653
+ 0, // 654
+ 0, // 655
+ 0, // 656
+ 0, // 657
+ 0, // 658
+ 0, // 659
+ 0, // 660
+ 0, // 661
+ 0, // 662
+ 0, // 663
+ 0, // 664
+ 0, // 665
+ 0, // 666
+ 0, // 667
+ 0, // 668
+ 0, // 669
+ 0, // 670
+ 0, // 671
+ 0, // 672
+ 0, // 673
+ 0, // 674
+ 0, // 675
+ 0, // 676
+ 0, // 677
+ 0, // 678
+ 0, // 679
+ 0, // 680
+ 0, // 681
+ 0, // 682
+ 0, // 683
+ 0, // 684
+ 0, // 685
+ 0, // 686
+ 0, // 687
+ 0, // 688
+ 0, // 689
+ 0, // 690
+ 0, // 691
+ 0, // 692
+ 0, // 693
+ 0, // 694
+ 0, // 695
+ 0, // 696
+ 0, // 697
+ 0, // 698
+ 0, // 699
+ PTM(parseNumericCodePageSet) , // 700 RPL_CODEPAGESET
+ 0, // 701
+ 0, // 702
+ PTM(parseNumericCodePageScheme) , // 703 RPL_WHOISSCHEME
+ PTM(parseCommandSyntaxHelp), // 704 RPL_COMMANDSYNTAX
+ PTM(parseCommandHelp), // 705 RPL_COMMANDHELP
+ PTM(parseCommandEndOfHelp), // 706 RPL_ENDOFCOMMANDHELP
+ 0, // 707
+ 0, // 708
+ 0, // 709
+ 0, // 710
+ 0, // 711
+ 0, // 712
+ 0, // 713
+ 0, // 714
+ 0, // 715
+ 0, // 716
+ 0, // 717
+ 0, // 718
+ 0, // 719
+ 0, // 720
+ 0, // 721
+ 0, // 722
+ 0, // 723
+ 0, // 724
+ 0, // 725
+ 0, // 726
+ 0, // 727
+ 0, // 728
+ 0, // 729
+ 0, // 730
+ 0, // 731
+ 0, // 732
+ 0, // 733
+ 0, // 734
+ 0, // 735
+ 0, // 736
+ 0, // 737
+ 0, // 738
+ 0, // 739
+ 0, // 740
+ 0, // 741
+ 0, // 742
+ 0, // 743
+ 0, // 744
+ 0, // 745
+ 0, // 746
+ 0, // 747
+ 0, // 748
+ 0, // 749
+ 0, // 750
+ 0, // 751
+ 0, // 752
+ 0, // 753
+ 0, // 754
+ 0, // 755
+ 0, // 756
+ 0, // 757
+ 0, // 758
+ 0, // 759
+ 0, // 760
+ 0, // 761
+ 0, // 762
+ 0, // 763
+ 0, // 764
+ 0, // 765
+ 0, // 766
+ 0, // 767
+ 0, // 768
+ 0, // 769
+ 0, // 770
+ 0, // 771
+ 0, // 772
+ 0, // 773
+ 0, // 774
+ 0, // 775
+ 0, // 776
+ 0, // 777
+ 0, // 778
+ 0, // 779
+ 0, // 780
+ 0, // 781
+ 0, // 782
+ 0, // 783
+ 0, // 784
+ 0, // 785
+ 0, // 786
+ 0, // 787
+ 0, // 788
+ 0, // 789
+ 0, // 790
+ 0, // 791
+ 0, // 792
+ 0, // 793
+ 0, // 794
+ 0, // 795
+ 0, // 796
+ 0, // 797
+ 0, // 798
+ 0, // 799
+ 0, // 800
+ 0, // 801
+ 0, // 802
+ 0, // 803
+ 0, // 804
+ 0, // 805
+ 0, // 806
+ 0, // 807
+ 0, // 808
+ 0, // 809
+ 0, // 810
+ 0, // 811
+ 0, // 812
+ 0, // 813
+ 0, // 814
+ 0, // 815
+ 0, // 816
+ 0, // 817
+ 0, // 818
+ 0, // 819
+ 0, // 820
+ 0, // 821
+ 0, // 822
+ 0, // 823
+ 0, // 824
+ 0, // 825
+ 0, // 826
+ 0, // 827
+ 0, // 828
+ 0, // 829
+ 0, // 830
+ 0, // 831
+ 0, // 832
+ 0, // 833
+ 0, // 834
+ 0, // 835
+ 0, // 836
+ 0, // 837
+ 0, // 838
+ 0, // 839
+ 0, // 840
+ 0, // 841
+ 0, // 842
+ 0, // 843
+ 0, // 844
+ 0, // 845
+ 0, // 846
+ 0, // 847
+ 0, // 848
+ 0, // 849
+ 0, // 850
+ 0, // 851
+ 0, // 852
+ 0, // 853
+ 0, // 854
+ 0, // 855
+ 0, // 856
+ 0, // 857
+ 0, // 858
+ 0, // 859
+ 0, // 860
+ 0, // 861
+ 0, // 862
+ 0, // 863
+ 0, // 864
+ 0, // 865
+ 0, // 866
+ 0, // 867
+ 0, // 868
+ 0, // 869
+ 0, // 870
+ 0, // 871
+ 0, // 872
+ 0, // 873
+ 0, // 874
+ 0, // 875
+ 0, // 876
+ 0, // 877
+ 0, // 878
+ 0, // 879
+ 0, // 880
+ 0, // 881
+ 0, // 882
+ 0, // 883
+ 0, // 884
+ 0, // 885
+ 0, // 886
+ 0, // 887
+ 0, // 888
+ 0, // 889
+ 0, // 890
+ 0, // 891
+ 0, // 892
+ 0, // 893
+ 0, // 894
+ 0, // 895
+ 0, // 896
+ 0, // 897
+ 0, // 898
+ 0, // 899
+ 0, // 900
+ 0, // 901
+ 0, // 902
+ 0, // 903
+ 0, // 904
+ 0, // 905
+ 0, // 906
+ 0, // 907
+ 0, // 908
+ 0, // 909
+ 0, // 910
+ 0, // 911
+ 0, // 912
+ 0, // 913
+ 0, // 914
+ 0, // 915
+ 0, // 916
+ 0, // 917
+ 0, // 918
+ 0, // 919
+ 0, // 920
+ 0, // 921
+ 0, // 922
+ 0, // 923
+ 0, // 924
+ 0, // 925
+ 0, // 926
+ 0, // 927
+ 0, // 928
+ 0, // 929
+ 0, // 930
+ 0, // 931
+ 0, // 932
+ 0, // 933
+ 0, // 934
+ 0, // 935
+ 0, // 936
+ 0, // 937
+ 0, // 938
+ 0, // 939
+ 0, // 940
+ 0, // 941
+ 0, // 942
+ 0, // 943
+ 0, // 944
+ 0, // 945
+ 0, // 946
+ 0, // 947
+ 0, // 948
+ 0, // 949
+ 0, // 950
+ 0, // 951
+ 0, // 952
+ 0, // 953
+ 0, // 954
+ 0, // 955
+ 0, // 956
+ 0, // 957
+ 0, // 958
+ 0, // 959
+ 0, // 960
+ 0, // 961
+ 0, // 962
+ 0, // 963
+ 0, // 964
+ 0, // 965
+ 0, // 966
+ 0, // 967
+ 0, // 968
+ 0, // 969
+ 0, // 970
+ 0, // 971
+ 0, // 972
+ 0, // 973
+ 0, // 974
+ 0, // 975
+ 0, // 976
+ 0, // 977
+ 0, // 978
+ 0, // 979
+ 0, // 980
+ 0, // 981
+ 0, // 982
+ 0, // 983
+ 0, // 984
+ 0, // 985
+ 0, // 986
+ 0, // 987
+ 0, // 988
+ 0, // 989
+ 0, // 990
+ 0, // 991
+ 0, // 992
+ 0, // 993
+ 0, // 994
+ 0, // 995
+ 0, // 996
+ 0, // 997
+ 0, // 998
+ 0 // 999
+};
diff --git a/src/kvirc/sparser/kvi_sparser.cpp b/src/kvirc/sparser/kvi_sparser.cpp
new file mode 100644
index 00000000..d0b69ea5
--- /dev/null
+++ b/src/kvirc/sparser/kvi_sparser.cpp
@@ -0,0 +1,150 @@
+//=============================================================================
+//
+// File : kvi_sparser.cpp
+// Creation date : Sun Jun 30 2000 03:25:17 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+#define __KVIRC__
+#define _KVI_SPARSER_CPP_
+
+#include "kvi_sparser.h"
+#include "kvi_window.h"
+#include "kvi_out.h"
+#include "kvi_locale.h"
+#include "kvi_ircsocket.h"
+#include "kvi_options.h"
+#include "kvi_kvs_eventmanager.h"
+#include "kvi_kvs_eventtriggers.h"
+#include "kvi_ircconnectionstatedata.h"
+
+KviServerParser * g_pServerParser = 0;
+
+
+KviServerParser::KviServerParser()
+: QObject(0,"server_parser")
+{
+}
+
+KviServerParser::~KviServerParser()
+{
+}
+
+void KviServerParser::parseMessage(const char * message,KviIrcConnection * pConnection)
+{
+ if(*message != 0 )
+ {
+ KviIrcMessage msg(message,pConnection);
+ if(msg.isNumeric())
+ {
+ if(KviKvsEventManager::instance()->hasRawHandlers(msg.numeric()))
+ {
+ KviKvsVariantList parms;
+ parms.append(pConnection->decodeText(msg.safePrefix()));
+ parms.append(pConnection->decodeText(msg.command()));
+
+ for(KviStr * str = msg.firstParam();str;str = msg.nextParam())
+ parms.append(pConnection->console()->decodeText(str->ptr()));
+
+ if(KviKvsEventManager::instance()->triggerRaw(msg.numeric(),pConnection->console(),&parms))
+ msg.setHaltOutput();
+ }
+
+ messageParseProc proc = m_numericParseProcTable[msg.numeric()];
+ if(proc)
+ {
+ (this->*proc)(&msg);
+ if(!msg.unrecognized())return; // parsed
+ } else {
+ // we don't have a proc for this
+
+ // special handling of unknown RPL_WHOIS* messages
+ // if
+ // - we're in the middle of a RPL_WHOIS* sequence (i.e. have received a RPL_WHOIS* message since less than 10 seconds)
+ // - we have not received RPL_ENDOFWHOIS yet (the time of the last RPL_WHOIS* is reset to zero when a RPL_ENDOFWHOIS is received)
+ // - this message is unrecognized and looks like a RPL_WHOIS*
+ // then pass it to the WhoisOther handler.
+ //
+ // Thnx Elephantman :)
+
+ if(msg.paramCount() >= 3) // might look like :prefix RPL_WHOIS* <target> <nick> [?] :<something>
+ {
+ kvi_time_t tNow = kvi_unixTime();
+
+ if((tNow - pConnection->stateData()->lastReceivedWhoisReply()) < 10)
+ {
+ // we're in the middle of a RPL_WHOIS* sequence and haven't
+ // received a RPL_ENDOFWHOIS yet.
+ parseNumericWhoisOther(&msg);
+ if(!msg.unrecognized())return;
+ }
+ }
+ }
+ } else {
+ for(int i=0;m_literalParseProcTable[i].msgName;i++)
+ {
+ if(kvi_strEqualCS(m_literalParseProcTable[i].msgName,msg.command()))
+ {
+ (this->*(m_literalParseProcTable[i].proc))(&msg);
+ if(!msg.unrecognized())return; // parsed
+ }
+ }
+
+
+ if(KviKvsEventManager::instance()->hasAppHandlers(KviEvent_OnUnhandledLiteral))
+ {
+ KviKvsVariantList parms;
+ parms.append(pConnection->decodeText(msg.safePrefix()));
+ parms.append(pConnection->decodeText(msg.command()));
+
+ for(KviStr * str = msg.firstParam();str;str = msg.nextParam())
+ parms.append(pConnection->console()->decodeText(str->ptr()));
+
+ if(KviKvsEventManager::instance()->trigger(KviEvent_OnUnhandledLiteral,pConnection->console(),&parms))
+ msg.setHaltOutput();
+ }
+
+ }
+
+ // unhandled || unrecognized
+ if(!msg.haltOutput() && !_OUTPUT_MUTE)
+ {
+ QString szWText = pConnection->decodeText(msg.allParams());
+ if(msg.unrecognized())
+ {
+ pConnection->console()->output(KVI_OUT_UNRECOGNIZED,
+ __tr2qs("[Server parser]: Encountered problems while parsing the following message:"));
+ pConnection->console()->output(KVI_OUT_UNRECOGNIZED,
+ __tr2qs("[Server parser]: [%s][%s] %Q"),msg.prefix(),msg.command(),&szWText);
+ pConnection->console()->output(KVI_OUT_UNRECOGNIZED,
+ __tr2qs("[Server parser]: %s"),m_szLastParserError.ptr());
+ } else {
+ // ignore spurious CRLF pairs (some servers send them a lot) unless we want PARANOID output
+ if((!msg.isEmpty()) || _OUTPUT_PARANOIC)
+ pConnection->console()->output(KVI_OUT_UNHANDLED,
+ "[%s][%s] %Q",msg.prefix(),msg.command(),&szWText);
+ }
+ }
+ }
+}
+
+
+
+
+#include "kvi_sparser.moc"
diff --git a/src/kvirc/sparser/kvi_sparser.h b/src/kvirc/sparser/kvi_sparser.h
new file mode 100644
index 00000000..72139ed7
--- /dev/null
+++ b/src/kvirc/sparser/kvi_sparser.h
@@ -0,0 +1,268 @@
+#ifndef _KVI_SPARSER_H_
+#define _KVI_SPARSER_H_
+
+//=============================================================================
+//
+// File : kvi_sparser.h
+// Creation date : Sat Jun 29 2000 14:23:11 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+
+#include "kvi_settings.h"
+
+#include <time.h>
+
+#include <qobject.h>
+#include "kvi_pointerlist.h"
+
+#include "kvi_qstring.h"
+#include "kvi_qcstring.h"
+#include "kvi_console.h"
+
+#include "kvi_ircmessage.h"
+
+class KviWindow;
+class KviChannel;
+class KviServerParser;
+class KviFrame;
+class KviIrcConnection;
+
+
+
+#define UNRECOGNIZED_MESSAGE(_msg,_err) \
+ _msg->setUnrecognized(); \
+ m_szLastParserError = _err;
+
+#define IS_ME(_msg,_nick) KviQString::equalCI(_msg->connection()->currentNickName(),_nick)
+
+typedef void (KviServerParser::*messageParseProc)(KviIrcMessage *);
+
+typedef struct _KviLiteralMessageParseStruct
+{
+ const char * msgName;
+ messageParseProc proc;
+} KviLiteralMessageParseStruct;
+
+class KviIrcMask;
+
+typedef struct _KviCtcpMessage
+{
+ KviIrcMessage * msg;
+ const char * pData;
+ QString szTarget;
+ KviIrcMask * pSource;
+ bool bIgnored;
+ bool bIsFlood;
+ bool bUnknown;
+
+ QString szTag;
+} KviCtcpMessage;
+
+typedef struct _KviDccRequest
+{
+ KviStr szType;
+ KviStr szParam1;
+ KviStr szParam2;
+ KviStr szParam3;
+ KviStr szParam4;
+ KviStr szParam5;
+ bool bIpV6;
+ KviCtcpMessage * ctcpMsg;
+ KviConsole * pConsole;
+} KviDccRequest;
+
+typedef void (KviServerParser::*ctcpParseProc)(KviCtcpMessage *);
+
+#define KVI_CTCP_MESSAGE_PARSE_TRIGGERNOEVENT 1
+
+typedef struct _KviCtcpMessageParseStruct
+{
+ const char * msgName;
+ ctcpParseProc proc;
+ int iFlags;
+} KviCtcpMessageParseStruct;
+
+
+#define EXTERNAL_SERVER_DATA_PARSER_CONTROL_RESET 0
+#define EXTERNAL_SERVER_DATA_PARSER_CONTROL_STARTOFDATA 1
+#define EXTERNAL_SERVER_DATA_PARSER_CONTROL_ENDOFDATA 2
+
+class KVIRC_API KviExternalServerDataParser
+{
+public:
+ KviExternalServerDataParser(){};
+ virtual ~KviExternalServerDataParser(){};
+public:
+ virtual void processData(KviIrcMessage *){};
+ virtual void control(int){};
+ virtual void die(){ delete this; };
+};
+
+
+class KVIRC_API KviServerParser : public QObject
+{
+ Q_OBJECT
+public:
+ KviServerParser();
+ ~KviServerParser();
+private:
+ static messageParseProc m_numericParseProcTable[1000];
+ static KviLiteralMessageParseStruct m_literalParseProcTable[];
+ static KviCtcpMessageParseStruct m_ctcpRequestParseProcTable[];
+ static KviCtcpMessageParseStruct m_ctcpReplyParseProcTable[];
+ KviStr m_szLastParserError;
+
+// KviStr m_szNoAwayNick; //<-- moved to kvi_console.h in KviConnectionInfo
+public:
+ void parseMessage(const char * message,KviIrcConnection *pConnection);
+private:
+ void parseNumeric001(KviIrcMessage *msg);
+ void parseNumeric002(KviIrcMessage *msg);
+ void parseNumeric003(KviIrcMessage *msg);
+ void parseNumeric004(KviIrcMessage *msg);
+ void parseNumeric005(KviIrcMessage *msg);
+
+ void parseNumericMotd(KviIrcMessage *msg);
+ void parseNumericNames(KviIrcMessage *msg);
+ void parseNumericEndOfNames(KviIrcMessage *msg);
+ void parseNumericTopic(KviIrcMessage *msg);
+ void parseNumericNoTopic(KviIrcMessage *msg);
+ void parseNumericTopicWhoTime(KviIrcMessage *msg);
+ void parseNumericChannelModeIs(KviIrcMessage *msg);
+ void parseNumericBanList(KviIrcMessage *msg);
+ void parseNumericEndOfBanList(KviIrcMessage *msg);
+ void parseNumericInviteList(KviIrcMessage *msg);
+ void parseNumericEndOfInviteList(KviIrcMessage *msg);
+ void parseNumericExceptList(KviIrcMessage *msg);
+ void parseNumericEndOfExceptList(KviIrcMessage *msg);
+ void parseNumericWhoReply(KviIrcMessage *msg);
+ void parseNumericEndOfWho(KviIrcMessage *msg);
+ void parseNumericNicknameProblem(KviIrcMessage *msg);
+ void parseNumericWhoisAway(KviIrcMessage *);
+ void parseNumericWhoisUser(KviIrcMessage *msg);
+ void parseNumericWhoisChannels(KviIrcMessage *msg);
+ void parseNumericWhoisIdle(KviIrcMessage *msg);
+ void parseNumericWhoisServer(KviIrcMessage *msg);
+ void parseNumericWhoisOther(KviIrcMessage *msg);
+ void parseNumericWhoisAuth(KviIrcMessage *msg);
+ void parseNumericWhowasUser(KviIrcMessage *msg);
+ void parseNumericEndOfWhois(KviIrcMessage *msg);
+ void parseNumericEndOfWhowas(KviIrcMessage *msg);
+ void parseNumericNoSuchNick(KviIrcMessage *msg);
+ void parseNumericCreationTime(KviIrcMessage *msg);
+ void parseNumericIsOn(KviIrcMessage *msg);
+ void parseNumericUnavailResource(KviIrcMessage *msg);
+ void parseNumericLinks(KviIrcMessage *msg);
+ void parseNumericEndOfLinks(KviIrcMessage *msg);
+ void parseNumericUserhost(KviIrcMessage *msg);
+ void parseLoginNicknameProblem(KviIrcMessage *msg);
+ void parseNumericBackFromAway(KviIrcMessage *);
+ void parseNumericAway(KviIrcMessage *);
+ void parseNumericWatch(KviIrcMessage *msg);
+ void parseNumericList(KviIrcMessage *msg);
+ void parseNumericListStart(KviIrcMessage *msg);
+ void parseNumericListEnd(KviIrcMessage *msg);
+ void parseNumericCantJoinChannel(KviIrcMessage *msg);
+ void parseNumericStats(KviIrcMessage *msg);
+ void parseNumericUserMode(KviIrcMessage * msg);
+ void parseNumericCodePageSet(KviIrcMessage * msg);
+ void parseNumericCodePageScheme(KviIrcMessage * msg);
+ void parseNumeric020(KviIrcMessage *msg);
+ void parseNumericCannotSend(KviIrcMessage *msg);
+ void parseNumericNoSuchChannel(KviIrcMessage *msg);
+ void parseNumericNoSuchServer(KviIrcMessage *msg);
+ void parseNumericTime(KviIrcMessage *msg);
+ void parseNumericInfoEnd(KviIrcMessage *msg);
+ void parseNumericInfoStart(KviIrcMessage *msg);
+ void parseNumericInfo(KviIrcMessage *msg);
+ void parseNumericInviting(KviIrcMessage *msg);
+ void parseNumericCommandSyntax(KviIrcMessage *msg);
+ void parseNumericServerAdminInfoAdminContact(KviIrcMessage *msg);
+ void parseNumericServerAdminInfoAdminName(KviIrcMessage *msg);
+ void parseNumericServerAdminInfoServerName(KviIrcMessage *msg);
+ void parseNumericServerAdminInfoTitle(KviIrcMessage *msg);
+ void parseNumericCannotSendColor(KviIrcMessage *msg);
+ void parseNumericEndOfStats(KviIrcMessage *msg);
+ void otherChannelError(KviIrcMessage *msg);
+ void parseCommandSyntaxHelp(KviIrcMessage *msg);
+ void parseCommandHelp(KviIrcMessage *msg);
+ void parseCommandEndOfHelp(KviIrcMessage *msg);
+ void parseChannelHelp(KviIrcMessage *msg);
+
+ void parseLiteralPing(KviIrcMessage *msg);
+ void parseLiteralJoin(KviIrcMessage *msg);
+ void parseLiteralTopic(KviIrcMessage *msg);
+ void parseLiteralPart(KviIrcMessage *msg);
+ void parseLiteralPrivmsg(KviIrcMessage *msg);
+ void parseLiteralNotice(KviIrcMessage *msg);
+ void parseLiteralQuit(KviIrcMessage *msg);
+ void parseLiteralNick(KviIrcMessage *msg);
+ void parseLiteralMode(KviIrcMessage *msg);
+ void parseLiteralKick(KviIrcMessage *msg);
+ void parseLiteralInvite(KviIrcMessage *msg);
+ void parseLiteralWallops(KviIrcMessage *msg);
+ void parseLiteralPong(KviIrcMessage *msg);
+ void parseLiteralError(KviIrcMessage *msg);
+ void parseChannelMode(const QString &szNick,const QString &szUser,const QString &szHost,KviChannel * chan,KviStr &modefl,KviIrcMessage *msg,int curParam);
+ void parseUserMode(KviIrcMessage *msg,const char * modeflptr);
+
+
+
+ void parseCtcpRequest(KviCtcpMessage *msg);
+ void parseCtcpReply(KviCtcpMessage *msg);
+ void echoCtcpRequest(KviCtcpMessage *msg);
+ void echoCtcpReply(KviCtcpMessage *msg);
+ void replyCtcp(KviCtcpMessage *msg,const char * data);
+ bool checkCtcpFlood(KviCtcpMessage *msg);
+
+ void parseCtcpRequestPing(KviCtcpMessage *msg);
+ void parseCtcpRequestVersion(KviCtcpMessage *msg);
+ void parseCtcpRequestUserinfo(KviCtcpMessage *msg);
+ void parseCtcpRequestClientinfo(KviCtcpMessage *msg);
+ void parseCtcpRequestFinger(KviCtcpMessage *msg);
+ void parseCtcpRequestSource(KviCtcpMessage *msg);
+ void parseCtcpRequestAction(KviCtcpMessage *msg);
+ void parseCtcpRequestTime(KviCtcpMessage *msg);
+ void parseCtcpRequestAvatar(KviCtcpMessage *msg);
+ void parseCtcpRequestDcc(KviCtcpMessage *msg);
+ void parseCtcpRequestPage(KviCtcpMessage *msg);
+
+ void parseCtcpReplyAvatar(KviCtcpMessage *msg);
+ void parseCtcpReplyUserinfo(KviCtcpMessage *msg);
+ void parseCtcpReplyGeneric(KviCtcpMessage *msg);
+ void parseCtcpReplyPing(KviCtcpMessage *msg);
+ void parseCtcpReplyLagcheck(KviCtcpMessage *msg);
+// void parseCtcpReply(const char * msg_ptr,KviIrcUser &source,const char * target);
+public:
+ static void encodeCtcpParameter(const char * param,KviStr &buffer,bool bSpaceBreaks = true);
+ static void encodeCtcpParameter(const char * param,QString &buffer,bool bSpaceBreaks = true);
+ static const char * decodeCtcpEscape(const char * msg_ptr,KviStr &buffer);
+ static const char * decodeCtcpEscape(const char * msg_ptr,KviQCString &buffer);
+ static const char * extractCtcpParameter(const char * msg_ptr,KviStr &buffer,bool bSpaceBreaks = true);
+ static const char * extractCtcpParameter(const char * msg_ptr,QString &buffer,bool bSpaceBreaks = true);
+};
+
+#ifndef _KVI_SPARSER_CPP_
+ extern KVIRC_API KviServerParser * g_pServerParser;
+#endif
+
+
+#endif //_KVI_SPARSER_H_
diff --git a/src/kvirc/ui/Makefile.am b/src/kvirc/ui/Makefile.am
new file mode 100644
index 00000000..c84487eb
--- /dev/null
+++ b/src/kvirc/ui/Makefile.am
@@ -0,0 +1,5 @@
+###############################################################################
+# KVirc IRC client Makefile - 16.12.98 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+EXTRA_DIST = *.cpp *.h
diff --git a/src/kvirc/ui/kvi_actiondrawer.cpp b/src/kvirc/ui/kvi_actiondrawer.cpp
new file mode 100644
index 00000000..a4659141
--- /dev/null
+++ b/src/kvirc/ui/kvi_actiondrawer.cpp
@@ -0,0 +1,227 @@
+//=============================================================================
+//
+// File : kvi_actiondrawer.cpp
+// Created on Sun 21 Nov 2004 05:44:22 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_actiondrawer.h"
+#include "kvi_action.h"
+#include "kvi_actionmanager.h"
+#include "kvi_iconmanager.h"
+#include "kvi_locale.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+//#include <qscrollview.h>
+#include <qpainter.h>
+#include <qpixmap.h>
+#ifdef COMPILE_USE_QT4
+ #include <q3header.h>
+ #include <q3simplerichtext.h>
+ #include <qmime.h>
+ #include <qevent.h>
+#else
+ #include <qheader.h>
+ #include <qsimplerichtext.h>
+#endif
+
+#include "kvi_draganddrop.h"
+
+#define LVI_ICON_SIZE 32
+#define LVI_BORDER 4
+#define LVI_SPACING 8
+#define LVI_MINIMUM_TEXT_WIDTH 300
+#define LVI_MINIMUM_CELL_WIDTH (LVI_MINIMUM_TEXT_WIDTH + LVI_BORDER + LVI_ICON_SIZE + LVI_SPACING + LVI_BORDER)
+
+KviActionDrawerPageListViewItem::KviActionDrawerPageListViewItem(KviTalListView * v,KviAction * a)
+: KviTalListViewItem(v,"")
+{
+ m_pListView = v;
+ setDragEnabled(true);
+ m_szName = a->name();
+ QString t = "<b>" + a->visibleName() + "</b>";
+ if(a->isKviUserActionNeverOverrideThis())
+ t += " <font color=\"#a0a0a0\">[" + __tr2qs("Script") + "]</font>";
+ t += "<br><font size=\"-1\">" + a->description()+ "</font>";
+ m_szKey = a->visibleName().upper();
+#ifdef COMPILE_USE_QT4
+ m_pText = new Q3SimpleRichText(t,v->font());
+#else
+ m_pText = new QSimpleRichText(t,v->font());
+#endif
+ QPixmap * p = a->bigIcon();
+ m_pIcon = p ? new QPixmap(*p) : new QPixmap(LVI_ICON_SIZE,LVI_ICON_SIZE);
+}
+
+KviActionDrawerPageListViewItem::~KviActionDrawerPageListViewItem()
+{
+ delete m_pIcon;
+ delete m_pText;
+}
+
+QString KviActionDrawerPageListViewItem::key(int,bool) const
+{
+ return m_szKey;
+}
+
+void KviActionDrawerPageListViewItem::setup()
+{
+ KviTalListViewItem::setup();
+ int iWidth = m_pListView->visibleWidth();
+ if(iWidth < LVI_MINIMUM_CELL_WIDTH)iWidth = LVI_MINIMUM_CELL_WIDTH;
+ iWidth -= LVI_BORDER + LVI_ICON_SIZE + LVI_SPACING + LVI_BORDER;
+ m_pText->setWidth(iWidth);
+ int iHeight = m_pText->height() + (2 * LVI_BORDER);
+ if(iHeight < (LVI_ICON_SIZE + (2 * LVI_BORDER)))iHeight = LVI_ICON_SIZE + (2 * LVI_BORDER);
+ setHeight(iHeight);
+}
+
+void KviActionDrawerPageListViewItem::paintCell(QPainter * p,const QColorGroup & cg,int column,int width,int align)
+{
+ KviTalListViewItem::paintCell(p,cg,column,width,align);
+ //p->fillRect(QRect(0,0,width,height()),isSelected() ? cg.highlight() : cg.base());
+ p->drawPixmap(LVI_BORDER,LVI_BORDER,*m_pIcon);
+ int afterIcon = LVI_BORDER + LVI_ICON_SIZE + LVI_SPACING;
+ int www = m_pListView->visibleWidth() - (afterIcon + LVI_BORDER);
+ m_pText->setWidth(www);
+ if(isSelected())
+ {
+ QColorGroup cg2(cg);
+ cg2.setColor(QColorGroup::HighlightedText,cg.text());
+ m_pText->draw(p,afterIcon,LVI_BORDER,QRect(afterIcon,LVI_BORDER,www,height() - (LVI_BORDER * 2)),cg2);
+ } else {
+ m_pText->draw(p,afterIcon,LVI_BORDER,QRect(afterIcon,LVI_BORDER,www,height() - (LVI_BORDER * 2)),cg);
+ }
+}
+
+KviActionDrawerPageListView::KviActionDrawerPageListView(KviActionDrawerPage * pParent)
+: KviListView(pParent)
+{
+ QPixmap * p = g_pIconManager->getImage("kvi_actiondrawer.png");
+ if(p)setBackgroundOverlayPixmap(p,Qt::AlignRight | Qt::AlignBottom);
+
+// m_pPage = pParent;
+ setSelectionMode(Single);
+ header()->hide();
+ int iWidth = visibleWidth();
+ if(iWidth < LVI_MINIMUM_CELL_WIDTH)iWidth = LVI_MINIMUM_CELL_WIDTH;
+ addColumn("",iWidth);
+ setSorting(0,true);
+}
+
+KviActionDrawerPageListView::~KviActionDrawerPageListView()
+{
+}
+
+
+void KviActionDrawerPageListView::contentsMousePressEvent(QMouseEvent * e)
+{
+ KviListView::contentsMousePressEvent(e);
+ KviActionDrawerPageListViewItem * i = (KviActionDrawerPageListViewItem *)itemAt(QPoint(5,contentsToViewport(e->pos()).y()));
+ if(!i)return;
+ KviTextDrag * dr = new KviTextDrag(i->name(),this); // does this leak memory ?
+ if(i->icon())dr->setPixmap(*(i->icon()),QPoint(3,3));
+ dr->dragCopy();
+}
+
+void KviActionDrawerPageListView::resizeEvent(QResizeEvent * e)
+{
+ KviListView::resizeEvent(e);
+ int iWidth = visibleWidth();
+ if(iWidth < LVI_MINIMUM_CELL_WIDTH)iWidth = LVI_MINIMUM_CELL_WIDTH;
+ setColumnWidth(0,iWidth);
+}
+
+
+KviActionDrawerPage::KviActionDrawerPage(QWidget * pParent,const QString &szDescription)
+: QWidget(pParent)
+{
+ QGridLayout * g = new QGridLayout(this,2,1,4,4);
+
+ QString t = "<b>" + szDescription + "</b>";
+ QLabel * l = new QLabel(t,this);
+ g->addWidget(l,0,0);
+
+ m_pListView = new KviActionDrawerPageListView(this);
+
+ g->addWidget(m_pListView,1,0);
+
+ g->setRowStretch(1,1);
+}
+
+KviActionDrawerPage::~KviActionDrawerPage()
+{
+}
+
+void KviActionDrawerPage::add(KviAction * a)
+{
+ (void)new KviActionDrawerPageListViewItem(m_pListView,a);
+}
+
+KviActionDrawer::KviActionDrawer(QWidget * pParent)
+: QTabWidget(pParent)
+{
+ setMinimumWidth(400);
+ setMinimumHeight(300);
+}
+
+KviActionDrawer::~KviActionDrawer()
+{
+}
+
+void KviActionDrawer::fill()
+{
+ KviActionManager::loadAllAvailableActions();
+
+ KviPointerHashTable<QString,KviActionDrawerPage> pages;
+ pages.setAutoDelete(false);
+
+ KviPointerHashTable<QString,KviAction> * d = KviActionManager::instance()->actions();
+ if(!d)return; // ooops
+
+ KviPointerHashTableIterator<QString,KviAction> it(*d);
+ while(KviAction * a = it.current())
+ {
+ KviActionCategory * c = a->category();
+ if(!c)c = KviActionManager::categoryGeneric();
+ KviActionDrawerPage * p = pages.find(c->visibleName());
+ if(!p)
+ {
+ p = new KviActionDrawerPage(this,c->description());
+ pages.replace(c->visibleName(),p);
+ addTab(p,c->visibleName());
+ //p->show();
+ }
+ p->add(a);
+ ++it;
+ }
+
+ KviActionDrawerPage * p = pages.find(KviActionManager::categoryIrc()->visibleName());
+ if(p)
+ {
+ int iii = indexOf(p);
+ if(iii >= 0)setCurrentPage(iii);
+ }
+}
+
+
diff --git a/src/kvirc/ui/kvi_actiondrawer.h b/src/kvirc/ui/kvi_actiondrawer.h
new file mode 100644
index 00000000..d9cd2778
--- /dev/null
+++ b/src/kvirc/ui/kvi_actiondrawer.h
@@ -0,0 +1,107 @@
+#ifndef _KVI_ACTIONDRAWER_H_
+#define _KVI_ACTIONDRAWER_H_
+//=============================================================================
+//
+// File : kvi_actiondrawer.h
+// Created on Sun 21 Nov 2004 05:44:22 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+
+#include <qwidget.h>
+#include <qtabwidget.h>
+
+#include "kvi_listview.h"
+
+class KviActionDrawerPage;
+class QPixmap;
+#ifdef COMPILE_USE_QT4
+ class Q3SimpleRichText;
+#else
+ class QSimpleRichText;
+#endif
+class KviAction;
+
+class KVIRC_API KviActionDrawerPageListViewItem : public KviTalListViewItem
+{
+public:
+ KviActionDrawerPageListViewItem(KviTalListView * v,KviAction * a);
+ ~KviActionDrawerPageListViewItem();
+protected:
+ QString m_szName;
+#ifdef COMPILE_USE_QT4
+ Q3SimpleRichText * m_pText;
+#else
+ QSimpleRichText * m_pText;
+#endif
+ QPixmap * m_pIcon;
+ KviTalListView * m_pListView;
+ QString m_szKey;
+public:
+ QPixmap * icon(){ return m_pIcon; };
+ const QString & name(){ return m_szName; };
+protected:
+ virtual void paintCell(QPainter * p,const QColorGroup & cg,int column,int width,int align);
+ virtual void setup();
+ virtual QString key(int,bool) const;
+};
+
+class KVIRC_API KviActionDrawerPageListView : public KviListView
+{
+ friend class KviActionDrawerPage;
+ Q_OBJECT
+protected:
+ KviActionDrawerPageListView(KviActionDrawerPage * pParent);
+public:
+ ~KviActionDrawerPageListView();
+//protected:
+// KviActionDrawerPage * m_pPage;
+protected:
+ virtual void resizeEvent(QResizeEvent * e);
+ virtual void contentsMousePressEvent(QMouseEvent * e);
+};
+
+class KVIRC_API KviActionDrawerPage : public QWidget
+{
+ friend class KviActionDrawer;
+ Q_OBJECT
+protected:
+ KviActionDrawerPage(QWidget * pParent,const QString &szDescription);
+public:
+ ~KviActionDrawerPage();
+protected:
+ KviActionDrawerPageListView * m_pListView;
+protected:
+ void add(KviAction * a);
+};
+
+class KVIRC_API KviActionDrawer : public QTabWidget
+{
+ Q_OBJECT
+public:
+ KviActionDrawer(QWidget * pParent);
+ ~KviActionDrawer();
+public:
+ void fill();
+};
+
+#endif //!_KVI_ACTIONDRAWER_H_
diff --git a/src/kvirc/ui/kvi_channel.cpp b/src/kvirc/ui/kvi_channel.cpp
new file mode 100644
index 00000000..a06ab144
--- /dev/null
+++ b/src/kvirc/ui/kvi_channel.cpp
@@ -0,0 +1,1628 @@
+//=============================================================================
+//
+// File : kvi_channel.cpp
+// Creation date : Tue Aug 1 2000 02:20:22 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+//
+// Channel widget : abstraction of an IRC channel
+//
+
+#define __KVIRC__
+
+#include "kvi_toolwindows_container.h"
+#include "kvi_styled_controls.h"
+#include "kvi_channel.h"
+#include "kvi_console.h"
+#include "kvi_iconmanager.h"
+#include "kvi_ircview.h"
+#include "kvi_input.h"
+#include "kvi_options.h"
+#include "kvi_locale.h"
+#include "kvi_topicw.h"
+#include "kvi_ircsocket.h"
+#include "kvi_out.h"
+#include "kvi_malloc.h"
+#include "kvi_taskbar.h"
+#include "kvi_frame.h"
+#include "kvi_config.h"
+#include "kvi_themedlabel.h"
+#include "kvi_maskeditor.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_settings.h"
+#include "kvi_parameterlist.h"
+#include "kvi_modeeditor.h"
+#include "kvi_app.h"
+#include "kvi_useraction.h"
+#include "kvi_ircconnection.h"
+#include "kvi_ircconnectionserverinfo.h"
+#include "kvi_defaults.h"
+#include "kvi_sparser.h"
+#include "kvi_modew.h"
+#include "kvi_mirccntrl.h"
+
+#ifdef COMPILE_CRYPT_SUPPORT
+ #include "kvi_crypt.h"
+ #include "kvi_cryptcontroller.h"
+#endif
+
+#include "kvi_kvs_script.h"
+#include "kvi_kvs_eventtriggers.h"
+
+#include <time.h>
+
+#include <qsplitter.h>
+#include <qtoolbutton.h>
+#include <qlabel.h>
+#include <qevent.h>
+
+#include <qpalette.h>
+#include "kvi_tal_popupmenu.h"
+#include "kvi_pointerhashtable.h"
+#include <qmessagebox.h>
+#include "kvi_tal_widgetstack.h"
+
+#ifndef AVERAGE_CHANNEL_USERS
+ #define AVERAGE_CHANNEL_USERS 101
+#endif
+
+
+
+// FIXME: #warning "+a Anonymous channel mode!"
+// FIXME: #warning "+r channel mode (reop)"
+// FIXME: #warning "OnChannelFlood event...."
+
+
+KviChannel::KviChannel(KviFrame * lpFrm,KviConsole * lpConsole,const char * name)
+: KviWindow(KVI_WINDOW_TYPE_CHANNEL,lpFrm,name,lpConsole)
+{
+ // Init some member variables
+ m_pInput = 0;
+ m_iStateFlags = 0;
+ m_pBanList = new KviPointerList<KviMaskEntry>;
+ m_pBanList->setAutoDelete(true);
+ m_pBanExceptionList = new KviPointerList<KviMaskEntry>;
+ m_pBanExceptionList->setAutoDelete(true);
+ m_pInviteList = new KviPointerList<KviMaskEntry>;
+ m_pInviteList->setAutoDelete(true);
+ m_pActionHistory = new KviPointerList<KviChannelAction>;
+ m_pActionHistory->setAutoDelete(true);
+ m_uActionHistoryHotActionCount = 0;
+
+ m_pTmpHighLighted = new KviPointerHashTable<const char *,QString>();
+ m_pTmpHighLighted->setAutoDelete(true);
+
+ // Register ourselves
+ connection()->registerChannel(this);
+ // And create the widgets layout
+ // Button box
+ m_pButtonBox = new KviTalHBox(this);
+
+ m_pTopSplitter = new QSplitter(Qt::Horizontal,m_pButtonBox);
+
+ m_pButtonBox->setStretchFactor(m_pTopSplitter,1);
+
+ m_pButtonContainer = new KviTalHBox(m_pButtonBox);
+
+ // Topic widget on the left
+ m_pTopicWidget = new KviTopicWidget(m_pTopSplitter,"topic_widget");
+
+ connect(m_pTopicWidget,SIGNAL(topicSelected(const QString &)),
+ this,SLOT(topicSelected(const QString &)));
+ // mode label follows the topic widget
+ m_pModeWidget = new KviModeWidget(m_pTopSplitter,this,"mode_");
+ KviTalToolTip::add(m_pModeWidget,__tr2qs("Channel mode"));
+
+ createTextEncodingButton(m_pButtonContainer);
+
+ // Central splitter
+ m_pSplitter = new QSplitter(Qt::Horizontal,this);
+ #ifdef COMPILE_USE_QT4
+ m_pSplitter->setObjectName(name);
+ #else
+ m_pSplitter->setName(name);
+ #endif
+ m_pSplitter->setOpaqueResize(false);
+ // Spitted vertially on the left
+ m_pVertSplitter = new QSplitter(Qt::Vertical,m_pSplitter);
+ m_pVertSplitter->setOpaqueResize(false);
+ // With the IRC view over
+ m_pIrcView = new KviIrcView(m_pVertSplitter,lpFrm,this);
+ #ifdef COMPILE_USE_QT4
+ m_pIrcView->setObjectName(name);
+ #else
+ m_pIrcView->setName(name);
+ #endif
+ connect(m_pIrcView,SIGNAL(rightClicked()),this,SLOT(textViewRightClicked()));
+ // And the double view (that may be unused)
+ m_pMessageView = 0;
+ // The userlist on the right
+ //m_pEditorsContainer= new KviToolWindowsContainer(m_pSplitter);
+
+
+ // and the related buttons
+ m_pDoubleViewButton = createToolButton(m_pButtonContainer,"double_view_button",KVI_SMALLICON_HIDEDOUBLEVIEW,KVI_SMALLICON_SHOWDOUBLEVIEW,__tr2qs("Split View"),false);
+ connect(m_pDoubleViewButton,SIGNAL(clicked()),this,SLOT(toggleDoubleView()));
+
+ m_pListViewButton = new KviWindowToolPageButton(KVI_SMALLICON_HIDELISTVIEW,KVI_SMALLICON_SHOWLISTVIEW,__tr2qs("User List"),buttonContainer(),true,"list_view_button");
+ connect(m_pListViewButton,SIGNAL(clicked()),this,SLOT(toggleListView()));
+ m_pBanEditorButton = new KviWindowToolPageButton(KVI_SMALLICON_UNBAN,KVI_SMALLICON_BAN,__tr2qs("Ban Editor"),buttonContainer(),false,"ban_editor_button");
+ connect(m_pBanEditorButton,SIGNAL(clicked()),this,SLOT(toggleBanEditor()));
+
+ if(m_pConsole->connection()->serverInfo()->supportedListModes().contains('e'))
+ {
+ m_pBanExceptionEditorButton =new KviWindowToolPageButton(KVI_SMALLICON_BANUNEXCEPT,KVI_SMALLICON_BANEXCEPT,__tr2qs("Ban Exception Editor"),buttonContainer(),false,"ban_exception_editor_button");
+ connect(m_pBanExceptionEditorButton,SIGNAL(clicked()),this,SLOT(toggleBanExceptionEditor()));
+ } else {
+ m_pBanExceptionEditorButton=0;
+ }
+ if(m_pConsole->connection()->serverInfo()->supportedListModes().contains('I'))
+ {
+ m_pInviteEditorButton =new KviWindowToolPageButton(KVI_SMALLICON_INVITEUNEXCEPT,KVI_SMALLICON_INVITEEXCEPT,__tr2qs("Invite Exception Editor"),buttonContainer(),false,"invite_exception_editor_button");
+ connect(m_pInviteEditorButton,SIGNAL(clicked()),this,SLOT(toggleInviteEditor()));
+ } else {
+ m_pInviteEditorButton = 0;
+ }
+ m_pModeEditorButton = new KviWindowToolPageButton(KVI_SMALLICON_CHANMODEHIDE,KVI_SMALLICON_CHANMODE,__tr2qs("Mode Editor"),buttonContainer(),false,"mode_editor_button");
+ connect(m_pModeEditorButton,SIGNAL(clicked()),this,SLOT(toggleModeEditor()));
+ m_pModeEditor = 0;
+
+#ifdef COMPILE_CRYPT_SUPPORT
+ createCryptControllerButton(m_pButtonContainer);
+#endif
+
+ m_pHideToolsButton = new KviStyledToolButton(m_pButtonBox,"hide_container_button");
+
+#ifndef COMPILE_USE_QT4
+ m_pHideToolsButton->setUsesBigPixmap(false);
+#else
+ m_pHideToolsButton->setAutoRaise(true);
+#endif
+ m_pHideToolsButton->setFixedWidth(10);
+
+ if(g_pIconManager->getBigIcon("kvi_horizontal_left.png"))
+ m_pHideToolsButton->setPixmap(*(g_pIconManager->getBigIcon("kvi_horizontal_left.png")));
+
+ connect(m_pHideToolsButton,SIGNAL(clicked()),this,SLOT(toggleToolButtons()));
+
+ m_pUserListView = new KviUserListView(m_pSplitter,m_pListViewButton,connection()->userDataBase(),this,
+ AVERAGE_CHANNEL_USERS,__tr2qs("User List"),"user_list_view");
+// m_pEditorsContainer->addWidget(m_pUserListView);
+// m_pEditorsContainer->raiseWidget(m_pUserListView);
+ // And finally the input line on the bottom
+ m_pInput = new KviInput(this,m_pUserListView);
+ // no mask editors yet
+ m_pBanEditor = 0;
+ m_pBanExceptionEditor = 0;
+ m_pInviteEditor = 0;
+ // Ensure proper focusing
+ //setFocusHandler(m_pInput,this);
+ // And turn on the secondary IRC view if needed
+
+ if(KVI_OPTION_BOOL(KviOption_boolAutoLogChannels))m_pIrcView->startLogging();
+
+ applyOptions();
+ m_joinTime = QDateTime::currentDateTime();
+ m_tLastReceivedWhoReply = (kvi_time_t)m_joinTime.toTime_t();
+
+
+}
+
+KviChannel::~KviChannel()
+{
+ // Unregister ourself
+ if(type() == KVI_WINDOW_TYPE_DEADCHANNEL)context()->unregisterDeadChannel(this);
+ else connection()->unregisterChannel(this);
+ // Then remove all the users and free mem
+ m_pUserListView->enableUpdates(false);
+ m_pUserListView->partAll();
+ delete m_pActionHistory;
+ delete m_pBanList;
+ delete m_pBanExceptionList;
+ delete m_pInviteList;
+ delete m_pTmpHighLighted;
+}
+
+void KviChannel::toggleToolButtons()
+{
+ if(!buttonContainer()) return;
+ toggleButtonContainer();
+ QPixmap* pix= buttonContainer()->isVisible() ?
+ g_pIconManager->getBigIcon("kvi_horizontal_left.png") :
+ g_pIconManager->getBigIcon("kvi_horizontal_right.png");
+ if(pix)
+ m_pHideToolsButton->setPixmap(*pix);
+}
+
+void KviChannel::triggerCreationEvents()
+{
+ KVS_TRIGGER_EVENT_0(KviEvent_OnChannelWindowCreated,this);
+}
+
+void KviChannel::textViewRightClicked()
+{
+ KVS_TRIGGER_EVENT_0(KviEvent_OnChannelPopupRequest,this);
+}
+
+void KviChannel::getBaseLogFileName(QString &buffer)
+{
+ QString szChan(windowName());
+ szChan.replace(".","%2e");
+ if (console()->connection())
+ {
+ buffer=szChan;
+ buffer.append(".");
+ buffer.append(console()->currentNetworkName());
+ } else {
+ buffer=szChan;
+ buffer.append(".");
+ buffer.append(console()->ircContextId());
+ }
+}
+
+void KviChannel::applyOptions()
+{
+ m_pUserListView->applyOptions();
+ m_pTopicWidget->applyOptions();
+
+ if(m_pMessageView)m_pMessageView->applyOptions();
+
+ m_pModeWidget->applyOptions();
+
+ // this applies options for IrcView and Input and forces the window to relayout
+ KviWindow::applyOptions();
+}
+
+void KviChannel::getConfigGroupName(QString &buf)
+{
+ buf = windowName();
+}
+
+void KviChannel::saveProperties(KviConfig *cfg)
+{
+ KviWindow::saveProperties(cfg);
+ cfg->writeEntry("TopSplitter",m_pTopSplitter->sizes());
+ cfg->writeEntry("Splitter",m_pSplitter->sizes());
+#ifdef COMPILE_USE_QT4
+ QList<int> tmp = m_pVertSplitter->sizes();
+ KviValueList<int> tmp2;
+ for(QList<int>::Iterator it = tmp.begin();it != tmp.end();++it)
+ tmp2.append(*it);
+ cfg->writeEntry("VertSplitter",m_pMessageView ? tmp2 : m_VertSplitterSizesList);
+#else
+ cfg->writeEntry("VertSplitter",m_pMessageView ? m_pVertSplitter->sizes() : m_VertSplitterSizesList);
+#endif
+ cfg->writeEntry("PrivateBackground",m_privateBackground);
+ cfg->writeEntry("DoubleView",m_pMessageView ? true : false);
+ if(m_pUserListView)
+ cfg->writeEntry("UserListHidden",m_pUserListView->isHidden());
+ cfg->writeEntry("ToolButtonsHidden",buttonContainer()->isHidden());
+}
+
+void KviChannel::loadProperties(KviConfig *cfg)
+{
+ int w = width();
+ KviValueList<int> def;
+ def.append((w * 75) / 100);
+ def.append((w * 15) / 100);
+ def.append((w * 10) / 100);
+ m_pTopSplitter->setSizes(cfg->readIntListEntry("TopSplitter",def));
+ def.clear();
+ def.append((w * 82) / 100);
+ def.append((w * 18) / 100);
+ m_pSplitter->setSizes(cfg->readIntListEntry("Splitter",def));
+ //debug("SETTING DEFAULT SIZES");
+ def.clear();
+
+ def.append((w * 60) / 100);
+ def.append((w * 40) / 100);
+ m_VertSplitterSizesList=cfg->readIntListEntry("VertSplitter",def);
+ showDoubleView(cfg->readBoolEntry("DoubleView",false));
+ //def.append((w * 50) / 100);
+ //def.append((w * 50) / 100);
+
+ m_privateBackground = cfg->readPixmapEntry("PrivateBackground",KviPixmap());
+ if(m_privateBackground.pixmap())
+ {
+ m_pIrcView->setPrivateBackgroundPixmap(*(m_privateBackground.pixmap()));
+ if(m_pMessageView)m_pMessageView->setPrivateBackgroundPixmap(*(m_privateBackground.pixmap()));
+ }
+
+ KviWindow::loadProperties(cfg);
+ if(m_pUserListView)
+ {
+ bool bHidden=cfg->readBoolEntry("UserListHidden",0);
+ m_pUserListView->setHidden(bHidden);
+ resizeEvent(0);
+ }
+ if(cfg->readBoolEntry("ToolButtonsHidden",KVI_OPTION_BOOL(KviOption_boolHideWindowToolButtons))!=buttonContainer()->isHidden())
+ toggleToolButtons();
+}
+
+
+void KviChannel::showDoubleView(bool bShow)
+{
+ if(m_pMessageView)
+ {
+ if(bShow)return;
+ m_pIrcView->joinMessagesFrom(m_pMessageView);
+ m_VertSplitterSizesList=m_pVertSplitter->sizes();
+ delete m_pMessageView;
+ m_pMessageView = 0;
+ if(m_pDoubleViewButton->isOn())m_pDoubleViewButton->setOn(false);
+ } else {
+ if(!bShow)return;
+ m_pMessageView = new KviIrcView(m_pVertSplitter,m_pFrm,this);
+ m_pVertSplitter->setSizes(m_VertSplitterSizesList);
+ //setFocusHandler(m_pInput,m_pMessageView); //socket it!
+ if(!(m_pDoubleViewButton->isOn()))m_pDoubleViewButton->setOn(true);
+ if(m_privateBackground.pixmap())
+ {
+ m_pMessageView->setPrivateBackgroundPixmap(*(m_privateBackground.pixmap()));
+ }
+ connect(m_pMessageView,SIGNAL(rightClicked()),this,SLOT(textViewRightClicked()));
+ m_pMessageView->setMasterView(m_pIrcView);
+ m_pIrcView->splitMessagesTo(m_pMessageView);
+ m_pMessageView->show();
+ }
+}
+
+void KviChannel::toggleDoubleView()
+{
+ showDoubleView(!m_pMessageView);
+}
+
+void KviChannel::toggleListView()
+{
+ if(m_pUserListView->isVisible())
+ {
+ m_pUserListView->hide();
+ if(m_pListViewButton->isOn())m_pListViewButton->setOn(false);
+ } else {
+ m_pUserListView->show();
+ if(!(m_pListViewButton->isOn()))m_pListViewButton->setOn(true);
+ }
+}
+
+
+void KviChannel::toggleModeEditor()
+{
+ if(m_pModeEditor)
+ {
+ delete m_pModeEditor;
+ m_pModeEditor = 0;
+ m_pSplitter->setMinimumHeight(20); //gfgf
+ if(m_pModeEditorButton->isOn()) m_pModeEditorButton->setOn(false);
+ resizeEvent(0);
+ } else {
+ m_pModeEditor = new KviModeEditor(m_pSplitter,m_pModeEditorButton,"mode_editor",console(),m_szChannelMode,m_szChannelKey,m_szChannelLimit.ptr());
+ connect(m_pModeEditor,SIGNAL(setMode(const char *)),this,SLOT(setMode(const char *)));
+ connect(m_pModeEditor,SIGNAL(done()),this,SLOT(modeSelectorDone()));
+ m_pModeEditor->show();
+ //setFocusHandlerNoClass(m_pInput,m_pModeEditor,"QLineEdit");
+ if(!m_pModeEditorButton->isOn())m_pModeEditorButton->setOn(true);
+ }
+}
+
+void KviChannel::modeSelectorDone()
+{
+ if(m_pModeEditor)toggleModeEditor();
+}
+
+void KviChannel::setMode(const char * mode)
+{
+ if(!connection())return;
+ KviQCString tmp = connection()->encodeText(m_szName);
+ connection()->sendFmtData("MODE %s %s",tmp.data(),mode);
+}
+
+void KviChannel::toggleBanEditor()
+{
+ toggleEditor(&m_pBanEditor,&m_pBanEditorButton,
+ m_pBanList,'b',"ban_editor");
+}
+
+void KviChannel::toggleBanExceptionEditor()
+{
+ toggleEditor(&m_pBanExceptionEditor,&m_pBanExceptionEditorButton,
+ m_pBanExceptionList,'e',"ban_exception_editor");
+}
+
+void KviChannel::toggleInviteEditor()
+{
+ toggleEditor(&m_pInviteEditor,&m_pInviteEditorButton,
+ m_pInviteList,'I',"invite_exception_editor");
+}
+
+void KviChannel::toggleEditor(KviMaskEditor ** ppEd,KviWindowToolPageButton ** ppBtn,KviPointerList<KviMaskEntry> *l,char flag,const char *edName)
+{
+ if(*ppEd)
+ {
+ delete *ppEd;
+ *ppEd = 0;
+ if(!(*ppBtn))return;
+ if((*ppBtn)->isOn()) (*ppBtn)->setOn(false);
+ } else {
+ bool bHasList = true;
+ switch(flag)
+ {
+ case 'b':
+ if(!(bHasList = hasBanList()))
+ {
+ m_pBanList->clear();
+ setSentBanListRequest();
+ }
+ break;
+ case 'e':
+ if(!(bHasList = hasBanExceptionList()))
+ {
+ m_pBanExceptionList->clear();
+ setSentBanExceptionListRequest();
+ }
+ break;
+ case 'I':
+ if(!(bHasList = hasInviteList()))
+ {
+ m_pInviteList->clear();
+ setSentInviteListRequest();
+ }
+ break;
+ }
+ if(!bHasList)
+ {
+ if(connection())
+ {
+ KviQCString szName = connection()->encodeText(m_szName);
+ connection()->sendFmtData("MODE %s %c",szName.data(),flag);
+ }
+ }
+
+ *ppEd = new KviMaskEditor(m_pSplitter,*ppBtn,l,flag,edName);
+ connect(*ppEd,SIGNAL(removeMasks(KviMaskEditor *,KviPointerList<KviMaskEntry> *)),
+ this,SLOT(removeMasks(KviMaskEditor *,KviPointerList<KviMaskEntry> *)));
+ //setFocusHandler(m_pInput,*ppEd); //socket it!
+ (*ppEd)->show();
+ if(!(*ppBtn))return;
+ if(!((*ppBtn)->isOn()))(*ppBtn)->setOn(true);
+ }
+}
+
+void KviChannel::removeMasks(KviMaskEditor *ed,KviPointerList<KviMaskEntry> *l)
+{
+ KviStr masks;
+ KviStr flags;
+ unsigned int count = 0;
+ for(KviMaskEntry * e = l->first();e;e = l->next())
+ {
+ if(masks.hasData())masks.append(' ');
+ masks.append(e->szMask);
+ flags.append(ed->flag());
+ count++;
+ if(count == connection()->serverInfo()->maxModeChanges())
+ {
+ if(connection())
+ {
+ KviQCString szName = connection()->encodeText(m_szName);
+ connection()->sendFmtData("MODE %s -%s %s",szName.data(),flags.ptr(),connection()->encodeText(QString(masks)).data());
+ }
+ flags = "";
+ masks = "";
+ count = 0;
+ }
+ }
+ if(masks.hasData())
+ {
+ if(connection())
+ {
+ KviQCString szName = connection()->encodeText(m_szName);
+ connection()->sendFmtData("MODE %s -%s %s",szName.data(),flags.ptr(),connection()->encodeText(QString(masks)).data());
+ }
+ }
+}
+
+QPixmap * KviChannel::myIconPtr()
+{
+ return g_pIconManager->getSmallIcon((m_iStateFlags & KVI_CHANNEL_STATE_DEADCHAN) ? KVI_SMALLICON_DEADCHANNEL : KVI_SMALLICON_CHANNEL);
+}
+
+void KviChannel::resizeEvent(QResizeEvent *e)
+{
+#ifdef COMPILE_USE_QT4
+ int hght = m_pInput->heightHint();
+ int hght2 = m_pTopicWidget->sizeHint().height();
+ m_pButtonBox->setGeometry(0,0,width(),hght2);
+ m_pSplitter->setGeometry(0,hght2,width(),height() - (hght + hght2));
+ m_pInput->setGeometry(0,height() - hght,width(),hght);
+#else
+ int hght = m_pInput->heightHint();
+ int hght2 = m_pButtonBox->sizeHint().height();
+ m_pButtonBox->setGeometry(0,0,width(),hght2);
+ m_pSplitter->setGeometry(0,hght2,width(),height() - (hght + hght2));
+ m_pInput->setGeometry(0,height() - hght,width(),hght);
+#endif
+}
+
+QSize KviChannel::sizeHint() const
+{
+ QSize ret(m_pSplitter->sizeHint().width(),
+ m_pIrcView->sizeHint().height() + m_pInput->heightHint() + m_pButtonBox->sizeHint().height());
+ return ret;
+}
+
+void KviChannel::setChannelMode(char mode,bool bAdd)
+{
+ if(!m_pConsole->connection()->serverInfo()->supportedListModes().contains(mode)){
+ if(bAdd)
+ {
+ if(!(m_szChannelMode.contains(mode)))m_szChannelMode.append(mode);
+ } else {
+ if(m_szChannelMode.contains(mode))
+ {
+ m_szChannelMode.replace(mode,"");
+ }
+ }
+ updateModeLabel();
+ updateCaption();
+ }
+}
+
+void KviChannel::setChannelKey(const char * key)
+{
+ m_szChannelKey = key;
+ updateModeLabel();
+ updateCaption();
+}
+
+void KviChannel::setChannelLimit(const char * limit)
+{
+ m_szChannelLimit = limit;
+ updateModeLabel();
+ updateCaption();
+}
+
+void KviChannel::addHighlightedUser(const char * nick)
+{
+ if(!m_pUserListView->findEntry(nick))return;
+ else
+ m_pTmpHighLighted->replace(nick,new QString());
+}
+
+void KviChannel::removeHighlightedUser(const char * nick)
+{
+ m_pTmpHighLighted->remove(nick);
+}
+
+void KviChannel::getChannelModeString(QString &buffer)
+{
+ buffer = m_szChannelMode;
+ if(!m_szChannelKey.isEmpty())buffer.append('k');
+ if(m_szChannelLimit.hasData())buffer.append('l');
+}
+
+void KviChannel::setDeadChan()
+{
+ m_iStateFlags |= KVI_CHANNEL_STATE_DEADCHAN;
+ m_iStateFlags &= ~(KVI_CHANNEL_STATE_NOCLOSEONPART | KVI_CHANNEL_STATE_SENTSYNCWHOREQUEST);
+
+ m_pUserListView->enableUpdates(false);
+ m_pUserListView->partAll();
+ m_pUserListView->enableUpdates(true);
+ m_pUserListView->setUserDataBase(0);
+
+ m_pBanList->clear();
+ m_pBanExceptionList->clear();
+ m_pInviteList->clear();
+
+ m_pActionHistory->clear();
+ m_uActionHistoryHotActionCount = 0;
+
+ m_szChannelMode = "";
+ m_szChannelKey = "";
+ m_szChannelLimit = "";
+
+ // this should be moved to irc context!
+ connection()->unregisterChannel(this);
+ context()->registerDeadChannel(this);
+
+ setType(KVI_WINDOW_TYPE_DEADCHANNEL);
+
+ updateIcon();
+ updateModeLabel();
+ updateCaption();
+}
+
+void KviChannel::setAliveChan()
+{
+ // Rise like phoenix!
+ m_iStateFlags = 0;
+ setType(KVI_WINDOW_TYPE_CHANNEL);
+ m_pUserListView->setUserDataBase(connection()->userDataBase());
+ m_joinTime = QDateTime::currentDateTime();
+ context()->unregisterDeadChannel(this);
+ connection()->registerChannel(this);
+ // Update log file name
+ if(m_pIrcView->isLogging())m_pIrcView->startLogging();
+ updateIcon();
+ updateCaption();
+ m_pTopicWidget->reset(); // reset the topic (fixes bug #20 signaled by Klaus Weidenbach)
+}
+
+void KviChannel::getTalkingUsersStats(QString &buffer,QStringList &l,bool bPast)
+{
+ if(l.count() < 1)return;
+
+ if(l.count() == 1)
+ {
+ buffer += "<b>";
+ buffer += l.first();
+ buffer += "</b>";
+ buffer += " ";
+ buffer += bPast ? __tr2qs("said something recently") : __tr2qs("is talking");
+ } else if(l.count() == 2)
+ {
+ buffer += "<b>";
+ buffer += l.first();
+ buffer += "</b> ";
+ buffer += __tr2qs("and");
+ buffer += " <b>";
+ l.remove(l.begin());
+ buffer += l.first();
+ buffer += "</b> ";
+ buffer += bPast ? __tr2qs("were talking recently") : __tr2qs("are talking");
+ } else {
+ buffer += "<b>";
+ buffer += l.first();
+ buffer += "</b>, <b>";
+ l.remove(l.begin());
+ buffer += l.first();
+ if(l.count() == 2)
+ {
+ buffer += "</b> ";
+ buffer += __tr2qs("and");
+ buffer += " <b>";
+ l.remove(l.begin());
+ buffer += l.first();
+ buffer += "</b>";
+ } else {
+ // (l.count() - 1) is > 1
+ buffer += "</b> ";
+ buffer += __tr2qs("and other %1 users").arg(l.count() - 1);
+ }
+ buffer += " ";
+ buffer += bPast ? __tr2qs("were talking recently") : __tr2qs("are talking");
+ }
+}
+
+void KviChannel::getTaskBarTipText(QString &buffer)
+{
+ static QString html_bold("<b>");
+ static QString html_tab("&nbsp;&nbsp;");
+ static QString html_eofbold("</b> ");
+ static QString p5(" (");
+ // p6 == p4
+ static QString p7(" (");
+ static QString p8(": ");
+ static QString p9(")");
+ static QString p10("<br>");
+
+ static QString end_of_doc = "</table></body></html>";
+ static QString end_of_fontboldrow = END_TABLE_BOLD_ROW;
+ static QString start_of_row = "<tr><td>";
+ static QString end_of_row = "</td></tr>";
+
+ buffer = "<html>" \
+ "<body>" \
+ "<table width=\"100%\">"\
+ START_TABLE_BOLD_ROW;
+
+ if(m_iStateFlags & KVI_CHANNEL_STATE_DEADCHAN)
+ {
+ buffer += __tr2qs("Dead channel");
+ buffer += end_of_fontboldrow;
+ buffer += end_of_doc;
+ return;
+ }
+
+ KviUserListViewUserStats s;
+ m_pUserListView->userStats(&s);
+
+
+ buffer += m_szPlainTextCaption;
+ buffer += end_of_fontboldrow;
+
+ buffer += start_of_row;
+
+ QString op = __tr2qs("operator");
+ QString ops = __tr2qs("operators");
+
+ //////////////////////
+
+ buffer += html_tab;
+ buffer += html_bold;
+
+ QString num;
+
+ num.setNum(s.uActive);
+ buffer += num;
+
+ buffer += html_eofbold;
+ buffer += (s.uActive == 1 ? __tr2qs("active user") : __tr2qs("active users"));
+
+ buffer += p5;
+ buffer += html_bold;
+
+ num.setNum(s.uActiveOp);
+
+ buffer += num;
+ buffer += html_eofbold;
+ buffer += (s.uActiveOp == 1 ? op : ops);
+
+ buffer += p9;
+/*
+ * #warning FIXME: What is this supposed to mean?
+ buffer += "<font size=\"-1\">";
+ buffer += p7;
+
+ buffer += __tr2qs("humanity");
+
+ buffer += p8;
+ buffer += html_bold;
+
+ num.setNum(s.iAvgTemperature);
+
+ buffer += num;
+ buffer += "</bold>";
+
+ buffer += p9;
+*/
+ buffer += p10;
+ buffer += "</font>";
+
+
+
+ //////////////////////
+
+ buffer += html_tab;
+ buffer += html_bold;
+
+ num.setNum(s.uHot);
+ buffer += num;
+
+ buffer += html_eofbold;
+ buffer += (s.uHot == 1 ? __tr2qs("hot user") : __tr2qs("hot users"));
+
+ buffer += p5;
+ buffer += html_bold;
+
+ num.setNum(s.uHotOp);
+
+ buffer += num;
+ buffer += html_eofbold;
+ buffer += (s.uHotOp == 1 ? op : ops);
+
+ buffer += p9;
+
+ /////////////
+
+ buffer += end_of_row;
+ buffer += start_of_row;
+
+ ///////////////////
+
+ if(s.uChanOwner > 0)
+ {
+ buffer += html_tab;
+ buffer += html_bold;
+ num.setNum(s.uChanOwner);
+ buffer += num;
+ buffer += html_eofbold;
+ buffer += (s.uChanOwner == 1 ? __tr2qs("channel owner") : __tr2qs("channel owners"));
+ buffer += p10;
+ }
+
+ if(s.uChanAdmin > 0)
+ {
+ buffer += html_tab;
+ buffer += html_bold;
+ num.setNum(s.uChanAdmin);
+ buffer += num;
+ buffer += html_eofbold;
+ buffer += (s.uChanAdmin == 1 ? __tr2qs("channel administrator") : __tr2qs("channel administrators"));
+ buffer += p10;
+ }
+
+ if(s.uOp > 0)
+ {
+ buffer += html_tab;
+ buffer += html_bold;
+ num.setNum(s.uOp);
+ buffer += num;
+ buffer += html_eofbold;
+ buffer += (s.uOp == 1 ? op : ops);
+ buffer += p10;
+ }
+
+ if(s.uHalfOp > 0)
+ {
+ buffer += html_tab;
+ buffer += html_bold;
+ num.setNum(s.uHalfOp);
+ buffer += num;
+ buffer += html_eofbold;
+ buffer += (s.uHalfOp == 1 ? __tr2qs("half-operator") : __tr2qs("half-operators"));
+ buffer += p10;
+ }
+
+ if(s.uVoiced > 0)
+ {
+ buffer += html_tab;
+ buffer += html_bold;
+ num.setNum(s.uVoiced);
+ buffer += num;
+ buffer += html_eofbold;
+ buffer += (s.uVoiced == 1 ? __tr2qs("voiced user") : __tr2qs("voiced users"));
+ buffer += p10;
+ }
+
+ if(s.uUserOp > 0)
+ {
+ buffer += html_tab;
+ buffer += html_bold;
+ num.setNum(s.uUserOp);
+ buffer += num;
+ buffer += html_eofbold;
+ buffer += (s.uUserOp == 1 ? __tr2qs("user-operator") : __tr2qs("user-operators"));
+ buffer += p10;
+ }
+
+ buffer += html_tab;
+ buffer += html_bold;
+ num.setNum(s.uTotal);
+ buffer += num;
+ buffer += html_eofbold;
+ buffer += (s.uTotal == 1 ? __tr2qs("user total") : __tr2qs("users total"));
+
+ buffer += end_of_row;
+
+ KviChannelActivityStats cas;
+ getChannelActivityStats(&cas);
+
+
+ if(cas.lTalkingUsers.count() > 0)
+ {
+ if((cas.lTalkingUsers.count() < 3) && (cas.lWereTalkingUsers.count() > 0))
+ {
+ buffer += "<tr><td bgcolor=\"#E0E0E0\">";
+ getTalkingUsersStats(buffer,cas.lWereTalkingUsers,true);
+ buffer += end_of_row;
+ }
+ buffer += "<tr><td bgcolor=\"#E0E0E0\">";
+ getTalkingUsersStats(buffer,cas.lTalkingUsers,false);
+ buffer += end_of_row;
+ } else {
+ if(cas.lWereTalkingUsers.count() > 0)
+ {
+ buffer += "<tr><td bgcolor=\"#E0E0E0\">";
+ getTalkingUsersStats(buffer,cas.lWereTalkingUsers,true);
+ buffer += end_of_row;
+ }
+ }
+
+ buffer += "<tr><td bgcolor=\"#A0A0A0\"><b>";
+
+ if(cas.dActionsPerMinute < 0.1)buffer += __tr2qs("No activity");
+ else if(cas.dActionsPerMinute < 0.3)buffer += __tr2qs("Minimal activity");
+ else if(cas.dActionsPerMinute < 1.0)buffer += __tr2qs("Very low activity");
+ else if(cas.dActionsPerMinute < 3.0)buffer += cas.bStatsInaccurate ? __tr2qs("Might be low activity") : __tr2qs("Low activity");
+ else if(cas.dActionsPerMinute < 10.0)buffer += cas.bStatsInaccurate ? __tr2qs("Might be medium activity") : __tr2qs("Medium activity");
+ else if(cas.dActionsPerMinute < 30.0)buffer += cas.bStatsInaccurate ? __tr2qs("Might be high activity") : __tr2qs("High activity");
+ else if(cas.dActionsPerMinute < 60.0)buffer += cas.bStatsInaccurate ? __tr2qs("Might be very high activity") : __tr2qs("Very high activity");
+ else buffer += cas.bStatsInaccurate ? __tr2qs("Might be flooded with messages") : __tr2qs("Flooded with messages");
+
+
+ if(cas.dActionsPerMinute >= 0.1)
+ {
+ QString num;
+ num.sprintf(" [%u%% ",cas.uHotActionPercent);
+ buffer += num;
+ buffer += __tr2qs("human");
+ buffer += "]";
+ }
+
+
+ buffer += "</b></td></tr>";
+
+ buffer += end_of_doc;
+}
+
+void KviChannel::fillCaptionBuffers()
+{
+ static QString begin("<nobr><font color=\"");
+ static QString boldbegin("\"><b>");
+ static QString endofbold("</b></font> <font color=\"");
+ static QString endoffont("\">");
+ static QString end("</font></nobr>");
+
+ if(!connection())
+ {
+ QString dead = __tr2qs("[Dead channel]");
+
+ m_szNameWithUserFlag = m_szName;
+
+ m_szPlainTextCaption = m_szName;
+ m_szPlainTextCaption += " : ";
+ m_szPlainTextCaption += dead;
+
+ m_szHtmlActiveCaption = begin;
+ m_szHtmlActiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextActive).name();
+ m_szHtmlActiveCaption += boldbegin;
+ m_szHtmlActiveCaption += m_szName;
+ m_szHtmlActiveCaption += endofbold;
+ m_szHtmlActiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextActive2).name();
+ m_szHtmlActiveCaption += endoffont;
+ m_szHtmlActiveCaption += dead;
+ m_szHtmlActiveCaption += end;
+
+ m_szHtmlInactiveCaption = begin;
+ m_szHtmlInactiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextInactive).name();
+ m_szHtmlInactiveCaption += boldbegin;
+ m_szHtmlInactiveCaption += m_szName;
+ m_szHtmlInactiveCaption += endofbold;
+ m_szHtmlInactiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextInactive2).name();
+ m_szHtmlInactiveCaption += endoffont;
+ m_szHtmlInactiveCaption += dead;
+ m_szHtmlInactiveCaption += end;
+ return;
+ }
+
+ char uFlag = getUserFlag(connection()->currentNickName());
+
+
+ if(uFlag)
+ {
+ m_szNameWithUserFlag = QChar(uFlag);
+ m_szNameWithUserFlag += m_szName;
+ } else {
+ m_szNameWithUserFlag = m_szName;
+ }
+
+ QString szChanMode;
+ getChannelModeString(szChanMode);
+
+ m_szPlainTextCaption = m_szNameWithUserFlag;
+ if(!szChanMode.isEmpty())
+ {
+ m_szPlainTextCaption += " (+";
+ m_szPlainTextCaption += szChanMode;
+ m_szPlainTextCaption += QChar(')');
+ }
+
+ QString szNickOnServer = QChar('[');
+ szNickOnServer += connection()->currentNickName();
+ szNickOnServer += __tr2qs(" on ");
+ szNickOnServer += connection()->currentServerName();
+ szNickOnServer += QChar(']');
+
+ m_szPlainTextCaption += QChar(' ');
+ m_szPlainTextCaption += szNickOnServer;
+
+ m_szHtmlActiveCaption = begin;
+ m_szHtmlActiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextActive).name();
+ m_szHtmlActiveCaption += boldbegin;
+ m_szHtmlActiveCaption += m_szNameWithUserFlag;
+ m_szHtmlActiveCaption += endofbold;
+ m_szHtmlActiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextActive2).name();
+ m_szHtmlActiveCaption += endoffont;
+ m_szHtmlActiveCaption += szNickOnServer;
+ m_szHtmlActiveCaption += end;
+
+ m_szHtmlInactiveCaption = begin;
+ m_szHtmlInactiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextInactive).name();
+ m_szHtmlInactiveCaption += boldbegin;
+ m_szHtmlInactiveCaption += m_szNameWithUserFlag;
+ m_szHtmlInactiveCaption += endofbold;
+ m_szHtmlInactiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextInactive2).name();
+ m_szHtmlInactiveCaption += endoffont;
+ m_szHtmlInactiveCaption += szNickOnServer;
+ m_szHtmlInactiveCaption += end;
+}
+
+void KviChannel::ownMessage(const QString &buffer)
+{
+ if(!connection())return;
+
+ KviQCString szName = connection()->encodeText(windowName());
+ KviQCString szData = encodeText(buffer);
+ const char * d = szData.data();
+ if(!d)return;
+
+#ifdef COMPILE_CRYPT_SUPPORT
+ if(cryptSessionInfo())
+ {
+ if(cryptSessionInfo()->bDoEncrypt)
+ {
+ if(*d != KVI_TEXT_CRYPTESCAPE)
+ {
+ KviStr encrypted;
+ cryptSessionInfo()->pEngine->setMaxEncryptLen(500 - szName.length());
+ switch(cryptSessionInfo()->pEngine->encrypt(d,encrypted))
+ {
+ case KviCryptEngine::Encrypted:
+ if(!connection()->sendFmtData("PRIVMSG %s :%s",szName.data(),encrypted.ptr()))return;
+ m_pConsole->outputPrivmsg(this,KVI_OUT_OWNPRIVMSGCRYPTED,
+ QString::null,QString::null,QString::null,buffer,KviConsole::NoNotifications);
+ break;
+ case KviCryptEngine::Encoded:
+ {
+ if(!connection()->sendFmtData("PRIVMSG %s :%s",szName.data(),encrypted.ptr()))return;
+ // ugly ,but we must redecode here
+ QString szRedecoded = decodeText(encrypted.ptr());
+ m_pConsole->outputPrivmsg(this,KVI_OUT_OWNPRIVMSG,
+ QString::null,QString::null,QString::null,szRedecoded,KviConsole::NoNotifications);
+ }
+ break;
+ default: // also case KviCryptEngine::EncryptError
+ {
+ QString szEngineError = cryptSessionInfo()->pEngine->lastError();
+ output(KVI_OUT_SYSTEMERROR,
+ __tr2qs("The crypto engine was unable to encrypt the current message (%Q): %Q, no data sent to the server"),
+ &buffer,&szEngineError);
+ }
+ break;
+ }
+ userAction(connection()->currentNickName(),KVI_USERACTION_PRIVMSG);
+ return;
+ } else {
+ d++; //eat the escape code
+ QString tmp = buffer.right(buffer.length() - 1);
+ if(!connection()->sendFmtData("PRIVMSG %s :%s",szName.data(),d))return;
+ m_pConsole->outputPrivmsg(this,KVI_OUT_OWNPRIVMSG,QString::null,QString::null,QString::null,tmp,KviConsole::NoNotifications);
+ userAction(connection()->currentNickName(),KVI_USERACTION_PRIVMSG);
+ return;
+ }
+ }
+ }
+#endif
+
+ if(connection()->sendFmtData("PRIVMSG %s :%s",szName.data(),d))
+ {
+ m_pConsole->outputPrivmsg(this,KVI_OUT_OWNPRIVMSG,QString::null,QString::null,QString::null,buffer,KviConsole::NoNotifications);
+ userAction(connection()->currentNickName(),KVI_USERACTION_PRIVMSG);
+ }
+}
+
+void KviChannel::ownAction(const QString &buffer)
+{
+ if(!connection())return;
+ KviQCString szName = connection()->encodeText(m_szName);
+ KviQCString szData = encodeText(buffer);
+ const char * d = szData.data();
+ if(!d)return;
+ if(!connection()->sendFmtData("PRIVMSG %s :%cACTION %s%c",szName.data(),0x01,d,0x01))return;
+ if(KVS_TRIGGER_EVENT_1_HALTED(KviEvent_OnMeAction,this,QString(d)))return;
+ QString szBuffer = "\r!nc\r";
+ szBuffer += connection()->currentNickName();
+ szBuffer += "\r ";
+ szBuffer += buffer;
+ outputMessage(KVI_OUT_ACTION,szBuffer);
+ userAction(connection()->currentNickName(),KVI_USERACTION_ACTION);
+}
+
+bool KviChannel::nickChange(const QString &oldNick,const QString &newNick)
+{
+ bool bWasHere = m_pUserListView->nickChange(oldNick,newNick);
+ if(bWasHere)channelAction(newNick,KVI_USERACTION_NICK,kvi_getUserActionTemperature(KVI_USERACTION_NICK));
+ return bWasHere;
+}
+
+bool KviChannel::part(const QString &nick)
+{
+ bool bWasHere = m_pUserListView->part(nick);
+ if(bWasHere)channelAction(nick,KVI_USERACTION_PART,kvi_getUserActionTemperature(KVI_USERACTION_PART));
+ return bWasHere;
+}
+
+
+#define KVI_CHANACTIVITY_LIMIT_ICE 5
+#define KVI_CHANACTIVITY_LIMIT_VERYCOLD 10
+#define KVI_CHANACTIVITY_LIMIT_COLD 20
+#define KVI_CHANACTIVITY_LIMIT_UNDEFINED 30
+#define KVI_CHANACTIVITY_LIMIT_HOT 50
+#define KVI_CHANACTIVITY_LIMIT_VERYHOT 70
+
+
+bool KviChannel::activityMeter(unsigned int * puActivityValue,unsigned int * puActivityTemperature)
+{
+ fixActionHistory();
+
+ unsigned int uHotActionPercent;
+ double dActionsPerMinute;
+
+ if(m_pActionHistory->count() < 1)
+ {
+ // nothing is happening
+ uHotActionPercent = 0;
+ dActionsPerMinute = 0;
+ } else {
+ kvi_time_t tNow = kvi_unixTime();
+
+ KviChannelAction * a = m_pActionHistory->last();
+
+ double dSpan = (double)(tNow - a->tTime);
+
+ if(m_pActionHistory->count() < KVI_CHANNEL_ACTION_HISTORY_MAX_COUNT)
+ {
+ if(m_joinTime.secsTo(QDateTime::currentDateTime()) < KVI_CHANNEL_ACTION_HISTORY_MAX_TIMESPAN)
+ {
+ // we can't exactly estimate
+ if(dSpan < 60.0)dSpan = 60.0;
+ } else {
+ // there are less actions at all or they have been pushed out because of the timespan
+ dSpan = KVI_CHANNEL_ACTION_HISTORY_MAX_TIMESPAN;
+ }
+ } // else the actions have been pushed out of the history because they were too much
+
+ if(dSpan > 0.0)
+ dActionsPerMinute = (((double)(m_pActionHistory->count())) / (dSpan)) * 60.0;
+ else
+ dActionsPerMinute = (double)(m_pActionHistory->count()); // ???
+
+ uHotActionPercent = (m_uActionHistoryHotActionCount * 100) / (m_pActionHistory->count());
+ }
+
+
+ if(dActionsPerMinute < 0.3)*puActivityValue = KVI_ACTIVITY_NONE;
+ else if(dActionsPerMinute < 1.0)*puActivityValue = KVI_ACTIVITY_VERYLOW;
+ else if(dActionsPerMinute < 4.0)*puActivityValue = KVI_ACTIVITY_LOW;
+ else if(dActionsPerMinute < 10.0)*puActivityValue = KVI_ACTIVITY_MEDIUM;
+ else if(dActionsPerMinute < 30.0)*puActivityValue = KVI_ACTIVITY_HIGH;
+ else *puActivityValue = KVI_ACTIVITY_VERYHIGH;
+
+ if(uHotActionPercent < KVI_CHANACTIVITY_LIMIT_ICE)*puActivityTemperature = KVI_ACTIVITY_ICE;
+ else if(uHotActionPercent < KVI_CHANACTIVITY_LIMIT_VERYCOLD)*puActivityTemperature = KVI_ACTIVITY_VERYCOLD;
+ else if(uHotActionPercent < KVI_CHANACTIVITY_LIMIT_COLD)*puActivityTemperature = KVI_ACTIVITY_COLD;
+ else if(uHotActionPercent < KVI_CHANACTIVITY_LIMIT_UNDEFINED)*puActivityTemperature = KVI_ACTIVITY_UNDEFINED;
+ else if(uHotActionPercent < KVI_CHANACTIVITY_LIMIT_HOT)*puActivityTemperature = KVI_ACTIVITY_HOT;
+ else if(uHotActionPercent < KVI_CHANACTIVITY_LIMIT_VERYHOT)*puActivityTemperature = KVI_ACTIVITY_VERYHOT;
+ else *puActivityTemperature = KVI_ACTIVITY_FIRE;
+
+ return true;
+}
+
+
+void KviChannel::channelAction(const QString &nick,unsigned int uActionType,int iTemperature)
+{
+ KviChannelAction * a = new KviChannelAction;
+ a->tTime = kvi_unixTime();
+ a->uActionType = uActionType;
+ a->iTemperature = iTemperature;
+ a->szNick = nick;
+
+ if(iTemperature > 0)m_uActionHistoryHotActionCount++;
+
+ m_pActionHistory->append(a);
+ fixActionHistory();
+}
+
+void KviChannel::fixActionHistory()
+{
+ while(m_pActionHistory->count() > KVI_CHANNEL_ACTION_HISTORY_MAX_COUNT)m_pActionHistory->removeFirst();
+ KviChannelAction * a = m_pActionHistory->last();
+ if(!a)return;
+
+ kvi_time_t tMinimum = a->tTime - KVI_CHANNEL_ACTION_HISTORY_MAX_TIMESPAN;
+
+ KviChannelAction * act = m_pActionHistory->first();
+ while(act && (act->tTime < tMinimum))
+ {
+ if(act->iTemperature > 0)m_uActionHistoryHotActionCount--;
+ m_pActionHistory->removeFirst();
+ act = m_pActionHistory->first();
+ }
+}
+
+
+void KviChannel::lostUserFocus()
+{
+ KviWindow::lostUserFocus();
+ if(!m_pMessageView)return;
+ if(m_pMessageView->hasLineMark())m_pMessageView->clearLineMark(true);
+}
+
+
+void KviChannel::getChannelActivityStats(KviChannelActivityStats * s)
+{
+ fixActionHistory();
+
+ s->uActionCount = m_pActionHistory->count();
+ s->iAverageActionTemperature = 0;
+ s->uActionsInTheLastMinute = 0;
+ s->uHotActionCount = 0;
+ s->uHotActionPercent = 0;
+ s->bStatsInaccurate = false;
+
+ if(s->uActionCount < 1)
+ {
+ // nothing is happening
+ s->uLastActionTimeSpan = 0;
+ s->uFirstActionTimeSpan = 0;
+ s->dActionsPerMinute = 0;
+
+ return;
+ }
+
+ kvi_time_t tNow = kvi_unixTime();
+
+ KviChannelAction * a = m_pActionHistory->last();
+ s->uLastActionTimeSpan = tNow - a->tTime;
+
+ a = m_pActionHistory->first();
+ s->uFirstActionTimeSpan = tNow - a->tTime;
+
+ double dSpan = (double)s->uFirstActionTimeSpan;
+
+ if(s->uActionCount < KVI_CHANNEL_ACTION_HISTORY_MAX_COUNT)
+ {
+ if(m_joinTime.secsTo(QDateTime::currentDateTime()) < KVI_CHANNEL_ACTION_HISTORY_MAX_TIMESPAN)
+ {
+ // we can't exactly estimate
+ s->bStatsInaccurate = true;
+ if(dSpan < 60.0)dSpan = 60.0;
+ } else {
+ // there are less actions at all or they have been pushed out because of the timespan
+ dSpan = KVI_CHANNEL_ACTION_HISTORY_MAX_TIMESPAN;
+ }
+ } // else the actions have been pushed out of the history because they were too much
+
+ if(dSpan > 0.0)
+ s->dActionsPerMinute = (((double)s->uActionCount) / (dSpan)) * 60.0;
+ else
+ s->dActionsPerMinute = (double)s->uActionCount; // ???
+
+ kvi_time_t tTwoMinsAgo = tNow;
+ tTwoMinsAgo-= 120;
+ tNow -= 60;
+
+ KviPointerHashTable<QString,int> userDict;
+ userDict.setAutoDelete(false);
+
+ int fake;
+ s->lTalkingUsers.clear();
+ s->lWereTalkingUsers.clear();
+
+ for(a = m_pActionHistory->last();a;a = m_pActionHistory->prev())
+ {
+ if(a->tTime >= tNow)s->uActionsInTheLastMinute++;
+
+ if(a->iTemperature > 0)s->uHotActionCount++;
+ s->iAverageActionTemperature += a->iTemperature;
+
+ if((a->uActionType == KVI_USERACTION_PRIVMSG) ||
+ (a->uActionType == KVI_USERACTION_NOTICE) ||
+ (a->uActionType == KVI_USERACTION_ACTION))
+ {
+ if(!userDict.find(a->szNick))
+ {
+ if(isOn(a->szNick.ascii()))
+ {
+ if(a->tTime >= tTwoMinsAgo)s->lTalkingUsers.append(a->szNick);
+ else s->lWereTalkingUsers.append(a->szNick);
+ userDict.insert(a->szNick,&fake);
+ }
+ }
+ }
+ }
+
+ s->iAverageActionTemperature = s->iAverageActionTemperature / (int)s->uActionCount;
+
+ s->uHotActionPercent = (s->uHotActionCount * 100) / s->uActionCount;
+}
+
+
+
+void KviChannel::userAction(const QString &nick,const QString &user,const QString &host,unsigned int uActionType)
+{
+ int iTemperature = kvi_getUserActionTemperature(uActionType);
+ channelAction(nick,uActionType,iTemperature);
+ m_pUserListView->userAction(nick,user,host,iTemperature);
+}
+
+void KviChannel::userAction(const QString &nick,unsigned int uActionType)
+{
+ int iTemperature = kvi_getUserActionTemperature(uActionType);
+ channelAction(nick,uActionType,iTemperature);
+ m_pUserListView->userAction(nick,iTemperature);
+}
+
+void KviChannel::userAction(KviIrcMask * user,unsigned int uActionType)
+{
+ int iTemperature = kvi_getUserActionTemperature(uActionType);
+ channelAction(user->nick(),uActionType,iTemperature);
+ m_pUserListView->userAction(user,iTemperature);
+}
+
+void KviChannel::topicSelected(const QString & topic)
+{
+ if(!connection())return;
+ KviQCString szEncoded = encodeText(topic);
+ KviQCString szName = connection()->encodeText(m_szName);
+ connection()->sendFmtData("TOPIC %s :%s",szName.data(),szEncoded.length() ? szEncoded.data() : "");
+}
+
+void KviChannel::closeEvent(QCloseEvent *e)
+{
+ if((m_iStateFlags & KVI_CHANNEL_STATE_SENTPART) || (m_iStateFlags & KVI_CHANNEL_STATE_DEADCHAN) || !(m_pConsole->isConnected()))
+ {
+ m_pContext->unregisterDeadChannel(this);
+ KviWindow::closeEvent(e);
+ } else {
+ e->ignore();
+ // FIXME: #warning "THIS PART SHOULD BECOME A COMMAND /PART $option()..so the identifiers are parsed"
+ if(connection())
+ {
+ QString tmp = KVI_OPTION_STRING(KviOption_stringPartMessage);
+ tmp.replace(";","\\;");
+ tmp.replace("\n"," ");
+ KviKvsVariant vRet;
+
+ if(KviKvsScript::evaluate(tmp,this,0,&vRet))vRet.asString(tmp);
+
+ KviQCString dat = encodeText(tmp);
+ partMessageSent();
+ KviQCString szName = connection()->encodeText(m_szName);
+ connection()->sendFmtData("PART %s :%s",szName.data(),dat.data() ? dat.data() : "");
+ // be sure to not reference ourselves here.. we could be disconnected!
+ } else {
+ partMessageSent(); // huh ?
+ }
+ }
+}
+
+void KviChannel::partMessageSent(bool bCloseOnPart,bool bShowMessage)
+{
+ m_iStateFlags |= KVI_CHANNEL_STATE_SENTPART;
+ if(!bCloseOnPart)m_iStateFlags |= KVI_CHANNEL_STATE_NOCLOSEONPART;
+ if(bShowMessage)outputNoFmt(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Sent part request, waiting for reply..."));
+}
+
+#define IS_FNC(__name,__ulvname) \
+bool KviChannel::__name(bool bAtLeast) \
+{ \
+ if(!connection())return false; \
+ return m_pUserListView->__ulvname(connection()->currentNickName(),bAtLeast); \
+}
+
+IS_FNC(isMeChanOwner,isChanOwner)
+IS_FNC(isMeChanAdmin,isChanAdmin)
+IS_FNC(isMeOp,isOp)
+IS_FNC(isMeVoice,isVoice)
+IS_FNC(isMeHalfOp,isHalfOp)
+IS_FNC(isMeUserOp,isUserOp)
+
+int KviChannel::myFlags()
+{
+ if(!connection())return 0;
+ return m_pUserListView->flags(connection()->currentNickName());
+}
+
+
+void KviChannel::setMask(char flag, const QString &mask,bool bAdd,const QString &setBy,unsigned int setAt)
+{
+ if(!connection())return;
+ KviPointerList<KviMaskEntry> * list = m_pBanList;
+ KviMaskEditor * editor = m_pBanEditor;
+ switch(flag)
+ {
+ case 'b':
+ m_iStateFlags ^= KVI_CHANNEL_STATE_HAVEBANLIST;
+ break;
+ case 'e':
+ m_iStateFlags ^= KVI_CHANNEL_STATE_HAVEBANEXCEPTIONLIST;
+ list = m_pBanExceptionList;
+ editor = m_pBanExceptionEditor;
+ break;
+ case 'I':
+ m_iStateFlags ^= KVI_CHANNEL_STATE_HAVEINVITELIST;
+ list = m_pInviteList;
+ editor = m_pInviteEditor;
+ break;
+ }
+
+ internalMask(mask,bAdd,setBy,setAt,list,&editor);
+ m_pUserListView->setMaskEntries(flag,(int)list->count());
+}
+
+void KviChannel::internalMask(const QString &mask,bool bAdd,const QString &setBy,unsigned int setAt,KviPointerList<KviMaskEntry> *l,KviMaskEditor **ppEd)
+{
+ KviMaskEntry * e = 0;
+ if(bAdd)
+ {
+ for(e = l->first();e;e = l->next())
+ {
+ if(KviQString::equalCI(e->szMask,mask))return; //already there
+ }
+ e = new KviMaskEntry;
+ e->szMask = mask;
+ e->szSetBy = (!setBy.isEmpty()) ? setBy : __tr2qs("(Unknown)");
+ e->uSetAt = setAt;
+ l->append(e);
+ if(*ppEd)(*ppEd)->addMask(e);
+ } else {
+ for(e = l->first();e;e = l->next())
+ {
+ if(KviQString::equalCI(e->szMask,mask))break;
+ }
+ if(e)
+ {
+ if(*ppEd)(*ppEd)->removeMask(e);
+ l->removeRef(e);
+ }
+ }
+}
+
+void KviChannel::updateModeLabel()
+{
+ QString tmp = m_szChannelMode;
+ QString tip = __tr2qs("<b>Channel mode:</b>");
+ //const char * aux = m_szChannelMode.utf8().data(); leaks memory and will not work with getChannelModeDescription() (can channel modes be multibyte ?)
+ KviStr mod = m_szChannelMode;
+ const char * aux = mod.ptr();
+ while(*aux)
+ {
+ KviQString::appendFormatted(tip,"<br>%c: %Q",*aux,&(m_pConsole->connection()->serverInfo()->getChannelModeDescription(*aux)));
+ ++aux;
+ }
+
+ if(!m_szChannelKey.isEmpty())
+ {
+ if(!tmp.isEmpty())tmp.append(' ');
+ KviQString::appendFormatted(tmp,"k:%s",m_szChannelKey.utf8().data());
+ KviQString::appendFormatted(tip,__tr2qs("<br><b>Key:</b> %s"),m_szChannelKey.utf8().data());
+ }
+
+ if(m_szChannelLimit.hasData())
+ {
+ if(!tmp.isEmpty())tmp.append(' ');
+ KviQString::appendFormatted(tmp,"l:%s",m_szChannelLimit.ptr());
+ KviQString::appendFormatted(tip,__tr2qs("<br><b>Limit:</b> %s"),m_szChannelLimit.ptr());
+ }
+
+ m_pModeWidget->refreshModes();
+ KviTalToolTip::remove(m_pModeWidget);
+ KviTalToolTip::add(m_pModeWidget,tip);
+}
+
+/*
+void KviChannel::outputMessage(int msg_type,const char *format,...)
+{
+ kvi_wchar_t txt_ptr[512]; //It should be enough for all outputs...
+ kvi_va_list list;
+ kvi_va_start(list,format);
+ if(kvi_wvsnprintcf(txt_ptr,512,format,list) < 0){
+ //Just in case...
+ kvi_va_end(list);
+ int len = 512;
+ kvi_wchar_t *long_txt_ptr = 0;
+ int result;
+ do{
+ len += 512;
+ //first time long_txt_ptr == 0 so it is equivalent to malloc
+ //At least the man page says that...
+ long_txt_ptr = (kvi_wchar_t *)kvi_realloc((void *)long_txt_ptr,len * sizeof(kvi_wchar_t));
+ kvi_va_start(list,format);
+ result = kvi_wvsnprintcf(long_txt_ptr,len,format,list);
+ kvi_va_end(list);
+ } while(result < 0);
+ internalOutput(m_pMessageView ? m_pMessageView : m_pIrcView,msg_type,long_txt_ptr);
+ kvi_free((void *)long_txt_ptr);
+ } else {
+ //Succesful vsnprintf
+ kvi_va_end(list);
+ internalOutput(m_pMessageView ? m_pMessageView : m_pIrcView,msg_type,txt_ptr);
+ }
+}
+*/
+
+void KviChannel::outputMessage(int msg_type,const QString &msg)
+{
+ QString szBuf(msg);
+ preprocessMessage(szBuf);
+ const QChar * pC = KviQString::nullTerminatedArray(szBuf);
+ if(!pC)return;
+ internalOutput(m_pMessageView ? m_pMessageView : m_pIrcView,msg_type,(const kvi_wchar_t *)pC);
+}
+
+
+
+void KviChannel::checkChannelSync()
+{
+ if(m_iStateFlags & KVI_CHANNEL_STATE_SYNCHRONIZED)return;
+
+ if(m_iStateFlags & KVI_CHANNEL_STATE_SENTWHOREQUEST)
+ {
+ if(!(m_iStateFlags & KVI_CHANNEL_STATE_HAVEWHOLIST))return;
+ }
+
+ if(m_iStateFlags & KVI_CHANNEL_STATE_SENTBANLISTREQUEST)
+ {
+ if(!(m_iStateFlags & KVI_CHANNEL_STATE_HAVEBANLIST))return;
+ }
+
+ if(m_iStateFlags & KVI_CHANNEL_STATE_SENTBANEXCEPTIONLISTREQUEST)
+ {
+ if(!(m_iStateFlags & KVI_CHANNEL_STATE_HAVEBANEXCEPTIONLIST))return;
+ }
+
+ if(m_iStateFlags & KVI_CHANNEL_STATE_SENTINVITELISTREQUEST)
+ {
+ if(!(m_iStateFlags & KVI_CHANNEL_STATE_HAVEINVITELIST))return;
+ }
+
+ m_iStateFlags |= KVI_CHANNEL_STATE_SYNCHRONIZED;
+ // we already have all the spontaneous server replies
+ // (so probably mode, topic (or no topic is set),names)
+ // we have already received the I and e lists (if requested)
+ kvs_int_t iSyncTime = m_joinTime.time().msecsTo(QTime::currentTime());
+ if(iSyncTime < 0)iSyncTime += 86400000;
+
+ bool bStop = KVS_TRIGGER_EVENT_1_HALTED(KviEvent_OnChannelSync,this,iSyncTime);
+
+ if(!bStop && KVI_OPTION_BOOL(KviOption_boolShowChannelSyncTime))
+ {
+ output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Channel synchronized in %d.%d seconds"),iSyncTime / 1000,iSyncTime % 1000);
+ }
+}
+
+bool KviChannel::eventFilter(QObject * o, QEvent * e)
+{
+ if(e->type() == QEvent::FocusOut && o == m_pTopicWidget && \
+ m_pTopicWidget->isVisible())
+ m_pTopicWidget->deactivate();
+
+ return KviWindow::eventFilter(o, e);
+}
+
+
+void KviChannel::preprocessMessage(QString & szMessage)
+{
+ QStringList strings = QStringList::split(" ",szMessage, TRUE);
+ for ( QStringList::Iterator it = strings.begin(); it != strings.end(); ++it ) {
+ if((*it).contains('\r')) continue;
+ QString tmp = KviMircCntrl::stripControlBytes(*it);
+ if( findEntry(*it) ) *it=QString("\r!n\r%1\r").arg(*it);
+ if(m_pConsole)
+ if(m_pConsole->connection())
+ if(m_pConsole->connection()->serverInfo()->supportedChannelTypes().contains(tmp[0]))
+ if((*it)==tmp)
+ *it=QString("\r!c\r%1\r").arg(*it);
+ else
+ *it=QString("\r!c%1\r%2\r").arg(tmp).arg(*it);
+ }
+ szMessage=strings.join(" ");
+}
+
+void KviChannel::unhighlight()
+{
+ if(!m_pTaskBarItem)return;
+ m_pTaskBarItem->unhighlight();
+}
+
+#include "kvi_channel.moc"
diff --git a/src/kvirc/ui/kvi_channel.h b/src/kvirc/ui/kvi_channel.h
new file mode 100644
index 00000000..0efdabb0
--- /dev/null
+++ b/src/kvirc/ui/kvi_channel.h
@@ -0,0 +1,313 @@
+#ifndef _KVI_CHANNEL_H_
+#define _KVI_CHANNEL_H_
+//=============================================================================
+//
+// File : kvi_channel.h
+// Creation date : Tue Aug 1 2000 01:42:00 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+
+#include "kvi_console.h"
+#include "kvi_window.h"
+#include "kvi_string.h"
+#include "kvi_ircuserdb.h"
+#include "kvi_pixmap.h"
+#include "kvi_userlistview.h"
+#include "kvi_time.h"
+#include "kvi_modew.h"
+#include "kvi_valuelist.h"
+
+#include <qdatetime.h>
+#include "kvi_pointerhashtable.h"
+#include <qstringlist.h>
+
+class KviConsole;
+class QSplitter;
+class QToolButton;
+class KviTopicWidget;
+class KviIrcMask;
+class KviThemedLabel;
+class KviTalHBox;
+
+#ifdef COMPILE_ON_WINDOWS
+ // windows compiler wants this instead of the forward decl
+ #include "kvi_maskeditor.h"
+#else
+ typedef struct _KviMaskEntry KviMaskEntry; // kvi_maskeditor.h
+#endif
+class KviMaskEditor;
+class KviModeEditor;
+
+#define KVI_CHANNEL_STATE_HAVEALLNAMES 1
+#define KVI_CHANNEL_STATE_HAVEBANLIST (1 << 1)
+#define KVI_CHANNEL_STATE_HAVEWHOLIST (1 << 2)
+#define KVI_CHANNEL_STATE_HAVEBANEXCEPTIONLIST (1 << 3)
+#define KVI_CHANNEL_STATE_HAVEINVITELIST (1 << 4)
+#define KVI_CHANNEL_STATE_DEADCHAN (1 << 5)
+
+#define KVI_CHANNEL_STATE_SENTBANLISTREQUEST (1 << 6)
+#define KVI_CHANNEL_STATE_SENTBANEXCEPTIONLISTREQUEST (1 << 7)
+#define KVI_CHANNEL_STATE_SENTINVITELISTREQUEST (1 << 8)
+#define KVI_CHANNEL_STATE_SENTWHOREQUEST (1 << 9)
+
+#define KVI_CHANNEL_STATE_SENTPART (1 << 10)
+#define KVI_CHANNEL_STATE_SYNCHRONIZED (1 << 11)
+
+#define KVI_CHANNEL_STATE_NOCLOSEONPART (1 << 12)
+
+#define KVI_CHANNEL_STATE_SENTSYNCWHOREQUEST (1 << 13)
+
+typedef struct _KviChannelAction
+{
+ QString szNick; // action source nick
+ unsigned int uActionType; // type of the action
+ kvi_time_t tTime; // time of the action
+ int iTemperature; // temperature of the action
+} KviChannelAction;
+
+// this is the maximum count of actions that we keep in memory
+#define KVI_CHANNEL_ACTION_HISTORY_MAX_COUNT 40
+// this is the timespan of the oldest action that we keep in memory
+// 600 secs = 10 mins
+#define KVI_CHANNEL_ACTION_HISTORY_MAX_TIMESPAN 600
+
+typedef struct _KviChannelActivityStats
+{
+ unsigned int uActionCount; // number of actions in the history
+ bool bStatsInaccurate; // the stats are inaccurate because we have just joined the chan
+ unsigned int uLastActionTimeSpan; // the timespan between the last action and now
+ unsigned int uFirstActionTimeSpan; // the time span between the first and the last action
+ double dActionsPerMinute; // average number of actions per minute in the lastActionTimeSpan
+ unsigned int uActionsInTheLastMinute; // number of actions in the last minute
+ int iAverageActionTemperature; // the average chan temperature
+ unsigned int uHotActionCount;
+ unsigned int uHotActionPercent;
+ QStringList lTalkingUsers; // users that seem to be talking NOW
+ QStringList lWereTalkingUsers;
+} KviChannelActivityStats;
+
+class KVIRC_API KviChannel : public KviWindow
+{
+ Q_OBJECT
+public:
+ KviChannel(KviFrame * lpFrm,KviConsole * lpConsole,const char * name);
+ ~KviChannel();
+protected:
+ QSplitter * m_pTopSplitter;
+ QSplitter * m_pVertSplitter;
+ BUTTON_CLASS * m_pDoubleViewButton;
+ KviWindowToolPageButton * m_pListViewButton;
+ KviWindowToolPageButton * m_pBanEditorButton;
+ KviWindowToolPageButton * m_pBanExceptionEditorButton;
+ KviWindowToolPageButton * m_pInviteEditorButton;
+ KviWindowToolPageButton * m_pModeEditorButton;
+ KviMaskEditor * m_pBanEditor;
+ KviMaskEditor * m_pBanExceptionEditor;
+ KviMaskEditor * m_pInviteEditor;
+ KviModeEditor * m_pModeEditor;
+ KviIrcView * m_pMessageView;
+ KviTopicWidget * m_pTopicWidget;
+ KviUserListView * m_pUserListView;
+ KviModeWidget * m_pModeWidget;
+ int m_iStateFlags;
+ QString m_szChannelMode;
+ QString m_szChannelKey;
+ KviStr m_szChannelLimit;
+ KviPointerList<KviMaskEntry> * m_pBanList;
+ KviPointerList<KviMaskEntry> * m_pBanExceptionList;
+ KviPointerList<KviMaskEntry> * m_pInviteList;
+ KviPixmap m_privateBackground;
+ QDateTime m_joinTime;
+ QString m_szNameWithUserFlag;
+ KviPointerHashTable<const char *,QString> * m_pTmpHighLighted;
+ unsigned int m_uActionHistoryHotActionCount;
+ KviPointerList<KviChannelAction> * m_pActionHistory;
+ kvi_time_t m_tLastReceivedWhoReply;
+ KviValueList<int> m_VertSplitterSizesList;
+ KviTalHBox * m_pButtonContainer;
+protected:
+ bool eventFilter(QObject *, QEvent *);
+ virtual QPixmap * myIconPtr();
+ virtual void fillCaptionBuffers();
+ virtual void resizeEvent(QResizeEvent *e);
+ virtual void closeEvent(QCloseEvent *e);
+// virtual void fillContextPopup(KviTalPopupMenu * p);
+ virtual void getConfigGroupName(QString &buf);
+ virtual void saveProperties(KviConfig * cfg);
+ virtual void loadProperties(KviConfig * cfg);
+ virtual void applyOptions();
+ virtual void getBaseLogFileName(QString &buffer);
+ virtual void triggerCreationEvents();
+ void toggleEditor(KviMaskEditor ** ppEd,KviWindowToolPageButton ** ppBtn,KviPointerList<KviMaskEntry> *l,char flag,const char *edName);
+ void internalMask(const QString &mask,bool bAdd,const QString &setBy,unsigned int setAt,KviPointerList<KviMaskEntry> *l,KviMaskEditor **ppEd);
+ void checkChannelSync();
+ void showDoubleView(bool bShow);
+ void fixActionHistory();
+ void getTalkingUsersStats(QString &buffer,QStringList &l,bool bPast);
+public:
+ void getChannelActivityStats(KviChannelActivityStats * s);
+ //void getChannelActivityStatsDescription(QString &buffer);
+
+ KviPointerList<KviMaskEntry> * banList(){ return m_pBanList; };
+ KviPointerList<KviMaskEntry> * banExceptionList(){ return m_pBanExceptionList; };
+ KviPointerList<KviMaskEntry> * inviteList(){ return m_pInviteList; };
+
+ QString * firstSelectedNickname(){ return m_pUserListView->firstSelectedNickname(); };
+ QString * nextSelectedNickname(){ return m_pUserListView->nextSelectedNickname(); };
+
+ int selectedCount(){ return m_pUserListView->selectedCount(); };
+ int opCount(){ return m_pUserListView->opCount(); };
+ int voiceCount(){ return m_pUserListView->voiceCount(); };
+ int halfOpCount(){ return m_pUserListView->halfOpCount(); };
+ int userOpCount(){ return m_pUserListView->userOpCount(); };
+ int chanAdminCount(){ return m_pUserListView->chanAdminCount(); };
+ int chanOwnerCount(){ return m_pUserListView->chanOwnerCount(); };
+ unsigned int count(){ return m_pUserListView->count(); };
+
+ unsigned int banCount(){ return m_pBanList->count(); };
+ unsigned int banExceptionCount(){ return m_pBanExceptionList->count(); };
+ unsigned int inviteCount(){ return m_pInviteList->count(); };
+
+ const QString & nameWithUserFlag(){ return m_szNameWithUserFlag; };
+ virtual const QString & target(){ return windowName(); };
+// void appendSelectedNicknames(KviStr &buffer);
+ void setMask(char flag, const QString &mask,bool bAdd,const QString &setBy,unsigned int setAt);
+
+ kvi_time_t lastReceivedWhoReply(){ return m_tLastReceivedWhoReply; };
+ void setLastReceivedWhoReply(kvi_time_t tTime){ m_tLastReceivedWhoReply = tTime; };
+ void setSentSyncWhoRequest(){ m_iStateFlags |= KVI_CHANNEL_STATE_SENTSYNCWHOREQUEST; };
+ void clearSentSyncWhoRequest(){ m_iStateFlags ^= KVI_CHANNEL_STATE_SENTSYNCWHOREQUEST; };
+ bool sentSyncWhoRequest(){ return (m_iStateFlags & KVI_CHANNEL_STATE_SENTSYNCWHOREQUEST); };
+
+ bool sentWhoRequest(){ return (m_iStateFlags & KVI_CHANNEL_STATE_SENTWHOREQUEST); };
+ void setSentWhoRequest(){ m_iStateFlags |= KVI_CHANNEL_STATE_SENTWHOREQUEST; };
+ bool sentInviteListRequest(){ return (m_iStateFlags & KVI_CHANNEL_STATE_SENTINVITELISTREQUEST); };
+ void setSentInviteListRequest(){ m_iStateFlags |= KVI_CHANNEL_STATE_SENTINVITELISTREQUEST; };
+ void setInviteListDone(){ m_iStateFlags ^= KVI_CHANNEL_STATE_SENTINVITELISTREQUEST; };
+ bool sentBanListRequest(){ return (m_iStateFlags & KVI_CHANNEL_STATE_SENTBANLISTREQUEST); };
+ void setSentBanListRequest(){ m_iStateFlags |= KVI_CHANNEL_STATE_SENTBANLISTREQUEST; };
+ void setBanListDone(){ m_iStateFlags ^= KVI_CHANNEL_STATE_SENTBANLISTREQUEST; };
+ bool sentBanExceptionListRequest(){ return (m_iStateFlags & KVI_CHANNEL_STATE_SENTBANEXCEPTIONLISTREQUEST); };
+ void setSentBanExceptionListRequest(){ m_iStateFlags |= KVI_CHANNEL_STATE_SENTBANEXCEPTIONLISTREQUEST; };
+ void setBanExceptionListDone(){ m_iStateFlags ^= KVI_CHANNEL_STATE_SENTBANEXCEPTIONLISTREQUEST; };
+
+ bool hasAllNames(){ return (m_iStateFlags & KVI_CHANNEL_STATE_HAVEALLNAMES); };
+ void setHasAllNames(){ m_iStateFlags |= KVI_CHANNEL_STATE_HAVEALLNAMES; checkChannelSync(); };
+ bool hasInviteList(){ return (m_iStateFlags & KVI_CHANNEL_STATE_HAVEINVITELIST); checkChannelSync(); };
+ void setHasInviteList(){ m_iStateFlags |= KVI_CHANNEL_STATE_HAVEINVITELIST; };
+ bool hasWhoList(){ return (m_iStateFlags & KVI_CHANNEL_STATE_HAVEWHOLIST); };
+ void setHasWhoList(){ m_iStateFlags |= KVI_CHANNEL_STATE_HAVEWHOLIST; checkChannelSync(); };
+ bool hasBanList(){ return (m_iStateFlags & KVI_CHANNEL_STATE_HAVEBANLIST); };
+ void setHasBanList(){ m_iStateFlags |= KVI_CHANNEL_STATE_HAVEBANLIST; checkChannelSync(); };
+ bool hasBanExceptionList(){ return (m_iStateFlags & KVI_CHANNEL_STATE_HAVEBANEXCEPTIONLIST); };
+ void setHasBanExceptionList(){ m_iStateFlags |= KVI_CHANNEL_STATE_HAVEBANEXCEPTIONLIST; checkChannelSync(); };
+
+ bool closeOnPart(){ return !(m_iStateFlags & KVI_CHANNEL_STATE_NOCLOSEONPART); };
+ void partMessageSent(bool bCloseOnPart = true,bool bShowMessage = true);
+
+ virtual bool activityMeter(unsigned int * puActivityValue,unsigned int * puActivityTemperature);
+
+ void setDeadChan();
+ void setAliveChan();
+ void prependUserFlag(const QString &nick,QString &buffer){ m_pUserListView->prependUserFlag(nick,buffer); };
+ char getUserFlag(const QString &nick){ return m_pUserListView->getUserFlag(nick); };
+ bool isDeadChan(){ return (m_iStateFlags & KVI_CHANNEL_STATE_DEADCHAN); };
+ virtual QSize sizeHint() const;
+ void enableUserListUpdates(bool bEnable){ m_pUserListView->enableUpdates(bEnable); };
+ KviUserListEntry * join(const QString &nick,const QString &user = QString::null,const QString &host = QString::null,int iFlags = 0)
+ { return m_pUserListView->join(nick,user,host,iFlags); };
+ bool op(const QString &nick,bool bOp){ return m_pUserListView->op(nick,bOp); };
+ bool avatarChanged(const QString &nick){ return m_pUserListView->avatarChanged(nick); };
+ bool voice(const QString &nick,bool bVoice){ return m_pUserListView->voice(nick,bVoice); };
+ bool halfop(const QString &nick,bool bHalfOp){ return m_pUserListView->halfop(nick,bHalfOp); };
+ bool userop(const QString &nick,bool bUserOp){ return m_pUserListView->userop(nick,bUserOp); };
+ bool setChanOwner(const QString &nick,bool bChanOwner){ return m_pUserListView->setChanOwner(nick,bChanOwner); };
+ bool setChanAdmin(const QString &nick,bool bChanAdmin){ return m_pUserListView->setChanAdmin(nick,bChanAdmin); };
+ void userAction(KviIrcMask * user,unsigned int uActionType);
+ void userAction(const QString &nick,unsigned int uActionType);
+ void userAction(const QString &nick,const QString &user,const QString &host,unsigned int uActionType);
+ bool nickChange(const QString &oldNick,const QString &newNick);
+ void channelAction(const QString &nick,unsigned int uActionType,int iTemperature);
+ bool part(const QString &nick);
+ bool isOn(const QString &nick){ return (m_pUserListView->findEntry(nick) != 0); };
+ KviUserListEntry * findEntry(const QString &nick){ return m_pUserListView->findEntry(nick); };
+ KviUserListView * userListView(){ return m_pUserListView; };
+ bool isMeOp(bool bAtLeast = false);
+ bool isMeChanOwner(bool bAtLeast = false);
+ bool isMeChanAdmin(bool bAtLeast = false);
+ bool isMeVoice(bool bAtLeast = false);
+ bool isMeHalfOp(bool bAtLeast = false);
+ bool isMeUserOp(bool bAtLeast = false);
+ bool isOp(const QString &nick,bool bAtLeast = false){ return m_pUserListView->isOp(nick,bAtLeast); };
+ bool isVoice(const QString &nick,bool bAtLeast = false){ return m_pUserListView->isVoice(nick,bAtLeast); };
+ bool isHalfOp(const QString &nick,bool bAtLeast = false){ return m_pUserListView->isHalfOp(nick,bAtLeast); };
+ bool isUserOp(const QString &nick,bool bAtLeast = false){ return m_pUserListView->isUserOp(nick,bAtLeast); };
+ bool isChanOwner(const QString &nick,bool bAtLeast = false){ return m_pUserListView->isChanOwner(nick,bAtLeast); };
+ bool isChanAdmin(const QString &nick,bool bAtLeast = false){ return m_pUserListView->isChanAdmin(nick,bAtLeast); };
+ int myFlags();
+ void updateModeLabel();
+ KviTopicWidget * topicWidget(){ return m_pTopicWidget; };
+ virtual void outputMessage(int msg_type,const QString &msg);
+ void ownMessage(const QString &buffer);
+ void ownAction(const QString &buffer);
+ void setChannelMode(char mode,bool bAdd);
+ void setChannelKey(const char * key);
+ void setChannelLimit(const char * limit);
+
+ void getChannelModeString(QString &buffer);
+
+ KviStr & channelLimit(){ return m_szChannelLimit; };
+ bool hasChannelLimit(){ return m_szChannelLimit.hasData(); };
+
+ bool hasChannelKey() { return !m_szChannelKey.isEmpty(); };
+ QString & channelKey(){ return m_szChannelKey; };
+
+ void addHighlightedUser(const char * nick);
+ void removeHighlightedUser(const char * nick);
+ bool isHighlightedUser(const char * nick) { return m_pTmpHighLighted->find(nick); };
+ KviIrcView * messageView() const { return m_pMessageView; };
+ virtual void lostUserFocus();
+ virtual void getTaskBarTipText(QString &buffer);
+ QString channelMode() { return m_szChannelMode; };
+
+ void unhighlight();
+
+ QFrame * buttonContainer() { return (QFrame*)m_pButtonContainer; };
+private slots:
+ void toggleDoubleView();
+ void toggleListView();
+ void toggleBanEditor();
+ void toggleBanExceptionEditor();
+ void toggleInviteEditor();
+ void toggleModeEditor();
+ void topicSelected(const QString & topic);
+ void setMode(const char * mode);
+ void modeSelectorDone();
+ void textViewRightClicked();
+ void removeMasks(KviMaskEditor *ed,KviPointerList<KviMaskEntry> *l);
+ void toggleToolButtons();
+protected:
+ virtual void preprocessMessage(QString & szMessage);
+};
+
+#endif //_KVI_CHANNEL_H_
diff --git a/src/kvirc/ui/kvi_colorwin.cpp b/src/kvirc/ui/kvi_colorwin.cpp
new file mode 100644
index 00000000..9cc1c6e4
--- /dev/null
+++ b/src/kvirc/ui/kvi_colorwin.cpp
@@ -0,0 +1,122 @@
+//=============================================================================
+//
+// File : kvi_colorwin.cpp
+// Creation date : Wed Jan 6 1999 04:30:20 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_colorwin.h"
+#include "kvi_app.h"
+#include "kvi_options.h"
+
+
+#include <qnamespace.h>
+#include <qpainter.h>
+#include <qstring.h>
+#include <qevent.h>
+
+
+KviColorWindow::KviColorWindow()
+:QWidget(0,"toplevel_color_window",Qt::WType_Popup)
+{
+#ifdef COMPILE_USE_QT4
+ setFocusPolicy(Qt::NoFocus);
+#else
+ setFocusPolicy(QWidget::NoFocus);
+#endif
+ setBackgroundMode(Qt::NoBackground);
+ setFixedSize(146,38);
+ m_pOwner = 0;
+ QFont fnt = QFont();
+ fnt.setStyleHint(QFont::TypeWriter);
+ fnt.setPointSize(10);
+ //QFont fnt("fixed",10);
+ setFont(fnt);
+ m_iTimerId = -1;
+}
+
+KviColorWindow::~KviColorWindow()
+{
+ if(m_iTimerId != -1)
+ killTimer(m_iTimerId);
+// if(m_pOwner)m_pOwner->setFocus();
+}
+
+void KviColorWindow::popup(QWidget *owner)
+{
+ m_pOwner = owner;
+ show();
+}
+
+
+void KviColorWindow::paintEvent(QPaintEvent *)
+{
+ static int clrIdx[16]={ 1,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1 };
+ QPainter p(this);
+
+ for(int i=0;i<16;i++)
+ {
+ p.fillRect((i % 8) * 18,(i / 8) * 18,18,18,KVI_OPTION_MIRCCOLOR(i));
+ p.setPen(KVI_OPTION_MIRCCOLOR(clrIdx[i]));
+ KviStr szI(KviStr::Format,"%d",i);
+ p.drawText((i % 8) * 18,(i / 8) * 18,18,18,Qt::AlignVCenter | Qt::AlignHCenter,szI.ptr());
+ }
+}
+
+void KviColorWindow::keyPressEvent(QKeyEvent *e)
+{
+ if(m_iTimerId != -1)
+ killTimer(m_iTimerId);
+ hide();
+ if(m_pOwner)g_pApp->sendEvent(m_pOwner,e);
+}
+
+void KviColorWindow::mousePressEvent(QMouseEvent *e)
+{
+ QString str;
+ int key=e->x()/18;
+ if (e->x()<36 && e->y()>18) key +=8;
+ if (e->x()>36 && e->y()>18) key -=2;
+ int ascii=key+48;
+ str.setNum(key);
+ if (e->x()>36 && e->y()>18)
+ if(m_pOwner) g_pApp->sendEvent(m_pOwner,new QKeyEvent(QEvent::KeyPress,Qt::Key_1,49,Qt::NoButton,"1"));
+ if(m_pOwner) g_pApp->sendEvent(m_pOwner,new QKeyEvent(QEvent::KeyPress,key,ascii,Qt::NoButton,str));
+ if(m_iTimerId != -1)
+ killTimer(m_iTimerId);
+ hide();
+}
+void KviColorWindow::show()
+{
+ m_iTimerId = startTimer(10000); //10 sec ...seems enough
+ QWidget::show();
+}
+
+void KviColorWindow::timerEvent(QTimerEvent *)
+{
+ if(m_iTimerId != -1)
+ killTimer(m_iTimerId);
+ hide();
+}
+
+
+#include "kvi_colorwin.moc"
diff --git a/src/kvirc/ui/kvi_colorwin.h b/src/kvirc/ui/kvi_colorwin.h
new file mode 100644
index 00000000..21cf1ae3
--- /dev/null
+++ b/src/kvirc/ui/kvi_colorwin.h
@@ -0,0 +1,47 @@
+#ifndef _KVI_COLORWIN_H_
+#define _KVI_COLORWIN_H_
+//
+// File : kvi_colorwin.h
+// Creation date : Wed Jan 6 1999 04:27:45 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+#include "kvi_settings.h"
+
+#include <qwidget.h>
+
+class KVIRC_API KviColorWindow : public QWidget
+{
+ Q_OBJECT
+public:
+ KviColorWindow();
+ ~KviColorWindow();
+private:
+ QWidget *m_pOwner;
+ int m_iTimerId;
+public:
+ void popup(QWidget *owner);
+private:
+ virtual void show();
+ virtual void paintEvent(QPaintEvent *);
+ virtual void keyPressEvent(QKeyEvent *e);
+ virtual void mousePressEvent(QMouseEvent *);
+ virtual void timerEvent(QTimerEvent *);
+};
+
+#endif //_KVI_COLORWIN_H_
diff --git a/src/kvirc/ui/kvi_console.cpp b/src/kvirc/ui/kvi_console.cpp
new file mode 100644
index 00000000..df0bd707
--- /dev/null
+++ b/src/kvirc/ui/kvi_console.cpp
@@ -0,0 +1,1283 @@
+//=============================================================================
+//
+// File : kvi_console.cpp
+// Creation date : Sun Jun 25 2000 15:01:34 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+
+// FIXME: The TextEncoding should be inherited from network!
+
+#define __KVIRC__
+
+#include "kvi_ircurl.h"
+#include "kvi_app.h"
+#include "kvi_console.h"
+#include "kvi_frame.h"
+#include "kvi_iconmanager.h"
+#include "kvi_options.h"
+#include "kvi_locale.h"
+#include "kvi_ircview.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_input.h"
+#include "kvi_error.h"
+#include "kvi_proxydb.h"
+#include "kvi_netutils.h"
+#include "kvi_ircserver.h"
+#include "kvi_ircserverdb.h"
+#include "kvi_dns.h"
+#include "kvi_defaults.h"
+#include "kvi_ircuserdb.h"
+#include "kvi_channel.h"
+#include "kvi_query.h"
+#include "kvi_parameterlist.h"
+#include "kvi_regusersdb.h"
+#include "kvi_userlistview.h"
+#include "kvi_out.h"
+#include "kvi_config.h"
+#include "kvi_irctoolbar.h"
+#include "kvi_internalcmd.h"
+#include "kvi_sparser.h"
+#include "kvi_themedlabel.h"
+#include "kvi_garbage.h"
+#include "kvi_modulemanager.h"
+#include "kvi_fileutils.h"
+#include "kvi_irctoolbar.h"
+#include "kvi_time.h"
+#include "kvi_mexlinkfilter.h"
+#include "kvi_avatarcache.h"
+#include "kvi_ircconnection.h"
+#include "kvi_ircconnectionuserinfo.h"
+#include "kvi_ircconnectionserverinfo.h"
+#include "kvi_ircconnectionstatedata.h"
+#include "kvi_ircconnectiontarget.h"
+#include "kvi_ircconnectionstatistics.h"
+#include "kvi_asynchronousconnectiondata.h"
+#include "kvi_ircdatastreammonitor.h"
+#include "kvi_toolwindows_container.h"
+#include "kvi_msgbox.h"
+
+#ifdef COMPILE_SSL_SUPPORT
+ #include "kvi_sslmaster.h"
+#endif
+
+#include "kvi_kvs_script.h"
+#include "kvi_kvs_eventtriggers.h"
+
+#include <qsplitter.h>
+#include <qtoolbar.h>
+#include <qtoolbutton.h>
+#include <qtimer.h>
+#include "kvi_tal_hbox.h"
+#include "kvi_tal_popupmenu.h"
+#include <qmessagebox.h>
+#include <qstringlist.h>
+
+#ifdef COMPILE_USE_QT4
+ #include <q3mimefactory.h>
+#endif
+
+#define __KVI_DEBUG__
+#include "kvi_debug.h"
+
+#ifdef COMPILE_USE_QT4
+ #include <QTextDocument>
+#else
+ #include <qstylesheet.h>
+#endif
+
+extern KVIRC_API KviIrcServerDataBase * g_pIrcServerDataBase;
+extern KVIRC_API KviProxyDataBase * g_pProxyDataBase;
+extern KVIRC_API KviGarbageCollector * g_pGarbageCollector;
+
+// %tmp[] = $str.grep("test",%array[])
+
+KviConsole::KviConsole(KviFrame * lpFrm,int iFlags)
+#ifdef COMPILE_ON_WINDOWS
+: KviWindow(KVI_WINDOW_TYPE_CONSOLE,lpFrm,"CONSOLE",0)
+#else
+: KviWindow(KVI_WINDOW_TYPE_CONSOLE,lpFrm,"CONSOLE",this)
+#endif
+{
+ m_pConsole = this;
+ m_pContext = new KviIrcContext(this);
+
+ m_iFlags = iFlags;
+ if(m_pContext->id() == 1)
+ {
+ m_iFlags |= KVI_CONSOLE_FLAG_FIRSTINAPP;
+ }
+
+ m_pButtonBox = new KviTalHBox(this);
+ m_pButtonBox->setSpacing(0);
+ m_pButtonBox->setMargin(0);
+ new QLabel(__tr2qs("Address:"),m_pButtonBox,"url_label");
+ m_pAddressEdit = new QComboBox(m_pButtonBox,"url_editor");
+ m_pAddressEdit->setAutoCompletion(true);
+ m_pAddressEdit->setDuplicatesEnabled(false);
+ m_pAddressEdit->setEditable(true);
+ m_pAddressEdit->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_URL)));
+ recentUrlsChanged();
+ m_pAddressEdit->setCurrentText("");
+ m_pAddressEdit->setInsertionPolicy(QComboBox::NoInsertion);
+ m_pAddressEdit->setMinimumHeight(24); //icon is 16px, + margins
+ m_pButtonBox->setStretchFactor(m_pAddressEdit,1);
+#ifdef COMPILE_USE_QT4
+ m_pButtonBox->setObjectName( QLatin1String( "kvi_window_button_box" ) );
+#endif
+ KviTalToolTip::add(m_pAddressEdit,__tr2qs("Current IRC URI"));
+ connect(m_pAddressEdit,SIGNAL(activated(const QString & )),this,SLOT(ircUriChanged(const QString & )));
+ connect(g_pApp,SIGNAL(recentUrlsChanged()),this,SLOT(recentUrlsChanged()));
+
+
+ m_pSplitter = new QSplitter(Qt::Horizontal,this,"splitter");
+ m_pIrcView = new KviIrcView(m_pSplitter,lpFrm,this);
+ connect(m_pIrcView,SIGNAL(rightClicked()),this,SLOT(textViewRightClicked()));
+
+ // FIXME: #warning "If notify list is disabled avoid to show this"
+ // FIXME: #warning "Button to show/hide the notifyListView (NOT DELETE RE_CREATE!)"
+ // The userlist on the right
+ //m_pEditorsContainer= new KviToolWindowsContainer(m_pSplitter);
+ m_pNotifyViewButton = new KviWindowToolPageButton(KVI_SMALLICON_HIDELISTVIEW,KVI_SMALLICON_SHOWLISTVIEW,__tr2qs("Notify List"),buttonContainer(),true,"list_view_button");
+ connect(m_pNotifyViewButton,SIGNAL(clicked()),this,SLOT(toggleNotifyView()));
+
+ m_pNotifyListView = new KviUserListView(m_pSplitter,m_pNotifyViewButton,0,this,19,__tr2qs("Notify List"),"notify_list_view");
+
+ m_pInput = new KviInput(this,m_pNotifyListView);
+
+ if(KVI_OPTION_BOOL(KviOption_boolAutoLogConsole))m_pIrcView->startLogging();
+
+}
+
+
+int KviConsole::selectedCount()
+{
+ return m_pNotifyListView->selectedCount();
+}
+
+void KviConsole::recentUrlsChanged(){
+ QString cur = m_pAddressEdit->currentText();
+ m_pAddressEdit->clear();
+ for (
+ QStringList::Iterator it = KVI_OPTION_STRINGLIST(KviOption_stringlistRecentIrcUrls).begin();
+ it != KVI_OPTION_STRINGLIST(KviOption_stringlistRecentIrcUrls).end();
+ ++it
+ ) {
+ m_pAddressEdit->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_URL)),*it);
+ }
+ m_pAddressEdit->setCurrentText(cur);
+}
+
+bool KviConsole::isNotConnected()
+{
+ return (context()->state() == KviIrcContext::Idle);
+}
+
+bool KviConsole::connectionInProgress()
+{
+ if(context()->asynchronousConnectionData() != 0)return true;
+ if(context()->state() != KviIrcContext::Idle)return true;
+ return false;
+}
+
+
+KviConsole::~KviConsole()
+{
+ // FIXME: #warning "WARNING : THIS SHOULD BECOME A COMMAND /QUIT $option() so the idents are parsed!"
+
+ // Force connection close: it will just return if no connection is present
+ context()->terminateConnectionRequest(true);
+
+ KVS_TRIGGER_EVENT_0(KviEvent_OnIrcContextDestroyed,this);
+
+ if(g_pFrame->consoleCount() <= 1)
+ {
+ KVS_TRIGGER_EVENT_0(KviEvent_OnFrameWindowDestroyed,this);
+ KVS_TRIGGER_EVENT_0(KviEvent_OnKVIrcShutdown,this);
+ }
+
+ //if(m_pLastIrcServer)delete m_pLastIrcServer;
+
+ delete m_pContext;
+ m_pContext = 0;
+}
+
+KviIrcSocket * KviConsole::socket()
+{
+ return connection() ? connection()->socket() : 0;
+}
+
+unsigned int KviConsole::ircContextId()
+{
+ return m_pContext->id();
+}
+
+QString KviConsole::currentNetworkName()
+{
+ return (connection() ? connection()->networkName() : QString::null);
+}
+
+
+void KviConsole::triggerCreationEvents()
+{
+ if(m_iFlags & KVI_CONSOLE_FLAG_FIRSTINAPP) // this is the first context in the application
+ {
+ KVS_TRIGGER_EVENT_0(KviEvent_OnKVIrcStartup,this);
+
+ if(KVI_OPTION_BOOL(KviOption_boolShowTipAtStartup))
+ g_pFrame->executeInternalCommand(KVI_INTERNALCOMMAND_TIP_OPEN);
+ }
+
+ if(m_iFlags & KVI_CONSOLE_FLAG_FIRSTINFRAME)
+ {
+ KVS_TRIGGER_EVENT_0(KviEvent_OnFrameWindowCreated,this);
+ }
+
+ KVS_TRIGGER_EVENT_0(KviEvent_OnIrcContextCreated,this);
+}
+
+
+void KviConsole::fillContextPopup(KviTalPopupMenu * p)
+{
+ int id;
+ int cc = 0;
+ int qc = 0;
+ // FIXME: add items to close dead queries and channels ?
+ if(connection())
+ {
+ cc = channelCount();
+ qc = queryCount();
+ p->insertSeparator();
+ id = p->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CHANNEL)),__tr2qs("Part All Channels"),connection(),SLOT(partAllChannels()));
+ if(!cc)p->setItemEnabled(id,false);
+ id = p->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_QUERY)),__tr2qs("Close All Queries"),connection(),SLOT(closeAllQueries()));
+ if(!qc)p->setItemEnabled(id,false);
+ }
+
+ p->insertSeparator();
+ p->insertItem(__tr2qs("Unhighlight All Windows"),context(),SLOT(unhighlightAllWindows()));
+ if(connection())
+ {
+ id = p->insertItem(__tr2qs("Unhighlight All Channels"),connection(),SLOT(unhighlightAllChannels()));
+ if(!cc)p->setItemEnabled(id,false);
+ id = p->insertItem(__tr2qs("Unhighlight All Queries"),connection(),SLOT(unhighlightAllQueries()));
+ if(!qc)p->setItemEnabled(id,false);
+ }
+}
+
+void KviConsole::completeChannel(const QString &word,KviPointerList<QString> * matches)
+{
+ // FIXME: first look in our context ?
+ /*
+ if(!connection())return;
+ for(KviChannel * c = connection()->channelList()->first();c;c = connection()->channelList()->next())
+ {
+ if(kvi_strEqualCIN(c->windowName(),word.ptr(),word.len()))matches->append(new KviStr((*it)
+ }
+ */
+ QStringList *pList = g_pApp->getRecentChannels(currentNetworkName());
+ if(pList)
+ {
+ for(QStringList::Iterator it = pList->begin(); it != pList->end(); ++it)
+ {
+ if(KviQString::equalCIN((*it),word,word.length()))matches->append(new QString(*it));
+ }
+ }
+}
+
+void KviConsole::completeServer(const QString &word, KviPointerList<QString> * matches)
+{
+ for(QStringList::Iterator it = KVI_OPTION_STRINGLIST(KviOption_stringlistRecentServers).begin(); it != KVI_OPTION_STRINGLIST(KviOption_stringlistRecentServers).end(); ++it)
+ {
+ QString srv((*it));
+
+ KviQString::cutToFirst(srv,'/');
+ while(srv.startsWith("/"))srv.remove(0,1);
+ KviQString::cutFromLast(srv,':');
+ //We should have a full server name here, without the irc:// and without the port
+ if(KviQString::equalCIN(srv,word,word.length()))
+ {
+ matches->append(new QString(srv));
+ }
+
+ }
+}
+
+void KviConsole::getUserTipText(const QString &nick,KviIrcUserEntry *e,QString &buffer)
+{
+ KviRegisteredMask *u = g_pRegisteredUserDataBase->findMatchingMask(nick,e->user(),e->host());
+
+ buffer = "<table width=\"100%\">" \
+ "<tr><td bgcolor=\"#303030\">" \
+ "<center><font color=\"#FFFFFF\"><b>";
+
+ buffer += nick;
+ buffer += "!";
+ buffer += e->user().isEmpty() ? QString("*") : e->user();
+ buffer += "@";
+ buffer += e->host().isEmpty() ? QString("*") : e->host();
+
+
+ buffer += "</b></font></center></td></tr>";
+ if(u)
+ {
+ QString szComment=u->user()->getProperty("comment");
+ if(!szComment.isEmpty())
+ {
+ buffer += "<tr bgcolor=\"#F0F0F0\"><td><center><font size=\"-1\">(";
+ buffer += szComment;
+ buffer += ")</font></center></td></tr>";
+ }
+ }
+ if(e->avatar())
+ {
+#ifdef COMPILE_USE_QT4
+ Q3MimeSourceFactory::defaultFactory()->setPixmap("ulv_avatar",*(e->avatar()->pixmap()));
+#else
+ QMimeSourceFactory::defaultFactory()->setPixmap("ulv_avatar",*(e->avatar()->pixmap()));
+#endif
+ buffer += QString("<tr><td><center><img src=\"ulv_avatar\" width=\"%1\"></center></td></tr>").arg(e->avatar()->pixmap()->width());
+ }
+
+ if(e->hasRealName())
+ {
+ buffer += "<tr><td><center><b>";
+ buffer += KviMircCntrl::stripControlBytes(e->realName());
+ buffer += "</b></center></td></tr>";
+ }
+
+ if(e->gender()!=KviIrcUserEntry::Unknown)
+ {
+ buffer += "<tr><td>";
+ buffer += __tr2qs("Gender:");
+ buffer += " ";
+ buffer += (e->gender()==KviIrcUserEntry::Male) ? __tr2qs("Male") : __tr2qs("Female");
+ buffer += "</td></tr>";
+ }
+
+ if(u)
+ {
+ QString mask;
+ u->mask()->mask(mask);
+ buffer += "<tr bgcolor=\"#F0F0F0\"><td>";
+ buffer += __tr2qs("Registered as");
+ buffer += " <b>";
+ buffer += u->user()->name();
+ buffer += "</b>; Group ";
+ buffer += u->user()->group();
+ buffer += "</td></tr><tr bgcolor=\"#F0F0F0\"><td><font size=\"-1\">";
+ buffer += __tr2qs("(Matched by");
+ buffer += " ";
+ buffer += mask;
+ buffer += ")</td></tr>";
+ }
+
+ if(connection())
+ {
+ QString chans;
+ if(connection()->getCommonChannels(nick,chans,false))
+ {
+ buffer += "<tr><td bgcolor=\"#F0F0F0\">";
+ buffer += __tr2qs("On <b>");
+ buffer += chans;
+ buffer += "</b></td></tr>";
+ }
+ }
+
+ if(e->hasServer())
+ {
+ buffer += "<tr><td bgcolor=\"#F0F0F0\"><nobr>";
+ buffer += __tr2qs("Using server <b>%1</b>").arg(e->server());
+
+ if(e->hasHops())
+ {
+ buffer += " (";
+ buffer += __tr2qs("%1 hops").arg(e->hops());
+ buffer += ")</nobr></td></tr>";
+ } else {
+ buffer += "</nobr></td></tr></table>";
+ }
+ }
+
+ if(e->isAway())
+ {
+ buffer += "<tr><td bgcolor=\"#F0F0F0\">";
+ buffer += __tr2qs("Probably Away");
+ buffer += "</td></tr>";
+ }
+}
+
+
+void KviConsole::toggleNotifyView()
+{
+ showNotifyList(!m_pNotifyListView->isVisible());
+}
+
+void KviConsole::executeInternalCommand(int index)
+{
+ KviKvsScript::run(kvi_getInternalCommandBuffer(index),this);
+}
+
+void KviConsole::saveProperties(KviConfig *cfg)
+{
+ KviWindow::saveProperties(cfg);
+ cfg->writeEntry("Splitter",m_pSplitter->sizes());
+ cfg->writeEntry("NotifyListViewVisible",m_pNotifyListView->isVisible());
+
+}
+
+void KviConsole::getBaseLogFileName(QString &buffer)
+{
+ buffer=QString("CONSOLE%1").arg(ircContextId());
+}
+
+void KviConsole::showNotifyList(bool bShow)
+{
+ if(!bShow)
+ {
+ m_pNotifyListView->hide();
+ if(m_pNotifyViewButton->isOn())m_pNotifyViewButton->setOn(false);
+ } else {
+ m_pNotifyListView->show();
+ if(!(m_pNotifyViewButton->isOn()))m_pNotifyViewButton->setOn(true);
+ }
+}
+
+void KviConsole::loadProperties(KviConfig *cfg)
+{
+ int w = width();
+ KviValueList<int> def;
+ def.append((w * 85) / 100);
+ def.append((w * 15) / 100);
+ KviValueList<int> cur = cfg->readIntListEntry("Splitter",def);
+ // check the size correctness
+ if(cur.count() != 2)cur = def;
+ else {
+ int i1 = cur[0];
+ int i2 = cur[1];
+ if(i1 < i2)cur = def;
+ }
+ m_pSplitter->setSizes(cur);
+ KviWindow::loadProperties(cfg);
+ showNotifyList(cfg->readBoolEntry("NotifyListViewVisible",false));
+}
+
+void KviConsole::textViewRightClicked()
+{
+ KVS_TRIGGER_EVENT_0(KviEvent_OnConsolePopupRequest,this);
+}
+
+
+KviWindow * KviConsole::activeWindow()
+{
+ if(!g_pActiveWindow)return this;
+ if(g_pActiveWindow->console() == this)return g_pActiveWindow;
+ return this;
+}
+
+void KviConsole::ircUriChanged(const QString & text){
+ if(KviIrcUrl::run(text,KviIrcUrl::CurrentContext,this) & KviIrcUrl::InvalidProtocol)
+ {
+ KviMessageBox::warning(__tr2qs("KVIrc can accept only irc://, irc6://, ircs:// or irc6s:// URL's\n"
+ "Your URL is invalid. Check spelling and try again"));
+ }
+}
+
+void KviConsole::updateUri()
+{
+ QString uri;
+ if(connection())
+ {
+ KviIrcServer* server = connection()->target()->server();
+ if(server)
+ {
+ KviIrcUrl::join(uri,server);
+ KviChannel * last =connection()->channelList()->last();
+ for(KviChannel * c = connection()->channelList()->first();c;c = connection()->channelList()->next())
+ {
+ uri.append(c->name());
+ if(c->hasChannelKey()) {
+ uri.append("?");
+ uri.append(c->channelKey());
+ }
+ if(c!=last) uri.append(",");
+ }
+ }
+ }
+ m_pAddressEdit->setCurrentText(uri);
+}
+
+void KviConsole::connectionAttached()
+{
+ //need to update URI
+ connect(m_pContext->connection(),SIGNAL(chanListChanged()),this,SLOT(updateUri()));
+ updateUri();
+ m_pNotifyListView->setUserDataBase(connection()->userDataBase());
+}
+
+void KviConsole::connectionDetached()
+{
+ //need to update URI?
+ m_pNotifyListView->partAll();
+ m_pNotifyListView->setUserDataBase(0); // this is rather for crash tests
+}
+
+bool KviConsole::isIpV6Connection()
+{
+ __range_valid(connection());
+ return connection()->server()->isIpV6();
+}
+
+void KviConsole::closeEvent(QCloseEvent *e)
+{
+ if(g_pFrame->consoleCount() > 1)
+ {
+ // there are other consoles beside this one
+ if(context()->state() == KviIrcContext::Connected)
+ {
+ if(!KVI_OPTION_BOOL(KviOption_boolAlwaysDisconnectClosingConnectedConsole))
+ {
+ switch(QMessageBox::warning(this,
+ __tr2qs("Confirmation - KVIrc"),
+ __tr2qs("You have just attempted to close a console window with an active connection inside.\n" \
+ "Are you sure you wish to terminate the connection?"),
+ __tr2qs("&Always"),
+ __tr2qs("&Yes"),
+ __tr2qs("&No"),
+ 2,2))
+ {
+ case 0:
+ KVI_OPTION_BOOL(KviOption_boolAlwaysDisconnectClosingConnectedConsole) = true;
+ break;
+ case 1:
+ // nothing here
+ break;
+ default: // 2 = no
+ return;
+ break;
+ }
+ }
+ // ask the context to terminate the connection gracefully
+ context()->terminateConnectionRequest(false);
+ // the close event will recall terminateConnectionRequest()
+ // to brutally interrupt it in a while
+ }
+
+ // just close
+ KviWindow::closeEvent(e);
+ return;
+ }
+
+ // this is the only console... ask if the user really wants to quit KVirc
+ if(!KVI_OPTION_BOOL(KviOption_boolAlwaysQuitKVIrcClosingLastConsole))
+ {
+ switch(QMessageBox::warning(this,
+ __tr2qs("Confirmation - KVIrc"),
+ __tr2qs("You have just attempted to close the last console window.\nAre you sure you wish to quit KVIrc?"),
+ __tr2qs("&Always"),
+ __tr2qs("&Yes"),
+ __tr2qs("&No"),
+ 2,2))
+ {
+ case 0:
+ KVI_OPTION_BOOL(KviOption_boolAlwaysQuitKVIrcClosingLastConsole) = true;
+ break;
+ case 1:
+ // nothing here
+ break;
+ default: // 2 = no
+ return;
+ break;
+ }
+ }
+
+ g_pApp->quit();
+}
+
+// internal helper for applyHighlighting
+int KviConsole::triggerOnHighlight(KviWindow *wnd,int type,const QString &nick,const QString &user,const QString &host,const QString &szMsg,const QString &trigger)
+{
+ if(!KVI_OPTION_STRING(KviOption_stringOnHighlightedMessageSound).isEmpty() && wnd!=g_pActiveWindow) KviKvsScript::run("snd.play $0",0,new KviKvsVariantList(new KviKvsVariant(KVI_OPTION_STRING(KviOption_stringOnHighlightedMessageSound))));
+ QString szMessageType;
+ KviQString::sprintf(szMessageType,"%d",type);
+ if(KVS_TRIGGER_EVENT_7_HALTED(KviEvent_OnHighlight,
+ wnd,nick,user,host,
+ szMsg,trigger,
+ szMessageType,(type == KVI_OUT_ACTION)))
+ return -1;
+ return KVI_OUT_HIGHLIGHT;
+}
+
+// if it returns -1 you should just return and not display the message
+int KviConsole::applyHighlighting(KviWindow *wnd,int type,const QString &nick,const QString &user,const QString &host,const QString &szMsg)
+{
+ QString szPattern=KVI_OPTION_STRING(KviOption_stringWordSplitters);
+ QString szSource;
+ QString szStripMsg=KviMircCntrl::stripControlBytes(szMsg);
+ QChar* aux=(QChar*)(szStripMsg.ucs2());
+ if(aux)
+ {
+ while(aux->unicode())
+ {
+ if( KVI_OPTION_STRING(KviOption_stringWordSplitters).find(*aux) > -1 )
+ szSource.append(' ');
+ else
+ szSource.append(*aux);
+ aux++;
+ }
+ } else {
+ szSource=szStripMsg;
+ }
+ szSource.append(' ');
+ szSource.prepend(' ');
+ if(KVI_OPTION_BOOL(KviOption_boolAlwaysHighlightNick) && connection())
+ {
+ if(szSource.find(QString(" %1 ").arg(connection()->userInfo()->nickName()),0,false) > -1)
+ return triggerOnHighlight(wnd,type,nick,user,host,szMsg,connection()->userInfo()->nickName());
+ }
+
+ if(KVI_OPTION_BOOL(KviOption_boolUseWordHighlighting))
+ {
+ for(QStringList::Iterator it = KVI_OPTION_STRINGLIST(KviOption_stringlistHighlightWords).begin();
+ it != KVI_OPTION_STRINGLIST(KviOption_stringlistHighlightWords).end() ; ++it)
+ {
+ if((*it).isEmpty())
+ continue;
+ // FIXME : This is SLOOOOOOOOW (QString -> ascii translation!!) !!!!
+ if(szSource.find(QString(" %1 ").arg(*it),0,false) > -1)
+ {
+ return triggerOnHighlight(wnd,type,nick,user,host,szMsg,*it);
+ }
+ }
+ }
+
+ if(wnd->type() == KVI_WINDOW_TYPE_CHANNEL)
+ {
+ if(((KviChannel *)wnd)->isHighlightedUser(nick))
+ return triggerOnHighlight(wnd,type,nick,user,host,szMsg,nick);
+
+ // FIXME: this is for userhighlighing
+ // maybe mark the users as highlighted in the console user database
+ // and then lookup them there ? this would be potentially a lot faster
+ KviRegisteredUser * u = connection()->userDataBase()->registeredUser(nick,user,host);
+
+ // note that we're highlighting users only in channels since
+ // in a query (or DCC) highlighting the remote end is senseless.
+ if(u)
+ {
+ if(u->getBoolProperty("highlight"))
+ return triggerOnHighlight(wnd,type,nick,user,host,szMsg,nick);
+ }
+ }
+
+ return type;
+}
+
+#define KVI_NUM_NICK_COLORS 95
+
+static const char * g_nickColors[KVI_NUM_NICK_COLORS]=
+{
+ "0,1" ,"0,2" ,"0,3" ,"0,4" ,"0,5" ,"0,6" ,"0,10" ,"0,12" ,"0,14" , //9
+ "1,0" ,"1,4" ,"1,7" ,"1,8" ,"1,9" ,"1,11" ,"1,15" , //7
+ "2,0" ,"2,4" ,"2,7" ,"2,8" ,"2,9" ,"2,11" ,"2,15" , //7
+ "3,8" ,"3,9" ,"3,0" ,"3,15" , //4
+ "4,0" ,"4,1" ,"4,8" ,"4,9" ,"4,11" ,"4,15" , //6
+ "5,0" ,"5,7" ,"5,8" ,"5,15" , //4
+ "6,0" ,"6,7" ,"6,8" ,"6,9" ,"6,10" ,"6,11" ,"6,15" , //7
+ "7,1" ,"7,2" ,"7,5" ,"7,6" ,"7,14" , //5
+ "8,1" ,"8,2" ,"8,3" ,"8,4" ,"8,5" ,"8,6" ,"8,7" ,"8,10" ,"8,12" ,"8,14" , //10
+ "9,1" ,"9,2" ,"9,3" ,"9,5" ,"9,6" ,"9,14" , //6
+ "10,1" ,"10,2" , //2
+ "11,1" ,"11,2" ,"11,3" ,"11,5" ,"11,6" ,"11,14", //6
+ "12,0" ,"12,7" ,"12,8" ,"12,9" ,"12,10","12,11","12,15", //7
+ "13,0" ,"13,1" ,"13,6" ,"13,8" ,"13,11","13,15", //6
+ "14,0" ,"14,8" ,"14,11","14,15", //4
+ "15,1" ,"15,2" ,"15,3" ,"15,6" ,"15,14" //5
+};
+
+void KviConsole::outputPrivmsg(KviWindow *wnd,
+ int type,
+ const QString &daNick,
+ const QString &daUser,
+ const QString &daHost,
+ const QString &msg,
+ int iFlags,
+ const QString &prefix,
+ const QString &suffix)
+{
+ // FIXME: #warning "THIS IS USED BY WINDOWS THAT ARE NOT BOUND TO THIS IRC CONTEXT"
+ // FIXME: #warning "REMEMBER IT IN ESCAPE COMMANDS"
+ // __range_valid(wnd);
+
+ bool bIsChan = (wnd->type() == KVI_WINDOW_TYPE_CHANNEL);
+ bool bIsNotice = ((type == KVI_OUT_CHANNELNOTICE)||(type == KVI_OUT_CHANNELNOTICECRYPTED) \
+ ||(type == KVI_OUT_QUERYNOTICE)||(type == KVI_OUT_QUERYNOTICECRYPTED));
+
+ QString nick = daNick; // not that beautiful.. :/
+ QString user = daUser;
+ QString host = daHost;
+
+ if(connection())
+ {
+ if(nick.isEmpty())nick = connection()->userInfo()->nickName();
+ if(user.isEmpty())user = connection()->userInfo()->userName();
+ if(host.isEmpty())host = connection()->userInfo()->hostName();
+ }
+
+ QString szDecodedMessage = msg; // shallow copy
+
+ if(KVI_OPTION_BOOL(KviOption_boolStripMircColorsInUserMessages))
+ szDecodedMessage = KviMircCntrl::stripControlBytes(szDecodedMessage);
+
+ if(!(iFlags & NoHighlighting))
+ {
+ // HIGHLIGHTING BLOCK
+ int iSaveType = type;
+ type = applyHighlighting(wnd,type,nick,user,host,szDecodedMessage);
+ if(type < 0)return; // event stopped the message!
+ if(type == KVI_OUT_HIGHLIGHT)
+ {
+ if(!wnd->hasAttention())
+ {
+ if(KVI_OPTION_BOOL(KviOption_boolFlashWindowOnHighlightedMessages) &&
+ (!(iFlags & NoWindowFlashing)))
+ {
+ wnd->demandAttention();
+ }
+ if(KVI_OPTION_BOOL(KviOption_boolPopupNotifierOnHighlightedMessages) &&
+ (!(iFlags & NoNotifier)))
+ {
+ QString szMsg = "<b>&lt;";
+ szMsg += nick;
+ szMsg += "&gt;</b> ";
+ #ifdef COMPILE_USE_QT4
+ szMsg += Qt::escape(szDecodedMessage);
+ #else
+ szMsg += QStyleSheet::escape(szDecodedMessage);
+ #endif
+ //debug("kvi_console.cpp:629 debug: %s",szMsg.data());
+ g_pApp->notifierMessage(wnd,KVI_OPTION_MSGTYPE(iSaveType).pixId(),szMsg,90);
+ }
+ }
+ }
+ }
+
+ // <PREFIX>nick[!user@host]<POSTFIX>This is a test message
+
+ QString szNick;
+ KviQString::sprintf(szNick,"\r!nc\r%Q\r",&nick);
+
+ if(KVI_OPTION_BOOL(KviOption_boolShowUserAndHostInPrivmsgView))
+ KviQString::appendFormatted(szNick,"!%Q@\r!h\r%Q\r",&user,&host);
+
+ if(bIsChan && KVI_OPTION_BOOL(KviOption_boolShowChannelUserFlagInPrivmsgView))
+ ((KviChannel *)wnd)->prependUserFlag(nick,szNick);
+
+ if(KVI_OPTION_BOOL(KviOption_boolColorNicks))
+ {
+ int sum = 0;
+ int i = nick.length();
+ const QChar * aux = nick.unicode();
+ // FIXME: Shouldn't this be case insensitive ?
+ while(i > 0)
+ {
+ sum += aux->unicode();
+ aux++;
+ i--;
+ }
+ szNick.prepend(g_nickColors[sum % KVI_NUM_NICK_COLORS]);
+ szNick.prepend(KVI_TEXT_COLOR);
+ szNick.append(KVI_TEXT_COLOR);
+ }
+/* if(KVI_OPTION_BOOL(KviOption_boolUseUserListColorsAsNickColors) && bIsChan)
+ {
+ if(((KviChannel*)wnd)->userListView())
+ {
+ KviUserListEntry *e = ((KviChannel*)wnd)->userListView()->findEntry(nick);
+ if(e)
+ {
+ int sum = 0;
+ int i = nick.length();
+ const QChar * aux = nick.unicode();
+ // FIXME: Shouldn't this be case insensitive ?
+ while(i > 0)
+ {
+ sum += aux->unicode();
+ aux++;
+ i--;
+ }
+ int color;
+ if(e->flags() == 0)
+ {
+ color = KVI_COLOR_EXT_USER_NORMAL;
+ } else {
+ color = (e->flags() & KVI_USERFLAG_CHANOWNER) ? \
+ KVI_COLOR_EXT_USER_OWNER : ((e->flags() & KVI_USERFLAG_CHANADMIN) ? \
+ KVI_COLOR_EXT_USER_ADMIN : ((e->flags() & KVI_USERFLAG_OP) ? \
+ KVI_COLOR_EXT_USER_OP : ((e->flags() & KVI_USERFLAG_HALFOP) ? \
+ KVI_COLOR_EXT_USER_HALFOP : ((e->flags() & KVI_USERFLAG_VOICE) ? \
+ KVI_COLOR_EXT_USER_VOICE : KVI_COLOR_EXT_USER_USEROP))));
+ }
+ szNick.prepend(QString("%1").arg(color));
+ szNick.prepend(KVI_TEXT_COLOR);
+ szNick.append(KVI_TEXT_COLOR);
+ }
+ }
+ }*/
+ if(KVI_OPTION_BOOL(KviOption_boolBoldedNicks))
+ {
+ szNick.prepend(KVI_TEXT_BOLD);
+ szNick.append(KVI_TEXT_BOLD);
+ }
+
+ QString szMessage;
+
+ if(KVI_OPTION_BOOL(KviOption_boolUseExtendedPrivmsgView))
+ {
+ szMessage = prefix.isEmpty() ? KVI_OPTION_STRING(KviOption_stringExtendedPrivmsgPrefix) : prefix;
+ szMessage += szNick;
+ szMessage += suffix.isEmpty() ? KVI_OPTION_STRING(KviOption_stringExtendedPrivmsgPostfix) : suffix;
+ } else {
+ if(bIsNotice)
+ {
+ static QString pre1("*");
+ static QString suf1("* ");
+ szMessage = prefix.isEmpty() ? pre1 : prefix;
+ szMessage += szNick;
+ szMessage += suffix.isEmpty() ? suf1 : suffix;
+ } else {
+ static QString pre2("<");
+ static QString suf2("> ");
+ szMessage = prefix.isEmpty() ? pre2 : prefix;
+ szMessage += szNick;
+ szMessage += suffix.isEmpty() ? suf2 : suffix;
+ }
+ }
+
+ szMessage += szDecodedMessage;
+
+ if(bIsChan)((KviChannel *)wnd)->outputMessage(type,szMessage);
+ else wnd->outputNoFmt(type,szMessage);
+}
+
+void KviConsole::avatarChangedUpdateWindows(const QString &nick,const QString &textLine)
+{
+ if(!connection())return; //ops...
+
+ // in quiet mode avoid bugging the user about avatar changes
+ bool bOut = ((!textLine.isEmpty()) && (!(_OUTPUT_QUIET)));
+
+ for(KviChannel * c = connection()->channelList()->first();c;c = connection()->channelList()->next())
+ {
+ if(c->avatarChanged(nick))
+ {
+ if(bOut)c->outputNoFmt(KVI_OUT_AVATAR,textLine);
+ }
+ }
+ for(KviQuery * q = connection()->queryList()->first();q;q = connection()->queryList()->next())
+ {
+ if(q->avatarChanged(nick))
+ {
+ if(bOut)q->outputNoFmt(KVI_OUT_AVATAR,textLine);
+ }
+ }
+ m_pNotifyListView->avatarChanged(nick); // recalc the item height here too!
+}
+
+void KviConsole::avatarChanged(KviAvatar * avatar,const QString &nick,const QString &user,const QString &host,const QString &textLine)
+{
+ if(!connection())return; //ops...
+
+ bool bRegisteredStuff = false;
+
+ if(KVI_OPTION_BOOL(KviOption_boolSetLastAvatarAsDefaultForRegisteredUsers))
+ {
+ // Don't even try to do it for myself
+ if(!KviQString::equalCI(nick,connection()->userInfo()->nickName()))
+ {
+ KviRegisteredUser * u = connection()->userDataBase()->registeredUser(nick,user,host);
+ if(u)
+ {
+ if(avatar)u->setProperty("avatar",avatar->identificationString());
+ else u->setProperty("avatar",QString::null);
+ bRegisteredStuff = true;
+ }
+ }
+ }
+
+ if(!bRegisteredStuff)
+ {
+ // cache it
+ if(avatar)
+ KviAvatarCache::instance()->replace(avatar->identificationString(),KviIrcMask(nick,user,host),currentNetworkName().utf8().data());
+ else
+ KviAvatarCache::instance()->remove(KviIrcMask(nick,user,host),currentNetworkName().utf8().data());
+ }
+
+ avatarChangedUpdateWindows(nick,textLine);
+}
+
+void KviConsole::checkDefaultAvatar(KviIrcUserEntry *e,const QString &nick,const QString &user,const QString &host)
+{
+ // look it up in the cache
+ QString szAvatar = KviAvatarCache::instance()->lookup(KviIrcMask(nick,user,host),currentNetworkName().utf8().data());
+ if(!szAvatar.isEmpty())
+ {
+ // got a cache hit... is it on disk ?
+ KviAvatar * avatar = g_pIconManager->getAvatar(QString::null,szAvatar);
+ if(avatar)
+ {
+ // cached image on disk
+ e->setAvatar(avatar);
+ avatarChangedUpdateWindows(nick,QString::null);
+ return;
+ } else {
+ // no cached image on disk.. will need to requery it anyway
+ // remove from cache
+ KviAvatarCache::instance()->remove(KviIrcMask(nick,user,host),currentNetworkName().utf8().data());
+ }
+ }
+
+ // registered ?
+ KviRegisteredUser * u = connection()->userDataBase()->registeredUser(nick,user,host);
+ if(u)
+ {
+ // the user is registered...
+ QString szAvatar;
+ if(u->getProperty("avatar",szAvatar))
+ {
+ // the user has a default avatar...
+ KviAvatar * avatar = g_pIconManager->getAvatar(QString::null,szAvatar);
+ if(avatar)
+ {
+ e->setAvatar(avatar);
+ avatarChangedUpdateWindows(nick,QString::null);
+ return;
+ }
+ }
+ }
+}
+
+void KviConsole::resetAvatarForMatchingUsers(KviRegisteredUser * u)
+{
+ if(!connection())return;
+
+ QString szAvatar;
+ if(!u->getProperty("avatar",szAvatar))return;
+
+ KviPointerHashTableIterator<QString,KviIrcUserEntry> it(*(connection()->userDataBase()->dict()));
+ while(KviIrcUserEntry * e = it.current())
+ {
+ if(e->hasHost())
+ {
+ if(u->matchesFixed(it.currentKey(),e->user(),e->host()))
+ {
+ KviAvatar * a = g_pIconManager->getAvatar(QString::null,szAvatar);
+ e->setAvatar(a);
+ avatarChangedUpdateWindows(it.currentKey(),QString::null);
+ }
+ }
+ ++it;
+ }
+}
+
+KviAvatar * KviConsole::setAvatar(const QString &nick,const QString &user,const QString &host,const QString &szLocalPath,const QString &szName)
+{
+ if(!connection())return 0;
+ KviIrcUserEntry * e = connection()->userDataBase()->find(nick);
+ if(e)
+ {
+ // User and host must match
+ if((!user.isEmpty()) && e->hasUser())
+ {
+ if(!KviQString::equalCI(user,e->user()))return 0;
+ }
+
+ if((!host.isEmpty()) && e->hasHost())
+ {
+ if(!KviQString::equalCI(host,e->host()))return 0;
+ }
+
+ // Ok...got it
+
+ KviAvatar * avatar = g_pIconManager->getAvatar(szLocalPath,szName);
+ if(avatar)
+ {
+ e->setAvatar(avatar);
+ avatarChanged(avatar,nick,user,host,QString::null);
+ return avatar;
+ } else {
+ if(_OUTPUT_PARANOIC)
+ output(KVI_OUT_VERBOSE,__tr2qs("Failed to load avatar with name \"%Q\" and local path \"%Q\""),&szName,&szLocalPath);
+ }
+ }
+ return 0;
+}
+
+KviAvatar * KviConsole::defaultAvatarFromOptions()
+{
+ QPixmap * avatar = KVI_OPTION_PIXMAP(KviOption_pixmapMyAvatar).pixmap();
+ if(!avatar)return 0;
+ if(avatar->isNull())return 0;
+ if(KVI_OPTION_STRING(KviOption_stringMyAvatar).isEmpty())return 0;
+ return new KviAvatar(KVI_OPTION_PIXMAP(KviOption_pixmapMyAvatar).path(),KVI_OPTION_STRING(KviOption_stringMyAvatar),new QPixmap(*avatar));
+}
+
+KviAvatar * KviConsole::currentAvatar()
+{
+ if(!connection())return 0;
+ KviIrcUserEntry * e = connection()->userDataBase()->find(connection()->userInfo()->nickName());
+ if(!e)return 0;
+ KviAvatar * a = e->avatar();
+ if(!a)
+ {
+ a = defaultAvatarFromOptions();
+ if(a)
+ {
+ e->setAvatar(a);
+ avatarChanged(a,connection()->userInfo()->nickName(),QString::null,QString::null,QString::null);
+ }
+ }
+ return a;
+}
+
+void KviConsole::setAvatarFromOptions()
+{
+ if(!connection())return;
+ KviIrcUserEntry * e = connection()->userDataBase()->find(connection()->userInfo()->nickName());
+ if(!e)return;
+ KviAvatar * a = defaultAvatarFromOptions();
+ if(a)
+ {
+ e->setAvatar(a);
+ avatarChanged(a,connection()->userInfo()->nickName(),QString::null,QString::null,QString::null);
+ }
+}
+
+void KviConsole::applyOptions()
+{
+ m_pNotifyListView->applyOptions();
+ m_pInput->applyOptions();
+ m_pIrcView->applyOptions();
+
+ KviWindow::applyOptions();
+
+ // trick
+ resize(width() - 1,height() - 1);
+ resize(width() + 1,height() + 1);
+}
+
+void KviConsole::resizeEvent(QResizeEvent *e)
+{
+ int hght = m_pInput->heightHint();
+ int hght2 = m_pButtonBox->sizeHint().height();
+ m_pButtonBox->setGeometry(0,0,width(),hght2);
+ m_pSplitter->setGeometry(0,hght2,width(),height() - (hght + hght2));
+ m_pInput->setGeometry(0,height() - hght,width(),hght);
+}
+
+QSize KviConsole::sizeHint() const
+{
+ QSize ret(m_pIrcView->sizeHint().height(),m_pIrcView->sizeHint().height() + m_pInput->heightHint());
+ return ret;
+}
+
+void KviConsole::fillStatusString()
+{
+ switch(context()->state())
+ {
+ case KviIrcContext::Idle: m_szStatusString = __tr2qs("No connection"); break;
+ case KviIrcContext::Connecting: m_szStatusString = __tr2qs("Connection in progress..."); break;
+ case KviIrcContext::LoggingIn: m_szStatusString = __tr2qs("Login in progress..."); break;
+ case KviIrcContext::Connected:
+ m_szStatusString = connection()->userInfo()->nickName();
+ if(!connection()->userInfo()->userMode().isEmpty())
+ {
+ m_szStatusString += " (+";
+ m_szStatusString += connection()->userInfo()->userMode();
+
+ if(connection()->userInfo()->isAway())
+ {
+ m_szStatusString += QChar(' ');
+ m_szStatusString += __tr2qs("away");
+ }
+ m_szStatusString += QChar(')');
+ } else {
+ if(connection()->userInfo()->isAway())
+ {
+ m_szStatusString += " (";
+ m_szStatusString += __tr2qs("away");
+ m_szStatusString += QChar(')');
+ }
+ }
+
+ m_szStatusString += __tr2qs(" on ");
+ m_szStatusString += connection()->serverInfo()->name();
+ break;
+ }
+}
+
+void KviConsole::fillCaptionBuffers()
+{
+ fillStatusString();
+
+ static QString begin("<nobr><font color=\"");
+ static QString boldbegin("\"><b>");
+ static QString endofbold("</b></font> <font color=\"");
+ static QString endoffont("\">");
+ static QString end("</font></nobr>");
+
+ m_szPlainTextCaption = windowName();
+ m_szPlainTextCaption += " [";
+ m_szPlainTextCaption += m_szStatusString;
+ m_szPlainTextCaption += QChar(']');
+
+ m_szHtmlActiveCaption = begin;
+ m_szHtmlActiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextActive).name();
+ m_szHtmlActiveCaption += boldbegin;
+ m_szHtmlActiveCaption += windowName();
+ m_szHtmlActiveCaption += endofbold;
+ m_szHtmlActiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextActive2).name();
+ m_szHtmlActiveCaption += endoffont;
+ m_szHtmlActiveCaption += m_szStatusString;
+ m_szHtmlActiveCaption += end;
+
+ m_szHtmlInactiveCaption = begin;
+ m_szHtmlInactiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextInactive).name();
+ m_szHtmlInactiveCaption += boldbegin;
+ m_szHtmlInactiveCaption += windowName();
+ m_szHtmlInactiveCaption += endofbold;
+ m_szHtmlInactiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextInactive2).name();
+ m_szHtmlInactiveCaption += endoffont;
+ m_szHtmlInactiveCaption += m_szStatusString;
+ m_szHtmlInactiveCaption += end;
+}
+
+
+QPixmap * KviConsole::myIconPtr()
+{
+ return g_pIconManager->getSmallIcon(isConnected() ? KVI_SMALLICON_LINKS : KVI_SMALLICON_CONSOLE);
+}
+
+
+void KviConsole::getTaskBarTipText(QString &buffer)
+{
+ fillStatusString();
+
+ static QString html_bold("<b>");
+ static QString html_tab("&nbsp;&nbsp;");
+ static QString html_eofbold("</b>");
+ static QString html_hrbr("<br><hr>");
+ static QString html_channel(__tr2qs("channel"));
+ static QString html_channels(__tr2qs("channels"));
+ static QString html_query(__tr2qs("query"));
+ static QString html_queries(__tr2qs("queries"));
+ static QString html_space(" ");
+ static QString html_commaspace(", ");
+ static QString html_br("<br>");
+ static QString html_spaceparopen(" (");
+ static QString html_spaceparclosed(")");
+
+ buffer = "<table width=\"100%\">" \
+ START_TABLE_BOLD_ROW;
+ buffer += m_szStatusString;
+ buffer += END_TABLE_BOLD_ROW;
+ if((context()->state() == KviIrcContext::Connected) && connection())
+ {
+ QString num;
+
+ unsigned int uD;
+ unsigned int uH;
+
+ uD = connection()->channelList()->count();
+ uH = connection()->queryList()->count();
+
+ if(uD || uH > 0)
+ {
+ buffer += "<tr><td>";
+ buffer += html_tab;
+
+ if(uD > 0)
+ {
+ num.setNum(uD);
+
+ buffer += html_bold;
+ buffer += num;
+ buffer += html_eofbold;
+ buffer += html_space;
+ buffer += uD > 1 ? html_channels : html_channel;
+ if(uH > 0)
+ buffer += html_commaspace;
+ }
+
+ if(uH > 0)
+ {
+ num.setNum(uH);
+ buffer += html_bold;
+ buffer += num;
+ buffer += html_eofbold;
+ buffer += html_space;
+ buffer += uH > 1 ? html_queries : html_query;
+ }
+ buffer += "</td></tr>";
+ }
+
+ QDateTime dt;
+ dt.setTime_t(connection()->statistics()->connectionStartTime());
+
+ buffer += START_TABLE_NORMAL_ROW;
+
+ buffer += __tr2qs("Connected since");
+ buffer += html_space;
+ buffer += html_br;
+ buffer += html_tab;
+ buffer += html_bold;
+ buffer += dt.toString();
+ buffer += html_eofbold;
+ buffer += html_br;
+
+ //buffer += html_spaceparopen;
+
+ QString tspan = KviTimeUtils::formatTimeInterval((unsigned int)(kvi_secondsSince(connection()->statistics()->connectionStartTime())),
+ KviTimeUtils::NoLeadingEmptyIntervals | KviTimeUtils::NoLeadingZeroes);
+
+ buffer += __tr2qs("Online for");
+ buffer += html_space;
+ buffer += html_bold;
+ buffer += tspan;
+ buffer += html_eofbold;
+ //buffer += html_spaceparclosed;
+
+ buffer += "</td></tr><tr><td bgcolor=\"#F0F0F0\">";
+
+ tspan = KviTimeUtils::formatTimeInterval((unsigned int)(kvi_secondsSince(connection()->statistics()->lastMessageTime())),
+ KviTimeUtils::NoLeadingEmptyIntervals | KviTimeUtils::NoLeadingZeroes);
+
+ buffer += __tr2qs("Server idle for");
+ buffer += html_space;
+ buffer += html_bold;
+ buffer += tspan;
+ buffer += "</b></td></tr>";
+ }
+
+ buffer += "</table>";
+}
+
+#include "kvi_console.moc"
diff --git a/src/kvirc/ui/kvi_console.h b/src/kvirc/ui/kvi_console.h
new file mode 100644
index 00000000..b9f494c3
--- /dev/null
+++ b/src/kvirc/ui/kvi_console.h
@@ -0,0 +1,212 @@
+#ifndef _KVI_CONSOLE_H_
+#define _KVI_CONSOLE_H_
+//=============================================================================
+//
+// File : kvi_console.h
+// Creation date : Sun Jun 25 2000 15:00:20 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_ircconnection.h"
+#include "kvi_window.h"
+#include "kvi_ircsocket.h"
+#include "kvi_string.h"
+#include "kvi_irccontext.h"
+
+#include "kvi_pointerlist.h"
+
+#include <time.h>
+#include <qcombobox.h>
+
+
+class QToolBar;
+class QToolButton;
+
+class KviAvatar;
+class KviDns;
+class KviIrcUserDataBase;
+class KviIrcUserEntry;
+class KviIrcServer;
+class KviIrcNetwork;
+class KviProxy;
+#ifndef COMPILE_ON_WINDOWS
+ class KviChannel;
+ class KviQuery;
+#else
+ // windoze wants it to compile QList<KviChannel> and QList<KviQuery>
+ #include "kvi_channel.h"
+ #include "kvi_query.h"
+#endif
+class KviUserListView;
+class KviNotifyListManager;
+class KviRegisteredUser;
+class KviWindowToolPageButton;
+
+
+
+//=================================================================================================
+//
+// The console window
+//
+//=================================================================================================
+
+#define KVI_CONSOLE_FLAG_FIRSTINAPP 1
+#define KVI_CONSOLE_FLAG_FIRSTINFRAME 2
+
+
+class KVIRC_API KviConsole : public KviWindow
+{
+ friend class KviFrame;
+ friend class KviIrcSocket;
+ friend class KviChannel;
+ friend class KviQuery;
+ friend class KviIrcContext;
+ Q_OBJECT
+protected:
+ KviConsole(KviFrame * lpFrm,int iFlags);
+public:
+ ~KviConsole();
+protected:
+ int m_iFlags; // FIXME: make this a KviWindow property ?
+ // UI
+ KviUserListView * m_pNotifyListView;
+ KviWindowToolPageButton * m_pNotifyViewButton;
+ QComboBox * m_pAddressEdit;
+ QString m_szStatusString; // nick (flags) on server | not connected
+protected:
+ // UI
+ virtual QPixmap * myIconPtr();
+ virtual void fillCaptionBuffers();
+ virtual void resizeEvent(QResizeEvent *e);
+ virtual void closeEvent(QCloseEvent *e);
+ virtual void getBaseLogFileName(QString &buffer);
+ virtual void getTaskBarTipText(QString &buffer);
+ virtual void fillContextPopup(KviTalPopupMenu * p);
+ virtual QSize sizeHint() const;
+ virtual void applyOptions();
+ virtual void triggerCreationEvents();
+ void fillStatusString();
+ //void socketError(int iError);
+ //void socketStateChange();
+ //void registerLinkMonitor(KviIrcSocketMonitor * m);
+ //void unregisterLinkMonitor(KviIrcSocketMonitor * m);
+ virtual void loadProperties(KviConfig * cfg);
+ virtual void saveProperties(KviConfig * cfg);
+
+ void destroyConnection();
+ // internal helper for applyHighlighting
+ int triggerOnHighlight(KviWindow *wnd,int type,const QString &nick,const QString &user,const QString &host,const QString &szMsg,const QString &trigger);
+
+ void showNotifyList(bool bShow);
+
+public:
+ // UI
+ KviUserListView * notifyListView(){ return m_pNotifyListView; };
+ int selectedCount();
+
+
+ //
+ // State
+ //
+ KviIrcContext::State state(){ return context()->state(); };
+ KVI_DEPRECATED KviIrcContext * ircContext(){ return context(); };
+ unsigned int ircContextId() KVI_DEPRECATED;
+ //
+ // Sock state
+ //
+ KviIrcSocket * socket() KVI_DEPRECATED;
+
+ // these should disappear!
+ bool isConnected(){ return context()->isConnected(); };
+ bool isIpV6Connection();
+ bool isNotConnected();
+ bool connectionInProgress();
+ //
+ // This connection info
+ //
+ QString currentNetworkName();
+ KviAvatar * currentAvatar();
+ //
+ // IRC Context wide helpers (connection related)
+ //
+ void getUserTipText(const QString &nick,KviIrcUserEntry *e,QString &buffer);
+ enum OutputPrivmsgFlags {
+ NoWindowFlashing = 1, // has meaning only if NoHighlighting is NOT given, otherwise it is implied
+ NoNotifier = 2, // has meaning only if NoHighlighitng is NOT given, otherwise it is implied
+ NoHighlighting = 4,
+ NoNotifications = 7 // this is 1|2|4 implies NoWindowFlashing and NoNotifier
+ };
+ void outputPrivmsg(KviWindow *wnd,int type,const QString &nick,
+ const QString &user,const QString &host,const QString &msg,int iFlags = 0,const QString &prefix = QString::null,const QString &suffix = QString::null);
+ // this applies highlighting to the specified message
+ // and triggers the OnHighlight event.
+ // it returns KVI_OUT_HIGHLIGHT if highlighting was applied
+ // and -1 if OnHighlight called halt
+ // otherwise it returns <type>
+ int applyHighlighting(KviWindow *wnd,int type,const QString &nick,const QString &user,const QString &host,const QString &szMsg);
+ // Avatar helpers (conneciton related)
+ void resetAvatarForMatchingUsers(KviRegisteredUser * u);
+ // this should be protected at least
+ void avatarChangedUpdateWindows(const QString &nick,const QString &textLine);
+ void avatarChanged(KviAvatar * avatar,const QString &nick,const QString &user,const QString &host,const QString &textLine);
+ KviAvatar * setAvatar(const QString &nick,const QString &user,const QString &host,const QString &szLocalPath,const QString &szName);
+ void checkDefaultAvatar(KviIrcUserEntry *e,const QString &nick,const QString &user,const QString &host);
+ void setAvatarFromOptions();
+
+ // This returns the default avatar for the current KVIrc user
+ // if he has choosen a valid avatar in the options dialog
+ // otherwise returns 0.
+ // The avatar is allocated with new and must be deleted
+ // when no longer needed.
+ KviAvatar * defaultAvatarFromOptions();
+
+ void terminateConnectionRequest(bool bForce = false,const char * quitMsg = 0);
+
+ // Status string (usermode + nick) (connection related too)
+ const QString & statusString(){ return m_szStatusString; };
+
+ // forwarders from KviIrcConnection
+ KVI_DEPRECATED KviPointerList<KviChannel> * channelList(){ return connection() ? connection()->channelList() : 0; };
+ KVI_DEPRECATED KviPointerList<KviQuery> * queryList(){ return connection() ? connection()->queryList() : 0; };
+ KVI_DEPRECATED unsigned int channelCount(){ return (connection() ? connection()->channelList()->count() : 0); };
+ KVI_DEPRECATED unsigned int queryCount(){ return (connection() ? connection()->queryList()->count() : 0); };
+
+ // Window management
+ //KVI_DEPRECATED KviChannel * findChannel(const char * name){ return connection() ? connection()->findChannel(name) : 0; };
+ //KVI_DEPRECATED KviQuery * findQuery(const char * nick){ return connection() ? connection()->findQuery(nick) : 0; };
+
+ KviWindow * activeWindow();
+ // User db, connection related
+ void completeChannel(const QString &word,KviPointerList<QString> * matches);
+ void completeServer(const QString &word,KviPointerList<QString> * matches);
+ void connectionAttached();
+ void connectionDetached();
+public slots:
+ void updateUri();
+ void executeInternalCommand(int index);
+ void recentUrlsChanged();
+protected slots:
+ void ircUriChanged(const QString & );
+ void toggleNotifyView();
+ void textViewRightClicked();
+};
+
+#endif //_KVI_CONSOLE_H_
diff --git a/src/kvirc/ui/kvi_cryptcontroller.cpp b/src/kvirc/ui/kvi_cryptcontroller.cpp
new file mode 100644
index 00000000..6cbdd5bc
--- /dev/null
+++ b/src/kvirc/ui/kvi_cryptcontroller.cpp
@@ -0,0 +1,390 @@
+//
+// File : kvi_cryptcontroller.cpp
+// Creation date : Fri Nov 03 2000 14:16:33 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#define __KVIRC__
+
+#include "kvi_settings.h"
+
+
+#ifdef COMPILE_CRYPT_SUPPORT
+
+ #include "kvi_cryptcontroller.h"
+ #include "kvi_styled_controls.h"
+
+ #include "kvi_window.h"
+ #include "kvi_locale.h"
+ #include "kvi_out.h"
+ #include "kvi_iconmanager.h"
+ #include "kvi_modulemanager.h"
+ #include "kvi_module.h"
+ #include "kvi_malloc.h"
+ #include "kvi_memmove.h"
+ #include "kvi_toolwindows_container.h"
+
+ #include <qlayout.h>
+ #include "kvi_pointerhashtable.h"
+
+ // kvi_app.cpp
+ extern KVIRC_API KviCryptEngineManager * g_pCryptEngineManager;
+ extern KVIRC_API KviModuleManager * g_pModuleManager;
+
+ KviEngineListBoxItem::KviEngineListBoxItem(KviTalListBox * lb,KviCryptEngineDescription * d,const char * modName)
+ : KviTalListBoxText(lb,d->szName)
+ {
+ m_szName = d->szName;
+ m_szAuthor = d->szAuthor;
+ m_szDescription = d->szDescription;
+ m_iFlags = d->iFlags;
+ m_szModuleName = modName;
+ setText(d->szName);
+ }
+
+ KviEngineListBoxItem::~KviEngineListBoxItem()
+ {
+ }
+
+
+
+
+ KviCryptController::KviCryptController(QWidget * par,KviWindowToolPageButton* button,const char * name,KviWindow * wnd,KviCryptSessionInfo * cur)
+ : KviWindowToolWidget(par,button)
+ {
+// FIXME: #warning "Load the available modules here"
+
+ // Load the known encryption modules
+ (void)g_pModuleManager->loadModulesByCaps("crypt");
+// (void)g_pModuleManager->getModule("koi2win");
+// (void)g_pModuleManager->getModule("mircstrip");
+// (void)g_pModuleManager->getModule("texturizer");
+
+ m_pWindow = wnd;
+
+#ifdef COMPILE_USE_QT4
+ setFocusPolicy(Qt::ClickFocus);
+#else
+ setFocusPolicy(QWidget::ClickFocus);
+#endif
+
+ QGridLayout *g = new QGridLayout(this,10,4,2,2);
+
+ QLabel *l = new QLabel(this);
+ l->setPixmap(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_LOCKED)));
+ g->addWidget(l,0,0);
+ l = new QLabel(__tr2qs("Cryptography/text transformation"),this);
+ g->addMultiCellWidget(l,0,0,1,3);
+
+ QFrame * frm = new QFrame(this);
+ frm->setFrameStyle(QFrame::HLine | QFrame::Sunken);
+ g->addMultiCellWidget(frm,1,1,0,3);
+
+ m_pEnableCheck = new KviStyledCheckBox(__tr2qs("Use the crypt engine"),this);
+ g->addMultiCellWidget(m_pEnableCheck,2,2,0,3);
+ connect(m_pEnableCheck,SIGNAL(toggled(bool)),this,SLOT(enableCheckToggled(bool)));
+
+ m_pListBox = new KviTalListBox(this);
+ connect(m_pListBox,SIGNAL(highlighted(KviTalListBoxItem *)),this,SLOT(engineHighlighted(KviTalListBoxItem *)));
+ g->addMultiCellWidget(m_pListBox,3,8,0,0);
+
+ m_pDescriptionLabel = new QLabel(this);
+ m_pDescriptionLabel->setFrameStyle(QFrame::Sunken | QFrame::StyledPanel);
+#ifdef COMPILE_USE_QT4
+ m_pDescriptionLabel->setAlignment(Qt::AlignTop | Qt::AlignLeft);
+#else
+ m_pDescriptionLabel->setAlignment(Qt::AlignTop | Qt::AlignLeft);
+#endif
+ g->addMultiCellWidget(m_pDescriptionLabel,3,3,1,3);
+
+ m_pAuthorLabel = new QLabel(this);
+ m_pAuthorLabel->setFrameStyle(QFrame::Sunken | QFrame::StyledPanel);
+ g->addMultiCellWidget(m_pAuthorLabel,4,4,1,3);
+
+ m_pEnableEncrypt = new KviStyledCheckBox(__tr2qs("Enable encryption"),this);
+ g->addMultiCellWidget(m_pEnableEncrypt,5,5,1,3);
+
+ m_pEncryptKeyLabel = new QLabel(__tr2qs("Encrypt key:"),this);
+ g->addWidget(m_pEncryptKeyLabel,6,1);
+
+ m_pEncryptKeyEdit = new QLineEdit(this);
+ g->addWidget(m_pEncryptKeyEdit,6,2);
+
+ m_pEncryptHexKeyCheck = new KviStyledCheckBox(__tr2qs("Hex"),this);
+ g->addWidget(m_pEncryptHexKeyCheck,6,3);
+
+ m_pEnableDecrypt = new KviStyledCheckBox(__tr2qs("Enable decryption"),this);
+ g->addMultiCellWidget(m_pEnableDecrypt,7,7,1,3);
+
+ m_pDecryptKeyLabel = new QLabel(__tr2qs("Decrypt key:"),this);
+ g->addWidget(m_pDecryptKeyLabel,8,1);
+
+ m_pDecryptKeyEdit = new QLineEdit(this);
+ g->addWidget(m_pDecryptKeyEdit,8,2);
+
+ m_pDecryptHexKeyCheck = new KviStyledCheckBox(__tr2qs("Hex"),this);
+ g->addWidget(m_pDecryptHexKeyCheck,8,3);
+
+ m_pOkButton = new QPushButton(__tr2qs("OK"),this);
+ g->addMultiCellWidget(m_pOkButton,9,9,0,3);
+ connect(m_pOkButton,SIGNAL(clicked()),this,SLOT(okClicked()));
+
+ g->setRowStretch(3,1);
+ g->setColStretch(2,1);
+
+ m_pLastItem = 0;
+ m_pSessionInfo = 0;
+
+ fillEngineList();
+
+ if(cur)
+ {
+ KviTalListBoxItem * it = (KviTalListBoxItem *)m_pListBox->findItem(cur->szEngineName.ptr());
+ if(it)
+ {
+ m_pEnableCheck->setChecked(true);
+ m_pListBox->setCurrentItem(it);
+ engineHighlighted(it);
+ m_pEnableEncrypt->setChecked(cur->bDoEncrypt);
+ m_pEnableDecrypt->setChecked(cur->bDoDecrypt);
+ } else enableWidgets(false);
+ } else {
+ enableWidgets(false);
+ }
+ registerSelf();
+ }
+
+ KviCryptController::~KviCryptController()
+ {
+ if(m_pSessionInfo)
+ {
+ // huh ?
+ g_pCryptEngineManager->deallocateEngine(m_pSessionInfo->pEngine);
+ delete m_pSessionInfo;
+ }
+ // Unload the unused ones...
+ g_pModuleManager->cleanupUnusedModules();
+ }
+
+ void KviCryptController::fillEngineList()
+ {
+ const KviPointerHashTable<QString,KviCryptEngineDescription> * a = g_pCryptEngineManager->engineDict();
+ if(a)
+ {
+ KviPointerHashTableIterator<QString,KviCryptEngineDescription> it(*a);
+ while(it.current())
+ {
+ KviStr modName = it.current()->providerHandle ? ((KviModule *)(it.current()->providerHandle))->name() : "";
+ (void)(new KviEngineListBoxItem(m_pListBox,it.current(),modName.ptr()));
+ ++it;
+ }
+ if(m_pListBox->count() != 0)return;
+ }
+ noEnginesAvailable();
+ }
+
+ void KviCryptController::engineHighlighted(KviTalListBoxItem *it)
+ {
+ if(it)
+ {
+ KviEngineListBoxItem * eit = (KviEngineListBoxItem *)it;
+ m_pAuthorLabel->setText(eit->m_szAuthor.ptr());
+ QString des = "<p>";
+ des += eit->m_szDescription.ptr();
+ des += "<br><br>";
+ des += __tr2qs("If you dont want to encrypt a particular text line then just start it with the CTRL+P prefix");
+ m_pDescriptionLabel->setText(des);
+ m_pEnableEncrypt->setEnabled(eit->m_iFlags & KVI_CRYPTENGINE_CAN_ENCRYPT);
+ m_pEncryptKeyLabel->setEnabled((eit->m_iFlags & KVI_CRYPTENGINE_CAN_ENCRYPT) &&
+ (eit->m_iFlags & KVI_CRYPTENGINE_WANT_ENCRYPT_KEY));
+ m_pEncryptKeyEdit->setEnabled((eit->m_iFlags & KVI_CRYPTENGINE_CAN_ENCRYPT) &&
+ (eit->m_iFlags & KVI_CRYPTENGINE_WANT_ENCRYPT_KEY));
+ m_pEnableEncrypt->setChecked(m_pEncryptKeyEdit->isEnabled());
+ m_pEnableDecrypt->setEnabled(eit->m_iFlags & KVI_CRYPTENGINE_CAN_DECRYPT);
+ m_pEncryptHexKeyCheck->setEnabled(m_pEncryptKeyEdit->isEnabled());
+ m_pEncryptHexKeyCheck->setChecked(false);
+ m_pDecryptKeyLabel->setEnabled((eit->m_iFlags & KVI_CRYPTENGINE_CAN_DECRYPT) &&
+ (eit->m_iFlags & KVI_CRYPTENGINE_WANT_DECRYPT_KEY));
+ m_pDecryptKeyEdit->setEnabled((eit->m_iFlags & KVI_CRYPTENGINE_CAN_DECRYPT) &&
+ (eit->m_iFlags & KVI_CRYPTENGINE_WANT_DECRYPT_KEY));
+ m_pEnableDecrypt->setChecked(m_pDecryptKeyEdit->isEnabled());
+ m_pDecryptHexKeyCheck->setEnabled(m_pDecryptKeyEdit->isEnabled());
+ m_pDecryptHexKeyCheck->setChecked(false);
+ m_pLastItem = eit;
+ enableWidgets(true);
+ } else m_pLastItem = 0;
+ }
+
+ void KviCryptController::enableCheckToggled(bool bChecked)
+ {
+ enableWidgets(bChecked);
+ }
+
+ void KviCryptController::enableWidgets(bool bEnabled)
+ {
+ m_pListBox->setEnabled(bEnabled);
+ m_pAuthorLabel->setEnabled(bEnabled && m_pLastItem);
+ m_pDescriptionLabel->setEnabled(bEnabled && m_pLastItem);
+ bool bCanDecrypt = m_pLastItem ? m_pLastItem->m_iFlags & KVI_CRYPTENGINE_CAN_DECRYPT : false;
+ bool bCanEncrypt = m_pLastItem ? m_pLastItem->m_iFlags & KVI_CRYPTENGINE_CAN_ENCRYPT : false;
+ m_pEnableEncrypt->setEnabled(bEnabled && bCanEncrypt);
+ m_pEnableDecrypt->setEnabled(bEnabled && bCanDecrypt);
+ bool bWantDecryptKey = m_pLastItem ? (bCanDecrypt && (m_pLastItem->m_iFlags & KVI_CRYPTENGINE_WANT_DECRYPT_KEY)) : false;
+ bool bWantEncryptKey = m_pLastItem ? (bCanEncrypt && (m_pLastItem->m_iFlags & KVI_CRYPTENGINE_WANT_ENCRYPT_KEY)) : false;
+ m_pEncryptKeyLabel->setEnabled(bEnabled && m_pEnableEncrypt->isChecked() && bWantEncryptKey);
+ m_pDecryptKeyLabel->setEnabled(bEnabled && m_pEnableDecrypt->isChecked() && bWantDecryptKey);
+ m_pEncryptKeyEdit->setEnabled(m_pEncryptKeyLabel->isEnabled());
+ m_pDecryptKeyEdit->setEnabled(m_pDecryptKeyLabel->isEnabled());
+ m_pEncryptHexKeyCheck->setEnabled(m_pEncryptKeyLabel->isEnabled());
+ m_pDecryptHexKeyCheck->setEnabled(m_pDecryptKeyLabel->isEnabled());
+ }
+
+ void KviCryptController::noEnginesAvailable()
+ {
+
+ m_pEnableCheck->setEnabled(false);
+ enableWidgets(false);
+ m_pDescriptionLabel->setText(__tr2qs("Sorry, no crypt engines available"));
+ m_pDescriptionLabel->setEnabled(true); // we want this text to be visible.
+ m_pOkButton->setEnabled(false);
+ }
+
+ void KviCryptController::okClicked()
+ {
+ if(m_pEnableCheck->isChecked())
+ {
+ if(m_pLastItem)
+ {
+ if(m_pEnableEncrypt->isChecked() || m_pEnableDecrypt->isChecked())
+ {
+ m_pSessionInfo = allocateCryptSessionInfo();
+ // Reregister the module in case that it has been unloaded
+ // while this dialog was open
+ if(m_pLastItem->m_szModuleName.hasData())(void)g_pModuleManager->getModule(m_pLastItem->m_szModuleName.ptr());
+ m_pSessionInfo->pEngine = g_pCryptEngineManager->allocateEngine(m_pLastItem->m_szName.ptr());
+ if(!m_pSessionInfo->pEngine)
+ {
+ m_pWindow->output(KVI_OUT_SYSTEMERROR,__tr2qs("Crypt: Can't create an engine instance: crypting disabled"));
+ delete m_pSessionInfo;
+ m_pSessionInfo = 0;
+ } else {
+ // initialize the engine
+ if(!initializeEngine(m_pSessionInfo->pEngine))
+ {
+ KviStr errStr = m_pSessionInfo->pEngine->lastError();
+ g_pCryptEngineManager->deallocateEngine(m_pSessionInfo->pEngine);
+ delete m_pSessionInfo;
+ m_pSessionInfo = 0;
+ m_pWindow->output(KVI_OUT_SYSTEMERROR,__tr2qs("Crypt: Can't initialize the engine :%s"),errStr.ptr());
+ } else {
+ // ok, engine ready and waiting...
+ m_pSessionInfo->szEngineName = m_pLastItem->m_szName;
+ m_pSessionInfo->bDoEncrypt = m_pEnableEncrypt->isChecked();
+ m_pSessionInfo->bDoDecrypt = m_pEnableDecrypt->isChecked();
+ }
+ }
+ } else m_pWindow->output(KVI_OUT_SYSTEMERROR,__tr2qs("Crypt: You have to enable encryption and/or decryption for the engine to work"));
+ }
+ }
+ emit done();
+ }
+
+ bool KviCryptController::initializeEngine(KviCryptEngine * eng)
+ {
+ KviStr m_szEncryptKey;
+ KviStr m_szDecryptKey;
+
+ char * encKey = 0;
+ int encKeyLen = 0;
+
+ if(m_pEnableEncrypt->isChecked())
+ {
+ m_szEncryptKey = m_pEncryptKeyEdit->text();
+ if(m_pEncryptHexKeyCheck->isChecked())
+ {
+ char * tmpKey;
+ encKeyLen = m_szEncryptKey.hexToBuffer(&tmpKey,false);
+ if(encKeyLen > 0)
+ {
+ encKey = (char *)kvi_malloc(encKeyLen);
+ kvi_memmove(encKey,tmpKey,encKeyLen);
+ KviStr::freeBuffer(tmpKey);
+ }
+ } else {
+ encKey = (char *)kvi_malloc(m_szEncryptKey.len());
+ kvi_memmove(encKey,m_szEncryptKey.ptr(),m_szEncryptKey.len());
+ encKeyLen = m_szEncryptKey.len();
+ }
+ }
+
+ char * decKey = 0;
+ int decKeyLen = 0;
+
+ if(m_pEnableDecrypt->isChecked())
+ {
+ m_szDecryptKey = m_pDecryptKeyEdit->text();
+ if(m_pDecryptHexKeyCheck->isChecked())
+ {
+ char * tmpKey;
+ decKeyLen = m_szDecryptKey.hexToBuffer(&tmpKey,false);
+ if(decKeyLen > 0)
+ {
+ decKey = (char *)kvi_malloc(decKeyLen);
+ kvi_memmove(decKey,tmpKey,decKeyLen);
+ KviStr::freeBuffer(tmpKey);
+ }
+ } else {
+ decKey = (char *)kvi_malloc(m_szDecryptKey.len());
+ kvi_memmove(decKey,m_szDecryptKey.ptr(),m_szDecryptKey.len());
+ decKeyLen = m_szDecryptKey.len();
+ }
+ }
+
+ bool bRet = eng->init(encKey,encKeyLen,decKey,decKeyLen);
+ if(encKey)kvi_free(encKey);
+ if(decKey)kvi_free(decKey);
+
+ return bRet;
+ }
+
+ KviCryptSessionInfo * KviCryptController::getNewSessionInfo()
+ {
+ KviCryptSessionInfo * inf = m_pSessionInfo;
+ m_pSessionInfo = 0;
+ return inf;
+ }
+
+ KviCryptSessionInfo * KviCryptController::allocateCryptSessionInfo()
+ {
+ // this is mainly for modules wanting to alloc this
+ return new KviCryptSessionInfo();
+ }
+
+ void KviCryptController::destroyCryptSessionInfo(KviCryptSessionInfo ** inf)
+ {
+ if(!(*inf))return;
+ (*inf)->pEngine->disconnect(); // disconnect every signal (this is mainly for destroyed())
+ g_pCryptEngineManager->deallocateEngine((*inf)->pEngine); // kill the engine
+ delete *inf;
+ *inf = 0;
+ }
+
+ #include "kvi_cryptcontroller.moc"
+
+#endif //COMPILE_CRYPT_SUPPORT
diff --git a/src/kvirc/ui/kvi_cryptcontroller.h b/src/kvirc/ui/kvi_cryptcontroller.h
new file mode 100644
index 00000000..1d6afcb6
--- /dev/null
+++ b/src/kvirc/ui/kvi_cryptcontroller.h
@@ -0,0 +1,116 @@
+#ifndef _KVI_CRYPTCONTROLLER_H_
+#define _KVI_CRYPTCONTROLLER_H_
+//=============================================================================
+//
+// File : kvi_cryptcontroller.h
+// Creation date : Fri Nov 03 2000 14:11:03 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+
+
+// Qt4 moc bails out on this ??????
+
+#if defined(COMPILE_CRYPT_SUPPORT) || defined(Q_MOC_RUN)
+ #include <qwidget.h>
+ #include "kvi_tal_listbox.h"
+ #include <qpushbutton.h>
+ #include <qcheckbox.h>
+ #include <qlabel.h>
+ #include <qlineedit.h>
+ #include "kvi_styled_controls.h"
+
+ #include "kvi_crypt.h"
+ #include "kvi_heapobject.h"
+ #include "kvi_toolwindows_container.h"
+
+ class KviWindow;
+
+ class KVIRC_API KviCryptSessionInfo : public KviHeapObject
+ {
+ public:
+ KviCryptEngine * pEngine;
+ KviStr szEngineName;
+ bool bDoEncrypt;
+ bool bDoDecrypt;
+ };
+
+ class KVIRC_API KviEngineListBoxItem : public KviTalListBoxText
+ {
+ friend class KviCryptController;
+ public:
+ KviEngineListBoxItem(KviTalListBox * lb,KviCryptEngineDescription * d,const char * modName);
+ ~KviEngineListBoxItem();
+ public:
+ KviStr m_szName;
+ KviStr m_szAuthor;
+ KviStr m_szDescription;
+ KviStr m_szModuleName;
+ int m_iFlags;
+ };
+
+
+ class KVIRC_API KviCryptController : public KviWindowToolWidget
+ {
+ Q_OBJECT
+ public:
+ KviCryptController(QWidget * parent,KviWindowToolPageButton* button,const char * name,KviWindow * wnd,KviCryptSessionInfo * cur);
+ ~KviCryptController();
+ protected:
+ KviWindow * m_pWindow;
+ KviTalListBox * m_pListBox;
+ QPushButton * m_pOkButton;
+ KviStyledCheckBox * m_pEnableCheck;
+ QLabel * m_pDescriptionLabel;
+ QLabel * m_pAuthorLabel;
+ KviStyledCheckBox * m_pEnableEncrypt;
+ QLabel * m_pEncryptKeyLabel;
+ QLineEdit * m_pEncryptKeyEdit;
+ KviStyledCheckBox * m_pEncryptHexKeyCheck;
+ KviStyledCheckBox * m_pEnableDecrypt;
+ QLabel * m_pDecryptKeyLabel;
+ QLineEdit * m_pDecryptKeyEdit;
+ KviStyledCheckBox * m_pDecryptHexKeyCheck;
+ KviEngineListBoxItem * m_pLastItem;
+ KviCryptSessionInfo * m_pSessionInfo;
+ private slots:
+ void enableCheckToggled(bool bChecked);
+ void engineHighlighted(KviTalListBoxItem *it);
+ void okClicked();
+ public:
+ KviCryptSessionInfo * getNewSessionInfo();
+ static KviCryptSessionInfo * allocateCryptSessionInfo();
+ static void destroyCryptSessionInfo(KviCryptSessionInfo ** inf);
+ private:
+ void fillEngineList();
+ void noEnginesAvailable();
+ void enableWidgets(bool bEnabled);
+ bool initializeEngine(KviCryptEngine * eng);
+ signals:
+ void done();
+ };
+
+
+#endif //COMPILE_CRYPT_SUPPORT
+
+
+#endif //!_KVI_CRYPTCONTROLLER_H_
diff --git a/src/kvirc/ui/kvi_ctcppagedialog.cpp b/src/kvirc/ui/kvi_ctcppagedialog.cpp
new file mode 100644
index 00000000..e6f392d6
--- /dev/null
+++ b/src/kvirc/ui/kvi_ctcppagedialog.cpp
@@ -0,0 +1,147 @@
+//
+// File : kvi_ctcppagedialog.cpp
+// Creation date : Tue May 21 2002 22:09:45 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#define __KVIRC__
+
+#include "kvi_ctcppagedialog.h"
+
+#include "kvi_locale.h"
+#include "kvi_app.h"
+
+#include "kvi_iconmanager.h"
+
+#include <qdatetime.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qpixmap.h>
+
+#ifdef COMPILE_USE_QT4
+ #include <qdesktopwidget.h>
+#endif
+
+// kvi_app.cpp
+extern KVIRC_API KviCtcpPageDialog * g_pCtcpPageDialog;
+
+KviCtcpPageDialog::KviCtcpPageDialog()
+: QWidget(0,"kvirc_ctcppage_dialog",
+#ifdef COMPILE_USE_QT4
+ Qt::WindowStaysOnTopHint | Qt::Tool | Qt::Dialog | Qt::Window)
+#else
+ WStyle_StaysOnTop | WStyle_Tool | WType_Dialog | WType_TopLevel)
+#endif
+{
+ QGridLayout * g = new QGridLayout(this,4,1,6,0);
+ m_pWidgetStack = new KviTalWidgetStack(this);
+ g->addWidget(m_pWidgetStack,0,0);
+ m_pTabBar = new QTabBar(this);
+ m_pTabBar->setShape(QTabBar::TriangularBelow);
+ connect(m_pTabBar,SIGNAL(selected(int)),this,SLOT(tabSelected(int)));
+ g->addWidget(m_pTabBar,1,0);
+
+ g->setRowStretch(0,1);
+
+ g->addRowSpacing(2,15);
+
+ m_pCloseButton = new QPushButton(__tr2qs("Close"),this);
+ connect(m_pCloseButton,SIGNAL(clicked()),this,SLOT(die()));
+ g->addWidget(m_pCloseButton,3,0);
+
+ setMinimumSize(300,200);
+ setMaximumSize(780,580);
+ setIcon(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CTCPREQUESTREPLIED)));
+
+ setCaption(__tr2qs("CTCP Page - KVIrc"));
+}
+
+KviCtcpPageDialog::~KviCtcpPageDialog()
+{
+ g_pCtcpPageDialog = 0;
+}
+
+void KviCtcpPageDialog::center()
+{
+ move((g_pApp->desktop()->width() - width()) >> 1,
+ (g_pApp->desktop()->height() - height()) >> 1);
+}
+
+void KviCtcpPageDialog::die()
+{
+ delete this;
+}
+
+void KviCtcpPageDialog::tabSelected(int id)
+{
+ m_pWidgetStack->raiseWidget(id);
+}
+
+void KviCtcpPageDialog::addPage(const QString &szNick,const QString &szUser,const QString &szHost,const QString &szMsg)
+{
+#ifdef COMPILE_USE_QT4
+ int id = m_pTabBar->addTab(szNick);
+#else
+ int id = m_pTabBar->addTab(new QTab(szNick));
+#endif
+ QLabel * l = new QLabel(this);
+ l->setFrameStyle(QFrame::Raised | QFrame::StyledPanel);
+ //l->setMaximumWidth(600);
+ QString date = QDateTime::currentDateTime().toString();
+
+ QString tmp = "<center>";
+ tmp += __tr2qs("You have been paged by");
+ tmp += "<br><b>";
+ tmp += szNick;
+ tmp += " [";
+ tmp += szUser;
+ tmp += "@";
+ tmp += szHost;
+ tmp += "]</b>:<br><br><b>";
+ tmp += szMsg;
+ tmp += "</b><br><br>[";
+ tmp += date;
+ tmp += "]</center>";
+
+ l->setText(tmp);
+ m_pWidgetStack->addWidget(l,id);
+ m_pWidgetStack->raiseWidget(l);
+ m_pTabBar->setCurrentTab(id);
+}
+
+void KviCtcpPageDialog::closeEvent(QCloseEvent *)
+{
+ delete this;
+}
+
+void KviCtcpPageDialog::popup()
+{
+ show();
+// raise();
+// setActiveWindow();
+ m_pCloseButton->setFocus();
+}
+
+void KviCtcpPageDialog::showEvent(QShowEvent *e)
+{
+ QWidget::showEvent(e);
+ center();
+}
+
+#include "kvi_ctcppagedialog.moc"
diff --git a/src/kvirc/ui/kvi_ctcppagedialog.h b/src/kvirc/ui/kvi_ctcppagedialog.h
new file mode 100644
index 00000000..ea615257
--- /dev/null
+++ b/src/kvirc/ui/kvi_ctcppagedialog.h
@@ -0,0 +1,56 @@
+#ifndef _KVI_CTCPPAGEDIALOG_H_
+#define _KVI_CTCPPAGEDIALOG_H_
+//
+// File : kvi_ctcppagedialog.h
+// Creation date : Tue May 21 2002 22:09:45 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+
+#include "kvi_string.h"
+
+#include "kvi_tal_widgetstack.h"
+#include <qtabbar.h>
+#include <qwidget.h>
+#include <qpushbutton.h>
+
+class KVIRC_API KviCtcpPageDialog : public QWidget
+{
+ Q_OBJECT
+public:
+ KviCtcpPageDialog();
+ ~KviCtcpPageDialog();
+protected:
+ KviTalWidgetStack * m_pWidgetStack;
+ QTabBar * m_pTabBar;
+ QPushButton * m_pCloseButton;
+public:
+ void popup();
+ void addPage(const QString &szNick,const QString &szUser,const QString &szHost,const QString &szMsg);
+protected slots:
+ void tabSelected(int id);
+ void die();
+protected:
+ void center();
+ virtual void showEvent(QShowEvent *e);
+ virtual void closeEvent(QCloseEvent *);
+};
+
+#endif //_KVI_CTCPPAGEDIALOG_H_
diff --git a/src/kvirc/ui/kvi_customtoolbar.cpp b/src/kvirc/ui/kvi_customtoolbar.cpp
new file mode 100644
index 00000000..7aa6f1cc
--- /dev/null
+++ b/src/kvirc/ui/kvi_customtoolbar.cpp
@@ -0,0 +1,670 @@
+//=============================================================================
+//
+// File : kvi_customtoolbar.cpp
+// Created on Sun 21 Nov 2004 05:28:57 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_customtoolbar.h"
+#include "kvi_frame.h"
+#include "kvi_locale.h"
+#include "kvi_app.h"
+#include "kvi_actionmanager.h"
+#include "kvi_customtoolbardescriptor.h"
+
+#include <qcursor.h>
+#include "kvi_tal_popupmenu.h"
+#include <qlayout.h>
+#include <qpixmap.h>
+#include <qcursor.h>
+#include <qtoolbutton.h>
+#include <qpainter.h>
+#include <qstyle.h>
+
+#ifdef COMPILE_USE_QT4
+ #include <qevent.h>
+ #include <q3dragobject.h>
+
+ #define QDragObject Q3DragObject
+ #define QTextDrag Q3TextDrag
+ #define QIconDrag Q3IconDrag
+
+ #include <qstyleoption.h>
+#else
+ #include <qobjectlist.h>
+ #include <qdragobject.h>
+#endif
+
+
+
+KviCustomToolBarSeparator::KviCustomToolBarSeparator(KviCustomToolBar *pParent,const char * name)
+: QWidget(pParent,name)
+{
+ m_pToolBar = pParent;
+ setBackgroundMode(pParent->backgroundMode());
+ setBackgroundOrigin(ParentOrigin);
+ setSizePolicy(QSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum));
+}
+
+QSize KviCustomToolBarSeparator::sizeHint() const
+{
+#ifdef COMPILE_USE_QT4
+ QStyleOption opt;
+ opt.initFrom(this);
+ int extent = style()->pixelMetric(QStyle::PM_ToolBarSeparatorExtent,&opt,this);
+#else
+ int extent = style().pixelMetric(QStyle::PM_DockWindowSeparatorExtent,this);
+#endif
+ if(m_pToolBar->orientation() == Qt::Horizontal)return QSize(extent,0);
+ else return QSize(0,extent);
+}
+
+void KviCustomToolBarSeparator::paintEvent(QPaintEvent *)
+{
+ QPainter p(this);
+#ifdef COMPILE_USE_QT4
+ QStyleOption opt;
+ opt.initFrom(this);
+ style()->drawPrimitive(QStyle::PE_Q3DockWindowSeparator,&opt,&p,this);
+#else
+ QStyle::SFlags flags = QStyle::Style_Default;
+ if(m_pToolBar->orientation() == Qt::Horizontal)flags |= QStyle::Style_Horizontal;
+ style().drawPrimitive(QStyle::PE_DockWindowSeparator,&p,rect(),colorGroup(),flags);
+#endif
+}
+
+
+KviCustomToolBar::KviCustomToolBar(KviCustomToolBarDescriptor * d,const QString &label,QT_TOOLBARDOCK_TYPE dock,bool bNewLine,const char * nam)
+: KviToolBar(label,dock,bNewLine,nam)
+{
+ m_pDescriptor = d;
+ m_pMovedChild = 0;
+ m_pDraggedChild = 0;
+ m_pFilteredChildren = 0;
+ setAcceptDrops(true);
+ connect(KviActionManager::instance(),SIGNAL(beginCustomizeToolBars()),this,SLOT(beginCustomize()));
+ connect(KviActionManager::instance(),SIGNAL(endCustomizeToolBars()),this,SLOT(endCustomize()));
+ setMinimumSize(20,20);
+ d->registerToolBar(this);
+ if(KviActionManager::customizingToolBars())
+ beginCustomize(); // because we will not get the signal
+}
+
+KviCustomToolBar::~KviCustomToolBar()
+{
+ if(KviActionManager::customizingToolBars())
+ syncDescriptor(); // because we will not get endCustomize()
+ m_pDescriptor->unregisterToolBar(this);
+ if(KviActionManager::customizingToolBars())
+ {
+ if(KviActionManager::currentToolBar() == this)
+ KviActionManager::instance()->setCurrentToolBar(0);
+ }
+ if(m_pFilteredChildren)delete m_pFilteredChildren;
+}
+
+void KviCustomToolBar::paintEvent(QPaintEvent * e)
+{
+ KviToolBar::paintEvent(e);
+ if(KviActionManager::customizingToolBars() && (KviActionManager::currentToolBar() == this))
+ {
+ QPainter p(this);
+ p.setPen(Qt::red);
+ p.drawRect(0,0,width(),height());
+ }
+}
+
+void KviCustomToolBar::filteredChildDestroyed()
+{
+ if(!m_pFilteredChildren)return;
+ const QObject * o = sender();
+ m_pFilteredChildren->remove((void *)o);
+}
+
+void KviCustomToolBar::filterChild(QObject * o)
+{
+ bool * b = new bool(((QWidget *)o)->isEnabled());
+ if(m_pFilteredChildren)
+ m_pFilteredChildren->insert(o,b);
+ if(!*b)((QWidget *)o)->setEnabled(true);
+ o->installEventFilter(this);
+ connect(o,SIGNAL(destroyed()),this,SLOT(filteredChildDestroyed()));
+}
+
+void KviCustomToolBar::unfilterChild(QObject * o)
+{
+ if(m_pFilteredChildren)
+ {
+ bool * b = m_pFilteredChildren->find(o);
+ if(b)
+ {
+ if(!*b)((QWidget *)o)->setEnabled(false);
+ o->removeEventFilter(this);
+ disconnect(o,SIGNAL(destroyed()),this,SLOT(filteredChildDestroyed()));
+ }
+ }
+}
+
+void KviCustomToolBar::beginCustomize()
+{
+ if(m_pFilteredChildren)delete m_pFilteredChildren;
+ m_pFilteredChildren = new KviPointerHashTable<void *,bool>;
+ m_pFilteredChildren->setAutoDelete(true);
+ // filter the events for all the children
+#ifdef COMPILE_USE_QT4
+ QList<QObject*> l = children();
+ for(QList<QObject*>::Iterator it = l.begin();it != l.end();++it)
+ {
+ if((*it)->isWidgetType())
+ filterChild(*it);
+ }
+#else
+ const QObjectList * l = children();
+ QObjectListIterator it(*l);
+ while(QObject * o = it.current())
+ {
+ if(o->isWidgetType())
+ filterChild(o);
+ ++it;
+ }
+#endif
+}
+
+void KviCustomToolBar::endCustomize()
+{
+ // stop filtering events
+#ifdef COMPILE_USE_QT4
+ QList<QObject*> l = children();
+ for(QList<QObject*>::Iterator it = l.begin();it != l.end();++it)
+ {
+ if((*it)->isWidgetType())
+ unfilterChild(*it);
+ }
+#else
+ const QObjectList * l = children();
+ QObjectListIterator it(*l);
+ while(QObject * o = it.current())
+ {
+ if(o->isWidgetType())
+ unfilterChild(o);
+ ++it;
+ }
+#endif
+ // FIXME: We SHOULD MAKE SURE that the children are re-enabled...
+ // this could be done by calling setEnabled(isEnabled()) on each action ?
+ if(m_pFilteredChildren)
+ {
+ delete m_pFilteredChildren;
+ m_pFilteredChildren = 0;
+ }
+ syncDescriptor();
+}
+
+void KviCustomToolBar::syncDescriptor()
+{
+ // store the item order in the descriptor
+ QBoxLayout * lay = boxLayout();
+ QLayoutIterator iter = lay->iterator();
+ QLayoutItem * i;
+ m_pDescriptor->actions()->clear();
+ while((i = iter.current()))
+ {
+ if(QWidget * w = i->widget())
+ m_pDescriptor->actions()->append(new QString(w->name()));
+ ++iter;
+ }
+}
+
+void KviCustomToolBar::childEvent(QChildEvent *e)
+{
+ if(KviActionManager::customizingToolBars())
+ {
+ // this is useful for droppped and dragged-out children
+ if(e->type() == QEvent::ChildInserted)
+ {
+ if(e->child()->isWidgetType())
+ filterChild(e->child());
+ goto done;
+ }
+
+ if(e->type() == QEvent::ChildRemoved)
+ {
+ if(e->child()->isWidgetType())
+ unfilterChild(e->child());
+ goto done;
+ }
+ }
+done:
+ KviToolBar::childEvent(e);
+}
+
+void KviCustomToolBar::dragEnterEvent(QDragEnterEvent *e)
+{
+ if(!KviActionManager::customizingToolBars())return;
+ KviActionManager::instance()->setCurrentToolBar(this);
+ QString text;
+ if(QTextDrag::decode(e,text))
+ {
+ if(!text.isEmpty())
+ {
+ KviAction * a = KviActionManager::instance()->getAction(text);
+ if(a)
+ {
+ e->accept(true);
+ int idx = dropIndexAt(mapFromGlobal(QCursor::pos()),0,0);
+ m_pDraggedChild = a->addToCustomToolBar(this);
+#ifdef COMPILE_USE_QT4
+ QWidget * pWidgetToMove = widgetAt(idx);
+ bool bDone = false;
+ QAction * a;
+ if(pWidgetToMove)
+ {
+ a = actionForWidget(pWidgetToMove);
+ if(a)
+ {
+ bDone = true;
+ a = insertWidget(a,m_pDraggedChild);
+ }
+ }
+ if(!bDone)
+ a = addWidget(m_pDraggedChild);
+ a->setVisible(true);
+#else
+ boxLayout()->remove(m_pDraggedChild); // in case it was already added
+ boxLayout()->insertWidget(idx,m_pDraggedChild);
+#ifdef COMPILE_KDE_SUPPORT
+ // bleah ://///
+ insertWidget(-1,m_pDraggedChild->sizeHint().width(),m_pDraggedChild,idx);
+#endif
+#endif
+ QEvent ev(QEvent::LayoutHint);
+ QApplication::sendEvent(this,&ev);
+ } else e->accept(false);
+ } else e->accept(false);
+ } else e->accept(false);
+}
+
+void KviCustomToolBar::dragMoveEvent(QDragMoveEvent *e)
+{
+ if(!m_pDraggedChild)return;
+ drag(m_pDraggedChild,mapFromGlobal(QCursor::pos()));
+}
+
+void KviCustomToolBar::dragLeaveEvent(QDragLeaveEvent *e)
+{
+ if(m_pDraggedChild)
+ {
+ if(m_pFilteredChildren)
+ m_pFilteredChildren->remove(m_pDraggedChild); // just to be sure
+ delete m_pDraggedChild;
+ m_pDraggedChild = 0;
+ }
+}
+
+void KviCustomToolBar::dropEvent(QDropEvent *e)
+{
+ if(!m_pDraggedChild)return;
+ m_pDraggedChild = 0;
+ e->accept();
+ // nuthin :)
+}
+
+int KviCustomToolBar::dropIndexAt(const QPoint &pnt,QWidget * exclude,int * excludeIdx)
+{
+ // find the widget at the current poisition
+ // treating exclude as if it was going to be removed
+ // find also the exclude index if needed
+#ifdef COMPILE_USE_QT4
+ QLayout * l = layout();
+#else
+ QBoxLayout * l = boxLayout();
+#endif
+ QLayoutItem * i = 0;
+ if(excludeIdx)*excludeIdx = -1;
+ int idx = 0;
+
+ if(!l)return 0;
+ QLayoutIterator it = l->iterator();
+
+ // find the children with minimum distance
+ int iMinDistIdx = -1;
+ QWidget * pMinDistW = 0;
+ unsigned int uMinDist = 0xffffffff;
+ int iExcludeIdx = -1;
+ QPoint pntExclude;
+ QWidget * w = 0;
+
+ while((i = it.current()))
+ {
+ if((w = i->widget()))
+ {
+ if(uMinDist != 0)
+ {
+ int iRight = w->x() + w->width();
+ int iBottom = w->y() + w->height();
+ if((pnt.x() >= w->x()) && (pnt.y() >= w->y()) && (pnt.x() <= iRight) && (pnt.y() <= iBottom))
+ {
+ // inside the widget
+ // distance 0
+ pMinDistW = w;
+ iMinDistIdx = idx;
+ uMinDist = 0;
+ } else {
+ // outside the widget
+ // compute the distance
+ unsigned int uXDist = (pnt.x() < w->x()) ? (w->x() - pnt.x()) : (pnt.x() > iRight ? (pnt.x() - iRight) : 0);
+ unsigned int uYDist = (pnt.y() < w->y()) ? (w->y() - pnt.y()) : (pnt.y() > iBottom ? (pnt.y() - iBottom) : 0);
+ if((uXDist < 8192) && (uYDist < 8192))
+ {
+ // it is in reasonable rect
+ unsigned int uDist = (uXDist * uXDist) + (uYDist * uYDist);
+ if(uDist < uMinDist)
+ {
+ // min distance for now
+ uMinDist = uDist;
+ pMinDistW = w;
+ iMinDistIdx = idx;
+ }
+ } // else the user has a really HUUUGE screen
+ }
+ } // else the minimum distance widget has already been found
+ if(w == exclude)
+ {
+ iExcludeIdx = idx;
+ pntExclude = w->pos();
+ }
+ }
+ idx++;
+ ++it;
+ }
+
+ if(!pMinDistW)
+ {
+ // ops.. not found at all (empty toolbar or really far from any button)
+ if(orientation() == Qt::Horizontal)
+ {
+ if(pnt.x() < (width() / 2))iMinDistIdx = 0; // insert at position 0
+ else iMinDistIdx = idx;
+ // else insert at the last position found
+ } else {
+ if(pnt.y() < (height() / 2))iMinDistIdx = 0; // insert at position 0
+ else iMinDistIdx = idx;
+ // else insert at the last position found
+ }
+ } else {
+ // got it, check for the exclude idx
+ if((iExcludeIdx == -1) || (iExcludeIdx != iMinDistIdx))
+ {
+ // would not put it over exclude idx
+ // check if we have to stay on right or left of the widget found
+ if(orientation() == Qt::Horizontal)
+ {
+ if(pnt.x() > (pMinDistW->x() + (pMinDistW->width() / 2)))
+ iMinDistIdx++; // need to put it on the right
+ } else {
+ if(pnt.y() > (pMinDistW->y() + (pMinDistW->height() / 2)))
+ iMinDistIdx++; // need to put it below
+ }
+ }
+
+ // ok , check again (we might have moved exactly over exclude idx now!)
+ if((iExcludeIdx != -1) && (iExcludeIdx != iMinDistIdx))
+ {
+ // got the exclude idx by the way and wouldn't put exactly over it
+ // check if exclude idx is "before" the current possible insert position
+ // if it is , then lower down the index by one
+ if(orientation() == Qt::Horizontal)
+ {
+ if(pnt.x() > pntExclude.x())
+ iMinDistIdx--; // removing exclude will move everything one step back
+ } else {
+ if(pnt.y() > pntExclude.y())
+ iMinDistIdx--; // removing exclude will move everything one step back
+ }
+ }
+ }
+
+ if(iMinDistIdx < 0)iMinDistIdx = 0;
+ if(excludeIdx)*excludeIdx = iExcludeIdx;
+
+ return iMinDistIdx;
+
+}
+
+#ifdef COMPILE_USE_QT4
+QWidget * KviCustomToolBar::widgetAt(int index)
+{
+ QLayout * l = layout();
+ if(!l)
+ return NULL;
+ QLayoutItem * it = l->itemAt(index);
+ if(!it)
+ return NULL;
+ return it->widget();
+}
+
+QAction * KviCustomToolBar::actionForWidget(QWidget * pWidget)
+{
+ return actionAt(pWidget->x() + 1,pWidget->y() + 1);
+}
+
+#endif
+
+void KviCustomToolBar::drag(QWidget * child,const QPoint &pnt)
+{
+ int me = -1;
+ int idx = dropIndexAt(pnt,child,&me);
+ debug("DROP INDEX IS %d, ME IS %d",idx,me);
+ if(idx == me)
+ return; // would move over itself
+#ifdef COMPILE_USE_QT4
+ QWidget * pWidgetToMove = widgetAt(idx > me ? idx-1 : idx);
+ debug("SEARCHING FOR WIDGET TO MOVE AT %d AND FOUND %x (ME=%x)",idx > me ? idx-1 : idx,pWidgetToMove,child);
+ if(pWidgetToMove == child)
+ return; // hmmm
+ bool bDone = false;
+ QAction * pMyOwnAction = actionForWidget(child);
+ if(!pMyOwnAction)
+ return;
+ QAction * a;
+ removeAction(pMyOwnAction);
+ if(pWidgetToMove)
+ {
+ a = actionForWidget(pWidgetToMove);
+ if(a)
+ {
+ debug("AND GOT ACTION FOR THAT WIDGET");
+
+ bDone = true;
+ a = insertWidget(a,child);
+ }
+ } else {
+ addAction(a);
+ }
+ if(!bDone)
+ a = addWidget(child);
+ a->setVisible(true);
+#else
+ boxLayout()->remove(child);
+ boxLayout()->insertWidget(idx,child);
+#ifdef COMPILE_KDE_SUPPORT
+ // bleah ://///
+ insertWidget(-1,child->width(),child,idx);
+#endif
+#endif
+ QEvent ev(QEvent::LayoutHint);
+ QApplication::sendEvent(this,&ev);
+}
+
+void KviCustomToolBar::mousePressEvent(QMouseEvent * e)
+{
+ if(KviActionManager::customizingToolBars())
+ KviActionManager::instance()->setCurrentToolBar(this);
+ KviToolBar::mousePressEvent(e);
+}
+
+bool KviCustomToolBar::eventFilter(QObject *o,QEvent *e)
+{
+ if(!KviActionManager::customizingToolBars())goto unhandled; // anything here is done when customizing only
+ if(e->type() == QEvent::Enter)
+ {
+ if(m_pMovedChild)return true; // kill it while moving other children
+ }
+ if(e->type() == QEvent::Leave)
+ {
+ if(m_pMovedChild)return true; // kill it while moving other children
+ }
+ if(e->type() == QEvent::MouseButtonPress)
+ {
+ KviActionManager::instance()->setCurrentToolBar(this);
+ QMouseEvent * ev = (QMouseEvent *)e;
+ if(ev->button() & Qt::LeftButton)
+ {
+ if(o->isWidgetType())
+ {
+ if(!(
+ o->inherits("KviTalPopupMenu") ||
+ o->inherits("QToolBarHandle") ||
+ o->inherits("QDockWindowHandle") ||
+ o->inherits("QDockWindowResizeHandle") ||
+ o->inherits("QToolBarExtensionWidget")
+ ))
+ {
+ m_pMovedChild = (QWidget *)o;
+ // allow resizing of children
+ // FIXME: do it only if the child is really resizable
+ if(m_pMovedChild->width() > 20) // might be an applet
+ {
+ if(ev->pos().x() > (m_pMovedChild->width() - 4))
+ {
+ m_pMovedChild = 0;
+ goto unhandled; // let the applet handle the event it
+ }
+ }
+ g_pApp->setOverrideCursor(Qt::sizeAllCursor);
+ return true;
+ }
+ }
+ }
+ goto unhandled;
+ }
+ if(e->type() == QEvent::MouseButtonRelease)
+ {
+ if(m_pMovedChild)
+ {
+ g_pApp->restoreOverrideCursor();
+ m_pMovedChild = 0;
+ return true;
+ }
+ goto unhandled;
+ }
+ if(e->type() == QEvent::MouseMove)
+ {
+ if(m_pMovedChild)
+ {
+ QMouseEvent * ev = (QMouseEvent *)e;
+
+ QPoint pnt = mapFromGlobal(m_pMovedChild->mapToGlobal(ev->pos()));
+ if((pnt.y() < 0) || (pnt.y() > height()) || (pnt.x() < 0) || (pnt.x() > width()))
+ {
+ // drag out!
+// FIXME: This is screwed up in Qt4.... :/
+#ifdef COMPILE_USE_QT4
+ QDrag * d = new QDrag(this);
+ QMimeData * m = new QMimeData();
+ m->setText(m_pMovedChild->name());
+ d->setMimeData(m);
+#else
+ QDragObject * d = new QTextDrag(m_pMovedChild->name(),this);
+#endif
+ KviAction * act = KviActionManager::instance()->getAction(m_pMovedChild->name());
+ if(act)
+ {
+ QPixmap * pixie = act->bigIcon();
+#ifdef COMPILE_USE_QT4
+ if(pixie)
+ {
+ d->setPixmap(*pixie);
+ d->setHotSpot(QPoint(3,3));
+ }
+#else
+ if(pixie)d->setPixmap(*pixie,QPoint(3,3));
+#endif
+ }
+ //d->setPixmap(QPixmap::grabWidget(m_pMovedChild),QPoint(m_pMovedChild->width() / 2,m_pMovedChild->height() / 2));
+ // throw it somewhere else for now
+ if(m_pFilteredChildren)
+ unfilterChild(m_pMovedChild);
+#ifdef COMPILE_USE_QT4
+ QAction * pActionForMovedChild = actionForWidget(m_pMovedChild);
+ if(pActionForMovedChild)
+ pActionForMovedChild->setVisible(false);
+ m_pMovedChild->hide();
+#else
+ m_pMovedChild->hide();
+ m_pMovedChild->reparent(g_pFrame,QPoint(-1000,-1000),false);
+#endif
+ QEvent ev(QEvent::LayoutHint);
+ QApplication::sendEvent(this,&ev);
+#ifdef COMPILE_USE_QT4
+ if(!d->exec(Qt::MoveAction) != Qt::MoveAction)
+#else
+ if(!d->dragMove())
+#endif
+ {
+ // the user has probably failed to remove the action from the toolbar
+ // flash the trashcan in the customize toolbars dialog
+ KviActionManager::instance()->emitRemoveActionsHintRequest();
+ // will filter it as ChildInserted
+#ifndef COMPILE_USE_QT4
+ m_pMovedChild->reparent(this,QPoint(0,0),false);
+#endif
+#ifdef COMPILE_USE_QT4
+ QAction * pActionForMovedChild = actionForWidget(m_pMovedChild);
+ if(pActionForMovedChild)
+ pActionForMovedChild->setVisible(false);
+#else
+ boxLayout()->insertWidget(0,m_pMovedChild);
+ m_pMovedChild->show();
+#ifdef COMPILE_KDE_SUPPORT
+ // bleah ://///
+ insertWidget(-1,m_pMovedChild->width(),m_pMovedChild,0);
+#endif
+#endif
+ QEvent ev(QEvent::LayoutHint);
+ QApplication::sendEvent(this,&ev);
+ } else {
+ QApplication::sendPostedEvents(m_pMovedChild,0);
+ m_pMovedChild->deleteLater();
+ m_pMovedChild = 0;
+ }
+ return true;
+ }
+
+ drag(m_pMovedChild,pnt);
+ return true;
+ }
+ goto unhandled;
+ }
+unhandled:
+ return KviToolBar::eventFilter(o,e);
+}
diff --git a/src/kvirc/ui/kvi_customtoolbar.h b/src/kvirc/ui/kvi_customtoolbar.h
new file mode 100644
index 00000000..64e9526e
--- /dev/null
+++ b/src/kvirc/ui/kvi_customtoolbar.h
@@ -0,0 +1,91 @@
+#ifndef _KVI_CUSTOMTOOLBAR_H_
+#define _KVI_CUSTOMTOOLBAR_H_
+//=============================================================================
+//
+// File : kvi_customtoolbar.h
+// Created on Sun 21 Nov 2004 05:28:57 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_toolbar.h"
+#include "kvi_pointerhashtable.h"
+
+#ifdef COMPILE_ON_WINDOWS
+ #include "kvi_customtoolbardescriptor.h"
+#else
+ class KviCustomToolBarDescriptor;
+#endif
+class KviCustomToolBar;
+
+class KviCustomToolBarSeparator : public QWidget
+{
+ Q_OBJECT
+public:
+ KviCustomToolBarSeparator(KviCustomToolBar *pParent,const char * name);
+ QSize sizeHint() const;
+protected:
+ KviCustomToolBar * m_pToolBar;
+protected:
+ void paintEvent(QPaintEvent *e);
+};
+
+class KVIRC_API KviCustomToolBar : public KviToolBar
+{
+ friend class KviCustomToolBarDescriptor;
+ Q_OBJECT
+protected:
+ KviCustomToolBar(KviCustomToolBarDescriptor * d,const QString &label,QT_TOOLBARDOCK_TYPE dock = QT_DOCK_TOP,bool bNewLine = false,const char * nam = 0);
+public:
+ ~KviCustomToolBar();
+protected:
+ KviCustomToolBarDescriptor * m_pDescriptor;
+ QWidget * m_pMovedChild;
+ QWidget * m_pDraggedChild;
+ KviPointerHashTable<void *,bool> * m_pFilteredChildren;
+public:
+ KviCustomToolBarDescriptor * descriptor(){ return m_pDescriptor; };
+protected:
+ virtual void mousePressEvent(QMouseEvent * e);
+ virtual void dragEnterEvent(QDragEnterEvent *e);
+ virtual void dragMoveEvent(QDragMoveEvent *e);
+ virtual void dragLeaveEvent(QDragLeaveEvent *e);
+ virtual void dropEvent(QDropEvent *e);
+ virtual void childEvent(QChildEvent *e);
+ virtual bool eventFilter(QObject *o,QEvent *e);
+ int dropIndexAt(const QPoint &pnt,QWidget * exclude,int * excludeIdx);
+#ifdef COMPILE_USE_QT4
+ QWidget * widgetAt(int index);
+ QAction * actionForWidget(QWidget * pWidget);
+#endif
+ void drag(QWidget * child,const QPoint &pnt);
+ void filterChild(QObject * o);
+ void unfilterChild(QObject * o);
+ virtual void paintEvent(QPaintEvent * e);
+ void syncDescriptor();
+protected slots:
+ void beginCustomize();
+ void endCustomize();
+ void filteredChildDestroyed();
+};
+
+
+
+#endif //!_KVI_CUSTOMTOOLBAR_H_
diff --git a/src/kvirc/ui/kvi_debugwindow.cpp b/src/kvirc/ui/kvi_debugwindow.cpp
new file mode 100644
index 00000000..81067c04
--- /dev/null
+++ b/src/kvirc/ui/kvi_debugwindow.cpp
@@ -0,0 +1,132 @@
+//=============================================================================
+//
+// File : kvi_debugwindow.cpp
+// Creation date : Sun Jul 18 2005 14:12:22 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+#include "kvi_debugwindow.h"
+#include "kvi_console.h"
+#include "kvi_iconmanager.h"
+#include "kvi_ircview.h"
+#include "kvi_input.h"
+#include "kvi_options.h"
+#include "kvi_locale.h"
+#include "kvi_config.h"
+
+#include "kvi_parameterlist.h"
+#include "kvi_frame.h"
+#include "kvi_valuelist.h"
+
+#include <qpixmap.h>
+#include <qsplitter.h>
+#include <qtoolbutton.h>
+
+KviDebugWindow * KviDebugWindow::m_pInstance = 0;
+
+
+KviDebugWindow::KviDebugWindow()
+: KviWindow(KVI_WINDOW_TYPE_DEBUG,g_pFrame,__tr2qs("Debug Messages"),0)
+{
+ m_pInstance = this;
+ m_pSplitter = new QSplitter(Qt::Horizontal,this,"main_splitter");
+ m_pIrcView = new KviIrcView(m_pSplitter,g_pFrame,this);
+ m_pInput = new KviInput(this,0);
+ updateCaption();
+}
+
+KviDebugWindow::~KviDebugWindow()
+{
+ m_pInstance = 0;
+}
+
+KviDebugWindow * KviDebugWindow::getInstance()
+{
+ if(m_pInstance)return m_pInstance;
+ m_pInstance = new KviDebugWindow();
+ g_pFrame->addWindow(m_pInstance,!KVI_OPTION_BOOL(KviOption_boolShowMinimizedDebugWindow));
+ if(KVI_OPTION_BOOL(KviOption_boolShowMinimizedDebugWindow))
+ m_pInstance->minimize();
+ return m_pInstance;
+}
+
+
+
+void KviDebugWindow::getBaseLogFileName(QString &buffer)
+{
+ buffer = "debug";
+}
+
+void KviDebugWindow::saveProperties(KviConfig *cfg)
+{
+ KviWindow::saveProperties(cfg);
+ cfg->writeEntry("Splitter",m_pSplitter->sizes());
+}
+
+void KviDebugWindow::loadProperties(KviConfig *cfg)
+{
+ int w = width();
+ KviWindow::loadProperties(cfg);
+ KviValueList<int> def;
+ def.append((w * 80) / 100);
+ def.append((w * 20) / 100);
+ m_pSplitter->setSizes(cfg->readIntListEntry("Splitter",def));
+}
+
+void KviDebugWindow::fillCaptionBuffers()
+{
+ static QString begin("<nobr><font color=\"");
+ static QString boldbegin("\"><b>");
+ static QString end("</b></font></nobr>");
+
+ m_szPlainTextCaption = windowName();
+
+ m_szHtmlActiveCaption = begin;
+ m_szHtmlActiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextActive).name();
+ m_szHtmlActiveCaption += boldbegin;
+ m_szHtmlActiveCaption += windowName();
+ m_szHtmlActiveCaption += end;
+
+ m_szHtmlInactiveCaption = begin;
+ m_szHtmlInactiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextInactive).name();
+ m_szHtmlInactiveCaption += boldbegin;
+ m_szHtmlInactiveCaption += windowName();
+ m_szHtmlInactiveCaption += end;
+}
+
+QPixmap * KviDebugWindow::myIconPtr()
+{
+ return g_pIconManager->getSmallIcon(KVI_SMALLICON_BUG);
+}
+
+void KviDebugWindow::resizeEvent(QResizeEvent *e)
+{
+ int hght = m_pInput->heightHint();
+ m_pSplitter->setGeometry(0,0,width(),height() - hght);
+ m_pInput->setGeometry(0,height() - hght,width(),hght);
+}
+
+QSize KviDebugWindow::sizeHint() const
+{
+ QSize ret(m_pSplitter->sizeHint().width(),m_pIrcView->sizeHint().height() + m_pInput->heightHint());
+ return ret;
+}
+
diff --git a/src/kvirc/ui/kvi_debugwindow.h b/src/kvirc/ui/kvi_debugwindow.h
new file mode 100644
index 00000000..b9646e24
--- /dev/null
+++ b/src/kvirc/ui/kvi_debugwindow.h
@@ -0,0 +1,54 @@
+#ifndef _KVI_DEBUGWINDOW_H_
+#define _KVI_DEBUGWINDOW_H_
+//=============================================================================
+//
+// File : kvi_debugwindow.h
+// Creation date : Sun Jul 18 2005 14:14:00 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_window.h"
+#include "kvi_string.h"
+
+class QSplitter;
+
+class KVIRC_API KviDebugWindow : public KviWindow
+{
+ Q_OBJECT
+public:
+ KviDebugWindow();
+ ~KviDebugWindow();
+protected:
+ static KviDebugWindow * m_pInstance;
+public:
+ static KviDebugWindow * instance(){ return m_pInstance; };
+ static KviDebugWindow * getInstance();
+protected:
+ virtual QPixmap * myIconPtr();
+ virtual void fillCaptionBuffers();
+ virtual void resizeEvent(QResizeEvent *e);
+ virtual void loadProperties(KviConfig * cfg);
+ virtual void saveProperties(KviConfig * cfg);
+ virtual void getBaseLogFileName(QString &buffer);
+ virtual QSize sizeHint() const;
+};
+
+#endif //_KVI_DEBUGWINDOW_H_
diff --git a/src/kvirc/ui/kvi_dynamictooltip.cpp b/src/kvirc/ui/kvi_dynamictooltip.cpp
new file mode 100644
index 00000000..3e6f22ce
--- /dev/null
+++ b/src/kvirc/ui/kvi_dynamictooltip.cpp
@@ -0,0 +1,61 @@
+//
+// File : kvi_dynamictooltip.cpp
+// Creation date : Wed Nov 01 2000 15:25:11 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+#define __KVIRC__
+#include "kvi_dynamictooltip.h"
+
+KviDynamicToolTipHelper::KviDynamicToolTipHelper(QWidget * parent,KviDynamicToolTip * parToolTip)
+: KviTalToolTip(parent)
+{
+ m_pParentToolTip = parToolTip;
+}
+
+KviDynamicToolTipHelper::~KviDynamicToolTipHelper()
+{
+}
+
+void KviDynamicToolTipHelper::maybeTip(const QPoint & pnt)
+{
+ m_pParentToolTip->maybeTip(pnt);
+}
+
+KviDynamicToolTip::KviDynamicToolTip(QWidget * parent,const char * name)
+: QObject(parent,name)
+{
+ m_pHelper = new KviDynamicToolTipHelper(parent,this);
+}
+
+KviDynamicToolTip::~KviDynamicToolTip()
+{
+ delete m_pHelper;
+}
+
+void KviDynamicToolTip::maybeTip(const QPoint &pnt)
+{
+ emit tipRequest(this,pnt);
+}
+
+void KviDynamicToolTip::tip(const QRect &rct,const QString & text)
+{
+ m_pHelper->tip(rct,text);
+}
+
+#include "kvi_dynamictooltip.moc"
diff --git a/src/kvirc/ui/kvi_dynamictooltip.h b/src/kvirc/ui/kvi_dynamictooltip.h
new file mode 100644
index 00000000..119c224c
--- /dev/null
+++ b/src/kvirc/ui/kvi_dynamictooltip.h
@@ -0,0 +1,61 @@
+#ifndef _KVI_DYNAMICTOOLTIP_H_
+#define _KVI_DYNAMICTOOLTIP_H_
+
+//
+// File : kvi_dynamictooltip.h
+// Creation date : Wed Nov 01 2000 15:23:12 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+#include "kvi_tal_tooltip.h"
+#include <qobject.h>
+
+class KviDynamicToolTip;
+
+class KVIRC_API KviDynamicToolTipHelper : public KviTalToolTip
+{
+ friend class KviDynamicToolTip;
+protected:
+ KviDynamicToolTipHelper(QWidget * parent,KviDynamicToolTip * parToolTip);
+ virtual ~KviDynamicToolTipHelper();
+protected:
+ KviDynamicToolTip * m_pParentToolTip;
+protected:
+ virtual void maybeTip(const QPoint &pnt);
+};
+
+class KVIRC_API KviDynamicToolTip : public QObject
+{
+ friend class KviDynamicToolTipHelper;
+ Q_OBJECT
+public:
+ KviDynamicToolTip(QWidget * parent,const char * name = 0);
+ virtual ~KviDynamicToolTip();
+protected:
+ KviDynamicToolTipHelper * m_pHelper;
+public:
+ void tip(const QRect &rct,const QString & text);
+protected:
+ void maybeTip(const QPoint &pnt);
+signals:
+ void tipRequest(KviDynamicToolTip *tip,const QPoint &pnt);
+};
+
+#endif //!_KVI_DYNAMICTOOLTIP_H_
diff --git a/src/kvirc/ui/kvi_filedialog.cpp b/src/kvirc/ui/kvi_filedialog.cpp
new file mode 100644
index 00000000..99f9c169
--- /dev/null
+++ b/src/kvirc/ui/kvi_filedialog.cpp
@@ -0,0 +1,229 @@
+//
+// File : kvi_filedialog.cpp
+// Creation date : Mon Nov 20 2000 12:20:42 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+#define __KVIRC__
+#include "kvi_filedialog.h"
+#include "kvi_mediatype.h"
+#include "kvi_iconmanager.h"
+#include "kvi_locale.h"
+#include "kvi_app.h"
+#include "kvi_fileutils.h"
+#include "kvi_frame.h"
+#include "kvi_qstring.h"
+
+#include <qdir.h>
+#include "kvi_tal_tooltip.h"
+#include <qmessagebox.h>
+
+extern KviMediaManager * g_pMediaManager;
+
+
+KviFileDialog::KviFileDialog(const QString &dirName, const QString &filter,
+ QWidget *parent, const char *name, bool modal)
+: KviTalFileDialog(dirName,filter,parent,name,modal)
+{
+
+ setIcon(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_FOLDER)));
+
+}
+
+KviFileDialog::~KviFileDialog()
+{
+}
+
+
+/*
+void KviFileDialog::goKvirc()
+{
+
+ KviStr tmp;
+ g_pApp->getLocalKvircDirectory(tmp,KviApp::None);
+ setDir(QDir(tmp.ptr()));
+
+}
+
+void KviFileDialog::goHome()
+{
+
+ setDir(QDir::home());
+
+}
+*/
+
+
+
+bool KviFileDialog::askForOpenFileName(QString &buffer,const QString &caption,const QString &initial,const QString &filter,bool showHidden, bool showNative,QWidget* parent)
+{
+#ifdef COMPILE_ON_WINDOWS
+ if(showNative)
+ {
+ buffer=QFileDialog::getOpenFileName(initial,filter,parent,"open_file_name_dialog",caption);
+ KviFileUtils::adjustFilePath(buffer);
+ return !buffer.isEmpty();
+ }
+#endif
+ KviFileDialog * d = new KviFileDialog(initial,filter,parent,"open_file_name_dialog",true);
+ d->setCaption(caption);
+ d->setMode(QFileDialog::ExistingFile);
+ //d->setShowHiddenFiles(showHidden);
+ if(d->exec() == QDialog::Accepted)
+ {
+ buffer = d->selectedFile();
+ KviFileUtils::adjustFilePath(buffer);
+ delete d;
+ return !buffer.isEmpty();
+ }
+ delete d;
+ return false;
+}
+
+
+bool KviFileDialog::askForSaveFileName(QString &buffer,const QString & caption,const QString &initial,const QString &filter,bool showHidden,bool bConfirmOverwrite,bool showNative,QWidget* parent)
+{
+ #ifdef COMPILE_ON_WINDOWS
+ if (showNative)
+ {
+ while (1)
+ {
+ buffer=QFileDialog::getSaveFileName(initial,filter,parent,"save_file_name_dialog",caption);
+ KviFileUtils::adjustFilePath(buffer);
+ //return !buffer.isEmpty();
+ if(buffer.isEmpty()) return false;
+ if(!bConfirmOverwrite) return true;
+ // Check for the file existence
+ if(!KviFileUtils::fileExists(buffer)) return true;
+ QString tmp;
+ KviQString::sprintf(tmp,__tr2qs("The file %s already exists.<br>Do you wish to overwrite it?"),buffer.utf8().data());
+ switch(QMessageBox::information(parent,__tr2qs("File Exists - KVIrc"),tmp,QMessageBox::Yes,QMessageBox::No | QMessageBox::Default,QMessageBox::Cancel | QMessageBox::Escape))
+ {
+ case QMessageBox::Cancel: return false; break;
+ case QMessageBox::Yes: return true; break;
+ }
+
+ }
+
+
+ }
+ #endif
+
+
+ KviFileDialog * d = new KviFileDialog(initial,filter,parent,"save_file_name_dialog",true);
+ d->setCaption(caption);
+ d->setMode(QFileDialog::AnyFile);
+ //d->setShowHiddenFiles(showHidden);
+
+ while(d->exec() == QDialog::Accepted)
+ {
+ buffer = d->selectedFile();
+ KviFileUtils::adjustFilePath(buffer);
+
+ if(!buffer.isEmpty())
+ {
+ if(!bConfirmOverwrite)
+ {
+ delete d;
+ return true;
+ }
+ // Check for the file existence
+ if(KviFileUtils::fileExists(buffer))
+ {
+ QString tmp;
+ KviQString::sprintf(tmp,__tr2qs("The file %s already exists.<br>Do you wish to overwrite it?"),buffer.utf8().data());
+ switch(QMessageBox::information(d,__tr2qs("File Exists - KVIrc"),tmp,QMessageBox::Yes,QMessageBox::No | QMessageBox::Default,QMessageBox::Cancel | QMessageBox::Escape))
+ {
+ case QMessageBox::Cancel: delete d; return false; break;
+ case QMessageBox::Yes: delete d; return true; break;
+ }
+ } else {
+ delete d;
+ return true; // ok...file not exists
+ }
+ } else {
+ delete d;
+ return false; // empty buffer
+ }
+ }
+
+ delete d;
+ return false;
+
+}
+
+bool KviFileDialog::askForDirectoryName(QString &buffer,const QString & caption,const QString & initial,const char * filter,bool showHidden,bool showNative,QWidget* parent)
+{
+#ifdef COMPILE_ON_WINDOWS
+ if(showNative)
+ {
+ buffer = QFileDialog::getExistingDirectory(initial,parent,"open_file_name_dialog",caption);
+ return !buffer.isEmpty();
+ }
+#else
+ #ifdef COMPILE_KDE_SUPPORT
+ // the KDE based dir selection dialog is now quite nice
+ buffer = KFileDialog::getExistingDirectory(initial,parent,caption);
+ return !buffer.isEmpty();
+ #endif
+#endif
+
+ KviFileDialog * d = new KviFileDialog(initial,
+ filter,parent,"directory_name_dialog",true);
+ d->setCaption(caption);
+ d->setMode(QFileDialog::Directory);
+ //d->setShowHiddenFiles(showHidden);
+ if(d->exec() == QDialog::Accepted)
+ {
+ buffer = d->selectedFile();
+ KviFileUtils::adjustFilePath(buffer);
+ delete d;
+ return !buffer.isEmpty();
+ }
+ delete d;
+
+ return false;
+}
+
+
+bool KviFileDialog::askForOpenFileNames(QStringList &buffer,const QString & caption,const QString & initial,const char * filter,bool showHidden,bool showNative,QWidget* parent)
+{
+ #ifdef COMPILE_ON_WINDOWS
+ if (showNative)
+ {
+ buffer=QFileDialog::getOpenFileNames(filter,initial,parent,"open_file_name_dialog",caption);
+ return (buffer.count()>0);
+ }
+
+ #endif
+ KviFileDialog * d = new KviFileDialog(initial,filter ? QString(filter) : QString::null,parent,"open_file_names_dialog",true);
+ d->setCaption(caption);
+ d->setMode(QFileDialog::ExistingFiles);
+ //d->setShowHiddenFiles(showHidden);
+ if(d->exec() == QDialog::Accepted)
+ {
+ buffer = d->selectedFiles();
+ delete d;
+ return (buffer.count() > 0);
+ }
+ delete d;
+ return false;
+}
+
+
+#include "kvi_filedialog.moc"
diff --git a/src/kvirc/ui/kvi_filedialog.h b/src/kvirc/ui/kvi_filedialog.h
new file mode 100644
index 00000000..985898d6
--- /dev/null
+++ b/src/kvirc/ui/kvi_filedialog.h
@@ -0,0 +1,55 @@
+#ifndef _KVI_FILEDIALOG_H_
+#define _KVI_FILEDIALOG_H_
+
+//
+// File : kvi_filedialog.h
+// Creation date : Mon Nov 20 2000 03:52:12 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#ifdef Unsorted
+ #undef Unsorted
+#endif
+#include "kvi_settings.h"
+#include "kvi_string.h"
+
+
+#include "kvi_tal_filedialog.h"
+
+#include <qstringlist.h>
+
+
+class KVIRC_API KviFileDialog : public KviTalFileDialog
+{
+ Q_OBJECT
+public:
+ KviFileDialog(const QString &dirName, const QString &filter=QString::null,
+ QWidget *parent=0, const char *name=0, bool modal=false);
+ ~KviFileDialog();
+public:
+ static bool askForOpenFileName(QString &buffer,const QString & caption,const QString &initial = QString::null,const QString &filter = QString::null,bool showHidden = false,bool showNative = true,QWidget* parent=0);
+ static bool askForSaveFileName(QString &buffer,const QString & caption,const QString &initial = QString::null,const QString &filter = QString::null,bool showHidden = false,bool bConfirmOverwrite = false,bool showNative = true,QWidget* parent=0);
+
+ static bool askForDirectoryName(QString &buffer,const QString & caption,const QString & initial,const char * filter = 0,bool showHidden = false,bool showNative=true,QWidget* parent=0);
+ static bool askForOpenFileNames(QStringList &buffer,const QString & caption,const QString & initial,const char * filter = 0,bool showHidden = false,bool showNative=true,QWidget* parent=0);
+
+};
+
+
+#endif //_KVI_FILEDIALOG_H_
diff --git a/src/kvirc/ui/kvi_frame.cpp b/src/kvirc/ui/kvi_frame.cpp
new file mode 100644
index 00000000..e7b7c0b8
--- /dev/null
+++ b/src/kvirc/ui/kvi_frame.cpp
@@ -0,0 +1,1450 @@
+//=============================================================================
+//
+// File : kvi_frame.cpp
+// Creation date : Sun Jun 18 2000 17:59:02 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+#define _KVI_FRAME_CPP_
+
+#include "kvi_debug.h"
+#include "kvi_app.h"
+#include "kvi_settings.h"
+#include "kvi_frame.h"
+#include "kvi_options.h"
+#include "kvi_menubar.h"
+#include "kvi_mdimanager.h"
+#include "kvi_mdichild.h"
+#include "kvi_iconmanager.h"
+#include "kvi_window.h"
+#include "kvi_taskbar.h"
+#include "kvi_console.h"
+#include "kvi_config.h"
+#include "kvi_internalcmd.h"
+#include "kvi_console.h"
+#include "kvi_debug.h"
+#include "kvi_irctoolbar.h"
+#include "kvi_confignames.h"
+#include "kvi_parameterlist.h"
+#include "kvi_module.h"
+#include "kvi_mextoolbar.h"
+#include "kvi_locale.h"
+#include "kvi_irccontext.h"
+#include "kvi_statusbar.h"
+#include "kvi_customtoolbar.h"
+#include "kvi_customtoolbarmanager.h"
+#include "kvi_customtoolbardescriptor.h"
+#include "kvi_actionmanager.h"
+#include "kvi_defaults.h"
+#include "kvi_ircview.h"
+#include "kvi_tal_popupmenu.h"
+
+#include "kvi_kvs_script.h"
+#include "kvi_kvs_eventtriggers.h"
+
+#include <qsplitter.h>
+#include <qvariant.h>
+#include <qlineedit.h>
+#include <qmessagebox.h>
+#include <qcheckbox.h>
+
+#include <qtimer.h>
+#include <qlayout.h>
+
+#if QT_VERSION >= 300
+ #include <qfile.h>
+ #include <qtextstream.h>
+ #ifdef COMPILE_USE_QT4
+ #include <q3dockarea.h>
+ #define QDockArea Q3DockArea
+ #else
+ #include <qdockarea.h>
+ #endif
+#endif
+
+
+#ifdef COMPILE_USE_QT4
+ #include <qdesktopwidget.h>
+ #include <qevent.h>
+ #include <QShortcut>
+#else
+ #include <qaccel.h>
+#endif
+
+#include <time.h>
+
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ #include <qpixmap.h>
+ // kvi_app.h
+ extern QPixmap * g_pShadedParentGlobalDesktopBackground;
+ extern QPixmap * g_pShadedChildGlobalDesktopBackground;
+// FIXME: #warning "When a toolbar is moved , MdiManager is resized but does not update the MdiChild backgrounds"
+#endif
+
+// Declared and managed by KviApp (kvi_app.cpp)
+extern KviConfig * g_pWinPropertiesConfig;
+KVIRC_API KviFrame * g_pFrame = 0; // the one and only frame object
+
+KviFrame::KviFrame()
+: KviTalMainWindow(0,"kvirc_frame")
+{
+ g_pFrame = this;
+
+ setIcon(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_KVIRC)));
+
+ m_pWinList = new KviPointerList<KviWindow>;
+ m_pWinList->setAutoDelete(false);
+
+ m_pModuleExtensionToolBarList = new KviPointerList<KviMexToolBar>;
+ m_pModuleExtensionToolBarList->setAutoDelete(false);
+
+ m_pActiveContext = 0;
+
+ m_pDockExtension = 0;
+
+ m_pSplitter = new QSplitter(Qt::Horizontal,this,"main_splitter");
+// m_pSplitter->setFrameShape(QFrame::NoFrame);
+
+ setCentralWidget(m_pSplitter);
+
+ setUsesBigPixmaps(KVI_OPTION_BOOL(KviOption_boolUseBigIcons));
+
+ m_pMdi = new KviMdiManager(m_pSplitter,this,"mdi_manager");
+ connect(m_pMdi,SIGNAL(enteredSdiMode()),this,SLOT(enteredSdiMode()));
+ connect(m_pMdi,SIGNAL(leftSdiMode()),this,SLOT(leftSdiMode()));
+
+ // This theoretically had to exists before KviMdiManager (that uses enterSdiMode)
+ m_pMenuBar = new KviMenuBar(this,"main_menu_bar");
+#ifdef COMPILE_USE_QT4
+ setMenuWidget(m_pMenuBar);
+#endif
+
+ if(KVI_OPTION_BOOL(KviOption_boolStatusBarVisible))
+ {
+ m_pStatusBar = new KviStatusBar(this);
+#ifdef COMPILE_USE_QT4
+ setStatusBar(m_pStatusBar);
+#endif
+ // torque: moved out of status bar constructor
+ // because module init functions exectued in load()
+ // couldn't access the status bar via g_pFrame->mainStatusBar()
+ // (assignment of m_pStatusBar happened after load() and
+ // the init function)
+ m_pStatusBar->load();
+
+ } else
+ m_pStatusBar = 0;
+
+ m_pTaskBar = 0;
+
+ createTaskBar();
+
+ if((KVI_OPTION_RECT(KviOption_rectFrameGeometry).width() < 100) || (KVI_OPTION_RECT(KviOption_rectFrameGeometry).height() < 100))
+ {
+ // Try to find some reasonable defaults
+ KVI_OPTION_RECT(KviOption_rectFrameGeometry) = QRect(10,10,g_pApp->desktop()->width() - 200,g_pApp->desktop()->height() - 150);
+ }
+
+ resize(KVI_OPTION_RECT(KviOption_rectFrameGeometry).width(),
+ KVI_OPTION_RECT(KviOption_rectFrameGeometry).height());
+ move(KVI_OPTION_RECT(KviOption_rectFrameGeometry).x(),
+ KVI_OPTION_RECT(KviOption_rectFrameGeometry).y());
+
+ applyOptions();
+
+
+ m_pAccel = new KviAccel(this);
+
+ installAccelerators(this);
+
+ layout()->setResizeMode(QLayout::FreeResize);
+}
+
+KviFrame::~KviFrame()
+{
+ KVI_OPTION_RECT(KviOption_rectFrameGeometry) = QRect(pos().x(),pos().y(),
+ size().width(),size().height());
+
+ KVI_OPTION_BOOL(KviOption_boolUseBigIcons) = usesBigPixmaps();
+ KVI_OPTION_BOOL(KviOption_boolMdiManagerInSdiMode) = m_pMdi->isInSDIMode();
+ KVI_OPTION_BOOL(KviOption_boolStatusBarVisible) = m_pStatusBar ? true : false;
+
+ KviCustomToolBarManager::instance()->storeVisibilityState();
+
+ saveToolBarPositions();
+ saveModuleExtensionToolBars();
+
+ // Call the frame destructor callback AFTER saving the toolbar positions
+ // This is because the destructor callback kills alls the KVS objects
+ // and thus the eventual user toolbar objects too and their position
+ // wouldn't be saved if they are shown at startup.
+
+ g_pApp->frameDestructorCallback();
+
+ // Now start killing stuff
+
+ // Explicitly kill all the module extension toolbars: qt has NOT to delete them: we must call their "die" method
+ while(KviMexToolBar * t = m_pModuleExtensionToolBarList->first())t->die();
+ delete m_pModuleExtensionToolBarList;
+
+ KVI_OPTION_BOOL(KviOption_boolShowDockExtension) = m_pDockExtension;
+
+ if(m_pDockExtension)
+ {
+ m_pDockExtension->die();
+ m_pDockExtension = 0;
+ }
+
+ // the really last thing to do : close all the windows
+ while(m_pWinList->first())
+ closeWindow(m_pWinList->first());
+ delete m_pWinList;
+
+ delete m_pAccel;
+ g_pFrame = 0;
+}
+
+int KviFrame::registerAccelerator(const QString &szKeySequence,QObject * recv,const char * slot)
+{
+ int id = m_pAccel->insertItem(szKeySequence);
+ m_pAccel->connectItem(id,recv,slot);
+ return id;
+}
+
+void KviFrame::unregisterAccelerator(int id)
+{
+ m_pAccel->removeItem(id);
+}
+
+void KviFrame::registerModuleExtensionToolBar(KviMexToolBar * t)
+{
+ m_pModuleExtensionToolBarList->append(t);
+}
+
+void KviFrame::unregisterModuleExtensionToolBar(KviMexToolBar * t)
+{
+ m_pModuleExtensionToolBarList->removeRef(t);
+}
+
+void KviFrame::restoreModuleExtensionToolBars()
+{
+ for(QStringList::Iterator it = KVI_OPTION_STRINGLIST(KviOption_stringlistModuleExtensionToolbars).begin();it != KVI_OPTION_STRINGLIST(KviOption_stringlistModuleExtensionToolbars).end();++it)
+ {
+ QString szEntry = *it;
+ int idx = szEntry.find(':');
+ if(idx != -1)
+ {
+ QString szMod = szEntry.left(idx);
+ szEntry.remove(0,idx + 1);
+ g_pModuleExtensionManager->allocateExtension("toolbar",KviStr(szEntry),firstConsole(),0,0,szMod);
+ }
+ }
+}
+
+void KviFrame::saveModuleExtensionToolBars()
+{
+ KVI_OPTION_STRINGLIST(KviOption_stringlistModuleExtensionToolbars).clear();
+
+ for(KviMexToolBar * t = m_pModuleExtensionToolBarList->first();t;t = m_pModuleExtensionToolBarList->next())
+ {
+ QString s = t->descriptor()->module()->name();
+ s += ":";
+ s += t->descriptor()->name().ptr();
+
+ //debug("FOUND TOOLBAR %s",t->descriptor()->name().ptr());
+
+ KVI_OPTION_STRINGLIST(KviOption_stringlistModuleExtensionToolbars).append(s);
+ }
+}
+
+KviMexToolBar * KviFrame::moduleExtensionToolBar(int extensionId)
+{
+ for(KviMexToolBar * t = m_pModuleExtensionToolBarList->first();t;t = m_pModuleExtensionToolBarList->next())
+ {
+ if(extensionId == t->descriptor()->id())return t;
+ }
+ return 0;
+}
+
+/*
+ @doc: keyboard
+ @type:
+ generic
+ @title:
+ Keyboard shortcuts
+ @keyterms:
+ Keyboard shortcuts
+ @short:
+ The list of the common keyboard shortcuts
+ @body:
+ [b]Ctrl+LeftArrow[/b]: Selection left to the previous word[br]
+ [b]Ctrl+RightArrow[/b]: Selection right to the next word[br]
+ [b]Ctrl+Shift+LeftArrow[/b]: Previous word[br]
+ [b]Ctrl+Shift+RightArrow[/b]: Next word[br]
+ [b]Alt+LeftArrow[/b]: Previous window[br]
+ [b]Alt+RightArrow[/b]: Next window[br]
+ [b]Alt+Shift+LeftArrow[/b]: Previous window in the same IRC context[/b]
+ [b]Alt+Shift+RightArrow[/b]: Next window in the same IRC context[/b]
+ [b]Ctrl+UpArrow[/b]: Maximize current window[br]
+ [b]Ctrl+DownArrow[/b] or [b]ESC[/b]: Minimize current window[br]
+ [b]Ctrl+&lt;digit&gt;[/b], [b]F1-F12[/b], [b]Shift+(F1-F12)[/b]: Script accelerators (see [event:onaccelkeypressed]OnAccelKeyPressed[/event])[br]
+ [b]Shift+&lt;F1-F12&gt;[/b] window switch[br]
+ [b]Tab in the first word of input[/b]: Completes nicknames in the current channel or query[br]
+ [b]Tab after a leading /[/b]: Completes commands[br]
+ [b]Tab after a / in the middle of input[/b]: Completes directories[br]
+ [b]Tab after a $[/b]: Completes function names[br]
+ [b]Shift+Tab after the first word of input[/b]: completes masks in the current channel or query[br]
+ [b]Ctrl+B[/b]: Inserts the 'bold' mIRC text control character[br]
+ [b]Ctrl+K[/b]: Inserts the 'color' mIRC text control character[br]
+ [b]Ctrl+R[/b]: Inserts the 'reverse' mIRC text control character[br]
+ [b]Ctrl+U[/b]: Inserts the 'underline' mIRC text control character[br]
+ [b]Ctrl+O[/b]: Inserts the 'reset' mIRC text control character[br]
+ [b]Ctrl+P[/b]: Inserts the 'non-crypt' (plain text) KVIrc control character used to disable encryption of the current text line[br]
+ [b]Ctrl+C[/b]: Copies the selected text to clipboard[br]
+ [b]Ctrl+X[/b]: Cuts the selected text[br]
+ [b]Ctrl+V[/b]: Pastes the clipboard contents (same as middle mouse click)[br]
+ [b]Ctrl+I[/b]: Inserts the 'icon' control code and pops up the icon list box
+ [b]CursorUp[/b]: Moves backward in the command history[br]
+ [b]CursorDown[/b]: Moves forward in the command history[br]
+ [b]Ctrl+PageUp[/b]: Opens the history popup[br]
+ [b]CursorRight[/b]: Moves the cursor to the right[br]
+ [b]CursorLeft[/b]: Moves the cursor to the left :)[br]
+ [b]Shift+CursorLeft[/b]: Moves the selection to the left[br]
+ [b]Shift+RightCursor[/b]: Moves the selection to the right[br]
+ [b]PageUp[/b]: Scrolls the output window up one page[br]
+ [b]PageDown[/b]: Scrolls the output window down one page[b]
+ [b]Shift+PageUp[/b]: Scrolls the output window up one line[br]
+ [b]Shift+PageDown[/b]: Scrolls the output window down one line[b]
+ [b]Alt+lt;numeric_sequence&gt;[/b]: Inserts the character by ASCII/Unicode code[br]
+ [b]Ctrl+Backspace[/b]: Shows or hides the multiline editor[br]
+ [b]Ctrl+F4[/b]: Closes the current window[br]
+ <example>
+ Alt+32: Inserts ASCII/Unicode character 32: ' ' (a space)
+ Alt+00032: Same as above :)
+ Alt+13: Inserts the Carriage Return (CR) control character
+ Alt+77: Inserts ASCII/Unicode character 77: 'M'
+ Alt+23566: Inserts Unicode character 23566 (an ideogram)
+ </example>
+*/
+
+KviAccel * KviFrame::installAccelerators(QWidget * wnd)
+{
+ QWidget * pParent = wnd ? (QWidget *)wnd : (QWidget *)this;
+#ifdef COMPILE_USE_QT4
+ new QShortcut(QKeySequence(Qt::Key_Left + Qt::ALT),pParent,SLOT(switchToPrevWindow()));
+ new QShortcut(QKeySequence(Qt::Key_Right + Qt::ALT),pParent,SLOT(switchToNextWindow()));
+ new QShortcut(QKeySequence(Qt::Key_Up + Qt::CTRL),pParent,SLOT(maximizeWindow()));
+ new QShortcut(QKeySequence(Qt::Key_Down + Qt::CTRL),pParent,SLOT(minimizeWindow()));
+ new QShortcut(QKeySequence(Qt::Key_Escape +Qt::CTRL),pParent,SLOT(minimizeWindow()));
+ new QShortcut(QKeySequence(Qt::Key_Left + Qt::ALT + Qt::SHIFT),pParent,SLOT(switchToPrevWindowInContext()));
+ new QShortcut(QKeySequence(Qt::Key_Right + Qt::ALT + Qt::SHIFT),pParent,SLOT(switchToNextWindowInContext()));
+#endif
+ KviAccel *ac = new KviAccel(pParent);
+
+ static int accel_table[] = {
+ Qt::Key_Left + Qt::ALT , // prev window
+ Qt::Key_Right + Qt::ALT , // next window
+ Qt::Key_Up + Qt::CTRL , // maximize window
+ Qt::Key_Down + Qt::CTRL , // minimize window
+ Qt::Key_Escape +Qt::CTRL, // minimize window
+ Qt::Key_Left + Qt::ALT + Qt::SHIFT , // prev window in context
+ Qt::Key_Right + Qt::ALT + Qt::SHIFT, // next window in context
+ Qt::Key_F4 + Qt::CTRL , // close current window
+ Qt::Key_1 + Qt::CTRL , // script accels...
+ Qt::Key_2 + Qt::CTRL ,
+ Qt::Key_3 + Qt::CTRL ,
+ Qt::Key_4 + Qt::CTRL ,
+ Qt::Key_5 + Qt::CTRL ,
+ Qt::Key_6 + Qt::CTRL ,
+ Qt::Key_7 + Qt::CTRL ,
+ Qt::Key_8 + Qt::CTRL ,
+ Qt::Key_9 + Qt::CTRL ,
+ Qt::Key_0 + Qt::CTRL ,
+ Qt::Key_F1 , // reserved for context sensitive help
+ Qt::Key_F2 ,
+ Qt::Key_F3 ,
+ Qt::Key_F4 ,
+ Qt::Key_F5 ,
+ Qt::Key_F6 ,
+ Qt::Key_F7 ,
+ Qt::Key_F8 ,
+ Qt::Key_F9 ,
+ Qt::Key_F10 ,
+ Qt::Key_F11 ,
+ Qt::Key_F12 ,
+/* Qt::Key_F1 + Qt::SHIFT , // window select...
+ Qt::Key_F2 + Qt::SHIFT ,
+ Qt::Key_F3 + Qt::SHIFT ,
+ Qt::Key_F4 + Qt::SHIFT ,
+ Qt::Key_F5 + Qt::SHIFT ,
+ Qt::Key_F6 + Qt::SHIFT ,
+ Qt::Key_F7 + Qt::SHIFT ,
+ Qt::Key_F8 + Qt::SHIFT ,
+ Qt::Key_F9 + Qt::SHIFT ,
+ Qt::Key_F10 + Qt::SHIFT ,
+ Qt::Key_F11 + Qt::SHIFT ,
+ Qt::Key_F12 + Qt::SHIFT ,*/
+ 0
+ };
+
+ int i=0;
+ int keys;
+ while((keys = accel_table[i]))
+ {
+ ac->insertItem(keys);
+ i++;
+ }
+
+ connect(ac,SIGNAL(activated(int)),this,SLOT(accelActivated(int)));
+ return ac;
+}
+
+void KviFrame::accelActivated(int id)
+{
+ KviAccel * acc = (KviAccel *)sender();
+
+ int keys = (int)(acc->key(id));
+ KviTaskBarItem *item = 0;
+ debug("accel");
+ switch(keys)
+ {
+ case (Qt::Key_Left+Qt::ALT): switchToPrevWindow(); break;
+ case (Qt::Key_Right+Qt::ALT): switchToNextWindow(); break;
+ case (Qt::Key_Up+Qt::CTRL): maximizeWindow(); break;
+ case (Qt::Key_Escape+Qt::CTRL):
+ case (Qt::Key_Down+Qt::CTRL): minimizeWindow(); break;
+ case (Qt::Key_Left+Qt::ALT+Qt::SHIFT): switchToPrevWindowInContext(); break;
+ case (Qt::Key_Right+Qt::ALT+Qt::SHIFT): switchToNextWindowInContext(); break;
+ case (Qt::Key_F4+Qt::CTRL): if(g_pActiveWindow)g_pActiveWindow->close(); break;
+ case (Qt::Key_F1): g_pApp->contextSensitiveHelp(); break;
+/* case(Qt::Key_F1 + SHIFT):
+ item = m_pTaskBar->item(0);
+ if(item) setActiveWindow(item->window());
+ break;
+ case(Qt::Key_F2 + SHIFT):
+ item = m_pTaskBar->item(1);
+ if(item) setActiveWindow(item->window());
+ break;
+ case(Qt::Key_F3 + SHIFT):
+ item = m_pTaskBar->item(2);
+ if(item) setActiveWindow(item->window());
+ break;
+ case(Qt::Key_F4 + SHIFT):
+ item = m_pTaskBar->item(3);
+ if(item) setActiveWindow(item->window());
+ break;
+ case(Qt::Key_F5 + SHIFT):
+ item = m_pTaskBar->item(4);
+ if(item) setActiveWindow(item->window());
+ break;
+ case(Qt::Key_F6 + SHIFT):
+ item = m_pTaskBar->item(5);
+ if(item) setActiveWindow(item->window());
+ break;
+ case(Qt::Key_F7 + SHIFT):
+ item = m_pTaskBar->item(6);
+ if(item) setActiveWindow(item->window());
+ break;
+ case(Qt::Key_F8 + SHIFT):
+ item = m_pTaskBar->item(7);
+ if(item) setActiveWindow(item->window());
+ break;
+ case(Qt::Key_F9 + SHIFT):
+ item = m_pTaskBar->item(8);
+ if(item) setActiveWindow(item->window());
+ break;
+ case(Qt::Key_F10 + SHIFT):
+ item = m_pTaskBar->item(9);
+ if(item) setActiveWindow(item->window());
+ break;
+ case(Qt::Key_F11 + SHIFT):
+ item = m_pTaskBar->item(10);
+ if(item) setActiveWindow(item->window());
+ break;
+ case(Qt::Key_F12 + SHIFT):
+ item = m_pTaskBar->item(11);
+ if(item) setActiveWindow(item->window());
+ break;*/
+ default:
+ {
+ KVS_TRIGGER_EVENT_1(KviEvent_OnAccelKeyPressed,g_pActiveWindow,(QString)(acc->key(id)));
+ }
+ break;
+ };
+}
+
+void KviFrame::executeInternalCommand(int index)
+{
+ KviKvsScript::run(kvi_getInternalCommandBuffer(index),firstConsole());
+}
+
+
+void KviFrame::saveWindowProperties(KviWindow * wnd,const char * szSection)
+{
+ g_pWinPropertiesConfig->setGroup(szSection);
+ g_pWinPropertiesConfig->writeEntry("EntryTimestamp",(unsigned int)time(0));
+
+ // Allow max 80 window properties to be floating around
+ while(g_pWinPropertiesConfig->groupsCount() > 80)
+ {
+ // Kill the oldest group
+ KviConfigIterator it(*(g_pWinPropertiesConfig->dict()));
+ KviStr minKey;
+ unsigned int minVal = time(0);
+ while(it.current() && minVal)
+ {
+ QString * pVal = it.current()->find("EntryTimestamp");
+ if(pVal)
+ {
+ bool bOk;
+ unsigned int uVal = pVal->toUInt(&bOk);
+ if(bOk)
+ {
+ if(uVal < minVal)
+ {
+ minVal = uVal;
+ minKey = it.currentKey();
+ }
+ } else {
+ minVal = 0;
+ minKey = it.currentKey();
+ }
+ } else {
+ minVal = 0;
+ minKey = it.currentKey();
+ }
+ ++it;
+ }
+
+ if(minKey.hasData())g_pWinPropertiesConfig->clearGroup(minKey.ptr());
+ else debug("Oops...no minimum key found!");
+ }
+
+ // The following line should NOT be needed...but just to be sure...
+ g_pWinPropertiesConfig->setGroup(szSection);
+
+ g_pWinPropertiesConfig->writeEntry("IsDocked",wnd->mdiParent());
+
+// KviWindow * top = g_pActiveWindow;
+// if(!top)top = wnd;
+// g_pWinPropertiesConfig->writeEntry("IsMaximized",top->isMaximized());
+
+ g_pWinPropertiesConfig->writeEntry("WinRect",wnd->externalGeometry());
+
+ wnd->saveProperties(g_pWinPropertiesConfig);
+}
+
+void KviFrame::closeWindow(KviWindow *wnd)
+{
+ // notify the destruction
+ wnd->triggerDestructionEvents();
+
+ // save it's properties
+ if(KVI_OPTION_BOOL(KviOption_boolWindowsRememberProperties)) // && (wnd->type() == KVI_WINDOW_TYPE_CHANNEL))
+ {
+ QString group;
+ wnd->getConfigGroupName(group);
+ // not uses default settings : store it always
+ saveWindowProperties(wnd,group);
+ }
+
+ // forget it...
+ m_pWinList->removeRef(wnd);
+
+ // hide it
+ if(wnd->mdiParent())wnd->mdiParent()->hide();
+ else wnd->hide();
+
+ if(wnd == g_pActiveWindow)
+ {
+ // we need another active window before destroying it
+ KviMdiChild * pMdiChild = wnd->mdiParent();
+ if(pMdiChild)
+ {
+ pMdiChild = m_pMdi->highestChildExcluding(pMdiChild);
+ } else {
+ // the best candidate for the new active window
+ // is the top mdiManager's child
+ pMdiChild = m_pMdi->topChild();
+ }
+ KviWindow * pCandidate;
+ if(pMdiChild)
+ {
+ pCandidate = (KviWindow *)(pMdiChild->client());
+ } else {
+ pCandidate = m_pWinList->first();
+ if(pCandidate == wnd)pCandidate = 0;
+ }
+
+ if(pCandidate)
+ childWindowActivated(pCandidate);
+ // else { m_pActiveWindow = 0; m_pActiveContext = 0; };
+ }
+
+ if(wnd == g_pActiveWindow) // ops... :/ ... this happens only at shutdown
+ {
+ g_pActiveWindow = 0;
+ m_pActiveContext = 0;
+ }
+
+ // and shut it down...
+ // KviWindow will call childWindowDestroyed() here
+ if(wnd->mdiParent())m_pMdi->destroyChild(wnd->mdiParent(),true);
+ else delete wnd;
+}
+
+
+void KviFrame::addWindow(KviWindow *wnd,bool bShow)
+{
+ m_pWinList->append(wnd);
+ wnd->createTaskBarItem(); // create the window taskbar item AFTER it has been constructed
+
+ QString group;
+ wnd->getConfigGroupName(group);
+
+ bool bGroupSettings = false;
+
+ if(g_pWinPropertiesConfig->hasGroup(group))
+ {
+ g_pWinPropertiesConfig->setGroup(group);
+ } else {
+ bGroupSettings = true;
+ if(g_pWinPropertiesConfig->hasGroup(wnd->typeString()))
+ {
+ g_pWinPropertiesConfig->setGroup(wnd->typeString());
+ } else {
+ g_pWinPropertiesConfig->setGroup("no_settings_group");
+ wnd->loadProperties(g_pWinPropertiesConfig); // load it anyway (will set defaults if windows don't remember properties)
+ goto default_docking; // no settings stored
+ }
+ }
+
+ {
+ wnd->loadProperties(g_pWinPropertiesConfig); // load it anyway (will set defaults if windows don't remember properties)
+
+ if(KVI_OPTION_BOOL(KviOption_boolWindowsRememberProperties))
+ {
+ bool bDocked = g_pWinPropertiesConfig->readBoolEntry("IsDocked",true);
+ //bool bMaximized = g_pWinPropertiesConfig->readBoolEntry("IsMaximized",false);
+ bool bMaximized;
+
+ if(KVI_OPTION_BOOL(KviOption_boolMdiManagerInSdiMode))
+ {
+ bMaximized = true;
+ //KVI_OPTION_BOOL(KviOption_boolMdiManagerInSdiMode) = false;
+ } else bMaximized = false;
+
+ QRect rect = g_pWinPropertiesConfig->readRectEntry("WinRect",QRect(10,10,500,380));
+
+ if(bDocked)
+ {
+ // when group settings are used , we always cascade the windows
+ // this means that windows that have no specialized config group name
+ // are always cascaded : this is true for consoles , queries (and other windows) but not channels (and some other windows)
+ KviMdiChild * lpC = dockWindow(wnd,false,bGroupSettings,&rect);
+ lpC->setRestoredGeometry(rect);
+ wnd->triggerCreationEvents();
+ if(bShow)
+ {
+ m_pMdi->showAndActivate(lpC);
+ if(bMaximized)wnd->maximize();
+ // Handle the special case of this top level widget not being the active one.
+ // In this situation the child will not get the focusInEvent
+ // and thus will not call out childWindowActivated() method
+ if(!isActiveWindow())childWindowActivated(wnd);
+ }
+ } else {
+ wnd->setGeometry(rect);
+ wnd->triggerCreationEvents();
+ if(bShow)
+ {
+ wnd->show();
+ if(bMaximized)wnd->maximize();
+ }
+ wnd->youAreUndocked();
+ if(bShow)
+ {
+ wnd->raise();
+ wnd->setFocus();
+ }
+ }
+ goto docking_done;
+ }
+ }
+
+default_docking:
+ {
+ KviMdiChild * lpC = dockWindow(wnd,false); //cascade it
+ wnd->triggerCreationEvents();
+ if(bShow)
+ {
+ m_pMdi->showAndActivate(lpC);
+ if(KVI_OPTION_BOOL(KviOption_boolMdiManagerInSdiMode)) wnd->maximize();
+ // Handle the special case of this top level widget not being the active one.
+ // In this situation the child will not get the focusInEvent
+ // and thus will not call out childWindowActivated() method
+ if(!isActiveWindow())childWindowActivated(wnd);
+ }
+ }
+docking_done:
+ // we like to have an active window.. but don't trigger the events until it is really shown
+ if(!g_pActiveWindow)
+ {
+ g_pActiveWindow = wnd;
+ m_pActiveContext = wnd->context();
+ }
+}
+
+KviMdiChild * KviFrame::dockWindow(KviWindow *wnd,bool bShow,bool bCascade,QRect *setGeom)
+{
+ if(wnd->mdiParent())return wnd->mdiParent();
+ KviMdiChild * lpC = new KviMdiChild(m_pMdi,"");
+ lpC->setClient(wnd);
+ wnd->youAreDocked();
+ m_pMdi->manageChild(lpC,bCascade,setGeom);
+ if(bShow)m_pMdi->showAndActivate(lpC);
+ return lpC;
+}
+
+void KviFrame::undockWindow(KviWindow *wnd)
+{
+ if(!(wnd->mdiParent()))return;
+ KviMdiChild * lpC = wnd->mdiParent();
+ lpC->unsetClient();
+ m_pMdi->destroyChild(lpC,false);
+ wnd->youAreUndocked();
+ wnd->raise();
+ wnd->setFocus();
+}
+
+
+void KviFrame::newConsole()
+{
+ createNewConsole();
+}
+
+KviConsole * KviFrame::createNewConsole(bool bFirstInFrame)
+{
+ // the first console must be created BEFORE the toolbars visible
+ // at startup otherwise we cannot execute script code
+ // which is necessary for the actions that are going to be added
+ // to the toolbars
+ KviConsole * c = new KviConsole(this,bFirstInFrame ? KVI_CONSOLE_FLAG_FIRSTINFRAME : 0);
+ addWindow(c);
+
+ if(bFirstInFrame)
+ {
+ restoreModuleExtensionToolBars();
+ KviCustomToolBarManager::instance()->createToolBarsVisibleAtStartup();
+ KviActionManager::instance()->delayedRegisterAccelerators();
+ restoreToolBarPositions();
+ }
+
+ return c;
+}
+
+unsigned int KviFrame::consoleCount()
+{
+ unsigned int count = 0;
+ for(KviWindow * wnd = m_pWinList->first();wnd;wnd = m_pWinList->next())
+ {
+ if(wnd->type() == KVI_WINDOW_TYPE_CONSOLE)count++;
+ }
+ return count;
+}
+
+KviConsole * KviFrame::firstConsole()
+{
+ for(KviWindow * wnd = m_pWinList->first();wnd;wnd = m_pWinList->next())
+ {
+ if(wnd->type() == KVI_WINDOW_TYPE_CONSOLE)return (KviConsole *)wnd;
+ }
+ __range_valid(false);
+ return 0; //should newer be here!.. but sometimes we are ?
+}
+
+KviConsole * KviFrame::firstNotConnectedConsole()
+{
+ for(KviWindow * wnd = m_pWinList->first();wnd;wnd = m_pWinList->next())
+ {
+ if(wnd->type() == KVI_WINDOW_TYPE_CONSOLE)
+ {
+ if(!((KviConsole *)wnd)->connectionInProgress())
+ return (KviConsole *)wnd;
+ }
+ }
+ return 0;
+}
+
+void KviFrame::childWindowCloseRequest(KviWindow *wnd)
+{
+ closeWindow(wnd);
+}
+
+void KviFrame::unhighlightWindowsOfContext(KviIrcContext * c)
+{
+ for(KviWindow *w = m_pWinList->first();w;w = m_pWinList->next())
+ if(w->context() == c)w->unhighlight();
+}
+
+void KviFrame::setActiveWindow(KviWindow *wnd)
+{
+ // ASSERT(m_pWinList->findRef(wnd))
+ if(wnd->isMinimized())wnd->restore();
+ if(wnd->mdiParent())wnd->setFocus();
+ else wnd->delayedAutoRaise();
+}
+
+KviIrcConnection * KviFrame::activeConnection()
+{
+ return m_pActiveContext ? m_pActiveContext->connection() : 0;
+}
+
+void KviFrame::childWindowSelectionStateChange(KviWindow * pWnd,bool bGotSelectionNow)
+{
+ if(pWnd != g_pActiveWindow)return;
+ emit activeWindowSelectionStateChanged(bGotSelectionNow);
+
+}
+
+void KviFrame::childContextStateChange(KviIrcContext * c)
+{
+ if(c != m_pActiveContext)return;
+ emit activeContextStateChanged();
+}
+
+void KviFrame::childConnectionLagChange(KviIrcConnection * c)
+{
+ KviIrcContext * ctx = c->context();
+ if(ctx != m_pActiveContext)return;
+ emit activeConnectionLagChanged();
+}
+
+void KviFrame::childConnectionServerInfoChange(KviIrcConnection * c)
+{
+ KviIrcContext * ctx = c->context();
+ if(ctx != m_pActiveContext)return;
+ emit activeConnectionServerInfoChanged();
+}
+
+void KviFrame::childConnectionNickNameChange(KviIrcConnection * c)
+{
+ KviIrcContext * ctx = c->context();
+ if(ctx != m_pActiveContext)return;
+ emit activeConnectionNickNameChanged();
+}
+
+void KviFrame::childConnectionAwayStateChange(KviIrcConnection * c)
+{
+ KviIrcContext * ctx = c->context();
+ if(ctx != m_pActiveContext)return;
+ emit activeConnectionAwayStateChanged();
+}
+
+void KviFrame::childConnectionUserModeChange(KviIrcConnection * c)
+{
+ KviIrcContext * ctx = c->context();
+ if(ctx != m_pActiveContext)return;
+ emit activeConnectionUserModeChanged();
+}
+
+
+void KviFrame::childWindowActivated(KviWindow *wnd)
+{
+ // ASSERT(m_pWinList->findRef(wnd))
+ if(g_pActiveWindow == wnd)return;
+ if(g_pActiveWindow)g_pActiveWindow->lostUserFocus();
+ // YES: it's HERE!
+ g_pActiveWindow = wnd;
+
+ bool bActiveContextChanged = (m_pActiveContext != wnd->context());
+ m_pActiveContext = wnd->context();
+
+ if(wnd->isMaximized() && wnd->mdiParent())updateCaption();
+ m_pTaskBar->setActiveItem(wnd->taskBarItem());
+
+ //wnd->gainedActiveWindowStatus(); // <-- atm unused
+
+ if(g_pActiveWindow->view())
+ g_pActiveWindow->view()->clearUnreaded();
+
+ emit activeWindowChanged();
+ if(bActiveContextChanged)emit activeContextChanged();
+
+ KVS_TRIGGER_EVENT_0(KviEvent_OnWindowActivated,wnd);
+}
+
+void KviFrame::windowActivationChange(bool bOldActive)
+{
+ // if we have just been activated by the WM
+ // then update the active window task bar item
+ // It will then reset its highlight state
+ // and hopefully make the dock widget work correctly
+ // in this case.
+ // This will also trigger the OnWindowActivated event :)
+ if(isActiveWindow())
+ {
+ if(!bOldActive)
+ {
+ if(g_pActiveWindow)
+ {
+ KviWindow * pTmp = g_pActiveWindow;
+ g_pActiveWindow = 0; // really ugly hack!
+ childWindowActivated(pTmp);
+ }
+ }
+ } else {
+ if(g_pActiveWindow)g_pActiveWindow->lostUserFocus();
+ }
+}
+
+void KviFrame::enteredSdiMode()
+{
+ updateCaption();
+}
+
+void KviFrame::leftSdiMode()
+{
+ updateCaption();
+}
+
+#define KVI_DEFAULT_FRAME_CAPTION "KVIrc " KVI_VERSION " " KVI_RELEASE_NAME
+
+void KviFrame::updateCaption()
+{
+ if(g_pActiveWindow)
+ {
+ if(g_pActiveWindow->isMaximized() && g_pActiveWindow->mdiParent())
+ {
+ QString tmp = g_pActiveWindow->plainTextCaption();
+ tmp += QChar(' ');
+ tmp += KVI_DEFAULT_FRAME_CAPTION;
+ setCaption(tmp);
+ return;
+ }
+ }
+ setCaption(KVI_DEFAULT_FRAME_CAPTION);
+}
+
+
+void KviFrame::closeEvent(QCloseEvent *e)
+{
+
+ if(KVI_OPTION_BOOL(KviOption_boolCloseInTray))
+ {
+ e->ignore();
+
+ if(!dockExtension())
+ {
+ executeInternalCommand(KVI_INTERNALCOMMAND_DOCKWIDGET_SHOW);
+ }
+ if(dockExtension())
+ {
+
+ dockExtension()->setPrevWindowState(windowState());
+ QTimer::singleShot( 0, this, SLOT(hide()) );
+ }
+ return;
+ }
+
+ if(KVI_OPTION_BOOL(KviOption_boolConfirmCloseWhenThereAreConnections))
+ {
+ // check for running connections
+
+ bool bGotRunningConnection = false;
+ for(KviWindow * w = m_pWinList->first();w;w = m_pWinList->next())
+ {
+ if(w->type() == KVI_WINDOW_TYPE_CONSOLE)
+ {
+ if(((KviConsole *)w)->connectionInProgress())
+ {
+ bGotRunningConnection = true;
+ break;
+ }
+ }
+ }
+
+ if(bGotRunningConnection)
+ {
+ QString txt = "<p>";
+ txt += __tr2qs("There are active connections, are you sure you wish to ");
+ txt += __tr2qs("quit KVIrc?");
+ txt += "</p>";
+
+ switch(QMessageBox::warning(this,__tr2qs("Confirmation - KVIrc"),txt,__tr2qs("&Yes"),__tr2qs("&Always"),__tr2qs("&No"),2,2))
+ {
+ case 0:
+ // ok to close
+ break;
+ case 1:
+ // ok to close but don't ask again
+ KVI_OPTION_BOOL(KviOption_boolConfirmCloseWhenThereAreConnections) = false;
+ break;
+ case 2:
+ e->ignore();
+ return;
+ break;
+ }
+ }
+ }
+
+ e->accept();
+
+ if(g_pApp)
+ g_pApp->destroyFrame();
+}
+
+void KviFrame::resizeEvent(QResizeEvent *e)
+{
+ KVI_OPTION_RECT(KviOption_rectFrameGeometry) = QRect(pos().x(),pos().y(),
+ size().width(),size().height());
+ KviTalMainWindow::resizeEvent(e);
+}
+
+void KviFrame::updatePseudoTransparency()
+{
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ if(g_pShadedParentGlobalDesktopBackground)m_pMdi->viewport()->update();
+
+ if(g_pShadedChildGlobalDesktopBackground)
+ {
+ for(KviWindow * wnd = m_pWinList->first();wnd;wnd = m_pWinList->next())wnd->updateBackgrounds();
+ m_pTaskBar->updatePseudoTransparency();
+ }
+#endif
+}
+
+void KviFrame::moveEvent(QMoveEvent *e)
+{
+ KVI_OPTION_RECT(KviOption_rectFrameGeometry) = QRect(pos().x(),pos().y(),
+ size().width(),size().height());
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ updatePseudoTransparency();
+#endif
+ KviTalMainWindow::moveEvent(e);
+}
+
+void KviFrame::applyOptions()
+{
+ m_pMdi->update();
+ for(KviWindow * wnd = m_pWinList->first();wnd;wnd = m_pWinList->next())wnd->applyOptions();
+ updateCaption();
+
+ m_pTaskBar->applyOptions();
+}
+
+void KviFrame::toggleStatusBar()
+{
+ if(m_pStatusBar)
+ {
+ delete m_pStatusBar;
+ m_pStatusBar = 0;
+ } else {
+ //if(statusBar())delete statusBar(); // kill any existing status bar (QT BUG)
+
+ m_pStatusBar = new KviStatusBar(this);
+ m_pStatusBar->load();
+#ifdef COMPILE_USE_QT4
+ setStatusBar(m_pStatusBar);
+#endif
+ m_pStatusBar->show();
+#ifndef COMPILE_USE_QT4
+ setUpLayout();
+#endif //!COMPILE_USE_QT4
+ }
+}
+
+void KviFrame::fillToolBarsPopup(KviTalPopupMenu * p)
+{
+ p->clear();
+
+ disconnect(p,SIGNAL(activated(int)),this,SLOT(toolbarsPopupSelected(int))); // just to be sure
+ connect(p,SIGNAL(activated(int)),this,SLOT(toolbarsPopupSelected(int)));
+
+ int id;
+ int cnt = 0;
+
+ KviModuleExtensionDescriptorList * l = g_pModuleExtensionManager->getExtensionList("toolbar");
+ if(l)
+ {
+ for(KviModuleExtensionDescriptor * d = l->first();d;d = l->next())
+ {
+ QString label = __tr2qs("Show %1").arg(d->visibleName());
+ if(d->icon())id = p->insertItem(*(d->icon()),label);
+ else id = p->insertItem(label);
+ p->setItemChecked(id,moduleExtensionToolBar(d->id()));
+ p->setItemParameter(id,d->id());
+ cnt++;
+ }
+ }
+
+ // FIXME: Should this display "Hide %1" when the toolbar is already visible ?
+ KviPointerHashTableIterator<QString,KviCustomToolBarDescriptor> it2(*(KviCustomToolBarManager::instance()->descriptors()));
+ if(it2.current())
+ {
+ if(cnt > 0)p->insertSeparator();
+ while(KviCustomToolBarDescriptor * d = it2.current())
+ {
+ QString label = __tr2qs("Show %1").arg(d->label());
+ QString ico = d->iconId();
+ // use the icon only if there is no check
+ if(d->toolBar())
+ {
+ id = p->insertItem(label);
+ p->setItemChecked(id,true);
+ } else {
+ if(!ico.isEmpty())
+ {
+ QPixmap * pix = g_pIconManager->getImage(d->iconId());
+ if(pix)
+ {
+ id = p->insertItem(*pix,label);
+ } else {
+ id = p->insertItem(label);
+ }
+ } else {
+ id = p->insertItem(label);
+ }
+ }
+ p->setItemParameter(id,d->internalId());
+ ++it2;
+ cnt++;
+ }
+ }
+
+ if(cnt > 0)p->insertSeparator();
+ p->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TOOLBAR)),__tr2qs("Customize..."),this,SLOT(customizeToolBars()));
+}
+
+void KviFrame::customizeToolBars()
+{
+ KviKvsScript::run("toolbareditor.open",g_pActiveWindow);
+}
+
+void KviFrame::toolbarsPopupSelected(int id)
+{
+ const QObject * o = sender();
+ if(!o)return;
+ if(!o->inherits("KviTalPopupMenu"))return;
+ const KviTalPopupMenu * p = (const KviTalPopupMenu *)o;
+ int idext = p->itemParameter(id);
+
+ KviCustomToolBarDescriptor * dd = KviCustomToolBarManager::instance()->findDescriptorByInternalId(idext);
+ if(dd)
+ {
+ if(dd->toolBar())delete dd->toolBar();
+ else dd->createToolBar();
+ }
+
+ if(KviMexToolBar * t = moduleExtensionToolBar(idext))
+ {
+ t->die();
+ } else {
+ g_pModuleExtensionManager->allocateExtension("toolbar",idext,firstConsole());
+ }
+}
+
+
+
+bool KviFrame::focusNextPrevChild(bool next)
+{
+ //debug("FOCUS NEXT PREV CHILD");
+ QWidget * w = focusWidget();
+ if(w)
+ {
+#ifdef COMPILE_USE_QT4
+ if(w->focusPolicy() == Qt::StrongFocus)return false;
+#else
+ if(w->focusPolicy() == QWidget::StrongFocus)return false;
+#endif
+ //QVariant v = w->property("KviProperty_FocusOwner");
+ //if(v.isValid())return false; // Do NOT change the focus widget!
+
+ if(w->parent())
+ {
+ QVariant v = w->parent()->property("KviProperty_ChildFocusOwner");
+ if(v.isValid())return false; // Do NOT change the focus widget!
+ }
+ }
+ // try to focus the widget on top of the Mdi
+ if(m_pMdi->topChild())
+ {
+ m_pMdi->focusTopChild();
+ return false;
+ }
+ return KviTalMainWindow::focusNextPrevChild(next);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Toolbar positioning stuff
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+void KviFrame::saveToolBarPositions()
+{
+ QString szTemp;
+ g_pApp->getLocalKvircDirectory(szTemp,KviApp::Config,KVI_CONFIGFILE_TOOLBARS);
+
+ QFile f(szTemp);
+ if(f.open(IO_WriteOnly | IO_Truncate))
+ {
+#ifdef COMPILE_USE_QT4
+ f.write(saveState(1));
+#else //!COMPILE_USE_QT4
+ QTextStream ts(&f);
+ ts << *this;
+ f.close();
+#endif //!COMPILE_USE_QT4
+ }
+}
+
+void KviFrame::restoreToolBarPositions()
+{
+ QString szTemp;
+ g_pApp->getLocalKvircDirectory(szTemp,KviApp::Config,KVI_CONFIGFILE_TOOLBARS);
+
+ QFile f(szTemp);
+
+ bool bNeedDefaults = false;
+
+ if(f.open(IO_ReadOnly))
+ {
+#ifdef COMPILE_USE_QT4
+ if(!restoreState(f.readAll(),1))
+ debug("Error while restoring toolbars position");
+#else //!COMPILE_USE_QT4
+ QTextStream ts(&f);
+ ts >> *this;
+ f.close();
+#endif //!COMPILE_USE_QT4
+ } else {
+ bNeedDefaults = true;
+ }
+
+ if(m_pTaskBar->inherits("KviTreeTaskBar"))
+ {
+#ifdef COMPILE_USE_QT4
+ // ensure that it is not too wide
+ m_pTaskBar->setMaximumWidth(600);
+ if(m_pTaskBar->width() > 600)
+ m_pTaskBar->setFixedWidth(250);
+#else //!COMPILE_USE_QT4
+ QDockArea * a = m_pTaskBar->area();
+ if((a == topDock()) || (a == bottomDock()))
+ {
+ // nope.... need to move it
+ a->removeDockWindow(m_pTaskBar,true,false);
+
+ //int iMaxWidth = m_pTaskBar->maximumWidth();
+ leftDock()->moveDockWindow(m_pTaskBar);
+ //m_pTaskBar->setMaximumWidth(iMaxWidth);
+ //m_pTaskBar->setOrientation(Vertical);
+ }
+ // ensure that it is not too wide
+ if(m_pTaskBar->width() > 600)
+ m_pTaskBar->setFixedExtentWidth(250);
+#endif //!COMPILE_USE_QT4
+ } /*else if(m_pTaskBar->inherits("KviClassicTaskBar"))
+ {
+ QDockArea * a = m_pTaskBar->area();
+ if((a == leftDock()) || (a == rightDock()))
+ {
+ // nope.... need to move it
+ a->removeDockWindow(m_pTaskBar,true,false);
+ bottomDock()->moveDockWindow(m_pTaskBar);
+ bottomDock()->lineUp(true);
+ }
+ }*/
+
+#ifndef COMPILE_USE_QT4
+ if(bNeedDefaults)
+ lineUpDockWindows(false);
+#endif //!COMPILE_USE_QT4
+}
+
+
+void KviFrame::createTaskBar()
+{
+ if(KVI_OPTION_BOOL(KviOption_boolUseTreeWindowListTaskBar))
+ {
+ m_pTaskBar = new KviTreeTaskBar();
+#ifdef COMPILE_USE_QT4
+ m_pTaskBar->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
+ addDockWidget(Qt::LeftDockWidgetArea,m_pTaskBar);
+#else //!COMPILE_USE_QT4
+ setDockEnabled(m_pTaskBar,Qt::DockTop,false);
+ setDockEnabled(m_pTaskBar,Qt::DockBottom,false);
+#endif //!COMPILE_USE_QT4
+ } else {
+ m_pTaskBar = new KviClassicTaskBar();
+#ifdef COMPILE_USE_QT4
+ m_pTaskBar->setAllowedAreas(Qt::AllDockWidgetAreas);
+ addDockWidget(Qt::BottomDockWidgetArea,m_pTaskBar);
+#else //!COMPILE_USE_QT4
+ setDockEnabled(m_pTaskBar,Qt::DockTop,true);
+ setDockEnabled(m_pTaskBar,Qt::DockBottom,true);
+#endif //!COMPILE_USE_QT4
+ }
+#ifndef COMPILE_USE_QT4
+ setDockEnabled(m_pTaskBar,Qt::DockLeft,true);
+ setDockEnabled(m_pTaskBar,Qt::DockRight,true);
+#endif //!COMPILE_USE_QT4
+}
+
+void KviFrame::recreateTaskBar()
+{
+ QString szOldClass = m_pTaskBar->className();
+
+ saveToolBarPositions();
+ KviWindow * w;
+ for(w = m_pWinList->first();w;w = m_pWinList->next())
+ {
+ w->destroyTaskBarItem();
+ }
+#ifndef COMPILE_USE_QT4
+ removeDockWindow(m_pTaskBar);
+#endif //!COMPILE_USE_QT4
+ delete m_pTaskBar;
+ createTaskBar();
+ for(w = m_pWinList->first();w;w = m_pWinList->next())
+ {
+ w->createTaskBarItem();
+ }
+ restoreToolBarPositions();
+
+
+ /*
+ QString szNewClass = m_pTaskBar->className();
+ if(szOldClass != szNewClass)
+ {
+ // the class changed...
+ // make sure that the tree task bar is in the left or right dock
+ // and the classic one is in the top or bottom on
+
+ Qt::Dock dock;
+ int index;
+ bool nl;
+ int eo;
+ getLocation(m_pTaskBar,dock,index,nl,eo);
+
+ if(KVI_OPTION_BOOL(KviOption_boolUseTreeWindowListTaskBar))
+ {
+ if((dock == Qt::Bottom) || (dock == Qt::Top))
+ moveDockWindow(m_pTaskBar,Qt::Left);
+ } else {
+ if((dock == Qt::Left) || (dock == Qt::Right))
+ moveDockWindow(m_pTaskBar,Qt::Bottom);
+ }
+ }
+ */
+
+ if(g_pActiveWindow)m_pTaskBar->setActiveItem(g_pActiveWindow->taskBarItem());
+}
+
+
+#if QT_VERSION == 0x030201
+unsigned int KviFrame::windowState()
+{
+ /* enum GNWindowState { WindowNoState = 0x00000000, WindowMinimized = 0x00000001,
+ WindowMaximized = 0x00000002, WindowFullScreen = 0x00000004, WindowActive = 0x00000008 };
+ GNWindowState GNWState;
+ if(isMinimized()) GNWState=WindowMinimized;
+ else if(isMaximized()) GNWState=WindowMaximized;
+ else if(isActiveWindow()) GNWState=WindowActive;
+ else if(isFullScreen()) GNWState=WindowFullScreen;
+ else GNWState=WindowNoState; */
+
+/* WindowNoState = 0x00000000 WindowMinimized = 0x00000001
+ WindowMaximized = 0x00000002 WindowFullScreen = 0x00000004 WindowActive = 0x00000008*/
+ if(isMinimized()) return 0x00000001;
+ else if(isMaximized()) return 0x00000002;
+ else if(isActiveWindow()) return 0x00000008;
+ else if(isFullScreen()) return 0x00000004;
+ else return 0x00000000;
+}
+void KviFrame::setWindowState(unsigned int GNWState)
+{
+ switch(GNWState)
+ {
+ case 0x00000001:
+ showMinimized();
+ break;
+ case 0x00000002:
+ showMaximized();
+ break;
+ } // switch
+}
+#endif
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Some accelerators
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void KviFrame::maximizeWindow(void)
+{
+ if(!g_pActiveWindow)return;
+ if(g_pActiveWindow->isMaximized())g_pActiveWindow->restore();
+ else g_pActiveWindow->maximize();
+}
+
+void KviFrame::minimizeWindow(void)
+{
+ if(g_pActiveWindow)g_pActiveWindow->minimize();
+}
+
+void KviFrame::switchToPrevWindow(void)
+{
+ m_pTaskBar->switchWindow(false,false);
+}
+
+void KviFrame::switchToNextWindow(void)
+{
+ m_pTaskBar->switchWindow(true,false);
+}
+
+void KviFrame::switchToPrevWindowInContext(void)
+{
+ m_pTaskBar->switchWindow(false,true);
+}
+
+void KviFrame::switchToNextWindowInContext(void)
+{
+ m_pTaskBar->switchWindow(true,true);
+}
+
+void KviFrame::hideEvent ( QHideEvent * e)
+{
+ if(KVI_OPTION_BOOL(KviOption_boolMinimizeInTray))
+ {
+ if(e->spontaneous())
+ {
+
+ if(!dockExtension())
+ {
+ executeInternalCommand(KVI_INTERNALCOMMAND_DOCKWIDGET_SHOW);
+ }
+ QTimer::singleShot( 0, this, SLOT(hide()) );
+ }
+
+ }
+}
+
+#include "kvi_frame.moc"
diff --git a/src/kvirc/ui/kvi_frame.h b/src/kvirc/ui/kvi_frame.h
new file mode 100644
index 00000000..d735a7c6
--- /dev/null
+++ b/src/kvirc/ui/kvi_frame.h
@@ -0,0 +1,259 @@
+#ifndef _KVI_FRAME_H_
+#define _KVI_FRAME_H_
+//=============================================================================
+//
+// File : kvi_frame.h
+// Creation date : Sun Jun 18 2000 17:59:02 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+//=============================================================================
+//
+// KviFrame:
+// The main window for the KVIrc application
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#include "kvi_tal_mainwindow.h"
+#include "kvi_qstring.h"
+#include "kvi_pointerlist.h"
+
+class KviMenuBar;
+class KviMdiManager;
+class KviMdiChild;
+class KviWindow;
+class KviConsole;
+class KviTaskBarBase;
+class QSplitter;
+class KviConfig;
+class KviMexToolBar;
+class KviIrcContext;
+class KviIrcConnection;
+class KviStatusBar;
+class KviTalPopupMenu;
+
+#include "kvi_accel.h" // we need this :/
+
+#ifdef COMPILE_ON_WINDOWS
+ // MSCV has problems with KviPointerList<KviWindow> otherwise
+ #include "kvi_window.h"
+#endif
+
+// base class for the dock extension applets..
+// this should be probably moved out of here
+class KVIRC_API KviDockExtension
+{
+protected:
+ unsigned int m_uStoredWindowState;
+public:
+ KviDockExtension() : m_uStoredWindowState(0){};
+ virtual ~KviDockExtension(){};
+public:
+ void setPrevWindowState(unsigned int state) { m_uStoredWindowState = state; };
+ unsigned int getPrevWindowState() { return m_uStoredWindowState; };
+
+ virtual void refresh(){};
+ virtual void die(){ delete this; };
+};
+
+
+
+class KVIRC_API KviFrame : public KviTalMainWindow // , public KviIrcContextManager
+{
+ friend class KviWindow;
+ friend class KviConsole;
+ friend class KviApp;
+ friend class KviServerParser;
+ friend class KviMexToolBar;
+ friend class KviMdiManager;
+ friend class KviIrcContext;
+ friend class KviIrcConnection;
+ friend class KviLagMeter;
+ friend class KviUserListView;
+ friend class KviUserListViewArea;
+ Q_OBJECT
+public:
+ KviFrame();
+ ~KviFrame();
+protected:
+ // subwindows
+ QSplitter * m_pSplitter; // the frame is splitted vertically and thus can host widgets
+ KviMenuBar * m_pMenuBar; // the main menu bar
+ KviMdiManager * m_pMdi; // the mdi manager widget (child of the splitter)
+ KviPointerList<KviMexToolBar> * m_pModuleExtensionToolBarList; // the module extension toolbars
+ KviTaskBarBase * m_pTaskBar; // the taskbar
+ KviStatusBar * m_pStatusBar;
+ // the mdi workspace child windows
+ KviPointerList<KviWindow> * m_pWinList; // the main list of windows
+ KviIrcContext * m_pActiveContext; // the context of the m_pActiveWindow
+ // other
+ KviDockExtension * m_pDockExtension; // the frame's dock extension: this should be prolly moved ?
+ KviAccel * m_pAccel; // the global accelelrator
+public:
+ // the mdi manager: handles mdi children
+ KviMdiManager * mdiManager(){ return m_pMdi; };
+ // the splitter is the central widget for this frame
+ QSplitter * splitter(){ return m_pSplitter; };
+ // KviTaskBarBase is the base class for KviTreeTaskBar and the KviClassicTaskBar
+ KviTaskBarBase * taskBar(){ return m_pTaskBar; };
+ // well.. the menu bar :D
+ KviMenuBar * mainMenuBar(){ return m_pMenuBar; };
+ KviStatusBar * mainStatusBar(){ return m_pStatusBar; };
+ // this function may return 0 if the active window has no irc context
+ KviIrcContext * activeContext(){ return m_pActiveContext; };
+ // shortcut to a = activeContext(); return a ? a->connection() : 0
+ KviIrcConnection * activeConnection();
+ // The list of the windows belonging to this frame
+ // Note that the windows may be also undocked, but they are still owned by the frame
+ KviPointerList<KviWindow> * windowList() { return m_pWinList; };
+ // Sets the specified window to be the active one
+ // Raises it and focuses it
+ void setActiveWindow(KviWindow *wnd);
+ // Adds a new KviWindow to this frame
+ // This should be done just after the KviWindow constructor has returned
+ // If bShow is false then the window is not explicitly shown
+ // otherwise it is set as active window.
+ void addWindow(KviWindow *wnd,bool bShow = true); // public for modules
+ // Checks if a specified window is still existing in this frame child
+ // window list. This is useful for asynchronous functions
+ // that keep a window pointer and need to ensure that it is still
+ // valid after an uncontrolled delay. (Think of a /timer implementation)
+ bool windowExists(KviWindow * wnd){ return (m_pWinList->findRef(wnd) != -1); };
+ // The number of consoles in this frame
+ unsigned int consoleCount();
+ // Creates a new console window. DON'T use the KviConsole constructor directly.
+ // (The script creation events are triggered from here)
+ KviConsole * createNewConsole(bool bFirstInFrame = false);
+ // Returns the first available console.
+ // There is almost always an available console.
+ // Exceptions are the startup and the shutdown (see activeWindow())
+ KviConsole * firstConsole();
+ // Returns the first console that has no connection in progress
+ // This function CAN return 0 if all the consoles are connected
+ KviConsole * firstNotConnectedConsole();
+ // this is explicitly dedicated to the DockExtension applets
+ void setDockExtension(KviDockExtension * e){ m_pDockExtension = e; };
+ // returns the dockExtension applet. Useful for calling refresh() when
+ // some particular event happens
+ KviDockExtension * dockExtension(){ return m_pDockExtension; };
+ // Updates the main window caption.
+ // Should be called when the active window changes
+ // and the active irc context changes state
+ void updateCaption();
+ // helper for saving the window properties
+ void saveWindowProperties(KviWindow * wnd,const char * szSection);
+ // finds the module extension toolbar with the specified identifier
+ // see kvi_moduleextension.h and kvi_mextoolbar.h
+ KviMexToolBar * moduleExtensionToolBar(int extensionId);
+ // Helper to fill the toolbars popup
+ // it is used by KviToolBar and KviMenuBar
+ void fillToolBarsPopup(KviTalPopupMenu * p);
+ int registerAccelerator(const QString &szKeySequence,QObject * recv,const char * slot);
+ void unregisterAccelerator(int id);
+
+#if QT_VERSION == 0x030201
+
+ unsigned int windowState();
+ void setWindowState(unsigned int GNWState);
+
+#endif
+
+public slots:
+ void newConsole();
+ void executeInternalCommand(int index);
+ void toggleStatusBar();
+ void customizeToolBars();
+protected:
+ void restoreModuleExtensionToolBars();
+ void saveModuleExtensionToolBars();
+ void registerModuleExtensionToolBar(KviMexToolBar * t);
+ void unregisterModuleExtensionToolBar(KviMexToolBar * t);
+
+ void unhighlightWindowsOfContext(KviIrcContext * c);
+
+ void createTaskBar();
+ void recreateTaskBar();
+
+ KviMdiChild * dockWindow(KviWindow *wnd,bool bShow = true,bool bCascade = true,QRect * setGeom = 0);
+ void undockWindow(KviWindow *wnd);
+
+ void closeWindow(KviWindow *wnd);
+
+ // called by KviWindow
+ void childWindowCloseRequest(KviWindow *wnd);
+ void childWindowActivated(KviWindow *wnd);
+
+ void childContextStateChange(KviIrcContext * c);
+ void childConnectionNickNameChange(KviIrcConnection * c);
+ void childConnectionAwayStateChange(KviIrcConnection * c);
+ void childConnectionUserModeChange(KviIrcConnection * c);
+ void childConnectionLagChange(KviIrcConnection * c);
+ void childConnectionServerInfoChange(KviIrcConnection * c);
+ void childWindowSelectionStateChange(KviWindow * pWnd,bool bGotSelectionNow);
+
+ virtual void closeEvent(QCloseEvent *e);
+ virtual void resizeEvent(QResizeEvent *e);
+ virtual void moveEvent(QMoveEvent *e);
+ virtual bool focusNextPrevChild(bool next);
+ virtual void windowActivationChange(bool bOldActive);
+
+ void updatePseudoTransparency();
+
+ KviAccel * installAccelerators(QWidget * wnd);
+
+ virtual void hideEvent ( QHideEvent * e);
+protected slots:
+ void switchToNextWindow();
+ void switchToPrevWindow();
+ void switchToNextWindowInContext();
+ void switchToPrevWindowInContext();
+
+ void maximizeWindow();
+ void minimizeWindow();
+
+ void accelActivated(int id);
+ void enteredSdiMode();
+ void leftSdiMode();
+ void toolbarsPopupSelected(int id);
+
+signals:
+ void activeWindowChanged(); // almost never 0.. but may be
+ void activeContextChanged(); // may be 0!
+ void activeContextStateChanged(); // emitted only when the active context is non 0 and it changes state
+ void activeConnectionNickNameChanged();
+ void activeConnectionUserModeChanged();
+ void activeConnectionAwayStateChanged();
+ void activeConnectionServerInfoChanged();
+ void activeConnectionLagChanged();
+ void activeWindowSelectionStateChanged(bool bGotSelectionNow);
+protected:
+ void applyOptions();
+private:
+ void saveToolBarPositions();
+ void restoreToolBarPositions();
+};
+
+#ifndef _KVI_FRAME_CPP_
+ extern KVIRC_API KviFrame * g_pFrame;
+#endif
+
+#endif //_KVI_FRAME_H_
diff --git a/src/kvirc/ui/kvi_historywin.cpp b/src/kvirc/ui/kvi_historywin.cpp
new file mode 100644
index 00000000..ba9ca315
--- /dev/null
+++ b/src/kvirc/ui/kvi_historywin.cpp
@@ -0,0 +1,255 @@
+#ifndef _KVI_HISTORYWIN_CPP_
+#define _KVI_HISTORYWIN_CPP_
+//
+// File : kvi_historywin.cpp
+// Creation date : Mon Aug 19 01:34:48 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+#define __KVIRC__
+
+#include "kvi_historywin.h"
+#include "kvi_app.h"
+#include "kvi_options.h"
+#include "kvi_input.h"
+#include "kvi_mirccntrl.h"
+
+#include <qnamespace.h>
+
+#ifdef COMPILE_USE_QT4
+ #include <qevent.h>
+#endif
+
+#include <ctype.h>
+
+extern KviInputHistory * g_pInputHistory;
+
+KviHistoryWindow::KviHistoryWindow()
+#ifdef COMPILE_USE_QT4
+: KviTalListBox(0,Qt::Popup)
+#else
+: KviTalListBox(0,Qt::WType_Popup)
+#endif
+{
+ m_pOwner = 0;
+#ifdef COMPILE_USE_QT4
+ setHScrollBarMode(Q3ScrollView::AlwaysOff);
+#else
+ setHScrollBarMode(QScrollView::AlwaysOff);
+#endif
+ connect(this,SIGNAL(selected(const QString &)),this,SLOT(itemSelected(const QString &)));
+
+ m_iTimerId = -1;
+}
+
+KviHistoryWindow::~KviHistoryWindow()
+{
+ if(m_iTimerId != -1)
+ {
+ killTimer(m_iTimerId);
+ m_iTimerId = -1;
+ }
+}
+
+void KviHistoryWindow::fill()
+{
+ clear();
+ for(QString * s = g_pInputHistory->list()->last();s;s = g_pInputHistory->list()->prev())
+ {
+ insertItem(*s);
+ }
+ if(count() > 0)setCurrentItem(count() - 1);
+}
+
+void KviHistoryWindow::popup(KviInput *owner)
+{
+ if(m_pOwner)disconnect(m_pOwner,SIGNAL(destroyed()),this,SLOT(ownerDead()));
+ m_pOwner = owner;
+ connect(m_pOwner,SIGNAL(destroyed()),this,SLOT(ownerDead()));
+ fill();
+ show();
+}
+
+void KviHistoryWindow::mousePressEvent(QMouseEvent *e)
+{
+ if(e->pos().x() < 0)goto hideme;
+ if(e->pos().x() > width())goto hideme;
+ if(e->pos().y() < 0)goto hideme;
+ if(e->pos().y() > height())goto hideme;
+
+ KviTalListBox::mousePressEvent(e);
+ e->accept();
+ return;
+
+hideme:
+ doHide();
+}
+
+/*
+bool KviHistoryWindow::findTypedSeq()
+{
+ int cnt = count();
+ int max = 0;
+ int mit = -1;
+ bool bFullMax = false;
+ for(int i=0;i<cnt;i++)
+ {
+ KviStr szIt = text(i);
+ int j;
+ for(j=0;j<szIt.len();j++)
+ {
+ if(tolower(*(szIt.ptr() + j)) != tolower(*(m_szTypedSeq.ptr() + j)))break;
+ }
+ if(j < max)
+ {
+ goto got_mit;
+ } else {
+ if(j >= max)
+ {
+ bFullMax = (j == szIt.len());
+ max = j;
+ mit = i;
+ }
+ }
+ }
+got_mit:
+ setCurrentItem(mit);
+ m_szCurFullSeq = text(mit);
+ return bFullMax;
+}
+*/
+
+void KviHistoryWindow::keyPressEvent(QKeyEvent *e)
+{
+ switch(e->key())
+ {
+ case Qt::Key_Up:
+ case Qt::Key_Down:
+ case Qt::Key_PageUp:
+ case Qt::Key_PageDown:
+ case Qt::Key_Return:
+ KviTalListBox::keyPressEvent(e);
+ return;
+ break;
+ case Qt::Key_Escape:
+ doHide();
+ return;
+ break;
+/*
+ case Qt::Key_Backspace:
+ if(m_szTypedSeq.hasData())
+ {
+ m_szTypedSeq.cutRight(1);
+ findTypedSeq();
+ } else {
+ doHide();
+ if(m_pOwner)g_pApp->sendEvent(m_pOwner,e);
+ }
+ return;
+ break;
+*/
+/*
+ case Qt::Key_Space:
+ doHide();
+ if(findTypedSeq())
+ {
+ KviStr szItem = m_szTypedSeq;
+ szItem.append(' ');
+ if(m_pOwner)m_pOwner->insertText(szItem);
+ } else {
+ if(m_pOwner)g_pApp->sendEvent(m_pOwner,e);
+ }
+ return;
+ break;
+*/
+/*
+ case Qt::Key_Tab:
+ doHide();
+ findTypedSeq();
+ KviStr szItem = m_szCurFullSeq;
+ szItem.append(KVI_TEXT_ICON);
+ if(m_pOwner)m_pOwner->insertText(szItem);
+ return;
+ break;
+*/
+ }
+/*
+ int as = e->ascii();
+ if((as >= 'a' && as <= 'z') || (as >= 'A' && as <= 'Z') || (as >= '0' && as <= '9')
+ || (as == '?') || (as == '$') || (as == '.') || (as == ',') || (as == '!') || (as =='&'))
+ {
+ m_szTypedSeq.append((char)as);
+ findTypedSeq();
+ } else {
+*/
+ if(m_pOwner)g_pApp->sendEvent(m_pOwner,e);
+/*
+ }
+*/
+}
+
+void KviHistoryWindow::ownerDead()
+{
+ m_pOwner = 0;
+ doHide();
+}
+
+void KviHistoryWindow::show()
+{
+ m_iTimerId = startTimer(100000); //100 sec ...seems enough
+ QWidget::show();
+}
+
+void KviHistoryWindow::timerEvent(QTimerEvent *)
+{
+ m_pOwner = 0; // do not setFocus() to the owner after the timeout
+ doHide();
+}
+
+void KviHistoryWindow::doHide()
+{
+ if(m_iTimerId != -1)
+ {
+ killTimer(m_iTimerId);
+ m_iTimerId = -1;
+ }
+ hide();
+ if(m_pOwner)
+ m_pOwner->setFocus();
+}
+
+void KviHistoryWindow::itemSelected(const QString &str)
+{
+ doHide();
+ if(m_pOwner)m_pOwner->setText(str);
+}
+
+
+void KviHistoryWindow::hideEvent(QHideEvent *)
+{
+ if(m_iTimerId != -1)
+ {
+ killTimer(m_iTimerId);
+ m_iTimerId = -1;
+ }
+}
+
+#include "kvi_historywin.moc"
+#endif //_KVI_HISTORYWIN_CPP_
diff --git a/src/kvirc/ui/kvi_historywin.h b/src/kvirc/ui/kvi_historywin.h
new file mode 100644
index 00000000..9a17eecd
--- /dev/null
+++ b/src/kvirc/ui/kvi_historywin.h
@@ -0,0 +1,61 @@
+#ifndef _KVI_HISTORYWIN_H_
+#define _KVI_HISTORYWIN_H_
+//
+// File : kvi_historywin.h
+// Creation date : Mon Aug 19 01:34:46 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+#include "kvi_settings.h"
+#include "kvi_string.h"
+
+#include "kvi_tal_listbox.h"
+
+class KviInput;
+
+#define KVI_HISTORY_WIN_HEIGHT 130
+
+class KVIRC_API KviHistoryWindow : public KviTalListBox
+{
+ Q_OBJECT
+public:
+ KviHistoryWindow();
+ ~KviHistoryWindow();
+private:
+ KviInput * m_pOwner;
+ int m_iTimerId;
+public:
+ void popup(KviInput *owner);
+// KviInput * owner(){ return m_pOwner; };
+ void doHide();
+private:
+ virtual void show();
+// bool findTypedSeq(); // returns true if it is a complete word
+ virtual void keyPressEvent(QKeyEvent *e);
+ virtual void mousePressEvent(QMouseEvent *e);
+ virtual void timerEvent(QTimerEvent *);
+ virtual void hideEvent ( QHideEvent * );
+ void fill();
+public slots:
+ void ownerDead();
+ void itemSelected(const QString &str);
+};
+
+#endif //_KVI_HISTORYWIN_H_
diff --git a/src/kvirc/ui/kvi_htmldialog.cpp b/src/kvirc/ui/kvi_htmldialog.cpp
new file mode 100644
index 00000000..6a8b4378
--- /dev/null
+++ b/src/kvirc/ui/kvi_htmldialog.cpp
@@ -0,0 +1,155 @@
+//=============================================================================
+//
+// File : kvi_htmldialog.cpp
+// Created on Wed 03 Jan 2007 03:36:36 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2007 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+#define __KVIRC__
+
+#include "kvi_htmldialog.h"
+#include "kvi_locale.h"
+#include "kvi_tal_textedit.h"
+
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qlayout.h>
+#include <qtextbrowser.h>
+
+KviHtmlDialog::KviHtmlDialog(QWidget * pParent,KviHtmlDialogData * pData)
+: QDialog(pParent)
+{
+ m_pData = pData;
+
+ if(pData->szCaption.isEmpty())
+ setCaption("KVIrc");
+ else
+ setCaption(pData->szCaption);
+
+ if(!pData->pixIcon.isNull())
+ setIcon(pData->pixIcon);
+
+ QGridLayout * g = new QGridLayout(this,4,3,7,7);
+
+ QLabel * l;
+ QTextBrowser * te;
+ QPushButton * pb;
+
+ int iUp = 0;
+ int iDown = 2;
+
+ if(!pData->szUpperLabelText.isEmpty())
+ {
+ l = new QLabel(this);
+ l->setText(pData->szUpperLabelText);
+ g->addMultiCellWidget(l,0,0,0,2);
+ iUp = 1;
+ }
+
+ if(!pData->szLowerLabelText.isEmpty())
+ {
+ l = new QLabel(this);
+ l->setText(pData->szLowerLabelText);
+ g->addMultiCellWidget(l,2,2,0,2);
+ iDown = 1;
+ }
+
+ te = new QTextBrowser(this);
+ te->setText(pData->szHtmlText);
+ //te->setReadOnly(true);
+
+ if(pData->iFlags & KviHtmlDialogData::ForceMinimumSize)
+ te->setMinimumSize(pData->iMinimumWidth,pData->iMinimumHeight);
+
+ //te->setReadOnly(true);
+ g->addMultiCellWidget(te,iUp,iDown,0,2);
+
+ int iButtons = pData->szButton3Text.isEmpty() ? (pData->szButton2Text.isEmpty() ? 1 : 2) : 3;
+ if(pData->iCancelButton > iButtons)pData->iCancelButton = iButtons;
+ if(pData->iDefaultButton > iButtons)pData->iDefaultButton = iButtons;
+
+ pb = new QPushButton(this);
+ pb->setText(pData->szButton1Text.isEmpty() ? __tr2qs("OK") : pData->szButton1Text);
+ pb->setDefault(pData->iDefaultButton == 1);
+ int iCoord = iButtons == 1 ? 1 : 0;
+ g->addWidget(pb,3,iCoord);
+ connect(pb,SIGNAL(clicked()),this,SLOT(button1Pressed()));
+
+ if(!pData->szButton2Text.isEmpty())
+ {
+ pb = new QPushButton(this);
+ pb->setText(pData->szButton2Text);
+ pb->setDefault(pData->iDefaultButton == 2);
+ iCoord = iButtons == 2 ? 2 : 1;
+ g->addWidget(pb,3,iCoord);
+ connect(pb,SIGNAL(clicked()),this,SLOT(button2Pressed()));
+
+ if(!pData->szButton3Text.isEmpty())
+ {
+ pb = new QPushButton(this);
+ pb->setText(pData->szButton3Text);
+ pb->setDefault(pData->iDefaultButton == 3);
+ g->addWidget(pb,3,2);
+ connect(pb,SIGNAL(clicked()),this,SLOT(button3Pressed()));
+ }
+ }
+
+ g->setRowStretch(1,1);
+
+ m_pData->iSelectedButton = m_pData->iDefaultButton;
+}
+
+KviHtmlDialog::~KviHtmlDialog()
+{
+
+}
+
+void KviHtmlDialog::button1Pressed()
+{
+ m_pData->iSelectedButton = 1;
+ accept();
+}
+
+void KviHtmlDialog::button2Pressed()
+{
+ m_pData->iSelectedButton = 2;
+ accept();
+}
+
+void KviHtmlDialog::button3Pressed()
+{
+ m_pData->iSelectedButton = 3;
+ accept();
+}
+
+void KviHtmlDialog::reject()
+{
+ m_pData->iSelectedButton = m_pData->iCancelButton;
+ QDialog::reject();
+}
+
+int KviHtmlDialog::display(QWidget * pParent,KviHtmlDialogData * pData)
+{
+ KviHtmlDialog * pDialog = new KviHtmlDialog(pParent,pData);
+ pDialog->exec();
+ delete pDialog;
+ return pData->iSelectedButton;
+}
+
+
diff --git a/src/kvirc/ui/kvi_htmldialog.h b/src/kvirc/ui/kvi_htmldialog.h
new file mode 100644
index 00000000..3f9a6d2a
--- /dev/null
+++ b/src/kvirc/ui/kvi_htmldialog.h
@@ -0,0 +1,87 @@
+#ifndef _KVI_HTMLDIALOG_H_
+#define _KVI_HTMLDIALOG_H_
+//=============================================================================
+//
+// File : kvi_htmldialog.h
+// Created on Wed 03 Jan 2007 03:36:36 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2007 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_qstring.h"
+#include "kvi_settings.h"
+
+
+#include <qpixmap.h>
+#include <qdialog.h>
+
+class KviHtmlDialogData
+{
+public:
+ // input
+
+ // mandatory fields
+ enum Flags { ForceMinimumSize = 1 };
+ int iFlags; // da flags :)
+ int iDefaultButton; // the button to use when Enter is pressed (1,2 or 3)
+ int iCancelButton; // the button to use when Esc is pressed (1,2 or 3)
+ QString szHtmlText; // Shouldn't be empty :D
+
+ // optional fields
+ QString szCaption; // KVIrc is used when this is empty
+ QString szUpperLabelText; // no label is shown if this is empty
+ QString szLowerLabelText; // no label is shown if this is empty
+ QString szButton1Text; // OK is used if this is empty
+ QString szButton2Text; // no button is shown if this is empty
+ QString szButton3Text; // no button is shown if this is empty
+
+ int iMinimumWidth;
+ int iMinimumHeight;
+
+ QPixmap pixIcon; // may be null
+
+ // output
+ int iSelectedButton; // returns 1,2 or 3
+};
+
+class KVIRC_API KviHtmlDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ // the dialog does NOT delete this structure and assumes that
+ // it remains alive until the dialog closes (i.e. it may access
+ // the structure in the destructor
+ KviHtmlDialog(QWidget * pParent,KviHtmlDialogData * pData);
+ ~KviHtmlDialog();
+protected:
+ KviHtmlDialogData * m_pData;
+public:
+ // displays the dialog as modal and returns 1,2 or 3
+ static int display(QWidget * pParent,KviHtmlDialogData * pData);
+protected slots:
+ void button1Pressed();
+ void button2Pressed();
+ void button3Pressed();
+protected:
+ virtual void reject();
+};
+
+
+
+#endif //!_KVI_HTMLDIALOG_H_
diff --git a/src/kvirc/ui/kvi_imagedialog.cpp b/src/kvirc/ui/kvi_imagedialog.cpp
new file mode 100644
index 00000000..adb33a16
--- /dev/null
+++ b/src/kvirc/ui/kvi_imagedialog.cpp
@@ -0,0 +1,367 @@
+//
+// File : kvi_imagedialog.cpp
+// Creation date : Sun Dec 22 2002 19:42 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#define __KVIRC__
+#include "kvi_imagedialog.h"
+
+#include "kvi_locale.h"
+
+#include <qlayout.h>
+#include <qpushbutton.h>
+
+#include <qimage.h>
+#include <qfileinfo.h>
+#include <qdir.h>
+
+#include <qpainter.h>
+
+#include "kvi_fileutils.h"
+
+#include "kvi_iconmanager.h"
+#include "kvi_options.h"
+
+#include "kvi_app.h"
+
+int KviImageDialogItem::height(const KviTalListBox *lb) const
+{
+ return pixmap()->height() + 12 + lb->fontMetrics().lineSpacing();
+}
+
+int KviImageDialogItem::width(const KviTalListBox *lb) const
+{
+ int w;
+ if(text().isEmpty())w = 24;
+ w = lb->fontMetrics().width(text()) + 4;
+ if(w > 100)w = 100;
+ if(w < 24)w = 24;
+ return QMAX(pixmap()->width() + 10,w);
+}
+
+void KviImageDialogItem::paint(QPainter * p)
+{
+ const QPixmap *pm = pixmap();
+ if(pm && !pm->isNull())p->drawPixmap(5,5, *pm);
+
+ if(!m_bIsFolder)
+ {
+ p->setPen(Qt::gray);
+ p->drawRect(3,3,pm->width() + 4,pm->height() + 4);
+ }
+
+ QRect daRect(listBox()->itemRect(this));
+
+ p->setPen(Qt::black);
+ p->drawRect(1,1,daRect.width() - 2,daRect.height() - 2);
+
+ if(text().isEmpty())return;
+
+ QString t = text();
+
+ QFontMetrics fm(p->fontMetrics());
+
+ int wdth = fm.width(t);
+
+ int idx = t.length();
+ while(wdth > (daRect.width() - 6) && idx > 3)
+ {
+ t = text();
+ t.truncate(idx);
+ t.append("...");
+ wdth = fm.width(t);
+ idx--;
+ }
+
+ p->drawText(3,pm->height() + 8,daRect.width() - 6,daRect.height() - (pm->height() + 6),Qt::AlignLeft | Qt::AlignTop,t);
+}
+
+
+KviImageDialog::KviImageDialog(QWidget * par,
+ const QString &szCaption,
+ int types,
+ int initialType,
+ const QString &szInitialDir,
+ int maxPreviewFileSize,bool modal)
+: QDialog(par)
+{
+ m_szInitialPath = szInitialDir;
+ setModal(modal);
+ m_iMaxPreviewFileSize = maxPreviewFileSize;
+
+ setCaption(szCaption.isEmpty() ? __tr2qs("Choose image ...") : szCaption);
+
+ m_pTimer = new QTimer(this);
+ connect(m_pTimer,SIGNAL(timeout()),this,SLOT(heartbeat()));
+
+ QGridLayout * g = new QGridLayout(this,4,3,5,3);
+
+ m_pTypeComboBox = new QComboBox(this);
+
+ g->addMultiCellWidget(m_pTypeComboBox,0,0,0,2);
+
+ m_pTypeList = new KviValueList<int>;
+
+ QString bi = __tr2qs("Builtin images");
+
+ QString tmp = bi;
+
+ if((types & KID_TYPE_ALL) == 0)types = KID_TYPE_FULL_PATH;
+
+ if(types & KID_TYPE_BUILTIN_IMAGES_SMALL)
+ {
+ tmp += ": ";
+ tmp += __tr2qs("Small icons");
+ m_pTypeComboBox->insertItem(tmp);
+ m_pTypeList->append(KID_TYPE_BUILTIN_IMAGES_SMALL);
+ }
+
+ if(types & KID_TYPE_FULL_PATH)
+ {
+ m_pTypeComboBox->insertItem(__tr2qs("Full path"));
+ m_pTypeList->append(KID_TYPE_FULL_PATH);
+ }
+
+ int idx = m_pTypeList->findIndex(initialType);
+ if(idx < 0)idx = 0;
+
+ QWidget * l = new QWidget(this);
+ g->addMultiCellWidget(l,1,1,0,2);
+
+
+ m_pListBox = new KviTalListBox(this);
+ m_pListBox->setColumnMode(KviTalListBox::FitToWidth);
+ m_pListBox->setRowMode(KviTalListBox::Variable);
+
+ m_pTip = new KviDynamicToolTip(m_pListBox->viewport());
+
+ g->addMultiCellWidget(m_pListBox,2,2,0,2);
+
+ QPushButton * b = new QPushButton(__tr2qs("Cancel"),this);
+ connect(b,SIGNAL(clicked()),this,SLOT(cancelClicked()));
+ g->addWidget(b,3,1);
+
+ b = new QPushButton(__tr2qs("Ok"),this);
+ connect(b,SIGNAL(clicked()),this,SLOT(okClicked()));
+ g->addWidget(b,3,2);
+
+ g->setRowStretch(2,1);
+ g->setColStretch(0,1);
+
+ connect(m_pTypeComboBox,SIGNAL(activated(int)),this,SLOT(jobTypeSelected(int)));
+ connect(m_pListBox,SIGNAL(doubleClicked(KviTalListBoxItem *)),this,SLOT(itemDoubleClicked(KviTalListBoxItem *)));
+ connect(m_pTip,SIGNAL(tipRequest(KviDynamicToolTip *,const QPoint &)),this,SLOT(tipRequest(KviDynamicToolTip *,const QPoint &)));
+
+ m_pTypeComboBox->setCurrentItem(idx);
+ jobTypeSelected(idx);
+
+ m_pListBox->setMinimumSize(420,350);
+}
+
+KviImageDialog::~KviImageDialog()
+{
+ delete m_pTimer;
+ delete m_pTypeList;
+}
+
+void KviImageDialog::jobTypeSelected(int index)
+{
+ if(index < 0)return;
+ if(index >= (int)(m_pTypeList->count()))index = (int)m_pTypeList->count();
+ if(m_szInitialPath.isEmpty())
+ startJob(*(m_pTypeList->at(index)),KVI_OPTION_STRING(KviOption_stringLastImageDialogPath));
+ else {
+ startJob(*(m_pTypeList->at(index)),m_szInitialPath);
+ m_szInitialPath = ""; // clear it so we will use the last path
+ }
+}
+
+void KviImageDialog::startJob(int type,const QString &szInitialPath)
+{
+ m_pTimer->stop();
+ m_iJobType = type;
+
+ m_iJobIndexHelper = 0;
+ if(m_iJobType == KID_TYPE_FULL_PATH)
+ {
+ QDir d(szInitialPath);
+ if(!d.exists())d = QDir::homeDirPath();
+ if(!d.exists())d = QDir::rootDirPath();
+ m_szJobPath = d.absPath();
+ KVI_OPTION_STRING(KviOption_stringLastImageDialogPath) = m_szJobPath;
+ m_lJobFileList = d.entryList(QDir::Hidden | QDir::All,QDir::DirsFirst | QDir::Name | QDir::IgnoreCase);
+ }
+
+ m_pTimer->start(100);
+}
+
+void KviImageDialog::jobTerminated()
+{
+ m_pTimer->stop();
+}
+
+void KviImageDialog::heartbeat()
+{
+ if(m_iJobIndexHelper == 0)m_pListBox->clear();
+
+
+ switch(m_iJobType)
+ {
+ case KID_TYPE_BUILTIN_IMAGES_SMALL:
+ {
+ if(m_iJobIndexHelper >= KVI_NUM_SMALL_ICONS)
+ {
+ jobTerminated();
+ return;
+ }
+ int max = m_iJobIndexHelper + 15;
+ if(max > KVI_NUM_SMALL_ICONS)max = KVI_NUM_SMALL_ICONS;
+ while(m_iJobIndexHelper < max)
+ {
+ QString id = g_pIconManager->getSmallIconName(m_iJobIndexHelper);
+ KviImageDialogItem * it;
+ QString tip;
+ KviQString::sprintf(tip,__tr2qs("Builtin $icon(%Q) [index %d]"),&id,m_iJobIndexHelper);
+ QString image_id = "$icon(";
+ image_id += id;
+ image_id += ")";
+ it = new KviImageDialogItem(m_pListBox,*(g_pIconManager->getSmallIcon(m_iJobIndexHelper)),id,image_id,tip);
+ m_iJobIndexHelper++;
+ }
+ }
+ break;
+ case KID_TYPE_FULL_PATH:
+ {
+ m_iJobIndexHelper++;
+ if(m_lJobFileList.isEmpty())
+ {
+ jobTerminated();
+ return;
+ }
+ int idx = 0;
+ while((idx < 20) && (!m_lJobFileList.isEmpty()))
+ {
+ QString szFile = m_lJobFileList.first();
+ m_lJobFileList.remove(szFile);
+ QString szPath = m_szJobPath;
+ szPath += KVI_PATH_SEPARATOR;
+ szPath += szFile;
+ QFileInfo fi(szPath);
+ idx += fi.size() / 128000; // we do less entries when have big files to read
+ if(fi.isDir())
+ {
+ if(szFile != ".")
+ {
+ QString tip = szFile;
+ tip += "<br><hr>";
+ tip += __tr2qs("directory");
+ KviImageDialogItem * it;
+ it = new KviImageDialogItem(m_pListBox,*(g_pIconManager->getBigIcon(KVI_BIGICON_FOLDER)),szFile,szPath,tip,true);
+ }
+ } else {
+ if(((int)fi.size()) < m_iMaxPreviewFileSize)
+ {
+ QImage i(szPath);
+ if(i.isNull())continue;
+ QPixmap pix;
+#ifdef COMPILE_USE_QT4
+ if((i.width() > 80) || (i.height() > 80))pix = i.scaled(80,80,Qt::KeepAspectRatio);
+#else
+ if((i.width() > 80) || (i.height() > 80))pix = i.scale(80,80,QImage::ScaleMin);
+#endif
+ else pix = i;
+
+ QString tip = szFile;
+ tip += "<br><hr>";
+ QString sz;
+ sz.setNum(i.width());
+ tip += sz;
+ tip += " x ";
+ sz.setNum(i.height());
+ tip += sz;
+ tip += " ";
+ tip += __tr2qs("pixels");
+ tip += "<br>";
+ sz.setNum(fi.size());
+ tip += sz;
+ tip += " ";
+ tip += __tr2qs("bytes");
+ tip += "<br>";
+
+ KviImageDialogItem * it;
+ it = new KviImageDialogItem(m_pListBox,pix,szFile,szPath,tip);
+ }
+ }
+ idx++;
+ }
+ }
+ break;
+ }
+}
+
+void KviImageDialog::okClicked()
+{
+ KviTalListBoxItem * it = 0;
+ int idx = m_pListBox->currentItem();
+ if(idx != -1)it = (KviTalListBoxItem *)m_pListBox->item(idx);
+ if(!it)return;
+ itemDoubleClicked(it);
+}
+
+void KviImageDialog::cancelClicked()
+{
+ m_szSelectedImage = QString::null;
+ reject();
+}
+
+void KviImageDialog::closeEvent(QCloseEvent * e)
+{
+ m_szSelectedImage = QString::null;
+ QDialog::closeEvent(e);
+}
+
+void KviImageDialog::itemDoubleClicked(KviTalListBoxItem * it)
+{
+ if(!it)return;
+ KviImageDialogItem * i = (KviImageDialogItem *)it;
+ if(i->isFolder())
+ {
+ startJob(KID_TYPE_FULL_PATH,i->imageId());
+ } else {
+ QString szImageId = i->imageId();
+ if(szImageId.length() > 0)
+ {
+ if(szImageId.at(0) == QChar('$'))
+ m_szSelectedImage = szImageId; // it's $icon(something)
+ else
+ g_pApp->mapImageFile(m_szSelectedImage,i->imageId()); // it's a file and we need to map it to our filesystem view
+ accept();
+ }
+ }
+}
+
+void KviImageDialog::tipRequest(KviDynamicToolTip *,const QPoint &pnt)
+{
+ KviTalListBoxItem * it = (KviTalListBoxItem *)m_pListBox->itemAt(pnt);
+ if(!it)return;
+ QRect r = m_pListBox->itemRect(it);
+ KviImageDialogItem * i = (KviImageDialogItem *)it;
+ m_pTip->tip(r,i->tipText());
+}
diff --git a/src/kvirc/ui/kvi_imagedialog.h b/src/kvirc/ui/kvi_imagedialog.h
new file mode 100644
index 00000000..7e1da54d
--- /dev/null
+++ b/src/kvirc/ui/kvi_imagedialog.h
@@ -0,0 +1,109 @@
+#ifndef _KVI_IMAGEDIALOG_H_
+#define _KVI_IMAGEDIALOG_H_
+//
+// File : kvi_imagedialog.h
+// Creation date : Sun Dec 22 2002 19:42 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+
+
+
+
+#include <qdialog.h>
+#include <qcombobox.h>
+#include "kvi_tal_listbox.h"
+#include "kvi_valuelist.h"
+#include <qtimer.h>
+#include <qstringlist.h>
+
+#include "kvi_dynamictooltip.h"
+
+class KviImageDialogItem : public KviTalListBoxPixmap
+{
+public:
+ bool m_bIsFolder;
+ QString m_szImageId;
+ QString m_szTipText;
+public:
+ KviImageDialogItem(KviTalListBox * b,const QPixmap &thumb,const QString &szFile,const QString &image_id,const QString &szTipText = QString::null,bool bIsFolder = false)
+ : KviTalListBoxPixmap(b,thumb,szFile) , m_bIsFolder(bIsFolder) , m_szImageId(image_id) , m_szTipText(szTipText) {};
+ ~KviImageDialogItem(){};
+public:
+ bool isFolder(){ return m_bIsFolder; };
+ const QString & imageId(){ return m_szImageId; };
+ const QString & tipText(){ return m_szTipText; };
+ virtual int height(const KviTalListBox *) const;
+ virtual int width(const KviTalListBox *) const;
+ virtual void paint(QPainter * p);
+};
+
+
+#define KID_TYPE_BUILTIN_IMAGES_SMALL 1
+#define KID_TYPE_FULL_PATH 2
+
+#define KID_TYPE_ALL 3
+
+class KVIRC_API KviImageDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ KviImageDialog(QWidget * par,
+ const QString &szCaption = QString::null,
+ int types = KID_TYPE_ALL,
+ int initialType = 0,
+ const QString &szInitialDir = QString::null,
+ int maxPreviewFileSize = 256000, bool modal=false);
+ virtual ~KviImageDialog();
+protected:
+ QComboBox * m_pTypeComboBox;
+ KviValueList<int> * m_pTypeList;
+ KviTalListBox * m_pListBox;
+ QTimer * m_pTimer;
+ int m_iJobType;
+
+ int m_iMaxPreviewFileSize;
+
+ QString m_szJobPath;
+ QStringList m_lJobFileList;
+
+ int m_iJobIndexHelper;
+
+ QString m_szSelectedImage;
+
+ QString m_szInitialPath;
+
+ KviDynamicToolTip * m_pTip;
+public:
+ const QString & selectedImage(){ return m_szSelectedImage; };
+protected:
+ void startJob(int type,const QString &szInitialPath = QString::null);
+ void jobTerminated();
+ virtual void closeEvent(QCloseEvent *e);
+protected slots:
+ void okClicked();
+ void cancelClicked();
+ void heartbeat();
+ void jobTypeSelected(int index);
+ void itemDoubleClicked(KviTalListBoxItem * it);
+ void tipRequest(KviDynamicToolTip *,const QPoint &pnt);
+};
+
+#endif //_KVI_IMAGEDIALOG_H_
diff --git a/src/kvirc/ui/kvi_input.cpp b/src/kvirc/ui/kvi_input.cpp
new file mode 100644
index 00000000..c0fbbd9e
--- /dev/null
+++ b/src/kvirc/ui/kvi_input.cpp
@@ -0,0 +1,2680 @@
+//=============================================================================
+//
+// File : kvi_input.cpp
+// Creation date : Sun Jan 3 1999 23:11:50 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+#define _KVI_DEBUG_CHECK_RANGE_
+#include "kvi_debug.h"
+
+#define _KVI_INPUT_CPP_
+
+#include "kvi_options.h"
+#include "kvi_app.h"
+#include "kvi_settings.h"
+#include "kvi_defaults.h"
+#include "kvi_colorwin.h"
+#include "kvi_texticonwin.h"
+#include "kvi_window.h"
+
+#include "kvi_locale.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_userlistview.h"
+#include "kvi_ircview.h"
+#include "kvi_console.h"
+#include "kvi_out.h"
+#include "kvi_iconmanager.h"
+#include "kvi_scripteditor.h"
+#include "kvi_config.h"
+#include "kvi_historywin.h"
+#include "kvi_input.h"
+#include "kvi_userinput.h"
+#include "kvi_kvs_script.h"
+#include "kvi_kvs_kernel.h"
+#include "kvi_doublebuffer.h"
+#include "kvi_styled_controls.h"
+#include "kvi_texticonmanager.h"
+#include "kvi_draganddrop.h"
+
+#include <qlabel.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <qfiledialog.h>
+#include "kvi_tal_popupmenu.h"
+#include <qpainter.h>
+#include <qclipboard.h>
+#include <qstringlist.h>
+#include "kvi_pointerlist.h"
+#include <qapplication.h>
+#include <qclipboard.h>
+#include <qmessagebox.h>
+#include "kvi_tal_hbox.h"
+#include <qlayout.h>
+#include <qstyle.h>
+#include <qevent.h>
+
+
+#ifndef ACCEL_KEY
+#define ACCEL_KEY(k) "\t" + QString(QKeySequence( Qt::CTRL | Qt::Key_ ## k ))
+#endif
+
+// FIXME: #warning "This hack is temporary...later remove it"
+#if QT_VERSION >= 300
+ #ifndef QT_CLEAN_NAMESPACE
+ #define QT_CLEAN_NAMESPACE
+ #include <qcursor.h>
+ #undef QT_CLEAN_NAMESPACE
+ #else
+ #include <qcursor.h>
+ #endif
+#else
+ #include <qcursor.h>
+#endif
+
+
+
+//This comes from kvi_app.cpp
+extern KviColorWindow * g_pColorWindow;
+extern KviTextIconWindow * g_pTextIconWindow;
+extern KviHistoryWindow * g_pHistoryWindow;
+extern KviTalPopupMenu * g_pInputPopup;
+
+static QFontMetrics * g_pLastFontMetrics = 0;
+
+
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ extern QPixmap * g_pShadedChildGlobalDesktopBackground;
+#endif
+
+
+#define KVI_INPUT_MAX_GLOBAL_HISTORY_ENTRIES 100
+#define KVI_INPUT_MAX_LOCAL_HISTORY_ENTRIES 20
+
+
+extern KviInputHistory * g_pInputHistory;
+
+
+KviInputHistory::KviInputHistory()
+{
+ m_pStringList = new KviPointerList<QString>;
+ m_pStringList->setAutoDelete(true);
+}
+
+KviInputHistory::~KviInputHistory()
+{
+ delete m_pStringList;
+}
+
+void KviInputHistory::add(QString * s)
+{
+ m_pStringList->insert(0,s);
+ if(m_pStringList->count() > KVI_INPUT_MAX_GLOBAL_HISTORY_ENTRIES)m_pStringList->removeLast();
+}
+
+void KviInputHistory::load(const char * filename)
+{
+ KviConfig c(filename,KviConfig::Read);
+
+ int cnt = c.readIntEntry("Count",0);
+
+ if(cnt > KVI_INPUT_MAX_GLOBAL_HISTORY_ENTRIES)cnt = KVI_INPUT_MAX_GLOBAL_HISTORY_ENTRIES;
+
+ KviStr tmp;
+
+ for(int i=0;i<cnt;i++)
+ {
+ tmp.sprintf("S%d",i);
+ QString entry = c.readQStringEntry(tmp.ptr(),"");
+ if(!entry.isEmpty())add(new QString(entry));
+ }
+}
+
+void KviInputHistory::save(const char * filename)
+{
+ KviConfig c(filename,KviConfig::Write);
+ c.clear();
+
+ c.writeEntry("Count",m_pStringList->count());
+
+ KviStr tmp;
+ int idx = 0;
+
+ for(QString * s = m_pStringList->first();s;s = m_pStringList->next())
+ {
+ if(!s->isEmpty())
+ {
+ tmp.sprintf("S%d",idx);
+ c.writeEntry(tmp.ptr(),*s);
+ idx++;
+ }
+ }
+}
+
+//=============== KviInputEditor ==============//
+
+static int g_iInputFontCharWidth[256];
+static bool g_bInputFontMetricsDirty = true;
+
+
+KviInputEditor::KviInputEditor(QWidget * par,KviWindow *wnd,KviUserListView * view)
+:QFrame(par,"input")
+{
+ m_pIconMenu = 0;
+ m_pInputParent = par;
+ m_iMaxBufferSize = KVI_INPUT_MAX_BUFFER_SIZE;
+ m_iCursorPosition = 0; //Index of the char AFTER the cursor
+ m_iFirstVisibleChar = 0; //Index of the first visible character
+ m_iSelectionBegin = -1; //Index of the first char in the selection
+ m_iSelectionEnd = -1; //Index of the last char in the selection
+ m_bIMComposing = false; //Whether the input method is active (composing).
+ // for input method support
+ m_iIMStart = 0; //Index of the start of the preedit string.
+ m_iIMLength = 0; //Length of the preedit string.
+ m_iIMSelectionBegin = 0; //Index of the start of the selection in preedit string.
+ m_iIMSelectionLength = 0; //Length of the selection in preedit string.
+
+ m_bCursorOn = false; //Cursor state
+ m_iCursorTimer = 0; //Timer that iverts the cursor state
+ m_iDragTimer = 0; //Timer for drag selection updates
+ m_iLastCursorXPosition = KVI_INPUT_MARGIN; //Calculated in paintEvent
+ m_iSelectionAnchorChar = -1; //Character clicked at the beginning of the selection process
+ m_iCurHistoryIdx = -1; //No data in the history
+ m_bUpdatesEnabled = true;
+ m_pKviWindow = wnd;
+ m_pUserListView = view;
+ m_pHistory = new KviPointerList<QString>;
+ m_pHistory->setAutoDelete(true);
+ m_bReadOnly = FALSE;
+
+ setInputMethodEnabled(true);
+
+#ifdef COMPILE_USE_QT4
+ setAutoFillBackground(false);
+ setFocusPolicy(Qt::StrongFocus);
+#else
+ setBackgroundMode(Qt::NoBackground);
+ setFocusPolicy(QWidget::StrongFocus);
+#endif
+ setAcceptDrops(true);
+ setFrameStyle( LineEditPanel );
+ setFrameShadow( Plain );
+
+ m_pIconMenu = new KviTalPopupMenu();
+ connect(m_pIconMenu,SIGNAL(activated(int)),this,SLOT(iconPopupActivated(int)));
+
+#ifdef COMPILE_USE_QT4
+ setCursor(Qt::IBeamCursor);
+#else
+ setCursor(IbeamCursor);
+#endif
+}
+
+KviInputEditor::~KviInputEditor()
+{
+ if(g_pLastFontMetrics) delete g_pLastFontMetrics;
+ g_pLastFontMetrics = 0;
+ if(m_pIconMenu)delete m_pIconMenu;
+ delete m_pHistory;
+ if(m_iCursorTimer)killTimer(m_iCursorTimer);
+ killDragTimer();
+}
+
+void KviInputEditor::recalcFontMetrics(QFontMetrics * pFm)
+{
+ QFontMetrics fm(KVI_OPTION_FONT(KviOption_fontInput));
+ unsigned short i;
+ for(i=1;i<32;i++)
+ {
+ QChar c = getSubstituteChar(i);
+ g_iInputFontCharWidth[i] = fm.width(c);
+ if(c != QChar(i))g_iInputFontCharWidth[i] += 4;
+ }
+ for(i=32;i<256;i++)
+ {
+ g_iInputFontCharWidth[i] = fm.width(QChar(i));
+ }
+ g_bInputFontMetricsDirty = false;
+}
+
+void KviInputEditor::applyOptions()
+{
+ g_bInputFontMetricsDirty = true;
+ update();
+}
+
+void KviInputEditor::dragEnterEvent(QDragEnterEvent *e)
+{
+ if(KviUriDrag::canDecode(e))
+ {
+ e->accept(true);
+// FIXME: #warning "FIX THIS COMMENTED STUFF"
+/*
+ m_pKviWindow->m_pFrm->m_pStatusBar->tempText(__tr("Drop the file to /PARSE it"),5000);
+*/
+ } else e->accept(false);
+}
+
+void KviInputEditor::dropEvent(QDropEvent *e)
+{
+ QStringList list;
+ if(KviUriDrag::decodeLocalFiles(e,list))
+ {
+ //debug("Local files decoded");
+ if(!list.isEmpty())
+ {
+ //debug("List not empty");
+ QStringList::ConstIterator it = list.begin(); //kewl ! :)
+ for( ; it != list.end(); ++it )
+ {
+ QString tmp = *it; //wow :)
+#ifndef COMPILE_ON_WINDOWS
+ if(tmp.length() > 0)
+ {
+ if(tmp[0] != QChar('/'))tmp.prepend("/"); //HACK HACK HACK for Qt bug (?!?)
+ }
+#endif
+ tmp.prepend("/PARSE \"");
+ tmp.append("\"");
+ if(m_pKviWindow)
+ KviKvsScript::run(tmp,m_pKviWindow);
+ }
+ }
+ }
+}
+
+int KviInputEditor::heightHint() const
+{
+ return sizeHint().height();
+}
+
+QSize KviInputEditor::sizeHint() const
+{
+ //grabbed from qlineedit.cpp
+ constPolish();
+ QFontMetrics fm(KVI_OPTION_FONT(KviOption_fontInput));
+ int h = QMAX(fm.lineSpacing(), 14) + 2*2; /* innerMargin */
+ int w = fm.width( 'x' ) * 17; // "some"
+ int m = frameWidth() * 2;
+#ifdef COMPILE_USE_QT4
+ QStyleOption opt;
+ opt.initFrom(this);
+ return (style()->sizeFromContents(QStyle::CT_LineEdit,&opt,
+ QSize( w + m, h + m ).
+ expandedTo(QApplication::globalStrut()),this));
+#else
+ return (style().sizeFromContents(QStyle::CT_LineEdit, this,
+ QSize( w + m, h + m ).
+ expandedTo(QApplication::globalStrut())));
+#endif
+}
+
+#define KVI_INPUT_DEF_BACK 100
+#define KVI_INPUT_DEF_FORE 101
+
+#ifdef COMPILE_USE_QT4
+void KviInputEditor::paintEvent(QPaintEvent *e)
+{
+ QPainter p(this);
+ SET_ANTI_ALIASING(p);
+ drawFrame(&p);
+ drawContents(&p);
+}
+#endif
+
+void KviInputEditor::drawContents(QPainter *p)
+{
+ if(!isVisible())return;
+
+ QRect rect = contentsRect();
+ int widgetWidth = rect.width();
+ int widgetHeight = rect.height();
+
+ KviDoubleBuffer doublebuffer(widgetWidth,widgetHeight);
+ QPixmap * pDoubleBufferPixmap = doublebuffer.pixmap();
+
+ QPainter pa(pDoubleBufferPixmap);
+ SET_ANTI_ALIASING(pa);
+
+ pa.setFont(KVI_OPTION_FONT(KviOption_fontInput));
+
+ QFontMetrics fm(pa.fontMetrics());
+
+ if(!g_pLastFontMetrics)
+ g_pLastFontMetrics = new QFontMetrics(pa.fontMetrics());
+
+ if(g_bInputFontMetricsDirty)
+ recalcFontMetrics(&fm);
+
+
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ if(g_pShadedChildGlobalDesktopBackground)
+ {
+ QPoint pnt = mapToGlobal(rect.topLeft());
+ pa.drawTiledPixmap(0,0,widgetWidth,widgetHeight,*g_pShadedChildGlobalDesktopBackground,pnt.x(),pnt.y());
+ } else {
+#endif
+ QPixmap *pix=KVI_OPTION_PIXMAP(KviOption_pixmapInputBackground).pixmap();
+
+ pa.fillRect(0,0,widgetWidth,widgetHeight,KVI_OPTION_COLOR(KviOption_colorInputBackground));
+ if(pix)
+ KviPixmapUtils::drawPixmapWithPainter(&pa,pix,KVI_OPTION_UINT(KviOption_uintInputPixmapAlign),rect,widgetWidth,widgetHeight);
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ }
+#endif
+
+
+ int curXPos = KVI_INPUT_MARGIN;
+ int maxXPos = widgetWidth-2*KVI_INPUT_MARGIN;
+ m_iCurBack = KVI_INPUT_DEF_BACK; //transparent
+ m_iCurFore = KVI_INPUT_DEF_FORE; //normal fore color
+ m_bCurBold = false;
+ m_bCurUnderline = false;
+
+ int bottom = widgetHeight-(widgetHeight-fm.height())/2;
+ int textBaseline = fm.ascent()+(widgetHeight-fm.height())/2;
+ int top = (widgetHeight-fm.height())/2;
+
+ runUpToTheFirstVisibleChar();
+
+ int charIdx = m_iFirstVisibleChar;
+
+ pa.setClipRect(0,0,widgetWidth,widgetHeight);
+
+ //Control the selection state
+ if((m_iSelectionEnd < m_iSelectionBegin) || (m_iSelectionEnd == -1) || (m_iSelectionBegin == -1))
+ {
+ m_iSelectionEnd = -1;
+ m_iSelectionBegin = -1;
+ }
+
+ if((m_iSelectionBegin != -1) && (m_iSelectionEnd >= m_iFirstVisibleChar))
+ {
+ int iSelStart = m_iSelectionBegin;
+
+ // TODO Refactor: write a function to combine this with the code determining iIMStart and iIMSelectionStart
+ if(iSelStart < m_iFirstVisibleChar)iSelStart = m_iFirstVisibleChar;
+ int xLeft = xPositionFromCharIndex(fm,iSelStart,TRUE);
+ int xRight = xPositionFromCharIndex(fm,m_iSelectionEnd + 1,TRUE);
+
+// pa.setRasterOp(Qt::NotROP);
+ pa.fillRect(xLeft,frameWidth(),xRight - xLeft,widgetWidth,KVI_OPTION_COLOR(KviOption_colorInputSelectionBackground));
+// pa.setRasterOp(Qt::CopyROP);
+ }
+
+ // When m_bIMComposing is true, the text between m_iIMStart and m_iIMStart+m_iIMLength should be highlighted to show that this is the active
+ // preedit area for the input method, and the text outside cannot be edited while
+ // composing. Maybe this can be implemented similarly as painting the selection?
+ // Also notice that inside the preedit, there can also be a selection, given by
+ // m_iSelectionBegin and m_iSelectionLength, and the widget needs to highlight that
+ // while in IM composition mode
+ if(m_bIMComposing && m_iIMLength > 0)
+ {
+ // TODO Write a function to combine IM selection drawing code. maybe the preedit area too.
+ int iIMSelectionStart = m_iIMSelectionBegin;
+ if(iIMSelectionStart < m_iFirstVisibleChar) iIMSelectionStart = m_iFirstVisibleChar;
+ int xIMSelectionLeft = xPositionFromCharIndex(fm,iIMSelectionStart,TRUE);
+ int xIMSelectionRight = xPositionFromCharIndex(fm,iIMSelectionStart + m_iIMSelectionLength,TRUE);
+// pa.setRasterOp(Qt::NotROP);
+ pa.fillRect(xIMSelectionLeft,0,xIMSelectionRight - xIMSelectionLeft, widgetWidth,KVI_OPTION_COLOR(KviOption_colorInputSelectionBackground));
+// pa.setRasterOp(Qt::CopyROP);
+
+ // highlight the IM selection
+ int iIMStart = m_iIMStart;
+ if(m_iIMStart < m_iFirstVisibleChar) m_iIMStart = m_iFirstVisibleChar;
+ int xIMLeft = xPositionFromCharIndex(fm,iIMStart,TRUE);
+ int xIMRight = xPositionFromCharIndex(fm,iIMStart + m_iIMLength,TRUE);
+
+ // underline the IM preedit
+ // Maybe should be put in drawTextBlock, similar to drawing underlined text
+ pa.drawLine(xIMLeft, bottom, xIMRight, bottom);
+ }
+
+ pa.setClipping(false);
+
+ while((charIdx < ((int)(m_szTextBuffer.length()))) && (curXPos < maxXPos))
+ {
+ extractNextBlock(charIdx,fm,curXPos,maxXPos);
+
+ if(m_bControlBlock)
+ {
+ pa.setPen(KVI_OPTION_COLOR(KviOption_colorInputControl));
+
+ QString s = getSubstituteChar(m_szTextBuffer[charIdx].unicode());
+
+ // the block width is 4 pixels more than the actual character
+
+ pa.drawText(curXPos + 2,textBaseline,s,1);
+
+ pa.drawRect(curXPos,top,m_iBlockWidth-1,bottom);
+ } else {
+ if(m_iSelectionBegin!=-1)
+ {
+ int iBlockEnd=charIdx+m_iBlockLen;
+ //block is selected (maybe partially)
+ if( iBlockEnd>m_iSelectionBegin && charIdx<=m_iSelectionEnd )
+ {
+ int iSubStart,iSubLen;
+ //in common it consists of 3 parts: unselected-selected-unselected
+ //some of thst parts can be empty (for example block is fully selected)
+
+ //first part start is always equal to the block start
+ iSubStart=charIdx;
+ iSubLen = m_iSelectionBegin>charIdx ? m_iSelectionBegin-charIdx : 0;
+
+
+ if(iSubLen)
+ {
+ drawTextBlock(&pa,fm,curXPos,textBaseline,iSubStart,iSubLen,FALSE);
+ curXPos += m_iBlockWidth;
+ m_iBlockWidth=0;
+ }
+
+ //second one
+ iSubStart+=iSubLen;
+ iSubLen=m_iSelectionEnd<iBlockEnd ? m_iSelectionEnd-iSubStart+1 : iBlockEnd-iSubStart;
+
+
+ if(iSubLen)
+ {
+ drawTextBlock(&pa,fm,curXPos,textBaseline,iSubStart,iSubLen,TRUE);
+ curXPos += m_iBlockWidth;
+ m_iBlockWidth=0;
+ }
+
+ if( m_iSelectionEnd<(iBlockEnd-1))
+ {
+ iSubStart+=iSubLen;
+ iSubLen=iBlockEnd-iSubStart;
+ drawTextBlock(&pa,fm,curXPos,textBaseline,iSubStart,iSubLen,FALSE);
+ }
+ } else {
+ drawTextBlock(&pa,fm,curXPos,textBaseline,charIdx,m_iBlockLen);
+ }
+ } else {
+ drawTextBlock(&pa,fm,curXPos,textBaseline,charIdx,m_iBlockLen);
+ }
+ }
+
+ curXPos += m_iBlockWidth;
+ charIdx += m_iBlockLen;
+ }
+
+ //Now the cursor
+
+ m_iLastCursorXPosition = KVI_INPUT_MARGIN;
+ m_iBlockLen = m_iFirstVisibleChar;
+
+ while(m_iBlockLen < m_iCursorPosition)
+ {
+ QChar c = m_szTextBuffer.at(m_iBlockLen);
+#ifdef COMPILE_USE_QT4
+ m_iLastCursorXPosition+= c.unicode() < 32 ? fm.width(getSubstituteChar(c.unicode())) + 3 : fm.width(c);
+#else
+ m_iLastCursorXPosition+= (c.unicode() < 256) ? g_iInputFontCharWidth[c.unicode()] : fm.width(c);
+#endif
+ m_iBlockLen++;
+ }
+
+ //m_iLastCursorXPosition = cur1XPos;
+
+ if(m_bCursorOn)
+ {
+ pa.setPen(KVI_OPTION_COLOR(KviOption_colorInputCursor));
+ pa.drawLine(m_iLastCursorXPosition,0,m_iLastCursorXPosition,widgetHeight);
+ } else {
+ pa.setPen(KVI_OPTION_COLOR(KviOption_colorInputForeground));
+ }
+
+#ifdef COMPILE_USE_QT4
+ // The other version of drawPixmap seems to be buggy
+ p->drawPixmap(rect.x(),rect.y(),rect.width(),rect.height(),*pDoubleBufferPixmap,0,0,widgetWidth,widgetHeight);
+#else
+ p->drawPixmap(rect.x(),rect.y(),*pDoubleBufferPixmap,0,0,widgetWidth,widgetHeight);
+#endif
+}
+
+void KviInputEditor::drawTextBlock(QPainter * pa,QFontMetrics & fm,int curXPos,int textBaseline,int charIdx,int len,bool bSelected)
+{
+ QString tmp = m_szTextBuffer.mid(charIdx,len);
+ m_iBlockWidth = fm.width(tmp);
+
+ QRect rect = contentsRect();
+ int widgetHeight = rect.height();
+
+ if(m_iCurFore == KVI_INPUT_DEF_FORE)
+ {
+ pa->setPen( bSelected ? KVI_OPTION_COLOR(KviOption_colorInputSelectionForeground) : KVI_OPTION_COLOR(KviOption_colorInputForeground));
+ } else {
+ if(((unsigned char)m_iCurFore) > 16)
+ {
+ pa->setPen(KVI_OPTION_COLOR(KviOption_colorInputBackground));
+ } else {
+ pa->setPen(KVI_OPTION_MIRCCOLOR((unsigned char)m_iCurFore));
+ }
+ }
+
+ if(m_iCurBack != KVI_INPUT_DEF_BACK)
+ {
+ if(((unsigned char)m_iCurBack) > 16)
+ {
+ pa->fillRect(curXPos,(widgetHeight-fm.height())/2,m_iBlockWidth,fm.height(),KVI_OPTION_COLOR(KviOption_colorInputForeground));
+ } else {
+ pa->fillRect(curXPos,(widgetHeight-fm.height())/2,m_iBlockWidth,fm.height(),KVI_OPTION_MIRCCOLOR((unsigned char)m_iCurBack));
+ }
+ }
+
+ pa->drawText(curXPos,textBaseline,tmp);
+
+ if(m_bCurBold)pa->drawText(curXPos+1,textBaseline,tmp);
+ if(m_bCurUnderline)
+ {
+ pa->drawLine(curXPos,textBaseline + fm.descent(),curXPos+m_iBlockWidth,textBaseline + fm.descent());
+ }
+
+}
+
+QChar KviInputEditor::getSubstituteChar(unsigned short control_code)
+{
+ switch(control_code)
+ {
+ case KVI_TEXT_COLOR:
+ return QChar('K');
+ break;
+ case KVI_TEXT_BOLD:
+ return QChar('B');
+ break;
+ case KVI_TEXT_RESET:
+ return QChar('O');
+ break;
+ case KVI_TEXT_REVERSE:
+ return QChar('R');
+ break;
+ case KVI_TEXT_UNDERLINE:
+ return QChar('U');
+ break;
+ case KVI_TEXT_CRYPTESCAPE:
+ return QChar('P');
+ break;
+ case KVI_TEXT_ICON:
+ return QChar('I');
+ break;
+ default:
+ return QChar(control_code);
+ break;
+ }
+}
+
+void KviInputEditor::extractNextBlock(int idx,QFontMetrics & fm,int curXPos,int maxXPos)
+{
+ m_iBlockLen = 0;
+ m_iBlockWidth = 0;
+
+ QChar c = m_szTextBuffer[idx];
+
+ if((c.unicode() > 32) ||
+ ((c != QChar(KVI_TEXT_COLOR)) &&
+ (c != QChar(KVI_TEXT_BOLD)) && (c != QChar(KVI_TEXT_UNDERLINE)) &&
+ (c != QChar(KVI_TEXT_RESET)) && (c != QChar(KVI_TEXT_REVERSE)) &&
+ (c != QChar(KVI_TEXT_CRYPTESCAPE)) && (c != QChar(KVI_TEXT_ICON))))
+ {
+ m_bControlBlock = false;
+ //Not a control code...run..
+ while((idx < ((int)(m_szTextBuffer.length()))) && (curXPos < maxXPos))
+ {
+ c = m_szTextBuffer[idx];
+ if((c.unicode() > 32) ||
+ ((c != QChar(KVI_TEXT_COLOR)) && (c != QChar(KVI_TEXT_BOLD)) &&
+ (c != QChar(KVI_TEXT_UNDERLINE)) && (c != QChar(KVI_TEXT_RESET)) &&
+ (c != QChar(KVI_TEXT_REVERSE)) && (c != QChar(KVI_TEXT_CRYPTESCAPE)) &&
+ (c != QChar(KVI_TEXT_ICON))))
+ {
+ m_iBlockLen++;
+#ifdef COMPILE_USE_QT4
+ int xxx = c.unicode() < 32 ? fm.width(getSubstituteChar(c.unicode())) + 3 : fm.width(c);;
+#else
+ int xxx = (c.unicode() < 256 ? g_iInputFontCharWidth[c.unicode()] : fm.width(c));
+#endif
+ m_iBlockWidth +=xxx;
+ curXPos +=xxx;
+ idx++;
+ } else break;
+ }
+ return;
+ } else {
+ m_bControlBlock = true;
+ m_iBlockLen = 1;
+ m_iBlockWidth = g_iInputFontCharWidth[c.unicode()];
+ //Control code
+ switch(c.unicode())
+ {
+ case KVI_TEXT_BOLD:
+ m_bCurBold = ! m_bCurBold;
+ break;
+ case KVI_TEXT_UNDERLINE:
+ m_bCurUnderline = ! m_bCurUnderline;
+ break;
+ case KVI_TEXT_RESET:
+ m_iCurFore = KVI_INPUT_DEF_FORE;
+ m_iCurBack = KVI_INPUT_DEF_BACK;
+ m_bCurBold = false;
+ m_bCurUnderline = false;
+ break;
+ case KVI_TEXT_REVERSE:
+ {
+ char auxClr = m_iCurFore;
+ m_iCurFore = m_iCurBack;
+ m_iCurBack = auxClr;
+ }
+ break;
+ case KVI_TEXT_CRYPTESCAPE:
+ case KVI_TEXT_ICON:
+ // makes a single block
+ break;
+ case KVI_TEXT_COLOR:
+ {
+ idx++;
+ if(idx >= ((int)(m_szTextBuffer.length())))return;
+ unsigned char fore;
+ unsigned char back;
+ idx = getUnicodeColorBytes(m_szTextBuffer,idx,&fore,&back);
+ if(fore != KVI_NOCHANGE)
+ {
+ m_iCurFore = fore;
+ if(back != KVI_NOCHANGE)m_iCurBack = back;
+ } else {
+ // ONLY a CTRL+K
+ m_iCurBack = KVI_INPUT_DEF_BACK;
+ m_iCurFore = KVI_INPUT_DEF_FORE;
+ }
+ }
+ break;
+ default:
+ debug("Ops..");
+ exit(0);
+ break;
+ }
+ }
+}
+
+void KviInputEditor::runUpToTheFirstVisibleChar()
+{
+ register int idx = 0;
+ while(idx < m_iFirstVisibleChar)
+ {
+ unsigned short c = m_szTextBuffer[idx].unicode();
+ if(c < 32)
+ {
+ switch(c)
+ {
+ case KVI_TEXT_BOLD:
+ m_bCurBold = ! m_bCurBold;
+ break;
+ case KVI_TEXT_UNDERLINE:
+ m_bCurUnderline = ! m_bCurUnderline;
+ break;
+ case KVI_TEXT_RESET:
+ m_iCurFore = KVI_INPUT_DEF_FORE;
+ m_iCurBack = KVI_INPUT_DEF_BACK;
+ m_bCurBold = false;
+ m_bCurUnderline = false;
+ break;
+ case KVI_TEXT_REVERSE:
+ {
+ char auxClr = m_iCurFore;
+ m_iCurFore = m_iCurBack;
+ m_iCurBack = auxClr;
+ }
+ break;
+ case KVI_TEXT_COLOR:
+ {
+ idx++;
+ if(idx >= ((int)(m_szTextBuffer.length())))return;
+ unsigned char fore;
+ unsigned char back;
+ idx = getUnicodeColorBytes(m_szTextBuffer,idx,&fore,&back);
+ idx--;
+ if(fore != KVI_NOCHANGE)m_iCurFore = fore;
+ else m_iCurFore = KVI_INPUT_DEF_FORE;
+ if(back != KVI_NOCHANGE)m_iCurBack = back;
+ else m_iCurBack = KVI_INPUT_DEF_BACK;
+ }
+ break;
+ case 0:
+ debug("KviInputEditor::Encountered invisible end of the string!");
+ exit(0);
+ break;
+ }
+ }
+ idx++;
+ }
+}
+
+
+void KviInputEditor::mousePressEvent(QMouseEvent *e)
+{
+ if(e->button() & Qt::LeftButton)
+ {
+ m_iCursorPosition = charIndexFromXPosition(e->pos().x());
+ //move the cursor to
+ int anchorX = xPositionFromCharIndex(m_iCursorPosition);
+ if(anchorX > (width()-frameWidth()))m_iFirstVisibleChar++;
+ m_iSelectionAnchorChar = m_iCursorPosition;
+ selectOneChar(-1);
+ //grabMouse(QCursor(crossCursor));
+ repaintWithCursorOn();
+ killDragTimer();
+ m_iDragTimer = startTimer(KVI_INPUT_DRAG_TIMEOUT);
+
+ } else if(e->button() & Qt::RightButton)
+ {
+ int type = g_pActiveWindow->type();
+
+ //Popup menu
+ g_pInputPopup->clear();
+
+ QString szClip;
+
+ QClipboard * c = QApplication::clipboard();
+ if(c)
+ {
+ szClip = c->text(QClipboard::Clipboard);
+
+#ifdef COMPILE_USE_QT4
+ int occ = szClip.count(QChar('\n'));
+#else
+ int occ = szClip.contains(QChar('\n'));
+#endif
+
+ if(!szClip.isEmpty())
+ {
+ if(szClip.length() > 60)
+ {
+ szClip.truncate(60);
+ szClip.append("...");
+ }
+ szClip.replace(QChar('&'),"&amp;");
+ szClip.replace(QChar('<'),"&lt;");
+ szClip.replace(QChar('>'),"&gt;");
+ szClip.replace(QChar('\n'),"<br>");
+
+ QString label = "<center><b>";
+ label += __tr2qs("Clipboard");
+ label += ":</b><br>";
+ label += szClip;
+ label += "<br><b>";
+
+ QString num;
+ num.setNum(occ);
+
+ label += num;
+ label += QChar(' ');
+ label += (occ == 1) ? __tr2qs("line break") : __tr2qs("line breaks");
+ label += "</b></center>";
+
+ QLabel * l = new QLabel(label,g_pInputPopup);
+ l->setFrameStyle(QFrame::Raised | QFrame::StyledPanel);
+ l->setMargin(5);
+ // FIXME: This does NOT work under Qt 4.x (they seem to consider it as bad UI design)
+#ifndef COMPILE_USE_QT4
+ g_pInputPopup->insertItem(l);
+#else
+ delete l;
+#endif
+ }
+ }
+
+ int id = g_pInputPopup->insertItem(__tr2qs("Cu&t") + ACCEL_KEY(X),this,SLOT(cut()));
+ g_pInputPopup->setItemEnabled(id,hasSelection());
+ id = g_pInputPopup->insertItem(__tr2qs("&Copy") + ACCEL_KEY(C),this,SLOT(copyToClipboard()));
+ g_pInputPopup->setItemEnabled(id,hasSelection());
+ id = g_pInputPopup->insertItem(__tr2qs("&Paste") + ACCEL_KEY(V),this,SLOT(pasteClipboardWithConfirmation()));
+ g_pInputPopup->setItemEnabled(id,!szClip.isEmpty() && !m_bReadOnly);
+ id = g_pInputPopup->insertItem(__tr2qs("Paste (Slowly)"),this,SLOT(pasteSlow()));
+ if ((type == KVI_WINDOW_TYPE_CHANNEL) || (type == KVI_WINDOW_TYPE_QUERY) || (type == KVI_WINDOW_TYPE_DCCCHAT))
+ g_pInputPopup->setItemEnabled(id,!szClip.isEmpty() && !m_bReadOnly);
+ else
+ g_pInputPopup->setItemEnabled(id,false);
+ id = g_pInputPopup->insertItem(__tr2qs("Paste &File") + ACCEL_KEY(F),this,SLOT(pasteFile()));
+ if ((type != KVI_WINDOW_TYPE_CHANNEL) && (type != KVI_WINDOW_TYPE_QUERY) && (type != KVI_WINDOW_TYPE_DCCCHAT))
+ g_pInputPopup->setItemEnabled(id,false);
+ else
+ g_pInputPopup->setItemEnabled(id,!m_bReadOnly);
+ if(m_bSpSlowFlag ==true)
+ {
+ id = g_pInputPopup->insertItem(__tr2qs("Stop Paste"),this,SLOT(stopPasteSlow())); /*G&N 2005*/
+ }
+ id = g_pInputPopup->insertItem(__tr2qs("Clear"),this,SLOT(clear()));
+ g_pInputPopup->setItemEnabled(id,!m_szTextBuffer.isEmpty() && !m_bReadOnly);
+ g_pInputPopup->insertSeparator();
+ id = g_pInputPopup->insertItem(__tr2qs("Select All"),this,SLOT(selectAll()));
+ g_pInputPopup->setItemEnabled(id,(!m_szTextBuffer.isEmpty()));
+
+
+ g_pInputPopup->insertSeparator();
+ m_pIconMenu->clear();
+
+ KviPointerHashTable<QString,KviTextIcon> * d = g_pTextIconManager->textIconDict();
+ KviPointerHashTableIterator<QString,KviTextIcon> it(*d);
+ QStringList strList;
+ while(KviTextIcon * i = it.current())
+ {
+ strList.append(it.currentKey());
+ ++it;
+ }
+ strList.sort();
+ KviTextIcon * icon;
+ QPixmap *pix;
+
+ for(QStringList::Iterator iter = strList.begin(); iter != strList.end(); ++iter)
+ {
+ icon=g_pTextIconManager->lookupTextIcon(*iter);
+ if(icon)
+ {
+ pix = icon->pixmap();
+ if(pix) m_pIconMenu->insertItem(*pix,*iter);
+ }
+ }
+
+ g_pInputPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_BIGGRIN)),__tr2qs("Insert Icon"),m_pIconMenu);
+ g_pInputPopup->popup(mapToGlobal(e->pos()));
+ } else {
+ pasteSelectionWithConfirmation();
+ }
+}
+void KviInputEditor::iconPopupActivated(int id)
+{
+ if(!m_bReadOnly)
+ {
+ QString text = m_pIconMenu->text(id);
+ if(!text.isEmpty())
+ {
+ text.prepend(KVI_TEXT_ICON);
+ text.append(' ');
+ insertText(text);
+ }
+ }
+}
+
+bool KviInputEditor::hasSelection()
+{
+ return ((m_iSelectionBegin != -1)&&(m_iSelectionEnd != -1));
+}
+
+void KviInputEditor::copyToClipboard()
+{
+ if(!hasSelection())return;
+ QClipboard * c = QApplication::clipboard();
+ if(!c)return;
+ QString szTxt = m_szTextBuffer.mid(m_iSelectionBegin,(m_iSelectionEnd-m_iSelectionBegin)+1);
+ c->setText(szTxt,QClipboard::Clipboard);
+ repaintWithCursorOn();
+}
+
+void KviInputEditor::copyToSelection(bool bDonNotCopyToClipboard)
+{
+ if(!hasSelection())return;
+ QClipboard * c = QApplication::clipboard();
+ if(!c)return;
+ QString szTxt = m_szTextBuffer.mid(m_iSelectionBegin,(m_iSelectionEnd-m_iSelectionBegin)+1);
+ if(c->supportsSelection())
+ c->setText(szTxt,QClipboard::Selection);
+ else if(!bDonNotCopyToClipboard)
+ c->setText(szTxt,QClipboard::Clipboard);
+ repaintWithCursorOn();
+}
+
+
+void KviInputEditor::moveCursorTo(int idx,bool bRepaint)
+{
+ if(idx < 0)idx = 0;
+ if(idx > ((int)(m_szTextBuffer.length())))idx = m_szTextBuffer.length();
+ if(idx > m_iCursorPosition)
+ {
+ while(m_iCursorPosition < idx)
+ {
+ moveRightFirstVisibleCharToShowCursor();
+ m_iCursorPosition++;
+ }
+ } else {
+ m_iCursorPosition = idx;
+ if(m_iFirstVisibleChar > m_iCursorPosition)m_iFirstVisibleChar = m_iCursorPosition;
+ }
+ if(bRepaint)repaintWithCursorOn();
+}
+
+void KviInputEditor::removeSelected()
+{
+ if(!hasSelection())return;
+ m_szTextBuffer.remove(m_iSelectionBegin,(m_iSelectionEnd-m_iSelectionBegin)+1);
+ moveCursorTo(m_iSelectionBegin,false);
+ selectOneChar(-1);
+ repaintWithCursorOn();
+}
+
+void KviInputEditor::cut()
+{
+ if(!hasSelection())return;
+ QClipboard * c = QApplication::clipboard();
+ if(!c)return;
+ c->setText(m_szTextBuffer.mid(m_iSelectionBegin,(m_iSelectionEnd-m_iSelectionBegin)+1),QClipboard::Clipboard);
+ m_szTextBuffer.remove(m_iSelectionBegin,(m_iSelectionEnd-m_iSelectionBegin)+1);
+ moveCursorTo(m_iSelectionBegin,false);
+ selectOneChar(-1);
+ repaintWithCursorOn();
+}
+
+void KviInputEditor::insertText(const QString &text)
+{
+ QString szText = text; // crop away constness
+ if(szText.isEmpty())return;
+
+ //szText.replaceAll('\t'," "); //Do not paste tabs
+
+ //szText.replace(QRegExp("\t")," "); // do not paste tabs
+
+ m_bUpdatesEnabled = false;
+ removeSelected();
+ m_bUpdatesEnabled = true;
+
+ if(szText.find('\n') == -1)
+ {
+ m_szTextBuffer.insert(m_iCursorPosition,szText);
+ m_szTextBuffer.truncate(m_iMaxBufferSize);
+ moveCursorTo(m_iCursorPosition + szText.length());
+ } else {
+ //Multiline paste...do not execute commands here
+ QString szBlock;
+ while(!szText.isEmpty())
+ {
+ int idx = szText.find('\n');
+ if(idx != -1)
+ {
+ szBlock = szText.left(idx);
+ //else szBlock = QChar(KVI_TEXT_RESET);
+ szText.remove(0,idx+1);
+ } else {
+ szBlock = szText;
+ szText = "";
+ }
+
+ m_szTextBuffer.insert(m_iCursorPosition,szBlock);
+ m_szTextBuffer.truncate(m_iMaxBufferSize);
+
+ int pos = 0;
+ while((pos < ((int)(m_szTextBuffer.length()))) && (m_szTextBuffer[pos] < 33))pos++;
+ if((pos < ((int)(m_szTextBuffer.length()))) && (m_szTextBuffer[pos] == QChar('/')))m_szTextBuffer.insert(pos,"\\");
+
+ returnPressed(idx != -1);
+ }
+ }
+}
+
+// Replace (length) characters in the buffer from (start) with (text), returns
+// the length of the text inserted (different from text.length() only if the
+// buffer was truncated.
+int KviInputEditor::replaceSegment(int start, int length, const QString &text)
+{
+ m_szTextBuffer.remove(start, length);
+ m_szTextBuffer.insert(start, text);
+ m_szTextBuffer.truncate(m_iMaxBufferSize);
+ repaintWithCursorOn();
+
+ int iInsertedLength = text.length();
+ int iMaxInsertedLength = m_iMaxBufferSize - start;
+ if(iInsertedLength > iMaxInsertedLength) return iMaxInsertedLength;
+ return iInsertedLength;
+}
+
+void KviInputEditor::pasteClipboardWithConfirmation()
+{
+ QClipboard * c = QApplication::clipboard();
+ if(!c)return;
+ QString szText = c->text(QClipboard::Clipboard);
+
+ if(szText.contains(QChar('\n')) > 0)
+ {
+ if(m_pInputParent->inherits("KviInput"))
+ ((KviInput*)(m_pInputParent))->multiLinePaste(szText);
+ } else {
+ insertText(szText);
+ }
+}
+
+void KviInputEditor::pasteSelectionWithConfirmation()
+{
+ QClipboard * c = QApplication::clipboard();
+ if(!c)return;
+ QString szText = c->text(c->supportsSelection() ? QClipboard::Selection : QClipboard::Clipboard);
+
+ if(szText.contains(QChar('\n')) > 0)
+ {
+ if(m_pInputParent->inherits("KviInput"))
+ ((KviInput*)(m_pInputParent))->multiLinePaste(szText);
+ } else {
+ insertText(szText);
+ }
+}
+
+void KviInputEditor::pasteSlow()
+{
+ KviKvsScript::run("spaste.clipboard",g_pActiveWindow);
+ m_bSpSlowFlag = true;
+}
+
+void KviInputEditor::stopPasteSlow()
+{
+ KviKvsScript::run("spaste.stop",g_pActiveWindow);
+ m_bSpSlowFlag = false;
+}
+
+void KviInputEditor::pasteFile()
+{
+ QString stmp = QFileDialog::getOpenFileName("","",this,"Paste File", "Choose a file" );
+ if(stmp!="")
+ {
+ QString stmp1 = "spaste.file " + stmp ;
+ KviKvsScript::run(stmp1,g_pActiveWindow);
+ m_bSpSlowFlag = true;
+ }
+}
+
+void KviInputEditor::selectAll()
+{
+ if(m_szTextBuffer.length() > 0)
+ {
+ m_iSelectionBegin = 0;
+ m_iSelectionEnd = m_szTextBuffer.length()-1;
+ }
+ end();
+}
+
+void KviInputEditor::clear()
+{
+ m_szTextBuffer = "";
+ selectOneChar(-1);
+ home();
+}
+
+void KviInputEditor::setText(const QString text)
+{
+ m_szTextBuffer = text;
+ m_szTextBuffer.truncate(m_iMaxBufferSize);
+ selectOneChar(-1);
+ end();
+}
+
+void KviInputEditor::mouseReleaseEvent(QMouseEvent *)
+{
+ if(m_iDragTimer)
+ {
+ m_iSelectionAnchorChar =-1;
+ //releaseMouse();
+ killDragTimer();
+ }
+ if(hasSelection())
+ copyToSelection();
+}
+
+void KviInputEditor::killDragTimer()
+{
+ if(m_iDragTimer)
+ {
+ killTimer(m_iDragTimer);
+ m_iDragTimer = 0;
+ }
+}
+
+void KviInputEditor::timerEvent(QTimerEvent *e)
+{
+ if(e->timerId() == m_iCursorTimer)
+ {
+ if(!hasFocus() || !isVisibleToTLW())
+ {
+ killTimer(m_iCursorTimer);
+ m_iCursorTimer = 0;
+ m_bCursorOn = false;
+ } else m_bCursorOn = ! m_bCursorOn;
+ update();
+ } else {
+ //Drag timer
+ handleDragSelection();
+ }
+}
+
+void KviInputEditor::handleDragSelection()
+{
+ if(m_iSelectionAnchorChar == -1)return;
+
+ QPoint pnt = mapFromGlobal(QCursor::pos());
+
+
+ if(pnt.x() <= 0)
+ {
+ //Left side dragging
+ if(m_iFirstVisibleChar > 0)m_iFirstVisibleChar--;
+ m_iCursorPosition = m_iFirstVisibleChar;
+ } else if(pnt.x() >= width())
+ {
+ //Right side dragging...add a single character to the selection on the right
+ if(m_iCursorPosition < ((int)(m_szTextBuffer.length())))
+ {
+ moveRightFirstVisibleCharToShowCursor();
+ m_iCursorPosition++;
+ } //else at the end of the selection...don't move anything
+ } else {
+ //Inside the window...
+ m_iCursorPosition = charIndexFromXPosition(pnt.x());
+ }
+ if(m_iCursorPosition == m_iSelectionAnchorChar)selectOneChar(-1);
+ else {
+ if(m_iCursorPosition > m_iSelectionAnchorChar)
+ {
+ m_iSelectionBegin = m_iSelectionAnchorChar;
+ m_iSelectionEnd = m_iCursorPosition-1;
+ } else {
+ m_iSelectionBegin = m_iCursorPosition;
+ m_iSelectionEnd = m_iSelectionAnchorChar-1;
+ }
+ }
+ repaintWithCursorOn();
+}
+
+void KviInputEditor::returnPressed(bool bRepaint)
+{
+ if (!m_szTextBuffer.isEmpty() /* && (!m_pHistory->current() || m_szTextBuffer.compare(*(m_pHistory->current())))*/)
+ {
+ if(m_pInputParent->inherits("KviInput"))
+ g_pInputHistory->add(new QString(m_szTextBuffer));
+
+ m_pHistory->insert(0,new QString(m_szTextBuffer));
+ }
+
+ __range_valid(KVI_INPUT_MAX_LOCAL_HISTORY_ENTRIES > 1); //ABSOLUTELY NEEDED, if not, pHist will be destroyed...
+ if(m_pHistory->count() > KVI_INPUT_MAX_LOCAL_HISTORY_ENTRIES)m_pHistory->removeLast();
+
+ m_iCurHistoryIdx = -1;
+
+ // FIXME: ALL THIS STUFF SHOULD BE CONVERTED TO QString
+ /*
+ if(m_pInputParent->inherits("KviInput"))
+ {
+ QString szBuffer(m_szTextBuffer);
+ m_szTextBuffer="";
+ selectOneChar(-1);
+ m_iCursorPosition = 0;
+ m_iFirstVisibleChar = 0;
+ if(bRepaint)repaintWithCursorOn();
+ KviUserInput::parse(szBuffer,m_pKviWindow);
+ } else {
+ */
+ emit enterPressed();
+ /*
+ return;
+ }
+ */
+}
+
+void KviInputEditor::focusInEvent(QFocusEvent *)
+{
+ if(m_iCursorTimer==0)
+ {
+ m_iCursorTimer = startTimer(KVI_INPUT_BLINK_TIME);
+ m_bCursorOn = true;
+ update();
+ }
+ // XIM handling...
+#ifndef COMPILE_USE_QT4
+ // THIS SEEMS TO BE GONE IN Qt4.x ? (even if the documentation states that it *should* be there)
+ setMicroFocusHint(1,1,width() - 2,height() - 2,true,0);
+#endif
+}
+
+void KviInputEditor::focusOutEvent(QFocusEvent *)
+{
+ if(m_iCursorTimer)killTimer(m_iCursorTimer);
+ m_iCursorTimer = 0;
+ m_bCursorOn = false;
+ update();
+}
+
+
+void KviInputEditor::internalCursorRight(bool bShift)
+{
+ if(m_iCursorPosition >= ((int)(m_szTextBuffer.length())))return;
+ moveRightFirstVisibleCharToShowCursor();
+ //Grow the selection if needed
+ if(bShift)
+ {
+ if((m_iSelectionBegin > -1)&&(m_iSelectionEnd > -1))
+ {
+ if(m_iSelectionEnd == m_iCursorPosition-1)m_iSelectionEnd++;
+ else if(m_iSelectionBegin == m_iCursorPosition)m_iSelectionBegin++;
+ else selectOneChar(m_iCursorPosition);
+ } else selectOneChar(m_iCursorPosition);
+ } else selectOneChar(-1);
+ m_iCursorPosition++;
+}
+
+void KviInputEditor::internalCursorLeft(bool bShift)
+{
+ if(m_iCursorPosition <= 0)return;
+
+ if(bShift)
+ {
+ if((m_iSelectionBegin > -1)&&(m_iSelectionEnd > -1))
+ {
+ if(m_iSelectionBegin == m_iCursorPosition)m_iSelectionBegin--;
+ else if(m_iSelectionEnd == m_iCursorPosition-1)m_iSelectionEnd--;
+ else selectOneChar(m_iCursorPosition - 1);
+ } else selectOneChar(m_iCursorPosition - 1);
+ } else selectOneChar(-1);
+
+ m_iCursorPosition--;
+ if(m_iFirstVisibleChar > m_iCursorPosition)m_iFirstVisibleChar--;
+}
+
+// remember the text before and after the cursor at this point, and put them
+// before and after the text inserted by IM in imEndEvent.
+// hagabaka
+void KviInputEditor::imStartEvent(QIMEvent *e)
+{
+ removeSelected();
+ m_iIMStart = m_iIMSelectionBegin = m_iCursorPosition;
+ m_iIMLength = 0;
+ m_bIMComposing = true;
+ e->accept();
+}
+
+// Whenever the IM's preedit changes, update the visuals and internal data. refer to <http://doc.trolltech.com/3.3/qimevent.html> */
+// hagabaka
+void KviInputEditor::imComposeEvent(QIMEvent *e)
+{
+ // replace the old pre-edit string with e->text()
+ m_bUpdatesEnabled = false;
+#ifdef COMPILE_USE_QT4
+ // Qt 4.x ??????????
+ m_iIMLength = replaceSegment(m_iIMStart, m_iIMLength, e->commitString());
+
+ // update selection inside the pre-edit
+ m_iIMSelectionBegin = m_iIMStart + e->replacementStart();
+ m_iIMSelectionLength = e->replacementLength();
+ moveCursorTo(m_iIMSelectionBegin);
+
+#else
+ m_iIMLength = replaceSegment(m_iIMStart, m_iIMLength, e->text());
+
+ // update selection inside the pre-edit
+ m_iIMSelectionBegin = m_iIMStart + e->cursorPos();
+ m_iIMSelectionLength = e->selectionLength();
+ moveCursorTo(m_iIMSelectionBegin);
+#endif
+
+
+ // repaint
+ m_bUpdatesEnabled = true;
+ repaintWithCursorOn();
+ e->accept();
+}
+
+// Input method is done; put its resulting text to where the preedit area was
+// hagabaka
+void KviInputEditor::imEndEvent(QIMEvent *e)
+{
+ // replace the preedit area with the IM result text
+ m_bUpdatesEnabled = false;
+#ifdef COMPILE_USE_QT4
+ // Qt 4.x ??????????
+ m_iIMLength = replaceSegment(m_iIMStart, m_iIMLength, e->commitString());
+#else
+ m_iIMLength = replaceSegment(m_iIMStart, m_iIMLength, e->text());
+#endif
+
+ // move cursor to after the IM result text
+ moveCursorTo(m_iIMStart + m_iIMLength);
+
+ // repaint
+ m_bUpdatesEnabled = true;
+ repaintWithCursorOn();
+
+ // reset data
+ m_bIMComposing = false;
+ e->accept();
+}
+
+// FIXME According to <http://www.kde.gr.jp/~asaki/how-to-support-input-method.html>, if the XIM
+// style used is OverTheTop, code needs to be added in keyPressEvent handler */
+// hagabaka
+void KviInputEditor::keyPressEvent(QKeyEvent *e)
+{
+ // disable the keyPress handling when IM is in composition.
+ if(m_bIMComposing)
+ {
+ e->ignore();
+ return;
+ }
+ // completion thingies
+
+ if(!m_bReadOnly)
+ {
+ if((e->key() == Qt::Key_Tab) || (e->key() == Qt::Key_BackTab))
+ {
+ completion(e->state() & Qt::ShiftButton);
+ return;
+ } else {
+ m_bLastCompletionFinished=1;
+ }
+ }
+
+
+ if(e->key() == Qt::Key_Escape)
+ {
+ emit escapePressed();
+ return;
+ }
+
+ if((e->state() & Qt::AltButton) || (e->state() & Qt::ControlButton))
+ {
+ switch(e->key())
+ {
+ case Qt::Key_Backspace:
+ if(m_pInputParent->inherits("KviInput"))
+ {
+ ((KviInput*)(m_pInputParent))->multiLinePaste(m_szTextBuffer);
+ clear();
+ return;
+ }
+ break;
+ }
+ }
+
+//Make CtrlKey and CommandKey ("Apple") behave equally on MacOSX.
+//This way typical X11 and Apple shortcuts can be used simultanously within the input line.
+#ifndef Q_OS_MACX
+ if(e->state() & Qt::ControlButton)
+#else
+ if((e->state() & Qt::ControlButton) || (e->state() & Qt::MetaButton))
+#endif
+ {
+ switch(e->key())
+ {
+ case Qt::Key_Right:
+ if(m_iCursorPosition < ((int)(m_szTextBuffer.length())))
+ {
+ // skip whitespace
+ while(m_iCursorPosition < ((int)(m_szTextBuffer.length())))
+ {
+ if(!m_szTextBuffer.at(m_iCursorPosition).isSpace())break;
+ internalCursorRight(e->state() & Qt::ShiftButton);
+ }
+ // skip nonwhitespace
+ while(m_iCursorPosition < ((int)(m_szTextBuffer.length())))
+ {
+ if(m_szTextBuffer.at(m_iCursorPosition).isSpace())break;
+ internalCursorRight(e->state() & Qt::ShiftButton);
+ }
+ repaintWithCursorOn();
+ }
+ break;
+ case Qt::Key_Left:
+ if(m_iCursorPosition > 0)
+ {
+ // skip whitespace
+ while(m_iCursorPosition > 0)
+ {
+ if(!m_szTextBuffer.at(m_iCursorPosition - 1).isSpace())break;
+ internalCursorLeft(e->state() & Qt::ShiftButton);
+ }
+ // skip nonwhitespace
+ while(m_iCursorPosition > 0)
+ {
+ if(m_szTextBuffer.at(m_iCursorPosition - 1).isSpace())break;
+ internalCursorLeft(e->state() & Qt::ShiftButton);
+ }
+ repaintWithCursorOn();
+ }
+ break;
+ case Qt::Key_K:
+ {
+ if(!m_bReadOnly)
+ {
+ insertChar(KVI_TEXT_COLOR);
+ int xPos = xPositionFromCharIndex(m_iCursorPosition);
+ if(xPos > 24)xPos-=24;
+ if(!g_pColorWindow)g_pColorWindow = new KviColorWindow();
+ if(xPos+g_pColorWindow->width() > width())xPos = width()-(g_pColorWindow->width()+2);
+ g_pColorWindow->move(mapToGlobal(QPoint(xPos,-35)));
+ g_pColorWindow->popup(this);
+ }
+ }
+ break;
+ case Qt::Key_B:
+ if(!m_bReadOnly) insertChar(KVI_TEXT_BOLD);
+ break;
+ case Qt::Key_O:
+ if(!m_bReadOnly) insertChar(KVI_TEXT_RESET);
+ break;
+ case Qt::Key_U:
+ if(!m_bReadOnly) insertChar(KVI_TEXT_UNDERLINE);
+ break;
+ case Qt::Key_R:
+ if(!m_bReadOnly) insertChar(KVI_TEXT_REVERSE);
+ break;
+ case Qt::Key_P:
+ if(!m_bReadOnly) insertChar(KVI_TEXT_CRYPTESCAPE); // DO NOT CRYPT THIS STUFF
+ break;
+ case Qt::Key_I:
+ {
+ if(!m_bReadOnly)
+ {
+ insertChar(KVI_TEXT_ICON); // THE NEXT WORD IS AN ICON NAME
+ int xPos = xPositionFromCharIndex(m_iCursorPosition);
+ if(xPos > 24)xPos-=24;
+ if(!g_pTextIconWindow)g_pTextIconWindow = new KviTextIconWindow();
+ if(xPos+g_pTextIconWindow->width() > width())xPos = width()-(g_pTextIconWindow->width()+2);
+ g_pTextIconWindow->move(mapToGlobal(QPoint(xPos,-KVI_TEXTICON_WIN_HEIGHT)));
+ g_pTextIconWindow->popup(this);
+ }
+ }
+ break;
+ case Qt::Key_C:
+ copyToClipboard();
+ break;
+ case Qt::Key_X:
+ if(!m_bReadOnly) cut();
+ break;
+ case Qt::Key_V:
+ if(!m_bReadOnly) pasteClipboardWithConfirmation();
+ break;
+ //case Qt::Key_Backspace:
+ case Qt::Key_W:
+ if(m_iCursorPosition > 0 && !m_bReadOnly && !hasSelection())
+ {
+ // skip whitespace
+ while(m_iCursorPosition > 0)
+ {
+ if(!m_szTextBuffer.at(m_iCursorPosition - 1).isSpace())break;
+ m_szTextBuffer.remove(m_iCursorPosition-1,1);
+ m_iCursorPosition--;
+ if(m_iFirstVisibleChar > m_iCursorPosition)m_iFirstVisibleChar--;
+ }
+ // skip nonwhitespace
+ while(m_iCursorPosition > 0)
+ {
+ if(m_szTextBuffer.at(m_iCursorPosition - 1).isSpace())break;
+ m_szTextBuffer.remove(m_iCursorPosition-1,1);
+ m_iCursorPosition--;
+ if(m_iFirstVisibleChar > m_iCursorPosition)m_iFirstVisibleChar--;
+ }
+ repaintWithCursorOn();
+ }
+ break;
+ case Qt::Key_PageUp:
+ if(KVI_OPTION_BOOL(KviOption_boolDisableInputHistory)) break;
+ if(m_pInputParent->inherits("KviInput"))
+ ((KviInput*)(m_pInputParent))->historyButtonClicked();
+ break;
+ case Qt::Key_F:
+ if(m_pKviWindow)
+ if(m_pKviWindow->view())m_pKviWindow->view()->toggleToolWidget();
+ break;
+ case Qt::Key_A:
+ m_iSelectionBegin=0;
+ m_iSelectionEnd=m_szTextBuffer.length()-1;
+ m_iCursorPosition=m_szTextBuffer.length();
+ repaintWithCursorOn();
+ break;
+ case Qt::Key_Return:
+ case Qt::Key_Enter:
+ if(m_pInputParent->inherits("KviInput"))
+ {
+ QString szBuffer(m_szTextBuffer);
+ m_szTextBuffer="";
+ selectOneChar(-1);
+ m_iCursorPosition = 0;
+ m_iFirstVisibleChar = 0;
+ repaintWithCursorOn();
+ KviUserInput::parseNonCommand(szBuffer,m_pKviWindow);
+ if (!szBuffer.isEmpty())
+ {
+ g_pInputHistory->add(new QString(szBuffer));
+ m_pHistory->insert(0,new QString(szBuffer));
+ }
+
+ __range_valid(KVI_INPUT_MAX_LOCAL_HISTORY_ENTRIES > 1); //ABSOLUTELY NEEDED, if not, pHist will be destroyed...
+ if(m_pHistory->count() > KVI_INPUT_MAX_LOCAL_HISTORY_ENTRIES)m_pHistory->removeLast();
+
+ m_iCurHistoryIdx = -1;
+ }
+ break;
+ default:
+ if(!m_bReadOnly) insertText(e->text());
+ break;
+ }
+ return;
+ }
+
+ if((e->state() & Qt::AltButton) && (e->state() & Qt::Keypad))
+ {
+ // Qt::Key_Meta seems to substitute Qt::Key_Alt on some keyboards
+ if((e->key() == Qt::Key_Alt) || (e->key() == Qt::Key_Meta))
+ {
+ m_szAltKeyCode = "";
+ return;
+ } else if((e->ascii() >= '0') && (e->ascii() <= '9'))
+ {
+ m_szAltKeyCode += e->ascii();
+ return;
+ }
+
+ //debug("%c",e->ascii());
+ if(!m_bReadOnly) {
+ insertText(e->text());
+ }
+ return;
+ }
+
+ if(e->state() & Qt::ShiftButton)
+ {
+ switch(e->key())
+ {
+ case Qt::Key_Insert:
+ if(!m_bReadOnly) pasteClipboardWithConfirmation();
+ return;
+ break;
+ case Qt::Key_PageUp:
+ if(m_pKviWindow)
+ if(m_pKviWindow->view())m_pKviWindow->view()->prevLine();
+ return;
+ break;
+ case Qt::Key_PageDown:
+ if(m_pKviWindow)
+ if(m_pKviWindow->view())m_pKviWindow->view()->nextLine();
+ return;
+ break;
+ }
+ }
+
+ switch(e->key())
+ {
+ case Qt::Key_Right:
+ if(m_iCursorPosition < ((int)(m_szTextBuffer.length())))
+ {
+ internalCursorRight(e->state() & Qt::ShiftButton);
+ repaintWithCursorOn();
+ }
+ break;
+ case Qt::Key_Left:
+ if(m_iCursorPosition > 0)
+ {
+ internalCursorLeft(e->state() & Qt::ShiftButton);
+ repaintWithCursorOn();
+ }
+ break;
+ case Qt::Key_Backspace:
+ if(!m_bReadOnly)
+ {
+ if(hasSelection() && (m_iSelectionEnd >= m_iCursorPosition-1) && (m_iSelectionBegin <= m_iCursorPosition))
+ {
+ //remove the selection
+ m_szTextBuffer.remove(m_iSelectionBegin,(m_iSelectionEnd-m_iSelectionBegin)+1);
+ m_iCursorPosition = m_iSelectionBegin;
+ if(m_iFirstVisibleChar > m_iCursorPosition)m_iFirstVisibleChar = m_iCursorPosition;
+ } else if(m_iCursorPosition > 0) {
+ m_iCursorPosition--;
+ m_szTextBuffer.remove(m_iCursorPosition,1);
+ if(m_iFirstVisibleChar > m_iCursorPosition)m_iFirstVisibleChar--;
+ }
+ selectOneChar(-1);
+ repaintWithCursorOn();
+ }
+ break;
+ case Qt::Key_Delete:
+ if(!m_bReadOnly)
+ {
+ if(hasSelection()) removeSelected();
+ else if(m_iCursorPosition < (int)m_szTextBuffer.length())
+ {
+ m_szTextBuffer.remove(m_iCursorPosition,1);
+ selectOneChar(-1);
+ repaintWithCursorOn();
+ }
+ }
+ break;
+ case Qt::Key_Home:
+ if(m_iCursorPosition > 0)
+ {
+ if(e->state() & Qt::ShiftButton)
+ {
+ if((m_iSelectionBegin == -1)&&(m_iSelectionEnd == -1))m_iSelectionEnd = m_iCursorPosition - 1;
+ m_iSelectionBegin = 0;
+ } else {
+ selectOneChar(-1);
+ }
+ home();
+ }
+ break;
+ case Qt::Key_End://we should call it even the cursor is at the end for deselecting
+ if(e->state() & Qt::ShiftButton)
+ {
+ if((m_iSelectionBegin == -1)&&(m_iSelectionEnd == -1))m_iSelectionBegin = m_iCursorPosition;
+ m_iSelectionEnd = m_szTextBuffer.length()-1;
+ } else {
+ selectOneChar(-1);
+ }
+ end();
+ break;
+ case Qt::Key_Up:
+ if(!m_bReadOnly)
+ {
+ if(m_pHistory->count() > 0)
+ {
+ if(m_iCurHistoryIdx < 0)
+ {
+ m_szSaveTextBuffer = m_szTextBuffer;
+ m_szTextBuffer = *(m_pHistory->at(0));
+ m_iCurHistoryIdx = 0;
+ } else if(m_iCurHistoryIdx >= (int)(m_pHistory->count()-1))
+ {
+ m_szTextBuffer=m_szSaveTextBuffer;
+ m_iCurHistoryIdx = -1;
+ } else {
+ m_iCurHistoryIdx++;
+ m_szTextBuffer = *(m_pHistory->at(m_iCurHistoryIdx));
+ }
+ selectOneChar(-1);
+ if(KVI_OPTION_BOOL(KviOption_boolInputHistoryCursorAtEnd))end();
+ else home();
+ }
+ }
+ break;
+ case Qt::Key_Down:
+ if(!m_bReadOnly)
+ {
+ if(m_pHistory->count() > 0)
+ {
+ if(m_iCurHistoryIdx < 0)
+ {
+ m_szSaveTextBuffer = m_szTextBuffer;
+ m_szTextBuffer = *(m_pHistory->at(m_pHistory->count()-1));
+ m_iCurHistoryIdx =m_pHistory->count()-1;
+ } else if(m_iCurHistoryIdx == 0)
+ {
+ m_szTextBuffer=m_szSaveTextBuffer;
+ m_iCurHistoryIdx = -1;
+ } else {
+ m_iCurHistoryIdx--;
+ m_szTextBuffer = *(m_pHistory->at(m_iCurHistoryIdx));
+ }
+ selectOneChar(-1);
+ if(KVI_OPTION_BOOL(KviOption_boolInputHistoryCursorAtEnd))end();
+ else home();
+ }
+ }
+ break;
+ case Qt::Key_PageUp:
+ if(m_pKviWindow)
+ if(m_pKviWindow->view())m_pKviWindow->view()->prevPage();
+ break;
+ case Qt::Key_PageDown:
+ if(m_pKviWindow)
+ if(m_pKviWindow->view())m_pKviWindow->view()->nextPage();
+ break;
+ case Qt::Key_Return:
+ case Qt::Key_Enter:
+ returnPressed();
+ break;
+ case Qt::Key_Alt:
+ case Qt::Key_Meta:
+ m_szAltKeyCode = "";
+ break;
+ default:
+ if(!e->text().isEmpty() && !m_bReadOnly)
+ insertText(e->text());
+ break;
+ }
+}
+
+void KviInputEditor::keyReleaseEvent(QKeyEvent *e)
+{
+ if((e->key() == Qt::Key_Alt) || (e->key() == Qt::Key_Meta))
+ {
+ if(m_szAltKeyCode.hasData())
+ {
+ bool bOk;
+ unsigned short ch = m_szAltKeyCode.toUShort(&bOk);
+ if(bOk && ch != 0)
+ {
+ //debug("INSERTING CHAR %d",ch);
+ insertChar(QChar(ch));
+ e->accept();
+ }
+ }
+ m_szAltKeyCode = "";
+ }
+ e->ignore();
+}
+
+void KviInputEditor::getWordBeforeCursor(QString &buffer,bool * bIsFirstWordInLine)
+{
+ if(m_szTextBuffer.isEmpty() || m_iCursorPosition <= 0)
+ {
+ buffer = "";
+ return;
+ }
+
+ buffer = m_szTextBuffer.left(m_iCursorPosition);
+
+ int idx = buffer.findRev(' ');
+ int idx2 = buffer.findRev(','); // This is for comma separated lists...
+ int idx3 = buffer.findRev('(');
+ int idx4 = buffer.findRev('"');
+ if(idx2 > idx)idx = idx2;
+ if(idx3 > idx)idx = idx3;
+ if(idx4 > idx)idx = idx4;
+ *bIsFirstWordInLine = false;
+ if(idx > -1)buffer.remove(0,idx+1);
+ else *bIsFirstWordInLine = true;
+}
+
+void KviInputEditor::completion(bool bShift)
+{
+ // FIXME: Spaces in directory completion can mess everything completely
+ // On windows the KVI_PATH_SEPARATOR_CHARacters are breaking everything...
+ // Well.... :D
+
+ QString word;
+ QString match;
+
+ bool bFirstWordInLine;
+ getWordBeforeCursor(word,&bFirstWordInLine);
+ if(word.isEmpty())
+ {
+ if(m_szLastCompletedNick.isEmpty())return; // nothing to complete
+ else {
+ // this is standard nick completion continued
+ standardNickCompletion(bShift,word,bFirstWordInLine);
+ repaintWithCursorOn();
+ return;
+ }
+ }
+ KviPointerList<QString> tmp;
+ tmp.setAutoDelete(true);
+
+ bool bIsCommand = false;
+ bool bIsDir = false;
+ bool bIsNick = false;
+
+ unsigned short uc = word[0].unicode();
+
+ if(uc == '/')
+ {
+ if(bFirstWordInLine)
+ {
+ // command completion
+ word.remove(0,1);
+ if(word.isEmpty())return;
+ KviKvsKernel::instance()->completeCommand(word,&tmp);
+ bIsCommand = true;
+ } else {
+ // directory completion attempt
+ g_pApp->completeDirectory(word,&tmp);
+ bIsDir = true;
+ }
+ } else if(uc == '$')
+ {
+ // function/identifer completion
+ word.remove(0,1);
+ if(word.isEmpty())return;
+ KviKvsKernel::instance()->completeFunction(word,&tmp);
+ } else if(uc == '#' || uc == '&' || uc == '!')
+ {
+ if(m_pKviWindow)
+ {
+ if( (word.length()==1) && (m_pKviWindow->windowName()[0].unicode()==uc))
+ {
+ match=m_pKviWindow->windowName();
+ match.append(" ");
+ replaceWordBeforeCursor(word,match,false);
+ repaintWithCursorOn();
+ return;
+ } else {
+ if(m_pKviWindow->console())
+ m_pKviWindow->console()->completeChannel(word,&tmp);
+ }
+ }
+
+ //FIXME: Complete also on irc:// starting strings, not only irc.?
+ } else if(KviQString::equalCIN(word,"irc.",4))
+ {
+ // irc server name
+ if(m_pKviWindow)
+ if(m_pKviWindow->console())
+ m_pKviWindow->console()->completeServer(word,&tmp);
+ } else {
+ // empty word will end up here
+ if(m_pUserListView)
+ {
+ if(KVI_OPTION_BOOL(KviOption_boolBashLikeNickCompletion))
+ {
+ m_pUserListView->completeNickBashLike(word,&tmp,bShift);
+ bIsNick = true;
+ } else {
+ standardNickCompletion(bShift,word,bFirstWordInLine);
+ repaintWithCursorOn();
+ return;
+ }
+ }
+ }
+
+ // Lookup the longest exact match
+
+ if(tmp.count() > 0)
+ {
+ if(tmp.count() == 1)
+ {
+ match = *(tmp.first());
+ if(bIsCommand)match.append(' ');
+ else if(bIsNick)
+ {
+ if(!KVI_OPTION_STRING(KviOption_stringNickCompletionPostfix).isEmpty())
+ {
+ if(bFirstWordInLine || (!KVI_OPTION_BOOL(KviOption_boolUseNickCompletionPostfixForFirstWordOnly)))
+ match.append(KVI_OPTION_STRING(KviOption_stringNickCompletionPostfix));
+ }
+ }
+ } else {
+ QString all;
+ QString * s = tmp.first();
+ match = *s;
+ int wLen = word.length();
+ for(;s;s = tmp.next())
+ {
+ if(s->length() < match.length())
+ match.remove(s->length(),match.length() - s->length());
+ // All the matches here have length >= word.len()!!!
+ const QChar * b1 = KviQString::nullTerminatedArray(*s) + wLen;
+ const QChar * b2 = KviQString::nullTerminatedArray(match) + wLen;
+ const QChar * c1 = b1;
+ const QChar * c2 = b2;
+ if(bIsDir)while(c1->unicode() && (c1->unicode() == c2->unicode()))c1++,c2++;
+ else while(c1->unicode() && (c1->lower().unicode() == c2->lower().unicode()))c1++,c2++;
+ int len = wLen + (c1 - b1);
+ if(len < ((int)(match.length())))match.remove(len,match.length() - len);
+ if(!all.isEmpty())all.append(", ");
+ all.append(*s);
+ }
+ if(m_pKviWindow)
+ m_pKviWindow->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("%d matches: %Q"),tmp.count(),&all);
+ }
+ } else
+ if(m_pKviWindow)
+ m_pKviWindow->outputNoFmt(KVI_OUT_SYSTEMMESSAGE,__tr2qs("No matches"));
+
+ if(!match.isEmpty())
+ {
+ //if(!bIsDir && !bIsNick)match = match.lower(); <-- why? It is nice to have
+ // $module.someFunctionName instad
+ // of unreadable $module.somefunctionfame
+ replaceWordBeforeCursor(word,match,false);
+ }
+
+ repaintWithCursorOn();
+}
+
+void KviInputEditor::replaceWordBeforeCursor(const QString &word,const QString &replacement,bool bRepaint)
+{
+ selectOneChar(-1);
+ m_iCursorPosition -= word.length();
+ m_szTextBuffer.remove(m_iCursorPosition,word.length());
+ m_szTextBuffer.insert(m_iCursorPosition,replacement);
+ m_szTextBuffer.truncate(m_iMaxBufferSize);
+ moveCursorTo(m_iCursorPosition + replacement.length());
+ if(bRepaint)repaintWithCursorOn();
+}
+
+void KviInputEditor::standardNickCompletion(bool bAddMask,QString &word,bool bFirstWordInLine)
+{
+ // FIXME: this could be really simplified...
+ if(!m_pUserListView)return;
+ selectOneChar(-1);
+
+ QString buffer;
+ if(m_szLastCompletedNick.isEmpty())
+ {
+ // New completion session: we NEED sth to complete
+ if(word.isEmpty())return;
+ if(m_pUserListView->completeNickStandard(word,m_szLastCompletedNick,buffer,bAddMask))
+ {
+ // completed: save the buffer
+ m_szLastCompletionBuffer = m_szTextBuffer;
+ m_iLastCompletionCursorPosition = m_iCursorPosition;
+ m_iLastCompletionCursorXPosition = m_iLastCursorXPosition;
+ m_iLastCompletionFirstVisibleChar = m_iFirstVisibleChar;
+ m_szLastCompletedNick = buffer;
+ if(!KVI_OPTION_STRING(KviOption_stringNickCompletionPostfix).isEmpty())
+ {
+ if(bFirstWordInLine || (!KVI_OPTION_BOOL(KviOption_boolUseNickCompletionPostfixForFirstWordOnly)))
+ buffer.append(KVI_OPTION_STRING(KviOption_stringNickCompletionPostfix));
+ }
+ replaceWordBeforeCursor(word,buffer,false);
+ m_bLastCompletionFinished=0;
+ // REPAINT CALLED FROM OUTSIDE!
+ } // else no match at all
+ } else if(!m_bLastCompletionFinished) {
+ // Old session
+ // swap the buffers
+ m_szTextBuffer = m_szLastCompletionBuffer;
+ m_iCursorPosition = m_iLastCompletionCursorPosition;
+ m_iLastCursorXPosition = m_iLastCompletionCursorXPosition;
+ m_iFirstVisibleChar = m_iLastCompletionFirstVisibleChar;
+ // re-extract
+ //word = m_szTextBuffer.left(m_iCursorPosition);
+
+ getWordBeforeCursor(word,&bFirstWordInLine);
+ if(word.isEmpty())return;
+ if(m_pUserListView->completeNickStandard(word,m_szLastCompletedNick,buffer,bAddMask))
+ {
+ // completed
+ m_szLastCompletedNick = buffer;
+ if(!KVI_OPTION_STRING(KviOption_stringNickCompletionPostfix).isEmpty())
+ {
+ if(bFirstWordInLine || (!KVI_OPTION_BOOL(KviOption_boolUseNickCompletionPostfixForFirstWordOnly)))
+ buffer.append(KVI_OPTION_STRING(KviOption_stringNickCompletionPostfix));
+ }
+ replaceWordBeforeCursor(word,buffer,false);
+ m_bLastCompletionFinished=0;
+ // REPAINT CALLED FROM OUTSIDE!
+ } else {
+ m_bLastCompletionFinished=1;
+ m_szLastCompletedNick = "";
+ }
+ } else {
+ // Old session finished
+ // re-extract
+ //word = m_szTextBuffer.left(m_iCursorPosition);
+ //getWordBeforeCursor(word,&bFirstWordInLine);
+ if(word.isEmpty())return;
+ if(m_pUserListView->completeNickStandard(word,"",buffer,bAddMask))
+ {
+ // completed
+ m_szLastCompletionBuffer = m_szTextBuffer;
+ m_iLastCompletionCursorPosition = m_iCursorPosition;
+ m_iLastCompletionCursorXPosition = m_iLastCursorXPosition;
+ m_iLastCompletionFirstVisibleChar = m_iFirstVisibleChar;
+ m_szLastCompletedNick = buffer;
+ if(!KVI_OPTION_STRING(KviOption_stringNickCompletionPostfix).isEmpty())
+ {
+ if(bFirstWordInLine || (!KVI_OPTION_BOOL(KviOption_boolUseNickCompletionPostfixForFirstWordOnly)))
+ buffer.append(KVI_OPTION_STRING(KviOption_stringNickCompletionPostfix));
+ }
+ replaceWordBeforeCursor(word,buffer,false);
+ m_bLastCompletionFinished=0;
+ // REPAINT CALLED FROM OUTSIDE!
+ } else {
+ m_bLastCompletionFinished=1;
+ m_szLastCompletedNick = "";
+ }
+ }
+}
+
+
+//Funky helpers
+
+void KviInputEditor::end()
+{
+ m_iLastCursorXPosition = frameWidth();
+ m_iCursorPosition = 0;
+ m_iFirstVisibleChar = 0;
+ while(m_iCursorPosition < ((int)(m_szTextBuffer.length())))
+ {
+ moveRightFirstVisibleCharToShowCursor();
+ m_iCursorPosition++;
+ }
+ repaintWithCursorOn();
+}
+
+void KviInputEditor::home()
+{
+ m_iFirstVisibleChar = 0;
+ m_iCursorPosition = 0;
+ repaintWithCursorOn();
+}
+
+void KviInputEditor::insertChar(QChar c)
+{
+ if(m_szTextBuffer.length() >= m_iMaxBufferSize)return;
+
+ // Kill the selection
+ if((m_iSelectionBegin > -1) || (m_iSelectionEnd > -1))
+ {
+ if((m_iCursorPosition >= m_iSelectionBegin) && (m_iCursorPosition <= m_iSelectionEnd))
+ {
+ m_bUpdatesEnabled = false;
+ removeSelected();
+ m_bUpdatesEnabled = true;
+ }
+ }
+ selectOneChar(-1);
+ m_szTextBuffer.insert(m_iCursorPosition,c);
+ moveRightFirstVisibleCharToShowCursor();
+ m_iCursorPosition++;
+ repaintWithCursorOn();
+}
+
+void KviInputEditor::moveRightFirstVisibleCharToShowCursor()
+{
+ // :)
+ QFontMetrics fm(KVI_OPTION_FONT(KviOption_fontInput));
+
+ QChar c = m_szTextBuffer.at(m_iCursorPosition);
+
+#ifdef COMPILE_USE_QT4
+ m_iLastCursorXPosition += c.unicode() < 32 ? fm.width(getSubstituteChar(c.unicode())) + 3 : fm.width(c);;
+#else
+ m_iLastCursorXPosition += (c.unicode() < 256) ? g_iInputFontCharWidth[c.unicode()] : fm.width(c);
+#endif
+ while(m_iLastCursorXPosition >= contentsRect().width()-2*KVI_INPUT_MARGIN)
+ {
+ c = m_szTextBuffer.at(m_iFirstVisibleChar);
+#ifdef COMPILE_USE_QT4
+ m_iLastCursorXPosition -= c.unicode() < 32 ? fm.width(getSubstituteChar(c.unicode())) + 3 : fm.width(c);;
+#else
+ m_iLastCursorXPosition -= (c.unicode() < 256) ? g_iInputFontCharWidth[c.unicode()] : fm.width(c);
+#endif
+ m_iFirstVisibleChar++;
+ }
+}
+
+void KviInputEditor::repaintWithCursorOn()
+{
+ // :)
+ if(m_bUpdatesEnabled)
+ {
+ m_bCursorOn = true;
+ update();
+ }
+}
+
+void KviInputEditor::selectOneChar(int pos)
+{
+ m_iSelectionBegin = pos;
+ m_iSelectionEnd = pos;
+}
+
+int KviInputEditor::charIndexFromXPosition(int xPos)
+{
+ int curXPos = frameWidth()+KVI_INPUT_MARGIN;
+ int curChar = m_iFirstVisibleChar;
+ int bufLen = m_szTextBuffer.length();
+
+ QFontMetrics fm(KVI_OPTION_FONT(KviOption_fontInput));
+ while(curChar < bufLen)
+ {
+ QChar c = m_szTextBuffer.at(curChar);
+#ifdef COMPILE_USE_QT4
+ int widthCh = c.unicode() < 32 ? fm.width(getSubstituteChar(c.unicode())) + 3 : fm.width(c);;
+#else
+ int widthCh = (c.unicode() < 256) ? g_iInputFontCharWidth[c.unicode()] : fm.width(c);
+#endif
+ if(xPos < (curXPos+(widthCh/2)))return curChar;
+ else if(xPos < (curXPos+widthCh))return (curChar+1);
+ {
+ curXPos+=widthCh;
+ curChar++;
+ }
+ }
+ return curChar;
+}
+
+int KviInputEditor::xPositionFromCharIndex(QFontMetrics& fm,int chIdx,bool bContentsCoords)
+{
+ // FIXME: this could use fm.width(m_szTextBuffer,chIdx)
+ int curXPos = bContentsCoords ? KVI_INPUT_MARGIN : frameWidth()+KVI_INPUT_MARGIN;
+ int curChar = m_iFirstVisibleChar;
+ while(curChar < chIdx)
+ {
+ QChar c = m_szTextBuffer.at(curChar);
+#ifdef COMPILE_USE_QT4
+ curXPos += c.unicode() < 32 ? fm.width(getSubstituteChar(c.unicode())) + 3 : fm.width(c);;
+#else
+ curXPos += (c.unicode() < 256) ? g_iInputFontCharWidth[c.unicode()] : fm.width(c);
+#endif
+ curChar++;
+ }
+ return curXPos;
+}
+
+int KviInputEditor::xPositionFromCharIndex(int chIdx,bool bContentsCoords)
+{
+ // FIXME: this could use fm.width(m_szTextBuffer,chIdx)
+ int curXPos = bContentsCoords ? KVI_INPUT_MARGIN : frameWidth()+KVI_INPUT_MARGIN;
+ int curChar = m_iFirstVisibleChar;
+ //debug("%i",g_pLastFontMetrics);
+ if(!g_pLastFontMetrics) g_pLastFontMetrics = new QFontMetrics(KVI_OPTION_FONT(KviOption_fontInput));
+ while(curChar < chIdx)
+ {
+ QChar c = m_szTextBuffer.at(curChar);
+#ifdef COMPILE_USE_QT4
+ curXPos += c.unicode() < 32 ? g_pLastFontMetrics->width(getSubstituteChar(c.unicode())) + 3 : g_pLastFontMetrics->width(c);
+#else
+ curXPos += (c.unicode() < 256) ? g_iInputFontCharWidth[c.unicode()] : g_pLastFontMetrics->width(c);
+#endif
+ curChar++;
+ }
+ return curXPos;
+}
+
+/*
+ @doc: texticons
+ @type:
+ generic
+ @title:
+ The KVIrc TextIcons extension
+ @short:
+ The KVIrc TextIcons extension
+ @body:
+ Starting from version 3.0.0 KVIrc supports the TextIcon extension
+ to the standard IRC protocol. It is a mean for sending text enriched
+ of small images without sending the images themselves.[br]
+ The idea is quite simple: the IRC client (and it's user) associates
+ some small images to text strings (called icon tokens) and the strings are sent
+ in place of the images preceeded by a special escape character.[br]
+ The choosen escape character is 29 (hex 0x1d) which corresponds
+ to the ASCII group separator.[br]
+ So for example if a client has the association of the icon token "rose" with a small
+ icon containing a red rose flower then KVIrc could send the string
+ "&lt;0x1d&gt;rose" in the message stream to ask the remote parties to
+ display such an icon. If the remote parties don't have this association
+ then they will simply strip the control code and display the string "rose",
+ (eventually showing it in some enchanced way).[br]
+ The icon tokens can't contain spaces
+ so the receiving clients stop the extraction of the icon strings
+ when a space, an icon escape or the message termination is encountered.
+ [br]
+ &lt;icon escape&gt; := character 0x1d (ASCII group separator)[br]
+ &lt;icon token&gt; := any character with the exception of 0x1d, CR,LF and SPACE.[br]
+ [br]
+ Please note that this is a KVIrc extension and the remote clients
+ that don't support this feature will not display the icon (and will
+ eventually show the 0x1d character in the data stream).[br]
+ If you like this feature please either convince the remote users
+ to try KVIrc or tell them to write to their client developers asking
+ for this simple feature to be implemented.[br]
+*/
+
+
+/*
+ @doc: commandline
+ @title:
+ The Commandline Input Features
+ @type:
+ generic
+ @short:
+ Commandline input features
+ @body:
+ [big]Principles of operation[/big]
+ [p]
+ The idea is simple: anything that starts with a slash (/) character
+ is interpreted as a command. Anything else is plain text that is
+ sent to the target of the window (channel, query, dcc chat etc..).
+ [/p]
+ [big]The two operating modes[/big]
+ [p]
+ The commandline input has two operating modes: the "user friendly mode" and
+ the "kvs mode". In the user friendly mode all the parameters of the commands
+ are interpreted exactly like you type them. There is no special interpretation
+ of $,%,-,( and ; characters. This allows you to type "/me is happy ;)", for example.
+ In the kvs mode the full parameter interpretation is enabled and the commands
+ work just like in any other script editor. This means that anything that
+ starts with a $ is a function call, anything that starts with a % is a variable,
+ the dash characters after command names are interpreted as switches and ; is the
+ command separator. This in turn does NOT allow you to type "/me is happy ;)"
+ because ; is the command separator and ) will be interpreted as the beginning
+ of the next command. In KVS mode you obviously have to escape the ; character
+ by typing "/me is happy \;)". The user friendly mode is good for everyday chatting
+ and for novice users while the KVS mode is for experts that know that minimum about
+ scripting languages. Please note that in the user-friendly mode you're not allowed
+ to type multiple commands at once :).
+ [/p]
+ [big]Default Key Bindings:[/big][br]
+ Ctrl+B: Inserts the 'bold' mIRC text control character<br>
+ Ctrl+K: Inserts the 'color' mIRC text control character<br>
+ Ctrl+R: Inserts the 'reverse' mIRC text control character<br>
+ Ctrl+U: Inserts the 'underline' mIRC text control character<br>
+ Ctrl+O: Inserts the 'reset' mIRC text control character<br>
+ Ctrl+P: Inserts the 'non-crypt' (plain text) KVIrc control character used to disable encryption of the current text line<br>
+ Ctrl+C: Copies the selected text to clipboard<br>
+ Ctrl+X: Cuts the selected text<br>
+ Ctrl+V: Pastes the clipboard contents (same as middle mouse click)<br>
+ Ctrl+I: Inserts the 'icon' control code and pops up the icon list box<br>
+ Ctrl+A: Select all<br>
+ CursorUp: Moves backward in the command history<br>
+ CursorDown: Moves forward in the command history<br>
+ CursorRight: Moves the cursor to the right<br>
+ CursorLeft: Moves the cursor to the left :)<br>
+ Shift+CursorLeft: Moves the selection to the left<br>
+ Shift+RightCursor: Moves the selection to the right<br>
+ Ctrl+CursorLeft: Moves the cursor one word left<br>
+ Ctrl+CursorRight: Moves the cursor one word right<br>
+ Ctrl+Shift+CursorLeft: Moves the selection one word left<br>
+ Ctrl+Shift+CursorRight: Moves the selection one word right<br>
+ Tab: Nickname, function/command, or filename completion (see below)<br>
+ Shift+Tab: Hostmask or function/command completion (see below)<br>
+ Alt+&lt;numeric_sequence&gt;: Inserts the character by ASCII/Unicode code<br>
+ <example>
+ Alt+32: Inserts ASCII/Unicode character 32: ' ' (a space)
+ Alt+00032: Same as above :)
+ Alt+13: Inserts the Carriage Return (CR) control character
+ Alt+77: Inserts ASCII/Unicode character 77: 'M'
+ Alt+23566: Inserts Unicode character 23566 (an ideogram)
+ </example>
+ Also look at the <a href="shortcuts.kvihelp">global shortcuts</a> reference.<br>
+ If you drop a file on this widget, a <a href="parse.kvihelp">/PARSE &lt;filename&gt;</a> will be executed.<br>
+ You can enable word substitution in the preferences dialog.<br>
+ For example, if you choose to substitute "afaik" with "As far as I know",<br>
+ when you will type "afaik" somewhere in the command line, and then
+ press Space or Return, that word will be replaced with "As far as I know".<br>
+ Experiment with it :)<br>
+ The Tab key activates the completion of the current word.<br>
+ If a word is prefixed with a '/', it is treated as a command to be completed,
+ if it begins with '$', it is treated as a function or identifier to be completed,
+ otherwise it is treated as a nickname or filename to be completed.<br>
+ <example>
+ /ec&lt;Tab&gt; will produce /echo&lt;space&gt
+ /echo $loca&lt;Tab&gt; will produce /echo $localhost
+ </example>
+ Multiple matches are listed in the view window and the word is completed
+ to the common part of all the matches.<br>
+ <example>
+ $sel&lt;Tab;&gt; will find multiple matches and produce $selected
+ </example>
+ Experiment with that too :)
+*/
+
+
+
+KviInput::KviInput(KviWindow *par,KviUserListView * view)
+: QWidget(par,"input")
+{
+ QBoxLayout* pLayout=new QHBoxLayout(this);
+ pLayout->setAutoAdd(true);
+ pLayout->setDirection(QBoxLayout::RightToLeft);
+
+ pLayout->setMargin(0);
+ pLayout->setSpacing(0);
+
+ m_pWindow = par;
+ m_pMultiLineEditor = 0;
+
+ m_pHideToolsButton = new KviStyledToolButton(this,"hide_container_button");
+
+ m_pHideToolsButton->setUsesBigPixmap(false);
+ m_pHideToolsButton->setFixedWidth(10);
+
+ if(g_pIconManager->getBigIcon("kvi_horizontal_left.png"))
+ m_pHideToolsButton->setPixmap(*(g_pIconManager->getBigIcon("kvi_horizontal_left.png")));
+
+ connect(m_pHideToolsButton,SIGNAL(clicked()),this,SLOT(toggleToolButtons()));
+
+ m_pButtonContainer=new KviTalHBox(this);
+ m_pButtonContainer->setSpacing(0);
+
+#ifdef COMPILE_USE_QT4
+ m_pButtonContainer->setSizePolicy(QSizePolicy(QSizePolicy::Minimum,QSizePolicy::Preferred));
+// if(m_pButtonContainer->layout())
+// m_pButtonContainer->layout()->setSizeConstraint(QLayout::SetMinimumSize);
+#endif
+
+ m_pHistoryButton = new KviStyledToolButton(m_pButtonContainer,"historybutton");
+ m_pHistoryButton->setUsesBigPixmap(false);
+ //m_pHistoryButton->setUpdatesEnabled(TRUE); ???
+ QIconSet is1;
+ if(!KVI_OPTION_BOOL(KviOption_boolDisableInputHistory))//G&N mar 2005
+ {
+ is1.setPixmap(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TIME)),QIconSet::Small);
+ m_pHistoryButton->setIconSet(is1);
+ KviTalToolTip::add(m_pHistoryButton,__tr2qs("Show History<br>&lt;Ctrl+PageUp&gt;"));
+ connect(m_pHistoryButton,SIGNAL(clicked()),this,SLOT(historyButtonClicked()));
+ }
+ else
+ {
+ is1.setPixmap(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_QUITSPLIT)),QIconSet::Small);
+ m_pHistoryButton->setIconSet(is1);
+ KviTalToolTip::add(m_pHistoryButton,__tr2qs("Input History Disabled"));
+ }
+
+ m_pIconButton = new KviStyledToolButton(m_pButtonContainer,"iconbutton");
+ m_pIconButton->setUsesBigPixmap(false);
+ QIconSet is3;
+ is3.setPixmap(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_BIGGRIN)),QIconSet::Small);
+ m_pIconButton->setIconSet(is3);
+ KviTalToolTip::add(m_pIconButton,__tr2qs("Show Icons Popup<br>&lt;Ctrl+I&gt;<br>See also /help texticons"));
+
+ connect(m_pIconButton,SIGNAL(clicked()),this,SLOT(iconButtonClicked()));
+
+
+ m_pCommandlineModeButton = new KviStyledToolButton(m_pButtonContainer,"commandlinemodebutton");
+ m_pCommandlineModeButton->setUsesBigPixmap(false);
+ m_pCommandlineModeButton->setToggleButton(true);
+ QIconSet is0;
+ is0.setPixmap(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_SAYSMILE)),QIconSet::Small,QIconSet::Normal,QIconSet::On);
+ is0.setPixmap(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_SAYKVS)),QIconSet::Small,QIconSet::Normal,QIconSet::Off);
+ m_pCommandlineModeButton->setIconSet(is0);
+ KviTalToolTip::add(m_pCommandlineModeButton,__tr2qs("User friendly commandline mode<br>See also /help commandline"));
+ if(KVI_OPTION_BOOL(KviOption_boolCommandlineInUserFriendlyModeByDefault))
+ m_pCommandlineModeButton->setOn(true);
+
+
+ m_pMultiEditorButton = new KviStyledToolButton(m_pButtonContainer,"multieditorbutton");
+ m_pMultiEditorButton->setToggleButton(true);
+ m_pMultiEditorButton->setUsesBigPixmap(false);
+ QIconSet is2;
+ is2.setPixmap(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TERMINAL)),QIconSet::Small,QIconSet::Normal,QIconSet::On);
+ is2.setPixmap(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TERMINAL)),QIconSet::Small,QIconSet::Normal,QIconSet::Off);
+ m_pMultiEditorButton->setIconSet(is2);
+ QString szTip = __tr2qs("Multi-line Editor<br>&lt;Alt+Backspace&gt;");
+ szTip += " - &lt;Ctrl+Backspace&gt;";
+ KviTalToolTip::add(m_pMultiEditorButton,szTip);
+
+ connect(m_pMultiEditorButton,SIGNAL(toggled(bool)),this,SLOT(multilineEditorButtonToggled(bool)));
+
+ m_pInputEditor = new KviInputEditor(this,par,view);
+ connect(m_pInputEditor,SIGNAL(enterPressed()),this,SLOT(inputEditorEnterPressed()));
+#ifdef COMPILE_USE_QT4
+ m_pInputEditor->setSizePolicy(QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Ignored));
+#else
+ m_pInputEditor->setSizePolicy(QSizePolicy(QSizePolicy::Ignored,QSizePolicy::Ignored));
+#endif
+
+
+#ifdef COMPILE_USE_QT4
+ m_pMultiEditorButton->setAutoRaise(true);
+ m_pCommandlineModeButton->setAutoRaise(true);
+ m_pIconButton->setAutoRaise(true);
+ m_pHistoryButton->setAutoRaise(true);
+ m_pHideToolsButton->setAutoRaise(true);
+#endif
+
+ pLayout->setStretchFactor(m_pInputEditor,100000);
+ pLayout->setStretchFactor(m_pButtonContainer,0);
+ pLayout->setStretchFactor(m_pHideToolsButton,0);
+}
+
+KviInput::~KviInput()
+{
+ if(m_pMultiLineEditor)KviScriptEditor::destroyInstance(m_pMultiLineEditor);
+}
+
+bool KviInput::isButtonsHidden()
+{
+ return m_pButtonContainer->isHidden();
+}
+
+void KviInput::setButtonsHidden(bool bHidden)
+{
+ if(!m_pHideToolsButton || !m_pButtonContainer) return;
+ if(bHidden==m_pButtonContainer->isHidden()) return;
+ m_pButtonContainer->setHidden(bHidden);
+ QPixmap* pix= bHidden ?
+ g_pIconManager->getBigIcon("kvi_horizontal_right.png") :
+ g_pIconManager->getBigIcon("kvi_horizontal_left.png");
+ if(pix)
+ m_pHideToolsButton->setPixmap(*pix);
+}
+
+void KviInput::toggleToolButtons()
+{
+ setButtonsHidden(!isButtonsHidden());
+}
+
+void KviInput::inputEditorEnterPressed()
+{
+ QString szText = m_pInputEditor->text();
+ KviUserInput::parse(szText,m_pWindow,QString::null,m_pCommandlineModeButton->isOn());
+ m_pInputEditor->setText("");
+}
+
+void KviInput::keyPressEvent(QKeyEvent *e)
+{
+ //debug("KviInput::keyPressEvent(key:%d,state:%d,text:%s)",e->key(),e->state(),e->text().isEmpty() ? "empty" : e->text().utf8().data());
+
+ if((e->state() & Qt::ControlButton) || (e->state() & Qt::AltButton) || (e->state() & Qt::MetaButton))
+ {
+ switch(e->key())
+ {
+ case Qt::Key_Backspace:
+ //if(m_pMultiLineEditor)
+ multilineEditorButtonToggled(!m_pMultiLineEditor);
+ break;
+ }
+ }
+
+ if(e->state() & Qt::ControlButton)
+ {
+ switch(e->key())
+ {
+ case Qt::Key_Enter:
+ case Qt::Key_Return:
+ {
+ if(m_pMultiLineEditor)
+ {
+ QString szText;
+ m_pMultiLineEditor->getText(szText);
+ if(szText.isEmpty())return;
+ if(KVI_OPTION_BOOL(KviOption_boolWarnAboutPastingMultipleLines))
+ {
+ if(szText.length() > 256)
+ {
+ if(szText[0] != '/')
+ {
+#ifdef COMPILE_USE_QT4
+ int nLines = szText.count('\n') + 1;
+#else
+ int nLines = szText.contains('\n') + 1;
+#endif
+ if(nLines > 15)
+ {
+ int nRet = QMessageBox::question(
+ this,
+ __tr2qs("Confirm Multiline Message"),
+ __tr2qs("You're about to send a message with %1 lines of text.<br><br>" \
+ "There is nothing wrong with it, this warning is<br>" \
+ "here to prevent you from accidentally sending<br>" \
+ "a really large message just because you didn't edit it<br>" \
+ "properly after pasting text from the clipboard.<br><br>" \
+ "Do you want the message to be sent?").arg(nLines),
+ __tr2qs("Yes, always"),
+ __tr2qs("Yes"),
+ __tr2qs("No"),
+ 1,2);
+ switch(nRet)
+ {
+ case 0:
+ KVI_OPTION_BOOL(KviOption_boolWarnAboutPastingMultipleLines) = false;
+ break;
+ case 2:
+ return;
+ break;
+ default: // also case 1
+ break;
+ }
+ }
+ }
+ }
+ }
+ KviUserInput::parse(szText,m_pWindow,QString::null,m_pCommandlineModeButton->isOn());
+ m_pMultiLineEditor->setText("");
+ }
+ }
+ break;
+ case Qt::Key_PageUp:
+ historyButtonClicked();
+ break;
+ }
+ }
+}
+
+void KviInput::multiLinePaste(const QString &text)
+{
+ if(!m_pMultiLineEditor)multilineEditorButtonToggled(true);
+ m_pMultiLineEditor->setText(text);
+}
+
+void KviInput::multilineEditorButtonToggled(bool bOn)
+{
+ if(m_pMultiLineEditor)
+ {
+ if(bOn)return;
+ KviScriptEditor::destroyInstance(m_pMultiLineEditor);
+ m_pMultiLineEditor = 0;
+ m_pInputEditor->show();
+ m_pWindow->childrenTreeChanged(0);
+ m_pInputEditor->setFocus();
+ m_pMultiEditorButton->setOn(false);
+ } else {
+ if(!bOn)return;
+ m_pMultiLineEditor = KviScriptEditor::createInstance(this);
+ QString szText = __tr2qs("<Ctrl+Return>; submits, <Alt+Backspace>; hides this editor");
+ // compatibility entry to avoid breaking translation just before a release... :)
+ szText.replace("Alt+Backspace","Ctrl+Backspace");
+ m_pMultiLineEditor->setFindText(szText);
+ m_pMultiLineEditor->setFindLineeditReadOnly(true);
+ m_pInputEditor->hide();
+ m_pMultiLineEditor->show();
+ m_pWindow->childrenTreeChanged(m_pMultiLineEditor);
+ m_pMultiLineEditor->setFocus();
+ m_pMultiEditorButton->setOn(true);
+ }
+}
+
+void KviInput::iconButtonClicked()
+{
+ if(!g_pTextIconWindow)g_pTextIconWindow = new KviTextIconWindow();
+ QPoint pnt = m_pIconButton->mapToGlobal(QPoint(m_pIconButton->width(),0));
+ g_pTextIconWindow->move(pnt.x()-g_pTextIconWindow->width(),pnt.y() - g_pTextIconWindow->height());
+ g_pTextIconWindow->popup(this,true);
+}
+
+void KviInput::historyButtonClicked()
+{
+ if(!g_pHistoryWindow)g_pHistoryWindow = new KviHistoryWindow();
+
+ QPoint pnt = mapToGlobal(QPoint(0,0));
+
+ g_pHistoryWindow->setGeometry(pnt.x(),pnt.y() - KVI_HISTORY_WIN_HEIGHT,width(),KVI_HISTORY_WIN_HEIGHT);
+ g_pHistoryWindow->popup(this);
+}
+
+#define BUTTON_WIDTH 20
+
+/*void KviInput::resizeEvent(QResizeEvent *e)
+{
+ //m_pButtonContainer
+ m_pInputEditor->setGeometry(0,0,m_pButtonContainer->isVisible() ? width() - (BUTTON_WIDTH * 4)-10 : width() - 10,height());
+ if(m_pMultiLineEditor)m_pMultiLineEditor->setGeometry(0,0,m_pButtonContainer->isVisible() ? width() - (BUTTON_WIDTH * 4)-10 : width() - 10,height());
+ if(m_pButtonContainer->isVisible()) m_pButtonContainer->setGeometry(width() - (BUTTON_WIDTH * 4)-10,0,BUTTON_WIDTH*4,height());
+
+ m_pHideToolsButton->setGeometry(width() - 10,0,10,height());
+
+ QWidget::resizeEvent(e);
+}*/
+
+void KviInput::setFocus()
+{
+ // redirect setFocus() to the right children
+ if(m_pMultiLineEditor)m_pMultiLineEditor->setFocus();
+ else m_pInputEditor->setFocus();
+}
+
+void KviInput::focusInEvent(QFocusEvent * e)
+{
+ // if we get a focus in event , redirect the focus to the children
+ if(m_pMultiLineEditor)m_pMultiLineEditor->setFocus();
+ else m_pInputEditor->setFocus();
+}
+
+
+int KviInput::heightHint() const
+{
+ return m_pMultiLineEditor ? 120 : m_pInputEditor->heightHint();
+}
+
+void KviInput::setText(const QString &text)
+{
+ // FIXME: Latin1 -> QString ?
+ if(m_pMultiLineEditor)m_pMultiLineEditor->setText(text);
+ else m_pInputEditor->setText(text);
+}
+
+void KviInput::insertChar(char c)
+{
+ m_pInputEditor->insertChar(c);
+}
+
+void KviInput::insertText(const QString& text)
+{
+ m_pInputEditor->insertText(text);
+}
+
+void KviInput::applyOptions()
+{
+ if(g_pLastFontMetrics) delete g_pLastFontMetrics;
+ g_pLastFontMetrics = 0;
+
+ if(KVI_OPTION_BOOL(KviOption_boolDisableInputHistory))//G&N mar 2005
+ {
+ QIconSet is1;
+ is1.setPixmap(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_QUITSPLIT)),QIconSet::Small);
+ m_pHistoryButton->setIconSet(is1);
+ KviTalToolTip::add(m_pHistoryButton,__tr2qs("Input History Disabled"));
+ m_pHistoryButton->disconnect(SIGNAL(clicked()));
+ }
+
+ if(!KVI_OPTION_BOOL(KviOption_boolDisableInputHistory))
+ {
+ QIconSet is1;
+ is1.setPixmap(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TIME)),QIconSet::Small);
+ m_pHistoryButton->setIconSet(is1);
+ KviTalToolTip::add(m_pHistoryButton,__tr2qs("Show History<br>&lt;Ctrl+PageUp&gt;"));
+ connect(m_pHistoryButton,SIGNAL(clicked()),this,SLOT(historyButtonClicked()));
+ }
+
+ m_pInputEditor->applyOptions();
+}
+
+void KviInput::setFocusProxy(QWidget *)
+{
+ /* do nothing */
+}
+
+//const QString & KviInput::text()
+QString KviInput::text()
+{
+ QString szText;
+ if(m_pMultiLineEditor)
+ m_pMultiLineEditor->getText(szText);
+ else
+ szText=m_pInputEditor->text();
+ return szText;
+}
+
+#include "kvi_input.moc"
diff --git a/src/kvirc/ui/kvi_input.h b/src/kvirc/ui/kvi_input.h
new file mode 100644
index 00000000..56ec5070
--- /dev/null
+++ b/src/kvirc/ui/kvi_input.h
@@ -0,0 +1,262 @@
+#ifndef _KVI_INPUT_H_
+#define _KVI_INPUT_H_
+
+//=============================================================================
+//
+// File : kvi_input.h
+// Creation date : Sun Jan 3 1999 23:04:10 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+
+#include <qwidget.h>
+#include "kvi_tal_hbox.h"
+#include <qpixmap.h>
+#include "kvi_pointerlist.h"
+
+#include "kvi_string.h"
+
+//#include <qdialog.h>
+#include <qtoolbutton.h>
+
+class KviUserListView;
+class KviWindow;
+class KviInput;
+class KviTalHBox;
+class QFontMetrics;
+
+// Default maximum buffer size.
+#define KVI_INPUT_MAX_BUFFER_SIZE 400
+// Border , better do not touch this
+#define KVI_INPUT_BORDER 1
+#define KVI_INPUT_MARGIN 2
+// Cursor blink time...just don't set it to a value less than 100 if
+// you don't want to be lagged by your cursors :)
+#define KVI_INPUT_BLINK_TIME 800
+// Drag scroll speed...(smaller values = faster)
+#define KVI_INPUT_DRAG_TIMEOUT 80
+// Maximum entries in the history buffer
+#define KVI_INPUT_MAX_HISTORY_ENTRIES 100
+
+class KVIRC_API KviInputHistory
+{
+public:
+ KviInputHistory();
+ ~KviInputHistory();
+protected:
+ KviPointerList<QString> * m_pStringList;
+public:
+ void add(QString * s);
+ KviPointerList<QString> * list(){ return m_pStringList; };
+ void save(const char * filename);
+ void load(const char * filename);
+};
+
+#ifdef COMPILE_USE_QT4
+ #define QIMEvent QInputMethodEvent
+#endif
+
+class KVIRC_API KviInputEditor : public QFrame
+{
+ // friend class KviUserParser;
+ //Q_PROPERTY( int KviProperty_FocusOwner READ heightHint )
+ Q_PROPERTY( int TransparencyCapable READ heightHint )
+
+ Q_OBJECT
+public:
+ KviInputEditor(QWidget * par,KviWindow *wnd,KviUserListView * view = 0);
+ ~KviInputEditor();
+protected:
+
+ QString m_szTextBuffer;
+ int m_iCursorPosition;
+ int m_iFirstVisibleChar;
+ int m_iSelectionBegin;
+ int m_iSelectionEnd;
+ int m_iMaxBufferSize;
+ bool m_bSpSlowFlag; // <-- what is this ?
+
+ // members for supporting input methods
+ QString m_szIMText;
+ int m_iIMStart;
+ int m_iIMLength;
+ int m_iIMSelectionBegin;
+ int m_iIMSelectionLength;
+ bool m_bIMComposing;
+
+ unsigned char m_iCurFore;
+ unsigned char m_iCurBack;
+ bool m_bCurBold;
+ bool m_bCurUnderline;
+
+ int m_iBlockLen;
+ int m_iBlockWidth;
+ bool m_bControlBlock;
+
+ bool m_bCursorOn;
+
+ int m_iCursorTimer;
+ int m_iDragTimer;
+
+ int m_iLastCursorXPosition;
+ int m_iSelectionAnchorChar;
+
+ // History stuff
+ KviPointerList<QString> * m_pHistory;
+ int m_iCurHistoryIdx;
+
+ KviStr m_szSaveTextBuffer;
+
+ // Nick completion
+ KviUserListView * m_pUserListView;
+ QString m_szLastCompletedNick;
+ QString m_szLastCompletionBuffer;
+ int m_iLastCompletionCursorPosition;
+ int m_iLastCompletionCursorXPosition;
+ int m_iLastCompletionFirstVisibleChar;
+ bool m_bLastCompletionFinished;
+
+ bool m_bUpdatesEnabled;
+ KviStr m_szAltKeyCode;
+ KviWindow * m_pKviWindow;
+ QWidget * m_pInputParent;
+ KviTalPopupMenu * m_pIconMenu;
+ bool m_bReadOnly;
+public:
+ int heightHint() const;
+ virtual QSize sizeHint() const;
+ void setText(const QString text);
+ QString text() { return m_szTextBuffer; };
+ void insertChar(QChar c);
+ void insertText(const QString &text);
+ void applyOptions();
+ void setMaxBufferSize(int size) { m_iMaxBufferSize = size; };
+ void setReadOnly(bool bReadOnly) {m_bReadOnly=bReadOnly; };
+ bool readOnly() {return m_bReadOnly; };
+private:
+ void replaceWordBeforeCursor(const QString &word,const QString &replacement,bool bRepaint = true);
+ int replaceSegment(int start, int length, const QString &string);
+ void getWordBeforeCursor(QString &buffer,bool * bIsFirstWordInLine);
+ void runUpToTheFirstVisibleChar();
+ void extractNextBlock(int idx,QFontMetrics & fm,int curXPos,int maxXPos);
+ void drawTextBlock(QPainter *pa,QFontMetrics & fm,int curXPos,int textBaseline,int idx,int len,bool bSelected=FALSE);
+ QChar getSubstituteChar(unsigned short control_code);
+ void moveRightFirstVisibleCharToShowCursor();
+ void repaintWithCursorOn();
+ void selectOneChar(int pos);
+ int charIndexFromXPosition(int xPos);
+ int xPositionFromCharIndex(QFontMetrics& fm,int chIdx,bool bContentsCoords=FALSE);
+ int xPositionFromCharIndex(int chIdx,bool bContentsCoords=FALSE);
+ void killDragTimer();
+ void handleDragSelection();
+ void end();
+ void home();
+ bool hasSelection();
+ void moveCursorTo(int idx,bool bRepaint = true);
+ void returnPressed(bool bRepaint = true);
+ void completion(bool bShift);
+ void standardNickCompletion(bool bAddMask,QString &word,bool bFirstWordInLine);
+ void recalcFontMetrics(QFontMetrics * pFm);
+ void internalCursorRight(bool bShift);
+ void internalCursorLeft(bool bShift);
+public slots:
+ void iconPopupActivated(int id);
+ void copyToSelection(bool bDonNotCopyToClipboard=true);
+ void copyToClipboard();
+ void removeSelected();
+ void cut();
+ void pasteClipboardWithConfirmation();
+ void pasteSelectionWithConfirmation();
+ void pasteSlow();
+ void stopPasteSlow();
+ void pasteFile();
+ void selectAll();
+ void clear();
+signals:
+ void escapePressed();
+ void enterPressed();
+protected:
+ virtual void drawContents(QPainter *);
+ //virtual void resizeEvent(QResizeEvent *);
+ virtual void timerEvent(QTimerEvent *e);
+ virtual void focusInEvent(QFocusEvent *);
+ virtual void focusOutEvent(QFocusEvent *);
+ virtual void keyPressEvent(QKeyEvent *e);
+ virtual void keyReleaseEvent(QKeyEvent *e);
+ virtual void mousePressEvent(QMouseEvent *e);
+ virtual void mouseReleaseEvent(QMouseEvent *);
+ virtual void dragEnterEvent(QDragEnterEvent *e);
+ virtual void dropEvent(QDropEvent *e);
+ virtual void imStartEvent(QIMEvent *e);
+ virtual void imComposeEvent(QIMEvent *e);
+ virtual void imEndEvent(QIMEvent *e);
+#ifdef COMPILE_USE_QT4
+ virtual void paintEvent(QPaintEvent *e);
+#endif
+};
+
+class KviScriptEditor;
+
+class KVIRC_API KviInput : public QWidget
+{
+ Q_OBJECT
+public:
+ KviInput(KviWindow *par,KviUserListView * view = 0);
+ ~KviInput();
+public:
+ KviWindow * m_pWindow;
+ KviInputEditor * m_pInputEditor;
+ KviScriptEditor * m_pMultiLineEditor;
+ KviTalHBox * m_pButtonContainer;
+ QToolButton * m_pMultiEditorButton;
+ QToolButton * m_pHistoryButton;
+ QToolButton * m_pIconButton;
+ QToolButton * m_pCommandlineModeButton;
+ QToolButton * m_pHideToolsButton;
+protected:
+// virtual void resizeEvent(QResizeEvent * e);
+ virtual void focusInEvent(QFocusEvent * e);
+ virtual void setFocusProxy(QWidget * w);
+ virtual void keyPressEvent(QKeyEvent * e);
+public slots:
+ void multilineEditorButtonToggled(bool bOn);
+ void historyButtonClicked();
+ void iconButtonClicked();
+ void inputEditorEnterPressed();
+ void toggleToolButtons();
+public:
+ virtual void setFocus();
+ void multiLinePaste(const QString &text);
+ bool isUserFriendly() { return m_pCommandlineModeButton->isOn(); };
+ void setUserFriendly(bool bSet) { m_pCommandlineModeButton->setOn(bSet); };
+ int heightHint() const;
+ void setText(const QString &text);
+ void insertChar(char c);
+ void insertText(const QString & text);
+ void applyOptions();
+ bool isButtonsHidden();
+ void setButtonsHidden(bool bHidden);
+ //const QString & text();
+ QString text();
+};
+
+#endif //_KVI_INPUT_H_
diff --git a/src/kvirc/ui/kvi_ipeditor.cpp b/src/kvirc/ui/kvi_ipeditor.cpp
new file mode 100644
index 00000000..13291c24
--- /dev/null
+++ b/src/kvirc/ui/kvi_ipeditor.cpp
@@ -0,0 +1,453 @@
+//
+// File : kvi_ipeditor.cpp
+// Creation date : Wed Jun 12 2000 14:16:49 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+#define __KVIRC__
+#include "kvi_ipeditor.h"
+#include "kvi_qcstring.h"
+
+#include <qapplication.h>
+#include <qlineedit.h>
+#include <qlabel.h>
+#include <qframe.h>
+#include <ctype.h>
+#include <qevent.h>
+
+
+// FIXME: #warning "THIS COULD GO INTO libkvioptions ?"
+
+KviIpEditor::KviIpEditor(QWidget * parent,AddressType addrType,const QString &ipAddr,const char *name)
+:QFrame(parent,name)
+{
+
+ for(int i=0;i<7;i++)
+ {
+ m_pEdit[i] = 0;
+ m_pLabel[i] = 0;
+ }
+ m_pEdit[7] = 0;
+ setFrameStyle(QFrame::Sunken|QFrame::StyledPanel);
+
+#ifdef COMPILE_USE_QT4
+ setBackgroundRole(QPalette::Base);
+#else
+ setBackgroundMode(QWidget::PaletteBase);
+#endif
+
+ setAddressType(addrType);
+
+ setAddress(ipAddr);
+}
+
+KviIpEditor::~KviIpEditor()
+{
+
+}
+
+void KviIpEditor::setEnabled(bool bEnabled)
+{
+ QFrame::setEnabled(bEnabled);
+ for(int i=0;i<8;i++)
+ {
+ if(m_pEdit[i])m_pEdit[i]->setEnabled(bEnabled);
+ if(i<7)if(m_pLabel[i])
+ {
+ // Is this the right way ?
+#ifdef COMPILE_USE_QT4
+ m_pLabel[i]->setBackgroundRole(isEnabled() ? QPalette::Base : QPalette::Background);
+#else
+ m_pLabel[i]->setBackgroundMode(isEnabled() ? QWidget::PaletteBase : QWidget::PaletteBackground);
+#endif
+ m_pLabel[i]->setEnabled(bEnabled);
+ }
+ }
+#ifdef COMPILE_USE_QT4
+ setBackgroundRole(isEnabled() ? QPalette::Base : QPalette::Background);
+#else
+ setBackgroundMode(isEnabled() ? QWidget::PaletteBase : QWidget::PaletteBackground);
+#endif
+}
+
+void KviIpEditor::setAddressType(AddressType addrType)
+{
+ if((addrType != IpV4) && (addrType != IpV6))m_addrType = IpV4;
+ else m_addrType = addrType;
+ recreateChildren();
+}
+
+KviIpEditor::AddressType KviIpEditor::addressType() const
+{
+ return m_addrType;
+}
+
+bool KviIpEditor::hasEmptyFields() const
+{
+ bool bHasEF = false;
+ for(int i=0;i<8;i++)
+ {
+ if(m_pEdit[i])
+ {
+ if(m_pEdit[i]->text().isEmpty())bHasEF = true;
+ }
+ }
+ return bHasEF;
+}
+
+void KviIpEditor::clear()
+{
+ if(!m_pEdit[0])return;
+ int maxW = (m_addrType == IpV4) ? 4 : 8;
+ for(int i=0;i< maxW ;i++)
+ {
+ m_pEdit[i]->setText("");
+ }
+}
+
+bool KviIpEditor::setAddress(const QString &ipAddr)
+{
+ // FIXME We could check if the addres
+ // is valid before effectively setting the fields
+ clear();
+
+ KviQCString ip = ipAddr.ascii(); // ip addresses are digits & latin letters abcdef (IpV6)
+
+ ip = ip.stripWhiteSpace();
+ const char * c = ip.data();
+
+ if(!c)return false; // huh ?....(should never happen at this point)
+
+ if(m_addrType == IpV4)
+ {
+ for(int i=0;i<4;i++)
+ {
+ const char *anchor = c;
+ while(isdigit(*c))c++;
+ if(c == anchor)return false; // Invalid empty field
+ KviQCString str(anchor,(c - anchor) + 1);
+ bool bOk;
+ int num = str.toInt(&bOk);
+ if(!bOk)return false; // should never happen , but just to be sure
+ if((num < 0) || (num > 255))return false; // Invalid field
+ m_pEdit[i]->setText(str.data());
+ if(i < 3){
+ if(*c == '.')c++;
+ else return false; // missing separator
+ }
+ }
+ } else {
+ for(int i=0;i<8;i++)
+ {
+ const char *anchor = c;
+ while(isdigit(*c) || ((tolower(*c) >= 'a') && (tolower(*c) <= 'f')) || ((tolower(*c) >= 'A') && (tolower(*c) <= 'F')))c++;
+ KviQCString str(anchor,(c - anchor) + 1);
+ if(str.length() > 4)return false; // Too long
+ m_pEdit[i]->setText(str.data());
+ if(i < 7){
+ if(*c == ':')c++;
+ else return false; // missing separator
+ }
+ }
+ }
+ if(*c)return false; // trailing garbage (we could avoid this)
+ return true;
+}
+
+QString KviIpEditor::address() const
+{
+ QString ret;
+
+ if(m_addrType == IpV6)
+ {
+ for(int i=0;i<8;i++)
+ {
+ ret.append(m_pEdit[i]->text());
+ if(i < 7)ret.append(":");
+ }
+ } else {
+ for(int i=0;i<4;i++)
+ {
+ QString tmp = m_pEdit[i]->text();
+ bool bOk;
+ int num = tmp.toInt(&bOk);
+ if(!bOk)num = 0;
+ tmp.setNum(num);
+ ret.append(tmp);
+ if(i < 3)ret.append(".");
+ }
+ }
+ return ret;
+}
+
+void KviIpEditor::recreateChildren()
+{
+ // A bit slow , but compact
+ bool bIpV4 = (m_addrType == IpV4);
+ int max = bIpV4 ? 4 : 8;
+ QFontMetrics fm(font());
+ //int minWidth = fm.width(bIpV4 ? "000" : "AAAA") + 4;
+ for(int i=0;i<max;i++)
+ {
+ if(!m_pEdit[i]){
+ m_pEdit[i] = new QLineEdit(this);
+ m_pEdit[i]->installEventFilter(this);
+ m_pEdit[i]->setFrame(false);
+ m_pEdit[i]->setAlignment(Qt::AlignCenter);
+ }
+ //m_pEdit[i]->setMinimumWidth(minWidth);
+ m_pEdit[i]->setMaxLength(bIpV4 ? 3 : 4);
+ m_pEdit[i]->show();
+ if(i < (max - 1))
+ {
+ if(!m_pLabel[i])m_pLabel[i] = new QLabel(this);
+ m_pLabel[i]->setText(bIpV4 ? "." : ":");
+ m_pLabel[i]->show();
+ // Is this the right way ? setBackgroundMode seems to not work well
+#ifdef COMPILE_USE_QT4
+ m_pLabel[i]->setBackgroundRole(isEnabled() ? QPalette::Base : QPalette::Background);
+#else
+ m_pLabel[i]->setBackgroundMode(isEnabled() ? QWidget::PaletteBase : QWidget::PaletteBackground);
+#endif
+ }
+ }
+ // Kill the unused widgets , if any
+ if(bIpV4)
+ {
+ for(int i=4;i<8;i++)
+ {
+ if(m_pEdit[i])
+ {
+ delete m_pEdit[i];
+ m_pEdit[i] = 0;
+ }
+ if(m_pLabel[i - 1])
+ {
+ delete m_pLabel[i - 1];
+ m_pLabel[i - 1] = 0;
+ }
+ }
+ }
+ //setMinimumWidth(4 + (max * minWidth) + ((max - 1) * m_pLabel[0]->sizeHint().width()));
+ setMinimumHeight(m_pLabel[0]->sizeHint().height() + 4);
+ resizeEvent(0);
+}
+
+bool KviIpEditor::eventFilter(QObject * o,QEvent *e)
+{
+ if(o->inherits("QLineEdit"))
+ {
+ if(e->type() == QEvent::KeyPress)
+ {
+ QString s;
+ // find the editor
+ int edIdx = -1;
+ for(int i=0;i<8;i++)
+ {
+ if(m_pEdit[i] == o)
+ {
+ edIdx = i;
+ break;
+ }
+ }
+ if(edIdx == -1)return QFrame::eventFilter(o,e); // user added QLineEdit child ?
+ int edMax = (m_addrType == IpV4) ? 3 : 7;
+ int cursorPos = ((QLineEdit *)o)->cursorPosition();
+ switch(((QKeyEvent *)e)->key())
+ {
+ case Qt::Key_Right:
+ s = ((QLineEdit *)o)->text();
+ if(((unsigned int)cursorPos) == s.length())
+ {
+ if(edIdx < edMax)
+ {
+ m_pEdit[++edIdx]->setCursorPosition(0);
+ m_pEdit[edIdx]->setFocus();
+ return true;
+ }
+ }
+ break;
+ case Qt::Key_Left:
+ case Qt::Key_Backspace:
+ if(cursorPos == 0)
+ {
+ if(edIdx > 0)
+ {
+ s = m_pEdit[--edIdx]->text();
+ m_pEdit[edIdx]->setCursorPosition(s.length());
+ m_pEdit[edIdx]->setFocus();
+ return true;
+ }
+ }
+ return QFrame::eventFilter(o,e);
+ break;
+ case Qt::Key_End:
+ case Qt::Key_Home:
+ case Qt::Key_Delete:
+ case Qt::Key_Tab:
+ return QFrame::eventFilter(o,e);
+ break;
+ default:
+ // a normal key (this part substitutes a QValidator)
+ const char c = tolower(((QKeyEvent *)e)->ascii());
+ if(m_addrType == IpV4)
+ {
+ if((c >= '0') && (c <= '9'))
+ {
+#if QT_VERSION >= 300
+ if(m_pEdit[edIdx]->hasSelectedText())m_pEdit[edIdx]->cut();
+#else
+ if(m_pEdit[edIdx]->hasMarkedText())m_pEdit[edIdx]->cut();
+#endif
+ cursorPos = m_pEdit[edIdx]->cursorPosition();
+ s = m_pEdit[edIdx]->text();
+ s.insert(cursorPos,c);
+ bool bOk = false;
+ int num = s.toInt(&bOk);
+ if(!bOk)return true; //should never happen , but just to be sure
+ if((num < 0) || (num > 255))return true; //invalid field
+ m_pEdit[edIdx]->setText(s);
+ if(num > 25)
+ {
+ // The focus goes to the next editor
+ if(edIdx < edMax)
+ {
+ m_pEdit[++edIdx]->setFocus();
+ m_pEdit[edIdx]->selectAll();
+ //m_pEdit[edIdx]->setCursorPosition(0);
+ return true;
+ }
+ }
+#if QT_VERSION >= 300
+ m_pEdit[edIdx]->cursorForward(false);
+#else
+ m_pEdit[edIdx]->cursorRight(false);
+#endif
+ } else {
+ if((c == '.') && (edIdx < edMax))
+ {
+#if QT_VERSION >= 300
+ if(!m_pEdit[edIdx]->hasSelectedText())
+#else
+ if(!m_pEdit[edIdx]->hasMarkedText())
+#endif
+ {
+ m_pEdit[++edIdx]->setFocus();
+ m_pEdit[edIdx]->selectAll();
+ }
+ }
+ }
+ } else {
+ if( ((c >= '0') && (c <= '9')) || ((c >= 'a') && (c <= 'f')) )
+ {
+#if QT_VERSION >= 300
+ if(m_pEdit[edIdx]->hasSelectedText())m_pEdit[edIdx]->cut();
+#else
+ if(m_pEdit[edIdx]->hasMarkedText())m_pEdit[edIdx]->cut();
+#endif
+ cursorPos = m_pEdit[edIdx]->cursorPosition();
+ s = m_pEdit[edIdx]->text();
+
+ if(s.length() == 4)
+ {
+ if((cursorPos == 4) && (edIdx < edMax))
+ {
+ // the char goes in the next editor
+ s = c;
+ m_pEdit[++edIdx]->setText(s);
+ m_pEdit[edIdx]->end(false);
+ m_pEdit[edIdx]->setFocus();
+ } // else either no space or invalid place in the string
+ } else {
+ // ok .. can insert
+ s.insert(cursorPos,c);
+ m_pEdit[edIdx]->setText(s);
+ if((s.length() == 4) && (edIdx < edMax))
+ {
+ // the focus now goes to the next editor
+ m_pEdit[++edIdx]->setFocus();
+ m_pEdit[edIdx]->selectAll();
+ //m_pEdit[edIdx]->setCursorPosition(0);
+ } else {
+#if QT_VERSION >= 300
+ m_pEdit[edIdx]->cursorForward(false);
+#else
+ m_pEdit[edIdx]->cursorRight(false);
+#endif
+ }
+ }
+ } else {
+ if((c == ':') && (edIdx < edMax))
+ {
+#if QT_VERSION >= 300
+ if(!m_pEdit[edIdx]->hasSelectedText())
+#else
+ if(!m_pEdit[edIdx]->hasMarkedText())
+#endif
+ {
+ m_pEdit[++edIdx]->setFocus();
+ m_pEdit[edIdx]->selectAll();
+ }
+ }
+ }
+ }
+ return true;
+ break;
+ }
+ }
+ }
+ return QFrame::eventFilter(o,e);
+}
+
+void KviIpEditor::resizeEvent(QResizeEvent *e)
+{
+ if(m_pEdit[0])
+ {
+ int maxW = (m_addrType == IpV4) ? 4 : 8;
+ int labHint = m_pLabel[0]->sizeHint().width();
+ int hghHint = height() - 4;
+ int ediWdth = ((width() - 4) - ((maxW - 1) * labHint)) / maxW;
+ int curX = 2;
+ for(int i=0;i<maxW;i++)
+ {
+ if(i > 0)
+ {
+ m_pLabel[i - 1]->setGeometry(curX,2,labHint,hghHint);
+ curX += labHint;
+ }
+ m_pEdit[i]->setGeometry(curX,2,ediWdth,hghHint);
+ curX += ediWdth;
+ }
+ }
+ if(e)QFrame::resizeEvent(e);
+}
+
+QSize KviIpEditor::sizeHint()
+{
+ if(m_pEdit[0])
+ {
+ int labHint = m_pLabel[0]->sizeHint().width();
+ int hghHint = m_pEdit[0]->sizeHint().height();
+ int ediHint = m_pEdit[0]->sizeHint().width();
+ if(m_addrType == IpV4)return QSize((labHint * 3) + (ediHint * 4) + 4,hghHint + 4);
+ else return QSize((labHint * 7) + (ediHint * 8) + 4,hghHint + 4);
+ } else return QFrame::sizeHint();
+}
+
+
+#include "kvi_ipeditor.moc"
diff --git a/src/kvirc/ui/kvi_ipeditor.h b/src/kvirc/ui/kvi_ipeditor.h
new file mode 100644
index 00000000..04574e61
--- /dev/null
+++ b/src/kvirc/ui/kvi_ipeditor.h
@@ -0,0 +1,62 @@
+#ifndef _KVI_IPEDITOR_H_
+#define _KVI_IPEDITOR_H_
+
+//
+// File : kvi_ipeditor.h
+// Creation date : Wed Jun 12 2000 14:16:02 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+
+#include <qwidget.h>
+#include <qstring.h>
+#include <qframe.h>
+
+class QLineEdit;
+class QLabel;
+
+class KVIRC_API KviIpEditor : public QFrame
+{
+ Q_OBJECT
+public:
+ enum AddressType { IpV4 , IpV6 };
+ KviIpEditor(QWidget * parent,AddressType = IpV4,const QString &ipAddr = QString::null,const char *name = 0);
+ ~KviIpEditor();
+private:
+ QLabel * m_pLabel[7];
+ QLineEdit * m_pEdit[8];
+ AddressType m_addrType;
+public:
+ bool setAddress(const QString &ipAddr);
+ QString address() const;
+ void setAddressType(AddressType addrType);
+ AddressType addressType() const;
+ bool hasEmptyFields() const;
+ void clear();
+ virtual void setEnabled(bool bEnabled);
+protected:
+ virtual bool eventFilter(QObject * o,QEvent *e);
+ virtual void resizeEvent(QResizeEvent *e);
+ virtual QSize sizeHint();
+private:
+ void recreateChildren();
+};
+
+#endif //_KVI_IPEDITOR_H_
diff --git a/src/kvirc/ui/kvi_irctoolbar.cpp b/src/kvirc/ui/kvi_irctoolbar.cpp
new file mode 100644
index 00000000..a7e45f3f
--- /dev/null
+++ b/src/kvirc/ui/kvi_irctoolbar.cpp
@@ -0,0 +1,441 @@
+//=============================================================================
+//
+// File : kvi_irctoolbar.cpp
+// Creation date : Thu Oct 29 2000 14:13:13 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+#include "kvi_irctoolbar.h"
+#include "kvi_console.h"
+#include "kvi_frame.h"
+#include "kvi_locale.h"
+#include "kvi_iconmanager.h"
+#include "kvi_settings.h"
+#include "kvi_options.h"
+#include "kvi_frame.h"
+#include "kvi_app.h"
+#include "kvi_dynamictooltip.h"
+#include "kvi_ircurl.h"
+#include "kvi_internalcmd.h"
+#include "kvi_pointerlist.h"
+#include "kvi_ircconnection.h"
+#include "kvi_ircconnectionuserinfo.h"
+#include "kvi_irccontext.h"
+#include "kvi_lagmeter.h"
+
+#include <qstyle.h>
+#include <qpainter.h>
+#include "kvi_tal_popupmenu.h"
+#include <qlayout.h>
+
+#ifdef COMPILE_USE_QT4
+ #include <qevent.h>
+#endif
+
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ extern QPixmap * g_pShadedChildGlobalDesktopBackground;
+#endif
+
+static QPixmap * g_pIccMemBuffer = 0;
+static KviPointerList<KviToolBarGraphicalApplet> * g_pToolBarGraphicalAppletList = 0;
+
+KviToolBarGraphicalApplet::KviToolBarGraphicalApplet(QWidget * par,const char * name)
+: QToolButton(par,name)
+{
+ if(!g_pToolBarGraphicalAppletList)
+ {
+ g_pToolBarGraphicalAppletList = new KviPointerList<KviToolBarGraphicalApplet>();
+ g_pToolBarGraphicalAppletList->setAutoDelete(false);
+ g_pIccMemBuffer = new QPixmap(1,1);
+ }
+
+ g_pToolBarGraphicalAppletList->append(this);
+#ifdef COMPILE_USE_QT4
+ setAutoFillBackground(false);
+#else
+ setBackgroundMode(QWidget::NoBackground);
+#endif
+
+ setMouseTracking(true);
+ m_bResizeMode = false;
+
+ m_sizeHint = QSize(180,32);
+ m_bSizeLoaded = false;
+}
+
+unsigned int KviToolBarGraphicalApplet::loadAppletWidth()
+{
+ if(KVI_OPTION_UINT(KviOption_uintIrcContextAppletWidth) < 32)
+ KVI_OPTION_UINT(KviOption_uintIrcContextAppletWidth) = 32;
+ return KVI_OPTION_UINT(KviOption_uintIrcContextAppletWidth);
+}
+
+void KviToolBarGraphicalApplet::saveAppletWidth(unsigned int uWidth)
+{
+ KVI_OPTION_UINT(KviOption_uintIrcContextAppletWidth) = uWidth;
+}
+
+void KviToolBarGraphicalApplet::setupSizeHint()
+{
+ m_sizeHint = QSize(loadAppletWidth(),22);
+ m_bSizeLoaded = true;
+}
+
+QSize KviToolBarGraphicalApplet::sizeHint() const
+{
+ // forget constness :(
+ KviToolBarGraphicalApplet * that = (KviToolBarGraphicalApplet *)this;
+ if(!m_bSizeLoaded)that->setupSizeHint();
+ return m_sizeHint;
+}
+
+/*
+toolbar.define(default)
+{
+ applet(thisandthat);
+ applet(thisandthat);
+ applet(thisandthat);
+ applet(thisandthat);
+}
+*/
+
+
+void KviToolBarGraphicalApplet::mouseMoveEvent(QMouseEvent * e)
+{
+ if(e->state() & Qt::LeftButton)
+ {
+ if(m_bResizeMode)
+ {
+ int w = e->pos().x();
+ if(w < 32)w = 32;
+ if(w > 480)w = 480;
+ m_sizeHint = QSize(w,22);
+ resize(w,height());
+ g_pApp->postEvent(parentWidget(),new QEvent(QEvent::LayoutHint));
+ }
+ } else {
+ if(e->pos().x() > width() - 4)
+ setCursor(Qt::sizeHorCursor);
+ else
+ setCursor(Qt::arrowCursor);
+ }
+}
+
+void KviToolBarGraphicalApplet::mousePressEvent(QMouseEvent * e)
+{
+ if(e->button() & Qt::LeftButton)
+ {
+ m_bResizeMode = (e->pos().x() > (width() - 4));
+ }
+}
+
+void KviToolBarGraphicalApplet::mouseReleaseEvent(QMouseEvent * e)
+{
+ m_bResizeMode = false;
+}
+
+
+KviToolBarGraphicalApplet::~KviToolBarGraphicalApplet()
+{
+ saveAppletWidth(m_sizeHint.width());
+ g_pToolBarGraphicalAppletList->removeRef(this);
+ if(g_pToolBarGraphicalAppletList->isEmpty())
+ {
+ delete g_pToolBarGraphicalAppletList;
+ g_pToolBarGraphicalAppletList = 0;
+ delete g_pIccMemBuffer;
+ g_pIccMemBuffer = 0;
+ } else {
+ // resize the mem buffer to match the maximum width / height of the applets
+ resizeMemBuffer();
+ }
+}
+
+void KviToolBarGraphicalApplet::resizeMemBuffer()
+{
+ int uMaxW = 0;
+ int uMaxH = 0;
+ for(KviToolBarGraphicalApplet * a = g_pToolBarGraphicalAppletList->first();a;a = g_pToolBarGraphicalAppletList->next())
+ {
+ if(uMaxW < a->width())uMaxW = a->width();
+ if(uMaxH < a->height())uMaxH = a->height();
+ }
+ g_pIccMemBuffer->resize(uMaxW,uMaxH);
+}
+
+void KviToolBarGraphicalApplet::paintEvent(QPaintEvent *e)
+{
+ if(!isVisible())return;
+
+ QPainter pa(g_pIccMemBuffer);
+
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ if(g_pShadedChildGlobalDesktopBackground)
+ {
+ QPoint pnt = mapToGlobal(QPoint(0,0));
+ pa.drawTiledPixmap(e->rect().left(),e->rect().top(),e->rect().width(),e->rect().height(),*g_pShadedChildGlobalDesktopBackground,pnt.x(),pnt.y());
+ } else {
+#endif
+ if(KVI_OPTION_PIXMAP(KviOption_pixmapIrcToolBarAppletBackground).pixmap())
+ {
+ QPoint pnt = mapToGlobal(QPoint(0,0));
+ pa.drawTiledPixmap(e->rect().left(),e->rect().top(),e->rect().width(),e->rect().height(),*(KVI_OPTION_PIXMAP(KviOption_pixmapIrcToolBarAppletBackground).pixmap()),pnt.x(),pnt.y());
+ } else {
+ pa.fillRect(e->rect().left(),e->rect().top(),e->rect().width(),e->rect().height(),KVI_OPTION_COLOR(KviOption_colorIrcToolBarAppletBackground));
+ }
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ }
+#endif
+
+ drawContents(&pa);
+
+ //Need to draw the sunken rect around the view now...
+ pa.setPen(colorGroup().dark());
+ pa.drawLine(0,0,width(),0);
+ pa.drawLine(0,0,0,width());
+ pa.setPen(colorGroup().light());
+ pa.drawLine(1,height() - 1,width() - 1,height() - 1);
+ pa.drawLine(width() - 1,1,width() - 1,height());
+
+#ifdef COMPILE_USE_QT4
+ QPainter qt4SucksBecauseItNeedsAnAdditionalQPainter(this);
+ qt4SucksBecauseItNeedsAnAdditionalQPainter.drawPixmap(e->rect().left(),e->rect().top(),e->rect().width(),e->rect().height(),*g_pIccMemBuffer,e->rect().left(),e->rect().top(),e->rect().width(),e->rect().height());
+#else
+ bitBlt(this,e->rect().left(),e->rect().top(),g_pIccMemBuffer,e->rect().left(),e->rect().top(),e->rect().width(),e->rect().height(),Qt::CopyROP);
+#endif
+}
+
+void KviToolBarGraphicalApplet::drawContents(QPainter *)
+{
+ // nothing here
+}
+
+void KviToolBarGraphicalApplet::resizeEvent(QResizeEvent *e)
+{
+ unsigned int uBufferW = g_pIccMemBuffer->width();
+ unsigned int uBufferH = g_pIccMemBuffer->height();
+ unsigned int uW = width();
+ unsigned int uH = height();
+
+ if((uBufferW != uW) || (uBufferH != uH))
+ {
+ if((uBufferW < uW) && (uBufferH < uH))g_pIccMemBuffer->resize(uW,uH);
+ else resizeMemBuffer();
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// KviIrcContextDisplay
+//
+// Main applet of all irc contexts
+// Displays the server connection status, server name
+// nickname, user mode and the graphical indication of the context
+//
+//////////////////////////////////////////////////////////////////////////////
+
+KviIrcContextDisplay::KviIrcContextDisplay(QWidget * par,const char * name)
+: KviToolBarGraphicalApplet(par,name)
+{
+ KviDynamicToolTip * tip = new KviDynamicToolTip(this);
+ connect(tip,SIGNAL(tipRequest(KviDynamicToolTip *,const QPoint &)),this,SLOT(tipRequest(KviDynamicToolTip *,const QPoint &)));
+}
+
+
+KviIrcContextDisplay::~KviIrcContextDisplay()
+{
+}
+
+void KviIrcContextDisplay::tipRequest(KviDynamicToolTip * tip,const QPoint &)
+{
+ QString txt;
+
+ KviConsole * c = g_pActiveWindow->console();
+
+ static QString b = "<b>";
+ static QString nb = "</b>";
+ static QString br = "<br>";
+
+ if(c)
+ {
+ KviIrcConnection * ic = c->connection();
+
+ txt = b;
+
+ if(!ic)
+ {
+ txt += __tr2qs("No connection");
+ txt += nb;
+ txt += br;
+ } else {
+ KviStr nickAndMode = ic->userInfo()->nickName();
+ if(!(ic->userInfo()->userMode().isEmpty()))nickAndMode.append(KviStr::Format," (+%s)",ic->userInfo()->userMode().utf8().data());
+
+ txt += ic->currentServerName();
+ txt += nb;
+ txt += br;
+ txt += nickAndMode.ptr();
+ txt += br;
+ }
+
+ QString szNum;
+ szNum.setNum(c->ircContextId());
+
+ QString szIrcContext = QChar('(');
+ szIrcContext += __tr2qs("IRC Context");
+ szIrcContext += QChar(' ');
+ szIrcContext += szNum;
+ szIrcContext += QChar(')');
+ txt += szIrcContext;
+
+ if(ic && ic->lagMeter() && (KVI_OPTION_BOOL(KviOption_boolShowLagOnContextDisplay)))
+ {
+ txt += br;
+ int lll;
+ if((lll = ic->lagMeter()->lag()) > 0)
+ {
+ int llls = lll / 1000;
+ int llld = (lll % 1000) / 100;
+ int lllc = (lll % 100) / 10;
+ KviQString::appendFormatted(txt,__tr2qs("Lag: %d.%d%d"),llls,llld,lllc);
+ } else {
+ txt += __tr2qs("Lag: ?.??");
+ }
+ }
+ } else {
+ txt = b;
+ txt += __tr2qs("No IRC context");
+ txt += nb;
+ }
+
+ tip->tip(rect(),txt);
+}
+
+
+/*
+QSize KviIrcContextDisplay::sizeHint() const
+{
+ return QSize(160,22);
+}
+*/
+
+#define KVI_APPLETIRCCONTEXTINDICATORWIDTH 12
+
+void KviIrcContextDisplay::drawContents(QPainter * p)
+{
+ // The context indicator
+ KviWindow * wnd = g_pActiveWindow;
+ KviConsole * c = wnd ? wnd->console() : 0;
+
+ if(c)
+ {
+ QString serv,nick;
+ QString tmp;
+ if(!c->connection())
+ {
+ serv = __tr2qs("Not connected");
+ } else {
+ if(c->isConnected())
+ {
+ KviIrcConnection * ic = c->connection();
+ nick = ic->currentNickName();
+ if(!ic->userInfo()->userMode().isEmpty())
+ {
+ static QString spp(" (+");
+ nick += spp;
+ nick += ic->userInfo()->userMode();
+ if(ic->userInfo()->isAway())
+ {
+ nick += QChar(' ');
+ nick += __tr2qs("away");
+ }
+ nick += QChar(')');
+ } else {
+ if(ic->userInfo()->isAway())
+ {
+ static QString ugly(" (");
+ nick += ugly;
+ nick += __tr2qs("away");
+ nick += QChar(')');
+ }
+ }
+ serv = ic->currentServerName();
+ if(ic->lagMeter() && (KVI_OPTION_BOOL(KviOption_boolShowLagOnContextDisplay)))
+ {
+ nick += " ";
+ int lll;
+ if((lll = ic->lagMeter()->lag()) > 0)
+ {
+ int llls = lll / 1000;
+ int llld = (lll % 1000) / 100;
+ int lllc = (lll % 100) / 10;
+ KviQString::appendFormatted(nick,__tr2qs("Lag: %d.%d%d"),llls,llld,lllc);
+ } else {
+ nick += __tr2qs("Lag: ?.??");
+ }
+ }
+ } else {
+ serv = __tr2qs("In progress...");
+ }
+ }
+
+ p->setPen(KVI_OPTION_COLOR(KviOption_colorIrcToolBarAppletForegroundHighContrastActive1));
+
+ p->setClipRect(KVI_APPLETIRCCONTEXTINDICATORWIDTH + 2,2,width() - (KVI_APPLETIRCCONTEXTINDICATORWIDTH + 4),height() - 4);
+
+ if(height() < 30)
+ {
+ static QString xxx(" [");
+ serv += xxx;
+ serv += nick;
+ serv += QChar(']');
+ p->drawText(KVI_APPLETIRCCONTEXTINDICATORWIDTH + 4,16,serv,serv.length());
+ } else {
+ p->drawText(KVI_APPLETIRCCONTEXTINDICATORWIDTH + 4,16,serv,serv.length());
+ p->drawText(KVI_APPLETIRCCONTEXTINDICATORWIDTH + 4,30,nick,nick.length());
+ }
+
+ p->setClipping(false);
+
+ QColor base = colorGroup().background();
+ QColor cntx = KVI_OPTION_ICCOLOR(c->ircContextId() % KVI_NUM_ICCOLOR_OPTIONS);
+ base.setRgb((base.red() + cntx.red()) >> 1,(base.green() + cntx.green()) >> 1,
+ (base.blue() + cntx.blue()) >> 1);
+
+ p->fillRect(2,2, KVI_APPLETIRCCONTEXTINDICATORWIDTH - 2,height() - 4,base);
+ }
+
+ p->setPen(KVI_OPTION_COLOR(KviOption_colorIrcToolBarAppletForegroundMidContrast));
+ p->drawLine(1,1,width() - 1,1);
+ p->drawLine(1,1,1,height() - 1);
+ p->drawLine(2,height() - 2,width() - 1,height() - 2);
+ p->drawLine(width() - 2,1,width() - 2,height());
+ p->drawLine(KVI_APPLETIRCCONTEXTINDICATORWIDTH,2,KVI_APPLETIRCCONTEXTINDICATORWIDTH,height() - 2);
+
+}
+
+
+#ifdef Bool
+ #undef Bool
+#endif
+
+#include "kvi_irctoolbar.moc"
diff --git a/src/kvirc/ui/kvi_irctoolbar.h b/src/kvirc/ui/kvi_irctoolbar.h
new file mode 100644
index 00000000..a9030650
--- /dev/null
+++ b/src/kvirc/ui/kvi_irctoolbar.h
@@ -0,0 +1,95 @@
+#ifndef _KVI_IRCTOOLBAR_H_
+#define _KVI_IRCTOOLBAR_H_
+
+//
+// File : kvi_irctoolbar.h
+// Creation date : Thu Oct 29 2000 14:09:11 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+
+#include "kvi_string.h"
+#include "kvi_toolbar.h"
+#include "kvi_console.h"
+
+#include "kvi_pointerlist.h"
+#include <qwidget.h>
+#include <qtoolbutton.h>
+#include "kvi_tal_widgetstack.h"
+#include <qlabel.h>
+
+class KviTalPopupMenu;
+
+
+//
+// Basic graphical applet
+//
+// Thinks about the "common" background (handles transparency stuff & co.)
+// Can be a child of any AppletContainer
+//
+
+class KVIRC_API KviToolBarGraphicalApplet : public QToolButton
+{
+ Q_OBJECT
+public:
+ KviToolBarGraphicalApplet(QWidget * par,const char * name = 0);
+ ~KviToolBarGraphicalApplet();
+private:
+ bool m_bResizeMode;
+ bool m_bSizeLoaded;
+ QSize m_sizeHint;
+private:
+ void resizeMemBuffer();
+protected:
+ void setupSizeHint();
+
+ virtual unsigned int loadAppletWidth();
+ virtual void saveAppletWidth(unsigned int uWidth);
+ virtual QSize sizeHint() const;
+ virtual void mouseMoveEvent(QMouseEvent *e);
+ virtual void mousePressEvent(QMouseEvent *e);
+ virtual void mouseReleaseEvent(QMouseEvent *e);
+
+ virtual void paintEvent(QPaintEvent *e);
+ virtual void drawContents(QPainter * p);
+ virtual void resizeEvent(QResizeEvent *e);
+};
+
+
+class KviDynamicToolTip;
+
+class KVIRC_API KviIrcContextDisplay : public KviToolBarGraphicalApplet
+{
+ Q_OBJECT
+public:
+ KviIrcContextDisplay(QWidget * par,const char * name = 0);
+ ~KviIrcContextDisplay();
+protected:
+ virtual void drawContents(QPainter * p);
+protected slots:
+ void tipRequest(KviDynamicToolTip * tip,const QPoint &);
+};
+
+
+
+
+
+
+#endif //_KVI_IRCTOOLBAR_H_
diff --git a/src/kvirc/ui/kvi_ircview.cpp b/src/kvirc/ui/kvi_ircview.cpp
new file mode 100644
index 00000000..e09edee1
--- /dev/null
+++ b/src/kvirc/ui/kvi_ircview.cpp
@@ -0,0 +1,5161 @@
+//=============================================================================
+//
+// File : kvi_ircview.cpp
+// Creation date : Tue Jul 6 1999 14:45:20 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+// Damn complex class ...but it works :)
+// #include <brain.h>
+//
+// #define HOPE_THAT_IT_WILL_NEVER_NEED_TO_BE_MODIFIED :)
+
+// 07 May 1999 ,
+// Already forgot how this damn thing works ,
+// and spent 1 hour over a stupid bug.
+// I had to recreate the whole thing in my mind......ooooouh...
+// How did I wrote it ?
+// Just take a look to paintEvent() or to calculateLineWraps()...
+// Anyway...I've solved the bug.
+
+// 23 Nov 1999 ,
+// Well , not so bad...I seem to still remember how it works
+// So just for fun , complicated the things a little bit more.
+// Added precaclucaltion of the text blocks and word wrapping
+// and a fast scrolling mode (3 lines at once) for consecutive
+// appendText() calls.
+// Now the code becomes really not understandable...:)
+
+// 29 Jun 2000 21:02 ,
+// Here we go again... I have to adjust this stuff for 3.0.0
+// Will I make this thingie work ?
+// 01 Jul 2000 04:20 (AM!) ,
+// Yes....I got it to work just now
+// and YES , complicated the things yet more.
+// This time made some paint event code completely unreadable
+// by placing two monster macros...
+// I hope that you have a smart compiler (such as gcc is).
+
+// 09 Dec 2000
+// This is my C-asm-optimisation-hack playground
+// Expect Bad Programming(tm) , Ugly Code(tm) , Unreadable Macros (tm)
+// and massive usage of the Evil(tm) goto.
+
+// 25 Sep 2001
+// This stuff is going to be ported to Windoze
+// A conditionally compiled code will use only Qt calls...let's see :)
+//
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Here we go... a huge set of includes
+//
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#include "kvi_ircview.h"
+#include "kvi_ircviewtools.h"
+#include "kvi_ircviewprivate.h"
+#include "kvi_styled_controls.h"
+#include "kvi_debug.h"
+#include "kvi_app.h"
+#include "kvi_settings.h"
+#include "kvi_options.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_defaults.h"
+#include "kvi_window.h"
+#include "kvi_locale.h"
+#include "kvi_frame.h"
+#include "kvi_malloc.h"
+#include "kvi_memmove.h"
+#include "kvi_iconmanager.h"
+#include "kvi_out.h"
+#include "kvi_parameterlist.h"
+#include "kvi_console.h"
+#include "kvi_ircuserdb.h"
+#include "kvi_channel.h"
+#include "kvi_topicw.h"
+#include "kvi_query.h"
+#include "kvi_filedialog.h"
+#include "kvi_msgbox.h"
+#include "kvi_texticonmanager.h"
+#include "kvi_ircconnection.h"
+#include "kvi_ircconnectiontarget.h"
+#include "kvi_mdimanager.h"
+#include "kvi_userinput.h"
+#include "kvi_kvs_eventtriggers.h"
+#include "kvi_doublebuffer.h"
+#include "kvi_ircurl.h"
+#include "kvi_draganddrop.h"
+#include "kvi_qcstring.h"
+// FIXME: #warning "There should be an option to preserve control codes in copied text (clipboard) (mIrc = CTRL+Copy->with colors)"
+
+#include <qbitmap.h>
+#include <qpainter.h>
+#include <qregexp.h>
+#include <qfile.h>
+#include <qtoolbutton.h>
+#include <qfontmetrics.h> // needed
+#include <qapplication.h>
+#include "kvi_tal_popupmenu.h"
+#include <qmessagebox.h>
+#include <qtextcodec.h>
+#include <qdatetime.h>
+#include <qevent.h>
+
+//#include <qcolor.h> // needed
+
+// FIXME: #warning "There are problems with the selection and wrapped lines: you can select something on the first line and get the second highlighted"
+// FIXME: #warning "This hack is temporary...later remove it"
+
+#if QT_VERSION >= 300
+ #ifndef QT_CLEAN_NAMESPACE
+ #define QT_CLEAN_NAMESPACE
+ #include <qcursor.h>
+ #undef QT_CLEAN_NAMESPACE
+ #else
+ #include <qcursor.h>
+ #endif
+#else
+ #include <qcursor.h>
+#endif
+
+#include <qclipboard.h>
+#include <qdatetime.h>
+#include <qmessagebox.h>
+#include <qscrollbar.h>
+#include <qfontdialog.h>
+
+#include <time.h>
+
+#ifdef COMPILE_USE_QT4
+ #include <q3mimefactory.h>
+ #define QMimeSourceFactory Q3MimeSourceFactory
+#endif
+
+
+#ifdef COMPILE_ON_WINDOWS
+ #pragma warning(disable: 4102)
+#endif
+
+#ifdef __STRICT_ANSI__
+ #ifdef COMPILE_USE_DYNAMIC_LABELS
+ // incompatible with -ansi
+ #undef COMPILE_USE_DYNAMIC_LABELS
+ #endif
+#endif
+
+#ifdef COMPILE_ZLIB_SUPPORT
+ #include <zlib.h>
+#endif
+
+#define KVI_DEF_BACK 200
+
+// FIXME: #warning "The scrollbar should NOT have a fixed size : the KDE styles can configure the size (sizeHint() ?)"
+
+//
+// FIXME: PgUp and PgDn scrolls a fixed number of lines!
+// Make it view height dependant
+//
+// FIXME: This widget is quite slow on a 300 MHz processor
+//
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Globals
+//
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// Stuff declared in kvi_app.cpp and managed by KviApp class
+
+
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ extern QPixmap * g_pShadedChildGlobalDesktopBackground;
+#endif
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Internal constants
+//
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+// Maximum size of the internal buffer for each window
+// This is the default value
+//#define KVI_IRCVIEW_MAX_LINES 1024
+// Borders...just do not set it to 0
+#define KVI_IRCVIEW_HORIZONTAL_BORDER 4
+#define KVI_IRCVIEW_VERTICAL_BORDER 4
+// A little bit more than the scroll-bar...
+// Qt+X have strange interactions that I can not understand when I try to move the splitter
+// to the maximum on the left , Maybe the cache pixmap size becomes negative ? (I don't think so)
+// Anyway , when the scroll bar position becomes negative (or the IrcView has smaller width than
+// the scroll bar) X aborts with a funny
+// X Error: BadDrawable (invalid Pixmap or Window parameter) 9
+// Major opcode: 55
+// Program received signal SIGABRT, Aborted.
+// Do not change unless you're sure that it will not happen :)
+#define KVI_IRCVIEW_MINIMUM_WIDTH 22
+//16+4+(2*4) * Do not change
+#define KVI_IRCVIEW_PIXMAP_AND_SEPARATOR 20
+#define KVI_IRCVIEW_PIXMAP_SEPARATOR_AND_DOUBLEBORDER_WIDTH 28
+#define KVI_IRCVIEW_SELECT_REPAINT_INTERVAL 100
+#define KVI_IRCVIEW_SIZEHINT_WIDTH 150
+#define KVI_IRCVIEW_SIZEHINT_HEIGHT 150
+
+#define KVI_IRCVIEW_BLOCK_SELECTION_TOTAL 0
+#define KVI_IRCVIEW_BLOCK_SELECTION_LEFT 1
+#define KVI_IRCVIEW_BLOCK_SELECTION_RIGHT 2
+#define KVI_IRCVIEW_BLOCK_SELECTION_CENTRAL 3
+#define KVI_IRCVIEW_BLOCK_SELECTION_ICON 4
+
+#define KVI_IRCVIEW_PIXMAP_SIZE 16
+
+#define KVI_IRCVIEW_ESCAPE_TAG_URLLINK 'u'
+#define KVI_IRCVIEW_ESCAPE_TAG_NICKLINK 'n'
+#define KVI_IRCVIEW_ESCAPE_TAG_SERVERLINK 's'
+#define KVI_IRCVIEW_ESCAPE_TAG_HOSTLINK 'h'
+#define KVI_IRCVIEW_ESCAPE_TAG_GENERICESCAPE '['
+
+// FIXME: Get rid of this!!!!!!!!!
+#define WSTRINGCONFIG_SAFE_TO_MEMCPY_QCHAR
+
+#define _WSTRING_WMEMCPY(_dst,_src,_len) kvi_fastmoveodd((void *)(_dst),(const void *)(_src),sizeof(kvi_wchar_t) * (_len))
+
+void kvi_appendWCharToQStringWithLength(QString * qstrptr,const kvi_wchar_t * ptr,kvi_wslen_t len)
+{
+ kvi_wslen_t oldLen = qstrptr->length();
+ qstrptr->setLength(oldLen + len);
+ #ifdef WSTRINGCONFIG_SAFE_TO_MEMCPY_QCHAR
+ _WSTRING_WMEMCPY(qstrptr->unicode() + oldLen,ptr,len);
+ #else // !WSTRINGCONFIG_SAFE_TO_MEMCPY_QCHAR
+ QChar * c = (qstrptr->unicode() + oldLen);
+ while(*ptr)
+ {
+ c->unicode() = *ptr;
+ ptr++;
+ c++;
+ }
+ #endif // !WSTRINGCONFIG_SAFE_TO_MEMCPY_QCHAR
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Info about escape syntax
+//
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// escape commands:
+//
+// <cr>!<escape_command><cr><visible parameters<cr>
+//
+// <escape_command> ::= u <--- url link
+// <escape_command> ::= n <--- nick link
+// <escape_command> ::= s <--- server link
+// <escape_command> ::= h <--- host link
+// <escape_command> ::= [... <--- generic escape "rbt" | "mbt" | "dbl" | "txt"
+//
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// The IrcView : construct and destroy
+//
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+KviIrcView::KviIrcView(QWidget *parent,KviFrame *pFrm,KviWindow *pWnd)
+: QWidget(parent,"irc_view")
+{
+ // Ok...here we go
+ // initialize the initializable
+
+#ifdef COMPILE_USE_QT4
+ setAttribute(Qt::WA_NoSystemBackground); // This disables automatic qt double buffering
+ setAttribute(Qt::WA_OpaquePaintEvent);
+ //setAttribute(Qt::WA_PaintOnScreen); // disable qt backing store (that would force us to trigger repaint() instead of the 10 times faster paintEvent(0))
+#endif
+
+ m_iFlushTimer = 0;
+ m_pToolsPopup = 0;
+ m_pFirstLine = 0;
+ m_pCurLine = 0;
+ m_pLastLine = 0;
+ m_pCursorLine = 0;
+ m_uLineMarkLineIndex = KVI_IRCVIEW_INVALID_LINE_MARK_INDEX;
+ m_bHaveUnreadedHighlightedMessages = false;
+ m_bHaveUnreadedMessages = false;
+ m_iNumLines = 0;
+ m_iMaxLines = KVI_OPTION_UINT(KviOption_uintIrcViewMaxBufferSize);
+
+ m_uNextLineIndex = 0;
+
+ if(m_iMaxLines < 32)
+ {
+ m_iMaxLines = 32;
+ KVI_OPTION_UINT(KviOption_uintIrcViewMaxBufferSize) = 32;
+ }
+
+ m_bMouseIsDown = false;
+
+ //m_bShowImages = KVI_OPTION_BOOL(KviOption_boolIrcViewShowImages);
+
+ m_iSelectTimer = 0;
+ m_iMouseTimer = 0;
+ //m_iTipTimer = 0;
+ //m_bTimestamp = KVI_OPTION_BOOL(KviOption_boolIrcViewTimestamp);
+
+ m_bAcceptDrops = false;
+ m_pPrivateBackgroundPixmap = 0;
+ m_bSkipScrollBarRepaint = false;
+ m_pLogFile = 0;
+ m_pKviWindow = pWnd;
+ m_pFrm = pFrm;
+
+ m_iUnprocessedPaintEventRequests = 0;
+ m_bPostedPaintEventPending = false;
+
+ m_pLastLinkUnderMouse = 0;
+ m_iLastLinkRectTop = -1;
+ m_iLastLinkRectHeight = -1;
+
+ m_pMasterView = 0;
+
+ m_pToolWidget = 0;
+
+ m_pWrappedBlockSelectionInfo = new KviIrcViewWrappedBlockSelectionInfo;
+
+
+ m_pMessagesStoppedWhileSelecting = new KviPointerList<KviIrcViewLine>;
+ m_pMessagesStoppedWhileSelecting->setAutoDelete(false);
+
+ // say qt to avoid erasing on repaint
+#ifdef COMPILE_USE_QT4
+ setAutoFillBackground(false);
+#else
+ setBackgroundMode(NoBackground);
+#endif
+
+ m_pFm = 0; // will be updated in the first paint event
+
+ m_pToolTip = new KviIrcViewToolTip(this);
+
+ // Create the scroll bar
+#ifdef COMPILE_USE_QT4
+ m_pScrollBar = new QScrollBar(0,0,1,10,0,Qt::Vertical,this,"irc_view_scrollbar");
+#else
+ m_pScrollBar = new QScrollBar(0,0,1,10,0,QScrollBar::Vertical,this,"irc_view_scrollbar");
+#endif
+ m_pScrollBar->setTracking(true);
+ m_pScrollBar->show();
+
+ m_pScrollBar->setFocusProxy(this);
+
+
+ m_pToolsButton = new KviStyledToolButton(this,"btntools");
+#ifdef COMPILE_USE_QT4
+ QIcon is1(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_POPUPMENU)));
+ m_pToolsButton->setAutoRaise(true);
+#else
+ QIconSet is1(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_POPUPMENU)),QIconSet::Small);
+#endif
+ m_pToolsButton->setIconSet(is1);
+
+ KviTalToolTip::add(m_pToolsButton,__tr2qs("Search tools"));
+ m_pToolsButton->setFocusProxy(this);
+
+ connect(m_pToolsButton,SIGNAL(clicked()),this,SLOT(showToolsPopup()));
+ m_pToolsButton->show();
+
+ connect(m_pScrollBar,SIGNAL(valueChanged(int)),this,SLOT(scrollBarPositionChanged(int)));
+ m_iLastScrollBarValue = 0;
+
+ // set the minimum width
+ setMinimumWidth(KVI_IRCVIEW_MINIMUM_WIDTH);
+ // and catch all mouse events
+ setMouseTracking(true);
+ // let's go!
+ applyOptions();
+
+ if(KVI_OPTION_UINT(KviOption_uintAutoFlushLogs)) //m_iFlushTimer
+ {
+ m_iFlushTimer = startTimer(KVI_OPTION_UINT(KviOption_uintAutoFlushLogs)*60*1000);
+ }
+
+// if(pWnd->input()) setFocusProxy(pWnd->input());
+
+}
+
+static inline void delete_text_line(KviIrcViewLine * l)
+{
+ for(unsigned int i=0;i<l->uChunkCount;i++)
+ {
+ if((l->pChunks[i].type == KVI_TEXT_ESCAPE) || (l->pChunks[i].type == KVI_TEXT_ICON))
+ {
+ if( (l->pChunks[i].type == KVI_TEXT_ICON) && (l->pChunks[i].szPayload!=l->pChunks[i].szSmileId) )
+ kvi_free(l->pChunks[i].szSmileId);
+ kvi_free(l->pChunks[i].szPayload);
+ }
+ }
+ kvi_free(l->pChunks); //free attributes data
+ if(l->iBlockCount)kvi_free(l->pBlocks);
+ delete l;
+}
+
+KviIrcView::~KviIrcView()
+{
+ // kill any pending timer
+ if(m_iFlushTimer) killTimer(m_iFlushTimer);
+ if(m_iSelectTimer)killTimer(m_iSelectTimer);
+ if(m_iMouseTimer)killTimer(m_iMouseTimer);
+ // and close the log file (flush!)
+ stopLogging();
+ if(m_pToolWidget)delete m_pToolWidget;
+ // don't forget the bacgkround pixmap!
+ if(m_pPrivateBackgroundPixmap)delete m_pPrivateBackgroundPixmap;
+ // and to remove all the text lines
+ emptyBuffer(false);
+ // the pending ones too!
+ while(KviIrcViewLine * l = m_pMessagesStoppedWhileSelecting->first())
+ {
+ m_pMessagesStoppedWhileSelecting->removeFirst();
+ delete_text_line(l);
+ }
+ delete m_pMessagesStoppedWhileSelecting;
+ if(m_pFm)delete m_pFm;
+ delete m_pToolTip;
+ delete m_pWrappedBlockSelectionInfo;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// The IrcView : options
+//
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void KviIrcView::setFont(const QFont &f)
+{
+ if(m_pFm)
+ {
+ // force an update to the font variables
+ delete m_pFm;
+ m_pFm = 0;
+ }
+ KviIrcViewLine * l = m_pFirstLine;
+ while(l)
+ {
+ l->iMaxLineWidth = -1;
+ l = l->pNext;
+ }
+ QWidget::setFont(f);
+ update();
+}
+
+void KviIrcView::applyOptions()
+{
+ flushLog();
+ setFont(KVI_OPTION_FONT(KviOption_fontIrcView));
+ if(m_iFlushTimer) killTimer(m_iFlushTimer);
+ if(KVI_OPTION_UINT(KviOption_uintAutoFlushLogs))
+ {
+ m_iFlushTimer = startTimer(KVI_OPTION_UINT(KviOption_uintAutoFlushLogs)*60*1000);
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// The IrcView : DnD //2005.Resurection by Grifisx & Noldor
+//
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void KviIrcView::enableDnd(bool bEnable)
+{
+ setAcceptDrops(bEnable);
+ m_bAcceptDrops = bEnable;
+}
+
+void KviIrcView::dragEnterEvent(QDragEnterEvent *e)
+{
+ if(!m_bAcceptDrops)return;
+ e->accept(KviUriDrag::canDecode(e));
+ emit dndEntered();
+}
+
+void KviIrcView::dropEvent(QDropEvent *e)
+{
+ if(!m_bAcceptDrops)return;
+ QStringList list;
+ if(KviUriDrag::decodeLocalFiles(e,list))
+ {
+ if(!list.isEmpty())
+ {
+ QStringList::ConstIterator it = list.begin(); //kewl ! :)
+ for( ; it != list.end(); ++it )
+ {
+ QString tmp = *it; //wow :)
+ #ifndef COMPILE_ON_WINDOWS
+ if(tmp[0] != '/')tmp.prepend("/"); //HACK HACK HACK for Qt bug (?!?)
+ #endif
+ emit fileDropped(tmp);
+ }
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// The IrcView : Logging
+//
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+void KviIrcView::stopLogging()
+{
+ if(m_pLogFile)
+ {
+ QString szLogEnd;
+ szLogEnd.sprintf(__tr2qs("### Log session terminated at %s ###"),QDateTime::currentDateTime().toString().utf8().data());
+
+ add2Log(szLogEnd);
+ m_pLogFile->close();
+#ifdef COMPILE_ZLIB_SUPPORT
+ if(KVI_OPTION_BOOL(KviOption_boolGzipLogs))
+ {
+ if(m_pLogFile->open(IO_ReadOnly))
+ {
+ QByteArray bytes;
+ bytes=m_pLogFile->readAll();
+ m_pLogFile->close();
+ QFileInfo fi(*m_pLogFile);
+ QString szFname=fi.dirPath(true)+QString("/")+fi.baseName(true);
+ gzFile file=gzopen(QTextCodec::codecForLocale()->fromUnicode(szFname).data(),"ab9");
+ if(file)
+ {
+ gzwrite(file,bytes.data(),bytes.size());
+ gzclose(file);
+ m_pLogFile->remove();
+ } else {
+ debug("Cannot open compressed stream");
+ }
+ }
+ }
+#endif
+ delete m_pLogFile;
+ m_pLogFile = 0;
+ }
+}
+
+void KviIrcView::getLogFileName(KviStr &buffer)
+{
+ if(m_pLogFile)buffer.append(m_pLogFile->name());
+}
+
+void KviIrcView::getLogFileName(QString &buffer)
+{
+ if(m_pLogFile) buffer=m_pLogFile->name();
+}
+
+void KviIrcView::getTextBuffer(QString &buffer)
+{
+ // FIXME: #warning "This does not merge the KviChannel::m_pMessageView buffer!"
+ buffer = "";
+ if(!m_pLastLine)return;
+ for(KviIrcViewLine *l=m_pFirstLine;l;l=l->pNext)
+ {
+ buffer.append(l->szText);
+ buffer.append("\n");
+ }
+}
+
+void KviIrcView::flushLog()
+{
+ if(m_pLogFile) {
+#ifdef COMPILE_ZLIB_SUPPORT
+ if(KVI_OPTION_BOOL(KviOption_boolGzipLogs))
+ {
+ m_pLogFile->close();
+ if(m_pLogFile->open(IO_ReadOnly))
+ {
+ QByteArray bytes;
+ bytes=m_pLogFile->readAll();
+ m_pLogFile->close();
+ QFileInfo fi(*m_pLogFile);
+ QString szFname=fi.dirPath(true)+QString("/")+fi.baseName(true);
+ gzFile file=gzopen(QTextCodec::codecForLocale()->fromUnicode(szFname).data(),"ab9");
+ if(file)
+ {
+ gzwrite(file,bytes.data(),bytes.size());
+ gzclose(file);
+ m_pLogFile->remove();
+ } else {
+ debug("Cannot open compressed stream");
+ }
+ }
+ m_pLogFile->open(IO_Append|IO_WriteOnly);
+ } else
+#endif
+ m_pLogFile->flush();
+ }
+ else if(m_pMasterView)m_pMasterView->flushLog();
+}
+
+const QString & KviIrcView::lastMessageText()
+{
+ KviIrcViewLine * pCur=m_pLastLine;
+ while(pCur)
+ {
+ switch(pCur->iMsgType)
+ {
+ case KVI_OUT_CHANPRIVMSG:
+ case KVI_OUT_CHANPRIVMSGCRYPTED:
+ case KVI_OUT_CHANNELNOTICE:
+ case KVI_OUT_CHANNELNOTICECRYPTED:
+ case KVI_OUT_ACTION:
+ case KVI_OUT_OWNPRIVMSG:
+ case KVI_OUT_OWNPRIVMSGCRYPTED:
+ case KVI_OUT_HIGHLIGHT:
+ return pCur->szText;
+ }
+ pCur=pCur->pPrev;
+ }
+ return KviQString::empty;
+}
+
+const QString & KviIrcView::lastLineOfText()
+{
+ if(!m_pLastLine)return KviQString::empty;
+ return m_pLastLine->szText;
+}
+
+//void KviIrcView::toggleLogging()
+//{
+// if(isLogging())stopLogging();
+// else {
+//#warning "FIX THIS COMMENTED STUFF"
+//
+// KviStr tmp;
+// m_pKviWindow->getDefaultLogName(tmp);
+// startLogging(tmp.ptr());
+//
+// }
+//}
+
+void KviIrcView::setMasterView(KviIrcView * v)
+{
+ if(m_pMasterView)disconnect(this,SLOT(masterDead()));
+ m_pMasterView = v;
+ if(m_pMasterView)connect(m_pMasterView,SIGNAL(destroyed()),this,SLOT(masterDead()));
+}
+
+void KviIrcView::masterDead()
+{
+ m_pMasterView = 0;
+}
+
+bool KviIrcView::startLogging(const QString& fname,bool bPrependCurBuffer)
+{
+ stopLogging();
+ QString szFname(fname);
+
+ if(fname.isEmpty())
+ {
+ if(!m_pKviWindow)return false;
+ m_pKviWindow->getDefaultLogFileName(szFname);
+ }
+
+#ifdef COMPILE_ZLIB_SUPPORT
+ if(KVI_OPTION_BOOL(KviOption_boolGzipLogs))
+ szFname+=".tmp";
+#endif
+
+ m_pLogFile = new QFile(szFname);
+
+ if(m_pLogFile->exists())
+ {
+ if(!m_pLogFile->open(IO_Append|IO_WriteOnly))
+ {
+ delete m_pLogFile;
+ m_pLogFile = 0;
+ return false;
+ }
+ } else {
+ if(!m_pLogFile->open(IO_WriteOnly))
+ {
+ delete m_pLogFile;
+ m_pLogFile = 0;
+ return false;
+ }
+ }
+
+ QString szLogStart;
+ szLogStart.sprintf(__tr2qs("### Log session started at %s ###"),QDateTime::currentDateTime().toString().utf8().data());
+ add2Log(szLogStart);
+ if(bPrependCurBuffer)
+ {
+ add2Log(__tr2qs("### Existing data buffer:"));
+ QString buffer;
+ getTextBuffer(buffer);
+ add2Log(buffer);
+ add2Log(__tr2qs("### End of existing data buffer."));
+ m_pLogFile->flush();
+ }
+
+ return true;
+}
+
+void KviIrcView::add2Log(const QString &szBuffer,int iMsgType)
+{
+ QString szToWrite=QString("%1 %2\n").arg(iMsgType).arg(szBuffer);
+ KviQCString szTmp = KviQString::toUtf8(szToWrite);
+ if(m_pLogFile->writeBlock(szTmp.data(),szTmp.length())==-1) debug("WARNING : Can not write to the log file.");
+}
+
+//=============================================================================
+//
+// Some slots
+//
+
+//void KviIrcView::saveBufferToFile()
+//{
+// // Yeah....this is powerful! :)
+//// KviStr cmd = "/DIALOG (savefile,Choose a file name,$deflogfile($window).savebuf,$window) "
+//// "if(\"$dialogresult\" != \"\")window $dialogmagic savebuffer $dialogresult";
+//// m_pFrm->m_pUserParser->parseUserCommand(cmd,m_pKviWindow);
+//}
+/*
+void KviIrcView::toggleTimestamp()
+{
+ setTimestamp(!timestamp());
+}
+
+void KviIrcView::toggleImages()
+{
+ setShowImages(!imagesVisible());
+}*/
+
+void KviIrcView::clearBuffer()
+{
+ emptyBuffer(true);
+}
+
+bool KviIrcView::saveBuffer(const char *filename)
+{
+ QFile f(QString::fromUtf8(filename));
+ if(!f.open(IO_WriteOnly|IO_Truncate))return false;
+ QString tmp;
+ getTextBuffer(tmp);
+ KviQCString tmpx = KviQString::toUtf8(tmp);
+ f.writeBlock(tmpx.data(),tmpx.length());
+ f.close();
+ return true;
+}
+
+void KviIrcView::prevLine(){ m_pScrollBar->subtractLine(); }
+void KviIrcView::nextLine(){ m_pScrollBar->addLine(); }
+void KviIrcView::prevPage(){ m_pScrollBar->subtractPage(); }
+void KviIrcView::nextPage(){ m_pScrollBar->addPage(); }
+
+void KviIrcView::setPrivateBackgroundPixmap(const QPixmap &pixmap,bool bRepaint)
+{
+ if(m_pPrivateBackgroundPixmap)
+ {
+ delete m_pPrivateBackgroundPixmap;
+ m_pPrivateBackgroundPixmap=0;
+ }
+ if(!pixmap.isNull())m_pPrivateBackgroundPixmap = new QPixmap(pixmap);
+
+ if(bRepaint)
+ update();
+}
+
+void KviIrcView::emptyBuffer(bool bRepaint)
+{
+ while(m_pLastLine != 0)removeHeadLine();
+ if(bRepaint)
+ update();
+}
+
+void KviIrcView::clearLineMark(bool bRepaint)
+{
+ m_uLineMarkLineIndex = KVI_IRCVIEW_INVALID_LINE_MARK_INDEX;
+ clearUnreaded();
+ if(bRepaint)
+ update();
+}
+
+void KviIrcView::checkLogDate()
+{
+ QDate::currentDate();
+}
+
+void KviIrcView::clearUnreaded()
+{
+ m_bHaveUnreadedHighlightedMessages = false;
+ m_bHaveUnreadedMessages = false;
+
+ if(m_pFrm)
+ if(m_pFrm->dockExtension())
+ m_pFrm->dockExtension()->refresh();
+}
+
+void KviIrcView::setMaxBufferSize(int maxBufSize,bool bRepaint)
+{
+ if(maxBufSize < 32)maxBufSize = 32;
+ m_iMaxLines = maxBufSize;
+ while(m_iNumLines > m_iMaxLines)removeHeadLine();
+ m_pScrollBar->setRange(0,m_iNumLines);
+ if(bRepaint)
+ update();
+}
+
+/*
+void KviIrcView::setShowImages(bool bShow,bool bRepaint)
+{
+ if(m_bShowImages!=bShow)
+ {
+ m_bShowImages=bShow;
+ if(bRepaint)paintEvent(0);
+ }
+}
+*/
+/*
+void KviIrcView::setTimestamp(bool bTimestamp)
+{
+ m_bTimestamp = bTimestamp;
+
+
+// STATS FOR A BUFFER FULL OF HIGHLY COLORED STRINGS , HIGHLY WRAPPED
+//
+// Lines = 1024 (322425 bytes - 314 KB) (avg 314 bytes per line) , well :)
+// string bytes = 87745 (85 KB)
+// attributes = 3576 (42912 bytes - 41 KB)
+// blocks = 12226 (146712 bytes - 143 KB)
+//
+// unsigned long int nAlloc = 0;
+// unsigned long int nLines = 0;
+// unsigned long int nStringBytes = 0;
+// unsigned long int nAttrBytes = 0;
+// unsigned long int nBlockBytes = 0;
+// unsigned long int nBlocks = 0;
+// unsigned long int nAttributes = 0;
+// KviIrcViewLine * l=m_pFirstLine;
+// while(l){
+// nLines++;
+// nAlloc += sizeof(KviIrcViewLine);
+// nStringBytes += l->data_len + 1;
+// nAlloc += l->data_len + 1;
+// nAlloc += (l->uChunkCount * sizeof(KviIrcViewLineChunk));
+// nAttrBytes +=(l->uChunkCount * sizeof(KviIrcViewLineChunk));
+// nAlloc += (l->iBlockCount * sizeof(KviIrcViewLineChunk));
+// nBlockBytes += (l->iBlockCount * sizeof(KviIrcViewLineChunk));
+// nBlocks += (l->iBlockCount);
+// nAttributes += (l->uChunkCount);
+// l = l->pNext;
+// }
+// debug("\n\nLines = %u (%u bytes - %u KB) (avg %u bytes per line)",nLines,nAlloc,nAlloc / 1024,nLines ? (nAlloc / nLines) : 0);
+// debug("string bytes = %u (%u KB)",nStringBytes,nStringBytes / 1024);
+// debug("attributes = %u (%u bytes - %u KB)",nAttributes,nAttrBytes,nAttrBytes / 1024);
+// debug("blocks = %u (%u bytes - %u KB)\n",nBlocks,nBlockBytes,nBlockBytes / 1024);
+
+}
+*/
+void KviIrcView::scrollBarPositionChanged(int newValue)
+{
+ if(!m_pCurLine)return;
+ int diff = 0;
+ if(newValue > m_iLastScrollBarValue)
+ {
+ while(newValue > m_iLastScrollBarValue)
+ {
+ if(m_pCurLine->pNext)
+ {
+ m_pCurLine=m_pCurLine->pNext;
+ diff++;
+ }
+ m_iLastScrollBarValue++;
+ }
+ } else {
+ while(newValue < m_iLastScrollBarValue)
+ {
+ if(m_pCurLine->pPrev)m_pCurLine=m_pCurLine->pPrev;
+ m_iLastScrollBarValue--;
+ }
+ }
+ if(!m_bSkipScrollBarRepaint)
+ repaint();
+ //update();
+// if(!m_bSkipScrollBarRepaint)postUpdateEvent();
+}
+
+bool KviIrcView::event(QEvent *e)
+{
+ if(e->type() == QEvent::User)
+ {
+ __range_valid(m_bPostedPaintEventPending);
+ if(m_iUnprocessedPaintEventRequests)
+ repaint();
+ // else we just had a pointEvent that did the job
+ m_bPostedPaintEventPending = false;
+ return true;
+ }
+ return QWidget::event(e);
+}
+
+void KviIrcView::wheelEvent(QWheelEvent *e)
+{
+#ifdef COMPILE_USE_QT4
+ static bool bHere = false;
+ if(bHere)return;
+ bHere = true; // Qt4 tends to jump into infinite recursion here
+#endif
+ g_pApp->sendEvent(m_pScrollBar,e);
+#ifdef COMPILE_USE_QT4
+ bHere = false;
+#endif
+}
+
+
+void KviIrcView::postUpdateEvent()
+{
+ // This will post a QEvent with a full repaint request
+ if(!m_bPostedPaintEventPending)
+ {
+ m_bPostedPaintEventPending = true;
+ QEvent *e = new QEvent(QEvent::User);
+ g_pApp->postEvent(this,e); // queue a repaint
+ }
+
+ m_iUnprocessedPaintEventRequests++; // paintEvent() will set it to 0
+
+ if(m_iUnprocessedPaintEventRequests == 3)
+ {
+ // Three unprocessed paint events...do it now
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ if(! ((KVI_OPTION_PIXMAP(KviOption_pixmapIrcViewBackground).pixmap()) || m_pPrivateBackgroundPixmap || g_pShadedChildGlobalDesktopBackground))
+ fastScroll(3);
+#else
+ if(! ((KVI_OPTION_PIXMAP(KviOption_pixmapIrcViewBackground).pixmap()) || m_pPrivateBackgroundPixmap))
+ fastScroll(3);
+#endif
+ else
+ repaint();
+ }
+}
+
+void KviIrcView::appendLine(KviIrcViewLine *ptr,bool bRepaint)
+{
+ //This one appends a KviIrcViewLine to
+ //the buffer list (at the end)
+ if(m_bMouseIsDown)
+ {
+ // Do not move the view!
+ // So we append the text line to a temp queue
+ // and then we'll add it when the mouse button is released
+ m_pMessagesStoppedWhileSelecting->append(ptr);
+ return;
+ }
+
+ // First log the line and assign the index
+ // Don't use add2log here!...we must go as fast as possible, so we avoid some push and pop calls, and also a couple of branches
+ if(m_pLogFile && KVI_OPTION_BOOL(KviOption_boolStripControlCodesInLogs))
+ {
+ // a slave view has no log files!
+ if(KVI_OPTION_MSGTYPE(ptr->iMsgType).logEnabled())
+ {
+ add2Log(ptr->szText,ptr->iMsgType);
+ // If we fail...this has been already reported!
+ }
+ // mmh.. when this overflows... we have problems (find doesn't work anymore :()
+ // but it overflows at 2^32 lines... 2^32 = 4.294.967.296 lines
+ // to spit it out in a year you'd need to print 1360 lines per second... that's insane :D
+ // a really fast but reasonable rate of printed lines might be 10 per second
+ // thus 429.496.730 seconds would be needed to make this var overflow
+ // that means more or less 13 years of text spitting at full rate :D
+ // I think that we can safely assume that this will NOT overflow ... your cpu (or you)
+ // will get mad before. Well.. it is not that dangerous after all...
+ ptr->uIndex = m_uNextLineIndex;
+ m_uNextLineIndex++;
+ } else {
+ // no log: we could have master view!
+ if(m_pMasterView)
+ {
+ if(m_pMasterView->m_pLogFile && KVI_OPTION_BOOL(KviOption_boolStripControlCodesInLogs))
+ {
+ if(KVI_OPTION_MSGTYPE(ptr->iMsgType).logEnabled())
+ {
+ m_pMasterView->add2Log(ptr->szText,ptr->iMsgType);
+ }
+ }
+ ptr->uIndex = m_pMasterView->m_uNextLineIndex;
+ m_pMasterView->m_uNextLineIndex++;
+ } else {
+ ptr->uIndex = m_uNextLineIndex;
+ m_uNextLineIndex++;
+ }
+ }
+
+ if(m_pLastLine)
+ {
+ // There is at least one line in the view
+ m_pLastLine->pNext=ptr;
+ ptr->pPrev =m_pLastLine;
+ ptr->pNext =0;
+ m_iNumLines++;
+
+ if(m_iNumLines > m_iMaxLines)
+ {
+ // Too many lines in the view...remove one
+ removeHeadLine();
+ if(m_pCurLine==m_pLastLine)
+ {
+ m_pCurLine=ptr;
+ if(bRepaint)
+ postUpdateEvent();
+ } else {
+ // the cur line remains the same
+ // the scroll bar must move up one place to be in sync
+ m_bSkipScrollBarRepaint = true;
+ if(m_pScrollBar->value() > 0)
+ {
+ m_iLastScrollBarValue--;
+ __range_valid(m_iLastScrollBarValue >= 0);
+ m_pScrollBar->subtractLine();
+ } // else will stay in sync
+ m_bSkipScrollBarRepaint = false;
+ }
+ } else {
+ // Just append
+ m_pScrollBar->setRange(0,m_iNumLines);
+ if(m_pCurLine==m_pLastLine)
+ {
+ m_bSkipScrollBarRepaint = true;
+ m_pScrollBar->addLine();
+ m_bSkipScrollBarRepaint = false;
+ if(bRepaint)
+ postUpdateEvent();
+ }
+ }
+ m_pLastLine=ptr;
+ } else {
+ //First line
+ m_pLastLine = ptr;
+ m_pFirstLine = ptr;
+ m_pCurLine = ptr;
+ ptr->pPrev = 0;
+ ptr->pNext = 0;
+ m_iNumLines = 1;
+ m_pScrollBar->setRange(0,1);
+ m_pScrollBar->addLine();
+ if(bRepaint)
+ postUpdateEvent();
+ }
+}
+
+//============== removeHeadLine ===============//
+
+void KviIrcView::removeHeadLine(bool bRepaint)
+{
+ //Removes the first line of the text buffer
+ if(!m_pLastLine)return;
+ if(m_pFirstLine == m_pCursorLine)m_pCursorLine = 0;
+
+ if(m_pFirstLine->pNext)
+ {
+ KviIrcViewLine *aux_ptr=m_pFirstLine->pNext; //get the next line
+ aux_ptr->pPrev=0; //becomes the first
+ if(m_pFirstLine==m_pCurLine)m_pCurLine=aux_ptr; //move the cur line if necessary
+ delete_text_line(m_pFirstLine); //delete the struct
+ m_pFirstLine=aux_ptr; //set the last
+ m_iNumLines--; //and decrement the count
+ } else { //unique line
+ m_pCurLine = 0;
+ delete_text_line(m_pFirstLine);
+ m_pFirstLine = 0;
+ m_iNumLines = 0;
+ m_pLastLine = 0;
+ }
+ if(bRepaint)
+ repaint();
+}
+
+void KviIrcView::splitMessagesTo(KviIrcView *v)
+{
+ v->emptyBuffer(false);
+
+ KviIrcViewLine * l = m_pFirstLine;
+ KviIrcViewLine * tmp;
+ while(l)
+ switch(l->iMsgType)
+ {
+ case KVI_OUT_CHANPRIVMSG:
+ case KVI_OUT_CHANPRIVMSGCRYPTED:
+ case KVI_OUT_CHANNELNOTICE:
+ case KVI_OUT_CHANNELNOTICECRYPTED:
+ case KVI_OUT_ACTION:
+ case KVI_OUT_OWNPRIVMSG:
+ case KVI_OUT_OWNPRIVMSGCRYPTED:
+ case KVI_OUT_HIGHLIGHT:
+ {
+ m_iNumLines--;
+ v->m_iNumLines++;
+
+ if(l->pNext)l->pNext->pPrev = l->pPrev;
+ if(l->pPrev)l->pPrev->pNext = l->pNext;
+ if(l == m_pFirstLine)m_pFirstLine = l->pNext;
+ if(l == m_pLastLine)m_pLastLine = l->pPrev;
+ if(v->m_pLastLine)
+ {
+ v->m_pLastLine->pNext = l;
+ l->pPrev = v->m_pLastLine;
+ v->m_pLastLine = l;
+ } else {
+ v->m_pFirstLine = l;
+ l->pPrev = 0;
+ v->m_pLastLine = l;
+ }
+ tmp = l->pNext;
+ l->pNext = 0;
+ l = tmp;
+ }
+ break;
+ default:
+ l = l->pNext;
+ break;
+ }
+ v->m_pCurLine = v->m_pLastLine;
+ m_pCurLine = m_pLastLine;
+
+ v->m_pCursorLine = 0;
+ m_pCursorLine = 0;
+
+ m_iLastScrollBarValue = m_iNumLines;
+ m_pScrollBar->setRange(0,m_iNumLines);
+ m_pScrollBar->setValue(m_iNumLines);
+
+ repaint();
+
+ v->m_iLastScrollBarValue = v->m_iNumLines;
+ v->m_pScrollBar->setRange(0,v->m_iNumLines);
+ v->m_pScrollBar->setValue(v->m_iNumLines);
+ v->repaint();
+
+}
+
+void KviIrcView::appendMessagesFrom(KviIrcView *v)
+{
+ if(!m_pLastLine)
+ {
+ m_pFirstLine = v->m_pFirstLine;
+ } else {
+ m_pLastLine->pNext = v->m_pFirstLine;
+ v->m_pFirstLine->pPrev = m_pLastLine;
+ }
+ m_pLastLine = v->m_pLastLine;
+ m_pCurLine = m_pLastLine;
+ m_pCursorLine = 0;
+ v->m_pFirstLine = 0;
+ v->m_pLastLine = 0;
+ v->m_pCurLine = 0;
+ v->m_pCursorLine = 0;
+ m_iNumLines += v->m_iNumLines;
+ v->m_iNumLines = 0;
+// v->m_pScrollBar->setRange(0,0);
+// v->m_pScrollBar->setValue(0);
+ m_iLastScrollBarValue = m_iNumLines;
+ m_pScrollBar->setRange(0,m_iNumLines);
+ m_pScrollBar->setValue(m_iNumLines);
+
+ repaint();
+}
+
+void KviIrcView::joinMessagesFrom(KviIrcView *v)
+{
+ KviIrcViewLine * l1 = m_pFirstLine;
+ KviIrcViewLine * l2 = v->m_pFirstLine;
+ KviIrcViewLine * tmp;
+
+ while(l2)
+ {
+ if(l1)
+ {
+ if(l2->uIndex < l1->uIndex)
+ {
+ // the external message is older than the current internal one
+ l2->pPrev = l1->pPrev;
+ if(l1->pPrev)l1->pPrev->pNext = l2;
+ else m_pFirstLine = l2;
+ l1->pPrev = l2;
+ tmp = l2->pNext;
+ l2->pNext = l1;
+ l2 = tmp;
+ } else {
+ // the external message is younger than the current internal one
+ l1 = l1->pNext;
+ }
+ } else {
+ // There is no current internal message (ran over the end)
+ // merge at the end then
+ if(m_pFirstLine)
+ {
+ m_pLastLine->pNext = l2;
+ l2->pPrev = m_pLastLine;
+ } else {
+ m_pFirstLine = l2;
+ l2->pPrev = 0;
+ }
+ tmp = l2->pNext;
+ l2->pNext = 0;
+ m_pLastLine = l2;
+ l2 = tmp;
+ }
+ }
+
+ m_pCurLine = m_pLastLine;
+ m_pCursorLine = 0;
+ v->m_pFirstLine = 0;
+ v->m_pLastLine = 0;
+ v->m_pCurLine = 0;
+ v->m_pCursorLine = 0;
+ m_iNumLines += v->m_iNumLines;
+ v->m_iNumLines = 0;
+// v->m_pScrollBar->setRange(0,0);
+// v->m_pScrollBar->setValue(0);
+
+ m_iLastScrollBarValue = m_iNumLines;
+ m_pScrollBar->setRange(0,m_iNumLines);
+ m_pScrollBar->setValue(m_iNumLines);
+
+ repaint();
+}
+
+void KviIrcView::appendText(int iMsgType,const kvi_wchar_t *data_ptr,int iFlags)
+{
+ //appends a text string to the buffer list
+ //splits the lines
+ __range_valid(data_ptr);
+ m_pLastLinkUnderMouse = 0;
+
+ while(*data_ptr)
+ { //Have more data
+ KviIrcViewLine *line_ptr=new KviIrcViewLine; //create a line struct
+ line_ptr->iMsgType=iMsgType;
+ line_ptr->iMaxLineWidth=-1;
+ line_ptr->iBlockCount=0;
+
+ if(!KVI_OPTION_BOOL(KviOption_boolStripControlCodesInLogs))
+ {
+ QString szBuffer;
+ kvi_appendWCharToQStringWithLength(&szBuffer,data_ptr,kvi_wstrlen(data_ptr));
+ szBuffer.prepend(QDateTime::currentDateTime().toString("[h:mm:ss] "));
+ if(m_pLogFile && KVI_OPTION_MSGTYPE(iMsgType).logEnabled())
+ {
+ add2Log(szBuffer,iMsgType);
+ } else if(m_pMasterView) {
+ if(m_pMasterView->m_pLogFile && KVI_OPTION_MSGTYPE(iMsgType).logEnabled())
+ {
+ m_pMasterView->add2Log(szBuffer,iMsgType);
+ }
+ }
+ }
+
+ data_ptr=getTextLine(iMsgType,data_ptr,line_ptr,!(iFlags & NoTimestamp));
+ appendLine(line_ptr,!(iFlags & NoRepaint));
+ if(iFlags & SetLineMark)
+ {
+ if(KVI_OPTION_BOOL(KviOption_boolTrackLastReadTextViewLine))
+ {
+ m_uLineMarkLineIndex = line_ptr->uIndex;
+ iFlags &= ~SetLineMark;
+ }
+ m_bHaveUnreadedHighlightedMessages = m_bHaveUnreadedHighlightedMessages || iMsgType == KVI_OUT_HIGHLIGHT;
+ m_bHaveUnreadedMessages = m_bHaveUnreadedMessages ||
+ iMsgType == KVI_OUT_CHANPRIVMSG ||
+ iMsgType == KVI_OUT_CHANPRIVMSGCRYPTED ||
+ iMsgType == KVI_OUT_CHANNELNOTICE ||
+ iMsgType == KVI_OUT_CHANNELNOTICECRYPTED ||
+ iMsgType == KVI_OUT_ACTION ||
+ iMsgType == KVI_OUT_OWNPRIVMSGCRYPTED ||
+ iMsgType == KVI_OUT_HIGHLIGHT;
+ }
+ }
+}
+
+
+void KviIrcView::getLinkEscapeCommand(QString &buffer,const QString &szPayload,const QString &escape_label)
+{
+ if(szPayload.isEmpty())return;
+
+ int idx = szPayload.find(escape_label);
+ if(idx == -1)return;
+ idx += escape_label.length();
+
+ int idx2 = szPayload.find("[!",idx);
+ int len = idx2 == -1 ? szPayload.length() - idx : idx2 - idx;
+
+ buffer = szPayload.mid(idx,len);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// The IrcView : Get text line
+//
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+static kvi_wchar_t case_xtx_XX[256] =
+{
+ 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
+ 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
+ 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
+ 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
+ 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
+ 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
+ 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
+ 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
+ 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
+ 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
+ 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
+ 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
+ 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
+ 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
+ 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
+ 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000
+};
+
+static kvi_wchar_t case_ltu_00[256] =
+{
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0130, 0x004A, 0x212A, 0x004C, 0x004D, 0x004E, 0x004F,
+ 0x0050, 0x0051, 0x0052, 0x017F, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x212B, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+ 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x0000, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x0178
+};
+
+
+static kvi_wchar_t case_ltu_01[256] =
+{
+ 0x0000, 0x0100, 0x0000, 0x0102, 0x0000, 0x0104, 0x0000, 0x0106, 0x0000, 0x0108, 0x0000, 0x010A, 0x0000, 0x010C, 0x0000, 0x010E,
+ 0x0000, 0x0110, 0x0000, 0x0112, 0x0000, 0x0114, 0x0000, 0x0116, 0x0000, 0x0118, 0x0000, 0x011A, 0x0000, 0x011C, 0x0000, 0x011E,
+ 0x0000, 0x0120, 0x0000, 0x0122, 0x0000, 0x0124, 0x0000, 0x0126, 0x0000, 0x0128, 0x0000, 0x012A, 0x0000, 0x012C, 0x0000, 0x012E,
+ 0x0000, 0x0049, 0x0000, 0x0132, 0x0000, 0x0134, 0x0000, 0x0136, 0x0000, 0x0000, 0x0139, 0x0000, 0x013B, 0x0000, 0x013D, 0x0000,
+ 0x013F, 0x0000, 0x0141, 0x0000, 0x0143, 0x0000, 0x0145, 0x0000, 0x0147, 0x0000, 0x0000, 0x014A, 0x0000, 0x014C, 0x0000, 0x014E,
+ 0x0000, 0x0150, 0x0000, 0x0152, 0x0000, 0x0154, 0x0000, 0x0156, 0x0000, 0x0158, 0x0000, 0x015A, 0x0000, 0x015C, 0x0000, 0x015E,
+ 0x0000, 0x0160, 0x0000, 0x0162, 0x0000, 0x0164, 0x0000, 0x0166, 0x0000, 0x0168, 0x0000, 0x016A, 0x0000, 0x016C, 0x0000, 0x016E,
+ 0x0000, 0x0170, 0x0000, 0x0172, 0x0000, 0x0174, 0x0000, 0x0176, 0x0000, 0x0000, 0x0179, 0x0000, 0x017B, 0x0000, 0x017D, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0182, 0x0000, 0x0184, 0x0000, 0x0000, 0x0187, 0x0000, 0x0000, 0x0000, 0x018B, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0191, 0x0000, 0x0000, 0x01F6, 0x0000, 0x0000, 0x0000, 0x0198, 0x0000, 0x0000, 0x0000, 0x0000, 0x0220, 0x0000,
+ 0x0000, 0x01A0, 0x0000, 0x01A2, 0x0000, 0x01A4, 0x0000, 0x0000, 0x01A7, 0x0000, 0x0000, 0x0000, 0x0000, 0x01AC, 0x0000, 0x0000,
+ 0x01AF, 0x0000, 0x0000, 0x0000, 0x01B3, 0x0000, 0x01B5, 0x0000, 0x0000, 0x01B8, 0x0000, 0x0000, 0x0000, 0x01BC, 0x0000, 0x01F7,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x01C5, 0x0000, 0x0000, 0x01C8, 0x0000, 0x0000, 0x01CB, 0x0000, 0x01CD, 0x0000,
+ 0x01CF, 0x0000, 0x01D1, 0x0000, 0x01D3, 0x0000, 0x01D5, 0x0000, 0x01D7, 0x0000, 0x01D9, 0x0000, 0x01DB, 0x018E, 0x0000, 0x01DE,
+ 0x0000, 0x01E0, 0x0000, 0x01E2, 0x0000, 0x01E4, 0x0000, 0x01E6, 0x0000, 0x01E8, 0x0000, 0x01EA, 0x0000, 0x01EC, 0x0000, 0x01EE,
+ 0x0000, 0x0000, 0x0000, 0x01F2, 0x0000, 0x01F4, 0x0000, 0x0000, 0x0000, 0x01F8, 0x0000, 0x01FA, 0x0000, 0x01FC, 0x0000, 0x01FE
+};
+
+
+static kvi_wchar_t case_ltu_02[256] =
+{
+ 0x0000, 0x0200, 0x0000, 0x0202, 0x0000, 0x0204, 0x0000, 0x0206, 0x0000, 0x0208, 0x0000, 0x020A, 0x0000, 0x020C, 0x0000, 0x020E,
+ 0x0000, 0x0210, 0x0000, 0x0212, 0x0000, 0x0214, 0x0000, 0x0216, 0x0000, 0x0218, 0x0000, 0x021A, 0x0000, 0x021C, 0x0000, 0x021E,
+ 0x0000, 0x0000, 0x0000, 0x0222, 0x0000, 0x0224, 0x0000, 0x0226, 0x0000, 0x0228, 0x0000, 0x022A, 0x0000, 0x022C, 0x0000, 0x022E,
+ 0x0000, 0x0230, 0x0000, 0x0232, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0181, 0x0186, 0x0000, 0x0189, 0x018A, 0x0000, 0x018F, 0x0000, 0x0190, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0193, 0x0000, 0x0000, 0x0194, 0x0000, 0x0000, 0x0000, 0x0000, 0x0197, 0x0196, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x019C,
+ 0x0000, 0x0000, 0x019D, 0x0000, 0x0000, 0x019F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x01A6, 0x0000, 0x0000, 0x01A9, 0x0000, 0x0000, 0x0000, 0x0000, 0x01AE, 0x0000, 0x01B1, 0x01B2, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x01B7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+
+static kvi_wchar_t case_ltu_03[256] =
+{
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0386, 0x0388, 0x0389, 0x038A,
+ 0x0000, 0x0391, 0x03D0, 0x0393, 0x0394, 0x03F5, 0x0396, 0x0397, 0x03F4, 0x1FBE, 0x03F0, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
+ 0x03D6, 0x03F1, 0x0000, 0x03F2, 0x03A4, 0x03A5, 0x03D5, 0x03A7, 0x03A8, 0x2126, 0x03AA, 0x03AB, 0x038C, 0x038E, 0x038F, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x03D8, 0x0000, 0x03DA, 0x0000, 0x03DC, 0x0000, 0x03DE,
+ 0x0000, 0x03E0, 0x0000, 0x03E2, 0x0000, 0x03E4, 0x0000, 0x03E6, 0x0000, 0x03E8, 0x0000, 0x03EA, 0x0000, 0x03EC, 0x0000, 0x03EE,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+
+static kvi_wchar_t case_ltu_04[256] =
+{
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
+ 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
+ 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, 0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x040D, 0x040E, 0x040F,
+ 0x0000, 0x0460, 0x0000, 0x0462, 0x0000, 0x0464, 0x0000, 0x0466, 0x0000, 0x0468, 0x0000, 0x046A, 0x0000, 0x046C, 0x0000, 0x046E,
+ 0x0000, 0x0470, 0x0000, 0x0472, 0x0000, 0x0474, 0x0000, 0x0476, 0x0000, 0x0478, 0x0000, 0x047A, 0x0000, 0x047C, 0x0000, 0x047E,
+ 0x0000, 0x0480, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x048A, 0x0000, 0x048C, 0x0000, 0x048E,
+ 0x0000, 0x0490, 0x0000, 0x0492, 0x0000, 0x0494, 0x0000, 0x0496, 0x0000, 0x0498, 0x0000, 0x049A, 0x0000, 0x049C, 0x0000, 0x049E,
+ 0x0000, 0x04A0, 0x0000, 0x04A2, 0x0000, 0x04A4, 0x0000, 0x04A6, 0x0000, 0x04A8, 0x0000, 0x04AA, 0x0000, 0x04AC, 0x0000, 0x04AE,
+ 0x0000, 0x04B0, 0x0000, 0x04B2, 0x0000, 0x04B4, 0x0000, 0x04B6, 0x0000, 0x04B8, 0x0000, 0x04BA, 0x0000, 0x04BC, 0x0000, 0x04BE,
+ 0x0000, 0x0000, 0x04C1, 0x0000, 0x04C3, 0x0000, 0x04C5, 0x0000, 0x04C7, 0x0000, 0x04C9, 0x0000, 0x04CB, 0x0000, 0x04CD, 0x0000,
+ 0x0000, 0x04D0, 0x0000, 0x04D2, 0x0000, 0x04D4, 0x0000, 0x04D6, 0x0000, 0x04D8, 0x0000, 0x04DA, 0x0000, 0x04DC, 0x0000, 0x04DE,
+ 0x0000, 0x04E0, 0x0000, 0x04E2, 0x0000, 0x04E4, 0x0000, 0x04E6, 0x0000, 0x04E8, 0x0000, 0x04EA, 0x0000, 0x04EC, 0x0000, 0x04EE,
+ 0x0000, 0x04F0, 0x0000, 0x04F2, 0x0000, 0x04F4, 0x0000, 0x0000, 0x0000, 0x04F8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+
+static kvi_wchar_t case_ltu_05[256] =
+{
+ 0x0000, 0x0500, 0x0000, 0x0502, 0x0000, 0x0504, 0x0000, 0x0506, 0x0000, 0x0508, 0x0000, 0x050A, 0x0000, 0x050C, 0x0000, 0x050E,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0531, 0x0532, 0x0533, 0x0534, 0x0535, 0x0536, 0x0537, 0x0538, 0x0539, 0x053A, 0x053B, 0x053C, 0x053D, 0x053E, 0x053F,
+ 0x0540, 0x0541, 0x0542, 0x0543, 0x0544, 0x0545, 0x0546, 0x0547, 0x0548, 0x0549, 0x054A, 0x054B, 0x054C, 0x054D, 0x054E, 0x054F,
+ 0x0550, 0x0551, 0x0552, 0x0553, 0x0554, 0x0555, 0x0556, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+
+static kvi_wchar_t case_ltu_1E[256] =
+{
+ 0x0000, 0x1E00, 0x0000, 0x1E02, 0x0000, 0x1E04, 0x0000, 0x1E06, 0x0000, 0x1E08, 0x0000, 0x1E0A, 0x0000, 0x1E0C, 0x0000, 0x1E0E,
+ 0x0000, 0x1E10, 0x0000, 0x1E12, 0x0000, 0x1E14, 0x0000, 0x1E16, 0x0000, 0x1E18, 0x0000, 0x1E1A, 0x0000, 0x1E1C, 0x0000, 0x1E1E,
+ 0x0000, 0x1E20, 0x0000, 0x1E22, 0x0000, 0x1E24, 0x0000, 0x1E26, 0x0000, 0x1E28, 0x0000, 0x1E2A, 0x0000, 0x1E2C, 0x0000, 0x1E2E,
+ 0x0000, 0x1E30, 0x0000, 0x1E32, 0x0000, 0x1E34, 0x0000, 0x1E36, 0x0000, 0x1E38, 0x0000, 0x1E3A, 0x0000, 0x1E3C, 0x0000, 0x1E3E,
+ 0x0000, 0x1E40, 0x0000, 0x1E42, 0x0000, 0x1E44, 0x0000, 0x1E46, 0x0000, 0x1E48, 0x0000, 0x1E4A, 0x0000, 0x1E4C, 0x0000, 0x1E4E,
+ 0x0000, 0x1E50, 0x0000, 0x1E52, 0x0000, 0x1E54, 0x0000, 0x1E56, 0x0000, 0x1E58, 0x0000, 0x1E5A, 0x0000, 0x1E5C, 0x0000, 0x1E5E,
+ 0x0000, 0x1E9B, 0x0000, 0x1E62, 0x0000, 0x1E64, 0x0000, 0x1E66, 0x0000, 0x1E68, 0x0000, 0x1E6A, 0x0000, 0x1E6C, 0x0000, 0x1E6E,
+ 0x0000, 0x1E70, 0x0000, 0x1E72, 0x0000, 0x1E74, 0x0000, 0x1E76, 0x0000, 0x1E78, 0x0000, 0x1E7A, 0x0000, 0x1E7C, 0x0000, 0x1E7E,
+ 0x0000, 0x1E80, 0x0000, 0x1E82, 0x0000, 0x1E84, 0x0000, 0x1E86, 0x0000, 0x1E88, 0x0000, 0x1E8A, 0x0000, 0x1E8C, 0x0000, 0x1E8E,
+ 0x0000, 0x1E90, 0x0000, 0x1E92, 0x0000, 0x1E94, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x1EA0, 0x0000, 0x1EA2, 0x0000, 0x1EA4, 0x0000, 0x1EA6, 0x0000, 0x1EA8, 0x0000, 0x1EAA, 0x0000, 0x1EAC, 0x0000, 0x1EAE,
+ 0x0000, 0x1EB0, 0x0000, 0x1EB2, 0x0000, 0x1EB4, 0x0000, 0x1EB6, 0x0000, 0x1EB8, 0x0000, 0x1EBA, 0x0000, 0x1EBC, 0x0000, 0x1EBE,
+ 0x0000, 0x1EC0, 0x0000, 0x1EC2, 0x0000, 0x1EC4, 0x0000, 0x1EC6, 0x0000, 0x1EC8, 0x0000, 0x1ECA, 0x0000, 0x1ECC, 0x0000, 0x1ECE,
+ 0x0000, 0x1ED0, 0x0000, 0x1ED2, 0x0000, 0x1ED4, 0x0000, 0x1ED6, 0x0000, 0x1ED8, 0x0000, 0x1EDA, 0x0000, 0x1EDC, 0x0000, 0x1EDE,
+ 0x0000, 0x1EE0, 0x0000, 0x1EE2, 0x0000, 0x1EE4, 0x0000, 0x1EE6, 0x0000, 0x1EE8, 0x0000, 0x1EEA, 0x0000, 0x1EEC, 0x0000, 0x1EEE,
+ 0x0000, 0x1EF0, 0x0000, 0x1EF2, 0x0000, 0x1EF4, 0x0000, 0x1EF6, 0x0000, 0x1EF8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+
+static kvi_wchar_t case_ltu_1F[256] =
+{
+ 0x1F08, 0x1F09, 0x1F0A, 0x1F0B, 0x1F0C, 0x1F0D, 0x1F0E, 0x1F0F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1F18, 0x1F19, 0x1F1A, 0x1F1B, 0x1F1C, 0x1F1D, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1F28, 0x1F29, 0x1F2A, 0x1F2B, 0x1F2C, 0x1F2D, 0x1F2E, 0x1F2F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1F38, 0x1F39, 0x1F3A, 0x1F3B, 0x1F3C, 0x1F3D, 0x1F3E, 0x1F3F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1F48, 0x1F49, 0x1F4A, 0x1F4B, 0x1F4C, 0x1F4D, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x1F59, 0x0000, 0x1F5B, 0x0000, 0x1F5D, 0x0000, 0x1F5F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1F68, 0x1F69, 0x1F6A, 0x1F6B, 0x1F6C, 0x1F6D, 0x1F6E, 0x1F6F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1FBA, 0x1FBB, 0x1FC8, 0x1FC9, 0x1FCA, 0x1FCB, 0x1FDA, 0x1FDB, 0x1FF8, 0x1FF9, 0x1FEA, 0x1FEB, 0x1FFA, 0x1FFB, 0x0000, 0x0000,
+ 0x1F88, 0x1F89, 0x1F8A, 0x1F8B, 0x1F8C, 0x1F8D, 0x1F8E, 0x1F8F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1F98, 0x1F99, 0x1F9A, 0x1F9B, 0x1F9C, 0x1F9D, 0x1F9E, 0x1F9F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1FA8, 0x1FA9, 0x1FAA, 0x1FAB, 0x1FAC, 0x1FAD, 0x1FAE, 0x1FAF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1FB8, 0x1FB9, 0x0000, 0x1FBC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x1FCC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1FD8, 0x1FD9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1FE8, 0x1FE9, 0x0000, 0x0000, 0x0000, 0x1FEC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x1FFC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+
+static kvi_wchar_t case_ltu_21[256] =
+{
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216A, 0x216B, 0x216C, 0x216D, 0x216E, 0x216F,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+
+static kvi_wchar_t case_ltu_24[256] =
+{
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x24B6, 0x24B7, 0x24B8, 0x24B9, 0x24BA, 0x24BB, 0x24BC, 0x24BD, 0x24BE, 0x24BF, 0x24C0, 0x24C1, 0x24C2, 0x24C3, 0x24C4, 0x24C5,
+ 0x24C6, 0x24C7, 0x24C8, 0x24C9, 0x24CA, 0x24CB, 0x24CC, 0x24CD, 0x24CE, 0x24CF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+
+static kvi_wchar_t case_ltu_FF[256] =
+{
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xFF21, 0xFF22, 0xFF23, 0xFF24, 0xFF25, 0xFF26, 0xFF27, 0xFF28, 0xFF29, 0xFF2A, 0xFF2B, 0xFF2C, 0xFF2D, 0xFF2E, 0xFF2F,
+ 0xFF30, 0xFF31, 0xFF32, 0xFF33, 0xFF34, 0xFF35, 0xFF36, 0xFF37, 0xFF38, 0xFF39, 0xFF3A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+
+kvi_wchar_t * kvirc_case_map_ltu[256] =
+{
+ case_ltu_00, case_ltu_01, case_ltu_02, case_ltu_03, case_ltu_04, case_ltu_05, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_ltu_1E, case_ltu_1F,
+ case_xtx_XX, case_ltu_21, case_xtx_XX, case_xtx_XX, case_ltu_24, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_ltu_FF
+};
+
+
+static kvi_wchar_t case_utl_00[256] =
+{
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0131, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x03BC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+ 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x0000, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+
+static kvi_wchar_t case_utl_01[256] =
+{
+ 0x0101, 0x0000, 0x0103, 0x0000, 0x0105, 0x0000, 0x0107, 0x0000, 0x0109, 0x0000, 0x010B, 0x0000, 0x010D, 0x0000, 0x010F, 0x0000,
+ 0x0111, 0x0000, 0x0113, 0x0000, 0x0115, 0x0000, 0x0117, 0x0000, 0x0119, 0x0000, 0x011B, 0x0000, 0x011D, 0x0000, 0x011F, 0x0000,
+ 0x0121, 0x0000, 0x0123, 0x0000, 0x0125, 0x0000, 0x0127, 0x0000, 0x0129, 0x0000, 0x012B, 0x0000, 0x012D, 0x0000, 0x012F, 0x0000,
+ 0x0069, 0x0000, 0x0133, 0x0000, 0x0135, 0x0000, 0x0137, 0x0000, 0x0000, 0x013A, 0x0000, 0x013C, 0x0000, 0x013E, 0x0000, 0x0140,
+ 0x0000, 0x0142, 0x0000, 0x0144, 0x0000, 0x0146, 0x0000, 0x0148, 0x0000, 0x0000, 0x014B, 0x0000, 0x014D, 0x0000, 0x014F, 0x0000,
+ 0x0151, 0x0000, 0x0153, 0x0000, 0x0155, 0x0000, 0x0157, 0x0000, 0x0159, 0x0000, 0x015B, 0x0000, 0x015D, 0x0000, 0x015F, 0x0000,
+ 0x0161, 0x0000, 0x0163, 0x0000, 0x0165, 0x0000, 0x0167, 0x0000, 0x0169, 0x0000, 0x016B, 0x0000, 0x016D, 0x0000, 0x016F, 0x0000,
+ 0x0171, 0x0000, 0x0173, 0x0000, 0x0175, 0x0000, 0x0177, 0x0000, 0x00FF, 0x017A, 0x0000, 0x017C, 0x0000, 0x017E, 0x0000, 0x0073,
+ 0x0000, 0x0253, 0x0183, 0x0000, 0x0185, 0x0000, 0x0254, 0x0188, 0x0000, 0x0256, 0x0257, 0x018C, 0x0000, 0x0000, 0x01DD, 0x0259,
+ 0x025B, 0x0192, 0x0000, 0x0260, 0x0263, 0x0000, 0x0269, 0x0268, 0x0199, 0x0000, 0x0000, 0x0000, 0x026F, 0x0272, 0x0000, 0x0275,
+ 0x01A1, 0x0000, 0x01A3, 0x0000, 0x01A5, 0x0000, 0x0280, 0x01A8, 0x0000, 0x0283, 0x0000, 0x0000, 0x01AD, 0x0000, 0x0288, 0x01B0,
+ 0x0000, 0x028A, 0x028B, 0x01B4, 0x0000, 0x01B6, 0x0000, 0x0292, 0x01B9, 0x0000, 0x0000, 0x0000, 0x01BD, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x01C6, 0x01C6, 0x0000, 0x01C9, 0x01C9, 0x0000, 0x01CC, 0x01CC, 0x0000, 0x01CE, 0x0000, 0x01D0,
+ 0x0000, 0x01D2, 0x0000, 0x01D4, 0x0000, 0x01D6, 0x0000, 0x01D8, 0x0000, 0x01DA, 0x0000, 0x01DC, 0x0000, 0x0000, 0x01DF, 0x0000,
+ 0x01E1, 0x0000, 0x01E3, 0x0000, 0x01E5, 0x0000, 0x01E7, 0x0000, 0x01E9, 0x0000, 0x01EB, 0x0000, 0x01ED, 0x0000, 0x01EF, 0x0000,
+ 0x0000, 0x01F3, 0x01F3, 0x0000, 0x01F5, 0x0000, 0x0195, 0x01BF, 0x01F9, 0x0000, 0x01FB, 0x0000, 0x01FD, 0x0000, 0x01FF, 0x0000
+};
+
+
+static kvi_wchar_t case_utl_02[256] =
+{
+ 0x0201, 0x0000, 0x0203, 0x0000, 0x0205, 0x0000, 0x0207, 0x0000, 0x0209, 0x0000, 0x020B, 0x0000, 0x020D, 0x0000, 0x020F, 0x0000,
+ 0x0211, 0x0000, 0x0213, 0x0000, 0x0215, 0x0000, 0x0217, 0x0000, 0x0219, 0x0000, 0x021B, 0x0000, 0x021D, 0x0000, 0x021F, 0x0000,
+ 0x019E, 0x0000, 0x0223, 0x0000, 0x0225, 0x0000, 0x0227, 0x0000, 0x0229, 0x0000, 0x022B, 0x0000, 0x022D, 0x0000, 0x022F, 0x0000,
+ 0x0231, 0x0000, 0x0233, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+
+static kvi_wchar_t case_utl_03[256] =
+{
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x03B9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x03AC, 0x0000, 0x03AD, 0x03AE, 0x03AF, 0x0000, 0x03CC, 0x0000, 0x03CD, 0x03CE,
+ 0x0000, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
+ 0x03C0, 0x03C1, 0x0000, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x03C3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x03B2, 0x03B8, 0x0000, 0x0000, 0x0000, 0x03C6, 0x03C0, 0x0000, 0x03D9, 0x0000, 0x03DB, 0x0000, 0x03DD, 0x0000, 0x03DF, 0x0000,
+ 0x03E1, 0x0000, 0x03E3, 0x0000, 0x03E5, 0x0000, 0x03E7, 0x0000, 0x03E9, 0x0000, 0x03EB, 0x0000, 0x03ED, 0x0000, 0x03EF, 0x0000,
+ 0x03BA, 0x03C1, 0x03C3, 0x0000, 0x03B8, 0x03B5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+
+static kvi_wchar_t case_utl_04[256] =
+{
+ 0x0450, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457, 0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x045D, 0x045E, 0x045F,
+ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
+ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0461, 0x0000, 0x0463, 0x0000, 0x0465, 0x0000, 0x0467, 0x0000, 0x0469, 0x0000, 0x046B, 0x0000, 0x046D, 0x0000, 0x046F, 0x0000,
+ 0x0471, 0x0000, 0x0473, 0x0000, 0x0475, 0x0000, 0x0477, 0x0000, 0x0479, 0x0000, 0x047B, 0x0000, 0x047D, 0x0000, 0x047F, 0x0000,
+ 0x0481, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x048B, 0x0000, 0x048D, 0x0000, 0x048F, 0x0000,
+ 0x0491, 0x0000, 0x0493, 0x0000, 0x0495, 0x0000, 0x0497, 0x0000, 0x0499, 0x0000, 0x049B, 0x0000, 0x049D, 0x0000, 0x049F, 0x0000,
+ 0x04A1, 0x0000, 0x04A3, 0x0000, 0x04A5, 0x0000, 0x04A7, 0x0000, 0x04A9, 0x0000, 0x04AB, 0x0000, 0x04AD, 0x0000, 0x04AF, 0x0000,
+ 0x04B1, 0x0000, 0x04B3, 0x0000, 0x04B5, 0x0000, 0x04B7, 0x0000, 0x04B9, 0x0000, 0x04BB, 0x0000, 0x04BD, 0x0000, 0x04BF, 0x0000,
+ 0x0000, 0x04C2, 0x0000, 0x04C4, 0x0000, 0x04C6, 0x0000, 0x04C8, 0x0000, 0x04CA, 0x0000, 0x04CC, 0x0000, 0x04CE, 0x0000, 0x0000,
+ 0x04D1, 0x0000, 0x04D3, 0x0000, 0x04D5, 0x0000, 0x04D7, 0x0000, 0x04D9, 0x0000, 0x04DB, 0x0000, 0x04DD, 0x0000, 0x04DF, 0x0000,
+ 0x04E1, 0x0000, 0x04E3, 0x0000, 0x04E5, 0x0000, 0x04E7, 0x0000, 0x04E9, 0x0000, 0x04EB, 0x0000, 0x04ED, 0x0000, 0x04EF, 0x0000,
+ 0x04F1, 0x0000, 0x04F3, 0x0000, 0x04F5, 0x0000, 0x0000, 0x0000, 0x04F9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+
+static kvi_wchar_t case_utl_05[256] =
+{
+ 0x0501, 0x0000, 0x0503, 0x0000, 0x0505, 0x0000, 0x0507, 0x0000, 0x0509, 0x0000, 0x050B, 0x0000, 0x050D, 0x0000, 0x050F, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567, 0x0568, 0x0569, 0x056A, 0x056B, 0x056C, 0x056D, 0x056E, 0x056F,
+ 0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577, 0x0578, 0x0579, 0x057A, 0x057B, 0x057C, 0x057D, 0x057E, 0x057F,
+ 0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+
+static kvi_wchar_t case_utl_1E[256] =
+{
+ 0x1E01, 0x0000, 0x1E03, 0x0000, 0x1E05, 0x0000, 0x1E07, 0x0000, 0x1E09, 0x0000, 0x1E0B, 0x0000, 0x1E0D, 0x0000, 0x1E0F, 0x0000,
+ 0x1E11, 0x0000, 0x1E13, 0x0000, 0x1E15, 0x0000, 0x1E17, 0x0000, 0x1E19, 0x0000, 0x1E1B, 0x0000, 0x1E1D, 0x0000, 0x1E1F, 0x0000,
+ 0x1E21, 0x0000, 0x1E23, 0x0000, 0x1E25, 0x0000, 0x1E27, 0x0000, 0x1E29, 0x0000, 0x1E2B, 0x0000, 0x1E2D, 0x0000, 0x1E2F, 0x0000,
+ 0x1E31, 0x0000, 0x1E33, 0x0000, 0x1E35, 0x0000, 0x1E37, 0x0000, 0x1E39, 0x0000, 0x1E3B, 0x0000, 0x1E3D, 0x0000, 0x1E3F, 0x0000,
+ 0x1E41, 0x0000, 0x1E43, 0x0000, 0x1E45, 0x0000, 0x1E47, 0x0000, 0x1E49, 0x0000, 0x1E4B, 0x0000, 0x1E4D, 0x0000, 0x1E4F, 0x0000,
+ 0x1E51, 0x0000, 0x1E53, 0x0000, 0x1E55, 0x0000, 0x1E57, 0x0000, 0x1E59, 0x0000, 0x1E5B, 0x0000, 0x1E5D, 0x0000, 0x1E5F, 0x0000,
+ 0x1E61, 0x0000, 0x1E63, 0x0000, 0x1E65, 0x0000, 0x1E67, 0x0000, 0x1E69, 0x0000, 0x1E6B, 0x0000, 0x1E6D, 0x0000, 0x1E6F, 0x0000,
+ 0x1E71, 0x0000, 0x1E73, 0x0000, 0x1E75, 0x0000, 0x1E77, 0x0000, 0x1E79, 0x0000, 0x1E7B, 0x0000, 0x1E7D, 0x0000, 0x1E7F, 0x0000,
+ 0x1E81, 0x0000, 0x1E83, 0x0000, 0x1E85, 0x0000, 0x1E87, 0x0000, 0x1E89, 0x0000, 0x1E8B, 0x0000, 0x1E8D, 0x0000, 0x1E8F, 0x0000,
+ 0x1E91, 0x0000, 0x1E93, 0x0000, 0x1E95, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1E61, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1EA1, 0x0000, 0x1EA3, 0x0000, 0x1EA5, 0x0000, 0x1EA7, 0x0000, 0x1EA9, 0x0000, 0x1EAB, 0x0000, 0x1EAD, 0x0000, 0x1EAF, 0x0000,
+ 0x1EB1, 0x0000, 0x1EB3, 0x0000, 0x1EB5, 0x0000, 0x1EB7, 0x0000, 0x1EB9, 0x0000, 0x1EBB, 0x0000, 0x1EBD, 0x0000, 0x1EBF, 0x0000,
+ 0x1EC1, 0x0000, 0x1EC3, 0x0000, 0x1EC5, 0x0000, 0x1EC7, 0x0000, 0x1EC9, 0x0000, 0x1ECB, 0x0000, 0x1ECD, 0x0000, 0x1ECF, 0x0000,
+ 0x1ED1, 0x0000, 0x1ED3, 0x0000, 0x1ED5, 0x0000, 0x1ED7, 0x0000, 0x1ED9, 0x0000, 0x1EDB, 0x0000, 0x1EDD, 0x0000, 0x1EDF, 0x0000,
+ 0x1EE1, 0x0000, 0x1EE3, 0x0000, 0x1EE5, 0x0000, 0x1EE7, 0x0000, 0x1EE9, 0x0000, 0x1EEB, 0x0000, 0x1EED, 0x0000, 0x1EEF, 0x0000,
+ 0x1EF1, 0x0000, 0x1EF3, 0x0000, 0x1EF5, 0x0000, 0x1EF7, 0x0000, 0x1EF9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+
+static kvi_wchar_t case_utl_1F[256] =
+{
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1F00, 0x1F01, 0x1F02, 0x1F03, 0x1F04, 0x1F05, 0x1F06, 0x1F07,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1F10, 0x1F11, 0x1F12, 0x1F13, 0x1F14, 0x1F15, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1F20, 0x1F21, 0x1F22, 0x1F23, 0x1F24, 0x1F25, 0x1F26, 0x1F27,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1F30, 0x1F31, 0x1F32, 0x1F33, 0x1F34, 0x1F35, 0x1F36, 0x1F37,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1F40, 0x1F41, 0x1F42, 0x1F43, 0x1F44, 0x1F45, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1F51, 0x0000, 0x1F53, 0x0000, 0x1F55, 0x0000, 0x1F57,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1F60, 0x1F61, 0x1F62, 0x1F63, 0x1F64, 0x1F65, 0x1F66, 0x1F67,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1F80, 0x1F81, 0x1F82, 0x1F83, 0x1F84, 0x1F85, 0x1F86, 0x1F87,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1F90, 0x1F91, 0x1F92, 0x1F93, 0x1F94, 0x1F95, 0x1F96, 0x1F97,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1FA0, 0x1FA1, 0x1FA2, 0x1FA3, 0x1FA4, 0x1FA5, 0x1FA6, 0x1FA7,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1FB0, 0x1FB1, 0x1F70, 0x1F71, 0x1FB3, 0x0000, 0x03B9, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1F72, 0x1F73, 0x1F74, 0x1F75, 0x1FC3, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1FD0, 0x1FD1, 0x1F76, 0x1F77, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1FE0, 0x1FE1, 0x1F7A, 0x1F7B, 0x1FE5, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1F78, 0x1F79, 0x1F7C, 0x1F7D, 0x1FF3, 0x0000, 0x0000, 0x0000
+};
+
+
+static kvi_wchar_t case_utl_21[256] =
+{
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x03C9, 0x0000, 0x0000, 0x0000, 0x006B, 0x00E5, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+
+static kvi_wchar_t case_utl_24[256] =
+{
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x24D0, 0x24D1, 0x24D2, 0x24D3, 0x24D4, 0x24D5, 0x24D6, 0x24D7, 0x24D8, 0x24D9,
+ 0x24DA, 0x24DB, 0x24DC, 0x24DD, 0x24DE, 0x24DF, 0x24E0, 0x24E1, 0x24E2, 0x24E3, 0x24E4, 0x24E5, 0x24E6, 0x24E7, 0x24E8, 0x24E9,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+
+static kvi_wchar_t case_utl_FF[256] =
+{
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F,
+ 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57, 0xFF58, 0xFF59, 0xFF5A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+
+kvi_wchar_t * kvirc_case_map_utl[256] =
+{
+ case_utl_00, case_utl_01, case_utl_02, case_utl_03, case_utl_04, case_utl_05, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_utl_1E, case_utl_1F,
+ case_xtx_XX, case_utl_21, case_xtx_XX, case_xtx_XX, case_utl_24, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX,
+ case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_xtx_XX, case_utl_FF
+};
+
+
+// Case mapping tables are 13824 bytes long
+
+
+
+kvi_wchar_t kvi_wtolower(kvi_wchar_t c)
+{
+ kvi_wchar_t l = kvirc_case_map_utl[c >> 8][c & 0xff];
+ return l ? l : c;
+}
+
+bool kvi_hstrEqualCIN(const kvi_wchar_t *str1,const char *str2,int len)
+{
+ while(len-- && *str1)if(kvi_wtolower(*str1++) != (kvi_wchar_t)tolower(*str2++))return false;
+ return (len < 0);
+}
+
+
+const kvi_wchar_t * KviIrcView::getTextLine(int iMsgType,
+ const kvi_wchar_t * data_ptr,
+ KviIrcViewLine *line_ptr,
+ bool bEnableTimeStamp)
+{
+ const kvi_wchar_t* pUnEscapeAt = 0;
+ // Splits the text data in lines (separated by '\n')
+
+ // NOTE: This function may be NOT reentrant
+ // ... no function in this file is supposed to be thread safe anyway
+
+ int iTextIdx = 0; //we're at the beginning in the buffer
+ int iCurChunk = 0;
+ int blockLen;
+
+ register const kvi_wchar_t *p= data_ptr;
+
+ //Alloc the first attribute
+ line_ptr->uChunkCount = 1;
+ line_ptr->pChunks = (KviIrcViewLineChunk *)kvi_malloc(sizeof(KviIrcViewLineChunk));
+ //And fill it up
+ line_ptr->pChunks[0].type = KVI_TEXT_COLOR;
+ line_ptr->pChunks[0].iTextStart = 0;
+ line_ptr->pChunks[0].colors.back = KVI_OPTION_MSGTYPE(iMsgType).back();
+ line_ptr->pChunks[0].colors.fore = KVI_OPTION_MSGTYPE(iMsgType).fore();
+ line_ptr->pChunks[0].customFore=QColor();
+
+ if(bEnableTimeStamp && KVI_OPTION_BOOL(KviOption_boolIrcViewTimestamp))
+ {
+ QString szTimestamp;
+ szTimestamp=QDateTime::currentDateTime (
+ KVI_OPTION_BOOL(KviOption_boolIrcViewTimestampUTC) ? Qt::UTC : Qt::LocalTime ).toString(
+ KVI_OPTION_STRING(KviOption_stringIrcViewTimestampFormat) );
+ szTimestamp.append(' ');
+ int iTimeStampLength=szTimestamp.length();
+
+ if(KVI_OPTION_BOOL(KviOption_boolUseSpecialColorForTimestamp))
+ {
+ // we need three chunks: the first one uses the default colors
+ // for the message type, the second one the special colors
+ // of the timestamp and the third one goes back to the defaults
+ line_ptr->pChunks[0].iTextLen = 0;
+
+ line_ptr->uChunkCount=3;
+ line_ptr->pChunks=(KviIrcViewLineChunk *)kvi_realloc((void *)line_ptr->pChunks,3 * sizeof(KviIrcViewLineChunk));
+
+ line_ptr->pChunks[1].type = KVI_TEXT_COLOR;
+ line_ptr->pChunks[1].iTextStart = 0;
+ line_ptr->pChunks[1].iTextLen = iTimeStampLength-1;
+ line_ptr->pChunks[1].colors.back = KVI_OPTION_UINT(KviOption_uintTimeStampBackground);
+ line_ptr->pChunks[1].colors.fore = KVI_OPTION_UINT(KviOption_uintTimeStampForeground);
+
+ line_ptr->pChunks[2].type = KVI_TEXT_COLOR;
+ line_ptr->pChunks[2].iTextStart = iTimeStampLength-1;
+ line_ptr->pChunks[2].iTextLen = 1;
+ line_ptr->pChunks[2].colors.back = KVI_OPTION_MSGTYPE(iMsgType).back();
+ line_ptr->pChunks[2].colors.fore = KVI_OPTION_MSGTYPE(iMsgType).fore();
+ line_ptr->pChunks[2].customFore=QColor();
+ iCurChunk+=2;
+ } else {
+ // only one chunk
+ line_ptr->pChunks[0].iTextLen = iTimeStampLength;
+ }
+
+ // We need the timestamp string to be added
+ // alloc the necessary space
+ line_ptr->szText.setLength(iTimeStampLength);
+
+ iTextIdx = iTimeStampLength; // the rest of the string will begin 11 chars later
+
+ // throw away const: we WANT to set the chars :D
+ register QChar * data_ptr_aux = (QChar *)line_ptr->szText.unicode();
+ register QChar * stamp_ptr_aux = (QChar *)szTimestamp.unicode();
+
+ for(int i=0;i<iTimeStampLength;i++)
+ *data_ptr_aux++ = *stamp_ptr_aux++;
+ } else {
+ // Timestamp not needed... but we don't want null strings floating around
+ line_ptr->szText = "";
+ line_ptr->pChunks[0].iTextLen = 0;
+ }
+
+ //
+ // Ok... a couple of macros that occur really frequently
+ // in the following code...
+ // these could work well as functions too...but the macros are a lot faster :)
+ //
+
+#define APPEND_LAST_TEXT_BLOCK(__data_ptr,__data_len) \
+ blockLen = (__data_len); \
+ line_ptr->pChunks[iCurChunk].iTextLen += blockLen; \
+ kvi_appendWCharToQStringWithLength(&(line_ptr->szText),__data_ptr,__data_len); \
+ iTextIdx+=blockLen;
+
+#define APPEND_LAST_TEXT_BLOCK_HIDDEN_FROM_NOW(__data_ptr,__data_len) \
+ blockLen = (__data_len); \
+ kvi_appendWCharToQStringWithLength(&(line_ptr->szText),__data_ptr,__data_len); \
+ iTextIdx+=blockLen;
+
+
+#define APPEND_ZERO_LENGTH_BLOCK(__data_ptr) /* does nothing */
+
+#define NEW_LINE_CHUNK(_chunk_type) \
+ line_ptr->uChunkCount++; \
+ line_ptr->pChunks=(KviIrcViewLineChunk *)kvi_realloc((void *)line_ptr->pChunks, \
+ line_ptr->uChunkCount * sizeof(KviIrcViewLineChunk)); \
+ iCurChunk++; \
+ line_ptr->pChunks[iCurChunk].type = _chunk_type; \
+ line_ptr->pChunks[iCurChunk].iTextStart = iTextIdx; \
+ line_ptr->pChunks[iCurChunk].iTextLen = 0; \
+ line_ptr->pChunks[iCurChunk].customFore=iCurChunk ? line_ptr->pChunks[iCurChunk-1].customFore : QColor();
+
+ // EOF Macros
+
+ int partLen;
+
+#ifdef COMPILE_USE_DYNAMIC_LABELS
+
+ // Herezy :)
+
+ // This is not only usage of the *Evil Goto(tm)*
+ // This is also a *rather unclear* use of the *Really Evil Goto(tm)*
+ // char_to_check_jump_table is a table of dynamic label addresses...
+ // we use it to jump to the proper check
+ // loop_begin is a dynamic label, and we use it to
+ // return to the appropriate loop
+ // This is again BAD PROGRAMMING(TM) :).... but it is faster than
+ // the version with no dynamic gotos, and really faster
+ // that any version without gotos that comed into my mind...
+ //
+ // This code will prolly work only with GCC...(and even needs a "smart" one)
+
+ // Again did two versions... the first was:
+ //
+ // if(void * jmp_address = char_to_check_jump_table[*((unsigned char *)p)])goto *jmp_address;
+ // 18a3: 8b 55 f0 movl 0xfffffff0(%ebp),%edx
+ // 18a6: 31 c0 xorl %eax,%eax
+ // 18a8: 8a 02 movb (%edx),%al
+ // 18aa: 8b 04 85 20 00 00 00 movl 0x20(,%eax,4),%eax
+ // 18b1: 85 c0 testl %eax,%eax
+ // 18b3: 74 02 je 18b7 <KviIrcView::getTextLine(int, char const *, KviIrcViewLine *)+0x1f3>
+ // 18b5: ff e0 jmp *%eax
+ //
+ // I even had a nicer version:
+ //
+ // goto *(char_to_check_jump_table[*((unsigned char *)p)]);
+ // 18a3: 8b 55 f0 movl 0xfffffff0(%ebp),%edx
+ // 18a6: 31 c0 xorl %eax,%eax
+ // 18a8: 8a 02 movb (%edx),%al
+ // 18aa: ff 24 85 20 00 00 00 jmp *0x20(,%eax,4)
+ //
+ // but sth tells me that "jmp *0x20(,%eax,4)" takes a loooooot of clock ticks...
+ // ...we have less instructions , but the code takes longer to execute (7-8% longer)
+ // it might be also due to pipeline tricks, jump "next instruction precalculation" stuff...
+
+ // So we end up using the fist version here
+
+ void * loop_begin;
+
+ static void * char_to_check_jump_table[256]=
+ {
+ &&found_end_of_buffer ,0 ,&&found_mirc_escape ,&&found_color_escape ,
+ 0 ,0 ,0 ,0 ,
+ 0 ,0 ,&&found_end_of_line ,0 ,
+ 0 ,&&found_command_escape ,0 ,&&found_mirc_escape ,
+ 0 ,0 ,0 ,0 ,
+ 0 ,0 ,&&found_mirc_escape ,0 ,
+ 0 ,0 ,0 ,0 ,
+ 0 ,&&found_icon_escape ,0 ,&&found_mirc_escape , // 000-031
+ 0 ,0 ,0 ,0 ,
+ 0 ,0 ,0 ,0 ,
+ 0 ,0 ,0 ,0 ,
+ 0 ,0 ,0 ,0 , // 032-047
+ 0 ,0 ,0 ,0 ,
+ 0 ,0 ,0 ,0 ,
+ 0 ,0 ,&&check_emoticon_char ,&&check_emoticon_char ,
+ 0 ,&&check_emoticon_char ,0 ,0 , // 048-063 // 61='=' , 59=';' , 58=':'
+ 0 ,0 ,0 ,0 ,
+ 0 ,&&check_e2k_url ,&&check_file_or_ftp_url,0 ,
+ &&check_http_url ,&&check_irc_url ,0 ,0 ,
+ 0 ,&&check_mailto_url ,0 ,0 , // 064-079 // 070==F 072==H 073==I 077==M
+ 0 ,0 ,0 ,0 ,
+ 0 ,0 ,0 ,&&check_www_url ,
+ 0 ,0 ,0 ,0 ,
+ 0 ,0 ,0 ,0 , // 080-095 // 087==W
+ 0 ,0 ,0 ,0 ,
+ 0 ,&&check_e2k_url ,&&check_file_or_ftp_url,0 ,
+ &&check_http_url ,&&check_irc_url ,0 ,0 ,
+ 0 ,&&check_mailto_url ,0 ,0 , // 096-111 // 101=e 102=f 104=h 105=i 109==m
+ 0 ,0 ,0 ,0 ,
+ 0 ,0 ,0 ,&&check_www_url ,
+ 0 ,0 ,0 ,0 ,
+ 0 ,0 ,0 ,0 , // 112-127 // 119==w
+ 0 ,0 ,0 ,0 ,
+ 0 ,0 ,0 ,0 ,
+ 0 ,0 ,0 ,0 ,
+ 0 ,0 ,0 ,0 , // 128-133
+ 0 ,0 ,0 ,0 ,
+ 0 ,0 ,0 ,0 ,
+ 0 ,0 ,0 ,0 ,
+ 0 ,0 ,0 ,0 , // 134-159
+ 0 ,0 ,0 ,0 ,
+ 0 ,0 ,0 ,0 ,
+ 0 ,0 ,0 ,0 ,
+ 0 ,0 ,0 ,0 , // 160-175
+ 0 ,0 ,0 ,0 ,
+ 0 ,0 ,0 ,0 ,
+ 0 ,0 ,0 ,0 ,
+ 0 ,0 ,0 ,0 , // 176-191
+ 0 ,0 ,0 ,0 ,
+ 0 ,0 ,0 ,0 ,
+ 0 ,0 ,0 ,0 ,
+ 0 ,0 ,0 ,0 , // 192-207
+ 0 ,0 ,0 ,0 ,
+ 0 ,0 ,0 ,0 ,
+ 0 ,0 ,0 ,0 ,
+ 0 ,0 ,0 ,0 , // 208-223
+ 0 ,0 ,0 ,0 ,
+ 0 ,0 ,0 ,0 ,
+ 0 ,0 ,0 ,0 ,
+ 0 ,0 ,0 ,0 , // 224-239
+ 0 ,0 ,0 ,0 ,
+ 0 ,0 ,0 ,0 ,
+ 0 ,0 ,0 ,0 ,
+ 0 ,0 ,0 ,0 // 240-255
+ };
+
+ if(KVI_OPTION_BOOL(KviOption_boolIrcViewUrlHighlighting))
+ {
+ loop_begin = &&highlighting_check_loop; // get the address of the return label
+ // forewer loop
+highlighting_check_loop:
+ // yet more optimized
+ if(*((unsigned short *)p) < 0xff)
+ if(void * jmp_address = char_to_check_jump_table[*((unsigned short *)p)])goto *jmp_address;
+ // goto *(char_to_check_jump_table[*((unsigned char *)p)]); <--- replace 0 with &nothing_found
+//nothing_found:
+ p++;
+ goto highlighting_check_loop;
+ // newer here
+ } else {
+ loop_begin = &&escape_check_loop; // get the address of the return label
+ // forever loop
+escape_check_loop:
+ while(*((unsigned short *)p) > 31)p++;
+ goto check_escape_switch; // returns to escape_check_loop or returns from the function at all
+ // newer here
+ }
+ // newer here
+
+
+#else // !COMPILE_USE_DYNAMIC_LABELS
+
+ // No way to have a jump table, nor a dynamic return jump
+ // Anyway...we can have sth similar to a jump table...
+ // Note: this could be substituted by a compiler generated jump table
+ // for a switch command... but this is STILL faster
+
+ static char char_to_check_table[256]=
+ {
+ 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, // 000-015
+ 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, // 016-031
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, // 032-047
+ 0,0,0,0,0,0,0,0, 0,0,7,7,0,7,0,0, // 048-063
+ 0,0,0,0,0,8,3,0, 2,5,0,0,0,6,0,0, // 064-079 // 070==F 072==H 073==I 077==M
+ 0,0,0,0,0,0,0,4, 0,0,0,0,0,0,0,0, // 080-095 // 087==W
+ 0,0,0,0,0,8,3,0, 2,5,0,0,0,6,0,0, // 096-111 // 102==f 104==h 105==i 109==m
+ 0,0,0,0,0,0,0,4, 0,0,0,0,0,0,0,0, // 112-127 // 119==w
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, // 128-133
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, // 134-159
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, // 160-175
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, // 176-191
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, // 192-207
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, // 208-223
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, // 224-239
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0 // 240-255
+ };
+
+check_char_loop:
+ if(KVI_OPTION_BOOL(KviOption_boolIrcViewUrlHighlighting))
+ {
+ for(;;)
+ {
+ if(*((unsigned short *)p) < 0xff)
+ if(unsigned int chk = char_to_check_table[*((unsigned short *)p)])
+ {
+ switch(chk)
+ {
+ case 1: goto check_escape_switch; break; // returns to check_char_loop or returns from the function at all
+ case 2: goto check_http_url; break; // returns to check_char_loop
+ case 3: goto check_file_or_ftp_url; break; // returns to check_char_loop
+ case 4: goto check_www_url; break; // returns to check_char_loop
+ case 5: goto check_irc_url; break; // returns to check_char_loop
+ case 6: goto check_mailto_url; break; // returns to check_char_loop
+ case 7: goto check_emoticon_char; break; // returns to check_char_loop
+ case 8: goto check_e2k_url; break;
+ }
+ }
+ p++;
+ }
+ } else {
+ while(((unsigned short)*p) > 31)p++;
+ goto check_escape_switch; // returns to check_char_loop
+ }
+
+#endif // !COMPILE_USE_DYNAMIC_LABELS
+
+check_escape_switch:
+ switch(*p)
+ {
+ case '\0':
+#ifdef COMPILE_USE_DYNAMIC_LABELS
+found_end_of_buffer:
+#endif //COMPILE_USE_DYNAMIC_LABELS
+ APPEND_LAST_TEXT_BLOCK(data_ptr,p - data_ptr)
+ return p;
+ break;
+ case '\n':
+#ifdef COMPILE_USE_DYNAMIC_LABELS
+found_end_of_line:
+#endif //COMPILE_USE_DYNAMIC_LABELS
+ // Found the end of a line
+ APPEND_LAST_TEXT_BLOCK(data_ptr,p - data_ptr)
+ // terminate the string
+ // move the current pointer to the next character...
+ // if it is '\0' we will simply stop
+ p++;
+ return p;
+ break;
+ case '\r':
+#ifdef COMPILE_USE_DYNAMIC_LABELS
+found_command_escape:
+#endif //COMPILE_USE_DYNAMIC_LABELS
+ if (p==pUnEscapeAt) {
+ APPEND_LAST_TEXT_BLOCK(data_ptr,p - data_ptr);
+ NEW_LINE_CHUNK(KVI_TEXT_UNESCAPE);
+ pUnEscapeAt = 0;
+ p++;
+ data_ptr=p;
+ break;
+ }
+ // Command escape sequence
+ // \r!<escape_cmd>\r<visible parameters string>\r
+ p++;
+ if(*p == '!')
+ {
+ const kvi_wchar_t * next_cr = p;
+ // lookup the next carriage return
+ while(*next_cr && (*next_cr != '\r'))next_cr++;
+ if(*next_cr)
+ {
+ const kvi_wchar_t * term_cr = next_cr;
+ term_cr++;
+ while(*term_cr && (*term_cr != '\r'))term_cr++;
+ if(*term_cr)
+ {
+ // ok....the format is right:
+ // \r! ... \r ... \r
+ // ^p ^next_cr ^term_cr
+ p--;
+ // \r! ... \r ... \r
+ // ^p ^next_cr ^term_cr
+ APPEND_LAST_TEXT_BLOCK(data_ptr,p - data_ptr)
+ NEW_LINE_CHUNK(KVI_TEXT_ESCAPE)
+
+ p+=2; //point after \r!
+
+ blockLen = (next_cr - p);
+ line_ptr->pChunks[iCurChunk].szPayload = (kvi_wchar_t *)kvi_malloc(((next_cr - p) + 1) * sizeof(kvi_wchar_t));
+ kvi_fastmoveodd((void *)(line_ptr->pChunks[iCurChunk].szPayload),p,blockLen * sizeof(kvi_wchar_t));
+
+ line_ptr->pChunks[iCurChunk].szPayload[blockLen] = 0;
+
+ ++next_cr; //point after the middle \r
+
+ pUnEscapeAt = term_cr;
+
+ bool bColorSetted=false;
+ if((line_ptr->pChunks[iCurChunk].szPayload[0]=='n') && KVI_OPTION_BOOL(KviOption_boolUseUserListColorsAsNickColors) && (!KVI_OPTION_BOOL(KviOption_boolColorNicks)))
+ {
+ if(m_pKviWindow->type()==KVI_WINDOW_TYPE_CHANNEL && m_pKviWindow)
+ {
+ if(line_ptr->pChunks[iCurChunk].szPayload[1]=='c' && ((KviChannel*)m_pKviWindow)->userListView())
+ {
+ KviUserListEntry *e = ((KviChannel*)m_pKviWindow)->userListView()->findEntry(QString((QChar*)next_cr,term_cr-next_cr));
+ if(e)
+ {
+ line_ptr->pChunks[iCurChunk].colors.fore = KVI_COLOR_CUSTOM; e->color(line_ptr->pChunks[iCurChunk].customFore);
+ bColorSetted=true;
+ }
+ }
+ }
+ else if(m_pKviWindow->type()==KVI_WINDOW_TYPE_QUERY && m_pKviWindow && line_ptr->pChunks[iCurChunk].szPayload[1]=='c')
+ {
+ QString m_szNick = QString((QChar*)next_cr,term_cr-next_cr);
+ if(m_szNick==m_pKviWindow->connection()->currentNickName()) {
+ line_ptr->pChunks[iCurChunk].colors.fore = KVI_COLOR_OWN;
+ bColorSetted=true;
+ }
+ }
+ }
+ if(!bColorSetted)
+ {
+ line_ptr->pChunks[iCurChunk].colors.fore=KVI_NOCHANGE;
+ }
+
+ /*APPEND_LAST_TEXT_BLOCK(next_cr,term_cr - next_cr)
+ NEW_LINE_CHUNK(KVI_TEXT_UNESCAPE)*/
+
+ p=next_cr;
+ data_ptr=p;
+ }
+ }
+ }
+ break;
+ case KVI_TEXT_COLOR:
+#ifdef COMPILE_USE_DYNAMIC_LABELS
+found_color_escape:
+#endif //COMPILE_USE_DYNAMIC_LABELS
+ //Color control code...need a new attribute struct
+ APPEND_LAST_TEXT_BLOCK(data_ptr,p - data_ptr)
+ NEW_LINE_CHUNK(*p)
+ p++;
+ p=getColorBytesW(p,&(line_ptr->pChunks[iCurChunk].colors.fore),
+ &(line_ptr->pChunks[iCurChunk].colors.back));
+ data_ptr=p;
+ break;
+ case KVI_TEXT_ICON:
+#ifdef COMPILE_USE_DYNAMIC_LABELS
+found_icon_escape:
+#endif //COMPILE_USE_DYNAMIC_LABELS
+ p++;
+ if(*p > 32)
+ {
+ // Icon control word... need a new attribute struct
+ const kvi_wchar_t * beginPtr = p - 1;
+ const kvi_wchar_t * icon_name = p;
+ while(*p > 32)p++;
+ int datalen = p - icon_name;
+ kvi_wchar_t save = *p;
+ // throw away constness!
+ *((kvi_wchar_t *)p) = 0;
+ // FIXME: this has to be changed! : lookupTextIcon must use wide characters!
+ QString tmpQ;
+ tmpQ.setUnicodeCodes(icon_name,datalen);
+ KviTextIcon * icon = g_pTextIconManager->lookupTextIcon(tmpQ);
+ // throw away constness!
+ *((kvi_wchar_t *)p) = save;
+ //if(*p == KVI_TEXT_ICON)p++; // ending delimiter
+ if(icon)
+ {
+ APPEND_LAST_TEXT_BLOCK(data_ptr,beginPtr - data_ptr)
+ NEW_LINE_CHUNK(KVI_TEXT_ICON)
+ line_ptr->pChunks[iCurChunk].szPayload = (kvi_wchar_t *)kvi_malloc((datalen + 1) * sizeof(kvi_wchar_t));
+ kvi_fastmoveodd((void *)(line_ptr->pChunks[iCurChunk].szPayload),icon_name,datalen * sizeof(kvi_wchar_t));
+ line_ptr->pChunks[iCurChunk].szPayload[datalen] = 0;
+ line_ptr->pChunks[iCurChunk].szSmileId=line_ptr->pChunks[iCurChunk].szPayload;
+
+ APPEND_LAST_TEXT_BLOCK_HIDDEN_FROM_NOW(icon_name,datalen)
+
+ data_ptr = p;
+ NEW_LINE_CHUNK(KVI_TEXT_UNICON)
+ }
+ }
+ break;
+ case KVI_TEXT_BOLD:
+ case KVI_TEXT_UNDERLINE:
+ case KVI_TEXT_REVERSE:
+ case KVI_TEXT_RESET:
+#ifdef COMPILE_USE_DYNAMIC_LABELS
+found_mirc_escape:
+#endif //COMPILE_USE_DYNAMIC_LABELS
+ APPEND_LAST_TEXT_BLOCK(data_ptr,p - data_ptr)
+ NEW_LINE_CHUNK(*p)
+ data_ptr=++p;
+ break;
+ default:
+ p++;
+ break;
+ }
+#ifdef COMPILE_USE_DYNAMIC_LABELS
+ goto *loop_begin;
+#else // !COMPILE_USE_DYNAMIC_LABELS
+ goto check_char_loop;
+#endif // !COMPILE_USE_DYNAMIC_LABELS
+
+check_http_url:
+ p++;
+ if((*p == 't') || (*p == 'T'))
+ {
+ p--;
+ if(kvi_hstrEqualCIN(p,"http://",7))
+ {
+ partLen = 7;
+ goto got_url;
+ }
+ if(kvi_hstrEqualCIN(p,"https://",8))
+ {
+ partLen = 8;
+ goto got_url;
+ }
+ p++;
+ }
+#ifdef COMPILE_USE_DYNAMIC_LABELS
+ goto *loop_begin;
+#else // !COMPILE_USE_DYNAMIC_LABELS
+ goto check_char_loop;
+#endif // !COMPILE_USE_DYNAMIC_LABELS
+
+
+check_file_or_ftp_url:
+ p++;
+ if((*p == 'i') || (*p == 'I'))
+ {
+ p--;
+ if(kvi_hstrEqualCIN(p,"file://",7))
+ {
+ partLen = 7;
+ goto got_url;
+ }
+ p++;
+ } else if((*p == 't') || (*p == 'T'))
+ {
+ p--;
+ if(kvi_hstrEqualCIN(p,"ftp://",6))
+ {
+ partLen = 6;
+ goto got_url;
+ }
+ if(kvi_hstrEqualCIN(p,"ftp.",4))
+ {
+ partLen = 4;
+ goto got_url;
+ }
+ p++;
+ }
+
+#ifdef COMPILE_USE_DYNAMIC_LABELS
+ goto *loop_begin;
+#else // !COMPILE_USE_DYNAMIC_LABELS
+ goto check_char_loop;
+#endif // !COMPILE_USE_DYNAMIC_LABELS
+
+check_e2k_url:
+ p++;
+ if((*p == 'd') || (*p == 'D'))
+ {
+ p--;
+ if(kvi_hstrEqualCIN(p,"ed2k://",7))
+ {
+ partLen = 7;
+ goto got_url;
+ }
+ p++;
+ }
+
+#ifdef COMPILE_USE_DYNAMIC_LABELS
+ goto *loop_begin;
+#else // !COMPILE_USE_DYNAMIC_LABELS
+ goto check_char_loop;
+#endif // !COMPILE_USE_DYNAMIC_LABELS
+
+check_www_url:
+ p++;
+ if((*p == 'w') || (*p == 'W'))
+ {
+ p--;
+ if(kvi_hstrEqualCIN(p,"www.",4))
+ {
+ partLen = 4;
+ goto got_url;
+ }
+ p++;
+ }
+
+#ifdef COMPILE_USE_DYNAMIC_LABELS
+ goto *loop_begin;
+#else // !COMPILE_USE_DYNAMIC_LABELS
+ goto check_char_loop;
+#endif // !COMPILE_USE_DYNAMIC_LABELS
+
+check_irc_url:
+ p++;
+ if((*p == 'r') || (*p == 'R'))
+ {
+ p--;
+ if(kvi_hstrEqualCIN(p,"irc://",6))
+ {
+ partLen = 6;
+ goto got_url;
+ }
+ if(kvi_hstrEqualCIN(p,"irc6://",7))
+ {
+ partLen = 7;
+ goto got_url;
+ }
+ if(kvi_hstrEqualCIN(p,"ircs://",7))
+ {
+ partLen = 7;
+ goto got_url;
+ }
+ if(kvi_hstrEqualCIN(p,"ircs6://",8))
+ {
+ partLen = 8;
+ goto got_url;
+ }
+ p++;
+ }
+
+#ifdef COMPILE_USE_DYNAMIC_LABELS
+ goto *loop_begin;
+#else // !COMPILE_USE_DYNAMIC_LABELS
+ goto check_char_loop;
+#endif // !COMPILE_USE_DYNAMIC_LABELS
+
+check_mailto_url:
+ p++;
+ if((*p == 'a') || (*p == 'A'))
+ {
+ p--;
+ if(kvi_hstrEqualCIN(p,"mailto:",7))
+ {
+ partLen = 7;
+ goto got_url;
+ }
+ p++;
+ }
+#ifdef COMPILE_USE_DYNAMIC_LABELS
+ goto *loop_begin;
+#else // !COMPILE_USE_DYNAMIC_LABELS
+ goto check_char_loop;
+#endif // !COMPILE_USE_DYNAMIC_LABELS
+
+
+
+got_url:
+ //Url highlighting block
+ if(*(p + partLen) < 47)
+ {
+ p+=partLen;
+ APPEND_LAST_TEXT_BLOCK(data_ptr,p - data_ptr)
+ } else {
+ APPEND_LAST_TEXT_BLOCK(data_ptr,p - data_ptr)
+ NEW_LINE_CHUNK(KVI_TEXT_ESCAPE)
+// FIXME: #warning "Option for the URL escape...double click and right button!!!"
+// int urlLen = KVI_OPTION_STRING(KviOption_stringUrlLinkCommand).len() + 1;
+ line_ptr->pChunks[iCurChunk].szPayload = (kvi_wchar_t *)kvi_malloc(2 * sizeof(kvi_wchar_t));
+ line_ptr->pChunks[iCurChunk].szPayload[0] = 'u';
+ line_ptr->pChunks[iCurChunk].szPayload[1] = 0x0;
+ line_ptr->pChunks[iCurChunk].colors.fore = KVI_OPTION_MSGTYPE(KVI_OUT_URL).fore();
+ //and run until the presumed end of the url
+ data_ptr=p;
+ p+=partLen;
+ // Question : What characters are NOT allowed in an URL ?
+ // I assume [] () {} 'and chars below 33 (space too , and negative chars too! (for signed char systems))
+ // [] and () are used in ed2k links often
+
+ // These characters are "{", "}", "|", "\", "^", "~", "[", "]", and "`". (RFC1738)
+ while((*p > 32) && (*p != '[') && (*p != '|') && (*p != '{') && (*p != '>') &&
+ (*p != ']') && (*p != '}') && (*p != '<') && (*p != '"'))p++;
+
+ if(m_pKviWindow)
+ {
+ QString tmp;
+ tmp.setUnicodeCodes(data_ptr,p-data_ptr);
+ KVS_TRIGGER_EVENT_1(KviEvent_OnUrl,m_pKviWindow,tmp);
+ }
+
+ APPEND_LAST_TEXT_BLOCK(data_ptr,p - data_ptr)
+ NEW_LINE_CHUNK(KVI_TEXT_UNESCAPE)
+
+ }
+ data_ptr=p;
+
+#ifdef COMPILE_USE_DYNAMIC_LABELS
+ goto *loop_begin;
+#else // !COMPILE_USE_DYNAMIC_LABELS
+ goto check_char_loop;
+#endif // !COMPILE_USE_DYNAMIC_LABELS
+
+ //FIXME #warning: Add more emoticons, and more intelligent code to detect when they're not really emoticons
+
+check_emoticon_char:
+ // What about this ?
+
+ const kvi_wchar_t * begin = p;
+ p++;
+ if(KVI_OPTION_BOOL(KviOption_boolDrawEmoticons))
+ switch(iMsgType)
+ {
+ case KVI_OUT_CHANPRIVMSG:
+ case KVI_OUT_ACTION:
+ case KVI_OUT_OWNPRIVMSG:
+ case KVI_OUT_QUERYPRIVMSG:
+ case KVI_OUT_QUERYPRIVMSGCRYPTED:
+ case KVI_OUT_QUERYNOTICE:
+ case KVI_OUT_QUERYNOTICECRYPTED:
+ case KVI_OUT_CHANPRIVMSGCRYPTED:
+ case KVI_OUT_CHANNELNOTICE:
+ case KVI_OUT_CHANNELNOTICECRYPTED:
+ case KVI_OUT_OWNPRIVMSGCRYPTED:
+ case KVI_OUT_HIGHLIGHT:
+ case KVI_OUT_DCCCHATMSG:
+ {
+ // Pragma: 31.05.2002 : I had to kill the 8 prefix
+ // It happens really too often to have an 8 followed by a parenthesis
+ // that is not an emoticon
+
+ // *begin can be one of ':' , ';' , '='
+ if(*p == '-')p++; // FIXME: we could handle also 'o' as a nose ??? (extreme: also '+' ?)
+ // FIXME: use a "jump-like-check-table" here ? .... it would be surely faster
+ // FIXME: handle also '[',']','\\','p','@','#','<','>','|' ???
+ switch(*p)
+ {
+ case ')':
+ case '(':
+ case '/':
+ case 'D':
+ case 'P':
+ case 'S':
+ case 'O':
+ case '*':
+ case '|':
+ case 176: // '°' -> alt 176 : teardrop
+ {
+ const kvi_wchar_t * item = p;
+ const kvi_wchar_t * item2 = 0;
+ p++;
+ while(*p == *item)p++;
+ int count = (p - item) - 1;
+ if(*item == 176)
+ {
+ if(*p == ')')
+ {
+ item2 = p;
+ p++;
+ }
+ }
+ if(!*p || (*p == ' '))
+ {
+ // ok! this is an emoticon (sequence) !
+ // We lookup simplified versions of the emoticons...
+
+ // FIXME: this sould become UNICODE!!!
+ QString lookupstring;
+ kvi_wchar_t ng[3];
+ ng[0] = *begin;
+ ng[1] = *item;
+ if(item2)ng[2] = *item2;
+ lookupstring.setUnicodeCodes(ng,item2 ? 3 : 2);
+
+ KviTextIcon * icon = g_pTextIconManager->lookupTextIcon(lookupstring);
+ // do we have that emoticon-icon association ?
+ if(icon)
+ {
+ // we got an icon for this emoticon
+ // the tooltip will carry the original emoticon source text
+ APPEND_LAST_TEXT_BLOCK(data_ptr,begin - data_ptr)
+ NEW_LINE_CHUNK(KVI_TEXT_ICON)
+
+ int emolen = p - begin;
+ int reallen=item2 ? 3 : 2;
+
+ line_ptr->pChunks[iCurChunk].szPayload = (kvi_wchar_t *)kvi_malloc((emolen + 1) * sizeof(kvi_wchar_t));
+ kvi_fastmoveodd(line_ptr->pChunks[iCurChunk].szPayload,begin,emolen * sizeof(kvi_wchar_t));
+ line_ptr->pChunks[iCurChunk].szPayload[emolen] = 0;
+
+ line_ptr->pChunks[iCurChunk].szSmileId = (kvi_wchar_t *)kvi_malloc((reallen + 1) * sizeof(kvi_wchar_t));
+ kvi_fastmoveodd(line_ptr->pChunks[iCurChunk].szSmileId,ng,reallen * sizeof(kvi_wchar_t));
+ line_ptr->pChunks[iCurChunk].szSmileId[reallen] = 0;
+
+ APPEND_LAST_TEXT_BLOCK_HIDDEN_FROM_NOW(begin,emolen)
+ data_ptr = p;
+ // let's also handle thingies like :DDDD
+ item++;
+ while(count > 0)
+ {
+ NEW_LINE_CHUNK(KVI_TEXT_ICON)
+ line_ptr->pChunks[iCurChunk].szPayload = (kvi_wchar_t *)kvi_malloc((emolen + 1) * sizeof(kvi_wchar_t));
+ kvi_fastmoveodd(line_ptr->pChunks[iCurChunk].szPayload,begin,emolen * sizeof(kvi_wchar_t));
+ line_ptr->pChunks[iCurChunk].szPayload[emolen] = 0;
+
+ line_ptr->pChunks[iCurChunk].szSmileId = (kvi_wchar_t *)kvi_malloc((reallen + 1) * sizeof(kvi_wchar_t));
+ kvi_fastmoveodd(line_ptr->pChunks[iCurChunk].szSmileId,ng,reallen * sizeof(kvi_wchar_t));
+ line_ptr->pChunks[iCurChunk].szSmileId[reallen] = 0;
+
+ APPEND_ZERO_LENGTH_BLOCK(data_ptr)
+ count--;
+ }
+ NEW_LINE_CHUNK(KVI_TEXT_UNICON)
+ } // we don't even need to skip back... the text eventually parsed is ok to be in a single block for sure
+ } // we don't even need to skip back... the text eventually parsed is ok to be in a single block for sure
+ } // we don't even need to skip back... the text eventually parsed is ok to be in a single block for sure
+ break;
+ } // switch(*p)
+ } break;
+
+ }
+
+
+#ifdef COMPILE_USE_DYNAMIC_LABELS
+ goto *loop_begin;
+#else // !COMPILE_USE_DYNAMIC_LABELS
+ goto check_char_loop;
+#endif // !COMPILE_USE_DYNAMIC_LABELS
+
+ // never here
+ return p;
+
+}
+
+void KviIrcView::fastScroll(int lines)
+{
+ m_iUnprocessedPaintEventRequests = 0;
+
+ if(!isVisible())return;
+
+ if(!m_pFm)
+ {
+ // We must get the metrics from a real paint event :/
+ // must do a full repaint to get them...
+ repaint();
+ return;
+ }
+
+ // Ok...the current line is the last one here
+ // It is the only one that needs to be repainted
+ int widgetWidth = width()-m_pScrollBar->width();
+ if(widgetWidth < KVI_IRCVIEW_PIXMAP_SEPARATOR_AND_DOUBLEBORDER_WIDTH+10)return; //can't show stuff here
+ int widgetHeight = height();
+ int maxLineWidth = widgetWidth;
+ int defLeftCoord=KVI_IRCVIEW_HORIZONTAL_BORDER;
+ if(KVI_OPTION_BOOL(KviOption_boolIrcViewShowImages))
+ {
+ maxLineWidth -= KVI_IRCVIEW_PIXMAP_SEPARATOR_AND_DOUBLEBORDER_WIDTH;
+ defLeftCoord+=KVI_IRCVIEW_PIXMAP_AND_SEPARATOR;
+ }
+
+
+ int heightToPaint = 1;
+ KviIrcViewLine * l = m_pCurLine;
+ while(lines > 0)
+ {
+ if(l)
+ {
+ if(maxLineWidth != l->iMaxLineWidth)calculateLineWraps(l,maxLineWidth);
+ heightToPaint += l->uLineWraps * m_iFontLineSpacing;
+ heightToPaint += (m_iFontLineSpacing + m_iFontDescent);
+ lines--;
+ l = l->pPrev;
+ } else lines = 0;
+ }
+
+#ifdef COMPILE_USE_QT4
+ scroll(0,-(heightToPaint-1),QRect(1,1,widgetWidth-2,widgetHeight-2));
+#else
+ bitBlt(this,1,1,this,1,heightToPaint,widgetWidth -2,widgetHeight - (heightToPaint + KVI_IRCVIEW_VERTICAL_BORDER));
+
+ QRect r(0,widgetHeight - (heightToPaint + KVI_IRCVIEW_VERTICAL_BORDER),
+ widgetWidth,heightToPaint + KVI_IRCVIEW_VERTICAL_BORDER);
+
+ QPaintEvent * e = new QPaintEvent(r);
+ paintEvent(e);
+ delete e;
+#endif
+
+ if(m_iLastLinkRectHeight > -1)
+ {
+ // need to kill the last highlighted link
+ m_iLastLinkRectTop -= heightToPaint;
+ if(m_iLastLinkRectTop < 0)
+ {
+ m_iLastLinkRectHeight += m_iLastLinkRectTop;
+ m_iLastLinkRectTop = 0;
+ }
+ }
+
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// The IrcView : THE paint event
+//
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void KviIrcView::paintEvent(QPaintEvent *p)
+{
+ //
+ // THIS FUNCTION IS A MONSTER
+ //
+
+ int scrollbarWidth = m_pScrollBar->width();
+ int widgetWidth = width() - scrollbarWidth;
+ if(!isVisible() || (widgetWidth < 20))
+ {
+ m_iUnprocessedPaintEventRequests = 0; // assume a full repaint when this widget is shown...
+ return; //can't show stuff here
+ }
+
+ // if the mdiManager is in SDI mode
+ // and this window is attacched but is not the toplevel one
+ // then it is hidden completely behind the other windows
+ // and we can avoid to paint it :)
+ if(g_pFrame->mdiManager()->isInSDIMode() &&
+ (m_pKviWindow->mdiParent() != g_pFrame->mdiManager()->topChild()) &&
+ (m_pKviWindow->mdiParent()))
+ {
+ m_iUnprocessedPaintEventRequests = 0; // assume a full repaint when this widget is shown...
+ return; // totally hidden behind other windows
+ }
+
+ int widgetHeight = height();
+
+ static QRect r; // static: avoid calling constructor and destructor every time...
+
+ if(p)
+ {
+ r=p->rect(); // app triggered , or self triggered from fastScroll (in that case m_iUnprocessedPaintEventRequests is set to 0 there)
+ if(r == rect())
+ m_iUnprocessedPaintEventRequests = 0; // only full repaints reset
+ } else {
+ // A self triggered event
+ m_iUnprocessedPaintEventRequests = 0; // only full repaints reset
+ r = rect();
+ }
+
+ int rectLeft = r.x();
+ int rectTop = r.y();
+ int rectHeight = r.height();
+ int rectBottom = rectTop + rectHeight;
+ int rectWidth = r.width();
+ if(rectWidth > widgetWidth)rectWidth = widgetWidth;
+
+#ifdef COMPILE_USE_QT4
+ QPainter pa(this); // we use qt4 double buffering
+#else
+ KviDoubleBuffer doublebuffer(width(),height());
+ QPixmap * pDoubleBufferPixmap = doublebuffer.pixmap();
+
+ QPainter pa(pDoubleBufferPixmap);
+#endif
+ SET_ANTI_ALIASING(pa);
+
+ pa.setFont(font());
+ if(!m_pFm)
+ {
+ // note that QFontMetrics(pa.font()) may be not the same as QFontMetrics(font())
+ // because the painter might effectively use an approximation of the QFont specified
+ // by font().
+ recalcFontVariables(QFontMetrics(pa.font()),pa.fontInfo());
+ }
+
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ if(g_pShadedChildGlobalDesktopBackground)
+ {
+ QPoint pnt = mapToGlobal(QPoint(rectLeft,rectTop));
+ pa.drawTiledPixmap(rectLeft,rectTop,rectWidth,rectHeight,*g_pShadedChildGlobalDesktopBackground,pnt.x(),pnt.y());
+ } else {
+#endif
+ QPixmap * pix = m_pPrivateBackgroundPixmap;
+
+ if(!pix)
+ pix = KVI_OPTION_PIXMAP(KviOption_pixmapIrcViewBackground).pixmap();
+
+ pa.fillRect(rectLeft,rectTop,rectWidth,rectHeight,KVI_OPTION_COLOR(KviOption_colorIrcViewBackground));
+ if(pix)
+ KviPixmapUtils::drawPixmapWithPainter(&pa,pix,KVI_OPTION_UINT(KviOption_uintIrcViewPixmapAlign),r,widgetWidth,widgetHeight);
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ }
+#endif
+
+ //Have lines visible
+ int curBottomCoord = widgetHeight - KVI_IRCVIEW_VERTICAL_BORDER;
+ int maxLineWidth = widgetWidth;
+ int defLeftCoord = KVI_IRCVIEW_HORIZONTAL_BORDER;
+ int lineWrapsHeight;
+
+ if(KVI_OPTION_BOOL(KviOption_boolIrcViewShowImages))
+ {
+ maxLineWidth -= KVI_IRCVIEW_PIXMAP_SEPARATOR_AND_DOUBLEBORDER_WIDTH;
+ defLeftCoord += KVI_IRCVIEW_PIXMAP_AND_SEPARATOR;
+ }
+
+ KviIrcViewLine *pCurTextLine = m_pCurLine;
+
+ if(m_bMouseIsDown)
+ {
+ m_szLastSelectionLine = "";
+ m_szLastSelection = "";
+ }
+
+ //Make sure that we have enough space to paint something...
+ if(maxLineWidth < m_iMinimumPaintWidth)pCurTextLine=0;
+
+ bool bLineMarkPainted = !KVI_OPTION_BOOL(KviOption_boolTrackLastReadTextViewLine);
+
+
+ //And loop thru lines until we not run over the upper bound of the view
+ while((curBottomCoord >= KVI_IRCVIEW_VERTICAL_BORDER) && pCurTextLine)
+ {
+ //Paint pCurTextLine
+ if(maxLineWidth != pCurTextLine->iMaxLineWidth)
+ {
+ // Width of the widget or the font has been changed
+ // from the last time that this line was painted
+ calculateLineWraps(pCurTextLine,maxLineWidth);
+ }
+
+ // the evil multiplication
+ // in an i486 it can get up to 42 clock cycles
+ lineWrapsHeight = (pCurTextLine->uLineWraps) * m_iFontLineSpacing;
+ curBottomCoord -= lineWrapsHeight;
+
+ if((curBottomCoord - m_iFontLineSpacing) > rectBottom)
+ {
+ // not in update rect... skip
+ curBottomCoord -= (m_iFontLineSpacing + m_iFontDescent);
+ pCurTextLine = pCurTextLine->pPrev;
+ continue;
+ }
+
+ if(KVI_OPTION_BOOL(KviOption_boolIrcViewShowImages))
+ {
+ //Paint the pixmap first
+ //Calculate the position of the image
+ //imageYPos = curBottomCoord - (pixmapHeight(16) + ((m_iFontLineSpacing - 16)/2) );
+ int imageYPos = curBottomCoord - m_iRelativePixmapY;
+ //Set the mask if needed
+ int iPixId = KVI_OPTION_MSGTYPE(pCurTextLine->iMsgType).pixId();
+ if(iPixId > 0)
+ pa.drawPixmap(KVI_IRCVIEW_HORIZONTAL_BORDER,imageYPos,*(g_pIconManager->getSmallIcon(iPixId)));
+ }
+
+ if(m_pToolWidget)
+ {
+ if(!m_pToolWidget->messageEnabled(pCurTextLine->iMsgType))
+ {
+ // not in update rect... skip
+ curBottomCoord -= (m_iFontLineSpacing + m_iFontDescent);
+ pCurTextLine = pCurTextLine->pPrev;
+ continue;
+ }
+ }
+
+ // Initialize for drawing this line of text
+ // The first block is always an attribute block
+ char defaultBack = pCurTextLine->pBlocks->pChunk->colors.back;
+ char defaultFore = pCurTextLine->pBlocks->pChunk->colors.fore;
+ bool curBold = false;
+ bool curUnderline = false;
+ char foreBeforeEscape= KVI_BLACK;
+ bool curLink = false;
+ bool bacWasTransp = false;
+ char curFore = defaultFore;
+ char curBack = defaultBack;
+ int curLeftCoord = defLeftCoord;
+ curBottomCoord -= m_iFontDescent; //rise up the text...
+
+ //
+ // Single text line loop (paint all text blocks)
+ // (May correspond to more physical lines on the display if the text is wrapped)
+ //
+
+ for(int i=0;i < pCurTextLine->iBlockCount;i++)
+ {
+ register KviIrcViewWrappedBlock * block = &(pCurTextLine->pBlocks[i]);
+
+ // Play with the attributes
+ if(block->pChunk)
+ {
+ //normal block
+ switch(block->pChunk->type)
+ {
+ case KVI_TEXT_COLOR:
+ if(block->pChunk->colors.fore != KVI_NOCHANGE)
+ {
+ curFore = block->pChunk->colors.fore;
+ if(block->pChunk->colors.back != KVI_NOCHANGE)
+ curBack = block->pChunk->colors.back;
+ } else {
+ // only a CTRL+K... reset
+ curFore = defaultFore;
+ curBack = defaultBack;
+ }
+ // Begin Edit by GMC-jimmy: Added
+ // When KVIrc encounters a CTRL+K code without any trailing numbers, we then use KVIrc's default color value
+ // defined by the user in the Options dialog.
+ // This is to allow KVIrc to handle mIRC color codes in a similar fashion to most other modern irc clients.
+ // See also kvi_input.cpp
+
+ // Pragma: optimized: moved the code above (avoided duplicate if())
+ // Pragma(05.03.2003): fixed again: reset ONLY if CTRL+K without numbers
+ // otherwise leave the background unchanged
+
+ //if(block->pChunk->colors.fore == KVI_NOCHANGE)
+ // curFore = defaultFore;
+ //if(block->pChunk->colors.back == KVI_NOCHANGE)
+ // curBack = defaultBack;
+ // End Edit
+ break;
+ case KVI_TEXT_ESCAPE:
+ foreBeforeEscape = curFore;
+ if(block->pChunk->colors.fore != KVI_NOCHANGE)
+ curFore = block->pChunk->colors.fore;
+ if(m_pLastLinkUnderMouse == block)curLink = true;
+ break;
+ case KVI_TEXT_UNESCAPE:
+ curLink = false;
+ curFore = foreBeforeEscape;
+ break;
+ case KVI_TEXT_BOLD:
+ curBold = !curBold;
+ break;
+ case KVI_TEXT_UNDERLINE:
+ curUnderline = !curUnderline;
+ break;
+ case KVI_TEXT_RESET:
+ curBold = false;
+ curUnderline = false;
+ curFore = defaultFore;
+ curBack = defaultBack;
+ break;
+ case KVI_TEXT_REVERSE: //Huh ?
+ char aux = curBack;
+ if(bacWasTransp == true)
+ {
+ curBack = KVI_TRANSPARENT;
+ } else {
+ curBack = curFore;
+ }
+ if(aux == KVI_TRANSPARENT)
+ {
+ curFore = (char)KVI_DEF_BACK;
+ } else {
+ curFore = aux;
+ }
+ bacWasTransp = (aux == KVI_TRANSPARENT);
+/* if(curBack != KVI_TRANSPARENT)
+ {
+ char aux =curFore;
+ curFore = curBack;
+ curBack = aux;
+ } else {
+ curBack = curFore;
+ switch(curBack)
+ {
+ case KVI_WHITE:
+ case KVI_ORANGE:
+ case KVI_YELLOW:
+ case KVI_LIGHTGREEN:
+ case KVI_BLUEMARINE:
+ case KVI_LIGHTBLUE:
+ case KVI_LIGHTVIOLET:
+ case KVI_LIGHTGRAY:
+ curFore=KVI_BLACK;
+ break;
+ default: //transparent too
+ curFore=KVI_LIGHTGREEN;
+ break;
+ }
+ }
+*/
+ break;
+ //case KVI_TEXT_ICON:
+ //case KVI_TEXT_UNICON:
+ // does nothing
+ //debug("Have a block with ICON/UNICON attr");
+ //break;
+ }
+
+ } else {
+ // no attributes , it is a line wrap
+ curLeftCoord = defLeftCoord;
+ if(KVI_OPTION_BOOL(KviOption_boolIrcViewWrapMargin))curLeftCoord+=m_iWrapMargin;
+ curBottomCoord += m_iFontLineSpacing;
+ }
+
+//
+// Here we run really out of bounds :)))))
+// A couple of macros that could work well as functions...
+// but since there are really many params to be passed
+// and push & pop calls take clock cycles
+// my paranoic mind decided to go for the macro way.
+// This is NOT good programming
+//
+
+#define SET_PEN(_color,_custom)\
+ if( ((unsigned char)_color) < 16 )\
+ {\
+ pa.setPen(KVI_OPTION_MIRCCOLOR((unsigned char)_color));\
+ } else {\
+ switch((unsigned char)_color)\
+ {\
+ case KVI_COLOR_EXT_USER_OP:\
+ pa.setPen(KVI_OPTION_COLOR(KviOption_colorUserListViewOpForeground));\
+ break;\
+ case KVI_COLOR_EXT_USER_HALFOP:\
+ pa.setPen(KVI_OPTION_COLOR(KviOption_colorUserListViewHalfOpForeground));\
+ break;\
+ case KVI_COLOR_EXT_USER_ADMIN:\
+ pa.setPen(KVI_OPTION_COLOR(KviOption_colorUserListViewChanAdminForeground));\
+ break;\
+ case KVI_COLOR_EXT_USER_OWNER:\
+ pa.setPen(KVI_OPTION_COLOR(KviOption_colorUserListViewChanOwnerForeground));\
+ break;\
+ case KVI_COLOR_EXT_USER_VOICE:\
+ pa.setPen(KVI_OPTION_COLOR(KviOption_colorUserListViewVoiceForeground));\
+ break;\
+ case KVI_COLOR_EXT_USER_USEROP:\
+ pa.setPen(KVI_OPTION_COLOR(KviOption_colorUserListViewUserOpForeground));\
+ break;\
+ case KVI_COLOR_EXT_USER_NORMAL:\
+ pa.setPen(KVI_OPTION_COLOR(KviOption_colorUserListViewNormalForeground));\
+ break;\
+ case KVI_DEF_BACK :\
+ pa.setPen(KVI_OPTION_COLOR(KviOption_colorIrcViewBackground));\
+ break;\
+ case KVI_COLOR_CUSTOM :\
+ pa.setPen(_custom);\
+ break;\
+ case KVI_COLOR_OWN :\
+ pa.setPen(KVI_OPTION_COLOR(KviOption_colorUserListViewOwnForeground));\
+ break;\
+ }\
+ }
+
+#define DRAW_SELECTED_TEXT(_text_str,_text_idx,_text_len,_text_width) \
+ SET_PEN(KVI_OPTION_MSGTYPE(KVI_OUT_SELECT).fore(),block->pChunk ? block->pChunk->customFore : QColor()); \
+ { \
+ int theWdth = _text_width; \
+ if(theWdth < 0) \
+ theWdth=width()-(curLeftCoord+KVI_IRCVIEW_HORIZONTAL_BORDER+scrollbarWidth); \
+ pa.fillRect(curLeftCoord,curBottomCoord - m_iFontLineSpacing + m_iFontDescent,theWdth,m_iFontLineSpacing,KVI_OPTION_MIRCCOLOR(KVI_OPTION_MSGTYPE(KVI_OUT_SELECT).back())); \
+ } \
+ pa.drawText(curLeftCoord,curBottomCoord,_text_str,_text_idx,_text_len); \
+ m_szLastSelectionLine.append(_text_str.mid(_text_idx,_text_len)); \
+ curLeftCoord += _text_width;
+
+#define DRAW_NORMAL_TEXT(_text_str,_text_idx,_text_len,_text_width) \
+ SET_PEN(curFore,block->pChunk ? block->pChunk->customFore : QColor()); \
+ if(curBack != KVI_TRANSPARENT){ \
+ int theWdth = _text_width; \
+ if(theWdth < 0) \
+ theWdth=width()-(curLeftCoord+KVI_IRCVIEW_HORIZONTAL_BORDER+scrollbarWidth); \
+ pa.fillRect(curLeftCoord,curBottomCoord - m_iFontLineSpacing + m_iFontDescent,theWdth,m_iFontLineSpacing,KVI_OPTION_MIRCCOLOR((unsigned char)curBack)); \
+ } \
+ pa.drawText(curLeftCoord,curBottomCoord,_text_str,_text_idx,_text_len); \
+ if(curBold)pa.drawText(curLeftCoord+1,curBottomCoord,_text_str,_text_idx,_text_len); \
+ if(curUnderline){ \
+ int theWdth = _text_width; \
+ if(theWdth < 0) \
+ theWdth=width()-(curLeftCoord+KVI_IRCVIEW_HORIZONTAL_BORDER+scrollbarWidth); \
+ pa.drawLine(curLeftCoord,curBottomCoord+2,curLeftCoord+theWdth,curBottomCoord+2); \
+ } \
+ curLeftCoord += _text_width;
+
+
+// EOF macro declarations
+
+ if(m_bMouseIsDown)
+ {
+ //Check if the block or a part of it is selected
+ if(checkSelectionBlock(pCurTextLine,curLeftCoord,curBottomCoord,i))
+ {
+ //Selected in some way
+ //__range_valid(g_pOptions->m_cViewOutSeleFore != KVI_TRANSPARENT);
+ //__range_valid(g_pOptions->m_cViewOutSeleBack != KVI_TRANSPARENT);
+
+ if(m_bShiftPressed && i && block->pChunk &&
+ ((m_pWrappedBlockSelectionInfo->selection_type == KVI_IRCVIEW_BLOCK_SELECTION_TOTAL) ||
+ (m_pWrappedBlockSelectionInfo->selection_type == KVI_IRCVIEW_BLOCK_SELECTION_LEFT))
+ )
+ {
+ switch(block->pChunk->type)
+ {
+ case KVI_TEXT_BOLD:
+ case KVI_TEXT_UNDERLINE:
+ case KVI_TEXT_REVERSE:
+ case KVI_TEXT_RESET:
+ m_szLastSelectionLine.append(QChar(block->pChunk->type));
+ break;
+ case KVI_TEXT_COLOR:
+ m_szLastSelectionLine.append(QChar(block->pChunk->type));
+ if((block->pChunk->colors.fore != KVI_NOCHANGE) && (block->pChunk->colors.fore != KVI_TRANSPARENT))
+ {
+ if(curFore > 9)m_szLastSelectionLine.append(QChar('1'));
+ m_szLastSelectionLine.append(QChar((curFore%10)+'0'));
+ }
+ if((block->pChunk->colors.back != KVI_NOCHANGE) && (block->pChunk->colors.back != KVI_TRANSPARENT) )
+ {
+ m_szLastSelectionLine.append(QChar(','));
+ if(curBack > 9)m_szLastSelectionLine.append(QChar('1'));
+ m_szLastSelectionLine.append(QChar((curBack%10)+'0'));
+ }
+ break;
+ }
+ }
+
+ switch(m_pWrappedBlockSelectionInfo->selection_type)
+ {
+ case KVI_IRCVIEW_BLOCK_SELECTION_TOTAL:
+ DRAW_SELECTED_TEXT(pCurTextLine->szText,block->block_start,
+ block->block_len,block->block_width)
+ break;
+ case KVI_IRCVIEW_BLOCK_SELECTION_LEFT:
+ DRAW_SELECTED_TEXT(pCurTextLine->szText,block->block_start,
+ m_pWrappedBlockSelectionInfo->part_1_length,
+ m_pWrappedBlockSelectionInfo->part_1_width)
+ DRAW_NORMAL_TEXT(pCurTextLine->szText,block->block_start+m_pWrappedBlockSelectionInfo->part_1_length,
+ m_pWrappedBlockSelectionInfo->part_2_length,
+ m_pWrappedBlockSelectionInfo->part_2_width)
+ break;
+ case KVI_IRCVIEW_BLOCK_SELECTION_RIGHT:
+ DRAW_NORMAL_TEXT(pCurTextLine->szText,block->block_start,
+ m_pWrappedBlockSelectionInfo->part_1_length,
+ m_pWrappedBlockSelectionInfo->part_1_width)
+ DRAW_SELECTED_TEXT(pCurTextLine->szText,block->block_start+m_pWrappedBlockSelectionInfo->part_1_length,
+ m_pWrappedBlockSelectionInfo->part_2_length,
+ m_pWrappedBlockSelectionInfo->part_2_width)
+ break;
+ case KVI_IRCVIEW_BLOCK_SELECTION_CENTRAL:
+ DRAW_NORMAL_TEXT(pCurTextLine->szText,block->block_start,
+ m_pWrappedBlockSelectionInfo->part_1_length,
+ m_pWrappedBlockSelectionInfo->part_1_width)
+ DRAW_SELECTED_TEXT(pCurTextLine->szText,block->block_start+m_pWrappedBlockSelectionInfo->part_1_length,
+ m_pWrappedBlockSelectionInfo->part_2_length,
+ m_pWrappedBlockSelectionInfo->part_2_width)
+ DRAW_NORMAL_TEXT(pCurTextLine->szText,block->block_start+m_pWrappedBlockSelectionInfo->part_1_length+m_pWrappedBlockSelectionInfo->part_2_length,
+ m_pWrappedBlockSelectionInfo->part_3_length,
+ m_pWrappedBlockSelectionInfo->part_3_width)
+ break;
+ case KVI_IRCVIEW_BLOCK_SELECTION_ICON:
+ {
+ int theWdth = block->block_width;
+ if(theWdth < 0)theWdth=width()-(curLeftCoord+KVI_IRCVIEW_HORIZONTAL_BORDER+scrollbarWidth);
+ pa.fillRect(curLeftCoord,curBottomCoord - m_iFontLineSpacing + m_iFontDescent,theWdth,m_iFontLineSpacing,KVI_OPTION_MIRCCOLOR(KVI_OPTION_MSGTYPE(KVI_OUT_SELECT).back()));
+ kvi_wslen_t the_len = kvi_wstrlen(block->pChunk->szPayload);
+ m_szLastSelectionLine.append(QChar(block->pChunk->type));
+ QString tmp;
+ tmp.setUnicodeCodes(block->pChunk->szPayload,the_len);
+ m_szLastSelectionLine.append(tmp);
+ goto no_selection_paint;
+ }
+ break;
+ }
+ } else {
+ if(block->pChunk && block->pChunk->type == KVI_TEXT_ICON)goto no_selection_paint;
+ int wdth = block->block_width;
+ if(wdth == 0)
+ {
+ // Last block before a word wrap , or a zero characters attribute block ?
+ if(i < (pCurTextLine->iBlockCount - 1))
+ {
+ // There is another block...
+ // Check if it is a wrap...
+ if(pCurTextLine->pBlocks[i+1].pChunk == 0)wdth = widgetWidth-(curLeftCoord+KVI_IRCVIEW_HORIZONTAL_BORDER);
+ // else simply a zero characters block
+ }
+ // else simply a zero characters block
+ }
+ DRAW_NORMAL_TEXT(pCurTextLine->szText,block->block_start,block->block_len,wdth)
+ }
+ } else {
+ //No selection ...go fast!
+no_selection_paint:
+ if(block->pChunk && block->pChunk->type == KVI_TEXT_ICON)
+ {
+ int wdth = block->block_width;
+ if(wdth < 0)wdth = widgetWidth - (curLeftCoord + KVI_IRCVIEW_HORIZONTAL_BORDER);
+ int imageYPos = curBottomCoord - m_iRelativePixmapY;
+ //Set the mask if needed
+ if(curBack != KVI_TRANSPARENT && curBack < 16)
+ {
+ pa.fillRect(curLeftCoord,curBottomCoord - m_iFontLineSpacing + m_iFontDescent,wdth,m_iFontLineSpacing,KVI_OPTION_MIRCCOLOR((unsigned char)curBack));
+ }
+ QString tmpQ;
+ tmpQ.setUnicodeCodes(block->pChunk->szSmileId,kvi_wstrlen(block->pChunk->szSmileId));
+ QPixmap * daIcon =0;
+ KviTextIcon* pIcon = g_pTextIconManager->lookupTextIcon(tmpQ);
+ if(pIcon)
+ {
+ daIcon = pIcon->pixmap();
+ }
+ if(!daIcon)
+ {
+ // this should never happen since we do a check
+ // when building the text icon block , but.. better safe than sorry:
+ // so... we lost some icons ? wrong associations ?
+ // recover it by displaying the "question mark" icon
+ daIcon = g_pIconManager->getSmallIcon(KVI_SMALLICON_HELP); // must be there, eventually null pixmap :D
+ }
+ int moredown = 1; //used to center imager vertically (pixels which the image is moved more down)
+ moredown += ((m_iFontLineSpacing - daIcon->height()) / 2);
+ pa.drawPixmap(curLeftCoord + m_iIconSideSpacing,imageYPos + moredown,*(daIcon));
+
+ //debug("SHifting by %d",block->block_width);
+ curLeftCoord += block->block_width;
+ } else {
+
+ int wdth = block->block_width;
+ if(wdth < 0)wdth = widgetWidth - (curLeftCoord + KVI_IRCVIEW_HORIZONTAL_BORDER);
+
+ // FIXME: We could avoid this XSetForeground if the curFore was not changed....
+
+ SET_PEN(curFore,block->pChunk ? block->pChunk->customFore : QColor());
+
+ if(curBack != KVI_TRANSPARENT && curBack < 16 )
+ {
+ pa.fillRect(curLeftCoord,curBottomCoord - m_iFontLineSpacing + m_iFontDescent,wdth,m_iFontLineSpacing,KVI_OPTION_MIRCCOLOR((unsigned char)curBack));
+ }
+
+ if(curLink)
+ {
+ SET_PEN(KVI_OPTION_MSGTYPE(KVI_OUT_LINK).fore(),block->pChunk ? block->pChunk->customFore : QColor());
+ pa.drawText(curLeftCoord,curBottomCoord,pCurTextLine->szText,block->block_start,block->block_len);
+ pa.drawText(curLeftCoord+1,curBottomCoord,pCurTextLine->szText,block->block_start,block->block_len);
+ pa.drawLine(curLeftCoord,curBottomCoord+2,curLeftCoord+wdth,curBottomCoord+2);
+ } else if(curBold) {
+ //Draw doubled font (simulate bold)
+ pa.drawText(curLeftCoord,curBottomCoord,pCurTextLine->szText,block->block_start,block->block_len);
+ pa.drawText(curLeftCoord + 1,curBottomCoord,pCurTextLine->szText,block->block_start,block->block_len);
+ } else {
+ pa.drawText(curLeftCoord,curBottomCoord,pCurTextLine->szText,block->block_start,block->block_len);
+ }
+
+ if(curUnderline)
+ {
+ //Draw a line under the text block....
+ pa.drawLine(curLeftCoord,curBottomCoord+2,curLeftCoord+wdth,curBottomCoord+2);
+ }
+ curLeftCoord += block->block_width;
+ }
+ }
+ }
+
+ if(pCurTextLine == m_pCursorLine)
+ {
+ // paint the cursor line
+ int iH = lineWrapsHeight + m_iFontLineSpacing;
+#ifdef COMPILE_USE_QT4
+ pa.setCompositionMode(QPainter::CompositionMode_SourceOut);
+#else
+ pa.setRasterOp(NotROP);
+#endif
+ pa.fillRect(0,curBottomCoord - iH,widgetWidth,iH + (m_iFontDescent << 1),Qt::black);
+#ifdef COMPILE_USE_QT4
+ pa.setCompositionMode(QPainter::CompositionMode_SourceOver);
+#else
+ pa.setRasterOp(CopyROP);
+#endif
+ }
+
+ if(m_bMouseIsDown)
+ {
+ if(!m_szLastSelectionLine.isEmpty())
+ {
+ if(!m_szLastSelection.isEmpty())m_szLastSelection.prepend("\n");
+ m_szLastSelection.prepend(m_szLastSelectionLine);
+ m_szLastSelectionLine = "";
+ }
+ }
+
+ curBottomCoord -= (lineWrapsHeight + m_iFontLineSpacing);
+
+ if(pCurTextLine->uIndex == m_uLineMarkLineIndex)
+ {
+ if((curBottomCoord >= KVI_IRCVIEW_VERTICAL_BORDER) && !bLineMarkPainted)
+ {
+ // visible!
+ bLineMarkPainted = true;
+ //pa.setRasterOp(NotROP);
+#ifdef COMPILE_USE_QT4
+ pa.setPen(QPen(KVI_OPTION_COLOR(KviOption_colorIrcViewMarkLine),1,Qt::DotLine));
+#else
+ pa.setPen(QPen(KVI_OPTION_COLOR(KviOption_colorIrcViewMarkLine),1,QPen::DotLine));
+#endif
+ pa.drawLine(0,curBottomCoord,widgetWidth,curBottomCoord);
+ //pa.setRasterOp(CopyROP);
+ } // else was partially visible only
+ }
+
+ pCurTextLine = pCurTextLine->pPrev;
+ }
+
+ if(!bLineMarkPainted && pCurTextLine && (rectTop <= (KVI_IRCVIEW_VERTICAL_BORDER + 5)))
+ {
+ // the line mark hasn't been painted yet
+ // need to find out if the mark is above the display
+ // the mark might be somewhere before the current text line
+ // find the first line that can't be painted in the view at all
+ while((curBottomCoord >= KVI_IRCVIEW_VERTICAL_BORDER) && pCurTextLine)
+ {
+ // the line wraps for the visible lines MUST have been already calculated
+ // for this view width
+ lineWrapsHeight = (pCurTextLine->uLineWraps) * m_iFontLineSpacing;
+ curBottomCoord -= lineWrapsHeight + m_iFontLineSpacing + m_iFontDescent;
+ pCurTextLine = pCurTextLine->pPrev;
+ }
+
+ if(pCurTextLine)
+ {
+ // this is the first NOT visible
+ // so pCurTextLine->pNext is the last visible one
+ if(pCurTextLine->pNext)
+ {
+ if(pCurTextLine->pNext->uIndex >= m_uLineMarkLineIndex)
+ bLineMarkPainted = true; // yes, its somewhere before or on this line
+ } else {
+ // no next line ? hm... compare to the not visible one.. but this should never happen
+ if(pCurTextLine->uIndex >= m_uLineMarkLineIndex)
+ bLineMarkPainted = true; // yes, its somewhere before or on this line
+ }
+ if(bLineMarkPainted)
+ {
+ // need to mark it!
+ //pa.setRasterOp(NotROP);
+ //pa.setPen(Qt::black);
+#ifdef COMPILE_USE_QT4
+ pa.setPen(QPen(KVI_OPTION_COLOR(KviOption_colorIrcViewMarkLine),1,Qt::DotLine));
+#else
+ pa.setPen(QPen(KVI_OPTION_COLOR(KviOption_colorIrcViewMarkLine),1,QPen::DotLine));
+#endif
+ int x = widgetWidth - 8;
+ int y = KVI_IRCVIEW_VERTICAL_BORDER;
+ pa.drawLine(x,y,x,y);
+ y++; pa.drawLine(x-1,y,x+1,y);
+ y++; pa.drawLine(x-2,y,x+2,y);
+ y++; pa.drawLine(x-3,y,x+3,y);
+ y++; pa.drawLine(x-4,y,x+4,y);
+ //pa.setRasterOp(CopyROP);
+ }
+ }
+ }
+
+ //Need to draw the sunken rect around the view now...
+ pa.setPen(colorGroup().dark());
+ pa.drawLine(0,0,widgetWidth,0);
+ pa.drawLine(0,0,0,widgetHeight);
+ pa.setPen(colorGroup().light());
+ widgetWidth--;
+ pa.drawLine(1,widgetHeight-1,widgetWidth,widgetHeight-1);
+ pa.drawLine(widgetWidth,1,widgetWidth,widgetHeight);
+
+ // COPY TO THE DISPLAY
+#ifndef COMPILE_USE_QT4
+ bitBlt(this,rectLeft,rectTop,pDoubleBufferPixmap,rectLeft,rectTop,rectWidth,rectHeight,Qt::CopyROP);
+#endif
+// else we use the Qt4 native double buffering
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// The IrcView : calculate line wraps
+//
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#define IRCVIEW_WCHARWIDTH(__c) (((__c).unicode() < 0xff) ? m_iFontCharacterWidth[(__c).unicode()] : m_pFm->width(__c))
+
+void KviIrcView::calculateLineWraps(KviIrcViewLine *ptr,int maxWidth)
+{
+ //
+ // Another monster
+ //
+
+ if(maxWidth<=0) return;
+
+ if(ptr->iBlockCount != 0)kvi_free(ptr->pBlocks); // free any previous wrap blocks
+ ptr->pBlocks = (KviIrcViewWrappedBlock *)kvi_malloc(sizeof(KviIrcViewWrappedBlock)); // alloc one block
+ ptr->iMaxLineWidth = maxWidth; // calculus for this width
+ ptr->iBlockCount = 0; // it will be ++
+ ptr->uLineWraps = 0; // no line wraps yet
+
+ unsigned int curAttrBlock = 0; // Current attribute block
+ int curLineWidth = 0;
+
+ // init the first block
+ ptr->pBlocks->block_start = 0;
+ ptr->pBlocks->block_len = 0;
+ ptr->pBlocks->block_width = 0;
+ ptr->pBlocks->pChunk = &(ptr->pChunks[0]); // always an attribute block
+
+ int maxBlockLen = ptr->pChunks->iTextLen; // ptr->pChunks[0].iTextLen
+
+ const QChar * unicode = ptr->szText.unicode();
+
+ for(;;)
+ {
+ //Calculate the block_width
+ register const QChar * p = unicode + ptr->pBlocks[ptr->iBlockCount].block_start;
+ int curBlockLen = 0;
+ int curBlockWidth = 0;
+
+ if(ptr->pChunks[curAttrBlock].type == KVI_TEXT_ICON)
+ {
+ curBlockWidth = m_iIconWidth;
+ } else {
+ while(curBlockLen < maxBlockLen)
+ {
+ // FIXME: this is ugly :/
+ curBlockWidth += IRCVIEW_WCHARWIDTH(*p);
+ curBlockLen++;
+ p++;
+ }
+ }
+ //Check the length
+ curLineWidth += curBlockWidth;
+
+ if(curLineWidth < maxWidth)
+ {
+ //debug("Block of %d pix and len %d with type %d",ptr->pBlocks[ptr->iBlockCount].block_width,ptr->pBlocks[ptr->iBlockCount].block_len,ptr->pChunks[curAttrBlock].type);
+ //Ok....proceed to next block
+ ptr->pBlocks[ptr->iBlockCount].block_len = curBlockLen;
+ ptr->pBlocks[ptr->iBlockCount].block_width = curBlockWidth;
+ curAttrBlock++;
+ ptr->iBlockCount++;
+ //Process the next block of data in the next loop or return if have no more blocks
+ if(curAttrBlock < ptr->uChunkCount)
+ {
+ ptr->pBlocks = (KviIrcViewWrappedBlock *)kvi_realloc(ptr->pBlocks,(ptr->iBlockCount + 1) * sizeof(KviIrcViewWrappedBlock));
+ ptr->pBlocks[ptr->iBlockCount].block_start = ptr->pChunks[curAttrBlock].iTextStart;
+ ptr->pBlocks[ptr->iBlockCount].block_len = 0;
+ ptr->pBlocks[ptr->iBlockCount].block_width = 0;
+ ptr->pBlocks[ptr->iBlockCount].pChunk = &(ptr->pChunks[curAttrBlock]);
+ maxBlockLen = ptr->pBlocks[ptr->iBlockCount].pChunk->iTextLen;
+ } else return;
+ } else {
+ //Need word wrap
+ //First go back to an admissible width
+ while((curLineWidth >= maxWidth) && curBlockLen)
+ {
+ p--;
+ curBlockLen--;
+ curLineWidth-=IRCVIEW_WCHARWIDTH(*p);
+ }
+ //Now look for a space
+ while((*p != ' ') && curBlockLen)
+ {
+ p--;
+ curBlockLen--;
+ curLineWidth-=IRCVIEW_WCHARWIDTH(*p);
+ }
+
+ //If we ran up to the beginning of the block....
+ if(curBlockLen == 0)
+ {
+ if(ptr->pChunks[curAttrBlock].type == KVI_TEXT_ICON)
+ {
+ // This is an icon block: needs to be wrapped differently:
+ // The wrap block goes BEFORE the icon itself
+ ptr->pBlocks[ptr->iBlockCount].pChunk = 0;
+ ptr->pBlocks[ptr->iBlockCount].block_width = 0;
+ ptr->iBlockCount++;
+ ptr->pBlocks = (KviIrcViewWrappedBlock *)kvi_realloc(ptr->pBlocks,(ptr->iBlockCount + 1) * sizeof(KviIrcViewWrappedBlock));
+ ptr->pBlocks[ptr->iBlockCount].block_start = p - unicode;
+ ptr->pBlocks[ptr->iBlockCount].block_len = 0;
+ ptr->pBlocks[ptr->iBlockCount].block_width = 0;
+ ptr->pBlocks[ptr->iBlockCount].pChunk = &(ptr->pChunks[curAttrBlock]);
+ goto wrap_line;
+ }
+ //Don't like it....forced wrap here...
+ //Go ahead up to the biggest possible string
+ if(maxBlockLen > 0)
+ {
+ do
+ {
+ curBlockLen++;
+ p++;
+ curLineWidth+=IRCVIEW_WCHARWIDTH(*p);
+ } while((curLineWidth < maxWidth) && (curBlockLen < maxBlockLen));
+ //Now overrunned , go back 1 char
+ p--;
+ curBlockLen--;
+ }
+ //K...wrap
+ } else {
+ //found a space...
+ //include it in the first block
+ p++;
+ curBlockLen++;
+ }
+
+ ptr->pBlocks[ptr->iBlockCount].block_len = curBlockLen;
+ ptr->pBlocks[ptr->iBlockCount].block_width = -1; // word wrap --> negative block_width
+ maxBlockLen-=curBlockLen;
+ ptr->iBlockCount++;
+ ptr->pBlocks = (KviIrcViewWrappedBlock *)kvi_realloc(ptr->pBlocks,(ptr->iBlockCount + 1) * sizeof(KviIrcViewWrappedBlock));
+ ptr->pBlocks[ptr->iBlockCount].block_start = p - unicode;
+ ptr->pBlocks[ptr->iBlockCount].block_len = 0;
+ ptr->pBlocks[ptr->iBlockCount].block_width = 0;
+ ptr->pBlocks[ptr->iBlockCount].pChunk = 0;
+wrap_line:
+ curLineWidth = 0;
+ ptr->uLineWraps++;
+ if(ptr->uLineWraps == 1)
+ {
+ if(KVI_OPTION_BOOL(KviOption_boolIrcViewWrapMargin))maxWidth-=m_iWrapMargin;
+ if(maxWidth<=0) return;
+ }
+ }
+ }
+
+ ptr->iBlockCount++;
+}
+
+//================= calculateSelectionBounds ==================//
+
+void KviIrcView::calculateSelectionBounds()
+{
+ if(m_mousePressPos.y() < m_mouseCurrentPos.y())
+ {
+ m_iSelectionTop = m_mousePressPos.y();
+ m_iSelectionBottom = m_mouseCurrentPos.y();
+ m_iSelectionBegin = m_mousePressPos.x();
+ m_iSelectionEnd = m_mouseCurrentPos.x();
+ } else {
+ m_iSelectionTop = m_mouseCurrentPos.y();
+ m_iSelectionBottom = m_mousePressPos.y();
+ m_iSelectionBegin = m_mouseCurrentPos.x();
+ m_iSelectionEnd = m_mousePressPos.x();
+ }
+
+ if(m_iSelectionBegin < m_iSelectionEnd)
+ {
+ m_iSelectionLeft = m_iSelectionBegin;
+ m_iSelectionRight = m_iSelectionEnd;
+ } else {
+ m_iSelectionLeft = m_iSelectionEnd;
+ m_iSelectionRight = m_iSelectionBegin;
+ }
+}
+
+
+//=============== checkSelectionBlock ===============//
+
+bool KviIrcView::checkSelectionBlock(KviIrcViewLine * line,int left,int bottom,int bufIndex)
+{
+ //
+ // Yahoo!!!!
+ //
+ const QChar * unicode = line->szText.unicode();
+ register const QChar * p = unicode + line->pBlocks[bufIndex].block_start;
+
+ int top = bottom-m_iFontLineSpacing;
+ int right = ((line->pBlocks[bufIndex].block_width >= 0) ? \
+ left+line->pBlocks[bufIndex].block_width : width()-(KVI_IRCVIEW_HORIZONTAL_BORDER + m_pScrollBar->width()));
+ if(bottom < m_iSelectionTop)return false; //The selection starts under this line
+ if(top > m_iSelectionBottom)return false; //The selection ends over this line
+ if((top >= m_iSelectionTop)&&(bottom < m_iSelectionBottom))
+ {
+ //Whole line selected
+ if(line->pBlocks[bufIndex].pChunk && line->pBlocks[bufIndex].pChunk->type == KVI_TEXT_ICON)
+ m_pWrappedBlockSelectionInfo->selection_type = KVI_IRCVIEW_BLOCK_SELECTION_ICON;
+ else
+ m_pWrappedBlockSelectionInfo->selection_type = KVI_IRCVIEW_BLOCK_SELECTION_TOTAL;
+ return true;
+ }
+ if((top < m_iSelectionTop) && (bottom >= m_iSelectionBottom))
+ {
+ //Selection begins and ends in this line
+ if(right < m_iSelectionLeft)return false;
+ if(left > m_iSelectionRight)return false;
+ if(line->pBlocks[bufIndex].pChunk && line->pBlocks[bufIndex].pChunk->type == KVI_TEXT_ICON)
+ {
+ m_pWrappedBlockSelectionInfo->selection_type = KVI_IRCVIEW_BLOCK_SELECTION_ICON;
+ return true;
+ }
+ if((right <= m_iSelectionRight) && (left > m_iSelectionLeft))
+ {
+ //Whole line selected
+ m_pWrappedBlockSelectionInfo->selection_type = KVI_IRCVIEW_BLOCK_SELECTION_TOTAL;
+ return true;
+ }
+ if((right > m_iSelectionRight) && (left <= m_iSelectionLeft))
+ {
+ //Selection ends and begins in THIS BLOCK!
+ m_pWrappedBlockSelectionInfo->selection_type = KVI_IRCVIEW_BLOCK_SELECTION_CENTRAL;
+ m_pWrappedBlockSelectionInfo->part_1_length = 0;
+ m_pWrappedBlockSelectionInfo->part_1_width = 0;
+ while((left <= m_iSelectionLeft) && (m_pWrappedBlockSelectionInfo->part_1_length < line->pBlocks[bufIndex].block_len)){
+ int www = IRCVIEW_WCHARWIDTH(*p);
+ left += www;
+ m_pWrappedBlockSelectionInfo->part_1_width += www;
+ p++;
+ m_pWrappedBlockSelectionInfo->part_1_length++;
+ }
+ //Need to include the first character
+ if(m_pWrappedBlockSelectionInfo->part_1_length > 0)
+ {
+ m_pWrappedBlockSelectionInfo->part_1_length--;
+ p--;
+ int www = IRCVIEW_WCHARWIDTH(*p);
+ left -= www;
+ m_pWrappedBlockSelectionInfo->part_1_width -= www;
+ }
+ int maxLenNow = line->pBlocks[bufIndex].block_len-m_pWrappedBlockSelectionInfo->part_1_length;
+ int maxWidthNow = line->pBlocks[bufIndex].block_width-m_pWrappedBlockSelectionInfo->part_1_width;
+ m_pWrappedBlockSelectionInfo->part_2_length = 0;
+ m_pWrappedBlockSelectionInfo->part_2_width = 0;
+ while((left < m_iSelectionRight) && (m_pWrappedBlockSelectionInfo->part_2_length < maxLenNow))
+ {
+ int www = IRCVIEW_WCHARWIDTH(*p);
+ left += www;
+ m_pWrappedBlockSelectionInfo->part_2_width += www;
+ p++;
+ m_pWrappedBlockSelectionInfo->part_2_length++;
+ }
+ m_pWrappedBlockSelectionInfo->part_3_length = maxLenNow-m_pWrappedBlockSelectionInfo->part_2_length;
+ m_pWrappedBlockSelectionInfo->part_3_width = maxWidthNow-m_pWrappedBlockSelectionInfo->part_2_width;
+ return true;
+ }
+ if(right > m_iSelectionRight)
+ {
+ //Selection ends in THIS BLOCK!
+ m_pWrappedBlockSelectionInfo->selection_type = KVI_IRCVIEW_BLOCK_SELECTION_LEFT;
+ m_pWrappedBlockSelectionInfo->part_1_length = 0;
+ m_pWrappedBlockSelectionInfo->part_1_width = 0;
+ while((left < m_iSelectionRight) && (m_pWrappedBlockSelectionInfo->part_1_length < line->pBlocks[bufIndex].block_len))
+ {
+ int www = IRCVIEW_WCHARWIDTH(*p);
+ left += www;
+ m_pWrappedBlockSelectionInfo->part_1_width += www;
+ p++;
+ m_pWrappedBlockSelectionInfo->part_1_length++;
+ }
+ m_pWrappedBlockSelectionInfo->part_2_length = line->pBlocks[bufIndex].block_len-m_pWrappedBlockSelectionInfo->part_1_length;
+ m_pWrappedBlockSelectionInfo->part_2_width = line->pBlocks[bufIndex].block_width-m_pWrappedBlockSelectionInfo->part_1_width;
+ //debug("%d",m_pWrappedBlockSelectionInfo->part_2_width);
+ return true;
+ }
+ //Selection begins in THIS BLOCK!
+ m_pWrappedBlockSelectionInfo->selection_type = KVI_IRCVIEW_BLOCK_SELECTION_RIGHT;
+ m_pWrappedBlockSelectionInfo->part_1_length = 0;
+ m_pWrappedBlockSelectionInfo->part_1_width = 0;
+ while((left <= m_iSelectionLeft) && (m_pWrappedBlockSelectionInfo->part_1_length < line->pBlocks[bufIndex].block_len))
+ {
+ int www = IRCVIEW_WCHARWIDTH(*p);
+ left += www;
+ m_pWrappedBlockSelectionInfo->part_1_width += www;
+ p++;
+ m_pWrappedBlockSelectionInfo->part_1_length++;
+ }
+ //Need to include the first character
+ if(m_pWrappedBlockSelectionInfo->part_1_length > 0)
+ {
+ m_pWrappedBlockSelectionInfo->part_1_length--;
+ p--;
+ int www = IRCVIEW_WCHARWIDTH(*p);
+ left -= www;
+ m_pWrappedBlockSelectionInfo->part_1_width -= www;
+ }
+ m_pWrappedBlockSelectionInfo->part_2_length = line->pBlocks[bufIndex].block_len-m_pWrappedBlockSelectionInfo->part_1_length;
+ m_pWrappedBlockSelectionInfo->part_2_width = line->pBlocks[bufIndex].block_width-m_pWrappedBlockSelectionInfo->part_1_width;
+ return true;
+ }
+
+ if(top < m_iSelectionTop)
+ {
+ //Selection starts in this line
+ if(right < m_iSelectionBegin)return false;
+ if(line->pBlocks[bufIndex].pChunk && line->pBlocks[bufIndex].pChunk->type == KVI_TEXT_ICON)
+ {
+ m_pWrappedBlockSelectionInfo->selection_type = KVI_IRCVIEW_BLOCK_SELECTION_ICON;
+ return true;
+ }
+ if(left > m_iSelectionBegin)
+ {
+ //Whole block selected
+ m_pWrappedBlockSelectionInfo->selection_type = KVI_IRCVIEW_BLOCK_SELECTION_TOTAL;
+ return true;
+ }
+ //Selection begins in THIS BLOCK!
+ m_pWrappedBlockSelectionInfo->selection_type = KVI_IRCVIEW_BLOCK_SELECTION_RIGHT;
+ m_pWrappedBlockSelectionInfo->part_1_length = 0;
+ m_pWrappedBlockSelectionInfo->part_1_width = 0;
+ while((left <= m_iSelectionBegin) && (m_pWrappedBlockSelectionInfo->part_1_length < line->pBlocks[bufIndex].block_len))
+ {
+ int www = IRCVIEW_WCHARWIDTH(*p);
+ left += www;
+ m_pWrappedBlockSelectionInfo->part_1_width += www;
+ p++;
+ m_pWrappedBlockSelectionInfo->part_1_length++;
+ }
+ //Need to include the first character
+ if(m_pWrappedBlockSelectionInfo->part_1_length > 0)
+ {
+ m_pWrappedBlockSelectionInfo->part_1_length--;
+ p--;
+ int www = IRCVIEW_WCHARWIDTH(*p);
+ left -= www;
+ m_pWrappedBlockSelectionInfo->part_1_width -= www;
+ }
+ m_pWrappedBlockSelectionInfo->part_2_length = line->pBlocks[bufIndex].block_len-m_pWrappedBlockSelectionInfo->part_1_length;
+ m_pWrappedBlockSelectionInfo->part_2_width = line->pBlocks[bufIndex].block_width-m_pWrappedBlockSelectionInfo->part_1_width;
+ return true;
+ }
+ //Selection ends in this line
+ if(left > m_iSelectionEnd)return false;
+ if(line->pBlocks[bufIndex].pChunk && line->pBlocks[bufIndex].pChunk->type == KVI_TEXT_ICON)
+ {
+ m_pWrappedBlockSelectionInfo->selection_type = KVI_IRCVIEW_BLOCK_SELECTION_ICON;
+ return true;
+ }
+ if(right < m_iSelectionEnd)
+ {
+ //Whole block selected
+ m_pWrappedBlockSelectionInfo->selection_type = KVI_IRCVIEW_BLOCK_SELECTION_TOTAL;
+ return true;
+ }
+ //Selection ends in THIS BLOCK!
+ m_pWrappedBlockSelectionInfo->selection_type = KVI_IRCVIEW_BLOCK_SELECTION_LEFT;
+ m_pWrappedBlockSelectionInfo->part_1_length = 0;
+ m_pWrappedBlockSelectionInfo->part_1_width = 0;
+ while((left < m_iSelectionEnd) && (m_pWrappedBlockSelectionInfo->part_1_length < line->pBlocks[bufIndex].block_len))
+ {
+ int www = IRCVIEW_WCHARWIDTH(*p);
+ left += www;
+ m_pWrappedBlockSelectionInfo->part_1_width += www;
+ p++;
+ m_pWrappedBlockSelectionInfo->part_1_length++;
+ }
+ m_pWrappedBlockSelectionInfo->part_2_length = line->pBlocks[bufIndex].block_len-m_pWrappedBlockSelectionInfo->part_1_length;
+ m_pWrappedBlockSelectionInfo->part_2_width = line->pBlocks[bufIndex].block_width-m_pWrappedBlockSelectionInfo->part_1_width;
+ return true;
+}
+
+//============ recalcFontVariables ==============//
+
+void KviIrcView::recalcFontVariables(const QFontMetrics &fm,const QFontInfo &fi)
+{
+ // FIXME: #warning "OPTIMIZE THIS: GLOBAL VARIABLES"
+ if(m_pFm)delete m_pFm;
+ m_pFm = new QFontMetrics(fm);
+ m_iFontLineSpacing = m_pFm->lineSpacing();
+ if(m_iFontLineSpacing < KVI_IRCVIEW_PIXMAP_SIZE && KVI_OPTION_BOOL(KviOption_boolIrcViewShowImages))
+ {
+ m_iFontLineSpacing = KVI_IRCVIEW_PIXMAP_SIZE;
+ }
+ m_iFontDescent =m_pFm->descent();
+ m_iFontLineWidth =m_pFm->lineWidth();
+ // cache the first 256 characters
+ for(unsigned short i=0;i<256;i++)
+ {
+ m_iFontCharacterWidth[i]=m_pFm->width(QChar(i));
+ }
+ if(m_iFontLineWidth==0)m_iFontLineWidth=1;
+ m_iWrapMargin = m_pFm->width("wwww");
+ //for(int i=0;i<256;i++)m_iFontCharacterWidth[i]=fm.width((char)i);
+ m_iMinimumPaintWidth = (m_pFm->width('w') << 1)+m_iWrapMargin;
+ m_iRelativePixmapY = (m_iFontLineSpacing + KVI_IRCVIEW_PIXMAP_SIZE) >> 1;
+ m_iIconWidth = m_pFm->width("w");
+
+ if(fi.fixedPitch() && (m_iIconWidth > 0))
+ {
+ while(m_iIconWidth < 18)m_iIconWidth += m_iIconWidth;
+ m_iIconSideSpacing = (m_iIconWidth - 16) >> 1;
+ } else {
+ m_iIconWidth = 18;
+ m_iIconSideSpacing = 1;
+ }
+}
+
+//================ resizeEvent ===============//
+
+void KviIrcView::resizeEvent(QResizeEvent *)
+{
+ int iScr = m_pScrollBar->sizeHint().width();
+ int iLeft = width()-iScr;
+ m_pToolsButton->setGeometry(iLeft,0,iScr,iScr);
+ m_pScrollBar->setGeometry(iLeft,iScr,iScr,height() - iScr);
+
+ if(m_pToolWidget)
+ {
+ if( ((m_pToolWidget->x() + m_pToolWidget->width()) > (iLeft - 1)) ||
+ ((m_pToolWidget->y() + m_pToolWidget->height()) > (height() - 1)))
+ {
+ m_pToolWidget->move(10,10);
+ }
+ }
+}
+
+QSize KviIrcView::sizeHint() const
+{
+ QSize ret(KVI_IRCVIEW_SIZEHINT_WIDTH,KVI_IRCVIEW_SIZEHINT_HEIGHT);
+ return ret;
+}
+
+void KviIrcView::showToolsPopup()
+{
+ if(!m_pToolsPopup)
+ m_pToolsPopup = new KviTalPopupMenu(this);
+
+ m_pToolsPopup->clear();
+
+ if(m_pToolWidget)
+ m_pToolsPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_SEARCH)),__tr2qs("Hide Find Window"),this,SLOT(toggleToolWidget()));
+ else
+ m_pToolsPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_SEARCH)),__tr2qs("Show Find Window"),this,SLOT(toggleToolWidget()));
+ m_pToolsPopup->insertSeparator();
+ m_pToolsPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_PLUS)),__tr2qs("Zoom In"),this,SLOT(increaseFontSize()));
+ m_pToolsPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_MINUS)),__tr2qs("Zoom Out"),this,SLOT(decreaseFontSize()));
+ m_pToolsPopup->insertItem(__tr2qs("Choose Temporary Font..."),this,SLOT(chooseFont()));
+ m_pToolsPopup->insertItem(__tr2qs("Choose Temporary Background..."),this,SLOT(chooseBackground()));
+ int id = m_pToolsPopup->insertItem(__tr2qs("Reset Temporary Background"),this,SLOT(resetBackground()));
+ m_pToolsPopup->setItemEnabled(id,m_pPrivateBackgroundPixmap != 0);
+ m_pToolsPopup->insertSeparator();
+ m_pToolsPopup->insertItem(__tr2qs("Clear Buffer"),this,SLOT(clearBuffer()));
+
+ QSize s = m_pToolsPopup->sizeHint();
+
+ m_pToolsPopup->popup(m_pToolsButton->mapToGlobal(QPoint(m_pToolsButton->width() - s.width(),m_pToolsButton->height())));
+}
+
+void KviIrcView::increaseFontSize()
+{
+ QFont f = font();
+ f.setPointSize(f.pointSize() + 1);
+ setFont(f);
+}
+
+void KviIrcView::decreaseFontSize()
+{
+ QFont f = font();
+ int p = f.pointSize();
+ if(p > 2)p--;
+ f.setPointSize(p);
+ setFont(f);
+}
+
+void KviIrcView::chooseFont()
+{
+ bool bOk;
+ QFont f = QFontDialog::getFont(&bOk,font(),this);
+ if(!bOk)return;
+ setFont(f);
+}
+
+void KviIrcView::chooseBackground()
+{
+ QString f;
+ if(!KviFileDialog::askForOpenFileName(f,__tr2qs("Choose the background image...")))return;
+ if(f.isEmpty())return;
+ QPixmap p(f);
+ if(p.isNull())
+ {
+ QMessageBox::information(this,__tr2qs("Invalid image"),__tr2qs("Failed to load the selected image"),__tr2qs("Ok"));
+ return;
+ }
+ setPrivateBackgroundPixmap(p);
+}
+
+void KviIrcView::resetBackground()
+{
+ setPrivateBackgroundPixmap(0);
+}
+
+void KviIrcView::toggleToolWidget()
+{
+ if(m_pToolWidget)
+ {
+ delete m_pToolWidget;
+ m_pToolWidget = 0;
+ m_pCursorLine = 0;
+ repaint();
+
+ } else {
+ m_pToolWidget = new KviIrcViewToolWidget(this);
+ int w = m_pToolWidget->sizeHint().width();
+ m_pToolWidget->move(width() - (w + 40),10);
+ m_pToolWidget->show();
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// The IrcView : find
+//
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+void KviIrcView::setCursorLine(KviIrcViewLine * l)
+{
+ m_pCursorLine = l;
+ if(m_pCursorLine == m_pCurLine)
+ {
+
+ repaint();
+
+ return;
+ }
+ int sc = m_pScrollBar->value();
+ l = m_pCurLine;
+ if(m_pCursorLine->uIndex > m_pCurLine->uIndex)
+ {
+ // The cursor line is below the current line
+ while(l && (l != m_pCursorLine))
+ {
+ l = l->pNext;
+ sc++;
+ }
+ if(!l)return;
+ if(sc != m_pScrollBar->value())
+ {
+ m_pCurLine = m_pCursorLine;
+ m_iLastScrollBarValue = sc;
+ m_pScrollBar->setValue(sc);
+ } else {
+ repaint();
+ }
+ } else {
+ // The cursor line is over the current line
+ // Here we're in trouble :D
+ int curBottomCoord = height() - KVI_IRCVIEW_VERTICAL_BORDER;
+ int maxLineWidth = width();
+ if(KVI_OPTION_BOOL(KviOption_boolIrcViewShowImages))maxLineWidth -= KVI_IRCVIEW_PIXMAP_SEPARATOR_AND_DOUBLEBORDER_WIDTH;
+ //Make sure that we have enough space to paint something...
+ if(maxLineWidth < m_iMinimumPaintWidth)return; // ugh
+ //And loop thru lines until we not run over the upper bound of the view
+ KviIrcViewLine * curLine = m_pCurLine;
+ while(l)
+ {
+ if(maxLineWidth != l->iMaxLineWidth)calculateLineWraps(l,maxLineWidth);
+ curBottomCoord -= (l->uLineWraps + 1) * m_iFontLineSpacing;
+ while(curLine && (curBottomCoord < KVI_IRCVIEW_VERTICAL_BORDER))
+ {
+ if(curLine->iMaxLineWidth != maxLineWidth)calculateLineWraps(curLine,maxLineWidth);
+ curBottomCoord += ((curLine->uLineWraps + 1) * m_iFontLineSpacing) + m_iFontDescent;
+ curLine = curLine->pPrev;
+ sc--;
+ }
+ if(l == m_pCursorLine)break;
+ curBottomCoord -= m_iFontDescent;
+ l = l->pPrev;
+ }
+ if(!curLine)return;
+ if(sc != m_pScrollBar->value())
+ {
+ m_pCurLine = curLine;
+ m_iLastScrollBarValue = sc;
+ m_pScrollBar->setValue(sc);
+ } else {
+ repaint();
+ }
+ }
+}
+
+void KviIrcView::findNext(const QString& szText,bool bCaseS,bool bRegExp,bool bExtended)
+{
+ KviIrcViewLine * l = m_pCursorLine;
+ if(!l)l = m_pCurLine;
+ if(l)
+ {
+ l = l->pNext;
+ if(!l)l = m_pFirstLine;
+ KviIrcViewLine * start = l;
+
+ int idx = -1;
+
+ do{
+ if(m_pToolWidget)
+ {
+ if(!(m_pToolWidget->messageEnabled(l->iMsgType)))goto do_pNext;
+ }
+
+ if(bRegExp)
+ {
+ QRegExp re(szText,bCaseS,!bExtended);
+#if QT_VERSION >= 300
+ idx = re.search(l->szText,0);
+#else
+ idx = re.find(l->szText,0);
+#endif
+ } else {
+ QString tmp = l->szText;
+ idx = tmp.find(szText,0,bCaseS);
+ }
+
+ if(idx != -1)
+ {
+ setCursorLine(l);
+ if(m_pToolWidget)
+ {
+ QString tmp;
+ KviQString::sprintf(tmp,__tr2qs("Pos %d"),idx);
+ m_pToolWidget->setFindResult(tmp);
+ }
+ return;
+ }
+
+do_pNext:
+
+ l = l->pNext;
+ if(!l)l = m_pFirstLine;
+
+ } while(l != start);
+ }
+ m_pCursorLine = 0;
+ repaint();
+ if(m_pToolWidget)m_pToolWidget->setFindResult(__tr2qs("Not found"));
+}
+
+
+void KviIrcView::findPrev(const QString& szText,bool bCaseS,bool bRegExp,bool bExtended)
+{
+ KviIrcViewLine * l = m_pCursorLine;
+ if(!l)l = m_pCurLine;
+ if(l)
+ {
+ l = l->pPrev;
+ if(!l)l = m_pLastLine;
+ KviIrcViewLine * start = l;
+
+ int idx = -1;
+
+ do{
+
+ if(m_pToolWidget)
+ {
+ if(!(m_pToolWidget->messageEnabled(l->iMsgType)))goto do_pPrev;
+ }
+
+ if(bRegExp)
+ {
+ QRegExp re(szText,bCaseS,!bExtended);
+#if QT_VERSION >= 300
+ idx = re.search(l->szText,0);
+#else
+ idx = re.find(l->szText,0);
+#endif
+ } else {
+ QString tmp = l->szText;
+ idx = tmp.find(szText,0,bCaseS);;
+ }
+
+ if(idx != -1)
+ {
+ setCursorLine(l);
+ if(m_pToolWidget)
+ {
+ QString tmp;
+ KviQString::sprintf(tmp,__tr2qs("Pos %d"),idx);
+ m_pToolWidget->setFindResult(tmp);
+ }
+ return;
+ }
+
+do_pPrev:
+
+ l = l->pPrev;
+ if(!l)l = m_pLastLine;
+
+ } while(l != start);
+ }
+ m_pCursorLine = 0;
+
+ repaint();
+ if(m_pToolWidget)m_pToolWidget->setFindResult(__tr2qs("Not found"));
+}
+
+/*
+void KviIrcView::findClosestPositionInText(int xCursorPos,int yCursorPos,KviIrcViewPositionInText &pos)
+{
+ pos.pLine = getVisibleLineAt(xCursorPos,uCursorPos);
+}
+*/
+
+
+KviIrcViewLine * KviIrcView::getVisibleLineAt(int xPos,int yPos)
+{
+ KviIrcViewLine * l = m_pCurLine;
+ int iTop = height() + m_iFontDescent - KVI_IRCVIEW_VERTICAL_BORDER;
+
+ while(iTop > yPos)
+ {
+ if(l)
+ {
+ iTop -= ((l->uLineWraps + 1) * m_iFontLineSpacing) + m_iFontDescent;
+ if(iTop <= yPos)return l;
+ l = l->pPrev;
+ } else return 0;
+ }
+ return 0;
+}
+
+KviIrcViewWrappedBlock * KviIrcView::getLinkUnderMouse(int xPos,int yPos,QRect * pRect,QString * linkCmd,QString * linkText)
+{
+ KviIrcViewLine * l = m_pCurLine;
+ int iTop = height() + m_iFontDescent - KVI_IRCVIEW_VERTICAL_BORDER;
+
+ while(iTop > yPos)
+ {
+ if(!l)return 0;
+
+ iTop -= ((l->uLineWraps + 1) * m_iFontLineSpacing) + m_iFontDescent;
+
+ if(iTop > yPos)
+ {
+ // still below the mouse
+ l = l->pPrev;
+ continue;
+ }
+
+ // got the right KviIrcViewLine
+ int iLeft = KVI_IRCVIEW_HORIZONTAL_BORDER;
+ if(KVI_OPTION_BOOL(KviOption_boolIrcViewShowImages))iLeft += KVI_IRCVIEW_PIXMAP_AND_SEPARATOR;
+ int firstRowTop = iTop;
+ int i = 0;
+
+ for(;;)
+ {
+ if(yPos <= iTop + m_iFontLineSpacing)
+ {
+ // exactly this row of this line
+ if(iTop != firstRowTop)
+ if(KVI_OPTION_BOOL(KviOption_boolIrcViewWrapMargin))iLeft+=m_iWrapMargin;
+ if(xPos < iLeft)return 0;
+ int iBlockWidth = 0;
+ int iLastEscapeBlock = -1;
+ int iLastEscapeBlockTop = -1;
+ for(;;)
+ {
+ int iLastLeft = iLeft;
+ if(i >= l->iBlockCount)return 0;
+ if(l->pBlocks[i].pChunk)
+ if(l->pBlocks[i].pChunk->type == KVI_TEXT_ESCAPE)
+ {
+ iLastEscapeBlock=i;
+ iLastEscapeBlockTop=iTop;
+ }
+ if(l->pBlocks[i].pChunk)
+ if(l->pBlocks[i].pChunk->type == KVI_TEXT_UNESCAPE) iLastEscapeBlock=-1;
+ if(l->pBlocks[i].block_width > 0)
+ {
+ iBlockWidth = l->pBlocks[i].block_width;
+ iLeft += iBlockWidth;
+ } else {
+ if(i < (l->iBlockCount - 1))
+ {
+ // There is another block...
+ // Check if it is a wrap...
+ if(l->pBlocks[i+1].pChunk == 0)
+ {
+ iBlockWidth = width() - iLastLeft;
+ iLeft = width();
+ }
+ // else simply a zero characters block
+ }
+ }
+ if(xPos < iLeft)
+ {
+ // Got it!
+ // link ?
+ bool bHadWordWraps = false;
+ while(l->pBlocks[i].pChunk == 0)
+ {
+ // word wrap ?
+ if(i >= 0)
+ {
+ i--;
+ bHadWordWraps = true;
+ } else return 0; // all word wraps ?!!!
+ }
+ if(iLastEscapeBlock != -1)
+ {
+ int iLeftBorder=iLeft;
+ int k;
+ for(k = i ; k>=iLastEscapeBlock ; k--)
+ iLeftBorder-=l->pBlocks[k].block_width;
+ int iRightBorder=0;
+ unsigned int uLineWraps = 0;
+ for(k = iLastEscapeBlock;; k++)
+ {
+ if(l->pBlocks[k].pChunk)
+ if(l->pBlocks[k].pChunk->type != KVI_TEXT_UNESCAPE)
+ iRightBorder+=l->pBlocks[k].block_width;
+ else
+ break;
+ else
+ {
+ uLineWraps++;
+ bHadWordWraps=1;
+ }
+ }
+ if(pRect)
+ {
+ *pRect = QRect(iLeftBorder,
+ bHadWordWraps ? iLastEscapeBlockTop : iTop,
+ iRightBorder,
+ ((uLineWraps + 1) * m_iFontLineSpacing) + m_iFontDescent);
+ }
+ if(linkCmd)
+ {
+ linkCmd->setUnicodeCodes(l->pBlocks[iLastEscapeBlock].pChunk->szPayload,kvi_wstrlen(l->pBlocks[iLastEscapeBlock].pChunk->szPayload));
+ linkCmd->stripWhiteSpace();
+ if((*linkCmd)=="nc") (*linkCmd)="n";
+ }
+ if(linkText)
+ {
+ QString szLink;
+ int iEndOfLInk = iLastEscapeBlock;
+ while(1)
+ {
+ if(l->pBlocks[iEndOfLInk].pChunk)
+ if(l->pBlocks[iEndOfLInk].pChunk->type != KVI_TEXT_UNESCAPE)
+ {
+ switch(l->pBlocks[iEndOfLInk].pChunk->type)
+ {
+ case KVI_TEXT_BOLD:
+ case KVI_TEXT_UNDERLINE:
+ case KVI_TEXT_REVERSE:
+ case KVI_TEXT_RESET:
+ szLink.append(QChar(l->pBlocks[iEndOfLInk].pChunk->type));
+ break;
+ case KVI_TEXT_COLOR:
+ szLink.append(QChar(KVI_TEXT_COLOR));
+ if(l->pBlocks[iEndOfLInk].pChunk->colors.fore != KVI_NOCHANGE)
+ {
+ szLink.append(QString("%1").arg((int)(l->pBlocks[iEndOfLInk].pChunk->colors.fore)));
+ }
+ if(l->pBlocks[iEndOfLInk].pChunk->colors.back != KVI_NOCHANGE)
+ {
+ szLink.append(QChar(','));
+ szLink.append(QString("%1").arg((int)(l->pBlocks[iEndOfLInk].pChunk->colors.back)));
+ }
+ break;
+ }
+ szLink.append(l->szText.mid(l->pBlocks[iEndOfLInk].block_start,l->pBlocks[iEndOfLInk].block_len));
+ } else
+ break;
+ iEndOfLInk++;
+
+ }
+ *linkText=szLink;
+ // grab the rest of the link visible string
+ // Continue while we do not find a non word wrap block block
+ for(int bufIndex = (i + 1);bufIndex < l->iBlockCount;bufIndex++)
+ {
+ if(l->pBlocks[bufIndex].pChunk ) break; //finished : not a word wrap
+ else {
+ linkText->append(l->szText.mid(l->pBlocks[bufIndex].block_start,l->pBlocks[bufIndex].block_len));
+ }
+ }
+ }
+ return &(l->pBlocks[iLastEscapeBlock]);
+ }
+ if(l->pBlocks[i].pChunk->type == KVI_TEXT_ICON)
+ {
+ if(pRect)
+ {
+ *pRect = QRect(iLastLeft,
+ bHadWordWraps ? firstRowTop : iTop,
+ iBlockWidth,
+ ((l->uLineWraps + 1) * m_iFontLineSpacing) + m_iFontDescent);
+ }
+ if(linkCmd)
+ {
+ *linkCmd = "[!txt]";
+ QString tmp;
+ tmp.setUnicodeCodes(l->pBlocks[i].pChunk->szPayload,kvi_wstrlen(l->pBlocks[i].pChunk->szPayload));
+ linkCmd->append(tmp);
+ linkCmd->stripWhiteSpace();
+ }
+ if(linkText)
+ {
+ *linkText = "";
+ }
+ return &(l->pBlocks[i]);
+ }
+ return 0;
+ }
+ i++;
+ }
+ } else {
+ // run until a word wrap block
+ i++; //at least one block!
+ while(i < l->iBlockCount)
+ {
+ // still ok to run right
+ if(l->pBlocks[i].pChunk == 0)
+ {
+// i++;
+ break;
+ } else i++;
+ }
+ if(i >= l->iBlockCount)return 0;
+ iTop += m_iFontLineSpacing;
+ }
+ }
+ }
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Mouse handling routines
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/*
+ @doc: escape_sequences
+ @title:
+ Escape sequences and clickable links
+ @type:
+ generic
+ @body:
+ The KVIrc view widgets support clickable links.[br]
+ The links can be created using special escape sequences in the text
+ passed to the [cmd]echo[/cmd] command.[br]
+ KVIrc uses some escape sequences in the text "echoed" internally.[br]
+ The simplest way to explain it is to use an example:[br]
+ [example]
+ [cmd]echo[/cmd] This is a [fnc]$cr[/fnc]![!dbl][cmd]echo[/cmd] You have clicked it![fnc]$cr[/fnc]\clickable link$cr !
+ [/example]
+ The example above will show the following text line: "This is a clickable link".
+ If you move the mouse over the words "clickable link", you will see the text highlighted.[br]
+ Once you double-click one of that words, the command "[cmd]echo[/cmd] You have clicked it!" will be executed.[br]
+ The format looks complex ?... it is not...just read on.[br]
+
+ <cr>!<link_type><cr><visible text><cr>
+ <cr>!<escape_command><cr><visible text><cr>
+
+ [big]Escape format[/big]
+ The whole escape sequence format is the following:[br]
+ [b]<cr>!<escape_command><cr><visible text><cr>[/b][br]
+ <cr> is the carriage return character. You can obtain it by using the [fnc]]$cr[/fnc] function.[br]
+ <visible text> is the text that will appear as "link" when you move the mouse over it.[br]
+ <escape_command> is the description of the actions to be taken when the user interacts with the link.[br]
+ <escape_command> has the two following syntactic forms:[br]
+ [b]<escape_command> ::= <user_defined_commands>[/b][br]
+ [b]<escape_command> ::= <builtin_link_description>[/b]
+
+ [big]User defined links[/big][br]
+ The user defined links allow you to perform arbitrary commands when the user interacts with the link.[br]
+ The commands are specified in the <escape_command> part by using the following syntax:[br]
+ <escape_command> ::= <user_defined_commands>[br]
+ <user_defined_commands> ::= <command_rule> [<user_defined_commands>][br]
+ <command_rule> ::= <action_tag><command>[br]
+ <action_tag> ::= "[!" <action> "]"[br]
+ <action> ::= "rbt" | "mbt" | "dbl" | "txt"[br]
+ <command> ::= any kvirc command (see notes below)[br]
+
+ [big]Builtin links[/big][br]
+ The builtin links have builtin actions performed when the user interact with the link.[br]
+ These links are used internally in KVIrc , but you can use them too.[br]
+ The <escape_command> is a single letter this time: it defines the type of the link.[br]
+ Currently KVIrc uses six types of builtin links : 'n' for nickname links, 'u' for url links,
+ 'c' for channel links, 'h' for hostname links, 'm' for mask links and 's' for server links.[br]
+ Theoretically you can also use your own link types: just use any other letter or digit (you can't use ']' and <cr>),
+ but probably you will prefer a completely user defined link in that case anyway.[br]
+ Once the user interacts with the link , kvirc executes the predefined events:[br]
+ On right-click the event OnBuiltinLinkRightClicked is triggered: the first parameter is the link type,
+ the second parameter is the <visible text> (as a single parameter!!!)[br]
+ On middle-click the event OnBuiltinLinkMiddleClicked is triggered: the parameters are similar to the previous one.[br]
+ In the same way you have OnBuiltinLinkDoubleClicked.[br]
+
+ [big]A shortcut[/big]
+ You may have a look at the [fnc]$fmtlink[/fnc] function: it does automatically some of the job explained
+ in this document.[br]
+
+*/
+
+// FIXME: #warning "Finish the doc above!! Maybe some examples ?!"
+
+
+void KviIrcView::mouseDoubleClickEvent(QMouseEvent *e)
+{
+ QString cmd;
+ QString linkCmd;
+ QString linkText;
+
+ if(m_iMouseTimer)
+ {
+ killTimer(m_iMouseTimer);
+ m_iMouseTimer=0;
+ delete m_pLastEvent;
+ m_pLastEvent = 0;
+ }
+
+ getLinkUnderMouse(e->pos().x(),e->pos().y(),0,&linkCmd,&linkText);
+
+ if(linkCmd.isEmpty())
+ {
+ KVS_TRIGGER_EVENT_0(KviEvent_OnTextViewDoubleClicked,m_pKviWindow);
+ return;
+ }
+
+ QString szCmd(linkCmd);
+ szCmd.remove(0,1);
+
+ KviKvsVariantList * pParams = new KviKvsVariantList();
+ if(!szCmd.isEmpty()) pParams->append(szCmd);
+ else pParams->append(linkText);
+ pParams->append(linkText);
+ pParams->append(szCmd);
+
+
+ switch(linkCmd[0].unicode())
+ {
+ case 'n':
+ {
+ bool bTrigger = false;
+ switch(m_pKviWindow->type())
+ {
+ case KVI_WINDOW_TYPE_CHANNEL:
+ if(((KviChannel *)m_pKviWindow)->isOn(linkText))
+ {
+ KVS_TRIGGER_EVENT(KviEvent_OnChannelNickDefaultActionRequest,m_pKviWindow,pParams);
+ } else bTrigger = true;
+ break;
+ case KVI_WINDOW_TYPE_QUERY:
+ if(KviQString::equalCI(((KviQuery *)m_pKviWindow)->windowName(),linkText))
+ {
+ KVS_TRIGGER_EVENT(KviEvent_OnQueryNickDefaultActionRequest,m_pKviWindow,pParams);
+ } else bTrigger = true;
+ break;
+ default:
+ bTrigger = true;
+ break;
+ }
+ if(bTrigger)
+ {
+ if(console())
+ {
+ KVS_TRIGGER_EVENT(KviEvent_OnNickLinkDefaultActionRequest,m_pKviWindow,pParams);
+ }
+ }
+ }
+ break;
+ case 'm':
+ if((linkCmd.length() > 2) && (m_pKviWindow->type() == KVI_WINDOW_TYPE_CHANNEL))
+ {
+ if(((KviChannel *)m_pKviWindow)->isMeOp())
+ {
+ QChar plmn = linkCmd[1];
+ if((plmn.unicode() == '+') || (plmn.unicode() == '-'))
+ {
+ QString target(m_pKviWindow->windowName());
+ target.replace("\\","\\\\");
+ target.replace("\"","\\\"");
+ target.replace(";","\\;");
+ target.replace("$","\\$");
+ target.replace("%","\\%");
+ QChar flag = linkCmd[2];
+ switch(flag.unicode())
+ {
+ case 'o':
+ case 'v':
+ // We can do nothing here...
+ break;
+
+ case 'b':
+ case 'I':
+ case 'e':
+ case 'k':
+ KviQString::sprintf(cmd,"mode %Q %c%c $0",&target,plmn.latin1(),flag.latin1());
+ break;
+ default:
+ KviQString::sprintf(cmd,"mode %Q %c%c",&target,plmn.latin1(),flag.latin1());
+ break;
+ }
+ }
+ }
+ }
+ break;
+ case 'h':
+ m_pKviWindow->output(KVI_OUT_HOSTLOOKUP,__tr2qs("Looking up host %Q..."),&linkText);
+ cmd = "host -a $0";
+ break;
+ case 'u':
+ {
+ QString urlText;
+ if(!szCmd.isEmpty()) urlText=szCmd;
+ else urlText=linkText;
+ if(
+ !KviQString::cmpCIN(urlText,"irc://",6) ||
+ !KviQString::cmpCIN(urlText,"irc6://",7) ||
+ !KviQString::cmpCIN(urlText,"ircs://",7) ||
+ !KviQString::cmpCIN(urlText,"ircs6://",8)
+ )
+ {
+ KviIrcUrl::run(urlText,KviIrcUrl::TryCurrentContext | KviIrcUrl::DoNotPartChans, console());
+ } else {
+ cmd = "openurl $0";
+ }
+ }
+ break;
+ case 'c':
+ {
+ if(console() && console()->connection())
+ {
+ QString szChan=linkText;
+ if(szCmd.length()>0) szChan=szCmd;
+ if(KviChannel * c = console()->connection()->findChannel(szChan))
+ {
+ // FIXME: #warning "Is this ok ?"
+ c->raise();
+ c->setFocus();
+ } else {
+ cmd = QString("join %1").arg(szChan);
+ }
+ }
+ }
+ break;
+ case 's':
+ cmd = "motd $0";
+ break;
+ default:
+ {
+ getLinkEscapeCommand(cmd,linkCmd,"[!dbl]");
+ if(cmd.isEmpty())
+ {
+ KVS_TRIGGER_EVENT_0(KviEvent_OnTextViewDoubleClicked,m_pKviWindow);
+ }
+ }
+ break;
+ }
+ if(!cmd.isEmpty())
+ {
+ KviKvsScript::run(cmd,m_pKviWindow,pParams);
+ }
+ delete pParams;
+}
+
+void KviIrcView::mousePressEvent(QMouseEvent *e)
+{
+ if(m_pKviWindow->input()) m_pKviWindow->input()->setFocus();
+
+ if(e->button() & Qt::LeftButton)
+ {
+ // This is the beginning of a selection...
+ // We just set the mouse to be "down" and
+ // await mouseMove events...
+
+ if(m_pToolWidget)
+ {
+ m_pCursorLine = getVisibleLineAt(e->pos().x(),e->pos().y());
+ repaint();
+ }
+
+ m_mousePressPos = e->pos();
+ m_mouseCurrentPos = e->pos();
+
+ m_bMouseIsDown = true;
+
+ m_bShiftPressed = (e->state() & Qt::ShiftButton);
+
+ calculateSelectionBounds();
+ }
+
+ if(e->button() & Qt::LeftButton)
+ {
+ if(m_iMouseTimer)
+ {
+ killTimer(m_iMouseTimer);
+ m_iMouseTimer=0;
+ delete m_pLastEvent;
+ m_pLastEvent = 0;
+ } else {
+ m_iMouseTimer = startTimer(QApplication::doubleClickInterval());
+ m_pLastEvent = new QMouseEvent(*e);
+ }
+ } else {
+ mouseRealPressEvent(e);
+ }
+}
+
+void KviIrcView::mouseRealPressEvent(QMouseEvent *e)
+{
+ QString linkCmd;
+ QString linkText;
+ getLinkUnderMouse(e->pos().x(),e->pos().y(),0,&linkCmd,&linkText);
+
+ QString szCmd(linkCmd);
+ szCmd.remove(0,1);
+
+ KviKvsVariantList * pParams = new KviKvsVariantList();
+ if(!szCmd.isEmpty()) pParams->append(szCmd);
+ else pParams->append(linkText);
+ pParams->append(linkText);
+ pParams->append(szCmd);
+
+
+ if(!(e->state() & Qt::ControlButton))//(e->button() & Qt::RightButton) && (
+ {
+ if(!linkCmd.isEmpty())
+ {
+ switch(linkCmd[0].unicode())
+ {
+ case 'n':
+ {
+ bool bTrigger = false;
+ switch(m_pKviWindow->type())
+ {
+ case KVI_WINDOW_TYPE_CHANNEL:
+ if(((KviChannel *)m_pKviWindow)->isOn(linkText))
+ {
+ if(e->button() & Qt::RightButton)
+ KVS_TRIGGER_EVENT(KviEvent_OnChannelNickPopupRequest,m_pKviWindow,pParams);
+ if(e->button() & Qt::LeftButton) {
+ KVS_TRIGGER_EVENT(KviEvent_OnChannelNickLinkClick,m_pKviWindow,pParams);
+ if(m_pKviWindow)
+ {
+ if(m_pKviWindow->inherits("KviChannel")) {
+ KviChannel *c = (KviChannel*)m_pKviWindow;
+ QString nick;
+ if(pParams->firstAsString(nick))
+ c->userListView()->select(nick);
+ }
+ }
+ }
+ } else bTrigger = true;
+ break;
+ case KVI_WINDOW_TYPE_QUERY:
+ if(KviQString::equalCI(((KviQuery *)m_pKviWindow)->windowName(),linkText))
+ {
+ if(e->button() & Qt::RightButton)
+ KVS_TRIGGER_EVENT(KviEvent_OnQueryNickPopupRequest,m_pKviWindow,pParams);
+ if(e->button() & Qt::LeftButton)
+ KVS_TRIGGER_EVENT(KviEvent_OnQueryNickLinkClick,m_pKviWindow,pParams);
+ } else bTrigger = true;
+ break;
+ default:
+ bTrigger = true;
+ break;
+ }
+ if(bTrigger)
+ {
+ if(console())
+ {
+ if(e->button() & Qt::RightButton)
+ KVS_TRIGGER_EVENT(KviEvent_OnNickLinkPopupRequest,m_pKviWindow,pParams);
+ if(e->button() & Qt::LeftButton)
+ KVS_TRIGGER_EVENT(KviEvent_OnConsoleNickLinkClick,m_pKviWindow,pParams);
+ } else emit rightClicked();
+ }
+ }
+ break;
+ case 'h':
+ if(e->button() & Qt::RightButton)
+ KVS_TRIGGER_EVENT(KviEvent_OnHostLinkPopupRequest,m_pKviWindow,pParams);
+ if(e->button() & Qt::LeftButton)
+ KVS_TRIGGER_EVENT(KviEvent_OnHostLinkClick,m_pKviWindow,pParams);
+ break;
+ case 'u':
+ if(e->button() & Qt::RightButton)
+ KVS_TRIGGER_EVENT(KviEvent_OnUrlLinkPopupRequest,m_pKviWindow,pParams);
+ if(e->button() & Qt::LeftButton)
+ KVS_TRIGGER_EVENT(KviEvent_OnUrlLinkClick,m_pKviWindow,pParams);
+ break;
+ case 'c':
+ if(e->button() & Qt::RightButton)
+ KVS_TRIGGER_EVENT(KviEvent_OnChannelLinkPopupRequest,m_pKviWindow,pParams);
+ if(e->button() & Qt::LeftButton)
+ KVS_TRIGGER_EVENT(KviEvent_OnChannelLinkClick,m_pKviWindow,pParams);
+ break;
+ case 's':
+ if(e->button() & Qt::RightButton)
+ KVS_TRIGGER_EVENT(KviEvent_OnServerLinkPopupRequest,m_pKviWindow,pParams);
+ if(e->button() & Qt::LeftButton)
+ KVS_TRIGGER_EVENT(KviEvent_OnServerLinkClick,m_pKviWindow,pParams);
+ break;
+ default:
+ {
+ if(e->button() & Qt::RightButton)
+ {
+ QString tmp;
+ getLinkEscapeCommand(tmp,linkCmd,"[!rbt]");
+ if(!tmp.isEmpty())
+ {
+ KviKvsScript::run(tmp,m_pKviWindow,pParams);
+ } else emit rightClicked();
+ }
+ }
+ break;
+ }
+ } else if(e->button() & Qt::RightButton) emit rightClicked();
+
+ } else if((e->button() & Qt::MidButton) || ((e->button() & Qt::RightButton) && (e->state() & Qt::ControlButton)))
+ {
+ QString tmp;
+ getLinkEscapeCommand(tmp,linkCmd,QString("[!mbt]"));
+ if(!tmp.isEmpty())
+ {
+ KviKvsScript::run(tmp,m_pKviWindow,pParams);
+ } else {
+ KVS_TRIGGER_EVENT_0(KviEvent_OnWindowPopupRequest,m_pKviWindow);
+ }
+ }
+ delete pParams;
+}
+
+//================ mouseReleaseEvent ===============//
+
+void KviIrcView::mouseReleaseEvent(QMouseEvent *)
+{
+ if(m_iSelectTimer)
+ {
+ killTimer(m_iSelectTimer);
+ m_iSelectTimer = 0;
+ QClipboard * c = QApplication::clipboard();
+ if(c)
+ {
+ // copy to both!
+ c->setText(m_szLastSelection,QClipboard::Clipboard);
+ if(c->supportsSelection())
+ c->setText(m_szLastSelection,QClipboard::Selection);
+ }
+ }
+
+ if(m_bMouseIsDown)
+ {
+ m_bMouseIsDown = false;
+ m_bShiftPressed = false;
+ // Insert the lines blocked while selecting
+ while(KviIrcViewLine * l = m_pMessagesStoppedWhileSelecting->first())
+ {
+ m_pMessagesStoppedWhileSelecting->removeFirst();
+ appendLine(l,false);
+ }
+ repaint();
+ }
+}
+
+// FIXME: #warning "The tooltip timeout should be small, because the view scrolls!"
+
+void KviIrcView::mouseMoveEvent(QMouseEvent *e)
+{
+// debug("Pos : %d,%d",e->pos().x(),e->pos().y());
+ if(m_bMouseIsDown && (e->state() & Qt::LeftButton)) // m_bMouseIsDown MUST BE true...(otherwise the mouse entered the window with the button pressed ?)
+ {
+
+ if(m_iSelectTimer == 0)m_iSelectTimer = startTimer(KVI_IRCVIEW_SELECT_REPAINT_INTERVAL);
+
+ /*if(m_iMouseTimer)
+ {
+ killTimer(m_iMouseTimer);
+ m_iMouseTimer=0;
+ mouseRealPressEvent(m_pLastEvent);
+ delete m_pLastEvent;
+ m_pLastEvent=0;
+ }*/
+ } else {
+ if(m_iSelectTimer)
+ {
+ killTimer(m_iSelectTimer);
+ m_iSelectTimer = 0;
+ }
+
+ int yPos = e->pos().y();
+ int rectTop;
+ int rectHeight;
+ QRect rctLink;
+ KviIrcViewWrappedBlock * newLinkUnderMouse = getLinkUnderMouse(e->pos().x(),yPos,&rctLink);
+
+ rectTop = rctLink.y();
+ rectHeight = rctLink.height();
+
+ if(newLinkUnderMouse != m_pLastLinkUnderMouse)
+ {
+ //abortTip();
+ //m_iTipTimer = startTimer(KVI_OPTION_UINT(KviOption_uintIrcViewToolTipTimeoutInMsec));
+ m_pLastLinkUnderMouse = newLinkUnderMouse;
+ if(m_pLastLinkUnderMouse)
+ {
+ setCursor(Qt::PointingHandCursor);
+ if(rectTop < 0)rectTop = 0;
+ if((rectTop + rectHeight) > height())rectHeight = height() - rectTop;
+
+ if(m_iLastLinkRectHeight > -1)
+ {
+ // prev link
+ int top = (rectTop < m_iLastLinkRectTop) ? rectTop : m_iLastLinkRectTop;
+ int lastBottom = m_iLastLinkRectTop + m_iLastLinkRectHeight;
+ int thisBottom = rectTop + rectHeight;
+ QRect r(0,top,width(),((lastBottom > thisBottom) ? lastBottom : thisBottom) - top);
+ repaint(r);
+ } else {
+ // no prev link
+ QRect r(0,rectTop,width(),rectHeight);
+ repaint(r);
+ }
+ m_iLastLinkRectTop = rectTop;
+ m_iLastLinkRectHeight = rectHeight;
+ } else {
+ setCursor(Qt::ArrowCursor);
+ if(m_iLastLinkRectHeight > -1)
+ {
+ // There was a previous bottom rect
+ QRect r(0,m_iLastLinkRectTop,width(),m_iLastLinkRectHeight);
+ repaint(r);
+ m_iLastLinkRectTop = -1;
+ m_iLastLinkRectHeight = -1;
+ }
+ }
+
+ }
+ }
+}
+
+KviConsole * KviIrcView::console()
+{
+ return m_pKviWindow->console();
+}
+
+void KviIrcView::doLinkToolTip(const QRect &rct,QString &linkCmd,QString &linkText)
+{
+ if(linkCmd.isEmpty())return;
+
+ QString szCmd(linkCmd);
+ szCmd.remove(0,1);
+
+ QString tip;
+
+ switch(linkCmd[0].unicode())
+ {
+ case 'u': // url link
+ {
+ tip = "<table width=\"100%\">" \
+ "<tr><td valign=\"center\"><img src=\"url_icon\"> <u><font color=\"blue\"><nowrap>";
+ if(linkText.length() > 50)
+ {
+ tip += linkText.left(47);
+ tip += "...";
+ } else {
+ tip += linkText;
+ }
+ tip+="</nowrap></font></u></td></tr><tr><td>";
+ QMimeSourceFactory::defaultFactory()->setPixmap("url_icon",*(g_pIconManager->getSmallIcon(KVI_SMALLICON_URL)));
+ tip += __tr2qs("Double-click to open this link");
+ tip += "</td></tr></table>";
+ }
+ break;
+ case 'h': // host link
+ {
+ tip = "<table width=\"100%\">" \
+ "<tr><td valign=\"center\"><img src=\"host_icon\"> <u><font color=\"blue\"><nowrap>";
+ if(linkText.length() > 50)
+ {
+ tip += linkText.left(47);
+ tip += "...";
+ } else {
+ tip += linkText;
+ }
+ tip+="</nowrap></font></u></td></tr><tr><td>";
+ QMimeSourceFactory::defaultFactory()->setPixmap("host_icon",*(g_pIconManager->getSmallIcon(KVI_SMALLICON_SERVER)));
+
+ if(linkText.find('*') != -1)
+ {
+ if(linkText.length() > 1)tip += __tr2qs("Unable to look it up hostname: Hostname appears to be masked");
+ else tip += __tr2qs("Unable to look it up hostname: Unknown host");
+ } else {
+ tip += __tr2qs("Double-click to look up this hostname<br>Right-click to view other options");
+ }
+ tip += "</td></tr></table>";
+ }
+ break;
+ case 's': // server link
+ {
+ // FIXME: #warning "Spit out some server info...hub ?...registered ?"
+
+ tip = "<table width=\"100%\">" \
+ "<tr><td valign=\"center\"><img src=\"server_icon\"> <u><font color=\"blue\"><nowrap>";
+ QMimeSourceFactory::defaultFactory()->setPixmap("server_icon",*(g_pIconManager->getSmallIcon(KVI_SMALLICON_IRC)));
+ if(linkText.length() > 50)
+ {
+ tip += linkText.left(47);
+ tip += "...";
+ } else {
+ tip += linkText;
+ }
+ tip+="</nowrap></font></u></td></tr><tr><td>";
+
+ if(linkText.find('*') != -1)
+ {
+ if(linkText.length() > 1)tip += __tr2qs("Server appears to be a network hub<br>");
+ else tip += __tr2qs("Unknown server<br>"); // might happen...
+ }
+
+ tip.append(__tr2qs("Double-click to read the MOTD<br>Right-click to view other options"));
+ tip += "</td></tr></table>";
+ }
+ break;
+ case 'm': // mode link
+ {
+ if((linkCmd.length() > 2) && (m_pKviWindow->type() == KVI_WINDOW_TYPE_CHANNEL))
+ {
+ if(((KviChannel *)m_pKviWindow)->isMeOp())
+ {
+ QChar plmn = linkCmd[1];
+ if((plmn.unicode() == '+') || (plmn.unicode() == '-'))
+ {
+ tip = __tr2qs("Double-click to set<br>");
+ QChar flag = linkCmd[2];
+ switch(flag.unicode())
+ {
+ case 'o':
+ case 'v':
+ // We can do nothing here...
+ tip = "";
+ break;
+ case 'b':
+ case 'I':
+ case 'e':
+ case 'k':
+ KviQString::appendFormatted(tip,QString("<b>mode %Q %c%c %Q</b>"),&(m_pKviWindow->windowName()),plmn.latin1(),flag.latin1(),&linkText);
+ break;
+ default:
+ KviQString::appendFormatted(tip,QString("<b>mode %Q %c%c</b>"),&(m_pKviWindow->windowName()),plmn.latin1(),flag.latin1());
+ break;
+ }
+ }
+ } else {
+ // I'm not op...no way
+ tip = __tr2qs("You're not an operator: You may not change channel modes");
+ }
+ }
+ }
+ break;
+ case 'n': // nick link
+ {
+ if(console())
+ {
+ if(console()->connection())
+ {
+ KviIrcUserEntry * e = console()->connection()->userDataBase()->find(linkText);
+ if(e)
+ {
+ QString buffer;
+ console()->getUserTipText(linkText,e,buffer);
+ tip = buffer;
+ } else KviQString::sprintf(tip,__tr2qs("Nothing known about %Q"),&linkText);
+ } else KviQString::sprintf(tip,__tr2qs("Nothing known about %Q (no connection)"),&linkText);
+ }
+ }
+ break;
+ case 'c': // channel link
+ {
+ if(console() && console()->connection())
+ {
+ QString szChan = linkText;
+ QString buf;
+ tip = "<img src=\"chan_icon\"> ";
+ QMimeSourceFactory::defaultFactory()->setPixmap("chan_icon",*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CHANNEL)));
+
+ if(szCmd.length()>0) szChan=szCmd;
+ KviChannel * c = console()->connection()->findChannel(szChan);
+ QString szUrl;
+ if(c)
+ {
+ QString chanMode;
+ c->getChannelModeString(chanMode);
+ QString topic = KviMircCntrl::stripControlBytes(c->topicWidget()->topic());
+ topic.replace("<","&lt;");
+ topic.replace(">","&gt;");
+ KviIrcUrl::join(szUrl,console()->connection()->target()->server());
+ szUrl.append(szChan);
+ KviQString::sprintf(buf,__tr2qs("<b>%Q</b> (<u><font color=\"blue\"><nowrap>"
+ "%Q</nowrap></font></u>): <br><nowrap>+%Q (%u users)<hr>%Q</nowrap>"),&szChan,&szUrl,&chanMode,
+ c->count(),&topic);
+ } else {
+ KviIrcUrl::join(szUrl,console()->connection()->target()->server());
+ szUrl.append(szChan);
+ KviQString::sprintf(buf,__tr2qs("<b>%Q</b> (<u><font color=\"blue\"><nowrap>"
+ "%Q</nowrap></font></u>)<hr>Double-click to join %Q<br>Right click to view other options"),&szChan,&szUrl,&szChan);
+ }
+
+ tip += buf;
+ }
+ }
+ break;
+ default:
+ {
+ QString dbl,rbt,txt,mbt;
+ getLinkEscapeCommand(dbl,linkCmd,"[!dbl]");
+ getLinkEscapeCommand(rbt,linkCmd,"[!rbt]");
+ getLinkEscapeCommand(txt,linkCmd,"[!txt]");
+ getLinkEscapeCommand(mbt,linkCmd,"[!mbt]");
+
+ if(!txt.isEmpty())tip = txt;
+ if(tip.isEmpty() && (!dbl.isEmpty()))
+ {
+ if(!tip.isEmpty())tip.append("<hr>");
+ KviQString::appendFormatted(tip,__tr2qs("<b>Double-click:</b><br>%Q"),&dbl);
+ }
+ if(tip.isEmpty() && (!mbt.isEmpty()))
+ {
+ if(!tip.isEmpty())tip.append("<hr>");
+ KviQString::appendFormatted(tip,__tr2qs("<b>Middle-click:</b><br>%Q"),&mbt);
+ }
+ if(tip.isEmpty() && (!rbt.isEmpty()))
+ {
+ if(!tip.isEmpty())tip.append("<hr>");
+ KviQString::appendFormatted(tip,__tr2qs("<b>Right-click:</b><br>%Q"),&rbt);
+ }
+ }
+ break;
+ }
+
+ if(tip.isEmpty())return;
+
+ m_pToolTip->doTip(rct,tip);
+}
+void KviIrcView::leaveEvent ( QEvent * )
+{
+ if(m_pLastLinkUnderMouse)
+ {
+ m_pLastLinkUnderMouse=0;
+ update();
+ }
+}
+void KviIrcView::timerEvent(QTimerEvent *e)
+{
+ m_mouseCurrentPos = mapFromGlobal(QCursor::pos());
+
+ if(e->timerId() == m_iSelectTimer)
+ {
+ calculateSelectionBounds();
+ repaint();
+ }
+ if(e->timerId() == m_iMouseTimer)
+ {
+ killTimer(m_iMouseTimer);
+ m_iMouseTimer=0;
+ mouseRealPressEvent(m_pLastEvent);
+ delete m_pLastEvent;
+ m_pLastEvent=0;
+ }
+ if(e->timerId() == m_iFlushTimer)
+ {
+ flushLog();
+ }
+}
+
+void KviIrcView::keyPressEvent(QKeyEvent *e)
+{
+ switch(e->key())
+ {
+ case Qt::Key_PageUp:
+ prevPage();
+ e->accept();
+ break;
+ case Qt::Key_PageDown:
+ nextPage();
+ e->accept();
+ break;
+ default:
+ e->ignore();
+ }
+}
+
+void KviIrcView::maybeTip(const QPoint &pnt)
+{
+ QString linkCmd;
+ QString linkText;
+
+ QRect rctLink;
+
+ KviIrcViewWrappedBlock * linkUnderMouse = getLinkUnderMouse(pnt.x(),pnt.y(),&rctLink,&linkCmd,&linkText);
+
+ if((linkUnderMouse == m_pLastLinkUnderMouse) && linkUnderMouse)doLinkToolTip(rctLink,linkCmd,linkText);
+ else m_pLastLinkUnderMouse = 0; //
+}
+
+#include "kvi_ircview.moc"
diff --git a/src/kvirc/ui/kvi_ircview.h b/src/kvirc/ui/kvi_ircview.h
new file mode 100644
index 00000000..62ee3e75
--- /dev/null
+++ b/src/kvirc/ui/kvi_ircview.h
@@ -0,0 +1,252 @@
+#ifndef _KVI_IRCVIEW_H_
+#define _KVI_IRCVIEW_H_
+//=========================================================================================================
+//
+// File : kvi_ircview.h
+// Creation date : Fri Mar 19 1999 05:39:01 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=========================================================================================================
+
+#include "kvi_settings.h"
+#include "kvi_string.h"
+#include "kvi_pointerlist.h"
+
+#include <qwidget.h>
+#include <qpixmap.h> // needed
+
+class QScrollBar;
+class QLineEdit;
+class QFile;
+class QToolButton;
+class QFontMetrics;
+class KviTalPopupMenu;
+
+class KviWindow;
+class KviFrame;
+class KviConsole;
+class KviIrcViewToolWidget;
+class KviIrcViewToolTip;
+
+typedef struct _KviIrcViewLineChunk KviIrcViewLineChunk;
+typedef struct _KviIrcViewWrappedBlock KviIrcViewWrappedBlock;
+typedef struct _KviIrcViewLine KviIrcViewLine;
+typedef struct _KviIrcViewWrappedBlockSelectionInfoTag KviIrcViewWrappedBlockSelectionInfo;
+
+#define KVI_IRCVIEW_INVALID_LINE_MARK_INDEX 0xffffffff
+
+class KVIRC_API KviIrcView : public QWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(int TransparencyCapable READ dummyRead)
+ // we cannot #ifdef due to a bug in moc
+ Q_PROPERTY(bool usePaintOnScreen READ getPaintOnScreen WRITE setPaintOnScreen)
+public:
+ friend class KviIrcViewToolTip;
+ friend class KviIrcViewToolWidget;
+public:
+ KviIrcView(QWidget *parent,KviFrame *pFrm,KviWindow *pWnd);
+ ~KviIrcView();
+public:
+ int dummyRead() const { return 0; };
+#ifdef COMPILE_USE_QT4
+ bool getPaintOnScreen() const { return testAttribute(Qt::WA_PaintOnScreen);};
+ void setPaintOnScreen(bool bFlag){setAttribute(Qt::WA_PaintOnScreen,bFlag);} ;
+#else
+ // hack to fix moc bug on win qt4
+ bool getPaintOnScreen() const { return 0;};
+ void setPaintOnScreen(bool bFlag){} ;
+#endif
+private:
+// QDate m_lastLogDay;
+ int m_iFlushTimer;
+ KviIrcViewLine * m_pFirstLine;
+ KviIrcViewLine * m_pCurLine; // Bottom line in the view
+ KviIrcViewLine * m_pLastLine;
+ KviIrcViewLine * m_pCursorLine;
+ unsigned int m_uLineMarkLineIndex;
+
+ // Highliting of links
+ KviIrcViewWrappedBlock * m_pLastLinkUnderMouse;
+ int m_iLastLinkRectTop;
+ int m_iLastLinkRectHeight;
+
+ int m_iNumLines;
+ int m_iMaxLines;
+
+ unsigned int m_uNextLineIndex;
+
+ QPixmap * m_pPrivateBackgroundPixmap;
+ QScrollBar * m_pScrollBar;
+ QToolButton * m_pToolsButton;
+ KviTalPopupMenu * m_pToolsPopup;
+
+ KviIrcViewToolWidget * m_pToolWidget;
+
+ int m_iLastScrollBarValue;
+
+ // Font related stuff (needs precalculation!)
+ int m_iFontLineSpacing;
+ int m_iFontLineWidth;
+ int m_iFontDescent;
+ int m_iFontCharacterWidth[256]; //1024 bytes fixed
+
+ int m_iWrapMargin;
+ int m_iMinimumPaintWidth;
+ int m_iRelativePixmapY;
+ int m_iIconWidth;
+ int m_iIconSideSpacing;
+
+ QPoint m_mousePressPos;
+ QPoint m_mouseCurrentPos;
+
+ // Selection
+ int m_iSelectionBegin;
+ int m_iSelectionTop;
+ int m_iSelectionEnd;
+ int m_iSelectionBottom;
+ int m_iSelectionLeft;
+ int m_iSelectionRight;
+
+ bool m_bMouseIsDown;
+ bool m_bShiftPressed;
+
+ bool m_bSkipScrollBarRepaint;
+ int m_iSelectTimer;
+ int m_iMouseTimer;
+ //int m_iTipTimer;
+ QString m_szLastSelection;
+ QString m_szLastSelectionLine;
+ KviWindow * m_pKviWindow;
+ KviIrcViewWrappedBlockSelectionInfo * m_pWrappedBlockSelectionInfo;
+ QFile * m_pLogFile;
+ KviFrame * m_pFrm;
+ bool m_bAcceptDrops;
+ int m_iUnprocessedPaintEventRequests;
+ bool m_bPostedPaintEventPending;
+ KviPointerList<KviIrcViewLine> * m_pMessagesStoppedWhileSelecting;
+ KviIrcView * m_pMasterView;
+ QFontMetrics * m_pFm; // assume this valid only inside a paint event (may be 0 in other circumstances)
+
+ QMouseEvent * m_pLastEvent;
+
+ KviIrcViewToolTip * m_pToolTip;
+ bool m_bHaveUnreadedHighlightedMessages;
+ bool m_bHaveUnreadedMessages;
+public:
+ void checkLogDate();
+ void clearUnreaded();
+ void applyOptions();
+ void enableDnd(bool bEnable);
+ bool haveUnreadedMessages() { return m_bHaveUnreadedMessages; };
+ bool haveUnreadedHighlightedMessages() { return m_bHaveUnreadedHighlightedMessages; };
+ enum AppendTextFlags { NoRepaint = 1, NoTimestamp = 2, SetLineMark = 4 };
+ void appendText(int msg_type,const kvi_wchar_t *data_ptr,int iFlags = 0);
+ void clearLineMark(bool bRepaint=false);
+ bool hasLineMark(){ return m_uLineMarkLineIndex != KVI_IRCVIEW_INVALID_LINE_MARK_INDEX; };
+ void removeHeadLine(bool bRepaint=false);
+ void emptyBuffer(bool bRepaint=true);
+ void getTextBuffer(QString &buffer);
+ void setMaxBufferSize(int maxBufSize,bool bRepaint=true);
+ int maxBufferSize(){ return m_iMaxLines; }; //Never used ?
+ bool saveBuffer(const char *filename);
+ void findNext(const QString& szText,bool bCaseS = false,bool bRegExp = false,bool bExtended = false);
+ void findPrev(const QString& szText,bool bCaseS = false,bool bRegExp = false,bool bExtended = false);
+ KviWindow * parentKviWindow(){ return m_pKviWindow; };
+ KviConsole * console();
+ // A null pixmap passed here unsets the private backgrdound.
+ void setPrivateBackgroundPixmap(const QPixmap &pixmap,bool bRepaint=true);
+ bool hasPrivateBackgroundPixmap(){ return (m_pPrivateBackgroundPixmap != 0); };
+
+ //==============================================================================================
+ // Logging
+ // Stops previous logging session too...
+ bool startLogging(const QString& fname = QString::null,bool bPrependCurBuffer = false);
+ void stopLogging();
+ bool isLogging(){ return (m_pLogFile != 0); };
+ void getLogFileName(KviStr &buffer);
+ void getLogFileName(QString &buffer);
+ //void add2Log(const char *buffer,int buf_len=-1);
+ void add2Log(const QString &szBuffer,int iMsgType=0);
+
+ //==============================================================================================
+ // Channel view splitting
+ void setMasterView(KviIrcView * v);
+ void splitMessagesTo(KviIrcView * v);
+ void joinMessagesFrom(KviIrcView * v);
+ void appendMessagesFrom(KviIrcView * v);
+
+ void prevLine();
+ void nextLine();
+ void nextPage();
+ void prevPage();
+ virtual QSize sizeHint() const;
+ const QString & lastLineOfText();
+ const QString & lastMessageText();
+ virtual void setFont(const QFont &f);
+public slots:
+ void flushLog();
+ void showToolsPopup();
+ void clearBuffer();
+ void toggleToolWidget();
+ void increaseFontSize();
+ void decreaseFontSize();
+ void chooseFont();
+ void chooseBackground();
+ void resetBackground();
+signals:
+ void rightClicked();
+ void dndEntered();
+ void fileDropped(const char *);
+private:
+ void setCursorLine(KviIrcViewLine * l);
+ KviIrcViewLine * getVisibleLineAt(int xPos,int yPos);
+ void getLinkEscapeCommand(QString &buffer,const QString &escape_cmd,const QString &escape_label);
+ void appendLine(KviIrcViewLine *ptr,bool bRepaint);
+ void postUpdateEvent();
+ void fastScroll(int lines = 1);
+ const kvi_wchar_t * getTextLine(int msg_type,const kvi_wchar_t * data_ptr,KviIrcViewLine *line_ptr,bool bEnableTimeStamp = true);
+ void calculateLineWraps(KviIrcViewLine *ptr,int maxWidth);
+ void recalcFontVariables(const QFontMetrics &fm,const QFontInfo &fi);
+ bool checkSelectionBlock(KviIrcViewLine * line,int left,int bottom,int bufIndex);
+ void calculateSelectionBounds();
+ KviIrcViewWrappedBlock * getLinkUnderMouse(int xPos,int yPos,QRect * pRect = 0,QString * linkCmd = 0,QString * linkText = 0);
+ void doLinkToolTip(const QRect &rct,QString &linkCmd,QString &linkText);
+protected:
+ virtual void paintEvent(QPaintEvent *);
+ virtual void resizeEvent(QResizeEvent *);
+ virtual void mousePressEvent(QMouseEvent *e);
+ virtual void mouseRealPressEvent(QMouseEvent *e);
+ virtual void mouseReleaseEvent(QMouseEvent *);
+ virtual void mouseDoubleClickEvent(QMouseEvent *e);
+ virtual void mouseMoveEvent(QMouseEvent *e);
+ virtual void timerEvent(QTimerEvent *e);
+ virtual void dragEnterEvent(QDragEnterEvent *e);
+ virtual void dropEvent(QDropEvent *e);
+ virtual bool event(QEvent *e);
+ virtual void wheelEvent(QWheelEvent *e);
+ virtual void keyPressEvent(QKeyEvent *e);
+ void maybeTip(const QPoint &pnt);
+ virtual void leaveEvent ( QEvent * );
+protected slots:
+ virtual void scrollBarPositionChanged(int newValue);
+ void masterDead();
+};
+
+#endif //_KVI_IRCVIEW_H_
diff --git a/src/kvirc/ui/kvi_ircviewprivate.h b/src/kvirc/ui/kvi_ircviewprivate.h
new file mode 100644
index 00000000..0a2dea20
--- /dev/null
+++ b/src/kvirc/ui/kvi_ircviewprivate.h
@@ -0,0 +1,164 @@
+#ifndef _KVI_IRCVIEWPRIVATE_H_
+#define _KVI_IRCVIEWPRIVATE_H_
+//=========================================================================================================
+//
+// File : kvi_ircviewprivate.h
+// Creation date : Sat Oct 9 2004 16:29:01 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=========================================================================================================
+
+#include "kvi_settings.h"
+#include <qstring.h>
+
+//=========================================================================================================
+// Internal data structures
+//=========================================================================================================
+
+// Force the structs to be packed...
+#ifdef COMPILE_ON_WINDOWS
+ #pragma pack(push,old_packing,1)
+ #define _KVI_PACKED
+#else //!COMPILE_ON_WIDNOWS
+ // this works only on gcc
+ #ifdef __GNUC__
+ #define _KVI_PACKED __attribute__((__packed__))
+ #else
+ #define _KVI_PACKED
+ #endif
+#endif //!COMPILE_ON_WINDOWS
+
+//
+// The LineChunk structure contains informations about
+// an attribute change, an icon or a link
+//
+// type can be one of:
+//
+// KVI_TEXT_ICON:
+// the uIconId member is the icon to be shown
+// szPayload contains the text that triggered this icon was triggered by
+// KVI_TEXT_UNICON:
+// the text block after an icon
+// KVI_TEXT_ESCAPE:
+// szPayload contains the encoded escape command
+// colors.fore contains the new text color
+// KVI_TEXT_UNESCAPE:
+// the text block after an escape
+// KVI_TEXT_COLOR:
+// the colors.back and colors.fore members indicate the color change
+// KVI_TEXT_BOLD:
+// toggles the bold flag
+// KVI_TEXT_UNDERLINE:
+// toggles the underline flag
+// KVI_TEXT_REVERSE:
+// inverts the current fore and back colors
+// KVI_TEXT_RESET:
+// resets the color, bold and underline flags
+//
+
+typedef struct _KviIrcViewLineChunk
+{
+ unsigned char type; // chunk type
+ int iTextStart; // index in the szText string of the beginning of the block
+ int iTextLen; // length in chars of the block (excluding the terminator)
+ kvi_wchar_t * szPayload; // KVI_TEXT_ESCAPE attribute command buffer and KVI_TEXT_ICON icon name (non zeroed for other attributes!!!)
+ kvi_wchar_t * szSmileId;
+ struct {
+ unsigned char back; // optional background color for KVI_TEXT_COLOR attribute
+ unsigned char fore; // optional foreground color for KVI_TEXT_COLOR attribute (used also for KVI_TEXT_ESCAPE!!!)
+ } _KVI_PACKED colors; // anonymous
+// QColor customBack;
+ QColor customFore;
+} /*_KVI_PACKED*/ KviIrcViewLineChunk;
+
+//
+// The wrapped paintable data block
+//
+
+typedef struct _KviIrcViewWrappedBlock
+{
+ KviIrcViewLineChunk * pChunk; // pointer to real line chunk or 0 for word wraps
+ int block_start; // this is generally different than pAttribute->block_idx!
+ int block_len; // length if the block in characters
+ int block_width; // width of the block in pixels
+} _KVI_PACKED KviIrcViewWrappedBlock;
+
+
+typedef struct _KviIrcViewLine
+{
+ // this is a text line in the IrcView's memory
+ unsigned int uIndex; // index of the text line (needed for find and splitting)
+ QString szText; // data string without color codes nor escapes...
+ int iMsgType; // type of the line (defines icon and colors)
+
+ // At line instert time the szData text is splitted in parts which
+ // signal attribute changes (or icons)
+ unsigned int uChunkCount; // number of allocated chunks
+ KviIrcViewLineChunk * pChunks; // pointer to the allocated structures
+
+ // At paint time the data is re-splitted in drawable chunks which
+ // are either real data chunks or line wraps.
+ // The algorightm that does this is lazy and computes it
+ // only once for a given widget width (iMaxLineWidth)
+ unsigned int uLineWraps; // number of line wraps (lines - 1)
+ int iMaxLineWidth; // width that the blocks were calculated for (lazy calculation)
+ int iBlockCount; // number of allocated paintable blocks
+ KviIrcViewWrappedBlock * pBlocks; // pointer to the re-splitted paintable blocks
+
+ // next and previous line
+ struct _KviIrcViewLine * pPrev;
+ struct _KviIrcViewLine * pNext;
+} KviIrcViewLine;
+
+typedef struct _KviIrcViewWrappedBlockSelectionInfoTag
+{
+ int selection_type;
+ /*struct {
+ int length;
+ int width;
+ } part[3];*/
+ int part_1_length;
+ int part_1_width;
+ int part_2_length;
+ int part_2_width;
+ int part_3_length;
+ int part_3_width;
+} KviIrcViewWrappedBlockSelectionInfo;
+
+#ifdef COMPILE_ON_WINDOWS
+ #pragma pack(pop,old_packing)
+#else //!COMPILE_ON_WINDOWS
+ #undef _KVI_PACKED
+#endif //!COMPILE_ON_WINDOWS
+
+//=========================================================================================================
+// Screen layout
+//=========================================================================================================
+
+//FIRST LINE (prev_line = 0) <---m_pFirstLine
+//LINE
+//--------------------SCREEN--
+//LINE
+//LINE
+//LINE
+//LINE <-------------------------m_pCurLine
+//--------------------SCREEN--
+//LAST LINE (next_line = 0) <----m_pLastLine
+
+#endif //!_KVI_IRCVIEWPRIVATE_H_
diff --git a/src/kvirc/ui/kvi_ircviewtools.cpp b/src/kvirc/ui/kvi_ircviewtools.cpp
new file mode 100644
index 00000000..ea473107
--- /dev/null
+++ b/src/kvirc/ui/kvi_ircviewtools.cpp
@@ -0,0 +1,348 @@
+//=============================================================================
+//
+// File : kvi_ircviewtools.cpp
+// Creation date : Sat Oct 9 2004 16:03:01 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_ircviewtools.h"
+#include "kvi_ircview.h"
+#include "kvi_styled_controls.h"
+#include "kvi_iconmanager.h"
+#include "kvi_options.h"
+#include "kvi_locale.h"
+#include "kvi_malloc.h"
+#include "kvi_msgbox.h"
+#include "kvi_filedialog.h"
+#include "kvi_app.h"
+#include "kvi_memmove.h"
+
+#include <qtoolbutton.h>
+#include <qtabwidget.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qcheckbox.h>
+#include <qpushbutton.h>
+#ifdef COMPILE_USE_QT4
+ #include <q3header.h>
+#else
+ #include <qheader.h>
+#endif
+#include <qlineedit.h>
+#include <qcursor.h>
+#include "kvi_accel.h"
+#include <qevent.h>
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Tool widget implementation
+//
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+KviIrcMessageCheckListItem::KviIrcMessageCheckListItem(KviTalListView * par,KviIrcViewToolWidget * w,int id)
+: KviTalCheckListItem(par,QString::null,KviTalCheckListItem::CheckBox)
+{
+ m_iId = id;
+ m_pToolWidget = 0;
+ setPixmap(0,*(g_pIconManager->getSmallIcon(KVI_OPTION_MSGTYPE(id).pixId())));
+ setOn(true);
+ m_pToolWidget = w;
+}
+
+KviIrcMessageCheckListItem::~KviIrcMessageCheckListItem()
+{
+}
+
+void KviIrcMessageCheckListItem::stateChange(bool bOn)
+{
+ KviTalCheckListItem::stateChange(bOn);
+ if(!m_pToolWidget)return;
+ m_pToolWidget->forceRepaint();
+}
+
+
+
+KviIrcViewToolWidget::KviIrcViewToolWidget(KviIrcView * par)
+: QFrame(par)
+{
+ m_pIrcView = par;
+ setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
+
+ QGridLayout * gl = new QGridLayout(this,2,2,4,2);
+
+ QLabel * l = new QLabel(__tr2qs("<b><font color=\"#EAEAEA\" size=\"-1\">Find Text</font></b>"),this);
+ l->setMaximumHeight(14);
+ l->setBackgroundColor(Qt::black);
+ gl->addWidget(l,0,0);
+
+ QToolButton *tb = new QToolButton(Qt::DownArrow,this,"down_arrow");
+ tb->setFixedSize(14,14);
+ tb->setAutoRepeat(false);
+ connect(tb,SIGNAL(clicked()),m_pIrcView,SLOT(toggleToolWidget()));
+ gl->addWidget(tb,0,1);
+
+
+ QTabWidget * tw = new QTabWidget(this);
+
+
+
+ // Find tab
+ QWidget * w = new QWidget(tw);
+
+ QGridLayout * g = new QGridLayout(w,6,2,2,1);
+
+ m_pStringToFind = new QLineEdit(w);
+ g->addMultiCellWidget(m_pStringToFind,0,0,0,2);
+ connect(m_pStringToFind,SIGNAL(returnPressed()),this,SLOT(findNext()));
+
+ m_pRegExp = new KviStyledCheckBox(__tr2qs("&Regular expression"),w);
+ g->addMultiCellWidget(m_pRegExp,1,1,0,2);
+
+ m_pExtendedRegExp = new KviStyledCheckBox(__tr2qs("E&xtended regexp."),w);
+ g->addMultiCellWidget(m_pExtendedRegExp,2,2,0,2);
+ m_pExtendedRegExp->setEnabled(false);
+ connect(m_pRegExp,SIGNAL(toggled(bool)),m_pExtendedRegExp,SLOT(setEnabled(bool)));
+
+ m_pCaseSensitive = new KviStyledCheckBox(__tr2qs("C&ase sensitive"),w);
+ g->addMultiCellWidget(m_pCaseSensitive,3,3,0,2);
+
+ QPushButton * pb = new QPushButton(__tr2qs("Find &Prev."),w);
+ connect(pb,SIGNAL(clicked()),this,SLOT(findPrev()));
+ g->addWidget(pb,4,0);
+
+ pb = new QPushButton(__tr2qs("&Find Next"),w);
+ pb->setDefault(true);
+ connect(pb,SIGNAL(clicked()),this,SLOT(findNext()));
+ g->addMultiCellWidget(pb,4,4,1,2);
+
+ m_pFindResult = new QLabel(w);
+ m_pFindResult->setFrameStyle(QFrame::Sunken | QFrame::StyledPanel);
+ g->addMultiCellWidget(m_pFindResult,5,5,0,2);
+
+ //g->setResizeMode(QGridLayout::Fixed);
+
+ tw->addTab(w,__tr2qs("Find"));
+
+ // Filter tab
+ QWidget * w1 = new QWidget(tw);
+
+ g = new QGridLayout(w1,5,2,2,1);
+
+ m_pFilterView = new KviTalListView(w1);
+ m_pFilterView->addColumn(__tr2qs("Type"));
+ m_pFilterView->header()->hide();
+ m_pFilterView->setMinimumSize(QSize(10,10));
+
+ g->addMultiCellWidget(m_pFilterView,0,4,0,0);
+
+
+ m_pFilterItems = (KviIrcMessageCheckListItem **)kvi_malloc(KVI_NUM_MSGTYPE_OPTIONS * sizeof(KviIrcMessageCheckListItem *));
+
+ for(int i=0;i<KVI_NUM_MSGTYPE_OPTIONS;i++)
+ {
+ m_pFilterItems[i] = new KviIrcMessageCheckListItem(m_pFilterView,this,i);
+ }
+
+ pb = new QPushButton(__tr2qs("Set &All"),w1);
+ connect(pb,SIGNAL(clicked()),this,SLOT(filterEnableAll()));
+ g->addWidget(pb,0,1);
+
+ pb = new QPushButton(__tr2qs("Set &None"),w1);
+ connect(pb,SIGNAL(clicked()),this,SLOT(filterEnableNone()));
+ g->addWidget(pb,1,1);
+
+ pb = new QPushButton(__tr2qs("&Load From..."),w1);
+ connect(pb,SIGNAL(clicked()),this,SLOT(filterLoad()));
+ g->addWidget(pb,2,1);
+
+ pb = new QPushButton(__tr2qs("&Save As..."),w1);
+ connect(pb,SIGNAL(clicked()),this,SLOT(filterSave()));
+ g->addWidget(pb,3,1);
+
+ tw->addTab(w1,__tr2qs("Filter"));
+
+ gl->addMultiCellWidget(tw,1,1,0,1);
+
+ gl->setResizeMode(QGridLayout::Fixed);
+ m_pStringToFind->setFocus();
+ tw->showPage(w);
+ KviAccel *a = new KviAccel( this );
+ a->connectItem( a->insertItem(Qt::Key_Escape), this,SLOT(close()) );
+}
+
+KviIrcViewToolWidget::~KviIrcViewToolWidget()
+{
+ kvi_free((void *)m_pFilterItems);
+}
+
+void KviIrcViewToolWidget::filterEnableAll()
+{
+ for(int i=0;i<KVI_NUM_MSGTYPE_OPTIONS;i++)
+ {
+ m_pFilterItems[i]->setToolWidget(0);
+ m_pFilterItems[i]->setOn(true);
+ m_pFilterItems[i]->setToolWidget(this);
+ }
+ forceRepaint();
+}
+
+void KviIrcViewToolWidget::filterEnableNone()
+{
+ for(int i=0;i<KVI_NUM_MSGTYPE_OPTIONS;i++)
+ {
+ m_pFilterItems[i]->setToolWidget(0);
+ m_pFilterItems[i]->setOn(false);
+ m_pFilterItems[i]->setToolWidget(this);
+ }
+ forceRepaint();
+}
+
+void KviIrcViewToolWidget::hideEvent ( QHideEvent * ){
+ m_pIrcView->toggleToolWidget();
+}
+
+void KviIrcViewToolWidget::closeEvent ( QCloseEvent * e ){
+ m_pIrcView->toggleToolWidget();
+}
+
+void KviIrcViewToolWidget::filterLoad()
+{
+ QString szFile;
+ QString szInit;
+ g_pApp->getLocalKvircDirectory(szInit,KviApp::Filters);
+
+ if(KviFileDialog::askForOpenFileName(szFile,__tr2qs("Select a Filter File"),szInit))
+ {
+ QFile f(szFile);
+ if(f.open(IO_ReadOnly))
+ {
+ char buffer[KVI_NUM_MSGTYPE_OPTIONS];
+ kvi_memset(buffer,0,KVI_NUM_MSGTYPE_OPTIONS);
+ f.readBlock(buffer,KVI_NUM_MSGTYPE_OPTIONS);
+ f.close();
+ for(int i=0;i<KVI_NUM_MSGTYPE_OPTIONS;i++)
+ {
+ m_pFilterItems[i]->setToolWidget(0);
+ m_pFilterItems[i]->setOn(buffer[i]);
+ m_pFilterItems[i]->setToolWidget(this);
+ }
+ forceRepaint();
+ } else {
+ KviMessageBox::warning(__tr2qs("Can't open the filter file %s for reading."),&szFile);
+ }
+ }
+}
+
+void KviIrcViewToolWidget::filterSave()
+{
+ QString szFile;
+ QString szInit;
+ g_pApp->getLocalKvircDirectory(szInit,KviApp::Filters,"filter.kvf");
+ if(KviFileDialog::askForSaveFileName(szFile,__tr2qs("Select a Name for the Filter File"),szInit,0,false,true))
+ {
+ QFile f(szFile);
+ if(f.open(IO_WriteOnly))
+ {
+ char buffer[KVI_NUM_MSGTYPE_OPTIONS];
+ for(int i=0;i<KVI_NUM_MSGTYPE_OPTIONS;i++)
+ {
+ buffer[i] = messageEnabled(i) ? 1 : 0;
+ }
+ if(f.writeBlock(buffer,KVI_NUM_MSGTYPE_OPTIONS) < KVI_NUM_MSGTYPE_OPTIONS)
+ KviMessageBox::warning(__tr2qs("Failed to write the filter file %Q (IO Error)"),&szFile);
+ f.close();
+ } else KviMessageBox::warning(__tr2qs("Can't open the filter file %Q for writing"),&szFile);
+ }
+}
+
+void KviIrcViewToolWidget::forceRepaint()
+{
+ #if defined(COMPILE_USE_QT4) && defined(COMPILE_ON_WINDOWS)
+ m_pIrcView->repaint();
+ #else
+ m_pIrcView->paintEvent(0);
+ #endif
+
+}
+
+void KviIrcViewToolWidget::setFindResult(const QString & text)
+{
+ m_pFindResult->setText(text);
+}
+
+void KviIrcViewToolWidget::findPrev()
+{
+ bool bRegExp = m_pRegExp->isChecked();
+ m_pIrcView->findPrev(m_pStringToFind->text(),m_pCaseSensitive->isChecked(),bRegExp,bRegExp && m_pExtendedRegExp->isChecked());
+}
+
+void KviIrcViewToolWidget::findNext()
+{
+ bool bRegExp = m_pRegExp->isChecked();
+ m_pIrcView->findNext(m_pStringToFind->text(),m_pCaseSensitive->isChecked(),bRegExp,bRegExp && m_pExtendedRegExp->isChecked());
+}
+
+
+void KviIrcViewToolWidget::mousePressEvent(QMouseEvent *e)
+{
+ m_pressPoint = e->pos();
+}
+
+void KviIrcViewToolWidget::mouseMoveEvent(QMouseEvent *)
+{
+ QPoint p=m_pIrcView->mapFromGlobal(QCursor::pos());
+ p-=m_pressPoint;
+ if(p.x() < 1)p.setX(1);
+ else {
+ int www = (m_pIrcView->width() - (m_pIrcView->m_pScrollBar->width() + 1));
+ if((p.x() + width()) > www)p.setX(www - width());
+ }
+ if(p.y() < 1)p.setY(1);
+ else {
+ int hhh = (m_pIrcView->height() - 1);
+ if((p.y() + height()) > hhh)p.setY(hhh - height());
+ }
+ move(p);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Link tip label implementation
+//
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+KviIrcViewToolTip::KviIrcViewToolTip(KviIrcView * pView)
+: KviTalToolTip(pView)
+{
+ m_pView = pView;
+}
+
+KviIrcViewToolTip::~KviIrcViewToolTip()
+{
+}
+
+void KviIrcViewToolTip::maybeTip(const QPoint &pnt)
+{
+ m_pView->maybeTip(pnt);
+}
+
diff --git a/src/kvirc/ui/kvi_ircviewtools.h b/src/kvirc/ui/kvi_ircviewtools.h
new file mode 100644
index 00000000..248c180d
--- /dev/null
+++ b/src/kvirc/ui/kvi_ircviewtools.h
@@ -0,0 +1,119 @@
+#ifndef _KVI_IRCVIEWTOOLS_H_
+#define _KVI_IRCVIEWTOOLS_H_
+//=========================================================================================================
+//
+// File : kvi_ircviewtools.h
+// Creation date : Sat Oct 9 2004 16:03:01 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=========================================================================================================
+
+#include "kvi_settings.h"
+
+#include "kvi_tal_tooltip.h"
+#include <qframe.h>
+#include "kvi_tal_listview.h"
+#include <qstring.h>
+
+class QLabel;
+//class KviStyledCheckBox;
+#include "kvi_styled_controls.h"
+class QLineEdit;
+
+class KviIrcView;
+
+class KviIrcViewToolTip : public KviTalToolTip
+{
+public:
+ KviIrcViewToolTip(KviIrcView * pView);
+ virtual ~KviIrcViewToolTip();
+protected:
+ KviIrcView * m_pView;
+protected:
+ virtual void maybeTip(const QPoint &pnt);
+public:
+ void doTip(const QRect &rct,const QString &str){ tip(rct,str); };
+};
+
+//=========================================================================================================
+// Item for the filter list view
+//=========================================================================================================
+
+class KviIrcViewToolWidget;
+
+class KviIrcMessageCheckListItem : public KviTalCheckListItem
+{
+public:
+ KviIrcMessageCheckListItem(KviTalListView * par,KviIrcViewToolWidget * w,int id);
+ ~KviIrcMessageCheckListItem();
+private:
+ int m_iId;
+ KviIrcViewToolWidget * m_pToolWidget;
+public:
+ void setToolWidget(KviIrcViewToolWidget * w){ m_pToolWidget = w; };
+ virtual void stateChange(bool bOn);
+};
+
+//=========================================================================================================
+// Search tools widget
+//=========================================================================================================
+
+class KviIrcView;
+
+class KviIrcViewToolWidget : public QFrame
+{
+ friend class KviIrcView;
+ Q_OBJECT
+protected:
+ KviIrcViewToolWidget(KviIrcView * par);
+ ~KviIrcViewToolWidget();
+protected:
+ KviIrcView * m_pIrcView;
+ QLineEdit * m_pStringToFind;
+ QPoint m_pressPoint;
+
+ KviStyledCheckBox * m_pCaseSensitive;
+ KviStyledCheckBox * m_pRegExp;
+ KviStyledCheckBox * m_pExtendedRegExp;
+
+ QLabel * m_pFindResult;
+
+ KviTalListView * m_pFilterView;
+
+ KviIrcMessageCheckListItem ** m_pFilterItems;
+
+public:
+ void setFindResult(const QString & text);
+ inline bool messageEnabled(int msg_type){ return m_pFilterItems[msg_type]->isOn(); }
+ void forceRepaint();
+protected slots:
+ void findPrev();
+ void findNext();
+ void filterEnableAll();
+ void filterEnableNone();
+ void filterSave();
+ void filterLoad();
+protected:
+ virtual void hideEvent( QHideEvent * );
+ virtual void closeEvent( QCloseEvent * e );
+ virtual void mouseMoveEvent(QMouseEvent *);
+ virtual void mousePressEvent(QMouseEvent *);
+};
+
+#endif //!_KVI_IRCVIEWTOOLS_H_
diff --git a/src/kvirc/ui/kvi_listview.cpp b/src/kvirc/ui/kvi_listview.cpp
new file mode 100644
index 00000000..e9c4b233
--- /dev/null
+++ b/src/kvirc/ui/kvi_listview.cpp
@@ -0,0 +1,212 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// File : kvi_listview.cpp
+// Creation date : 19 Jan 2006 GMT by Alexey Uzhva
+//
+// This toolbar is part of the KVirc irc client distribution
+// Copyright (C) 2006 Alexey Uzhva
+// Copyright (C) 2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#define __KVIRC__
+
+#include "kvi_listview.h"
+
+#include <qpainter.h>
+#include <qpixmap.h>
+
+#include "kvi_doublebuffer.h"
+
+KviListView::KviListView( QWidget * parent, const char * name)
+:KviTalListView(parent)
+{
+ m_pBackgroundOverlayPixmap=0;
+ m_iBackgroundOverlayAlignment=Qt::AlignAuto;
+}
+
+KviListView::~KviListView()
+{
+ if(m_pBackgroundOverlayPixmap)
+ delete m_pBackgroundOverlayPixmap;
+}
+
+void KviListView::setBackgroundOverlayPixmap(QPixmap * pix,int iAlignmentFlags)
+{
+ setStaticBackground(TRUE);
+#ifdef COMPILE_USE_QT4
+ viewport()->setAutoFillBackground(false);
+#else
+ viewport()->setBackgroundMode(QWidget::NoBackground);
+#endif
+ m_pBackgroundOverlayPixmap=new QPixmap(*pix);
+ m_iBackgroundOverlayAlignment= Qt::AlignRight | Qt::AlignBottom;
+ repaintContents();
+}
+
+
+
+void KviListView::drawContentsOffset(QPainter * p,int ox,int oy,int cx,int cy,int cw,int ch)
+{
+ if(!m_pBackgroundOverlayPixmap)
+ {
+ KviTalListView::drawContentsOffset(p,ox,oy,cx,cy,cw,ch);
+ return;
+ }
+
+ if(cw <= 0)return; // this does happen
+ if(ch <= 0)return; // this does happen
+
+ KviDoubleBuffer pix(viewport()->width(),viewport()->height());
+
+ QPixmap * pMemPixmap = pix.pixmap();
+
+ QPainter pa(pMemPixmap);
+
+ int xx = cx - ox;
+ int yy = cy - oy;
+
+ pa.fillRect(QRect(xx,yy,cw,ch),viewport()->backgroundColor());
+
+ //KviTalListView::paintEmptyArea(&pa,);
+
+ // compute the pixmap position
+ int x,y;
+ if(m_iBackgroundOverlayAlignment == Qt::AlignAuto)
+ x=y=0;
+ else {
+ if(m_iBackgroundOverlayAlignment & Qt::AlignLeft)
+ x=0;
+ else if ( m_iBackgroundOverlayAlignment & Qt::AlignRight )
+ x=viewport()->width() - m_pBackgroundOverlayPixmap->width();
+ else if( m_iBackgroundOverlayAlignment & Qt::AlignHCenter )
+ x=(viewport()->width() - m_pBackgroundOverlayPixmap->width())/2;
+ else
+ x=0;
+
+ if( m_iBackgroundOverlayAlignment & Qt::AlignTop )
+ y=0;
+ else if ( m_iBackgroundOverlayAlignment & Qt::AlignBottom )
+ y=viewport()->height() - m_pBackgroundOverlayPixmap->height();
+ else if ( m_iBackgroundOverlayAlignment & Qt::AlignVCenter )
+ y=(viewport()->height() - m_pBackgroundOverlayPixmap->height())/2;
+ else
+ y=0;
+ }
+
+ pa.drawPixmap(xx,yy,*m_pBackgroundOverlayPixmap,xx-x,yy-y,cw,ch);
+
+ // Qt's auto double buffering is buggy and can't be disabled... too bad :/
+ //
+ // The Qt source for the listview painting is also totally unreadable
+ // (maybe that's why they have thrown this cool widget away in Qt4: unmantainable)
+ //
+ // Anyway, I've noticed that when double buffering is choosen (and
+ // Qt seems to have a really complex logic to choose when to enable it
+ // and when not) then the painter passed to paintCell() of the
+ // list view items is NOT this painter. It's the internal painter
+ // of the QSharedDoubleBuffer private Qt class. It's screwed
+ // because of the multiple coordinate translations. With this
+ // widget we screw it even more just because our paintEmptyArea()
+ // does nothing and we do double buffering ourselves.
+
+ KviTalListView::drawContentsOffset(&pa,ox,oy,cx,cy,cw,ch);
+
+ p->drawPixmap(xx,yy,*pMemPixmap,xx,yy,cw,ch);
+
+ //p->drawPixmap(cx-ox,cy-oy,*pMemPixmap,0,0,cw,ch);
+ //KviTalListView::drawContentsOffset(p,ox,oy,cx,cy,cw,ch);
+}
+
+
+void KviListView::paintEmptyArea(QPainter * p,const QRect & rect)
+{
+ if(!m_pBackgroundOverlayPixmap)
+ {
+ KviTalListView::paintEmptyArea(p,rect);
+ return;
+ }
+
+ // otherwise just do nothing (we're filling the background in drawContentsOffset)
+
+ /*
+ KviDoubleBuffer pix(rect.right()+1,rect.bottom()+1);
+
+ QPixmap * pMemPixmap = pix.pixmap();
+
+ QPainter pa(pMemPixmap);
+
+ pa.fillRect(rect,viewport()->backgroundColor());
+
+ KviTalListView::paintEmptyArea(&pa,rect);
+
+ QPoint realTopLeft = p->xForm(rect.topLeft());
+
+ // compute the pixmap position
+ int x,y;
+ if(m_iBackgroundOverlayAlignment == Qt::AlignAuto)
+ x=y=0;
+ else {
+ if(m_iBackgroundOverlayAlignment & Qt::AlignLeft)
+ x=0;
+ else if ( m_iBackgroundOverlayAlignment & Qt::AlignRight )
+ x=viewport()->width() - m_pBackgroundOverlayPixmap->width();
+ else if( m_iBackgroundOverlayAlignment & Qt::AlignHCenter )
+ x=(viewport()->width() - m_pBackgroundOverlayPixmap->width())/2;
+ else
+ x=0;
+
+ if( m_iBackgroundOverlayAlignment & Qt::AlignTop )
+ y=0;
+ else if ( m_iBackgroundOverlayAlignment & Qt::AlignBottom )
+ y=viewport()->height() - m_pBackgroundOverlayPixmap->height();
+ else if ( m_iBackgroundOverlayAlignment & Qt::AlignVCenter )
+ y=(viewport()->height() - m_pBackgroundOverlayPixmap->height())/2;
+ else
+ y=0;
+ }
+
+ pa.drawPixmap(rect.x(),rect.y(),*m_pBackgroundOverlayPixmap,realTopLeft.x()-x,realTopLeft.y()-y,rect.width(),rect.height());
+
+ p->drawPixmap(rect.x(),rect.y(),*pMemPixmap,rect.x(),rect.y(),rect.width(),rect.height());
+ */
+}
+
+void KviListView::resizeEvent(QResizeEvent * e)
+{
+ KviTalListView::resizeEvent(e);
+ if(m_pBackgroundOverlayPixmap)
+ repaintContents(); // force a full repaint (otherwise qt does not honor static background here)
+}
+
+#ifdef COMPILE_ON_WINDOWS
+
+void KviListView::focusInEvent(QFocusEvent * e)
+{
+ KviTalListView::focusInEvent(e);
+ if(m_pBackgroundOverlayPixmap)
+ repaintContents();
+}
+
+void KviListView::focusOutEvent(QFocusEvent * e)
+{
+ KviTalListView::focusOutEvent(e);
+ if(m_pBackgroundOverlayPixmap)
+ repaintContents();
+}
+
+#endif
diff --git a/src/kvirc/ui/kvi_listview.h b/src/kvirc/ui/kvi_listview.h
new file mode 100644
index 00000000..8d39529b
--- /dev/null
+++ b/src/kvirc/ui/kvi_listview.h
@@ -0,0 +1,58 @@
+#ifndef _KVI_LISTVIEW_H_
+#define _KVI_LISTVIEW_H_
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// File : kvi_listview.h
+// Creation date : 19 Jan 2006 GMT by Alexey Uzhva
+//
+// This toolbar is part of the KVirc irc client distribution
+// Copyright (C) 2006 Alexey Uzhva
+// Copyright (C) 2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "kvi_heapobject.h"
+
+#include "kvi_tal_listview.h"
+
+class QPainter;
+
+class KVIRC_API KviListView : public KviTalListView
+{
+ Q_OBJECT
+public:
+ KviListView( QWidget * parent = 0, const char * name = 0);
+ ~KviListView();
+protected:
+ QPixmap * m_pBackgroundOverlayPixmap;
+ int m_iBackgroundOverlayAlignment;
+public:
+ virtual void setBackgroundOverlayPixmap(QPixmap* pix,int iAlignmentFlags = Qt::AlignAuto);
+public:
+ void publicUpdateContents(){ updateContents(); }; // <-- unscrewContents(); :D
+protected:
+ virtual void paintEmptyArea(QPainter * p, const QRect & rect );
+ virtual void drawContentsOffset(QPainter * p,int ox,int oy,int cx,int cy,int cw,int ch);
+ virtual void resizeEvent(QResizeEvent * e);
+#ifdef COMPILE_ON_WINDOWS
+ virtual void focusInEvent(QFocusEvent * e);
+ virtual void focusOutEvent(QFocusEvent * e);
+#endif
+};
+
+#endif //!_KVI_LISTVIEW_H_
diff --git a/src/kvirc/ui/kvi_maskeditor.cpp b/src/kvirc/ui/kvi_maskeditor.cpp
new file mode 100644
index 00000000..744df1ca
--- /dev/null
+++ b/src/kvirc/ui/kvi_maskeditor.cpp
@@ -0,0 +1,350 @@
+//=============================================================================
+//
+// File : kvi_maskeditor.cpp
+// Creation date : Tue Aug 30 2000 12:24:59 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+#include "kvi_maskeditor.h"
+#include "kvi_locale.h"
+#include "kvi_iconmanager.h"
+#include "kvi_qstring.h"
+#include "kvi_channel.h"
+#include "kvi_ircconnectionuserinfo.h"
+#include "kvi_toolwindows_container.h"
+#include "kvi_channel.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qvalidator.h>
+
+KviMaskItem::KviMaskItem(KviTalListView* parent,KviMaskEntry* entry)
+:KviTalListViewItem(parent), m_Mask(*entry)
+{
+ QDateTime date;
+ date.setTime_t(mask()->uSetAt);
+ setText(0,mask()->szMask);
+ setText(1,mask()->szSetBy);
+ setText(2,date.toString());
+}
+
+KviMaskItem::~KviMaskItem()
+{
+}
+#ifdef COMPILE_USE_QT4
+int KviMaskItem::compare ( KviTalListViewItem * i, int col, bool ascending ) const
+#else
+int KviMaskItem::compare ( QListViewItem * i, int col, bool ascending ) const
+#endif
+{
+ if(col==2)
+ {
+ if( ((KviMaskItem*)i)->mask()->uSetAt > m_Mask.uSetAt ) return -1;
+ if( ((KviMaskItem*)i)->mask()->uSetAt == m_Mask.uSetAt ) return 0;
+ if( ((KviMaskItem*)i)->mask()->uSetAt < m_Mask.uSetAt ) return 1;
+ }
+ return KviTalListViewItem::compare(i,col,ascending);
+}
+
+KviMaskInputDialog::KviMaskInputDialog(const QString &szMask,KviMaskEditor* pEditor,KviChannel * pChannel)
+:QDialog(pEditor)
+{
+ m_pChannel=pChannel;
+ m_pEditor=pEditor;
+ setModal(1);
+ m_szOldMask=szMask;
+
+ setCaption(__tr2qs("Mask editor - KVirc"));
+
+ QGridLayout * g = new QGridLayout(this,2,3,5,5);
+
+ QLabel * tl = new QLabel(__tr2qs("New mask must match an *!*@* expression"),this);
+ g->addMultiCellWidget(tl,0,0,0,3);
+
+ m_pEdit=new QLineEdit(szMask,this);
+ g->addMultiCellWidget(m_pEdit,1,1,0,3);
+
+ m_pOkButton= new QPushButton(__tr2qs("Ok"),this);
+ connect(m_pOkButton,SIGNAL(clicked()), this, SLOT(accept()));
+ g->addWidget(m_pOkButton,2,1);
+ m_pOkButton->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_ACCEPT)));
+
+ m_pChancelButton= new QPushButton(__tr2qs("Cancel"),this);
+ connect(m_pChancelButton,SIGNAL(clicked()), this, SLOT(reject()));
+ g->addWidget(m_pChancelButton,2,2);
+ m_pChancelButton->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_DISCARD)));
+
+ QRegExp rx( "*!*@*", false,true );
+ QValidator* validator = new QRegExpValidator( rx, this );
+
+ m_pEdit->setValidator( validator );
+}
+
+KviMaskInputDialog::~KviMaskInputDialog()
+{
+}
+
+void KviMaskInputDialog::accept()
+{
+ if(m_szOldMask.isEmpty())
+ {
+ m_pChannel->connection()->sendFmtData("MODE %s +%c %s",
+ m_pChannel->connection()->encodeText(m_pChannel->name()).data(),
+ m_pEditor->flag(),
+ m_pChannel->connection()->encodeText(m_pEdit->text()).data()
+ );
+ } else {
+ m_pChannel->connection()->sendFmtData("MODE %s -%c+%c %s %s",
+ m_pChannel->connection()->encodeText(m_pChannel->name()).data(),
+ m_pEditor->flag(),
+ m_pEditor->flag(),
+ m_pChannel->connection()->encodeText(m_szOldMask).data(),
+ m_pChannel->connection()->encodeText(m_pEdit->text()).data()
+ );
+ }
+ QDialog::accept();
+}
+
+KviMaskEditor::KviMaskEditor(QWidget * par,KviWindowToolPageButton* button,KviPointerList<KviMaskEntry> * maskList,char flag,const char * nam)
+: KviWindowToolWidget(par,button)
+{
+ bool isEnabled=1;
+
+ QObject * w = parent();
+ while(w)
+ {
+ if(w->inherits("KviChannel"))
+ {
+ KviChannel *chan = ((KviChannel *)w);
+ if(!( chan->isMeHalfOp() || chan->isMeOp() || chan->isMeChanOwner() || chan->isMeChanAdmin() || chan->connection()->userInfo()->hasUserMode('o') || chan->connection()->userInfo()->hasUserMode('O') ) ) isEnabled=0;
+ break;
+ }
+ w = w->parent();
+ }
+
+#ifdef COMPILE_USE_QT4
+ setFocusPolicy(Qt::ClickFocus);
+#else
+ setFocusPolicy(QWidget::ClickFocus);
+#endif
+
+ QGridLayout *g = new QGridLayout(this,4,2,2,2);
+
+ m_cFlag = flag;
+
+ QString txt;
+ switch(flag)
+ {
+ case 'b':
+ txt = __tr2qs("Active Bans");
+ m_iIconId = KVI_SMALLICON_BAN;
+ break;
+ case 'I':
+ txt = __tr2qs("Active Invite Exceptions");
+ m_iIconId = KVI_SMALLICON_INVITEEXCEPT;
+ break;
+ case 'e':
+ txt = __tr2qs("Active Ban Exceptions");
+ m_iIconId = KVI_SMALLICON_BANEXCEPT;
+ break;
+ default:
+ txt = "?";
+ m_iIconId = KVI_SMALLICON_UNHANDLED;
+ break;
+ }
+
+ QLabel * l = new QLabel("",this);
+ l->setPixmap(*(g_pIconManager->getSmallIcon(m_iIconId)));
+ g->addWidget(l,0,0);
+
+ l = new QLabel(txt,this);
+ g->addWidget(l,0,1);
+
+ KviTalHBox * hb = new KviTalHBox(this);
+ g->addMultiCellWidget(hb,1,1,0,1);
+
+ new QLabel(__tr2qs("Filter:"),hb);
+ m_pSearch = new QLineEdit(hb);
+ connect(m_pSearch,SIGNAL(textChanged ( const QString & ) ),this,SLOT(searchTextChanged ( const QString & )));
+
+ l = new QLabel(__tr2qs("Use doubleclick to edit item"),this);
+ g->addWidget(l,1,1);
+ g->addMultiCellWidget(l,2,2,0,1);
+
+ m_pMaskBox = new KviTalListView(this);
+#ifdef COMPILE_USE_QT4
+ m_pMaskBox->setFocusPolicy(Qt::ClickFocus);
+#else
+ m_pMaskBox->setFocusPolicy(QWidget::ClickFocus);
+#endif
+ m_pMaskBox->setFocusProxy(this);
+ m_pMaskBox->setFrameStyle(QFrame::StyledPanel|QFrame::Sunken);
+ m_pMaskBox->addColumn(__tr2qs("Mask"));
+ m_pMaskBox->addColumn(__tr2qs("Set by"));
+ m_pMaskBox->addColumn(__tr2qs("Set at"));
+ m_pMaskBox->setMultiSelection(true);
+ m_pMaskBox->setAllColumnsShowFocus(true);
+ m_pMaskBox->setShowSortIndicator(true);
+ m_pMaskBox->setSorting(2,false);
+ connect(m_pMaskBox,SIGNAL(doubleClicked ( KviTalListViewItem * )),this,SLOT(listViewDoubleClicked( KviTalListViewItem * )));
+ g->addMultiCellWidget(m_pMaskBox,3,3,0,1);
+
+ m_pRemoveMask = new QPushButton(__tr2qs("Re&move"),this);
+ m_pRemoveMask->setEnabled(isEnabled);
+#ifdef COMPILE_USE_QT4
+ m_pRemoveMask->setFocusPolicy(Qt::ClickFocus);
+#else
+ m_pRemoveMask->setFocusPolicy(QWidget::ClickFocus);
+#endif
+ m_pRemoveMask->setFocusProxy(this);
+ g->addWidget(m_pRemoveMask,4,1);
+ connect(m_pRemoveMask,SIGNAL(clicked()),this,SLOT(removeClicked()));
+ m_pRemoveMask->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_DELETEITEM)));
+
+ m_pAddButton = new QPushButton(__tr2qs("Add"),this);
+ m_pAddButton->setEnabled(isEnabled);
+#ifdef COMPILE_USE_QT4
+ m_pAddButton->setFocusPolicy(Qt::ClickFocus);
+#else
+ m_pAddButton->setFocusPolicy(QWidget::ClickFocus);
+#endif
+ m_pAddButton->setFocusProxy(this);
+ g->addWidget(m_pAddButton,4,0);
+ connect(m_pAddButton,SIGNAL(clicked()),this,SLOT(addClicked()));
+ m_pAddButton->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_NEWITEM)));
+
+ g->setColStretch(3,1);
+
+ for(KviMaskEntry * e = maskList->first();e;e = maskList->next()) addMask(e);
+ registerSelf();
+}
+
+KviMaskEditor::~KviMaskEditor()
+{
+
+}
+
+void KviMaskEditor::searchTextChanged ( const QString & text)
+{
+ KviTalListViewItem *pItem=m_pMaskBox->firstChild();
+ KviMaskItem *pMaskItem;
+ bool bEmpty = text.isEmpty();
+ while(pItem)
+ {
+ pMaskItem = (KviMaskItem *)pItem;
+ if(bEmpty)
+ {
+ pMaskItem->setVisible(true);
+ } else {
+ if(pMaskItem->mask()->szMask.contains(text))
+ pMaskItem->setVisible(true);
+ else
+ pMaskItem->setVisible(false);
+ }
+ pItem=pItem->nextSibling();
+ }
+}
+
+void KviMaskEditor::removeClicked()
+{
+ KviPointerList<KviMaskEntry> * l = new KviPointerList<KviMaskEntry>;
+ l->setAutoDelete(true);
+ KviMaskItem * it = (KviMaskItem *)(m_pMaskBox->firstChild());
+ while(it)
+ {
+ if(it->isSelected())
+ {
+ KviMaskEntry * e = new KviMaskEntry;
+ e->szMask = it->mask()->szMask;
+ e->szSetBy = it->mask()->szSetBy;
+ e->uSetAt = it->mask()->uSetAt;
+ l->append(e);
+ }
+ it = (KviMaskItem *)(it->nextSibling());
+ }
+ if(l->count() > 0)emit removeMasks(this,l);
+ delete l;
+}
+
+void KviMaskEditor::addClicked()
+{
+ QObject * w = parent();
+ while(w)
+ {
+ if(w->inherits("KviChannel"))
+ {
+ KviChannel *chan = ((KviChannel *)w);
+ if(chan->isMeHalfOp() || chan->isMeOp() || chan->isMeChanAdmin() || chan->isMeChanOwner() || chan->connection()->userInfo()->hasUserMode('o') || chan->connection()->userInfo()->hasUserMode('O'))
+ {
+ KviMaskInputDialog* pDialog=new KviMaskInputDialog("",this,chan);
+ pDialog->show();
+ }
+ break;
+ }
+ w = w->parent();
+ }
+}
+
+void KviMaskEditor::addMask(KviMaskEntry *e)
+{
+// debug("%s %s %i",__FILE__,__FUNCTION__,__LINE__);
+ KviMaskItem *it;
+ it = new KviMaskItem(m_pMaskBox,e);
+ it->setPixmap(0,*(g_pIconManager->getSmallIcon(m_iIconId)));
+}
+
+void KviMaskEditor::removeMask(KviMaskEntry *e)
+{
+ KviMaskItem * it =(KviMaskItem *)(m_pMaskBox->firstChild());
+ while(it)
+ {
+ if(KviQString::equalCI(it->mask()->szMask,e->szMask))
+ {
+ delete it;
+ return;
+ }
+ it = (KviMaskItem *)(it->nextSibling());
+ }
+}
+
+void KviMaskEditor::listViewDoubleClicked( KviTalListViewItem * pItem)
+{
+ if(pItem)
+ {
+ QObject * w = parent();
+ while(w)
+ {
+ if(w->inherits("KviChannel"))
+ {
+ KviChannel *chan = ((KviChannel *)w);
+ if(chan->isMeHalfOp() || chan->isMeOp() || chan->isMeChanAdmin() || chan->isMeChanOwner() || chan->connection()->userInfo()->hasUserMode('o') || chan->connection()->userInfo()->hasUserMode('O'))
+ {
+ KviMaskInputDialog* pDialog=new KviMaskInputDialog(pItem->text(0),this,chan);
+ pDialog->show();
+ }
+ break;
+ }
+ w = w->parent();
+ }
+ }
+}
+
+#include "kvi_maskeditor.moc"
diff --git a/src/kvirc/ui/kvi_maskeditor.h b/src/kvirc/ui/kvi_maskeditor.h
new file mode 100644
index 00000000..de281377
--- /dev/null
+++ b/src/kvirc/ui/kvi_maskeditor.h
@@ -0,0 +1,108 @@
+#ifndef _KVI_MASKEDITOR_H_
+#define _KVI_MASKEDITOR_H_
+
+//
+// File : kvi_maskeditor.h
+// Creation date : Tue Aug 30 2000 12:20:10 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+#include <qdialog.h>
+#include <qlineedit.h>
+#include <qwidget.h>
+#include "kvi_tal_listview.h"
+#include <qpushbutton.h>
+#include "kvi_pointerlist.h"
+
+#include "kvi_string.h"
+#include "kvi_toolwindows_container.h"
+
+class KviMaskEditor;
+class KviChannel;
+
+typedef struct _KviMaskEntry
+{
+ QString szMask;
+ QString szSetBy;
+ unsigned int uSetAt;
+} KviMaskEntry;
+
+class KviMaskItem: public KviTalListViewItem
+{
+public:
+ KviMaskItem(KviTalListView* parent,KviMaskEntry* entry);
+ ~KviMaskItem();
+
+ KviMaskEntry* mask() { return &m_Mask; };
+#ifdef COMPILE_USE_QT4
+ virtual int compare ( KviTalListViewItem * i, int col, bool ascending ) const;
+#else
+ virtual int compare ( QListViewItem * i, int col, bool ascending ) const;
+#endif
+protected:
+ KviMaskEntry m_Mask;
+
+};
+
+class KviMaskInputDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ KviMaskInputDialog(const QString &szMask,KviMaskEditor* pEditor,KviChannel * pChannel);
+ ~KviMaskInputDialog();
+protected:
+ QLineEdit * m_pEdit;
+ QPushButton * m_pOkButton;
+ QPushButton * m_pChancelButton;
+ QString m_szOldMask;
+ KviChannel * m_pChannel;
+ KviMaskEditor * m_pEditor;
+protected slots:
+ virtual void accept();
+};
+
+class KVIRC_API KviMaskEditor : public KviWindowToolWidget
+{
+ Q_OBJECT
+public:
+ KviMaskEditor(QWidget * par,KviWindowToolPageButton* button,KviPointerList<KviMaskEntry> * maskList,
+ char flag,const char * nam);
+ ~KviMaskEditor();
+protected:
+ KviTalListView * m_pMaskBox;
+ QPushButton * m_pRemoveMask;
+ QPushButton * m_pAddButton;
+ QLineEdit * m_pSearch;
+ char m_cFlag;
+ int m_iIconId;
+public:
+ char flag(){ return m_cFlag; };
+ void addMask(KviMaskEntry *e);
+ void removeMask(KviMaskEntry *e);
+protected slots:
+ void removeClicked();
+ void addClicked();
+ void listViewDoubleClicked( KviTalListViewItem * );
+ void searchTextChanged ( const QString & );
+signals:
+ void removeMasks(KviMaskEditor *,KviPointerList<KviMaskEntry> *);
+};
+
+#endif //_KVI_MASKEDITOR_H_
diff --git a/src/kvirc/ui/kvi_mdicaption.cpp b/src/kvirc/ui/kvi_mdicaption.cpp
new file mode 100644
index 00000000..ba4aea40
--- /dev/null
+++ b/src/kvirc/ui/kvi_mdicaption.cpp
@@ -0,0 +1,285 @@
+//=================================================================================================
+//
+// File : kvi_mdicaption.cpp
+// Creation date : Tue Sep 2 2003 02:35:45 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=================================================================================================
+
+#define __KVIRC__
+
+#define _KVI_DEBUG_CHECK_RANGE_
+#include "kvi_debug.h"
+#include "kvi_mdichild.h"
+#include "kvi_mdimanager.h"
+#include "kvi_string.h"
+#include "kvi_locale.h"
+#include "kvi_options.h"
+#include "kvi_settings.h"
+#include "kvi_iconmanager.h"
+#include "kvi_window.h"
+#include "kvi_mdicaption.h"
+
+#include <qcursor.h>
+#include <qnamespace.h>
+#include <qapplication.h>
+#include <qfontmetrics.h>
+#include "kvi_pointerlist.h"
+#include <qpixmap.h>
+#include <qstyle.h>
+#include <qpainter.h>
+#include "kvi_tal_popupmenu.h"
+#ifdef COMPILE_USE_QT4
+ #include <q3simplerichtext.h>
+ #define QSimpleRichText Q3SimpleRichText
+ #include <qstyleoption.h>
+#else
+ #include <qsimplerichtext.h>
+#endif
+#include <qdrawutil.h>
+#include <qevent.h>
+
+KviMdiCaptionButton::KviMdiCaptionButton(const QPixmap &pix,QWidget * parent,const char * name)
+: QToolButton(parent,name)
+{
+ setPixmap(pix);
+ //setAutoRaise(true);
+ setMinimumSize(18,18);
+}
+
+KviMdiCaptionButton::~KviMdiCaptionButton()
+{
+}
+
+
+#ifdef COMPILE_USE_QT4
+void KviMdiCaptionButton::paintEvent(QPaintEvent *e)
+{
+ QPainter painter(this);
+ drawButton(&painter);
+}
+#endif
+
+void KviMdiCaptionButton::drawButton(QPainter *p)
+{
+#ifdef COMPILE_USE_QT4
+ QBrush b(parentWidget()->palette().window());
+#else
+ QBrush b(parentWidget()->colorGroup().background());
+#endif
+
+ if(isDown())
+ qDrawShadePanel(p,0,0,width(),height(),colorGroup(),true,1,&b);
+ else
+ p->fillRect(0,0,width(),height(),b);
+
+#ifdef COMPILE_USE_QT4
+ int x = (width() - 16) / 2;
+ int y = (width() - 16) / 2;
+ p->drawPixmap(x,y,16,16,icon().pixmap(16,16),0,0,16,16);
+#else
+ drawButtonLabel(p);
+#endif
+}
+
+
+
+
+
+
+
+KviMdiCaption::KviMdiCaption(KviMdiChild * parent,const char * name)
+: QWidget(parent,name)
+{
+ m_pMaximizeButton = new KviMdiCaptionButton(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_MAXIMIZE)),this,"maximize_button");
+ connect(m_pMaximizeButton,SIGNAL(clicked()),parent,SLOT(maximize()));
+ m_pMinimizeButton = new KviMdiCaptionButton(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_MINIMIZE)),this,"minimize_button");
+ connect(m_pMinimizeButton,SIGNAL(clicked()),parent,SLOT(minimize()));
+ m_pCloseButton = new KviMdiCaptionButton(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CLOSE)),this,"close_button");
+ connect(m_pCloseButton,SIGNAL(clicked()),parent,SLOT(closeRequest()));
+ m_pSystemButton = new KviMdiCaptionButton(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_DEFAULTICON)),this,"icon_button");
+ connect(m_pSystemButton,SIGNAL(clicked()),parent,SLOT(systemPopupSlot()));
+
+ m_lastMousePos = QPoint(-1,-1);
+ m_bMouseGrabbed = true;
+ m_bActive = false;
+ calcLineSpacing();
+#ifdef COMPILE_USE_QT4
+ setAutoFillBackground(false);
+#endif
+}
+
+KviMdiCaption::~KviMdiCaption()
+{
+}
+
+void KviMdiCaption::reloadImages()
+{
+ m_pMaximizeButton->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_MAXIMIZE)));
+ m_pMinimizeButton->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_MINIMIZE)));
+ m_pCloseButton->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CLOSE)));
+}
+
+void KviMdiCaption::calcLineSpacing()
+{
+ QFontMetrics fm(font());
+ m_iLineSpacing = fm.lineSpacing() + 3;
+ if(m_iLineSpacing < 20)m_iLineSpacing = 20;
+}
+
+int KviMdiCaption::heightHint()
+{
+ return m_iLineSpacing;
+}
+
+void KviMdiCaption::setActive(bool bActive)
+{
+ m_bActive = bActive;
+
+ QPalette pal(Qt::white,m_bActive ? KVI_OPTION_COLOR(KviOption_colorMdiCaptionActive) : KVI_OPTION_COLOR(KviOption_colorMdiCaptionInactive));
+ setPalette(pal);
+ //update();
+ m_pSystemButton->update();
+ m_pCloseButton->update();
+ m_pMinimizeButton->update();
+ m_pMaximizeButton->update();
+}
+
+void KviMdiCaption::fontChange(const QFont &old)
+{
+ calcLineSpacing();
+ QWidget::fontChange(old);
+ ((KviMdiChild *)parent())->resizeEvent(0);
+}
+
+void KviMdiCaption::mousePressEvent(QMouseEvent *e)
+{
+ m_bMouseGrabbed = true;
+ m_lastMousePos = QCursor::pos();
+#ifdef COMPILE_USE_QT4
+ setCursor(Qt::SizeAllCursor);
+#else
+ setCursor(QCursor::sizeAllCursor);
+#endif
+ ((KviMdiChild *)parent())->activate(true);
+}
+
+void KviMdiCaption::mouseMoveEvent(QMouseEvent *)
+{
+ if(m_bMouseGrabbed)
+ {
+ QPoint p = QCursor::pos();
+ int dx = m_lastMousePos.x() - p.x();
+ int dy = m_lastMousePos.y() - p.y();
+ KviMdiChild * c = (KviMdiChild *)parent();
+
+ int nx = c->manager()->childX(c) - dx;
+ int ny = c->manager()->childY(c) - dy;
+
+ if((nx < 0) || (ny < 0))
+ {
+ int cx = p.x();
+ int cy = p.y();
+ if(nx < 0)
+ {
+ cx -= nx;
+ nx = 0;
+ }
+ if(ny < 0)
+ {
+ cy -= ny;
+ ny = 0;
+ }
+
+ QCursor::setPos(cx,cy);
+ m_lastMousePos = QPoint(cx,cy);
+ } else {
+ m_lastMousePos = p;
+ }
+
+ c->manager()->moveChild(c,nx,ny);
+ c->manager()->childMoved(c);
+ }
+}
+
+void KviMdiCaption::mouseDoubleClickEvent(QMouseEvent *e)
+{
+ ((KviMdiChild *)parent())->maximize();
+}
+
+void KviMdiCaption::paintEvent(QPaintEvent * e)
+{
+ QRect r = e->rect();
+ QPainter p(this);
+ p.fillRect(r,m_bActive ? KVI_OPTION_COLOR(KviOption_colorMdiCaptionActive) : KVI_OPTION_COLOR(KviOption_colorMdiCaptionInactive));
+ QSimpleRichText rt(m_bActive ? ((KviMdiChild *)parent())->xmlActiveCaption() : ((KviMdiChild *)parent())->xmlInactiveCaption(),font());
+ rt.draw(&p,height() + 2,-1,rect(),colorGroup());
+}
+
+void KviMdiCaption::mouseReleaseEvent(QMouseEvent *)
+{
+ m_bMouseGrabbed = false;
+#ifdef COMPILE_USE_QT4
+ setCursor(Qt::arrowCursor);
+#else
+ setCursor(QCursor::arrowCursor);
+#endif
+// releaseMouse();
+}
+
+void KviMdiCaption::setFocusProxy(QWidget * w)
+{
+ QWidget::setFocusProxy(w);
+ m_pSystemButton->setFocusProxy(w);
+ m_pMinimizeButton->setFocusProxy(w);
+ m_pMaximizeButton->setFocusProxy(w);
+ m_pCloseButton->setFocusProxy(w);
+}
+
+void KviMdiCaption::resizeEvent(QResizeEvent * e)
+{
+ int s = height() - 2;
+ m_pSystemButton->setGeometry(1,1,s,s);
+ m_pCloseButton->setGeometry(width() - (s + 1),
+ 1,s,s);
+ m_pMaximizeButton->setGeometry(width() - ((s << 1) + 2),
+ 1,s,s);
+ m_pMinimizeButton->setGeometry(width() - ((s * 3) + 3),
+ 1,s,s);
+}
+
+
+
+KviMenuBarToolButton::KviMenuBarToolButton(QWidget * par,const QPixmap &img, const char * name)
+: KviStyledToolButton(par)
+{
+ setProperty("name","name");
+ setIconSet(img);
+ setAutoRaise(true);
+}
+
+KviMenuBarToolButton::~KviMenuBarToolButton()
+{
+}
+
+QSize KviMenuBarToolButton::sizeHint() const
+{
+ return QSize(20,20);
+}
+
diff --git a/src/kvirc/ui/kvi_mdicaption.h b/src/kvirc/ui/kvi_mdicaption.h
new file mode 100644
index 00000000..6bec4051
--- /dev/null
+++ b/src/kvirc/ui/kvi_mdicaption.h
@@ -0,0 +1,101 @@
+#ifndef _KVI_MDICAPTION_H_
+#define _KVI_MDICAPTION_H_
+//=================================================================================================
+//
+// File : kvi_mdicaption.h
+// Creation date : Tue Sep 2 2003 02:35:45 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=================================================================================================
+
+#include "kvi_settings.h"
+
+#include <qtoolbutton.h>
+#include <qlabel.h>
+#include "kvi_styled_controls.h"
+
+class KviMdiManager;
+class KviMdiChild;
+
+
+class KVIRC_API KviMdiCaptionButton : public QToolButton
+{
+ Q_OBJECT
+public:
+ KviMdiCaptionButton(const QPixmap &pix,QWidget * parent,const char * name);
+ ~KviMdiCaptionButton();
+protected:
+ virtual void drawButton(QPainter * p);
+#ifdef COMPILE_USE_QT4
+ virtual void paintEvent(QPaintEvent *e);
+#endif
+};
+
+
+class KviMenuBarToolButton : public KviStyledToolButton
+{
+ Q_OBJECT
+public:
+ KviMenuBarToolButton(QWidget * par,const QPixmap &img, const char * name);
+ ~KviMenuBarToolButton();
+public:
+ virtual QSize sizeHint() const;
+};
+
+
+class KVIRC_API KviMdiCaption : public QWidget
+{
+ friend class KviMdiChild;
+ Q_OBJECT
+public:
+ KviMdiCaption(KviMdiChild * parent,const char * name);
+ ~KviMdiCaption();
+protected:
+ QPoint m_lastMousePos;
+ bool m_bMouseGrabbed;
+ int m_iLineSpacing;
+ bool m_bActive;
+ KviMdiCaptionButton * m_pSystemButton;
+ KviMdiCaptionButton * m_pMinimizeButton;
+ KviMdiCaptionButton * m_pMaximizeButton;
+ KviMdiCaptionButton * m_pCloseButton;
+ QPixmap m_pixSystemIcon;
+public:
+ int heightHint();
+ void setActive(bool bActive);
+ bool active(){ return m_bActive; };
+ void setSystemIcon(const QPixmap &pix){ m_pSystemButton->setPixmap(pix); m_pixSystemIcon = pix; };
+ const QPixmap * systemIcon(){ return &m_pixSystemIcon; };
+ void enableClose(bool bEnable){ m_pCloseButton->setEnabled(bEnable); };
+ bool closeEnabled(){ return m_pCloseButton->isEnabled(); };
+ virtual void setFocusProxy(QWidget * w);
+protected:
+ void calcLineSpacing();
+ virtual void fontChange(const QFont &old);
+ virtual void mousePressEvent(QMouseEvent *e);
+ virtual void mouseDoubleClickEvent(QMouseEvent *e);
+ virtual void mouseMoveEvent(QMouseEvent *e);
+ virtual void mouseReleaseEvent(QMouseEvent *e);
+ virtual void paintEvent(QPaintEvent * e);
+ virtual void resizeEvent(QResizeEvent * e);
+ void reloadImages();
+};
+
+
+#endif //_KVI_MDICAPTION_H_
diff --git a/src/kvirc/ui/kvi_mdichild.cpp b/src/kvirc/ui/kvi_mdichild.cpp
new file mode 100644
index 00000000..9b92c563
--- /dev/null
+++ b/src/kvirc/ui/kvi_mdichild.cpp
@@ -0,0 +1,576 @@
+//=============================================================================
+//
+// File : kvi_mdichild.cpp
+// Creation date : Wed Jun 21 2000 17:35:45 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+#define __KVIRC__
+
+#define _KVI_DEBUG_CHECK_RANGE_
+#include "kvi_debug.h"
+#include "kvi_mdichild.h"
+#include "kvi_mdimanager.h"
+#include "kvi_string.h"
+#include "kvi_locale.h"
+#include "kvi_options.h"
+#include "kvi_settings.h"
+#include "kvi_iconmanager.h"
+#include "kvi_window.h"
+#include "kvi_mdicaption.h"
+
+#include <qcursor.h>
+#include <qnamespace.h>
+#include <qapplication.h>
+#include <qfontmetrics.h>
+#include "kvi_pointerlist.h"
+#include <qpixmap.h>
+#include <qstyle.h>
+#include <qpainter.h>
+#include "kvi_tal_popupmenu.h"
+#ifndef COMPILE_USE_QT4
+ #include <qobjectlist.h>
+#endif
+#include <qevent.h>
+
+#ifdef Q_OS_MACX
+#include "kvi_app.h" //Needed for g_pApp
+#ifdef COMPILE_USE_QT4
+ #include <QDesktopWidget>
+#endif
+#endif
+
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ extern QPixmap * g_pShadedChildGlobalDesktopBackground;
+#endif
+
+
+#define KVI_MDI_NORESIZE 0
+#define KVI_MDI_RESIZE_TOP 1
+#define KVI_MDI_RESIZE_LEFT 2
+#define KVI_MDI_RESIZE_RIGHT 4
+#define KVI_MDI_RESIZE_BOTTOM 8
+#define KVI_MDI_RESIZE_TOPLEFT (1|2)
+#define KVI_MDI_RESIZE_TOPRIGHT (1|4)
+#define KVI_MDI_RESIZE_BOTTOMLEFT (8|2)
+#define KVI_MDI_RESIZE_BOTTOMRIGHT (8|4)
+
+
+KviMdiChild::KviMdiChild(KviMdiManager * par,const char * name)
+: QFrame(par->viewport(),name ? name : "mdi_child")
+{
+ setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
+ setFrameShape(NoFrame);
+ m_pManager = par;
+
+ m_pCaption = new KviMdiCaption(this,"mdi_caption");
+
+ m_bResizeMode = false;
+ m_iResizeCorner = KVI_MDI_NORESIZE;
+ m_iLastCursorCorner = KVI_MDI_NORESIZE;
+
+ m_pClient = 0;
+ m_state = Normal;
+ m_restoredGeometry = QRect(10,10,100,100);
+
+ setMouseTracking(true);
+ setMinimumSize(KVI_MDICHILD_MIN_WIDTH,KVI_MDICHILD_MIN_HEIGHT);
+
+#ifdef COMPILE_USE_QT4
+ setAutoFillBackground(true);
+#endif
+
+}
+
+KviMdiChild::~KviMdiChild()
+{
+ if(m_pClient)delete m_pClient;
+}
+
+void KviMdiChild::reloadImages()
+{
+ m_pCaption->reloadImages();
+}
+
+QRect KviMdiChild::restoredGeometry()
+{
+ if(m_state == Maximized)return m_restoredGeometry;
+ else return QRect(x(),y(),width(),height());
+// else return geometry();
+
+}
+
+#ifdef COMPILE_USE_QT4
+void KviMdiChild::setBackgroundRole(QPalette::ColorRole)
+{
+ // hack
+ QFrame::setBackgroundRole(QPalette::Window);
+}
+#else
+void KviMdiChild::setBackgroundMode(QWidget::BackgroundMode)
+{
+ // hack
+ QFrame::setBackgroundMode(QWidget::PaletteBackground);
+}
+#endif
+
+void KviMdiChild::setIcon(const QPixmap &pix)
+{
+ m_pCaption->setSystemIcon(pix);
+
+ if((m_state == Maximized) && (m_pManager->topChild() == this))
+ {
+ m_pManager->updateSDIMode();
+ }
+}
+
+const QPixmap * KviMdiChild::icon()
+{
+ return m_pCaption->systemIcon();
+}
+
+void KviMdiChild::enableClose(bool bEnable)
+{
+ m_pCaption->enableClose(bEnable);
+ if((m_state == Maximized) && (m_pManager->topChild() == this))
+ {
+ m_pManager->updateSDIMode();
+ }
+
+}
+
+bool KviMdiChild::closeEnabled()
+{
+ return m_pCaption->closeEnabled();
+}
+
+void KviMdiChild::setCaption(const QString & plain,const QString & xmlActive,const QString & xmlInactive)
+{
+ m_szPlainCaption = plain;
+ m_szXmlActiveCaption = xmlActive;
+ m_szXmlInactiveCaption = xmlInactive;
+ //m_pCaptionLabel->setActive(m_pCaptionLabel->active());
+ m_pCaption->update();
+}
+
+void KviMdiChild::maximize()
+{
+ if(m_state == Minimized)restore(); // restore first
+ if(m_state == Normal)m_restoredGeometry = geometry();
+ m_state = Maximized;
+ manager()->maximizeChild(this);
+}
+
+void KviMdiChild::restore()
+{
+ if(m_restoredGeometry.x() < 0)m_restoredGeometry.setX(0);
+ if(m_restoredGeometry.y() < 0)m_restoredGeometry.setY(0);
+ // ensure coherency
+ if(m_restoredGeometry.width() < 5)m_restoredGeometry.setWidth(5);
+ if(m_restoredGeometry.height() < 5)m_restoredGeometry.setHeight(5);
+
+ /*
+ if((m_restoredGeometry.x() + m_restoredGeometry.width()) > m_pManager->width())
+ m_restoredGeometry.setWidth(m_pManager->width() - m_restoredGeometry.x());
+ if((m_restoredGeometry.y() + m_restoredGeometry.height()) > m_pManager->height())
+ m_restoredGeometry.setHeight(m_pManager->height() - m_restoredGeometry.y());
+ */
+
+ switch(m_state)
+ {
+ case Maximized:
+ m_pManager->moveChild(this,m_restoredGeometry.x(),m_restoredGeometry.y());
+ resize(m_restoredGeometry.width(),m_restoredGeometry.height());
+ m_state = Normal;
+ m_pManager->childRestored(this,true);
+ break;
+ case Minimized:
+ m_pManager->moveChild(this,m_restoredGeometry.x(),m_restoredGeometry.y());
+ resize(m_restoredGeometry.width(),m_restoredGeometry.height());
+ show();
+ m_state = Normal;
+ m_pManager->childRestored(this,false);
+ break;
+ case Normal:
+ m_state = Normal;
+ if(!isVisible())show();
+ return;
+ break;
+ }
+}
+
+void KviMdiChild::minimize()
+{
+ switch(m_state)
+ {
+ case Maximized:
+ hide();
+ m_state = Minimized;
+ m_pManager->childMinimized(this,true);
+ break;
+ case Normal:
+ m_restoredGeometry = geometry();
+ hide();
+ m_state = Minimized;
+ m_pManager->childMinimized(this,false);
+ break;
+ case Minimized:
+ m_state = Minimized;
+ if(isVisible())hide();
+ return;
+ break;
+ }
+}
+
+void KviMdiChild::closeRequest()
+{
+ if(closeEnabled())if(m_pClient)m_pClient->close();
+}
+/*
+void KviMdiChild::systemPopupAboutToShow()
+{
+ m_pSystemPopup->clear();
+ if(m_state != Maximized)m_pSystemPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_MAXIMIZE)),__tr("&Maximize"),this,SLOT(maximize()));
+ if(m_state != Minimized)m_pSystemPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_MINIMIZE)),__tr("M&inimize"),this,SLOT(minimize()));
+ if(m_state != Normal)m_pSystemPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_RESTORE)),__tr("&Restore"),this,SLOT(restore()));
+ if(closeEnabled())
+ {
+ m_pSystemPopup->insertSeparator();
+ m_pSystemPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CLOSE)),__tr("&Close"),this,SLOT(closeRequest()));
+ }
+}
+*/
+void KviMdiChild::moveEvent(QMoveEvent *e)
+{
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ if(m_pClient && g_pShadedChildGlobalDesktopBackground)
+ {
+ if(m_pClient->inherits("KviWindow")) // actually this is always the case
+ {
+ ((KviWindow *)m_pClient)->updateBackgrounds();
+ }
+ }
+#endif
+ QFrame::moveEvent(e);
+}
+
+void KviMdiChild::systemPopupSlot()
+{
+ if(sender()->inherits("QToolButton"))
+ {
+ emit systemPopupRequest(((QToolButton *)sender())->mapToGlobal(QPoint(0,((QToolButton *)sender())->height())));
+ } else {
+ emit systemPopupRequest(m_pCaption->mapToGlobal(QPoint(5,5)));
+ }
+}
+
+void KviMdiChild::resizeEvent(QResizeEvent *e)
+{
+ int s = m_pCaption->heightHint();
+ m_pCaption->setGeometry(KVI_MDICHILD_BORDER,KVI_MDICHILD_BORDER,
+ width() - (KVI_MDICHILD_BORDER << 1),s);
+
+ if(m_pClient)
+ {
+ int yPos = KVI_MDICHILD_BORDER + s + KVI_MDICHILD_SPACING;
+ m_pClient->setGeometry(KVI_MDICHILD_BORDER,yPos,
+ width() - (KVI_MDICHILD_BORDER << 1),height() - (yPos + KVI_MDICHILD_BORDER));
+ }
+ QFrame::resizeEvent(e);
+}
+
+void KviMdiChild::mousePressEvent(QMouseEvent *e)
+{
+ if(m_state == Maximized)return;
+ m_iResizeCorner=getResizeCorner(e->pos().x(),e->pos().y());
+ if(m_iResizeCorner != KVI_MDI_NORESIZE)
+ {
+ grabMouse(getResizeCursor(m_iResizeCorner));
+ m_bResizeMode = true;
+ }
+}
+
+void KviMdiChild::mouseReleaseEvent(QMouseEvent *)
+{
+ m_iResizeCorner=KVI_MDI_NORESIZE;
+ m_iLastCursorCorner=KVI_MDI_NORESIZE;
+
+ if(m_bResizeMode)
+ {
+ m_bResizeMode = false;
+ releaseMouse();
+ }
+
+ //if(QApplication::overrideCursor())QApplication::restoreOverrideCursor();
+}
+
+QCursor KviMdiChild::getResizeCursor(int resizeCorner)
+{
+ switch (resizeCorner)
+ {
+ case KVI_MDI_RESIZE_LEFT:
+ case KVI_MDI_RESIZE_RIGHT:
+ return Qt::sizeHorCursor;
+ break;
+ case KVI_MDI_RESIZE_TOP:
+ case KVI_MDI_RESIZE_BOTTOM:
+ return Qt::sizeVerCursor;
+ break;
+ case KVI_MDI_RESIZE_TOPLEFT:
+ case KVI_MDI_RESIZE_BOTTOMRIGHT:
+ return Qt::sizeFDiagCursor;
+ break;
+ case KVI_MDI_RESIZE_BOTTOMLEFT:
+ case KVI_MDI_RESIZE_TOPRIGHT:
+ return Qt::sizeBDiagCursor;
+ break;
+ default:
+ return Qt::arrowCursor;
+ break;
+ }
+}
+
+void KviMdiChild::mouseMoveEvent(QMouseEvent *e)
+{
+ if(e->state() & Qt::LeftButton)
+ {
+ if(m_iResizeCorner && (m_state != Maximized))resizeWindowOpaque(m_iResizeCorner);
+ } else {
+ setResizeCursor(getResizeCorner(e->pos().x(), e->pos().y()));
+ }
+}
+
+void KviMdiChild::setResizeCursor(int resizeCorner)
+{
+ if(resizeCorner == m_iLastCursorCorner)
+ return; //Don't do it twice
+ m_iLastCursorCorner = resizeCorner;
+ if(resizeCorner == KVI_MDI_NORESIZE)
+ {
+ setCursor(getResizeCursor(resizeCorner));
+ //if(QApplication::overrideCursor())QApplication::restoreOverrideCursor();
+ } else {
+ if(m_state != Maximized)
+ {
+ setCursor(getResizeCursor(resizeCorner));
+ //QApplication::setOverrideCursor(getResizeCursor(resizeCorner),true);
+ }
+ }
+}
+
+void KviMdiChild::leaveEvent(QEvent *)
+{
+ if(!m_bResizeMode)
+ {
+ m_iResizeCorner=KVI_MDI_NORESIZE;
+ m_iLastCursorCorner=KVI_MDI_NORESIZE;
+ //if(QApplication::overrideCursor())QApplication::restoreOverrideCursor();
+ } else {
+ if(m_iResizeCorner != KVI_MDI_NORESIZE)resizeWindowOpaque(m_iResizeCorner);
+ }
+}
+
+void KviMdiChild::calculateResizeRect(int resizeCorner,QPoint mousePos,QRect &resizeRect,int minWidth,int minHeight)
+{
+ switch(resizeCorner)
+ {
+ case KVI_MDI_RESIZE_LEFT:
+ resizeRect.setLeft(mousePos.x() - 1);
+ if(resizeRect.width() < minWidth)resizeRect.setLeft(resizeRect.right() - minWidth);
+ if(resizeRect.x() < 0)resizeRect.setX(0);
+ break;
+ case KVI_MDI_RESIZE_RIGHT:
+ resizeRect.setRight(mousePos.x() + 1);
+ if(resizeRect.width() < minWidth)resizeRect.setRight(resizeRect.left() + minWidth);
+ break;
+ case KVI_MDI_RESIZE_TOP:
+ resizeRect.setTop(mousePos.y() - 1);
+ if(resizeRect.height() < minHeight)resizeRect.setTop(resizeRect.bottom() - minHeight);
+ if(resizeRect.y() < 0)resizeRect.setY(0);
+ break;
+ case KVI_MDI_RESIZE_BOTTOM:
+ resizeRect.setBottom(mousePos.y() + 1);
+ if(resizeRect.height() < minHeight)resizeRect.setBottom(resizeRect.top() + minHeight);
+ break;
+ case KVI_MDI_RESIZE_BOTTOMRIGHT:
+ resizeRect.setBottom(mousePos.y() + 1);
+ if(resizeRect.height() < minHeight)resizeRect.setBottom(resizeRect.top() + minHeight);
+ resizeRect.setRight(mousePos.x() + 1);
+ if(resizeRect.width() < minWidth)resizeRect.setRight(resizeRect.left() + minWidth);
+ break;
+ case KVI_MDI_RESIZE_TOPRIGHT:
+ resizeRect.setTop(mousePos.y() - 1);
+ if(resizeRect.height() < minHeight)resizeRect.setTop(resizeRect.bottom() - minHeight);
+ if(resizeRect.y() < 0)resizeRect.setY(0);
+ resizeRect.setRight(mousePos.x() + 1);
+ if(resizeRect.width() < minWidth)resizeRect.setRight(resizeRect.left() + minWidth);
+ break;
+ case KVI_MDI_RESIZE_BOTTOMLEFT:
+ resizeRect.setBottom(mousePos.y() + 1);
+ if(resizeRect.height() < minHeight)resizeRect.setBottom(resizeRect.top() + minHeight);
+ resizeRect.setLeft(mousePos.x() - 1);
+ if(resizeRect.width() < minWidth)resizeRect.setLeft(resizeRect.right() - minWidth);
+ if(resizeRect.x() < 0)resizeRect.setX(0);
+ break;
+ case KVI_MDI_RESIZE_TOPLEFT:
+ resizeRect.setTop(mousePos.y() - 1);
+ if(resizeRect.height() < minHeight)resizeRect.setTop(resizeRect.bottom() - minHeight);
+ if(resizeRect.y() < 0)resizeRect.setY(0);
+ resizeRect.setLeft(mousePos.x() - 1);
+ if(resizeRect.width() < minWidth)resizeRect.setLeft(resizeRect.right() - minWidth);
+ if(resizeRect.x() < 0)resizeRect.setX(0);
+ break;
+ }
+}
+
+void KviMdiChild::calculateMinimumSize(int &minWidth,int &minHeight)
+{
+ if(m_pClient){
+ minWidth = m_pClient->minimumSize().width() + (KVI_MDICHILD_BORDER << 1);
+ minHeight = m_pClient->minimumSize().height()+ (KVI_MDICHILD_BORDER << 1)+
+ m_pCaption->heightHint() + KVI_MDICHILD_SPACING;
+ }
+ if(minWidth<KVI_MDICHILD_MIN_WIDTH)minWidth=KVI_MDICHILD_MIN_WIDTH;
+ if(minHeight<KVI_MDICHILD_MIN_HEIGHT)minHeight=KVI_MDICHILD_MIN_HEIGHT;
+}
+
+void KviMdiChild::resizeWindowOpaque(int resizeCorner)
+{
+ int minWidth=0;
+ int minHeight=0;
+ QRect resizeRect(m_pManager->childX(this),m_pManager->childY(this),width(),height());
+ calculateMinimumSize(minWidth,minHeight);
+ QPoint mousePos = m_pManager->viewportToContents(m_pManager->viewport()->mapFromGlobal(QCursor::pos()));
+ calculateResizeRect(resizeCorner,mousePos,resizeRect,minWidth,minHeight);
+ m_pManager->moveChild(this,resizeRect.x(),resizeRect.y());
+ resize(resizeRect.width(),resizeRect.height());
+ m_pManager->childMoved(this);
+
+ if(m_state == Maximized)
+ {
+ m_state=Normal;
+ m_pManager->childRestored(this,true);
+ }
+
+}
+
+int KviMdiChild::getResizeCorner(int ax,int ay)
+{
+ int ret = KVI_MDI_NORESIZE;
+ if((ax>0)&&(ax<(KVI_MDICHILD_BORDER+2))) ret |= KVI_MDI_RESIZE_LEFT;
+ if((ax<width())&&(ax>(width()-(KVI_MDICHILD_BORDER+2)))) ret |= KVI_MDI_RESIZE_RIGHT;
+ if((ay>0)&&(ay<(KVI_MDICHILD_BORDER+2))) ret |= KVI_MDI_RESIZE_TOP;
+ if((ay<(height()))&&(ay>(height()-(KVI_MDICHILD_BORDER+2)))) ret |= KVI_MDI_RESIZE_BOTTOM;
+ return ret;
+}
+
+void KviMdiChild::setClient(QWidget *w)
+{
+ __range_valid(m_pClient==0);
+ __range_valid(w!=0);
+
+ m_pClient = w;
+ //resize to match the client
+ int clientYPos=m_pCaption->heightHint()+KVI_MDICHILD_SPACING+KVI_MDICHILD_BORDER;
+ resize(w->width()+(KVI_MDICHILD_BORDER << 1),w->height()+KVI_MDICHILD_BORDER+clientYPos);
+
+ //Reparent if needed
+ if(w->parent()!=this){
+ //reparent to this widget , no flags , point , show it
+ QPoint pnt2(KVI_MDICHILD_BORDER,clientYPos);
+ w->reparent(this,pnt2,true);
+ } else w->move(KVI_MDICHILD_BORDER,clientYPos);
+
+ setFocusProxy(w);
+ m_pCaption->setFocusProxy(w);
+
+/*
+ m_pMinimizeButton->setFocusProxy(w);
+ m_pMaximizeButton->setFocusProxy(w);
+ m_pCloseButton->setFocusProxy(w);
+ m_pIconButton->setFocusProxy(w);
+*/
+ //linkChildren(w);
+
+ if(m_pClient->minimumSize().width() > KVI_MDICHILD_MIN_WIDTH &&
+ m_pClient->minimumSize().height() > KVI_MDICHILD_MIN_HEIGHT){
+ setMinimumWidth(m_pClient->minimumSize().width() + (KVI_MDICHILD_BORDER << 1));
+ setMinimumHeight(m_pClient->minimumSize().height()+ (KVI_MDICHILD_BORDER << 1) +
+ m_pCaption->heightHint() + KVI_MDICHILD_SPACING);
+ }
+
+ KviStr tmp(KviStr::Format,"mdi_child_%s",w->name());
+ setName(tmp.ptr());
+}
+
+void KviMdiChild::unsetClient()
+{
+ __range_valid(m_pClient!=0);
+ if(!m_pClient)return;
+ //reparent to desktop widget , no flags , point , show it
+ //unlinkChildren(m_pClient);
+ setFocusProxy(0); //remove the focus proxy...
+ //Kewl...the reparent function has a small prob now..
+ //the new toplelvel widgets gets not reenabled for dnd
+#ifndef Q_OS_MACX
+ m_pClient->reparent(0,m_pClient->mapToGlobal(QPoint(0,0)),true);
+#else
+ QRect r = g_pApp->desktop()->availableGeometry(m_pClient);
+ r.moveBy(0, 22);
+ m_pClient->reparent(0,r.topLeft(),true);
+#endif
+ m_pClient=0;
+ setName("mdi_child");
+}
+
+
+
+void KviMdiChild::activate(bool bSetFocus)
+{
+ if(!m_pCaption->active())m_pCaption->setActive(true);
+ if(m_pManager->topChild() != this)
+ m_pManager->setTopChild(this,bSetFocus);
+ else if(bSetFocus)setFocus();
+}
+
+void KviMdiChild::focusInEvent(QFocusEvent *)
+{
+ // We gained focus by click , tab or from the caption label
+ // Bring this child to top
+ m_pCaption->setActive(true);
+ m_pManager->setTopChild(this,false); //Do not focus by now...
+ /*The client is our focusProxy ! it should be focused by Qt !*/
+#ifdef _KVI_DEBUG_CLASS_NAME_
+ __range_valid(focusProxy() == m_pClient);
+#endif
+}
+
+QSize KviMdiChild::sizeHint()
+{
+ if(m_pClient)
+ {
+ QSize s = m_pClient->sizeHint();
+ QSize ret(s.width() + (KVI_MDICHILD_BORDER << 1),
+ s.height() + (KVI_MDICHILD_BORDER << 1) + KVI_MDICHILD_SPACING + m_pCaption->heightHint());
+ return ret;
+ }
+ return QFrame::sizeHint();
+}
+
+
diff --git a/src/kvirc/ui/kvi_mdichild.h b/src/kvirc/ui/kvi_mdichild.h
new file mode 100644
index 00000000..7915a3bb
--- /dev/null
+++ b/src/kvirc/ui/kvi_mdichild.h
@@ -0,0 +1,122 @@
+#ifndef _KVI_MDICHILD_H_
+#define _KVI_MDICHILD_H_
+//=================================================================================================
+//
+// File : kvi_mdichild.h
+// Creation date : Wed Jun 21 2000 17:35:04 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=================================================================================================
+
+#include "kvi_settings.h"
+#include "kvi_string.h"
+
+#include <qframe.h>
+#include <qtoolbutton.h>
+#include <qlabel.h>
+
+
+class KviMdiManager;
+class KviMdiChild;
+class KviMdiCaption;
+
+class QCursor;
+
+
+
+class KVIRC_API KviMdiChild : public QFrame
+{
+ friend class KviMdiManager;
+ friend class KviMdiCaption;
+ Q_OBJECT
+public:
+ KviMdiChild(KviMdiManager* par,const char * name = 0);
+ ~KviMdiChild();
+public:
+ enum MdiChildState { Maximized , Minimized , Normal };
+protected:
+ KviMdiManager * m_pManager;
+ KviMdiCaption * m_pCaption;
+private:
+ int m_iResizeCorner;
+ int m_iLastCursorCorner;
+ bool m_bResizeMode;
+ QWidget * m_pClient;
+ MdiChildState m_state;
+ QRect m_restoredGeometry;
+
+ QString m_szXmlActiveCaption;
+ QString m_szXmlInactiveCaption;
+ QString m_szPlainCaption;
+public:
+ QRect restoredGeometry();
+ void setRestoredGeometry(const QRect &r){ m_restoredGeometry = r; };
+ void setClient(QWidget * w);
+ QWidget * client(){ return m_pClient; };
+ void unsetClient();
+ KviMdiCaption * captionLabel(){ return m_pCaption; };
+ MdiChildState state(){ return m_state; };
+ const QString & plainCaption(){ return m_szPlainCaption; };
+ const QString & xmlActiveCaption(){ return m_szXmlActiveCaption; };
+ const QString & xmlInactiveCaption(){ return m_szXmlInactiveCaption; };
+ void setCaption(const QString & plain,const QString & xmlActive,const QString & xmlInactive);
+ virtual QSize sizeHint();
+ void setIcon(const QPixmap &pix);
+ const QPixmap * icon();
+ void enableClose(bool bEnable);
+ bool closeEnabled();
+ KviMdiManager * manager(){ return m_pManager; };
+ void activate(bool bSetFocus);
+ void reloadImages();
+public slots:
+ void maximize();
+ void minimize();
+ void restore();
+ void systemPopupSlot();
+ void closeRequest();
+signals:
+ void systemPopupRequest(const QPoint & pnt);
+protected:
+#ifdef COMPILE_USE_QT4
+ virtual void setBackgroundRole(QPalette::ColorRole);
+#else
+ virtual void setBackgroundMode(QWidget::BackgroundMode bgmd);
+#endif
+ virtual void resizeEvent(QResizeEvent *e);
+ virtual void mousePressEvent(QMouseEvent *e);
+ virtual void mouseMoveEvent(QMouseEvent *e);
+ virtual void mouseReleaseEvent(QMouseEvent *e);
+ virtual void leaveEvent(QEvent *e);
+ virtual void focusInEvent(QFocusEvent *);
+ virtual void moveEvent(QMoveEvent *e);
+// bool eventFilter(QObject *o,QEvent *e);
+ void emitSystemPopupRequest(const QPoint & pnt){ emit systemPopupRequest(pnt); };
+private:
+// void linkChildren(QWidget *w);
+// void unlinkChildren(QWidget *w);
+ QCursor getResizeCursor(int resizeCorner);
+ void resizeWindowOpaque(int resizeCorner);
+ int getResizeCorner(int ax,int ay);
+ void calculateMinimumSize(int &minWidth,int &minHeight);
+ void setResizeCursor(int resizeCorner);
+ void calculateResizeRect(int resizeCorner,QPoint mousePos,QRect &resizeRect,int minWidth,int minHeight);
+};
+
+
+#endif //_KVI_MDICHILD_H_
diff --git a/src/kvirc/ui/kvi_mdimanager.cpp b/src/kvirc/ui/kvi_mdimanager.cpp
new file mode 100644
index 00000000..feddca11
--- /dev/null
+++ b/src/kvirc/ui/kvi_mdimanager.cpp
@@ -0,0 +1,1126 @@
+//=============================================================================
+//
+// File : kvi_mdimanager.cpp
+// Creation date : Wed Jun 21 2000 17:28:04 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_debug.h"
+#include "kvi_settings.h"
+#include "kvi_mdimanager.h"
+#include "kvi_mdichild.h"
+#include "kvi_locale.h"
+#include "kvi_options.h"
+#include "kvi_iconmanager.h"
+#include "kvi_frame.h"
+#include "kvi_menubar.h"
+#include "kvi_mdicaption.h"
+#include "kvi_app.h"
+
+#include "kvi_tal_popupmenu.h"
+#include <qmenubar.h>
+#include <qlayout.h>
+#include <qpainter.h>
+#include <math.h>
+#include <qcursor.h>
+#include <qdrawutil.h>
+#include <qevent.h>
+
+#ifdef COMPILE_USE_QT4
+ #include "kvi_tal_hbox.h"
+#endif
+
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ #include <qpixmap.h>
+ extern QPixmap * g_pShadedParentGlobalDesktopBackground;
+#endif
+
+
+
+
+KviMdiManager::KviMdiManager(QWidget * parent,KviFrame * pFrm,const char * name)
+: KviTalScrollView(parent)
+{
+ setFrameShape(NoFrame);
+ m_pZ = new KviPointerList<KviMdiChild>;
+ m_pZ->setAutoDelete(true);
+
+ m_pFrm = pFrm;
+
+ m_iSdiIconItemId = 0;
+ m_iSdiCloseItemId = 0;
+ m_iSdiRestoreItemId = 0;
+ m_iSdiMinimizeItemId = 0;
+ m_pSdiIconButton = 0;
+ m_pSdiCloseButton = 0;
+ m_pSdiRestoreButton = 0;
+ m_pSdiMinimizeButton = 0;
+#ifdef COMPILE_USE_QT4
+ m_pSdiControls = 0;
+#endif
+
+ m_pWindowPopup = new KviTalPopupMenu(this);
+ connect(m_pWindowPopup,SIGNAL(activated(int)),this,SLOT(menuActivated(int)));
+ connect(m_pWindowPopup,SIGNAL(aboutToShow()),this,SLOT(fillWindowPopup()));
+ m_pTileMethodPopup = new KviTalPopupMenu(this);
+ connect(m_pTileMethodPopup,SIGNAL(activated(int)),this,SLOT(tileMethodMenuActivated(int)));
+
+#ifdef COMPILE_USE_QT4
+ viewport()->setAutoFillBackground(false);
+#else
+ viewport()->setBackgroundMode(QWidget::NoBackground);
+#endif
+ setStaticBackground(true);
+ resizeContents(width(),height());
+
+#ifdef COMPILE_USE_QT4
+ setFocusPolicy(Qt::NoFocus);
+ viewport()->setFocusPolicy(Qt::NoFocus);
+#else
+ setFocusPolicy(QWidget::NoFocus);
+ viewport()->setFocusPolicy(QWidget::NoFocus);
+#endif
+
+ connect(g_pApp,SIGNAL(reloadImages()),this,SLOT(reloadImages()));
+}
+
+KviMdiManager::~KviMdiManager()
+{
+ delete m_pZ;
+}
+
+void KviMdiManager::reloadImages()
+{
+ for(KviMdiChild * c = m_pZ->first();c;c = m_pZ->next())
+ {
+ c->reloadImages();
+ }
+}
+
+bool KviMdiManager::focusNextPrevChild(bool bNext)
+{
+ //bug("FFFFFF");
+ // this is a QScrollView bug... it doesn't pass this
+ // event to the toplevel window
+ return m_pFrm->focusNextPrevChild(bNext);
+}
+
+void KviMdiManager::drawContents(QPainter *p,int x,int y,int w,int h)
+{
+ //debug("MY DRAW CONTENTS (%d,%d,%d,%d)",x,y,w,h);
+ QRect r(x,y,w,h);
+
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ if(g_pShadedParentGlobalDesktopBackground)
+ {
+ QPoint pnt = viewport()->mapToGlobal(contentsToViewport(r.topLeft()));
+ p->drawTiledPixmap(r,*(g_pShadedParentGlobalDesktopBackground),pnt);
+ return;
+ }
+#endif
+
+ if(KVI_OPTION_PIXMAP(KviOption_pixmapMdiBackground).pixmap())
+ {
+ p->drawTiledPixmap(r,*(KVI_OPTION_PIXMAP(KviOption_pixmapMdiBackground).pixmap()));
+ } else {
+ p->fillRect(r,KVI_OPTION_COLOR(KviOption_colorMdiBackground));
+ }
+}
+
+void KviMdiManager::manageChild(KviMdiChild * lpC,bool bCascade,QRect *setGeom)
+{
+ __range_valid(lpC);
+
+ m_pZ->insert(0,lpC); //hidden -> last in the Z order
+
+ if(bCascade)
+ {
+ QPoint p = getCascadePoint(m_pZ->count()-1);
+ addChild(lpC,p.x(),p.y());
+ } else {
+ // FIXME: is this right ?
+ QPoint p = lpC->pos();
+ if(p.x() < 0)p.setX(0);
+ if(p.y() < 0)p.setY(0);
+ addChild(lpC,p.x(),p.y());
+
+ if(setGeom)
+ {
+ if(setGeom->left() < 0)setGeom->setLeft(0);
+ if(setGeom->top() < 0)setGeom->setTop(0);
+ moveChild(lpC,setGeom->x(),setGeom->y());
+ lpC->setGeometry(*setGeom);
+ }
+ }
+
+ if(KVI_OPTION_BOOL(KviOption_boolAutoTileWindows))tile();
+}
+
+void KviMdiManager::showAndActivate(KviMdiChild * lpC)
+{
+ lpC->show();
+ setTopChild(lpC,true);
+ if(KVI_OPTION_BOOL(KviOption_boolAutoTileWindows))tile();
+}
+
+void KviMdiManager::setTopChild(KviMdiChild *lpC,bool bSetFocus)
+{
+ __range_valid(lpC);
+ // The following check fails safely at startup....
+ // __range_valid(lpC->isVisible() || lpC->testWState(WState_ForceHide));
+
+ KviMdiChild * pOldTop = m_pZ->last();
+ if(pOldTop != lpC)
+ {
+ m_pZ->setAutoDelete(false);
+
+ if(!m_pZ->removeRef(lpC))
+ {
+ m_pZ->setAutoDelete(true);
+ return; // no such child ?
+ }
+
+ // disable the labels of all the other children
+ //for(KviMdiChild *pC=m_pZ->first();pC;pC=m_pZ->next())
+ //{
+ // pC->captionLabel()->setActive(false);
+ //}
+ KviMdiChild * pMaximizedChild = pOldTop;
+ if(pOldTop)
+ {
+ pOldTop->captionLabel()->setActive(false);
+ if(pOldTop->m_state != KviMdiChild::Maximized)pMaximizedChild=0;
+ }
+
+ m_pZ->setAutoDelete(true);
+ m_pZ->append(lpC);
+
+ if(pMaximizedChild)lpC->maximize(); //do not animate the change
+ lpC->raise();
+ if(pMaximizedChild)pMaximizedChild->restore();
+ }
+
+ if(bSetFocus)
+ {
+ if(!lpC->hasFocus())
+ {
+ lpC->setFocus();
+ /*
+ if(topLevelWidget()->isActiveWindow())
+ {
+
+ }
+ */
+ }
+ }
+}
+
+void KviMdiManager::focusInEvent(QFocusEvent *)
+{
+ focusTopChild();
+}
+
+void KviMdiManager::destroyChild(KviMdiChild *lpC,bool bFocusTopChild)
+{
+ bool bWasMaximized = lpC->state() == KviMdiChild::Maximized;
+ disconnect(lpC);
+ lpC->blockSignals(true);
+#ifdef _KVI_DEBUG_CHECK_RANGE_
+ //Report invalid results in a debug session
+ __range_valid(m_pZ->removeRef(lpC));
+#else
+ m_pZ->removeRef(lpC);
+#endif
+ if(bWasMaximized)
+ {
+ KviMdiChild * c=topChild();
+ if(c)
+ {
+ if(c->state() != KviMdiChild::Minimized)c->maximize();
+ else {
+ // minimized top child...the last one
+ leaveSDIMode();
+ }
+ } else {
+ // SDI state change
+ leaveSDIMode();
+ }
+ }
+ if(bFocusTopChild)focusTopChild();
+
+ if(KVI_OPTION_BOOL(KviOption_boolAutoTileWindows))tile();
+ updateContentsSize();
+}
+
+KviMdiChild * KviMdiManager::highestChildExcluding(KviMdiChild * pChild)
+{
+ KviMdiChild * c = m_pZ->last();
+ while(c && (c == pChild))c = m_pZ->prev();
+ return c;
+}
+
+QPoint KviMdiManager::getCascadePoint(int indexOfWindow)
+{
+ QPoint pnt(0,0);
+ if(indexOfWindow==0)return pnt;
+ KviMdiChild *lpC=m_pZ->first();
+ int step=(lpC ? (lpC->captionLabel()->heightHint()+KVI_MDICHILD_BORDER) : 20);
+ int availableHeight=viewport()->height()-(lpC ? lpC->minimumSize().height() : KVI_MDICHILD_MIN_HEIGHT);
+ int availableWidth=viewport()->width()-(lpC ? lpC->minimumSize().width() : KVI_MDICHILD_MIN_WIDTH);
+ int ax=0;
+ int ay=0;
+ for(int i=0;i<indexOfWindow;i++)
+ {
+ ax+=step;
+ ay+=step;
+ if(ax>availableWidth)ax=0;
+ if(ay>availableHeight)ay=0;
+ }
+ pnt.setX(ax);
+ pnt.setY(ay);
+ return pnt;
+}
+
+void KviMdiManager::mousePressEvent(QMouseEvent *e)
+{
+ //Popup the window menu
+ if(e->button() & Qt::RightButton)m_pWindowPopup->popup(mapToGlobal(e->pos()));
+}
+
+void KviMdiManager::childMoved(KviMdiChild *)
+{
+ updateContentsSize();
+}
+
+void KviMdiManager::maximizeChild(KviMdiChild * lpC)
+{
+ // the children must be moved once by the means of QScrollView::moveChild()
+ // so the QScrollView internal structures get updated with the negative
+ // position of the widget, otherwise, when restoring with moveChild()
+ // it will refuse to move it back to the original position
+ resizeContents(visibleWidth(),visibleHeight());
+ updateScrollBars();
+ g_pApp->sendPostedEvents();
+ if(g_pApp->closingDown())return;
+
+ moveChild(lpC,-KVI_MDICHILD_HIDDEN_EDGE,
+ -(KVI_MDICHILD_HIDDEN_EDGE + KVI_MDICHILD_SPACING + lpC->m_pCaption->heightHint()));
+
+ lpC->setGeometry(
+ -KVI_MDICHILD_HIDDEN_EDGE,
+ -(KVI_MDICHILD_HIDDEN_EDGE + KVI_MDICHILD_SPACING + lpC->m_pCaption->heightHint()),
+ viewport()->width() + (KVI_MDICHILD_HIDDEN_EDGE * 2), //KVI_MDICHILD_DOUBLE_HIDDEN_EDGE,
+ viewport()->height() + (KVI_MDICHILD_HIDDEN_EDGE * 2) + lpC->m_pCaption->heightHint() + KVI_MDICHILD_SPACING);
+
+ if(isInSDIMode())updateSDIMode();
+ else {
+ enterSDIMode(lpC);
+ // make sure that the child is focused
+ lpC->setFocus();
+ }
+
+ // fixme: we could hide all the other children now!
+}
+
+
+
+void KviMdiManager::resizeEvent(QResizeEvent *e)
+{
+ //If we have a maximized children at the top , adjust its size
+ KviTalScrollView::resizeEvent(e);
+ KviMdiChild *lpC=m_pZ->last();
+ if(lpC)
+ {
+ if(lpC->state()==KviMdiChild::Maximized)
+ {
+ // SDI mode
+ lpC->resize(viewport()->width() + (KVI_MDICHILD_HIDDEN_EDGE * 2),
+ viewport()->height() + lpC->m_pCaption->heightHint() + (KVI_MDICHILD_HIDDEN_EDGE * 2) + KVI_MDICHILD_SPACING);
+ return;
+ } else {
+ if(KVI_OPTION_BOOL(KviOption_boolAutoTileWindows))tile();
+ }
+ }
+ updateContentsSize();
+}
+
+
+/*
+void KviMdiManager::childMaximized(KviMdiChild * lpC)
+{
+ if(lpC == m_pZ->last())
+ {
+ enterSDIMode(lpC);
+ }
+ updateContentsSize();
+}
+*/
+
+void KviMdiManager::childMinimized(KviMdiChild * lpC,bool bWasMaximized)
+{
+ __range_valid(lpC);
+ if(m_pZ->findRef(lpC) == -1)return;
+ if(m_pZ->count() > 1)
+ {
+ m_pZ->setAutoDelete(false);
+#ifdef _KVI_DEBUG_CHECK_RANGE_
+ //Report invalid results in a debug session
+ __range_valid(m_pZ->removeRef(lpC));
+#else
+ m_pZ->removeRef(lpC);
+#endif
+ m_pZ->setAutoDelete(true);
+ m_pZ->insert(0,lpC);
+ if(bWasMaximized)
+ {
+ // Need to maximize the top child
+ lpC = m_pZ->last();
+ if(!lpC)return; //??
+ if(lpC->state()==KviMdiChild::Minimized)
+ {
+ if(bWasMaximized)leaveSDIMode();
+ return;
+ }
+ lpC->maximize(); //do nrot animate the change
+ } else {
+ if(KVI_OPTION_BOOL(KviOption_boolAutoTileWindows))tile();
+ }
+ focusTopChild();
+ } else {
+ // Unique window minimized...it won't loose the focus...!!
+ setFocus(); //Remove focus from the child
+ if(bWasMaximized)leaveSDIMode();
+ }
+ updateContentsSize();
+}
+
+void KviMdiManager::childRestored(KviMdiChild * lpC,bool bWasMaximized)
+{
+ if(bWasMaximized)
+ {
+ if(lpC != m_pZ->last())return; // do nothing in this case
+ leaveSDIMode();
+ updateContentsSize();
+ }
+ if(KVI_OPTION_BOOL(KviOption_boolAutoTileWindows))tile();
+}
+
+void KviMdiManager::focusTopChild()
+{
+ KviMdiChild *lpC=m_pZ->last();
+ if(!lpC)return;
+ if(!lpC->isVisible())return;
+ // if(lpC->state()==KviMdiChild::Minimized)return;
+ // debug("Focusing top child %s",lpC->name());
+ //disable the labels of all the other children
+ for(KviMdiChild *pC=m_pZ->first();pC;pC=m_pZ->next())
+ {
+ if(pC != lpC)
+ pC->captionLabel()->setActive(false);
+ }
+ lpC->raise();
+ if(!lpC->hasFocus())lpC->setFocus();
+}
+
+void KviMdiManager::minimizeActiveChild()
+{
+ KviMdiChild * lpC = m_pZ->last();
+ if(!lpC)return;
+ if(lpC->state() != KviMdiChild::Minimized)lpC->minimize();
+}
+
+void KviMdiManager::restoreActiveChild()
+{
+ KviMdiChild * lpC = m_pZ->last();
+ if(!lpC)return;
+ if(lpC->state() == KviMdiChild::Maximized)lpC->restore();
+}
+
+void KviMdiManager::closeActiveChild()
+{
+ KviMdiChild * lpC = m_pZ->last();
+ if(!lpC)return;
+ lpC->closeRequest();
+}
+
+void KviMdiManager::updateContentsSize()
+{
+ KviMdiChild * c = m_pZ->last();
+ if(c)
+ {
+ if(c->state() == KviMdiChild::Maximized)
+ {
+ return;
+ }
+ }
+
+ int fw = frameWidth() * 2;
+ int mx = width() - fw;
+ int my = height() - fw;
+
+ for(c = m_pZ->first();c;c = m_pZ->next())
+ {
+ if(c->isVisible())
+ {
+ int x = childX(c) + c->width();
+ if(x > mx)mx = x;
+ int y = childY(c) + c->height();
+ if(y > my)my = y;
+ }
+ }
+
+ resizeContents(mx,my);
+}
+
+
+void KviMdiManager::updateSDIMode()
+{
+
+ KviMdiChild * lpC = m_pZ->last();
+
+ if(m_pSdiCloseButton)
+ m_pSdiCloseButton->setEnabled(lpC ? lpC->closeEnabled() : false);
+
+// This would result in an addictional main menu bar entry on MacOSX which would trigger a popup menu and not
+// a submenu. Due to the optical reasons it is removed here.
+// The same popup is triggered by right clicking on the window name in the channel window list.
+#ifndef Q_OS_MACX
+ KviMenuBar * b = m_pFrm->mainMenuBar();
+
+ const QPixmap * pix = lpC ? lpC->icon() : 0;
+ if(!pix)pix = g_pIconManager->getSmallIcon(KVI_SMALLICON_NONE);
+ else if(pix->isNull())pix = g_pIconManager->getSmallIcon(KVI_SMALLICON_NONE);
+
+ if(!m_pSdiIconButton)
+ {
+ m_pSdiIconButton = new KviMenuBarToolButton(b,*pix,"nonne");
+ connect(m_pSdiIconButton,SIGNAL(clicked()),this,SLOT(activeChildSystemPopup()));
+#ifdef COMPILE_USE_QT4
+ // This is an obscure, undocumented and internal function in QT4 QMenuBar
+ // I won't be surprised if this disappears....
+ b->setCornerWidget(m_pSdiIconButton,Qt::TopLeftCorner);
+ m_pSdiIconButton->show();
+#else
+ m_iSdiIconItemId = b->insertItem(m_pSdiIconButton,-1,0);
+#endif
+ connect(m_pSdiIconButton,SIGNAL(destroyed()),this,SLOT(sdiIconButtonDestroyed()));
+ } else {
+ m_pSdiIconButton->setPixmap(*pix);
+ }
+#endif //Q_OS_MACX
+}
+
+void KviMdiManager::activeChildSystemPopup()
+{
+ KviMdiChild * lpC = m_pZ->last();
+ if(!lpC)return;
+ QPoint pnt;
+ if(m_pSdiIconButton)
+ {
+ pnt = m_pSdiIconButton->mapToGlobal(QPoint(0,m_pSdiIconButton->height()));
+ } else {
+ pnt = QCursor::pos();
+ }
+ lpC->emitSystemPopupRequest(pnt);
+}
+
+bool KviMdiManager::isInSDIMode()
+{
+ return (m_pSdiCloseButton != 0);
+}
+
+
+void KviMdiManager::enterSDIMode(KviMdiChild *lpC)
+{
+ if(!m_pSdiCloseButton)
+ {
+ KviMenuBar * b = m_pFrm->mainMenuBar();
+
+ QWidget * pButtonParent;
+
+#ifdef COMPILE_USE_QT4
+ m_pSdiControls = new KviTalHBox(b);
+ m_pSdiControls->setMargin(0);
+ m_pSdiControls->setSpacing(2);
+ m_pSdiControls->setAutoFillBackground(false);
+ pButtonParent = m_pSdiControls;
+#else
+ pButtonParent = b;
+#endif
+ m_pSdiMinimizeButton = new KviMenuBarToolButton(pButtonParent,*(g_pIconManager->getSmallIcon(KVI_SMALLICON_MINIMIZE)),"btnminimize");
+ connect(m_pSdiMinimizeButton,SIGNAL(clicked()),this,SLOT(minimizeActiveChild()));
+#ifndef COMPILE_USE_QT4
+ m_iSdiMinimizeItemId = b->insertItem(m_pSdiMinimizeButton,-1,b->count());
+#endif
+ connect(m_pSdiMinimizeButton,SIGNAL(destroyed()),this,SLOT(sdiMinimizeButtonDestroyed()));
+
+ m_pSdiRestoreButton = new KviMenuBarToolButton(pButtonParent,*(g_pIconManager->getSmallIcon(KVI_SMALLICON_RESTORE)),"btnrestore");
+ connect(m_pSdiRestoreButton,SIGNAL(clicked()),this,SLOT(restoreActiveChild()));
+#ifndef COMPILE_USE_QT4
+ m_iSdiRestoreItemId = b->insertItem(m_pSdiRestoreButton,-1,b->count());
+#endif
+ connect(m_pSdiRestoreButton,SIGNAL(destroyed()),this,SLOT(sdiRestoreButtonDestroyed()));
+
+ m_pSdiCloseButton = new KviMenuBarToolButton(pButtonParent,*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CLOSE)),"btnclose");
+ connect(m_pSdiCloseButton,SIGNAL(clicked()),this,SLOT(closeActiveChild()));
+#ifndef COMPILE_USE_QT4
+ m_iSdiCloseItemId = b->insertItem(m_pSdiCloseButton,-1,b->count());
+#endif
+ connect(m_pSdiCloseButton,SIGNAL(destroyed()),this,SLOT(sdiCloseButtonDestroyed()));
+
+#ifdef COMPILE_USE_QT4
+ // This is an obscure, undocumented and internal function in QT4 QMenuBar
+ // I won't be surprised if this disappears....
+ b->setCornerWidget(m_pSdiControls,Qt::TopRightCorner);
+ // The show below SHOULD force a re-layout of the menubar..
+ // but it doesn't work when the KviFrame is still hidden (at startup)
+ // We handle this BUG in showEvent()
+ m_pSdiControls->show();
+#else
+ m_pSdiRestoreButton->show();
+ m_pSdiMinimizeButton->show();
+ m_pSdiCloseButton->show();
+#endif
+ emit enteredSdiMode();
+
+ setVScrollBarMode(KviTalScrollView::AlwaysOff);
+ setHScrollBarMode(KviTalScrollView::AlwaysOff);
+ }
+
+ updateSDIMode();
+}
+void KviMdiManager::relayoutMenuButtons()
+{
+#ifdef COMPILE_USE_QT4
+ // force a re-layout of the menubar in Qt4 (see the note in enterSDIMode())
+ // by resetting the corner widget
+ if(m_pSdiControls)
+ {
+ m_pFrm->mainMenuBar()->setCornerWidget(0,Qt::TopRightCorner);
+ m_pFrm->mainMenuBar()->setCornerWidget(m_pSdiControls,Qt::TopRightCorner);
+ }
+ // also force an activation of the top MdiChild since it probably didn't get it yet
+ KviMdiChild * c = topChild();
+ if(c)
+ c->activate(false);
+#endif
+}
+
+
+void KviMdiManager::sdiIconButtonDestroyed()
+{
+ m_iSdiIconItemId = 0;
+ m_pSdiIconButton = 0;
+}
+
+void KviMdiManager::sdiMinimizeButtonDestroyed()
+{
+ m_iSdiMinimizeItemId = 0;
+ m_pSdiMinimizeButton = 0;
+}
+
+void KviMdiManager::sdiRestoreButtonDestroyed()
+{
+ m_iSdiRestoreItemId = 0;
+ m_pSdiRestoreButton = 0;
+}
+
+void KviMdiManager::sdiCloseButtonDestroyed()
+{
+ m_iSdiCloseItemId = 0;
+ m_pSdiCloseButton = 0;
+}
+
+void KviMdiManager::leaveSDIMode()
+{
+ __range_valid(m_pSdiCloseButton);
+
+#ifdef COMPILE_USE_QT4
+ if(m_pSdiControls)
+ {
+ delete m_pSdiControls;
+ m_pSdiControls = 0;
+ }
+ if(m_pSdiIconButton)
+ {
+ m_pSdiIconButton->hide(); // this will force a QMenuBar relayout
+ delete m_pSdiIconButton;
+ m_pSdiIconButton = 0;
+ }
+#else
+ if(m_iSdiIconItemId != 0)m_pFrm->mainMenuBar()->removeItem(m_iSdiIconItemId);
+ if(m_iSdiCloseItemId != 0)m_pFrm->mainMenuBar()->removeItem(m_iSdiCloseItemId);
+ if(m_iSdiRestoreItemId != 0)m_pFrm->mainMenuBar()->removeItem(m_iSdiRestoreItemId);
+ if(m_iSdiMinimizeItemId != 0)m_pFrm->mainMenuBar()->removeItem(m_iSdiMinimizeItemId);
+#endif
+
+ setVScrollBarMode(KviTalScrollView::Auto);
+ setHScrollBarMode(KviTalScrollView::Auto);
+
+ emit leftSdiMode();
+}
+
+#define KVI_TILE_METHOD_ANODINE 0
+#define KVI_TILE_METHOD_PRAGMA4HOR 1
+#define KVI_TILE_METHOD_PRAGMA4VER 2
+#define KVI_TILE_METHOD_PRAGMA6HOR 3
+#define KVI_TILE_METHOD_PRAGMA6VER 4
+#define KVI_TILE_METHOD_PRAGMA9HOR 5
+#define KVI_TILE_METHOD_PRAGMA9VER 6
+
+#define KVI_NUM_TILE_METHODS 7
+
+void KviMdiManager::fillWindowPopup()
+{
+ m_pWindowPopup->clear();
+
+ m_pWindowPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CASCADEWINDOWS)),(__tr2qs("&Cascade Windows")),this,SLOT(cascadeWindows()));
+ m_pWindowPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CASCADEWINDOWS)),(__tr2qs("Cascade &Maximized")),this,SLOT(cascadeMaximized()));
+
+ m_pWindowPopup->insertSeparator();
+ m_pWindowPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TILEWINDOWS)),(__tr2qs("&Tile Windows")),this,SLOT(tile()));
+
+ m_pTileMethodPopup->clear();
+ int id = m_pTileMethodPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_AUTOTILEWINDOWS)),(__tr2qs("&Auto Tile")),this,SLOT(toggleAutoTile()));
+ m_pTileMethodPopup->setItemChecked(id,KVI_OPTION_BOOL(KviOption_boolAutoTileWindows));
+ m_pTileMethodPopup->setItemParameter(id,-1);
+ m_pTileMethodPopup->insertSeparator();
+ int ids[KVI_NUM_TILE_METHODS];
+ ids[KVI_TILE_METHOD_ANODINE] = m_pTileMethodPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TILEWINDOWS)),(__tr2qs("Anodine's Full Grid")));
+ m_pTileMethodPopup->setItemParameter(ids[KVI_TILE_METHOD_ANODINE],KVI_TILE_METHOD_ANODINE);
+ ids[KVI_TILE_METHOD_PRAGMA4HOR] = m_pTileMethodPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TILEWINDOWS)),(__tr2qs("Pragma's Horizontal 4-Grid")));
+ m_pTileMethodPopup->setItemParameter(ids[KVI_TILE_METHOD_PRAGMA4HOR],KVI_TILE_METHOD_PRAGMA4HOR);
+ ids[KVI_TILE_METHOD_PRAGMA4VER] = m_pTileMethodPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TILEWINDOWS)),(__tr2qs("Pragma's Vertical 4-Grid")));
+ m_pTileMethodPopup->setItemParameter(ids[KVI_TILE_METHOD_PRAGMA4VER],KVI_TILE_METHOD_PRAGMA4VER);
+ ids[KVI_TILE_METHOD_PRAGMA6HOR] = m_pTileMethodPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TILEWINDOWS)),(__tr2qs("Pragma's Horizontal 6-Grid")));
+ m_pTileMethodPopup->setItemParameter(ids[KVI_TILE_METHOD_PRAGMA6HOR],KVI_TILE_METHOD_PRAGMA6HOR);
+ ids[KVI_TILE_METHOD_PRAGMA6VER] = m_pTileMethodPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TILEWINDOWS)),(__tr2qs("Pragma's Vertical 6-Grid")));
+ m_pTileMethodPopup->setItemParameter(ids[KVI_TILE_METHOD_PRAGMA6VER],KVI_TILE_METHOD_PRAGMA6VER);
+ ids[KVI_TILE_METHOD_PRAGMA9HOR] = m_pTileMethodPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TILEWINDOWS)),(__tr2qs("Pragma's Horizontal 9-Grid")));
+ m_pTileMethodPopup->setItemParameter(ids[KVI_TILE_METHOD_PRAGMA9HOR],KVI_TILE_METHOD_PRAGMA9HOR);
+ ids[KVI_TILE_METHOD_PRAGMA9VER] = m_pTileMethodPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TILEWINDOWS)),(__tr2qs("Pragma's Vertical 9-Grid")));
+ m_pTileMethodPopup->setItemParameter(ids[KVI_TILE_METHOD_PRAGMA9VER],KVI_TILE_METHOD_PRAGMA9VER);
+
+ if(KVI_OPTION_UINT(KviOption_uintTileMethod) >= KVI_NUM_TILE_METHODS)KVI_OPTION_UINT(KviOption_uintTileMethod) = KVI_TILE_METHOD_PRAGMA9HOR;
+ m_pTileMethodPopup->setItemChecked(ids[KVI_OPTION_UINT(KviOption_uintTileMethod)],true);
+
+ m_pWindowPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TILEWINDOWS)),(__tr2qs("Tile Met&hod")),m_pTileMethodPopup);
+
+ m_pWindowPopup->insertSeparator();
+ m_pWindowPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_MAXVERTICAL)),(__tr2qs("Expand &Vertically")),this,SLOT(expandVertical()));
+ m_pWindowPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_MAXHORIZONTAL)),(__tr2qs("Expand &Horizontally")),this,SLOT(expandHorizontal()));
+
+ m_pWindowPopup->insertSeparator();
+ m_pWindowPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_MINIMIZE)),(__tr2qs("Mi&nimize All")),this,SLOT(minimizeAll()));
+// m_pWindowPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_RESTORE)),(__tr2qs("&Restore all")),this,SLOT(restoreAll()));
+//
+ m_pWindowPopup->insertSeparator();
+ int i=100;
+ QString szItem;
+ QString szCaption;
+ for(KviMdiChild *lpC=m_pZ->first();lpC;lpC=m_pZ->next())
+ {
+ szItem.setNum(((uint)i)-99);
+ szItem+=". ";
+
+ szCaption = lpC->plainCaption();
+ if(szCaption.length() > 30)
+ {
+ QString trail = szCaption.right(12);
+ szCaption.truncate(12);
+ szCaption+="...";
+ szCaption+=trail;
+ }
+
+ if(lpC->state()==KviMdiChild::Minimized)
+ {
+ szItem+="(";
+ szItem+=szCaption;
+ szItem+=")";
+ } else szItem+=szCaption;
+ const QPixmap * pix = lpC->icon();
+ if(pix && !(pix->isNull()))m_pWindowPopup->insertItem(*pix,szItem,i);
+ else m_pWindowPopup->insertItem(szItem,i);
+ m_pWindowPopup->setItemChecked(i,((uint)i)==(m_pZ->count()+99));
+ i++;
+ }
+}
+
+void KviMdiManager::menuActivated(int id)
+{
+ if(id<100)return;
+ id-=100;
+ __range_valid(((uint)id) < m_pZ->count());
+ KviMdiChild *lpC=m_pZ->at(id);
+ if(!lpC)return;
+ if(lpC->state()==KviMdiChild::Minimized)lpC->restore();
+ setTopChild(lpC,true);
+}
+
+void KviMdiManager::ensureNoMaximized()
+{
+ KviMdiChild * lpC;
+
+ for(lpC=m_pZ->first();lpC;lpC=m_pZ->next())
+ {
+ if(lpC->state()==KviMdiChild::Maximized)lpC->restore();
+ }
+}
+
+void KviMdiManager::tileMethodMenuActivated(int id)
+{
+ int idx = m_pTileMethodPopup->itemParameter(id);
+ if(idx < 0)idx = 0;
+ if(idx >= KVI_NUM_TILE_METHODS)idx = KVI_TILE_METHOD_PRAGMA9VER;
+ KVI_OPTION_UINT(KviOption_uintTileMethod) = idx;
+ if(KVI_OPTION_BOOL(KviOption_boolAutoTileWindows))tile();
+}
+
+void KviMdiManager::cascadeWindows()
+{
+ ensureNoMaximized();
+ // this hack is needed to ensure that the scrollbars are hidden and the viewport()->width() and height() are correct
+ resizeContents(visibleWidth(),visibleHeight());
+ updateScrollBars();
+ g_pApp->sendPostedEvents();
+ if(g_pApp->closingDown())return;
+
+ int idx=0;
+ KviPointerList<KviMdiChild> list(*m_pZ);
+ list.setAutoDelete(false);
+ while(!list.isEmpty())
+ {
+ KviMdiChild *lpC=list.first();
+ if(lpC->state() != KviMdiChild::Minimized)
+ {
+ QPoint p = getCascadePoint(idx);
+ moveChild(lpC,p.x(),p.y());
+ lpC->resize(lpC->sizeHint());
+ idx++;
+ }
+ list.removeFirst();
+ }
+ focusTopChild();
+ updateContentsSize();
+}
+
+void KviMdiManager::cascadeMaximized()
+{
+ ensureNoMaximized();
+ // this hack is needed to ensure that the scrollbars are hidden and the viewport()->width() and height() are correct
+ resizeContents(visibleWidth(),visibleHeight());
+ updateScrollBars();
+ g_pApp->sendPostedEvents();
+ if(g_pApp->closingDown())return;
+
+ int idx=0;
+ KviPointerList<KviMdiChild> list(*m_pZ);
+
+ list.setAutoDelete(false);
+ while(!list.isEmpty())
+ {
+ KviMdiChild *lpC=list.first();
+ if(lpC->state() != KviMdiChild::Minimized)
+ {
+ QPoint pnt(getCascadePoint(idx));
+ moveChild(lpC,pnt.x(),pnt.y());
+ QSize curSize(viewport()->width() - pnt.x(),viewport()->height() - pnt.y());
+ if((lpC->minimumSize().width() > curSize.width()) ||
+ (lpC->minimumSize().height() > curSize.height()))lpC->resize(lpC->minimumSize());
+ else lpC->resize(curSize);
+ idx++;
+ }
+ list.removeFirst();
+ }
+ focusTopChild();
+ updateContentsSize();
+}
+
+void KviMdiManager::expandVertical()
+{
+ ensureNoMaximized();
+ // this hack is needed to ensure that the scrollbars are hidden and the viewport()->width() and height() are correct
+ resizeContents(visibleWidth(),visibleHeight());
+ updateScrollBars();
+ g_pApp->sendPostedEvents();
+ if(g_pApp->closingDown())return;
+
+ KviPointerList<KviMdiChild> list(*m_pZ);
+ list.setAutoDelete(false);
+ while(!list.isEmpty())
+ {
+ KviMdiChild *lpC=list.first();
+ if(lpC->state() != KviMdiChild::Minimized)
+ {
+ moveChild(lpC,lpC->x(),0);
+ lpC->resize(lpC->width(),viewport()->height());
+ }
+ list.removeFirst();
+ }
+
+ focusTopChild();
+ updateContentsSize();
+}
+
+void KviMdiManager::expandHorizontal()
+{
+ ensureNoMaximized();
+ // this hack is needed to ensure that the scrollbars are hidden and the viewport()->width() and height() are correct
+ resizeContents(visibleWidth(),visibleHeight());
+ updateScrollBars();
+ g_pApp->sendPostedEvents();
+ if(g_pApp->closingDown())return;
+
+ KviPointerList<KviMdiChild> list(*m_pZ);
+ list.setAutoDelete(false);
+ while(!list.isEmpty())
+ {
+ KviMdiChild *lpC=list.first();
+ if(lpC->state() != KviMdiChild::Minimized)
+ {
+ moveChild(lpC,0,lpC->y());
+ lpC->resize(viewport()->width(),lpC->height());
+ }
+ list.removeFirst();
+ }
+ focusTopChild();
+ updateContentsSize();
+}
+
+void KviMdiManager::minimizeAll()
+{
+ KviPointerList<KviMdiChild> list(*m_pZ);
+ list.setAutoDelete(false);
+ m_pFrm->setActiveWindow((KviWindow*)m_pFrm->firstConsole());
+ while(!list.isEmpty())
+ {
+ KviMdiChild *lpC=list.first();
+ if(lpC->state() != KviMdiChild::Minimized)lpC->minimize();
+ list.removeFirst();
+ }
+ focusTopChild();
+ updateContentsSize();
+}
+
+/*
+void KviMdiManager::restoreAll()
+{
+ int idx=0;
+ KviPointerList<KviMdiChild> list(*m_pZ);
+ list.setAutoDelete(false);
+ while(!list.isEmpty())
+ {
+ KviMdiChild *lpC=list.first();
+ if(lpC->state() != KviMdiChild::Normal && (!(lpC->plainCaption()).contains("CONSOLE") ))
+ lpC->restore();
+ list.removeFirst();
+ }
+ focusTopChild();
+ updateContentsSize();
+}
+*/
+
+int KviMdiManager::getVisibleChildCount()
+{
+ int cnt=0;
+ for(KviMdiChild *lpC=m_pZ->first();lpC;lpC=m_pZ->next())
+ {
+ if(lpC->state() != KviMdiChild::Minimized)cnt++;
+ }
+ return cnt;
+}
+
+void KviMdiManager::tile()
+{
+ switch(KVI_OPTION_UINT(KviOption_uintTileMethod))
+ {
+ case KVI_TILE_METHOD_ANODINE: tileAnodine(); break;
+ case KVI_TILE_METHOD_PRAGMA4HOR: tileAllInternal(4,true); break;
+ case KVI_TILE_METHOD_PRAGMA4VER: tileAllInternal(4,false); break;
+ case KVI_TILE_METHOD_PRAGMA6HOR: tileAllInternal(6,true); break;
+ case KVI_TILE_METHOD_PRAGMA6VER: tileAllInternal(6,false); break;
+ case KVI_TILE_METHOD_PRAGMA9HOR: tileAllInternal(9,true); break;
+ case KVI_TILE_METHOD_PRAGMA9VER: tileAllInternal(9,false); break;
+ default:
+ KVI_OPTION_UINT(KviOption_uintTileMethod) = KVI_TILE_METHOD_PRAGMA9HOR;
+ tileAllInternal(9,true);
+ break;
+ }
+}
+
+void KviMdiManager::toggleAutoTile()
+{
+ if(KVI_OPTION_BOOL(KviOption_boolAutoTileWindows))
+ {
+ KVI_OPTION_BOOL(KviOption_boolAutoTileWindows) = false;
+ } else {
+ KVI_OPTION_BOOL(KviOption_boolAutoTileWindows) = true;
+ tile();
+ }
+}
+
+
+void KviMdiManager::tileAllInternal(int maxWnds,bool bHorizontal)
+{
+ //NUM WINDOWS = 1,2,3,4,5,6,7,8,9
+ static int colstable[9]={ 1,1,1,2,2,2,3,3,3 }; //num columns
+ static int rowstable[9]={ 1,2,3,2,3,3,3,3,3 }; //num rows
+ static int lastwindw[9]={ 1,1,1,1,2,1,3,2,1 }; //last window multiplier
+ static int colrecall[9]={ 0,0,0,3,3,3,6,6,6 }; //adjust self
+ static int rowrecall[9]={ 0,0,0,0,4,4,4,4,4 }; //adjust self
+
+ int * pColstable = bHorizontal ? colstable : rowstable;
+ int * pRowstable = bHorizontal ? rowstable : colstable;
+ int * pColrecall = bHorizontal ? colrecall : rowrecall;
+ int * pRowrecall = bHorizontal ? rowrecall : colrecall;
+
+ ensureNoMaximized();
+ // this hack is needed to ensure that the scrollbars are hidden and the viewport()->width() and height() are correct
+ resizeContents(visibleWidth(),visibleHeight());
+ updateScrollBars();
+ g_pApp->sendPostedEvents();
+ if(g_pApp->closingDown())return;
+
+ KviMdiChild *lpTop=topChild();
+ int numVisible=getVisibleChildCount();
+
+ if(numVisible<1)return;
+
+ int numToHandle=((numVisible > maxWnds) ? maxWnds : numVisible);
+ int xQuantum=viewport()->width()/pColstable[numToHandle-1];
+ if(xQuantum < ((lpTop->minimumSize().width() > KVI_MDICHILD_MIN_WIDTH) ? lpTop->minimumSize().width() : KVI_MDICHILD_MIN_WIDTH)){
+ if(pColrecall[numToHandle-1]==0)debug("Tile : Not enouh space");
+ else tileAllInternal(pColrecall[numToHandle-1],bHorizontal);
+ return;
+ }
+ int yQuantum=viewport()->height()/pRowstable[numToHandle-1];
+ if(yQuantum < ((lpTop->minimumSize().height() > KVI_MDICHILD_MIN_HEIGHT) ? lpTop->minimumSize().height() : KVI_MDICHILD_MIN_HEIGHT)){
+ if(pRowrecall[numToHandle-1]==0)debug("Tile : Not enough space");
+ else tileAllInternal(pRowrecall[numToHandle-1],bHorizontal);
+ return;
+ }
+ int curX=0;
+ int curY=0;
+ int curRow=1;
+ int curCol=1;
+ int curWin=1;
+
+ for(KviMdiChild * lpC=m_pZ->first();lpC;lpC=m_pZ->next())
+ {
+ if(lpC->state()!=KviMdiChild::Minimized)
+ {
+ if((curWin%numToHandle)==0)
+ {
+ moveChild(lpC,curX,curY);
+ lpC->resize(xQuantum * lastwindw[numToHandle-1],yQuantum);
+ } else {
+ moveChild(lpC,curX,curY);
+ lpC->resize(xQuantum,yQuantum);
+ }
+ //example : 12 windows : 3 cols 3 rows
+ if(curCol<pColstable[numToHandle-1])
+ { //curCol<3
+ curX+=xQuantum; //add a column in the same row
+ curCol++; //increase current column
+ } else {
+ curX=0; //new row
+ curCol=1; //column 1
+ if(curRow<pRowstable[numToHandle-1])
+ { //curRow<3
+ curY+=yQuantum; //add a row
+ curRow++; //
+ } else {
+ curY=0; //restart from beginning
+ curRow=1; //
+ }
+ }
+ curWin++;
+ }
+ }
+ if(lpTop)lpTop->setFocus();
+ updateContentsSize();
+}
+
+void KviMdiManager::tileAnodine()
+{
+ ensureNoMaximized();
+ // this hack is needed to ensure that the scrollbars are hidden and the viewport()->width() and height() are correct
+ resizeContents(visibleWidth(),visibleHeight());
+ updateScrollBars();
+ g_pApp->sendPostedEvents();
+ if(g_pApp->closingDown())return;
+
+ KviMdiChild *lpTop=topChild();
+ int numVisible=getVisibleChildCount(); // count visible windows
+ if(numVisible<1)return;
+ int numCols=int(sqrt((double)numVisible)); // set columns to square root of visible count
+ // create an array to form grid layout
+ int *numRows=new int[numCols];
+ int numCurCol=0;
+ while(numCurCol<numCols)
+ {
+ numRows[numCurCol]=numCols; // create primary grid values
+ numCurCol++;
+ }
+ int numDiff=numVisible-(numCols*numCols); // count extra rows
+ int numCurDiffCol=numCols; // set column limiting for grid updates
+ while(numDiff>0)
+ {
+ numCurDiffCol--;
+ numRows[numCurDiffCol]++; // add extra rows to column grid
+ if(numCurDiffCol<1)numCurDiffCol=numCols; // rotate through the grid
+ numDiff--;
+ }
+ numCurCol=0;
+ int numCurRow=0;
+ int curX=0;
+ int curY=0;
+ // the following code will size everything based on my grid above
+ // there is no limit to the number of windows it will handle
+ // it's great when a kick-ass theory works!!! // Pragma :)
+ int xQuantum=viewport()->width()/numCols;
+ int yQuantum=viewport()->height()/numRows[numCurCol];
+
+ for(KviMdiChild * lpC=m_pZ->first();lpC;lpC=m_pZ->next())
+ {
+ if(lpC->state() != KviMdiChild::Minimized)
+ {
+ moveChild(lpC,curX,curY);
+ lpC->resize(xQuantum,yQuantum);
+ numCurRow++;
+ curY+=yQuantum;
+ if(numCurRow==numRows[numCurCol])
+ {
+ numCurRow=0;
+ numCurCol++;
+ curY=0;
+ curX+=xQuantum;
+ if(numCurCol!=numCols)yQuantum=viewport()->height()/numRows[numCurCol];
+ }
+ }
+ }
+ delete[] numRows;
+ if(lpTop)lpTop->setFocus();
+ updateContentsSize();
+}
+
+
diff --git a/src/kvirc/ui/kvi_mdimanager.h b/src/kvirc/ui/kvi_mdimanager.h
new file mode 100644
index 00000000..17202fa0
--- /dev/null
+++ b/src/kvirc/ui/kvi_mdimanager.h
@@ -0,0 +1,144 @@
+#ifndef _KVI_MDIMANAGER_H_
+#define _KVI_MDIMANAGER_H_
+//=============================================================================
+//
+// File : kvi_mdimanager.h
+// Creation date : Wed Jun 21 2000 17:28:04 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+
+#include "kvi_settings.h"
+#include "kvi_pointerlist.h"
+
+#include <qwidget.h>
+#include <qframe.h>
+#include <qpixmap.h>
+#include <qtoolbutton.h>
+
+#include "kvi_tal_scrollview.h"
+
+#define KVI_MDICHILD_BORDER 4
+#define KVI_MDICHILD_SPACING 2
+#define KVI_MDICHILD_MIN_WIDTH 100
+#define KVI_MDICHILD_MIN_HEIGHT 40
+#define KVI_MDICHILD_HIDDEN_EDGE 3
+
+#ifdef COMPILE_ON_WINDOWS
+ #include "kvi_mdichild.h"
+#else
+ class KviMdiChild;
+#endif
+//class KviMdiCaptionButton;
+class KviFrame;
+
+class KviTalPopupMenu;
+class KviTalHBox;
+class KviSdiButtonBox;
+class KviMenuBarToolButton;
+
+class KVIRC_API KviMdiManager : public KviTalScrollView
+{
+ friend class KviMdiChild;
+ friend class KviMdiCaption;
+ Q_OBJECT
+public:
+ KviMdiManager(QWidget * parent,KviFrame * pFrm,const char * name);
+ ~KviMdiManager();
+public:
+ KviMdiChild * topChild(){ return m_pZ->last(); };
+ KviMdiChild * highestChildExcluding(KviMdiChild * pChild);
+ void manageChild(KviMdiChild * lpC,bool bCascade = true,QRect * setGeom = 0);
+ void setTopChild(KviMdiChild *lpC,bool bSetFocus);
+ void showAndActivate(KviMdiChild * lpC);
+ KviTalPopupMenu * windowPopup(){ return m_pWindowPopup; };
+ void focusTopChild();
+ void destroyChild(KviMdiChild *lpC,bool bFocusTopChild = true);
+ int getVisibleChildCount();
+ bool isInSDIMode();
+protected:
+ KviPointerList<KviMdiChild> * m_pZ; // topmost child is the last in the list
+
+ KviMenuBarToolButton * m_pSdiRestoreButton;
+ KviMenuBarToolButton * m_pSdiMinimizeButton;
+ KviMenuBarToolButton * m_pSdiCloseButton;
+ KviMenuBarToolButton * m_pSdiIconButton;
+
+#ifdef COMPILE_USE_QT4
+ KviTalHBox * m_pSdiControls;
+#endif
+ int m_iSdiIconItemId;
+ int m_iSdiRestoreItemId;
+ int m_iSdiMinimizeItemId;
+ int m_iSdiCloseItemId;
+
+ KviTalPopupMenu * m_pWindowPopup;
+ KviTalPopupMenu * m_pTileMethodPopup;
+ KviFrame * m_pFrm;
+protected:
+ void updateContentsSize();
+ //void childMaximized(KviMdiChild *lpC);
+ void childMinimized(KviMdiChild *lpC,bool bWasMaximized);
+ void childRestored(KviMdiChild *lpC,bool bWasMaximized);
+ void childMoved(KviMdiChild * lpC);
+ void maximizeChild(KviMdiChild * lpC);
+ virtual void focusInEvent(QFocusEvent *e);
+ virtual void mousePressEvent(QMouseEvent *e);
+ virtual void resizeEvent(QResizeEvent *e);
+ virtual void drawContents(QPainter * p,int x,int y,int w,int h);
+ virtual bool focusNextPrevChild(bool pNext);
+public slots:
+ void relayoutMenuButtons();
+ void cascadeWindows();
+ void cascadeMaximized();
+ void expandVertical();
+ void expandHorizontal();
+ void minimizeAll();
+// void restoreAll(); <-- this does nothing
+ void tile();
+ void toggleAutoTile();
+
+ void tileAnodine();
+ void reloadImages();
+protected slots:
+ void minimizeActiveChild();
+ void restoreActiveChild();
+ void closeActiveChild();
+ void activeChildSystemPopup();
+ void menuActivated(int id);
+ void tileMethodMenuActivated(int id);
+ void fillWindowPopup();
+ void sdiMinimizeButtonDestroyed();
+ void sdiRestoreButtonDestroyed();
+ void sdiCloseButtonDestroyed();
+ void sdiIconButtonDestroyed();
+private:
+ void ensureNoMaximized();
+ void tileAllInternal(int maxWnds,bool bHorizontal);
+ QPoint getCascadePoint(int indexOfWindow);
+ void enterSDIMode(KviMdiChild *lpC);
+ void leaveSDIMode();
+ void updateSDIMode();
+signals:
+ void enteredSdiMode();
+ void leftSdiMode();
+};
+
+#endif //_KVI_MDIMANAGER_H_
diff --git a/src/kvirc/ui/kvi_menubar.cpp b/src/kvirc/ui/kvi_menubar.cpp
new file mode 100644
index 00000000..a382f738
--- /dev/null
+++ b/src/kvirc/ui/kvi_menubar.cpp
@@ -0,0 +1,415 @@
+//=============================================================================
+//
+// File : kvi_menubar.cpp
+// Creation date : Wen Jun 21 2000 13:12:11 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+#include "kvi_menubar.h"
+#include "kvi_app.h"
+#include "kvi_locale.h"
+#include "kvi_frame.h"
+#include "kvi_mdimanager.h"
+#include "kvi_iconmanager.h"
+#include "kvi_internalcmd.h"
+#include "kvi_settings.h"
+#include "kvi_ircurl.h"
+#include "kvi_console.h"
+#include "kvi_kvs_popupmenu.h"
+#include "kvi_malloc.h"
+#include "kvi_moduleextension.h"
+#include "kvi_actionmanager.h"
+#include "kvi_coreactionnames.h"
+#include "kvi_kvs_script.h"
+
+#include "kvi_tal_popupmenu.h"
+
+KviMenuBar::KviMenuBar(KviFrame * par,const char * name)
+ : KviTalMenuBar(par,name)
+{
+ m_pFrm = par;
+
+ m_iNumDefaultItems = 0;
+ m_pDefaultItemId = 0;
+
+ KviTalPopupMenu * pop = new KviTalPopupMenu(this,"KVIrc");
+ connect(pop,SIGNAL(aboutToShow()),this,SLOT(setupMainPopup()));
+#ifndef Q_OS_MACX
+ addDefaultItem("&KVIrc",pop);
+#else
+ // Qt/Mac creates already a "KVirc" menu item on its own, and we don't like double entries ;-)
+ addDefaultItem("&IRC",pop);
+#endif //Q_OS_MACX
+ m_pRecentServersPopup = new KviTalPopupMenu(this,"recentservers");
+ connect(m_pRecentServersPopup,SIGNAL(aboutToShow()),this,SLOT(setupRecentServersPopup()));
+ connect(m_pRecentServersPopup,SIGNAL(activated(int)),this,SLOT(newConnectionToServer(int)));
+
+ m_pScriptItemList = 0;
+
+ pop = new KviTalPopupMenu(this,"scripting");
+ connect(pop,SIGNAL(aboutToShow()),this,SLOT(setupScriptingPopup()));
+ addDefaultItem(__tr2qs("Scri&pting"),pop);
+
+ pop = new KviTalPopupMenu(this,"tools");
+ connect(pop,SIGNAL(aboutToShow()),this,SLOT(setupToolsPopup()));
+ connect(pop,SIGNAL(activated(int)),this,SLOT(toolsPopupSelected(int)));
+ addDefaultItem(__tr2qs("&Tools"),pop);
+
+ m_pToolbarsPopup = new KviTalPopupMenu(this,"toolbars");
+ connect(m_pToolbarsPopup,SIGNAL(aboutToShow()),this,SLOT(setupToolbarsPopup()));
+
+ pop = new KviTalPopupMenu(this,"settings");
+ connect(pop,SIGNAL(aboutToShow()),this,SLOT(setupSettingsPopup()));
+ addDefaultItem(__tr2qs("&Settings"),pop);
+
+ addDefaultItem(__tr2qs("&Window"),par->mdiManager()->windowPopup());
+
+ pop = new KviTalPopupMenu(this,"help");
+ connect(pop,SIGNAL(aboutToShow()),this,SLOT(setupHelpPopup()));
+ addDefaultItem(__tr2qs("&Help"),pop);
+}
+
+KviMenuBar::~KviMenuBar()
+{
+ if(m_pScriptItemList)delete m_pScriptItemList;
+ if(m_pDefaultItemId)kvi_free(m_pDefaultItemId);
+}
+
+void KviMenuBar::showEvent(QShowEvent *e)
+{
+#ifdef COMPILE_USE_QT4
+ debug("menubar show");
+ // force a re-layout of the menubar in Qt4 (see the note in enterSDIMode())
+ // by resetting the corner widget
+ m_pFrm->mdiManager()->relayoutMenuButtons();
+#endif
+}
+
+void KviMenuBar::addDefaultItem(const QString &text,KviTalPopupMenu * pop)
+{
+ m_iNumDefaultItems++;
+ m_pDefaultItemId = (int *)kvi_realloc((void *)m_pDefaultItemId,sizeof(int) * m_iNumDefaultItems);
+ m_pDefaultItemId[m_iNumDefaultItems - 1] = insertItem(text,pop);
+}
+
+void KviMenuBar::setupHelpPopup()
+{
+ KviTalPopupMenu * help = (KviTalPopupMenu *)sender();
+ help->clear();
+
+ // FIXME: Convert these to actions!
+ int id = help->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_HELP)),__tr2qs("&Help Browser (Panel)"),m_pFrm,SLOT(executeInternalCommand(int)));
+ help->setItemParameter(id,KVI_INTERNALCOMMAND_HELP_NEWSTATICWINDOW);
+ id = help->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_MDIHELP)),__tr2qs("Help Browser (&Window)"),m_pFrm,SLOT(executeInternalCommand(int)));
+ help->setItemParameter(id,KVI_INTERNALCOMMAND_HELP_NEWMDIWINDOW);
+ help->insertSeparator();
+ id = help->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_IDEA)),__tr2qs("&Tip of the Day"),m_pFrm,SLOT(executeInternalCommand(int)));
+ help->setItemParameter(id,KVI_INTERNALCOMMAND_TIP_OPEN);
+ help->insertSeparator();
+ id = help->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_KVIRC)),__tr2qs("About &KVIrc"),m_pFrm,SLOT(executeInternalCommand(int)));
+ help->setItemParameter(id,KVI_INTERNALCOMMAND_ABOUT_ABOUTKVIRC);
+ help->insertSeparator();
+ id = help->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_HOMEPAGE)),__tr2qs("KVIrc Home&page"),m_pFrm,SLOT(executeInternalCommand(int)));
+ help->setItemParameter(id,KVI_INTERNALCOMMAND_KVIRC_HOMEPAGE);
+ if(kvi_strEqualCIN(KviLocale::localeName(),"ru",2))
+ {
+ id = help->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_HOMEPAGE)),__tr2qs("KVIrc Russian Home&page"),m_pFrm,SLOT(executeInternalCommand(int)));
+ help->setItemParameter(id,KVI_INTERNALCOMMAND_KVIRC_HOMEPAGE_RU);
+ }
+ if(kvi_strEqualCIN(KviLocale::localeName(),"fr",2))
+ {
+ id = help->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_HOMEPAGE)),__tr2qs("KVIrc French Home&page"),m_pFrm,SLOT(executeInternalCommand(int)));
+ help->setItemParameter(id,KVI_INTERNALCOMMAND_KVIRC_HOMEPAGE_FR);
+ }
+ help->insertSeparator();
+ id = help->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_MESSAGE)),__tr2qs("Subscribe to the Mailing List"),m_pFrm,SLOT(executeInternalCommand(int)));
+ help->setItemParameter(id,KVI_INTERNALCOMMAND_OPENURL_KVIRC_MAILINGLIST);
+ id = help->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_BOMB)),__tr2qs("Report a Bug / Propose Improvements"),m_pFrm,SLOT(executeInternalCommand(int)));
+ help->setItemParameter(id,KVI_INTERNALCOMMAND_OPENURL_KVIRC_BUGTRACK);
+ help->insertSeparator();
+ id = help->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CHANNEL)),__tr2qs("Join KVIrc International Channel on Freenode"),m_pFrm,SLOT(executeInternalCommand(int)));
+ help->setItemParameter(id,KVI_INTERNALCOMMAND_OPENURL_KVIRC_ON_FREENODE);
+ id = help->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CHANNEL)),__tr2qs("Join KVIrc International Channel on IRCNet"),m_pFrm,SLOT(executeInternalCommand(int)));
+ help->setItemParameter(id,KVI_INTERNALCOMMAND_OPENURL_KVIRC_ON_IRCNET);
+ if(kvi_strEqualCIN(KviLocale::localeName(),"it",2))
+ {
+ // join #kvirc.net on azzurra
+ id = help->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CHANNEL)),__tr2qs("Join KVIrc Italian Channel on AzzurraNet"),m_pFrm,SLOT(executeInternalCommand(int)));
+ help->setItemParameter(id,KVI_INTERNALCOMMAND_OPENURL_KVIRC_IT_ON_AZZURRA);
+ }
+ if(kvi_strEqualCIN(KviLocale::localeName(),"fr",2))
+ {
+ // join #kvirc-fr on freenode
+ id = help->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CHANNEL)),__tr2qs("Join KVIrc French Channel on Freenode"),m_pFrm,SLOT(executeInternalCommand(int)));
+ help->setItemParameter(id,KVI_INTERNALCOMMAND_OPENURL_KVIRC_FR_ON_FREENODE);
+ // join #kvirc on europnet
+ id = help->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CHANNEL)),__tr2qs("Join KVIrc French Channel on EuropNet"),m_pFrm,SLOT(executeInternalCommand(int)));
+ help->setItemParameter(id,KVI_INTERNALCOMMAND_OPENURL_KVIRC_FR_ON_EUROPNET);
+ }
+ // add your localized #kvirc channels here...
+}
+
+void KviMenuBar::setupSettingsPopup()
+{
+ // FIXME: Move everything to actions!
+
+ KviTalPopupMenu * opt = (KviTalPopupMenu *)sender();
+ opt->clear();
+
+ opt->insertItem(__tr2qs("Toolbars"),m_pToolbarsPopup);
+
+ int id = opt->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_STATUSBAR)),__tr2qs("Show StatusBar"),m_pFrm,SLOT(toggleStatusBar()));
+ opt->setItemChecked(id,m_pFrm->mainStatusBar());
+
+
+ opt->insertSeparator();
+ // FIXME: #warning "Toggle these items on the fly ?"
+ ACTION_POPUP_ITEM(KVI_COREACTION_GENERALOPTIONS,opt)
+ ACTION_POPUP_ITEM(KVI_COREACTION_THEMEOPTIONS,opt)
+ ACTION_POPUP_ITEM(KVI_COREACTION_MANAGETHEMES,opt)
+ ACTION_POPUP_ITEM(KVI_COREACTION_MANAGEADDONS,opt)
+ ACTION_POPUP_ITEM(KVI_COREACTION_SERVEROPTIONS,opt)
+ ACTION_POPUP_ITEM(KVI_COREACTION_TOOLBAREDITOR,opt)
+ ACTION_POPUP_ITEM(KVI_COREACTION_EDITREGUSERS,opt)
+
+ opt->insertSeparator();
+ opt->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_FLOPPY)),__tr2qs("&Save Configuration"),g_pApp,SLOT(saveConfiguration()));
+}
+
+void KviMenuBar::setupScriptingPopup()
+{
+ KviTalPopupMenu * script = (KviTalPopupMenu *)sender();
+ script->clear();
+
+ ACTION_POPUP_ITEM(KVI_COREACTION_ACTIONEDITOR,script)
+ ACTION_POPUP_ITEM(KVI_COREACTION_ALIASEDITOR,script)
+ ACTION_POPUP_ITEM(KVI_COREACTION_EVENTEDITOR,script)
+ ACTION_POPUP_ITEM(KVI_COREACTION_POPUPEDITOR,script)
+ ACTION_POPUP_ITEM(KVI_COREACTION_RAWEDITOR,script)
+ script->insertSeparator();
+ ACTION_POPUP_ITEM(KVI_COREACTION_CODETESTER,script)
+ script->insertSeparator();
+ ACTION_POPUP_ITEM(KVI_COREACTION_EXECUTEKVS,script)
+
+ script->insertSeparator();
+ script->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TEXTEXCLAMATIVE)),__tr2qs("Restore &Default Script"),g_pApp,SLOT(restoreDefaultScript()));
+}
+
+void KviMenuBar::setupMainPopup()
+{
+ KviTalPopupMenu * main = (KviTalPopupMenu *)sender();
+ main->clear();
+
+ ACTION_POPUP_ITEM(KVI_COREACTION_NEWIRCCONTEXT,main)
+ if(m_pFrm->activeContext())
+ if(m_pFrm->activeContext()->state()==KviIrcContext::Connected)
+ {
+ int id = main->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_QUIT)),__tr2qs("Disconnect"),m_pFrm,SLOT(executeInternalCommand(int)));
+ main->setItemParameter(id,KVI_INTERNALCOMMAND_QUIT);
+ }
+ main->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_WORLD)),__tr2qs("New &Connection To"),m_pRecentServersPopup);
+
+ main->insertSeparator();
+
+ if(m_pFrm->dockExtension())
+ {
+ int id = main->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_DOCKWIDGET)),__tr2qs("Hide &Dock Icon"),m_pFrm,SLOT(executeInternalCommand(int)));
+ main->setItemParameter(id,KVI_INTERNALCOMMAND_DOCKWIDGET_HIDE);
+ } else {
+ int id = main->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_DOCKWIDGET)),__tr2qs("Show &Dock Icon"),m_pFrm,SLOT(executeInternalCommand(int)));
+ main->setItemParameter(id,KVI_INTERNALCOMMAND_DOCKWIDGET_SHOW);
+ }
+
+// Qt/Mac creates a Quit item on its own
+#ifndef Q_OS_MACX
+ main->insertSeparator();
+
+ main->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_QUITAPP)),__tr2qs("&Quit"),g_pApp,SLOT(quit()));
+#endif //Q_OS_MACX
+}
+
+
+void KviMenuBar::setupRecentServersPopup()
+{
+ KviTalPopupMenu * m = (KviTalPopupMenu *)sender();
+ g_pApp->fillRecentServersPopup(m);
+ m->insertSeparator();
+ m->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_SERVER)),__tr2qs("&Other..."));
+}
+
+void KviMenuBar::newConnectionToServer(int id)
+{
+ QString text = m_pRecentServersPopup->text(id);
+ if(!text.isEmpty())
+ {
+ // the gentoo qt 3.3.4-r2 is broken
+ // since it adds random & characters to the popup texts...
+ if(text == __tr2qs("&Other..."))
+ {
+ KviKvsScript::run("options.edit KviServerOptionsWidget",m_pFrm->firstConsole());
+ } else {
+ text.replace(QString("&"),QString(""));
+ KviStr szCommand;
+ if(KviIrcUrl::parse(text.utf8().data(),szCommand,KVI_IRCURL_CONTEXT_NEW))
+ KviKvsScript::run(szCommand.ptr(),m_pFrm->firstConsole());
+ }
+ }
+}
+
+void KviMenuBar::setupToolsPopup()
+{
+ KviTalPopupMenu * m = (KviTalPopupMenu *)sender();
+ if(!m)return;
+
+ m->clear();
+
+ KviModuleExtensionDescriptorList * l = g_pModuleExtensionManager->getExtensionList("tool");
+ if(l)
+ {
+ for(KviModuleExtensionDescriptor * d = l->first();d;d = l->next())
+ {
+ int id;
+ if(d->icon())id = m->insertItem(*(d->icon()),d->visibleName());
+ else id = m->insertItem(d->visibleName());
+ //m->setItemChecked(id,(m_pFrm->moduleExtensionToolBar(d->id())));
+ m->setItemParameter(id,d->id());
+ }
+ }
+ m->insertSeparator();
+ ACTION_POPUP_ITEM(KVI_COREACTION_SOCKETSPY,m)
+ ACTION_POPUP_ITEM(KVI_COREACTION_NETWORKLINKS,m)
+ ACTION_POPUP_ITEM(KVI_COREACTION_CHANNELLIST,m)
+ m->insertSeparator();
+
+ ACTION_POPUP_ITEM(KVI_COREACTION_SCREENSHOT,m)
+
+ // moved the old tools here
+ m->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_ICONMANAGER)),__tr2qs("Show &Icon Table"),g_pIconManager,SLOT(showIconWidget()));
+#ifdef COMPILE_KDE_SUPPORT
+ int id;
+ id = m->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TERMINAL)),__tr2qs("Open &Terminal"),m_pFrm,SLOT(executeInternalCommand(int)));
+ m->setItemParameter(id,KVI_INTERNALCOMMAND_TERM_OPEN);
+#endif
+
+
+ KviPointerList<KviAction> list;
+ KviActionManager::instance()->listActionsByCategory("tools",&list);
+ if(!list.isEmpty())
+ {
+ m->insertSeparator();
+ for(KviAction * ac = list.first();ac;ac = list.next())
+ ac->addToPopupMenu(m);
+ }
+}
+
+void KviMenuBar::toolsPopupSelected(int id)
+{
+ KviTalPopupMenu * m = (KviTalPopupMenu *)sender();
+ if(!m)return;
+ int idext = m->itemParameter(id);
+ g_pModuleExtensionManager->allocateExtension("tool",idext,m_pFrm->firstConsole());
+}
+
+
+void KviMenuBar::setupToolbarsPopup()
+{
+ m_pFrm->fillToolBarsPopup(m_pToolbarsPopup);
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Script items
+//
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+int KviMenuBar::getDefaultItemRealIndex(int iDefaultIndex)
+{
+ if(iDefaultIndex < 0)iDefaultIndex = 0;
+ if(iDefaultIndex >= m_iNumDefaultItems)
+ return indexOf(m_pDefaultItemId[m_iNumDefaultItems - 1]) + 1;
+ return indexOf(m_pDefaultItemId[iDefaultIndex]);
+}
+
+KviScriptMenuBarItem * KviMenuBar::findMenu(const QString &text)
+{
+ if(!m_pScriptItemList)return 0;
+ for(KviScriptMenuBarItem * i = m_pScriptItemList->first();i;i = m_pScriptItemList->next())
+ {
+ if(KviQString::equalCI(i->szText,text))return i;
+ }
+ return 0;
+}
+
+KviScriptMenuBarItem * KviMenuBar::findMenu(KviKvsPopupMenu * p)
+{
+ if(!m_pScriptItemList)return 0;
+ for(KviScriptMenuBarItem * i = m_pScriptItemList->first();i;i = m_pScriptItemList->next())
+ {
+ if(i->pPopup == p)return i;
+ }
+ return 0;
+}
+
+bool KviMenuBar::removeMenu(const QString &text)
+{
+ KviScriptMenuBarItem * i = findMenu(text);
+ if(i)
+ {
+ disconnect(i->pPopup,SIGNAL(destroyed()),this,SLOT(menuDestroyed()));
+ removeItem(i->id);
+ m_pScriptItemList->removeRef(i);
+ return true;
+ }
+ return false;
+}
+
+void KviMenuBar::menuDestroyed()
+{
+ KviScriptMenuBarItem * i = findMenu(((KviKvsPopupMenu *)sender()));
+ if(i)
+ {
+ removeItem(i->id);
+ m_pScriptItemList->removeRef(i);
+ }
+}
+
+void KviMenuBar::addMenu(const QString &text,KviKvsPopupMenu * p,int index)
+{
+ if(!m_pScriptItemList)
+ {
+ m_pScriptItemList = new KviPointerList<KviScriptMenuBarItem>;
+ m_pScriptItemList->setAutoDelete(true);
+ }/* else {
+ removeMenu(text);
+ }*/
+ KviScriptMenuBarItem * it = new KviScriptMenuBarItem;
+ it->szText = text;
+ it->szPopupName = p->name();
+ it->pPopup = p;
+ it->id = insertItem(text,p,-1,index);
+ connect(p,SIGNAL(destroyed()),this,SLOT(menuDestroyed()));
+ m_pScriptItemList->append(it);
+}
+
+#include "kvi_menubar.moc"
diff --git a/src/kvirc/ui/kvi_menubar.h b/src/kvirc/ui/kvi_menubar.h
new file mode 100644
index 00000000..3095913b
--- /dev/null
+++ b/src/kvirc/ui/kvi_menubar.h
@@ -0,0 +1,83 @@
+#ifndef _KVI_MENUBAR_H_
+#define _KVI_MENUBAR_H_
+
+//=============================================================================
+//
+// File : kvi_menubar.h
+// Creation date : Wen Jun 21 2000 13:11:24 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#include "kvi_tal_menubar.h"
+#include "kvi_string.h"
+
+#include "kvi_pointerlist.h"
+
+class KviFrame;
+class KviTalPopupMenu;
+class KviKvsPopupMenu;
+
+typedef struct _KviScriptMenuBarItem
+{
+ int id;
+ KviStr szPopupName;
+ KviKvsPopupMenu * pPopup;
+ KviStr szText;
+} KviScriptMenuBarItem;
+
+
+class KVIRC_API KviMenuBar : public KviTalMenuBar
+{
+ Q_OBJECT
+public:
+ KviMenuBar(KviFrame * par,const char * name);
+ ~KviMenuBar();
+protected:
+ KviTalPopupMenu * m_pToolbarsPopup;
+ KviTalPopupMenu * m_pRecentServersPopup;
+ KviFrame * m_pFrm;
+ KviPointerList<KviScriptMenuBarItem> * m_pScriptItemList;
+ int m_iNumDefaultItems;
+ int * m_pDefaultItemId;
+protected:
+ KviScriptMenuBarItem * findMenu(const QString &text);
+ KviScriptMenuBarItem * findMenu(KviKvsPopupMenu * p);
+ void addDefaultItem(const QString &text,KviTalPopupMenu * pop);
+ virtual void showEvent(QShowEvent *e);
+public:
+ int getDefaultItemRealIndex(int iDefaultIndex);
+ void addMenu(const QString &text,KviKvsPopupMenu * p,int index);
+ bool removeMenu(const QString &text);
+protected slots:
+ void menuDestroyed();
+ void setupMainPopup();
+ void setupSettingsPopup();
+ void setupHelpPopup();
+ void setupRecentServersPopup();
+ void setupScriptingPopup();
+ void newConnectionToServer(int id);
+ void setupToolbarsPopup();
+ void setupToolsPopup();
+ void toolsPopupSelected(int id);
+};
+
+#endif //_KVI_MENUBAR_H_
diff --git a/src/kvirc/ui/kvi_modeeditor.cpp b/src/kvirc/ui/kvi_modeeditor.cpp
new file mode 100644
index 00000000..f72d0a22
--- /dev/null
+++ b/src/kvirc/ui/kvi_modeeditor.cpp
@@ -0,0 +1,336 @@
+//
+// File : kvi_modeeditor.cpp
+// Creation date : Sat Apr 14 2001 13:52:11 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+#define __KVIRC__
+#include "kvi_modeeditor.h"
+#include "kvi_iconmanager.h"
+#include "kvi_locale.h"
+#include "kvi_qstring.h"
+#include "kvi_console.h"
+#include "kvi_ircconnection.h"
+#include "kvi_ircconnectionserverinfo.h"
+#include "kvi_channel.h"
+#include "kvi_ircconnectionuserinfo.h"
+#include "kvi_styled_controls.h"
+#include "kvi_toolwindows_container.h"
+#include "kvi_tal_scrollview.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+
+
+//////////////////////////////////////////////////////////////////////
+// class KviModeEditor
+//
+//////////////////////////////////////////////////////////////////////
+
+//static char checkable_modes_table[KVI_NUM_CHECKABLE_MODES] = { 'p','s','t','n','m','i'};
+
+// FIXME: This widget should use a KviTalScrollView!
+
+KviModeEditor::KviModeEditor(QWidget * par,KviWindowToolPageButton* button,const char * nam,KviConsole * c,const char * mode,const char * key,const char * limit)
+: KviWindowToolWidget(par,button)
+{
+ m_szMode = mode;
+ m_szKey = key;
+ m_szLimit = limit;
+ bool isEnabled=1;
+
+ QObject * w = parent();
+ while(w)
+ {
+ if(w->inherits("KviChannel"))
+ {
+ KviChannel *chan = ((KviChannel *)w);
+ if(!( chan->isMeHalfOp() || chan->isMeOp() || chan->isMeChanOwner() || chan->isMeChanAdmin() || chan->connection()->userInfo()->hasUserMode('o') || chan->connection()->userInfo()->hasUserMode('O') ) ) isEnabled=0;
+ break;
+ }
+ w = w->parent();
+ }
+
+ QGridLayout *pMasterLayout = new QGridLayout(this,2,1,2,2);
+
+#ifdef COMPILE_USE_QT4
+ setFocusPolicy(Qt::ClickFocus);
+#else
+ setFocusPolicy(QWidget::ClickFocus);
+#endif
+
+ KviTalScrollView *pScrollView = new KviTalScrollView(this);
+#ifdef COMPILE_USE_QT4
+ pScrollView->viewport()->setBackgroundRole(QPalette::Background);
+#else
+ pScrollView->viewport()->setBackgroundMode(QWidget::PaletteBackground);
+#endif
+
+ pMasterLayout->addWidget(pScrollView,0,0);
+
+ pMasterLayout->setRowStretch(1,1);
+ QPushButton * b;
+ if(isEnabled) b = new QPushButton(__tr2qs("&Apply"),this);
+ else b = new QPushButton(__tr2qs("Close"),this);
+
+ pMasterLayout->addWidget(b,1,0);
+ connect(b,SIGNAL(clicked()),this,SLOT(commit()));
+
+ QWidget * pBackground = new QWidget(pScrollView->viewport());
+
+ QGridLayout *g = new QGridLayout(pBackground,20,3,2,2);
+
+ QLabel * l = new QLabel("",pBackground);
+ l->setPixmap(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_MODE)));
+ g->addWidget(l,0,0);
+
+ l = new QLabel(__tr2qs("Channel Modes"),pBackground);
+ g->addMultiCellWidget(l,0,0,1,2);
+
+ QFrame * f = new QFrame(pBackground);
+ f->setFrameStyle(QFrame::HLine | QFrame::Sunken);
+ g->addMultiCellWidget(f,1,1,0,2);
+
+ int i = 1;
+ QString tmp;
+
+ m_pCheckBoxes = new KviPointerList<KviStyledCheckBox>;
+ m_pCheckBoxes->setAutoDelete(false);
+
+
+ // first che basic checkable modes pstnmi
+ QString szModes = "pstnmi";
+
+ while(!szModes.isEmpty())
+ {
+ QChar ccc = szModes[0];
+ szModes.remove(0,1);
+
+ KviQString::sprintf(tmp,"%c: %Q",ccc.unicode(),&(c->connection()->serverInfo()->getChannelModeDescription(ccc)));
+ KviStyledCheckBox * cb = new KviStyledCheckBox(tmp,pBackground);
+ cb->setEnabled(isEnabled);
+ m_pCheckBoxes->append(cb);
+ cb->setChecked(m_szMode.contains((char)ccc.unicode()));
+ i++;
+ g->addMultiCellWidget(cb,i,i,0,2);
+ }
+
+ KviQString::sprintf(tmp,"l: %Q",&(c->connection()->serverInfo()->getChannelModeDescription('l')));
+ m_pLimitBox = new KviStyledCheckBox(tmp,pBackground);
+ m_pLimitBox->setEnabled(isEnabled);
+ i++;
+ g->addMultiCellWidget(m_pLimitBox,i,i,0,2);
+ connect(m_pLimitBox,SIGNAL(toggled(bool)),this,SLOT(limitBoxToggled(bool)));
+ m_pLimitEdit = new QLineEdit(pBackground);
+ m_pLimitEdit->setEnabled(isEnabled);
+ i++;
+ g->addMultiCellWidget(m_pLimitEdit,i,i,1,2);
+ if(m_szLimit.hasData())
+ {
+ m_pLimitBox->setChecked(true);
+// m_pLimitEdit->setEnabled(true);
+ m_pLimitEdit->setText(m_szLimit.ptr());
+ } else {
+ m_pLimitEdit->setEnabled(false);
+ }
+
+ KviQString::sprintf(tmp,"k: %Q",&(c->connection()->serverInfo()->getChannelModeDescription('k')));
+ m_pKeyBox = new KviStyledCheckBox(tmp,pBackground);
+ m_pKeyBox->setEnabled(isEnabled);
+ i++;
+ g->addMultiCellWidget(m_pKeyBox,i,i,0,2);
+ connect(m_pKeyBox,SIGNAL(toggled(bool)),this,SLOT(keyBoxToggled(bool)));
+ m_pKeyEdit = new QLineEdit(pBackground);
+ m_pKeyEdit->setEnabled(isEnabled);
+ i++;
+ g->addMultiCellWidget(m_pKeyEdit,i,i,1,2);
+ if(m_szKey.hasData())
+ {
+ m_pKeyBox->setChecked(true);
+// m_pLimitEdit->setEnabled(true);
+ m_pKeyEdit->setText(m_szKey.ptr());
+ } else {
+ m_pKeyEdit->setEnabled(false);
+ }
+
+ if(c->connection())
+ {
+ if(c->connection()->serverInfo())
+ szModes = c->connection()->serverInfo()->supportedChannelModes();
+ }
+
+ int idx = szModes.findRev(',');
+ if(idx != -1)szModes.remove(0,idx+1);
+
+ szModes.replace("p","");
+ szModes.replace("s","");
+ szModes.replace("t","");
+ szModes.replace("n","");
+ szModes.replace("m","");
+ szModes.replace("i","");
+ szModes.replace(",","");
+ szModes.replace("b","");
+ szModes.replace("k","");
+ szModes.replace("l","");
+
+ while(!szModes.isEmpty())
+ {
+ QChar ccc = szModes[0];
+ szModes.remove(0,1);
+
+ KviQString::sprintf(tmp,"%c: %Q",(char)ccc.unicode(),&(c->connection()->serverInfo()->getChannelModeDescription(ccc)));
+ KviStyledCheckBox * cb = new KviStyledCheckBox(tmp,pBackground);
+ cb->setEnabled(isEnabled);
+ m_pCheckBoxes->append(cb);
+ cb->setChecked(m_szMode.contains((char)ccc.unicode()));
+ i++;
+ g->addMultiCellWidget(cb,i,i,0,2);
+ }
+
+ i++;
+
+ g->setRowStretch(i,1);
+ g->setColStretch(2,1);
+
+ pScrollView->addChild(pBackground,0,0);
+ registerSelf();
+}
+
+KviModeEditor::~KviModeEditor()
+{
+ delete m_pCheckBoxes;
+}
+
+void KviModeEditor::limitBoxToggled(bool bChecked)
+{
+ m_pLimitEdit->setEnabled(bChecked);
+}
+
+void KviModeEditor::keyBoxToggled(bool bChecked)
+{
+ m_pKeyEdit->setEnabled(bChecked);
+}
+
+void KviModeEditor::commit()
+{
+ KviStr szPlusModes;
+ KviStr szMinusModes;
+
+ if(m_szKey.hasData())
+ {
+ // had a key before
+ if(m_pKeyBox->isChecked())
+ {
+ // still have it
+ KviStr tmp = m_pKeyEdit->text();
+ tmp.stripWhiteSpace();
+ if(tmp.hasData())
+ {
+ if(!kvi_strEqualCI(tmp.ptr(),m_szKey.ptr()))
+ {
+ // not the same key!
+ // set the new one
+ KviStr mode(KviStr::Format,"-k %s",m_szKey.ptr());
+ emit setMode(mode.ptr());
+ mode.sprintf("+k %s",tmp.ptr());
+ emit setMode(mode.ptr());
+ }
+ }
+ } else {
+ // no key now! reset
+ KviStr mode(KviStr::Format,"-k %s",m_szKey.ptr());
+ emit setMode(mode.ptr());
+ }
+ } else {
+ // there was no key before
+ if(m_pKeyBox->isChecked())
+ {
+ KviStr tmp = m_pKeyEdit->text();
+ tmp.stripWhiteSpace();
+ if(tmp.hasData())
+ {
+ // new key to be set
+ KviStr mode(KviStr::Format,"+k %s",tmp.ptr());
+ emit setMode(mode.ptr());
+ }
+ }
+ }
+
+ if(m_szLimit.hasData())
+ {
+ // had a limit before
+ if(m_pLimitBox->isChecked())
+ {
+ // still have it
+ KviStr tmp = m_pLimitEdit->text();
+ tmp.stripWhiteSpace();
+ if(tmp.hasData() && tmp.isUnsignedNum())
+ {
+ if(!kvi_strEqualCI(tmp.ptr(),m_szLimit.ptr()))
+ {
+ // not the same limit!
+ KviStr mode(KviStr::Format,"+l %s",tmp.ptr());
+ emit setMode(mode.ptr());
+ }
+ }
+ } else {
+ // no limit now! reset
+ szMinusModes.append('l');
+ }
+ } else {
+ // there was no limit before
+ if(m_pLimitBox->isChecked())
+ {
+ KviStr tmp = m_pLimitEdit->text();
+ tmp.stripWhiteSpace();
+ if(tmp.hasData() && tmp.isUnsignedNum())
+ {
+ // new limit to be set
+ KviStr mode(KviStr::Format,"+l %s",tmp.ptr());
+ emit setMode(mode.ptr());
+ }
+ }
+ }
+
+
+ for(KviStyledCheckBox * cb = m_pCheckBoxes->first();cb;cb = m_pCheckBoxes->next())
+ {
+ QString sz = cb->text();
+ sz.replace("&","");
+ if(sz.length() > 0)
+ {
+ QChar ccc = sz[0];
+ if(cb->isChecked())
+ {
+ if(!m_szMode.contains((char)ccc.unicode()))szPlusModes.append((char)ccc.unicode());
+ } else {
+ if(m_szMode.contains((char)ccc.unicode()))szMinusModes.append((char)ccc.unicode());
+ }
+ }
+ }
+
+ KviStr szModes;
+
+ if(szMinusModes.hasData())szModes.sprintf("-%s",szMinusModes.ptr());
+ if(szPlusModes.hasData())szModes.append(KviStr::Format,"+%s",szPlusModes.ptr());
+ if(szModes.hasData())emit setMode(szModes.ptr());
+
+ emit done();
+}
+
+#include "kvi_modeeditor.moc"
diff --git a/src/kvirc/ui/kvi_modeeditor.h b/src/kvirc/ui/kvi_modeeditor.h
new file mode 100644
index 00000000..06512d9b
--- /dev/null
+++ b/src/kvirc/ui/kvi_modeeditor.h
@@ -0,0 +1,70 @@
+#ifndef _KVI_MODEEDITOR_H_
+#define _KVI_MODEEDITOR_H_
+
+//
+// File : kvi_modeeditor.h
+// Creation date : Sat Apr 14 2001 13:50:12 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+
+#include <qwidget.h>
+#include <qpushbutton.h>
+#include <qcheckbox.h>
+#include <qlineedit.h>
+#include <qlabel.h>
+
+#include "kvi_string.h"
+#include "kvi_pointerlist.h"
+#include "kvi_styled_controls.h"
+#include "kvi_toolwindows_container.h"
+
+class KviConsole;
+
+//////////////////////////////////////////////////////////////////////
+// class KviModeEditor
+//
+//////////////////////////////////////////////////////////////////////
+
+class KVIRC_API KviModeEditor : public KviWindowToolWidget
+{
+ Q_OBJECT
+public:
+ KviModeEditor(QWidget * par,KviWindowToolPageButton* button,const char * nam,KviConsole * c,const char * mode,const char * key,const char * limit);
+ ~KviModeEditor();
+protected: // fields
+ KviStr m_szMode;
+ KviStr m_szKey;
+ KviStr m_szLimit;
+ KviPointerList<KviStyledCheckBox> * m_pCheckBoxes;
+ KviStyledCheckBox * m_pLimitBox;
+ QLineEdit * m_pLimitEdit;
+ KviStyledCheckBox * m_pKeyBox;
+ QLineEdit * m_pKeyEdit;
+signals:
+ void setMode(const char *);
+ void done();
+protected slots:
+ void limitBoxToggled(bool bChecked);
+ void keyBoxToggled(bool bChecked);
+ void commit();
+};
+
+#endif //_KVI_MODEEDITOR_H_
diff --git a/src/kvirc/ui/kvi_modew.cpp b/src/kvirc/ui/kvi_modew.cpp
new file mode 100755
index 00000000..a0cf85e4
--- /dev/null
+++ b/src/kvirc/ui/kvi_modew.cpp
@@ -0,0 +1,175 @@
+//============================================================================
+//
+// File : kvi_modew.cpp
+// Creation date : 12.11.2005 23.50 by Uzhva Alexey
+//
+// This file is part of the KVirc irc client distribution
+//
+// 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 opinion) 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.
+//
+//============================================================================
+#define __KVIRC__
+
+#include "kvi_themedlabel.h"
+#include "kvi_channel.h"
+#include "kvi_options.h"
+#include "kvi_ircconnectionserverinfo.h"
+#include "kvi_ircconnectionuserinfo.h"
+#include "kvi_qcstring.h"
+
+#include <qframe.h>
+#include <qlineedit.h>
+#include "kvi_tal_hbox.h"
+#include <qevent.h>
+
+KviModeWidget::KviModeWidget(QWidget * par,KviChannel* chan,const char * name)
+:QFrame(par,name)
+{
+ m_pChannel=chan;
+ m_pLabel=0;
+ m_pLineEdit=0;
+#ifdef COMPILE_USE_QT4
+ setAutoFillBackground(false);
+#else
+ setBackgroundMode(QWidget::NoBackground);
+#endif
+ reset();
+}
+
+KviModeWidget::~KviModeWidget()
+{
+}
+
+void KviModeWidget::reset()
+{
+ if(m_pLineEdit)
+ {
+ delete m_pLineEdit;
+ m_pLineEdit=0;
+ }
+ if(!m_pLabel)
+ m_pLabel=new KviThemedLabel(this,0);
+ refreshModes();
+ m_pLabel->show();
+ connect(m_pLabel,SIGNAL(doubleClicked()),this,SLOT(labelDoubleClick()));
+ QResizeEvent* ev=new QResizeEvent(size(),size());
+ resizeEvent(ev);
+ delete ev;
+ if(m_pChannel->input())
+ m_pChannel->setFocus();
+}
+
+void KviModeWidget::refreshModes()
+{
+ QString szMode=m_pChannel->channelMode();
+ if(!m_pChannel->channelKey().isEmpty())
+ szMode+=QString(" k:%1").arg(m_pChannel->channelKey());
+ if(!m_pChannel->channelLimit().isEmpty())
+ szMode+=QString(" l:%1").arg(m_pChannel->channelLimit().ptr());
+ if(m_pLabel)
+ m_pLabel->setText(szMode);
+}
+
+void KviModeWidget::applyOptions()
+{
+ if(m_pLabel)
+ m_pLabel->applyOptions();
+}
+
+void KviModeWidget::resizeEvent(QResizeEvent *e)
+{
+ if(e)QFrame::resizeEvent(e);
+ if(m_pLabel)
+ {
+ m_pLabel->setGeometry(0,0,width(),height());
+ }
+ if(m_pLineEdit)
+ {
+ m_pLineEdit->setGeometry(0,0,width(),height());
+ }
+}
+
+void KviModeWidget::labelDoubleClick()
+{
+ if(m_pLabel && ( m_pChannel->isMeHalfOp() || m_pChannel->isMeOp() || m_pChannel->isMeChanOwner() || m_pChannel->isMeChanAdmin() || m_pChannel->connection()->userInfo()->hasUserMode('o') || m_pChannel->connection()->userInfo()->hasUserMode('O')) )
+ {
+ delete m_pLabel;
+ m_pLabel=0;
+ m_pLineEdit = new QLineEdit(this,0);
+ m_pLineEdit->setText(m_pChannel->channelMode());
+ m_pLineEdit->show();
+ m_pLineEdit->setFocus();
+ resizeEvent(new QResizeEvent(size(),size()));
+ m_pLineEdit->installEventFilter( this );
+ connect(m_pLineEdit,SIGNAL(textChanged ( const QString & ) ),this,SLOT(editorTextChanged( const QString & )));
+ }
+}
+
+bool KviModeWidget::eventFilter( QObject *obj, QEvent *ev )
+{
+ if( (obj==m_pLineEdit) && ( ev->type() == QEvent::KeyPress ) )
+ {
+ QKeyEvent *keyEvent = (QKeyEvent*)ev;
+ switch(keyEvent->key())
+ {
+ case Qt::Key_Return:
+ case Qt::Key_Enter:
+ editorReturnPressed();
+ return TRUE;
+ case Qt::Key_Escape:
+ reset();
+ return TRUE;
+ }
+ }
+ return QFrame::eventFilter( obj, ev );
+}
+
+void KviModeWidget::editorReturnPressed()
+{
+ QString szCurModes=m_pChannel->channelMode();
+ QString szNewModes=m_pLineEdit->text();
+ QString szMinusModes;
+ for(int i=0; i<szCurModes.length(); i++)
+ {
+ if(szNewModes.contains(szCurModes[i]))
+ szNewModes.remove(szCurModes[i]);
+ else
+ szMinusModes+=szCurModes[i];
+ }
+ QString mode;
+ if(!szMinusModes.isEmpty()) mode+=QString("-"+szMinusModes);
+ if(!szNewModes.isEmpty()) mode+=QString("+"+szNewModes);
+ if(!mode.isEmpty())
+ {
+ KviQCString chan = m_pChannel->connection()->encodeText(m_pChannel->name());
+ m_pChannel->connection()->sendFmtData("MODE %s %s",chan.data(),mode.utf8().data());
+ }
+ reset();
+}
+
+void KviModeWidget::editorTextChanged( const QString & text)
+{
+ int i = 0;
+ QString szText=text;
+ for(i=0;i<szText.length();i++)
+ {
+ if( !m_pChannel->connection()->serverInfo()->supportedPlainModes().contains(szText[i]) ||
+ szText.find(szText[i])<i )
+ szText.remove(i,1);
+ }
+ m_pLineEdit->setText(szText);
+}
+
+#include "kvi_modew.moc"
diff --git a/src/kvirc/ui/kvi_modew.h b/src/kvirc/ui/kvi_modew.h
new file mode 100755
index 00000000..7efbc961
--- /dev/null
+++ b/src/kvirc/ui/kvi_modew.h
@@ -0,0 +1,57 @@
+#ifndef _KVI_MODEW_H_
+#define _KVI_MODEW_H_
+
+//============================================================================
+//
+// File : kvi_modew.h
+// Creation date : 12.11.2005 23.50 by Uzhva Alexey
+//
+// This file is part of the KVirc irc client distribution
+//
+// 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 opinion) 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.
+//
+//============================================================================
+
+#include "kvi_themedlabel.h"
+#include "kvi_channel.h"
+
+#include <qframe.h>
+#include <qlineedit.h>
+#include "kvi_tal_hbox.h"
+
+class KVIRC_API KviModeWidget : public QFrame
+{
+ Q_OBJECT
+
+public:
+ KviModeWidget(QWidget * par,KviChannel* chan,const char * name=0);
+ ~KviModeWidget();
+ void reset();
+ void refreshModes();
+ void applyOptions();
+private:
+ KviChannel * m_pChannel;
+ KviThemedLabel * m_pLabel;
+ QLineEdit * m_pLineEdit;
+protected:
+ void resizeEvent(QResizeEvent *e);
+ bool eventFilter( QObject *obj, QEvent *ev );
+public slots:
+ void labelDoubleClick();
+ void editorReturnPressed();
+ void editorTextChanged( const QString & );
+};
+
+#endif //_KVI_MODEW_H_
diff --git a/src/kvirc/ui/kvi_msgbox.cpp b/src/kvirc/ui/kvi_msgbox.cpp
new file mode 100644
index 00000000..81cea104
--- /dev/null
+++ b/src/kvirc/ui/kvi_msgbox.cpp
@@ -0,0 +1,89 @@
+//
+// File : kvi_msgbox.cpp
+// Creation date : Tue Jun 20 2000 12:49:41 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+#define __KVIRC__
+#include "kvi_msgbox.h"
+
+// FIXME: #warning "This should go into TAL as layer ...then maybe a wrapper in KviApp!"
+
+#ifdef COMPILE_KDE_SUPPORT
+ #include <kmessagebox.h>
+#else
+ #include <qmessagebox.h>
+#endif //!COMPILE_WITH_KDE
+
+#include "kvi_malloc.h"
+#include "kvi_string.h"
+#include "kvi_locale.h"
+
+// FIXME: #warning "This could go into KviApp"
+
+namespace KviMessageBox
+{
+ void warning(const QString &fmt,...)
+ {
+ kvi_va_list list;
+ kvi_va_start_by_reference(list,fmt);
+ QString s;
+ KviQString::vsprintf(s,fmt,list);
+ kvi_va_end(list);
+#ifdef COMPILE_KDE_SUPPORT
+ KMessageBox::error(0,s,"KVIrc");
+#else
+ QMessageBox::warning(0,"KVIrc",s);
+#endif
+ }
+
+ void information(const QString &fmt,...)
+ {
+ kvi_va_list list;
+ kvi_va_start_by_reference(list,fmt);
+ QString s;
+ KviQString::vsprintf(s,fmt,list);
+ kvi_va_end(list);
+#ifdef COMPILE_KDE_SUPPORT
+ KMessageBox::information(0,s,"KVIrc");
+#else
+ QMessageBox::information(0,"KVIrc",s);
+#endif
+ }
+
+ bool yesNo(const QString &caption,const QString &fmt,...)
+ {
+ kvi_va_list list;
+ kvi_va_start_by_reference(list,fmt);
+ QString s;
+ KviQString::vsprintf(s,fmt,list);
+ kvi_va_end(list);
+ bool bRet;
+#ifdef COMPILE_KDE_SUPPORT
+ bRet = (KMessageBox::questionYesNo(0,s,caption) == KMessageBox::Yes);
+#else
+ bRet = (QMessageBox::information(0,caption,s,
+ QMessageBox::Yes | QMessageBox::Default,
+ QMessageBox::No | QMessageBox::Escape) == QMessageBox::Yes);
+#endif
+ return bRet;
+ }
+};
+
+
+
diff --git a/src/kvirc/ui/kvi_msgbox.h b/src/kvirc/ui/kvi_msgbox.h
new file mode 100644
index 00000000..71b22a26
--- /dev/null
+++ b/src/kvirc/ui/kvi_msgbox.h
@@ -0,0 +1,53 @@
+#ifndef _KVI_MSGBOX_H_
+#define _KVI_MSGBOX_H_
+
+//
+// File : kvi_msgbox.h
+// Creation date : Sun Jan 17 1999 13:55:41 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+/*
+class KviMessageBox : public KviTalMessageBox
+{
+ enum Result { Yes , No , Ok , Cancel };
+ enum ButtonResult { Button1 , Button2 , Button3 };
+
+ KVIRC_API void warning(const char * fmt,...);
+ KVIRC_API void information(const char * fmt,...);
+
+ KVIRC_API Result yesNo(const char * fmt,...);
+ KVIRC_API Result yesNoCancel(const char * fmt,...);
+
+ KVIRC_API ButtonResult oneButton(const char * btnTxt,const char * fmt,...);
+ KVIRC_API ButtonResult twoButtons(const char * btnTxt1,const char * btnTxt2,const char * fmt,...);
+ KVIRC_API ButtonResult threeButtons(const char * btnTxt1,const char * btnTxt2,const char * btnTxt3,const char * fmt,...);
+};
+*/
+
+namespace KviMessageBox
+{
+ KVIRC_API void warning(const QString &fmt,...);
+ KVIRC_API void information(const QString &fmt,...);
+ KVIRC_API bool yesNo(const QString &caption,const QString &fmt,...);
+};
+
+#endif //!_KVI_MSGBOX_H_
diff --git a/src/kvirc/ui/kvi_optionswidget.cpp b/src/kvirc/ui/kvi_optionswidget.cpp
new file mode 100644
index 00000000..546d4b1e
--- /dev/null
+++ b/src/kvirc/ui/kvi_optionswidget.cpp
@@ -0,0 +1,722 @@
+//=============================================================================
+//
+// File : kvi_optionswidget.h
+// Creation date : Mon Jun 10 2000 17:47:33 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_optionswidget.h"
+
+#define _WANT_OPTION_FLAGS_
+#include "kvi_options.h"
+
+#include "kvi_locale.h"
+
+#include "kvi_app.h"
+
+#include "kvi_tal_tooltip.h"
+
+#define KVI_OPTIONSWIDGET_GRIDLAYOUT_BORDER 4
+#define KVI_OPTIONSWIDGET_GRIDLAYOUT_SPACE 6
+
+QString KviOptionsWidget::m_szBasicTipStart; // empty decl
+QString KviOptionsWidget::m_szBasicTipEnd;
+
+KviOptionsWidget::KviOptionsWidget(QWidget * parent,const char * name,bool bSunken)
+: QFrame(parent,name), KviSelectorInterface()
+{
+ if(m_szBasicTipStart.isEmpty())
+ {
+ m_szBasicTipStart = "<center><font color=\"#a0a0a0\">";
+ m_szBasicTipStart += __tr2qs("This option is also available as");
+ m_szBasicTipStart += "<br><nobr>/option <b> ";
+ m_szBasicTipEnd = "</b></nobr></font></center>";
+
+ }
+ // FIXME: The bSunken value is ignored!
+ //if(bSunken)setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
+ //setFrameStyle(QFrame::StyledPanel | QFrame::Plain);
+ m_pLayout = 0;
+ m_pTabWidget = 0;
+ m_iResetFlags = 0;
+ m_iSelectors = 0;
+ m_pSelectorInterfaceList = new KviPointerList<KviSelectorInterface>;
+ m_pSelectorInterfaceList->setAutoDelete(false);
+}
+
+KviOptionsWidget::~KviOptionsWidget()
+{
+ delete m_pSelectorInterfaceList;
+}
+
+void KviOptionsWidget::mergeTip(QWidget * w,const QString &tip)
+{
+ static QString begin = "<table width=\"100%\" align=\"center\"><tr><td bgcolor=\"#fefef0\">";
+ static QString mid = "</td></tr><tr><td>";
+ static QString end = "</td></tr></table>";
+#ifdef COMPILE_USE_QT4
+ QString s = w->toolTip();
+#else
+ QString s = KviTalToolTip::textFor(w);
+#endif
+ if(s.isEmpty())KviTalToolTip::add(w,tip);
+ else {
+ QString tmp = begin;
+ tmp += tip;
+ tmp += mid;
+ tmp += s;
+ tmp += end;
+ KviTalToolTip::add(w,tmp);
+ }
+}
+
+void KviOptionsWidget::createLayout(int rows,int cols)
+{
+ if(m_pLayout)delete m_pLayout;
+ m_pLayout = new QGridLayout(this,rows,cols,KVI_OPTIONSWIDGET_GRIDLAYOUT_BORDER,KVI_OPTIONSWIDGET_GRIDLAYOUT_SPACE);
+}
+
+void KviOptionsWidget::createTabbedPage()
+{
+ createLayout(1,1);
+ layout()->setMargin(0);
+ layout()->setSpacing(0);
+ m_pTabWidget = new QTabWidget(this);
+ addWidgetToLayout(m_pTabWidget,0,0,0,0);
+}
+
+void KviOptionsWidget::addOptionsWidget(const QString &szText,const QIconSet &iconSet,KviOptionsWidget * pWidget)
+{
+ if(pWidget->layout())
+ pWidget->layout()->setMargin(10);
+ m_pTabWidget->addTab(pWidget,iconSet,szText);
+ m_pSelectorInterfaceList->append(pWidget);
+}
+
+
+void KviOptionsWidget::addWidgetToLayout(QWidget * w,int x1,int y1,int x2,int y2)
+{
+ if((x1 == x2) && (y1 == y2))layout()->addWidget(w,y1,x1);
+ else layout()->addMultiCellWidget(w,y1,y2,x1,x2);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+KviDirectorySelector * KviOptionsWidget::addDirectorySelector(int x1,int y1,int x2,int y2,const QString & txt,QString *pOption,bool bEnabled)
+{
+ KviDirectorySelector * d = new KviDirectorySelector(this,txt,pOption,bEnabled);
+ addWidgetToLayout(d,x1,y1,x2,y2);
+ m_pSelectorInterfaceList->append(d);
+ return d;
+}
+
+KviDirectorySelector * KviOptionsWidget::addDirectorySelector(QWidget * pParent,const QString & txt,QString *pOption,bool bEnabled)
+{
+ KviDirectorySelector * d = new KviDirectorySelector(pParent,txt,pOption,bEnabled);
+ //addWidgetToLayout(d,x1,y1,x2,y2);
+ m_pSelectorInterfaceList->append(d);
+ return d;
+}
+
+KviDirectorySelector * KviOptionsWidget::addDirectorySelector(int x1,int y1,int x2,int y2,const QString & txt,int optId,bool bEnabled)
+{
+ m_iResetFlags |= (g_stringOptionsTable[optId].flags & KviOption_resetMask);
+ KviDirectorySelector * d = addDirectorySelector(x1,y1,x2,y2,txt,&(KVI_OPTION_STRING(optId)),bEnabled);
+
+ QString tmp = m_szBasicTipStart;
+ tmp += g_stringOptionsTable[optId].name;
+ tmp += m_szBasicTipEnd;
+ KviTalToolTip::add(d,tmp);
+
+ return d;
+}
+
+KviDirectorySelector * KviOptionsWidget::addDirectorySelector(QWidget * pParent,const QString & txt,int optId,bool bEnabled)
+{
+ m_iResetFlags |= (g_stringOptionsTable[optId].flags & KviOption_resetMask);
+ KviDirectorySelector * d = addDirectorySelector(pParent,txt,&(KVI_OPTION_STRING(optId)),bEnabled);
+
+ QString tmp = m_szBasicTipStart;
+ tmp += g_stringOptionsTable[optId].name;
+ tmp += m_szBasicTipEnd;
+ KviTalToolTip::add(d,tmp);
+
+ return d;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+KviFileSelector * KviOptionsWidget::addFileSelector(int x1,int y1,int x2,int y2,const QString & txt,QString *pOption,bool bEnabled)
+{
+ KviFileSelector * d = new KviFileSelector(this,txt,pOption,bEnabled);
+ addWidgetToLayout(d,x1,y1,x2,y2);
+ m_pSelectorInterfaceList->append(d);
+ return d;
+}
+
+KviFileSelector * KviOptionsWidget::addFileSelector(QWidget * pParent,const QString & txt,QString *pOption,bool bEnabled)
+{
+ KviFileSelector * d = new KviFileSelector(pParent,txt,pOption,bEnabled);
+ m_pSelectorInterfaceList->append(d);
+ return d;
+}
+
+KviFileSelector * KviOptionsWidget::addFileSelector(int x1,int y1,int x2,int y2,const QString & txt,int optId,bool bEnabled)
+{
+ m_iResetFlags |= (g_stringOptionsTable[optId].flags & KviOption_resetMask);
+ KviFileSelector * d = addFileSelector(x1,y1,x2,y2,txt,&(KVI_OPTION_STRING(optId)),bEnabled);
+
+ QString tmp = m_szBasicTipStart;
+ tmp += g_stringOptionsTable[optId].name;
+ tmp += m_szBasicTipEnd;
+ KviTalToolTip::add(d,tmp);
+
+ return d;
+}
+
+KviFileSelector * KviOptionsWidget::addFileSelector(QWidget * pParent,const QString & txt,int optId,bool bEnabled)
+{
+ m_iResetFlags |= (g_stringOptionsTable[optId].flags & KviOption_resetMask);
+ KviFileSelector * d = addFileSelector(pParent,txt,&(KVI_OPTION_STRING(optId)),bEnabled);
+
+ QString tmp = m_szBasicTipStart;
+ tmp += g_stringOptionsTable[optId].name;
+ tmp += m_szBasicTipEnd;
+ KviTalToolTip::add(d,tmp);
+
+ return d;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+KviSoundSelector * KviOptionsWidget::addSoundSelector(int x1,int y1,int x2,int y2,const QString & txt,QString *pOption,bool bEnabled)
+{
+ KviSoundSelector * d = new KviSoundSelector(this,txt,pOption,bEnabled);
+ addWidgetToLayout(d,x1,y1,x2,y2);
+ m_pSelectorInterfaceList->append(d);
+ return d;
+}
+
+KviSoundSelector * KviOptionsWidget::addSoundSelector(QWidget * pParent,const QString & txt,QString *pOption,bool bEnabled)
+{
+ KviSoundSelector * d = new KviSoundSelector(pParent,txt,pOption,bEnabled);
+ m_pSelectorInterfaceList->append(d);
+ return d;
+}
+
+KviSoundSelector * KviOptionsWidget::addSoundSelector(int x1,int y1,int x2,int y2,const QString & txt,int optId,bool bEnabled)
+{
+ m_iResetFlags |= (g_stringOptionsTable[optId].flags & KviOption_resetMask);
+ KviSoundSelector * d = addSoundSelector(x1,y1,x2,y2,txt,&(KVI_OPTION_STRING(optId)),bEnabled);
+
+ QString tmp = m_szBasicTipStart;
+ tmp += g_stringOptionsTable[optId].name;
+ tmp += m_szBasicTipEnd;
+ KviTalToolTip::add(d,tmp);
+
+ return d;
+}
+
+KviSoundSelector * KviOptionsWidget::addSoundSelector(QWidget * pParent,const QString & txt,int optId,bool bEnabled)
+{
+ m_iResetFlags |= (g_stringOptionsTable[optId].flags & KviOption_resetMask);
+ KviSoundSelector * d = addSoundSelector(pParent,txt,&(KVI_OPTION_STRING(optId)),bEnabled);
+
+ QString tmp = m_szBasicTipStart;
+ tmp += g_stringOptionsTable[optId].name;
+ tmp += m_szBasicTipEnd;
+ KviTalToolTip::add(d,tmp);
+
+ return d;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+KviBoolSelector * KviOptionsWidget::addBoolSelector(int x1,int y1,int x2,int y2,const QString & txt,bool *pOption,bool bEnabled)
+{
+ KviBoolSelector * b = new KviBoolSelector(this,txt,pOption,bEnabled);
+ addWidgetToLayout(b,x1,y1,x2,y2);
+ m_pSelectorInterfaceList->append(b);
+ return b;
+}
+
+KviBoolSelector * KviOptionsWidget::addBoolSelector(QWidget * pParent,const QString & txt,bool *pOption,bool bEnabled)
+{
+ KviBoolSelector * b = new KviBoolSelector(pParent,txt,pOption,bEnabled);
+ m_pSelectorInterfaceList->append(b);
+ return b;
+}
+
+KviBoolSelector * KviOptionsWidget::addBoolSelector(int x1,int y1,int x2,int y2,const QString & txt,int optId,bool bEnabled)
+{
+ m_iResetFlags |= (g_boolOptionsTable[optId].flags & KviOption_resetMask);
+ KviBoolSelector * d = addBoolSelector(x1,y1,x2,y2,txt,&(KVI_OPTION_BOOL(optId)),bEnabled);
+ QString tmp = m_szBasicTipStart;
+ tmp += g_boolOptionsTable[optId].name;
+ tmp += m_szBasicTipEnd;
+ KviTalToolTip::add(d,tmp);
+ return d;
+}
+
+KviBoolSelector * KviOptionsWidget::addBoolSelector(QWidget * pParent,const QString & txt,int optId,bool bEnabled)
+{
+ m_iResetFlags |= (g_boolOptionsTable[optId].flags & KviOption_resetMask);
+ KviBoolSelector * d = addBoolSelector(pParent,txt,&(KVI_OPTION_BOOL(optId)),bEnabled);
+ QString tmp = m_szBasicTipStart;
+ tmp += g_boolOptionsTable[optId].name;
+ tmp += m_szBasicTipEnd;
+ KviTalToolTip::add(d,tmp);
+ return d;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+KviPixmapSelector * KviOptionsWidget::addPixmapSelector(int x1,int y1,int x2,int y2,const QString & txt,KviPixmap *pOption,bool bEnabled)
+{
+ KviPixmapSelector * b = new KviPixmapSelector(this,txt,pOption,bEnabled);
+ addWidgetToLayout(b,x1,y1,x2,y2);
+ m_pSelectorInterfaceList->append(b);
+ return b;
+}
+
+KviPixmapSelector * KviOptionsWidget::addPixmapSelector(int x1,int y1,int x2,int y2,const QString & txt,int optId,bool bEnabled)
+{
+ m_iResetFlags |= (g_pixmapOptionsTable[optId].flags & KviOption_resetMask);
+ KviPixmapSelector * d = addPixmapSelector(x1,y1,x2,y2,txt,&(KVI_OPTION_PIXMAP(optId)),bEnabled);
+ QString tmp = m_szBasicTipStart;
+ tmp += g_pixmapOptionsTable[optId].name;
+ tmp += m_szBasicTipEnd;
+ KviTalToolTip::add(d,tmp);
+ return d;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+KviUIntSelector * KviOptionsWidget::addUIntSelector(int x1,int y1,int x2,int y2,const QString & txt,
+ unsigned int * pOption,unsigned int uLowBound,
+ unsigned int uHighBound,unsigned int uDefault,bool bEnabled)
+{
+ KviUIntSelector * u = new KviUIntSelector(this,txt,pOption,uLowBound,uHighBound,uDefault,bEnabled,false);
+ addWidgetToLayout(u,x1,y1,x2,y2);
+ m_pSelectorInterfaceList->append(u);
+ return u;
+}
+
+KviUIntSelector * KviOptionsWidget::addUIntSelector(QWidget * pParent,const QString & txt,
+ unsigned int * pOption,unsigned int uLowBound,
+ unsigned int uHighBound,unsigned int uDefault,bool bEnabled)
+{
+ KviUIntSelector * u = new KviUIntSelector(pParent,txt,pOption,uLowBound,uHighBound,uDefault,bEnabled,false);
+ m_pSelectorInterfaceList->append(u);
+ return u;
+}
+
+KviUIntSelector * KviOptionsWidget::addUIntSelector(int x1,int y1,int x2,int y2,const QString & txt,
+ int optId,unsigned int uLowBound,
+ unsigned int uHighBound,unsigned int uDefault,bool bEnabled)
+{
+ m_iResetFlags |= (g_uintOptionsTable[optId].flags & KviOption_resetMask);
+ KviUIntSelector * d = addUIntSelector(x1,y1,x2,y2,txt,&(KVI_OPTION_UINT(optId)),uLowBound,uHighBound,uDefault,bEnabled);
+ QString tmp = m_szBasicTipStart;
+ tmp += g_uintOptionsTable[optId].name;
+ tmp += m_szBasicTipEnd;
+ KviTalToolTip::add(d,tmp);
+ return d;
+}
+
+KviUIntSelector * KviOptionsWidget::addUIntSelector(QWidget * pParent,const QString & txt,
+ int optId,unsigned int uLowBound,
+ unsigned int uHighBound,unsigned int uDefault,bool bEnabled)
+{
+ m_iResetFlags |= (g_uintOptionsTable[optId].flags & KviOption_resetMask);
+ KviUIntSelector * d = addUIntSelector(pParent,txt,&(KVI_OPTION_UINT(optId)),uLowBound,uHighBound,uDefault,bEnabled);
+ QString tmp = m_szBasicTipStart;
+ tmp += g_uintOptionsTable[optId].name;
+ tmp += m_szBasicTipEnd;
+ KviTalToolTip::add(d,tmp);
+ return d;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+
+KviUIntSelector * KviOptionsWidget::addUShortIntSelector(int x1,int y1,int x2,int y2,const QString & txt,
+ unsigned short int * pOption,unsigned int uLowBound,
+ unsigned int uHighBound,unsigned int uDefault,bool bEnabled)
+{
+ KviUIntSelector * u = new KviUIntSelector(this,txt,(unsigned int *)pOption,uLowBound,uHighBound,uDefault,bEnabled,true);
+ addWidgetToLayout(u,x1,y1,x2,y2);
+ m_pSelectorInterfaceList->append(u);
+ return u;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+KviStringSelector * KviOptionsWidget::addStringSelector(int x1,int y1,int x2,int y2,const QString & txt,QString *pOption,bool bEnabled)
+{
+ KviStringSelector * d = new KviStringSelector(this,txt,pOption,bEnabled);
+ addWidgetToLayout(d,x1,y1,x2,y2);
+ m_pSelectorInterfaceList->append(d);
+ return d;
+}
+
+KviStringSelector * KviOptionsWidget::addStringSelector(QWidget * pParent,const QString & txt,QString *pOption,bool bEnabled)
+{
+ KviStringSelector * d = new KviStringSelector(pParent,txt,pOption,bEnabled);
+ m_pSelectorInterfaceList->append(d);
+ return d;
+}
+
+KviStringSelector * KviOptionsWidget::addStringSelector(int x1,int y1,int x2,int y2,const QString & txt,int optId,bool bEnabled)
+{
+ m_iResetFlags |= (g_stringOptionsTable[optId].flags & KviOption_resetMask);
+ KviStringSelector * d = addStringSelector(x1,y1,x2,y2,txt,&(KVI_OPTION_STRING(optId)),bEnabled);
+ QString tmp = m_szBasicTipStart;
+ tmp += g_stringOptionsTable[optId].name;
+ tmp += m_szBasicTipEnd;
+ KviTalToolTip::add(d,tmp);
+ return d;
+}
+
+KviStringSelector * KviOptionsWidget::addStringSelector(QWidget * pParent,const QString & txt,int optId,bool bEnabled)
+{
+ m_iResetFlags |= (g_stringOptionsTable[optId].flags & KviOption_resetMask);
+ KviStringSelector * d = addStringSelector(pParent,txt,&(KVI_OPTION_STRING(optId)),bEnabled);
+ QString tmp = m_szBasicTipStart;
+ tmp += g_stringOptionsTable[optId].name;
+ tmp += m_szBasicTipEnd;
+ KviTalToolTip::add(d,tmp);
+ return d;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+KviPasswordSelector * KviOptionsWidget::addPasswordSelector(int x1,int y1,int x2,int y2,const QString & txt,QString *pOption,bool bEnabled)
+{
+ KviPasswordSelector * d = new KviPasswordSelector(this,txt,pOption,bEnabled);
+ addWidgetToLayout(d,x1,y1,x2,y2);
+ m_pSelectorInterfaceList->append(d);
+ return d;
+}
+
+KviPasswordSelector * KviOptionsWidget::addPasswordSelector(QWidget * pParent,const QString & txt,QString *pOption,bool bEnabled)
+{
+ KviPasswordSelector * d = new KviPasswordSelector(pParent,txt,pOption,bEnabled);
+ m_pSelectorInterfaceList->append(d);
+ return d;
+}
+
+KviPasswordSelector * KviOptionsWidget::addPasswordSelector(int x1,int y1,int x2,int y2,const QString & txt,int optId,bool bEnabled)
+{
+ m_iResetFlags |= (g_stringOptionsTable[optId].flags & KviOption_resetMask);
+ KviPasswordSelector * d = addPasswordSelector(x1,y1,x2,y2,txt,&(KVI_OPTION_STRING(optId)),bEnabled);
+ QString tmp = m_szBasicTipStart;
+ tmp += g_stringOptionsTable[optId].name;
+ tmp += m_szBasicTipEnd;
+ KviTalToolTip::add(d,tmp);
+ return d;
+}
+
+KviPasswordSelector * KviOptionsWidget::addPasswordSelector(QWidget * pParent,const QString & txt,int optId,bool bEnabled)
+{
+ m_iResetFlags |= (g_stringOptionsTable[optId].flags & KviOption_resetMask);
+ KviPasswordSelector * d = addPasswordSelector(pParent,txt,&(KVI_OPTION_STRING(optId)),bEnabled);
+ QString tmp = m_szBasicTipStart;
+ tmp += g_stringOptionsTable[optId].name;
+ tmp += m_szBasicTipEnd;
+ KviTalToolTip::add(d,tmp);
+ return d;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+KviStringListSelector * KviOptionsWidget::addStringListSelector(int x1,int y1,int x2,int y2,const QString & txt,QStringList * pOption,bool bEnabled)
+{
+ KviStringListSelector * d = new KviStringListSelector(this,txt,pOption,bEnabled);
+ addWidgetToLayout(d,x1,y1,x2,y2);
+ m_pSelectorInterfaceList->append(d);
+ return d;
+}
+
+KviStringListSelector * KviOptionsWidget::addStringListSelector(int x1,int y1,int x2,int y2,const QString & txt,int optId,bool bEnabled)
+{
+ m_iResetFlags |= (g_stringlistOptionsTable[optId].flags & KviOption_resetMask);
+ KviStringListSelector * d = addStringListSelector(x1,y1,x2,y2,txt,&(KVI_OPTION_STRINGLIST(optId)),bEnabled);
+ QString tmp = m_szBasicTipStart;
+ tmp += g_stringlistOptionsTable[optId].name;
+ tmp += m_szBasicTipEnd;
+ KviTalToolTip::add(d,tmp);
+ return d;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+KviColorSelector * KviOptionsWidget::addColorSelector(int x1,int y1,int x2,int y2,const QString & txt,QColor * pOption,bool bEnabled)
+{
+ KviColorSelector * s = new KviColorSelector(this,txt,pOption,bEnabled);
+ addWidgetToLayout(s,x1,y1,x2,y2);
+ m_pSelectorInterfaceList->append(s);
+ return s;
+}
+
+KviColorSelector * KviOptionsWidget::addColorSelector(QWidget * pParent,const QString & txt,QColor * pOption,bool bEnabled)
+{
+ KviColorSelector * s = new KviColorSelector(pParent,txt,pOption,bEnabled);
+ m_pSelectorInterfaceList->append(s);
+ return s;
+}
+
+KviColorSelector * KviOptionsWidget::addColorSelector(int x1,int y1,int x2,int y2,const QString & txt,int optId,bool bEnabled)
+{
+ m_iResetFlags |= (g_colorOptionsTable[optId].flags & KviOption_resetMask);
+ KviColorSelector * d = addColorSelector(x1,y1,x2,y2,txt,&(KVI_OPTION_COLOR(optId)),bEnabled);
+ QString tmp = m_szBasicTipStart;
+ tmp += g_colorOptionsTable[optId].name;
+ tmp += m_szBasicTipEnd;
+ KviTalToolTip::add(d,tmp);
+ return d;
+}
+
+KviColorSelector * KviOptionsWidget::addColorSelector(QWidget * pParent,const QString & txt,int optId,bool bEnabled)
+{
+ m_iResetFlags |= (g_colorOptionsTable[optId].flags & KviOption_resetMask);
+ KviColorSelector * d = addColorSelector(pParent,txt,&(KVI_OPTION_COLOR(optId)),bEnabled);
+ QString tmp = m_szBasicTipStart;
+ tmp += g_colorOptionsTable[optId].name;
+ tmp += m_szBasicTipEnd;
+ KviTalToolTip::add(d,tmp);
+ return d;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+KviMircTextColorSelector * KviOptionsWidget::addMircTextColorSelector(int x1,int y1,int x2,int y2,const QString & txt,unsigned int *uFore,unsigned int *uBack,bool bEnabled)
+{
+ KviMircTextColorSelector * s = new KviMircTextColorSelector(this,txt,uFore,uBack,bEnabled);
+ addWidgetToLayout(s,x1,y1,x2,y2);
+ m_pSelectorInterfaceList->append(s);
+ return s;
+}
+
+KviMircTextColorSelector * KviOptionsWidget::addMircTextColorSelector(QWidget * pParent,const QString & txt,unsigned int *uFore,unsigned int *uBack,bool bEnabled)
+{
+ KviMircTextColorSelector * s = new KviMircTextColorSelector(pParent,txt,uFore,uBack,bEnabled);
+ m_pSelectorInterfaceList->append(s);
+ return s;
+}
+
+KviMircTextColorSelector * KviOptionsWidget::addMircTextColorSelector(int x1,int y1,int x2,int y2,const QString & txt,int optForeId,int optBackId,bool bEnabled)
+{
+ m_iResetFlags |= (g_uintOptionsTable[optForeId].flags & KviOption_resetMask);
+ m_iResetFlags |= (g_uintOptionsTable[optBackId].flags & KviOption_resetMask);
+ KviMircTextColorSelector * d = addMircTextColorSelector(x1,y1,x2,y2,txt,&(KVI_OPTION_UINT(optForeId)),&(KVI_OPTION_UINT(optBackId)),bEnabled);
+ QString tmp = m_szBasicTipStart;
+ tmp += g_uintOptionsTable[optForeId].name;
+ tmp += m_szBasicTipEnd;
+ KviTalToolTip::add(d,tmp);
+ return d;
+}
+
+KviMircTextColorSelector * KviOptionsWidget::addMircTextColorSelector(QWidget * pParent,const QString & txt,int optForeId,int optBackId,bool bEnabled)
+{
+ m_iResetFlags |= (g_uintOptionsTable[optForeId].flags & KviOption_resetMask);
+ m_iResetFlags |= (g_uintOptionsTable[optBackId].flags & KviOption_resetMask);
+ KviMircTextColorSelector * d = addMircTextColorSelector(pParent,txt,&(KVI_OPTION_UINT(optForeId)),&(KVI_OPTION_UINT(optBackId)),bEnabled);
+ QString tmp = m_szBasicTipStart;
+ tmp += g_uintOptionsTable[optForeId].name;
+ tmp += m_szBasicTipEnd;
+ KviTalToolTip::add(d,tmp);
+ return d;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+KviFontSelector * KviOptionsWidget::addFontSelector(int x1,int y1,int x2,int y2,const QString & txt,QFont * pOption,bool bEnabled)
+{
+ KviFontSelector * f = new KviFontSelector(this,txt,pOption,bEnabled);
+ addWidgetToLayout(f,x1,y1,x2,y2);
+ m_pSelectorInterfaceList->append(f);
+ return f;
+}
+
+KviFontSelector * KviOptionsWidget::addFontSelector(QWidget * pParent,const QString & txt,QFont * pOption,bool bEnabled)
+{
+ KviFontSelector * f = new KviFontSelector(pParent,txt,pOption,bEnabled);
+ m_pSelectorInterfaceList->append(f);
+ return f;
+}
+
+KviFontSelector * KviOptionsWidget::addFontSelector(int x1,int y1,int x2,int y2,const QString & txt,int optId,bool bEnabled)
+{
+ m_iResetFlags |= (g_fontOptionsTable[optId].flags & KviOption_resetMask);
+ KviFontSelector * d = addFontSelector(x1,y1,x2,y2,txt,&(KVI_OPTION_FONT(optId)),bEnabled);
+ QString tmp = m_szBasicTipStart;
+ tmp += g_fontOptionsTable[optId].name;
+ tmp += m_szBasicTipEnd;
+ KviTalToolTip::add(d,tmp);
+ return d;
+}
+
+KviFontSelector * KviOptionsWidget::addFontSelector(QWidget * pParent,const QString & txt,int optId,bool bEnabled)
+{
+ m_iResetFlags |= (g_fontOptionsTable[optId].flags & KviOption_resetMask);
+ KviFontSelector * d = addFontSelector(pParent,txt,&(KVI_OPTION_FONT(optId)),bEnabled);
+ QString tmp = m_szBasicTipStart;
+ tmp += g_fontOptionsTable[optId].name;
+ tmp += m_szBasicTipEnd;
+ KviTalToolTip::add(d,tmp);
+ return d;
+}
+
+//#define DECLARE_COMMIT_FUNCTION(__fnc,__class,__classString)
+// void KviOptionsWidget::__fnc()
+// {
+// QObjectList * l = queryList(__classString);
+// if(!l)return;
+// QObjectListIt it(*l);
+// while(it.current())
+// {
+// ((__class *)it.current())->commit();
+// ++it;
+// }
+// delete l;
+// }
+
+//DECLARE_COMMIT_FUNCTION(commitBoolSelectors,KviBoolSelector,"KviBoolSelector")
+//DECLARE_COMMIT_FUNCTION(commitUIntSelectors,KviUIntSelector,"KviUIntSelector")
+//DECLARE_COMMIT_FUNCTION(commitStringSelectors,KviStringSelector,"KviStringSelector")
+//DECLARE_COMMIT_FUNCTION(commitPixmapSelectors,KviPixmapSelector,"KviPixmapSelector")
+
+void KviOptionsWidget::addRowSpacer(int x1,int y1,int x2,int y2)
+{
+ QWidget * w = new QWidget(this);
+ addWidgetToLayout(w,x1,y1,x2,y2);
+ layout()->setRowStretch(y1,1);
+}
+
+QLabel * KviOptionsWidget::addLabel(int x1,int y1,int x2,int y2,const QString & text,bool bEnabled)
+{
+ QLabel * l = new QLabel(text,this);
+#ifdef COMPILE_USE_QT4
+ l->setWordWrap(true);
+#endif
+ l->setEnabled(bEnabled);
+ addWidgetToLayout(l,x1,y1,x2,y2);
+ return l;
+}
+
+QLabel * KviOptionsWidget::addLabel(QWidget * pParent,const QString & text,bool bEnabled)
+{
+ QLabel * l = new QLabel(text,pParent);
+#ifdef COMPILE_USE_QT4
+ l->setWordWrap(true);
+#endif
+ l->setEnabled(bEnabled);
+ return l;
+}
+
+QLineEdit * KviOptionsWidget::addLineEdit(int x1,int y1,int x2,int y2,bool bEnabled)
+{
+ QLineEdit * l = new QLineEdit(this);
+ l->setEnabled(bEnabled);
+ addWidgetToLayout(l,x1,y1,x2,y2);
+ return l;
+}
+
+QFrame * KviOptionsWidget::addSeparator(int x1,int y1,int x2,int y2)
+{
+ QFrame * f = new QFrame(this);
+ f->setFrameStyle(QFrame::HLine | QFrame::Sunken);
+ addWidgetToLayout(f,x1,y1,x2,y2);
+ return f;
+}
+
+#ifdef COMPILE_USE_QT4
+KviTalGroupBox * KviOptionsWidget::addGroupBox(int x1,int y1,int x2,int y2,int nStrips,Qt::Orientation o,const QString &txt,bool bEnabled)
+#else
+KviTalGroupBox * KviOptionsWidget::addGroupBox(int x1,int y1,int x2,int y2,int nStrips,KviTalGroupBox::Orientation o,const QString &txt,bool bEnabled)
+#endif
+{
+ KviTalGroupBox * g = new KviTalGroupBox(nStrips,o,txt,this);
+ g->setEnabled(bEnabled);
+ addWidgetToLayout(g,x1,y1,x2,y2);
+ return g;
+}
+
+void KviOptionsWidget::addAdvancedButton(int x1,int y1,int x2,int y2)
+{
+ QWidget * w = topLevelWidget();
+ if(!w)return;
+ if(!w->inherits("KviGeneralOptionsDialog"))return;
+
+ QPushButton * b = new QPushButton(__tr2qs("Advanced..."),this);
+ connect(b,SIGNAL(clicked()),this,SLOT(switchToAdvancedPage()));
+ addWidgetToLayout(b,x1,y1,x2,y2);
+}
+
+
+void KviOptionsWidget::commitSelectors()
+{
+// if(m_iSelectors & KVI_OPTIONSELECTOR_TYPE_BOOL)commitBoolSelectors();
+// if(m_iSelectors & KVI_OPTIONSELECTOR_TYPE_UINT)commitUIntSelectors();
+// if(m_iSelectors & KVI_OPTIONSELECTOR_TYPE_STRING)commitStringSelectors();
+// if(m_iSelectors & KVI_OPTIONSELECTOR_TYPE_PIXMAP)commitPixmapSelectors();
+// m_iSelectors = 0;
+ for(KviSelectorInterface * i = m_pSelectorInterfaceList->first();i;i = m_pSelectorInterfaceList->next())
+ {
+ i->commit();
+ }
+}
+
+void KviOptionsWidget::commitOptionsReset()
+{
+ if(m_iResetFlags)g_pApp->optionResetUpdate(m_iResetFlags);
+ //m_iResetFlags = 0;
+}
+
+void KviOptionsWidget::commit()
+{
+ commitSelectors();
+ commitOptionsReset();
+}
+
+void KviOptionsWidget::switchToAdvancedPage()
+{
+ // FIXME: what happens if we're toplevel ????
+ // (so nobody listens to this signal....)
+
+ emit wantToSwitchToAdvancedPage(this);
+}
+
+#include "kvi_optionswidget.moc"
diff --git a/src/kvirc/ui/kvi_optionswidget.h b/src/kvirc/ui/kvi_optionswidget.h
new file mode 100644
index 00000000..84660939
--- /dev/null
+++ b/src/kvirc/ui/kvi_optionswidget.h
@@ -0,0 +1,163 @@
+#ifndef _KVI_OPTIONSWIDGET_H_
+#define _KVI_OPTIONSWIDGET_H_
+
+//=============================================================================
+//
+// File : kvi_optionswidget.h
+// Creation date : Mon Jun 10 2000 17:47:33 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#include <qframe.h>
+#include <qlayout.h>
+#include "kvi_pointerlist.h"
+#include <qlineedit.h>
+#include <kvi_tal_groupbox.h>
+#include <qtabwidget.h>
+#include "kvi_tal_groupbox.h"
+#include "kvi_selectors.h"
+
+class KVIRC_API KviOptionsWidget : public QFrame, public KviSelectorInterface
+{
+ Q_OBJECT
+public:
+ KviOptionsWidget(QWidget * parent,const char * name = 0,bool bSunken = true);
+ ~KviOptionsWidget();
+private:
+ QGridLayout * m_pLayout;
+ QTabWidget * m_pTabWidget;
+ int m_iResetFlags;
+ int m_iSelectors;
+ KviPointerList<KviSelectorInterface> * m_pSelectorInterfaceList;
+ static QString m_szBasicTipStart;
+ static QString m_szBasicTipEnd;
+public:
+ void mergeResetFlag(int flag){ m_iResetFlags |= flag; };
+ void createLayout(int rows,int columns);
+ QGridLayout * layout(){ return m_pLayout; };
+protected:
+ void commitSelectors();
+ void commitOptionsReset();
+public:
+ void mergeTip(QWidget * w,const QString &tip);
+
+ // tabbed page paradigm
+ void createTabbedPage();
+ void addOptionsWidget(const QString &szText,const QIconSet &iconSet,KviOptionsWidget * pWidget);
+ QTabWidget * tabWidget(){ return m_pTabWidget; };
+
+ // non tabbed page paradigm
+ KviBoolSelector * addBoolSelector(int x1,int y1,int x2,int y2,const QString & txt,bool * pOption,bool bEnabled = true);
+ KviBoolSelector * addBoolSelector(QWidget * pParent,const QString & txt,bool * pOption,bool bEnabled = true);
+ KviBoolSelector * addBoolSelector(int x1,int y1,int x2,int y2,const QString & txt,int optId,bool bEnabled = true);
+ KviBoolSelector * addBoolSelector(QWidget * pParnt,const QString & txt,int optId,bool bEnabled = true);
+
+ KviColorSelector * addColorSelector(int x1,int y1,int x2,int y2,const QString & txt,QColor * pOption,bool bEnabled = true);
+ KviColorSelector * addColorSelector(QWidget * pParent,const QString & txt,QColor * pOption,bool bEnabled = true);
+ KviColorSelector * addColorSelector(int x1,int y1,int x2,int y2,const QString & txt,int optId,bool bEnabled = true);
+ KviColorSelector * addColorSelector(QWidget * pParent,const QString & txt,int optId,bool bEnabled = true);
+
+ KviMircTextColorSelector * addMircTextColorSelector(int x1,int y1,int x2,int y2,const QString & txt,unsigned int *uFore,unsigned int *uBack,bool bEnabled = true);
+ KviMircTextColorSelector * addMircTextColorSelector(QWidget * pParent,const QString & txt,unsigned int *uFore,unsigned int *uBack,bool bEnabled = true);
+ KviMircTextColorSelector * addMircTextColorSelector(int x1,int y1,int x2,int y2,const QString & txt,int optForeId,int optBackId,bool bEnabled = true);
+ KviMircTextColorSelector * addMircTextColorSelector(QWidget * pParent,const QString & txt,int optForeId,int optBackId,bool bEnabled = true);
+
+ KviDirectorySelector * addDirectorySelector(int x1,int y1,int x2,int y2,const QString & txt,QString * pOption,bool bEnabled = true);
+ KviDirectorySelector * addDirectorySelector(QWidget * pParent,const QString & txt,QString * pOption,bool bEnabled = true);
+ KviDirectorySelector * addDirectorySelector(int x1,int y1,int x2,int y2,const QString & txt,int optId,bool bEnabled = true);
+ KviDirectorySelector * addDirectorySelector(QWidget * pParent,const QString & txt,int optId,bool bEnabled = true);
+
+ KviFileSelector * addFileSelector(int x1,int y1,int x2,int y2,const QString & txt,QString * pOption,bool bEnabled = true);
+ KviFileSelector * addFileSelector(QWidget * pParent,const QString & txt,QString * pOption,bool bEnabled = true);
+ KviFileSelector * addFileSelector(int x1,int y1,int x2,int y2,const QString & txt,int optId,bool bEnabled = true);
+ KviFileSelector * addFileSelector(QWidget * pParent,const QString & txt,int optId,bool bEnabled = true);
+
+ KviSoundSelector * addSoundSelector(int x1,int y1,int x2,int y2,const QString & txt,QString * pOption,bool bEnabled = true);
+ KviSoundSelector * addSoundSelector(QWidget * pParent,const QString & txt,QString * pOption,bool bEnabled = true);
+ KviSoundSelector * addSoundSelector(int x1,int y1,int x2,int y2,const QString & txt,int optId,bool bEnabled = true);
+ KviSoundSelector * addSoundSelector(QWidget * pParent,const QString & txt,int optId,bool bEnabled = true);
+
+
+ KviFontSelector * addFontSelector(int x1,int y1,int x2,int y2,const QString & txt,QFont * pOption,bool bEnabled = true);
+ KviFontSelector * addFontSelector(QWidget * pParent,const QString & txt,QFont * pOption,bool bEnabled = true);
+ KviFontSelector * addFontSelector(int x1,int y1,int x2,int y2,const QString & txt,int optId,bool bEnabled = true);
+ KviFontSelector * addFontSelector(QWidget * pParent,const QString & txt,int optId,bool bEnabled = true);
+
+ KviPasswordSelector * addPasswordSelector(int x1,int y1,int x2,int y2,const QString & txt,QString * pOption,bool bEnabled = true);
+ KviPasswordSelector * addPasswordSelector(QWidget * pParent,const QString & txt,QString * pOption,bool bEnabled = true);
+ KviPasswordSelector * addPasswordSelector(int x1,int y1,int x2,int y2,const QString & txt,int optId,bool bEnabled = true);
+ KviPasswordSelector * addPasswordSelector(QWidget * pParent,const QString & txt,int optId,bool bEnabled = true);
+
+ KviPixmapSelector * addPixmapSelector(int x1,int y1,int x2,int y2,const QString & txt,int optId,bool bEnabled = true);
+ KviPixmapSelector * addPixmapSelector(int x1,int y1,int x2,int y2,const QString & txt,KviPixmap * pOption,bool bEnabled = true);
+
+ KviStringListSelector * addStringListSelector(int x1,int y1,int x2,int y2,const QString & txt,QStringList * pOption,bool bEnabled = true);
+ KviStringListSelector * addStringListSelector(int x1,int y1,int x2,int y2,const QString & txt,int optId,bool bEnabled = true);
+
+ KviStringSelector * addStringSelector(int x1,int y1,int x2,int y2,const QString & txt,QString * pOption,bool bEnabled = true);
+ KviStringSelector * addStringSelector(QWidget * pParent,const QString & txt,QString * pOption,bool bEnabled = true);
+ KviStringSelector * addStringSelector(int x1,int y1,int x2,int y2,const QString & txt,int optId,bool bEnabled = true);
+ KviStringSelector * addStringSelector(QWidget * pParent,const QString & txt,int optId,bool bEnabled = true);
+
+ KviUIntSelector * addUIntSelector(int x1,int y1,int x2,int y2,const QString & txt,unsigned int * pOption,
+ unsigned int uLowBound,unsigned int uHighBound,unsigned int uDefault,bool bEnabled = true);
+ KviUIntSelector * addUIntSelector(QWidget * pParent,const QString & txt,unsigned int * pOption,
+ unsigned int uLowBound,unsigned int uHighBound,unsigned int uDefault,bool bEnabled = true);
+ KviUIntSelector * addUIntSelector(int x1,int y1,int x2,int y2,const QString & txt,int optId,
+ unsigned int uLowBound,unsigned int uHighBound,unsigned int uDefault,bool bEnabled = true);
+ KviUIntSelector * addUIntSelector(QWidget * pParent,const QString & txt,int optId,
+ unsigned int uLowBound,unsigned int uHighBound,unsigned int uDefault,bool bEnabled = true);
+
+
+ KviUIntSelector * addUShortIntSelector(int x1,int y1,int x2,int y2,const QString & txt,unsigned short int * pOption,
+ unsigned int uLowBound,unsigned int uHighBound,unsigned int uDefault,bool bEnabled = true);
+
+ QLabel * addLabel(int x1,int y1,int x2,int y2,const QString & text,bool bEnabled = true);
+ QLabel * addLabel(QWidget * pParent,const QString & text,bool bEnabled = true);
+ QLineEdit * addLineEdit(int x1,int y1,int x2,int y2,bool bEnabled = true);
+#ifdef COMPILE_USE_QT4
+ KviTalGroupBox * addGroupBox(int x1,int y1,int x2,int y2,int nStrips,Qt::Orientation o,const QString &txt,bool bEnabled = true);
+#else
+ KviTalGroupBox * addGroupBox(int x1,int y1,int x2,int y2,int nStrips,KviTalGroupBox::Orientation o,const QString &txt,bool bEnabled = true);
+#endif
+ QFrame * addSeparator(int x1,int y1,int x2,int y2);
+ void addRowSpacer(int x1,int y1,int x2,int y2);
+
+ void addWidgetToLayout(QWidget * w,int x1,int y1,int x2,int y2);
+
+ // this does NOT add the advanced button if this page is not inside a KviGeneralOptionsDialog
+ // this is because nobody listens to the "switchToAdvancedPage" requests....
+ void addAdvancedButton(int x1,int y1,int x2,int y2);
+
+ virtual void commit();
+protected slots:
+ // this is internal to the options dialog (options module)
+ // it attempts to show all the hidden subitems (usually the "Advanced...") page
+ // and switch to the first of them
+ void switchToAdvancedPage();
+signals:
+ // internal signal used for the stuff above
+ void wantToSwitchToAdvancedPage(KviOptionsWidget *);
+};
+
+
+#endif //!_KVI_OPTIONSWIDGET_H_
diff --git a/src/kvirc/ui/kvi_query.cpp b/src/kvirc/ui/kvi_query.cpp
new file mode 100644
index 00000000..c32c33f8
--- /dev/null
+++ b/src/kvirc/ui/kvi_query.cpp
@@ -0,0 +1,659 @@
+//=============================================================================
+//
+// File : kvi_query.cpp
+// Creation date : Tue Aug 7 2000 14:23:22 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+#include "kvi_query.h"
+#include "kvi_console.h"
+#include "kvi_iconmanager.h"
+#include "kvi_ircview.h"
+#include "kvi_input.h"
+#include "kvi_options.h"
+#include "kvi_locale.h"
+#include "kvi_settings.h"
+#include "kvi_ircsocket.h"
+#include "kvi_out.h"
+#include "kvi_taskbar.h"
+#include "kvi_config.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_settings.h"
+#include "kvi_themedlabel.h"
+#include "kvi_useraction.h"
+#include "kvi_parameterlist.h"
+#include "kvi_ircconnection.h"
+#include "kvi_ircconnectionuserinfo.h"
+#include "kvi_sparser.h"
+#include "kvi_ircuserdb.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_toolwindows_container.h"
+#include "kvi_qcstring.h"
+
+#ifdef COMPILE_CRYPT_SUPPORT
+ #include "kvi_crypt.h"
+ #include "kvi_cryptcontroller.h"
+#endif
+
+#include "kvi_kvs_eventtriggers.h"
+
+#include <qpixmap.h>
+#include <qsplitter.h>
+#include "kvi_tal_hbox.h"
+#include <qtoolbutton.h>
+#include "kvi_draganddrop.h"
+#include "kvi_valuelist.h"
+
+KviQuery::KviQuery(KviFrame * lpFrm,KviConsole * lpConsole,const QString &nick)
+: KviWindow(KVI_WINDOW_TYPE_QUERY,lpFrm,nick,lpConsole)
+{
+
+ m_iFlags = 0;
+ connection()->registerQuery(this);
+
+ //m_pTopSplitter = new QSplitter(QSplitter::Horizontal,this,"top_splitter");
+ m_pButtonBox = new KviTalHBox(this);
+ m_pLabel = new KviThemedLabel(m_pButtonBox,"query_label");
+ m_pLabel->setAutoHeight(1);
+ updateLabelText();
+ m_pButtonBox->setStretchFactor(m_pLabel,1);
+
+ // The button box on the right
+ //KviTalHBox * box = new KviTalHBox(m_pTopSplitter,"button_box");
+ if(KVI_OPTION_BOOL(KviOption_boolShowExtendedInfoInQueryLabel))
+ m_pButtonGrid= (QFrame*) new KviTalGrid(2,Qt::Horizontal,m_pButtonBox);
+ else
+ m_pButtonGrid= (QFrame*) new KviTalGrid(4,Qt::Horizontal,m_pButtonBox);
+
+ createTextEncodingButton(m_pButtonGrid);
+
+#ifdef COMPILE_USE_QT4
+ m_pSplitter = new QSplitter(Qt::Horizontal,this,"main_splitter");
+#else
+ m_pSplitter = new QSplitter(QSplitter::Horizontal,this,"main_splitter");
+#endif
+ m_pIrcView = new KviIrcView(m_pSplitter,lpFrm,this);
+ connect(m_pIrcView,SIGNAL(rightClicked()),this,SLOT(textViewRightClicked()));
+ //m_pEditorsContainer= new KviToolWindowsContainer(m_pSplitter);
+
+
+ m_pListViewButton = new KviWindowToolPageButton(KVI_SMALLICON_HIDELISTVIEW,KVI_SMALLICON_SHOWLISTVIEW,__tr2qs("Show User List"),buttonContainer(),true,"list_view_button");
+ connect(m_pListViewButton,SIGNAL(clicked()),this,SLOT(toggleListView()));
+
+#ifdef COMPILE_CRYPT_SUPPORT
+ createCryptControllerButton(m_pButtonGrid);
+#endif
+
+ m_pUserListView = new KviUserListView(m_pSplitter,m_pListViewButton,connection()->userDataBase(),this,7,__tr2qs("Query Targets"),"user_list_view");
+
+ m_pInput = new KviInput(this,m_pUserListView);
+
+ if(KVI_OPTION_BOOL(KviOption_boolAutoLogQueries)) m_pIrcView->startLogging();
+ // FIXME: #warning "Maybe tell the user all that we know about the remote end(s)....channels..."
+
+ m_pIrcView->enableDnd(TRUE);
+ connect(m_pIrcView,SIGNAL(fileDropped(const char *)),this,SLOT(slotDndEvents(const char *)));
+
+ updateCaption();
+}
+
+KviQuery::~KviQuery()
+{
+ m_pUserListView->partAll();
+ if(type() == KVI_WINDOW_TYPE_DEADQUERY)
+ context()->unregisterDeadQuery(this);
+ else
+ connection()->unregisterQuery(this);
+}
+
+void KviQuery::updateLabelText()
+{
+ QString szText=getInfoLabelText();
+ if(szText!=m_pLabel->text())
+ {
+ m_pLabel->setText(szText);
+ KviTalToolTip::add(m_pLabel,getInfoLabelTipText());
+ }
+}
+
+QString KviQuery::getInfoLabelTipText()
+{
+ QString txt;
+ KviIrcUserEntry * e = connection()->userDataBase()->find(m_szName);
+ if(e)
+ {
+ QString tmp;
+ QString szMask;
+ if(e->hasUser())
+ szMask+=e->user();
+ else
+ szMask+="*";
+ szMask+="@";
+ if(e->hasHost())
+ szMask+=e->host();
+ else
+ szMask+="*";
+ tmp+="\n";
+ QString szChans;
+ connection()->getCommonChannels(m_szName,szChans,0);
+ if(console()->connection())
+ {
+
+ txt = "<html>" \
+ "<body>" \
+ "<table width=\"100%\">";
+
+ txt += START_TABLE_BOLD_ROW;
+ txt += __tr2qs("Query target:");
+ txt += END_TABLE_BOLD_ROW;
+ txt += "<tr><td>";
+
+ if(e->hasRealName())
+ tmp=__tr2qs("%1 is %2 (%3)").arg(m_szName).arg(szMask).arg(KviMircCntrl::stripControlBytes(e->realName()));
+ else
+ tmp=__tr2qs("%1 is %2").arg(m_szName).arg(szMask);
+
+ tmp.replace('&',"&amp;");
+ tmp.replace('<',"&lt;");
+ tmp.replace('>',"&gt;");
+
+ txt += tmp;
+
+ txt += "</td></tr>";
+
+ if(e->hasServer())
+ {
+ txt+="<tr><td>";
+ if(e->hasHops())
+ txt+=__tr2qs("%1 is using irc server: %2 (%3 hops)").arg(m_szName).arg(e->server()).arg(e->hops());
+ else
+ txt+=__tr2qs("%1 is using irc server: %2").arg(m_szName).arg(e->server());
+ txt+="</td></tr>";
+ }
+
+ if(e->isAway())
+ {
+ txt+="<tr><td>";
+ txt+=__tr2qs("%1 is probably away").arg(m_szName);
+ txt+="</td></tr>";
+ }
+
+ txt+="<tr><td>";
+ tmp=__tr2qs("Common channels with %1: %2").arg(m_szName).arg(szChans);
+
+ tmp.replace('&',"&amp;");
+ tmp.replace('<',"&lt;");
+ tmp.replace('>',"&gt;");
+
+ txt+=tmp;
+ txt +="</td></tr>";
+
+ txt += "</table>" \
+ "</body>" \
+ "<html>";
+ } else {
+ txt=__tr2qs("[Dead Query]");
+ }
+ }
+ return txt;
+}
+
+QString KviQuery::getInfoLabelText()
+{
+ QString tmp;
+ if(KVI_OPTION_BOOL(KviOption_boolShowExtendedInfoInQueryLabel))
+ {
+ KviIrcUserEntry * e = connection()->userDataBase()->find(m_szName);
+ if(e)
+ {
+ QString szMask;
+ if(console()->connection())
+ {
+ if(e->hasUser())
+ szMask+=e->user();
+ else
+ szMask+="*";
+ szMask+="@";
+ if(e->hasHost())
+ szMask+=e->host();
+ else
+ szMask+="*";
+ if(e->hasRealName())
+ tmp=__tr2qs("Query with %1!%2 (%3)").arg(m_szName).arg(szMask).arg(KviMircCntrl::stripControlBytes(e->realName()));
+ else
+ tmp=__tr2qs("Query with %1!%2").arg(m_szName).arg(szMask);
+ if(e->hasServer())
+ tmp+=__tr2qs(", using server %1").arg(e->server());
+ if(e->hasHops())
+ tmp+=__tr2qs(" (%1 hops)").arg(e->hops());
+ if(e->isAway())
+ tmp+=__tr2qs(", probably away");
+ tmp+="\n";
+ QString szChans;
+ connection()->getCommonChannels(m_szName,szChans,0);
+ tmp+=__tr2qs("Common channels: %2").arg(szChans);
+ } else {
+ tmp=__tr2qs("[Dead Query]");
+ }
+ }
+ }
+ return tmp;
+}
+void KviQuery::slotDndEvents(const char *file)
+{
+ KVS_TRIGGER_EVENT_1(KviEvent_OnQueryFileDropped,this,QString(file));
+}
+
+void KviQuery::triggerCreationEvents()
+{
+ if(!KVI_OPTION_STRING(KviOption_stringOnNewQueryOpenedSound).isEmpty()) KviKvsScript::run("snd.play $0",0,new KviKvsVariantList(new KviKvsVariant(KVI_OPTION_STRING(KviOption_stringOnNewQueryOpenedSound))));
+ KVS_TRIGGER_EVENT_0(KviEvent_OnQueryWindowCreated,this);
+}
+
+void KviQuery::getBaseLogFileName(QString &buffer)
+{
+ if(console()->connection())
+ {
+ buffer=windowName();
+ buffer += ".";
+ buffer += console()->currentNetworkName();
+ } else {
+ buffer=windowName();
+ buffer+=".";
+ buffer+=console()->ircContextId();
+ }
+}
+
+void KviQuery::mergeQuery(KviQuery * q)
+{
+ m_pIrcView->appendMessagesFrom(q->m_pIrcView);
+ updateLabelText();
+}
+
+void KviQuery::textViewRightClicked()
+{
+ KVS_TRIGGER_EVENT_0(KviEvent_OnQueryPopupRequest,this);
+}
+
+void KviQuery::saveProperties(KviConfig *cfg)
+{
+ KviWindow::saveProperties(cfg);
+ cfg->writeEntry("Splitter",m_pSplitter->sizes());
+ cfg->writeEntry("UserListViewVisible",m_pUserListView->isVisible());
+}
+
+void KviQuery::loadProperties(KviConfig *cfg)
+{
+ int w = width();
+ KviWindow::loadProperties(cfg);
+ KviValueList<int> def;
+ def.append((w * 80) / 100);
+ def.append((w * 20) / 100);
+ m_pSplitter->setSizes(cfg->readIntListEntry("Splitter",def));
+ showListView(cfg->readBoolEntry("UserListViewVisible",false));
+}
+
+void KviQuery::notifyTargetChange(const QString &oldNick,const QString &oldUser,const QString &oldHost,const QString &nick,const QString &user,const QString &host)
+{
+ QString oldN = oldNick.isEmpty() ? QString("*") : oldNick;
+ QString oldU = oldUser.isEmpty() ? QString("*") : oldUser;
+ QString oldH = oldHost.isEmpty() ? QString("*") : oldHost;
+ output(KVI_OUT_QUERYTRACE,
+ __tr2qs("The target of this query has changed from \r!n\r%Q\r [%Q@\r!h\r%Q\r] to \r!n\r%Q\r [%Q@\r!h\r%Q\r]"),
+ &oldN,&oldU,&oldH,&nick,&user,&host);
+ updateLabelText();
+}
+
+
+void KviQuery::userAction(const QString &nick,const QString &user,const QString &host,unsigned int uActionType)
+{
+ int iTemperature = kvi_getUserActionTemperature(uActionType);
+ if(KVI_OPTION_BOOL(KviOption_boolEnableQueryTracing))
+ {
+ QString oldUser,oldHost;
+ if(!m_pUserListView->userActionVerifyMask(nick,user,host,iTemperature,oldUser,oldHost))
+ notifyTargetChange(nick,oldUser,oldHost,nick,user,host);
+ } else {
+ m_pUserListView->userAction(nick,user,host,iTemperature);
+ }
+ updateLabelText();
+}
+
+
+void KviQuery::userAction(const QString &nick,unsigned int uActionType)
+{
+ int iTemperature = kvi_getUserActionTemperature(uActionType);
+ m_pUserListView->userAction(nick,iTemperature);
+ updateLabelText();
+}
+
+void KviQuery::userAction(KviIrcMask *user,unsigned int uActionType)
+{
+ int iTemperature = kvi_getUserActionTemperature(uActionType);
+ if(KVI_OPTION_BOOL(KviOption_boolEnableQueryTracing))
+ {
+ QString oldUser,oldHost;
+ if(!m_pUserListView->userActionVerifyMask(user->nick(),user->user(),user->host(),iTemperature,oldUser,oldHost))
+ notifyTargetChange(user->nick(),oldUser,oldHost,user->nick(),user->user(),user->host());
+ } else {
+ m_pUserListView->userAction(user,iTemperature);
+ }
+ updateLabelText();
+}
+
+
+KviUserListEntry * KviQuery::setTarget(const QString &nick,const QString &user,const QString &host)
+{
+ KviUserListEntry * e = m_pUserListView->join(nick,user,host);
+ if((!e->globalData()->avatar()) && (!user.isEmpty()) && (user != "*"))
+ m_pConsole->checkDefaultAvatar(e->globalData(),nick,user,host);
+
+ setWindowName(nick);
+ updateCaption();
+
+ if(KVI_OPTION_BOOL(KviOption_boolEnableQueryTracing))
+ {
+ QString szChans;
+ int iChans = m_pConsole->connection()->getCommonChannels(nick,szChans);
+ notifyCommonChannels(nick,user,host,iChans,szChans);
+ }
+
+ KVS_TRIGGER_EVENT_3(KviEvent_OnQueryTargetAdded,this,nick,user,host);
+ updateLabelText();
+ return e;
+}
+
+void KviQuery::notifyCommonChannels(const QString &nick,const QString &user,const QString &host,int iChans,const QString &szChans)
+{
+ static QString star("*");
+ if(iChans > 0)
+ {
+ output(KVI_OUT_QUERYTRACE,__tr2qs("Common channels for \r!n\r%Q\r [%Q@\r!h\r%Q\r]: %Q"),
+ &nick,user.isEmpty() ? &star : &user,host.isEmpty() ? &star : &host,&szChans);
+ } else {
+ output(KVI_OUT_QUERYTRACE,__tr2qs("No common channels for \r!n\r%Q\r [%Q@\r!h\r%Q\r]"),
+ &nick,user.isEmpty() ? &star : &user,host.isEmpty() ? &star : &host);
+ }
+ updateLabelText();
+}
+
+
+
+
+/*void KviQuery::updateTargets()
+{
+ QString szName;
+
+ if(targetCount() > 0)
+ {
+ KviPointerHashTableIterator<QString,KviUserListEntry> it(*(m_pUserListView->entryDict()));
+ if(it.current())szName = it.currentKey();
+ }
+
+ if(szName.isEmpty())szName = __tr2qs("[No targets]");
+
+ setWindowName(szName);
+
+ updateCaption();
+}*/
+
+void KviQuery::fillCaptionBuffers()
+{
+ static QString begin("<nobr><font color=\"");
+ static QString boldbegin("\"><b>");
+ static QString endofbold("</b></font> <font color=\"");
+ static QString endoffont("\">");
+ static QString end("</font></nobr>");
+
+ if(!console()->connection())
+ {
+ QString dead = __tr2qs("[Dead query]");
+
+ m_szPlainTextCaption = windowName();
+ m_szPlainTextCaption += " : ";
+ m_szPlainTextCaption += dead;
+
+ m_szHtmlActiveCaption = begin;
+ m_szHtmlActiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextActive).name();
+ m_szHtmlActiveCaption += boldbegin;
+ m_szHtmlActiveCaption += windowName();
+ m_szHtmlActiveCaption += endofbold;
+ m_szHtmlActiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextActive2).name();
+ m_szHtmlActiveCaption += endoffont;
+ m_szHtmlActiveCaption += dead;
+ m_szHtmlActiveCaption += end;
+
+ m_szHtmlInactiveCaption = begin;
+ m_szHtmlInactiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextInactive).name();
+ m_szHtmlInactiveCaption += boldbegin;
+ m_szHtmlInactiveCaption += windowName();
+ m_szHtmlInactiveCaption += endofbold;
+ m_szHtmlInactiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextInactive2).name();
+ m_szHtmlInactiveCaption += endoffont;
+ m_szHtmlInactiveCaption += dead;
+ m_szHtmlInactiveCaption += end;
+
+ return;
+ }
+
+ QString szNickOnServer = QChar('[');
+ szNickOnServer += connection()->currentNickName();
+ szNickOnServer += __tr2qs(" on ");
+ szNickOnServer += connection()->currentServerName();
+ szNickOnServer += QChar(']');
+
+ m_szPlainTextCaption = windowName();
+ m_szPlainTextCaption += QChar(' ');
+ m_szPlainTextCaption += szNickOnServer;
+
+ m_szHtmlActiveCaption = begin;
+ m_szHtmlActiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextActive).name();
+ m_szHtmlActiveCaption += boldbegin;
+ m_szHtmlActiveCaption += windowName();
+ m_szHtmlActiveCaption += endofbold;
+ m_szHtmlActiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextActive2).name();
+ m_szHtmlActiveCaption += endoffont;
+ m_szHtmlActiveCaption += szNickOnServer;
+ m_szHtmlActiveCaption += end;
+
+ m_szHtmlInactiveCaption = begin;
+ m_szHtmlInactiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextInactive).name();
+ m_szHtmlInactiveCaption += boldbegin;
+ m_szHtmlInactiveCaption += windowName();
+ m_szHtmlInactiveCaption += endofbold;
+ m_szHtmlInactiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextInactive2).name();
+ m_szHtmlInactiveCaption += endoffont;
+ m_szHtmlInactiveCaption += szNickOnServer;
+ m_szHtmlInactiveCaption += end;
+}
+
+bool KviQuery::nickChange(const QString &oldNick,const QString &newNick)
+{
+ bool bRet = m_pUserListView->nickChange(oldNick,newNick);
+ if(!bRet)return false; // ugh!! ?
+ setWindowName(newNick);
+ updateCaption();
+ updateLabelText();
+ return bRet;
+}
+
+void KviQuery::showListView(bool bShow)
+{
+ if(!bShow)
+ {
+ m_pUserListView->hide();
+ if(m_pListViewButton->isOn())m_pListViewButton->setOn(false);
+ } else {
+ m_pUserListView->show();
+ if(!(m_pListViewButton->isOn()))m_pListViewButton->setOn(true);
+ }
+}
+
+void KviQuery::toggleListView()
+{
+ showListView(!m_pUserListView->isVisible());
+}
+
+void KviQuery::setDeadQuery()
+{
+ m_iFlags |= KVI_QUERY_FLAG_DEAD;
+
+ m_pUserListView->enableUpdates(false);
+ m_pUserListView->partAll();
+ m_pUserListView->enableUpdates(true);
+ m_pUserListView->setUserDataBase(0);
+ connection()->unregisterQuery(this);
+ context()->registerDeadQuery(this);
+ setType(KVI_WINDOW_TYPE_DEADQUERY);
+
+ updateIcon();
+ updateCaption();
+ updateLabelText();
+};
+
+void KviQuery::setAliveQuery()
+{
+ m_iFlags &= ~KVI_QUERY_FLAG_DEAD;
+ m_pUserListView->setUserDataBase(connection()->userDataBase());
+ setType(KVI_WINDOW_TYPE_QUERY);
+ context()->unregisterDeadQuery(this);
+ connection()->registerQuery(this);
+ // Update log file name
+ if(m_pIrcView->isLogging()) m_pIrcView->startLogging();
+ updateIcon();
+ updateCaption();
+ updateLabelText();
+}
+
+void KviQuery::applyOptions()
+{
+ m_pUserListView->applyOptions();
+ updateLabelText();
+ // this applies options for IrcView and Input and forces the window to relayout
+ KviWindow::applyOptions();
+}
+
+QPixmap * KviQuery::myIconPtr()
+{
+ return g_pIconManager->getSmallIcon(isDeadQuery() ? KVI_SMALLICON_DEADQUERY : KVI_SMALLICON_QUERY);
+}
+
+void KviQuery::resizeEvent(QResizeEvent *e)
+{
+ int hght = m_pInput->heightHint();
+ int hght2 = m_pButtonBox->sizeHint().height();
+ m_pButtonBox->setGeometry(0,0,width(),hght2);
+ m_pSplitter->setGeometry(0,hght2,width(),height() - (hght + hght2));
+ m_pInput->setGeometry(0,height() - hght,width(),hght);
+}
+
+QSize KviQuery::sizeHint() const
+{
+ QSize ret(m_pSplitter->sizeHint().width(),m_pIrcView->sizeHint().height() + m_pInput->heightHint());
+ return ret;
+}
+
+void KviQuery::ownMessage(const QString &buffer)
+{
+ if(!connection())
+ {
+ outputNoFmt(KVI_OUT_SYSTEMWARNING,__tr2qs("This query has no active targets, no message sent"));
+ return;
+ }
+
+ KviQCString szName = connection()->encodeText(windowName());
+ KviQCString szData = encodeText(buffer);
+
+ const char * d = szData.data();
+ if(!d)return;
+
+#ifdef COMPILE_CRYPT_SUPPORT
+ if(cryptSessionInfo())
+ {
+ if(cryptSessionInfo()->bDoEncrypt)
+ {
+ if(*d != KVI_TEXT_CRYPTESCAPE)
+ {
+ KviStr encrypted;
+ cryptSessionInfo()->pEngine->setMaxEncryptLen(500 - szName.length());
+ switch(cryptSessionInfo()->pEngine->encrypt(d,encrypted))
+ {
+ case KviCryptEngine::Encrypted:
+ if(!connection()->sendFmtData("PRIVMSG %s :%s",szName.data(),encrypted.ptr()))return;
+ m_pConsole->outputPrivmsg(this,KVI_OUT_OWNPRIVMSGCRYPTED,
+ QString::null,QString::null,QString::null,buffer,KviConsole::NoNotifications);
+ break;
+ case KviCryptEngine::Encoded:
+ {
+ if(!connection()->sendFmtData("PRIVMSG %s :%s",szName.data(),encrypted.ptr()))return;
+ // ugly ,but we must redecode here
+ QString szRedecoded = decodeText(encrypted.ptr());
+ m_pConsole->outputPrivmsg(this,KVI_OUT_OWNPRIVMSG,
+ QString::null,QString::null,QString::null,szRedecoded,KviConsole::NoNotifications);
+ }
+ break;
+ default: // also case KviCryptEngine::EncryptError
+ {
+ QString szEngineError = cryptSessionInfo()->pEngine->lastError();
+ output(KVI_OUT_SYSTEMERROR,
+ __tr2qs("The crypto engine was unable to encrypt the current message (%Q): %s, no data sent to the server"),
+ &buffer,&szEngineError);
+ }
+ break;
+ }
+ userAction(connection()->currentNickName(),KVI_USERACTION_PRIVMSG);
+ return;
+ } else {
+ d++; //eat the escape code
+ QString tmp = buffer.right(buffer.length() - 1);
+ if(!connection()->sendFmtData("PRIVMSG %s :%s",szName.data(),d))return;
+ m_pConsole->outputPrivmsg(this,KVI_OUT_OWNPRIVMSG,QString::null,QString::null,QString::null,tmp,KviConsole::NoNotifications);
+ userAction(connection()->currentNickName(),KVI_USERACTION_PRIVMSG);
+ return;
+ }
+ }
+ }
+#endif
+
+ if(!connection()->sendFmtData("PRIVMSG %s :%s",szName.data(),d))return;
+ m_pConsole->outputPrivmsg(this,KVI_OUT_OWNPRIVMSG,QString::null,QString::null,QString::null,buffer,KviConsole::NoNotifications);
+ userAction(connection()->currentNickName(),KVI_USERACTION_PRIVMSG);
+}
+
+void KviQuery::ownAction(const QString &buffer)
+{
+ if(!connection())
+ {
+ outputNoFmt(KVI_OUT_SYSTEMWARNING,__tr2qs("This query has no active targets, no message sent"));
+ } else {
+ KviQCString szBuffer = encodeText(buffer);
+ if(!szBuffer.data())return;
+ KviQCString sz = connection()->encodeText(windowName());
+ if(sz.isEmpty())return;
+ if(!connection()->sendFmtData("PRIVMSG %s :%cACTION %s%c",
+ sz.data(),0x01,szBuffer.data(),0x01))return;
+ if(KVS_TRIGGER_EVENT_1_HALTED(KviEvent_OnMeAction,this,QString(szBuffer.data())))return;
+ output(KVI_OUT_ACTION,"\r!nc\r%Q\r %Q",&(connection()->currentNickName()),&buffer);
+ m_pUserListView->userAction(connection()->currentNickName(),KVI_USERACTION_ACTION);
+ }
+}
+
+#include "kvi_query.moc"
diff --git a/src/kvirc/ui/kvi_query.h b/src/kvirc/ui/kvi_query.h
new file mode 100644
index 00000000..ba087acb
--- /dev/null
+++ b/src/kvirc/ui/kvi_query.h
@@ -0,0 +1,95 @@
+#ifndef _KVI_QUERY_H_
+#define _KVI_QUERY_H_
+//=============================================================================
+//
+// File : kvi_query.h
+// Creation date : Mon Aug 7 2000 14:19:00 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_window.h"
+#include "kvi_string.h"
+#include "kvi_ircuserdb.h"
+#include "kvi_userlistview.h"
+#include "kvi_themedlabel.h"
+
+#include "kvi_pointerhashtable.h"
+#include "kvi_tal_grid.h"
+
+class KviConsole;
+class KviConfig;
+class QSplitter;
+class KviWindowToolPageButton;
+
+#define KVI_QUERY_FLAG_DEAD 1
+
+class KVIRC_API KviQuery : public KviWindow
+{
+ Q_OBJECT
+public:
+ KviQuery(KviFrame * lpFrm,KviConsole * lpConsole,const QString &nick);
+ ~KviQuery();
+protected:
+ KviUserListView * m_pUserListView;
+ KviWindowToolPageButton * m_pListViewButton;
+ int m_iFlags;
+ KviThemedLabel * m_pLabel;
+ QFrame * m_pButtonGrid;
+protected:
+ virtual QPixmap * myIconPtr();
+ virtual void fillCaptionBuffers();
+ virtual void resizeEvent(QResizeEvent *e);
+ virtual void loadProperties(KviConfig * cfg);
+ virtual void saveProperties(KviConfig * cfg);
+ virtual void getBaseLogFileName(QString &buffer);
+ virtual void triggerCreationEvents();
+public:
+ void setDeadQuery();
+ void setAliveQuery();
+ bool isDeadQuery(){ return m_iFlags & KVI_QUERY_FLAG_DEAD; };
+ virtual QSize sizeHint() const;
+ virtual const QString & target(){ return windowName(); };
+ virtual void applyOptions();
+ KviUserListEntry * setTarget(const QString &nick,const QString &user,const QString &host);
+ void userAction(KviIrcMask *user,unsigned int uActionType);
+ void userAction(const QString &nick,unsigned int uActionType);
+ void userAction(const QString &nick,const QString &user,const QString &host,unsigned int uActionType);
+ bool nickChange(const QString &oldNick,const QString &newNick);
+ void ownMessage(const QString &buffer);
+ void ownAction(const QString &buffer);
+ int selectedCount(){ return m_pUserListView->selectedCount(); };
+ bool avatarChanged(const QString &nick){ return m_pUserListView->avatarChanged(nick); };
+ void notifyCommonChannels(const QString &nick,const QString &user,const QString &host,int iChans,const QString &szChans);
+ void showListView(bool bShow);
+ void mergeQuery(KviQuery * q);
+ void updateLabelText();
+ QFrame * buttonContainer() { return (QFrame*)m_pButtonGrid; };
+protected:
+ void notifyTargetChange(const QString &oldNick,const QString &oldUser,const QString &oldHost,const QString &nick,const QString &user,const QString &host);
+ QString getInfoLabelText();
+ QString getInfoLabelTipText();
+protected slots:
+ void textViewRightClicked();
+ void toggleListView();
+ void slotDndEvents(const char *);
+};
+
+#endif //_KVI_CHANNEL_H_
diff --git a/src/kvirc/ui/kvi_scriptbutton.cpp b/src/kvirc/ui/kvi_scriptbutton.cpp
new file mode 100644
index 00000000..7b4a8e71
--- /dev/null
+++ b/src/kvirc/ui/kvi_scriptbutton.cpp
@@ -0,0 +1,98 @@
+//
+// File : kvi_scriptbutton.cpp
+// Creation date : Wed Nov 14 15:43:41 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+#define __KVIRC__
+#include "kvi_scriptbutton.h"
+#include "kvi_irctoolbar.h"
+#include "kvi_window.h"
+#include "kvi_console.h"
+#include "kvi_app.h"
+#include "kvi_parameterlist.h"
+#include "kvi_kvs_variantlist.h"
+#include "kvi_kvs_script.h"
+
+
+KviScriptUserButton::KviScriptUserButton(QWidget * par,const char * name)
+: KviStyledToolButton(par,name)
+{
+ m_pScript = 0;
+// setAutoRaise(true);
+ connect(this,SIGNAL(clicked()),this,SLOT(btnClicked()));
+ setAutoRaise(true);
+}
+
+KviScriptUserButton::~KviScriptUserButton()
+{
+ if(m_pScript)delete m_pScript;
+}
+
+KviWindow * KviScriptUserButton::window()
+{
+ return g_pActiveWindow;
+}
+
+void KviScriptUserButton::setButtonCode(KviKvsScript * pScript)
+{
+ if(m_pScript)delete m_pScript;
+ m_pScript = pScript;
+}
+
+
+void KviScriptUserButton::btnClicked()
+{
+ KviWindow * pWnd = window();
+ if(!pWnd)return; // ops...
+ QPoint pos = mapToGlobal(QPoint(0,height()));
+
+ KviKvsVariantList vList;
+ vList.append((kvs_int_t)pos.x());
+ vList.append((kvs_int_t)pos.y());
+ m_pScript->run(pWnd,&vList,0,KviKvsScript::PreserveParams);
+}
+/*
+
+KviIrcToolBarScriptButton::KviIrcToolBarScriptButton(QToolBar * p,const char * name)
+: KviScriptUserButton(p,name)
+{
+ setAutoRaise(true);
+}
+
+KviIrcToolBarScriptButton::~KviIrcToolBarScriptButton()
+{
+}
+
+KviWindow * KviIrcToolBarScriptButton::window()
+{
+ return g_pActiveWindow;
+}
+*/
+
+KviWindowScriptButton::KviWindowScriptButton(QWidget * p,KviWindow * wnd,const char * name)
+: KviScriptUserButton(p,name)
+{
+ m_pWnd = wnd;
+}
+
+KviWindowScriptButton::~KviWindowScriptButton()
+{
+}
+
+#include "kvi_scriptbutton.moc"
diff --git a/src/kvirc/ui/kvi_scriptbutton.h b/src/kvirc/ui/kvi_scriptbutton.h
new file mode 100644
index 00000000..79740c86
--- /dev/null
+++ b/src/kvirc/ui/kvi_scriptbutton.h
@@ -0,0 +1,79 @@
+#ifndef _KVI_SCRIPTBUTTON_H_
+#define _KVI_SCRIPTBUTTON_H_
+//
+// File : kvi_scriptbutton.h
+// Creation date : Wed Nov 14 15:43:39 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+#include "kvi_string.h"
+#include "kvi_styled_controls.h"
+
+#include <qtoolbutton.h>
+#include <qtoolbar.h>
+
+class KviKvsScript;
+class KviWindow;
+
+class KVIRC_API KviScriptUserButton : public KviStyledToolButton
+{
+ Q_OBJECT
+public:
+ KviScriptUserButton(QWidget * par,const char * name);
+ ~KviScriptUserButton();
+protected:
+ KviKvsScript * m_pScript;
+public:
+ void setButtonCode(KviKvsScript * pScript);
+ virtual void setButtonPixmap(const QPixmap & pix){ setIconSet(pix); };
+ void setButtonText(const char * text){ setTextLabel(text); };
+ virtual KviWindow * window();
+protected slots:
+ void btnClicked();
+};
+
+/*
+class KVIRC_API KviIrcToolBarScriptButton : public KviScriptUserButton
+{
+ Q_OBJECT
+public:
+ KviIrcToolBarScriptButton(QToolBar * p,const char * name);
+ ~KviIrcToolBarScriptButton();
+protected:
+ KviStr m_szCode;
+public:
+ virtual KviWindow * window();
+};
+*/
+
+class KVIRC_API KviWindowScriptButton : public KviScriptUserButton
+{
+ Q_OBJECT
+public:
+ KviWindowScriptButton(QWidget * p,KviWindow * wnd,const char * name);
+ ~KviWindowScriptButton();
+protected:
+ KviWindow * m_pWnd;
+public:
+ virtual void setButtonPixmap(const QPixmap & pix){ setIconSet(pix); setUsesBigPixmap(false); };
+ virtual KviWindow * window(){ return m_pWnd; };
+};
+
+#endif //_KVI_SCRIPTBUTTON_H_
diff --git a/src/kvirc/ui/kvi_scripteditor.cpp b/src/kvirc/ui/kvi_scripteditor.cpp
new file mode 100644
index 00000000..f94000da
--- /dev/null
+++ b/src/kvirc/ui/kvi_scripteditor.cpp
@@ -0,0 +1,139 @@
+//
+// File : kvi_scripteditor.cpp
+// Creation date : Sun Mar 28 1999 16:12:41 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#define __KVIRC__
+
+#define _KVI_SCRIPTEDITOR_CPP_
+
+#define _KVI_DEBUG_CHECK_RANGE_
+#include "kvi_debug.h"
+
+#include "kvi_scripteditor.h"
+#include "kvi_modulemanager.h"
+
+
+KviScriptEditor::KviScriptEditor(QWidget * par)
+: QWidget(par)
+{
+}
+
+
+KviScriptEditor::~KviScriptEditor()
+{
+}
+
+void KviScriptEditor::setText(const char * txt)
+{
+ setText(KviQCString(txt));
+}
+
+void KviScriptEditor::setText(const KviQCString &txt)
+{
+}
+
+void KviScriptEditor::setText(const QString &txt)
+{
+ setText(KviQCString(txt.utf8()));
+}
+
+void KviScriptEditor::setFindText(const QString &text)
+{
+}
+void KviScriptEditor::setInfoText(const QString &text)
+{
+}
+
+void KviScriptEditor::setFindLineeditReadOnly(bool b)
+{
+}
+
+void KviScriptEditor::getText(KviQCString &txt)
+{
+}
+
+void KviScriptEditor::setCursorPosition(QPoint)
+{
+}
+
+bool KviScriptEditor::isModified()
+{
+ return false;
+}
+
+QPoint KviScriptEditor::getCursor()
+{
+ return QPoint(0,0);
+}
+void KviScriptEditor::getText(QString &txt)
+{
+ KviQCString tmp;
+ getText(tmp);
+ txt = QString::fromUtf8(tmp.data());
+}
+
+KviScriptEditor * KviScriptEditor::getDummyEditor(QWidget * par)
+{
+ return new KviScriptEditor(par);
+}
+
+
+static KviScriptEditor * (*editorModuleCreateScriptEditor)(QWidget *);
+static void (*editorModuleDestroyScriptEditor)(KviScriptEditor *);
+
+
+KviScriptEditor * KviScriptEditor::createInstance(QWidget * par)
+{
+ KviModule * m = g_pModuleManager->getModule("editor");
+ // If the module can't be loaded...return a dummy widget
+// FIXME: #warning "Maybe provide some sort of basic default editable widget ?"
+ if(!m)return KviScriptEditor::getDummyEditor(par); // dummy implementation
+
+
+ editorModuleCreateScriptEditor = (KviScriptEditor * (*)(QWidget *)) m->getSymbol("editor_module_createScriptEditor");
+
+ if(!editorModuleCreateScriptEditor)return KviScriptEditor::getDummyEditor(par);
+
+ return editorModuleCreateScriptEditor(par);
+
+}
+
+void KviScriptEditor::destroyInstance(KviScriptEditor * e)
+{
+ KviModule * m = g_pModuleManager->getModule("editor");
+ if(!m)
+ {
+ delete e;
+ return;
+ }
+
+ editorModuleDestroyScriptEditor = (void (*)(KviScriptEditor *)) m->getSymbol("editor_module_destroyScriptEditor");
+
+ if(!editorModuleDestroyScriptEditor)
+ {
+ delete e;
+ return;
+ }
+
+ editorModuleDestroyScriptEditor(e);
+}
+
+#include "kvi_scripteditor.moc"
diff --git a/src/kvirc/ui/kvi_scripteditor.h b/src/kvirc/ui/kvi_scripteditor.h
new file mode 100644
index 00000000..e9f04c26
--- /dev/null
+++ b/src/kvirc/ui/kvi_scripteditor.h
@@ -0,0 +1,69 @@
+#ifndef _KVI_SCRIPTEDITOR_H_
+#define _KVI_SCRIPTEDITOR_H_
+
+//
+// File : kvi_scripteditor.h
+// Creation date : Sun Mar 28 1999 16:11:48 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+#include <qwidget.h>
+#include <qlineedit.h>
+#include "kvi_qcstring.h"
+
+//
+// This is the basic interface of a script editor widget
+//
+// Actually the REAL script editor is implemented in an
+// external module called "libkvieditor", and it is a really
+// huge class.
+// The constructor of this thing is protected: forget
+// about instantiating it directly
+//
+
+
+class KVIRC_API KviScriptEditor : public QWidget
+{
+ Q_OBJECT
+protected:
+ KviScriptEditor(QWidget * par);
+ ~KviScriptEditor();
+protected:
+ QLineEdit * m_pFindLineedit;
+public:
+ virtual void setText(const char * txt);
+ virtual void setText(const KviQCString &txt);
+ virtual void setText(const QString &txt);
+ virtual void getText(KviQCString &txt);
+ virtual void getText(QString &txt);
+ virtual void setInfoText(const QString &text);
+ virtual void setFindText(const QString &text);
+ virtual void setCursorPosition(QPoint);
+ virtual QPoint getCursor();
+ virtual void setFindLineeditReadOnly(bool b);
+ virtual bool isModified();
+
+ static KviScriptEditor * getDummyEditor(QWidget * par);
+ static KviScriptEditor * createInstance(QWidget * par);
+ static void destroyInstance(KviScriptEditor * e);
+};
+
+
+#endif //!_KVI_SCRIPTEDITOR_H_
diff --git a/src/kvirc/ui/kvi_selectors.cpp b/src/kvirc/ui/kvi_selectors.cpp
new file mode 100644
index 00000000..f8c9af9f
--- /dev/null
+++ b/src/kvirc/ui/kvi_selectors.cpp
@@ -0,0 +1,839 @@
+//=============================================================================
+//
+// File : kvi_selectors.cpp
+// Creation date : Mon Nov 13 2000 15:22:12 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#define _KVI_SELECTORS_CPP_
+
+#include "kvi_selectors.h"
+#include "kvi_locale.h"
+#include "kvi_options.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_filedialog.h"
+#include "kvi_kvs_script.h"
+
+#include <qlabel.h>
+#include <qpainter.h>
+#include <qlayout.h>
+#include <qcolordialog.h>
+#include <qpalette.h>
+#include <qfontdialog.h>
+#include "kvi_tal_popupmenu.h"
+
+KviBoolSelector::KviBoolSelector(QWidget * par,const QString & txt,bool *pOption,bool bEnabled)
+: KviStyledCheckBox(txt,par), KviSelectorInterface()
+{
+ setEnabled(bEnabled);
+ setChecked(*pOption);
+ m_pOption = pOption;
+}
+
+void KviBoolSelector::setNotEnabled(bool bNotEnabled)
+{
+ setEnabled(!bNotEnabled);
+}
+
+void KviBoolSelector::commit()
+{
+ *m_pOption = isChecked();
+}
+
+KviUIntSelector::KviUIntSelector(QWidget * par,const QString & txt,unsigned int *pOption,
+ unsigned int uLowBound,unsigned int uHighBound,unsigned int uDefault,bool bEnabled,bool bShortInt)
+: KviTalHBox(par) , KviSelectorInterface()
+{
+ m_pLabel = new QLabel(txt,this);
+ //m_pLineEdit = new QLineEdit(this);
+ //m_pLineEdit->setMaximumWidth(150);
+ m_pSpinBox = new QSpinBox(this);
+
+ m_bIsShortInt = bShortInt;
+
+ setEnabled(bEnabled);
+
+ m_pOption = pOption;
+
+ m_uLowBound = uLowBound;
+ m_uHighBound = uHighBound;
+ m_uDefault = uDefault;
+
+ m_pSpinBox->setMinValue(m_uLowBound);
+ m_pSpinBox->setMaxValue(m_uHighBound);
+
+ //KviStr tmp(KviStr::Format,"%u",bShortInt ? (unsigned int) *((unsigned short int *)pOption) : *pOption);
+ //m_pLineEdit->setText(tmp.ptr());
+ m_pSpinBox->setValue(bShortInt ? (unsigned int) *((unsigned short int *)pOption) : *pOption);
+
+ setSpacing(4);
+ setStretchFactor(m_pLabel,1);
+}
+
+void KviUIntSelector::setPrefix(const QString & txt)
+{
+ m_pSpinBox->setPrefix(txt);
+}
+
+void KviUIntSelector::setSuffix(const QString & txt)
+{
+ m_pSpinBox->setSuffix(txt);
+}
+
+void KviUIntSelector::commit()
+{
+ KviStr tmp = m_pSpinBox->cleanText();
+ bool bOk;
+ unsigned int val = tmp.toUInt(&bOk);
+ if(!bOk)val = m_uDefault;
+ if(m_uHighBound > m_uLowBound)
+ {
+ if(val < m_uLowBound)val = m_uLowBound;
+ else if(val > m_uHighBound)val = m_uHighBound;
+ }
+
+ if(m_bIsShortInt)*((unsigned short int *)m_pOption) = (unsigned short int)val;
+ else *m_pOption = val;
+}
+
+
+void KviUIntSelector::setEnabled(bool bEnabled)
+{
+ KviTalHBox::setEnabled(bEnabled);
+ m_pLabel->setEnabled(bEnabled);
+ m_pSpinBox->setEnabled(bEnabled);
+}
+
+
+
+KviStringSelector::KviStringSelector(QWidget * par,const QString & txt,QString * pOption,bool bEnabled)
+: KviTalHBox(par) , KviSelectorInterface()
+{
+ m_pLabel = new QLabel(txt,this);
+ m_pLineEdit = new QLineEdit(this);
+ //m_pLineEdit->setMinimumWidth(200);
+ QString tmp = *pOption;
+ m_pLineEdit->setText(tmp);
+
+ setSpacing(4);
+ setStretchFactor(m_pLineEdit,1);
+
+ m_pOption = pOption;
+
+ setEnabled(bEnabled);
+}
+
+KviStringSelector::~KviStringSelector()
+{
+}
+
+void KviStringSelector::commit()
+{
+ QString tmp = m_pLineEdit->text();
+ *m_pOption = tmp;
+}
+
+void KviStringSelector::setEnabled(bool bEnabled)
+{
+ KviTalHBox::setEnabled(bEnabled);
+ m_pLineEdit->setEnabled(bEnabled);
+ m_pLabel->setEnabled(bEnabled);
+}
+
+void KviStringSelector::setText(const QString& text){
+ m_pLineEdit->setText(text);
+}
+
+KviPasswordSelector::KviPasswordSelector(QWidget * par,const QString & txt,QString *pOption,bool bEnabled)
+: KviStringSelector(par,txt,pOption,bEnabled)
+{
+ m_pLineEdit->setEchoMode(QLineEdit::Password);
+}
+
+
+
+
+KviPixmapPreview::KviPixmapPreview(QWidget * par)
+: KviTalScrollView(par)
+{
+ m_pPixmap = 0;
+ resizeContents(0,0);
+}
+
+
+KviPixmapPreview::~KviPixmapPreview()
+{
+}
+
+void KviPixmapPreview::setPixmap(KviPixmap * pix)
+{
+ m_pPixmap = pix;
+ if(m_pPixmap)
+ {
+ if(m_pPixmap->pixmap())
+ {
+ resizeContents(m_pPixmap->pixmap()->width(),m_pPixmap->pixmap()->height());
+ update();
+ return;
+ }
+ }
+ resizeContents(0,0);
+ update();
+}
+
+void KviPixmapPreview::drawContents(QPainter * p, int clipx, int clipy, int clipw, int cliph)
+{
+ if(m_pPixmap)
+ {
+ if(m_pPixmap->pixmap())
+ {
+ p->drawPixmap(clipx,clipy,*(m_pPixmap->pixmap()),clipx,clipy,clipw,cliph);
+ }
+ }
+}
+
+
+KviPixmapSelector::KviPixmapSelector(QWidget * par,const QString & txt,KviPixmap * pOption,bool bEnabled)
+: QWidget(par), KviSelectorInterface()
+{
+ QGridLayout * g = new QGridLayout(this,3,2,4,8);
+ m_pOption = pOption;
+
+ m_localPixmap = *pOption;
+
+ m_pCheckBox = new KviStyledCheckBox(txt,this);
+ m_pCheckBox->setChecked(m_localPixmap.pixmap());
+ connect(m_pCheckBox,SIGNAL(toggled(bool)),this,SLOT(checkBoxToggled(bool)));
+ g->addMultiCellWidget(m_pCheckBox,0,0,0,1);
+
+ m_pPreview = new KviPixmapPreview(this);
+ m_pPreview->setPixmap(&m_localPixmap);
+ g->addMultiCellWidget(m_pPreview,1,1,0,1);
+
+ m_pFileNameLabel = new QLabel(this);
+ m_pFileNameLabel->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
+ if(m_localPixmap.pixmap())m_pFileNameLabel->setText(m_localPixmap.path());
+ g->addWidget(m_pFileNameLabel,2,0);
+
+ m_pChooseButton = new QPushButton("...",this);
+ g->addWidget(m_pChooseButton,2,1);
+ connect(m_pChooseButton,SIGNAL(clicked()),this,SLOT(choosePixmap()));
+
+ g->setRowStretch(1,1);
+ g->setColStretch(0,1);
+
+ setEnabled(bEnabled);
+}
+
+KviPixmapSelector::~KviPixmapSelector()
+{
+}
+
+
+void KviPixmapSelector::checkBoxToggled(bool bEnabled)
+{
+ setEnabled(isEnabled());
+}
+
+void KviPixmapSelector::commit()
+{
+ if(m_pCheckBox->isChecked())
+ {
+ *m_pOption = m_localPixmap;
+ } else {
+ *m_pOption = KviPixmap(); // null pixmap
+ }
+}
+
+void KviPixmapSelector::choosePixmap()
+{
+// KviStr tmp;
+ QString tmp;
+ if(KviFileDialog::askForOpenFileName(tmp,__tr("Choose an Image File - KVIrc")))
+ {
+ setImagePath(tmp);
+ }
+}
+
+void KviPixmapSelector::setImagePath(const char * path)
+{
+ m_localPixmap.load(path);
+ m_pPreview->setPixmap(&m_localPixmap);
+
+ if(m_localPixmap.isNull())
+ {
+ KviStr tmp2(KviStr::Format,__tr("Unloadable: %s"),path);
+ m_pFileNameLabel->setText(tmp2.ptr());
+ m_pCheckBox->setChecked(false);
+ } else {
+ m_pCheckBox->setChecked(true);
+ m_pFileNameLabel->setText(path);
+ }
+
+ setEnabled(isEnabled());
+}
+
+void KviPixmapSelector::setEnabled(bool bEnabled)
+{
+ QWidget::setEnabled(bEnabled);
+ m_pCheckBox->setEnabled(bEnabled);
+ m_pPreview->setEnabled(bEnabled && m_pCheckBox->isChecked());
+ m_pFileNameLabel->setEnabled(bEnabled && m_pCheckBox->isChecked());
+ m_pChooseButton->setEnabled(bEnabled && m_pCheckBox->isChecked());
+}
+
+
+
+// FIXME: #warning "Option for DIR_MUST_EXISTS...(this widget could be turned into a file selector too)"
+KviFileSelector::KviFileSelector(QWidget * par,const QString & txt,QString * pOption,bool bEnabled,unsigned int uFlags,const QString &szFilter)
+: KviTalHBox(par), KviSelectorInterface()
+{
+ m_uFlags = uFlags;
+ m_szFilter = szFilter;
+ m_pLabel = new QLabel(txt,this);
+ m_pLineEdit = new QLineEdit(this);
+ //m_pLineEdit->setMinimumWidth(200);
+ m_pLineEdit->setText(*pOption);
+ m_pButton = new QPushButton(__tr2qs("&Browse..."),this);
+ connect(m_pButton,SIGNAL(clicked()),this,SLOT(browseClicked()));
+
+ setSpacing(4);
+ setStretchFactor(m_pLineEdit,1);
+
+ m_pOption = pOption;
+
+ setEnabled(bEnabled);
+}
+
+
+void KviFileSelector::commit()
+{
+ *m_pOption = m_pLineEdit->text();
+}
+
+void KviFileSelector::setEnabled(bool bEnabled)
+{
+ KviTalHBox::setEnabled(bEnabled);
+ m_pLineEdit->setEnabled(bEnabled);
+ m_pLabel->setEnabled(bEnabled);
+ m_pButton->setEnabled(bEnabled);
+}
+
+void KviFileSelector::browseClicked()
+{
+ select();
+}
+
+void KviFileSelector::setSelection(const QString &szSelection)
+{
+ m_pLineEdit->setText(szSelection);
+}
+
+
+void KviFileSelector::select()
+{
+ //KviStr tmp;
+ QString tmp = *m_pOption;
+ if(m_uFlags & ChooseSaveFileName)
+ {
+ if(KviFileDialog::askForSaveFileName(tmp,__tr2qs("Choose a File - KVIrc"),tmp,m_szFilter,true,!(m_uFlags & DontConfirmOverwrite)))
+ {
+ m_pLineEdit->setText(tmp);
+ emit selectionChanged(tmp);
+ }
+ } else {
+ if(KviFileDialog::askForOpenFileName(tmp,__tr2qs("Choose a File - KVIrc"),tmp,m_szFilter,true))
+ {
+ m_pLineEdit->setText(tmp);
+ emit selectionChanged(tmp);
+ }
+ }
+
+}
+
+
+KviDirectorySelector::KviDirectorySelector(QWidget * par,const QString & txt,QString * pOption,bool bEnabled)
+: KviFileSelector(par,txt,pOption,bEnabled)
+{
+}
+
+void KviDirectorySelector::select()
+{
+ QString tmp;
+ if(KviFileDialog::askForDirectoryName(tmp,__tr2qs("Choose a Directory - KVIrc"),""))
+ {
+ m_pLineEdit->setText(tmp);
+ }
+
+}
+
+
+
+
+
+
+
+
+KviStringListSelector::KviStringListSelector(QWidget * par,const QString & txt,QStringList * pOption,bool bEnabled)
+: KviTalVBox(par), KviSelectorInterface()
+{
+ m_pLabel = new QLabel(txt,this);
+ m_pListBox = new KviTalListBox(this);
+ m_pLineEdit = new QLineEdit(this);
+ connect(m_pLineEdit,SIGNAL(textChanged(const QString &)),this,SLOT(textChanged(const QString &)));
+ connect(m_pLineEdit,SIGNAL(returnPressed()),this,SLOT(addClicked()));
+ KviTalHBox * hBox = new KviTalHBox(this);
+ m_pAddButton = new QPushButton(__tr2qs("A&dd"),hBox);
+ connect(m_pAddButton,SIGNAL(clicked()),this,SLOT(addClicked()));
+ m_pRemoveButton = new QPushButton(__tr2qs("Re&move"),hBox);
+ connect(m_pRemoveButton,SIGNAL(clicked()),this,SLOT(removeClicked()));
+ m_pOption = pOption;
+ m_pListBox->insertStringList(*pOption);
+ m_pListBox->setSelectionMode(KviTalListBox::Extended);
+ connect(m_pListBox,SIGNAL(selectionChanged()),this,SLOT(selectionChanged()));
+ setSpacing(4);
+ setStretchFactor(m_pListBox,1);
+ setEnabled(bEnabled);
+}
+
+KviStringListSelector::~KviStringListSelector()
+{
+}
+
+void KviStringListSelector::selectionChanged()
+{
+ unsigned int uCount = m_pListBox->count();
+ bool bSomeSelected = false;
+ for(unsigned int u=0;u<uCount;u++)
+ {
+ if(m_pListBox->isSelected(u))
+ {
+ bSomeSelected = true;
+ break;
+ }
+ }
+ m_pRemoveButton->setEnabled(isEnabled() && bSomeSelected);
+}
+
+void KviStringListSelector::textChanged(const QString &str)
+{
+ str.stripWhiteSpace();
+ m_pAddButton->setEnabled((str.length() > 0) && isEnabled());
+}
+
+void KviStringListSelector::setEnabled(bool bEnabled)
+{
+ KviTalVBox::setEnabled(bEnabled);
+ m_pLineEdit->setEnabled(bEnabled);
+ m_pLabel->setEnabled(bEnabled);
+ QString txt = m_pLineEdit->text();
+ txt.stripWhiteSpace();
+ m_pAddButton->setEnabled(bEnabled && (txt.length() > 0));
+ unsigned int uCount = m_pListBox->count();
+ bool bSomeSelected = false;
+ for(unsigned int u=0;u<uCount;u++)
+ {
+ if(m_pListBox->isSelected(u))
+ {
+ bSomeSelected = true;
+ break;
+ }
+ }
+ m_pRemoveButton->setEnabled(bEnabled && bSomeSelected);
+ m_pListBox->setEnabled(bEnabled);
+}
+
+void KviStringListSelector::commit()
+{
+ unsigned int uCount = m_pListBox->count();
+ m_pOption->clear();
+ for(unsigned int u=0;u<uCount;u++)
+ {
+ QString str = m_pListBox->text(u);
+ str.stripWhiteSpace();
+ if(str.length() > 0)m_pOption->append(str);
+ }
+}
+
+void KviStringListSelector::addClicked()
+{
+ QString str = m_pLineEdit->text();
+ str.stripWhiteSpace();
+ if(str.length() > 0)m_pListBox->insertItem(str);
+ m_pLineEdit->setText("");
+}
+
+void KviStringListSelector::removeClicked()
+{
+ unsigned int uCount = m_pListBox->count();
+ for(unsigned int u=0;u<uCount;u++)
+ {
+ while(m_pListBox->isSelected(u))m_pListBox->removeItem(u);
+ }
+}
+
+
+KviColorSelector::KviColorSelector(QWidget * par,const QString & txt,QColor * pOption,bool bEnabled)
+: KviTalHBox(par), KviSelectorInterface()
+{
+ m_pLabel = new QLabel(txt,this);
+
+ m_pButton = new QPushButton(" ",this);
+ // m_pButton->setMinimumWidth(150);
+ connect(m_pButton,SIGNAL(clicked()),this,SLOT(changeClicked()));
+
+ setSpacing(4);
+ setStretchFactor(m_pLabel,1);
+
+ setButtonPalette(pOption);
+
+ m_pOption = pOption;
+
+ setEnabled(bEnabled);
+}
+
+void KviColorSelector::setButtonPalette(QColor * pOption)
+{
+ QPalette pal(*pOption,colorGroup().background());
+ m_memColor = *pOption;
+ m_pButton->setPalette(pal);
+
+ QPixmap pix(16,16);
+ pix.fill(*pOption);
+ m_pButton->setIconSet(pix);
+}
+
+void KviColorSelector::forceColor(QColor clr)
+{
+ setButtonPalette(&clr);
+}
+
+void KviColorSelector::changeClicked()
+{
+ QColor tmp = QColorDialog::getColor(m_memColor);
+ if(tmp.isValid())setButtonPalette(&tmp);
+}
+
+void KviColorSelector::commit()
+{
+ *m_pOption = m_memColor;
+}
+
+void KviColorSelector::setEnabled(bool bEnabled)
+{
+ KviTalHBox::setEnabled(bEnabled);
+ m_pLabel->setEnabled(bEnabled);
+ m_pButton->setEnabled(bEnabled);
+}
+
+
+KviFontSelector::KviFontSelector(QWidget * par,const QString & txt,QFont * pOption,bool bEnabled)
+: KviTalHBox(par), KviSelectorInterface()
+{
+ m_pLabel = new QLabel(txt,this);
+
+ m_pButton = new QPushButton("",this);
+ // m_pButton->setMinimumWidth(150);
+ connect(m_pButton,SIGNAL(clicked()),this,SLOT(changeClicked()));
+
+ setSpacing(4);
+ setStretchFactor(m_pLabel,1);
+
+ setButtonFont(pOption);
+
+ m_pOption = pOption;
+
+ setEnabled(bEnabled);
+}
+
+void KviFontSelector::setButtonFont(QFont * pOption)
+{
+ m_pButton->setText(pOption->family());
+ m_pButton->setFont(*pOption);
+}
+
+void KviFontSelector::changeClicked()
+{
+ bool bOk;
+ QFont tmp = QFontDialog::getFont(&bOk,m_pButton->font());
+ if(bOk)setButtonFont(&tmp);
+}
+
+void KviFontSelector::commit()
+{
+ *m_pOption = m_pButton->font();
+}
+
+void KviFontSelector::setEnabled(bool bEnabled)
+{
+ KviTalHBox::setEnabled(bEnabled);
+ m_pLabel->setEnabled(bEnabled);
+ m_pButton->setEnabled(bEnabled);
+}
+
+
+
+
+
+KviMircTextColorSelector::KviMircTextColorSelector(QWidget * par,const QString &txt,unsigned int * uFore,unsigned int * uBack,bool bEnabled)
+: KviTalHBox(par), KviSelectorInterface()
+{
+ m_pLabel = new QLabel(txt,this);
+
+ m_pButton = new QPushButton(__tr2qs("Sample Text"),this);
+ // m_pButton->setMinimumWidth(150);
+ connect(m_pButton,SIGNAL(clicked()),this,SLOT(buttonClicked()));
+
+ setSpacing(4);
+ setStretchFactor(m_pLabel,1);
+
+ m_pUFore = uFore;
+ m_pUBack = uBack;
+
+ m_uBack = *uBack;
+ m_uFore = *uFore;
+
+ setButtonPalette();
+
+ setEnabled(bEnabled);
+
+ m_pContextPopup = new KviTalPopupMenu(this);
+
+ m_pForePopup = new KviTalPopupMenu(this);
+ connect(m_pForePopup,SIGNAL(activated(int)),this,SLOT(foreSelected(int)));
+ int i;
+ for(i=0;i<KVI_MIRCCOLOR_MAX_FOREGROUND;i++)
+ {
+ QPixmap tmp(120,16);
+ tmp.fill(KVI_OPTION_MIRCCOLOR(i));
+#ifdef COMPILE_USE_QT4
+ int id = m_pForePopup->insertItem(tmp,QString("x"));
+#else
+ int id = m_pForePopup->insertItem(tmp);
+#endif
+ m_pForePopup->setItemParameter(id,i);
+ }
+ m_pContextPopup->insertItem(__tr2qs("Foreground"),m_pForePopup);
+
+ m_pBackPopup = new KviTalPopupMenu(this);
+ connect(m_pBackPopup,SIGNAL(activated(int)),this,SLOT(backSelected(int)));
+ i = m_pBackPopup->insertItem(__tr2qs("Transparent"));
+ m_pBackPopup->setItemParameter(i,KVI_TRANSPARENT);
+ for(i=0;i<KVI_MIRCCOLOR_MAX_BACKGROUND;i++)
+ {
+ QPixmap tmp(120,16);
+ tmp.fill(KVI_OPTION_MIRCCOLOR(i));
+#ifdef COMPILE_USE_QT4
+ int id = m_pForePopup->insertItem(tmp,QString("x"));
+#else
+ int id = m_pBackPopup->insertItem(tmp);
+#endif
+ m_pBackPopup->setItemParameter(id,i);
+ }
+ m_pContextPopup->insertItem(__tr2qs("Background"),m_pBackPopup);
+}
+
+KviMircTextColorSelector::~KviMircTextColorSelector()
+{
+}
+
+void KviMircTextColorSelector::commit()
+{
+ *m_pUFore = m_uFore;
+ *m_pUBack = m_uBack;
+}
+
+void KviMircTextColorSelector::setEnabled(bool bEnabled)
+{
+ KviTalHBox::setEnabled(bEnabled);
+ m_pLabel->setEnabled(bEnabled);
+ m_pButton->setEnabled(bEnabled);
+}
+
+void KviMircTextColorSelector::setButtonPalette()
+{
+ QPalette pal;
+
+ if(m_uBack > KVI_MIRCCOLOR_MAX_BACKGROUND)
+ {
+ if(m_uBack != KVI_TRANSPARENT)m_uBack = KVI_TRANSPARENT;
+ pal = palette();
+ } else {
+ pal = QPalette(KVI_OPTION_MIRCCOLOR(m_uBack));
+ }
+
+ if(m_uFore > KVI_MIRCCOLOR_MAX_FOREGROUND)m_uFore = KVI_MIRCCOLOR_MAX_FOREGROUND;
+
+ pal.setColor(QColorGroup::ButtonText,KVI_OPTION_MIRCCOLOR(m_uFore));
+ pal.setColor(QColorGroup::Text,KVI_OPTION_MIRCCOLOR(m_uFore));
+
+ m_pButton->setPalette(pal);
+}
+
+void KviMircTextColorSelector::buttonClicked()
+{
+ QPoint p = m_pButton->mapToGlobal(QPoint(0,m_pButton->height()));
+ m_pContextPopup->popup(p);
+}
+
+void KviMircTextColorSelector::foreSelected(int id)
+{
+ if(m_pForePopup)
+ m_uFore = m_pForePopup->itemParameter(id);
+ setButtonPalette();
+}
+
+void KviMircTextColorSelector::backSelected(int id)
+{
+ if(m_pBackPopup)
+ m_uBack = m_pBackPopup->itemParameter(id);
+ setButtonPalette();
+}
+
+KviSoundSelector::KviSoundSelector(QWidget * par,const QString & txt,QString * pOption,bool bEnabled)
+:KviFileSelector(par,txt,pOption,bEnabled)
+{
+ m_pPlayButton = new QPushButton(__tr2qs("Play"),this);
+ connect(m_pPlayButton,SIGNAL(clicked()),this,SLOT(playSound()));
+}
+
+KviSoundSelector::~KviSoundSelector()
+{
+}
+
+void KviSoundSelector::playSound()
+{
+ KviKvsScript::run("snd.play $0",0,new KviKvsVariantList(new KviKvsVariant(m_pLineEdit->text())));
+}
+
+void KviSoundSelector::setEnabled(bool bEnabled)
+{
+ KviFileSelector::setEnabled(bEnabled);
+ m_pPlayButton->setEnabled(bEnabled);
+}
+
+KviChanListViewItem::KviChanListViewItem(KviTalListView* pList,QString szChan,QString szPass)
+:KviTalListViewItem(pList,szChan)
+{
+ m_szPass=szPass;
+ QString mask;
+ mask.fill('*',szPass.length());
+ setText(1,mask);
+}
+
+KviCahnnelListSelector::KviCahnnelListSelector(QWidget * par,const QString & txt,QStringList * pOption,bool bEnabled)
+: KviTalVBox(par), KviSelectorInterface()
+{
+ m_pLabel = new QLabel(txt,this);
+ m_pListView = new KviTalListView(this);
+ m_pListView->addColumn(__tr2qs("Channel name"));
+ m_pListView->addColumn(__tr2qs("Channel password"));
+
+ KviTalHBox* pEditsHBox = new KviTalHBox(this);
+
+ m_pChanLineEdit = new QLineEdit(pEditsHBox);
+ connect(m_pChanLineEdit,SIGNAL(textChanged(const QString &)),this,SLOT(textChanged(const QString &)));
+ connect(m_pChanLineEdit,SIGNAL(returnPressed()),this,SLOT(addClicked()));
+
+ m_pPassLineEdit = new QLineEdit(pEditsHBox);
+ m_pPassLineEdit->setEchoMode(QLineEdit::Password);
+ connect(m_pPassLineEdit,SIGNAL(textChanged(const QString &)),this,SLOT(textChanged(const QString &)));
+ connect(m_pPassLineEdit,SIGNAL(returnPressed()),this,SLOT(addClicked()));
+
+
+ KviTalHBox * hBox = new KviTalHBox(this);
+ m_pAddButton = new QPushButton(__tr2qs("A&dd"),hBox);
+ connect(m_pAddButton,SIGNAL(clicked()),this,SLOT(addClicked()));
+ m_pRemoveButton = new QPushButton(__tr2qs("Re&move"),hBox);
+ connect(m_pRemoveButton,SIGNAL(clicked()),this,SLOT(removeClicked()));
+ m_pOption = pOption;
+
+ for ( QStringList::Iterator it = pOption->begin(); it != pOption->end(); ++it ) {
+ new KviChanListViewItem(m_pListView,(*it).section(':',0,0),(*it).section(':',1));
+ }
+
+ m_pListView->setSelectionMode(KviTalListView::Extended);
+ m_pListView->setAllColumnsShowFocus(TRUE);
+ connect(m_pListView,SIGNAL(selectionChanged()),this,SLOT(selectionChanged()));
+ setSpacing(4);
+ setStretchFactor(m_pListView,1);
+ setEnabled(bEnabled);
+}
+
+KviCahnnelListSelector::~KviCahnnelListSelector()
+{
+}
+
+void KviCahnnelListSelector::commit()
+{
+ m_pOption->clear();
+ register KviChanListViewItem* pItem;
+ KviTalListViewItemIterator it( m_pListView);
+ while ( it.current() ) {
+ pItem = (KviChanListViewItem*)( it.current() );
+ m_pOption->append(pItem->text(0)+":"+pItem->pass());
+ ++it;
+ }
+}
+
+void KviCahnnelListSelector::setEnabled(bool bEnabled)
+{
+ m_pLabel->setEnabled(bEnabled);
+ m_pListView->setEnabled(bEnabled);
+ m_pChanLineEdit->setEnabled(bEnabled);
+ m_pPassLineEdit->setEnabled(bEnabled);
+ m_pAddButton->setEnabled(bEnabled);
+ m_pRemoveButton->setEnabled(bEnabled);
+}
+
+void KviCahnnelListSelector::textChanged(const QString &str)
+{
+ m_pAddButton->setEnabled(!m_pChanLineEdit->text().isEmpty());
+}
+
+void KviCahnnelListSelector::selectionChanged()
+{
+}
+
+void KviCahnnelListSelector::addClicked()
+{
+ if(!m_pChanLineEdit->text().isEmpty())
+ {
+ new KviChanListViewItem(m_pListView,m_pChanLineEdit->text().stripWhiteSpace(),m_pPassLineEdit->text().stripWhiteSpace());
+ m_pChanLineEdit->clear();
+ m_pPassLineEdit->clear();
+ }
+}
+
+void KviCahnnelListSelector::removeClicked()
+{
+ KviPointerList<KviTalListViewItem> lst;
+ KviTalListViewItemIterator it( m_pListView, KviTalListViewItemIterator::Selected );
+ while ( it.current() ) {
+ lst.append((KviTalListViewItem *)it.current() );
+ ++it;
+ }
+ lst.setAutoDelete(TRUE);
+ lst.clear();
+}
+
+#include "kvi_selectors.moc"
diff --git a/src/kvirc/ui/kvi_selectors.h b/src/kvirc/ui/kvi_selectors.h
new file mode 100644
index 00000000..3e620127
--- /dev/null
+++ b/src/kvirc/ui/kvi_selectors.h
@@ -0,0 +1,367 @@
+#ifndef _KVI_SELECTORS_H_
+#define _KVI_SELECTORS_H_
+
+//=============================================================================
+//
+// File : kvi_selectors.h
+// Creation date : Mon Now 13 2000 15:21:10 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+
+#include "kvi_settings.h"
+
+#include <qcheckbox.h>
+#include "kvi_tal_hbox.h"
+#include "kvi_tal_vbox.h"
+#include <qlineedit.h>
+#include <qlabel.h>
+#include "kvi_tal_scrollview.h"
+#include <qpushbutton.h>
+#include <qcolor.h>
+#include <qfont.h>
+#include "kvi_tal_listbox.h"
+#include "kvi_tal_listview.h"
+#include <qspinbox.h>
+#include <qstringlist.h>
+#include <qvalidator.h>
+
+#include "kvi_string.h"
+#include "kvi_pixmap.h"
+#include "kvi_styled_controls.h"
+
+//#ifndef _KVI_SELECTORS_CPP_
+// extern void commitAllSelectors(QWidget * par,const char * classname);
+//#endif
+
+
+//
+// This is the common KviSelectorInterface
+//
+// Note: I'm always learning
+// Today I have discovered that:
+// QObject * o = new KviBoolSelector(...)
+// ((KviSelectorInterface *)o)->commit()
+// Does not work (SIGSEGV when jumping into commit(): bad vtable entry)
+// But the following works fine:
+// KviBoolSelector * b = new KviBoolSelector(...)
+// ((KviSelectorInterface *)b)->commit();
+// Mmmmmh.... the assembler generated by gcc
+// uses two different vtable offsets in the two cases
+// why ?
+//
+
+class KVIRC_API KviSelectorInterface
+{
+public:
+ KviSelectorInterface(){};
+ virtual ~KviSelectorInterface(){};
+public:
+ virtual void commit(){};
+};
+
+class KVIRC_API KviBoolSelector : public KviStyledCheckBox, public KviSelectorInterface
+{
+ Q_OBJECT
+public:
+ KviBoolSelector(QWidget * par,const QString & txt,bool *pOption,bool bEnabled);
+ ~KviBoolSelector(){};
+private:
+ bool * m_pOption;
+public:
+ virtual void commit();
+public slots:
+ void setNotEnabled(bool bNotEnabled);
+};
+
+class KVIRC_API KviStringSelector : public KviTalHBox, public KviSelectorInterface
+{
+ Q_OBJECT
+public:
+ KviStringSelector(QWidget * par,const QString & txt,QString * pOption,bool bEnabled);
+ ~KviStringSelector();
+protected:
+ QLabel * m_pLabel;
+ QLineEdit * m_pLineEdit;
+ QString * m_pOption;
+public:
+ void setValidator(QValidator * v){ m_pLineEdit->setValidator(v); };
+ void setMinimumLabelWidth(unsigned int uWidth){ m_pLabel->setMinimumWidth(uWidth); };
+ virtual void commit();
+ virtual void setEnabled(bool bEnabled);
+ void setText(const QString& text);
+};
+
+
+class KVIRC_API KviPasswordSelector : public KviStringSelector
+{
+ Q_OBJECT
+public:
+ KviPasswordSelector(QWidget * par,const QString & txt,QString * pOption,bool bEnabled);
+ ~KviPasswordSelector(){};
+};
+
+class KVIRC_API KviPixmapPreview : public KviTalScrollView
+{
+ Q_OBJECT
+public:
+ KviPixmapPreview(QWidget * par);
+ ~KviPixmapPreview();
+protected:
+ KviPixmap * m_pPixmap;
+public:
+ void setPixmap(KviPixmap * pix);
+protected:
+ virtual void drawContents(QPainter * p, int clipx, int clipy, int clipw, int cliph);
+
+};
+
+class KVIRC_API KviPixmapSelector : public QWidget, public KviSelectorInterface
+{
+ Q_OBJECT
+public:
+ KviPixmapSelector(QWidget * par,const QString & txt,KviPixmap * pOption,bool bEnabled);
+ ~KviPixmapSelector();
+private:
+ KviStyledCheckBox * m_pCheckBox;
+ QLabel * m_pFileNameLabel;
+ KviPixmapPreview * m_pPreview;
+ QPushButton * m_pChooseButton;
+ KviPixmap * m_pOption;
+ KviPixmap m_localPixmap;
+public:
+ void setImagePath(const char * path);
+ virtual void commit();
+ virtual void setEnabled(bool bEnabled);
+protected slots:
+ void checkBoxToggled(bool bEnabled);
+ void choosePixmap();
+};
+
+class KVIRC_API KviUIntSelector : public KviTalHBox, public KviSelectorInterface
+{
+ Q_OBJECT
+public:
+ KviUIntSelector(QWidget * par,const QString & txt,unsigned int *pOption,
+ unsigned int uLowBound,unsigned int uHighBound,unsigned int uDefault,bool bEnabled,bool bShortInt = false);
+ ~KviUIntSelector(){};
+private:
+ QLabel * m_pLabel;
+ QSpinBox * m_pSpinBox;
+ unsigned int * m_pOption;
+ unsigned int m_uLowBound;
+ unsigned int m_uHighBound;
+ unsigned int m_uDefault;
+ bool m_bIsShortInt;
+public:
+ virtual void setPrefix(const QString & txt);
+ virtual void setSuffix(const QString & txt);
+ virtual void commit();
+ virtual void setEnabled(bool bEnabled);
+};
+
+
+class KVIRC_API KviFileSelector : public KviTalHBox, public KviSelectorInterface
+{
+ Q_OBJECT
+public:
+ KviFileSelector(QWidget * par,const QString & txt,QString * pOption,bool bEnabled,unsigned int uFlags = 0,const QString &szFilter = QString::null);
+ ~KviFileSelector(){};
+public:
+ enum Flags {
+ ChooseSaveFileName = 1,
+ DontConfirmOverwrite = 2
+ };
+protected:
+ QLabel * m_pLabel;
+ QLineEdit * m_pLineEdit;
+ QPushButton * m_pButton;
+ QString * m_pOption;
+ unsigned int m_uFlags;
+ QString m_szFilter;
+public:
+ virtual void commit();
+ virtual void setEnabled(bool bEnabled);
+ void setSelection(const QString &szSelection);
+signals:
+ void selectionChanged(const QString &szNewValue);
+private slots:
+ void browseClicked();
+protected:
+ virtual void select();
+};
+
+class KVIRC_API KviDirectorySelector : public KviFileSelector
+{
+ Q_OBJECT
+public:
+ KviDirectorySelector(QWidget * par,const QString & txt,QString * pOption,bool bEnabled);
+ ~KviDirectorySelector(){};
+protected:
+ virtual void select();
+};
+
+
+class KVIRC_API KviColorSelector : public KviTalHBox, public KviSelectorInterface
+{
+ Q_OBJECT
+public:
+ KviColorSelector(QWidget * par,const QString & txt,QColor * pOption,bool bEnabled);
+ ~KviColorSelector(){};
+private:
+ QLabel * m_pLabel;
+ QColor * m_pOption;
+ QColor m_memColor;
+ QPushButton * m_pButton;
+public:
+ virtual void commit();
+ virtual void setEnabled(bool bEnabled);
+ QColor getColor(){ return m_memColor; };
+ void forceColor(QColor clr);
+private:
+ void setButtonPalette(QColor * pOption);
+private slots:
+ void changeClicked();
+};
+
+class KVIRC_API KviFontSelector : public KviTalHBox, public KviSelectorInterface
+{
+ Q_OBJECT
+public:
+ KviFontSelector(QWidget * par,const QString & txt,QFont * pOption,bool bEnabled);
+ ~KviFontSelector(){};
+private:
+ QLabel * m_pLabel;
+ QFont * m_pOption;
+ QPushButton * m_pButton;
+public:
+ virtual void commit();
+ virtual void setEnabled(bool bEnabled);
+private:
+ void setButtonFont(QFont * pOption);
+private slots:
+ void changeClicked();
+};
+
+class KVIRC_API KviStringListSelector : public KviTalVBox, public KviSelectorInterface
+{
+ Q_OBJECT
+public:
+ KviStringListSelector(QWidget * par,const QString & txt,QStringList * pOption,bool bEnabled);
+ ~KviStringListSelector();
+private:
+ QLabel * m_pLabel;
+ KviTalListBox * m_pListBox;
+ QLineEdit * m_pLineEdit;
+ QPushButton * m_pAddButton;
+ QPushButton * m_pRemoveButton;
+ QStringList * m_pOption;
+public:
+ virtual void commit();
+ virtual void setEnabled(bool bEnabled);
+private slots:
+ void textChanged(const QString &str);
+ void selectionChanged();
+ void addClicked();
+ void removeClicked();
+};
+
+class KviTalPopupMenu;
+
+class KVIRC_API KviMircTextColorSelector : public KviTalHBox, public KviSelectorInterface
+{
+ Q_OBJECT
+public:
+ KviMircTextColorSelector(QWidget * par,const QString &txt,unsigned int * uFore,unsigned int * uBack,bool bEnabled);
+ ~KviMircTextColorSelector();
+private:
+ QLabel *m_pLabel;
+ QPushButton * m_pButton;
+ unsigned int * m_pUFore;
+ unsigned int * m_pUBack;
+ unsigned int m_uFore;
+ unsigned int m_uBack;
+ KviTalPopupMenu * m_pContextPopup;
+ KviTalPopupMenu * m_pForePopup;
+ KviTalPopupMenu * m_pBackPopup;
+public:
+ virtual void commit();
+ virtual void setEnabled(bool bEnabled);
+protected slots:
+ void buttonClicked();
+ void foreSelected(int);
+ void backSelected(int);
+protected:
+ void setButtonPalette();
+};
+
+
+class KVIRC_API KviSoundSelector : public KviFileSelector
+{
+ Q_OBJECT
+public:
+ KviSoundSelector(QWidget * par,const QString & txt,QString * pOption,bool bEnabled);
+ ~KviSoundSelector();
+protected:
+ QPushButton *m_pPlayButton;
+private slots:
+ void playSound();
+public:
+ virtual void setEnabled(bool bEnabled);
+};
+
+class KVIRC_API KviChanListViewItem : public KviTalListViewItem
+{
+private:
+ QString m_szPass;
+public:
+ KviChanListViewItem(KviTalListView* pList,QString szChan,QString szPass);
+ ~KviChanListViewItem() {};
+
+ const QString& pass() { return m_szPass; }
+};
+
+class KVIRC_API KviCahnnelListSelector : public KviTalVBox, public KviSelectorInterface
+{
+ Q_OBJECT
+public:
+ KviCahnnelListSelector(QWidget * par,const QString & txt,QStringList * pOption,bool bEnabled);
+ ~KviCahnnelListSelector();
+private:
+ QLabel * m_pLabel;
+ KviTalListView * m_pListView;
+ QLineEdit * m_pChanLineEdit;
+ QLineEdit * m_pPassLineEdit;
+ QPushButton * m_pAddButton;
+ QPushButton * m_pRemoveButton;
+ QStringList * m_pOption;
+public:
+ virtual void commit();
+ virtual void setEnabled(bool bEnabled);
+private slots:
+ void textChanged(const QString &str);
+ void selectionChanged();
+ void addClicked();
+ void removeClicked();
+};
+
+
+
+#endif //!_KVI_SELECTORS_H_
diff --git a/src/kvirc/ui/kvi_splash.cpp b/src/kvirc/ui/kvi_splash.cpp
new file mode 100644
index 00000000..7b6b7177
--- /dev/null
+++ b/src/kvirc/ui/kvi_splash.cpp
@@ -0,0 +1,222 @@
+//=============================================================================
+//
+// File : kvi_splash.cpp
+// Creation date : Wed Aug 8 2001 17:46:10 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+#include "kvi_string.h"
+#include "kvi_app.h"
+#include "kvi_defaults.h"
+#include "kvi_splash.h"
+#include "kvi_locale.h"
+#include "kvi_fileutils.h"
+#include <qsplashscreen.h>
+
+#ifdef COMPILE_USE_QT4
+ #include <qdesktopwidget.h>
+#endif
+
+#include <qpixmap.h>
+#include <qpainter.h>
+#include <qlayout.h>
+
+#include <stdio.h>
+
+
+KviSplashScreen::KviSplashScreen()
+: QSplashScreen(QPixmap(1,1),Qt::WStyle_NoBorder | Qt::WType_TopLevel | Qt::WStyle_Customize | Qt::WStyle_StaysOnTop | Qt::WStyle_Splash)
+{
+ QString szPix;
+ QPixmap * pix = 0;
+
+ // check for the current theme splash screen pointer
+ QString szPointerFile;
+ g_pApp->getLocalKvircDirectory(szPointerFile,KviApp::Themes,"current-splash");
+ if(KviFileUtils::fileExists(szPointerFile))
+ {
+ QString szBuf;
+ KviFileUtils::readFile(szPointerFile,szBuf);
+ if(!szBuf.isEmpty())
+ {
+ g_pApp->getLocalKvircDirectory(szPix,KviApp::Themes,szBuf);
+ KviQString::ensureLastCharIs(szPix,KVI_PATH_SEPARATOR_CHAR);
+ szPix.append("kvi_splash.png");
+ pix = new QPixmap(szPix);
+ if(pix->isNull())
+ {
+ // no way..
+ delete pix;
+ pix = 0;
+ } else {
+ // else we might have a themed splash screen
+// g_pApp->getLocalKvircDirectory(szPix,KviApp::Themes,szBuf);
+ KviQString::ensureLastCharIs(szPix,KVI_PATH_SEPARATOR_CHAR);
+ szPix.append("kvi_splash_overlay.png");
+ m_pOverlay = new QPixmap(szPix);
+ if(m_pOverlay->isNull())
+ {
+ // no way..
+ delete pix;
+ pix = 0;
+ delete m_pOverlay;
+ m_pOverlay = 0;
+ }
+ }
+ }
+ }
+
+ if(!pix)
+ {
+ if(g_pApp->findImage(szPix,"kvi_splash.png"))
+ {
+ pix = new QPixmap(szPix);
+ } else {
+ // dummy image
+ pix = new QPixmap(300,200);
+ }
+
+ if(g_pApp->findImage(szPix,"kvi_splash_overlay.png"))
+ {
+ m_pOverlay = new QPixmap(szPix);
+ } else {
+ m_pOverlay = new QPixmap(300,20);
+ }
+ }
+
+ setPixmap(*pix);
+ m_pTimer = new QTimer(this);
+ connect(m_pTimer,SIGNAL(timeout()),this,SLOT(suicide()));
+ delete pix;
+
+#ifdef COMPILE_USE_QT4
+ setWindowOpacity(0);
+ m_bIncreasing=true;
+ m_rTransparency=0;
+ m_pFadeTimer= new QTimer(this);
+ connect(m_pFadeTimer,SIGNAL(timeout()),this,SLOT(fadeTimerShot()));
+ m_pFadeTimer->start(6);
+#endif
+}
+
+// We don't need messages on the splash: they just add work to the translators and nobody can read them anyway :D
+//void KviSplashScreen::message(QString szMessage)
+//{
+ //QSplashScreen::message(szMessage, Qt::AlignRight | Qt::AlignBottom, Qt::white);
+//}
+
+KviSplashScreen::~KviSplashScreen()
+{
+ g_pSplashScreen = 0; // make sure it's true
+ delete m_pTimer;
+ delete m_pOverlay;
+}
+
+
+void KviSplashScreen::showEvent(QShowEvent *e)
+{
+ move((g_pApp->desktop()->width() - width())/2,
+ (g_pApp->desktop()->height() - height())/2);
+ m_creationTime = QTime::currentTime();
+}
+
+void KviSplashScreen::hideEvent(QHideEvent *e)
+{
+ suicide();
+}
+
+void KviSplashScreen::setProgress(int progress)
+{
+#ifdef COMPILE_USE_QT4
+ QPixmap slowQt4Copy = pixmap();
+ QPainter painter(&slowQt4Copy);
+ QSize size = slowQt4Copy.size();
+ int w = (m_pOverlay->width() * progress) / 100;
+ painter.drawPixmap(0,size.height() - m_pOverlay->height(),w,m_pOverlay->height(),*m_pOverlay,0,0,w,m_pOverlay->height());
+ painter.end();
+ setPixmap(slowQt4Copy);
+#else
+ QPainter painter(pixmap());
+ QSize size = pixmap()->size();
+ painter.drawPixmap(0,size.height() - m_pOverlay->height(),*m_pOverlay,0,0,(m_pOverlay->width() * progress) / 100,m_pOverlay->height());
+ painter.end();
+#endif
+ //raise();
+ repaint();
+ g_pApp->processEvents(); //damn...
+}
+
+#define KVI_SPLASH_SCREEN_MINIMUM_TIMEOUT_IN_MSECS 2000
+
+void KviSplashScreen::die()
+{
+#ifdef COMPILE_USE_QT4
+ m_bIncreasing = false;
+ m_pFadeTimer->start(6);
+#else
+ QTime now = QTime::currentTime();
+ int mSecs = m_creationTime.msecsTo(now);
+ int mRemaining = KVI_SPLASH_SCREEN_MINIMUM_TIMEOUT_IN_MSECS - mSecs;
+ if(mRemaining < 0)mRemaining = 0;
+ m_pTimer->start(mRemaining,true);
+#endif
+}
+
+
+void KviSplashScreen::suicide()
+{
+ if(!g_pSplashScreen)return; // already in suicide ?
+ //g_pApp->collectGarbage(this);
+ g_pSplashScreen = 0;
+ deleteLater();
+ //delete this;
+}
+
+
+void KviSplashScreen::fadeTimerShot()
+{
+#ifdef COMPILE_USE_QT4
+ if(m_bIncreasing)
+ {
+ m_rTransparency+=0.05;
+ setWindowOpacity(m_rTransparency);
+ if(m_rTransparency>=1)
+ {
+ m_pFadeTimer->stop();
+ m_bIncreasing=false;
+ }
+
+
+ } else {
+ m_rTransparency-=0.02;
+ setWindowOpacity(m_rTransparency);
+ if(m_rTransparency<=0)
+ {
+ m_pFadeTimer->stop();
+ m_bIncreasing=true;
+ suicide();
+ }
+ }
+#endif
+}
+
+
+#include "kvi_splash.moc"
diff --git a/src/kvirc/ui/kvi_splash.h b/src/kvirc/ui/kvi_splash.h
new file mode 100644
index 00000000..83cfb734
--- /dev/null
+++ b/src/kvirc/ui/kvi_splash.h
@@ -0,0 +1,72 @@
+#ifndef _KVI_SPLASH_H_
+#define _KVI_SPLASH_H_
+//=============================================================================
+//
+// File : kvi_splash.h
+// Creation date : Wed Aug 8 2001 17:45:12 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+
+#include <qframe.h>
+
+#include <qprogressbar.h>
+#include <qlabel.h>
+#include <qtimer.h>
+#include <qdatetime.h>
+#include <qsplashscreen.h>
+#include <qpixmap.h>
+
+class KVIRC_API KviSplashScreen : public QSplashScreen
+{
+ Q_OBJECT
+public:
+ KviSplashScreen();
+ virtual ~KviSplashScreen();
+private:
+ QTimer * m_pTimer;
+ QTime m_creationTime;
+ QPixmap * m_pOverlay;
+#ifdef COMPILE_USE_QT4
+ bool m_bIncreasing;
+ qreal m_rTransparency;
+ QTimer * m_pFadeTimer;
+#endif
+protected:
+ virtual void showEvent(QShowEvent * e);
+ virtual void hideEvent(QHideEvent * e);
+public:
+ void setProgress(int progress);
+ void die();
+ //void message(QString);
+protected slots:
+ void suicide();
+ void fadeTimerShot();
+};
+
+extern KVIRC_API KviSplashScreen * g_pSplashScreen;
+
+#define KVI_SPLASH_SET_PROGRESS(__val) if(g_pSplashScreen)g_pSplashScreen->setProgress(__val);
+//#define KVI_SPLASH_SET_TEXT(__txt) if(g_pSplashScreen){ g_pSplashScreen->message(__txt); debug(__txt.latin1()); }
+
+
+#endif //_KVI_SPLASH_H_
diff --git a/src/kvirc/ui/kvi_statusbar.cpp b/src/kvirc/ui/kvi_statusbar.cpp
new file mode 100644
index 00000000..df20a225
--- /dev/null
+++ b/src/kvirc/ui/kvi_statusbar.cpp
@@ -0,0 +1,643 @@
+//=============================================================================
+//
+// File : kvi_statusbar.cpp
+// Created on Tue 07 Sep 2004 03:56:46 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_statusbar.h"
+#include "kvi_frame.h"
+
+#include <qlabel.h>
+
+#include "kvi_iconmanager.h"
+#include "kvi_window.h"
+#include "kvi_irccontext.h"
+#include "kvi_ircconnection.h"
+#include "kvi_ircconnectionuserinfo.h"
+#include "kvi_locale.h"
+#include "kvi_app.h"
+#include "kvi_config.h"
+#include "kvi_modulemanager.h"
+#include "kvi_statusbarapplet.h"
+#include "kvi_dynamictooltip.h"
+
+#include <qpainter.h>
+#include <qstyle.h>
+#include <qlayout.h>
+#include <qtimer.h>
+#include <qcursor.h>
+#include "kvi_tal_popupmenu.h"
+#include <qpixmap.h>
+
+#ifdef COMPILE_USE_QT4
+ #include <qevent.h>
+#endif
+
+// This class COULD be derived also from KStatusBar but in fact
+// it adds no graphic functionality and it has only useless methods for us.
+// ... for now let's keep it simple :)
+
+
+#include "kvi_time.h"
+#include "kvi_qstring.h"
+
+#include <qfont.h>
+
+/*
+ IDEAS:
+ - Countdown timer
+*/
+
+
+
+
+
+KviStatusBar::KviStatusBar(KviFrame * pFrame)
+: QStatusBar(pFrame)
+{
+
+ setProperty("name","statusbar");
+ m_pFrame = pFrame;
+ // ugh :D
+ setSizeGripEnabled(false);
+
+ m_pContextPopup = 0;
+ m_pAppletsPopup = 0;
+
+ m_pClickedApplet = 0;
+
+ m_pAppletDescriptors = new KviPointerHashTable<QString,KviStatusBarAppletDescriptor>;
+ m_pAppletDescriptors->setAutoDelete(true);
+
+ KviStatusBarClock::selfRegister(this);
+ KviStatusBarAwayIndicator::selfRegister(this);
+ KviStatusBarLagIndicator::selfRegister(this);
+ KviStatusBarConnectionTimer::selfRegister(this);
+ KviStatusBarSeparator::selfRegister(this);
+
+ m_pAppletList = new KviPointerList<KviStatusBarApplet>;
+ m_pAppletList->setAutoDelete(false);
+
+ m_pMessageQueue = new KviPointerList<KviStatusBarMessage>;
+ m_pMessageQueue->setAutoDelete(true);
+
+ m_pMessageTimer = 0;
+
+ m_pMessageLabel = new QLabel("<b>[x]</b> x",this,"msgstatuslabel");
+ m_pMessageLabel->setMargin(1);
+#ifdef COMPILE_USE_QT4
+ m_pMessageLabel->setAlignment(Qt::AlignVCenter | Qt::AlignLeft);
+#else
+ m_pMessageLabel->setAlignment(SingleLine | Qt::AlignVCenter | Qt::AlignLeft);
+#endif
+ m_pMessageLabel->setMinimumWidth(350);
+
+ m_iLastMinimumHeight = 0;
+ m_bStopLayoutOnAddRemove = true;
+
+ connect(m_pFrame,SIGNAL(activeContextChanged()),this,SLOT(setPermanentMessage()));
+ connect(m_pFrame,SIGNAL(activeContextStateChanged()),this,SLOT(setPermanentMessage()));
+ connect(m_pFrame,SIGNAL(activeConnectionUserModeChanged()),this,SLOT(setPermanentMessage()));
+ connect(m_pFrame,SIGNAL(activeConnectionNickNameChanged()),this,SLOT(setPermanentMessage()));
+ setPermanentMessage();
+
+ m_bStopLayoutOnAddRemove = false;
+
+ m_pToolTip = new KviDynamicToolTip(this);
+ connect(m_pToolTip,SIGNAL(tipRequest(KviDynamicToolTip *,const QPoint &)),this,SLOT(tipRequest(KviDynamicToolTip *,const QPoint &)));
+
+ updateLayout();
+}
+
+KviStatusBar::~KviStatusBar()
+{
+ save();
+
+ m_bStopLayoutOnAddRemove = true;
+
+ if(m_pMessageTimer)delete m_pMessageTimer;
+ delete m_pMessageQueue;
+ delete m_pAppletDescriptors;
+ delete m_pAppletList;
+}
+
+void KviStatusBar::load()
+{
+ KviStr szBuf;
+ if(!g_pApp->getReadOnlyConfigPath(szBuf,"statusbar.kvc"))return; // no config file at all
+
+ KviConfig cfg(szBuf.ptr(),KviConfig::Read);
+ cfg.setGroup("Applets");
+
+ int nApplets = cfg.readIntEntry("Count",0);
+ for(int i=0;i<nApplets;i++)
+ {
+ KviStr prefix(KviStr::Format,"Applet%d",i);
+ KviStr tmp(KviStr::Format,"%s_InternalName",prefix.ptr());
+ QString szInternalName = cfg.readEntry(tmp.ptr(),"");
+ if(!szInternalName.isEmpty())
+ {
+ tmp.sprintf("%s_PreloadModule",prefix.ptr());
+ QString szPreloadModule = cfg.readEntry(tmp.ptr(),"");
+ if(!szPreloadModule.isEmpty())
+ g_pModuleManager->getModule(szPreloadModule.utf8().data());
+
+ KviStatusBarApplet * a = createApplet(szInternalName);
+ if (a)
+ a->loadState(prefix.ptr(),&cfg);
+ else
+ debug("warning: failed to create applet %s (preload: %s)!",
+ szInternalName.utf8().data(), szPreloadModule.utf8().data());
+ }
+ }
+}
+
+void KviStatusBar::save()
+{
+ // FIXME: This will preserve the settings of the last saved KviFrame's statusbar only :/
+ KviStr szBuf;
+ g_pApp->getLocalKvircDirectory(szBuf,KviApp::Config,"statusbar.kvc");
+
+ KviConfig cfg(szBuf.ptr(),KviConfig::Write);
+ cfg.setGroup("Applets");
+
+ cfg.writeEntry("Count",m_pAppletList->count());
+
+ int i = 0;
+ for(KviStatusBarApplet * a = m_pAppletList->first();a;a = m_pAppletList->next())
+ {
+ KviStr prefix(KviStr::Format,"Applet%d",i);
+ KviStr tmp(KviStr::Format,"%s_InternalName",prefix.ptr());
+ cfg.writeEntry(tmp.ptr(),a->descriptor()->internalName());
+ a->saveState(prefix.ptr(),&cfg);
+ if(!(a->descriptor()->preloadModule().isEmpty()))
+ {
+ tmp.sprintf("%s_PreloadModule",prefix.ptr());
+ cfg.writeEntry(tmp.ptr(),a->descriptor()->preloadModule());
+ }
+ i++;
+ }
+}
+
+#define VMARGIN 3
+#define HMARGIN 4
+#define SPACING 3
+#define RICHTEXTLABELTRICK 2
+
+void KviStatusBar::layoutChildren()
+{
+ int x = width() - HMARGIN;
+ int h = height() - (VMARGIN * 2);
+ for(KviStatusBarApplet * a = m_pAppletList->last();a;a = m_pAppletList->prev())
+ {
+ int w = a->sizeHint().width();
+ x -= w;
+ a->setGeometry(x,VMARGIN,w,h);
+ x -= SPACING;
+ }
+ // trick to center vertically the rich text label: make it some pixels smaller
+ m_pMessageLabel->setGeometry(HMARGIN,VMARGIN,x - HMARGIN,h - RICHTEXTLABELTRICK);
+}
+
+void KviStatusBar::resizeEvent(QResizeEvent * e)
+{
+ layoutChildren();
+}
+
+bool KviStatusBar::event(QEvent * e)
+{
+ if(e->type() == QEvent::LayoutHint)
+ {
+ updateLayout();
+ return false; // send to parents too!
+ }
+ return QStatusBar::event(e);
+}
+
+void KviStatusBar::recalcMinimumHeight()
+{
+ int s = 18;
+ int h = m_pMessageLabel->sizeHint().height();
+ if(h > s)s = h;
+ for(KviStatusBarApplet * a = m_pAppletList->last();a;a = m_pAppletList->prev())
+ {
+ h = a->sizeHint().height();
+ if(h > s)s = h;
+ }
+ s += (VMARGIN * 2) + RICHTEXTLABELTRICK;
+ if(m_iLastMinimumHeight != s)
+ {
+ m_iLastMinimumHeight = s;
+ setMinimumHeight(s);
+ QLayout * l = layout();
+ if(l)
+ if(l->inherits("QBoxLayout"))
+ ((QBoxLayout *)l)->addStrut(s);
+ // FIXME: do QMainWindow need setUpLayout() here ?
+ }
+}
+
+bool KviStatusBar::appletExists(KviStatusBarApplet * pApplet)
+{
+ return (m_pAppletList->findRef(pApplet) != -1);
+}
+
+KviStatusBarApplet * KviStatusBar::appletAt(const QPoint &pnt,bool bBestMatch)
+{
+ QPoint local = mapFromGlobal(pnt);
+ if(bBestMatch)
+ {
+ for(KviStatusBarApplet * a = m_pAppletList->first();a;a = m_pAppletList->next())
+ {
+ if(local.x() <= (a->x() + a->width()))return a;
+ }
+ return m_pAppletList->last(); // last anyway
+ }
+
+ for(KviStatusBarApplet * a = m_pAppletList->first();a;a = m_pAppletList->next())
+ {
+ if((local.x() >= a->x()) && (local.y() >= a->y()))
+ {
+ if((local.x() <= (a->x() + a->width())) && (local.y() <= (a->y() + a->height())))
+ {
+ return a;
+ }
+ }
+ }
+ return 0;
+}
+
+void KviStatusBar::tipRequest(KviDynamicToolTip *pTip,const QPoint &pnt)
+{
+ KviStatusBarApplet * a = appletAt(mapToGlobal(pnt));
+ QString szTip;
+ QRect r;
+ if(a)
+ {
+ szTip = "<table width=\"100%\"><tr><td bgcolor=\"#303030\" align=\"center\"><font color=\"#ffffff\"><b>" + a->descriptor()->visibleName() + "</b></font></td></tr>";
+
+ QString szTipx = a->tipText(a->mapFromGlobal(mapToGlobal(pnt)));
+ if(!szTipx.isEmpty())
+ {
+ szTip += "<tr><td>";
+ szTip += szTipx;
+ szTip += "</td></tr><tr><td align=\"center\"><hr></td></tr>";
+ }
+
+ szTip += "<tr><td align=\"center\"><font color=\"#808080\" size=\"-1\">";
+ szTip += __tr2qs("<b>Shift+Drag</b> or <b>Ctrl+Drag</b> to move the applet around<br><b>Right click</b> to see the other options");
+ szTip += "</font></td></tr></table>";
+ r = QRect(a->x(),a->y(),a->width(),a->height());
+ } else {
+ szTip = "<center>";
+ szTip += __tr2qs("<b>Right click</b> to add/remove applets");
+ szTip += "</center>";
+ r = QRect(m_pMessageLabel->x(),m_pMessageLabel->y(),m_pMessageLabel->width(),m_pMessageLabel->height());
+ }
+ pTip->tip(r,szTip);
+}
+
+KviTalPopupMenu * KviStatusBar::contextPopup()
+{
+ if(!m_pContextPopup)
+ {
+ m_pContextPopup = new KviTalPopupMenu(this);
+ connect(m_pContextPopup,SIGNAL(aboutToShow()),this,SLOT(contextPopupAboutToShow()));
+ }
+ m_pClickedApplet = appletAt(QCursor::pos());
+ return m_pContextPopup;
+}
+
+void KviStatusBar::contextPopupAboutToShow()
+{
+ if(!m_pContextPopup)return;
+ m_pContextPopup->clear();
+
+
+ if(appletExists(m_pClickedApplet))
+ {
+ QString app = m_pClickedApplet->descriptor()->visibleName();
+
+ QString tmp;
+ KviQString::sprintf(tmp,"<center><b>%Q</b></center>",&app);
+
+#ifndef COMPILE_USE_QT4
+ // FIXME: This is not supported under Qt4.. :(
+ QLabel * l = new QLabel(tmp,m_pContextPopup);
+ l->setFrameStyle(QFrame::Raised | QFrame::StyledPanel);
+ m_pContextPopup->insertItem(l);
+#endif
+
+ m_pClickedApplet->fillContextPopup(m_pContextPopup);
+
+ KviQString::sprintf(tmp,__tr2qs("Remove %Q"),&app);
+ m_pContextPopup->insertSeparator();
+ m_pContextPopup->insertItem(tmp,this,SLOT(removeClickedApplet()));
+ }
+
+ if(!m_pAppletsPopup)
+ {
+ m_pAppletsPopup = new KviTalPopupMenu(this);
+ connect(m_pAppletsPopup,SIGNAL(aboutToShow()),this,SLOT(appletsPopupAboutToShow()));
+ connect(m_pAppletsPopup,SIGNAL(activated(int)),this,SLOT(appletsPopupActivated(int)));
+ }
+
+ m_pContextPopup->insertItem(__tr2qs("Add Applet"),m_pAppletsPopup);
+}
+
+void KviStatusBar::removeClickedApplet()
+{
+ if(!appletExists(m_pClickedApplet))return;
+ delete m_pClickedApplet;
+ m_pClickedApplet = 0;
+}
+
+void KviStatusBar::appletsPopupAboutToShow()
+{
+ if(!m_pAppletsPopup)return;
+ m_pAppletsPopup->clear();
+
+ // FIXME: could we cache the module results in some way ?
+ g_pModuleManager->loadModulesByCaps("statusbarapplet");
+
+ KviPointerHashTableIterator<QString,KviStatusBarAppletDescriptor> it(*m_pAppletDescriptors);
+ while(KviStatusBarAppletDescriptor * d = it.current())
+ {
+ int id;
+ QPixmap * pix = d->icon();
+ if(pix)id = m_pAppletsPopup->insertItem(*pix,d->visibleName());
+ else id = m_pAppletsPopup->insertItem(d->visibleName());
+ m_pAppletsPopup->setItemParameter(id,d->id());
+ ++it;
+ }
+}
+
+KviStatusBarApplet * KviStatusBar::createApplet(const QString &szInternalName)
+{
+ KviStatusBarAppletDescriptor * d = m_pAppletDescriptors->find(szInternalName);
+ if(!d)return 0;
+ return d->create(this);
+}
+
+void KviStatusBar::showLayoutHelp()
+{
+ queueMessage(new KviStatusBarMessage(__tr2qs("Drag the applet while holding the Shift or Ctrl key to move it to the desired position")));
+}
+
+void KviStatusBar::appletsPopupActivated(int id)
+{
+ // FIXME: In fact the applet descriptors in modules could
+ // have been unloaded while the popup was being shown...
+ // For now we just assume that this never happens :D
+
+ if(!m_pAppletsPopup)return;
+ int par = m_pAppletsPopup->itemParameter(id);
+ KviPointerHashTableIterator<QString,KviStatusBarAppletDescriptor> it(*m_pAppletDescriptors);
+ while(KviStatusBarAppletDescriptor * d = it.current())
+ {
+ if(par == d->id())
+ {
+ if(m_pClickedApplet)
+ {
+ int idx = m_pAppletList->findRef(m_pClickedApplet);
+ if(idx != -1)
+ {
+ // try to put the new applet just after the clicked one
+ bool bSave = m_bStopLayoutOnAddRemove;
+ m_bStopLayoutOnAddRemove = true;
+ KviStatusBarApplet * a = d->create(this);
+ m_pAppletList->removeRef(a);
+ m_pAppletList->insert(idx + 1,a);
+ m_bStopLayoutOnAddRemove = bSave;
+ if(!m_bStopLayoutOnAddRemove)updateLayout();
+ showLayoutHelp();
+ return;
+ }
+ }
+ d->create(this);
+ showLayoutHelp();
+ return;
+ }
+ ++it;
+ }
+}
+
+void KviStatusBar::registerAppletDescriptor(KviStatusBarAppletDescriptor * d)
+{
+ m_pAppletDescriptors->replace(d->internalName(),d);
+}
+
+void KviStatusBar::registerApplet(KviStatusBarApplet * a)
+{
+ m_pAppletList->append(a);
+ if(!a->isVisible())a->show();
+ if(!m_bStopLayoutOnAddRemove)updateLayout();
+}
+
+void KviStatusBar::unregisterApplet(KviStatusBarApplet * a)
+{
+ if(!a)return;
+ m_pAppletList->removeRef(a);
+ if(a->isVisible())a->hide();
+ if(!m_bStopLayoutOnAddRemove)updateLayout();
+}
+
+
+void KviStatusBar::paintEvent(QPaintEvent * e)
+{
+ // avoid the ugly rectangle around the widgets painted by QStatusBar
+// QPainter p(this);
+// style().drawPrimitive(QStyle::PE_Panel,&p,rect(),colorGroup(),QStyle::Style_Raised,QStyleOption(1,1));
+ //QStatusBar::paintEvent(e);
+ //qDrawWinPanel(&p,0,0,width(),height(),colorGroup(),false,0);
+}
+
+void KviStatusBar::mousePressEvent(QMouseEvent * e)
+{
+ m_pClickedApplet = 0;
+ if(e->button() & Qt::RightButton)
+ {
+ contextPopup()->popup(QCursor::pos());
+ return;
+ }
+ if((e->button() & Qt::LeftButton) && (e->state() & (Qt::ShiftButton | Qt::ControlButton)))
+ {
+ // move!
+ m_pClickedApplet = appletAt(mapToGlobal(e->pos()));
+ if(!m_pClickedApplet)return;
+ m_pClickedApplet->select();
+#ifdef COMPILE_USE_QT4
+ g_pApp->setOverrideCursor(Qt::SizeAllCursor);
+#else
+ g_pApp->setOverrideCursor(sizeAllCursor);
+#endif
+ }
+}
+
+void KviStatusBar::mouseMoveEvent(QMouseEvent * e)
+{
+ if(!m_pClickedApplet)return;
+ if(!appletExists(m_pClickedApplet))return;
+ QPoint g = mapToGlobal(e->pos());
+ KviStatusBarApplet * a = appletAt(g,true);
+ if(a == m_pClickedApplet)return;
+ // move!
+ if(!a)
+ {
+ a = m_pAppletList->first();
+ if(!a)return; // ops!
+
+ if(e->pos().x() < (a->x() + a->width()))
+ {
+ if(a == m_pClickedApplet)return; // don't move
+ } else {
+ a = m_pAppletList->last();
+ if(!a)return;
+ if(a == m_pClickedApplet)return; // no way to move
+ }
+ }
+
+ m_pAppletList->removeRef(m_pClickedApplet);
+ int idx = m_pAppletList->findRef(a);
+ if(idx == -1)m_pAppletList->append(m_pClickedApplet); // uhg ?
+ else {
+ QPoint p = a->mapFromGlobal(g);
+ if(p.x() > (a->width() / 2))idx++; // just after
+ m_pAppletList->insert(idx,m_pClickedApplet);
+ }
+ layoutChildren();
+}
+
+void KviStatusBar::mouseReleaseEvent(QMouseEvent * e)
+{
+ if(e->button() & Qt::LeftButton)
+ {
+ if(m_pClickedApplet && appletExists(m_pClickedApplet))
+ {
+ m_pClickedApplet->select(false);
+ g_pApp->restoreOverrideCursor();
+ }
+ }
+}
+
+void KviStatusBar::queueMessage(KviStatusBarMessage * pMsg)
+{
+ // FIXME: the priority of the message!!!
+ m_pMessageQueue->append(pMsg);
+ if(!m_pMessageTimer)showFirstMessageInQueue();
+ // else we wait for the message timer to shot
+}
+
+void KviStatusBar::messageTimerFired()
+{
+ if(m_pMessageTimer)m_pMessageTimer->stop();
+
+ if(!m_pMessageQueue->isEmpty())
+ {
+ // the first message in queue is currently visible
+ // kill it
+ m_pMessageQueue->removeFirst();
+ if(!m_pMessageQueue->isEmpty())
+ {
+ // something to show
+ showFirstMessageInQueue();
+ }
+ }
+ // nothing else to show
+ delete m_pMessageTimer;
+ m_pMessageTimer = 0;
+
+ setPermanentMessage();
+}
+
+void KviStatusBar::showFirstMessageInQueue()
+{
+ KviStatusBarMessage * pMsg = m_pMessageQueue->first();
+ if(!pMsg)
+ {
+ if(m_pMessageTimer)
+ {
+ delete m_pMessageTimer;
+ m_pMessageTimer = 0;
+ }
+ return;
+ }
+
+ if(!m_pMessageTimer)
+ {
+ m_pMessageTimer = new QTimer(this);
+ QObject::connect(m_pMessageTimer,SIGNAL(timeout()),this,SLOT(messageTimerFired()));
+ } else {
+ m_pMessageTimer->stop();
+ }
+
+ m_pMessageLabel->setText("<nobr>" + pMsg->text() + "</nobr>");
+ m_pMessageTimer->start(pMsg->timeout());
+}
+
+
+void KviStatusBar::setPermanentMessage()
+{
+ if(m_pMessageTimer)return; // something is being actually shown!
+
+ KviIrcContext * c = m_pFrame->activeContext();
+
+ QString txt = "<nobr>";
+
+ if(c)
+ {
+ switch(c->state())
+ {
+ case KviIrcContext::Connected:
+ txt += "<b>[";
+ txt += c->connection()->currentServerName();
+ txt += "]</b> ";
+ txt += c->connection()->currentNickName();
+ if(!c->connection()->userInfo()->userMode().isEmpty())
+ {
+ txt += " (+";
+ txt += c->connection()->userInfo()->userMode();
+ txt += ")";
+ }
+ break;
+ case KviIrcContext::Connecting:
+ txt += __tr2qs("Connection in progress...");
+ break;
+ case KviIrcContext::LoggingIn:
+ txt += "<b>[";
+ txt += c->connection()->currentServerName();
+ txt += "]</b> ";
+ txt += __tr2qs("Login in progress...");
+ break;
+ default:
+ txt += __tr2qs("Not connected");
+ break;
+ }
+ } else {
+ txt += __tr2qs("No IRC context");
+ }
+
+ txt += "</nobr>";
+
+ m_pMessageLabel->setText(txt);
+}
diff --git a/src/kvirc/ui/kvi_statusbar.h b/src/kvirc/ui/kvi_statusbar.h
new file mode 100644
index 00000000..119c93d8
--- /dev/null
+++ b/src/kvirc/ui/kvi_statusbar.h
@@ -0,0 +1,130 @@
+#ifndef _KVI_STATUSBAR_H_
+#define _KVI_STATUSBAR_H_
+//=============================================================================
+//
+// File : kvi_statusbar.h
+// Created on Tue 07 Sep 2004 03:56:46 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_pointerlist.h"
+#include "kvi_heapobject.h"
+
+#include <qstring.h>
+#include "kvi_pointerhashtable.h"
+#include <qstatusbar.h>
+
+class KviFrame;
+
+class QTimer;
+class QLabel;
+class KviTalPopupMenu;
+
+class KVIRC_API KviStatusBarMessage : public KviHeapObject
+{
+ friend class KviStatusBar;
+protected:
+ QString m_szText;
+ unsigned int m_uTimeout;
+ unsigned int m_uPriority;
+public:
+ KviStatusBarMessage(const QString &szText,unsigned int uTimeout = 8000,unsigned int uPriority = 0)
+ : KviHeapObject(), m_szText(szText), m_uTimeout(uTimeout), m_uPriority(uPriority) {};
+ ~KviStatusBarMessage(){};
+public:
+ const QString & text(){ return m_szText; };
+ unsigned int timeout(){ return m_uTimeout; };
+ unsigned int priority(){ return m_uPriority; };
+};
+
+
+class KviStatusBarApplet;
+class KviStatusBarAppletDescriptor;
+class KviIrcContext;
+class KviDynamicToolTip;
+
+class KVIRC_API KviStatusBar : public QStatusBar
+{
+ friend class KviStatusBarApplet;
+ friend class KviFrame;
+ Q_OBJECT
+public:
+ KviStatusBar(KviFrame * pFrame);
+ ~KviStatusBar();
+protected:
+ KviFrame * m_pFrame;
+ KviPointerList<KviStatusBarMessage> * m_pMessageQueue;
+ QTimer * m_pMessageTimer;
+ QLabel * m_pMessageLabel;
+ KviPointerList<KviStatusBarApplet> * m_pAppletList;
+ KviPointerHashTable<QString,KviStatusBarAppletDescriptor> * m_pAppletDescriptors;
+ KviTalPopupMenu * m_pContextPopup;
+ KviTalPopupMenu * m_pAppletsPopup;
+ KviStatusBarApplet * m_pClickedApplet;
+ int m_iLastMinimumHeight;
+ bool m_bStopLayoutOnAddRemove;
+ KviDynamicToolTip * m_pToolTip;
+public:
+ KviFrame * frame(){ return m_pFrame; };
+protected slots:
+ void messageTimerFired();
+protected:
+ void showFirstMessageInQueue();
+ virtual void paintEvent(QPaintEvent * e);
+ virtual void mousePressEvent(QMouseEvent * e);
+ virtual void mouseMoveEvent(QMouseEvent * e);
+ virtual void mouseReleaseEvent(QMouseEvent * e);
+ virtual void resizeEvent(QResizeEvent * e);
+ virtual bool event(QEvent * e);
+ void registerApplet(KviStatusBarApplet * a);
+ void unregisterApplet(KviStatusBarApplet * a);
+ void recalcMinimumHeight();
+ void layoutChildren();
+ void updateLayout(){ recalcMinimumHeight(); layoutChildren(); };
+ void save();
+ void load();
+ KviStatusBarApplet * createApplet(const QString &szInternalName);
+ void showLayoutHelp();
+public:
+ bool appletExists(KviStatusBarApplet * pApplet);
+ // pnt is global!
+ KviStatusBarApplet * appletAt(const QPoint &pnt,bool bBestMatch = false);
+
+ KviTalPopupMenu * contextPopup();
+ // takes the ownership of pMsg
+ void queueMessage(KviStatusBarMessage * pMsg);
+ // called by KviFrame
+ void activeWindowChanged();
+
+ void registerAppletDescriptor(KviStatusBarAppletDescriptor * d);
+
+ //void addApplet(KviStatusBarApplet * pApplet);
+ //void removeApplet(KviStatusBarApplet * pApplet);
+protected slots:
+ void contextPopupAboutToShow();
+ void appletsPopupAboutToShow();
+ void appletsPopupActivated(int id);
+ void removeClickedApplet();
+ void setPermanentMessage();
+ void tipRequest(KviDynamicToolTip *pTip,const QPoint &pnt);
+};
+
+#endif //!_KVI_STATUSBAR_H_
diff --git a/src/kvirc/ui/kvi_statusbarapplet.cpp b/src/kvirc/ui/kvi_statusbarapplet.cpp
new file mode 100644
index 00000000..8e4ec89a
--- /dev/null
+++ b/src/kvirc/ui/kvi_statusbarapplet.cpp
@@ -0,0 +1,563 @@
+//=============================================================================//
+// File : kvi_statusbarapplet.cpp
+// Created on Tue 07 Sep 2004 03:56:46 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_statusbarapplet.h"
+#include "kvi_frame.h"
+#include "kvi_iconmanager.h"
+#include "kvi_window.h"
+#include "kvi_irccontext.h"
+#include "kvi_ircconnection.h"
+#include "kvi_ircconnectionuserinfo.h"
+#include "kvi_ircconnectionstatistics.h"
+#include "kvi_locale.h"
+#include "kvi_app.h"
+#include "kvi_config.h"
+#include "kvi_modulemanager.h"
+#include "kvi_console.h"
+#include "kvi_lagmeter.h"
+#include "kvi_options.h"
+#include "kvi_kvs_script.h"
+
+#include <qpainter.h>
+#include <qstyle.h>
+#include <qlayout.h>
+#include <qtimer.h>
+#include <qcursor.h>
+#include "kvi_tal_popupmenu.h"
+#include <qpixmap.h>
+#ifdef COMPILE_USE_QT4
+ #include <qevent.h>
+#endif
+
+// This class COULD be derived also from KStatusBar but in fact
+// it adds no graphic functionality and it has only useless methods for us.
+// ... for now let's keep it simple :)
+
+
+// FIXME: Applets in modules SHOULD be unregistered automatically on unload!
+
+#include "kvi_time.h"
+#include "kvi_qstring.h"
+
+#include <qfont.h>
+
+/*
+ IDEAS:
+ - Lag meter
+ - Countdown timer
+*/
+
+KviStatusBarAppletDescriptor::KviStatusBarAppletDescriptor(const QString &szVisibleName,const QString &szInternalName,CreateAppletCallback pProc,const QString &szPreloadModule,const QPixmap &pixIcon)
+: KviHeapObject()
+{
+ static int s_iAppletDescriptorUniqueId = 0;
+ m_iId = s_iAppletDescriptorUniqueId;
+ s_iAppletDescriptorUniqueId++;
+ m_szVisibleName = szVisibleName;
+ m_szInternalName = szInternalName;
+ m_szPreloadModule = szPreloadModule;
+ m_pProc = pProc;
+ m_pAppletList = new KviPointerList<KviStatusBarApplet>;
+ m_pAppletList->setAutoDelete(false);
+ if(!pixIcon.isNull())m_pIcon = new QPixmap(pixIcon);
+ else m_pIcon = 0;
+}
+
+KviStatusBarAppletDescriptor::~KviStatusBarAppletDescriptor()
+{
+ while(KviStatusBarApplet * a = m_pAppletList->first())delete a;
+ delete m_pAppletList;
+ if(m_pIcon)delete m_pIcon;
+}
+
+KviStatusBarApplet * KviStatusBarAppletDescriptor::create(KviStatusBar * pBar)
+{
+ return m_pProc(pBar,this);
+}
+
+void KviStatusBarAppletDescriptor::registerApplet(KviStatusBarApplet * a)
+{
+ m_pAppletList->append(a);
+}
+
+void KviStatusBarAppletDescriptor::unregisterApplet(KviStatusBarApplet * a)
+{
+ m_pAppletList->removeRef(a);
+}
+
+
+
+
+
+
+KviStatusBarApplet::KviStatusBarApplet(KviStatusBar * pParent,KviStatusBarAppletDescriptor *pDescriptor)
+: QLabel(pParent), m_pStatusBar(pParent), m_pDescriptor(pDescriptor)
+{
+ m_pDescriptor->registerApplet(this);
+ m_pStatusBar->registerApplet(this);
+ m_bSelected = false;
+}
+
+KviStatusBarApplet::~KviStatusBarApplet()
+{
+ m_pDescriptor->unregisterApplet(this);
+ m_pStatusBar->unregisterApplet(this);
+}
+
+QString KviStatusBarApplet::tipText(const QPoint &)
+{
+ return QString::null;
+}
+
+void KviStatusBarApplet::paintEvent(QPaintEvent * e)
+{
+ QLabel::paintEvent(e);
+ setFont(KVI_OPTION_FONT(KviOption_fontIrcToolBarApplet));
+ if(m_bSelected)
+ {
+ QPainter p(this);
+#ifdef COMPILE_USE_QT4
+ p.setCompositionMode(QPainter::CompositionMode_SourceOut);
+ p.fillRect(rect(),Qt::black);
+ p.setCompositionMode(QPainter::CompositionMode_SourceOver);
+#else
+ p.setRasterOp(Qt::NotROP);
+ p.fillRect(rect(),Qt::black);
+ p.setRasterOp(Qt::CopyROP);
+#endif
+ }
+}
+
+void KviStatusBarApplet::select(bool bSelect)
+{
+ if(m_bSelected == bSelect)return;
+ m_bSelected = bSelect;
+ update();
+}
+
+
+
+
+KviStatusBarAwayIndicator::KviStatusBarAwayIndicator(KviStatusBar * pParent,KviStatusBarAppletDescriptor *pDescriptor)
+: KviStatusBarApplet(pParent,pDescriptor)
+{
+ m_bAwayOnAllContexts = false;
+ connect(pParent->frame(),SIGNAL(activeContextChanged()),this,SLOT(updateDisplay()));
+ connect(pParent->frame(),SIGNAL(activeContextStateChanged()),this,SLOT(updateDisplay()));
+ connect(pParent->frame(),SIGNAL(activeConnectionAwayStateChanged()),this,SLOT(updateDisplay()));
+
+ updateDisplay();
+
+ if(!pixmap())
+ setPixmap(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_NOTAWAY)));
+}
+
+KviStatusBarAwayIndicator::~KviStatusBarAwayIndicator()
+{
+}
+
+void KviStatusBarAwayIndicator::updateDisplay()
+{
+ KviIrcContext * c = statusBar()->frame()->activeContext();
+
+ if(c && c->isConnected())
+ {
+ setPixmap(c->connection()->userInfo()->isAway() ?
+ *(g_pIconManager->getSmallIcon(KVI_SMALLICON_AWAY)) : *(g_pIconManager->getSmallIcon(KVI_SMALLICON_NOTAWAY)));
+ } else {
+ // FIXME: We'd like to appear disabled here... but then we
+ // no longer get mouse events :/
+ setPixmap(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_NOTAWAY)));
+ }
+}
+
+void KviStatusBarAwayIndicator::toggleContext()
+{
+ m_bAwayOnAllContexts = !m_bAwayOnAllContexts;
+}
+
+void KviStatusBarAwayIndicator::fillContextPopup(KviTalPopupMenu *p)
+{
+ int id = p->insertItem(__tr2qs("Apply to all IRC Contexts"),this,SLOT(toggleContext()));
+ p->setItemChecked(id,m_bAwayOnAllContexts);
+}
+
+void KviStatusBarAwayIndicator::loadState(const char * prefix,KviConfig *cfg)
+{
+ KviStr tmp(KviStr::Format,"%s_AwayOnAllContexts",prefix);
+ m_bAwayOnAllContexts = cfg->readBoolEntry(tmp.ptr(),false);
+}
+
+void KviStatusBarAwayIndicator::saveState(const char * prefix,KviConfig *cfg)
+{
+ KviStr tmp(KviStr::Format,"%s_AwayOnAllContexts",prefix);
+ cfg->writeEntry(tmp.ptr(),m_bAwayOnAllContexts);
+}
+
+KviStatusBarApplet * CreateStatusBarAwayIndicator(KviStatusBar * pBar,KviStatusBarAppletDescriptor *pDescriptor)
+{
+ return new KviStatusBarAwayIndicator(pBar,pDescriptor);
+}
+
+void KviStatusBarAwayIndicator::selfRegister(KviStatusBar * pBar)
+{
+ KviStatusBarAppletDescriptor * d = new KviStatusBarAppletDescriptor(
+ __tr2qs("Away Indicator"),"awayindicator",CreateStatusBarAwayIndicator,"",*(g_pIconManager->getSmallIcon(KVI_SMALLICON_AWAY)));
+ pBar->registerAppletDescriptor(d);
+}
+
+// FIXME: Away on all context should know where user is not away/back before toggling status
+void KviStatusBarAwayIndicator::mouseDoubleClickEvent(QMouseEvent * e)
+{
+ if(!(e->button() & Qt::LeftButton))return;
+ KviIrcConnection * c = statusBar()->frame()->activeConnection();
+ if(!c)return;
+ if(c->state() != KviIrcConnection::Connected)return;
+ QString command;
+ if(m_bAwayOnAllContexts)
+ command = "if($away)back -a; else away -a";
+ else
+ command = "if($away)back; else away";
+ KviKvsScript::run(command,c->console());
+}
+
+QString KviStatusBarAwayIndicator::tipText(const QPoint &)
+{
+ KviIrcConnection * c = statusBar()->frame()->activeConnection();
+ QString ret = "<center><b>";
+ if(!c)goto not_connected;
+ if(c->state() != KviIrcConnection::Connected)goto not_connected;
+ if(c->userInfo()->isAway())
+ {
+ QString tmp = KviTimeUtils::formatTimeInterval(kvi_unixTime() - c->userInfo()->awayTime(),KviTimeUtils::NoLeadingEmptyIntervals);
+ ret += __tr2qs("Away since");
+ ret += ' ';
+ ret += tmp;
+ ret += "</b><br>";
+ ret += __tr2qs("Double click to leave away mode");
+ } else {
+ ret += __tr2qs("Not away");
+ ret += "</b><br>";
+ ret += __tr2qs("Double click to enter away mode");
+ }
+ ret += "</center>";
+ return ret;
+
+not_connected:
+ ret += __tr2qs("Not connected");
+ ret += "</b></center>";
+ return ret;
+}
+
+
+KviStatusBarLagIndicator::KviStatusBarLagIndicator(KviStatusBar * pParent,KviStatusBarAppletDescriptor *pDescriptor)
+: KviStatusBarApplet(pParent,pDescriptor)
+{
+ connect(pParent->frame(),SIGNAL(activeContextChanged()),this,SLOT(updateDisplay()));
+ connect(pParent->frame(),SIGNAL(activeContextStateChanged()),this,SLOT(updateDisplay()));
+ connect(pParent->frame(),SIGNAL(activeConnectionLagChanged()),this,SLOT(updateDisplay()));
+
+ updateDisplay();
+
+ QFont f = font();
+ f.setFixedPitch(true);
+ f.setFamily("fixed");
+ setFont(f);
+
+ updateDisplay();
+}
+
+KviStatusBarLagIndicator::~KviStatusBarLagIndicator()
+{
+}
+
+void KviStatusBarLagIndicator::mouseDoubleClickEvent(QMouseEvent *e)
+{
+ if(!(e->button() & Qt::LeftButton))return;
+
+ KviIrcConnection * c = statusBar()->frame()->activeConnection();
+ if(!c)return;
+ if(c->state() != KviIrcConnection::Connected)return;
+ if(!c->lagMeter())
+ {
+ KVI_OPTION_BOOL(KviOption_boolUseLagMeterEngine) = true;
+ g_pApp->restartLagMeters();
+ }
+}
+
+
+QString KviStatusBarLagIndicator::tipText(const QPoint &)
+{
+ KviIrcConnection * c = statusBar()->frame()->activeConnection();
+ QString ret = "<center><b>";
+ if(!c)goto not_connected;
+ if(c->state() != KviIrcConnection::Connected)goto not_connected;
+ if(c->lagMeter())
+ {
+ int lll;
+ if((lll = c->lagMeter()->lag()) > 0)
+ {
+ int llls = lll / 1000;
+ int llld = (lll % 1000) / 100;
+ int lllc = (lll % 100) / 10;
+ KviQString::appendFormatted(ret,__tr2qs("Lag: %d.%d%d"),llls,llld,lllc);
+ ret += "</b><br>";
+ int vss = c->lagMeter()->secondsSinceLastCompleted();
+ int vmm = vss / 60;
+ vss = vss % 60;
+ KviQString::appendFormatted(ret,__tr2qs("Last checked %d mins %d secs ago"),vmm,vss);
+ } else {
+ ret += __tr2qs("Lag measure not available yet");
+ ret += "</b>";
+ }
+ } else {
+ ret += __tr2qs("Lag meter engine disabled");
+ ret += "</b><br>";
+ ret += __tr2qs("Double click to enable it");
+ }
+ ret += "</center>";
+ return ret;
+
+not_connected:
+ ret += __tr2qs("Not connected");
+ ret += "</b></center>";
+ return ret;
+}
+
+void KviStatusBarLagIndicator::updateDisplay()
+{
+ KviIrcContext * c = statusBar()->frame()->activeContext();
+ if(!c)return;
+ if(c->isConnected())
+ {
+ KviIrcConnection * ic = c->connection();
+ if(ic->lagMeter())
+ {
+ int lll;
+ if((lll = ic->lagMeter()->lag()) > 0)
+ {
+ int llls = lll / 1000;
+ int llld = (lll % 1000) / 100;
+ int lllc = (lll % 100) / 10;
+ QString tmp;
+ KviQString::sprintf(tmp,__tr2qs("Lag: %d.%d%d"),llls,llld,lllc);
+ if(lll > 60000)
+ {
+ // one minute lag!
+ // paint it in red
+ tmp.prepend("<nobr><font color=\"#e00000\">");
+ tmp.append("</font></nobr>");
+ }
+ setText(tmp);
+ return;
+ }
+ }
+ }
+ // no lag available
+ setText(__tr2qs("Lag: ?.??"));
+}
+
+KviStatusBarApplet * CreateStatusBarLagIndicator(KviStatusBar * pBar,KviStatusBarAppletDescriptor *pDescriptor)
+{
+ return new KviStatusBarLagIndicator(pBar,pDescriptor);
+}
+
+
+void KviStatusBarLagIndicator::selfRegister(KviStatusBar * pBar)
+{
+ KviStatusBarAppletDescriptor * d = new KviStatusBarAppletDescriptor(
+ __tr2qs("Lag Indicator"),"lagindicator",CreateStatusBarLagIndicator,"",*(g_pIconManager->getSmallIcon(KVI_SMALLICON_SERVERPING)));
+ pBar->registerAppletDescriptor(d);
+}
+
+
+
+KviStatusBarClock::KviStatusBarClock(KviStatusBar * pParent,KviStatusBarAppletDescriptor *pDescriptor)
+: KviStatusBarApplet(pParent,pDescriptor)
+{
+ m_bUtc = false;
+
+ startTimer(1000);
+
+ QFont f = font();
+ f.setFixedPitch(true);
+ f.setFamily("fixed");
+ setFont(f);
+}
+
+KviStatusBarClock::~KviStatusBarClock()
+{
+}
+
+void KviStatusBarClock::timerEvent(QTimerEvent *)
+{
+ kvi_time_t tt = kvi_unixTime();
+ struct tm * t = m_bUtc ? gmtime(&tt) : localtime(&tt);
+ QString tmp;
+ KviQString::sprintf(tmp,"%d%d:%d%d:%d%d",
+ t->tm_hour / 10,
+ t->tm_hour % 10,
+ t->tm_min / 10,
+ t->tm_min % 10,
+ t->tm_sec / 10,
+ t->tm_sec % 10);
+ setText(tmp);
+}
+
+void KviStatusBarClock::fillContextPopup(KviTalPopupMenu * p)
+{
+ int id = p->insertItem("UTC",this,SLOT(toggleUtc()));
+ p->setItemChecked(id,m_bUtc);
+}
+
+void KviStatusBarClock::toggleUtc()
+{
+ m_bUtc = !m_bUtc;
+ timerEvent(0);
+}
+
+void KviStatusBarClock::loadState(const char * prefix,KviConfig *cfg)
+{
+ KviStr tmp(KviStr::Format,"%s_Utc",prefix);
+ m_bUtc = cfg->readBoolEntry(tmp.ptr(),false);
+}
+
+void KviStatusBarClock::saveState(const char * prefix,KviConfig *cfg)
+{
+ KviStr tmp(KviStr::Format,"%s_Utc",prefix);
+ cfg->writeEntry(tmp.ptr(),m_bUtc);
+}
+
+KviStatusBarApplet * CreateStatusBarClock(KviStatusBar * pBar,KviStatusBarAppletDescriptor *pDescriptor)
+{
+ return new KviStatusBarClock(pBar,pDescriptor);
+}
+
+void KviStatusBarClock::selfRegister(KviStatusBar * pBar)
+{
+ KviStatusBarAppletDescriptor * d = new KviStatusBarAppletDescriptor(
+ __tr2qs("Simple Clock"),"clock",CreateStatusBarClock,"",*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TIME)));
+ pBar->registerAppletDescriptor(d);
+}
+
+
+KviStatusBarConnectionTimer::KviStatusBarConnectionTimer(KviStatusBar * pParent,KviStatusBarAppletDescriptor *pDescriptor)
+: KviStatusBarApplet(pParent,pDescriptor)
+{
+ startTimer(1000);
+ m_bTotal=0;
+}
+
+KviStatusBarConnectionTimer::~KviStatusBarConnectionTimer()
+{
+}
+//g_pApp->topmostConnectedConsole()
+void KviStatusBarConnectionTimer::timerEvent(QTimerEvent * e)
+{
+ if(m_bTotal)
+ {
+ setText(KviTimeUtils::formatTimeInterval(KVI_OPTION_UINT(KviOption_uintTotalConnectionTime)));
+ } else {
+ if(g_pActiveWindow)
+ {
+ KviIrcContext * c = g_pActiveWindow->context();
+ if(c)
+ {
+ if(c->isConnected())
+ {
+ KviIrcConnection * cnn = c->connection();
+ if(cnn)
+ {
+ setText(KviTimeUtils::formatTimeInterval(kvi_unixTime() - cnn->statistics()->connectionStartTime()));
+ return;
+ }
+ }
+ }
+ }
+
+ setText(KviTimeUtils::formatTimeInterval(0,KviTimeUtils::FillWithHypens));
+ }
+ return;
+}
+
+void KviStatusBarConnectionTimer::toggleTotal()
+{
+ m_bTotal = !m_bTotal;
+}
+
+void KviStatusBarConnectionTimer::fillContextPopup(KviTalPopupMenu *p)
+{
+ int id = p->insertItem(__tr2qs("Show total connection time"),this,SLOT(toggleTotal()));
+ p->setItemChecked(id,m_bTotal);
+}
+
+void KviStatusBarConnectionTimer::loadState(const char * prefix,KviConfig *cfg)
+{
+ KviStr tmp(KviStr::Format,"%s_Total",prefix);
+ m_bTotal = cfg->readBoolEntry(tmp.ptr(),false);
+}
+
+void KviStatusBarConnectionTimer::saveState(const char * prefix,KviConfig *cfg)
+{
+ KviStr tmp(KviStr::Format,"%s_Total",prefix);
+ cfg->writeEntry(tmp.ptr(),m_bTotal);
+}
+
+KviStatusBarApplet * CreateStatusBarConnectionTimer(KviStatusBar * pBar,KviStatusBarAppletDescriptor *pDescriptor)
+{
+ return new KviStatusBarConnectionTimer(pBar,pDescriptor);
+}
+
+void KviStatusBarConnectionTimer::selfRegister(KviStatusBar * pBar)
+{
+ KviStatusBarAppletDescriptor * d = new KviStatusBarAppletDescriptor(
+ __tr2qs("Connection Timer"),"connectiontimer",CreateStatusBarConnectionTimer,"",*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TIME)));
+ pBar->registerAppletDescriptor(d);
+}
+
+
+
+KviStatusBarSeparator::KviStatusBarSeparator(KviStatusBar * pParent,KviStatusBarAppletDescriptor *pDescriptor)
+: KviStatusBarApplet(pParent,pDescriptor)
+{
+ setFrameStyle(QFrame::VLine | QFrame::Sunken);
+}
+
+KviStatusBarSeparator::~KviStatusBarSeparator()
+{
+}
+
+KviStatusBarApplet * CreateStatusBarSeparator(KviStatusBar * pBar,KviStatusBarAppletDescriptor *pDescriptor)
+{
+ return new KviStatusBarSeparator(pBar,pDescriptor);
+}
+
+void KviStatusBarSeparator::selfRegister(KviStatusBar * pBar)
+{
+ KviStatusBarAppletDescriptor * d = new KviStatusBarAppletDescriptor(
+ __tr2qs("Separator"),"separator",CreateStatusBarSeparator);
+ pBar->registerAppletDescriptor(d);
+}
+
diff --git a/src/kvirc/ui/kvi_statusbarapplet.h b/src/kvirc/ui/kvi_statusbarapplet.h
new file mode 100644
index 00000000..6302be59
--- /dev/null
+++ b/src/kvirc/ui/kvi_statusbarapplet.h
@@ -0,0 +1,195 @@
+#ifndef _KVI_STATUSBARAPPLET_H_
+#define _KVI_STATUSBARAPPLET_H_
+//=============================================================================
+//
+// File : kvi_statusbarapplet.h
+// Created on Tue 07 Sep 2004 03:56:46 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_pointerlist.h"
+#include "kvi_heapobject.h"
+#include "kvi_statusbar.h"
+
+#include <qstring.h>
+#include "kvi_pointerhashtable.h"
+#include <qstatusbar.h>
+#include <qlabel.h>
+#include <qpixmap.h>
+
+class QTimer;
+class QLabel;
+class KviTalPopupMenu;
+
+class KviConfig;
+class KviFrame;
+class KviIrcContext;
+class KviIrcConnection;
+class KviStatusBarApplet;
+class KviStatusBarAppletDescriptor;
+
+typedef KviStatusBarApplet * (*CreateAppletCallback)(KviStatusBar *,KviStatusBarAppletDescriptor *);
+
+class KVIRC_API KviStatusBarAppletDescriptor : public KviHeapObject
+{
+ friend class KviStatusBar;
+ friend class KviStatusBarApplet;
+protected:
+ QString m_szVisibleName; // visible name of the applet
+ QString m_szInternalName; // UNIQUE name of the applet
+ QString m_szPreloadModule; // name of the module that must be preloaded for this applet
+ CreateAppletCallback m_pProc; // creation callback
+ QPixmap * m_pIcon;
+ int m_iId;
+ KviPointerList<KviStatusBarApplet> * m_pAppletList;
+public:
+ KviStatusBarAppletDescriptor(const QString &szVisibleName,
+ const QString &szInternalName,
+ CreateAppletCallback pProc,
+ const QString &szPreloadModule = QString::null,
+ const QPixmap &pixIcon = QPixmap());
+ virtual ~KviStatusBarAppletDescriptor();
+public:
+ const QString &visibleName(){ return m_szVisibleName; };
+ const QString &internalName(){ return m_szInternalName; };
+ const QString &preloadModule(){ return m_szPreloadModule; };
+ int id(){ return m_iId; };
+ QPixmap * icon(){ return m_pIcon; };
+protected:
+ KviStatusBarApplet * create(KviStatusBar * pBar);
+ void registerApplet(KviStatusBarApplet * a);
+ void unregisterApplet(KviStatusBarApplet * a);
+};
+
+
+class KVIRC_API KviStatusBarApplet : public QLabel
+{
+ friend class KviStatusBar;
+ Q_OBJECT
+protected:
+ KviStatusBar * m_pStatusBar;
+ KviStatusBarAppletDescriptor * m_pDescriptor;
+ bool m_bSelected;
+public:
+ KviStatusBarApplet(KviStatusBar * pParent,KviStatusBarAppletDescriptor *pDescriptor);
+ virtual ~KviStatusBarApplet();
+public:
+ KviStatusBar * statusBar(){ return m_pStatusBar; };
+ KviFrame * frame(){ return m_pStatusBar->frame(); };
+ KviStatusBarAppletDescriptor * descriptor(){ return m_pDescriptor; };
+ void select(bool bSelect = true);
+ bool isSelected(){ return m_bSelected; };
+protected:
+ virtual void paintEvent(QPaintEvent *e);
+ virtual void fillContextPopup(KviTalPopupMenu *p){};
+ virtual void loadState(const char * prefix,KviConfig *cfg){};
+ virtual void saveState(const char * prefix,KviConfig *cfg){};
+ virtual QString tipText(const QPoint &);
+};
+
+
+
+class KviStatusBarClock : public KviStatusBarApplet
+{
+ Q_OBJECT
+public:
+ KviStatusBarClock(KviStatusBar * pParent,KviStatusBarAppletDescriptor *pDescriptor);
+ virtual ~KviStatusBarClock();
+protected:
+ bool m_bUtc;
+public:
+ static void selfRegister(KviStatusBar * pBar);
+protected:
+ virtual void fillContextPopup(KviTalPopupMenu * p);
+ virtual void timerEvent(QTimerEvent * e);
+ virtual void loadState(const char * prefix,KviConfig *cfg);
+ virtual void saveState(const char * prefix,KviConfig *cfg);
+protected slots:
+ void toggleUtc();
+};
+
+class KviStatusBarConnectionTimer : public KviStatusBarApplet
+{
+ Q_OBJECT
+public:
+ KviStatusBarConnectionTimer(KviStatusBar * pParent,KviStatusBarAppletDescriptor *pDescriptor);
+ virtual ~KviStatusBarConnectionTimer();
+protected:
+ bool m_bTotal;
+protected:
+ virtual void timerEvent(QTimerEvent * e);
+ virtual void fillContextPopup(KviTalPopupMenu *p);
+ virtual void loadState(const char * prefix,KviConfig *cfg);
+ virtual void saveState(const char * prefix,KviConfig *cfg);
+public:
+ static void selfRegister(KviStatusBar * pBar);
+protected slots:
+ void toggleTotal();
+};
+
+class KviStatusBarSeparator : public KviStatusBarApplet
+{
+ Q_OBJECT
+public:
+ KviStatusBarSeparator(KviStatusBar * pParent,KviStatusBarAppletDescriptor *pDescriptor);
+ virtual ~KviStatusBarSeparator();
+public:
+ static void selfRegister(KviStatusBar * pBar);
+};
+
+class KviStatusBarAwayIndicator : public KviStatusBarApplet
+{
+ Q_OBJECT
+public:
+ KviStatusBarAwayIndicator(KviStatusBar * pParent,KviStatusBarAppletDescriptor *pDescriptor);
+ virtual ~KviStatusBarAwayIndicator();
+public:
+ static void selfRegister(KviStatusBar * pBar);
+protected:
+ bool m_bAwayOnAllContexts;
+protected:
+ virtual void mouseDoubleClickEvent(QMouseEvent *e);
+ virtual QString tipText(const QPoint &);
+ virtual void fillContextPopup(KviTalPopupMenu *p);
+ virtual void loadState(const char * prefix,KviConfig *cfg);
+ virtual void saveState(const char * prefix,KviConfig *cfg);
+protected slots:
+ void updateDisplay();
+ void toggleContext();
+};
+
+class KviStatusBarLagIndicator : public KviStatusBarApplet
+{
+ Q_OBJECT
+public:
+ KviStatusBarLagIndicator(KviStatusBar * pParent,KviStatusBarAppletDescriptor *pDescriptor);
+ virtual ~KviStatusBarLagIndicator();
+public:
+ static void selfRegister(KviStatusBar * pBar);
+protected:
+ virtual void mouseDoubleClickEvent(QMouseEvent *e);
+ virtual QString tipText(const QPoint &);
+protected slots:
+ void updateDisplay();
+};
+
+
+#endif //!_KVI_STATUSBARAPPLET_H_
diff --git a/src/kvirc/ui/kvi_styled_controls.cpp b/src/kvirc/ui/kvi_styled_controls.cpp
new file mode 100644
index 00000000..8656b69b
--- /dev/null
+++ b/src/kvirc/ui/kvi_styled_controls.cpp
@@ -0,0 +1,373 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// File : kvi_styled_controls.cpp
+// Creation date : 19 Jan 2006 GMT by Alexey Uzhva
+//
+// This toolbar is part of the KVirc irc client distribution
+// Copyright (C) 2006 Alexey Uzhva
+//
+// 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 opinion) 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.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+#define __KVIRC__
+
+#include "kvi_styled_controls.h"
+
+#ifndef COMPILE_USE_QT4
+
+#include "kvi_iconmanager.h"
+#include "kvi_app.h"
+#include "kvi_options.h"
+#include "kvi_doublebuffer.h"
+#include "kvi_tal_toolbar.h"
+
+#include <qcheckbox.h>
+#include <qpainter.h>
+#include <qimage.h>
+#include <qevent.h>
+#include <qtimer.h>
+
+
+KviStyledControlInternal::KviStyledControlInternal( KviStyledControl* control)
+:QObject(0,0)
+{
+ m_pControl=control;
+}
+
+KviStyledControlInternal::~KviStyledControlInternal()
+{
+
+}
+
+bool KviStyledControlInternal::eventFilter( QObject *obj, QEvent *ev )
+{
+ if(ev->type()==QEvent::Enter)
+ {
+ m_pControl->enterEvent(ev);
+ } else if(ev->type()==QEvent::Leave) {
+ m_pControl->leaveEvent(ev);
+ }
+ return FALSE;
+}
+
+void KviStyledControlInternal::paintTimerShot ()
+{
+// debug("%s %s %i",__FILE__,__FUNCTION__,__LINE__);
+// debug("%s %i",__FUNCTION__,m_pControl->m_iStepNumber);
+ if(m_pControl->m_bMouseEnter)
+ {
+ m_pControl->m_iStepNumber++;
+ if(m_pControl->m_iStepNumber>=KVI_STYLE_NUM_STEPS)
+ {
+ m_pControl->m_iStepNumber=KVI_STYLE_NUM_STEPS;
+ m_pControl->m_pTimer->stop();
+ }
+ } else {
+ m_pControl->m_iStepNumber--;
+ if(m_pControl->m_iStepNumber<=0)
+ {
+ m_pControl->m_iStepNumber=0;
+ m_pControl->m_pTimer->stop();
+ }
+ }
+ m_pControl->m_pWidget->repaint( false );
+}
+
+KviStyledControl::KviStyledControl(QWidget* w)
+{
+ m_pWidget=w;
+ m_iStepNumber=0;
+ m_bMouseEnter=0;
+ m_pInternal=new KviStyledControlInternal(this);
+ m_pTimer = new QTimer(m_pInternal);
+ m_pWidget->installEventFilter(m_pInternal);
+}
+
+KviStyledControl::~KviStyledControl()
+{
+ delete m_pTimer;
+ delete m_pInternal;
+}
+
+void KviStyledControl::enterEvent ( QEvent * )
+{
+// debug("%s %s %i",__FILE__,__FUNCTION__,__LINE__);
+ if(m_pWidget->isEnabled() && KVI_OPTION_BOOL(KviOption_boolEnableVisualEffects))
+ {
+ if(m_iStepNumber<KVI_STYLE_NUM_STEPS)
+ {
+ if(!m_pTimer->isActive())
+ {
+ m_pTimer->connect( m_pTimer, SIGNAL(timeout()), m_pInternal, SLOT(paintTimerShot()) );
+ m_pTimer->start(KVI_STYLE_TIMER_STEP);
+ }
+ }
+ m_bMouseEnter=1;
+ m_iStepNumber++;
+ m_pWidget->repaint( false );
+ }
+}
+
+void KviStyledControl::leaveEvent ( QEvent * )
+{
+// debug("%s %s %i",__FILE__,__FUNCTION__,__LINE__);
+ if(m_pWidget->isEnabled() && KVI_OPTION_BOOL(KviOption_boolEnableVisualEffects))
+ {
+ if(m_iStepNumber>0)
+ {
+ if(!m_pTimer->isActive())
+ {
+ m_pTimer->connect( m_pTimer, SIGNAL(timeout()), m_pInternal, SLOT(paintTimerShot()) );
+ m_pTimer->start(KVI_STYLE_TIMER_STEP);
+ }
+ }
+ m_bMouseEnter=0;
+ m_iStepNumber--;
+ m_pWidget->repaint( false );
+ }
+}
+
+
+KviStyledCheckBox::KviStyledCheckBox ( QWidget * parent, const char * name )
+: QCheckBox(parent,name), KviStyledControl(this)
+{
+ setWFlags(WNoAutoErase);
+
+}
+
+KviStyledCheckBox::KviStyledCheckBox ( const QString & text, QWidget * parent, const char * name )
+: QCheckBox(text,parent,name), KviStyledControl(this)
+{
+ setWFlags(WNoAutoErase);
+}
+
+KviStyledCheckBox::~KviStyledCheckBox()
+{
+
+}
+
+
+void KviStyledCheckBox::paintEvent ( QPaintEvent * event)
+{
+ //debug("%s %s %i %i %i",__FILE__,__FUNCTION__,__LINE__,m_bMouseEnter,m_iStepNumber);
+ if(KVI_OPTION_BOOL(KviOption_boolEnableVisualEffects))
+ {
+ KviDoubleBuffer doublebuffer(event->rect().width(),event->rect().height());
+ QPixmap * pDoubleBufferPixmap = doublebuffer.pixmap();
+
+ QRect rect=event->rect();
+ pDoubleBufferPixmap->fill(this, rect.topLeft());
+
+ QPainter p(pDoubleBufferPixmap, this);
+ p.translate(-rect.x(), -rect.y());
+
+ QPixmap* pStoredPix = 0;
+
+ if(isChecked())
+ pStoredPix=g_pIconManager->getBigIcon("kvi_checkbox_selected.png");
+ else
+ pStoredPix=g_pIconManager->getBigIcon("kvi_checkbox_unselected.png");
+ //debug("%s %s %i %i %i",__FILE__,__FUNCTION__,__LINE__,m_bMouseEnter,m_iStepNumber);
+ if(pStoredPix)
+ {
+ //debug("%s %s %i %i %i",__FILE__,__FUNCTION__,__LINE__,m_bMouseEnter,m_iStepNumber);
+ QPixmap pix=*pStoredPix;
+ if(m_iStepNumber && isEnabled())
+ {
+ QImage image = pix.convertToImage();
+ for(int x=0; x<image.width(); x++)
+ for(int y=0; y<image.height(); y++)
+ {
+ QRgb rgb=image.pixel(x,y);
+ rgb=qRgba(
+ qRed(rgb)+KVI_STYLE_COLOR_DIFF/KVI_STYLE_NUM_STEPS*m_iStepNumber < 255 ? qRed(rgb)+KVI_STYLE_COLOR_DIFF/KVI_STYLE_NUM_STEPS*m_iStepNumber : 255 ,
+ qGreen(rgb)+KVI_STYLE_COLOR_DIFF/KVI_STYLE_NUM_STEPS*m_iStepNumber < 255 ? qGreen(rgb)+KVI_STYLE_COLOR_DIFF/KVI_STYLE_NUM_STEPS*m_iStepNumber : 255,
+ qBlue(rgb),
+ qAlpha(rgb)
+ );
+ image.setPixel(x,y,rgb);
+ }
+ p.drawImage(0,0,image);
+ } else if( !isEnabled()) {
+ QImage image = pix.convertToImage();
+ for(int x=0; x<image.width(); x++)
+ for(int y=0; y<image.height(); y++)
+ {
+ //- From Black to Gray conversion for disabled mode.
+ QRgb rgb=image.pixel(x,y);
+ rgb=qRgba(
+ qRed(rgb)+KVI_STYLE_COLOR_DIFF/KVI_STYLE_NUM_STEPS*m_iStepNumber == 0 ? 180 : qRed(rgb)+KVI_STYLE_COLOR_DIFF/KVI_STYLE_NUM_STEPS*m_iStepNumber,
+ qGreen(rgb)+KVI_STYLE_COLOR_DIFF/KVI_STYLE_NUM_STEPS*m_iStepNumber == 0 ? 180 : qGreen(rgb)+KVI_STYLE_COLOR_DIFF/KVI_STYLE_NUM_STEPS*m_iStepNumber,
+ qBlue(rgb)+KVI_STYLE_COLOR_DIFF/KVI_STYLE_NUM_STEPS*m_iStepNumber == 0 ? 180 : qBlue(rgb)+KVI_STYLE_COLOR_DIFF/KVI_STYLE_NUM_STEPS*m_iStepNumber,
+ qAlpha(rgb)
+ );
+ image.setPixel(x,y,rgb);
+ }
+ p.drawImage(0,0,image);
+ } else {
+ p.drawPixmap(0,0,pix);
+ }
+ //debug("%s %s %i %i %i",__FILE__,__FUNCTION__,__LINE__,m_bMouseEnter,m_iStepNumber);
+ QString szText=text();
+ szText=szText.remove("&");
+ p.drawText(pix.width()+3,0,width(),height(),0,szText);
+ bitBlt(this, rect.x(), rect.y(), pDoubleBufferPixmap, 0, 0, rect.width(), rect.height());
+ //debug("%s %s %i %i %i",__FILE__,__FUNCTION__,__LINE__,m_bMouseEnter,m_iStepNumber);
+ } else {
+ QCheckBox::paintEvent(event);
+ }
+ } else
+ QCheckBox::paintEvent(event);
+}
+
+KviStyledToolButton::KviStyledToolButton( QWidget * parent, const char * name )
+: QToolButton(parent,name), KviStyledControl(this), bShowSubmenuIndicator(false)
+{
+ setWFlags(WNoAutoErase);
+ resizeEvent(0);
+}
+
+KviStyledToolButton::KviStyledToolButton ( const QIconSet & iconSet, const QString & textLabel, const QString & grouptext, QObject * receiver, const char * slot, KviTalToolBar * parent, const char * name )
+: QToolButton(iconSet,textLabel,grouptext,receiver,slot,parent,name), KviStyledControl(this), bShowSubmenuIndicator(false)
+{
+ setWFlags(WNoAutoErase);
+ resizeEvent(0);
+}
+
+KviStyledToolButton::~KviStyledToolButton()
+{
+
+}
+
+void KviStyledToolButton::setShowSubmenuIndicator(bool bShow)
+{
+ bShowSubmenuIndicator=bShow;
+ resizeEvent(0);
+}
+
+void KviStyledToolButton::paintEvent ( QPaintEvent * event)
+{
+ if(KVI_OPTION_BOOL(KviOption_boolEnableVisualEffects))
+ {
+ QPixmap* pArrowPix = 0;
+ int iWidth=width();
+ int iPixWidth=0;
+ if(bShowSubmenuIndicator)
+ {
+ if(pArrowPix=g_pIconManager->getBigIcon("kvi_toolbutton_menuindicator.png"))
+ iPixWidth=pArrowPix->width();
+ }
+ bool bActive= isOn() || m_bMouseEnter;
+ KviDoubleBuffer doublebuffer(event->rect().width(),event->rect().height());
+ QPixmap * pDoubleBufferPixmap = doublebuffer.pixmap();
+
+ QRect rect=event->rect();
+
+ pDoubleBufferPixmap->fill(
+ bActive ? QColor(206,215,223) :
+ colorGroup().background()
+ );
+
+
+ QPainter p(pDoubleBufferPixmap, this);
+ p.translate(-rect.x(), -rect.y());
+
+ if(bActive)
+ {
+ p.setPen(QColor(185,190,195));
+ p.drawRect(0,0,iWidth,height());
+ }
+
+ QPixmap pix=iconSet().pixmap(
+ usesBigPixmap() ? QIconSet::Large : QIconSet::Small,
+ isEnabled() ? QIconSet::Normal :
+ QIconSet::Disabled,
+ isOn() ? QIconSet::On :
+ QIconSet::Off);
+ QPoint pos((iWidth-iPixWidth-pix.width())/2,(height()-pix.height())/2);
+ if(!pix.isNull())
+ {
+ if(m_iStepNumber && isEnabled())
+ {
+ QImage image = pix.convertToImage();
+ for(int x=0; x<image.width(); x++)
+ for(int y=0; y<image.height(); y++)
+ {
+ QRgb rgb=image.pixel(x,y);
+ rgb=qRgba(
+ qRed(rgb)+KVI_STYLE_COLOR_DIFF/KVI_STYLE_NUM_STEPS*m_iStepNumber < 255 ? qRed(rgb)+KVI_STYLE_COLOR_DIFF/KVI_STYLE_NUM_STEPS*m_iStepNumber : 255 ,
+ qGreen(rgb)+KVI_STYLE_COLOR_DIFF/KVI_STYLE_NUM_STEPS*m_iStepNumber < 255 ? qGreen(rgb)+KVI_STYLE_COLOR_DIFF/KVI_STYLE_NUM_STEPS*m_iStepNumber : 255,
+ qBlue(rgb),
+ qAlpha(rgb)
+ );
+ image.setPixel(x,y,rgb);
+ }
+ p.drawImage(pos,image);
+ } else if( !isEnabled()) {
+ QImage image = pix.convertToImage();
+ for(int x=0; x<image.width(); x++)
+ for(int y=0; y<image.height(); y++)
+ {
+ //- From Black to Gray conversion for disabled mode.
+ QRgb rgb=image.pixel(x,y);
+ rgb=qRgba(
+ qRed(rgb)+KVI_STYLE_COLOR_DIFF/KVI_STYLE_NUM_STEPS*m_iStepNumber == 0 ? 180 : qRed(rgb)+KVI_STYLE_COLOR_DIFF/KVI_STYLE_NUM_STEPS*m_iStepNumber,
+ qGreen(rgb)+KVI_STYLE_COLOR_DIFF/KVI_STYLE_NUM_STEPS*m_iStepNumber == 0 ? 180 : qGreen(rgb)+KVI_STYLE_COLOR_DIFF/KVI_STYLE_NUM_STEPS*m_iStepNumber,
+ qBlue(rgb)+KVI_STYLE_COLOR_DIFF/KVI_STYLE_NUM_STEPS*m_iStepNumber == 0 ? 180 : qBlue(rgb)+KVI_STYLE_COLOR_DIFF/KVI_STYLE_NUM_STEPS*m_iStepNumber,
+ qAlpha(rgb)
+ );
+ image.setPixel(x,y,rgb);
+ }
+ p.drawImage(pos,image);
+ } else {
+ p.drawPixmap(pos,pix);
+ }
+ }
+
+ if(pArrowPix)
+ {
+ pos.setX(pix.width()+4);
+ pos.setY((height()-pArrowPix->height())/2);
+ p.drawPixmap(pos,*pArrowPix);
+ }
+
+ bitBlt(this, rect.x(), rect.y(), pDoubleBufferPixmap, 0, 0, rect.width(), rect.height());
+
+ } else {
+ QToolButton::paintEvent(event);
+ }
+}
+
+void KviStyledToolButton::resizeEvent ( QResizeEvent * e)
+{
+ QPixmap* pStoredPix = 0;
+ if(pStoredPix=g_pIconManager->getBigIcon("kvi_toolbutton_menuindicator.png"))
+ {
+ QPixmap pix=iconSet().pixmap(
+ usesBigPixmap() ? QIconSet::Large : QIconSet::Small,
+ isEnabled() ? QIconSet::Normal :
+ QIconSet::Disabled,
+ isOn() ? QIconSet::On :
+ QIconSet::Off);
+
+ setMinimumWidth(bShowSubmenuIndicator ? pix.width()+8+pStoredPix->width() : pix.width());
+ }
+}
+
+#include "kvi_styled_controls.moc"
+
+#endif
diff --git a/src/kvirc/ui/kvi_styled_controls.h b/src/kvirc/ui/kvi_styled_controls.h
new file mode 100644
index 00000000..8d096fa8
--- /dev/null
+++ b/src/kvirc/ui/kvi_styled_controls.h
@@ -0,0 +1,113 @@
+#ifndef _KVI_STYLED_CONTROLS_H_
+#define _KVI_STYLED_CONTROLS_H_
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// File : kvi_styled_controls.h
+// Creation date : 19 Jan 2006 GMT by Alexey Uzhva
+//
+// This toolbar is part of the KVirc irc client distribution
+// Copyright (C) 2006 Alexey Uzhva
+//
+// 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 opinion) 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.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_USE_QT4
+ // we use internal Qt4 styles for now
+ #include <qcheckbox.h>
+ #include <qtoolbutton.h>
+
+ #define KviStyledCheckBox QCheckBox
+ #define KviStyledToolButton QToolButton
+#else
+
+#include <qcheckbox.h>
+#include <qtoolbutton.h>
+#include <qevent.h>
+#include <qtimer.h>
+#include "kvi_heapobject.h"
+
+class KviTalToolBar;
+
+#define KVI_STYLE_NUM_STEPS 20
+#define KVI_STYLE_COLOR_DIFF 60
+#define KVI_STYLE_TIMER_STEP 18
+
+class KviStyledControl;
+
+class KVIRC_API KviStyledControlInternal : public QObject
+{
+ Q_OBJECT
+public:
+ KviStyledControlInternal( KviStyledControl* control );
+ ~KviStyledControlInternal();
+public slots:
+ virtual void paintTimerShot();
+protected:
+ bool eventFilter( QObject *obj, QEvent *ev );
+protected:
+ KviStyledControl* m_pControl;
+};
+
+class KVIRC_API KviStyledControl
+{
+ friend class KviStyledControlInternal;
+public:
+ KviStyledControl(QWidget*);
+ ~KviStyledControl();
+protected:
+ virtual void enterEvent ( QEvent * );
+ virtual void leaveEvent ( QEvent * );
+
+ int m_bMouseEnter;
+ int m_iStepNumber;
+ QTimer* m_pTimer;
+ KviStyledControlInternal* m_pInternal;
+ QWidget *m_pWidget;
+};
+
+class KVIRC_API KviStyledCheckBox : public QCheckBox, public KviStyledControl
+{
+ Q_OBJECT
+public:
+ KviStyledCheckBox ( QWidget * parent, const char * name = 0 );
+ KviStyledCheckBox ( const QString & text, QWidget * parent, const char * name = 0 );
+ ~KviStyledCheckBox();
+protected:
+ virtual void paintEvent ( QPaintEvent * );
+};
+
+class KVIRC_API KviStyledToolButton : public QToolButton, public KviStyledControl
+{
+ Q_OBJECT
+private:
+ bool bShowSubmenuIndicator;
+public:
+ KviStyledToolButton ( QWidget * parent, const char * name = 0 );
+ KviStyledToolButton ( const QIconSet & iconSet, const QString & textLabel, const QString & grouptext, QObject * receiver, const char * slot, KviTalToolBar * parent, const char * name = 0 );
+ ~KviStyledToolButton();
+
+ void setShowSubmenuIndicator(bool bShow);
+protected:
+ virtual void paintEvent ( QPaintEvent * );
+ virtual void resizeEvent ( QResizeEvent * ) ;
+};
+
+#endif
+
+#endif
diff --git a/src/kvirc/ui/kvi_taskbar.cpp b/src/kvirc/ui/kvi_taskbar.cpp
new file mode 100644
index 00000000..8e75bfde
--- /dev/null
+++ b/src/kvirc/ui/kvi_taskbar.cpp
@@ -0,0 +1,1509 @@
+//===============================================================================================
+//
+// File : kvi_taskbar.cpp
+// Last major modification : Thu Jan 7 1999 03:59:43 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//===============================================================================================
+
+#define __KVIRC__
+//#define KVI_TASKBARBUTTON_MIN_WIDTH 100
+#define KVI_TASKBARBUTTON_CONTEXTINDICATORHEIGHT 6
+#define KVI_TASKBAR_MIN_WIDTH 120
+
+#define KVI_NUM_STEPS 20
+#define KVI_TIMER_DELAY 18
+
+
+#define _KVI_DEBUG_CHECK_RANGE_
+#include "kvi_debug.h"
+#include "kvi_taskbar.h"
+#include "kvi_frame.h"
+#include "kvi_window.h"
+#include "kvi_string.h"
+#include "kvi_options.h"
+#include "kvi_console.h"
+#include "kvi_locale.h"
+#include "kvi_dynamictooltip.h"
+#include "kvi_settings.h"
+#include "kvi_channel.h"
+#include "kvi_ircconnection.h"
+#include "kvi_doublebuffer.h"
+
+// FIXME: #warning "The tree taskbar min width should be configurable"
+#include <qtimer.h>
+#include <qfontmetrics.h>
+#include <qpainter.h>
+#include <qpixmap.h>
+#include <qimage.h>
+#include "kvi_tal_popupmenu.h"
+#include <qcursor.h>
+
+#ifdef COMPILE_USE_QT4
+ #include <q3header.h>
+#else
+ #include <qheader.h>
+#endif
+#include <qevent.h>
+
+#ifdef COMPILE_USE_QT4
+ #include <QPaintEvent>
+#endif
+
+
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ extern QPixmap * g_pShadedChildGlobalDesktopBackground;
+#endif
+
+extern QPixmap * g_pActivityMeterPixmap;
+
+// FIXME: This should be renamed to "Window List"
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// KviTaskBarBase
+//
+
+KviTaskBarBase::KviTaskBarBase()
+#ifdef COMPILE_USE_QT4
+: QDockWidget(__tr2qs("Taskbar"),g_pFrame)
+#else
+: KviToolBar(__tr2qs("Taskbar"),QT_DOCK_BOTTOM,false,"taskbar")
+#endif
+{
+ // FIXME: this timer should be started only if KVI_OPTION_BOOL(KviOption_boolUseTaskBarActivityMeter)
+#ifdef COMPILE_USE_QT4
+ setObjectName(__tr2qs("taskbar"));
+ setFeatures(QDockWidget::DockWidgetMovable);
+#endif //COMPILE_USE_QT4
+ m_pActivityMeterTimer = new QTimer();
+ connect(m_pActivityMeterTimer,SIGNAL(timeout()),this,SLOT(updateActivityMeter()));
+ m_pActivityMeterTimer->start(5000);
+}
+
+KviTaskBarBase::~KviTaskBarBase()
+{
+ delete m_pActivityMeterTimer;
+}
+
+void KviTaskBarBase::updateActivityMeter()
+{
+}
+
+void KviTaskBarBase::getTextForConsole(QString &szText,KviConsole * pConsole)
+{
+ if(pConsole->isConnected())
+ {
+ if(KVI_OPTION_BOOL(KviOption_boolShowNetworkNameForConsoleTaskBarEntry))
+ {
+ // FIXME: Should never show "Standalone Servers" or "orphan_servers".
+ // It would also be nice to have a number appended to
+ // multiple entries with the same server name...but this costs too much.
+ szText = pConsole->connection()->networkName();
+ if(szText.isEmpty())
+ szText = pConsole->connection()->currentServerName();
+ } else {
+ szText = pConsole->connection()->currentServerName();
+ }
+ } else {
+ szText = pConsole->statusString();
+ }
+}
+
+
+KviTaskBarItem * KviTaskBarBase::item(int number)
+{
+ KviTaskBarItem * it = firstItem();
+ if(!setIterationPointer(it))return 0;
+
+ while(it && (number > 0))
+ {
+ it = nextItem();
+ number--;
+ }
+ return it;
+}
+
+void KviTaskBarBase::switchWindow(bool bNext,bool bInContextOnly)
+{
+ if(!g_pActiveWindow)return;
+
+ KviConsole * cons = g_pActiveWindow->console();
+ KviTaskBarItem * cur = g_pActiveWindow->taskBarItem();
+ KviTaskBarItem * it = cur;
+
+ if(!setIterationPointer(cur))return;
+
+ while(it)
+ {
+ it = bNext ? nextItem() : prevItem();
+ if(!it)it = bNext ? firstItem() : lastItem();
+ if(it)
+ {
+ if(bInContextOnly)
+ {
+ if(it->kviWindow()->console() == cons)
+ {
+ g_pFrame->setActiveWindow(it->kviWindow());
+ return;
+ }
+ } else {
+ g_pFrame->setActiveWindow(it->kviWindow());
+ return;
+ }
+ }
+ if(it == cur)return; // did a complete loop.... no window to switch to
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// KviTaskBarItem
+//
+
+KviTaskBarItem::KviTaskBarItem(KviWindow * wnd)
+{
+ m_pWindow = wnd;
+ m_iHighlightLevel = 0;
+ m_iProgress = -1;
+}
+
+KviTaskBarItem::~KviTaskBarItem()
+{
+ m_pWindow->m_pTaskBarItem = 0;
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// KviTaskBarButton
+//
+
+
+KviTaskBarButton::KviTaskBarButton(QWidget * par,KviWindow * wnd,const char * name)
+: QPushButton(par,name) , KviTaskBarItem(wnd)
+{
+ m_bActive = false;
+ m_pTip = new KviDynamicToolTip(this);
+ connect(m_pTip,SIGNAL(tipRequest(KviDynamicToolTip *,const QPoint &)),this,SLOT(tipRequest(KviDynamicToolTip *,const QPoint &)));
+// setBackgroundMode(QWidget::NoBackground);
+ setToggleButton (true);
+ setFlat ( KVI_OPTION_BOOL(KviOption_boolUseFlatClassicTaskbarButtons) );
+}
+
+KviTaskBarButton::~KviTaskBarButton()
+{
+ delete m_pTip; //not necessary ?
+}
+
+void KviTaskBarButton::tipRequest(KviDynamicToolTip *,const QPoint &pnt)
+{
+ if(KVI_OPTION_BOOL(KviOption_boolShowTaskBarToolTips))
+ {
+ QString szText;
+ m_pWindow->getTaskBarTipText(szText);
+ m_pTip->tip(rect(),szText);
+ }
+}
+
+void KviTaskBarButton::mousePressEvent(QMouseEvent *e)
+{
+ if(e->button() & Qt::LeftButton)
+ {
+ if(e->state() & Qt::ShiftButton)
+ {
+ m_pWindow->delayedClose();
+ } else {
+ if((g_pActiveWindow != m_pWindow) || (m_pWindow->isMinimized()))g_pFrame->setActiveWindow(m_pWindow);
+ else m_pWindow->minimize();
+ }
+ } else m_pWindow->contextPopup();
+}
+
+#if QT_VERSION >= 300
+void KviTaskBarButton::contextMenuEvent(QContextMenuEvent *e)
+{
+ m_pWindow->contextPopup();
+ e->accept();
+}
+#endif
+
+void KviTaskBarButton::setActive(bool bActive)
+{
+ if(bActive)
+ {
+ m_bActive = true;
+ m_iHighlightLevel = 0;
+ } else {
+ if(m_bActive)
+ {
+ // was active... unset the highlighting if it was silently turned on while being active...
+ m_iHighlightLevel = 0;
+ }
+ m_bActive = false;
+ }
+ setOn(bActive);
+ update();
+}
+
+#ifdef COMPILE_USE_QT4
+void KviTaskBarButton::paintEvent(QPaintEvent * e)
+{
+ QPainter p(this);
+ QStyleOption opt;
+ opt.initFrom(this);
+ if(isOn())
+ opt.state = QStyle::State_On | QStyle::State_Active;
+ style()->drawPrimitive(QStyle::PE_PanelButtonTool,&opt,&p,this);
+ drawButtonLabel(&p);
+}
+#endif
+
+void KviTaskBarButton::drawButtonLabel(QPainter * painter)
+{
+ QRect distRect = painter->window();
+ int iHeight = distRect.height();
+ int iWidth = distRect.width();
+
+ QPainter * pPainter;
+#ifdef COMPILE_USE_QT4
+ pPainter = painter;
+#else //!COMPILE_USE_QT4
+ KviDoubleBuffer db(iWidth,iHeight);
+ QPixmap * pMemBuffer = db.pixmap();
+ QPainter p(pMemBuffer);
+ bitBlt(pMemBuffer,0,0,painter->device(),distRect.x(),distRect.y(),iWidth,iHeight);
+ pPainter = &p;
+#endif //!COMPILE_USE_QT4
+ if(KVI_OPTION_BOOL(KviOption_boolUseTaskBarIrcContextIndicator))
+ {
+ iHeight -= KVI_TASKBARBUTTON_CONTEXTINDICATORHEIGHT;
+ QColor base = colorGroup().background();
+ if(m_pWindow->console())
+ {
+ QColor cntx = KVI_OPTION_ICCOLOR(m_pWindow->console()->ircContextId() % KVI_NUM_ICCOLOR_OPTIONS);
+ base.setRgb((base.red() + cntx.red()) >> 1,(base.green() + cntx.green()) >> 1,
+ (base.blue() + cntx.blue()) >> 1);
+ pPainter->fillRect(2,iHeight,iWidth - 4,KVI_TASKBARBUTTON_CONTEXTINDICATORHEIGHT - 2,base);
+ } else {
+ pPainter->fillRect(2,iHeight,iWidth - 4,KVI_TASKBARBUTTON_CONTEXTINDICATORHEIGHT - 2,colorGroup().brush(QColorGroup::Background));
+ }
+ }
+
+ int daX = 3;
+
+ if(KVI_OPTION_BOOL(KviOption_boolUseTaskBarIcons))
+ {
+ pPainter->drawPixmap(3,3,*(m_pWindow->myIconPtr()));
+ daX = 20;
+ }
+
+ if(KVI_OPTION_BOOL(KviOption_boolUseTaskBarActivityMeter))
+ {
+ unsigned int uActivityValue;
+ unsigned int uActivityTemperature;
+ if(m_pWindow->activityMeter(&uActivityValue,&uActivityTemperature))
+ {
+ pPainter->drawPixmap(daX,3,*g_pActivityMeterPixmap,uActivityValue * 5,uActivityTemperature * 16,5,16);
+ daX = 27;
+ }
+ }
+
+ QRect cRect(daX,3,iWidth - (20 + daX),iHeight - 6);
+
+ if(m_iProgress >= 0)
+ {
+ // paint the progress bar
+ int wdth = (m_iProgress * cRect.width()) / 100;
+ pPainter->setPen(KVI_OPTION_COLOR(KviOption_colorTaskBarProgressBar));
+ pPainter->drawRect(cRect);
+ pPainter->fillRect(daX,3,wdth,cRect.height(),KVI_OPTION_COLOR(KviOption_colorTaskBarProgressBar));
+ }
+
+ QRect bRect;
+ QString szText;
+
+ bool bMinimized = m_pWindow->isMinimized();
+
+ if(m_bActive)
+ {
+ pPainter->setPen(KVI_OPTION_COLOR(KviOption_colorTaskBarNormalText));
+ } else {
+ int iLevel;
+
+ switch(m_iHighlightLevel)
+ {
+ case 0: iLevel = bMinimized ? KviOption_colorTaskBarMinimizedText : KviOption_colorTaskBarNormalText; break;
+ case 1: iLevel = KviOption_colorTaskBarHighlight1Text; break;
+ case 2: iLevel = KviOption_colorTaskBarHighlight2Text; break;
+ case 3: iLevel = KviOption_colorTaskBarHighlight3Text; break;
+ case 4: iLevel = KviOption_colorTaskBarHighlight4Text; break;
+ default: iLevel = KviOption_colorTaskBarHighlight5Text; break;
+ }
+ pPainter->setPen(KVI_OPTION_COLOR(iLevel));
+ }
+
+ pPainter->setFont(KVI_OPTION_FONT(KviOption_fontTaskbar));
+
+ switch(m_pWindow->type())
+ {
+ case KVI_WINDOW_TYPE_CONSOLE:
+ {
+ QFont f = QFont(KVI_OPTION_FONT(KviOption_fontTaskbar));
+ f.setBold(true);
+ pPainter->setFont(f);
+ KviTaskBarBase::getTextForConsole(szText,(KviConsole *)m_pWindow);
+ }
+ break;
+ case KVI_WINDOW_TYPE_CHANNEL:
+ case KVI_WINDOW_TYPE_DEADCHANNEL:
+ szText = ((KviChannel *)m_pWindow)->nameWithUserFlag();
+ break;
+ case KVI_WINDOW_TYPE_QUERY:
+ case KVI_WINDOW_TYPE_DEADQUERY:
+ szText = m_pWindow->windowName();
+ break;
+ default:
+ szText = m_pWindow->plainTextCaption();
+ break;
+ }
+
+ if(bMinimized)
+ {
+ QString tmp = QChar('(');
+ tmp += szText;
+ tmp += QChar(')');
+ pPainter->drawText(cRect,Qt::AlignLeft | Qt::AlignTop,tmp,-1,&bRect);
+ } else {
+ pPainter->drawText(cRect,Qt::AlignLeft | Qt::AlignTop,szText,-1,&bRect);
+ }
+
+ if(bRect.width() > cRect.width())
+ {
+ pPainter->setClipRect(cRect.right(),cRect.y(),10,cRect.height());
+ QColor base = pPainter->pen().color();
+ QColor bg = colorGroup().color(QColorGroup::Background);
+ base.setRgb((base.red() + bg.red()) / 2,(base.green() + bg.green()) / 2,(base.blue() + bg.blue()) / 2);
+ pPainter->setPen(base);
+ cRect.setWidth(cRect.width() + 10);
+ pPainter->drawText(cRect,Qt::AlignLeft | Qt::AlignTop,szText,-1);
+ pPainter->setClipRect(cRect.right(),cRect.y(),5,cRect.height());
+ base.setRgb((base.red() + bg.red()) / 2,(base.green() + bg.green()) / 2,(base.blue() + bg.blue()) / 2);
+ pPainter->setPen(base);
+ cRect.setWidth(cRect.width() + 10);
+ pPainter->drawText(cRect,Qt::AlignLeft | Qt::AlignTop,szText,-1);
+ }
+#ifndef COMPILE_USE_QT4
+ pPainter->setClipping(FALSE);
+ painter->drawPixmap(0,0,*pMemBuffer,distRect.x(),distRect.y(),iWidth,iHeight);
+#endif
+}
+
+
+void KviTaskBarButton::captionChanged()
+{
+ update();
+}
+
+void KviTaskBarButton::setProgress(int progress)
+{
+ if(progress == m_iProgress)return;
+ m_iProgress = progress;
+ update(); // repaint(false) ?
+}
+
+void KviTaskBarButton::unhighlight()
+{
+ if(m_iHighlightLevel < 1)return;
+ m_iHighlightLevel = 0;
+ if(g_pFrame->dockExtension())g_pFrame->dockExtension()->refresh();
+ update();
+}
+
+void KviTaskBarButton::highlight(int iLevel)
+{
+ if(iLevel <= m_iHighlightLevel)return;
+ if(m_bActive && g_pFrame->isActiveWindow())return;
+ m_iHighlightLevel = iLevel;
+ if(g_pFrame->dockExtension())g_pFrame->dockExtension()->refresh();
+ if(m_bActive)return;
+ update(); // repaint(false) ?
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// KviTaskBarToolTip
+//
+/*
+KviTaskBarToolTip::KviTaskBarToolTip(KviTaskBarButton * b)
+: KviTalToolTip(b,0)
+{
+ m_pTaskBarButton = b;
+}
+
+KviTaskBarToolTip::~KviTaskBarToolTip()
+{
+}
+
+void KviTaskBarToolTip::maybeTip(const QPoint &pnt)
+{
+ tip(m_pTaskBarButton->rect(),m_pTaskBarButton->m_pWindow->plainTextCaption());
+}
+*/
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// KviClasicTaskBar
+//
+
+
+KviClassicTaskBar::KviClassicTaskBar()
+: KviTaskBarBase()
+{
+ m_pButtonList = new KviPointerList<KviTaskBarButton>;
+ m_pButtonList->setAutoDelete(true);
+
+ calcButtonHeight();
+
+ m_pBase = new QWidget(this);
+// m_pBase->setBackgroundMode(NoBackground);
+#ifdef COMPILE_USE_QT4
+ setWidget(m_pBase);
+
+ m_pBase->setMinimumWidth(KVI_TASKBAR_MIN_WIDTH);
+ setMinimumWidth(KVI_TASKBAR_MIN_WIDTH);
+#else //!COMPILE_USE_QT4
+ setStretchableWidget(m_pBase);
+
+ setVerticalStretchable(true);
+ setHorizontalStretchable(true);
+#endif //!COMPILE_USE_QT4
+ //m_pBase->setMinimumWidth(KVI_TASKBAR_MIN_WIDTH);
+ //setMinimumWidth(KVI_TASKBAR_MIN_WIDTH);
+
+ m_pBase->setMinimumHeight(m_iButtonHeight+5);
+ setMinimumHeight(m_iButtonHeight+5);
+
+#ifndef COMPILE_USE_QT4
+ setResizeEnabled( true );
+ connect(this,SIGNAL(orientationChanged(Orientation)),this,SLOT(orientationChangedSlot(Orientation)));
+#endif
+}
+
+KviClassicTaskBar::~KviClassicTaskBar()
+{
+ delete m_pButtonList;
+ m_pButtonList = 0;
+}
+
+void KviClassicTaskBar::orientationChangedSlot(Qt::Orientation o)
+{
+#ifndef COMPILE_USE_QT4
+ if (orientation() == Qt::Horizontal) m_pBase->setMinimumHeight(m_iButtonHeight);
+#endif
+ doLayout();
+}
+
+/*
+void KviClassicTaskBar::fontChange(const QFont &old)
+{
+ calcButtonHeight();
+ doLayout();
+ QToolBar::fontChange(old);
+}
+*/
+
+void KviClassicTaskBar::updateActivityMeter()
+{
+ if(KVI_OPTION_BOOL(KviOption_boolUseTaskBarActivityMeter))
+ {
+ for(KviTaskBarButton * btn = m_pButtonList->first();btn;btn = m_pButtonList->next())
+ btn->update();
+ }
+}
+
+void KviClassicTaskBar::calcButtonHeight()
+{
+ QFontMetrics fm(KVI_OPTION_FONT(KviOption_fontTaskbar));
+ m_iButtonHeight = fm.lineSpacing() + 6;
+ if(m_iButtonHeight < 22)m_iButtonHeight = 22;
+ if(KVI_OPTION_BOOL(KviOption_boolUseTaskBarIrcContextIndicator))
+ m_iButtonHeight += KVI_TASKBARBUTTON_CONTEXTINDICATORHEIGHT;
+}
+
+void KviClassicTaskBar::insertButton(KviTaskBarButton * b)
+{
+ int idx = 0;
+// if(KVI_OPTION_BOOL(KviOption_boolSortTaskbarButtons))
+// {
+ // first sort by irc context
+ for(KviTaskBarButton * btn = m_pButtonList->first();btn;btn = m_pButtonList->next())
+ {
+ if(btn->kviWindow()->console() == b->kviWindow()->console())
+ {
+ // same irc context (or none)
+ // sort by type now
+ for(;btn;btn = m_pButtonList->next())
+ {
+ if((btn->kviWindow()->type() > b->kviWindow()->type()) ||
+ (btn->kviWindow()->console() != b->kviWindow()->console()))
+ {
+ // greater type or another irc context
+ m_pButtonList->insert(idx,b);
+ return;
+ } else if(btn->kviWindow()->type() == b->kviWindow()->type())
+ {
+ // same type!
+ // sort by name
+ if(!KVI_OPTION_BOOL(KviOption_boolSortTaskBarItemsByName) || (KviQString::cmpCI(btn->kviWindow()->windowName(),b->kviWindow()->windowName()) > 0))
+ {
+ // got a "higher one"
+ m_pButtonList->insert(idx,b);
+ return;
+ }
+ }
+ idx++;
+ }
+ // ran out of buttons
+ m_pButtonList->append(b);
+ return;
+ } else {
+ if(!(btn->kviWindow()->console()) && b->kviWindow()->console())
+ {
+ // this must be a new console...insert before the contextless windows
+ __range_valid(b->kviWindow()->console() == b->kviWindow());
+ m_pButtonList->insert(idx,b);
+ return;
+ } else idx++; // wrong irc contet...go on searching
+ }
+ }
+// }
+ // no sorting selected , or no match for this irc context
+ m_pButtonList->append(b);
+}
+
+
+KviTaskBarItem * KviClassicTaskBar::addItem(KviWindow * wnd)
+{
+ KviTaskBarButton * b = new KviTaskBarButton(m_pBase,wnd,"");
+ insertButton(b);
+ b->show();
+ doLayout();
+ if(g_pFrame->dockExtension())g_pFrame->dockExtension()->refresh();
+/* if(b->width() < m_pBase->width()) m_pBase->setMinimumWidth(b->width());
+ if(b->height() < m_pBase->height()) m_pBase->setMinimumWidth(b->height());*/
+ return b;
+}
+
+bool KviClassicTaskBar::removeItem(KviTaskBarItem * it)
+{
+ if(it)
+ {
+ m_pButtonList->removeRef((KviTaskBarButton *)it);
+ doLayout();
+ if(g_pFrame->dockExtension())g_pFrame->dockExtension()->refresh();
+ }
+ return true;
+}
+
+void KviClassicTaskBar::setActiveItem(KviTaskBarItem * it)
+{
+ if(it)
+ {
+ for(KviTaskBarButton * b = m_pButtonList->first();b;b = m_pButtonList->next())
+ {
+ b->setActive(((KviTaskBarButton *)it) == b);
+ }
+ if(g_pFrame->dockExtension())g_pFrame->dockExtension()->refresh();
+ }
+}
+
+
+void KviClassicTaskBar::doLayout()
+{
+ if(!m_pButtonList->count())return;
+
+ if(!m_pBase->isVisible())
+ {
+ // handle a windows bug: sometimes this ugly thing happens
+ // this shouldn't hurt on other platforms
+ if(isVisible())m_pBase->show();
+ }
+
+ int baseWidth = m_pBase->width();
+ int btnsInRow = baseWidth / KVI_OPTION_UINT(KviOption_uintTaskBarButtonMinWidth);
+ int totCount = m_pButtonList->count();
+ //int btnsInRow = totCount * totCount * btnWidth * btnWidth / (wdth * wdth);
+ if(btnsInRow < 1)btnsInRow = 1;
+
+ int rows = 0;
+ while(totCount > 0)
+ {
+ rows++;
+ totCount -= btnsInRow;
+ }
+
+#ifdef COMPILE_USE_QT4
+ if(isFloating() || ((g_pFrame->dockWidgetArea(this) != Qt::BottomDockWidgetArea) && (g_pFrame->dockWidgetArea(this) != Qt::TopDockWidgetArea)))
+ {
+ QDockWidget::DockWidgetFeatures f = features();
+ if(f & QDockWidget::DockWidgetVerticalTitleBar)
+ {
+ f &= ~QDockWidget::DockWidgetVerticalTitleBar;
+ setFeatures(f);
+ }
+ } else {
+ QDockWidget::DockWidgetFeatures f = features();
+ if(!(f & QDockWidget::DockWidgetVerticalTitleBar))
+ {
+ f |= QDockWidget::DockWidgetVerticalTitleBar;
+ setFeatures(f);
+ }
+ }
+#endif
+
+#ifdef COMPILE_USE_QT4
+ if ((width() > height()) &&
+#else
+ if ((orientation() == Qt::Horizontal) &&
+#endif
+ (((unsigned int)rows) > m_pBase->height() / m_iButtonHeight ))
+ {
+ rows = m_pBase->height() / m_iButtonHeight;
+ }
+ if(rows==0) rows=1;
+ totCount = m_pButtonList->count();
+ btnsInRow = totCount / rows;
+ if(totCount % rows)btnsInRow++;
+
+ //m_pBase->setMinimumHeight(rows * m_iButtonHeight);
+
+ int theWidth = 0;
+ int theX = 0;
+ int theY = -m_iButtonHeight;
+ int btnIdx = 0;
+ int btnInRow = 1;
+ for(KviTaskBarButton * b = m_pButtonList->first();b;b = m_pButtonList->next())
+ {
+ if((btnIdx % btnsInRow) == 0)
+ {
+ int inRow = ((totCount < btnsInRow ) ? totCount : btnsInRow);
+ theWidth = baseWidth / (inRow ? inRow : 1);
+ theX = 0;
+ theY += m_iButtonHeight;
+ btnInRow = 1;
+ } else {
+ if((btnInRow == btnsInRow) || (totCount == 1))theWidth = baseWidth - theX;
+ }
+
+ if( KVI_OPTION_BOOL(KviOption_boolClassicTaskBarSetMaximumButtonWidth) && (theWidth > KVI_OPTION_UINT(KviOption_uintClassicTaskBarMaximumButtonWidth)) &&
+#ifdef COMPILE_USE_QT4
+ (width() > height())
+#else
+ (orientation() == Qt::Horizontal)
+#endif
+ )
+ theWidth = KVI_OPTION_UINT(KviOption_uintClassicTaskBarMaximumButtonWidth);
+
+ b->setGeometry(theX,theY,theWidth,m_iButtonHeight);
+
+ if(btnInRow != btnsInRow)
+ {
+ theX += theWidth;
+ btnInRow++;
+ }
+ btnIdx++;
+ totCount--;
+ }
+}
+
+void KviClassicTaskBar::applyOptions()
+{
+ for(KviTaskBarButton * b = m_pButtonList->first();b;b = m_pButtonList->next())
+ {
+ b->setFlat(KVI_OPTION_BOOL(KviOption_boolUseFlatClassicTaskbarButtons));
+ }
+ doLayout();
+}
+
+void KviClassicTaskBar::resizeEvent(QResizeEvent *e)
+{
+/*
+#ifdef COMPILE_USE_QT4
+ if(orientation() == Qt::Horizontal)
+ {
+ int iRows = height()/m_iButtonHeight;
+ if(!iRows) iRows=1;
+ debug("%i %i",height(),iRows);
+ resize(width(),iRows*m_iButtonHeight);
+ }
+#endif
+*/
+ KviTaskBarBase::resizeEvent(e);
+ doLayout();
+}
+
+inline KviTaskBarItem * KviClassicTaskBar::firstItem()
+{
+ return m_pButtonList->first();
+}
+
+inline KviTaskBarItem * KviClassicTaskBar::lastItem(void)
+{
+ return m_pButtonList->last();
+}
+
+inline KviTaskBarItem * KviClassicTaskBar::nextItem()
+{
+ return m_pButtonList->next();
+}
+
+inline KviTaskBarItem * KviClassicTaskBar::prevItem(void)
+{
+ return m_pButtonList->prev();
+}
+
+inline bool KviClassicTaskBar::setIterationPointer(KviTaskBarItem * it)
+{
+ return (m_pButtonList->findRef((const KviTaskBarButton *)it) != -1);
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// KviTreeTaskBarItem
+//
+
+
+KviTreeTaskBarItem::KviTreeTaskBarItem(KviTalListView * par,KviWindow * wnd)
+: KviTalListViewItem(par) , KviTaskBarItem(wnd)
+{
+ m_iStepNumber=0;
+ m_bIncreasing=0;
+ m_pInternal=new KviTreeTaskBarItemInternal(this);
+ m_pAnimTimer=new QTimer();
+ QObject::connect( m_pAnimTimer, SIGNAL(timeout()), m_pInternal, SLOT(timerShot()));
+ applyOptions();
+}
+
+KviTreeTaskBarItem::KviTreeTaskBarItem(KviTreeTaskBarItem * par,KviWindow * wnd)
+: KviTalListViewItem(par) , KviTaskBarItem(wnd)
+{
+ m_iStepNumber=0;
+ m_bIncreasing=0;
+ m_pInternal=new KviTreeTaskBarItemInternal(this);
+ m_pAnimTimer=new QTimer();
+ QObject::connect( m_pAnimTimer, SIGNAL(timeout()), m_pInternal, SLOT(timerShot()));
+ applyOptions();
+}
+
+int KviTreeTaskBarItem::calculateColor(int col1,int col2)
+{
+ int result=col1+(col2-col1)/KVI_NUM_STEPS*m_iStepNumber;
+ return result<255 ? result :255;
+}
+
+KviTreeTaskBarItem::~KviTreeTaskBarItem()
+{
+ KviTalListView* pView=(KviTalListView *)listView();
+ if(pView)
+ if(((KviTreeTaskBarListView*)(pView))->m_pPrevItem==this) ((KviTreeTaskBarListView*)(listView()))->m_pPrevItem=0;
+ delete m_pAnimTimer;
+ delete m_pInternal;
+}
+
+void KviTreeTaskBarItem::applyOptions()
+{
+ m_iRedDiff=(KVI_OPTION_COLOR(KviOption_colorTreeTaskBarActiveBackground).red()-KVI_OPTION_COLOR(KviOption_colorTreeTaskBarBackground).red())/KVI_NUM_STEPS;
+ m_iGreenDiff=(KVI_OPTION_COLOR(KviOption_colorTreeTaskBarActiveBackground).green()-KVI_OPTION_COLOR(KviOption_colorTreeTaskBarBackground).green())/KVI_NUM_STEPS;
+ m_iBlueDiff=(KVI_OPTION_COLOR(KviOption_colorTreeTaskBarActiveBackground).blue()-KVI_OPTION_COLOR(KviOption_colorTreeTaskBarBackground).blue())/KVI_NUM_STEPS;
+}
+
+void KviTreeTaskBarItem::captionChanged()
+{
+ // FIXME: can we do better ?
+ repaint();
+}
+
+void KviTreeTaskBarItem::unhighlight()
+{
+ if(m_iHighlightLevel < 1)return;
+ m_iHighlightLevel = 0;
+ if(g_pFrame->dockExtension())g_pFrame->dockExtension()->refresh();
+ repaint();
+}
+
+void KviTreeTaskBarItem::highlight(int iLevel)
+{
+ if(iLevel <= m_iHighlightLevel)return;
+ if(isSelected() && g_pFrame->isActiveWindow())return;
+ m_iHighlightLevel = iLevel;
+ if(g_pFrame->dockExtension())g_pFrame->dockExtension()->refresh();
+ if(isSelected())return;
+ repaint(); // repaint(false) ?
+}
+
+void KviTreeTaskBarItem::setProgress(int progress)
+{
+ if(progress == m_iProgress)return;
+ m_iProgress = progress;
+ repaint(); // repaint(false) ?
+}
+
+void KviTreeTaskBarItem::setActive(bool bActive)
+{
+ if(bActive)
+ {
+// m_bHighlighted = false;
+// m_bAltColor = false;
+ m_iHighlightLevel = 0;
+ // was not selected: the listView will repaint it
+ } else {
+ if(isSelected())
+ {
+ // was active... unset the highlighting if it was silently turned on while being active...
+// m_bHighlighted = false;
+// m_bAltColor = false;
+ m_iHighlightLevel = 0;
+ // was selected: the list view will repaint it
+ }
+ }
+}
+
+#ifdef COMPILE_USE_QT4
+void KviTreeTaskBarItem::paintBranches(QPainter *p,const QColorGroup &,int w,int y,int h)
+#else
+void KviTreeTaskBarItem::paintBranches(QPainter *p,const QColorGroup &,int w,int y,int h,GUIStyle s)
+#endif
+{
+ SET_ANTI_ALIASING(*p);
+ ((KviTreeTaskBarListView *)listView())->paintEmptyArea(p,QRect(0,y,w,totalHeight() - height()));
+}
+
+void KviTreeTaskBarItem::paintCell(QPainter *painter,const QColorGroup &cg,int column,int width,int)
+{
+ KviDoubleBuffer db(width,height());
+ QPixmap * pMemBuffer = db.pixmap();
+ QPainter p(pMemBuffer);
+ SET_ANTI_ALIASING(p);
+
+ if(isSelected())
+ {
+ p.fillRect(0,0,width,height(),KVI_OPTION_COLOR(KviOption_colorTreeTaskBarActiveBackground));
+ } else {
+ if(!m_iStepNumber)
+ {
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ if(g_pShadedChildGlobalDesktopBackground)
+ {
+ QPoint pnt = listView()->viewport()->mapToGlobal(QPoint(int(painter->worldMatrix().dx()),int(painter->worldMatrix().dy())));
+ p.drawTiledPixmap(0,0,width,height(),*g_pShadedChildGlobalDesktopBackground,pnt.x(),pnt.y());
+ } else {
+#endif
+ p.fillRect(0,0,width,height(),KVI_OPTION_COLOR(KviOption_colorTreeTaskBarBackground));
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ }
+#endif
+ QPixmap * pix = KVI_OPTION_PIXMAP(KviOption_pixmapTreeTaskBarBackground).pixmap();
+ if(pix)
+ {
+ QPoint pnt = listView()->viewportToContents(QPoint(int(painter->worldMatrix().dx()),int(painter->worldMatrix().dy())));
+ //p.drawTiledPixmap(0,0,width,height(),*pix,pnt.x(),pnt.y());
+// debug("%i %i",pnt.x(),pnt.y());
+ p.translate(-pnt.x(),-pnt.y());
+ KviPixmapUtils::drawPixmapWithPainter(&p,pix,KVI_OPTION_UINT(KviOption_uintTreeTaskBarPixmapAlign),QRect(pnt.x(),pnt.y(),width,height()),listView()->width(),listView()->height());
+ p.translate(pnt.x(),pnt.y());
+ }
+ } else {
+ p.fillRect(0,0,width,height(),
+ QColor(KVI_OPTION_COLOR(KviOption_colorTreeTaskBarBackground).red()+m_iRedDiff*m_iStepNumber,
+ KVI_OPTION_COLOR(KviOption_colorTreeTaskBarBackground).green()+m_iGreenDiff*m_iStepNumber,
+ KVI_OPTION_COLOR(KviOption_colorTreeTaskBarBackground).blue()+m_iBlueDiff*m_iStepNumber
+ )
+ );
+
+ }
+ }
+
+ int h = height();
+ int im = listView()->itemMargin();
+ int yPixmap = (h - 16) >> 1;
+
+ QString szText;
+
+ QRect cRect(im + 3,0,width - (im << 1),height());
+
+ switch(m_pWindow->type())
+ {
+ case KVI_WINDOW_TYPE_CONSOLE:
+ {
+ if(KVI_OPTION_BOOL(KviOption_boolUseTaskBarIrcContextIndicator))
+ {
+ QColor base = cg.background();
+ QColor cntx = KVI_OPTION_ICCOLOR(m_pWindow->console()->ircContextId() % KVI_NUM_ICCOLOR_OPTIONS);
+ base.setRgb((base.red() + cntx.red()) >> 1,(base.green() + cntx.green()) >> 1,
+ (base.blue() + cntx.blue()) >> 1);
+ p.fillRect(im + 2,yPixmap + 1,14,15,base);
+ //draw_frame_helper(&p,im + 1,yPixmap,im + 15,yPixmap + 15,base.light(180),base.dark());
+ if(KVI_OPTION_BOOL(KviOption_boolUseTaskBarIcons))
+ {
+ p.drawPixmap(im + 20,yPixmap,*(m_pWindow->myIconPtr()));
+ cRect.setLeft(cRect.left() + 37);
+ } else {
+ cRect.setLeft(cRect.left() + 20);
+ }
+ } else {
+ if(KVI_OPTION_BOOL(KviOption_boolUseTaskBarIcons))
+ {
+ p.drawPixmap(im,yPixmap,*(m_pWindow->myIconPtr()));
+ cRect.setLeft(cRect.left() + 17);
+ }
+ }
+ QFont f = QFont();
+ f.setBold(true);
+ p.setFont(f);
+ KviTaskBarBase::getTextForConsole(szText,(KviConsole *)m_pWindow);
+ }
+ break;
+ case KVI_WINDOW_TYPE_CHANNEL:
+ case KVI_WINDOW_TYPE_DEADCHANNEL:
+ szText = ((KviChannel *)m_pWindow)->nameWithUserFlag();
+ if(KVI_OPTION_BOOL(KviOption_boolUseTaskBarIcons))
+ {
+ p.drawPixmap(im,yPixmap,*(m_pWindow->myIconPtr()));
+ cRect.setLeft(cRect.left() + 17);
+ }
+ break;
+ case KVI_WINDOW_TYPE_QUERY:
+ case KVI_WINDOW_TYPE_DEADQUERY:
+ szText = m_pWindow->windowName();
+ if(KVI_OPTION_BOOL(KviOption_boolUseTaskBarIcons))
+ {
+ p.drawPixmap(im,yPixmap,*(m_pWindow->myIconPtr()));
+ cRect.setLeft(cRect.left() + 17);
+ }
+ break;
+ default:
+ szText = m_pWindow->plainTextCaption();
+ if(KVI_OPTION_BOOL(KviOption_boolUseTaskBarIcons))
+ {
+ p.drawPixmap(im,yPixmap,*(m_pWindow->myIconPtr()));
+ cRect.setLeft(cRect.left() + 17);
+ }
+ break;
+ }
+
+ if(KVI_OPTION_BOOL(KviOption_boolUseTaskBarActivityMeter))
+ {
+ unsigned int uActivityValue;
+ unsigned int uActivityTemperature;
+ if(m_pWindow->activityMeter(&uActivityValue,&uActivityTemperature))
+ {
+ p.drawPixmap(cRect.left(),yPixmap,*g_pActivityMeterPixmap,uActivityValue * 5,uActivityTemperature * 16,5,16);
+ cRect.setLeft(cRect.left() + 7);
+ }
+ }
+
+ if(m_iProgress >= 0)
+ {
+ // paint the progress bar
+ int wdth = (m_iProgress * cRect.width()) / 100;
+ p.fillRect(cRect.x(),cRect.y(),wdth,cRect.height(),KVI_OPTION_COLOR(KviOption_colorTreeTaskBarProgress));
+ }
+
+ if(isSelected())
+ {
+ p.setPen(KVI_OPTION_COLOR(KviOption_colorTreeTaskBarActiveForeground));
+ } else {
+ int iLevel;
+ switch(m_iHighlightLevel)
+ {
+ case 0: iLevel = KviOption_colorTreeTaskBarForeground; break;
+ case 1: iLevel = KviOption_colorTreeTaskBarHighlight1Foreground; break;
+ case 2: iLevel = KviOption_colorTreeTaskBarHighlight2Foreground; break;
+ case 3: iLevel = KviOption_colorTreeTaskBarHighlight3Foreground; break;
+ case 4: iLevel = KviOption_colorTreeTaskBarHighlight4Foreground; break;
+ default: iLevel = KviOption_colorTreeTaskBarHighlight5Foreground; break;
+ }
+ p.setPen(
+ QColor(
+ calculateColor(KVI_OPTION_COLOR(iLevel).red(),KVI_OPTION_COLOR(KviOption_colorTreeTaskBarActiveForeground).red()),
+ calculateColor(KVI_OPTION_COLOR(iLevel).green(),KVI_OPTION_COLOR(KviOption_colorTreeTaskBarActiveForeground).green()),
+ calculateColor(KVI_OPTION_COLOR(iLevel).blue(),KVI_OPTION_COLOR(KviOption_colorTreeTaskBarActiveForeground).blue())
+ )
+ );
+ }
+
+ if(m_pWindow->isMinimized())
+ {
+ QString tmp = QChar('(');
+ tmp += szText;
+ tmp += QChar(')');
+ p.drawText(cRect,Qt::AlignLeft | Qt::AlignVCenter,tmp,-1,0);
+ } else {
+ p.drawText(cRect,Qt::AlignLeft | Qt::AlignVCenter,szText,-1,0);
+ }
+
+ painter->drawPixmap(0,0,*pMemBuffer,0,0,width,height());
+ //bitBlt(painter->pixmap(),0,0,pMemBuffer,0,0,width,height(),Qt::CopyROP,false);
+}
+
+QString KviTreeTaskBarItem::key(int,bool) const
+{
+ QString ret = m_pWindow->typeString();
+ ret.append(m_pWindow->windowName());
+ return ret;
+}
+
+void KviTreeTaskBarItem::timerShot()
+{
+ if(m_bIncreasing)
+ m_iStepNumber++;
+ else
+ m_iStepNumber--;
+
+ if((m_iStepNumber>=KVI_NUM_STEPS) && m_bIncreasing)
+ {
+ m_pAnimTimer->stop();
+ m_iStepNumber=KVI_NUM_STEPS; //make shure, that we cannot get out of range
+ } else if((m_iStepNumber<=0) && !m_bIncreasing) {
+ m_pAnimTimer->stop();
+ m_iStepNumber=0; //make shure, that we cannot get out of range
+ }
+ repaint();
+}
+
+void KviTreeTaskBarItem::mouseEnter()
+{
+ if(KVI_OPTION_BOOL(KviOption_boolEnableVisualEffects))
+ {
+ m_bIncreasing=true;
+ if(!m_pAnimTimer->isActive()) m_pAnimTimer->start(KVI_TIMER_DELAY);
+ }
+}
+
+void KviTreeTaskBarItem::mouseLeave()
+{
+ if(KVI_OPTION_BOOL(KviOption_boolEnableVisualEffects))
+ {
+ m_bIncreasing=false;
+ if(!m_pAnimTimer->isActive()) m_pAnimTimer->start(KVI_TIMER_DELAY);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// KviTreeTaskBarListView
+//
+
+
+KviTreeTaskBarListView::KviTreeTaskBarListView(QWidget * par)
+: KviTalListView(par)
+{
+ //setSorting(0);
+ setShowSortIndicator(true);
+ setItemMargin(2);
+ setFrameShape(NoFrame);
+ viewport()->setMouseTracking(TRUE);
+ m_pPrevItem=0;
+ setHScrollBarMode(KviTalListView::AlwaysOff);
+}
+
+KviTreeTaskBarListView::~KviTreeTaskBarListView()
+{
+}
+
+void KviTreeTaskBarListView::contentsMouseMoveEvent ( QMouseEvent * e )
+{
+ if(!e) return;
+ KviTreeTaskBarItem* pCur=(KviTreeTaskBarItem*)(itemAt(contentsToViewport(e->pos())));
+ if(pCur!=m_pPrevItem)
+ {
+ if(m_pPrevItem)m_pPrevItem->mouseLeave();
+ if(pCur) pCur->mouseEnter();
+ setCursor(Qt::PointingHandCursor);
+ m_pPrevItem=pCur;
+ } else if(!pCur) {
+ setCursor(Qt::ArrowCursor);
+ }
+}
+void KviTreeTaskBarListView::leaveEvent(QEvent *)
+{
+ if(m_pPrevItem) m_pPrevItem->mouseLeave();
+ m_pPrevItem=0;
+ setCursor(Qt::ArrowCursor);
+}
+
+
+void KviTreeTaskBarListView::contentsMousePressEvent(QMouseEvent *e)
+{
+ KviTalListViewItem * it = (KviTalListViewItem *)itemAt(contentsToViewport(e->pos()));
+ if(it)
+ {
+ if(e->button() & Qt::LeftButton)emit leftMousePress(it);
+ else if(e->button() & Qt::RightButton)emit rightMousePress(it);
+ } else {
+ if(e->button() & Qt::RightButton)
+ {
+ KviTalPopupMenu* pPopup=new KviTalPopupMenu();
+ pPopup->insertItem(__tr2qs("Sort"),this,SLOT(sort()));
+ pPopup->insertItem(__tr2qs("Reverse Sort"),this,SLOT(reverseSort()));
+ pPopup->popup(QCursor::pos());
+ }
+ }
+}
+
+void KviTreeTaskBarListView::sort()
+{
+ setSorting(0,TRUE);
+}
+
+void KviTreeTaskBarListView::reverseSort()
+{
+ setSorting(0,FALSE);
+}
+
+void KviTreeTaskBarListView::resizeEvent(QResizeEvent *e)
+{
+ KviTalListView::resizeEvent(e);
+ setColumnWidth(0,viewport()->width());
+ resizeContents(viewport()->width(),contentsHeight());
+}
+
+//void KviTreeTaskBarListView::paintEmptyAreaInternal(QPainter * p,const QRect &viewportRect,const QRect &painterRect)
+//{
+//
+//}
+
+void KviTreeTaskBarListView::paintEmptyArea(QPainter * p,const QRect &rct)
+{
+ SET_ANTI_ALIASING(*p);
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ if(g_pShadedChildGlobalDesktopBackground)
+ {
+ QPoint pnt = viewport()->mapToGlobal(QPoint(rct.x() + int(p->worldMatrix().dx()),rct.y() + int(p->worldMatrix().dy())));
+ p->drawTiledPixmap(rct.x(),rct.y(),rct.width(),rct.height(),*g_pShadedChildGlobalDesktopBackground,pnt.x(),pnt.y());
+ } else {
+#endif
+ p->fillRect(rct.x(),rct.y(),rct.width(),rct.height(),KVI_OPTION_COLOR(KviOption_colorTreeTaskBarBackground));
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ }
+#endif
+
+ QPixmap * pix = KVI_OPTION_PIXMAP(KviOption_pixmapTreeTaskBarBackground).pixmap();
+ if(pix)
+ {
+ QPoint pnt = viewportToContents(QPoint(rct.x() + int(p->worldMatrix().dx()),rct.y() + int(p->worldMatrix().dy())));
+ //p->drawTiledPixmap(rct.x(),rct.y(),rct.width(),rct.height(),*pix,pnt.x(),pnt.y());
+ KviPixmapUtils::drawPixmapWithPainter(p,pix,KVI_OPTION_UINT(KviOption_uintTreeTaskBarPixmapAlign),rct,viewport()->width(),viewport()->height(),pnt.x(),pnt.y());
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// KviTreeTaskBar
+//
+
+KviTreeTaskBar::KviTreeTaskBar()
+: KviTaskBarBase()
+{
+ m_pListView = new KviTreeTaskBarListView(this);
+ m_pListView->addColumn(__tr2qs("Window List"),135);
+ m_pListView->setAllColumnsShowFocus(true);
+ m_pListView->setMultiSelection(false);
+
+#ifdef COMPILE_USE_QT4
+ setWidget(m_pListView);
+#else //!COMPILE_USE_QT4
+ setStretchableWidget(m_pListView);
+
+ setVerticalStretchable(true);
+ setHorizontalStretchable(true);
+#endif //!COMPILE_USE_QT4
+
+
+ // FIXME: this code is useless ?
+ if(KVI_OPTION_UINT(KviOption_uintTreeTaskBarMinimumWidth) < 48)
+ KVI_OPTION_UINT(KviOption_uintTreeTaskBarMinimumWidth) = 48;
+ int iMin = m_pListView->minimumSize().width() + 4;
+ if(((unsigned int)iMin) < KVI_OPTION_UINT(KviOption_uintTreeTaskBarMinimumWidth))
+ iMin = KVI_OPTION_UINT(KviOption_uintTreeTaskBarMinimumWidth);
+ setMinimumWidth(iMin);
+
+ // this is surely useful :)
+ m_pListView->setMinimumWidth(4);
+
+ //setMaximumWidth(KVI_OPTION_UINT(KviOption_uintTreeTaskBarMaximumWidth));
+ //m_pListView->setMinimumWidth(KVI_OPTION_UINT(KviOption_uintTreeTaskBarMinimumWidth));
+ //m_pListView->setMaximumWidth(KVI_OPTION_UINT(KviOption_uintTreeTaskBarMaximumWidth));
+#ifdef COMPILE_USE_QT4
+ m_pListView->setFocusPolicy(Qt::NoFocus);
+#else
+ m_pListView->setFocusPolicy(QWidget::NoFocus);
+#endif
+ m_pListView->setStaticBackground(true);
+#ifdef COMPILE_USE_QT4
+ m_pListView->viewport()->setAutoFillBackground(false);
+#else
+ m_pListView->viewport()->setBackgroundMode(QWidget::NoBackground);
+#endif
+ if(!KVI_OPTION_BOOL(KviOption_boolShowTreeTaskbarHeader))
+ {
+ m_pListView->header()->hide();
+ }
+
+ m_pListView->header()->setResizeEnabled(true);
+
+#ifdef COMPILE_USE_QT4
+ setMaximumWidth(600);
+#endif
+
+ m_pListView->viewport()->installEventFilter(this);
+
+#if QT_VERSION >= 300
+#ifndef COMPILE_USE_QT4
+ setResizeEnabled(true);
+#endif
+#endif
+
+ m_pToolTip = new KviDynamicToolTip(m_pListView->viewport(),"tree_taskbar_tooltip");
+ connect(m_pToolTip,SIGNAL(tipRequest(KviDynamicToolTip *,const QPoint &)),this,SLOT(tipRequest(KviDynamicToolTip *,const QPoint &)));
+}
+
+KviTreeTaskBar::~KviTreeTaskBar()
+{
+}
+
+void KviTreeTaskBar::updatePseudoTransparency()
+{
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ m_pListView->viewport()->update();
+#endif
+}
+
+void KviTreeTaskBar::moveEvent(QMoveEvent *)
+{
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ updatePseudoTransparency();
+#endif
+}
+
+void KviTreeTaskBar::tipRequest(KviDynamicToolTip *,const QPoint &pnt)
+{
+ if(KVI_OPTION_BOOL(KviOption_boolShowTaskBarToolTips))
+ {
+ KviTalListViewItem * it = (KviTalListViewItem *)m_pListView->itemAt(pnt);
+ if(it)
+ {
+ QString szText;
+ ((KviTreeTaskBarItem *)it)->m_pWindow->getTaskBarTipText(szText);
+ m_pToolTip->tip(m_pListView->itemRect(it),szText);
+ }
+ }
+}
+
+bool KviTreeTaskBar::eventFilter(QObject * o,QEvent *e)
+{
+ if(o == m_pListView->viewport())
+ {
+ if(e->type() == QEvent::MouseButtonPress)
+ {
+ QMouseEvent * ev = (QMouseEvent *)e;
+ KviTreeTaskBarItem * it = (KviTreeTaskBarItem *)m_pListView->itemAt(ev->pos());
+ if(!it)return false;
+ KviWindow * wnd = it->kviWindow();
+ if(wnd)
+ {
+ if(ev->button() & Qt::LeftButton)
+ {
+ if(ev->state() & Qt::ShiftButton)
+ {
+ wnd->delayedClose();
+ } else {
+ if((g_pActiveWindow != wnd) || (wnd->isMinimized()))g_pFrame->setActiveWindow(wnd);
+ else wnd->minimize();
+ }
+ } else {
+ wnd->contextPopup();
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+
+KviTaskBarItem * KviTreeTaskBar::addItem(KviWindow * wnd)
+{
+ // complex insertion task
+ if(wnd->console())
+ {
+ if(wnd->type() != KVI_WINDOW_TYPE_CONSOLE)
+ {
+ ((KviTreeTaskBarItem *)(wnd->console()->m_pTaskBarItem))->setOpen(true);
+ return new KviTreeTaskBarItem(((KviTreeTaskBarItem *)(wnd->console()->m_pTaskBarItem)),wnd);
+ }
+ }
+
+ // console , or a window that has no irc context
+ return new KviTreeTaskBarItem(m_pListView,wnd);
+}
+
+bool KviTreeTaskBar::removeItem(KviTaskBarItem * it)
+{
+ delete (KviTreeTaskBarItem *)it;
+ return true;
+}
+
+void KviTreeTaskBar::setActiveItem(KviTaskBarItem * it)
+{
+ if(it)
+ {
+ KviTreeTaskBarItem * cur = (KviTreeTaskBarItem *)m_pListView->currentItem();
+ if(cur && (cur != (KviTreeTaskBarItem *)it))
+ {
+ cur->setActive(false);
+ }
+ if(((KviTreeTaskBarItem *)it)->parent())
+ {
+ if(!((KviTreeTaskBarItem *)it)->parent()->isOpen())((KviTreeTaskBarItem *)it)->parent()->setOpen(true);
+ }
+ ((KviTreeTaskBarItem *)it)->setActive(true);
+ m_pListView->setSelected(((KviTreeTaskBarItem *)it),true); // this MUST go after it->setActive()
+ if(g_pFrame->dockExtension())g_pFrame->dockExtension()->refresh();
+ }
+}
+
+void KviTreeTaskBar::updateActivityMeter()
+{
+ if(KVI_OPTION_BOOL(KviOption_boolUseTaskBarActivityMeter))
+ {
+ m_pListView->viewport()->update();
+ }
+}
+
+KviTaskBarItem * KviTreeTaskBar::firstItem()
+{
+ m_pCurrentItem = (KviTreeTaskBarItem *)m_pListView->firstChild();
+ return m_pCurrentItem;
+}
+
+KviTaskBarItem * KviTreeTaskBar::nextItem()
+{
+ if(!m_pCurrentItem)return 0;
+
+ if(m_pCurrentItem->firstChild())
+ {
+ m_pCurrentItem = (KviTreeTaskBarItem *)m_pCurrentItem->firstChild();
+ } else {
+ // this item has no children: try the next sibling
+ if(m_pCurrentItem->nextSibling())
+ {
+ m_pCurrentItem = (KviTreeTaskBarItem *)m_pCurrentItem->nextSibling();
+ } else {
+ if(m_pCurrentItem->parent())
+ {
+ // child with not siblings : try the sibling of the parent
+ m_pCurrentItem = (KviTreeTaskBarItem *)m_pCurrentItem->parent()->nextSibling();
+ } else {
+ m_pCurrentItem = 0; // toplevel with no siblings
+ }
+ }
+ }
+ return m_pCurrentItem;
+}
+
+KviTaskBarItem * KviTreeTaskBar::prevItem()
+{
+ KviTreeTaskBarItem * it;
+
+ if(!m_pCurrentItem)return 0;
+
+ if(m_pCurrentItem->parent())
+ {
+ // a child item
+ it = (KviTreeTaskBarItem *)m_pCurrentItem->parent()->firstChild();
+
+ while(it)
+ {
+ if(((KviTreeTaskBarItem *)it->nextSibling()) == m_pCurrentItem)break;
+ else it = ((KviTreeTaskBarItem *)(it->nextSibling()));
+ }
+ if(!it)
+ {
+ it = (KviTreeTaskBarItem *)m_pCurrentItem->parent();
+ }
+
+ } else {
+ // a toplevel one
+ it = (KviTreeTaskBarItem *)m_pListView->firstChild();
+ while(it)
+ {
+ if(((KviTreeTaskBarItem *)it->nextSibling()) == m_pCurrentItem)break;
+ else it = ((KviTreeTaskBarItem *)(it->nextSibling()));
+ }
+ if(it)
+ {
+ if(it->firstChild())
+ {
+ it = ((KviTreeTaskBarItem *)(it->firstChild()));
+ while(it->nextSibling())it = ((KviTreeTaskBarItem *)(it->nextSibling()));
+ }
+ }
+ }
+
+ m_pCurrentItem = it;
+ return it;
+}
+
+KviTaskBarItem * KviTreeTaskBar::lastItem()
+{
+ // first find last toplevel item
+ m_pCurrentItem = (KviTreeTaskBarItem *)m_pListView->firstChild();
+ for(;;)
+ {
+ if(m_pCurrentItem->nextSibling())
+ {
+ m_pCurrentItem = (KviTreeTaskBarItem *)m_pCurrentItem->nextSibling();
+ } else if(m_pCurrentItem->firstChild())
+ {
+ m_pCurrentItem = (KviTreeTaskBarItem *)m_pCurrentItem->firstChild();
+ } else return m_pCurrentItem;
+ }
+ return 0;
+}
+
+bool KviTreeTaskBar::setIterationPointer(KviTaskBarItem * it)
+{
+ m_pCurrentItem = (KviTreeTaskBarItem *)it;
+ if(!it)return true;
+ if(((KviTalListView *)m_pListView) == ((KviTreeTaskBarItem *)it)->listView())return true;
+ m_pCurrentItem = 0;
+ return false;
+}
+
+void KviTreeTaskBar::applyOptions()
+{
+ m_pListView->update();
+ if(!KVI_OPTION_BOOL(KviOption_boolShowTreeTaskbarHeader))
+ {
+ m_pListView->header()->hide();
+ } else {
+ m_pListView->header()->show();
+ }
+}
+
+#include "kvi_taskbar.moc"
diff --git a/src/kvirc/ui/kvi_taskbar.h b/src/kvirc/ui/kvi_taskbar.h
new file mode 100644
index 00000000..300e0f68
--- /dev/null
+++ b/src/kvirc/ui/kvi_taskbar.h
@@ -0,0 +1,312 @@
+#ifndef _KVI_TASKBAR_H_
+#define _KVI_TASKBAR_H_
+//=============================================================================
+//
+// File : kvi_taskbar.h
+// Creation date : Thu Jan 7 1999 03:56:50 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#include "kvi_pointerlist.h"
+#include <qframe.h>
+#include "kvi_tal_tooltip.h"
+#include "kvi_tal_listview.h"
+#include <qpushbutton.h>
+
+
+
+class KviWindow;
+class KviFrame;
+class QPixmap;
+class KviDynamicToolTip;
+class KviConsole;
+
+//
+// KviTaskBarItem
+//
+// The base class for the taskBar items
+// this is the only interface to an item visible to external classes
+//
+
+class KVIRC_API KviTaskBarItem
+{
+public:
+ KviTaskBarItem(KviWindow * wnd);
+ virtual ~KviTaskBarItem();
+protected:
+ KviWindow * m_pWindow;
+ int m_iHighlightLevel;
+ int m_iProgress;
+public:
+ KviWindow * kviWindow(){ return m_pWindow; };
+ virtual void captionChanged(){};
+ virtual void highlight(int iLevel = 1){};
+ virtual void setProgress(int progress){};
+ virtual bool active(){ return false; };
+ virtual void unhighlight(){};
+ int progress(){ return m_iProgress; };
+ int highlightLevel(){ return m_iHighlightLevel; };
+};
+
+//
+// KviTaskBarBase
+//
+// The base class for the taskbar implementations
+// This is the basic interface that all the external classes should see
+//
+
+// Please note that Qt3 moc skips the *_SKIP_BEGIN -> *_SKIP_END blocks
+// while the Qt4 moc skips the Q_MOC_RUN ifdef block.. so...
+
+// Qt4 version
+
+// If you get failures (undefined references) in some non-autotools based
+// build system that uses Qt4 then you must add the -DCOMPILE_USE_QT4
+// commandline parameter to moc (at leat) when parsing this file.
+
+// MOC_SKIP_BEGIN
+#ifdef COMPILE_USE_QT4
+
+#include <QDockWidget>
+
+class KVIRC_API KviTaskBarBase : public QDockWidget
+{
+ Q_OBJECT
+#endif //COMPILE_USE_QT4
+// MOC_SKIP_END
+
+// Qt3 version
+#ifndef Q_MOC_RUN
+#ifndef COMPILE_USE_QT4
+
+#include "kvi_toolbar.h"
+
+class KVIRC_API KviTaskBarBase : public KviToolBar
+{
+ Q_OBJECT
+#endif
+#endif
+
+public:
+ KviTaskBarBase();
+ virtual ~KviTaskBarBase();
+protected:
+ KviFrame * m_pFrm;
+ QTimer * m_pActivityMeterTimer;
+public:
+ virtual KviTaskBarItem * addItem(KviWindow *){ return 0; };
+ virtual bool removeItem(KviTaskBarItem *){ return false; };
+ virtual void setActiveItem(KviTaskBarItem *){};
+ virtual KviTaskBarItem * firstItem(){ return 0; };
+ virtual KviTaskBarItem * lastItem(void) { return 0; }
+ virtual KviTaskBarItem * nextItem(){ return 0; };
+ virtual KviTaskBarItem * prevItem(void) { return 0; }
+ virtual KviTaskBarItem * item(int number);
+ virtual bool setIterationPointer(KviTaskBarItem * it){ return false; };
+ virtual void switchWindow(bool bNext,bool bInContextOnly);
+ virtual void updatePseudoTransparency(){};
+ virtual void applyOptions(){};
+ static void getTextForConsole(QString &szText,KviConsole * pConsole);
+protected slots:
+ virtual void updateActivityMeter();
+};
+
+//
+// Implementation details: the following classes should be
+// never used directly (with just the exception of KviFrame
+// that creates the taskbar)
+//
+
+class KviClassicTaskBar;
+
+class KVIRC_API KviTaskBarButton : public QPushButton , KviTaskBarItem
+{
+ friend class KviClassicTaskBar;
+ Q_OBJECT
+public:
+ KviTaskBarButton(QWidget * par,KviWindow * wnd,const char * name);
+ ~KviTaskBarButton();
+protected:
+ bool m_bActive;
+ KviDynamicToolTip * m_pTip;
+protected:
+ virtual void mousePressEvent(QMouseEvent *e);
+#if QT_VERSION >= 300
+ virtual void contextMenuEvent(QContextMenuEvent *e);
+#endif
+ virtual void drawButtonLabel(QPainter *p);
+#ifdef COMPILE_USE_QT4
+ virtual void paintEvent(QPaintEvent * e);
+#endif
+public:
+ virtual bool active(){ return m_bActive; };
+ virtual void highlight(int iLevel = 1);
+ virtual void unhighlight();
+ virtual void setProgress(int progress);
+ virtual void captionChanged();
+protected:
+ void setActive(bool bActive);
+protected slots:
+ void tipRequest(KviDynamicToolTip *tip,const QPoint &pnt);
+};
+
+
+class KVIRC_API KviClassicTaskBar : public KviTaskBarBase
+{
+ Q_OBJECT
+public:
+ KviClassicTaskBar();
+ ~KviClassicTaskBar();
+protected:
+ KviPointerList<KviTaskBarButton> * m_pButtonList;
+ int m_iButtonHeight;
+ QWidget * m_pBase;
+protected:
+ void calcButtonHeight();
+ void doLayout(); // called by KviFrame to adjust a bug on WIndows
+ void insertButton(KviTaskBarButton * b);
+public:
+// virtual void fontChange(const QFont & old);
+ virtual void resizeEvent(QResizeEvent *e);
+public:
+ virtual KviTaskBarItem * addItem(KviWindow *);
+ virtual bool removeItem(KviTaskBarItem *);
+ virtual void setActiveItem(KviTaskBarItem *);
+ virtual KviTaskBarItem * firstItem();
+ virtual KviTaskBarItem * lastItem(void);
+ virtual KviTaskBarItem * nextItem();
+ virtual KviTaskBarItem * prevItem(void);
+ virtual bool setIterationPointer(KviTaskBarItem * it);
+ virtual void updateActivityMeter();
+ virtual void applyOptions();
+protected slots:
+ void orientationChangedSlot(Qt::Orientation o);
+};
+
+class KviTreeTaskBar;
+class KviTreeTaskBarItemInternal;
+
+class KVIRC_API KviTreeTaskBarItem : public KviTalListViewItem , public KviTaskBarItem
+{
+ friend class KviTreeTaskBar;
+ friend class KviTreeTaskBarListView;
+ friend class KviTreeTaskBarItemInternal;
+public:
+ KviTreeTaskBarItem(KviTalListView * par,KviWindow * wnd);
+ KviTreeTaskBarItem(KviTreeTaskBarItem * par,KviWindow * wnd);
+ ~KviTreeTaskBarItem();
+protected:
+ int m_iStepNumber;
+ bool m_bIncreasing;
+ QTimer* m_pAnimTimer;
+ KviTreeTaskBarItemInternal *m_pInternal;
+ int m_iRedDiff;
+ int m_iGreenDiff;
+ int m_iBlueDiff;
+public:
+ virtual QString key(int column,bool) const;
+ virtual void paintCell(QPainter *p,const QColorGroup &cg,int column,int width,int alignment);
+#ifdef COMPILE_USE_QT4
+ virtual void paintBranches(QPainter *p,const QColorGroup &cg,int w,int y,int h);
+#else
+ virtual void paintBranches(QPainter *p,const QColorGroup &cg,int w,int y,int h,GUIStyle s);
+#endif
+ virtual void captionChanged();
+ virtual void highlight(int iLevel = 1);
+ virtual void unhighlight();
+ virtual void setProgress(int progress);
+ virtual bool active(){ return isSelected(); };
+ virtual void applyOptions();
+protected:
+ void setActive(bool bActive);
+ void mouseEnter();
+ void mouseLeave();
+ void timerShot();
+ int calculateColor(int col1,int col2);
+};
+
+class KviTreeTaskBarItemInternal : public QObject
+{
+ Q_OBJECT
+public:
+ KviTreeTaskBarItemInternal(KviTreeTaskBarItem* pItem):m_pItem(pItem) {};
+ ~KviTreeTaskBarItemInternal() {};
+protected:
+ KviTreeTaskBarItem* m_pItem;
+public slots:
+ void timerShot() { m_pItem->timerShot();};
+};
+
+class KVIRC_API KviTreeTaskBarListView : public KviTalListView
+{
+ friend class KviTreeTaskBarItem;
+ Q_OBJECT
+ KviTreeTaskBarItem* m_pPrevItem;
+public:
+ KviTreeTaskBarListView(QWidget * par);
+ ~KviTreeTaskBarListView();
+protected:
+ virtual void contentsMousePressEvent(QMouseEvent *e);
+ virtual void paintEmptyArea(QPainter * p,const QRect &rct);
+ virtual void resizeEvent(QResizeEvent *e);
+ virtual void contentsMouseMoveEvent ( QMouseEvent * e );
+ virtual void leaveEvent(QEvent *);
+signals:
+ void leftMousePress(KviTalListViewItem * it);
+ void rightMousePress(KviTalListViewItem * it);
+public slots:
+ void sort();
+ void reverseSort();
+};
+
+
+class KVIRC_API KviTreeTaskBar : public KviTaskBarBase
+{
+ Q_OBJECT
+public:
+ KviTreeTaskBar();
+ ~KviTreeTaskBar();
+private:
+ KviTreeTaskBarListView * m_pListView;
+ KviTreeTaskBarItem * m_pCurrentItem;
+ KviDynamicToolTip * m_pToolTip;
+public:
+ virtual KviTaskBarItem * addItem(KviWindow *);
+ virtual bool removeItem(KviTaskBarItem *);
+ virtual void setActiveItem(KviTaskBarItem *);
+ virtual KviTaskBarItem * firstItem();
+ virtual KviTaskBarItem * nextItem(void);
+ virtual KviTaskBarItem * lastItem();
+ virtual KviTaskBarItem * prevItem(void);
+ virtual bool setIterationPointer(KviTaskBarItem * it);
+ virtual void updatePseudoTransparency();
+ virtual bool eventFilter(QObject * o,QEvent *e);
+ virtual void updateActivityMeter();
+ virtual void applyOptions();
+protected:
+ virtual void moveEvent(QMoveEvent *);
+protected slots:
+ void tipRequest(KviDynamicToolTip *tip,const QPoint &pnt);
+};
+
+
+#endif //_KVI_TASKBAR_H_
diff --git a/src/kvirc/ui/kvi_texticonwin.cpp b/src/kvirc/ui/kvi_texticonwin.cpp
new file mode 100644
index 00000000..bd480785
--- /dev/null
+++ b/src/kvirc/ui/kvi_texticonwin.cpp
@@ -0,0 +1,283 @@
+//=============================================================================
+//
+// File : kvi_texticonwin.cpp
+// Creation date : Fri May 17 2002 02:35:20 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_texticonwin.h"
+#include "kvi_texticonmanager.h"
+#include "kvi_app.h"
+#include "kvi_options.h"
+#include "kvi_input.h"
+#include "kvi_topicw.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_iconmanager.h"
+
+#include <qnamespace.h>
+#include <qlineedit.h>
+#include <ctype.h>
+#ifdef COMPILE_USE_QT4
+ #include <qevent.h>
+#endif
+
+KviTextIconWindow::KviTextIconWindow()
+#ifdef COMPILE_USE_QT4
+: KviTalIconView(0,Qt::Popup)
+#else
+: KviTalIconView(0,Qt::WType_Popup)
+#endif
+{
+ m_iTimerId = -1;
+ setGridX ( 40 );
+ setFixedSize(KVI_TEXTICON_WIN_WIDTH,KVI_TEXTICON_WIN_HEIGHT);
+ m_pOwner = 0;
+ fill();
+ connect(g_pTextIconManager,SIGNAL(changed()),this,SLOT(fill()));
+ connect(this,SIGNAL(doubleClicked( KviTalIconViewItem * )),this,SLOT(itemSelected(KviTalIconViewItem *)));
+ connect(this,SIGNAL(returnPressed ( KviTalIconViewItem * ) ),this,SLOT(itemSelected(KviTalIconViewItem *)));
+ m_bAltMode = false;
+ setWordWrapIconText(true);
+}
+
+KviTextIconWindow::~KviTextIconWindow()
+{
+ if(m_iTimerId != -1)
+ {
+ killTimer(m_iTimerId);
+ m_iTimerId = -1;
+ }
+// killTimers();
+// if(m_pOwner)m_pOwner->setFocus();
+}
+
+void KviTextIconWindow::fill()
+{
+ clear();
+ KviPointerHashTable<QString,KviTextIcon> * d = g_pTextIconManager->textIconDict();
+ KviPointerHashTableIterator<QString,KviTextIcon> it(*d);
+ while(KviTextIcon * i = it.current())
+ {
+ QPixmap *pix = i->pixmap();
+ if(pix)insertItem(new KviTalIconViewItem(this,it.currentKey(),*pix));
+ ++it;
+ }
+ sort();
+ setCurrentItem(0);
+}
+
+void KviTextIconWindow::popup(QWidget *owner,bool bAltMode)
+{
+ if(m_pOwner)disconnect(m_pOwner,SIGNAL(destroyed()),this,SLOT(ownerDead()));
+ m_pOwner = owner;
+ m_szTypedSeq = "";
+ m_bAltMode = bAltMode;
+ connect(m_pOwner,SIGNAL(destroyed()),this,SLOT(ownerDead()));
+ show();
+}
+
+bool KviTextIconWindow::findTypedSeq()
+{
+ int cnt = count();
+ int max = 0;
+ KviTalIconViewItem *mit = 0;
+ bool bFullMax = false;
+ KviTalIconViewItem *item;
+ for ( item = (KviTalIconViewItem *)firstItem(); item; item = (KviTalIconViewItem *)item->nextItem() )
+ {
+ QString szIt = item->text();
+ int j;
+ for(j=0;j<((int)(szIt.length()));j++)
+ {
+ if(szIt[j].lower() != m_szTypedSeq[j].lower())break;
+ }
+ if(j < max)
+ {
+ goto got_mit;
+ } else {
+ if(j >= max)
+ {
+ bFullMax = (j == ((int)(szIt.length())));
+ max = j;
+ mit = item;
+ }
+ }
+ }
+got_mit:
+ setCurrentItem(mit);
+ m_szCurFullSeq = mit->text();
+ return bFullMax;
+}
+
+void KviTextIconWindow::keyPressEvent(QKeyEvent *e)
+{
+ switch(e->key())
+ {
+ case Qt::Key_Up:
+ case Qt::Key_Down:
+ case Qt::Key_Left:
+ case Qt::Key_Right:
+ case Qt::Key_PageUp:
+ case Qt::Key_PageDown:
+ case Qt::Key_Return:
+ KviTalIconView::keyPressEvent(e);
+ return;
+ break;
+ case Qt::Key_Escape:
+ doHide();
+ return;
+ break;
+ case Qt::Key_Backspace:
+ if(!m_szTypedSeq.isEmpty())
+ {
+ m_szTypedSeq.remove(m_szTypedSeq.length() - 1,1);
+ findTypedSeq();
+ } else {
+ doHide();
+ if(m_pOwner)g_pApp->sendEvent(m_pOwner,e);
+ }
+ return;
+ break;
+ case Qt::Key_Space:
+ doHide();
+ if(findTypedSeq())
+ {
+ QString szItem = m_szTypedSeq;
+ szItem.append(' ');
+ if(m_pOwner)
+ {
+ if(m_pOwner->inherits("KviInputEditor"))
+ ((KviInputEditor *)m_pOwner)->insertText(szItem);
+ else if(m_pOwner->inherits("KviInput"))
+ ((KviInput *)m_pOwner)->insertText(szItem);
+ else if(m_pOwner->inherits("QLineEdit"))
+ {
+ QString tmp = ((QLineEdit *)m_pOwner)->text();
+ tmp.insert(((QLineEdit *)m_pOwner)->cursorPosition(),szItem);
+ ((QLineEdit *)m_pOwner)->setText(tmp);
+ ((QLineEdit *)m_pOwner)->setCursorPosition(((QLineEdit *)m_pOwner)->cursorPosition() + szItem.length());
+ }
+ }
+ } else {
+ if(m_pOwner)g_pApp->sendEvent(m_pOwner,e);
+ }
+ return;
+ break;
+ case Qt::Key_Tab:
+ doHide();
+ findTypedSeq();
+ QString szItem = m_szCurFullSeq;
+ szItem.append(' ');
+ if(m_bAltMode)szItem.prepend(KVI_TEXT_ICON);
+ if(m_pOwner->inherits("KviInputEditor"))
+ ((KviInputEditor *)m_pOwner)->insertText(szItem);
+ else if(m_pOwner->inherits("KviInput"))
+ ((KviInput *)m_pOwner)->insertText(szItem);
+ else if(m_pOwner->inherits("QLineEdit"))
+ {
+ QString tmp = ((QLineEdit *)m_pOwner)->text();
+ tmp.insert(((QLineEdit *)m_pOwner)->cursorPosition(),szItem);
+ ((QLineEdit *)m_pOwner)->setText(tmp);
+ ((QLineEdit *)m_pOwner)->setCursorPosition(((QLineEdit *)m_pOwner)->cursorPosition() + szItem.length());
+ }
+ return;
+ break;
+ }
+
+ int as = e->ascii();
+ if((as >= 'a' && as <= 'z') || (as >= 'A' && as <= 'Z') || (as >= '0' && as <= '9')
+ || (as == '?') || (as == '$') || (as == '.') || (as == ',') || (as == '!') || (as =='&'))
+ {
+ m_szTypedSeq.append((char)as);
+ findTypedSeq();
+ } else {
+ if(m_pOwner)g_pApp->sendEvent(m_pOwner,e);
+ }
+}
+
+void KviTextIconWindow::ownerDead()
+{
+ m_pOwner = 0;
+ doHide();
+}
+
+void KviTextIconWindow::show()
+{
+ m_iTimerId = startTimer(50000); //50 sec ...seems enough
+ QWidget::show();
+}
+
+void KviTextIconWindow::timerEvent(QTimerEvent *)
+{
+ doHide();
+}
+
+void KviTextIconWindow::doHide()
+{
+ if(m_iTimerId != -1)
+ {
+ killTimer(m_iTimerId);
+ m_iTimerId = -1;
+ }
+ hide();
+ if(m_pOwner)m_pOwner->setFocus();
+}
+
+void KviTextIconWindow::itemSelected(KviTalIconViewItem * item)
+{
+ if(item)
+ {
+// debug("%i %i %i %s",m_pOwner->inherits("KviInputEditor"),m_pOwner->inherits("KviInput"),m_pOwner->inherits("QLineEdit"),m_pOwner->className());
+ doHide();
+ QString szItem = item->text();
+ szItem.append(' ');
+ if(m_bAltMode)szItem.prepend(KVI_TEXT_ICON);
+ if(m_pOwner->inherits("KviInputEditor"))
+ ((KviInputEditor *)m_pOwner)->insertText(szItem);
+ else if(m_pOwner->inherits("KviInput"))
+ ((KviInput *)m_pOwner)->insertText(szItem);
+ else if(m_pOwner->inherits("QLineEdit"))
+ {
+ QString tmp = ((QLineEdit *)m_pOwner)->text();
+ tmp.insert(((QLineEdit *)m_pOwner)->cursorPosition(),szItem);
+ ((QLineEdit *)m_pOwner)->setText(tmp);
+ ((QLineEdit *)m_pOwner)->setCursorPosition(((QLineEdit *)m_pOwner)->cursorPosition() + szItem.length());
+ }
+ }
+}
+
+void KviTextIconWindow::mousePressEvent(QMouseEvent *e)
+{
+ if(e->pos().x() < 0)goto hideme;
+ if(e->pos().x() > width())goto hideme;
+ if(e->pos().y() < 0)goto hideme;
+ if(e->pos().y() > height())goto hideme;
+
+ KviTalIconView::mousePressEvent(e);
+ return;
+
+hideme:
+ doHide();
+}
+
+
+#include "kvi_texticonwin.moc"
diff --git a/src/kvirc/ui/kvi_texticonwin.h b/src/kvirc/ui/kvi_texticonwin.h
new file mode 100644
index 00000000..76a4a60e
--- /dev/null
+++ b/src/kvirc/ui/kvi_texticonwin.h
@@ -0,0 +1,64 @@
+#ifndef _KVI_TEXTICONWIN_H_
+#define _KVI_TEXTICONWIN_H_
+//=============================================================================
+//
+// File : kvi_texticonwin.h
+// Creation date : Fri May 17 2002 02:33:45 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_string.h"
+
+#include "kvi_tal_iconview.h"
+
+
+#define KVI_TEXTICON_WIN_WIDTH 230
+#define KVI_TEXTICON_WIN_HEIGHT 200
+
+class KVIRC_API KviTextIconWindow : public KviTalIconView
+{
+ Q_OBJECT
+public:
+ KviTextIconWindow();
+ ~KviTextIconWindow();
+private:
+ QWidget * m_pOwner;
+ QString m_szTypedSeq;
+ QString m_szCurFullSeq;
+ bool m_bAltMode; // in alt mode the itemSelected() string contains
+ // also the CTRL+I escape code
+ int m_iTimerId;
+public:
+ void popup(QWidget *owner,bool bAltMode = false);
+private:
+ void doHide();
+ virtual void show();
+ bool findTypedSeq(); // returns true if it is a complete word
+ virtual void keyPressEvent(QKeyEvent *e);
+ virtual void mousePressEvent(QMouseEvent *);
+ virtual void timerEvent(QTimerEvent *);
+public slots:
+ void fill();
+ void ownerDead();
+ void itemSelected(KviTalIconViewItem * item);
+};
+
+#endif //_KVI_TEXTICONWIN_H_
diff --git a/src/kvirc/ui/kvi_themedlabel.cpp b/src/kvirc/ui/kvi_themedlabel.cpp
new file mode 100644
index 00000000..f9cf8e33
--- /dev/null
+++ b/src/kvirc/ui/kvi_themedlabel.cpp
@@ -0,0 +1,154 @@
+//
+// File : kvi_themedlabel.cpp
+// Creation date : Tue Aug 29 2000 21:17:01 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+#define __KVIRC__
+#include "kvi_themedlabel.h"
+
+#include "kvi_options.h"
+#include "kvi_settings.h"
+#include "kvi_app.h"
+#include "kvi_window.h"
+#include <qpainter.h>
+
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ extern QPixmap * g_pShadedChildGlobalDesktopBackground;
+#endif
+
+KviThemedLabel::KviThemedLabel(QWidget * par,const char * name)
+: QFrame(par,name)
+{
+ setFrameStyle(QFrame::Sunken | QFrame::StyledPanel);
+ applyOptions();
+ m_bAutoHeight=0;
+}
+
+KviThemedLabel::~KviThemedLabel()
+{
+}
+
+/*QSize KviThemedLabel::sizeHint()
+{
+ QSize size=QFrame::sizeHint();
+ int iHeight=fontMetrics().height()*QStringList::split('\n',m_szText).count()+4;
+ size.setHeight(iHeight);
+ return size;
+}*/
+
+void KviThemedLabel::setText(const char * text)
+{
+ m_szText = QString(text);
+ if(m_bAutoHeight)
+ {
+ int iHeight=fontMetrics().height()*QStringList::split('\n',m_szText).count()+4;
+ setMinimumHeight(iHeight);
+ //g_pApp->postEvent(parent(),new QEvent(QEvent::Resize));
+ }
+ update();
+}
+
+void KviThemedLabel::setText(const QString& text)
+{
+ m_szText = text;
+ if(m_bAutoHeight)
+ {
+ int iHeight=fontMetrics().height()*QStringList::split('\n',m_szText).count()+4;
+ setMinimumHeight(iHeight);
+ //g_pApp->postEvent(parent(),new QEvent(QEvent::Resize));
+ }
+ update();
+}
+
+void KviThemedLabel::applyOptions()
+{
+ setFont(KVI_OPTION_FONT(KviOption_fontLabel));
+ update();
+}
+
+#ifdef COMPILE_USE_QT4
+void KviThemedLabel::paintEvent ( QPaintEvent * event )
+{
+ QFrame::paintEvent(event);
+ QPainter p(this);
+ SET_ANTI_ALIASING(p);
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ if(g_pShadedChildGlobalDesktopBackground)
+ {
+ QPoint pnt = mapToGlobal(contentsRect().topLeft());
+ p.drawTiledPixmap(contentsRect(),*g_pShadedChildGlobalDesktopBackground,pnt);
+ } else {
+#endif
+
+ if(KVI_OPTION_PIXMAP(KviOption_pixmapLabelBackground).pixmap())
+ {
+ p.drawTiledPixmap(contentsRect(),*(KVI_OPTION_PIXMAP(KviOption_pixmapLabelBackground).pixmap()));
+ } else {
+ p.fillRect(contentsRect(),KVI_OPTION_COLOR(KviOption_colorLabelBackground));
+ }
+
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ }
+#endif
+
+ QRect r = contentsRect();
+ r.setLeft(r.left() + 2); // some margin
+
+ p.setPen(KVI_OPTION_COLOR(KviOption_colorLabelForeground));
+
+ p.drawText(r,Qt::AlignLeft | Qt::AlignVCenter,m_szText);
+}
+#else
+void KviThemedLabel::drawContents(QPainter *p)
+{
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ if(g_pShadedChildGlobalDesktopBackground)
+ {
+ QPoint pnt = mapToGlobal(contentsRect().topLeft());
+ p->drawTiledPixmap(contentsRect(),*g_pShadedChildGlobalDesktopBackground,pnt);
+ } else {
+#endif
+
+ if(KVI_OPTION_PIXMAP(KviOption_pixmapLabelBackground).pixmap())
+ {
+ p->drawTiledPixmap(contentsRect(),*(KVI_OPTION_PIXMAP(KviOption_pixmapLabelBackground).pixmap()));
+ } else {
+ p->fillRect(contentsRect(),KVI_OPTION_COLOR(KviOption_colorLabelBackground));
+ }
+
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ }
+#endif
+
+ QRect r = contentsRect();
+ r.setLeft(r.left() + 2); // some margin
+
+ p->setPen(KVI_OPTION_COLOR(KviOption_colorLabelForeground));
+
+ p->drawText(r,Qt::AlignLeft | Qt::AlignVCenter,m_szText);
+}
+#endif
+
+void KviThemedLabel::mouseDoubleClickEvent(QMouseEvent *)
+{
+ emit doubleClicked();
+}
+
+
+#include "kvi_themedlabel.moc"
diff --git a/src/kvirc/ui/kvi_themedlabel.h b/src/kvirc/ui/kvi_themedlabel.h
new file mode 100644
index 00000000..b63e2386
--- /dev/null
+++ b/src/kvirc/ui/kvi_themedlabel.h
@@ -0,0 +1,62 @@
+#ifndef _KVI_THEMEDLABEL_H_
+#define _KVI_THEMEDLABEL_H_
+
+//
+// File : kvi_themedlabel.h
+// Creation date : Tue Aug 29 2000 21:12:12 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+
+#include <qframe.h>
+
+#include "kvi_string.h"
+
+class KVIRC_API KviThemedLabel : public QFrame
+{
+ Q_OBJECT
+ Q_PROPERTY(int TransparencyCapable READ dummyRead)
+public:
+ KviThemedLabel(QWidget * par,const char * name);
+ ~KviThemedLabel();
+private:
+ QString m_szText;
+ bool m_bAutoHeight;
+protected:
+#ifdef COMPILE_USE_QT4
+ virtual void paintEvent ( QPaintEvent * event );
+#else
+ virtual void drawContents(QPainter *p);
+#endif
+ virtual void mouseDoubleClickEvent(QMouseEvent *e);
+public:
+ int dummyRead() const { return 0; };
+ void setText(const char * text);
+ void setText(const QString& text);
+ QString text() { return m_szText; };
+ void setAutoHeight(bool value) { m_bAutoHeight=value; };
+ void applyOptions();
+
+// QSize sizeHint();
+signals:
+ void doubleClicked();
+};
+
+#endif //_KVI_THEMEDLABEL_H_
diff --git a/src/kvirc/ui/kvi_toolbar.cpp b/src/kvirc/ui/kvi_toolbar.cpp
new file mode 100644
index 00000000..792f9fc0
--- /dev/null
+++ b/src/kvirc/ui/kvi_toolbar.cpp
@@ -0,0 +1,160 @@
+//=============================================================================
+//
+// File : kvi_toolbar.cpp
+// Creation date : Tue Sep 17 02:00:17 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_toolbar.h"
+#include "kvi_frame.h"
+#include "kvi_locale.h"
+#include "kvi_app.h"
+
+#include <qcursor.h>
+#include "kvi_tal_popupmenu.h"
+
+#ifdef COMPILE_USE_QT4
+ #include <qevent.h>
+#endif
+
+static KviTalPopupMenu * g_pToolBarContextPopup = 0;
+static KviTalPopupMenu * g_pToolBarWindowsPopup = 0;
+static KviTalPopupMenu * g_pToolBarIconSizesPopup = 0;
+static KviTalPopupMenu * g_pToolBarPositionsPopup = 0;
+
+
+KviToolBar::KviToolBar(const QString &label,QT_TOOLBARDOCK_TYPE dock,bool bNewLine,const char * nam)
+: KviTalToolBar(label,g_pFrame,dock,bNewLine,nam)
+{
+}
+
+KviToolBar::~KviToolBar()
+{
+ if(g_pToolBarContextPopup)delete g_pToolBarContextPopup;
+ if(g_pToolBarIconSizesPopup)delete g_pToolBarIconSizesPopup;
+ if(g_pToolBarPositionsPopup)delete g_pToolBarPositionsPopup;
+ if(g_pToolBarWindowsPopup)delete g_pToolBarWindowsPopup;
+
+ g_pToolBarContextPopup = 0;
+ g_pToolBarIconSizesPopup = 0;
+ g_pToolBarPositionsPopup = 0;
+ g_pToolBarWindowsPopup = 0;
+}
+
+void KviToolBar::mousePressEvent(QMouseEvent *e)
+{
+ if(!(e->button() & Qt::RightButton))
+ {
+ KviTalToolBar::mousePressEvent(e);
+ return;
+ }
+
+ if(!g_pToolBarContextPopup)g_pToolBarContextPopup = new KviTalPopupMenu();
+ if(!g_pToolBarIconSizesPopup)g_pToolBarIconSizesPopup = new KviTalPopupMenu();
+ if(!g_pToolBarPositionsPopup)g_pToolBarPositionsPopup = new KviTalPopupMenu();
+ if(!g_pToolBarWindowsPopup)g_pToolBarWindowsPopup = new KviTalPopupMenu();
+
+ g_pToolBarContextPopup->clear();
+ g_pToolBarIconSizesPopup->clear();
+ g_pToolBarPositionsPopup->clear();
+ g_pToolBarWindowsPopup->clear();
+
+ g_pFrame->fillToolBarsPopup(g_pToolBarWindowsPopup);
+ g_pToolBarContextPopup->insertItem(__tr2qs("Toolbars"),g_pToolBarWindowsPopup);
+
+ g_pToolBarContextPopup->insertItem(__tr2qs("Orientation"),g_pToolBarPositionsPopup);
+
+ g_pToolBarPositionsPopup->insertItem(__tr2qs("Top"),this,SLOT(moveToTop()));
+ g_pToolBarPositionsPopup->insertItem(__tr2qs("Left"),this,SLOT(moveToLeft()));
+ g_pToolBarPositionsPopup->insertItem(__tr2qs("Right"),this,SLOT(moveToRight()));
+ g_pToolBarPositionsPopup->insertItem(__tr2qs("Bottom"),this,SLOT(moveToBottom()));
+ g_pToolBarPositionsPopup->insertSeparator();
+ g_pToolBarPositionsPopup->insertItem(__tr2qs("Detached"),this,SLOT(moveToTornOff()));
+ g_pToolBarPositionsPopup->insertItem(__tr2qs("Flat"),this,SLOT(moveToMinimized()));
+
+ g_pToolBarContextPopup->insertItem(__tr2qs("Icon Size"),g_pToolBarIconSizesPopup);
+
+ g_pToolBarIconSizesPopup->insertItem(__tr2qs("Small (22x22)"),this,SLOT(setSmallIcons()));
+ g_pToolBarIconSizesPopup->insertItem(__tr2qs("Large (32x32)"),this,SLOT(setBigIcons()));
+
+ g_pToolBarContextPopup->popup(QCursor::pos());
+}
+
+void KviToolBar::moveTo(QT_TOOLBARDOCK_TYPE dock)
+{
+ // FIXME: this should be hidden in Tal
+#ifdef COMPILE_USE_QT4
+ g_pFrame->removeToolBar(this);
+ g_pFrame->addToolBar(dock,this);
+#else //!COMPILE_USE_QT4
+#if QT_VERSION >= 300
+ g_pFrame->moveDockWindow(this,dock);
+#else
+ g_pFrame->moveToolBar(this,dock);
+#endif
+#endif //!COMPILE_USE_QT4
+}
+
+void KviToolBar::moveToTop()
+{
+ moveTo(QT_DOCK_TOP);
+}
+
+void KviToolBar::moveToLeft()
+{
+ moveTo(QT_DOCK_LEFT);
+}
+
+void KviToolBar::moveToRight()
+{
+ moveTo(QT_DOCK_RIGHT);
+}
+
+void KviToolBar::moveToBottom()
+{
+ moveTo(QT_DOCK_BOTTOM);
+}
+
+void KviToolBar::moveToMinimized()
+{
+ moveTo(QT_DOCK_MINIMIZED);
+}
+
+void KviToolBar::moveToTornOff()
+{
+ moveTo(QT_DOCK_TORNOFF);
+}
+
+void KviToolBar::setBigIcons()
+{
+ g_pFrame->setUsesBigPixmaps(true);
+}
+
+void KviToolBar::setSmallIcons()
+{
+ g_pFrame->setUsesBigPixmaps(false);
+}
+
+
+
+
+#include "kvi_toolbar.moc"
diff --git a/src/kvirc/ui/kvi_toolbar.h b/src/kvirc/ui/kvi_toolbar.h
new file mode 100644
index 00000000..a0e05119
--- /dev/null
+++ b/src/kvirc/ui/kvi_toolbar.h
@@ -0,0 +1,52 @@
+#ifndef _KVI_TOOLBAR_H_
+#define _KVI_TOOLBAR_H_
+//=============================================================================
+//
+// File : kvi_toolbar.h
+// Creation date : Tue Sep 17 02:00:16 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_tal_toolbar.h"
+
+class KviFrame;
+
+class KVIRC_API KviToolBar : public KviTalToolBar
+{
+ Q_OBJECT
+public:
+ KviToolBar(const QString &label,QT_TOOLBARDOCK_TYPE dock = QT_DOCK_TOP,bool bNewLine = false,const char * nam = 0);
+ ~KviToolBar();
+protected:
+ virtual void mousePressEvent(QMouseEvent *e);
+ void moveTo(QT_TOOLBARDOCK_TYPE dock);
+public slots:
+ void moveToTop();
+ void moveToLeft();
+ void moveToRight();
+ void moveToBottom();
+ void moveToMinimized();
+ void moveToTornOff();
+ void setBigIcons();
+ void setSmallIcons();
+};
+
+
+#endif //_KVI_TOOLBAR_H_
diff --git a/src/kvirc/ui/kvi_toolwindows_container.cpp b/src/kvirc/ui/kvi_toolwindows_container.cpp
new file mode 100644
index 00000000..270a7063
--- /dev/null
+++ b/src/kvirc/ui/kvi_toolwindows_container.cpp
@@ -0,0 +1,140 @@
+#define __KVIRC__
+
+
+#include <qlayout.h>
+#include <qtoolbutton.h>
+#include <qobjectcleanuphandler.h>
+#include <qpushbutton.h>
+#include "kvi_tal_vbox.h"
+#include <qpainter.h>
+#include <qapplication.h>
+
+#include "kvi_toolwindows_container.h"
+#include "kvi_iconmanager.h"
+
+
+KviWindowToolWidget::KviWindowToolWidget(QWidget * parent, KviWindowToolPageButton* button/*, const char * name, WFlags f*/ )
+:QWidget(parent/*,name,f*/)
+{
+// m_pContainer=parent;
+ m_pButton=button;
+ m_bAutoDelete=1;
+ m_bHidden=0;
+ if(m_pButton) m_pButton->setOn(!isHidden());
+// m_ObjectHandler.add(button);
+// setMinimumWidth(0);
+}
+
+KviWindowToolWidget::~KviWindowToolWidget()
+{
+// unregisterSelf();
+// m_ObjectHandler.remove(m_pButton);
+
+}
+
+void KviWindowToolWidget::registerSelf()
+{
+/* m_pContainer->registerWidget(this);
+ if(!m_ObjectHandler.isEmpty())
+ {
+ if(m_pButton)
+ m_pButton->setOn(true);
+ } else {
+ m_pButton=0;
+ }*/
+}
+
+void KviWindowToolWidget::unregisterSelf()
+{
+/* if(!m_bHidden)
+ m_pContainer->unregisterWidget(this);
+ if(!m_ObjectHandler.isEmpty())
+ {
+ if(m_pButton)
+ m_pButton->setOn(false);
+ } else {
+ m_pButton=0;
+ }*/
+}
+
+/*void KviWindowToolWidget::hide()
+{
+ if(m_bAutoDelete==0)
+ {
+ unregisterSelf();
+ m_bHidden=1;
+ }
+ QWidget::hide();
+}*/
+
+/*void KviWindowToolWidget::show()
+{
+ if(m_bHidden)
+ {
+ registerSelf();
+ }
+ QWidget::show();
+ m_bHidden=0;
+}*/
+
+KviWindowToolPageButton::KviWindowToolPageButton ( int pixon,int pixoff, const QString & text, QWidget * parent,bool bOn, const char * name )
+:TOOL_PAGE_PARENT(parent)
+{
+#ifdef COMPILE_USE_QT4
+ setFlat(true);
+ setObjectName("kvi_window_tool_button");
+ setIcon(QIcon(*(g_pIconManager->getSmallIcon(pixon))));
+#else
+ QIconSet is1;
+ is1.setPixmap(*(g_pIconManager->getSmallIcon(pixon)),QIconSet::Small,QIconSet::Normal,QIconSet::On);
+ is1.setPixmap(*(g_pIconManager->getSmallIcon(pixoff)),QIconSet::Small,QIconSet::Normal,QIconSet::Off);
+ setIconSet(is1);
+ setUsesBigPixmap(false);
+#endif
+ setToggleButton(true);
+ setOn(bOn);
+
+// setSizePolicy(QSizePolicy(QSizePolicy::Fixed,QSizePolicy::Ignored));
+}
+
+KviWindowToolPageButton::~KviWindowToolPageButton()
+{
+
+}
+
+/*void KviWindowToolPageButton::drawButton ( QPainter * p)
+{
+ QPixmap pixmap( height(), width() );
+ if(isOn())
+ pixmap.fill(colorGroup().mid());
+ else
+ pixmap.fill(colorGroup().button());
+ QPainter painter( &pixmap );
+
+ QPixmap icon;
+ if(isOn())
+ icon=iconSet()->pixmap(QIconSet::Small,QIconSet::Normal,QIconSet::On);
+ else
+ icon=iconSet()->pixmap(QIconSet::Small,QIconSet::Normal,QIconSet::Off);
+
+ // Draw the frame
+ //painter.setPen( colorGroup().mid() );
+ //if ( m_id != NUM_TABS - 1 ) painter.drawLine( 0, 0, 0, pixmap.height() - 1 );
+ //painter.drawLine( 0, pixmap.height() - 1, pixmap.width() - 1, pixmap.height() - 1 );
+
+ // Draw the text
+ QFont font;
+ QString str = text();
+ str.remove("&");
+ const int textX = pixmap.width() / 2 - QFontMetrics( font ).width( str ) / 2;
+ painter.setPen( colorGroup().buttonText() );
+ const QRect rect( textX + icon.width() / 2 + 2, 0, pixmap.width(), pixmap.height() );
+ painter.drawText( rect, Qt::AlignLeft | Qt::AlignVCenter, str );
+
+ // Draw the icon
+ painter.drawPixmap( textX - icon.width() / 2 - 2, pixmap.height() / 2 - icon.height() / 2, icon );
+
+ // Paint to widget
+ p->rotate( -90 );
+ p->drawPixmap( 1 - pixmap.width(), 0, pixmap );
+}*/
diff --git a/src/kvirc/ui/kvi_toolwindows_container.h b/src/kvirc/ui/kvi_toolwindows_container.h
new file mode 100644
index 00000000..ec131d9b
--- /dev/null
+++ b/src/kvirc/ui/kvi_toolwindows_container.h
@@ -0,0 +1,65 @@
+#ifndef _KVI_TOOLWINDOWS_CONTAINER_H_
+#define _KVI_TOOLWINDOWS_CONTAINER_H_
+
+#include "kvi_tal_widgetstack.h"
+#include "kvi_tal_vbox.h"
+
+#include <qtoolbutton.h>
+#include <qobjectcleanuphandler.h>
+#include <qpushbutton.h>
+
+#include "kvi_heapobject.h"
+#include "kvi_styled_controls.h"
+
+class KviWindowToolWidget;
+class KviWindowToolPageButton;
+
+// FIXME: these classes are probably useless now... no ?
+
+// Pragma: KviWindowToolPageButton is actually used in kvi_window.h and others (need to fix the name and move
+// it to its own file.
+
+
+
+class KVIRC_API KviWindowToolWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ KviWindowToolWidget( QWidget * parent,KviWindowToolPageButton* button/*, const char * name = 0, WFlags f = 0 */);
+ ~KviWindowToolWidget();
+
+ void setAutoDelete(bool b) { m_bAutoDelete=b; };
+ bool autoDelete() { return m_bAutoDelete; };
+
+ virtual void registerSelf();
+ virtual void unregisterSelf();
+/*public slots:
+ virtual void hide ();
+ virtual void show ();*/
+protected:
+// KviToolWindowsContainer *m_pContainer;
+ KviWindowToolPageButton *m_pButton;
+ bool m_bAutoDelete;
+ bool m_bHidden;
+// QObjectCleanupHandler m_ObjectHandler;
+
+};
+
+#ifdef COMPILE_USE_QT4
+ #define TOOL_PAGE_PARENT QPushButton
+#else
+ #define TOOL_PAGE_PARENT KviStyledToolButton
+#endif
+
+
+class KVIRC_API KviWindowToolPageButton : public TOOL_PAGE_PARENT
+{
+ Q_OBJECT
+public:
+ KviWindowToolPageButton ( int pixon,int pixoff, const QString & text, QWidget * parent,bool bOn=0,const char * name = 0 );
+ ~KviWindowToolPageButton();
+/*protected:
+ virtual void drawButton ( QPainter * painter);*/
+};
+
+#endif //_KVI_TOOLWINDOWS_CONTAINER_H_
diff --git a/src/kvirc/ui/kvi_topicw.cpp b/src/kvirc/ui/kvi_topicw.cpp
new file mode 100644
index 00000000..bbcf0c5c
--- /dev/null
+++ b/src/kvirc/ui/kvi_topicw.cpp
@@ -0,0 +1,834 @@
+//=============================================================================
+//
+// File : kvi_topicw.cpp
+// Creation date : Fri Aug 4 2000 12:09:21 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+
+#include "kvi_topicw.h"
+#include "kvi_options.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_locale.h"
+#include "kvi_defaults.h"
+#include "kvi_settings.h"
+#include "kvi_iconmanager.h"
+#include "kvi_texticonmanager.h"
+#include "kvi_app.h"
+#include "kvi_colorwin.h"
+#include "kvi_texticonwin.h"
+#include "kvi_window.h"
+#include "kvi_channel.h"
+#include "kvi_ircconnection.h"
+#include "kvi_ircconnectionserverinfo.h"
+#include "kvi_ircconnectionuserinfo.h"
+#include "kvi_mirccntrl.h"
+
+extern KviTextIconWindow * g_pTextIconWindow;
+extern KviColorWindow * g_pColorWindow;
+static int g_iInputFontCharWidth[256];
+
+#include <qpainter.h>
+#include <qfontmetrics.h>
+#include "kvi_tal_tooltip.h"
+#include <qlineedit.h>
+#include "kvi_tal_listbox.h"
+#include <qregexp.h>
+#include <qclipboard.h>
+#include "kvi_tal_popupmenu.h"
+#include <qevent.h>
+
+// FIXME: #warning "The combo should disappear when it looses focus!...(how to do it ?)"
+
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ extern QPixmap * g_pShadedChildGlobalDesktopBackground;
+
+#endif
+
+
+extern QStringList * g_pRecentTopicList;
+
+int KviListBoxTopicItem::width ( const KviTalListBox * lb ) const
+{
+ QFontMetrics fm(lb->font());
+ return fm.width(KviMircCntrl::stripControlBytes(text()));
+}
+
+void KviListBoxTopicItem::paint ( QPainter * p )
+{
+ KviTopicWidget::paintColoredText(p,text(),listBox()->colorGroup(),height(listBox()));
+}
+
+
+KviTopicWidget::KviTopicWidget(QWidget * par,const char * name)
+: QFrame(par,name)
+{
+ setFrameStyle(QFrame::Sunken | QFrame::StyledPanel);
+ setFont(KVI_OPTION_FONT(KviOption_fontLabel));
+ m_pHistory = 0;
+ m_pAccept = 0;
+ m_pDiscard = 0;
+ m_pContextPopup = 0;
+ m_iCursorPosition = 0;
+ m_pInput = 0;
+#ifdef COMPILE_USE_QT4
+ setAutoFillBackground(false);
+#else
+ setBackgroundMode(QWidget::NoBackground);
+#endif
+ reset();
+#ifdef COMPILE_USE_QT4
+ m_pCompletionBox=new KviTalListBox(this,Qt::Popup);
+#else
+ m_pCompletionBox=new KviTalListBox(this,Qt::WType_Popup);
+#endif
+ m_pCompletionBox->setFont( font() );
+ m_pCompletionBox->setPalette( palette() );
+// m_pCompletionBox->setVScrollBarMode( KviTalListBox::AlwaysOff );
+// m_pCompletionBox->setHScrollBarMode( KviTalListBox::AlwaysOff );
+ m_pCompletionBox->setFrameStyle( QFrame::Box | QFrame::Plain );
+ m_pCompletionBox->setLineWidth( 1 );
+ connect(m_pCompletionBox,SIGNAL(selected(int)),this,SLOT(complete(int)));
+ m_pCompletionBox->hide();
+}
+
+KviTopicWidget::~KviTopicWidget()
+{
+ delete m_pCompletionBox;
+}
+
+void KviTopicWidget::popDownListBox()
+{
+ m_pCompletionBox->removeEventFilter( this );
+ m_pCompletionBox->hide();
+}
+
+void KviTopicWidget::reset()
+{
+ KviTalToolTip::remove(this);
+ m_szTopic = __tr2qs("Unknown");
+ KviTalToolTip::add(this,__tr2qs("No topic message has been received from the server yet"));
+ m_szSetAt = "";
+ m_szSetBy = "";
+ update();
+}
+
+void KviTopicWidget::applyOptions()
+{
+// setFont(KVI_OPTION_FONT(KviOption_fontLabel));
+// if(m_pComboBox)m_pComboBox->setFont(KVI_OPTION_FONT(KviOption_fontLabel));
+ resizeEvent(0);
+}
+
+#define KVI_LABEL_DEF_BACK 100
+#define KVI_LABEL_DEF_FORE 101
+
+QString convertToHtml(const QString &text)
+{
+ QString result;
+ bool curBold = false;
+ bool curUnderline = false;
+ unsigned char curFore = KVI_LABEL_DEF_FORE; //default fore
+ unsigned char curBack = KVI_LABEL_DEF_BACK; //default back
+
+ unsigned int idx = 0;
+
+ while(idx < text.length())
+ {
+ unsigned short c = text[(int)idx].unicode();
+
+ unsigned int start = idx;
+
+ while(
+ (c != KVI_TEXT_COLOR) &&
+ (c != KVI_TEXT_BOLD) &&
+ (c != KVI_TEXT_UNDERLINE) &&
+ (c != KVI_TEXT_REVERSE) &&
+ (c != KVI_TEXT_RESET) &&
+ (c != KVI_TEXT_ICON)
+ )
+ {
+ idx++;
+ if(idx >= text.length())break;
+ else c = text[(int)idx].unicode();
+ }
+
+ int len = idx - start;
+
+ if(len > 0)
+ {
+ bool bOpened = FALSE;
+ QString szText = text.mid(start,len);
+
+ if(curBold) result.append("<b>");
+ if(curUnderline) result.append("<u>");
+
+ if(curFore != KVI_LABEL_DEF_FORE)
+ {
+ result.append("<font color=\"");
+ result.append(KVI_OPTION_MIRCCOLOR(curFore).name());
+ result.append('"');
+ bOpened = TRUE;
+ }
+
+/* if(curBack != KVI_LABEL_DEF_BACK)
+ {
+ if(!bOpened)
+ result.append("<font bgcolor=");
+ else
+ result.append(" bgcolor=");
+ result.append(KVI_OPTION_MIRCCOLOR(curBack).name());
+ }*/
+
+ if(bOpened) result.append(">");
+
+ result.append(text.mid(start,len));
+
+ if( (curFore != KVI_LABEL_DEF_FORE) /*|| (curBack != KVI_LABEL_DEF_BACK)*/ )
+ result.append("</font>");
+
+ if(curUnderline) result.append("</u>");
+ if(curBold) result.append("</b>");
+
+ }
+
+ switch(c)
+ {
+ case KVI_TEXT_BOLD: curBold = !curBold; ++idx; break;
+ case KVI_TEXT_UNDERLINE: curUnderline = !curUnderline; ++idx; break;
+ case KVI_TEXT_REVERSE:
+ {
+ char auxBack = curBack;
+ curBack = curFore;
+ curFore = auxBack;
+ }
+ ++idx;
+ break;
+ case KVI_TEXT_RESET:
+ curFore = KVI_LABEL_DEF_FORE;
+ curBack = KVI_LABEL_DEF_BACK;
+ curBold = false;
+ curUnderline = false;
+ ++idx;
+ break;
+ case KVI_TEXT_COLOR:
+ {
+ ++idx;
+ unsigned char fore;
+ unsigned char back;
+ idx = getUnicodeColorBytes(text,idx,&fore,&back);
+ if(fore != KVI_NOCHANGE)
+ {
+ curFore = fore;
+ if(back != KVI_NOCHANGE)curBack = back;
+ } else {
+ // only a CTRL+K
+ curBack = KVI_LABEL_DEF_BACK;
+ curFore = KVI_LABEL_DEF_FORE;
+ }
+ }
+ break;
+ case KVI_TEXT_ICON:
+ {
+ ++idx;
+
+ unsigned int icoStart = idx;
+ while((idx < text.length()) && (text[(int)idx].unicode() > 32))idx++;
+
+ KviStr lookupString = text.mid(icoStart,idx - icoStart);
+
+ KviTextIcon * icon = g_pTextIconManager->lookupTextIcon(lookupString.ptr());
+ if(icon)
+ {
+ //TODO: icons
+/* QPixmap * pigzmap = icon->pixmap();
+ p->drawPixmap(curX,(baseline + 2) - pigzmap->height(),*(pigzmap));
+ curX += pigzmap->width();*/
+ } else {
+ idx = icoStart;
+ }
+ }
+ break;
+ }
+ }
+ return result;
+}
+
+void KviTopicWidget::paintColoredText(QPainter *p, QString text,const QColorGroup& cg,int height, int width)
+{
+ QFontMetrics fm(p->font());
+
+ if(height<0) height=p->window().height();
+ if(width<0) width=p->window().width();
+
+ bool curBold = false;
+ bool curUnderline = false;
+ unsigned char curFore = KVI_LABEL_DEF_FORE; //default fore
+ unsigned char curBack = KVI_LABEL_DEF_BACK; //default back
+ int baseline = ((height + fm.ascent() - fm.descent() + 1) >> 1);
+
+ int curX = p->window().x() + 2; //2 is the margin
+
+ unsigned int idx = 0;
+
+ while((idx < text.length()) && (curX < width))
+ {
+ unsigned short c = text[(int)idx].unicode();
+
+ unsigned int start = idx;
+
+ while((idx < text.length()) &&
+ (c != KVI_TEXT_COLOR) &&
+ (c != KVI_TEXT_BOLD) &&
+ (c != KVI_TEXT_UNDERLINE) &&
+ (c != KVI_TEXT_REVERSE) &&
+ (c != KVI_TEXT_RESET) &&
+ (c != KVI_TEXT_ICON)
+ )
+ {
+ idx++;
+ c = text[(int)idx].unicode();
+ }
+
+ int len = idx - start;
+ int wdth;
+
+ if(len > 0)
+ {
+ QString szText = text.mid(start,len);
+
+ wdth = fm.width(szText);
+
+ if(curFore == KVI_LABEL_DEF_FORE)
+ {
+ p->setPen(cg.text());
+ } else {
+ if(curFore > 16)p->setPen(cg.background());
+ else p->setPen(KVI_OPTION_MIRCCOLOR(curFore));
+ }
+
+ if(curBack != KVI_LABEL_DEF_BACK)
+ {
+ if(curBack > 16)
+ {
+ p->fillRect(curX,p->window().y() + 2,wdth,height - 4,
+ cg.text());
+ } else {
+ p->fillRect(curX,p->window().y() + 2,wdth,height - 4,
+ KVI_OPTION_MIRCCOLOR(curBack));
+ }
+ }
+
+ p->drawText(curX,baseline,szText,0,len);
+
+ if(curBold)p->drawText(curX+1,baseline,szText,0,len);
+ if(curUnderline)
+ {
+ p->drawLine(curX,baseline + 1,curX+wdth,baseline + 1);
+ }
+ } else {
+ wdth = 0;
+ }
+
+
+ curX += wdth;
+
+ switch(c)
+ {
+ case KVI_TEXT_BOLD: curBold = !curBold; ++idx; break;
+ case KVI_TEXT_UNDERLINE: curUnderline = !curUnderline; ++idx; break;
+ case KVI_TEXT_REVERSE:
+ {
+ char auxBack = curBack;
+ curBack = curFore;
+ curFore = auxBack;
+ }
+ ++idx;
+ break;
+ case KVI_TEXT_RESET:
+ curFore = KVI_LABEL_DEF_FORE;
+ curBack = KVI_LABEL_DEF_BACK;
+ curBold = false;
+ curUnderline = false;
+ ++idx;
+ break;
+ case KVI_TEXT_COLOR:
+ {
+ ++idx;
+ unsigned char fore;
+ unsigned char back;
+ idx = getUnicodeColorBytes(text,idx,&fore,&back);
+ if(fore != KVI_NOCHANGE)
+ {
+ curFore = fore;
+ if(back != KVI_NOCHANGE)curBack = back;
+ } else {
+ // only a CTRL+K
+ curBack = KVI_LABEL_DEF_BACK;
+ curFore = KVI_LABEL_DEF_FORE;
+ }
+ }
+ break;
+ case KVI_TEXT_ICON:
+ {
+ ++idx;
+
+ unsigned int icoStart = idx;
+ while((idx < text.length()) && (text[(int)idx].unicode() > 32))idx++;
+
+ KviStr lookupString = text.mid(icoStart,idx - icoStart);
+
+ KviTextIcon * icon = g_pTextIconManager->lookupTextIcon(lookupString.ptr());
+ if(icon)
+ {
+ QPixmap * pigzmap = icon->pixmap();
+ p->drawPixmap(curX,(baseline + 2) - pigzmap->height(),*(pigzmap));
+ curX += pigzmap->width();
+ } else {
+ idx = icoStart;
+ }
+ }
+ break;
+ }
+ }
+}
+
+#ifdef COMPILE_USE_QT4
+void KviTopicWidget::paintEvent(QPaintEvent * e)
+{
+ QPainter pa(this);
+ drawFrame(&pa);
+ drawContents(&pa);
+}
+#endif
+
+void KviTopicWidget::drawContents(QPainter *p)
+{
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ if(g_pShadedChildGlobalDesktopBackground)
+ {
+ QPoint pnt = mapToGlobal(contentsRect().topLeft());
+ p->drawTiledPixmap(contentsRect(),*g_pShadedChildGlobalDesktopBackground,pnt);
+ } else {
+#endif
+ if(KVI_OPTION_PIXMAP(KviOption_pixmapLabelBackground).pixmap())
+ {
+ p->drawTiledPixmap(contentsRect(),*(KVI_OPTION_PIXMAP(KviOption_pixmapLabelBackground).pixmap()));
+ } else {
+ p->fillRect(contentsRect(),KVI_OPTION_COLOR(KviOption_colorLabelBackground));
+ }
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ }
+#endif
+ QColorGroup colorGroup;
+ //colorGroup()
+ colorGroup.setColor(QColorGroup::Text,KVI_OPTION_COLOR(KviOption_colorLabelForeground));
+ colorGroup.setColor(QColorGroup::Background,KVI_OPTION_COLOR(KviOption_colorLabelBackground));
+ paintColoredText(p,m_szTopic,colorGroup);
+}
+
+void KviTopicWidget::setTopic(const QString & topic)
+{
+ m_szTopic = topic;
+ bool bFound = false;
+ for(QStringList::Iterator it=g_pRecentTopicList->begin();it != g_pRecentTopicList->end(); ++it)
+ {
+ if(*it == m_szTopic)
+ {
+ bFound = true;
+ break;
+ }
+ }
+ if(!bFound && (!m_szTopic.isEmpty()))
+ {
+ if(g_pRecentTopicList->count() >= KVI_RECENT_TOPIC_ENTRIES)
+ {
+ g_pRecentTopicList->remove(g_pRecentTopicList->begin());
+ }
+ g_pRecentTopicList->append(m_szTopic);
+ }
+ updateToolTip();
+ update();
+}
+
+void KviTopicWidget::setTopicSetBy(const QString & setBy)
+{
+ m_szSetBy = setBy;
+ updateToolTip();
+}
+
+void KviTopicWidget::setTopicSetAt(const QString & setAt)
+{
+ m_szSetAt = setAt;
+ updateToolTip();
+}
+
+void KviTopicWidget::updateToolTip()
+{
+ KviTalToolTip::remove(this);
+
+ QString txt = "<html>" \
+ "<body>" \
+ "<table width=\"100%\">";
+
+ if(!m_szTopic.isEmpty())
+ {
+ txt += START_TABLE_BOLD_ROW;
+ txt += __tr2qs("Channel topic:");
+ txt += END_TABLE_BOLD_ROW;
+
+ txt += "<tr><td><center>";
+
+ QString tmp = m_szTopic;
+
+ tmp.replace('&',"&amp;");
+ tmp.replace('<',"&lt;");
+ tmp.replace('>',"&gt;");
+ tmp = convertToHtml(tmp);
+
+ txt += tmp;
+ txt += "</center></td></tr>";
+
+ if(!m_szSetBy.isEmpty())
+ {
+ txt += "<tr><td bgcolor=\"#D0D0D0\">";
+ txt += __tr2qs("Set by") + " <b>" + m_szSetBy + "</b>";
+ txt += "</td></tr>";
+
+ if(!m_szSetAt.isEmpty())
+ {
+ txt += "<tr><td bgcolor=\"#D0D0D0\">";
+ txt += __tr2qs("Set on") + " <b>" + m_szSetAt + "</b>";
+ txt += "</td></tr>";
+ }
+ }
+
+ txt += "<tr><td>";
+ txt += __tr2qs("Double-click to edit...");
+ txt += "</td></tr>";
+
+ } else {
+ txt += "<tr><td>";
+ txt += __tr2qs("No topic is set");
+ txt += "</td></tr>";
+ txt += "<tr><td>";
+ txt += __tr2qs("Double-click to set...");
+ txt += "</td></tr>";
+ }
+
+ txt += "</table>" \
+ "</body>" \
+ "<html>";
+
+ KviTalToolTip::add(this,txt);
+}
+
+QSize KviTopicWidget::sizeHint() const
+{
+ QFontMetrics fm(font());
+ int hght = fm.lineSpacing() + (frameWidth() << 1) + 4;
+ int baseline = ((hght + fm.ascent() - fm.descent() + 1) >> 1);
+ if(baseline < 16)hght += (16 - baseline);
+ return QSize(width(),hght);
+}
+
+void KviTopicWidget::mouseDoubleClickEvent(QMouseEvent *)
+{
+ int maxlen=-1;
+ QObject * w = parent();
+ QString szModes;
+ bool bCanEdit = TRUE;
+ while(w)
+ {
+ if(w->inherits("KviChannel"))
+ {
+ KviChannel *chan = ((KviChannel *)w);
+ maxlen=chan->connection()->serverInfo()->maxTopicLen();
+ chan->getChannelModeString(szModes);
+ if(szModes.contains('t') && !( chan->isMeHalfOp() || chan->isMeOp() || chan->isMeChanOwner() || chan->isMeChanAdmin() || chan->connection()->userInfo()->hasUserMode('o') || chan->connection()->userInfo()->hasUserMode('O')) ) {
+ bCanEdit=false;
+ }
+ break;
+ }
+ w = w->parent();
+ }
+ if(m_pInput == 0)
+ {
+ m_pInput=new KviInputEditor(this,0);
+ m_pInput->setReadOnly(!bCanEdit);
+ m_pInput->setMaxBufferSize(maxlen);
+ m_pInput->setGeometry(0,0,width() - (height() << 2)+height(),height());
+ m_pInput->setText(m_szTopic);
+ connect(m_pInput,SIGNAL(enterPressed()),this,SLOT(acceptClicked()));
+ connect(m_pInput,SIGNAL(escapePressed()),this,SLOT(discardClicked()));
+ m_pInput->installEventFilter(this);
+
+ m_pHistory = new QPushButton(this);
+ m_pHistory->setPixmap(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TIME)));
+ m_pHistory->setGeometry(width() - (height() << 2)+height(),0,height(),height());
+ KviTalToolTip::add(m_pHistory,__tr2qs("History"));
+ m_pHistory->show();
+ connect(m_pHistory,SIGNAL(clicked()),this,SLOT(historyClicked()));
+
+ m_pAccept = new QPushButton(this);
+ m_pAccept->setPixmap(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_ACCEPT)));
+ m_pAccept->setGeometry(width() - (height() << 1),0,height(),height());
+ m_pAccept->setEnabled(bCanEdit);
+ m_pAccept->show();
+ KviTalToolTip::add(m_pAccept,__tr2qs("Commit Changes"));
+ connect(m_pAccept,SIGNAL(clicked()),this,SLOT(acceptClicked()));
+
+ m_pDiscard = new QPushButton(this);
+ m_pDiscard->setPixmap(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_DISCARD)));
+ m_pDiscard->setGeometry(width() - height(),0,height(),height());
+ KviTalToolTip::add(m_pDiscard,__tr2qs("Discard Changes"));
+ m_pDiscard->show();
+ connect(m_pDiscard,SIGNAL(clicked()),this,SLOT(discardClicked()));
+
+ m_pInput->show();
+ m_pInput->setFocus();
+ }
+}
+
+void KviTopicWidget::mousePressEvent(QMouseEvent * e)
+{
+
+ if(!(e->button() & Qt::RightButton))return;
+ if(!m_pContextPopup)
+ {
+ m_pContextPopup = new KviTalPopupMenu(this);
+ connect(m_pContextPopup,SIGNAL(aboutToShow()),this,SLOT(contextPopupAboutToShow()));
+ }
+ m_pContextPopup->popup(mapToGlobal(e->pos()));
+}
+
+void KviTopicWidget::contextPopupAboutToShow()
+{
+ if(!m_pContextPopup)return; // hm ?
+ m_pContextPopup->clear();
+ m_pContextPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_COPY)),__tr2qs("Copy to clipboard"),this,SLOT(copy()));
+}
+
+void KviTopicWidget::copy()
+{
+ QClipboard * c = QApplication::clipboard();
+ if(!c)return;
+ if(c->supportsSelection())c->setText(m_szTopic,QClipboard::Selection);
+ c->setText(m_szTopic,QClipboard::Clipboard);
+}
+
+bool KviTopicWidget::eventFilter(QObject *object,QEvent *e)
+{
+ if ( !e )
+ return TRUE;
+ if(object==m_pCompletionBox)
+ {
+ switch( e->type() ) {
+ case QEvent::MouseButtonPress:
+ if ( m_pCompletionBox->rect().contains( ((QMouseEvent*)e)->pos() ) ) {
+ complete(m_pCompletionBox->index(m_pCompletionBox->itemAt(((QMouseEvent*)e)->pos())));
+ return TRUE;
+ }
+ break;
+ case QEvent::MouseButtonRelease:
+ if ( m_pCompletionBox->rect().contains( ((QMouseEvent*)e)->pos() ) ) {
+ QMouseEvent tmp( QEvent::MouseButtonDblClick,
+ ((QMouseEvent*)e)->pos(), ((QMouseEvent*)e)->button(), ((QMouseEvent*)e)->state() ) ;
+ // will hide popup
+ QApplication::sendEvent( object, &tmp );
+ return TRUE;
+ } else {
+ if ( m_pCompletionBox->isVisible() )
+ popDownListBox();
+ }
+ break;
+ case QEvent::KeyPress:
+ switch( ((QKeyEvent *)e)->key() ) {
+ case Qt::Key_Up:
+ case Qt::Key_Down:
+ if ( !(((QKeyEvent *)e)->state() & Qt::AltButton) )
+ break;
+ case Qt::Key_F4:
+ case Qt::Key_Escape:
+ if ( m_pCompletionBox->isVisible() ) {
+ popDownListBox();
+ return TRUE;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ case QEvent::Hide:
+ popDownListBox();
+ break;
+ default:
+ break;
+ }
+ }
+ return QFrame::eventFilter(object,e);
+}
+
+bool KviTopicWidget::handleKeyPressEvent(QKeyEvent * e)
+{
+ return 1;
+}
+
+void KviTopicWidget::keyPressEvent(QKeyEvent * e)
+{
+ if(handleKeyPressEvent(e))
+ {
+ e->accept();
+ return;
+ }
+}
+
+void KviTopicWidget::resizeEvent(QResizeEvent *e)
+{
+ if(e)QFrame::resizeEvent(e);
+ if(m_pInput)
+ {
+ m_pInput->setGeometry(0,0,width() - (height() << 2)+height(),height());
+ m_pHistory->setGeometry(width() - (height() << 2)+height(),0,height(),height());
+ m_pAccept->setGeometry(width() - (height() << 1),0,height(),height());
+ m_pDiscard->setGeometry(width() - height(),0,height(),height());
+ }
+}
+
+void KviTopicWidget::deactivate()
+{
+ popDownListBox();
+ if(m_pInput)
+ {
+ delete m_pInput;
+ m_pInput = 0;
+ delete m_pHistory;
+ m_pHistory = 0;
+ delete m_pAccept;
+ m_pAccept = 0;
+ delete m_pDiscard;
+ m_pDiscard = 0;
+ }
+
+ // try to find a KviWindow parent and give it the focus
+
+ QObject * w = parent();
+ while(w)
+ {
+ if(w->inherits("KviWindow"))
+ {
+ ((KviWindow *)w)->setFocus();
+ return;
+ }
+ w = w->parent();
+ }
+
+ // no KviWindow on the path
+ w = parent();
+ if(w)
+ {
+ if(w->inherits("QWidget"))
+ ((QWidget *)w)->setFocus();
+ }
+}
+
+void KviTopicWidget::discardClicked()
+{
+ deactivate();
+}
+
+void KviTopicWidget::historyClicked()
+{
+ if(g_pRecentTopicList)
+ {
+ m_pCompletionBox->installEventFilter( this );
+ m_pCompletionBox->clear();
+ for ( QStringList::Iterator it = g_pRecentTopicList->begin(); it != g_pRecentTopicList->end(); ++it ) {
+ KviListBoxTopicItem* item=new KviListBoxTopicItem(m_pCompletionBox,*it);
+ }
+ m_pCompletionBox->resize(m_pInput->width(),6*m_pCompletionBox->fontMetrics().height()+20);
+ QPoint point=m_pInput->mapToGlobal(QPoint(0,0));
+ point+=QPoint(0,m_pInput->height());
+ m_pCompletionBox->move(point);
+ m_pCompletionBox->show();
+ }
+}
+
+void KviTopicWidget::acceptClicked()
+{
+ if(!m_pInput->readOnly())
+ {
+ QString tmp = m_pInput->text();
+ if(tmp != m_szTopic)emit topicSelected(tmp);
+ }
+ deactivate();
+}
+
+void KviTopicWidget::insertChar(QChar c)
+{
+ insertText(QString(c));
+}
+
+void KviTopicWidget::insertText(const QString &c)
+{
+ if(m_pInput)
+ m_pInput->insertText(c);
+}
+
+int KviTopicWidget::xCursorPostionCalculation(int xInd)
+{
+ return 0;
+}
+void KviTopicWidget::complete(int pos)
+{
+ m_pInput->setText(m_pCompletionBox->text(pos));
+ popDownListBox();
+}
+
+QChar KviTopicWidget::getSubstituteChar(unsigned short control_code)
+{
+ switch(control_code)
+ {
+ case KVI_TEXT_COLOR:
+ return QChar('K');
+ break;
+ case KVI_TEXT_BOLD:
+ return QChar('B');
+ break;
+ case KVI_TEXT_RESET:
+ return QChar('O');
+ break;
+ case KVI_TEXT_REVERSE:
+ return QChar('R');
+ break;
+ case KVI_TEXT_UNDERLINE:
+ return QChar('U');
+ break;
+ case KVI_TEXT_ICON:
+ return QChar('I');
+ break;
+ default:
+ return QChar(control_code);
+ break;
+ }
+}
+
+#include "kvi_topicw.moc"
diff --git a/src/kvirc/ui/kvi_topicw.h b/src/kvirc/ui/kvi_topicw.h
new file mode 100644
index 00000000..b13088d7
--- /dev/null
+++ b/src/kvirc/ui/kvi_topicw.h
@@ -0,0 +1,120 @@
+#ifndef _KVI_TOPICW_H_
+#define _KVI_TOPICW_H_
+
+//============================================================================
+//
+// File : kvi_topicw.h
+// Creation date : Fri Aug 4 2000 12:03:12 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//============================================================================
+
+#include "kvi_settings.h"
+
+#include <qframe.h>
+#include <qpushbutton.h>
+#include "kvi_tal_listbox.h"
+
+#include "kvi_string.h"
+#include "kvi_app.h"
+#include "kvi_input.h"
+
+class QComboBox;
+class KviChannel;
+class KviTalPopupMenu;
+class KviIrcConnection;
+class KviTalListBox;
+
+class KVIRC_API KviListBoxTopicItem : public KviTalListBoxText
+{
+public:
+ KviListBoxTopicItem( KviTalListBox * listbox = 0 , const QString & text = QString::null):KviTalListBoxText(listbox,text) { ; };
+ virtual int width ( const KviTalListBox * lb ) const;
+protected:
+ virtual void paint ( QPainter * p );
+
+};
+
+class KVIRC_API KviTopicWidget : public QFrame
+{
+ Q_OBJECT
+ Q_PROPERTY(int TransparencyCapable READ dummyRead)
+ friend class KviChannel;
+
+public:
+ KviTopicWidget(QWidget * par,const char * name);
+ ~KviTopicWidget();
+
+private:
+ QString m_szTopic;
+ QString m_szSetBy;
+ QString m_szSetAt;
+ QPushButton * m_pAccept;
+ QPushButton * m_pDiscard;
+ QPushButton * m_pHistory;
+ KviTalPopupMenu * m_pContextPopup;
+ QChar getSubstituteChar(unsigned short control_code);
+ int xCursorPostionCalculation(int xInd);
+ KviInputEditor* m_pInput;
+ KviTalListBox* m_pCompletionBox;
+protected:
+ int m_iCursorPosition;
+ virtual void drawContents(QPainter *p);
+ virtual void mouseDoubleClickEvent(QMouseEvent *e);
+ virtual void mousePressEvent(QMouseEvent *e);
+ virtual void keyPressEvent(QKeyEvent *e);
+ virtual void resizeEvent(QResizeEvent *e);
+#ifdef COMPILE_USE_QT4
+ virtual void paintEvent(QPaintEvent * e);
+#endif
+ void updateToolTip();
+ void deactivate();
+ void iconButtonClicked();
+ virtual bool eventFilter(QObject *o,QEvent *e);
+ bool handleKeyPressEvent(QKeyEvent * e);
+public:
+ void insertChar(QChar c);
+ void insertText(const QString &s);
+ int dummyRead() const { return 0; };
+ void reset();
+
+ void setTopic(const QString & szTopic);
+ void setTopicSetBy(const QString & setBy);
+ void setTopicSetAt(const QString & setAt);
+
+ const QString & topic(){ return m_szTopic; };
+ const QString & topicSetBy(){ return m_szSetBy; };
+ const QString & topicSetAt(){ return m_szSetAt; };
+ virtual QSize sizeHint() const;
+ void applyOptions();
+
+ static void paintColoredText(QPainter *p, QString text,const QColorGroup& cg, int h=-1, int w=-1);
+protected slots:
+ void acceptClicked();
+ void discardClicked();
+ void historyClicked();
+ void contextPopupAboutToShow();
+ void copy();
+ void complete(int);
+ void popDownListBox();
+signals:
+ void topicSelected(const QString &szTopic);
+};
+
+#endif //_KVI_TOPICW_H_
diff --git a/src/kvirc/ui/kvi_userlistview.cpp b/src/kvirc/ui/kvi_userlistview.cpp
new file mode 100644
index 00000000..20f75f06
--- /dev/null
+++ b/src/kvirc/ui/kvi_userlistview.cpp
@@ -0,0 +1,1972 @@
+//=============================================================================
+//
+// File : kvi_userlistview.cpp
+// Creation date : Tue Aug 1 2000 21:05:22 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+#define _KVI_USERLISTVIEW_CPP_
+
+#include "kvi_debug.h"
+#include "kvi_userlistview.h"
+#include "kvi_settings.h"
+#include "kvi_locale.h"
+#include "kvi_options.h"
+#include "kvi_defaults.h"
+#include "kvi_iconmanager.h"
+#include "kvi_regusersdb.h"
+#include "kvi_parameterlist.h"
+#include "kvi_window.h"
+#include "kvi_console.h"
+#include "kvi_app.h"
+#include "kvi_useraction.h"
+#include "kvi_qstring.h"
+#include "kvi_frame.h"
+#include "kvi_mdimanager.h"
+#include "kvi_kvs_eventtriggers.h"
+#include "kvi_toolwindows_container.h"
+#include "kvi_doublebuffer.h"
+#include "kvi_stringconversion.h"
+#include "kvi_ircconnection.h"
+#include "kvi_ircconnectionserverinfo.h"
+
+#include <qlabel.h>
+#include <qscrollbar.h>
+#include <qpainter.h>
+#include <qpixmap.h>
+#include <qfontmetrics.h>
+#include <qdatetime.h>
+#include <qmime.h>
+#include "kvi_styled_controls.h"
+#include <qevent.h>
+
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ extern QPixmap * g_pShadedChildGlobalDesktopBackground;
+#endif
+
+
+// kvi_app.cpp (loaded and destroyed by KviIconManager)
+extern QPixmap * g_pUserChanStatePixmap;
+
+// Yet another really complex widget :)
+
+#define KVI_USERLIST_BORDER_WIDTH 2
+
+// FIXME: #warning "Button to show/hide avatars"
+// FIXME: #warning "We want to be able to navigate the list with the keyboard!"
+
+KviUserListToolTip::KviUserListToolTip(KviUserListView * v,KviUserListViewArea * a)
+: KviTalToolTip(a)
+{
+ m_pListView = v;
+}
+
+KviUserListToolTip::~KviUserListToolTip()
+{
+}
+
+void KviUserListToolTip::maybeTip(const QPoint &pnt)
+{
+ m_pListView->maybeTip(this,pnt);
+}
+
+
+
+
+KviUserListEntry::KviUserListEntry(KviUserListView * parent,const QString &nick,
+ KviIrcUserEntry * e,short int iFlags,bool bJoinTimeUnknown)
+{
+ m_pListView = parent;
+ m_szNick = nick;
+ m_pGlobalData = e;
+ m_iFlags = iFlags;
+ m_lastActionTime = (kvi_time_t)0;
+ m_joinTime = bJoinTimeUnknown ? (kvi_time_t)0 : kvi_unixTime();
+ m_iTemperature = bJoinTimeUnknown ? 0 : KVI_USERACTION_JOIN;
+
+ m_bSelected = false;
+
+ recalcSize();
+}
+
+KviUserListEntry::~KviUserListEntry()
+{
+}
+
+bool KviUserListEntry::color(QColor& color)
+{
+ //
+ // FIXME: Unused ?
+ //
+ KviRegisteredUser* pRegisteredUser=m_pListView->m_pKviWindow->connection()->userDataBase()->registeredUser(m_szNick);
+ if(pRegisteredUser)
+ {
+ if(m_pListView->m_pKviWindow->connection()->userDataBase()->haveCustomColor(m_szNick))
+ {
+ color=*(m_pListView->m_pKviWindow->connection()->userDataBase()->customColor(m_szNick));
+ return true;
+ }
+ }
+ if(KVI_OPTION_BOOL(KviOption_boolUseDifferentColorForOwnNick) && m_pListView->m_pKviWindow->connection())
+ {
+ if(m_szNick==m_pListView->m_pKviWindow->connection()->currentNickName())
+ {
+ color = KVI_OPTION_COLOR(KviOption_colorUserListViewOwnForeground);
+ return true;
+ }
+ }
+ if(m_iFlags == 0)
+ {
+ color=KVI_OPTION_COLOR(KviOption_colorUserListViewNormalForeground);
+ return true;
+ } else {
+ color = KVI_OPTION_COLOR((m_iFlags & KVI_USERFLAG_CHANOWNER) ? \
+ KviOption_colorUserListViewChanOwnerForeground : ((m_iFlags & KVI_USERFLAG_CHANADMIN) ? \
+ KviOption_colorUserListViewChanAdminForeground : ((m_iFlags & KVI_USERFLAG_OP) ? \
+ KviOption_colorUserListViewOpForeground : ((m_iFlags & KVI_USERFLAG_HALFOP) ? \
+ KviOption_colorUserListViewHalfOpForeground : ((m_iFlags & KVI_USERFLAG_VOICE) ? \
+ KviOption_colorUserListViewVoiceForeground : KviOption_colorUserListViewUserOpForeground)))));
+ return true;
+ }
+ return true;
+}
+
+void KviUserListEntry::recalcSize()
+{
+ KviAvatar * av = m_pGlobalData->avatar();
+ m_iHeight = m_pListView->m_iFontHeight;
+ if(KVI_OPTION_BOOL(KviOption_boolShowUserChannelIcons) && (m_iHeight < 20))m_iHeight = 20;
+
+ if(!KVI_OPTION_BOOL(KviOption_boolDisableAvatars))//G&N 2005
+ {
+ if(av)
+ {
+ if( KVI_OPTION_BOOL(KviOption_boolScaleAvatars) &&
+ (
+ !KVI_OPTION_BOOL(KviOption_boolDoNotStretchAvatars) ||
+ (av->pixmap()->width() > KVI_OPTION_UINT(KviOption_uintAvatarScaleWidth)) ||
+ (av->pixmap()->height() > KVI_OPTION_UINT(KviOption_uintAvatarScaleHeight))
+ )
+ )
+ {
+ QPixmap * pix = av->scaledPixmap(KVI_OPTION_UINT(KviOption_uintAvatarScaleWidth), KVI_OPTION_UINT(KviOption_uintAvatarScaleHeight));
+
+ m_iHeight += pix->height();
+ }
+ else
+ {
+ m_iHeight += av->pixmap()->height();
+ }
+ }
+ }
+ m_iHeight += 3;
+}
+
+///////////////////////////////////////////////
+
+
+
+KviUserListView::KviUserListView(QWidget * parent,KviWindowToolPageButton* button,KviIrcUserDataBase * db,KviWindow * pWnd,int dictSize,const QString & label_text,const char * name)
+: KviWindowToolWidget(parent,button)
+{
+ setAutoDelete(0);
+ m_pKviWindow = pWnd;
+ m_pEntryDict = new KviPointerHashTable<QString,KviUserListEntry>(dictSize,false);
+ m_pEntryDict->setAutoDelete(true);
+
+ m_pUsersLabel = new QLabel(this,"userslabel");
+ KviTalToolTip::add(m_pUsersLabel,label_text);
+
+ m_pViewArea = new KviUserListViewArea(this);
+ m_pToolTip = new KviUserListToolTip(this,m_pViewArea);
+ m_pTopItem = 0;
+ m_pHeadItem = 0;
+ m_pTailItem = 0;
+ m_iOpCount = 0;
+ m_iHalfOpCount = 0;
+ m_iVoiceCount = 0;
+ m_iChanAdminCount = 0;
+ m_iChanOwnerCount = 0;
+ m_iUserOpCount = 0;
+ m_pIrcUserDataBase = db;
+ m_iTotalHeight = 0;
+ m_ibEntries = 0;
+ m_ieEntries = 0;
+ m_iIEntries = 0;
+ m_iSelectedCount = 0;
+// setBackgroundMode(QWidget::NoBackground);
+ applyOptions();
+ registerSelf();
+}
+
+KviUserListView::~KviUserListView()
+{
+ removeAllEntries();
+ delete m_pEntryDict;
+ delete m_pToolTip;
+}
+
+void KviUserListView::emitRightClick()
+{
+ int ev = -1;
+ switch(m_pKviWindow->type())
+ {
+ case KVI_WINDOW_TYPE_CHANNEL: ev = KviEvent_OnChannelNickPopupRequest; break;
+ case KVI_WINDOW_TYPE_QUERY: ev = KviEvent_OnQueryNickPopupRequest; break;
+ case KVI_WINDOW_TYPE_CONSOLE: ev = KviEvent_OnNotifyListPopupRequest; break;
+ default: ev = KviEvent_OnNickLinkPopupRequest; break; // this should actually never happen
+ }
+ if(ev > -1)
+ {
+ if(KviKvsEventManager::instance()->hasAppHandlers(ev))
+ {
+ QString nicks;
+ appendSelectedNicknames(nicks);
+ KviKvsVariantList vList;
+ vList.append(nicks);
+ KviKvsEventManager::instance()->trigger(ev,m_pKviWindow,&vList);
+ } else {
+ g_pApp->checkSuggestRestoreDefaultScript();
+ }
+ }
+}
+
+void KviUserListView::emitDoubleClick()
+{
+ int ev = -1;
+ switch(m_pKviWindow->type())
+ {
+ case KVI_WINDOW_TYPE_CHANNEL: ev = KviEvent_OnChannelNickDefaultActionRequest; break;
+ case KVI_WINDOW_TYPE_QUERY: ev = KviEvent_OnQueryNickDefaultActionRequest; break;
+ case KVI_WINDOW_TYPE_CONSOLE: ev = KviEvent_OnNotifyListDefaultActionRequest; break;
+ default: ev = KviEvent_OnNickLinkDefaultActionRequest; break; // this should actually never happen
+ }
+ if(ev > -1)
+ {
+ if(KviKvsEventManager::instance()->hasAppHandlers(ev))
+ {
+ QString nicks;
+ appendSelectedNicknames(nicks);
+ KviKvsVariantList vList;
+ vList.append(nicks);
+ KviKvsEventManager::instance()->trigger(ev,m_pKviWindow,&vList);
+ } else {
+ g_pApp->checkSuggestRestoreDefaultScript();
+ }
+ }
+}
+
+void KviUserListView::updateScrollBarRange()
+{
+ int max = m_iTotalHeight - (m_pViewArea->height() - (KVI_USERLIST_BORDER_WIDTH * 2));
+ m_pViewArea->m_pScrollBar->setRange(0,max > 0 ? max : 0);
+}
+
+void KviUserListView::applyOptions()
+{
+/* if(!KVI_OPTION_BOOL(KviOption_boolDisableUserListLabel)){
+ m_pUsersLabel->hide();
+ m_pViewArea->setGeometry(0,0,width(),height());
+ }
+ if(KVI_OPTION_BOOL(KviOption_boolDisableUserListLabel)){
+ m_pUsersLabel->show();
+ updateUsersLabel();
+ }*/
+ setFont(KVI_OPTION_FONT(KviOption_fontUserListView));
+ QFontMetrics fm(KVI_OPTION_FONT(KviOption_fontUserListView));
+ m_iFontHeight = fm.lineSpacing();
+ KviUserListEntry * e = m_pHeadItem;
+ m_iTotalHeight = 0;
+ while(e)
+ {
+ e->recalcSize();
+ m_iTotalHeight += e->m_iHeight;
+ e = e->m_pNext;
+ }
+ updateScrollBarRange();
+ m_pUsersLabel->setFont(KVI_OPTION_FONT(KviOption_fontUserListView));
+ setMinimumWidth(100);
+ resizeEvent(0); // this will call update() too
+ repaint();
+}
+void KviUserListView::updateArea()
+{
+ bool bEnable = m_pViewArea->isUpdatesEnabled();
+ if(!bEnable) m_pViewArea->setUpdatesEnabled(true);
+ triggerUpdate();
+ if(!bEnable) m_pViewArea->setUpdatesEnabled(false);
+}
+
+void KviUserListView::enableUpdates(bool bEnable)
+{
+ m_pViewArea->setUpdatesEnabled(bEnable);
+ if(bEnable)triggerUpdate();
+}
+
+void KviUserListView::setMaskEntries(char type, int num)
+{
+ switch (type)
+ {
+ case 'b':
+ m_ibEntries = num;
+ break;
+ case 'e':
+ m_ieEntries = num;
+ break;
+ case 'I':
+ m_iIEntries = num;
+ break;
+ }
+ updateUsersLabel();
+}
+
+void KviUserListView::completeNickBashLike(const QString &begin,KviPointerList<QString> *l,bool bAppendMask)
+{
+ KviUserListEntry * entry = m_pHeadItem;
+
+ while(entry)
+ {
+ if(KviQString::equalCIN(begin,entry->m_szNick,begin.length()))
+ {
+ if(bAppendMask)
+ {
+ QString * s = new QString();
+ KviQString::sprintf(*s,"%Q!%Q@%Q",&(entry->m_szNick),&(entry->m_pGlobalData->user()),&(entry->m_pGlobalData->host()));
+ l->append(s);
+ } else
+ l->append(new QString(entry->m_szNick));
+ }
+ entry = entry->m_pNext;
+ }
+}
+
+bool KviUserListView::completeNickStandard(const QString &begin,const QString &skipAfter,QString &buffer,bool bAppendMask)
+{
+ KviUserListEntry * entry = m_pHeadItem;
+
+ if(!skipAfter.isEmpty())
+ {
+ while(entry)
+ {
+ if(KviQString::equalCI(skipAfter,entry->m_szNick))
+ {
+ entry = entry->m_pNext;
+ break;
+ }
+ entry = entry->m_pNext;
+ }
+ }
+
+ // FIXME: completion should skip my own nick or place it as last entry in the chain (?)
+
+ // if(KviConsole * c = m_pKviWindow->console())
+ // {
+ // if(kvi_strEqualCI(entry->m_szNick.ptr(),c->currentNickName())
+ // }
+
+ // Ok...now the real completion
+ while(entry)
+ {
+ if(entry->m_szNick.length() >= begin.length())
+ {
+ int result = KviQString::cmpCIN(begin,entry->m_szNick,begin.length());
+ if(result == 0)
+ {
+ // This is ok.
+ buffer = entry->m_szNick;
+ if(bAppendMask)
+ {
+ buffer += entry->m_pGlobalData->user();
+ buffer += entry->m_pGlobalData->host();
+ }
+ return true;
+ } else if(result < 0)
+ {
+ // No match...begin is lower than the current entry
+ if(entry->m_iFlags == 0)return false;
+ else {
+ int flags = entry->m_iFlags;
+ // skip the current flag
+ while(entry)
+ {
+ if(entry->m_iFlags != flags)break;
+ entry = entry->m_pNext;
+ }
+ continue;
+ }
+ }
+ }
+ entry = entry->m_pNext;
+ }
+
+ return false;
+}
+
+
+void KviUserListView::insertUserEntry(const QString &nick,KviUserListEntry * e)
+{
+ // Complex insertion task :)
+
+ m_pEntryDict->insert(nick,e);
+ m_iTotalHeight += e->m_iHeight;
+
+ bool bGotTopItem = false;
+
+ int flag = 0;
+ if(e->m_iFlags != 0)
+ {
+ if(e->m_iFlags & KVI_USERFLAG_USEROP)
+ {
+ flag = KVI_USERFLAG_USEROP;
+ m_iUserOpCount++;
+ }
+ if(e->m_iFlags & KVI_USERFLAG_VOICE)
+ {
+ flag = KVI_USERFLAG_VOICE;
+ m_iVoiceCount++;
+ }
+ if(e->m_iFlags & KVI_USERFLAG_HALFOP)
+ {
+ flag = KVI_USERFLAG_HALFOP;
+ m_iHalfOpCount++;
+ }
+ if(e->m_iFlags & KVI_USERFLAG_OP)
+ {
+ flag = KVI_USERFLAG_OP;
+ m_iOpCount++;
+ }
+ if(e->m_iFlags & KVI_USERFLAG_CHANADMIN)
+ {
+ flag = KVI_USERFLAG_CHANADMIN;
+ m_iChanAdminCount++;
+ }
+ if(e->m_iFlags & KVI_USERFLAG_CHANOWNER)
+ {
+ flag = KVI_USERFLAG_CHANOWNER;
+ m_iChanOwnerCount++;
+ }
+ }
+
+
+ if(m_pHeadItem)
+ {
+ KviUserListEntry * entry = m_pHeadItem;
+
+ if(!(e->m_iFlags & KVI_USERFLAG_CHANOWNER))
+ {
+ // the new user is not a channel owner...
+ // skip the channel owners
+ while(entry && (entry->m_iFlags & KVI_USERFLAG_CHANOWNER))
+ {
+ if(entry == m_pTopItem)bGotTopItem = true;
+ entry = entry->m_pNext;
+ }
+
+ if(!(e->m_iFlags & KVI_USERFLAG_CHANADMIN))
+ {
+ // the new user is not a channel admin...
+ // skip chan admins
+ while(entry && (entry->m_iFlags & KVI_USERFLAG_CHANADMIN))
+ {
+ if(entry == m_pTopItem)bGotTopItem = true;
+ entry = entry->m_pNext;
+ }
+
+ // is operator ?
+ if(!(e->m_iFlags & KVI_USERFLAG_OP))
+ {
+ // the new user is not an op...
+ // skip ops
+ while(entry && (entry->m_iFlags & KVI_USERFLAG_OP))
+ {
+ if(entry == m_pTopItem)bGotTopItem = true;
+ entry = entry->m_pNext;
+ }
+
+ // is half oped ?
+ if(!(e->m_iFlags & KVI_USERFLAG_HALFOP))
+ {
+ // nope , skip halfops
+ while(entry && (entry->m_iFlags & KVI_USERFLAG_HALFOP))
+ {
+ if(entry == m_pTopItem)bGotTopItem = true;
+ entry = entry->m_pNext;
+ }
+
+ // is voiced ?
+ if(!(e->m_iFlags & KVI_USERFLAG_VOICE))
+ {
+ // nope , not voiced so skip voiced users
+ while(entry && (entry->m_iFlags & KVI_USERFLAG_VOICE))
+ {
+ if(entry == m_pTopItem)bGotTopItem = true;
+ entry = entry->m_pNext;
+ }
+
+ // is userop'd?
+ if(!(e->m_iFlags & KVI_USERFLAG_USEROP))
+ {
+ // nope , skip userops
+ while(entry && (entry->m_iFlags & KVI_USERFLAG_USEROP))
+ {
+ if(entry == m_pTopItem)bGotTopItem = true;
+ entry = entry->m_pNext;
+ }
+ } // else is userop, ops, halfops, and voiced are skipped
+ } // else it is voiced , ops and halfops are skipped
+ } // else it is halfop , ops are skipped
+ } // else it is op , chan admins are skipped
+ } // else it is chan admin , chan owners are skipped
+ } // else it is chan owner, so nothing to skip: the chan owners are first in the list
+
+ // now strcmp within the current user-flag group...
+ while(entry && (KviQString::cmpCI(entry->m_szNick,e->m_szNick) < 0) &&
+ ((entry->m_iFlags & flag) || (flag == 0)))
+ {
+ if(entry == m_pTopItem)bGotTopItem = true;
+ entry = entry->m_pNext;
+ }
+ if(entry)
+ {
+ // inserting
+ e->m_pNext = entry;
+ e->m_pPrev = entry->m_pPrev;
+ if(e->m_pPrev == 0)m_pHeadItem = e;
+ else e->m_pPrev->m_pNext = e;
+ entry->m_pPrev = e;
+ // need to adjust the item offsets now...
+ // ok... if we're inserting something after
+ // the top item, we move everything down
+ // otherwise we only update the scrollbar values
+ if(!bGotTopItem)
+ {
+ // Inserting BEFORE the top item
+ if((e == m_pHeadItem) && (m_pTopItem == e->m_pNext) && (m_pViewArea->m_iTopItemOffset == 0))
+ {
+ // special case...the top item is the head one
+ // and it has zero offset...change the top item too
+ m_pTopItem = e;
+ triggerUpdate();
+ } else {
+ // invisible insertion
+ m_pViewArea->m_bIgnoreScrollBar = true;
+ m_pViewArea->m_iLastScrollBarVal += e->m_iHeight;
+ updateScrollBarRange();
+ m_pViewArea->m_pScrollBar->setValue(m_pViewArea->m_iLastScrollBarVal);
+ m_pViewArea->m_bIgnoreScrollBar = false;
+ updateUsersLabel();
+ }
+ } else {
+ triggerUpdate();
+ }
+ } else {
+ // appending to the end (may be visible)
+ m_pTailItem->m_pNext = e;
+ e->m_pNext = 0;
+ e->m_pPrev = m_pTailItem;
+ m_pTailItem = e;
+ triggerUpdate();
+ }
+ } else {
+ // There were no items (is rather visible)
+ m_pHeadItem = e;
+ m_pTailItem = e;
+ m_pTopItem = e;
+ e->m_pNext = 0;
+ e->m_pPrev = 0;
+ triggerUpdate();
+ }
+ if(e->m_bSelected)
+ {
+ m_iSelectedCount++;
+ if(m_iSelectedCount == 1)g_pFrame->childWindowSelectionStateChange(m_pKviWindow,true);
+ }
+}
+
+KviUserListEntry * KviUserListView::join(const QString &nick,const QString &user,
+ const QString &host,int iFlags)
+{
+ // Ok..an user joins the channel
+ KviUserListEntry * it = m_pEntryDict->find(nick);
+ if(it == 0)
+ {
+ // add an entry to the global dict
+ KviIrcUserEntry * pGlobalData = m_pIrcUserDataBase->insertUser(nick,user,host);
+ // calculate the flags and update the counters
+ it = new KviUserListEntry(this,nick,pGlobalData,iFlags,(user == QString::null));
+ insertUserEntry(nick,it);
+ } else {
+// if(!host.isEmpty()) - it can be UHNAMES with host or NAMEX(X) w/o it
+// {
+ // Ok...the user was already on...
+ // Probably this is a NAMES(X) reply , and the user IS_ME
+ // (already joined after the JOIN message)
+ if(iFlags != it->m_iFlags)
+ {
+//// FIXME: #warning "Maybe say to the channel that we're oped : and the op is guessed from the names reply"
+ if((iFlags & KVI_USERFLAG_CHANOWNER) != (it->m_iFlags & KVI_USERFLAG_CHANOWNER))setChanOwner(nick,iFlags & KVI_USERFLAG_CHANOWNER);
+ if((iFlags & KVI_USERFLAG_CHANADMIN) != (it->m_iFlags & KVI_USERFLAG_CHANADMIN))setChanAdmin(nick,iFlags & KVI_USERFLAG_CHANADMIN);
+ if((iFlags & KVI_USERFLAG_OP) != (it->m_iFlags & KVI_USERFLAG_OP))op(nick,iFlags & KVI_USERFLAG_OP);
+ if((iFlags & KVI_USERFLAG_HALFOP) != (it->m_iFlags & KVI_USERFLAG_HALFOP))halfop(nick,iFlags & KVI_USERFLAG_HALFOP);
+ if((iFlags & KVI_USERFLAG_VOICE) != (it->m_iFlags & KVI_USERFLAG_VOICE))voice(nick,iFlags & KVI_USERFLAG_VOICE);
+ if((iFlags & KVI_USERFLAG_USEROP) != (it->m_iFlags & KVI_USERFLAG_USEROP))userop(nick,iFlags & KVI_USERFLAG_USEROP);
+ }
+// }
+ }
+ return it;
+}
+
+void KviUserListView::triggerUpdate()
+{
+ // This stuff is useful on joins only
+ if(m_pViewArea->isUpdatesEnabled())
+ {
+ //m_pViewArea->m_pScrollBar->setRange(0,m_iTotalHeight);
+ updateScrollBarRange();
+ m_pViewArea->update();
+ updateUsersLabel();
+ }
+}
+
+bool KviUserListView::avatarChanged(const QString &nick)
+{
+ KviUserListEntry * it = m_pEntryDict->find(nick);
+ if(it)
+ {
+ int oldH = it->m_iHeight;
+ m_iTotalHeight -= it->m_iHeight;
+ it->recalcSize();
+ m_iTotalHeight += it->m_iHeight;
+ // if this was "over" the top item , we must adjust the scrollbar value
+ // otherwise scroll everything down
+ KviUserListEntry * e = m_pHeadItem;
+ bool bGotTopItem = false;
+ while(e != it)
+ {
+ if(e == m_pTopItem)
+ {
+ bGotTopItem = true;
+ e = it;
+ } else e = e->m_pNext;
+ }
+ if(!bGotTopItem && (m_pTopItem != it))
+ {
+ // we're "over" the top item , so over the
+ // upper side of the view...adjust the scroll bar value
+ int hDiff = it->m_iHeight - oldH;
+ m_pViewArea->m_iLastScrollBarVal += hDiff;
+ m_pViewArea->m_bIgnoreScrollBar = true;
+// m_pViewArea->m_pScrollBar->setRange(0,m_iTotalHeight);
+ updateScrollBarRange();
+ m_pViewArea->m_pScrollBar->setValue(m_pViewArea->m_iLastScrollBarVal);
+ m_pViewArea->m_bIgnoreScrollBar = false;
+ } else {
+ // the item may be visible!
+ // the scroll bar should take care of the case
+ // in that the current value runs out of the allowed
+ // range.... it should set the value to a good one
+ // and emit the signal
+ updateScrollBarRange();
+// m_pViewArea->m_pScrollBar->setRange(0,m_iTotalHeight);
+ m_pViewArea->update();
+ }
+ return true;
+ }
+ return false;
+}
+
+
+bool KviUserListView::userActionVerifyMask(const QString &nick,const QString &user,const QString &host,int actionTemperature,QString &oldUser,QString &oldHost)
+{
+ // This is called when an user "acts" in some visible way
+ // on the channel, so we can keep track of his channeel
+ // idle time.
+ // This particular function version of userAction
+ // will return false if there was a user or hostname
+ // change (unless they were not known at all)
+ // This will also update the username and hostname
+ // if needed.
+ KviUserListEntry * it = m_pEntryDict->find(QString(nick));
+ if(it)
+ {
+ it->m_lastActionTime = kvi_unixTime();
+ bool bChanged = false;
+ if(!(host.isEmpty() || (KviQString::equalCS(host,"*"))))
+ {
+ if(!KviQString::equalCI(it->m_pGlobalData->host(),host))
+ {
+ if(!(it->m_pGlobalData->host().isEmpty() || KviQString::equalCS(it->m_pGlobalData->host(),"*")))
+ {
+ oldHost = it->m_pGlobalData->host();
+ bChanged = true;
+ }
+ it->m_pGlobalData->setHost(host);
+ }
+ }
+ if(!(user.isEmpty() || (KviQString::equalCS(user,"*"))))
+ {
+ if(!KviQString::equalCI(it->m_pGlobalData->user(),user))
+ {
+ if(!(it->m_pGlobalData->user().isEmpty() || KviQString::equalCS(it->m_pGlobalData->user(),"*")))
+ {
+ oldUser = it->m_pGlobalData->user();
+ bChanged = true;
+ }
+ it->m_pGlobalData->setUser(user);
+ }
+ }
+ it->m_iTemperature += actionTemperature;
+ // Don't allow it to grow too much
+ if(it->m_iTemperature > 300)it->m_iTemperature = 300;
+ else if(it->m_iTemperature < -300)it->m_iTemperature = -300;
+ if(itemVisible(it))triggerUpdate();
+ return !bChanged;
+ }
+ return true; // no such nick so no change
+}
+
+
+void KviUserListView::userAction(const QString &nick,const QString &user,const QString &host,int actionTemperature)
+{
+ // This is called when an user "acts" in some visible way
+ // on the channel, so we can keep track of his channeel
+ // idle time. This will also update the username and hostname
+ // if needed.
+ KviUserListEntry * it = m_pEntryDict->find(QString(nick));
+ if(it)
+ {
+ it->m_lastActionTime = kvi_unixTime();
+ if(!(host.isEmpty() || (KviQString::equalCS(host,"*"))))
+ it->m_pGlobalData->setHost(host);
+ if(!(user.isEmpty() || (KviQString::equalCS(user,"*"))))
+ it->m_pGlobalData->setUser(user);
+ it->m_iTemperature += actionTemperature;
+ // Don't allow it to grow too much
+ if(it->m_iTemperature > 300)it->m_iTemperature = 300;
+ else if(it->m_iTemperature < -300)it->m_iTemperature = -300;
+ if(itemVisible(it))triggerUpdate();
+ }
+}
+
+
+void KviUserListView::userAction(KviIrcMask *user,int actionTemperature)
+{
+ // This is called when an user "acts" in some visible way
+ // on the channel, so we can keep track of his channeel
+ // idle time. This will also update the username and hostname
+ // if needed.
+ KviUserListEntry * it = m_pEntryDict->find(QString(user->nick()));
+ if(it)
+ {
+ it->m_lastActionTime = kvi_unixTime();
+ if(user->hasUser())it->m_pGlobalData->setUser(user->user());
+ if(user->hasHost())it->m_pGlobalData->setHost(user->host());
+ it->m_iTemperature += actionTemperature;
+ // Don't allow it to grow too much
+ if(it->m_iTemperature > 300)it->m_iTemperature = 300;
+ else if(it->m_iTemperature < -300)it->m_iTemperature = -300;
+ if(itemVisible(it))triggerUpdate();
+ }
+}
+
+void KviUserListView::userAction(const QString &nick,int actionTemperature)
+{
+ // This is called when an user "acts" in some visible way
+ // on the channel, so we can keep track of his channeel
+ // idle time. This will also update the username and hostname
+ // if needed.
+ KviUserListEntry * it = m_pEntryDict->find(nick);
+ if(it)
+ {
+ it->m_lastActionTime = kvi_unixTime();
+ it->m_iTemperature += actionTemperature;
+ if(it->m_iTemperature > 300)it->m_iTemperature = 300;
+ else if(it->m_iTemperature < -300)it->m_iTemperature = -300;
+ if(itemVisible(it))triggerUpdate();
+ }
+}
+
+kvi_time_t KviUserListView::getUserJoinTime(const QString &szNick)
+{
+ KviUserListEntry * e = m_pEntryDict->find(szNick);
+ if(!e)return (kvi_time_t)0;
+ return e->m_joinTime;
+}
+
+kvi_time_t KviUserListView::getUserLastActionTime(const QString &szNick)
+{
+ KviUserListEntry * e = m_pEntryDict->find(szNick);
+ if(!e)return (kvi_time_t)0;
+ return e->m_lastActionTime;
+}
+
+
+int KviUserListView::getUserModeLevel(const QString &szNick)
+{
+ KviUserListEntry * e = m_pEntryDict->find(szNick);
+ if(!e)return 0;
+ if(e->m_iFlags & KVI_USERFLAG_MODEMASK)
+ {
+ if(e->m_iFlags & KVI_USERFLAG_CHANOWNER)return 60;
+ if(e->m_iFlags & KVI_USERFLAG_CHANADMIN)return 50;
+ if(e->m_iFlags & KVI_USERFLAG_OP)return 40;
+ if(e->m_iFlags & KVI_USERFLAG_HALFOP)return 30;
+ if(e->m_iFlags & KVI_USERFLAG_VOICE)return 20;
+ if(e->m_iFlags & KVI_USERFLAG_USEROP)return 10;
+ }
+ return 0;
+}
+
+char KviUserListView::getUserFlag(KviUserListEntry * e)
+{
+ if(!e)return 0;
+ return (char)m_pKviWindow->connection()->serverInfo()->modePrefixChar(e->m_iFlags).unicode();
+}
+
+void KviUserListView::prependUserFlag(const QString &nick,QString &buffer)
+{
+ char uFlag = getUserFlag(nick);
+ if(uFlag)buffer.prepend(uFlag);
+}
+
+int KviUserListView::flags(const QString &nick)
+{
+ KviUserListEntry * it = m_pEntryDict->find(nick);
+ return it ? it->m_iFlags : 0;
+}
+
+#define SET_FLAG_FUNC(__funcname,__flag) \
+ bool KviUserListView::__funcname(const QString &nick,bool bYes) \
+ { \
+ KviUserListEntry * it = m_pEntryDict->find(nick); \
+ if(!it)return false; \
+ m_pEntryDict->setAutoDelete(false); \
+ partInternal(nick,false); \
+ m_pEntryDict->setAutoDelete(true); \
+ if(bYes) \
+ { \
+ if(!(it->m_iFlags & __flag))it->m_iFlags |= __flag; \
+ } else { \
+ if(it->m_iFlags & __flag)it->m_iFlags &= ~__flag; \
+ } \
+ updateScrollBarRange(); \
+ insertUserEntry(nick,it); \
+ m_pViewArea->update(); \
+ return true; \
+ }
+
+SET_FLAG_FUNC(setChanOwner,KVI_USERFLAG_CHANOWNER)
+SET_FLAG_FUNC(setChanAdmin,KVI_USERFLAG_CHANADMIN)
+SET_FLAG_FUNC(op,KVI_USERFLAG_OP)
+SET_FLAG_FUNC(halfop,KVI_USERFLAG_HALFOP)
+SET_FLAG_FUNC(userop,KVI_USERFLAG_USEROP)
+SET_FLAG_FUNC(voice,KVI_USERFLAG_VOICE)
+
+#define GET_FLAG_FUNC(__funcname,__flag) \
+ bool KviUserListView::__funcname(const QString &nick,bool bAtLeast) \
+ { \
+ KviUserListEntry * it = m_pEntryDict->find(nick); \
+ return it ? (bAtLeast ? (it->m_iFlags >= __flag) : (it->m_iFlags & __flag)) : false; \
+ }
+
+GET_FLAG_FUNC(isChanOwner,KVI_USERFLAG_CHANOWNER)
+GET_FLAG_FUNC(isChanAdmin,KVI_USERFLAG_CHANADMIN)
+GET_FLAG_FUNC(isOp,KVI_USERFLAG_OP)
+GET_FLAG_FUNC(isVoice,KVI_USERFLAG_VOICE)
+GET_FLAG_FUNC(isHalfOp,KVI_USERFLAG_HALFOP)
+GET_FLAG_FUNC(isUserOp,KVI_USERFLAG_USEROP)
+
+
+QString * KviUserListView::firstSelectedNickname()
+{
+ m_pIterator = m_pHeadItem;
+ while(m_pIterator)
+ {
+ if(m_pIterator->m_bSelected)
+ {
+ QString * s = &(m_pIterator->m_szNick);
+ m_pIterator = m_pIterator->m_pNext;
+ return s;
+ }
+ m_pIterator = m_pIterator->m_pNext;
+ }
+ return 0;
+}
+
+QString * KviUserListView::nextSelectedNickname()
+{
+ while(m_pIterator)
+ {
+ if(m_pIterator->m_bSelected)
+ {
+ QString * s = &(m_pIterator->m_szNick);
+ m_pIterator = m_pIterator->m_pNext;
+ return s;
+ }
+ m_pIterator = m_pIterator->m_pNext;
+ }
+ return 0;
+}
+
+void KviUserListView::appendSelectedNicknames(QString &buffer)
+{
+ KviUserListEntry * aux = m_pHeadItem;
+ bool bFirst = true;
+ while(aux)
+ {
+ if(aux->m_bSelected)
+ {
+ if(!bFirst)buffer.append(',');
+ else bFirst = false;
+ buffer.append(aux->m_szNick);
+ }
+ aux = aux->m_pNext;
+ }
+}
+
+void KviUserListView::select(const QString& nick){
+ KviPointerHashTableIterator<QString,KviUserListEntry> it(*m_pEntryDict);
+ while(it.current())
+ {
+ ((KviUserListEntry *)it.current())->m_bSelected = false;
+ ++it;
+ }
+
+ KviUserListEntry * entry = m_pEntryDict->find(nick);
+ if(entry)
+ {
+ entry->m_bSelected = true;
+ m_iSelectedCount = 1;
+ } else {
+ m_iSelectedCount = 0;
+ }
+ g_pFrame->childWindowSelectionStateChange(m_pKviWindow,true);
+ m_pViewArea->update();
+}
+
+bool KviUserListView::partInternal(const QString &nick,bool bRemove)
+{
+ KviUserListEntry * it = m_pEntryDict->find(nick);
+ if(it)
+ {
+ // so, first of all..check if this item is over, or below the top item
+ KviUserListEntry * e = m_pHeadItem;
+ bool bGotTopItem = false;
+ while(e != it)
+ {
+ if(e == m_pTopItem)
+ {
+ bGotTopItem = true;
+ e = it;
+ } else e = e->m_pNext;
+ }
+ if(bRemove)m_pIrcUserDataBase->removeUser(nick,it->m_pGlobalData);
+
+ // now just remove it
+ if(it->m_iFlags & KVI_USERFLAG_OP)m_iOpCount--;
+ if(it->m_iFlags & KVI_USERFLAG_VOICE)m_iVoiceCount--;
+ if(it->m_iFlags & KVI_USERFLAG_HALFOP)m_iHalfOpCount--;
+ if(it->m_iFlags & KVI_USERFLAG_CHANADMIN)m_iChanAdminCount--;
+ if(it->m_iFlags & KVI_USERFLAG_CHANOWNER)m_iChanOwnerCount--;
+ if(it->m_iFlags & KVI_USERFLAG_USEROP)m_iUserOpCount--;
+ if(it->m_bSelected)
+ {
+ m_iSelectedCount--;
+ if(m_iSelectedCount == 0)g_pFrame->childWindowSelectionStateChange(m_pKviWindow,false);
+ }
+ if(it->m_pPrev)it->m_pPrev->m_pNext = it->m_pNext;
+ if(it->m_pNext)it->m_pNext->m_pPrev = it->m_pPrev;
+ if(m_pTopItem == it)
+ {
+ bGotTopItem = true; //!!! the previous while() does not handle it!
+ m_pTopItem = it->m_pNext;
+ if(m_pTopItem == 0)m_pTopItem = it->m_pPrev;
+ }
+ if(it == m_pHeadItem)m_pHeadItem = it->m_pNext;
+ if(it == m_pTailItem)m_pTailItem = it->m_pPrev;
+ m_iTotalHeight -= it->m_iHeight;
+
+ int iHeight = it->m_iHeight;
+
+ m_pEntryDict->remove(nick);
+
+ if(bGotTopItem)
+ {
+ // removing after (or exactly) the top item, may be visible
+ if(bRemove)triggerUpdate();
+ } else {
+ // removing over (before) the top item...not visible
+ m_pViewArea->m_bIgnoreScrollBar = true;
+ m_pViewArea->m_iLastScrollBarVal -= iHeight;
+ m_pViewArea->m_pScrollBar->setValue(m_pViewArea->m_iLastScrollBarVal);
+// m_pViewArea->m_pScrollBar->setRange(0,m_iTotalHeight);
+ updateScrollBarRange();
+ m_pViewArea->m_bIgnoreScrollBar = false;
+ if(bRemove)updateUsersLabel();
+ }
+
+ return true;
+ }
+ return false;
+}
+
+bool KviUserListView::nickChange(const QString &oldNick,const QString &newNick)
+{
+ KviUserListEntry * it = m_pEntryDict->find(oldNick);
+ if(it)
+ {
+ QString user = it->m_pGlobalData->user();
+ QString host = it->m_pGlobalData->host();
+ int iFlags = it->m_iFlags;
+ kvi_time_t joint = it->m_joinTime;
+ bool bSelect = it->m_bSelected;
+ KviAvatar * av = it->m_pGlobalData->forgetAvatar();
+ KviIrcUserEntry::Gender gender = it->m_pGlobalData->gender();
+ bool bBot = it->m_pGlobalData->isBot();
+ part(oldNick);
+ __range_invalid(m_pEntryDict->find(oldNick));
+ it = join(newNick,user,host,iFlags);
+ it->m_pGlobalData->setGender(gender);
+ it->m_pGlobalData->setBot(bBot);
+ it->m_joinTime = joint;
+ it->m_lastActionTime = kvi_unixTime();
+ it->m_bSelected = bSelect;
+ it->m_iTemperature += KVI_USERACTION_NICK;
+ if(av)
+ {
+ it->m_pGlobalData->setAvatar(av);
+ avatarChanged(newNick);
+ }
+ return true;
+ }
+ return false;
+}
+
+
+void KviUserListView::updateUsersLabel()
+{
+ if(!KVI_OPTION_BOOL(KviOption_boolDisableUserListLabel))//G&N 2005
+ {
+ KviStr tmp;
+ tmp.sprintf("<nobr><b>[%u]</b>",m_pEntryDict->count());
+ if(m_iChanOwnerCount)tmp.append(KviStr::Format," q:%d",m_iChanOwnerCount);
+ if(m_iChanAdminCount)tmp.append(KviStr::Format," a:%d",m_iChanAdminCount);
+ if(m_iOpCount)tmp.append(KviStr::Format," o:%d",m_iOpCount);
+ if(m_iHalfOpCount)tmp.append(KviStr::Format," h:%d",m_iHalfOpCount);
+ if(m_iVoiceCount)tmp.append(KviStr::Format," v:%d",m_iVoiceCount);
+ if(m_iUserOpCount)tmp.append(KviStr::Format," u:%d",m_iUserOpCount);
+ if(m_ibEntries)tmp.append(KviStr::Format," b:%d",m_ibEntries);
+ if(m_ieEntries)tmp.append(KviStr::Format," e:%d",m_ieEntries);
+ if(m_iIEntries)tmp.append(KviStr::Format," I:%d",m_iIEntries);
+ tmp.append("</nobr>");
+ m_pUsersLabel->setText(tmp.ptr());
+ }
+}
+
+// FIXME: this could be done really better
+void KviUserListView::partAllButOne(const QString &whoNot)
+{
+ QStringList ll;
+ KviPointerHashTableIterator<QString,KviUserListEntry> it(*m_pEntryDict);
+ while(it.current())
+ {
+ if(!KviQString::equalCI(whoNot,it.currentKey()))
+ ll.append(it.currentKey());
+ ++it;
+ }
+ for(QStringList::Iterator it2 = ll.begin();it2 != ll.end();it2++)
+ {
+ part(*it2);
+ }
+}
+
+void KviUserListView::removeAllEntries()
+{
+ KviPointerHashTableIterator<QString,KviUserListEntry> it(*m_pEntryDict);
+ while(it.current())
+ {
+ m_pIrcUserDataBase->removeUser(it.currentKey(),
+ ((KviUserListEntry *)it.current())->m_pGlobalData);
+ ++it;
+ }
+ m_pEntryDict->clear();
+ m_pHeadItem = 0;
+ m_pTopItem = 0;
+ m_iVoiceCount = 0;
+ m_iHalfOpCount = 0;
+ m_iChanAdminCount = 0;
+ m_iChanOwnerCount = 0;
+ m_iOpCount = 0;
+ m_iUserOpCount = 0;
+ if(m_iSelectedCount != 0)
+ {
+ m_iSelectedCount = 0;
+ g_pFrame->childWindowSelectionStateChange(m_pKviWindow,false);
+ }
+ m_pViewArea->m_iTopItemOffset = 0;
+ m_pViewArea->m_iLastScrollBarVal = 0;
+ m_pViewArea->m_bIgnoreScrollBar = true;
+ m_pViewArea->m_pScrollBar->setValue(0);
+ m_iTotalHeight = 0;
+ updateScrollBarRange();
+ m_pViewArea->m_bIgnoreScrollBar = false; // gfgf
+}
+
+void KviUserListView::partAll()
+{
+ removeAllEntries();
+ triggerUpdate();
+}
+
+void KviUserListView::resizeEvent(QResizeEvent *)
+{
+ int hght;
+ if(!KVI_OPTION_BOOL(KviOption_boolDisableUserListLabel))//G&N 2005
+ {
+ hght = m_pUsersLabel->sizeHint().height();
+ if(hght < 16)hght = 16; // at least
+ m_pUsersLabel->setGeometry(0,0,width(),hght);
+ }
+ else
+ {
+ hght =0;
+ }
+
+ m_pViewArea->setGeometry(0,hght,width(),height() - hght);
+
+ updateScrollBarRange();
+}
+
+bool KviUserListView::itemVisible(KviUserListEntry * e)
+{
+ KviUserListEntry * le = m_pTopItem;
+ int curTop = KVI_USERLIST_BORDER_WIDTH - m_pViewArea->m_iTopItemOffset;
+ int hght = height();
+ while(le && (curTop < hght))
+ {
+ if(le == e)return true;
+ curTop += le->m_iHeight;
+ le = le->m_pNext;
+ }
+ return false;
+}
+
+KviUserListEntry * KviUserListView::itemAt(const QPoint &pnt,QRect * rct)
+{
+ if(!m_pTopItem)return 0;
+ if(pnt.y() < 0)return 0;
+ int curTop = KVI_USERLIST_BORDER_WIDTH - m_pViewArea->m_iTopItemOffset;
+ KviUserListEntry * e = m_pTopItem;
+ int curBottom = 0;
+ while(e && (curTop <= m_pViewArea->height()))
+ {
+ curBottom = curTop + e->m_iHeight;
+ if((pnt.y() >= curTop) && (pnt.y() < curBottom))
+ {
+ if(rct)
+ {
+ rct->setX(0);
+ rct->setY(curTop);
+ rct->setWidth(m_pViewArea->width());
+ rct->setHeight(e->m_iHeight);
+ }
+ return e;
+ }
+ curTop = curBottom;
+ e = e->m_pNext;
+ }
+ return 0;
+}
+
+
+
+void KviUserListView::userStats(KviUserListViewUserStats * s)
+{
+ s->uTotal = m_pEntryDict->count();
+ s->uHot = 0;
+ s->uHotOp = 0;
+ s->uActive = 0;
+ s->uActiveOp = 0;
+ s->uChanAdmin = 0;
+ s->uChanOwner = 0;
+ s->iAvgTemperature = 0;
+ s->uOp = 0;
+ s->uVoiced = 0;
+ s->uHalfOp = 0;
+ s->uUserOp = 0;
+
+ KviUserListEntry * e = m_pHeadItem;
+
+ kvi_time_t curTime = kvi_unixTime();
+
+ while(e)
+ {
+ if(e->m_lastActionTime)
+ {
+ unsigned int uTimeDiff = (((unsigned int)(curTime - e->m_lastActionTime)) >> 6);
+ if(uTimeDiff < 10)
+ {
+ s->uActive++; // the user was alive in the last ~16 mins
+ if(e->m_iFlags & (KVI_USERFLAG_OP | KVI_USERFLAG_CHANADMIN | KVI_USERFLAG_CHANOWNER))
+ {
+ s->uActiveOp++;
+ if(e->m_iTemperature > 0)
+ {
+ s->uHot++;
+ s->uHotOp++;
+ }
+ } else {
+ if(e->m_iTemperature > 0)s->uHot++;
+ }
+ s->iAvgTemperature += e->m_iTemperature;
+ }
+ }
+ if(e->m_iFlags & KVI_USERFLAG_CHANOWNER)s->uChanOwner++;
+ else {
+ if(e->m_iFlags & KVI_USERFLAG_CHANADMIN)s->uChanAdmin++;
+ else {
+ if(e->m_iFlags & KVI_USERFLAG_OP)s->uOp++;
+ else {
+ if(e->m_iFlags & KVI_USERFLAG_HALFOP)s->uHalfOp++;
+ else {
+ if(e->m_iFlags & KVI_USERFLAG_VOICE)s->uVoiced++;
+ else {
+ if(e->m_iFlags & KVI_USERFLAG_USEROP)s->uUserOp++;
+ }
+ }
+ }
+ }
+ }
+ e = e->m_pNext;
+ }
+
+ if(s->uActive > 0)s->iAvgTemperature /= ((int)s->uActive);
+}
+
+
+void KviUserListView::maybeTip(KviUserListToolTip * tip,const QPoint &pnt)
+{
+ if(!KVI_OPTION_BOOL(KviOption_boolShowUserListViewToolTips))return;
+ QRect itRect;
+ KviUserListEntry * it = (KviUserListEntry *)itemAt(pnt,&itRect);
+ if(it)
+ {
+ if(m_pKviWindow->console())
+ {
+ QString buffer;
+ m_pKviWindow->console()->getUserTipText(it->m_szNick,it->m_pGlobalData,buffer);
+
+ buffer += "<table width=\"100%\">";
+
+ if(it->m_joinTime != 0)
+ {
+ QDateTime dt;
+ dt.setTime_t(it->m_joinTime);
+ buffer += "<tr><td bgcolor=\"#F0F0F0\"><nobr>";
+ buffer += __tr2qs("Joined on <b>%1</b>").arg(dt.toString());
+ buffer += "</nobr></td></tr>";
+ }
+
+ if(it->m_lastActionTime != 0)
+ {
+ int secs = kvi_unixTime() - it->m_lastActionTime;
+ int mins = secs / 60;
+ secs = secs % 60;
+ int hors = mins / 60;
+ mins = mins % 60;
+ buffer += "<tr><td bgcolor=\"#F0F0F0\"><nobr>";
+ buffer += __tr2qs("Quiet for <b>%1h %2m %3s</b>").arg(hors).arg(mins).arg(secs);
+ buffer += "</nobr></td></tr>";
+ }
+ buffer += "</table>";
+
+ tip->doTip(itRect,buffer);
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////
+
+KviUserListViewArea::KviUserListViewArea(KviUserListView * par)
+: QWidget(par)
+{
+ m_pListView = par;
+#ifdef COMPILE_USE_QT4
+ setAutoFillBackground(false);
+#else
+ setBackgroundMode(QWidget::NoBackground);
+#endif
+#ifdef COMPILE_USE_QT4
+ m_pScrollBar = new QScrollBar(Qt::Vertical,this,"scrollbar");
+#else
+ m_pScrollBar = new QScrollBar(QScrollBar::Vertical,this,"scrollbar");
+#endif
+ m_pScrollBar->setRange(0,0);
+ m_pScrollBar->setValue(0);
+ connect(m_pScrollBar,SIGNAL(valueChanged(int)),this,SLOT(scrollBarMoved(int)));
+ m_pScrollBar->setPageStep(height());
+ m_pScrollBar->setLineStep(m_pListView->m_iFontHeight);
+ m_iLastScrollBarVal = 0;
+ m_iTopItemOffset = 0;
+ m_bIgnoreScrollBar = false;
+ m_pLastEntryUnderMouse = 0;
+}
+
+KviUserListViewArea::~KviUserListViewArea()
+{
+}
+
+void KviUserListViewArea::scrollBarMoved(int newVal)
+{
+ if(m_bIgnoreScrollBar)return;
+ int diff = newVal - m_iLastScrollBarVal;
+ if(m_pListView->m_pTopItem)
+ {
+ while(diff > 0)
+ {
+ int nextH = (m_pListView->m_pTopItem->m_iHeight - m_iTopItemOffset);
+ if(diff >= nextH)
+ {
+ // the diff is greater than the top item visible part
+ diff -= nextH;
+ if(m_pListView->m_pTopItem->m_pNext)
+ {
+ // There is a next item (offset to 0)
+ m_pListView->m_pTopItem = m_pListView->m_pTopItem->m_pNext;
+ m_iTopItemOffset = 0;
+ } else {
+ // No next item (rather a bug) (offset to the top item size)
+ m_iTopItemOffset = m_pListView->m_pTopItem->m_iHeight;
+ diff = 0;
+ }
+ } else {
+ // just offset the top item
+ m_iTopItemOffset += diff;
+ diff = 0;
+ }
+ }
+ while(diff < 0)
+ {
+ if((-diff) <= m_iTopItemOffset)
+ {
+ // just move the top item
+ m_iTopItemOffset += diff;
+ diff = 0;
+ } else {
+ diff += m_iTopItemOffset;
+ if(m_pListView->m_pTopItem->m_pPrev)
+ {
+ // There is a prev item (offset to 0)
+ m_pListView->m_pTopItem = m_pListView->m_pTopItem->m_pPrev;
+ m_iTopItemOffset = m_pListView->m_pTopItem->m_iHeight;
+ } else {
+ // No prev item (rather a bug) (offset to the top item size)
+ m_iTopItemOffset = 0;
+ diff = 0;
+ }
+ }
+ }
+ }
+ m_iLastScrollBarVal = newVal;
+ update();
+
+}
+
+void KviUserListViewArea::paintEvent(QPaintEvent *ev)
+{
+ // update the scroll bar
+
+ if(!isVisible())return;
+
+ // if the mdiManager is in SDI mode
+ // and this window is attacched but is not the toplevel one
+ // then it is hidden completely behind the other windows
+ // and we can avoid to paint it :)
+ if(g_pFrame->mdiManager()->isInSDIMode() &&
+ (m_pListView->window()->mdiParent() != g_pFrame->mdiManager()->topChild()) &&
+ (m_pListView->window()->mdiParent()))
+ {
+ return; // totally hidden behind other windows
+ }
+
+ int wdth = width() - m_pScrollBar->width();
+
+ QRect r = ev->rect();
+ if(r.right() > wdth)r.setRight(wdth);
+
+ //debug("PAINT EVENT %d,%d,%d,%d",r.left(),r.top(),r.width(),r.height());
+
+ KviDoubleBuffer db(width(),height());
+ QPixmap * pMemBuffer = db.pixmap();
+
+ QPainter p(pMemBuffer);
+ SET_ANTI_ALIASING(p);
+ p.setFont(KVI_OPTION_FONT(KviOption_fontUserListView));
+
+#ifdef COMPILE_USE_QT4
+ QFontMetrics fm(p.fontMetrics());
+#endif
+
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ if(g_pShadedChildGlobalDesktopBackground)
+ {
+ QPoint pnt = mapToGlobal(QPoint(r.left(),r.top()));
+ p.drawTiledPixmap(r.left(),r.top(),r.width(),r.height(),*g_pShadedChildGlobalDesktopBackground,pnt.x(),pnt.y());
+ } else {
+#endif
+ QPixmap *pix = KVI_OPTION_PIXMAP(KviOption_pixmapUserListViewBackground).pixmap();
+ p.fillRect(r.left(),r.top(),r.width(),r.height(),KVI_OPTION_COLOR(KviOption_colorUserListViewBackground));
+ if(pix)
+ KviPixmapUtils::drawPixmapWithPainter(&p,pix,KVI_OPTION_UINT(KviOption_uintUserListPixmapAlign),r,width(),height());
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ }
+#endif
+
+ KviUserListEntry * e = m_pListView->m_pTopItem;
+
+ int theY = KVI_USERLIST_BORDER_WIDTH - m_iTopItemOffset;
+
+ kvi_time_t curTime = kvi_unixTime();
+
+ bool bShowIcons = KVI_OPTION_BOOL(KviOption_boolShowUserChannelIcons);
+ bool bShowState = KVI_OPTION_BOOL(KviOption_boolShowUserChannelState);
+ bool bShowGender = KVI_OPTION_BOOL(KviOption_boolDrawGenderIcons);
+
+ while(e && theY <= r.bottom())
+ {
+ int bottom = theY + e->m_iHeight;
+ // theY is our top line
+ // theX is our left corner
+ // bottom is our bottom line
+ // wdth is the width of the whole widget
+
+ if(bottom >= r.top())
+ {
+ QColor * pClrFore = 0;
+ bool bColorAllocated=0; // FIXME: bool is true or false
+ if(e->m_bSelected)
+ {
+ p.fillRect(0,theY,wdth,e->m_iHeight,KVI_OPTION_COLOR(KviOption_colorUserListViewSelectionBackground));
+ pClrFore = &(KVI_OPTION_COLOR(KviOption_colorUserListViewSelectionForeground));
+ } else if(KVI_OPTION_BOOL(KviOption_boolUseDifferentColorForOwnNick) && m_pListView->m_pKviWindow->connection())
+ {
+ if(e->m_szNick==m_pListView->m_pKviWindow->connection()->currentNickName())
+ pClrFore = &(KVI_OPTION_COLOR(KviOption_colorUserListViewOwnForeground));
+ }
+
+ if(!pClrFore){
+ // FIXME:
+ //
+ // this is slow... VERY slow when one has a lot of registered users.
+ // (this is NOT a simple lookup in the user db... it is a mask match)
+ // if we REALLY need to use custom colors for regged users then
+ // they should be updated ONCE and stored (cached) in the KviUserListEntry structure
+ //
+ if(m_pListView->m_pKviWindow->connection()->userDataBase()->haveCustomColor(e->m_szNick))
+ {
+ pClrFore = m_pListView->m_pKviWindow->connection()->userDataBase()->customColor(e->m_szNick);
+ }
+ if(!pClrFore)
+ {
+ if(e->m_iFlags == 0)
+ {
+ pClrFore = &(KVI_OPTION_COLOR(KviOption_colorUserListViewNormalForeground));
+ } else {
+ pClrFore = &(KVI_OPTION_COLOR((e->m_iFlags & KVI_USERFLAG_CHANOWNER) ? \
+ KviOption_colorUserListViewChanOwnerForeground : ((e->m_iFlags & KVI_USERFLAG_CHANADMIN) ? \
+ KviOption_colorUserListViewChanAdminForeground : ((e->m_iFlags & KVI_USERFLAG_OP) ? \
+ KviOption_colorUserListViewOpForeground : ((e->m_iFlags & KVI_USERFLAG_HALFOP) ? \
+ KviOption_colorUserListViewHalfOpForeground : ((e->m_iFlags & KVI_USERFLAG_VOICE) ? \
+ KviOption_colorUserListViewVoiceForeground : KviOption_colorUserListViewUserOpForeground))))));
+ }
+ }
+ }
+
+ int theX = KVI_USERLIST_BORDER_WIDTH + 1;
+
+ int iAvatarAndTextX = theX;
+
+ if(bShowGender)iAvatarAndTextX += 11;
+ if(bShowIcons)iAvatarAndTextX += 18;
+ if(bShowState)iAvatarAndTextX += 11;
+
+ if(KVI_OPTION_BOOL(KviOption_boolUserListViewDrawGrid))
+ {
+ // the grid
+ switch(KVI_OPTION_UINT(KviOption_uintUserListViewGridType))
+ {
+ case KVI_USERLISTVIEW_GRIDTYPE_PLAINGRID:
+ case KVI_USERLISTVIEW_GRIDTYPE_DOTGRID:
+ p.setPen(QPen(KVI_OPTION_COLOR(KviOption_colorUserListViewGrid),0,
+#ifdef COMPILE_USE_QT4
+ (KVI_OPTION_UINT(KviOption_uintUserListViewGridType) == KVI_USERLISTVIEW_GRIDTYPE_DOTGRID) ? Qt::DotLine : Qt::SolidLine));
+#else
+ (KVI_OPTION_UINT(KviOption_uintUserListViewGridType) == KVI_USERLISTVIEW_GRIDTYPE_DOTGRID) ? QPen::DotLine : QPen::SolidLine));
+#endif
+ p.drawLine(0,bottom - 1,wdth,bottom - 1);
+ if(bShowState || bShowIcons)
+ p.drawLine(iAvatarAndTextX,bottom - 1,iAvatarAndTextX,theY);
+ break;
+ default: // KVI_USERLISTVIEW_GRIDTYPE_3DGRID and KVI_USERLISTVIEW_GRIDTYPE_3DBUTTONS
+ if(!e->m_bSelected)
+ {
+ p.setPen(QPen(KVI_OPTION_COLOR(KviOption_colorUserListViewGrid),0 /*,QPen::DotLine*/));
+ if((bShowState || bShowIcons) && (KVI_OPTION_UINT(KviOption_uintUserListViewGridType) == KVI_USERLISTVIEW_GRIDTYPE_3DGRID))
+ p.drawLine(iAvatarAndTextX,bottom - 1,iAvatarAndTextX,theY);
+ p.setPen(colorGroup().shadow());
+ p.drawLine(0,bottom - 1,wdth,bottom - 1);
+ p.setPen(colorGroup().light());
+ p.drawLine(0,theY,wdth,theY);
+ theY--;
+ }
+ theY++;
+ break;
+ }
+ iAvatarAndTextX += 3;
+ } else {
+ iAvatarAndTextX += 1;
+ }
+
+ if(e->globalData()->isAway())
+ {
+ QRgb rgb2 = pClrFore->rgb();
+ QRgb rgb1 = KVI_OPTION_COLOR(KviOption_colorUserListViewAwayForeground).rgb();
+ p.setPen(QColor(((qRed(rgb1)*2) + qRed(rgb2)) / 3,((qGreen(rgb1)*2) + qGreen(rgb2)) / 3,((qBlue(rgb1)*2) + qBlue(rgb2)) / 3));
+ } else {
+ p.setPen(*pClrFore);
+ }
+ theY+=2;
+
+ if(!KVI_OPTION_BOOL(KviOption_boolDisableAvatars))//G&N 2005
+ {
+ KviAvatar * av = e->m_pGlobalData->avatar();
+ if(av && KVI_OPTION_UINT(KviOption_uintAvatarScaleWidth) && KVI_OPTION_UINT(KviOption_uintAvatarScaleHeight))
+ {
+ QPixmap * pix;
+ if( KVI_OPTION_BOOL(KviOption_boolScaleAvatars) &&
+ (
+ !KVI_OPTION_BOOL(KviOption_boolDoNotStretchAvatars) ||
+ (av->pixmap()->width() > KVI_OPTION_UINT(KviOption_uintAvatarScaleWidth)) ||
+ (av->pixmap()->height() > KVI_OPTION_UINT(KviOption_uintAvatarScaleHeight))
+ )
+ )
+ pix=av->scaledPixmap(KVI_OPTION_UINT(KviOption_uintAvatarScaleWidth),KVI_OPTION_UINT(KviOption_uintAvatarScaleHeight));
+ else
+ pix=av->pixmap();
+ p.drawPixmap(iAvatarAndTextX,theY,*pix);
+ theY += pix->height() + 1;
+ }
+ }
+
+ if(bShowGender)
+ {
+ if(e->globalData()->gender()!=KviIrcUserEntry::Unknown)
+ {
+ QPixmap * ico = g_pIconManager->getBigIcon((e->globalData()->gender()==KviIrcUserEntry::Male) ? "kvi_icon_male.png" : "kvi_icon_female.png");
+ p.drawPixmap(theX,theY+(m_pListView->m_iFontHeight-11)/2,*ico);
+ }
+ if(e->globalData()->isBot())
+ {
+ QPixmap * ico = g_pIconManager->getBigIcon("kvi_icon_bot.png");
+ p.drawPixmap(theX,theY+(m_pListView->m_iFontHeight-11)/2,*ico);
+ }
+ theX +=11;
+ }
+
+ if(bShowState)
+ {
+ if(e->m_lastActionTime)
+ {
+ // the g_pUserChanStatePixmap is 36 x 80 pixels
+ // divided into 6 rows of 5 pixmaps
+ // row 0 is hot , row 5 is cold
+ // left is most active , right is least active
+ // e->m_iTemperature is a signed short , negative values are cold
+ // e->m_lastActionTime is the time of the last action (eventually 0 , if not known)
+ // 6 bit right shift is an aprox division for 64 : really aprox minutes
+ unsigned int uTimeDiff = (((unsigned int)(curTime - e->m_lastActionTime)) >> 6);
+ if(uTimeDiff < 16)
+ {
+ //p.drawRect(theX,theY + 2,10,e->m_iHeight - 4);
+ static int xOffTable[16] =
+ {
+ 0 , 8 , 16 , 16 ,
+ 24 , 24 , 24 , 24 ,
+ 32 , 32 , 32 , 32 ,
+ 32 , 32 , 32 , 32
+ };
+ // the temperature now
+ // temp > 100 is hot (offset y = 0)
+ // temp < -100 is cold (offset y = 80)
+ // temp > 30 is half-hot (offset y = 16)
+ // temp < -30 is half-cold (offset y = 64)
+ // temp > 0 is a-bit-hot (offset y = 32)
+ // temp < 0 is a-bit-cold (offset y = 48)
+
+ if(e->m_iTemperature > KVI_MID_TEMPERATURE)
+ {
+ if(e->m_iTemperature > KVI_HALF_HOT_TEMPERATURE)
+ {
+ if(e->m_iTemperature > KVI_HOT_TEMPERATURE)
+ {
+ // hot
+ p.drawPixmap(theX,theY,*g_pUserChanStatePixmap,xOffTable[uTimeDiff],0,8,16);
+ } else {
+ // half-hot
+ p.drawPixmap(theX,theY,*g_pUserChanStatePixmap,xOffTable[uTimeDiff],16,8,16);
+ }
+ } else {
+ // bit-hot
+ p.drawPixmap(theX,theY,*g_pUserChanStatePixmap,xOffTable[uTimeDiff],32,8,16);
+ }
+ } else {
+ if(e->m_iTemperature < KVI_HALF_COLD_TEMPERATURE)
+ {
+ if(e->m_iTemperature < KVI_COLD_TEMPERATURE)
+ {
+ // cold
+ p.drawPixmap(theX,theY,*g_pUserChanStatePixmap,xOffTable[uTimeDiff],80,8,16);
+ } else {
+ // half-cold
+ p.drawPixmap(theX,theY,*g_pUserChanStatePixmap,xOffTable[uTimeDiff],64,8,16);
+ }
+ } else {
+ // bit-cold
+ p.drawPixmap(theX,theY,*g_pUserChanStatePixmap,xOffTable[uTimeDiff],48,8,16);
+ }
+ }
+ }
+ }
+ theX += 11;
+ }
+
+ if(bShowIcons)
+ {
+ //p.drawRect(theX,theY + 2,18,e->m_iHeight - 4);
+ if(e->m_iFlags != 0)
+ {
+ QPixmap * ico = g_pIconManager->getSmallIcon( \
+ e->globalData()->isAway() ? \
+ ( \
+ (e->m_iFlags & KVI_USERFLAG_CHANOWNER) ? \
+ KVI_SMALLICON_CHANOWNERAWAY : ((e->m_iFlags & KVI_USERFLAG_CHANADMIN) ? \
+ KVI_SMALLICON_CHANADMINAWAY : ((e->m_iFlags & KVI_USERFLAG_OP) ? \
+ KVI_SMALLICON_OPAWAY : ((e->m_iFlags & KVI_USERFLAG_HALFOP) ? \
+ KVI_SMALLICON_HALFOPAWAY : ((e->m_iFlags & KVI_USERFLAG_VOICE) ? \
+ KVI_SMALLICON_VOICEAWAY : KVI_SMALLICON_USEROPAWAY))))
+ ) \
+ : \
+ ( \
+ (e->m_iFlags & KVI_USERFLAG_CHANOWNER) ? \
+ KVI_SMALLICON_CHANOWNER : ((e->m_iFlags & KVI_USERFLAG_CHANADMIN) ? \
+ KVI_SMALLICON_CHANADMIN : ((e->m_iFlags & KVI_USERFLAG_OP) ? \
+ KVI_SMALLICON_OP : ((e->m_iFlags & KVI_USERFLAG_HALFOP) ? \
+ KVI_SMALLICON_HALFOP : ((e->m_iFlags & KVI_USERFLAG_VOICE) ? \
+ KVI_SMALLICON_VOICE : KVI_SMALLICON_USEROP)))) \
+ ) \
+ );
+#ifdef COMPILE_USE_QT4
+ p.drawPixmap(theX,theY+(fm.lineSpacing()-16/*size of small icon*/)/2,*ico);
+#else
+ p.drawPixmap(theX,theY+(m_pListView->m_iFontHeight-16/*size of small icon*/)/2,*ico);
+#endif
+ }
+ theX +=18;
+#ifdef COMPILE_USE_QT4
+ p.drawText(iAvatarAndTextX,theY,wdth - theX,fm.lineSpacing(),Qt::AlignLeft|Qt::AlignVCenter,e->m_szNick);
+#else
+ p.drawText(iAvatarAndTextX,theY,wdth - theX,m_pListView->m_iFontHeight,Qt::AlignLeft|Qt::AlignVCenter,e->m_szNick);
+#endif
+ } else {
+
+ char flag = m_pListView->getUserFlag(e);
+ if(flag)
+ {
+ QString ttt = QChar(flag);
+ ttt += e->m_szNick;
+#ifdef COMPILE_USE_QT4
+ p.drawText(iAvatarAndTextX,theY,wdth - theX,fm.lineSpacing(),Qt::AlignLeft|Qt::AlignVCenter,ttt);
+#else
+ p.drawText(iAvatarAndTextX,theY,wdth - theX,m_pListView->m_iFontHeight,Qt::AlignLeft|Qt::AlignVCenter,ttt);
+#endif
+ } else {
+#ifdef COMPILE_USE_QT4
+ p.drawText(iAvatarAndTextX,theY,wdth - theX,fm.lineSpacing(),Qt::AlignLeft|Qt::AlignVCenter,e->m_szNick);
+#else
+ p.drawText(iAvatarAndTextX,theY,wdth - theX,m_pListView->m_iFontHeight,Qt::AlignLeft|Qt::AlignVCenter,e->m_szNick);
+#endif
+ }
+ }
+ if(bColorAllocated) delete pClrFore;
+ }
+
+ theY = bottom;
+ e = e->m_pNext;
+ }
+
+ //we really do not need any self-draw borders.
+ //if we will need it, we will draw a better one with system style
+
+ //p.setPen(colorGroup().dark());
+ //p.drawLine(0,0,wdth,0);
+ //p.drawLine(0,0,0,height());
+ //p.setPen(colorGroup().light());
+ //p.drawLine(1,height()-1,wdth,height()-1);
+ //p.drawLine(wdth - 1,1,wdth - 1,height());
+
+#ifdef COMPILE_USE_QT4
+ QPainter qt4SuxBecauseOfThisAdditionalPainter(this);
+ qt4SuxBecauseOfThisAdditionalPainter.drawPixmap(r.left(),r.top(),r.width(),r.height(),*pMemBuffer,r.left(),r.top(),r.width(),r.height());
+#else
+ bitBlt(this,r.left(),r.top(),pMemBuffer,r.left(),r.top(),r.width(),r.height(),Qt::CopyROP,false);
+#endif
+}
+
+void KviUserListViewArea::resizeEvent(QResizeEvent *)
+{
+ int iScr = m_pScrollBar->sizeHint().width();
+ m_pScrollBar->setGeometry(width() - iScr,0,iScr,height());
+ m_pScrollBar->setPageStep(height());
+ m_pScrollBar->setLineStep(m_pListView->m_iFontHeight - 1);
+}
+
+void KviUserListViewArea::mousePressEvent(QMouseEvent *e)
+{
+ setFocus();
+ if(e->button() & Qt::LeftButton)
+ {
+ KviUserListEntry * entry = m_pListView->itemAt(e->pos());
+ if(entry)
+ {
+ if(e->state() & Qt::ShiftButton)
+ {
+ // Multiselect mode
+ if(!entry->m_bSelected)m_pListView->m_iSelectedCount++;
+ entry->m_bSelected = true;
+ if(m_pListView->m_iSelectedCount == 1)g_pFrame->childWindowSelectionStateChange(m_pListView->m_pKviWindow,true);
+ update();
+ } else if(e->state() & Qt::ControlButton)
+ {
+ // Invert mode
+ if(!entry->m_bSelected)m_pListView->m_iSelectedCount++;
+ else m_pListView->m_iSelectedCount--;
+ entry->m_bSelected = ! entry->m_bSelected;
+ if(m_pListView->m_iSelectedCount == 0)g_pFrame->childWindowSelectionStateChange(m_pListView->m_pKviWindow,false);
+ else if(m_pListView->m_iSelectedCount == 1)g_pFrame->childWindowSelectionStateChange(m_pListView->m_pKviWindow,true);
+ update();
+ } else {
+ // Single select mode
+ bool bThereWasSelection = false;
+ if(m_pListView->m_iSelectedCount > 0)
+ {
+ KviUserListEntry * aux = m_pListView->m_pHeadItem;
+ while(aux)
+ {
+ aux->m_bSelected = false;
+ aux = aux->m_pNext;
+ }
+ bThereWasSelection = true;
+ }
+ entry->m_bSelected = true;
+ m_pListView->m_iSelectedCount = 1;
+ if(!bThereWasSelection)g_pFrame->childWindowSelectionStateChange(m_pListView->m_pKviWindow,true);
+ update();
+ }
+ }
+ m_pLastEntryUnderMouse = entry;
+ } else if(e->button() & Qt::RightButton)
+ {
+ KviUserListEntry * entry = m_pListView->itemAt(e->pos());
+ if(entry)
+ {
+ if(!entry->m_bSelected){
+ entry->m_bSelected = true;
+ m_pListView->m_iSelectedCount=1;
+ KviPointerHashTableIterator<QString,KviUserListEntry> it(*(m_pListView->m_pEntryDict));
+ while(it.current())
+ {
+ if(it.current()!=entry)
+ ((KviUserListEntry *)it.current())->m_bSelected = false;
+ ++it;
+ }
+ }
+ if(m_pListView->m_iSelectedCount == 1)
+ g_pFrame->childWindowSelectionStateChange(m_pListView->m_pKviWindow,true);
+ update();
+ }
+ m_pListView->emitRightClick();
+ }
+}
+void KviUserListViewArea::keyPressEvent( QKeyEvent * e )
+{
+ if(e->key()==Qt::Key_Escape)
+ {
+ if(m_pListView->m_pKviWindow->input())
+ ((QWidget*)(m_pListView->m_pKviWindow->input()))->setFocus();
+ } else {
+ QString szKey=e->text();
+ if(!szKey.isEmpty())
+ {
+ KviUserListEntry * nick=0;
+ KviUserListEntry * aux = m_pListView->m_pHeadItem;
+ while(aux)
+ {
+ //debug("%s %s %i %s %i",__FILE__,__FUNCTION__,__LINE__,aux->nick().utf8().data(),aux->nick().find(szKey,0,0));
+ if(aux->nick().find(szKey,0,0)==0)
+ {
+ nick=aux;
+ break;
+ }
+ aux = aux->m_pNext;
+ }
+ if(nick)
+ {
+ bool bThereWasSelection = false;
+ if(m_pListView->m_iSelectedCount > 0)
+ {
+ aux = m_pListView->m_pHeadItem;
+ while(aux)
+ {
+ aux->m_bSelected = false;
+ aux = aux->m_pNext;
+ }
+ bThereWasSelection = true;
+ }
+ nick->m_bSelected = true;
+ m_pListView->m_iSelectedCount = 1;
+ if(!bThereWasSelection)g_pFrame->childWindowSelectionStateChange(m_pListView->m_pKviWindow,true);
+ update();
+ }
+ }
+ }
+}
+
+void KviUserListViewArea::mouseDoubleClickEvent(QMouseEvent *e)
+{
+ m_pListView->emitDoubleClick();
+}
+
+void KviUserListViewArea::mouseMoveEvent(QMouseEvent *e)
+{
+ if(e->state() & Qt::LeftButton)
+ {
+ KviUserListEntry * entry = m_pListView->itemAt(e->pos());
+ if(entry && (entry != m_pLastEntryUnderMouse))
+ {
+ if(e->state() & Qt::ControlButton)
+ {
+ if(entry->m_bSelected)m_pListView->m_iSelectedCount--;
+ else m_pListView->m_iSelectedCount++;
+ entry->m_bSelected = ! entry->m_bSelected;
+ if(m_pListView->m_iSelectedCount == 0)g_pFrame->childWindowSelectionStateChange(m_pListView->m_pKviWindow,false);
+ else if(m_pListView->m_iSelectedCount == 1)g_pFrame->childWindowSelectionStateChange(m_pListView->m_pKviWindow,true);
+ } else {
+ if(!entry->m_bSelected)m_pListView->m_iSelectedCount++;
+ entry->m_bSelected = true;
+ if(m_pListView->m_iSelectedCount == 1)g_pFrame->childWindowSelectionStateChange(m_pListView->m_pKviWindow,true);
+ }
+ update();
+ m_pLastEntryUnderMouse = entry;
+ } else {
+ // out of the widget ?
+ if(entry == m_pLastEntryUnderMouse)return;
+ if(e->pos().y() < KVI_USERLIST_BORDER_WIDTH)
+ {
+ KviUserListEntry * top = m_pListView->m_pTopItem;
+ if(top)
+ {
+ m_pScrollBar->setValue(m_pScrollBar->value() - top->m_iHeight);
+ if(m_pListView->m_pTopItem != top)
+ {
+ if(e->state() & Qt::ControlButton)
+ {
+ if(m_pListView->m_pTopItem->m_bSelected)m_pListView->m_iSelectedCount--;
+ else m_pListView->m_iSelectedCount++;
+ m_pListView->m_pTopItem->m_bSelected = ! m_pListView->m_pTopItem->m_bSelected;
+ if(m_pListView->m_iSelectedCount == 0)g_pFrame->childWindowSelectionStateChange(m_pListView->m_pKviWindow,false);
+ else if(m_pListView->m_iSelectedCount == 1)g_pFrame->childWindowSelectionStateChange(m_pListView->m_pKviWindow,true);
+ } else {
+ if(!m_pListView->m_pTopItem->m_bSelected)m_pListView->m_iSelectedCount++;
+ m_pListView->m_pTopItem->m_bSelected = true;
+ if(m_pListView->m_iSelectedCount == 1)g_pFrame->childWindowSelectionStateChange(m_pListView->m_pKviWindow,true);
+ }
+ update();
+ }
+ }
+ m_pLastEntryUnderMouse = top;
+ } else if(e->pos().y() > (height() - KVI_USERLIST_BORDER_WIDTH))
+ {
+ KviUserListEntry * bottom = m_pListView->m_pTopItem;
+ if(bottom)
+ {
+ int theY = KVI_USERLIST_BORDER_WIDTH - m_iTopItemOffset;
+ while(bottom && (theY < height()))
+ {
+ theY+= bottom->m_iHeight;
+ bottom = bottom->m_pNext;
+ }
+ if(!bottom)bottom = m_pListView->m_pTailItem;
+ if(bottom)
+ {
+ m_pScrollBar->setValue(m_pScrollBar->value() + bottom->m_iHeight);
+ if(bottom != m_pLastEntryUnderMouse)
+ {
+ if(e->state() & Qt::ControlButton)
+ {
+ if(bottom->m_bSelected)m_pListView->m_iSelectedCount--;
+ else m_pListView->m_iSelectedCount++;
+ bottom->m_bSelected = ! bottom->m_bSelected;
+ if(m_pListView->m_iSelectedCount == 0)g_pFrame->childWindowSelectionStateChange(m_pListView->m_pKviWindow,false);
+ else if(m_pListView->m_iSelectedCount == 1)g_pFrame->childWindowSelectionStateChange(m_pListView->m_pKviWindow,true);
+ } else {
+ if(!bottom->m_bSelected)m_pListView->m_iSelectedCount++;
+ bottom->m_bSelected = true;
+ if(m_pListView->m_iSelectedCount == 1)g_pFrame->childWindowSelectionStateChange(m_pListView->m_pKviWindow,true);
+ }
+ update();
+ }
+ }
+ }
+ m_pLastEntryUnderMouse = bottom;
+ } else m_pLastEntryUnderMouse = 0;
+ }
+ }
+}
+
+void KviUserListViewArea::mouseReleaseEvent(QMouseEvent *)
+{
+ m_pLastEntryUnderMouse = 0;
+}
+
+void KviUserListViewArea::wheelEvent(QWheelEvent *e)
+{
+#ifdef COMPILE_USE_QT4
+ static bool bHere = false; // Qt4(<= 4.2.2) has a nasty bug that makes the re-sent wheelEvent to cause infinite recursion
+ if(bHere)return;
+ bHere = true;
+#endif
+ g_pApp->sendEvent(m_pScrollBar,e);
+#ifdef COMPILE_USE_QT4
+ bHere = false;
+#endif
+}
+
+#include "kvi_userlistview.moc"
diff --git a/src/kvirc/ui/kvi_userlistview.h b/src/kvirc/ui/kvi_userlistview.h
new file mode 100644
index 00000000..f5405937
--- /dev/null
+++ b/src/kvirc/ui/kvi_userlistview.h
@@ -0,0 +1,259 @@
+#ifndef _KVI_USERLISTVIEW_H_
+#define _KVI_USERLISTVIEW_H_
+
+//=============================================================================
+//
+// File : kvi_userlistview.h
+// Creation date : Tue Aug 1 2000 21:03:41 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#include "kvi_string.h"
+#include "kvi_ircuserdb.h"
+#include "kvi_ircmask.h"
+#include "kvi_time.h"
+
+#include <time.h>
+#include "kvi_tal_tooltip.h"
+#include <qwidget.h>
+#include "kvi_pointerlist.h"
+#include "kvi_pointerhashtable.h"
+#include "kvi_toolwindows_container.h"
+
+class QLabel;
+class QScrollBar;
+
+class KviUserListView;
+class KviUserListViewArea;
+class KviConsole;
+class KviWindow;
+
+#define KVI_USERLISTVIEW_GRIDTYPE_3DGRID 0
+#define KVI_USERLISTVIEW_GRIDTYPE_3DBUTTONS 1
+#define KVI_USERLISTVIEW_GRIDTYPE_PLAINGRID 2
+#define KVI_USERLISTVIEW_GRIDTYPE_DOTGRID 3
+
+#define KVI_USERLISTVIEW_GRIDTYPE_MAXIMUM 3
+#define KVI_USERLISTVIEW_GRIDTYPE_DEFAULT 0
+
+class KVIRC_API KviUserListToolTip : public KviTalToolTip
+{
+public:
+ KviUserListToolTip(KviUserListView *v,KviUserListViewArea * a);
+ virtual ~KviUserListToolTip();
+private:
+ KviUserListView * m_pListView;
+public:
+ virtual void maybeTip(const QPoint &pnt);
+ void doTip(const QRect &rct,const QString &str){ tip(rct,str); };
+};
+
+
+
+class KVIRC_API KviUserListEntry
+{
+ friend class KviUserListView;
+ friend class KviUserListViewArea;
+public:
+ KviUserListEntry(KviUserListView * parent,const QString &nick,KviIrcUserEntry * e,short int iFlags,bool bJoinTimeUnknown = true);
+ ~KviUserListEntry();
+protected:
+ KviUserListView * m_pListView;
+ QString m_szNick;
+ KviIrcUserEntry * m_pGlobalData;
+ short int m_iFlags;
+ short int m_iTemperature; // user temperature : 0 = neutral
+ kvi_time_t m_lastActionTime;
+ kvi_time_t m_joinTime;
+
+ int m_iHeight;
+ bool m_bSelected;
+ KviUserListEntry * m_pNext;
+ KviUserListEntry * m_pPrev;
+public:
+ short int flags() const { return m_iFlags; };
+ KviIrcUserEntry * globalData(){ return m_pGlobalData; };
+ const QString &nick() const { return m_szNick; };
+ KviUserListEntry * next(){ return m_pNext; };
+ bool color(QColor& color);
+protected:
+ void recalcSize();
+};
+
+
+typedef struct _KviUserListViewUserStats
+{
+ unsigned int uTotal; // total users on the channel
+ unsigned int uActive; // active users in the last 10 mins
+ unsigned int uActiveOp; // active operators in the last 10 minutes
+ unsigned int uHot; // hot active users
+ unsigned int uHotOp; // hot operators
+ unsigned int uOp; // total operators
+ unsigned int uHalfOp; // total halfops
+ unsigned int uVoiced; // total voiced users
+ unsigned int uChanAdmin; // total channel administrators
+ unsigned int uChanOwner; // total channel owners
+ unsigned int uUserOp; // total userops (uops)
+ int iAvgTemperature; // average user temperature
+} KviUserListViewUserStats;
+
+
+class KVIRC_API KviUserListView : public KviWindowToolWidget
+{
+ friend class KviUserListEntry;
+ friend class KviUserListViewArea;
+ friend class KviUserListToolTip;
+ friend class KviConsole;
+ friend class KviChannel;
+ friend class KviQuery;
+ Q_OBJECT
+public:
+ KviUserListView(QWidget * parent,KviWindowToolPageButton* button,KviIrcUserDataBase * db,KviWindow * pWnd,int dictSize = 5,const QString &label_text = QString::null,const char * name = 0);
+ ~KviUserListView();
+protected:
+ KviPointerHashTable<QString,KviUserListEntry> * m_pEntryDict;
+ KviUserListEntry * m_pTopItem;
+ KviUserListEntry * m_pHeadItem;
+ KviUserListEntry * m_pTailItem;
+ KviUserListEntry * m_pIterator;
+ QLabel * m_pUsersLabel;
+ KviUserListViewArea * m_pViewArea;
+ KviIrcUserDataBase * m_pIrcUserDataBase;
+ int m_iSelectedCount;
+ int m_iOpCount;
+ int m_iVoiceCount;
+ int m_iHalfOpCount;
+ int m_iChanAdminCount;
+ int m_iChanOwnerCount;
+ int m_iUserOpCount;
+ int m_iTotalHeight;
+ int m_iFontHeight;
+ KviUserListToolTip * m_pToolTip;
+ int m_ibEntries;
+ int m_ieEntries;
+ int m_iIEntries;
+ KviWindow * m_pKviWindow;
+protected:
+ void maybeTip(KviUserListToolTip * tip,const QPoint &pnt);
+ void triggerUpdate();
+ void updateUsersLabel();
+ void insertUserEntry(const QString &nick,KviUserListEntry * e);
+ void removeAllEntries();
+ virtual void resizeEvent(QResizeEvent *);
+ bool partInternal(const QString &nick,bool bRemove = true);
+ void setUserDataBase(KviIrcUserDataBase * db){ m_pIrcUserDataBase = db; };
+ void updateScrollBarRange();
+public:
+ void updateArea();
+ void select(const QString&);
+ void applyOptions();
+ KviPointerHashTable<QString,KviUserListEntry> * entryDict(){ return m_pEntryDict; };
+ KviUserListEntry * firstItem(){ return m_pHeadItem; };
+ KviUserListEntry * itemAt(const QPoint &pnt,QRect * rct = 0);
+ bool itemVisible(KviUserListEntry * e);
+ KviWindow * window(){ return m_pKviWindow; };
+
+ unsigned int count(){ return m_pEntryDict->count(); };
+ int selectedCount(){ return m_iSelectedCount; };
+ int opCount(){ return m_iOpCount; };
+ int voiceCount(){ return m_iVoiceCount; };
+ int chanOwnerCount(){ return m_iChanOwnerCount; };
+ int chanAdminCount(){ return m_iChanAdminCount; };
+ int halfOpCount(){ return m_iHalfOpCount; };
+ int userOpCount(){ return m_iUserOpCount; };
+
+ KviUserListEntry * findEntry(const QString &nick){ return nick.isEmpty() ? 0 : m_pEntryDict->find(nick); };
+ void appendSelectedNicknames(QString &buffer);
+ QString * firstSelectedNickname();
+ QString * nextSelectedNickname();
+ void partAll();
+ void partAllButOne(const QString &whoNot);
+ void userStats(KviUserListViewUserStats * s);
+ int getUserModeLevel(const QString &nick);
+ kvi_time_t getUserJoinTime(const QString &nick);
+ kvi_time_t getUserLastActionTime(const QString &nick);
+ char getUserFlag(KviUserListEntry * e);
+ char getUserFlag(const QString &nick){ return getUserFlag(m_pEntryDict->find(nick)); };
+ bool part(const QString &nick){ return partInternal(nick,true); };
+ bool op(const QString &nick,bool bOp);
+ void prependUserFlag(const QString &nick,QString &buffer);
+ int flags(const QString &nick);
+ bool isOp(const QString &nick,bool bAtLeast = false);
+ bool isVoice(const QString &nick,bool bAtLeast = false);
+ bool isHalfOp(const QString &nick,bool bAtLeast = false);
+ bool isChanAdmin(const QString &nick,bool bAtLeast = false);
+ bool isChanOwner(const QString &nick,bool bAtLeast = false);
+ bool isUserOp(const QString &nick,bool bAtLeast = false);
+ bool voice(const QString &nick,bool bVoice);
+ bool setChanAdmin(const QString &nick,bool bChanAdmin);
+ bool setChanOwner(const QString &nick,bool bChanOwner);
+ bool halfop(const QString &nick,bool bHalfOp);
+ bool userop(const QString &nick,bool bUserOp);
+ void userAction(KviIrcMask *user,int actionTemperature);
+ bool userActionVerifyMask(const QString &nick,const QString &user,const QString &host,int actionTemperature,QString &oldUser,QString &oldHost);
+ void userAction(const QString &nick,const QString &user,const QString &host,int actionTemperature);
+ void userAction(const QString &nick,int actionTemperature);
+ bool nickChange(const QString &oldNick,const QString &newNick);
+ //KviUserListEntry * join(const char *nick,const char * user,const char * host,bool bOp,bool bVoice,bool bHalfOp);
+ KviUserListEntry * join(const QString &nick,const QString &user = QString::null,const QString &host = QString::null,int iFlags = 0);
+ bool avatarChanged(const QString &nick);
+ void enableUpdates(bool bEnable);
+ void setMaskEntries(char type, int num);
+ void emitRightClick();
+ void emitDoubleClick();
+ bool completeNickStandard(const QString &begin,const QString &skipAfter,QString &buffer,bool bAppendMask);
+ void completeNickBashLike(const QString &begin,KviPointerList<QString> * l,bool bAppendMask);
+};
+
+class KVIRC_API KviUserListViewArea : public QWidget
+{
+ friend class KviUserListView;
+
+ Q_OBJECT
+ Q_PROPERTY(int TransparencyCapable READ dummyRead)
+public:
+ KviUserListViewArea(KviUserListView * par);
+ ~KviUserListViewArea();
+public:
+ int dummyRead() const { return 0; };
+protected:
+ KviUserListView * m_pListView;
+ KviUserListEntry * m_pLastEntryUnderMouse;
+ QScrollBar * m_pScrollBar;
+ int m_iLastScrollBarVal;
+ int m_iTopItemOffset;
+ bool m_bIgnoreScrollBar;
+protected:
+ virtual void paintEvent(QPaintEvent *);
+ virtual void resizeEvent(QResizeEvent *);
+ virtual void mousePressEvent(QMouseEvent *e);
+ virtual void mouseMoveEvent(QMouseEvent *e);
+ virtual void mouseReleaseEvent(QMouseEvent *);
+ virtual void mouseDoubleClickEvent(QMouseEvent *e);
+ virtual void wheelEvent(QWheelEvent *e);
+ virtual void keyPressEvent( QKeyEvent * e );
+protected slots:
+ void scrollBarMoved(int newVal);
+};
+
+
+#endif //!_KVI_USERLISTVIEW_H_
diff --git a/src/kvirc/ui/kvi_window.cpp b/src/kvirc/ui/kvi_window.cpp
new file mode 100644
index 00000000..2cf64085
--- /dev/null
+++ b/src/kvirc/ui/kvi_window.cpp
@@ -0,0 +1,1518 @@
+//=============================================================================
+//
+// File : kvi_window.cpp
+// Creation date : Tue Jul 6 1999 14:52:11 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define __KVIRC__
+#define KVI_WINDOW_MIN_WIDTH 100
+#define KVI_WINDOW_MIN_HEIGHT 100
+
+#define _KVI_WINDOW_CPP_
+
+#define _KVI_DEBUG_CHECK_RANGE_
+
+#include "kvi_debug.h"
+#include "kvi_app.h"
+#include "kvi_window.h"
+#include "kvi_frame.h"
+#include "kvi_taskbar.h"
+#include "kvi_iconmanager.h"
+#include "kvi_mdichild.h"
+#include "kvi_locale.h"
+#include "kvi_ircview.h"
+#include "kvi_out.h"
+#include "kvi_malloc.h"
+#include "kvi_input.h"
+#include "kvi_fileutils.h"
+#include "kvi_options.h"
+#include "kvi_config.h"
+#include "kvi_irccontext.h"
+#include "kvi_console.h"
+#include "kvi_ircconnectionserverinfo.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_toolwindows_container.h"
+#include "kvi_styled_controls.h"
+#include "kvi_kvs_script.h"
+
+#include <qpixmap.h>
+#include "kvi_tal_popupmenu.h"
+#include <qcursor.h>
+#include <qtimer.h>
+#include <qsplitter.h>
+#include <qmetaobject.h>
+#include <qdatetime.h>
+#include <qtextcodec.h>
+#include <qevent.h>
+
+// it looks they can't decide :D
+#ifdef COMPILE_USE_QT4
+ #include <QPushButton>
+ #include <qdesktopwidget.h>
+#else
+ #include <qobjectlist.h>
+#endif
+
+
+#include <qvariant.h>
+#include <qtoolbutton.h>
+#include "kvi_tal_tooltip.h"
+#include <qmessagebox.h>
+
+#ifdef COMPILE_CRYPT_SUPPORT
+ #include "kvi_crypt.h"
+ #include "kvi_cryptcontroller.h"
+#endif
+
+#ifdef COMPILE_KDE_SUPPORT
+ #include <kwin.h>
+ #include <kdeversion.h>
+#endif
+
+#ifdef COMPILE_ON_WINDOWS
+ #include <windows.h>
+#endif
+
+KVIRC_API KviWindow * g_pActiveWindow = 0;
+
+static KviTalPopupMenu * g_pMdiWindowSystemMainPopup = 0;
+static KviTalPopupMenu * g_pMdiWindowSystemTextEncodingPopup = 0;
+static KviTalPopupMenu * g_pMdiWindowSystemTextEncodingPopupStandard = 0;
+static KviTalPopupMenu * g_pMdiWindowSystemTextEncodingPopupSmart = 0;
+static KviTalPopupMenu * g_pMdiWindowSystemTextEncodingPopupSmartUtf8 = 0;
+
+unsigned long int g_uUniqueWindowId = 1;
+
+// FIXME: #warning "Mouse wheel support"
+KviWindow::KviWindow(int type,KviFrame * lpFrm,const QString &name,KviConsole * lpConsole)
+ : QWidget(0)
+{
+ m_uId = g_uUniqueWindowId;
+ g_uUniqueWindowId++;
+
+
+ // FIXME: REMOVE THIS
+ setName(name);
+ // END FIXME
+ m_szName = name;
+
+ g_pApp->registerWindow(this);
+
+ m_iType = type;
+ m_pFocusHandler = 0;
+
+ m_pFrm = lpFrm; // FIXME: Should disappear!
+ m_pIrcView = 0;
+ m_pInput = 0;
+ m_pSplitter = 0;
+ m_pButtonBox = 0;
+ m_pConsole = lpConsole;
+ m_pContext = lpConsole ? lpConsole->context() : 0;
+ m_pLastFocusedChild = 0;
+ m_pTextCodec = 0; // will be set by loadProperties
+ m_pTextEncodingButton = 0;
+ m_pHideToolsButton = 0;
+// m_pEditorsContainer = 0;
+
+#ifdef COMPILE_CRYPT_SUPPORT
+
+ m_pCryptControllerButton = 0;
+ m_pCryptController = 0;
+ m_pCryptSessionInfo = 0;
+#endif
+
+ m_pAccel = 0;
+
+ m_pTaskBarItem = 0;
+
+ setMinimumSize(KVI_WINDOW_MIN_WIDTH,KVI_WINDOW_MIN_HEIGHT);
+#ifdef COMPILE_USE_QT4
+ //setAutoFillBackground(false);
+ setFocusPolicy(Qt::StrongFocus);
+#else
+ setBackgroundMode(NoBackground);
+ setFocusPolicy(StrongFocus);
+#endif
+
+ connect(g_pApp,SIGNAL(reloadImages()),this,SLOT(reloadImages()));
+}
+
+KviWindow::~KviWindow()
+{
+ //g_pFrame->childWindowDestroyed(this);
+ destroyTaskBarItem();
+ g_pApp->unregisterWindow(this);
+ if(g_pApp->windowCount() == 0)
+ {
+ // this is the last window!
+ if(g_pMdiWindowSystemMainPopup)
+ delete g_pMdiWindowSystemMainPopup;
+ if(g_pMdiWindowSystemTextEncodingPopup)
+ delete g_pMdiWindowSystemTextEncodingPopup;
+ if(g_pMdiWindowSystemTextEncodingPopupStandard)
+ delete g_pMdiWindowSystemTextEncodingPopupStandard;
+ if(g_pMdiWindowSystemTextEncodingPopupSmart)
+ delete g_pMdiWindowSystemTextEncodingPopupSmart;
+ if(g_pMdiWindowSystemTextEncodingPopupSmartUtf8)
+ delete g_pMdiWindowSystemTextEncodingPopupSmartUtf8;
+ }
+#ifdef COMPILE_CRYPT_SUPPORT
+ if(m_pCryptSessionInfo)
+ KviCryptController::destroyCryptSessionInfo(&m_pCryptSessionInfo);
+#endif
+}
+
+void KviWindow::setWindowName(const QString &szName)
+{
+ m_szName = szName;
+ emit windowNameChanged();
+}
+
+void KviWindow::toggleButtonContainer()
+{
+ QFrame *pContainer=buttonContainer();
+ if(pContainer)
+ {
+ pContainer->setHidden(!pContainer->isHidden());
+ }
+}
+
+void KviWindow::setName(const char * name)
+{
+ m_szName = name;
+ QWidget::setName(name);
+}
+
+KviIrcConnection * KviWindow::connection()
+{
+ return m_pContext ? m_pContext->connection() : 0;
+}
+
+void KviWindow::reloadImages()
+{
+ updateIcon();
+}
+
+bool KviWindow::hasAttention()
+{
+ if(((QApplication *)g_pApp)->activeWindow() == 0)return false; // no application window has the focus atm
+
+ if(mdiParent())
+ {
+ if(frame()->isActiveWindow())return true;
+ // This frame is not the active window but the
+ // active window still belongs to KVIrc.
+ // When the active window is derived from QDialog
+ // then it is probably a KVIrc's option dialog
+ // or something similar.
+ // In this case we assume that the user has the
+ // KVIrc window just below and can see it.
+
+ // Handle the special case of the dialogs then
+ QWidget * w = ((QApplication *)g_pApp)->activeWindow();
+ if(w->inherits("QDialog"))
+ {
+ // but make sure that the frame is visible at all!
+ if(!frame()->isVisible())return false;
+ return true;
+ }
+ // any other class is so unfrequent that we ignore it
+ } else {
+ // when the window is undocked, instead
+ // it is likely to be covered by KVIrc or other windows...
+ if(isActiveWindow())return true;
+ }
+ return false;
+}
+
+void KviWindow::demandAttention()
+{
+ if(mdiParent())
+ {
+ if(frame()->isActiveWindow())return;
+#ifdef COMPILE_ON_WINDOWS
+ FLASHWINFO fwi;
+ fwi.cbSize = sizeof(fwi);
+ fwi.hwnd = (HWND)(frame()->winId());
+ fwi.dwFlags = FLASHW_TRAY | FLASHW_TIMERNOFG;
+ fwi.uCount = 20;
+ fwi.dwTimeout = 500;
+ FlashWindowEx(&fwi);
+#else
+ #ifdef COMPILE_KDE_SUPPORT
+ #if (KDE_VERSION_MAJOR >= 3) && (KDE_VERSION_MINOR >= 2)
+ KWin::demandAttention(frame()->winId(),true);
+ #endif
+ #endif
+#endif
+ } else {
+ if(isActiveWindow())return;
+#ifdef COMPILE_ON_WINDOWS
+ FLASHWINFO fwi;
+ fwi.cbSize = sizeof(fwi);
+ fwi.hwnd = (HWND)winId();
+ fwi.dwFlags = FLASHW_TRAY | FLASHW_TIMERNOFG;
+ fwi.uCount = 20;
+ fwi.dwTimeout = 500;
+ FlashWindowEx(&fwi);
+#else
+ #ifdef COMPILE_KDE_SUPPORT
+ #if (KDE_VERSION_MAJOR >= 3) && (KDE_VERSION_MINOR >= 2)
+ KWin::demandAttention(winId(),true);
+ #endif
+ #endif
+#endif
+ }
+}
+
+bool KviWindow::focusNextPrevChild(bool next)
+{
+ QWidget * w = focusWidget();
+ if(w)
+ {
+#ifdef COMPILE_USE_QT4
+ if(w->focusPolicy() == Qt::StrongFocus)return false;
+#else
+ if(w->focusPolicy() == QWidget::StrongFocus)return false;
+#endif
+ //QVariant v = w->property("KviProperty_FocusOwner");
+ //if(v.isValid())return false; // Do NOT change the focus widget!
+
+ if(w->parent())
+ {
+#ifdef COMPILE_USE_QT4
+ if(w->parent()->metaObject()->indexOfProperty("KviProperty_ChildFocusOwner") == -1)
+#else
+ if(w->parent()->metaObject()->findProperty("KviProperty_ChildFocusOwner") == -1)
+#endif
+ return false; // Do NOT change the focus widget!
+ }
+ }
+
+ return QWidget::focusNextPrevChild(next);
+}
+
+void KviWindow::forceTextCodec(QTextCodec * c)
+{
+ if(!c)return;
+ m_pTextCodec = c;
+ QTextCodec * dc = defaultTextCodec();
+ if(dc != c)
+ m_szTextEncoding = c->name();
+ else
+ m_szTextEncoding = ""; // this is the default anyway
+}
+
+bool KviWindow::setTextEncoding(const QString &szTextEncoding)
+{
+ if(!szTextEncoding.isEmpty())
+ {
+ m_pTextCodec = KviLocale::codecForName(szTextEncoding.latin1());
+ if(m_pTextCodec)
+ {
+ m_szTextEncoding = szTextEncoding;
+ return true;
+ }
+ // this is an error because we specified an encoding
+ // and we couldn't find a codec for this
+ } // else it is empty : this means : guess from locale
+ // either empty or not found...
+ m_pTextCodec = 0;
+ m_szTextEncoding = ""; // empty: we're using the default
+ return false;
+}
+
+QTextCodec * KviWindow::defaultTextCodec()
+{
+ // if we have a connection try to inherit from there...
+ if(connection())
+ {
+ QTextCodec * c = connection()->textCodec();
+ if(c)return c;
+ }
+ return KviApp::defaultTextCodec();
+}
+
+KviQCString KviWindow::encodeText(const QString &szText)
+{
+ if(!m_pTextCodec)return defaultTextCodec()->fromUnicode(szText);
+ return m_pTextCodec->fromUnicode(szText);
+}
+
+QString KviWindow::decodeText(const char * szText)
+{
+ if(!m_pTextCodec)return defaultTextCodec()->toUnicode(szText);
+ return m_pTextCodec->toUnicode(szText);
+}
+
+bool KviWindow::activityMeter(unsigned int *,unsigned int *)
+{
+ return false;
+}
+
+
+const char * KviWindow::m_typeTable[KVI_WINDOW_NUM_TYPES + 1]=
+{
+ "console",
+ "channel",
+ "query",
+ "help",
+ "terminal",
+ "editor",
+ "dccchat",
+ "dccsend",
+ "socketspy",
+ "links",
+ "tool",
+ "gnutella",
+ "dirbrowser",
+ "dcccanvas",
+ "dccvoice",
+ "list",
+ "offer",
+ "logview",
+ "deadchannel",
+ "deadquery",
+ "scripteditor",
+ "scriptobject",
+ "userwindow",
+ "debug",
+ // <------ NEW TYPES GO HERE!
+ "unknown"
+};
+
+const char * KviWindow::typeString()
+{
+ if(m_iType < KVI_WINDOW_NUM_TYPES)
+ {
+ return m_typeTable[m_iType];
+ }
+ return m_typeTable[KVI_WINDOW_NUM_TYPES];
+}
+
+void KviWindow::setType(int iType)
+{
+ m_iType = iType;
+}
+
+
+void KviWindow::createTaskBarItem()
+{
+ if(m_pTaskBarItem)return;
+ m_pTaskBarItem = g_pFrame->m_pTaskBar->addItem(this);
+}
+
+void KviWindow::destroyTaskBarItem()
+{
+ if(!m_pTaskBarItem)return;
+ g_pFrame->m_pTaskBar->removeItem(m_pTaskBarItem);
+ // m_pTaskBarItem = 0; // actually the taskBarItem destructor sets it
+}
+
+BUTTON_CLASS * KviWindow::createToolButton(QWidget * par,const char * nam,int pixon,int pixoff,const QString & tooltip,bool bOn)
+{
+#ifdef COMPILE_USE_QT4
+ BUTTON_CLASS * b = new BUTTON_CLASS(par);
+ b->setObjectName(nam);
+ b->setFlat(true);
+ b->setIcon(QIcon(*(g_pIconManager->getSmallIcon(pixon))));
+#else
+ BUTTON_CLASS * b = new BUTTON_CLASS(par,nam);
+ b->setToggleButton(true);
+ b->setUsesBigPixmap(false);
+ QIconSet is1;
+ is1.setPixmap(*(g_pIconManager->getSmallIcon(pixon)),QIconSet::Small,QIconSet::Normal,QIconSet::On);
+ is1.setPixmap(*(g_pIconManager->getSmallIcon(pixoff)),QIconSet::Small,QIconSet::Normal,QIconSet::Off);
+ b->setIconSet(is1);
+#endif
+
+
+ KviTalToolTip::add
+ (b,tooltip);
+ b->setOn(bOn);
+ return b;
+}
+
+// This is always defined...
+void KviWindow::createCryptControllerButton(QWidget * par)
+{
+#ifdef COMPILE_CRYPT_SUPPORT
+ m_pCryptControllerButton = new KviWindowToolPageButton(KVI_SMALLICON_UNLOCKEDOFF,KVI_SMALLICON_UNLOCKED,__tr2qs("Crypting"),buttonContainer(),false,"crypt_controller_button");
+ connect(m_pCryptControllerButton,SIGNAL(clicked()),this,SLOT(toggleCryptController()));
+#endif // COMPILE_CRYPT_SUPPORT
+}
+
+void KviWindow::createTextEncodingButton(QWidget * par)
+{
+ if(m_pTextEncodingButton)delete m_pTextEncodingButton;
+ m_pTextEncodingButton = createToolButton(par,"text_encoding_button",KVI_SMALLICON_TEXTENCODING,KVI_SMALLICON_TEXTENCODING,__tr2qs("Private Text Encoding"),false);
+ connect(m_pTextEncodingButton,SIGNAL(clicked()),this,SLOT(textEncodingButtonClicked()));
+}
+
+void KviWindow::textEncodingButtonClicked()
+{
+ createSystemTextEncodingPopup();
+ g_pMdiWindowSystemTextEncodingPopup->popup(m_pTextEncodingButton->mapToGlobal(QPoint(0,m_pTextEncodingButton->height())));
+ m_pTextEncodingButton->setOn(false);
+}
+
+const QString & KviWindow::lastLineOfText()
+{
+ if(m_pIrcView)
+ return m_pIrcView->lastLineOfText();
+ return KviQString::empty;
+}
+
+const QString & KviWindow::lastMessageText()
+{
+ if(m_pIrcView)
+ return m_pIrcView->lastMessageText();
+ return KviQString::empty;
+}
+
+// The following three have to be here even if the crypt support is disabled...moc does not support conditional compilations
+void KviWindow::toggleCryptController()
+{
+#ifdef COMPILE_CRYPT_SUPPORT
+ if(!m_pCryptControllerButton->isOn())
+ {
+ if(m_pCryptController)
+ {
+ delete m_pCryptController;
+ m_pCryptController = 0;
+ if(!m_pCryptControllerButton)
+ return;
+ if(m_pCryptControllerButton->isOn())
+ m_pCryptControllerButton->setOn(false);
+ }
+ } else {
+ if(m_pSplitter && m_pInput)
+ {
+ m_pCryptController = new KviCryptController(m_pSplitter,m_pCryptControllerButton,"crypt_controller",this,m_pCryptSessionInfo);
+ connect(m_pCryptController,SIGNAL(done()),this,SLOT(cryptControllerFinished()));
+ //setFocusHandlerNoClass(m_pInput,m_pCryptController,"QLineEdit"); //link it!
+ m_pCryptController->show();
+ if(!m_pCryptControllerButton)
+ return;
+ if(!(m_pCryptControllerButton->isOn()))
+ m_pCryptControllerButton->setOn(true);
+ }
+ }
+#endif // COMPILE_CRYPT_SUPPORT
+}
+
+#ifdef COMPILE_CRYPT_SUPPORT
+void KviWindow::setCryptSessionInfo(KviCryptSessionInfo * inf)
+{
+ if(m_pCryptSessionInfo)
+ KviCryptController::destroyCryptSessionInfo(&m_pCryptSessionInfo);
+ m_pCryptSessionInfo = inf;
+ if(m_pCryptSessionInfo)
+ {
+ connect(m_pCryptSessionInfo->pEngine,SIGNAL(destroyed()),this,SLOT(cryptSessionInfoDestroyed()));
+ }
+ if(m_pCryptControllerButton)
+ {
+#if QT_VERSION >= 300
+ QIconSet is;
+ is.setPixmap(*(g_pIconManager->getSmallIcon(m_pCryptSessionInfo ? KVI_SMALLICON_LOCKEDOFF : KVI_SMALLICON_UNLOCKEDOFF)),QIconSet::Small,QIconSet::Normal,QIconSet::Off);
+ is.setPixmap(*(g_pIconManager->getSmallIcon(m_pCryptSessionInfo ? KVI_SMALLICON_LOCKED : KVI_SMALLICON_UNLOCKED)),QIconSet::Small,QIconSet::Normal,QIconSet::On);
+ m_pCryptControllerButton->setIconSet(is);
+#else
+
+ m_pCryptControllerButton->setOnIconSet(
+ *(g_pIconManager->getSmallIcon(m_pCryptSessionInfo ? KVI_SMALLICON_LOCKEDOFF : KVI_SMALLICON_UNLOCKEDOFF)));
+ m_pCryptControllerButton->setOffIconSet(
+ *(g_pIconManager->getSmallIcon(m_pCryptSessionInfo ? KVI_SMALLICON_LOCKED : KVI_SMALLICON_UNLOCKED)));
+#endif
+
+ if(m_pCryptControllerButton->isOn())
+ m_pCryptControllerButton->setOn(false);
+ }
+}
+#endif // COMPILE_CRYPT_SUPPORT
+
+void KviWindow::cryptControllerFinished()
+{
+#ifdef COMPILE_CRYPT_SUPPORT
+ KviCryptSessionInfo * inf = m_pCryptController->getNewSessionInfo();
+ setCryptSessionInfo(inf);
+ delete m_pCryptController;
+ m_pCryptController = 0;
+#endif
+}
+
+void KviWindow::cryptSessionInfoDestroyed()
+{
+#ifdef COMPILE_CRYPT_SUPPORT
+ output(KVI_OUT_SYSTEMERROR,__tr2qs("Ops...I've accidentally lost the crypting engine..."));
+ m_pCryptSessionInfo->pEngine = 0;
+ delete m_pCryptSessionInfo;
+ m_pCryptSessionInfo = 0;
+#endif
+}
+
+
+
+void KviWindow::setProgress(int progress)
+{
+ m_pTaskBarItem->setProgress(progress);
+}
+
+void KviWindow::listWindowTypes()
+{
+ outputNoFmt(KVI_OUT_SYSTEMMESSAGE,__tr2qs("List of window types available in this release of KVIrc:"));
+ for(int i=0;i< KVI_WINDOW_NUM_TYPES;i++)
+ outputNoFmt(KVI_OUT_SYSTEMMESSAGE,m_typeTable[i]);
+}
+
+void KviWindow::getConfigGroupName(QString &buf)
+{
+ buf = typeString();
+}
+
+
+void KviWindow::getDefaultLogFileName(QString &buffer)
+{
+ // FIXME: #warning "Make it configurable ?"
+ QString date;
+ QDate dt(QDate::currentDate());
+ date=dt.toString("yyyy.MM.dd");
+ QString base;
+ getBaseLogFileName(base);
+ kvi_encodeFileName(base);
+ base.replace("%%2e","%2e");
+ base=base.lower();
+ QString tmp;
+ if(KVI_OPTION_BOOL(KviOption_boolGzipLogs))
+ KviQString::sprintf(tmp,"%s_%s_%s.log.gz",typeString(),base.utf8().data(),date.utf8().data());
+ else
+ KviQString::sprintf(tmp,"%s_%s_%s.log",typeString(),base.utf8().data(),date.utf8().data());
+ g_pApp->getLocalKvircDirectory(buffer,KviApp::Log,tmp);
+}
+
+/*void KviWindow::getBaseLogFileName(KviStr &buffer)
+{
+ buffer = m_szName;
+}*/
+
+void KviWindow::getBaseLogFileName(QString &buffer)
+{
+ buffer = m_szName;
+}
+
+
+void KviWindow::saveProperties(KviConfig *cfg)
+{
+ // store only the non-default text encoding.
+ QString szCodec = m_szTextEncoding;
+ QTextCodec * c = defaultTextCodec();
+ if(c && m_pTextCodec)
+ {
+#ifdef COMPILE_USE_QT4
+ if(KviQString::equalCI(szCodec,c->name().data()))szCodec = KviQString::empty; // store "default"
+#else
+ if(KviQString::equalCI(szCodec,c->name()))szCodec = KviQString::empty; // store "default"
+#endif
+ }
+ QString szKey = "TextEncoding_";
+ szKey += m_szName;
+ cfg->writeEntry(szKey,szCodec);
+ if(m_pInput) {
+ cfg->writeEntry("inputToolButtonsHidden",m_pInput->isButtonsHidden());
+ cfg->writeEntry("commandLineIsUserFriendly",m_pInput->isUserFriendly());
+ }
+
+ //
+
+ /*if(m_pIrcView && m_iType==KVI_WINDOW_TYPE_CHANNEL)
+ if(m_pIrcView->isLogging())
+ cfg->writeEntry("LoggingEnabled",m_pIrcView->isLogging());*/
+}
+
+void KviWindow::loadProperties(KviConfig *cfg)
+{
+ QString szKey = "TextEncoding_";
+ szKey += m_szName;
+ setTextEncoding(cfg->readQStringEntry(szKey,KviQString::empty).utf8().data());
+ if(m_pInput) {
+ m_pInput->setButtonsHidden(cfg->readBoolEntry("inputToolButtonsHidden",KVI_OPTION_BOOL(KviOption_boolHideInputToolButtons)));
+ m_pInput->setUserFriendly(cfg->readBoolEntry("commandLineIsUserFriendly",KVI_OPTION_BOOL(KviOption_boolCommandlineInUserFriendlyModeByDefault)));
+ }
+/* if(m_pIrcView && m_iType==KVI_WINDOW_TYPE_CHANNEL)
+ {
+ bool bEnableLogs=cfg->readBoolEntry("LoggingEnabled",0);
+ if(!m_pIrcView->isLogging() && bEnableLogs)
+ {
+ QString szTmp;
+ getBaseLogFileName(szTmp);
+ m_pIrcView->startLogging();
+ }
+ }*/
+}
+
+QPixmap * KviWindow::myIconPtr()
+{
+ return g_pIconManager->getSmallIcon(KVI_SMALLICON_DEFAULTICON);
+}
+
+void KviWindow::getTaskBarTipText(QString &buffer)
+{
+ buffer = m_szPlainTextCaption;
+}
+
+void KviWindow::setFixedCaption(const QString &szCaption)
+{
+ m_szPlainTextCaption = szCaption;
+}
+
+void KviWindow::fillCaptionBuffers()
+{
+ QString szCaption = m_szPlainTextCaption;
+ if(szCaption.isEmpty())
+ szCaption = m_szName;
+
+ fillSingleColorCaptionBuffers(szCaption);
+}
+
+void KviWindow::fillSingleColorCaptionBuffers(const QString &szName)
+{
+ static QString p1("<nobr><font color=\"");
+ static QString p2("\"><b>");
+ static QString p3("</b></font></nobr>");
+
+ m_szPlainTextCaption = szName;
+
+ m_szHtmlActiveCaption = p1;
+ m_szHtmlActiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextActive).name();
+ m_szHtmlActiveCaption += p2;
+ m_szHtmlActiveCaption += szName;
+ m_szHtmlActiveCaption += p3;
+
+ m_szHtmlInactiveCaption = p1;
+ m_szHtmlInactiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextInactive).name();
+ m_szHtmlInactiveCaption += p2;
+ m_szHtmlInactiveCaption += szName;
+ m_szHtmlInactiveCaption += p3;
+}
+
+void KviWindow::updateCaption()
+{
+ fillCaptionBuffers();
+ if(mdiParent())
+ mdiParent()->setCaption(plainTextCaption(),htmlActiveCaption(),htmlInactiveCaption());
+ else
+ setCaption(plainTextCaption());
+ if(m_pTaskBarItem)m_pTaskBarItem->captionChanged();
+ if(mdiParent() && isMaximized() && (g_pActiveWindow == this))
+ g_pFrame->updateCaption();
+}
+
+void KviWindow::createSystemTextEncodingPopup()
+{
+ if(!g_pMdiWindowSystemTextEncodingPopup)
+ g_pMdiWindowSystemTextEncodingPopup = new KviTalPopupMenu();
+ else
+ {
+ g_pMdiWindowSystemTextEncodingPopup->clear();
+ }
+
+ if(!g_pMdiWindowSystemTextEncodingPopupStandard)
+ g_pMdiWindowSystemTextEncodingPopupStandard = new KviTalPopupMenu();
+ else
+ {
+ g_pMdiWindowSystemTextEncodingPopupStandard->clear();
+ disconnect(g_pMdiWindowSystemTextEncodingPopupStandard,SIGNAL(activated(int)),0,0);
+ }
+
+ if(!g_pMdiWindowSystemTextEncodingPopupSmart)
+ g_pMdiWindowSystemTextEncodingPopupSmart = new KviTalPopupMenu();
+ else
+ {
+ g_pMdiWindowSystemTextEncodingPopupSmart->clear();
+ disconnect(g_pMdiWindowSystemTextEncodingPopupSmart,SIGNAL(activated(int)),0,0);
+ }
+
+ if(!g_pMdiWindowSystemTextEncodingPopupSmartUtf8)
+ g_pMdiWindowSystemTextEncodingPopupSmartUtf8 = new KviTalPopupMenu();
+ else
+ {
+ g_pMdiWindowSystemTextEncodingPopupSmartUtf8->clear();
+ disconnect(g_pMdiWindowSystemTextEncodingPopupSmartUtf8,SIGNAL(activated(int)),0,0);
+ }
+
+ QTextCodec * c = defaultTextCodec();
+ QString tmp = __tr2qs("Use Default Encoding");
+ if(c)
+ {
+ tmp += " (";
+ tmp += c->name();
+ tmp += ")";
+ }
+
+ int id = g_pMdiWindowSystemTextEncodingPopup->insertItem(tmp,this,SLOT(systemTextEncodingPopupDefault()));
+ if(m_szTextEncoding.isEmpty())g_pMdiWindowSystemTextEncodingPopup->setItemChecked(id,true);
+ g_pMdiWindowSystemTextEncodingPopup->insertSeparator();
+
+ g_pMdiWindowSystemTextEncodingPopup->insertItem(__tr2qs("Standard"),g_pMdiWindowSystemTextEncodingPopupStandard);
+ g_pMdiWindowSystemTextEncodingPopup->insertItem(__tr2qs("Smart (Send Local)"),g_pMdiWindowSystemTextEncodingPopupSmart);
+ g_pMdiWindowSystemTextEncodingPopup->insertItem(__tr2qs("Smart (Send UTF-8)"),g_pMdiWindowSystemTextEncodingPopupSmartUtf8);
+
+ int i = 0;
+ KviLocale::EncodingDescription * d = KviLocale::encodingDescription(i);
+ while(d->szName)
+ {
+ KviQString::sprintf(tmp,"%s (%s)",d->szName,d->szDescription);
+ KviTalPopupMenu * ppp = d->bSmart ? (d->bSendUtf8 ? g_pMdiWindowSystemTextEncodingPopupSmartUtf8 : g_pMdiWindowSystemTextEncodingPopupSmart) : g_pMdiWindowSystemTextEncodingPopupStandard;
+ id = ppp->insertItem(tmp);
+ if(KviQString::equalCI(m_szTextEncoding,d->szName))
+ ppp->setItemChecked(id,true);
+ i = i + 1;
+ d = KviLocale::encodingDescription(i);
+ }
+
+ connect(g_pMdiWindowSystemTextEncodingPopupSmart,SIGNAL(activated(int)),this,SLOT(systemTextEncodingPopupSmartActivated(int)));
+ connect(g_pMdiWindowSystemTextEncodingPopupSmartUtf8,SIGNAL(activated(int)),this,SLOT(systemTextEncodingPopupSmartUtf8Activated(int)));
+ connect(g_pMdiWindowSystemTextEncodingPopupStandard,SIGNAL(activated(int)),this,SLOT(systemTextEncodingPopupStandardActivated(int)));
+}
+
+
+void KviWindow::systemPopupRequest(const QPoint &pnt)
+{
+ if(!g_pMdiWindowSystemMainPopup)
+ g_pMdiWindowSystemMainPopup = new KviTalPopupMenu();
+ else
+ {
+ g_pMdiWindowSystemMainPopup->clear();
+ g_pMdiWindowSystemMainPopup->disconnect();
+ }
+
+ if(mdiParent())
+ g_pMdiWindowSystemMainPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_UNDOCK)),
+ __tr2qs("&Undock"),this,SLOT(undock()));
+ else
+ g_pMdiWindowSystemMainPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_DOCK)),
+ __tr2qs("&Dock"),this,SLOT(dock()));
+
+ g_pMdiWindowSystemMainPopup->insertSeparator();
+
+ int id = g_pMdiWindowSystemMainPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_MINIMIZE)),
+ __tr2qs("Mi&nimize"),this,SLOT(minimize()));
+ g_pMdiWindowSystemMainPopup->setItemEnabled(id,!isMinimized());
+ id = g_pMdiWindowSystemMainPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_MAXIMIZE)),
+ __tr2qs("Ma&ximize"),this,SLOT(maximize()));
+ g_pMdiWindowSystemMainPopup->setItemEnabled(id,!isMaximized());
+ id = g_pMdiWindowSystemMainPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_RESTORE)),
+ __tr2qs("&Restore"),this,SLOT(restore()));
+ g_pMdiWindowSystemMainPopup->setItemEnabled(id,isMinimized()||isMaximized());
+
+ g_pMdiWindowSystemMainPopup->insertSeparator();
+
+ g_pMdiWindowSystemMainPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CLOSE)),
+ __tr2qs("Close"),this,SLOT(close()));
+
+ g_pMdiWindowSystemMainPopup->insertSeparator();
+
+ if(m_pTextEncodingButton)
+ {
+ createSystemTextEncodingPopup();
+ g_pMdiWindowSystemMainPopup->insertItem(__tr2qs("Text &Encoding"),g_pMdiWindowSystemTextEncodingPopup);
+ } // else we don't support setting private encoding anyway
+
+
+ g_pMdiWindowSystemMainPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_XY)),
+ __tr2qs("Sa&ve Window Properties"),this,SLOT(savePropertiesAsDefault()));
+
+ fillContextPopup(g_pMdiWindowSystemMainPopup);
+
+ g_pMdiWindowSystemMainPopup->popup(pnt);
+}
+
+void KviWindow::systemTextEncodingPopupDefault()
+{
+ // default
+ setTextEncoding("");
+}
+
+void KviWindow::systemTextEncodingPopupSmartActivated(int id)
+{
+ if(!g_pMdiWindowSystemTextEncodingPopupSmart)
+ return;
+ QString tmp = g_pMdiWindowSystemTextEncodingPopupSmart->text(id);
+ KviQString::cutFromFirst(tmp," (");
+ setTextEncoding(tmp);
+}
+
+void KviWindow::systemTextEncodingPopupSmartUtf8Activated(int id)
+{
+ if(!g_pMdiWindowSystemTextEncodingPopupSmartUtf8)
+ return;
+ QString tmp = g_pMdiWindowSystemTextEncodingPopupSmartUtf8->text(id);
+ KviQString::cutFromFirst(tmp," (");
+ setTextEncoding(tmp);
+}
+
+void KviWindow::systemTextEncodingPopupStandardActivated(int id)
+{
+ if(!g_pMdiWindowSystemTextEncodingPopupStandard)
+ return;
+ QString tmp = g_pMdiWindowSystemTextEncodingPopupStandard->text(id);
+ KviQString::cutFromFirst(tmp," (");
+ setTextEncoding(tmp);
+}
+
+void KviWindow::savePropertiesAsDefault()
+{
+ QString group;
+ getConfigGroupName(group);
+
+ if(!kvi_strEqualCI(group,typeString()))
+ {
+ // save also the settings for THIS specialized window
+ g_pFrame->saveWindowProperties(this,group);
+ }
+
+ g_pFrame->saveWindowProperties(this,typeString());
+}
+
+void KviWindow::contextPopup()
+{
+ systemPopupRequest(QCursor::pos());
+}
+
+void KviWindow::fillContextPopup(KviTalPopupMenu *)
+{
+ // nothing here
+}
+
+void KviWindow::undock()
+{
+ g_pFrame->undockWindow(this);
+}
+
+void KviWindow::dock()
+{
+ g_pFrame->dockWindow(this);
+}
+
+void KviWindow::delayedAutoRaise()
+{
+ QTimer::singleShot(0,this,SLOT(autoRaise()));
+}
+
+void KviWindow::autoRaise()
+{
+ if(!mdiParent())
+ {
+ raise();
+ setActiveWindow();
+ }
+ if(m_pFocusHandler)
+ m_pFocusHandler->setFocus();
+ else
+ setFocus();
+}
+
+void KviWindow::delayedClose()
+{
+ QTimer::singleShot(0,this,SLOT(close()));
+}
+
+void KviWindow::closeEvent(QCloseEvent *e)
+{
+ e->ignore();
+ g_pFrame->childWindowCloseRequest(this);
+}
+
+void KviWindow::updateIcon()
+{
+ if(parent())
+ {
+ ((KviMdiChild *)parent())->setIcon(*myIconPtr());
+ } else {
+ setIcon(*myIconPtr());
+ }
+}
+
+void KviWindow::youAreDocked()
+{
+ if(m_pAccel)
+ {
+ delete m_pAccel;
+ m_pAccel = 0;
+ }
+ ((KviMdiChild *)parent())->setIcon(*myIconPtr());
+ updateCaption();
+ connect(((KviMdiChild *)parent()),SIGNAL(systemPopupRequest(const QPoint &)),this,SLOT(systemPopupRequest(const QPoint &)));
+}
+
+void KviWindow::youAreUndocked()
+{
+ m_pAccel = g_pFrame->installAccelerators(this);
+ setIcon(*myIconPtr());
+ updateCaption();
+}
+
+#ifdef FocusIn
+// Hack for X.h
+#undef FocusIn
+#endif
+
+void KviWindow::activateSelf()
+{
+ if(mdiParent())
+ mdiParent()->activate(false);
+
+ g_pFrame->childWindowActivated(this);
+ // this is now done by KviFrame in childWindowActivated
+ //g_pFrame->m_pTaskBar->setActiveItem(m_pTaskBarItem);
+}
+
+void KviWindow::setFocus()
+{
+ // don't trigger the whole Qt focus mechanism..
+ // just trigger directly our focusInEvent
+ // so we'll redirect the focus to the m_pFocusHandler
+ focusInEvent(0);
+}
+
+void KviWindow::focusInEvent(QFocusEvent *)
+{
+ if(m_pLastFocusedChild)
+ {
+ if(m_pLastFocusedChild->hasFocus() && m_pLastFocusedChild->isVisible())
+ {
+ // the last focused child still has focus (ehm ???)
+ if(g_pActiveWindow != this)activateSelf();
+ return;
+ }
+ }
+
+ if(!m_pFocusHandler)
+ {
+ // must find one NOW
+ // we probably have no KviInput since it would have been grabbed anyway
+
+ if(m_pIrcView)m_pFocusHandler = m_pIrcView;
+ else {
+#ifdef COMPILE_USE_QT4
+ QList<QObject *> list = children();
+ for(QList<QObject *>::Iterator it = list.begin();it != list.end();++it)
+ {
+ QObject * c = *it;
+ if(c->isWidgetType())
+ {
+ m_pFocusHandler = (QWidget *)c;
+ break;
+ }
+ }
+#else
+ QObjectList *list = (QObjectList *)(children());
+ if(list)
+ {
+ for(QObject * c = list->first();c;c = list->next())
+ {
+ if(c->isWidgetType())
+ {
+ m_pFocusHandler = (QWidget *)c;
+ break;
+ }
+ }
+ }
+#endif
+ }
+ if(m_pFocusHandler)m_pFocusHandler->setFocus();
+ else {
+ // else too bad :/
+ debug("No widget able to handle focus for window %s",name());
+ return;
+ }
+ } else {
+ m_pFocusHandler->setFocus();
+ }
+
+ // Setting the focus to the focus handler usually
+ // triggers our filter for the children's focusInEvent.
+ // This should call activateSelf() and thus
+ // we should be already the active window at this point.
+ // If we're not, then run activateSelf() to fix this.
+ if(g_pActiveWindow != this)activateSelf();
+ //else debug("ACTIVE WINDOW IS ALREADY THIS");
+ updateCaption();
+}
+
+bool KviWindow::eventFilter(QObject *o,QEvent *e)
+{
+ switch(e->type())
+ {
+ case QEvent::FocusIn:
+ m_pLastFocusedChild = (QWidget *)o;
+ if(g_pActiveWindow != this)activateSelf();
+ break;
+ case QEvent::Enter:
+ // this is a handler moved here from KviMdiChild::eventFilter
+ if(QApplication::overrideCursor())
+ QApplication::restoreOverrideCursor();
+ break;
+ case QEvent::MouseButtonPress:
+#ifdef COMPILE_USE_QT4
+ if( (((QWidget *)o)->focusPolicy() == Qt::NoFocus) ||
+ (((QWidget *)o)->focusPolicy() == Qt::TabFocus))
+#else
+ if( (((QWidget *)o)->focusPolicy() == QWidget::NoFocus) ||
+ (((QWidget *)o)->focusPolicy() == QWidget::TabFocus))
+#endif
+ {
+ // this will not focus our window
+ // set the focus to the focus handler
+ if(m_pLastFocusedChild)
+ {
+ if(m_pLastFocusedChild->hasFocus() && m_pLastFocusedChild->isVisible())
+ return false;
+ }
+
+ if(m_pFocusHandler)
+ {
+ m_pFocusHandler->setFocus();
+ } else {
+ setFocus(); // we grab the focus (someone must do it , damn :D)
+ }
+ }
+ break;
+ case QEvent::ChildInserted:
+ if(((QChildEvent *)e)->child()->isWidgetType())
+ childInserted((QWidget *)((QChildEvent *)e)->child());
+ break;
+ case QEvent::ChildRemoved:
+ if(((QChildEvent *)e)->child()->isWidgetType())
+ childRemoved((QWidget *)((QChildEvent *)e)->child());
+ break;
+ default: /* make gcc happy */ break;
+ }
+ return false;
+}
+
+
+void KviWindow::childInserted(QWidget * o)
+{
+ o->removeEventFilter(this); // ensure that we don't filter twice
+ o->installEventFilter(this); // we filter its events
+ connect(o,SIGNAL(destroyed()),this,SLOT(childDestroyed()));
+
+ if(o->inherits("KviInput"))
+ m_pFocusHandler = o;
+ else
+ {
+#ifdef COMPILE_USE_QT4
+ if(!m_pFocusHandler && (o->focusPolicy() == Qt::StrongFocus))
+#else
+ if(!m_pFocusHandler && (o->focusPolicy() == QWidget::StrongFocus))
+#endif
+ {
+ m_pFocusHandler = o;
+ }
+ }
+
+#ifdef COMPILE_USE_QT4
+ QList<QObject *> list = o->children();
+ for(QList<QObject *>::Iterator it = list.begin();it != list.end();++it)
+ {
+ QObject * c = *it;
+ if(c->isWidgetType())
+ {
+ childInserted((QWidget *)c);
+ }
+ }
+#else
+ QObjectList *list = (QObjectList *)(o->children());
+ if(list)
+ {
+ for(QObject * c = list->first();c;c = list->next())
+ {
+ if(c->isWidgetType())
+ childInserted((QWidget *)c);
+ }
+ }
+#endif
+}
+
+void KviWindow::childDestroyed()
+{
+ QWidget * s = (QWidget *)sender();
+ childRemoved(s);
+}
+
+void KviWindow::childRemoved(QWidget * o)
+{
+ //debug("CHILD REMOVED %d",o);
+ o->removeEventFilter(this);
+ if(o == m_pFocusHandler)
+ m_pFocusHandler = 0;
+ if(o == m_pLastFocusedChild)
+ m_pLastFocusedChild = 0;
+
+#ifdef COMPILE_USE_QT4
+ QList<QObject *> list = o->children();
+ for(QList<QObject *>::Iterator it = list.begin();it != list.end();++it)
+ {
+ QObject * c = *it;
+ if(c->isWidgetType())
+ {
+ childRemoved((QWidget *)c);
+ }
+ }
+#else
+ QObjectList *list = (QObjectList *)(o->children());
+ if(list)
+ {
+ for(QObject * c = list->first();c;c = list->next())
+ {
+ if(c->isWidgetType())
+ childRemoved((QWidget *)c);
+ }
+ } //else debug("The removed object has no children");
+#endif
+}
+
+void KviWindow::childEvent(QChildEvent *e)
+{
+ if(e->child()->isWidgetType())
+ {
+ if(e->removed())
+ childRemoved((QWidget *)(e->child()));
+ else
+ childInserted((QWidget *)(e->child()));
+ }
+ QWidget::childEvent(e);
+}
+
+void KviWindow::wheelEvent(QWheelEvent *e)
+{
+ /* NOTHING HERE FOR NOW (FIXME) */
+}
+
+
+void KviWindow::childrenTreeChanged(QWidget * widgetAdded)
+{
+ // if(widgetAdded && m_pFocusHandler)setFocusHandler(m_pFocusHandler,widgetAdded);
+ // FIXME: This might be useless
+ QResizeEvent * e = new QResizeEvent(size(),size());
+ resizeEvent(e);
+ delete e;
+}
+
+
+void KviWindow::updateBackgrounds(QObject * obj)
+{
+ if(!obj)
+ obj = this;
+#ifdef COMPILE_USE_QT4
+ QList<QObject *> list = obj->children();
+ if (list.count())
+ {
+
+ for(QList<QObject *>::Iterator it = list.begin();it != list.end();++it)
+ {
+ QObject * child = *it;
+ if(child->metaObject()->indexOfProperty("TransparencyCapable") != -1){
+ // if (child->isWidgetType())
+ ((QWidget *)child)->update();
+ }
+ updateBackgrounds(child);
+ }
+ }
+#else
+ QObjectList * list = (QObjectList *)(obj->children());
+ if(list)
+ {
+ for(unsigned int i=0;i<list->count();i++)
+ {
+ QObject * child = list->at(i);
+#if QT_VERSION >= 300
+ // FIXME: check if this code can work with qt < 3.0.0 too
+ if(child->metaObject()->findProperty("TransparencyCapable",true) != -1)
+ ((QWidget *)child)->update();
+#else
+
+ QVariant v = list->at(i)->property("TransparencyCapable");
+ if(v.isValid())
+ ((QWidget *)child)->update();
+#endif
+
+ updateBackgrounds(child);
+ }
+ }
+#endif
+}
+
+void KviWindow::moveEvent(QMoveEvent *e)
+{
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ updateBackgrounds();
+#endif
+
+ QWidget::moveEvent(e);
+}
+
+void KviWindow::minimize()
+{
+ if(mdiParent())
+ {
+ if(!isMinimized())
+ mdiParent()->minimize();
+ }
+ else
+ showMinimized();
+}
+
+void KviWindow::maximize()
+{
+ if(mdiParent())
+ {
+ if(!isMaximized())
+ mdiParent()->maximize();
+ }
+ else
+ showMaximized();
+ autoRaise();
+}
+
+bool KviWindow::isMinimized()
+{
+ if(mdiParent())
+ return (mdiParent()->state() == KviMdiChild::Minimized);
+ else
+ return QWidget::isMinimized();
+}
+
+bool KviWindow::isMaximized()
+{
+ if(mdiParent())
+ return (mdiParent()->state() == KviMdiChild::Maximized);
+ // Heh...how to check it ?
+ // Empirical check
+ int wdth = (g_pApp->desktop()->width() * 75) / 100;
+ int hght = (g_pApp->desktop()->height() * 75) / 100;
+
+ return ((x() <= 1)&&(y() <= 1)&&(width() >= wdth)&&(height() >= hght));
+}
+
+void KviWindow::restore()
+{
+ if(mdiParent())
+ {
+ if(isMinimized()||isMaximized())
+ mdiParent()->restore();
+ }
+ else
+ showNormal();
+ autoRaise();
+}
+
+QRect KviWindow::externalGeometry()
+{
+#ifndef Q_OS_MACX
+ return mdiParent() ? mdiParent()->restoredGeometry() : frameGeometry();
+#else
+ return mdiParent() ? mdiParent()->restoredGeometry() : geometry();
+#endif
+}
+
+void KviWindow::applyOptions()
+{
+ updateCaption();
+ if(m_pIrcView)m_pIrcView->applyOptions();
+ if(m_pInput)m_pInput->applyOptions();
+
+ // trick: relayout
+ resize(width() - 1,height() - 1);
+ resize(width() + 1,height() + 1);
+}
+
+KviWindow * KviWindow::outputProxy()
+{
+ return 0;
+}
+
+void KviWindow::lostUserFocus()
+{
+ if(!m_pIrcView)return;
+ if(m_pIrcView->hasLineMark())m_pIrcView->clearLineMark(true);
+}
+
+
+void KviWindow::internalOutput(KviIrcView * pView,int msg_type,const kvi_wchar_t * pText,int iFlags)
+{
+ // all roads lead to Rome :)
+
+ if(pView)
+ {
+ if((this != g_pActiveWindow) || (!isActiveWindow()))
+ {
+ if(!pView->hasLineMark())
+ {
+ iFlags |= KviIrcView::SetLineMark;
+ }
+ }
+ pView->appendText(msg_type,pText,iFlags);
+ } else {
+ // Redirect to the output proxy
+ KviWindow *wnd = outputProxy();
+ if(wnd)wnd->outputNoFmt(msg_type,pText,iFlags);
+ }
+
+ if(!m_pTaskBarItem) {
+ return;
+ }
+
+ // if this option is checked we dont highlight other than channel msg
+ if(KVI_OPTION_BOOL(KviOption_boolHighlightOnlyNormalMsg))
+ {
+ if((msg_type != KVI_OUT_CHANPRIVMSG) && (msg_type != KVI_OUT_CHANPRIVMSGCRYPTED))
+ {
+ if(!(
+ (
+ KVI_OPTION_BOOL(KviOption_boolHighlightOnlyNormalMsgQueryToo) &&
+ (
+ (msg_type == KVI_OUT_QUERYPRIVMSG) || (msg_type == KVI_OUT_QUERYTRACE) ||
+ (msg_type == KVI_OUT_QUERYPRIVMSGCRYPTED) || (msg_type == KVI_OUT_QUERYNOTICE) || (msg_type == KVI_OUT_QUERYNOTICECRYPTED)
+ )
+ )
+ ||
+ (
+ KVI_OPTION_BOOL(KviOption_boolHighlightOnlyNormalMsgHighlightInChanToo) && (msg_type == KVI_OUT_HIGHLIGHT)
+ )
+ )
+ )
+ return;
+ }
+ }
+
+ if(KVI_OPTION_BOOL(KviOption_boolHighlightOnlyAtCostumHighlightLevel) &&
+ (KVI_OPTION_MSGTYPE(msg_type).level() < ((int)(KVI_OPTION_UINT(KviOption_uintMinHighlightLevel)))))
+ {
+ return;
+ }
+
+ m_pTaskBarItem->highlight(KVI_OPTION_MSGTYPE(msg_type).level());
+}
+
+void KviWindow::output(int msg_type,const char *format,...)
+{
+ QString szFmt(format);
+ kvi_va_list l;
+ kvi_va_start(l,format);
+ QString szBuf;
+ KviQString::vsprintf(szBuf,szFmt,l);
+ kvi_va_end(l);
+ preprocessMessage(szBuf);
+ const QChar * pC = KviQString::nullTerminatedArray(szBuf);
+ if(!pC)return;
+ internalOutput(m_pIrcView,msg_type,(kvi_wchar_t *)pC);
+}
+
+void KviWindow::output(int msg_type,const QString &szFmt,...)
+{
+ kvi_va_list l;
+ kvi_va_start_by_reference(l,szFmt);
+ QString szBuf;
+ KviQString::vsprintf(szBuf,szFmt,l);
+ kvi_va_end(l);
+ preprocessMessage(szBuf);
+ const QChar * pC = KviQString::nullTerminatedArray(szBuf);
+ if(!pC)return;
+ internalOutput(m_pIrcView,msg_type,(kvi_wchar_t *)pC);
+}
+
+void KviWindow::output(int msg_type,const kvi_wchar_t *format,...)
+{
+ QString szFmt=QString::fromUtf8(KviStr(format).ptr());
+ kvi_va_list l;
+ kvi_va_start(l,format);
+ QString szBuf;
+ KviQString::vsprintf(szBuf,szFmt,l);
+ kvi_va_end(l);
+ preprocessMessage(szBuf);
+ const QChar * pC = KviQString::nullTerminatedArray(szBuf);
+ if(!pC)return;
+ internalOutput(m_pIrcView,msg_type,(kvi_wchar_t *)pC);
+}
+
+void KviWindow::outputNoFmt(int msg_type,const char * text,int iFlags)
+{
+ QString szText(text);
+ preprocessMessage(szText);
+ const QChar * pC = KviQString::nullTerminatedArray(szText);
+ if(!pC)return;
+ internalOutput(m_pIrcView,msg_type,(kvi_wchar_t *)pC,iFlags);
+}
+
+void KviWindow::outputNoFmt(int msg_type,const QString &szText,int iFlags)
+{
+ QString szBuf(szText);
+ preprocessMessage(szBuf);
+ const QChar * pC = KviQString::nullTerminatedArray(szBuf);
+ if(!pC)return;
+ internalOutput(m_pIrcView,msg_type,(kvi_wchar_t *)pC,iFlags);
+}
+
+void KviWindow::unhighlight()
+{
+ if(!m_pTaskBarItem)return;
+ m_pTaskBarItem->unhighlight();
+}
+
+/* This messes up a bit: for example it breaks the WHOIS output where
+ escapes are already present (checking for them here would be an overkill).
+ This should be eventually done ONLY for remote user message texts
+ in the server parser.
+
+ Fixed
+*/
+
+void KviWindow::preprocessMessage(QString & szMessage)
+{
+ // slow
+#ifdef COMPILE_USE_QT4
+ QStringList strings = szMessage.split(" ");
+#else
+ QStringList strings = QStringList::split(" ",szMessage, TRUE);
+#endif
+ for ( QStringList::Iterator it = strings.begin(); it != strings.end(); ++it ) {
+ QString tmp(*it);
+ if(tmp.contains('\r')) continue;
+ tmp = KviMircCntrl::stripControlBytes(tmp);
+ tmp.stripWhiteSpace();
+ if(m_pConsole)
+ if(m_pConsole->connection())
+ if(m_pConsole->connection()->serverInfo()->supportedChannelTypes().contains(tmp[0]))
+ if((*it)==tmp)
+ *it=QString("\r!c\r%1\r").arg(*it);
+ else
+ {
+ *it=QString("\r!c%1\r%2\r").arg(tmp).arg(*it);
+ }
+ }
+ szMessage=strings.join(" ");
+}
+
+
+#include "kvi_window.moc"
diff --git a/src/kvirc/ui/kvi_window.h b/src/kvirc/ui/kvi_window.h
new file mode 100644
index 00000000..419096fc
--- /dev/null
+++ b/src/kvirc/ui/kvi_window.h
@@ -0,0 +1,393 @@
+#ifndef _KVI_WINDOW_H_
+#define _KVI_WINDOW_H_
+//=============================================================================
+//
+// File : kvi_window.h
+// Creation date : Tue Jul 6 1999 14:52:20 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_string.h"
+#include "kvi_qstring.h"
+#include "kvi_qcstring.h"
+#include "kvi_settings.h"
+
+#ifdef COMPILE_ON_WINDOWS
+ // The brain-damaged MSVC compiler can't instantiate QList templates without a destructor definition
+ #include "kvi_mdichild.h"
+#else
+ class KviMdiChild;
+#endif
+
+#include <qframe.h>
+
+class KviFrame;
+class KviTaskBarItem;
+class KviConfig;
+class KviIrcView;
+class KviInput;
+class KviConsole;
+class KviIrcContext;
+class KviIrcConnection;
+class KviWindowToolPageButton;
+
+class KviTalPopupMenu;
+class QPixmap;
+class QSplitter;
+class KviTalHBox;
+class QToolButton;
+class QTextCodec;
+class KviTalWidgetStack;
+
+#include "kvi_tal_hbox.h"
+#include "kvi_tal_widgetstack.h"
+#include "kvi_accel.h"
+
+#ifdef COMPILE_CRYPT_SUPPORT
+ class KviCryptController;
+ class KviCryptSessionInfo;
+#endif
+
+#include <qwidget.h>
+
+//
+// Window types
+//
+// There are KVI_WINDOW_NUM_TYPES predefined
+// window types: these are used by the KVIrc core and distributed modules
+// If you add a new def, increase KVI_WINDOW_NUM_TYPES
+//
+
+#define KVI_WINDOW_TYPE_CONSOLE 0
+#define KVI_WINDOW_TYPE_CHANNEL 1
+#define KVI_WINDOW_TYPE_QUERY 2
+#define KVI_WINDOW_TYPE_HELP 3
+#define KVI_WINDOW_TYPE_TERM 4
+#define KVI_WINDOW_TYPE_EDITOR 5
+#define KVI_WINDOW_TYPE_DCCCHAT 6
+#define KVI_WINDOW_TYPE_DCCSEND 7
+#define KVI_WINDOW_TYPE_SOCKETSPY 8
+#define KVI_WINDOW_TYPE_LINKS 9
+#define KVI_WINDOW_TYPE_TOOL 10
+#define KVI_WINDOW_TYPE_GNUTELLA 11
+#define KVI_WINDOW_TYPE_DIRBROWSER 12
+#define KVI_WINDOW_TYPE_DCCCANVAS 13
+#define KVI_WINDOW_TYPE_DCCVOICE 14
+#define KVI_WINDOW_TYPE_LIST 15
+#define KVI_WINDOW_TYPE_OFFER 16
+#define KVI_WINDOW_TYPE_LOGVIEW 17
+#define KVI_WINDOW_TYPE_DEADCHANNEL 18
+#define KVI_WINDOW_TYPE_DEADQUERY 19
+#define KVI_WINDOW_TYPE_SCRIPTEDITOR 20
+#define KVI_WINDOW_TYPE_SCRIPTOBJECT 21
+#define KVI_WINDOW_TYPE_USERWINDOW 22
+#define KVI_WINDOW_TYPE_DEBUG 23
+
+
+#define KVI_WINDOW_NUM_TYPES 24
+
+
+#define KVI_WINDOW_TYPE_USER 10000
+
+
+
+
+#define KVI_ACTIVITY_NONE 0
+#define KVI_ACTIVITY_VERYLOW 1
+#define KVI_ACTIVITY_LOW 2
+#define KVI_ACTIVITY_MEDIUM 3
+#define KVI_ACTIVITY_HIGH 4
+#define KVI_ACTIVITY_VERYHIGH 5
+
+#define KVI_ACTIVITY_ICE 0
+#define KVI_ACTIVITY_VERYCOLD 1
+#define KVI_ACTIVITY_COLD 2
+#define KVI_ACTIVITY_UNDEFINED 3
+#define KVI_ACTIVITY_HOT 4
+#define KVI_ACTIVITY_VERYHOT 5
+#define KVI_ACTIVITY_FIRE 6
+
+#ifdef COMPILE_USE_QT4
+ class QPushButton;
+ #define BUTTON_CLASS QPushButton
+#else
+ #define BUTTON_CLASS QToolButton
+#endif
+
+
+class KVIRC_API KviWindow : public QWidget
+{
+ friend class KviInput;
+ friend class KviFrame;
+ friend class KviTaskBarItem;
+ friend class KviTaskBarButton;
+ friend class KviTreeTaskBarItem;
+ friend class KviTreeTaskBar;
+ Q_PROPERTY(int KviProperty_ChildFocusOwner READ type)
+ Q_OBJECT
+public:
+ KviWindow(int type,KviFrame * lpFrm,const QString &name,KviConsole * pConsole = 0);
+ virtual ~KviWindow();
+protected: // almost private: don't touch :D
+ QString m_szName; // the current window name (usually also the target)
+ KviFrame * m_pFrm;
+ KviConsole * m_pConsole;
+ KviIrcContext * m_pContext;
+
+ int m_iType;
+
+ KviTaskBarItem * m_pTaskBarItem;
+ QWidget * m_pFocusHandler;
+ QString m_szPlainTextCaption;
+ QString m_szHtmlActiveCaption;
+ QString m_szHtmlInactiveCaption;
+ KviIrcView * m_pIrcView;
+ KviInput * m_pInput;
+ QSplitter * m_pSplitter;
+ KviTalHBox * m_pButtonBox;
+ unsigned long int m_uId;
+ QString m_szTextEncoding;
+#ifdef COMPILE_CRYPT_SUPPORT
+ KviWindowToolPageButton * m_pCryptControllerButton;
+ KviCryptController * m_pCryptController;
+ KviCryptSessionInfo * m_pCryptSessionInfo;
+#endif
+ BUTTON_CLASS * m_pTextEncodingButton;
+ QToolButton * m_pHideToolsButton;
+ QWidget * m_pLastFocusedChild;
+ KviAccel * m_pAccel;
+ static const char * m_typeTable[KVI_WINDOW_NUM_TYPES + 1];
+ // text encoding and decoding
+ //unsigned int m_uTextEncoding;
+ QTextCodec * m_pTextCodec;
+// KviToolWindowsContainer * m_pEditorsContainer;
+public:
+ // The global ID of this window: unique in the application
+ QString id(){ return QString("%1").arg(m_uId); };
+ unsigned long int numericId(){ return m_uId; };
+public:
+ // THIS is the function that should be used
+ const QString & windowName(){ return m_szName; };
+ void setWindowName(const QString &szName);
+ // force QT to set our UNICODE name too... FIXME: this should be removed later...
+ virtual void setName(const char * szName);
+
+ // Window type management
+ int type() const { return m_iType; };
+ // This returns a descriptive name of the window type
+ // if the window is an user window, the typeString returned
+ // by THIS implementation is "unknown"
+ virtual const char * typeString();
+
+ QTextCodec * textCodec(){ return m_pTextCodec ? m_pTextCodec : defaultTextCodec(); };
+ void forceTextCodec(QTextCodec * c);
+
+ // The frame that this window belongs to
+ // It is always non-null and never changes
+ KviFrame * frame() const { return m_pFrm; };
+ // The KviIrcView of this window: may be NULL if the window has no KviIrcView (and thus supports no direct output)
+ KviIrcView * view() const { return m_pIrcView; };
+ // The mdiParent widget: may be nulll if the window is undocked
+ KviMdiChild * mdiParent(){ return (KviMdiChild *)parent(); };
+ // The console that this window belongs to: may be null for windows that aren't bound to irc contexts
+ KviConsole * console(){ return m_pConsole; };
+ // same as above
+ KviIrcContext * context(){ return m_pContext; };
+ // the current IRC connection (if any)
+ KviIrcConnection * connection();
+ // The splitter of this window: it *shouldn't* be null... but ... well.. who knows ? :D ...better check it
+ QSplitter * splitter(){ return m_pSplitter; };
+ // The window has ALWAYS a taskbar item
+ KviTaskBarItem * taskBarItem(){ return m_pTaskBarItem; };
+ // The window *might* have a button container
+ virtual QFrame * buttonContainer(){ return (QFrame*)m_pButtonBox; };
+ virtual void toggleButtonContainer();
+ // The window *might* have an output proxy: if it has no view() for example
+ virtual KviWindow * outputProxy();
+ // The window input widget
+ KviInput * input(){ return m_pInput; };
+
+ // The target of this window: empty when it makes no sense :D
+ virtual const QString & target(){ return KviQString::empty; };
+ // The local nickname bound to this window: might be empty when a local nickname makes no sense
+ virtual const QString & localNick(){ return KviQString::empty; };
+
+#ifdef COMPILE_CRYPT_SUPPORT
+ KviCryptSessionInfo * cryptSessionInfo(){ return m_pCryptSessionInfo; };
+ void setCryptSessionInfo(KviCryptSessionInfo * i);
+#endif
+
+ virtual bool activityMeter(unsigned int * puActivityValue,unsigned int * puActivityTemperature);
+
+ void unhighlight();
+
+ virtual void getTaskBarTipText(QString &buffer);
+
+ // This is meaningful only if view() is non NULL
+ const QString & lastLineOfText();
+ const QString & lastMessageText();
+
+ const QString &textEncoding(){ return m_szTextEncoding; };
+ // returns true if the encoding could be succesfully set
+ bool setTextEncoding(const QString &szTextEncoding);
+ // this must return a default text codec suitable for this window
+ virtual QTextCodec * defaultTextCodec();
+ // encode the text from szSource by using m_uTextEncoding
+ KviQCString encodeText(const QString &szText);
+ QString decodeText(const char * szText);
+
+ void contextPopup();
+ // Raises the window (after a light delay to prevent focus pingpongs)
+ void delayedAutoRaise();
+ // Window state: might work :D
+ bool isMinimized();
+ bool isMaximized();
+ // Retrieves the default log file name: this is pre-build
+ void getDefaultLogFileName(QString &buffer);
+ // Well...the external geometry :)
+ QRect externalGeometry();
+
+ void delayedClose(); // close that jumps out of the current event loop
+
+ // Interesting overridables:
+ virtual void fillContextPopup(KviTalPopupMenu * p);
+ virtual void getConfigGroupName(QString &buf);
+// virtual void getBaseLogFileName(KviStr &buffer);
+ virtual void getBaseLogFileName(QString &buffer);
+ virtual void updateCaption();
+ virtual void applyOptions();
+ virtual void updateIcon();
+ virtual void ownMessage(const QString &text){};
+ virtual void ownAction(const QString &text){};
+ virtual const QString & plainTextCaption(){ return m_szPlainTextCaption; };
+ virtual const QString & htmlActiveCaption(){ return m_szHtmlActiveCaption; };
+ virtual const QString & htmlInactiveCaption(){ return m_szHtmlInactiveCaption; };
+ virtual void setFocus();
+
+ void internalOutput(KviIrcView * pView,int msg_type,const kvi_wchar_t * text,int iFlags=0);
+ // You *might* want to override these too.. but better don't touch them :D
+ virtual void output(int msg_type,const char * format,...);
+ virtual void outputNoFmt(int msg_type,const char * text,int iFlags=0);
+ virtual void output(int msg_type,const kvi_wchar_t * format,...);
+ virtual void outputNoFmt(int msg_type,const kvi_wchar_t * text,int iFlags=0){ internalOutput(m_pIrcView,msg_type,text,iFlags); };
+ virtual void output(int msg_type,const QString &szFmt,...);
+ virtual void outputNoFmt(int msg_type,const QString &szText,int iFlags=0); // <-- these are KviIrcView::AppendTextFlags
+ // Just helpers.. FIXME: might be redesigned in some other way
+ void updateBackgrounds(QObject * obj = 0);
+
+ void demandAttention();
+ bool hasAttention();
+
+ // This should die, probably
+ void listWindowTypes();
+
+public slots:
+ void dock();
+ void undock();
+ void autoRaise();
+ void maximize();
+ void minimize();
+ void restore();
+ void reloadImages();
+protected slots:
+ void savePropertiesAsDefault();
+ void toggleCryptController(); // This has to be here even if the crypt support is enabled...moc does not support conditionals
+ void cryptControllerFinished(); // same as above
+ void cryptSessionInfoDestroyed(); // same as above
+ void textEncodingButtonClicked();
+ void systemPopupRequest(const QPoint &pnt);
+ void systemTextEncodingPopupSmartActivated(int id);
+ void systemTextEncodingPopupSmartUtf8Activated(int id);
+ void systemTextEncodingPopupStandardActivated(int id);
+ void systemTextEncodingPopupDefault();
+ void childDestroyed();
+signals:
+ void windowNameChanged();
+protected:
+ // Loading and saving of properties
+ // Protected: only KviFrame can call these
+ virtual void saveProperties(KviConfig *cfg);
+ virtual void loadProperties(KviConfig *cfg);
+ // Creation and destruction events: overridden in windows that have script events bound to creation and destruction
+ virtual void triggerCreationEvents(){};
+ virtual void triggerDestructionEvents(){};
+ // Internal: do not touch :D (KviFrame)
+ virtual void createTaskBarItem();
+ virtual void destroyTaskBarItem();
+ // called by KviFrame
+ // either lost the active window status or the frame is no longer active (but we're still the active kvirc's subwindow)
+ virtual void lostUserFocus();
+ // Sets the progress for the taskbar item: if "progress" makes sense in your window , well , use this
+ void setProgress(int progress);
+ // call this in the constructor if your caption is fixed:
+ // it will set m_szPlainTextCaption to szCaption and it will
+ // automatically use it without the need of overriding fillCaptionBuffers
+ void setFixedCaption(const QString &szCaption);
+ // this by default calls fillSingleColorCaptionBuffer(plainTextCaption());
+ virtual void fillCaptionBuffers();
+ // protected helper
+ void fillSingleColorCaptionBuffers(const QString &szName);
+ // Virtual events that signal dock state change
+ virtual void youAreDocked();
+ virtual void youAreUndocked();
+ // Reimplement to show a special icon in the taskbar items and captions
+ virtual QPixmap * myIconPtr();
+ // Sets the type of this window: be careful with this
+ void setType(int iType);
+
+ bool eventFilter(QObject *o,QEvent *e);
+
+ // Virtuals overridden to manage the internal layouts...
+ virtual void moveEvent(QMoveEvent *e);
+ virtual void closeEvent(QCloseEvent *e);
+ virtual void wheelEvent(QWheelEvent *e);
+ virtual void childEvent(QChildEvent *e);
+ virtual void focusInEvent(QFocusEvent *e);
+
+ void childInserted(QWidget * o);
+ void childRemoved(QWidget * o);
+
+ void activateSelf();
+
+ // Internal helpers
+ void createCryptControllerButton(QWidget * par);
+ void createTextEncodingButton(QWidget * par);
+ void createSystemTextEncodingPopup();
+
+ BUTTON_CLASS * createToolButton(QWidget * par,const char * nam,int pixon,int pixoff,const QString & tooltip,bool bOn);
+ // This is called by KviInput: actually it links the widgetAdded
+ virtual void childrenTreeChanged(QWidget * widgetAdded);
+
+ virtual bool focusNextPrevChild(bool bNext);
+
+ virtual void preprocessMessage(QString & szMessage);
+};
+
+#ifndef _KVI_WINDOW_CPP_
+ // The active window:
+ // This is almost always non null
+ // The exception is the startup (when there are no windows at all)
+ // and the last phase of the destructor.
+ // You usually shouldn't care of checking this pointer for NULL unless
+ // you're running very early at startup or very late at shutdown
+ extern KVIRC_API KviWindow * g_pActiveWindow;
+#endif
+
+#endif //_KVI_WINDOW_H_
diff --git a/src/kvirc/ui/moc_kvi_actiondrawer.cpp b/src/kvirc/ui/moc_kvi_actiondrawer.cpp
new file mode 100644
index 00000000..833bc391
--- /dev/null
+++ b/src/kvirc/ui/moc_kvi_actiondrawer.cpp
@@ -0,0 +1,238 @@
+/****************************************************************************
+** KviActionDrawerPageListView meta object code from reading C++ file 'kvi_actiondrawer.h'
+**
+** Created: Mon Feb 25 00:12:20 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_actiondrawer.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviActionDrawerPageListView::className() const
+{
+ return "KviActionDrawerPageListView";
+}
+
+QMetaObject *KviActionDrawerPageListView::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviActionDrawerPageListView( "KviActionDrawerPageListView", &KviActionDrawerPageListView::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviActionDrawerPageListView::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviActionDrawerPageListView", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviActionDrawerPageListView::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviActionDrawerPageListView", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviActionDrawerPageListView::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = KviListView::staticMetaObject();
+ metaObj = QMetaObject::new_metaobject(
+ "KviActionDrawerPageListView", parentObject,
+ 0, 0,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviActionDrawerPageListView.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviActionDrawerPageListView::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviActionDrawerPageListView" ) )
+ return this;
+ return KviListView::qt_cast( clname );
+}
+
+bool KviActionDrawerPageListView::qt_invoke( int _id, QUObject* _o )
+{
+ return KviListView::qt_invoke(_id,_o);
+}
+
+bool KviActionDrawerPageListView::qt_emit( int _id, QUObject* _o )
+{
+ return KviListView::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviActionDrawerPageListView::qt_property( int id, int f, QVariant* v)
+{
+ return KviListView::qt_property( id, f, v);
+}
+
+bool KviActionDrawerPageListView::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
+
+
+const char *KviActionDrawerPage::className() const
+{
+ return "KviActionDrawerPage";
+}
+
+QMetaObject *KviActionDrawerPage::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviActionDrawerPage( "KviActionDrawerPage", &KviActionDrawerPage::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviActionDrawerPage::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviActionDrawerPage", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviActionDrawerPage::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviActionDrawerPage", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviActionDrawerPage::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = QWidget::staticMetaObject();
+ metaObj = QMetaObject::new_metaobject(
+ "KviActionDrawerPage", parentObject,
+ 0, 0,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviActionDrawerPage.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviActionDrawerPage::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviActionDrawerPage" ) )
+ return this;
+ return QWidget::qt_cast( clname );
+}
+
+bool KviActionDrawerPage::qt_invoke( int _id, QUObject* _o )
+{
+ return QWidget::qt_invoke(_id,_o);
+}
+
+bool KviActionDrawerPage::qt_emit( int _id, QUObject* _o )
+{
+ return QWidget::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviActionDrawerPage::qt_property( int id, int f, QVariant* v)
+{
+ return QWidget::qt_property( id, f, v);
+}
+
+bool KviActionDrawerPage::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
+
+
+const char *KviActionDrawer::className() const
+{
+ return "KviActionDrawer";
+}
+
+QMetaObject *KviActionDrawer::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviActionDrawer( "KviActionDrawer", &KviActionDrawer::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviActionDrawer::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviActionDrawer", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviActionDrawer::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviActionDrawer", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviActionDrawer::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = QTabWidget::staticMetaObject();
+ metaObj = QMetaObject::new_metaobject(
+ "KviActionDrawer", parentObject,
+ 0, 0,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviActionDrawer.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviActionDrawer::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviActionDrawer" ) )
+ return this;
+ return QTabWidget::qt_cast( clname );
+}
+
+bool KviActionDrawer::qt_invoke( int _id, QUObject* _o )
+{
+ return QTabWidget::qt_invoke(_id,_o);
+}
+
+bool KviActionDrawer::qt_emit( int _id, QUObject* _o )
+{
+ return QTabWidget::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviActionDrawer::qt_property( int id, int f, QVariant* v)
+{
+ return QTabWidget::qt_property( id, f, v);
+}
+
+bool KviActionDrawer::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvirc/ui/moc_kvi_customtoolbar.cpp b/src/kvirc/ui/moc_kvi_customtoolbar.cpp
new file mode 100644
index 00000000..4a89b121
--- /dev/null
+++ b/src/kvirc/ui/moc_kvi_customtoolbar.cpp
@@ -0,0 +1,180 @@
+/****************************************************************************
+** KviCustomToolBarSeparator meta object code from reading C++ file 'kvi_customtoolbar.h'
+**
+** Created: Mon Feb 25 00:12:23 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_customtoolbar.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviCustomToolBarSeparator::className() const
+{
+ return "KviCustomToolBarSeparator";
+}
+
+QMetaObject *KviCustomToolBarSeparator::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviCustomToolBarSeparator( "KviCustomToolBarSeparator", &KviCustomToolBarSeparator::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviCustomToolBarSeparator::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviCustomToolBarSeparator", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviCustomToolBarSeparator::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviCustomToolBarSeparator", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviCustomToolBarSeparator::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = QWidget::staticMetaObject();
+ metaObj = QMetaObject::new_metaobject(
+ "KviCustomToolBarSeparator", parentObject,
+ 0, 0,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviCustomToolBarSeparator.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviCustomToolBarSeparator::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviCustomToolBarSeparator" ) )
+ return this;
+ return QWidget::qt_cast( clname );
+}
+
+bool KviCustomToolBarSeparator::qt_invoke( int _id, QUObject* _o )
+{
+ return QWidget::qt_invoke(_id,_o);
+}
+
+bool KviCustomToolBarSeparator::qt_emit( int _id, QUObject* _o )
+{
+ return QWidget::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviCustomToolBarSeparator::qt_property( int id, int f, QVariant* v)
+{
+ return QWidget::qt_property( id, f, v);
+}
+
+bool KviCustomToolBarSeparator::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
+
+
+const char *KviCustomToolBar::className() const
+{
+ return "KviCustomToolBar";
+}
+
+QMetaObject *KviCustomToolBar::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviCustomToolBar( "KviCustomToolBar", &KviCustomToolBar::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviCustomToolBar::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviCustomToolBar", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviCustomToolBar::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviCustomToolBar", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviCustomToolBar::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = KviToolBar::staticMetaObject();
+ static const QUMethod slot_0 = {"beginCustomize", 0, 0 };
+ static const QUMethod slot_1 = {"endCustomize", 0, 0 };
+ static const QUMethod slot_2 = {"filteredChildDestroyed", 0, 0 };
+ static const QMetaData slot_tbl[] = {
+ { "beginCustomize()", &slot_0, QMetaData::Protected },
+ { "endCustomize()", &slot_1, QMetaData::Protected },
+ { "filteredChildDestroyed()", &slot_2, QMetaData::Protected }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviCustomToolBar", parentObject,
+ slot_tbl, 3,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviCustomToolBar.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviCustomToolBar::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviCustomToolBar" ) )
+ return this;
+ return KviToolBar::qt_cast( clname );
+}
+
+bool KviCustomToolBar::qt_invoke( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->slotOffset() ) {
+ case 0: beginCustomize(); break;
+ case 1: endCustomize(); break;
+ case 2: filteredChildDestroyed(); break;
+ default:
+ return KviToolBar::qt_invoke( _id, _o );
+ }
+ return TRUE;
+}
+
+bool KviCustomToolBar::qt_emit( int _id, QUObject* _o )
+{
+ return KviToolBar::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviCustomToolBar::qt_property( int id, int f, QVariant* v)
+{
+ return KviToolBar::qt_property( id, f, v);
+}
+
+bool KviCustomToolBar::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvirc/ui/moc_kvi_debugwindow.cpp b/src/kvirc/ui/moc_kvi_debugwindow.cpp
new file mode 100644
index 00000000..5e3da82c
--- /dev/null
+++ b/src/kvirc/ui/moc_kvi_debugwindow.cpp
@@ -0,0 +1,92 @@
+/****************************************************************************
+** KviDebugWindow meta object code from reading C++ file 'kvi_debugwindow.h'
+**
+** Created: Mon Feb 25 00:12:25 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_debugwindow.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviDebugWindow::className() const
+{
+ return "KviDebugWindow";
+}
+
+QMetaObject *KviDebugWindow::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviDebugWindow( "KviDebugWindow", &KviDebugWindow::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviDebugWindow::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviDebugWindow", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviDebugWindow::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviDebugWindow", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviDebugWindow::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = KviWindow::staticMetaObject();
+ metaObj = QMetaObject::new_metaobject(
+ "KviDebugWindow", parentObject,
+ 0, 0,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviDebugWindow.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviDebugWindow::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviDebugWindow" ) )
+ return this;
+ return KviWindow::qt_cast( clname );
+}
+
+bool KviDebugWindow::qt_invoke( int _id, QUObject* _o )
+{
+ return KviWindow::qt_invoke(_id,_o);
+}
+
+bool KviDebugWindow::qt_emit( int _id, QUObject* _o )
+{
+ return KviWindow::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviDebugWindow::qt_property( int id, int f, QVariant* v)
+{
+ return KviWindow::qt_property( id, f, v);
+}
+
+bool KviDebugWindow::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvirc/ui/moc_kvi_htmldialog.cpp b/src/kvirc/ui/moc_kvi_htmldialog.cpp
new file mode 100644
index 00000000..62d76814
--- /dev/null
+++ b/src/kvirc/ui/moc_kvi_htmldialog.cpp
@@ -0,0 +1,107 @@
+/****************************************************************************
+** KviHtmlDialog meta object code from reading C++ file 'kvi_htmldialog.h'
+**
+** Created: Mon Feb 25 00:12:27 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_htmldialog.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviHtmlDialog::className() const
+{
+ return "KviHtmlDialog";
+}
+
+QMetaObject *KviHtmlDialog::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviHtmlDialog( "KviHtmlDialog", &KviHtmlDialog::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviHtmlDialog::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviHtmlDialog", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviHtmlDialog::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviHtmlDialog", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviHtmlDialog::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = QDialog::staticMetaObject();
+ static const QUMethod slot_0 = {"button1Pressed", 0, 0 };
+ static const QUMethod slot_1 = {"button2Pressed", 0, 0 };
+ static const QUMethod slot_2 = {"button3Pressed", 0, 0 };
+ static const QMetaData slot_tbl[] = {
+ { "button1Pressed()", &slot_0, QMetaData::Protected },
+ { "button2Pressed()", &slot_1, QMetaData::Protected },
+ { "button3Pressed()", &slot_2, QMetaData::Protected }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviHtmlDialog", parentObject,
+ slot_tbl, 3,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviHtmlDialog.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviHtmlDialog::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviHtmlDialog" ) )
+ return this;
+ return QDialog::qt_cast( clname );
+}
+
+bool KviHtmlDialog::qt_invoke( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->slotOffset() ) {
+ case 0: button1Pressed(); break;
+ case 1: button2Pressed(); break;
+ case 2: button3Pressed(); break;
+ default:
+ return QDialog::qt_invoke( _id, _o );
+ }
+ return TRUE;
+}
+
+bool KviHtmlDialog::qt_emit( int _id, QUObject* _o )
+{
+ return QDialog::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviHtmlDialog::qt_property( int id, int f, QVariant* v)
+{
+ return QDialog::qt_property( id, f, v);
+}
+
+bool KviHtmlDialog::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvirc/ui/moc_kvi_imagedialog.cpp b/src/kvirc/ui/moc_kvi_imagedialog.cpp
new file mode 100644
index 00000000..be88643c
--- /dev/null
+++ b/src/kvirc/ui/moc_kvi_imagedialog.cpp
@@ -0,0 +1,126 @@
+/****************************************************************************
+** KviImageDialog meta object code from reading C++ file 'kvi_imagedialog.h'
+**
+** Created: Mon Feb 25 00:12:28 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_imagedialog.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviImageDialog::className() const
+{
+ return "KviImageDialog";
+}
+
+QMetaObject *KviImageDialog::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviImageDialog( "KviImageDialog", &KviImageDialog::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviImageDialog::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviImageDialog", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviImageDialog::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviImageDialog", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviImageDialog::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = QDialog::staticMetaObject();
+ static const QUMethod slot_0 = {"okClicked", 0, 0 };
+ static const QUMethod slot_1 = {"cancelClicked", 0, 0 };
+ static const QUMethod slot_2 = {"heartbeat", 0, 0 };
+ static const QUParameter param_slot_3[] = {
+ { "index", &static_QUType_int, 0, QUParameter::In }
+ };
+ static const QUMethod slot_3 = {"jobTypeSelected", 1, param_slot_3 };
+ static const QUParameter param_slot_4[] = {
+ { "it", &static_QUType_ptr, "KviTalListBoxItem", QUParameter::In }
+ };
+ static const QUMethod slot_4 = {"itemDoubleClicked", 1, param_slot_4 };
+ static const QUParameter param_slot_5[] = {
+ { 0, &static_QUType_ptr, "KviDynamicToolTip", QUParameter::In },
+ { "pnt", &static_QUType_varptr, "\x0e", QUParameter::In }
+ };
+ static const QUMethod slot_5 = {"tipRequest", 2, param_slot_5 };
+ static const QMetaData slot_tbl[] = {
+ { "okClicked()", &slot_0, QMetaData::Protected },
+ { "cancelClicked()", &slot_1, QMetaData::Protected },
+ { "heartbeat()", &slot_2, QMetaData::Protected },
+ { "jobTypeSelected(int)", &slot_3, QMetaData::Protected },
+ { "itemDoubleClicked(KviTalListBoxItem*)", &slot_4, QMetaData::Protected },
+ { "tipRequest(KviDynamicToolTip*,const QPoint&)", &slot_5, QMetaData::Protected }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviImageDialog", parentObject,
+ slot_tbl, 6,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviImageDialog.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviImageDialog::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviImageDialog" ) )
+ return this;
+ return QDialog::qt_cast( clname );
+}
+
+bool KviImageDialog::qt_invoke( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->slotOffset() ) {
+ case 0: okClicked(); break;
+ case 1: cancelClicked(); break;
+ case 2: heartbeat(); break;
+ case 3: jobTypeSelected((int)static_QUType_int.get(_o+1)); break;
+ case 4: itemDoubleClicked((KviTalListBoxItem*)static_QUType_ptr.get(_o+1)); break;
+ case 5: tipRequest((KviDynamicToolTip*)static_QUType_ptr.get(_o+1),(const QPoint&)*((const QPoint*)static_QUType_ptr.get(_o+2))); break;
+ default:
+ return QDialog::qt_invoke( _id, _o );
+ }
+ return TRUE;
+}
+
+bool KviImageDialog::qt_emit( int _id, QUObject* _o )
+{
+ return QDialog::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviImageDialog::qt_property( int id, int f, QVariant* v)
+{
+ return QDialog::qt_property( id, f, v);
+}
+
+bool KviImageDialog::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvirc/ui/moc_kvi_ircviewtools.cpp b/src/kvirc/ui/moc_kvi_ircviewtools.cpp
new file mode 100644
index 00000000..e44adb66
--- /dev/null
+++ b/src/kvirc/ui/moc_kvi_ircviewtools.cpp
@@ -0,0 +1,116 @@
+/****************************************************************************
+** KviIrcViewToolWidget meta object code from reading C++ file 'kvi_ircviewtools.h'
+**
+** Created: Mon Feb 25 00:12:30 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_ircviewtools.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviIrcViewToolWidget::className() const
+{
+ return "KviIrcViewToolWidget";
+}
+
+QMetaObject *KviIrcViewToolWidget::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviIrcViewToolWidget( "KviIrcViewToolWidget", &KviIrcViewToolWidget::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviIrcViewToolWidget::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviIrcViewToolWidget", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviIrcViewToolWidget::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviIrcViewToolWidget", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviIrcViewToolWidget::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = QFrame::staticMetaObject();
+ static const QUMethod slot_0 = {"findPrev", 0, 0 };
+ static const QUMethod slot_1 = {"findNext", 0, 0 };
+ static const QUMethod slot_2 = {"filterEnableAll", 0, 0 };
+ static const QUMethod slot_3 = {"filterEnableNone", 0, 0 };
+ static const QUMethod slot_4 = {"filterSave", 0, 0 };
+ static const QUMethod slot_5 = {"filterLoad", 0, 0 };
+ static const QMetaData slot_tbl[] = {
+ { "findPrev()", &slot_0, QMetaData::Protected },
+ { "findNext()", &slot_1, QMetaData::Protected },
+ { "filterEnableAll()", &slot_2, QMetaData::Protected },
+ { "filterEnableNone()", &slot_3, QMetaData::Protected },
+ { "filterSave()", &slot_4, QMetaData::Protected },
+ { "filterLoad()", &slot_5, QMetaData::Protected }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviIrcViewToolWidget", parentObject,
+ slot_tbl, 6,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviIrcViewToolWidget.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviIrcViewToolWidget::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviIrcViewToolWidget" ) )
+ return this;
+ return QFrame::qt_cast( clname );
+}
+
+bool KviIrcViewToolWidget::qt_invoke( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->slotOffset() ) {
+ case 0: findPrev(); break;
+ case 1: findNext(); break;
+ case 2: filterEnableAll(); break;
+ case 3: filterEnableNone(); break;
+ case 4: filterSave(); break;
+ case 5: filterLoad(); break;
+ default:
+ return QFrame::qt_invoke( _id, _o );
+ }
+ return TRUE;
+}
+
+bool KviIrcViewToolWidget::qt_emit( int _id, QUObject* _o )
+{
+ return QFrame::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviIrcViewToolWidget::qt_property( int id, int f, QVariant* v)
+{
+ return QFrame::qt_property( id, f, v);
+}
+
+bool KviIrcViewToolWidget::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvirc/ui/moc_kvi_listview.cpp b/src/kvirc/ui/moc_kvi_listview.cpp
new file mode 100644
index 00000000..f9f61186
--- /dev/null
+++ b/src/kvirc/ui/moc_kvi_listview.cpp
@@ -0,0 +1,92 @@
+/****************************************************************************
+** KviListView meta object code from reading C++ file 'kvi_listview.h'
+**
+** Created: Mon Feb 25 00:12:44 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_listview.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviListView::className() const
+{
+ return "KviListView";
+}
+
+QMetaObject *KviListView::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviListView( "KviListView", &KviListView::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviListView::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviListView", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviListView::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviListView", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviListView::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = KviTalListView::staticMetaObject();
+ metaObj = QMetaObject::new_metaobject(
+ "KviListView", parentObject,
+ 0, 0,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviListView.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviListView::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviListView" ) )
+ return this;
+ return KviTalListView::qt_cast( clname );
+}
+
+bool KviListView::qt_invoke( int _id, QUObject* _o )
+{
+ return KviTalListView::qt_invoke(_id,_o);
+}
+
+bool KviListView::qt_emit( int _id, QUObject* _o )
+{
+ return KviTalListView::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviListView::qt_property( int id, int f, QVariant* v)
+{
+ return KviTalListView::qt_property( id, f, v);
+}
+
+bool KviListView::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvirc/ui/moc_kvi_mdicaption.cpp b/src/kvirc/ui/moc_kvi_mdicaption.cpp
new file mode 100644
index 00000000..3e027b92
--- /dev/null
+++ b/src/kvirc/ui/moc_kvi_mdicaption.cpp
@@ -0,0 +1,238 @@
+/****************************************************************************
+** KviMdiCaptionButton meta object code from reading C++ file 'kvi_mdicaption.h'
+**
+** Created: Mon Feb 25 00:12:32 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_mdicaption.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviMdiCaptionButton::className() const
+{
+ return "KviMdiCaptionButton";
+}
+
+QMetaObject *KviMdiCaptionButton::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviMdiCaptionButton( "KviMdiCaptionButton", &KviMdiCaptionButton::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviMdiCaptionButton::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviMdiCaptionButton", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviMdiCaptionButton::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviMdiCaptionButton", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviMdiCaptionButton::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = QToolButton::staticMetaObject();
+ metaObj = QMetaObject::new_metaobject(
+ "KviMdiCaptionButton", parentObject,
+ 0, 0,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviMdiCaptionButton.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviMdiCaptionButton::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviMdiCaptionButton" ) )
+ return this;
+ return QToolButton::qt_cast( clname );
+}
+
+bool KviMdiCaptionButton::qt_invoke( int _id, QUObject* _o )
+{
+ return QToolButton::qt_invoke(_id,_o);
+}
+
+bool KviMdiCaptionButton::qt_emit( int _id, QUObject* _o )
+{
+ return QToolButton::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviMdiCaptionButton::qt_property( int id, int f, QVariant* v)
+{
+ return QToolButton::qt_property( id, f, v);
+}
+
+bool KviMdiCaptionButton::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
+
+
+const char *KviMenuBarToolButton::className() const
+{
+ return "KviMenuBarToolButton";
+}
+
+QMetaObject *KviMenuBarToolButton::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviMenuBarToolButton( "KviMenuBarToolButton", &KviMenuBarToolButton::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviMenuBarToolButton::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviMenuBarToolButton", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviMenuBarToolButton::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviMenuBarToolButton", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviMenuBarToolButton::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = KviStyledToolButton::staticMetaObject();
+ metaObj = QMetaObject::new_metaobject(
+ "KviMenuBarToolButton", parentObject,
+ 0, 0,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviMenuBarToolButton.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviMenuBarToolButton::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviMenuBarToolButton" ) )
+ return this;
+ return KviStyledToolButton::qt_cast( clname );
+}
+
+bool KviMenuBarToolButton::qt_invoke( int _id, QUObject* _o )
+{
+ return KviStyledToolButton::qt_invoke(_id,_o);
+}
+
+bool KviMenuBarToolButton::qt_emit( int _id, QUObject* _o )
+{
+ return KviStyledToolButton::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviMenuBarToolButton::qt_property( int id, int f, QVariant* v)
+{
+ return KviStyledToolButton::qt_property( id, f, v);
+}
+
+bool KviMenuBarToolButton::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
+
+
+const char *KviMdiCaption::className() const
+{
+ return "KviMdiCaption";
+}
+
+QMetaObject *KviMdiCaption::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviMdiCaption( "KviMdiCaption", &KviMdiCaption::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviMdiCaption::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviMdiCaption", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviMdiCaption::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviMdiCaption", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviMdiCaption::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = QWidget::staticMetaObject();
+ metaObj = QMetaObject::new_metaobject(
+ "KviMdiCaption", parentObject,
+ 0, 0,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviMdiCaption.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviMdiCaption::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviMdiCaption" ) )
+ return this;
+ return QWidget::qt_cast( clname );
+}
+
+bool KviMdiCaption::qt_invoke( int _id, QUObject* _o )
+{
+ return QWidget::qt_invoke(_id,_o);
+}
+
+bool KviMdiCaption::qt_emit( int _id, QUObject* _o )
+{
+ return QWidget::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviMdiCaption::qt_property( int id, int f, QVariant* v)
+{
+ return QWidget::qt_property( id, f, v);
+}
+
+bool KviMdiCaption::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvirc/ui/moc_kvi_mdichild.cpp b/src/kvirc/ui/moc_kvi_mdichild.cpp
new file mode 100644
index 00000000..3fcefcda
--- /dev/null
+++ b/src/kvirc/ui/moc_kvi_mdichild.cpp
@@ -0,0 +1,141 @@
+/****************************************************************************
+** KviMdiChild meta object code from reading C++ file 'kvi_mdichild.h'
+**
+** Created: Mon Feb 25 00:12:34 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_mdichild.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviMdiChild::className() const
+{
+ return "KviMdiChild";
+}
+
+QMetaObject *KviMdiChild::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviMdiChild( "KviMdiChild", &KviMdiChild::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviMdiChild::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviMdiChild", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviMdiChild::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviMdiChild", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviMdiChild::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = QFrame::staticMetaObject();
+ static const QUMethod slot_0 = {"maximize", 0, 0 };
+ static const QUMethod slot_1 = {"minimize", 0, 0 };
+ static const QUMethod slot_2 = {"restore", 0, 0 };
+ static const QUMethod slot_3 = {"systemPopupSlot", 0, 0 };
+ static const QUMethod slot_4 = {"closeRequest", 0, 0 };
+ static const QMetaData slot_tbl[] = {
+ { "maximize()", &slot_0, QMetaData::Public },
+ { "minimize()", &slot_1, QMetaData::Public },
+ { "restore()", &slot_2, QMetaData::Public },
+ { "systemPopupSlot()", &slot_3, QMetaData::Public },
+ { "closeRequest()", &slot_4, QMetaData::Public }
+ };
+ static const QUParameter param_signal_0[] = {
+ { "pnt", &static_QUType_varptr, "\x0e", QUParameter::In }
+ };
+ static const QUMethod signal_0 = {"systemPopupRequest", 1, param_signal_0 };
+ static const QMetaData signal_tbl[] = {
+ { "systemPopupRequest(const QPoint&)", &signal_0, QMetaData::Public }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviMdiChild", parentObject,
+ slot_tbl, 5,
+ signal_tbl, 1,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviMdiChild.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviMdiChild::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviMdiChild" ) )
+ return this;
+ return QFrame::qt_cast( clname );
+}
+
+#include <qobjectdefs.h>
+#include <qsignalslotimp.h>
+
+// SIGNAL systemPopupRequest
+void KviMdiChild::systemPopupRequest( const QPoint& t0 )
+{
+ if ( signalsBlocked() )
+ return;
+ QConnectionList *clist = receivers( staticMetaObject()->signalOffset() + 0 );
+ if ( !clist )
+ return;
+ QUObject o[2];
+ static_QUType_varptr.set(o+1,&t0);
+ activate_signal( clist, o );
+}
+
+bool KviMdiChild::qt_invoke( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->slotOffset() ) {
+ case 0: maximize(); break;
+ case 1: minimize(); break;
+ case 2: restore(); break;
+ case 3: systemPopupSlot(); break;
+ case 4: closeRequest(); break;
+ default:
+ return QFrame::qt_invoke( _id, _o );
+ }
+ return TRUE;
+}
+
+bool KviMdiChild::qt_emit( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->signalOffset() ) {
+ case 0: systemPopupRequest((const QPoint&)*((const QPoint*)static_QUType_ptr.get(_o+1))); break;
+ default:
+ return QFrame::qt_emit(_id,_o);
+ }
+ return TRUE;
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviMdiChild::qt_property( int id, int f, QVariant* v)
+{
+ return QFrame::qt_property( id, f, v);
+}
+
+bool KviMdiChild::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvirc/ui/moc_kvi_mdimanager.cpp b/src/kvirc/ui/moc_kvi_mdimanager.cpp
new file mode 100644
index 00000000..fed719be
--- /dev/null
+++ b/src/kvirc/ui/moc_kvi_mdimanager.cpp
@@ -0,0 +1,191 @@
+/****************************************************************************
+** KviMdiManager meta object code from reading C++ file 'kvi_mdimanager.h'
+**
+** Created: Mon Feb 25 00:12:36 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_mdimanager.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviMdiManager::className() const
+{
+ return "KviMdiManager";
+}
+
+QMetaObject *KviMdiManager::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviMdiManager( "KviMdiManager", &KviMdiManager::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviMdiManager::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviMdiManager", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviMdiManager::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviMdiManager", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviMdiManager::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = KviTalScrollView::staticMetaObject();
+ static const QUMethod slot_0 = {"relayoutMenuButtons", 0, 0 };
+ static const QUMethod slot_1 = {"cascadeWindows", 0, 0 };
+ static const QUMethod slot_2 = {"cascadeMaximized", 0, 0 };
+ static const QUMethod slot_3 = {"expandVertical", 0, 0 };
+ static const QUMethod slot_4 = {"expandHorizontal", 0, 0 };
+ static const QUMethod slot_5 = {"minimizeAll", 0, 0 };
+ static const QUMethod slot_6 = {"tile", 0, 0 };
+ static const QUMethod slot_7 = {"toggleAutoTile", 0, 0 };
+ static const QUMethod slot_8 = {"tileAnodine", 0, 0 };
+ static const QUMethod slot_9 = {"reloadImages", 0, 0 };
+ static const QUMethod slot_10 = {"minimizeActiveChild", 0, 0 };
+ static const QUMethod slot_11 = {"restoreActiveChild", 0, 0 };
+ static const QUMethod slot_12 = {"closeActiveChild", 0, 0 };
+ static const QUMethod slot_13 = {"activeChildSystemPopup", 0, 0 };
+ static const QUParameter param_slot_14[] = {
+ { "id", &static_QUType_int, 0, QUParameter::In }
+ };
+ static const QUMethod slot_14 = {"menuActivated", 1, param_slot_14 };
+ static const QUParameter param_slot_15[] = {
+ { "id", &static_QUType_int, 0, QUParameter::In }
+ };
+ static const QUMethod slot_15 = {"tileMethodMenuActivated", 1, param_slot_15 };
+ static const QUMethod slot_16 = {"fillWindowPopup", 0, 0 };
+ static const QUMethod slot_17 = {"sdiMinimizeButtonDestroyed", 0, 0 };
+ static const QUMethod slot_18 = {"sdiRestoreButtonDestroyed", 0, 0 };
+ static const QUMethod slot_19 = {"sdiCloseButtonDestroyed", 0, 0 };
+ static const QUMethod slot_20 = {"sdiIconButtonDestroyed", 0, 0 };
+ static const QMetaData slot_tbl[] = {
+ { "relayoutMenuButtons()", &slot_0, QMetaData::Public },
+ { "cascadeWindows()", &slot_1, QMetaData::Public },
+ { "cascadeMaximized()", &slot_2, QMetaData::Public },
+ { "expandVertical()", &slot_3, QMetaData::Public },
+ { "expandHorizontal()", &slot_4, QMetaData::Public },
+ { "minimizeAll()", &slot_5, QMetaData::Public },
+ { "tile()", &slot_6, QMetaData::Public },
+ { "toggleAutoTile()", &slot_7, QMetaData::Public },
+ { "tileAnodine()", &slot_8, QMetaData::Public },
+ { "reloadImages()", &slot_9, QMetaData::Public },
+ { "minimizeActiveChild()", &slot_10, QMetaData::Protected },
+ { "restoreActiveChild()", &slot_11, QMetaData::Protected },
+ { "closeActiveChild()", &slot_12, QMetaData::Protected },
+ { "activeChildSystemPopup()", &slot_13, QMetaData::Protected },
+ { "menuActivated(int)", &slot_14, QMetaData::Protected },
+ { "tileMethodMenuActivated(int)", &slot_15, QMetaData::Protected },
+ { "fillWindowPopup()", &slot_16, QMetaData::Protected },
+ { "sdiMinimizeButtonDestroyed()", &slot_17, QMetaData::Protected },
+ { "sdiRestoreButtonDestroyed()", &slot_18, QMetaData::Protected },
+ { "sdiCloseButtonDestroyed()", &slot_19, QMetaData::Protected },
+ { "sdiIconButtonDestroyed()", &slot_20, QMetaData::Protected }
+ };
+ static const QUMethod signal_0 = {"enteredSdiMode", 0, 0 };
+ static const QUMethod signal_1 = {"leftSdiMode", 0, 0 };
+ static const QMetaData signal_tbl[] = {
+ { "enteredSdiMode()", &signal_0, QMetaData::Private },
+ { "leftSdiMode()", &signal_1, QMetaData::Private }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviMdiManager", parentObject,
+ slot_tbl, 21,
+ signal_tbl, 2,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviMdiManager.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviMdiManager::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviMdiManager" ) )
+ return this;
+ return KviTalScrollView::qt_cast( clname );
+}
+
+// SIGNAL enteredSdiMode
+void KviMdiManager::enteredSdiMode()
+{
+ activate_signal( staticMetaObject()->signalOffset() + 0 );
+}
+
+// SIGNAL leftSdiMode
+void KviMdiManager::leftSdiMode()
+{
+ activate_signal( staticMetaObject()->signalOffset() + 1 );
+}
+
+bool KviMdiManager::qt_invoke( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->slotOffset() ) {
+ case 0: relayoutMenuButtons(); break;
+ case 1: cascadeWindows(); break;
+ case 2: cascadeMaximized(); break;
+ case 3: expandVertical(); break;
+ case 4: expandHorizontal(); break;
+ case 5: minimizeAll(); break;
+ case 6: tile(); break;
+ case 7: toggleAutoTile(); break;
+ case 8: tileAnodine(); break;
+ case 9: reloadImages(); break;
+ case 10: minimizeActiveChild(); break;
+ case 11: restoreActiveChild(); break;
+ case 12: closeActiveChild(); break;
+ case 13: activeChildSystemPopup(); break;
+ case 14: menuActivated((int)static_QUType_int.get(_o+1)); break;
+ case 15: tileMethodMenuActivated((int)static_QUType_int.get(_o+1)); break;
+ case 16: fillWindowPopup(); break;
+ case 17: sdiMinimizeButtonDestroyed(); break;
+ case 18: sdiRestoreButtonDestroyed(); break;
+ case 19: sdiCloseButtonDestroyed(); break;
+ case 20: sdiIconButtonDestroyed(); break;
+ default:
+ return KviTalScrollView::qt_invoke( _id, _o );
+ }
+ return TRUE;
+}
+
+bool KviMdiManager::qt_emit( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->signalOffset() ) {
+ case 0: enteredSdiMode(); break;
+ case 1: leftSdiMode(); break;
+ default:
+ return KviTalScrollView::qt_emit(_id,_o);
+ }
+ return TRUE;
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviMdiManager::qt_property( int id, int f, QVariant* v)
+{
+ return KviTalScrollView::qt_property( id, f, v);
+}
+
+bool KviMdiManager::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvirc/ui/moc_kvi_statusbar.cpp b/src/kvirc/ui/moc_kvi_statusbar.cpp
new file mode 100644
index 00000000..d3cbf9c4
--- /dev/null
+++ b/src/kvirc/ui/moc_kvi_statusbar.cpp
@@ -0,0 +1,126 @@
+/****************************************************************************
+** KviStatusBar meta object code from reading C++ file 'kvi_statusbar.h'
+**
+** Created: Mon Feb 25 00:12:38 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_statusbar.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviStatusBar::className() const
+{
+ return "KviStatusBar";
+}
+
+QMetaObject *KviStatusBar::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviStatusBar( "KviStatusBar", &KviStatusBar::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviStatusBar::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviStatusBar", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviStatusBar::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviStatusBar", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviStatusBar::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = QStatusBar::staticMetaObject();
+ static const QUMethod slot_0 = {"messageTimerFired", 0, 0 };
+ static const QUMethod slot_1 = {"contextPopupAboutToShow", 0, 0 };
+ static const QUMethod slot_2 = {"appletsPopupAboutToShow", 0, 0 };
+ static const QUParameter param_slot_3[] = {
+ { "id", &static_QUType_int, 0, QUParameter::In }
+ };
+ static const QUMethod slot_3 = {"appletsPopupActivated", 1, param_slot_3 };
+ static const QUMethod slot_4 = {"removeClickedApplet", 0, 0 };
+ static const QUMethod slot_5 = {"setPermanentMessage", 0, 0 };
+ static const QUParameter param_slot_6[] = {
+ { "pTip", &static_QUType_ptr, "KviDynamicToolTip", QUParameter::In },
+ { "pnt", &static_QUType_varptr, "\x0e", QUParameter::In }
+ };
+ static const QUMethod slot_6 = {"tipRequest", 2, param_slot_6 };
+ static const QMetaData slot_tbl[] = {
+ { "messageTimerFired()", &slot_0, QMetaData::Protected },
+ { "contextPopupAboutToShow()", &slot_1, QMetaData::Protected },
+ { "appletsPopupAboutToShow()", &slot_2, QMetaData::Protected },
+ { "appletsPopupActivated(int)", &slot_3, QMetaData::Protected },
+ { "removeClickedApplet()", &slot_4, QMetaData::Protected },
+ { "setPermanentMessage()", &slot_5, QMetaData::Protected },
+ { "tipRequest(KviDynamicToolTip*,const QPoint&)", &slot_6, QMetaData::Protected }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviStatusBar", parentObject,
+ slot_tbl, 7,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviStatusBar.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviStatusBar::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviStatusBar" ) )
+ return this;
+ return QStatusBar::qt_cast( clname );
+}
+
+bool KviStatusBar::qt_invoke( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->slotOffset() ) {
+ case 0: messageTimerFired(); break;
+ case 1: contextPopupAboutToShow(); break;
+ case 2: appletsPopupAboutToShow(); break;
+ case 3: appletsPopupActivated((int)static_QUType_int.get(_o+1)); break;
+ case 4: removeClickedApplet(); break;
+ case 5: setPermanentMessage(); break;
+ case 6: tipRequest((KviDynamicToolTip*)static_QUType_ptr.get(_o+1),(const QPoint&)*((const QPoint*)static_QUType_ptr.get(_o+2))); break;
+ default:
+ return QStatusBar::qt_invoke( _id, _o );
+ }
+ return TRUE;
+}
+
+bool KviStatusBar::qt_emit( int _id, QUObject* _o )
+{
+ return QStatusBar::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviStatusBar::qt_property( int id, int f, QVariant* v)
+{
+ return QStatusBar::qt_property( id, f, v);
+}
+
+bool KviStatusBar::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvirc/ui/moc_kvi_statusbarapplet.cpp b/src/kvirc/ui/moc_kvi_statusbarapplet.cpp
new file mode 100644
index 00000000..85eb55e8
--- /dev/null
+++ b/src/kvirc/ui/moc_kvi_statusbarapplet.cpp
@@ -0,0 +1,496 @@
+/****************************************************************************
+** KviStatusBarApplet meta object code from reading C++ file 'kvi_statusbarapplet.h'
+**
+** Created: Mon Feb 25 00:12:39 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_statusbarapplet.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviStatusBarApplet::className() const
+{
+ return "KviStatusBarApplet";
+}
+
+QMetaObject *KviStatusBarApplet::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviStatusBarApplet( "KviStatusBarApplet", &KviStatusBarApplet::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviStatusBarApplet::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviStatusBarApplet", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviStatusBarApplet::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviStatusBarApplet", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviStatusBarApplet::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = QLabel::staticMetaObject();
+ metaObj = QMetaObject::new_metaobject(
+ "KviStatusBarApplet", parentObject,
+ 0, 0,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviStatusBarApplet.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviStatusBarApplet::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviStatusBarApplet" ) )
+ return this;
+ return QLabel::qt_cast( clname );
+}
+
+bool KviStatusBarApplet::qt_invoke( int _id, QUObject* _o )
+{
+ return QLabel::qt_invoke(_id,_o);
+}
+
+bool KviStatusBarApplet::qt_emit( int _id, QUObject* _o )
+{
+ return QLabel::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviStatusBarApplet::qt_property( int id, int f, QVariant* v)
+{
+ return QLabel::qt_property( id, f, v);
+}
+
+bool KviStatusBarApplet::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
+
+
+const char *KviStatusBarClock::className() const
+{
+ return "KviStatusBarClock";
+}
+
+QMetaObject *KviStatusBarClock::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviStatusBarClock( "KviStatusBarClock", &KviStatusBarClock::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviStatusBarClock::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviStatusBarClock", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviStatusBarClock::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviStatusBarClock", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviStatusBarClock::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = KviStatusBarApplet::staticMetaObject();
+ static const QUMethod slot_0 = {"toggleUtc", 0, 0 };
+ static const QMetaData slot_tbl[] = {
+ { "toggleUtc()", &slot_0, QMetaData::Protected }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviStatusBarClock", parentObject,
+ slot_tbl, 1,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviStatusBarClock.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviStatusBarClock::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviStatusBarClock" ) )
+ return this;
+ return KviStatusBarApplet::qt_cast( clname );
+}
+
+bool KviStatusBarClock::qt_invoke( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->slotOffset() ) {
+ case 0: toggleUtc(); break;
+ default:
+ return KviStatusBarApplet::qt_invoke( _id, _o );
+ }
+ return TRUE;
+}
+
+bool KviStatusBarClock::qt_emit( int _id, QUObject* _o )
+{
+ return KviStatusBarApplet::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviStatusBarClock::qt_property( int id, int f, QVariant* v)
+{
+ return KviStatusBarApplet::qt_property( id, f, v);
+}
+
+bool KviStatusBarClock::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
+
+
+const char *KviStatusBarConnectionTimer::className() const
+{
+ return "KviStatusBarConnectionTimer";
+}
+
+QMetaObject *KviStatusBarConnectionTimer::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviStatusBarConnectionTimer( "KviStatusBarConnectionTimer", &KviStatusBarConnectionTimer::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviStatusBarConnectionTimer::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviStatusBarConnectionTimer", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviStatusBarConnectionTimer::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviStatusBarConnectionTimer", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviStatusBarConnectionTimer::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = KviStatusBarApplet::staticMetaObject();
+ static const QUMethod slot_0 = {"toggleTotal", 0, 0 };
+ static const QMetaData slot_tbl[] = {
+ { "toggleTotal()", &slot_0, QMetaData::Protected }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviStatusBarConnectionTimer", parentObject,
+ slot_tbl, 1,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviStatusBarConnectionTimer.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviStatusBarConnectionTimer::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviStatusBarConnectionTimer" ) )
+ return this;
+ return KviStatusBarApplet::qt_cast( clname );
+}
+
+bool KviStatusBarConnectionTimer::qt_invoke( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->slotOffset() ) {
+ case 0: toggleTotal(); break;
+ default:
+ return KviStatusBarApplet::qt_invoke( _id, _o );
+ }
+ return TRUE;
+}
+
+bool KviStatusBarConnectionTimer::qt_emit( int _id, QUObject* _o )
+{
+ return KviStatusBarApplet::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviStatusBarConnectionTimer::qt_property( int id, int f, QVariant* v)
+{
+ return KviStatusBarApplet::qt_property( id, f, v);
+}
+
+bool KviStatusBarConnectionTimer::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
+
+
+const char *KviStatusBarSeparator::className() const
+{
+ return "KviStatusBarSeparator";
+}
+
+QMetaObject *KviStatusBarSeparator::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviStatusBarSeparator( "KviStatusBarSeparator", &KviStatusBarSeparator::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviStatusBarSeparator::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviStatusBarSeparator", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviStatusBarSeparator::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviStatusBarSeparator", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviStatusBarSeparator::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = KviStatusBarApplet::staticMetaObject();
+ metaObj = QMetaObject::new_metaobject(
+ "KviStatusBarSeparator", parentObject,
+ 0, 0,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviStatusBarSeparator.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviStatusBarSeparator::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviStatusBarSeparator" ) )
+ return this;
+ return KviStatusBarApplet::qt_cast( clname );
+}
+
+bool KviStatusBarSeparator::qt_invoke( int _id, QUObject* _o )
+{
+ return KviStatusBarApplet::qt_invoke(_id,_o);
+}
+
+bool KviStatusBarSeparator::qt_emit( int _id, QUObject* _o )
+{
+ return KviStatusBarApplet::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviStatusBarSeparator::qt_property( int id, int f, QVariant* v)
+{
+ return KviStatusBarApplet::qt_property( id, f, v);
+}
+
+bool KviStatusBarSeparator::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
+
+
+const char *KviStatusBarAwayIndicator::className() const
+{
+ return "KviStatusBarAwayIndicator";
+}
+
+QMetaObject *KviStatusBarAwayIndicator::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviStatusBarAwayIndicator( "KviStatusBarAwayIndicator", &KviStatusBarAwayIndicator::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviStatusBarAwayIndicator::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviStatusBarAwayIndicator", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviStatusBarAwayIndicator::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviStatusBarAwayIndicator", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviStatusBarAwayIndicator::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = KviStatusBarApplet::staticMetaObject();
+ static const QUMethod slot_0 = {"updateDisplay", 0, 0 };
+ static const QUMethod slot_1 = {"toggleContext", 0, 0 };
+ static const QMetaData slot_tbl[] = {
+ { "updateDisplay()", &slot_0, QMetaData::Protected },
+ { "toggleContext()", &slot_1, QMetaData::Protected }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviStatusBarAwayIndicator", parentObject,
+ slot_tbl, 2,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviStatusBarAwayIndicator.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviStatusBarAwayIndicator::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviStatusBarAwayIndicator" ) )
+ return this;
+ return KviStatusBarApplet::qt_cast( clname );
+}
+
+bool KviStatusBarAwayIndicator::qt_invoke( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->slotOffset() ) {
+ case 0: updateDisplay(); break;
+ case 1: toggleContext(); break;
+ default:
+ return KviStatusBarApplet::qt_invoke( _id, _o );
+ }
+ return TRUE;
+}
+
+bool KviStatusBarAwayIndicator::qt_emit( int _id, QUObject* _o )
+{
+ return KviStatusBarApplet::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviStatusBarAwayIndicator::qt_property( int id, int f, QVariant* v)
+{
+ return KviStatusBarApplet::qt_property( id, f, v);
+}
+
+bool KviStatusBarAwayIndicator::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
+
+
+const char *KviStatusBarLagIndicator::className() const
+{
+ return "KviStatusBarLagIndicator";
+}
+
+QMetaObject *KviStatusBarLagIndicator::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviStatusBarLagIndicator( "KviStatusBarLagIndicator", &KviStatusBarLagIndicator::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviStatusBarLagIndicator::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviStatusBarLagIndicator", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviStatusBarLagIndicator::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviStatusBarLagIndicator", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviStatusBarLagIndicator::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = KviStatusBarApplet::staticMetaObject();
+ static const QUMethod slot_0 = {"updateDisplay", 0, 0 };
+ static const QMetaData slot_tbl[] = {
+ { "updateDisplay()", &slot_0, QMetaData::Protected }
+ };
+ metaObj = QMetaObject::new_metaobject(
+ "KviStatusBarLagIndicator", parentObject,
+ slot_tbl, 1,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviStatusBarLagIndicator.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviStatusBarLagIndicator::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviStatusBarLagIndicator" ) )
+ return this;
+ return KviStatusBarApplet::qt_cast( clname );
+}
+
+bool KviStatusBarLagIndicator::qt_invoke( int _id, QUObject* _o )
+{
+ switch ( _id - staticMetaObject()->slotOffset() ) {
+ case 0: updateDisplay(); break;
+ default:
+ return KviStatusBarApplet::qt_invoke( _id, _o );
+ }
+ return TRUE;
+}
+
+bool KviStatusBarLagIndicator::qt_emit( int _id, QUObject* _o )
+{
+ return KviStatusBarApplet::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviStatusBarLagIndicator::qt_property( int id, int f, QVariant* v)
+{
+ return KviStatusBarApplet::qt_property( id, f, v);
+}
+
+bool KviStatusBarLagIndicator::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/kvirc/ui/moc_kvi_toolwindows_container.cpp b/src/kvirc/ui/moc_kvi_toolwindows_container.cpp
new file mode 100644
index 00000000..dc5a24f9
--- /dev/null
+++ b/src/kvirc/ui/moc_kvi_toolwindows_container.cpp
@@ -0,0 +1,165 @@
+/****************************************************************************
+** KviWindowToolWidget meta object code from reading C++ file 'kvi_toolwindows_container.h'
+**
+** Created: Mon Feb 25 00:12:41 2008
+** by: The Qt MOC ($Id: qt/moc_yacc.cpp 3.3.8 edited Feb 2 14:59 $)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#undef QT_NO_COMPAT
+#include "kvi_toolwindows_container.h"
+#include <qmetaobject.h>
+#include <qapplication.h>
+
+#include <private/qucomextra_p.h>
+#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26)
+#error "This file was generated using the moc from 3.3.8. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+const char *KviWindowToolWidget::className() const
+{
+ return "KviWindowToolWidget";
+}
+
+QMetaObject *KviWindowToolWidget::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviWindowToolWidget( "KviWindowToolWidget", &KviWindowToolWidget::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviWindowToolWidget::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviWindowToolWidget", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviWindowToolWidget::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviWindowToolWidget", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviWindowToolWidget::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = QWidget::staticMetaObject();
+ metaObj = QMetaObject::new_metaobject(
+ "KviWindowToolWidget", parentObject,
+ 0, 0,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviWindowToolWidget.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviWindowToolWidget::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviWindowToolWidget" ) )
+ return this;
+ return QWidget::qt_cast( clname );
+}
+
+bool KviWindowToolWidget::qt_invoke( int _id, QUObject* _o )
+{
+ return QWidget::qt_invoke(_id,_o);
+}
+
+bool KviWindowToolWidget::qt_emit( int _id, QUObject* _o )
+{
+ return QWidget::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviWindowToolWidget::qt_property( int id, int f, QVariant* v)
+{
+ return QWidget::qt_property( id, f, v);
+}
+
+bool KviWindowToolWidget::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
+
+
+const char *KviWindowToolPageButton::className() const
+{
+ return "KviWindowToolPageButton";
+}
+
+QMetaObject *KviWindowToolPageButton::metaObj = 0;
+static QMetaObjectCleanUp cleanUp_KviWindowToolPageButton( "KviWindowToolPageButton", &KviWindowToolPageButton::staticMetaObject );
+
+#ifndef QT_NO_TRANSLATION
+QString KviWindowToolPageButton::tr( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviWindowToolPageButton", s, c, QApplication::DefaultCodec );
+ else
+ return QString::fromLatin1( s );
+}
+#ifndef QT_NO_TRANSLATION_UTF8
+QString KviWindowToolPageButton::trUtf8( const char *s, const char *c )
+{
+ if ( qApp )
+ return qApp->translate( "KviWindowToolPageButton", s, c, QApplication::UnicodeUTF8 );
+ else
+ return QString::fromUtf8( s );
+}
+#endif // QT_NO_TRANSLATION_UTF8
+
+#endif // QT_NO_TRANSLATION
+
+QMetaObject* KviWindowToolPageButton::staticMetaObject()
+{
+ if ( metaObj )
+ return metaObj;
+ QMetaObject* parentObject = TOOL_PAGE_PARENT::staticMetaObject();
+ metaObj = QMetaObject::new_metaobject(
+ "KviWindowToolPageButton", parentObject,
+ 0, 0,
+ 0, 0,
+#ifndef QT_NO_PROPERTIES
+ 0, 0,
+ 0, 0,
+#endif // QT_NO_PROPERTIES
+ 0, 0 );
+ cleanUp_KviWindowToolPageButton.setMetaObject( metaObj );
+ return metaObj;
+}
+
+void* KviWindowToolPageButton::qt_cast( const char* clname )
+{
+ if ( !qstrcmp( clname, "KviWindowToolPageButton" ) )
+ return this;
+ return TOOL_PAGE_PARENT::qt_cast( clname );
+}
+
+bool KviWindowToolPageButton::qt_invoke( int _id, QUObject* _o )
+{
+ return TOOL_PAGE_PARENT::qt_invoke(_id,_o);
+}
+
+bool KviWindowToolPageButton::qt_emit( int _id, QUObject* _o )
+{
+ return TOOL_PAGE_PARENT::qt_emit(_id,_o);
+}
+#ifndef QT_NO_PROPERTIES
+
+bool KviWindowToolPageButton::qt_property( int id, int f, QVariant* v)
+{
+ return TOOL_PAGE_PARENT::qt_property( id, f, v);
+}
+
+bool KviWindowToolPageButton::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }
+#endif // QT_NO_PROPERTIES
diff --git a/src/modules/Makefile.am b/src/modules/Makefile.am
new file mode 100644
index 00000000..267a89ef
--- /dev/null
+++ b/src/modules/Makefile.am
@@ -0,0 +1,61 @@
+SUBDIRS = about \
+ action \
+ actioneditor \
+ addon \
+ aliaseditor \
+ avatar \
+ chan \
+ channelsjoin \
+ clock \
+ codetester \
+ config \
+ context \
+ dcc \
+ dialog \
+ editor \
+ eventeditor \
+ file \
+ filetransferwindow \
+ dockwidget \
+ help \
+ http \
+ ident \
+ iograph \
+ lamerizer \
+ links \
+ list \
+ log \
+ logview \
+ mask \
+ math \
+ mediaplayer \
+ mircimport \
+ my \
+ notifier \
+ objects \
+ options \
+ perl \
+ perlcore \
+ popupeditor \
+ raweditor \
+ regchan \
+ reguser \
+ rijndael \
+ setup \
+ sharedfile \
+ sharedfileswindow \
+ snd \
+ socketspy \
+ spaste \
+ str \
+ system \
+ term \
+ texticons \
+ theme \
+ tip \
+ tmphighlight \
+ toolbar \
+ toolbareditor \
+ torrent \
+ url \
+ window
diff --git a/src/modules/about/ENTRIES b/src/modules/about/ENTRIES
new file mode 100644
index 00000000..0e53b3da
--- /dev/null
+++ b/src/modules/about/ENTRIES
@@ -0,0 +1,259 @@
+NAME: Szymon Stefanek
+NICK: Pragma
+MAIL: pragma at kvirc dot net
+ROLE: The "Creator" of KVIrc
+ROLE: Mental work, hand work,
+ROLE: eyes consuming and coffee drinking
+TEXT: I'll check... lemme check...
+TEXT: I'll fix it tomorrow...
+TEXT: KVIrc: the client that can't make coffee
+
+NAME: Jan Wagner
+NICK: Istari
+NICK: spion
+ROLE: Webmaster, bughunter, snapshot mantainer
+ROLE: support gay^Wguy :o) and the man that gives
+ROLE: you KVIrc through IPv6.
+
+NAME: Luk De Ketelaere
+NICK: Balboy
+MAIL: balboy at kvirc dot net
+ROLE: Documentation, bug searching, public relations
+TEXT: No idea of what you're talking about... or why you need it :)
+
+NAME: Andrea Parrella
+NICK: YaP
+MAIL: yap at kvirc dot net
+ROLE: Bug hunting, plugin development, bug fixes,
+ROLE: windows porting and snapshots
+TEXT: why you haven't implemented a class like DoEverythingByYourself ? :)
+TEXT: <Pragma> a wonderful recursive function :)
+TEXT: <YaP> Damn...I knew it eheheheheh
+
+NAME: Christian Strommen
+NICK: Number1
+MAIL: number1 at realityx dot net
+ROLE: Makes sure that nobody is lazy, bug-hunter, a LOT of suggestions and maker of RealityX IRC
+TEXT: Skydiving is almost as exciting as KVIrc scripting!
+TEXT: Pragma: could you add these functions: $rubmyback() and $makecoffe() ?
+
+NAME: Olle Hällnäs
+NICK: Crocodile
+MAIL: olle at xmms dot org
+ROLE: The "open hand" for the KVIrc project.
+ROLE: Provider of the CVS service, www & ftp mirroring, bandwidth,
+ROLE: great ideas and fun while coding.
+
+NAME: Juanjo Alvarez
+NICK: Kane
+MAIL: juanjux at yahoo dot es
+ROLE: Away system, colored nicks, general programming, spanish translantation
+TEXT: Pragma: think of KVIrc as a tool for scripters... we have to left them something to do :)
+
+NAME: Krzysztof Godlewski
+NICK: Kristoff
+MAIL: kristoff at proczta dot wprost dot pl
+ROLE: Official polish beer provider
+ROLE: and plugin developer
+TEXT: echo "STOP IT" > /dev/neighbour
+TEXT: cd ./neighbour && make clean
+TEXT: Pragma...erm...bugs ? WHICH bugs ? ;))
+
+NAME: Christopher R. Gabriel
+NICK: CGabriel
+MAIL: cgabriel at linux dot it
+ROLE: The 'light' inside the GNU clouds
+ROLE: Generic (??!) official project supporter :)
+TEXT: Pragma: seems that kvirc with all its plugins is becoming a desktop environment
+TEXT: echo espresso > /dev/coffee
+TEXT: Pragma: you reached the user limit. WTF!
+
+NAME: Andrew Frolov
+NICK: Drosha@Undernet
+ROLE: Beta testing
+ROLE: Ideator of www.kvirc.org
+TEXT: This free project is better that shareware
+TEXT: mIrc for windows even in alpha stage
+
+NAME: Ted Podgurski
+NICK: alch3m1st
+MAIL: tedp at toocool dot com
+ROLE: Test scripter, bug hunting
+ROLE: ideator & creator of the first www.kvirc.net
+TEXT: whassup ?
+
+NAME: RAD Kade 1
+NICK: RADKade1
+ROLE: Debugging an improvements
+TEXT: I'm just *really* good at doing things
+TEXT: when I have no idea of what I'm actually doing
+
+NAME: Fritz Elfert
+NICK: KNFritz@OpenProjects
+ROLE: Improvements of KVIrc code and of my linux knowledge
+ROLE: I like to think him as a 'spiritual guide'... :D
+
+NAME: Charles Samuels
+NICK: Njaard
+MAIL: charles at altair dot dhs dot org
+ROLE: The KDE man! Making sure that KVirc has a reason to have a K in the beginning
+TEXT: Could I please make KVirc a pure KDE application today?? Pleeease...
+
+NAME: BuTi
+NICK: BuTi@OpenProjects
+MAIL: buti at geocities dot com
+ROLE: Some "tiny" pieces of code
+
+NAME: Nick Betcher
+NICK: Error403
+MAIL: nbetcher at real-time dot com
+TEXT: &lt;Error403&gt; Number1: I imagined you looking crazy :)
+TEXT: "&lt;NumeroUno&gt; I was drunk
+
+NAME: Orn E. Hansen
+NICK: oehansen
+MAIL: oe.hansen at gamma dot telenordia dot se
+ROLE: The official C++ manual and plugin developer
+TEXT: prepare yourselves..
+TEXT: #include <iostream.h>
+TEXT: class testing {...
+TEXT: <oehansen> I must admit, I'm getting confused :-)
+TEXT: <Pragma> Me too , at this point :)
+
+NAME: Giovanni Ferri
+NICK: marl
+MAIL: giovanni at fonderiadigitale dot it
+ROLE: Bug hunter, ideas source :)
+TEXT: buy a pigeon traveller and pass dcc transfers to him
+
+NAME: Anodine
+NICK: [Anodine]
+ROLE: Various funky improvements
+TEXT: I can program anything I set my mind to!
+
+NAME: Paul Boehm
+NICK: infected
+ROLE: Beta testing, language structure improvements
+TEXT: ...it's enough for 100 IPs per meter
+TEXT: on earth, so every lightswitch can have
+TEXT: its own IP...then you telnet to your lightswitch
+TEXT: and turn it off!
+
+NAME: munehiro
+NICK: munehiro
+ROLE: Italian translations, code improvements and many useful suggestions
+
+NAME: Eva Schaller
+NICK: Penny
+ROLE: Italian translation, bug hunting, moral support :))))
+TEXT: KVirc ? Ah! Il dinosauro...
+
+NAME: Christoph Thielecke
+NICK: Crissi
+ROLE: German translation, bug hunting, new ideas
+ROLE: Some scripting, Code improvements + new code ;)
+TEXT: Pragma: Short question...
+
+NAME: Triskelios
+NICK: Triskelios
+MAIL: trisk-kvirc at quasarnet dot org
+ROLE: Breaking everything, and correcting grammar when there isn't anything left to break
+ROLE: Also, listening to Aeri's requests and getting about half of them done...
+TEXT: Hey, it's not my responsibility to find a funny quote of myself ^_~
+
+NAME: Du&#353;an Hok&#367;v
+NICK: Hunterz
+MAIL: dusan at mirc dot cz
+ROLE: Czech translation
+
+NAME: Thilo Shulz
+NICK: Thilo
+ROLE: Bugtracking and constant user support on #kvirc
+
+NAME: Iacopo Palazzi
+NICK: Iakko@IrcNet
+MAIL: iakko at omnikron dot net
+ROLE: Various code patches, ideas and bug hunting
+
+NAME: Thomas Kalla
+NICK: |Tom|@IrcNet
+ROLE: MacOSX porting
+
+NAME: Valeriy Girchenko
+ROLE: Russian translation
+
+NAME: José Melo
+NICK: Ze_M
+ROLE: Portuguese translation, default script patches and Mandriva (MDE) packager.
+
+NAME: Adilson Gonçalves Soares Junior
+NICK: CaBiDe
+MAIL: cabide at brfree dot com dot br
+ROLE: Portuguese Brasilian translation
+
+NAME: Alessandro Carbone
+NICK: Noldor
+MAIL: noldor at barmes dot org
+ROLE: Betatesting, bugfixing, exotic scripting,
+ROLE: code improvements, documentation....To be continued :-)
+TEXT: <Grifisx>...damned brackets  ...there are always too many...
+TEXT: <Noldor>....or too few..
+
+NAME: Tonino Imbesi
+NICK: Grifisx
+MAIL: grifisx at barmes dot org
+ROLE: Betatesting, bugfixing, exotic scripting,
+ROLE: code improvements, documentation....To be continued :-)
+TEXT: <Grifisx> The difference between me and you is just that
+TEXT: <Grifisx> You see things and you say "Why?" But I dream things
+TEXT: <Grifisx> that never were and I say..."Why not?"
+
+NAME: Alexey Uzhva
+NICK: Alexey
+MAIL: wizard at opendoor dot ru
+ROLE: Bugfixing, code improvements, localization improvements
+ROLE: To be continued :-)
+
+NAME: Ahinu
+NICK: Ahinu
+MAIL: ahinu at wanadoo dot fr
+ROLE: French translation, code fixes, betatesting and heavy bughunting
+
+NAME: Cle'
+NICK: Etherea
+MAIL: badgirl at virg0 dot org
+ROLE: Artist :)
+TEXT: Time makes no sense ;)
+
+NAME: Andidas
+NICK: Andidas
+ROLE: Splash screen Artist :)
+MAIL: http://www.andidas.com
+
+NAME: TheXception
+NICK: TheXception
+MAIL: kvirc@thexception.net
+ROLE: bugfixes, german tutorials
+TEXT: everything is possible, it only needs its time.
+
+NAME: Elvio Basello
+NICK: HelLViS69
+MAIL: hellvis69 at netsons dot org
+ROLE: Site (re)creator, Italian translation, scripting,
+ROLE: bughunting, Slackware packages, new ideas...
+TEXT: <HelLViS69> Blessed gdb, in the name of ritchie,
+TEXT: kermingham and rms
+
+NAME: Massimiliano Leone
+NICK: k0sm|k0
+MAIL: k0smik0 at logorroici dot org
+ROLE: Debian packages, moral support
+TEXT: One must make one's self superior to humanity, in power,
+TEXT: in loftiness of soul, in contempt. - Friedrich Nietzsche
+
+NAME: Lorenzo Marcon
+NICK: LoSko
+MAIL: http://losko.altervista.org/nglfserv/
+ROLE: Bug hunting and fixing, doc fixes, scripting (NGL File Server)
+TEXT: I don't know what I want, but I know how to get it.
+
diff --git a/src/modules/about/Makefile.am b/src/modules/about/Makefile.am
new file mode 100644
index 00000000..4192c119
--- /dev/null
+++ b/src/modules/about/Makefile.am
@@ -0,0 +1,27 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkviabout.la
+
+libkviabout_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkviabout_la_SOURCES = libkviabout.cpp aboutdialog.cpp
+
+libkviabout_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+noinst_HEADERS= aboutdialog.h
+
+EXTRA_DIST = mkabouttext.pl abouttext.inc ENTRIES
+
+abouttext:
+ perl mkabouttext.pl
+
+%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
+
+#libkviabout.cpp: libkviabout.moc
+aboutdialog.cpp: aboutdialog.moc
diff --git a/src/modules/about/aboutdialog.cpp b/src/modules/about/aboutdialog.cpp
new file mode 100644
index 00000000..4d13d98f
--- /dev/null
+++ b/src/modules/about/aboutdialog.cpp
@@ -0,0 +1,166 @@
+//=============================================================================
+//
+// File : aboutdialog.cpp
+// Creation date : Sun Jun 23 17:59:12 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "aboutdialog.h"
+
+#include "kvi_defaults.h"
+
+#include "kvi_locale.h"
+#include "kvi_app.h"
+#include "kvi_fileutils.h"
+#include "kvi_sourcesdate.h"
+
+#include <qwidget.h>
+#include <qlayout.h>
+#include <kvi_tal_textedit.h>
+#include <qlabel.h>
+#include <qpixmap.h>
+#include <qevent.h>
+
+extern KviAboutDialog * g_pAboutDialog;
+/*
+"<font color=\"#FFFF00\"><b>KVIrc public releases :</b></font><br>\n" \
+"<br>\n" \
+"<font color=\"#FF0000\">0.9.0</font><br>\n" \
+"<font size=\"2\" color=\"#808080\">Release date: 25.01.1999</font><br>\n" \
+"<br>\n" \
+"<font color=\"#FF0000\">1.0.0 'Millennium'</font><br>\n" \
+"<font size=\"2\">\"The net in your hands\"</font><br>\n" \
+"<font size=\"2\" color=\"#808080\">Release date: 21.12.1999</font><br>\n" \
+"<br>\n" \
+"<font color=\"#FF0000\">2.0.0 'Phoenix'</font><br>\n" \
+"<font size=\"2\">\"The client that can't make coffee\"</font><br>\n" \
+"<font size=\"2\" color=\"#808080\">Release date: 30.05.2000</font><br>\n" \
+"<br>\n" \
+"<font color=\"#FF0000\">2.1.0 'Dark Star'</font><br>\n" \
+"<font size=\"2\">\"The client that can't make coffee\"</font><br>\n" \
+"<font size=\"2\" color=\"#808080\">Release date: 30.01.2001</font><br>\n" \
+"<br>\n" \
+"<font color=\"#FF0000\">2.1.1 'Monolith'</font><br>\n" \
+"<font size=\"2\">\"A breath of fresh net\"</font><br>\n" \
+"<font size=\"2\" color=\"#808080\">Release date: 01.05.2001</font><br>\n" \
+"<br> 3.0.0-xmas build: 24-12-2001\n" \
+"3.0.0-beta1: 24-06-2002\n "
+"<font color=\"#FF0000\">3.0.0 'Avatar'</font><br>\n" \
+"<font size=\"2\">\"No slogan yet\"</font><br>\n" \
+"<font size=\"2\" color=\"#808080\">Release date: Still unknown</font><br>\n" \
+*/
+
+#include "abouttext.inc"
+
+KviAboutDialog::KviAboutDialog()
+: KviTalTabDialog(0)
+{
+ setCaption(__tr2qs_ctx("About KVIrc...","about"));
+ setOkButton(__tr2qs_ctx("Close","about"));
+
+ KviStr buffer;
+ g_pApp->findImage(buffer,"kvi_splash.png");
+
+ QPixmap pix(buffer.ptr());
+
+ QWidget * w = new QWidget(this);
+ QGridLayout * g = new QGridLayout(w,2,1,4,8);
+
+ QLabel * l = new QLabel(w);
+ l->setFrameStyle(QFrame::WinPanel | QFrame::Sunken);
+ l->setBackgroundColor(Qt::black);
+ l->setAlignment(Qt::AlignCenter);
+ l->setPixmap(pix);
+
+ g->addWidget(l,0,0);
+
+ QString aboutString= "KVIrc <b>" KVI_VERSION " '" KVI_RELEASE_NAME "'</b><br>";
+ aboutString += __tr2qs_ctx("Forged by the <b>KVIrc Development Team</b>","about");
+ aboutString += "<br>";
+ aboutString += __tr2qs_ctx("Sources date","about");
+ aboutString += ": ";
+ aboutString += KVI_SOURCES_DATE;
+
+ l = new QLabel(aboutString,w);
+ l->setAlignment(Qt::AlignCenter);
+ g->addWidget(l,1,0);
+
+ addTab(w,__tr2qs_ctx("About","about"));
+
+
+
+ w = new QWidget(this);
+ g = new QGridLayout(w,1,1,4,8);
+
+ KviTalTextEdit * v = new KviTalTextEdit(w);
+ v->setReadOnly(true);
+ g->addWidget(v,0,0);
+
+ v->setText(g_szAboutText);
+
+ addTab(w,__tr2qs_ctx("Honor && Glory","about"));
+
+
+
+ w = new QWidget(this);
+ g = new QGridLayout(w,1,1,4,8);
+
+ v = new KviTalTextEdit(w);
+ v->setReadOnly(true);
+ v->setWordWrap(KviTalTextEdit::NoWrap);
+ g->addWidget(v,0,0);
+
+ QString szLicense;
+
+ QString szLicensePath;
+ g_pApp->getGlobalKvircDirectory(szLicensePath,KviApp::License,"EULA");
+
+ if(!KviFileUtils::loadFile(szLicensePath,szLicense))
+ {
+ szLicense = __tr2qs_ctx("Oops... Can't find the license file...\n" \
+ "It MUST be included in the distribution...\n" \
+ "Please report to <pragma at kvirc dot net>","about");
+ }
+
+ v->setText(szLicense);
+
+ addTab(w,__tr2qs_ctx("License","about"));
+
+
+ connect(this,SIGNAL(applyButtonPressed()),this,SLOT(closeButtonPressed()));
+}
+
+KviAboutDialog::~KviAboutDialog()
+{
+ g_pAboutDialog = 0;
+}
+
+void KviAboutDialog::closeEvent(QCloseEvent *e)
+{
+ e->ignore();
+ delete this;
+}
+
+void KviAboutDialog::closeButtonPressed()
+{
+ delete this;
+}
+
+#include "aboutdialog.moc"
diff --git a/src/modules/about/aboutdialog.h b/src/modules/about/aboutdialog.h
new file mode 100644
index 00000000..da543a19
--- /dev/null
+++ b/src/modules/about/aboutdialog.h
@@ -0,0 +1,39 @@
+#ifndef _ABOUTDIALOG_H_
+#define _ABOUTDIALOG_H_
+//
+// File : aboutdialog.h
+// Creation date : Sun Jun 23 17:59:13 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include <kvi_tal_tabdialog.h>
+
+class KviAboutDialog : public KviTalTabDialog
+{
+ Q_OBJECT
+public:
+ KviAboutDialog();
+ ~KviAboutDialog();
+protected:
+ virtual void closeEvent(QCloseEvent *e);
+protected slots:
+ void closeButtonPressed();
+};
+
+#endif //_ABOUTDIALOG_H_
diff --git a/src/modules/about/abouttext.inc b/src/modules/about/abouttext.inc
new file mode 100644
index 00000000..c35fc173
--- /dev/null
+++ b/src/modules/about/abouttext.inc
@@ -0,0 +1,768 @@
+static char * g_szAboutText = "" \
+"<html>" \
+"<head>" \
+"<title>Honor and glory</title>" \
+"</head>" \
+"<body bgcolor=\"#FFFFFF\" text=\"#000000\" link=\"#FF0000\"><center>" \
+"<h4>" \
+"This is a partial list of the people that have " \
+"contributed in some way to the KVIrc project.<br><br>" \
+"Honor and glory to:<br>" \
+"</h4><br><br>" \
+"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" \
+"<tr><td align=\"center\">" \
+"<font color=\"#000000\" size=\"+2\"><b>Szymon Stefanek</b></font>" \
+"</td></tr>" \
+"<tr><td align=\"center\"><font color=\"#800020\" size=\"+2\"> (" \
+"Pragma" \
+")</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#0000FF\" size=\"+1\">" \
+"[" \
+"pragma at kvirc dot net" \
+"]" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#303030\">" \
+"The \"Creator\" of KVIrc" \
+"<br>" \
+"Mental work, hand work," \
+"<br>" \
+"eyes consuming and coffee drinking" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#606060\"><i>" \
+"\"I'll check... lemme check...\"" \
+"<br>" \
+"\"I'll fix it tomorrow...\"" \
+"<br>" \
+"\"KVIrc: the client that can't make coffee\"" \
+"</i></font></td></tr>" \
+"</table><br><br>" \
+"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" \
+"<tr><td align=\"center\">" \
+"<font color=\"#000000\" size=\"+2\"><b>Jan Wagner</b></font>" \
+"</td></tr>" \
+"<tr><td align=\"center\"><font color=\"#800020\" size=\"+2\"> (" \
+"Istari" \
+", " \
+"spion" \
+")</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#303030\">" \
+"Webmaster, bughunter, snapshot mantainer" \
+"<br>" \
+"support gay^Wguy :o) and the man that gives" \
+"<br>" \
+"you KVIrc through IPv6." \
+"</font></td></tr>" \
+"</table><br><br>" \
+"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" \
+"<tr><td align=\"center\">" \
+"<font color=\"#000000\" size=\"+2\"><b>Luk De Ketelaere</b></font>" \
+"</td></tr>" \
+"<tr><td align=\"center\"><font color=\"#800020\" size=\"+2\"> (" \
+"Balboy" \
+")</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#0000FF\" size=\"+1\">" \
+"[" \
+"balboy at kvirc dot net" \
+"]" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#303030\">" \
+"Documentation, bug searching, public relations" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#606060\"><i>" \
+"\"No idea of what you're talking about... or why you need it :)\"" \
+"</i></font></td></tr>" \
+"</table><br><br>" \
+"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" \
+"<tr><td align=\"center\">" \
+"<font color=\"#000000\" size=\"+2\"><b>Andrea Parrella</b></font>" \
+"</td></tr>" \
+"<tr><td align=\"center\"><font color=\"#800020\" size=\"+2\"> (" \
+"YaP" \
+")</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#0000FF\" size=\"+1\">" \
+"[" \
+"yap at kvirc dot net" \
+"]" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#303030\">" \
+"Bug hunting, plugin development, bug fixes," \
+"<br>" \
+"windows porting and snapshots" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#606060\"><i>" \
+"\"why you haven't implemented a class like DoEverythingByYourself ? :)\"" \
+"<br>" \
+"\"&lt;Pragma&gt; a wonderful recursive function :)\"" \
+"<br>" \
+"\"&lt;YaP&gt; Damn...I knew it eheheheheh\"" \
+"</i></font></td></tr>" \
+"</table><br><br>" \
+"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" \
+"<tr><td align=\"center\">" \
+"<font color=\"#000000\" size=\"+2\"><b>Christian Strommen</b></font>" \
+"</td></tr>" \
+"<tr><td align=\"center\"><font color=\"#800020\" size=\"+2\"> (" \
+"Number1" \
+")</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#0000FF\" size=\"+1\">" \
+"[" \
+"number1 at realityx dot net" \
+"]" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#303030\">" \
+"Makes sure that nobody is lazy, bug-hunter, a LOT of suggestions and maker of RealityX IRC" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#606060\"><i>" \
+"\"Skydiving is almost as exciting as KVIrc scripting!\"" \
+"<br>" \
+"\"Pragma: could you add these functions: $rubmyback() and $makecoffe() ?\"" \
+"</i></font></td></tr>" \
+"</table><br><br>" \
+"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" \
+"<tr><td align=\"center\">" \
+"<font color=\"#000000\" size=\"+2\"><b>Olle Hällnäs</b></font>" \
+"</td></tr>" \
+"<tr><td align=\"center\"><font color=\"#800020\" size=\"+2\"> (" \
+"Crocodile" \
+")</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#0000FF\" size=\"+1\">" \
+"[" \
+"olle at xmms dot org" \
+"]" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#303030\">" \
+"The \"open hand\" for the KVIrc project." \
+"<br>" \
+"Provider of the CVS service, www & ftp mirroring, bandwidth," \
+"<br>" \
+"great ideas and fun while coding." \
+"</font></td></tr>" \
+"</table><br><br>" \
+"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" \
+"<tr><td align=\"center\">" \
+"<font color=\"#000000\" size=\"+2\"><b>Juanjo Alvarez</b></font>" \
+"</td></tr>" \
+"<tr><td align=\"center\"><font color=\"#800020\" size=\"+2\"> (" \
+"Kane" \
+")</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#0000FF\" size=\"+1\">" \
+"[" \
+"juanjux at yahoo dot es" \
+"]" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#303030\">" \
+"Away system, colored nicks, general programming, spanish translantation" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#606060\"><i>" \
+"\"Pragma: think of KVIrc as a tool for scripters... we have to left them something to do :)\"" \
+"</i></font></td></tr>" \
+"</table><br><br>" \
+"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" \
+"<tr><td align=\"center\">" \
+"<font color=\"#000000\" size=\"+2\"><b>Krzysztof Godlewski</b></font>" \
+"</td></tr>" \
+"<tr><td align=\"center\"><font color=\"#800020\" size=\"+2\"> (" \
+"Kristoff" \
+")</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#0000FF\" size=\"+1\">" \
+"[" \
+"kristoff at proczta dot wprost dot pl" \
+"]" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#303030\">" \
+"Official polish beer provider" \
+"<br>" \
+"and plugin developer" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#606060\"><i>" \
+"\"echo \"STOP IT\" &gt; /dev/neighbour\"" \
+"<br>" \
+"\"cd ./neighbour && make clean\"" \
+"<br>" \
+"\"Pragma...erm...bugs ? WHICH bugs ? ;))\"" \
+"</i></font></td></tr>" \
+"</table><br><br>" \
+"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" \
+"<tr><td align=\"center\">" \
+"<font color=\"#000000\" size=\"+2\"><b>Christopher R. Gabriel</b></font>" \
+"</td></tr>" \
+"<tr><td align=\"center\"><font color=\"#800020\" size=\"+2\"> (" \
+"CGabriel" \
+")</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#0000FF\" size=\"+1\">" \
+"[" \
+"cgabriel at linux dot it" \
+"]" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#303030\">" \
+"The 'light' inside the GNU clouds" \
+"<br>" \
+"Generic (??!) official project supporter :)" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#606060\"><i>" \
+"\"Pragma: seems that kvirc with all its plugins is becoming a desktop environment\"" \
+"<br>" \
+"\"echo espresso &gt; /dev/coffee\"" \
+"<br>" \
+"\"Pragma: you reached the user limit. WTF!\"" \
+"</i></font></td></tr>" \
+"</table><br><br>" \
+"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" \
+"<tr><td align=\"center\">" \
+"<font color=\"#000000\" size=\"+2\"><b>Andrew Frolov</b></font>" \
+"</td></tr>" \
+"<tr><td align=\"center\"><font color=\"#800020\" size=\"+2\"> (" \
+"Drosha@Undernet" \
+")</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#303030\">" \
+"Beta testing" \
+"<br>" \
+"Ideator of www.kvirc.org" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#606060\"><i>" \
+"\"This free project is better that shareware\"" \
+"<br>" \
+"\"mIrc for windows even in alpha stage\"" \
+"</i></font></td></tr>" \
+"</table><br><br>" \
+"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" \
+"<tr><td align=\"center\">" \
+"<font color=\"#000000\" size=\"+2\"><b>Ted Podgurski</b></font>" \
+"</td></tr>" \
+"<tr><td align=\"center\"><font color=\"#800020\" size=\"+2\"> (" \
+"alch3m1st" \
+")</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#0000FF\" size=\"+1\">" \
+"[" \
+"tedp at toocool dot com" \
+"]" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#303030\">" \
+"Test scripter, bug hunting" \
+"<br>" \
+"ideator & creator of the first www.kvirc.net" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#606060\"><i>" \
+"\"whassup ?\"" \
+"</i></font></td></tr>" \
+"</table><br><br>" \
+"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" \
+"<tr><td align=\"center\">" \
+"<font color=\"#000000\" size=\"+2\"><b>RAD Kade 1</b></font>" \
+"</td></tr>" \
+"<tr><td align=\"center\"><font color=\"#800020\" size=\"+2\"> (" \
+"RADKade1" \
+")</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#303030\">" \
+"Debugging an improvements" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#606060\"><i>" \
+"\"I'm just *really* good at doing things\"" \
+"<br>" \
+"\"when I have no idea of what I'm actually doing\"" \
+"</i></font></td></tr>" \
+"</table><br><br>" \
+"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" \
+"<tr><td align=\"center\">" \
+"<font color=\"#000000\" size=\"+2\"><b>Fritz Elfert</b></font>" \
+"</td></tr>" \
+"<tr><td align=\"center\"><font color=\"#800020\" size=\"+2\"> (" \
+"KNFritz@OpenProjects" \
+")</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#303030\">" \
+"Improvements of KVIrc code and of my linux knowledge" \
+"<br>" \
+"I like to think him as a 'spiritual guide'... :D" \
+"</font></td></tr>" \
+"</table><br><br>" \
+"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" \
+"<tr><td align=\"center\">" \
+"<font color=\"#000000\" size=\"+2\"><b>Charles Samuels</b></font>" \
+"</td></tr>" \
+"<tr><td align=\"center\"><font color=\"#800020\" size=\"+2\"> (" \
+"Njaard" \
+")</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#0000FF\" size=\"+1\">" \
+"[" \
+"charles at altair dot dhs dot org" \
+"]" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#303030\">" \
+"The KDE man! Making sure that KVirc has a reason to have a K in the beginning" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#606060\"><i>" \
+"\"Could I please make KVirc a pure KDE application today?? Pleeease...\"" \
+"</i></font></td></tr>" \
+"</table><br><br>" \
+"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" \
+"<tr><td align=\"center\">" \
+"<font color=\"#000000\" size=\"+2\"><b>BuTi</b></font>" \
+"</td></tr>" \
+"<tr><td align=\"center\"><font color=\"#800020\" size=\"+2\"> (" \
+"BuTi@OpenProjects" \
+")</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#0000FF\" size=\"+1\">" \
+"[" \
+"buti at geocities dot com" \
+"]" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#303030\">" \
+"Some \"tiny\" pieces of code" \
+"</font></td></tr>" \
+"</table><br><br>" \
+"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" \
+"<tr><td align=\"center\">" \
+"<font color=\"#000000\" size=\"+2\"><b>Nick Betcher</b></font>" \
+"</td></tr>" \
+"<tr><td align=\"center\"><font color=\"#800020\" size=\"+2\"> (" \
+"Error403" \
+")</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#0000FF\" size=\"+1\">" \
+"[" \
+"nbetcher at real-time dot com" \
+"]" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#606060\"><i>" \
+"\"&lt;Error403&gt; Number1: I imagined you looking crazy :)\"" \
+"<br>" \
+"\"\"&lt;NumeroUno&gt; I was drunk\"" \
+"</i></font></td></tr>" \
+"</table><br><br>" \
+"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" \
+"<tr><td align=\"center\">" \
+"<font color=\"#000000\" size=\"+2\"><b>Orn E. Hansen</b></font>" \
+"</td></tr>" \
+"<tr><td align=\"center\"><font color=\"#800020\" size=\"+2\"> (" \
+"oehansen" \
+")</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#0000FF\" size=\"+1\">" \
+"[" \
+"oe.hansen at gamma dot telenordia dot se" \
+"]" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#303030\">" \
+"The official C++ manual and plugin developer" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#606060\"><i>" \
+"\"prepare yourselves..\"" \
+"<br>" \
+"\"#include &lt;iostream.h&gt;\"" \
+"<br>" \
+"\"class testing {...\"" \
+"<br>" \
+"\"&lt;oehansen&gt; I must admit, I'm getting confused :-)\"" \
+"<br>" \
+"\"&lt;Pragma&gt; Me too , at this point :)\"" \
+"</i></font></td></tr>" \
+"</table><br><br>" \
+"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" \
+"<tr><td align=\"center\">" \
+"<font color=\"#000000\" size=\"+2\"><b>Giovanni Ferri</b></font>" \
+"</td></tr>" \
+"<tr><td align=\"center\"><font color=\"#800020\" size=\"+2\"> (" \
+"marl" \
+")</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#0000FF\" size=\"+1\">" \
+"[" \
+"giovanni at fonderiadigitale dot it" \
+"]" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#303030\">" \
+"Bug hunter, ideas source :)" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#606060\"><i>" \
+"\"buy a pigeon traveller and pass dcc transfers to him\"" \
+"</i></font></td></tr>" \
+"</table><br><br>" \
+"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" \
+"<tr><td align=\"center\">" \
+"<font color=\"#000000\" size=\"+2\"><b>Anodine</b></font>" \
+"</td></tr>" \
+"<tr><td align=\"center\"><font color=\"#800020\" size=\"+2\"> (" \
+"[Anodine]" \
+")</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#303030\">" \
+"Various funky improvements" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#606060\"><i>" \
+"\"I can program anything I set my mind to!\"" \
+"</i></font></td></tr>" \
+"</table><br><br>" \
+"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" \
+"<tr><td align=\"center\">" \
+"<font color=\"#000000\" size=\"+2\"><b>Paul Boehm</b></font>" \
+"</td></tr>" \
+"<tr><td align=\"center\"><font color=\"#800020\" size=\"+2\"> (" \
+"infected" \
+")</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#303030\">" \
+"Beta testing, language structure improvements" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#606060\"><i>" \
+"\"...it's enough for 100 IPs per meter\"" \
+"<br>" \
+"\"on earth, so every lightswitch can have\"" \
+"<br>" \
+"\"its own IP...then you telnet to your lightswitch\"" \
+"<br>" \
+"\"and turn it off!\"" \
+"</i></font></td></tr>" \
+"</table><br><br>" \
+"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" \
+"<tr><td align=\"center\">" \
+"<font color=\"#000000\" size=\"+2\"><b>munehiro</b></font>" \
+"</td></tr>" \
+"<tr><td align=\"center\"><font color=\"#800020\" size=\"+2\"> (" \
+"munehiro" \
+")</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#303030\">" \
+"Italian translations, code improvements and many useful suggestions" \
+"</font></td></tr>" \
+"</table><br><br>" \
+"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" \
+"<tr><td align=\"center\">" \
+"<font color=\"#000000\" size=\"+2\"><b>Eva Schaller</b></font>" \
+"</td></tr>" \
+"<tr><td align=\"center\"><font color=\"#800020\" size=\"+2\"> (" \
+"Penny" \
+")</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#303030\">" \
+"Italian translation, bug hunting, moral support :))))" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#606060\"><i>" \
+"\"KVirc ? Ah! Il dinosauro...\"" \
+"</i></font></td></tr>" \
+"</table><br><br>" \
+"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" \
+"<tr><td align=\"center\">" \
+"<font color=\"#000000\" size=\"+2\"><b>Christoph Thielecke</b></font>" \
+"</td></tr>" \
+"<tr><td align=\"center\"><font color=\"#800020\" size=\"+2\"> (" \
+"Crissi" \
+")</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#303030\">" \
+"German translation, bug hunting, new ideas" \
+"<br>" \
+"Some scripting, Code improvements + new code ;)" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#606060\"><i>" \
+"\"Pragma: Short question...\"" \
+"</i></font></td></tr>" \
+"</table><br><br>" \
+"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" \
+"<tr><td align=\"center\">" \
+"<font color=\"#000000\" size=\"+2\"><b>Triskelios</b></font>" \
+"</td></tr>" \
+"<tr><td align=\"center\"><font color=\"#800020\" size=\"+2\"> (" \
+"Triskelios" \
+")</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#0000FF\" size=\"+1\">" \
+"[" \
+"trisk-kvirc at quasarnet dot org" \
+"]" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#303030\">" \
+"Breaking everything, and correcting grammar when there isn't anything left to break" \
+"<br>" \
+"Also, listening to Aeri's requests and getting about half of them done..." \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#606060\"><i>" \
+"\"Hey, it's not my responsibility to find a funny quote of myself ^_~\"" \
+"</i></font></td></tr>" \
+"</table><br><br>" \
+"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" \
+"<tr><td align=\"center\">" \
+"<font color=\"#000000\" size=\"+2\"><b>Du&#353;an Hok&#367;v</b></font>" \
+"</td></tr>" \
+"<tr><td align=\"center\"><font color=\"#800020\" size=\"+2\"> (" \
+"Hunterz" \
+")</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#0000FF\" size=\"+1\">" \
+"[" \
+"dusan at mirc dot cz" \
+"]" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#303030\">" \
+"Czech translation" \
+"</font></td></tr>" \
+"</table><br><br>" \
+"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" \
+"<tr><td align=\"center\">" \
+"<font color=\"#000000\" size=\"+2\"><b>Thilo Shulz</b></font>" \
+"</td></tr>" \
+"<tr><td align=\"center\"><font color=\"#800020\" size=\"+2\"> (" \
+"Thilo" \
+")</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#303030\">" \
+"Bugtracking and constant user support on #kvirc" \
+"</font></td></tr>" \
+"</table><br><br>" \
+"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" \
+"<tr><td align=\"center\">" \
+"<font color=\"#000000\" size=\"+2\"><b>Iacopo Palazzi</b></font>" \
+"</td></tr>" \
+"<tr><td align=\"center\"><font color=\"#800020\" size=\"+2\"> (" \
+"Iakko@IrcNet" \
+")</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#0000FF\" size=\"+1\">" \
+"[" \
+"iakko at omnikron dot net" \
+"]" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#303030\">" \
+"Various code patches, ideas and bug hunting" \
+"</font></td></tr>" \
+"</table><br><br>" \
+"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" \
+"<tr><td align=\"center\">" \
+"<font color=\"#000000\" size=\"+2\"><b>Thomas Kalla</b></font>" \
+"</td></tr>" \
+"<tr><td align=\"center\"><font color=\"#800020\" size=\"+2\"> (" \
+"|Tom|@IrcNet" \
+")</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#303030\">" \
+"MacOSX porting" \
+"</font></td></tr>" \
+"</table><br><br>" \
+"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" \
+"<tr><td align=\"center\">" \
+"<font color=\"#000000\" size=\"+2\"><b>Valeriy Girchenko</b></font>" \
+"</td></tr>" \
+"<tr><td align=\"center\"><font color=\"#303030\">" \
+"Russian translation" \
+"</font></td></tr>" \
+"</table><br><br>" \
+"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" \
+"<tr><td align=\"center\">" \
+"<font color=\"#000000\" size=\"+2\"><b>José Melo</b></font>" \
+"</td></tr>" \
+"<tr><td align=\"center\"><font color=\"#800020\" size=\"+2\"> (" \
+"Ze_M" \
+")</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#303030\">" \
+"Portuguese translation, default script patches and Mandriva (MDE) packager." \
+"</font></td></tr>" \
+"</table><br><br>" \
+"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" \
+"<tr><td align=\"center\">" \
+"<font color=\"#000000\" size=\"+2\"><b>Adilson Gonçalves Soares Junior</b></font>" \
+"</td></tr>" \
+"<tr><td align=\"center\"><font color=\"#800020\" size=\"+2\"> (" \
+"CaBiDe" \
+")</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#0000FF\" size=\"+1\">" \
+"[" \
+"cabide at brfree dot com dot br" \
+"]" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#303030\">" \
+"Portuguese Brasilian translation" \
+"</font></td></tr>" \
+"</table><br><br>" \
+"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" \
+"<tr><td align=\"center\">" \
+"<font color=\"#000000\" size=\"+2\"><b>Alessandro Carbone</b></font>" \
+"</td></tr>" \
+"<tr><td align=\"center\"><font color=\"#800020\" size=\"+2\"> (" \
+"Noldor" \
+")</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#0000FF\" size=\"+1\">" \
+"[" \
+"noldor at barmes dot org" \
+"]" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#303030\">" \
+"Betatesting, bugfixing, exotic scripting," \
+"<br>" \
+"code improvements, documentation....To be continued :-)" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#606060\"><i>" \
+"\"&lt;Grifisx&gt;...damned brackets  ...there are always too many...\"" \
+"<br>" \
+"\"&lt;Noldor&gt;....or too few..\"" \
+"</i></font></td></tr>" \
+"</table><br><br>" \
+"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" \
+"<tr><td align=\"center\">" \
+"<font color=\"#000000\" size=\"+2\"><b>Tonino Imbesi</b></font>" \
+"</td></tr>" \
+"<tr><td align=\"center\"><font color=\"#800020\" size=\"+2\"> (" \
+"Grifisx" \
+")</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#0000FF\" size=\"+1\">" \
+"[" \
+"grifisx at barmes dot org" \
+"]" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#303030\">" \
+"Betatesting, bugfixing, exotic scripting," \
+"<br>" \
+"code improvements, documentation....To be continued :-)" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#606060\"><i>" \
+"\"&lt;Grifisx&gt; The difference between me and you is just that\"" \
+"<br>" \
+"\"&lt;Grifisx&gt; You see things and you say \"Why?\" But I dream things \"" \
+"<br>" \
+"\"&lt;Grifisx&gt; that never were and I say...\"Why not?\"\"" \
+"</i></font></td></tr>" \
+"</table><br><br>" \
+"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" \
+"<tr><td align=\"center\">" \
+"<font color=\"#000000\" size=\"+2\"><b>Alexey Uzhva</b></font>" \
+"</td></tr>" \
+"<tr><td align=\"center\"><font color=\"#800020\" size=\"+2\"> (" \
+"Alexey" \
+")</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#0000FF\" size=\"+1\">" \
+"[" \
+"wizard at opendoor dot ru" \
+"]" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#303030\">" \
+"Bugfixing, code improvements, localization improvements" \
+"<br>" \
+"To be continued :-)" \
+"</font></td></tr>" \
+"</table><br><br>" \
+"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" \
+"<tr><td align=\"center\">" \
+"<font color=\"#000000\" size=\"+2\"><b>Ahinu</b></font>" \
+"</td></tr>" \
+"<tr><td align=\"center\"><font color=\"#800020\" size=\"+2\"> (" \
+"Ahinu" \
+")</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#0000FF\" size=\"+1\">" \
+"[" \
+"ahinu at wanadoo dot fr " \
+"]" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#303030\">" \
+"French translation, code fixes, betatesting and heavy bughunting" \
+"</font></td></tr>" \
+"</table><br><br>" \
+"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" \
+"<tr><td align=\"center\">" \
+"<font color=\"#000000\" size=\"+2\"><b>Cle'</b></font>" \
+"</td></tr>" \
+"<tr><td align=\"center\"><font color=\"#800020\" size=\"+2\"> (" \
+"Etherea" \
+")</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#0000FF\" size=\"+1\">" \
+"[" \
+"badgirl at virg0 dot org" \
+"]" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#303030\">" \
+"Artist :)" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#606060\"><i>" \
+"\"Time makes no sense ;)\"" \
+"</i></font></td></tr>" \
+"</table><br><br>" \
+"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" \
+"<tr><td align=\"center\">" \
+"<font color=\"#000000\" size=\"+2\"><b>Andidas</b></font>" \
+"</td></tr>" \
+"<tr><td align=\"center\"><font color=\"#800020\" size=\"+2\"> (" \
+"Andidas" \
+")</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#0000FF\" size=\"+1\">" \
+"[" \
+"http://www.andidas.com" \
+"]" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#303030\">" \
+"Splash screen Artist :)" \
+"</font></td></tr>" \
+"</table><br><br>" \
+"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" \
+"<tr><td align=\"center\">" \
+"<font color=\"#000000\" size=\"+2\"><b>TheXception</b></font>" \
+"</td></tr>" \
+"<tr><td align=\"center\"><font color=\"#800020\" size=\"+2\"> (" \
+"TheXception" \
+")</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#0000FF\" size=\"+1\">" \
+"[" \
+"kvirc@thexception.net" \
+"]" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#303030\">" \
+"bugfixes, german tutorials" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#606060\"><i>" \
+"\"everything is possible, it only needs its time.\"" \
+"</i></font></td></tr>" \
+"</table><br><br>" \
+"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" \
+"<tr><td align=\"center\">" \
+"<font color=\"#000000\" size=\"+2\"><b>Elvio Basello</b></font>" \
+"</td></tr>" \
+"<tr><td align=\"center\"><font color=\"#800020\" size=\"+2\"> (" \
+"HelLViS69" \
+")</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#0000FF\" size=\"+1\">" \
+"[" \
+"hellvis69 at netsons dot org" \
+"]" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#303030\">" \
+"Site (re)creator, Italian translation, scripting," \
+"<br>" \
+"bughunting, Slackware packages, new ideas..." \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#606060\"><i>" \
+"\"&lt;HelLViS69&gt; Blessed gdb, in the name of ritchie,\"" \
+"<br>" \
+"\"kermingham and rms\"" \
+"</i></font></td></tr>" \
+"</table><br><br>" \
+"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" \
+"<tr><td align=\"center\">" \
+"<font color=\"#000000\" size=\"+2\"><b>Massimiliano Leone</b></font>" \
+"</td></tr>" \
+"<tr><td align=\"center\"><font color=\"#800020\" size=\"+2\"> (" \
+"k0sm|k0" \
+")</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#0000FF\" size=\"+1\">" \
+"[" \
+"k0smik0 at logorroici dot org" \
+"]" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#303030\">" \
+"Debian packages, moral support" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#606060\"><i>" \
+"\"One must make one's self superior to humanity, in power,\"" \
+"<br>" \
+"\"in loftiness of soul, in contempt. - Friedrich Nietzsche\"" \
+"</i></font></td></tr>" \
+"</table><br><br>" \
+"<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">" \
+"<tr><td align=\"center\">" \
+"<font color=\"#000000\" size=\"+2\"><b>Lorenzo Marcon</b></font>" \
+"</td></tr>" \
+"<tr><td align=\"center\"><font color=\"#800020\" size=\"+2\"> (" \
+"LoSko" \
+")</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#0000FF\" size=\"+1\">" \
+"[" \
+"http://losko.altervista.org/nglfserv/" \
+"]" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#303030\">" \
+"Bug hunting and fixing, doc fixes, scripting (NGL File Server)" \
+"</font></td></tr>" \
+"<tr><td align=\"center\"><font color=\"#606060\"><i>" \
+"\"I don't know what I want, but I know how to get it.\"" \
+"</i></font></td></tr>" \
+"</table><br><br>" \
+"<br>" \
+"This list is far from being complete.<br>" \
+"A lot of more or less \"anonymous\" people have wasted their time, " \
+"eyes, bandwidth and brain resources on this project.<br>" \
+"If you're one of those, then well, this dialog is also for you :)<br>" \
+"</center><body>" \
+"</html>" \
+"";
diff --git a/src/modules/about/libkviabout.cpp b/src/modules/about/libkviabout.cpp
new file mode 100644
index 00000000..c7cb899c
--- /dev/null
+++ b/src/modules/about/libkviabout.cpp
@@ -0,0 +1,100 @@
+//=============================================================================
+//
+// File : kvi_about.cpp
+// Creation date : Tue Jul 6 1999 03:54:25 by Szymon Stefanek
+// Last major modification : Tue Dec 05 2000 06:00:00 by Christian Strmmen
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Till Bush (buti at geocities dot com)
+// Copyright (C) 1999-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_module.h"
+#include "kvi_locale.h"
+
+
+#include "aboutdialog.h"
+
+KviAboutDialog * g_pAboutDialog = 0;
+
+/*
+ @doc: about.kvirc
+ @type:
+ command
+ @title:
+ about.kvirc
+ @short:
+ Shows the "about kvirc" dialog
+ @syntax:
+ about.kvirc
+ @description:
+ Shows the KVIrc "about dialog".
+ This command is exported by the "about" module.
+*/
+
+
+static bool about_kvs_command_kvirc(KviKvsModuleCommandCall *)
+{
+ if(!g_pAboutDialog)
+ {
+ g_pAboutDialog = new KviAboutDialog();
+ g_pAboutDialog->show();
+ } else {
+ g_pAboutDialog->raise();
+ }
+ return true;
+}
+
+
+// =======================================
+// init routine
+// =======================================
+
+static bool about_module_init(KviModule * m)
+{
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"kvirc",about_kvs_command_kvirc)
+ return true;
+}
+
+static bool about_module_cleanup(KviModule *m)
+{
+ if(g_pAboutDialog)delete g_pAboutDialog;
+ g_pAboutDialog = 0;
+ return true;
+}
+
+static bool about_module_can_unload(KviModule * m)
+{
+ return (!g_pAboutDialog);
+}
+
+// =======================================
+// plugin definition structure
+// =======================================
+
+KVIRC_MODULE(
+ "KVIrc about dialog",
+ "2.0.0",
+ "Till Bush <buti@geocities.com>\n" \
+ "Szymon Stefanek <pragma at kvirc dot net>" ,
+ "Exports the /about.kvirc command\n",
+ about_module_init ,
+ about_module_can_unload,
+ 0,
+ about_module_cleanup
+)
diff --git a/src/modules/about/mkabouttext.pl b/src/modules/about/mkabouttext.pl
new file mode 100644
index 00000000..0b58a42c
--- /dev/null
+++ b/src/modules/about/mkabouttext.pl
@@ -0,0 +1,172 @@
+#!/usr/bin/perl
+
+open(TEMPLATE,"ENTRIES") or die "Can't open the ENTRIES file";
+
+$cnt = -1;
+
+while(<TEMPLATE>)
+{
+ $_ =~ s/\n//g;
+ $_ =~ s/</&lt;/g;
+ $_ =~ s/>/&gt;/g;
+
+ if(/^NAME:[ ]*/)
+ {
+ $_ =~ s/^NAME:[ ]*//;
+ $cnt++;
+ $g_names[$cnt]=$_;
+ } elsif(/^MAIL:[ ]*/)
+ {
+ $_ =~ s/^MAIL:[ ]*//;
+ $tmp = $g_mails[$cnt];
+ if($tmp ne "")
+ {
+ $tmp = "$tmp<!!!>";
+ }
+ $tmp = "$tmp$_";
+ $g_mails[$cnt] = $tmp;
+ } elsif(/^ROLE:[ ]*/)
+ {
+ $_ =~ s/^ROLE:[ ]*//;
+ $tmp = $g_roles[$cnt];
+ if($tmp ne "")
+ {
+ $tmp = "$tmp<!!!>";
+ }
+ $tmp = "$tmp$_";
+ $g_roles[$cnt] = $tmp;
+ } elsif(/^TEXT:[ ]*/)
+ {
+ $_ =~ s/^TEXT:[ ]*//;
+ $tmp = $g_texts[$cnt];
+ if($tmp ne "")
+ {
+ $tmp = "$tmp<!!!>";
+ }
+ $tmp = "$tmp$_";
+ $g_texts[$cnt] = $tmp;
+ } elsif(/^NICK:[ ]*/)
+ {
+ $_ =~ s/^NICK:[ ]*//;
+ $tmp = $g_nicks[$cnt];
+ if($tmp ne "")
+ {
+ $tmp = "$tmp<!!!>";
+ }
+ $tmp = "$tmp$_";
+ $g_nicks[$cnt] = $tmp;
+ }
+}
+
+close(TEMPLATE);
+
+sub p
+{
+ $t = $_[0];
+ $t =~ s/\"/\\\"/g;
+ $t =~ s/^[ ]*//g;
+ print OUT "\"$t\" \\\n";
+}
+
+open(OUT,">abouttext.inc") or die "Can't open abouttext.inc";
+
+print OUT "static char * g_szAboutText = \"\" \\\n";
+
+p "<html>";
+p " <head>";
+p " <title>Honor and glory</title>";
+p " </head>";
+p " <body bgcolor=\"#FFFFFF\" text=\"#000000\" link=\"#FF0000\"><center>";
+
+
+p " <h4>";
+p "This is a partial list of the people that have ";
+p "contributed in some way to the KVIrc project.<br><br>";
+p "Honor and glory to:<br>";
+p " </h4><br><br>";
+
+$i = 0;
+$cnt++;
+while($i < $cnt)
+{
+ p "<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">";
+ p "<tr><td align=\"center\">";
+ p "<font color=\"#000000\" size=\"+2\"><b>$g_names[$i]</b></font>";
+ p "</td></tr>";
+
+ if($g_nicks[$i] ne "")
+ {
+
+ p "<tr><td align=\"center\"><font color=\"#800020\" size=\"+2\"> (";
+ @n = split(/<!!!>/,$g_nicks[$i]);
+ $j = 0;
+ while($n[$j] ne "")
+ {
+ if($j > 0){ p ", "; }
+ p $n[$j];
+ $j++;
+ }
+ p ")</font></td></tr>";
+
+ }
+
+ if($g_mails[$i] ne "")
+ {
+ p "<tr><td align=\"center\"><font color=\"#0000FF\" size=\"+1\">";
+ @n = split(/<!!!>/,$g_mails[$i]);
+ $j = 0;
+ while($n[$j] ne "")
+ {
+ if($j > 0){ p "<br>"; }
+ p "[";
+ p $n[$j];
+ p "]";
+ $j++;
+ }
+ p "</font></td></tr>";
+ }
+
+ if($g_roles[$i] ne "")
+ {
+ p "<tr><td align=\"center\"><font color=\"#303030\">";
+ @n = split(/<!!!>/,$g_roles[$i]);
+ $j = 0;
+ while($n[$j] ne "")
+ {
+ if($j > 0){ p "<br>"; }
+ p $n[$j];
+ $j++;
+ }
+ p "</font></td></tr>";
+ }
+
+ if($g_texts[$i] ne "")
+ {
+ p "<tr><td align=\"center\"><font color=\"#606060\"><i>";
+ @n = split(/<!!!>/,$g_texts[$i]);
+ $j = 0;
+ while($n[$j] ne "")
+ {
+ if($j > 0){ p "<br>" ; }
+ p "\"$n[$j]\"";
+ $j++;
+ }
+ p "</i></font></td></tr>";
+ }
+
+ p "</table><br><br>";
+ $i++;
+}
+
+p "<br>";
+p "This list is far from being complete.<br>";
+p "A lot of more or less \"anonymous\" people have wasted their time, ";
+p "eyes, bandwidth and brain resources on this project.<br>";
+p "If you're one of those, then well, this dialog is also for you :)<br>";
+
+p " </center><body>";
+p "</html>";
+
+print OUT "\"\";\n";
+
+close(OUT);
diff --git a/src/modules/action/Makefile.am b/src/modules/action/Makefile.am
new file mode 100644
index 00000000..2015e908
--- /dev/null
+++ b/src/modules/action/Makefile.am
@@ -0,0 +1,17 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkviaction.la
+
+libkviaction_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkviaction_la_SOURCES = libkviaction.cpp
+
+libkviaction_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+#noinst_HEADERS= actiondialog.h
+
diff --git a/src/modules/action/libkviaction.cpp b/src/modules/action/libkviaction.cpp
new file mode 100644
index 00000000..daf84699
--- /dev/null
+++ b/src/modules/action/libkviaction.cpp
@@ -0,0 +1,533 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// File : libkviaction.cpp
+// Creation date : Tue 7 Dec 00:05:59 2002 GMT by Szymon Stefanek
+//
+// This toolbar is part of the KVirc irc client distribution
+// Copyright (C) 2004-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "kvi_module.h"
+#include "kvi_action.h"
+#include "kvi_actionmanager.h"
+#include "kvi_locale.h"
+#include "kvi_qstring.h"
+#include "kvi_parameterlist.h"
+#include "kvi_cmdformatter.h"
+#include "kvi_qstring.h"
+#include "kvi_error.h"
+#include "kvi_out.h"
+#include "kvi_iconmanager.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_kvs_useraction.h"
+#include "kvi_kvs_script.h"
+
+/*
+ @doc: action.list
+ @type:
+ command
+ @title:
+ action.list
+ @short:
+ Lists the available actions
+ @syntax:
+ action.list
+ @description:
+ Lists the currently defined actions: nothing more, nothing less.
+*/
+
+static bool action_kvs_cmd_list(KviKvsModuleCommandCall * c)
+{
+ KviWindow * pOut = c->window();
+
+ KviPointerHashTableIterator<QString,KviAction> it(*(KviActionManager::instance()->actions()));
+ while(KviAction * a = it.current())
+ {
+ if(a->isKviUserActionNeverOverrideThis())
+ pOut->output(KVI_OUT_VERBOSE,__tr2qs("%cCore action: %Q"),KVI_TEXT_BOLD,&(a->name()));
+ else
+ pOut->output(KVI_OUT_VERBOSE,__tr2qs("%cUser action: %Q"),KVI_TEXT_BOLD,&(a->name()));
+ pOut->output(KVI_OUT_VERBOSE,__tr2qs("Label: %Q"),&(a->visibleName()));
+ pOut->output(KVI_OUT_VERBOSE,__tr2qs("Category: %Q"),&(a->category()->visibleName()));
+ pOut->output(KVI_OUT_VERBOSE,__tr2qs("Description: %Q"),&(a->description()));
+ pOut->output(KVI_OUT_VERBOSE," "); // spacer
+ ++it;
+ }
+ return true;
+}
+
+/*
+ @doc: action.trigger
+ @type:
+ command
+ @title:
+ action.trigger
+ @short:
+ Triggers an action
+ @syntax:
+ action.trigger [-q] <name:string>
+ @switches:
+ !sw: -q | --quiet
+ Run in quiet mode (do not print any warnings)
+ @description:
+ Triggers the action specified by <name>, if that action exists and is enabled.
+ If the -q switch is specified the command runs in quiet mode and
+ does not print warnings if the action is not defined or disabled.
+ @examples:
+ [example]
+ action.trigger connect
+ [/example]
+*/
+
+static bool action_kvs_cmd_trigger(KviKvsModuleCommandCall * c)
+{
+ QString szName;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("name",KVS_PT_NONEMPTYSTRING,0,szName)
+ KVSM_PARAMETERS_END(c)
+
+ KviAction * a = KviActionManager::instance()->getAction(szName);
+ if(a)
+ {
+ if(a->isEnabled())
+ {
+ a->activate();
+ } else {
+ if(!c->switches()->find('q',"quiet"))
+ c->warning(__tr2qs("The action \"%1\" is disabled").arg(szName));
+ }
+ } else {
+ c->warning(__tr2qs("The action \"%1\" does not exist").arg(szName));
+ }
+
+ return true;
+}
+
+/*
+ @doc: action.enable
+ @type:
+ command
+ @title:
+ action.enable
+ @short:
+ Enables an action
+ @syntax:
+ action.enable [-q] <name:string>
+ @switches:
+ !sw: -q | --quiet
+ Run quietly, do not print any warnings
+ @description:
+ Enables the action specified by <name>, if that action exists.
+ If the action was previously enabled then this command does nothing.
+ otherwise all the toolbar buttons and menu items belonging to this
+ action will get enabled.[br]
+ Since [cmd]action.create[/cmd] command allows specifying contexts
+ for actions and the action engine is able to enable/disable the actions
+ automatically on certain events you will probably never need to use this command.
+ If the -q switch is specified the command runs in quiet mode and
+ does not print warnings if the action is not defined.
+ @seealso:
+ [cmd]action.disable[/cmd]
+*/
+
+static bool action_kvs_cmd_enable(KviKvsModuleCommandCall * c)
+{
+ QString szName;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("name",KVS_PT_NONEMPTYSTRING,0,szName)
+ KVSM_PARAMETERS_END(c)
+
+ KviAction * a = KviActionManager::instance()->getAction(szName);
+ if(a)
+ {
+ if(!a->isEnabled())a->setEnabled(true);
+ } else {
+ if(!c->switches()->find('q',"quiet"))
+ c->warning(__tr2qs("The action \"%1\" does not exist").arg(szName));
+ }
+
+ return true;
+}
+
+/*
+ @doc: action.disable
+ @type:
+ command
+ @title:
+ action.disable
+ @short:
+ Disables an action
+ @syntax:
+ action.disable [-q] [-f] <name:string>
+ @switches:
+ !sw: -q | --quiet
+ Run quietly, do not print any warnings
+ @description:
+ Disables the action specified by <name>, if that action exists.
+ If the action was previously disabled then this command does nothing.
+ otherwise all the toolbar buttons and menu items belonging to this
+ action will get disabled.[br]
+ Since [cmd]action.create[/cmd] command allows specifying contexts
+ for actions and the action engine is able to enable/disable the actions
+ automatically on certain events you will probably never need to use this command.
+ For the same reason the action may get automatically re-enabled when
+ one of the enabling events specified at [cmd]action.create[/cmd] time happens.
+ If the -q switch is specified the command runs in quiet mode and
+ does not print warnings if the action is not defined.
+ @seealso:
+ [cmd]action.enable[/cmd]
+*/
+
+static bool action_kvs_cmd_disable(KviKvsModuleCommandCall * c)
+{
+ QString szName;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("name",KVS_PT_NONEMPTYSTRING,0,szName)
+ KVSM_PARAMETERS_END(c)
+
+ KviAction * a = KviActionManager::instance()->getAction(szName);
+ if(a)
+ {
+ if(a->isEnabled())a->setEnabled(false);
+ } else {
+ if(!c->switches()->find('q',"quiet"))
+ c->warning(__tr2qs("The action \"%1\" does not exist").arg(szName));
+ }
+
+ return true;
+}
+
+/*
+ @doc: action.destroy
+ @type:
+ command
+ @title:
+ action.destroy
+ @short:
+ Destroy an action
+ @syntax:
+ action.destroy [-q] <name:string>
+ @switches:
+ !sw: -q | --quiet
+ Run quietly, do not print any warnings
+ @description:
+ Destroys the action specified by <name>, if that action exists.[br]
+ Destroying an action will remove it from any toolbar or popup.[br]
+ If the -q switch is specified the command runs in quiet mode and
+ does not print warnings if the action is not defined.
+ Please note that you CAN'T destroy core actions, you can destroy
+ only script actions that have been defined by the user (or other scripts).
+ @seealso:
+ # this will trigger a warning and NOT work
+ action.destroy connect
+*/
+
+static bool action_kvs_cmd_destroy(KviKvsModuleCommandCall * c)
+{
+ QString szName;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("name",KVS_PT_NONEMPTYSTRING,0,szName)
+ KVSM_PARAMETERS_END(c)
+
+ KviAction * a = KviActionManager::instance()->getAction(szName);
+ if(a)
+ {
+ if(a->isKviUserActionNeverOverrideThis())
+ {
+ a->suicide();
+ } else {
+ if(!c->switches()->find('q',"quiet"))
+ c->warning(__tr2qs("The action \"%1\" is a core action and cannot be destroyed").arg(szName));
+ }
+ } else {
+ if(!c->switches()->find('q',"quiet"))
+ c->warning(__tr2qs("The action \"%1\" does not exist").arg(szName));
+ }
+
+ return true;
+}
+
+/*
+ @doc: action.create
+ @type:
+ command
+ @title:
+ action.create
+ @short:
+ Defines a new action
+ @syntax:
+ action.create [-i] [-c] [-l] [-w=<window_types:string>] [-s] [-t=<category:string>] (<name:string>,<visible label:string>,<description:string>,<big_icon_id:string>[,<small_icon_id:string>])
+ {
+ <action body>
+ }
+ @switches:
+ !sw: -i | --bind-to-context
+ Specifies that the action needs an IRC context to be executed.
+ When the current window does not belong to an IRC context
+ the action is automatically disabled
+
+ !sw: -c | --bind-to-connection
+ Specifies that the action needs an IRC connection to be executed.
+ When the current window has no associated IRC connection
+ the action is automatically disabled.
+ This switch implies -i.
+
+ !sw: -l | --enable-at-login
+ Specifies that the action needs to be enabled at login time, that is
+ when a link to the server has been estabilished but the login
+ operations haven't been carried out yet (and thus there is no real IRC connection).
+ This switch requires -c to work.
+
+ !sw: -w=<window_types> | --window-types=<window_type>
+ Causes the action to be enabled only when the active window
+ is one of the specified types. <window_types> may be any combination
+ of the letters 'q' (query), 'c' (channel), 'x' (console), 'd' (dccchat).
+ If this switch is omitted then the action is enabled in all the windows.[br]
+
+ !sw: -s | --selected-only
+ Specifies that the action will be activated only if the active window
+ has selected users in the userlist. This switch requires -w with a combination
+ of flags 'q','c' and 'x' (it doesn't work for dcc chat).
+
+ !sw: -t=<category> | --category=<category>
+ Causes the action to belong to the specified category.
+ <category> can be one of "irc","scripting","settings","gui","channel","tools" and "generic".
+ If this switch is omitted the "generic" category is automatically assumed.
+ The actions failing in the "tools" category will appear in the "Tools" KVIrc menu too.
+
+ !sw: -k=<key sequence> | --key-sequence=<key sequence>
+ Specifies that the action will be activated also by the <key sequence>
+ which is a string formed from up to four keyboard codes separated by
+ commas optionally combined with the modifiers "Alt","Ctrl","Shift" and "Meta".[br]
+ Examples of such sequences are: "Ctrl+X", "Ctrl+Alt+F" or "Ctrl+X,Alt+Space".
+ @description:
+ [p]
+ Defines a new script action.
+ [/p]
+ [p]
+ Each action has an unique <name> that must not collide with any core action
+ (i.e. don't use the "kvirc." prefix).
+ At any time you can check [cmd]action.list[/cmd] to verify that no core action
+ is already using your <name>. If the <name> was already used for a script action
+ then this action is simply replaced by the new one.
+ [/p]
+ [p]
+ Each action has an associated <visible label> that is the name meant to be presented to the user,
+ possibly even translated. This label will appear on the toolbar buttons, in the tooltips and
+ in the popup menu items. The string will be evaluated just before the actions is displayed
+ so the eventual runtime translation will fetch from the correct language catalogue.
+ [/p]
+ [p]
+ <description> is the descriptive text that will be displayed in the action choice dialog
+ (and maybe in other places).
+ The string will be evaluated just before the actions is displayed
+ so the eventual runtime translation will fetch from the correct language catalogue.
+ [/p]
+ [p]
+ <big_icon_id> is the [doc:image_id]image identifier[/doc] of the icon that will
+ appear on the toolbar buttons and in the action choice dialog.
+ [/p]
+ [p]
+ <small_icon_id> is optional and is the [doc:image_id]image identifier[/doc] of the icon
+ that will appear in the menu items. Since menu items can be also iconless then
+ this parameter is optional.
+ [/p]
+ [p]
+ <action body> is the callback code snippet that will be triggered when this action is activated
+ either by the means of [cmd]action.trigger[/cmd], a toolbar button or a menu item selection.
+ An empty <action body> causes this command to behave like [cmd]action.destoy[/cmd] <name>.
+ [/p]
+ @seealso:
+ [cmd]action.destroy[/cmd], [cmd]action.trigger[/cmd]
+ @examples:
+ [example]
+
+ [/example]
+*/
+
+static bool action_kvs_cmd_create(KviKvsModuleCallbackCommandCall * c)
+{
+ QString szName,szVisibleText,szDescription,szBigIconId,szSmallIconId;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("name",KVS_PT_NONEMPTYSTRING,0,szName)
+ KVSM_PARAMETER_IGNORED("visible_label")
+ KVSM_PARAMETER_IGNORED("description")
+ KVSM_PARAMETER("big_icon_id",KVS_PT_NONEMPTYSTRING,0,szBigIconId)
+ KVSM_PARAMETER("small_icon_id",KVS_PT_STRING,KVS_PF_OPTIONAL,szSmallIconId)
+ KVSM_PARAMETERS_END(c)
+
+ if(!(c->getParameterCode(1,szVisibleText) && c->getParameterCode(2,szDescription)))
+ {
+ c->error(__tr2qs("Internal error: call a head-shrinker"));
+ return false;
+ }
+
+ QString szCategory,szWindows,szKeySequence;
+
+ int iFlags = 0;
+
+ if(c->switches()->find('i',"bind-to-context"))iFlags |= KviAction::NeedsContext;
+ if(c->switches()->find('c',"bind-to-connection"))iFlags |= KviAction::NeedsConnection | KviAction::NeedsContext;
+ if(c->switches()->find('l',"enable-at-login"))
+ {
+ if(iFlags & KviAction::NeedsConnection)
+ iFlags |= KviAction::EnableAtLogin;
+ else
+ c->warning(__tr2qs("The switch -l requires -c"));
+ }
+ c->switches()->getAsStringIfExisting('t',"category",szCategory);
+ if(szCategory.isEmpty())szCategory = "generic";
+ c->switches()->getAsStringIfExisting('w',"window-types",szWindows);
+ if(!szWindows.isEmpty())
+ {
+ if(szWindows.find('c') != -1)iFlags |= KviAction::WindowChannel;
+ if(szWindows.find('x') != -1)iFlags |= KviAction::WindowConsole;
+ if(szWindows.find('d') != -1)iFlags |= KviAction::WindowDccChat;
+ if(szWindows.find('q') != -1)iFlags |= KviAction::WindowQuery;
+ }
+ if(c->switches()->find('s',"enable-on-selected"))
+ {
+ if(iFlags & (KviAction::WindowChannel | KviAction::WindowConsole | KviAction::WindowQuery))
+ iFlags |= KviAction::WindowOnlyIfUsersSelected;
+ else
+ c->warning(__tr2qs("The switch -s requires -w with a combination of flags 'c','x' and 'q'"));
+ }
+ c->switches()->getAsStringIfExisting('k',"key-sequence",szKeySequence);
+
+
+ KviAction * old = KviActionManager::instance()->getAction(szName);
+ if(old)
+ {
+ if(old->isKviUserActionNeverOverrideThis())
+ old->suicide();
+ else {
+ c->warning(__tr2qs("The action \"%1\" is already defined as core action and cannot be overridden").arg(szName));
+ return false;
+ }
+ }
+
+ QString szCmd = c->callback()->code();
+
+ if(szCmd.isEmpty())
+ {
+ // just killed it :)
+ return true;
+ }
+
+ int iOldFlags = iFlags;
+ iFlags = KviAction::validateFlags(iFlags);
+ if(iFlags != iOldFlags)
+ debug("action.validate has provided invalid flags: %d fixed to %d",iOldFlags,iFlags);
+
+ KviKvsUserAction * a = KviKvsUserAction::createInstance(KviActionManager::instance(),
+ szName,szCmd,szVisibleText,
+ szDescription,szCategory,szBigIconId,
+ szSmallIconId,iFlags,szKeySequence);
+
+ KviActionManager::instance()->registerAction(a);
+
+ return true;
+}
+
+/*
+ @doc: action.exists
+ @type:
+ function
+ @title:
+ $action.exists
+ @short:
+ Checks if an action is currently defined
+ @syntax:
+ <boolean> $action.exists(<name:string>)
+ @description:
+ Returns 1 if the action with the specified <name> is currently defined
+ and 0 otherwise.
+*/
+
+static bool action_kvs_fnc_exists(KviKvsModuleFunctionCall * c)
+{
+ QString szName;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("action_name",KVS_PT_NONEMPTYSTRING,0,szName)
+ KVSM_PARAMETERS_END(c)
+ c->returnValue()->setBoolean(KviActionManager::instance()->getAction(szName) ? true : false);
+ return true;
+}
+
+/*
+ @doc: action.isEnabled
+ @type:
+ function
+ @title:
+ $action.isEnabled
+ @short:
+ Checks if an action is currently enabled.
+ @syntax:
+ <boolean> $action.isEnabled(<name:string>)
+ @description:
+ Returns 1 if the action with the specified <name> is currently enabled
+ and 0 otherwise. If the action does not exist the function returns 0.
+*/
+
+static bool action_kvs_fnc_isEnabled(KviKvsModuleFunctionCall * c)
+{
+ QString szName;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("action_name",KVS_PT_NONEMPTYSTRING,0,szName)
+ KVSM_PARAMETERS_END(c)
+ KviAction * a = KviActionManager::instance()->getAction(szName);
+ if(a)
+ c->returnValue()->setBoolean(a->isEnabled());
+ else
+ c->returnValue()->setBoolean(false);
+ return true;
+}
+
+
+static bool action_module_init(KviModule *m)
+{
+ // setlabel , $label , $position , move , $itempos , $itemexists , $itemtype
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"list",action_kvs_cmd_list);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"trigger",action_kvs_cmd_trigger);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"enable",action_kvs_cmd_enable);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"disable",action_kvs_cmd_disable);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"destroy",action_kvs_cmd_destroy);
+
+ KVSM_REGISTER_CALLBACK_COMMAND(m,"create",action_kvs_cmd_create);
+
+ KVSM_REGISTER_FUNCTION(m,"exists",action_kvs_fnc_exists);
+ KVSM_REGISTER_FUNCTION(m,"isEnabled",action_kvs_fnc_isEnabled);
+ return true;
+}
+
+static bool action_module_cleanup(KviModule *m)
+{
+ return true;
+}
+
+KVIRC_MODULE(
+ "action", // module name
+ "1.0.0", // module version
+ "Copyright (C) 2004 Szymon Stefanek (pragma at kvirc dot net)", // author & (C)
+ "Interface to the system actions",
+ action_module_init,
+ 0,
+ 0,
+ action_module_cleanup
+)
diff --git a/src/modules/actioneditor/Makefile.am b/src/modules/actioneditor/Makefile.am
new file mode 100644
index 00000000..84ce9dd7
--- /dev/null
+++ b/src/modules/actioneditor/Makefile.am
@@ -0,0 +1,21 @@
+###############################################################################
+# KVirc IRC client module Makefile - Szymon Stefanek <pragma at kvirc dot net>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkviactioneditor.la
+
+libkviactioneditor_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkviactioneditor_la_SOURCES = libkviactioneditor.cpp actioneditor.cpp
+nodist_libkviactioneditor_la_SOURCES = moc_actioneditor.cpp
+
+noinst_HEADERS = actioneditor.h
+libkviactioneditor_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+# noinst_HEADERS=
+
+moc_actioneditor.cpp: actioneditor.h
+ $(SS_QT_MOC) $< -o $@
diff --git a/src/modules/actioneditor/actioneditor.cpp b/src/modules/actioneditor/actioneditor.cpp
new file mode 100644
index 00000000..cfc12932
--- /dev/null
+++ b/src/modules/actioneditor/actioneditor.cpp
@@ -0,0 +1,1009 @@
+//=============================================================================
+//
+// File : aliaseditor.cpp
+// Creation date : Tue 29 Dec 2004 02:45:59 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2004 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the linkss of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) 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.
+//
+//=============================================================================
+#include "actioneditor.h"
+
+#include "kvi_iconmanager.h"
+#include "kvi_options.h"
+#include "kvi_locale.h"
+#include "kvi_imagedialog.h"
+#include "kvi_config.h"
+#include "kvi_filedialog.h"
+#include "kvi_fileutils.h"
+#include "kvi_scripteditor.h"
+#include "kvi_debug.h"
+#include "kvi_app.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_aliasmanager.h"
+#include "kvi_filedialog.h"
+#include "kvi_actionmanager.h"
+#include "kvi_action.h"
+#include "kvi_kvs_useraction.h"
+#include "kvi_customtoolbarmanager.h"
+
+#include <qsplitter.h>
+#include <qlayout.h>
+#include "kvi_tal_vbox.h"
+#include <qtooltip.h>
+#include <qpushbutton.h>
+#include <qdir.h>
+#include <qmessagebox.h>
+#include <qlineedit.h>
+#include <qcombobox.h>
+#include <qtoolbutton.h>
+#include <qcheckbox.h>
+#include <qtooltip.h>
+#include <qpainter.h>
+#ifdef COMPILE_USE_QT4
+ #include <q3header.h>
+#else
+ #include <qheader.h>
+#endif
+#include <qtabwidget.h>
+#include <kvi_tal_groupbox.h>
+#include "kvi_valuelist.h"
+#include <qlabel.h>
+
+extern KviActionEditorWindow * g_pActionEditorWindow;
+
+static QString g_szLastEditedAction;
+
+#define LVI_ICON_SIZE 32
+#define LVI_BORDER 4
+#define LVI_SPACING 8
+#define LVI_MINIMUM_TEXT_WIDTH 150
+#define LVI_MINIMUM_CELL_WIDTH (LVI_MINIMUM_TEXT_WIDTH + LVI_BORDER + LVI_ICON_SIZE + LVI_SPACING + LVI_BORDER)
+
+KviActionEditorListViewItem::KviActionEditorListViewItem(KviTalListView * v,KviActionData * a)
+: KviTalListViewItem(v,"")
+{
+ m_pActionData = a;
+ m_pListView = v;
+ m_pIcon = 0;
+ setupForActionData();
+}
+
+KviActionEditorListViewItem::~KviActionEditorListViewItem()
+{
+ if(m_pIcon)delete m_pIcon;
+ delete m_pActionData;
+}
+
+void KviActionEditorListViewItem::setupForActionData()
+{
+ QString t = "<b>" + m_pActionData->m_szName + "</b>";
+ t += "<br><font color=\"#808080\" size=\"-1\">" + m_pActionData->m_szVisibleName + "</font>";
+ m_szKey = m_pActionData->m_szName.upper();
+ m_pText = new QSimpleRichText(t,m_pListView->font());
+ if(m_pIcon)delete m_pIcon;
+ QPixmap * p = g_pIconManager->getBigIcon(m_pActionData->m_szBigIcon);
+ if(p)m_pIcon = new QPixmap(*p);
+ else {
+ p = g_pIconManager->getImage("kvi_bigicon_unknown.png");
+ if(p)m_pIcon = new QPixmap(*p);
+ else m_pIcon = new QPixmap(LVI_ICON_SIZE,LVI_ICON_SIZE);
+ }
+ setup();
+}
+
+QString KviActionEditorListViewItem::key(int,bool) const
+{
+ return m_szKey;
+}
+
+void KviActionEditorListViewItem::setup()
+{
+ KviTalListViewItem::setup();
+ int iWidth = m_pListView->visibleWidth();
+ if(iWidth < LVI_MINIMUM_CELL_WIDTH)iWidth = LVI_MINIMUM_CELL_WIDTH;
+ iWidth -= LVI_BORDER + LVI_ICON_SIZE + LVI_SPACING + LVI_BORDER;
+ m_pText->setWidth(iWidth);
+ int iHeight = m_pText->height() + (2 * LVI_BORDER);
+ if(iHeight < (LVI_ICON_SIZE + (2 * LVI_BORDER)))iHeight = LVI_ICON_SIZE + (2 * LVI_BORDER);
+ setHeight(iHeight);
+}
+
+void KviActionEditorListViewItem::paintCell(QPainter * p,const QColorGroup & cg,int column,int width,int align)
+{
+ p->fillRect(QRect(0,0,width,height()),isSelected() ? cg.highlight() : cg.base());
+ p->drawPixmap(LVI_BORDER,LVI_BORDER,*m_pIcon);
+ int afterIcon = LVI_BORDER + LVI_ICON_SIZE + LVI_SPACING;
+ int www = m_pListView->visibleWidth() - (afterIcon + LVI_BORDER);
+ m_pText->setWidth(www);
+ m_pText->draw(p,afterIcon,LVI_BORDER,QRect(afterIcon,LVI_BORDER,www,height() - (LVI_BORDER * 2)),cg);
+}
+
+
+KviSingleActionEditor::KviSingleActionEditor(QWidget * par,KviActionEditor * ed)
+: QWidget(par)
+{
+ m_pActionEditor = ed;
+ m_pActionData = 0;
+
+ QGridLayout * g = new QGridLayout(this,3,2,0,4);
+
+ QLabel * l = new QLabel(__tr2qs("Name:"),this);
+ g->addWidget(l,0,0);
+ m_pNameEdit = new QLineEdit(this);
+ g->addWidget(m_pNameEdit,0,1);
+ QToolTip::add(m_pNameEdit,__tr2qs("Internal unique name for the action"));
+
+ l = new QLabel(__tr2qs("Label:"),this);
+ g->addWidget(l,1,0);
+ m_pVisibleNameEdit = new QLineEdit(this);
+ g->addWidget(m_pVisibleNameEdit,1,1);
+ QToolTip::add(m_pVisibleNameEdit,__tr2qs("Visible name for this action.<br>This string will be displayed to the user so it is a good idea to use $tr() here"));
+
+ QTabWidget * tw = new QTabWidget(this);
+ g->addMultiCellWidget(tw,2,2,0,1);
+
+ // code tab
+ QWidget * tab = new QWidget(tw);
+ QGridLayout * gl = new QGridLayout(tab,1,1,8,4);
+
+ m_pScriptEditor = KviScriptEditor::createInstance(tab);
+ gl->addWidget(m_pScriptEditor,0,0);
+ QToolTip::add(m_pScriptEditor,__tr2qs("Action code"));
+
+ tw->addTab(tab,__tr2qs("Code"));
+
+ // properties tab
+ tab = new QWidget(tw);
+ gl = new QGridLayout(tab,7,4,8,4);
+
+ l = new QLabel(__tr2qs("Category:"),tab);
+ gl->addWidget(l,0,0);
+ m_pCategoryCombo = new QComboBox(false,tab);
+ gl->addMultiCellWidget(m_pCategoryCombo,0,0,1,3);
+ QToolTip::add(m_pCategoryCombo,__tr2qs("Choose the category that best fits for this action"));
+
+ l = new QLabel(__tr2qs("Description:"),tab);
+ gl->addWidget(l,1,0);
+ m_pDescriptionEdit = new QLineEdit(tab);
+ gl->addMultiCellWidget(m_pDescriptionEdit,1,1,1,3);
+ QToolTip::add(m_pDescriptionEdit,__tr2qs("Visible short description for this action.<br>This string will be displayed to the user so it is a good idea to use $tr() here"));
+
+ l = new QLabel(__tr2qs("Small Icon:"),tab);
+ gl->addWidget(l,2,0);
+ m_pSmallIconEdit = new QLineEdit(tab);
+ gl->addWidget(m_pSmallIconEdit,2,1);
+ m_pSmallIconButton = new QToolButton(tab);
+ m_pSmallIconButton->setMinimumSize(QSize(20,20));
+ connect(m_pSmallIconButton,SIGNAL(clicked()),this,SLOT(chooseSmallIcon()));
+ gl->addWidget(m_pSmallIconButton,2,2);
+ QString s= __tr2qs("The small icon associated to this action.<br>" \
+ "It will appear at least in the popup menus when this action is inserted.<br>" \
+ "It should be 16x16 pixels.");
+ QToolTip::add(m_pSmallIconEdit,s);
+ QToolTip::add(m_pSmallIconButton,s);
+
+ l = new QLabel(__tr2qs("Big Icon:"),tab);
+ gl->addWidget(l,3,0);
+ m_pBigIconEdit = new QLineEdit(tab);
+ gl->addWidget(m_pBigIconEdit,3,1);
+ m_pBigIconButton = new QToolButton(tab);
+ m_pBigIconButton->setMinimumSize(QSize(48,48));
+ m_pBigIconButton->setUsesBigPixmap(true);
+ connect(m_pBigIconButton,SIGNAL(clicked()),this,SLOT(chooseBigIcon()));
+ gl->addMultiCellWidget(m_pBigIconButton,3,4,2,3);
+ s = __tr2qs("The big icon associated to this action.<br>" \
+ "It will appear at least in the toolbar buttons when this action is inserted.<br>" \
+ "It should be 32x32 pixels.");
+ QToolTip::add(m_pBigIconEdit,s);
+ QToolTip::add(m_pBigIconButton,s);
+
+ l = new QLabel(__tr2qs("Key Sequence:"),tab);
+ gl->addMultiCellWidget(l,4,5,0,0);
+ m_pKeySequenceEdit = new QLineEdit(tab);
+ gl->addMultiCellWidget(m_pKeySequenceEdit,4,5,1,1);
+ QToolTip::add(m_pKeySequenceEdit,__tr2qs("Optional keyboard sequence that will activate this action.<br>" \
+ "The sequence should be expressed as a string of up to four key codes separated by commas " \
+ "eventually combined with the modifiers \"Ctrl\",\"Shift\",\"Alt\" and \"Meta\".<br>" \
+ "Examples of such sequences are \"Ctrl+X\", \"Ctrl+Alt+Z\", \"Ctrl+X,Ctrl+C\" ..."));
+
+ l = new QLabel(tab);
+ gl->addMultiCellWidget(l,6,6,0,3);
+
+ gl->setColStretch(1,1);
+ gl->setRowStretch(6,1);
+
+
+ tw->addTab(tab,__tr2qs("Properties"));
+
+
+
+ // flags tab
+ tab = new QWidget(tw);
+ gl = new QGridLayout(tab,12,4,8,4);
+
+
+ m_pNeedsContextCheck = new KviStyledCheckBox(__tr2qs("Needs IRC Context"),tab);
+ connect(m_pNeedsContextCheck,SIGNAL(toggled(bool)),this,SLOT(needsContextCheckToggled(bool)));
+ QToolTip::add(m_pNeedsContextCheck,__tr2qs("Check this option if this action should be enabled only when " \
+ "the active window belongs to an irc context"));
+ gl->addMultiCellWidget(m_pNeedsContextCheck,0,0,0,3);
+
+ l = new QLabel(tab);
+ l->setMinimumWidth(40);
+ gl->addWidget(l,1,0);
+
+ m_pNeedsConnectionCheck = new KviStyledCheckBox(__tr2qs("Needs IRC Connection"),tab);
+ connect(m_pNeedsConnectionCheck,SIGNAL(toggled(bool)),this,SLOT(needsConnectionCheckToggled(bool)));
+ QToolTip::add(m_pNeedsConnectionCheck,__tr2qs("Check this option if this action should be enabled only when " \
+ "the active window has an active IRC connection"));
+ gl->addMultiCellWidget(m_pNeedsConnectionCheck,1,1,1,3);
+
+ l = new QLabel(tab);
+ l->setMinimumWidth(40);
+ gl->addWidget(l,2,1);
+
+ m_pEnableAtLoginCheck = new KviStyledCheckBox(__tr2qs("Enable at Login"),tab);
+ QToolTip::add(m_pEnableAtLoginCheck,__tr2qs("Check this option if this action should be enabled also during " \
+ "the login operations (so when the logical IRC connection hasn't been estabilished yet)"));
+ gl->addMultiCellWidget(m_pEnableAtLoginCheck,2,2,2,3);
+
+ m_pSpecificWindowsCheck = new KviStyledCheckBox(__tr2qs("Enable Only in Specified Windows"),tab);
+ connect(m_pSpecificWindowsCheck,SIGNAL(toggled(bool)),this,SLOT(specificWindowsCheckToggled(bool)));
+ QToolTip::add(m_pSpecificWindowsCheck,__tr2qs("Check this option if this action should be enabled only when " \
+ "the active window is of a specified type"));
+ gl->addMultiCellWidget(m_pSpecificWindowsCheck,3,3,0,3);
+
+ m_pWindowConsoleCheck = new KviStyledCheckBox(__tr2qs("Enable in Console Windows"),tab);
+ QToolTip::add(m_pWindowConsoleCheck,__tr2qs("Check this option if this action should be enabled only when " \
+ "the active window is a console"));
+ connect(m_pWindowConsoleCheck,SIGNAL(toggled(bool)),this,SLOT(channelQueryOrConsoleWindowCheckToggled(bool)));
+ gl->addMultiCellWidget(m_pWindowConsoleCheck,4,4,1,3);
+
+ m_pConsoleOnlyIfUsersSelectedCheck = new KviStyledCheckBox(__tr2qs("Only If There Are Selected Users"),tab);
+ QToolTip::add(m_pConsoleOnlyIfUsersSelectedCheck,__tr2qs("This will enable the action only if there are " \
+ "selected users in the active window"));
+ gl->addMultiCellWidget(m_pConsoleOnlyIfUsersSelectedCheck,5,5,2,3);
+
+ m_pWindowChannelCheck = new KviStyledCheckBox(__tr2qs("Enable in Channel Windows"),tab);
+ QToolTip::add(m_pWindowChannelCheck,__tr2qs("Check this option if this action should be enabled only when " \
+ "the active window is a channel"));
+ connect(m_pWindowChannelCheck,SIGNAL(toggled(bool)),this,SLOT(channelQueryOrConsoleWindowCheckToggled(bool)));
+ gl->addMultiCellWidget(m_pWindowChannelCheck,6,6,1,3);
+
+ m_pChannelOnlyIfUsersSelectedCheck = new KviStyledCheckBox(__tr2qs("Only If There Are Selected Users"),tab);
+ QToolTip::add(m_pChannelOnlyIfUsersSelectedCheck,__tr2qs("This will enable the action only if there are " \
+ "selected users in the active window"));
+ gl->addMultiCellWidget(m_pChannelOnlyIfUsersSelectedCheck,7,7,2,3);
+
+ m_pWindowQueryCheck = new KviStyledCheckBox(__tr2qs("Enable in Query Windows"),tab);
+ QToolTip::add(m_pWindowQueryCheck,__tr2qs("Check this option if this action should be enabled only when " \
+ "the active window is a query"));
+ connect(m_pWindowQueryCheck,SIGNAL(toggled(bool)),this,SLOT(channelQueryOrConsoleWindowCheckToggled(bool)));
+ gl->addMultiCellWidget(m_pWindowQueryCheck,8,8,1,3);
+
+ m_pQueryOnlyIfUsersSelectedCheck = new KviStyledCheckBox(__tr2qs("Only If There Are Selected Users"),tab);
+ QToolTip::add(m_pQueryOnlyIfUsersSelectedCheck,__tr2qs("This will enable the action only if there are " \
+ "selected users in the active window"));
+ gl->addMultiCellWidget(m_pQueryOnlyIfUsersSelectedCheck,9,9,2,3);
+
+ m_pWindowDccChatCheck = new KviStyledCheckBox(__tr2qs("Enable in DCC Chat Windows"),tab);
+ QToolTip::add(m_pWindowDccChatCheck,__tr2qs("Check this option if this action should be enabled only when " \
+ "the active window is a dcc chat"));
+ gl->addMultiCellWidget(m_pWindowDccChatCheck,10,10,1,3);
+
+
+
+ l = new QLabel(tab);
+ gl->addMultiCellWidget(l,11,11,0,3);
+
+ gl->setColStretch(3,1);
+ gl->setRowStretch(11,1);
+
+ tw->addTab(tab,__tr2qs("Flags"));
+
+
+
+ tw->setCurrentPage(0);
+
+ g->setRowStretch(2,1);
+ g->setColStretch(1,1);
+
+
+ KviPointerHashTableIterator<QString,KviActionCategory> it(*(KviActionManager::instance()->categories()));
+ while(KviActionCategory * ac = it.current())
+ {
+ m_pCategoryCombo->insertItem(ac->visibleName() + " (" + ac->name() + ")");
+ ++it;
+ }
+}
+
+KviSingleActionEditor::~KviSingleActionEditor()
+{
+}
+
+void KviSingleActionEditor::channelQueryOrConsoleWindowCheckToggled(bool)
+{
+ m_pChannelOnlyIfUsersSelectedCheck->setEnabled(m_pWindowChannelCheck->isChecked());
+ m_pChannelOnlyIfUsersSelectedCheck->setChecked(false);
+ m_pQueryOnlyIfUsersSelectedCheck->setEnabled(m_pWindowQueryCheck->isChecked());
+ m_pQueryOnlyIfUsersSelectedCheck->setChecked(false);
+ m_pConsoleOnlyIfUsersSelectedCheck->setEnabled(m_pWindowConsoleCheck->isChecked());
+ m_pConsoleOnlyIfUsersSelectedCheck->setChecked(false);
+}
+
+void KviSingleActionEditor::needsContextCheckToggled(bool)
+{
+ m_pEnableAtLoginCheck->setChecked(false);
+ m_pEnableAtLoginCheck->setEnabled(false);
+ m_pNeedsConnectionCheck->setChecked(false);
+ m_pNeedsConnectionCheck->setEnabled(m_pNeedsContextCheck->isChecked());
+}
+
+void KviSingleActionEditor::needsConnectionCheckToggled(bool)
+{
+ m_pEnableAtLoginCheck->setChecked(false);
+ m_pEnableAtLoginCheck->setEnabled(m_pNeedsConnectionCheck->isChecked());
+}
+
+void KviSingleActionEditor::specificWindowsCheckToggled(bool)
+{
+ m_pWindowConsoleCheck->setChecked(false);
+ m_pWindowChannelCheck->setChecked(false);
+ m_pWindowQueryCheck->setChecked(false);
+ m_pWindowDccChatCheck->setChecked(false);
+ m_pQueryOnlyIfUsersSelectedCheck->setChecked(false);
+ m_pChannelOnlyIfUsersSelectedCheck->setChecked(false);
+ m_pConsoleOnlyIfUsersSelectedCheck->setChecked(false);
+ m_pQueryOnlyIfUsersSelectedCheck->setEnabled(false);
+ m_pChannelOnlyIfUsersSelectedCheck->setEnabled(false);
+ m_pConsoleOnlyIfUsersSelectedCheck->setEnabled(false);
+ bool b = m_pSpecificWindowsCheck->isChecked();
+ m_pWindowConsoleCheck->setEnabled(b);
+ m_pWindowChannelCheck->setEnabled(b);
+ m_pWindowQueryCheck->setEnabled(b);
+ m_pWindowDccChatCheck->setEnabled(b);
+}
+
+void KviSingleActionEditor::chooseSmallIcon()
+{
+ if(!m_pActionData)return;
+ KviImageDialog * d = new KviImageDialog(this);
+ int ret = d->exec();
+ QString s = d->selectedImage();
+ delete d;
+ if(ret != QDialog::Accepted)return;
+ QPixmap * p = g_pIconManager->getImage(s.utf8().data());
+ if(!p)return;
+ m_pSmallIconEdit->setText(s);
+ m_pSmallIconButton->setPixmap(*p);
+}
+
+void KviSingleActionEditor::chooseBigIcon()
+{
+ if(!m_pActionData)return;
+ KviImageDialog * d = new KviImageDialog(this,QString::null,KID_TYPE_ALL,KID_TYPE_FULL_PATH);
+ int ret = d->exec();
+ QString s = d->selectedImage();
+ delete d;
+ if(ret != QDialog::Accepted)return;
+ QPixmap * p = g_pIconManager->getBigIcon(s);
+ if(!p)return;
+ m_pBigIconEdit->setText(s);
+ m_pBigIconButton->setPixmap(*p);
+}
+
+void KviSingleActionEditor::setActionData(KviActionData * d)
+{
+ m_pActionData = d;
+
+ if(d)
+ {
+ unsigned int uOldFlags = d->m_uFlags;
+ d->m_uFlags = KviAction::validateFlags(d->m_uFlags);
+ if(d->m_uFlags != uOldFlags)
+ debug("invalid action flags in KviSingleActionEditor::setActionData(): %d fixed to %d",uOldFlags,d->m_uFlags);
+
+ m_pNameEdit->setText(d->m_szName);
+ m_pNameEdit->setEnabled(true);
+ m_pVisibleNameEdit->setText(d->m_szVisibleName);
+ m_pVisibleNameEdit->setEnabled(true);
+ m_pCategoryCombo->setEnabled(true);
+ int i;
+ for(i=0;i<m_pCategoryCombo->count();i++)
+ {
+ QString t = m_pCategoryCombo->text(i);
+ int idx = t.findRev('(');
+ QString r = t.right(t.length() - (idx + 1));
+ QString r2 = r.left(r.length() - 1);
+ r2.stripWhiteSpace();
+ if(r2 == d->m_szCategory)
+ {
+ m_pCategoryCombo->setCurrentItem(i);
+ break;
+ }
+ }
+ if(i == m_pCategoryCombo->count())
+ {
+ m_pCategoryCombo->setCurrentItem(0);
+ }
+ m_pScriptEditor->setText(d->m_szScriptCode);
+ m_pScriptEditor->setEnabled(true);
+ m_pKeySequenceEdit->setText(d->m_szKeySequence);
+ m_pKeySequenceEdit->setEnabled(true);
+ m_pDescriptionEdit->setText(d->m_szDescription);
+ m_pDescriptionEdit->setEnabled(true);
+ m_pSmallIconEdit->setEnabled(true);
+ m_pBigIconEdit->setEnabled(true);
+ QPixmap * p = g_pIconManager->getImage(d->m_szSmallIcon);
+ if(p)
+ {
+ m_pSmallIconEdit->setText(d->m_szSmallIcon);
+ m_pSmallIconButton->setPixmap(*p);
+ } else {
+ m_pSmallIconEdit->setText("");
+ m_pSmallIconButton->setPixmap(QPixmap());
+ }
+ p = g_pIconManager->getImage(d->m_szBigIcon);
+ if(p)
+ {
+ m_pBigIconEdit->setText(d->m_szBigIcon);
+ m_pBigIconButton->setPixmap(*p);
+ } else {
+ m_pBigIconEdit->setText("");
+ m_pBigIconButton->setPixmap(QPixmap());
+ }
+ m_pSmallIconButton->setEnabled(true);
+ m_pBigIconButton->setEnabled(true);
+ m_pNeedsContextCheck->setEnabled(true);
+ bool b = (d->m_uFlags & KviAction::NeedsContext) || (d->m_uFlags & KviAction::NeedsConnection);
+ m_pNeedsContextCheck->setChecked(b);
+
+ m_pNeedsConnectionCheck->setEnabled(b);
+ b = (d->m_uFlags & KviAction::NeedsContext) && (d->m_uFlags & KviAction::NeedsConnection);
+ m_pNeedsConnectionCheck->setChecked(b);
+
+ m_pEnableAtLoginCheck->setEnabled(b);
+ m_pEnableAtLoginCheck->setChecked(b && (d->m_uFlags & KviAction::EnableAtLogin));
+
+ m_pSpecificWindowsCheck->setEnabled(true);
+ b = d->m_uFlags & KviAction::InternalWindowMask;
+ m_pSpecificWindowsCheck->setChecked(b);
+
+ m_pWindowConsoleCheck->setEnabled(b);
+ m_pWindowChannelCheck->setEnabled(b);
+ m_pWindowQueryCheck->setEnabled(b);
+ m_pWindowDccChatCheck->setEnabled(b);
+ b = d->m_uFlags & KviAction::WindowConsole;
+ m_pWindowConsoleCheck->setChecked(b);
+ m_pConsoleOnlyIfUsersSelectedCheck->setEnabled(b);
+ m_pConsoleOnlyIfUsersSelectedCheck->setChecked(b && (d->m_uFlags & KviAction::WindowOnlyIfUsersSelected));
+ b = d->m_uFlags & KviAction::WindowChannel;
+ m_pWindowChannelCheck->setChecked(b);
+ m_pChannelOnlyIfUsersSelectedCheck->setEnabled(b);
+ m_pChannelOnlyIfUsersSelectedCheck->setChecked(b && (d->m_uFlags & KviAction::WindowOnlyIfUsersSelected));
+ b = d->m_uFlags & KviAction::WindowQuery;
+ m_pWindowQueryCheck->setChecked(b);
+ m_pQueryOnlyIfUsersSelectedCheck->setEnabled(b);
+ m_pQueryOnlyIfUsersSelectedCheck->setChecked(b && (d->m_uFlags & KviAction::WindowOnlyIfUsersSelected));
+ m_pWindowDccChatCheck->setChecked(d->m_uFlags & KviAction::WindowDccChat);
+ } else {
+ m_pNameEdit->setText("");
+ m_pNameEdit->setEnabled(false);
+ m_pVisibleNameEdit->setText("");
+ m_pVisibleNameEdit->setEnabled(false);
+ m_pCategoryCombo->setEnabled(false);
+ m_pScriptEditor->setText("");
+ m_pScriptEditor->setEnabled(false);
+ m_pKeySequenceEdit->setText("");
+ m_pKeySequenceEdit->setEnabled(false);
+ m_pDescriptionEdit->setText("");
+ m_pDescriptionEdit->setEnabled(false);
+ m_pSmallIconEdit->setText("");
+ m_pSmallIconEdit->setEnabled(false);
+ m_pBigIconEdit->setText("");
+ m_pBigIconEdit->setEnabled(false);
+ m_pSmallIconButton->setPixmap(QPixmap());
+ m_pSmallIconButton->setEnabled(false);
+ m_pBigIconButton->setPixmap(QPixmap());
+ m_pBigIconButton->setEnabled(false);
+ m_pNeedsContextCheck->setChecked(false);
+ m_pNeedsContextCheck->setEnabled(false);
+ m_pNeedsConnectionCheck->setChecked(false);
+ m_pNeedsConnectionCheck->setEnabled(false);
+ m_pEnableAtLoginCheck->setChecked(false);
+ m_pEnableAtLoginCheck->setEnabled(false);
+ m_pWindowConsoleCheck->setChecked(false);
+ m_pWindowConsoleCheck->setEnabled(false);
+ m_pWindowChannelCheck->setChecked(false);
+ m_pWindowChannelCheck->setEnabled(false);
+ m_pWindowQueryCheck->setChecked(false);
+ m_pWindowQueryCheck->setEnabled(false);
+ m_pWindowDccChatCheck->setChecked(false);
+ m_pWindowDccChatCheck->setEnabled(false);
+ m_pSpecificWindowsCheck->setChecked(false);
+ m_pSpecificWindowsCheck->setEnabled(false);
+ m_pQueryOnlyIfUsersSelectedCheck->setChecked(false);
+ m_pChannelOnlyIfUsersSelectedCheck->setChecked(false);
+ m_pConsoleOnlyIfUsersSelectedCheck->setChecked(false);
+ m_pQueryOnlyIfUsersSelectedCheck->setEnabled(false);
+ m_pChannelOnlyIfUsersSelectedCheck->setEnabled(false);
+ m_pConsoleOnlyIfUsersSelectedCheck->setEnabled(false);
+ }
+}
+
+void KviSingleActionEditor::commit()
+{
+ if(!m_pActionData)return;
+
+ QString tmp = m_pNameEdit->text();
+ if(tmp != m_pActionData->m_szName)
+ {
+ int idx = 1;
+ while(KviActionManager::instance()->coreActionExists(tmp) || m_pActionEditor->actionExists(tmp))
+ {
+ QString tmp2;
+ tmp2.setNum(idx);
+ tmp = m_pNameEdit->text();
+ tmp.append(tmp2);
+ idx++;
+ }
+ }
+
+ m_pActionData->m_szName = tmp;
+ m_pScriptEditor->getText(m_pActionData->m_szScriptCode);
+ m_pActionData->m_szVisibleName = m_pVisibleNameEdit->text();
+ m_pActionData->m_szDescription = m_pDescriptionEdit->text();
+ m_pActionData->m_szBigIcon = m_pBigIconEdit->text();
+ m_pActionData->m_szSmallIcon = m_pSmallIconEdit->text();
+ m_pActionData->m_szKeySequence = m_pKeySequenceEdit->text();
+ QString szCat = m_pCategoryCombo->currentText();
+ int idx = szCat.findRev(')');
+ if(idx != -1)m_pActionData->m_szCategory = szCat.left(idx);
+ else m_pActionData->m_szCategory = szCat;
+ idx = m_pActionData->m_szCategory.findRev('(');
+ if(idx != -1)m_pActionData->m_szCategory.remove(0,idx+1);
+ m_pActionData->m_uFlags = 0;
+ if(m_pNeedsContextCheck->isChecked())
+ {
+ m_pActionData->m_uFlags |= KviAction::NeedsContext;
+ if(m_pNeedsConnectionCheck->isChecked())
+ {
+ m_pActionData->m_uFlags |= KviAction::NeedsConnection;
+ if(m_pEnableAtLoginCheck->isChecked())m_pActionData->m_uFlags |= KviAction::EnableAtLogin;
+ }
+
+ }
+ if(m_pSpecificWindowsCheck->isChecked())
+ {
+ if(m_pWindowConsoleCheck->isChecked())m_pActionData->m_uFlags |= KviAction::WindowConsole;
+ if(m_pWindowChannelCheck->isChecked())m_pActionData->m_uFlags |= KviAction::WindowChannel;
+ if(m_pWindowQueryCheck->isChecked())m_pActionData->m_uFlags |= KviAction::WindowQuery;
+ if(m_pWindowDccChatCheck->isChecked())m_pActionData->m_uFlags |= KviAction::WindowDccChat;
+ if(m_pActionData->m_uFlags & KviAction::InternalWindowMask)
+ {
+ if(m_pConsoleOnlyIfUsersSelectedCheck->isChecked() ||
+ m_pChannelOnlyIfUsersSelectedCheck->isChecked() ||
+ m_pQueryOnlyIfUsersSelectedCheck->isChecked())
+ {
+ m_pActionData->m_uFlags |= KviAction::WindowOnlyIfUsersSelected;
+ }
+ }
+ }
+
+ unsigned int uOldFlags = m_pActionData->m_uFlags;
+ m_pActionData->m_uFlags = KviAction::validateFlags(m_pActionData->m_uFlags);
+ if(m_pActionData->m_uFlags != uOldFlags)
+ debug("invalid action flags in KviSingleActionEditor::commit(): %d fixed to %d",uOldFlags,m_pActionData->m_uFlags);
+}
+
+
+
+
+
+
+
+
+KviActionEditorListView::KviActionEditorListView(QWidget * pParent)
+: KviTalListView(pParent)
+{
+ setSelectionMode(Extended);
+ int iWidth = visibleWidth();
+ if(iWidth < LVI_MINIMUM_CELL_WIDTH)iWidth = LVI_MINIMUM_CELL_WIDTH;
+ addColumn(__tr2qs("Action"),iWidth);
+ setSorting(0,true);
+}
+
+KviActionEditorListView::~KviActionEditorListView()
+{
+}
+
+
+void KviActionEditorListView::resizeEvent(QResizeEvent * e)
+{
+ KviTalListView::resizeEvent(e);
+ int iWidth = visibleWidth();
+ if(iWidth < LVI_MINIMUM_CELL_WIDTH)iWidth = LVI_MINIMUM_CELL_WIDTH;
+ setColumnWidth(0,iWidth);
+}
+
+
+
+
+
+
+
+
+KviActionEditor::KviActionEditor(QWidget * par)
+: QWidget(par)
+{
+
+ QGridLayout * l = new QGridLayout(this,1,1,2,2);
+
+#ifdef COMPILE_USE_QT4
+ m_pSplitter = new QSplitter(Qt::Horizontal,this);
+ m_pSplitter->setOpaqueResize(false);
+
+#else
+ m_pSplitter = new QSplitter(QSplitter::Horizontal,this);
+#endif
+
+ l->addWidget(m_pSplitter,0,0);
+
+
+ KviTalVBox * box = new KviTalVBox(m_pSplitter);
+ m_pListView = new KviActionEditorListView(box);
+ //m_pListView->setMultiSelection(false);
+ m_pListView->setShowSortIndicator(true);
+#ifdef COMPILE_USE_QT4
+ m_pListView->setFocusPolicy(Qt::StrongFocus);
+#else
+ m_pListView->setFocusPolicy(QWidget::StrongFocus);
+#endif
+ connect(m_pListView,SIGNAL(currentChanged(KviTalListViewItem *)),this,SLOT(currentChanged(KviTalListViewItem *)));
+
+
+ m_pNewActionButton = new QPushButton(__tr2qs("New Action"),box);
+ connect(m_pNewActionButton,SIGNAL(clicked()),this,SLOT(newAction()));
+
+ m_pDeleteActionsButton = new QPushButton(__tr2qs("Delete Actions"),box);
+ connect(m_pDeleteActionsButton,SIGNAL(clicked()),this,SLOT(deleteActions()));
+
+ m_pExportActionsButton = new QPushButton(__tr2qs("Export Actions..."),box);
+ connect(m_pExportActionsButton,SIGNAL(clicked()),this,SLOT(exportActions()));
+
+ box->setSpacing(1);
+
+ m_pSingleActionEditor = new KviSingleActionEditor(m_pSplitter,this);
+
+ KviActionEditorListViewItem * last = 0;
+ KviActionEditorListViewItem * first = 0;
+
+ KviPointerHashTableIterator<QString,KviAction> it(*(KviActionManager::instance()->actions()));
+ while(KviAction * a = it.current())
+ {
+ if(a->isKviUserActionNeverOverrideThis())
+ {
+ KviActionData * ad = new KviActionData(a->name(),
+ ((KviKvsUserAction *)a)->scriptCode(),
+ ((KviKvsUserAction *)a)->visibleNameCode(),
+ ((KviKvsUserAction *)a)->descriptionCode(),
+ a->category() ? a->category()->name() : KviActionManager::categoryGeneric()->name(),
+ a->bigIconString(),
+ ((KviKvsUserAction *)a)->smallIconString(),
+ a->flags(),
+ a->keySequence(),
+ 0);
+ KviActionEditorListViewItem * lvi = new KviActionEditorListViewItem(m_pListView,ad);
+ ad->m_pItem = lvi;
+ if(ad->m_szName == g_szLastEditedAction)
+ last = lvi;
+ if(!first)
+ first = lvi;
+ }
+ ++it;
+ }
+
+ if(!last)last = first; // try to sleect the first one then
+
+ if(last)
+ {
+ m_pListView->setCurrentItem(last);
+ currentChanged(last);
+ } else {
+ currentChanged(0);
+ }
+
+}
+
+KviActionEditor::~KviActionEditor()
+{
+}
+
+void KviActionEditor::exportActions()
+{
+ QString szName = QDir::homeDirPath();
+ if(!szName.endsWith(QString(KVI_PATH_SEPARATOR)))szName += KVI_PATH_SEPARATOR;
+ szName += "myactions.kvs";
+
+ QString szFile;
+
+ if(!KviFileDialog::askForSaveFileName(szFile,__tr2qs("Choose a Filename - KVIrc"),szName,QString::null,true,true,true))return;
+
+ QString szCode;
+
+ KviActionEditorListViewItem * it = (KviActionEditorListViewItem *)m_pListView->firstChild();
+ while(it)
+ {
+ if(it->isSelected())
+ {
+ KviActionData * a = it->actionData();
+
+ KviKvsUserAction::exportToKvs(szCode,
+ a->m_szName,
+ a->m_szScriptCode,
+ a->m_szVisibleName,
+ a->m_szDescription,
+ a->m_szCategory,
+ a->m_szBigIcon,
+ a->m_szSmallIcon,
+ a->m_uFlags,
+ a->m_szKeySequence);
+ }
+
+ it = (KviActionEditorListViewItem *)(it->nextSibling());
+ }
+
+ if(!KviFileUtils::writeFile(szFile,szCode))
+ {
+ QMessageBox::warning(this,__tr2qs("Write Failed - KVIrc"),__tr2qs("Unable to write to the actions file."),__tr2qs("OK"));
+ }
+}
+
+void KviActionEditor::deleteActions()
+{
+ KviPointerList<KviActionEditorListViewItem> l;
+ l.setAutoDelete(false);
+
+ KviActionEditorListViewItem * it = (KviActionEditorListViewItem *)m_pListView->firstChild();
+ while(it)
+ {
+ if(it->isSelected())
+ l.append(it);
+
+ it = (KviActionEditorListViewItem *)(it->nextSibling());
+ }
+
+ if(l.isEmpty())return;
+
+ //if(QMessageBox::question(this,__tr2qsf("Confirm Deletion"),__tr2qsf("Do you really want to delete the selected actions ?"),__tr2qsf("Yes"),__tr2qsf("No")) != 0)
+ // return;
+
+ for(KviActionEditorListViewItem * i = l.first();i;i = l.next())
+ {
+ if(m_pSingleActionEditor->actionData() == i->actionData())
+ m_pSingleActionEditor->setActionData(0);
+ delete i;
+ }
+}
+
+
+QString KviActionEditor::nameForAutomaticAction(const QString &szTemplate)
+{
+ QString ret;
+ QString szT = szTemplate;
+ szT.replace(" ","");
+ szT.replace(".","_");
+
+ int i = 1;
+ do {
+ KviQString::sprintf(ret,"%Q%d",&szT,i);
+ i++;
+ } while(actionExists(ret));
+
+ return ret;
+}
+
+void KviActionEditor::newAction()
+{
+ QString szName = nameForAutomaticAction(__tr2qs("My Action"));
+ QString szVis = __tr2qs("My Action");
+ QString szDes = __tr2qs("Put here a short description of your action");
+
+ szVis.prepend("$tr(\"");
+ szVis.append("\")");
+ szDes.prepend("$tr(\"");
+ szDes.append("\")");
+
+ KviActionData * ad = new KviActionData(szName,
+ QString::null,
+ szVis,
+ szDes,
+ KviActionManager::categoryGeneric()->name(),
+ QString::null,
+ QString::null,
+ 0,
+ QString::null,
+ 0);
+
+ KviActionEditorListViewItem * lvi = new KviActionEditorListViewItem(m_pListView,ad);
+ ad->m_pItem = lvi;
+ m_pListView->setCurrentItem(lvi);
+ currentChanged(lvi);
+}
+
+bool KviActionEditor::actionExists(const QString &szName)
+{
+ KviActionEditorListViewItem * it = (KviActionEditorListViewItem *)m_pListView->firstChild();
+ while(it)
+ {
+ if(it->actionData()->m_szName == szName)return true;
+ it = (KviActionEditorListViewItem *)(it->nextSibling());
+ }
+ return false;
+}
+
+
+void KviActionEditor::currentChanged(KviTalListViewItem * i)
+{
+ if(m_pSingleActionEditor->actionData())
+ {
+ m_pSingleActionEditor->commit();
+ m_pSingleActionEditor->actionData()->m_pItem->setupForActionData();
+ }
+
+ m_pListView->update();
+
+ KviActionEditorListViewItem * it = (KviActionEditorListViewItem *)i;
+ if(!it)
+ {
+ m_pSingleActionEditor->setActionData(0);
+ m_pDeleteActionsButton->setEnabled(false);
+ m_pExportActionsButton->setEnabled(false);
+ return;
+ }
+ m_pDeleteActionsButton->setEnabled(true);
+ m_pExportActionsButton->setEnabled(true);
+
+ if(!it->isSelected())m_pListView->setSelected(it,true);
+
+ m_pSingleActionEditor->setActionData(it->actionData());
+ g_szLastEditedAction = it->actionData()->m_szName;
+}
+
+void KviActionEditor::commit()
+{
+ m_pSingleActionEditor->commit();
+
+ // the hard part: update the actions without destroying them...
+
+ KviActionManager::instance()->killAllKvsUserActions();
+
+ KviActionEditorListViewItem * it = (KviActionEditorListViewItem *)m_pListView->firstChild();
+ while(it)
+ {
+ KviKvsUserAction * a = KviKvsUserAction::createInstance( // msvc workaround
+ KviActionManager::instance(),
+ it->actionData()->m_szName,
+ it->actionData()->m_szScriptCode,
+ it->actionData()->m_szVisibleName,
+ it->actionData()->m_szDescription,
+ it->actionData()->m_szCategory,
+ it->actionData()->m_szBigIcon,
+ it->actionData()->m_szSmallIcon,
+ it->actionData()->m_uFlags,
+ it->actionData()->m_szKeySequence);
+
+ KviActionManager::instance()->registerAction(a);
+
+ it = (KviActionEditorListViewItem *)(it->nextSibling());
+ }
+
+ KviCustomToolBarManager::instance()->updateVisibleToolBars();
+}
+
+
+
+KviActionEditorWindow::KviActionEditorWindow(KviFrame * lpFrm)
+: KviWindow(KVI_WINDOW_TYPE_SCRIPTEDITOR,lpFrm,"actioneditor",0)
+{
+ g_pActionEditorWindow = this;
+ setFixedCaption(__tr2qs("Action Editor"));
+
+ m_pEditor = new KviActionEditor(this);
+
+ m_pBase = new QWidget(this);
+ QGridLayout * g = new QGridLayout(m_pBase,1,4,4,4);
+
+ QPushButton * btn = new QPushButton(__tr2qs("OK"),m_pBase);
+ btn->setMinimumWidth(80);
+ connect(btn,SIGNAL(clicked()),this,SLOT(okClicked()));
+ btn->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_ACCEPT)));
+ g->addWidget(btn,0,1);
+
+ btn = new QPushButton(__tr2qs("Apply"),m_pBase);
+ btn->setMinimumWidth(80);
+ connect(btn,SIGNAL(clicked()),this,SLOT(applyClicked()));
+ btn->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_ACCEPT)));
+ g->addWidget(btn,0,2);
+
+ btn = new QPushButton(__tr2qs("Cancel"),m_pBase);
+ btn->setMinimumWidth(80);
+ connect(btn,SIGNAL(clicked()),this,SLOT(cancelClicked()));
+ btn->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_DISCARD)));
+ g->addWidget(btn,0,3);
+
+ g->setColStretch(0,1);
+
+}
+
+KviActionEditorWindow::~KviActionEditorWindow()
+{
+ g_pActionEditorWindow = 0;
+}
+
+void KviActionEditorWindow::okClicked()
+{
+ m_pEditor->commit();
+ close();
+}
+
+void KviActionEditorWindow::applyClicked()
+{
+ m_pEditor->commit();
+}
+
+void KviActionEditorWindow::cancelClicked()
+{
+ close();
+}
+
+
+QPixmap * KviActionEditorWindow::myIconPtr()
+{
+ return g_pIconManager->getSmallIcon(KVI_SMALLICON_SCRIPTACTION);
+}
+
+void KviActionEditorWindow::resizeEvent(QResizeEvent *e)
+{
+ int hght = m_pBase->sizeHint().height();
+ m_pEditor->setGeometry(0,0,width(),height()- hght);
+ m_pBase->setGeometry(0,height() - hght,width(),hght);
+}
+
+
+void KviActionEditorWindow::getConfigGroupName(KviStr &szName)
+{
+ szName = "actioneditor";
+}
+
+
+void KviActionEditorWindow::saveProperties(KviConfig *cfg)
+{
+ KviWindow::saveProperties(cfg);
+ cfg->writeEntry("Splitter",m_pEditor->m_pSplitter->sizes());
+}
+
+void KviActionEditorWindow::loadProperties(KviConfig *cfg)
+{
+ int w = width();
+ KviWindow::loadProperties(cfg);
+ KviValueList<int> def;
+ def.append((w * 25) / 100);
+ def.append((w * 75) / 100);
+ m_pEditor->m_pSplitter->setSizes(cfg->readIntListEntry("Splitter",def));
+}
diff --git a/src/modules/actioneditor/actioneditor.h b/src/modules/actioneditor/actioneditor.h
new file mode 100644
index 00000000..fc112614
--- /dev/null
+++ b/src/modules/actioneditor/actioneditor.h
@@ -0,0 +1,210 @@
+#ifndef _ACTIONEDITOR_H_
+#define _ACTIONEDITOR_H_
+//=============================================================================
+//
+// File : actioneditor.h
+// Creation date : Tue Dec 29 2004 02:40:55 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2004 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the linkss of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_window.h"
+
+#include <qwidget.h>
+#include "kvi_tal_listview.h"
+#include "kvi_styled_controls.h"
+
+class KviActionEditorListViewItem;
+
+class KviActionData
+{
+public:
+ QString m_szName;
+ QString m_szScriptCode;
+ QString m_szVisibleName;
+ QString m_szDescription;
+ QString m_szCategory;
+ QString m_szBigIcon;
+ QString m_szSmallIcon;
+ QString m_szKeySequence;
+ unsigned int m_uFlags;
+ KviActionEditorListViewItem * m_pItem; // ummigarba tanto...
+public:
+ KviActionData(const QString &szName,
+ const QString &szScriptCode,
+ const QString &szVisibleName,
+ const QString &szDescription,
+ const QString &szCategory,
+ const QString &szBigIcon,
+ const QString &szSmallIcon,
+ unsigned int uFlags,
+ const QString &szKeySequence,
+ KviActionEditorListViewItem * pItem)
+ : m_szName(szName), m_szScriptCode(szScriptCode), m_szVisibleName(szVisibleName),
+ m_szDescription(szDescription), m_szCategory(szCategory), m_szBigIcon(szBigIcon),
+ m_szSmallIcon(szSmallIcon), m_szKeySequence(szKeySequence), m_uFlags(uFlags),
+ m_pItem(pItem)
+ {};
+};
+
+
+class QLineEdit;
+class QComboBox;
+class KviScriptEditor;
+class QToolButton;
+class QSimpleRichText;
+class QPushButton;
+
+#ifdef COMPILE_USE_QT4
+ #include <q3simplerichtext.h>
+ #define QSimpleRichText Q3SimpleRichText
+#else
+ #include <qsimplerichtext.h>
+#endif
+
+
+
+class KviActionEditorListViewItem : public KviTalListViewItem
+{
+public:
+ KviActionEditorListViewItem(KviTalListView * v,KviActionData * a);
+ ~KviActionEditorListViewItem();
+protected:
+ KviActionData * m_pActionData;
+ QSimpleRichText * m_pText;
+ QPixmap * m_pIcon;
+ KviTalListView * m_pListView;
+ QString m_szKey;
+public:
+ KviActionData * actionData(){ return m_pActionData; };
+ void setupForActionData();
+public:
+ virtual void paintCell(QPainter * p,const QColorGroup & cg,int column,int width,int align);
+ virtual void setup();
+ virtual QString key(int,bool) const;
+};
+
+
+class KviActionEditorListView : public KviTalListView
+{
+ Q_OBJECT
+public:
+ KviActionEditorListView(QWidget * pParent);
+ ~KviActionEditorListView();
+protected:
+ virtual void resizeEvent(QResizeEvent * e);
+};
+
+class KviActionEditor;
+
+class KviSingleActionEditor : public QWidget
+{
+ Q_OBJECT
+public:
+ KviSingleActionEditor(QWidget * par,KviActionEditor * ed);
+ ~KviSingleActionEditor();
+protected:
+ KviActionEditor * m_pActionEditor;
+ KviActionData * m_pActionData;
+ QLineEdit * m_pNameEdit;
+ QLineEdit * m_pVisibleNameEdit;
+ QComboBox * m_pCategoryCombo;
+ KviScriptEditor * m_pScriptEditor;
+ QLineEdit * m_pKeySequenceEdit;
+ QLineEdit * m_pDescriptionEdit;
+ QLineEdit * m_pSmallIconEdit;
+ QLineEdit * m_pBigIconEdit;
+ QToolButton * m_pSmallIconButton;
+ QToolButton * m_pBigIconButton;
+ KviStyledCheckBox * m_pNeedsContextCheck;
+ KviStyledCheckBox * m_pNeedsConnectionCheck;
+ KviStyledCheckBox * m_pEnableAtLoginCheck;
+ KviStyledCheckBox * m_pSpecificWindowsCheck;
+ KviStyledCheckBox * m_pWindowConsoleCheck;
+ KviStyledCheckBox * m_pWindowChannelCheck;
+ KviStyledCheckBox * m_pWindowQueryCheck;
+ KviStyledCheckBox * m_pWindowDccChatCheck;
+ KviStyledCheckBox * m_pConsoleOnlyIfUsersSelectedCheck;
+ KviStyledCheckBox * m_pChannelOnlyIfUsersSelectedCheck;
+ KviStyledCheckBox * m_pQueryOnlyIfUsersSelectedCheck;
+public:
+ KviActionData * actionData(){ return m_pActionData; };
+ void setActionData(KviActionData * d);
+ void commit();
+protected slots:
+ void chooseSmallIcon();
+ void chooseBigIcon();
+ void needsContextCheckToggled(bool);
+ void needsConnectionCheckToggled(bool);
+ void specificWindowsCheckToggled(bool);
+ void channelQueryOrConsoleWindowCheckToggled(bool);
+};
+
+class QSplitter;
+
+class KviActionEditor : public QWidget
+{
+ friend class KviActionEditorWindow;
+ Q_OBJECT
+public:
+ KviActionEditor(QWidget * par);
+ ~KviActionEditor();
+protected:
+ KviActionEditorListView * m_pListView;
+ KviSingleActionEditor * m_pSingleActionEditor;
+ QSplitter * m_pSplitter;
+ QPushButton * m_pNewActionButton;
+ QPushButton * m_pDeleteActionsButton;
+ QPushButton * m_pExportActionsButton;
+public:
+ void commit();
+ bool actionExists(const QString &szName);
+protected:
+ int selectedCount();
+ QString nameForAutomaticAction(const QString &szTemplate);
+protected slots:
+ void currentChanged(KviTalListViewItem * it);
+ void newAction();
+ void deleteActions();
+ void exportActions();
+};
+
+
+class KviActionEditorWindow : public KviWindow
+{
+ Q_OBJECT
+public:
+ KviActionEditorWindow(KviFrame * lpFrm);
+ ~KviActionEditorWindow();
+protected:
+ KviActionEditor * m_pEditor;
+ QWidget * m_pBase;
+protected:
+ virtual QPixmap * myIconPtr();
+ virtual void resizeEvent(QResizeEvent *e);
+ virtual void getConfigGroupName(KviStr &szName);
+ virtual void saveProperties(KviConfig *);
+ virtual void loadProperties(KviConfig *);
+protected slots:
+ void cancelClicked();
+ void okClicked();
+ void applyClicked();
+};
+
+#endif //_ACTIONEDITOR_H_
diff --git a/src/modules/actioneditor/libkviactioneditor.cpp b/src/modules/actioneditor/libkviactioneditor.cpp
new file mode 100644
index 00000000..c2e489e5
--- /dev/null
+++ b/src/modules/actioneditor/libkviactioneditor.cpp
@@ -0,0 +1,86 @@
+//=============================================================================
+//
+// File : libkviactioneditor.cpp
+// Creation date : Tue 29 Dec 2004 02:45:59 2002 GMT by Szymon Stefanek
+//
+// This toolbar is part of the KVirc irc client distribution
+// Copyright (C) 2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_module.h"
+#include "kvi_locale.h"
+#include "kvi_frame.h"
+
+#include "actioneditor.h"
+KviActionEditorWindow * g_pActionEditorWindow = 0;
+
+
+/*
+ @doc: actioneditor.open
+ @type:
+ command
+ @title:
+ actioneditor.open
+ @short:
+ Shows the action editor
+ @syntax:
+ actioneditor.open
+ @description:
+ Opens the script action editor dialog.
+*/
+
+static bool actioneditor_kvs_cmd_open(KviKvsModuleCommandCall * c)
+{
+ if(!g_pActionEditorWindow)
+ {
+ g_pActionEditorWindow = new KviActionEditorWindow(c->window()->frame());
+ c->window()->frame()->addWindow(g_pActionEditorWindow);
+ }
+
+ g_pActionEditorWindow->setFocus();
+ return true;
+}
+static bool actioneditor_module_init(KviModule * m)
+{
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"open",actioneditor_kvs_cmd_open);
+ g_pActionEditorWindow = 0;
+ return true;
+}
+
+static bool actioneditor_module_can_unload(KviModule * m)
+{
+ return (g_pActionEditorWindow == 0);
+}
+
+static bool actioneditor_module_cleanup(KviModule *m)
+{
+ if(g_pActionEditorWindow)delete g_pActionEditorWindow;
+ g_pActionEditorWindow = 0;
+ return true;
+}
+
+KVIRC_MODULE(
+ "ActionEditor", // module name
+ "1.0.0", // module version
+ "Copyright (C) 2004 Szymon Stefanek (pragma at kvirc dot net)", // author & (C)
+ "Editor for the script actions",
+ actioneditor_module_init,
+ actioneditor_module_can_unload,
+ 0,
+ actioneditor_module_cleanup
+)
diff --git a/src/modules/addon/Makefile.am b/src/modules/addon/Makefile.am
new file mode 100644
index 00000000..e232b8ff
--- /dev/null
+++ b/src/modules/addon/Makefile.am
@@ -0,0 +1,22 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+SUBDIRS = pics
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkviaddon.la
+
+libkviaddon_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkviaddon_la_SOURCES = libkviaddon.cpp managementdialog.cpp
+nodist_libkviaddon_la_SOURCES = moc_managementdialog.cpp
+
+libkviaddon_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+noinst_HEADERS= managementdialog.h
+
+moc_managementdialog.cpp: managementdialog.h
+ $(SS_QT_MOC) $< -o $@
diff --git a/src/modules/addon/libkviaddon.cpp b/src/modules/addon/libkviaddon.cpp
new file mode 100644
index 00000000..a7cd4b88
--- /dev/null
+++ b/src/modules/addon/libkviaddon.cpp
@@ -0,0 +1,659 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// File : libkviaddon.cpp
+// Creation date : Tue 31 Mar 01:02:12 2005 GMT by Szymon Stefanek
+//
+// This toolbar is part of the KVirc irc client distribution
+// Copyright (C) 2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "kvi_module.h"
+#include "kvi_kvs_scriptaddonmanager.h"
+#include "kvi_locale.h"
+#include "kvi_qstring.h"
+#include "kvi_parameterlist.h"
+#include "kvi_cmdformatter.h"
+#include "kvi_qstring.h"
+#include "kvi_error.h"
+#include "kvi_out.h"
+#include "kvi_iconmanager.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_config.h"
+#include "kvi_sourcesdate.h"
+#include "kvi_miscutils.h"
+
+#include "managementdialog.h"
+
+
+
+QRect g_rectManagementDialogGeometry(0,0,0,0);
+
+/*
+ @doc: addon.exists
+ @type:
+ function
+ @title:
+ $addon.exists
+ @short:
+ Checks if an addon is currently installed
+ @syntax:
+ <boolean> $addon.exists(<id:string>[,<version:string>])
+ @description:
+ Returns 1 if the addon with the specified <id> is currently installed
+ and 0 otherwise. If <version> is specified then any addon with
+ a version lower than <version> is ignored (so you can effectively
+ check if a greater or equal version is present).
+*/
+
+static bool addon_kvs_fnc_exists(KviKvsModuleFunctionCall * c)
+{
+ QString szId;
+ QString szVersion;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("id",KVS_PT_NONEMPTYSTRING,0,szId)
+ KVSM_PARAMETER("version",KVS_PT_STRING,KVS_PF_OPTIONAL,szVersion)
+ KVSM_PARAMETERS_END(c)
+
+ KviKvsScriptAddon * a = KviKvsScriptAddonManager::instance()->findAddon(szId);
+ if(a)
+ {
+ if(szVersion.isEmpty())
+ {
+ c->returnValue()->setBoolean(true);
+ } else {
+ c->returnValue()->setBoolean(KviMiscUtils::compareVersions(a->version(),szVersion) < 0);
+ }
+ } else {
+ c->returnValue()->setBoolean(false);
+ }
+ return true;
+}
+
+/*
+ @doc: addon.version
+ @type:
+ function
+ @title:
+ $addon.version
+ @short:
+ Returns the version of an installed addon
+ @syntax:
+ <string> $addon.version(<id:string>)
+ @description:
+ Returns the version of the currently installed addon with the
+ specified <id>. If the addon with the given <id> does not exist
+ then an empty string is returned.
+*/
+
+static bool addon_kvs_fnc_version(KviKvsModuleFunctionCall * c)
+{
+ QString szId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("id",KVS_PT_NONEMPTYSTRING,0,szId)
+ KVSM_PARAMETERS_END(c)
+
+ KviKvsScriptAddon * a = KviKvsScriptAddonManager::instance()->findAddon(szId);
+ if(a)
+ {
+ c->returnValue()->setString(a->version());
+ } else {
+ c->returnValue()->setNothing();
+ }
+ return true;
+}
+
+/*
+ @doc: addon.list
+ @type:
+ command
+ @title:
+ addon.list
+ @short:
+ Lists the installed addons
+ @syntax:
+ addon.list
+ @description:
+ Lists the currently installed addons
+ @seealso:
+ [cmd]addon.register[/cmd]
+*/
+
+static bool addon_kvs_cmd_list(KviKvsModuleCommandCall * c)
+{
+ KviPointerHashTable<QString,KviKvsScriptAddon> * da = KviKvsScriptAddonManager::instance()->addonDict();
+
+ int cnt = 0;
+ KviPointerHashTableIterator<QString,KviKvsScriptAddon> it(*da);
+ while(KviKvsScriptAddon * a = it.current())
+ {
+ c->window()->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("%cAddon id %Q, version %Q%c"),KVI_TEXT_BOLD,&(a->name()),&(a->version()),KVI_TEXT_BOLD);
+ c->window()->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Name: %Q"),&(a->visibleName()));
+ c->window()->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Description: %Q"),&(a->description()));
+
+ ++it;
+ cnt++;
+ }
+
+ c->window()->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Total: %d addons installed"),cnt);
+ return true;
+}
+
+/*
+ @doc: addon.uninstall
+ @type:
+ command
+ @title:
+ addon.uninstall
+ @short:
+ Uninstalls an addon
+ @syntax:
+ addon.uninstall [-q] [-n] <id:string>
+ @switches:
+ !sw: -n | --no-callback
+ Doesn't call the uninstall callback but only removes the
+ registration entry.
+ !sw: -q | --quiet
+ Makes the command run quietly
+ @description:
+ Uninstalls the specified addon by executing its uninstall callback function.
+ It also removes the addon's registration entry.
+ If the -n switch is specified the the uninstall callback is not called,
+ only the registration entry is removed.
+ @seealso:
+ [cmd]addon.register[/cmd]
+*/
+
+static bool addon_kvs_cmd_uninstall(KviKvsModuleCommandCall * c)
+{
+ QString szName;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("name",KVS_PT_NONEMPTYSTRING,0,szName)
+ KVSM_PARAMETERS_END(c)
+
+ KviKvsScriptAddon * a = KviKvsScriptAddonManager::instance()->findAddon(szName);
+ if(a)
+ {
+ if(!c->switches()->find('q',"quiet"))
+ c->window()->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Uninstalling existing addon version %Q"),&(a->version()));
+
+ // uninstall the existing version
+ KviKvsScriptAddonManager::instance()->unregisterAddon(szName,c->window(),!c->switches()->find('n',"no-callback"));
+ } else {
+ if(!c->switches()->find('q',"quiet"))
+ c->warning(__tr2qs("The addon \"%1\" does not exist").arg(szName));
+ }
+
+ return true;
+}
+
+/*
+ @doc: addon.configure
+ @type:
+ command
+ @title:
+ addon.configure
+ @short:
+ Executes a addon's configuration callback
+ @syntax:
+ addon.configure [-q] <id:string>
+ @switches:
+ !sw: -q | --quiet
+ Makes the command run quietly
+ @description:
+ Executes the configuration callback of the specified addon.
+ @seealso:
+ [cmd]addon.register[/cmd]
+ [cmd]addon.setconfigurecallback[/cmd]
+*/
+
+static bool addon_kvs_cmd_configure(KviKvsModuleCommandCall * c)
+{
+ QString szName;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("name",KVS_PT_NONEMPTYSTRING,0,szName)
+ KVSM_PARAMETERS_END(c)
+
+ KviKvsScriptAddon * a = KviKvsScriptAddonManager::instance()->findAddon(szName);
+ if(a)
+ {
+ QString ss = a->configureCallbackCode();
+ if(ss.isEmpty())
+ {
+ if(!c->switches()->find('q',"quiet"))
+ c->warning(__tr2qs("The addon \"%1\" has no configure callback set").arg(szName));
+ } else {
+ a->executeConfigureCallback(c->window());
+ }
+ } else {
+ if(!c->switches()->find('q',"quiet"))
+ c->warning(__tr2qs("The addon \"%1\" does not exist").arg(szName));
+ }
+
+ return true;
+}
+
+/*
+ @doc: addon.help
+ @type:
+ command
+ @title:
+ addon.help
+ @short:
+ Executes a addon's help callback
+ @syntax:
+ addon.help [-q] <id:string>
+ @switches:
+ !sw: -q | --quiet
+ Makes the command run quietly
+ @description:
+ Executes the help callback of the specified addon.
+ It will usually display the addon's documentation in the help viewer.
+ @seealso:
+ [cmd]addon.register[/cmd]
+ [cmd]addon.sethelpcallback[/cmd]
+*/
+
+static bool addon_kvs_cmd_help(KviKvsModuleCommandCall * c)
+{
+ QString szName;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("name",KVS_PT_NONEMPTYSTRING,0,szName)
+ KVSM_PARAMETERS_END(c)
+
+ KviKvsScriptAddon * a = KviKvsScriptAddonManager::instance()->findAddon(szName);
+ if(a)
+ {
+ QString ss = a->helpCallbackCode();
+ if(ss.isEmpty())
+ {
+ if(!c->switches()->find('q',"quiet"))
+ c->warning(__tr2qs("The addon \"%1\" has no help callback set").arg(szName));
+ } else {
+ a->executeHelpCallback(c->window());
+ }
+ } else {
+ if(!c->switches()->find('q',"quiet"))
+ c->warning(__tr2qs("The addon \"%1\" does not exist").arg(szName));
+ }
+
+ return true;
+}
+
+/*
+ @doc: addon.setconfigurecallback
+ @type:
+ command
+ @title:
+ addon.setconfigurecallback
+ @short:
+ Sets a addon's configuration callback
+ @syntax:
+ addon.setconfigurecallback [-q] (<id:string>)
+ {
+ <configure_callback>
+ }
+ @switches:
+ !sw: -q
+ Makes the command run quietly
+ @description:
+ Sets the configure callback for the specified addon.
+ The configure callback will be called by the user either by the
+ means of [cmd]addon.configure[/cmd] or by accessing the
+ proper function via GUI.
+ @seealso:
+ [cmd]addon.register[/cmd]
+ [cmd]addon.configure[/cmd]
+*/
+
+static bool addon_kvs_cmd_setconfigurecallback(KviKvsModuleCallbackCommandCall * c)
+{
+ QString szName;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("name",KVS_PT_NONEMPTYSTRING,0,szName)
+ KVSM_PARAMETERS_END(c)
+
+ KviKvsScriptAddon * a = KviKvsScriptAddonManager::instance()->findAddon(szName);
+ if(a)
+ {
+ a->setConfigureCallback(c->callback()->code());
+ } else {
+ if(!c->switches()->find('q',"quiet"))
+ c->warning(__tr2qs("The addon \"%1\" does not exist").arg(szName));
+ }
+
+ return true;
+}
+
+/*
+ @doc: addon.sethelpcallback
+ @type:
+ command
+ @title:
+ addon.sethelpcallback
+ @short:
+ Sets a addon's configuration callback
+ @syntax:
+ addon.sethelpcallback(<id:string>)
+ {
+ <configure_callback>
+ }
+ @switches:
+ !sw: -q
+ Makes the command run quietly
+ @description:
+ Sets the help callback for the specified addon.
+ The help callback will be called by the user either by the
+ means of [cmd]addon.help[/cmd] or by accessing the
+ proper function via GUI. It should display some sort
+ of addon documentation, usually in the help browser.
+ @seealso:
+ [cmd]addon.register[/cmd]
+ [cmd]addon.help[/cmd]
+*/
+
+static bool addon_kvs_cmd_sethelpcallback(KviKvsModuleCallbackCommandCall * c)
+{
+ QString szName;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("name",KVS_PT_NONEMPTYSTRING,0,szName)
+ KVSM_PARAMETERS_END(c)
+
+ KviKvsScriptAddon * a = KviKvsScriptAddonManager::instance()->findAddon(szName);
+ if(a)
+ {
+ a->setHelpCallback(c->callback()->code());
+ } else {
+ if(!c->switches()->find('q',"quiet"))
+ c->warning(__tr2qs("The addon \"%1\" does not exist").arg(szName));
+ }
+
+ return true;
+}
+
+/*
+ @doc: addon.register
+ @type:
+ command
+ @title:
+ addon.register
+ @short:
+ Registers a script-based addon
+ @syntax:
+ addon.register [-f] [-n] [-q] (<id:string>,<version:string>,<visible_name:string>,<description:string>,<minkvircverion:string>[,<iconid:string>])
+ {
+ <uninstall callback>
+ }
+ @switches:
+ !sw: -f | --force
+ Registers the addon even if an addon with the same <id> and
+ a higher version already exists. The usage of this flag
+ is highly discouraged (i.e. use it only for debugging purposes
+ on your own machine).
+ !sw: -n | --no-uninstall
+ Performs no uninstallation of existing versions of the addon:
+ it simply replaces the registration entry with the new data.
+ Again, do NOT use this switch if not for debugging purposes
+ and on your own machine.
+ !sw: -q | --quiet
+ Makes the command run quietly
+ @description:
+ [p]
+ Registers a script-based addon.
+ [/p]
+ [p]
+ The registration process allows to "show" the addon in the script-addon manager
+ dialog and provides a standard way for the user to manage and uninstall the addons.
+ You simply register your addon BEFORE attempting to install it.
+ [/p]
+ [p]
+ A script-based addon is a set of scripts, icons, translations and possibly
+ other data files that add functionality to the KVIrc program.
+ The script-based addons are often simply called "scripts" and
+ we will adhere to that naming in certain parts of the documentation too.
+ [/p]
+ [p]
+ Each script-based addon (a set of scripts) is identified by an UNIQUE
+ <id>. Two addons with the same <id> can't co-exist in the same
+ KVIrc installation (so be sure to choose a token characteristic enough
+ to avoid collisions with others). The <id> itself is used only for
+ identification purposes and the user will almost always see the <visible_name>
+ instead, which can contain the [fnc]$tr[/fnc] function that will handle
+ the translation for it.
+ [/p]
+ [p]
+ Each addon has also a <version> which is a string in the form x.y.z
+ where x, y and z are numbers (yes.. that's the standard major-minor-patch level
+ version numbering scheme). A <version> of 2.4.23 is greater than 2.4.3
+ even if 2.4.3 comes after when compared as a string.
+ When an addon with a greater or equal version is installed over
+ an addon with a lower version, the lower one gets uninstalled first.
+ Installing a lower version over a greater one is not possible, unless
+ the lower versioned one is uninstalled first.
+ [/p]
+ [p]
+ <description> is another, possibly translated, string that will
+ be presented to the user in the addon management dialog.
+ [/p]
+ [p]
+ <minkvircversion> is the minimum KVIrc version required for the
+ addon to run. If the version of the running KVIrc executable
+ is lower than the requested one then the command will abort with an error.
+ If you want to completly ignore the KVIrc versioning (don't do it),
+ use "0.0.0" here. If you need fine tuning on cvs features you may add also
+ the sources date tag at the end of the required version string (e.g 3.2.1.20060303).
+ [/p]
+ [p]
+ <iconid> is the [doc:image_id]image identifier[/doc] of the icon
+ that will be displayed in the addon management dialog.
+ If not specified, a default icon will be used.
+ [/p]
+ [p]
+ The <uninstall_callback> is a snippet of code that should
+ wipe out the addon from the system. It is ALWAYS a good practice
+ to write a complete uninstallation procedure (think that YOU like
+ to be able to completly uninstall a program that you don't use anymore).
+ The <uninstall_callback> will be called by KVIrc when the addon
+ uninstallation is requested, either explicitly by using the GUI or the
+ command [cmd]addon.uninstall[/cmd], or implicitly by installing
+ a newer version of the addon (upgrading).
+ [/p]
+ [p]
+ If the user security rules don't allow your addon to be installed
+ or a higher version of a addon with the same name already exists
+ the command will fail with an error (aborting your whole intallation addon).
+ If you don't want to fail with an error but handle it gracefully instead
+ then you should use [fnc]$addon.exists()[/fnc] to check if a
+ addon with the same name and a greater version already exists.
+ You can't gracefully handle security error conditions: your installation
+ will be always aborted with an error in this case.
+ [/p]
+ [p]
+ The addon can also have a configuration callback settable with [cmd]addon.setconfigurecallback[/cmd]
+ and a help callback settable with [cmd]addon.sethelpcallback[/cmd]. The first
+ will usually display a configuration dialog, the second will display
+ some sort of addon's documentation, usually in the help browser.
+ [/p]
+ [p]
+ The registration process uninstalls any previous addon version
+ by executing its uninstall callback routine. This is another reason for that
+ you should call addon.register BEFORE you attempt to install your addon.
+ Failing to do that may cause your old uninstalled to wipe out your newly
+ installed files or code.
+ [/p]
+ @seealso:
+ [cmd]addon.uninstall[/cmd], [fnc]$addon.exists[/fnc],
+ [cmd]addon.setconfigurecallback[/cmd], [cmd]addon.configure[/cmd],
+ [cmd]addon.sethelpcallback[/cmd], [cmd]addon.help[/cmd]
+ @examples:
+ [example]
+
+ [/example]
+*/
+
+static bool addon_kvs_cmd_register(KviKvsModuleCallbackCommandCall * c)
+{
+ KviKvsScriptAddonRegistrationData rd;
+ QString szMinKVIrcVersion;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("name",KVS_PT_NONEMPTYSTRING,0,(rd.szName))
+ KVSM_PARAMETER("version",KVS_PT_NONEMPTYSTRING,0,(rd.szVersion))
+ KVSM_PARAMETER_IGNORED("visible_text")
+ KVSM_PARAMETER_IGNORED("description")
+ KVSM_PARAMETER("min_kvirc_version",KVS_PT_NONEMPTYSTRING,0,szMinKVIrcVersion)
+ KVSM_PARAMETER("icon_id",KVS_PT_STRING,KVS_PF_OPTIONAL,(rd.szIconId))
+ KVSM_PARAMETERS_END(c)
+
+
+ if(!(c->getParameterCode(2,rd.szVisibleNameScript) && c->getParameterCode(3,rd.szDescriptionScript)))
+ {
+ c->error(__tr2qs("Internal error: call a head-shrinker"));
+ return false;
+ }
+
+ if(c->callback())
+ rd.szUninstallCallbackScript = c->callback()->code();
+
+ if(!KviMiscUtils::isValidVersionString(rd.szVersion))
+ {
+ c->error(__tr2qs("The specified version \"%Q\" is not a valid version string"),&(rd.szVersion));
+ return false;
+ }
+
+ if(!KviMiscUtils::isValidVersionString(szMinKVIrcVersion))
+ {
+ c->error(__tr2qs("The specified KVIrc version \"%Q\" is not a valid version string"),&szMinKVIrcVersion);
+ return false;
+ }
+
+ if(KviMiscUtils::compareVersions(szMinKVIrcVersion,KVI_VERSION "." KVI_SOURCES_DATE) < 0)
+ {
+ c->error(__tr2qs("This KVIrc executable is too old to run this addon (minimum version required is %Q)"),&szMinKVIrcVersion);
+ return false;
+ }
+
+ if(!c->switches()->find('q',"quiet"))
+ c->window()->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Attempting to register addon \"%Q\" with version %Q"),&(rd.szName),&(rd.szVersion));
+
+ KviKvsScriptAddon * a = KviKvsScriptAddonManager::instance()->findAddon(rd.szName);
+ if(a)
+ {
+ // the same addon already exists
+ if(KviMiscUtils::compareVersions(a->version(),rd.szVersion) < 0)
+ {
+ // and it has a higher version...
+ // complain unless -f is used
+ if(!c->switches()->find('f',"force"))
+ {
+ c->error(__tr2qs("The script addon \"%Q\" already exists with version %Q which is higher than %Q"),&(rd.szName),&(a->version()),&(rd.szVersion));
+ return false;
+ }
+ }
+
+ if(!c->switches()->find('q',"quiet"))
+ c->window()->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Uninstalling existing addon version %Q"),&(a->version()));
+
+ // uninstall the existing version
+ KviKvsScriptAddonManager::instance()->unregisterAddon(rd.szName,c->window(),!c->switches()->find('n',"no-uninstall"));
+ }
+
+ if(!KviKvsScriptAddonManager::instance()->registerAddon(&rd))
+ {
+ c->error(__tr2qs("Script registration failed"));
+ return false;
+ }
+
+ if(!c->switches()->find('q',"quiet"))
+ c->window()->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Script succesfully registered"));
+
+ return true;
+}
+
+/*
+ @doc: addon.dialog
+ @type:
+ command
+ @title:
+ addon.dialog
+ @short:
+ Shows the addon addon management editor
+ @syntax:
+ addon.dialog
+ @description:
+ Shows the addon addon management editor
+*/
+
+static bool addon_kvs_cmd_dialog(KviKvsModuleCommandCall * c)
+{
+ KviScriptManagementDialog::display();
+ return true;
+}
+
+static bool addon_module_init(KviModule *m)
+{
+ KVSM_REGISTER_FUNCTION(m,"exists",addon_kvs_fnc_exists);
+ KVSM_REGISTER_FUNCTION(m,"version",addon_kvs_fnc_version);
+
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"dialog",addon_kvs_cmd_dialog);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"list",addon_kvs_cmd_list);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"uninstall",addon_kvs_cmd_uninstall);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"configure",addon_kvs_cmd_configure);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"help",addon_kvs_cmd_help);
+
+ KVSM_REGISTER_CALLBACK_COMMAND(m,"setconfigurecallback",addon_kvs_cmd_setconfigurecallback);
+ KVSM_REGISTER_CALLBACK_COMMAND(m,"sethelpcallback",addon_kvs_cmd_sethelpcallback);
+ KVSM_REGISTER_CALLBACK_COMMAND(m,"register",addon_kvs_cmd_register);
+
+ QString szBuf;
+ m->getDefaultConfigFileName(szBuf);
+ KviConfig cfg(szBuf,KviConfig::Read);
+ g_rectManagementDialogGeometry = cfg.readRectEntry("EditorGeometry",QRect(10,10,390,440));
+
+ return true;
+}
+
+static bool addon_module_cleanup(KviModule *m)
+{
+ KviScriptManagementDialog::cleanup();
+
+ QString szBuf;
+ m->getDefaultConfigFileName(szBuf);
+ KviConfig cfg(szBuf,KviConfig::Write);
+ cfg.writeEntry("EditorGeometry",g_rectManagementDialogGeometry);
+
+ return true;
+}
+
+static bool addon_module_can_unload(KviModule * m)
+{
+ return (!KviScriptManagementDialog::instance());
+}
+
+
+KVIRC_MODULE(
+ "addon", // module name
+ "1.0.0", // module version
+ "Copyright (C) 2005 Szymon Stefanek (pragma at kvirc dot net)", // author & (C)
+ "Script management functions for the KVS engine",
+ addon_module_init,
+ addon_module_can_unload,
+ 0,
+ addon_module_cleanup
+)
diff --git a/src/modules/addon/managementdialog.cpp b/src/modules/addon/managementdialog.cpp
new file mode 100644
index 00000000..a6765587
--- /dev/null
+++ b/src/modules/addon/managementdialog.cpp
@@ -0,0 +1,403 @@
+//=============================================================================
+//
+// File : managementdialog.cpp
+// Created on Fri 08 Apr 2005 14:54:56 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "managementdialog.h"
+
+#include "kvi_listview.h"
+#include "kvi_locale.h"
+#include "kvi_frame.h"
+#include "kvi_iconmanager.h"
+#include "kvi_kvs_scriptaddonmanager.h"
+#include "kvi_window.h"
+
+#include "kvi_filedialog.h"
+#include "kvi_fileutils.h"
+#include "kvi_kvs_script.h"
+#include "kvi_sourcesdate.h"
+
+#include <qpushbutton.h>
+#include <qlayout.h>
+#include <qapplication.h>
+#include <qtooltip.h>
+#include <qlineedit.h>
+#include <qlabel.h>
+#include <qmessagebox.h>
+#include <qframe.h>
+#include "kvi_tal_scrollview.h"
+#ifdef COMPILE_USE_QT4
+ #include <q3header.h>
+
+#else
+ #include <qheader.h>
+#endif
+#include "kvi_draganddrop.h"
+#include <qpainter.h>
+#include <qpixmap.h>
+#include <qmessagebox.h>
+#include <qevent.h>
+
+KviScriptManagementDialog * KviScriptManagementDialog::m_pInstance = 0;
+extern QRect g_rectManagementDialogGeometry;
+
+
+#define LVI_ICON_SIZE 32
+#define LVI_BORDER 4
+#define LVI_SPACING 8
+#define LVI_MINIMUM_TEXT_WIDTH 300
+#define LVI_MINIMUM_CELL_WIDTH (LVI_MINIMUM_TEXT_WIDTH + LVI_BORDER + LVI_ICON_SIZE + LVI_SPACING + LVI_BORDER)
+
+KviScriptAddonListViewItem::KviScriptAddonListViewItem(KviTalListView * v,KviKvsScriptAddon * a)
+: KviTalListViewItem(v,"")
+{
+ m_pAddon = new KviKvsScriptAddon(*a);
+ m_pListView = v;
+ QString t = "<nobr><b>";
+ t += a->visibleName();
+ t += "</b> [";
+ t += a->version();
+ t += "]";
+ t += " <font color=\"#a0a0a0\">[";
+ t += a->name();
+ t += "]</font></nobr>";
+ t += "<br><nobr><font size=\"-1\">";
+ t += a->description();
+ t += "</font></nobr>";
+ m_szKey = a->visibleName().upper();
+#ifdef COMPILE_USE_QT4
+ m_pText = new QTextDocument();
+ m_pText->setHtml(t);
+ m_pText->setDefaultFont(v->font());
+#else
+ m_pText = new QSimpleRichText(t,v->font());
+#endif
+
+ QPixmap * p = a->icon();
+ m_pIcon = p ? new QPixmap(*p) : new QPixmap(LVI_ICON_SIZE,LVI_ICON_SIZE);
+}
+
+KviScriptAddonListViewItem::~KviScriptAddonListViewItem()
+{
+ delete m_pIcon;
+ delete m_pText;
+ delete m_pAddon;
+}
+
+QString KviScriptAddonListViewItem::key(int,bool) const
+{
+ return m_szKey;
+}
+
+void KviScriptAddonListViewItem::setup()
+{
+ KviTalListViewItem::setup();
+ int iWidth = m_pListView->visibleWidth();
+ if(iWidth < LVI_MINIMUM_CELL_WIDTH)iWidth = LVI_MINIMUM_CELL_WIDTH;
+ iWidth -= LVI_BORDER + LVI_ICON_SIZE + LVI_SPACING + LVI_BORDER;
+
+ #ifdef COMPILE_USE_QT4
+ int iHeight = m_pText->size().height() + (2 * LVI_BORDER);
+ #else
+ m_pText->setWidth(iWidth);
+ int iHeight = m_pText->height() + (2 * LVI_BORDER);
+ #endif
+ if(iHeight < (LVI_ICON_SIZE + (2 * LVI_BORDER)))iHeight = LVI_ICON_SIZE + (2 * LVI_BORDER);
+ setHeight(iHeight+2);
+}
+
+void KviScriptAddonListViewItem::paintCell(QPainter * p,const QColorGroup & cg,int column,int width,int align)
+{
+ #ifdef COMPILE_USE_QT4
+ if (isSelected())
+ {
+ QColor col(m_pListView->palette().highlight());
+ col.setAlpha(127);
+ p->setBrush(col);
+ p->drawRect(0, 0, m_pListView->visibleWidth(), height());
+ }
+ p->drawPixmap(LVI_BORDER,LVI_BORDER,*m_pIcon);
+ int afterIcon = LVI_BORDER + LVI_ICON_SIZE + LVI_SPACING;
+ int www = m_pListView->visibleWidth() - (afterIcon + LVI_BORDER);
+ p->translate(afterIcon,LVI_BORDER);
+ m_pText->setPageSize(QSizeF(www,height() - (LVI_BORDER * 2)));
+ m_pText->drawContents(p);
+ #else
+ p->drawPixmap(LVI_BORDER,LVI_BORDER,*m_pIcon);
+ int afterIcon = LVI_BORDER + LVI_ICON_SIZE + LVI_SPACING;
+ int www = m_pListView->visibleWidth() - (afterIcon + LVI_BORDER);
+ m_pText->setWidth(www);
+ if(isSelected())
+ {
+ QColorGroup cg2(cg);
+ cg2.setColor(QColorGroup::HighlightedText,cg.text());
+
+ m_pText->draw(p,afterIcon,LVI_BORDER,QRect(afterIcon,LVI_BORDER,www,height() - (LVI_BORDER * 2)),cg2);
+ } else {
+ m_pText->draw(p,afterIcon,LVI_BORDER,QRect(afterIcon,LVI_BORDER,www,height() - (LVI_BORDER * 2)),cg);
+ }
+ #endif
+}
+
+
+
+
+
+
+
+KviScriptAddonListView::KviScriptAddonListView(QWidget * pParent)
+: KviListView(pParent)
+{
+ QPixmap * p = g_pIconManager->getImage("kvi_dialog_addons.png");
+ if(p)setBackgroundOverlayPixmap(p,Qt::AlignRight | Qt::AlignBottom);
+
+ setSelectionMode(Single);
+ header()->hide();
+ int iWidth = visibleWidth();
+ if(iWidth < LVI_MINIMUM_CELL_WIDTH)iWidth = LVI_MINIMUM_CELL_WIDTH;
+ addColumn("",iWidth);
+ setSorting(0,true);
+}
+
+KviScriptAddonListView::~KviScriptAddonListView()
+{
+}
+
+void KviScriptAddonListView::resizeEvent(QResizeEvent * e)
+{
+ KviListView::resizeEvent(e);
+ int iWidth = visibleWidth();
+ if(iWidth < LVI_MINIMUM_CELL_WIDTH)iWidth = LVI_MINIMUM_CELL_WIDTH;
+ setColumnWidth(0,iWidth);
+}
+
+
+KviScriptManagementDialog::KviScriptManagementDialog(QWidget * p)
+: QDialog(p,"" /*,WType_TopLevel | WStyle_Customize | WStyle_Title | WStyle_StaysOnTop | WStyle_DialogBorder*/)
+{
+ setCaption(__tr2qs("Manage Script-Based Addons"));
+ setIcon(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_ADDONS)));
+ setModal(true);
+
+ m_pInstance = this;
+
+ QGridLayout * g = new QGridLayout(this,11,3,4,5);
+
+ /*QLabel * lb = new QLabel(this);
+ lb->setFrameStyle(QFrame::WinPanel | QFrame::Sunken);
+
+ g->addMultiCellWidget(lb,0,10,0,0);
+ QPixmap * pix = g_pIconManager->getImage("kvi_dialog_addons.png");
+ if(pix)
+ {
+ lb->setPixmap(*pix);
+ lb->setFixedWidth(pix->width());
+ }
+ lb->setBackgroundColor(Qt::black);
+ lb->setAlignment(Qt::AlignBottom | Qt::AlignRight);
+ */
+ m_pListView = new KviScriptAddonListView(this);
+ g->addMultiCellWidget(m_pListView,0,10,1,1);
+
+ m_pConfigureButton = new QPushButton(__tr2qs("Configure"),this);
+ connect(m_pConfigureButton,SIGNAL(clicked()),this,SLOT(configureScript()));
+ g->addWidget(m_pConfigureButton,0,2);
+
+ m_pHelpButton = new QPushButton(__tr2qs("Show Help"),this);
+ connect(m_pHelpButton,SIGNAL(clicked()),this,SLOT(showScriptHelp()));
+ g->addWidget(m_pHelpButton,1,2);
+
+ g->addRowSpacing(2,40);
+
+ m_pUninstallButton = new QPushButton(__tr2qs("Uninstall"),this);
+ connect(m_pUninstallButton,SIGNAL(clicked()),this,SLOT(uninstallScript()));
+ g->addWidget(m_pUninstallButton,3,2);
+
+ g->addRowSpacing(4,15);
+
+ QFrame *f = new QFrame(this);
+ f->setFrameStyle(QFrame::HLine | QFrame::Sunken);
+ g->addWidget(f,5,2);
+
+ g->addRowSpacing(6,15);
+
+ m_pInstallButton = new QPushButton(__tr2qs("Install Addon..."),this);
+ connect(m_pInstallButton,SIGNAL(clicked()),this,SLOT(installScript()));
+ g->addWidget(m_pInstallButton,7,2);
+
+ m_pGetScriptsButton = new QPushButton(__tr2qs("More Addons..."),this);
+ connect(m_pGetScriptsButton,SIGNAL(clicked()),this,SLOT(getMoreScripts()));
+ g->addWidget(m_pGetScriptsButton,8,2);
+
+ QPushButton * b = new QPushButton(__tr2qs("Close"),this);
+ connect(b,SIGNAL(clicked()),this,SLOT(closeClicked()));
+ g->addWidget(b,10,2);
+
+ g->setRowStretch(9,1);
+ g->setColStretch(1,1);
+
+ fillListView();
+
+ currentChanged(0);
+ connect(m_pListView,SIGNAL(currentChanged(KviTalListViewItem *)),this,SLOT(currentChanged(KviTalListViewItem *)));
+ //currentToolBarChanged();
+
+ if(g_rectManagementDialogGeometry.y() < 5)
+ {
+ g_rectManagementDialogGeometry.setY(5);
+ }
+ resize(g_rectManagementDialogGeometry.width(),
+ g_rectManagementDialogGeometry.height());
+ move(g_rectManagementDialogGeometry.x(),
+ g_rectManagementDialogGeometry.y());
+}
+
+KviScriptManagementDialog::~KviScriptManagementDialog()
+{
+ g_rectManagementDialogGeometry = QRect(pos().x(),pos().y(),size().width(),size().height());
+
+ //KviActionManager::instance()->customizeToolBarsDialogDestroyed();
+ m_pInstance = 0;
+}
+
+void KviScriptManagementDialog::fillListView()
+{
+ m_pListView->clear();
+ KviPointerHashTable<QString,KviKvsScriptAddon> * d = KviKvsScriptAddonManager::instance()->addonDict();
+ if(!d)return;
+ KviPointerHashTableIterator<QString,KviKvsScriptAddon> it(*d);
+ KviScriptAddonListViewItem * item;
+ while(KviKvsScriptAddon * a = it.current())
+ {
+ item = new KviScriptAddonListViewItem(m_pListView,a);
+ ++it;
+ }
+}
+
+void KviScriptManagementDialog::currentChanged(KviTalListViewItem *)
+{
+ KviScriptAddonListViewItem * it = (KviScriptAddonListViewItem *)m_pListView->currentItem();
+ if(!it)
+ {
+ m_pConfigureButton->setEnabled(false);
+ m_pUninstallButton->setEnabled(false);
+ m_pHelpButton->setEnabled(false);
+ } else {
+ m_pConfigureButton->setEnabled(!(it->addon()->configureCallbackCode().isEmpty()));
+ m_pHelpButton->setEnabled(!(it->addon()->helpCallbackCode().isEmpty()));
+ m_pUninstallButton->setEnabled(true);
+ }
+}
+
+void KviScriptManagementDialog::showScriptHelp()
+{
+ KviScriptAddonListViewItem * it = (KviScriptAddonListViewItem *)m_pListView->currentItem();
+ if(!it)return;
+ if(it->addon()->helpCallbackCode().isEmpty())return;
+ it->addon()->executeHelpCallback(g_pActiveWindow);
+}
+
+void KviScriptManagementDialog::configureScript()
+{
+ KviScriptAddonListViewItem * it = (KviScriptAddonListViewItem *)m_pListView->currentItem();
+ if(!it)return;
+ if(it->addon()->configureCallbackCode().isEmpty())return;
+ it->addon()->executeConfigureCallback(g_pActiveWindow);
+}
+
+void KviScriptManagementDialog::uninstallScript()
+{
+ KviScriptAddonListViewItem * it = (KviScriptAddonListViewItem *)m_pListView->currentItem();
+ if(!it)return;
+
+ QString txt = "<p>";
+ txt += __tr2qs("Do you really want to uninstall the addon \"%1\" ?").arg(it->addon()->visibleName());
+ txt += "</p>";
+
+ if(QMessageBox::question(this,
+ __tr2qs("Confirm addon uninstallation"),txt,__tr2qs("&Yes"),__tr2qs("&No"),0,1) != 0)return;
+
+ KviKvsScriptAddonManager::instance()->unregisterAddon(it->addon()->name(),g_pActiveWindow);
+
+ fillListView();
+ currentChanged(0);
+}
+
+void KviScriptManagementDialog::getMoreScripts()
+{
+ KviKvsScript::run("openurl http://www.kvirc.net/?id=addons&version=" KVI_VERSION "." KVI_SOURCES_DATE,g_pActiveWindow);
+}
+
+void KviScriptManagementDialog::installScript()
+{
+ QString buffer;
+
+ if(!KviFileDialog::askForOpenFileName(buffer,__tr2qs("Please select the addon installation file"),QString::null,"install.kvs",false,true))return;
+
+ buffer.replace("\\","\\\\");
+
+ QString szCmd = "parse \"";
+ szCmd += buffer;
+ szCmd += "\"";
+
+ KviKvsScript::run(szCmd,g_pActiveWindow);
+
+ fillListView();
+ currentChanged(0);
+
+ m_pListView->publicUpdateContents();
+ //m_pListView->triggerUpdate();
+}
+
+void KviScriptManagementDialog::showEvent(QShowEvent * e)
+{
+// QRect r = parentWidget() ? parentWidget()->rect() : QApplication::desktop()->rect();
+// int x = (r.width() - width()) / 2;
+// int y = (r.height() - height()) / 2;
+// move(x,y);
+}
+
+void KviScriptManagementDialog::closeClicked()
+{
+ delete this;
+}
+
+void KviScriptManagementDialog::cleanup()
+{
+ if(!m_pInstance)return;
+ delete m_pInstance;
+ m_pInstance = 0;
+}
+
+void KviScriptManagementDialog::display()
+{
+ if(m_pInstance)return;
+ m_pInstance = new KviScriptManagementDialog(g_pFrame);
+ m_pInstance->show();
+}
+
+void KviScriptManagementDialog::closeEvent(QCloseEvent * e)
+{
+ e->ignore();
+ delete this;
+}
+
diff --git a/src/modules/addon/managementdialog.h b/src/modules/addon/managementdialog.h
new file mode 100644
index 00000000..0abbb4f9
--- /dev/null
+++ b/src/modules/addon/managementdialog.h
@@ -0,0 +1,114 @@
+#ifndef _MANAGEMENTDIALOG_H_
+#define _MANAGEMENTDIALOG_H_
+//=============================================================================
+//
+// File : managementdialog.h
+// Created on Fri 08 Apr 2005 14:54:56 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include <qdialog.h>
+
+#include "kvi_listview.h"
+#include "kvi_settings.h"
+#include <qwidget.h>
+#include <qlabel.h>
+#include <qdialog.h>
+#include <qcolor.h>
+#include "kvi_tal_listview.h"
+
+class QPushButton;
+class QPixmap;
+class KviKvsScriptAddon;
+
+#ifdef COMPILE_USE_QT4
+ #include <QTextDocument>
+#else
+ #include <qsimplerichtext.h>
+#endif
+
+class KviScriptAddonListViewItem : public KviTalListViewItem
+{
+public:
+ KviScriptAddonListViewItem(KviTalListView * v,KviKvsScriptAddon * a);
+ ~KviScriptAddonListViewItem();
+protected:
+ KviKvsScriptAddon * m_pAddon;
+#ifdef COMPILE_USE_QT4
+ QTextDocument * m_pText;
+#else
+ QSimpleRichText * m_pText;
+#endif
+ QPixmap * m_pIcon;
+ KviTalListView * m_pListView;
+ QString m_szKey;
+public:
+ KviKvsScriptAddon * addon(){ return m_pAddon; };
+protected:
+ virtual QString key(int,bool) const;
+ virtual void paintCell(QPainter * p,const QColorGroup & cg,int column,int width,int align);
+ virtual void setup();
+};
+
+class KviScriptAddonListView : public KviListView
+{
+ Q_OBJECT
+public:
+ KviScriptAddonListView(QWidget * pParent);
+ ~KviScriptAddonListView();
+protected:
+ virtual void resizeEvent(QResizeEvent * e);
+};
+
+class KviScriptManagementDialog : public QDialog
+{
+ Q_OBJECT
+protected:
+ KviScriptManagementDialog(QWidget * p);
+public:
+ ~KviScriptManagementDialog();
+protected:
+ KviScriptAddonListView * m_pListView;
+ static KviScriptManagementDialog * m_pInstance;
+ QPushButton * m_pUninstallButton;
+ QPushButton * m_pConfigureButton;
+ QPushButton * m_pHelpButton;
+ QPushButton * m_pInstallButton;
+ QPushButton * m_pGetScriptsButton;
+public:
+ static KviScriptManagementDialog * instance(){ return m_pInstance; };
+ static void display();
+ static void cleanup();
+protected:
+ void fillListView();
+ virtual void showEvent(QShowEvent * e);
+ virtual void closeEvent(QCloseEvent *e);
+protected slots:
+ void currentChanged(KviTalListViewItem *i);
+ void closeClicked();
+ void showScriptHelp();
+ void configureScript();
+ void uninstallScript();
+ void getMoreScripts();
+ void installScript();
+};
+
+
+#endif //!_MANAGEMENTDIALOG_H_
diff --git a/src/modules/addon/pics/Makefile.am b/src/modules/addon/pics/Makefile.am
new file mode 100644
index 00000000..726f519d
--- /dev/null
+++ b/src/modules/addon/pics/Makefile.am
@@ -0,0 +1,9 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+tmpdir = $(picsdir)
+
+tmp_DATA= kvi_dialog_addons.png
+
+EXTRA_DIST = $(tmp_DATA)
diff --git a/src/modules/addon/pics/kvi_dialog_addons.png b/src/modules/addon/pics/kvi_dialog_addons.png
new file mode 100644
index 00000000..6cfa53d9
--- /dev/null
+++ b/src/modules/addon/pics/kvi_dialog_addons.png
Binary files differ
diff --git a/src/modules/aliaseditor/Makefile.am b/src/modules/aliaseditor/Makefile.am
new file mode 100644
index 00000000..60845dbc
--- /dev/null
+++ b/src/modules/aliaseditor/Makefile.am
@@ -0,0 +1,21 @@
+###############################################################################
+# KVirc IRC client Makealiaseditor - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkvialiaseditor.la
+
+libkvialiaseditor_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkvialiaseditor_la_SOURCES = libkvialiaseditor.cpp aliaseditor.cpp
+nodist_libkvialiaseditor_la_SOURCES = moc_aliaseditor.cpp
+
+noinst_HEADERS = aliaseditor.h
+libkvialiaseditor_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+# noinst_HEADERS=
+
+moc_aliaseditor.cpp: aliaseditor.h
+ $(SS_QT_MOC) $< -o $@
diff --git a/src/modules/aliaseditor/aliaseditor.cpp b/src/modules/aliaseditor/aliaseditor.cpp
new file mode 100644
index 00000000..3317fd3f
--- /dev/null
+++ b/src/modules/aliaseditor/aliaseditor.cpp
@@ -0,0 +1,1408 @@
+//=====================================================================================
+//
+// File : aliaseditor.cpp
+// Creation date : Mon Dec 23 2002 14:36:18 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002-2005 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the linkss of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) 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.
+//
+//=====================================================================================
+
+#include "aliaseditor.h"
+
+#include "kvi_iconmanager.h"
+#include "kvi_options.h"
+#include "kvi_locale.h"
+#include "kvi_imagedialog.h"
+#include "kvi_config.h"
+#include "kvi_filedialog.h"
+#include "kvi_fileutils.h"
+#include "kvi_scripteditor.h"
+#include "kvi_debug.h"
+#include "kvi_app.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_aliasmanager.h"
+#include "kvi_filedialog.h"
+#include "kvi_cmdformatter.h"
+#include "kvi_module.h"
+#include "kvi_valuelist.h"
+
+#include <qsplitter.h>
+#include <qlayout.h>
+#include "kvi_tal_vbox.h"
+#include <qtooltip.h>
+#include <qpushbutton.h>
+#include <qdir.h>
+#include <qmessagebox.h>
+#include <qinputdialog.h>
+#include <qregexp.h>
+
+extern KviAliasEditorWindow * g_pAliasEditorWindow;
+extern KviModule * g_pAliasEditorModule;
+
+KviAliasEditorListViewItem::KviAliasEditorListViewItem(KviTalListView * pListView,Type eType,const QString &szName)
+: KviTalListViewItem(pListView), m_eType(eType), m_pParentNamespaceItem(0)
+{
+ setName(szName);
+}
+
+KviAliasEditorListViewItem::KviAliasEditorListViewItem(KviAliasNamespaceListViewItem * pParentNamespaceItem,Type eType,const QString &szName)
+: KviTalListViewItem(pParentNamespaceItem), m_eType(eType), m_pParentNamespaceItem(pParentNamespaceItem)
+{
+ setName(szName);
+}
+
+QString KviAliasEditorListViewItem::key(int column,bool bAsc) const
+{
+ QString ret;
+ if(m_eType == Namespace)ret = "1";
+ else ret = "2";
+ ret += m_szName;
+ return ret;
+}
+
+
+void KviAliasEditorListViewItem::setName(const QString &szName)
+{
+ m_szName = szName;
+ setText(0,m_szName);
+}
+
+KviAliasListViewItem::KviAliasListViewItem(KviAliasNamespaceListViewItem * pParentNamespaceItem,const QString &szName)
+: KviAliasEditorListViewItem(pParentNamespaceItem,KviAliasEditorListViewItem::Alias,szName)
+{
+ setPixmap(0,*(g_pIconManager->getSmallIcon(KVI_SMALLICON_ALIAS)));
+ m_cPos=QPoint(0,0);
+}
+
+KviAliasListViewItem::KviAliasListViewItem(KviTalListView * pListView,const QString &szName)
+: KviAliasEditorListViewItem(pListView,KviAliasEditorListViewItem::Alias,szName)
+{
+ setPixmap(0,*(g_pIconManager->getSmallIcon(KVI_SMALLICON_ALIAS)));
+ m_cPos=QPoint(0,0);
+}
+
+
+KviAliasNamespaceListViewItem::KviAliasNamespaceListViewItem(KviTalListView * pListView,const QString &szName)
+: KviAliasEditorListViewItem(pListView,KviAliasEditorListViewItem::Namespace,szName)
+{
+ setPixmap(0,*(g_pIconManager->getSmallIcon(KVI_SMALLICON_NAMESPACE)));
+}
+
+KviAliasNamespaceListViewItem::KviAliasNamespaceListViewItem(KviAliasNamespaceListViewItem * pParentNamespaceItem,const QString &szName)
+: KviAliasEditorListViewItem(pParentNamespaceItem,KviAliasEditorListViewItem::Namespace,szName)
+{
+ setPixmap(0,*(g_pIconManager->getSmallIcon(KVI_SMALLICON_NAMESPACE)));
+}
+
+
+KviAliasNamespaceListViewItem * KviAliasNamespaceListViewItem::findNamespaceItem(const QString &szName)
+{
+ KviAliasEditorListViewItem * it = (KviAliasEditorListViewItem *)firstChild();
+ while(it)
+ {
+ if(it->isNamespace())
+ {
+ if(KviQString::equalCI(szName,it->name()))return (KviAliasNamespaceListViewItem *)it;
+ }
+ it = (KviAliasEditorListViewItem *)it->nextSibling();
+ }
+ return 0;
+}
+
+KviAliasNamespaceListViewItem * KviAliasNamespaceListViewItem::getNamespaceItem(const QString &szName)
+{
+ KviAliasNamespaceListViewItem * it = findNamespaceItem(szName);
+ if(it)return it;
+ it = new KviAliasNamespaceListViewItem(this,szName);
+ return it;
+}
+
+KviAliasListViewItem * KviAliasNamespaceListViewItem::findAliasItem(const QString &szName)
+{
+ KviAliasEditorListViewItem * it = (KviAliasEditorListViewItem *)firstChild();
+ while(it)
+ {
+ if(it->isAlias())
+ {
+ if(KviQString::equalCI(szName,it->name()))return (KviAliasListViewItem *)it;
+ }
+ it = (KviAliasEditorListViewItem *)it->nextSibling();
+ }
+ return 0;
+}
+
+KviAliasListViewItem * KviAliasNamespaceListViewItem::getAliasItem(const QString &szName)
+{
+ KviAliasListViewItem * it = findAliasItem(szName);
+ if(it)return it;
+ it = new KviAliasListViewItem(this,szName);
+ return it;
+}
+
+
+KviAliasListViewItem * KviAliasNamespaceListViewItem::createFullAliasItem(const QString &szFullName)
+{
+ QStringList lNamespaces;
+ QString szName;
+ KviAliasEditor::splitFullAliasOrNamespaceName(szFullName,lNamespaces,szName);
+
+ if(lNamespaces.isEmpty())
+ return getAliasItem(szName);
+
+ QStringList::Iterator it = lNamespaces.begin();
+
+ KviAliasNamespaceListViewItem * nit = getNamespaceItem(*it);
+ ++it;
+ while(it != lNamespaces.end())
+ {
+ nit = nit->getNamespaceItem(*it);
+ ++it;
+ }
+
+ return nit->getAliasItem(szName);
+}
+
+KviAliasNamespaceListViewItem * KviAliasNamespaceListViewItem::createFullNamespaceItem(const QString &szFullName)
+{
+ QStringList lNamespaces;
+ QString szName;
+ KviAliasEditor::splitFullAliasOrNamespaceName(szFullName,lNamespaces,szName);
+
+ if(lNamespaces.isEmpty())
+ return getNamespaceItem(szName);
+
+ QStringList::Iterator it = lNamespaces.begin();
+
+ KviAliasNamespaceListViewItem * nit = getNamespaceItem(*it);
+ ++it;
+ while(it != lNamespaces.end())
+ {
+ nit = nit->getNamespaceItem(*it);
+ ++it;
+ }
+
+ return nit->getNamespaceItem(szName);
+}
+
+
+KviAliasEditor::KviAliasEditor(QWidget * par)
+: QWidget(par)
+{
+ m_pLastEditedItem = 0;
+ m_pLastClickedItem = 0;
+ m_szDir = QDir::homeDirPath();
+
+
+ QGridLayout * l = new QGridLayout(this,1,1,2,2);
+
+#ifdef COMPILE_USE_QT4
+ m_pSplitter = new QSplitter(Qt::Horizontal,this);
+ m_pSplitter->setOpaqueResize(false);
+#else
+ m_pSplitter = new QSplitter(QSplitter::Horizontal,this);
+#endif
+
+ l->addWidget(m_pSplitter,0,0);
+
+ KviTalVBox * box = new KviTalVBox(m_pSplitter);
+ m_pListView = new KviTalListView(box);
+ m_pListView->addColumn(__tr2qs("Alias"));
+ m_pListView->setSelectionMode(KviTalListView::Extended);
+ m_pListView->setShowSortIndicator(true);
+ m_pListView->setRootIsDecorated(true);
+
+ box = new KviTalVBox(m_pSplitter);
+ KviTalHBox * hbox = new KviTalHBox(box);
+ m_pNameLabel = new QLabel(__tr2qs("No item selected"),hbox);
+ m_pRenameButton = new QPushButton(__tr2qs("Rename"),hbox);
+ m_pRenameButton->setEnabled(false);
+ connect(m_pRenameButton,SIGNAL(clicked()),this,SLOT(renameItem()));
+ hbox->setStretchFactor(m_pNameLabel,2);
+ QToolTip::add(m_pRenameButton,__tr2qs("Edit the alias or namespace name"));
+ m_pEditor = KviScriptEditor::createInstance(box);
+ m_pEditor->setFocus();
+ connect(m_pEditor,SIGNAL(find(const QString &)),this,SLOT(slotFindWord(const QString &)));
+ connect(m_pEditor,SIGNAL(replaceAll(const QString &,const QString &)),this,SLOT(slotReplaceAll(const QString &,const QString &)));
+
+ m_pContextPopup = new KviTalPopupMenu(this);
+
+ oneTimeSetup();
+
+ currentItemChanged(0);
+}
+
+KviAliasEditor::~KviAliasEditor()
+{
+ KviScriptEditor::destroyInstance(m_pEditor);
+}
+
+KviAliasNamespaceListViewItem * KviAliasEditor::findNamespaceItem(const QString &szName)
+{
+ KviAliasNamespaceListViewItem * it = (KviAliasNamespaceListViewItem *)m_pListView->firstChild();
+ while(it)
+ {
+ if(KviQString::equalCI(szName,it->name()))return it;
+ it = (KviAliasNamespaceListViewItem *)it->nextSibling();
+ }
+ return 0;
+}
+
+KviAliasNamespaceListViewItem * KviAliasEditor::getNamespaceItem(const QString &szName)
+{
+ KviAliasNamespaceListViewItem * it = findNamespaceItem(szName);
+ if(it)return it;
+ it = new KviAliasNamespaceListViewItem(m_pListView,szName);
+ return it;
+}
+
+KviAliasListViewItem * KviAliasEditor::findAliasItem(const QString &szName)
+{
+ KviAliasEditorListViewItem * it = (KviAliasEditorListViewItem *)m_pListView->firstChild();
+ while(it)
+ {
+ if(it->isAlias())
+ {
+ if(KviQString::equalCI(szName,it->name()))return (KviAliasListViewItem *)it;
+ }
+ it = (KviAliasEditorListViewItem *)it->nextSibling();
+ }
+ return 0;
+}
+
+KviAliasListViewItem * KviAliasEditor::getAliasItem(const QString &szName)
+{
+ KviAliasListViewItem * it = findAliasItem(szName);
+ if(it)return it;
+ it = new KviAliasListViewItem(m_pListView,szName);
+ return it;
+}
+
+
+void KviAliasEditor::splitFullAliasOrNamespaceName(const QString &szFullName,QStringList &lNamespaces,QString &szName)
+{
+ lNamespaces = QStringList::split("::",szFullName);
+ if(lNamespaces.count() < 1)
+ {
+ szName = "unnamed";
+ lNamespaces.append(QString(""));
+ return;
+ }
+ szName = *(lNamespaces.fromLast());
+ lNamespaces.remove(lNamespaces.fromLast());
+}
+
+QString KviAliasEditor::buildFullItemName(KviAliasEditorListViewItem * it)
+{
+ if(!it) return QString::null;
+ QString szName = it->name();
+ KviAliasNamespaceListViewItem * nit = it->parentNamespaceItem();
+ while(nit)
+ {
+ QString tmp = nit->name();
+ if(!tmp.isEmpty())
+ {
+ szName.prepend("::");
+ szName.prepend(tmp);
+ }
+ nit = nit->parentNamespaceItem();
+ }
+ return szName;
+}
+
+
+KviAliasListViewItem * KviAliasEditor::createFullAliasItem(const QString &szFullName)
+{
+ QStringList lNamespaces;
+ QString szName;
+ splitFullAliasOrNamespaceName(szFullName,lNamespaces,szName);
+
+ if(lNamespaces.isEmpty())
+ return getAliasItem(szName);
+
+ QStringList::Iterator it = lNamespaces.begin();
+
+ KviAliasNamespaceListViewItem * nit = getNamespaceItem(*it);
+ ++it;
+ while(it != lNamespaces.end())
+ {
+ nit = nit->getNamespaceItem(*it);
+ ++it;
+ }
+
+ return nit->getAliasItem(szName);
+}
+
+KviAliasNamespaceListViewItem * KviAliasEditor::createFullNamespaceItem(const QString &szFullName)
+{
+ QStringList lNamespaces;
+ QString szName;
+ splitFullAliasOrNamespaceName(szFullName,lNamespaces,szName);
+
+ if(lNamespaces.isEmpty())
+ return getNamespaceItem(szName);
+
+ QStringList::Iterator it = lNamespaces.begin();
+
+ KviAliasNamespaceListViewItem * nit = getNamespaceItem(*it);
+ ++it;
+ while(it != lNamespaces.end())
+ {
+ nit = nit->getNamespaceItem(*it);
+ ++it;
+ }
+
+ return nit->getNamespaceItem(szName);
+}
+
+void KviAliasEditor::oneTimeSetup()
+{
+ KviPointerHashTable<QString,KviKvsScript> * a = KviKvsAliasManager::instance()->aliasDict();
+ if(!a)return;
+
+ KviPointerHashTableIterator<QString,KviKvsScript> it(*a);
+
+ KviAliasListViewItem * item;
+ while(it.current())
+ {
+ KviKvsScript * alias = it.current();
+ item = createFullAliasItem(alias->name());
+ item->setBuffer(alias->code());
+ ++it;
+ }
+
+ connect(m_pListView,SIGNAL(currentChanged(KviTalListViewItem *)),this,SLOT(currentItemChanged(KviTalListViewItem *)));
+ connect(m_pListView,SIGNAL(rightButtonPressed(KviTalListViewItem *,const QPoint &,int)),
+ this,SLOT(itemPressed(KviTalListViewItem *,const QPoint &,int)));
+}
+
+bool KviAliasEditor::hasSelectedItems(KviTalListViewItem * it)
+{
+ if(!it)return false;
+ if(it->isSelected())return true;
+ if(it->isOpen())
+ {
+ if(hasSelectedItems(it->firstChild()))return true;
+ }
+ return hasSelectedItems(it->nextSibling());
+}
+
+bool KviAliasEditor::itemExists(KviTalListViewItem *pSearchFor,KviTalListViewItem * pSearchAt)
+{
+ if(!pSearchFor)return false;
+ if(!pSearchAt)return false;
+ if(pSearchFor == pSearchAt)return true;
+ if(itemExists(pSearchFor,pSearchAt->firstChild()))return true;
+ return itemExists(pSearchFor,pSearchAt->nextSibling());
+}
+
+
+void KviAliasEditor::itemPressed(KviTalListViewItem *it,const QPoint &pnt,int col)
+{
+ m_pContextPopup->clear();
+
+ m_pLastClickedItem = (KviAliasEditorListViewItem *)it;
+
+ int id;
+
+ m_pContextPopup->insertItem(
+ *(g_pIconManager->getSmallIcon(KVI_SMALLICON_ALIAS)),
+ __tr2qs("Add Alias"),
+ this,SLOT(newAlias()));
+
+ m_pContextPopup->insertItem(
+ *(g_pIconManager->getSmallIcon(KVI_SMALLICON_ALIAS)),
+ __tr2qs("Add Namespace"),
+ this,SLOT(newNamespace()));
+
+
+ bool bHasItems = m_pListView->firstChild() != 0;
+ bool bHasSelected = hasSelectedItems(m_pListView->firstChild());
+
+ m_pContextPopup->insertSeparator();
+
+ id = m_pContextPopup->insertItem(
+ *(g_pIconManager->getSmallIcon(KVI_SMALLICON_QUIT)),
+ __tr2qs("Remove Selected"),
+ this,SLOT(removeSelectedItems()));
+ m_pContextPopup->setItemEnabled(id,bHasSelected);
+
+
+ m_pContextPopup->insertSeparator();
+
+ m_pContextPopup->insertItem(
+ *(g_pIconManager->getSmallIcon(KVI_SMALLICON_FOLDER)),
+ __tr2qs("Export Selected..."),
+ this,SLOT(exportSelected()));
+ m_pContextPopup->setItemEnabled(id,bHasSelected);
+
+ m_pContextPopup->insertItem(
+ *(g_pIconManager->getSmallIcon(KVI_SMALLICON_FOLDER)),
+ __tr2qs("Export Selected in singles files..."),
+ this,SLOT(exportSelectedSepFiles()));
+
+ m_pContextPopup->setItemEnabled(id,bHasSelected);
+
+ m_pContextPopup->insertItem(
+ *(g_pIconManager->getSmallIcon(KVI_SMALLICON_FOLDER)),
+ __tr2qs("Export All..."),
+ this,SLOT(exportAll()));
+ m_pContextPopup->setItemEnabled(id,bHasItems);
+
+ m_pContextPopup->insertSeparator();
+
+ m_pContextPopup->insertItem(
+ *(g_pIconManager->getSmallIcon(KVI_SMALLICON_SEARCH)),
+ __tr2qs("Find In Aliases..."),
+ this,SLOT(slotFind()));
+ m_pContextPopup->setItemEnabled(id,bHasItems);
+
+ m_pContextPopup->insertItem(
+ *(g_pIconManager->getSmallIcon(KVI_SMALLICON_NAMESPACE)),
+ __tr2qs("Collapse All Namespaces"),
+ this,SLOT(slotCollapseNamespaces()));
+
+ m_pContextPopup->setItemEnabled(id,bHasItems);
+
+
+ m_pContextPopup->popup(pnt);
+}
+
+void KviAliasEditor::recursiveSearchReplace(const QString &szSearch,KviAliasEditorListViewItem * it,bool bReplace,const QString &szReplace)
+{
+ if(!it)return;
+ if(it->isAlias())
+ {
+ if(((KviAliasListViewItem *)it)->buffer().find(szSearch,0,false) != -1)
+ {
+ it->setPixmap(0,*(g_pIconManager->getSmallIcon(KVI_SMALLICON_ALIASHIGHLIGHTED)));
+ if (bReplace) ((QString &)((KviAliasListViewItem *)it)->buffer()).replace(szSearch,szReplace,false);
+ openParentItems(it);
+ } else
+ it->setPixmap(0,*(g_pIconManager->getSmallIcon(KVI_SMALLICON_ALIAS)));
+ } else {
+ recursiveSearchReplace(szSearch,(KviAliasEditorListViewItem *)(it->firstChild()),bReplace,szReplace);
+ }
+ recursiveSearchReplace(szSearch,(KviAliasEditorListViewItem *)(it->nextSibling()),bReplace,szReplace);
+}
+
+void KviAliasEditor::slotFind()
+{
+ g_pAliasEditorModule->lock();
+ bool bOk;
+ QString szSearch = QInputDialog::getText(
+ __tr2qs("Find In Aliases"),
+ __tr2qs("Please enter the text to be searched for. The matching aliases will be highlighted."),
+ QLineEdit::Normal,
+ "",
+ &bOk,
+ this);
+ g_pAliasEditorModule->unlock();
+ if(!bOk)return;
+ if(szSearch.isEmpty())return;
+ m_pEditor->setFindText(szSearch);
+
+ recursiveSearchReplace(szSearch,(KviAliasEditorListViewItem *)m_pListView->firstChild());
+}
+void KviAliasEditor::slotFindWord(const QString &szSearch)
+{
+ m_pEditor->setFindText(szSearch);
+
+ recursiveSearchReplace(szSearch,(KviAliasEditorListViewItem *)m_pListView->firstChild());
+
+}
+void KviAliasEditor::recursiveCollapseNamespaces(KviAliasEditorListViewItem * it)
+{
+ if(!it)return;
+ if(it->isNamespace())
+ {
+ recursiveCollapseNamespaces((KviAliasEditorListViewItem *)(it->firstChild()));
+ }
+ recursiveCollapseNamespaces((KviAliasEditorListViewItem *)(it->nextSibling()));
+ it->setOpen(false);
+}
+
+void KviAliasEditor::slotCollapseNamespaces()
+{
+ recursiveCollapseNamespaces((KviAliasEditorListViewItem *)m_pListView->firstChild());
+}
+
+
+void KviAliasEditor::slotReplaceAll(const QString &before,const QString &after)
+{
+ recursiveSearchReplace(before,(KviAliasEditorListViewItem *)m_pListView->firstChild(),true,after);
+}
+
+
+
+void KviAliasEditor::getExportAliasBuffer(QString &buffer,KviAliasListViewItem * it)
+{
+ QString szBuf = it->buffer();
+ KviCommandFormatter::blockFromBuffer(szBuf);
+ QString szNam = buildFullItemName(it);
+
+ buffer = "alias(";
+ buffer += szNam;
+ buffer += ")\n";
+ buffer += szBuf;
+ buffer += "\n";
+}
+
+
+void KviAliasEditor::exportAll()
+{
+ exportAliases(false);
+}
+
+void KviAliasEditor::exportSelectedSepFiles()
+{
+ exportAliases (true,true);
+}
+void KviAliasEditor::exportSelected()
+{
+ exportAliases(true);
+}
+
+void KviAliasEditor::exportSelectionInSinglesFiles(KviPointerList<KviAliasListViewItem> *l)
+{
+ if(!m_szDir.endsWith(QString(KVI_PATH_SEPARATOR)))m_szDir += KVI_PATH_SEPARATOR;
+ debug ("dir %s",m_szDir.latin1());
+ if (!l->first())
+ {
+ g_pAliasEditorModule->lock();
+ QMessageBox::warning(this,__tr2qs("Alias Export"),__tr2qs("There is not selection!"),__tr2qs("Ok"));
+ g_pAliasEditorModule->unlock();
+ return;
+ }
+ g_pAliasEditorModule->lock();
+
+ if(!KviFileDialog::askForDirectoryName(m_szDir,__tr2qs("Choose a Directory - KVIrc"),m_szDir)){
+ g_pAliasEditorModule->unlock();
+ return;
+ }
+
+ if(!m_szDir.endsWith(QString(KVI_PATH_SEPARATOR)))m_szDir += KVI_PATH_SEPARATOR;
+ debug ("dir changed in %s",m_szDir.latin1());
+
+ bool bReplaceAll=false;
+
+ for(KviAliasListViewItem * it = l->first();it;it = l->next())
+ {
+ QString tmp;
+ getExportAliasBuffer(tmp,it);
+ QString szFileName=buildFullItemName(it);
+ szFileName += ".kvs";
+ szFileName.replace("::","_");
+ QString szCompletePath=m_szDir+szFileName;
+
+ if (KviFileUtils::fileExists(szCompletePath) && !bReplaceAll)
+ {
+ QString szMsg;
+ KviQString::sprintf(szMsg,__tr2qs("The file \"%Q\" exists. Do you want to replace it ?"),&szFileName);
+ int ret = QMessageBox::question(this,__tr2qs("Replace file"),szMsg,__tr2qs("Yes"),__tr2qs("Yes to All"),__tr2qs("No"));
+ if (ret!=2){
+ KviFileUtils::writeFile(szCompletePath,tmp);
+ if (ret==1) bReplaceAll=true;
+ }
+
+ }
+ else
+ KviFileUtils::writeFile(szCompletePath,tmp);
+
+ }
+ g_pAliasEditorModule->unlock();
+
+}
+void KviAliasEditor::exportAliases(bool bSelectedOnly,bool bSingleFiles)
+{
+ saveLastEditedItem();
+
+ KviPointerList<KviAliasListViewItem> l;
+ l.setAutoDelete(false);
+
+ QString out;
+
+ appendAliasItems(&l,(KviAliasEditorListViewItem *)(m_pListView->firstChild()),bSelectedOnly);
+ if (bSingleFiles)
+ {
+ exportSelectionInSinglesFiles(&l);
+ return;
+
+ }
+ int count=0;
+ KviAliasListViewItem * tempitem=0;
+ for(KviAliasListViewItem * it = l.first();it;it = l.next())
+ {
+ tempitem=it;
+ count ++;
+ QString tmp;
+ getExportAliasBuffer(tmp,it);
+ out += tmp;
+ out += "\n";
+ }
+ QString szNameFile;
+ if(out.isEmpty())
+ {
+ g_pAliasEditorModule->lock();
+ QMessageBox::warning(this,__tr2qs("Alias Export"),__tr2qs("There exported file would be empty: cowardly refusing to write it"),__tr2qs("Ok"));
+ g_pAliasEditorModule->unlock();
+ return;
+ }
+
+ QString szName = m_szDir;
+
+ if(!szName.endsWith(QString(KVI_PATH_SEPARATOR)))szName += KVI_PATH_SEPARATOR;
+ QString szFile;
+ g_pAliasEditorModule->lock();
+
+ if (count==1)
+ {
+ QString tmp=buildFullItemName(tempitem);
+ szNameFile = tmp.replace("::","_");
+ }
+ else szNameFile="aliases";
+ szName += szNameFile;
+ szName += ".kvs";
+ if(!KviFileDialog::askForSaveFileName(szFile,__tr2qs("Choose a Filename - KVIrc"),szName,"*.kvs",false,true,true))
+ {
+ g_pAliasEditorModule->unlock();
+ return;
+ }
+ m_szDir=QFileInfo(szFile).dirPath(TRUE);
+ g_pAliasEditorModule->unlock();
+
+ if(!KviFileUtils::writeFile(szFile,out))
+ {
+ g_pAliasEditorModule->lock();
+ QMessageBox::warning(this,__tr2qs("Write Failed - KVIrc"),__tr2qs("Unable to write to the alias file."),__tr2qs("Ok"));
+ g_pAliasEditorModule->unlock();
+ }
+}
+
+void KviAliasEditor::saveProperties(KviConfig *cfg)
+{
+ cfg->writeEntry("Sizes",m_pSplitter->sizes());
+ QString szName;
+ if(m_pLastEditedItem)
+ szName = buildFullItemName(m_pLastEditedItem);
+ cfg->writeEntry("LastAlias",szName);
+}
+
+void KviAliasEditor::loadProperties(KviConfig *cfg)
+{
+ KviValueList<int> def;
+ def.append(20);
+ def.append(80);
+ m_pSplitter->setSizes(cfg->readIntListEntry("Sizes",def));
+ QString tmp = cfg->readEntry("LastAlias",QString::null);
+
+ KviAliasEditorListViewItem * it = findAliasItem(tmp);
+ if(!it)it = findNamespaceItem(tmp);
+ if(it)activateItem(it);
+}
+
+void KviAliasEditor::appendAliasItems(KviPointerList<KviAliasListViewItem> * l,KviAliasEditorListViewItem * pStartFrom,bool bSelectedOnly)
+{
+ if(!pStartFrom)return;
+ if(pStartFrom->isAlias())
+ {
+ if(bSelectedOnly)
+ {
+ if(pStartFrom->isSelected())
+ l->append((KviAliasListViewItem *)pStartFrom);
+ } else {
+ l->append((KviAliasListViewItem *)pStartFrom);
+ }
+ } else {
+ if(bSelectedOnly)
+ {
+ if(pStartFrom->isSelected())
+ appendAliasItems(l,(KviAliasEditorListViewItem *)(pStartFrom->firstChild()),false); // ALL the items below the selected namespace
+ else
+ appendAliasItems(l,(KviAliasEditorListViewItem *)(pStartFrom->firstChild()),true); // only the selected items below
+ } else {
+ appendAliasItems(l,(KviAliasEditorListViewItem *)(pStartFrom->firstChild()),false);
+ }
+ }
+ appendAliasItems(l,(KviAliasEditorListViewItem *)(pStartFrom->nextSibling()),bSelectedOnly);
+}
+
+void KviAliasEditor::appendNamespaceItems(KviPointerList<KviAliasListViewItem> * l,KviAliasEditorListViewItem * pStartFrom,bool bSelectedOnly)
+{
+ if(!pStartFrom)return;
+ if(pStartFrom->isNamespace())
+ {
+ if(bSelectedOnly)
+ {
+ if(pStartFrom->isSelected())
+ l->append((KviAliasListViewItem *)pStartFrom);
+ } else {
+ l->append((KviAliasListViewItem *)pStartFrom);
+ }
+ } else {
+ if(bSelectedOnly)
+ {
+ if(pStartFrom->isSelected())
+ appendNamespaceItems(l,(KviAliasEditorListViewItem *)(pStartFrom->firstChild()),false); // ALL the items below the selected namespace
+ else
+ appendNamespaceItems(l,(KviAliasEditorListViewItem *)(pStartFrom->firstChild()),true); // only the selected items below
+ } else {
+ appendNamespaceItems(l,(KviAliasEditorListViewItem *)(pStartFrom->firstChild()),false);
+ }
+ }
+ appendNamespaceItems(l,(KviAliasEditorListViewItem *)(pStartFrom->nextSibling()),bSelectedOnly);
+}
+
+void KviAliasEditor::appendSelectedItems(KviPointerList<KviAliasEditorListViewItem> * l,KviAliasEditorListViewItem * pStartFrom,bool bIncludeChildrenOfSelected)
+{
+ if(!pStartFrom)return;
+ if(pStartFrom->isSelected())
+ {
+ l->append(pStartFrom);
+ if(bIncludeChildrenOfSelected)
+ appendSelectedItems(l,(KviAliasEditorListViewItem *)(pStartFrom->firstChild()),bIncludeChildrenOfSelected);
+ } else {
+ appendSelectedItems(l,(KviAliasEditorListViewItem *)(pStartFrom->firstChild()),bIncludeChildrenOfSelected);
+ }
+ appendSelectedItems(l,(KviAliasEditorListViewItem *)(pStartFrom->nextSibling()),bIncludeChildrenOfSelected);
+}
+
+bool KviAliasEditor::removeItem(KviAliasEditorListViewItem *it,bool * pbYesToAll,bool bDeleteEmptyTree)
+{
+ if(!it)return true;
+ QString szMsg;
+ QString szName = it->name();
+
+ if(!*pbYesToAll)
+ {
+ if(it->isAlias())
+ KviQString::sprintf(szMsg,__tr2qs("Do you really want to remove the alias \"%Q\" ?"),&szName);
+ else {
+ KviQString::sprintf(szMsg,__tr2qs("Do you really want to remove the namespace \"%Q\" ?"),&szName);
+ szMsg += "<br>";
+ szMsg += __tr2qs("Please note that all the children items will be deleted too.");
+ }
+
+ g_pAliasEditorModule->lock();
+ int ret = QMessageBox::question(this,__tr2qs("Remove item"),szMsg,__tr2qs("Yes"),__tr2qs("Yes to All"),__tr2qs("No"));
+ g_pAliasEditorModule->unlock();
+ switch(ret)
+ {
+ case 0:
+ // nothing
+ break;
+ case 1:
+ *pbYesToAll = true;
+ break;
+ default:
+ return false;
+ break;
+ }
+ }
+
+ if(it == m_pLastEditedItem)
+ m_pLastEditedItem = 0;
+ if(it == m_pLastClickedItem)
+ m_pLastClickedItem = 0;
+ if(bDeleteEmptyTree)
+ {
+ while(it)
+ {
+ KviAliasEditorListViewItem * par = (KviAliasEditorListViewItem *)(it->parent());
+ delete it;
+ if(par)
+ {
+ if(!par->firstChild())it = par;
+ else it = 0;
+ } else {
+ it = 0;
+ }
+ }
+ } else {
+ delete it;
+ }
+ return true;
+}
+
+void KviAliasEditor::removeSelectedItems()
+{
+ KviPointerList<KviAliasEditorListViewItem> l;
+ l.setAutoDelete(false);
+ appendSelectedItems(&l,(KviAliasEditorListViewItem *)(m_pListView->firstChild()),false);
+
+ bool bYesToAll = false;
+
+ for(KviAliasEditorListViewItem *it = l.first();it;it = l.next())
+ {
+ if(!removeItem(it,&bYesToAll,false))return;
+ }
+}
+
+QString KviAliasEditor::askForAliasName(const QString &szAction,const QString &szText,const QString &szInitialText)
+{
+ bool bOk = false;
+ QString szNewName;
+ while(szNewName.isEmpty())
+ {
+ g_pAliasEditorModule->lock();
+ szNewName = QInputDialog::getText(
+ szAction,
+ szText,
+ QLineEdit::Normal,
+ szInitialText,
+ &bOk,
+ this);
+ g_pAliasEditorModule->unlock();
+ if(!bOk)return QString::null;
+ if(szNewName.isEmpty())
+ {
+ g_pAliasEditorModule->lock();
+ QMessageBox::warning(this,
+ __tr2qs("Missing Alias Name"),
+ __tr2qs("You must specify a valid name for the alias"),
+ __tr2qs("Ok, Let me try again..."));
+ g_pAliasEditorModule->unlock();
+ continue;
+ }
+
+ // we allow only [\w:]+
+ QRegExp re("[\\w:]+");
+ if(!re.exactMatch(szNewName))
+ {
+ g_pAliasEditorModule->lock();
+ QMessageBox::information(this,
+ __tr2qs("Bad Alias Name"),
+ __tr2qs("Alias names can contain only letters, digits, underscores and '::' namespace separators"),
+ __tr2qs("Ok, Let me try again..."));
+ g_pAliasEditorModule->unlock();
+ szNewName = "";
+ continue;
+ }
+ // make sure that we have only doubled "::" and not ":" or ":::..."
+ QString tmp = szNewName;
+ tmp.replace("::","@"); // @ is not allowed by the rule above
+ if(tmp.find(":") != -1)
+ {
+ g_pAliasEditorModule->lock();
+ QMessageBox::information(this,
+ __tr2qs("Bad Alias Name"),
+ __tr2qs("Stray ':' character in alias name: did you mean ...<namespace>::<name> ?"),
+ __tr2qs("Ok, Let me try again..."));
+ g_pAliasEditorModule->unlock();
+ szNewName = "";
+ continue;
+ }
+ if(tmp.find("@@") != -1)
+ {
+ g_pAliasEditorModule->lock();
+ QMessageBox::information(this,
+ __tr2qs("Bad Alias Name"),
+ __tr2qs("Found an empty namespace in alias name"),
+ __tr2qs("Ok, Let me try again..."));
+ g_pAliasEditorModule->unlock();
+ szNewName = "";
+ continue;
+ }
+ }
+ return szNewName;
+}
+
+QString KviAliasEditor::askForNamespaceName(const QString &szAction,const QString &szText,const QString &szInitialText)
+{
+ bool bOk = false;
+ QString szNewName;
+ while(szNewName.isEmpty())
+ {
+ g_pAliasEditorModule->lock();
+ szNewName = QInputDialog::getText(
+ szAction,
+ szText,
+ QLineEdit::Normal,
+ szInitialText,
+ &bOk,
+ this);
+ g_pAliasEditorModule->unlock();
+ if(!bOk)return QString::null;
+ if(szNewName.isEmpty())
+ {
+ g_pAliasEditorModule->lock();
+ QMessageBox::warning(this,
+ __tr2qs("Missing Namespace Name"),
+ __tr2qs("You must specify a valid name for the namespace"),
+ __tr2qs("Ok, Let me try again..."));
+ g_pAliasEditorModule->unlock();
+ continue;
+ }
+
+ // we allow only [\w:]+
+ QRegExp re("[\\w:]+");
+ if(!re.exactMatch(szNewName))
+ {
+ g_pAliasEditorModule->lock();
+ QMessageBox::information(this,
+ __tr2qs("Bad Namespace Name"),
+ __tr2qs("Namespace names can contain only letters, digits, underscores and '::' namespace separators"),
+ __tr2qs("Ok, Let me try again..."));
+ g_pAliasEditorModule->unlock();
+ szNewName = "";
+ continue;
+ }
+ // make sure that we have only doubled "::" and not ":" or ":::..."
+ QString tmp = szNewName;
+ tmp.replace("::","@"); // @ is not allowed by the rule above
+ if(tmp.find(":") != -1)
+ {
+ g_pAliasEditorModule->lock();
+ QMessageBox::information(this,
+ __tr2qs("Bad Namespace Name"),
+ __tr2qs("Stray ':' character in namespace name: did you mean ...<namespace>::<name> ?"),
+ __tr2qs("Ok, Let me try again..."));
+ g_pAliasEditorModule->unlock();
+ szNewName = "";
+ continue;
+ }
+ if(tmp.find("@@") != -1)
+ {
+ g_pAliasEditorModule->lock();
+ QMessageBox::information(this,
+ __tr2qs("Bad Namespace Name"),
+ __tr2qs("Found an empty namespace in namespace name"),
+ __tr2qs("Ok, Let me try again..."));
+ g_pAliasEditorModule->unlock();
+ szNewName = "";
+ continue;
+ }
+ }
+ return szNewName;
+}
+
+void KviAliasEditor::openParentItems(KviTalListViewItem * it)
+{
+ if(it->parent())
+ {
+ it->parent()->setOpen(true);
+ openParentItems(it->parent());
+ }
+}
+
+
+void KviAliasEditor::selectOneItem(KviTalListViewItem * it,KviTalListViewItem *pStartFrom)
+{
+ if(!pStartFrom)return;
+ if(pStartFrom == it)pStartFrom->setSelected(true);
+ else pStartFrom->setSelected(false);
+ selectOneItem(it,pStartFrom->firstChild());
+ selectOneItem(it,pStartFrom->nextSibling());
+}
+
+
+void KviAliasEditor::activateItem(KviTalListViewItem * it)
+{
+ openParentItems(it);
+ selectOneItem(it,m_pListView->firstChild());
+ m_pListView->setCurrentItem(it);
+}
+
+
+void KviAliasEditor::newAlias()
+{
+ if(m_pLastClickedItem)
+ {
+ if(!itemExists(m_pLastClickedItem,m_pListView->firstChild()))return; // dead ?
+ if(m_pLastClickedItem->isAlias())
+ m_pLastClickedItem = m_pLastClickedItem->parentNamespaceItem();
+ }
+
+ QString szNewName = askForAliasName(__tr2qs("Add Alias"),__tr2qs("Please enter the name for the new alias"),"myfunction");
+ if(szNewName.isEmpty())return;
+
+ getUniqueItemName(m_pLastClickedItem,szNewName,KviAliasEditorListViewItem::Alias);
+
+ KviAliasListViewItem * it;
+
+ if(m_pLastClickedItem)
+ it = ((KviAliasNamespaceListViewItem *)m_pLastClickedItem)->createFullAliasItem(szNewName);
+ else
+ it = createFullAliasItem(szNewName);
+
+ activateItem(it);
+}
+
+void KviAliasEditor::newNamespace()
+{
+ if(m_pLastClickedItem)
+ {
+ if(!itemExists(m_pLastClickedItem,m_pListView->firstChild()))return; // dead ?
+ if(m_pLastClickedItem->isAlias())
+ m_pLastClickedItem = m_pLastClickedItem->parentNamespaceItem();
+ }
+
+
+ QString szNewName = askForNamespaceName(__tr2qs("Add Namespace"),__tr2qs("Please enter the name for the new namespace"),"mynamespace");
+ if(szNewName.isEmpty())return;
+
+ getUniqueItemName(m_pLastClickedItem,szNewName,KviAliasEditorListViewItem::Namespace);
+
+ KviAliasNamespaceListViewItem * it;
+
+ if(m_pLastClickedItem)
+ it = ((KviAliasNamespaceListViewItem *)m_pLastClickedItem)->createFullNamespaceItem(szNewName);
+ else
+ it = createFullNamespaceItem(szNewName);
+
+ activateItem(it);
+}
+
+bool KviAliasEditor::aliasExists(QString &szFullItemName)
+{
+ KviPointerList<KviAliasListViewItem> l;
+ l.setAutoDelete(false);
+
+ appendAliasItems(&l,(KviAliasEditorListViewItem *)(m_pListView->firstChild()),false);
+ for(KviAliasListViewItem * it = l.first();it;it = l.next())
+ {
+ if (KviQString::equalCI(buildFullItemName(it),szFullItemName))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool KviAliasEditor::namespaceExists(QString &szFullItemName)
+{
+ KviPointerList<KviAliasListViewItem> l;
+ l.setAutoDelete(false);
+
+ appendNamespaceItems(&l,(KviAliasEditorListViewItem *)(m_pListView->firstChild()),false);
+ for(KviAliasListViewItem * it = l.first();it;it = l.next())
+ {
+ if (KviQString::equalCI(buildFullItemName(it),szFullItemName))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+void KviAliasEditor::renameItem()
+{
+ if(!m_pLastEditedItem)return;
+ if(!itemExists(m_pLastEditedItem,m_pListView->firstChild()))return; // dead ?
+
+ QString szName = buildFullItemName(m_pLastEditedItem);
+ QString szNewName;
+
+ bool bAlias = m_pLastEditedItem->isAlias();
+
+ if(bAlias)
+ szNewName = askForAliasName(__tr2qs("Rename Alias"),__tr2qs("Please enter the new name for the alias"),szName);
+ else
+ szNewName = askForNamespaceName(__tr2qs("Rename Namespace"),__tr2qs("Please enter the new name for the namespace"),szName);
+ if(szNewName.isEmpty())return;
+
+ if(szName == szNewName)return;
+
+ // check if there is already an alias with this name
+ if (bAlias)
+ {
+ if (aliasExists(szNewName))
+ {
+ g_pAliasEditorModule->lock();
+ QMessageBox::information(this,
+ __tr2qs("Alias already exists"),
+ __tr2qs("This name is already in use. Please choose another one."),
+ __tr2qs("Ok, Let me try again..."));
+ g_pAliasEditorModule->unlock();
+ return;
+ }
+ } else {
+ // check if there is already a anmespace with this name
+ if (namespaceExists(szNewName))
+ {
+ g_pAliasEditorModule->lock();
+ QMessageBox::information(this,
+ __tr2qs("Namespace already exists"),
+ __tr2qs("This name is already in use. Please choose another one."),
+ __tr2qs("Ok, let me try again..."));
+ g_pAliasEditorModule->unlock();
+ return;
+ }
+ }
+
+ QString szCode;
+ QPoint pntCursor;
+ if(bAlias)
+ {
+ m_pEditor->getText(szCode);
+ pntCursor = m_pEditor->getCursor();
+ }
+
+ // take child items, if any
+ KviPointerList<KviTalListViewItem> lChildren;
+ lChildren.setAutoDelete(false);
+ KviTalListViewItem * it = m_pLastEditedItem->firstChild();
+ while(it)
+ {
+ lChildren.append(it);
+ it = it->nextSibling();
+ }
+ for(it = lChildren.first();it;it = lChildren.next())
+ m_pLastEditedItem->takeItem(it);
+
+ bool bYesToAll = true;
+ removeItem(m_pLastEditedItem,&bYesToAll,true);
+
+ m_pLastEditedItem = 0; // make sure it's true (but it already should be because of removeItem())
+ m_pLastClickedItem = 0; // make sure it's true (but it already should be because of removeItem())
+
+ if(bAlias)
+ {
+ KviAliasListViewItem * ait = createFullAliasItem(szNewName);
+ ait->setBuffer(szCode);
+ ait->setCursorPosition(pntCursor);
+ activateItem(ait);
+
+ for(it = lChildren.first();it;it = lChildren.next())
+ ait->insertItem(it);
+ } else {
+ KviAliasNamespaceListViewItem * nit = createFullNamespaceItem(szNewName);
+ activateItem(nit);
+
+ for(it = lChildren.first();it;it = lChildren.next())
+ {
+ ((KviAliasEditorListViewItem*)it)->setParentNamespaceItem(nit);
+ nit->insertItem(it);
+ }
+ }
+}
+
+// warning: this saves ONLY the body, not the name!
+// the name is changed explicitly with renameItem(), when needed
+void KviAliasEditor::saveLastEditedItem()
+{
+ if(!m_pLastEditedItem)return;
+ if(!m_pEditor->isModified())return; // nothing to save
+ if(!itemExists(m_pLastEditedItem,m_pListView->firstChild()))return; // dead ?
+
+ if(m_pLastEditedItem->isNamespace())return;
+
+ QString newCode;
+ m_pEditor->getText(newCode);
+ ((KviAliasListViewItem *)m_pLastEditedItem)->setBuffer(newCode);
+ ((KviAliasListViewItem *)m_pLastEditedItem)->setCursorPosition(m_pEditor->getCursor());
+}
+
+void KviAliasEditor::currentItemChanged(KviTalListViewItem *it)
+{
+ saveLastEditedItem();
+
+ m_pLastEditedItem = (KviAliasEditorListViewItem *)it;
+
+ if(!m_pLastEditedItem)
+ {
+ m_pNameLabel->setText(__tr2qs("No item selected"));
+ m_pRenameButton->setEnabled(false);
+ m_pEditor->setText("");
+ m_pEditor->setEnabled(false);
+ return;
+ }
+
+ QString szNam = buildFullItemName(m_pLastEditedItem);
+ if(m_pLastEditedItem->isNamespace())
+ {
+ QString szLabelText = __tr2qs("Namespace");
+ szLabelText += ": <b>";
+ szLabelText += szNam;
+ szLabelText += "</b>";
+ m_pNameLabel->setText(szLabelText);
+ m_pRenameButton->setEnabled(true);
+ m_pEditor->setText("");
+ m_pEditor->setEnabled(false);
+ return;
+ }
+
+ QString szLabelText = __tr2qs("Alias");
+ szLabelText += ": <b>";
+ szLabelText += szNam;
+ szLabelText += "</b>";
+ m_pNameLabel->setText(szLabelText);
+ m_pRenameButton->setEnabled(true);
+ m_pEditor->setText(((KviAliasListViewItem *)it)->buffer());
+ m_pEditor->setCursorPosition(((KviAliasListViewItem *)it)->cursorPosition());
+ m_pEditor->setEnabled(true);
+}
+
+void KviAliasEditor::recursiveCommit(KviAliasEditorListViewItem * it)
+{
+ if(!it)return;
+ if(it->isAlias())
+ {
+ QString szName = buildFullItemName(it);
+ //debug("ADDING %s",szName.latin1());
+ // WARNING: On MSVC operator new here is valid ONLY because
+ // KviKvsScript has a non virtual detructor!
+ KviKvsScript * a = new KviKvsScript(szName,((KviAliasListViewItem *)it)->buffer());
+ KviKvsAliasManager::instance()->add(szName,a);
+ } else {
+ recursiveCommit((KviAliasEditorListViewItem *)(it->firstChild()));
+ }
+ recursiveCommit((KviAliasEditorListViewItem *)(it->nextSibling()));
+}
+
+
+void KviAliasEditor::commit()
+{
+ saveLastEditedItem();
+ KviKvsAliasManager::instance()->clear();
+
+ recursiveCommit((KviAliasEditorListViewItem *)(m_pListView->firstChild()));
+
+ g_pApp->saveAliases();
+}
+
+
+void KviAliasEditor::getUniqueItemName(KviAliasEditorListViewItem *item,QString &buffer,KviAliasEditorListViewItem::Type eType)
+{
+ QString ret;
+
+ int idx = 0;
+ KviAliasEditorListViewItem * found;
+
+ for(;;)
+ {
+ ret = buffer;
+ if(idx > 0)
+ {
+ QString tmp;
+ tmp.setNum(idx);
+ ret.append(tmp);
+ }
+
+ if(item)
+ {
+ if(!item->isNamespace())
+ {
+ buffer = ret;
+ return;
+ }
+
+ if(eType == KviAliasEditorListViewItem::Namespace)
+ found = ((KviAliasNamespaceListViewItem *)item)->findNamespaceItem(ret);
+ else
+ found = ((KviAliasNamespaceListViewItem *)item)->findAliasItem(ret);
+ } else {
+ if(eType == KviAliasEditorListViewItem::Namespace)
+ found = findNamespaceItem(ret);
+ else
+ found = findAliasItem(ret);
+ }
+
+ if(!found)
+ {
+ buffer = ret;
+ return;
+ }
+
+ idx++;
+ }
+}
+
+
+
+
+KviAliasEditorWindow::KviAliasEditorWindow(KviFrame * lpFrm)
+: KviWindow(KVI_WINDOW_TYPE_SCRIPTEDITOR,lpFrm,"aliaseditor",0)
+{
+ g_pAliasEditorWindow = this;
+
+ setFixedCaption(__tr2qs("Alias Editor"));
+
+ m_pEditor = new KviAliasEditor(this);
+
+ m_pBase = new QWidget(this);
+ QGridLayout * g = new QGridLayout(m_pBase,1,4,4,4);
+
+ QPushButton * btn = new QPushButton(__tr2qs("&OK"),m_pBase);
+ connect(btn,SIGNAL(clicked()),this,SLOT(okClicked()));
+ btn->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_ACCEPT)));
+ g->addWidget(btn,0,1);
+
+ btn = new QPushButton(__tr2qs("&Apply"),m_pBase);
+ connect(btn,SIGNAL(clicked()),this,SLOT(applyClicked()));
+ btn->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_ACCEPT)));
+ g->addWidget(btn,0,2);
+
+ btn = new QPushButton(__tr2qs("Cancel"),m_pBase);
+ connect(btn,SIGNAL(clicked()),this,SLOT(cancelClicked()));
+ btn->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_DISCARD)));
+ g->addWidget(btn,0,3);
+
+ g->setColStretch(0,1);
+}
+
+KviAliasEditorWindow::~KviAliasEditorWindow()
+{
+ g_pAliasEditorWindow = 0;
+}
+
+void KviAliasEditorWindow::okClicked()
+{
+ m_pEditor->commit();
+ close();
+}
+
+void KviAliasEditorWindow::applyClicked()
+{
+ m_pEditor->commit();
+}
+
+void KviAliasEditorWindow::cancelClicked()
+{
+ close();
+}
+
+
+QPixmap * KviAliasEditorWindow::myIconPtr()
+{
+ return g_pIconManager->getSmallIcon(KVI_SMALLICON_ALIAS);
+}
+
+void KviAliasEditorWindow::resizeEvent(QResizeEvent *e)
+{
+ int hght = m_pBase->sizeHint().height();
+ m_pEditor->setGeometry(0,0,width(),height()- hght);
+ m_pBase->setGeometry(0,height() - hght,width(),hght);
+}
+
+
+void KviAliasEditorWindow::getConfigGroupName(KviStr &szName)
+{
+ szName = "aliaseditor";
+}
+
+
+void KviAliasEditorWindow::saveProperties(KviConfig *cfg)
+{
+ m_pEditor->saveProperties(cfg);
+}
+
+
+
+void KviAliasEditorWindow::loadProperties(KviConfig *cfg)
+{
+ m_pEditor->loadProperties(cfg);
+}
diff --git a/src/modules/aliaseditor/aliaseditor.h b/src/modules/aliaseditor/aliaseditor.h
new file mode 100644
index 00000000..fa49fc96
--- /dev/null
+++ b/src/modules/aliaseditor/aliaseditor.h
@@ -0,0 +1,197 @@
+#ifndef _ALIASEDITOR_H_
+#define _ALIASEDITOR_H_
+//=====================================================================================
+//
+// File : aliaseditor.h
+// Creation date : Mon Dec 23 2002 14:35:55 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002-2005 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the linkss of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) 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.
+//
+//=====================================================================================
+
+#include "kvi_window.h"
+#include "kvi_string.h"
+#include "kvi_pointerlist.h"
+
+
+#include <qwidget.h>
+#include "kvi_tal_listview.h"
+#include <qlineedit.h>
+#include "kvi_tal_popupmenu.h"
+#include <qstringlist.h>
+#include <qpushbutton.h>
+#include <qlabel.h>
+
+class KviScriptEditor;
+class KviAliasNamespaceListViewItem;
+
+
+class KviAliasEditorListViewItem : public KviTalListViewItem
+{
+public:
+ enum Type { Alias, Namespace };
+public:
+ KviAliasEditorListViewItem(KviTalListView * pListView,Type eType,const QString &szName);
+ KviAliasEditorListViewItem(KviAliasNamespaceListViewItem * pParentNamespaceItem,Type eType,const QString &szName);
+ ~KviAliasEditorListViewItem(){};
+protected:
+ Type m_eType;
+ KviAliasNamespaceListViewItem * m_pParentNamespaceItem;
+ QString m_szName;
+public:
+ const QString & name(){ return m_szName; };
+ void setName(const QString &szName);
+ Type type(){ return m_eType; };
+ bool isAlias(){ return m_eType == Alias; };
+ bool isNamespace(){ return m_eType == Namespace; };
+ void setParentNamespaceItem(KviAliasNamespaceListViewItem* it){ m_pParentNamespaceItem=it; };
+ KviAliasNamespaceListViewItem * parentNamespaceItem(){ return m_pParentNamespaceItem; };
+ virtual QString key(int column,bool bAsc) const;
+};
+
+class KviAliasListViewItem;
+
+class KviAliasNamespaceListViewItem : public KviAliasEditorListViewItem
+{
+public:
+ KviAliasNamespaceListViewItem(KviTalListView * pListView,const QString &szName);
+ KviAliasNamespaceListViewItem(KviAliasNamespaceListViewItem * pParentNamespace,const QString &szName);
+ ~KviAliasNamespaceListViewItem(){};
+public:
+ KviAliasNamespaceListViewItem * findNamespaceItem(const QString &szName);
+ KviAliasNamespaceListViewItem * getNamespaceItem(const QString &szName);
+ KviAliasListViewItem * findAliasItem(const QString &szName);
+ KviAliasListViewItem * getAliasItem(const QString &szName);
+ KviAliasListViewItem * createFullAliasItem(const QString &szFullName);
+ KviAliasNamespaceListViewItem * createFullNamespaceItem(const QString &szFullName);
+};
+
+
+class KviAliasListViewItem : public KviAliasEditorListViewItem
+{
+public:
+ KviAliasListViewItem(KviAliasNamespaceListViewItem * pParentNamespace,const QString &szName);
+ KviAliasListViewItem(KviTalListView *pListView,const QString &szName);
+ ~KviAliasListViewItem(){};
+public:
+ QString m_szBuffer;
+ QPoint m_cPos;
+public:
+ const QString & buffer(){ return m_szBuffer; };
+ const QPoint & cursorPosition(){ return m_cPos; };
+ void setBuffer(const QString &szBuffer){ m_szBuffer = szBuffer; };
+ void setCursorPosition(const QPoint &cPos){ m_cPos = cPos; };
+};
+
+class QSplitter;
+
+class KviAliasEditor : public QWidget
+{
+ Q_OBJECT
+public:
+ KviAliasEditor(QWidget * par);
+ ~KviAliasEditor();
+public:
+ KviScriptEditor * m_pEditor;
+ KviTalListView * m_pListView;
+ QLabel * m_pNameLabel;
+ QPushButton * m_pRenameButton;
+ KviAliasEditorListViewItem * m_pLastEditedItem;
+ KviAliasEditorListViewItem * m_pLastClickedItem;
+ //KviAliasListViewItem * m_pLastEditedItem;
+ KviTalPopupMenu * m_pContextPopup;
+ QSplitter * m_pSplitter;
+ QString m_szDir;
+public:
+ //bool modified(){ return m_bModified; };
+ void commit();
+ void exportAliases(bool,bool=false);
+ void exportSelectionInSinglesFiles(KviPointerList<KviAliasListViewItem> *l);
+
+ void saveProperties(KviConfig *);
+ void loadProperties(KviConfig *);
+ static void splitFullAliasOrNamespaceName(const QString &szFullName,QStringList &lNamespaces,QString &szName);
+protected slots:
+ void currentItemChanged(KviTalListViewItem *it);
+ void newAlias();
+ void newNamespace();
+ void exportAll();
+ void exportSelectedSepFiles();
+ void exportSelected();
+ void removeSelectedItems();
+ void itemPressed(KviTalListViewItem *it,const QPoint &pnt,int col);
+ void renameItem();
+ void slotFind();
+ void slotCollapseNamespaces();
+ void slotFindWord(const QString &);
+ void slotReplaceAll(const QString &before,const QString &after);
+protected:
+// QString const & findWord(const QString &txt,bool);
+ void recursiveCollapseNamespaces(KviAliasEditorListViewItem * it);
+ void recursiveSearchReplace(const QString &szSearch,KviAliasEditorListViewItem * it,bool bReplace=false,const QString &szReplace="n");
+
+ void recursiveCommit(KviAliasEditorListViewItem * it);
+ void getExportAliasBuffer(QString &buffer,KviAliasListViewItem * it);
+ void oneTimeSetup();
+ void selectOneItem(KviTalListViewItem * it,KviTalListViewItem *pStartFrom);
+ void saveLastEditedItem();
+ void getUniqueItemName(KviAliasEditorListViewItem *item,QString &buffer,KviAliasEditorListViewItem::Type eType);
+ void appendSelectedItems(KviPointerList<KviAliasEditorListViewItem> * l,KviAliasEditorListViewItem * pStartFrom,bool bIncludeChildrenOfSelected = false);
+ void appendAliasItems(KviPointerList<KviAliasListViewItem> * l,KviAliasEditorListViewItem * pStartFrom,bool bSelectedOnly);
+ void appendNamespaceItems(KviPointerList<KviAliasListViewItem> * l,KviAliasEditorListViewItem * pStartFrom,bool bSelectedOnly);
+ bool removeItem(KviAliasEditorListViewItem *it,bool * pbYesToAll,bool bDeleteEmptyTree);
+ void openParentItems(KviTalListViewItem * it);
+ void activateItem(KviTalListViewItem * it);
+ QString askForAliasName(const QString &szAction,const QString &szText,const QString &szInitialText);
+ QString askForNamespaceName(const QString &szAction,const QString &szText,const QString &szInitialText);
+ bool itemExists(KviTalListViewItem *pSearchFor,KviTalListViewItem * pSearchAt);
+ bool namespaceExists(QString &szFullItemName);
+ bool aliasExists(QString &szFullItemName);
+ bool hasSelectedItems(KviTalListViewItem * it);
+ KviAliasNamespaceListViewItem * findNamespaceItem(const QString &szName);
+ KviAliasNamespaceListViewItem * getNamespaceItem(const QString &szName);
+ KviAliasListViewItem * findAliasItem(const QString &szName);
+ KviAliasListViewItem * getAliasItem(const QString &szName);
+ KviAliasListViewItem * createFullAliasItem(const QString &szFullName);
+ KviAliasNamespaceListViewItem * createFullNamespaceItem(const QString &szFullName);
+ QString buildFullItemName(KviAliasEditorListViewItem * it);
+};
+
+
+class KviAliasEditorWindow : public KviWindow
+{
+ Q_OBJECT
+public:
+ KviAliasEditorWindow(KviFrame * lpFrm);
+ ~KviAliasEditorWindow();
+protected:
+ KviAliasEditor * m_pEditor;
+ QWidget * m_pBase;
+protected:
+ virtual QPixmap * myIconPtr();
+ virtual void resizeEvent(QResizeEvent *e);
+ virtual void getConfigGroupName(KviStr &szName);
+ virtual void saveProperties(KviConfig *);
+ virtual void loadProperties(KviConfig *);
+protected slots:
+ void cancelClicked();
+ void okClicked();
+ void applyClicked();
+};
+
+#endif //_ALIASEDITOR_H_
diff --git a/src/modules/aliaseditor/libkvialiaseditor.cpp b/src/modules/aliaseditor/libkvialiaseditor.cpp
new file mode 100644
index 00000000..079197c7
--- /dev/null
+++ b/src/modules/aliaseditor/libkvialiaseditor.cpp
@@ -0,0 +1,90 @@
+//==========================================================================================
+//
+// File : libkvialiaseditor.cpp
+// Creation date : Mon 23 Dec 2002 14:30:59 2002 GMT by Szymon Stefanek
+//
+// This toolbar is part of the KVirc irc client distribution
+// Copyright (C) 2002-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//==========================================================================================
+
+#include "kvi_module.h"
+#include "kvi_locale.h"
+#include "kvi_frame.h"
+
+#include "aliaseditor.h"
+KviAliasEditorWindow * g_pAliasEditorWindow = 0;
+KviModule * g_pAliasEditorModule = 0;
+
+
+/*
+ @doc: aliaseditor.open
+ @type:
+ command
+ @title:
+ aliaseditor.open
+ @short:
+ Shows the alias editor
+ @syntax:
+ aliaseditor.open
+ @description:
+ Opens the script alias editor dialog.
+*/
+
+static bool aliaseditor_kvs_cmd_open(KviKvsModuleCommandCall * c)
+{
+ if(!g_pAliasEditorWindow)
+ {
+ g_pAliasEditorWindow = new KviAliasEditorWindow(c->window()->frame());
+ c->window()->frame()->addWindow(g_pAliasEditorWindow);
+ }
+
+ g_pAliasEditorWindow->setFocus();
+
+ return true;
+}
+
+static bool aliaseditor_module_init(KviModule * m)
+{
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"open",aliaseditor_kvs_cmd_open);
+ g_pAliasEditorWindow = 0;
+ g_pAliasEditorModule = m;
+ return true;
+}
+
+static bool aliaseditor_module_can_unload(KviModule * m)
+{
+ return (g_pAliasEditorWindow == 0);
+}
+
+static bool aliaseditor_module_cleanup(KviModule *m)
+{
+ if(g_pAliasEditorWindow)delete g_pAliasEditorWindow;
+ g_pAliasEditorWindow = 0;
+ return true;
+}
+
+KVIRC_MODULE(
+ "AliasEditor", // module name
+ "2.0.0", // module version
+ "Copyright (C) 2002-2005 Szymon Stefanek (pragma at kvirc dot net)", // author & (C)
+ "Editor for the script aliases",
+ aliaseditor_module_init,
+ aliaseditor_module_can_unload,
+ 0,
+ aliaseditor_module_cleanup
+)
diff --git a/src/modules/avatar/Makefile.am b/src/modules/avatar/Makefile.am
new file mode 100644
index 00000000..8e8a793a
--- /dev/null
+++ b/src/modules/avatar/Makefile.am
@@ -0,0 +1,20 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkviavatar.la
+
+libkviavatar_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkviavatar_la_SOURCES = libkviavatar.cpp
+nodist_libkviavatar_la_SOURCES = moc_libkviavatar.cpp
+
+libkviavatar_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+noinst_HEADERS = libkviavatar.h
+
+moc_%.cpp: %.h
+ $(SS_QT_MOC) $< -o $@
diff --git a/src/modules/avatar/libkviavatar.cpp b/src/modules/avatar/libkviavatar.cpp
new file mode 100644
index 00000000..e97b1f67
--- /dev/null
+++ b/src/modules/avatar/libkviavatar.cpp
@@ -0,0 +1,585 @@
+//=============================================================================
+//
+// File : libkviavatar.cpp
+// Creation date : Thu Nov 12 02:32:59 2004 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "libkviavatar.h"
+
+#include "kvi_module.h"
+#include "kvi_fileutils.h"
+#include "kvi_locale.h"
+#include "kvi_malloc.h"
+#include "kvi_app.h"
+#include "kvi_options.h"
+#include "kvi_http.h"
+#include "kvi_iconmanager.h"
+#include "kvi_avatar.h"
+#include "kvi_ircuserdb.h"
+
+#include "kvi_ircconnection.h"
+#include "kvi_ircconnectionuserinfo.h"
+#include "kvi_console.h"
+#include "kvi_filedialog.h"
+#include "kvi_pointerlist.h"
+#include "kvi_frame.h"
+#include "kvi_sharedfiles.h"
+#include "kvi_out.h"
+#include "kvi_ircmask.h"
+#include "kvi_qcstring.h"
+
+#include <qlineedit.h>
+#include <qpushbutton.h>
+#include <qmessagebox.h>
+#include <qtimer.h>
+#include <qlabel.h>
+#include "kvi_tal_hbox.h"
+#include <qlayout.h>
+
+static KviPointerList<KviAsyncAvatarSelectionDialog> * g_pAvatarSelectionDialogList = 0;
+extern KVIRC_API KviSharedFilesManager * g_pSharedFilesManager;
+
+KviAsyncAvatarSelectionDialog::KviAsyncAvatarSelectionDialog(QWidget * par,const QString &szInitialPath,KviIrcConnection * c)
+: QDialog(par,0,false,Qt::WType_Dialog | Qt::WStyle_DialogBorder | Qt::WStyle_StaysOnTop)
+{
+ g_pAvatarSelectionDialogList->append(this);
+
+ m_pConnection = c;
+
+ setCaption(__tr2qs("Choose Avatar - KVIrc"));
+
+ QGridLayout * g = new QGridLayout(this,3,3,4,8);
+
+ QString msg = "<center>";
+ msg += __tr2qs("Please select an avatar image. " \
+ "The full path to a local file or an image on the Web can be used.<br>" \
+ "If you wish to use a local image file, click the \"<b>Browse</b>\"" \
+ "button to browse local folders.<br>" \
+ "The full URL for an image (including <b>http://</b>) can be entered manually.");
+ msg += "</center><br>";
+
+ QLabel * l = new QLabel(msg,this);
+ l->setMinimumWidth(250);
+
+ g->addMultiCellWidget(l,0,0,0,2);
+
+ m_pLineEdit = new QLineEdit(this);
+ m_pLineEdit->setText(szInitialPath);
+ m_pLineEdit->setMinimumWidth(180);
+
+ g->addMultiCellWidget(m_pLineEdit,1,1,0,1);
+
+ QPushButton * b = new QPushButton(__tr2qs("&Browse..."),this);
+ connect(b,SIGNAL(clicked()),this,SLOT(chooseFileClicked()));
+ g->addWidget(b,1,2);
+ KviTalHBox * h = new KviTalHBox(this);h->setSpacing(8);g->addMultiCellWidget(h,2,2,1,2);
+ b = new QPushButton(__tr2qs("&OK"),h);
+ b->setMinimumWidth(80);
+ b->setDefault(true);
+ connect(b,SIGNAL(clicked()),this,SLOT(okClicked()));
+
+ b = new QPushButton(__tr2qs("Cancel"),h);
+ b->setMinimumWidth(80);
+ connect(b,SIGNAL(clicked()),this,SLOT(cancelClicked()));
+
+ g->setRowStretch(0,1);
+ g->setColStretch(0,1);
+}
+
+KviAsyncAvatarSelectionDialog::~KviAsyncAvatarSelectionDialog()
+{
+ g_pAvatarSelectionDialogList->removeRef(this);
+}
+
+void KviAsyncAvatarSelectionDialog::okClicked()
+{
+ m_szAvatarName = m_pLineEdit->text();
+
+ if(!g_pApp->connectionExists(m_pConnection))return; // the connection no longer exists :/
+
+ if(!m_szAvatarName.isEmpty())
+ {
+ QString tmp = m_szAvatarName;
+ tmp.replace("\\","\\\\");
+ QString szBuffer=QString("avatar.set \"%1\"").arg(tmp);
+ KviKvsScript::run(szBuffer,m_pConnection->console());
+ }
+
+ accept();
+ deleteLater();
+}
+
+void KviAsyncAvatarSelectionDialog::cancelClicked()
+{
+ reject();
+ deleteLater();
+}
+
+void KviAsyncAvatarSelectionDialog::chooseFileClicked()
+{
+ QString tmp;
+ if(KviFileDialog::askForOpenFileName(tmp,__tr2qs("Choose an Image File - KVIrc")))
+ {
+ m_pLineEdit->setText(tmp);
+ }
+}
+
+void KviAsyncAvatarSelectionDialog::closeEvent(QCloseEvent * e)
+{
+ e->ignore();
+ reject();
+ deleteLater();
+}
+
+/*
+ @doc: avatar.set
+ @type:
+ command
+ @title:
+ avatar.set
+ @keyterms:
+ setting your avatar, avatar
+ @short:
+ Sets the local user's avatar
+ @syntax:
+ avatar.set [avatar:string]
+ @description:
+ Sets your avatar in the current connection to <avatar>.
+ <avatar> may be a local filename or a http url.[br]
+ If avatar is an empty string then an asynchronous dialog
+ will be opened that will allow choosing an avatar.[br]
+ Note that this command does NOT notify the avatar to
+ any target: use [cmd]avatar.notify[/cmd] for that purpose.
+ Note also that this will NOT set your default avatar
+ option: you must use the options dialog for that.[br]
+ @examples:
+ [example]
+ avatar.set /home/myavatar.png
+ avatar.set http://www.kvirc.net/img/pragma.png
+ [/example]
+ @seealso:
+ [cmd]avatar.unset[/cmd]
+*/
+
+static bool avatar_kvs_cmd_set(KviKvsModuleCommandCall * c)
+{
+ QString szAvatar;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("avatar",KVS_PT_NONEMPTYSTRING,KVS_PF_OPTIONAL,szAvatar)
+ KVSM_PARAMETERS_END(c)
+
+ KVSM_REQUIRE_CONNECTION(c)
+
+ QString absPath;
+
+ if(szAvatar.isEmpty())
+ {
+ KviAsyncAvatarSelectionDialog * d = new KviAsyncAvatarSelectionDialog(g_pFrame,QString::null,c->window()->connection());
+ d->show();
+ return true;
+ }
+
+ // new avatar specified...try to load it
+
+ KviIrcUserEntry * e = c->window()->connection()->userDataBase()->find(c->window()->connection()->currentNickName());
+ if(!e)
+ {
+ c->warning(__tr2qs("Internal error: I'm not in the user database ?"));
+ return true;
+ }
+
+ KviAvatar * av = g_pIconManager->getAvatar(QString::null,szAvatar);
+ if(av)
+ {
+ // Ok...got it...
+ e->setAvatar(av);
+ c->window()->console()->avatarChanged(av,
+ c->window()->connection()->userInfo()->nickName(),
+ c->window()->connection()->userInfo()->userName(),
+ c->window()->connection()->userInfo()->hostName(),
+ QString::null);
+ } else {
+ bool bIsUrl = KviQString::equalCIN(szAvatar,"http://",7) && (szAvatar.length() > 7);
+
+ if(bIsUrl)
+ {
+ // This is an url, and we don't have a cached copy for now
+ QString szLocalFilePath;
+ QString szLocalFile = szAvatar;
+ g_pIconManager->urlToCachedFileName(szLocalFile);
+ g_pApp->getLocalKvircDirectory(szLocalFilePath,KviApp::Avatars,szLocalFile);
+
+ szLocalFilePath.replace("\\","\\\\");
+
+ QString szCommand = "http.get -w=nm ";
+ szCommand += szAvatar;
+ szCommand += " ";
+ szCommand += szLocalFilePath;
+
+ if(KviKvsScript::run(szCommand,c->window()->console()))
+ {
+ g_pApp->setAvatarOnFileReceived(c->window()->console(),
+ szAvatar,
+ c->window()->connection()->userInfo()->nickName(),
+ c->window()->connection()->userInfo()->userName(),
+ c->window()->connection()->userInfo()->hostName());
+ } else {
+ c->warning(__tr2qs("Can't set the current avatar to '%Q': failed to start the http transfer"),&szAvatar);
+ return true;
+ }
+ } else {
+ c->warning(__tr2qs("Can't set the current avatar to '%Q': can't load the image"),&szAvatar);
+ return true;
+ }
+ }
+
+ return true;
+}
+
+
+/*
+ @doc: avatar.unset
+ @type:
+ command
+ @title:
+ avatar.unset
+ @short:
+ Unsets the local user's avatar
+ @syntax:
+ avatar.unset
+ @description:
+ Unsets the local user's avatar.
+ Note also that this will NOT unset your default avatar
+ option: you must use the options dialog for that.[br]
+ @seealso:
+ [cmd]avatar.set[/cmd]
+*/
+
+static bool avatar_kvs_cmd_unset(KviKvsModuleCommandCall * c)
+{
+ KVSM_REQUIRE_CONNECTION(c)
+
+ KviIrcUserEntry * e = c->window()->connection()->userDataBase()->find(c->window()->connection()->currentNickName());
+ if(!e)
+ {
+ c->warning(__tr2qs("Internal error: I'm not in the user database ?"));
+ return true;
+ }
+
+ e->setAvatar(0);
+ c->window()->console()->avatarChanged(0,
+ c->window()->connection()->userInfo()->nickName(),
+ c->window()->connection()->userInfo()->userName(),
+ c->window()->connection()->userInfo()->hostName(),
+ QString::null);
+
+ return true;
+}
+
+/*
+ @doc: avatar.notify
+ @type:
+ command
+ @title:
+ avatar.notify
+ @short:
+ Notifies the current avatar to a remote target
+ @syntax:
+ avatar.notify [-q] [-t=<timeout:integer>] <target:string>
+ @switches:
+ !sw: -q | --quiet
+ Do not print warnings
+ !sw: -t=<timeout> | --timeout=<integer>
+ @description:
+ Notifies the current avatar to the remote <target> via CTCP AVATAR.
+ See the [doc:ctcp_avatar]avatar protocol documentation[/doc] for the
+ description of the protocol.[br]
+ This has the effect to notify your avatar image to the <target>.[br]
+ The CTCP is sent thru a NOTICE and the current avatar image
+ is added to the public offer list for <timeout> seconds (or a default timeout if the -t switch is not used).[br]
+ If the -q switch is specified, the command executes in quet mode and
+ prints nothing in the current window.[br]
+ If you don't have an avatar set, the ctcp will unset the previous avatar
+ on the target side.[br]
+ [b]Warning:[/b] The implementation of the avatar protocol is actually
+ restricted to KVIrc clients only. In the future other clients may implement it.[br]
+ This command is [doc:connection_dependant_commands]connection dependant[/doc].[br]
+ @examples:
+ [example]
+ [comment]# Notify your current avatar to Pragma[/comment]
+ avatar.notify Pragma
+ [comment]# Notify your avatar to the channel #kvirc and to Pragma[/comment]
+ avatar #kvirc,Pragma
+ [/example]
+ @seealso:
+ [cmd]avatar.set[/cmd], [cmd]avatar.unset[/cmd]
+*/
+
+static bool avatar_kvs_cmd_notify(KviKvsModuleCommandCall * c)
+{
+ QString szTarget;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("target",KVS_PT_NONEMPTYSTRING,0,szTarget)
+ KVSM_PARAMETERS_END(c)
+
+ KVSM_REQUIRE_CONNECTION(c)
+
+ kvs_int_t iTimeout = (kvs_int_t)KVI_OPTION_UINT(KviOption_uintAvatarOfferTimeoutInSecs);
+ if(KviKvsVariant * pTimeout = c->switches()->find('t',"timeout"))
+ {
+ if(!pTimeout->asInteger(iTimeout))
+ {
+ if(!c->switches()->find('q',"quiet"))
+ c->warning(__tr2qs("Invalid timeout specified, using default"));
+ }
+ }
+
+ KviIrcUserEntry * e = c->window()->connection()->userDataBase()->find(c->window()->connection()->currentNickName());
+ if(!e)
+ {
+ c->warning(__tr2qs("Internal error: I'm not in the user database ?"));
+ return true;
+ }
+
+ QString absPath,avatar;
+
+ if(e->avatar())
+ {
+ absPath = e->avatar()->localPath();
+ avatar = e->avatar()->name();
+ }
+
+ KviSharedFile * o = 0;
+ if((!absPath.isEmpty()) && (!avatar.isEmpty()))
+ {
+ bool bTargetIsChan = (szTarget.contains('#') || szTarget.contains('&') || szTarget.contains('!'));
+ if(bTargetIsChan)o = g_pSharedFilesManager->lookupSharedFile(avatar,0);
+ else {
+ KviIrcMask u(szTarget);
+ o = g_pSharedFilesManager->lookupSharedFile(avatar,&u);
+ }
+ if(!o)
+ {
+ // FIXME: #warning "OPTION FOR PERMANENT OR TIMEDOUT OFFER...TIMEDOUT WOULD ALSO NEED TO EXTEND EXISTING OFFERS LIFETIME"
+ QString szUserMask = bTargetIsChan ? QString("*") : szTarget;
+ szUserMask += "!*@*";
+ o = g_pSharedFilesManager->addSharedFile(avatar,absPath,szUserMask,iTimeout);
+ if(!o)
+ {
+ // Don't delete o...it has been already deleted by g_pFileTrader
+ if(!c->switches()->find('q',"quiet"))
+ c->warning(__tr2qs("Can't add a file offer for file %Q (huh ? file not readable ?)"),&absPath);
+ return true;
+ }
+
+ if(_OUTPUT_VERBOSE)
+ {
+ if(!c->switches()->find('q',"quiet"))
+ c->window()->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Added %d secs file offer for file %Q (%Q) and receiver %Q"),
+ iTimeout,&(o->absFilePath()),&avatar,&(o->userMask()));
+ }
+ }
+ }
+
+ if(!c->switches()->find('q',"quiet"))
+ c->window()->output(KVI_OUT_AVATAR,__tr2qs("Notifying avatar '%Q' to %Q"),&avatar,&szTarget);
+
+ KviQCString encodedTarget = c->window()->connection()->encodeText(szTarget);
+
+ if(!avatar.isEmpty())
+ {
+ KviQCString encodedAvatar = c->window()->connection()->encodeText(avatar);
+
+ if(o)
+ {
+ c->window()->connection()->sendFmtData("NOTICE %s :%cAVATAR %s %u%c",encodedTarget.data(),0x01,
+ encodedAvatar.data(),o->fileSize(),0x01);
+ } else {
+ c->window()->connection()->sendFmtData("NOTICE %s :%cAVATAR %s%c",encodedTarget.data(),0x01,
+ encodedAvatar.data(),0x01);
+ }
+ } else {
+ c->window()->connection()->sendFmtData("NOTICE %s :%cAVATAR%c",encodedTarget.data(),0x01,0x01);
+ }
+
+ return true;
+}
+
+/*
+ @doc: avatar.name
+ @type:
+ function
+ @title:
+ $avatar.name
+ @short:
+ Returns the avatar name for the specified user
+ @syntax:
+ <string> $avatar.name
+ <string> $avatar.name(<nick:string>)
+ @description:
+ Returns the name of the avatar belonging to <nick> in the current IRC context.
+ If <nick> is omitted then the name of the avatar of the current local user
+ is returned. The returned string is empty if the specified user has no
+ avatar set or there is no such user at all.
+ @seealso:
+ [fnc]$avatar.path[/fnc]
+*/
+
+static bool avatar_kvs_fnc_name(KviKvsModuleFunctionCall * c)
+{
+ QString szNick;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("nick",KVS_PT_STRING,KVS_PF_OPTIONAL,szNick)
+ KVSM_PARAMETERS_END(c)
+
+ KVSM_REQUIRE_CONNECTION(c)
+
+ if(szNick.isEmpty())szNick = c->window()->connection()->currentNickName();
+
+ KviIrcUserEntry * e = c->window()->connection()->userDataBase()->find(szNick);
+ if(e)
+ {
+ if(e->avatar())
+ {
+ c->returnValue()->setString(e->avatar()->name());
+ return true;
+ }
+ }
+ c->returnValue()->setNothing();
+ return true;
+}
+
+/*
+ @doc: avatar.path
+ @type:
+ function
+ @title:
+ $avatar.path
+ @short:
+ Returns the avatar path for the specified user
+ @syntax:
+ <string> $avatar.path
+ <string> $avatar.path(<nick:string>)
+ @description:
+ Returns the local path of the avatar belonging to <nick> in the current IRC context.
+ If <nick> is omitted then the path of the avatar of the current local user
+ is returned. The returned string is empty if the specified user has no
+ avatar set or there is no such user at all.
+ @seealso:
+ [fnc]$avatar.name[/fnc]
+*/
+
+static bool avatar_kvs_fnc_path(KviKvsModuleFunctionCall * c)
+{
+ QString szNick;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("path",KVS_PT_STRING,KVS_PF_OPTIONAL,szNick)
+ KVSM_PARAMETERS_END(c)
+
+ KVSM_REQUIRE_CONNECTION(c)
+
+ if(szNick.isEmpty())szNick = c->window()->connection()->currentNickName();
+
+ KviIrcUserEntry * e = c->window()->connection()->userDataBase()->find(szNick);
+ if(e)
+ {
+ if(e->avatar())
+ {
+ c->returnValue()->setString(e->avatar()->localPath());
+ return true;
+ }
+ }
+ c->returnValue()->setNothing();
+ return true;
+}
+
+/*
+ @doc: avatar.query
+ @type:
+ command
+ @title:
+ avatar.query
+ @short:
+ Queries the avatar of a remote target
+ @syntax:
+ avatar.query <target:string>
+ @description:
+ Queries the avatar of a remote target via CTCP AVATAR.
+ The <target> can be a channel or a nickname.
+ This command is equivalent to "[cmd]ctcp[/cmd] <target> AVATAR".
+ @seealso:
+ [cmd]avatar.set[/cmd]
+*/
+
+static bool avatar_kvs_cmd_query(KviKvsModuleCommandCall * c)
+{
+ QString szName;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("target",KVS_PT_NONEMPTYSTRING,0,szName)
+ KVSM_PARAMETERS_END(c)
+
+ KVSM_REQUIRE_CONNECTION(c)
+
+ KviQCString target = c->window()->connection()->encodeText(szName);
+ c->window()->connection()->sendFmtData("PRIVMSG %s :%cAVATAR%c",target.data(),0x01,0x01);
+
+ return true;
+}
+
+static bool avatar_module_init(KviModule * m)
+{
+ g_pAvatarSelectionDialogList = new KviPointerList<KviAsyncAvatarSelectionDialog>;
+ g_pAvatarSelectionDialogList->setAutoDelete(false);
+
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"query",avatar_kvs_cmd_query);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"set",avatar_kvs_cmd_set);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"unset",avatar_kvs_cmd_set);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"notify",avatar_kvs_cmd_notify);
+
+ KVSM_REGISTER_FUNCTION(m,"name",avatar_kvs_fnc_name);
+ KVSM_REGISTER_FUNCTION(m,"path",avatar_kvs_fnc_path);
+
+ return true;
+}
+
+static bool avatar_module_can_unload(KviModule *m)
+{
+ return g_pAvatarSelectionDialogList->isEmpty();
+}
+
+static bool avatar_module_cleanup(KviModule *m)
+{
+ while(KviAsyncAvatarSelectionDialog * d = g_pAvatarSelectionDialogList->first())
+ delete d;
+ delete g_pAvatarSelectionDialogList;
+ return true;
+}
+
+KVIRC_MODULE(
+ "Avatar",
+ "1.0.0",
+ "Copyright (C) 2004 Szymon Stefanek (pragma at kvirc dot net)",
+ "Avatar manipulation routines",
+ avatar_module_init,
+ avatar_module_can_unload,
+ 0,
+ avatar_module_cleanup
+)
diff --git a/src/modules/avatar/libkviavatar.h b/src/modules/avatar/libkviavatar.h
new file mode 100644
index 00000000..d30b4233
--- /dev/null
+++ b/src/modules/avatar/libkviavatar.h
@@ -0,0 +1,54 @@
+#ifndef _LIBKVIAVATAR_H_
+#define _LIBKVIAVATAR_H_
+//=============================================================================
+//
+// File : libkviavatar.cpp
+// Creation date : Thu Nov 12 02:32:59 2004 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include <qdialog.h>
+
+class QLineEdit;
+class KviIrcConnection;
+
+class KviAsyncAvatarSelectionDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ KviAsyncAvatarSelectionDialog(QWidget * par,const QString &szInitialPath,KviIrcConnection * c);
+ ~KviAsyncAvatarSelectionDialog();
+protected:
+ QLineEdit * m_pLineEdit;
+ QString m_szAvatarName;
+ KviIrcConnection * m_pConnection;
+protected:
+ virtual void closeEvent(QCloseEvent * e);
+ const QString &avatarName(){ return m_szAvatarName; };
+protected slots:
+ void okClicked();
+ void cancelClicked();
+ void chooseFileClicked();
+};
+
+
+#endif //!_LIBKVIAVATAR_H_
diff --git a/src/modules/chan/Makefile.am b/src/modules/chan/Makefile.am
new file mode 100644
index 00000000..620836ac
--- /dev/null
+++ b/src/modules/chan/Makefile.am
@@ -0,0 +1,18 @@
+###############################################################################
+# KVirc IRC client Makefile - 31.01.2002 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkvichan.la
+
+libkvichan_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkvichan_la_SOURCES = libkvichan.cpp
+libkvichan_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+# noinst_HEADERS=
+
+%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
diff --git a/src/modules/chan/libkvichan.cpp b/src/modules/chan/libkvichan.cpp
new file mode 100644
index 00000000..99f8e38e
--- /dev/null
+++ b/src/modules/chan/libkvichan.cpp
@@ -0,0 +1,1635 @@
+//=============================================================================
+//
+// File : libkvichan.cpp
+// Creation date : Sun Feb 02 2002 05:27:11 GMT by Szymon Stefanek
+//
+// This chan is part of the KVirc irc client distribution
+// Copyright (C) 2002-2005 Szymon Stefanek (pragma@kvirc.net)
+// Copyright (C) 2002-2004 Juanjo Alvarez (juanjux@yahoo.es)
+//
+// 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_module.h"
+#include "kvi_string.h"
+#include "kvi_app.h"
+#include "kvi_channel.h"
+#include "kvi_locale.h"
+#include "kvi_topicw.h"
+#include "kvi_ircmask.h"
+#include "kvi_maskeditor.h"
+#include "kvi_ircurl.h"
+#include "kvi_ircconnectiontarget.h"
+#include "kvi_ircconnection.h"
+
+static KviChannel * chan_kvs_find_channel(KviKvsModuleFunctionCall * c,QString &szChan,bool noWarnings=false)
+{
+ if(szChan.isEmpty())
+ {
+ if(c->window()->type() == KVI_WINDOW_TYPE_CHANNEL)return (KviChannel *)(c->window());
+ if(c->window()->type() == KVI_WINDOW_TYPE_DEADCHANNEL)return (KviChannel *)(c->window());
+ if(!noWarnings) c->warning(__tr2qs("The current window is not a channel"));
+ } else {
+ KviWindow * w = g_pApp->findWindow(szChan);
+ if(!w)
+ {
+ if(!noWarnings) c->warning(__tr2qs("Can't find the window with id '%Q'"),&szChan);
+ return 0;
+ }
+ if(w->type() == KVI_WINDOW_TYPE_CHANNEL)return (KviChannel *)w;
+ if(!noWarnings) c->warning(__tr2qs("The specified window (%Q) is not a channel"),&szChan);
+ }
+ return 0;
+}
+
+/*
+ @doc: chan.name
+ @type:
+ function
+ @title:
+ $chan.name
+ @short:
+ Returns the name of a channel
+ @syntax:
+ <string> $chan.name
+ <string> $chan.name(<window_id:string>)
+ @description:
+ The first form returns the name of the current channel (assuming that the current window
+ is a channel at all). If the current window is not a channel, a warning is printed
+ and an empty string is returned.[br]
+ The second form returns the name of the channel specified by <window_id>.[br]
+ This function works also on dead channels.[br]
+*/
+
+static bool chan_kvs_fnc_name(KviKvsModuleFunctionCall * c)
+{
+ QString szId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("window id",KVS_PT_STRING,KVS_PF_OPTIONAL,szId)
+ KVSM_PARAMETERS_END(c)
+ KviChannel * ch = chan_kvs_find_channel(c,szId);
+ if (ch) {
+ c->returnValue()->setString(ch->windowName());
+ }
+ return true;
+}
+
+/*
+ @doc: chan.getUrl
+ @type:
+ function
+ @title:
+ $chan.getUrl
+ @short:
+ Returns the URL of a channel
+ @syntax:
+ <string> $chan.getUrl
+ <string> $chan.getUrl(<window_id:string>)
+ <string> $chan.getUrl(<channel_name:string>)
+ @description:
+ Returns IRC URL for this channel
+*/
+
+static bool chan_kvs_fnc_getUrl(KviKvsModuleFunctionCall * c)
+{
+ QString szId,url;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("channel id",KVS_PT_STRING,KVS_PF_OPTIONAL,szId)
+ KVSM_PARAMETERS_END(c)
+ KviChannel * ch = chan_kvs_find_channel(c,szId,true);
+ if (ch) {
+ KviIrcUrl::join(url,ch->connection()->target()->server());
+ url.append(ch->windowName());
+ if(ch->hasChannelKey())
+ {
+ url.append('?');
+ url.append(ch->channelKey());
+ }
+ } else {
+ if(c->window()->connection()) {
+ KviIrcUrl::join(url,c->window()->connection()->target()->server());
+ url.append(szId);
+ } else {
+ c->error("There is no active IRC connection for current context");
+ }
+ }
+ c->returnValue()->setString(url);
+ return true;
+}
+
+/*
+ @doc: chan.isDead
+ @type:
+ function
+ @title:
+ $chan.isDead
+ @short:
+ Checks if a channel is dead
+ @syntax:
+ <boolean> $chan.isDead
+ <boolean> $chan.isDead(<window_id:string>)
+ @description:
+ Returns 1 if the channel specified by <window_id> is a dead channel and 0 otherwise.[br]
+ The form without parameters works on the current window.[br]
+*/
+
+static bool chan_kvs_fnc_isdead(KviKvsModuleFunctionCall * c)
+{
+ QString szId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("window id",KVS_PT_STRING,KVS_PF_OPTIONAL,szId)
+ KVSM_PARAMETERS_END(c)
+ KviChannel * ch = chan_kvs_find_channel(c,szId);
+ if (ch) c->returnValue()->setBoolean((ch->type() == KVI_WINDOW_TYPE_DEADCHANNEL));
+ return true;
+}
+
+/*
+ @doc: chan.topic
+ @type:
+ function
+ @title:
+ $chan.topic
+ @short:
+ Returns the topic of a channel
+ @syntax:
+ <string> $chan.topic
+ <string> $chan.topic(<window_id:string>)
+ @description:
+ The first form returns the topic of the current channel (assuming that the current window
+ is a channel at all). If the current window is not a channel, a warning is printed
+ and an empty string is returned.[br]
+ The second form returns the topic of the channel specified by <window_id>.[br]
+ The topic is returned as it is known form at the call time: this means that
+ if the channel is not synchronized with the server (as just after the join, for example)
+ you might get an empty string (the topic is not yet known).[br]
+ This function works also on dead channels altough the topic returned is the last
+ topic seen while the channel wasn't dead.[br]
+*/
+
+static bool chan_kvs_fnc_topic(KviKvsModuleFunctionCall * c)
+{
+ QString szId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("window id",KVS_PT_STRING,KVS_PF_OPTIONAL,szId)
+ KVSM_PARAMETERS_END(c)
+ KviChannel * ch = chan_kvs_find_channel(c,szId);
+ if (ch) c->returnValue()->setString(ch->topicWidget()->topic());
+ return true;
+}
+
+/*
+ @doc: chan.topicsetby
+ @type:
+ function
+ @title:
+ $chan.topicsetby
+ @short:
+ Returns the author of the topic of a channel
+ @syntax:
+ <string> $chan.topicsetby
+ <string> $chan.topicsetby(<window_id:string>)
+ @description:
+ The first form returns the author of the topic of the current channel (assuming that the current window
+ is a channel at all). If the current window is not a channel, a warning is printed
+ and an empty string is returned.[br]
+ The second form returns the author of the topic of the channel specified by <window_id>.[br]
+ The topic author nickname is returned if it is known form at the call time: this means that
+ if the channel is not synchronized with the server (as just after the join, for example)
+ you might get an empty string (the topic is not yet known).[br]
+ This function works also on dead channels altough the information returned is the last
+ information seen while the channel wasn't dead.[br]
+*/
+
+static bool chan_kvs_fnc_topicsetby(KviKvsModuleFunctionCall * c)
+{
+ QString szId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("window id",KVS_PT_STRING,KVS_PF_OPTIONAL,szId)
+ KVSM_PARAMETERS_END(c)
+ KviChannel * ch = chan_kvs_find_channel(c,szId);
+ if (ch) c->returnValue()->setString(ch->topicWidget()->topicSetBy());
+ return true;
+}
+
+/*
+ @doc: chan.topicsetat
+ @type:
+ function
+ @title:
+ $chan.topicsetat
+ @short:
+ Returns the set time of the topic of a channel
+ @syntax:
+ <string> $chan.topicsetat
+ <string> $chan.topicsetat(<window_id:string>)
+ @description:
+ The first form returns the set time of the topic of the current channel (assuming that the current window
+ is a channel at all). If the current window is not a channel, a warning is printed
+ and an empty string is returned.[br]
+ The second form returns the set time of the topic of the channel specified by <window_id>.[br]
+ The topic set time is returned if it is known form at the call time: this means that
+ if the channel is not synchronized with the server (as just after the join, for example)
+ you might get an empty string (the topic is not yet known).[br]
+ This function works also on dead channels altough the information returned is the last
+ information seen while the channel wasn't dead.[br]
+*/
+
+static bool chan_kvs_fnc_topicsetat(KviKvsModuleFunctionCall * c)
+{
+ QString szId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("window id",KVS_PT_STRING,KVS_PF_OPTIONAL,szId)
+ KVSM_PARAMETERS_END(c)
+ KviChannel * ch = chan_kvs_find_channel(c,szId);
+ if (ch) c->returnValue()->setString(ch->topicWidget()->topicSetAt());
+ return true;
+}
+/*
+ @doc: chan.usercount
+ @type:
+ function
+ @title:
+ $chan.usercount
+ @short:
+ Returns the number of users on a channel
+ @syntax:
+ <intger> $chan.usercount
+ <integer> $chan.usercount(<window_id:string>)
+ @description:
+ The first form returns the number of users on the current channel (assuming that the current window
+ is a channel at all). If the current window is not a channel, a warning is printed
+ and an empty string is returned.[br]
+ The second form returns the number of users on the channel specified by <window_id>.[br]
+ The number of users is returned if it is known form at the call time: this means that
+ if the channel is not synchronized with the server (as just after the join, for example)
+ you might get a number that is actually smaller.[br]
+*/
+
+static bool chan_kvs_fnc_usercount(KviKvsModuleFunctionCall * c)
+{
+ QString szId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("window id",KVS_PT_STRING,KVS_PF_OPTIONAL,szId)
+ KVSM_PARAMETERS_END(c)
+ KviChannel * ch = chan_kvs_find_channel(c,szId);
+ if (ch) c->returnValue()->setInteger(ch->count());
+ return true;
+}
+
+/*
+ @doc: chan.ownercount
+ @type:
+ function
+ @title:
+ $chan.ownercount
+ @short:
+ Returns the number of channel owner users on a channel
+ @syntax:
+ <integer> $chan.ownercount
+ <integer> $chan.ownercount(<window_id:integer>)
+ @description:
+ The first form returns the number of owners users on the current channel (assuming that the current window
+ is a channel at all). If the current window is not a channel, a warning is printed
+ and an empty string is returned.[br]
+ The second form returns the number of owners users on the channel specified by <window_id>.[br]
+ The number of owners is returned if it is known form at the call time: this means that
+ if the channel is not synchronized with the server (as just after the join, for example)
+ you might get a number that is actually smaller.[br]
+*/
+
+static bool chan_kvs_fnc_ownercount(KviKvsModuleFunctionCall * c)
+{
+ QString szId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("window id",KVS_PT_STRING,KVS_PF_OPTIONAL,szId)
+ KVSM_PARAMETERS_END(c)
+ KviChannel * ch = chan_kvs_find_channel(c,szId);
+ if (ch) c->returnValue()->setInteger(ch->chanOwnerCount());
+ return true;
+}
+
+/*
+ @doc: chan.admincount
+ @type:
+ function
+ @title:
+ $chan.admincount
+ @short:
+ Returns the number of channel admin users on a channel
+ @syntax:
+ <integer> $chan.admincount
+ <integer> $chan.admincount(<window_id:string>)
+ @description:
+ The first form returns the number of administrator users on the current channel (assuming that the current window
+ is a channel at all). If the current window is not a channel, a warning is printed
+ and an empty string is returned.[br]
+ The second form returns the number of administrator users on the channel specified by <window_id>.[br]
+ The number of administrators is returned if it is known form at the call time: this means that
+ if the channel is not synchronized with the server (as just after the join, for example)
+ you might get a number that is actually smaller.[br]
+*/
+
+static bool chan_kvs_fnc_admincount(KviKvsModuleFunctionCall * c)
+{
+ QString szId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("window id",KVS_PT_STRING,KVS_PF_OPTIONAL,szId)
+ KVSM_PARAMETERS_END(c)
+ KviChannel * ch = chan_kvs_find_channel(c,szId);
+ if (ch) c->returnValue()->setInteger(ch->chanAdminCount());
+ return true;
+}
+
+
+/*
+ @doc: chan.opcount
+ @type:
+ function
+ @title:
+ $chan.opcount
+ @short:
+ Returns the number of op users on a channel
+ @syntax:
+ <integer> $chan.opcount
+ <integer> $chan.opcount(<window_id:string>)
+ @description:
+ The first form returns the number of op users on the current channel (assuming that the current window
+ is a channel at all). If the current window is not a channel, a warning is printed
+ and an empty string is returned.[br]
+ The second form returns the number of op users on the channel specified by <window_id>.[br]
+ The number of ops is returned if it is known form at the call time: this means that
+ if the channel is not synchronized with the server (as just after the join, for example)
+ you might get a number that is actually smaller.[br]
+*/
+
+static bool chan_kvs_fnc_opcount(KviKvsModuleFunctionCall * c)
+{
+ QString szId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("window id",KVS_PT_STRING,KVS_PF_OPTIONAL,szId)
+ KVSM_PARAMETERS_END(c)
+ KviChannel * ch = chan_kvs_find_channel(c,szId);
+ if (ch) c->returnValue()->setInteger(ch->opCount());
+ return true;
+}
+
+/*
+ @doc: chan.voicecount
+ @type:
+ function
+ @title:
+ $chan.voicecount
+ @short:
+ Returns the number of voiced users on a channel
+ @syntax:
+ <integer> $chan.voicecount
+ <integer> $chan.voicecount(<window_id:string>)
+ @description:
+ The first form returns the number of voiced users on the current channel (assuming that the current window
+ is a channel at all). If the current window is not a channel, a warning is printed
+ and an empty string is returned.[br]
+ The second form returns the number of voiced users on the channel specified by <window_id>.[br]
+ The number of voiced users is returned if it is known form at the call time: this means that
+ if the channel is not synchronized with the server (as just after the join, for example)
+ you might get a number that is actually smaller.[br]
+*/
+
+static bool chan_kvs_fnc_voicecount(KviKvsModuleFunctionCall * c)
+{
+ QString szId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("window id",KVS_PT_STRING,KVS_PF_OPTIONAL,szId)
+ KVSM_PARAMETERS_END(c)
+ KviChannel * ch = chan_kvs_find_channel(c,szId);
+ if (ch) c->returnValue()->setInteger(ch->voiceCount());
+ return true;
+}
+
+/*
+ @doc: chan.halfopcount
+ @type:
+ function
+ @title:
+ $chan.halfopcount
+ @short:
+ Returns the number of halfop users on a channel
+ @syntax:
+ <integer> $chan.halfOpCount
+ <integer> $chan.halfOpCount(<window_id:string>)
+ @description:
+ The first form returns the number of half-operator users on the current channel (assuming that the current window
+ is a channel at all). If the current window is not a channel, a warning is printed
+ and an empty string is returned.[br]
+ The second form returns the number of half-operator users on the channel specified by <window_id>.[br]
+ The number of half-operator users is returned if it is known form at the call time: this means that
+ if the channel is not synchronized with the server (as just after the join, for example)
+ you might get a number that is actually smaller.[br]
+*/
+
+static bool chan_kvs_fnc_halfopcount(KviKvsModuleFunctionCall * c)
+{
+ QString szId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("window id",KVS_PT_STRING,KVS_PF_OPTIONAL,szId)
+ KVSM_PARAMETERS_END(c)
+ KviChannel * ch = chan_kvs_find_channel(c,szId);
+ if (ch) c->returnValue()->setInteger(ch->halfOpCount());
+ return true;
+}
+
+/*
+ @doc: chan.useropcount
+ @type:
+ function
+ @title:
+ $chan.useropcount
+ @short:
+ Returns the number of userop users on a channel
+ @syntax:
+ <integer> $chan.userOpCount
+ <integer> $chan.userOpCount(<window_id:string>)
+ @description:
+ The first form returns the number of user-operator users on the current channel (assuming that the current window
+ is a channel at all). If the current window is not a channel, a warning is printed
+ and an empty string is returned.[br]
+ The second form returns the number of user-operator users on the channel specified by <window_id>.[br]
+ The number of user-operator users is returned if it is known form at the call time: this means that
+ if the channel is not synchronized with the server (as just after the join, for example)
+ you might get a number that is actually smaller.[br]
+*/
+
+static bool chan_kvs_fnc_useropcount(KviKvsModuleFunctionCall * c)
+{
+ QString szId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("window id",KVS_PT_STRING,KVS_PF_OPTIONAL,szId)
+ KVSM_PARAMETERS_END(c)
+ KviChannel * ch = chan_kvs_find_channel(c,szId);
+ if (ch) c->returnValue()->setInteger(ch->userOpCount());
+ return true;
+}
+
+/*
+ @doc: chan.bancount
+ @type:
+ function
+ @title:
+ $chan.bancount
+ @short:
+ Returns the number of entries in the channel ban list
+ @syntax:
+ <integer> $chan.bancount
+ <integer> $chan.bancount(<window_id:string>)
+ @description:
+ The first form returns the number of entries in the ban list of the current channel (assuming that the current window
+ is a channel at all). If the current window is not a channel, a warning is printed
+ and 0 is returned.[br]
+ The second form returns the number entries in the ban list of the channel specified by <window_id>.[br]
+ The number of ban list entries is returned if it is known form at the call time: this means that
+ if the channel is not synchronized with the server (as just after the join, for example)
+ you might get a number that is actually smaller.[br]
+*/
+
+static bool chan_kvs_fnc_bancount(KviKvsModuleFunctionCall * c)
+{
+ QString szId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("window id",KVS_PT_STRING,KVS_PF_OPTIONAL,szId)
+ KVSM_PARAMETERS_END(c)
+ KviChannel * ch = chan_kvs_find_channel(c,szId);
+ if (ch) c->returnValue()->setInteger(ch->banCount());
+ return true;
+}
+
+/*
+ @doc: chan.banexceptioncount
+ @type:
+ function
+ @title:
+ $chan.banexceptioncount
+ @short:
+ Returns the number of entries in the channel ban exception list
+ @syntax:
+ <integer> $chan.banexceptioncount
+ <integer> $chan.banexceptioncount(<window_id:string>)
+ @description:
+ The first form returns the number of entries in the ban exception list of the current channel (assuming that the current window
+ is a channel at all). If the current window is not a channel, a warning is printed
+ and 0 is returned.[br]
+ The second form returns the number entries in the ban exception list of the channel specified by <window_id>.[br]
+ The number of ban exception list entries is returned if it is known form at the call time: this means that
+ if the channel is not synchronized with the server (as just after the join, for example)
+ you might get a number that is actually smaller.[br]
+*/
+
+static bool chan_kvs_fnc_banexceptioncount(KviKvsModuleFunctionCall * c)
+{
+ QString szId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("window id",KVS_PT_STRING,KVS_PF_OPTIONAL,szId)
+ KVSM_PARAMETERS_END(c)
+ KviChannel * ch = chan_kvs_find_channel(c,szId);
+ if (ch) c->returnValue()->setInteger(ch->banExceptionCount());
+ return true;
+}
+
+/*
+ @doc: chan.invitecount
+ @type:
+ function
+ @title:
+ $chan.invitecount
+ @short:
+ Returns the number of entries in the channel invite list
+ @syntax:
+ <integer> $chan.invitecount
+ <integer> $chan.invitecount(<window_id:string>)
+ @description:
+ The first form returns the number of entries in the invite list of the current channel (assuming that the current window
+ is a channel at all). If the current window is not a channel, a warning is printed
+ and 0 is returned.[br]
+ The second form returns the number entries in the invite list of the channel specified by <window_id>.[br]
+ The number of invite list entries is returned if it is known form at the call time: this means that
+ if the channel is not synchronized with the server (as just after the join, for example)
+ you might get a number that is actually smaller.[br]
+*/
+
+static bool chan_kvs_fnc_invitecount(KviKvsModuleFunctionCall * c)
+{
+ QString szId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("window id",KVS_PT_STRING,KVS_PF_OPTIONAL,szId)
+ KVSM_PARAMETERS_END(c)
+ KviChannel * ch = chan_kvs_find_channel(c,szId);
+ if (ch) c->returnValue()->setInteger(ch->inviteCount());
+ return true;
+}
+
+/*
+ @doc: chan.ison
+ @type:
+ function
+ @title:
+ $chan.ison
+ @short:
+ Checks if an user is on a channel
+ @syntax:
+ <boolean> $chan.ison(<nickname:string>[,<window_id:string>])
+ @description:
+ Returns 1 if <nickname> is on the channel identified by <window_id>, 0 otherwise.[br]
+ If <window_id> is not specified the current window is used (assuming that it is a channel at all).[br]
+ If the window is not a channel, a warning is printed and an empty string is returned.[br]
+*/
+
+static bool chan_kvs_fnc_ison(KviKvsModuleFunctionCall * c)
+{
+ QString szId,szNick;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("nickname",KVS_PT_NONEMPTYSTRING,0,szNick)
+ KVSM_PARAMETER("window id",KVS_PT_STRING,KVS_PF_OPTIONAL,szId)
+ KVSM_PARAMETERS_END(c)
+ KviChannel * ch = chan_kvs_find_channel(c,szId);
+ if (ch) c->returnValue()->setBoolean(ch->isOn(szNick));
+ return true;
+}
+
+/*
+ @doc: chan.getflag
+ @type:
+ function
+ @title:
+ $chan.getflag
+ @short:
+ Returns the channel-user mode flag of an user
+ @syntax:
+ <char> $chan.getflag(<nickname:string>[,<window_id:string>])
+ @description:
+ Returns the channel user mode flag of an user on the channel specified by <window_id>.[br]
+ If <window_id> is not passed, the current window is used.[br]
+ If the specified window is not a channel, a warning is printed and an empty string is returned.[br]
+ If the specified user is not on the channel identified by <window_id>, and empty string is returned.[br]
+ The possible user flags are:[br]
+ '!' for channel administrators[br]
+ '@' for ops[br]
+ '%' for halfops[br]
+ '+' for voiced users[br]
+ '-' for userops[br]
+ If the user has more than one flag then the highest one is returned.[br]
+ If the user has no flag at all then an empty string is returned.
+*/
+
+static bool chan_kvs_fnc_getflag(KviKvsModuleFunctionCall * c)
+{
+ QString szId,szNick;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("nickname",KVS_PT_NONEMPTYSTRING,0,szNick)
+ KVSM_PARAMETER("window id",KVS_PT_STRING,KVS_PF_OPTIONAL,szId)
+ KVSM_PARAMETERS_END(c)
+ KviChannel * ch = chan_kvs_find_channel(c,szId);
+ if(ch)
+ {
+ QChar cFlag = ch->userListView()->getUserFlag(szNick);
+ if(cFlag != QChar(0))
+ {
+ QString szFlag = cFlag;
+ c->returnValue()->setString(szFlag);
+ } else {
+ c->returnValue()->setNothing();
+ }
+ }
+ return true;
+}
+
+#define IS_KVS_FUNC(__clbkname,__chanfunc) \
+static bool __clbkname(KviKvsModuleFunctionCall * c) \
+{ \
+ QString szId,szNick;\
+ KVSM_PARAMETERS_BEGIN(c)\
+ KVSM_PARAMETER("nickname",KVS_PT_NONEMPTYSTRING,0,szNick)\
+ KVSM_PARAMETER("window id",KVS_PT_STRING,KVS_PF_OPTIONAL,szId)\
+ KVSM_PARAMETERS_END(c)\
+ KviChannel * ch = chan_kvs_find_channel(c,szId); \
+ if(ch) c->returnValue()->setBoolean(ch->__chanfunc(szNick,true)); \
+ return true; \
+}
+
+/*
+ @doc: chan.isowner
+ @type:
+ function
+ @title:
+ $chan.isowner
+ @short:
+ Checks if an user is at least a channel owner
+ @syntax:
+ <boolean> $chan.isowner(<nickname:string>[,<window_id:string>])
+ @description:
+ Returns 1 if <nickname> is at least an owner on the channel identified by <window_id>, 0 otherwise.[br]
+ If <window_id> is not specified the current window is used (assuming that it is a channel at all).[br]
+ If the window is not a channel, a warning is printed and an empty string is returned.[br]
+ Note that if the user is not on the channel at all, you will get 0 as return value.[br]
+*/
+
+IS_KVS_FUNC(chan_kvs_fnc_isowner,isChanOwner)
+
+/*
+ @doc: chan.isadmin
+ @type:
+ function
+ @title:
+ $chan.isadmin
+ @short:
+ Checks if an user is at least channel administrator
+ @syntax:
+ <boolean> $chan.isadmin(<nickname:string>[,<window_id:string>])
+ @description:
+ Returns 1 if <nickname> is at least an administrator on the channel identified by <window_id>, 0 otherwise.[br]
+ If <window_id> is not specified the current window is used (assuming that it is a channel at all).[br]
+ If the window is not a channel, a warning is printed and an empty string is returned.[br]
+ Note that if the user is not on the channel at all, you will get 0 as return value.[br]
+*/
+
+IS_KVS_FUNC(chan_kvs_fnc_isadmin,isChanAdmin)
+
+/*
+ @doc: chan.isop
+ @type:
+ function
+ @title:
+ $chan.isop
+ @short:
+ Checks if an user is at least an op on a channel
+ @syntax:
+ <boolean> $chan.isop(<nickname:string>[,<window_id:stringn>])
+ @description:
+ Returns 1 if <nickname> is at least an operator on the channel identified by <window_id>, 0 otherwise.[br]
+ If <window_id> is not specified the current window is used (assuming that it is a channel at all).[br]
+ If the window is not a channel, a warning is printed and an empty string is returned.[br]
+ Note that if the user is not on the channel at all, you will get 0 as return value.[br]
+*/
+
+IS_KVS_FUNC(chan_kvs_fnc_isop,isOp)
+
+/*
+ @doc: chan.isvoice
+ @type:
+ function
+ @title:
+ $chan.isvoice
+ @short:
+ Checks if an user is at least voiced on a channel
+ @syntax:
+ <boolean> $chan.isvoice(<nickname:string>[,<window_id:string>])
+ @description:
+ Returns 1 if <nickname> is at least voiced on the channel identified by <window_id>, 0 otherwise.[br]
+ If <window_id> is not specified the current window is used (assuming that it is a channel at all).[br]
+ If the window is not a channel, a warning is printed and an empty string is returned.[br]
+ Note that if the user is not on the channel at all, you will get 0 as return value.[br]
+*/
+
+IS_KVS_FUNC(chan_kvs_fnc_isvoice,isVoice)
+
+/*
+ @doc: chan.ishalfop
+ @type:
+ function
+ @title:
+ $chan.ishalfop
+ @short:
+ Checks if an user is at least halfop on a channel
+ @syntax:
+ <boolean> $chan.ishalfop(<nickname:string>[,<window_id:string>])
+ @description:
+ Returns 1 if <nickname> is at least a half-operator on the channel identified by <window_id>, 0 otherwise.[br]
+ If <window_id> is not specified the current window is used (assuming that it is a channel at all).[br]
+ If the window is not a channel, a warning is printed and an empty string is returned.[br]
+ Note that if the user is not on the channel at all, you will get 0 as return value.[br]
+*/
+
+IS_KVS_FUNC(chan_kvs_fnc_ishalfop,isHalfOp)
+
+/*
+ @doc: chan.isuserop
+ @type:
+ function
+ @title:
+ $chan.isuserop
+ @short:
+ Checks if an user is at least an userop on a channel
+ @syntax:
+ <boolean> $chan.isuserop(<nickname:string>[,<window_id:string>])
+ @description:
+ Returns 1 if <nickname> is at least an user-operator on the channel identified by <window_id>, 0 otherwise.[br]
+ If <window_id> is not specified the current window is used (assuming that it is a channel at all).[br]
+ If the window is not a channel, a warning is printed and an empty string is returned.[br]
+ Note that if the user is not on the channel at all, you will get 0 as return value.[br]
+*/
+
+IS_KVS_FUNC(chan_kvs_fnc_isuserop,isUserOp)
+
+
+/*
+ @doc: chan.ismeowner
+ @type:
+ function
+ @title:
+ $chan.isMeOwner
+ @short:
+ Checks if the current user is at least an owner on a channel
+ @syntax:
+ <boolean> $chan.isMeOwner
+ <boolean> $chan.isMeOwner(<window_id:string>)
+ @description:
+ Returns 1 if the current user is at least an owner on the channel specified by <window_id>, 0 otherwise.[br]
+ If <window_id> is not passed, the current window is used (assuming it is a channel at all).[br]
+ If the window is not a channel, a warning is printed and an empty string is returned.[br]
+ This function is a "shortcut" for [fnc]$chan.isowner[/fnc]([fnc]$me[/fnc]).[br]
+*/
+
+#define IS_ME_KVS_FUNC(__clbkname,__chanfunc) \
+static bool __clbkname(KviKvsModuleFunctionCall * c) \
+{ \
+ QString szId;\
+ KVSM_PARAMETERS_BEGIN(c)\
+ KVSM_PARAMETER("window id",KVS_PT_STRING,KVS_PF_OPTIONAL,szId)\
+ KVSM_PARAMETERS_END(c)\
+ KviChannel * ch = chan_kvs_find_channel(c,szId); \
+ if(ch) c->returnValue()->setBoolean(ch->__chanfunc(true)); \
+ return true; \
+}
+
+IS_ME_KVS_FUNC(chan_kvs_fnc_ismeowner,isMeChanOwner)
+
+/*
+ @doc: chan.ismeadmin
+ @type:
+ function
+ @title:
+ $chan.isMeAdmin
+ @short:
+ Checks if the current user is at least an administrator on a channel
+ @syntax:
+ <boolean> $chan.isMeAdmin
+ <boolean> $chan.isMeAdmin(<window_id:string>)
+ @description:
+ Returns 1 if the current user is at least an administrator on the channel specified by <window_id>, 0 otherwise.[br]
+ If <window_id> is not passed, the current window is used (assuming it is a channel at all).[br]
+ If the window is not a channel, a warning is printed and an empty string is returned.[br]
+ This function is a "shortcut" for [fnc]$chan.isadmin[/fnc]([fnc]$me[/fnc]).[br]
+*/
+
+IS_ME_KVS_FUNC(chan_kvs_fnc_ismeadmin,isMeChanAdmin)
+
+/*
+ @doc: chan.ismeop
+ @type:
+ function
+ @title:
+ $chan.isMeOp
+ @short:
+ Checks if the current user is at least op on a channel
+ @syntax:
+ <boolean> $chan.isMeOp
+ <boolean> $chan.isMeOp(<window_id:string>)
+ @description:
+ Returns 1 if the current user is at least op on the channel specified by <window_id>, 0 otherwise.[br]
+ If <window_id> is not passed, the current window is used (assuming it is a channel at all).[br]
+ If the window is not a channel, a warning is printed and an empty string is returned.[br]
+ This function is a "shortcut" for [fnc]$chan.isop[/fnc]([fnc]$me[/fnc]).[br]
+*/
+
+IS_ME_KVS_FUNC(chan_kvs_fnc_ismeop,isMeOp)
+
+/*
+ @doc: chan.ismehalfop
+ @type:
+ function
+ @title:
+ $chan.isMeHalfOp
+ @short:
+ Checks if the current user is at least an half operator on a channel
+ @syntax:
+ <boolean> $chan.isMeHalfOp
+ <boolean> $chan.isMeHalfOp(<window_id:string>)
+ @description:
+ Returns 1 if the current user is at least an half operator on the channel specified by <window_id>, 0 otherwise.[br]
+ If <window_id> is not passed, the current window is used (assuming it is a channel at all).[br]
+ If the window is not a channel, a warning is printed and an empty string is returned.[br]
+ This function is a "shortcut" for [fnc]$chan.ishalfop[/fnc]([fnc]$me[/fnc]).[br]
+*/
+
+IS_ME_KVS_FUNC(chan_kvs_fnc_ismehalfop,isMeHalfOp)
+
+/*
+ @doc: chan.ismevoice
+ @type:
+ function
+ @title:
+ $chan.isMeVoice
+ @short:
+ Checks if the current user is at least voice on a channel
+ @syntax:
+ <boolean> $chan.isMeVoice
+ <boolean> $chan.isMeVoice(<window_id:string>)
+ @description:
+ Returns 1 if the current user is at least voice on the channel specified by <window_id>, 0 otherwise.[br]
+ If <window_id> is not passed, the current window is used (assuming it is a channel at all).[br]
+ If the window is not a channel, a warning is printed and an empty string is returned.[br]
+ This function is a "shortcut" for [fnc]$chan.isvoice[/fnc]([fnc]$me[/fnc]).[br]
+*/
+
+IS_ME_KVS_FUNC(chan_kvs_fnc_ismevoice,isMeVoice)
+
+/*
+ @doc: chan.ismeuserop
+ @type:
+ function
+ @title:
+ $chan.isMeUserOp
+ @short:
+ Checks if the current user is at least an user operator on a channel
+ @syntax:
+ <boolean> $chan.isMeUserOp
+ <boolean> $chan.isMeUserOp(<window_id:String>)
+ @description:
+ Returns 1 if the current user is at least an user operator on the channel specified by <window_id>, 0 otherwise.[br]
+ If <window_id> is not passed, the current window is used (assuming it is a channel at all).[br]
+ If the window is not a channel, a warning is printed and an empty string is returned.[br]
+ This function is a "shortcut" for [fnc]$chan.isuserop[/fnc]([fnc]$me[/fnc]).[br]
+*/
+
+IS_ME_KVS_FUNC(chan_kvs_fnc_ismeuserop,isMeUserOp)
+
+/*
+ @doc: chan.mode
+ @type:
+ function
+ @title:
+ $chan.mode
+ @short:
+ Returns the mode string of a channel
+ @syntax:
+ <string> $chan.mode
+ <string> $chan.mode(<window_id:string>)
+ @description:
+ Returns the mode string of the channel identified by <window_id>.[br]
+ If no <window_id> is passed, the current channel mode string is returned (assuming that
+ the current window is a chnannel at all).[br]
+ If the window is not a channel, a warning is printed and an empty string is returned.[br]
+*/
+
+static bool chan_kvs_fnc_mode(KviKvsModuleFunctionCall * c)
+{
+ QString szId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("window id",KVS_PT_STRING,KVS_PF_OPTIONAL,szId)
+ KVSM_PARAMETERS_END(c)
+ KviChannel * ch = chan_kvs_find_channel(c,szId);
+ if(ch)
+ {
+ QString chMode;
+ ch->getChannelModeString(chMode);
+ c->returnValue()->setString(chMode);
+ }
+ return true;
+}
+
+
+/*
+ @doc: chan.key
+ @type:
+ function
+ @title:
+ $chan.key
+ @short:
+ Returns the key of a channel
+ @syntax:
+ <string> $chan.key
+ <string> $chan.key(<window_id:string>)
+ @description:
+ Returns the key of the channel identified by <window_id>.[br]
+ If no <window_id> is passed, the current channel key is returned (assuming that
+ the current window is a chnannel at all).[br]
+ If the window is not a channel, a warning is printed and an empty string is returned.[br]
+ If the channel has no key set, an empty string is returned.[br]
+*/
+
+static bool chan_kvs_fnc_key(KviKvsModuleFunctionCall * c)
+{
+ QString szId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("window id",KVS_PT_STRING,KVS_PF_OPTIONAL,szId)
+ KVSM_PARAMETERS_END(c)
+ KviChannel * ch = chan_kvs_find_channel(c,szId);
+ if (ch) c->returnValue()->setString(ch->channelKey());
+ return true;
+}
+
+/*
+ @doc: chan.limit
+ @type:
+ function
+ @title:
+ $chan.limit
+ @short:
+ Returns the limit of a channel
+ @syntax:
+ <integer> $chan.limit
+ <integer> $chan.limit(<window_id:string>)
+ @description:
+ Returns the limit of the channel identified by <window_id>.[br]
+ If no <window_id> is passed, the current channel limit is returned (assuming that
+ the current window is a chnannel at all).[br]
+ If the window is not a channel, a warning is printed and an empty string is returned.[br]
+ If the channel has no limit set, "0" is returned.[br]
+*/
+
+static bool chan_kvs_fnc_limit(KviKvsModuleFunctionCall * c)
+{
+ QString szId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("window id",KVS_PT_STRING,KVS_PF_OPTIONAL,szId)
+ KVSM_PARAMETERS_END(c)
+ KviChannel * ch = chan_kvs_find_channel(c,szId);
+ kvs_int_t limit=0;
+ QString lim;
+ if (ch)
+ {
+ if(ch->hasChannelLimit())
+ {
+ lim=ch->channelLimit().ptr();
+ limit=lim.toInt();
+ }
+ c->returnValue()->setInteger(limit);
+ }
+ return true;
+}
+
+
+/*
+ @doc: chan.users
+ @type:
+ function
+ @title:
+ $chan.users
+ @short:
+ Returns an array of channel user nicknames
+ @syntax:
+ <array> $chan.users([window_id:string],[mask:string],[flags:string])
+ @description:
+ Returns an array of nicknames on the channel specified by [window_id].[br]
+ If [window_id] is empty, the current window is used.[br]
+ If the window designated by [window_id] is not a channel a warning is printed and an empty array is returned.[br]
+ If [mask] is given, each user is added to the array only
+ if it matches the [mask].[br]
+ [flags] may contain a subset of the letters "aovhnmi":[br]
+ "ovhn" are mode flags: the users are added to the array only if they are channel administrators ('a'), operators ('o'),
+ voiced users ('v'), half-operators ('h'), user-operators ('u') or unflagged ('n') users. (Unflagged means not operators, not
+ voiced and not half-operators). If none of the "ovhun" flags are used, KVIrc behaves like all five were passed.[br]
+ The flag 'm' causes the entire user masks to be added to the
+ array entries, as known by KVIrc at the moment of this function call.[br]
+ The flag 'i' causes KVIrc to invert the match and add only the users that do NOT match [mask].[br]
+ Please note that on really large channels this function may be time consuming (especially if [mask] is used):
+ use with care.[br]
+ @example:
+ [example]
+ [comment]# Get the nickname list[/comment]
+ %test[] = $chan.users
+ [comment]# And loop thru the items[/comment]
+ %i = 0
+ [comment]# %test[]# returns the number of elements in the array[/comment]
+ %count = %test[]#
+ while(%i < %count)
+ {
+ echo "User %i : %test[%i]"
+ %i++
+ }
+ [comment]# Another way of looping[/comment]
+ foreach(%tmp,%test[])echo "User %tmp"
+ [comment]# Find all the users that come from the *.org domain[/comment]
+ %test[]=$chan.users(,*!*@*.org)
+ echo %test[]
+ [comment]# This will work too![/comment]
+ echo $chan.users(,*!*@*.org)
+ [comment]# Find all the channel operators[/comment]
+ %test[] = $chan.users(,,o)
+ echo %test[]
+ [comment]# Find all the voiced users that do NOT come from *.edu[/comment]
+ [comment]# See also their whole mask[/comment]
+ %test[] = $chan.users(,*!*@*.edu,vim)
+ echo %test[]
+ [/example]
+
+*/
+
+static bool chan_kvs_fnc_users(KviKvsModuleFunctionCall * c)
+{
+ QString szWinId,szMask,szFlags;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("window id",KVS_PT_STRING,KVS_PF_OPTIONAL,szWinId)
+ KVSM_PARAMETER("mask",KVS_PT_STRING,KVS_PF_OPTIONAL,szMask)
+ KVSM_PARAMETER("flags",KVS_PT_STRING,KVS_PF_OPTIONAL,szFlags)
+ KVSM_PARAMETERS_END(c)
+
+ KviKvsArray * pArray = new KviKvsArray();
+ c->returnValue()->setArray(pArray);
+
+ KviChannel * ch = chan_kvs_find_channel(c,szWinId);
+ if(!ch)return true;
+
+ KviUserListEntry * e = ch->userListView()->firstItem(); // Thnx Julien :)
+
+ bool bCheckMask = !szMask.isEmpty();
+ bool bOp = szFlags.find('o',false) != -1;
+ bool bVoice = szFlags.find('v',false) != -1;
+ bool bHalfOp = szFlags.find('h',false) != -1;
+ bool bChanAdmins = szFlags.find('a',false) != -1;
+ bool bUserOp = szFlags.find('u',false) != -1;
+ bool bNone = szFlags.find('n',false) != -1;
+ bool bCheckFlags = bOp || bVoice || bHalfOp || bNone || bChanAdmins || bUserOp;
+ bool bAddMask = szFlags.find('m',false) != -1;
+
+ int idx = 0;
+
+ if(bAddMask || bCheckFlags || bCheckMask)
+ {
+ bool bMaskMustMatch = szFlags.find('i',false) == -1;
+ KviIrcMask mask(szMask);
+
+ while(e)
+ {
+ if(bCheckFlags)
+ {
+ if(bChanAdmins)
+ {
+ if(e->flags() & KVI_USERFLAG_CHANADMIN)goto check_mask;
+ }
+ if(bOp)
+ {
+ if(e->flags() & KVI_USERFLAG_OP)goto check_mask;
+ }
+ if(bVoice)
+ {
+ if(e->flags() & KVI_USERFLAG_VOICE)goto check_mask;
+ }
+ if(bHalfOp)
+ {
+ if(e->flags() & KVI_USERFLAG_HALFOP)goto check_mask;
+ }
+ if(bUserOp)
+ {
+ if(e->flags() & KVI_USERFLAG_USEROP)goto check_mask;
+ }
+ if(bNone)
+ {
+ if(!(e->flags() & KVI_USERFLAG_MASK))goto check_mask;
+ }
+ goto next_item;
+ }
+check_mask:
+ if(bCheckMask)
+ {
+ if(mask.matchesFixed(e->nick(),e->globalData()->user(),e->globalData()->host()) == bMaskMustMatch)goto add_item;
+ goto next_item;
+ }
+add_item:
+ if(bAddMask)
+ {
+ QString x(e->nick());
+ x.append('!');
+ x.append(e->globalData()->user());
+ x.append('@');
+ x.append(e->globalData()->host());
+ pArray->set(idx,new KviKvsVariant(x));
+ } else {
+ pArray->set(idx,new KviKvsVariant(e->nick()));
+ }
+ idx++;
+next_item:
+ e = e->next();
+ }
+ } else {
+ while(e)
+ {
+ pArray->set(idx,new KviKvsVariant(e->nick()));
+ idx++;
+ e = e->next();
+ }
+ }
+
+
+ return true;
+}
+
+/*
+ @doc: chan.banlist
+ @type:
+ function
+ @title:
+ $chan.banlist
+ @short:
+ Returns an array of channel ban masks
+ @syntax:
+ $chan.banlist([window_id])
+ @description:
+ Returns an array of ban masks set ont the channel identified by [window_id].[br]
+ If [window_id] is empty, the current window is used.[br]
+ If the window designated by [window_id] is not a channel a warning is printed and an empty array is returned.[br]
+*/
+
+static bool chan_kvs_fnc_banlist(KviKvsModuleFunctionCall * c)
+{
+ QString szWinId,szMask,szFlags;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("window id",KVS_PT_STRING,KVS_PF_OPTIONAL,szWinId)
+ KVSM_PARAMETERS_END(c)
+
+ KviKvsArray * pArray = new KviKvsArray();
+ c->returnValue()->setArray(pArray);
+
+ KviChannel * ch = chan_kvs_find_channel(c,szWinId);
+
+ if(!ch)return true;
+
+ int idx = 0;
+
+ KviPointerList<KviMaskEntry> * l = ((KviChannel *)(c->window()))->banList();
+
+ for(KviMaskEntry * e = l->first();e;e = l->next())
+ {
+ pArray->set(idx,new KviKvsVariant(e->szMask));
+ idx++;
+ }
+
+ return true;
+}
+
+/*
+ @doc: chan.banexceptionlist
+ @type:
+ function
+ @title:
+ $chan.banexceptionlist
+ @short:
+ Returns an array of channel ban exception masks
+ @syntax:
+ <array> $chan.banexceptionlist([window_id])
+ @description:
+ Returns an array of ban exception masks set ont the channel identified by [window_id].[br]
+ If [window_id] is empty, the current window is used.[br]
+ If the window designated by [window_id] is not a channel a warning is printed and an empty array is returned.[br]
+*/
+
+static bool chan_kvs_fnc_banexceptionlist(KviKvsModuleFunctionCall * c)
+{
+ QString szWinId,szMask,szFlags;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("window id",KVS_PT_STRING,KVS_PF_OPTIONAL,szWinId)
+ KVSM_PARAMETERS_END(c)
+
+ KviKvsArray * pArray = new KviKvsArray();
+ c->returnValue()->setArray(pArray);
+
+ KviChannel * ch = chan_kvs_find_channel(c,szWinId);
+
+ if(!ch)return true;
+
+ int idx = 0;
+
+ KviPointerList<KviMaskEntry> * l = ((KviChannel *)(c->window()))->banExceptionList();
+
+ for(KviMaskEntry * e = l->first();e;e = l->next())
+ {
+ pArray->set(idx,new KviKvsVariant(e->szMask));
+ idx++;
+ }
+
+ return true;
+}
+
+/*
+ @doc: chan.invitelist
+ @type:
+ function
+ @title:
+ $chan.invitelist
+ @short:
+ Returns an array of channel invite masks
+ @syntax:
+ <array> $chan.banexceptionlist([window_id])
+ @description:
+ Returns an array of invite masks set ont the channel identified by [window_id].[br]
+ If [window_id] is empty, the current window is used.[br]
+ If the window designated by [window_id] is not a channel a warning is printed and an empty array is returned.[br]
+*/
+
+static bool chan_kvs_fnc_invitelist(KviKvsModuleFunctionCall * c)
+{
+ QString szWinId,szMask,szFlags;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("window id",KVS_PT_STRING,KVS_PF_OPTIONAL,szWinId)
+ KVSM_PARAMETERS_END(c)
+
+ KviKvsArray * pArray = new KviKvsArray();
+ c->returnValue()->setArray(pArray);
+
+ KviChannel * ch = chan_kvs_find_channel(c,szWinId);
+
+ if(!ch)return true;
+
+ int idx = 0;
+
+ KviPointerList<KviMaskEntry> * l = ((KviChannel *)(c->window()))->inviteList();
+
+ for(KviMaskEntry * e = l->first();e;e = l->next())
+ {
+ pArray->set(idx,new KviKvsVariant(e->szMask));
+ idx++;
+ }
+
+ return true;
+}
+
+/*
+ @doc: chan.matchban
+ @type:
+ function
+ @title:
+ $chan.matchban
+ @short:
+ Matches a mask agains the channel ban list
+ @syntax:
+ <string> $chan.matchban([window_id],<complete_mask>)
+ @description:
+ Returns the ban mask that matches <complete_mask> on channel identified by [window_id].[br]
+ If no ban mask matches <complete_mask> an empty string is returned.[br]
+ If [window_id] is empty, the current window is used.[br]
+ If the window designated by [window_id] is not a channel a warning is printed and an empty string is returned.[br]
+ This function is useful to determine if a ban set on the channel matches an user.[br]
+*/
+
+static bool chan_kvs_fnc_matchban(KviKvsModuleFunctionCall * c)
+{
+ QString szWinId,szMask;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("window id",KVS_PT_STRING,0,szWinId)
+ KVSM_PARAMETER("mask",KVS_PT_STRING,0,szMask)
+ KVSM_PARAMETERS_END(c)
+
+ KviChannel * ch = chan_kvs_find_channel(c,szWinId);
+
+ if(!ch)
+ {
+ c->returnValue()->setNothing();
+ return true;
+ }
+
+ KviPointerList<KviMaskEntry> * l = ((KviChannel *)(c->window()))->banList();
+
+ for(KviMaskEntry * e = l->first();e;e = l->next())
+ {
+ if(KviQString::matchStringCI(e->szMask,szMask))
+ {
+ c->returnValue()->setString(e->szMask);
+ return true;
+ }
+ }
+
+ c->returnValue()->setNothing();
+ return true;
+}
+
+/*
+ @doc: chan.matchbanexception
+ @type:
+ function
+ @title:
+ $chan.matchbanexception
+ @short:
+ Matches a mask agains the channel ban exception list
+ @syntax:
+ <string> $chan.matchbanexception([window_id],<complete_mask>)
+ @description:
+ Returns the ban exception mask that matches <complete_mask> on channel identified by [window_id].[br]
+ If no ban exception mask matches <complete_mask> an empty string is returned.[br]
+ If [window_id] is empty, the current window is used.[br]
+ If the window designated by [window_id] is not a channel a warning is printed and an empty string is returned.[br]
+ This function is useful to determine if a ban exception set on the channel matches an user.[br]
+*/
+
+static bool chan_kvs_fnc_matchbanexception(KviKvsModuleFunctionCall * c)
+{
+ QString szWinId,szMask;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("window id",KVS_PT_STRING,0,szWinId)
+ KVSM_PARAMETER("mask",KVS_PT_STRING,0,szMask)
+ KVSM_PARAMETERS_END(c)
+
+ KviChannel * ch = chan_kvs_find_channel(c,szWinId);
+
+ if(!ch)
+ {
+ c->returnValue()->setNothing();
+ return true;
+ }
+
+ KviPointerList<KviMaskEntry> * l = ((KviChannel *)(c->window()))->banExceptionList();
+
+ for(KviMaskEntry * e = l->first();e;e = l->next())
+ {
+ if(KviQString::matchStringCI(e->szMask,szMask))
+ {
+ c->returnValue()->setString(e->szMask);
+ return true;
+ }
+ }
+
+ c->returnValue()->setNothing();
+ return true;
+}
+
+/*
+ @doc: chan.matchinvite
+ @type:
+ function
+ @title:
+ $chan.matchinvite
+ @short:
+ Matches a mask agains the channel invite list
+ @syntax:
+ <string> $chan.matchinvite([window_id:string],<complete_mask>)
+ @description:
+ Returns the invite mask that matches <complete_mask> on channel identified by [window_id].[br]
+ If no invite mask matches <complete_mask> an empty string is returned.[br]
+ If [window_id] is empty, the current window is used.[br]
+ If the window designated by [window_id] is not a channel a warning is printed and an empty string is returned.[br]
+ This function is useful to determine if a invite set on the channel matches an user.[br]
+*/
+
+static bool chan_kvs_fnc_matchinvite(KviKvsModuleFunctionCall * c)
+{
+ QString szWinId,szMask;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("window id",KVS_PT_STRING,0,szWinId)
+ KVSM_PARAMETER("mask",KVS_PT_STRING,0,szMask)
+ KVSM_PARAMETERS_END(c)
+
+ KviChannel * ch = chan_kvs_find_channel(c,szWinId);
+
+ if(!ch)
+ {
+ c->returnValue()->setNothing();
+ return true;
+ }
+
+ KviPointerList<KviMaskEntry> * l = ((KviChannel *)(c->window()))->inviteList();
+
+ for(KviMaskEntry * e = l->first();e;e = l->next())
+ {
+ if(KviQString::matchStringCI(e->szMask,szMask))
+ {
+ c->returnValue()->setString(e->szMask);
+ return true;
+ }
+ }
+
+ c->returnValue()->setNothing();
+ return true;
+}
+
+/*
+ @doc: chan.usermodelevel
+ @type:
+ function
+ @title:
+ $chan.usermodelevel
+ @short:
+ Returns the channel user-mode level
+ @syntax:
+ <integer> $chan.userModeLevel(<nickname:string>[,<window_id:string>])
+ @description:
+ Returns an integer identifying the specified user's channel mode on the channel specified by <window_id>.[br]
+ If <window_id> is not passed, the current window is used.[br]
+ If the specified window is not a channel, a warning is printed and '0' is returned.[br]
+ This number can be useful to implement comparison functions between
+ users in order to determine the actions they can issue between each other.[br]
+ For example it is granted that an op will have userModeLevel greater than
+ a voiced user or that a simple "modeless" user will have
+ an userModeLevel lower than a halfop.[br]
+ IRC allows multiple modes to be applied to a single user on a channel,
+ in that case this function will return the level of the highest mode
+ applied to the user.[br]
+ Note: Don't rely on this number being any particular exact value except
+ for the completely modeless users (in which case this function will return always '0').
+*/
+
+static bool chan_kvs_fnc_usermodelevel(KviKvsModuleFunctionCall * c)
+{
+ QString szNick,szWinId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("nickname",KVS_PT_STRING,0,szNick)
+ KVSM_PARAMETER("window id",KVS_PT_STRING,KVS_PF_OPTIONAL,szWinId)
+ KVSM_PARAMETERS_END(c)
+ KviChannel * ch = chan_kvs_find_channel(c,szWinId);
+
+ kvs_int_t mode=0;
+ if(ch) mode=ch->userListView()->getUserModeLevel(szNick);
+ c->returnValue()->setInteger(mode);
+ return true;
+}
+
+/*
+ @doc: chan.userjointime
+ @type:
+ function
+ @title:
+ $chan.userJoinTime
+ @short:
+ Returns the time that an user has joined the channel
+ @syntax:
+ <integer> $chan.userJoinTime(<nickname:string>[,<window_id:string>])
+ @description:
+ Returns the unix time at which the user specified by <nickname> has joined the channel specified by <window_id>.[br]
+ If <window_id> is not passed, the current window is used.[br]
+ If the specified window is not a channel, a warning is printed and '0' is returned.[br]
+ '0' is also returned when the user's join time is unknown: this is true
+ for all the users that were on the channel before the local user has joined it (e.g.
+ you know the join time only for users that YOU see joining).[br]
+ @seealso:
+ [fnc]$unixTime[/fnc], [fnc]$chan.userLastActionTime[/fnc]
+*/
+
+static bool chan_kvs_fnc_userjointime(KviKvsModuleFunctionCall * c)
+{
+ QString szNick,szWinId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("nickname",KVS_PT_STRING,0,szNick)
+ KVSM_PARAMETER("window id",KVS_PT_STRING,KVS_PF_OPTIONAL,szWinId)
+ KVSM_PARAMETERS_END(c)
+ KviChannel * ch = chan_kvs_find_channel(c,szWinId);
+
+ kvs_int_t time=0;
+ if(ch) time=ch->userListView()->getUserJoinTime(szNick);
+ c->returnValue()->setInteger(time);
+ return true;
+}
+
+/*
+ @doc: chan.userlastactiontime
+ @type:
+ function
+ @title:
+ $chan.userLastActionTime
+ @short:
+ Returns the time that an user has last performed some kind of action on the channel
+ @syntax:
+ <integer> $chan.userLastActionTime(<nickname:string>[,<window_id:string>])
+ @description:
+ Returns the unix time at which the user specified by <nickname> has performed
+ some kind of action on the channel specified by <window_id>.[br]
+ If <window_id> is not passed, the current window is used.[br]
+ If the specified window is not a channel, a warning is printed and '0' is returned.[br]
+ '0' is also returned when the user's last action time is unknown: this is true
+ for all the users that were on the channel before the local user has joined it
+ and have performed no actions since that moment.
+ @seealso:
+ [fnc]$unixTime[/fnc], [fnc]$chan.userJoinTime[/fnc]
+*/
+
+static bool chan_kvs_fnc_userlastactiontime(KviKvsModuleFunctionCall * c)
+{
+ QString szNick,szWinId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("nickname",KVS_PT_STRING,0,szNick)
+ KVSM_PARAMETER("window id",KVS_PT_STRING,KVS_PF_OPTIONAL,szWinId)
+ KVSM_PARAMETERS_END(c)
+ KviChannel * ch = chan_kvs_find_channel(c,szWinId);
+
+ kvs_int_t time=0;
+ if(ch) time=ch->userListView()->getUserLastActionTime(szNick);
+ c->returnValue()->setInteger(time);
+ return true;
+}
+
+static bool chan_module_init(KviModule * m)
+{
+ KVSM_REGISTER_FUNCTION(m,"name",chan_kvs_fnc_name);
+ KVSM_REGISTER_FUNCTION(m,"topic",chan_kvs_fnc_topic);
+ KVSM_REGISTER_FUNCTION(m,"topicsetby",chan_kvs_fnc_topicsetby);
+ KVSM_REGISTER_FUNCTION(m,"topicsetat",chan_kvs_fnc_topicsetat);
+ KVSM_REGISTER_FUNCTION(m,"usercount",chan_kvs_fnc_usercount);
+ KVSM_REGISTER_FUNCTION(m,"ownercount",chan_kvs_fnc_ownercount);
+ KVSM_REGISTER_FUNCTION(m,"admincount",chan_kvs_fnc_admincount);
+ KVSM_REGISTER_FUNCTION(m,"opcount",chan_kvs_fnc_opcount);
+ KVSM_REGISTER_FUNCTION(m,"voicecount",chan_kvs_fnc_voicecount);
+ KVSM_REGISTER_FUNCTION(m,"halfopcount",chan_kvs_fnc_halfopcount);
+ KVSM_REGISTER_FUNCTION(m,"useropcount",chan_kvs_fnc_useropcount);
+ KVSM_REGISTER_FUNCTION(m,"isowner",chan_kvs_fnc_isowner);
+ KVSM_REGISTER_FUNCTION(m,"ison",chan_kvs_fnc_ison);
+ KVSM_REGISTER_FUNCTION(m,"isadmin",chan_kvs_fnc_isadmin);
+ KVSM_REGISTER_FUNCTION(m,"isop",chan_kvs_fnc_isop);
+ KVSM_REGISTER_FUNCTION(m,"isvoice",chan_kvs_fnc_isvoice);
+ KVSM_REGISTER_FUNCTION(m,"ishalfop",chan_kvs_fnc_ishalfop);
+ KVSM_REGISTER_FUNCTION(m,"isuserop",chan_kvs_fnc_isuserop);
+ KVSM_REGISTER_FUNCTION(m,"ismeuserop",chan_kvs_fnc_ismeuserop);
+ KVSM_REGISTER_FUNCTION(m,"ismevoice",chan_kvs_fnc_ismevoice);
+ KVSM_REGISTER_FUNCTION(m,"ismehalfop",chan_kvs_fnc_ismehalfop);
+ KVSM_REGISTER_FUNCTION(m,"ismeop",chan_kvs_fnc_ismeop);
+ KVSM_REGISTER_FUNCTION(m,"ismeadmin",chan_kvs_fnc_ismeadmin);
+ KVSM_REGISTER_FUNCTION(m,"ismeowner",chan_kvs_fnc_ismeowner);
+ KVSM_REGISTER_FUNCTION(m,"isdead",chan_kvs_fnc_isdead);
+ KVSM_REGISTER_FUNCTION(m,"getflag",chan_kvs_fnc_getflag);
+
+ KVSM_REGISTER_FUNCTION(m,"usermodelevel",chan_kvs_fnc_usermodelevel);
+ KVSM_REGISTER_FUNCTION(m,"userjointime",chan_kvs_fnc_userjointime);//
+ KVSM_REGISTER_FUNCTION(m,"userlastactiontime",chan_kvs_fnc_userlastactiontime);
+ KVSM_REGISTER_FUNCTION(m,"mode",chan_kvs_fnc_mode);
+
+ KVSM_REGISTER_FUNCTION(m,"key",chan_kvs_fnc_key);
+ KVSM_REGISTER_FUNCTION(m,"limit",chan_kvs_fnc_limit);
+ KVSM_REGISTER_FUNCTION(m,"users",chan_kvs_fnc_users);
+ KVSM_REGISTER_FUNCTION(m,"bancount",chan_kvs_fnc_bancount);
+ KVSM_REGISTER_FUNCTION(m,"banexceptioncount",chan_kvs_fnc_banexceptioncount);
+ KVSM_REGISTER_FUNCTION(m,"invitecount",chan_kvs_fnc_invitecount);
+ KVSM_REGISTER_FUNCTION(m,"banlist",chan_kvs_fnc_banlist);
+ KVSM_REGISTER_FUNCTION(m,"banexceptionlist",chan_kvs_fnc_banexceptionlist);
+ KVSM_REGISTER_FUNCTION(m,"invitelist",chan_kvs_fnc_invitelist);
+ KVSM_REGISTER_FUNCTION(m,"matchban",chan_kvs_fnc_matchban);
+ KVSM_REGISTER_FUNCTION(m,"matchbanexception",chan_kvs_fnc_matchbanexception);
+ KVSM_REGISTER_FUNCTION(m,"matchinvite",chan_kvs_fnc_matchinvite);
+ KVSM_REGISTER_FUNCTION(m,"getUrl",chan_kvs_fnc_getUrl);
+
+ return true;
+}
+
+static bool chan_module_cleanup(KviModule *m)
+{
+ return true;
+}
+
+
+KVIRC_MODULE(
+ "Chan", // module name
+ "1.0.0", // module version
+ "Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot net)"\
+ " (C) 2002 Juanjo Alvarez (juanjux at yahoo dot es)",
+ "Scripting interface for the channel management",
+ chan_module_init,
+ 0,
+ 0,
+ chan_module_cleanup
+)
diff --git a/src/modules/channelsjoin/Makefile.am b/src/modules/channelsjoin/Makefile.am
new file mode 100644
index 00000000..c9f8a78e
--- /dev/null
+++ b/src/modules/channelsjoin/Makefile.am
@@ -0,0 +1,20 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+################################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkvichannelsjoin.la
+
+libkvichannelsjoin_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkvichannelsjoin_la_SOURCES = libkvichannelsjoin.cpp channelsjoinwindow.cpp
+libkvichannelsjoin_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+noinst_HEADERS= channelsjoinwindow.h
+
+m_%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
+
+channelsjoinwindow.cpp: m_channelsjoinwindow.moc
diff --git a/src/modules/channelsjoin/channelsjoinwindow.cpp b/src/modules/channelsjoin/channelsjoinwindow.cpp
new file mode 100644
index 00000000..5f73b55e
--- /dev/null
+++ b/src/modules/channelsjoin/channelsjoinwindow.cpp
@@ -0,0 +1,301 @@
+//=============================================================================
+//
+// File : channelsjoinwindow.cpp
+// Creation date : Thu Nov 6 2001 12:41:18 by Juanjo �varez
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2003 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the linkss of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) 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.
+//
+//=============================================================================
+
+#include "channelsjoinwindow.h"
+
+#include "kvi_locale.h"
+#include "kvi_options.h"
+#include "kvi_selectors.h"
+#include "kvi_app.h"
+
+#include "kvi_string.h"
+#include "kvi_iconmanager.h"
+#include "kvi_console.h"
+#include "kvi_regchan.h"
+#include "kvi_kvs_script.h"
+
+#include <qlabel.h>
+#include <qlineedit.h>
+#include "kvi_tal_listview.h"
+#include <kvi_tal_groupbox.h>
+#include <qlayout.h>
+#include <qcheckbox.h>
+#include <qpushbutton.h>
+#ifdef COMPILE_USE_QT4
+ #include <q3header.h>
+#else
+ #include <qheader.h>
+#endif
+#include <qevent.h>
+
+extern KviChannelsJoinWindow * g_pChannelsWindow;
+extern QRect g_rectChannelsJoinGeometry;
+// kvi_app.cpp
+extern KVIRC_API KviRegisteredChannelDataBase * g_pRegisteredChannelDataBase;
+
+
+KviChannelsJoinWindow::KviChannelsJoinWindow(QWidget * par, const char * name)
+: QDialog(par,name)
+{
+ m_pConsole=0;
+ setCaption(__tr2qs("Join Channels"));
+
+ setIcon(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CHANNEL)));
+
+ QGridLayout * g = new QGridLayout(this,4,2,4,8);
+
+ m_pListView = new KviTalListView(this);
+ m_pListView->addColumn(__tr2qs("Channel"));
+ m_pListView->setRootIsDecorated(true);
+ m_pListView->setSelectionMode(KviTalListView::Single);
+ g->addMultiCellWidget(m_pListView,0,0,0,1);
+ connect(m_pListView,SIGNAL(clicked(KviTalListViewItem *)),this,SLOT(itemClicked(KviTalListViewItem *)));
+ connect(m_pListView,SIGNAL(doubleClicked(KviTalListViewItem *)),this,SLOT(itemDoubleClicked(KviTalListViewItem *)));
+
+
+ m_pGroupBox = new KviTalGroupBox(2,Qt::Horizontal,__tr2qs("Channel" ),this);
+ QString szMsg = __tr2qs("Name");
+ szMsg.append(":");
+ QLabel * l = new QLabel(szMsg,m_pGroupBox);
+
+ m_pChannelEdit = new QLineEdit(m_pGroupBox);
+ connect(m_pChannelEdit,SIGNAL(returnPressed()), this, SLOT(editReturnPressed()));
+ connect(m_pChannelEdit,SIGNAL(textChanged(const QString &)),this,SLOT(editTextChanged(const QString &)));
+
+ szMsg = __tr2qs("Password");
+ szMsg.append(":");
+ l = new QLabel(szMsg,m_pGroupBox);
+
+ m_pPass = new QLineEdit(m_pGroupBox);
+ m_pPass->setEchoMode(QLineEdit::Password);
+
+ g->addMultiCellWidget(m_pGroupBox,1,1,0,1);
+
+
+ m_pJoinButton = new QPushButton(__tr2qs("&Join"),this);
+ // Join on return pressed
+ m_pJoinButton->setDefault(true);
+ connect(m_pJoinButton,SIGNAL(clicked()),this,SLOT(joinClicked()));
+
+#ifdef COMPILE_USE_QT4
+ g->addMultiCellWidget(m_pJoinButton,2,2,0,1,Qt::AlignHCenter);
+#else
+ g->addMultiCellWidget(m_pJoinButton,2,2,0,1,AlignHCenter);
+#endif
+
+
+ m_pShowAtStartupCheck = new KviStyledCheckBox(__tr2qs("Show this window after connecting"),this);
+ m_pShowAtStartupCheck->setChecked(KVI_OPTION_BOOL(KviOption_boolShowChannelsJoinOnIrc));
+ g->addWidget(m_pShowAtStartupCheck,3,0);
+
+
+ QPushButton * cancelButton = new QPushButton(__tr2qs("Close"),this);
+ connect(cancelButton,SIGNAL(clicked()),this,SLOT(cancelClicked()));
+
+ g->addWidget(cancelButton,3,1);
+
+/*
+ KviTalHBox * hb = new KviTalHBox(this);
+ hb->setSpacing(4);
+
+ QPushButton * namesButton = new QPushButton("/names", hb);
+ connect(namesButton,SIGNAL(clicked()),this,SLOT(namesClicked()));
+ QPushButton * whoButton = new QPushButton("/who", hb);
+ connect(whoButton,SIGNAL(clicked()),this,SLOT(whoClicked()));
+
+ g->addWidget(hb,2,0);
+*/
+
+ g->setRowStretch(0,1);
+ g->setColStretch(0,1);
+
+ fillListView();
+
+ if(g_rectChannelsJoinGeometry.y() < 5)g_rectChannelsJoinGeometry.setY(5);
+
+ resize(g_rectChannelsJoinGeometry.width(),g_rectChannelsJoinGeometry.height());
+ move(g_rectChannelsJoinGeometry.x(),g_rectChannelsJoinGeometry.y());
+
+ enableJoin();
+}
+
+KviChannelsJoinWindow::~KviChannelsJoinWindow()
+{
+ KVI_OPTION_BOOL(KviOption_boolShowChannelsJoinOnIrc) = m_pShowAtStartupCheck->isChecked();
+
+ g_rectChannelsJoinGeometry = QRect(pos().x(),pos().y(),size().width(),size().height());
+ g_pChannelsWindow = 0;
+}
+
+void KviChannelsJoinWindow::setConsole(KviConsole * pConsole)
+{
+ m_pConsole=pConsole;
+ fillListView();
+}
+
+void KviChannelsJoinWindow::fillListView()
+{
+ m_pListView->clear();
+
+ m_pListView->header()->hide();
+
+ KviTalListViewItem * par = new KviTalListViewItem(m_pListView,__tr2qs("Recent Channels"));
+ par->setOpen(true);
+ KviTalListViewItem * chld;
+
+ if(m_pConsole)
+ {
+
+ QStringList* pList=g_pApp->getRecentChannels(m_pConsole->currentNetworkName());
+ if(pList)
+ {
+ for(QStringList::Iterator it = pList->begin(); it != pList->end(); ++it)
+ {
+ chld = new KviTalListViewItem(par,*it);
+ chld->setPixmap(0,*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CHANNEL)));
+ }
+ }
+ }
+
+ // FIXME: Registered channels go here!
+ par = new KviTalListViewItem(m_pListView,__tr2qs("Registered Channels"));
+ par->setOpen(true);
+
+ KviPointerHashTable<const char *,KviRegisteredChannelList> * d = g_pRegisteredChannelDataBase->channelDict();
+ if(d)
+ {
+ KviPointerHashTableIterator<const char *,KviRegisteredChannelList> it(*d);
+ while(it.current())
+ {
+ chld = new KviTalListViewItem(par,it.currentKey());
+ chld->setPixmap(0,*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CHANNEL)));
+ ++it;
+ }
+ }
+
+
+}
+
+void KviChannelsJoinWindow::itemClicked(KviTalListViewItem * it)
+{
+ if(!it)return;
+ if(!it->parent())return;
+ KviStr tmp = it->text(0);
+ m_pChannelEdit->setText(tmp.ptr());
+ enableJoin();
+}
+
+void KviChannelsJoinWindow::itemDoubleClicked(KviTalListViewItem * it)
+{
+ if(!it)return;
+ if(!it->parent())return;
+ KviStr tmp = it->text(0);
+ m_pChannelEdit->setText(tmp.ptr());
+ enableJoin();
+ joinClicked();
+}
+
+
+void KviChannelsJoinWindow::editTextChanged(const QString &)
+{
+ enableJoin();
+}
+
+void KviChannelsJoinWindow::enableJoin()
+{
+ KviStr tmp = m_pChannelEdit->text();
+ KviConsole * c = g_pApp->topmostConnectedConsole();
+ if(c)
+ {
+ if(tmp.isEmpty())
+ m_pJoinButton->setEnabled(false);
+ else
+ m_pJoinButton->setEnabled(true);
+ } else {
+ m_pListView->setEnabled(false);
+ m_pGroupBox->setEnabled(false);
+ m_pJoinButton->setEnabled(false);
+ }
+}
+
+void KviChannelsJoinWindow::cancelClicked()
+{
+ delete this;
+}
+
+void KviChannelsJoinWindow::joinClicked()
+{
+ KviStr pass = m_pPass->text();
+ KviStr tmp = m_pChannelEdit->text();
+
+ if(tmp.isEmpty())return;
+
+ KviStr command(KviStr::Format,"join %s %s",tmp.ptr(),pass.ptr());
+
+ KviConsole * c = g_pApp->topmostConnectedConsole();
+ if(!c)return; // no connection
+ KviWindow * w = g_pActiveWindow;
+ if(w->console() != c)w = c;
+ KviKvsScript::run(command.ptr(),w);
+
+ m_pChannelEdit->setText("");
+ m_pPass->setText("");
+}
+
+/*
+void KviChannelsJoinWindow::whoClicked()
+{
+ KviStr tmp = m_pChannelEdit->text();
+ if(!tmp.isEmpty())doCmd("who", tmp.ptr());
+}
+
+void KviChannelsJoinWindow::namesClicked()
+{
+ KviStr tmp = m_pChannelEdit->text();
+ //FIXME: I must be a nice guy and implement /names in the core...
+ if(!tmp.isEmpty())doCmd("raw names", tmp.ptr());
+}
+
+void KviChannelsJoinWindow::itemDoubleClicked(KviTalListBoxItem * it)
+{
+ if (it == 0)return;
+ KviStr tmp = it->text();
+ doCmd("join", tmp.ptr());
+// if(KVI_OPTION_BOOL(KviOption_boolCloseChannelsJoinAfterJoin))
+// g_pApp->collectGarbage(this);
+}
+*/
+
+void KviChannelsJoinWindow::editReturnPressed()
+{
+ joinClicked();
+}
+
+void KviChannelsJoinWindow::closeEvent(QCloseEvent *e)
+{
+ e->ignore();
+ delete this;
+}
+
+#include "m_channelsjoinwindow.moc"
diff --git a/src/modules/channelsjoin/channelsjoinwindow.h b/src/modules/channelsjoin/channelsjoinwindow.h
new file mode 100644
index 00000000..d0ce62a9
--- /dev/null
+++ b/src/modules/channelsjoin/channelsjoinwindow.h
@@ -0,0 +1,70 @@
+//
+// File : channelsjoinwindow.h
+// Creation date : Thu Nov 06 2001 12:30:25 CEST by Juan Jos��varez
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+#ifndef _CHANNELSJOIN_H_
+#define _CHANNELSJOIN_H_
+#include "kvi_window.h"
+#include "kvi_string.h"
+
+#include <qdialog.h>
+
+class KviConsole;
+class KviTalGroupBox;
+class QPushButton;
+class QLineEdit;
+
+#include "kvi_styled_controls.h"
+#include "kvi_tal_listview.h"
+
+class KviChannelsJoinWindow : public QDialog
+{
+ Q_OBJECT
+public:
+ KviChannelsJoinWindow(QWidget * par, const char * name);
+ ~KviChannelsJoinWindow();
+protected:
+ QLineEdit * m_pChannelEdit;
+ KviTalListView * m_pListView;
+ KviTalGroupBox * m_pGroupBox;
+ QLineEdit * m_pPass;
+ KviStyledCheckBox * m_pShowAtStartupCheck;
+ KviStyledCheckBox * m_pCloseAfterJoinCheck;
+ QPushButton * m_pJoinButton;
+ KviConsole * m_pConsole;
+public:
+ virtual void closeEvent(QCloseEvent *e);
+ void fillListView();
+ void enableJoin();
+ void setConsole(KviConsole * pConsole);
+protected slots:
+ void editTextChanged(const QString &);
+ void itemClicked(KviTalListViewItem *it);
+ void itemDoubleClicked(KviTalListViewItem *it);
+ void editReturnPressed();
+ void cancelClicked();
+ void joinClicked();
+// void whoClicked();
+// void namesClicked();
+};
+
+#endif //_CHANNELSJOINSWINDOW_H_
diff --git a/src/modules/channelsjoin/libkvichannelsjoin.cpp b/src/modules/channelsjoin/libkvichannelsjoin.cpp
new file mode 100644
index 00000000..a2936e8e
--- /dev/null
+++ b/src/modules/channelsjoin/libkvichannelsjoin.cpp
@@ -0,0 +1,108 @@
+//=============================================================================
+//
+// File : libkvichannelsjoin.cpp
+// Creation date : Thu Nov 06 2001 12:30:25 CEST by Juanjo Alvarez
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2005 Juanjo Alvarez
+// Copyright (C) 2001-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+#include "kvi_module.h"
+
+#include "channelsjoinwindow.h"
+#include "kvi_window.h"
+#include "kvi_frame.h"
+#include "kvi_locale.h"
+#include "kvi_config.h"
+
+#include <qsplitter.h>
+
+KviChannelsJoinWindow * g_pChannelsWindow = 0;
+QRect g_rectChannelsJoinGeometry;
+
+/*
+ @doc: channelsjoin.open
+ @type:
+ command
+ @title:
+ channelsjoin.open
+ @short:
+ Opens a window to join channels
+ @syntax:
+ channelsjoin.open
+ @description:
+ Shows a dialog that allows the user to enter channels in a visual manner.[br]
+ This command is exported by the "channelsjoin" module.
+
+*/
+
+static bool channelsjoin_kvs_cmd_open(KviKvsModuleCommandCall * c)
+{
+ if(!g_pChannelsWindow)g_pChannelsWindow = new KviChannelsJoinWindow(c->window()->frame(),"channelsjoin");
+
+ g_pChannelsWindow->setConsole(c->window()->console());
+
+ g_pChannelsWindow->show();
+ g_pChannelsWindow->raise();
+ g_pChannelsWindow->setFocus();
+
+ return true;
+
+
+}
+
+static bool channelsjoin_module_init(KviModule * m)
+{
+ QString fName;
+ m->getDefaultConfigFileName(fName);
+ KviConfig cfg(fName,KviConfig::Read);
+
+ g_rectChannelsJoinGeometry = cfg.readRectEntry("geometry",QRect(30,30,320,410));
+
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"open",channelsjoin_kvs_cmd_open);
+ return true;
+}
+
+static bool channelsjoin_module_cleanup(KviModule *m)
+{
+ QString fName;
+ m->getDefaultConfigFileName(fName);
+ KviConfig cfg(fName,KviConfig::Write);
+
+ cfg.writeEntry("geometry",g_rectChannelsJoinGeometry);
+
+ if (g_pChannelsWindow)delete g_pChannelsWindow;
+ g_pChannelsWindow = 0;
+ return true;
+}
+
+static bool channelsjoin_module_can_unload(KviModule *m)
+{
+ return (!g_pChannelsWindow);
+}
+
+KVIRC_MODULE(
+ "ChannelsJoin",
+ "0.0.3",
+ "Copyright (C) 2001-2006 Juan Jos��varez (juanjux@yahoo.es), Alexey (wizard@opendoor.ru)",
+ "Window to join channels in a GUI",
+ channelsjoin_module_init,
+ channelsjoin_module_can_unload,
+ 0,
+ channelsjoin_module_cleanup
+)
diff --git a/src/modules/clock/Makefile.am b/src/modules/clock/Makefile.am
new file mode 100644
index 00000000..bf0a6816
--- /dev/null
+++ b/src/modules/clock/Makefile.am
@@ -0,0 +1,20 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkviclock.la
+
+libkviclock_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkviclock_la_SOURCES = libkviclock.cpp
+libkviclock_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+noinst_HEADERS= libkviclock.h
+
+%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
+
+libkviclock.cpp: libkviclock.moc
diff --git a/src/modules/clock/libkviclock.cpp b/src/modules/clock/libkviclock.cpp
new file mode 100644
index 00000000..03757b0d
--- /dev/null
+++ b/src/modules/clock/libkviclock.cpp
@@ -0,0 +1,257 @@
+//
+// File : kvi_clock.cpp
+// Creation date : Mon Aug 13 2001 16:34:12 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+#include "libkviclock.h"
+#include "kvi_module.h"
+#include "kvi_console.h"
+#include "kvi_options.h"
+#include "kvi_frame.h"
+#include "kvi_locale.h"
+
+#include "kvi_pointerlist.h"
+#include <qbitmap.h>
+#include <qtooltip.h>
+#include <qpainter.h>
+
+
+
+
+//#include <X11/Xlib.h>
+#include <time.h>
+
+#if 0
+
+
+#warning "Change this XPM to bitmap bits! (And thus use the QBitmap(w,h,bits) constructor)"
+#warning "Support GMT , LOCAL , DATE , ALARM..."
+
+/* XPM */
+static const char * kvi_clock_digits_xpm[] = {
+"234 25 3 1",
+" c None",
+". c #000000",
+"+ c #FFFFFF",
+"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++",
+"+................+++++++++++.......++................++................+...+++++++.......++................++................++................++................++................+++++++++++++++++++++++++++++++++++++++++++++...+++++++",
+"+................+++++++++++.......++...+++++++......++...+++++++......+...+++++++.......++....++++++++++++++....++++++......++...+++++++......++....++++++......++...+++++++......++++++++++++++++++++++++++++++++++++++++++++.....++++++",
+"+....++++++......+++++++++++.......++...+++++++......++...+++++++......+...+++++++.......++....++++++++++++++....++++++......++...+++++++......++....++++++......++...+++++++......++++++++++++++++++++++++++++++++++++++++++++.....++++++",
+"+....++++++......+++++++++++.......++...+++++++......++...+++++++......+...+++++++.......++....++++++++++++++....++++++......++...+++++++......++....++++++......++...+++++++......++++...+++++++++++++++++++++++++++++++++++++.....++++++",
+"+....++++++......+++++++++++.......++...+++++++......++...+++++++......+...+++++++.......++....++++++++++++++....++++++......++...+++++++......++....++++++......++...+++++++......++++...++++++++++++++++++++++++++++++++++++.......+++++",
+"+....++++++......+++++++++++.......++++++++++++......++...+++++++......+...+++++++.......++....++++++++++++++....++++++++++++++...+++++++......++....++++++......++...+++++++......++++...++++..++++++++++++++++++++++++++++++++++++++++++",
+"+....++++++......+++++++++++.......++++++++++++......++++++++++++......+...+++++++.......++....++++++++++++++....++++++++++++++++++++++++......++....++++++......++...+++++++......+++++++++++..+++++++++++++++++++++++++++++++++.++++++++",
+"+....++++++......+++++++++++.......++................+++...............+.................++................++................++++++++++++......++................++...+++++++......+++++++++++..++++++++++++++++++++++++++++++++++++++++++",
+"+....++++++......+++++++++++.......++................+++...............+.................++................++................++++++++++++......++................++................+++++++++++..++++++++++++++++++++++++++++++++++++++++++",
+"+....++++++......+++++++++++.......++...+++++++++++++++++++++++++......+++++++++++.......++++++++++++......++....++++++......++++++++++++......++....++++++......++++++++++++......+++++++++++..++++++++++++++++++++++++++++++++++++++++++",
+"+....++++++......+++++++++++.......++...+++++++++++++++++++++++++......+++++++++++.......++++++++++++......++....++++++......++++++++++++......++....++++++......++++++++++++......++++...++++.......++.......++.......+++++.+++++++++.+++",
+"+....++++++......+++++++++++.......++...+++++++++++++++...+++++++......+++++++++++.......++....++++++......++....++++++......++++++++++++......++....++++++......++++++++++++......++++...++++..+++..++..+.+..++..+++++++++.++.++.++.++.++",
+"+....++++++......+++++++++++.......++...+++++++++++++++...+++++++......+++++++++++.......++....++++++......++....++++++......++++++++++++......++....++++++......++++++++++++......++++...++++..+++..++..+.+..++.......++++.+.++...++.+.++",
+"+....++++++......+++++++++++.......++...+++++++++++++++...+++++++......+++++++++++.......++....++++++......++....++++++......++++++++++++......++....++++++......++++++++++++......+++++++++++..+++..++..+.+..+++++++..++++.+.++...++.+.++",
+"+................+++++++++++.......++................++................+++++++++++.......++................++................++++++++++++......++................++++++++++++......+++++++++++..+++..++..+.+..++..+++..++++.++.++.++.++.++",
+"+................+++++++++++.......++................++................+++++++++++.......++................++................++++++++++++......++................++++++++++++......+++++++++++..+++..++..+.+..++.......+++++.+++++++++.+++",
+"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++",
+"+................++................++................++................++................+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++",
+"+..+...+++.++++..++..+.+.+++.++++..++..+++.+++.+.....++..+++.+++.+.....++..+++.+++.+.....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++",
+"+..+...+.+.+.....++..+.+..+..+.....++..+...+.+.+.....++..+...+.+.+.....++..+...+.+.+.....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++",
+"+..+...+.+.+.....++..+.+..+..+.....++..+...+++.+.....++..+...+++.+.....++..+...+++.+.....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++",
+"+..+...+.+.+.....++..+.+..+..+.....++..+...+.+.+.....++..+...+.+.+.....++..+...+.+.+.....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++",
+"+..+++.+++.++++..++..+++..+..++++..++..+++.+.+.++++..++..+++.+.+.++++..++..+++.+.+.++++..+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++",
+"+................++................++................++................++................+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"};
+
+
+// kvi_app.cpp
+//extern Display * g_display;
+//extern GC g_iccGC;
+extern QPixmap * g_pIccMemBuffer;
+//extern HANDLE g_hIccMemBuffer;
+
+
+static KviPointerList<KviClockDisplay> * g_pClockWidgetList;
+
+static QBitmap * g_pClockBitmap = 0;
+
+
+KviClockDisplay::KviClockDisplay(KviIrcToolBarAppletContainer * pContainer)
+: KviIrcToolBarGraphicalApplet(pContainer,"clock_display")
+{
+ g_pClockWidgetList->append(this);
+
+ for(int i=0;i<6;i++)
+ {
+ m_uDigit[i] = 0;
+ }
+
+ startTimer(1000);
+}
+
+KviClockDisplay::~KviClockDisplay()
+{
+ g_pClockWidgetList->removeRef(this);
+}
+
+void KviClockDisplay::timerEvent(QTimerEvent *e)
+{
+ time_t t = time(0);
+ struct tm * pTm = gmtime(&t);
+
+ m_uDigit[0] = pTm->tm_hour / 10;
+ m_uDigit[1] = pTm->tm_hour % 10;
+ m_uDigit[2] = pTm->tm_min / 10;
+ m_uDigit[3] = pTm->tm_min % 10;
+ m_uDigit[4] = pTm->tm_sec / 10;
+ m_uDigit[5] = pTm->tm_sec % 10;
+
+ update();
+}
+
+
+
+void KviClockDisplay::drawContents(QPainter *p)
+{
+ //XSetLineAttributes(g_display,g_iccGC,1,LineSolid,CapButt,JoinMiter); //need this for line size
+
+
+ //XSetClipMask(g_display,g_iccGC,g_pClockBitmap->handle());
+
+ #define LOW_ROW_Y 6
+
+
+
+#define DRAW_DIGIT(_x,_num,_br) \
+ p->setBrushOrigin(- (m_uDigit[_num] * 18) + _x,LOW_ROW_Y); \
+ p->fillRect(_x,LOW_ROW_Y,18,18,_br);
+
+#define DRAW_DOTS(_x,_br) \
+ p->setBrushOrigin(- 180 + _x,LOW_ROW_Y); \
+ p->fillRect(_x,LOW_ROW_Y,9,18,_br);
+
+ QBrush br1(KVI_OPTION_COLOR(KviOption_colorIrcToolBarAppletForegroundLowContrast),*g_pClockBitmap);
+
+ p->setBrushOrigin(- 216,LOW_ROW_Y);
+ p->fillRect(0,LOW_ROW_Y,18,18,br1);
+
+ p->setBrushOrigin(22,LOW_ROW_Y + 2 /*-18 + LOW_ROW_Y + 20 */);
+ p->fillRect(22,LOW_ROW_Y + 20,18 * 5,7,br1);
+
+ QBrush br2(KVI_OPTION_COLOR(KviOption_colorIrcToolBarAppletForegroundHighContrastActive1),*g_pClockBitmap);
+
+ DRAW_DIGIT(22,0,br2)
+ DRAW_DIGIT(40,1,br2)
+
+ DRAW_DOTS(58,br2)
+
+ DRAW_DIGIT(67,2,br2)
+ DRAW_DIGIT(85,3,br2)
+
+ DRAW_DOTS(103,br2)
+
+ DRAW_DIGIT(112,4,br2)
+ DRAW_DIGIT(130,5,br2)
+
+}
+
+QSize KviClockDisplay::sizeHint() const
+{
+ return QSize(KVI_IRCTOOLBARAPPLET_MAXIMUM_WIDTH,KVI_IRCTOOLBARAPPLET_MAXIMUM_HEIGHT);
+}
+
+
+/*
+ @doc: clock.add
+ @type:
+ command
+ @title:
+ clock.add
+ @short:
+ Adds a Clock applet
+ @syntax:
+ clock.add
+ @description:
+*/
+
+
+
+static bool clock_module_cmd_add(KviModule *m,KviCommand *c)
+{
+ ENTER_STACK_FRAME(c,"clock_module_cmd_add");
+
+ KviStr dummy;
+ if(!g_pUserParser->parseCmdFinalPart(c,dummy))return false;
+
+ KviClockDisplay * dpy = new KviClockDisplay(c->window()->frame()->frameAppletContainer());
+ c->window()->frame()->frameAppletContainer()->addApplet(dpy);
+ dpy->show();
+
+ return c->leaveStackFrame();
+}
+#endif
+
+
+static bool clock_module_init(KviModule *m)
+{
+#if 0
+ g_pClockBitmap = new QBitmap();
+ QPixmap pix(kvi_clock_digits_xpm);
+ *g_pClockBitmap = pix;
+ g_pClockWidgetList = new KviPointerList<KviClockDisplay>;
+ g_pClockWidgetList->setAutoDelete(false);
+ m->registerCommand("add",clock_module_cmd_add);
+#endif
+ return true;
+}
+
+static bool clock_module_cleanup(KviModule *m)
+{
+#if 0
+ while(g_pClockWidgetList->first())
+ {
+ KviClockDisplay * dpy = g_pClockWidgetList->first();
+ dpy->container()->removeApplet(dpy); // deleted path
+ }
+ delete g_pClockWidgetList;
+ delete g_pClockBitmap;
+#endif
+ return true;
+}
+
+static bool clock_module_can_unload(KviModule *m)
+{
+#if 0
+ return g_pClockWidgetList->isEmpty();
+#else
+ return true;
+#endif
+}
+
+KVIRC_MODULE(
+ "Clock", // module name
+ "1.0.0", // module version
+ "Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot net)", // author & (C)
+ "Clock toolbar applet",
+ clock_module_init,
+ clock_module_can_unload,
+ 0,
+ clock_module_cleanup
+)
+#if 0
+#include "libkviclock.moc"
+#endif
diff --git a/src/modules/clock/libkviclock.h b/src/modules/clock/libkviclock.h
new file mode 100644
index 00000000..bf4881a6
--- /dev/null
+++ b/src/modules/clock/libkviclock.h
@@ -0,0 +1,46 @@
+#ifndef _LIBKVICLOCK_H_
+#define _LIBKVICLOCK_H_
+
+//
+// File : kvi_clock.cpp
+// Creation date : Mon Aug 13 2001 16:33:12 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#if 0
+
+#include "kvi_irctoolbar.h"
+
+class KviClockDisplay : public KviIrcToolBarGraphicalApplet
+{
+ Q_OBJECT
+public:
+ KviClockDisplay(KviIrcToolBarAppletContainer * pContainer);
+ ~KviClockDisplay();
+protected:
+ unsigned char m_uDigit[6];
+protected:
+ virtual void drawContents(QPainter * p);
+ virtual QSize sizeHint() const;
+ virtual void timerEvent(QTimerEvent *e);
+};
+
+#endif
+
+#endif
diff --git a/src/modules/codetester/Makefile.am b/src/modules/codetester/Makefile.am
new file mode 100644
index 00000000..37540094
--- /dev/null
+++ b/src/modules/codetester/Makefile.am
@@ -0,0 +1,17 @@
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkvicodetester.la
+
+libkvicodetester_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkvicodetester_la_SOURCES = libkvicodetester.cpp codetester.cpp
+nodist_libkvicodetester_la_SOURCES = moc_codetester.cpp
+
+noinst_HEADERS = codetester.h
+libkvicodetester_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+# noinst_HEADERS=
+
+moc_codetester.cpp: codetester.h
+ $(SS_QT_MOC) $< -o $@
diff --git a/src/modules/codetester/codetester.cpp b/src/modules/codetester/codetester.cpp
new file mode 100644
index 00000000..69a46abc
--- /dev/null
+++ b/src/modules/codetester/codetester.cpp
@@ -0,0 +1,157 @@
+//
+// File : codetester.cpp
+// Creation date : Mon Dec 23 2002 20:28:18 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the linkss of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) 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.
+//
+#include "codetester.h"
+
+#include "kvi_iconmanager.h"
+#include "kvi_options.h"
+#include "kvi_locale.h"
+#include "kvi_config.h"
+#include "kvi_filedialog.h"
+#include "kvi_fileutils.h"
+#include "kvi_scripteditor.h"
+
+#include "kvi_app.h"
+#include "kvi_console.h"
+#include "kvi_parameterlist.h"
+#include "kvi_kvs_script.h"
+#include "kvi_kvs_variantlist.h"
+
+#include <qpushbutton.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qtoolbutton.h>
+#include "kvi_tal_popupmenu.h"
+
+extern KviPointerList<KviCodeTesterWindow> * g_pCodeTesterWindowList;
+
+
+
+
+KviCodeTester::KviCodeTester(QWidget * par)
+: QWidget(par,"code_tester")
+{
+ QGridLayout * g = new QGridLayout(this,2,4,2,2);
+ m_pEditor = KviScriptEditor::createInstance(this);
+ g->addMultiCellWidget(m_pEditor,0,0,0,3);
+ m_pExecuteButton = new QPushButton(__tr2qs("&Execute"),this);
+ g->addWidget(m_pExecuteButton,1,3);
+ connect(m_pExecuteButton,SIGNAL(clicked()),this,SLOT(execute()));
+
+ m_pModeLabel = new QLabel(__tr("Params:"),this);
+ g->addWidget(m_pModeLabel,1,1);
+ m_pParams = new QLineEdit(this);
+ g->addWidget(m_pParams,1,2);
+}
+
+KviCodeTester::~KviCodeTester()
+{
+ KviScriptEditor::destroyInstance(m_pEditor);
+}
+
+//#warning "Allow to bind the command to a specified window"
+
+void KviCodeTester::execute()
+{
+ QString parms = m_pParams->text();
+ QString buffer;
+ m_pEditor->getText(buffer);
+ KviConsole * con = g_pApp->activeConsole();
+ //KviParameterList * l = new KviParameterList(parms.ptr());
+ KviKvsScript::run(buffer,con,new KviKvsVariantList(new QString(parms)));
+}
+
+KviCodeTesterWindow::KviCodeTesterWindow(KviFrame * lpFrm)
+: KviWindow(KVI_WINDOW_TYPE_SCRIPTEDITOR,lpFrm,"codetester",0)
+{
+ g_pCodeTesterWindowList->append(this);
+
+ m_pTester = new KviCodeTester(this);
+}
+
+KviCodeTesterWindow::~KviCodeTesterWindow()
+{
+ g_pCodeTesterWindowList->removeRef(this);
+}
+
+QPixmap * KviCodeTesterWindow::myIconPtr()
+{
+ return g_pIconManager->getSmallIcon(KVI_SMALLICON_BOMB);
+}
+
+void KviCodeTesterWindow::resizeEvent(QResizeEvent *e)
+{
+ m_pTester->setGeometry(0,0,width(),height());
+}
+
+void KviCodeTesterWindow::fillCaptionBuffers()
+{
+ m_szPlainTextCaption = __tr2qs("Script Tester");
+
+ static QString p1("<nobr><font color=\"");
+ static QString p2("\"><b>");
+ static QString p3("</b></font></nobr>");
+
+ m_szHtmlActiveCaption = p1;
+ m_szHtmlActiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextActive).name();
+ m_szHtmlActiveCaption += p2;
+ m_szHtmlActiveCaption += m_szPlainTextCaption;
+ m_szHtmlActiveCaption += p3;
+
+ m_szHtmlInactiveCaption = p1;
+ m_szHtmlInactiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextInactive).name();
+ m_szHtmlInactiveCaption += p2;
+ m_szHtmlInactiveCaption += m_szPlainTextCaption;
+ m_szHtmlInactiveCaption += p3;
+}
+
+
+void KviCodeTesterWindow::getConfigGroupName(KviStr &szName)
+{
+ szName = "codetester";
+}
+
+
+void KviCodeTesterWindow::saveProperties(KviConfig *cfg)
+{
+/*
+#ifdef COMPILE_SCRIPTTOOLBAR
+ cfg->writeEntry("Sizes",m_pEditor->sizes());
+ cfg->writeEntry("LastRaw",m_pEditor->lastEditedRaw().ptr());
+ //debug("LAST EDITED=%s",m_pEditor->lastEditedRaw().ptr());
+#endif // COMPILE_SCRIPTTOOLBAR
+*/
+}
+
+void KviCodeTesterWindow::loadProperties(KviConfig *cfg)
+{
+/*
+#ifdef COMPILE_SCRIPTTOOLBAR
+ QValueList<int> def;
+ def.append(20);
+ def.append(80);
+ m_pEditor->setSizes(cfg->readIntListEntry("Sizes",def));
+ KviStr tmp = cfg->readEntry("LastRaw","");
+ m_pEditor->editRaw(tmp);
+ //debug("LAST EDITED WAS %s",tmp.ptr());
+#endif // COMPILE_SCRIPTTOOLBAR
+*/
+}
diff --git a/src/modules/codetester/codetester.h b/src/modules/codetester/codetester.h
new file mode 100644
index 00000000..ce24ca5d
--- /dev/null
+++ b/src/modules/codetester/codetester.h
@@ -0,0 +1,67 @@
+#ifndef _CODETESTER_H_
+#define _CODETESTER_H_
+//
+// File : eventeditor.h
+// Creation date : Mon Dec 23 2002 20:24:55 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the linkss of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) 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.
+//
+
+#include "kvi_window.h"
+#include "kvi_string.h"
+
+#include <qlineedit.h>
+
+class QPushButton;
+class QLabel;
+
+class KviScriptEditor;
+
+class KviCodeTester : public QWidget
+{
+ Q_OBJECT
+public:
+ KviCodeTester(QWidget * par);
+ ~KviCodeTester();
+private:
+ KviScriptEditor * m_pEditor;
+ QLineEdit * m_pParams;
+ QPushButton * m_pExecuteButton;
+ QLabel * m_pModeLabel;
+private slots:
+ void execute();
+};
+
+class KviCodeTesterWindow : public KviWindow
+{
+ Q_OBJECT
+public:
+ KviCodeTesterWindow(KviFrame * lpFrm);
+ ~KviCodeTesterWindow();
+protected:
+ KviCodeTester * m_pTester;
+protected:
+ virtual QPixmap * myIconPtr();
+ virtual void fillCaptionBuffers();
+ virtual void resizeEvent(QResizeEvent *e);
+ virtual void getConfigGroupName(KviStr &szName);
+ virtual void saveProperties(KviConfig *);
+ virtual void loadProperties(KviConfig *);
+};
+
+#endif //_CODETESTER_H_
diff --git a/src/modules/codetester/libkvicodetester.cpp b/src/modules/codetester/libkvicodetester.cpp
new file mode 100644
index 00000000..ec84a217
--- /dev/null
+++ b/src/modules/codetester/libkvicodetester.cpp
@@ -0,0 +1,89 @@
+//===============================================================================
+//
+// File : libkvicodetester.cpp
+// Creation date : Mon 23 Dec 2002 20:23:59 2002 GMT by Szymon Stefanek
+//
+// This toolbar is part of the KVirc irc client distribution
+// Copyright (C) 2002-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//===============================================================================
+
+#include "kvi_module.h"
+#include "kvi_locale.h"
+#include "kvi_frame.h"
+#include "kvi_pointerlist.h"
+
+#include "codetester.h"
+
+KviPointerList<KviCodeTesterWindow> * g_pCodeTesterWindowList = 0;
+
+
+/*
+ @doc: codetester.open
+ @type:
+ command
+ @title:
+ codetester.open
+ @short:
+ Shows the code tester window
+ @syntax:
+ codetester.open
+ @description:
+ Opens a new code tester window
+*/
+
+static bool codetester_kvs_cmd_open(KviKvsModuleCommandCall * c)
+{
+ KviCodeTesterWindow * w = new KviCodeTesterWindow(c->window()->frame());
+ c->window()->frame()->addWindow(w);
+ w->setFocus();
+ return true;
+}
+
+static bool codetester_module_init(KviModule * m)
+{
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"open",codetester_kvs_cmd_open);
+
+ g_pCodeTesterWindowList = new KviPointerList<KviCodeTesterWindow>();
+ g_pCodeTesterWindowList->setAutoDelete(false);
+ return true;
+}
+
+static bool codetester_module_can_unload(KviModule * m)
+{
+ return (g_pCodeTesterWindowList->count() == 0);
+}
+
+static bool codetester_module_cleanup(KviModule *m)
+{
+ while(KviCodeTesterWindow * w = g_pCodeTesterWindowList->first())
+ {
+ w->close(); // deleted path!
+ }
+ return true;
+}
+
+KVIRC_MODULE(
+ "CodeTester", // module name
+ "1.0.0", // module version
+ "Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot net)", // author & (C)
+ "Code tester window",
+ codetester_module_init,
+ codetester_module_can_unload,
+ 0,
+ codetester_module_cleanup
+)
diff --git a/src/modules/config/Makefile.am b/src/modules/config/Makefile.am
new file mode 100644
index 00000000..1a43c2e9
--- /dev/null
+++ b/src/modules/config/Makefile.am
@@ -0,0 +1,18 @@
+###############################################################################
+# KVirc IRC client Makefile - 31.01.2002 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkviconfig.la
+
+libkviconfig_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkviconfig_la_SOURCES = libkviconfig.cpp
+libkviconfig_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+# noinst_HEADERS=
+
+%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
diff --git a/src/modules/config/libkviconfig.cpp b/src/modules/config/libkviconfig.cpp
new file mode 100644
index 00000000..854c321b
--- /dev/null
+++ b/src/modules/config/libkviconfig.cpp
@@ -0,0 +1,877 @@
+//=============================================================================
+//
+// File : libkviconfig.cpp
+// Creation date : Thu Jan 31 2002 22:50:12 GMT by Szymon Stefanek
+//
+// This config is part of the KVirc irc client distribution
+// Copyright (C) 2002-2005 Szymon Stefanek (pragma@kvirc.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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_module.h"
+#include "kvi_string.h"
+#include "kvi_config.h"
+#include "kvi_fileutils.h"
+#include "kvi_app.h"
+#include "kvi_locale.h"
+
+#include "kvi_pointerhashtable.h"
+
+static KviPointerHashTable<QString,KviConfig> * g_pConfigDict = 0;
+static int g_iNextConfigId = 0;
+
+/*
+ @doc: config.open
+ @type:
+ function
+ @title:
+ $config.open
+ @short:
+ Opens a config file
+ @syntax:
+ $config.open(<filename:string>[,<flags:string>])
+ @description:
+ Opens a config file.
+ If the file already exists , its contents
+ are parsed and available for extracting by the [fnc]$config.read[/fnc]() function.[br]
+ <filename> may be an absolute path or a relative path: if a relative path is used,
+ KVIrc will complete it with a local kvirc directory suitable for writing script config files.[br]
+ If the config file doesn't exist , it is opened as empty config file.[br]
+ Flags can contain a combination of letters 'r' and 'w'.[br]
+ If only 'r' is specified , the config file is opened in "read-only" mode: no changes will be written to disk.[br]
+ If only 'w' is specified , the config file is opened in "write-only" mode: the contents of the file on disk
+ are not readed.[br]
+ If <flags> are not specified then 'rw' is assumed.[br]
+ The function returns an identifier for the open config file. This identifier
+ is a mandatory parameter in all the other config.* functions and commands.[br]
+ The config section is set to the default section name: you can change it by using
+ [cmd]config.setsection[/cmd].[br]
+ After you have finished using the file , don't forget to call [cmd]config.close[/cmd]!
+ KVIrc tries to not open a config file twice: if the file was already opened then
+ the identifier of the open file is returned.[br]
+ You can check if a config file is already open by using the
+ [fnc]$config.id[/fnc]() function.[br]
+ @examples:
+ [example]
+ # It is a good idea to store the returned id to a variable :)
+ %cfg = $config.open(myscript.kvc)
+ %num = [fnc]$config.read[/fnc](%cfg,Number,0)
+ [cmd]echo[/cmd] Number of entries is %num
+ %num++;
+ [cmd]config.write[/cmd] %cfg Number %num
+ [cmd]config.close[/cmd] %cfg
+ [/example]
+ @seealso:
+ [module:config]Config module documentation[/module]
+*/
+
+
+static bool config_kvs_fnc_open(KviKvsModuleFunctionCall * c)
+{
+ QString szFile;
+ QString szMode;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("filename",KVS_PT_STRING,0,szFile)
+ KVSM_PARAMETER("mode",KVS_PT_STRING,KVS_PF_OPTIONAL,szMode)
+ KVSM_PARAMETERS_END(c)
+
+ KviConfig::FileMode fileMode;
+
+ if(szMode.contains('r'))
+ {
+ if(szMode.contains('w'))fileMode = KviConfig::ReadWrite;
+ else fileMode = KviConfig::Read;
+ } else {
+ if(szMode.contains('w'))fileMode = KviConfig::Write;
+ else fileMode = KviConfig::ReadWrite;
+ }
+
+ KviFileUtils::adjustFilePath(szFile);
+ QString szAbsFile;
+
+ if(KviFileUtils::isAbsolutePath(szFile))szAbsFile = szFile;
+ else g_pApp->getLocalKvircDirectory(szAbsFile,KviApp::ConfigScripts,szFile,true);
+
+ KviPointerHashTableIterator<QString,KviConfig> it(*g_pConfigDict);
+ while(it.current())
+ {
+ if(KviQString::equalCI(it.current()->fileName(),szAbsFile))
+ {
+ c->returnValue()->setString(it.currentKey());
+ if(it.current()->readOnly() && (fileMode & KviConfig::Write))
+ {
+ it.current()->setReadOnly(false);
+ }
+ return true;
+ }
+ ++it;
+ }
+
+ KviConfig * cfg = new KviConfig(szAbsFile,fileMode);
+ g_iNextConfigId++;
+ QString tmp = QString("%1").arg(g_iNextConfigId);
+ g_pConfigDict->insert(tmp,cfg);
+ c->returnValue()->setString(tmp);
+ return true;
+}
+
+/*
+ @doc: config.id
+ @type:
+ function
+ @title:
+ $config.id
+ @short:
+ Returns the id of an open config file
+ @syntax:
+ $config.id(<filename>)
+ @description:
+ Returns the id of an open config file specified by <filename>.[br]
+ (This is the same id that is returned by [fnc]$config.open[/fnc].[br]
+ If no such file is open, 0 is returned (that is an invalid config identifier).[br]
+ @seealso:
+ [module:config]Config module documentation[/module]
+*/
+
+static bool config_kvs_fnc_id(KviKvsModuleFunctionCall * c)
+{
+ QString szFile;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("file",KVS_PT_STRING,0,szFile)
+ KVSM_PARAMETERS_END(c)
+
+ KviFileUtils::adjustFilePath(szFile);
+
+ QString szAbsFile;
+
+ if(KviFileUtils::isAbsolutePath(szFile))szAbsFile = szFile;
+ else g_pApp->getLocalKvircDirectory(szAbsFile,KviApp::ConfigScripts,szFile,true);
+
+ KviPointerHashTableIterator<QString,KviConfig> it(*g_pConfigDict);
+ while(it.current())
+ {
+ if(KviQString::equalCI(it.current()->fileName(),szAbsFile))
+ {
+ c->returnValue()->setString(it.currentKey());
+ return true;
+ }
+ ++it;
+ }
+
+ c->returnValue()->setString("0");
+
+ return true;
+}
+
+/*
+ @doc: config.read
+ @type:
+ function
+ @title:
+ $config.read
+ @short:
+ Reads an entry from a config file
+ @syntax:
+ $config.read(<id:string>,<key:string>[,<default:string>])
+ @description:
+ Reads and returns the value associated to <key> in the current section of the config
+ file identified by <id>.[br]
+ <id> must be a valid config identifier returned by [fnc]$config.open[/fnc]()
+ If no value is associated with <key> in the current section the return value
+ is an empty string or the string <default> if it has been passed.[br]
+ @seealso:
+ [module:config]Config module documentation[/module]
+*/
+
+static bool config_kvs_fnc_read(KviKvsModuleFunctionCall * c)
+{
+ QString szId;
+ QString szKey;
+ QString szDefault;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("id",KVS_PT_STRING,0,szId)
+ KVSM_PARAMETER("key",KVS_PT_STRING,0,szKey)
+ KVSM_PARAMETER("default",KVS_PT_STRING,KVS_PF_OPTIONAL,szDefault)
+ KVSM_PARAMETERS_END(c)
+
+ KviConfig * cfg = g_pConfigDict->find(szId);
+
+ if(cfg)
+ {
+ c->returnValue()->setString(cfg->readEntry(szKey,szDefault));
+ } else {
+ c->warning(__tr2qs("The config file with id '%Q' is not open"),&szId);
+ }
+ return true;
+}
+
+/*
+ @doc: config.section
+ @type:
+ function
+ @title:
+ $config.section
+ @short:
+ Returns the name of the current section of a config file
+ @syntax:
+ $config.section(<id>)
+ @description:
+ Returns the name of the current section in the config file identifier by <id>.[br]
+ <id> must be a valid config identifier returned by [fnc]$config.open[/fnc]()
+ @seealso:
+ [module:config]Config module documentation[/module]
+*/
+
+static bool config_kvs_fnc_section(KviKvsModuleFunctionCall * c)
+{
+ QString szId;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("id",KVS_PT_STRING,0,szId)
+ KVSM_PARAMETERS_END(c)
+
+ KviConfig * cfg = g_pConfigDict->find(szId);
+
+ if(cfg)
+ {
+ c->returnValue()->setString(cfg->group());
+ } else {
+ c->warning(__tr2qs("The config file with id '%Q' is not open"),&szId);
+ }
+ return true;
+}
+
+/*
+ @doc: config.readonly
+ @type:
+ function
+ @title:
+ $config.readonly
+ @short:
+ Checks wheter a config file is opened in readonly mode
+ @syntax:
+ $config.readonly(<id>)
+ @description:
+ Returns 1 if the config file identified by <id> is opened in readonly mode,
+ 0 otherwise.[br]
+ <id> must be a valid config identifier returned by [fnc]$config.open[/fnc]()
+ If <id> does not identify an open config file, a warning is printed and 0 is returned.[br]
+ @seealso:
+ [module:config]Config module documentation[/module]
+*/
+
+static bool config_kvs_fnc_readonly(KviKvsModuleFunctionCall * c)
+{
+ QString szId;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("id",KVS_PT_STRING,0,szId)
+ KVSM_PARAMETERS_END(c)
+
+ KviConfig * cfg = g_pConfigDict->find(szId);
+
+ if(cfg)
+ {
+ c->returnValue()->setBoolean(cfg->readOnly());
+ } else {
+ c->warning(__tr2qs("The config file with id '%Q' is not open"),&szId);
+ c->returnValue()->setInteger(false);
+ }
+ return true;
+}
+
+/*
+ @doc: config.filename
+ @type:
+ function
+ @title:
+ $config.filename
+ @short:
+ Returns the filename of an open config file
+ @syntax:
+ $config.filename(<id>)
+ @description:
+ Returns the filename of the [b]open[/b] config file identifier by <id>.[br]
+ <id> must be a valid config identifier returned by [fnc]$config.open[/fnc]()
+ If the <id> doesn't match any open file, and empty string is returned.[br]
+ @seealso:
+ [module:config]Config module documentation[/module]
+*/
+
+static bool config_kvs_fnc_filename(KviKvsModuleFunctionCall * c)
+{
+ QString szId;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("id",KVS_PT_STRING,0,szId)
+ KVSM_PARAMETERS_END(c)
+
+ KviConfig * cfg = g_pConfigDict->find(szId);
+
+ if(cfg)
+ {
+ c->returnValue()->setString(cfg->fileName());
+ }
+ return true;
+}
+
+/*
+ @doc: config.hassection
+ @type:
+ function
+ @title:
+ $config.hassection
+ @short:
+ Checks wheter a section is present in a config file
+ @syntax:
+ $config.hassection(<id>,<section_name>)
+ @description:
+ Returns 1 if the section <section_name> exists in the config file identifier by <id>,
+ 0 otherwise.[br]
+ <id> must be a valid config identifier returned by [fnc]$config.open[/fnc]()
+ @seealso:
+ [module:config]Config module documentation[/module]
+*/
+
+static bool config_kvs_fnc_hassection(KviKvsModuleFunctionCall * c)
+{
+ QString szId;
+ QString szSect;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("id",KVS_PT_STRING,0,szId)
+ KVSM_PARAMETER("id",KVS_PT_STRING,0,szSect)
+ KVSM_PARAMETERS_END(c)
+
+ KviConfig * cfg = g_pConfigDict->find(szId);
+
+ if(cfg)
+ {
+ c->returnValue()->setBoolean(cfg->hasGroup(szSect));
+ } else {
+ c->warning(__tr2qs("The config file with id '%Q' is not open"),&szId);
+ }
+ return true;
+}
+
+/*
+ @doc: config.sectionlist
+ @type:
+ function
+ @title:
+ $config.sectionlist
+ @short:
+ Returns a list of the sections in a config file
+ @syntax:
+ $config.sectionlist(<id>)
+ @description:
+ Returns an array of sections present in the config file identified by <id>.[br]
+ <id> must be a valid config identifier returned by [fnc]$config.open[/fnc]()
+ @seealso:
+ [module:config]Config module documentation[/module]
+*/
+
+static bool config_kvs_fnc_sectionlist(KviKvsModuleFunctionCall * c)
+{
+ QString szId;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("id",KVS_PT_STRING,0,szId)
+ KVSM_PARAMETERS_END(c)
+
+ KviConfig * cfg = g_pConfigDict->find(szId);
+
+ if(cfg)
+ {
+ KviConfigIterator it(*(cfg->dict()));
+ KviKvsArray* pArray = new KviKvsArray();
+ int id=0;
+ while(it.current())
+ {
+ pArray->set(id++, new KviKvsVariant(it.currentKey()));
+ ++it;
+ }
+ c->returnValue()->setArray(pArray);
+ } else {
+ c->warning(__tr2qs("The config file with id '%Q' is not open"),&szId);
+ }
+ return true;
+}
+
+/*
+ @doc: config.keylist
+ @type:
+ function
+ @title:
+ $config.keylist
+ @short:
+ Returns a list of keys in a config file
+ @syntax:
+ $config.keylist(<id>)
+ @description:
+ Returns an array of keys present in the current section of the config file identified by <id>.[br]
+ <id> must be a valid config identifier returned by [fnc]$config.open[/fnc]()
+ @seealso:
+ [module:config]Config module documentation[/module]
+*/
+
+static bool config_kvs_fnc_keylist(KviKvsModuleFunctionCall * c)
+{
+ QString szId;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("id",KVS_PT_STRING,0,szId)
+ KVSM_PARAMETERS_END(c)
+
+ KviConfig * cfg = g_pConfigDict->find(szId);
+
+ if(cfg)
+ {
+ KviConfigGroup * d = cfg->dict()->find(cfg->group());
+ if(!d)return true;
+
+ KviConfigGroupIterator it(*d);
+
+ KviKvsArray* pArray = new KviKvsArray();
+ int id=0;
+
+ while(it.current())
+ {
+ pArray->set(id++, new KviKvsVariant(it.currentKey()));
+ ++it;
+ }
+ c->returnValue()->setArray(pArray);
+ } else {
+ c->warning(__tr2qs("The config file with id '%Q' is not open"),&szId);
+ }
+ return true;
+}
+
+/*
+ @doc: config.filelist
+ @type:
+ function
+ @title:
+ $config.filelist
+ @short:
+ Returns a list of open config files
+ @syntax:
+ $config.filelist
+ @description:
+ Returns an array of open config files.[br]
+ @seealso:
+ [module:config]Config module documentation[/module]
+*/
+
+static bool config_kvs_fnc_filelist(KviKvsModuleFunctionCall * c)
+{
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETERS_END(c)
+
+ KviKvsArray* pArray = new KviKvsArray();
+ int id=0;
+
+ KviPointerHashTableIterator<QString,KviConfig> it(*g_pConfigDict);
+ while(it.current())
+ {
+ pArray->set(id++, new KviKvsVariant(it.currentKey()));
+ ++it;
+ }
+ c->returnValue()->setArray(pArray);
+ return true;
+}
+
+/*
+ @doc: config.close
+ @type:
+ command
+ @title:
+ config.close
+ @keyterms:
+ storing & reading configuration entries
+ @short:
+ Closes a config file
+ @syntax:
+ config.close [-q] <id>
+ @description:
+ Closes the config file identified by <id>.[br]
+ <id> must be a a valid config file identifier returned by [fnc]$config.open[/fnc].[br]
+ If the config file was opened as read-write (default), the changes will be stored
+ to disk. If the config was opened as read-only , changes will not be written.[br]
+ If the <id> does not match any open config file, a warning is printed unless
+ the -q switch is used.[br]
+ @seealso:
+ [module:config]Config module documentation[/module]
+*/
+
+static bool config_kvs_cmd_close(KviKvsModuleCommandCall * c)
+{
+ QString szId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("id",KVS_PT_STRING,0,szId)
+ KVSM_PARAMETERS_END(c)
+
+ KviConfig * cfg = g_pConfigDict->find(szId);
+
+ if(cfg)
+ {
+ if(cfg->dirty() && cfg->readOnly())
+ {
+ if(!c->hasSwitch('q',"quiet"))
+ c->warning(__tr2qs("The config file '%Q' has been changed but is opened as read-only: changes will be lost"),&cfg->fileName());
+ }
+ g_pConfigDict->remove(szId);
+ } else {
+ if(!c->hasSwitch('q',"quiet"))
+ c->warning(__tr2qs("The config file with id '%Q' is not open"),&szId);
+ }
+
+ return true;
+}
+
+/*
+ @doc: config.flush
+ @type:
+ command
+ @title:
+ config.flush
+ @keyterms:
+ storing & reading configuration entries
+ @short:
+ Flushes a config file
+ @syntax:
+ config.flush <id>
+ @description:
+ Flushes the config file identified by <id>.[br]
+ <id> must be a a valid config file identifier returned by [fnc]$config.open[/fnc].[br]
+ If the config file was opened as read-write (default), the changes will be stored
+ to disk. If the config was opened as read-only ,an error is printed.[br]
+ If the <id> does not match any open config file, a warning is printed.
+ @seealso:
+ [module:config]Config module documentation[/module]
+*/
+
+static bool config_kvs_cmd_flush(KviKvsModuleCommandCall * c)
+{
+ QString szId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("id",KVS_PT_STRING,0,szId)
+ KVSM_PARAMETERS_END(c)
+
+ KviConfig * cfg = g_pConfigDict->find(szId);
+
+ if(cfg)
+ {
+ if(cfg->readOnly())
+ c->warning(__tr2qs("The config file with id '%Q' is read only"),&szId);
+ else
+ cfg->sync();
+ } else {
+ c->warning(__tr2qs("The config file with id '%Q' is not open"),&szId);
+ }
+
+ return true;
+}
+
+/*
+ @doc: config.clear
+ @type:
+ command
+ @title:
+ config.clear
+ @keyterms:
+ storing & reading configuration entries
+ @short:
+ Clears a config file
+ @syntax:
+ config.clear <id>
+ @description:
+ Clears the contents of the config file identified by <id>.[br]
+ All the sections are removed (except for the default section) and all the key=value
+ pairs are destroyed.[br]
+ <id> must be a a valid config file identifier returned by [fnc]$config.open[/fnc].[br]
+ If the <id> does not match any open config file, a warning is printed.
+ @seealso:
+ [module:config]Config module documentation[/module]
+*/
+
+static bool config_kvs_cmd_clear(KviKvsModuleCommandCall * c)
+{
+ QString szId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("id",KVS_PT_STRING,0,szId)
+ KVSM_PARAMETERS_END(c)
+
+ KviConfig * cfg = g_pConfigDict->find(szId);
+
+ if(cfg)
+ {
+ cfg->clear();
+ } else {
+ c->warning(__tr2qs("The config file with id '%Q' is not open"),&szId);
+ }
+
+ return true;
+}
+
+/*
+ @doc: config.clearsection
+ @type:
+ command
+ @title:
+ config.clearsection
+ @keyterms:
+ storing & reading configuration entries
+ @short:
+ Clears a section in a config file
+ @syntax:
+ config.clearsection <id> <section_name>
+ @description:
+ Clears the contents of the section <section_name> in the config file identified by <id>.[br]
+ All the key=value pairs in the section are destroyed.[br]
+ <id> must be a a valid config file identifier returned by [fnc]$config.open[/fnc].[br]
+ If the <id> does not match any open config file, a warning is printed.
+ If <section_name> was also the current section, the current section is set to the default one.[br]
+ No warning is printed if the section wasn't existing.[br]
+ @seealso:
+ [module:config]Config module documentation[/module]
+*/
+
+static bool config_kvs_cmd_clearsection(KviKvsModuleCommandCall * c)
+{
+ QString szId;
+ QString szSect;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("id",KVS_PT_STRING,0,szId)
+ KVSM_PARAMETER("section",KVS_PT_STRING,0,szSect)
+ KVSM_PARAMETERS_END(c)
+
+ KviConfig * cfg = g_pConfigDict->find(szId);
+
+ if(cfg)
+ {
+ cfg->clearGroup(szSect);
+ } else {
+ c->warning(__tr2qs("The config file with id '%Q' is not open"),&szId);
+ }
+
+ return true;
+}
+
+/*
+ @doc: config.write
+ @type:
+ command
+ @title:
+ config.write
+ @keyterms:
+ storing & reading configuration entries
+ @short:
+ Writes a data field to a config file
+ @syntax:
+ config.write <id> <key> <value>
+ @description:
+ Writes the <key>=<value> pair to the config file identifier by <id>.[br]
+ <id> must be a valid config file id returned by [fnc]$config.open[/fnc]().[br]
+ <key> and <value> can be any strings.[br]
+ The <key>=<value> pair is written in the current section of the config file.[br]
+ If <key> already exists in the current section of the config , the corresponding value is replaced with <value>.[br]
+ If <value> is an empty string, the <key> is simply removed from the current section.[br]
+ If a section remains empty (with no keys) at file write time, that section will be removed.[br]
+ The changes are NOT written to disk: you must call [cmd]config.flush[/cmd] or (better) [cmd]config.close[/cmd]
+ for the changes to be effectively written.[br]
+ @seealso:
+ [module:config]Config module documentation[/module]
+*/
+
+static bool config_kvs_cmd_write(KviKvsModuleCommandCall * c)
+{
+ QString szId;
+ QString szKey;
+ QString szVal;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("id",KVS_PT_STRING,0,szId)
+ KVSM_PARAMETER("key",KVS_PT_STRING,0,szKey)
+ KVSM_PARAMETER("value",KVS_PT_STRING,0,szVal)
+ KVSM_PARAMETERS_END(c)
+
+ KviConfig * cfg = g_pConfigDict->find(szId);
+
+ if(cfg)
+ {
+ cfg->writeEntry(szKey,szVal);
+ } else {
+ c->warning(__tr2qs("The config file with id '%Q' is not open"),&szId);
+ }
+
+ return true;
+}
+
+/*
+ @doc: config.setsection
+ @type:
+ command
+ @title:
+ config.setsection
+ @keyterms:
+ storing & reading configuration entries
+ @short:
+ Changes the current section of a config file
+ @syntax:
+ config.setsection <id> <section_name>
+ @description:
+ Changes the current section of the config file <id> to <section_name>.[br]
+ Sections are effectively namespaces for the keys: each section can contain
+ a set of keys and equal keys in different sections do not collide.[br]
+ <id> must be a valid config file id returned by [fnc]$config.open[/fnc]().[br]
+ @seealso:
+ [module:config]Config module documentation[/module]
+*/
+
+static bool config_kvs_cmd_setsection(KviKvsModuleCommandCall * c)
+{
+ QString szId;
+ QString szSect;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("id",KVS_PT_STRING,0,szId)
+ KVSM_PARAMETER("section",KVS_PT_STRING,0,szSect)
+ KVSM_PARAMETERS_END(c)
+
+ KviConfig * cfg = g_pConfigDict->find(szId);
+
+ if(cfg)
+ {
+ cfg->setGroup(szSect);
+ } else {
+ c->warning(__tr2qs("The config file with id '%Q' is not open"),&szId);
+ }
+
+ return true;
+}
+
+/*
+ @doc: config
+ @type:
+ module
+ @short:
+ Managing of configuration files
+ @title:
+ The config module
+ @body:
+ The config module is a powerful interface that manages text configuration files.[br]
+ The files are arranged in named sections and the data is stored in key=value pairs
+ belonging to each section.[br]
+ [br]
+ [section1_name][br]
+ <key1>=<value1>[br]
+ <key2>=<value2>[br]
+ <key3>=<value3>[br]
+ ....[br]
+ [section2_name][br]
+ <key1>=<value1>[br]
+ ....[br]
+ [br]
+ Keys and values are plain text strings. Eventual newlines in values are encoded using
+ a simple hexadecimal notation.[br]
+ The config files can be also edited by using any text editor.[br]
+ The config module works on config files loaded in memory. For this reason,
+ you must first open a config file by the means of [fnc]$config.open[/fnc]().[br]
+ Once you open the file , if it exists on disk , its contents are loaded into memory
+ and you can access the data stored in it. If the file wasn't existing, and empty
+ memory config file is created.[br]
+ The config file is opened in read-write mode by default. You can also choose
+ the "read-only" method: a read-only config file is never flushed to disk (but you can
+ set the values in memory!).[br]
+ It is not a good idea to keep a config file open forever: a good approach
+ is to keep settings in memory variables and write them all at once when it comes to
+ write settings: you open the config file , write all your values and close the file.[br]
+ You can obviously keep the config file open for some time but remember that
+ no change is written to the disk until [cmd]config.flush[/cmd] or [cmd]config.close[/cmd] is called.[br]
+ You write entries by using [cmd]config.write[/cmd] and read them by using [fnc]$config.read[/fnc]().[br]
+ You can change the "current" config section by using [cmd]config.setsection[/cmd].[br]
+ Here comes a complete list of commands and functions exported by this module:[br]
+ [fnc]$config.open[/fnc][br]
+ [fnc]$config.read[/fnc][br]
+ [fnc]$config.section[/fnc][br]
+ [fnc]$config.hassection[/fnc][br]
+ [fnc]$config.sectionlist[/fnc][br]
+ [fnc]$config.keylist[/fnc][br]
+ [fnc]$config.filelist[/fnc][br]
+ [fnc]$config.filename[/fnc][br]
+ [fnc]$config.id[/fnc][br]
+ [fnc]$config.readonly[/fnc][br]
+ [cmd]config.close[/cmd][br]
+ [cmd]config.flush[/cmd][br]
+ [cmd]config.clear[/cmd][br]
+ [cmd]config.clearsection[/cmd][br]
+ [cmd]config.setsection[/cmd][br]
+ [cmd]config.write[/cmd][br]
+*/
+
+static bool config_module_init(KviModule * m)
+{
+ g_pConfigDict = new KviPointerHashTable<QString,KviConfig>;
+ g_pConfigDict->setAutoDelete(true);
+
+ KVSM_REGISTER_FUNCTION(m,"open",config_kvs_fnc_open);
+ KVSM_REGISTER_FUNCTION(m,"id",config_kvs_fnc_id);
+ KVSM_REGISTER_FUNCTION(m,"read",config_kvs_fnc_read);
+ KVSM_REGISTER_FUNCTION(m,"section",config_kvs_fnc_section);
+ KVSM_REGISTER_FUNCTION(m,"hassection",config_kvs_fnc_hassection);
+ KVSM_REGISTER_FUNCTION(m,"sectionlist",config_kvs_fnc_sectionlist);
+ KVSM_REGISTER_FUNCTION(m,"keylist",config_kvs_fnc_keylist);
+ KVSM_REGISTER_FUNCTION(m,"filelist",config_kvs_fnc_filelist);
+ KVSM_REGISTER_FUNCTION(m,"filename",config_kvs_fnc_filename);
+ KVSM_REGISTER_FUNCTION(m,"readonly",config_kvs_fnc_readonly);
+
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"close",config_kvs_cmd_close);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"flush",config_kvs_cmd_flush);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"clear",config_kvs_cmd_clear);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"clearsection",config_kvs_cmd_clearsection);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"setsection",config_kvs_cmd_setsection);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"write",config_kvs_cmd_write);
+
+ return true;
+}
+
+static bool config_module_cleanup(KviModule *m)
+{
+ delete g_pConfigDict;
+ g_pConfigDict = 0;
+ return true;
+}
+
+static bool config_module_can_unload(KviModule *m)
+{
+ return g_pConfigDict->isEmpty();
+}
+
+KVIRC_MODULE(
+ "Config", // module name
+ "1.0.0", // module version
+ "Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot net)", // author & (C)
+ "Config file system for KVIrc",
+ config_module_init,
+ config_module_can_unload,
+ 0,
+ config_module_cleanup
+)
diff --git a/src/modules/context/Makefile.am b/src/modules/context/Makefile.am
new file mode 100644
index 00000000..e4ec3252
--- /dev/null
+++ b/src/modules/context/Makefile.am
@@ -0,0 +1,18 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkvicontext.la
+
+libkvicontext_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkvicontext_la_SOURCES = libkvicontext.cpp
+libkvicontext_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+# noinst_HEADERS=
+
+%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
diff --git a/src/modules/context/libkvicontext.cpp b/src/modules/context/libkvicontext.cpp
new file mode 100644
index 00000000..a6a3bb97
--- /dev/null
+++ b/src/modules/context/libkvicontext.cpp
@@ -0,0 +1,401 @@
+//=============================================================================
+//
+// File : libkvicontext.cpp
+// Creation date : Wed Jan 02 2007 03:04:12 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+//#warning: FIXME: Incomplete documentation ('seealso', 'example', etc)
+
+#include "kvi_module.h"
+#include "kvi_locale.h"
+#include "kvi_qstring.h"
+#include "kvi_window.h"
+#include "kvi_frame.h"
+#include "kvi_console.h"
+#include "kvi_app.h"
+
+#include "kvi_ircserver.h"
+#include "kvi_irccontext.h"
+#include "kvi_ircconnection.h"
+#include "kvi_ircconnectionserverinfo.h"
+#include "kvi_ircconnectionuserinfo.h"
+#include "kvi_ircconnectiontarget.h"
+
+#define GET_CONSOLE_FROM_STANDARD_PARAMS \
+ kvs_int_t iContextId; \
+ KVSM_PARAMETERS_BEGIN(c) \
+ KVSM_PARAMETER("irc_context_id",KVS_PT_UINT,KVS_PF_OPTIONAL,iContextId) \
+ KVSM_PARAMETERS_END(c) \
+ KviConsole * pConsole = NULL; \
+ if(c->parameterCount() > 0) \
+ pConsole = g_pApp->findConsole(iContextId); \
+ else \
+ pConsole = c->window()->console();
+
+#define GET_CONNECTION_FROM_STANDARD_PARAMS \
+ GET_CONSOLE_FROM_STANDARD_PARAMS \
+ KviIrcConnection * pConnection = NULL; \
+ if(pConsole) \
+ pConnection = pConsole->context()->connection();
+
+#define STANDARD_IRC_CONNECTION_TARGET_PARAMETER(_fncName,_setCall) \
+ static bool _fncName(KviKvsModuleFunctionCall * c) \
+ { \
+ GET_CONNECTION_FROM_STANDARD_PARAMS \
+ if(pConnection) \
+ { \
+ if(pConnection->target()) \
+ { \
+ _setCall; \
+ return true; \
+ } \
+ } \
+ c->returnValue()->setNothing(); \
+ return true; \
+ }
+
+/*
+ @doc: context.networkName
+ @type:
+ function
+ @title:
+ $context.networkName
+ @short:
+ Returns the IRC network name of an IRC context
+ @syntax:
+ <string> $contex.networkName
+ <string> $contex.networkName(<irc_context_id:uint>)
+ @description:
+ Returns the name of the network for the specified IRC context.
+ If no irc_context_id is specified then the current irc_context is used.
+ If the irc_context_id specification is not valid then this function
+ returns nothing. If the specified IRC context is not currently connected
+ then this function returns nothing.
+ @seealso:
+ [fnc]$context.serverHostName[/fnc]
+*/
+
+STANDARD_IRC_CONNECTION_TARGET_PARAMETER(
+ context_kvs_fnc_networkName,
+ c->returnValue()->setString(pConnection->target()->network()->name())
+ )
+
+
+/*
+ @doc: context.serverHostName
+ @type:
+ function
+ @title:
+ $context.serverHostName
+ @short:
+ Returns the IRC server name of an IRC context
+ @syntax:
+ <string> $contex.serverHostName
+ <string> $contex.serverHostName(<irc_context_id:uint>)
+ @description:
+ Returns the host name of the IRC server that was used to perform
+ the connection in the specified irc context.
+ If no irc_context_id is specified then the current irc_context is used.
+ If the irc_context_id specification is not valid then this function
+ returns nothing. If the specified IRC context is not currently connected
+ then this function returns nothing.
+ If the returned value is non empty then it will always be a valid
+ DNS hostname that can be used to perform a real connection.
+ Please note that this is different from $my.server() which might
+ return an invalid DNS entry.
+ @seealso:
+ [fnc]$context.serverPort[/fnc],
+ [fnc]$context.serverIpAddress[/fnc],
+ [fnc]$context.serverPassword[/fnc]
+*/
+
+STANDARD_IRC_CONNECTION_TARGET_PARAMETER(
+ context_kvs_fnc_serverHostName,
+ c->returnValue()->setString(pConnection->target()->server()->hostName())
+ )
+
+/*
+ @doc: context.serverIpAddress
+ @type:
+ function
+ @title:
+ $context.serverIpAddress
+ @short:
+ Returns the IRC server ip address of an IRC context
+ @syntax:
+ <string> $contex.serverIpAddress
+ <string> $contex.serverIpAddress(<irc_context_id:uint>)
+ @description:
+ Returns the ip address of the IRC server for the specified irc context.
+ If no irc_context_id is specified then the current irc_context is used.
+ If the irc_context_id specification is not valid then this function
+ returns nothing. If the specified IRC context is not currently connected
+ then this function returns nothing.
+ @seealso:
+ [fnc]$context.serverPort[/fnc],
+ [fnc]$context.serverHostName[/fnc],
+ [fnc]$context.serverPassword[/fnc]
+*/
+
+STANDARD_IRC_CONNECTION_TARGET_PARAMETER(
+ context_kvs_fnc_serverIpAddress,
+ c->returnValue()->setString(pConnection->target()->server()->ipAddress())
+ )
+
+/*
+ @doc: context.serverIsIPV6
+ @type:
+ function
+ @title:
+ $context.serverIsIPV6
+ @short:
+ Returns the IPV6 state of an IRC context
+ @syntax:
+ <string> $contex.serverIsIPV6
+ <string> $contex.serverIsIPV6(<irc_context_id:uint>)
+ @description:
+ Returns true if the current irc context connection runs over IPV6.
+ If no irc_context_id is specified then the current irc_context is used.
+ If the irc_context_id specification is not valid then this function
+ returns nothing (that evaluates to false). If the specified IRC context
+ is not currently connected then this function returns nothing (that
+ evaluates to false).
+ @seealso:
+ [fnc]$context.serverPort[/fnc],
+ [fnc]$context.serverHostName[/fnc],
+ [fnc]$context.serverPassword[/fnc]
+*/
+
+STANDARD_IRC_CONNECTION_TARGET_PARAMETER(
+ context_kvs_fnc_serverIsIPV6,
+ c->returnValue()->setBoolean(pConnection->target()->server()->isIpV6())
+ )
+
+/*
+ @doc: context.serverIsSSL
+ @type:
+ function
+ @title:
+ $context.serverIsSSL
+ @short:
+ Returns the SSL state of an IRC context
+ @syntax:
+ <string> $contex.serverIsSSL
+ <string> $contex.serverIsSSL(<irc_context_id:uint>)
+ @description:
+ Returns true if the current irc context connection runs over SSL.
+ If no irc_context_id is specified then the current irc_context is used.
+ If the irc_context_id specification is not valid then this function
+ returns nothing (that evaluates to false). If the specified IRC context
+ is not currently connected then this function returns nothing (that
+ evaluates to false).
+ @seealso:
+ [fnc]$context.serverPort[/fnc],
+ [fnc]$context.serverHostName[/fnc],
+ [fnc]$context.serverPassword[/fnc]
+*/
+
+STANDARD_IRC_CONNECTION_TARGET_PARAMETER(
+ context_kvs_fnc_serverIsSSL,
+ c->returnValue()->setBoolean(pConnection->target()->server()->useSSL())
+ )
+
+/*
+ @doc: context.serverPassword
+ @type:
+ function
+ @title:
+ $context.serverPassword
+ @short:
+ Returns the password used to login to the server of an IRC context
+ @syntax:
+ <string> $contex.serverPassword
+ <string> $contex.serverPassword(<irc_context_id:uint>)
+ @description:
+ Returns the password used to login to the IRC server for the specified irc context.
+ If no irc_context_id is specified then the current irc_context is used.
+ If the irc_context_id specification is not valid then this function
+ returns nothing. If the specified IRC context is not currently connected
+ then this function returns nothing.
+ @seealso:
+ [fnc]$context.serverHostName[/fnc],
+ [fnc]$context.serverIpAddress[/fnc],
+ [fnc]$context.serverPort[/fnc]
+*/
+
+STANDARD_IRC_CONNECTION_TARGET_PARAMETER(
+ context_kvs_fnc_serverPassword,
+ c->returnValue()->setString(pConnection->target()->server()->password())
+ )
+
+
+/*
+ @doc: context.serverPort
+ @type:
+ function
+ @title:
+ $context.serverPort
+ @short:
+ Returns the port of the IRC server of an IRC context
+ @syntax:
+ <uint> $contex.serverPort
+ <uint> $contex.serverPort(<irc_context_id:uint>)
+ @description:
+ Returns the port of the IRC server for the specified irc context.
+ If no irc_context_id is specified then the current irc_context is used.
+ If the irc_context_id specification is not valid then this function
+ returns nothing. If the specified IRC context is not currently connected
+ then this function returns nothing.
+ @seealso:
+ [fnc]$context.serverHostName[/fnc],
+ [fnc]$context.serverIpAddress[/fnc]
+*/
+
+STANDARD_IRC_CONNECTION_TARGET_PARAMETER(
+ context_kvs_fnc_serverPort,
+ c->returnValue()->setInteger(pConnection->target()->server()->port())
+ )
+
+
+/*
+ @doc: context.state
+ @type:
+ function
+ @title:
+ $context.state
+ @short:
+ Returns the state of an IRC context
+ @syntax:
+ <string> $context.state
+ <string> $context.state(<irc_context_id:uint>)
+ @description:
+ Returns a string describing the state of the specified irc context.
+ The string will be either "idle","connecting","loggingin" or "connected".
+ If no irc_context_id is specified then the current irc_context is used.
+ If the irc_context_id specification is not valid then this function
+ returns nothing.
+ @seealso:
+ [fnc]$context.serverHostName[/fnc],
+ [fnc]$context.serverIpAddress[/fnc]
+*/
+
+static bool context_kvs_fnc_state(KviKvsModuleFunctionCall * c)
+{
+ GET_CONSOLE_FROM_STANDARD_PARAMS
+
+ if(pConsole)
+ {
+ switch(pConsole->ircContext()->state())
+ {
+ case KviIrcContext::Idle:
+ c->returnValue()->setString(QString("idle"));
+ break;
+ case KviIrcContext::Connecting:
+ c->returnValue()->setString(QString("connecting"));
+ break;
+ case KviIrcContext::LoggingIn:
+ c->returnValue()->setString(QString("loggingin"));
+ break;
+ case KviIrcContext::Connected:
+ c->returnValue()->setString(QString("connected"));
+ break;
+ default:
+ c->returnValue()->setString(QString("unknown"));
+ break;
+ }
+ return true;
+ }
+
+ c->returnValue()->setNothing();
+ return true;
+}
+
+
+/*
+ @doc: context.list
+ @type:
+ function
+ @title:
+ $context.list
+ @short:
+ Returns a list of existing IRC contexts
+ @syntax:
+ <array> $contex.list
+ @description:
+ Returns the array of currently existing IRC context identifiers.
+ @seealso:
+ @examples:
+ Print the names of the currently connected servers
+ [example]
+ foreach(%ic,$context.list)
+ echo "IRC Context" %ic ": " $context.serverHostName
+ [/example]
+*/
+
+static bool context_kvs_fnc_list(KviKvsModuleFunctionCall * c)
+{
+ KviKvsArray * pArray = new KviKvsArray();
+
+ KviPointerList<KviWindow> * pWinList = g_pFrame->windowList();
+ int idx = 0;
+ for(KviWindow * pWnd = pWinList->first();pWnd;pWnd = pWinList->next())
+ {
+ if(pWnd->type() == KVI_WINDOW_TYPE_CONSOLE)
+ {
+ pArray->set(idx,new KviKvsVariant((kvs_int_t)((KviConsole *)pWnd)->ircContextId()));
+ idx++;
+ }
+ }
+
+ c->returnValue()->setArray(pArray);
+ return true;
+}
+
+static bool context_module_init(KviModule * m)
+{
+ KVSM_REGISTER_FUNCTION(m,"serverHostName",context_kvs_fnc_serverHostName);
+ KVSM_REGISTER_FUNCTION(m,"serverIpAddress",context_kvs_fnc_serverIpAddress);
+ KVSM_REGISTER_FUNCTION(m,"serverPort",context_kvs_fnc_serverPort);
+ KVSM_REGISTER_FUNCTION(m,"serverIsIPV6",context_kvs_fnc_serverIsIPV6);
+ KVSM_REGISTER_FUNCTION(m,"serverIsSSL",context_kvs_fnc_serverIsSSL);
+ KVSM_REGISTER_FUNCTION(m,"serverPassword",context_kvs_fnc_serverPassword);
+ KVSM_REGISTER_FUNCTION(m,"networkName",context_kvs_fnc_networkName);
+ KVSM_REGISTER_FUNCTION(m,"state",context_kvs_fnc_state);
+ KVSM_REGISTER_FUNCTION(m,"list",context_kvs_fnc_list);
+
+ return true;
+}
+
+static bool context_module_cleanup(KviModule *m)
+{
+ return true;
+}
+
+KVIRC_MODULE(
+ "context",
+ "1.0.0",
+ "Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot net)",
+ "Irc Context Related Functions",
+ context_module_init,
+ 0,
+ 0,
+ context_module_cleanup
+)
diff --git a/src/modules/dcc/Makefile.am b/src/modules/dcc/Makefile.am
new file mode 100644
index 00000000..8a63b888
--- /dev/null
+++ b/src/modules/dcc/Makefile.am
@@ -0,0 +1,66 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+tmpdir=$(picsdir)
+
+tmp_DATA=kvi_dccfiletransfericons.png
+
+EXTRA_DIST=kvi_dccfiletransfericons.png
+
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkvidcc.la
+
+libkvidcc_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkvidcc_la_SOURCES = adpcmcodec.cpp \
+ broker.cpp \
+ canvas.cpp \
+ canvaswidget.cpp \
+ chat.cpp \
+ codec.cpp \
+ descriptor.cpp \
+ dialogs.cpp \
+ gsmcodec.cpp \
+ libkvidcc.cpp \
+ marshal.cpp \
+ requests.cpp \
+ send.cpp \
+ thread.cpp \
+ utils.cpp \
+ voice.cpp \
+ window.cpp
+
+libkvidcc_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+noinst_HEADERS= adpcmcodec.h \
+ broker.h \
+ canvas.h \
+ canvaswidget.h \
+ chat.h \
+ codec.h \
+ descriptor.h \
+ dialogs.h \
+ gsmcodec.h \
+ marshal.h \
+ send.h \
+ thread.h \
+ utils.h \
+ voice.h \
+ window.h
+
+m_%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
+
+broker.cpp: m_broker.moc
+canvas.cpp: m_canvas.moc
+canvaswidget.cpp: m_canvaswidget.moc
+chat.cpp: m_chat.moc
+dialogs.cpp: m_dialogs.moc
+marshal.cpp: m_marshal.moc
+send.cpp: m_send.moc
+voice.cpp: m_voice.moc
+window.cpp: m_window.moc
diff --git a/src/modules/dcc/adpcmcodec.cpp b/src/modules/dcc/adpcmcodec.cpp
new file mode 100644
index 00000000..65f12a00
--- /dev/null
+++ b/src/modules/dcc/adpcmcodec.cpp
@@ -0,0 +1,294 @@
+//
+// File : adpcmcodec.cpp
+// Creation date : Wed Aug 22 19:12:50 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+//
+// Code derived from adpcm.c : Intel ADPCM coder/decoder
+// Adapted for the KVirc distribution by Szymon Stefanek (pragma at kvirc dot net)
+// Last revision : 20 Sep 1999
+//
+// Copyright 1992 by Stichting Mathematisch Centrum, Amsterdam, The Netherlands.
+// All Rights Reserved
+//
+// Permission to use, copy, modify, and distribute this software and its
+// documentation for any purpose and without fee is hereby granted,
+// provided that the above copyright notice appear in all copies and that
+// both that copyright notice and this permission notice appear in
+// supporting documentation, and that the names of Stichting Mathematisch
+// Centrum or CWI not be used in advertising or publicity pertaining to
+// distribution of the software without specific, written prior permission.
+//
+// STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+// THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+// FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+// FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+// OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+//
+// Intel/DVI ADPCM coder/decoder.
+//
+// The algorithm for this coder was taken from the IMA Compatability Project
+// proceedings, Vol 2, Number 2; May 1992.
+//
+// Version 1.2, 18-Dec-92.
+//
+
+#define _ADPCMCODEC_CPP_
+#include "adpcmcodec.h"
+
+#include <stdio.h> /*DBG*/
+
+#ifndef __STDC__
+ #define signed
+#endif
+
+
+
+#define ADPCM_PACKED_FRAME_SIZE_IN_BYTES 512
+#define ADPCM_UNPACKED_FRAME_SIZE_IN_BYTES 2048
+#define ADPCM_UNPACKED_FRAME_SIZE_IN_SHORTS 1024
+
+// Intel ADPCM step variation table */
+static int indexTable[16] = {
+ -1, -1, -1, -1, 2, 4, 6, 8,
+ -1, -1, -1, -1, 2, 4, 6, 8,
+};
+
+static int stepsizeTable[89] = {
+ 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
+ 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
+ 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
+ 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
+ 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
+ 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
+ 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
+ 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
+ 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
+};
+
+
+void ADPCM_compress(short indata[],char outdata[],int len,ADPCM_state *state)
+{
+ short *lpIn; /* Input buffer pointer */
+ signed char *lpOut; /* output buffer pointer */
+ int val; /* Current input sample value */
+ int sign; /* Current adpcm sign bit */
+ int delta; /* Current adpcm output value */
+ int diff; /* Difference between val and valprev */
+ int step; /* Stepsize */
+ int valpred; /* Predicted output value */
+ int vpdiff; /* Current change to valpred */
+ int index; /* Current step change index */
+ int outputbuffer = 0; /* place to keep previous 4-bit value */
+ int bufferstep; /* toggle between outputbuffer/output */
+
+ lpOut = (signed char *)outdata;
+ lpIn = indata;
+
+ valpred = state->valprev;
+ index = state->index;
+ step = stepsizeTable[index];
+
+ bufferstep = 1;
+
+ for ( ;len > 0;len-- ) {
+ val = *lpIn++;
+ // Step 1 - compute difference with previous value
+ diff = val - valpred;
+ sign = (diff < 0) ? 8 : 0;
+ if(sign)diff=(-diff);
+ // Step 2 - Divide and clamp
+ // Note:
+ // This code *approximately* computes:
+ // delta = diff*4/step;
+ // vpdiff = (delta+0.5)*step/4;
+ // but in shift step bits are dropped. The net result of this is
+ // that even if you have fast mul/div hardware you cannot put it to
+ // good use since the fixup would be too expensive.
+ //
+ delta = 0;
+ vpdiff = (step >> 3);
+ if (diff >=step){
+ delta = 4;
+ diff -= step;
+ vpdiff += step;
+ }
+ step >>= 1;
+ if (diff >= step) {
+ delta |= 2;
+ diff -= step;
+ vpdiff += step;
+ }
+ step >>= 1;
+ if ( diff >= step ) {
+ delta |= 1;
+ vpdiff += step;
+ }
+ // Step 3 - Update previous value
+ if(sign)valpred -= vpdiff;
+ else valpred += vpdiff;
+ // Step 4 - Clamp previous value to 16 bits
+ if ( valpred > 32767 )valpred = 32767;
+ else if ( valpred < -32768 )valpred = -32768;
+ // Step 5 - Assemble value, update index and step values
+ delta |= sign;
+ index += indexTable[delta];
+ if ( index < 0 ) index = 0;
+ if ( index > 88 ) index = 88;
+ step = stepsizeTable[index];
+ // Step 6 - Output value
+ if ( bufferstep )outputbuffer = (delta << 4) & 0xf0;
+ else *lpOut++ = (delta & 0x0f) | outputbuffer;
+ bufferstep = !bufferstep;
+ }
+ // Output last step, if needed
+ if (!bufferstep)*lpOut++ = outputbuffer;
+ state->valprev = valpred;
+ state->index = index;
+}
+
+void ADPCM_uncompress(char indata[],short outdata[],int len,ADPCM_state *state)
+{
+ signed char *inp; /* Input buffer pointer */
+ short *outp; /* output buffer pointer */
+ int sign; /* Current adpcm sign bit */
+ int delta; /* Current adpcm output value */
+ int step; /* Stepsize */
+ int valpred; /* Predicted value */
+ int vpdiff; /* Current change to valpred */
+ int index; /* Current step change index */
+ int inputbuffer=0; /* place to keep next 4-bit value */
+ int bufferstep; /* toggle between inputbuffer/input */
+
+ outp = outdata;
+ inp = (signed char *)indata;
+
+ valpred = state->valprev;
+ index = state->index;
+ step = stepsizeTable[index];
+
+ bufferstep = 0;
+
+ for ( ; len > 0 ; len-- ) {
+
+ /* Step 1 - get the delta value */
+ if ( bufferstep )delta = inputbuffer & 0xf;
+ else {
+ inputbuffer = *inp++;
+ delta = (inputbuffer >> 4) & 0xf;
+ }
+ bufferstep = !bufferstep;
+
+ /* Step 2 - Find new index value (for later) */
+ index += indexTable[delta];
+ if ( index < 0 ) index = 0;
+ if ( index > 88 ) index = 88;
+
+ /* Step 3 - Separate sign and magnitude */
+ sign = delta & 8;
+ delta = delta & 7;
+
+ /* Step 4 - Compute difference and new predicted value */
+ /*
+ ** Computes 'vpdiff = (delta+0.5)*step/4', but see comment
+ ** in adpcm_coder.
+ */
+ vpdiff = step >> 3;
+ if( delta & 4 )vpdiff += step;
+ if( delta & 2 )vpdiff += step>>1;
+ if( delta & 1 )vpdiff += step>>2;
+
+ if(sign)valpred -= vpdiff;
+ else valpred += vpdiff;
+
+ /* Step 5 - clamp output value */
+ if(valpred > 32767)valpred = 32767;
+ else if(valpred < -32768)valpred = -32768;
+
+ /* Step 6 - Update step value */
+ step = stepsizeTable[index];
+
+ /* Step 7 - Output value */
+ *outp++ = valpred;
+ }
+
+ state->valprev = valpred;
+ state->index = index;
+}
+
+
+KviDccVoiceAdpcmCodec::KviDccVoiceAdpcmCodec()
+: KviDccVoiceCodec()
+{
+ m_pEncodeState = new ADPCM_state;
+ m_pEncodeState->index = 0;
+ m_pEncodeState->valprev = 0;
+ m_pDecodeState = new ADPCM_state;
+ m_pDecodeState->index = 0;
+ m_pDecodeState->valprev = 0;
+ m_szName = "adpcm (compression 1:4)";
+}
+
+KviDccVoiceAdpcmCodec::~KviDccVoiceAdpcmCodec()
+{
+ delete m_pEncodeState;
+ delete m_pDecodeState;
+}
+
+void KviDccVoiceAdpcmCodec::encode(KviDataBuffer * signal,KviDataBuffer * stream)
+{
+ if(signal->size() < ADPCM_UNPACKED_FRAME_SIZE_IN_BYTES)return; // nothing to encode
+
+ char * ptr = (char *)signal->data();
+
+ int uFrames = signal->size() / ADPCM_UNPACKED_FRAME_SIZE_IN_BYTES;
+ int uTotalDataCompressed = uFrames * ADPCM_UNPACKED_FRAME_SIZE_IN_BYTES;
+ int uFrameOffset = stream->size();
+ char * endPtr = ptr + uTotalDataCompressed;
+
+ stream->addSize(ADPCM_PACKED_FRAME_SIZE_IN_BYTES * uFrames);
+
+ while(ptr != endPtr)
+ {
+ ADPCM_compress((short *)ptr,(char *)(stream->data() + uFrameOffset),ADPCM_UNPACKED_FRAME_SIZE_IN_SHORTS,m_pEncodeState);
+ ptr += ADPCM_UNPACKED_FRAME_SIZE_IN_BYTES;
+ uFrameOffset += ADPCM_PACKED_FRAME_SIZE_IN_BYTES;
+ }
+ signal->remove(uTotalDataCompressed);
+}
+
+void KviDccVoiceAdpcmCodec::decode(KviDataBuffer * stream,KviDataBuffer * signal)
+{
+ if(stream->size() < ADPCM_PACKED_FRAME_SIZE_IN_BYTES)return; // nothing to decode
+
+ char * ptr = (char *)stream->data();
+
+ // Adpcm codec
+ int uFrames = stream->size() / ADPCM_PACKED_FRAME_SIZE_IN_BYTES;
+ int uTotalDataDecompressed = uFrames * ADPCM_PACKED_FRAME_SIZE_IN_BYTES;
+ int uSignalOffset = signal->size();
+ char * endPtr = ptr + (uTotalDataDecompressed);
+
+ signal->addSize(ADPCM_UNPACKED_FRAME_SIZE_IN_BYTES * uFrames);
+
+ while(ptr != endPtr)
+ {
+ ADPCM_uncompress((char *)ptr,(short *)(signal->data() + uSignalOffset),ADPCM_UNPACKED_FRAME_SIZE_IN_SHORTS,m_pDecodeState);
+ ptr += ADPCM_PACKED_FRAME_SIZE_IN_BYTES;
+ uSignalOffset += ADPCM_UNPACKED_FRAME_SIZE_IN_BYTES;
+ }
+ stream->remove(uTotalDataDecompressed);
+}
+
+int KviDccVoiceAdpcmCodec::encodedFrameSize()
+{
+ return ADPCM_PACKED_FRAME_SIZE_IN_BYTES;
+}
+
+int KviDccVoiceAdpcmCodec::decodedFrameSize()
+{
+ return ADPCM_UNPACKED_FRAME_SIZE_IN_BYTES;
+}
diff --git a/src/modules/dcc/adpcmcodec.h b/src/modules/dcc/adpcmcodec.h
new file mode 100644
index 00000000..63343df0
--- /dev/null
+++ b/src/modules/dcc/adpcmcodec.h
@@ -0,0 +1,59 @@
+#ifndef _ADPCMCODEC_H_
+#define _ADPCMCODEC_H_
+//
+// File : adpcmcodec.h
+// Creation date : Wed Aug 22 19:12:46 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Code derived from adpcm.c : Intel ADPCM coder/decoder
+// Adapted for the KVirc distribution by Szymon Stefanek (pragma at kvirc dot net)
+// Last revision : 22 Aug 2001
+// See kvi_adpcm.cpp for the complete copyright notice.
+//
+//
+// adpcm.h - include file for adpcm coder.
+//
+// Version 1.0, 7-Jul-92.
+//
+//
+// Average compression speed experiment: P166MMX 32MEG
+//
+// INPUT | OUTPUT | COMPRESSION TIME
+// ------------------------------------------------------------------------
+// shorts bytes | bytes | min msec. avrg. high peak (1 time)
+// ------------------------------------------------------------------------
+// 512 1024 | 256 | ~4 4 34
+// 1024 2048 | 512 | ~7 8 75
+// 2048 4096 | 1024 | ~13 15 175 (!!!)
+// 4096 8192 | 2048 | ~26 33 91
+// 8192 16384 | 4096 | ~57 80 220 (~1 sec of audio)
+// 16384 32768 | 8192 | ~110 250 290
+//
+
+#include <qstring.h> // fix for qtextstream.h
+#include "codec.h"
+
+typedef struct adpcm_state
+{
+ short valprev; /* Previous output value */
+ char index; /* Index into stepsize table */
+} ADPCM_state;
+
+
+class KviDccVoiceAdpcmCodec : public KviDccVoiceCodec
+{
+public:
+ KviDccVoiceAdpcmCodec();
+ virtual ~KviDccVoiceAdpcmCodec();
+private:
+ ADPCM_state * m_pEncodeState;
+ ADPCM_state * m_pDecodeState;
+public:
+ virtual void encode(KviDataBuffer * signal,KviDataBuffer * stream);
+ virtual void decode(KviDataBuffer * stream,KviDataBuffer * signal);
+ virtual int encodedFrameSize();
+ virtual int decodedFrameSize();
+};
+
+
+#endif //_ADPCMCODEC_H_
diff --git a/src/modules/dcc/broker.cpp b/src/modules/dcc/broker.cpp
new file mode 100644
index 00000000..b6548e0c
--- /dev/null
+++ b/src/modules/dcc/broker.cpp
@@ -0,0 +1,898 @@
+//
+// File : broker.cpp
+// Creation date : Tue Sep 19 09 2000 10:21:54 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "broker.h"
+#include "dialogs.h"
+#include "chat.h"
+#include "send.h"
+#ifdef COMPILE_DCC_CANVAS
+#include "canvas.h"
+#endif
+#include "voice.h"
+
+#include "kvi_app.h"
+#include "kvi_frame.h"
+#include "kvi_locale.h"
+#include "kvi_options.h"
+#include "kvi_console.h"
+#include "kvi_fileutils.h"
+#include "kvi_out.h"
+#include "kvi_mediatype.h"
+#include "kvi_ircconnection.h"
+#include "kvi_sharedfiles.h"
+
+// kvi_app.cpp
+extern KVIRC_API KviMediaManager * g_pMediaManager;
+extern KVIRC_API KviSharedFilesManager * g_pSharedFilesManager;
+
+#include <qfileinfo.h>
+#include <qstring.h>
+
+//#warning "The broker might lookup the remote host name"
+
+KviDccBroker::KviDccBroker()
+: QObject(0,"dcc_broker")
+{
+ KviDccFileTransfer::init();
+
+ m_pBoxList = new KviPointerList<KviDccBox>;
+ m_pBoxList->setAutoDelete(false);
+
+ m_pDccWindowList = new KviPointerList<KviWindow>;
+ m_pDccWindowList->setAutoDelete(false);
+
+ m_pZeroPortTags = new KviPointerHashTable<QString,KviDccZeroPortTag>(17);
+ m_pZeroPortTags->setAutoDelete(true);
+}
+
+KviDccBroker::~KviDccBroker()
+{
+ delete m_pZeroPortTags;
+ while(m_pBoxList->first())delete m_pBoxList->first();
+ delete m_pBoxList;
+ m_pBoxList = 0;
+ while(m_pDccWindowList->first())delete m_pDccWindowList->first();
+ delete m_pDccWindowList;
+ KviDccFileTransfer::done();
+}
+
+
+KviDccZeroPortTag * KviDccBroker::addZeroPortTag()
+{
+ static unsigned int g_uNextZeroPortTag = 0;
+ g_uNextZeroPortTag++;
+ KviDccZeroPortTag * t = new KviDccZeroPortTag;
+ t->m_tTimestamp = QDateTime::currentDateTime();
+ t->m_szTag.setNum(g_uNextZeroPortTag);
+ //t->m_szTag.prepend("mIrc-zero-port-");
+ t->m_uResumePosition = 0;
+ // FIXME: we should clear this dict if it grows too high....
+ m_pZeroPortTags->insert(t->m_szTag,t);
+ return t;
+}
+
+KviDccZeroPortTag * KviDccBroker::findZeroPortTag(const QString &szTag)
+{
+ KviDccZeroPortTag * t = m_pZeroPortTags->find(szTag);
+ if(!t)return 0;
+ if(t->m_tTimestamp.secsTo(QDateTime::currentDateTime()) > 180)
+ {
+ // too late man...
+ m_pZeroPortTags->remove(szTag);
+ return 0;
+ }
+ return t;
+}
+
+void KviDccBroker::removeZeroPortTag(const QString &szTag)
+{
+ m_pZeroPortTags->remove(szTag);
+}
+
+unsigned int KviDccBroker::dccBoxCount()
+{
+ return m_pBoxList->count();
+}
+
+void KviDccBroker::unregisterDccWindow(KviWindow *wnd)
+{
+ m_pDccWindowList->removeRef(wnd);
+}
+
+void KviDccBroker::unregisterDccBox(KviDccBox * box)
+{
+ //debug("Forgetting box %d",box);
+ m_pBoxList->removeRef(box);
+}
+
+
+void KviDccBroker::cancelDcc(KviDccDescriptor * dcc)
+{
+ delete dcc;
+ dcc = 0;
+}
+
+void KviDccBroker::cancelDcc(KviDccBox *box,KviDccDescriptor * dcc)
+{
+ if(box)box->forgetDescriptor();
+ delete dcc;
+ dcc = 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// RSEND
+///////////////////////////////////////////////////////////////////////////////
+
+void KviDccBroker::rsendManage(KviDccDescriptor * dcc)
+{
+ // We need the filename...
+ QFileInfo fi(dcc->szLocalFileName);
+ if(fi.exists())rsendExecute(0,dcc);
+ else rsendAskForFileName(dcc);
+}
+
+void KviDccBroker::rsendAskForFileName(KviDccDescriptor * dcc)
+{
+ QStringList filenames;
+ if(
+ KviFileDialog::askForOpenFileNames(filenames,
+ __tr2qs_ctx("Choose Files to Send - KVIrc","dcc"),"")
+ ) {
+ if(filenames.count() > 0)
+ {
+ KviDccDescriptor * d;
+ KviDccDescriptor * templ = dcc;
+ QStringList::Iterator it=filenames.begin();
+ while(it != filenames.end())
+ {
+ d = new KviDccDescriptor(*dcc);
+ d->szLocalFileName = *(it);
+ d->szLocalFileName.stripWhiteSpace();
+ ++it;
+ if(d->szLocalFileName.isEmpty())
+ cancelDcc(d);
+ else
+ rsendExecute(d);
+ }
+ delete dcc;
+ }
+ } else {
+ cancelDcc(dcc);
+ }
+}
+
+void KviDccBroker::rsendExecute(KviDccDescriptor * dcc)
+{
+ if(!g_pApp->windowExists(dcc->console()))
+ {
+ // No way...we NEED the right IRC context...
+ g_pApp->activeConsole()->output(KVI_OUT_DCCERROR,
+ __tr2qs_ctx("Can't send DCC %Q request to %Q: IRC connection has been terminated","dcc"),
+ &(dcc->szType),&(dcc->szNick));
+ delete dcc;
+ return;
+ }
+
+ // Ok...we need the file to exist
+ QFileInfo fi(dcc->szLocalFileName);
+ if(!(fi.exists() && fi.isReadable() && (fi.isFile()) && (fi.size() > 0)))
+ {
+ dcc->console()->output(KVI_OUT_DCCERROR,__tr2qs_ctx("Can't open file %Q for reading","dcc"),
+ &(dcc->szLocalFileName));
+ delete dcc;
+ return;
+ }
+
+ dcc->szFileName = dcc->szLocalFileName;
+ dcc->szFileName = QFileInfo(dcc->szFileName).fileName();
+
+ QString fName = dcc->szFileName;
+ fName.replace(' ',"\\040"); // be cool :)
+
+ QString szTag;
+ if(dcc->isZeroPortRequest())
+ {
+ // actually we tagged it as "nonempty" in /dcc.rsend --zero-port
+ // retag it with something more reasonable
+ KviDccZeroPortTag * t = addZeroPortTag();
+ t->m_uFileSize = fi.size();
+ dcc->setZeroPortRequestTag(t->m_szTag.latin1()); // latin1() should be ok here
+ szTag = t->m_szTag;
+
+ // DCC [ST]SEND <filename> <fakeipaddress> <zero-port> <filesize> <sessionid>
+ dcc->console()->connection()->sendFmtData("PRIVMSG %s :%cDCC %s %s 127.0.0.1 0 %u %s%c",
+ dcc->console()->connection()->encodeText(dcc->szNick).data(),
+ 0x01,
+ dcc->console()->connection()->encodeText(dcc->szType).data(),
+ dcc->console()->connection()->encodeText(fName).data(),
+ fi.size(),
+ dcc->console()->connection()->encodeText(szTag).data(),
+ 0x01);
+ } else {
+ dcc->console()->connection()->sendFmtData("PRIVMSG %s :%cDCC %s %s %u%c",
+ dcc->console()->connection()->encodeText(dcc->szNick).data(),
+ 0x01,
+ dcc->console()->connection()->encodeText(dcc->szType).data(),
+ dcc->console()->connection()->encodeText(fName).data(),
+ fi.size(),0x01);
+ szTag = dcc->szFileName;
+ }
+
+ // now add a file offer , so he we will accept it automatically
+ // 120 secs is a reasonable timeout
+ QString szMask = dcc->szNick;
+ szMask += "!*@*";
+
+ g_pSharedFilesManager->addSharedFile(szTag,dcc->szLocalFileName,szMask,120);
+
+ delete dcc;
+}
+
+void KviDccBroker::rsendExecute(KviDccBox * box,KviDccDescriptor * dcc)
+{
+ if(box)box->forgetDescriptor();
+ rsendExecute(dcc);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// DCC CHAT
+///////////////////////////////////////////////////////////////////////////////
+
+void KviDccBroker::handleChatRequest(KviDccDescriptor * dcc)
+{
+
+ if(!dcc->bAutoAccept)
+ {
+ // FIXME: better message ? Secure Direct Client Connection...eventually
+ // need confirmation
+ QString tmp = __tr2qs_ctx( \
+ "<b>%1 [%2@%3]</b> requests a " \
+ "<b>Direct Client Connection</b> in <b>%4</b> mode.<br>", \
+ "dcc").arg(dcc->szNick).arg(dcc->szUser).arg(dcc->szHost).arg(dcc->szType);
+
+#ifdef COMPILE_SSL_SUPPORT
+ if(dcc->bIsSSL)tmp += __tr2qs_ctx("The connection will be secured using SSL.<br>","dcc");
+#endif
+
+ if(dcc->isZeroPortRequest())
+ {
+ tmp += __tr2qs_ctx( \
+ "You will be the passive side of the connection.<br>" \
+ ,"dcc");
+ } else {
+ tmp += __tr2qs_ctx( \
+ "The connection target will be host <b>%1</b> on port <b>%2</b><br>" \
+ ,"dcc").arg(dcc->szIp).arg(dcc->szPort);
+ }
+
+
+ QString caption = __tr2qs_ctx("DCC %1 Request - KVIrc","dcc").arg(dcc->szType);
+
+ KviDccAcceptBox * box = new KviDccAcceptBox(this,dcc,tmp,caption);
+
+ m_pBoxList->append(box);
+ connect(box,SIGNAL(accepted(KviDccBox *,KviDccDescriptor *)),
+ this,SLOT(executeChat(KviDccBox *,KviDccDescriptor *)));
+ connect(box,SIGNAL(rejected(KviDccBox *,KviDccDescriptor *)),
+ this,SLOT(cancelDcc(KviDccBox *,KviDccDescriptor *)));
+ box->show();
+ } else {
+ // auto accept
+ executeChat(0,dcc);
+ }
+}
+
+void KviDccBroker::executeChat(KviDccBox *box,KviDccDescriptor * dcc)
+{
+ if(box)box->forgetDescriptor();
+
+ if(!g_pApp->windowExists(dcc->console()))
+ {
+ // rebind to the first available console....
+ dcc->setConsole(g_pApp->activeConsole());
+ }
+
+ KviStr szSubProto = dcc->szType;
+ szSubProto.toLower();
+
+ QString tmp = QString("dcc: %1 %2@%3:%4").arg(szSubProto.ptr()).arg(dcc->szNick).arg(dcc->szIp).arg(dcc->szPort);
+ KviDccChat * chat = new KviDccChat(dcc->console()->frame(),dcc,tmp.utf8().data());
+
+ bool bMinimized = dcc->bOverrideMinimize ? dcc->bShowMinimized : \
+ (KVI_OPTION_BOOL(KviOption_boolCreateMinimizedDccChat) || \
+ (dcc->bAutoAccept && KVI_OPTION_BOOL(KviOption_boolCreateMinimizedDccChatWhenAutoAccepted)));
+
+ dcc->console()->frame()->addWindow(chat,!bMinimized);
+ if(bMinimized)chat->minimize();
+ m_pDccWindowList->append(chat);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// ACTIVE VOICE
+///////////////////////////////////////////////////////////////////////////////
+
+void KviDccBroker::activeVoiceManage(KviDccDescriptor * dcc)
+{
+ if(!dcc->bAutoAccept)
+ {
+ // need confirmation
+ QString tmp = __tr2qs_ctx(
+ "<b>%1 [%2@%3]</b> requests a<br>" \
+ "<b>Direct Client Connection</b> in <b>VOICE</b> mode.<br>" \
+ "The connection target will be host <b>%4</b> on port <b>%5</b><br>" \
+ ,"dcc" \
+ ).arg(dcc->szNick).arg(dcc->szUser).arg(dcc->szHost).arg(dcc->szIp).arg(dcc->szPort);
+
+ KviDccAcceptBox * box = new KviDccAcceptBox(this,dcc,tmp,__tr2qs_ctx("DCC VOICE request","dcc"));
+ m_pBoxList->append(box);
+ connect(box,SIGNAL(accepted(KviDccBox *,KviDccDescriptor *)),
+ this,SLOT(activeVoiceExecute(KviDccBox *,KviDccDescriptor *)));
+ connect(box,SIGNAL(rejected(KviDccBox *,KviDccDescriptor *)),
+ this,SLOT(cancelDcc(KviDccBox *,KviDccDescriptor *)));
+ box->show();
+ } else {
+ // auto accept
+ activeVoiceExecute(0,dcc);
+ }
+}
+
+void KviDccBroker::activeVoiceExecute(KviDccBox *box,KviDccDescriptor * dcc)
+{
+ if(box)box->forgetDescriptor();
+
+ if(!g_pApp->windowExists(dcc->console()))
+ {
+ // rebind to the first available console....
+ dcc->setConsole(g_pApp->activeConsole());
+ }
+
+ KviStr tmp(KviStr::Format,"dcc: voice %s@%s:%s",dcc->szNick.utf8().data(),dcc->szIp.utf8().data(),dcc->szPort.utf8().data());
+ KviDccVoice * v = new KviDccVoice(dcc->console()->frame(),dcc,tmp.ptr());
+
+ bool bMinimized = dcc->bOverrideMinimize ? dcc->bShowMinimized : \
+ (KVI_OPTION_BOOL(KviOption_boolCreateMinimizedDccVoice) || \
+ (dcc->bAutoAccept && KVI_OPTION_BOOL(KviOption_boolCreateMinimizedDccVoiceWhenAutoAccepted)));
+
+ dcc->console()->frame()->addWindow(v,!bMinimized);
+ if(bMinimized)v->minimize();
+
+ m_pDccWindowList->append(v);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// PASSIVE VOICE
+///////////////////////////////////////////////////////////////////////////////
+
+void KviDccBroker::passiveVoiceExecute(KviDccDescriptor * dcc)
+{
+ KviStr tmp(KviStr::Format,"dcc: voice %s@%s:%s",dcc->szNick.utf8().data(),dcc->szIp.utf8().data(),dcc->szPort.utf8().data());
+ KviDccVoice * v = new KviDccVoice(dcc->console()->frame(),dcc,tmp.ptr());
+//#warning "Create minimized dcc voice ?... or maybe it's too much ? :)"
+ bool bMinimized = dcc->bOverrideMinimize ? dcc->bShowMinimized : KVI_OPTION_BOOL(KviOption_boolCreateMinimizedDccChat);
+ dcc->console()->frame()->addWindow(v,!bMinimized);
+ if(bMinimized)v->minimize();
+ m_pDccWindowList->append(v);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// ACTIVE CANVAS
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef COMPILE_DCC_CANVAS
+
+void KviDccBroker::activeCanvasManage(KviDccDescriptor * dcc)
+{
+ if(!dcc->bAutoAccept)
+ {
+ // need confirmation
+ QString tmp = __tr2qs_ctx( \
+ "<b>%1 [%2@%3]</b> requests a<br>" \
+ "<b>Direct Client Connection</b> in <b>CANVAS</b> mode.<br>" \
+ "The connection target will be host <b>%4</b> on port <b>%5</b><br>" \
+ ,"dcc" \
+ ).arg(dcc->szNick).arg(dcc->szUser).arg(dcc->szHost).arg(dcc->szIp).arg(dcc->szPort);
+
+ KviDccAcceptBox * box = new KviDccAcceptBox(this,dcc,tmp,__tr2qs_ctx("DCC CANVAS request","dcc"));
+ m_pBoxList->append(box);
+ connect(box,SIGNAL(accepted(KviDccBox *,KviDccDescriptor *)),
+ this,SLOT(activeCanvasExecute(KviDccBox *,KviDccDescriptor *)));
+ connect(box,SIGNAL(rejected(KviDccBox *,KviDccDescriptor *)),
+ this,SLOT(cancelDcc(KviDccBox *,KviDccDescriptor *)));
+ box->show();
+ } else {
+ // auto accept
+ activeCanvasExecute(0,dcc);
+ }
+}
+
+#endif
+
+void KviDccBroker::activeCanvasExecute(KviDccBox *box,KviDccDescriptor * dcc)
+{
+#ifdef COMPILE_DCC_CANVAS
+ if(box)box->forgetDescriptor();
+
+ if(!g_pApp->windowExists(dcc->console()))
+ {
+ // rebind to the first available console....
+ dcc->setConsole(g_pApp->activeConsole());
+ }
+
+ KviStr tmp(KviStr::Format,"dcc: canvas %s@%s:%s",dcc->szNick.utf8().data(),dcc->szIp.utf8().data(),dcc->szPort.utf8().data());
+ KviDccCanvas * cnv = new KviDccCanvas(dcc->console()->frame(),dcc,tmp.ptr());
+
+//#warning "This option should be dedicated to Dcc Canvas!....for now we are using the DccChat options"
+ bool bMinimized = dcc->bOverrideMinimize ? dcc->bShowMinimized : \
+ (KVI_OPTION_BOOL(KviOption_boolCreateMinimizedDccChat) || \
+ (dcc->bAutoAccept && KVI_OPTION_BOOL(KviOption_boolCreateMinimizedDccChatWhenAutoAccepted)));
+
+ dcc->console()->frame()->addWindow(cnv,!bMinimized);
+ if(bMinimized)cnv->minimize();
+
+ m_pDccWindowList->append(cnv);
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// PASSIVE CANVAS
+///////////////////////////////////////////////////////////////////////////////
+#ifdef COMPILE_DCC_CANVAS
+void KviDccBroker::passiveCanvasExecute(KviDccDescriptor * dcc)
+{
+ KviStr tmp(KviStr::Format,"dcc: canvas %s@%s:%s",dcc->szNick.utf8().data(),dcc->szIp.utf8().data(),dcc->szPort.utf8().data());
+ KviDccCanvas * cnv = new KviDccCanvas(dcc->console()->frame(),dcc,tmp.ptr());
+//#warning "This option should be dedicated to Dcc Canvas!....for now we are using the DccChat options"
+ bool bMinimized = dcc->bOverrideMinimize ? dcc->bShowMinimized : KVI_OPTION_BOOL(KviOption_boolCreateMinimizedDccChat);
+ dcc->console()->frame()->addWindow(cnv,!bMinimized);
+ if(bMinimized)cnv->minimize();
+ m_pDccWindowList->append(cnv);
+}
+
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// SEND
+///////////////////////////////////////////////////////////////////////////////
+
+void KviDccBroker::recvFileManage(KviDccDescriptor * dcc)
+{
+ if(dcc->bIsIncomingAvatar)
+ {
+ bool bOk;
+ uint size = dcc->szFileSize.toUInt(&bOk);
+ if(bOk) {
+ if(size>=KVI_OPTION_UINT(KviOption_uintMaximumRequestedAvatarSize)) {
+ cancelDcc(0,dcc);
+ return;
+ }
+ }
+ }
+
+ if(!dcc->bAutoAccept)
+ {
+ // need confirmation
+ QString tmp;
+
+ if(dcc->bActive)
+ {
+ // Normal active send: we will be connecting
+ tmp = __tr2qs_ctx( \
+ "<b>%1 [%2@%3]</b> " \
+ "wants to send you the file " \
+ "'<b>%4</b>', " \
+ "<b>%5</b> large.<br>" \
+ "The connection target will be host <b>%6</b> on port <b>%7</b><br>" \
+ ,"dcc" \
+ ).arg(dcc->szNick).arg(dcc->szUser).arg(dcc->szHost).arg(
+ dcc->szFileName).arg(KviQString::makeSizeReadable(dcc->szFileSize.toInt())).arg(
+ dcc->szIp).arg(dcc->szPort);
+
+ } else {
+ // passive: we will be listening!
+ tmp = __tr2qs_ctx( \
+ "<b>%1 [%2@%3]</b> "
+ "wants to send you the file " \
+ "'<b>%4</b>', " \
+ "<b>%5</b> large.<br>" \
+ "You will be the passive side of the connection.<br>" \
+ ,"dcc" \
+ ).arg(dcc->szNick).arg(dcc->szUser).arg(dcc->szHost).arg(
+ dcc->szFileName).arg(KviQString::makeSizeReadable(dcc->szFileSize.toInt()));
+ }
+
+ if(dcc->bIsIncomingAvatar)
+ {
+ tmp += __tr2qs_ctx( \
+ "<center><b>Note:</b></center>" \
+ "The file appears to be an avatar that you have requested. " \
+ "You should not change its filename. " \
+ "Save it in a location where KVIrc can find it, such as " \
+ "the 'avatars', 'incoming', or 'pics' directories, " \
+ "your home directory, or the save directory for the incoming file type. " \
+ "The default save path will probably work. " \
+ "You can instruct KVIrc to accept incoming avatars automatically " \
+ "by setting the option <tt>boolAutoAcceptIncomingAvatars</tt> to true.<br>" \
+ ,"dcc" \
+ );
+ }
+
+//#warning "Maybe remove the pending avatar if rejected ?"
+
+ QString title = __tr2qs_ctx("DCC %1 Request - KVIrc","dcc").arg(dcc->szType);
+
+ KviDccAcceptBox * box = new KviDccAcceptBox(this,dcc,tmp,title);
+ m_pBoxList->append(box);
+ connect(box,SIGNAL(accepted(KviDccBox *,KviDccDescriptor *)),
+ this,SLOT(chooseSaveFileName(KviDccBox *,KviDccDescriptor *)));
+ connect(box,SIGNAL(rejected(KviDccBox *,KviDccDescriptor *)),
+ this,SLOT(cancelDcc(KviDccBox *,KviDccDescriptor *)));
+ box->show();
+ } else {
+ // auto accept
+
+ if(_OUTPUT_VERBOSE)
+ {
+ dcc->console()->output(KVI_OUT_DCCMSG,__tr2qs_ctx("Auto-accepting DCC %Q request from %Q!%Q@%Q for file %Q","dcc"),
+ &(dcc->szType),&(dcc->szNick),&(dcc->szUser),
+ &(dcc->szHost),&(dcc->szFileName));
+ }
+ chooseSaveFileName(0,dcc);
+ }
+}
+
+void KviDccBroker::chooseSaveFileName(KviDccBox *box,KviDccDescriptor *dcc)
+{
+ if(box)box->forgetDescriptor();
+
+ // Lookup the suggested save directory
+
+ dcc->szLocalFileName = "";
+
+ if(dcc->bIsIncomingAvatar)g_pApp->getLocalKvircDirectory(dcc->szLocalFileName,KviApp::Avatars);
+ else {
+
+ if(KVI_OPTION_BOOL(KviOption_boolUseIncomingDccMediaTypeSavePath))
+ {
+ g_pMediaManager->lock();
+ if(KviMediaType * mt = g_pMediaManager->findMediaType(dcc->szFileName.utf8().data(),false))
+ {
+ if(mt->szSavePath.hasData())
+ {
+ if(KviFileUtils::directoryExists(mt->szSavePath.ptr()))dcc->szLocalFileName = mt->szSavePath;
+ else {
+ if(KviFileUtils::makeDir(mt->szSavePath.ptr()))dcc->szLocalFileName = mt->szSavePath;
+ }
+ if(KVI_OPTION_BOOL(KviOption_boolSortReceivedByDccFilesByNicks))
+ {
+ KviQString::ensureLastCharIs(dcc->szLocalFileName,KVI_PATH_SEPARATOR_CHAR);
+ dcc->szLocalFileName.append(dcc->szNick);
+ KviFileUtils::adjustFilePath(dcc->szLocalFileName);
+ }
+ KviFileUtils::makeDir(dcc->szLocalFileName);
+ }
+ }
+ g_pMediaManager->unlock();
+ }
+
+ if(dcc->szLocalFileName.isEmpty())
+ {
+ g_pApp->getLocalKvircDirectory(dcc->szLocalFileName,KviApp::Incoming);
+ if(KVI_OPTION_BOOL(KviOption_boolSortReceivedByDccFilesByNicks))
+ {
+ KviQString::ensureLastCharIs(dcc->szLocalFileName,KVI_PATH_SEPARATOR_CHAR);
+ dcc->szLocalFileName.append(dcc->szNick);
+ KviFileUtils::adjustFilePath(dcc->szLocalFileName);
+ KviFileUtils::makeDir(dcc->szLocalFileName);
+ }
+ }
+ }
+ KviFileUtils::adjustFilePath(dcc->szLocalFileName);
+ KviQString::ensureLastCharIs(dcc->szLocalFileName,KVI_PATH_SEPARATOR_CHAR);
+
+ if(!(dcc->bAutoAccept))
+ {
+ dcc->szLocalFileName+=dcc->szFileName;
+ if(KviFileDialog::askForSaveFileName(dcc->szLocalFileName,
+ __tr2qs_ctx("Choose Files to Save - KVIrc","dcc"),dcc->szLocalFileName))
+ {
+ renameOverwriteResume(0,dcc);
+ } else {
+ cancelDcc(dcc);
+ }
+ } else {
+ // auto accept
+ // WE choose the filename
+ dcc->szLocalFileName.append(dcc->szFileName);
+
+ if(_OUTPUT_VERBOSE)
+ {
+ dcc->console()->output(KVI_OUT_DCCMSG,__tr2qs_ctx("Auto-saving DCC %Q file %Q as \r![!dbl]play $0\r%Q\r","dcc"),
+ &(dcc->szType),&(dcc->szFileName),&(dcc->szLocalFileName));
+ }
+
+ renameOverwriteResume(0,dcc);
+ }
+}
+
+void KviDccBroker::renameOverwriteResume(KviDccBox *box,KviDccDescriptor * dcc)
+{
+ if(box)box->forgetDescriptor();
+
+ // Check if file exists
+ QFileInfo fi(dcc->szLocalFileName);
+ if(fi.exists() && (fi.size() > 0)) // 0 byte files are senseless for us
+ {
+ dcc->szLocalFileSize.setNum(fi.size());
+
+ bool bOk;
+ int iRemoteSize = dcc->szFileSize.toInt(&bOk);
+ if(!bOk)iRemoteSize = -1;
+
+ // FIXME: Files downloaded succesfully shouldn't be resumed
+ // we should keep a db of downloaded files!
+
+ if(!dcc->bAutoAccept)
+ {
+ QString tmp;
+ bool bDisableResume = false;
+
+ if((iRemoteSize > -1) || // remote size is unknown
+ (iRemoteSize > ((int)(fi.size())))) // or it is larger than the actual size on disk
+ {
+ tmp = __tr2qs_ctx( \
+ "The file '<b>%1</b>' already exists " \
+ "and is <b>%2</b> large.<br>" \
+ "Do you wish to<br>" \
+ "<b>overwrite</b> the existing file,<br> " \
+ "<b>auto-rename</b> the new file, or<br>" \
+ "<b>resume</b> an incomplete download?" \
+ ,"dcc" \
+ ).arg(dcc->szLocalFileName).arg(KviQString::makeSizeReadable(fi.size()));
+ } else {
+ bDisableResume = true;
+ // the file on disk is larger or equal to the remote one
+ tmp = __tr2qs_ctx( \
+ "The file '<b>%1</b>' already exists" \
+ "and is larger than the offered one.<br>" \
+ "Do you wish to<br>" \
+ "<b>overwrite</b> the existing file, or<br> " \
+ "<b>auto-rename</b> the new file ?" \
+ ,"dcc" \
+ ).arg(dcc->szLocalFileName);
+ }
+
+ KviDccRenameBox * box = new KviDccRenameBox(this,dcc,tmp,bDisableResume);
+ m_pBoxList->append(box);
+ connect(box,SIGNAL(renameSelected(KviDccBox *,KviDccDescriptor *)),
+ this,SLOT(renameDccSendFile(KviDccBox *,KviDccDescriptor *)));
+ connect(box,SIGNAL(overwriteSelected(KviDccBox *,KviDccDescriptor *)),
+ this,SLOT(recvFileExecute(KviDccBox *,KviDccDescriptor *)));
+ connect(box,SIGNAL(cancelSelected(KviDccBox *,KviDccDescriptor *)),
+ this,SLOT(cancelDcc(KviDccBox *,KviDccDescriptor *)));
+ box->show();
+ return;
+ } else {
+ // auto resume ?
+ if(KVI_OPTION_BOOL(KviOption_boolAutoResumeDccSendWhenAutoAccepted) &&
+ (iRemoteSize > -1) && // only if the remote size is really known
+ (iRemoteSize > ((int)(fi.size()))) && // only if the remote size is larger than the local size
+ (!KviDccFileTransfer::nonFailedTransferWithLocalFileName(dcc->szLocalFileName.utf8().data()))) // only if there is no transfer with this local file name yet
+ {
+ // yep, auto resume...
+ dcc->bResume = true;
+ recvFileExecute(0,dcc);
+ } else {
+ // otherwise auto rename
+ renameDccSendFile(0,dcc);
+ }
+ return;
+ }
+ } else dcc->szLocalFileSize = "0";
+
+ // everything OK
+ recvFileExecute(0,dcc);
+}
+
+void KviDccBroker::renameDccSendFile(KviDccBox *box,KviDccDescriptor * dcc)
+{
+ if(box)box->forgetDescriptor();
+
+
+ if(QFileInfo(dcc->szLocalFileName).exists())
+ {
+ KviStr szOrig = dcc->szLocalFileName;
+ int i = 1;
+ do {
+ KviStr szNum;
+ szNum.setNum(i);
+ int idx = szOrig.findLastIdx('.');
+ if(idx != -1)
+ {
+ dcc->szLocalFileName = szOrig.left(idx);
+ dcc->szLocalFileName += ".";
+ dcc->szLocalFileName += szNum;
+ dcc->szLocalFileName += szOrig.right(szOrig.len() - idx);
+ } else {
+ dcc->szLocalFileName = szOrig;
+ dcc->szLocalFileName += ".";
+ dcc->szLocalFileName += szNum;
+ }
+ i++;
+ } while(QFileInfo(dcc->szLocalFileName).exists());
+
+ if(_OUTPUT_VERBOSE)
+ {
+ dcc->console()->output(KVI_OUT_DCCMSG,__tr2qs_ctx("File %s exists, auto-renaming to %Q","dcc"),
+ szOrig.ptr(),&(dcc->szLocalFileName));
+ }
+ }
+
+ dcc->szLocalFileSize = "0"; // 0 for sure
+
+ recvFileExecute(0,dcc);
+}
+
+void KviDccBroker::recvFileExecute(KviDccBox *box,KviDccDescriptor * dcc)
+{
+ if(box)box->forgetDescriptor();
+
+ if(!g_pApp->windowExists(dcc->console()))
+ {
+ // rebind to the first available console....
+ dcc->setConsole(g_pApp->activeConsole());
+ }
+
+ //KviDccSend * send = new KviDccSend(dcc->console()->frame(),dcc,tmp.ptr());
+ KviDccFileTransfer * send = new KviDccFileTransfer(dcc);
+
+ bool bMinimized = dcc->bOverrideMinimize ? dcc->bShowMinimized : \
+ (KVI_OPTION_BOOL(KviOption_boolCreateMinimizedDccSend) || \
+ (dcc->bAutoAccept && KVI_OPTION_BOOL(KviOption_boolCreateMinimizedDccSendWhenAutoAccepted)));
+
+ send->invokeTransferWindow(dcc->console(),bMinimized,bMinimized);
+}
+
+
+void KviDccBroker::sendFileManage(KviDccDescriptor * dcc)
+{
+ QStringList filenames;
+ if(
+ KviFileDialog::askForOpenFileNames(filenames,
+ __tr2qs_ctx("Choose Files to Send - KVIrc","dcc"),"")
+ ) {
+ if(filenames.count() > 0)
+ {
+ KviDccDescriptor * d;
+ KviDccDescriptor * templ = dcc;
+ QStringList::Iterator it=filenames.begin();
+ while(it != filenames.end())
+ {
+ d = new KviDccDescriptor(*dcc);
+ d->szLocalFileName = *(it);
+ d->szLocalFileName.stripWhiteSpace();
+ ++it;
+ if(d->szLocalFileName.isEmpty())
+ cancelDcc(d);
+ else
+ sendFileExecute(0,d);
+ }
+ delete dcc;
+ }
+ } else {
+ cancelDcc(dcc);
+ }
+}
+
+void KviDccBroker::sendFileExecute(KviDccBox * box,KviDccDescriptor *dcc)
+{
+ if(box)box->forgetDescriptor();
+
+ if(!g_pApp->windowExists(dcc->console()))
+ {
+ // rebind to the first available console....
+ dcc->setConsole(g_pApp->activeConsole());
+ }
+
+ QFileInfo fi(dcc->szLocalFileName);
+ if(!(fi.exists() && fi.isReadable() && (fi.isFile()) && (fi.size() > 0)))
+ {
+ dcc->console()->output(KVI_OUT_DCCERROR,__tr2qs_ctx("Can't open file %Q for reading","dcc"),
+ &(dcc->szLocalFileName));
+ delete dcc;
+ return;
+ }
+
+ dcc->szFileName = dcc->szLocalFileName;
+ dcc->szFileName = QFileInfo(dcc->szFileName).fileName();
+
+ dcc->szLocalFileSize.setNum(fi.size());
+
+ KviDccFileTransfer * send = new KviDccFileTransfer(dcc);
+
+ bool bMinimized = dcc->bOverrideMinimize ? dcc->bShowMinimized : KVI_OPTION_BOOL(KviOption_boolCreateMinimizedDccSend);
+
+ send->invokeTransferWindow(dcc->console(),bMinimized,bMinimized);
+}
+
+bool KviDccBroker::canUnload()
+{
+ if(m_pBoxList)
+ {
+ if((m_pBoxList->count() != 0) ||
+ (m_pDccWindowList->count() != 0) ||
+ (KviDccFileTransfer::transferCount() != 0))return false;
+ } // else in the destructor anyway (going to die)
+ return true;
+}
+
+bool KviDccBroker::handleResumeAccepted(const char * filename,const char * port,const char * szZeroPortTag)
+{
+ return KviDccFileTransfer::handleResumeAccepted(filename,port,szZeroPortTag);
+}
+
+bool KviDccBroker::handleResumeRequest(KviDccRequest * dcc,const char * filename,const char * port,unsigned int filePos,const char * szZeroPortTag)
+{
+ //debug("HANDLE %s %s %u %s",filename,port,filePos,szZeroPortTag);
+ // the zeroPOrtTag is nonempty here only if port == 0
+ if(kvi_strEqualCI("0",port) && szZeroPortTag)
+ {
+ // zero port resume request (we have sent out a DCC SEND <filename> <fakeip> 0 <tag>
+ KviDccZeroPortTag * t = findZeroPortTag(QString(szZeroPortTag));
+ if(t)
+ {
+ //debug("FOUND");
+ // valid zero port resume request
+ if(filePos < t->m_uFileSize)
+ {
+ //debug("VALID");
+ // ok!
+ t->m_uResumePosition = filePos;
+
+ KviStr szBuffy;
+ KviServerParser::encodeCtcpParameter(filename,szBuffy);
+
+ dcc->ctcpMsg->msg->console()->connection()->sendFmtData(
+ "PRIVMSG %s :%cDCC ACCEPT %s %s %u %s%c",
+ dcc->ctcpMsg->msg->console()->connection()->encodeText(dcc->ctcpMsg->pSource->nick()).data(),
+ 0x01,
+ szBuffy.ptr(),
+ port,
+ filePos,
+ szZeroPortTag,
+ 0x01);
+
+ return true;
+ } else {
+ return false; // invalid resume size
+ }
+ }
+ }
+ //debug("NOT A ZeRO PORT");
+
+ return KviDccFileTransfer::handleResumeRequest(filename,port,filePos);
+}
+
+
+#include "m_broker.moc"
diff --git a/src/modules/dcc/broker.h b/src/modules/dcc/broker.h
new file mode 100644
index 00000000..80fa9768
--- /dev/null
+++ b/src/modules/dcc/broker.h
@@ -0,0 +1,124 @@
+#ifndef _BROKER_H_
+#define _BROKER_H_
+//=======================================================================================
+//
+// File : broker.h
+// Creation date : Tue Sep 19 09 2000 10:20:01 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=======================================================================================
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_USE_QT4
+ // #define COMPILE_DCC_CANVAS
+#else
+ #define COMPILE_DCC_CANVAS
+#endif
+
+#include "kvi_string.h"
+#include "kvi_pointerlist.h"
+#include "kvi_sparser.h"
+
+#include "kvi_pointerhashtable.h"
+#include <qdatetime.h>
+#include <qobject.h>
+
+class KviConsole;
+class KviDccBroker;
+class KviWindow;
+class KviDccBox;
+
+#include "descriptor.h"
+
+class KviDccZeroPortTag
+{
+public:
+ QDateTime m_tTimestamp;
+ QString m_szTag;
+ unsigned int m_uFileSize; // outgoing file size, valid only for file transfers obviously
+ unsigned int m_uResumePosition; // if 0 = no resume, valid only for file transfers obviously
+};
+
+class KviDccBroker : public QObject
+{
+ Q_OBJECT
+public:
+ KviDccBroker();
+ ~KviDccBroker();
+protected:
+ KviPointerList<KviDccBox> * m_pBoxList;
+ KviPointerList<KviWindow> * m_pDccWindowList;
+ KviPointerHashTable<QString,KviDccZeroPortTag> * m_pZeroPortTags;
+public:
+ KviDccZeroPortTag * addZeroPortTag();
+ KviDccZeroPortTag * findZeroPortTag(const QString &szTag);
+ void removeZeroPortTag(const QString &szTag);
+
+ unsigned int dccWindowsCount(){ return m_pDccWindowList->count(); };
+ unsigned int dccBoxCount();
+
+ void unregisterDccBox(KviDccBox * box);
+ void unregisterDccWindow(KviWindow *dcc);
+
+ void rsendManage(KviDccDescriptor * dcc);
+ void rsendAskForFileName(KviDccDescriptor * dcc);
+
+ void handleChatRequest(KviDccDescriptor * dcc);
+
+#ifdef COMPILE_DCC_CANVAS
+ void activeCanvasManage(KviDccDescriptor * dcc);
+ void passiveCanvasExecute(KviDccDescriptor * dcc);
+#endif
+
+ void activeVoiceManage(KviDccDescriptor * dcc);
+ void passiveVoiceExecute(KviDccDescriptor * dcc);
+
+ void recvFileManage(KviDccDescriptor * dcc);
+ void sendFileManage(KviDccDescriptor * dcc);
+
+ bool handleResumeAccepted(const char * filename,const char * port,const char * szZeroPortTag);
+ bool handleResumeRequest(KviDccRequest * dcc,const char * filename,const char * port,unsigned int filePos,const char * szZeroPortTag);
+
+public slots:
+ void rsendExecute(KviDccBox * box,KviDccDescriptor * dcc);
+ void rsendExecute(KviDccDescriptor * dcc);
+
+// void activeChatExecute(KviDccBox * box,KviDccDescriptor * dcc);
+ void executeChat(KviDccBox * box,KviDccDescriptor * dcc);
+
+ void activeCanvasExecute(KviDccBox * box,KviDccDescriptor * dcc);
+ void activeVoiceExecute(KviDccBox * box,KviDccDescriptor * dcc);
+
+ void sendFileExecute(KviDccBox * box,KviDccDescriptor * dcc);
+ void recvFileExecute(KviDccBox * box,KviDccDescriptor * dcc);
+
+
+ void chooseSaveFileName(KviDccBox *box,KviDccDescriptor * dcc);
+ void renameOverwriteResume(KviDccBox *box,KviDccDescriptor * dcc);
+ void renameDccSendFile(KviDccBox *box,KviDccDescriptor * dcc);
+
+ void cancelDcc(KviDccBox *box,KviDccDescriptor * dcc);
+ void cancelDcc(KviDccDescriptor * dcc);
+
+public:
+ bool canUnload();
+};
+
+#endif
diff --git a/src/modules/dcc/canvas.cpp b/src/modules/dcc/canvas.cpp
new file mode 100644
index 00000000..e80272ae
--- /dev/null
+++ b/src/modules/dcc/canvas.cpp
@@ -0,0 +1,301 @@
+//
+// File : canvas.cpp
+// Creation date : Sun Jul 29 07 2001 20:23:13 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#define QT_MODULE_CANVAS
+
+#include "canvas.h"
+
+#ifdef COMPILE_DCC_CANVAS
+
+#include "dialogs.h"
+#include "marshal.h"
+#include "canvaswidget.h"
+
+#define _KVI_DEBUG_CHECK_RANGE_
+#include "kvi_debug.h"
+#include "kvi_options.h"
+#include "kvi_input.h"
+#include "kvi_ircview.h"
+#include "kvi_iconmanager.h"
+#include "kvi_locale.h"
+#include "kvi_error.h"
+#include "kvi_out.h"
+#include "kvi_netutils.h"
+#include "kvi_console.h"
+#include "kvi_frame.h"
+#include "kvi_malloc.h"
+#include "kvi_memmove.h"
+#include "kvi_thread.h"
+#include "kvi_ircsocket.h"
+#include "kvi_settings.h"
+#include "kvi_themedlabel.h"
+#include "kvi_ircconnection.h"
+
+#include <qsplitter.h>
+
+extern KviDccBroker * g_pDccBroker;
+
+
+KviDccCanvas::KviDccCanvas(KviFrame *pFrm,KviDccDescriptor * dcc,const char * name)
+: KviDccWindow(KVI_WINDOW_TYPE_DCCCANVAS,pFrm,name,dcc)
+{
+ m_pSplitter = new QSplitter(QSplitter::Vertical,this,"splitter");
+
+ m_pCanvas = new KviCanvasWidget(m_pSplitter);
+
+ m_pIrcView = new KviIrcView(m_pSplitter,pFrm,this);
+ m_pInput = new KviInput(this);
+
+// setFocusHandler(m_pInput,this);
+
+ m_pMarshal = new KviDccMarshal(this);
+ connect(m_pMarshal,SIGNAL(error(int)),this,SLOT(handleMarshalError(int)));
+ connect(m_pMarshal,SIGNAL(connected()),this,SLOT(connected()));
+
+
+ if(!(m_pDescriptor->bActive))
+ {
+ // PASSIVE CONNECTION
+ output(KVI_OUT_DCCMSG,__tr2qs_ctx("Attempting a passive DCC CANVAS connection","dcc"));
+ int ret = m_pMarshal->dccListen(dcc->szListenIp,dcc->szListenPort,m_pDescriptor->bDoTimeout);
+ if(ret != KviError_success)handleMarshalError(ret);
+ else {
+
+ output(KVI_OUT_DCCMSG,__tr2qs_ctx("Listening on interface %Q port %Q","dcc"),
+ &(m_pMarshal->localIp()),&(m_pMarshal->localPort()));
+
+ if(dcc->bSendRequest)
+ {
+ QString ip = !dcc->szFakeIp.isEmpty() ? dcc->szFakeIp : dcc->szListenIp;
+ QString port = !dcc->szFakePort.isEmpty() ? dcc->szFakePort.utf8().data() : m_pMarshal->localPort();
+//#warning "OPTION FOR SENDING 127.0.0.1 and so on (not an unsigned number)"
+ struct in_addr a;
+ if(kvi_stringIpToBinaryIp(ip.utf8().data(),&a))ip.setNum(htonl(a.s_addr));
+ dcc->console()->connection()->sendFmtData("PRIVMSG %s :%cDCC CANVAS chat %Q %Q%c",
+ dcc->console()->connection()->encodeText( dcc->szNick.utf8().data() ).data(),
+ 0x01,&ip,
+ &port,
+ 0x01);
+ output(KVI_OUT_DCCMSG,__tr2qs_ctx("Sent DCC CANVAS request to %Q, waiting for the remote client to connect...","dcc"),
+ &(dcc->szNick));
+ } else outputNoFmt(KVI_OUT_DCCMSG,__tr2qs_ctx("DCC CANVAS request not sent: awaiting manual connections","dcc"));
+ }
+ } else {
+ // ACTIVE CONNECTION
+ outputNoFmt(KVI_OUT_DCCMSG,__tr2qs_ctx("Attempting an active DCC CANVAS connection","dcc"));
+ int ret = m_pMarshal->dccConnect(dcc->szIp.utf8().data(),dcc->szPort.utf8().data(),m_pDescriptor->bDoTimeout);
+ if(ret != KviError_success)handleMarshalError(ret);
+ else output(KVI_OUT_DCCMSG,__tr2qs_ctx("Contacting host %Q on port %Q","dcc"),&(dcc->szIp),&(dcc->szPort));
+ }
+
+// m_pSlaveThread = 0;
+}
+
+KviDccCanvas::~KviDccCanvas()
+{
+ g_pDccBroker->unregisterDccWindow(this);
+// if(m_pSlaveThread)
+// {
+// m_pSlaveThread->terminate();
+// delete m_pSlaveThread;
+// m_pSlaveThread = 0;
+// }
+ KviThreadManager::killPendingEvents(this);
+// delete m_pDescriptor;
+// delete m_pMarshal;
+}
+
+const QString & KviDccCanvas::target()
+{
+ // This may change on the fly...
+ m_szTarget.sprintf("%s@%s:%s",
+ m_pDescriptor->szNick.utf8().data(),m_pDescriptor->szIp.utf8().data(),m_pDescriptor->szPort.utf8().data());
+ return m_szTarget;
+}
+
+void KviDccCanvas::fillCaptionBuffers()
+{
+ KviStr tmp(KviStr::Format,"DCC Canvas %s@%s:%s",
+ m_pDescriptor->szNick.utf8().data(),m_pDescriptor->szIp.utf8().data(),m_pDescriptor->szPort.utf8().data());
+
+ m_szPlainTextCaption = tmp;
+
+ m_szHtmlActiveCaption.sprintf("<nobr><font color=\"%s\"><b>%s</b></font></nobr>",
+ KVI_OPTION_COLOR(KviOption_colorCaptionTextActive).name().ascii(),tmp.ptr());
+ m_szHtmlInactiveCaption.sprintf("<nobr><font color=\"%s\"><b>%s</b></font></nobr>",
+ KVI_OPTION_COLOR(KviOption_colorCaptionTextInactive).name().ascii(),tmp.ptr());
+}
+
+QPixmap * KviDccCanvas::myIconPtr()
+{
+ return g_pIconManager->getSmallIcon(KVI_SMALLICON_CANVAS);
+}
+
+
+void KviDccCanvas::getBaseLogFileName(KviStr &buffer)
+{
+ buffer.sprintf("%s_%s_%s",m_pDescriptor->szNick.utf8().data(),m_pDescriptor->szIp.utf8().data(),m_pDescriptor->szPort.utf8().data());
+}
+
+void KviDccCanvas::ownMessage(const char * text)
+{
+ KviStr buf(KviStr::Format,"%s\r\n",text);
+// m_pSlaveThread->sendRawData(buf.ptr(),buf.len());
+ m_pFrm->firstConsole()->outputPrivmsg(this,KVI_OUT_OWNPRIVMSG,
+ m_pDescriptor->szLocalNick.utf8().data(),m_pDescriptor->szLocalUser.utf8().data(),
+ m_pDescriptor->szLocalHost.utf8().data(),text);
+}
+
+void KviDccCanvas::ownAction(const char * text)
+{
+ KviStr buf(KviStr::Format,"%cACTION %s%c\r\n",text);
+// m_pSlaveThread->sendRawData(buf.ptr(),buf.len());
+ output(KVI_OUT_ACTION,"%Q %s",&(m_pDescriptor->szLocalNick),text);
+}
+
+bool KviDccCanvas::event(QEvent *e)
+{
+// if(e->type() == KVI_THREAD_EVENT)
+// {
+// switch(((KviThreadEvent *)e)->id())
+// {
+// case KVI_DCC_THREAD_EVENT_ERROR:
+// {
+// int * err = ((KviThreadDataEvent<int> *)e)->getData();
+// output(KVI_OUT_DCCERROR,__tr("ERROR: %s"),kvi_getErrorString(*err));
+// delete err;
+// return true;
+// }
+// break;
+// case KVI_DCC_THREAD_EVENT_DATA:
+// {
+// KviStr * d = ((KviThreadDataEvent<KviStr> *)e)->getData();
+// if(d->firstCharIs(0x01))
+// {
+// d->cutLeft(1);
+// if(d->lastCharIs(0x01))d->cutRight(1);
+// if(kvi_strEqualCIN("ACTION",d->ptr(),6))d->cutLeft(6);
+// d->stripLeftWhiteSpace();
+// output(KVI_OUT_ACTION,"%s %s",m_pDescriptor->szNick.ptr(),d->ptr());
+// } else {
+//
+//#ifdef COMPILE_CRYPT_SUPPORT
+// if(KviCryptSessionInfo * cinf = cryptSessionInfo())
+// {
+// if(cinf->bDoDecrypt)
+// {
+// if(cinf->pEngine->isCryptographicEngine() && (*(d->ptr()) == KVI_TEXT_CRYPT))
+// {
+// KviStr decryptedStuff;
+// if(cinf->pEngine->decrypt(d->ptr() + 1,decryptedStuff))
+// {
+// m_pFrm->firstConsole()->outputPrivmsg(this,KVI_OUT_DCCCHATMSGCRYPTED,
+// m_pDescriptor->szNick.ptr(),m_pDescriptor->szUser.ptr(),
+// m_pDescriptor->szHost.ptr(),decryptedStuff.ptr());
+// } else {
+// output(KVI_OUT_SYSTEMERROR,
+// __tr("The following message looks like an encrypted one, but the crypting engine failed to decode it: %s"),
+// cinf->pEngine->lastError());
+// m_pFrm->firstConsole()->outputPrivmsg(this,KVI_OUT_DCCCHATMSG,
+// m_pDescriptor->szNick.ptr(),m_pDescriptor->szUser.ptr(),
+// m_pDescriptor->szHost.ptr(),d->ptr() + 1);
+// }
+// delete d;
+// return true;
+// } else {
+// if(!(cinf->pEngine->isCryptographicEngine()))
+// {
+// KviStr decryptedStuff;
+// if(cinf->pEngine->decrypt(d->ptr(),decryptedStuff))
+// {
+// m_pFrm->firstConsole()->outputPrivmsg(this,KVI_OUT_DCCCHATMSG,
+// m_pDescriptor->szNick.ptr(),m_pDescriptor->szUser.ptr(),
+// m_pDescriptor->szHost.ptr(),decryptedStuff.ptr());
+// delete d;
+// return true;
+// } else {
+// output(KVI_OUT_SYSTEMERROR,
+// __tr("The following message looks like an encrypted one, but the crypting engine failed to decode it: %s"),
+// cinf->pEngine->lastError());
+// }
+// }
+// }
+// }
+// }
+//#endif
+// m_pFrm->firstConsole()->outputPrivmsg(this,KVI_OUT_DCCCHATMSG,
+// m_pDescriptor->szNick.ptr(),m_pDescriptor->szUser.ptr(),
+// m_pDescriptor->szHost.ptr(),d->ptr());
+// }
+// delete d;
+// return true;
+// }
+// break;
+// }
+// }
+ return KviWindow::event(e);
+}
+
+void KviDccCanvas::resizeEvent(QResizeEvent *e)
+{
+ int hght = m_pInput->heightHint();
+// int hght2 = m_pTopSplitter->sizeHint().height();
+// m_pTopSplitter->setGeometry(0,0,width(),hght2);
+ m_pSplitter->setGeometry(0,0,width(),height() - hght);
+ m_pInput->setGeometry(0,height() - hght,width(),hght);
+}
+
+QSize KviDccCanvas::sizeHint() const
+{
+ QSize ret(m_pIrcView->sizeHint().width(),
+ m_pIrcView->sizeHint().height() + m_pInput->heightHint());
+ return ret;
+}
+
+void KviDccCanvas::handleMarshalError(int err)
+{
+ QString sss = KviError::getDescription(err);
+ output(KVI_OUT_DCCERROR,__tr2qs_ctx("DCC Failed: %Q","dcc"),&sss);
+}
+
+void KviDccCanvas::connected()
+{
+ output(KVI_OUT_DCCMSG,__tr2qs_ctx("Connected to %Q:%Q","dcc"),
+ &(m_pMarshal->remoteIp()),&(m_pMarshal->remotePort()));
+ output(KVI_OUT_DCCMSG,__tr2qs_ctx("Local end is %Q:%Q","dcc"),
+ &(m_pMarshal->localIp()),&(m_pMarshal->localPort()));
+ if(!(m_pDescriptor->bActive))
+ {
+ // PASSIVE CONNECTION...Find out the remote end
+ m_pDescriptor->szIp = m_pMarshal->remoteIp();
+ m_pDescriptor->szPort = m_pMarshal->remotePort();
+ m_pDescriptor->szHost = m_pMarshal->remoteIp();
+ }
+ updateCaption();
+// m_pSlaveThread = new KviDccCanvasThread(this,m_pMarshal->releaseSocket());
+// m_pSlaveThread->start();
+}
+
+
+#include "m_canvas.moc"
+
+#endif
diff --git a/src/modules/dcc/canvas.h b/src/modules/dcc/canvas.h
new file mode 100644
index 00000000..8e6b1fb3
--- /dev/null
+++ b/src/modules/dcc/canvas.h
@@ -0,0 +1,74 @@
+#ifndef _CANVAS_H_
+#define _CANVAS_H_
+//
+// File : canvas.h
+// Creation date : Sun Jul 29 07 2001 20:17:12 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "broker.h"
+
+#ifdef COMPILE_DCC_CANVAS
+
+#include "kvi_window.h"
+#include "kvi_string.h"
+
+#include "descriptor.h"
+#include "window.h"
+#include "thread.h"
+
+#include "kvi_pointerlist.h"
+
+
+
+class KviDccMarshal;
+class KviCanvasWidget;
+
+class QSplitter;
+
+
+class KviDccCanvas : public KviDccWindow
+{
+ Q_OBJECT
+public:
+ KviDccCanvas(KviFrame *pFrm,KviDccDescriptor * dcc,const char * name);
+ ~KviDccCanvas();
+protected:
+// KviDccCanvasThread * m_pSlaveThread;
+ KviCanvasWidget * m_pCanvas;
+// QSplitter * m_pTopSplitter;
+ QString m_szTarget;
+protected:
+ virtual const QString &target();
+ virtual void fillCaptionBuffers();
+ virtual void getBaseLogFileName(KviStr &buffer);
+ virtual QPixmap * myIconPtr();
+ virtual void resizeEvent(QResizeEvent *e);
+ virtual QSize sizeHint() const;
+ virtual bool event(QEvent *e);
+ virtual void ownMessage(const char *text);
+ virtual void ownAction(const char *text);
+protected slots:
+ void handleMarshalError(int err);
+ void connected();
+};
+
+#endif
+
+#endif // _CANVAS_H_
diff --git a/src/modules/dcc/canvaswidget.cpp b/src/modules/dcc/canvaswidget.cpp
new file mode 100644
index 00000000..203e0b36
--- /dev/null
+++ b/src/modules/dcc/canvaswidget.cpp
@@ -0,0 +1,1601 @@
+//
+// File : canvaswidget.cpp
+// Creation date : Mon Jul 30 07 2001 04:50:50 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "canvaswidget.h"
+
+#ifdef COMPILE_DCC_CANVAS
+
+
+#include <qcursor.h>
+#include <qpainter.h>
+#include <qsimplerichtext.h>
+#include <qlineedit.h>
+#include <qcombobox.h>
+#include <qvalidator.h>
+#include <stdlib.h>
+
+#include "kvi_string.h"
+
+#include "kvi_locale.h"
+#include "kvi_tal_popupmenu.h"
+
+#include <math.h>
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// KviCanvasRectangleItem
+//
+
+KviCanvasRectangleItem::KviCanvasRectangleItem(QCanvas * c,int x,int y,int w,int h)
+: QCanvasRectangle(x,y,w,h,c)
+{
+}
+
+KviCanvasRectangleItem::~KviCanvasRectangleItem()
+{
+}
+
+void KviCanvasRectangleItem::drawSelection(QPainter &p)
+{
+ p.setRasterOp(NotROP);
+ p.fillRect((int)x() + 1,(int)y() + 1,width() - 2,height() - 2,QBrush(Dense6Pattern));
+ p.setPen(QPen(DotLine));
+ p.drawRect((int)x(),(int)y(),width(),height());
+ p.setRasterOp(CopyROP);
+}
+
+
+void KviCanvasRectangleItem::setProperty(const QString &property,const QVariant &val)
+{
+ if(m_properties[property].isValid())
+ {
+ m_properties.replace(property,val);
+ hide();
+ show();
+ }
+}
+
+
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// KviCanvasPolygon
+//
+
+
+KviCanvasPolygon::KviCanvasPolygon(QCanvas * c,int x,int y,QPointArray &pnts,double dScaleFactor)
+: QCanvasPolygon(c)
+{
+ m_properties.insert("clrForeground",QVariant(QColor(0,0,0)));
+ m_properties.insert("uLineWidth",QVariant((unsigned int)0));
+
+ m_properties.insert("clrBackground",QVariant(QColor(0,0,0)));
+ m_properties.insert("bHasBackground",QVariant(false,1));
+
+ m_dScaleFactor = dScaleFactor;
+ m_points = pnts;
+
+ resetPoints();
+ move(x,y);
+}
+
+
+KviCanvasPolygon::~KviCanvasPolygon()
+{
+}
+
+void KviCanvasPolygon::setScaleFactor(double dScaleFactor)
+{
+ m_dScaleFactor = dScaleFactor;
+ resetPoints();
+}
+
+void KviCanvasPolygon::setInternalPoints(const QPointArray &pnts)
+{
+ m_points = pnts;
+ resetPoints();
+
+}
+
+void KviCanvasPolygon::resetPoints()
+{
+ QPointArray scaled(m_points.size());
+ for(unsigned int i=0;i<m_points.size();i++)
+ {
+ int px;
+ int py;
+ m_points.point(i,&px,&py);
+ px = (int)(px * m_dScaleFactor);
+ py = (int)(py * m_dScaleFactor);
+ scaled.setPoint(i,px,py);
+ }
+ setPoints(scaled);
+}
+
+int KviCanvasPolygon::rtti() const
+{
+ return KVI_CANVAS_RTTI_POLYGON;
+}
+
+void KviCanvasPolygon::setProperty(const QString &property,const QVariant &val)
+{
+ if(m_properties[property].isValid())
+ {
+ m_properties.replace(property,val);
+ if((property == "clrForeground") || (property == "uLineWidth"))
+ {
+ setPen(QPen(m_properties["clrForeground"].asColor(),m_properties["uLineWidth"].toInt()));
+ } else if((property == "clrBackground") || (property == "bHasBackground"))
+ {
+ if(m_properties["bHasBackground"].asBool())
+ setBrush(QBrush(m_properties["clrBackground"].asColor()));
+ else
+ setBrush(QBrush());
+ } else {
+ hide(); show();
+ }
+ }
+}
+
+void KviCanvasPolygon::draw(QPainter &p)
+{
+#if QT_VERSION >= 300
+ if(isEnabled())
+#else
+ if(enabled())
+#endif
+ {
+ p.setBrush(brush());
+ p.setPen(pen());
+ p.drawPolygon(areaPoints());
+ }
+
+#if QT_VERSION >=300
+ if(isSelected())
+#else
+ if(selected())
+#endif
+ {
+ p.setRasterOp(NotROP);
+ p.setPen(QPen(DotLine));
+ p.drawPolygon(areaPoints());
+ p.setBrush(QBrush());
+ double dVal = 10;
+ p.drawEllipse((int)(x() - dVal),(int)(y() - dVal),(int)(dVal * 2),(int)(dVal * 2));
+ p.drawLine((int)(x() - (dVal * 2)),(int)y(),(int)(x() + (dVal * 2)),(int)y());
+ p.drawLine((int)x(),(int)(y() - (dVal * 2)),(int)x(),(int)(y() + (dVal * 2)));
+ p.setRasterOp(CopyROP);
+ canvas()->setChanged(QRect((int)(x() - dVal),(int)(y() - dVal),(int)(dVal * 4),(int)(dVal * 4)));
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// KviCanvasEllipticItem
+//
+
+KviCanvasEllipticItem::KviCanvasEllipticItem(QCanvas * c,int x,int y,int w,int h)
+: KviCanvasRectangleItem(c,x,y,w,h)
+{
+ m_properties.insert("clrForeground",QVariant(QColor(0,0,0)));
+ m_properties.insert("uLineWidth",QVariant((unsigned int)0));
+
+ m_properties.insert("clrBackground",QVariant(QColor(0,0,0)));
+ m_properties.insert("bHasBackground",QVariant(false,1));
+
+// m_properties.insert("iStartAngle",QVariant(0));
+// m_properties.insert("iEndAngle",QVariant(360));
+}
+
+KviCanvasEllipticItem::~KviCanvasEllipticItem()
+{
+}
+
+void KviCanvasEllipticItem::draw(QPainter &p)
+{
+#if QT_VERSION >= 300
+ if(isEnabled())
+#else
+ if(enabled())
+#endif
+ {
+ QBrush b = p.brush();
+ if(m_properties["bHasBackground"].asBool())p.setBrush(m_properties["clrBackground"].asColor());
+ else p.setBrush(QBrush());
+ p.setPen(pen());
+ drawContent(p);
+ p.setBrush(b);
+ }
+
+#if QT_VERSION >= 300
+ if(isSelected())drawSelection(p);
+#else
+ if(selected())drawSelection(p);
+#endif
+}
+
+void KviCanvasEllipticItem::drawContent(QPainter &p)
+{
+}
+
+
+void KviCanvasEllipticItem::setProperty(const QString & property,const QVariant &val)
+{
+ if(m_properties[property].isValid())
+ {
+ m_properties.replace(property,val);
+ if((property == "clrForeground") || (property == "uLineWidth"))
+ {
+ setPen(QPen(m_properties["clrForeground"].asColor(),m_properties["uLineWidth"].toInt()));
+ } else {
+ hide(); show();
+ }
+ }
+}
+
+int KviCanvasEllipticItem::rtti() const
+{
+ return KVI_CANVAS_RTTI_ELLIPSE;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// KviCanvasEllipse
+//
+
+
+KviCanvasEllipse::KviCanvasEllipse(QCanvas * c,int x,int y,int w,int h)
+: KviCanvasEllipticItem(c,x,y,w,h)
+{
+}
+
+KviCanvasEllipse::~KviCanvasEllipse()
+{
+}
+
+int KviCanvasEllipse::rtti() const
+{
+ return KVI_CANVAS_RTTI_ELLIPSE;
+}
+
+void KviCanvasEllipse::drawContent(QPainter &p)
+{
+ p.drawEllipse((int)x(),(int)y(),width(),height());
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// KviCanvasPie
+//
+
+
+KviCanvasPie::KviCanvasPie(QCanvas * c,int x,int y,int w,int h)
+: KviCanvasEllipticItem(c,x,y,w,h)
+{
+ m_properties.insert("iStartAngle",QVariant((int)0));
+ m_properties.insert("iExtensionAngle",QVariant((int)360));
+}
+
+KviCanvasPie::~KviCanvasPie()
+{
+}
+
+int KviCanvasPie::rtti() const
+{
+ return KVI_CANVAS_RTTI_PIE;
+}
+
+void KviCanvasPie::drawContent(QPainter &p)
+{
+ int iStartAngle = m_properties["iStartAngle"].asInt() * 16;
+ int iEndAngle = m_properties["iExtensionAngle"].asInt() * 16;
+ p.drawPie((int)x(),(int)y(),width(),height(),iStartAngle,iEndAngle);
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// KviCanvasChord
+//
+
+
+KviCanvasChord::KviCanvasChord(QCanvas * c,int x,int y,int w,int h)
+: KviCanvasEllipticItem(c,x,y,w,h)
+{
+ m_properties.insert("iStartAngle",QVariant((int)0));
+ m_properties.insert("iExtensionAngle",QVariant((int)360));
+}
+
+KviCanvasChord::~KviCanvasChord()
+{
+}
+
+int KviCanvasChord::rtti() const
+{
+ return KVI_CANVAS_RTTI_CHORD;
+}
+
+void KviCanvasChord::drawContent(QPainter &p)
+{
+ int iStartAngle = m_properties["iStartAngle"].asInt() * 16;
+ int iEndAngle = m_properties["iExtensionAngle"].asInt() * 16;
+ p.drawChord((int)x(),(int)y(),width(),height(),iStartAngle,iEndAngle);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// KviCanvasRectangle
+//
+
+KviCanvasRectangle::KviCanvasRectangle(QCanvas * c,int x,int y,int w,int h)
+: KviCanvasRectangleItem(c,x,y,w,h)
+{
+ m_properties.insert("clrForeground",QVariant(QColor(0,0,0)));
+ m_properties.insert("uLineWidth",QVariant((unsigned int)0));
+
+ m_properties.insert("clrBackground",QVariant(QColor(0,0,0)));
+ m_properties.insert("bHasBackground",QVariant(false,1));
+}
+
+KviCanvasRectangle::~KviCanvasRectangle()
+{
+}
+
+int KviCanvasRectangle::rtti() const
+{
+ return KVI_CANVAS_RTTI_RECTANGLE;
+}
+
+
+void KviCanvasRectangle::setProperty(const QString &property,const QVariant &val)
+{
+ if(m_properties[property].isValid())
+ {
+ m_properties.replace(property,val);
+ if((property == "clrForeground") || (property == "uLineWidth"))
+ {
+ setPen(QPen(m_properties["clrForeground"].asColor(),m_properties["uLineWidth"].toInt()));
+ } else {
+ hide(); show();
+ }
+ }
+}
+
+void KviCanvasRectangle::draw(QPainter & p)
+{
+#if QT_VERSION >= 300
+ if(isEnabled())
+#else
+ if(enabled())
+#endif
+ {
+ if(m_properties["bHasBackground"].asBool())
+ {
+ p.fillRect((int)x() + 1,(int)y() + 1,width() - 2,height() - 2,m_properties["clrBackground"].asColor());
+ }
+ p.setPen(pen());
+ p.drawRect((int)x(),(int)y(),width(),height());
+ }
+#if QT_VERSION >= 300
+ if(isSelected())drawSelection(p);
+#else
+ if(selected())drawSelection(p);
+#endif
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// KviCanvasRichText
+//
+
+KviCanvasRichText::KviCanvasRichText(QCanvas * c,int x,int y,int w,int h)
+: KviCanvasRectangleItem(c,x,y,w,h)
+{
+ QFont f = QFont();
+ f.setStyleHint(QFont::SansSerif);
+ f.setPointSize(12);
+ m_properties.insert("szText",QVariant(QString("<center>Insert here your <font color=\"#FF0000\"><b>RICH TEXT</b></font></center>")));
+ m_properties.insert("fntDefault",QVariant(f));
+}
+
+KviCanvasRichText::~KviCanvasRichText()
+{
+}
+
+int KviCanvasRichText::rtti() const
+{
+ return KVI_CANVAS_RTTI_RICHTEXT;
+}
+
+void KviCanvasRichText::draw(QPainter & p)
+{
+#if QT_VERSION >= 300
+ if(isEnabled())
+#else
+ if(enabled())
+#endif
+ {
+ QString szText = m_properties["szText"].asString();
+ QSimpleRichText text(szText,m_properties["fntDefault"].asFont());
+ text.setWidth(width());
+#if QT_VERSION >= 300
+ text.draw(&p,(int)x() + 1,(int)y() + 1,QRegion(QRect((int)x() + 1,(int)y() + 1,width(),height())),QColorGroup());
+#else
+ text.draw(&p,(int)x() + 1,(int)y() + 1,QRegion(QRect((int)x() + 1,(int)y() + 1,width(),height())),QPalette());
+#endif
+ }
+#if QT_VERSION >= 300
+ if(isSelected())drawSelection(p);
+#else
+ if(selected())drawSelection(p);
+#endif
+}
+
+
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// KviCanvasLine
+//
+
+
+KviCanvasLine::KviCanvasLine(QCanvas * c,int x1,int y1,int x2,int y2)
+: QCanvasLine(c)
+{
+ setPoints(x1,y1,x2,y2);
+ m_properties.insert("uLineWidth",QVariant((unsigned int)0));
+ m_properties.insert("clrForeground",QVariant(QColor()));
+}
+
+KviCanvasLine::~KviCanvasLine()
+{
+}
+
+void KviCanvasLine::setProperty(const QString &property,const QVariant &val)
+{
+ m_properties.replace(property,val);
+ if((property == "uLineWidth") || (property == "clrForeground"))
+ {
+ setPen(QPen(m_properties["clrForeground"].asColor(),m_properties["uLineWidth"].toInt()));
+ }
+}
+
+int KviCanvasLine::rtti() const
+{
+ return KVI_CANVAS_RTTI_LINE;
+}
+
+void KviCanvasLine::draw(QPainter &p)
+{
+#if QT_VERSION >= 300
+ if(isEnabled())
+#else
+ if(enabled())
+#endif
+ {
+ p.setPen(pen());
+ p.drawLine(startPoint(),endPoint());
+ }
+
+#if QT_VERSION >= 300
+ if(isSelected())
+#else
+ if(selected())
+#endif
+ {
+ p.setRasterOp(NotROP);
+ p.setPen(QPen(DotLine));
+ p.drawLine(startPoint(),endPoint());
+ p.setRasterOp(CopyROP);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// KviCanvasView
+//
+
+KviCanvasView::KviCanvasView(QCanvas * c,KviCanvasWidget * cw,QWidget * par)
+: QCanvasView(c,par)
+{
+ m_pCanvasWidget = cw;
+ m_state = Idle;
+ m_dragMode = None;
+ m_pSelectedItem = 0;
+ viewport()->setMouseTracking(true);
+}
+
+
+KviCanvasView::~KviCanvasView()
+{
+}
+
+
+void KviCanvasView::insertRectangle()
+{
+ m_state = SelectOrigin;
+ setCursor(crossCursor);
+ m_objectToInsert = Rectangle;
+}
+
+void KviCanvasView::insertRichText()
+{
+ m_state = SelectOrigin;
+ setCursor(crossCursor);
+ m_objectToInsert = RichText;
+}
+
+void KviCanvasView::insertLine()
+{
+ m_state = SelectOrigin;
+ setCursor(crossCursor);
+ m_objectToInsert = Line;
+}
+
+void KviCanvasView::insertEllipse()
+{
+ m_state = SelectOrigin;
+ setCursor(crossCursor);
+ m_objectToInsert = Ellipse;
+}
+
+void KviCanvasView::insertPie()
+{
+ m_state = SelectOrigin;
+ setCursor(crossCursor);
+ m_objectToInsert = Pie;
+}
+
+void KviCanvasView::insertChord()
+{
+ m_state = SelectOrigin;
+ setCursor(crossCursor);
+ m_objectToInsert = Chord;
+}
+
+
+void KviCanvasView::insertPolygonTriangle()
+{
+ m_state = SelectOrigin;
+ setCursor(crossCursor);
+ m_objectToInsert = PolygonTriangle;
+}
+
+
+void KviCanvasView::insertPolygonRectangle()
+{
+ m_state = SelectOrigin;
+ setCursor(crossCursor);
+ m_objectToInsert = PolygonRectangle;
+}
+
+
+void KviCanvasView::insertPolygonPentagon()
+{
+ m_state = SelectOrigin;
+ setCursor(crossCursor);
+ m_objectToInsert = PolygonPentagon;
+}
+
+void KviCanvasView::insertPolygonHexagon()
+{
+ m_state = SelectOrigin;
+ setCursor(crossCursor);
+ m_objectToInsert = PolygonPentagon;
+}
+
+#ifndef M_PI
+ #define M_PI 3.14159265358979323846
+#endif
+
+static void calcPolygonPoints(QPointArray &pnts,unsigned int nVertices)
+{
+ double dDelta = (2 * M_PI) / nVertices;
+ for(unsigned int i=0;i<nVertices;i++)
+ {
+ double dAng = dDelta * i;
+ double theX = 300 * sin(dAng);
+ double theY = 300 * cos(dAng);
+ pnts.setPoint(i,(int)theX,(int)theY);
+ }
+}
+
+void KviCanvasView::insertObjectAt(const QPoint & pnt,ObjectType o)
+{
+ QCanvasItem * r = 0;
+
+ switch(o)
+ {
+ case Rectangle:
+ r = new KviCanvasRectangle(canvas(),pnt.x(),pnt.y(),0,0);
+ break;
+ case RichText:
+ r = new KviCanvasRichText(canvas(),pnt.x(),pnt.y(),0,0);
+ break;
+ case Line:
+ r = new KviCanvasLine(canvas(),pnt.x(),pnt.y(),pnt.x(),pnt.y());
+ break;
+ case Ellipse:
+ r = new KviCanvasEllipse(canvas(),pnt.x(),pnt.y(),0,0);
+ break;
+ case Pie:
+ r = new KviCanvasPie(canvas(),pnt.x(),pnt.y(),0,0);
+ break;
+ case Chord:
+ r = new KviCanvasChord(canvas(),pnt.x(),pnt.y(),0,0);
+ break;
+ case PolygonTriangle:
+ {
+ QPointArray pa(3);
+ pa.setPoint(0,0,-500);
+ pa.setPoint(1,-450,220);
+ pa.setPoint(2,450,220);
+ r = new KviCanvasPolygon(canvas(),pnt.x(),pnt.y(),pa,0.1);
+ }
+ break;
+ case PolygonRectangle:
+ {
+ QPointArray pa(4);
+ pa.setPoint(0,-350,-350);
+ pa.setPoint(1,350,-350);
+ pa.setPoint(2,350,350);
+ pa.setPoint(3,-350,350);
+ r = new KviCanvasPolygon(canvas(),pnt.x(),pnt.y(),pa,0.1);
+ }
+ break;
+ case PolygonPentagon:
+ {
+ QPointArray pa(5);
+ calcPolygonPoints(pa,5);
+ r = new KviCanvasPolygon(canvas(),pnt.x(),pnt.y(),pa,0.1);
+ }
+ break;
+ case PolygonHexagon:
+ {
+ QPointArray pa(6);
+ calcPolygonPoints(pa,6);
+ r = new KviCanvasPolygon(canvas(),pnt.x(),pnt.y(),pa,0.1);
+ }
+ break;
+ }
+
+ if(r)
+ {
+ setItemSelected(r);
+ r->setEnabled(true);
+ r->show();
+ }
+
+ switch(KVI_CANVAS_RTTI_CONTROL_TYPE(r))
+ {
+ case KVI_CANVAS_RTTI_CONTROL_TYPE_RECTANGLE:
+ beginDragRectangle((KviCanvasRectangleItem *)r,pnt,true);
+ break;
+ case KVI_CANVAS_RTTI_CONTROL_TYPE_LINE:
+ beginDragLine((KviCanvasLine *)r,pnt,true);
+ break;
+// case KVI_CANVAS_RTTI_CONTROL_TYPE_POLYGON:
+// beginDragPolygon((KviCanvasPolygon *)r,pnt,true);
+// break;
+ }
+
+// canvas()->update();
+}
+
+void KviCanvasView::setItemSelected(QCanvasItem * it)
+{
+ clearSelection();
+ it->setSelected(true);
+ m_pSelectedItem = it;
+ m_pCanvasWidget->m_pPropertiesWidget->editItem(it);
+
+}
+
+void KviCanvasView::clearSelection()
+{
+ if(!m_pSelectedItem)return;
+ m_pSelectedItem->setSelected(false);
+ m_pSelectedItem = 0;
+ m_pCanvasWidget->m_pPropertiesWidget->editItem(0);
+}
+
+
+
+void KviCanvasView::beginDragLine(KviCanvasLine * it,const QPoint &p,bool bInitial)
+{
+ QPoint sp = it->startPoint();
+
+ m_dragBegin = p - sp;
+
+ if(bInitial)
+ {
+ m_dragMode = Bottom;
+ setCursor(sizeAllCursor);
+ return;
+ }
+
+ if((abs(p.x() - sp.x()) < 3) && (abs(p.y() - sp.y()) < 3))
+ {
+ m_dragMode = Top;
+ setCursor(sizeAllCursor);
+ return;
+ }
+
+ sp = it->endPoint();
+ if((abs(p.x() - sp.x()) < 3) && (abs(p.y() - sp.y()) < 3))
+ {
+ m_dragMode = Bottom;
+ setCursor(sizeAllCursor);
+ return;
+ }
+
+ m_dragMode = All;
+ setCursor(pointingHandCursor);
+}
+
+void KviCanvasView::dragLine(KviCanvasLine * it,const QPoint &p)
+{
+ switch(m_dragMode)
+ {
+ case Bottom:
+ {
+ QPoint sp = it->startPoint();
+ it->setPoints(sp.x(),sp.y(),p.x(),p.y());
+ }
+ break;
+ case Top:
+ {
+ QPoint ep = it->endPoint();
+ it->setPoints(p.x(),p.y(),ep.x(),ep.y());
+ }
+ break;
+ case All:
+ {
+ QPoint sp = p - m_dragBegin;
+ QPoint ep = sp + (it->endPoint() - it->startPoint());
+ it->setPoints(sp.x(),sp.y(),ep.x(),ep.y());
+ }
+ break;
+ default: /* make gcc happy */
+ break;
+ }
+ canvas()->update();
+}
+
+
+static double ssm_2d_rotationAngleFromXAxis(double dx,double dy)
+{
+ //
+ // v1 . v2 dx * 1 + dy * 0 dx
+ //acos(---------) = acos(-----------------) = acos(---------)
+ // |v1||v2| |(dx,dy)| * 1 |(dx,dy)|
+ //
+
+ //double dVal = hypot(dx,dy);
+ double dVal = sqrt((dx * dx) + (dy * dy));
+
+ if(dVal == 0.0)return 0; // ???
+
+ dVal = acos(dx / dVal);
+
+ return (dy > 0.0) ? dVal : -dVal;
+}
+
+static double ssm_2d_rotationAngle(double drefx,double drefy,double drotatedx,double drotatedy)
+{
+ double dRefAngle = ssm_2d_rotationAngleFromXAxis(drefx,drefy);
+ double dRotAngle = ssm_2d_rotationAngleFromXAxis(drotatedx,drotatedy);
+ return dRotAngle - dRefAngle;
+}
+
+static void ssm_2d_rotate(double &dx,double &dy,double dAngle)
+{
+ // Rotation matrix:
+ //
+ // | cos(x) sin(x) |
+ // | |
+ // | -sin(x) cos(x) |
+
+ double s = sin(dAngle);
+ double c = cos(dAngle);
+
+ double tmpX = (dx * c) - (dy * s);
+ double tmpY = (dx * s) + (dy * c);
+
+ dx = tmpX;
+ dy = tmpY;
+}
+
+static double ssm_hypot(double a,double b)
+{
+ return sqrt((a * a) + (b * b));
+}
+
+void KviCanvasView::beginDragPolygon(KviCanvasPolygon * it,const QPoint &p,bool bShift,bool bCtrl)
+{
+ m_dragBegin = QPoint((int)(p.x() - it->x()),(int)(p.y() - it->y()));
+
+ QPointArray pa = it->areaPoints();
+
+ for(unsigned int i=0;i<pa.size();i++)
+ {
+ QPoint pnt = pa.point(i);
+ double dX = pnt.x() - p.x();
+ double dY = pnt.y() - p.y();
+ double dHypot = sqrt((dX * dX) + (dY * dY));
+ if(dHypot < 3.0)
+ {
+ // We're dragging a point
+ m_dragMode = SinglePoint;
+ m_dragPointIndex = i;
+ setCursor(crossCursor);
+ return;
+ }
+ }
+
+ if(bShift)
+ {
+ m_dragMode = Scale;
+ m_dragScaleFactor = it->scaleFactor();
+ setCursor(sizeAllCursor);
+ return;
+ }
+
+ if(bCtrl)
+ {
+ m_dragMode = Rotate;
+ m_dragPointArray = it->internalPoints();
+// debug("Here");
+ setCursor(sizeHorCursor);
+ return;
+ }
+
+ m_dragMode = All;
+ setCursor(pointingHandCursor);
+}
+
+void KviCanvasView::dragPolygon(KviCanvasPolygon * it,const QPoint &p)
+{
+ switch(m_dragMode)
+ {
+ case All:
+ it->move(p.x() - m_dragBegin.x(),p.y() - m_dragBegin.y());
+ break;
+ case SinglePoint:
+ {
+ QPointArray pnt = it->internalPoints();
+ pnt.setPoint(m_dragPointIndex,(int)((p.x() - it->x()) / it->scaleFactor()),(int)((p.y() - it->y()) / it->scaleFactor()));
+ it->setInternalPoints(pnt);
+ }
+ break;
+ case Scale:
+ {
+ double dDistance = ssm_hypot(p.x() - it->x(),p.y() - it->y());
+ double dOriginal = ssm_hypot(m_dragBegin.x(),m_dragBegin.y());
+ if(dOriginal < 1)dOriginal = 1;
+ if(dDistance < 0.1)dDistance = 0.1;
+ it->setScaleFactor(m_dragScaleFactor * dDistance / dOriginal);
+ }
+ break;
+ case Rotate:
+ {
+ QPoint act((int)(p.x() - it->x()),(int)(p.y() - it->y()));
+ double dAngle = ssm_2d_rotationAngle(m_dragBegin.x(),m_dragBegin.y(),act.x(),act.y());
+// debug("%d,%d %d,%d %f",m_dragBegin.x(),m_dragBegin.y(),act.x(),act.y(),dAngle);
+ QPointArray thePoints = m_dragPointArray.copy();
+ for(unsigned int i=0;i<thePoints.size();i++)
+ {
+ QPoint tmp = thePoints.point(i);
+ double dx = tmp.x();
+ double dy = tmp.y();
+ ssm_2d_rotate(dx,dy,dAngle);
+ thePoints.setPoint(i,(int)dx,(int)dy);
+ }
+ it->setInternalPoints(thePoints);
+ }
+ break;
+ default:
+ break;
+ }
+ canvas()->update();
+}
+
+void KviCanvasView::beginDragRectangle(KviCanvasRectangleItem * it,const QPoint & p,bool bInitial)
+{
+ m_dragBegin = QPoint((int)(p.x() - it->x()),(int)(p.y() - it->y()));
+
+ if(bInitial)
+ {
+ // Right bottom
+ m_dragMode = RightBottom;
+ setCursor(sizeFDiagCursor);
+ return;
+ }
+
+ if(p.x() < (((int)it->x()) + 2))
+ {
+ // Left edge
+ if(p.y() < (((int)it->y()) + 2))
+ {
+ // Left top
+ m_dragMode = LeftTop;
+ setCursor(sizeFDiagCursor);
+ return;
+ }
+ if(p.y() > ( it->bottom() - 2))
+ {
+ // Left bottom
+ m_dragMode = LeftBottom;
+ setCursor(sizeBDiagCursor);
+ return;
+ }
+ m_dragMode = Left;
+ setCursor(sizeHorCursor);
+ return;
+ }
+
+ if(p.x() > (it->right() - 2))
+ {
+ // Right edge
+ if(p.y() < (((int)it->y()) + 2))
+ {
+ // Right top
+ m_dragMode = RightTop;
+ setCursor(sizeBDiagCursor);
+ return;
+ }
+ if(p.y() > ( it->bottom() - 2))
+ {
+ // Right bottom
+ m_dragMode = RightBottom;
+ setCursor(sizeFDiagCursor);
+ return;
+ }
+ m_dragMode = Right;
+ setCursor(sizeHorCursor);
+ return;
+ }
+
+ // Somewhere in the middle
+ if(p.y() < (((int)it->y()) + 2))
+ {
+ // Top
+ m_dragMode = Top;
+ setCursor(sizeVerCursor);
+ return;
+ }
+ if(p.y() > ( it->bottom() - 2))
+ {
+ // Bottom
+ m_dragMode = Bottom;
+ setCursor(sizeVerCursor);
+ return;
+ }
+
+ m_dragMode = All;
+ setCursor(pointingHandCursor);
+}
+
+void KviCanvasView::dragRectangle(KviCanvasRectangleItem * it,const QPoint & p)
+{
+
+ int aux1,aux2,aux3,aux4;
+
+ switch(m_dragMode)
+ {
+ case All:
+ it->move(p.x() - m_dragBegin.x(),p.y() - m_dragBegin.y());
+ break;
+ case Left:
+ aux1 = it->width() + (int)(it->x() - p.x());
+ aux2 = p.x();
+ if(aux1 < 1)
+ {
+ aux2 += (aux1 - 1);
+ aux1 = 1;
+ }
+ it->move(aux2,it->y());
+ it->setSize(aux1,it->height());
+ break;
+ case Right:
+ aux1 = it->width() + (p.x() - it->right());
+ if(aux1 < 1)aux1 = 1;
+ it->setSize(aux1,it->height());
+ break;
+ case Top:
+ aux1 = it->height() + (int)(it->y() - p.y());
+ aux2 = p.y();
+ if(aux1 < 1)
+ {
+ aux2 += (aux1 - 1);
+ aux1 = 1;
+ }
+ it->move(it->x(),aux2);
+ it->setSize(it->width(),aux1);
+ break;
+ case Bottom:
+ aux1 = (int)it->height() + (p.y() - it->bottom());
+ if(aux1 < 1)aux1 = 1;
+ it->setSize(it->width(),aux1);
+ break;
+ case LeftTop:
+ aux1 = it->width() + (int)(it->x() - p.x());
+ aux3 = p.x();
+ if(aux1 < 1)
+ {
+ aux3 += (aux1 - 1);
+ aux1 = 1;
+ }
+ aux2 = it->height() + (int)(it->y() - p.y());
+ aux4 = p.y();
+ if(aux2 < 1)
+ {
+ aux4 += (aux2 - 1);
+ aux2 = 1;
+ }
+ it->setSize(aux1,aux2);
+ it->move(aux3,aux4);
+ break;
+ case RightTop:
+ aux1 = it->width() + (int)(p.x() - it->right());
+ if(aux1 < 1)aux1 = 1;
+ aux2 = it->height() + (int)(it->y() - p.y());
+ aux4 = p.y();
+ if(aux2 < 1)
+ {
+ aux4 += (aux2 - 1);
+ aux2 = 1;
+ }
+ it->setSize(aux1,aux2);
+ it->move(it->x(),aux4);
+ break;
+ case LeftBottom:
+ aux1 = it->width() + (int)(it->x() - p.x());
+ aux3 = p.x();
+ if(aux1 < 1)
+ {
+ aux3 += (aux1 - 1);
+ aux1 = 1;
+ }
+ aux2 = it->height() + (int)(p.y() - it->bottom());
+ if(aux2 < 1)aux2 = 1;
+ it->setSize(aux1,aux2);
+ it->move(aux3,it->y());
+ break;
+ case RightBottom:
+ aux1 = it->width() + (int)(p.x() - it->right());
+ if(aux1 < 1)aux1 = 1;
+ aux2 = it->height() + (int)(p.y() - it->bottom());
+ if(aux2 < 1)aux2 = 1;
+ it->setSize(aux1,aux2);
+ break;
+ default:
+ break;
+ }
+
+ canvas()->update();
+}
+
+void KviCanvasView::contentsMouseMoveEvent(QMouseEvent *e)
+{
+// QPoint p = inverseWorldMatrix().map(e->pos());
+ QPoint p = e->pos();
+ if(e->state() & Qt::LeftButton)
+ {
+ if((m_dragMode != None) && (m_pSelectedItem))
+ {
+#if QT_VERSION >= 300
+ if(m_pSelectedItem->isEnabled())m_pSelectedItem->setEnabled(false);
+#else
+ if(m_pSelectedItem->enabled())m_pSelectedItem->setEnabled(false);
+#endif
+ switch(KVI_CANVAS_RTTI_CONTROL_TYPE(m_pSelectedItem))
+ {
+ case KVI_CANVAS_RTTI_CONTROL_TYPE_RECTANGLE:
+ dragRectangle((KviCanvasRectangleItem *)m_pSelectedItem,p);
+ break;
+ case KVI_CANVAS_RTTI_CONTROL_TYPE_LINE:
+ dragLine((KviCanvasLine *)m_pSelectedItem,p);
+ break;
+ case KVI_CANVAS_RTTI_CONTROL_TYPE_POLYGON:
+ dragPolygon((KviCanvasPolygon *)m_pSelectedItem,p);
+ break;
+ }
+ }
+ } else {
+ // Without buttons
+ if(m_state == Idle)
+ {
+ QCanvasItemList l = canvas()->collisions(p);
+ QCanvasItemList::Iterator it = l.begin();
+
+ if(it != l.end())
+ {
+ // Got an item
+ QCanvasItem * hit = (QCanvasItem *)*it;
+ // Now find the point on that we have clicked it
+ if(hit == m_pSelectedItem)
+ {
+ switch(KVI_CANVAS_RTTI_CONTROL_TYPE(m_pSelectedItem))
+ {
+ case KVI_CANVAS_RTTI_CONTROL_TYPE_RECTANGLE:
+ beginDragRectangle((KviCanvasRectangleItem *)m_pSelectedItem,p);
+ break;
+ case KVI_CANVAS_RTTI_CONTROL_TYPE_LINE:
+ beginDragLine((KviCanvasLine *)m_pSelectedItem,p);
+ break;
+ case KVI_CANVAS_RTTI_CONTROL_TYPE_POLYGON:
+ beginDragPolygon((KviCanvasPolygon *)m_pSelectedItem,p);
+ break;
+ }
+ }
+ else if(m_dragMode != None)setCursor(arrowCursor);
+ } else {
+ if(m_dragMode != None)setCursor(arrowCursor);
+ }
+ }
+ }
+}
+
+void KviCanvasView::contentsMouseReleaseEvent(QMouseEvent *e)
+{
+ if(m_dragMode != None)
+ {
+ // Was just dragging a rectangle
+ m_dragMode = None;
+ setCursor(arrowCursor);
+ if(m_pSelectedItem)
+ {
+ m_pSelectedItem->setEnabled(true);
+ canvas()->update();
+ }
+ }
+}
+
+void KviCanvasView::contentsMousePressEvent(QMouseEvent *e)
+{
+ if(e->button() & Qt::LeftButton)
+ {
+// QPoint p = inverseWorldMatrix().map(e->pos());
+ QPoint p = e->pos();
+
+ switch(m_state)
+ {
+ case SelectOrigin:
+ clearSelection();
+ setCursor(arrowCursor);
+ m_state = Idle;
+ insertObjectAt(p,m_objectToInsert);
+ canvas()->update();
+ break;
+
+ case Idle:
+ {
+ QCanvasItemList l = canvas()->collisions(p);
+ QCanvasItemList::Iterator it = l.begin();
+
+ if(it != l.end())
+ {
+ // Got an item
+ QCanvasItem * hit = *it;
+ if(hit != m_pSelectedItem)
+ {
+ // Was not selected yet
+ setItemSelected(hit);
+ canvas()->update();
+ }
+ // Now find the point on that we have clicked it
+ switch(KVI_CANVAS_RTTI_CONTROL_TYPE(hit))
+ {
+ case KVI_CANVAS_RTTI_CONTROL_TYPE_RECTANGLE:
+ beginDragRectangle(((KviCanvasRectangleItem *)hit),p);
+ break;
+ case KVI_CANVAS_RTTI_CONTROL_TYPE_LINE:
+ beginDragLine(((KviCanvasLine *)hit),p);
+ break;
+ case KVI_CANVAS_RTTI_CONTROL_TYPE_POLYGON:
+ beginDragPolygon(((KviCanvasPolygon *)hit),p,e->state() & Qt::ShiftButton,e->state() & Qt::ControlButton);
+ break;
+ }
+ } else {
+ // No item
+ clearSelection();
+ canvas()->update();
+ }
+ }
+ break;
+ }
+ }
+}
+
+
+void KviCanvasView::propertyChanged(const QString &s,const QVariant &v)
+{
+ if(!m_pSelectedItem)return;
+
+
+ switch(KVI_CANVAS_RTTI_CONTROL_TYPE(m_pSelectedItem))
+ {
+ case KVI_CANVAS_RTTI_CONTROL_TYPE_RECTANGLE:
+ ((KviCanvasRectangleItem *)m_pSelectedItem)->setProperty(s,v);
+ break;
+ case KVI_CANVAS_RTTI_CONTROL_TYPE_LINE:
+ ((KviCanvasLine *)m_pSelectedItem)->setProperty(s,v);
+ break;
+ case KVI_CANVAS_RTTI_CONTROL_TYPE_POLYGON:
+ ((KviCanvasPolygon *)m_pSelectedItem)->setProperty(s,v);
+ break;
+ }
+
+ canvas()->update();
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// KviVariantTableItem
+//
+
+
+
+KviVariantTableItem::KviVariantTableItem(QTable * t,const QVariant & property)
+: QTableItem(t,QTableItem::WhenCurrent,QString::null)
+{
+ m_property = property;
+}
+
+KviVariantTableItem::~KviVariantTableItem()
+{
+}
+
+
+QWidget * KviVariantTableItem::createEditor() const
+{
+ switch(m_property.type())
+ {
+ case QVariant::String:
+ {
+ QLineEdit * e = new QLineEdit(table()->viewport());
+ e->setText(m_property.toString());
+ return e;
+ }
+ break;
+ case QVariant::Int:
+ {
+ QLineEdit * e = new QLineEdit(table()->viewport());
+ QString sz;
+ sz.setNum(m_property.toInt());
+ e->setText(sz);
+ e->setValidator(new QIntValidator(e));
+ return e;
+ }
+ break;
+ case QVariant::UInt:
+ {
+ QLineEdit * e = new QLineEdit(table()->viewport());
+ QString sz;
+ sz.setNum(m_property.toInt());
+ e->setText(sz);
+ QIntValidator * i = new QIntValidator(e);
+ i->setBottom(0);
+ e->setValidator(i);
+ return e;
+ }
+ break;
+ case QVariant::Bool:
+ {
+ QComboBox * b = new QComboBox(false,table()->viewport());
+ b->insertItem("FALSE");
+ b->insertItem("TRUE");
+ b->setCurrentItem(m_property.toBool() ? 1 : 0);
+ return b;
+ }
+ break;
+ case QVariant::Color:
+ {
+ QLineEdit * e = new QLineEdit(table()->viewport());
+ e->setText(m_property.toColor().name());
+ return e;
+ }
+ break;
+ case QVariant::Font:
+ {
+ QComboBox * b = new QComboBox(true,table()->viewport());
+
+ QString tmp;
+ QString tmpDefault;
+ QFont f = QFont();
+ f.setStyleHint(QFont::SansSerif);
+ tmpDefault = f.family();
+ f.setStyleHint(QFont::TypeWriter);
+ tmp.setNum(m_property.toFont().pointSize());
+ tmp.prepend(", ");
+ tmp.prepend(m_property.toFont().family());
+ b->insertItem(tmp);
+ b->insertItem(tmpDefault + ", 8");
+ b->insertItem(tmpDefault + ", 10");
+ b->insertItem(tmpDefault + ", 12");
+ b->insertItem(tmpDefault + ", 14");
+ b->insertItem(tmpDefault + ", 16");
+ b->insertItem(tmpDefault + ", 18");
+ b->insertItem(tmpDefault + ", 20");
+ b->insertItem(tmpDefault + ", 24");
+ b->insertItem(tmpDefault + ", 28");
+ b->insertItem(tmpDefault + ", 32");
+ b->insertItem(tmpDefault + ", 40");
+ b->insertItem(tmpDefault + ", 48");
+ b->insertItem(f.family() + ", 12");
+ b->setCurrentItem(0);
+
+ b->setCurrentItem(m_property.toBool() ? 1 : 0);
+ return b;
+ }
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+void KviVariantTableItem::setContentFromEditor(QWidget * w)
+{
+ switch(m_property.type())
+ {
+ case QVariant::String:
+ m_property = QVariant(((QLineEdit *)w)->text());
+ break;
+ case QVariant::Int:
+ m_property = QVariant(((QLineEdit *)w)->text().toInt());
+ break;
+ case QVariant::UInt:
+ m_property = QVariant(((QLineEdit *)w)->text().toUInt());
+ break;
+ case QVariant::Bool:
+ m_property = QVariant(((QComboBox *)w)->currentItem(),1);
+ break;
+ case QVariant::Color:
+ m_property.asColor().setNamedColor(((QLineEdit *)w)->text());
+ break;
+ case QVariant::Font:
+ {
+ KviStr txt = ((QComboBox *)w)->currentText();
+ if(txt.hasData())
+ {
+ KviStr fam = txt;
+ fam.cutFromFirst(',',true);
+ fam.stripWhiteSpace();
+ KviStr psz = txt;
+ psz.cutToFirst(',',true);
+ psz.stripWhiteSpace();
+ bool bOk;
+ unsigned int uSize = psz.toUInt(&bOk);
+ if(!bOk)uSize = 12;
+ m_property = QVariant(QFont(fam.ptr(),uSize));
+ }
+
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+
+void KviVariantTableItem::paint(QPainter *p,const QColorGroup &cg,const QRect &cr,bool)
+{
+ p->fillRect(0,0,cr.width(),cr.height(),cg.base());
+
+ if(m_property.type() == QVariant::Color)
+ {
+ p->fillRect(3,3,cr.width() - 6,cr.height() - 6,m_property.asColor());
+ } else {
+ QString sz;
+ switch(m_property.type())
+ {
+ case QVariant::String:
+ sz = m_property.toString();
+ break;
+ case QVariant::Bool:
+ sz = m_property.toBool() ? "TRUE" : "FALSE";
+ break;
+ case QVariant::Font:
+ sz.setNum(m_property.toFont().pointSize());
+ sz.prepend(", ");
+ sz.prepend(m_property.toFont().family());
+ break;
+ case QVariant::Int:
+ sz.setNum(m_property.toInt());
+ break;
+ case QVariant::UInt:
+ sz.setNum(m_property.toUInt());
+ break;
+ default:
+ break;
+ }
+ p->setPen(cg.text());
+ p->drawText(0,0,cr.width(),cr.height(),Qt::AlignLeft | Qt::AlignTop,sz);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// KviCanvasItemPropertiesWidget
+//
+
+
+KviCanvasItemPropertiesWidget::KviCanvasItemPropertiesWidget(QWidget * par)
+: QTable(par)
+{
+ setSelectionMode(QTable::NoSelection);
+ setColumnMovingEnabled(false);
+ setRowMovingEnabled(false);
+ setShowGrid(true);
+ setNumCols(2);
+ setSorting(false);
+ setLeftMargin(0);
+ verticalHeader()->hide();
+ connect(this,SIGNAL(valueChanged(int,int)),this,SLOT(cellEdited(int,int)));
+}
+
+KviCanvasItemPropertiesWidget::~KviCanvasItemPropertiesWidget()
+{
+}
+
+void KviCanvasItemPropertiesWidget::cellEdited(int row,int)
+{
+ QTableItem * it = item(row,0);
+ if(!it)return;
+ QString szName = it->text();
+ it = item(row,1);
+ if(!it)return;
+ emit propertyChanged(szName,((KviVariantTableItem *)it)->property());
+}
+
+void KviCanvasItemPropertiesWidget::editItem(QCanvasItem * it)
+{
+ if(!it)
+ {
+ for(int i=0;i<numRows();i++)
+ {
+ clearCell(i,0);
+ clearCell(i,1);
+ clearCellWidget(i,1);
+ }
+ setNumRows(0);
+ return;
+ }
+
+ QMap<QString,QVariant> * m = 0;
+
+ switch(KVI_CANVAS_RTTI_CONTROL_TYPE(it))
+ {
+ case KVI_CANVAS_RTTI_CONTROL_TYPE_RECTANGLE:
+ m = ((KviCanvasRectangleItem *)it)->properties();
+ break;
+ case KVI_CANVAS_RTTI_CONTROL_TYPE_LINE:
+ m = ((KviCanvasLine *)it)->properties();
+ break;
+ case KVI_CANVAS_RTTI_CONTROL_TYPE_POLYGON:
+ m = ((KviCanvasPolygon *)it)->properties();
+ break;
+ }
+
+ if(!m)
+ {
+ editItem(0);
+ return;
+ }
+
+ for(int i=0;i<numRows();i++)
+ {
+ clearCell(i,0);
+ clearCell(i,1);
+ clearCellWidget(i,1);
+ }
+
+ setNumRows(m->count());
+
+ QTableItem * item;
+
+ int idx = 0;
+
+ for(QMap<QString,QVariant>::ConstIterator iter = m->begin();iter != m->end();++iter)
+ {
+ item = new QTableItem(this,QTableItem::Never,iter.key().utf8().data());
+ setItem(idx,0,item);
+ item = new KviVariantTableItem(this,iter.data());
+ setItem(idx,1,item);
+ idx++;
+ }
+
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// KviCanvasWidget
+//
+
+KviCanvasWidget::KviCanvasWidget(QWidget * par)
+: QWidget(par,"canvas_widget")
+{
+ m_pCanvas = new QCanvas(this);
+//#warning "Make this size as parameter of Dcc ?"
+ m_pCanvas->resize(648,480);
+ m_pMenuBar = new QMenuBar(this);
+ m_pSplitter = new QSplitter(QSplitter::Horizontal,this);
+ m_pCanvasView = new KviCanvasView(m_pCanvas,this,m_pSplitter);
+ m_pStatusLabel = new QLabel(this);
+ m_pPropertiesWidget = new KviCanvasItemPropertiesWidget(m_pSplitter);
+ QValueList<int> l;
+ l.append(80);
+ l.append(20);
+ m_pSplitter->setSizes(l);
+
+ connect(m_pPropertiesWidget,SIGNAL(propertyChanged(const QString &,const QVariant &)),m_pCanvasView,SLOT(propertyChanged(const QString &,const QVariant &)));
+
+ KviTalPopupMenu * add = new KviTalPopupMenu(m_pMenuBar);
+ KviTalPopupMenu * shapes = new KviTalPopupMenu(add);
+ KviTalPopupMenu * polygons = new KviTalPopupMenu(add);
+ KviTalPopupMenu * items = new KviTalPopupMenu(add);
+ shapes->insertItem(__tr2qs_ctx("&Line","dcc"),m_pCanvasView,SLOT(insertLine()));
+ shapes->insertItem(__tr2qs_ctx("&Rectangle","dcc"),m_pCanvasView,SLOT(insertRectangle()));
+ shapes->insertItem(__tr2qs_ctx("&Ellipse","dcc"),m_pCanvasView,SLOT(insertEllipse()));
+ shapes->insertItem(__tr2qs_ctx("&Pie","dcc"),m_pCanvasView,SLOT(insertPie()));
+ shapes->insertItem(__tr2qs_ctx("&Chord","dcc"),m_pCanvasView,SLOT(insertChord()));
+
+ items->insertItem(__tr2qs_ctx("&Rich text (html)","dcc"),m_pCanvasView,SLOT(insertRichText()));
+
+ polygons->insertItem(__tr2qs_ctx("&Triangle","dcc"),m_pCanvasView,SLOT(insertPolygonTriangle()));
+ polygons->insertItem(__tr2qs_ctx("&Rectangle","dcc"),m_pCanvasView,SLOT(insertPolygonRectangle()));
+ polygons->insertItem(__tr2qs_ctx("&Pentagon","dcc"),m_pCanvasView,SLOT(insertPolygonPentagon()));
+ polygons->insertItem(__tr2qs_ctx("&Hexagon","dcc"),m_pCanvasView,SLOT(insertPolygonHexagon()));
+
+ add->insertItem(__tr2qs_ctx("&Shape","dcc"),shapes);
+ add->insertItem(__tr2qs_ctx("&Item","dcc"),items);
+ add->insertItem(__tr2qs_ctx("&Polygons","dcc"),polygons);
+
+ m_pMenuBar->insertItem(__tr2qs_ctx("&Insert","dcc"),add);
+}
+
+KviCanvasWidget::~KviCanvasWidget()
+{
+}
+
+
+
+void KviCanvasWidget::resizeEvent(QResizeEvent *)
+{
+ int h = m_pMenuBar->sizeHint().height();
+ m_pMenuBar->setGeometry(0,0,width(),h);
+ int h2 = m_pStatusLabel->sizeHint().height();
+ m_pStatusLabel->setGeometry(0,height() - h2,width(),h2);
+ m_pSplitter->setGeometry(0,h,width(),height() - (h + h2));
+}
+
+
+#include "m_canvaswidget.moc"
+
+#endif
diff --git a/src/modules/dcc/canvaswidget.h b/src/modules/dcc/canvaswidget.h
new file mode 100644
index 00000000..41d451e4
--- /dev/null
+++ b/src/modules/dcc/canvaswidget.h
@@ -0,0 +1,322 @@
+#ifndef _CANVAS_WIDGET_H_
+#define _CANVAS_WIDGET_H_
+//
+// File : canvaswidget.h
+// Creation date : Mon Jul 30 07 2001 04:49:49 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "broker.h"
+
+#ifdef COMPILE_DCC_CANVAS
+
+
+#include <qcanvas.h>
+
+//#ifdef QT_NO_CANVAS
+// #warning "HEre is not"
+//#endif
+
+
+#include <qmenubar.h>
+#include <qlabel.h>
+
+#include <qmap.h>
+#include <qvariant.h>
+#include <qtable.h>
+#include <qsplitter.h>
+
+
+
+class KviCanvasWidget;
+
+
+
+#define KVI_CANVAS_RTTI_CONTROL_TYPE_RECTANGLE 1
+#define KVI_CANVAS_RTTI_CONTROL_TYPE_LINE 2
+#define KVI_CANVAS_RTTI_CONTROL_TYPE_POLYGON 4
+
+#define KVI_CANVAS_RTTI_CONTROL_TYPE_MASK 255
+
+#define KVI_CANVAS_RTTI_RECTANGLE (KVI_CANVAS_RTTI_CONTROL_TYPE_RECTANGLE | (1 << 8))
+#define KVI_CANVAS_RTTI_RICHTEXT (KVI_CANVAS_RTTI_CONTROL_TYPE_RECTANGLE | (2 << 8))
+#define KVI_CANVAS_RTTI_LINE (KVI_CANVAS_RTTI_CONTROL_TYPE_LINE | (3 << 8))
+#define KVI_CANVAS_RTTI_ELLIPSE (KVI_CANVAS_RTTI_CONTROL_TYPE_RECTANGLE | (4 << 8))
+#define KVI_CANVAS_RTTI_CHORD (KVI_CANVAS_RTTI_CONTROL_TYPE_RECTANGLE | (5 << 8))
+#define KVI_CANVAS_RTTI_PIE (KVI_CANVAS_RTTI_CONTROL_TYPE_RECTANGLE | (6 << 8))
+#define KVI_CANVAS_RTTI_POLYGON (KVI_CANVAS_RTTI_CONTROL_TYPE_POLYGON | (7 << 8))
+
+#define KVI_CANVAS_RTTI_CONTROL_TYPE(__item) (__item->rtti() & KVI_CANVAS_RTTI_CONTROL_TYPE_MASK)
+
+
+
+class KviCanvasPolygon : public QCanvasPolygon
+{
+public:
+ KviCanvasPolygon(QCanvas * c,int x,int y,QPointArray &pnts,double dScaleFactor);
+ virtual ~KviCanvasPolygon();
+protected:
+ QMap<QString,QVariant> m_properties;
+ double m_dScaleFactor;
+ QPointArray m_points;
+public:
+ virtual void draw(QPainter & p);
+ double scaleFactor(){ return m_dScaleFactor; };
+ void setScaleFactor(double dScaleFactor);
+ void resetPoints();
+ const QPointArray & internalPoints(){ return m_points; };
+ void setInternalPoints(const QPointArray &pnts);
+ QMap<QString,QVariant> * properties(){ return &m_properties; };
+ virtual void setProperty(const QString &property,const QVariant &val);
+ virtual int rtti() const;
+};
+
+
+
+
+class KviCanvasRectangleItem : public QCanvasRectangle
+{
+ friend class KviCanvasRectangle;
+ friend class KviCanvasRichText;
+ friend class KviCanvasEllipticItem;
+protected:
+ KviCanvasRectangleItem(QCanvas * c,int x,int y,int w,int h);
+public:
+ virtual ~KviCanvasRectangleItem();
+protected:
+ QMap<QString,QVariant> m_properties;
+public:
+ int right(){ return ((int)x()) + width(); };
+ int bottom(){ return ((int)y()) + height(); };
+ QMap<QString,QVariant> * properties(){ return &m_properties; };
+ virtual void setProperty(const QString &property,const QVariant &val);
+// QVariant property(const QString &name){ return m_properties[name]; };
+protected:
+ void drawSelection(QPainter &p);
+};
+
+
+class KviCanvasEllipticItem : public KviCanvasRectangleItem
+{
+ friend class KviCanvasEllipse;
+ friend class KviCanvasChord;
+ friend class KviCanvasPie;
+protected:
+ KviCanvasEllipticItem(QCanvas * c,int x,int y,int w,int h);
+ ~KviCanvasEllipticItem();
+public:
+ virtual void setProperty(const QString & property,const QVariant &val);
+ virtual void draw(QPainter & p);
+ virtual void drawContent(QPainter & p);
+ virtual int rtti() const;
+};
+
+
+class KviCanvasEllipse : public KviCanvasEllipticItem
+{
+public:
+ KviCanvasEllipse(QCanvas * c,int x,int y,int w,int h);
+ ~KviCanvasEllipse();
+public:
+ virtual void drawContent(QPainter & p);
+ virtual int rtti() const;
+};
+
+
+class KviCanvasPie : public KviCanvasEllipticItem
+{
+public:
+ KviCanvasPie(QCanvas * c,int x,int y,int w,int h);
+ ~KviCanvasPie();
+public:
+ virtual void drawContent(QPainter & p);
+ virtual int rtti() const;
+};
+
+
+class KviCanvasChord : public KviCanvasEllipticItem
+{
+public:
+ KviCanvasChord(QCanvas * c,int x,int y,int w,int h);
+ ~KviCanvasChord();
+public:
+ virtual void drawContent(QPainter & p);
+ virtual int rtti() const;
+};
+
+
+class KviCanvasLine : public QCanvasLine
+{
+public:
+ KviCanvasLine(QCanvas * c,int x1,int y1,int x2,int y2);
+ virtual ~KviCanvasLine();
+protected:
+ QMap<QString,QVariant> m_properties;
+public:
+ QMap<QString,QVariant> * properties(){ return &m_properties; };
+ virtual void setProperty(const QString &property,const QVariant &val);
+// QVariant property(const QString &name){ return m_properties[name]; };
+ virtual void draw(QPainter & p);
+ virtual int rtti() const;
+};
+
+
+
+class KviCanvasRectangle : public KviCanvasRectangleItem
+{
+public:
+ KviCanvasRectangle(QCanvas * c,int x,int y,int w,int h);
+ ~KviCanvasRectangle();
+public:
+ virtual void draw(QPainter & p);
+ virtual void setProperty(const QString &property,const QVariant &val);
+ virtual int rtti() const;
+};
+
+
+class KviCanvasRichText : public KviCanvasRectangleItem
+{
+public:
+ KviCanvasRichText(QCanvas * c,int x,int y,int w,int h);
+ ~KviCanvasRichText();
+public:
+ virtual void draw(QPainter & p);
+ virtual int rtti() const;
+};
+
+
+class KviCanvasView : public QCanvasView
+{
+ Q_OBJECT
+public:
+ KviCanvasView(QCanvas * c,KviCanvasWidget * cw,QWidget * par);
+ ~KviCanvasView();
+public:
+ enum State { Idle , SelectOrigin };
+ enum ObjectType {
+ Rectangle , RichText , Line , Ellipse , Chord , Pie ,
+ PolygonTriangle , PolygonRectangle , PolygonPentagon ,
+ PolygonHexagon
+ };
+ enum DragMode {
+ None , All , Left , Right , Top , Bottom , LeftTop , RightTop ,
+ LeftBottom , RightBottom , Scale , SinglePoint , Rotate
+ };
+protected:
+ KviCanvasWidget * m_pCanvasWidget;
+
+ // Insertion of objects
+ State m_state;
+ ObjectType m_objectToInsert;
+
+ // Selected item
+ QCanvasItem * m_pSelectedItem;
+
+ DragMode m_dragMode;
+ QPoint m_dragBegin;
+ double m_dragScaleFactor;
+ unsigned int m_dragPointIndex;
+ QPointArray m_dragPointArray;
+protected:
+ void beginDragRectangle(KviCanvasRectangleItem * it,const QPoint &p,bool bInitial = false);
+ void dragRectangle(KviCanvasRectangleItem * it,const QPoint & p);
+
+ void beginDragLine(KviCanvasLine * it,const QPoint &p,bool bInitial = false);
+ void dragLine(KviCanvasLine * it,const QPoint &p);
+
+ void beginDragPolygon(KviCanvasPolygon * it,const QPoint &p,bool bShift = false,bool bCtrl = false);
+ void dragPolygon(KviCanvasPolygon * it,const QPoint &p);
+
+
+ void setItemSelected(QCanvasItem * it);
+ void clearSelection();
+ void insertObjectAt(const QPoint & pnt,ObjectType o);
+ virtual void contentsMousePressEvent(QMouseEvent *e);
+ virtual void contentsMouseMoveEvent(QMouseEvent *e);
+ virtual void contentsMouseReleaseEvent(QMouseEvent *e);
+public slots:
+ void insertRectangle();
+ void insertRichText();
+ void insertLine();
+ void insertPie();
+ void insertChord();
+ void insertEllipse();
+ void insertPolygonTriangle();
+ void insertPolygonRectangle();
+ void insertPolygonPentagon();
+ void insertPolygonHexagon();
+ void propertyChanged(const QString &s,const QVariant &v);
+};
+
+// For Qt3.0 this might need to be changed
+
+class KviVariantTableItem : public QTableItem
+{
+public:
+ KviVariantTableItem(QTable * t,const QVariant & property);
+ ~KviVariantTableItem();
+private:
+ QVariant m_property;
+public:
+ virtual QWidget * createEditor() const;
+ virtual void setContentFromEditor(QWidget *w);
+ QVariant & property(){ return m_property; };
+ virtual void paint(QPainter *p,const QColorGroup &cg,const QRect &cr,bool selected);
+};
+
+
+
+class KviCanvasItemPropertiesWidget : public QTable
+{
+ Q_OBJECT
+public:
+ KviCanvasItemPropertiesWidget(QWidget * par);
+ ~KviCanvasItemPropertiesWidget();
+public:
+ void editItem(QCanvasItem * it);
+protected slots:
+ void cellEdited(int row,int col);
+signals:
+ void propertyChanged(const QString &s,const QVariant &v);
+};
+
+
+
+class KviCanvasWidget : public QWidget
+{
+ friend class KviCanvasView;
+ Q_OBJECT
+public:
+ KviCanvasWidget(QWidget * par);
+ ~KviCanvasWidget();
+protected:
+ QSplitter * m_pSplitter;
+ QCanvas * m_pCanvas;
+ QMenuBar * m_pMenuBar;
+ KviCanvasView * m_pCanvasView;
+ QLabel * m_pStatusLabel;
+ KviCanvasItemPropertiesWidget * m_pPropertiesWidget;
+protected:
+ virtual void resizeEvent(QResizeEvent *);
+};
+
+
+#endif
+
+#endif //_CANVAS_WIDGET_H_
diff --git a/src/modules/dcc/chat.cpp b/src/modules/dcc/chat.cpp
new file mode 100644
index 00000000..715d17b9
--- /dev/null
+++ b/src/modules/dcc/chat.cpp
@@ -0,0 +1,842 @@
+//=======================================================================================
+//
+// File : chat.cpp
+// Creation date : Tue Sep 20 09 2000 15:13:13 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=======================================================================================
+
+#include "chat.h"
+#include "marshal.h"
+#include "broker.h"
+
+#ifdef COMPILE_ON_WINDOWS
+ // Ugly Windoze compiler...
+ #include "dialogs.h"
+#endif
+
+#define _KVI_DEBUG_CHECK_RANGE_
+#include "kvi_debug.h"
+#include "kvi_options.h"
+#include "kvi_input.h"
+#include "kvi_ircview.h"
+#include "kvi_iconmanager.h"
+#include "kvi_locale.h"
+#include "kvi_error.h"
+#include "kvi_out.h"
+#include "kvi_netutils.h"
+#include "kvi_console.h"
+#include "kvi_frame.h"
+#include "kvi_malloc.h"
+#include "kvi_memmove.h"
+#include "kvi_thread.h"
+#include "kvi_ircsocket.h"
+#include "kvi_settings.h"
+#include "kvi_themedlabel.h"
+#include "kvi_socket.h"
+#include "kvi_app.h"
+#include "kvi_parameterlist.h"
+#include "kvi_ircconnection.h"
+#include "kvi_ircconnectionuserinfo.h"
+#include "kvi_kvs_eventtriggers.h"
+#include "kvi_qcstring.h"
+
+#ifdef COMPILE_CRYPT_SUPPORT
+ #include "kvi_crypt.h"
+ #include "kvi_cryptcontroller.h"
+ #include "kvi_mirccntrl.h"
+#endif
+
+#include <qsplitter.h>
+#include <qevent.h>
+#include "kvi_tal_vbox.h"
+
+
+#ifdef COMPILE_SSL_SUPPORT
+ #include "kvi_sslmaster.h"
+#endif
+
+
+
+extern KviDccBroker * g_pDccBroker;
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////
+////// WINDOW
+//////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+KviDccChat::KviDccChat(KviFrame *pFrm,KviDccDescriptor * dcc,const char * name)
+: KviDccWindow(KVI_WINDOW_TYPE_DCCCHAT,pFrm,name,dcc)
+{
+ m_pTopSplitter = new QSplitter(Qt::Horizontal,this,"top_splitter");
+ KviThemedLabel * dummy;
+ dummy = new KviThemedLabel(m_pTopSplitter,"dummy_label");
+ KviTalVBox * box = new KviTalVBox(m_pTopSplitter);
+
+#ifdef COMPILE_CRYPT_SUPPORT
+ createCryptControllerButton(box);
+#endif
+
+ m_pSplitter = new QSplitter(Qt::Horizontal,this,"splitter");
+ m_pIrcView = new KviIrcView(m_pSplitter,pFrm,this);
+ connect(m_pIrcView,SIGNAL(rightClicked()),this,SLOT(textViewRightClicked()));
+ m_pInput = new KviInput(this);
+
+ //setFocusHandler(m_pInput,this);
+
+ m_pSlaveThread = 0;
+
+ if(KVI_OPTION_BOOL(KviOption_boolAutoLogDccChat))m_pIrcView->startLogging();
+
+ m_pMarshal = new KviDccMarshal(this);
+ connect(m_pMarshal,SIGNAL(error(int)),this,SLOT(handleMarshalError(int)));
+ connect(m_pMarshal,SIGNAL(connected()),this,SLOT(connected()));
+ connect(m_pMarshal,SIGNAL(inProgress()),this,SLOT(connectionInProgress()));
+#ifdef COMPILE_SSL_SUPPORT
+ connect(m_pMarshal,SIGNAL(startingSSLHandshake()),this,SLOT(startingSSLHandshake()));
+ connect(m_pMarshal,SIGNAL(sslError(const char *)),this,SLOT(sslError(const char *)));
+#endif
+
+ m_pSlaveThread = 0;
+
+ startConnection();
+}
+
+KviDccChat::~KviDccChat()
+{
+ g_pDccBroker->unregisterDccWindow(this);
+ if(m_pSlaveThread)
+ {
+ m_pSlaveThread->terminate();
+ delete m_pSlaveThread;
+ m_pSlaveThread = 0;
+ }
+ KviThreadManager::killPendingEvents(this);
+}
+
+void KviDccChat::textViewRightClicked()
+{
+ KVS_TRIGGER_EVENT_1(KviEvent_OnDCCChatPopupRequest,this,m_pDescriptor->idString());
+}
+
+void KviDccChat::triggerCreationEvents()
+{
+ KVS_TRIGGER_EVENT_1(KviEvent_OnDCCChatWindowCreated,this,m_pDescriptor->idString());
+}
+
+void KviDccChat::triggerDestructionEvents()
+{
+ KVS_TRIGGER_EVENT_1(KviEvent_OnDCCChatWindowClosing,this,m_pDescriptor->idString());
+}
+
+void KviDccChat::startConnection()
+{
+ if(!(m_pDescriptor->bActive))
+ {
+ // PASSIVE CONNECTION
+ output(KVI_OUT_DCCMSG,__tr2qs_ctx("Attempting a passive DCC %s connection","dcc"),m_pDescriptor->szType.utf8().data());
+#ifdef COMPILE_SSL_SUPPORT
+ int ret = m_pMarshal->dccListen(m_pDescriptor->szListenIp,m_pDescriptor->szListenPort,m_pDescriptor->bDoTimeout,m_pDescriptor->bIsSSL);
+#else
+ int ret = m_pMarshal->dccListen(m_pDescriptor->szListenIp,m_pDescriptor->szListenPort,m_pDescriptor->bDoTimeout);
+#endif
+ if(ret != KviError_success)handleMarshalError(ret);
+
+ } else {
+ // ACTIVE CONNECTION
+ output(KVI_OUT_DCCMSG,__tr2qs_ctx("Attempting an active DCC %s connection","dcc"),m_pDescriptor->szType.utf8().data());
+#ifdef COMPILE_SSL_SUPPORT
+ int ret = m_pMarshal->dccConnect(m_pDescriptor->szIp.utf8().data(),m_pDescriptor->szPort.utf8().data(),m_pDescriptor->bDoTimeout,m_pDescriptor->bIsSSL);
+#else
+ int ret = m_pMarshal->dccConnect(m_pDescriptor->szIp.utf8().data(),m_pDescriptor->szPort.utf8().data(),m_pDescriptor->bDoTimeout);
+#endif
+ if(ret != KviError_success)handleMarshalError(ret);
+ }
+}
+
+void KviDccChat::connectionInProgress()
+{
+ if(m_pDescriptor->bActive)
+ {
+ output(KVI_OUT_DCCMSG,__tr2qs_ctx("Contacting host %Q on port %Q","dcc"),&(m_pDescriptor->szIp),&(m_pDescriptor->szPort));
+ } else {
+ output(KVI_OUT_DCCMSG,__tr2qs_ctx("Listening on interface %Q port %Q","dcc"),&(m_pMarshal->localIp()),&(m_pMarshal->localPort()));
+
+ if(m_pDescriptor->bSendRequest)
+ {
+
+ KviStr ip;
+ if(!m_pDescriptor->szFakeIp.isEmpty())
+ {
+ ip = m_pDescriptor->szFakeIp;
+ } else {
+ ip = m_pDescriptor->szListenIp;
+
+ if(KVI_OPTION_BOOL(KviOption_boolDccGuessIpFromServerWhenLocalIsUnroutable))
+ {
+ if(!kvi_isRoutableIpString(ip.ptr()))
+ {
+ // try to get the IP that the IRC server can see
+ if(m_pDescriptor->console())
+ {
+ KviStr tmp = m_pDescriptor->console()->connection() ? m_pDescriptor->console()->connection()->userInfo()->hostIp().utf8().data() : "";
+ if(tmp.hasData())
+ {
+ ip = tmp;
+ output(KVI_OUT_DCCMSG,__tr2qs_ctx("The local IP address is private, determining from IRC server: %s","dcc"),ip.ptr());
+ } else {
+ output(KVI_OUT_DCCMSG,__tr2qs_ctx("The local IP address is private, but unable to determine it from the IRC server","dcc"));
+ }
+ } else {
+ output(KVI_OUT_DCCMSG,__tr2qs_ctx("The local IP address is private, but have no IRC server to determine it from","dcc"));
+ }
+ }
+ }
+ }
+
+ QString port = !m_pDescriptor->szFakePort.isEmpty() ? m_pDescriptor->szFakePort : QString(m_pMarshal->localPort());
+
+ //FIXME: #warning "OPTION FOR SENDING 127.0.0.1 and so on (not an unsigned number)"
+ struct in_addr a;
+ if(kvi_stringIpToBinaryIp(ip.ptr(),&a))ip.setNum(htonl(a.s_addr));
+
+ QString szReq = QString("PRIVMSG %1 :%2DCC %3 chat %4 %5").arg(m_pDescriptor->szNick).arg((char)0x01).arg(m_pDescriptor->szType).arg(ip.ptr()).arg(port);
+
+ if(m_pDescriptor->isZeroPortRequest())
+ {
+ szReq.append(" ");
+ szReq+=m_pDescriptor->zeroPortRequestTag();
+ }
+ szReq.append((char)(0x01));
+
+ m_pDescriptor->console()->connection()->sendData(m_pDescriptor->console()->connection()->encodeText(szReq).data());
+ output(KVI_OUT_DCCMSG,__tr2qs_ctx("Sent DCC %Q request to %Q, waiting for the remote client to connect...","dcc"),
+ &(m_pDescriptor->szType),&(m_pDescriptor->szNick));
+ //qDebug(m_pDescriptor->szNick);
+ } else output(KVI_OUT_DCCMSG,__tr2qs_ctx("DCC %Q request not sent, awaiting manual connection","dcc"),&(m_pDescriptor->szType));
+ }
+ KVS_TRIGGER_EVENT_1(KviEvent_OnDCCChatConnectionInProgress,this,m_pDescriptor->idString());
+}
+
+void KviDccChat::startingSSLHandshake()
+{
+#ifdef COMPILE_SSL_SUPPORT
+ outputNoFmt(KVI_OUT_SSL,__tr2qs_ctx("Low-level transport connection established","dcc"));
+ outputNoFmt(KVI_OUT_SSL,__tr2qs_ctx("Starting Secure Socket Layer handshake","dcc"));
+#endif
+}
+
+void KviDccChat::sslError(const char * msg)
+{
+#ifdef COMPILE_SSL_SUPPORT
+ if(!KVS_TRIGGER_EVENT_2_HALTED(KviEvent_OnDCCChatError,this,QString(msg),m_pDescriptor->idString()))
+ output(KVI_OUT_DCCERROR,__tr2qs_ctx("[SSL ERROR]: %s","dcc"),msg);
+#endif
+}
+
+const QString & KviDccChat::target()
+{
+ // This may change on the fly...
+ m_szTarget = m_pDescriptor->szNick;
+ m_szTarget += "@";
+ m_szTarget += m_pDescriptor->szIp;
+ m_szTarget += ":";
+ m_szTarget += m_pDescriptor->szPort;
+ return m_szTarget;
+}
+
+void KviDccChat::fillCaptionBuffers()
+{
+ QString tmp = QString("DCC %1 %2@%3:%4").arg(
+#ifdef COMPILE_SSL_SUPPORT
+ m_pDescriptor->bIsSSL ? "SChat" : "Chat").arg(
+#else
+ "Chat").arg(
+#endif
+ m_pDescriptor->szNick).arg(m_pDescriptor->szIp).arg(m_pDescriptor->szPort);
+
+ m_szPlainTextCaption = tmp;
+
+ m_szHtmlActiveCaption.sprintf("<nobr><font color=\"%s\"><b>%s</b></font></nobr>",
+ KVI_OPTION_COLOR(KviOption_colorCaptionTextActive).name().ascii(),tmp.utf8().data());
+ m_szHtmlInactiveCaption.sprintf("<nobr><font color=\"%s\"><b>%s</b></font></nobr>",
+ KVI_OPTION_COLOR(KviOption_colorCaptionTextInactive).name().ascii(),tmp.utf8().data());
+}
+
+QPixmap * KviDccChat::myIconPtr()
+{
+ return g_pIconManager->getSmallIcon(KVI_SMALLICON_DCCMSG);
+}
+
+
+void KviDccChat::getBaseLogFileName(KviStr &buffer)
+{
+ buffer.sprintf("%s_%s_%s",m_pDescriptor->szNick.utf8().data(),m_pDescriptor->szIp.utf8().data(),m_pDescriptor->szPort.utf8().data());
+}
+
+void KviDccChat::ownMessage(const QString &text)
+{
+ if(!m_pSlaveThread)
+ {
+ output(KVI_OUT_SYSTEMWARNING,__tr2qs_ctx("Cannot send data: No active connection","dcc"));
+ return;
+ }
+
+ KviQCString szData = encodeText(text);
+ const char * d = szData.data();
+ if(!d)return;
+
+#ifdef COMPILE_CRYPT_SUPPORT
+ if(cryptSessionInfo())
+ {
+ if(cryptSessionInfo()->bDoEncrypt)
+ {
+ if(*d != KVI_TEXT_CRYPTESCAPE)
+ {
+ KviStr encrypted;
+ cryptSessionInfo()->pEngine->setMaxEncryptLen(-1);
+ switch(cryptSessionInfo()->pEngine->encrypt(d,encrypted))
+ {
+ case KviCryptEngine::Encrypted:
+ {
+ KviStr buf(KviStr::Format,"%s\r\n",encrypted.ptr());
+ m_pSlaveThread->sendRawData(buf.ptr(),buf.len());
+ m_pFrm->firstConsole()->outputPrivmsg(this,KVI_OUT_OWNPRIVMSGCRYPTED,
+ m_pDescriptor->szLocalNick.utf8().data(),m_pDescriptor->szLocalUser.utf8().data(),
+ m_pDescriptor->szLocalHost.utf8().data(),text,KviConsole::NoNotifications);
+ }
+ break;
+ case KviCryptEngine::Encoded:
+ {
+ KviStr buf(KviStr::Format,"%s\r\n",encrypted.ptr());
+ m_pSlaveThread->sendRawData(buf.ptr(),buf.len());
+ QString encr = decodeText(encrypted.ptr());
+ m_pFrm->firstConsole()->outputPrivmsg(this,KVI_OUT_OWNPRIVMSG,
+ m_pDescriptor->szLocalNick.utf8().data(),m_pDescriptor->szLocalUser.utf8().data(),
+ m_pDescriptor->szLocalHost.utf8().data(),encr,KviConsole::NoNotifications);
+ }
+ break;
+ default: // also case KviCryptEngine::EncryptError
+ {
+ QString szErr = cryptSessionInfo()->pEngine->lastError();
+ output(KVI_OUT_SYSTEMERROR,
+ __tr2qs_ctx("The crypto engine was not able to encrypt the current message (%Q): %Q, no data was sent to the remote end","dcc"),
+ &text,&szErr);
+ }
+ break;
+ }
+ return;
+ } else {
+ d++; //eat the escape code
+ KviStr buf(KviStr::Format,"%s\r\n",d);
+ QString tmp = text.right(text.length() - 1);
+ m_pSlaveThread->sendRawData(buf.ptr(),buf.len());
+ m_pFrm->firstConsole()->outputPrivmsg(this,KVI_OUT_OWNPRIVMSG,
+ m_pDescriptor->szLocalNick.utf8().data(),m_pDescriptor->szLocalUser.utf8().data(),
+ m_pDescriptor->szLocalHost.utf8().data(),tmp,KviConsole::NoNotifications);
+ return;
+ }
+ }
+ }
+#endif
+ KviStr buf(KviStr::Format,"%s\r\n",d);
+ m_pSlaveThread->sendRawData(buf.ptr(),buf.len());
+ m_pFrm->firstConsole()->outputPrivmsg(this,KVI_OUT_OWNPRIVMSG,
+ m_pDescriptor->szLocalNick.utf8().data(),m_pDescriptor->szLocalUser.utf8().data(),
+ m_pDescriptor->szLocalHost.utf8().data(),text,KviConsole::NoNotifications);
+}
+
+const QString & KviDccChat::localNick()
+{
+ // FIXME: This is just a complete HACK
+ m_szLocalNick = m_pDescriptor->szLocalNick;
+ return m_szLocalNick;
+}
+
+void KviDccChat::ownAction(const QString &text)
+{
+ if(m_pSlaveThread)
+ {
+ KviQCString szData = encodeText(text);
+ const char * d = szData.data();
+ if(!d)return;
+ KviStr buf(KviStr::Format,"%cACTION %s%c\r\n",0x01,d,0x01);
+ m_pSlaveThread->sendRawData(buf.ptr(),buf.len());
+ output(KVI_OUT_ACTION,"%Q %Q",&(m_pDescriptor->szLocalNick),&text);
+ } else {
+ output(KVI_OUT_SYSTEMWARNING,__tr2qs_ctx("Cannot send data: No active connection","dcc"));
+ }
+}
+
+bool KviDccChat::event(QEvent *e)
+{
+ if(e->type() == KVI_THREAD_EVENT)
+ {
+ switch(((KviThreadEvent *)e)->id())
+ {
+ case KVI_DCC_THREAD_EVENT_ERROR:
+ {
+ int * err = ((KviThreadDataEvent<int> *)e)->getData();
+ QString szErr = KviError::getDescription(*err);
+ if(!KVS_TRIGGER_EVENT_2_HALTED(KviEvent_OnDCCChatError,this,szErr,m_pDescriptor->idString()))
+ output(KVI_OUT_DCCERROR,__tr2qs_ctx("ERROR: %Q","dcc"),&szErr);
+ KVS_TRIGGER_EVENT_1(KviEvent_OnDCCChatDisconnected,this,m_pDescriptor->idString());
+ delete err;
+ return true;
+ }
+ break;
+ case KVI_DCC_THREAD_EVENT_DATA:
+ {
+ KviStr * encoded = ((KviThreadDataEvent<KviStr> *)e)->getData();
+ KviStr d=KviStr(decodeText(encoded->ptr()));
+ if(d.firstCharIs(0x01))
+ {
+ d.cutLeft(1);
+ if(d.lastCharIs(0x01))d.cutRight(1);
+ if(kvi_strEqualCIN("ACTION",d.ptr(),6))d.cutLeft(6);
+ d.stripLeftWhiteSpace();
+ output(KVI_OUT_ACTION,"%Q %s",&(m_pDescriptor->szNick),d.ptr());
+ } else {
+
+#ifdef COMPILE_CRYPT_SUPPORT
+ if(KviCryptSessionInfo * cinf = cryptSessionInfo())
+ {
+ if(cinf->bDoDecrypt)
+ {
+ KviStr decryptedStuff;
+ switch(cinf->pEngine->decrypt(d.ptr(),decryptedStuff))
+ {
+ case KviCryptEngine::DecryptOkWasEncrypted:
+ case KviCryptEngine::DecryptOkWasEncoded:
+ case KviCryptEngine::DecryptOkWasPlainText:
+ if(!KVS_TRIGGER_EVENT_2_HALTED(KviEvent_OnDCCChatMessage,this,QString(decryptedStuff.ptr()),m_pDescriptor->idString()))
+ {
+ m_pFrm->firstConsole()->outputPrivmsg(this,KVI_OUT_DCCCHATMSG,
+ m_pDescriptor->szNick.utf8().data(),m_pDescriptor->szUser.utf8().data(),
+ m_pDescriptor->szHost.utf8().data(),decryptedStuff.ptr());
+ }
+ delete encoded;
+ return true;
+ break;
+
+ default: // also case KviCryptEngine::DecryptError
+ {
+ QString szErr = cinf->pEngine->lastError();
+ output(KVI_OUT_SYSTEMERROR,
+ __tr2qs_ctx("The following message appears to be encrypted, but the crypto engine failed to decode it: %Q","dcc"),
+ &szErr);
+ }
+ break;
+ }
+ }
+ } else {
+#endif
+ // FIXME!
+ if(!KVS_TRIGGER_EVENT_2_HALTED(KviEvent_OnDCCChatMessage,this,QString(d.ptr()),m_pDescriptor->idString()))
+ m_pFrm->firstConsole()->outputPrivmsg(this,KVI_OUT_DCCCHATMSG,
+ m_pDescriptor->szNick.utf8().data(),m_pDescriptor->szUser.utf8().data(),
+ m_pDescriptor->szHost.utf8().data(),d.ptr());
+#ifdef COMPILE_CRYPT_SUPPORT
+ }
+#endif
+ }
+ delete encoded;
+ return true;
+ }
+ break;
+ }
+ }
+ return KviWindow::event(e);
+}
+
+void KviDccChat::resizeEvent(QResizeEvent *e)
+{
+ int hght = m_pInput->heightHint();
+ int hght2 = m_pTopSplitter->sizeHint().height();
+ m_pTopSplitter->setGeometry(0,0,width(),hght2);
+ m_pSplitter->setGeometry(0,hght2,width(),height() - (hght + hght2));
+ m_pInput->setGeometry(0,height() - hght,width(),hght);
+}
+
+QSize KviDccChat::sizeHint() const
+{
+ QSize ret(m_pIrcView->sizeHint().width(),
+ m_pIrcView->sizeHint().height() + m_pInput->heightHint());
+ return ret;
+}
+
+void KviDccChat::handleMarshalError(int err)
+{
+ QString szErr = KviError::getDescription(err);
+ if(!KVS_TRIGGER_EVENT_2_HALTED(KviEvent_OnDCCChatError,this,szErr,m_pDescriptor->idString()))
+ output(KVI_OUT_DCCERROR,__tr2qs_ctx("DCC %Q failed: %Q","dcc"),&(m_pDescriptor->szType),&szErr);
+}
+
+void KviDccChat::connected()
+{
+ if(!(m_pDescriptor->bActive))
+ {
+ // PASSIVE CONNECTION...Find out the remote end
+ m_pDescriptor->szIp = m_pMarshal->remoteIp();
+ m_pDescriptor->szPort = m_pMarshal->remotePort();
+ m_pDescriptor->szHost = m_pMarshal->remoteIp();
+ }
+
+ updateCaption();
+
+ m_pSlaveThread = new KviDccChatThread(this,m_pMarshal->releaseSocket());
+#ifdef COMPILE_SSL_SUPPORT
+ KviSSL * s = m_pMarshal->releaseSSL();
+ if(s)
+ {
+ KviSSLMaster::printSSLConnectionInfo(this,s);
+ m_pSlaveThread->setSSL(s);
+ }
+#endif
+ m_pSlaveThread->start();
+
+ if(!KVS_TRIGGER_EVENT_1_HALTED(KviEvent_OnDCCChatConnected,this,m_pDescriptor->idString()))
+ {
+ output(KVI_OUT_DCCMSG,__tr2qs_ctx("Connected to %Q:%Q","dcc"),
+ &(m_pMarshal->remoteIp()),&(m_pMarshal->remotePort()));
+ output(KVI_OUT_DCCMSG,__tr2qs_ctx("Local end is %Q:%Q","dcc"),
+ &(m_pMarshal->localIp()),&(m_pMarshal->localPort()));
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////
+////// THREAD
+//////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+KviDccChatThread::KviDccChatThread(KviWindow *wnd,kvi_socket_t fd)
+: KviDccThread(wnd,fd)
+{
+ m_pOutBuffers = new KviPointerList<KviDataBuffer>;
+ m_pOutBuffers->setAutoDelete(true);
+}
+
+
+KviDccChatThread::~KviDccChatThread()
+{
+ if(m_pOutBuffers)delete m_pOutBuffers;
+}
+
+
+void KviDccChatThread::run()
+{
+ KviDccThreadIncomingData data;
+ data.iLen = 0;
+ data.buffer = 0;
+
+ for(;;)
+ {
+ // Dequeue events
+ while(KviThreadEvent * e = dequeueEvent())
+ {
+ if(e->id() == KVI_THREAD_EVENT_TERMINATE)
+ {
+ delete e;
+ goto out_of_the_loop;
+ } else {
+ // Other events are senseless to us
+ delete e;
+ }
+ }
+
+ bool bCanRead;
+ bool bCanWrite;
+ if(kvi_select(m_fd,&bCanRead,&bCanWrite))
+ {
+ if(bCanWrite)
+ {
+ if(!tryFlushOutBuffers())goto out_of_the_loop;
+ }
+ if(bCanRead)
+ {
+ data.buffer = (char *) kvi_realloc(data.buffer,(data.iLen + 512) * sizeof(char));
+ int readLen;
+#ifdef COMPILE_SSL_SUPPORT
+ if(m_pSSL)
+ {
+ readLen = m_pSSL->read(data.buffer + data.iLen,512);
+ } else {
+#endif
+ readLen = kvi_socket_recv(m_fd,data.buffer + data.iLen,512);
+#ifdef COMPILE_SSL_SUPPORT
+ }
+#endif
+ if(readLen > 0)
+ {
+ data.iLen += readLen;
+ data.buffer = (char *)kvi_realloc(data.buffer,data.iLen * sizeof(char));
+ if(!handleIncomingData(&data,false))break; // non critical...
+ } else {
+
+#ifdef COMPILE_SSL_SUPPORT
+ if(m_pSSL)
+ {
+ // ssl error....?
+ switch(m_pSSL->getProtocolError(readLen))
+ {
+ case KviSSL::ZeroReturn:
+ readLen = 0;
+ break;
+ case KviSSL::WantRead:
+ case KviSSL::WantWrite:
+ // hmmm...
+ break;
+ case KviSSL::SyscallError:
+ {
+ int iE = m_pSSL->getLastError(true);
+ if(iE != 0)
+ {
+ raiseSSLError();
+ postErrorEvent(KviError_SSLError);
+ goto out_of_the_loop;
+ }
+ }
+ break;
+ case KviSSL::SSLError:
+ {
+ raiseSSLError();
+ postErrorEvent(KviError_SSLError);
+ goto out_of_the_loop;
+ }
+ break;
+ default:
+ // Raise unknown SSL ERROR
+ postErrorEvent(KviError_SSLError);
+ goto out_of_the_loop;
+ break;
+ }
+ }
+#endif
+ if(data.iLen > 0)
+ {
+ data.buffer = (char *)kvi_realloc(data.buffer,data.iLen * sizeof(char));
+ } else {
+ kvi_free(data.buffer);
+ data.buffer = 0;
+ }
+
+ if(!handleInvalidSocketRead(readLen))
+ {
+ if(data.iLen)handleIncomingData(&data,true); // critical
+ __range_invalid(data.iLen);
+ break; // error
+ }
+ }
+ }
+ msleep(100);
+ }
+ }
+
+out_of_the_loop:
+
+
+ if(data.iLen)kvi_free(data.buffer);
+
+#ifdef COMPILE_SSL_SUPPORT
+ if(m_pSSL)
+ {
+ KviSSLMaster::freeSSL(m_pSSL);
+ m_pSSL = 0;
+ }
+#endif
+
+ if(m_fd != KVI_INVALID_SOCKET)::kvi_socket_close(m_fd);
+ m_fd = KVI_INVALID_SOCKET;
+}
+
+bool KviDccChatThread::handleIncomingData(KviDccThreadIncomingData * data,bool bCritical)
+{
+ __range_valid(data->iLen);
+ __range_valid(data->buffer);
+ char * aux = data->buffer;
+ char * end = data->buffer + data->iLen;
+ while(aux != end)
+ {
+ if((*aux == '\n') || (*aux == '\0'))
+ {
+ KviThreadDataEvent<KviStr> * e = new KviThreadDataEvent<KviStr>(KVI_DCC_THREAD_EVENT_DATA);
+ // The left part is len chars long
+ int len = aux - data->buffer;
+// debug("LEN = %d, iLen = %d",len,data->iLen);
+//#warning "DO IT BETTER (the \r cutting)"
+ KviStr * s = new KviStr(data->buffer,len);
+ if(s->lastCharIs('\r'))s->cutRight(1);
+ e->setData(s);
+ // but we cut also \n (or \0)
+ ++aux;
+ // so len += 1; --> new data->iLen -= len;
+ data->iLen -= (len + 1);
+// debug("iLen now = %d",data->iLen);
+ __range_valid(data->iLen >= 0);
+ if(data->iLen > 0)
+ {
+ // memmove the remaining part to the beginning
+ // aux points after \n or \0
+ kvi_memmove(data->buffer,aux,data->iLen);
+ data->buffer = (char *)kvi_realloc(data->buffer,data->iLen);
+ end = data->buffer + data->iLen;
+ aux = data->buffer;
+ } else {
+ // no more data in the buffer
+ __range_valid(data->iLen == 0);
+ kvi_free(data->buffer);
+ data->buffer = end = aux = 0;
+ }
+ postEvent(parent(),e);
+ } else aux++;
+// debug("PASSING CHAR %c",*aux);
+ }
+ // now aux == end
+ if(bCritical)
+ {
+ // need to flush everything...
+ if(data->iLen > 0)
+ {
+ // in the last part there are no NULL and \n chars
+ KviThreadDataEvent<KviStr> * e = new KviThreadDataEvent<KviStr>(KVI_DCC_THREAD_EVENT_DATA);
+ KviStr * s = new KviStr(data->buffer,data->iLen);
+ if(s->lastCharIs('\r'))s->cutRight(1);
+ e->setData(s);
+ data->iLen = 0;
+ kvi_free(data->buffer);
+ data->buffer = 0;
+ postEvent(parent(),e);
+ }
+ }
+ return true;
+}
+
+void KviDccChatThread::sendRawData(const void * buffer,int len)
+{
+ m_pMutex->lock();
+ m_pOutBuffers->append(new KviDataBuffer((unsigned int)len,(const unsigned char *)buffer));
+ m_pMutex->unlock();
+}
+
+bool KviDccChatThread::tryFlushOutBuffers()
+{
+ bool bRet = true;
+ m_pMutex->lock();
+ while(KviDataBuffer * b = m_pOutBuffers->first())
+ {
+ int sentLen;
+#ifdef COMPILE_SSL_SUPPORT
+ if(m_pSSL)
+ {
+ sentLen = m_pSSL->write((const char *)b->data(),b->size());
+ } else {
+#endif
+ sentLen = kvi_socket_send(m_fd,b->data(),b->size());
+#ifdef COMPILE_SSL_SUPPORT
+ }
+#endif
+ if(sentLen > 0)
+ {
+ if(sentLen == b->size())m_pOutBuffers->removeFirst();
+ else {
+ // just a part
+ b->remove((unsigned int)sentLen);
+ break;
+ }
+ } else {
+#ifdef COMPILE_SSL_SUPPORT
+ if(m_pSSL)
+ {
+ // ops...might be an SSL error
+ switch(m_pSSL->getProtocolError(sentLen))
+ {
+ case KviSSL::WantWrite:
+ case KviSSL::WantRead:
+ // Async continue...
+ goto handle_system_error;
+ break;
+ case KviSSL::SyscallError:
+ if(sentLen == 0)
+ {
+ raiseSSLError();
+ postErrorEvent(KviError_remoteEndClosedConnection);
+ bRet = false;
+ goto out_of_the_loop;
+ } else {
+ int iSSLErr = m_pSSL->getLastError(true);
+ if(iSSLErr != 0)
+ {
+ raiseSSLError();
+ postErrorEvent(KviError_SSLError);
+ bRet = false;
+ goto out_of_the_loop;
+ } else {
+ goto handle_system_error;
+ }
+ }
+ break;
+ case KviSSL::SSLError:
+ raiseSSLError();
+ postErrorEvent(KviError_SSLError);
+ bRet = false;
+ goto out_of_the_loop;
+ break;
+ default:
+ postErrorEvent(KviError_SSLError);
+ bRet = false;
+ goto out_of_the_loop;
+ break;
+ }
+ }
+#endif
+handle_system_error:
+ if(sentLen < 0)
+ {
+ int err = kvi_socket_error();
+#ifdef COMPILE_ON_WINDOWS
+ if((err != EAGAIN) || (err != EINTR) || (err != WSAEWOULDBLOCK))
+#else
+ if((err != EAGAIN)||(err != EINTR))
+#endif
+ {
+ postErrorEvent(KviError::translateSystemError(err));
+ bRet = false;
+ goto out_of_the_loop;
+ }
+ }
+ break; // send error
+ }
+ }
+out_of_the_loop:
+ m_pMutex->unlock();
+ return bRet;
+}
+
+#include "m_chat.moc"
diff --git a/src/modules/dcc/chat.h b/src/modules/dcc/chat.h
new file mode 100644
index 00000000..ae1d51b9
--- /dev/null
+++ b/src/modules/dcc/chat.h
@@ -0,0 +1,101 @@
+#ifndef _CHAT_H_
+#define _CHAT_H_
+//=============================================================================
+//
+// File : chat.h
+// Creation date : Tue Sep 20 09 2000 15:11:12 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_window.h"
+#include "kvi_string.h"
+#include "kvi_databuffer.h"
+
+#include "window.h"
+#include "descriptor.h"
+#include "thread.h"
+
+#include "kvi_pointerlist.h"
+
+#ifdef COMPILE_SSL_SUPPORT
+ class KviSSL;
+#endif
+
+class KviDccChatThread : public KviDccThread
+{
+public:
+ KviDccChatThread(KviWindow * wnd,kvi_socket_t fd);
+ ~KviDccChatThread();
+protected:
+ KviPointerList<KviDataBuffer> * m_pOutBuffers;
+protected:
+ virtual void run();
+ bool tryFlushOutBuffers();
+ // This should handle the incoming data buffer
+ // must "eat" some data from data.buffer, memmove the remaining part
+ // to the beginning , kvi_realloc data.buffer and update data.iLen
+ // If bCritical is true , it should handle the whole data buffer
+ // since the thread is going to die
+ // It should return true if the handing was succesfull
+ // or false if the thread should be stopped
+ virtual bool handleIncomingData(KviDccThreadIncomingData *data,bool bCritical);
+public:
+ virtual void sendRawData(const void * buffer,int len); // mutex (m_pOutBuffers usage)
+};
+
+class KviDccMarshal;
+class QSplitter;
+
+class KviDccChat : public KviDccWindow
+{
+ Q_OBJECT
+public:
+ KviDccChat(KviFrame *pFrm,KviDccDescriptor * dcc,const char * name);
+ ~KviDccChat();
+protected:
+ KviDccChatThread * m_pSlaveThread;
+ QSplitter * m_pTopSplitter;
+ QString m_szTarget;
+ QString m_szLocalNick;
+protected:
+ virtual const QString & target();
+ virtual void fillCaptionBuffers();
+ virtual void getBaseLogFileName(KviStr &buffer);
+ virtual QPixmap * myIconPtr();
+ virtual void resizeEvent(QResizeEvent *e);
+ virtual QSize sizeHint() const;
+ virtual const QString & localNick();
+ virtual bool event(QEvent *e);
+ virtual void ownMessage(const QString &text);
+ virtual void ownAction(const QString &text);
+ virtual void triggerCreationEvents();
+ virtual void triggerDestructionEvents();
+ void startConnection();
+protected slots:
+ void handleMarshalError(int err);
+ void connected();
+ void sslError(const char * msg);
+ void connectionInProgress();
+ void startingSSLHandshake();
+ void textViewRightClicked();
+};
+
+
+#endif //_CHAT_H_
diff --git a/src/modules/dcc/codec.cpp b/src/modules/dcc/codec.cpp
new file mode 100644
index 00000000..833796ac
--- /dev/null
+++ b/src/modules/dcc/codec.cpp
@@ -0,0 +1,88 @@
+//
+// File : codec.cpp
+// Creation date : Sun Aug 26 04:19:36 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "codec.h"
+
+KviDccVoiceCodec::KviDccVoiceCodec()
+{
+}
+
+KviDccVoiceCodec::~KviDccVoiceCodec()
+{
+}
+
+void KviDccVoiceCodec::encode(KviDataBuffer *,KviDataBuffer *)
+{
+}
+
+void KviDccVoiceCodec::decode(KviDataBuffer *,KviDataBuffer *)
+{
+}
+
+int KviDccVoiceCodec::encodedFrameSize()
+{
+ return 0;
+}
+
+int KviDccVoiceCodec::decodedFrameSize()
+{
+ return 0;
+}
+
+const char * KviDccVoiceCodec::name()
+{
+ return m_szName.ptr();
+}
+
+KviDccVoiceNullCodec::KviDccVoiceNullCodec()
+: KviDccVoiceCodec()
+{
+ m_szName = "null (no compression)";
+}
+
+KviDccVoiceNullCodec::~KviDccVoiceNullCodec()
+{
+}
+
+void KviDccVoiceNullCodec::encode(KviDataBuffer * signal,KviDataBuffer * stream)
+{
+ if(signal->size() < 1)return;
+ stream->append(signal->data(),signal->size());
+ signal->resize(0);
+}
+
+void KviDccVoiceNullCodec::decode(KviDataBuffer * stream,KviDataBuffer * signal)
+{
+ if(stream->size() < 1)return;
+ signal->append(stream->data(),stream->size());
+ stream->resize(0);
+}
+
+int KviDccVoiceNullCodec::encodedFrameSize()
+{
+ return 1024;
+}
+
+int KviDccVoiceNullCodec::decodedFrameSize()
+{
+ return 1024;
+}
diff --git a/src/modules/dcc/codec.h b/src/modules/dcc/codec.h
new file mode 100644
index 00000000..72fa6023
--- /dev/null
+++ b/src/modules/dcc/codec.h
@@ -0,0 +1,57 @@
+#ifndef _CODEC_H_
+#define _CODEC_H_
+//
+// File : codec.h
+// Creation date : Sun Aug 26 04:19:34 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_string.h"
+#include "kvi_databuffer.h"
+
+class KviDccVoiceCodec
+{
+public:
+ KviDccVoiceCodec();
+ virtual ~KviDccVoiceCodec();
+protected:
+ KviStr m_szName;
+public:
+ const char * name();
+ virtual void encode(KviDataBuffer * signal,KviDataBuffer * stream);
+ virtual void decode(KviDataBuffer * stream,KviDataBuffer * signal);
+ virtual int encodedFrameSize();
+ virtual int decodedFrameSize();
+};
+
+class KviDccVoiceNullCodec : public KviDccVoiceCodec
+{
+public:
+ KviDccVoiceNullCodec();
+ virtual ~KviDccVoiceNullCodec();
+public:
+ virtual void encode(KviDataBuffer * signal,KviDataBuffer * stream);
+ virtual void decode(KviDataBuffer * stream,KviDataBuffer * signal);
+ virtual int encodedFrameSize();
+ virtual int decodedFrameSize();
+};
+
+
+
+#endif //_CODEC_H_
diff --git a/src/modules/dcc/descriptor.cpp b/src/modules/dcc/descriptor.cpp
new file mode 100644
index 00000000..b21b0561
--- /dev/null
+++ b/src/modules/dcc/descriptor.cpp
@@ -0,0 +1,224 @@
+//=============================================================================
+//
+// File : src/modules/dcc/descriptor.cpp
+// Creation date : Tue Jul 23 01:11:54 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "descriptor.h"
+
+#include "kvi_locale.h"
+#include "kvi_kvs_eventtriggers.h"
+
+#include "kvi_window.h"
+#include "kvi_app.h"
+
+#include "send.h"
+#include "window.h"
+
+
+static unsigned int g_uNextDescriptorId = 1; // we use 0 as an invalid descriptor id
+static KviPointerHashTable<int,KviDccDescriptor> * g_pDescriptorDict = 0;
+
+KviPointerHashTable<int,KviDccDescriptor> * KviDccDescriptor::descriptorDict()
+{
+ return g_pDescriptorDict;
+}
+
+/*
+KviDccDescriptor::KviDccDescriptor(const KviDccDescriptor & src)
+{
+ copyFrom(src);
+}
+*/
+
+KviDccDescriptor::KviDccDescriptor(KviConsole * pConsole)
+{
+ m_pConsole = pConsole;
+ m_pDccWindow = 0;
+ m_pDccTransfer = 0;
+
+ m_uId = g_uNextDescriptorId;
+ g_uNextDescriptorId++;
+
+ m_szId.setNum(m_uId);
+
+ if(!g_pDescriptorDict)
+ {
+ g_pDescriptorDict = new KviPointerHashTable<int,KviDccDescriptor>;
+ g_pDescriptorDict->setAutoDelete(false);
+ }
+ g_pDescriptorDict->replace((long)m_uId,this);
+
+ szNick = __tr_ctx("unknown","dcc");
+ szUser = szNick;
+ szHost = szNick;
+
+ szLocalNick = szNick;
+ szLocalUser = szNick;
+ szLocalHost = szNick;
+
+ szIp = szNick;
+ szPort = szNick;
+
+
+ bSendRequest = true;
+ bDoTimeout = true;
+ bIsTdcc = false;
+ bOverrideMinimize = false;
+ bShowMinimized = false;
+ bAutoAccept = false;
+#ifdef COMPILE_SSL_SUPPORT
+ bIsSSL = false;
+#endif
+ bRecvFile = false;
+ bResume = false;
+ bNoAcks = false;
+ bIsIncomingAvatar = false;
+
+ iSampleRate = 0;
+
+
+ m_bCreationEventTriggered = false;
+}
+
+KviDccDescriptor::~KviDccDescriptor()
+{
+ if(m_bCreationEventTriggered)
+ {
+ KviWindow * pEventWindow = m_pConsole;
+ if(!pEventWindow)pEventWindow = g_pApp->activeConsole(); // any console
+ else {
+ if(!(g_pApp->windowExists(pEventWindow)))pEventWindow = g_pApp->activeConsole();
+ }
+
+ if(pEventWindow)
+ {
+ // recheck it again...
+ if(g_pApp->windowExists(pEventWindow))
+ {
+ KVS_TRIGGER_EVENT_1(KviEvent_OnDCCSessionDestroyed,pEventWindow,m_szId);
+ }
+ }
+ }
+
+ if(g_pDescriptorDict)
+ {
+ g_pDescriptorDict->remove((long)m_uId);
+ if(g_pDescriptorDict->count() < 1)
+ {
+ delete g_pDescriptorDict;
+ g_pDescriptorDict = 0;
+ }
+ }
+
+}
+
+void KviDccDescriptor::triggerCreationEvent()
+{
+ if(m_bCreationEventTriggered)
+ {
+ debug("Ops.. trying to trigger OnDccSessionCreated twice");
+ return;
+ }
+ m_bCreationEventTriggered = true;
+ KviWindow * pEventWindow = m_pConsole;
+ if(!pEventWindow)pEventWindow = g_pApp->activeConsole(); // any console
+ if(pEventWindow)
+ {
+ KVS_TRIGGER_EVENT_1(KviEvent_OnDCCSessionCreated,pEventWindow,m_szId);
+ }
+}
+
+
+KviDccDescriptor * KviDccDescriptor::find(unsigned int uId)
+{
+ if(!g_pDescriptorDict)return 0;
+ return g_pDescriptorDict->find((long)uId);
+}
+
+/*
+void KviDccDescriptor::copyFrom(const KviDccDescriptor &src)
+{
+ m_pDccWindow = src.m_pDccWindow;
+ m_pDccTransfer = src.m_pDccTransfer;
+ m_uId = src.m_uId;
+ szType = src.szType;
+ szNick = src.szNick;
+ szUser = src.szUser;
+ szHost = src.szHost;
+ szLocalNick = src.szLocalNick;
+ szLocalUser = src.szLocalUser;
+ szLocalHost = src.szLocalHost;
+ szIp = src.szIp;
+ szPort = src.szPort;
+ m_pConsole = src.console();
+ m_szZeroPortRequestTag= src.zeroPortRequestTag();
+ bActive = src.bActive;
+ szListenIp = src.szListenIp;
+ szListenPort = src.szListenPort;
+ szFakeIp = src.szFakeIp;
+ szFakePort = src.szFakePort;
+ bSendRequest = src.bSendRequest;
+ bDoTimeout = src.bDoTimeout;
+ szFileName = src.szFileName;
+ szFileSize = src.szFileSize;
+ bResume = src.bResume;
+ bRecvFile = src.bRecvFile;
+ bNoAcks = src.bNoAcks;
+ bIsTdcc = src.bIsTdcc;
+ bOverrideMinimize = src.bOverrideMinimize;
+ bShowMinimized = src.bShowMinimized;
+ bAutoAccept = src.bAutoAccept;
+ bIsIncomingAvatar = src.bIsIncomingAvatar;
+#ifdef COMPILE_SSL_SUPPORT
+ bIsSSL = src.bIsSSL;
+#endif
+}
+*/
+
+bool KviDccDescriptor::isFileUpload()
+{
+ if(szType.upper()=="SEND")return true;
+ if(szType.upper()=="TSEND")return true;
+#ifdef COMPILE_SSL_SUPPORT
+ if(szType.upper()=="SSEND")return true;
+#endif
+ return false;
+}
+
+bool KviDccDescriptor::isFileDownload()
+{
+ if(szType.upper()=="RECV")return true;
+ if(szType.upper()=="TRECV")return true;
+#ifdef COMPILE_SSL_SUPPORT
+ if(szType.upper()=="SRECV")return true;
+#endif
+ return false;
+}
+
+bool KviDccDescriptor::isDccChat()
+{
+ if(szType.upper()=="CHAT")return true;
+#ifdef COMPILE_SSL_SUPPORT
+ if(szType.upper()=="SCHAT")return true;
+#endif
+ return false;
+}
diff --git a/src/modules/dcc/descriptor.h b/src/modules/dcc/descriptor.h
new file mode 100644
index 00000000..f3f6c3f3
--- /dev/null
+++ b/src/modules/dcc/descriptor.h
@@ -0,0 +1,163 @@
+#ifndef _DESCRIPTOR_H_
+#define _DESCRIPTOR_H_
+//=============================================================================
+//
+// File : src/modules/dcc/descriptor.h
+// Creation date : Tue Jul 23 01:11:52 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002-2004 Szymon Stefanek (oragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_string.h"
+#include "kvi_console.h"
+
+#include "kvi_pointerhashtable.h"
+
+
+class KviDccWindow;
+class KviDccFileTransfer;
+
+class KviDccDescriptor
+{
+public:
+ KviDccDescriptor(KviConsole * pConsole);
+ //KviDccDescriptor(const KviDccDescriptor & src);
+ ~KviDccDescriptor();
+protected:
+ KviConsole * m_pConsole;
+
+ // mIrc zero port reverse send/chat extension
+ KviStr m_szZeroPortRequestTag;
+
+ unsigned int m_uId; // this dcc session ID
+ QString m_szId;
+
+ KviDccWindow * m_pDccWindow; // 0 if it has no window
+ KviDccFileTransfer * m_pDccTransfer; // 0 if it is not a transfer
+
+ bool m_bCreationEventTriggered;
+public:
+ // A console that this DCC is bound to (might be replaced while we wait for user acknowledge in dialogs)
+ KviConsole * console() const { return m_pConsole; };
+ void setConsole(KviConsole * c){ m_pConsole = c; };
+
+ KviDccWindow * window() const { return m_pDccWindow; };
+ void setWindow(KviDccWindow * w){ m_pDccWindow = w; };
+
+ KviDccFileTransfer * transfer() const { return m_pDccTransfer; };
+ void setTransfer(KviDccFileTransfer * t){ m_pDccTransfer = t; };
+
+ // mIrc zero port reverse send/chat extension
+ bool isZeroPortRequest() const { return m_szZeroPortRequestTag.hasData(); };
+ const char * zeroPortRequestTag() const { return m_szZeroPortRequestTag.ptr(); };
+ void setZeroPortRequestTag(const KviStr &szTag){ m_szZeroPortRequestTag = szTag; };
+
+ unsigned int id() const { return m_uId; };
+ const QString & idString() const { return m_szId; };
+ static KviDccDescriptor * find(unsigned int uId);
+ static KviPointerHashTable<int,KviDccDescriptor> * descriptorDict();
+
+ void triggerCreationEvent(); // this MUST be called by the creator of the descriptor!
+//private:
+// void copyFrom(const KviDccDescriptor &src);
+public:
+ // Generic parameters
+ QString szType; // DCC protocol : CHAT , SCHAT , SEND , TSSEND....
+
+ bool bActive; // active or passive connection ?
+
+ QString szNick; // remote user nickname
+ QString szUser; // remote user name (unknown for passive dcc)
+ QString szHost; // remote user host (unknown for passive dcc)
+
+ QString szLocalNick; // local user nickname (always from irc)
+ QString szLocalUser; // local user username (always from irc)
+ QString szLocalHost; // local user hostname (always from irc)
+
+ QString szIp; // remote user ip (active dcc only)
+ QString szPort; // remote user port (active dcc only)
+
+ QString szListenIp; // passive only : ip to listen on
+ QString szListenPort; // passive only : port to listen on
+
+ bool bSendRequest; // passive only : true if we have to send the CTCP request
+
+ QString szFakeIp; // passive only : fake ip to send in the CTCP
+ QString szFakePort; // passive only : fake port to send in the CTCP
+
+ bool bDoTimeout; // the marshall has to setup a timeout ?
+
+ bool bIsTdcc; // is this a TDCC ?
+
+ bool bOverrideMinimize; // Override the default minimize option ?
+ bool bShowMinimized; // Show minimized ? (valid if bOverrideMinimize is true)
+
+ bool bAutoAccept; // Auto accepted dcc send/chat ?
+#ifdef COMPILE_SSL_SUPPORT
+ bool bIsSSL; // do we have to use SSL ?
+#endif
+ // Specific parameters
+
+ // DCC SEND/RECV
+
+ QString szFileName; // RECVFILE: incoming file name, SENDFILE: filename sent to the remote end
+ QString szFileSize; // RECVFILE: incoming file size, SENDFILE: remote resume size
+
+ QString szLocalFileName; // RECVFILE: save file name selected, SENDFILE: file to send
+ QString szLocalFileSize; // RECVFILE: local file size (to resume), SENDFILE: file to send size
+
+ bool bRecvFile; // do we have to RECEIVE the file or SEND it ?
+
+ bool bResume; // do we want to resume ?
+ bool bNoAcks; // blind dcc send ? (do not receive nor send acknowledges)
+
+ bool bIsIncomingAvatar; // It is an Incoming Avatar DCC SEND ?
+
+ // DCC VOICE
+
+ KviStr szCodec; // codec name
+ int iSampleRate; // Sample rate
+public:
+ // new interface... but should be converted to QString...
+ QString protocol(){ return szType; };
+ bool isActive(){ return bActive; };
+ QString remoteNick(){ return szNick; };
+ QString remoteUser(){ return szUser; };
+ QString remoteHost(){ return szHost; };
+ QString remoteIp(){ return szIp; };
+ QString remotePort(){ return szPort; };
+ QString remoteFileName(){ return szFileName; };
+ QString remoteFileSize(){ return szFileSize; };
+ QString localNick(){ return szLocalNick; };
+ QString localUser(){ return szLocalUser; };
+ QString localHost(){ return szLocalHost; };
+ QString localIp(){ return szIp; };
+ QString localPort(){ return szPort; };
+ QString localFileName(){ return szLocalFileName; };
+ QString localFileSize(){ return szLocalFileSize; };
+ bool isFileUpload();
+ bool isFileDownload();
+ bool isDccChat();
+ bool isFileTransfer(){ return (isFileUpload() || isFileDownload()); };
+};
+
+
+
+
+#endif //_DESCRIPTOR_H_
diff --git a/src/modules/dcc/dialogs.cpp b/src/modules/dcc/dialogs.cpp
new file mode 100644
index 00000000..0ec0afba
--- /dev/null
+++ b/src/modules/dcc/dialogs.cpp
@@ -0,0 +1,206 @@
+//
+// File : dialogs.cpp
+// Creation date : Tue Sep 19 09 2000 15:23:12 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+#include "dialogs.h"
+
+#include "kvi_locale.h"
+#include "kvi_iconmanager.h"
+#include "kvi_app.h"
+
+#include <qlayout.h>
+#include <qpushbutton.h>
+#include <qlabel.h>
+#include <qstringlist.h>
+#include <qevent.h>
+#include <qdesktopwidget.h>
+
+KviDccBox::KviDccBox(KviDccBroker * br,KviDccDescriptor * dcc)
+{
+ m_pDescriptor = dcc;
+ m_pBroker = br;
+}
+
+KviDccBox::~KviDccBox()
+{
+ if(m_pDescriptor)delete m_pDescriptor;
+ m_pDescriptor = 0;
+ m_pBroker->unregisterDccBox(this);
+}
+
+void KviDccBox::forgetDescriptor()
+{
+ m_pDescriptor = 0;
+}
+
+KviDccAcceptBox::KviDccAcceptBox(KviDccBroker * br,KviDccDescriptor * dcc,const QString &text,const QString &capt)
+: QWidget(0,"dcc_accept_box") , KviDccBox(br,dcc)
+{
+ QVBoxLayout * vb = new QVBoxLayout(this,4,4);
+ QLabel * l = new QLabel(text,this);
+#ifdef COMPILE_USE_QT4
+ l->setWordWrap(true);
+#endif
+ vb->addWidget(l);
+ QHBoxLayout *hb = new QHBoxLayout(4);
+ vb->addLayout(hb,Qt::AlignCenter);
+ QPushButton * btn = new QPushButton(__tr2qs_ctx("&Accept","dcc"),this);
+ btn->setDefault(true);
+ //btn->setFocus();
+ hb->addWidget(btn);
+ connect(btn,SIGNAL(clicked()),this,SLOT(acceptClicked()));
+ btn = new QPushButton(__tr2qs_ctx("&Reject","dcc"),this);
+ connect(btn,SIGNAL(clicked()),this,SLOT(rejectClicked()));
+ hb->addWidget(btn);
+
+ setIcon(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_DCCMSG)));
+ setCaption(capt);
+
+ l->setActiveWindow();
+ l->setFocus();
+}
+
+KviDccAcceptBox::~KviDccAcceptBox()
+{
+}
+
+void KviDccAcceptBox::acceptClicked()
+{
+ hide();
+ emit accepted(this,m_pDescriptor);
+ g_pApp->collectGarbage(this);
+}
+
+void KviDccAcceptBox::rejectClicked()
+{
+ hide();
+ emit rejected(this,m_pDescriptor);
+ g_pApp->collectGarbage(this);
+}
+
+void KviDccAcceptBox::closeEvent(QCloseEvent *e)
+{
+ hide();
+ e->ignore();
+ emit rejected(this,m_pDescriptor);
+ g_pApp->collectGarbage(this);
+}
+
+void KviDccAcceptBox::showEvent(QShowEvent *e)
+{
+ move((g_pApp->desktop()->width() - width()) >> 1,
+ (g_pApp->desktop()->height() - height()) >> 1);
+ QWidget::showEvent(e);
+}
+
+
+
+
+KviDccRenameBox::KviDccRenameBox(KviDccBroker * br,KviDccDescriptor * dcc,const QString &text,bool bDisableResume)
+: QWidget(0,"dcc_rename_box") , KviDccBox(br,dcc)
+{
+ QVBoxLayout * vb = new QVBoxLayout(this,4,4);
+ QLabel * l = new QLabel(text,this);
+#ifdef COMPILE_USE_QT4
+ l->setWordWrap(true);
+#endif
+ vb->addWidget(l);
+
+ QHBoxLayout *hb = new QHBoxLayout(4);
+ vb->addLayout(hb,Qt::AlignCenter);
+
+ QPushButton * btn = new QPushButton(__tr2qs_ctx("&Rename","dcc"),this);
+ hb->addWidget(btn);
+ connect(btn,SIGNAL(clicked()),this,SLOT(renameClicked()));
+
+ btn = new QPushButton(__tr2qs_ctx("Over&write","dcc"),this);
+ hb->addWidget(btn);
+ connect(btn,SIGNAL(clicked()),this,SLOT(overwriteClicked()));
+
+ btn = new QPushButton(__tr2qs_ctx("Re&sume","dcc"),this);
+ hb->addWidget(btn);
+ connect(btn,SIGNAL(clicked()),this,SLOT(resumeClicked()));
+ if(bDisableResume)btn->setEnabled(false);
+
+ btn = new QPushButton(__tr2qs_ctx("Cancel","dcc"),this);
+ hb->addWidget(btn);
+ connect(btn,SIGNAL(clicked()),this,SLOT(cancelClicked()));
+ btn->setDefault(true);
+ //btn->setFocus();
+
+ setIcon(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_DCCMSG)));
+ setCaption(__tr2qs_ctx("File Already Exists - KVIrc","dcc"));
+}
+
+KviDccRenameBox::~KviDccRenameBox()
+{
+}
+
+void KviDccRenameBox::closeEvent(QCloseEvent *e)
+{
+ hide();
+ e->ignore();
+ if(m_pDescriptor)
+ {
+ emit cancelSelected(this,m_pDescriptor);
+ g_pApp->collectGarbage(this);
+ }
+}
+
+void KviDccRenameBox::showEvent(QShowEvent *e)
+{
+ move((g_pApp->desktop()->width() - width()) >> 1,
+ (g_pApp->desktop()->height() - height()) >> 1);
+ QWidget::showEvent(e);
+}
+
+void KviDccRenameBox::renameClicked()
+{
+ hide();
+ emit renameSelected(this,m_pDescriptor);
+ g_pApp->collectGarbage(this);
+}
+
+void KviDccRenameBox::overwriteClicked()
+{
+ hide();
+ emit overwriteSelected(this,m_pDescriptor);
+ g_pApp->collectGarbage(this);
+}
+
+void KviDccRenameBox::resumeClicked()
+{
+ hide();
+ m_pDescriptor->bResume = true;
+ emit overwriteSelected(this,m_pDescriptor);
+ g_pApp->collectGarbage(this);
+}
+
+void KviDccRenameBox::cancelClicked()
+{
+ hide();
+ emit cancelSelected(this,m_pDescriptor);
+ g_pApp->collectGarbage(this);
+}
+
+
+
+
+#include "m_dialogs.moc"
diff --git a/src/modules/dcc/dialogs.h b/src/modules/dcc/dialogs.h
new file mode 100644
index 00000000..805c0147
--- /dev/null
+++ b/src/modules/dcc/dialogs.h
@@ -0,0 +1,82 @@
+#ifndef _DIALOGS_H_
+#define _DIALOGS_H_
+//
+// File : dialogs.h
+// Creation date : Tue Sep 19 09 2000 15:17:22 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+#include <qwidget.h>
+#include "kvi_filedialog.h"
+
+#include "broker.h"
+
+class KviDccBox
+{
+protected:
+ KviDccDescriptor * m_pDescriptor;
+ KviDccBroker * m_pBroker;
+public:
+ KviDccBox(KviDccBroker * br,KviDccDescriptor * dcc);
+ virtual ~KviDccBox();
+public:
+ virtual void forgetDescriptor();
+};
+
+
+
+class KviDccAcceptBox : public QWidget , public KviDccBox
+{
+ Q_OBJECT
+public:
+ KviDccAcceptBox(KviDccBroker * br,KviDccDescriptor * dcc,const QString &text,const QString &capt);
+ ~KviDccAcceptBox();
+protected:
+ virtual void closeEvent(QCloseEvent *e);
+ virtual void showEvent(QShowEvent *e);
+private slots:
+ void acceptClicked();
+ void rejectClicked();
+signals:
+ void accepted(KviDccBox *,KviDccDescriptor *);
+ void rejected(KviDccBox *,KviDccDescriptor *);
+};
+
+class KviDccRenameBox : public QWidget , public KviDccBox
+{
+ Q_OBJECT
+public:
+ KviDccRenameBox(KviDccBroker * br,KviDccDescriptor * dcc,const QString &text,bool bDisableResume);
+ ~KviDccRenameBox();
+protected:
+ virtual void closeEvent(QCloseEvent *e);
+ virtual void showEvent(QShowEvent *e);
+private slots:
+ void renameClicked();
+ void overwriteClicked();
+ void resumeClicked();
+ void cancelClicked();
+signals:
+ void overwriteSelected(KviDccBox *,KviDccDescriptor *);
+ void renameSelected(KviDccBox *,KviDccDescriptor *);
+ void cancelSelected(KviDccBox *,KviDccDescriptor *);
+};
+
+#endif
diff --git a/src/modules/dcc/gsmcodec.cpp b/src/modules/dcc/gsmcodec.cpp
new file mode 100644
index 00000000..58af1473
--- /dev/null
+++ b/src/modules/dcc/gsmcodec.cpp
@@ -0,0 +1,149 @@
+//
+// File : gsmcodec.cpp
+// Creation date : Wed Aug 22 19:12:55 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#define _GSMCODEC_CPP_
+
+#include "gsmcodec.h"
+
+#ifdef COMPILE_USE_GSM
+
+#include <dlfcn.h>
+
+#define GSM_PACKED_FRAME_SIZE_IN_BYTES 33
+#define GSM_UNPACKED_FRAME_SIZE_IN_BYTES 320
+#define GSM_UNPACKED_FRAME_SIZE_IN_SHORTS 160
+
+void * (*gsm_session_create)() = 0;
+void (*gsm_session_destroy)(void *) = 0;
+void (*gsm_session_encode)(void *,short *,unsigned char *) = 0;
+int (*gsm_session_decode)(void *,unsigned char *,short *) = 0;
+
+
+void * g_pGSMCodecLibraryHandle = 0;
+
+bool kvi_gsm_codec_init()
+{
+ if(g_pGSMCodecLibraryHandle)return true; // Already initialized
+
+ g_pGSMCodecLibraryHandle = dlopen("libgsm.so",RTLD_NOW | RTLD_GLOBAL);
+ if(!g_pGSMCodecLibraryHandle)return false; // no way to open it
+
+ gsm_session_create = (void * (*)()) dlsym(g_pGSMCodecLibraryHandle,"gsm_create");
+ gsm_session_destroy = (void (*)(void *)) dlsym(g_pGSMCodecLibraryHandle,"gsm_destroy");
+ gsm_session_encode = (void (*)(void *,short *,unsigned char *)) dlsym(g_pGSMCodecLibraryHandle,"gsm_encode");
+ gsm_session_decode = (int (*)(void *,unsigned char *,short *)) dlsym(g_pGSMCodecLibraryHandle,"gsm_decode");
+
+ if(! (gsm_session_create && gsm_session_destroy && gsm_session_encode && gsm_session_decode))
+ {
+ dlclose(g_pGSMCodecLibraryHandle);
+ g_pGSMCodecLibraryHandle = 0;
+ return false;
+ }
+ return true;
+}
+
+void kvi_gsm_codec_done()
+{
+ if(g_pGSMCodecLibraryHandle)
+ {
+ dlclose(g_pGSMCodecLibraryHandle);
+ g_pGSMCodecLibraryHandle = 0;
+ }
+}
+
+
+
+KviDccVoiceGsmCodec::KviDccVoiceGsmCodec()
+: KviDccVoiceCodec()
+{
+ m_pEncodeState = gsm_session_create();
+ m_pDecodeState = gsm_session_create();
+ m_szName = "gsm (compression 33:320)";
+}
+
+KviDccVoiceGsmCodec::~KviDccVoiceGsmCodec()
+{
+ gsm_session_destroy(m_pEncodeState);
+ gsm_session_destroy(m_pDecodeState);
+}
+
+void KviDccVoiceGsmCodec::encode(KviDataBuffer * signal,KviDataBuffer * stream)
+{
+ if(signal->size() < GSM_UNPACKED_FRAME_SIZE_IN_BYTES)return; // nothing to encode
+
+ unsigned char * ptr = signal->data();
+
+ int uFrames = signal->size() / GSM_UNPACKED_FRAME_SIZE_IN_BYTES;
+ int uTotalDataCompressed = uFrames * GSM_UNPACKED_FRAME_SIZE_IN_BYTES;
+ int uFrameOffset = stream->size();
+ unsigned char * endPtr = ptr + uTotalDataCompressed;
+
+ stream->addSize(GSM_PACKED_FRAME_SIZE_IN_BYTES * uFrames);
+
+ while(ptr != endPtr)
+ {
+ gsm_session_encode(m_pEncodeState,(short *)ptr,stream->data() + uFrameOffset);
+ ptr += GSM_UNPACKED_FRAME_SIZE_IN_BYTES;
+ uFrameOffset += GSM_PACKED_FRAME_SIZE_IN_BYTES;
+ }
+ signal->remove(uTotalDataCompressed);
+}
+
+void KviDccVoiceGsmCodec::decode(KviDataBuffer * stream,KviDataBuffer * signal)
+{
+ if(stream->size() < GSM_PACKED_FRAME_SIZE_IN_BYTES)return; // nothing to decode
+
+ unsigned char * ptr = stream->data();
+
+ // Gsm codec
+ int uFrames = stream->size() / GSM_PACKED_FRAME_SIZE_IN_BYTES;
+ int uTotalDataDecompressed = uFrames * GSM_PACKED_FRAME_SIZE_IN_BYTES;
+ int uSignalOffset = signal->size();
+ unsigned char * endPtr = ptr + (uTotalDataDecompressed);
+
+ signal->addSize(GSM_UNPACKED_FRAME_SIZE_IN_BYTES * uFrames);
+
+ while(ptr != endPtr)
+ {
+ // We don't check the return value here
+ // Well..it is either an unrecoverable internal error
+ // or a broken frame...
+ // but if we receive broken frames over DCC...well....better
+ // check the hardware...or the remote codec as well...
+ gsm_session_decode(m_pDecodeState,ptr,(short *)(signal->data() + uSignalOffset));
+ ptr += GSM_PACKED_FRAME_SIZE_IN_BYTES;
+ uSignalOffset += GSM_UNPACKED_FRAME_SIZE_IN_BYTES;
+ }
+ stream->remove(uTotalDataDecompressed);
+}
+
+int KviDccVoiceGsmCodec::encodedFrameSize()
+{
+ return GSM_PACKED_FRAME_SIZE_IN_BYTES;
+}
+
+int KviDccVoiceGsmCodec::decodedFrameSize()
+{
+ return GSM_UNPACKED_FRAME_SIZE_IN_BYTES;
+}
+
+#endif // COMPILE_USE_GSM
diff --git a/src/modules/dcc/gsmcodec.h b/src/modules/dcc/gsmcodec.h
new file mode 100644
index 00000000..a1de407b
--- /dev/null
+++ b/src/modules/dcc/gsmcodec.h
@@ -0,0 +1,54 @@
+#ifndef _GSMCODEC_H_
+#define _GSMCODEC_H_
+//
+// File : gsmcodec.h
+// Creation date : Wed Aug 22 19:12:54 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+
+
+#ifdef COMPILE_USE_GSM
+
+ #include "codec.h"
+
+ #ifndef _GSMCODEC_CPP_
+ extern bool kvi_gsm_codec_init();
+ extern void kvi_gsm_codec_done();
+ #endif //_GSMCODEC_CPP_
+
+ class KviDccVoiceGsmCodec : public KviDccVoiceCodec
+ {
+ public:
+ KviDccVoiceGsmCodec();
+ virtual ~KviDccVoiceGsmCodec();
+ private:
+ void * m_pEncodeState;
+ void * m_pDecodeState;
+ public:
+ virtual void encode(KviDataBuffer * signal,KviDataBuffer * stream);
+ virtual void decode(KviDataBuffer * stream,KviDataBuffer * signal);
+ virtual int encodedFrameSize();
+ virtual int decodedFrameSize();
+ };
+
+#endif //COMPILE_USE_GSM
+
+#endif //_GSMCODEC_H_
diff --git a/src/modules/dcc/kvi_dccfiletransfericons.png b/src/modules/dcc/kvi_dccfiletransfericons.png
new file mode 100644
index 00000000..11999a03
--- /dev/null
+++ b/src/modules/dcc/kvi_dccfiletransfericons.png
Binary files differ
diff --git a/src/modules/dcc/libkvidcc.cpp b/src/modules/dcc/libkvidcc.cpp
new file mode 100644
index 00000000..717f568d
--- /dev/null
+++ b/src/modules/dcc/libkvidcc.cpp
@@ -0,0 +1,2766 @@
+//=============================================================================
+//
+// File : libkviobjects.cpp
+// Creation date : Wed Sep 09 2000 20:59:01 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_debug.h"
+#include "kvi_settings.h"
+#include "kvi_string.h"
+#include "kvi_module.h"
+#include "kvi_sparser.h"
+#include "kvi_locale.h"
+#include "kvi_out.h"
+#include "kvi_console.h"
+#include "kvi_netutils.h"
+#include "kvi_frame.h"
+#include "kvi_console.h"
+#include "kvi_error.h"
+#include "kvi_options.h"
+#include "kvi_defaults.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_app.h"
+#include "kvi_ircconnection.h"
+#include "kvi_ircconnectionuserinfo.h"
+
+#include "gsmcodec.h"
+#include "broker.h"
+#include "voice.h"
+#include "utils.h"
+#include "send.h"
+#include "window.h"
+
+#include <qfileinfo.h>
+
+#ifdef COMPILE_ON_WINDOWS
+ // Ugly Windoze compiler...
+ #include "dialogs.h"
+#endif
+
+//#warning "KviOption_boolIgnoreDccChat and other types too"
+
+//extern KVIRC_API KviSharedFilesManager * g_pSharedFilesManager;
+
+KviDccBroker * g_pDccBroker = 0;
+
+
+static void dcc_module_set_dcc_type(KviDccDescriptor * d,const char * szBaseType)
+{
+ d->szType = szBaseType;
+#ifdef COMPILE_SSL_SUPPORT
+ if(d->bIsSSL)d->szType.prepend('S');
+#endif
+ if(d->bIsTdcc)d->szType.prepend('T');
+}
+
+static bool dcc_kvs_parse_default_parameters(KviDccDescriptor * d,KviKvsModuleCommandCall *c)
+{
+ d->bIsTdcc = c->switches()->find('t',"tdcc");
+
+ KviKvsVariant * pSw = c->switches()->find('m',"minimize");
+
+ if(pSw != 0)
+ d->bOverrideMinimize = pSw->asBoolean();
+ else
+ d->bOverrideMinimize = false;
+
+ if(!d->console())
+ {
+ // We don't need a console with -c and -n , otherwise we need it
+ if(!(c->switches()->find('c',"connect") || c->switches()->find('n',"no-ctcp")))
+ {
+ delete d;
+ c->error(__tr2qs_ctx("This window has no associated IRC context (an IRC context is required unless -c or -n are passed)","dcc"));
+ return false;
+ } else d->setConsole(c->window()->frame()->firstConsole());
+ }
+
+ __range_valid(d->console());
+
+ if(!d->console()->isConnected())
+ {
+ // We don't need a connection with -c and -n , otherwise we need it
+ if(!(c->switches()->find('c',"connect") || c->switches()->find('n',"no-ctcp")))
+ {
+ delete d;
+ c->error(__tr2qs_ctx("You're not connected to a server (an active connection is required unless -c or -n are passed)","dcc"));
+ return false;
+ } else {
+ // -c or -n , grab a local nick from somewhere
+ d->szLocalNick = KVI_OPTION_STRING(KviOption_stringNickname1);
+ d->szLocalNick.stripWhiteSpace();
+ if(d->szLocalNick.isEmpty())d->szLocalNick = KVI_DEFAULT_NICKNAME1;
+ d->szLocalUser = __tr2qs_ctx("unknown","dcc"); // we can live without it
+ d->szLocalHost = d->szLocalUser; // we can live without it
+ }
+ } else {
+ // We know everything
+ d->szLocalNick = d->console()->connection()->userInfo()->nickName();
+ d->szLocalUser = d->console()->connection()->userInfo()->userName();
+ d->szLocalHost = d->console()->connection()->userInfo()->hostName();
+ }
+
+ if(pSw = c->switches()->find('i',"ip"))
+ {
+ pSw->asString(d->szListenIp);
+ if(!(d->szListenIp.contains('.') || d->szListenIp.contains(':')))
+ {
+ // This will magically work with the same buffer as source and dst!
+ if(!KviNetUtils::getInterfaceAddress(d->szListenIp,d->szListenIp))
+ {
+ c->error(__tr2qs_ctx("Unable to get address of interface %Q","dcc"),&(d->szListenIp));
+ delete d;
+ return false;
+ }
+ }
+ } else {
+ QString tmp;
+ if(!dcc_kvs_get_listen_ip_address(c,d->console(),tmp))
+ {
+ delete d;
+ c->error(__tr2qs_ctx("No suitable interfaces to listen on, use -i","dcc"));
+ return false;
+ }
+ d->szListenIp=tmp;
+ }
+
+ if(pSw = c->switches()->find('p',"port"))
+ {
+ pSw->asString(d->szListenPort); // fixme!
+ }
+ else d->szListenPort = "0"; // any port is ok
+
+ if(pSw = c->switches()->find('a',"fake-address"))
+ {
+ pSw->asString(d->szFakeIp);
+ }
+ else {
+ if(KVI_OPTION_BOOL(KviOption_boolDccSendFakeAddressByDefault))
+ {
+ d->szFakeIp = KVI_OPTION_STRING(KviOption_stringDefaultDccFakeAddress);
+ if(d->szFakeIp.isEmpty())KVI_OPTION_BOOL(KviOption_boolDccSendFakeAddressByDefault) = false;
+ }
+ }
+
+ if(pSw = c->switches()->find('f',"fake-port"))
+ {
+ pSw->asString(d->szFakePort);
+ }
+
+ d->bDoTimeout = (!c->switches()->find('u',"unlimited"));
+#ifdef COMPILE_SSL_SUPPORT
+ d->bIsSSL = c->switches()->find('s',"ssl");
+#else
+ if(c->switches()->find('s',"ssl"))c->warning(__tr2qs_ctx("This executable was built without SSL support, -s switch ignored","dcc"));
+#endif
+
+ return true;
+}
+
+
+/*
+ @doc: dcc.chat
+ @type:
+ command
+ @title:
+ dcc.chat
+ @short:
+ Starts a DCC Chat connection
+ @syntax:
+ dcc.chat [-s] [-n] [-c] [-u] [-m[=<boolean>]] [-i=<interface>] [-p=<port>] [-a=<fake address>] [-f=<fake port>] <nickname>
+ @switches:
+ !sw: -m[=<boolean>] | --minimize[=<boolean>]
+ If the -m switch is passed, the default boolCreateMinimizedDccChat option
+ is overridden with the <boolean> parameter passed. So actually
+ by passing -m=1 will create a minimized DCC send even
+ if the [fnc]$option[/fnc](boolCreateMinimizedDccChat) returns false.[br]
+ In the same way, by passing -m=0 you will create a non minimized DCC send.
+ If no <boolean> value is specified, it defaults to 1.[br]
+
+ !sw: -n | --no-ctcp
+ Do NOT send the CTCP request to the target user, you will have to do it manually,
+ or the remote user will have to connect manually (for example by using dcc.chat -c).[br]
+
+ !sw: -c | --connect
+ Attempt to CONNECT to the remote host specified as <interface> and <port>,
+ instead of listening (active connection instead of a passive one).
+ In this case the -i and -p switches are mandatory.[br]
+ The 'c' switch takes precedence over 'n' (In fact both should
+ be mutually exclusive).[br]
+ If the 'c' and 'n' switches are missing, this commands
+ needs to be executed in a window that is bound to a connected
+ IRC context (you need a third entity to accomplish the negotiation).[br]
+
+ !sw: -i=<interface> | --ip=<interface>
+ Bind the local listening socket to the specified <interface> (which is an IP address, IPv4 or IPv6).
+ If this switch is NOT specified, the socket is bound to the interface of
+ the current IRC connection (if any) or to "127.0.0.1".[br]
+ You can also specify a local interface name to get the address from (this works only for IPv4 interfaces
+ since IPv6 ones seems to be unsupported by the system ioctl() calls at the moment (for linux at least)).[br]
+ Here go some examples:[br]
+ -i=215.243.12.12: this will bind to the IPv4 interface with the specified address.[br]
+ -i=3ffe:1001::1: this will bind to the IPv6 interface with the specified address.[br]
+ -i=ppp0: this will bind to the IPv4 address of the interface ppp0 (if supported by the underlying system).[br]
+ The -i switch parameter may serve also as a target address when the -c switch is used.[br]
+
+ !sw: -p=<port> | --port=<port>
+ Bind the local listening socket to the specified <port>.
+ If this switch is NOT specified, the port will be a "random" one choosen by the kernel.[br]
+
+ !sw: -a=<fake address> | --fake-address=<fake address>
+ Send the <fake address> as target for the remote client in the requesting CTCP message.
+ If this switch is not given, the CTCP will contain the real IP address of the listening
+ interface.[br]
+
+ !sw: -f=<fake port> | --fake-port=<fake port>
+ Send the <fake port> as target port for the remote client in the requesting CTCP message.
+ If this switch is not given, the CTCP will contain the real port of the listening socket.
+ [br][br]
+ All these switches are meant to allow maximum flexibility of the
+ DCC negotiation, earlier KVIrc releases had serious problems
+ with firewalled and/or masqueraded machines. With the -a and -f switches
+ you can work around it.[br]
+ [br]
+
+ !sw: -u | --unlimited
+ If the 'u' switch is given, the connection attempt will
+ never time out; this might be useful if you want to leave
+ a listening socket for a friend of yours while you are sleeping
+ and have the CTCP processing disabled. The 'u' switch works either
+ in active and passive mode.[br]
+
+ !sw: -s | --ssl
+ Use a Secure Socket Layer for the transfer; the whole communication will be encrypted
+ with a private key algorithm after a public key handshake.[br]
+ This option will work only if the KVIrc executable has been compiled with SSL support
+ and the remote end supports the SSL protocol too.[br]
+ Please note that this will may down the transfer somewhat.[br]
+ -s can be combined with -t.[br]
+ The CTCP negotiation will use SSEND as parameter (or eventually TSSEND).[br]
+ When requesting a SSL based DCC send to someone you probably will need a
+ certificate. If you don't have one, create it (for example with CA.pl -newcert)
+ and set it in the options dialog.
+
+ !sw: -z | --zero-port
+ Use the 0 port method. This is a dirty hack that allows you to use the CHAT
+ protocol with mIrc receiving clients.
+ @description:
+ Attempts a DCC connection to <nickname>.[br]
+ The simplest case "dcc.chat <nickname>" will work just as in all
+ the other IRC clients, but this command is really more powerful...[br]
+ Before attempting to understand the possibilities of this command,
+ be sure to know how [doc:dcc_connection]DCC negotiation and connections[/doc] work.
+ If the 'i' switch is specified, the local listening socket
+ will be bound to the specified <interface> (which is an IP address, IPv4 or IPv6),
+ otherwise it will be bound to the interface of the
+ current IRC connection.[br]
+ You can also specify a local interface name to get the address from (this works only for IPv4 interfaces
+ since IPv6 ones seem to be unsupported by the system ioctl() calls at the moment (in Linux at least)).[br]
+ Here are some examples:[br]
+ -i=215.243.12.12: This will bind to the IPv4 interface with the specified address.[br]
+ -i=3ffe:1001::1: This will bind to the IPv6 interface with the specified address.[br]
+ -i=ppp0: This will bind to the IPv4 address of the interface ppp0 (if supported by the underlying system).[br]
+ The -i switch parameter may serve also as a target address when the -c switch is used.[br]
+ If the 'p' switch is specified, the local listening socket
+ will be bound to the <port>, otherwise it will be bound to
+ a random port choosen by the kernel.[br]
+ If the 'a' switch is specified, the requesting CTCP message
+ will contain <fake address> as target for the remote user,
+ otherwise the CTCP message will contain the real IP address
+ of the listening interface.
+ If the 'f' switch is specified, the requesting CTCP message
+ will contain <fake port> as target for the remote user,
+ otherwise the CTCP message will contain the real port of the
+ listening socket.
+ All these switches are meant to allow maximum flexibility of the
+ DCC negotiation, earlier KVIrc releases had serious problems
+ with firewalled and/or masqueraded machines. With the -a and -f switches
+ you can workaround it.
+ If the 'n' switch is specified, KVIrc will NOT send the CTCP request
+ to the target user; you will have to do it manually, or the remote user
+ will have to connect manually (for example by using dcc.chat -c).
+ If the 'c' switch is specified, KVIrc will attempt to connect
+ to the remote host specified as <interface> and <port>, instead
+ of listening (active connection instead of a passive one).
+ In this case the -i and -p switches are mandatory.[br]
+ The 'c' switch takes precedence over 'n' (In fact both should
+ be mutually exclusive).[br]
+ If the 'c' and 'n' switches are missing, this commands
+ needs to be executed in a window that is bound to a connected
+ IRC context (you need a third entity to accomplish the negotiation).[br]
+ If the 'u' switch is given, the connection attempt will
+ never time out; this might be useful if you want to leave
+ a listening socket for a friend of yours while you are sleeping
+ and have the CTCP processing disabled. The 'u' switch works either
+ in active and passive mode.[br]
+ If the -m switch is passed, the default boolCreateMinimizedDccChat option
+ is overridden with the <boolean> parameter passed. So actually
+ by passing -m=1 will create a minimized DCC chat even
+ if the [fnc]$option[/fnc](boolCreateMinimizedDccChat) returns false.[br]
+ In the same way, by passing -m=0 you will create a non minimized DCC chat.
+ If no <boolean> value is specified, it defaults to 1.[br]
+ -s will cause the DCC chat to be attempted in Secure Sockets Layer mode:
+ the connection will be encrypted with a private key algorithm after a
+ public key handshake. -s will work only if the KVIrc executable was compiled
+ with SSL support enabled and if the remote end supports it.
+ The eventual DCC request will contain the string SCHAT instead of CHAT.[br]
+ When requesting a SSL based DCC chat to someone you probably will need a
+ certificate. If you don't have one, create it (for example with CA.pl -newcert)
+ and set it in the options dialog.
+ @examples:
+ Simple examples:
+ [example]
+ # Simple DCC chat to Pragma
+ dcc.chat Pragma
+ # DCC chat to Pragma, listen on address 127.0.0.1
+ dcc.chat -i=127.0.0.1 Pragma
+ # DCC chat to Pragma, listen on address 168.0.0.1 and port 1025
+ dcc.chat -i=168.0.0.1 -p=1025 Pragma
+ [/example]
+ More tricky ones:
+ [example]
+ # DCC chat to Pragma, listen on address 127.0.0.1 and port 1080
+ # but tell him to connect to address 212.134.22.11 port 1080
+ dcc.chat -i=127.0.0.1 -p=1080 -a=212.134.22.11 Pragma
+ # DCC chat to Pragma, listen on address 127.0.0.1 and port 1080
+ # but tell him to connect to address 212.134.22.11 port 1090
+ dcc.chat -i=127.0.0.1 -p=1080 -a=212.134.22.11 -f=1090 Pragma
+ [/example]
+ Now run completely out of bounds. Use dcc.chat connections
+ to do various things:
+ [example]
+ # Tricky: simulate a HTTP server
+ dcc.chat -n -i=127.0.0.1 -p=80 Netscape
+ # Now open http://127.0.0.1 with netscape
+ # and type "<html><body>Hello!</body></html>" :)
+ #
+ # Tricky 2: simulate the ident daemon (if you have none)
+ dcc.chat -n -i=127.0.0.1 -p=113 Client
+ #
+ # Now a self-DCC connection without the IRC negotiation
+ # Src: Setup a listening socket awaiting the "Destination" user connection
+ dcc.chat -n -i=127.0.0.1 -p=1080 Dst
+ # Dst: Connect to the listening socket at addr 127.0.0.1 and port 1080
+ dcc.chat -c -i=127.0.0.1 -p=1080 Src
+ # The above example will mess you a bit...
+ # Try to guess why in both windows YOU have the same nickname
+ # that is probably not Dst nor Src... :)
+ [/example]
+ Using the shell ftp proggie is too easy:
+ we're [b]real hackers[/b] and want to do complicated things...
+ [example]
+ # Connect to the local ftp server and get the list of contents
+ /dcc.chat -c -i=127.0.0.1 -p=21 FtpServer
+ # Now login, type in the new window (the following lines are NOT commands):
+ USER youruser
+ PASS yourpass
+ # Now enter passive mode
+ PASV
+ # And watch the line that you have received...sth like
+ # 227 Entering passive mode (127,0,0,1,210,195)
+ /dcc.chat -c -i=127.0.0.1 -p=$((210 * 256) + 195) FtpList
+ # (Change the port numbers accordingly)
+ # And then type in the FtpServer window (this is NOT a KVIrc command):
+ LIST
+ # Then watch the ls output in the FtpList window. :)
+ # In this way you can also read ascii files by ftp:
+ # Assume that in the previous ls output you have seen
+ # a README file.
+ # In the FtpServer window type:
+ PASV
+ # Watch the message
+ # 227 Entering passive mode (127,0,0,1,22,227)
+ /dcc.chat -c -i=127.0.0.1 -p=$((22 * 256) + 227) README
+ # In the FtpServer window type:
+ RETR README
+ # And read the file in the README window :)
+ [/example]
+*/
+
+static bool dcc_kvs_cmd_chat(KviKvsModuleCommandCall * c)
+{
+ QString szTarget;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("target",KVS_PT_NONEMPTYSTRING,0,szTarget)
+ KVSM_PARAMETERS_END(c)
+
+ KviDccDescriptor * d = new KviDccDescriptor(c->window()->console());
+
+ d->szNick = szTarget; // we always specify the nickname
+ d->szUser = __tr2qs_ctx("unknown","dcc"); // username is always unknown
+ d->szHost = d->szUser; // host is always unknown
+
+ if(!dcc_kvs_parse_default_parameters(d,c))return false;
+ dcc_module_set_dcc_type(d,"CHAT");
+
+ if(c->switches()->find('z',"zero-port"))
+ {
+ // we want to have it reversed... add a tag and send out the request
+ KviDccZeroPortTag * t = g_pDccBroker->addZeroPortTag();
+
+ d->console()->connection()->sendFmtData("PRIVMSG %s :%cDCC %s chat 127.0.0.1 0 %s%c",
+ d->console()->connection()->encodeText(d->szNick).data(),
+ 0x01,
+ d->console()->connection()->encodeText(d->szType).data(),
+ d->console()->connection()->encodeText(t->m_szTag).data(),
+ 0x01);
+
+ return true;
+ }
+
+ if(c->switches()->find('c',"connect"))
+ {
+ if(!(c->switches()->find('i',"ip") && c->switches()->find('p',"port")))
+ {
+ delete d;
+ c->error(__tr2qs_ctx("-c requires -i and -p","dcc"));
+ return false;
+ }
+ d->szIp = d->szListenIp;
+ d->szPort = d->szListenPort;
+ d->szListenIp = ""; // useless
+ d->szListenPort = ""; // useless
+ d->bActive = true;
+ } else {
+ d->szIp = __tr2qs_ctx("unknown","dcc");
+ d->szPort = d->szIp;
+ d->bActive = false;
+ d->bSendRequest = !c->switches()->find('n',"no-ctcp");
+ }
+
+ //c->window()->output(0,"%Q %Q %Q",&(d->szIp),&(d->szPort),&(d->szListenIp));
+ d->triggerCreationEvent();
+ g_pDccBroker->executeChat(0,d);
+
+ return true;
+}
+
+
+/*
+ @doc: dcc.send
+ @type:
+ command
+ @title:
+ dcc.send
+ @short:
+ Sends a file
+ @syntax:
+ dcc.send [-s] [-n] [-c] [-u] [-b] [-g[=<file size>]] [-t] [-m[=<boolean>]] [-i=<interface>] [-p=<port>] [-a=<fake address>] [-f=<fake port>] <nickname> [filename]
+ @switches:
+ !sw: -g[=<file size>] | --get[=<file size>]
+ This switch is a dirty trick, you can use it to receive files from people
+ behind a firewall with masquerading enabled.[br]
+ It causes the transfer direction to be inverted; your client will receive
+ the file from the remote host instead of sending it.[br]
+ <file size> is the expected file size in bytes. This parameter can be omitted,
+ and in this case the DCC will "blindly" trust the remote end and assume
+ that the file has been transferred correctly when the remote end closes the connection.[br]
+ If you don't pass the -n option, the remote end will receive an informational DCC RECV request,
+ specifying the IP address and the port to connect to.[br]
+ -t can be used to prevent sending acknowledges to the remote end, and -u can be used
+ to avoid the listening socket to timeout.[br]
+ -a and -f can be used as well, but I see no real reason for that...[br]
+ Here is an example of usage of this option:[br]
+ spion can't accept connections (is behind a firewall with masquerading or some other reason...),
+ to his machine.[br]
+ spion wants to send the file important.jpg to Pragma.[br]
+ spion tells to Pragma that he wants to send him the file and Pragma sets up a connection in the following way:[br]
+ [b]dcc.send -g spion important.png[/b][br]
+ spion will see the informational DCC RECV request with the IP address and port that Pragma is listening on.
+ Assume that the address was 212.212.231.220 and the port 32344.[br]
+ spion will then use the following command:[br]
+ [b]dcc.send -c -i=212.212.231.220 -p=32344 Pragma /home/spion/important.jpg[/b][br]
+ Et voila!..the file is transferring.[br]
+ Pragma will see no file progress indication, since the file size is unknown on Pragma's side.[br]
+ If spion had specified the file size, Pragma could use -g=<file size> while setting up the connection,
+ to be able to see the progress indications.[br]
+ If Pragma used the the -n option, the DCC RECV indication wouldn't have been sent, in this case
+ Pragma would need to communicate the Ip address and the port "manually" to spion.[br]
+
+ !sw: -b | --blind
+ Assume that no acknowledges are sent.
+ Assume that the transfer was successful when the whole file has been sent,
+ then close the socket.[br]
+ This is called a "blind" DCC send.[br]
+
+ !sw: -t | -tdcc
+ Emulate the TDCC protocol: Use the TDCC CTCP message (DCC TSEND) for requesting the connection
+ and assume that no acknowledges are sent. Wait for the remote end to close the connection.[br]
+
+ !sw: -m[=<boolean>] | --minimize[=<boolean>]
+ If the -m switch is passed, the default boolCreateMinimizedDccSend option
+ is overridden with the <boolean> parameter passed. So actually
+ by passing -m=1 will create a minimized DCC send even
+ if the [fnc]$option[/fnc](boolCreateMinimizedDccSend) returns false.[br]
+ In the same way, by passing -m=0 you will create a non minimized DCC send.
+ If no <boolean> value is specified, it defaults to 1.[br]
+
+ !sw: -n | --no-ctcp
+ Do NOT send the CTCP request to the target user, you will have to do it manually,
+ or the remote user will have to connect manually (for example by using dcc.recv -c).[br]
+
+ !sw: -c | --connect
+ Attempt to CONNECT to the remote host specified as <interface> and <port>,
+ instead of listening (active connection instead of a passive one).
+ In this case the -i and -p switches are mandatory.[br]
+ The 'c' switch takes precedence over 'n' (In fact both should
+ be mutually exclusive).[br]
+ If the 'c' and 'n' switches are missing, this commands
+ needs to be executed in a window that is bound to a connected
+ IRC context (you need a third entity to accomplish the negotiation).[br]
+
+ !sw: -i=<interface> | --ip=<interface>
+ Bind the local listening socket to the specified <interface> (which is an IP address, IPv4 or IPv6).
+ If this switch is NOT specified, the socket is bound to the interface of
+ the current IRC connection (if any) or to "127.0.0.1".[br]
+ You can also specify a local interface name to get the address from (this works only for IPv4 interfaces
+ since IPv6 ones seems to be unsupported by the system ioctl() calls at the moment (for linux at least)).[br]
+ Here go some examples:[br]
+ -i=215.243.12.12: this will bind to the IPv4 interface with the specified address.[br]
+ -i=3ffe:1001::1: this will bind to the IPv6 interface with the specified address.[br]
+ -i=ppp0: this will bind to the IPv4 address of the interface ppp0 (if supported by the underlying system).[br]
+ The -i switch parameter may serve also as a target address when the -c switch is used.[br]
+
+ !sw: -p=<port> | --port=<port>
+ Bind the local listening socket to the specified <port>.
+ If this switch is NOT specified, the port will be a "random" one choosen by the kernel.[br]
+
+ !sw: -a=<fake address> | --fake-address=<fake address>
+ Send the <fake address> as target for the remote client in the requesting CTCP message.
+ If this switch is not given, the CTCP will contain the real IP address of the listening
+ interface.[br]
+
+ !sw: -f=<fake port> | --fake-port=<fake port>
+ Send the <fake port> as target port for the remote client in the requesting CTCP message.
+ If this switch is not given, the CTCP will contain the real port of the listening socket.
+ [br][br]
+ All these switches are meant to allow maximum flexibility of the
+ DCC negotiation, earlier KVIrc releases had serious problems
+ with firewalled and/or masqueraded machines. With the -a and -f switches
+ you can work around it.[br]
+ [br]
+
+ !sw: -u | --unlimited
+ If the 'u' switch is given, the connection attempt will
+ never time out; this might be useful if you want to leave
+ a listening socket for a friend of yours while you are sleeping
+ and have the CTCP processing disabled. The 'u' switch works either
+ in active and passive mode.[br]
+
+ !sw: -s | --ssl
+ Use a Secure Socket Layer for the transfer; the whole communication will be encrypted
+ with a private key algorithm after a public key handshake.[br]
+ This option will work only if the KVIrc executable has been compiled with SSL support
+ and the remote end supports the SSL protocol too.[br]
+ Please note that this will may down the transfer somewhat.[br]
+ -s can be combined with -t.[br]
+ The CTCP negotiation will use SSEND as parameter (or eventually TSSEND).[br]
+ When requesting a SSL based DCC send to someone you probably will need a
+ certificate. If you don't have one, create it (for example with CA.pl -newcert)
+ and set it in the options dialog.
+
+ @description:
+ Attempts to send the file <filename> to <nickname>.[br]
+ If [filename] is specified it must be an absolute file path,
+ otherwise a file selection dialog is opened.[br]
+ The simplest case "dcc.send <nickname> <filename>" will work just as in all
+ the other IRC clients, but this command is really more powerful...[br]
+ Before attempting to understand the possibilities of this command,
+ be sure to know how a [doc:dcc_connection]DCC negotiation and connection[/doc] works.[br]
+ The file will be sent as a sequence of packets which must
+ be acknowledged one by one by the active client.[br]
+ There is a special option (see $option()) called "fast send" (also known
+ as "send ahead") that makes KVIrc avoid to wait for the acknowledge
+ of the last packet before sending the next one.[br]
+ Anyway, the connection is declared as successful only
+ when the whole file (all the packets) has been acknowledged.[br]
+ If you need to send a file but you're firewalled, you might take
+ a look at the [cmd]dcc.rsend[/cmd] command. It also handles
+ the mIrc zero port protocol extension.
+ @examples:
+
+*/
+
+//#warning "Example for -r"
+//#warning "OPTION FOR NO GUI ? (this is hard...)"
+//#warning "When in IPv6 mode, should be able to use the IPv4 binding!"
+
+static bool dcc_kvs_cmd_send(KviKvsModuleCommandCall * c)
+{
+ QString szTarget,szFileName;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("target",KVS_PT_NONEMPTYSTRING,0,szTarget)
+ KVSM_PARAMETER("file name",KVS_PT_NONEMPTYSTRING,KVS_PF_OPTIONAL,szFileName)
+ KVSM_PARAMETERS_END(c)
+
+ KviDccDescriptor * d = new KviDccDescriptor(c->window()->console());
+
+ d->szNick = szTarget; // we always specify the nickname
+
+ QString szTmp;
+ KviKvsVariant * pSw = 0;
+
+ if(pSw = c->switches()->find('g',"get"))
+ {
+ d->szFileName = QFileInfo(szFileName).fileName();
+
+ if(!pSw->isBoolean())
+ {
+ kvs_int_t iSize;
+ if(pSw->asInteger(iSize)) // is an integer
+ {
+ pSw->asString(szTmp);
+ // avoid sprintf as long as possibile
+ d->szFileSize = szTmp;
+ } else {
+ d->szFileSize = __tr_ctx("<unknown size>","dcc");
+ }
+ }
+ } else {
+ d->szFileName = szFileName;
+ d->szLocalFileName = szFileName;
+ }
+
+ d->szUser = __tr2qs_ctx("unknown","dcc"); // username is always unknown
+ d->szHost = d->szUser; // host is always unknown
+ d->bRecvFile = pSw != 0;
+ d->bNoAcks = c->switches()->find('b',"blind") || c->switches()->find('t',"tdcc");
+ d->bResume = false;
+ d->bAutoAccept = pSw != 0;
+ d->bIsIncomingAvatar = false;
+
+ if(!dcc_kvs_parse_default_parameters(d,c))return false;
+
+ if(c->switches()->find('c',"connect"))
+ {
+ if(!(c->switches()->find('i',"ip") && c->switches()->find('p',"port")))
+ {
+ delete d;
+ c->error(__tr2qs_ctx("-c requires -i and -p","dcc"));
+ return false;
+ }
+ d->szIp = d->szListenIp;
+ d->szPort = d->szListenPort;
+ d->szListenIp = ""; // useless
+ d->szListenPort = ""; // useless
+ d->bActive = true;
+ } else {
+ d->szIp = __tr2qs_ctx("unknown","dcc");
+ d->szPort = d->szIp;
+ d->bActive = false;
+ d->bSendRequest = !c->switches()->find('n',"no-ctcp");
+ }
+
+ if(c->switches()->find('g',"get"))
+ {
+ dcc_module_set_dcc_type(d,"RECV");
+ d->triggerCreationEvent();
+ g_pDccBroker->recvFileManage(d);
+ } else {
+ dcc_module_set_dcc_type(d,"SEND");
+ d->triggerCreationEvent();
+ if(!d->szLocalFileName.isEmpty())
+ {
+ g_pDccBroker->sendFileExecute(0,d);
+ } else {
+ g_pDccBroker->sendFileManage(d);
+ }
+ }
+
+ return true;
+}
+
+/*
+ @doc: dcc.recv
+ @type:
+ command
+ @title:
+ dcc.recv
+ @short:
+ Sets up a file receiving connection
+ @syntax:
+ dcc.recv [-s] [-t] [-u] [-b] [-n] [-c] [-i=<interface>] [-p=<port>] [-m[=<boolean>]] <nickname> <filename> <remote file size>
+ @switches:
+ !sw: -b | --blind
+ Assume that no acknowledges are sent.
+ Assume that the transfer was successful when the whole file has been sent,
+ then close the socket.[br]
+ This is called a "blind" DCC send.[br]
+
+ !sw: -t | -tdcc
+ Emulate the TDCC protocol: Use the TDCC CTCP message (DCC TSEND) for requesting the connection
+ and assume that no acknowledges are sent. Wait for the remote end to close the connection.[br]
+
+ !sw: -m[=<boolean>] | --minimize[=<boolean>]
+ If the -m switch is passed, the default boolCreateMinimizedDccSend option
+ is overridden with the <boolean> parameter passed. So actually
+ by passing -m=1 will create a minimized DCC send even
+ if the [fnc]$option[/fnc](boolCreateMinimizedDccSend) returns false.[br]
+ In the same way, by passing -m=0 you will create a non minimized DCC send.
+ If no <boolean> value is specified, it defaults to 1.[br]
+
+ !sw: -n | --no-ctcp
+ Do NOT send the CTCP request to the target user, you will have to do it manually,
+ or the remote user will have to connect manually (for example by using dcc.recv -c).[br]
+
+ !sw: -i=<interface> | --ip=<interface>
+ Bind the local listening socket to the specified <interface> (which is an IP address, IPv4 or IPv6).
+ If this switch is NOT specified, the socket is bound to the interface of
+ the current IRC connection (if any) or to "127.0.0.1".[br]
+ You can also specify a local interface name to get the address from (this works only for IPv4 interfaces
+ since IPv6 ones seems to be unsupported by the system ioctl() calls at the moment (for linux at least)).[br]
+ Here go some examples:[br]
+ -i=215.243.12.12: this will bind to the IPv4 interface with the specified address.[br]
+ -i=3ffe:1001::1: this will bind to the IPv6 interface with the specified address.[br]
+ -i=ppp0: this will bind to the IPv4 address of the interface ppp0 (if supported by the underlying system).[br]
+ The -i switch parameter may serve also as a target address when the -c switch is used.[br]
+
+ !sw: -p=<port> | --port=<port>
+ Bind the local listening socket to the specified <port>.
+ If this switch is NOT specified, the port will be a "random" one choosen by the kernel.[br]
+
+ !sw: -a=<fake address> | --fake-address=<fake address>
+ Send the <fake address> as target for the remote client in the requesting CTCP message.
+ If this switch is not given, the CTCP will contain the real IP address of the listening
+ interface.[br]
+
+ !sw: -f=<fake port> | --fake-port=<fake port>
+ Send the <fake port> as target port for the remote client in the requesting CTCP message.
+ If this switch is not given, the CTCP will contain the real port of the listening socket.
+ [br][br]
+ All these switches are meant to allow maximum flexibility of the
+ DCC negotiation, earlier KVIrc releases had serious problems
+ with firewalled and/or masqueraded machines. With the -a and -f switches
+ you can work around it.[br]
+ [br]
+
+ !sw: -u | --unlimited
+ If the 'u' switch is given, the connection attempt will
+ never time out; this might be useful if you want to leave
+ a listening socket for a friend of yours while you are sleeping
+ and have the CTCP processing disabled. The 'u' switch works either
+ in active and passive mode.[br]
+
+ !sw: -s | --ssl
+ Use a Secure Socket Layer for the transfer; the whole communication will be encrypted
+ with a private key algorithm after a public key handshake.[br]
+ This option will work only if the KVIrc executable has been compiled with SSL support
+ and the remote end supports the SSL protocol too.[br]
+ Please note that this will may down the transfer somewhat.[br]
+ -s can be combined with -t.[br]
+ The CTCP negotiation will use SSEND as parameter (or eventually TSSEND).[br]
+ When requesting a SSL based DCC send to someone you probably will need a
+ certificate. If you don't have one, create it (for example with CA.pl -newcert)
+ and set it in the options dialog.
+
+ !sw: -c | --connect
+ Accepted for compatibility: don't use it!
+ @description:
+ Sets up a connection ready to receive a file.[br]
+ In most 'common' cases you will not need this command, you might want to use [cmd]dcc.get[/cmd] instead.[br]
+ This works like dcc.send but has two main differences: The file is INCOMING, and the CTCP sent to the other side
+ is a CTCP RECV.[br]
+ This command is the counterpart of [cmd]dcc.send[/cmd] and its parameters are exactly the same, so please refer to that
+ help page for the full discussion. This help page contains only a brief resume of these parameters.[br]
+ The [doc:dcc_connection]dcc documentation[/doc] explains the DCC Recv subprotocol in detail.[br]
+ @examples:
+
+*/
+
+//#warning "ENCODE THE CTCP'S!!!!!!!"
+//#warning "DOCS FOR dcc.recv (examples!)"
+
+static bool dcc_kvs_cmd_recv(KviKvsModuleCommandCall * c)
+{
+ QString szTarget,szFileName;
+ kvs_uint_t uSize;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("target",KVS_PT_NONEMPTYSTRING,0,szTarget)
+ KVSM_PARAMETER("filename",KVS_PT_NONEMPTYSTRING,0,szFileName)
+ KVSM_PARAMETER("size",KVS_PT_UINT,0,uSize)
+ KVSM_PARAMETERS_END(c)
+
+ KviDccDescriptor * d = new KviDccDescriptor(c->window()->console());
+ d->szNick = szTarget;
+ d->szUser = __tr2qs_ctx("unknown","dcc");
+ d->szHost = d->szUser;
+ d->szIp = __tr2qs_ctx("unknown","dcc");
+ d->szPort = d->szIp;
+
+ // -c is senseless here...but we accept it for compatibility
+
+ if(!dcc_kvs_parse_default_parameters(d,c))return false;
+
+ d->szFileName = szFileName;
+ d->szFileSize.setNum(uSize);
+
+ d->bActive = false; // we have to listen!
+ d->bResume = false;
+ d->bRecvFile = true; // we have to receive the file!
+ d->bSendRequest = !c->switches()->find('n',"no-ctcp");
+ d->bNoAcks = d->bIsTdcc || c->switches()->find('b',"blind");
+ d->bAutoAccept = KVI_OPTION_BOOL(KviOption_boolAutoAcceptDccSend);
+ d->bIsIncomingAvatar = g_pApp->findPendingAvatarChange(d->console(),d->szNick,d->szFileName);
+
+ if(KVI_OPTION_BOOL(KviOption_boolAutoAcceptIncomingAvatars))d->bAutoAccept = d->bAutoAccept || d->bIsIncomingAvatar;
+ dcc_module_set_dcc_type(d,"RECV");
+ d->triggerCreationEvent();
+ g_pDccBroker->recvFileManage(d);
+
+ return true;
+}
+
+/*
+ @doc: dcc.rsend
+ @type:
+ command
+ @title:
+ dcc.rsend
+ @short:
+ Sends a file by using the Reverse DCC Send protocol
+ @syntax:
+ dcc.rsend [-s] [-t] <nickname> [filename]
+ @switches:
+ !sw: -t | -tdcc
+ Emulate the TDCC protocol.
+
+ !sw: -s | --ssl
+ Use a Secure Socket Layer for the transfer; the whole communication will be encrypted
+ with a private key algorithm after a public key handshake.[br]
+ This option will work only if the KVIrc executable has been compiled with SSL support
+ and the remote end supports the SSL protocol too.[br]
+ Please note that this will may down the transfer somewhat.[br]
+ -s can be combined with -t.[br]
+ The CTCP negotiation will use SSEND as parameter (or eventually TSSEND).[br]
+ When requesting a SSL based DCC send to someone you probably will need a
+ certificate. If you don't have one, create it (for example with CA.pl -newcert)
+ and set it in the options dialog.
+ !sw: -z | --zero-port
+ Use the 0 port method. This is a dirty hack that allows you to use the RSEND
+ protocol with mIrc receiving clients.
+ @description:
+ Sends a DCC RSEND request to <nickname> notifying him that you want to
+ send him the file [filename].[br]
+ The remote end may acknowledge the request by sending a DCC RECV request.
+ This command effects are similar to [cmd]dcc.send[/cmd], but will work also on machines
+ that can't accept incoming connections (firewalling or masquerading problems).[br]
+ A 120 seconds file offer is added for the specified file and mask "<nickname>!*@*".
+ @examples:
+
+*/
+
+//#warning "ENCODE THE CTCP'S!!!!!!!"
+//#warning "DOCS FOR dcc.rsend"
+
+static bool dcc_kvs_cmd_rsend(KviKvsModuleCommandCall * c)
+{
+ QString szTarget,szFileName;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("target",KVS_PT_NONEMPTYSTRING,0,szTarget)
+ KVSM_PARAMETER("filename",KVS_PT_NONEMPTYSTRING,KVS_PF_OPTIONAL,szFileName)
+ KVSM_PARAMETERS_END(c)
+
+ KVSM_REQUIRE_CONNECTION(c)
+
+ KviDccDescriptor * d = new KviDccDescriptor(c->window()->console());
+ d->szNick = szTarget;
+ d->szLocalFileName = szFileName;
+ d->bIsTdcc = c->switches()->find('t',"tdcc");
+#ifdef COMPILE_SSL_SUPPORT
+ d->bIsSSL = c->switches()->find('s',"ssl");
+#else
+ if(c->switches()->find('s',"ssl"))c->warning(__tr2qs_ctx("This executable has been built without SSL support, -s switch ignored","dcc"));
+#endif //!COMPILE_SSL_SUPPORT
+
+ if(c->switches()->find('z',"zero-port"))
+ {
+ dcc_module_set_dcc_type(d,"SEND");
+ d->setZeroPortRequestTag("nonempty"); // just to tag it
+ } else
+ dcc_module_set_dcc_type(d,"RSEND");
+ d->triggerCreationEvent();
+ g_pDccBroker->rsendManage(d);
+
+ return true;
+}
+
+
+
+
+/*
+ @doc: dcc.get
+ @type:
+ command
+ @title:
+ dcc.get
+ @short:
+ Requests a file
+ @syntax:
+ dcc.get [-s] [-t] <nickname> <filename> [filesize]
+ @description:
+ Sends a CTCP DCC GET to <nickname> requesting the file <filename>.
+ The remote end should reply with a DCC SEND request CTCP.
+ <filename> must not contain any leading path.
+ If the -t switch is given, the message is a DCC TGET, expecting
+ a TSEND reply.[br]
+ If the -s switch is given, the message will be a DCC SGET, expecting
+ a SSEND reply.[br]
+ -t and -s can be combined together to obtain a "turbo"+"SSL" extension transfer.[br]
+ -s will work only if the KVIrc executable has been compiled with SSL support and
+ the remote client supports it.[br]
+ @examples:
+
+*/
+
+//#warning "ENCODE THE CTCP'S!!!!!!!"
+//#warning "DOCS FOR dcc.get"
+
+static bool dcc_kvs_cmd_get(KviKvsModuleCommandCall * c)
+{
+ QString szTarget,szFileName;
+ kvs_uint_t uSize;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("target",KVS_PT_NONEMPTYSTRING,0,szTarget)
+ KVSM_PARAMETER("filename",KVS_PT_NONEMPTYSTRING,0,szFileName)
+ KVSM_PARAMETER("size",KVS_PT_UINT,KVS_PF_OPTIONAL,uSize)
+ KVSM_PARAMETERS_END(c)
+
+ KVSM_REQUIRE_CONNECTION(c)
+
+ KviQString::cutToLast(szFileName,'/');
+
+ if(szFileName.contains(' '))
+ {
+ szFileName.prepend('"');
+ szFileName.append('"');
+ }
+
+ KviStr szDCC("GET");
+#ifdef COMPILE_SSL_SUPPORT
+ if(c->switches()->find('s',"ssl"))szDCC.prepend('S');
+#else
+ if(c->switches()->find('s',"ssl"))c->warning(__tr2qs_ctx("This executable has no SSL support, -s switch ignored","dcc"));
+#endif
+ if(c->switches()->find('t',"tdcc"))szDCC.prepend('T');
+
+ if(uSize == 0)
+ {
+ c->window()->console()->connection()->sendFmtData("PRIVMSG %s :%cDCC %s %s%c",
+ c->window()->console()->connection()->encodeText(szTarget).data(),
+ 0x01,
+ c->window()->console()->connection()->encodeText(szDCC.ptr()).data(),
+ c->window()->console()->connection()->encodeText(szFileName).data(),
+ 0x01);
+ } else {
+ c->window()->console()->connection()->sendFmtData("PRIVMSG %s :%cDCC %s %s %u%c",
+ c->window()->console()->connection()->encodeText(szTarget).data(),
+ 0x01,
+ c->window()->console()->connection()->encodeText(szDCC.ptr()).data(),
+ c->window()->console()->connection()->encodeText(szFileName).data(),
+ uSize,0x01);
+ }
+
+ return true;
+}
+
+
+
+
+// FIXME: SSL support for DCC VOICE ? (has a sense ?)
+
+/*
+ @doc: dcc.voice
+ @type:
+ command
+ @title:
+ dcc.voice
+ @short:
+ Starts a DCC Voice connection
+ @syntax:
+ dcc.voice [-g=<codec>] [-n] [-c] [-u] [-h=<sample_rate_in_hz>] [-m[=<boolean>]] [-i=<interface>] [-p=<port>] [-a=<fake address>] [-f=<fake port>] <nickname>
+ @switches:
+ !sw: -g=<codec> | --codec=<codec>
+ Use the codec specified as parameter.
+ Actually the supported codecs are "null","adpcm" and "gsm".
+
+ !sw: -h=<rate> | --sample-rate=<rate>
+ Use the sample rate specified by <rage>.
+ Valid sample rates are 8000, 11025, 22050 and 44100 Hz.
+
+ !sw: -m[=<boolean>] | --minimize[=<boolean>]
+ If the -m switch is passed, the default boolCreateMinimizedDccSend option
+ is overridden with the <boolean> parameter passed. So actually
+ by passing -m=1 will create a minimized DCC send even
+ if the [fnc]$option[/fnc](boolCreateMinimizedDccSend) returns false.[br]
+ In the same way, by passing -m=0 you will create a non minimized DCC send.
+ If no <boolean> value is specified, it defaults to 1.[br]
+
+ !sw: -n | --no-ctcp
+ Do NOT send the CTCP request to the target user, you will have to do it manually,
+ or the remote user will have to connect manually (for example by using dcc.recv -c).[br]
+
+ !sw: -c | --connect
+ Attempt to CONNECT to the remote host specified as <interface> and <port>,
+ instead of listening (active connection instead of a passive one).
+ In this case the -i and -p switches are mandatory.[br]
+ The 'c' switch takes precedence over 'n' (In fact both should
+ be mutually exclusive).[br]
+ If the 'c' and 'n' switches are missing, this commands
+ needs to be executed in a window that is bound to a connected
+ IRC context (you need a third entity to accomplish the negotiation).[br]
+
+ !sw: -i=<interface> | --ip=<interface>
+ Bind the local listening socket to the specified <interface> (which is an IP address, IPv4 or IPv6).
+ If this switch is NOT specified, the socket is bound to the interface of
+ the current IRC connection (if any) or to "127.0.0.1".[br]
+ You can also specify a local interface name to get the address from (this works only for IPv4 interfaces
+ since IPv6 ones seems to be unsupported by the system ioctl() calls at the moment (for linux at least)).[br]
+ Here go some examples:[br]
+ -i=215.243.12.12: this will bind to the IPv4 interface with the specified address.[br]
+ -i=3ffe:1001::1: this will bind to the IPv6 interface with the specified address.[br]
+ -i=ppp0: this will bind to the IPv4 address of the interface ppp0 (if supported by the underlying system).[br]
+ The -i switch parameter may serve also as a target address when the -c switch is used.[br]
+
+ !sw: -p=<port> | --port=<port>
+ Bind the local listening socket to the specified <port>.
+ If this switch is NOT specified, the port will be a "random" one choosen by the kernel.[br]
+
+ !sw: -a=<fake address> | --fake-address=<fake address>
+ Send the <fake address> as target for the remote client in the requesting CTCP message.
+ If this switch is not given, the CTCP will contain the real IP address of the listening
+ interface.[br]
+
+ !sw: -f=<fake port> | --fake-port=<fake port>
+ Send the <fake port> as target port for the remote client in the requesting CTCP message.
+ If this switch is not given, the CTCP will contain the real port of the listening socket.
+ [br][br]
+ All these switches are meant to allow maximum flexibility of the
+ DCC negotiation, earlier KVIrc releases had serious problems
+ with firewalled and/or masqueraded machines. With the -a and -f switches
+ you can work around it.[br]
+ [br]
+
+ !sw: -u | --unlimited
+ If the 'u' switch is given, the connection attempt will
+ never time out; this might be useful if you want to leave
+ a listening socket for a friend of yours while you are sleeping
+ and have the CTCP processing disabled. The 'u' switch works either
+ in active and passive mode.[br]
+
+ @description:
+ Attempts a DCC Voice connection to <nickname>.[br]
+ The -g option is used to select the GSM codec, available codecs are "gsm", "adpcm" and "null".[br]
+ The adpcm codec is the one that was used in previous KVIrc versions, it provides a 1:4 compression rate
+ and is designed for 8 KHz audio sampling rate (but will work also with other sampling rates).[br]
+ The gsm codec offers 1:10 compression at the cost of some quality and cpu time. If you have a good
+ cpu and plan to transmit voice only, use this codec.<br> The null codec
+ offers no compression and may be used to transfer plain audio data over a fast connection (usually loopback
+ connection or local networks). The null codec with 44100 sampling rate would provide CD quality audio
+ streaming, but it is practically not usable (at the time I'm writing) since requires a
+ monster bandwidth. If the -g switch is not present, the adpcm codec is used by default (for compatibility reasons).[br]
+ The -h switch is used to select the sampling rate, if not given the sampling rate defaults to 8000 Hz.
+ This switch accepts any value, but in fact the soundcards have limits on the values. Typically
+ the lowest limit is 5 KHz and the upper limit is 44.1 KHz (but some soundcards support 96 KHz).
+ It is also possible that the soundcard can't support a continous range of frequencies and
+ will select a discrete closest match instead.[br]
+ The "commonly used" sample rates are 8000, 11025, 22050 and 44100 Hz.[br]
+ The remaining parameters are equivalent to the ones used in [cmd]dcc.send[/cmd], so please refer to that
+ help page for the full discussion. This help page contains only a brief resume of these parameters.[br]
+ @examples:
+ [example]
+ [comment]# Setup a DCC VOICE connection with Pragma (IRC user)[/comment]
+ dcc.voice Pragma
+ [comment]# Setup a DCC VOICE connection with Pragma and use the gsm codec[/comment]
+ dcc.voice -g=gsm Pragma
+ [comment]# Setup a DCC VOICE connection with Pragma, use the gsm codec and 22050 Hz sampling rate[/comment]
+ dcc.voice -g=gsm -h=22050 Pragma
+ [comment]# Setup a listening socket for a DCC VOICE connection on interface 127.0.0.1 and port 8088[/comment]
+ dcc.voice -n -i=127.0.0.1 -p=8088 Pippo
+ [comment]# Connect to the socket above[/comment]
+ dcc.voice -c -i=127.0.0.1 -p=8088 Pluto
+ [comment]# Same as above but use the NULL codec with 11025 Hz sampling rate[/comment]
+ dcc.voice -g=null -h=11025 -n -i=127.0.0.1 -p=8088 Pippo
+ [comment]# Connect to the socket above[/comment]
+ dcc.voice -g=null -h=11025 -c -i=127.0.0.1 -p=8088 Pluto
+ [/example]
+*/
+
+static bool dcc_kvs_cmd_voice(KviKvsModuleCommandCall * c)
+{
+ QString szTarget;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("target",KVS_PT_NONEMPTYSTRING,0,szTarget)
+ KVSM_PARAMETERS_END(c)
+
+#ifdef COMPILE_DISABLE_DCC_VOICE
+ c->warning(__tr2qs_ctx("DCC VOICE support not enabled at compilation time","dcc"));
+ return true;
+#endif
+
+ KviDccDescriptor * d = new KviDccDescriptor(c->window()->console());
+
+ d->szNick = szTarget; // we always specify the nickname
+ d->szUser = __tr2qs_ctx("unknown","dcc"); // username is always unknown
+ d->szHost = d->szUser; // host is always unknown
+ d->iSampleRate = 8000;
+
+ if(!dcc_kvs_parse_default_parameters(d,c))return false;
+
+ if(KviKvsVariant * pSR = c->switches()->find('h',"sample-rate"))
+ {
+ kvs_int_t iSR;
+ if(!pSR->asInteger(iSR))
+ {
+ c->warning(__tr2qs_ctx("Invalid sample rate specified, defaulting to 8000","dcc"));
+ d->iSampleRate = 8000;
+ } else {
+ d->iSampleRate = iSR;
+ }
+ }
+
+ d->szCodec = "adpcm";
+
+ if(KviKvsVariant * pCodec = c->switches()->find('g',"codec"))
+ {
+ QString szCodec;
+ pCodec->asString(szCodec);
+
+ if(!kvi_dcc_voice_is_valid_codec(szCodec))
+ {
+ c->warning(__tr2qs_ctx("Invalid codec specified, defaulting to 'adpcm'","dcc"));
+ d->szCodec = "adpcm";
+ }
+ }
+
+ dcc_module_set_dcc_type(d,"VOICE");
+ if(c->switches()->find('c',"connect"))
+ {
+ if(!(c->switches()->find('i',"ip") && c->switches()->find('p',"port")))
+ {
+ delete d;
+ c->error(__tr2qs_ctx("-c requires -i and -p","dcc"));
+ return false;
+ }
+ d->szIp = d->szListenIp;
+ d->szPort = d->szListenPort;
+ d->szListenIp = ""; // useless
+ d->szListenPort = ""; // useless
+ d->bActive = true;
+
+ d->triggerCreationEvent();
+ g_pDccBroker->activeVoiceExecute(0,d);
+ } else {
+ d->szIp = __tr2qs_ctx("unknown","dcc");
+ d->szPort = d->szIp;
+ d->bActive = false;
+ d->bSendRequest = !(c->switches()->find('n',"no-ctcp"));
+
+ d->triggerCreationEvent();
+ g_pDccBroker->passiveVoiceExecute(d);
+ }
+
+ return true;
+}
+
+
+
+
+/*
+static bool dcc_module_cmd_canvas(KviModule *m,KviCommand *c)
+{
+ ENTER_STACK_FRAME(c,"dcc_module_cmd_canvas");
+
+ KviStr target;
+ if(!g_pUserParser->parseCmdFinalPart(c,target))return false;
+
+ if(target.isEmpty())return c->error(KviError_notEnoughParameters,"%s",__tr_ctx("Missing target nickname","dcc"));
+
+ KviDccDescriptor * d = new KviDccDescriptor(c->window()->console());
+
+ d->szNick = target.ptr(); // we always specify the nickname
+ d->szUser = __tr2qs_ctx("unknown","dcc"); // username is always unknown
+ d->szHost = d->szUser; // host is always unknown
+*/
+/*
+ d->bIsTdcc = c->hasSwitch('t');
+
+ d->bOverrideMinimize = c->hasSwitch('m');
+
+ if(d->bOverrideMinimize)
+ {
+ KviStr tmpVal;
+ if(!(c->getSwitchValue('m',tmpVal)))d->bShowMinimized = false;
+ else d->bShowMinimized = kvi_strEqualCI(tmpVal.ptr(),"1");
+ }
+
+
+ if(!d->console())
+ {
+ // We don't need a console with -c and -n , otherwise we need it
+ if(!(c->hasSwitch('c') || c->hasSwitch('n')))return c->noIrcContext();
+ else d->console() = c->window()->frame()->firstConsole();
+ }
+
+ __range_valid(d->console());
+
+ if(!d->console()->isConnected())
+ {
+ // We don't need a connection with -c and -n , otherwise we need it
+ if(!(c->hasSwitch('c') || c->hasSwitch('n')))return c->notConnectedToServer();
+ else {
+ // -c or -n , grab a local nick from somewhere
+ d->szLocalNick = KVI_OPTION_STRING(KviOption_stringNickname1);
+ d->szLocalNick.stripWhiteSpace();
+ if(d->szLocalNick.isEmpty())d->szLocalNick = KVI_DEFAULT_NICKNAME1;
+ d->szLocalUser = __tr("unknown"); // we can live without it
+ d->szLocalHost = d->szLocalUser; // we can live without it
+ }
+ } else {
+ // We know everything
+ d->szLocalNick = d->console()->currentNickName();
+ d->szLocalUser = d->console()->currentUserName();
+ d->szLocalHost = d->console()->currentLocalHostName();
+ }
+
+
+ if(c->hasSwitch('i'))
+ {
+ c->getSwitchValue('i',d->szListenIp);
+ if(!(d->szListenIp.contains('.') || d->szListenIp.contains(':')))
+ {
+ // This will magically work with the same buffer as source and dst!
+ if(!kvi_getInterfaceAddress(d->szListenIp.ptr(),d->szListenIp))
+ {
+ return c->error(KviError_invalidParameter,__tr("Can't get address of interface %s"),d->szListenIp.ptr());
+ }
+ }
+ } else {
+ if(d->console()->isConnected())
+ {
+ d->console()->socket()->getLocalHostIp(d->szListenIp,d->console()->isIpV6Connection());
+ } else d->szListenIp = "127.0.0.1"; // huh ? :)
+ }
+
+ if(c->hasSwitch('p'))c->getSwitchValue('p',d->szListenPort);
+ else d->szListenPort = "0"; // any port is ok
+
+ if(c->hasSwitch('a'))c->getSwitchValue('a',d->szFakeIp);
+
+ if(c->hasSwitch('f'))c->getSwitchValue('f',d->szFakePort);
+
+ d->bDoTimeout = (!c->hasSwitch('u'));
+
+*/
+/*
+ if(!dcc_module_parse_default_parameters(d,c))return false;
+ dcc_module_set_dcc_type(d,"VOICE");
+
+ if(c->hasSwitch('c'))
+ {
+ if(!(c->hasSwitch('i') && c->hasSwitch('p')))
+ {
+ delete d;
+ return c->error(KviError_notEnoughParameters,__tr_ctx("-c requires -i and -p","dcc"));
+ }
+ d->szIp = d->szListenIp;
+ d->szPort = d->szListenPort;
+ d->szListenIp = ""; // useless
+ d->szListenPort = ""; // useless
+ d->bActive = true;
+
+ d->triggerCreationEvent();
+ g_pDccBroker->activeCanvasExecute(0,d);
+ } else {
+ d->szIp = __tr2qs_ctx("unknown","dcc");
+ d->szPort = d->szIp;
+ d->bActive = false;
+ d->bSendRequest = !c->hasSwitch('n');
+
+ d->triggerCreationEvent();
+ g_pDccBroker->passiveCanvasExecute(d);
+ }
+
+ return c->leaveStackFrame();
+}
+*/
+
+
+
+
+
+/*
+ @doc: dcc_connection
+ @type:
+ generic
+ @title:
+ DCC negotiation and connection
+ @short:
+ Overview of the DCC internals
+ @keyterms:
+ DCC without IRC
+ @body:
+ [big]What is DCC?[/big][br]
+ 'DCC' stands for Direct Client Connection, it is used to exchange data
+ directly between two IRC clients (with no IRC server in the middle).[br]
+ DCC itself is not a well-defined protocol, but rather a set of
+ subprotocols with (more or less) standardized rules.[br]
+ Sub-protocols are also (historically) called [b]"DCC types"[/b]; this term often
+ leads to confusion and it will become clear later.[br]
+ Each subprotocol has two main parts: The [b]DCC negotiation[/b] and the [b]DCC transfer[/b].[br]
+ The [b]DCC negotiation[/b] part is used to request the [b]DCC transfer[/b] and define its necessary parameters,[br]
+ while the [b]DCC transfer[/b] part is the real data transfer between clients.[br]
+ The [b]DCC negotiation[/b] requires a third entity that routes the negotiation data between clients,
+ this is usually an IRC server.[br]
+ [br]
+ [big]DCC Negotiation[/big][br]
+ This part of the protocol is the most tricky and difficult one, and is different for almost every DCC subprotocol.[br]
+ The "constant" scenario of the negotiation is more or less the following:[br]
+ There are two IRC clients connected to the same IRC network and they want to exchange some data in
+ a direct client connection.[br]
+ Each client knows the other by nickname only (and eventually by the host displayed by the IRC server,
+ but this cannot be trusted for several reasons), and can send text messages to each other by using the
+ IRC network as data channel.[br]
+ To initiate a direct client connection, one of the clients must start listening on some port (this is called [b]passive client[/b])
+ and the other must connect to that port on the first client's machine (this is the [b]active client[/b]).[br]
+ Both clients must agree on who is the passive and who is the active client. The active client must also
+ know the passive client's IP address and port (in order to be able to contact it).[br]
+ Finally, both clients must agree on the transfer type that has to be initiated.[br]
+ The negotiation exchanges these informations between clients by using IRC as channel and CTCP messages
+ as encoding method.[br]
+ An example will make things clearer:[br]
+ DCC Chat is the simplest (and most widely implemented) DCC subprotocol:
+ it is used to exchange <cr><lf> separated text data between clients.[br]
+ Assume that you want to establish a DCC Chat
+ connection to 'Sarah' that is actually connected to your IRC network (so
+ she/he is an IRC user just like you).
+ All you have to do is type sth as "/dcc chat Sarah" in your IRC client.
+ The client will setup a listening socket on a random port choosen
+ usually by the kernel of your OS. In this case YOU are the [b]passive client[/b], and Sarah is the active one.[br]
+ Once the socket is ready to accept connections,
+ your client will send a [doc:ctcp_handling]CTCP message[/doc] to Sarah using the IRC connection (and protocol) as channel:[br]
+ PRIVMSG Sarah :<0x01>DCC CHAT chat <ip_address> <port><0x01>[br]
+ where <ip_address> is the address of the listening socket and <port>
+ is the port that it has been bound to (these informations are obtained
+ after the socket has been setup). Once Sarah has received the CTCP message,
+ and agreed to connect, her (active) client will attempt to connect to the
+ specified <ip_address> and <port> (eg. to your listening socket).[br]
+ Once the connection has been established, it continues using the
+ specific CHAT transfer protocol.[br]
+ Some IRC clients allow modifications of this procedure:[br]
+ First of all, the port to listen on can be specified by the user
+ and not by the kernel; this is useful when the passive client
+ is behind a firewall that "shades" some sets of ports.
+ The ip address for the listening socket
+ can be specified by the user as well (especially when the machine has more than one network interface).[br]
+ A more challenging trick is to listen on a specified ip address and port
+ and notify different ones to the remote user (eg, <ip_address> and <port>
+ parameters of the CTCP message are not the ones that the client is listening on).
+ This is especially useful with "transparent proxy" firewalls that
+ often are not transparent enough to allow the DCC connections.
+ (If you have one of these firewalls you know what I'm talking about,
+ otherwise just read on). KVIrc allows to avoid the usage of a third entity
+ for the protocol negotiation too.
+ You can setup a listening socket on a specified port and ip address
+ without notyfying anyone of this.
+ You can also manually connect to a specified port and ip address without
+ having been notified of a DCC request.[br][br][br]
+ Is everything clear ?...I don't think so... my English is really too bad...
+ [br]
+ [big]DCC Transfer[/big][br]
+ The DCC transfer part is different for every DCC subprotocol, but
+ it always happens over a direct client to client TCP connection.[br]
+ [br]
+ [big]DCC Subprotocols[/big][br]
+ There are two main standardized DCC subprotocols that are widely implemented in IRC clients:
+ [b]DCC Chat[/b] and [b]DCC Send[/b].[br]
+ DCC Chat is quite simple and the protocol is more or less completely defined.[br]
+ DCC Send is a *real mess*, the original definition was not very flexible
+ so many IRC clients tried to enchance both the negotiation and the transfer, leading
+ often to incompatible implementations. (I can remember the Turbo File Transfer implemented
+ by VIrc, the Send-Ahead enchancement implemented in many clients, the RESUME facility...)[br]
+ Many clients introduced new DCC subprotocols with non-standard implementations,
+ leading again to client incompatibility.[br]
+ Some of the notable subprotocols are DCC Voice, DCC Draw, DCC Whiteboard...[br]
+ [br]
+ [big]DCC Chat[/big][br]
+ This is the simplest and most standardized DCC subprotocol. Almost every IRC client implements it.[br]
+ It is used to exchange lines of text between the two clients.[br]
+ The negotiation is quite simple, we assume that Client A wants to establish a DCC Chat connection to Client B.
+ Client A sets up a listening socket and retrieves its adress (ip address and port).[br]
+ Once the socket is ready Client A sends a CTCP request to B, in the following form:[br]
+ [b]DCC CHAT chat <ipaddress> <port>[/b][br]
+ Where <ipaddress> is a string representing an positive integer that is the A socket's IP address
+ in network byte order, and where <port> is a string representing an positive integer that is the
+ A socket's port.[br]
+ The original purpose of the second "chat" string in the CTCP request is quite obscure, it was probably
+ introduced to have the <ipaddress> as second parameter, as in the DCC Send subprotocol.[br]
+ Client B receives the CTCP, parses it, eventually asks the user for permission and connects
+ to the specified ip address and port.
+ The transfer protocol is quite simple, both clients can send text lines separated by <cr><lf> pairs.[br]
+ Some clients use only <lf> as line terminator so the general idea is that one of <cr> <cr><lf> or <lf>
+ can be used as line terminator.[br]
+ As extension to the protocol, KVIrc allows <ipaddress> to be an IPv6 address in the standard hexadecimal
+ notation, the connection will be made over the IPv6 protocol in this case (obviously if both clients
+ support this feature).[br]
+ (It is not clear why the original DCC specification used the unsigned int format instead of a
+ standard string representation of the IP address... missing inet_aton() function on the target system?).[br]
+ KVIrc adds the Secure Sockets Layer to the DCC Chat protocol. In this case the negotiation string becomes:[br]
+ [b]DCC SCHAT chat <ipaddress> <port>[/b][br]
+ where "SCHAT" stands for Secure CHAT.[br] The external protocol is exactly the same but is built on top of a Secure Sockets Layer
+ implementation (specifically OpenSSL). The connection will be encrypted with a private key algorithm after
+ a public key handshake.[br]
+ [br]
+ [big]DCC Send[/big][br]
+ DCC Send is another standard subprotocol. Most clients implement this as well, many have tried
+ to enchance it.[br]
+ The basic DCC Send protocol allows transferring a file from the requesting client to the receiving client.[br]
+ The requesting client (the one that sends the file) is always passive and the receiving client is always active.[br]
+ This is a huge protocol limitation since firewalled clients are often unable to accept incoming connections.[br]
+ The negotiation protocol is more complex than DCC Chat; we assume that Client A wants to send the file F to Client B.[br]
+ Client A sets up a listening socket and retrieves its ip address and port.[br]
+ Client A sends a CTCP request to Client B in the following form:[br]
+ [b]DCC SEND <filename> <ipaddress> <port> <filesize>[/b][br]
+ <ipaddress> and <port> have the same semantics as in the DCC Chat subprotocol.[br]
+ <filename> is the name (without path!) of the file to be sent, and <filesize> is (yeah), the file size.[br]
+ Client B receives the CTCP, parses it, eventually asks the user for confirmation and connects to the
+ specified ip address and port; the transfer then begins.[br]
+ Client A sends blocks of data (usually 1-2 KB) and at every block awaits confirmation from the Client B,
+ that when receiving a block should reply 4 bytes containing an positive number specifying the total size
+ of the file received up to that moment.[br]
+ The transmission closes when the last acknowledge is received by Client A.[br]
+ The acknowledges were meant to include some sort of coherency check in the transmission, but in fact
+ no client can "recover" from an acknowledge error/desync, all of them just close the connection declaring the
+ transfer as failed (the situation is even worse in fact, often acknowledge errors aren't even detected!).[br]
+ Since the packet-acknowledge round trip eats a lot of time, many clients included
+ the "send-ahead" feature; the Client A does NOT wait for the acknowledge of the first packet before sending the second one.[br]
+ The acknowledges are still sent, but just a reverse independent stream.[br] This makes the DCC Send considerably faster.[br]
+ Since the acknowledge stream has non-zero bandwidth usage, no client can recover from an acknowledge error and
+ having them as an independant stream is more or less like having no acknowledges, the "Turbo" ( :) ) extension has been added:
+ Client B will send no acknowledges and will just close the connection when he has received all the expected data.[br]
+ This makes the DCC Send as fast as FTP transfers.[br]
+ The "Turbo" extension is specified during the negotiation phase, bu using TSEND as DCC message type (instead of SEND).[br]
+ The "Turbo" extension is not widely implemented.[br]
+ Later implementations have added the support for resuming interrupted DCC Send transfers:[br]
+ Client A sets up the socket and sends the CTCP request as before.[br]
+ If Client B discovers that the file has been partially received in a previous DCC Send session it sends
+ a resume request in the following form:[br]
+ [b]DCC RESUME <filename> <port> <resume position>[/b][br]
+ Where <port> is the <port> sent in the DCC SEND request and <resume position> is the position in the file
+ from where the transfer should start.[br]
+ Cilent A receives the request, parses it and eventually replies with:[br]
+ [b]DCC ACCEPT <filename> <port> <resume position>[/b][br]
+ Client B receives the ACCEPT message, connects to Client A and the transfer initiates as before.[br]
+ The "Send-ahead" and "Turbo" extensions can obviously be used also in this case (But 'T' is NOT prepended to the RESUME and ACCEPT messages).[br]
+ The IPv6 extension can be used also in this subprotocol, so <ipaddress> can be also an IPv6 address in hexadecimal notation.[br]
+ KVIrc introduces the SSL extension also to DCC Send. The protocol remains the same again but it is built on top of
+ a Secure Sockets Layer implementation just like DCC Chat.[br]
+ With SSL the negotiation string becomes:[br]
+ [b]DCC SSEND <filename> <ipaddress> <port> <filesize>[/b][br]
+ where "SSEND" stands for Secure SEND.[br]
+ The "turbo" extension can be combined with the SSL extension too. In this case the second parameter
+ of the negotiation string must be "TSSEND" or "STSEND".[br]
+ [br]
+ [big]DCC Recv[/big][br]
+ DCC Recv is the counterpart of DCC Send. This is a KVIrc extension and is not standard yet.[br]
+ The purpose of this subprotocol will not be immediately clear, but read on for an explanation.[br]
+ It is used to request a file from another client; we assume that Client A knows that Client B has
+ a specific file and is able/wants to send it.[br]
+ Client A sets up a listening socket, retrieves its address and port and then
+ sends a CTCP request to Client B in the following form:[br]
+ [b]DCC RECV <filename> <ipaddress> <port> <resume position>[/b][br]
+ where <filename> is the name of the requested file without path, <ipaddress> and <port> have the usual meaning and <resume position>
+ is the position from that the transfer should start from.[br]
+ <ipaddress> can be an IPv6 address as well.[br]
+ Client B receives the CTCP message, parses it, looks for the file to send (in some unspecified way)
+ and connects to the specified ip address and port. The transfer then begins just as in the DCC send, but in the inverse way:
+ Client B sends blocks of data to Client A and Client B sends back acknowledges.[br]
+ This subprotocol is useful in transferring data from clients that are behind a firewall and are not able to accept
+ incoming connections (this is not possible with a normal DCC Send). In this case the client that receives
+ the file is passive and the client that sends it is active (as opposite to DCC Send).[br]
+ The "Send ahead" extension can be used also in this case and the "Turbo" extension is activated by prepending a 'T' to the
+ DCC message, "TRECV" instead of "RECV". The SSL extension is activated by prepending an 'S' to the
+ DCC message, "SRECV", "STRECV" or "TSRECV".[br]
+ This subprotocol has an implicit resume capability and thus has no need for RESUME and ACCEPT messages.[br]
+ DCC Recv requires the initiating (passive) client to know that the file to be transferred is avaiable on the B's side
+ and probably also know the file size. This subprotocol does not specify how this information is obtained, but it
+ will become clear soon that it can be obtained either manually (User B can simply tell the info to User A),
+ or automatically (as in the DCC Rsend subprotocol (keep reading)).[br]
+ [br]
+ [big]DCC RSend[/big][br]
+ DCC RSend stands for Reverse Send. This is a KVIrc extension to the SEND protocol to allow firewalled clients
+ to send files.[br] In fact, this is a "half" subprotocol, since it defines only a part of the DCC negotiation;
+ the transfer is defined by another subprotocol (and specifically bu DCC Recv).[br]
+ The requesting client (the one that sends the file) is active and the receiving client is passive.[br]
+ Assume that Client A wants to send a file to Client B and that Client A cannot accept incoming connections.[br]
+ Client A sends a CTCP request to Client B in the following form:[br]
+ [b]DCC RSEND <filename> <filesize>[/b][br]
+ Client B receives the request, parses it, eventually asks the user for confirmation, sets up a listening socket, retrieves
+ its ip address and port and switches to the DCC Recv subprotocol by effectively sending the following CTCP message:[br]
+ [b]DCC RECV <filename> <ipaddress> <port> <resume position>[/b][br]
+ The rest of the transfer is defined by the DCC Recv subprotocol.[br]
+ The "Turbo" extension is again activated by prepending a 'T' to the RSEND string, so the initial CTCP will become:[br]
+ [b]DCC TRSEND <filename> <filesize>[/b][br]
+ The "SSL" extension is also activated by prepending an 'S' to the RSEND string. It can be again combined
+ with the "turbo" extension. The negotiation parameter becomes then "SRSEND","TSRSEND" or "STRSEND".[br]
+ Easy, no ? :)[br]
+ [br]
+ [big]DCC Get[/big][br]
+ This is again a "half" subprotocol in fact since it defines only a part of the negotiation for file transfers.[br]
+ It is also NON standard, since actually no client except KVIrc implements it (AFAIK).[br]
+ DCC Get is used to request a file from a remote client. Assume that Client A wants to request a file from Client B
+ (and assume that Client A knows that B has that file and wants to send it).[br]
+ Client A sends a CTCP message to Client B in the following form:[br]
+ [b]DCC GET <filename>[/b][br]
+ Where <filename> is a name of a file without path.[br]
+ Client B receives the message, parses it, looks for an association of the <filename> to a real filesystem file
+ and starts one of the two DCC File transfer subprotocols, DCC Send or DCC RSend.[br]
+ Client B should prefer the DCC Send method and choose DCC RSend only if it is not able to accept incoming connections.[br]
+ This subprotocol can be used by firewalled clients that can't accept connections but still want to request a file
+ from another client, this one can fail only if both clients are firewalled (in this case no DCC transfer is possible at all).[br]
+ This subprotocol also does not need to "magically" know the file size, the size definition
+ is found in the subprotocol that the remote client will choose.[br]
+ The association of <filename> with a real file on the B's machine is not explicitly defined by the subprotocol;
+ KVIrc uses an internal "file-offer" table with a list of files that are available for download.[br]
+ The "turbo" and "SSL" extensions are activated as usual, "TGET", "SGET", "TSGET" and "STGET" are supported.[br]
+ [br]
+ [big]DCC File Transfer[/big][br]
+ DCC Send: Send a file, sender is passive, receiver is active (not good for firewalled senders)[br]
+ DCC Recv: Receive a file, sender is active, receiver is passive (not good for firewalled receivers)[br]
+ DCC RSend: Send a file, sender is active, receiver is passive (not good for firewalled receivers)[br]
+ DCC Get: Receive a file, sender is passive if not firewalled, receiver active if sender not firewalled (will fail only if both are firewalled)[br]
+ The "turbo" extension disables the stream of acknowledges and is activated by prepending the 'T' character to the DCC subprotocol name[br]
+ The "SSL" extension causes a Secure Socket Layer to be used and is activated by prepending the 'S' character to the DCC subprotocol name[br]
+ [br]
+ [big]DCC Voice[/big][br]
+ DCC Voice is a KVIrc extension (there is a Windows client called VIrc that implements such
+ a protocol, but it is incompatible with KVIrc).[br]
+ DCC Voice allows audio level communication between two clients, the audio stream is compressed
+ with a specified codec.[br]
+ KVIrc currently supports the ADPCM (core support) and the GSM codec (if the libgsm is available on the target system).[br]
+ [b]TODO: Finish the DCC Voice doc :)[/b]
+ [big]More tricks[/big][br]
+ KVIrc supports another "hack" to the DCC negotiation, it recognizes "XDCC" as
+ a DCC negotiation CTCP parameter.[br]
+ This can be used to circumvent limitations of some IRC clients (read mIRC) that will not allow
+ you to send a /DCC GET since it is an unrecognized DCC type.[br]
+ "XDCC" has exactly the same meaning as "DCC" (at least in KVIrc).[br]
+*/
+
+static KviDccDescriptor * dcc_kvs_find_dcc_descriptor(const kvs_uint_t &uId,KviKvsModuleRunTimeCall * c,bool bWarn = true)
+{
+ KviDccDescriptor * dcc = 0;
+ if(uId == 0)
+ {
+ if(c->window()->inherits("KviDccWindow"))
+ {
+ dcc = ((KviDccWindow *)(c->window()))->descriptor();
+ }
+ if((!dcc) && bWarn)
+ c->warning(__tr2qs_ctx("The current window has no associated DCC session","dcc"));
+ return dcc;
+ }
+ dcc = KviDccDescriptor::find(uId);
+ if((!dcc) && bWarn)
+ c->warning(__tr2qs_ctx("The specified parameter is not a valid DCC identifier","dcc"));
+ return dcc;
+}
+
+
+/*
+ @doc: dcc.abort
+ @type:
+ command
+ @title:
+ dcc.abort
+ @short:
+ Aborts a dcc session
+ @syntax:
+ dcc.abort [-q] [dcc_id:uint]
+ @description:
+ Terminates the Direct Client Connection specified by <dcc_id>.[br]
+ If <dcc_id> is omitted then the DCC Session associated
+ to the current window is assumed.[br]
+ If <dcc_id> is not a valid DCC session identifier (or it is omitted
+ and the current window has no associated DCC session) then
+ this function doesn't abort anything and prints a warning unless the -q switch is used.[br]
+ If <dcc_id> refers to a file transfer then it the transfer is simply
+ terminated. If <dcc_id> refers to a dcc chat then the result
+ is equivalent to closing the related window.[br]
+ See the [module:dcc]dcc module[/module] documentation for more informations.[br]
+ @examples:
+*/
+
+static bool dcc_kvs_cmd_abort(KviKvsModuleCommandCall * c)
+{
+ kvs_uint_t uDccId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
+ KVSM_PARAMETERS_END(c)
+
+ KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c,!c->switches()->find('q',"quiet"));
+
+ if(dcc)
+ {
+ if(dcc->transfer())dcc->transfer()->abort();
+ else if(dcc->window())dcc->window()->close();
+ }
+
+ return true;
+}
+
+/*
+ @doc: dcc.setBandwidthLimit
+ @type:
+ command
+ @title:
+ dcc.setBandwidthLimit
+ @short:
+ Set the bandwidthlimit of a dcc.send session.
+ @syntax:
+ dcc.setBandwidthLimit [-q] [dcc_id:uint]
+ @description:
+ Terminates the Direct Client Connection specified by <dcc_id>.[br]
+ If <dcc_id> is omitted then the DCC Session associated
+ to the current window is assumed.[br]
+ If <dcc_id> is not a valid DCC session identifier (or it is omitted
+ and the current window has no associated DCC session) then
+ this function prints a warning unless the -q switch is used.[br]
+ If <dcc_id> does not refers to a file transfer a warning will be printing unless the -q switch is used.[br]
+ See the [module:dcc]dcc module[/module] documentation for more informations.[br]
+ @examples:
+*/
+static bool dcc_kvs_cmd_setBandwidthLimit(KviKvsModuleCommandCall * c)
+{
+ kvs_uint_t uDccId,uVal;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("limit_value",KVS_PT_UINT,0,uVal)
+ KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
+ KVSM_PARAMETERS_END(c)
+
+ KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c,!c->switches()->find('q',"quiet"));
+ if(dcc)
+ {
+ if (dcc->transfer())dcc->transfer()->setBandwidthLimit(uVal);
+ else if (!c->switches()->find('q',"quiet"))c->warning(__tr2qs_ctx("This DCC session is not a DCC transfer session","dcc"));
+ }
+ return true;
+}
+
+/*
+ @doc: dcc.protocol
+ @type:
+ function
+ @title:
+ $dcc.protocol
+ @short:
+ Returns the protocol of the specified DCC
+ @syntax:
+ <string> $dcc.protocol
+ <string> $dcc.protocol(<dcc_id:uint>)
+ @description:
+ Returns the string describing the protocol of the
+ Direct Client Connection specified by <dcc_id>.[br]
+ If <dcc_id> is omitted then the DCC Session associated
+ to the current window is assumed.[br]
+ If <dcc_id> is not a valid DCC session identifier (or it is omitted
+ and the current window has no associated DCC session) then
+ this function prints a warning and returns an empty sting.[br]
+ See the [module:dcc]dcc module[/module] documentation for more informations.[br]
+*/
+
+static bool dcc_kvs_fnc_protocol(KviKvsModuleFunctionCall * c)
+{
+ kvs_uint_t uDccId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
+ KVSM_PARAMETERS_END(c)
+
+ KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
+
+ if(dcc)c->returnValue()->setString(dcc->protocol());
+ return true;
+}
+
+
+/*
+ @doc: dcc.connectionType
+ @type:
+ function
+ @title:
+ $dcc.connectionType
+ @short:
+ Returns the connection type of the specified DCC
+ @syntax:
+ <string> $dcc.connectionType
+ <string> $dcc.connectionType(<dcc_id:uint>)
+ @description:
+ Returns the connection type of the specified DCC.[br]
+ Returns the string "ACTIVE" for active DCC connections
+ and the string "PASSIVE" for passive DCC connections.
+ If <dcc_id> is omitted then the DCC Session associated
+ to the current window is assumed.[br]
+ If <dcc_id> is not a valid DCC session identifier (or it is omitted
+ and the current window has no associated DCC session) then
+ this function prints a warning and returns an empty sting.[br]
+ See the [module:dcc]dcc module[/module] documentation for more informations.[br]
+*/
+
+static bool dcc_kvs_fnc_connectionType(KviKvsModuleFunctionCall * c)
+{
+ kvs_uint_t uDccId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
+ KVSM_PARAMETERS_END(c)
+
+ KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
+
+ if(dcc)c->returnValue()->setString(dcc->isActive() ? "ACTIVE" : "PASSIVE");
+ return true;
+}
+
+
+/*
+ @doc: dcc.isFileTransfer
+ @type:
+ function
+ @title:
+ $dcc.isFileTransfer
+ @short:
+ Checks if a DCC is a file transfer
+ @syntax:
+ <boolean> $dcc.isFileTransfer
+ <boolean> $dcc.isFileTransfer(<dcc_id:uint>)
+ @description:
+ Returns 1 if the specified Direct Client Connection
+ is a file transfer and 0 otherwise.[br]
+ If <dcc_id> is omitted then the DCC Session associated
+ to the current window is assumed.[br]
+ If <dcc_id> is not a valid DCC session identifier (or it is omitted
+ and the current window has no associated DCC session) then
+ this and returns 0.[br]
+ See the [module:dcc]dcc module[/module] documentation for more informations.[br]
+*/
+
+static bool dcc_kvs_fnc_isFileTransfer(KviKvsModuleFunctionCall * c)
+{
+ kvs_uint_t uDccId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
+ KVSM_PARAMETERS_END(c)
+
+ KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c,false);
+
+ if(dcc)c->returnValue()->setBoolean(dcc->isFileTransfer());
+ return true;
+}
+
+
+/*
+ @doc: dcc.isFileUpload
+ @type:
+ function
+ @title:
+ $dcc.isFileUpload
+ @short:
+ Checks if a DCC is an upload file transfer
+ @syntax:
+ <boolean> $dcc.isFileUpload
+ <boolean> $dcc.isFileUpload(<dcc_id:uint>)
+ @description:
+ Returns 1 if the specified Direct Client Connection
+ is an upload file transfer and 0 otherwise.[br]
+ If <dcc_id> is omitted then the DCC Session associated
+ to the current window is assumed.[br]
+ If <dcc_id> is not a valid DCC session identifier (or it is omitted
+ and the current window has no associated DCC session) then
+ this function prints a warning and returns 0.[br]
+ See the [module:dcc]dcc module[/module] documentation for more informations.[br]
+*/
+
+static bool dcc_kvs_fnc_isFileUpload(KviKvsModuleFunctionCall * c)
+{
+ kvs_uint_t uDccId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
+ KVSM_PARAMETERS_END(c)
+
+ KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
+
+ if(dcc)c->returnValue()->setBoolean(dcc->isFileUpload());
+ return true;
+}
+
+
+/*
+ @doc: dcc.isFileDownload
+ @type:
+ function
+ @title:
+ $dcc.isFileDownload
+ @short:
+ Checks if a DCC is a download file transfer
+ @syntax:
+ <boolean> $dcc.isFileDownload
+ <boolean> $dcc.isFileDownload(<dcc_id:uint>)
+ @description:
+ Returns 1 if the specified Direct Client Connection
+ is a download file transfer and 0 otherwise.[br]
+ If <dcc_id> is omitted then the DCC Session associated
+ to the current window is assumed.[br]
+ If <dcc_id> is not a valid DCC session identifier (or it is omitted
+ and the current window has no associated DCC session) then
+ this function prints a warning and returns 0.[br]
+ See the [module:dcc]dcc module[/module] documentation for more informations.[br]
+*/
+
+static bool dcc_kvs_fnc_isFileDownload(KviKvsModuleFunctionCall * c)
+{
+ kvs_uint_t uDccId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
+ KVSM_PARAMETERS_END(c)
+
+ KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
+
+ if(dcc)c->returnValue()->setBoolean(dcc->isFileDownload());
+ return true;
+}
+
+
+/*
+ @doc: dcc.localNick
+ @type:
+ function
+ @title:
+ $dcc.localNick
+ @short:
+ Returns the local nickname associated to the specified DCC
+ @syntax:
+ <string> $dcc.localNick
+ <string> $dcc.localNick(<dcc_id:uint>)
+ @description:
+ Returns the local nickname associated to the specified DCC.[br]
+ If <dcc_id> is omitted then the DCC Session associated
+ to the current window is assumed.[br]
+ If <dcc_id> is not a valid DCC session identifier (or it is omitted
+ and the current window has no associated DCC session) then
+ this function prints a warning and returns an empty sting.[br]
+ See the [module:dcc]dcc module[/module] documentation for more informations.[br]
+*/
+
+static bool dcc_kvs_fnc_localNick(KviKvsModuleFunctionCall * c)
+{
+ kvs_uint_t uDccId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
+ KVSM_PARAMETERS_END(c)
+
+ KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
+
+ if(dcc)c->returnValue()->setString(dcc->localNick());
+ return true;
+}
+
+
+/*
+ @doc: dcc.localUser
+ @type:
+ function
+ @title:
+ $dcc.localUser
+ @short:
+ Returns the local username associated to the specified DCC
+ @syntax:
+ <string> $dcc.localUser
+ <string> $dcc.localUser(<dcc_id:uint>)
+ @description:
+ Returns the local username associated to the specified DCC.[br]
+ If <dcc_id> is omitted then the DCC Session associated
+ to the current window is assumed.[br]
+ If <dcc_id> is not a valid DCC session identifier (or it is omitted
+ and the current window has no associated DCC session) then
+ this function prints a warning and returns an empty sting.[br]
+ See the [module:dcc]dcc module[/module] documentation for more informations.[br]
+*/
+
+static bool dcc_kvs_fnc_localUser(KviKvsModuleFunctionCall * c)
+{
+ kvs_uint_t uDccId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
+ KVSM_PARAMETERS_END(c)
+
+ KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
+
+ if(dcc)c->returnValue()->setString(dcc->localUser());
+ return true;
+}
+
+/*
+ @doc: dcc.localHost
+ @type:
+ function
+ @title:
+ $dcc.localHost
+ @short:
+ Returns the local hostname associated to the specified DCC
+ @syntax:
+ <string> $dcc.localHost
+ <string> $dcc.localHost(<dcc_id:uint>)
+ @description:
+ Returns the local hostname associated to the specified DCC.[br]
+ If <dcc_id> is omitted then the DCC Session associated
+ to the current window is assumed.[br]
+ If <dcc_id> is not a valid DCC session identifier (or it is omitted
+ and the current window has no associated DCC session) then
+ this function prints a warning and returns an empty sting.[br]
+ See the [module:dcc]dcc module[/module] documentation for more informations.[br]
+*/
+
+static bool dcc_kvs_fnc_localHost(KviKvsModuleFunctionCall * c)
+{
+ kvs_uint_t uDccId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
+ KVSM_PARAMETERS_END(c)
+
+ KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
+
+ if(dcc)c->returnValue()->setString(dcc->localHost());
+ return true;
+}
+
+
+/*
+ @doc: dcc.localIp
+ @type:
+ function
+ @title:
+ $dcc.localIp
+ @short:
+ Returns the local ip address associated to the specified DCC
+ @syntax:
+ <string> $dcc.localIp
+ <string> $dcc.localIp(<dcc_id:uint>)
+ @description:
+ Returns the local ip address associated to the specified DCC.[br]
+ If <dcc_id> is omitted then the DCC Session associated
+ to the current window is assumed.[br]
+ If <dcc_id> is not a valid DCC session identifier (or it is omitted
+ and the current window has no associated DCC session) then
+ this function prints a warning and returns an empty sting.[br]
+ See the [module:dcc]dcc module[/module] documentation for more informations.[br]
+*/
+
+static bool dcc_kvs_fnc_localIp(KviKvsModuleFunctionCall * c)
+{
+ kvs_uint_t uDccId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
+ KVSM_PARAMETERS_END(c)
+
+ KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
+
+ if(dcc)c->returnValue()->setString(dcc->localIp());
+ return true;
+}
+
+
+/*
+ @doc: dcc.localPort
+ @type:
+ function
+ @title:
+ $dcc.localPort
+ @short:
+ Returns the local port associated to the specified DCC
+ @syntax:
+ <integer> $dcc.localPort
+ <integer> $dcc.localPort(<dcc_id:uint>)
+ @description:
+ Returns the local port associated to the specified DCC.[br]
+ If <dcc_id> is omitted then the DCC Session associated
+ to the current window is assumed.[br]
+ If <dcc_id> is not a valid DCC session identifier then
+ this function prints a warning and returns an empty sting.[br]
+ See the [module:dcc]dcc module[/module] documentation for more informations.[br]
+*/
+
+static bool dcc_kvs_fnc_localPort(KviKvsModuleFunctionCall * c)
+{
+ kvs_uint_t uDccId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
+ KVSM_PARAMETERS_END(c)
+
+ KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
+
+ if(dcc)c->returnValue()->setString(dcc->localPort());
+ return true;
+}
+
+
+/*
+ @doc: dcc.localFileName
+ @type:
+ function
+ @title:
+ $dcc.localFileName
+ @short:
+ Returns the local file name associated to the specified DCC
+ @syntax:
+ <string> $dcc.localFileName(<dcc_id:uint>)
+ @description:
+ Returns the local file name associated to the specified DCC.[br]
+ If <dcc_id> does not identify a file transfer DCC then this
+ function returns an empty string.
+ If <dcc_id> is not a valid Direct Client Connection identifier
+ then this function prints a warning and returns an empty string.
+*/
+
+static bool dcc_kvs_fnc_localFileName(KviKvsModuleFunctionCall * c)
+{
+ kvs_uint_t uDccId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
+ KVSM_PARAMETERS_END(c)
+
+ KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
+
+ if(dcc)c->returnValue()->setString(dcc->localFileName());
+ return true;
+}
+
+
+/*
+ @doc: dcc.localFileSize
+ @type:
+ function
+ @title:
+ $dcc.localFileSize
+ @short:
+ Returns the local file size associated to the specified DCC
+ @syntax:
+ <integer> $dcc.localFileSize(<dcc_id:uint>)
+ @description:
+ Returns the local file size associated to the specified DCC.[br]
+ If <dcc_id> does not identify a file transfer DCC then this
+ function returns '0'[br]
+ If <dcc_id> is not a valid Direct Client Connection identifier
+ then this function prints a warning and returns '0'[br]
+ In upload transfers the local file size rappresents the
+ total size of the file to be transferred. In download transfers
+ the local file size is non zero only if the transfer has to resume
+ a file already existing on the local disk and it rappresents the
+ size of that file (and thus the offset that the transfer started on).
+*/
+
+static bool dcc_kvs_fnc_localFileSize(KviKvsModuleFunctionCall * c)
+{
+ kvs_uint_t uDccId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
+ KVSM_PARAMETERS_END(c)
+
+ KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
+
+ if(dcc)c->returnValue()->setString(dcc->localFileSize().isEmpty() ? QString("0") : dcc->localFileSize());
+ return true;
+}
+
+
+/*
+ @doc: dcc.remoteNick
+ @type:
+ function
+ @title:
+ $dcc.remoteNick
+ @short:
+ Returns the remote nickname associated to the specified DCC
+ @syntax:
+ <string> $dcc.remoteNick
+ <string> $dcc.remoteNick(<dcc_id:uint>)
+ @description:
+ Returns the remote nickname associated to the specified DCC.[br]
+ If <dcc_id> is omitted then the DCC Session associated
+ to the current window is assumed.[br]
+ If <dcc_id> is not a valid DCC session identifier (or it is omitted
+ and the current window has no associated DCC session) then
+ this function prints a warning and returns an empty sting.[br]
+ See the [module:dcc]dcc module[/module] documentation for more informations.[br]
+*/
+
+static bool dcc_kvs_fnc_remoteNick(KviKvsModuleFunctionCall * c)
+{
+ kvs_uint_t uDccId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
+ KVSM_PARAMETERS_END(c)
+
+ KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
+
+ if(dcc)c->returnValue()->setString(dcc->remoteNick());
+ return true;
+}
+
+
+/*
+ @doc: dcc.remoteUser
+ @type:
+ function
+ @title:
+ $dcc.remoteUser
+ @short:
+ Returns the remote username associated to the specified DCC
+ @syntax:
+ <string> $dcc.remoteUser
+ <string> $dcc.remoteUser(<dcc_id:uint>)
+ @description:
+ Returns the remote username associated to the specified DCC.[br]
+ If <dcc_id> is omitted then the DCC Session associated
+ to the current window is assumed.[br]
+ If <dcc_id> is not a valid DCC session identifier (or it is omitted
+ and the current window has no associated DCC session) then
+ this function prints a warning and returns an empty sting.[br]
+ See the [module:dcc]dcc module[/module] documentation for more informations.[br]
+*/
+
+static bool dcc_kvs_fnc_remoteUser(KviKvsModuleFunctionCall * c)
+{
+ kvs_uint_t uDccId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
+ KVSM_PARAMETERS_END(c)
+
+ KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
+
+ if(dcc)c->returnValue()->setString(dcc->remoteUser());
+ return true;
+}
+
+/*
+ @doc: dcc.remoteHost
+ @type:
+ function
+ @title:
+ $dcc.remoteHost
+ @short:
+ Returns the remote hostname associated to the specified DCC
+ @syntax:
+ <string> $dcc.remoteHost
+ <string> $dcc.remoteHost(<dcc_id:uint>)
+ @description:
+ Returns the remote hostname associated to the specified DCC.[br]
+ If <dcc_id> is omitted then the DCC Session associated
+ to the current window is assumed.[br]
+ If <dcc_id> is not a valid DCC session identifier (or it is omitted
+ and the current window has no associated DCC session) then
+ this function prints a warning and returns an empty sting.[br]
+ See the [module:dcc]dcc module[/module] documentation for more informations.[br]
+*/
+
+static bool dcc_kvs_fnc_remoteHost(KviKvsModuleFunctionCall * c)
+{
+ kvs_uint_t uDccId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
+ KVSM_PARAMETERS_END(c)
+
+ KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
+
+ if(dcc)c->returnValue()->setString(dcc->remoteHost());
+ return true;
+}
+
+/*
+ @doc: dcc.remoteIp
+ @type:
+ function
+ @title:
+ $dcc.remoteIp
+ @short:
+ Returns the remote ip address associated to the specified DCC
+ @syntax:
+ <string> $dcc.remoteIp
+ <string> $dcc.remoteIp(<dcc_id:uint>)
+ @description:
+ Returns the remote ip address associated to the specified DCC.[br]
+ If <dcc_id> is omitted then the DCC Session associated
+ to the current window is assumed.[br]
+ If <dcc_id> is not a valid DCC session identifier (or it is omitted
+ and the current window has no associated DCC session) then
+ this function prints a warning and returns an empty sting.[br]
+ See the [module:dcc]dcc module[/module] documentation for more informations.[br]
+*/
+
+static bool dcc_kvs_fnc_remoteIp(KviKvsModuleFunctionCall * c)
+{
+ kvs_uint_t uDccId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
+ KVSM_PARAMETERS_END(c)
+
+ KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
+
+ if(dcc)c->returnValue()->setString(dcc->remoteIp());
+ return true;
+}
+
+
+/*
+ @doc: dcc.remotePort
+ @type:
+ function
+ @title:
+ $dcc.remotePort
+ @short:
+ Returns the remote port associated to the specified DCC
+ @syntax:
+ <integer> $dcc.remotePort
+ <integer> $dcc.remotePort(<dcc_id:uint>)
+ @description:
+ Returns the remote port associated to the specified DCC.[br]
+ If <dcc_id> is omitted then the DCC Session associated
+ to the current window is assumed.[br]
+ If <dcc_id> is not a valid DCC session identifier (or it is omitted
+ and the current window has no associated DCC session) then
+ this function prints a warning and returns an empty sting.[br]
+ See the [module:dcc]dcc module[/module] documentation for more informations.[br]
+*/
+
+static bool dcc_kvs_fnc_remotePort(KviKvsModuleFunctionCall * c)
+{
+ kvs_uint_t uDccId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
+ KVSM_PARAMETERS_END(c)
+
+ KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
+
+ if(dcc)c->returnValue()->setString(dcc->remotePort());
+ return true;
+}
+
+
+/*
+ @doc: dcc.remoteFileName
+ @type:
+ function
+ @title:
+ $dcc.remoteFileName
+ @short:
+ Returns the remote file name associated to the specified DCC
+ @syntax:
+ <string> $dcc.remoteFileName(<dcc_id:uint>)
+ @description:
+ Returns the remote file name associated to the specified DCC.[br]
+ If <dcc_id> does not identify a file transfer DCC then this
+ function returns an empty string.
+ If <dcc_id> is not a valid Direct Client Connection identifier
+ then this function prints a warning and returns an empty string.
+*/
+
+static bool dcc_kvs_fnc_remoteFileName(KviKvsModuleFunctionCall * c)
+{
+ kvs_uint_t uDccId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
+ KVSM_PARAMETERS_END(c)
+
+ KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
+
+ if(dcc)c->returnValue()->setString(dcc->remoteFileName());
+ return true;
+}
+
+
+/*
+ @doc: dcc.remoteFileSize
+ @type:
+ function
+ @title:
+ $dcc.remoteFileSize
+ @short:
+ Returns the remote file size associated to the specified DCC
+ @syntax:
+ <integer> $dcc.remoteFileSize(<dcc_id:uint>)
+ @description:
+ Returns the remote file size associated to the specified DCC.[br]
+ If <dcc_id> does not identify a file transfer DCC then this
+ function returns '0'[br]
+ If <dcc_id> is not a valid Direct Client Connection identifier
+ then this function prints a warning and returns '0'[br]
+ In download transfers the remote file size rappresents the
+ total size of the file to be transferred (advertished by the remote end).[br]
+ In upload transfers the remote file size is non zero only if the
+ remote user has issued a resume request and is rappresents the requested offset
+ in bytes from which the transfer has started.
+*/
+
+static bool dcc_kvs_fnc_remoteFileSize(KviKvsModuleFunctionCall * c)
+{
+ kvs_uint_t uDccId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
+ KVSM_PARAMETERS_END(c)
+
+ KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
+
+ if(dcc)c->returnValue()->setString(dcc->remoteFileSize().isEmpty() ? QString("0") : dcc->remoteFileSize());
+ return true;
+}
+
+
+/*
+ @doc: dcc.ircContext
+ @type:
+ function
+ @title:
+ $dcc.ircContext
+ @short:
+ Returns the ircContext from which this DCC has originated
+ @syntax:
+ <integer> $dcc.ircContext
+ <integer> $dcc.ircContext(<dcc_id:uint>)
+ @description:
+ Returns the identifier of the irc context from which
+ the specified DCC has been originated.[br]
+ When the DCC is not originated from an IRC context
+ then this function returns '0' : an invalid irc context id.
+ If <dcc_id> is omitted then the DCC Session associated
+ to the current window is assumed.[br]
+ If <dcc_id> is not a valid DCC session identifier (or it is omitted
+ and the current window has no associated DCC session) then
+ this function prints a warning and returns 0.[br]
+ See the [module:dcc]dcc module[/module] documentation for more informations.[br]
+*/
+
+static bool dcc_kvs_fnc_ircContext(KviKvsModuleFunctionCall * c)
+{
+ kvs_uint_t uDccId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
+ KVSM_PARAMETERS_END(c)
+
+ KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
+
+ if(dcc)c->returnValue()->setInteger(dcc->console()->context()->id());
+ return true;
+}
+
+
+
+/*
+ @doc: dcc.transferStatus
+ @type:
+ function
+ @title:
+ $dcc.transferStatus
+ @short:
+ Returns the current status of a dcc file transfer
+ @syntax:
+ <string> $dcc.transferStatus
+ <string> $dcc.transferStatus(<dcc_id:uint>)
+ @description:
+ Returns the status in the specified DCC session.[br]
+ The status is one of the strings "connecting", "transferring", "success" and "failure".
+ "success" and "failure" are reported when the transfer is terminated.
+ If <dcc_id> is omitted then the DCC Session associated
+ to the current window is assumed.[br]
+ If <dcc_id> is not a valid DCC session identifier (or it is omitted
+ and the current window has no associated DCC session) then
+ this function prints a warning and returns an empty sting.[br]
+ If the DCC session does not refer to a file transfer then
+ this function returns "".[br]
+ See the [module:dcc]dcc module[/module] documentation for more informations.[br]
+*/
+
+static bool dcc_kvs_fnc_transferStatus(KviKvsModuleFunctionCall * c)
+{
+ kvs_uint_t uDccId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
+ KVSM_PARAMETERS_END(c)
+
+ KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
+
+ if(dcc)
+ {
+ if(dcc->transfer())
+ {
+ QString tmp;
+ dcc->transfer()->fillStatusString(tmp);
+ c->returnValue()->setString(tmp);
+ }
+ }
+ return true;
+}
+
+
+/*
+ @doc: dcc.transferredBytes
+ @type:
+ function
+ @title:
+ $dcc.transferredBytes
+ @short:
+ Returns the number of transferred bytes in a dcc file transfer
+ @syntax:
+ <integer> $dcc.transferredBytes
+ <integer> $dcc.transferredBytes(<dcc_id:uint>)
+ @description:
+ Returns the number of transferred bytes in the specified DCC session.[br]
+ If <dcc_id> is omitted then the DCC Session associated
+ to the current window is assumed.[br]
+ If <dcc_id> is not a valid DCC session identifier (or it is omitted
+ and the current window has no associated DCC session) then
+ this function prints a warning and returns an empty sting.[br]
+ If the DCC session does not refer to a file transfer then
+ this function returns 0.[br]
+ See the [module:dcc]dcc module[/module] documentation for more informations.[br]
+*/
+
+static bool dcc_kvs_fnc_transferredBytes(KviKvsModuleFunctionCall * c)
+{
+ kvs_uint_t uDccId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
+ KVSM_PARAMETERS_END(c)
+
+ KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
+
+ if(dcc)
+ {
+ if(dcc->transfer())
+ {
+ c->returnValue()->setInteger(dcc->transfer()->transferredBytes());
+ } else {
+ c->returnValue()->setInteger(0);
+ }
+ }
+ return true;
+}
+
+
+
+/*
+ @doc: dcc.averageSpeed
+ @type:
+ function
+ @title:
+ $dcc.averageSpeed
+ @short:
+ Returns the average speed of a dcc file transfer
+ @syntax:
+ $dcc.averageSpeed
+ $dcc.averageSpeed(<dcc_id>)
+ @description:
+ Returns the average speed (in bytes/sec) of the specified DCC session.[br]
+ If <dcc_id> is omitted then the DCC Session associated
+ to the current window is assumed.[br]
+ If <dcc_id> is not a valid DCC session identifier (or it is omitted
+ and the current window has no associated DCC session) then
+ this function prints a warning and returns an empty sting.[br]
+ If the DCC session does not refer to a file transfer then
+ this function returns 0.[br]
+ See the [module:dcc]dcc module[/module] documentation for more informations.[br]
+*/
+
+static bool dcc_kvs_fnc_averageSpeed(KviKvsModuleFunctionCall * c)
+{
+ kvs_uint_t uDccId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
+ KVSM_PARAMETERS_END(c)
+
+ KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
+
+ if(dcc)
+ {
+ if(dcc->transfer())
+ {
+ c->returnValue()->setInteger(dcc->transfer()->averageSpeed());
+ } else {
+ c->returnValue()->setInteger(0);
+ }
+ }
+ return true;
+}
+
+
+
+/*
+ @doc: dcc.session
+ @type:
+ function
+ @title:
+ $dcc.session
+ @short:
+ Returns the DCC session identifier associated to a window
+ @syntax:
+ <uint> $dcc.session
+ <uint> $dcc.session(<window_id>)
+ @description:
+ Returns the DCC session identifier associated to the DCC window specified
+ by <window_id>. If <window_id> is omitted then the DCC session identifier
+ associated to the current window is returned. If the specified window
+ has no associated DCC session then a warning is printed and 0 is returned.[br]
+*/
+
+static bool dcc_kvs_fnc_session(KviKvsModuleFunctionCall * c)
+{
+ QString szWinId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("window_id",KVS_PT_STRING,KVS_PF_OPTIONAL,szWinId)
+ KVSM_PARAMETERS_END(c)
+
+ KviDccDescriptor * dcc = 0;
+ if(szWinId.isEmpty())
+ {
+ if(c->window()->inherits("KviDccWindow"))
+ dcc = ((KviDccWindow *)(c->window()))->descriptor();
+ if(!dcc)
+ {
+ c->warning(__tr2qs_ctx("The current window has no associated DCC session","dcc"));
+ c->returnValue()->setInteger(0);
+ } else {
+ c->returnValue()->setInteger(dcc->id());
+ }
+ return true;
+ }
+
+ KviWindow * pWnd = g_pApp->findWindow(szWinId);
+ if(!pWnd)
+ {
+ c->warning(__tr2qs_ctx("The specified window identifier is not valid","dcc"));
+ c->returnValue()->setInteger(0);
+ return true;
+ }
+
+ if(pWnd->inherits("KviDccWindow"))
+ dcc = ((KviDccWindow *)pWnd)->descriptor();
+ if(!dcc)
+ {
+ c->warning(__tr2qs_ctx("The current window has no associated DCC session","dcc"));
+ c->returnValue()->setInteger(0);
+ } else {
+ c->returnValue()->setInteger(dcc->id());
+ }
+ return true;
+}
+
+
+/*
+ @doc: dcc.sessionList
+ @type:
+ function
+ @title:
+ $dcc.sessionList
+ @short:
+ List the existing dcc session identifiers
+ @syntax:
+ <array> $dcc.sessionList
+ <array> $dcc.sessionList(<filter:string>)
+ @description:
+ The first form returns an array with all the currently existing dcc session
+ identifiers. The second form returns an array with the session types specified
+ in <filter> which may be a combination of the flags 'u' (for file upload),
+ 'd' (for file download) and 'c' (for dcc chat). To select all the file transfers
+ please use the combination 'ud'.[br]
+ See the [module:dcc]dcc module[/module] documentation for more informations.[br]
+*/
+
+static bool dcc_kvs_fnc_sessionList(KviKvsModuleFunctionCall * c)
+{
+ QString szFlags;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("filter",KVS_PT_STRING,KVS_PF_OPTIONAL,szFlags)
+ KVSM_PARAMETERS_END(c)
+
+ KviKvsArray * a = new KviKvsArray();
+ c->returnValue()->setArray(a);
+
+ KviPointerHashTable<int,KviDccDescriptor> * dict = KviDccDescriptor::descriptorDict();
+ if(!dict)return true;
+
+ KviPointerHashTableIterator<int,KviDccDescriptor> it(*dict);
+
+ int idx = 0;
+
+ if(szFlags.isEmpty())
+ {
+ // all
+ while(KviDccDescriptor * dcc = it.current())
+ {
+ a->set(idx++,new KviKvsVariant((kvs_int_t)(dcc->id())));
+ ++it;
+ }
+ } else {
+ bool bWantFileUploads = szFlags.find('u',false) != -1;
+ bool bWantFileDownloads = szFlags.contains('d',false) != -1;
+ bool bWantChats = szFlags.contains('c',false) != -1;
+
+ while(KviDccDescriptor * dcc = it.current())
+ {
+ if((dcc->isFileUpload() && bWantFileUploads) ||
+ (dcc->isFileDownload() && bWantFileDownloads) ||
+ (dcc->isDccChat() && bWantChats))
+ {
+ a->set(idx++,new KviKvsVariant((kvs_int_t)(dcc->id())));
+ }
+ ++it;
+ }
+ }
+
+ return true;
+}
+
+
+/*
+ @doc: dcc
+ @type:
+ module
+ @short:
+ Direct Client Connections
+ @title:
+ The DCC module
+ @body:
+ [big]Overview[/big][br]
+ The DCC module handles the Direct Client Connection
+ protocol layer and all it's sub-protocols.[br]
+ The sub-protocols include the standard CHAT
+ the standard SEND and its variants plus several
+ KVIrc extensions like RECV,RSEND,GET and VOICE.[br]
+ [br]
+ [big]Initiating a DCC negotiation[/big][br]
+ The following commands initiate a specific DCC session
+ with a remote client:[br]
+ [cmd]dcc.chat[/cmd][br]
+ [cmd]dcc.send[/cmd][br]
+ [cmd]dcc.rsend[/cmd][br]
+ [cmd]dcc.recv[/cmd][br]
+ [cmd]dcc.get[/cmd][br]
+ [cmd]dcc.voice[/cmd][br]
+ [br]
+ [big]Handling the DCC events[/big][br]
+ Each DCC session has an associated unique identifier (&lt;dcc_id&gt;).[br]
+ You can interact with the session by using several commands
+ and functions exported by this module and by passing the above session
+ id as parameter.[br]
+ The session related commands and functions are the following:[br]
+ [fnc]$dcc.sessionList[/fnc][br]
+ [fnc]$dcc.protocol[/fnc][br]
+ [fnc]$dcc.connectionType[/fnc][br]
+ [fnc]$dcc.transferStatus[/fnc][br]
+ [fnc]$dcc.isFileTransfer[/fnc][br]
+ [fnc]$dcc.isFileUpload[/fnc][br]
+ [fnc]$dcc.isFileDownload[/fnc][br]
+ [fnc]$dcc.localNick[/fnc][br]
+ [fnc]$dcc.localUser[/fnc][br]
+ [fnc]$dcc.localHost[/fnc][br]
+ [fnc]$dcc.localIp[/fnc][br]
+ [fnc]$dcc.localPort[/fnc][br]
+ [fnc]$dcc.localFileName[/fnc][br]
+ [fnc]$dcc.localFileSize[/fnc][br]
+ [fnc]$dcc.remoteNick[/fnc][br]
+ [fnc]$dcc.remoteUser[/fnc][br]
+ [fnc]$dcc.remoteHost[/fnc][br]
+ [fnc]$dcc.remoteIp[/fnc][br]
+ [fnc]$dcc.remotePort[/fnc][br]
+ [fnc]$dcc.remoteFileName[/fnc][br]
+ [fnc]$dcc.remoteFileSize[/fnc][br]
+ [fnc]$dcc.ircContext[/fnc][br]
+ [fnc]$dcc.session[/fnc][br]
+*/
+
+
+static bool dcc_module_init(KviModule * m)
+{
+ g_pDccBroker = new KviDccBroker();
+
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"send",dcc_kvs_cmd_send);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"chat",dcc_kvs_cmd_chat);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"voice",dcc_kvs_cmd_voice);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"recv",dcc_kvs_cmd_recv);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"rsend",dcc_kvs_cmd_rsend);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"get",dcc_kvs_cmd_get);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"abort",dcc_kvs_cmd_abort);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"setBandwidthLimit",dcc_kvs_cmd_setBandwidthLimit);
+
+
+ // FIXME: file upload / download state ?
+
+ KVSM_REGISTER_FUNCTION(m,"transferStatus",dcc_kvs_fnc_transferStatus);
+ KVSM_REGISTER_FUNCTION(m,"protocol",dcc_kvs_fnc_protocol);
+ KVSM_REGISTER_FUNCTION(m,"connectionType",dcc_kvs_fnc_connectionType);
+ KVSM_REGISTER_FUNCTION(m,"isFileTransfer",dcc_kvs_fnc_isFileTransfer);
+ KVSM_REGISTER_FUNCTION(m,"isFileUpload",dcc_kvs_fnc_isFileUpload);
+ KVSM_REGISTER_FUNCTION(m,"isFileDownload",dcc_kvs_fnc_isFileDownload);
+ KVSM_REGISTER_FUNCTION(m,"localNick",dcc_kvs_fnc_localNick);
+ KVSM_REGISTER_FUNCTION(m,"localUser",dcc_kvs_fnc_localUser);
+ KVSM_REGISTER_FUNCTION(m,"localHost",dcc_kvs_fnc_localHost);
+ KVSM_REGISTER_FUNCTION(m,"localIp",dcc_kvs_fnc_localIp);
+ KVSM_REGISTER_FUNCTION(m,"localPort",dcc_kvs_fnc_localPort);
+ KVSM_REGISTER_FUNCTION(m,"localFileName",dcc_kvs_fnc_localFileName);
+ KVSM_REGISTER_FUNCTION(m,"localFileSize",dcc_kvs_fnc_localFileSize);
+ KVSM_REGISTER_FUNCTION(m,"remoteNick",dcc_kvs_fnc_remoteNick);
+ KVSM_REGISTER_FUNCTION(m,"remoteUser",dcc_kvs_fnc_remoteUser);
+ KVSM_REGISTER_FUNCTION(m,"remoteHost",dcc_kvs_fnc_remoteHost);
+ KVSM_REGISTER_FUNCTION(m,"remoteIp",dcc_kvs_fnc_remoteIp);
+ KVSM_REGISTER_FUNCTION(m,"remotePort",dcc_kvs_fnc_remotePort);
+ KVSM_REGISTER_FUNCTION(m,"remoteFileName",dcc_kvs_fnc_remoteFileName);
+ KVSM_REGISTER_FUNCTION(m,"remoteFileSize",dcc_kvs_fnc_remoteFileSize);
+ KVSM_REGISTER_FUNCTION(m,"averageSpeed",dcc_kvs_fnc_averageSpeed);
+ KVSM_REGISTER_FUNCTION(m,"transferredBytes",dcc_kvs_fnc_transferredBytes);
+ KVSM_REGISTER_FUNCTION(m,"ircContext",dcc_kvs_fnc_ircContext);
+ KVSM_REGISTER_FUNCTION(m,"session",dcc_kvs_fnc_session);
+ KVSM_REGISTER_FUNCTION(m,"sessionList",dcc_kvs_fnc_sessionList);
+
+ return true;
+}
+
+static bool dcc_module_cleanup(KviModule *m)
+{
+ delete g_pDccBroker;
+ g_pDccBroker = 0;
+#ifdef COMPILE_USE_GSM
+ kvi_gsm_codec_done();
+#endif
+
+ return true;
+}
+
+static bool dcc_module_can_unload(KviModule *m)
+{
+ return g_pDccBroker ? g_pDccBroker->canUnload() : true;
+}
+
+KVIRC_MODULE(
+ "Dcc",
+ "1.0.0",
+ "Copyright (C) 2000-2004:\n" \
+ " Szymon Stefanek (pragma at kvirc dot net)\n",
+ "DCC extension for KVIrc\n",
+ dcc_module_init,
+ dcc_module_can_unload,
+ 0,
+ dcc_module_cleanup
+)
diff --git a/src/modules/dcc/marshal.cpp b/src/modules/dcc/marshal.cpp
new file mode 100644
index 00000000..9aedec41
--- /dev/null
+++ b/src/modules/dcc/marshal.cpp
@@ -0,0 +1,647 @@
+//
+// File : marshal.cpp
+// Creation date : Sun Sep 17 2000 15:59:11 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "marshal.h"
+
+#include "kvi_settings.h"
+#include "kvi_netutils.h"
+#include "kvi_error.h"
+#include "kvi_options.h"
+#include "kvi_locale.h"
+#include "kvi_memmove.h"
+#include "kvi_socket.h"
+#include "kvi_fileutils.h"
+
+
+#include <stdlib.h> //for exit()
+
+
+
+
+KviDccMarshal::KviDccMarshal(KviDccMarshalOutputContext * ctx)
+: QObject(0,"dcc_marshal")
+{
+ m_pSn = 0;
+ m_fd = KVI_INVALID_SOCKET;
+ m_pTimeoutTimer = 0;
+ m_bIpV6 = false;
+ m_pOutputContext = ctx;
+#ifdef COMPILE_SSL_SUPPORT
+ m_pSSL = 0;
+#endif
+ m_szIp = "";
+ m_szPort = "";
+ m_szSecondaryIp = "";
+ m_szSecondaryPort = "";
+}
+
+KviDccMarshal::~KviDccMarshal()
+{
+ reset();
+}
+
+kvi_socket_t KviDccMarshal::releaseSocket()
+{
+ kvi_socket_t aux_fd = m_fd;
+ m_fd = KVI_INVALID_SOCKET;
+ return aux_fd;
+}
+
+#ifdef COMPILE_SSL_SUPPORT
+KviSSL * KviDccMarshal::releaseSSL()
+{
+ KviSSL * theSSL = m_pSSL;
+ m_pSSL = 0;
+ return theSSL;
+}
+#endif
+
+void KviDccMarshal::reset()
+{
+ if(m_pSn)
+ {
+ delete m_pSn;
+ m_pSn = 0;
+ }
+ if(m_fd != KVI_INVALID_SOCKET)
+ {
+ kvi_socket_close(m_fd);
+ m_fd = KVI_INVALID_SOCKET;
+ }
+#ifdef COMPILE_SSL_SUPPORT
+// debug("MARSHAL RESETTING (SSL=%d)",m_pSSL);
+ if(m_pSSL)
+ {
+// debug("MARSHAL CLEARING THE SSL");
+ KviSSLMaster::freeSSL(m_pSSL);
+ m_pSSL = 0;
+ }
+#endif
+ if(m_pTimeoutTimer)
+ {
+ delete m_pTimeoutTimer;
+ m_pTimeoutTimer = 0;
+ }
+ m_bIpV6 = false;
+}
+
+int KviDccMarshal::dccListen(const QString &ip,const QString &port,bool bUseTimeout,bool bUseSSL)
+{
+ if(m_fd != KVI_INVALID_SOCKET)return KviError_anotherConnectionInProgress;
+
+ m_szIp = ip;
+ m_szPort = port;
+
+ m_bOutgoing = false;
+
+ m_bUseTimeout = bUseTimeout;
+
+#ifdef COMPILE_SSL_SUPPORT
+ m_bUseSSL = bUseSSL;
+#else
+ if(bUseSSL)return KviError_noSSLSupport;
+#endif
+
+ if(m_pTimeoutTimer)delete m_pTimeoutTimer;
+ m_pTimeoutTimer = new QTimer();
+ connect(m_pTimeoutTimer,SIGNAL(timeout()),this,SLOT(doListen()));
+ m_pTimeoutTimer->start(100,true);
+
+ return KviError_success;
+}
+
+void KviDccMarshal::doListen()
+{
+ if(m_pTimeoutTimer)
+ {
+ delete m_pTimeoutTimer;
+ m_pTimeoutTimer = 0;
+ }
+
+ // Check the address type
+ if(!kvi_isValidStringIp(m_szIp))
+ {
+#ifdef COMPILE_IPV6_SUPPORT
+ if(!kvi_isValidStringIp_V6(m_szIp))
+ {
+ emit error(KviError_invalidIpAddress);
+ return;
+ } else m_bIpV6 = true;
+#else
+ emit error(KviError_invalidIpAddress);
+ return;
+#endif
+ }
+
+ bool bOk;
+ m_uPort = m_szPort.toUInt(&bOk);
+ if(!bOk)
+ {
+ emit error(KviError_invalidPortNumber);
+ return;
+ }
+
+
+#ifndef COMPILE_IPV6_SUPPORT
+ if(m_bIpV6)
+ {
+ emit error(KviError_noIpV6Support);
+ return;
+ }
+#endif
+
+
+#ifdef COMPILE_IPV6_SUPPORT
+ m_fd = kvi_socket_create(m_bIpV6 ? KVI_SOCKET_PF_INET6 : KVI_SOCKET_PF_INET,
+ KVI_SOCKET_TYPE_STREAM,KVI_SOCKET_PROTO_TCP);
+#else
+ m_fd = kvi_socket_create(KVI_SOCKET_PF_INET,KVI_SOCKET_TYPE_STREAM,KVI_SOCKET_PROTO_TCP);
+#endif
+
+ if(m_fd == KVI_INVALID_SOCKET)
+ {
+ emit error(KviError_socketCreationFailed);
+ return;
+ }
+
+ if((!KVI_OPTION_BOOL(KviOption_boolUserDefinedPortRange)) || (m_uPort != 0))
+ {
+#ifdef COMPILE_IPV6_SUPPORT
+ KviSockaddr sa(m_szIp,m_uPort,m_bIpV6);
+#else
+ KviSockaddr sa(m_szIp,m_uPort,false);
+#endif
+
+ if(!sa.socketAddress())
+ {
+ reset();
+ emit error(KviError_bindFailed);
+ return;
+ }
+
+ if(!kvi_socket_bind(m_fd,sa.socketAddress(),sa.addressLength()))
+ {
+ reset();
+ emit error(KviError_bindFailed);
+ return;
+ }
+
+ } else {
+ m_uPort = KVI_OPTION_UINT(KviOption_uintDccMinPort);
+ if(KVI_OPTION_UINT(KviOption_uintDccMaxPort) > 65535)KVI_OPTION_UINT(KviOption_uintDccMaxPort) = 65535;
+ bool bBindSuccess;
+ do {
+#ifdef COMPILE_IPV6_SUPPORT
+ KviSockaddr sa(m_szIp,m_uPort,m_bIpV6);
+#else
+ KviSockaddr sa(m_szIp,m_uPort,false);
+#endif
+ if(!sa.socketAddress())
+ {
+ reset();
+ emit error(KviError_bindFailed);
+ return;
+ }
+
+ bBindSuccess = kvi_socket_bind(m_fd,sa.socketAddress(),sa.addressLength());
+
+ if(!bBindSuccess)
+ {
+ if(m_uPort == 65535)
+ {
+ reset();
+ emit error(KviError_bindFailed);
+ return;
+ }
+ m_uPort++;
+ }
+
+ } while((!bBindSuccess) && (m_uPort <= KVI_OPTION_UINT(KviOption_uintDccMaxPort)));
+
+ if(!bBindSuccess)
+ {
+ reset();
+ emit error(KviError_bindFailed);
+ return;
+ }
+
+ }
+
+ if(!kvi_socket_listen(m_fd,1))
+ {
+ reset();
+ emit error(KviError_listenFailed);
+ return;
+ }
+
+
+ // Reread the port in case we're binding to a random one (0)
+
+#ifdef COMPILE_IPV6_SUPPORT
+ KviSockaddr sareal(0,m_bIpV6);
+#else
+ KviSockaddr sareal(0,false);
+#endif
+
+
+ int size = sareal.addressLength();
+
+ if(kvi_socket_getsockname(m_fd,sareal.socketAddress(),&size))
+ {
+// debug("GETSOCKNAMEOK");
+ m_szPort.setNum(sareal.port());
+ m_uPort = sareal.port();
+// debug("REALPORT %u",m_uPort);
+ } else {
+// debug("GETSOCKNAMEFAILED");
+ }
+
+ // and setup the READ notifier...
+ m_pSn = new QSocketNotifier(m_fd,QSocketNotifier::Read);
+ QObject::connect(m_pSn,SIGNAL(activated(int)),this,SLOT(snActivated(int)));
+ m_pSn->setEnabled(true);
+
+ // set the timer
+ if(KVI_OPTION_UINT(KviOption_uintDccSocketTimeout) < 5)
+ KVI_OPTION_UINT(KviOption_uintDccSocketTimeout) = 5;
+
+ if(m_bUseTimeout)
+ {
+ m_pTimeoutTimer = new QTimer();
+ connect(m_pTimeoutTimer,SIGNAL(timeout()),this,SLOT(connectionTimedOut()));
+ m_pTimeoutTimer->start(KVI_OPTION_UINT(KviOption_uintDccSocketTimeout) * 1000,true);
+ }
+ // and wait for connect
+
+ emit inProgress();
+}
+
+int KviDccMarshal::dccConnect(const char * ip,const char * port,bool bUseTimeout,bool bUseSSL)
+{
+ if(m_fd != KVI_INVALID_SOCKET)return KviError_anotherConnectionInProgress;
+
+ m_bUseTimeout = bUseTimeout;
+ m_szIp = ip;
+ m_szPort = port;
+ m_bOutgoing = true;
+
+#ifdef COMPILE_SSL_SUPPORT
+ m_bUseSSL = bUseSSL;
+#else
+ if(bUseSSL)return KviError_noSSLSupport;
+#endif
+
+ if(m_pTimeoutTimer)delete m_pTimeoutTimer;
+ m_pTimeoutTimer = new QTimer();
+ connect(m_pTimeoutTimer,SIGNAL(timeout()),this,SLOT(doConnect()));
+ m_pTimeoutTimer->start(100,true);
+
+ return KviError_success;
+}
+
+void KviDccMarshal::doConnect()
+{
+ if(m_pTimeoutTimer)
+ {
+ delete m_pTimeoutTimer;
+ m_pTimeoutTimer = 0;
+ }
+
+ // Check the address type
+ if(!kvi_isValidStringIp(m_szIp))
+ {
+#ifdef COMPILE_IPV6_SUPPORT
+ if(!kvi_isValidStringIp_V6(m_szIp))
+ {
+ emit error(KviError_invalidIpAddress);
+ return;
+ } else m_bIpV6 = true;
+#else
+ emit error(KviError_invalidIpAddress);
+ return;
+#endif
+ }
+
+ bool bOk;
+ m_uPort = m_szPort.toUInt(&bOk);
+ if(!bOk)
+ {
+ emit error(KviError_invalidPortNumber);
+ return;
+ }
+
+
+ // create the socket
+#ifdef COMPILE_IPV6_SUPPORT
+ m_fd = kvi_socket_create(m_bIpV6 ? KVI_SOCKET_PF_INET6 : KVI_SOCKET_PF_INET,
+ KVI_SOCKET_TYPE_STREAM,KVI_SOCKET_PROTO_TCP);
+#else
+ m_fd = kvi_socket_create(KVI_SOCKET_PF_INET,
+ KVI_SOCKET_TYPE_STREAM,KVI_SOCKET_PROTO_TCP);
+#endif
+ if(m_fd == KVI_INVALID_SOCKET)
+ {
+ emit error(KviError_socketCreationFailed);
+ return;
+ }
+
+ // make it non blocking
+ if(!kvi_socket_setNonBlocking(m_fd))
+ {
+ reset();
+ emit error(KviError_asyncSocketFailed);
+ return;
+ }
+
+
+ // fill the sockaddr structure
+
+#ifdef COMPILE_IPV6_SUPPORT
+ KviSockaddr sa(m_szIp,m_uPort,m_bIpV6);
+#else
+ KviSockaddr sa(m_szIp,m_uPort,false);
+#endif
+
+ if(!sa.socketAddress())
+ {
+ reset();
+ emit error(KviError_socketCreationFailed);
+ return;
+ }
+
+ if(!kvi_socket_connect(m_fd,sa.socketAddress(),sa.addressLength()))
+ {
+ int err = kvi_socket_error();
+
+ if(!kvi_socket_recoverableConnectError(err))
+ {
+ // Ops...
+ int sockError=err;
+ if(sockError==0)
+ {
+ // Zero error ?...let's look closer
+ int iSize=sizeof(int);
+ if(!kvi_socket_getsockopt(m_fd,SOL_SOCKET,SO_ERROR,
+ (void *)&sockError,&iSize))sockError=0;
+ }
+ // Die
+ reset();
+ // And declare problems :)
+ if(sockError)emit error(KviError::translateSystemError(sockError));
+ else emit error(KviError_unknownError); //Error 0 ?
+ return;
+ }
+ }
+
+
+ // and setup the WRITE notifier...
+ m_pSn = new QSocketNotifier(m_fd,QSocketNotifier::Write);
+ QObject::connect(m_pSn,SIGNAL(activated(int)),this,SLOT(snActivated(int)));
+ m_pSn->setEnabled(true);
+
+ // set the timer
+ if(KVI_OPTION_UINT(KviOption_uintDccSocketTimeout) < 5)
+ KVI_OPTION_UINT(KviOption_uintDccSocketTimeout) = 5;
+
+ if(m_bUseTimeout)
+ {
+ m_pTimeoutTimer = new QTimer();
+ connect(m_pTimeoutTimer,SIGNAL(timeout()),this,SLOT(connectionTimedOut()));
+ m_pTimeoutTimer->start(KVI_OPTION_UINT(KviOption_uintDccSocketTimeout) * 1000,true);
+ }
+
+ // and wait for connect
+ emit inProgress();
+}
+
+
+void KviDccMarshal::snActivated(int)
+{
+ if(m_pTimeoutTimer)
+ {
+ delete m_pTimeoutTimer;
+ m_pTimeoutTimer = 0;
+ }
+
+#ifdef COMPILE_IPV6_SUPPORT
+ struct sockaddr_in6 hostSockAddr6;
+#endif
+ struct sockaddr_in hostSockAddr;
+
+ int size = sizeof(hostSockAddr);
+ struct sockaddr * addr = (struct sockaddr *)&hostSockAddr;
+
+#ifdef COMPILE_IPV6_SUPPORT
+ if(m_bIpV6)
+ {
+ addr = (struct sockaddr *)&hostSockAddr6;
+ size = sizeof(hostSockAddr6);
+ }
+#endif
+
+ if(m_bOutgoing)
+ {
+ // outgoing connection (we have called connect())
+ // Check for errors...
+ int sockError;
+ int iSize=sizeof(int);
+ if(!kvi_socket_getsockopt(m_fd,SOL_SOCKET,SO_ERROR,(void *)&sockError,&iSize))sockError = -1;
+ if(sockError != 0)
+ {
+ //failed
+ if(sockError > 0)sockError = KviError::translateSystemError(sockError);
+ else sockError = KviError_unknownError; //Error 0 ?
+ reset();
+ emit error(sockError);
+ return;
+ }
+ //Succesfully connected...
+ delete m_pSn;
+ m_pSn = 0;
+ // get the local address
+ if(!kvi_socket_getsockname(m_fd,addr,&size))
+ {
+ m_szSecondaryIp = "localhost";
+ m_szSecondaryPort = __tr2qs_ctx("unknown","dcc");
+ } else {
+#ifdef COMPILE_IPV6_SUPPORT
+ if(m_bIpV6)
+ {
+ m_szSecondaryPort.setNum(ntohs(((struct sockaddr_in6 *)addr)->sin6_port));
+ if(!kvi_binaryIpToStringIp_V6(((struct sockaddr_in6 *)addr)->sin6_addr,m_szSecondaryIp))
+ m_szSecondaryIp = "localhost";
+ } else {
+#endif
+ m_szSecondaryPort.setNum(ntohs(((struct sockaddr_in *)addr)->sin_port));
+ if(!kvi_binaryIpToStringIp(((struct sockaddr_in *)addr)->sin_addr,m_szSecondaryIp))
+ m_szSecondaryIp = "localhost";
+#ifdef COMPILE_IPV6_SUPPORT
+ }
+#endif
+ }
+ } else {
+ // Incoming connection
+ int newsock = kvi_socket_accept(m_fd,addr,&size);
+ if(newsock != KVI_INVALID_SOCKET)
+ {
+ // Connected
+ delete m_pSn;
+ m_pSn = 0;
+#ifdef COMPILE_IPV6_SUPPORT
+ if(m_bIpV6)
+ {
+ m_szSecondaryPort.setNum(ntohs(((struct sockaddr_in6 *)addr)->sin6_port));
+ if(!kvi_binaryIpToStringIp_V6(((struct sockaddr_in6 *)addr)->sin6_addr,m_szSecondaryIp))
+ m_szSecondaryIp = __tr2qs_ctx("unknown","dcc");
+ } else {
+#endif
+ m_szSecondaryPort.setNum(ntohs(((struct sockaddr_in *)addr)->sin_port));
+ if(!kvi_binaryIpToStringIp(((struct sockaddr_in *)addr)->sin_addr,m_szSecondaryIp))
+ m_szSecondaryIp = __tr2qs_ctx("unknown","dcc");
+#ifdef COMPILE_IPV6_SUPPORT
+ }
+#endif
+ kvi_socket_close(m_fd);
+ m_fd = newsock;
+ if(!kvi_socket_setNonBlocking(m_fd))
+ {
+ reset();
+ emit error(KviError_asyncSocketFailed);
+ return;
+ }
+
+ } else {
+ // Huh ?.. wait for the next notifier call
+ return;
+ }
+ }
+
+#ifdef COMPILE_SSL_SUPPORT
+ // SSL Handshake needed ?
+ if(m_bUseSSL)
+ {
+ m_pSSL = KviSSLMaster::allocSSL(m_pOutputContext->dccMarshalOutputWindow(),m_fd,m_bOutgoing ? KviSSL::Client : KviSSL::Server,m_pOutputContext->dccMarshalOutputContextString());
+
+ if(m_pSSL)
+ {
+ emit startingSSLHandshake();
+ doSSLHandshake(0);
+ } else {
+ reset();
+ emit error(KviError_SSLError);
+ }
+ return;
+ }
+#endif
+
+ emit connected();
+}
+
+
+void KviDccMarshal::doSSLHandshake(int)
+{
+#ifdef COMPILE_SSL_SUPPORT
+// debug("DO SSL HANDSHAKE");
+ if(m_pSn)
+ {
+ delete m_pSn;
+ m_pSn = 0;
+ }
+
+ if(!m_pSSL)
+ {
+ debug("Ops... I've lost the SSL class ?");
+ reset();
+ emit error(KviError_internalError);
+ return; // ops ?
+ }
+
+ KviSSL::Result r = m_bOutgoing ? m_pSSL->connect() : m_pSSL->accept();
+
+ switch(r)
+ {
+ case KviSSL::Success:
+ // done!
+// debug("EMITTING CONNECTED");
+ emit connected();
+// debug("CONNECTED EMITTED");
+ break;
+ case KviSSL::WantRead:
+ m_pSn = new QSocketNotifier((int)m_fd,QSocketNotifier::Read);
+ QObject::connect(m_pSn,SIGNAL(activated(int)),this,SLOT(doSSLHandshake(int)));
+ m_pSn->setEnabled(true);
+ break;
+ case KviSSL::WantWrite:
+ m_pSn = new QSocketNotifier((int)m_fd,QSocketNotifier::Write);
+ QObject::connect(m_pSn,SIGNAL(activated(int)),this,SLOT(doSSLHandshake(int)));
+ m_pSn->setEnabled(true);
+ break;
+ case KviSSL::RemoteEndClosedConnection:
+ reset();
+ emit error(KviError_remoteEndClosedConnection);
+ break;
+ case KviSSL::SyscallError:
+ {
+ // syscall problem
+ int err = kvi_socket_error();
+ if(kvi_socket_recoverableError(err))
+ {
+ // can recover ? (EAGAIN , EINTR ?)
+ m_pSn = new QSocketNotifier((int)m_fd,QSocketNotifier::Write);
+ QObject::connect(m_pSn,SIGNAL(activated(int)),this,SLOT(doSSLHandshake(int)));
+ m_pSn->setEnabled(true);
+ return;
+ } else {
+ // Declare problems :)
+ reset();
+ emit error(err ? KviError::translateSystemError(err) : KviError_unknownError);
+ }
+ }
+ break;
+ default:
+ {
+ KviStr buffer;
+ while(m_pSSL->getLastErrorString(buffer))emit sslError(buffer.ptr());
+ reset();
+ emit error(KviError_SSLError);
+ }
+ break;
+ }
+#else //!COMPILE_SSL_SUPPORT
+ debug("Ops.. ssl handshake without ssl support!...aborting!");
+ exit(-1);
+#endif //!COMPILE_SSL_SUPPORT
+}
+
+void KviDccMarshal::abort()
+{
+ reset();
+}
+
+void KviDccMarshal::connectionTimedOut()
+{
+ reset();
+ emit error(KviError_connectionTimedOut);
+}
+
+
+#include "m_marshal.moc"
diff --git a/src/modules/dcc/marshal.h b/src/modules/dcc/marshal.h
new file mode 100644
index 00000000..9665e09a
--- /dev/null
+++ b/src/modules/dcc/marshal.h
@@ -0,0 +1,112 @@
+#ifndef _MARSHAL_H_
+#define _MARSHAL_H_
+//
+// File marshal.h
+// Creation date : Sun Sep 17 2000 10:44:20 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_string.h"
+#include "kvi_sockettype.h"
+#include <qobject.h>
+#include <qsocketnotifier.h>
+#include <qtimer.h>
+#include "kvi_inttypes.h"
+
+class KviWindow;
+
+#ifdef COMPILE_SSL_SUPPORT
+ #include "kvi_sslmaster.h"
+#endif
+
+class KviDccMarshal;
+
+class KviDccMarshalOutputContext
+{
+ friend class KviDccMarshal;
+public:
+ KviDccMarshalOutputContext(){};
+ virtual ~KviDccMarshalOutputContext(){};
+protected:
+ virtual KviWindow * dccMarshalOutputWindow() = 0;
+ virtual const char * dccMarshalOutputContextString() = 0;
+};
+
+class KviDccMarshal : public QObject
+{
+ Q_OBJECT
+public:
+ KviDccMarshal(KviDccMarshalOutputContext * ctx);
+ ~KviDccMarshal();
+protected:
+ // DCC DESCRIPTOR
+ QString m_szIp; // Dcc initiator ip address (the one that listens)
+ QString m_szPort; // Dcc initiator port (the one that listens)
+ // other info
+ bool m_bIpV6; // Dcc mode
+ kvi_u32_t m_uPort; // Dcc initiator port
+ bool m_bOutgoing; // true if WE have connected to the remote host (so m_szIp is the remote host ip)
+ QString m_szSecondaryIp; // Ip of the client that has connected to the remote host
+ QString m_szSecondaryPort; // Port of the client that has connected to the remote host
+ // internals
+ kvi_socket_t m_fd; // socket
+ QSocketNotifier * m_pSn;
+ QTimer * m_pTimeoutTimer;
+ bool m_bUseTimeout;
+#ifdef COMPILE_SSL_SUPPORT
+ KviSSL * m_pSSL;
+ bool m_bUseSSL;
+#endif
+ KviDccMarshalOutputContext * m_pOutputContext;
+public:
+ const QString & dccIp() const { return m_szIp; };
+ const QString & dccPort() const { return m_szPort; };
+ const QString & localIp() const { return m_bOutgoing ? m_szSecondaryIp : m_szIp; };
+ const QString & localPort() const { return m_bOutgoing ? m_szSecondaryPort : m_szPort; };
+ const QString & remoteIp() const { return m_bOutgoing ? m_szIp : m_szSecondaryIp; };
+ const QString & remotePort() const { return m_bOutgoing ? m_szPort : m_szSecondaryPort; };
+ int dccListen(const QString &ip,const QString &port,bool bUseTimeout,bool bUseSSL = false);
+ int dccConnect(const char * ip,const char * port,bool bUseTimeout,bool bUseSSL = false);
+ kvi_socket_t releaseSocket();
+#ifdef COMPILE_SSL_SUPPORT
+ KviSSL * releaseSSL();
+#endif
+ void abort();
+private:
+ void reset();
+//#ifdef COMPILE_SSL_SUPPORT
+// bool trySSLCertificate();
+//#endif
+private slots:
+ void doSSLHandshake(int);
+// void doListenSSLHandshake();
+ void snActivated(int);
+ void connectionTimedOut();
+ void doListen();
+ void doConnect();
+signals:
+ void startingSSLHandshake();
+ void sslError(const char * msg);
+ void connected();
+ void inProgress();
+ void error(int);
+};
+
+
+#endif //_MARSHAL_H_
diff --git a/src/modules/dcc/requests.cpp b/src/modules/dcc/requests.cpp
new file mode 100644
index 00000000..e1e18143
--- /dev/null
+++ b/src/modules/dcc/requests.cpp
@@ -0,0 +1,1154 @@
+//=============================================================================
+//
+// File : requests.cpp
+// Creation date : Tue Jul 23 02:44:38 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define _KVI_DEBUG_CHECK_RANGE_
+#include "kvi_debug.h"
+#include "kvi_settings.h"
+#include "kvi_string.h"
+#include "kvi_module.h"
+#include "kvi_sparser.h"
+#include "kvi_locale.h"
+#include "kvi_out.h"
+#include "kvi_console.h"
+#include "kvi_netutils.h"
+#include "kvi_frame.h"
+#include "kvi_console.h"
+
+#include "kvi_error.h"
+#include "kvi_options.h"
+#include "kvi_defaults.h"
+#include "kvi_sharedfiles.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_app.h"
+#include "kvi_ircconnection.h"
+#include "kvi_ircconnectionuserinfo.h"
+
+#include "gsmcodec.h"
+#include "broker.h"
+#include "voice.h"
+#include "utils.h"
+#include "send.h"
+
+#include <qfileinfo.h>
+
+#ifdef COMPILE_ON_WINDOWS
+ // Ugly Windoze compiler...
+ #include "dialogs.h"
+#endif
+
+//#warning "KviOption_boolIgnoreDccChat and other types too"
+
+extern KVIRC_API KviSharedFilesManager * g_pSharedFilesManager;
+extern KviDccBroker * g_pDccBroker;
+
+static void dcc_module_reply_errmsg(KviDccRequest * dcc,const QString& errText)
+{
+ dcc->ctcpMsg->msg->console()->connection()->sendFmtData(
+ "NOTICE %s :%cERRMSG %s%c",
+ dcc->ctcpMsg->msg->console()->connection()->encodeText(dcc->ctcpMsg->pSource->nick()).data(),0x01,
+ dcc->ctcpMsg->msg->console()->connection()->encodeText(errText).data()
+ ,0x01);
+}
+
+static void dcc_module_request_error(KviDccRequest * dcc,const QString& errText)
+{
+ dcc->ctcpMsg->msg->console()->output(KVI_OUT_DCCERROR,
+ __tr2qs_ctx("Unable to process the above request: %Q, %Q","dcc"),
+ &errText,
+ KVI_OPTION_BOOL(KviOption_boolNotifyFailedDccHandshakes) ? &(__tr2qs_ctx("Ignoring and notifying failure","dcc")) : &(__tr2qs_ctx("Ignoring","dcc")));
+
+ if(KVI_OPTION_BOOL(KviOption_boolNotifyFailedDccHandshakes))
+ {
+ QString szError = QString("Sorry, your DCC %1 request can't be satisfied: %2").arg(dcc->szType.ptr()).arg(errText);
+ dcc_module_reply_errmsg(dcc,szError);
+ }
+}
+
+static bool dcc_module_check_concurrent_transfers_limit(KviDccRequest * dcc)
+{
+ if(KVI_OPTION_UINT(KviOption_uintMaxDccSendTransfers) > 0)
+ {
+ unsigned int uTransfers = KviDccFileTransfer::runningTransfersCount();
+ if(uTransfers >= KVI_OPTION_UINT(KviOption_uintMaxDccSendTransfers))
+ {
+ KviStr szError(KviStr::Format,__tr2qs_ctx("Concurrent transfer limit reached (%u of %u transfers running)","dcc"),
+ uTransfers,KVI_OPTION_UINT(KviOption_uintMaxDccSendTransfers));
+ dcc_module_request_error(dcc,szError.ptr());
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool dcc_module_check_limits(KviDccRequest * dcc)
+{
+ if(KVI_OPTION_UINT(KviOption_uintMaxDccSlots) > 0)
+ {
+ unsigned int uWindows = g_pDccBroker->dccWindowsCount();
+ if(uWindows >= KVI_OPTION_UINT(KviOption_uintMaxDccSlots))
+ {
+ KviStr szError(KviStr::Format,__tr2qs_ctx("Slot limit reached (%u slots of %u)","dcc"),
+ uWindows,KVI_OPTION_UINT(KviOption_uintMaxDccSlots));
+ dcc_module_request_error(dcc,szError.ptr());
+ return false;
+ }
+ }
+ if(g_pDccBroker->dccBoxCount() >= 32)
+ {
+ // there are too many pending dcc requests: the user isn't watching....
+ dcc_module_request_error(dcc,__tr2qs_ctx("Too many pending connections","dcc"));
+ return false;
+ }
+ return true;
+}
+
+static void dcc_fill_local_nick_user_host(KviDccDescriptor * d,KviDccRequest * dcc)
+{
+ if(dcc->pConsole->connection())
+ {
+ d->szLocalNick = dcc->pConsole->connection()->userInfo()->nickName();
+ d->szLocalUser = dcc->pConsole->connection()->userInfo()->userName();
+ d->szLocalHost = dcc->pConsole->connection()->userInfo()->hostName();
+ } else {
+ d->szLocalNick = __tr_ctx("unknown","dcc");
+ d->szLocalUser = __tr2qs_ctx("unknown","dcc");
+ d->szLocalHost = __tr2qs_ctx("unknown","dcc");
+ }
+}
+
+static void dcc_module_set_dcc_type(KviDccDescriptor * d,const char * szBaseType)
+{
+ d->szType = szBaseType;
+#ifdef COMPILE_SSL_SUPPORT
+ if(d->bIsSSL)d->szType.prepend('S');
+#endif
+ if(d->bIsTdcc)d->szType.prepend('T');
+}
+
+
+static bool dcc_module_normalize_target_data(KviDccRequest * dcc,KviStr &ipaddr,KviStr &port)
+{
+ if(!port.isUnsignedNum())
+ {
+ if(!dcc->ctcpMsg->msg->haltOutput())
+ {
+ KviStr szError(KviStr::Format,__tr2qs_ctx("Invalid port number %s","dcc"),port.ptr());
+ dcc_module_request_error(dcc,szError.ptr());
+ }
+ return false;
+ }
+
+ struct in_addr addr;
+
+ if(ipaddr.isUnsignedNum())
+ {
+ addr.s_addr = htonl((unsigned long)ipaddr.toULong());
+ QString tmp;
+ if(!kvi_binaryIpToStringIp(addr,tmp))
+ {
+ if(!dcc->ctcpMsg->msg->haltOutput())
+ {
+ KviStr szError(KviStr::Format,__tr2qs_ctx("Invalid IP address in old format %s","dcc"),ipaddr.ptr());
+ dcc_module_request_error(dcc,szError.ptr());
+ }
+ return false;
+ }
+ ipaddr = tmp;
+ } else {
+ if(!kvi_stringIpToBinaryIp(ipaddr,&addr))
+ {
+#ifdef COMPILE_IPV6_SUPPORT
+ struct in6_addr addr6;
+ if(kvi_stringIpToBinaryIp_V6(ipaddr,&addr6))
+ {
+ dcc->bIpV6 = true;
+ return true; // IPV6 address.
+ }
+#endif
+ if(!dcc->ctcpMsg->msg->haltOutput())
+ {
+ KviStr szError(KviStr::Format,__tr2qs_ctx("Invalid IP address %s","dcc"),ipaddr.ptr());
+ dcc_module_request_error(dcc,szError.ptr());
+ }
+ return false;
+ }
+ }
+ return true;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// CHAT
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+static void dccModuleParseDccChat(KviDccRequest *dcc)
+{
+ //
+ // We have received a DCC CHAT request in the following form:
+ //
+ // DCC CHAT chat <ipaddress> <port>
+ //
+ // This means that we're requested to setup an ACTIVE chat connection
+ // ... Easy task :)
+ //
+ // Anybody understands the meaning of the secondo "chat" in there ?
+ // It was meant to simplify the parsing ? :DDD
+ //
+ // There is a mIrc extension that allows <port> to be 0
+ // and adds a last parameter that seems to be a random number (thnx YaP :)
+ // that is used to keep track of the connection.
+ // This extension is used by firewalled machines to initiate a DCC CHAT:
+ // the receiving side should respond with a DCC CHAT offer
+ // with the same random number appended, and then should listen for a connection.
+ //
+ // when a zero port request is initiated by another party we get
+ //
+ // DCC CHAT chat <fakeipaddress> 0 <tag>
+ //
+ // and we reply with
+ //
+ // DCC CHAT chat <ourip> <ourport> <tag>
+ //
+ // when a zero port request is initiated by us we send out
+ //
+ // DCC CHAT chat <fakeipaddress> 0 <tag>
+ //
+ // and we get
+ //
+ // DCC CHAT chat <remoteip> <remoteport> <tag>
+ //
+ // Thus if there is a <tag> and the port is 0, then the remote party
+ // wanted to estabilish a dcc with us and wants us to listen, but if the port is nonzero then
+ // we have sent out a zero port request and the remote party acked it
+ // thus we have to connect instead!
+ //
+
+ // First of all we check the dcc slot limits
+ if(!dcc_module_check_limits(dcc))return;
+
+ // Then we check the target host data
+ if(!dcc_module_normalize_target_data(dcc,dcc->szParam2,dcc->szParam3))return;
+
+ if(!kvi_strEqualCI(dcc->szParam1.ptr(),"chat"))
+ {
+ if(!dcc->ctcpMsg->msg->haltOutput())
+ {
+ dcc->ctcpMsg->msg->console()->output(KVI_OUT_DCCMSG,
+ __tr2qs_ctx("The above request is broken: The second parameter is '%s' and should be 'chat', trying to continue","dcc"),dcc->szParam1.ptr());
+ }
+ }
+
+ KviStr szExtensions = dcc->szType;
+ szExtensions.cutRight(4); // cut off CHAT
+
+#ifdef COMPILE_SSL_SUPPORT
+ bool bSSLExtension = szExtensions.contains('S',false);
+#else //!COMPILE_SSL_SUPPORT
+ if(szExtensions.contains('S',false))
+ {
+ dcc_module_request_error(dcc,__tr2qs_ctx("This executable has been compiled without SSL support, the SSL extension to DCC CHAT is not available","dcc"));
+ return;
+ }
+#endif //!COMPILE_SSL_SUPPORT
+
+ KviDccDescriptor * d = new KviDccDescriptor(dcc->pConsole);
+
+ d->szNick = dcc->ctcpMsg->pSource->nick();
+ d->szUser = dcc->ctcpMsg->pSource->username();
+ d->szHost = dcc->ctcpMsg->pSource->host();
+
+ dcc_fill_local_nick_user_host(d,dcc);
+
+ d->szIp = dcc->szParam2.ptr();
+ d->szPort = dcc->szParam3.ptr();
+
+
+ if(dcc->szParam4.hasData())
+ {
+ // zero port tag ?
+ if(d->szPort == "0")
+ {
+ // zero port request
+ if(KVI_OPTION_BOOL(KviOption_boolDccSendFakeAddressByDefault))
+ {
+ d->szFakeIp = KVI_OPTION_STRING(KviOption_stringDefaultDccFakeAddress);
+ if(d->szFakeIp.isEmpty())KVI_OPTION_BOOL(KviOption_boolDccSendFakeAddressByDefault) = false;
+ }
+ d->setZeroPortRequestTag(dcc->szParam4.ptr());
+ QString tmp;
+ if(!dcc_kvs_get_listen_ip_address(0,d->console(),tmp))d->szListenIp = "0.0.0.0";
+ else d->szListenIp=tmp;
+ d->szListenPort = "0"; // any port is OK
+ d->bAutoAccept = KVI_OPTION_BOOL(KviOption_boolAutoAcceptDccChat);
+ d->bActive = false; // we must listen then...
+ } else {
+ // zero port acknowledge
+ // check if this is a tag that we have sent out
+ QString szTag = QString(dcc->szParam4.ptr());
+ KviDccZeroPortTag * t = g_pDccBroker->findZeroPortTag(szTag);
+ if(!t)
+ {
+ // hum.. not our tag
+
+ // FIXME: As segnaled by PRAEDO, ezbounce seems to send a fourth parameter in response to /quote ezb log
+ // Pragma: That's a bug in ezbounce, it sends the filesize of the log as a DCC CHAT parameter...
+ // The author probably copied and pasted the CTCP line from DCC SEND and forgot to remove the filesize.
+ // We *could* add an option to ignore the last parameter and treat it as a standard dcc chat
+ // request, but since we don't encourage bugs, we don't do it :D
+ // Mail me at pragma at kvirc dot net if you really think it's necessary.
+ dcc->ctcpMsg->msg->console()->output(KVI_OUT_DCCMSG,
+ __tr2qs_ctx("The above request is broken: it looks like a zero port tag acknowledge but I have either never seen this tag or it was sent more than 120 seconds ago","dcc"));
+ dcc_module_request_error(dcc,__tr2qs_ctx("It seems that I haven't requested this dcc chat","dcc"));
+ delete d;
+ return;
+ } else {
+ g_pDccBroker->removeZeroPortTag(szTag);
+ }
+
+ d->bAutoAccept = true; // auto-accept it (we have sent it out)
+ d->bActive = true;
+ }
+ } else {
+ d->bAutoAccept = KVI_OPTION_BOOL(KviOption_boolAutoAcceptDccChat);
+ d->bActive = true; // we have to connct (standard active chat)
+ }
+
+#ifdef COMPILE_SSL_SUPPORT
+ d->bIsSSL = bSSLExtension;
+#endif
+
+ dcc_module_set_dcc_type(d,"CHAT");
+ d->triggerCreationEvent();
+
+ g_pDccBroker->handleChatRequest(d);
+}
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// SEND
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+static void dccModuleParseDccRecv(KviDccRequest * dcc);
+
+static void dccModuleParseDccSend(KviDccRequest *dcc)
+{
+//#warning "Ignore files depending on file type ? (MediaType ?)"
+ //
+ // We have received a DCC SEND request in the following form
+ //
+ // DCC [ST]SEND <filename> <ipaddress> <port> <filesize>
+ //
+ // Now the things are a bit tricky... we eventually can
+ // reply with a DCC RESUME and receive a DCC ACCEPT then
+ // The format of these requests is:
+ //
+ // DCC RESUME <filename> <port> <resumepos>
+ // ACCEPT <filename> <port> <resumepos>
+ //
+ // There is a mIrc extension that allows <port> to be 0
+ // and adds a last parameter that seems to be a random number (thnx YaP :)
+ // that is used to keep track of the connection.
+ // This extension is used by firewalled machines to initiate a DCC SEND:
+ // the receiving side should respond with a DCC SEND offer
+ // with the same random number appended, listen for a connection, and receive the file
+ // instead of sending it.
+ //
+ // when a zero port request is initiated by another party we get
+ // DCC SEND <filename> <fakeipaddress> 0 <filesize> <tag>
+ // if (and only if) we want to resume we reply with
+ // DCC RESUME <filename> 0 <resumesize> <tag>
+ // in this case the remote part replies again with
+ // DCC ACCEPT <filename> 0 <resumesize> <tag>
+ // and we finally reply with
+ // DCC SEND <filename> <ourip> <ourport> <filesize> <tag>
+ //
+ // when a zero port request is initiated by us we send out
+ // DCC SEND <filename> <fakeipaddress> 0 <filesize> <tag>
+ // and if the remote party wants to resume then we get
+ // DCC RESUME <filename> 0 <resumesize> <tag>
+ // and we eventually reply with
+ // DCC ACCEPT <filename> 0 <resumesize> <tag>
+ // and we finally get
+ // DCC SEND <filename> <remoteip> <remoteport> <filesize> <tag>
+ //
+ // Thus if there is a <tag> and the port is 0, then the remote party
+ // is trying to send a file to us, but if the port is nonzero then
+ // we have sent out a zero port request and the remote party acked it
+ //
+
+ if((!kvi_strEqualCS(dcc->szParam3.ptr(),"0")) && dcc->szParam5.hasData())
+ {
+ // DCC SEND <filename> <remoteip> <remoteport> <filesize> <tag>
+ // zero port acknowledge: treat as a RECV that should look like
+ // DCC [TS]RECV <filename> <remoteip> <remoteport> <resume-filesize>
+ // but since we have stored the sharedfile with the name <tag>
+ // we do exchange the params :)
+
+ KviDccZeroPortTag * t = g_pDccBroker->findZeroPortTag(dcc->szParam5.ptr());
+ if(t)
+ {
+ dcc->szParam4.sprintf("%u",t->m_uResumePosition);
+ g_pDccBroker->removeZeroPortTag(dcc->szParam5.ptr());
+ } else {
+ // this should never happen since we always add
+ // a zero port tag for out outgoing requests
+ // but well... maybe the user did something behing our back...
+ dcc->szParam4 = "0"; // no resume possible in this case
+ }
+
+ // swap the tag and the filename (we have added a fileoffer with this tag)
+ dcc->szParam1 = dcc->szParam5;
+ dcc->szParam5 = "";
+
+ dccModuleParseDccRecv(dcc);
+ return;
+ }
+
+ // First of all we check the transfer limits
+ dcc->szParam1=dcc->pConsole->decodeText(dcc->szParam1);
+ if(!dcc_module_check_limits(dcc))return;
+ if(!dcc_module_check_concurrent_transfers_limit(dcc))return;
+
+ // Then we ensure that the data that the remote end has sent are valid
+ if(!dcc_module_normalize_target_data(dcc,dcc->szParam2,dcc->szParam3))return;
+
+ if(!(dcc->szParam4.isUnsignedNum()))
+ {
+ if(!dcc->ctcpMsg->msg->haltOutput())
+ {
+ dcc->ctcpMsg->msg->console()->output(KVI_OUT_DCCMSG,
+ __tr2qs_ctx("The above request is broken: The fourth parameter should be the file size but does not appear to be an unsigned number, trying to continue","dcc"),dcc->szParam4.ptr());
+ }
+ dcc->szParam4 = __tr2qs_ctx("<unknown size>","dcc");
+ }
+
+ if(dcc->szParam1.contains('/'))
+ {
+ if(!dcc->ctcpMsg->msg->haltOutput())
+ {
+ dcc->ctcpMsg->msg->console()->output(KVI_OUT_DCCMSG,
+ __tr2qs_ctx("The above request is broken: The filename contains path components, stripping the leading path and trying to continue","dcc"),dcc->szParam1.ptr());
+ }
+ dcc->szParam1.cutToLast('/');
+ }
+
+ KviStr szExtensions = dcc->szType;
+ szExtensions.cutRight(4); // cut off SEND
+
+ bool bTurboExtension = szExtensions.contains('T',false);
+#ifdef COMPILE_SSL_SUPPORT
+ bool bSSLExtension = szExtensions.contains('S',false);
+#else //!COMPILE_SSL_SUPPORT
+ if(szExtensions.contains('S',false))
+ {
+ dcc_module_request_error(dcc,__tr2qs_ctx("This executable has been compiled without SSL support, the SSL extension to DCC SEND is not available","dcc"));
+ return;
+ }
+#endif //!COMPILE_SSL_SUPPORT
+
+ KviDccDescriptor * d = new KviDccDescriptor(dcc->pConsole);
+ d->szNick = dcc->ctcpMsg->pSource->nick();
+ d->szUser = dcc->ctcpMsg->pSource->username();
+ d->szHost = dcc->ctcpMsg->pSource->host();
+ dcc_fill_local_nick_user_host(d,dcc);
+
+ d->szIp = dcc->szParam2.ptr();
+ d->szPort = dcc->szParam3.ptr();
+ d->szFileName = dcc->szParam1.ptr();
+ d->szFileSize = dcc->szParam4.ptr();
+
+ if(d->szPort=="0" && dcc->szParam5.hasData())
+ {
+ if(KVI_OPTION_BOOL(KviOption_boolDccSendFakeAddressByDefault))
+ {
+ d->szFakeIp = KVI_OPTION_STRING(KviOption_stringDefaultDccFakeAddress);
+ if(d->szFakeIp.isEmpty())KVI_OPTION_BOOL(KviOption_boolDccSendFakeAddressByDefault) = false;
+ }
+ d->setZeroPortRequestTag(dcc->szParam5.ptr());
+ QString tmp;
+ if(!dcc_kvs_get_listen_ip_address(0,d->console(),tmp))d->szListenIp = "0.0.0.0";
+ else d->szListenIp=QString(tmp);
+ d->szListenPort = "0"; // any port is OK
+ d->bSendRequest = true;
+ d->szLocalFileSize = d->szFileSize;
+ }
+
+ d->bActive = !d->isZeroPortRequest(); // we have to connect unless it is a zero port request
+
+ d->bResume = false;
+ d->bRecvFile = true;
+ d->bIsTdcc = bTurboExtension;
+ d->bNoAcks = d->bIsTdcc;
+#ifdef COMPILE_SSL_SUPPORT
+ d->bIsSSL = bSSLExtension;
+#endif
+ d->bOverrideMinimize = false;
+ d->bAutoAccept = KVI_OPTION_BOOL(KviOption_boolAutoAcceptDccSend);
+
+ d->bIsIncomingAvatar = g_pApp->findPendingAvatarChange(dcc->pConsole,d->szNick,d->szFileName);
+ dcc_module_set_dcc_type(d,"RECV");
+ if(KVI_OPTION_BOOL(KviOption_boolAutoAcceptIncomingAvatars))d->bAutoAccept = d->bAutoAccept || d->bIsIncomingAvatar;
+ d->triggerCreationEvent();
+
+ g_pDccBroker->recvFileManage(d);
+}
+
+static void dccModuleParseDccAccept(KviDccRequest *dcc)
+{
+ // this is usually DCC ACCEPT <filename> <port> <resumesize>
+ // but may be also
+ // DCC ACCEPT <filename> 0 <resumesize> <tag>
+ if(!g_pDccBroker->handleResumeAccepted(dcc->szParam1.ptr(),dcc->szParam2.ptr(),dcc->szParam4.ptr()))
+ {
+//#warning "IF KviOption_boolReplyCtcpErrmsgOnInvalidAccept..."
+ if(!dcc->ctcpMsg->msg->haltOutput())
+ {
+ KviStr szError(KviStr::Format,__tr2qs_ctx("Can't proceed with DCC RECV: Transfer not initiated for file %s on port %s","dcc"),dcc->szParam1.ptr(),dcc->szParam2.ptr());
+ dcc_module_request_error(dcc,szError.ptr());
+ }
+ }
+}
+
+static void dccModuleParseDccResume(KviDccRequest *dcc)
+{
+ // This is usually RESUME <filename> <port> <resumesize>
+
+ // when a zero port request is initiated by us we send out
+ // DCC SEND <filename> <fakeipaddress> 0 <filesize> <tag>
+ // and if the remote party wants to resume then we get
+ // DCC RESUME <filename> 0 <resumesize> <tag>
+ // and we eventually reply with
+ // DCC ACCEPT <filename> 0 <resumesize> <tag>
+ // and we finally get
+ // DCC SEND <filename> <remoteip> <remoteport> <filesize> <tag>
+
+ bool bOk;
+ unsigned int filePos = dcc->szParam3.toUInt(&bOk);
+ if(!bOk)
+ {
+ if(!dcc->ctcpMsg->msg->haltOutput())
+ {
+ KviStr szError(KviStr::Format,__tr2qs_ctx("Invalid resume position argument '%s'","dcc"),dcc->szParam3.ptr());
+ dcc_module_request_error(dcc,szError.ptr());
+ }
+ return;
+ }
+
+ if(!g_pDccBroker->handleResumeRequest(dcc,dcc->szParam1.ptr(),dcc->szParam2.ptr(),filePos,dcc->szParam4.ptr()))
+ {
+//#warning "IF KviOption_boolReplyCtcpErrmsgOnInvalidResume..."
+ if(!dcc->ctcpMsg->msg->haltOutput())
+ {
+ KviStr szError(KviStr::Format,
+ __tr2qs_ctx("Can't proceed with DCC SEND: Transfer not initiated for file %s on port %s, or invalid resume size","dcc"),
+ dcc->szParam1.ptr(),dcc->szParam2.ptr());
+ dcc_module_request_error(dcc,szError.ptr());
+ }
+ }
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// RECV
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+static void dccModuleParseDccRecv(KviDccRequest * dcc)
+{
+ // DCC [TS]RECV <filename> <ipaddr> <port> <resume-filesize>
+ if(!dcc_module_check_limits(dcc))return;
+ if(!dcc_module_check_concurrent_transfers_limit(dcc))return;
+
+ if(!dcc_module_normalize_target_data(dcc,dcc->szParam2,dcc->szParam3))return;
+
+ if(!(dcc->szParam4.isUnsignedNum()))
+ {
+ if(!dcc->ctcpMsg->msg->haltOutput())
+ {
+ dcc->ctcpMsg->msg->console()->outputNoFmt(KVI_OUT_DCCMSG,
+ __tr2qs_ctx("The above request has resume file size missing, assuming a resume file size of 0","dcc"));
+ }
+ dcc->szParam4 = "0";
+ }
+
+ if(dcc->szParam1.contains('/'))
+ {
+ if(!dcc->ctcpMsg->msg->haltOutput())
+ {
+ dcc->ctcpMsg->msg->console()->output(KVI_OUT_DCCMSG,
+ __tr2qs_ctx("The above request is broken: The filename contains path components, stripping the leading path and trying to continue","dcc"),dcc->szParam1.ptr());
+ }
+ dcc->szParam1.cutToLast('/');
+ }
+
+ KviStr szExtensions = dcc->szType;
+ szExtensions.cutRight(4); // cut off RECV
+
+ bool bTurboExtension = szExtensions.contains('T',false);
+#ifdef COMPILE_SSL_SUPPORT
+ bool bSSLExtension = szExtensions.contains('S',false);
+#else //!COMPILE_SSL_SUPPORT
+ if(szExtensions.contains('S',false))
+ {
+ dcc_module_request_error(dcc,__tr2qs_ctx("This executable has been compiled without SSL support, the SSL extension to DCC RECV is not available","dcc"));
+ return;
+ }
+#endif //!COMPILE_SSL_SUPPORT
+
+ // If we have a file offer for this...do it automatically
+ KviSharedFile * o = g_pSharedFilesManager->lookupSharedFile(dcc->szParam1.ptr(),dcc->ctcpMsg->pSource,0);
+ if(o)
+ {
+
+ unsigned int uResumeSize = dcc->szParam4.toUInt(); // this will NEVER fail
+ if(uResumeSize >= o->fileSize())
+ {
+ // senseless request
+ KviStr szError(KviStr::Format,
+ __tr2qs_ctx("Invalid RECV request: Position %u is is larger than file size","dcc"),uResumeSize);
+ dcc_module_request_error(dcc,szError.ptr());
+ return;
+ }
+
+ // ok...we have requested this send
+// #warning "Maybe remove this file offer now ?"
+ KviDccDescriptor * d = new KviDccDescriptor(dcc->pConsole);
+
+ d->szNick = dcc->ctcpMsg->pSource->nick();
+ d->szUser = dcc->ctcpMsg->pSource->user();
+ d->szHost = dcc->ctcpMsg->pSource->host();
+
+ d->szFileName = dcc->szParam1.ptr();
+ d->szFileSize = dcc->szParam4.ptr();
+
+ //d->bResume = false; // This is actually useless
+
+ d->szLocalFileName = o->absFilePath();
+ d->szLocalFileSize.setNum(o->fileSize()); // Should we look it up again ?
+
+
+ d->bRecvFile = false;
+ d->bNoAcks = bTurboExtension;
+
+ d->bAutoAccept = true;
+ d->bIsIncomingAvatar = false;
+
+ d->bIsTdcc = bTurboExtension;
+#ifdef COMPILE_SSL_SUPPORT
+ d->bIsSSL = bSSLExtension;
+#endif
+
+ d->bOverrideMinimize = false;
+
+ // We know everything
+ dcc_fill_local_nick_user_host(d,dcc);
+
+
+ d->bDoTimeout = true;
+
+ d->szIp = dcc->szParam2.ptr();
+ d->szPort = dcc->szParam3.ptr();
+
+ d->bActive = true;
+ dcc_module_set_dcc_type(d,"SEND");
+ d->triggerCreationEvent();
+ g_pDccBroker->sendFileExecute(0,d);
+
+ return;
+
+ } else {
+
+ dcc->ctcpMsg->msg->console()->output(KVI_OUT_DCCMSG,
+ __tr2qs_ctx("%Q [%Q@%Q] is ready to receive the file \"%s\"","dcc"),
+ &(dcc->ctcpMsg->pSource->nick()),
+ &(dcc->ctcpMsg->pSource->username()),
+ &(dcc->ctcpMsg->pSource->host()),
+ dcc->szParam1.ptr());
+ dcc->ctcpMsg->msg->console()->output(KVI_OUT_DCCMSG,
+ __tr2qs_ctx("The remote client is listening on interface %s and port %s","dcc"),dcc->szParam2.ptr(),dcc->szParam3.ptr());
+ KviStr szSwitches = "-c";
+ if(bTurboExtension)szSwitches.prepend("-t ");
+#ifdef COMPILE_SSL_SUPPORT
+ if(bSSLExtension)szSwitches.prepend("-s ");
+#endif
+ dcc->ctcpMsg->msg->console()->output(KVI_OUT_DCCMSG,
+ __tr2qs_ctx("Use %c\r![!dbl]dcc.send %s -i=%s -p=%s %Q\r/dcc.send %s -i=%s -p=%s %Q\r%c to send the file (or double-click on the socket)","dcc"),
+ KVI_TEXT_BOLD,
+ szSwitches.ptr(),
+ dcc->szParam2.ptr(),dcc->szParam3.ptr(),&(dcc->ctcpMsg->pSource->nick()),
+ szSwitches.ptr(),
+ dcc->szParam2.ptr(),dcc->szParam3.ptr(),&(dcc->ctcpMsg->pSource->nick()),
+ KVI_TEXT_BOLD);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// RSEND
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+static void dccModuleParseDccRSend(KviDccRequest *dcc)
+{
+ // DCC RSEND <filename> <filesize>
+//#warning "Ignore files depending on file type ? (MediaType ?)"
+ //
+ // We have received a DCC RSEND request in the following form
+ //
+ // DCC [ST]RSEND <filename> <filesize>
+ //
+ dcc->szParam1 = dcc->pConsole->decodeText(dcc->szParam1);
+ if(!dcc_module_check_limits(dcc))return;
+ if(!dcc_module_check_concurrent_transfers_limit(dcc))return;
+
+ if(!(dcc->szParam2.isUnsignedNum()))
+ {
+ if(!dcc->ctcpMsg->msg->haltOutput())
+ {
+ dcc->ctcpMsg->msg->console()->output(KVI_OUT_DCCMSG,
+ __tr2qs_ctx("The above request is broken: The fourth parameter should be the file size but does not appear to be an unsigned number; trying to continue","dcc"),dcc->szParam2.ptr());
+ }
+ dcc->szParam2 = __tr_ctx("<unknown size>","dcc");
+ }
+
+ if(dcc->szParam1.contains('/'))
+ {
+ if(!dcc->ctcpMsg->msg->haltOutput())
+ {
+ dcc->ctcpMsg->msg->console()->output(KVI_OUT_DCCMSG,
+ __tr2qs_ctx("The above request is broken: The filename contains path components, stripping the leading path and trying to continue","dcc"),dcc->szParam1.ptr());
+ }
+ dcc->szParam1.cutToLast('/');
+ }
+
+ KviStr szExtensions = dcc->szType;
+ szExtensions.cutRight(4); // cut off SEND
+
+ bool bTurboExtension = szExtensions.contains('T',false);
+#ifdef COMPILE_SSL_SUPPORT
+ bool bSSLExtension = szExtensions.contains('S',false);
+#else //!COMPILE_SSL_SUPPORT
+ if(szExtensions.contains('S',false))
+ {
+ dcc_module_request_error(dcc,__tr2qs_ctx("This executable has been compiled without SSL support, the SSL extension to DCC RSEND is not available","dcc"));
+ return;
+ }
+#endif //!COMPILE_SSL_SUPPORT
+
+//#warning "When behind a firewall, we should reply an error message and avoid setting up the listening connection"
+
+ KviDccDescriptor * d = new KviDccDescriptor(dcc->pConsole);
+ d->szNick = dcc->ctcpMsg->pSource->nick();
+ d->szUser = dcc->ctcpMsg->pSource->username();
+ d->szHost = dcc->ctcpMsg->pSource->host();
+ d->szIp = __tr2qs_ctx("(unknown)","dcc");
+ d->szPort = d->szIp;
+ QString tmp;
+ if(!dcc_kvs_get_listen_ip_address(0,d->console(),tmp))
+ {
+ d->console()->output(KVI_OUT_DCCMSG,
+ __tr2qs_ctx("No suitable interface to listen on, trying to continue anyway...","dcc"));
+ d->szListenIp = "0.0.0.0";
+ } else
+ d->szListenIp=QString(tmp);
+
+ d->szListenPort = "0";
+ dcc_fill_local_nick_user_host(d,dcc);
+
+
+ d->szFileName = dcc->szParam1.ptr();
+ d->szFileSize = dcc->szParam2.ptr();
+ d->bActive = false; // we have to listen!
+ d->bResume = false;
+ d->bRecvFile = true; // we have to receive the file!
+
+#ifdef COMPILE_SSL_SUPPORT
+ d->bIsSSL = bSSLExtension;
+#endif
+ d->bIsTdcc = bTurboExtension;
+ d->bSendRequest = true; // we have to send the [ST]RECV request back
+ d->bNoAcks = d->bIsTdcc;
+ d->bOverrideMinimize = false;
+ d->bAutoAccept = KVI_OPTION_BOOL(KviOption_boolAutoAcceptDccSend);
+ d->bIsIncomingAvatar = g_pApp->findPendingAvatarChange(dcc->pConsole,d->szNick.utf8().data(),d->szFileName.utf8().data());
+
+ if(KVI_OPTION_BOOL(KviOption_boolDccSendFakeAddressByDefault))
+ {
+ d->szFakeIp = KVI_OPTION_STRING(KviOption_stringDefaultDccFakeAddress);
+ if(d->szFakeIp.isEmpty())KVI_OPTION_BOOL(KviOption_boolDccSendFakeAddressByDefault) = false;
+ }
+
+ if(KVI_OPTION_BOOL(KviOption_boolAutoAcceptIncomingAvatars))d->bAutoAccept = d->bAutoAccept || d->bIsIncomingAvatar;
+
+ dcc_module_set_dcc_type(d,"RECV");
+ d->triggerCreationEvent();
+ g_pDccBroker->recvFileManage(d);
+}
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// GET
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+static void dccModuleParseDccGet(KviDccRequest *dcc)
+{
+ // DCC [TS]GET <filename> [filesize]
+ // -> DCC [TS]SEND <filename> <ipaddr> <port> <filesize>
+ // ...
+ dcc->szParam1=dcc->pConsole->decodeText(dcc->szParam1);
+ bool bOk;
+ unsigned int uSize = dcc->szParam2.toUInt(&bOk);
+ if(!bOk)uSize = 0;
+
+ if(!dcc_module_check_limits(dcc))return;
+ if(!dcc_module_check_concurrent_transfers_limit(dcc))return;
+
+ KviStr szExtensions = dcc->szType;
+ szExtensions.cutRight(3); // cut off GET
+
+ bool bTurboExtension = szExtensions.contains('T',false);
+#ifdef COMPILE_SSL_SUPPORT
+ bool bSSLExtension = szExtensions.contains('S',false);
+#else //!COMPILE_SSL_SUPPORT
+ if(szExtensions.contains('S',false))
+ {
+ dcc_module_request_error(dcc,__tr2qs_ctx("This executable has been compiled without SSL support, the SSL extension to DCC GET is not available","dcc"));
+ return;
+ }
+#endif //!COMPILE_SSL_SUPPORT
+
+ KviSharedFile * o = g_pSharedFilesManager->lookupSharedFile(dcc->szParam1.ptr(),dcc->ctcpMsg->pSource,uSize);
+ if(!o)
+ {
+ if(!dcc->ctcpMsg->msg->haltOutput())
+ {
+ KviStr szError(KviStr::Format,
+ __tr2qs_ctx("No file offer named '%s' (with size %s) available for %Q [%Q@%Q]","dcc"),
+ dcc->szParam1.ptr(),uSize > 0 ? dcc->szParam2.ptr() : __tr_ctx("\"any\"","dcc"),
+ &(dcc->ctcpMsg->pSource->nick()),
+ &(dcc->ctcpMsg->pSource->username()),
+ &(dcc->ctcpMsg->pSource->host()));
+ dcc_module_request_error(dcc,szError.ptr());
+ }
+ return;
+ }
+
+//#warning "IF NOT IGNORE DCC GET!"
+
+//#warning "CREATE IT MINIMIZED ETC..."
+//#warning "MAYBE USE A DIALOG TO ACCEPT THE REQUEST ?"
+//#warning "DO NOT ACCEPT /etc/* requests..."
+
+ if(KVI_OPTION_BOOL(KviOption_boolCantAcceptIncomingDccConnections))
+ {
+ // we have to use DCC RSEND , otherwise it will not work
+ KviStr szSubproto("RSEND");
+ szSubproto.prepend(szExtensions);
+
+
+ QString szFileName = QFileInfo(o->absFilePath()).fileName();
+ if(o->name() != szFileName)
+ {
+ // BUG
+ // If the file offer was added with a name that is senseless (like "mediaXYZ" for an *.mp3 file)
+ // then we would be going to RSEND that name here: the remote user woulnd't be
+ // able to recognize the file.
+ // Here we add another temporary offer with the right filename.
+
+ // now add a file offer , so he we will accept it automatically
+ // 120 secs is a reasonable timeout
+ QString szMask;
+ dcc->ctcpMsg->pSource->mask(szMask,KviIrcMask::NickUserHost);
+
+ KviSharedFile * pOld = o;
+ o = g_pSharedFilesManager->addSharedFile(szFileName,o->absFilePath(),szMask,120);
+ if(!o)o = pOld; // give up (FIXME: should we notify that ?)
+ }
+
+ if(!dcc->ctcpMsg->msg->haltOutput())
+ {
+ dcc->ctcpMsg->msg->console()->output(KVI_OUT_DCCMSG,
+ __tr2qs_ctx("Accepting file request from %Q [%Q@%Q] for '%s' (real file: %Q), offering DCC %s since we can't accept incoming connections (user option)","dcc"),
+ &(dcc->ctcpMsg->pSource->nick()),
+ &(dcc->ctcpMsg->pSource->username()),
+ &(dcc->ctcpMsg->pSource->host()),dcc->szParam1.ptr(),
+ &(o->absFilePath()),szSubproto.ptr());
+ }
+
+ dcc->pConsole->connection()->sendFmtData("PRIVMSG %s :%cDCC %s %s %u%c",
+ dcc->pConsole->connection()->encodeText(dcc->ctcpMsg->pSource->nick()).data(),
+ 0x01,szSubproto.ptr(),
+ dcc->pConsole->connection()->encodeText(dcc->szParam1.ptr()).data(),o->fileSize(),0x01);
+ return;
+ }
+
+
+ KviDccDescriptor * d = new KviDccDescriptor(dcc->pConsole);
+ d->szNick = dcc->ctcpMsg->pSource->nick();
+ d->szLocalFileName = o->absFilePath();
+ d->szUser = dcc->ctcpMsg->pSource->username();
+ d->szHost = dcc->ctcpMsg->pSource->host();
+ d->bRecvFile = false;
+ dcc_fill_local_nick_user_host(d,dcc);
+
+ QString tmp;
+ if(!dcc_kvs_get_listen_ip_address(0,d->console(),tmp))
+ {
+ d->console()->output(KVI_OUT_DCCMSG,
+ __tr2qs_ctx("No suitable interface to listen on, trying to continue anyway...","dcc"));
+ d->szListenIp = "0.0.0.0";
+ } else
+ d->szListenIp=QString(tmp);
+//#warning "DO STH WITH THIS PORT (HOW TO SPECIFY IT ?)"
+ d->szListenPort = "0"; // any port is ok
+
+ if(KVI_OPTION_BOOL(KviOption_boolDccSendFakeAddressByDefault))
+ {
+ d->szFakeIp = KVI_OPTION_STRING(KviOption_stringDefaultDccFakeAddress);
+ if(d->szFakeIp.isEmpty())KVI_OPTION_BOOL(KviOption_boolDccSendFakeAddressByDefault) = false;
+ }
+
+ d->bDoTimeout = true;
+ d->szIp = __tr2qs_ctx("(unknown)","dcc");
+ d->szPort = d->szIp;
+ d->bActive = false;
+ d->bSendRequest = true;
+ d->bIsTdcc = bTurboExtension;
+#ifdef COMPILE_SSL_SUPPORT
+ d->bIsSSL = bSSLExtension;
+#endif
+ d->bNoAcks = d->bIsTdcc;
+ d->bOverrideMinimize = false;
+
+ dcc_module_set_dcc_type(d,"SEND");
+
+ if(!dcc->ctcpMsg->msg->haltOutput())
+ {
+ dcc->ctcpMsg->msg->console()->output(KVI_OUT_DCCMSG,
+ __tr2qs_ctx("Accepting file request from %Q [%Q@%Q] for '%s' (real file: %Q), offering DCC %Q","dcc"),
+ &(dcc->ctcpMsg->pSource->nick()),
+ &(dcc->ctcpMsg->pSource->username()),
+ &(dcc->ctcpMsg->pSource->host()),
+ dcc->szParam1.ptr(),
+ &(o->absFilePath()),&(d->szType));
+ }
+ d->triggerCreationEvent();
+ g_pDccBroker->sendFileExecute(0,d);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// VOICE
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+static void dccModuleParseDccVoice(KviDccRequest *dcc)
+{
+ //
+ // We have received a DCC VOICE request in the following form:
+ //
+ // DCC VOICE codec <ipaddress> <port> <sample-rate>
+ //
+ // This means that we're requested to setup an ACTIVE voice connection
+ // ... Easy task :)
+ //
+
+ if(!dcc_module_check_limits(dcc))return;
+
+ if(!dcc_module_normalize_target_data(dcc,dcc->szParam2,dcc->szParam3))return;
+
+#ifdef COMPILE_DISABLE_DCC_VOICE
+ if(!dcc->ctcpMsg->msg->haltOutput())
+ {
+ dcc->ctcpMsg->msg->console()->output(KVI_OUT_DCCERROR,
+ __tr2qs_ctx("The above request cannot be accepted: DCC VOICE support not enabled at compilation time ","dcc"));
+ return;
+ }
+#endif
+ // Actually unused parameter
+ if(!kvi_dcc_voice_is_valid_codec(dcc->szParam1.ptr()))
+ {
+ if(!dcc->ctcpMsg->msg->haltOutput())
+ {
+ dcc->ctcpMsg->msg->console()->output(KVI_OUT_DCCERROR,
+ __tr2qs_ctx("The above request cannot be accepted: Unsupported codec '%s'","dcc"),dcc->szParam1.ptr());
+ return;
+ }
+ }
+
+ bool bOk;
+
+ int iSampleRate = dcc->szParam4.toInt(&bOk);
+ if(!bOk)
+ {
+ if(!dcc->ctcpMsg->msg->haltOutput())
+ {
+ dcc->ctcpMsg->msg->console()->output(KVI_OUT_DCCMSG,
+ __tr2qs_ctx("The above request appears to be broken: Invalid sample-rate '%s', defaulting to 8000","dcc"),dcc->szParam4.ptr());
+ }
+ iSampleRate = 8000;
+ }
+
+
+ KviDccDescriptor * d = new KviDccDescriptor(dcc->pConsole);
+ d->szNick = dcc->ctcpMsg->pSource->nick();
+ d->szUser = dcc->ctcpMsg->pSource->username();
+ d->szHost = dcc->ctcpMsg->pSource->host();
+ dcc_fill_local_nick_user_host(d,dcc);
+
+
+ d->szIp = dcc->szParam2.ptr();
+ d->szPort = dcc->szParam3.ptr();
+ d->bActive = true; // we have to connect
+ d->bIsTdcc = false;
+ d->bNoAcks = false; // this has no meaning in voice
+ d->szCodec = dcc->szParam1;
+ d->iSampleRate = iSampleRate;
+ d->bOverrideMinimize = false;
+ d->bAutoAccept = KVI_OPTION_BOOL(KviOption_boolAutoAcceptDccVoice);
+ dcc_module_set_dcc_type(d,"VOICE");
+ d->triggerCreationEvent();
+ g_pDccBroker->activeVoiceManage(d);
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// CANVAS
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+static void dccModuleParseDccCanvas(KviDccRequest *dcc)
+{
+ //
+ // We have received a DCC CANVAS request in the following form:
+ //
+ // DCC CANVAS unused <ipaddress> <port>
+ //
+ // This means that we're requested to setup an ACTIVE canvas connection
+ // ... Easy task :)
+ //
+ if(!dcc_module_check_limits(dcc))return;
+
+ if(!dcc_module_normalize_target_data(dcc,dcc->szParam2,dcc->szParam3))return;
+
+// Actually unused parameter
+// if(!(kvi_strEqualCI("canvas",dcc->szParam1.ptr())))
+// {
+// if(!dcc->ctcpMsg->msg->haltOutput())
+// {
+// dcc->ctcpMsg->msg->console()->output(KVI_OUT_DCCMSG,
+// __tr("The above request is broken: the second parameter is '%s' and shoud be 'chat'; trying to continue"),dcc->szParam1.ptr());
+// }
+// }
+#ifdef COMPILE_DCC_CANVAS
+ KviDccDescriptor * d = new KviDccDescriptor(dcc->pConsole);
+ d->szNick = dcc->ctcpMsg->pSource->nick();
+ d->szUser = dcc->ctcpMsg->pSource->username();
+ d->szHost = dcc->ctcpMsg->pSource->host();
+ dcc_fill_local_nick_user_host(d,dcc);
+
+
+ d->szIp = dcc->szParam2.ptr();
+ d->szPort = dcc->szParam3.ptr();
+ d->bActive = true; // we have to connect
+ d->bIsTdcc = false;
+ d->bNoAcks = false; // this has no meaning in canvas
+ d->bOverrideMinimize = false;
+ d->bAutoAccept = KVI_OPTION_BOOL(KviOption_boolAutoAcceptDccCanvas);
+ dcc_module_set_dcc_type(d,"CANVAS");
+ d->triggerCreationEvent();
+ g_pDccBroker->activeCanvasManage(d);
+#endif
+}
+
+
+static void dccModuleParseDccList(KviDccRequest *dcc)
+{
+ // DCC LIST <mask> <ipaddr> <port>
+ // FIXME!
+}
+
+
+
+typedef void (*dccParseProc)(KviDccRequest *);
+typedef struct _dccParseProcEntry
+{
+ const char * type;
+ dccParseProc proc;
+} dccParseProcEntry;
+
+#define KVI_NUM_KNOWN_DCC_TYPES 27
+
+static dccParseProcEntry dccParseProcTable[KVI_NUM_KNOWN_DCC_TYPES]=
+{
+ { "CHAT" , dccModuleParseDccChat },
+ { "SCHAT" , dccModuleParseDccChat },
+ { "SEND" , dccModuleParseDccSend },
+ { "TSEND" , dccModuleParseDccSend },
+ { "SSEND" , dccModuleParseDccSend },
+ { "TSSEND" , dccModuleParseDccSend },
+ { "STSEND" , dccModuleParseDccSend },
+ { "GET" , dccModuleParseDccGet },
+ { "SGET" , dccModuleParseDccGet },
+ { "TGET" , dccModuleParseDccGet },
+ { "STGET" , dccModuleParseDccGet },
+ { "TSGET" , dccModuleParseDccGet },
+ { "LIST" , dccModuleParseDccList },
+ { "ACCEPT" , dccModuleParseDccAccept },
+ { "RESUME" , dccModuleParseDccResume },
+ { "RECV" , dccModuleParseDccRecv },
+ { "SRECV" , dccModuleParseDccRecv },
+ { "TRECV" , dccModuleParseDccRecv },
+ { "TSRECV" , dccModuleParseDccRecv },
+ { "STRECV" , dccModuleParseDccRecv },
+ { "RSEND" , dccModuleParseDccRSend },
+ { "SRSEND" , dccModuleParseDccRSend },
+ { "TRSEND" , dccModuleParseDccRSend },
+ { "STRSEND", dccModuleParseDccRSend },
+ { "TSRSEND", dccModuleParseDccRSend },
+ { "CANVAS" , dccModuleParseDccCanvas },
+ { "VOICE" , dccModuleParseDccVoice }
+};
+
+
+
+// We want C linkage on this one: we want to be able to dlsym() it with a simple name
+// FIXME: Is this portable enough ? Or is better to have a table entry ?
+
+KVIMODULEEXPORTFUNC void dccModuleCtcpDccParseRoutine(KviDccRequest *dcc)
+{
+ dcc->szType.toUpper();
+
+ for(int i=0;i<KVI_NUM_KNOWN_DCC_TYPES;i++)
+ {
+ if(kvi_strEqualCS(dccParseProcTable[i].type,dcc->szType.ptr()))
+ {
+ (dccParseProcTable[i].proc)(dcc);
+ return;
+ }
+ }
+ // ops...we don't know this dcc type
+ if(!dcc->ctcpMsg->msg->haltOutput())
+ {
+ KviStr szError(KviStr::Format,
+ __tr2qs_ctx("Unknown DCC type '%s'","dcc"),dcc->szType.ptr());
+ dcc_module_request_error(dcc,szError.ptr());
+ }
+}
diff --git a/src/modules/dcc/send.cpp b/src/modules/dcc/send.cpp
new file mode 100644
index 00000000..c6cc1182
--- /dev/null
+++ b/src/modules/dcc/send.cpp
@@ -0,0 +1,1898 @@
+//=============================================================================
+//
+// File : send.cpp
+// Creation date : Tue Sep 20 09 2000 15:14:14 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "send.h"
+#include "broker.h"
+#include "marshal.h"
+#include "broker.h"
+#include "window.h"
+#include "kvi_styled_controls.h"
+
+#ifdef COMPILE_ON_WINDOWS
+ // Ugly Windoze compiler...
+ #include "dialogs.h"
+#endif
+
+#define _KVI_DEBUG_CHECK_RANGE_
+#include "kvi_debug.h"
+#include "kvi_app.h"
+#include "kvi_options.h"
+#include "kvi_ircview.h"
+#include "kvi_iconmanager.h"
+#include "kvi_locale.h"
+#include "kvi_error.h"
+#include "kvi_out.h"
+#include "kvi_netutils.h"
+#include "kvi_console.h"
+#include "kvi_frame.h"
+#include "kvi_malloc.h"
+#include "kvi_memmove.h"
+#include "kvi_thread.h"
+#include "kvi_ircsocket.h"
+
+#include "kvi_mediatype.h"
+#include "kvi_socket.h"
+#include "kvi_kvs_eventtriggers.h"
+#include "kvi_parameterlist.h"
+#include "kvi_ircconnection.h"
+#include "kvi_ircconnectionuserinfo.h"
+#include "kvi_sparser.h"
+#include "kvi_kvs_script.h"
+
+#include <qevent.h>
+#include <qfile.h>
+#include <qpainter.h>
+#include <qdatetime.h>
+#include <qglobal.h>
+#include <qcheckbox.h>
+#include <qspinbox.h>
+#include <qlayout.h>
+#include <qpushbutton.h>
+
+#define INSTANT_BANDWIDTH_CHECK_INTERVAL_IN_MSECS 3000
+#define INSTANT_BANDWIDTH_CHECK_INTERVAL_IN_SECS 3
+
+// This limit, when multiplied by INSTANT_BANDWIDTH_CHECK_INTERVAL_IN_SECS
+// must fit in 31 bits (0x7fffffff)! (because of data size limits)
+#define MAX_DCC_BANDWIDTH_LIMIT 0x1fffffff
+
+//#include <unistd.h> //close()
+
+// FIXME: SSL Support here!
+// FIXME: The events OnDCCConnect etc are in wrong places here...!
+
+extern KviDccBroker * g_pDccBroker;
+
+extern KVIRC_API KviMediaManager * g_pMediaManager; // kvi_app.cpp
+
+
+static KviPointerList<KviDccFileTransfer> * g_pDccFileTransfers = 0;
+static QPixmap * g_pDccFileTransferIcon = 0;
+
+//#warning "The events that have a KviStr data pointer should become real classes, that take care of deleting the data pointer!"
+//#warning "Otherwise, when left undispatched we will be leaking memory (event class destroyed but not the data ptr)"
+
+KviDccRecvThread::KviDccRecvThread(QObject * par,kvi_socket_t fd,KviDccRecvThreadOptions * opt)
+: KviDccThread(par,fd)
+{
+ m_pOpt = opt;
+ m_iAverageSpeed = -1;
+ m_iInstantSpeed = -1;
+ m_iFilePosition = 0;
+
+ m_iTotalReceivedBytes = 0;
+ m_iInstantReceivedBytes = 0;
+ m_pFile = 0;
+ m_pTimeInterval = new KviMSecTimeInterval();
+ m_uStartTime = 0;
+ m_uInstantSpeedInterval = 0;
+}
+
+KviDccRecvThread::~KviDccRecvThread()
+{
+ if(m_pOpt)delete m_pOpt;
+ if(m_pFile)delete m_pFile;
+ delete m_pTimeInterval;
+}
+
+bool KviDccRecvThread::sendAck(int filePos)
+{
+ int size = htonl(filePos);
+ if(kvi_socket_send(m_fd,(void *)(&size),4) != 4)
+ {
+ postErrorEvent(KviError_acknowledgeError);
+ return false;
+ }
+ return true;
+}
+
+void KviDccRecvThread::updateStats()
+{
+ m_uInstantSpeedInterval += m_pTimeInterval->mark();
+ unsigned long uCurTime = m_pTimeInterval->secondsCounter();
+
+ m_pMutex->lock();
+ unsigned long uElapsedTime = uCurTime - m_uStartTime;
+ if(uElapsedTime < 1)uElapsedTime = 1;
+
+ m_iFilePosition = m_pFile->at();
+ m_iAverageSpeed = m_iTotalReceivedBytes / uElapsedTime;
+
+ if(m_uInstantSpeedInterval > INSTANT_BANDWIDTH_CHECK_INTERVAL_IN_MSECS)
+ {
+ unsigned int uMSecsOfTheNextInterval = 0;
+ if(m_uInstantSpeedInterval < (INSTANT_BANDWIDTH_CHECK_INTERVAL_IN_MSECS + (INSTANT_BANDWIDTH_CHECK_INTERVAL_IN_MSECS / 2)))
+ uMSecsOfTheNextInterval = m_uInstantSpeedInterval - INSTANT_BANDWIDTH_CHECK_INTERVAL_IN_MSECS;
+ m_iInstantSpeed = (m_iInstantReceivedBytes * 1000) / m_uInstantSpeedInterval;
+ m_iInstantReceivedBytes = 0;
+ m_uInstantSpeedInterval = uMSecsOfTheNextInterval;
+ } else {
+ if(uElapsedTime <= INSTANT_BANDWIDTH_CHECK_INTERVAL_IN_SECS)
+ m_iInstantSpeed = m_iAverageSpeed;
+ }
+ m_pMutex->unlock();
+}
+
+void KviDccRecvThread::postMessageEvent(const char * m)
+{
+ KviThreadDataEvent<KviStr> * e = new KviThreadDataEvent<KviStr>(KVI_DCC_THREAD_EVENT_MESSAGE);
+ e->setData(new KviStr(m));
+ postEvent(parent(),e);
+}
+
+// FIXME: This stuff should be somewhat related to the 1448 bytes TCP basic packet size
+#define KVI_DCC_RECV_BLOCK_SIZE 8192
+#define KVI_DCC_RECV_75PERCENTOF_BLOCK_SIZE 6150
+
+void KviDccRecvThread::run()
+{
+ // take care of sleeping a bit if we can't read stuff
+ // so we don't hog the CPU too much...
+ int iFailedSelects = 0;
+ // take care of sleeping a bit if we get a lot of short reads
+ // so we don't hog the CPU too much...
+ int iShortReadQuantifier = 0;
+ // the algorithm is as follows:
+ // attempt to read KVI_DCC_RECV_BLOCK_SIZE bytes
+ // iShortReadQuantifier += ((KVI_DCC_RECV_75PERCENT_OF_BLOCK_SIZE - realReadedBytes) / 42);
+ // thus we gain points if we read less than 75% of the requested size
+ // and we loose points otherwise
+ // there are nearly 24 points per KB
+ // if(iShortReadQuantifier > 10)
+ // msleep(iShortReadQuantifier);
+ // also never sleep more than 500 msecs since it will
+ // rise our exit latency too much
+
+ m_pTimeInterval->mark();
+ m_pMutex->lock();
+ m_uStartTime = m_pTimeInterval->secondsCounter();
+ m_pMutex->unlock();
+
+ int iProbableTerminationTime = 0;
+
+ m_pFile = new QFile(QString::fromUtf8(m_pOpt->szFileName.ptr()));
+
+ if(m_pOpt->bResume)
+ {
+ if(!m_pFile->open(IO_WriteOnly | IO_Append))
+ {
+ postErrorEvent(KviError_cantOpenFileForAppending);
+ goto exit_dcc;
+ } // else pFile is already at end
+ } else {
+ if(!m_pFile->open(IO_WriteOnly))
+ {
+ postErrorEvent(KviError_cantOpenFileForWriting);
+ goto exit_dcc;
+ }
+ }
+
+ if(m_pOpt->bSendZeroAck && (!m_pOpt->bNoAcks))
+ {
+ if(!sendAck(m_pFile->at()))goto exit_dcc;
+ }
+
+ for(;;)
+ {
+ // Dequeue events
+ while(KviThreadEvent * e = dequeueEvent())
+ {
+ if(e->id() == KVI_THREAD_EVENT_TERMINATE)
+ {
+ delete e;
+ goto exit_dcc;
+ } else {
+ // Other events are senseless to us
+ delete e;
+ }
+ }
+
+ bool bCanRead;
+ bool bDummy;
+
+ if(kvi_select(m_fd,&bCanRead,&bDummy,15000))
+ {
+ // reset sleep time
+
+ if(bCanRead)
+ {
+ iFailedSelects = 0;
+
+ // Read a data block
+ char buffer[KVI_DCC_RECV_BLOCK_SIZE];
+
+ m_pMutex->lock(); // FIXME: how to remove this lock ?
+ unsigned int uMaxPossible = (m_pOpt->uMaxBandwidth < MAX_DCC_BANDWIDTH_LIMIT) ? m_pOpt->uMaxBandwidth * INSTANT_BANDWIDTH_CHECK_INTERVAL_IN_SECS : MAX_DCC_BANDWIDTH_LIMIT * INSTANT_BANDWIDTH_CHECK_INTERVAL_IN_SECS;
+ m_pMutex->unlock();
+ unsigned int uToRead = uMaxPossible > ((unsigned int)(m_iInstantReceivedBytes)) ? uMaxPossible - m_iInstantReceivedBytes : 0;
+ if(uToRead > KVI_DCC_RECV_BLOCK_SIZE)uToRead = KVI_DCC_RECV_BLOCK_SIZE;
+
+ if(uToRead > 0)
+ {
+ int readLen = kvi_socket_recv(m_fd,buffer,uToRead);
+
+ if(readLen > 0)
+ {
+ // Readed something useful...write back
+ if((m_pOpt->iTotalFileSize > -1) && ((readLen + (int)m_pFile->at()) > m_pOpt->iTotalFileSize))
+ {
+ postMessageEvent(__tr2qs_ctx("WARNING: The peer is sending garbage data past the end of the file","dcc"));
+ postMessageEvent(__tr2qs_ctx("WARNING: Ignoring data past the declared end of file and closing the connection","dcc"));
+
+ readLen = m_pOpt->iTotalFileSize - m_pFile->at();
+ if(readLen > 0)
+ {
+ if(m_pFile->writeBlock(buffer,readLen) != readLen)
+ postErrorEvent(KviError_fileIOError);
+ }
+ break;
+
+ } else {
+ if(m_pFile->writeBlock(buffer,readLen) != readLen)
+ {
+ postErrorEvent(KviError_fileIOError);
+ break;
+ }
+ }
+
+ // Update stats
+ m_iTotalReceivedBytes += readLen;
+ m_iInstantReceivedBytes += readLen;
+
+ updateStats();
+ // Now send the ack
+ if(m_pOpt->bNoAcks)
+ {
+ // No acks...
+ // Interrupt if the whole file has been received
+ if(m_pOpt->iTotalFileSize > 0)
+ {
+ if(((int)(m_pFile->at())) == m_pOpt->iTotalFileSize)
+ {
+ // Received the whole file...die
+ KviThreadEvent * e = new KviThreadEvent(KVI_DCC_THREAD_EVENT_SUCCESS);
+ postEvent(parent(),e);
+ break;
+ }
+ }
+ } else {
+ // Must send the ack... the peer must close the connection
+ if(!sendAck(m_pFile->at()))break;
+ }
+
+ // now take care of short reads
+ iShortReadQuantifier += ((KVI_DCC_RECV_75PERCENTOF_BLOCK_SIZE - readLen) / 42);
+ if(iShortReadQuantifier > 10)
+ {
+ // we're having short reads.. sleep a while
+ // but don't allow it to go too high: 0.45 sec is really a lot
+ if(iShortReadQuantifier > 500)
+ iShortReadQuantifier = 500;
+ msleep(iShortReadQuantifier);
+ } else {
+ // don't allow it to go too low
+ if(iShortReadQuantifier < -500)
+ iShortReadQuantifier = -500;
+ }
+
+ } else {
+ updateStats();
+ // Read problem...
+
+ if(readLen == 0)
+ {
+ // readed EOF..
+ if((((int)(m_pFile->at())) == m_pOpt->iTotalFileSize) || (m_pOpt->iTotalFileSize < 0))
+ {
+ // success if we got the whole file or if we don't know the file size (we trust the peer)
+ KviThreadEvent * e = new KviThreadEvent(KVI_DCC_THREAD_EVENT_SUCCESS);
+ postEvent(parent(),e);
+ break;
+ }
+ }
+ if(!handleInvalidSocketRead(readLen))break;
+ }
+ } else {
+ updateStats();
+
+ // reached the bandwidth limit: slow down a bit
+ if(m_uInstantSpeedInterval < (INSTANT_BANDWIDTH_CHECK_INTERVAL_IN_MSECS - 100))
+ msleep(100);
+ else if(m_uInstantSpeedInterval < (INSTANT_BANDWIDTH_CHECK_INTERVAL_IN_MSECS - 20))
+ msleep(20);
+ }
+ } else {
+ // Can't read stuff (can just write)
+ updateStats();
+
+ // sleep up to 300 msecs (if data arrives...we want low exit latency here)
+ if(iFailedSelects < 100)iFailedSelects++;
+ updateStats();
+ if(iFailedSelects > 3)
+ msleep(3 * iFailedSelects);
+
+ if(((int)(m_pFile->at())) == m_pOpt->iTotalFileSize)
+ {
+ // Wait for the peer to close the connection
+ if(iProbableTerminationTime == 0)
+ {
+ iProbableTerminationTime = (int)kvi_unixTime();
+ m_pFile->flush();
+ postMessageEvent(__tr2qs_ctx("Data transfer terminated, waiting 30 seconds for the peer to close the connection...","dcc"));
+ // FIXME: Close the file ?
+ } else {
+ int iDiff = (((int)kvi_unixTime()) - iProbableTerminationTime);
+ if(iDiff > 30)
+ {
+ // success if we got the whole file or if we don't know the file size (we trust the peer)
+ postMessageEvent(__tr2qs_ctx("Data transfer was terminated 30 seconds ago, closing the connection","dcc"));
+ KviThreadEvent * e = new KviThreadEvent(KVI_DCC_THREAD_EVENT_SUCCESS);
+ postEvent(parent(),e);
+ break;
+ }
+ }
+ }
+ }
+ // include the artificial delay if needed
+ if(m_pOpt->iIdleStepLengthInMSec > 0)
+ {
+ debug("LOOP: artificial delay");
+ msleep(m_pOpt->iIdleStepLengthInMSec);
+ }
+ } else {
+ // sleep up to 200 msecs (if data arrives...we want low exit latency here)
+ if(iFailedSelects < 100)iFailedSelects++;
+ updateStats();
+ if(iFailedSelects > 3)
+ msleep(2 * iFailedSelects);
+ }
+ }
+
+exit_dcc:
+ if(m_pFile)
+ {
+ m_pFile->close();
+ delete m_pFile;
+ m_pFile = 0;
+ }
+ kvi_socket_close(m_fd);
+ m_fd = KVI_INVALID_SOCKET;
+}
+
+void KviDccRecvThread::initGetInfo()
+{
+ m_pMutex->lock();
+}
+
+void KviDccRecvThread::doneGetInfo()
+{
+ m_pMutex->unlock();
+}
+
+KviDccSendThread::KviDccSendThread(QObject * par,kvi_socket_t fd,KviDccSendThreadOptions * opt)
+: KviDccThread(par,fd)
+{
+ m_pOpt = opt;
+ // stats
+ m_iAverageSpeed = -1;
+ m_iInstantSpeed = -1;
+ m_iFilePosition = 0;
+ m_iTotalSentBytes = 0;
+ m_pTimeInterval = new KviMSecTimeInterval();
+ m_uStartTime = 0;
+ m_uInstantSpeedInterval = 0;
+}
+
+KviDccSendThread::~KviDccSendThread()
+{
+ if(m_pOpt)delete m_pOpt;
+ delete m_pTimeInterval;
+}
+
+void KviDccSendThread::updateStats()
+{
+ m_uInstantSpeedInterval += m_pTimeInterval->mark();
+
+ m_pMutex->lock();
+ unsigned long uElapsedTime = m_pTimeInterval->secondsCounter() - m_uStartTime;
+ if(uElapsedTime < 1)uElapsedTime = 1;
+
+ if(m_pOpt->bNoAcks)
+ {
+ // There are no acks : the avg bandwidth is based on the sent bytes
+ m_iAverageSpeed = m_iTotalSentBytes / uElapsedTime;
+ } else {
+ // acknowledges : we compute the avg bandwidth based on the acks we receive
+ m_iAverageSpeed = (m_iAckedBytes - m_pOpt->iStartPosition) / uElapsedTime;
+ }
+
+ if(m_uInstantSpeedInterval >= INSTANT_BANDWIDTH_CHECK_INTERVAL_IN_MSECS)
+ {
+ // we often overcount the time interval of 10-20 msecs
+ // and thus our bandwidth is used less than requested.
+ // for this reason we try to account the time in excess
+ // to the next period in order to balance the bandwidth usage.
+ unsigned long uMSecsOfNextPeriodUsed = 0;
+ if(m_uInstantSpeedInterval > INSTANT_BANDWIDTH_CHECK_INTERVAL_IN_MSECS)
+ {
+ if(m_uInstantSpeedInterval < (INSTANT_BANDWIDTH_CHECK_INTERVAL_IN_MSECS + (INSTANT_BANDWIDTH_CHECK_INTERVAL_IN_MSECS / 2)))
+ {
+ uMSecsOfNextPeriodUsed = m_uInstantSpeedInterval - INSTANT_BANDWIDTH_CHECK_INTERVAL_IN_MSECS;
+ m_uInstantSpeedInterval = INSTANT_BANDWIDTH_CHECK_INTERVAL_IN_MSECS;
+ }
+ // else we have been delayed for a time comparable to a period
+ // and thus we can't recover the bandwidth... let it go as it does...
+ }
+ m_iInstantSpeed = (m_iInstantSentBytes * 1000) / m_uInstantSpeedInterval;
+ m_uInstantSpeedInterval = uMSecsOfNextPeriodUsed;
+ m_iInstantSentBytes = 0;
+ } else {
+ if(uElapsedTime <= INSTANT_BANDWIDTH_CHECK_INTERVAL_IN_SECS)
+ m_iInstantSpeed = m_iAverageSpeed;
+ }
+ m_pMutex->unlock();
+}
+
+void KviDccSendThread::run()
+{
+ m_pTimeInterval->mark();
+ m_pMutex->lock();
+ m_uStartTime = m_pTimeInterval->secondsCounter();
+ m_pMutex->unlock();
+
+ m_iTotalSentBytes = 0;
+ m_iInstantSentBytes = 0;
+ int iFailedSelects = 0;
+ char ackbuffer[4];
+ int iBytesInAckBuffer = 0;
+ Q_UINT32 iLastAck = 0;
+
+ if(m_pOpt->iPacketSize < 32)m_pOpt->iPacketSize = 32;
+ char * buffer = (char *)kvi_malloc(m_pOpt->iPacketSize * sizeof(char));
+
+ QFile * pFile = new QFile(QString::fromUtf8(m_pOpt->szFileName.ptr()));
+
+ if(!pFile->open(IO_ReadOnly))
+ {
+ postErrorEvent(KviError_cantOpenFileForReading);
+ goto exit_dcc;
+ }
+
+ if(pFile->size() < 1)
+ {
+ postErrorEvent(KviError_cantSendAZeroSizeFile);
+ goto exit_dcc;
+ }
+
+ if(m_pOpt->iStartPosition > 0)
+ {
+ // seek
+ if(!(pFile->at(m_pOpt->iStartPosition)))
+ {
+ postErrorEvent(KviError_fileIOError);
+ goto exit_dcc;
+ }
+ }
+
+ iLastAck = m_pOpt->iStartPosition;
+
+ for(;;)
+ {
+ // Dequeue events
+ while(KviThreadEvent * e = dequeueEvent())
+ {
+ if(e->id() == KVI_THREAD_EVENT_TERMINATE)
+ {
+ delete e;
+ goto exit_dcc;
+ } else {
+ // Other events are senseless to us
+ delete e;
+ }
+ }
+
+ bool bCanRead;
+ bool bCanWrite;
+
+ if(kvi_select(m_fd,&bCanRead,&bCanWrite,15000))
+ {
+ // reset the sleep time
+ iFailedSelects = 0;
+ if(bCanRead)
+ {
+ if(!m_pOpt->bNoAcks)
+ {
+ int iAckBytesToRead = 4 - iBytesInAckBuffer;
+ int readLen = kvi_socket_recv(m_fd,(void *)(ackbuffer + iBytesInAckBuffer),iAckBytesToRead);
+ if(readLen > 0)
+ {
+ iBytesInAckBuffer += readLen;
+ if(iBytesInAckBuffer == 4)
+ {
+ Q_UINT32 iNewAck = ntohl(*((Q_UINT32 *)ackbuffer));
+ if((iNewAck > pFile->at()) || (iNewAck < iLastAck))
+ {
+ // the peer is drunk or is trying to fool us
+ postErrorEvent(KviError_acknowledgeError);
+ break;
+ }
+ iLastAck = iNewAck;
+ iBytesInAckBuffer = 0;
+ }
+ } else {
+ if(!handleInvalidSocketRead(readLen))break;
+ }
+
+ // update stats
+ m_pMutex->lock(); // is this really necessary ?
+ m_iAckedBytes = iLastAck;
+ m_pMutex->unlock();
+
+ if(iLastAck >= pFile->size())
+ {
+ KviThreadEvent * e = new KviThreadEvent(KVI_DCC_THREAD_EVENT_SUCCESS);
+ postEvent(parent(),e);
+ break;
+ }
+ } else {
+ // No acknowledges
+ if(m_pOpt->bIsTdcc)
+ {
+ // We expect the remote end to close the connection when the whole file has been sent
+ if(pFile->atEnd())
+ {
+ int iAck;
+ int readLen = kvi_socket_recv(m_fd,(void *)&iAck,4);
+ if(readLen == 0)
+ {
+ // done...success
+ updateStats();
+ KviThreadEvent * e = new KviThreadEvent(KVI_DCC_THREAD_EVENT_SUCCESS);
+ postEvent(parent(),e);
+ break;
+ } else {
+ if(readLen < 0)
+ {
+ if(!handleInvalidSocketRead(readLen))break;
+ } else {
+ KviThreadDataEvent<KviStr> * e = new KviThreadDataEvent<KviStr>(KVI_DCC_THREAD_EVENT_MESSAGE);
+ e->setData(new KviStr(__tr2qs_ctx("WARNING: Received data in a DCC TSEND, there should be no acknowledges","dcc")));
+ postEvent(parent(),e);
+ }
+ }
+ }
+ }
+ }
+ }
+ if(bCanWrite)
+ {
+ if(!pFile->atEnd())
+ {
+ if(m_pOpt->bFastSend || m_pOpt->bNoAcks || (iLastAck == pFile->at()))
+ {
+ // maximum readable size
+ int toRead = pFile->size() - pFile->at();
+ // the max number of bytes we can send in this interval (bandwidth limit)
+ m_pMutex->lock(); // FIXME: how to remove this lock ?
+ int iMaxPossible = m_pOpt->uMaxBandwidth < MAX_DCC_BANDWIDTH_LIMIT ? m_pOpt->uMaxBandwidth * INSTANT_BANDWIDTH_CHECK_INTERVAL_IN_SECS : MAX_DCC_BANDWIDTH_LIMIT * INSTANT_BANDWIDTH_CHECK_INTERVAL_IN_SECS;
+ m_pMutex->unlock();
+ if(iMaxPossible < m_iInstantSentBytes)toRead = 0; // already sent too much!
+ else {
+ iMaxPossible -= m_iInstantSentBytes;
+ if(toRead > iMaxPossible)toRead = iMaxPossible;
+ }
+ // limit to packet size
+ if(toRead > m_pOpt->iPacketSize)toRead = m_pOpt->iPacketSize;
+
+ int written = 0;
+ if(toRead > 0)
+ {
+ // read data
+ int readed = pFile->readBlock(buffer,toRead);
+ if(readed < toRead)
+ {
+ postErrorEvent(KviError_fileIOError);
+ break;
+ }
+ // send it out
+ written = kvi_socket_send(m_fd,buffer,toRead);
+ if(written < toRead)
+ {
+ if(written < 0)
+ {
+ // error ?
+ if(!handleInvalidSocketRead(written))break;
+ } else {
+ // seek back to the right position
+ pFile->at(pFile->at() - (toRead - written));
+ }
+ }
+ } else {
+ // just nothing to send out in this interval
+ // sleep a while
+ if(m_uInstantSpeedInterval < (INSTANT_BANDWIDTH_CHECK_INTERVAL_IN_MSECS - 100))
+ {
+ msleep(100);
+ } else if(m_uInstantSpeedInterval < (INSTANT_BANDWIDTH_CHECK_INTERVAL_IN_MSECS - 20))
+ {
+ msleep(20);
+ }
+ }
+
+ m_iTotalSentBytes += written;
+ m_iInstantSentBytes += written;
+ m_iFilePosition = pFile->at();
+ updateStats();
+ }
+ } else {
+ if(m_pOpt->bNoAcks && !m_pOpt->bIsTdcc)
+ {
+ // at end of the file in a blind dcc send...
+ // not in a tdcc: we can close the file...
+ updateStats();
+ KviThreadEvent * e = new KviThreadEvent(KVI_DCC_THREAD_EVENT_SUCCESS);
+ postEvent(parent(),e);
+ break;
+ } else {
+ // upload finished but we're waiting for the last ack
+ // sleep a bit: don't lag the kernie too much while waiting
+ msleep(100);
+ }
+ }
+ }
+ } else {
+ // after 2 failed selects start to sleep
+ if(iFailedSelects > 3)
+ {
+ // sleep up to 200 msecs
+ if(iFailedSelects < 100)iFailedSelects++;
+ msleep(3 * iFailedSelects);
+ } else {
+ iFailedSelects++;
+ }
+ }
+
+ // include the artificial delay if needed
+ if(m_pOpt->iIdleStepLengthInMSec > 0)
+ {
+ msleep(m_pOpt->iIdleStepLengthInMSec);
+ }
+ }
+
+exit_dcc:
+ kvi_free(buffer);
+ pFile->close();
+ delete pFile;
+ pFile = 0;
+ kvi_socket_close(m_fd);
+ m_fd = KVI_INVALID_SOCKET;
+}
+
+void KviDccSendThread::initGetInfo()
+{
+ m_pMutex->lock();
+}
+
+void KviDccSendThread::doneGetInfo()
+{
+ m_pMutex->unlock();
+}
+
+
+KviDccFileTransfer::KviDccFileTransfer(KviDccDescriptor * dcc)
+: KviFileTransfer()
+{
+ init(); // ensure we're initialized
+ g_pDccFileTransfers->append(this);
+
+ m_pResumeTimer = 0;
+ m_pBandwidthDialog = 0;
+
+ KviQString::sprintf(m_szTransferIdString,__tr2qs_ctx("TRANSFER %d","dcc"),id());
+
+ m_pDescriptor = dcc;
+ m_pDescriptor->setTransfer(this);
+
+ m_pMarshal = new KviDccMarshal(this);
+
+ connect(m_pMarshal,SIGNAL(error(int)),this,SLOT(handleMarshalError(int)));
+ connect(m_pMarshal,SIGNAL(connected()),this,SLOT(connected()));
+ connect(m_pMarshal,SIGNAL(inProgress()),this,SLOT(connectionInProgress()));
+#ifdef COMPILE_SSL_SUPPORT
+ connect(m_pMarshal,SIGNAL(startingSSLHandshake()),this,SLOT(startingSSLHandshake()));
+ connect(m_pMarshal,SIGNAL(sslError(const char *)),this,SLOT(sslError(const char *)));
+#endif
+
+ m_szDccType = dcc->bIsTdcc ? (dcc->bRecvFile ? "TRECV" : "TSEND") : (dcc->bRecvFile ? "RECV" : "SEND");
+
+ m_pSlaveRecvThread = 0;
+ m_pSlaveSendThread = 0;
+
+ m_tTransferStartTime = 0;
+ m_tTransferEndTime = 0;
+
+ m_szStatusString = __tr2qs_ctx("Setting up the connection","dcc");
+ m_eGeneralStatus = Connecting;
+
+ bool bOk;
+ m_uTotalFileSize = dcc->bRecvFile ? dcc->szFileSize.toUInt(&bOk) : dcc->szLocalFileSize.toUInt(&bOk);
+ if(!bOk)m_uTotalFileSize = 0;
+
+ if(m_pDescriptor->bRecvFile)
+ m_uMaxBandwidth = KVI_OPTION_BOOL(KviOption_boolLimitDccRecvSpeed) ? KVI_OPTION_UINT(KviOption_uintMaxDccRecvSpeed) : MAX_DCC_BANDWIDTH_LIMIT;
+ else
+ m_uMaxBandwidth = KVI_OPTION_BOOL(KviOption_boolLimitDccSendSpeed) ? KVI_OPTION_UINT(KviOption_uintMaxDccSendSpeed) : MAX_DCC_BANDWIDTH_LIMIT;
+
+ startConnection();
+}
+
+KviDccFileTransfer::~KviDccFileTransfer()
+{
+ g_pDccFileTransfers->removeRef(this);
+
+ if(m_pResumeTimer)delete m_pResumeTimer;
+ if(m_pBandwidthDialog)delete m_pBandwidthDialog;
+
+ if(m_pSlaveRecvThread)
+ {
+ m_pSlaveRecvThread->terminate();
+ delete m_pSlaveRecvThread;
+ m_pSlaveRecvThread = 0;
+ }
+
+ if(m_pSlaveSendThread)
+ {
+ m_pSlaveSendThread->terminate();
+ delete m_pSlaveSendThread;
+ m_pSlaveSendThread = 0;
+ }
+
+ KviThreadManager::killPendingEvents(this);
+
+ delete m_pDescriptor;
+ delete m_pMarshal;
+}
+
+void KviDccFileTransfer::bandwidthDialogDestroyed()
+{
+ m_pBandwidthDialog = 0;
+}
+
+KviWindow * KviDccFileTransfer::eventWindow()
+{
+ KviWindow *w = transferWindow();
+ if(w)return w;
+ return m_pDescriptor->console();
+}
+
+void KviDccFileTransfer::startConnection()
+{
+ if(!(m_pDescriptor->bActive))
+ {
+ // PASSIVE CONNECTION
+ m_szStatusString = __tr2qs_ctx("Attempting a passive DCC %1 connection","dcc").arg(m_szDccType.ptr());
+ outputAndLog(m_szStatusString);
+ } else {
+ // ACTIVE CONNECTION
+ m_szStatusString = __tr2qs_ctx("Attempting an active DCC %1 connection","dcc").arg(m_szDccType.ptr());
+ outputAndLog(m_szStatusString);
+ }
+
+
+ if(m_pDescriptor->bResume && m_pDescriptor->bRecvFile)
+ {
+ QString fName;
+ KviServerParser::encodeCtcpParameter(m_pDescriptor->szFileName.utf8().data(),fName);
+ if(m_pDescriptor->isZeroPortRequest())
+ {
+ m_pDescriptor->console()->connection()->sendFmtData("PRIVMSG %s :%cDCC RESUME %s %s %s %s%c",
+ m_pDescriptor->console()->connection()->encodeText(m_pDescriptor->szNick).data(),
+ 0x01,
+ m_pDescriptor->console()->connection()->encodeText(fName).data(),
+ m_pDescriptor->szPort.utf8().data(),
+ m_pDescriptor->szLocalFileSize.utf8().data(),
+ m_pDescriptor->zeroPortRequestTag(),0x01);
+ } else {
+ m_pDescriptor->console()->connection()->sendFmtData("PRIVMSG %s :%cDCC RESUME %s %s %s%c",
+ m_pDescriptor->console()->connection()->encodeText(m_pDescriptor->szNick).data(),
+ 0x01,
+ m_pDescriptor->console()->connection()->encodeText(fName).data(),
+ m_pDescriptor->szPort.utf8().data(),
+ m_pDescriptor->szLocalFileSize.utf8().data(),0x01);
+ }
+ m_szStatusString = __tr2qs_ctx("Sent DCC RESUME request to %1, waiting for ACCEPT","dcc").arg(m_pDescriptor->szNick);
+ outputAndLog(m_szStatusString);
+
+ // setup the resume timer: we don't want to wait forever
+
+ if(KVI_OPTION_UINT(KviOption_uintDccSocketTimeout) < 5)
+ KVI_OPTION_UINT(KviOption_uintDccSocketTimeout) = 5;
+
+ if(m_pResumeTimer)delete m_pResumeTimer;
+ m_pResumeTimer = new QTimer(this);
+ connect(m_pResumeTimer,SIGNAL(timeout()),this,SLOT(resumeTimedOut()));
+ m_pResumeTimer->start(KVI_OPTION_UINT(KviOption_uintDccSocketTimeout) * 1000,true);
+ } else {
+ listenOrConnect();
+ }
+
+ displayUpdate();
+}
+
+void KviDccFileTransfer::listenOrConnect()
+{
+ if(!(m_pDescriptor->bActive))
+ {
+ int ret = m_pMarshal->dccListen(m_pDescriptor->szListenIp,m_pDescriptor->szListenPort,m_pDescriptor->bDoTimeout);
+ if(ret != KviError_success)handleMarshalError(ret);
+ } else {
+ int ret = m_pMarshal->dccConnect(m_pDescriptor->szIp.utf8().data(),m_pDescriptor->szPort.utf8().data(),m_pDescriptor->bDoTimeout);
+ if(ret != KviError_success)handleMarshalError(ret);
+ }
+
+ displayUpdate();
+}
+
+void KviDccFileTransfer::resumeTimedOut()
+{
+ if(m_pResumeTimer)
+ {
+ delete m_pResumeTimer;
+ m_pResumeTimer = 0;
+ }
+ handleMarshalError(KviError_connectionTimedOut);
+}
+
+KviWindow * KviDccFileTransfer::dccMarshalOutputWindow()
+{
+ return transferWindow();
+}
+
+const char * KviDccFileTransfer::dccMarshalOutputContextString()
+{
+ return m_szTransferIdString.utf8().data();
+}
+
+void KviDccFileTransfer::die()
+{
+ delete this;
+}
+
+QString KviDccFileTransfer::localFileName()
+{
+ return m_pDescriptor->szLocalFileName;
+}
+
+void KviDccFileTransfer::abort()
+{
+ if(m_pSlaveRecvThread)m_pSlaveRecvThread->terminate();
+ if(m_pSlaveSendThread)m_pSlaveSendThread->terminate();
+ if(m_pMarshal)m_pMarshal->abort();
+
+ if(m_pDescriptor->bRecvFile)
+ g_pApp->fileDownloadTerminated(false,m_pDescriptor->szFileName.utf8().data(),m_pDescriptor->szLocalFileName.utf8().data(),m_pDescriptor->szNick.utf8().data(),__tr_ctx("Aborted","dcc"));
+
+ KviStr tmp;
+
+ if(m_pSlaveRecvThread)tmp.setNum(m_pSlaveRecvThread->receivedBytes());
+ else if(m_pSlaveSendThread)tmp.setNum(m_pSlaveSendThread->sentBytes());
+ else tmp = '0';
+
+ m_eGeneralStatus = Failure;
+ m_tTransferEndTime = kvi_unixTime();
+ m_szStatusString = __tr2qs_ctx("Transfer failed: ","dcc");
+ m_szStatusString += __tr2qs_ctx("Aborted","dcc");
+
+ KVS_TRIGGER_EVENT_3(KviEvent_OnDCCFileTransferFailed,eventWindow(),QString("Aborted by user"),QString(tmp.ptr()),m_pDescriptor->idString());
+
+ outputAndLog(KVI_OUT_DCCERROR,m_szStatusString);
+ displayUpdate();
+}
+
+
+void KviDccFileTransfer::fillContextPopup(KviTalPopupMenu * m,int column)
+{
+ m->insertItem(__tr2qs_ctx("Configure Bandwidth...","dcc"),this,SLOT(configureBandwidth()));
+ m->insertSeparator();
+ m->insertItem(__tr2qs_ctx("Resend DCC","dcc"),this,SLOT(retryDCC()));
+ m->insertItem(__tr2qs_ctx("Resend TDCC","dcc"),this,SLOT(retryTDCC()));
+ m->insertItem(__tr2qs_ctx("Resend RevDCC","dcc"),this,SLOT(retryRevDCC()));
+ /* FIX ME credo che il problema sia che se riavvio un trasferimento, a sua volta gia'
+ avviato, questo non ha irc contex, perche' la finestra "in cui e' nato"e' sta
+ quella della dcc. Conservarsi l'id della finestra? */
+ int id = m->insertItem(__tr2qs_ctx("Abort","dcc"),this,SLOT(abort()));
+ if(!active())m->setItemEnabled(id,false);
+}
+
+void KviDccFileTransfer::configureBandwidth()
+{
+ if(m_pBandwidthDialog)return;
+ m_pBandwidthDialog = new KviDccFileTransferBandwidthDialog(g_pFrame,this);
+ connect(m_pBandwidthDialog,SIGNAL(destroyed()),this,SLOT(bandwidthDialogDestroyed()));
+ m_pBandwidthDialog->setModal(true);
+ m_pBandwidthDialog->show();
+}
+
+void KviDccFileTransfer::retryDCC()
+{
+ abort();
+ QString szRemoteNick = m_pDescriptor->remoteNick();
+ QString szFileName = m_pDescriptor->localFileName();
+ QString szId;
+ szId.setNum(m_pDescriptor->id());
+ QString szCommand = "dcc.send -r=$console($dcc.irccontext(" + szId + ")) " + szRemoteNick + " " + "\"" + szFileName + "\"";
+ KviKvsScript::run(szCommand,g_pActiveWindow);
+}
+
+void KviDccFileTransfer::retryTDCC()
+{
+ abort();
+ QString szRemoteNick = m_pDescriptor->remoteNick();
+ QString szFileName = m_pDescriptor->localFileName();
+ QString szId;
+ szId.setNum(m_pDescriptor->id());
+ QString szCommand = "dcc.send -r=$console($dcc.irccontext(" + szId + ")) -t " + szRemoteNick + " " + "\"" + szFileName + "\"";
+ KviKvsScript::run(szCommand,g_pActiveWindow);
+}
+void KviDccFileTransfer::retryRevDCC()
+{
+ abort();
+ QString szRemoteNick = m_pDescriptor->remoteNick();
+ QString szFileName = m_pDescriptor->localFileName();
+ QString szId;
+ szId.setNum(m_pDescriptor->id());
+ QString szCommand = "dcc.rsend -z -r=$console($dcc.irccontext(" + szId + ")) " + szRemoteNick + " " + "\"" + szFileName + "\"";
+ KviKvsScript::run(szCommand,g_pActiveWindow);
+}
+
+void KviDccFileTransfer::fillStatusString(QString &szBuffer)
+{
+ switch(m_eGeneralStatus)
+ {
+ case Connecting:
+ szBuffer = "connecting";
+ break;
+ case Transferring:
+ szBuffer = "transferring";
+ break;
+ case Failure:
+ szBuffer = "failure";
+ break;
+ case Success:
+ szBuffer = "success";
+ break;
+ default:
+ szBuffer = "unknown";
+ break;
+ }
+}
+
+bool KviDccFileTransfer::active()
+{
+ return ((m_eGeneralStatus == Connecting) || (m_eGeneralStatus == Transferring));
+}
+
+int KviDccFileTransfer::bandwidthLimit()
+{
+ int iLimit = m_uMaxBandwidth; // we have the cached value anyway...
+ if(m_pDescriptor->bRecvFile)
+ {
+ if(m_pSlaveRecvThread)
+ {
+ m_pSlaveRecvThread->initGetInfo();
+ iLimit = (int)m_pSlaveRecvThread->bandwidthLimit();
+ m_pSlaveRecvThread->doneGetInfo();
+ if(iLimit < 0)iLimit = MAX_DCC_BANDWIDTH_LIMIT;
+ }
+ } else {
+ if(m_pSlaveSendThread)
+ {
+ m_pSlaveSendThread->initGetInfo();
+ iLimit = (int)m_pSlaveSendThread->bandwidthLimit();
+ m_pSlaveSendThread->doneGetInfo();
+ if(iLimit < 0)iLimit = MAX_DCC_BANDWIDTH_LIMIT;
+ }
+ }
+ return iLimit;
+}
+
+void KviDccFileTransfer::setBandwidthLimit(int iVal)
+{
+ if(iVal < 0)iVal = MAX_DCC_BANDWIDTH_LIMIT;
+ if(iVal > MAX_DCC_BANDWIDTH_LIMIT)iVal = MAX_DCC_BANDWIDTH_LIMIT;
+ m_uMaxBandwidth = iVal;
+ if(m_pDescriptor->bRecvFile)
+ {
+ if(m_pSlaveRecvThread)
+ {
+ m_pSlaveRecvThread->initGetInfo();
+ m_pSlaveRecvThread->setBandwidthLimit(iVal);
+ m_pSlaveRecvThread->doneGetInfo();
+ }
+ } else {
+ if(m_pSlaveSendThread)
+ {
+ m_pSlaveSendThread->initGetInfo();
+ m_pSlaveSendThread->setBandwidthLimit(iVal);
+ m_pSlaveSendThread->doneGetInfo();
+ }
+ }
+}
+
+unsigned int KviDccFileTransfer::averageSpeed()
+{
+ unsigned int iAvgBandwidth = 0;
+ if(m_pDescriptor->bRecvFile)
+ {
+ if(m_pSlaveRecvThread)
+ {
+ m_pSlaveRecvThread->initGetInfo();
+ iAvgBandwidth = (unsigned int)m_pSlaveRecvThread->averageSpeed();
+ m_pSlaveRecvThread->doneGetInfo();
+ }
+ } else {
+ if(m_pSlaveSendThread)
+ {
+ m_pSlaveSendThread->initGetInfo();
+ iAvgBandwidth = (unsigned int)m_pSlaveSendThread->averageSpeed();
+ m_pSlaveSendThread->doneGetInfo();
+ }
+ }
+ return iAvgBandwidth;
+}
+
+unsigned int KviDccFileTransfer::transferredBytes()
+{
+ unsigned int uTransferred = 0;
+ if(m_pDescriptor->bRecvFile)
+ {
+ if(m_pSlaveRecvThread)
+ {
+ m_pSlaveRecvThread->initGetInfo();
+ uTransferred = m_pSlaveRecvThread->filePosition();
+ m_pSlaveRecvThread->doneGetInfo();
+ }
+ } else {
+ if(m_pSlaveSendThread)
+ {
+ m_pSlaveSendThread->initGetInfo();
+ uTransferred = m_pSlaveSendThread->filePosition();
+ m_pSlaveSendThread->doneGetInfo();
+ }
+ }
+ return uTransferred;
+}
+
+void KviDccFileTransfer::displayPaint(QPainter * p,int column,int width,int height)
+{
+
+ QString txt;
+ bool bIsTerminated = ((m_eGeneralStatus == Success) || (m_eGeneralStatus == Failure));
+
+ switch(column)
+ {
+ case COLUMN_TRANSFERTYPE:
+ {
+ int xoffset = 0;
+ int yoffset = 0;
+ if(m_pDescriptor->bRecvFile)yoffset = 64;
+ switch(m_eGeneralStatus)
+ {
+ case Connecting: xoffset = 0; break;
+ case Transferring: xoffset = 48; break;
+ case Success: xoffset = 96; break;
+ case Failure: xoffset = 144; break;
+ }
+ p->drawPixmap(3,3,*g_pDccFileTransferIcon,xoffset,yoffset,48,64);
+ }
+ break;
+ case COLUMN_FILEINFO:
+ {
+
+ QFontMetrics fm(p->font());
+
+ QString szFrom = __tr2qs_ctx("From: ","dcc");
+ QString szTo = __tr2qs_ctx("To: ","dcc");
+
+ int daW1 = fm.width(szFrom);
+ int daW2 = fm.width(szTo);
+ if(daW1 < daW2)daW1 = daW2;
+ int iLineSpacing = fm.lineSpacing();
+
+ int iY = 4;
+
+ p->setPen(Qt::black);
+
+ KviStr szRemote(KviStr::Format,"dcc://%s@%s:%s/%s",m_pDescriptor->szNick.utf8().data(),m_pDescriptor->szIp.utf8().data(),m_pDescriptor->szPort.utf8().data(),
+ m_pDescriptor->szFileName.utf8().data());
+
+ p->drawText(4 + daW1,iY,width - (8 + daW1),height - 8,Qt::AlignTop | Qt::AlignLeft,
+ m_pDescriptor->bRecvFile ? szRemote.ptr() : m_pDescriptor->szLocalFileName.utf8().data());
+ iY += iLineSpacing;
+
+ p->drawText(4 + daW1,iY,width - (8 + daW1),height - 8,Qt::AlignTop | Qt::AlignLeft,
+ m_pDescriptor->bRecvFile ? m_pDescriptor->szLocalFileName.utf8().data() : szRemote.ptr());
+ iY += iLineSpacing;
+
+
+ p->setPen(Qt::darkGray);
+
+ p->drawText(4,4,width - 8,height - 8,Qt::AlignTop | Qt::AlignLeft,szFrom);
+ p->drawText(4,4 + iLineSpacing,width - 8,height - 8,Qt::AlignTop | Qt::AlignLeft,szTo);
+
+
+ p->setPen(QColor(180,180,200));
+
+ iLineSpacing += 2;
+
+ p->drawRect(4,height - (iLineSpacing + 4),width - 8,iLineSpacing);
+ p->fillRect(5,height - (iLineSpacing + 3),width - 10,iLineSpacing - 2,bIsTerminated ? QColor(210,210,210) : QColor(190,190,240));
+
+ p->setPen(Qt::black);
+
+ p->drawText(7,height - (iLineSpacing + 4),width - 14,iLineSpacing,Qt::AlignVCenter | Qt::AlignLeft,m_szStatusString);
+
+ }
+ break;
+ case COLUMN_PROGRESS:
+ {
+
+ QFontMetrics fm(p->font());
+
+ int iW = width - 8;
+ int iAvgBandwidth = -1;
+ int iInstantSpeed = -1;
+ int iAckedBytes = -1;
+
+ int iEta = -1;
+
+ unsigned int uTransferred = 0;
+
+ if(m_pDescriptor->bRecvFile)
+ {
+ if(m_pSlaveRecvThread)
+ {
+ m_pSlaveRecvThread->initGetInfo();
+ iAvgBandwidth = m_pSlaveRecvThread->averageSpeed();
+ iInstantSpeed = m_pSlaveRecvThread->instantSpeed();
+ uTransferred = m_pSlaveRecvThread->filePosition();
+ m_pSlaveRecvThread->doneGetInfo();
+ }
+ } else {
+ if(m_pSlaveSendThread)
+ {
+ m_pSlaveSendThread->initGetInfo();
+ iAvgBandwidth = m_pSlaveSendThread->averageSpeed();
+ iInstantSpeed = m_pSlaveSendThread->instantSpeed();
+ uTransferred = m_pSlaveSendThread->filePosition();
+ iAckedBytes = m_pSlaveSendThread->ackedBytes();
+ m_pSlaveSendThread->doneGetInfo();
+ }
+ }
+
+ p->setPen(bIsTerminated ? Qt::lightGray : QColor(210,210,240));
+ p->drawRect(4,4,iW,12);
+
+ iW -= 2;
+
+ if(m_uTotalFileSize > 0)
+ {
+ if(iAvgBandwidth > 0)
+ {
+ unsigned int uRemaining = m_uTotalFileSize - uTransferred;
+ iEta = uRemaining / iAvgBandwidth;
+ }
+
+ if(!m_pDescriptor->bNoAcks && (iAckedBytes > 0) && (iAckedBytes < ((int)(uTransferred))))
+ {
+ // we are sending a file and are getting acks
+
+ double dPerc1 = (double)(((double)uTransferred) * 100.0) / (double)m_uTotalFileSize;
+ int iL1 = (int) ((((double)iW) * dPerc1) / 100.0);
+ double dPerc2 = (double)(((double)iAckedBytes) * 100.0) / (double)m_uTotalFileSize;
+ int iL2 = (int) ((((double)iW) * dPerc2) / 100.0);
+ int iW2 = iL1 - iL2;
+ if(iW2 > 0)p->fillRect(5 + iL2,5,iW2,10,bIsTerminated ? QColor(150,130,110) : QColor(220,170,100));
+ p->fillRect(5,5,iL2,10,bIsTerminated ? QColor(140,110,110) : QColor(200,100,100));
+
+ txt = QString(__tr2qs_ctx("%1 of %2 (%3%)","dcc")).arg(KviQString::makeSizeReadable(iAckedBytes)).arg(KviQString::makeSizeReadable(m_uTotalFileSize)).arg(dPerc2,0,'f',2);
+ } else {
+ // we are receiving a file or not sending acks
+ double dPerc = (double)(((double)uTransferred) * 100.0) / (double)m_uTotalFileSize;
+ int iL = (int) ((((double)iW) * dPerc) / 100.0);
+ p->fillRect(5,5,iL,10,bIsTerminated ? QColor(140,110,110) : QColor(200,100,100));
+
+ txt = QString(__tr2qs_ctx("%1 of %2 (%3%)","dcc")).arg(KviQString::makeSizeReadable(uTransferred)).arg(KviQString::makeSizeReadable(m_uTotalFileSize)).arg(dPerc,0,'f',2);
+ }
+
+ } else {
+ txt = QString(__tr2qs_ctx("%1","dcc")).arg(KviQString::makeSizeReadable(uTransferred));
+ }
+
+ p->setPen(Qt::black);
+
+ p->drawText(4,19,width - 8,height - 8,Qt::AlignTop | Qt::AlignLeft,txt);
+
+ int iLeftHalf = (iW - 2) / 2;
+ int iRightHalf = iW - (iLeftHalf + 1);
+ int iLineSpacing = fm.lineSpacing() + 2;
+
+ if(!bIsTerminated)
+ {
+ txt = __tr2qs_ctx("Spd:","dcc");
+ txt += " ";
+ if(iInstantSpeed >= 0)
+ {
+ QString tmpisp;
+ KviNetUtils::formatNetworkBandwidthString(tmpisp,iInstantSpeed);
+ txt += tmpisp;
+ } else {
+ txt += "? B/s";
+ }
+ txt += " [";
+ } else {
+ txt = "";
+ }
+
+ txt += __tr2qs_ctx("Avg:","dcc");
+ txt += " ";
+ if(iAvgBandwidth >= 0)
+ {
+ QString tmpspd;
+ KviNetUtils::formatNetworkBandwidthString(tmpspd,iAvgBandwidth);
+ txt += tmpspd;
+ } else {
+ txt += "? B/s";
+ }
+
+ if(!bIsTerminated)
+ {
+ txt += "]";
+ }
+
+ int iDaH = height - (iLineSpacing + 4);
+
+ p->setPen(QColor(180,180,200));
+ p->drawRect(4,iDaH,iLeftHalf,iLineSpacing);
+ p->fillRect(5,iDaH + 1,iLeftHalf - 2,iLineSpacing - 2,bIsTerminated ? QColor(210,210,210) : QColor(190,190,240));
+ p->setPen(bIsTerminated ? Qt::darkGray : Qt::black);
+ p->drawText(6,iDaH,iLeftHalf - 4,iLineSpacing,Qt::AlignLeft | Qt::AlignVCenter,txt);
+
+ if(bIsTerminated)
+ {
+ if((m_tTransferStartTime != 0) && (m_tTransferEndTime != 0))
+ {
+ QString tot = KviTimeUtils::formatTimeInterval(kvi_timeSpan(m_tTransferEndTime,m_tTransferStartTime),KviTimeUtils::NoLeadingEmptyIntervals | KviTimeUtils::NoLeadingZeroes);
+ txt = "TOT: ";
+ txt += tot;
+ } else {
+ txt = "";
+ }
+ } else {
+ if(iEta >= 0)
+ {
+ QString eta = KviTimeUtils::formatTimeInterval(iEta,KviTimeUtils::NoLeadingEmptyIntervals | KviTimeUtils::NoLeadingZeroes);
+ txt = "ETA: ";
+ txt += eta;
+ } else {
+ txt = "ETA: ?";
+ }
+ }
+
+ p->setPen(QColor(180,180,200));
+ p->drawRect(width - (4 + iRightHalf),iDaH,iRightHalf,iLineSpacing);
+ p->fillRect(width - (3 + iRightHalf),iDaH + 1,iRightHalf - 2,iLineSpacing - 2,bIsTerminated ? QColor(210,210,210) : QColor(190,190,240));
+ p->setPen(bIsTerminated ? Qt::darkGray : Qt::black);
+ p->drawText(width - (2 + iRightHalf),iDaH,iRightHalf - 4,iLineSpacing,Qt::AlignLeft | Qt::AlignVCenter,txt);
+
+ }
+ break;
+ }
+
+}
+
+int KviDccFileTransfer::displayHeight(int iLineSpacing)
+{
+ int iH = (iLineSpacing * 3) + 10;
+ return iH >= 70 ? iH : 70;
+}
+
+QString KviDccFileTransfer::tipText()
+{
+
+ QString s;
+
+ s = QString("<table><tr><td bgcolor=\"#000000\"><font color=\"#FFFFFF\"><b>DCC %1 (ID %2)</b></font></td></tr>").arg(m_szDccType.ptr()).arg(id());
+
+ s += "<tr><td bgcolor=\"#404040\"><font color=\"#FFFFFF\">";
+ s += __tr2qs_ctx("Transfer Log","dcc");
+ s += "</font></td></tr>";
+ s += "<tr><td bgcolor=\"#C0C0C0\">";
+ s += m_szTransferLog;
+ s += "</td></tr>";
+ s += "<table>";
+
+ return s;
+}
+
+void KviDccFileTransfer::init()
+{
+ if(g_pDccFileTransfers)return;
+ g_pDccFileTransfers = new KviPointerList<KviDccFileTransfer>;
+ g_pDccFileTransfers->setAutoDelete(false);
+
+ QPixmap * pix = g_pIconManager->getImage("kvi_dccfiletransfericons.png");
+ if(pix)g_pDccFileTransferIcon = new QPixmap(*pix);
+ else g_pDccFileTransferIcon = new QPixmap(192,128);
+}
+
+void KviDccFileTransfer::done()
+{
+ if(!g_pDccFileTransfers)return;
+ while(KviDccFileTransfer * t = g_pDccFileTransfers->first())
+ delete t;
+ delete g_pDccFileTransfers;
+ g_pDccFileTransfers = 0;
+ delete g_pDccFileTransferIcon;
+ g_pDccFileTransferIcon = 0;
+}
+
+unsigned int KviDccFileTransfer::transferCount()
+{
+ if(!g_pDccFileTransfers)return 0;
+ return g_pDccFileTransfers->count();
+}
+
+KviDccFileTransfer * KviDccFileTransfer::nonFailedTransferWithLocalFileName(const QString &szLocalFileName)
+{
+ if(!g_pDccFileTransfers)return 0;
+ for(KviDccFileTransfer * t = g_pDccFileTransfers->first();t;t = g_pDccFileTransfers->next())
+ {
+#ifdef COMPILE_ON_WINDOWS
+ // on windows the file names are case insensitive
+ if(t->localFileName().lower() == szLocalFileName.lower())
+#else
+ if(t->localFileName() == szLocalFileName)
+#endif
+ {
+ if(t->m_eGeneralStatus != Failure)
+ return t;
+ }
+ }
+ return 0;
+}
+
+
+unsigned int KviDccFileTransfer::runningTransfersCount()
+{
+ if(!g_pDccFileTransfers)return 0;
+ unsigned int cnt = 0;
+ for(KviDccFileTransfer * t = g_pDccFileTransfers->first();t;t = g_pDccFileTransfers->next())
+ {
+ if(t->active())cnt++;
+ }
+ return cnt;
+}
+
+bool KviDccFileTransfer::handleResumeAccepted(const char * filename,const char * port,const char * szZeroPortTag)
+{
+ if(!g_pDccFileTransfers)return false;
+
+ for(KviDccFileTransfer * t = g_pDccFileTransfers->first();t;t = g_pDccFileTransfers->next())
+ {
+ if(t->resumeAccepted(filename,port,szZeroPortTag))return true;
+ }
+
+ return false;
+}
+
+bool KviDccFileTransfer::handleResumeRequest(const char * filename,const char * port,unsigned int filePos)
+{
+ if(!g_pDccFileTransfers)return false;
+
+ for(KviDccFileTransfer * t = g_pDccFileTransfers->first();t;t = g_pDccFileTransfers->next())
+ {
+ if(t->doResume(filename,port,filePos))return true;
+ }
+
+ return false;
+}
+
+void KviDccFileTransfer::outputAndLog(const QString &s)
+{
+ KviWindow * out = transferWindow();
+ addToTransferLog(s);
+ if(out)out->output(KVI_OUT_DCCMSG,"[%Q]: %Q",&m_szTransferIdString,&s);
+}
+
+void KviDccFileTransfer::outputAndLog(int msgtype,const QString &s)
+{
+ KviWindow * out = transferWindow();
+ addToTransferLog(s);
+ if(out)out->output(msgtype,"[%Q]: %Q",&m_szTransferIdString,&s);
+}
+
+
+void KviDccFileTransfer::addToTransferLog(const QString &s)
+{
+ QDateTime dt = QDateTime::currentDateTime();
+ QString ts;
+ ts.sprintf("[%4d.%2d.%2d %2d:%2d:%2d] ",dt.date().year(),dt.date().month(),dt.date().day(),dt.time().hour(),dt.time().minute(),dt.time().second());
+ m_szTransferLog += ts+s;
+ m_szTransferLog += "<br>";
+}
+
+
+void KviDccFileTransfer::connectionInProgress()
+{
+ if(m_pDescriptor->bActive)
+ {
+ // ACTIVE CONNECTION
+// if((kvi_strEqualCS(m_szDccType.ptr(), "RECV")) || (kvi_strEqualCS(m_szDccType.ptr(),"TRECV")))
+// {
+// // FIXME: that's not true!... we're NOT connected here
+// if(TRIGGER_EVENT_5PARAM_RETVALUE(KviEvent_OnDCCGetConnected,this,m_pDescriptor->szPort.ptr(),m_pDescriptor->szFileName.ptr(),m_pDescriptor->szNick.ptr(),m_pDescriptor->szUser.ptr(),m_pDescriptor->szHost.ptr()));
+// } else {
+// if(TRIGGER_EVENT_5PARAM_RETVALUE(KviEvent_OnDCCSendConnected,this,m_pDescriptor->szPort.ptr(),m_pDescriptor->szFileName.ptr(),m_pDescriptor->szNick.ptr(),m_pDescriptor->szUser.ptr(),m_pDescriptor->szHost.ptr()));
+// }
+//
+ m_szStatusString = __tr2qs_ctx("Contacting host %1 on port %2","dcc").arg(m_pDescriptor->szIp).arg(m_pDescriptor->szPort);
+ outputAndLog(m_szStatusString);
+ displayUpdate();
+ return;
+ }
+
+ // PASSIVE CONNECTION
+ m_szStatusString = __tr2qs_ctx("Listening on interface %1 port %2","dcc").arg(m_pMarshal->localIp()).arg(m_pMarshal->localPort());
+ outputAndLog(m_szStatusString);
+
+ if(m_pDescriptor->bSendRequest)
+ {
+ QString ip;
+ if(!m_pDescriptor->szFakeIp.isEmpty())
+ {
+ ip = m_pDescriptor->szFakeIp;
+ } else {
+ ip = m_pDescriptor->szListenIp;
+
+ if(KVI_OPTION_BOOL(KviOption_boolDccGuessIpFromServerWhenLocalIsUnroutable))
+ {
+ if(!KviNetUtils::isRoutableIpString(ip))
+ {
+ // try to get the IP that the IRC server can see
+ if(m_pDescriptor->console())
+ {
+ QString tmp = m_pDescriptor->console()->connection() ? m_pDescriptor->console()->connection()->userInfo()->hostIp() : "";
+ if(!tmp.isEmpty())
+ {
+ ip = tmp;
+ outputAndLog(__tr2qs_ctx("The local IP address is private, determining from IRC server: %1","dcc").arg(ip));
+ } else {
+ outputAndLog(__tr2qs_ctx("The local IP address is private, but unable to determine it from the IRC server","dcc"));
+ }
+ } else {
+ outputAndLog(__tr2qs_ctx("The local IP address is private, but have no IRC server to determine it from","dcc"));
+ }
+ }
+ }
+ }
+
+ KviStr port = !m_pDescriptor->szFakePort.isEmpty() ? m_pDescriptor->szFakePort : m_pMarshal->localPort();
+ //#warning "OPTION FOR SENDING 127.0.0.1 and so on (not an unsigned nuumber)"
+ struct in_addr a;
+ if(KviNetUtils::stringIpToBinaryIp(ip,&a))ip.setNum(htonl(a.s_addr));
+
+ QString tmp = m_pDescriptor->szFileName;
+ // just to be sure
+ KviQString::cutToLast(tmp,'/');
+ KviQString::cutToLast(tmp,'\\');
+
+ QString fName;
+
+ // BUG-TO-BUG mIrc compatibility
+ if(KVI_OPTION_BOOL(KviOption_boolDCCFileTransferReplaceOutgoingSpacesWithUnderscores))
+ tmp.replace(" ","_");
+
+ KviServerParser::encodeCtcpParameter(tmp.utf8().data(),fName);
+ // Zero port requests want DCC SEND as back-request
+ KviStr szReq;
+
+ if(m_pDescriptor->isZeroPortRequest())
+ {
+ szReq = "SEND";
+ m_pDescriptor->console()->connection()->sendFmtData("PRIVMSG %s :%cDCC %s %s %s %s %s %s%c",
+ m_pDescriptor->console()->connection()->encodeText(m_pDescriptor->szNick).data(),
+ 0x01,
+ m_pDescriptor->console()->connection()->encodeText(szReq.ptr()).data(),
+ m_pDescriptor->console()->connection()->encodeText(fName).data(),
+ ip.utf8().data(),port.ptr(),
+ m_pDescriptor->szFileSize.utf8().data(),m_pDescriptor->zeroPortRequestTag(),0x01);
+ } else {
+ szReq = m_szDccType;
+ m_pDescriptor->console()->connection()->sendFmtData("PRIVMSG %s :%cDCC %s %s %s %s %Q%c",
+ m_pDescriptor->console()->connection()->encodeText(m_pDescriptor->szNick).data(),
+ 0x01,
+ m_pDescriptor->console()->connection()->encodeText(szReq.ptr()).data(),
+ m_pDescriptor->console()->connection()->encodeText(fName).data(),
+ ip.utf8().data(),port.ptr(),
+ &(m_pDescriptor->szLocalFileSize),0x01);
+ }
+ outputAndLog(__tr2qs_ctx("Sent DCC %1 request to %2, waiting for remote client to connect...","dcc").arg(szReq.ptr()).arg(m_pDescriptor->szNick));
+ } else {
+ outputAndLog(__tr2qs_ctx("DCC %1 request not sent, awaiting manual connection","dcc").arg(m_szDccType.ptr()));
+ }
+
+ KVS_TRIGGER_EVENT_1(KviEvent_OnDCCFileTransferConnectionInProgress,eventWindow(),m_pDescriptor->idString());
+
+ displayUpdate();
+}
+
+void KviDccFileTransfer::startingSSLHandshake()
+{
+#ifdef COMPILE_SSL_SUPPORT
+ outputAndLog(KVI_OUT_SSL,__tr2qs_ctx("Low-level transport connection established","dcc"));
+ outputAndLog(KVI_OUT_SSL,__tr2qs_ctx("Starting Secure Socket Layer handshake","dcc"));
+#endif
+}
+
+void KviDccFileTransfer::sslError(const char * msg)
+{
+#ifdef COMPILE_SSL_SUPPORT
+ outputAndLog(KVI_OUT_DCCERROR,__tr2qs_ctx("[SSL ERROR]: %1","dcc").arg(msg));
+#endif
+}
+
+
+
+
+bool KviDccFileTransfer::event(QEvent *e)
+{
+ if(e->type() == KVI_THREAD_EVENT)
+ {
+ switch(((KviThreadEvent *)e)->id())
+ {
+ case KVI_DCC_THREAD_EVENT_ERROR:
+ {
+ int * err = ((KviThreadDataEvent<int> *)e)->getData();
+ QString szErrorString = KviError::getDescription(*err);
+ delete err;
+ if(m_pDescriptor->bRecvFile)
+ g_pApp->fileDownloadTerminated(false,m_pDescriptor->szFileName.utf8().data(),m_pDescriptor->szLocalFileName.utf8().data(),m_pDescriptor->szNick.utf8().data(),szErrorString.utf8().data());
+
+ m_szStatusString = __tr2qs_ctx("Transfer failed: ","dcc");
+ m_szStatusString += szErrorString;
+ m_eGeneralStatus = Failure;
+ m_tTransferEndTime = kvi_unixTime();
+
+ KVS_TRIGGER_EVENT_3(KviEvent_OnDCCFileTransferFailed,
+ eventWindow(),
+ szErrorString,
+ (kvs_int_t)(m_pSlaveRecvThread ? m_pSlaveRecvThread->receivedBytes() : m_pSlaveSendThread->sentBytes()),
+ m_pDescriptor->idString());
+
+ outputAndLog(KVI_OUT_DCCERROR,m_szStatusString);
+ displayUpdate();
+ return true;
+ }
+ break;
+ case KVI_DCC_THREAD_EVENT_SUCCESS:
+ {
+ // FIXME: for >= 3.2.0 change this text to
+ // File Upload/Download terminated, or something like this
+ if(KVI_OPTION_BOOL(KviOption_boolNotifyDccSendSuccessInConsole))
+ {
+ KviConsole *c;
+ if(!g_pApp->windowExists(m_pDescriptor->console())) c=g_pApp->activeConsole();
+ else c=m_pDescriptor->console();
+ c->output(KVI_OUT_DCCMSG,__tr2qs_ctx("DCC %s transfer with %Q@%Q:%Q completed: \r![!dbl]play $0\r%s\r","dcc"),
+ m_pDescriptor->bIsTdcc ? (m_pDescriptor->bRecvFile ? "TRECV" : "TSEND") : (m_pDescriptor->bRecvFile ? "RECV" : "SEND"),
+ &(m_pDescriptor->szNick),&(m_pDescriptor->szIp),&(m_pDescriptor->szPort),
+ &(m_pDescriptor->szLocalFileName));
+ }
+ /*
+ // Also add an optional message to the notifier, unless it is an AVATAR download!
+ if(KVI_OPTION_BOOL(KviOption_boolNotifiDccDownloadSuccessInNotifier))
+ {
+ QString szMsg;
+ KviQString::sprintf(szMsg,__tr2qs_ctx(""));
+ g_pApp->notifierMessage(0,KVI_SMALLICON_DCCMSG,szMsg,30);
+ }
+ */
+ if(m_pDescriptor->bRecvFile)g_pApp->fileDownloadTerminated(true,m_pDescriptor->szFileName.utf8().data(),m_pDescriptor->szLocalFileName.utf8().data(),m_pDescriptor->szNick.utf8().data());
+ m_szStatusString = __tr2qs_ctx("Transfer completed","dcc");
+ outputAndLog(m_szStatusString);
+ m_eGeneralStatus = Success;
+ m_tTransferEndTime = kvi_unixTime();
+
+ KVS_TRIGGER_EVENT_2(KviEvent_OnDCCFileTransferSuccess,
+ eventWindow(),
+ (kvs_int_t)(m_pSlaveRecvThread ? m_pSlaveRecvThread->receivedBytes() : m_pSlaveSendThread->sentBytes()),
+ m_pDescriptor->idString());
+
+ displayUpdate();
+
+ if(KVI_OPTION_BOOL(KviOption_boolAutoCloseDccSendOnSuccess))die();
+ return true;
+ }
+ break;
+ case KVI_DCC_THREAD_EVENT_MESSAGE:
+ {
+ KviStr * str = ((KviThreadDataEvent<KviStr> *)e)->getData();
+ outputAndLog(QString(__tr_no_xgettext_ctx(str->ptr(),"dcc")));
+ delete str;
+ return true;
+ }
+ break;
+ default:
+ debug("Invalid event type %d received",((KviThreadEvent *)e)->id());
+ break;
+ }
+ }
+//#warning "Remove this!"
+// if(e->type() == QEvent::Close)debug("Close event received");
+ return KviFileTransfer::event(e);
+}
+
+void KviDccFileTransfer::handleMarshalError(int err)
+{
+ QString szErr = KviError::getDescription(err);
+ m_eGeneralStatus = Failure;
+ m_szStatusString = __tr2qs_ctx("Transfer failed: ","dcc");
+ m_szStatusString += szErr;
+ outputAndLog(m_szStatusString);
+ KVS_TRIGGER_EVENT_3(KviEvent_OnDCCFileTransferFailed,eventWindow(),szErr,(kvs_int_t)0,m_pDescriptor->idString());
+ displayUpdate();
+}
+
+void KviDccFileTransfer::connected()
+{
+ outputAndLog(__tr2qs_ctx("Connected to %1:%2","dcc").arg(m_pMarshal->remoteIp()).arg(m_pMarshal->remotePort()));
+ outputAndLog(__tr2qs_ctx("Local end is %1:%2","dcc").arg(m_pMarshal->localIp()).arg(m_pMarshal->localPort()));
+
+ m_tTransferStartTime = kvi_unixTime();
+
+ if(!(m_pDescriptor->bActive))
+ {
+ m_pDescriptor->szIp = m_pMarshal->remoteIp();
+ m_pDescriptor->szPort = m_pMarshal->remotePort();
+ m_pDescriptor->szHost = m_pMarshal->remoteIp();
+ }
+
+ if(m_pDescriptor->bRecvFile)
+ {
+ KviDccRecvThreadOptions * o = new KviDccRecvThreadOptions;
+ o->szFileName = m_pDescriptor->szLocalFileName.utf8().data();
+ bool bOk;
+ o->iTotalFileSize = m_pDescriptor->szFileSize.toInt(&bOk);
+ if(!bOk)o->iTotalFileSize = -1;
+ o->bResume = m_pDescriptor->bResume;
+ o->iIdleStepLengthInMSec = KVI_OPTION_BOOL(KviOption_boolDccSendForceIdleStep) ? KVI_OPTION_UINT(KviOption_uintDccSendIdleStepInMSec) : 0;
+ o->bIsTdcc = m_pDescriptor->bIsTdcc;
+ o->bSendZeroAck = KVI_OPTION_BOOL(KviOption_boolSendZeroAckInDccRecv);
+ o->bNoAcks = m_pDescriptor->bNoAcks;
+ o->uMaxBandwidth = m_uMaxBandwidth;
+ m_pSlaveRecvThread = new KviDccRecvThread(this,m_pMarshal->releaseSocket(),o);
+ m_pSlaveRecvThread->start();
+ } else {
+ KviDccSendThreadOptions * o = new KviDccSendThreadOptions;
+ o->szFileName = m_pDescriptor->szLocalFileName.utf8().data();
+ o->bFastSend = KVI_OPTION_BOOL(KviOption_boolUseFastDccSend);
+ o->iIdleStepLengthInMSec = KVI_OPTION_BOOL(KviOption_boolDccSendForceIdleStep) ? KVI_OPTION_UINT(KviOption_uintDccSendIdleStepInMSec) : 0;
+ bool bOk;
+ o->bIsTdcc = m_pDescriptor->bIsTdcc;
+ o->iStartPosition = m_pDescriptor->szFileSize.toInt(&bOk);
+ if(!bOk || (o->iStartPosition < 0))o->iStartPosition = 0;
+ o->iPacketSize = KVI_OPTION_UINT(KviOption_uintDccSendPacketSize);
+ if(o->iPacketSize < 32)o->iPacketSize = 32;
+ o->uMaxBandwidth = m_uMaxBandwidth;
+ o->bNoAcks = m_pDescriptor->bNoAcks;
+ m_pSlaveSendThread = new KviDccSendThread(this,m_pMarshal->releaseSocket(),o);
+ m_pSlaveSendThread->start();
+ }
+
+ m_eGeneralStatus = Transferring;
+ m_szStatusString = __tr2qs_ctx("Transferring data","dcc");
+
+ KVS_TRIGGER_EVENT_1(KviEvent_OnDCCFileTransferBegin,eventWindow(),m_pDescriptor->idString());
+
+ outputAndLog(m_szStatusString);
+ displayUpdate();
+}
+
+bool KviDccFileTransfer::resumeAccepted(const char *filename,const char *port,const char *szZeroPortTag)
+{
+ if(!(kvi_strEqualCI(filename,m_pDescriptor->szFileName.utf8().data()) || KVI_OPTION_BOOL(KviOption_boolAcceptBrokenFileNameDccResumeRequests)))
+ return false;
+
+ if(!(kvi_strEqualCI(port,m_pDescriptor->szPort.utf8().data()) &&
+ (!m_pSlaveRecvThread) && m_pDescriptor->bResume && m_pDescriptor->bRecvFile && m_pResumeTimer))
+ return false;
+
+ if(kvi_strEqualCI(port,"0"))
+ {
+ if(!kvi_strEqualCI(szZeroPortTag,m_pDescriptor->zeroPortRequestTag()))
+ return false;
+ }
+
+ delete m_pResumeTimer;
+ m_pResumeTimer = 0;
+
+ outputAndLog(__tr2qs_ctx("RESUME accepted, transfer will begin at position %1","dcc").arg(m_pDescriptor->szLocalFileSize));
+
+ listenOrConnect();
+
+ /*
+ int ret = m_pMarshal->dccConnect(m_pDescriptor->szIp.utf8().data(),
+ m_pDescriptor->szPort.utf8().data(),m_pDescriptor->bDoTimeout);
+
+ if(ret != KviError_success)handleMarshalError(ret);
+ else {
+ m_szStatusString = __tr2qs_ctx("Contacting host %1 on port %2","dcc").arg(m_pDescriptor->szIp).arg(m_pDescriptor->szPort);
+ outputAndLog(m_szStatusString);
+ displayUpdate();
+ }
+ */
+
+ return true;
+}
+
+bool KviDccFileTransfer::doResume(const char * filename,const char * port,unsigned int filePos)
+{
+ if(KviQString::equalCI(port,m_pMarshal->dccPort()) &&
+ (!m_pSlaveRecvThread) && (!m_pDescriptor->bRecvFile))
+ {
+ if(KviQString::equalCI(filename,m_pDescriptor->szFileName) || KVI_OPTION_BOOL(KviOption_boolAcceptBrokenFileNameDccResumeRequests))
+ {
+ bool bOk;
+ unsigned int iLocalFileSize = m_pDescriptor->szLocalFileSize.toUInt(&bOk);
+ if(!bOk)
+ {
+ // ops...internal error
+ outputAndLog(KVI_OUT_DCCERROR,__tr2qs_ctx("Internal error in RESUME request","dcc"));
+ return false;
+ }
+ if(iLocalFileSize <= filePos)
+ {
+ outputAndLog(KVI_OUT_DCCERROR,__tr2qs_ctx("Invalid RESUME request: Position %1 is larger than file size","dcc").arg(filePos));
+ return false;
+ }
+
+ outputAndLog(KVI_OUT_DCCERROR,__tr2qs_ctx("Accepting RESUME request, transfer will begin at position %1","dcc").arg(filePos));
+
+ m_pDescriptor->szFileSize.setNum(filePos);
+
+
+ KviStr szBuffy;
+ KviServerParser::encodeCtcpParameter(filename,szBuffy);
+
+ m_pDescriptor->console()->connection()->sendFmtData("PRIVMSG %s :%cDCC ACCEPT %s %s %u%c",
+ m_pDescriptor->console()->connection()->encodeText(m_pDescriptor->szNick).data(),
+ 0x01,
+ m_pDescriptor->console()->connection()->encodeText(szBuffy.ptr()).data(),
+ port,filePos,0x01);
+ return true;
+ }
+ }
+ return false;
+}
+
+
+
+
+
+
+KviDccFileTransferBandwidthDialog::KviDccFileTransferBandwidthDialog(QWidget * pParent,KviDccFileTransfer * t)
+: QDialog(pParent)
+{
+ QGridLayout * g = new QGridLayout(this,3,3,4,4);
+
+ m_pTransfer = t;
+ int iVal = m_pTransfer->bandwidthLimit();
+
+ QString szText = __tr2qs_ctx("Configure bandwidth for DCC transfer %1","dcc").arg(t->id());
+ setCaption(szText);
+
+ szText = t->isFileUpload() ? __tr2qs_ctx("Limit upload bandwidth to","dcc") : __tr2qs_ctx("Limit download bandwidth to","dcc");
+
+ m_pEnableLimitCheck = new KviStyledCheckBox(szText,this);
+ g->addWidget(m_pEnableLimitCheck,0,0);
+
+ m_pEnableLimitCheck->setChecked((iVal >= 0) && (iVal < MAX_DCC_BANDWIDTH_LIMIT));
+
+ m_pLimitBox = new QSpinBox(0,MAX_DCC_BANDWIDTH_LIMIT-1,1,this);
+ m_pLimitBox->setEnabled((iVal >= 0) && (iVal < MAX_DCC_BANDWIDTH_LIMIT));
+ connect(m_pEnableLimitCheck,SIGNAL(toggled(bool)),m_pLimitBox,SLOT(setEnabled(bool)));
+ g->addMultiCellWidget(m_pLimitBox,0,0,1,2);
+
+ szText = " ";
+ szText += __tr2qs_ctx("bytes/sec","dcc");
+ m_pLimitBox->setSuffix(szText);
+ m_pLimitBox->setValue(iVal < MAX_DCC_BANDWIDTH_LIMIT ? iVal : 0);
+
+ QPushButton * pb = new QPushButton(__tr2qs_ctx("OK","dcc"),this);
+ connect(pb,SIGNAL(clicked()),this,SLOT(okClicked()));
+ pb->setMinimumWidth(80);
+ g->addWidget(pb,2,2);
+
+ pb = new QPushButton(__tr2qs_ctx("Cancel","dcc"),this);
+ connect(pb,SIGNAL(clicked()),this,SLOT(cancelClicked()));
+ pb->setMinimumWidth(80);
+ g->addWidget(pb,2,1);
+
+ g->setColStretch(0,1);
+ g->setRowStretch(1,1);
+}
+
+KviDccFileTransferBandwidthDialog::~KviDccFileTransferBandwidthDialog()
+{
+}
+
+void KviDccFileTransferBandwidthDialog::okClicked()
+{
+ int iVal = MAX_DCC_BANDWIDTH_LIMIT;
+ if(m_pEnableLimitCheck->isChecked())
+ {
+ iVal = m_pLimitBox->value();
+ if(iVal < 0)iVal = MAX_DCC_BANDWIDTH_LIMIT;
+ if(iVal > MAX_DCC_BANDWIDTH_LIMIT)iVal = MAX_DCC_BANDWIDTH_LIMIT;
+ }
+ m_pTransfer->setBandwidthLimit(iVal);
+ delete this;
+}
+
+void KviDccFileTransferBandwidthDialog::cancelClicked()
+{
+ delete this;
+}
+
+void KviDccFileTransferBandwidthDialog::closeEvent(QCloseEvent * e)
+{
+ e->ignore();
+ delete this;
+}
+
+
+
+
+#include "m_send.moc"
diff --git a/src/modules/dcc/send.h b/src/modules/dcc/send.h
new file mode 100644
index 00000000..636f2b3b
--- /dev/null
+++ b/src/modules/dcc/send.h
@@ -0,0 +1,260 @@
+#ifndef _SEND_H_
+#define _SEND_H_
+//=============================================================================
+//
+// File : send.h
+// Creation date : Tue Sep 24 09 2000 15:06:12 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_window.h"
+#include "kvi_string.h"
+
+#include "descriptor.h"
+#include "window.h"
+#include "thread.h"
+
+#include "kvi_sockettype.h"
+
+#include "kvi_pointerlist.h"
+#include <qlabel.h>
+#include <qprogressbar.h>
+#include "kvi_tal_popupmenu.h"
+#include "kvi_tal_hbox.h"
+#include "kvi_tal_vbox.h"
+#include <qfile.h>
+#include <qdialog.h>
+
+#include "kvi_filetransfer.h"
+#include "kvi_time.h"
+
+
+typedef struct _KviDccSendThreadOptions
+{
+ KviStr szFileName;
+ int iStartPosition;
+ int iPacketSize;
+ int iIdleStepLengthInMSec;
+ bool bFastSend;
+ bool bNoAcks;
+ bool bIsTdcc;
+ unsigned int uMaxBandwidth;
+} KviDccSendThreadOptions;
+
+
+class KviDccSendThread : public KviDccThread
+{
+public:
+ KviDccSendThread(QObject * par,kvi_socket_t fd,KviDccSendThreadOptions * opt);
+ ~KviDccSendThread();
+private:
+ // stats: SHARED!!!
+ int m_iAverageSpeed;
+ int m_iInstantSpeed;
+ int m_iFilePosition;
+ int m_iAckedBytes;
+ int m_iTotalSentBytes;
+ // internal
+ unsigned long m_uStartTime;
+ unsigned long m_uInstantSpeedInterval;
+ int m_iInstantSentBytes;
+ KviDccSendThreadOptions * m_pOpt;
+ KviMSecTimeInterval * m_pTimeInterval; // used for computing the instant bandwidth but not only
+public:
+ void initGetInfo();
+ int averageSpeed(){ return m_iAverageSpeed; };
+ int instantSpeed(){ return m_iInstantSpeed; };
+ int filePosition(){ return m_iFilePosition; };
+ // sent ONLY in this session
+ int sentBytes(){ return m_iTotalSentBytes; };
+ int ackedBytes(){ return m_iAckedBytes; };
+ unsigned int bandwidthLimit(){ return m_pOpt->uMaxBandwidth; };
+ void setBandwidthLimit(unsigned int uMaxBandwidth){ m_pOpt->uMaxBandwidth = uMaxBandwidth; };
+ void doneGetInfo();
+protected:
+ void updateStats();
+ virtual void run();
+};
+
+typedef struct _KviDccRecvThreadOptions
+{
+ bool bResume;
+ KviStr szFileName;
+ int iTotalFileSize;
+ int iIdleStepLengthInMSec;
+ bool bSendZeroAck;
+ bool bNoAcks;
+ bool bIsTdcc;
+ unsigned int uMaxBandwidth;
+} KviDccRecvThreadOptions;
+
+class KviDccRecvThread : public KviDccThread
+{
+public:
+ KviDccRecvThread(QObject * par,kvi_socket_t fd,KviDccRecvThreadOptions * opt);
+ ~KviDccRecvThread();
+protected:
+ KviDccRecvThreadOptions * m_pOpt;
+
+ // stats: SHARED!
+ int m_iAverageSpeed;
+ int m_iInstantSpeed;
+ int m_iFilePosition;
+ int m_iTotalReceivedBytes;
+
+ // internal
+ unsigned long m_uStartTime;
+ KviMSecTimeInterval * m_pTimeInterval; // used for computing the instant bandwidth
+ int m_iInstantReceivedBytes;
+ unsigned long m_uInstantSpeedInterval;
+ QFile * m_pFile;
+public:
+ void initGetInfo();
+ int averageSpeed(){ return m_iAverageSpeed; };
+ int instantSpeed(){ return m_iInstantSpeed; };
+ int filePosition(){ return m_iFilePosition; };
+ // received ONLY in this session
+ int receivedBytes(){ return m_iTotalReceivedBytes; };
+ unsigned int bandwidthLimit(){ return m_pOpt->uMaxBandwidth; };
+ void setBandwidthLimit(unsigned int uMaxBandwidth){ m_pOpt->uMaxBandwidth = uMaxBandwidth; };
+ void doneGetInfo();
+protected:
+ void postMessageEvent(const char * msg);
+ void updateStats();
+ bool sendAck(int filePos);
+ virtual void run();
+};
+
+class KviDccFileTransfer;
+class QSpinBox;
+class QTimer;
+
+#include "kvi_styled_controls.h"
+
+class KviDccFileTransferBandwidthDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ KviDccFileTransferBandwidthDialog(QWidget * pParent,KviDccFileTransfer * t);
+ ~KviDccFileTransferBandwidthDialog();
+protected:
+ KviDccFileTransfer * m_pTransfer;
+ KviStyledCheckBox * m_pEnableLimitCheck;
+ QSpinBox * m_pLimitBox;
+protected:
+ virtual void closeEvent(QCloseEvent *e);
+protected slots:
+ void okClicked();
+ void cancelClicked();
+};
+
+
+class KviDccMarshal;
+class QPainter;
+class KviTalPopupMenu;
+
+class KviDccFileTransfer : public KviFileTransfer, public KviDccMarshalOutputContext
+{
+ enum GeneralStatus { Connecting , Transferring , Success , Failure };
+ Q_OBJECT
+public:
+ KviDccFileTransfer(KviDccDescriptor * dcc);
+ ~KviDccFileTransfer();
+private:
+ KviDccSendThread * m_pSlaveSendThread;
+ KviDccRecvThread * m_pSlaveRecvThread;
+ KviDccDescriptor * m_pDescriptor;
+ KviDccMarshal * m_pMarshal;
+
+ KviStr m_szTarget;
+ KviStr m_szDccType;
+ QString m_szTransferIdString;
+
+ QString m_szStatusString;
+ GeneralStatus m_eGeneralStatus;
+
+ QString m_szTransferLog; // html
+
+ kvi_time_t m_tTransferStartTime;
+ kvi_time_t m_tTransferEndTime;
+ // cached stats
+ unsigned int m_uTotalFileSize; // total file size to transfer
+
+ unsigned int m_uMaxBandwidth;
+ KviDccFileTransferBandwidthDialog * m_pBandwidthDialog;
+
+ QTimer * m_pResumeTimer; // used to signal resume timeout
+public:
+ bool resumeAccepted(const char * filename,const char * port,const char *szZeroPortTag);
+ bool doResume(const char * filename,const char * port,unsigned int filePos);
+
+ static void init();
+ static void done();
+ static unsigned int runningTransfersCount();
+ static KviDccFileTransfer * nonFailedTransferWithLocalFileName(const QString &szLocalFileName);
+ static unsigned int transferCount();
+ static bool handleResumeAccepted(const char * filename,const char * port,const char * szZeroPortTag);
+ static bool handleResumeRequest(const char * filename,const char * port,unsigned int filePos);
+
+ virtual bool event(QEvent *e);
+
+ virtual KviWindow * dccMarshalOutputWindow();
+ virtual const char * dccMarshalOutputContextString();
+
+ virtual void displayPaint(QPainter * p,int column,int width,int height);
+ virtual int displayHeight(int iLineSpacing);
+ virtual void fillContextPopup(KviTalPopupMenu * m,int column);
+ virtual void fillStatusString(QString &szBuffer);
+ virtual bool active();
+ virtual void die();
+ virtual QString tipText();
+ virtual QString localFileName();
+
+ bool isFileUpload(){ return m_pDescriptor->isFileUpload(); };
+
+ unsigned int averageSpeed();
+ unsigned int transferredBytes();
+
+ int bandwidthLimit();
+ void setBandwidthLimit(int iVal);
+protected:
+ void startConnection();
+ void listenOrConnect();
+ void addToTransferLog(const QString &s);
+ void outputAndLog(const QString &s);
+ void outputAndLog(int msgtype,const QString &s);
+ KviWindow * eventWindow();
+protected slots:
+ void connectionInProgress();
+ void sslError(const char * msg);
+ void startingSSLHandshake();
+ void handleMarshalError(int err);
+ void connected();
+ void bandwidthDialogDestroyed();
+ void configureBandwidth();
+ void resumeTimedOut();
+public slots:
+ void abort();
+ void retryDCC();
+ void retryTDCC();
+ void retryRevDCC();
+};
+
+#endif //_SEND_H_
diff --git a/src/modules/dcc/thread.cpp b/src/modules/dcc/thread.cpp
new file mode 100644
index 00000000..7ae38bbe
--- /dev/null
+++ b/src/modules/dcc/thread.cpp
@@ -0,0 +1,111 @@
+//
+// File : thread.cpp
+// Creation date : Tue Sep 20 09 2000 18:29:51 CEST Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "thread.h"
+#define _KVI_DEBUG_CHECK_RANGE_
+#include "kvi_debug.h"
+#include "kvi_window.h"
+#include "kvi_error.h"
+#include "kvi_memmove.h"
+#include "kvi_malloc.h"
+#include "kvi_netutils.h"
+#include "kvi_socket.h"
+#ifdef COMPILE_SSL_SUPPORT
+ #include "kvi_sslmaster.h"
+#endif
+
+KviDccThread::KviDccThread(QObject * par,kvi_socket_t fd)
+: KviSensitiveThread()
+{
+ m_pParent = par;
+ m_fd = fd;
+ m_pMutex = new KviMutex();
+#ifdef COMPILE_SSL_SUPPORT
+// debug("CLEARING SSL IN KviDccThread constructor");
+ m_pSSL = 0;
+#endif
+}
+
+KviDccThread::~KviDccThread()
+{
+#ifdef COMPILE_SSL_SUPPORT
+ if(m_pSSL)KviSSLMaster::freeSSL(m_pSSL);
+ m_pSSL = 0;
+#endif
+ if(m_fd != KVI_INVALID_SOCKET)kvi_socket_close(m_fd);
+ __range_invalid(m_pMutex->locked());
+ delete m_pMutex;
+}
+
+#ifdef COMPILE_SSL_SUPPORT
+void KviDccThread::setSSL(KviSSL * s)
+{
+ if(m_pSSL)KviSSLMaster::freeSSL(m_pSSL);
+ m_pSSL = s;
+}
+#endif
+
+bool KviDccThread::handleInvalidSocketRead(int readLen)
+{
+ __range_valid(readLen < 1);
+ if(readLen == 0)
+ {
+ // connection closed
+ postErrorEvent(KviError_remoteEndClosedConnection);
+ return false;
+ } else {
+ // error ?
+ int err = kvi_socket_error();
+ if((err != EINTR) && (err != EAGAIN))
+ {
+ postErrorEvent(KviError::translateSystemError(err));
+ return false;
+ }
+ }
+ return true; // continue
+}
+
+#ifdef COMPILE_SSL_SUPPORT
+void KviDccThread::raiseSSLError()
+{
+ KviStr buffer;
+ while(m_pSSL->getLastErrorString(buffer))
+ {
+ KviStr msg(KviStr::Format,"[SSL ERROR]: %s",buffer.ptr());
+ postMessageEvent(msg.ptr());
+ }
+}
+#endif
+
+void KviDccThread::postErrorEvent(int err)
+{
+ KviThreadDataEvent<int> * e = new KviThreadDataEvent<int>(KVI_DCC_THREAD_EVENT_ERROR);
+ e->setData(new int(err));
+ postEvent(m_pParent,e);
+}
+
+void KviDccThread::postMessageEvent(const char * message)
+{
+ KviThreadDataEvent<KviStr> * e = new KviThreadDataEvent<KviStr>(KVI_DCC_THREAD_EVENT_MESSAGE);
+ e->setData(new KviStr(message));
+ postEvent(m_pParent,e);
+}
diff --git a/src/modules/dcc/thread.h b/src/modules/dcc/thread.h
new file mode 100644
index 00000000..3d56661d
--- /dev/null
+++ b/src/modules/dcc/thread.h
@@ -0,0 +1,79 @@
+#ifndef _THREAD_H_
+#define _THREAD_H_
+//
+// File : thread.h
+// Creation date : Tue Sep 20 09 2000 18:28:44 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+#include "kvi_thread.h"
+#include "kvi_sockettype.h"
+
+#include "kvi_pointerlist.h"
+
+#include <qobject.h>
+
+#ifdef COMPILE_SSL_SUPPORT
+ #include "kvi_ssl.h"
+#endif
+
+// KviThreadDataEvent<int>
+#define KVI_DCC_THREAD_EVENT_ERROR (KVI_THREAD_USER_EVENT_BASE + 1)
+// KviThreadDataEvent<KviStr>
+#define KVI_DCC_THREAD_EVENT_DATA (KVI_THREAD_USER_EVENT_BASE + 2)
+// KviThreadEvent
+#define KVI_DCC_THREAD_EVENT_SUCCESS (KVI_THREAD_USER_EVENT_BASE + 3)
+// KviThreadDataEvent<KviStr>
+#define KVI_DCC_THREAD_EVENT_MESSAGE (KVI_THREAD_USER_EVENT_BASE + 4)
+// KviThreadDataEvent<int>
+#define KVI_DCC_THREAD_EVENT_ACTION (KVI_THREAD_USER_EVENT_BASE + 5)
+
+typedef struct _KviDccThreadIncomingData
+{
+ int iLen;
+ char * buffer;
+} KviDccThreadIncomingData;
+
+class KviDccThread : public KviSensitiveThread
+{
+public:
+ KviDccThread(QObject * par,kvi_socket_t fd);
+ ~KviDccThread();
+protected:
+ KviMutex * m_pMutex; // OWNED! PROTECTS m_pOutBuffers
+ kvi_socket_t m_fd;
+ QObject * m_pParent; // READ ONLY!
+#ifdef COMPILE_SSL_SUPPORT
+ KviSSL * m_pSSL;
+#endif
+protected:
+ bool handleInvalidSocketRead(int readLen);
+public:
+ QObject * parent(){ return m_pParent; };
+ void postErrorEvent(int err);
+ // Warning!..newer call __tr() here!...use __tr_no_lookup()
+ void postMessageEvent(const char * message);
+#ifdef COMPILE_SSL_SUPPORT
+ void raiseSSLError();
+ void setSSL(KviSSL * s);
+#endif
+};
+
+#endif //_THREAD_H_
diff --git a/src/modules/dcc/utils.cpp b/src/modules/dcc/utils.cpp
new file mode 100644
index 00000000..8d3229e7
--- /dev/null
+++ b/src/modules/dcc/utils.cpp
@@ -0,0 +1,169 @@
+//
+// File : utils.cpp
+// Creation date : Tue Jul 23 02:54:44 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#define _UTILS_CPP_
+
+#include "utils.h"
+
+#include "kvi_options.h"
+#include "kvi_locale.h"
+#include "kvi_netutils.h"
+#include "kvi_ircsocket.h"
+#include "kvi_qstring.h"
+
+/*
+bool dcc_module_get_listen_ip_address(KviCommand *c,KviConsole * pConsole,QString &szListenIp)
+{
+ //
+ // Find an interface suitable for listening....
+ // Either from user options or from the current connection...
+ //
+
+ if(KVI_OPTION_BOOL(KviOption_boolDccListenOnSpecifiedInterfaceByDefault))
+ {
+ KVI_OPTION_STRING(KviOption_stringDccListenDefaultInterface).stripWhiteSpace();
+ if(!KVI_OPTION_STRING(KviOption_stringDccListenDefaultInterface).isEmpty())
+ {
+ if(kvi_isValidStringIp(KVI_OPTION_STRING(KviOption_stringDccListenDefaultInterface).utf8().data()))
+ {
+ if(KviQString::equalCI(KVI_OPTION_STRING(KviOption_stringDccListenDefaultInterface),"0.0.0.0"))
+ {
+ // Try to find the first available IpV4 interface
+ if(!kvi_getLocalHostAddress(szListenIp))
+ {
+ if(c)c->warning(__tr2qs_ctx("Can't retrieve a suitable local IPV4 address","dcc"),
+ KVI_OPTION_STRING(KviOption_stringDccListenDefaultInterface).utf8().data());
+ return false;
+ }
+ } else {
+ szListenIp = KVI_OPTION_STRING(KviOption_stringDccListenDefaultInterface);
+ }
+ return true;
+ }
+#ifdef COMPILE_IPV6_SUPPORT
+ if(kvi_isValidStringIp_V6(KVI_OPTION_STRING(KviOption_stringDccListenDefaultInterface).utf8().data()))
+ {
+ szListenIp = KVI_OPTION_STRING(KviOption_stringDccListenDefaultInterface);
+ } else {
+#endif
+ if(!kvi_getInterfaceAddress(KVI_OPTION_STRING(KviOption_stringDccListenDefaultInterface).utf8().data(),szListenIp))
+ {
+ KVI_OPTION_BOOL(KviOption_boolDccListenOnSpecifiedInterfaceByDefault) = false;
+ if(c)c->warning(__tr2qs_ctx("Can't listen on default interface '%s': fix it in the options dialog, disabling the option (so the next dcc will work)","dcc"),
+ KVI_OPTION_STRING(KviOption_stringDccListenDefaultInterface).utf8().data());
+ return false;
+ }
+#ifdef COMPILE_IPV6_SUPPORT
+ }
+#endif
+ return true;
+ } else {
+ // the option was empty.. disable it
+ KVI_OPTION_BOOL(KviOption_boolDccListenOnSpecifiedInterfaceByDefault) = false;
+ }
+ }
+
+ if(pConsole)
+ {
+ if(pConsole->isConnected())
+ {
+ //#warning "The IPV6 choice is not OK here.... and maybe allow to bind to specified ports"
+ pConsole->socket()->getLocalHostIp(szListenIp,pConsole->isIpV6Connection());
+ } else {
+ szListenIp = "0.0.0.0"; // huh ? :)
+ }
+ } else {
+ szListenIp = "0.0.0.0";
+ }
+
+ return true;
+}
+*/
+
+
+bool dcc_kvs_get_listen_ip_address(KviKvsModuleCommandCall *c,KviConsole * pConsole,QString &szListenIp)
+{
+ //
+ // Find an interface suitable for listening....
+ // Either from user options or from the current connection...
+ //
+
+ if(KVI_OPTION_BOOL(KviOption_boolDccListenOnSpecifiedInterfaceByDefault))
+ {
+ KVI_OPTION_STRING(KviOption_stringDccListenDefaultInterface).stripWhiteSpace();
+ if(!KVI_OPTION_STRING(KviOption_stringDccListenDefaultInterface).isEmpty())
+ {
+ if(kvi_isValidStringIp(KVI_OPTION_STRING(KviOption_stringDccListenDefaultInterface).utf8().data()))
+ {
+ if(KviQString::equalCI(KVI_OPTION_STRING(KviOption_stringDccListenDefaultInterface),"0.0.0.0"))
+ {
+ // Try to find the first available IpV4 interface
+ if(!kvi_getLocalHostAddress(szListenIp))
+ {
+ if(c)c->warning(__tr2qs_ctx("Can't retrieve a suitable local IPV4 address","dcc"),
+ KVI_OPTION_STRING(KviOption_stringDccListenDefaultInterface).utf8().data());
+ return false;
+ }
+ } else {
+ szListenIp = KVI_OPTION_STRING(KviOption_stringDccListenDefaultInterface);
+ }
+ return true;
+ }
+#ifdef COMPILE_IPV6_SUPPORT
+ if(kvi_isValidStringIp_V6(KVI_OPTION_STRING(KviOption_stringDccListenDefaultInterface).utf8().data()))
+ {
+ szListenIp = KVI_OPTION_STRING(KviOption_stringDccListenDefaultInterface);
+ } else {
+#endif
+ if(!kvi_getInterfaceAddress(KVI_OPTION_STRING(KviOption_stringDccListenDefaultInterface).utf8().data(),szListenIp))
+ {
+ KVI_OPTION_BOOL(KviOption_boolDccListenOnSpecifiedInterfaceByDefault) = false;
+ if(c)c->warning(__tr2qs_ctx("Can't listen on default interface '%s': fix it in the options dialog, disabling the option (so the next dcc will work)","dcc"),
+ KVI_OPTION_STRING(KviOption_stringDccListenDefaultInterface).utf8().data());
+ return false;
+ }
+#ifdef COMPILE_IPV6_SUPPORT
+ }
+#endif
+ return true;
+ } else {
+ // the option was empty.. disable it
+ KVI_OPTION_BOOL(KviOption_boolDccListenOnSpecifiedInterfaceByDefault) = false;
+ }
+ }
+
+ if(pConsole)
+ {
+ if(pConsole->isConnected())
+ {
+ //#warning "The IPV6 choice is not OK here.... and maybe allow to bind to specified ports"
+ pConsole->socket()->getLocalHostIp(szListenIp,pConsole->isIpV6Connection());
+ } else {
+ szListenIp = "0.0.0.0"; // huh ? :)
+ }
+ } else {
+ szListenIp = "0.0.0.0";
+ }
+
+ return true;
+}
+
diff --git a/src/modules/dcc/utils.h b/src/modules/dcc/utils.h
new file mode 100644
index 00000000..992814f2
--- /dev/null
+++ b/src/modules/dcc/utils.h
@@ -0,0 +1,34 @@
+#ifndef _UTILS_H_
+#define _UTILS_H_
+//
+// File : utils.h
+// Creation date : Tue Jul 23 02:54:45 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+#include "kvi_string.h"
+#include "kvi_console.h"
+#include "kvi_kvs_moduleinterface.h"
+
+#ifndef _UTILS_CPP_
+ extern bool dcc_kvs_get_listen_ip_address(KviKvsModuleCommandCall *c,KviConsole * pConsole,QString &szListenIp);
+#endif
+
+#endif //_UTILS_H_
diff --git a/src/modules/dcc/voice.cpp b/src/modules/dcc/voice.cpp
new file mode 100644
index 00000000..2e34df2f
--- /dev/null
+++ b/src/modules/dcc/voice.cpp
@@ -0,0 +1,1041 @@
+//
+// File : voice.cpp
+// Creation date : Thu Aug 23 04:08:09 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "voice.h"
+#include "marshal.h"
+#include "broker.h"
+
+#include "kvi_settings.h"
+#include "kvi_iconmanager.h"
+#include "kvi_ircview.h"
+#include "kvi_locale.h"
+#include "kvi_out.h"
+#include "kvi_error.h"
+#include "kvi_netutils.h"
+#include "kvi_options.h"
+#include "kvi_console.h"
+#include "kvi_malloc.h"
+#include "kvi_socket.h"
+#include "kvi_ircconnection.h"
+
+#include "adpcmcodec.h"
+#include "gsmcodec.h"
+
+#include <qframe.h>
+#include <qsplitter.h>
+#include "kvi_tal_vbox.h"
+#include <qslider.h>
+#include <qtooltip.h>
+
+#ifndef COMPILE_ON_WINDOWS
+ #include <sys/time.h>
+ #include <sys/types.h>
+ #include <unistd.h>
+ #include <errno.h>
+ #include <fcntl.h>
+//#include "kvi_error.h"
+
+#include <sys/stat.h> // for open()
+#include <sys/ioctl.h> // for ioctl()
+#endif //!COMPILE_ON_WIDNOWS
+
+extern KviDccBroker * g_pDccBroker;
+
+//Check for the *SS Api....we don't want to fail here...
+
+#ifndef COMPILE_DISABLE_DCC_VOICE
+ #ifdef HAVE_LINUX_SOUNDCARD_H
+ #include <linux/soundcard.h>
+ #else
+ #ifdef HAVE_SYS_SOUNDCARD_H
+ #include <sys/soundcard.h>
+ #else
+ #ifdef HAVE_SOUNDCARD_H
+ #include <soundcard.h>
+ #else
+ //CAN NOT COMPILE :(
+ #define COMPILE_DISABLE_DCC_VOICE
+ #ifndef COMPILE_ON_WINDOWS
+ #warning "Cannot find the soundcard.h header; you will NOT be able to use DCC Voice"
+ #endif
+ #endif
+ #endif
+ #endif
+#endif
+
+
+//#define KVI_AUDIO_DEVICE "/dev/dsp"
+// 32 fragments , 512 bytes
+#define KVI_SNDCTL_FRAG_SIZE 0x00B00009
+#define KVI_FRAGMENT_SIZE_IN_BYTES 512
+#define KVI_FORMAT AFMT_S16_LE
+#define KVI_NUM_CHANNELS 1
+
+
+bool kvi_dcc_voice_is_valid_codec(const char * codecName)
+{
+#ifdef COMPILE_USE_GSM
+ if(kvi_strEqualCI("gsm",codecName))
+ {
+ return kvi_gsm_codec_init();
+ }
+#endif
+ if(kvi_strEqualCI("adpcm",codecName))return true;
+ if(kvi_strEqualCI("null",codecName))return true;
+ return false;
+}
+
+static KviDccVoiceCodec * kvi_dcc_voice_get_codec(const char * codecName)
+{
+#ifdef COMPILE_USE_GSM
+ if(kvi_strEqualCI("gsm",codecName))
+ {
+ if(kvi_gsm_codec_init())return new KviDccVoiceGsmCodec();
+ }
+#endif
+ if(kvi_strEqualCI("adpcm",codecName))return new KviDccVoiceAdpcmCodec();
+ if(kvi_strEqualCI("null",codecName))return new KviDccVoiceNullCodec();
+ return new KviDccVoiceAdpcmCodec();
+}
+
+
+KviDccVoiceThread::KviDccVoiceThread(KviWindow * wnd,kvi_socket_t fd,KviDccVoiceThreadOptions * opt)
+: KviDccThread(wnd,fd)
+{
+#ifndef COMPILE_DISABLE_DCC_VOICE
+ m_pOpt = opt;
+ m_bPlaying = false;
+ m_bRecording = false;
+ m_bSoundcardChecked = false;
+ m_soundFd = -1;
+ m_soundFdMode = 0;
+ m_pInfoMutex = new KviMutex();
+ m_bRecordingRequestPending = false;
+#endif
+}
+
+KviDccVoiceThread::~KviDccVoiceThread()
+{
+#ifndef COMPILE_DISABLE_DCC_VOICE
+ delete m_pOpt->pCodec;
+ delete m_pOpt;
+ delete m_pInfoMutex;
+#endif
+}
+
+
+bool KviDccVoiceThread::checkSoundcard()
+{
+#ifdef COMPILE_DISABLE_DCC_VOICE
+ return false;
+#else
+ bool bOpened = false;
+ if(m_soundFd == -1)
+ {
+ if(!openSoundcard(O_RDONLY))return false;
+ bOpened = true;
+ }
+
+ int caps;
+
+ m_bSoundcardChecked = true;
+
+ if(ioctl(m_soundFd,SNDCTL_DSP_GETCAPS,&caps) < 0)
+ {
+ postMessageEvent(__tr2qs_ctx("WARNING: failed to check the soundcard duplex capabilities: if this is a half-duplex soundcard , use the DCC VOICE option to force half-duplex algorithm","dcc"));
+ if(bOpened)closeSoundcard();
+ return false;
+ }
+
+ if(!(caps & DSP_CAP_DUPLEX))
+ {
+ m_pOpt->bForceHalfDuplex = true; // the device is half duplex...use it in that way
+ postMessageEvent(__tr2qs_ctx("Half duplex soundcard detected, you will not be able to talk and listen at the same time","dcc"));
+ }
+
+ if(bOpened)closeSoundcard();
+
+ return true;
+#endif
+}
+
+
+bool KviDccVoiceThread::openSoundcard(int mode)
+{
+#ifdef COMPILE_DISABLE_DCC_VOICE
+ return false;
+#else
+ int speed = m_pOpt->iSampleRate;
+ static int chans=KVI_NUM_CHANNELS;
+ static int fmt=KVI_FORMAT;
+ static int frag = KVI_SNDCTL_FRAG_SIZE;
+
+
+ if(m_soundFd != -1)
+ {
+ if(m_soundFdMode == mode)return true; // already open
+ closeSoundcard();
+ }
+
+ m_soundFd = ::open(m_pOpt->szSoundDevice.ptr(),mode | O_NONBLOCK);
+ if(m_soundFd < 0)return false;
+
+ if(!m_pOpt->bForceHalfDuplex)
+ {
+ if(ioctl(m_soundFd,SNDCTL_DSP_SETDUPLEX,0) < 0)goto exit_false;
+ }
+
+ if(ioctl(m_soundFd,SNDCTL_DSP_SETFRAGMENT,&frag)<0)goto exit_false;
+ if(ioctl(m_soundFd,SNDCTL_DSP_SETFMT,&fmt)<0)goto exit_false;
+ if(ioctl(m_soundFd,SNDCTL_DSP_CHANNELS,&chans)<0)goto exit_false;
+ if(ioctl(m_soundFd,SNDCTL_DSP_SPEED,&speed)<0)goto exit_false;
+ if(speed != m_pOpt->iSampleRate)
+ {
+ KviStr tmp(KviStr::Format,__tr2qs_ctx("WARNING: failed to set the requested sample rate (%d): the device used closest match (%d)","dcc"),
+ m_pOpt->iSampleRate,speed);
+ postMessageEvent(tmp.ptr());
+ }
+
+ // TODO: #warning "We could also support blocking operations mode"
+
+ m_soundFdMode = mode;
+
+
+ return true;
+
+exit_false:
+ closeSoundcard();
+ return false;
+#endif
+}
+
+bool KviDccVoiceThread::openSoundcardForWriting()
+{
+#ifndef COMPILE_DISABLE_DCC_VOICE
+ return openSoundcardWithDuplexOption(O_WRONLY,O_RDONLY);
+#else
+ return false;
+#endif
+}
+
+bool KviDccVoiceThread::openSoundcardForReading()
+{
+#ifndef COMPILE_DISABLE_DCC_VOICE
+ return openSoundcardWithDuplexOption(O_RDONLY,O_WRONLY);
+#else
+ return false;
+#endif
+}
+
+bool KviDccVoiceThread::openSoundcardWithDuplexOption(int openMode,int failMode)
+{
+#ifndef COMPILE_DISABLE_DCC_VOICE
+ if(m_soundFd == -1)
+ {
+ // soundcard not open yet...open for write (at least)
+ if(m_pOpt->bForceHalfDuplex)
+ {
+ // Forcing half duplex... (user option or the card does not support full duplex mode)
+ if(!openSoundcard(openMode))return false;
+ } else {
+ // Try read/write open
+ if(!openSoundcard(O_RDWR))
+ {
+ // half-duplex sound card ?
+ if(!m_bSoundcardChecked)
+ {
+ // We haven't checked the full-duplex support yet...
+ // Try to open in RDONLY o WRONLY mode
+ if(!openSoundcard(openMode))return false;
+ if(!checkSoundcard())
+ {
+ postMessageEvent(__tr2qs_ctx("Ops...failed to test the soundcard capabilities...expect problems...","dcc"));
+ }
+ } // else the test has been done and it is a full duplex card that is just busy
+ }
+ }
+ } else {
+ // Hmmm...already open
+ // If it is open in O_RDWR or O_WRONLY mode...it is ok for us
+ // but if it is open in O_RDONLY mode...we can do nothing...just wait
+ return (m_soundFdMode != failMode);
+ }
+
+
+
+ return true;
+#else
+ return false;
+#endif
+}
+
+void KviDccVoiceThread::closeSoundcard()
+{
+#ifndef COMPILE_DISABLE_DCC_VOICE
+ if(m_soundFd != -1)
+ {
+ ::close(m_soundFd);
+ m_soundFd = -1;
+ m_soundFdMode = 0;
+ }
+#endif
+}
+
+
+
+bool KviDccVoiceThread::readWriteStep()
+{
+#ifndef COMPILE_DISABLE_DCC_VOICE
+ // Socket management
+ bool bCanRead;
+ bool bCanWrite;
+
+ if(kvi_select(m_fd,&bCanRead,&bCanWrite))
+ {
+ if(bCanRead)
+ {
+ unsigned int actualSize = m_inFrameBuffer.size();
+ m_inFrameBuffer.resize(actualSize + 1024);
+ int readLen = kvi_socket_recv(m_fd,(void *)(m_inFrameBuffer.data() + actualSize),1024);
+ if(readLen > 0)
+ {
+ if(readLen < 1024)m_inFrameBuffer.resize(actualSize + readLen);
+ m_pOpt->pCodec->decode(&m_inFrameBuffer,&m_inSignalBuffer);
+//#warning "A maximum length for the signal buffer is actually needed!!!"
+ } else {
+ if(!handleInvalidSocketRead(readLen))return false;
+ m_inFrameBuffer.resize(actualSize);
+ }
+ }// else {
+ // m_uSleepTime += 100;
+ //}
+
+ if(bCanWrite)
+ {
+ // Have somethihg to write ?
+ if(m_outFrameBuffer.size() > 0)
+ {
+ int written = kvi_socket_send(m_fd,m_outFrameBuffer.data(),m_outFrameBuffer.size());
+ if(written > 0)
+ {
+ m_outFrameBuffer.remove(written);
+ } else {
+ if(!handleInvalidSocketRead(written))return false;
+ }
+ }// else {
+ // m_uSleepTime += 100;
+ // }
+ }// else {
+ // m_uSleepTime += 100;
+// }
+//#warning "Usleep here ?"
+ }// else {
+// if(!(m_bPlaying || m_bRecording))
+// {
+// // Really NOTHING is happening...sleep a bit more
+// m_uSleepTime += 800;
+// } else {
+// m_uSleepTime += 100;
+// }
+// }
+
+#endif // !COMPILE_DISABLE_DCC_VOICE
+ return true;
+}
+
+bool KviDccVoiceThread::soundStep()
+{
+#ifndef COMPILE_DISABLE_DCC_VOICE
+ // Are we playing ?
+ if(m_bPlaying)
+ {
+ // Do we have something to write ?
+ audio_buf_info info;
+ if(m_inSignalBuffer.size() > 0)
+ {
+ // Get the number of fragments that can be written to the soundcard without blocking
+
+ if(ioctl(m_soundFd,SNDCTL_DSP_GETOSPACE,&info) < 0)
+ {
+ debug("get o space failed");
+ info.bytes = KVI_FRAGMENT_SIZE_IN_BYTES; // dummy... if this is not correct...well...we will block for 1024/16000 of a sec
+ info.fragments = 1;
+ info.fragsize = KVI_FRAGMENT_SIZE_IN_BYTES;
+ }
+ if(info.fragments > 0)
+ {
+ int toWrite = info.fragments * info.fragsize;
+ //debug("Can write %d bytes",toWrite);
+ if(m_inSignalBuffer.size() < toWrite)toWrite = m_inSignalBuffer.size();
+ int written = write(m_soundFd,m_inSignalBuffer.data(),toWrite);
+ if(written > 0)m_inSignalBuffer.remove(written);
+ else {
+//#warning "Do something for -1 here ?"
+//#warning "Usleep ?"
+ }
+ } //else {
+ // No stuff can be written...we are running too fast ?
+ // m_uSleepTime += 100; // sleep for a while
+ //}
+ } else {
+ // hmmmm....playing , but nothing to write , possible underrun or EOF
+ // a nice idea would be to use SNDCTL_DSP_GETODELAY here...
+ // but it appears to be broken on some audio devices
+ if(ioctl(m_soundFd,SNDCTL_DSP_GETOSPACE,&info) < 0)info.fragstotal = info.fragments; // dummy...but what should we do ?
+ if(info.fragstotal == info.fragments)
+ {
+ // underrun or EOF: close the device
+ stopPlaying();
+ }
+ }
+ } else {
+ // do we have anything to play ?
+ if(m_inSignalBuffer.size() > 0)
+ {
+ if(m_inSignalBuffer.size() >= m_pOpt->iPreBufferSize)
+ {
+ // yep...stuff to play... open the soundcard , if possible
+ startPlaying();
+
+ m_iLastSignalBufferSize = m_inSignalBuffer.size();
+ } else {
+ // have stuff to play , but it's not enough to fill the pre-buffer
+ //
+ struct timeval tv;
+ gettimeofday(&tv,0);
+
+ long int sigBufferTime = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
+
+ if(m_inSignalBuffer.size() == m_iLastSignalBufferSize)
+ {
+ // the same signal buffer size... check the time
+ // m_pOpt->iPreBufferSize / 16 gives us the preBufferTime in msecs
+ // we calc the remaining preBufferTime by subtracting the
+ // size of buffer already filled and we also add 50 milliseconds... smart heuristic
+ int preBufferTime = ((m_pOpt->iPreBufferSize - m_iLastSignalBufferSize) / 16) + 50;
+ // if the buffer size hasn't changed since preBufferTime
+ // it's time to start playing anyway, since there is
+ // either a network stall or it was just a really short data stream
+ if((sigBufferTime - m_iLastSignalBufferTime) > preBufferTime)
+ {
+ startPlaying();
+ if(m_bPlaying)m_iLastSignalBufferSize = 0;
+ }
+ } else {
+ // signal buffer size differs...we have received new packets
+ // and still pre-buffering
+ m_iLastSignalBufferSize = m_inSignalBuffer.size();
+ m_iLastSignalBufferTime = sigBufferTime;
+ }
+ }
+
+ }
+ }
+
+ // Are we recording ?
+ if(m_bRecording)
+ {
+ fd_set rs;
+ FD_ZERO(&rs);
+ FD_SET(m_soundFd,&rs);
+ struct timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = 10;
+ int ret = select(m_soundFd + 1,&rs,0,0,&tv);
+ if(ret > 0)
+ {
+ // This is rather easy...
+ audio_buf_info info;
+ if(ioctl(m_soundFd,SNDCTL_DSP_GETISPACE,&info) < 0)
+ {
+ debug("Ispace failed");
+ info.fragments = 0; // dummy...
+ info.bytes = 0;
+ }
+
+ //debug("INFO: fragments: %d, fragstotal: %d, fragsize: %d, bytes: %d",info.fragments,info.fragstotal,info.fragsize,info.bytes);
+
+ if(info.fragments == 0 && info.bytes == 0)
+ {
+ // force a dummy read: the device needs to be triggered
+ info.fragments = 1;
+ }
+
+ if(info.fragments > 0)
+ {
+ int oldSize = m_outSignalBuffer.size();
+ int available = info.fragments * info.fragsize;
+ m_outSignalBuffer.addSize(available);
+ int readed = read(m_soundFd,m_outSignalBuffer.data() + oldSize,available);
+
+ if(readed < available)
+ {
+ // huh ? ...error ?
+ if(readed >= 0)m_outSignalBuffer.resize(oldSize + readed);
+ else {
+ if((errno == EINTR) || (errno == EAGAIN))
+ {
+ m_outSignalBuffer.resize(oldSize);
+ } else {
+//#warning "Critical error...do something reasonable!"
+ m_outSignalBuffer.resize(oldSize);
+ }
+ }
+ }
+/*
+ debug("Signal buffer:");
+ for(int i=0;i<200;i+=2)
+ {
+ if(i >= m_outSignalBuffer.size())break;
+ printf("%04x ",*(((unsigned short *)(m_outSignalBuffer.data() + i))));
+ if((i % 6) == 0)printf("\n");
+ }
+ debug("END\n");
+*/
+ m_pOpt->pCodec->encode(&m_outSignalBuffer,&m_outFrameBuffer);
+ }
+ }// else {
+ // Nothing to read
+ // m_uSleepTime += 100;
+ // }
+ }
+
+#endif // !COMPILE_DISABLE_DCC_VOICE
+ return true;
+}
+
+void KviDccVoiceThread::startRecording()
+{
+#ifndef COMPILE_DISABLE_DCC_VOICE
+ //debug("Start recording");
+ if(m_bRecording)return; // already started
+ if(openSoundcardForReading())
+ {
+// debug("Posting event");
+ KviThreadDataEvent<int> * e = new KviThreadDataEvent<int>(KVI_DCC_THREAD_EVENT_ACTION);
+ e->setData(new int(KVI_DCC_VOICE_THREAD_ACTION_START_RECORDING));
+ postEvent(parent(),e);
+
+ m_bRecording = true;
+ m_bRecordingRequestPending = false;
+ } else {
+ m_bRecordingRequestPending = true;
+ }
+#endif
+}
+
+void KviDccVoiceThread::stopRecording()
+{
+#ifndef COMPILE_DISABLE_DCC_VOICE
+ //debug("Stop recording");
+ m_bRecordingRequestPending = false;
+ if(!m_bRecording)return; // already stopped
+
+ KviThreadDataEvent<int> * e = new KviThreadDataEvent<int>(KVI_DCC_THREAD_EVENT_ACTION);
+ e->setData(new int(KVI_DCC_VOICE_THREAD_ACTION_STOP_RECORDING));
+ postEvent(parent(),e);
+
+ m_bRecording = false;
+ if(!m_bPlaying)closeSoundcard();
+#endif
+}
+
+void KviDccVoiceThread::startPlaying()
+{
+#ifndef COMPILE_DISABLE_DCC_VOICE
+ //debug("Start playing");
+ if(m_bPlaying)return;
+
+ if(openSoundcardForWriting())
+ {
+ KviThreadDataEvent<int> * e = new KviThreadDataEvent<int>(KVI_DCC_THREAD_EVENT_ACTION);
+ e->setData(new int(KVI_DCC_VOICE_THREAD_ACTION_START_PLAYING));
+ postEvent(parent(),e);
+ m_bPlaying = true;
+ }
+#endif
+}
+
+void KviDccVoiceThread::stopPlaying()
+{
+#ifndef COMPILE_DISABLE_DCC_VOICE
+ //debug("Stop playing");
+ if(!m_bPlaying)return;
+
+ KviThreadDataEvent<int> * e = new KviThreadDataEvent<int>(KVI_DCC_THREAD_EVENT_ACTION);
+ e->setData(new int(KVI_DCC_VOICE_THREAD_ACTION_STOP_PLAYING));
+ postEvent(parent(),e);
+
+ m_bPlaying = false;
+ if(!m_bRecording)closeSoundcard();
+#endif
+}
+
+void KviDccVoiceThread::run()
+{
+#ifndef COMPILE_DISABLE_DCC_VOICE
+ for(;;)
+ {
+// m_uSleepTime = 0;
+
+ // Dequeue events
+ while(KviThreadEvent * e = dequeueEvent())
+ {
+ if(e->id() == KVI_THREAD_EVENT_TERMINATE)
+ {
+ delete e;
+ goto exit_dcc;
+ } else if(e->id() == KVI_DCC_THREAD_EVENT_ACTION)
+ {
+ int * act = ((KviThreadDataEvent<int> *)e)->getData();
+ if(*act)startRecording();
+ else stopRecording();
+ delete act;
+ delete e;
+ } else {
+ // Other events are senseless to us
+ delete e;
+ }
+ }
+
+ if(!readWriteStep())goto exit_dcc;
+ if(!soundStep())goto exit_dcc;
+
+ m_pInfoMutex->lock();
+ m_iInputBufferSize = m_inSignalBuffer.size();
+ m_iOutputBufferSize = (m_outFrameBuffer.size() / m_pOpt->pCodec->encodedFrameSize()) * m_pOpt->pCodec->decodedFrameSize();
+ m_pInfoMutex->unlock();
+
+ // Actually the maximum that we can sleep here is
+ // around 500 usecs... = 0.0005 sec -> 8 bytes at 8 KHz
+
+ // if(m_uSleepTime)usleep(m_uSleepTime);
+
+ // Start recording if the request was not fulfilled yet
+ if(m_bRecordingRequestPending)startRecording();
+ }
+
+
+exit_dcc:
+
+#endif //! COMPILE_DISABLE_DCC_VOICE
+ closeSoundcard();
+ kvi_socket_close(m_fd);
+ m_fd = KVI_INVALID_SOCKET;
+}
+
+
+
+
+KviDccVoice::KviDccVoice(KviFrame *pFrm,KviDccDescriptor * dcc,const char * name)
+: KviDccWindow(KVI_WINDOW_TYPE_DCCVOICE,pFrm,name,dcc)
+{
+ m_pDescriptor = dcc;
+ m_pSlaveThread = 0;
+
+ m_pSplitter = new QSplitter(Qt::Horizontal,this,"splitter");
+ m_pIrcView = new KviIrcView(m_pSplitter,pFrm,this);
+
+ m_pHBox = new KviTalHBox(this);
+
+ KviTalVBox * vbox = new KviTalVBox(m_pHBox);
+
+ m_pInputLabel = new QLabel(__tr2qs_ctx("Input buffer","dcc"),vbox);
+ m_pInputLabel->setFrameStyle(QFrame::Sunken | QFrame::Panel);
+ m_pOutputLabel = new QLabel(__tr2qs_ctx("Output buffer","dcc"),vbox);
+ m_pOutputLabel->setFrameStyle(QFrame::Sunken | QFrame::Panel);
+ vbox->setSpacing(1);
+
+ KviTalVBox * vbox2 = new KviTalVBox(m_pHBox);
+
+ m_pRecordingLabel = new QLabel(vbox2);
+ m_pRecordingLabel->setPixmap(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_RECORD)));
+ m_pRecordingLabel->setEnabled(false);
+ m_pRecordingLabel->setFrameStyle(QFrame::Raised | QFrame::Panel);
+
+ m_pPlayingLabel = new QLabel(vbox2);
+ m_pPlayingLabel->setPixmap(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_PLAY)));
+ m_pPlayingLabel->setEnabled(false);
+ m_pPlayingLabel->setFrameStyle(QFrame::Raised | QFrame::Panel);
+
+ vbox2->setSpacing(1);
+
+//#warning "The volume slider should be enabled only when receiving data"
+ m_pVolumeSlider = new QSlider(-100, 0, 10, 0, Qt::Vertical, m_pHBox, "dcc_voice_volume_slider");
+ m_pVolumeSlider->setValue(getMixerVolume());
+/* Update the tooltip */
+ setMixerVolume(m_pVolumeSlider->value());
+ m_pVolumeSlider->setMaximumWidth(16);
+ m_pVolumeSlider->setMaximumHeight(2*m_pPlayingLabel->height());
+ connect(m_pVolumeSlider, SIGNAL(valueChanged(int)), this, SLOT(setMixerVolume(int)));
+
+ m_pTalkButton = new QToolButton(m_pHBox);
+ m_pTalkButton->setEnabled(false);
+ m_pTalkButton->setToggleButton(true);
+#if QT_VERSION >= 300
+ QIconSet iset;
+ iset.setPixmap(*(g_pIconManager->getBigIcon(KVI_BIGICON_DISCONNECTED)),QIconSet::Large,QIconSet::Normal,QIconSet::Off);
+ iset.setPixmap(*(g_pIconManager->getBigIcon(KVI_BIGICON_CONNECTED)),QIconSet::Large,QIconSet::Normal,QIconSet::On);
+ m_pTalkButton->setIconSet(iset);
+#else
+ m_pTalkButton->setOffIconSet(*(g_pIconManager->getBigIcon(KVI_BIGICON_DISCONNECTED)));
+ m_pTalkButton->setOnIconSet(*(g_pIconManager->getBigIcon(KVI_BIGICON_CONNECTED)));
+#endif
+ m_pTalkButton->setUsesBigPixmap(true);
+
+ connect(m_pTalkButton,SIGNAL(toggled(bool)),this,SLOT(startOrStopTalking(bool)));
+
+ m_pHBox->setStretchFactor(vbox,1);
+ m_pHBox->setMargin(2);
+ m_pHBox->setSpacing(1);
+
+ //setFocusHandler(m_pIrcView,this);
+
+ m_pMarshal = new KviDccMarshal(this);
+ connect(m_pMarshal,SIGNAL(error(int)),this,SLOT(handleMarshalError(int)));
+ connect(m_pMarshal,SIGNAL(connected()),this,SLOT(connected()));
+ connect(m_pMarshal,SIGNAL(inProgress()),this,SLOT(connectionInProgress()));
+
+ m_pUpdateTimer = new QTimer();
+
+ startConnection();
+}
+
+KviDccVoice::~KviDccVoice()
+{
+ g_pDccBroker->unregisterDccWindow(this);
+ if(m_pSlaveThread)
+ {
+ m_pSlaveThread->terminate();
+ delete m_pSlaveThread;
+ m_pSlaveThread = 0;
+ }
+
+ KviThreadManager::killPendingEvents(this);
+
+ delete m_pUpdateTimer;
+// delete m_pDescriptor;
+// delete m_pMarshal;
+}
+
+
+void KviDccVoice::startConnection()
+{
+ if(!(m_pDescriptor->bActive))
+ {
+ // PASSIVE CONNECTION
+ output(KVI_OUT_DCCMSG,__tr2qs_ctx("Attempting a passive DCC VOICE connection","dcc"));
+ int ret = m_pMarshal->dccListen(m_pDescriptor->szListenIp,m_pDescriptor->szListenPort,m_pDescriptor->bDoTimeout);
+ if(ret != KviError_success)handleMarshalError(ret);
+ } else {
+ // ACTIVE CONNECTION
+ output(KVI_OUT_DCCMSG,__tr2qs_ctx("Attempting an active DCC VOICE connection","dcc"));
+ int ret = m_pMarshal->dccConnect(m_pDescriptor->szIp.utf8().data(),m_pDescriptor->szPort.utf8().data(),m_pDescriptor->bDoTimeout);
+ if(ret != KviError_success)handleMarshalError(ret);
+ }
+}
+
+void KviDccVoice::connectionInProgress()
+{
+ if(m_pDescriptor->bActive)
+ {
+ output(KVI_OUT_DCCMSG,__tr2qs_ctx("Contacting host %Q on port %Q","dcc"),&(m_pDescriptor->szIp),&(m_pDescriptor->szPort));
+ } else {
+
+ output(KVI_OUT_DCCMSG,__tr2qs_ctx("Listening on interface %Q port %Q","dcc"),
+ &(m_pMarshal->localIp()),&(m_pMarshal->localPort()));
+
+ if(m_pDescriptor->bSendRequest)
+ {
+ KviStr ip = !m_pDescriptor->szFakeIp.isEmpty() ? m_pDescriptor->szFakeIp : m_pDescriptor->szListenIp;
+ KviStr port = !m_pDescriptor->szFakePort.isEmpty() ? m_pDescriptor->szFakePort : m_pMarshal->localPort();
+//#warning "OPTION FOR SENDING 127.0.0.1 and so on (not an unsigned nuumber)"
+ struct in_addr a;
+ if(kvi_stringIpToBinaryIp(ip.ptr(),&a))ip.setNum(htonl(a.s_addr));
+
+ m_pDescriptor->console()->connection()->sendFmtData("PRIVMSG %s :%cDCC VOICE %s %s %s %d%c",
+ m_pDescriptor->console()->connection()->encodeText(m_pDescriptor->szNick).data(),
+ 0x01,m_pDescriptor->szCodec.ptr(),
+ ip.ptr(),port.ptr(),m_pDescriptor->iSampleRate,0x01);
+ output(KVI_OUT_DCCMSG,__tr2qs_ctx("Sent DCC VOICE (%s) request to %Q, waiting for the remote client to connect...","dcc"),
+ m_pDescriptor->szCodec.ptr(),&(m_pDescriptor->szNick));
+ } else output(KVI_OUT_DCCMSG,__tr2qs_ctx("DCC VOICE request not sent: awaiting manual connections","dcc"));
+ }
+}
+
+const QString & KviDccVoice::target()
+{
+ // This may change on the fly...
+ m_szTarget.sprintf("%s@%s:%s",
+ m_pDescriptor->szNick.utf8().data(),m_pDescriptor->szIp.utf8().data(),m_pDescriptor->szPort.utf8().data());
+ return m_szTarget;
+}
+
+void KviDccVoice::getBaseLogFileName(KviStr &buffer)
+{
+ buffer.sprintf("dccvoice_%s_%s_%s",m_pDescriptor->szNick.utf8().data(),m_pDescriptor->szLocalFileName.utf8().data(),m_pDescriptor->szPort.utf8().data());
+}
+
+void KviDccVoice::fillCaptionBuffers()
+{
+ KviStr tmp(KviStr::Format,"DCC Voice %s@%s:%s %s",
+ m_pDescriptor->szNick.utf8().data(),m_pDescriptor->szIp.utf8().data(),m_pDescriptor->szPort.utf8().data(),
+ m_pDescriptor->szLocalFileName.utf8().data());
+
+ m_szPlainTextCaption = tmp;
+
+ m_szHtmlActiveCaption.sprintf("<nobr><font color=\"%s\"><b>%s</b></font></nobr>",
+ KVI_OPTION_COLOR(KviOption_colorCaptionTextActive).name().ascii(),tmp.ptr());
+ m_szHtmlInactiveCaption.sprintf("<nobr><font color=\"%s\"><b>%s</b></font></nobr>",
+ KVI_OPTION_COLOR(KviOption_colorCaptionTextInactive).name().ascii(),tmp.ptr());
+}
+
+QPixmap * KviDccVoice::myIconPtr()
+{
+ return g_pIconManager->getSmallIcon(KVI_SMALLICON_DCCVOICE);
+}
+
+bool KviDccVoice::event(QEvent *e)
+{
+ if(e->type() == KVI_THREAD_EVENT)
+ {
+ switch(((KviThreadEvent *)e)->id())
+ {
+ case KVI_DCC_THREAD_EVENT_ERROR:
+ {
+ int * err = ((KviThreadDataEvent<int> *)e)->getData();
+ QString ssss = KviError::getDescription(*err);
+ output(KVI_OUT_DCCERROR,__tr2qs_ctx("ERROR: %Q","dcc"),&(ssss));
+ delete err;
+ m_pUpdateTimer->stop();
+ updateInfo();
+ m_pTalkButton->setEnabled(false);
+ m_pRecordingLabel->setEnabled(false);
+ m_pPlayingLabel->setEnabled(false);
+ return true;
+ }
+ break;
+ case KVI_DCC_THREAD_EVENT_MESSAGE:
+ {
+ KviStr * str = ((KviThreadDataEvent<KviStr> *)e)->getData();
+ outputNoFmt(KVI_OUT_DCCMSG,__tr_no_xgettext_ctx(str->ptr(),"dcc"));
+ delete str;
+ return true;
+ }
+ break;
+ case KVI_DCC_THREAD_EVENT_ACTION:
+ {
+ int * act = ((KviThreadDataEvent<int> *)e)->getData();
+ switch(*act)
+ {
+ case KVI_DCC_VOICE_THREAD_ACTION_START_RECORDING:
+ m_pRecordingLabel->setEnabled(true);
+ break;
+ case KVI_DCC_VOICE_THREAD_ACTION_STOP_RECORDING:
+ m_pRecordingLabel->setEnabled(false);
+ break;
+ case KVI_DCC_VOICE_THREAD_ACTION_START_PLAYING:
+ m_pPlayingLabel->setEnabled(true);
+ break;
+ case KVI_DCC_VOICE_THREAD_ACTION_STOP_PLAYING:
+ m_pPlayingLabel->setEnabled(false);
+ break;
+ }
+ delete act;
+ return true;
+ }
+ break;
+ default:
+ debug("Invalid event type %d received",((KviThreadEvent *)e)->id());
+ break;
+ }
+
+ }
+
+ return KviWindow::event(e);
+}
+
+void KviDccVoice::updateInfo()
+{
+ if(m_pSlaveThread)
+ {
+ m_pSlaveThread->m_pInfoMutex->lock();
+ int iOSize = m_pSlaveThread->m_iOutputBufferSize;
+ int iISize = m_pSlaveThread->m_iInputBufferSize;
+ m_pSlaveThread->m_pInfoMutex->unlock();
+ KviStr tmp(KviStr::Format,__tr_ctx("Input buffer: %d bytes","dcc"),iISize);
+ m_pInputLabel->setText(tmp.ptr());
+ tmp.sprintf(__tr_ctx("Output buffer: %d bytes","dcc"),iOSize);
+ m_pOutputLabel->setText(tmp.ptr());
+ }
+}
+
+void KviDccVoice::resizeEvent(QResizeEvent *e)
+{
+ int hght2 = m_pHBox->sizeHint().height();
+ m_pHBox->setGeometry(0,0,width(),hght2);
+ m_pSplitter->setGeometry(0,hght2,width(),height() - hght2);
+}
+
+QSize KviDccVoice::sizeHint() const
+{
+ int w = m_pIrcView->sizeHint().width();
+ int w2 = m_pHBox->sizeHint().width();
+ QSize ret(w > w2 ? w : w2, m_pIrcView->sizeHint().height() + m_pHBox->sizeHint().height());
+ return ret;
+}
+
+void KviDccVoice::handleMarshalError(int err)
+{
+ QString ssss = KviError::getDescription(err);
+ output(KVI_OUT_DCCERROR,__tr2qs_ctx("DCC Failed: %Q","dcc"),&ssss);
+ m_pTalkButton->setEnabled(false);
+ m_pTalkButton->setOn(false);
+ m_pRecordingLabel->setEnabled(false);
+ m_pPlayingLabel->setEnabled(false);
+}
+
+void KviDccVoice::connected()
+{
+ output(KVI_OUT_DCCMSG,__tr2qs_ctx("Connected to %Q:%Q","dcc"),
+ &(m_pMarshal->remoteIp()),&(m_pMarshal->remotePort()));
+ output(KVI_OUT_DCCMSG,__tr2qs_ctx("Local end is %Q:%Q","dcc"),
+ &(m_pMarshal->localIp()),&(m_pMarshal->localPort()));
+ if(!(m_pDescriptor->bActive))
+ {
+ m_pDescriptor->szIp = m_pMarshal->remoteIp();
+ m_pDescriptor->szPort = m_pMarshal->remotePort();
+ m_pDescriptor->szHost = m_pMarshal->remoteIp();
+ }
+ updateCaption();
+
+ connect(m_pUpdateTimer,SIGNAL(timeout()),this,SLOT(updateInfo()));
+ m_pUpdateTimer->start(1000);
+
+ KviDccVoiceThreadOptions * opt = new KviDccVoiceThreadOptions;
+
+
+ opt->pCodec = kvi_dcc_voice_get_codec(m_pDescriptor->szCodec.ptr());
+
+ output(KVI_OUT_DCCMSG,__tr2qs_ctx("Actual codec used is '%s'","dcc"),opt->pCodec->name());
+
+ opt->bForceHalfDuplex = KVI_OPTION_BOOL(KviOption_boolDccVoiceForceHalfDuplex);
+// opt->bForceDummyReadTrigger = false;
+ opt->iPreBufferSize = KVI_OPTION_UINT(KviOption_uintDccVoicePreBufferSize);
+ opt->szSoundDevice = KVI_OPTION_STRING(KviOption_stringDccVoiceSoundDevice).utf8().data();
+ opt->iSampleRate = m_pDescriptor->iSampleRate;
+
+ m_pSlaveThread = new KviDccVoiceThread(this,m_pMarshal->releaseSocket(),opt);
+ connect(m_pUpdateTimer,SIGNAL(timeout()),this,SLOT(updateInfo()));
+ m_pSlaveThread->start();
+
+ m_pTalkButton->setEnabled(true);
+}
+
+void KviDccVoice::stopTalking()
+{
+ KviThreadDataEvent<int> * e = new KviThreadDataEvent<int>(KVI_DCC_THREAD_EVENT_ACTION);
+ e->setData(new int(0));
+ m_pSlaveThread->enqueueEvent(e);
+}
+
+void KviDccVoice::startTalking()
+{
+ KviThreadDataEvent<int> * e = new KviThreadDataEvent<int>(KVI_DCC_THREAD_EVENT_ACTION);
+ e->setData(new int(1));
+ m_pSlaveThread->enqueueEvent(e);
+}
+
+void KviDccVoice::startOrStopTalking(bool bStart)
+{
+ if(bStart)startTalking();
+ else stopTalking();
+}
+
+int KviDccVoice::getMixerVolume(void) const
+{
+#ifndef COMPILE_DISABLE_DCC_VOICE
+ int fd;
+ int ret;
+ int left; //, right;
+ int req;
+
+ if((fd = ::open(KVI_OPTION_STRING(KviOption_stringDccVoiceMixerDevice).utf8().data(), O_RDONLY)) == -1)
+ {
+ return 0;
+ }
+
+ req = KVI_OPTION_BOOL(KviOption_boolDccVoiceVolumeSliderControlsPCM) ? SOUND_MIXER_READ_PCM : SOUND_MIXER_READ_VOLUME;
+
+ if(::ioctl(fd,req,&ret))
+ {
+ ::close(fd);
+ return 0;
+ }
+
+ left = (ret & 0x00ff);
+// right = (ret & 0xff00) >> 8;
+
+ ::close(fd);
+
+ return -left;
+#else
+ return 0;
+#endif
+}
+
+void KviDccVoice::setMixerVolume(int vol)
+{
+#ifndef COMPILE_DISABLE_DCC_VOICE
+ int fd;
+ int val;
+ int req;
+
+ if((fd = ::open(KVI_OPTION_STRING(KviOption_stringDccVoiceMixerDevice).utf8().data(), O_WRONLY)) == -1)
+ return;
+
+ req = KVI_OPTION_BOOL(KviOption_boolDccVoiceVolumeSliderControlsPCM) ? SOUND_MIXER_WRITE_PCM : SOUND_MIXER_WRITE_VOLUME;
+
+ val = (-vol << 8) | -vol;
+ ::ioctl(fd, req, &val);
+ ::close(fd);
+
+ QString s;
+ s.sprintf(__tr_ctx("Volume: %i","dcc"), -vol);
+ QToolTip::add(m_pVolumeSlider, s);
+#endif
+}
+
+
+/* The code below doesn't work. Guess I have to catch some other widget's focusInEvent. Which one ? */
+/* The point is to move the volume slider to correct position if for example user switched to
+ * another KVirc window, fired up xmms, changed the volume, and returned to our dcc voice window */
+void KviDccVoice::focusInEvent(QFocusEvent *e)
+{
+// debug("focusInEvent()");
+ m_pVolumeSlider->setValue(getMixerVolume());
+ setMixerVolume(m_pVolumeSlider->value());
+
+ KviWindow::focusInEvent(e);
+}
+
+#include "m_voice.moc"
diff --git a/src/modules/dcc/voice.h b/src/modules/dcc/voice.h
new file mode 100644
index 00000000..c74c677c
--- /dev/null
+++ b/src/modules/dcc/voice.h
@@ -0,0 +1,440 @@
+#ifndef _VOICE_H_
+#define _VOICE_H_
+//
+// File : voice.h
+// Creation date : Thu Aug 23 04:08:10 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_window.h"
+
+#include "kvi_databuffer.h"
+#include "kvi_sockettype.h"
+
+#include "codec.h"
+#include "descriptor.h"
+#include "thread.h"
+#include "window.h"
+
+#include "kvi_tal_hbox.h"
+#include <qlabel.h>
+#include <qtoolbutton.h>
+#include <qtimer.h>
+
+#ifndef _DCC_VOICE_CPP_
+ extern bool kvi_dcc_voice_is_valid_codec(const char * codecName);
+#endif
+
+#define KVI_DCC_VOICE_THREAD_ACTION_START_RECORDING 0
+#define KVI_DCC_VOICE_THREAD_ACTION_STOP_RECORDING 1
+#define KVI_DCC_VOICE_THREAD_ACTION_START_PLAYING 2
+#define KVI_DCC_VOICE_THREAD_ACTION_STOP_PLAYING 3
+
+typedef struct _KviDccVoiceThreadOptions
+{
+ bool bForceHalfDuplex;
+ int iPreBufferSize;
+ int iSampleRate;
+ KviStr szSoundDevice;
+ KviDccVoiceCodec * pCodec;
+} KviDccVoiceThreadOptions;
+
+class KviDccVoiceThread : public KviDccThread
+{
+ friend class KviDccVoice;
+public:
+ KviDccVoiceThread(KviWindow * wnd,kvi_socket_t fd,KviDccVoiceThreadOptions * opt);
+ ~KviDccVoiceThread();
+protected:
+// bool m_bUseGsm;
+ KviDccVoiceThreadOptions * m_pOpt;
+ int m_soundFd;
+ int m_soundFdMode;
+ KviDataBuffer m_outFrameBuffer;
+ KviDataBuffer m_inFrameBuffer;
+ KviDataBuffer m_inSignalBuffer;
+ KviDataBuffer m_outSignalBuffer;
+ bool m_bPlaying;
+ bool m_bRecording;
+ bool m_bRecordingRequestPending;
+ bool m_bSoundcardChecked;
+ int m_iLastSignalBufferSize;
+ long m_iLastSignalBufferTime;
+// unsigned int m_uSleepTime;
+ KviMutex * m_pInfoMutex;
+ // stuff protected by the mutex:
+ int m_iInputBufferSize;
+ int m_iOutputBufferSize;
+protected:
+ bool checkSoundcard();
+ bool openSoundcardWithDuplexOption(int openMode,int failMode);
+ bool openSoundcard(int mode);
+ bool openSoundcardForWriting();
+ bool openSoundcardForReading();
+ void closeSoundcard();
+ bool readWriteStep();
+ bool soundStep();
+ void startRecording();
+ void stopRecording();
+ void startPlaying();
+ void stopPlaying();
+ virtual void run();
+};
+
+class KviDccMarshal;
+class QSlider;
+
+class KviDccVoice : public KviDccWindow
+{
+ Q_OBJECT
+public:
+ KviDccVoice(KviFrame *pFrm,KviDccDescriptor * dcc,const char * name);
+ ~KviDccVoice();
+protected:
+ KviTalHBox * m_pHBox;
+ QSlider * m_pVolumeSlider;
+ QLabel * m_pInputLabel;
+ QLabel * m_pOutputLabel;
+ QLabel * m_pRecordingLabel;
+ QLabel * m_pPlayingLabel;
+ QToolButton * m_pTalkButton;
+ QTimer * m_pUpdateTimer;
+ QString m_szTarget;
+ KviDccVoiceThread * m_pSlaveThread;
+protected:
+ virtual void focusInEvent(QFocusEvent *);
+ virtual const QString & target();
+ virtual void fillCaptionBuffers();
+ virtual QPixmap * myIconPtr();
+ virtual void resizeEvent(QResizeEvent *e);
+ virtual QSize sizeHint() const;
+ virtual bool event(QEvent *e);
+ virtual void getBaseLogFileName(KviStr &buffer);
+ void startTalking();
+ void stopTalking();
+ void startConnection();
+ int getMixerVolume(void) const;
+protected slots:
+ void handleMarshalError(int err);
+ void connected();
+ void updateInfo();
+ void startOrStopTalking(bool bStart);
+ void setMixerVolume(int);
+ void connectionInProgress();
+// void stopTalking();
+};
+
+#if 0
+
+
+
+/*
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+CODEC DEFINITION
+
+ Sample rate = samples/sec (ex. 8000)
+ Sample size = bits (ex. 16 bits)
+ Sample endianness = le/be
+
+ Sample compressor = name
+
+ <rate>:<bits>:<endianness>:<compressor>
+
+ 8000:16:le:null
+ 8000:16:le:gsm
+ 8000:16:le:adpcm
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+class KviVoiceParty
+{
+public:
+ KviVoiceParty(const QString &szNick,const QString &szIp,unsigned short uPort);
+ ~KviVoiceParty();
+protected:
+ QString m_szIp;
+ unsigned short m_uPort;
+ QString m_szNick;
+ KviPointerList<KviVoiceParty> * m_pChildrenTree;
+public:
+ const QString & ip(){ return m_szIp; };
+ unsigned short port(){ return m_uPort; };
+ const QString & nick(){ return m_szNick; };
+ void addChild(KviVoiceParty * pChild);
+};
+
+
+KviVoiceParty::KviVoiceParty(const QString &szNick,const QString &szIp,unsigned short uPort)
+: m_szIp(szIp), m_uPort(uPort), m_szNick(szNick)
+{
+ m_pChildrenTree = 0;
+}
+
+KviVoiceParty::~KviVoiceParty()
+{
+ if(m_pChildrenTree)delete m_pChildrenTree;
+}
+
+void KviVoiceParty::addChild(KviVoiceParty * pChild)
+{
+ if(!m_pChildrenTree)
+ {
+ m_pChildrenTree = new KviPointerList<KviVoiceParty>;
+ m_pChildrenTree->setAutoDelete(true);
+ }
+ m_pChildrenTree->append(pChild);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+class KviVoiceAudioEncoder
+{
+public:
+ KviVoiceAudioEncoder();
+ ~KviVoiceAudioEncoder();
+public:
+
+};
+
+class KviVoiceAudioDecoder
+{
+public:
+ KviVoiceAudioDecoder();
+ ~KviVoiceAudioDecoder();
+};
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+class KviVoiceLink
+{
+public:
+ KviVoiceLink(KviVoiceParty * pRemoteParty);
+ ~KviVoiceLink();
+protected:
+ QString m_szId;
+ KviVoiceParty * m_pRemoteParty;
+ KviVoiceAudioEncoder * m_pAudioEncoder;
+ KviVoiceAudioDecoder * m_pAudioDecoder;
+public:
+ const QStirng & id(){ return m_szId; };
+ KviVoiceParty * remoteParty(){ return m_pRemoteParty; };
+};
+
+KviVoiceLink::KviVoiceLink(KviVoiceParty * pRemoteParty)
+{
+ KviQString::sprintf("%Q:%u",&(pRemoteParty->nick()),pRemoteParty->port());
+ m_pRemoteParty = pRemoteParty;
+ m_pAudioEncoder = 0;
+ m_pAudioDecoder = 0;
+}
+
+KviVoiceLink::~KviVoiceLink()
+{
+ delete m_pRemoteParty;
+ if(m_pAudioEncoder)delete m_pAudioEncoder;
+ if(m_pAudioDecoder)delete m_pAudioDecoder;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+class KviVoice_r8000s16eL_to_r8000s16eB_Transformer
+{
+
+}
+
+class KviVoice_r8000s16eB_to_r8000s16eL_Transformer
+{
+
+}
+
+class KviVoice_r11025s16eL_to_r11025s16eB_Transformer
+{
+
+}
+
+class KviVoice_r11025s16eB_to_r11025s16eL_Transformer
+{
+
+}
+
+class KviVoice_r11025s16eL_to_r8000s16eL_Transformer
+{
+
+}
+
+class KviVoice_r11025s16eL_to_r8000s16eB_Transformer
+{
+
+}
+
+class KviVoice_r11025s16eB_to_r8000s16eL_Transformer
+{
+
+}
+
+class KviVoice_r8000s16eL_to_r11025s16eL_Transformer
+{
+
+}
+
+class KviVoice_r8000s16eL_to_r11025s16eB_Transformer
+{
+
+}
+
+class KviVoice_r8000s16eB_to_r11025s16eL_Transformer
+{
+
+}
+
+
+
+class KviVoiceConference
+{
+public:
+ KviVoiceConference();
+ ~KviVoiceConference();
+public:
+ KviPointerList<KviVoiceLink> * m_pLinks;
+ KviPointerHashTable<QString,KviVoiceLink> *
+ SOCKET m_hUdpSocket;
+ QString m_szLastError;
+
+ unsigned int m_uLocalAudioSampleRate; // samples/sec
+ unsigned int m_uLocalAudioSampleSize; // bits
+ unsigned int m_uLocalAudioEndianness; // 0 = le, 1 = be
+
+public:
+ void conferenceThread();
+protected:
+ void conferenceThreadMain();
+ bool setupUdpSocket();
+};
+
+KviVoiceConference::KviVoiceConference()
+{
+ m_pLinks = new KviPointerList<KviVoiceLink>;
+ m_pLinks->setAutoDelete(true);
+}
+
+KviVoiceConference::~KviVoiceConference()
+{
+ delete m_pLinks;
+}
+
+bool KviVoiceConference::setupUdpSocket()
+{
+ return true;
+}
+
+void KviVoiceConference::shutdownUdpSocket()
+{
+}
+
+void KviVoiceConference::conferenceThreadMain()
+{
+ for(;;)
+ {
+ readAndDecompressIncomingDataForEveryLink();
+
+ mixIncomingDataToASingleStream();
+ playIncomingDataSingleStream();
+
+ readLocalAudioStream();
+
+ foreach(link)
+ {
+ mixLocalAndOtherIncomingDataStreams()
+ compressAndSendOtherIncomingDataStreams()
+ }
+
+ }
+}
+
+void KviVoiceConference::conferenceThread()
+{
+ if(!setupUdpSocket())return;
+
+ conferenceThreadMain();
+
+ shutdownUdpSocket();
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+*/
+
+// DCC VOICE NG proto
+
+//
+// tcp control connection
+// --> HELLO: DccVoice protocol header
+// <-- HELLO: DccVoice protocol header
+// --> IACCEPT: Codec-description|CodecId,Codec-description|CodecID,Codec... (in order of preference)
+// <-- IACCEPT: Codec-description|CodecID,Codec-description|CodecId,Codec... (in order of preference)
+// --> MYADDRESS
+// <-- MYADDRESS
+// --> YOURIDIS: <local id for the remote end> (CID)
+// <-- YOURIDIS: <local id for the remote end> (CID)
+
+// Audio is sent in blocks broken in chunks broken in udp packets
+// Each block is a set of consecutive audio chunks that theoretically
+// should be played consecutively.
+// Each packet in a chunk has an ordinal
+// Chunks must be relatively short in order
+// to allow a remote end that looses a packet to
+// synchronize after a short period of time
+// The maximum number of packets in a chunk is 65535 (but a chunk should be no more than 24-32 KBytes in size
+// and in general they should be as small as possible, even one packet per chunk, if the codec allows it)
+// Each chunk should be encoded independently of the others
+// We can switch codec at each chunk (but not at each packet)
+// When some packets are lost we loose the entire chunk
+// A block is completly synchronized in time (unless we loose some chunks: in that case
+// we may decide to synchronize with silence or insert a glitch...)
+// Decoding never depends on the future
+
+// Each packet should be decompressable (eventually dependently on the previous in the chunk)
+// but playable independently
+
+// start UDP stream
+
+// UDP Packet format:
+
+// <magic byte>: byte
+// <magic byte>: byte
+// <local id>: word
+// <payload len>: word
+// <payload>
+
+
+// Payload format:
+
+// <codec id>: word
+// <ordinal in a chunk>: word (0 = beginning of a chunk)
+
+// read raw audio data at sample rate X, sample size Y
+// multiplex data always at this sample rate and sample size
+
+
+#endif
+
+#endif //_VOICE_H_
diff --git a/src/modules/dcc/window.cpp b/src/modules/dcc/window.cpp
new file mode 100644
index 00000000..4abd7f99
--- /dev/null
+++ b/src/modules/dcc/window.cpp
@@ -0,0 +1,53 @@
+//
+// File : window.cpp
+// Creation date : Fri Jul 26 02:04:40 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "window.h"
+#include "kvi_tal_hbox.h"
+
+KviDccWindow::KviDccWindow(int type,KviFrame * lpFrm,const char * name,KviDccDescriptor * d)
+: KviWindow(type,lpFrm,name)
+{
+ m_pDescriptor = d;
+ m_pDescriptor->setWindow(this);
+ m_pMarshal = 0;
+ m_pButtonBox = new KviTalHBox(this);
+ createTextEncodingButton(m_pButtonBox);
+}
+
+KviDccWindow::~KviDccWindow()
+{
+ if(m_pMarshal)delete m_pMarshal;
+ if(m_pDescriptor)delete m_pDescriptor;
+}
+
+KviWindow * KviDccWindow::dccMarshalOutputWindow()
+{
+ return this;
+}
+
+const char * KviDccWindow::dccMarshalOutputContextString()
+{
+ static const char * static_context = "DCC";
+ return static_context;
+}
+
+#include "m_window.moc"
diff --git a/src/modules/dcc/window.h b/src/modules/dcc/window.h
new file mode 100644
index 00000000..b4bfa43d
--- /dev/null
+++ b/src/modules/dcc/window.h
@@ -0,0 +1,49 @@
+#ifndef _WINDOW_H_
+#define _WINDOW_H_
+//
+// File : window.h
+// Creation date : Fri Jul 26 02:04:39 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_window.h"
+
+#include "descriptor.h"
+#include "marshal.h"
+
+class KviDccWindow : public KviWindow , public KviDccMarshalOutputContext
+{
+ Q_OBJECT
+public:
+ KviDccWindow(int type,KviFrame * lpFrm,const char * name,KviDccDescriptor * d);
+ ~KviDccWindow();
+protected:
+ KviDccDescriptor * m_pDescriptor;
+ KviDccMarshal * m_pMarshal;
+public:
+ KviDccDescriptor * descriptor(){ return m_pDescriptor; };
+ const KviDccMarshal * marshal(){ return m_pMarshal; };
+
+ virtual KviWindow * dccMarshalOutputWindow();
+ virtual const char * dccMarshalOutputContextString();
+};
+
+
+
+#endif //_WINDOW_H_
diff --git a/src/modules/dialog/Makefile.am b/src/modules/dialog/Makefile.am
new file mode 100644
index 00000000..06018a14
--- /dev/null
+++ b/src/modules/dialog/Makefile.am
@@ -0,0 +1,21 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkvidialog.la
+
+libkvidialog_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkvidialog_la_SOURCES = libkvidialog.cpp
+
+libkvidialog_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+noinst_HEADERS= libkvidialog.h
+
+%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
+
+libkvidialog.cpp: libkvidialog.moc
diff --git a/src/modules/dialog/libkvidialog.cpp b/src/modules/dialog/libkvidialog.cpp
new file mode 100644
index 00000000..dd7cf391
--- /dev/null
+++ b/src/modules/dialog/libkvidialog.cpp
@@ -0,0 +1,920 @@
+//=============================================================================
+//
+// File : libkvidialog.cpp
+// Creation date : Sat Sep 15 2001 01:13:25 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+
+#include "libkvidialog.h"
+
+#include <qmessagebox.h>
+#include <qlayout.h>
+#include "kvi_tal_hbox.h"
+#include <qlineedit.h>
+#ifdef COMPILE_USE_QT4
+ #include <q3multilineedit.h>
+ #define QMultiLineEdit Q3MultiLineEdit
+ #include <qdesktopwidget.h>
+#else
+ #include <qmultilineedit.h>
+#endif
+#include <qevent.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+
+#include "kvi_locale.h"
+#include "kvi_module.h"
+#include "kvi_modulemanager.h"
+#include "kvi_error.h"
+#include "kvi_app.h"
+#include "kvi_iconmanager.h"
+#include "kvi_console.h"
+#include "kvi_iconmanager.h"
+#include "kvi_kvs_script.h"
+#include "kvi_msgbox.h"
+
+static KviPointerList<QWidget> * g_pDialogModuleDialogList;
+
+KviKvsCallbackMessageBox::KviKvsCallbackMessageBox(
+ const QString &szCaption,
+ const QString &szText,
+ const QString &szIcon,
+ const QString &szButton0,
+ const QString &szButton1,
+ const QString &szButton2,
+ const QString &szCode,
+ KviKvsVariantList * pMagicParams,
+ KviWindow * pWindow,bool modal)
+: QMessageBox(
+ szCaption,
+ szText,
+ QMessageBox::NoIcon,
+ szButton0.isEmpty() ? QMessageBox::NoButton : QMessageBox::Ok | QMessageBox::Default,
+ szButton1.isEmpty() ? QMessageBox::NoButton : (szButton2.isEmpty() ? QMessageBox::No | QMessageBox::Escape : QMessageBox::No),
+ szButton2.isEmpty() ? QMessageBox::NoButton : QMessageBox::Cancel | QMessageBox::Escape,
+ 0,0,modal) ,
+ KviKvsCallbackObject("dialog.message",pWindow,szCode,pMagicParams,0)
+{
+ g_pDialogModuleDialogList->append(this);
+#ifndef COMPILE_USE_QT4
+ setIcon(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_KVIRC)));
+#endif
+
+ QPixmap * pix = g_pIconManager->getImage(szIcon);
+
+ if(pix)setIconPixmap(*pix);
+ else {
+ if(KviQString::equalCI(szIcon,"information"))setIcon(QMessageBox::Information);
+ else if(KviQString::equalCI(szIcon,"warning"))setIcon(QMessageBox::Warning);
+ else if(KviQString::equalCI(szIcon,"critical"))setIcon(QMessageBox::Critical);
+ }
+ if(!szButton0.isEmpty())setButtonText(QMessageBox::Ok,szButton0);
+ if(!szButton1.isEmpty())setButtonText(QMessageBox::No,szButton1);
+ if(!szButton2.isEmpty())setButtonText(QMessageBox::Cancel,szButton2);
+}
+
+KviKvsCallbackMessageBox::~KviKvsCallbackMessageBox()
+{
+ g_pDialogModuleDialogList->removeRef(this);
+}
+
+void KviKvsCallbackMessageBox::done(int code)
+{
+ QMessageBox::done(code);
+
+ kvs_int_t iVal = 0;
+
+ switch(code)
+ {
+ case QMessageBox::No: iVal = 1; break;
+ case QMessageBox::Cancel: iVal = 2; break;
+ }
+
+ KviKvsVariantList params;
+ params.append(new KviKvsVariant(iVal));
+
+ execute(&params);
+
+ delete this;
+}
+
+
+/*
+ @doc: dialog.message
+ @type:
+ command
+ @title:
+ dialog.message
+ @short:
+ Shows a message box
+ @syntax:
+ dialog.message [-b] (<caption>,<message_text>,<icon>,<button0>[,<button1>[,<button2>[,<magic1>[,<magic2>[...]]]]])
+ {
+ <callback_command>
+ }
+ @description:
+ Shows a message dialog box with the specified <caption> , <message_text> , <icon> and
+ buttons.[br]
+ <caption> is a text string that will appear in the caption of the dialog box.[br]
+ <message_text> is a text string that will appear in the dialog box and can contain HTML formatting.[br]
+ <icon> is an [doc:image_id]image identifier[/doc] that defines an icon to be placed in the dialog box.
+ <icon> can be a relative or absolute path to an image file , a signed number (in that case it defines
+ an internal KVIrc image) or one of the special strings "critical", "information" and "warning".[br]
+ <button0> is the text of the first button (on the left).[br]
+ <button1> is the text of the second button (if empty or not given at all, only one button will appear in the dialog).[br]
+ <button2> is the text of the third button (if empty or not given, only two buttons will appear in the dialog).[br]
+ The first button is always the default button: it is activated when the user presses the
+ enter key. The thirs, or the second if the third is not present, is the escape button
+ and is activated when the user presses the Esc key.[br]
+ <magic1>,<magic2>... are the magic parameters: evaluated at dialog.message call time and passed
+ to the <callback_command> as positional parameters.[br]
+ If the -b or -modal switch is specified the dialog will have non-blocking modal behaviour:
+ it will appear above its parent widget and block its input until it's closed.[br]
+ Once the dialog has been shown , the user will click one of the buttons. At this point the dialog
+ is hidden and the <callback_command> is executed passing the number of the button clicked
+ as $0 and the magic parameters as positional parameters $1 , $2 , $3....[br]
+ Please note that if the user closes the window with the window manager close button ,
+ the action is interpreted as a button2 click (that is usually sth as "Cancel").[br]
+ @examples:
+ [example]
+ [comment]# Just a warning dialog[/comment]
+ dialog.message("Warning","You're being <b>warned</b>",warning,"Ok"){ echo The user clicked OK; }
+ [comment]# A question[/comment]
+ dialog.message("And now ?","What do you want to do ?",information,"Go home","Watch TV","Scream")
+ {
+ if($0 == 0)echo "The user want's to go home"
+ else if($0 == 1)echo "The user want's to watch TV"
+ else echo "The user wants to scream!"
+ }
+ [/example]
+*/
+
+static bool dialog_kvs_cmd_message(KviKvsModuleCallbackCommandCall * c)
+{
+ QString szCaption,szMessage,szIcon,szButton0,szButton1,szButton2;
+ KviKvsVariantList params;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("caption",KVS_PT_STRING,0,szCaption)
+ KVSM_PARAMETER("message",KVS_PT_STRING,0,szMessage)
+ KVSM_PARAMETER("icon",KVS_PT_STRING,0,szIcon)
+ KVSM_PARAMETER("button0",KVS_PT_STRING,KVS_PF_OPTIONAL,szButton0)
+ KVSM_PARAMETER("button1",KVS_PT_STRING,KVS_PF_OPTIONAL,szButton1)
+ KVSM_PARAMETER("button2",KVS_PT_STRING,KVS_PF_OPTIONAL,szButton2)
+ KVSM_PARAMETER("magic",KVS_PT_VARIANTLIST,KVS_PF_OPTIONAL,params)
+ KVSM_PARAMETERS_END(c)
+ bool modal;
+ if(c->hasSwitch('b',"modal")) modal=true;
+ else modal=false;
+ QString szCmd = c->callback()->code();
+
+ KviKvsCallbackMessageBox * box = new KviKvsCallbackMessageBox(
+ szCaption,szMessage,szIcon,szButton0,szButton1,szButton2,szCmd,&params,c->window(),modal);
+ box->show();
+
+ return true;
+}
+
+
+
+KviKvsCallbackTextInput::KviKvsCallbackTextInput(
+ const QString &szCaption,
+ const QString &szLabel,
+ const QString &szDefaultText,
+ const QString &szIcon,
+ bool bMultiLine,
+ const QString &szButton0,
+ const QString &szButton1,
+ const QString &szButton2,
+ const QString &szCode,
+ KviKvsVariantList * pMagicParams,
+ KviWindow * pWindow,bool modal)
+ : QDialog(), KviKvsCallbackObject("dialog.textinput",pWindow,szCode,pMagicParams,0)
+{
+ g_pDialogModuleDialogList->append(this);
+ setIcon(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_KVIRC)));
+ setModal(modal);
+ setCaption(szCaption);
+
+ QGridLayout * g = new QGridLayout(this,2,3,5,5);
+
+ QPixmap * pix = g_pIconManager->getImage(szIcon);
+
+ if(pix)
+ {
+ QLabel * il = new QLabel(this);
+ il->setPixmap(*pix);
+ il->setAlignment(Qt::AlignCenter);
+ g->addWidget(il,0,0);
+ QLabel * tl = new QLabel(szLabel,this);
+ g->addWidget(tl,0,1);
+ } else {
+ QLabel * tl = new QLabel(szLabel,this);
+ g->addMultiCellWidget(tl,0,0,0,1);
+ }
+
+ g->setColStretch(1,1);
+
+ m_bMultiLine = bMultiLine;
+
+ if(m_bMultiLine)
+ {
+ m_pEdit = new QMultiLineEdit(this);
+ ((QMultiLineEdit *)m_pEdit)->setText(szDefaultText);
+ } else {
+ m_pEdit = new QLineEdit(this);
+ ((QLineEdit *)m_pEdit)->setText(szDefaultText);
+ }
+
+ g->addMultiCellWidget(m_pEdit,1,1,0,1);
+
+ KviTalHBox * box = new KviTalHBox(this);
+ g->addMultiCellWidget(box,2,2,0,1);
+
+ m_iEscapeButton = 0;
+ m_iDefaultButton = 0;
+
+ if(!szButton0.isEmpty())
+ {
+ QString szB = szButton0;
+ bool bDef = false;
+ if(KviQString::equalCIN(szB,"default=",8))
+ {
+ bDef = true;
+ szB.remove(0,8);
+ m_iDefaultButton = 0;
+ } else if(KviQString::equalCIN(szB,"escape=",7))
+ {
+ szB.remove(0,7);
+ m_iEscapeButton = 0;
+ }
+ QPushButton * pb1 = new QPushButton(szB,box);
+ if(bDef)pb1->setDefault(true);
+ connect(pb1,SIGNAL(clicked()),this,SLOT(b0Clicked()));
+ }
+
+ if(!szButton1.isEmpty())
+ {
+ QString szB = szButton1;
+ bool bDef = false;
+ if(KviQString::equalCIN(szB,"default=",8))
+ {
+ bDef = true;
+ szB.remove(0,8);
+ m_iDefaultButton = 1;
+ } else if(KviQString::equalCIN(szB,"escape=",7))
+ {
+ szB.remove(0,7);
+ m_iEscapeButton = 1;
+ }
+ QPushButton * pb2 = new QPushButton(szB,box);
+ if(bDef)pb2->setDefault(true);
+ connect(pb2,SIGNAL(clicked()),this,SLOT(b1Clicked()));
+ }
+
+ if(!szButton2.isEmpty())
+ {
+ QString szB = szButton2;
+ bool bDef = false;
+ if(KviQString::equalCIN(szB,"default=",8))
+ {
+ bDef = true;
+ szB.remove(0,8);
+ m_iDefaultButton = 2;
+ } else if(KviQString::equalCIN(szB,"escape=",7))
+ {
+ szB.remove(0,7);
+ m_iEscapeButton = 2;
+ }
+ QPushButton * pb3 = new QPushButton(szB,box);
+ if(bDef)pb3->setDefault(true);
+ connect(pb3,SIGNAL(clicked()),this,SLOT(b2Clicked()));
+ }
+
+}
+
+KviKvsCallbackTextInput::~KviKvsCallbackTextInput()
+{
+ g_pDialogModuleDialogList->removeRef(this);
+}
+
+void KviKvsCallbackTextInput::b0Clicked()
+{
+ done(0+10);
+}
+
+void KviKvsCallbackTextInput::b1Clicked()
+{
+ done(1+10);
+}
+
+void KviKvsCallbackTextInput::b2Clicked()
+{
+ done(2+10);
+}
+
+void KviKvsCallbackTextInput::closeEvent(QCloseEvent *e)
+{
+ e->ignore();
+ done(m_iEscapeButton+10);
+}
+
+void KviKvsCallbackTextInput::done(int code)
+{
+ if(code >= 10)
+ {
+ code -= 10;
+ } else {
+ switch(code)
+ {
+ case QDialog::Accepted:
+ code = m_iDefaultButton;
+ break;
+ default:
+ code = m_iEscapeButton;
+ break;
+ }
+ }
+
+ QString txt;
+
+ if(m_bMultiLine)
+ {
+ txt = ((QMultiLineEdit *)m_pEdit)->text();
+ } else {
+ txt = ((QLineEdit *)m_pEdit)->text();
+ }
+
+ KviKvsVariantList params;
+ params.append(new KviKvsVariant((kvs_int_t)code));
+ params.append(new KviKvsVariant(txt));
+
+ execute(&params);
+
+ //QDialog::done(code);
+
+ delete this;
+}
+
+void KviKvsCallbackTextInput::showEvent(QShowEvent *e)
+{
+ move((g_pApp->desktop()->width() - width())/2,(g_pApp->desktop()->height() - height()) / 2);
+ QDialog::showEvent(e);
+}
+
+
+
+/*
+ @doc: dialog.textinput
+ @type:
+ command
+ @title:
+ dialog.textinput
+ @short:
+ Shows a dialog that accepts user input as text
+ @syntax:
+ dialog.textinput [-d=<default text>] [-i=<icon>] [-m] [-b] (<caption>,<info_text>,<button0>[,<button1>[,<button2>[,<magic1>[,<magic2>[...]]]]])
+ {
+ <callback_command>
+ }
+ @switches:
+ !sw: -d=<default_text> | --default=<default_text>
+ Set the initial text input value to <default_text>
+ !sw: -i=<icon> | --icon=<icon>
+ Display the specified icon, just of the left of the informational text
+ !sw: -m | --multiline
+ Input multiline text instead of single line
+ @description:
+ Shows a text input dialog box with the specified <caption> , <info_text> , <icon> and
+ buttons.[br]
+ <caption> is a text string that will appear in the caption of the dialog box.[br]
+ <info_text> is a fixed text string that will appear in the dialog box and can contain HTML formatting.[br]
+ <button0> is the text of the first button (on the left).[br]
+ <button1> is the text of the second button (if empty or not given at all, only one button will appear in the dialog).[br]
+ <button2> is the text of the third button (if empty or not given, only two buttons will appear in the dialog).[br]
+ If one of the text strings starts with a "default=" prefix then the button is assumed
+ to be the default button of the dialog and will be also activated when the user presses enter.
+ If the -m switch is used , the dialog will be a multi-line text input, otherwise the user will be able to
+ input only a single line of text.[br]
+ If the -d switch is used , the initial text input value is set to <default text>.[br]
+ If the -i switch is used , the dialog displays also the icon <icon> , just on the left ot the <info_text>[br]
+ If the -b or -modal switch is specified the dialog will have non-blocking modal behaviour:
+ it will appear above its parent widget and block its input until it's closed.[br]
+ In that case <icon> is an [doc:image_id]image identifier[/doc] (can be a relative or absolute
+ path to an image file or a signed number (in that case it defines an internal KVIrc image).[br]
+ <magic1>,<magic2>... are the magic parameters: evaluated at dialog.textinput call time and passed
+ to the <callback_command> as positional parameters.[br]
+ Once the dialog has been shown , the user will click one of the buttons. At this point the dialog
+ is hidden and the <callback_command> is executed passing the text input value in $1, the number of the button clicked
+ as $0, and the magic parameters as positional parameters $2 , $3 , $4....[br]
+ Please note that if the user closes the window with the window manager close button ,
+ the action is interpreted as a button2 click (that is usually sth as "Cancel").[br]
+ @examples:
+ [example]
+ [comment]# We need a single line "reason"[/comment]
+ dialog.textinput -d="Working !" (Away,<center>Please enter the <h1>away message</h1></center>,"Ok","Cancel")
+ {
+ switch($0)
+ {
+ case(0):
+ away $1-
+ break;
+ default:
+ # Cancelled
+ break;
+ }
+ }
+ [/example]
+*/
+
+static bool dialog_kvs_cmd_textinput(KviKvsModuleCallbackCommandCall * c)
+{
+ QString szCaption,szInfoText,szIcon,szDefaultText,szButton0,szButton1,szButton2;
+ KviKvsVariantList params;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("caption",KVS_PT_STRING,0,szCaption)
+ KVSM_PARAMETER("info_text",KVS_PT_STRING,0,szInfoText)
+ KVSM_PARAMETER("button0",KVS_PT_STRING,KVS_PF_OPTIONAL,szButton0)
+ KVSM_PARAMETER("button1",KVS_PT_STRING,KVS_PF_OPTIONAL,szButton1)
+ KVSM_PARAMETER("button2",KVS_PT_STRING,KVS_PF_OPTIONAL,szButton2)
+ KVSM_PARAMETER("magic",KVS_PT_VARIANTLIST,KVS_PF_OPTIONAL,params)
+ KVSM_PARAMETERS_END(c)
+
+ QString szCmd = c->callback()->code();
+
+ c->switches()->getAsStringIfExisting('i',"icon",szIcon);
+ c->switches()->getAsStringIfExisting('d',"default",szDefaultText);
+ bool modal;
+ if(c->hasSwitch('b',"modal")) modal=true;
+ else modal=false;
+ KviKvsCallbackTextInput * box = new KviKvsCallbackTextInput(
+ szCaption,szInfoText,szDefaultText,szIcon,c->switches()->find('m',"multiline"),
+ szButton0,szButton1,szButton2,szCmd,&params,c->window(),modal);
+ box->show();
+
+ return true;
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+// New KVS
+KviKvsCallbackFileDialog::KviKvsCallbackFileDialog(
+ const QString &szCaption,
+ const QString &szInitialSelection,
+ const QString &szFilter,
+ const QString &szCode,
+ KviKvsVariantList * pMagicParams,
+ KviWindow * pWindow,bool modal)
+ : KviFileDialog(szInitialSelection,szFilter,0,0,modal), KviKvsCallbackObject("dialog.file",pWindow,szCode,pMagicParams,0)
+{
+ g_pDialogModuleDialogList->append(this);
+ setCaption(szCaption);
+}
+
+KviKvsCallbackFileDialog::~KviKvsCallbackFileDialog()
+{
+ g_pDialogModuleDialogList->removeRef(this);
+}
+
+void KviKvsCallbackFileDialog::done(int code)
+{
+ KviFileDialog::done(code);
+ KviKvsVariantList params;
+
+ if(code == QDialog::Accepted)
+ {
+#ifdef COMPILE_KDE_SUPPORT
+ if(mode() == KFile::ExistingOnly)
+#else
+ if(mode() == QFileDialog::ExistingFiles)
+#endif
+ {
+ KviKvsArray * a = new KviKvsArray();
+ QStringList sl = selectedFiles();
+ int idx = 0;
+ for(QStringList::Iterator it = sl.begin();it != sl.end();++it)
+ {
+ a->set(idx,new KviKvsVariant(*it));
+ idx++;
+ }
+ params.append(new KviKvsVariant(a));
+ } else {
+ params.append(new KviKvsVariant(selectedFile()));
+ }
+ } else {
+ params.append(new KviKvsVariant(QString("")));
+ }
+
+ hide(); // ensure we're hidden
+
+ // ugly workaround for the Qt filedialog "destructive accept() before this reference" bug
+ // we can't delete ourselves in this moment.... :(((
+ // ...so skip out of this call stack and ask KviApp to destroy us just
+ // when the control returns to the main loop.
+ // If the module is unloaded then , KviApp will notice it and will NOT delete the dialog
+ g_pApp->collectGarbage(this);
+
+ // calling dialog.unload here WILL lead to a sigsegv (this is SURE
+ // with a lot of qt versions that have the ugly file dialog "accept before this reference" bug)
+ // to avoid it, we can execute the callback triggered by a timer...
+ // ... umpf ...
+ execute(&params);
+}
+
+/*
+ @doc: dialog.file
+ @type:
+ command
+ @title:
+ dialog.file
+ @short:
+ Shows a file dialog
+ @syntax:
+ dialog.file [-b] (<mode>,<caption>[,<initial_selection[,<file_filter>[,<magic1>[,<magic2>[...]]]]]])
+ {
+ <callback_command>
+ }
+ @description:
+ Shows an openfile dialog box with the specified <caption> , <initial_selection> , and <file_filter>.[br]
+ <mode> can be "open" , "openm" , "save" or "dir":[br]
+ "open" causes the dialog to return an existing file[br]
+ "openm" is similar to open but allows returning multiple files as a comma separated list[br]
+ "save" causes the dialog to return any file name (no overwrite confirmation is built in the dialog!)[br]
+ "dir" causes the dialog to return an existing directory name[br]
+ <mode> defaults to "open".[br]
+ <caption> is a text string that will appear in the caption of the dialog box.[br]
+ <initial_selection> can be a directory or filename that will be initially selected in the dialog.[br]
+ Only files matching <file_filter> are selectable. If filter is an empty string, all files are selectable.[br]
+ In the filter string multiple filters can be specified separated by either two semicolons next to each
+ other or separated by newlines. To add two filters, one to show all C++ files and one to show all
+ header files, the filter string could look like "C++ Files (*.cpp *.cc *.C *.cxx *.c++);;Header Files (*.h *.hxx *.h++)"
+ <magic1>,<magic2>... are the magic parameters: evaluated at dialog.message call time and passed
+ to the <callback_command> as positional parameters.[br]
+ If the -b or -modal switch is specified the dialog will have non-blocking modal behaviour:
+ it will appear above its parent widget and block its input until it's closed.[br]
+ Once the dialog has been shown , the user will select an EXISTING file and click either
+ Ok or Cancel. At this point the dialog is hidden and the <callback_command> is executed passing the selected file(s) as $0
+ and the magic parameters as positional parameters $1 , $2 , $3....[br]
+ If the user clicks "Cancel" or does not select any file the positional parameter $0 will be empty.[br]
+ @examples:
+ [example]
+ dialog.file(open,Choose an audio file,/home/pragma/TheAudio.au,"Audio files (*.au *.wav *.snd)")
+ {
+ if("$0" != "")run play $0
+ }
+ [/example]
+*/
+
+//#warning "Examples for these dialogs!"
+
+
+static bool dialog_kvs_cmd_file(KviKvsModuleCallbackCommandCall * c)
+{
+ QString szMode,szCaption,szInitialSelection,szFilter;
+ KviKvsVariantList params;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("mode",KVS_PT_STRING,0,szMode)
+ KVSM_PARAMETER("caption",KVS_PT_STRING,0,szCaption)
+ KVSM_PARAMETER("initial_selection",KVS_PT_STRING,KVS_PF_OPTIONAL,szInitialSelection)
+ KVSM_PARAMETER("filter",KVS_PT_STRING,KVS_PF_OPTIONAL,szFilter)
+ KVSM_PARAMETER("magic",KVS_PT_VARIANTLIST,KVS_PF_OPTIONAL,params)
+ KVSM_PARAMETERS_END(c)
+ bool modal;
+ if(c->hasSwitch('b',"modal")) modal=true;
+ else modal=false;
+ QString szCmd = c->callback()->code();
+
+ KviKvsCallbackFileDialog * box = new KviKvsCallbackFileDialog(szCaption,szInitialSelection,szFilter,szCmd,&params,c->window(),modal);
+
+ KviFileDialog::FileMode md = KviFileDialog::ExistingFile;
+
+ if(KviQString::equalCI(szMode,"openm"))md = KviFileDialog::ExistingFiles;
+ else if(KviQString::equalCI(szMode,"save"))md = KviFileDialog::AnyFile;
+ else if(KviQString::equalCI(szMode,"dir"))md = KviFileDialog::DirectoryOnly;
+
+ box->setFileMode(md);
+
+ box->show();
+
+ return true;
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+// New KVS
+KviKvsCallbackImageDialog::KviKvsCallbackImageDialog(
+ const QString &szCaption,
+ const QString &szInitialSelection,
+ int iType,
+ int iMaxSize,
+ const QString &szCode,
+ KviKvsVariantList * pMagicParams,
+ KviWindow * pWindow,bool modal)
+ : KviImageDialog(0,szCaption,iType,0,szInitialSelection,iMaxSize,modal), KviKvsCallbackObject("dialog.image",pWindow,szCode,pMagicParams,0)
+{
+ g_pDialogModuleDialogList->append(this);
+}
+
+KviKvsCallbackImageDialog::~KviKvsCallbackImageDialog()
+{
+ g_pDialogModuleDialogList->removeRef(this);
+}
+
+void KviKvsCallbackImageDialog::done(int code)
+{
+ KviImageDialog::done(code);
+ KviKvsVariantList params;
+
+ if(code == QDialog::Accepted)
+ {
+ params.append(new KviKvsVariant(selectedImage()));
+ } else {
+ params.append(new KviKvsVariant(QString("")));
+ }
+
+ hide(); // ensure we're hidden
+
+ // ugly workaround for the Qt filedialog "destructive accept() before this reference" bug
+ // we can't delete ourselves in this moment.... :(((
+ // ...so skip out of this call stack and ask KviApp to destroy us just
+ // when the control returns to the main loop.
+ // If the module is unloaded then , KviApp will notice it and will NOT delete the dialog
+ g_pApp->collectGarbage(this);
+
+ // calling dialog.unload here WILL lead to a sigsegv (this is SURE
+ // with a lot of qt versions that have the ugly file dialog "accept before this reference" bug)
+ // to avoid it, we can execute the callback triggered by a timer...
+ // ... umpf ...
+ execute(&params);
+}
+
+
+/*
+ @doc: dialog.image
+ @type:
+ command
+ @title:
+ dialog.image
+ @short:
+ Shows a image dialog
+ @syntax:
+ dialog.image [-b] (<type>,<caption>,<initial_directory>,[<maxsize>,[,<magic1>[,<magic2>[...]]]]]])
+ {
+ <callback_command>
+ }
+ @description:
+ Shows a dialog that allows selecting an [doc:image_id]image_id[doc].
+ The <type> parameter must be a combination of the following flags:<br>
+ 's' : allow selecting from the KVIrc builtin small icons<br>
+ 'f' : allow browsing the local directories<br>
+ 'a' : all of the above<br>
+ The default for <type> is 'a'.<br>
+ <caption> is the caption string for the dialog.<br>
+ <initial_directory> makes sense only if 'f' is specified (if <initial_directory> is empty
+ then the last path used by the image dialog will be used).<br>
+ <maxsize> is the maximum size of the images for that the preview will be generated:
+ this is 256000 bytes by default (if unspecified). Don't make it a lot bigger : it can take a lot to make
+ the thumbnails for bigger images (and it can eat a considerable amount of memory).<br>
+ <magic1>,<magic2>... are the magic parameters: evaluated at dialog.image call time and passed
+ to the <callback_command> as positional parameters.[br]
+ If the -b or -modal switch is specified the dialog will have non-blocking modal behaviour:
+ it will appear above its parent widget and block its input until it's closed.[br]
+ Once the dialog has been shown , the user will select an EXISTING file and click either
+ Ok or Cancel. At this point the dialog is hidden and the <callback_command> is executed passing the selected file(s) as $0
+ and the magic parameters as positional parameters $1 , $2 , $3....[br]
+ If the user clicks "Cancel" or does not select any image the positional parameter $0 will be empty.[br]
+ @examples:
+ [example]
+ dialog.image(f,Choose an image file,/home/pragma/,"256000")
+ {
+ if("$0" != "")run kview $0
+ }
+ [/example]
+*/
+
+//#warning "Examples for these dialogs!"
+
+
+static bool dialog_kvs_cmd_image(KviKvsModuleCallbackCommandCall * c)
+{
+ QString szType,szCaption,szInitialSelection;
+ kvs_uint_t iMaxSize;
+ KviKvsVariantList params;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("mode",KVS_PT_STRING,0,szType)
+ KVSM_PARAMETER("caption",KVS_PT_STRING,0,szCaption)
+ KVSM_PARAMETER("initial_directory",KVS_PT_STRING,0,szInitialSelection)
+ KVSM_PARAMETER("maxsize",KVS_PT_UINT,KVS_PF_OPTIONAL,iMaxSize)
+ KVSM_PARAMETER("magic",KVS_PT_VARIANTLIST,KVS_PF_OPTIONAL,params)
+ KVSM_PARAMETERS_END(c)
+ bool modal;
+ if(c->hasSwitch('b',"modal")) modal=true;
+ else modal=false;
+ QString szCmd = c->callback()->code();
+
+ int iType = 0;
+
+ if(szType.contains('s'))iType |= KID_TYPE_BUILTIN_IMAGES_SMALL;
+ if(szType.contains('f'))iType |= KID_TYPE_FULL_PATH;
+ if(szType.isEmpty())iType = KID_TYPE_ALL;
+
+ if(iMaxSize < 1)iMaxSize = 256000;
+
+ KviKvsCallbackImageDialog * box = new KviKvsCallbackImageDialog(szCaption,szInitialSelection,iType,iMaxSize,szCmd,&params,c->window(),modal);
+
+ box->show();
+
+ return true;
+}
+
+/*
+ @doc: dialog.yesno
+ @type:
+ function
+ @title:
+ $dialog.yesno
+ @short:
+ Shows a simple yes/no dialog
+ @syntax:
+ $dialog.yesno(<caption:string>,<szText:string>)
+ @description:
+ Shows a simple yes/no dialog. Returns 1 if user clicks "Yes" and 0 if (s)he clicks "No".
+ Please note that this dialog is BLOCKING: it blocks execution of the script
+ until the user has selected either YES or NO.
+ @examples:
+ @seealso:
+*/
+
+static bool dialog_kvs_fnc_yesno(KviKvsModuleFunctionCall * c)
+{
+ QString szCaption;
+ QString szText;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("caption",KVS_PT_STRING,0,szCaption)
+ KVSM_PARAMETER("text",KVS_PT_STRING,0,szText)
+ KVSM_PARAMETERS_END(c)
+
+ c->enterBlockingSection();
+ bool yes=KviMessageBox::yesNo(szCaption,szText); // this will happily crash on quit ?
+ if(!c->leaveBlockingSection())return true; // just die
+ c->returnValue()->setBoolean(yes);
+ return true;
+}
+
+/*
+
+static int g_iLocalEventLoops = 0;
+
+static bool dialog_module_cmd_unload(KviModule *m,KviCommand *c)
+{
+ // We use local loops in this module: we must FORBID explicit unloading of the
+ // module while local even loops are running
+ ENTER_STACK_FRAME(c,"dialog_module_cmd_unload");
+ c->warning(__tr("The dialog module can't be explicitly unloaded: a modal dialog is currently open"));
+ return c->leaveStackFrame();
+}
+
+static void dialog_module_entering_local_loop(KviModule * m)
+{
+ // Replace unload
+ g_iLocalEventLoops++;
+ if(g_iLocalEventLoops == 1)m->registerCommand("unload",dialog_module_cmd_unload);
+}
+
+static void dialog_module_exiting_local_loop(KviModule * m)
+{
+ g_pModuleManager->registerDefaultCommands(m);
+ g_iLocalEventLoops--;
+}
+
+static bool dialog_module_fnc_textline(KviModule *m,KviCommand *c,KviParameterList * parms,KviStr &buffer)
+{
+ ENTER_STACK_FRAME(c,"dialog_module_fnc_textline");
+
+ KviStr caption = parms->safeFirstParam();
+ KviStr info = parms->safeNextParam();
+ KviStr initial = parms->safeNextParam();
+
+ dialog_module_entering_local_loop(m);
+ QMessageBox::information(0,caption.ptr(),info.ptr(),QMessageBox::Ok);
+ dialog_module_exiting_local_loop(m);
+
+ // It might be that the current window is no longer available!!!
+
+ return c->leaveStackFrame();
+}
+
+*/
+
+/*
+ @doc: noblockingdialogs
+ @type:
+ generic
+ @title:
+ Why there are no blocking dialogs in KVIrc ?
+ @short:
+ Tecnical answer
+ @description:
+ Why there are no blocking dialogs in KVIrc ?[br]
+ The answer is simple: because they're more confusing and tricky than it seems.[br]
+ Blocking the entire program control flow while showing a dialog is
+ rather a bad idea since we have to deal with external entities (servers and other users)
+ that are NOT blocked. This means that the blocking dialogs must block only the
+ script control-flow but let the rest of the application running.
+ Such blocking dialogs actually seem to simplify scripting because
+ the programmer "feels" that the control is always left in the script snippet that he is writing.
+ This is actually confusing: the control IS in the script snippet but while the dialog
+ is open the whole world can change: you can return from the dialog call and discover
+ that the server connection no longer exists and the application is about to quit.[br]
+ This may happen even with non-blocking dialogs ,but in non-blocking mode you have
+ a way to handle this event. Consider the following snippet of code:[br]
+ [example]
+ echo My name is $?
+ [/example]
+ Where $? stands for a blocking input dialog that asks the user for some text.[br]
+ When the input dialog returns the window that the echo was directed to no longer
+ exists and you have no way to stop the echo! (Well...I could add extra code
+ in the executable to handle all these situations but that would be really too expensive).[br]
+ With object scripting this is actually dangerous: you might use a blocking dialog
+ in an object signal handler and when returning discover that this object has been deleted!
+ (The example refers to a simple object , but think about a complex hierarchy of objects
+ where one random gets deleted...).[br]
+ This is why the dialogs in KVIrc are non-blocking :)[br]
+ That's REAL programming.
+*/
+
+
+
+
+
+
+
+static bool dialog_module_init(KviModule * m)
+{
+ g_pDialogModuleDialogList = new KviPointerList<QWidget>;
+ g_pDialogModuleDialogList->setAutoDelete(false);
+
+ KVSM_REGISTER_CALLBACK_COMMAND(m,"message",dialog_kvs_cmd_message);
+ KVSM_REGISTER_CALLBACK_COMMAND(m,"textinput",dialog_kvs_cmd_textinput);
+ KVSM_REGISTER_CALLBACK_COMMAND(m,"file",dialog_kvs_cmd_file);
+ KVSM_REGISTER_CALLBACK_COMMAND(m,"image",dialog_kvs_cmd_image);
+
+ KVSM_REGISTER_FUNCTION(m,"yesno",dialog_kvs_fnc_yesno);
+
+ return true;
+}
+
+static bool dialog_module_cleanup(KviModule *m)
+{
+ // Here we get a tragedy if g_iLocalEventLoops > 0!
+ while(g_pDialogModuleDialogList->first())delete g_pDialogModuleDialogList->first();
+ delete g_pDialogModuleDialogList;
+ g_pDialogModuleDialogList = 0;
+ return true;
+}
+
+static bool dialog_module_can_unload(KviModule *m)
+{
+ return g_pDialogModuleDialogList->isEmpty();
+}
+
+
+KVIRC_MODULE(
+ "KVIrc script dialogs",
+ "1.0.0",
+ "Szymon Stefanek <pragma at kvirc dot net>" ,
+ "Adds the /dialog.* commands functionality\n",
+ dialog_module_init ,
+ dialog_module_can_unload,
+ 0,
+ dialog_module_cleanup
+)
+
+#include "libkvidialog.moc"
diff --git a/src/modules/dialog/libkvidialog.h b/src/modules/dialog/libkvidialog.h
new file mode 100644
index 00000000..43b1510f
--- /dev/null
+++ b/src/modules/dialog/libkvidialog.h
@@ -0,0 +1,133 @@
+#ifndef _KVI_DIALOG_H_
+#define _KVI_DIALOG_H_
+//=============================================================================
+//
+// File : libkvidialog.cpp
+// Creation date : Sat Sep 15 2001 01:13:25 by Szymon Stefanek
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_window.h"
+#include "kvi_string.h"
+#include "kvi_parameterlist.h"
+#include "kvi_filedialog.h"
+#include "kvi_imagedialog.h"
+
+#include "kvi_kvs_callbackobject.h"
+
+#include <qmessagebox.h>
+#include <qdialog.h>
+
+
+
+// New KVS
+class KviKvsCallbackMessageBox : public QMessageBox, public KviKvsCallbackObject
+{
+ Q_OBJECT
+public:
+ KviKvsCallbackMessageBox(
+ const QString &szCaption,
+ const QString &szText,
+ const QString &szIcon,
+ const QString &szButton0,
+ const QString &szButton1,
+ const QString &szButton2,
+ const QString &szCode,
+ KviKvsVariantList * pMagicParams,
+ KviWindow * pWindow, bool modal=false);
+ ~KviKvsCallbackMessageBox();
+protected slots:
+ virtual void done(int code);
+};
+
+
+
+
+// New KVS
+class KviKvsCallbackTextInput : public QDialog, public KviKvsCallbackObject
+{
+ Q_OBJECT
+public:
+ KviKvsCallbackTextInput(
+ const QString &szCaption,
+ const QString &szLabel,
+ const QString &szDefaultText,
+ const QString &szIcon,
+ bool bMultiLine,
+ const QString &szButton0,
+ const QString &szButton1,
+ const QString &szButton2,
+ const QString &szCode,
+ KviKvsVariantList * pMagicParams,
+ KviWindow * pWindow, bool modal=false);
+ ~KviKvsCallbackTextInput();
+protected:
+ bool m_bMultiLine;
+ QWidget * m_pEdit;
+ int m_iEscapeButton;
+ int m_iDefaultButton;
+protected:
+ virtual void closeEvent(QCloseEvent *e);
+ virtual void showEvent(QShowEvent *e);
+protected slots:
+ void b0Clicked();
+ void b1Clicked();
+ void b2Clicked();
+ virtual void done(int code);
+};
+
+
+
+// New KVS
+class KviKvsCallbackFileDialog : public KviFileDialog, public KviKvsCallbackObject
+{
+ Q_OBJECT
+public:
+ KviKvsCallbackFileDialog(
+ const QString &szCaption,
+ const QString &szInitialSelection,
+ const QString &szFilter,
+ const QString &szCode,
+ KviKvsVariantList * pMagicParams,
+ KviWindow * pWindow, bool modal=false);
+ ~KviKvsCallbackFileDialog();
+protected:
+ virtual void done(int code);
+};
+
+
+// New KVS
+class KviKvsCallbackImageDialog : public KviImageDialog, public KviKvsCallbackObject
+{
+ Q_OBJECT
+public:
+ KviKvsCallbackImageDialog(
+ const QString &szCaption,
+ const QString &szInitialSelection,
+ int iType,
+ int iMaxSize,
+ const QString &szCode,
+ KviKvsVariantList * pMagicParams,
+ KviWindow * pWindow,bool modal=false);
+ ~KviKvsCallbackImageDialog();
+protected:
+ virtual void done(int code);
+};
+
+#endif //_KVI_DIALOG_H_
diff --git a/src/modules/dockwidget/Makefile.am b/src/modules/dockwidget/Makefile.am
new file mode 100644
index 00000000..71a2f023
--- /dev/null
+++ b/src/modules/dockwidget/Makefile.am
@@ -0,0 +1,33 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkvidockwidget.la
+
+libkvidockwidget_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkvidockwidget_la_SOURCES = libkvidockwidget_qt3.cpp libkvidockwidget_qt4.cpp
+
+#nodist_libkvidockwidget_la_SOURCES = moc_trayicon.cpp
+
+libkvidockwidget_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+noinst_HEADERS= libkvidockwidget.h libkvidockwidget_qt4.h libkvidockwidget_qt3.h
+
+tmpdir = $(picsdir)
+
+tmp_DATA = kvi_dock.png kvi_dock_part-0.png kvi_dock_part-1.png kvi_dock_part-2.png
+
+EXTRA_DIST = $(tmp_DATA)
+
+%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
+
+moc_%.cpp: %.h
+ $(SS_QT_MOC) $< -o $@
+
+libkvidockwidget_qt3.cpp: libkvidockwidget_qt3.moc
+libkvidockwidget_qt4.cpp: libkvidockwidget_qt4.moc
diff --git a/src/modules/dockwidget/kvi_dock.png b/src/modules/dockwidget/kvi_dock.png
new file mode 100644
index 00000000..3ac1a3ce
--- /dev/null
+++ b/src/modules/dockwidget/kvi_dock.png
Binary files differ
diff --git a/src/modules/dockwidget/kvi_dock_part-0.png b/src/modules/dockwidget/kvi_dock_part-0.png
new file mode 100644
index 00000000..80bdbb0a
--- /dev/null
+++ b/src/modules/dockwidget/kvi_dock_part-0.png
Binary files differ
diff --git a/src/modules/dockwidget/kvi_dock_part-1.png b/src/modules/dockwidget/kvi_dock_part-1.png
new file mode 100644
index 00000000..b0acff09
--- /dev/null
+++ b/src/modules/dockwidget/kvi_dock_part-1.png
Binary files differ
diff --git a/src/modules/dockwidget/kvi_dock_part-2.png b/src/modules/dockwidget/kvi_dock_part-2.png
new file mode 100644
index 00000000..5229a74e
--- /dev/null
+++ b/src/modules/dockwidget/kvi_dock_part-2.png
Binary files differ
diff --git a/src/modules/dockwidget/libkvidockwidget.h b/src/modules/dockwidget/libkvidockwidget.h
new file mode 100644
index 00000000..89b99a47
--- /dev/null
+++ b/src/modules/dockwidget/libkvidockwidget.h
@@ -0,0 +1,34 @@
+#ifndef _KVI_TAL_DOCK_H_
+#define _KVI_TAL_DOCK_H_
+
+//
+// File : libkvidockwidget.h
+// Creation date : Sun Jun 18 2000 12:53:08 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_USE_QT4
+ #include "libkvidockwidget_qt4.h"
+#else
+ #include "libkvidockwidget_qt3.h"
+#endif
+
+#endif // _KVI_TAL_DOCK_H_
diff --git a/src/modules/dockwidget/libkvidockwidget_qt3.cpp b/src/modules/dockwidget/libkvidockwidget_qt3.cpp
new file mode 100644
index 00000000..60003853
--- /dev/null
+++ b/src/modules/dockwidget/libkvidockwidget_qt3.cpp
@@ -0,0 +1,858 @@
+//
+// File : libkvidockwidget.cpp
+// Creation date : Tue Jan 02 20001 14:34:12 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+#ifndef COMPILE_USE_QT4
+
+#include "kvi_app.h"
+#include "kvi_module.h"
+#include "kvi_locale.h"
+#include "kvi_memmove.h"
+#include "kvi_taskbar.h"
+#include "kvi_window.h"
+#include "kvi_dynamictooltip.h"
+#include "kvi_iconmanager.h"
+#include "kvi_internalcmd.h"
+#include "kvi_console.h"
+#include "kvi_ircconnection.h"
+#include "kvi_ircconnectionuserinfo.h"
+#include "kvi_imagelib.h"
+#include "kvi_options.h"
+#include "kvi_ircview.h"
+
+#include "libkvidockwidget.h"
+#include "kvi_doublebuffer.h"
+
+#ifdef COMPILE_KDE_SUPPORT
+ #include <kwin.h>
+ #include <kpopupmenu.h>
+#else
+ #include <qlabel.h>
+#endif
+
+#include "kvi_tal_popupmenu.h"
+
+
+#include <qpixmap.h>
+#include <qpainter.h>
+#include <qtimer.h>
+#include <qevent.h>
+#include <qregexp.h>
+
+#include <stdlib.h>
+#include <time.h>
+
+#ifdef COMPILE_ON_WINDOWS
+ #include <windows.h>
+
+ #include <qbitmap.h>
+ #include <qcursor.h>
+
+ #define ID_DOCKWIDGET_TASKBAR_ICON 0xdeadbeef
+ #define WM_KVIRC_NOTIFY_ICON_MESSAGE (WM_USER + 0xbeef)
+
+ static UINT WM_KVIRC_TASKBAR_CREATED = 0;
+#else
+#ifndef Q_OS_MACX
+ #include <X11/Xlib.h>
+
+ //const int XFocusOut = FocusOut;
+ const int XFocusIn = FocusIn;
+ #undef FocusOut
+ #undef FocusIn
+ #undef KeyPress
+ #undef KeyRelease
+
+ //#warning "Later remove this stuff and use a wrapper for #include <X11/Xlib.h>"
+ #ifdef Bool
+ #undef Bool
+ #endif
+#endif
+#endif
+
+extern KVIRC_API KviPointerHashTable<const char *,KviWindow> * g_pGlobalWindowDict;
+static KviPointerList<KviDockWidget> * g_pDockWidgetList = 0;
+
+static QPixmap * g_pDock1 = 0;
+static QPixmap * g_pDock2 = 0;
+static QPixmap * g_pDock3 = 0;
+
+#ifdef COMPILE_ON_WINDOWS
+ static HICON g_pCurrentIcon = 0;
+ static QPixmap * g_pCurrentPixmap = 0;
+#endif
+
+
+KviDockWidget::KviDockWidget(KviFrame * frm,const char * name)
+: QWidget(0,name)
+{
+ m_iConsoles = 0;
+ m_iChannels = 0;
+ m_iQueries = 0;
+ m_iOther = 0;
+
+ m_pFlashingTimer = new QTimer(this,"flashing_timer");
+ connect( m_pFlashingTimer, SIGNAL(timeout()), this, SLOT(flashingTimerShot()) );
+ m_bFlashed=0;
+ g_pDockWidgetList->append(this);
+ m_pFrm = frm;
+ m_pFrm->setDockExtension(this);
+
+#ifdef COMPILE_ON_WINDOWS
+ // kode54
+ if(!WM_KVIRC_TASKBAR_CREATED)WM_KVIRC_TASKBAR_CREATED = RegisterWindowMessage(TEXT("TaskbarCreated"));
+ createTaskbarIcon();
+#else //!COMPILE_ON_WINDOWS
+ setMinimumSize(22,22);
+ #ifndef COMPILE_USE_QT4
+ setBackgroundMode(X11ParentRelative);
+ #endif
+ #ifdef COMPILE_KDE_SUPPORT
+ KWin::setSystemTrayWindowFor(winId(),frm->winId());
+ #endif
+#endif //!COMPILE_ON_WINDOWS
+
+#ifdef COMPILE_USE_QT4
+ m_pSysTrayIcon = new QSystemTrayIcon(m_pFrm);
+#endif
+
+ m_pTip = new KviDynamicToolTip(this,"dock_tooltip");
+ connect(m_pTip,SIGNAL(tipRequest(KviDynamicToolTip *,const QPoint &)),this,SLOT(tipRequest(KviDynamicToolTip *,const QPoint &)));
+
+ m_pAwayPopup = new KviTalPopupMenu(this);
+
+#ifdef COMPILE_KDE_SUPPORT
+ m_pContextPopup = new KPopupMenu(this);
+ m_pContextPopup->insertTitle(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_KVIRC)),__tr2qs("KVIrc"));
+#else
+ m_pContextPopup = new KviTalPopupMenu(this);
+#ifndef COMPILE_USE_QT4
+ QLabel * l = new QLabel(__tr2qs("KVIrc"),m_pContextPopup);
+ l->setFrameStyle(QFrame::Raised | QFrame::StyledPanel);
+ m_pContextPopup->insertItem(l);
+#endif
+#endif
+ m_pContextPopup->setCaption(__tr2qs("Context"));
+ m_iAwayMenuId = m_pContextPopup->insertItem ( __tr2qs("Away"), m_pAwayPopup);
+ m_pContextPopup->changeItem(m_iAwayMenuId,*(g_pIconManager->getSmallIcon(KVI_SMALLICON_AWAY)),__tr2qs("Away"));
+
+ int id = m_pContextPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_OPTIONS)),__tr2qs("&Configure KVIrc..."),m_pFrm,SLOT(executeInternalCommand(int)));
+ m_pContextPopup->setItemParameter(id,KVI_INTERNALCOMMAND_OPTIONS_DIALOG);
+ id = m_pContextPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_KVIRC)),__tr2qs("&About KVIrc"),m_pFrm,SLOT(executeInternalCommand(int)));
+ m_pContextPopup->setItemParameter(id,KVI_INTERNALCOMMAND_ABOUT_ABOUTKVIRC);
+ m_pContextPopup->insertSeparator();
+ m_iToggleFrame = m_pContextPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_RAW)),QString(""),this,SLOT(toggleParentFrame()));
+ m_pContextPopup->insertSeparator();
+ id = m_pContextPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_DOCKWIDGET)),__tr2qs("Un&dock"),m_pFrm,SLOT(executeInternalCommand(int)));
+ m_pContextPopup->setItemParameter(id,KVI_INTERNALCOMMAND_DOCKWIDGET_HIDE);
+ id = m_pContextPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_QUITAPP)),__tr2qs("&Quit"),g_pApp,SLOT(quit()));
+ m_pContextPopup->setAccel(__tr2qs("Ctrl+Q"),id);
+ connect(m_pContextPopup,SIGNAL(aboutToShow()),this,SLOT(fillContextPopup()));
+}
+
+
+KviDockWidget::~KviDockWidget()
+{
+#ifdef COMPILE_ON_WINDOWS
+ destroyTaskbarIcon();
+#endif
+ m_pFrm->setDockExtension(0);
+ g_pDockWidgetList->removeRef(this);
+}
+
+void KviDockWidget::die()
+{
+ delete this;
+}
+void KviDockWidget::flashingTimerShot()
+{
+ m_bFlashed=!m_bFlashed;
+#ifdef COMPILE_ON_WINDOWS
+ updateTaskbarIcon();
+#else
+ update();
+#endif
+}
+
+#ifdef COMPILE_ON_WINDOWS
+void KviDockWidget::createTaskbarIcon()
+{
+ ICONINFO inf;
+ g_pCurrentPixmap=new QPixmap(*g_pDock1);
+ inf.hbmColor = g_pCurrentPixmap->hbm();
+ if(!g_pCurrentPixmap->mask())g_pCurrentPixmap->setMask(g_pCurrentPixmap->createHeuristicMask());
+ inf.hbmMask = g_pCurrentPixmap->mask()->hbm();
+ g_pCurrentIcon=CreateIconIndirect(&inf);
+
+ NOTIFYICONDATA nid;
+ nid.cbSize = sizeof(nid);
+ nid.hWnd = winId();
+ nid.uID = ID_DOCKWIDGET_TASKBAR_ICON;
+ nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
+ nid.uCallbackMessage = WM_KVIRC_NOTIFY_ICON_MESSAGE;
+ kvi_memmove(nid.szTip,"KVIrc",6);
+ nid.hIcon = g_pCurrentIcon;
+ Shell_NotifyIcon(NIM_ADD,&nid);
+}
+
+void KviDockWidget::destroyTaskbarIcon()
+{
+ NOTIFYICONDATA nid;
+ nid.cbSize = sizeof(nid);
+ nid.hWnd = winId();
+ nid.uID = ID_DOCKWIDGET_TASKBAR_ICON;
+ nid.uFlags = 0;
+ Shell_NotifyIcon(NIM_DELETE,&nid);
+}
+
+void KviDockWidget::updateTaskbarIcon()
+{
+ ICONINFO inf;
+ QPixmap* pix = m_bFlashed ? g_pIconManager->getSmallIcon(KVI_SMALLICON_MESSAGE) : g_pCurrentPixmap;
+ inf.hbmColor = pix->hbm();
+ if(!pix->mask())pix->setMask(pix->createHeuristicMask());
+ inf.hbmMask = pix->mask()->hbm();
+ HICON hIcon=CreateIconIndirect(&inf);
+
+ NOTIFYICONDATA nid;
+ nid.cbSize = sizeof(nid);
+ nid.hWnd = winId();
+ nid.uID = ID_DOCKWIDGET_TASKBAR_ICON;
+ nid.uFlags = NIF_ICON;
+ nid.hIcon = hIcon;
+ Shell_NotifyIcon(NIM_MODIFY,&nid);
+ DestroyIcon(g_pCurrentIcon);
+ g_pCurrentIcon=hIcon;
+}
+
+bool KviDockWidget::winEvent(MSG * m)
+{
+ if(m->message == WM_KVIRC_NOTIFY_ICON_MESSAGE)
+ {
+ if(m->wParam == ID_DOCKWIDGET_TASKBAR_ICON)
+ {
+ switch(m->lParam)
+ {
+ case WM_MOUSEMOVE:
+ tipRequest(m_pTip,QCursor::pos());
+ break;
+ case WM_LBUTTONDOWN:
+ toggleParentFrame();
+ break;
+ case WM_RBUTTONDOWN:
+ m_pContextPopup->popup(QCursor::pos());
+ break;
+ }
+ return true;
+ }
+ } else if(m->message == WM_KVIRC_TASKBAR_CREATED)
+ {
+ // kode54 : when the window shell dies and is restarted
+ // it sends the "TaskbarCreated" message to all the toplevel windows
+ // We recreate the taskbar icon then
+ createTaskbarIcon();
+ refresh();
+ }
+ return false;
+}
+
+#endif
+
+#define NIDLEMSGS 18
+
+static const char * idlemsgs[NIDLEMSGS]=
+{
+ __tr("Nothing is happening...") ,
+ __tr("Just idling...") ,
+ __tr("Dum de dum de dum...") ,
+ __tr("Hey man... do something!") ,
+ __tr("Umpf!") ,
+ __tr("Silence speaking") ,
+ __tr("Are ya here?") ,
+ __tr("The world has stopped?") ,
+ __tr("Everything is all right") ,
+ __tr("idle()") ,
+ __tr("It's so cold here...") ,
+ __tr("Do not disturb... watching TV") ,
+ __tr("Just vegetating") ,
+ __tr("Hey... are ya sure that your network is up?") ,
+ __tr("Seems like the world has stopped spinning") ,
+ __tr("This silence is freaking me out!") ,
+ __tr("Mieeeeeowww!") ,
+ __tr("idle idle idle idle!")
+};
+
+#ifdef COMPILE_KDE_SUPPORT
+ extern Time qt_x_time;
+#endif
+
+void KviDockWidget::enterEvent( QEvent* )
+{
+#ifdef COMPILE_KDE_SUPPORT
+ if(!g_pApp->focusWidget())
+ {
+ XEvent ev;
+ kvi_memset(&ev, 0, sizeof(ev));
+ ev.xfocus.display = qt_xdisplay();
+ ev.xfocus.type = XFocusIn;
+ ev.xfocus.window = winId();
+ ev.xfocus.mode = NotifyNormal;
+ ev.xfocus.detail = NotifyAncestor;
+ Time time = qt_x_time;
+ qt_x_time = 1;
+ g_pApp->x11ProcessEvent( &ev );
+ qt_x_time = time;
+ }
+#endif
+}
+
+void KviDockWidget::tipRequest(KviDynamicToolTip *tip,const QPoint &pnt)
+{
+ QString tmp;
+
+ KviTaskBarBase * t = m_pFrm->taskBar();
+
+ QString line;
+
+ for(KviTaskBarItem * b = t->firstItem();b;b = t->nextItem())
+ {
+
+ if(b->kviWindow()->view())
+ {
+ if(b->kviWindow()->view()->haveUnreadedMessages())
+ {
+ line = b->kviWindow()->lastMessageText();
+ if(!line.isEmpty())
+ {
+ line.replace(QChar('&'),"&amp;");
+ line.replace(QChar('<'),"&lt;");
+ line.replace(QChar('>'),"&gt;");
+ tmp += "<b>";
+ tmp += b->kviWindow()->plainTextCaption();
+ tmp += "</b><br>";
+ tmp += line;
+ tmp += "<br><br>\n";
+ }
+ }
+ }
+ }
+
+
+ srand(time(0));
+
+ // We use the bad way to generate random numbers :)))))
+
+ if(tmp.isEmpty())tmp = __tr2qs_no_xgettext(idlemsgs[(int)(rand() % NIDLEMSGS)]);
+
+#ifdef COMPILE_ON_WINDOWS
+
+#else
+ m_pTip->tip(rect(),tmp);
+#endif
+}
+
+//int KviDockWidget::message(int,void *)
+//{
+// debug("Message");
+// update();
+// return 0;
+//}
+
+void KviDockWidget::mousePressEvent(QMouseEvent *e)
+{
+ if(e->button() & Qt::LeftButton)toggleParentFrame();
+ else if(e->button() & Qt::RightButton)
+ m_pContextPopup->popup(mapToGlobal(e->pos()));
+}
+
+void KviDockWidget::doAway(int id)
+{
+ if(id<0)
+ {
+ KviPointerHashTableIterator<const char *,KviWindow> it(*g_pGlobalWindowDict);
+ while(KviWindow * wnd = it.current())
+ {
+ if(wnd->type()==KVI_WINDOW_TYPE_CONSOLE)
+ {
+ KviConsole* pConsole=(KviConsole*)wnd;
+ if(pConsole->isConnected())
+ if(id==-2)
+ pConsole->connection()->sendFmtData("AWAY");
+ else
+ pConsole->connection()->sendFmtData("AWAY :%s",
+ pConsole->connection()->encodeText(KVI_OPTION_STRING(KviOption_stringAwayMessage)).data()
+ );
+ }
+ ++it;
+ }
+ } else {
+ KviConsole* pConsole=g_pApp->findConsole((unsigned int)id);
+ if(pConsole)
+ if(pConsole->isConnected())
+ if(pConsole->connection()->userInfo()->isAway())
+ pConsole->connection()->sendFmtData("AWAY");
+ else
+ pConsole->connection()->sendFmtData("AWAY :%s",
+ pConsole->connection()->encodeText(KVI_OPTION_STRING(KviOption_stringAwayMessage)).data()
+ );
+ }
+}
+
+void KviDockWidget::fillContextPopup()
+{
+ m_pContextPopup->changeItem(m_iToggleFrame,m_pFrm->isVisible() ? __tr2qs("Hide Window") : __tr2qs("Show Window"));
+ if(g_pApp->topmostConnectedConsole())
+ {
+ m_pContextPopup->setItemVisible(m_iAwayMenuId,true);
+ m_pAwayPopup->clear();
+
+ int iAllAway=m_pAwayPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CONSOLE)),__tr2qs("Away on all"),this,SLOT(doAway(int)));
+ m_pAwayPopup->setItemParameter(iAllAway,-1);
+
+ int iAllUnaway=m_pAwayPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CONSOLE)),__tr2qs("Back on all"),this,SLOT(doAway(int)));
+ m_pAwayPopup->setItemParameter(iAllUnaway,-2);
+
+ int iSeparator=m_pAwayPopup->insertSeparator();
+
+ KviPointerHashTableIterator<const char *,KviWindow> it(*g_pGlobalWindowDict);
+ bool bAllAway=1;
+ bool bAllUnaway=1;
+ int iNetCount=0;
+ while(KviWindow * wnd = it.current())
+ {
+ if(wnd->type()==KVI_WINDOW_TYPE_CONSOLE)
+ {
+ KviConsole* pConsole=(KviConsole*)wnd;
+ if(pConsole->isConnected())
+ {
+ int id;
+ if(pConsole->connection()->userInfo()->isAway())
+ {
+ id=m_pAwayPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CONSOLE)),__tr2qs("Back on %1").arg(pConsole->currentNetworkName()),this,SLOT(doAway(int)));
+ bAllUnaway=0;
+ } else {
+ id=m_pAwayPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CONSOLE)),__tr2qs("Away on %1").arg(pConsole->currentNetworkName()),this,SLOT(doAway(int)));
+ bAllAway=0;
+ }
+ m_pAwayPopup->setItemParameter(id,pConsole->ircContextId());
+ iNetCount++;
+ }
+ }
+ ++it;
+ }
+ if(iNetCount==1)
+ {
+ m_pAwayPopup->setItemVisible(iAllAway,false);
+ m_pAwayPopup->setItemVisible(iAllUnaway,false);
+ m_pAwayPopup->setItemVisible(iSeparator,false);
+ } else {
+ m_pAwayPopup->setItemVisible(iAllAway,!bAllAway);
+ m_pAwayPopup->setItemVisible(iAllUnaway,!bAllUnaway);
+ }
+ } else {
+ m_pContextPopup->setItemVisible(m_iAwayMenuId,false);
+ }
+}
+
+void KviDockWidget::toggleParentFrame()
+{
+ QWidget *top_widget = m_pFrm->topLevelWidget();
+
+ if(m_pFrm->isVisible()) {
+ m_pFrm->hide();
+ } else {
+ top_widget->show();
+ top_widget->raise();
+ top_widget->setActiveWindow();
+ if(g_pActiveWindow) g_pActiveWindow->setFocus();
+ if(m_pFrm->isMinimized())
+ m_pFrm->showNormal();
+ else
+ m_pFrm->show();
+ }
+}
+
+void KviDockWidget::refresh()
+{
+ grabActivityInfo();
+
+#ifdef COMPILE_ON_WINDOWS
+ // how to copy transparency????
+ delete g_pCurrentPixmap;
+ g_pCurrentPixmap=new QPixmap(16,16);
+ bitBlt(g_pCurrentPixmap,0,0,m_iOther ? ((m_iOther == 2) ? g_pDock3 : g_pDock2) : g_pDock1,0,0,8,8,Qt::ClearROP);
+ bitBlt(g_pCurrentPixmap,0,8,m_iConsoles ? ((m_iConsoles == 2) ? g_pDock3 : g_pDock2) : g_pDock1,0,8,8,8,Qt::ClearROP);
+ bitBlt(g_pCurrentPixmap,8,0,m_iQueries ? ((m_iQueries == 2) ? g_pDock3 : g_pDock2) : g_pDock1,8,0,8,8,Qt::ClearROP);
+ bitBlt(g_pCurrentPixmap,8,8,m_iChannels ? ((m_iChannels == 2) ? g_pDock3 : g_pDock2) : g_pDock1,8,8,8,8,Qt::ClearROP);
+#endif
+
+ if( (m_iChannels == 2) || (m_iQueries == 2) )
+ {
+ if(!m_pFlashingTimer->isActive() && KVI_OPTION_BOOL(KviOption_boolEnableTrayIconFlashing) ) m_pFlashingTimer->start(1000);
+ } else {
+ if(m_pFlashingTimer->isActive()) m_pFlashingTimer->stop();
+ m_bFlashed=false;
+ }
+
+#ifdef COMPILE_ON_WINDOWS
+ updateTaskbarIcon();
+#else
+ update();
+#endif
+}
+
+void KviDockWidget::grabActivityInfo()
+{
+ KviTaskBarBase * t = m_pFrm->taskBar();
+
+ if(KVI_OPTION_BOOL(KviOption_boolUseLevelBasedTrayNotification))
+ {
+ if(KVI_OPTION_UINT(KviOption_uintMinTrayLowLevelMessage)>5) KVI_OPTION_UINT(KviOption_uintMinTrayLowLevelMessage)=5;
+ if(KVI_OPTION_UINT(KviOption_uintMinTrayHighLevelMessage)>5) KVI_OPTION_UINT(KviOption_uintMinTrayHighLevelMessage)=5;
+
+ if(KVI_OPTION_UINT(KviOption_uintMinTrayLowLevelMessage)<1) KVI_OPTION_UINT(KviOption_uintMinTrayLowLevelMessage)=1;
+ if(KVI_OPTION_UINT(KviOption_uintMinTrayHighLevelMessage)<1) KVI_OPTION_UINT(KviOption_uintMinTrayHighLevelMessage)=1;
+
+ if(KVI_OPTION_UINT(KviOption_uintMinTrayHighLevelMessage)<KVI_OPTION_UINT(KviOption_uintMinTrayLowLevelMessage))
+ KVI_OPTION_UINT(KviOption_uintMinTrayHighLevelMessage)=KVI_OPTION_UINT(KviOption_uintMinTrayLowLevelMessage);
+ }
+
+ m_iConsoles = 0;
+ m_iChannels = 0;
+ m_iQueries = 0;
+ m_iOther = 0;
+
+ for(KviTaskBarItem * b = t->firstItem();b;b = t->nextItem())
+ {
+ if(KVI_OPTION_BOOL(KviOption_boolUseLevelBasedTrayNotification))
+ {
+ int iLevel = b->highlightLevel();
+ switch(b->kviWindow()->type())
+ {
+ case KVI_WINDOW_TYPE_CONSOLE:
+ if(m_iConsoles < iLevel) m_iConsoles = iLevel;
+ break;
+ case KVI_WINDOW_TYPE_CHANNEL:
+ if(m_iChannels < iLevel) m_iChannels = iLevel;
+ break;
+ case KVI_WINDOW_TYPE_QUERY:
+ if(m_iQueries < iLevel) m_iQueries = iLevel;
+ break;
+ default:
+ if(m_iOther < iLevel) m_iOther = iLevel;
+ break;
+ }
+ } else {
+ int iLevel=0;
+ if(b->kviWindow()->view())
+ {
+ if(b->kviWindow()->view()->haveUnreadedHighlightedMessages())
+ {
+ iLevel=2;
+ } else if(b->kviWindow()->view()->haveUnreadedMessages())
+ {
+ iLevel=1;
+ }
+ if(iLevel>0)
+ switch(b->kviWindow()->type())
+ {
+ case KVI_WINDOW_TYPE_CONSOLE:
+ if(m_iConsoles < iLevel) m_iConsoles = iLevel;
+ break;
+ case KVI_WINDOW_TYPE_CHANNEL:
+ if(m_iChannels < iLevel) m_iChannels = iLevel;
+ break;
+ case KVI_WINDOW_TYPE_QUERY:
+ if(m_iQueries < iLevel) m_iQueries = iLevel;
+ break;
+ default:
+ if(m_iOther < iLevel) m_iOther = iLevel;
+ break;
+ }
+ }
+ }
+ }
+
+ if(KVI_OPTION_BOOL(KviOption_boolUseLevelBasedTrayNotification))
+ {
+ if(m_iConsoles >= KVI_OPTION_UINT(KviOption_uintMinTrayHighLevelMessage)) m_iConsoles=2;
+ else if(m_iConsoles >= KVI_OPTION_UINT(KviOption_uintMinTrayLowLevelMessage)) m_iConsoles=1;
+ else m_iConsoles=0;
+
+ if(m_iChannels >= KVI_OPTION_UINT(KviOption_uintMinTrayHighLevelMessage)) m_iChannels=2;
+ else if(m_iChannels >= KVI_OPTION_UINT(KviOption_uintMinTrayLowLevelMessage)) m_iChannels=1;
+ else m_iChannels=0;
+
+ if(m_iQueries >= KVI_OPTION_UINT(KviOption_uintMinTrayHighLevelMessage)) m_iQueries=2;
+ else if(m_iQueries >= KVI_OPTION_UINT(KviOption_uintMinTrayLowLevelMessage)) m_iQueries=1;
+ else m_iQueries=0;
+
+ if(m_iOther >= KVI_OPTION_UINT(KviOption_uintMinTrayHighLevelMessage)) m_iOther=2;
+ else if(m_iOther >= KVI_OPTION_UINT(KviOption_uintMinTrayLowLevelMessage)) m_iOther=1;
+ else m_iOther=0;
+ }
+}
+
+void KviDockWidget::paintEvent(QPaintEvent * event)
+{
+#ifdef COMPILE_USE_QT4
+ QPainter thisRestrictionOfQt4IsNotNice(this);
+ if(m_bFlashed)
+ {
+ erase();
+ thisRestrictionOfQt4IsNotNice.drawPixmap(4,4,16,16,*(g_pIconManager->getSmallIcon(KVI_SMALLICON_MESSAGE)),0,0,16,16);
+ } else {
+ thisRestrictionOfQt4IsNotNice.drawPixmap(0,0,12,12,m_iOther ? ((m_iOther == 2) ? *g_pDock3 : *g_pDock2) : *g_pDock1,0,0,12,12);
+ thisRestrictionOfQt4IsNotNice.drawPixmap(0,12,12,12,m_iConsoles ? ((m_iConsoles == 2) ? *g_pDock3 : *g_pDock2) : *g_pDock1,0,12,12,12);
+ thisRestrictionOfQt4IsNotNice.drawPixmap(12,0,12,12,m_iQueries ? ((m_iQueries == 2) ? *g_pDock3 : *g_pDock2) : *g_pDock1,12,0,12,12);
+ thisRestrictionOfQt4IsNotNice.drawPixmap(12,12,12,12,m_iChannels ? ((m_iChannels == 2) ? *g_pDock3 : *g_pDock2) : *g_pDock1,12,12,12,12);
+ }
+#else
+ if(m_bFlashed)
+ {
+ erase();
+ bitBlt(this,4,4,g_pIconManager->getSmallIcon(KVI_SMALLICON_MESSAGE),0,0,16,16);
+ } else {
+ bitBlt(this,0,0,m_iOther ? ((m_iOther == 2) ? g_pDock3 : g_pDock2) : g_pDock1,0,0,12,12,Qt::CopyROP,false);
+ bitBlt(this,0,12,m_iConsoles ? ((m_iConsoles == 2) ? g_pDock3 : g_pDock2) : g_pDock1,0,12,12,12,Qt::CopyROP,false);
+ bitBlt(this,12,0,m_iQueries ? ((m_iQueries == 2) ? g_pDock3 : g_pDock2) : g_pDock1,12,0,12,12,Qt::CopyROP,false);
+ bitBlt(this,12,12,m_iChannels ? ((m_iChannels == 2) ? g_pDock3 : g_pDock2) : g_pDock1,12,12,12,12,Qt::CopyROP,false);
+ }
+#endif
+}
+
+
+static KviDockWidget * dockwidget_find(KviFrame *f)
+{
+ if(!g_pDockWidgetList)return 0;
+ for(KviDockWidget * w = g_pDockWidgetList->first();w;w = g_pDockWidgetList->next())
+ {
+ if(w->frame() == f)return w;
+ }
+ return 0;
+}
+
+/*
+ @doc: dockwidget.show
+ @type:
+ command
+ @title:
+ dockwidget.show
+ @short:
+ Shows the dock widget for the current frame window
+ @keyterms:
+ dock widget , system tray
+ @syntax:
+ dockwidget.show
+ @description:
+ Shows the dock widget for the current frame window.[br]
+ The dock widget is a small widget that docks in the KDE panel.[br]
+ It shows a small icon of the earth and eventually displays four squares
+ that cover this icon: the bottom left square appears when there is some new
+ text in any console window, the square becomes red if the text is highlighted.[br]
+ The bottom right square appears when there is some new text in any channel window,
+ and it becomes red when the text is highlighted.[br] The upper right square refers to
+ query windows and the upper left one to any other kind of window (dcc , links...).[br]
+ If you move the mouse over the dock widget a tooltip will show you the last lines
+ of the "new" text in all these windows.[br]
+ This is useful when you keep the main KVIrc window minimized and you're working on something else:
+ if the dock widget shows nothing but the earth icon , nothing is happening in the main KVIrc window.
+ If the dock widget shows one or more white (or red) squares , you can move the mouse over
+ and check what's happened exactly and eventually bring up the main KVIrc window by clicking on the widget.[br]
+ [big]tecnical details[/big]
+ The dock widget is currently working in KDE compilation mode only:
+ it relies on the KWin implementation of the Window Manager interaction protocol.
+ @seealso:
+ [cmd]dockwidget.hide[/cmd]
+*/
+
+static bool dockwidget_kvs_cmd_show(KviKvsModuleCommandCall * c)
+{
+ if(!(dockwidget_find(c->window()->frame())))
+ {
+ KviDockWidget * w = new KviDockWidget(c->window()->frame(),"dock_widget");
+#ifndef COMPILE_ON_WINDOWS
+ w->show();
+#else
+ w->hide();
+#endif
+ }
+ return true;
+}
+
+/*
+ @doc: dockwidget.hide
+ @type:
+ command
+ @title:
+ dockwidget.hide
+ @short:
+ Hides the dock widget for the current frame window
+ @syntax:
+ dockwidget.hide
+ @description:
+ Hides the dock widget for the current frame window
+ @seealso:
+ [cmd]dockwidget.show[/cmd]
+*/
+
+static bool dockwidget_kvs_cmd_hide(KviKvsModuleCommandCall * c)
+{
+ KviDockWidget * w= dockwidget_find(c->window()->frame());
+ if(w)delete w;
+ // show the parent frame.. otherwise there will be no way to get it back
+ if(!c->window()->frame()->isVisible())
+ {
+ c->window()->frame()->show();
+ }
+ return true;
+}
+
+/*
+ @doc: dockwidget.hidewindow
+ @type:
+ command
+ @title:
+ dockwidget.hidewindow
+ @short:
+ Returns the state of the dock widget
+ @syntax:
+ dockwidget.hidewindow
+ @description:
+ Hides the window, assotiated with dockwidget
+ @seealso:
+ [cmd]dockwidget.show[/cmd], [cmd]dockwidget.hide[/cmd]
+*/
+
+static bool dockwidget_kvs_cmd_hidewindow(KviKvsModuleCommandCall * c)
+{
+ KviDockWidget * w= dockwidget_find(c->window()->frame());
+ if(w)
+ {
+#if QT_VERSION > 0x030201
+ w->setPrevWindowState(c->window()->frame()->windowState());
+#endif
+ c->window()->frame()->hide();
+ }
+ return true;
+}
+
+/*
+ @doc: dockwidget.isVisible
+ @type:
+ function
+ @title:
+ $dockwidget.isVisible
+ @short:
+ Returns the state of the dock widget
+ @syntax:
+ $reguser.isVisible()
+ @description:
+ Returns 1 if the dock widget is actually visible , 0 otherwise.
+ @seealso:
+ [cmd]dockwidget.show[/cmd]
+*/
+
+static bool dockwidget_kvs_fnc_isvisible(KviKvsModuleFunctionCall * c)
+{
+ c->returnValue()->setBoolean(dockwidget_find(c->window()->frame()));
+ return true;
+}
+
+
+
+// =======================================
+// init routine
+// =======================================
+static bool dockwidget_module_init(KviModule * m)
+{
+ KviStr buffer;
+#ifdef COMPILE_ON_WINDOWS
+ g_pApp->findImage(buffer,"kvi_dock_win32.png");
+ KviImageLibrary l1(buffer.ptr(),16,16);
+#else
+ g_pApp->findImage(buffer,"kvi_dock.png");
+ KviImageLibrary l1(buffer.ptr(),22,22);
+#endif
+ g_pDock1 = new QPixmap(l1.getImage(0));
+ g_pDock2 = new QPixmap(l1.getImage(1));
+ g_pDock3 = new QPixmap(l1.getImage(2));
+
+#ifdef COMPILE_ON_WINDOWS
+
+#endif
+
+
+ g_pDockWidgetList = new KviPointerList<KviDockWidget>;
+ g_pDockWidgetList->setAutoDelete(false);
+
+
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"hide",dockwidget_kvs_cmd_hide);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"hidewindow",dockwidget_kvs_cmd_hidewindow);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"show",dockwidget_kvs_cmd_show);
+ KVSM_REGISTER_FUNCTION(m,"isVisible",dockwidget_kvs_fnc_isvisible);
+
+ return true;
+}
+
+static bool dockwidget_module_cleanup(KviModule *m)
+{
+ while(g_pDockWidgetList->first())delete g_pDockWidgetList->first();
+ delete g_pDockWidgetList;
+ g_pDockWidgetList = 0;
+
+#ifdef COMPILE_ON_WINDOWS
+ DestroyIcon(g_pCurrentIcon);
+#endif
+
+ delete g_pDock1;
+ g_pDock1 = 0;
+ delete g_pDock2;
+ g_pDock2 = 0;
+ delete g_pDock3;
+ g_pDock3 = 0;
+
+ return true;
+}
+
+static bool dockwidget_module_can_unload(KviModule *)
+{
+ return g_pDockWidgetList->isEmpty();
+}
+
+// =======================================
+// plugin definition structure
+// =======================================
+KVIRC_MODULE(
+ "KVIrc dock widget implementation",
+ "1.0.0",
+ "Szymon Stefanek <pragma at kvirc dot net>" ,
+ "exports the /dockwidget.* interface\n",
+ dockwidget_module_init ,
+ dockwidget_module_can_unload,
+ 0,
+ dockwidget_module_cleanup
+)
+
+#include "libkvidockwidget_qt3.moc"
+
+#endif \ No newline at end of file
diff --git a/src/modules/dockwidget/libkvidockwidget_qt3.h b/src/modules/dockwidget/libkvidockwidget_qt3.h
new file mode 100644
index 00000000..1721c28b
--- /dev/null
+++ b/src/modules/dockwidget/libkvidockwidget_qt3.h
@@ -0,0 +1,95 @@
+#ifndef _KVI_DOCKWIDGET_H_
+#define _KVI_DOCKWIDGET_H_
+//
+// This file is part of the KVirc irc client distribution
+// Creation date : Tue 02 Jan 2001 14:28:25 by Szymon Stefanek
+// Copyright (C) 2000-2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+#include "kvi_frame.h"
+
+#ifdef COMPILE_KDE_SUPPORT
+ class KPopupMenu;
+#else
+ class KviTalPopupMenu;
+#endif
+
+
+
+
+class QPixmap;
+class QTimer;
+
+//class KviFrame;
+class KviDynamicToolTip;
+
+class KviDockWidget : public QWidget , public KviDockExtension
+{
+ Q_OBJECT
+public:
+ KviDockWidget(KviFrame * win,const char * name);
+ ~KviDockWidget();
+protected:
+ KviFrame * m_pFrm;
+ KviDynamicToolTip * m_pTip;
+#ifdef COMPILE_KDE_SUPPORT
+ KPopupMenu * m_pContextPopup;
+#else
+ KviTalPopupMenu * m_pContextPopup;
+#endif
+ KviTalPopupMenu * m_pAwayPopup;
+ int m_iToggleFrame;
+ int m_iAwayMenuId;
+
+ bool m_bFlashed;
+
+ QTimer* m_pFlashingTimer;
+ int m_iConsoles;
+ int m_iChannels;
+ int m_iQueries;
+ int m_iOther;
+public:
+ KviFrame * frame(){ return m_pFrm; };
+public:
+// virtual int message(int msgtype,void * data);
+ virtual void enterEvent(QEvent *);
+ virtual void refresh();
+ virtual void die();
+protected:
+ virtual void paintEvent(QPaintEvent *e);
+ virtual void mousePressEvent(QMouseEvent *e);
+ void grabActivityInfo();
+
+#ifdef COMPILE_ON_WINDOWS
+private:
+ void createTaskbarIcon();
+ void destroyTaskbarIcon();
+ void updateTaskbarIcon();
+protected:
+ bool winEvent(MSG * m);
+#endif
+
+protected slots:
+ void fillContextPopup();
+ void toggleParentFrame();
+ void tipRequest(KviDynamicToolTip *tip,const QPoint &pnt);
+ void doAway(int);
+ void flashingTimerShot();
+};
+
+#endif //_KVI_DOCKWIDGET_H_
diff --git a/src/modules/dockwidget/libkvidockwidget_qt4.cpp b/src/modules/dockwidget/libkvidockwidget_qt4.cpp
new file mode 100644
index 00000000..73a21998
--- /dev/null
+++ b/src/modules/dockwidget/libkvidockwidget_qt4.cpp
@@ -0,0 +1,691 @@
+//
+// File : libkvidockwidget.cpp
+// Creation date : Tue Jan 02 20001 14:34:12 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_USE_QT4
+
+#ifdef COMPILE_ON_WINDOWS
+ #define ICON_SIZE 16
+#else
+ #define ICON_SIZE 22
+#endif
+
+#include "kvi_app.h"
+#include "kvi_module.h"
+#include "kvi_locale.h"
+#include "kvi_memmove.h"
+#include "kvi_taskbar.h"
+#include "kvi_window.h"
+#include "kvi_dynamictooltip.h"
+#include "kvi_iconmanager.h"
+#include "kvi_internalcmd.h"
+#include "kvi_console.h"
+#include "kvi_ircconnection.h"
+#include "kvi_ircconnectionuserinfo.h"
+#include "kvi_imagelib.h"
+#include "kvi_options.h"
+#include "kvi_ircview.h"
+
+#include "libkvidockwidget.h"
+#include "kvi_doublebuffer.h"
+
+#include <qlabel.h>
+
+#include "kvi_tal_popupmenu.h"
+
+
+#include <qpixmap.h>
+#include <qpainter.h>
+#include <qtimer.h>
+#include <qevent.h>
+#include <qregexp.h>
+
+#include <stdlib.h>
+#include <time.h>
+
+
+extern KVIRC_API KviPointerHashTable<const char *,KviWindow> * g_pGlobalWindowDict;
+static KviPointerList<KviDockWidget> * g_pDockWidgetList = 0;
+
+static QPixmap * g_pDock1 = 0;
+static QPixmap * g_pDock2 = 0;
+static QPixmap * g_pDock3 = 0;
+
+KviDockWidget::KviDockWidget(KviFrame * frm)
+: QSystemTrayIcon(frm), m_CurrentPixmap(ICON_SIZE,ICON_SIZE)
+{
+ m_pContextPopup = new KviTalPopupMenu(0);
+ setContextMenu(m_pContextPopup);
+
+ m_iConsoles = 0;
+ m_iChannels = 0;
+ m_iQueries = 0;
+ m_iOther = 0;
+
+ m_pFlashingTimer = new QTimer(this,"flashing_timer");
+ connect( m_pFlashingTimer, SIGNAL(timeout()), this, SLOT(flashingTimerShot()) );
+ m_bFlashed=0;
+ g_pDockWidgetList->append(this);
+ m_pFrm = frm;
+ m_pFrm->setDockExtension(this);
+
+ m_pTip = new KviDynamicToolTip(frm,"dock_tooltip");
+ m_pAwayPopup = new KviTalPopupMenu(0);
+
+ QLabel * l = new QLabel(__tr2qs("KVIrc"),m_pContextPopup);
+ l->setFrameStyle(QFrame::Raised | QFrame::StyledPanel);
+ m_pContextPopup->insertItem(l);
+ m_pContextPopup->setCaption(__tr2qs("Context"));
+ m_iAwayMenuId = m_pContextPopup->insertItem ( __tr2qs("Away"), m_pAwayPopup);
+ m_pContextPopup->changeItem(m_iAwayMenuId,*(g_pIconManager->getSmallIcon(KVI_SMALLICON_AWAY)),__tr2qs("Away"));
+
+ int id = m_pContextPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_OPTIONS)),__tr2qs("&Configure KVIrc..."),m_pFrm,SLOT(executeInternalCommand(int)));
+ m_pContextPopup->setItemParameter(id,KVI_INTERNALCOMMAND_OPTIONS_DIALOG);
+ id = m_pContextPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_KVIRC)),__tr2qs("&About KVIrc"),m_pFrm,SLOT(executeInternalCommand(int)));
+ m_pContextPopup->setItemParameter(id,KVI_INTERNALCOMMAND_ABOUT_ABOUTKVIRC);
+ m_pContextPopup->insertSeparator();
+ m_iToggleFrame = m_pContextPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_RAW)),QString(""),this,SLOT(toggleParentFrame()));
+ m_pContextPopup->insertSeparator();
+ id = m_pContextPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_DOCKWIDGET)),__tr2qs("Un&dock"),m_pFrm,SLOT(executeInternalCommand(int)));
+ m_pContextPopup->setItemParameter(id,KVI_INTERNALCOMMAND_DOCKWIDGET_HIDE);
+ id = m_pContextPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_QUITAPP)),__tr2qs("&Quit"),g_pApp,SLOT(quit()));
+ m_pContextPopup->setAccel(__tr2qs("Ctrl+Q"),id);
+ connect(m_pContextPopup,SIGNAL(aboutToShow()),this,SLOT(fillContextPopup()));
+
+ QIcon icon(*g_pDock1);
+ setIcon(icon);
+
+ connect(this,SIGNAL(activated ( QSystemTrayIcon::ActivationReason )),this,SLOT(activatedSlot ( QSystemTrayIcon::ActivationReason )));
+}
+
+
+KviDockWidget::~KviDockWidget()
+{
+ m_pFrm->setDockExtension(0);
+ g_pDockWidgetList->removeRef(this);
+}
+
+void KviDockWidget::die()
+{
+ delete this;
+}
+
+void KviDockWidget::flashingTimerShot()
+{
+ m_bFlashed=!m_bFlashed;
+ refresh();
+}
+
+#define NIDLEMSGS 18
+
+static const char * idlemsgs[NIDLEMSGS]=
+{
+ __tr("Nothing is happening...") ,
+ __tr("Just idling...") ,
+ __tr("Dum de dum de dum...") ,
+ __tr("Hey man... do something!") ,
+ __tr("Umpf!") ,
+ __tr("Silence speaking") ,
+ __tr("Are ya here?") ,
+ __tr("The world has stopped?") ,
+ __tr("Everything is all right") ,
+ __tr("idle()") ,
+ __tr("It's so cold here...") ,
+ __tr("Do not disturb... watching TV") ,
+ __tr("Just vegetating") ,
+ __tr("Hey... are ya sure that your network is up?") ,
+ __tr("Seems like the world has stopped spinning") ,
+ __tr("This silence is freaking me out!") ,
+ __tr("Mieeeeeowww!") ,
+ __tr("idle idle idle idle!")
+};
+
+void KviDockWidget::tipRequest(KviDynamicToolTip *tip,const QPoint &pnt)
+{
+ QString tmp;
+
+ KviTaskBarBase * t = m_pFrm->taskBar();
+
+ QString line;
+
+ for(KviTaskBarItem * b = t->firstItem();b;b = t->nextItem())
+ {
+
+ if(b->kviWindow()->view())
+ {
+ if(b->kviWindow()->view()->haveUnreadedMessages())
+ {
+ line = b->kviWindow()->lastMessageText();
+ if(!line.isEmpty())
+ {
+ line.replace(QChar('&'),"&amp;");
+ line.replace(QChar('<'),"&lt;");
+ line.replace(QChar('>'),"&gt;");
+ tmp += "<b>";
+ tmp += b->kviWindow()->plainTextCaption();
+ tmp += "</b><br>";
+ tmp += line;
+ tmp += "<br><br>\n";
+ }
+ }
+ }
+ }
+
+
+ srand(time(0));
+
+ // We use the bad way to generate random numbers :)))))
+
+ if(tmp.isEmpty())tmp = __tr2qs_no_xgettext(idlemsgs[(int)(rand() % NIDLEMSGS)]);
+
+ //m_pTip->tip(rect(),tmp);
+}
+
+//int KviDockWidget::message(int,void *)
+//{
+// debug("Message");
+// update();
+// return 0;
+//}
+
+//FIXME: Qt4 port
+/*void KviDockWidget::mousePressEvent(QMouseEvent *e)
+{
+ if(e->button() & Qt::LeftButton)toggleParentFrame();
+ else if(e->button() & Qt::RightButton)
+ m_pContextPopup->popup(mapToGlobal(e->pos()));
+}*/
+
+void KviDockWidget::doAway(int id)
+{
+ if(id<0)
+ {
+ KviPointerHashTableIterator<const char *,KviWindow> it(*g_pGlobalWindowDict);
+ while(KviWindow * wnd = it.current())
+ {
+ if(wnd->type()==KVI_WINDOW_TYPE_CONSOLE)
+ {
+ KviConsole* pConsole=(KviConsole*)wnd;
+ if(pConsole->isConnected())
+ if(id==-2)
+ pConsole->connection()->sendFmtData("AWAY");
+ else
+ pConsole->connection()->sendFmtData("AWAY :%s",
+ pConsole->connection()->encodeText(KVI_OPTION_STRING(KviOption_stringAwayMessage)).data()
+ );
+ }
+ ++it;
+ }
+ } else {
+ KviConsole* pConsole=g_pApp->findConsole((unsigned int)id);
+ if(pConsole)
+ if(pConsole->isConnected())
+ if(pConsole->connection()->userInfo()->isAway())
+ pConsole->connection()->sendFmtData("AWAY");
+ else
+ pConsole->connection()->sendFmtData("AWAY :%s",
+ pConsole->connection()->encodeText(KVI_OPTION_STRING(KviOption_stringAwayMessage)).data()
+ );
+ }
+}
+
+void KviDockWidget::fillContextPopup()
+{
+ m_pContextPopup->changeItem(m_iToggleFrame,m_pFrm->isVisible() ? __tr2qs("Hide Window") : __tr2qs("Show Window"));
+ if(g_pApp->topmostConnectedConsole())
+ {
+ m_pContextPopup->setItemVisible(m_iAwayMenuId,true);
+ m_pAwayPopup->clear();
+
+ int iAllAway=m_pAwayPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CONSOLE)),__tr2qs("Away on all"),this,SLOT(doAway(int)));
+ m_pAwayPopup->setItemParameter(iAllAway,-1);
+
+ int iAllUnaway=m_pAwayPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CONSOLE)),__tr2qs("Back on all"),this,SLOT(doAway(int)));
+ m_pAwayPopup->setItemParameter(iAllUnaway,-2);
+
+ int iSeparator=m_pAwayPopup->insertSeparator();
+
+ KviPointerHashTableIterator<const char *,KviWindow> it(*g_pGlobalWindowDict);
+ bool bAllAway=1;
+ bool bAllUnaway=1;
+ int iNetCount=0;
+ while(KviWindow * wnd = it.current())
+ {
+ if(wnd->type()==KVI_WINDOW_TYPE_CONSOLE)
+ {
+ KviConsole* pConsole=(KviConsole*)wnd;
+ if(pConsole->isConnected())
+ {
+ int id;
+ if(pConsole->connection()->userInfo()->isAway())
+ {
+ id=m_pAwayPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CONSOLE)),__tr2qs("Back on %1").arg(pConsole->currentNetworkName()),this,SLOT(doAway(int)));
+ bAllUnaway=0;
+ } else {
+ id=m_pAwayPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CONSOLE)),__tr2qs("Away on %1").arg(pConsole->currentNetworkName()),this,SLOT(doAway(int)));
+ bAllAway=0;
+ }
+ m_pAwayPopup->setItemParameter(id,pConsole->ircContextId());
+ iNetCount++;
+ }
+ }
+ ++it;
+ }
+ if(iNetCount==1)
+ {
+ m_pAwayPopup->setItemVisible(iAllAway,false);
+ m_pAwayPopup->setItemVisible(iAllUnaway,false);
+ m_pAwayPopup->setItemVisible(iSeparator,false);
+ } else {
+ m_pAwayPopup->setItemVisible(iAllAway,!bAllAway);
+ m_pAwayPopup->setItemVisible(iAllUnaway,!bAllUnaway);
+ }
+ } else {
+ m_pContextPopup->setItemVisible(m_iAwayMenuId,false);
+ }
+}
+
+void KviDockWidget::toggleParentFrame()
+{
+ QWidget *top_widget = m_pFrm->topLevelWidget();
+
+ if(m_pFrm->isVisible()) {
+ m_pFrm->hide();
+ } else {
+ top_widget->show();
+ top_widget->raise();
+ top_widget->setActiveWindow();
+ if(g_pActiveWindow) g_pActiveWindow->setFocus();
+ if(m_pFrm->isMinimized())
+ m_pFrm->showNormal();
+ else
+ m_pFrm->show();
+ }
+}
+
+void KviDockWidget::refresh()
+{
+ grabActivityInfo();
+
+ if( (m_iChannels == 2) || (m_iQueries == 2) )
+ {
+ if(!m_pFlashingTimer->isActive() && KVI_OPTION_BOOL(KviOption_boolEnableTrayIconFlashing) )
+ m_pFlashingTimer->start(1000);
+ } else {
+ if(m_pFlashingTimer->isActive()) m_pFlashingTimer->stop();
+ m_bFlashed=false;
+ }
+
+ m_CurrentPixmap.fill(Qt::transparent);
+ QPainter thisRestrictionOfQt4IsNotNice(&m_CurrentPixmap);
+ //thisRestrictionOfQt4IsNotNice.drawPixmap(0,0,22,22,*g_pDock1,0,0,22,22);
+
+ if(m_bFlashed)
+ {
+ thisRestrictionOfQt4IsNotNice.drawPixmap((ICON_SIZE-16)/2,(ICON_SIZE-16)/2,16,16,*(g_pIconManager->getSmallIcon(KVI_SMALLICON_MESSAGE)),0,0,16,16);
+ } else {
+ thisRestrictionOfQt4IsNotNice.drawPixmap(0,0,ICON_SIZE/2,ICON_SIZE/2,
+ m_iOther ?
+ ((m_iOther == 2) ? *g_pDock3 : *g_pDock2)
+ : *g_pDock1,0,0,ICON_SIZE/2,ICON_SIZE/2);
+
+ thisRestrictionOfQt4IsNotNice.drawPixmap(0,ICON_SIZE/2,ICON_SIZE/2,ICON_SIZE/2,
+ m_iConsoles ?
+ ((m_iConsoles == 2) ? *g_pDock3 : *g_pDock2)
+ : *g_pDock1,0,ICON_SIZE/2,ICON_SIZE/2,ICON_SIZE/2);
+
+ thisRestrictionOfQt4IsNotNice.drawPixmap(ICON_SIZE/2,0,ICON_SIZE/2,ICON_SIZE/2,
+ m_iQueries ?
+ ((m_iQueries == 2)
+ ? *g_pDock3 : *g_pDock2)
+ : *g_pDock1,ICON_SIZE/2,0,ICON_SIZE/2,ICON_SIZE/2);
+
+ thisRestrictionOfQt4IsNotNice.drawPixmap(ICON_SIZE/2,ICON_SIZE/2,ICON_SIZE/2,ICON_SIZE/2,
+ m_iChannels ?
+ ((m_iChannels == 2) ? *g_pDock3 : *g_pDock2)
+ : *g_pDock1
+ ,ICON_SIZE/2,ICON_SIZE/2,ICON_SIZE/2,ICON_SIZE/2);
+
+ }
+ updateIcon();
+}
+
+void KviDockWidget::activatedSlot( QSystemTrayIcon::ActivationReason reason )
+{
+ if(reason==QSystemTrayIcon::Trigger)
+ {
+ toggleParentFrame();
+ }
+}
+
+void KviDockWidget::grabActivityInfo()
+{
+ KviTaskBarBase * t = m_pFrm->taskBar();
+
+ if(KVI_OPTION_BOOL(KviOption_boolUseLevelBasedTrayNotification))
+ {
+ if(KVI_OPTION_UINT(KviOption_uintMinTrayLowLevelMessage)>5) KVI_OPTION_UINT(KviOption_uintMinTrayLowLevelMessage)=5;
+ if(KVI_OPTION_UINT(KviOption_uintMinTrayHighLevelMessage)>5) KVI_OPTION_UINT(KviOption_uintMinTrayHighLevelMessage)=5;
+
+ if(KVI_OPTION_UINT(KviOption_uintMinTrayLowLevelMessage)<1) KVI_OPTION_UINT(KviOption_uintMinTrayLowLevelMessage)=1;
+ if(KVI_OPTION_UINT(KviOption_uintMinTrayHighLevelMessage)<1) KVI_OPTION_UINT(KviOption_uintMinTrayHighLevelMessage)=1;
+
+ if(KVI_OPTION_UINT(KviOption_uintMinTrayHighLevelMessage)<KVI_OPTION_UINT(KviOption_uintMinTrayLowLevelMessage))
+ KVI_OPTION_UINT(KviOption_uintMinTrayHighLevelMessage)=KVI_OPTION_UINT(KviOption_uintMinTrayLowLevelMessage);
+ }
+
+ m_iConsoles = 0;
+ m_iChannels = 0;
+ m_iQueries = 0;
+ m_iOther = 0;
+
+ for(KviTaskBarItem * b = t->firstItem();b;b = t->nextItem())
+ {
+ if(KVI_OPTION_BOOL(KviOption_boolUseLevelBasedTrayNotification))
+ {
+ int iLevel = b->highlightLevel();
+ switch(b->kviWindow()->type())
+ {
+ case KVI_WINDOW_TYPE_CONSOLE:
+ if(m_iConsoles < iLevel) m_iConsoles = iLevel;
+ break;
+ case KVI_WINDOW_TYPE_CHANNEL:
+ if(m_iChannels < iLevel) m_iChannels = iLevel;
+ break;
+ case KVI_WINDOW_TYPE_QUERY:
+ if(m_iQueries < iLevel) m_iQueries = iLevel;
+ break;
+ default:
+ if(m_iOther < iLevel) m_iOther = iLevel;
+ break;
+ }
+ } else {
+ int iLevel=0;
+ if(b->kviWindow()->view())
+ {
+ if(b->kviWindow()->view()->haveUnreadedHighlightedMessages())
+ {
+ iLevel=2;
+ } else if(b->kviWindow()->view()->haveUnreadedMessages())
+ {
+ iLevel=1;
+ }
+ if(iLevel>0)
+ switch(b->kviWindow()->type())
+ {
+ case KVI_WINDOW_TYPE_CONSOLE:
+ if(m_iConsoles < iLevel) m_iConsoles = iLevel;
+ break;
+ case KVI_WINDOW_TYPE_CHANNEL:
+ if(m_iChannels < iLevel) m_iChannels = iLevel;
+ break;
+ case KVI_WINDOW_TYPE_QUERY:
+ if(m_iQueries < iLevel) m_iQueries = iLevel;
+ break;
+ default:
+ if(m_iOther < iLevel) m_iOther = iLevel;
+ break;
+ }
+ }
+ }
+ }
+
+ if(KVI_OPTION_BOOL(KviOption_boolUseLevelBasedTrayNotification))
+ {
+ if(m_iConsoles >= KVI_OPTION_UINT(KviOption_uintMinTrayHighLevelMessage)) m_iConsoles=2;
+ else if(m_iConsoles >= KVI_OPTION_UINT(KviOption_uintMinTrayLowLevelMessage)) m_iConsoles=1;
+ else m_iConsoles=0;
+
+ if(m_iChannels >= KVI_OPTION_UINT(KviOption_uintMinTrayHighLevelMessage)) m_iChannels=2;
+ else if(m_iChannels >= KVI_OPTION_UINT(KviOption_uintMinTrayLowLevelMessage)) m_iChannels=1;
+ else m_iChannels=0;
+
+ if(m_iQueries >= KVI_OPTION_UINT(KviOption_uintMinTrayHighLevelMessage)) m_iQueries=2;
+ else if(m_iQueries >= KVI_OPTION_UINT(KviOption_uintMinTrayLowLevelMessage)) m_iQueries=1;
+ else m_iQueries=0;
+
+ if(m_iOther >= KVI_OPTION_UINT(KviOption_uintMinTrayHighLevelMessage)) m_iOther=2;
+ else if(m_iOther >= KVI_OPTION_UINT(KviOption_uintMinTrayLowLevelMessage)) m_iOther=1;
+ else m_iOther=0;
+ }
+}
+
+void KviDockWidget::updateIcon()
+{
+ setIcon(QIcon(m_CurrentPixmap));
+}
+
+
+static KviDockWidget * dockwidget_find(KviFrame *f)
+{
+ if(!g_pDockWidgetList)return 0;
+ for(KviDockWidget * w = g_pDockWidgetList->first();w;w = g_pDockWidgetList->next())
+ {
+ if(w->frame() == f)return w;
+ }
+ return 0;
+}
+
+/*
+ @doc: dockwidget.show
+ @type:
+ command
+ @title:
+ dockwidget.show
+ @short:
+ Shows the dock widget for the current frame window
+ @keyterms:
+ dock widget , system tray
+ @syntax:
+ dockwidget.show
+ @description:
+ Shows the dock widget for the current frame window.[br]
+ The dock widget is a small widget that docks in the KDE panel.[br]
+ It shows a small icon of the earth and eventually displays four squares
+ that cover this icon: the bottom left square appears when there is some new
+ text in any console window, the square becomes red if the text is highlighted.[br]
+ The bottom right square appears when there is some new text in any channel window,
+ and it becomes red when the text is highlighted.[br] The upper right square refers to
+ query windows and the upper left one to any other kind of window (dcc , links...).[br]
+ If you move the mouse over the dock widget a tooltip will show you the last lines
+ of the "new" text in all these windows.[br]
+ This is useful when you keep the main KVIrc window minimized and you're working on something else:
+ if the dock widget shows nothing but the earth icon , nothing is happening in the main KVIrc window.
+ If the dock widget shows one or more white (or red) squares , you can move the mouse over
+ and check what's happened exactly and eventually bring up the main KVIrc window by clicking on the widget.[br]
+ [big]tecnical details[/big]
+ The dock widget is currently working in KDE compilation mode only:
+ it relies on the KWin implementation of the Window Manager interaction protocol.
+ @seealso:
+ [cmd]dockwidget.hide[/cmd]
+*/
+
+static bool dockwidget_kvs_cmd_show(KviKvsModuleCommandCall * c)
+{
+ if(!(dockwidget_find(c->window()->frame())))
+ {
+ KviDockWidget * w = new KviDockWidget(c->window()->frame());
+ w->show();
+ }
+ return true;
+}
+
+/*
+ @doc: dockwidget.hide
+ @type:
+ command
+ @title:
+ dockwidget.hide
+ @short:
+ Hides the dock widget for the current frame window
+ @syntax:
+ dockwidget.hide
+ @description:
+ Hides the dock widget for the current frame window
+ @seealso:
+ [cmd]dockwidget.show[/cmd]
+*/
+
+static bool dockwidget_kvs_cmd_hide(KviKvsModuleCommandCall * c)
+{
+ KviDockWidget * w= dockwidget_find(c->window()->frame());
+ if(w)delete w;
+ // show the parent frame.. otherwise there will be no way to get it back
+ if(!c->window()->frame()->isVisible())
+ {
+ c->window()->frame()->show();
+ }
+ return true;
+}
+
+/*
+ @doc: dockwidget.hidewindow
+ @type:
+ command
+ @title:
+ dockwidget.hidewindow
+ @short:
+ Returns the state of the dock widget
+ @syntax:
+ dockwidget.hidewindow
+ @description:
+ Hides the window, assotiated with dockwidget
+ @seealso:
+ [cmd]dockwidget.show[/cmd], [cmd]dockwidget.hide[/cmd]
+*/
+
+static bool dockwidget_kvs_cmd_hidewindow(KviKvsModuleCommandCall * c)
+{
+ KviDockWidget * w= dockwidget_find(c->window()->frame());
+ if(w)
+ {
+ c->window()->frame()->hide();
+ }
+ return true;
+}
+
+/*
+ @doc: dockwidget.isVisible
+ @type:
+ function
+ @title:
+ $dockwidget.isVisible
+ @short:
+ Returns the state of the dock widget
+ @syntax:
+ $reguser.isVisible()
+ @description:
+ Returns 1 if the dock widget is actually visible , 0 otherwise.
+ @seealso:
+ [cmd]dockwidget.show[/cmd]
+*/
+
+static bool dockwidget_kvs_fnc_isvisible(KviKvsModuleFunctionCall * c)
+{
+ c->returnValue()->setBoolean(dockwidget_find(c->window()->frame()));
+ return true;
+}
+
+
+
+// =======================================
+// init routine
+// =======================================
+static bool dockwidget_module_init(KviModule * m)
+{
+ QString buffer;
+#ifdef COMPILE_ON_WINDOWS
+ g_pApp->findImage(buffer,"kvi_dock_win32-0.png");
+#else
+ g_pApp->findImage(buffer,"kvi_dock_part-0.png");
+#endif
+ g_pDock1 = new QPixmap(buffer);
+
+#ifdef COMPILE_ON_WINDOWS
+ g_pApp->findImage(buffer,"kvi_dock_win32-1.png");
+#else
+ g_pApp->findImage(buffer,"kvi_dock_part-1.png");
+#endif
+ g_pDock2 = new QPixmap(buffer);
+
+#ifdef COMPILE_ON_WINDOWS
+ g_pApp->findImage(buffer,"kvi_dock_win32-2.png");
+#else
+ g_pApp->findImage(buffer,"kvi_dock_part-2.png");
+#endif
+
+ g_pDock3 = new QPixmap(buffer);
+
+
+ g_pDockWidgetList = new KviPointerList<KviDockWidget>;
+ g_pDockWidgetList->setAutoDelete(false);
+
+
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"hide",dockwidget_kvs_cmd_hide);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"hidewindow",dockwidget_kvs_cmd_hidewindow);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"show",dockwidget_kvs_cmd_show);
+ KVSM_REGISTER_FUNCTION(m,"isVisible",dockwidget_kvs_fnc_isvisible);
+
+ return true;
+}
+
+static bool dockwidget_module_cleanup(KviModule *m)
+{
+ while(g_pDockWidgetList->first())delete g_pDockWidgetList->first();
+ delete g_pDockWidgetList;
+ g_pDockWidgetList = 0;
+
+ delete g_pDock1;
+ g_pDock1 = 0;
+
+ delete g_pDock2;
+ g_pDock2 = 0;
+
+ delete g_pDock3;
+ g_pDock3 = 0;
+
+ return true;
+}
+
+static bool dockwidget_module_can_unload(KviModule *)
+{
+ return g_pDockWidgetList->isEmpty();
+}
+
+// =======================================
+// plugin definition structure
+// =======================================
+KVIRC_MODULE(
+ "KVIrc dock widget implementation",
+ "2.0.0",
+ "Szymon Stefanek <pragma at kvirc dot net> and Alexey Uzhva <alexey at kvirc dot ru>" ,
+ "exports the /dockwidget.* interface\n",
+ dockwidget_module_init ,
+ dockwidget_module_can_unload,
+ 0,
+ dockwidget_module_cleanup
+)
+
+#include "libkvidockwidget_qt4.moc"
+
+#endif
diff --git a/src/modules/dockwidget/libkvidockwidget_qt4.h b/src/modules/dockwidget/libkvidockwidget_qt4.h
new file mode 100644
index 00000000..9d9e87bc
--- /dev/null
+++ b/src/modules/dockwidget/libkvidockwidget_qt4.h
@@ -0,0 +1,81 @@
+#ifndef _KVI_DOCKWIDGET_QT4_H_
+#define _KVI_DOCKWIDGET_QT4_H_
+//
+// This file is part of the KVirc irc client distribution
+// Creation date : Tue 02 Jan 2001 14:28:25 by Szymon Stefanek
+// Copyright (C) 2000-2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+//#ifdef COMPILE_USE_QT4
+
+#include "kvi_frame.h"
+
+class KviTalPopupMenu;
+#include <QSystemTrayIcon>
+
+class QPixmap;
+class QTimer;
+
+//class KviFrame;
+class KviDynamicToolTip;
+
+class KviDockWidget : public QSystemTrayIcon, public KviDockExtension
+{
+ Q_OBJECT
+public:
+ KviDockWidget(KviFrame * win);
+ ~KviDockWidget();
+protected:
+ KviFrame * m_pFrm;
+ KviDynamicToolTip * m_pTip;
+ KviTalPopupMenu * m_pContextPopup;
+ KviTalPopupMenu * m_pAwayPopup;
+
+ int m_iToggleFrame;
+ int m_iAwayMenuId;
+
+ bool m_bFlashed;
+
+ QPixmap m_CurrentPixmap;
+ QTimer* m_pFlashingTimer;
+ int m_iConsoles;
+ int m_iChannels;
+ int m_iQueries;
+ int m_iOther;
+public:
+ KviFrame * frame(){ return m_pFrm; };
+public:
+ virtual void refresh();
+ virtual void die();
+ void updateIcon();
+protected:
+ void grabActivityInfo();
+
+protected slots:
+ void fillContextPopup();
+ void toggleParentFrame();
+ void tipRequest(KviDynamicToolTip *tip,const QPoint &pnt);
+ void doAway(int);
+ void flashingTimerShot();
+
+ void activatedSlot( QSystemTrayIcon::ActivationReason reason );
+};
+
+//#endif
+
+#endif //_KVI_DOCKWIDGET_QT4_H_
diff --git a/src/modules/editor/Makefile.am b/src/modules/editor/Makefile.am
new file mode 100644
index 00000000..beb22541
--- /dev/null
+++ b/src/modules/editor/Makefile.am
@@ -0,0 +1,20 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\" -DKVIRC_SSEX
+
+pluglib_LTLIBRARIES = libkvieditor.la
+
+libkvieditor_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+nodist_libkvieditor_la_SOURCES = moc_scripteditor.cpp
+libkvieditor_la_SOURCES = libkvieditor.cpp scripteditor.cpp
+libkvieditor_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+noinst_HEADERS= scripteditor.h
+
+moc_%.cpp: %.h
+ $(SS_QT_MOC) $< -o $@
+
diff --git a/src/modules/editor/libkvieditor.cpp b/src/modules/editor/libkvieditor.cpp
new file mode 100644
index 00000000..14ad53b3
--- /dev/null
+++ b/src/modules/editor/libkvieditor.cpp
@@ -0,0 +1,94 @@
+//
+// File : libkvieditor.cpp
+// Creation date : Mon Sep 11 2000 12:19:00 by Szymon Stefanek
+//
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_module.h"
+
+#include "kvi_window.h"
+
+#include "scripteditor.h"
+
+KviModule * g_pEditorModulePointer = 0;
+
+KviPointerList<KviScriptEditorImplementation> * g_pScriptEditorWindowList = 0;
+
+static bool editor_module_init(KviModule * m)
+{
+ g_pScriptEditorWindowList = new KviPointerList<KviScriptEditorImplementation>;
+ g_pScriptEditorWindowList->setAutoDelete(false);
+
+ g_pEditorModulePointer = m;
+
+ return true;
+}
+
+static bool editor_module_cleanup(KviModule *m)
+{
+ while(g_pScriptEditorWindowList->first())
+ {
+ QObject * w = g_pScriptEditorWindowList->first()->parent();;
+ while(w)
+ {
+ //debug("%s %s %i %s",__FILE__,__FUNCTION__,__LINE__,w->className());
+ if(w->inherits("KviWindow"))
+ {
+ // debug("%s %s %i",__FILE__,__FUNCTION__,__LINE__);
+ ((KviWindow *)w)->close();
+ // debug("%s %s %i",__FILE__,__FUNCTION__,__LINE__);
+ break;
+ }
+ w = w->parent();
+ }
+ delete g_pScriptEditorWindowList->first();
+ }
+ delete g_pScriptEditorWindowList;
+ g_pScriptEditorWindowList = 0;
+
+ return true;
+}
+
+static bool editor_module_can_unload(KviModule *m)
+{
+ return ((g_pScriptEditorWindowList == 0) || (g_pScriptEditorWindowList->count() == 0));
+}
+
+KVIRC_MODULE(
+ "Editor", // module name
+ "1.0.0", // module version
+ "Copyright (C) 2000 Szymon Stefanek (pragma at kvirc dot net)", // author & (C)
+ "Text editor extension",
+ editor_module_init,
+ editor_module_can_unload,
+ 0,
+ editor_module_cleanup
+)
+
+// We want C linkage on this one: we want to be able to dlsym() it with a simple name
+// FIXME: Is this portable enough ? Or is better to have a table entry ?
+
+KVIMODULEEXPORTFUNC KviScriptEditor * editor_module_createScriptEditor(QWidget * par)
+{
+ return new KviScriptEditorImplementation(par);
+}
+
+KVIMODULEEXPORTFUNC void editor_module_destroyScriptEditor(KviScriptEditor * e)
+{
+ delete ((KviScriptEditorImplementation *)e);
+}
diff --git a/src/modules/editor/scripteditor.cpp b/src/modules/editor/scripteditor.cpp
new file mode 100644
index 00000000..06023a7c
--- /dev/null
+++ b/src/modules/editor/scripteditor.cpp
@@ -0,0 +1,1224 @@
+//=============================================================================
+//
+// File : scripteditor.cpp
+// Created on Sun Mar 28 1999 16:11:48 CEST by Szymon Stefanek
+// Code improvements by Carbone Alessandro & Tonino Imbesi
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 1999-2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "scripteditor.h"
+
+#include <qlayout.h>
+#include <qtoolbutton.h>
+#include <kvi_tal_groupbox.h>
+#include "kvi_tal_popupmenu.h"
+#include "kvi_tal_scrollview.h"
+#include <qmessagebox.h>
+#include <qtimer.h>
+#ifdef COMPILE_USE_QT4
+ //#define QSyntaxHighlighter Q3SyntaxHighlighter
+#else
+ #include <qobjectlist.h>
+#endif
+#include <qcursor.h>
+#include <qfont.h>
+#include <qrect.h>
+
+#include "kvi_fileutils.h"
+#include "kvi_locale.h"
+#include "kvi_filedialog.h"
+#include "kvi_qstring.h"
+#include "kvi_config.h"
+#include "kvi_module.h"
+#include "kvi_pointerlist.h"
+//
+#include "kvi_app.h"
+#include "kvi_console.h"
+#include "kvi_window.h"
+#include "kvi_iconmanager.h"
+#include "kvi_kvs_kernel.h"
+
+#include <qlayout.h>
+
+
+extern KviPointerList<KviScriptEditorImplementation> * g_pScriptEditorWindowList;
+extern KviModule * g_pEditorModulePointer;
+
+
+static QColor g_clrBackground(255,255,255);
+static QColor g_clrNormalText(0,0,0);
+static QColor g_clrBracket(255,0,0);
+static QColor g_clrComment(0,120,0);
+static QColor g_clrFunction(0,17,255);
+static QColor g_clrKeyword(85,85,255);
+static QColor g_clrVariable(255,0,0);
+static QColor g_clrPunctuation(180,180,0);
+static QColor g_clrFind(0,0,0);
+
+static QFont g_fntNormal("Courier New",8);
+
+KviCompletionBox::KviCompletionBox(QWidget * parent = 0)
+: KviTalListBox(parent)
+{
+ setPaletteForegroundColor(QColor(0,0,0));
+ setPaletteBackgroundColor(QColor(255,255,255));
+#ifdef COMPILE_USE_QT4
+ setHScrollBarMode(KviTalListBox::AlwaysOff);
+#else
+ setHScrollBarMode(QScrollView::AlwaysOff);
+#endif
+ QFont listfont=font();
+ listfont.setPointSize(8);
+ setFont(listfont);
+ setVariableWidth(false);
+ setFixedWidth(200);
+ //completelistbox->setColumnMode(KviTalListBox::Variable);
+ hide();
+}
+
+void KviCompletionBox::updateContents(QString buffer)
+{
+ buffer=buffer.stripWhiteSpace();
+ KviPointerList<QString> list;
+ clear();
+
+ QString szModule;
+ QChar* pCur = (QChar *)buffer.ucs2();
+
+ int pos=buffer.find('.');
+
+ if(pos>0)
+ {
+ szModule=buffer.left(pos);
+ if(szModule[0].unicode()=='$')
+ szModule.remove(0,1);
+ }
+
+ if(pCur->unicode() == '$')
+ {
+ buffer.remove(0,1);
+ if(!buffer.isEmpty())
+ {
+ if(szModule.isEmpty())
+ KviKvsKernel::instance()->completeFunction(buffer,&list);
+ else
+ debug("we need a module completion!");
+ for ( QString* szCurrent = list.first(); szCurrent; szCurrent = list.next() )
+ {
+ szCurrent->prepend('$');
+ //szCurrent->append('(');
+ insertItem(*szCurrent);
+ }
+ }
+ }
+ else
+ {
+ if(szModule.isEmpty())
+ KviKvsKernel::instance()->completeCommand(buffer,&list);
+ else
+ debug("we need a module completion!");
+ for ( QString* szCurrent = list.first(); szCurrent; szCurrent = list.next() )
+ {
+ szCurrent->append(' ');
+ insertItem(*szCurrent);
+ }
+ }
+// debug("%s %s %i %i",__FILE__,__FUNCTION__,__LINE__,count());
+}
+
+void KviCompletionBox::keyPressEvent(QKeyEvent * e)
+{
+// debug("%s %s %i %x",__FILE__,__FUNCTION__,__LINE__,e->key());
+ switch(e->key())
+ {
+ case Qt::Key_Escape:
+ hide();
+ setFocus();
+ break;
+ case Qt::Key_Return:
+ break;
+ default:
+ if(!e->text().isEmpty())
+ {
+ e->ignore();
+ }
+
+ }
+ KviTalListBox::keyPressEvent(e);
+}
+
+KviScriptEditorWidgetColorOptions::KviScriptEditorWidgetColorOptions(QWidget * pParent)
+: QDialog(pParent)
+{
+ m_pSelectorInterfaceList = new KviPointerList<KviSelectorInterface>;
+ m_pSelectorInterfaceList->setAutoDelete(false);
+ setCaption(__tr2qs_ctx("Preferences","editor"));
+ QGridLayout * g = new QGridLayout(this,3,3,4,4);
+
+ KviFontSelector * f = new KviFontSelector(this,__tr2qs_ctx("Font:","editor"),&g_fntNormal,true);
+ g->addMultiCellWidget(f,0,0,0,2);
+ m_pSelectorInterfaceList->append(f);
+ KviTalGroupBox * gbox = new KviTalGroupBox(1,Qt::Horizontal,__tr2qs("Colors" ),this);
+ g->addMultiCellWidget(gbox,1,1,0,2);
+ KviColorSelector * s = addColorSelector(gbox,__tr2qs_ctx("Background:","editor"),&g_clrBackground,true);
+ s = addColorSelector(gbox,__tr2qs_ctx("Normal text:","editor"),&g_clrNormalText,true);
+ s = addColorSelector(gbox,__tr2qs_ctx("Brackets:","editor"),&g_clrBracket,true);
+ s = addColorSelector(gbox,__tr2qs_ctx("Comments:","editor"),&g_clrComment,true);
+ s = addColorSelector(gbox,__tr2qs_ctx("Functions:","editor"),&g_clrFunction,true);
+ s = addColorSelector(gbox,__tr2qs_ctx("Keywords:","editor"),&g_clrKeyword,true);
+ s = addColorSelector(gbox,__tr2qs_ctx("Variables:","editor"),&g_clrVariable,true);
+ s = addColorSelector(gbox,__tr2qs_ctx("Punctuation:","editor"),&g_clrPunctuation,true);
+ s = addColorSelector(gbox,__tr2qs_ctx("Find:","editor"),&g_clrFind,true);
+
+ QPushButton * b = new QPushButton(__tr2qs_ctx("&OK","editor"),this);
+ b->setDefault(true);
+ connect(b,SIGNAL(clicked()),this,SLOT(okClicked()));
+ g->addWidget(b,2,1);
+
+ b = new QPushButton(__tr2qs_ctx("Cancel","editor"),this);
+ connect(b,SIGNAL(clicked()),this,SLOT(reject()));
+ g->addWidget(b,2,2);
+
+
+ g->setRowStretch(0,1);
+ g->setColStretch(0,1);
+}
+
+KviScriptEditorWidgetColorOptions::~KviScriptEditorWidgetColorOptions()
+{
+ delete m_pSelectorInterfaceList;
+}
+
+KviColorSelector * KviScriptEditorWidgetColorOptions::addColorSelector(QWidget * pParent,const QString & txt,QColor * pOption,bool bEnabled)
+{
+ KviColorSelector * s = new KviColorSelector(pParent,txt,pOption,bEnabled);
+ m_pSelectorInterfaceList->append(s);
+ return s;
+}
+
+void KviScriptEditorWidgetColorOptions::okClicked()
+{
+ for(KviSelectorInterface * i = m_pSelectorInterfaceList->first();i;i = m_pSelectorInterfaceList->next())
+ {
+ i->commit();
+ }
+
+ accept();
+}
+
+
+KviScriptEditorWidget::KviScriptEditorWidget(QWidget * pParent)
+: KviTalTextEdit(pParent)
+{
+ setWordWrap(KviTalTextEdit::NoWrap);
+ m_pParent=pParent;
+ m_szHelp="Nothing";
+ updateOptions();
+ m_szFind="";
+ completelistbox=new KviCompletionBox(this);
+ connect (completelistbox,SIGNAL(selected(const QString &)),this,SLOT(slotComplete(const QString &)));
+}
+
+KviScriptEditorWidget::~KviScriptEditorWidget()
+{
+
+}
+
+#ifdef COMPILE_USE_QT4
+Q3PopupMenu * KviScriptEditorWidget::createPopupMenu( const QPoint& pos )
+#else
+QPopupMenu * KviScriptEditorWidget::createPopupMenu( const QPoint& pos )
+#endif
+{
+#ifdef COMPILE_USE_QT4
+ Q3PopupMenu *pop=KviTalTextEdit::createPopupMenu(pos);
+#else
+ QPopupMenu *pop=KviTalTextEdit::createPopupMenu(pos);
+#endif
+ pop->insertItem(__tr2qs("Context sensitive help"),this,SLOT(slotHelp()),Qt::CTRL+Qt::Key_H);
+ pop->insertItem(__tr2qs("&Replace"),this,SLOT(slotReplace()),Qt::CTRL+Qt::Key_R);
+ return pop;
+}
+
+void KviScriptEditorWidget::slotFind()
+{
+ m_szFind=((KviScriptEditorImplementation*)m_pParent)->getFindlineedit()->text();
+ setText(text());
+}
+
+void KviScriptEditorWidget::slotReplace()
+{
+ KviScriptEditorReplaceDialog *dialog=new KviScriptEditorReplaceDialog(this,tr("Find & Repalce"));
+ connect (dialog,SIGNAL(replaceAll(const QString &,const QString &)),m_pParent,SLOT(slotReplaceAll(const QString &,const QString &)));
+ connect (dialog,SIGNAL(initFind()),m_pParent,SLOT(slotInitFind()));
+ connect (dialog,SIGNAL(nextFind(const QString &)),m_pParent,SLOT(slotNextFind(const QString &)));
+ if(dialog->exec()){};
+
+}
+void KviScriptEditorWidget::slotHelp()
+{
+ contextSensitiveHelp();
+}
+
+
+void KviScriptEditorWidget::updateOptions()
+{
+ setPaper(QBrush(g_clrBackground));
+ setFont(g_fntNormal);
+ setColor(g_clrNormalText);
+
+ QPalette p = palette();
+ p.setColor(QColorGroup::Text,g_clrNormalText);
+ setPalette(p);
+
+#ifdef COMPILE_USE_QT4
+ setTextFormat(Qt::PlainText);
+#else
+ setTextFormat(KviTalTextEdit::PlainText);
+#endif
+
+ // this will rehighlight everything
+ setText(text()); // an "hack" to ensure Update all in the editor
+ KviScriptSyntaxHighlighter *h = new KviScriptSyntaxHighlighter(this);
+ (void)h;
+ ((KviScriptEditorImplementation*)m_pParent)->getFindlineedit()->setPaletteForegroundColor(g_clrFind);
+}
+
+void KviScriptEditorWidget::keyPressEvent(QKeyEvent * e)
+{
+ if(e->state() == Qt::ControlButton)
+ {
+ switch(e->key())
+ {
+ case Qt::Key_B:
+ insert("$b");
+ return;
+ case Qt::Key_K:
+ insert("$k");
+ return;
+ case Qt::Key_O:
+ insert("$o");
+ return;
+ case Qt::Key_U:
+ insert("$u");
+ return;
+ case Qt::Key_Enter:
+ case Qt::Key_Return:
+ case Qt::Key_Backspace:
+ case Qt::Key_PageUp:
+ e->ignore(); // allow the parent to process it
+ return;
+ break;
+ }
+ }
+
+ if(e->state() == Qt::ShiftButton)
+ {
+ if (e->key() == Qt::Key_Insert)
+ {
+ completition();
+ return;
+ }
+ }
+ switch(e->key())
+ {
+ case Qt::Key_Period:
+ case Qt::Key_Left:
+ case Qt::Key_Right:
+ if(!completelistbox->isVisible()) completition(0);
+ break;
+ case Qt::Key_Up:
+ case Qt::Key_Escape:
+ case Qt::Key_PageUp:
+ case Qt::Key_PageDown:
+ case Qt::Key_End:
+ case Qt::Key_Home:
+ if(completelistbox->isVisible()) completelistbox->hide();
+ break;
+ case Qt::Key_Down:
+ if(completelistbox->isVisible())
+ {
+ completelistbox->setFocus();
+ completelistbox->setCurrentItem(0);
+ return;
+ }
+ break;
+ case Qt::Key_Return:
+ KviTalTextEdit::keyPressEvent(e);
+ int para,pos;
+ getCursorPosition(&para,&pos);
+ if(para > 0)
+ {
+ QString szPrev=text(para-1);
+ if(!szPrev.isEmpty())
+ {
+ if(szPrev.at(szPrev.length() - 1).unicode() == ' ')
+ szPrev.remove(szPrev.length() - 1,1);
+ QString szCur;
+ const QChar * pCur = (const QChar *)szPrev.ucs2();
+ if(pCur)
+ {
+ while(pCur->unicode() && pCur->isSpace())
+ {
+ szCur.append(*pCur);
+ pCur++;
+ }
+ }
+ insertAt(szCur,para,0);
+ setCursorPosition(para,szCur.length()+pos);
+ }
+// debug("|%i|",pos);
+ }
+ return;
+ default:
+ setFocus();
+ break;
+ }
+ KviTalTextEdit::keyPressEvent(e);
+ emit keyPressed();
+ if(completelistbox->isVisible())
+ completition(0);
+}
+
+void KviScriptEditorWidget::contentsMousePressEvent(QMouseEvent *e)
+{
+ completelistbox->hide();
+ if (e->button() == Qt::RightButton)
+ {
+// bool bIsFirstWordInLine;
+ QString buffer;
+ int para = paragraphAt(e->pos());
+ int index=charAt(e->pos(),&para);
+ buffer=this->text(para);
+ getWordOnCursor(buffer,index);
+ QString tmp=buffer;
+ KviPointerList<QString> l;
+ if (tmp.left(1) == "$")
+ {
+ tmp.remove(0,1);
+ KviKvsKernel::instance()->completeFunction(tmp,&l);
+ if (l.count() != 1) buffer="";
+ else buffer=*(l.at(0));
+ }
+ else
+ {
+ KviKvsKernel::instance()->completeCommand(tmp,&l);
+ if (l.count() != 1) buffer="";
+ else buffer=*(l.at(0));
+ }
+ //debug (buffer);
+ m_szHelp=buffer;
+ }
+ KviTalTextEdit::contentsMousePressEvent(e);
+
+}
+
+bool KviScriptEditorWidget::contextSensitiveHelp() const
+{
+ QString buffer;
+ int para,index;
+ getCursorPosition(&para,&index);
+ buffer=text(para);
+
+ getWordOnCursor(buffer,index);
+
+ /*
+ QString tmp=buffer;
+ KviPointerList<QString> * l;
+ if(tmp.left(1) == "$")
+ {
+ tmp.remove(0,1);
+ l = g_pUserParser->completeFunctionAllocateResult(tmp);
+ } else {
+ l = g_pUserParser->completeCommandAllocateResult(tmp);
+ }
+
+ bool bOk = false;
+ if(l)
+ {
+ for(QString * s = l->first();s;s = l->next())
+ {
+ if(KviQString::equalCI(*s,buffer))
+ {
+ l->last();
+ bOk = true;
+ }
+ }
+ }
+ g_pUserParser->freeCompletionResult(l);
+ if(!bOk)return false;
+ */
+
+ QString parse;
+ KviQString::sprintf(parse,"timer -s (help,0){ help -s %Q; }",&buffer);
+ debug ("parsing %s",parse.latin1());
+ KviKvsScript::run(parse,(KviWindow*)g_pApp->activeConsole());
+
+ return true;
+}
+
+
+void KviScriptEditorWidget::getWordOnCursor(QString &buffer,int index) const
+{
+ QRegExp re("[ \t=,\\(\\)\"}{\\[\\]\r\n+-*><;@!]");
+ //debug("BUFFER IS %s",buffer.utf8().data());
+ int start = buffer.findRev(re,index);
+ int end = buffer.find(re,index);
+
+ QString tmp;
+ if(start!=end)
+ {
+ if(start<0)start=0;
+ else start++;
+ if(end<0)end=index;
+ tmp = buffer.mid(start,end-start);
+ }
+ buffer = tmp;
+ //debug("BUFFER NOW IS %s",buffer.utf8().data());
+}
+
+void KviScriptEditorWidget::completition(bool bCanComplete)
+{
+ int line,index;
+ QString buffer;
+ QString word;
+ getCursorPosition(&line,&index);
+ buffer=this->text(line);
+ bool bIsFirstWordInLine;
+ getWordBeforeCursor(buffer,index,&bIsFirstWordInLine);
+ if(!buffer.isEmpty())
+ completelistbox->updateContents(buffer);
+ if (completelistbox->count() == 1) word=completelistbox->text(0);
+ if (!word.isEmpty() && bCanComplete)
+ {
+ insert(word);
+ completelistbox->hide();
+ }
+ if( completelistbox->count() == 0 )
+ completelistbox->hide();
+ else if(!completelistbox->isVisible())
+ {
+ if (completelistbox->count() <6) completelistbox->resize(completelistbox->width(),(completelistbox->count()*completelistbox->fontMetrics().height()+20));
+ else completelistbox->resize(completelistbox->width(),6*completelistbox->fontMetrics().height()+20);
+ int posy=paragraphRect(line).bottom();
+ int posx=fontMetrics().width(this->text(line).left(index));
+ completelistbox->move(posx,posy);
+ completelistbox->show();
+ }
+}
+
+void KviScriptEditorWidget::getWordBeforeCursor(QString &buffer,int index,bool *bIsFirstWordInLine)
+{
+ QString tmp = buffer.left(index);
+ buffer=tmp;
+ int idx = buffer.findRev(' ');
+ int idx1 = buffer.findRev("=");
+ int idx2 = buffer.findRev(',');
+ int idx3 = buffer.findRev('(');
+ int idx4 = buffer.findRev('"');
+ if(idx1 > idx) idx= idx1;
+ if(idx2 > idx)idx = idx2;
+ if(idx3 > idx)idx = idx3;
+ if(idx4 > idx)idx = idx4;
+ *bIsFirstWordInLine = false;
+ if(idx > -1)buffer.remove(0,idx);
+ else
+ {
+ *bIsFirstWordInLine = true;
+ buffer.insert(0," ");
+ }
+
+}
+
+void KviScriptEditorWidget::slotComplete(const QString &str)
+{
+ QString complete=str;
+ int line,index;
+ getCursorPosition(&line,&index);
+ QString buffer;
+ buffer=this->text(line);
+ bool bIsFirstWordInLine;
+ getWordBeforeCursor(buffer,index,&bIsFirstWordInLine);
+ int len=buffer.length();
+// if (buffer[1].unicode() == '$') len --;
+ complete.remove(0,len-1);
+ if (buffer[1].unicode() == '$') complete.append("(");
+ else complete.append(" ");
+ insert (complete);
+ completelistbox->hide();
+ setFocus();
+}
+
+KviScriptSyntaxHighlighter::KviScriptSyntaxHighlighter(KviScriptEditorWidget * pWidget)
+: QSyntaxHighlighter(pWidget)
+{
+}
+
+KviScriptSyntaxHighlighter::~KviScriptSyntaxHighlighter()
+{
+}
+
+#define IN_COMMENT 1
+#define IN_LINE 2
+#define IN_STRING 4
+
+int KviScriptSyntaxHighlighter::highlightParagraph(const QString &text,int endStateOfLastPara)
+
+{
+ const QChar * pBuf = (const QChar *)text.ucs2();
+ const QChar * c = pBuf;
+ if(!c)return endStateOfLastPara;
+
+ if(endStateOfLastPara < 0)endStateOfLastPara = 0;
+
+ bool bNewCommand = !(endStateOfLastPara & IN_LINE);
+ bool bInComment = endStateOfLastPara & IN_COMMENT;
+ bool bInString = endStateOfLastPara & IN_STRING;
+
+ const QChar * pBegin;
+
+
+ while(c->unicode())
+ {
+ if(bInComment)
+ {
+ pBegin = c;
+ while(c->unicode() && (c->unicode() != '*'))c++;
+ if(!c->unicode())
+ {
+ setFormat(pBegin - pBuf,c - pBegin,g_fntNormal,g_clrComment);
+ return IN_COMMENT;
+ }
+ c++;
+ if(c->unicode() == '/')
+ {
+ // end of the comment!
+ c++;
+ setFormat(pBegin - pBuf,c - pBegin,g_fntNormal,g_clrComment);
+ bInComment = false;
+ bNewCommand = true;
+ }
+ continue;
+ }
+
+ if(c->isSpace())
+ {
+ while(c->unicode() && c->isSpace())c++;
+ if(!c->unicode())continue;
+ }
+
+ pBegin = c;
+
+ // this does not break the bNewCommand flag
+ if((c->unicode() == '{') || (c->unicode() == '}'))
+ {
+ c++;
+ setFormat(pBegin - pBuf,1,g_fntNormal,g_clrBracket);
+ continue;
+ }
+
+
+ if(bNewCommand)
+ {
+ bNewCommand = false;
+
+ if(c->unicode() == '#')
+ {
+ if(c > pBuf)
+ {
+ const QChar * prev = c - 1;
+ if((prev->unicode() == ']') || (prev->unicode() == '}'))
+ {
+ // array or hash count
+ c++;
+ setFormat(pBegin - pBuf,c - pBegin,g_fntNormal,g_clrPunctuation);
+ continue;
+ }
+ }
+ // comment until the end of the line
+ while(c->unicode())c++;
+ setFormat(pBegin - pBuf,c - pBegin,g_fntNormal,g_clrComment);
+ continue;
+ }
+ if(c->unicode() == '/')
+ {
+ c++;
+ if(c->unicode() == '/')
+ {
+ while(c->unicode())c++;
+ setFormat(pBegin - pBuf,c - pBegin,g_fntNormal,g_clrComment);
+ continue;
+ } else if(c->unicode() == '*')
+ {
+ c++;
+ setFormat(pBegin - pBuf,c - pBegin,g_fntNormal,g_clrComment);
+ bInComment = true;
+ continue;
+ }
+ c--;
+ }
+ if(c->unicode() && (c->isLetterOrNumber() || (c->unicode() == '_')))
+ {
+ c++;
+ while(c->unicode() && (c->isLetterOrNumber() || (c->unicode() == '.') || (c->unicode() == '_') || (c->unicode() == ':')))c++;
+ setFormat(pBegin - pBuf,c - pBegin,g_fntNormal,g_clrKeyword);
+ // special processing for callbacks and magic commands
+ if(pBegin->unicode() == 'e')
+ {
+ if(c - pBegin == 4)
+ {
+ // might be "else"
+ QString tmp(pBegin,4);
+ if(tmp.lower() == "else")bNewCommand = true;
+ continue;
+ }
+ }
+ else
+ if(pBegin->unicode() == 'f')
+ {
+ if(c - pBegin == 8)
+ {
+ // might be "function"
+ QString tmp(pBegin,8);
+ if(tmp.lower() == "function")bNewCommand = true;
+ continue;
+ }
+ }
+
+ if(pBegin->unicode() == 'i')
+ {
+ if(c - pBegin == 8)
+ {
+ // might be "internal"
+ QString tmp(pBegin,8);
+ if(tmp.lower() == "internal")bNewCommand = true;
+ continue;
+ }
+ }
+
+ // not an else or special command function... FIXME: should check for callbacks.. but that's prolly too difficult :)
+ continue;
+ }
+ }
+ if(c->unicode() == '$')
+ {
+ c++;
+ if(c->unicode() == '$')
+ {
+ c++;
+ setFormat(pBegin - pBuf,c - pBegin,g_fntNormal,g_clrKeyword);
+ } else {
+ while(c->unicode() && (c->isLetterOrNumber() || (c->unicode() == '.') || (c->unicode() == '_') || (c->unicode() == ':')))c++;
+ setFormat(pBegin - pBuf,c - pBegin,g_fntNormal,g_clrFunction);
+ }
+ continue;
+ }
+
+ if(c->unicode() == '-')
+ {
+ QChar * pTmp =(QChar *) c;
+ c++;
+ if(c->unicode() == '-') c++;
+ if(c->isLetter())
+ {
+ while(c->unicode() && (c->isLetterOrNumber() || (c->unicode() == '_')))c++;
+ setFormat(pBegin - pBuf,c - pBegin,g_fntNormal,g_clrKeyword);
+ continue;
+ } else {
+ while(c!=pTmp) c--;
+ }
+ }
+
+ if(c->unicode() == '%')
+ {
+ c++;
+ if(c->unicode() && (c->isLetterOrNumber() || (c->unicode() == ':') || (c->unicode() == '_')))
+ {
+ while(c->unicode() && (c->isLetterOrNumber() || (c->unicode() == ':') || (c->unicode() == '_')))c++;
+ setFormat(pBegin - pBuf,c - pBegin,g_fntNormal,g_clrVariable);
+ continue;
+ }
+ c--;
+ }
+
+ if(!c->unicode())continue;
+
+ if(c->isLetterOrNumber() || c->unicode() == '_')
+ {
+ c++;
+ while(c->unicode() && c->isLetterOrNumber() || (c->unicode() == '_'))c++;
+ setFormat(pBegin - pBuf,c - pBegin,g_fntNormal,g_clrNormalText);
+ continue;
+ }
+
+ if(c->unicode() == '\\')
+ {
+ c++;
+ setFormat(pBegin - pBuf,c - pBegin,g_fntNormal,g_clrPunctuation);
+ // the next char is to be interpreted as normal text
+ pBegin = c;
+ if(c->unicode() && (c->unicode() != '\n'))
+ {
+ c++;
+ setFormat(pBegin - pBuf,c - pBegin,g_fntNormal,g_clrNormalText);
+ continue;
+ }
+ // this is never returned since Qt sux in string processing
+ // it sets the newlines to spaces and we have no secure way to undestand that this was the end of a line
+ return IN_LINE;
+ }
+
+ if(c->unicode() == '"')
+ {
+ bInString = !bInString;
+ c++;
+ setFormat(pBegin - pBuf,c - pBegin,g_fntNormal,g_clrPunctuation);
+ continue;
+ } else if(c->unicode() == ';')
+ {
+ if(!bInString) bNewCommand = true; // the next will be a new command
+ }
+
+ c++;
+ if(bInString)
+ {
+ setFormat(pBegin - pBuf,c - pBegin,g_fntNormal,g_clrNormalText);
+ } else {
+ setFormat(pBegin - pBuf,c - pBegin,g_fntNormal,g_clrPunctuation);
+ }
+ }
+
+ bool i=TRUE;
+ QString szFind=((KviScriptEditorWidget *)textEdit())->m_szFind;
+ if (!szFind.isEmpty())
+ {
+ int index=0;
+ while (i)
+ {
+ index=text.find(szFind,index,false);
+ if (index != -1)
+ {
+ setFormat(index,szFind.length(),g_clrFind);
+ index += szFind.length();
+ }
+ else i=false;
+ }
+ }
+ if(bInString)
+ return IN_LINE | IN_STRING;
+ else
+ return 0;
+}
+
+// 22.02.2005 :: 00:01
+// valgrind --leak-check=yes --num-callers=10 -v kvirc -f
+//
+//==30299== Warning: SIGSEGV not in user code; either from syscall kill()
+//==30299== or possible Valgrind bug. This message is only shown 3 times.
+//==30299== Warning: SIGSEGV not in user code; either from syscall kill()
+//==30299== or possible Valgrind bug. This message is only shown 3 times.
+//==30299== Warning: SIGSEGV not in user code; either from syscall kill()
+//==30299== or possible Valgrind bug. This message is only shown 3 times.
+
+
+KviScriptEditorImplementation::KviScriptEditorImplementation(QWidget * par)
+:KviScriptEditor(par)
+{
+ if(g_pScriptEditorWindowList->isEmpty())loadOptions();
+ g_pScriptEditorWindowList->append(this);
+ m_lastCursorPos=QPoint(0,0);
+ QGridLayout * g = new QGridLayout(this,2,3,0,0);
+
+ m_pFindLineedit = new QLineEdit(" ",this);
+#ifndef COMPILE_USE_QT4
+ m_pFindLineedit->setFrameStyle(QFrame::Sunken | QFrame::Panel);
+#endif
+ m_pFindLineedit->setText("");
+ m_pFindLineedit->setPaletteForegroundColor(g_clrFind);
+
+ m_pEditor = new KviScriptEditorWidget(this);
+ g->addMultiCellWidget(m_pEditor,0,0,0,3);
+ g->setRowStretch(0,1);
+
+#ifdef COMPILE_USE_QT4
+ QToolButton * b = new QToolButton(Qt::DownArrow,this,"dsa2");
+#else
+ QToolButton * b = new QToolButton(DownArrow,this);
+#endif
+ b->setMinimumWidth(24);
+ g->addWidget(b,1,0);
+
+ KviTalPopupMenu * pop = new KviTalPopupMenu(b);
+ pop->insertItem(__tr2qs_ctx("&Open...","editor"),this,SLOT(loadFromFile()));
+ pop->insertItem(__tr2qs_ctx("&Save As...","editor"),this,SLOT(saveToFile()));
+ pop->insertSeparator();
+ pop->insertItem(__tr2qs_ctx("&Configure Editor...","editor"),this,SLOT(configureColors()));
+ b->setPopup(pop);
+ b->setPopupDelay(1);
+
+ g->setColStretch(1,1);
+ g->setColStretch(2,10);
+ g->addWidget(m_pFindLineedit,1,2);
+ QLabel *lab= new QLabel("find",this);
+ lab->setText(tr("Find"));
+
+ g->addWidget(lab,1,1);
+ m_pRowColLabel = new QLabel("0",this);
+ m_pRowColLabel->setFrameStyle(QFrame::Sunken | QFrame::Panel);
+ m_pRowColLabel->setMinimumWidth(80);
+ g->addWidget(m_pRowColLabel,1,3);
+
+ connect(m_pFindLineedit,SIGNAL(returnPressed()),m_pEditor,SLOT(slotFind()));
+ connect(m_pFindLineedit,SIGNAL(returnPressed()),this,SLOT(slotFind()));
+ connect(m_pEditor,SIGNAL(keyPressed()),this,SLOT(updateRowColLabel()));
+ connect(m_pEditor,SIGNAL(textChanged()),this,SLOT(updateRowColLabel()));
+ connect(m_pEditor,SIGNAL(selectionChanged()),this,SLOT(updateRowColLabel()));
+ m_lastCursorPos = QPoint(-1,-1);
+}
+
+KviScriptEditorImplementation::~KviScriptEditorImplementation()
+{
+ g_pScriptEditorWindowList->removeRef(this);
+ if(g_pScriptEditorWindowList->isEmpty())saveOptions();
+}
+
+void KviScriptEditorImplementation::loadOptions()
+{
+ QString tmp;
+ g_pEditorModulePointer->getDefaultConfigFileName(tmp);
+
+ KviConfig cfg(tmp,KviConfig::Read);
+
+ g_clrBackground = cfg.readColorEntry("Background",QColor(0,0,0));;
+ g_clrNormalText = cfg.readColorEntry("NormalText",QColor(100,255,0));
+ g_clrBracket = cfg.readColorEntry("Bracket",QColor(255,0,0));
+ g_clrComment = cfg.readColorEntry("Comment",QColor(0,120,0));
+ g_clrFunction = cfg.readColorEntry("Function",QColor(255,255,0));
+ g_clrKeyword = cfg.readColorEntry("Keyword",QColor(120,120,150));
+ g_clrVariable = cfg.readColorEntry("Variable",QColor(200,200,200));
+ g_clrPunctuation = cfg.readColorEntry("Punctuation",QColor(180,180,0));
+ g_clrFind = cfg.readColorEntry("Find",QColor(255,0,0));
+
+ g_fntNormal = cfg.readFontEntry("Font",QFont("Fixed",12));
+}
+
+bool KviScriptEditorImplementation::isModified()
+{
+ return m_pEditor->isModified();
+}
+
+void KviScriptEditorImplementation::slotFind()
+{
+ emit find(m_pFindLineedit->text());
+
+}
+void KviScriptEditorImplementation::slotNextFind(const QString &text)
+{
+// emit nextFind(const QString &text);
+
+}void KviScriptEditorImplementation::slotInitFind()
+{
+ emit initFind();
+
+}
+void KviScriptEditorImplementation::slotReplaceAll(const QString &txt,const QString &txt1)
+{
+ emit replaceAll(txt,txt1);
+}
+void KviScriptEditorImplementation::saveOptions()
+{
+ QString tmp;
+ g_pEditorModulePointer->getDefaultConfigFileName(tmp);
+
+ KviConfig cfg(tmp,KviConfig::Write);
+
+ cfg.writeEntry("Background",g_clrBackground);;
+ cfg.writeEntry("NormalText",g_clrNormalText);
+ cfg.writeEntry("Bracket",g_clrBracket);
+ cfg.writeEntry("Comment",g_clrComment);
+ cfg.writeEntry("Function",g_clrFunction);
+ cfg.writeEntry("Keyword",g_clrKeyword);
+ cfg.writeEntry("Variable",g_clrVariable);
+ cfg.writeEntry("Punctuation",g_clrPunctuation);
+ cfg.writeEntry("Find",g_clrFind);
+ cfg.writeEntry("Font",g_fntNormal);
+}
+
+void KviScriptEditorImplementation::setFocus()
+{
+ m_pEditor->setFocus();
+}
+
+
+
+void KviScriptEditorImplementation::focusInEvent(QFocusEvent *)
+{
+ m_pEditor->setFocus();
+}
+
+
+void KviScriptEditorImplementation::setEnabled(bool bEnabled)
+{
+ QWidget::setEnabled(bEnabled);
+ m_pEditor->setEnabled(bEnabled);
+ m_pRowColLabel->setEnabled(bEnabled);
+}
+
+void KviScriptEditorImplementation::saveToFile()
+{
+ QString fName;
+ if(KviFileDialog::askForSaveFileName(fName,
+ __tr2qs_ctx("Choose a Filename - KVIrc","editor"),
+ QString::null,
+ QString::null,false,true,true))
+ {
+ QString buffer = m_pEditor->text();
+
+ //if(tmp.isEmpty())tmp = "";
+ //KviStr buffer = tmp.utf8().data();
+ if(!KviFileUtils::writeFile(fName,buffer))
+ {
+ QString tmp;
+ QMessageBox::warning(this,
+ __tr2qs_ctx("Save Failed - KVIrc","editor"),
+ KviQString::sprintf(tmp,__tr2qs_ctx("Can't open the file %s for writing.","editor"),&fName));
+ }
+ }
+}
+
+void KviScriptEditorImplementation::setText(const KviQCString &txt)
+{
+ m_pEditor->setText(txt.data());
+#ifdef COMPILE_USE_QT4
+ m_pEditor->setTextFormat(Qt::PlainText);
+#else
+ m_pEditor->setTextFormat(KviTalTextEdit::PlainText);
+#endif
+ m_pEditor->moveCursor(KviTalTextEdit::MoveEnd,false);
+ m_pEditor->setModified(false);
+ updateRowColLabel();
+}
+
+void KviScriptEditorImplementation::getText(KviQCString &txt)
+{
+ txt = m_pEditor->text();
+}
+QLineEdit * KviScriptEditorImplementation::getFindlineedit()
+{
+ return m_pFindLineedit;
+}
+void KviScriptEditorImplementation::setText(const QString &txt)
+{
+ m_pEditor->setText(txt);
+#ifdef COMPILE_USE_QT4
+ m_pEditor->setTextFormat(Qt::PlainText);
+#else
+ m_pEditor->setTextFormat(KviTalTextEdit::PlainText);
+#endif
+ m_pEditor->moveCursor(KviTalTextEdit::MoveEnd,false);
+ m_pEditor->setModified(false);
+ updateRowColLabel();
+}
+
+void KviScriptEditorImplementation::getText(QString &txt)
+{
+ txt = m_pEditor->text();
+}
+void KviScriptEditorImplementation::setFindText(const QString &txt)
+{
+ m_pFindLineedit->setText(txt);
+ m_pEditor->slotFind();
+
+}
+
+void KviScriptEditorImplementation::setFindLineeditReadOnly(bool b)
+{
+ m_pFindLineedit->setReadOnly(b);
+
+}
+
+
+void KviScriptEditorImplementation::updateRowColLabel()
+{
+ int iRow,iCol;
+ m_pEditor->getCursorPosition(&iRow,&iCol);
+ if(iRow != m_lastCursorPos.x() || iCol != m_lastCursorPos.y())
+ {
+ m_lastCursorPos = QPoint(iRow,iCol);
+ QString tmp;
+ KviQString::sprintf(tmp,__tr2qs_ctx("Row: %d Col: %d","editor"),iRow,iCol);
+ m_pRowColLabel->setText(tmp);
+ }
+}
+
+QPoint KviScriptEditorImplementation::getCursor()
+{
+ return m_lastCursorPos;
+}
+void KviScriptEditorImplementation::setCursorPosition(QPoint pos)
+{
+ m_pEditor->setCursorPosition(pos.x(),pos.y());
+ m_pEditor->setFocus();
+ m_pEditor->ensureCursorVisible();
+ QString tmp;
+ KviQString::sprintf(tmp,__tr2qs_ctx("Row: %d Col: %d","editor"),pos.x(),pos.y());
+ m_pRowColLabel->setText(tmp);
+
+ m_lastCursorPos=pos;
+}
+
+void KviScriptEditorImplementation::loadFromFile()
+{
+ QString fName;
+ if(KviFileDialog::askForOpenFileName(fName,
+ __tr2qs_ctx("Load Script File - KVIrc","editor"),
+ QString::null,
+ QString::null,false,true))
+ {
+ QString buffer;
+ if(KviFileUtils::loadFile(fName,buffer))
+ {
+ m_pEditor->setText(buffer);
+ m_pEditor->moveCursor(KviTalTextEdit::MoveEnd,false);
+ updateRowColLabel();
+ } else {
+ QString tmp;
+ QMessageBox::warning(this,
+ __tr2qs_ctx("Open Failed - KVIrc","editor"),
+ KviQString::sprintf(tmp,__tr2qs_ctx("Can't open the file %s for reading.","editor"),&fName));
+ }
+ }
+}
+
+void KviScriptEditorImplementation::configureColors()
+{
+ KviScriptEditorWidgetColorOptions dlg(this);
+ if(dlg.exec() == QDialog::Accepted)
+
+ {
+ m_pEditor->updateOptions();
+ saveOptions();
+ }
+}
+KviScriptEditorReplaceDialog::KviScriptEditorReplaceDialog( QWidget* parent, const char* name)
+ : QDialog( parent)
+{
+ m_pParent=parent;
+ emit initFind();
+ setPaletteForegroundColor( QColor( 0, 0, 0 ) );
+ setPaletteBackgroundColor( QColor( 236, 233, 216 ) );
+ QGridLayout *layout = new QGridLayout( this, 1, 1, 11, 6, "replace layout");
+
+ m_pFindlineedit = new QLineEdit( this, "findlineedit" );
+#ifndef COMPILE_USE_QT4
+ m_pFindlineedit->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)7, (QSizePolicy::SizeType)0, 0, 0, m_pFindlineedit->sizePolicy().hasHeightForWidth() ) );
+ m_pFindlineedit->setFrameShape( QLineEdit::LineEditPanel );
+ m_pFindlineedit->setFrameShadow( QLineEdit::Sunken );
+#endif
+
+ layout->addMultiCellWidget( m_pFindlineedit, 2, 2, 1, 2 );
+
+ m_pReplacelineedit = new QLineEdit( this, "replacelineedit" );
+#ifndef COMPILE_USE_QT4
+ m_pReplacelineedit->setFrameShape( QLineEdit::LineEditPanel );
+ m_pReplacelineedit->setFrameShadow( QLineEdit::Sunken );
+#endif
+ layout->addMultiCellWidget( m_pReplacelineedit, 3, 3, 1, 2 );
+
+ m_pFindlineedit->setFocus();
+
+ QLabel *findlabel = new QLabel( this, "findlabel" );
+ findlabel->setText(tr("Word to Find"));
+#ifndef COMPILE_USE_QT4
+ findlabel->setAutoResize(true);
+#endif
+
+ layout->addWidget( findlabel, 2, 0 );
+
+ QLabel *replacelabel = new QLabel( this, "replacelabel" );
+ replacelabel->setText(tr("Replace with"));
+#ifndef COMPILE_USE_QT4
+ replacelabel->setAutoResize(true);
+#endif
+ layout->addWidget( replacelabel, 3, 0 );
+
+ QPushButton *cancelbutton = new QPushButton( this, "cancelButton" );
+ cancelbutton->setText(tr("&Cancel"));
+ layout->addWidget( cancelbutton, 5, 2 );
+
+ replacebutton = new QPushButton( this, "replacebutton" );
+ replacebutton->setText(tr("&Replace"));
+ replacebutton->setEnabled( FALSE );
+ layout->addWidget( replacebutton, 5, 0 );
+
+ checkReplaceAll = new KviStyledCheckBox( this, "replaceAll" );
+ checkReplaceAll->setText(tr("&Replace in all Aliases"));
+ layout->addWidget( checkReplaceAll, 4, 0 );
+
+ findNext = new QPushButton(this, "findNext(WIP)" );
+ findNext->setText(tr("&Findnext"));
+ layout->addWidget( findNext, 2, 3 );
+ findNext->setEnabled(false);
+
+ replace = new QPushButton(this, "replace" );
+ replace->setText(tr("&Replace(WIP)"));
+ layout->addWidget( replace, 3, 3 );
+ replace->setEnabled(false);
+
+#ifndef COMPILE_USE_QT4
+ clearWState( WState_Polished );
+ setTabOrder(m_pFindlineedit,m_pReplacelineedit);
+#endif
+ // signals and slots connections
+ connect( replacebutton, SIGNAL( clicked() ), this, SLOT( slotReplace() ) );
+ connect( findNext, SIGNAL( clicked() ),this,SLOT( slotNextFind()));
+ connect( cancelbutton, SIGNAL( clicked() ), this, SLOT( reject() ) );
+ connect( m_pFindlineedit, SIGNAL( textChanged(const QString &)), this, SLOT( textChanged(const QString &)));
+
+}
+
+
+KviScriptEditorReplaceDialog::~KviScriptEditorReplaceDialog()
+{
+}
+
+void KviScriptEditorReplaceDialog::textChanged(const QString &txt)
+{
+ if (!txt.isEmpty()) replacebutton->setEnabled(TRUE);
+ else replacebutton->setEnabled(FALSE);
+
+}
+void KviScriptEditorReplaceDialog::slotReplace()
+{
+ QString txt=((KviScriptEditorWidget *)m_pParent)->text();
+ if (checkReplaceAll->isChecked()) emit replaceAll(m_pFindlineedit->text(),m_pReplacelineedit->text());
+ txt.replace(m_pFindlineedit->text(),m_pReplacelineedit->text(),false);
+ ((KviScriptEditorWidget *)m_pParent)->setText(txt);
+ ((KviScriptEditorWidget *)m_pParent)->setModified(true);
+ m_pFindlineedit->setText("");
+ m_pReplacelineedit->setText("");
+ setTabOrder(m_pFindlineedit,m_pReplacelineedit);
+}
+
+
+void KviScriptEditorReplaceDialog::slotNextFind()
+{
+ emit nextFind(m_pFindlineedit->text());
+}
diff --git a/src/modules/editor/scripteditor.h b/src/modules/editor/scripteditor.h
new file mode 100644
index 00000000..d7bc435f
--- /dev/null
+++ b/src/modules/editor/scripteditor.h
@@ -0,0 +1,200 @@
+#ifndef _SCRIPTEDITOR_H_
+#define _SCRIPTEDITOR_H_
+
+//=============================================================================
+//
+// File : scripteditor.h
+// Created on Sun Mar 28 1999 16:11:48 CEST by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 1999-2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_scripteditor.h"
+
+#include <qlabel.h>
+#include <kvi_tal_textedit.h>
+#include <qsyntaxhighlighter.h>
+#include <qdialog.h>
+#include <qcheckbox.h>
+#include "kvi_tal_listbox.h"
+#include <qevent.h>
+#include "kvi_qcstring.h"
+
+#include "kvi_tal_popupmenu.h"
+
+#include "kvi_pointerlist.h"
+#include "kvi_selectors.h"
+typedef KviPointerList<int> ColumnList;
+
+class KviCompletionBox: public KviTalListBox
+{
+ Q_OBJECT
+public:
+ KviCompletionBox(QWidget * parent);
+ ~KviCompletionBox(){};
+
+ void updateContents(QString word);
+protected:
+ virtual void keyPressEvent(QKeyEvent * e);
+};
+
+class KviScriptEditorWidget : public KviTalTextEdit
+{
+ Q_OBJECT
+ Q_PROPERTY(bool contextSensitiveHelp READ contextSensitiveHelp)
+public:
+ KviScriptEditorWidget(QWidget * pParent);
+ virtual ~KviScriptEditorWidget();
+public:
+ void updateOptions();
+ void find1();
+ QString m_szFind;
+ KviCompletionBox *completelistbox;
+ void completition(bool bCanComplete = 1);
+ void getWordBeforeCursor(QString &buffer,int index,bool *);
+ void getWordOnCursor(QString &buffer,int index) const;
+ bool contextSensitiveHelp() const;
+public slots:
+ void slotFind();
+ void slotHelp();
+ void slotReplace();
+ void slotComplete(const QString &str);
+
+signals:
+ void keyPressed();
+protected:
+ virtual void keyPressEvent(QKeyEvent * e);
+ void contentsMousePressEvent(QMouseEvent *);
+#ifdef COMPILE_USE_QT4
+ Q3PopupMenu *createPopupMenu( const QPoint& pos );
+#else
+ QPopupMenu *createPopupMenu( const QPoint& pos );
+#endif
+ QWidget *m_pParent;
+ QString m_szHelp;
+
+};
+
+#ifdef COMPILE_USE_QT4
+ #include <q3syntaxhighlighter.h>
+ #define QSyntaxHighlighter Q3SyntaxHighlighter
+#else
+ #include <qobjectlist.h>
+#endif
+class KviScriptSyntaxHighlighter : public QSyntaxHighlighter
+{
+public:
+ KviScriptSyntaxHighlighter(KviScriptEditorWidget * pWidget);
+ virtual ~KviScriptSyntaxHighlighter();
+public:
+ virtual int highlightParagraph(const QString & text,int endStateOfLastPara);
+};
+
+class KviScriptEditorWidgetColorOptions : public QDialog
+{
+ Q_OBJECT
+public:
+ KviScriptEditorWidgetColorOptions(QWidget * pParent);
+ ~KviScriptEditorWidgetColorOptions();
+private:
+ KviPointerList<KviSelectorInterface> * m_pSelectorInterfaceList;
+protected:
+ KviColorSelector * addColorSelector(QWidget * pParent,const QString & txt,QColor * pOption,bool bEnabled);
+
+protected slots:
+ void okClicked();
+};
+
+class QTimer;
+
+class KviScriptEditorImplementation : public KviScriptEditor
+{
+ Q_OBJECT
+public:
+ KviScriptEditorImplementation(QWidget * par);
+ virtual ~KviScriptEditorImplementation();
+protected:
+ KviScriptEditorWidget * m_pEditor;
+ QLabel * m_pRowColLabel;
+ QPoint m_lastCursorPos;
+public:
+ virtual void setText(const QString &txt);
+ virtual void getText(QString &txt);
+ virtual void setText(const KviQCString &txt);
+ virtual void getText(KviQCString &txt);
+ virtual void setFindText(const QString & text);
+ virtual void setEnabled(bool bEnabled);
+ virtual void setFocus();
+ virtual bool isModified();
+ void setFindLineeditReadOnly(bool b);
+ void setCursorPosition(QPoint);
+ QPoint getCursor();
+ QLineEdit *m_pFindlineedit;
+ QLineEdit * getFindlineedit();
+protected:
+ virtual void focusInEvent(QFocusEvent *e);
+ void loadOptions();
+ void saveOptions();
+protected slots:
+ void saveToFile();
+ void loadFromFile();
+ void configureColors();
+ void updateRowColLabel();
+ void slotFind();
+ void slotReplaceAll(const QString &,const QString &);
+ void slotInitFind();
+ void slotNextFind(const QString &);
+signals:
+ void find( const QString &);
+ void replaceAll( const QString &, const QString &);
+ void initFind();
+ void nextFind(const QString &);
+};
+
+class KviScriptEditorReplaceDialog: public QDialog
+{
+ Q_OBJECT
+public:
+ KviScriptEditorReplaceDialog( QWidget* parent = 0, const char* name = 0);
+ ~KviScriptEditorReplaceDialog();
+ QLineEdit *m_pFindlineedit;
+ QLineEdit *m_pReplacelineedit;
+protected:
+ QLabel *findlabel;
+ QLabel *replacelabel;
+ QPushButton *replacebutton;
+ QPushButton *replace;
+ QPushButton *findNext;
+
+// QPushButton *cancelbutton;
+ KviStyledCheckBox *checkReplaceAll;
+ QWidget *m_pParent;
+protected slots:
+ void textChanged(const QString &);
+ void slotReplace();
+ void slotNextFind();
+signals:
+ void replaceAll( const QString &,const QString &);
+ void initFind();
+ void nextFind(const QString &);
+
+};
+
+
+#endif //!_SCRIPTEDITOR_H_
diff --git a/src/modules/eventeditor/Makefile.am b/src/modules/eventeditor/Makefile.am
new file mode 100644
index 00000000..ceb7541a
--- /dev/null
+++ b/src/modules/eventeditor/Makefile.am
@@ -0,0 +1,21 @@
+###############################################################################
+# KVirc IRC client Makeeventeditor - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkvieventeditor.la
+
+libkvieventeditor_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkvieventeditor_la_SOURCES = libkvieventeditor.cpp eventeditor.cpp
+nodist_libkvieventeditor_la_SOURCES = moc_eventeditor.cpp
+
+noinst_HEADERS = eventeditor.h
+libkvieventeditor_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+# noinst_HEADERS=
+
+moc_eventeditor.cpp: eventeditor.h
+ $(SS_QT_MOC) $< -o $@
diff --git a/src/modules/eventeditor/eventeditor.cpp b/src/modules/eventeditor/eventeditor.cpp
new file mode 100644
index 00000000..bedeca5f
--- /dev/null
+++ b/src/modules/eventeditor/eventeditor.cpp
@@ -0,0 +1,536 @@
+//
+// File : eventeditor.cpp
+// Creation date : Mon Dec 23 2002 20:28:18 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the linkss of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) 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.
+//
+#include "eventeditor.h"
+
+#include "kvi_iconmanager.h"
+#include "kvi_options.h"
+#include "kvi_locale.h"
+#include "kvi_imagedialog.h"
+#include "kvi_config.h"
+#include "kvi_filedialog.h"
+#include "kvi_fileutils.h"
+#include "kvi_scripteditor.h"
+#include "kvi_debug.h"
+//#include "kvi_event.h"
+#include "kvi_app.h"
+#include "kvi_cmdformatter.h"
+//#include "kvi_eventhandler.h"
+#include "kvi_qstring.h"
+#include "kvi_filedialog.h"
+
+#include "kvi_kvs_eventmanager.h"
+
+#include <qmessagebox.h>
+
+#include <qsplitter.h>
+#include <qlayout.h>
+#include "kvi_tal_vbox.h"
+#include "kvi_tal_popupmenu.h"
+#include <qtooltip.h>
+#include <qpushbutton.h>
+#include <qevent.h>
+
+extern KviEventEditorWindow * g_pEventEditorWindow;
+
+
+
+const QPixmap * KviEventListViewItem::pixmap(int col) const
+{
+ return g_pIconManager->getSmallIcon(firstChild() ? KVI_SMALLICON_EVENT : KVI_SMALLICON_EVENTNOHANDLERS);
+}
+
+const QPixmap * KviEventHandlerListViewItem::pixmap(int col) const
+{
+ return g_pIconManager->getSmallIcon(m_bEnabled ? KVI_SMALLICON_HANDLER : KVI_SMALLICON_HANDLERDISABLED);
+}
+
+
+
+KviEventEditor::KviEventEditor(QWidget * par)
+: QWidget(par,"event_editor")
+{
+ QGridLayout * l = new QGridLayout(this,1,1,2,2);
+
+ QSplitter * spl = new QSplitter(Qt::Horizontal,this);
+ spl->setOpaqueResize(false);
+
+ l->addWidget(spl,0,0);
+
+ KviTalVBox * boxi = new KviTalVBox(spl);
+ m_pListView = new KviTalListView(boxi);
+ m_pListView->addColumn(__tr2qs("Event"));
+ m_pListView->setMultiSelection(false);
+ m_pListView->setShowSortIndicator(true);
+ m_pListView->setRootIsDecorated(true);
+
+ QPushButton * pb = new QPushButton(__tr2qs("&Export All To..."),boxi);
+ connect(pb,SIGNAL(clicked()),this,SLOT(exportAllEvents()));
+
+ KviTalVBox * box = new KviTalVBox(spl);
+ m_pNameEditor = new QLineEdit(box);
+ QToolTip::add(m_pNameEditor,__tr2qs("Edit the event handler name."));
+ m_pEditor = KviScriptEditor::createInstance(box);
+ m_pEditor->setFocus();
+
+ m_bOneTimeSetupDone = false;
+ m_pLastEditedItem = 0;
+}
+
+KviEventEditor::~KviEventEditor()
+{
+ KviScriptEditor::destroyInstance(m_pEditor);
+}
+
+void KviEventEditor::oneTimeSetup()
+{
+ if(m_bOneTimeSetupDone)return;
+ m_bOneTimeSetupDone = true;
+
+ KviEventListViewItem * it;
+ KviEventHandlerListViewItem * ch;
+
+ for(unsigned int i = 0;i < KVI_KVS_NUM_APP_EVENTS;i++)
+ {
+ KviKvsEvent * e = KviKvsEventManager::instance()->appEvent(i);
+ it = new KviEventListViewItem(m_pListView,i,e->name(),e->parameterDescription());
+ if(KviPointerList<KviKvsEventHandler> * l = e->handlers())
+ {
+ for(KviKvsEventHandler * s = l->first();s;s = l->next())
+ {
+ if(s->type() == KviKvsEventHandler::Script)
+ {
+ ch = new KviEventHandlerListViewItem(it,((KviKvsScriptEventHandler *)s)->name(),
+ ((KviKvsScriptEventHandler *)s)->code(),((KviKvsScriptEventHandler *)s)->isEnabled());
+ }
+ }
+ it->setOpen(true);
+ }
+ }
+
+
+ m_pContextPopup = new KviTalPopupMenu(this);
+
+ connect(m_pListView,SIGNAL(selectionChanged(KviTalListViewItem *)),this,SLOT(selectionChanged(KviTalListViewItem *)));
+ connect(m_pListView,SIGNAL(rightButtonPressed(KviTalListViewItem *,const QPoint &,int)),
+ this,SLOT(itemPressed(KviTalListViewItem *,const QPoint &,int)));
+}
+
+void KviEventEditor::itemPressed(KviTalListViewItem *it,const QPoint &pnt,int col)
+{
+ __range_valid(m_bOneTimeSetupDone);
+
+ if(it)
+ {
+ m_pContextPopup->clear();
+ if(it->parent())
+ {
+ QString tmp;
+ if(!(((KviEventHandlerListViewItem *)it)->m_bEnabled))
+ m_pContextPopup->insertItem(
+ *(g_pIconManager->getSmallIcon(KVI_SMALLICON_HANDLER)),
+ __tr2qs("&Enable Handler"),this,SLOT(toggleCurrentHandlerEnabled()));
+ else
+ m_pContextPopup->insertItem(
+ *(g_pIconManager->getSmallIcon(KVI_SMALLICON_HANDLERDISABLED)),
+ __tr2qs("&Disable Handler"),this,SLOT(toggleCurrentHandlerEnabled()));
+
+ //m_pContextPopup->setItemChecked(id,((KviEventHandlerListViewItem *)it)->m_bEnabled);
+
+ m_pContextPopup->insertItem(
+ *(g_pIconManager->getSmallIcon(KVI_SMALLICON_QUIT)),
+ __tr2qs("Re&move Handler"),
+ this,SLOT(removeCurrentHandler()));
+ m_pContextPopup->insertItem(
+ *(g_pIconManager->getSmallIcon(KVI_SMALLICON_FOLDER)),
+ __tr2qs("&Export Handler To..."),
+ this,SLOT(exportCurrentHandler()));
+ } else {
+ m_pContextPopup->insertItem(
+ *(g_pIconManager->getSmallIcon(KVI_SMALLICON_HANDLER)),
+ __tr2qs("&New Handler"),
+ this,SLOT(addHandlerForCurrentEvent()));
+ }
+
+ m_pContextPopup->popup(pnt);
+ }
+}
+
+void KviEventEditor::getUniqueHandlerName(KviEventListViewItem *it,QString &buffer)
+{
+ __range_valid(m_bOneTimeSetupDone);
+
+ QString newName = buffer;
+ if(newName.isEmpty())newName = __tr2qs("unnamed");
+
+ bool bFound = true;
+ int idx = 1;
+
+ while(bFound)
+ {
+ bFound = false;
+
+ for(KviEventHandlerListViewItem * ch = (KviEventHandlerListViewItem *)(it->firstChild());ch;ch = (KviEventHandlerListViewItem *)ch->nextSibling())
+ {
+ if(KviQString::equalCI(newName,ch->m_szName))
+ {
+ bFound = true;
+ KviQString::sprintf(newName,"%Q_%d",&buffer,idx);
+ idx++;
+ break;
+ }
+ }
+ }
+
+ buffer = newName;
+}
+
+void KviEventEditor::addHandlerForCurrentEvent()
+{
+ __range_valid(m_pOneTimeSetupDone);
+
+ KviTalListViewItem * it = m_pListView->selectedItem();
+ if(it)
+ {
+ if(it->parent() == 0)
+ {
+ QString buffer = __tr2qs("default");
+ getUniqueHandlerName((KviEventListViewItem *)it,buffer);
+ KviTalListViewItem * ch = new KviEventHandlerListViewItem(it,buffer,"",true);
+ it->setOpen(true);
+ m_pListView->setSelected(ch,true);
+ }
+ }
+}
+
+void KviEventEditor::removeCurrentHandler()
+{
+ __range_valid(m_pOneTimeSetupDone);
+ if(m_pLastEditedItem)
+ {
+ KviTalListViewItem * it = m_pLastEditedItem;
+ m_pLastEditedItem = 0;
+ delete it;
+ m_pEditor->setEnabled(false);
+ m_pNameEditor->setEnabled(false);
+ }
+}
+
+void KviEventEditor::toggleCurrentHandlerEnabled()
+{
+ __range_valid(m_pOneTimeSetupDone);
+ if(m_pLastEditedItem)
+ {
+ m_pLastEditedItem->m_bEnabled = !(m_pLastEditedItem->m_bEnabled);
+ m_pListView->repaintItem(m_pLastEditedItem);
+ selectionChanged(m_pLastEditedItem);
+ }
+}
+
+void KviEventEditor::commit()
+{
+ if(!m_bOneTimeSetupDone)return; // nothing to commit
+
+ saveLastEditedItem();
+ KviKvsEventManager::instance()->removeAllScriptAppHandlers();
+ for(KviTalListViewItem * it = m_pListView->firstChild();it;it = it->nextSibling())
+ {
+ if(it->firstChild())
+ {
+ QString szContext;
+
+ for(KviTalListViewItem * ch = it->firstChild();ch;ch = ch->nextSibling())
+ {
+ KviQString::sprintf(szContext,"%Q::%Q",&(((KviEventListViewItem *)it)->m_szName),&(((KviEventHandlerListViewItem *)ch)->m_szName));
+
+ KviKvsScriptEventHandler * s = KviKvsScriptEventHandler::createInstance( // msvc workaround
+ ((KviEventHandlerListViewItem *)ch)->m_szName,
+ szContext,
+ ((KviEventHandlerListViewItem *)ch)->m_szBuffer,
+ ((KviEventHandlerListViewItem *)ch)->m_bEnabled
+ );
+
+ KviKvsEventManager::instance()->addAppHandler(((KviEventListViewItem *)it)->m_uEventIdx,s);
+ }
+ }
+ }
+
+ g_pApp->saveAppEvents();
+}
+
+void KviEventEditor::saveLastEditedItem()
+{
+ __range_valid(m_bOneTimeSetupDone);
+ if(!m_pLastEditedItem)return;
+
+ QString buffer = m_pNameEditor->text();
+ if(!KviQString::equalCI(buffer,m_pLastEditedItem->m_szName))
+ {
+ getUniqueHandlerName((KviEventListViewItem *)(m_pLastEditedItem->parent()),buffer);
+ }
+
+ m_pLastEditedItem->m_szName = buffer;
+ QString tmp;
+ m_pEditor->getText(tmp);
+
+ m_pLastEditedItem->m_szBuffer = tmp;
+}
+
+void KviEventEditor::selectionChanged(KviTalListViewItem * it)
+{
+ __range_valid(m_bOneTimeSetupDone);
+ saveLastEditedItem();
+ if(it->parent())
+ {
+ m_pLastEditedItem = (KviEventHandlerListViewItem *)it;
+ m_pNameEditor->setEnabled(true);
+ m_pNameEditor->setText(it->text(0));
+ m_pEditor->setEnabled(true);
+ m_pEditor->setText(((KviEventHandlerListViewItem *)it)->m_szBuffer);
+ } else {
+ m_pLastEditedItem = 0;
+ m_pNameEditor->setEnabled(false);
+ m_pNameEditor->setText("");
+ m_pEditor->setEnabled(false);
+ QString parms = ((KviEventListViewItem *)it)->m_szParams;
+ if(parms.isEmpty())parms = __tr2qs("none");
+ KviCommandFormatter::indent(parms);
+ KviCommandFormatter::indent(parms);
+ QString tmp;
+ KviQString::sprintf(tmp,__tr2qs("\n\n Event:\n %s\n\n Parameters:\n%s"),
+ ((KviEventListViewItem *)it)->m_szName.utf8().data(),parms.utf8().data());
+ m_pEditor->setText(tmp);
+ }
+}
+
+void KviEventEditor::showEvent(QShowEvent *e)
+{
+ oneTimeSetup();
+ QWidget::showEvent(e);
+}
+
+
+void KviEventEditor::getExportEventBuffer(QString &buffer,KviEventHandlerListViewItem * it)
+{
+ if(!it->parent())return;
+
+ QString szBuf = it->m_szBuffer;
+
+ KviCommandFormatter::blockFromBuffer(szBuf);
+
+ buffer = "event(";
+ buffer += ((KviEventListViewItem *)(it->parent()))->m_szName;
+ buffer += ",";
+ buffer += it->m_szName;
+ buffer += ")\n";
+ buffer += szBuf;
+ buffer += "\n";
+
+ if(!it->m_bEnabled)
+ {
+ buffer += "\n";
+ buffer += "eventctl -d ";
+ buffer += ((KviEventListViewItem *)(it->parent()))->m_szName;
+ buffer += " ";
+ buffer += it->m_szName;
+ }
+}
+
+void KviEventEditor::exportCurrentHandler()
+{
+ if(!m_pLastEditedItem)return;
+ saveLastEditedItem();
+ if(!m_pLastEditedItem)return;
+
+ QString szName = QDir::homeDirPath();
+ if(!szName.endsWith(QString(KVI_PATH_SEPARATOR)))szName += KVI_PATH_SEPARATOR;
+ szName += ((KviEventListViewItem *)(m_pLastEditedItem->parent()))->m_szName;
+ szName += ".";
+ szName += m_pLastEditedItem->m_szName;
+ szName += ".kvs";
+
+ QString szFile;
+
+ if(!KviFileDialog::askForSaveFileName(szFile,__tr2qs("Choose a Filename - KVIrc"),szName,"*.kvs",true,true,true))return;
+
+ QString szOut;
+ getExportEventBuffer(szOut,m_pLastEditedItem);
+
+ if(!KviFileUtils::writeFile(szFile,szOut))
+ {
+ QMessageBox::warning(this,__tr2qs("Write Failed - KVIrc"),__tr2qs("Unable to write to the event file."),__tr2qs("&OK"));
+ }
+}
+
+void KviEventEditor::exportAllEvents()
+{
+ saveLastEditedItem();
+
+ KviEventListViewItem * it = (KviEventListViewItem *)m_pListView->firstChild();
+
+ QString out;
+
+ while(it)
+ {
+ KviEventHandlerListViewItem * item = (KviEventHandlerListViewItem *)it->firstChild();
+ while(item)
+ {
+ QString tmp;
+ getExportEventBuffer(tmp,item);
+ out += tmp;
+ out += "\n";
+ item = (KviEventHandlerListViewItem *)item->nextSibling();
+ }
+ it = (KviEventListViewItem *)it->nextSibling();
+ }
+
+ QString szName = QDir::homeDirPath();
+ if(!szName.endsWith(QString(KVI_PATH_SEPARATOR)))szName += KVI_PATH_SEPARATOR;
+ szName += "events.kvs";
+
+ QString szFile;
+
+ if(!KviFileDialog::askForSaveFileName(szFile,__tr2qs("Choose a Filename - KVIrc"),szName,QString::null,true,true))return;
+
+ if(!KviFileUtils::writeFile(szFile,out))
+ {
+ QMessageBox::warning(this,__tr2qs("Write Failed - KVIrc"),__tr2qs("Unable to write to the events file."),__tr2qs("Ok"));
+ }
+}
+
+
+
+
+KviEventEditorWindow::KviEventEditorWindow(KviFrame * lpFrm)
+: KviWindow(KVI_WINDOW_TYPE_SCRIPTEDITOR,lpFrm,"eventeditor",0)
+{
+ g_pEventEditorWindow = this;
+
+ m_pEditor = new KviEventEditor(this);
+
+ m_pBase = new QWidget(this);
+ QGridLayout * g = new QGridLayout(m_pBase,1,4,4,4);
+
+ QPushButton * btn = new QPushButton(__tr2qs("&OK"),m_pBase);
+ connect(btn,SIGNAL(clicked()),this,SLOT(okClicked()));
+ btn->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_ACCEPT)));
+ g->addWidget(btn,0,1);
+
+ btn = new QPushButton(__tr2qs("&Apply"),m_pBase);
+ connect(btn,SIGNAL(clicked()),this,SLOT(applyClicked()));
+ btn->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_ACCEPT)));
+ g->addWidget(btn,0,2);
+
+ btn = new QPushButton(__tr2qs("Cancel"),m_pBase);
+ connect(btn,SIGNAL(clicked()),this,SLOT(cancelClicked()));
+ btn->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_DISCARD)));
+ g->addWidget(btn,0,3);
+
+ g->setColStretch(0,1);
+}
+
+KviEventEditorWindow::~KviEventEditorWindow()
+{
+ g_pEventEditorWindow = 0;
+}
+
+void KviEventEditorWindow::okClicked()
+{
+ m_pEditor->commit();
+ close();
+}
+
+void KviEventEditorWindow::applyClicked()
+{
+ m_pEditor->commit();
+}
+
+void KviEventEditorWindow::cancelClicked()
+{
+ close();
+}
+
+
+QPixmap * KviEventEditorWindow::myIconPtr()
+{
+ return g_pIconManager->getSmallIcon(KVI_SMALLICON_EVENT);
+}
+
+void KviEventEditorWindow::resizeEvent(QResizeEvent *e)
+{
+ int hght = m_pBase->sizeHint().height();
+ m_pEditor->setGeometry(0,0,width(),height()- hght);
+ m_pBase->setGeometry(0,height() - hght,width(),hght);
+}
+
+void KviEventEditorWindow::fillCaptionBuffers()
+{
+ m_szPlainTextCaption = __tr2qs("Event Editor");
+
+ static QString p1("<nobr><font color=\"");
+ static QString p2("\"><b>");
+ static QString p3("</b></font></nobr>");
+
+ m_szHtmlActiveCaption = p1;
+ m_szHtmlActiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextActive).name();
+ m_szHtmlActiveCaption += p2;
+ m_szHtmlActiveCaption += m_szPlainTextCaption;
+ m_szHtmlActiveCaption += p3;
+
+ m_szHtmlInactiveCaption = p1;
+ m_szHtmlInactiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextInactive).name();
+ m_szHtmlInactiveCaption += p2;
+ m_szHtmlInactiveCaption += m_szPlainTextCaption;
+ m_szHtmlInactiveCaption += p3;
+}
+
+
+void KviEventEditorWindow::getConfigGroupName(KviStr &szName)
+{
+ szName = "eventeditor";
+}
+
+
+void KviEventEditorWindow::saveProperties(KviConfig *cfg)
+{
+/*
+#ifdef COMPILE_SCRIPTTOOLBAR
+ cfg->writeEntry("Sizes",m_pEditor->sizes());
+ cfg->writeEntry("LastEvent",m_pEditor->lastEditedEvent().ptr());
+ //debug("LAST EDITED=%s",m_pEditor->lastEditedEvent().ptr());
+#endif // COMPILE_SCRIPTTOOLBAR
+*/
+}
+
+void KviEventEditorWindow::loadProperties(KviConfig *cfg)
+{
+/*
+#ifdef COMPILE_SCRIPTTOOLBAR
+ QValueList<int> def;
+ def.append(20);
+ def.append(80);
+ m_pEditor->setSizes(cfg->readIntListEntry("Sizes",def));
+ KviStr tmp = cfg->readEntry("LastEvent","");
+ m_pEditor->editEvent(tmp);
+ //debug("LAST EDITED WAS %s",tmp.ptr());
+#endif // COMPILE_SCRIPTTOOLBAR
+*/
+}
diff --git a/src/modules/eventeditor/eventeditor.h b/src/modules/eventeditor/eventeditor.h
new file mode 100644
index 00000000..d94a07cc
--- /dev/null
+++ b/src/modules/eventeditor/eventeditor.h
@@ -0,0 +1,120 @@
+#ifndef _EVENTEDITOR_H_
+#define _EVENTEDITOR_H_
+//
+// File : eventeditor.h
+// Creation date : Mon Dec 23 2002 20:24:55 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the linkss of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) 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.
+//
+
+#include "kvi_window.h"
+#include "kvi_string.h"
+
+#include <qwidget.h>
+#include "kvi_tal_listview.h"
+#include <qlineedit.h>
+
+class KviScriptEditor;
+
+class KviEventListViewItem : public KviTalListViewItem
+{
+public:
+ unsigned int m_uEventIdx;
+ QString m_szName;
+ QString m_szParams;
+public:
+ KviEventListViewItem(KviTalListView * par,unsigned int uEvIdx,const QString &name,const QString &params)
+ : KviTalListViewItem(par), m_uEventIdx(uEvIdx), m_szName(name), m_szParams(params) {};
+ ~KviEventListViewItem() {};
+public:
+ virtual QString text(int col) const { return m_szName; };
+ virtual const QPixmap * pixmap(int col) const;
+};
+
+class KviEventHandlerListViewItem : public KviTalListViewItem
+{
+public:
+ QString m_szName;
+ QString m_szBuffer;
+ bool m_bEnabled;
+public:
+ KviEventHandlerListViewItem(KviTalListViewItem * par,const QString &name,const QString &buffer,bool bEnabled)
+ : KviTalListViewItem(par), m_szName(name) , m_szBuffer(buffer) , m_bEnabled(bEnabled) {};
+ ~KviEventHandlerListViewItem() {};
+public:
+ virtual QString text(int col) const { return m_szName; };
+ virtual const QPixmap * pixmap(int col) const;
+};
+
+class KviTalPopupMenu;
+
+class KviEventEditor : public QWidget
+{
+ Q_OBJECT
+public:
+ KviEventEditor(QWidget * par);
+ ~KviEventEditor();
+public:
+ KviScriptEditor * m_pEditor;
+ KviTalListView * m_pListView;
+ QLineEdit * m_pNameEditor;
+ KviTalPopupMenu * m_pContextPopup;
+ KviEventHandlerListViewItem * m_pLastEditedItem;
+ bool m_bOneTimeSetupDone;
+public:
+ void commit();
+ void saveLastEditedItem();
+ void getUniqueHandlerName(KviEventListViewItem *it,QString &buffer);
+ void getExportEventBuffer(QString &szBuffer,KviEventHandlerListViewItem * it);
+protected slots:
+ void selectionChanged(KviTalListViewItem *it);
+ void itemPressed(KviTalListViewItem *it,const QPoint &pnt,int col);
+ void toggleCurrentHandlerEnabled();
+ void removeCurrentHandler();
+ void addHandlerForCurrentEvent();
+ void exportAllEvents();
+ void exportCurrentHandler();
+protected:
+ void showEvent(QShowEvent *e);
+private:
+ void oneTimeSetup();
+};
+
+class KviEventEditorWindow : public KviWindow
+{
+ Q_OBJECT
+public:
+ KviEventEditorWindow(KviFrame * lpFrm);
+ ~KviEventEditorWindow();
+protected:
+ KviEventEditor * m_pEditor;
+ QWidget * m_pBase;
+protected:
+ virtual QPixmap * myIconPtr();
+ virtual void fillCaptionBuffers();
+ virtual void resizeEvent(QResizeEvent *e);
+ virtual void getConfigGroupName(KviStr &szName);
+ virtual void saveProperties(KviConfig *);
+ virtual void loadProperties(KviConfig *);
+protected slots:
+ void cancelClicked();
+ void okClicked();
+ void applyClicked();
+};
+
+#endif //_EVENTEDITOR_H_
diff --git a/src/modules/eventeditor/libkvieventeditor.cpp b/src/modules/eventeditor/libkvieventeditor.cpp
new file mode 100644
index 00000000..62111cad
--- /dev/null
+++ b/src/modules/eventeditor/libkvieventeditor.cpp
@@ -0,0 +1,88 @@
+//
+// File : libkvieventeditor.cpp
+// Creation date : Mon 23 Dec 2002 20:23:59 2002 GMT by Szymon Stefanek
+//
+// This toolbar is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_module.h"
+#include "kvi_locale.h"
+#include "kvi_frame.h"
+
+#include "eventeditor.h"
+
+KviEventEditorWindow * g_pEventEditorWindow = 0;
+
+
+/*
+ @doc: eventeditor.open
+ @type:
+ command
+ @title:
+ eventeditor.open
+ @short:
+ Shows the event editor
+ @syntax:
+ toolbareditor.open
+ @description:
+ Opens the script event editor dialog.
+*/
+
+static bool eventeditor_kvs_cmd_open(KviKvsModuleCommandCall * c)
+{
+ if(!g_pEventEditorWindow)
+ {
+ g_pEventEditorWindow = new KviEventEditorWindow(c->window()->frame());
+ c->window()->frame()->addWindow(g_pEventEditorWindow);
+ }
+
+ g_pEventEditorWindow->setFocus();
+ return true;
+}
+
+static bool eventeditor_module_init(KviModule * m)
+{
+
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"open",eventeditor_kvs_cmd_open);
+
+ g_pEventEditorWindow = 0;
+ return true;
+}
+
+static bool eventeditor_module_can_unload(KviModule * m)
+{
+ return (g_pEventEditorWindow == 0);
+}
+
+static bool eventeditor_module_cleanup(KviModule *m)
+{
+ if(g_pEventEditorWindow)delete g_pEventEditorWindow;
+ g_pEventEditorWindow = 0;
+ return true;
+}
+
+KVIRC_MODULE(
+ "EventEditor", // module name
+ "1.0.0", // module version
+ "Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot net)", // author & (C)
+ "Editor for the script events",
+ eventeditor_module_init,
+ eventeditor_module_can_unload,
+ 0,
+ eventeditor_module_cleanup
+)
diff --git a/src/modules/file/Makefile.am b/src/modules/file/Makefile.am
new file mode 100644
index 00000000..1545a63a
--- /dev/null
+++ b/src/modules/file/Makefile.am
@@ -0,0 +1,18 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkvifile.la
+
+libkvifile_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkvifile_la_SOURCES = libkvifile.cpp
+libkvifile_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+# noinst_HEADERS=
+
+%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
diff --git a/src/modules/file/libkvifile.cpp b/src/modules/file/libkvifile.cpp
new file mode 100644
index 00000000..8b8dd9ec
--- /dev/null
+++ b/src/modules/file/libkvifile.cpp
@@ -0,0 +1,1260 @@
+//=============================================================================
+//
+// File : libkvifile.cpp
+// Creation date : Fri Nov 9 03:27:59 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_module.h"
+#include "kvi_fileutils.h"
+#include "kvi_locale.h"
+#include "kvi_malloc.h"
+#include "kvi_app.h"
+#include "kvi_options.h"
+#include "kvi_qcstring.h"
+
+#include "kvi_kvs_arraycast.h"
+
+#include <qfileinfo.h>
+#include "kvi_file.h"
+#include <qdir.h>
+#include <qtextstream.h>
+
+/*
+ @doc: file.copy
+ @type:
+ command
+ @title:
+ file.copy
+ @keyterms:
+ copying files
+ @short:
+ Makes a copy of a file
+ @syntax:
+ file.copy [-o] <source:string> <destination:string>
+ @switches:
+ !sw: -o | --overwrite
+ Overwrites the file even if it already exists.
+ @description:
+ Makes a copy of the <source> file as <destination>.[br]
+ If the [-o] switch is used , the <destination> file is overwritten , if already exists.[br]
+ With no [-o] switch , this command does not overwrite files.[br]
+ The destination path must be already existing: if you want to ensure this, use [fnc]$file.mkdir[/fnc] first.[br]
+ The paths (<source> and <destination>) are adjusted according to the system that KVIrc
+ is running on so you don't have to bother about portability: it *should* be automatically
+ guaranteed. Just use UNIX style paths for them.[br]
+ @seealso:
+ [cmd]file.rename[/cmd], [fnc]$file.exists[/fnc]
+*/
+
+static bool file_kvs_cmd_copy(KviKvsModuleCommandCall * c)
+{
+ QString szSrc,szDst;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("source",KVS_PT_NONEMPTYSTRING,0,szSrc)
+ KVSM_PARAMETER("destination",KVS_PT_NONEMPTYSTRING,0,szDst)
+ KVSM_PARAMETERS_END(c)
+ KviFileUtils::adjustFilePath(szSrc);
+ KviFileUtils::adjustFilePath(szDst);
+ if(KviFileUtils::fileExists(szDst) && !c->switches()->find('o',"overwrite"))
+ {
+ c->warning(__tr2qs("Destinaion file exists: no copy made"));
+ return true;
+ }
+ if(!KviFileUtils::copyFile(szSrc,szDst))
+ {
+ c->warning(__tr2qs("Failed to copy from %Q to %Q"),&szSrc,&szDst);
+ c->warning(__tr2qs("Either the source doesn't exist or the destination can not be created"));
+ }
+ return true;
+}
+
+
+/*
+ @doc: file.addimagepath
+ @type:
+ command
+ @title:
+ file.addimagepath
+ @short:
+ Adds an image search path
+ @syntax:
+ file.addimagepath <path:string>
+ @description:
+ Adds <path> to the image search path list.[br]
+ KVIrc will look for images files (also) in that path (when a relative image file name is used).[br]
+ Yes, this function is a bit misplaced...
+ @seealso:
+ [cmd]file.delimagepath[/cmd]
+*/
+
+static bool file_kvs_cmd_addimagepath(KviKvsModuleCommandCall * c)
+{
+ QString szDst;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("path",KVS_PT_NONEMPTYSTRING,0,szDst)
+ KVSM_PARAMETERS_END(c)
+ KviFileUtils::adjustFilePath(szDst);
+
+ QStringList::Iterator it = KVI_OPTION_STRINGLIST(KviOption_stringlistImageSearchPaths).find(szDst);
+ if(it == KVI_OPTION_STRINGLIST(KviOption_stringlistImageSearchPaths).end())
+ KVI_OPTION_STRINGLIST(KviOption_stringlistImageSearchPaths).append(szDst);
+ return true;
+}
+
+
+
+/*
+ @doc: file.delimagepath
+ @type:
+ command
+ @title:
+ file.delimagepath
+ @short:
+ Removes an image search path
+ @syntax:
+ file.delimagepath <path:string>
+ @description:
+ Removes <path> from the image search path list.[br]
+ Yes, this function is a bit misplaced...
+ @seealso:
+ [cmd]file.addimagepath[/cmd]
+*/
+
+static bool file_kvs_cmd_delimagepath(KviKvsModuleCommandCall * c)
+{
+ QString szDst;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("path",KVS_PT_NONEMPTYSTRING,0,szDst)
+ KVSM_PARAMETERS_END(c)
+ KviFileUtils::adjustFilePath(szDst);
+
+ QStringList::Iterator it = KVI_OPTION_STRINGLIST(KviOption_stringlistImageSearchPaths).find(szDst);
+ if(it == KVI_OPTION_STRINGLIST(KviOption_stringlistImageSearchPaths).end())
+ KVI_OPTION_STRINGLIST(KviOption_stringlistImageSearchPaths).remove(szDst);
+ return true;
+}
+
+
+/*
+ @doc: file.write
+ @type:
+ command
+ @title:
+ file.write
+ @keyterms:
+ writing data to files
+ @short:
+ Writes an ascii data string to a file
+ @syntax:
+ file.write [-a] [-l] <filename:string> <data:string>
+ @switches:
+ !sw: -a | --append
+ If the file already exists, append the data instead of overwriting the original contents.
+ !sw: -l | --local-8-bit
+ Causes the file to be written in the local 8 bit character set instead of the
+ default utf8.
+ @description:
+ Writes <data> (which is an ASCII string) to the file <filename>.[br]
+ It does NOT append a traling LF character: if you want it you must explicitly specify it in the <data> parameter.[br]
+ -a causes the command to append the <data> to the file instead of overwriting the entire file.[br]
+ The path is adjusted according to the system that KVIrc
+ is running on so you don't have to bother about portability: it *should* be automatically
+ guaranteed. Just use UNIX style paths for them.[br]
+ The file is saved in utf8 unless the -l switch is specified (in that case the local 8 bit encoding is used).
+ Please note that uf8 is the only character set that preserves ALL the possible characters.
+ @seealso:
+ [cmd]file.rename[/cmd], [fnc]$file.exists[/fnc]
+*/
+
+static bool file_kvs_cmd_write(KviKvsModuleCommandCall * c)
+{
+ QString szFileName,szData;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("filename",KVS_PT_NONEMPTYSTRING,0,szFileName)
+ KVSM_PARAMETER("data",KVS_PT_NONEMPTYSTRING,0,szData)
+ KVSM_PARAMETERS_END(c)
+ KviFileUtils::adjustFilePath(szFileName);
+
+ bool bRet;
+ if(c->switches()->find('l',"local-8-bit"))
+ bRet = KviFileUtils::writeFileLocal8Bit(szFileName,szData,c->switches()->find('a',"append"));
+ else
+ bRet = KviFileUtils::writeFile(szFileName,szData,c->switches()->find('a',"append"));
+
+ if(!bRet)
+ c->warning(__tr2qs("Failed to write to file %Q: the destination couldn't be opened"),&szFileName);
+
+ return true;
+}
+
+
+/*
+ @doc: file.rename
+ @type:
+ command
+ @title:
+ file.rename
+ @keyterms:
+ copying files
+ @short:
+ Makes a copy of a file
+ @syntax:
+ file.rename <oldname:string> <newname:string>
+ @description:
+ Renames a file from <oldname> to <newname>.[br]
+ This command can also rename directories.[br]
+ If the <newname> file already exists , this command fails.[br]
+ The paths (<oldname> and <newname>) are adjusted according to the system that KVIrc
+ is running on so you don't have to bother about portability: it *should* be automatically
+ guaranteed.Just use UNIX style paths for them.[br]
+ @seealso:
+ [cmd]file.copy[/cmd], [fnc]$file.exists[/fnc]
+*/
+
+static bool file_kvs_cmd_rename(KviKvsModuleCommandCall * c)
+{
+ QString szOld,szNew;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("oldname",KVS_PT_NONEMPTYSTRING,0,szOld)
+ KVSM_PARAMETER("newname",KVS_PT_NONEMPTYSTRING,0,szNew)
+ KVSM_PARAMETERS_END(c)
+
+ KviFileUtils::adjustFilePath(szOld);
+ KviFileUtils::adjustFilePath(szNew);
+
+ if(KviFileUtils::fileExists(szNew))
+ c->warning(__tr2qs("Destination file exists: file not renamed"));
+
+ if(!KviFileUtils::renameFile(szOld,szNew))
+ c->warning(__tr2qs("Failed to rename %Q to %Q"),&szOld,&szNew);
+ return true;
+}
+
+
+/*
+ @doc: file.mkdir
+ @type:
+ command
+ @title:
+ file.mkdir
+ @keyterms:
+ creating directories
+ @short:
+ Creates a directory
+ @syntax:
+ file.mkdir <directory:string>
+ @description:
+ Creates the <directory>.[br]
+ The path is adjusted according to the system that KVIrc
+ is running on so you don't have to bother about portability: it *should* be automatically
+ guaranteed. Just use an UNIX style path.[br]
+ @seealso:
+ [fnc]$file.exists[/fnc]
+*/
+
+static bool file_kvs_cmd_mkdir(KviKvsModuleCommandCall * c)
+{
+ QString szDir;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("directory",KVS_PT_NONEMPTYSTRING,0,szDir)
+ KVSM_PARAMETERS_END(c)
+ KviFileUtils::adjustFilePath(szDir);
+ if(!KviFileUtils::makeDir(szDir))
+ c->warning(__tr2qs("Failed to make the directory %Q"),&szDir);
+ return true;
+}
+
+
+
+/*
+ @doc: file.remove
+ @type:
+ command
+ @title:
+ file.remove
+ @keyterms:
+ removing files
+ @short:
+ Removes a file
+ @syntax:
+ file.remove [-q] <name:string>
+ @switches:
+ !sw: -q | --quiet
+ Suppresses any warning message
+ @description:
+ Removes the file <name>.[br]
+ -q suppresses any warning message (about non existing file , for example).[br]
+ The path is adjusted according to the system that KVIrc
+ is running on so you don't have to bother about portability: it *should* be automatically
+ guaranteed. Just use an UNIX style path.[br]
+ @seealso:
+ [fnc]$file.exists[/fnc]
+*/
+
+static bool file_kvs_cmd_remove(KviKvsModuleCommandCall * c)
+{
+ QString szName;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("name",KVS_PT_NONEMPTYSTRING,0,szName)
+ KVSM_PARAMETERS_END(c)
+ KviFileUtils::adjustFilePath(szName);
+ if(!KviFileUtils::removeFile(szName))
+ {
+ if(!c->switches()->find('q',"quiet"))
+ c->warning(__tr2qs("Failed to remove the file %Q"),&szName);
+ }
+ return true;
+}
+
+
+/*
+ @doc: file.rmdir
+ @type:
+ command
+ @title:
+ file.rmdir
+ @keyterms:
+ removing directories
+ @short:
+ Removes a directory
+ @syntax:
+ file.rmdir [-q] <name:string>
+ @switches:
+ !sw: -q | --quiet
+ Suppresses any warning message
+ @description:
+ Removes the directory <name>.[br]
+ The directory must be empty for this command to success.[br]
+ -q suppresses any warning message (about non existing directory , for example).[br]
+ The path is adjusted according to the system that KVIrc
+ is running on so you don't have to bother about portability: it *should* be automatically
+ guaranteed. Just use an UNIX style path.[br]
+ @seealso:
+ [fnc]$file.exists[/fnc]
+ [cmd]file.remove[/cmd]
+*/
+
+static bool file_kvs_cmd_rmdir(KviKvsModuleCommandCall * c)
+{
+ QString szName;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("name",KVS_PT_NONEMPTYSTRING,0,szName)
+ KVSM_PARAMETERS_END(c)
+ KviFileUtils::adjustFilePath(szName);
+ if(!KviFileUtils::removeDir(szName))
+ {
+ if(!c->switches()->find('q',"quiet"))
+ c->warning(__tr2qs("Failed to remove the directory %Q"),&szName);
+ }
+ return true;
+}
+
+
+/*
+ @doc: file.exists
+ @type:
+ function
+ @title:
+ $file.exists
+ @short:
+ Check if a file exists
+ @syntax:
+ <boolean> $file.exists(<filename:string>)
+ @description:
+ Returns true if the file <filename> exists (this is also valid for directories!).[br]
+ The <filename> should be an unix-style file path and is adjusted according to the system that KVIrc is running on.[br]
+*/
+
+static bool file_kvs_fnc_exists(KviKvsModuleFunctionCall * c)
+{
+ QString szName;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("filename",KVS_PT_STRING,0,szName)
+ KVSM_PARAMETERS_END(c)
+ KviFileUtils::adjustFilePath(szName);
+ QFileInfo f(szName);
+ c->returnValue()->setBoolean(f.exists());
+ return true;
+}
+
+
+/*
+ @doc: file.type
+ @type:
+ function
+ @title:
+ $file.type
+ @short:
+ Checks the type of a path
+ @syntax:
+ <string> $file.type(<filename:string>)
+ @description:
+ Returns "f" if the <filename> points to a real file , "d" if <filename>
+ is the name of a directory or "l" if it is a symbolic link.[br]
+ The <filename> should be an unix-style file path and is adjusted according to the system that KVIrc is running on.[br]
+*/
+
+static bool file_kvs_fnc_type(KviKvsModuleFunctionCall * c)
+{
+ QString szName;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("filename",KVS_PT_NONEMPTYSTRING,0,szName)
+ KVSM_PARAMETERS_END(c)
+ KviFileUtils::adjustFilePath(szName);
+ QFileInfo f(szName);
+ if(f.isFile())c->returnValue()->setString("f");
+ else if(f.isDir())c->returnValue()->setString("d");
+ else if(f.isSymLink())c->returnValue()->setString("l");
+ return true;
+}
+
+
+/*
+ @doc: file.size
+ @type:
+ function
+ @title:
+ $file.size
+ @short:
+ Returns the size of a file
+ @syntax:
+ <integer> $file.size(<filename:string>)
+ @description:
+ Returns the size of the file pointed by <filename>.[br]
+ If the file does not exist , this function returns 0.[br]
+ The <filename> should be an unix-style file path and is adjusted according to the system that KVIrc is running on.[br]
+*/
+
+static bool file_kvs_fnc_size(KviKvsModuleFunctionCall * c)
+{
+ QString szName;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("filename",KVS_PT_NONEMPTYSTRING,0,szName)
+ KVSM_PARAMETERS_END(c)
+ KviFileUtils::adjustFilePath(szName);
+ QFileInfo f(szName);
+ c->returnValue()->setInteger(f.size());
+ return true;
+}
+/*
+ @doc: file.allSizese
+ @type:
+ function
+ @title:
+ $file.allSizes
+ @short:
+ Returns all sizes of a specified directory.
+ @syntax:
+ <array> $file.allSize(<dirname:string>)
+ @description:
+ Returns the size of every files of the specified directory as an array.[br]
+*/
+
+static bool file_kvs_fnc_allSizes(KviKvsModuleFunctionCall * c)
+{
+ QString szDir;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("directory",KVS_PT_NONEMPTYSTRING,0,szDir)
+ KVSM_PARAMETERS_END(c)
+ KviFileUtils::adjustFilePath(szDir);
+
+ QDir d(szDir);
+ if(!d.exists())
+ {
+ c->warning(__tr2qs("The specified directory does not exist '%Q'"),&szDir);
+ return true;
+ }
+
+ QStringList sl;
+ sl = d.entryList(QDir::Files);
+
+ KviKvsArray * a = new KviKvsArray();
+ QString szFile;
+ if(!sl.isEmpty())
+ {
+ int idx = 0;
+ for(QStringList::Iterator it = sl.begin();it != sl.end();++it)
+ {
+ szFile=szDir+(*it);
+ QFileInfo f(szFile);
+ a->set(idx,new KviKvsVariant((kvs_int_t)f.size()));
+ idx++;
+ }
+ }
+ c->returnValue()->setArray(a);
+
+
+
+
+ return true;
+}
+
+/*
+ @doc: file.fixpath
+ @type:
+ function
+ @title:
+ $file.fixpath
+ @short:
+ Converts file paths
+ @syntax:
+ <string> $file.fixpath(<filename:string>)
+ @description:
+ Returns the <filename> adjusted to match the current operating
+ system file path conventions.[br] This means that on UNIX , a path like "C:\folder\file.mp3"
+ will be returned as "/folder/file.mp3" and vice-versa.[br]
+ There is a minor problem with unix paths converted to the windows system: unix
+ has no "drive" concept thus the unix paths do not contain a drive. KVIrc will
+ always map the paths to the "default" C: drive.[br]
+ This is a good reason to avoid using absolute hard-coded paths :).[br]
+ Please note that you DON'T NEED to call this function on paths that you
+ pass to the other file.* functions: they are adjusted automatically.[br]
+ @seealso:
+ [fnc]$file.ps[/fnc]
+*/
+
+
+static bool file_kvs_fnc_fixpath(KviKvsModuleFunctionCall * c)
+{
+ QString szName;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("filename",KVS_PT_STRING,0,szName)
+ KVSM_PARAMETERS_END(c)
+ KviFileUtils::adjustFilePath(szName);
+ c->returnValue()->setString(szName);
+ return true;
+}
+
+
+/*
+ @doc: file.ps
+ @type:
+ function
+ @title:
+ $file.ps
+ @short:
+ Returns the file path separator
+ @syntax:
+ <string> $file.ps()
+ @description:
+ Returns the file path separator for the current operating system.[br]
+ On windows , '\' is returned , on UNIX , '/'.[br]
+ @seealso:
+ [fnc]$file.fixpath[/fnc]
+*/
+
+static bool file_kvs_fnc_ps(KviKvsModuleFunctionCall * c)
+{
+ c->returnValue()->setString(QString(QChar(KVI_PATH_SEPARATOR_CHAR)));
+ return true;
+}
+
+
+/*
+ @doc: file.ls
+ @type:
+ function
+ @title:
+ $file.ls
+ @short:
+ Returns a directory listing
+ @syntax:
+ <array> $file.ls(<directory:string>,[<flags:string>[,<namefilter:string>]])
+ @description:
+ Returns the listing of the specified directory as an array.[br]
+ The <directory> should be an unix-style file path and is adjusted according to the system that KVIrc is running on.[br]
+ <flags> may be a combination of the following characters:[br]
+ d: list directories[br]
+ f: list files[br]
+ l: list symbolic links[br]
+ r: list readable files[br]
+ w: list writeable files[br]
+ x: list executable files[br]
+ h: list hidden files[br]
+ s: list system files[br]
+ n: sort files by name[br]
+ t: sort files by file time[br]
+ b: sort files by file size[br]
+ z: put the directories first, then the files[br]
+ k: invert sort order[br]
+ i: case insensitive sort[br]
+ If <flags> is empty then a default of 'dfrwxhs'.[br]
+ If none of r,w,x is set then KVIrc sets all of them by default.[br]
+ If <namefilter> is passed then it is interpreted as a wildcard string
+ that must match the entries to be returned.[br]
+ @example:
+ [example]
+ %dir[]=$file.ls(/,"d")
+ [cmd]foreach[/cmd](%f,%dir[])echo %f
+ %dir[]=$file.ls(/usr/include,"f","t*.h");
+ [cmd]foreach[/cmd](%f,%dir[])echo %f
+ %dir[]=$file.ls($file.homedir,"dfr");
+ [cmd]foreach[/cmd](%f,%dir[])echo %f
+ [/example]
+*/
+
+static bool file_kvs_fnc_ls(KviKvsModuleFunctionCall * c)
+{
+ QString szDir,szFlags,szFilter;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("directory",KVS_PT_NONEMPTYSTRING,0,szDir)
+ KVSM_PARAMETER("flags",KVS_PT_STRING,KVS_PF_OPTIONAL,szFlags)
+ KVSM_PARAMETER("filter",KVS_PT_STRING,KVS_PF_OPTIONAL,szFilter)
+ KVSM_PARAMETERS_END(c)
+
+ KviFileUtils::adjustFilePath(szDir);
+
+ QDir d(szDir);
+ if(!d.exists())
+ {
+ c->warning(__tr2qs("The specified directory does not exist '%Q'"),&szDir);
+ return true;
+ }
+
+#ifdef COMPILE_USE_QT4
+ QFlags<QDir::Filter> iFlags = 0;
+#else
+ int iFlags = 0;
+#endif
+ if(szFlags.isEmpty())iFlags = QDir::Dirs | QDir::Files | QDir::NoSymLinks | QDir::Readable | QDir::Writable | QDir::Executable | QDir::Hidden | QDir::System;
+ else {
+ if(szFlags.find('d',false) != -1)iFlags |= QDir::Dirs;
+ if(szFlags.find('f',false) != -1)iFlags |= QDir::Files;
+ if(szFlags.find('l',false) == -1)iFlags |= QDir::NoSymLinks;
+ if(szFlags.find('r',false) != -1)iFlags |= QDir::Readable;
+ if(szFlags.find('w',false) != -1)iFlags |= QDir::Writable;
+ if(szFlags.find('x',false) != -1)iFlags |= QDir::Executable;
+ if(szFlags.find('h',false) != -1)iFlags |= QDir::Hidden;
+ if(szFlags.find('s',false) != -1)iFlags |= QDir::System;
+ }
+#ifdef COMPILE_USE_QT4
+ QFlags<QDir::SortFlag> iSort = 0;
+#else
+ int iSort = 0;
+#endif
+ if(szFlags.isEmpty())iSort = QDir::Unsorted;
+ else {
+ if(szFlags.find('n',false) != -1)iSort |= QDir::Name;
+ if(szFlags.find('t',false) != -1)iSort |= QDir::Time;
+ if(szFlags.find('b',false) != -1)iSort |= QDir::Size;
+ if(szFlags.find('z',false) != -1)iSort |= QDir::DirsFirst;
+ if(szFlags.find('k',false) != -1)iSort |= QDir::Reversed;
+ if(szFlags.find('i',false) != -1)iSort |= QDir::IgnoreCase;
+ }
+
+ QStringList sl;
+ if(!szFilter.isEmpty())sl = d.entryList(szFilter,iFlags,iSort);
+ else sl = d.entryList(iFlags,iSort);
+
+ KviKvsArray * a = new KviKvsArray();
+ if(!sl.isEmpty())
+ {
+ int idx = 0;
+ for(QStringList::Iterator it = sl.begin();it != sl.end();++it)
+ {
+ a->set(idx,new KviKvsVariant(*it));
+ idx++;
+ }
+ }
+ c->returnValue()->setArray(a);
+
+ return true;
+}
+
+/*
+ @doc: file.read
+ @type:
+ function
+ @title:
+ $file.read
+ @short:
+ Reads a text file
+ @syntax:
+ <string> $file.read(<filename:string>[,<size:integer>[,<flags:string>]])
+ @description:
+ Reads at most <size> bytes of the file pointed by <filename>.[br]
+ <size> is an upper limit but may be not reached if the real file is smaller.[br]
+ The data read is returned as a string , so if the file contains binary data,
+ expect strange results.[br] If <size> is not specified, then KVIrc tries to read
+ the whole file up to the 1 MB limit (so if you want to read a file that is
+ bigger thatn 1 MB then you MUST specify the <size>).[br]
+ WARNING: always check the file size before attemting to read a whole file...
+ reading a CDROM iso image may sit down your system :) (and will prolly crash while
+ allocating memory , before attempting to read anything)[br]
+ An empty string is returned if a serious error occures.[br]
+ The <filename> is adjusted according to the system that KVIrc is running on.[br]
+ Flags are actually limited to the single letter 'l'. By default the file
+ is decoded from the ut8 characters set. If 'l' is present the the file
+ is decoded by using the local 8 bit character set instead.
+ @examples:
+ [example]
+ echo $file.read(/proc/cpuinfo)
+ [/example]
+ @seealso:
+ [fnc]$file.readbinary[/fnc]
+*/
+
+static bool file_kvs_fnc_read(KviKvsModuleFunctionCall * c)
+{
+ QString szNameZ;
+ kvs_uint_t uSize;
+ QString szFlags;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("filename",KVS_PT_NONEMPTYSTRING,0,szNameZ)
+ KVSM_PARAMETER("size",KVS_PT_UINT,KVS_PF_OPTIONAL,uSize)
+ KVSM_PARAMETER("flags",KVS_PT_STRING,KVS_PF_OPTIONAL,szFlags)
+ KVSM_PARAMETERS_END(c)
+ KviFileUtils::adjustFilePath(szNameZ);
+
+ QFile f(szNameZ);
+ if(!f.open(IO_ReadOnly))
+ {
+ c->warning(__tr2qs("Can't open the file \"%Q\" for reading"),&szNameZ);
+ return true;
+ }
+
+ if(c->params()->count() < 2)uSize = 1024 * 1024; // 1 meg file default
+
+ char * buf = (char *)kvi_malloc(sizeof(char) * (uSize + 1));
+ unsigned int uReaded = 0;
+ unsigned int uRetries = 0;
+
+ while((uReaded < uSize) && (!f.atEnd()))
+ {
+ int readedNow = f.readBlock(buf + uReaded,uSize - uReaded);
+ if(readedNow < 0)
+ {
+ kvi_free(buf);
+ c->warning(__tr2qs("Read error for file %Q"),&szNameZ);
+ return true;
+ } else readedNow += uReaded;
+ uRetries ++;
+ if(uRetries > 1000)
+ {
+ // ops
+ kvi_free(buf);
+ c->warning(__tr2qs("Read error for file %Q (have been unable to read the requested size in 1000 retries)"),&szNameZ);
+ return true;
+ }
+ uReaded += readedNow;
+ }
+
+ buf[uReaded] = '\0';
+
+ if(szFlags.find('l',false) == -1)
+ c->returnValue()->setString(QString::fromUtf8(buf));
+ else
+ c->returnValue()->setString(QString::fromLocal8Bit(buf));
+
+ kvi_free(buf);
+
+ return true;
+}
+
+
+/*
+ @doc: file.readLines
+ @type:
+ function
+ @title:
+ $file.readLines
+ @short:
+ Reads lines of a text file
+ @syntax:
+ <array> $file.readLines(<filename:string>[,<startline:integer>,[<count:integer>[,<flags:string>]]])
+ @description:
+ Reads lines from the specified file and returns them as an array of strings.
+ The lines are assumed to be separated by linefeed characters (which are NOT returned).
+ Eventual terminating carriage return characters at the end of the line are stripped.
+ If <startline> is specified, then all the lines with indexes lower that <startline> are
+ discarded. If <count> is specified then a maximum of <count> lines is returned.
+ If <count> is not specified then all the lines until the end are read.
+ The <filename> is adjusted according to the system that KVIrc is running on.[br]
+ Flags are actually limited to the single letter 'l'. By default the file
+ is decoded from the ut8 characters set. If 'l' is present the the file
+ is decoded by using the local 8 bit character set instead.
+ WARNING: Always check the size of the file you're going to read: it is not
+ a good idea attempting to read a 700 MB binary file with this function since
+ it will probably sit down your system and exhaust your virtual memory.
+ @examples:
+ [example]
+ echo $file.readLines(/proc/cpuinfo)
+ [/example]
+ @seealso:
+ [fnc]$file.read[/fnc], [cmd]file.writeLines[/cmd], [fnc]$lf[/fnc]
+*/
+
+
+
+static bool file_kvs_fnc_readLines(KviKvsModuleFunctionCall * c)
+{
+ QString szName;
+ QString szFlags;
+ kvs_int_t iStartLine;
+ kvs_int_t iCount;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("filename",KVS_PT_NONEMPTYSTRING,0,szName)
+ KVSM_PARAMETER("startline",KVS_PT_INT,KVS_PF_OPTIONAL,iStartLine)
+ KVSM_PARAMETER("count",KVS_PT_INT,KVS_PF_OPTIONAL,iCount)
+ KVSM_PARAMETER("flags",KVS_PT_STRING,KVS_PF_OPTIONAL,szFlags)
+ KVSM_PARAMETERS_END(c)
+ KviFileUtils::adjustFilePath(szName);
+
+ QFile f(szName);
+ if(!f.open(IO_ReadOnly))
+ {
+ c->warning(__tr2qs("Can't open the file \"%Q\" for reading"),&szName);
+ return true;
+ }
+
+ if(c->params()->count() < 2)iStartLine = 0;
+ if(c->params()->count() < 3)iCount = -1;
+
+ bool bLocal8Bit = szFlags.find('l',0,false) != -1;
+
+ KviKvsArray * a = new KviKvsArray();
+
+ int iIndex=0;
+
+ QTextStream stream( &f );
+
+ stream.setEncoding(bLocal8Bit ? QTextStream::Locale : QTextStream::UnicodeUTF8);
+ for(int i=0;i<iStartLine;i++)
+ stream.readLine();
+
+ if(iCount>0)
+ {
+ for(; (iCount>0 && !stream.atEnd()) ; iCount-- )
+ a->set(iIndex,new KviKvsVariant(stream.readLine()));
+ iIndex++;
+ } else {
+ while(!stream.atEnd()) {
+ a->set(iIndex,new KviKvsVariant(stream.readLine()));
+ iIndex++;
+ }
+ }
+
+ f.close();
+
+ c->returnValue()->setArray(a);
+
+ return true;
+}
+
+
+/*
+ @doc: file.writelines
+ @type:
+ command
+ @title:
+ file.writeLines
+ @short:
+ Writes an array of lines to a file
+ @syntax:
+ file.writeLines [-l] [-a] [-c] <filename:string> <lines:array>
+ @switches:
+ !sw: -l | --local-8-bit
+ Causes the lines to be saved in local 8 bit character set instead
+ of the default unicode encoding.
+ !sw: -a | --append
+ If the file already exists, then the lines are appended to the end
+ instead of overwriting the file.
+ !sw: -c | --crlf
+ The lines are separated by a carriage-return+line-feed character
+ combination, compatible with windows text mode files.
+ This is the only way to make the file readable in windows notepad, for example.
+ Please note that this is broken design: do NOT use it :)
+ !sw: -n | --no-separator
+ Do not separate the lines at all (either the separators are already
+ inside the lines array or no line separation is desired at all).
+ -n takes precedence over -c.
+ !sw: -q | --quiet
+ Don't complain if the file can't be opened: just fail silently
+ @description:
+ Writes the array of <lines> to the specified file.
+ The lines are separated by a single linefeed character (see also [fnc]$lf[/fnc])
+ unless the -c or -n switches are used. If the file already exists then it is
+ overwritten with the new data unless the -a switch is used.
+ The lines array is encoded in the ut8 character set unless the -l switch is used.
+ @seealso:
+ [fnc]$file.readLines[/fnc]
+*/
+
+
+
+static bool file_kvs_cmd_writeLines(KviKvsModuleCommandCall * c)
+{
+ QString szFile,szFlags;
+ KviKvsArrayCast a;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("filename",KVS_PT_NONEMPTYSTRING,0,szFile)
+ KVSM_PARAMETER("lines",KVS_PT_ARRAYCAST,0,a)
+ KVSM_PARAMETERS_END(c)
+
+ KviFileUtils::adjustFilePath(szFile);
+
+ KviFile f(szFile);
+ int iFlags = IO_WriteOnly;
+
+ if(!f.openForWriting(c->switches()->find('a',"append")))
+ {
+ if(!c->switches()->find('q',"quiet"))
+ c->warning(__tr2qs("Can't open the file \"%Q\" for writing"),&szFile);
+ return true;
+ }
+
+ bool bLocal8Bit = c->switches()->find('l',"local-8-bit");
+ bool bNoSeparator = c->switches()->find('n',"no-separator");
+ bool bAddCR = c->switches()->find('c',"crlf");
+
+ unsigned int u = 0;
+ while(u < a.array()->size())
+ {
+ KviKvsVariant * v = a.array()->at(u);
+ KviQCString dat;
+ if(v)
+ {
+ QString szDat;
+ v->asString(szDat);
+ KviQCString dat = bLocal8Bit ? szDat.local8Bit() : szDat.utf8();
+ }
+ if(!bNoSeparator)
+ {
+ if(bAddCR)dat += "\r\n";
+ else dat += '\n';
+ }
+ f.writeBlock(dat.data(),dat.length());
+ u++;
+ }
+
+ f.close();
+
+ return true;
+}
+
+
+/*
+ @doc: file.localdir
+ @type:
+ function
+ @title:
+ $file.localdir
+ @short:
+ Get the KVIrc local directory
+ @syntax:
+ <string> $file.localdir([relative_path:string])
+ @description:
+ Returns the path to the KVIrc local data directory.[br]
+ The KVIrc local data directory is always writeable and contains
+ the various subdirectories that KVIrc uses internally: audio , avatars ,
+ config , help , incoming , log , modules , msgcolors and pics.[br]
+ If <relative_path> is passed , then it is appended at the end of the directory
+ to form a complete filepath.[br]
+ The path is adjusted to contain single separators suitable for the platform
+ that KVIrc is atually running on (thus you not need to care about path
+ separators in the <relative_path> , KVIrc will adjust them).[br]
+ @examples:
+ [example]
+ echo KVIrc looks for pictures in $file.localdir(pics)
+ echo panic.png would be translated to $file.localdir(pics/panic.png)
+ [/example]
+*/
+
+static bool file_kvs_fnc_localdir(KviKvsModuleFunctionCall * c)
+{
+ QString szName;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("relative_path",KVS_PT_STRING,KVS_PF_OPTIONAL,szName)
+ KVSM_PARAMETERS_END(c)
+ if(szName.isEmpty())szName.append(KVI_PATH_SEPARATOR_CHAR);
+ QString szPath;
+ g_pApp->getLocalKvircDirectory(szPath,KviApp::None,szName);
+ KviFileUtils::adjustFilePath(szPath);
+ c->returnValue()->setString(szPath);
+ return true;
+}
+
+
+
+/*
+ @doc: file.homedir
+ @type:
+ function
+ @title:
+ $file.homedir
+ @short:
+ Get the user's HOME directory
+ @syntax:
+ <string> $file.homedir([relative_path:string])
+ @description:
+ Returns the user's HOME directory path.[br]
+ If <relative_path> is passed , then it is appended at the end of the directory
+ to form a complete filepath.[br]
+ The path is adjusted to contain single separators suitable for the platform
+ that KVIrc is atually running on (thus you not need to care about path
+ separators in the <relative_path> , KVIrc will adjust them).[br]
+*/
+
+static bool file_kvs_fnc_homedir(KviKvsModuleFunctionCall * c)
+{
+ QString szName;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("relative_path",KVS_PT_STRING,KVS_PF_OPTIONAL,szName)
+ KVSM_PARAMETERS_END(c)
+ if(szName.isEmpty())szName.append(KVI_PATH_SEPARATOR_CHAR);
+ QString szPath = QDir::homeDirPath();
+ KviQString::ensureLastCharIs(szPath,KVI_PATH_SEPARATOR_CHAR);
+ szPath.append(szName);
+ KviFileUtils::adjustFilePath(szPath);
+ c->returnValue()->setString(szPath);
+ return true;
+}
+
+
+
+/*
+ @doc: file.rootdir
+ @type:
+ function
+ @title:
+ $file.rootdir
+ @short:
+ Get the system root directory
+ @syntax:
+ $file.rootdir(<relative_path>)
+ $file.rootdir
+ @description:
+ Returns the system's root directory (/ on UNIX and C:/ on Windows).[br]
+ If <relative_path> is passed , then it is appended at the end of the directory
+ to form a complete filepath.[br]
+ The path is adjusted to contain single separators suitable for the platform
+ that KVIrc is atually running on (thus you not need to care about path
+ separators in the <relative_path> , KVIrc will adjust them).[br]
+*/
+
+static bool file_kvs_fnc_rootdir(KviKvsModuleFunctionCall * c)
+{
+ QString szName;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("relative_path",KVS_PT_STRING,KVS_PF_OPTIONAL,szName)
+ KVSM_PARAMETERS_END(c)
+ if(szName.isEmpty())szName.append(KVI_PATH_SEPARATOR_CHAR);
+ QString szPath = QDir::rootDirPath();
+ KviQString::ensureLastCharIs(szPath,KVI_PATH_SEPARATOR_CHAR);
+ szPath.append(szName);
+ KviFileUtils::adjustFilePath(szPath);
+ c->returnValue()->setString(szPath);
+ return true;
+}
+
+
+/*
+ @doc: file.cwd
+ @type:
+ function
+ @title:
+ $file.currentdir
+ @short:
+ Get the current directory
+ @syntax:
+ <string> $file.cwd([relative_path:string])
+ @description:
+ Returns the current working directory.[br]
+ If <relative_path> is passed , then it is appended at the end of the directory
+ to form a complete filepath.[br]
+ The path is adjusted to contain single separators suitable for the platform
+ that KVIrc is atually running on (thus you not need to care about path
+ separators in the <relative_path> , KVIrc will adjust them).[br]
+*/
+
+static bool file_kvs_fnc_cwd(KviKvsModuleFunctionCall * c)
+{
+ QString szName;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("relative_path",KVS_PT_STRING,KVS_PF_OPTIONAL,szName)
+ KVSM_PARAMETERS_END(c)
+ if(szName.isEmpty())szName.append(KVI_PATH_SEPARATOR_CHAR);
+ QString szPath = QDir::currentDirPath();
+ KviQString::ensureLastCharIs(szPath,KVI_PATH_SEPARATOR_CHAR);
+ szPath.append(szName);
+ KviFileUtils::adjustFilePath(szPath);
+ c->returnValue()->setString(szPath);
+ return true;
+}
+
+
+/*
+ @doc: file.globaldir
+ @type:
+ function
+ @title:
+ $file.globaldir
+ @short:
+ Get the KVIrc global directory
+ @syntax:
+ $file.globaldir(<relative_path>)
+ $file.globaldir
+ @description:
+ Returns the path to the KVIrc global data directory.[br]
+ The KVIrc local data directory is always readable but usually not writeable and contains
+ the various subdirectories that KVIrc uses internally: audio , avatars ,
+ config , help , incoming , log , modules , msgcolors and pics.[br]
+ If <relative_path> is passed , then it is appended at the end of the directory
+ to form a complete filepath.[br]
+ The path is adjusted to contain single separators suitable for the platform
+ that KVIrc is atually running on (thus you not need to care about path
+ separators in the <relative_path> , KVIrc will adjust them).[br]
+ @examples:
+ [example]
+ echo KVIrc looks for pictures in $file.globaldir(pics)
+ echo panic.png would be translated to $file.globaldir(pics/panic.png)
+ [/example]
+*/
+
+static bool file_kvs_fnc_globaldir(KviKvsModuleFunctionCall * c)
+{
+ QString szName;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("relative_path",KVS_PT_STRING,KVS_PF_OPTIONAL,szName)
+ KVSM_PARAMETERS_END(c)
+ if(szName.isEmpty())szName.append(KVI_PATH_SEPARATOR_CHAR);
+ QString szPath;
+ g_pApp->getGlobalKvircDirectory(szPath,KviApp::None,szName);
+ KviFileUtils::adjustFilePath(szPath);
+ c->returnValue()->setString(szPath);
+ return true;
+}
+
+/*
+ @doc: file.extractpath
+ @type:
+ function
+ @title:
+ $file.extractpath
+ @short:
+ Extract the path from a filename
+ @syntax:
+ <string> $file.extractpath(<filepath:string>)
+ @description:
+ Returns the path part of the <filepath> translated to match the current
+ platform filesystem conventions.[br]
+ The path will NOT contain a trailing path separator.[br]
+ For example, if <filepath> is /usr/arch/mp3/Carisma_SuonoDelSilenzio.mp3 then
+ this function will return /usr/arch/mp3 on UNIX and C:\usr\arch\mp3 on Windows.
+ @seealso:
+ [fnc]$file.extractFileName[/fnc]
+*/
+
+static bool file_kvs_fnc_extractpath(KviKvsModuleFunctionCall * c)
+{
+ QString szName;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("filepath",KVS_PT_NONEMPTYSTRING,0,szName)
+ KVSM_PARAMETERS_END(c)
+ c->returnValue()->setString(QFileInfo(szName).dirPath(TRUE));
+ return true;
+}
+
+
+/*
+ @doc: file.extractfilename
+ @type:
+ function
+ @title:
+ $file.extractfilename
+ @short:
+ Extract the filename from a file path
+ @syntax:
+ <string> $file.extractpath(<filepath:string>)
+ @description:
+ Returns the filename part of the filepath translated to match the current
+ platform filesystem conventions.[br]
+ For example, if <filepath> is /usr/arch/mp3/Carisma_SuonoDelSilenzio.mp3 then
+ this function will return Carisma_SuonoDelSilenzio.mp3
+ @seealso:
+ [fnc]$file.extractPath[/fnc]
+*/
+
+static bool file_kvs_fnc_extractfilename(KviKvsModuleFunctionCall * c)
+{
+ QString szName;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("filepath",KVS_PT_NONEMPTYSTRING,0,szName)
+ KVSM_PARAMETERS_END(c)
+ KviFileUtils::extractFileName(szName);
+ KviQString::cutToLast(szName,KVI_PATH_SEPARATOR_CHAR);
+ c->returnValue()->setString(szName);
+ return true;
+}
+
+
+
+static bool file_module_init(KviModule * m)
+{
+
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"copy",file_kvs_cmd_copy);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"rename",file_kvs_cmd_rename);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"mkdir",file_kvs_cmd_mkdir);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"write",file_kvs_cmd_write);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"remove",file_kvs_cmd_remove);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"rmdir",file_kvs_cmd_rmdir);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"addimagepath",file_kvs_cmd_addimagepath);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"delimagepath",file_kvs_cmd_delimagepath);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"writeLines",file_kvs_cmd_writeLines);
+
+ KVSM_REGISTER_FUNCTION(m,"exists",file_kvs_fnc_exists);
+ KVSM_REGISTER_FUNCTION(m,"type",file_kvs_fnc_type);
+ KVSM_REGISTER_FUNCTION(m,"size",file_kvs_fnc_size);
+
+ KVSM_REGISTER_FUNCTION(m,"allsizes",file_kvs_fnc_allSizes);
+
+ KVSM_REGISTER_FUNCTION(m,"fixpath",file_kvs_fnc_fixpath);
+ KVSM_REGISTER_FUNCTION(m,"ps",file_kvs_fnc_ps);
+ KVSM_REGISTER_FUNCTION(m,"read",file_kvs_fnc_read);
+ KVSM_REGISTER_FUNCTION(m,"localdir",file_kvs_fnc_localdir);
+ KVSM_REGISTER_FUNCTION(m,"homedir",file_kvs_fnc_homedir);
+ KVSM_REGISTER_FUNCTION(m,"rootdir",file_kvs_fnc_rootdir);
+ KVSM_REGISTER_FUNCTION(m,"cwd",file_kvs_fnc_cwd);
+ KVSM_REGISTER_FUNCTION(m,"globaldir",file_kvs_fnc_globaldir);
+ KVSM_REGISTER_FUNCTION(m,"extractpath",file_kvs_fnc_extractpath);
+ KVSM_REGISTER_FUNCTION(m,"extractfilename",file_kvs_fnc_extractfilename);
+ KVSM_REGISTER_FUNCTION(m,"ls",file_kvs_fnc_ls);
+ KVSM_REGISTER_FUNCTION(m,"readLines",file_kvs_fnc_readLines);
+
+
+ return true;
+}
+
+static bool file_module_cleanup(KviModule *m)
+{
+ return true;
+}
+
+KVIRC_MODULE(
+ "File", // module name
+ "1.0.0", // module version
+ "Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot net)", // author & (C)
+ "Interface to the file system",
+ file_module_init,
+ 0,
+ 0,
+ file_module_cleanup
+)
diff --git a/src/modules/filetransferwindow/Makefile.am b/src/modules/filetransferwindow/Makefile.am
new file mode 100644
index 00000000..910d86b4
--- /dev/null
+++ b/src/modules/filetransferwindow/Makefile.am
@@ -0,0 +1,22 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+SUBDIRS = caps
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkvifiletransferwindow.la
+
+libkvifiletransferwindow_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkvifiletransferwindow_la_SOURCES = libkvifiletransferwindow.cpp filetransferwindow.cpp
+libkvifiletransferwindow_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+noinst_HEADERS= filetransferwindow.h
+
+m_%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
+
+filetransferwindow.cpp: m_filetransferwindow.moc
diff --git a/src/modules/filetransferwindow/caps/Makefile.am b/src/modules/filetransferwindow/caps/Makefile.am
new file mode 100644
index 00000000..c3e694b7
--- /dev/null
+++ b/src/modules/filetransferwindow/caps/Makefile.am
@@ -0,0 +1,9 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+tmpdir = $(pluglibdir)/caps/tool/
+
+tmp_DATA= filetransferwindow
+
+EXTRA_DIST = $(tmp_DATA)
diff --git a/src/modules/filetransferwindow/caps/filetransferwindow b/src/modules/filetransferwindow/caps/filetransferwindow
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/modules/filetransferwindow/caps/filetransferwindow
diff --git a/src/modules/filetransferwindow/filetransferwindow.cpp b/src/modules/filetransferwindow/filetransferwindow.cpp
new file mode 100644
index 00000000..a3951a7c
--- /dev/null
+++ b/src/modules/filetransferwindow/filetransferwindow.cpp
@@ -0,0 +1,768 @@
+//==================================================================================
+//
+// File : filetransferwindow.cpp
+// Creation date : Mon Apr 21 2003 23:14:12 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2001 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the linkss of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) 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.
+//
+//==================================================================================
+
+#include "filetransferwindow.h"
+
+#include "kvi_debug.h"
+#include "kvi_iconmanager.h"
+#include "kvi_ircview.h"
+#include "kvi_out.h"
+#include "kvi_options.h"
+#include "kvi_locale.h"
+#include "kvi_out.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_themedlabel.h"
+#include "kvi_input.h"
+#include "kvi_qstring.h"
+
+#include <qsplitter.h>
+#include <qtooltip.h>
+#include "kvi_tal_hbox.h"
+#ifdef COMPILE_USE_QT4
+ #include <q3header.h>
+#else
+ #include <qheader.h>
+#endif
+#include <qpainter.h>
+#include <qmessagebox.h>
+#include <qclipboard.h>
+#include <qfileinfo.h>
+#include <qfile.h>
+#include <qlabel.h>
+#include <qfontmetrics.h>
+#include <qevent.h>
+
+#ifdef COMPILE_KDE_SUPPORT
+ #include <kurl.h>
+ #include <krun.h>
+ #include <kuserprofile.h>
+ #include <kmimetype.h>
+#endif //COMPILE_KDE_SUPPORT
+
+extern KviFileTransferWindow * g_pFileTransferWindow;
+
+
+KviFileTransferItem::KviFileTransferItem(KviTalListView * v,KviFileTransfer * t)
+: KviTalListViewItem(v)
+{
+ m_pTransfer = t;
+ m_pTransfer->setDisplayItem(this);
+}
+
+KviFileTransferItem::~KviFileTransferItem()
+{
+ m_pTransfer->setDisplayItem(0);
+}
+
+QString KviFileTransferItem::key(int column,bool bAcending) const
+{
+ QString ret;
+ ret.setNum(m_pTransfer->id());
+ if(ret.length() == 1)ret.prepend("0000000");
+ else if(ret.length() == 2)ret.prepend("000000");
+ else if(ret.length() == 3)ret.prepend("00000");
+ else if(ret.length() == 4)ret.prepend("0000");
+ else if(ret.length() == 5)ret.prepend("000");
+ else if(ret.length() == 6)ret.prepend("00");
+ else if(ret.length() == 7)ret.prepend("0");
+ return ret;
+}
+
+void KviFileTransferItem::paintCell(QPainter * p,const QColorGroup &cg,int column,int width,int align)
+{
+ QPainter * newP;
+ QPixmap * pix = 0;
+ if(p->device() == listView()->viewport())
+ {
+ // ops.. there is no double buffering active ?
+ // we'll do it then
+ pix = g_pFileTransferWindow->memPixmap();
+ if((pix->width() < width) || (pix->height() < height()))
+ {
+ pix->resize(width,height());
+ } else {
+ if((pix->width() > 500) || (pix->height() > 110))
+ {
+ if((pix->width() * pix->height()) > (width * height() * 4))
+ {
+ // this is getting too big
+ pix->resize(width,height());
+ }
+ }
+ }
+ newP = new QPainter(pix);
+ } else {
+ newP = p;
+ }
+
+ p->setFont(listView()->font());
+
+ newP->setPen(isSelected() ? cg.highlight() : cg.base());
+ newP->drawRect(0,0,width,height());
+ newP->setPen(m_pTransfer->active() ? QColor(180,180,180) : QColor(200,200,200));
+ newP->drawRect(1,1,width - 2,height() - 2);
+ newP->fillRect(2,2,width - 4,height() - 4,m_pTransfer->active() ? QColor(240,240,240) : QColor(225,225,225));
+
+ m_pTransfer->displayPaint(newP,column,width,height());
+
+ if(newP != p)
+ {
+ p->drawPixmap(0,0,*pix,0,0,width,height());
+ delete newP;
+ }
+}
+
+void KviFileTransferItem::setHeight(int h)
+{
+ KviTalListViewItem::setHeight(m_pTransfer->displayHeight(g_pFileTransferWindow->lineSpacing()));
+}
+
+
+KviFileTransferWindow::KviFileTransferWindow(KviModuleExtensionDescriptor * d,KviFrame * lpFrm)
+: KviWindow(KVI_WINDOW_TYPE_TOOL,lpFrm,"file transfer window",0) , KviModuleExtension(d)
+{
+ g_pFileTransferWindow = this;
+
+ m_pContextPopup = 0;
+ m_pLocalFilePopup = 0;
+ m_pOpenFilePopup = 0;
+
+ m_pMemPixmap = new QPixmap(1,1);
+
+ m_pTimer = new QTimer(this);
+ connect(m_pTimer,SIGNAL(timeout()),this,SLOT(heartbeat()));
+
+ m_pInput = new KviInput(this,0);
+
+ m_pSplitter = new QSplitter(Qt::Horizontal,this,"splitter");
+ m_pVertSplitter = new QSplitter(Qt::Vertical,m_pSplitter,"vsplitter");
+
+ m_pListView = new KviTalListView(m_pVertSplitter);
+ //m_pListView->header()->hide();
+ m_pListView->setAllColumnsShowFocus(true);
+ m_pListView->addColumn(__tr2qs_ctx("Type","filetransferwindow"),56);
+ m_pListView->addColumn(__tr2qs_ctx("Information","filetransferwindow"),350);
+ m_pListView->addColumn(__tr2qs_ctx("Progress","filetransferwindow"),350);
+
+ KviDynamicToolTip * tp = new KviDynamicToolTip(m_pListView->viewport());
+ connect(tp,SIGNAL(tipRequest(KviDynamicToolTip *,const QPoint &)),this,SLOT(tipRequest(KviDynamicToolTip *,const QPoint &)));
+
+ //m_pListView->setFocusPolicy(NoFocus);
+ //m_pListView->viewport()->setFocusPolicy(NoFocus);
+
+ //connect(m_pListView,SIGNAL(rightButtonPressed(KviTalListViewItem *,const QPoint &,int)),
+ // this,SLOT(showHostPopup(KviTalListViewItem *,const QPoint &,int)));
+
+ QFontMetrics fm(font());
+ m_iLineSpacing = fm.lineSpacing();
+
+ m_pIrcView = new KviIrcView(m_pVertSplitter,lpFrm,this);
+
+ m_pListView->installEventFilter(this);
+ connect(m_pListView,SIGNAL(rightButtonPressed(KviTalListViewItem *,const QPoint &,int)),this,SLOT(rightButtonPressed(KviTalListViewItem *,const QPoint &,int)));
+ connect(m_pListView,SIGNAL(doubleClicked(KviTalListViewItem *,const QPoint &,int)),this,SLOT(doubleClicked(KviTalListViewItem *,const QPoint &,int)));
+ fillTransferView();
+
+ connect(KviFileTransferManager::instance(),SIGNAL(transferRegistered(KviFileTransfer *)),this,SLOT(transferRegistered(KviFileTransfer *)));
+ connect(KviFileTransferManager::instance(),SIGNAL(transferUnregistering(KviFileTransfer *)),this,SLOT(transferUnregistering(KviFileTransfer *)));
+
+ KviFileTransferManager::instance()->setTransferWindow(this);
+
+ //setFocusHandler(m_pInput,this);
+
+ m_pTimer->start(2000);
+}
+
+KviFileTransferWindow::~KviFileTransferWindow()
+{
+ KviFileTransferManager::instance()->setTransferWindow(0);
+ g_pFileTransferWindow = 0;
+ delete m_pMemPixmap;
+}
+
+bool KviFileTransferWindow::eventFilter( QObject *obj, QEvent *ev )
+{
+ if( (obj==m_pListView) && ( ev->type() == QEvent::KeyPress ) )
+ {
+ QKeyEvent *keyEvent = (QKeyEvent*)ev;
+ switch(keyEvent->key())
+ {
+ case Qt::Key_Delete:
+ if(m_pListView->currentItem())
+ {
+ delete m_pListView->currentItem();
+ return TRUE;
+ }
+ break;
+ }
+ }
+ return KviWindow::eventFilter( obj, ev );
+}
+
+void KviFileTransferWindow::fontChange(const QFont &oldFont)
+{
+ QFontMetrics fm(font());
+ m_iLineSpacing = fm.lineSpacing();
+ KviWindow::fontChange(oldFont);
+}
+
+
+void KviFileTransferWindow::tipRequest(KviDynamicToolTip * tip,const QPoint &pnt)
+{
+ KviFileTransferItem * it = (KviFileTransferItem *)m_pListView->itemAt(pnt);
+ if(!it)return;
+ QString txt = it->transfer()->tipText();
+ tip->tip(m_pListView->itemRect(it),txt);
+}
+
+void KviFileTransferWindow::fillTransferView()
+{
+ KviPointerList<KviFileTransfer> * l = KviFileTransferManager::instance()->transferList();
+ if(!l)return;
+ KviFileTransferItem * it;
+ for(KviFileTransfer * t = l->first();t;t = l->next())
+ {
+ it = new KviFileTransferItem(m_pListView,t);
+ t->setDisplayItem(it);
+ }
+}
+
+KviFileTransferItem * KviFileTransferWindow::findItem(KviFileTransfer * t)
+{
+ KviFileTransferItem * it = (KviFileTransferItem *)m_pListView->firstChild();
+ while(it)
+ {
+ if(it->transfer() == t)return it;
+ it = (KviFileTransferItem *)(it->nextSibling());
+ }
+ return 0;
+}
+
+void KviFileTransferWindow::transferRegistered(KviFileTransfer * t)
+{
+ KviFileTransferItem * it = new KviFileTransferItem(m_pListView,t);
+ //t->setDisplayItem(it);
+}
+
+void KviFileTransferWindow::transferUnregistering(KviFileTransfer * t)
+{
+ KviFileTransferItem * it = findItem(t);
+ //t->setDisplayItem(0);
+ if(it)delete it;
+ it = 0;
+}
+
+void KviFileTransferWindow::doubleClicked(KviTalListViewItem *it,const QPoint &pnt,int col)
+{
+ if(it)
+ openLocalFile();
+}
+
+void KviFileTransferWindow::rightButtonPressed(KviTalListViewItem *it,const QPoint &pnt,int col)
+{
+ if(!m_pContextPopup)m_pContextPopup = new KviTalPopupMenu(this);
+ if(!m_pLocalFilePopup)m_pLocalFilePopup = new KviTalPopupMenu(this);
+ if(!m_pOpenFilePopup)
+ {
+ m_pOpenFilePopup= new KviTalPopupMenu(this);
+ connect(m_pOpenFilePopup,SIGNAL(activated(int)),this,SLOT(openFilePopupActivated(int)));
+ }
+
+ m_pContextPopup->clear();
+
+ int id;
+
+
+ if(it)
+ {
+ KviFileTransferItem * i = (KviFileTransferItem *)it;
+ if(i->transfer())
+ {
+
+ QString szFile = i->transfer()->localFileName();
+ if(!szFile.isEmpty())
+ {
+ m_pLocalFilePopup->clear();
+
+ QString tmp = "<b>file:/";
+ tmp += szFile;
+ tmp += "</b><br>";
+
+ QFileInfo fi(szFile);
+ if(fi.exists())
+ {
+ tmp += "<nobr>";
+ tmp += __tr2qs_ctx("Size: %1","filetransferwindow").arg(KviQString::makeSizeReadable(fi.size()));
+ tmp += "</nobr><br>";
+ }
+
+#ifdef COMPILE_KDE_SUPPORT
+ tmp += "<nobr>Mime: ";
+ tmp += KMimeType::findByPath(szFile)->name();
+ tmp += "</nobr>";
+#endif //COMPILE_KDE_SUPPORT
+
+ QLabel * l = new QLabel(tmp,m_pLocalFilePopup);
+ l->setFrameStyle(QFrame::Raised | QFrame::Panel);
+ m_pLocalFilePopup->insertItem(l);
+
+#ifdef COMPILE_KDE_SUPPORT
+ QString mimetype = KMimeType::findByPath(szFile)->name();
+ KServiceTypeProfile::OfferList offers = KServiceTypeProfile::offers(mimetype,"Application");
+
+ id = m_pLocalFilePopup->insertItem(__tr2qs_ctx("&Open","filetransferwindow"),this,SLOT(openLocalFile()));
+ m_pLocalFilePopup->setItemParameter(id,-1);
+
+ m_pOpenFilePopup->clear();
+
+ int id;
+ int idx = 0;
+
+ for(KServiceTypeProfile::OfferList::Iterator itOffers = offers.begin();
+ itOffers != offers.end(); ++itOffers)
+ {
+ id = m_pOpenFilePopup->insertItem((*itOffers).service()->pixmap(KIcon::Small),(*itOffers).service()->name());
+ m_pOpenFilePopup->setItemParameter(id,idx);
+ idx++;
+ }
+
+ m_pOpenFilePopup->insertSeparator();
+
+ id = m_pOpenFilePopup->insertItem(__tr2qs_ctx("&Other...","filetransferwindow"),this,SLOT(openLocalFileWith()));
+ m_pOpenFilePopup->setItemParameter(id,-1);
+
+ m_pLocalFilePopup->insertItem(__tr2qs_ctx("Open &With","filetransferwindow"),m_pOpenFilePopup);
+ m_pLocalFilePopup->insertSeparator();
+ m_pLocalFilePopup->insertItem(__tr2qs_ctx("Open &Location","filetransferwindow"),this,SLOT(openLocalFileFolder()));
+ m_pLocalFilePopup->insertItem(__tr2qs_ctx("Terminal at Location","filetransferwindow"),this,SLOT(openLocalFileTerminal()));
+ m_pLocalFilePopup->insertSeparator();
+#endif //COMPILE_KDE_SUPPORT
+
+//-| Grifisx & Noldor |-
+#ifdef COMPILE_ON_WINDOWS
+ id = m_pLocalFilePopup->insertItem(__tr2qs_ctx("&Open","filetransferwindow"),this,SLOT(openLocalFile()));
+ m_pLocalFilePopup->setItemParameter(id,-1);
+ m_pOpenFilePopup->insertSeparator();
+ m_pLocalFilePopup->insertItem(__tr2qs_ctx("Open &With","filetransferwindow"),this,SLOT(openLocalFileWith()));
+ m_pLocalFilePopup->insertSeparator();
+ m_pLocalFilePopup->insertItem(__tr2qs_ctx("Open &Location","filetransferwindow"),this,SLOT(openLocalFileFolder()));
+ m_pLocalFilePopup->insertItem(__tr2qs_ctx("MS-DOS Prompt at Location","filetransferwindow"),this,SLOT(openLocalFileTerminal()));
+ m_pLocalFilePopup->insertSeparator();
+#endif //COMPILE_ON_WINDOWS
+// G&N end
+
+ m_pLocalFilePopup->insertItem(__tr2qs_ctx("&Copy Path to Clipboard","filetransferwindow"),this,SLOT(copyLocalFileToClipboard()));
+
+ id = m_pLocalFilePopup->insertItem(__tr2qs_ctx("&Delete file","filetransferwindow"),this,SLOT(deleteLocalFile()));
+ m_pLocalFilePopup->setItemEnabled(id,i->transfer()->terminated());
+ m_pContextPopup->insertItem(__tr2qs_ctx("Local &File","filetransferwindow"),m_pLocalFilePopup);
+
+
+ }
+
+ i->transfer()->fillContextPopup(m_pContextPopup,col);
+ m_pContextPopup->insertSeparator();
+ }
+ }
+
+
+ bool bHaveTerminated = false;
+ KviFileTransferItem * item = (KviFileTransferItem *)m_pListView->firstChild();
+ while(item)
+ {
+ if(item->transfer()->terminated())
+ {
+ bHaveTerminated = true;
+ break;
+ }
+ item = (KviFileTransferItem *)item->nextSibling();
+ }
+
+ id = m_pContextPopup->insertItem(__tr2qs_ctx("&Clear Terminated","filetransferwindow"),this,SLOT(clearTerminated()));
+ m_pContextPopup->setItemEnabled(id,bHaveTerminated);
+
+ bool bAreTransfersActive = false;
+ if(m_pListView->childCount() >= 1)
+ bAreTransfersActive = true;
+
+ id = m_pContextPopup->insertItem(__tr2qs_ctx("Clear &All","filetransferwindow"),this,SLOT(clearAll()));
+ m_pContextPopup->setItemEnabled(id,bAreTransfersActive);
+
+ m_pContextPopup->popup(pnt);
+}
+
+
+KviFileTransfer * KviFileTransferWindow::selectedTransfer()
+{
+ KviTalListViewItem * it = m_pListView->selectedItem();
+ if(!it)return 0;
+ KviFileTransferItem * i = (KviFileTransferItem *)it;
+ return i->transfer();
+}
+
+void KviFileTransferWindow::openFilePopupActivated(int id)
+{
+#ifdef COMPILE_KDE_SUPPORT
+ int ip = m_pOpenFilePopup->itemParameter(id);
+ if(ip < 0)return;
+ QString txt = m_pOpenFilePopup->text(id);
+
+ KviFileTransfer * t = selectedTransfer();
+ if(!t)return;
+ QString tmp = t->localFileName();
+ if(tmp.isEmpty())return;
+
+ QString mimetype = KMimeType::findByPath(tmp)->name();
+ KServiceTypeProfile::OfferList offers = KServiceTypeProfile::offers(mimetype,"Application");
+
+ for(KServiceTypeProfile::OfferList::Iterator itOffers = offers.begin();
+ itOffers != offers.end(); ++itOffers)
+ {
+ if(txt == (*itOffers).service()->name())
+ {
+ KURL::List lst;
+ KURL url;
+ url.setPath(tmp);
+ lst.append(url);
+ KRun::run(*((*itOffers).service()), lst);
+ break;
+ }
+ }
+#endif //COMPILE_KDE_SUPPORT
+}
+
+void KviFileTransferWindow::openLocalFileTerminal()
+{
+//-| Grifisx & Noldor |-
+#ifdef COMPILE_ON_WINDOWS
+ KviFileTransfer * t = selectedTransfer();
+ if(!t)return;
+ QString tmp = t->localFileName();
+ if(tmp.isEmpty())return;
+ int idx = tmp.findRev("/");
+ if(idx == -1)return;
+ tmp = tmp.left(idx);
+ tmp.append("\"");
+/*FIX ME " this is not a solution ...because if the drive isn't system's drive the command
+ 'cd' naturaly doesn't work"*/
+ tmp.prepend("cmd.exe /k cd \"");
+ system(tmp.local8Bit().data());
+#else //COMPILE_ON_WINDOWS
+// G&N end
+ #ifdef COMPILE_KDE_SUPPORT
+ KviFileTransfer * t = selectedTransfer();
+ if(!t)return;
+ QString tmp = t->localFileName();
+ if(tmp.isEmpty())return;
+
+ int idx = tmp.findRev("/");
+ if(idx == -1)return;
+ tmp = tmp.left(idx);
+
+ tmp.prepend("konsole --workdir=\"");
+ tmp.append("\"");
+
+ KRun::runCommand(tmp);
+ #endif //COMPILE_KDE_SUPPORT
+#endif //!COMPILE_ON_WINDOWS
+}
+
+void KviFileTransferWindow::deleteLocalFile()
+{
+ KviFileTransfer * t = selectedTransfer();
+ if(!t)return;
+
+ QString fName = t->localFileName();
+ QString tmp;
+
+ KviQString::sprintf(tmp,__tr2qs_ctx("Do you really want to delete the file %Q?","filetransferwindow"),&fName);
+
+ if(QMessageBox::warning(this,__tr2qs_ctx("Confirm delete","filetransferwindow"),
+ tmp,__tr2qs_ctx("Yes","filetransferwindow"),__tr2qs_ctx("No","filetransferwindow")) != 0)
+ return;
+
+ if(!QFile::remove(fName))
+ QMessageBox::warning(this,__tr2qs_ctx("Delete failed","filetransferwindow"),
+ __tr2qs_ctx("Failed to remove the file","filetransferwindow"),
+ __tr2qs_ctx("OK","filetransferwindow"));
+}
+
+
+void KviFileTransferWindow::openLocalFile()
+{
+//-| Grifisx & Noldor |-
+#ifdef COMPILE_ON_WINDOWS
+
+ KviFileTransfer * t = selectedTransfer();
+ if(!t)return;
+ QString tmp = t->localFileName();
+ if(tmp.isEmpty())return;
+ tmp.replace("/","\\");
+ ShellExecute(0,"open",tmp.local8Bit().data(),NULL,NULL,SW_SHOWNORMAL); //You have to link the shell32.lib
+#else //!COMPILE_ON_WINDOWS
+// G&N end
+ #ifdef COMPILE_KDE_SUPPORT
+ KviFileTransfer * t = selectedTransfer();
+ if(!t)return;
+ QString tmp = t->localFileName();
+ if(tmp.isEmpty())return;
+
+ QString mimetype = KMimeType::findByPath(tmp)->name(); //KMimeType
+ KService::Ptr offer = KServiceTypeProfile::preferredService(mimetype,"Application");
+ if(!offer)
+ {
+ openLocalFileWith();
+ return;
+ }
+
+ KURL::List lst;
+ KURL url;
+ url.setPath(tmp);
+ lst.append(url);
+ KRun::run(*offer, lst);
+ #endif //COMPILE_KDE_SUPPORT
+#endif //!COMPILE_ON_WINDOWS
+}
+
+void KviFileTransferWindow::openLocalFileWith()
+{
+//-| Grifisx & Noldor |-
+#ifdef COMPILE_ON_WINDOWS
+ KviFileTransfer * t = selectedTransfer();
+ if(!t)return;
+ QString tmp = t->localFileName();
+ if(tmp.isEmpty())return;
+ tmp.replace("/","\\");
+ tmp.prepend("rundll32.exe shell32.dll,OpenAs_RunDLL "); // this if to show the 'open with...' window
+ WinExec(tmp.local8Bit().data(),SW_SHOWNORMAL);
+#else //!COMPILE_ON_WINDOWS
+// G&N end
+ #ifdef COMPILE_KDE_SUPPORT
+ KviFileTransfer * t = selectedTransfer();
+ if(!t)return;
+ QString tmp = t->localFileName();
+ if(tmp.isEmpty())return;
+
+ KURL::List lst;
+ KURL url;
+ url.setPath(tmp);
+ lst.append(url);
+ KRun::displayOpenWithDialog(lst);
+ #endif //COMPILE_KDE_SUPPORT
+#endif //!COMPILE_ON_WINDOWS
+}
+
+void KviFileTransferWindow::copyLocalFileToClipboard()
+{
+ KviFileTransfer * t = selectedTransfer();
+ if(!t)return;
+ QString tmp = t->localFileName();
+ if(tmp.isEmpty())return;
+#ifdef COMPILE_USE_QT4
+ QApplication::clipboard()->setText(tmp);
+#else
+ QApplication::clipboard()->setSelectionMode(false);
+ QApplication::clipboard()->setText(tmp);
+ QApplication::clipboard()->setSelectionMode(true);
+ QApplication::clipboard()->setText(tmp);
+#endif
+}
+
+void KviFileTransferWindow::openLocalFileFolder()
+{
+//-| Grifisx & Noldor|-
+#ifdef COMPILE_ON_WINDOWS
+ KviFileTransfer * t = selectedTransfer();
+ if(!t)return;
+ QString tmp = t->localFileName();
+ if(tmp.isEmpty())return;
+ tmp=QFileInfo(tmp).dirPath(TRUE);
+ tmp.replace('/','\\');
+ tmp.prepend("explorer.exe ");
+ WinExec(tmp.local8Bit().data(), SW_MAXIMIZE);
+#else //!COMPILE_ON_WINDOWS
+// G&N end
+ #ifdef COMPILE_KDE_SUPPORT
+ KviFileTransfer * t = selectedTransfer();
+ if(!t)return;
+ QString tmp = t->localFileName();
+ if(tmp.isEmpty())return;
+
+ int idx = tmp.findRev("/");
+ if(idx == -1)return;
+ tmp = tmp.left(idx);
+
+ QString mimetype = KMimeType::findByPath(tmp)->name(); // inode/directory
+ KService::Ptr offer = KServiceTypeProfile::preferredService(mimetype,"Application");
+ if(!offer)return;
+
+ KURL::List lst;
+ KURL url;
+ url.setPath(tmp);
+ lst.append(url);
+ KRun::run(*offer, lst);
+ #endif //COMPILE_KDE_SUPPORT
+#endif //!COMPILE_ON_WINDOWS
+}
+
+
+void KviFileTransferWindow::heartbeat()
+{
+ if(m_pListView->childCount() < 1)return;
+
+ KviTalListViewItem * i1;
+ KviTalListViewItem * i2;
+
+ i1 = m_pListView->itemAt(QPoint(1,1));
+ if(!i1)
+ {
+ m_pListView->viewport()->update();
+ return;
+ }
+ i2 = m_pListView->itemAt(QPoint(1,m_pListView->viewport()->height() - 2));
+ if(i2)i2 = i2->nextSibling();
+
+ while(i1 && (i1 != i2))
+ {
+ if(((KviFileTransferItem *)i1)->transfer()->active())
+ {
+ m_pListView->repaintItem(i1);
+ }
+ i1 = i1->nextSibling();
+ }
+}
+
+void KviFileTransferWindow::clearAll()
+{
+ QString tmp;
+
+ bool bHaveAllTerminated = true;
+ KviFileTransferItem * item = (KviFileTransferItem *)m_pListView->firstChild();
+ while(item)
+ {
+ if(!item->transfer()->terminated())
+ {
+ bHaveAllTerminated = false;
+ break;
+ }
+ item = (KviFileTransferItem *)item->nextSibling();
+ }
+
+ KviQString::sprintf(tmp,__tr2qs_ctx("Clear all transfers, including any in progress?","filetransferwindow"));
+
+ // If any transfer is active asks for confirm
+ if(!bHaveAllTerminated)
+ if(QMessageBox::warning(this,__tr2qs_ctx("Clear All Transfers? - KVIrc","filetransferwindow"), tmp,__tr2qs_ctx("Yes","filetransferwindow"),__tr2qs_ctx("No","filetransferwindow")) != 0)
+ return;
+
+ KviFileTransferManager::instance()->killAllTransfers();
+}
+
+void KviFileTransferWindow::clearTerminated()
+{
+ KviFileTransferManager::instance()->killTerminatedTransfers();
+}
+
+void KviFileTransferWindow::getBaseLogFileName(KviStr &buffer)
+{
+ buffer.sprintf("FILETRANSFER");
+}
+
+QPixmap * KviFileTransferWindow::myIconPtr()
+{
+ return g_pIconManager->getSmallIcon(KVI_SMALLICON_FILETRANSFER);
+}
+
+void KviFileTransferWindow::resizeEvent(QResizeEvent *e)
+{
+ int h = m_pInput->heightHint();
+ m_pSplitter->setGeometry(0,0,width(),height() - h);
+ m_pInput->setGeometry(0,height() - h,width(),h);
+}
+
+QSize KviFileTransferWindow::sizeHint() const
+{
+ return m_pSplitter->sizeHint();
+}
+
+void KviFileTransferWindow::fillCaptionBuffers()
+{
+ m_szPlainTextCaption = __tr2qs_ctx("File Transfers","filetransferwindow");
+
+ m_szHtmlActiveCaption = "<nobr><font color=\"";
+ m_szHtmlActiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextActive).name();
+ m_szHtmlActiveCaption += "\"><b>";
+ m_szHtmlActiveCaption += m_szPlainTextCaption;
+ m_szHtmlActiveCaption += "</b></font></nobr>";
+
+ m_szHtmlInactiveCaption = "<nobr><font color=\"";
+ m_szHtmlInactiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextInactive).name();
+ m_szHtmlInactiveCaption += "\"><b>";
+ m_szHtmlInactiveCaption += m_szPlainTextCaption;
+ m_szHtmlInactiveCaption += "</b></font></nobr>";
+}
+
+void KviFileTransferWindow::die()
+{
+ close();
+}
+
+
+
+//#warning "Load & save properties of this kind of window"
+
+//void KviFileTransferWindow::saveProperties()
+//{
+// KviWindowProperty p;
+// p.rect = externalGeometry();
+// p.isDocked = isAttacched();
+// QValueList<int> l(m_pSplitter->sizes());
+// if(l.count() >= 1)p.splitWidth1 = *(l.at(0));
+// if(l.count() >= 2)p.splitWidth2 = *(l.at(1));
+// p.timestamp = m_pView->timestamp();
+// p.imagesVisible = m_pView->imagesVisible();
+// p.isMaximized = isAttacched() && isMaximized();
+// p.topSplitWidth1 = 0;
+// p.topSplitWidth2 = 0;
+// p.topSplitWidth3 = 0;
+// g_pOptions->m_pWinPropertiesList->setProperty(caption(),&p);
+//}
+//
+//void KviFileTransferWindow::setProperties(KviWindowProperty *p)
+//{
+// QValueList<int> l;
+// l.append(p->splitWidth1);
+// l.append(p->splitWidth2);
+// m_pVertSplitter->setSizes(l);
+// m_pIrcView->setTimestamp(p->timestamp);
+// m_pIrcView->setShowImages(p->imagesVisible);
+//}
+
+void KviFileTransferWindow::applyOptions()
+{
+ m_pIrcView->applyOptions();
+ KviWindow::applyOptions();
+}
+
+#include "m_filetransferwindow.moc"
diff --git a/src/modules/filetransferwindow/filetransferwindow.h b/src/modules/filetransferwindow/filetransferwindow.h
new file mode 100644
index 00000000..423dc3a1
--- /dev/null
+++ b/src/modules/filetransferwindow/filetransferwindow.h
@@ -0,0 +1,111 @@
+#ifndef _FILETRANSFERWINDOW_H_
+#define _FILETRANSFERWINDOW_H_
+//==================================================================================
+//
+// File : filetransferwindow.h
+// Creation date : Mon Apr 21 2003 23:14:12 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2001 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the linkss of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) 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.
+//
+//==================================================================================
+
+#include "kvi_window.h"
+#include "kvi_string.h"
+#include "kvi_ircsocket.h"
+#include "kvi_sparser.h"
+#include "kvi_console.h"
+#include "kvi_moduleextension.h"
+#include "kvi_filetransfer.h"
+#include "kvi_dynamictooltip.h"
+
+#include "kvi_tal_listview.h"
+#include "kvi_tal_popupmenu.h"
+#include <qtoolbutton.h>
+#include <qtimer.h>
+#include <qpixmap.h>
+
+
+
+class KviFileTransferItem : public KviTalListViewItem
+{
+public:
+ KviFileTransferItem(KviTalListView * v,KviFileTransfer * t);
+ ~KviFileTransferItem();
+protected:
+ KviFileTransfer * m_pTransfer;
+public:
+ KviFileTransfer * transfer(){ return m_pTransfer; };
+ virtual void paintCell(QPainter * p,const QColorGroup &cg,int column,int width,int align);
+ virtual void setHeight(int h);
+ virtual QString key(int column,bool bAcending) const;
+};
+
+
+class KviFileTransferWindow : public KviWindow , public KviModuleExtension
+{
+ friend class KviFileTransferItem;
+ Q_OBJECT
+public:
+ KviFileTransferWindow(KviModuleExtensionDescriptor * d,KviFrame * lpFrm);
+ ~KviFileTransferWindow();
+protected:
+ QSplitter * m_pVertSplitter;
+ KviTalListView * m_pListView;
+ KviTalPopupMenu * m_pContextPopup;
+ KviTalPopupMenu * m_pLocalFilePopup;
+ KviTalPopupMenu * m_pOpenFilePopup;
+ QTimer * m_pTimer;
+ QPixmap * m_pMemPixmap;
+ int m_iLineSpacing; // cached fm value
+public: // Methods
+ virtual void die();
+protected:
+ QPixmap * memPixmap(){ return m_pMemPixmap; };
+ virtual QPixmap * myIconPtr();
+ virtual void fillCaptionBuffers();
+ virtual void applyOptions();
+ virtual void resizeEvent(QResizeEvent *e);
+ virtual void getBaseLogFileName(KviStr &buffer);
+ KviFileTransferItem * findItem(KviFileTransfer * t);
+ void fillTransferView();
+ KviFileTransfer * selectedTransfer();
+ virtual void fontChange(const QFont &oldFont);
+ bool eventFilter( QObject *obj, QEvent *ev );
+public:
+ virtual QSize sizeHint() const;
+ int lineSpacing(){ return m_iLineSpacing; };
+protected slots:
+ void transferRegistered(KviFileTransfer *t);
+ void transferUnregistering(KviFileTransfer *t);
+ void rightButtonPressed(KviTalListViewItem *it,const QPoint &pnt,int col);
+ void doubleClicked(KviTalListViewItem *it,const QPoint &pnt,int col);
+ void heartbeat();
+ void clearTerminated();
+ void clearAll();
+ void tipRequest(KviDynamicToolTip * tip,const QPoint &pnt);
+
+ void openLocalFile();
+ void openLocalFileWith();
+ void copyLocalFileToClipboard();
+ void openLocalFileFolder();
+ void openFilePopupActivated(int id);
+ void openLocalFileTerminal();
+ void deleteLocalFile();
+};
+
+#endif //_FILETRANSFERWINDOW_H_
diff --git a/src/modules/filetransferwindow/libkvifiletransferwindow.cpp b/src/modules/filetransferwindow/libkvifiletransferwindow.cpp
new file mode 100644
index 00000000..6427e5eb
--- /dev/null
+++ b/src/modules/filetransferwindow/libkvifiletransferwindow.cpp
@@ -0,0 +1,161 @@
+//==================================================================================
+//
+// File : libkvifiletransferwindow.cpp
+// Creation date : Mon Apr 21 2003 23:14:12 CEST by Szymon Stefanek
+//
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//==================================================================================
+
+#include "kvi_module.h"
+
+
+#include "filetransferwindow.h"
+
+#include "kvi_app.h"
+#include "kvi_frame.h"
+#include "kvi_window.h"
+#include "kvi_locale.h"
+#include "kvi_iconmanager.h"
+
+#include <qsplitter.h>
+
+KviFileTransferWindow * g_pFileTransferWindow = 0;
+
+static KviModuleExtension * filetransferwindow_extension_alloc(KviModuleExtensionAllocStruct * s)
+{
+ bool bCreateMinimized = false;
+ bool bNoRaise = false;
+
+ if(!g_pFileTransferWindow)
+ {
+ if(s->pParams)
+ {
+ if(QVariant * v = s->pParams->find("bCreateMinimized"))
+ {
+ if(v->isValid())
+ {
+ if(v->type() == QVariant::Bool)
+ {
+ bCreateMinimized = v->toBool();
+ }
+ }
+ }
+ }
+
+ g_pFileTransferWindow = new KviFileTransferWindow(s->pDescriptor,g_pFrame);
+ g_pFrame->addWindow(g_pFileTransferWindow,!bCreateMinimized);
+ if(bCreateMinimized)g_pFileTransferWindow->minimize();
+ return g_pFileTransferWindow;
+ }
+
+ if(s->pParams)
+ {
+ if(QVariant * v = s->pParams->find("bNoRaise"))
+ {
+ if(v)
+ {
+ if(v->isValid() && v->type() == QVariant::Bool)
+ bNoRaise = v->toBool();
+ }
+ }
+ }
+
+ if(!bNoRaise)g_pFileTransferWindow->delayedAutoRaise();
+ return g_pFileTransferWindow;
+}
+
+
+/*
+ @doc: filetransferwindow.open
+ @type:
+ command
+ @title:
+ filetransferwindow.open
+ @short:
+ Opens the file transfer window
+ @syntax:
+ filetransferwindow.open [-m] [-n]
+ @switches:
+ !sw: -m
+ Causes the window to be created as minimized
+ !sw: -n
+ Causes the window to be not raised if already open
+ @description:
+ Opens the file transfer window
+*/
+
+static bool filetransferwindow_kvs_cmd_open(KviKvsModuleCommandCall * c)
+{
+ KviModuleExtensionDescriptor * d = c->module()->findExtensionDescriptor("tool",KVI_FILE_TRANSFER_WINDOW_EXTENSION_NAME);
+
+ if(d)
+ {
+ KviPointerHashTable<QString,QVariant> dict(17,true);
+ dict.setAutoDelete(true);
+ QString dummy;
+ dict.replace("bCreateMinimized",new QVariant(c->hasSwitch('m',dummy)));
+ dict.replace("bNoRaise",new QVariant(c->hasSwitch('n',dummy)));
+
+ d->allocate(c->window(),&dict,0);
+ } else {
+ c->warning(__tr("Ops.. internal error"));
+ }
+ return true;
+}
+
+static bool filetransferwindow_module_init(KviModule * m)
+{
+ KviModuleExtensionDescriptor * d = m->registerExtension("tool",
+ KVI_FILE_TRANSFER_WINDOW_EXTENSION_NAME,
+ __tr2qs("Manage File &Transfers"),
+ filetransferwindow_extension_alloc);
+
+ if(d)d->setIcon(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_FILETRANSFER)));
+
+
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"open",filetransferwindow_kvs_cmd_open);
+
+
+ return true;
+}
+
+static bool filetransferwindow_module_cleanup(KviModule *m)
+{
+ if(g_pFileTransferWindow)
+ {
+ delete g_pFileTransferWindow;
+ g_pFileTransferWindow = 0;
+ }
+ return true;
+}
+
+static bool filetransferwindow_module_can_unload(KviModule *m)
+{
+ return (!g_pFileTransferWindow);
+}
+
+KVIRC_MODULE(
+ "FileTransferWindow",
+ "1.0.0",
+ "Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot net)",
+ "Links window extension",
+ filetransferwindow_module_init,
+ filetransferwindow_module_can_unload,
+ 0,
+ filetransferwindow_module_cleanup
+)
diff --git a/src/modules/help/Makefile.am b/src/modules/help/Makefile.am
new file mode 100644
index 00000000..fe6f03f6
--- /dev/null
+++ b/src/modules/help/Makefile.am
@@ -0,0 +1,22 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkvihelp.la
+
+libkvihelp_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkvihelp_la_SOURCES = libkvihelp.cpp helpwidget.cpp helpwindow.cpp index.cpp index.moc
+libkvihelp_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+noinst_HEADERS= helpwidget.h helpwindow.h index.h
+
+%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
+
+helpwidget.cpp: helpwidget.moc
+helpwindow.cpp: helpwindow.moc
+index.cpp: index.moc
diff --git a/src/modules/help/helpwidget.cpp b/src/modules/help/helpwidget.cpp
new file mode 100644
index 00000000..4036a0dd
--- /dev/null
+++ b/src/modules/help/helpwidget.cpp
@@ -0,0 +1,154 @@
+//
+// File : helpwidget.cpp
+// Creation date : Thu Aug 10 2000 17:42:12 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "helpwidget.h"
+
+#include "kvi_frame.h"
+#include "kvi_iconmanager.h"
+#include "kvi_locale.h"
+#include "kvi_app.h"
+#include "kvi_msgbox.h"
+#include "kvi_module.h"
+#include "kvi_styled_controls.h"
+#include "helpwindow.h"
+#include "kvi_fileutils.h"
+
+#include <qtoolbutton.h>
+#include <qlineedit.h>
+#include <qtooltip.h>
+#include <qtimer.h>
+#include <qclipboard.h>
+
+extern Index * g_pDocIndex;
+extern KviPointerList<KviHelpWindow> * g_pHelpWindowList;
+extern KviPointerList<KviHelpWidget> * g_pHelpWidgetList;
+
+KviHelpWidget::KviHelpWidget(QWidget * par,KviFrame * lpFrm,bool bIsStandalone)
+: QWidget(par,"help_widget")
+{
+
+ if(bIsStandalone)g_pHelpWidgetList->append(this);
+ m_bIsStandalone = bIsStandalone;
+
+//#warning "Re enable this when using Qt 3.0 : QProcess "
+ m_pTextBrowser = new QTextBrowser(this,"text_browser");
+ m_pTextBrowser->setFrameStyle(QFrame::StyledPanel|QFrame::Sunken);
+#ifndef COMPILE_USE_QT4
+ m_pTextBrowser->setFocusPolicy(QWidget::NoFocus);
+#endif
+ m_pToolBar = new KviTalHBox(this);
+
+ m_pBtnIndex = new KviStyledToolButton(m_pToolBar);
+ m_pBtnIndex->setIconSet(*g_pIconManager->getBigIcon(KVI_BIGICON_HELPINDEX));
+ connect(m_pBtnIndex,SIGNAL(clicked()),this,SLOT(showIndex()));
+ //m_pBtnIndex->setUsesBigPixmap(true);
+
+ m_pBtnBackward = new KviStyledToolButton(m_pToolBar);
+ m_pBtnBackward->setIconSet(*g_pIconManager->getBigIcon(KVI_BIGICON_HELPBACK));
+ connect(m_pBtnBackward,SIGNAL(clicked()),m_pTextBrowser,SLOT(backward()));
+ m_pBtnBackward->setEnabled(false);
+ //m_pBtnBackward->setUsesBigPixmap(true);
+
+ m_pBtnForward = new KviStyledToolButton(m_pToolBar);
+ m_pBtnForward->setIconSet(*g_pIconManager->getBigIcon(KVI_BIGICON_HELPFORWARD));
+ connect(m_pBtnForward,SIGNAL(clicked()),m_pTextBrowser,SLOT(forward()));
+ m_pBtnForward->setEnabled(false);
+ //m_pBtnForward->setUsesBigPixmap(true);
+
+ QWidget* pSpacer=new QWidget(m_pToolBar);
+
+ if(bIsStandalone)
+ {
+ QToolButton * b = new KviStyledToolButton(m_pToolBar);
+ b->setIconSet(*g_pIconManager->getBigIcon(KVI_BIGICON_HELPCLOSE));
+ connect(b,SIGNAL(clicked()),this,SLOT(doClose()));
+ //b->setUsesBigPixmap(true);
+ }
+
+ m_pToolBar->setStretchFactor(pSpacer,1);
+ connect(m_pTextBrowser,SIGNAL(backwardAvailable(bool)),m_pBtnBackward,SLOT(setEnabled(bool)));
+ connect(m_pTextBrowser,SIGNAL(forwardAvailable(bool)),m_pBtnForward,SLOT(setEnabled(bool)));
+
+ m_pTextBrowser->viewport()->installEventFilter(this);
+
+}
+
+KviHelpWidget::~KviHelpWidget()
+{
+ if(m_bIsStandalone)g_pHelpWidgetList->removeRef(this);
+}
+
+void KviHelpWidget::showIndex()
+{
+#ifdef COMPILE_USE_QT4
+ m_pTextBrowser->setSource(QUrl("index.html"));
+#else
+ m_pTextBrowser->setSource("index.html");
+#endif
+}
+
+void KviHelpWidget::resizeEvent(QResizeEvent *e)
+{
+ int hght = m_pToolBar->sizeHint().height();
+ if(hght < 40)hght = 40;
+ m_pToolBar->setGeometry(0,0,width(),hght);
+ m_pTextBrowser->setGeometry(0,hght,width(),height() - hght);
+}
+
+void KviHelpWidget::doClose()
+{
+ // hack needed to workaround "QToolBar::emulateButtonClicked()"
+ // that refers to the "this" pointer after this slot has been
+ // called (from the "too-small-toolbar-for-all-items-popup")
+ QTimer::singleShot(0,this,SLOT(suicide()));
+}
+
+void KviHelpWidget::suicide()
+{
+ // goodbye cruel wolrd
+ delete this;
+}
+
+QSize KviHelpWidget::sizeHint() const
+{
+ int wdth = m_pTextBrowser->sizeHint().width();
+ if(m_pToolBar->sizeHint().width() > wdth)wdth = m_pToolBar->sizeHint().width();
+ QSize s(wdth,m_pTextBrowser->sizeHint().height() + m_pToolBar->sizeHint().height());
+ return s;
+}
+
+bool KviHelpWidget::eventFilter(QObject * o, QEvent *e)
+{
+ QClipboard *cb = QApplication::clipboard();
+
+ if(e->type() == QEvent::MouseButtonRelease) {
+ if(m_pTextBrowser->hasSelectedText()) {
+ cb->setText(m_pTextBrowser->selectedText());
+ }
+ }
+
+ return QWidget::eventFilter(o,e);
+}
+
+
+
+#include "helpwidget.moc"
diff --git a/src/modules/help/helpwidget.h b/src/modules/help/helpwidget.h
new file mode 100644
index 00000000..e00f8bcf
--- /dev/null
+++ b/src/modules/help/helpwidget.h
@@ -0,0 +1,61 @@
+#ifndef _HELPWIDGET_H_
+#define _HELPWIDGET_H_
+//
+// File : helpwidget.h
+// Creation date : Thu Aug 10 2000 17:26:20 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_tal_hbox.h"
+#include <qtextbrowser.h>
+#include "index.h"
+#include <qprogressbar.h>
+
+class KviFrame;
+class QToolButton;
+class QLineEdit;
+//class KviProcess;
+
+class KviHelpWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ KviHelpWidget(QWidget *par,KviFrame * lpFrm,bool bIsStandalone = false);
+ ~KviHelpWidget();
+private:
+ QToolButton * m_pBtnIndex;
+ QToolButton * m_pBtnBackward;
+ QToolButton * m_pBtnForward;
+ KviTalHBox * m_pToolBar;
+ QTextBrowser * m_pTextBrowser;
+ bool m_bIsStandalone;
+protected:
+ virtual void resizeEvent(QResizeEvent *e);
+ bool eventFilter(QObject *, QEvent *);
+protected slots:
+ void doClose();
+ void showIndex();
+ void suicide();
+public:
+ virtual QSize sizeHint() const;
+ QTextBrowser * textBrowser() { return m_pTextBrowser; }
+};
+
+
+#endif //_HELPWIDGET_H_
diff --git a/src/modules/help/helpwindow.cpp b/src/modules/help/helpwindow.cpp
new file mode 100644
index 00000000..9fc11427
--- /dev/null
+++ b/src/modules/help/helpwindow.cpp
@@ -0,0 +1,329 @@
+//
+// File : helpwindow.cpp
+// Creation date : Tue Aug 11 2000 18:08:22 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the m_terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) 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.
+//
+
+
+#include "helpwindow.h"
+#include "helpwidget.h"
+#include "kvi_app.h"
+
+#include "kvi_iconmanager.h"
+#include "kvi_options.h"
+#include "kvi_locale.h"
+#include "kvi_module.h"
+#include "kvi_config.h"
+#include "kvi_styled_controls.h"
+
+#include <qfileinfo.h>
+#include <qsplitter.h>
+#include <qlineedit.h>
+#include <qmessagebox.h>
+#include <qregexp.h>
+#include <qtooltip.h>
+#include "kvi_valuelist.h"
+
+#include "kvi_sourcesdate.h"
+
+extern Index * g_pDocIndex;
+extern KviPointerList<KviHelpWindow> * g_pHelpWindowList;
+extern KviPointerList<KviHelpWidget> * g_pHelpWidgetList;
+
+bool g_bIndexingDone = FALSE;
+KviHelpWindow::KviHelpWindow(KviFrame * lpFrm,const char * name)
+: KviWindow(KVI_WINDOW_TYPE_HELP,lpFrm,name)
+{
+
+ if(!g_bIndexingDone)
+ {
+ QString szDoclist,szDict;
+
+ g_pApp->getLocalKvircDirectory(szDoclist,KviApp::Help,"help.doclist." KVI_SOURCES_DATE);
+ g_pApp->getLocalKvircDirectory(szDict,KviApp::Help,"help.dict." KVI_SOURCES_DATE);
+
+ if ( QFileInfo( szDoclist ).exists() && QFileInfo( szDict ).exists() ) {
+ g_pDocIndex->readDict();
+ } else {
+#ifdef COMPILE_USE_QT4
+ QProgressDialog* pProgressDialog = new QProgressDialog( __tr2qs("Indexing help files"), __tr2qs("Cancel"), 0,100 );
+#else
+ QProgressDialog* pProgressDialog = new QProgressDialog( __tr2qs("Indexing help files"), __tr2qs("Cancel"), 100 );
+#endif
+ connect(g_pDocIndex,SIGNAL(indexingProgress(int)), pProgressDialog, SLOT(setProgress(int)) );
+ g_pDocIndex->makeIndex();
+ g_pDocIndex->writeDict();
+ g_pDocIndex->writeDocumentList();
+ delete pProgressDialog;
+ }
+ g_bIndexingDone=TRUE;
+ }
+
+ g_pHelpWindowList->append(this);
+ m_pSplitter = new QSplitter(Qt::Horizontal,this,"main_splitter");
+ m_pHelpWidget = new KviHelpWidget(m_pSplitter,lpFrm);
+
+ m_pToolBar=new KviTalVBox(m_pSplitter);
+
+ m_pTabWidget = new QTabWidget(m_pToolBar);
+
+ m_pIndexTab = new KviTalVBox(m_pTabWidget);
+ m_pTabWidget->insertTab(m_pIndexTab,__tr2qs("Index"));
+
+ KviTalHBox* pSearchBox = new KviTalHBox(m_pIndexTab);
+ m_pIndexSearch = new QLineEdit(pSearchBox);
+ connect( m_pIndexSearch, SIGNAL( textChanged(const QString&) ),
+ this, SLOT( searchInIndex(const QString&) ) );
+ connect( m_pIndexSearch, SIGNAL( returnPressed() ),
+ this, SLOT( showIndexTopic() ) );
+
+ KviStyledToolButton* pBtnRefreshIndex = new KviStyledToolButton(pSearchBox);
+ pBtnRefreshIndex->setIconSet(*g_pIconManager->getBigIcon(KVI_REFRESH_IMAGE_NAME));
+ connect(pBtnRefreshIndex,SIGNAL(clicked()),this,SLOT(refreshIndex()));
+ QToolTip::add( pBtnRefreshIndex, __tr2qs("Refresh index") );
+
+ m_pIndexListBox = new KviTalListBox(m_pIndexTab);
+ QStringList docList=g_pDocIndex->titlesList();
+ m_pIndexListBox->insertStringList(docList);
+ connect(m_pIndexListBox,SIGNAL(selected(int)),this,SLOT(indexSelected ( int )));
+ m_pIndexListBox->sort();
+
+ m_pSearchTab = new KviTalVBox(m_pTabWidget);
+ m_pTabWidget->insertTab(m_pSearchTab,__tr2qs("Search"));
+
+ m_pTermsEdit = new QLineEdit(m_pSearchTab);
+/* connect( m_pTermsEdit, SIGNAL( textChanged(const QString&) ),
+ this, SLOT( searchInIndex(const QString&) ) );*/
+ connect( m_pTermsEdit, SIGNAL( returnPressed() ),
+ this, SLOT( startSearch() ) );
+
+ m_pResultBox = new KviTalListBox(m_pSearchTab);
+ connect(m_pResultBox,SIGNAL(selected(int)),this,SLOT(searchSelected ( int )));
+
+ KviValueList<int> li;
+ li.append(width()-80);
+ li.append(80);
+ m_pSplitter->setSizes(li);
+
+}
+
+KviHelpWindow::~KviHelpWindow()
+{
+ g_pHelpWindowList->removeRef(this);
+}
+
+void KviHelpWindow::saveProperties(KviConfig *cfg)
+{
+ KviWindow::saveProperties(cfg);
+ cfg->writeEntry("Splitter",m_pSplitter->sizes());
+}
+
+void KviHelpWindow::loadProperties(KviConfig *cfg)
+{
+ KviValueList<int> def;
+ int w = width();
+ def.append((w * 82) / 100);
+ def.append((w * 18) / 100);
+ m_pSplitter->setSizes(cfg->readIntListEntry("Splitter",def));
+ KviWindow::loadProperties(cfg);
+}
+
+
+void KviHelpWindow::refreshIndex()
+{
+ m_pIndexListBox->clear();
+#ifdef COMPILE_USE_QT4
+ QProgressDialog* pProgressDialog = new QProgressDialog( __tr2qs("Indexing help files"), __tr2qs("Cancel"), 0,100 );
+#else
+ QProgressDialog* pProgressDialog = new QProgressDialog( __tr2qs("Indexing help files"), __tr2qs("Cancel"), 100 );
+#endif
+ connect(g_pDocIndex,SIGNAL(indexingProgress(int)), pProgressDialog, SLOT(setProgress(int)) );
+ g_pDocIndex->makeIndex();
+ g_pDocIndex->writeDict();
+ g_pDocIndex->writeDocumentList();
+ delete pProgressDialog;
+ g_bIndexingDone=TRUE;
+ QStringList docList=g_pDocIndex->titlesList();
+ m_pIndexListBox->insertStringList(docList);
+ m_pIndexListBox->sort();
+}
+
+void KviHelpWindow::startSearch()
+{
+
+ QString str = m_pTermsEdit->text();
+ str = str.replace( "\'", "\"" );
+ str = str.replace( "`", "\"" );
+ QString buf = str;
+ str = str.replace( "-", " " );
+ str = str.replace( QRegExp( "\\s[\\S]?\\s" ), " " );
+ m_terms = QStringList::split( " ", str );
+ QStringList termSeq;
+ QStringList seqWords;
+ QStringList::iterator it = m_terms.begin();
+ for ( ; it != m_terms.end(); ++it ) {
+ (*it) = (*it).simplifyWhiteSpace();
+ (*it) = (*it).lower();
+ (*it) = (*it).replace( "\"", "" );
+ }
+ if ( str.contains( '\"' ) ) {
+#ifdef COMPILE_USE_QT4
+ if ( (str.count( '\"' ))%2 == 0 ) {
+#else
+ if ( (str.contains( '\"' ))%2 == 0 ) {
+#endif
+ int beg = 0;
+ int end = 0;
+ QString s;
+ beg = str.find( '\"', beg );
+ while ( beg != -1 ) {
+ beg++;
+ end = str.find( '\"', beg );
+ s = str.mid( beg, end - beg );
+ s = s.lower();
+ s = s.simplifyWhiteSpace();
+ if ( s.contains( '*' ) ) {
+ QMessageBox::warning( this, tr( "Full Text Search" ),
+ tr( "Using a wildcard within phrases is not allowed." ) );
+ return;
+ }
+ seqWords += QStringList::split( ' ', s );
+ termSeq << s;
+ beg = str.find( '\"', end + 1);
+ }
+ } else {
+ QMessageBox::warning( this, tr( "Full Text Search" ),
+ tr( "The closing quotation mark is missing." ) );
+ return;
+ }
+ }
+#ifdef COMPILE_USE_QT4
+ setCursor( Qt::WaitCursor );
+#else
+ setCursor( waitCursor );
+#endif
+ m_foundDocs.clear();
+ m_foundDocs = g_pDocIndex->query( m_terms, termSeq, seqWords );
+
+ m_pResultBox->clear();
+ for ( it = m_foundDocs.begin(); it != m_foundDocs.end(); ++it )
+ m_pResultBox->insertItem( g_pDocIndex->getDocumentTitle( *it ) );
+
+ m_terms.clear();
+ bool isPhrase = FALSE;
+ QString s = "";
+ for ( int i = 0; i < (int)buf.length(); ++i ) {
+ if ( buf[i] == '\"' ) {
+ isPhrase = !isPhrase;
+ s = s.simplifyWhiteSpace();
+ if ( !s.isEmpty() )
+ m_terms << s;
+ s = "";
+ } else if ( buf[i] == ' ' && !isPhrase ) {
+ s = s.simplifyWhiteSpace();
+ if ( !s.isEmpty() )
+ m_terms << s;
+ s = "";
+ } else
+ s += buf[i];
+ }
+ if ( !s.isEmpty() )
+ m_terms << s;
+
+#ifdef COMPILE_USE_QT4
+ setCursor( Qt::ArrowCursor );
+#else
+ setCursor( arrowCursor );
+#endif
+}
+
+QTextBrowser * KviHelpWindow::textBrowser()
+{
+ return m_pHelpWidget->textBrowser();
+}
+
+void KviHelpWindow::showIndexTopic()
+{
+ if (m_pIndexSearch->text().isEmpty()|| !m_pIndexListBox->selectedItem()) return;
+ int i=g_pDocIndex->titlesList().findIndex(m_pIndexListBox->selectedItem()->text());
+ textBrowser()->setSource(g_pDocIndex->documentList()[ i ]);
+}
+
+void KviHelpWindow::searchInIndex( const QString &s )
+{
+ KviTalListBoxItem *i = m_pIndexListBox->firstItem();
+ QString sl = s.lower();
+ while ( i ) {
+ QString t = i->text();
+ if ( t.length() >= sl.length() &&
+ i->text().left(s.length()).lower() == sl ) {
+ m_pIndexListBox->setCurrentItem( i );
+ m_pIndexListBox->setTopItem(m_pIndexListBox->index(i));
+ break;
+ }
+ i = i->next();
+ }
+}
+
+void KviHelpWindow::indexSelected ( int index )
+{
+ int i=g_pDocIndex->titlesList().findIndex(m_pIndexListBox->text(index));
+ textBrowser()->setSource(g_pDocIndex->documentList()[ i ]);
+}
+
+void KviHelpWindow::searchSelected ( int index )
+{
+ int i=g_pDocIndex->titlesList().findIndex(m_pResultBox->text(index));
+ textBrowser()->setSource(g_pDocIndex->documentList()[ i ]);
+}
+
+QPixmap * KviHelpWindow::myIconPtr()
+{
+ return g_pIconManager->getSmallIcon(KVI_SMALLICON_MDIHELP);
+}
+
+void KviHelpWindow::resizeEvent(QResizeEvent *e)
+{
+ m_pSplitter->setGeometry(0,0,width(),height());
+}
+
+QSize KviHelpWindow::sizeHint() const
+{
+ return m_pHelpWidget->sizeHint();
+}
+void KviHelpWindow::fillCaptionBuffers()
+{
+ m_szPlainTextCaption = __tr2qs("Help Browser");
+
+ m_szHtmlActiveCaption = "<nobr><font color=\"";
+ m_szHtmlActiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextActive).name();
+ m_szHtmlActiveCaption += "\"><b>";
+ m_szHtmlActiveCaption += m_szPlainTextCaption;
+ m_szHtmlActiveCaption += "</b></font></nobr>";
+
+
+ m_szHtmlInactiveCaption = "<nobr><font color=\"";
+ m_szHtmlInactiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextInactive).name();
+ m_szHtmlInactiveCaption += "\"><b>";
+ m_szHtmlInactiveCaption += m_szPlainTextCaption;
+ m_szHtmlInactiveCaption += "</b></font></nobr>";
+}
+
+
+#include "helpwindow.moc"
diff --git a/src/modules/help/helpwindow.h b/src/modules/help/helpwindow.h
new file mode 100644
index 00000000..70f27af6
--- /dev/null
+++ b/src/modules/help/helpwindow.h
@@ -0,0 +1,75 @@
+#ifndef _HELPWINDOW_H_
+#define _HELPWINDOW_H_
+//
+// File : helpwindow.h
+// Creation date : Fri Aug 11 2000 18:05:59 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_window.h"
+#include "kvi_string.h"
+#include "kvi_tal_vbox.h"
+#include <qtabwidget.h>
+#include "kvi_tal_listbox.h"
+#include <qlineedit.h>
+#include <qprogressdialog.h>
+
+class KviHelpWidget;
+class QTextBrowser;
+
+class KviHelpWindow : public KviWindow
+{
+ Q_OBJECT
+public:
+ KviHelpWindow(KviFrame * lpFrm,const char * name);
+ ~KviHelpWindow();
+protected:
+ KviHelpWidget * m_pHelpWidget;
+ KviTalVBox * m_pToolBar;
+ QTabWidget * m_pTabWidget;
+ KviTalVBox * m_pIndexTab;
+ KviTalVBox * m_pSearchTab;
+
+ KviTalListBox * m_pIndexListBox;
+ QLineEdit * m_pIndexSearch;
+ QStringList m_foundDocs;
+ QStringList m_terms;
+ KviTalListBox * m_pResultBox;
+ QLineEdit * m_pTermsEdit;
+public:
+ KviHelpWidget * helpWidget(){ return m_pHelpWidget; };
+protected:
+ virtual QPixmap * myIconPtr();
+ virtual void fillCaptionBuffers();
+ virtual void resizeEvent(QResizeEvent *e);
+ virtual void saveProperties(KviConfig * cfg);
+ virtual void loadProperties(KviConfig * cfg);
+public:
+ virtual QSize sizeHint() const;
+ QTextBrowser * textBrowser();
+public slots:
+ void indexSelected ( int );
+ void searchInIndex( const QString &s );
+ void showIndexTopic();
+ void startSearch();
+ void searchSelected ( int index );
+ void refreshIndex();
+};
+
+#endif //_KVI_HELPWINDOW_H_
diff --git a/src/modules/help/index.cpp b/src/modules/help/index.cpp
new file mode 100755
index 00000000..659ff44c
--- /dev/null
+++ b/src/modules/help/index.cpp
@@ -0,0 +1,854 @@
+#include "index.h"
+
+#include "kvi_file.h"
+#include <qdir.h>
+#include <qstringlist.h>
+#include "kvi_pointerhashtable.h"
+#include <qapplication.h>
+#include <qtextstream.h>
+#include <ctype.h>
+
+
+int kvi_compare(const Term * p1,const Term * p2)
+{
+ if(p1->frequency == p2->frequency)
+ return 0;
+ if(p1->frequency < p2->frequency)
+ return -1;
+ return 1;
+}
+
+QDataStream &operator>>( QDataStream &s, Document &l )
+{
+ s >> l.docNumber;
+ s >> l.frequency;
+ return s;
+}
+
+QDataStream &operator<<( QDataStream &s, const Document &l )
+{
+ s << (Q_INT16)l.docNumber;
+ s << (Q_INT16)l.frequency;
+ return s;
+}
+
+Index::Index( const QString &dp, const QString &hp )
+
+ : QObject( 0, 0 ), dict( 8999 ), docPath( dp )
+
+{
+ alreadyHaveDocList = FALSE;
+ lastWindowClosed = FALSE;
+ connect( qApp, SIGNAL( lastWindowClosed() ),
+ this, SLOT( setLastWinClosed() ) );
+}
+
+
+
+Index::Index( const QStringList &dl, const QString &hp )
+
+ : QObject( 0, 0 ), dict( 8999 )
+
+{
+ docList = dl;
+ alreadyHaveDocList = TRUE;
+ lastWindowClosed = FALSE;
+ connect( qApp, SIGNAL( lastWindowClosed() ),
+ this, SLOT( setLastWinClosed() ) );
+}
+
+
+
+void Index::setLastWinClosed()
+
+{
+
+ lastWindowClosed = TRUE;
+
+}
+
+
+
+void Index::setDictionaryFile( const QString &f )
+
+{
+
+ dictFile = f;
+
+}
+
+
+
+void Index::setDocListFile( const QString &f )
+{
+ docListFile = f;
+}
+
+
+
+int Index::makeIndex()
+{
+ if ( !alreadyHaveDocList )
+ setupDocumentList();
+ if ( docList.isEmpty() )
+ return 1;
+ dict.clear();
+ QStringList::Iterator it = docList.begin();
+ int steps = docList.count() / 100;
+ if ( !steps )
+ steps++;
+ int prog = 0;
+ for ( int i = 0; it != docList.end(); ++it, ++i ) {
+ if ( lastWindowClosed ) {
+ return -1;
+ }
+ parseDocument( *it, i );
+ if ( i%steps == 0 ) {
+ prog++;
+ emit indexingProgress( prog );
+ }
+ }
+ return 0;
+}
+
+
+
+void Index::setupDocumentList()
+
+{
+ docList.clear();
+ titleList.clear();
+ QDir d( docPath );
+ QString szCur;
+ QStringList lst = d.entryList( "*.html" );
+ QStringList::ConstIterator it = lst.begin();
+ for ( ; it != lst.end(); ++it )
+ {
+ szCur=docPath + "/" + *it;
+ docList.append( szCur );
+ titleList.append(getDocumentTitle( szCur ));
+ }
+}
+
+
+
+void Index::insertInDict( const QString &str, int docNum )
+{
+ if ( strcmp( str, "amp" ) == 0 || strcmp( str, "nbsp" ) == 0 )
+ return;
+ Entry *e = 0;
+ if ( dict.count() )
+ e = dict[ str ];
+
+ if ( e ) {
+ if ( e->documents.first().docNumber != docNum )
+ e->documents.prepend( Document( docNum, 1 ) );
+ else
+ e->documents.first().frequency++;
+ } else {
+ dict.insert( str, new Entry( docNum ) );
+ }
+}
+
+
+
+void Index::parseDocument( const QString &filename, int docNum )
+{
+ KviFile file( filename );
+ if ( !file.openForReading() ) {
+ qWarning( "can not open file " + filename );
+ return;
+ }
+ QTextStream s( &file );
+ QString text = s.read();
+ if (text.isNull())
+ return;
+ bool valid = TRUE;
+ const QChar *buf = text.unicode();
+ QChar str[64];
+ QChar c = buf[0];
+ int j = 0;
+ int i = 0;
+ while ( (uint)j < text.length() ) {
+ if ( c == '<' || c == '&' ) {
+ valid = FALSE;
+ if ( i > 1 )
+ insertInDict( QString(str,i), docNum );
+ i = 0;
+ c = buf[++j];
+ continue;
+ }
+ if ( ( c == '>' || c == ';' ) && !valid ) {
+ valid = TRUE;
+ c = buf[++j];
+ continue;
+ }
+
+ if ( !valid ) {
+
+ c = buf[++j];
+
+ continue;
+
+ }
+
+ if ( ( c.isLetterOrNumber() || c == '_' ) && i < 63 ) {
+
+ str[i] = c.lower();
+
+ ++i;
+
+ } else {
+
+ if ( i > 1 )
+
+ insertInDict( QString(str,i), docNum );
+
+ i = 0;
+
+ }
+
+ c = buf[++j];
+
+ }
+
+ if ( i > 1 )
+
+ insertInDict( QString(str,i), docNum );
+
+ file.close();
+
+}
+
+
+
+void Index::writeDict()
+
+{
+
+ KviPointerHashTableIterator<QString,Entry> it( dict );
+
+ KviFile f( dictFile );
+
+ if ( !f.openForWriting() )
+
+ return;
+
+ QDataStream s( &f );
+
+ for( ; it.current(); ++it ) {
+
+ Entry *e = it.current();
+
+ s << it.currentKey();
+
+ s << e->documents;
+
+ }
+
+ f.close();
+
+ writeDocumentList();
+
+}
+
+
+
+void Index::writeDocumentList()
+
+{
+ KviFile f( docListFile );
+ if ( !f.openForWriting() )
+ return;
+ QTextStream s( &f );
+ QString docs = docList.join("[#item#]");
+ s << docs;
+
+ KviFile f1( docListFile+".titles" );
+ if ( !f1.openForWriting() )
+ return;
+ QTextStream s1( &f1 );
+ docs = titleList.join("[#item#]");
+ s1 << docs;
+}
+
+
+
+void Index::readDict()
+
+{
+ KviFile f( dictFile );
+ if ( !f.openForReading() )
+ return;
+ dict.clear();
+ QDataStream s( &f );
+ QString key;
+ KviValueList<Document> docs;
+ while ( !s.atEnd() ) {
+ s >> key;
+ s >> docs;
+ dict.insert( key, new Entry( docs ) );
+ }
+ f.close();
+ readDocumentList();
+}
+
+
+
+void Index::readDocumentList()
+{
+ //reading docs
+ KviFile f( docListFile );
+ if ( !f.openForReading() )
+ return;
+ QTextStream s( &f );
+ docList = QStringList::split("[#item#]",s.read());
+
+ //reading titles
+ KviFile f1( docListFile+".titles" );
+ if ( !f1.openForReading() )
+ return;
+ QTextStream s1( &f1 );
+ titleList = QStringList::split("[#item#]",s1.read());
+// debug(titleList);
+}
+
+
+
+QStringList Index::query( const QStringList &terms, const QStringList &termSeq, const QStringList &seqWords )
+
+{
+
+ TermList termList;
+
+
+
+ QStringList::ConstIterator it = terms.begin();
+
+ for ( it = terms.begin(); it != terms.end(); ++it ) {
+
+ Entry *e = 0;
+
+ if ( (*it).contains( '*' ) ) {
+
+ KviValueList<Document> wcts = setupDummyTerm( getWildcardTerms( *it ) );
+
+ termList.append( new Term( "dummy", wcts.count(), wcts ) );
+
+ } else if ( dict[ *it ] ) {
+
+ e = dict[ *it ];
+
+ termList.append( new Term( *it, e->documents.count(), e->documents ) );
+
+ } else {
+
+ return QStringList();
+
+ }
+
+ }
+
+ termList.sort();
+
+
+
+ Term *minTerm = termList.first();
+
+ if ( !termList.count() )
+
+ return QStringList();
+
+ termList.removeFirst();
+
+
+
+ KviValueList<Document> minDocs = minTerm->documents;
+
+ KviValueList<Document>::iterator C;
+
+ KviValueList<Document>::ConstIterator It;
+
+ Term *t = termList.first();
+
+ for ( ; t; t = termList.next() ) {
+
+ KviValueList<Document> docs = t->documents;
+
+ C = minDocs.begin();
+
+ while ( C != minDocs.end() ) {
+
+ bool found = FALSE;
+
+ for ( It = docs.begin(); It != docs.end(); ++It ) {
+
+ if ( (*C).docNumber == (*It).docNumber ) {
+
+ (*C).frequency += (*It).frequency;
+
+ found = TRUE;
+
+ break;
+
+ }
+
+ }
+
+ if ( !found )
+
+ C = minDocs.remove( C );
+
+ else
+
+ ++C;
+
+ }
+
+ }
+
+
+
+ QStringList results;
+
+#ifndef COMPILE_USE_QT4
+ qHeapSort( minDocs );
+#endif
+ if ( termSeq.isEmpty() ) {
+
+ for ( C = minDocs.begin(); C != minDocs.end(); ++C )
+
+ results << docList[ (int)(*C).docNumber ];
+
+ return results;
+
+ }
+
+
+
+ QString fileName;
+
+ for ( C = minDocs.begin(); C != minDocs.end(); ++C ) {
+
+ fileName = docList[ (int)(*C).docNumber ];
+
+ if ( searchForPattern( termSeq, seqWords, fileName ) )
+
+ results << fileName;
+
+ }
+
+ return results;
+
+}
+
+
+
+QString Index::getDocumentTitle( const QString &fileName )
+
+{
+
+ KviFile file( fileName );
+
+ if ( !file.openForReading() ) {
+
+ qWarning( "cannot open file " + fileName );
+
+ return fileName;
+
+ }
+
+ QTextStream s( &file );
+
+ QString text = s.read();
+
+
+
+ int start = text.find( "<title>", 0, FALSE ) + 7;
+
+ int end = text.find( "</title>", 0, FALSE );
+
+
+
+ QString title = ( end - start <= 0 ? tr("Untitled") : text.mid( start, end - start ) );
+
+ return title;
+
+}
+
+
+
+QStringList Index::getWildcardTerms( const QString &term )
+
+{
+
+ QStringList lst;
+
+ QStringList terms = split( term );
+
+#ifdef COMPILE_USE_QT4
+ QStringList::Iterator iter;
+#else
+ KviValueList<QString>::iterator iter;
+#endif
+
+
+ KviPointerHashTableIterator<QString,Entry> it( dict );
+
+ for( ; it.current(); ++it ) {
+
+ int index = 0;
+
+ bool found = FALSE;
+
+ QString text( it.currentKey() );
+
+ for ( iter = terms.begin(); iter != terms.end(); ++iter ) {
+
+ if ( *iter == "*" ) {
+
+ found = TRUE;
+
+ continue;
+
+ }
+
+ if ( iter == terms.begin() && (*iter)[0] != text[0] ) {
+
+ found = FALSE;
+
+ break;
+
+ }
+
+ index = text.find( *iter, index );
+
+ if ( *iter == terms.last() && index != (int)text.length()-1 ) {
+
+ index = text.findRev( *iter );
+
+ if ( index != (int)text.length() - (int)(*iter).length() ) {
+
+ found = FALSE;
+
+ break;
+
+ }
+
+ }
+
+ if ( index != -1 ) {
+
+ found = TRUE;
+
+ index += (*iter).length();
+
+ continue;
+
+ } else {
+
+ found = FALSE;
+
+ break;
+
+ }
+
+ }
+
+ if ( found )
+
+ lst << text;
+
+ }
+
+
+
+ return lst;
+
+}
+
+
+
+QStringList Index::split( const QString &str )
+
+{
+
+ QStringList lst;
+
+ int j = 0;
+
+ int i = str.find( '*', j );
+
+
+
+ while ( i != -1 ) {
+
+ if ( i > j && i <= (int)str.length() ) {
+
+ lst << str.mid( j, i - j );
+
+ lst << "*";
+
+ }
+
+ j = i + 1;
+
+ i = str.find( '*', j );
+
+ }
+
+
+
+ int l = str.length() - 1;
+
+ if ( str.mid( j, l - j + 1 ).length() > 0 )
+
+ lst << str.mid( j, l - j + 1 );
+
+
+
+ return lst;
+
+}
+
+
+
+KviValueList<Document> Index::setupDummyTerm( const QStringList &terms )
+
+{
+
+ TermList termList;
+
+ QStringList::ConstIterator it = terms.begin();
+
+ for ( ; it != terms.end(); ++it ) {
+
+ Entry *e = 0;
+
+ if ( dict[ *it ] ) {
+
+ e = dict[ *it ];
+
+ termList.append( new Term( *it, e->documents.count(), e->documents ) );
+
+ }
+
+ }
+
+ termList.sort();
+
+
+
+ KviValueList<Document> maxList;
+
+
+
+ if ( !termList.count() )
+
+ return maxList;
+
+ maxList = termList.last()->documents;
+
+ termList.removeLast();
+
+
+
+ KviValueList<Document>::iterator docIt;
+
+ Term *t = termList.first();
+
+ while ( t ) {
+
+ KviValueList<Document> docs = t->documents;
+
+ for ( docIt = docs.begin(); docIt != docs.end(); ++docIt ) {
+
+ if ( maxList.findIndex( *docIt ) == -1 )
+
+ maxList.append( *docIt );
+
+ }
+
+ t = termList.next();
+
+ }
+
+ return maxList;
+
+}
+
+
+
+void Index::buildMiniDict( const QString &str )
+
+{
+
+ if ( miniDict[ str ] )
+
+ miniDict[ str ]->positions.append( wordNum );
+
+ ++wordNum;
+
+}
+
+
+
+bool Index::searchForPattern( const QStringList &patterns, const QStringList &words, const QString &fileName )
+
+{
+
+ KviFile file( fileName );
+
+ if ( !file.openForReading() ) {
+
+ qWarning( "cannot open file " + fileName );
+
+ return FALSE;
+
+ }
+
+
+
+ wordNum = 3;
+
+ miniDict.clear();
+
+ QStringList::ConstIterator cIt = words.begin();
+
+ for ( ; cIt != words.end(); ++cIt )
+
+ miniDict.insert( *cIt, new PosEntry( 0 ) );
+
+
+
+ QTextStream s( &file );
+
+ QString text = s.read();
+
+ bool valid = TRUE;
+
+ const QChar *buf = text.unicode();
+
+ QChar str[64];
+
+ QChar c = buf[0];
+
+ int j = 0;
+
+ int i = 0;
+
+ while ( (uint)j < text.length() ) {
+
+ if ( c == '<' || c == '&' ) {
+
+ valid = FALSE;
+
+ if ( i > 1 )
+
+ buildMiniDict( QString(str,i) );
+
+ i = 0;
+
+ c = buf[++j];
+
+ continue;
+
+ }
+
+ if ( ( c == '>' || c == ';' ) && !valid ) {
+
+ valid = TRUE;
+
+ c = buf[++j];
+
+ continue;
+
+ }
+
+ if ( !valid ) {
+
+ c = buf[++j];
+
+ continue;
+
+ }
+
+ if ( ( c.isLetterOrNumber() || c == '_' ) && i < 63 ) {
+
+ str[i] = c.lower();
+
+ ++i;
+
+ } else {
+
+ if ( i > 1 )
+
+ buildMiniDict( QString(str,i) );
+
+ i = 0;
+
+ }
+
+ c = buf[++j];
+
+ }
+
+ if ( i > 1 )
+
+ buildMiniDict( QString(str,i) );
+
+ file.close();
+
+
+
+ QStringList::ConstIterator patIt = patterns.begin();
+
+ QStringList wordLst;
+
+ KviValueList<uint> a, b;
+
+ KviValueList<uint>::iterator aIt;
+
+ for ( ; patIt != patterns.end(); ++patIt ) {
+
+ wordLst = QStringList::split( ' ', *patIt );
+
+ a = miniDict[ wordLst[0] ]->positions;
+
+ for ( int j = 1; j < (int)wordLst.count(); ++j ) {
+
+ b = miniDict[ wordLst[j] ]->positions;
+
+ aIt = a.begin();
+
+ while ( aIt != a.end() ) {
+
+ if ( b.find( *aIt + 1 ) != b.end() ) {
+
+ (*aIt)++;
+
+ ++aIt;
+
+ } else {
+
+ aIt = a.remove( aIt );
+
+ }
+
+ }
+
+ }
+
+ }
+
+ if ( a.count() )
+
+ return TRUE;
+
+ return FALSE;
+
+}
+
+
+
+#include "index.moc" \ No newline at end of file
diff --git a/src/modules/help/index.h b/src/modules/help/index.h
new file mode 100755
index 00000000..9debcb3e
--- /dev/null
+++ b/src/modules/help/index.h
@@ -0,0 +1,124 @@
+/**********************************************************************
+** Copyright (C) 2000-2003 Trolltech AS. All rights reserved.
+**
+** This file is part of the Qt Assistant.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
+** licenses may use this file in accordance with the Qt Commercial License
+** Agreement provided with the Software.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
+** information about Qt Commercial License Agreements.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+
+
+#ifndef INDEX_H
+#define INDEX_H
+
+#include <qstringlist.h>
+#include "kvi_pointerhashtable.h"
+#include "kvi_pointerlist.h"
+#include "kvi_valuelist.h"
+#include <qdatastream.h>
+#include <qobject.h>
+
+struct Document {
+ Document( int d, int f ) : docNumber( d ), frequency( f ) {}
+ Document() : docNumber( -1 ), frequency( 0 ) {}
+ bool operator==( const Document &doc ) const {
+ return docNumber == doc.docNumber;
+ }
+ bool operator<( const Document &doc ) const {
+ return frequency > doc.frequency;
+ }
+ bool operator<=( const Document &doc ) const {
+ return frequency >= doc.frequency;
+ }
+ bool operator>( const Document &doc ) const {
+ return frequency < doc.frequency;
+ }
+ Q_INT16 docNumber;
+ Q_INT16 frequency;
+};
+
+QDataStream &operator>>( QDataStream &s, Document &l );
+QDataStream &operator<<( QDataStream &s, const Document &l );
+
+class Index : public QObject
+{
+ Q_OBJECT
+public:
+ struct Entry {
+ Entry( int d ) { documents.append( Document( d, 1 ) ); }
+ Entry( KviValueList<Document> l ) : documents( l ) {}
+ KviValueList<Document> documents;
+ };
+ struct PosEntry {
+ PosEntry( int p ) { positions.append( p ); }
+ KviValueList<uint> positions;
+ };
+ Index( const QString &dp, const QString &hp );
+ Index( const QStringList &dl, const QString &hp );
+ void writeDict();
+ void readDict();
+ int makeIndex();
+ QStringList query( const QStringList&, const QStringList&, const QStringList& );
+ QString getDocumentTitle( const QString& );
+ void setDictionaryFile( const QString& );
+ void setDocListFile( const QString& );
+ void writeDocumentList();
+ void readDocumentList();
+ void setupDocumentList();
+ const QStringList& documentList() { return docList; };
+ const QStringList& titlesList() { return titleList; };
+signals:
+ void indexingProgress( int );
+private slots:
+ void setLastWinClosed();
+private:
+ void parseDocument( const QString&, int );
+ void insertInDict( const QString&, int );
+ QStringList getWildcardTerms( const QString& );
+ QStringList split( const QString& );
+ KviValueList<Document> setupDummyTerm( const QStringList& );
+ bool searchForPattern( const QStringList&, const QStringList&, const QString& );
+ void buildMiniDict( const QString& );
+ QStringList docList;
+ QStringList titleList;
+ KviPointerHashTable<QString,Entry> dict;
+ KviPointerHashTable<QString,PosEntry> miniDict;
+ uint wordNum;
+ QString docPath;
+ QString dictFile, docListFile;
+ bool alreadyHaveDocList;
+ bool lastWindowClosed;
+};
+
+struct Term {
+ Term( const QString &t, int f, KviValueList<Document> l )
+ : term( t ), frequency( f ), documents( l ) {}
+ QString term;
+ int frequency;
+ KviValueList<Document>documents;
+};
+
+
+
+#define TermList KviPointerList<Term>
+
+#endif
+
diff --git a/src/modules/help/libkvihelp.cpp b/src/modules/help/libkvihelp.cpp
new file mode 100644
index 00000000..c8da3c33
--- /dev/null
+++ b/src/modules/help/libkvihelp.cpp
@@ -0,0 +1,236 @@
+//
+// File : libkvihelp.cpp
+// Creation date : Sun Aug 13 2000 03:00:00 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+//#include "libkvihelp.h"
+
+#include "kvi_module.h"
+
+#include "kvi_sourcesdate.h"
+
+#include "helpwidget.h"
+#include "helpwindow.h"
+#include "index.h"
+#include "kvi_app.h"
+
+#include "kvi_frame.h"
+
+#ifdef COMPILE_USE_QT4
+ #include <q3mimefactory.h>
+#endif
+
+
+#include <qsplitter.h>
+Index * g_pDocIndex = 0;
+KviPointerList<KviHelpWidget> * g_pHelpWidgetList = 0;
+KviPointerList<KviHelpWindow> * g_pHelpWindowList = 0;
+
+/*
+ @doc: help.search
+ @type:
+ command
+ @title:
+ help.search
+ @short:
+ Searches the documentation
+ @syntax:
+ help.search [-n] [-m] <key terms>
+ @description:
+ Finds the first available help browser in the current frame
+ then searches the documentation for the specified <key terms>.
+ If no help browser is available it creates one first:
+ if the -m switch is present, the created browser is a MDI window,
+ otherwise it is a static window.
+ If the -n switch is present, the window creation is forced even
+ if there are other help browsers already open.[br]
+ The <key terms> are [b]space separated words[/b]
+ to be matched inside the document body (logical AND).[br]
+ This command is exported by the "help" module.
+*/
+
+/*tatic bool help_module_cmd_search(KviModule *m,KviCommand *c)
+{
+ ENTER_STACK_FRAME(c,"help_module_cmd_search");
+
+ KviStr keys;
+ if(!g_pZZZZZZUserParser->parseCmdFinalPart(c,keys))return false;
+
+ if(keys.isEmpty())keys = "kvirc";
+
+ if(!c->hasSwitch('n'))
+ {
+ // look for an already open help widget in this frame
+ KviHelpWidget * w = (KviHelpWidget *)c->window()->frame()->child(
+ "help_widget","KviHelpWidget");
+
+ if(w)
+ {
+ w->doExactSearchFor(keys.ptr());
+ return c->leaveStackFrame();
+ }
+ }
+
+ if(c->hasSwitch('m'))
+ {
+ KviHelpWindow *w = new KviHelpWindow(c->window()->frame(),"Help browser");
+ w->helpWidget()->doExactSearchFor(keys.ptr());
+ c->window()->frame()->addWindow(w);
+ } else {
+ KviHelpWidget *w = new KviHelpWidget(c->window()->frame()->splitter(),
+ c->window()->frame(),true);
+ w->doExactSearchFor(keys.ptr());
+ w->show();
+ }
+
+ return c->leaveStackFrame();
+}*/
+/*
+#ifdef COMPILE_NEW_KVS
+static bool help_kvs_cmd_search(KviKvsModuleCommandCall * c)
+{
+}
+#endif
+*/
+/*
+ @doc: help.open
+ @type:
+ command
+ @title:
+ help.open
+ @short:
+ Shows a help document
+ @syntax:
+ help.open [-n] [-m] [document: string]
+ @description:
+ Finds the first available help browser in the current frame
+ then opens the specified [document].
+ If no [document] is specified it the documentation index is shown.
+ If no help browser is available , a new one is created.
+ [document] can be an absolute path or a relative one: in this case
+ the document is searched in the KVIrc documentation directory.[br]
+ The help browser has limited html browsing capabilities: you can
+ use it to view simple html files on your filesystem.[br]
+ This command is exported by the "help" module.
+ @switches:
+ !sw: -m | --mdi
+ The created browser is a MDI window,
+ otherwise it is a static window.
+ !sw: -n | --new
+ The window creation is forced even
+ if there are other help browsers already open.[br]
+*/
+
+
+static bool help_kvs_cmd_open(KviKvsModuleCommandCall * c)
+{
+ QString doc;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("document",KVS_PT_STRING,KVS_PF_OPTIONAL,doc)
+ KVSM_PARAMETERS_END(c)
+ if(doc.isEmpty())doc = "index.html";
+#ifdef COMPILE_USE_QT4
+ Q3MimeSourceFactory * f = Q3MimeSourceFactory::defaultFactory();
+#else
+ QMimeSourceFactory * f = QMimeSourceFactory::defaultFactory();
+#endif
+ if(f)
+ {
+ if(!f->data(doc))
+ doc = "nohelpavailable.html";
+ }
+
+ if(!c->switches()->find('n',"new"))
+ {
+ KviHelpWidget * w = (KviHelpWidget *)c->window()->frame()->child("help_widget","KviHelpWidget");
+ if(w)
+ {
+ w->textBrowser()->setSource(doc);
+ return true;
+ }
+ }
+ if(c->switches()->find('m',"mdi"))
+ {
+ KviHelpWindow *w = new KviHelpWindow(c->window()->frame(),"Help browser");
+ w->textBrowser()->setSource(doc);
+ c->window()->frame()->addWindow(w);
+ } else {
+ KviHelpWidget *w = new KviHelpWidget(c->window()->frame()->splitter(),
+ c->window()->frame(),true);
+ w->textBrowser()->setSource(doc);
+ w->show();
+ //debug ("mostro");
+ }
+ return true;
+}
+
+
+
+static bool help_module_init(KviModule * m)
+{
+ QString szHelpDir,szDocList;
+
+ g_pApp->getLocalKvircDirectory(szDocList,KviApp::Help,"help.doclist." KVI_SOURCES_DATE);
+ g_pApp->getGlobalKvircDirectory(szHelpDir,KviApp::Help);
+
+ g_pDocIndex = new Index(szHelpDir,szDocList);
+ g_pDocIndex->setDocListFile(szDocList);
+
+ g_pApp->getLocalKvircDirectory(szHelpDir,KviApp::Help,"help.dict." KVI_SOURCES_DATE);
+ g_pDocIndex->setDictionaryFile(szHelpDir);
+
+ g_pHelpWidgetList = new KviPointerList<KviHelpWidget>;
+ g_pHelpWidgetList->setAutoDelete(false);
+ g_pHelpWindowList = new KviPointerList<KviHelpWindow>;
+ g_pHelpWindowList->setAutoDelete(false);
+
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"open",help_kvs_cmd_open);
+
+
+ return true;
+}
+
+static bool help_module_cleanup(KviModule *m)
+{
+ if(g_pDocIndex) delete g_pDocIndex;
+ while(g_pHelpWidgetList->first())delete g_pHelpWidgetList->first();
+ delete g_pHelpWidgetList;
+ g_pHelpWidgetList = 0;
+ while(g_pHelpWindowList->first())g_pHelpWindowList->first()->close();
+ delete g_pHelpWindowList;
+ g_pHelpWindowList = 0;
+ return true;
+}
+
+static bool help_module_can_unload(KviModule *m)
+{
+ return (g_pHelpWidgetList->isEmpty() && g_pHelpWindowList->isEmpty());
+}
+
+KVIRC_MODULE(
+ "Help", // module name
+ "1.0.0", // module version
+ "Copyright (C) 2000 Szymon Stefanek (pragma at kvirc dot net)", // author & (C)
+ "Help browser extension",
+ help_module_init,
+ help_module_can_unload,
+ 0,
+ help_module_cleanup
+)
diff --git a/src/modules/http/Makefile.am b/src/modules/http/Makefile.am
new file mode 100644
index 00000000..ab7fe3b2
--- /dev/null
+++ b/src/modules/http/Makefile.am
@@ -0,0 +1,26 @@
+###############################################################################
+# KVirc IRC client Makefile - 31.01.2002 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+tmpdir=$(picsdir)
+
+tmp_DATA=kvi_httpicons.png
+
+EXTRA_DIST=kvi_httpicons.png
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkvihttp.la
+
+libkvihttp_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkvihttp_la_SOURCES = libkvihttp.cpp httpfiletransfer.cpp
+libkvihttp_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+noinst_HEADERS= httpfiletransfer.h
+
+m_%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
+
+httpfiletransfer.cpp: m_httpfiletransfer.moc
diff --git a/src/modules/http/httpfiletransfer.cpp b/src/modules/http/httpfiletransfer.cpp
new file mode 100644
index 00000000..09c3b1f9
--- /dev/null
+++ b/src/modules/http/httpfiletransfer.cpp
@@ -0,0 +1,489 @@
+//==================================================================================
+//
+// File : httpfiletransfer.h
+// Creation date : Tue Apr 22 2003 02:00:12 GMT by Szymon Stefanek
+//
+// This config is part of the KVirc irc client distribution
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//==================================================================================
+#include "httpfiletransfer.h"
+
+#include "kvi_app.h"
+#include "kvi_out.h"
+#include "kvi_locale.h"
+#include "kvi_window.h"
+#include "kvi_iconmanager.h"
+#include "kvi_netutils.h"
+#include "kvi_kvs_eventtriggers.h"
+#include "kvi_console.h"
+
+#include "kvi_kvs_script.h"
+
+#include "kvi_tal_popupmenu.h"
+#include <qpainter.h>
+
+static KviPointerList<KviHttpFileTransfer> * g_pHttpFileTransfers = 0;
+static QPixmap * g_pHttpIcon = 0;
+
+
+KviHttpFileTransfer::KviHttpFileTransfer()
+: KviFileTransfer()
+{
+ init(); // ensure we're initialized
+ g_pHttpFileTransfers->append(this);
+
+ m_tStartTime = kvi_unixTime();
+ m_tTransferStartTime = 0;
+ m_tTransferEndTime = 0;
+
+ m_bNotifyCompletion = true;
+ m_bAutoClean = false;
+ m_pAutoCleanTimer = 0;
+ m_bNoOutput = false;
+
+ m_pHttpRequest = new KviHttpRequest();
+
+ connect(m_pHttpRequest,SIGNAL(status(const QString &)),this,SLOT(statusMessage(const QString &)));
+ connect(m_pHttpRequest,SIGNAL(terminated(bool)),this,SLOT(transferTerminated(bool)));
+ connect(m_pHttpRequest,SIGNAL(header(KviPointerHashTable<const char *,KviStr> *)),this,SLOT(headersReceived(KviPointerHashTable<const char *,KviStr> *)));
+ connect(m_pHttpRequest,SIGNAL(resolvingHost(const QString &)),this,SLOT(resolvingHost(const QString &)));
+ connect(m_pHttpRequest,SIGNAL(requestSent(const QStringList &)),this,SLOT(requestSent(const QStringList &)));
+ connect(m_pHttpRequest,SIGNAL(contactingHost(const QString &)),this,SLOT(contactingHost(const QString &)));
+ connect(m_pHttpRequest,SIGNAL(receivedResponse(const QString &)),this,SLOT(receivedResponse(const QString &)));
+ connect(m_pHttpRequest,SIGNAL(connectionEstabilished()),this,SLOT(connectionEstabilished()));
+
+ m_eGeneralStatus = Initializing;
+ m_szStatusString = __tr2qs_ctx("Initializing","http");
+}
+
+KviHttpFileTransfer::~KviHttpFileTransfer()
+{
+ g_pHttpFileTransfers->removeRef(this);
+ delete m_pHttpRequest;
+ if(m_pAutoCleanTimer)
+ {
+ m_pAutoCleanTimer->stop();
+ delete m_pAutoCleanTimer;
+ }
+}
+
+void KviHttpFileTransfer::autoClean()
+{
+ die();
+}
+
+void KviHttpFileTransfer::die()
+{
+ delete this;
+}
+
+QString KviHttpFileTransfer::localFileName()
+{
+ return m_pHttpRequest->fileName();
+}
+
+void KviHttpFileTransfer::abort()
+{
+ m_pHttpRequest->abort();
+}
+
+void KviHttpFileTransfer::fillContextPopup(KviTalPopupMenu * m,int column)
+{
+ int id = m->insertItem(__tr2qs_ctx("Abort","http"),this,SLOT(abort()));
+ if(!active())m->setItemEnabled(id,false);
+}
+
+bool KviHttpFileTransfer::active()
+{
+ return ((m_eGeneralStatus == Connecting) || (m_eGeneralStatus == Downloading));
+}
+
+void KviHttpFileTransfer::displayPaint(QPainter * p,int column,int width,int height)
+{
+ QString txt;
+ bool bIsTerminated = ((m_eGeneralStatus == Success) || (m_eGeneralStatus == Failure));
+
+ switch(column)
+ {
+ case COLUMN_TRANSFERTYPE:
+ {
+ int offset = 0;
+ switch(m_eGeneralStatus)
+ {
+ case Initializing: offset = 0; break;
+ case Connecting: offset = 0; break;
+ case Downloading: offset = 48; break;
+ case Success: offset = 96; break;
+ case Failure: offset = 144; break;
+ }
+ p->drawPixmap(3,3,*g_pHttpIcon,offset,0,48,64);
+ }
+ break;
+ case COLUMN_FILEINFO:
+ {
+ QFontMetrics fm(p->font());
+
+ QString szFrom = __tr2qs_ctx("From: ","http");
+ QString szTo = __tr2qs_ctx("To: ","http");
+
+ int daW1 = fm.width(szFrom);
+ int daW2 = fm.width(szTo);
+ if(daW1 < daW2)daW1 = daW2;
+ int iLineSpacing = fm.lineSpacing();
+
+ p->setPen(Qt::black);
+
+ int iY = 4;
+
+ p->drawText(4 + daW1,iY,width - (8 + daW1),height - 8,Qt::AlignTop | Qt::AlignLeft,m_pHttpRequest->url().url().ptr());
+ iY += iLineSpacing;
+ if(!(m_pHttpRequest->fileName().isEmpty()))
+ {
+ p->drawText(4 + daW1,iY,width - (8 + daW1),height - 8,Qt::AlignTop | Qt::AlignLeft,m_pHttpRequest->fileName());
+ }
+ iY += iLineSpacing;
+
+
+ p->setPen(Qt::darkGray);
+
+ p->drawText(4,4,width - 8,height - 8,Qt::AlignTop | Qt::AlignLeft,szFrom);
+ p->drawText(4,4 + iLineSpacing,width - 8,height - 8,Qt::AlignTop | Qt::AlignLeft,szTo);
+
+ p->setPen(QColor(180,180,200));
+
+ iLineSpacing += 2;
+
+ p->drawRect(4,height - (iLineSpacing + 4),width - 8,iLineSpacing);
+ p->fillRect(5,height - (iLineSpacing + 3),width - 10,iLineSpacing - 2,bIsTerminated ? QColor(210,210,210) : QColor(190,190,240));
+ p->setPen(Qt::black);
+ p->drawText(7,height - (iLineSpacing + 4),width - 14,iLineSpacing,Qt::AlignVCenter | Qt::AlignLeft,m_szStatusString);
+ }
+ break;
+ case COLUMN_PROGRESS:
+ {
+ QFontMetrics fm(p->font());
+
+ unsigned int uTotal = m_pHttpRequest->totalSize();
+ unsigned int uRecvd = m_pHttpRequest->receivedSize();
+ int iW = width - 8;
+
+ p->setPen(bIsTerminated ? Qt::lightGray : QColor(210,210,240));
+ p->drawRect(4,4,iW,12);
+
+ int iAvgSpeed = -1;
+ int iEta = -1;
+
+ if(m_tTransferStartTime > 0)
+ {
+ int tSpan = kvi_timeSpan(m_tTransferEndTime > 0 ? m_tTransferEndTime : kvi_unixTime(),m_tTransferStartTime);
+ if(tSpan > 0)
+ {
+ //debug("SPAN: %d (%d - %d)",tSpan,m_tTransferEndTime > 0 ? m_tTransferEndTime : kvi_unixTime(),m_tTransferStartTime);
+ iAvgSpeed = uRecvd / tSpan;
+ if(!bIsTerminated && (uTotal >= uRecvd))
+ {
+ unsigned int uRemaining = uTotal - uRecvd;
+ iEta = uRemaining / iAvgSpeed;
+ }
+ }
+ }
+
+ if(uTotal > 0)
+ {
+ double dPerc = (double)(((double)uRecvd) * 100.0) / (double)uTotal;
+ iW -= 2;
+ int iL = (int) ((((double)iW) * dPerc) / 100.0);
+ //iR = iW - iL;
+ p->fillRect(5,5,iL,10,bIsTerminated ? QColor(140,110,110) : QColor(200,100,100));
+
+ txt = QString(__tr2qs_ctx("%1 of %2 (%3 %)","http")).arg(KviQString::makeSizeReadable(uRecvd))
+ .arg(KviQString::makeSizeReadable(uTotal)).arg(dPerc,0,'f',2);
+ } else {
+ txt = KviQString::makeSizeReadable(m_pHttpRequest->receivedSize());
+ }
+
+ p->setPen(Qt::black);
+
+ p->drawText(4,19,width - 8,height - 8,Qt::AlignTop | Qt::AlignLeft,txt);
+
+ int iLeftHalf = (iW - 2) / 2;
+ int iRightHalf = iW - (iLeftHalf + 1);
+ int iLineSpacing = fm.lineSpacing() + 2;
+
+ /*
+ txt = __tr2qs_ctx("Spd:","dcc");
+ txt += " ";
+ if(iInstantSpeed >= 0)
+ {
+ QString tmpisp;
+ KviNetUtils::formatNetworkBandwidthString(tmpisp,iAvgSpeed);
+ txt += tmpisp;
+ } else {
+ txt += "? B/s";
+ }
+ */
+
+ txt = __tr2qs_ctx("Avg:","dcc");
+ txt += " ";
+ if(iAvgSpeed >= 0)
+ {
+ QString tmpspd;
+ KviNetUtils::formatNetworkBandwidthString(tmpspd,iAvgSpeed);
+ txt += tmpspd;
+ } else {
+ txt += "? B/s";
+ }
+
+
+
+ int iDaH = height - (iLineSpacing + 4);
+
+ p->setPen(QColor(180,180,200));
+ p->drawRect(4,iDaH,iLeftHalf,iLineSpacing);
+ p->fillRect(5,iDaH + 1,iLeftHalf - 2,iLineSpacing - 2,bIsTerminated ? QColor(210,210,210) : QColor(190,190,240));
+ p->setPen(bIsTerminated ? Qt::darkGray : Qt::black);
+ p->drawText(6,iDaH,iLeftHalf - 4,iLineSpacing,Qt::AlignLeft | Qt::AlignVCenter,txt);
+
+ unsigned int uD,uH,uM,uS;
+
+ if(bIsTerminated)
+ {
+ KviTimeUtils::secondsToDaysHoursMinsSecs(kvi_timeSpan(m_tTransferEndTime,m_tTransferStartTime),&uD,&uH,&uM,&uS);
+ txt = "TOT: ";
+ if(uD > 0)txt += QString(__tr2qs_ctx("%1d %2h %3m %4s","http")).arg(uD).arg(uH).arg(uM).arg(uS);
+ else if(uH > 0)txt += QString(__tr2qs_ctx("%2h %3m %4s","http")).arg(uH).arg(uM).arg(uS);
+ else txt += QString(__tr2qs_ctx("%3m %4s","http")).arg(uM).arg(uS);
+ } else {
+ if(iEta >= 0)
+ {
+ KviTimeUtils::secondsToDaysHoursMinsSecs(iEta,&uD,&uH,&uM,&uS);
+ txt = "ETA: ";
+ if(uD > 0)txt += QString(__tr2qs_ctx("%1d %2h %3m %4s","http")).arg(uD).arg(uH).arg(uM).arg(uS);
+ else if(uH > 0)txt += QString(__tr2qs_ctx("%2h %3m %4s","http")).arg(uH).arg(uM).arg(uS);
+ else txt += QString(__tr2qs_ctx("%3m %4s","http")).arg(uM).arg(uS);
+ } else {
+ txt = "ETA: Unknown";
+ }
+ }
+
+ p->setPen(QColor(180,180,200));
+ p->drawRect(width - (4 + iRightHalf),iDaH,iRightHalf,iLineSpacing);
+ p->fillRect(width - (3 + iRightHalf),iDaH + 1,iRightHalf - 2,iLineSpacing - 2,bIsTerminated ? QColor(210,210,210) : QColor(190,190,240));
+ p->setPen(bIsTerminated ? Qt::darkGray : Qt::black);
+ p->drawText(width - (2 + iRightHalf),iDaH,iRightHalf - 4,iLineSpacing,Qt::AlignLeft | Qt::AlignVCenter,txt);
+
+ }
+ break;
+ }
+}
+
+int KviHttpFileTransfer::displayHeight(int iLineSpacing)
+{
+ int iH = (iLineSpacing * 3) + 10;
+ return iH >= 70 ? iH : 70;
+}
+
+QString KviHttpFileTransfer::tipText()
+{
+ QString s;
+ s = QString("<table><tr><td bgcolor=\"#000000\"><font color=\"#FFFFFF\"><b>HTTP Transfer (ID %1)</b></font></td></tr>").arg(id());
+
+ if(m_lRequest.count() > 0)
+ {
+ s += "<tr><td bgcolor=\"#404040\"><font color=\"#FFFFFF\">Request Headers</font></td></tr>";
+ s += "<tr><td bgcolor=\"#C0C0C0\">";
+ for(QStringList::ConstIterator it = m_lRequest.begin();it != m_lRequest.end();++it)
+ {
+ s += "&nbsp; &nbsp;";
+ s += *it;
+ s += "<br>";
+ }
+ s += "</td></tr>";
+ }
+
+ if(m_lHeaders.count() > 0)
+ {
+ s += "<tr><td bgcolor=\"#404040\"><font color=\"#FFFFFF\">Response Headers</font></td></tr>";
+ s += "<tr><td bgcolor=\"#C0C0C0\">";
+ for(QStringList::ConstIterator it = m_lHeaders.begin();it != m_lHeaders.end();++it)
+ {
+ s += "&nbsp; &nbsp;";
+ s += *it;
+ s += "<br>";
+ }
+ s += "</td></tr>";
+ }
+
+ s += "<table>";
+
+ return s;
+}
+
+void KviHttpFileTransfer::init()
+{
+ if(g_pHttpFileTransfers)return;
+ g_pHttpFileTransfers = new KviPointerList<KviHttpFileTransfer>;
+ g_pHttpFileTransfers->setAutoDelete(false);
+
+ QPixmap * pix = g_pIconManager->getImage("kvi_httpicons.png");
+ if(pix)g_pHttpIcon = new QPixmap(*pix);
+ else g_pHttpIcon = new QPixmap(192,48);
+}
+
+void KviHttpFileTransfer::done()
+{
+ if(!g_pHttpFileTransfers)return;
+ while(KviHttpFileTransfer * t = g_pHttpFileTransfers->first())
+ delete t;
+ delete g_pHttpFileTransfers;
+ g_pHttpFileTransfers = 0;
+ delete g_pHttpIcon;
+ g_pHttpIcon = 0;
+}
+
+unsigned int KviHttpFileTransfer::runningTransfers()
+{
+ if(!g_pHttpFileTransfers)return 0;
+ return g_pHttpFileTransfers->count();
+}
+
+void KviHttpFileTransfer::requestSent(const QStringList &requestHeaders)
+{
+ m_szStatusString = __tr2qs_ctx("Request sent, waiting for reply...","http");
+ displayUpdate();
+
+ KviWindow * out = transferWindow();
+ if(!out)return;
+
+ if(!m_bNoOutput)
+ out->output(KVI_OUT_GENERICSTATUS,__tr2qs_ctx("[HTTP %d]: Request data sent:","http"),id());
+
+ for(QStringList::ConstIterator it = requestHeaders.begin();it != requestHeaders.end();++it)
+ {
+ if(!m_bNoOutput)
+ out->output(KVI_OUT_GENERICSTATUS,"[HTTP %d]: %s",id(),(*it).utf8().data());
+ }
+
+ m_lRequest = requestHeaders;
+}
+
+void KviHttpFileTransfer::connectionEstabilished()
+{
+ m_szStatusString = __tr2qs_ctx("Connection established, sending request","http");
+ displayUpdate();
+}
+
+void KviHttpFileTransfer::resolvingHost(const QString &hostname)
+{
+ m_szStatusString = __tr2qs_ctx("Resolving host %1","http").arg(hostname);
+ displayUpdate();
+}
+
+void KviHttpFileTransfer::contactingHost(const QString &ipandport)
+{
+ m_szStatusString = __tr2qs_ctx("Contacting host %1","http").arg(ipandport);
+ displayUpdate();
+}
+
+void KviHttpFileTransfer::receivedResponse(const QString &response)
+{
+ m_lHeaders.clear();
+ m_lHeaders.append(response);
+ m_szStatusString = __tr2qs_ctx("Transferring data (%1)","http").arg(response);
+ m_tTransferStartTime = kvi_unixTime();
+ m_eGeneralStatus = Downloading;
+ displayUpdate();
+}
+
+void KviHttpFileTransfer::statusMessage(const QString &txt)
+{
+ KviWindow * out = transferWindow();
+ if(out && (!m_bNoOutput))
+ out->output(KVI_OUT_GENERICSTATUS,"[HTTP %d]: %Q",id(),&txt);
+}
+
+void KviHttpFileTransfer::transferTerminated(bool bSuccess)
+{
+ KviWindow * out = transferWindow();
+
+ m_tTransferEndTime = kvi_unixTime();
+
+ KviKvsVariantList vParams;
+ vParams.append(new KviKvsVariant(bSuccess));
+ vParams.append(new KviKvsVariant(m_pHttpRequest->url().url()));
+ vParams.append(new KviKvsVariant(m_pHttpRequest->fileName()));
+ vParams.append(new KviKvsVariant(m_vMagicIdentifier));
+
+ if(m_szCompletionCallback.isNull())
+ {
+ KVS_TRIGGER_EVENT(KviEvent_OnHTTPGetTerminated,out ? out : (KviWindow *)(g_pApp->activeConsole()),&vParams)
+ } else {
+ KviKvsScript::run(m_szCompletionCallback,out ? out : (KviWindow *)(g_pApp->activeConsole()),&vParams);
+ }
+
+ if(bSuccess)
+ {
+ m_szStatusString = __tr2qs_ctx("Transfer completed","http");
+ m_eGeneralStatus = Success;
+ displayUpdate();
+ if(out && (!m_bNoOutput))out->output(KVI_OUT_GENERICSUCCESS,__tr2qs_ctx("[HTTP %d]: Transfer completed","http"),id());
+ g_pApp->fileDownloadTerminated(true,m_pHttpRequest->url().url().ptr(),m_pHttpRequest->fileName(),QString::null,QString::null,!m_bNotifyCompletion);
+ } else {
+ m_szStatusString = __tr2qs_ctx("Transfer failed","http");
+ m_szStatusString += ": ";
+ m_szStatusString += m_pHttpRequest->lastError();
+ m_eGeneralStatus = Failure;
+ displayUpdate();
+ if(out && (!m_bNoOutput))out->output(KVI_OUT_GENERICERROR,__tr2qs_ctx("[HTTP %d]: Transfer failed: %Q","http"),id(),&(m_pHttpRequest->lastError()));
+ g_pApp->fileDownloadTerminated(false,m_pHttpRequest->url().url().ptr(),m_pHttpRequest->fileName(),QString::null,m_pHttpRequest->lastError(),!m_bNotifyCompletion);
+ }
+
+ if(m_bAutoClean)
+ {
+ if(m_pAutoCleanTimer)delete m_pAutoCleanTimer;
+ m_pAutoCleanTimer = new QTimer();
+ connect(m_pAutoCleanTimer,SIGNAL(timeout()),this,SLOT(autoClean()));
+ m_pAutoCleanTimer->start(100,true);
+ }
+}
+
+void KviHttpFileTransfer::headersReceived(KviPointerHashTable<const char *,KviStr> *h)
+{
+ if(!h)return;
+ KviWindow * out = transferWindow();
+
+ if(out && (!m_bNoOutput))out->output(KVI_OUT_GENERICSTATUS,__tr2qs_ctx("[HTTP %d]: Response headers:","http"),id());
+ KviPointerHashTableIterator<const char *,KviStr> it(*h);
+ while(KviStr * s = it.current())
+ {
+ QString szHeader = it.currentKey();
+ szHeader += ": ";
+ szHeader += s->ptr();
+ m_lHeaders.append(szHeader);
+ if(out && (!m_bNoOutput))out->output(KVI_OUT_GENERICSTATUS,"[HTTP %d]: %s: %s",id(),it.currentKey(),s->ptr());
+ ++it;
+ }
+}
+
+bool KviHttpFileTransfer::startDownload()
+{
+ m_eGeneralStatus = Connecting;
+ return m_pHttpRequest->start();
+}
+
+#include "m_httpfiletransfer.moc"
diff --git a/src/modules/http/httpfiletransfer.h b/src/modules/http/httpfiletransfer.h
new file mode 100644
index 00000000..e6c5006e
--- /dev/null
+++ b/src/modules/http/httpfiletransfer.h
@@ -0,0 +1,104 @@
+#ifndef _HTTPFILETRANSFER_H_
+#define _HTTPFILETRANSFER_H_
+//==================================================================================
+//
+// File : httpfiletransfer.h
+// Creation date : Tue Apr 22 2003 02:00:12 GMT by Szymon Stefanek
+//
+// This config is part of the KVirc irc client distribution
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//==================================================================================
+
+#include "kvi_filetransfer.h"
+#include "kvi_http.h"
+#include "kvi_time.h"
+
+#include "kvi_kvs_variant.h"
+
+#include <qstringlist.h>
+#include <qtimer.h>
+
+class QPainter;
+class KviTalPopupMenu;
+
+class KviHttpFileTransfer : public KviFileTransfer
+{
+ enum GeneralStatus { Initializing, Connecting, Downloading, Success, Failure };
+ Q_OBJECT
+public:
+ KviHttpFileTransfer();
+ ~KviHttpFileTransfer();
+private:
+ KviHttpRequest * m_pHttpRequest;
+ GeneralStatus m_eGeneralStatus;
+ QString m_szStatusString;
+
+ QStringList m_lHeaders;
+ QStringList m_lRequest;
+
+ kvi_time_t m_tStartTime;
+ kvi_time_t m_tTransferStartTime;
+ kvi_time_t m_tTransferEndTime;
+
+ KviKvsVariant m_vMagicIdentifier;
+ bool m_bNotifyCompletion;
+ bool m_bAutoClean;
+ bool m_bNoOutput;
+
+ QTimer * m_pAutoCleanTimer;
+
+ QString m_szCompletionCallback;
+public:
+ KviHttpRequest * request(){ return m_pHttpRequest; };
+ static unsigned int runningTransfers();
+ static void init();
+ static void done();
+
+ virtual bool startDownload();
+
+ void setCompletionCallback(const QString &szCallback){ m_szCompletionCallback = szCallback; };
+ void setMagicIdentifier(const KviKvsVariant &vIdentifier){ m_vMagicIdentifier = vIdentifier; };
+ void setNotifyCompletion(bool bNotify){ m_bNotifyCompletion = bNotify; };
+ void setAutoClean(bool bAutoClean){ m_bAutoClean = bAutoClean; };
+ void setNoOutput(bool bNoOutput){ m_bNoOutput = bNoOutput; };
+
+ virtual void displayPaint(QPainter * p,int column,int width,int height);
+ virtual int displayHeight(int iLineSpacing);
+ virtual void fillContextPopup(KviTalPopupMenu * m,int column);
+ virtual bool active();
+ virtual void die();
+ virtual QString tipText();
+ virtual QString localFileName();
+protected slots:
+ void statusMessage(const QString &txt);
+ void transferTerminated(bool bSuccess);
+ void headersReceived(KviPointerHashTable<const char *,KviStr> *h);
+ void requestSent(const QStringList &sl);
+
+ void resolvingHost(const QString &hostname);
+ void contactingHost(const QString &ipandport);
+ void receivedResponse(const QString &response);
+ void connectionEstabilished();
+
+ void abort();
+
+ void autoClean();
+};
+
+
+#endif //!_HTTPFILETRANSFER_H_
diff --git a/src/modules/http/kvi_httpicons.png b/src/modules/http/kvi_httpicons.png
new file mode 100644
index 00000000..30776c0f
--- /dev/null
+++ b/src/modules/http/kvi_httpicons.png
Binary files differ
diff --git a/src/modules/http/libkvihttp.cpp b/src/modules/http/libkvihttp.cpp
new file mode 100644
index 00000000..eb6f28fb
--- /dev/null
+++ b/src/modules/http/libkvihttp.cpp
@@ -0,0 +1,324 @@
+//==================================================================================
+//
+// File : libkvihttp.cpp
+// Creation date : Tue Apr 22 2003 02:00:12 GMT by Szymon Stefanek
+//
+// This config is part of the KVirc irc client distribution
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//==================================================================================
+
+#include "kvi_module.h"
+#include "kvi_string.h"
+
+
+#include "kvi_app.h"
+#include "kvi_locale.h"
+#include "kvi_filedialog.h"
+#include "kvi_window.h"
+#include "kvi_error.h"
+#include "kvi_cmdformatter.h"
+
+#include "httpfiletransfer.h"
+
+
+static bool http_kvs_complete_get(KviKvsModuleCommandCall * c,QString &szUrl,QString &szFileName,const QString &szCallback)
+{
+ if(szUrl.isEmpty())
+ {
+ c->warning(__tr2qs_ctx("No url specified","http"));
+ return true;
+ }
+
+ KviUrl url(szUrl);
+
+ QString tmp;
+
+ if(szFileName.isEmpty())
+ {
+ if(c->switches()->find('a',"auto-file-name"))
+ {
+ tmp = szUrl;
+ tmp.replace('/',"_");
+ tmp.replace(':',"_");
+ tmp.replace('@',"_");
+ tmp.replace('?',"_");
+ // http____path_path2_path3_filename.ext
+ g_pApp->getLocalKvircDirectory(szFileName,KviApp::Incoming,tmp);
+ } else {
+ if(!KviFileDialog::askForSaveFileName(szFileName,__tr2qs_ctx("Choose a save file name","http")))
+ return true;
+ if(szFileName.isEmpty())return true;
+ }
+ }
+
+ KviHttpFileTransfer * hft = new KviHttpFileTransfer();
+
+ bool bHead = c->switches()->find('h',"head");
+
+ if(c->switches()->getAsStringIfExisting('p',"post-data",tmp))
+ {
+ if(bHead)
+ {
+ c->warning(__tr2qs_ctx("The switch -p is incompatible with -h: -p takes precedence","http"));
+ bHead = false;
+ }
+ hft->request()->setPostData(tmp);
+ }
+
+ hft->request()->setUrl(url);
+ hft->request()->setProcessingType(bHead ? KviHttpRequest::HeadersOnly : KviHttpRequest::StoreToFile);
+ hft->request()->setFileName(szFileName);
+
+ if(c->switches()->getAsStringIfExisting('e',"existing-file-action",tmp))
+ {
+ if(KviQString::equalCI(tmp,"e"))
+ hft->request()->setExistingFileAction(KviHttpRequest::RenameExisting);
+ else if(KviQString::equalCI(tmp,"i"))
+ hft->request()->setExistingFileAction(KviHttpRequest::RenameIncoming);
+ else if(KviQString::equalCI(tmp,"o"))
+ hft->request()->setExistingFileAction(KviHttpRequest::Overwrite);
+ else if(KviQString::equalCI(tmp,"r"))
+ hft->request()->setExistingFileAction(KviHttpRequest::Resume);
+ }
+
+ // FIXME: this should be numeric
+ if(c->switches()->getAsStringIfExisting('m',"max-len",tmp))
+ {
+ bool bOk;
+ unsigned int uContentLength = tmp.toUInt(&bOk);
+ if(bOk)hft->request()->setMaxContentLength(uContentLength);
+ }
+
+ // FIXME: this should be numeric
+ if(c->switches()->getAsStringIfExisting('o',"offset",tmp))
+ {
+ bool bOk;
+ unsigned int uContentOffset = tmp.toUInt(&bOk);
+ if(bOk)hft->request()->setContentOffset(uContentOffset);
+ }
+
+ if(c->switches()->getAsStringIfExisting('w',"winctrl",tmp))
+ {
+ if(!tmp.contains('h'))hft->invokeTransferWindow(c->window(),tmp.contains('m'),tmp.contains('n'));
+ } else {
+ hft->invokeTransferWindow(c->window(),false,false);
+ }
+
+ KviKvsVariant * v = c->switches()->find('i',"identifier");
+ if(v)
+ hft->setMagicIdentifier(*v);
+
+ if(c->switches()->find('q',"quiet"))
+ hft->setNotifyCompletion(false);
+
+ if(c->switches()->find('y',"no-output"))
+ hft->setNoOutput(true);
+
+ if(!szCallback.isEmpty())
+ hft->setCompletionCallback(szCallback);
+
+ if(c->switches()->find('c',"clear"))
+ hft->setAutoClean(true);
+
+ if(!hft->startDownload())
+ {
+ tmp = hft->request()->lastError();
+ c->warning(__tr2qs_ctx("Failed to start the get request: %Q","http"),&tmp);
+ delete hft;
+ }
+
+ return true;
+}
+
+
+/*
+ @doc: http.get
+ @type:
+ command
+ @title:
+ http.get
+ @keyterms:
+ HTTP extension
+ @short:
+ Retrieves a file via HTTP GET
+ @syntax:
+ http.get [switches] <http_url> [save_file_name]
+ @description:
+ Attempts to download the file at <http_url> by using the HTTP GET or POST protocol.[br]
+ If [save_file_name] is specified, then is is used as save file name, otherwise
+ a save file dialog is displayed (unless -a is used).[br]
+ The event OnHTTPGetTerminated is triggered upon the download completion (both
+ in case of success or failure). If you want a callback command to be triggered
+ instead please use [cmd]http.asyncGet[/cmd].
+ If the url contains a https:// prefix then a SSL connection will be used.
+ @switches:
+ !sw: -a=<auto_file_name> | --auto-file-name=<auto_file_name>
+ Don't show the savefile dialog but determine automatically a file name.
+ The file is put in the KVIrc incoming directory and the file name
+ is the processed url.[br]
+
+ !sw: -e=<existing_file_action> | --existing-file-action=<existing_file_action>
+ Specifies the action to be taken when the local file already exists.[br]
+ The action can be one of "i","e","o" or "r".[br]
+ "i" causes the incoming file to be automatically renamed by appending a
+ non colliding suffix. "e" causes the existing file to be renamed
+ by appending a non colliding suffix (the incoming file will then have its name preserved).
+ "o" causes the existing file to be overwritten and "r" will attempt to resume
+ a interrupted transfer.[br]
+ The default is to rename the incoming file.[br]
+
+ !sw: -m=<max_content_length> | --max-len=<max_content_length>
+ Causes content longer than <max_content_length> to be discarded.[br]
+ This is mainly to prevent you from automatically downloading 300 MB files
+ and to prevent DOS attacks from malicious servers that do not report the Content-length header.[br]
+ If the Content-length header is reported by the server then the transfer is aborted
+ if the length exceedes <max_content_length>.[br]
+ If the Content-length header is missing then the transfer is interrupted when
+ the received data length exceeds <max_content_length>.[br]
+ -m=0 means "accept any content length" (which is the default).[br]
+
+ !sw: -o=<content_offset> | --offset=<content_offset>
+ Causes the download to start from position <content offset>.[br]
+ This can be used to download only a part of the file starting at byte <content_offset>.[br]
+ <content_offset> is used regardless if the file is resumed or not.
+ Please note that you don't need to specify the content offset when using
+ -e=r : the offset is automatically calculated. If you specify both -o=<content_offset>
+ and -e=r then the file will be resumed, the transfer will start at the specified offset
+ and the received stream will be appended to the existing file.(avoid it unless you know what you're doing:
+ it's easy to download broken files).[br]
+
+ !sw: -h | --head
+ Causes the connection to use the HTTP HEAD method that effectively
+ does not transfer real data. The server sends only the response headers.
+ This might be used in conjunction with the -v option to print the headers to the
+ active window.[br]
+
+ !sw: -w=<flags> | --winctrl
+ This switch controls the creation and visualization of the transfer window.
+ <flags> can be any combination of 'm','n' and 'h'.
+ The flag 'h' causes the window to not be created. The transfer will simply run in background.
+ Note that with 'h' the user has no possibility to interact with the transfer.
+ The flag 'm' causes the transfer window to be created as "minimized". 'm' does nothing
+ if the window alread exists. The flag 'n' causes the window to be NOT activated (brought to top).
+
+ !sw: -i=<magic identifier> | --identifier=<magic identifier>
+ This identifier is passed as $3 parameter to the [event]OnHTTPGetTerminated[/event]
+ when this transfer terminates. If this switch is not present then an empty string is used.
+ With [cmd]http.asyngGet[/cmd] this parameter is passed to the callback command instead.
+
+ !sw: -p=<post data> | --post-data=<post data>
+ The request is sent in form of a POST request. <post data> is the urlencoded payload of
+ the request. -p is incompatible with -h.
+
+ !sw: -q | --quiet
+ Do not notify download completion in the notifier window nor in the console.
+
+ !sw: -y | --no-output
+ Supress any output in the file transfer window. This will effectively disable
+ the file transfer window highlighting (so the user will not be alerted by a failed
+ download unless he's really watching the window). This is useful when you're notifying
+ failures in some other way...
+
+ !sw: -c | --clear
+ Automatically remove the transfer from the transfer list when terminated
+ @seealso:
+ [cmd]http.asyncGet[/cmd]
+*/
+
+static bool http_kvs_cmd_get(KviKvsModuleCommandCall * c)
+{
+ QString szUrl,szFileName;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("url",KVS_PT_NONEMPTYSTRING,0,szUrl)
+ KVSM_PARAMETER("filename",KVS_PT_STRING,KVS_PF_OPTIONAL,szFileName)
+ KVSM_PARAMETERS_END(c)
+
+ return http_kvs_complete_get(c,szUrl,szFileName,QString::null);
+}
+/*
+ @doc: http.asyncGet
+ @type:
+ command
+ @title:
+ http.asyncGet
+ @keyterms:
+ HTTP extension
+ @short:
+ Retrieves a file via HTTP GET and triggers a callback
+ @syntax:
+ http.asyncGet [switches] (<http_url> [,save_file_name])
+ {
+ <callback command>
+ }
+ @description:
+ Attempts to download the file at <http_url> by using the HTTP GET or POST protocol.[br]
+ If [save_file_name] is specified, then is is used as save file name, otherwise
+ a save file dialog is displayed (unless -a is used).[br]
+ This command is really similar to [cmd]http.get[/cmd]: it has exactly the same
+ parameters and switches (so also refer to its documentation).
+ The only difference is that asyncGet triggers the <callback command> upon completion
+ instead of the global OnHTTPGetTerminated event.
+ The parameters passed to the callback are exactly the same.
+ If the url contains a https:// prefix then a SSL connection will be used.
+ @seealso:
+ [cmd]http.get[/cmd]
+*/
+
+static bool http_kvs_cmd_asyncGet(KviKvsModuleCallbackCommandCall * c)
+{
+ QString szUrl,szFileName;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("url",KVS_PT_NONEMPTYSTRING,0,szUrl)
+ KVSM_PARAMETER("filename",KVS_PT_STRING,KVS_PF_OPTIONAL,szFileName)
+ KVSM_PARAMETERS_END(c)
+
+ return http_kvs_complete_get(c,szUrl,szFileName,c->callback()->code());
+}
+
+
+static bool http_module_init(KviModule * m)
+{
+ KviHttpFileTransfer::init();
+
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"get",http_kvs_cmd_get);
+ KVSM_REGISTER_CALLBACK_COMMAND(m,"asyncGet",http_kvs_cmd_asyncGet);
+
+ return true;
+}
+
+static bool http_module_cleanup(KviModule *m)
+{
+ KviHttpFileTransfer::done();
+ return true;
+}
+
+static bool http_module_can_unload(KviModule *m)
+{
+ return (KviHttpFileTransfer::runningTransfers() == 0);
+}
+
+KVIRC_MODULE(
+ "Http", // module name
+ "1.0.0", // module version
+ "Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot net)", // author & (C)
+ "HTTP interface for KVIrc",
+ http_module_init,
+ http_module_can_unload,
+ 0,
+ http_module_cleanup
+)
diff --git a/src/modules/ident/Makefile.am b/src/modules/ident/Makefile.am
new file mode 100644
index 00000000..c02c0b47
--- /dev/null
+++ b/src/modules/ident/Makefile.am
@@ -0,0 +1,20 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkviident.la
+
+libkviident_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkviident_la_SOURCES = libkviident.cpp
+libkviident_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+noinst_HEADERS= libkviident.h
+
+%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
+
+libkviident.cpp: libkviident.moc
diff --git a/src/modules/ident/libkviident.cpp b/src/modules/ident/libkviident.cpp
new file mode 100644
index 00000000..c8f4f194
--- /dev/null
+++ b/src/modules/ident/libkviident.cpp
@@ -0,0 +1,615 @@
+//
+// File : libkviident.cpp
+// Creation date : Tue Oct 2 18:22:04 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_module.h"
+
+#include "libkviident.h"
+
+#include "kvi_socket.h"
+#include "kvi_app.h"
+#include "kvi_out.h"
+#include "kvi_netutils.h"
+#include "kvi_locale.h"
+#include "kvi_window.h"
+
+#include "kvi_options.h"
+#include "kvi_defaults.h"
+
+#define KVI_IDENT_THREAD_EVENT_EXITING KVI_THREAD_USER_EVENT_BASE + 111
+#define KVI_IDENT_THREAD_EVENT_EXITING_ON_REQUEST KVI_THREAD_USER_EVENT_BASE + 112
+
+
+// FIXME: Should have a timeout on the requests!!!
+
+static KviIdentDaemon * g_pIdentDaemon = 0;
+static KviIdentSentinel * g_pIdentSentinel = 0;
+
+extern KVIRC_API int g_iIdentDaemonRunningUsers;
+
+void startIdentService()
+{
+// debug("Stargin");
+ if(!g_pIdentDaemon)g_pIdentDaemon = new KviIdentDaemon();
+ if(!g_pIdentDaemon->isRunning())g_pIdentDaemon->start();
+ while(g_pIdentDaemon->isStartingUp())
+ {
+#ifdef COMPILE_ON_WINDOWS
+ Sleep(10);
+#else
+ usleep(100);
+#endif
+ }
+// debug("Service started");
+}
+
+void stopIdentService()
+{
+// debug("Stopping");
+ if(g_pIdentDaemon)delete g_pIdentDaemon;
+ g_pIdentDaemon = 0;
+// debug("Stopped");
+}
+
+KviIdentSentinel::KviIdentSentinel()
+: QObject(0)
+{
+}
+
+KviIdentSentinel::~KviIdentSentinel()
+{
+ KviThreadManager::killPendingEvents(this);
+}
+
+bool KviIdentSentinel::event(QEvent *e)
+{
+ if(KVI_OPTION_UINT(KviOption_uintIdentdOutputMode)==KviIdentdOutputMode::Quiet || !g_pActiveWindow)
+ return QObject::event(e);
+
+ KviWindow * pTarget = KVI_OPTION_UINT(KviOption_uintIdentdOutputMode)==KviIdentdOutputMode::ToActiveWindow ?
+ (KviWindow *)g_pActiveWindow : (KviWindow *)g_pApp->activeConsole();
+
+ if(e->type() == KVI_THREAD_EVENT)
+ {
+ if(((KviThreadEvent *)e)->id() == KVI_THREAD_EVENT_DATA)
+ {
+ KviIdentMessageData * d = ((KviThreadDataEvent<KviIdentMessageData> *)e)->getData();
+ if(pTarget)
+ {
+ if(d->szHost.hasData())
+ {
+ if(d->szAux.hasData())
+ {
+ if(_OUTPUT_PARANOIC)
+ pTarget->output(KVI_OUT_IDENT,__tr("%s (%s) (%s:%u)"),d->szMessage.ptr(),d->szAux.ptr(),d->szHost.ptr(),d->uPort);
+ else
+ pTarget->output(KVI_OUT_IDENT,__tr("%s (%s)"),d->szMessage.ptr(),d->szAux.ptr());
+ } else {
+ if(_OUTPUT_PARANOIC)
+ pTarget->output(KVI_OUT_IDENT,__tr("%s (%s:%u)"),d->szMessage.ptr(),d->szHost.ptr(),d->uPort);
+ else
+ pTarget->output(KVI_OUT_IDENT,__tr("%s"),d->szMessage.ptr());
+ }
+ } else {
+ pTarget->output(KVI_OUT_IDENT,__tr("[IDENT]: %s"),d->szMessage.ptr());
+ }
+ }
+ delete d;
+ } else if(((KviThreadEvent *)e)->id() == KVI_IDENT_THREAD_EVENT_EXITING)
+ {
+ if(_OUTPUT_VERBOSE)
+ if(pTarget)pTarget->outputNoFmt(KVI_OUT_IDENT,__tr("Shutting down identd service (spontaneous action)"));
+ stopIdentService();
+ } else if(((KviThreadEvent *)e)->id() == KVI_IDENT_THREAD_EVENT_EXITING_ON_REQUEST)
+ {
+ if(_OUTPUT_VERBOSE)
+ if(pTarget)pTarget->outputNoFmt(KVI_OUT_IDENT,__tr("Shutting down identd service (requested action)"));
+ }
+
+ return true;
+ }
+
+ return QObject::event(e);
+}
+
+
+KviIdentRequest::KviIdentRequest(kvi_socket_t sock,const char * host,kvi_u32_t uPort)
+{
+ m_sock = sock;
+ m_szHost = host;
+ m_uPort = uPort;
+ m_tStart = time(0);
+}
+
+KviIdentRequest::~KviIdentRequest()
+{
+ kvi_socket_close(m_sock);
+}
+
+
+
+KviIdentDaemon::KviIdentDaemon()
+: KviSensitiveThread()
+{
+// debug("Thread constructor");
+ m_szUser = KVI_OPTION_STRING(KviOption_stringIdentdUser);
+ if(m_szUser.isEmpty())m_szUser = "kvirc";
+ m_uPort = KVI_OPTION_UINT(KviOption_uintIdentdPort);
+#ifdef COMPILE_IPV6_SUPPORT
+ m_bEnableIpV6 = KVI_OPTION_BOOL(KviOption_boolIdentdEnableIpV6);
+#else
+ m_bEnableIpV6 = false;
+#endif
+ m_bIpV6ContainsIpV4 = KVI_OPTION_BOOL(KviOption_boolIdentdIpV6ContainsIpV4);
+// debug("Thread constructor done");
+}
+
+KviIdentDaemon::~KviIdentDaemon()
+{
+// debug("Thread destructor");
+ terminate();
+ g_iIdentDaemonRunningUsers = 0;
+
+ g_pIdentDaemon = 0;
+// debug("Destructor gone");
+}
+
+void KviIdentDaemon::postMessage(const char * message,KviIdentRequest * r,const char * szAux)
+{
+ KviThreadDataEvent<KviIdentMessageData> * e = new KviThreadDataEvent<KviIdentMessageData>(KVI_THREAD_EVENT_DATA);
+
+ KviIdentMessageData * d = new KviIdentMessageData;
+
+ d->szMessage = message;
+ if(szAux)d->szAux = szAux;
+
+ if(r)
+ {
+ d->szHost = r->m_szHost;
+ d->uPort = r->m_uPort;
+ }
+
+ e->setData(d);
+ postEvent(g_pIdentSentinel,e);
+}
+
+void KviIdentDaemon::run()
+{
+// debug("RUN STARTED");
+ m_sock = KVI_INVALID_SOCKET;
+ m_sock6 = KVI_INVALID_SOCKET;
+ bool bEventPosted = false;
+
+ m_pRequestList = new KviPointerList<KviIdentRequest>;
+ m_pRequestList->setAutoDelete(true);
+
+ KviPointerList<KviIdentRequest> dying;
+ dying.setAutoDelete(false);
+
+#ifdef COMPILE_IPV6_SUPPORT
+ // If we have enabled ipv6 and we have to use a single socket: this one is IPV6
+ // otherwise this one is IPV4
+ KviSockaddr sa(m_uPort,m_bEnableIpV6 && m_bIpV6ContainsIpV4);
+#else
+ KviSockaddr sa(m_uPort,false);
+#endif
+
+ KviIdentRequest * r;
+
+#ifdef COMPILE_IPV6_SUPPORT
+ m_sock = kvi_socket_create((m_bEnableIpV6 && m_bIpV6ContainsIpV4) ? KVI_SOCKET_PF_INET6 : KVI_SOCKET_PF_INET,KVI_SOCKET_TYPE_STREAM,KVI_SOCKET_PROTO_TCP);
+#else
+ m_sock = kvi_socket_create(KVI_SOCKET_PF_INET,KVI_SOCKET_TYPE_STREAM,KVI_SOCKET_PROTO_TCP);
+#endif
+
+ if(m_sock == KVI_INVALID_SOCKET)
+ {
+ postMessage(__tr("Can't start the ident service : socket() failed"),0);
+ goto exit_thread;
+ }
+
+ if(!kvi_socket_setNonBlocking(m_sock))
+ {
+ postMessage(__tr("Can't start the ident service : async setting failed"),0);
+ goto exit_thread;
+ }
+
+ if(!sa.socketAddress())
+ {
+ postMessage(__tr("Can't enable the ident service : can't setup the listen address"),0);
+ goto exit_thread;
+ }
+
+ if(!kvi_socket_bind(m_sock,sa.socketAddress(),((int)(sa.addressLength()))))
+ {
+ postMessage(__tr("Can't start the ident service : bind() failed"),0);
+ goto exit_thread;
+ }
+
+ if(!kvi_socket_listen(m_sock,128))
+ {
+ postMessage(__tr("Can't start the ident service : listen() failed"),0);
+ goto exit_thread;
+ }
+
+
+#ifdef COMPILE_IPV6_SUPPORT
+ if(m_bEnableIpV6 && (!m_bIpV6ContainsIpV4))
+ {
+ // Need to start the IPV6 socket too
+ KviSockaddr sa6(m_uPort,true);
+ m_sock6 = kvi_socket_create(KVI_SOCKET_PF_INET6,KVI_SOCKET_TYPE_STREAM,KVI_SOCKET_PROTO_TCP);
+
+ if(m_sock6 == KVI_INVALID_SOCKET)
+ {
+ postMessage(__tr("Can't start the ident service on IpV6 : socket() failed"),0);
+ goto ipv6_failure;
+ }
+
+ if(!kvi_socket_setNonBlocking(m_sock6))
+ {
+ postMessage(__tr("Can't start the ident service on IpV6 : async setting failed"),0);
+ kvi_socket_close(m_sock6);
+ m_sock6 = KVI_INVALID_SOCKET;
+ goto ipv6_failure;
+ }
+
+ if(!sa6.socketAddress())
+ {
+ postMessage(__tr("Can't enable the ident service on IpV6 : can't setup the listen address"),0);
+ kvi_socket_close(m_sock6);
+ m_sock6 = KVI_INVALID_SOCKET;
+ goto ipv6_failure;
+ }
+
+ if(!kvi_socket_bind(m_sock6,sa6.socketAddress(),((int)(sa6.addressLength()))))
+ {
+ postMessage(__tr("Can't start the ident service on IpV6 : bind() failed"),0);
+ kvi_socket_close(m_sock6);
+ m_sock6 = KVI_INVALID_SOCKET;
+ goto ipv6_failure;
+
+ }
+
+ if(!kvi_socket_listen(m_sock6,128))
+ {
+ postMessage(__tr("Can't start the ident service on IpV6 : listen() failed"),0);
+ kvi_socket_close(m_sock6);
+ m_sock6 = KVI_INVALID_SOCKET;
+ goto ipv6_failure;
+ }
+
+ }
+#endif
+
+ipv6_failure:
+
+#ifdef COMPILE_IPV6_SUPPORT
+ if(m_bEnableIpV6)
+ {
+ if(m_sock6 != KVI_INVALID_SOCKET) {
+ if(_OUTPUT_PARANOIC)
+ postMessage(__tr("Starting identd service (IpV4/V6 on separate namespaces)"),0);
+ } else {
+ if(_OUTPUT_PARANOIC)
+ postMessage(__tr("Starting identd service (IpV4/V6 in IpV6 namespace)"),0);
+ }
+
+ } else {
+ if(_OUTPUT_PARANOIC)
+ postMessage(__tr("Starting identd service (IpV4)"),0);
+ }
+#else //!COMPILE_IPV6_SUPPORT
+ if(_OUTPUT_PARANOIC)
+ postMessage(__tr("Service startup (IpV4)"),0);
+#endif //!COMPILE_IPV6_SUPPORT
+
+
+ for(;;)
+ {
+
+ if(KviThreadEvent * e = dequeueEvent())
+ {
+ // This can be ONLY a terminate event
+ delete e;
+ goto exit_on_request;
+ }
+
+ struct timeval t;
+ t.tv_sec = 0;
+ t.tv_usec = 10000;
+
+ int nmax = 0;
+
+ fd_set rs;
+ FD_ZERO(&rs);
+
+ if(m_sock != KVI_INVALID_SOCKET)
+ {
+ FD_SET(m_sock,&rs);
+ if(((unsigned int)m_sock) > ((unsigned int)nmax))nmax = m_sock;
+ }
+#ifdef COMPILE_IPV6_SUPPORT
+ if(m_sock6 != KVI_INVALID_SOCKET)
+ {
+ FD_SET(m_sock6,&rs);
+ if(((unsigned int)m_sock6) > ((unsigned int)nmax))nmax = m_sock6;
+ }
+#endif
+
+ for(r = m_pRequestList->first();r;r = m_pRequestList->next())
+ {
+ FD_SET(r->m_sock,&rs);
+ if(((unsigned int)r->m_sock) > ((unsigned int)nmax))nmax = r->m_sock;
+ }
+
+ // FIXME: SO_REUSEADDR ?
+
+
+ int ret = kvi_socket_select(nmax + 1,&rs,0,0,&t);
+
+
+ if(ret == 0)msleep(100);
+ else {
+
+
+ if(m_sock != KVI_INVALID_SOCKET)
+ {
+ if(FD_ISSET(m_sock,&rs))
+ {
+#ifdef COMPILE_IPV6_SUPPORT
+ KviSockaddr satmp(0,m_bEnableIpV6 && m_bIpV6ContainsIpV4);
+#else
+ KviSockaddr satmp(0,false);
+#endif
+ int salen = (int)satmp.addressLength();
+
+ kvi_socket_t t = kvi_socket_accept(m_sock,satmp.socketAddress(),&salen);
+ if(t != KVI_INVALID_SOCKET)
+ {
+ QString szHost;
+ if(!satmp.getStringAddress(szHost))szHost = "unknown";
+ KviIdentRequest * r = new KviIdentRequest(t,szHost.utf8().data(),satmp.port());
+ m_pRequestList->append(r);
+ postMessage(__tr("Identd accepting connection"),r);
+ }
+ }
+ }
+
+#ifdef COMPILE_IPV6_SUPPORT
+ if(m_sock6 != KVI_INVALID_SOCKET)
+ {
+ if(FD_ISSET(m_sock6,&rs))
+ {
+ KviSockaddr satmp(0,true);
+ int salen = (int)satmp.addressLength();
+
+ kvi_socket_t t = kvi_socket_accept(m_sock6,satmp.socketAddress(),&salen);
+ if(t != KVI_INVALID_SOCKET)
+ {
+ QString szHost;
+ if(!satmp.getStringAddress(szHost))szHost = "unknown";
+ KviIdentRequest * r = new KviIdentRequest(t,szHost.utf8().data(),satmp.port());
+ m_pRequestList->append(r);
+ postMessage(__tr("Identd accepting connection"),r);
+ }
+ }
+ }
+#endif
+
+ for(r = m_pRequestList->first();r;r = m_pRequestList->next())
+ {
+ if(FD_ISSET(r->m_sock,&rs))
+ {
+ char buffer[1025];
+ int readed = kvi_socket_recv(r->m_sock,buffer,1024);
+ if(readed > 0)
+ {
+ buffer[readed] = '\0';
+ r->m_szData.append(buffer);
+ } else {
+ // error ?
+ if(readed < 0)
+ {
+ int err = kvi_socket_error();
+ if(!kvi_socket_recoverableConnectError(err))
+ {
+ postMessage(__tr("Identd socket error : dropping connection"),r);
+ dying.append(r);
+ }
+ } else {
+ // connection closed
+ postMessage(__tr("Identd connection closed by remote host"),r);
+ dying.append(r);
+ }
+ }
+ }
+ }
+
+ for(r = m_pRequestList->first();r;r = m_pRequestList->next())
+ {
+
+ int idx = r->m_szData.findFirstIdx('\n');
+
+ if(idx != -1)
+ {
+ // Ok...parse the request
+ KviStr szReq = r->m_szData.left(idx);
+ r->m_szData.cutLeft(idx + 1);
+ szReq.stripWhiteSpace();
+
+ if(szReq.hasData())
+ {
+ postMessage(__tr("Identd processing request"),r,szReq.ptr());
+
+ if(kvi_strEqualCI("VERSION",szReq.ptr()))
+ {
+ KviStr reply("Quad-Echelon 7.12-r-244");
+ kvi_socket_write(r->m_sock,reply.ptr(),reply.len());
+ } else {
+ KviStr reply(KviStr::Format,"%s : USERID : UNIX : %s\r\n",szReq.ptr(),m_szUser.ptr());
+ kvi_socket_write(r->m_sock,reply.ptr(),reply.len());
+ }
+
+ dying.append(r);
+
+ } else {
+
+ postMessage(__tr("Empty request (EOT ?)"),r,szReq.ptr());
+
+ dying.append(r);
+ }
+
+ } else {
+ // debug("Data is : (%s)",r->m_szData.ptr());
+ if(r->m_szData.len() > 1024)
+ {
+ // request too long...kill it
+ dying.append(r);
+ postMessage(__tr("Dropping connection (request too long)"),r);
+ }
+ }
+
+ }
+ }
+
+ time_t curTime = time(0);
+
+ for(r = m_pRequestList->first();r;r = m_pRequestList->next())
+ {
+ if((unsigned int)(curTime - r->m_tStart) > 30)
+ {
+ postMessage(__tr("Timed out while waiting for the request : dropping connection"),r);
+ dying.append(r);
+ }
+ }
+
+ for(KviIdentRequest * ir = dying.first();ir;ir = dying.next())
+ m_pRequestList->removeRef(ir);
+
+ dying.clear();
+
+ }
+
+
+
+exit_on_request:
+
+ postEvent(g_pIdentSentinel,new KviThreadEvent(KVI_IDENT_THREAD_EVENT_EXITING_ON_REQUEST));
+ bEventPosted = true;
+
+exit_thread:
+
+ if(!bEventPosted)
+ postEvent(g_pIdentSentinel,new KviThreadEvent(KVI_IDENT_THREAD_EVENT_EXITING));
+
+
+ if(m_sock != KVI_INVALID_SOCKET)kvi_socket_close(m_sock);
+ if(m_sock6 != KVI_INVALID_SOCKET)kvi_socket_close(m_sock6);
+ delete m_pRequestList;
+ m_pRequestList = 0;
+
+// debug("RUN EXITING");
+}
+
+
+/*
+ @doc: ident.start
+ @type:
+ command
+ @title:
+ ident.start
+ @short:
+ Starts the builtin ident service
+ @syntax:
+ ident.start
+ @description:
+ Starts the builtin ident service.[br]
+ WARNING: the kvirc ident service is just a partial implementation
+ of the RFC specifications. You should use is ONLY if you can't get
+ any other ident daemon running on your machine.[br]
+*/
+
+static bool ident_kvs_cmd_start(KviKvsModuleCommandCall * c)
+{
+ if(!g_iIdentDaemonRunningUsers)
+ startIdentService();
+ g_iIdentDaemonRunningUsers++;
+ return true;
+}
+
+/*
+ @doc: ident.stop
+ @type:
+ command
+ @title:
+ ident.stop
+ @short:
+ Stops the ident service
+ @syntax:
+ ident.stop
+ @description:
+ Stops the ident service
+ @seealso:
+ [cmd]ident.start[/cmd]
+*/
+
+static bool ident_kvs_cmd_stop(KviKvsModuleCommandCall * c)
+{
+ if(g_iIdentDaemonRunningUsers) g_iIdentDaemonRunningUsers--;
+ if(!g_iIdentDaemonRunningUsers) stopIdentService();
+ return true;
+}
+
+static bool ident_module_init(KviModule *m)
+{
+ g_pIdentSentinel = new KviIdentSentinel();
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"start",ident_kvs_cmd_start);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"stop",ident_kvs_cmd_stop);
+ return true;
+}
+
+static bool ident_module_cleanup(KviModule *m)
+{
+ stopIdentService();
+ delete g_pIdentSentinel;
+ g_pIdentSentinel = 0;
+
+ return true;
+}
+
+static bool ident_module_can_unload(KviModule *m)
+{
+ return !g_pIdentDaemon;
+}
+
+KVIRC_MODULE(
+ "Ident", // module name
+ "1.0.0", // module version
+ "Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot net)", // author & (C)
+ "Ident service",
+ ident_module_init,
+ ident_module_can_unload,
+ 0,
+ ident_module_cleanup
+)
+
+#include "libkviident.moc"
diff --git a/src/modules/ident/libkviident.h b/src/modules/ident/libkviident.h
new file mode 100644
index 00000000..c6d3d390
--- /dev/null
+++ b/src/modules/ident/libkviident.h
@@ -0,0 +1,86 @@
+#ifndef _LIBKVIIDENT_H_
+#define _LIBKVIIDENT_H_
+//
+// File : libkviident.h
+// Creation date : Tue Oct 2 18:22:05 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_thread.h"
+#include "kvi_sockettype.h"
+#include "kvi_string.h"
+#include "kvi_time.h"
+#include "kvi_settings.h"
+
+#include "kvi_pointerlist.h"
+#include <qobject.h>
+
+class KviIdentRequest
+{
+public:
+ KviIdentRequest(kvi_socket_t sock,const char * host,kvi_u32_t uPort);
+ ~KviIdentRequest();
+public:
+ kvi_socket_t m_sock;
+ KviStr m_szData;
+ KviStr m_szHost;
+ kvi_u32_t m_uPort;
+ time_t m_tStart;
+};
+
+typedef struct _KviIdentMessageData
+{
+ KviStr szMessage;
+ KviStr szHost;
+ KviStr szAux;
+ unsigned int uPort;
+} KviIdentMessageData;
+
+class KviIdentSentinel : public QObject
+{
+ Q_OBJECT
+public:
+ KviIdentSentinel();
+ ~KviIdentSentinel();
+protected:
+ virtual bool event(QEvent * e);
+};
+
+
+class KviIdentDaemon : public KviSensitiveThread
+{
+public:
+ KviIdentDaemon();
+ ~KviIdentDaemon();
+private:
+ KviStr m_szUser;
+ kvi_u32_t m_uPort;
+ bool m_bEnableIpV6;
+ bool m_bIpV6ContainsIpV4;
+ kvi_socket_t m_sock;
+ kvi_socket_t m_sock6;
+ KviPointerList<KviIdentRequest> * m_pRequestList;
+public:
+ virtual void run();
+protected:
+ void postMessage(const char * message,KviIdentRequest * r,const char * szAux = 0);
+};
+
+
+#endif //_LIBKVIIDENT_H_
diff --git a/src/modules/iograph/Makefile.am b/src/modules/iograph/Makefile.am
new file mode 100644
index 00000000..a9ea3928
--- /dev/null
+++ b/src/modules/iograph/Makefile.am
@@ -0,0 +1,20 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkviiograph.la
+
+libkviiograph_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkviiograph_la_SOURCES = libkviiograph.cpp
+libkviiograph_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+noinst_HEADERS= libkviiograph.h
+
+%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
+
+libkviiograph.cpp: libkviiograph.moc
diff --git a/src/modules/iograph/libkviiograph.cpp b/src/modules/iograph/libkviiograph.cpp
new file mode 100644
index 00000000..ab9aa4f1
--- /dev/null
+++ b/src/modules/iograph/libkviiograph.cpp
@@ -0,0 +1,297 @@
+//
+// File : kvi_iograph.cpp
+// Creation date : Tue Oct 31 2000 00:14:12 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+#include "libkviiograph.h"
+#include "kvi_module.h"
+
+#if 0
+
+
+#include "kvi_console.h"
+#include "kvi_options.h"
+#include "kvi_ircsocket.h"
+#include "kvi_frame.h"
+#include "kvi_locale.h"
+
+#include "kvi_pointerlist.h"
+#include <qtooltip.h>
+#include <qpointarray.h>
+#include <qpainter.h>
+
+
+extern QPixmap * g_pIccMemBuffer;
+
+
+static KviPointerList<KviIOGraphDisplay> * g_pIOGraphWidgetList;
+
+KviIOGraphDisplay::KviIOGraphDisplay(KviIrcContextController * pController,bool sentGraph,bool recvGraph)
+: KviIrcContextGraphicalApplet(pController,"iograph_display")
+{
+ g_pIOGraphWidgetList->append(this);
+ for(int i=0;i < KVI_IOGRAPH_NUMBER_POINTS;i++)
+ {
+ m_sendRates[i] = 0;
+ m_recvRates[i] = 0;
+ }
+ m_iNextPoint = 1;
+ m_uLastSentBytes = pController->console()->socket()->sentBytes();
+ m_uLastRecvBytes = pController->console()->socket()->readBytes();
+ m_bShowSentGraph = sentGraph;
+ m_bShowRecvGraph = recvGraph;
+
+ KviStr tip;
+ if(sentGraph)tip = __tr("Outgoing traffic");
+ if(recvGraph)
+ {
+ if(tip.hasData())tip.append("\n");
+ tip.append(__tr("Incoming traffic"));
+ }
+
+ QToolTip::add(this,tip.ptr());
+
+ startTimer(1000);
+}
+
+KviIOGraphDisplay::~KviIOGraphDisplay()
+{
+ g_pIOGraphWidgetList->removeRef(this);
+}
+
+void KviIOGraphDisplay::timerEvent(QTimerEvent *e)
+{
+ unsigned int sB = console()->socket()->sentBytes();
+ unsigned int rB = console()->socket()->readBytes();
+ int sDiff = (sB - m_uLastSentBytes) / 8;
+ int rDiff = (rB - m_uLastRecvBytes) / 32;
+// debug("s:%d,r:%d",sDiff,rDiff);
+ if(sDiff < 0)sDiff = 0;
+ else if(sDiff > 30)sDiff = 30;
+ if(rDiff < 0)rDiff = 0;
+ else if(rDiff > 30)rDiff = 30;
+ m_uLastSentBytes = sB;
+ m_uLastRecvBytes = rB;
+ m_sendRates[m_iNextPoint] = sDiff;
+ m_recvRates[m_iNextPoint] = rDiff;
+ m_iNextPoint++;
+ if(m_iNextPoint >= KVI_IOGRAPH_NUMBER_POINTS)m_iNextPoint = 0;
+ update();
+}
+
+static QCOORD horizSegments[6 * 4]=
+{
+ 5 , 3 , KVI_IRCTOOLBARAPPLET_MAXIMUM_WIDTH - 4 , 3 ,
+ 5 , 8 , KVI_IRCTOOLBARAPPLET_MAXIMUM_WIDTH - 4 , 8 ,
+ 5 , 13 , KVI_IRCTOOLBARAPPLET_MAXIMUM_WIDTH - 4 , 13 ,
+ 5 , 18 , KVI_IRCTOOLBARAPPLET_MAXIMUM_WIDTH - 4 , 18 ,
+ 5 , 23 , KVI_IRCTOOLBARAPPLET_MAXIMUM_WIDTH - 4 , 23 ,
+ 5 , 28 , KVI_IRCTOOLBARAPPLET_MAXIMUM_WIDTH - 4 , 28
+};
+
+static QCOORD vertSegments[29 * 4]=
+{
+ 9 , 4 , 9 , KVI_IRCTOOLBARAPPLET_MAXIMUM_HEIGHT - 5 ,
+ 14 , 4 , 14 , KVI_IRCTOOLBARAPPLET_MAXIMUM_HEIGHT - 5 ,
+ 19 , 4 , 19 , KVI_IRCTOOLBARAPPLET_MAXIMUM_HEIGHT - 5 ,
+ 24 , 4 , 24 , KVI_IRCTOOLBARAPPLET_MAXIMUM_HEIGHT - 5 ,
+ 29 , 4 , 29 , KVI_IRCTOOLBARAPPLET_MAXIMUM_HEIGHT - 5 ,
+ 34 , 4 , 34 , KVI_IRCTOOLBARAPPLET_MAXIMUM_HEIGHT - 5 ,
+ 39 , 4 , 39 , KVI_IRCTOOLBARAPPLET_MAXIMUM_HEIGHT - 5 ,
+ 44 , 4 , 44 , KVI_IRCTOOLBARAPPLET_MAXIMUM_HEIGHT - 5 ,
+ 49 , 4 , 49 , KVI_IRCTOOLBARAPPLET_MAXIMUM_HEIGHT - 5 ,
+ 54 , 4 , 54 , KVI_IRCTOOLBARAPPLET_MAXIMUM_HEIGHT - 5 ,
+ 59 , 4 , 59 , KVI_IRCTOOLBARAPPLET_MAXIMUM_HEIGHT - 5 ,
+ 64 , 4 , 64 , KVI_IRCTOOLBARAPPLET_MAXIMUM_HEIGHT - 5 ,
+ 69 , 4 , 69 , KVI_IRCTOOLBARAPPLET_MAXIMUM_HEIGHT - 5 ,
+ 74 , 4 , 74 , KVI_IRCTOOLBARAPPLET_MAXIMUM_HEIGHT - 5 ,
+ 79 , 4 , 79 , KVI_IRCTOOLBARAPPLET_MAXIMUM_HEIGHT - 5 ,
+ 84 , 4 , 84 , KVI_IRCTOOLBARAPPLET_MAXIMUM_HEIGHT - 5 ,
+ 89 , 4 , 89 , KVI_IRCTOOLBARAPPLET_MAXIMUM_HEIGHT - 5 ,
+ 94 , 4 , 94 , KVI_IRCTOOLBARAPPLET_MAXIMUM_HEIGHT - 5 ,
+ 99 , 4 , 99 , KVI_IRCTOOLBARAPPLET_MAXIMUM_HEIGHT - 5 ,
+ 104 , 4 , 104 , KVI_IRCTOOLBARAPPLET_MAXIMUM_HEIGHT - 5 ,
+ 109 , 4 , 109 , KVI_IRCTOOLBARAPPLET_MAXIMUM_HEIGHT - 5 ,
+ 114 , 4 , 114 , KVI_IRCTOOLBARAPPLET_MAXIMUM_HEIGHT - 5 ,
+ 119 , 4 , 119 , KVI_IRCTOOLBARAPPLET_MAXIMUM_HEIGHT - 5 ,
+ 124 , 4 , 124 , KVI_IRCTOOLBARAPPLET_MAXIMUM_HEIGHT - 5 ,
+ 129 , 4 , 129 , KVI_IRCTOOLBARAPPLET_MAXIMUM_HEIGHT - 5 ,
+ 134 , 4 , 134 , KVI_IRCTOOLBARAPPLET_MAXIMUM_HEIGHT - 5 ,
+ 139 , 4 , 139 , KVI_IRCTOOLBARAPPLET_MAXIMUM_HEIGHT - 5 ,
+ 144 , 4 , 144 , KVI_IRCTOOLBARAPPLET_MAXIMUM_HEIGHT - 5 ,
+ 149 , 4 , 149 , KVI_IRCTOOLBARAPPLET_MAXIMUM_HEIGHT - 5
+};
+
+void KviIOGraphDisplay::drawContents(QPainter * p)
+{
+ static QPointArray hp(6 * 4,horizSegments);
+ static QPointArray vp(29 * 4,vertSegments);
+
+ p->setPen(KVI_OPTION_COLOR(KviOption_colorIrcToolBarAppletForegroundLowContrast));
+ p->drawLineSegments(hp,0,6);
+ p->drawLineSegments(vp,0,29);
+ p->setPen(KVI_OPTION_COLOR(KviOption_colorIrcToolBarAppletForegroundMidContrast));
+
+ p->drawLine(4,33,KVI_IRCTOOLBARAPPLET_MAXIMUM_WIDTH - 4,33);
+ p->drawLine(4,3,4,KVI_IRCTOOLBARAPPLET_MAXIMUM_HEIGHT - 5);
+
+ p->setPen(isActiveContext() ?
+ KVI_OPTION_COLOR(KviOption_colorIrcToolBarAppletForegroundHighContrastActive1) :
+ KVI_OPTION_COLOR(KviOption_colorIrcToolBarAppletForegroundHighContrastInactive1));
+
+ // the first point to draw is "m_iNextPoint"
+ // it will be drawn at X = 4
+
+ int leftPart = KVI_IOGRAPH_NUMBER_POINTS - m_iNextPoint;
+
+ int i;
+
+ if(m_bShowSentGraph)
+ {
+ for(i = 1;i < leftPart;i++)
+ {
+ p->drawLine(3 + i,33 - m_sendRates[m_iNextPoint + i - 1],4 + i,33 - m_sendRates[m_iNextPoint + i]);
+ }
+
+ p->drawLine(3 + i,33 - m_sendRates[m_iNextPoint + i - 1],4 + i,33 - m_sendRates[0]);
+
+ for(i = 1;i < m_iNextPoint;i++)
+ {
+ p->drawLine(leftPart + 3 + i,33 - m_sendRates[i - 1],leftPart + 4 + i,33 - m_sendRates[i]);
+ }
+ }
+
+ if(m_bShowRecvGraph)
+ {
+ p->setPen(isActiveContext() ?
+ KVI_OPTION_COLOR(KviOption_colorIrcToolBarAppletForegroundHighContrastActive2) :
+ KVI_OPTION_COLOR(KviOption_colorIrcToolBarAppletForegroundHighContrastInactive2));
+
+ for(i = 1;i < leftPart;i++)
+ {
+ p->drawLine(3 + i,33 - m_recvRates[m_iNextPoint + i - 1],4 + i,33 - m_recvRates[m_iNextPoint + i]);
+ }
+
+ p->drawLine(3 + i,33 - m_recvRates[m_iNextPoint + i - 1],4 + i,33 - m_recvRates[0]);
+
+ for(i = 1;i < m_iNextPoint;i++)
+ {
+ p->drawLine(leftPart + 3 + i,33 - m_recvRates[i - 1],leftPart + 4 + i,33 - m_recvRates[i]);
+ }
+ }
+}
+
+QSize KviIOGraphDisplay::sizeHint() const
+{
+ return QSize(KVI_IRCTOOLBARAPPLET_MAXIMUM_WIDTH,KVI_IRCTOOLBARAPPLET_MAXIMUM_HEIGHT);
+}
+
+
+/*
+ @doc: iograph.add
+ @type:
+ command
+ @title:
+ iograph.add
+ @short:
+ Adds an IOGraph applet
+ @syntax:
+ iograph.add [-i] [-o]
+ @description:
+ Adds an IOGraph applet to the current irc-context toolbar. It will
+ monitor the Incoming and Outgoing socket traffic.[br]
+ Since both graphs often are somewhat unreadable,
+ the -i switch will cause the IOGraph applet to show only
+ the incoming traffic, and the -o switch will cause it to show
+ only the outgoing traffic.[br]
+ Well...I agree...this is an amazing misuse of resources :)
+*/
+
+
+
+static bool iograph_module_cmd_add(KviModule *m,KviCommand *c)
+{
+ ENTER_STACK_FRAME(c,"iograph_module_cmd_add");
+
+ KviStr dummy;
+ if(!g_pUserParser->parseCmdFinalPart(c,dummy))return false;
+
+ if(!c->window()->console())return c->noIrcContext();
+
+ bool bSentGraph = !(c->hasSwitch('i'));
+ bool bRecvGraph = !(c->hasSwitch('o'));
+
+ if(!(bSentGraph || bRecvGraph))bRecvGraph = true;
+
+ KviIOGraphDisplay * dpy = new KviIOGraphDisplay(c->window()->console()->icController(),bSentGraph,bRecvGraph);
+ c->window()->console()->icController()->addApplet(dpy);
+ dpy->show();
+
+ return c->leaveStackFrame();
+}
+#endif
+
+static bool iograph_module_init(KviModule *m)
+{
+#if 0
+ g_pIOGraphWidgetList = new KviPointerList<KviIOGraphDisplay>;
+ g_pIOGraphWidgetList->setAutoDelete(false);
+ m->registerCommand("add",iograph_module_cmd_add);
+#endif
+ return true;
+}
+
+static bool iograph_module_cleanup(KviModule *m)
+{
+#if 0
+ while(g_pIOGraphWidgetList->first())
+ {
+ KviIOGraphDisplay * dpy = g_pIOGraphWidgetList->first();
+ dpy->controller()->removeApplet(dpy); // deleted path
+ }
+ delete g_pIOGraphWidgetList;
+#endif
+ return true;
+}
+
+static bool iograph_module_can_unload(KviModule *m)
+{
+#if 0
+ return g_pIOGraphWidgetList->isEmpty();
+#else
+ return true;
+#endif
+}
+
+KVIRC_MODULE(
+ "IOGraph", // module name
+ "1.0.0", // module version
+ "Copyright (C) 2000 Szymon Stefanek (pragma at kvirc dot net)", // author & (C)
+ "IRC socket traffic monitor",
+ iograph_module_init,
+ iograph_module_can_unload,
+ 0,
+ iograph_module_cleanup
+)
+
+#if 0
+#include "libkviiograph.moc"
+#endif
diff --git a/src/modules/iograph/libkviiograph.h b/src/modules/iograph/libkviiograph.h
new file mode 100644
index 00000000..9b134615
--- /dev/null
+++ b/src/modules/iograph/libkviiograph.h
@@ -0,0 +1,55 @@
+#ifndef _LIBKVIIOGRAPH_H_
+#define _LIBKVIIOGRAPH_H_
+
+//
+// File : kvi_iograph.cpp
+// Creation date : Tue Oct 31 2000 00:14:12 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#if 0
+
+#include "kvi_irctoolbar.h"
+
+
+#define KVI_IOGRAPH_NUMBER_POINTS 148
+
+class KviIOGraphDisplay : public KviIrcContextGraphicalApplet
+{
+ Q_OBJECT
+public:
+ KviIOGraphDisplay(KviIrcContextController * pController,bool sentGraph,bool recvGraph);
+ ~KviIOGraphDisplay();
+protected:
+ unsigned int m_sendRates[KVI_IOGRAPH_NUMBER_POINTS];
+ unsigned int m_recvRates[KVI_IOGRAPH_NUMBER_POINTS];
+ int m_iNextPoint;
+ unsigned int m_uLastSentBytes;
+ unsigned int m_uLastRecvBytes;
+ bool m_bShowSentGraph;
+ bool m_bShowRecvGraph;
+protected:
+ virtual void drawContents(QPainter *p);
+ virtual QSize sizeHint() const;
+ virtual void timerEvent(QTimerEvent *e);
+};
+
+#endif
+
+#endif
diff --git a/src/modules/lamerizer/Makefile.am b/src/modules/lamerizer/Makefile.am
new file mode 100644
index 00000000..ce798e5c
--- /dev/null
+++ b/src/modules/lamerizer/Makefile.am
@@ -0,0 +1,27 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkvilamerizer.la
+
+libkvilamerizer_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkvilamerizer_la_SOURCES = libkvilamerizer.cpp
+libkvilamerizer_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+noinst_HEADERS= libkvilamerizer.h
+
+tmpdir = $(pluglibdir)/caps/crypt/
+
+tmp_DATA= lamerizer
+
+EXTRA_DIST = $(tmp_DATA)
+
+
+%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
+
+libkvilamerizer.cpp: libkvilamerizer.moc
diff --git a/src/modules/lamerizer/lamerizer b/src/modules/lamerizer/lamerizer
new file mode 100644
index 00000000..9788f702
--- /dev/null
+++ b/src/modules/lamerizer/lamerizer
@@ -0,0 +1 @@
+timestamp
diff --git a/src/modules/lamerizer/libkvilamerizer.cpp b/src/modules/lamerizer/libkvilamerizer.cpp
new file mode 100644
index 00000000..adb7a194
--- /dev/null
+++ b/src/modules/lamerizer/libkvilamerizer.cpp
@@ -0,0 +1,279 @@
+//=============================================================================
+//
+// File : libkvilamerizer.cpp
+// Creation date : Sat Jan 20 2002 17:06:12 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "libkvilamerizer.h"
+
+#include "kvi_module.h"
+#include "kvi_debug.h"
+#include "kvi_locale.h"
+
+
+
+/*
+ @doc: lamerizer
+ @type:
+ module
+ @short:
+ The Lamerizer text transformation engine
+ @title:
+ The lamerizer module
+ @body:
+ This is an example of what you should NOT do with a text transformation
+ engine. Do NOT use it! :D
+*/
+
+
+
+#ifdef COMPILE_CRYPT_SUPPORT
+
+ #include "kvi_memmove.h"
+ #include "kvi_malloc.h"
+
+ #include "kvi_pointerlist.h"
+
+ static KviPointerList<KviCryptEngine> * g_pEngineList = 0;
+
+ KviLamerizerEngine::KviLamerizerEngine(bool bLight)
+ : KviCryptEngine()
+ {
+ m_bLight = bLight;
+ g_pEngineList->append(this);
+ }
+
+ KviLamerizerEngine::~KviLamerizerEngine()
+ {
+ g_pEngineList->removeRef(this);
+ }
+
+ bool KviLamerizerEngine::init(const char *,int,const char *,int)
+ {
+ return true;
+ }
+
+ static char subst_table[256] =
+ {
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 007
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 015
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 023
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 031
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 039 : '
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 047 : /
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 055 : 7
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 063 : ?
+ 0 , '4' , '8' , 'C' , 'D' , '3' , 'F' , 'G' , // 071 : G
+ 'H' , '|' , 'J' , 'K' , 'L' , 'm' , 'N' , 'O' , // 079 : O
+ 'P' , 'q' , 'R' , '5' , '7' , 'U' , 'V' , 'W' , // 087 : W
+ 'x' , 'Y' , '2' , 0 , 0 , 0 , 0 , 0 , // 095 : _
+ 0 , '4' , 'b' , 'c' , 'd' , '3' , 'f' , '9' , // 103 : g
+ 'h' , '|' , 'j' , 'k' , '1' , 'm' , 'n' , '0' ,
+ 'p' , 'q' , 'r' , '5' , '7' , 'u' , 'v' , 'w' , // 119 : w
+ 'x' , 'y' , '2' , 0 , 0 , 0 , 0 , 0 , // 127 :
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 135 :
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 143 :
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 151 :
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 159 :
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 167 :
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 175 :
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 183 :
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 191 :
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 199 :
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 215 :
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 223 :
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 231 :
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 239 :
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 247 :
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
+ };
+
+ static char subst_table_light[256] =
+ {
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 007
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 015
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 023
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 031
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 039 : '
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 047 : /
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 055 : 7
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 063 : ?
+ 0 , '4' , 'B' , 'C' , 'D' , '3' , 'F' , 'G' , // 071 : G
+ 'H' , '|' , 'J' , 'K' , 'L' , 'm' , 'N' , 'O' , // 079 : O
+ 'P' , 'q' , 'R' , '5' , '7' , 'U' , 'V' , 'W' , // 087 : W
+ 'x' , 'Y' , 'Z' , 0 , 0 , 0 , 0 , 0 , // 095 : _
+ 0 , '4' , 'b' , 'c' , 'd' , '3' , 'f' , 'G' , // 103 : g
+ 'h' , '|' , 'j' , 'k' , '1' , 'm' , 'n' , '0' ,
+ 'p' , 'q' , 'r' , '5' , '7' , 'u' , 'v' , 'w' , // 119 : w
+ 'x' , 'y' , 'z' , 0 , 0 , 0 , 0 , 0 , // 127 :
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 135 :
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 143 :
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 151 :
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 159 :
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 167 :
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 175 :
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 183 :
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 191 :
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 199 :
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 215 :
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 223 :
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 231 :
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 239 :
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // 247 :
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
+ };
+
+
+ KviCryptEngine::EncryptResult KviLamerizerEngine::encrypt(const char * plainText,KviStr &outBuffer)
+ {
+ outBuffer = plainText;
+ unsigned char * aux = (unsigned char *)outBuffer.ptr();
+ if(m_bLight)
+ {
+ while(*aux)
+ {
+ if(subst_table_light[*aux])
+ {
+ *aux = subst_table_light[*aux];
+ }
+ aux++;
+ }
+ } else {
+ while(*aux)
+ {
+ if(subst_table[*aux])
+ {
+ *aux = subst_table[*aux];
+ }
+ aux++;
+ }
+ }
+
+ if(!m_bLight)
+ {
+ outBuffer.replaceAll("F","Ph");
+ outBuffer.replaceAll("V","\\/");
+ }
+
+ return KviCryptEngine::Encoded;
+ }
+
+ KviCryptEngine::DecryptResult KviLamerizerEngine::decrypt(const char * inBuffer,KviStr &plainText)
+ {
+ plainText = inBuffer;
+ return KviCryptEngine::DecryptOkWasPlainText;
+ }
+
+ static KviCryptEngine * allocLamerizerEngine()
+ {
+ return new KviLamerizerEngine(false);
+ }
+
+ static KviCryptEngine * allocLightLamerizerEngine()
+ {
+ return new KviLamerizerEngine(true);
+ }
+
+ static void deallocLamerizerEngine(KviCryptEngine * e)
+ {
+ delete e;
+ }
+
+#endif
+
+
+// =======================================
+// module routines
+// =======================================
+static bool lamerizer_module_init(KviModule * m)
+{
+#ifdef COMPILE_CRYPT_SUPPORT
+ g_pEngineList = new KviPointerList<KviCryptEngine>;
+ g_pEngineList->setAutoDelete(false);
+
+ // FIXME: Maybe convert this repeated code to a function eh ?
+
+ KviCryptEngineDescription * d = new KviCryptEngineDescription;
+ d->szName = "Lamerizer";
+ d->szAuthor = "Szymon Stefanek and Jan Wagner";
+ d->szDescription = __tr2qs("A really lame text transformation engine :D");
+ d->iFlags = KVI_CRYPTENGINE_CAN_ENCRYPT;
+ d->allocFunc = allocLamerizerEngine;
+ d->deallocFunc = deallocLamerizerEngine;
+ m->registerCryptEngine(d);
+
+
+ d = new KviCryptEngineDescription;
+ d->szName = "LamerizerLight";
+ d->szAuthor = "Szymon Stefanek and Jan Wagner";
+ d->szDescription = __tr2qs("A really lame text transformation engine: Light Version.");
+ d->iFlags = KVI_CRYPTENGINE_CAN_ENCRYPT;
+ d->allocFunc = allocLightLamerizerEngine;
+ d->deallocFunc = deallocLamerizerEngine;
+ m->registerCryptEngine(d);
+
+ return true;
+#else
+ return false;
+#endif
+}
+
+static bool lamerizer_module_cleanup(KviModule *m)
+{
+#ifdef COMPILE_CRYPT_SUPPORT
+ while(g_pEngineList->first())delete g_pEngineList->first();
+ delete g_pEngineList;
+ g_pEngineList = 0;
+ m->unregisterCryptEngines();
+ return true;
+#else
+ return false;
+#endif
+}
+
+static bool lamerizer_module_can_unload(KviModule *)
+{
+#ifdef COMPILE_CRYPT_SUPPORT
+ return g_pEngineList->isEmpty();
+#else
+ return true;
+#endif
+}
+
+// =======================================
+// plugin definition structure
+// =======================================
+KVIRC_MODULE(
+ "Lamerizer crypt engine",
+ "1.0.1",
+ "Szymon Stefanek <pragma at kvirc dot net> \n Jan Wagner <istari@kvirc.net>" ,
+ "Exports the lamerizer text transformation engine",
+ lamerizer_module_init ,
+ lamerizer_module_can_unload,
+ 0,
+ lamerizer_module_cleanup
+)
+
+#ifdef COMPILE_CRYPT_SUPPORT
+ #include "libkvilamerizer.moc"
+#endif
diff --git a/src/modules/lamerizer/libkvilamerizer.h b/src/modules/lamerizer/libkvilamerizer.h
new file mode 100644
index 00000000..e0b78bd7
--- /dev/null
+++ b/src/modules/lamerizer/libkvilamerizer.h
@@ -0,0 +1,47 @@
+#ifndef _LIBKVILAMERIZER_H_
+#define _LIBKVILAMERIZER_H_
+//
+// File : libkvilamerizer.h
+// Creation date : Sat Now 4 2000 15:41:41 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Till Bush (buti@geocities.com)
+//
+// 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_CRYPT_SUPPORT
+
+ #include "kvi_crypt.h"
+
+ class KviLamerizerEngine : public KviCryptEngine
+ {
+ Q_OBJECT
+ public:
+ KviLamerizerEngine(bool bLight);
+ ~KviLamerizerEngine();
+ protected:
+ bool m_bLight;
+ public:
+ virtual bool init(const char *encKey,int encKeyLen,const char *decKey,int decKeyLen);
+ virtual KviCryptEngine::EncryptResult encrypt(const char * plainText,KviStr &outBuffer);
+ virtual KviCryptEngine::DecryptResult decrypt(const char * inBuffer,KviStr &plainText);
+ };
+
+#endif // COMPILE_CRYPT_SUPPORT
+
+#endif // _LIBKVILAMERIZER_H_
diff --git a/src/modules/links/Makefile.am b/src/modules/links/Makefile.am
new file mode 100644
index 00000000..51eea094
--- /dev/null
+++ b/src/modules/links/Makefile.am
@@ -0,0 +1,20 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkvilinks.la
+
+libkvilinks_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkvilinks_la_SOURCES = libkvilinks.cpp linkswindow.cpp
+libkvilinks_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+noinst_HEADERS= linkswindow.h
+
+m_%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
+
+linkswindow.cpp: m_linkswindow.moc
diff --git a/src/modules/links/libkvilinks.cpp b/src/modules/links/libkvilinks.cpp
new file mode 100644
index 00000000..6486b985
--- /dev/null
+++ b/src/modules/links/libkvilinks.cpp
@@ -0,0 +1,116 @@
+//
+// File : libkvilinks.cpp
+// Creation date : Thu Dec 21 2000 12:39:12 CEST by Szymon Stefanek
+//
+// Copyright (C) 1999-2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+#include "kvi_module.h"
+
+
+#include "linkswindow.h"
+
+#include "kvi_frame.h"
+#include "kvi_window.h"
+#include "kvi_locale.h"
+
+#include <qsplitter.h>
+
+KviPointerList<KviLinksWindow> * g_pLinksWindowList = 0;
+
+
+/*
+ @doc: links.open
+ @type:
+ command
+ @title:
+ links.open
+ @short:
+ Opens a Links window
+ @syntax:
+ links.open
+ @description:
+ Opens a "links" window attacched to the current irc context.[br]
+ The links window handles the RPL_LINKS server replies and shows
+ them in a Tree-View form: this is useful in vizualizing the
+ current network connections.[br]
+ Please note that the total number of links received (and the
+ total count of servers displayed when all the links have been received)
+ may actually be less than the real number of irc servers in the network.
+ Servers that contain a wildcard in their name often act as gateways (hubs)
+ for a "local irc network"; if you're requesting links from a server that is
+ external to the gateway, the servers internal to the network "behind the gateway"
+ will not be shown; in the extreme case you will see the gateway as leaf node (and it isn't).
+ To see the internal network server tree you might request LINKS from the gateway server.[br]
+*/
+
+
+static bool links_kvs_cmd_open(KviKvsModuleCommandCall * c)
+{
+
+ // FIND ME
+ if(!c->window()->console())return c->context()->errorNoIrcContext();
+
+ if(!(c->window()->console()->ircContext()->linksWindow()))
+ {
+ KviLinksWindow *w = new KviLinksWindow(c->window()->frame(),c->window()->console());
+ c->window()->frame()->addWindow(w);
+ } else {
+ c->warning(__tr2qs("Links window alread open for this IRC context"));
+ }
+
+ return true;
+}
+
+
+
+
+static bool links_module_init(KviModule * m)
+{
+ g_pLinksWindowList = new KviPointerList<KviLinksWindow>;
+ g_pLinksWindowList->setAutoDelete(false);
+
+
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"open",links_kvs_cmd_open);
+
+ return true;
+}
+
+static bool links_module_cleanup(KviModule *m)
+{
+ while(g_pLinksWindowList->first())g_pLinksWindowList->first()->die();
+ delete g_pLinksWindowList;
+ g_pLinksWindowList = 0;
+ return true;
+}
+
+static bool links_module_can_unload(KviModule *m)
+{
+ return (g_pLinksWindowList->isEmpty());
+}
+
+KVIRC_MODULE(
+ "Links", // module name
+ "1.0.0", // module version
+ "Copyright (C) 2000-2001 Szymon Stefanek (pragma at kvirc dot net)", // author & (C)
+ "Links window extension",
+ links_module_init,
+ links_module_can_unload,
+ 0,
+ links_module_cleanup
+)
diff --git a/src/modules/links/linkswindow.cpp b/src/modules/links/linkswindow.cpp
new file mode 100644
index 00000000..1dd567f5
--- /dev/null
+++ b/src/modules/links/linkswindow.cpp
@@ -0,0 +1,472 @@
+//
+// File : linkswindow.cpp
+// Creation date : Thu Dec 21 2001 12:41:18 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+#include "linkswindow.h"
+
+#include "kvi_debug.h"
+#include "kvi_iconmanager.h"
+#include "kvi_ircview.h"
+#include "kvi_out.h"
+#include "kvi_options.h"
+#include "kvi_locale.h"
+#include "kvi_out.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_themedlabel.h"
+#include "kvi_irccontext.h"
+#include "kvi_ircconnection.h"
+
+#include <qsplitter.h>
+#include <qtooltip.h>
+#include "kvi_tal_hbox.h"
+#include <qlabel.h>
+
+extern KviPointerList<KviLinksWindow> * g_pLinksWindowList;
+
+KviLinksWindow::KviLinksWindow(KviFrame * lpFrm,KviConsole * lpConsole)
+: KviWindow(KVI_WINDOW_TYPE_LINKS,lpFrm,"links",lpConsole) , KviExternalServerDataParser()
+{
+ g_pLinksWindowList->append(this);
+
+ m_pTopSplitter = new QSplitter(Qt::Horizontal,this,"top_splitter");
+
+ // The button box on the left
+ KviTalHBox * box = new KviTalHBox(m_pTopSplitter);
+
+ m_pRequestButton = new QToolButton(box,"request_button");
+ m_pRequestButton->setUsesBigPixmap(false);
+ m_pRequestButton->setPixmap(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_LINKS)));
+ connect(m_pRequestButton,SIGNAL(clicked()),this,SLOT(requestLinks()));
+ QToolTip::add(m_pRequestButton,__tr2qs("Request Links"));
+
+ QLabel * l = new QLabel(box,"");
+ box->setStretchFactor(l,1);
+ m_pInfoLabel = new KviThemedLabel(m_pTopSplitter,"info_label");
+
+ connect(lpConsole->context(),SIGNAL(stateChanged()),
+ this,SLOT(connectionStateChange()));
+
+ m_pSplitter = new QSplitter(Qt::Horizontal,this,"splitter");
+ m_pVertSplitter = new QSplitter(Qt::Vertical,m_pSplitter,"vsplitter");
+
+ m_pListView = new KviTalListView(m_pVertSplitter);
+ m_pListView->addColumn(__tr2qs("Link"));
+ m_pListView->addColumn(__tr2qs("Hops"));
+ m_pListView->addColumn(__tr2qs("Description"));
+ m_pListView->setRootIsDecorated(true);
+ m_pListView->setAllColumnsShowFocus(true);
+ connect(m_pListView,SIGNAL(rightButtonPressed(KviTalListViewItem *,const QPoint &,int)),
+ this,SLOT(showHostPopup(KviTalListViewItem *,const QPoint &,int)));
+
+ m_pIrcView = new KviIrcView(m_pVertSplitter,lpFrm,this);
+
+ m_pLinkList = new KviPointerList<KviLink>;
+ m_pLinkList->setAutoDelete(true);
+
+ m_pHostPopup = new KviTalPopupMenu();
+ connect(m_pHostPopup,SIGNAL(activated(int)),this,SLOT(hostPopupClicked(int)));
+
+ connectionStateChange();
+
+ m_pConsole->ircContext()->setLinksWindowPointer(this);
+
+ m_szRootServer = __tr2qs("(None)");
+}
+
+KviLinksWindow::~KviLinksWindow()
+{
+ g_pLinksWindowList->removeRef(this);
+ m_pConsole->ircContext()->setLinksWindowPointer(0);
+ delete m_pLinkList;
+ delete m_pHostPopup;
+}
+
+void KviLinksWindow::getBaseLogFileName(KviStr &buffer)
+{
+ buffer.sprintf("LINKS_%d",console()->ircContextId());
+}
+
+
+void KviLinksWindow::requestLinks()
+{
+ if(m_pConsole->isConnected())
+ {
+ m_pConsole->connection()->sendFmtData("links");
+ outputNoFmt(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Sent links request, waiting for reply..."));
+ m_pRequestButton->setEnabled(false);
+ } else {
+ outputNoFmt(KVI_OUT_SYSTEMERROR,__tr2qs("Cannot request links: No active connection"));
+ }
+}
+
+void KviLinksWindow::connectionStateChange()
+{
+ KviIrcContext::State st = m_pConsole->context()->state();
+ m_pRequestButton->setEnabled(st == KviIrcContext::Connected);
+ if(st == KviIrcContext::Connected)
+ {
+ KviStr tmp(KviStr::Format,__tr2qs("Connected to %s (%s)"),m_pConsole->connection()->currentServerName().utf8().data(),m_pConsole->currentNetworkName().utf8().data());
+ m_pInfoLabel->setText(tmp.ptr());
+ } else {
+ m_pInfoLabel->setText(__tr2qs("Links cannot be requested: Not connected to a server"));
+ }
+}
+
+QPixmap * KviLinksWindow::myIconPtr()
+{
+ return g_pIconManager->getSmallIcon(KVI_SMALLICON_LINKS);
+}
+
+void KviLinksWindow::resizeEvent(QResizeEvent *e)
+{
+ int hght2 = m_pTopSplitter->sizeHint().height();
+ m_pTopSplitter->setGeometry(0,0,width(),hght2);
+ m_pSplitter->setGeometry(0,hght2,width(),height() - hght2);
+}
+
+QSize KviLinksWindow::sizeHint() const
+{
+ QSize ret(m_pSplitter->sizeHint().width(),
+ m_pSplitter->sizeHint().height() + m_pTopSplitter->sizeHint().height());
+ return ret;
+}
+
+void KviLinksWindow::fillCaptionBuffers()
+{
+ KviQString::sprintf(m_szPlainTextCaption,__tr2qs("Links for %Q [IRC Context %u]"),&m_szRootServer,m_pConsole->ircContextId());
+
+ KviQString::sprintf(m_szHtmlActiveCaption,
+ __tr2qs("<nobr><font color=\"%s\"><b>Links for %Q</b></font> " \
+ "<font color=\"%s\">[IRC Context %u]</font></nobr>"),
+ KVI_OPTION_COLOR(KviOption_colorCaptionTextActive).name().ascii(),
+ &m_szRootServer,
+ KVI_OPTION_COLOR(KviOption_colorCaptionTextActive2).name().ascii(),
+ m_pConsole->ircContextId());
+
+ KviQString::sprintf(m_szHtmlInactiveCaption,
+ __tr2qs("<nobr><font color=\"%s\"><b>Links for %Q</b></font> " \
+ "<font color=\"%s\">[IRC Context %u]</font></nobr>"),
+ KVI_OPTION_COLOR(KviOption_colorCaptionTextInactive).name().ascii(),
+ &m_szRootServer,
+ KVI_OPTION_COLOR(KviOption_colorCaptionTextInactive2).name().ascii(),
+ m_pConsole->ircContextId());
+}
+
+void KviLinksWindow::die()
+{
+ close();
+}
+
+void KviLinksWindow::control(int message)
+{
+ switch(message)
+ {
+ case EXTERNAL_SERVER_DATA_PARSER_CONTROL_RESET: reset(); break;
+ case EXTERNAL_SERVER_DATA_PARSER_CONTROL_ENDOFDATA: endOfLinks(); break;
+ }
+}
+
+void KviLinksWindow::endOfLinks()
+{
+ m_pRequestButton->setEnabled(true);
+
+ m_pListView->clear();
+ m_pListView->setSorting(-1);
+
+ outputNoFmt(KVI_OUT_SYSTEMMESSAGE,"======================");
+ outputNoFmt(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Received end of links."));
+ outputNoFmt(KVI_OUT_SYSTEMMESSAGE,"======================");
+
+ KviTalListViewItem * it = 0;
+ KviTalListViewItem * root = 0;
+
+ int totalHosts = 0;
+ int totalHops = 0;
+ int maxHops = 0;
+ int avgHops = 0;
+ int directLinks = 0;
+ int nearLinks = 0;
+ int brokenLinks = 0;
+ int maxLinks = 0;
+ int farLinks = 0;
+ int wildServers = 0;
+
+ KviStr szMaxHop,szMaxLinks;
+
+ m_pListView->setUpdatesEnabled(false);
+ for(KviLink *l=m_pLinkList->first();l;l=m_pLinkList->next()){
+ totalHosts++;
+ if(l->hops == 0)root = new KviTalListViewItem(m_pListView,QString(l->host.ptr()),"0",QString(l->description.ptr()));
+ else {
+ totalHops += l->hops;
+ if(l->hops < 4){
+ nearLinks++;
+ if(l->hops == 1)directLinks++;
+ } else {
+ if(l->hops >= 7)farLinks++;
+ }
+ if(l->hops == maxHops){
+ szMaxHop.append(',');
+ szMaxHop.append(l->host);
+ } else if(l->hops > maxHops){
+ maxHops = l->hops;
+ szMaxHop = l->host;
+ }
+ if(l->host.contains('*'))wildServers++;
+ it = insertLink(l);
+ if(!it){
+ output(KVI_OUT_SYSTEMERROR,__tr2qs("Broken link: Missing parent (%s) for %s (%d hops): %s (used /LINKS <mask> ?)"),
+ l->parent.ptr(),l->host.ptr(),l->hops,l->description.ptr());
+ brokenLinks++;
+ KviStr tmp(KviStr::Format,__tr2qs("%s: Parent link %s"),l->description.ptr(),l->parent.ptr());
+ KviStr tmp2(KviStr::Format,"%d",l->hops);
+ if(root)it = new KviTalListViewItem(m_pListView,root,QString(l->host.ptr()),QString(tmp2.ptr()),QString(tmp.ptr()));
+ else {
+ outputNoFmt(KVI_OUT_SYSTEMERROR,__tr2qs("Warning: No root link was sent by the server, the stats may be invalid."));
+ it = new KviTalListViewItem(m_pListView,QString(l->host.ptr()),QString(tmp2.ptr()),QString(tmp.ptr()));
+ }
+ } else {
+ it = it->parent();
+ if(it)
+ {
+ int links = it->childCount() + 1;
+ if(links == maxLinks)
+ {
+ szMaxLinks.append(',');
+ szMaxLinks.append(it->text(0));
+ } else if(links > maxLinks)
+ {
+ maxLinks = links;
+ szMaxLinks = it->text(0);
+ }
+ }
+ }
+ }
+ }
+
+ avgHops = ((totalHosts > 0) ? ((totalHops * 100) / totalHosts) : 0 );
+ int nearProcent = ((totalHosts > 0) ? ((nearLinks * 10000) / totalHosts) : 0);
+ int directProcent = ((totalHosts > 0) ? ((directLinks * 10000) / totalHosts) : 0);
+ int midLinks = totalHosts - (farLinks + nearLinks + 1 + brokenLinks);
+ if(midLinks < 0)midLinks = 0;
+ int midProcent = ((totalHosts > 0) ? ((midLinks * 10000) / totalHosts) : 0);
+ int farProcent = ((totalHosts > 0) ? ((farLinks * 10000) / totalHosts) : 0);
+
+ outputNoFmt(KVI_OUT_LINKS,"======================");
+
+// if(!root)root = m_pListView->firstChild();
+ if(root)
+ {
+ m_szRootServer = root->text(0);
+ output(KVI_OUT_LINKS,__tr2qs("%c%cLinks for %Q"),KVI_TEXT_BOLD,KVI_TEXT_UNDERLINE,&m_szRootServer);
+ outputNoFmt(KVI_OUT_LINKS,"======================");
+ QString tmpo = wildServers ? __tr2qs("Total hosts listed") : __tr2qs("Total hosts in the network");
+ output(KVI_OUT_LINKS,"%Q: %d",&tmpo,totalHosts);
+ if(wildServers)output(KVI_OUT_LINKS,__tr2qs("Wildcard servers (hubs?): %d"),wildServers);
+ output(KVI_OUT_LINKS,__tr2qs("Direct links: %d (~%d.%d %)"),directLinks,directProcent / 100, directProcent % 100);
+ output(KVI_OUT_LINKS,__tr2qs("Close links (1 <= hops <= 3): %d (~%d.%d %)"),nearLinks,nearProcent / 100,nearProcent % 100);
+ output(KVI_OUT_LINKS,__tr2qs("Mid-range links (4 <= hops <= 6): %d (~%d.%d %)"),midLinks,midProcent / 100,midProcent % 100);
+ output(KVI_OUT_LINKS,__tr2qs("Distant links (7 <= hops): %d (~%d.%d %)"),farLinks,farProcent / 100,farProcent % 100);
+ output(KVI_OUT_LINKS,__tr2qs("Broken (unknown) links: %d"),brokenLinks);
+ output(KVI_OUT_LINKS,__tr2qs("Maximum links per host: %d [%s]"),maxLinks,szMaxLinks.ptr());
+ output(KVI_OUT_LINKS,__tr2qs("Total links: %d"),totalHops);
+ output(KVI_OUT_LINKS,__tr2qs("Maximum hops: %d [%s]"),maxHops,szMaxHop.ptr());
+ output(KVI_OUT_LINKS,__tr2qs("Average hops: ~%d.%d"),avgHops / 100,avgHops % 100);
+ } else {
+ m_szRootServer = __tr2qs("(Unknown)");
+ outputNoFmt(KVI_OUT_LINKS,__tr2qs("Incomplete LINKS result, no stats available"));
+ }
+ outputNoFmt(KVI_OUT_LINKS,"======================");
+
+ updateCaption();
+
+
+ while(!m_pLinkList->isEmpty())m_pLinkList->removeFirst();
+
+ m_pListView->setUpdatesEnabled(true);
+ m_pListView->repaint();
+}
+
+KviTalListViewItem * KviLinksWindow::insertLink(KviLink *l)
+{
+ __range_valid(l->hops > 0);
+ KviTalListViewItem * i = getItemByHost(l->parent.ptr(),0);
+ KviTalListViewItem * it = 0;
+ if(!i)return 0;
+ else {
+ KviStr hops(KviStr::Format,"%d",l->hops);
+ it = new KviTalListViewItem(i,QString(l->host.ptr()),QString(hops.ptr()),QString(l->description.ptr()));
+ i->setOpen(true);
+ }
+ return it;
+}
+
+KviTalListViewItem * KviLinksWindow::getItemByHost(const char *host,KviTalListViewItem * par)
+{
+ KviTalListViewItem * i = (par ? par->firstChild() : m_pListView->firstChild());
+ if(!i)return 0;
+ while(i){
+ KviStr tmp = i->text(0);
+ if(kvi_strEqualCI(tmp.ptr(),host))return i;
+ KviTalListViewItem * ch = getItemByHost(host,i);
+ if(ch)return ch;
+ i = i->nextSibling();
+ }
+ return 0;
+}
+
+void KviLinksWindow::showHostPopup(KviTalListViewItem *i,const QPoint &p,int)
+{
+ if(!i)return;
+ KviStr host=i->text(0);
+ if(host.isEmpty())return;
+ m_pHostPopup->clear();
+ KviStr tmp(KviStr::Format,"LINKS %s *",host.ptr());
+ m_pHostPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_LINKS)),tmp.ptr());
+ m_pHostPopup->insertSeparator();
+ tmp.sprintf("TIME %s",host.ptr());
+ m_pHostPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TIME)),tmp.ptr());
+ tmp.sprintf("ADMIN %s",host.ptr());
+ m_pHostPopup->insertItem(tmp.ptr());
+ tmp.sprintf("INFO %s",host.ptr());
+ m_pHostPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_SERVERINFO)),tmp.ptr());
+ tmp.sprintf("MOTD %s",host.ptr());
+ m_pHostPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_MOTD)),tmp.ptr());
+ tmp.sprintf("VERSION %s",host.ptr());
+ m_pHostPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_KVIRC)),tmp.ptr());
+ tmp.sprintf("TRACE %s",host.ptr());
+ m_pHostPopup->insertItem(tmp.ptr());
+ tmp.sprintf("USERS %s",host.ptr());
+ m_pHostPopup->insertItem(tmp.ptr());
+ m_pHostPopup->insertSeparator();
+ tmp.sprintf("STATS c %s",host.ptr());
+ m_pHostPopup->insertItem(tmp.ptr());
+ tmp.sprintf("STATS d %s",host.ptr());
+ m_pHostPopup->insertItem(tmp.ptr());
+ tmp.sprintf("STATS h %s",host.ptr());
+ m_pHostPopup->insertItem(tmp.ptr());
+ tmp.sprintf("STATS i %s",host.ptr());
+ m_pHostPopup->insertItem(tmp.ptr());
+ tmp.sprintf("STATS k %s",host.ptr());
+ m_pHostPopup->insertItem(tmp.ptr());
+ tmp.sprintf("STATS l %s",host.ptr());
+ m_pHostPopup->insertItem(tmp.ptr());
+ tmp.sprintf("STATS m %s",host.ptr());
+ m_pHostPopup->insertItem(tmp.ptr());
+ tmp.sprintf("STATS o %s",host.ptr());
+ m_pHostPopup->insertItem(tmp.ptr());
+ tmp.sprintf("STATS t %s",host.ptr());
+ m_pHostPopup->insertItem(tmp.ptr());
+ tmp.sprintf("STATS u %s",host.ptr());
+ m_pHostPopup->insertItem(tmp.ptr());
+ tmp.sprintf("STATS y %s",host.ptr());
+ m_pHostPopup->insertItem(tmp.ptr());
+ tmp.sprintf("STATS z %s",host.ptr());
+ m_pHostPopup->insertItem(tmp.ptr());
+ m_pHostPopup->popup(p);
+}
+
+void KviLinksWindow::hostPopupClicked(int id)
+{
+ KviStr tmp = m_pHostPopup->text(id);
+ if(tmp.hasData())
+ {
+ if(!connection())output(KVI_OUT_SYSTEMERROR,__tr2qs("You're not connected to a server"));
+ m_pConsole->connection()->sendData(tmp.ptr());
+ }
+}
+
+void KviLinksWindow::reset()
+{
+ outputNoFmt(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Reset"));
+ while(!m_pLinkList->isEmpty())m_pLinkList->removeFirst();
+}
+
+void KviLinksWindow::processData(KviIrcMessage *msg)
+{
+ output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Processing link: %s"),msg->allParams());
+ KviLink * l = new KviLink;
+
+ l->host = msg->safeParam(1);
+ l->parent = msg->safeParam(2);
+
+ const char * tr = msg->safeTrailing();
+
+ if(isdigit(*tr))
+ {
+ const char *aux = tr;
+ while(*tr && (isdigit(*tr)))tr++;
+ KviStr tmp(aux,tr - aux);
+ l->hops = tmp.toInt();
+ } else {
+ outputNoFmt(KVI_OUT_SYSTEMERROR,__tr2qs("Broken message syntax, can't extract hops number, assuming 0"));
+ l->hops = 0;
+ }
+ while(*tr && (*tr == ' '))tr++;
+ l->description = tr;
+ uint idx=0;
+ for(KviLink *m=m_pLinkList->first();m;m=m_pLinkList->next())
+ {
+ if(m->hops >= l->hops)
+ {
+ m_pLinkList->insert(idx,l);
+ return;
+ }
+ idx++;
+ }
+ m_pLinkList->append(l);
+}
+
+//#warning "Load & save properties of this kind of window"
+
+//void KviLinksWindow::saveProperties()
+//{
+// KviWindowProperty p;
+// p.rect = externalGeometry();
+// p.isDocked = isAttacched();
+// QValueList<int> l(m_pSplitter->sizes());
+// if(l.count() >= 1)p.splitWidth1 = *(l.at(0));
+// if(l.count() >= 2)p.splitWidth2 = *(l.at(1));
+// p.timestamp = m_pView->timestamp();
+// p.imagesVisible = m_pView->imagesVisible();
+// p.isMaximized = isAttacched() && isMaximized();
+// p.topSplitWidth1 = 0;
+// p.topSplitWidth2 = 0;
+// p.topSplitWidth3 = 0;
+// g_pOptions->m_pWinPropertiesList->setProperty(caption(),&p);
+//}
+//
+//void KviLinksWindow::setProperties(KviWindowProperty *p)
+//{
+// QValueList<int> l;
+// l.append(p->splitWidth1);
+// l.append(p->splitWidth2);
+// m_pVertSplitter->setSizes(l);
+// m_pIrcView->setTimestamp(p->timestamp);
+// m_pIrcView->setShowImages(p->imagesVisible);
+//}
+
+void KviLinksWindow::applyOptions()
+{
+ m_pIrcView->applyOptions();
+ KviWindow::applyOptions();
+}
+
+#include "m_linkswindow.moc"
diff --git a/src/modules/links/linkswindow.h b/src/modules/links/linkswindow.h
new file mode 100644
index 00000000..b9cba76e
--- /dev/null
+++ b/src/modules/links/linkswindow.h
@@ -0,0 +1,89 @@
+#ifndef _LINKSWINDOW_H_
+#define _LINKSWINDOW_H_
+//
+// File : linkswindow.h
+// Creation date : Thu Dec 21 2000 12:42:55 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2001 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the linkss of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) 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.
+//
+
+#include "kvi_window.h"
+#include "kvi_string.h"
+#include "kvi_ircsocket.h"
+#include "kvi_sparser.h"
+#include "kvi_console.h"
+#include "kvi_irccontext.h"
+
+#include "kvi_tal_listview.h"
+#include "kvi_tal_popupmenu.h"
+#include <qtoolbutton.h>
+
+class KviThemedLabel;
+
+
+typedef struct _KviLink
+{
+ KviStr host;
+ KviStr parent;
+ int hops;
+ KviStr description;
+} KviLink;
+
+
+class KviLinksWindow : public KviWindow, public KviExternalServerDataParser
+{
+ Q_OBJECT
+public:
+ KviLinksWindow(KviFrame * lpFrm,KviConsole * lpConsole);
+ ~KviLinksWindow();
+protected:
+ QSplitter * m_pVertSplitter;
+ QSplitter * m_pTopSplitter;
+ KviTalListView * m_pListView;
+ KviPointerList<KviLink> * m_pLinkList;
+ KviTalPopupMenu * m_pHostPopup;
+ QString m_szRootServer;
+ QToolButton * m_pRequestButton;
+ KviThemedLabel * m_pInfoLabel;
+public: // Methods
+ virtual void control(int msg);
+ virtual void processData(KviIrcMessage * msg);
+ virtual void die();
+protected:
+ virtual QPixmap * myIconPtr();
+ virtual void fillCaptionBuffers();
+ virtual void applyOptions();
+ virtual void resizeEvent(QResizeEvent *e);
+ virtual void getBaseLogFileName(KviStr &buffer);
+// virtual void setProperties(KviWindowProperty *p);
+// virtual void saveProperties();
+protected slots:
+ void showHostPopup(KviTalListViewItem *i,const QPoint &p,int c);
+ void hostPopupClicked(int id);
+ void requestLinks();
+ void connectionStateChange();
+public:
+ virtual QSize sizeHint() const;
+private:
+ void reset();
+ void endOfLinks();
+ KviTalListViewItem * insertLink(KviLink * l);
+ KviTalListViewItem * getItemByHost(const char *host,KviTalListViewItem * par);
+};
+
+#endif //_KVI_LINKSWINDOW_H_
diff --git a/src/modules/list/Makefile.am b/src/modules/list/Makefile.am
new file mode 100644
index 00000000..52290210
--- /dev/null
+++ b/src/modules/list/Makefile.am
@@ -0,0 +1,20 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkvilist.la
+
+libkvilist_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkvilist_la_SOURCES = libkvilist.cpp listwindow.cpp
+libkvilist_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+noinst_HEADERS= listwindow.h
+
+%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
+
+listwindow.cpp: listwindow.moc
diff --git a/src/modules/list/libkvilist.cpp b/src/modules/list/libkvilist.cpp
new file mode 100644
index 00000000..7920934d
--- /dev/null
+++ b/src/modules/list/libkvilist.cpp
@@ -0,0 +1,101 @@
+//
+// File : libkvilist.cpp
+// Creation date : Sun Oct 21 2001 13:29:12 CEST by Szymon Stefanek
+//
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+#include "kvi_module.h"
+
+
+#include "listwindow.h"
+
+#include "kvi_frame.h"
+#include "kvi_window.h"
+#include "kvi_locale.h"
+
+#include <qsplitter.h>
+
+KviPointerList<KviListWindow> * g_pListWindowList = 0;
+
+
+/*
+ @doc: list.open
+ @type:
+ command
+ @title:
+ list.open
+ @short:
+ Opens a List window
+ @syntax:
+ list.open
+ @description:
+ Opens the channel list window attacched to the current irc context.[br]
+ The channel list window is opened automatically when a channel list
+ is requested from the server.
+*/
+
+static bool list_kvs_cmd_open(KviKvsModuleCommandCall * c)
+{
+
+ if(!c->window()->console())return c->context()->errorNoIrcContext();
+
+ if(!(c->window()->console()->ircContext()->listWindow()))
+ {
+ KviListWindow *w = new KviListWindow(c->window()->frame(),c->window()->console());
+ c->window()->frame()->addWindow(w);
+ } else {
+ c->warning(__tr2qs("List window alread open for this IRC context"));
+ }
+ return true;
+}
+
+
+
+static bool list_module_init(KviModule * m)
+{
+ g_pListWindowList = new KviPointerList<KviListWindow>;
+ g_pListWindowList->setAutoDelete(false);
+
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"open",list_kvs_cmd_open);
+ return true;
+}
+
+static bool list_module_cleanup(KviModule *m)
+{
+ while(g_pListWindowList->first())g_pListWindowList->first()->die();
+ delete g_pListWindowList;
+ g_pListWindowList = 0;
+ return true;
+}
+
+static bool list_module_can_unload(KviModule *m)
+{
+ return (g_pListWindowList->isEmpty());
+}
+
+KVIRC_MODULE(
+ "List", // module name
+ "1.0.0", // module version
+ "Copyright (C) 2000-2001 Szymon Stefanek (pragma at kvirc dot net)", // author & (C)
+ "List window extension",
+ list_module_init,
+ list_module_can_unload,
+ 0,
+ list_module_cleanup
+)
diff --git a/src/modules/list/listwindow.cpp b/src/modules/list/listwindow.cpp
new file mode 100644
index 00000000..2e1c5401
--- /dev/null
+++ b/src/modules/list/listwindow.cpp
@@ -0,0 +1,535 @@
+//=============================================================================
+//
+// File : listwindow.cpp
+// Creation date : Thu Oct 7 2001 13:27:55 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2004 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the lists of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) 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.
+//
+//=============================================================================
+
+#include "listwindow.h"
+
+#include "kvi_debug.h"
+#include "kvi_iconmanager.h"
+#include "kvi_ircview.h"
+#include "kvi_out.h"
+#include "kvi_options.h"
+#include "kvi_locale.h"
+#include "kvi_out.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_themedlabel.h"
+#include "kvi_options.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_ircconnection.h"
+#include "kvi_ircconnection.h"
+#include "kvi_qstring.h"
+#include "kvi_qcstring.h"
+#include "kvi_topicw.h"
+#include "kvi_config.h"
+#include "kvi_filedialog.h"
+
+#include "kvi_styled_controls.h"
+#include <qtimer.h>
+#include <qpainter.h>
+#include <qfontmetrics.h>
+#include <qsplitter.h>
+#include <qtooltip.h>
+#include <qdatetime.h>
+#include "kvi_tal_hbox.h"
+#include "kvi_msgbox.h"
+
+extern KviPointerList<KviListWindow> * g_pListWindowList;
+
+// kvi_ircview.cpp
+//extern KVIRC_API const char * getColorBytes(const char *data_ptr,unsigned char *byte_1,unsigned char *byte_2);
+
+
+KviChannelListViewItemData::KviChannelListViewItemData(const QString &szChan,const QString &szUsers,const QString &szTopic)
+{
+ m_szChan = szChan;
+ m_szUsers = szUsers;
+ m_szTopic = szTopic;
+ m_szUsersKey = szUsers;
+ //setText(0,szChan.upper());
+ while(m_szUsersKey.length() < 6)m_szUsersKey.prepend("0");
+}
+
+KviChannelListViewItemData::~KviChannelListViewItemData()
+{
+}
+
+
+
+KviChannelListViewItem::KviChannelListViewItem(KviTalListView * v,KviChannelListViewItemData * pData)
+: KviTalListViewItem(v)
+{
+ m_pData = pData;
+}
+
+
+KviChannelListViewItem::~KviChannelListViewItem()
+{
+ delete m_pData;
+}
+#ifdef COMPILE_USE_QT4
+int KviChannelListViewItem::width ( const QFontMetrics & fm, const KviTalListView * lv, int column ) const
+#else
+int KviChannelListViewItem::width ( const QFontMetrics & fm, const QListView * lv, int column ) const
+#endif
+{
+ debug("width request");
+ QString szText;
+
+ switch(column)
+ {
+ case 0: szText = m_pData->m_szChan; break;
+ case 1: szText = m_pData->m_szUsers; break;
+ default: szText = m_pData->m_szTopic; break;
+ }
+ if(column==2) return fm.width(KviMircCntrl::stripControlBytes(szText));
+ else return fm.width(szText);
+}
+
+#define KVI_LABEL_DEF_BACK 100
+#define KVI_LABEL_DEF_FORE 101
+
+void KviChannelListViewItem::paintCell(QPainter * p,const QColorGroup &cg,int column,int width,int align)
+{
+ QString szText;
+
+ switch(column)
+ {
+ case 0: szText = m_pData->m_szChan; break;
+ case 1: szText = m_pData->m_szUsers; break;
+ default: szText = m_pData->m_szTopic; break;
+ }
+
+ KviTalListView* lv = (KviTalListView *)listView();
+ int marg = lv->itemMargin();
+ int r = marg;
+
+#ifdef COMPILE_USE_QT4
+
+ p->fillRect( 0, 0, width, height(), cg.brush(lv->viewport()->backgroundRole()) );
+#else
+ const QColorGroup::ColorRole crole = QPalette::backgroundRoleFromMode(lv->viewport()->backgroundMode());
+
+ p->fillRect( 0, 0, width, height(), cg.brush( crole ) );
+#endif
+
+ if ( isSelected() &&
+ (column == 0 || lv->allColumnsShowFocus()) ) {
+ p->fillRect( r - marg, 0, width - r + marg, height(),
+ cg.brush( QColorGroup::Highlight ) );
+
+ if ( isEnabled() || !lv )
+ p->setPen( cg.highlightedText() );
+ else if ( !isEnabled() && lv)
+ p->setPen( lv->palette().disabled().highlightedText() );
+ } else {
+ if ( isEnabled() || !lv )
+ p->setPen( cg.text() );
+ else if ( !isEnabled() && lv)
+ p->setPen( lv->palette().disabled().text() );
+ }
+
+ KviTopicWidget::paintColoredText(p,szText,cg,height(),width);
+}
+
+QString KviChannelListViewItem::key(int col,bool) const
+{
+ switch(col)
+ {
+ case 0:
+ return m_pData->m_szChan;
+ break;
+ case 1:
+ return m_pData->m_szUsersKey;
+ break;
+ case 2:
+ return m_pData->m_szTopic;
+ break;
+ }
+ QString ret;
+ return ret;
+}
+
+
+
+KviListWindow::KviListWindow(KviFrame * lpFrm,KviConsole * lpConsole)
+: KviWindow(KVI_WINDOW_TYPE_LIST,lpFrm,"list",lpConsole) , KviExternalServerDataParser()
+{
+ g_pListWindowList->append(this);
+
+ m_pFlushTimer = 0;
+
+ m_pItemList = new KviPointerList<KviChannelListViewItemData>;
+ m_pItemList->setAutoDelete(false);
+
+ m_pSplitter = new QSplitter(Qt::Horizontal,this,"splitter");
+ m_pTopSplitter = new QSplitter(Qt::Horizontal,this,"top_splitter");
+ m_pVertSplitter = new QSplitter(Qt::Vertical,m_pSplitter,"vsplitter");
+
+ KviTalHBox * box = new KviTalHBox(m_pTopSplitter);
+ m_pOpenButton = new KviStyledToolButton(box);
+ m_pOpenButton->setPixmap(*(g_pIconManager->getBigIcon(KVI_BIGICON_OPEN)));
+ connect(m_pOpenButton,SIGNAL(clicked()),this,SLOT(importList()));
+
+ m_pSaveButton = new KviStyledToolButton(box);
+ m_pSaveButton->setPixmap(*(g_pIconManager->getBigIcon(KVI_BIGICON_SAVE)));
+ connect(m_pSaveButton,SIGNAL(clicked()),this,SLOT(exportList()));
+
+ m_pRequestButton = new KviStyledToolButton(box,"request_button");
+ m_pRequestButton->setUsesBigPixmap(false);
+ m_pRequestButton->setPixmap(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_LIST)));
+ connect(m_pRequestButton,SIGNAL(clicked()),this,SLOT(requestList()));
+ QToolTip::add(m_pRequestButton,__tr2qs("Request List"));
+
+ m_pStopListDownloadButton = new KviStyledToolButton(box,"stoplistdownload_button");
+ m_pStopListDownloadButton->setUsesBigPixmap(false);
+ m_pStopListDownloadButton->setPixmap(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_NICKNAMEPROBLEM)));
+ connect(m_pStopListDownloadButton,SIGNAL(clicked()),this,SLOT(stoplistdownload()));
+ QToolTip::add(m_pStopListDownloadButton,__tr2qs("Stop list download"));
+
+ m_pParamsEdit = new QLineEdit(box);
+ box->setStretchFactor(m_pParamsEdit,1);
+ QToolTip::add(m_pParamsEdit,__tr2qs("<center><b>/LIST command parameters:</b><br>Many servers accept special parameters that " \
+ "allow you to filter the returned entries.<br>" \
+ "Commonly, masked channel names (*kvirc*) are accepted as parameters, as well as strings " \
+ "like <b>c&lt;n</b> or <b>c&gt;n</b> where <b>n</b> is the minimum or maximum of users on the channel.</center>"));
+
+ m_pInfoLabel = new KviThemedLabel(m_pTopSplitter,"info_label");
+
+ m_pListView = new KviTalListView(m_pVertSplitter);
+ m_pListView->addColumn(__tr2qs("Channel"));
+ m_pListView->addColumn(__tr2qs("Users"));
+ m_pListView->addColumn(__tr2qs("Topic"));
+ m_pListView->setAllColumnsShowFocus(TRUE);
+ m_pListView->setColumnWidthMode(2,KviTalListView::Maximum);
+ m_pListView->setColumnWidthMode(3,KviTalListView::Maximum);
+ m_pListView->setSorting(100);
+
+ connect(m_pListView,SIGNAL(doubleClicked(KviTalListViewItem *)),this,SLOT(itemDoubleClicked(KviTalListViewItem *)));
+
+ m_pIrcView = new KviIrcView(m_pVertSplitter,lpFrm,this);
+
+ m_pConsole->ircContext()->setListWindowPointer(this);
+
+ connect(m_pConsole->context(),SIGNAL(stateChanged()),
+ this,SLOT(connectionStateChange()));
+
+ connectionStateChange();
+
+}
+
+KviListWindow::~KviListWindow()
+{
+ g_pListWindowList->removeRef(this);
+ m_pConsole->ircContext()->setListWindowPointer(0);
+ if(m_pFlushTimer)delete m_pFlushTimer;
+ m_pItemList->setAutoDelete(true);
+ delete m_pItemList;
+}
+
+void KviListWindow::getBaseLogFileName(KviStr &buffer)
+{
+ buffer.sprintf("LIST_%d",console()->ircContextId());
+}
+
+
+void KviListWindow::requestList()
+{
+ if(m_pConsole->isConnected())
+ {
+ KviStr parms = m_pParamsEdit->text();
+ if(parms.isEmpty())m_pConsole->connection()->sendFmtData("list");
+ else m_pConsole->connection()->sendFmtData("list %s",m_pConsole->connection()->encodeText(parms.ptr()).data());
+ outputNoFmt(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Sent list request, waiting for reply..."));
+ m_pRequestButton->setEnabled(false);
+ } else {
+ outputNoFmt(KVI_OUT_SYSTEMERROR,__tr2qs("Cannot request list: No active connection"));
+ }
+}
+
+void KviListWindow::stoplistdownload()
+{
+ if(m_pConsole->isConnected())
+ {
+ m_pConsole->connection()->sendFmtData("list stoplistdownloadnow");
+ outputNoFmt(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Stopping the list download...")); //G&N mar 2005
+ } else {
+ outputNoFmt(KVI_OUT_SYSTEMERROR,__tr2qs("Cannot stop list download, no active connection."));
+ }
+}
+
+void KviListWindow::connectionStateChange()
+{
+ KviIrcContext::State st = m_pConsole->context()->state();
+ m_pRequestButton->setEnabled(st == KviIrcContext::Connected);
+ if(st == KviIrcContext::Connected)
+ {
+ QString tmp;
+ KviQString::sprintf(tmp,
+ __tr2qs("Connected to %s (%s)"),
+ m_pConsole->connection()->currentServerName().utf8().data(),
+ m_pConsole->currentNetworkName().utf8().data());
+ m_pInfoLabel->setText(tmp);
+ } else {
+ m_pInfoLabel->setText(__tr2qs("List cannot be requested: Not connected to a server"));
+ }
+}
+
+QPixmap * KviListWindow::myIconPtr()
+{
+ return g_pIconManager->getSmallIcon(KVI_SMALLICON_LIST);
+}
+
+void KviListWindow::resizeEvent(QResizeEvent *e)
+{
+ int hght = m_pTopSplitter->sizeHint().height();
+ m_pTopSplitter->setGeometry(0,0,width(),hght);
+ m_pSplitter->setGeometry(0,hght,width(),height() - hght);
+}
+
+QSize KviListWindow::sizeHint() const
+{
+ return m_pSplitter->sizeHint();
+}
+
+void KviListWindow::fillCaptionBuffers()
+{
+ KviQString::sprintf(m_szPlainTextCaption,__tr2qs("Channel List [IRC Context %u]"),m_pConsole->ircContextId());
+
+ KviQString::sprintf(m_szHtmlActiveCaption,
+ __tr2qs("<nobr><font color=\"%s\"><b>Channel List</b></font> " \
+ "<font color=\"%s\">[IRC Context %u]</font></nobr>"),
+ KVI_OPTION_COLOR(KviOption_colorCaptionTextActive).name().ascii(),
+ KVI_OPTION_COLOR(KviOption_colorCaptionTextActive2).name().ascii(),
+ m_pConsole->ircContextId());
+
+ KviQString::sprintf(m_szHtmlInactiveCaption,
+ __tr2qs("<nobr><font color=\"%s\"><b>Channel list</b></font> " \
+ "<font color=\"%s\">[IRC Context %u]</font></nobr>"),
+ KVI_OPTION_COLOR(KviOption_colorCaptionTextInactive).name().ascii(),
+ KVI_OPTION_COLOR(KviOption_colorCaptionTextInactive2).name().ascii(),
+ m_pConsole->ircContextId());
+}
+
+void KviListWindow::die()
+{
+ close();
+}
+
+void KviListWindow::exportList()
+{
+ if(!m_pListView->firstChild())
+ {
+ KviMessageBox::warning(__tr2qs("You cannot export an empty list"));
+ return;
+ }
+
+ QString szFile;
+ if(connection())
+ {
+ QString szDate = QDateTime::currentDateTime().toString("d MMM yyyy hh-mm");
+ KviQString::sprintf(szFile,__tr2qs("Channel list for %Q - %Q"),
+ &(connection()->networkName()),&(szDate));
+ } else {
+ szFile = __tr2qs("Channel list");
+ }
+ if(KviFileDialog::askForSaveFileName(szFile,__tr2qs("Choose filename"),szFile,
+ __tr2qs("Configuration files (*.kvc)"),false,
+ false,true,this))
+ {
+ if(QFileInfo(szFile).extension()!="kvc")
+ szFile.append(".kvc");
+ KviConfig cfg(szFile,KviConfig::Write);
+ cfg.clear();
+ KviTalListViewItemIterator it(m_pListView);
+
+ while(it.current())
+ {
+ KviChannelListViewItemData* pData= ((KviChannelListViewItem*) ( it.current() ))->m_pData;
+ cfg.setGroup(pData->m_szChan);
+ // Write properties
+ cfg.writeEntry("topic",pData->m_szTopic);
+ cfg.writeEntry("users",pData->m_szUsers);
+// cfg.writeEntry("usersKey",pData->m_szUsersKey);
+ ++it;
+ }
+ }
+}
+
+void KviListWindow::importList()
+{
+
+ QString szFile;
+ if(KviFileDialog::askForOpenFileName(szFile,__tr2qs("Choose filename"),QString::null,
+ __tr2qs("Configuration files (*.kvc)"),false,
+ false,this))
+ {
+ if(m_pConsole->isConnected())
+ {
+ m_pConsole->connection()->sendFmtData("list stoplistdownloadnow");
+ outputNoFmt(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Stopping the list download...")); //G&N mar 2005
+ }
+
+ m_pItemList->clear();
+
+ KviConfig cfg(szFile,KviConfig::Read);
+ KviConfigIterator it(*cfg.dict());
+ while(it.current())
+ {
+ cfg.setGroup(it.currentKey());
+ m_pItemList->append(
+ new KviChannelListViewItemData(
+ it.currentKey(),
+ cfg.readQStringEntry("users","0"),
+ cfg.readQStringEntry("topic","")
+ )
+ );
+ ++it;
+ }
+ flush();
+ }
+}
+
+void KviListWindow::control(int message)
+{
+ switch(message)
+ {
+ case EXTERNAL_SERVER_DATA_PARSER_CONTROL_RESET: reset(); break;
+ case EXTERNAL_SERVER_DATA_PARSER_CONTROL_STARTOFDATA: startOfList(); break;
+ case EXTERNAL_SERVER_DATA_PARSER_CONTROL_ENDOFDATA: endOfList(); break;
+ }
+}
+
+void KviListWindow::reset()
+{
+ outputNoFmt(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Reset"));
+}
+
+void KviListWindow::endOfList()
+{
+ if(m_pFlushTimer)
+ {
+ delete m_pFlushTimer;
+ m_pFlushTimer = 0;
+ }
+ m_pRequestButton->setEnabled(true);
+ outputNoFmt(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Channels list download finished"));
+ flush(); // give it the last kick
+}
+
+void KviListWindow::startOfList()
+{
+ m_pItemList->setAutoDelete(true);
+ m_pItemList->clear();
+ m_pItemList->setAutoDelete(false);
+
+ m_pListView->clear();
+
+ m_pRequestButton->setEnabled(false);
+}
+
+void KviListWindow::processData(KviIrcMessage *msg)
+{
+ if(!m_pFlushTimer)
+ {
+ m_pFlushTimer = new QTimer(this);
+ connect(m_pFlushTimer,SIGNAL(timeout()),this,SLOT(flush()));
+ m_pFlushTimer->start(1000);
+ m_pRequestButton->setEnabled(false);
+ }
+
+ QString sz2 = msg->connection()->decodeText(msg->safeParam(2));
+
+ m_pItemList->append(
+ new KviChannelListViewItemData(
+ msg->connection()->decodeText(msg->safeParam(1)),
+ msg->connection()->decodeText(msg->safeParam(2)),
+ msg->connection()->decodeText(msg->safeTrailing()))
+ );
+
+ if(_OUTPUT_VERBOSE)
+ {
+ QString zzz = msg->connection()->decodeText(msg->allParams());
+ output(KVI_OUT_LIST,__tr2qs("Processing list: %Q"),&zzz);
+ }
+}
+
+void KviListWindow::flush()
+{
+ m_pListView->setUpdatesEnabled(true); /* for v_scroolbar */
+ while(KviChannelListViewItemData * d = m_pItemList->first())
+ {
+ (void)new KviChannelListViewItem(m_pListView,d);
+ m_pItemList->removeFirst();
+ }
+ m_pListView->setUpdatesEnabled(true);
+ m_pListView->viewport()->update();
+}
+
+void KviListWindow::itemDoubleClicked(KviTalListViewItem *it)
+{
+ QString sz = ((KviChannelListViewItem *)it)->channel();
+ if(sz.isEmpty())return;
+ if(!connection())return;
+ KviQCString dat = connection()->encodeText(sz);
+ if(!dat.data())return;
+ m_pConsole->connection()->sendFmtData("join %s",dat.data());
+}
+
+
+//
+//#warning "Load & save properties of this kind of window"
+
+//void KviListWindow::saveProperties()
+//{
+// KviWindowProperty p;
+// p.rect = externalGeometry();
+// p.isDocked = isAttacched();
+// QValueList<int> l(m_pSplitter->sizes());
+// if(l.count() >= 1)p.splitWidth1 = *(l.at(0));
+// if(l.count() >= 2)p.splitWidth2 = *(l.at(1));
+// p.timestamp = m_pView->timestamp();
+// p.imagesVisible = m_pView->imagesVisible();
+// p.isMaximized = isAttacched() && isMaximized();
+// p.topSplitWidth1 = 0;
+// p.topSplitWidth2 = 0;
+// p.topSplitWidth3 = 0;
+// g_pOptions->m_pWinPropertiesList->setProperty(caption(),&p);
+//}
+//
+//void KviListWindow::setProperties(KviWindowProperty *p)
+//{
+// QValueList<int> l;
+// l.append(p->splitWidth1);
+// l.append(p->splitWidth2);
+// m_pVertSplitter->setSizes(l);
+// m_pIrcView->setTimestamp(p->timestamp);
+// m_pIrcView->setShowImages(p->imagesVisible);
+//}
+
+void KviListWindow::applyOptions()
+{
+ m_pIrcView->applyOptions();
+ KviWindow::applyOptions();
+}
+
+#include "listwindow.moc"
diff --git a/src/modules/list/listwindow.h b/src/modules/list/listwindow.h
new file mode 100644
index 00000000..8e7d510e
--- /dev/null
+++ b/src/modules/list/listwindow.h
@@ -0,0 +1,122 @@
+#ifndef _LISTWINDOW_H_
+#define _LISTWINDOW_H_
+//=============================================================================
+//
+// File : listwindow.h
+// Creation date : Thu Oct 7 2001 13:27:55 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2004 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the lists of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_window.h"
+#include "kvi_string.h"
+#include "kvi_ircsocket.h"
+#include "kvi_pointerlist.h"
+#include "kvi_sparser.h"
+#include "kvi_console.h"
+#include "kvi_irccontext.h"
+
+#include "kvi_tal_listview.h"
+#include "kvi_tal_popupmenu.h"
+#include <qtoolbutton.h>
+#include <qlineedit.h>
+
+class KviThemedLabel;
+
+class KviChannelListViewItemData
+{
+ friend class KviChannelListViewItem;
+ friend class KviListWindow;
+public:
+ KviChannelListViewItemData(const QString &szChan,const QString &szUsers,const QString &szTopic);
+ ~KviChannelListViewItemData();
+protected:
+ QString m_szChan;
+ QString m_szUsers;
+ QString m_szTopic;
+ QString m_szUsersKey;
+};
+
+class KviChannelListViewItem : public KviTalListViewItem
+{
+ friend class KviListWindow;
+public:
+ KviChannelListViewItem(KviTalListView * v,KviChannelListViewItemData * pData);
+ ~KviChannelListViewItem();
+protected:
+ KviChannelListViewItemData * m_pData;
+public:
+ const QString & channel(){ return m_pData->m_szChan; };
+#ifdef COMPILE_USE_QT4
+ int width ( const QFontMetrics & fm, const KviTalListView * lv, int column ) const;
+#else
+ int width ( const QFontMetrics & fm, const QListView * lv, int column ) const;
+#endif
+protected:
+ virtual void paintCell(QPainter * p,const QColorGroup &cg,int col,int wdth,int align);
+ virtual QString key(int col,bool) const;
+};
+
+
+
+class KviListWindow : public KviWindow, public KviExternalServerDataParser
+{
+ Q_OBJECT
+public:
+ KviListWindow(KviFrame * lpFrm,KviConsole * lpConsole);
+ ~KviListWindow();
+protected:
+ QSplitter * m_pVertSplitter;
+ QSplitter * m_pTopSplitter;
+ KviTalListView * m_pListView;
+ QLineEdit * m_pParamsEdit;
+ QToolButton * m_pRequestButton;
+ QToolButton * m_pStopListDownloadButton;
+ QToolButton * m_pOpenButton;
+ QToolButton * m_pSaveButton;
+ KviThemedLabel * m_pInfoLabel;
+ QTimer * m_pFlushTimer;
+ KviPointerList<KviChannelListViewItemData> * m_pItemList;
+public: // Methods
+ virtual void control(int msg);
+ virtual void processData(KviIrcMessage * msg);
+ virtual void die();
+protected:
+ virtual QPixmap * myIconPtr();
+ virtual void fillCaptionBuffers();
+ virtual void applyOptions();
+ virtual void resizeEvent(QResizeEvent *e);
+ virtual void getBaseLogFileName(KviStr &buffer);
+protected slots:
+ void flush();
+ void itemDoubleClicked(KviTalListViewItem *it);
+ void requestList();
+ void stoplistdownload();
+ void connectionStateChange();
+ void exportList();
+ void importList();
+public:
+ virtual QSize sizeHint() const;
+private:
+ void reset();
+ void endOfList();
+ void startOfList();
+};
+
+#endif //_KVI_LISTWINDOW_H_
diff --git a/src/modules/log/Makefile.am b/src/modules/log/Makefile.am
new file mode 100644
index 00000000..e2bfe1e9
--- /dev/null
+++ b/src/modules/log/Makefile.am
@@ -0,0 +1,18 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkvilog.la
+
+libkvilog_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkvilog_la_SOURCES = libkvilog.cpp
+libkvilog_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+# noinst_HEADERS=
+
+%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
diff --git a/src/modules/log/libkvilog.cpp b/src/modules/log/libkvilog.cpp
new file mode 100644
index 00000000..5e29e30d
--- /dev/null
+++ b/src/modules/log/libkvilog.cpp
@@ -0,0 +1,309 @@
+//==============================================================================
+//
+// File : libkvilog.cpp
+// Creation date : Sat Jan 06 2001 13:28:02 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//==============================================================================
+
+#include "kvi_module.h"
+#include "kvi_window.h"
+#include "kvi_app.h"
+#include "kvi_locale.h"
+#include "kvi_ircview.h"
+
+
+//#warning "log.stats"
+//#warning "log.compress (gzip -r the log directory)"
+
+/*
+ @doc: log
+ @title:
+ The log interface module
+ @short:
+ Interface to the KVirc log subsystem
+ @type:
+ module
+ @keyterms:
+ logging
+ @body:
+ The log module is an interface to the KVIrc logging subsystem.[br]
+ It provides commands and functions that allow the management of
+ logging in the KVIrc windows:[br]
+ [cmd]log.start[/cmd], [cmd]log.stop[/cmd], [cmd]log.flush[/cmd],
+ [fnc]$log.file[/fnc]().[br]
+ NOTE:[br]
+ If you want to AUTOENABLE logging in certain types of windows
+ you have to use the [cmd]option[/cmd] command.[br]
+ For example, [b]option boolAutoLogQueries 1[/b] enables logging in all the newly created
+ query windows.
+*/
+
+/*
+ @doc: log.start
+ @type:
+ command
+ @title:
+ log.start
+ @keyterms:
+ logging
+ @short:
+ Starts logging in a specified window
+ @syntax:
+ log.start [-w = <window_id>] [-p] [filename]
+ @description:
+ Starts logging in the current window or in the window specified by the -w switch.[br]
+ If a logging session is already running in the specified window, it is stopped first.[br]
+ If [filename] is specified, this filename is used as log file, otherwise a default
+ filename is used.[br]
+ If the -p switch is used, all the already existing contents of the window are
+ stored to the log file before starting the log action.[br]
+ Please note that some windows do not have logging capabilities...this command
+ will print a warning in that case.[br]
+ @seealso:
+ [fnc]$window[/fnc],
+ [cmd]log.stop[/cmd],
+ [fnc]$log.file[/fnc],
+ [doc:window_naming_conventions]window naming conventions documentation[/doc]
+*/
+
+
+static bool log_kvs_cmd_start(KviKvsModuleCommandCall * c)
+{
+ QString szFile;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("filename",KVS_PT_STRING,KVS_PF_OPTIONAL,szFile)
+ KVSM_PARAMETERS_END(c)
+
+ KviWindow * pWnd = c->window();
+ if(c->hasSwitch('w',"window"))
+ {
+ QString szWindow;
+ if(c->switches()->getAsStringIfExisting('w',"window",szWindow))
+ {
+ pWnd = g_pApp->findWindow(szWindow);
+ if(!pWnd)
+ {
+ c->warning(__tr2qs("Window %Q not found"),&szWindow);
+ return true;
+ }
+
+ } else {
+ c->warning(__tr2qs("Missing window id after the 'w' switch"));
+ return true;
+ }
+ }
+
+ if(pWnd->view())
+ {
+
+ if(szFile.isEmpty())
+ {
+ pWnd->getDefaultLogFileName(szFile);
+ }
+ if(!pWnd->view()->startLogging(szFile,c->hasSwitch('p',"log-buffer")))
+ c->warning(__tr2qs("Can't log to file %Q"),&szFile);
+ } else {
+ c->warning(__tr2qs("This window has no logging capabilities"));
+ return true;
+ }
+ return true;
+}
+
+/*
+ @doc: log.stop
+ @type:
+ command
+ @title:
+ log.stop
+ @keyterms:
+ logging
+ @short:
+ Stops logging in a specified window
+ @syntax:
+ log.stop [-w = <window_id>]
+ @description:
+ Stops logging in the current window or in the window specified by the -w switch.[br]
+ If logging is not enabled in the specified window, this command does nothing.[br]
+ @seealso:
+ [fnc]$window[/fnc],
+ [cmd]log.start[/cmd],
+ [doc:window_naming_conventions]window naming conventions documentation[/doc]
+*/
+
+static bool log_kvs_cmd_stop(KviKvsModuleCommandCall * c)
+{
+
+ KviWindow * pWnd = c->window();
+ if(c->hasSwitch('w',"window"))
+ {
+ QString szWindow;
+ if(c->switches()->getAsStringIfExisting('w',"window",szWindow))
+ {
+ pWnd = g_pApp->findWindow(szWindow);
+ if(!pWnd)
+ {
+ c->warning(__tr2qs("Window %Q not found"),&szWindow);
+ return true;
+ }
+
+ } else {
+ c->warning(__tr2qs("Missing window id after the 'w' switch"));
+ return true;
+ }
+ }
+
+ if(pWnd->view())
+ pWnd->view()->stopLogging();
+ return true;
+}
+
+/*
+ @doc: log.flush
+ @type:
+ command
+ @title:
+ log.flush
+ @keyterms:
+ logging
+ @short:
+ Flushes the log file for a specified window
+ @syntax:
+ log.flush [-w = <window_id>]
+ @description:
+ Flushes the log file the current window or in the window specified by the -w switch.[br]
+ If logging is not enabled in the specified window, this command does nothing.[br]
+ If this command is never used, the log file is flushed at regulear file-size intervals,
+ depending on the underlying IO subsystem. This is usually 4KB.[br]
+ The "block flushing" is used to achieve a fast I/O on files, but may cause
+ the last data block to be lost in case of a program crash.[br]
+ @seealso:
+ [fnc]$window[/fnc],
+ [cmd]log.start[/cmd],
+ [cmd]log.stop[/cmd],
+ [doc:window_naming_conventions]window naming conventions documentation[/doc]
+*/
+
+static bool log_kvs_cmd_flush(KviKvsModuleCommandCall * c)
+{
+
+ KviWindow * pWnd = c->window();
+ if(c->hasSwitch('w',"window"))
+ {
+ QString szWindow;
+ if(c->switches()->getAsStringIfExisting('w',"window",szWindow))
+ {
+ pWnd = g_pApp->findWindow(szWindow);
+ if(!pWnd)
+ {
+ c->warning(__tr2qs("Window %Q not found"),&szWindow);
+ return true;
+ }
+
+ } else {
+ c->warning(__tr2qs("Missing window id after the 'w' switch"));
+ return true;
+ }
+ }
+
+ if(pWnd->view())
+ pWnd->view()->flushLog();
+ return true;
+}
+
+/*
+ @doc: log.file
+ @type:
+ function
+ @title:
+ $log.file
+ @short:
+ Returns the current log filename
+ @syntax:
+ $log.file
+ $log.file(<window id>)
+ @description:
+ The form with the <window id> parameter returns the log file name
+ of the window that has the specified id. If logging is not enabled
+ in the specified window, this function returns an empty string.[br]
+ The form without parameters returns the log file name of the current window,
+ thus it is equivalent to calling $log.file([fnc]$window[/fnc])
+ @examples:
+ [example]
+ [cmd]log[/cmd] mylogfilename.log
+ [cmd]echo[/cmd] $log
+ [cmd]echo[/cmd] $log([fnc]$console[/fnc])
+ [/example]
+ @seealso:
+ [fnc]$window[/fnc],
+ [cmd]log.start[/cmd],
+ [cmd]log.stop[/cmd],
+ [doc:window_naming_conventions]window naming conventions documentation[/doc]
+*/
+
+static bool log_kvs_fnc_file(KviKvsModuleFunctionCall * c)
+{
+ QString szWindow;
+ QString buffer;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("window id",KVS_PT_STRING,KVS_PF_OPTIONAL,szWindow)
+ KVSM_PARAMETERS_END(c)
+
+ KviWindow * wnd = c->window();
+
+ if(!szWindow.isEmpty())
+ {
+ wnd = g_pApp->findWindow(szWindow);
+ if(!wnd)
+ {
+ c->warning(__tr2qs("Window with id '%Q' not found, returning empty string"),&szWindow);
+ return true;
+ }
+ }
+
+ if(wnd->view())wnd->view()->getLogFileName(buffer);
+ c->returnValue()->setString(buffer);
+ return true;
+}
+
+static bool log_module_init(KviModule * m)
+{
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"start",log_kvs_cmd_start);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"stop",log_kvs_cmd_stop);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"flush",log_kvs_cmd_flush);
+
+ KVSM_REGISTER_FUNCTION(m,"file",log_kvs_fnc_file);
+ return true;
+}
+
+static bool log_module_cleanup(KviModule *m)
+{
+ return true;
+}
+
+KVIRC_MODULE(
+ "Log", // module name
+ "1.0.0", // module version
+ "Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot net)", // author & (C)
+ "User interface to the logging system for KVIrc",
+ log_module_init,
+ 0,
+ 0,
+ log_module_cleanup
+)
diff --git a/src/modules/logview/Makefile.am b/src/modules/logview/Makefile.am
new file mode 100644
index 00000000..03a1b07e
--- /dev/null
+++ b/src/modules/logview/Makefile.am
@@ -0,0 +1,23 @@
+###############################################################################
+# KVirc IRC client Makefile - 3.23.2002 Juanjo lvarez <juanjux@yahoo.es>
+###############################################################################
+
+SUBDIRS = caps
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkvilogview.la
+
+libkvilogview_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkvilogview_la_SOURCES = libkvilogview.cpp logviewwidget.cpp logviewmdiwindow.cpp
+libkvilogview_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+noinst_HEADERS= logviewwidget.h logviewmdiwindow.h
+
+%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
+
+logviewwidget.cpp: logviewwidget.moc
+logviewmdiwindow.cpp: logviewmdiwindow.moc
diff --git a/src/modules/logview/caps/Makefile.am b/src/modules/logview/caps/Makefile.am
new file mode 100644
index 00000000..13c80350
--- /dev/null
+++ b/src/modules/logview/caps/Makefile.am
@@ -0,0 +1,9 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+tmpdir = $(pluglibdir)/caps/tool/
+
+tmp_DATA= logview
+
+EXTRA_DIST = $(tmp_DATA)
diff --git a/src/modules/logview/caps/logview b/src/modules/logview/caps/logview
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/modules/logview/caps/logview
diff --git a/src/modules/logview/libkvilogview.cpp b/src/modules/logview/libkvilogview.cpp
new file mode 100644
index 00000000..2aa56a66
--- /dev/null
+++ b/src/modules/logview/libkvilogview.cpp
@@ -0,0 +1,170 @@
+//
+// File : libkvilogview.cpp
+// Creation date : Sun Feb 10 2000 23:25:10 CEST by Juanjo �varez
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "logviewwidget.h"
+#include "logviewmdiwindow.h"
+
+#include "kvi_config.h"
+
+#include "kvi_module.h"
+
+#include "kvi_frame.h"
+#include "kvi_iconmanager.h"
+#include "kvi_locale.h"
+#include "kvi_app.h"
+
+static QRect g_rectLogViewGeometry;
+KviLogViewMDIWindow * g_pLogViewWindow = 0;
+
+#define LOGVIEW_MODULE_EXTENSION_NAME "Log viewer extension"
+
+/*
+ @doc: logview.open
+ @type:
+ command
+ @title:
+ logview.open
+ @short:
+ Opens the log viewer window
+ @syntax:
+ logview.open [-m] [-n]
+ @switches:
+ !sw: -m
+ Causes the window to be created as minimized
+ !sw: -n
+ Causes the window to be not raised if already open
+ @description:
+ Opens a window that allows visual browsing of the logs
+ stored on disk.
+*/
+
+// ============================================
+// Module stuff
+// ============================================
+
+static bool logview_kvs_cmd_open(KviKvsModuleCommandCall * c)
+{
+ KviModuleExtensionDescriptor * d = c->module()->findExtensionDescriptor("tool",LOGVIEW_MODULE_EXTENSION_NAME);
+ if(d)
+ {
+ KviPointerHashTable<QString,QVariant> dict(17,true);
+ dict.setAutoDelete(true);
+ QString dummy;
+ dict.replace("bCreateMinimized",new QVariant(c->hasSwitch('m',dummy)));
+ dict.replace("bNoRaise",new QVariant(c->hasSwitch('n',dummy)));
+
+ d->allocate(c->window(),&dict,0);
+ } else {
+ c->warning("Ops.. internal error");
+ }
+ return true;
+}
+
+static KviModuleExtension * logview_extension_alloc(KviModuleExtensionAllocStruct * s)
+{
+ bool bCreateMinimized = false;
+ bool bNoRaise = false;
+
+ if(!g_pLogViewWindow)
+ {
+ if(s->pParams)
+ {
+ if(QVariant * v = s->pParams->find("bCreateMinimized"))
+ {
+ if(v->isValid())
+ {
+ if(v->type() == QVariant::Bool)
+ {
+ bCreateMinimized = v->toBool();
+ }
+ }
+ }
+ }
+
+ g_pLogViewWindow = new KviLogViewMDIWindow(s->pDescriptor,g_pFrame);
+ g_pFrame->addWindow(g_pLogViewWindow,!bCreateMinimized);
+ if(bCreateMinimized)g_pLogViewWindow->minimize();
+ return g_pLogViewWindow;
+ }
+
+ if(s->pParams)
+ {
+ if(QVariant * v = s->pParams->find("bNoRaise"))
+ {
+ if(v)
+ {
+ if(v->isValid() && v->type() == QVariant::Bool)
+ bNoRaise = v->toBool();
+ }
+ }
+ }
+
+ if(!bNoRaise)g_pLogViewWindow->delayedAutoRaise();
+ return g_pLogViewWindow;
+}
+
+
+static bool logview_module_init(KviModule * m)
+{
+ g_pLogViewWindow = 0;
+
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"open",logview_kvs_cmd_open);
+
+
+
+ KviModuleExtensionDescriptor * d = m->registerExtension("tool",
+ LOGVIEW_MODULE_EXTENSION_NAME,
+ __tr2qs_ctx("Browse &Log Files","logview"),
+ logview_extension_alloc);
+
+ if(d)d->setIcon(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_LOG)));
+
+ return true;
+}
+
+static bool logview_module_cleanup(KviModule * m)
+{
+ if(g_pLogViewWindow)delete g_pLogViewWindow;
+ g_pLogViewWindow = 0;
+ return true;
+}
+
+static bool logview_module_can_unload(KviModule *m)
+{
+ return (!g_pLogViewWindow);
+}
+
+
+// ============================================
+// module definition structure
+// ============================================
+
+KVIRC_MODULE(
+ "KVIrc Log Viewer Widget",
+ "1.0.0",
+ "Juanjo Alvarez <juanjux@yahoo.es>",
+ "An structured log file viewer",
+ logview_module_init,
+ logview_module_can_unload,
+ 0,
+ logview_module_cleanup
+)
diff --git a/src/modules/logview/logviewmdiwindow.cpp b/src/modules/logview/logviewmdiwindow.cpp
new file mode 100644
index 00000000..20a2a232
--- /dev/null
+++ b/src/modules/logview/logviewmdiwindow.cpp
@@ -0,0 +1,477 @@
+//
+// File : logviewmdiwindow.cpp
+// Creation date : Tue Apr 23 2002 18:08:22 by Juanjo �varez
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "logviewmdiwindow.h"
+#include "logviewwidget.h"
+#include "kvi_iconmanager.h"
+#include "kvi_locale.h"
+#include "kvi_module.h"
+#include "kvi_options.h"
+#include "kvi_frame.h"
+#include "kvi_ircview.h"
+#include "kvi_qstring.h"
+#include "kvi_qcstring.h"
+#include "kvi_app.h"
+#include "kvi_fileutils.h"
+#ifdef COMPILE_USE_QT4
+ #include <q3progressdialog.h>
+#else
+ #include <qprogressdialog.h>
+#endif
+#include "kvi_valuelist.h"
+#include "kvi_accel.h"
+#include <qpixmap.h>
+#include <qsplitter.h>
+#include <qtoolbutton.h>
+#include "kvi_tal_listview.h"
+#include <qfileinfo.h>
+#include <qdir.h>
+#include "kvi_tal_popupmenu.h"
+#include <qcursor.h>
+#include <qlayout.h>
+#include <qpushbutton.h>
+
+
+
+#ifdef COMPILE_ZLIB_SUPPORT
+ #include <zlib.h>
+#endif
+#include <qtextcodec.h>
+#include "kvi_styled_controls.h"
+#include <qdatetimeedit.h>
+#include <qlineedit.h>
+#include <qlabel.h>
+
+extern KviLogViewMDIWindow * g_pLogViewWindow;
+
+KviLogViewMDIWindow::KviLogViewMDIWindow(KviModuleExtensionDescriptor * d,KviFrame * lpFrm)
+: KviWindow(KVI_WINDOW_TYPE_LOGVIEW,lpFrm,"logview"), KviModuleExtension(d)
+{
+ g_pLogViewWindow = this;
+// m_pLogViewWidget = new KviLogViewWidget(this);
+ #ifdef COMPILE_USE_QT4
+ m_pSplitter = new QSplitter(Qt::Horizontal,this,"main_splitter");
+#else
+ m_pSplitter = new QSplitter(QSplitter::Horizontal,this,"main_splitter");
+#endif
+ m_pTabWidget = new QTabWidget(m_pSplitter);
+
+ m_pIndexTab = new KviTalVBox(m_pTabWidget);
+ m_pTabWidget->insertTab(m_pIndexTab,__tr2qs_ctx("Index","logview"));
+ m_pListView = new KviTalListView(m_pIndexTab);
+ m_pListView->addColumn(__tr2qs_ctx("Log File","logview"),135);
+ m_pListView->setColumnWidthMode(0,KviTalListView::Maximum);
+ m_pListView->setAllColumnsShowFocus(true);
+ m_pListView->setMultiSelection(false);
+ m_pListView->setShowSortIndicator(true);
+ m_pListView->setRootIsDecorated(true);
+ connect(m_pListView,SIGNAL(selectionChanged(KviTalListViewItem *)),this,SLOT(itemSelected(KviTalListViewItem *)));
+ connect(m_pListView,SIGNAL(rightButtonClicked ( KviTalListViewItem * , const QPoint &, int )),this,SLOT(rightButtonClicked ( KviTalListViewItem * , const QPoint &, int )));
+
+ m_pSearchTab = new QWidget(m_pTabWidget);
+ m_pTabWidget->insertTab(m_pSearchTab,__tr2qs_ctx("Filter","logview"));
+
+ QGridLayout *layout = new QGridLayout(m_pSearchTab,10,2,3,5);
+
+ m_pShowChannelsCheck = new KviStyledCheckBox(__tr2qs_ctx("Show channel logs","logview"),m_pSearchTab);
+ m_pShowChannelsCheck->setChecked(true);
+ layout->addMultiCellWidget(m_pShowChannelsCheck,0,0,0,1);
+
+ m_pShowQueryesCheck = new KviStyledCheckBox(__tr2qs_ctx("Show query logs","logview"),m_pSearchTab);
+ m_pShowQueryesCheck->setChecked(true);
+ layout->addMultiCellWidget(m_pShowQueryesCheck,1,1,0,1);
+
+ m_pShowConsolesCheck = new KviStyledCheckBox(__tr2qs_ctx("Show console logs","logview"),m_pSearchTab);
+ m_pShowConsolesCheck->setChecked(true);
+ layout->addMultiCellWidget(m_pShowConsolesCheck,2,2,0,1);
+
+ m_pShowDccChatCheck = new KviStyledCheckBox(__tr2qs_ctx("Show DCC chat logs","logview"),m_pSearchTab);
+ m_pShowDccChatCheck->setChecked(true);
+ layout->addMultiCellWidget(m_pShowDccChatCheck,3,3,0,1);
+
+ m_pShowOtherCheck = new KviStyledCheckBox(__tr2qs_ctx("Show other logs","logview"),m_pSearchTab);
+ m_pShowOtherCheck->setChecked(true);
+ layout->addMultiCellWidget(m_pShowOtherCheck,4,4,0,1);
+
+ QLabel *l;
+ l = new QLabel(__tr2qs_ctx("Contents filter","logview"),m_pSearchTab);
+ layout->addMultiCellWidget(l,5,5,0,1);
+
+ l = new QLabel(__tr2qs_ctx("Log name mask:","logview"),m_pSearchTab);
+ m_pFileNameMask = new QLineEdit(m_pSearchTab);
+ connect(m_pFileNameMask,SIGNAL(returnPressed()),this,SLOT(applyFilter()));
+ layout->addWidget(l,6,0);
+ layout->addWidget(m_pFileNameMask,6,1);
+
+ l = new QLabel(__tr2qs_ctx("Log contents mask:","logview"),m_pSearchTab);
+ m_pContentsMask = new QLineEdit(m_pSearchTab);
+ connect(m_pContentsMask,SIGNAL(returnPressed()),this,SLOT(applyFilter()));
+ layout->addWidget(l,7,0);
+ layout->addWidget(m_pContentsMask,7,1);
+
+ m_pEnableFromFilter = new KviStyledCheckBox(__tr2qs_ctx("Only older than","logview"),m_pSearchTab);
+ m_pFromDateEdit = new QDateEdit(m_pSearchTab);
+ m_pFromDateEdit->setDate(QDate::currentDate());
+ layout->addWidget(m_pEnableFromFilter,8,0);
+ layout->addWidget(m_pFromDateEdit,8,1);
+ connect(m_pEnableFromFilter,SIGNAL(toggled(bool)),m_pFromDateEdit,SLOT(setEnabled(bool)));
+ m_pFromDateEdit->setEnabled(false);
+
+ m_pEnableToFilter = new KviStyledCheckBox(__tr2qs_ctx("Only newier than","logview"),m_pSearchTab);
+ m_pToDateEdit = new QDateEdit(m_pSearchTab);
+ m_pToDateEdit->setDate(QDate::currentDate());
+ layout->addWidget(m_pEnableToFilter,9,0);
+ layout->addWidget(m_pToDateEdit,9,1);
+ connect(m_pEnableToFilter,SIGNAL(toggled(bool)),m_pToDateEdit,SLOT(setEnabled(bool)));
+ m_pToDateEdit->setEnabled(false);
+
+ QPushButton *pb = new QPushButton(__tr2qs_ctx("Apply filter","logview"),m_pSearchTab);
+ connect(pb,SIGNAL(clicked()),this,SLOT(applyFilter()));
+ layout->addWidget(pb,10,1);
+
+ QWidget *w = new QWidget(m_pSearchTab);
+ w->setSizePolicy(QSizePolicy::Ignored,QSizePolicy::Ignored);
+ layout->addWidget(w,11,1);
+
+ m_pIrcView = new KviIrcView(m_pSplitter,g_pFrame,this);
+#ifdef COMPILE_USE_QT4
+ m_pIrcView->setFocusPolicy(Qt::ClickFocus);
+#else
+ m_pIrcView->setFocusPolicy(QWidget::ClickFocus);
+#endif
+ KviValueList<int> li;
+ li.append(110);
+ li.append(width()-110);
+ m_pSplitter->setSizes(li);
+
+ g_pApp->getLocalKvircDirectory(m_szLogDirectory,KviApp::Log);
+ KviQString::ensureLastCharIs(m_szLogDirectory,'/'); // Does this work on Windows?
+
+ cacheFileList();
+ setupItemList();
+ KviAccel *a = new KviAccel( this );
+ a->connectItem( a->insertItem(Qt::Key_F+Qt::CTRL),
+ m_pIrcView,
+ SLOT(toggleToolWidget()) );
+}
+
+
+
+KviLogViewMDIWindow::~KviLogViewMDIWindow()
+{
+ g_pLogViewWindow = 0;
+}
+
+void KviLogViewMDIWindow::applyFilter()
+{
+ setupItemList();
+}
+
+
+QPixmap * KviLogViewMDIWindow::myIconPtr()
+{
+ return g_pIconManager->getSmallIcon(KVI_SMALLICON_LOG);
+}
+
+
+void KviLogViewMDIWindow::resizeEvent(QResizeEvent *e)
+{
+ m_pSplitter->setGeometry(0,0,width(),height());
+}
+
+void KviLogViewMDIWindow::fillCaptionBuffers()
+{
+ m_szPlainTextCaption = __tr2qs_ctx("Log Viewer","logview");
+
+ m_szHtmlActiveCaption = QString("<nobr><font color=\"%1\"><b>").arg(KVI_OPTION_COLOR(KviOption_colorCaptionTextActive).name().ascii());
+ m_szHtmlActiveCaption.append(m_szPlainTextCaption);
+ m_szHtmlActiveCaption.append("</b></font></nobr>");
+
+ m_szHtmlInactiveCaption = QString("<nobr><font color=\"%1\"><b>").arg(KVI_OPTION_COLOR(KviOption_colorCaptionTextInactive).name().ascii());
+ m_szHtmlInactiveCaption.append(m_szPlainTextCaption);
+ m_szHtmlInactiveCaption.append("</b></font></nobr>");
+}
+
+void KviLogViewMDIWindow::die()
+{
+ close();
+}
+
+QSize KviLogViewMDIWindow::sizeHint() const
+{
+ QSize ret(m_pSplitter->sizeHint().width(),m_pIrcView->sizeHint().height());
+ return ret;
+}
+
+void KviLogViewMDIWindow::setupItemList()
+{
+ m_pListView->clear();
+ KviLogFile *pFile;
+ //m_logList.begin();
+ KviLogListViewItem *pLastCategory=0;
+ KviLogListViewItemFolder *pLastGroupItem;
+ QString szLastGroup;
+ QString szCurGroup;
+ const bool bShowChannel=m_pShowChannelsCheck->isChecked();
+ const bool bShowQuery=m_pShowQueryesCheck->isChecked();
+ const bool bShowConsole=m_pShowConsolesCheck->isChecked();
+ const bool bShowOther=m_pShowOtherCheck->isChecked();
+ const bool bShowDccChat=m_pShowDccChatCheck->isChecked();
+
+ const bool filterFromDate=m_pEnableFromFilter->isChecked();
+ const bool filterToDate=m_pEnableToFilter->isChecked();
+
+ const QString nameFilterText = m_pFileNameMask->text();
+ const bool enableNameFilter = !nameFilterText.isEmpty();
+
+ const QString contentFilterText = m_pContentsMask->text();
+ const bool enableContentFilter = !contentFilterText.isEmpty();
+
+ QDate fromDate = m_pFromDateEdit->date();
+ QDate toDate = m_pToDateEdit->date();
+
+ QString textBuffer;
+#ifdef COMPILE_USE_QT4
+ Q3ProgressDialog progress( __tr2qs_ctx("Filtering files...","logview"),
+ __tr2qs_ctx("Abort filtering","logview"), m_logList.count(),
+ this, "progress", TRUE );
+#else
+ QProgressDialog progress( __tr2qs_ctx("Filtering files...","logview"),
+ __tr2qs_ctx("Abort filtering","logview"), m_logList.count(),
+ this, "progress", TRUE );
+#endif
+
+
+ int i=0;
+ for(pFile=m_logList.first();pFile;pFile=m_logList.next())
+ {
+ progress.setProgress( i );
+ i++;
+ g_pApp->processEvents();
+
+ if ( progress.wasCanceled() )
+ break;
+
+ if(pFile->type()==KviLogFile::Channel && !bShowChannel)
+ continue;
+ if(pFile->type()==KviLogFile::Console && !bShowConsole)
+ continue;
+ if(pFile->type()==KviLogFile::DccChat && !bShowDccChat)
+ continue;
+ if(pFile->type()==KviLogFile::Other && !bShowOther)
+ continue;
+ if(pFile->type()==KviLogFile::Query && !bShowQuery)
+ continue;
+
+ if(filterFromDate)
+ if(pFile->date()<fromDate)
+ continue;
+
+ if(filterToDate)
+ if(pFile->date()>toDate)
+ continue;
+
+ if(enableNameFilter)
+ if(!KviQString::matchStringCI(nameFilterText,pFile->name()))
+ continue;
+
+ if(enableContentFilter)
+ {
+ pFile->getText(textBuffer,m_szLogDirectory);
+ if(!KviQString::matchStringCI(contentFilterText,textBuffer))
+ continue;
+ }
+
+ if(pLastCategory)
+ {
+ if(pLastCategory->m_type!=pFile->type())
+ pLastCategory = new KviLogListViewItemType(m_pListView,pFile->type());
+ } else {
+ pLastCategory = new KviLogListViewItemType(m_pListView,pFile->type());
+ }
+
+ KviQString::sprintf(szCurGroup,__tr2qs_ctx("%Q on %Q","logview"),&(pFile->name()),
+ &(pFile->network())
+ );
+
+ if(szLastGroup!=szCurGroup) {
+ szLastGroup=szCurGroup;
+ pLastGroupItem=new KviLogListViewItemFolder(pLastCategory,szLastGroup);
+ }
+ new KviLogListViewLog(pLastGroupItem,pFile->type(),pFile);
+ }
+ progress.setProgress( m_logList.count() );
+}
+
+void KviLogViewMDIWindow::cacheFileList()
+{
+ QStringList m_pFileNames = getFileNames();
+ m_pFileNames.sort();
+ QString szFname;
+
+ for(QStringList::Iterator it = m_pFileNames.begin(); it != m_pFileNames.end(); ++it)
+ {
+ szFname=(*it);
+ QFileInfo fi(szFname);
+ if(fi.extension(false)=="gz" || fi.extension(false)=="log")
+ m_logList.append(new KviLogFile(szFname));
+ }
+}
+
+void KviLogViewMDIWindow::itemSelected(KviTalListViewItem * it)
+{
+ bool bCompressed=0;
+ //A parent node
+ m_pIrcView->clearBuffer();
+ if(!it || !it->parent() || !(((KviLogListViewItem *)it)->m_pFileData) )
+ {
+ return;
+ }
+
+ QString text;
+ ((KviLogListViewItem *)it)->m_pFileData->getText(text,m_szLogDirectory);
+
+ QStringList lines=QStringList::split('\n',text);
+ bool bOk;
+ int iMsgType;
+ for ( QStringList::Iterator it = lines.begin(); it != lines.end(); ++it ) {
+ QString num=(*it).section(' ',0,0);
+ iMsgType=num.toInt(&bOk);
+ if(bOk)
+ outputNoFmt(iMsgType,(*it).section(' ',1),KviIrcView::NoRepaint | KviIrcView::NoTimestamp);
+ else
+ outputNoFmt(0,*it,KviIrcView::NoRepaint | KviIrcView::NoTimestamp);
+ }
+ m_pIrcView->repaint(false);
+}
+
+QStringList KviLogViewMDIWindow::getFileNames()
+{
+ QString logPath;
+ g_pApp->getLocalKvircDirectory(logPath,KviApp::Log);
+ QString qPath(logPath);
+ QDir logDir(qPath);
+ return logDir.entryList();
+}
+
+void KviLogViewMDIWindow::rightButtonClicked ( KviTalListViewItem * it, const QPoint &, int )
+{
+ if(!it) return;
+ if(((KviLogListViewItem *)it)->fileName(0).isEmpty()) return;
+ KviTalPopupMenu* popup = new KviTalPopupMenu(this);
+ popup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_QUIT)),__tr2qs_ctx("Remove file","logview"),this,SLOT(deleteCurrent()));
+ popup->exec( QCursor::pos() );
+}
+
+void KviLogViewMDIWindow::deleteCurrent()
+{
+ KviLogListViewItem* pItem = (KviLogListViewItem *)(m_pListView->currentItem());
+ if(pItem)
+ {
+ if(!pItem->fileName(0).isNull())
+ {
+ QString szFname;
+ g_pApp->getLocalKvircDirectory(szFname,KviApp::Log,pItem->m_pFileData->fileName());
+ KviFileUtils::removeFile(szFname);
+ delete pItem;
+ m_pIrcView->clearBuffer();
+ }
+ }
+}
+
+KviLogFile::KviLogFile(const QString& name)
+{
+ m_szFilename=name;
+ QFileInfo fi(m_szFilename);
+ m_bCompressed=(fi.extension(false)=="gz");
+ QString typeToken = m_szFilename.section('_',0,0);
+ // Ignore non-logs files, this includes '.' and '..'
+ if( KviQString::equalCI(typeToken,"channel") )
+ m_type = Channel;
+ else if( KviQString::equalCI(typeToken,"console") )
+ m_type = Console;
+ else if( KviQString::equalCI(typeToken,"dccchat") )
+ m_type = DccChat;
+ else if( KviQString::equalCI(typeToken,"query") )
+ m_type = Query;
+ else
+ m_type = Other;
+
+ KviStr undecoded = m_szFilename.section('.',0,0);
+ undecoded.cutToFirst('_');
+ m_szName = undecoded.hexDecode(undecoded.ptr()).ptr();
+
+ undecoded = m_szFilename.section('.',1,1).section('_',0,0);
+ m_szNetwork = undecoded.hexDecode(undecoded.ptr()).ptr();
+
+ QString szDate = m_szFilename.section('.',1,3).section('_',1,1);
+ int iYear = szDate.section('.',0,0).toInt();
+ int iMonth = szDate.section('.',1,1).toInt();
+ int iDay = szDate.section('.',2,2).toInt();
+ m_date.setYMD(iYear,iMonth,iDay);
+
+ //debug("type=%i, name=%s, net=%s, date=%i %i %i",m_type,m_szName.ascii(),m_szNetwork.ascii(),iYear,iMonth,iDay);
+}
+
+void KviLogFile::getText(QString & text,const QString& logDir){
+ QString logName = logDir;
+ QFile logFile;
+ logName.append(fileName());
+#ifdef COMPILE_ZLIB_SUPPORT
+ if(m_bCompressed)
+ {
+ gzFile file=gzopen(logName.local8Bit().data(),"rb");
+ if(file)
+ {
+ char buff[1025];
+ int len;
+ KviQCString data;
+ //QCString data;
+ len=gzread(file,buff,1024);
+ while(len>0)
+ {
+ buff[len]=0;
+ data.append(buff);
+ len=gzread(file,buff,1024);
+ }
+ gzclose(file);
+ text = QString::fromUtf8(data);
+ } else {
+ debug("Cannot open compressed file %s",logName.local8Bit().data());
+ }
+ } else {
+#endif
+ logFile.setName(logName);
+
+ if(!logFile.open(IO_ReadOnly))
+ return;
+
+ QByteArray bytes;
+ bytes=logFile.readAll();
+ text = QString::fromUtf8(bytes.data(), bytes.size());
+ logFile.close();
+#ifdef COMPILE_ZLIB_SUPPORT
+ }
+#endif
+}
+
+#include "logviewmdiwindow.moc"
diff --git a/src/modules/logview/logviewmdiwindow.h b/src/modules/logview/logviewmdiwindow.h
new file mode 100644
index 00000000..df4bb245
--- /dev/null
+++ b/src/modules/logview/logviewmdiwindow.h
@@ -0,0 +1,125 @@
+#ifndef _LOGVIEWMDIWINDOW_H_
+#define _LOGVIEWMDIWINDOW_H_
+//
+// File : logviewmdiwindow.h
+// Creation date : Tue Apr 23 2002 18:05:59 by Juanjo �varez
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+#include "kvi_window.h"
+#include "kvi_moduleextension.h"
+
+#include "kvi_tal_vbox.h"
+#include "kvi_tal_listview.h"
+#include "kvi_pointerlist.h"
+#include <qtabwidget.h>
+#include <qdatetime.h>
+
+class KviTalListView;
+class QStringList;
+class KviLogViewWidget;
+class QCheckBox;
+class QLineEdit;
+class QDateEdit;
+
+class KviLogFile {
+
+public:
+
+ enum KviLogTypes {
+ Channel,
+ Console,
+ Query,
+ DccChat,
+ Other
+ };
+
+ KviLogFile(const QString& name);
+
+ const QString & fileName() { return m_szFilename; };
+ const QString & name() { return m_szName; };
+ const QString & network() { return m_szNetwork; };
+ const QDate & date() { return m_date; };
+
+ void getText(QString & text,const QString& logDir);
+
+ KviLogTypes type() { return m_type; };
+private:
+ KviLogTypes m_type;
+ QString m_szFilename;
+ bool m_bCompressed;
+ QString m_szName;
+ QString m_szNetwork;
+ QDate m_date;
+};
+
+class KviLogViewMDIWindow : public KviWindow , public KviModuleExtension
+{
+ Q_OBJECT
+public:
+ KviLogViewMDIWindow(KviModuleExtensionDescriptor * d,KviFrame * lpFrm);
+ ~KviLogViewMDIWindow();
+protected:
+ KviPointerList<KviLogFile> m_logList;
+
+ KviTalListView * m_pListView;
+
+ // Type filter
+ QCheckBox * m_pShowChannelsCheck;
+ QCheckBox * m_pShowQueryesCheck;
+ QCheckBox * m_pShowConsolesCheck;
+ QCheckBox * m_pShowOtherCheck;
+ QCheckBox * m_pShowDccChatCheck;
+
+ // Content filter
+ QLineEdit * m_pFileNameMask;
+ QLineEdit * m_pContentsMask;
+
+ // Date/time mask
+ QCheckBox * m_pEnableFromFilter;
+ QCheckBox * m_pEnableToFilter;
+ QDateEdit * m_pFromDateEdit;
+ QDateEdit * m_pToDateEdit;
+
+ QStringList * m_pFileNames;
+ QString m_szLogDirectory;
+ QTabWidget * m_pTabWidget;
+ KviTalVBox * m_pIndexTab;
+ QWidget * m_pSearchTab;
+protected:
+ QStringList getFileNames();
+
+ void setupItemList();
+ void cacheFileList();
+
+ virtual QPixmap * myIconPtr();
+ virtual void resizeEvent(QResizeEvent *e);
+ virtual void fillCaptionBuffers();
+ virtual void die();
+ virtual QSize sizeHint() const;
+protected slots:
+ void rightButtonClicked ( KviTalListViewItem *, const QPoint &, int );
+ void itemSelected(KviTalListViewItem * it);
+ void deleteCurrent();
+ void applyFilter();
+};
+
+#endif //_LOGVIEWMDIWINDOW_H_
+
diff --git a/src/modules/logview/logviewwidget.cpp b/src/modules/logview/logviewwidget.cpp
new file mode 100644
index 00000000..fc5c8abc
--- /dev/null
+++ b/src/modules/logview/logviewwidget.cpp
@@ -0,0 +1,76 @@
+//
+// File : logviewwidget.cpp
+// Creation date : Thu Apr 23 2002 17:42:12 by Juanjo �varez
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "logviewwidget.h"
+
+#include <qsplitter.h>
+#include <qlayout.h>
+#include <qdir.h>
+
+//#include "kvi_debug.h"
+#include "kvi_locale.h"
+#include "kvi_iconmanager.h"
+#include "kvi_app.h"
+
+#include "kvi_qstring.h"
+#ifdef COMPILE_ZLIB_SUPPORT
+ #include <zlib.h>
+#endif
+#include <qtextcodec.h>
+
+const QPixmap * KviLogListViewItemType::pixmap(int col) const
+{
+
+ switch(m_type)
+ {
+ case KviLogFile::Channel:
+ return g_pIconManager->getSmallIcon(KVI_SMALLICON_CHANNEL);
+ case KviLogFile::Query:
+ return g_pIconManager->getSmallIcon(KVI_SMALLICON_QUERY);
+ case KviLogFile::DccChat:
+ return g_pIconManager->getSmallIcon(KVI_SMALLICON_DCCMSG);
+ case KviLogFile::Console:
+ return g_pIconManager->getSmallIcon(KVI_SMALLICON_CONSOLE);
+ default:
+ return g_pIconManager->getSmallIcon(KVI_SMALLICON_HELP);
+ }
+}
+
+QString KviLogListViewItemType::text(int col) const
+{
+ switch(m_type)
+ {
+ case KviLogFile::Channel:
+ return __tr2qs_ctx("Channel","logview");
+ case KviLogFile::Query:
+ return __tr2qs_ctx("Query","logview");
+ case KviLogFile::DccChat:
+ return __tr2qs_ctx("DCC Chat","logview");
+ case KviLogFile::Console:
+ return __tr2qs_ctx("Console","logview");
+ default:
+ return __tr2qs_ctx("Other","logview");
+ }
+};
+
+
+#include "logviewwidget.moc"
diff --git a/src/modules/logview/logviewwidget.h b/src/modules/logview/logviewwidget.h
new file mode 100644
index 00000000..1b5eff97
--- /dev/null
+++ b/src/modules/logview/logviewwidget.h
@@ -0,0 +1,86 @@
+#ifndef _LOGVIEWWIDGET_H_
+#define _LOGVIEWWIDGET_H_
+
+//
+// File : logviewwidget.h
+// Creation date : Thue Apr 23 2002 03:01:53 CET by Juanjo �varez
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002-2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_window.h"
+#include "kvi_scripteditor.h"
+#include "logviewmdiwindow.h"
+
+#include "kvi_tal_listview.h"
+
+
+class KviScriptEditor;
+
+class KviLogListViewItem : public KviTalListViewItem
+{
+public:
+ KviLogListViewItem(KviTalListViewItem * par, KviLogFile::KviLogTypes type, KviLogFile * fileData)
+ : KviTalListViewItem(par), m_type(type), m_pFileData(fileData) {};
+ KviLogListViewItem(KviTalListView * par, KviLogFile::KviLogTypes type, KviLogFile * fileData)
+ : KviTalListViewItem(par), m_type(type), m_pFileData(fileData) {};
+ ~KviLogListViewItem() {};
+public:
+ KviLogFile::KviLogTypes m_type;
+ KviLogFile* m_pFileData;
+
+ virtual QString fileName(int col) const { return m_pFileData ? m_pFileData->name() : QString::null; };
+ virtual QString text(int col) const { return m_pFileData ? m_pFileData->name() : QString::null; };
+};
+
+class KviLogListViewItemFolder : public KviLogListViewItem
+{
+public:
+ KviLogListViewItemFolder(KviTalListViewItem * par, const QString& label)
+ : KviLogListViewItem(par,KviLogFile::Other,0),m_szLabel(label) {};
+ ~KviLogListViewItemFolder() {};
+public:
+ QString m_szLabel;
+ virtual QString text(int col) const { return m_szLabel; };
+};
+
+class KviLogListViewItemType : public KviLogListViewItem
+{
+public:
+ KviLogListViewItemType(KviTalListView * par, KviLogFile::KviLogTypes type)
+ : KviLogListViewItem(par,type,0) {};
+ ~KviLogListViewItemType() {};
+public:
+ virtual const QPixmap * pixmap(int col) const;
+ virtual QString text(int col) const;
+};
+
+
+class KviLogListViewLog : public KviLogListViewItem
+{
+public:
+ KviLogListViewLog(KviTalListViewItem * par, KviLogFile::KviLogTypes type, KviLogFile * fileData)
+ : KviLogListViewItem(par,type,fileData){};
+ ~KviLogListViewLog() {};
+ virtual QString key ( int column, bool ascending ) const { return m_pFileData->date().toString("yyyy.MM.dd"); };
+ virtual QString text(int col) const { return m_pFileData->date().toString("dd.MM.yyyy"); };
+};
+
+
+#endif
+
diff --git a/src/modules/mask/Makefile.am b/src/modules/mask/Makefile.am
new file mode 100644
index 00000000..0ca529fe
--- /dev/null
+++ b/src/modules/mask/Makefile.am
@@ -0,0 +1,18 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkvimask.la
+
+libkvimask_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkvimask_la_SOURCES = libkvimask.cpp
+libkvimask_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+# noinst_HEADERS=
+
+%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
diff --git a/src/modules/mask/libkvimask.cpp b/src/modules/mask/libkvimask.cpp
new file mode 100644
index 00000000..3f8be4b2
--- /dev/null
+++ b/src/modules/mask/libkvimask.cpp
@@ -0,0 +1,201 @@
+//
+// File : libkvistr.cpp
+// Creation date : Thu Dec 27 2001 17:13:12 GMT by Szymon Stefanek
+//
+// This str is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+#include "kvi_module.h"
+
+#include "kvi_locale.h"
+#include "kvi_string.h"
+#include "kvi_ircmask.h"
+
+ /*
+ @doc: mask.match
+ @type:
+ function
+ @title:
+ $mask.match
+ @short:
+ Matches a mask agains a wildcarded one
+ @syntax:
+ <boolean> $mask.match(<wildcard_mask:string>,<fixed_mask:string>)
+ @description:
+ Returns 1 if the <wildcard_mask> matches <fixed_mask> and 0 otherwise.
+ <wildcard_mask> can obviously contain wildcards ('*' and '?').
+ @example:
+ [example]
+ [cmd]if[/cmd]($mask.match(*!*@*.linux.it,$0))
+ [cmd]op[/cmd] [fnc]$mask.nick[/fnc]($0)
+ [/example]
+ */
+
+static bool mask_kvs_fnc_match(KviKvsModuleFunctionCall * c)
+{
+
+ QString wildmask,fixedmask;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("wildcard mask",KVS_PT_STRING,0,wildmask)
+ KVSM_PARAMETER("fixed mask",KVS_PT_STRING,0,fixedmask)
+ KVSM_PARAMETERS_END(c)
+ KviIrcMask mk1(wildmask);
+ KviIrcMask mk2(fixedmask);
+ c->returnValue()->setBoolean(mk1.matchesFixed(mk2.nick(),mk2.user(),mk2.host()));
+ return true;
+}
+
+ /*
+ @doc: mask.nick
+ @type:
+ function
+ @title:
+ $mask.nick
+ @short:
+ Returns the nick part of an IRC mask
+ @syntax:
+ <string> $mask.nick(<mask:string>)
+ @description:
+ Returns the nickname part of an IRC mask.
+ */
+
+static bool mask_kvs_fnc_nick(KviKvsModuleFunctionCall * c)
+{
+
+ QString mask;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("mask",KVS_PT_STRING,0,mask)
+ KVSM_PARAMETERS_END(c)
+ KviIrcMask mk(mask);
+ c->returnValue()->setString(mk.nick());
+ return true;
+}
+
+ /*
+ @doc: mask.user
+ @type:
+ function
+ @title:
+ $mask.user
+ @short:
+ Returns the username part of an IRC mask
+ @syntax:
+ <string> $mask.user(<mask:string>)
+ @description:
+ Returns the username part of an IRC mask.
+ */
+
+static bool mask_kvs_fnc_user(KviKvsModuleFunctionCall * c)
+{
+
+ QString mask;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("mask",KVS_PT_STRING,0,mask)
+ KVSM_PARAMETERS_END(c)
+ KviIrcMask mk(mask);
+ c->returnValue()->setString(mk.user());
+ return true;
+}
+
+
+ /*
+ @doc: mask.host
+ @type:
+ function
+ @title:
+ $mask.host
+ @short:
+ Returns the hostname part of an IRC mask
+ @syntax:
+ <string> $mask.host(<mask:string>)
+ @description:
+ Returns the hostname part of an IRC mask.
+ */
+
+static bool mask_kvs_fnc_host(KviKvsModuleFunctionCall * c)
+{
+ QString mask;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("mask",KVS_PT_STRING,0,mask)
+ KVSM_PARAMETERS_END(c)
+ KviIrcMask mk(mask);
+ c->returnValue()->setString(mk.host());
+ return true;
+}
+
+
+ /*
+ @doc: mask.hasnumerichost
+ @type:
+ function
+ @title:
+ $mask.hasNumericHost
+ @short:
+ Checks if a host part of a mask is numeric
+ @syntax:
+ <boolean> $mask.hasNumericHost(<mask: string>)
+ @description:
+ Returns 1 if the hostname part of the mask is numeric (e.g : unresolved IPV4 or IPV6 address)
+ */
+
+
+static bool mask_kvs_fnc_hasnumerichost(KviKvsModuleFunctionCall * c)
+{
+ QString mask;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("mask",KVS_PT_STRING,0,mask)
+ KVSM_PARAMETERS_END(c)
+ KviIrcMask mk(mask);
+ c->returnValue()->setBoolean(mk.hasNumericHost());
+ return true;
+}
+
+
+/*********************************************************************/
+// Module stuff
+/********************************************************************/
+
+
+
+static bool mask_module_init(KviModule * m)
+{
+ KVSM_REGISTER_FUNCTION(m,"match",mask_kvs_fnc_match);
+ KVSM_REGISTER_FUNCTION(m,"nick",mask_kvs_fnc_nick);
+ KVSM_REGISTER_FUNCTION(m,"user",mask_kvs_fnc_user);
+ KVSM_REGISTER_FUNCTION(m,"host",mask_kvs_fnc_host);
+ KVSM_REGISTER_FUNCTION(m,"hasnumerichost",mask_kvs_fnc_hasnumerichost);
+
+ return true;
+}
+
+static bool mask_module_cleanup(KviModule *m)
+{
+ return true;
+}
+
+KVIRC_MODULE(
+ "File", // module name
+ "1.0.0", // module version
+ "Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot net)",
+ "Mask manipulation functions",
+ mask_module_init,
+ 0,
+ 0,
+ mask_module_cleanup
+)
diff --git a/src/modules/math/Makefile.am b/src/modules/math/Makefile.am
new file mode 100644
index 00000000..001bef24
--- /dev/null
+++ b/src/modules/math/Makefile.am
@@ -0,0 +1,18 @@
+###############################################################################
+# KVirc IRC client Makemath - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkvimath.la
+
+libkvimath_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkvimath_la_SOURCES = libkvimath.cpp
+libkvimath_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+# noinst_HEADERS=
+
+%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
diff --git a/src/modules/math/libkvimath.cpp b/src/modules/math/libkvimath.cpp
new file mode 100644
index 00000000..63a29787
--- /dev/null
+++ b/src/modules/math/libkvimath.cpp
@@ -0,0 +1,475 @@
+//=============================================================================
+//
+// File : libkvimath.cpp
+// Creation date : Sat Jan 13 14:00:12 2006 GMT by Szymon Stefanek
+//
+// This math is part of the KVirc irc client distribution
+// Copyright (C) 2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_module.h"
+#include "kvi_string.h"
+
+#include <math.h>
+
+// Workaround for lost isnan and isinf definitions after
+// inclusion of iostream.h on some MacOS X systems
+#ifdef Q_OS_MACX
+ #ifndef isnan
+ extern "C" int isnan (double);
+ #endif
+ #ifndef isinf
+ extern "C" int isinf (double);
+ #endif
+#endif
+
+#define MATH_KVS_1PARAM_FUNCTION(__fncname,__paramname,__mathcallname) \
+static bool __fncname(KviKvsModuleFunctionCall * c) \
+{ \
+ kvs_real_t dReal; \
+ KVSM_PARAMETERS_BEGIN(c) \
+ KVSM_PARAMETER(__paramname,KVS_PT_REAL,0,dReal) \
+ KVSM_PARAMETERS_END(c) \
+ c->returnValue()->setReal(__mathcallname(dReal)); \
+ return true; \
+}
+
+#ifdef COMPILE_ON_WINDOWS
+// dobbiamo testare meglio, i risultati.
+static double cbrt(double x)
+{
+ if (x > 0.0) return pow(x, 1.0/3.0);
+ else return -pow(-x, 1.0/3.0);
+}
+
+static int isinf (double d) {
+ int expon = 0;
+ double val = frexp (d, &expon);
+ if (expon == 1025) {
+ if (val == 0.5) return 1;
+ else if (val == -0.5) return -1;
+ else return 0;
+ } else {
+ return 0;
+ }
+}
+static int isnan (double d) {
+ int expon = 0;
+ double val = frexp (d, &expon);
+ if (expon == 1025) {
+ if (val == 0.5) return 0;
+ else if (val == -0.5) return 0;
+ else return 1;
+ } else {
+ return 0;
+ }
+}
+#endif
+/*
+ @doc: math.sin
+ @type:
+ function
+ @title:
+ $math.sin
+ @short:
+ Returns the sinus of the specified angle in radiants
+ @syntax:
+ <real> $math.sin(<angle:real>)
+ @description:
+ Returns the sinus of the specified angle in radiants
+*/
+MATH_KVS_1PARAM_FUNCTION(math_kvs_fnc_sin,"angle",sin)
+
+/*
+ @doc: math.cos
+ @type:
+ function
+ @title:
+ $math.cos
+ @short:
+ Returns the cosinus of the specified angle in radiants
+ @syntax:
+ <real> $math.cos(<angle:real>)
+ @description:
+ Returns the cosinus of the specified angle in radiants
+*/
+MATH_KVS_1PARAM_FUNCTION(math_kvs_fnc_cos,"angle",cos)
+
+/*
+ @doc: math.tan
+ @type:
+ function
+ @title:
+ $math.tan
+ @short:
+ Returns the tangent of the specified angle in radiants
+ @syntax:
+ <real> $math.tan(<angle:real>)
+ @description:
+ Returns the tangent of the specified angle in radiants
+*/
+MATH_KVS_1PARAM_FUNCTION(math_kvs_fnc_tan,"angle",tan)
+
+/*
+ @doc: math.asin
+ @type:
+ function
+ @title:
+ $math.asin
+ @short:
+ Returns the angle in radiants that has the specified sinus value.
+ @syntax:
+ <real> $math.asin(<sinus:real>)
+ @description:
+ Returns the angle in radiants that has the specified sinus value.
+*/
+MATH_KVS_1PARAM_FUNCTION(math_kvs_fnc_asin,"sinus",asin)
+
+/*
+ @doc: math.acos
+ @type:
+ function
+ @title:
+ $math.acos
+ @short:
+ Returns the angle in radiants that has the specified cosinus value.
+ @syntax:
+ <real> $math.acos(<cosinus:real>)
+ @description:
+ Returns the angle in radiants that has the specified cosinus value.
+*/
+MATH_KVS_1PARAM_FUNCTION(math_kvs_fnc_acos,"cosinus",acos)
+
+
+/*
+ @doc: math.atan
+ @type:
+ function
+ @title:
+ $math.atan
+ @short:
+ Returns the angle in radiants that has the specified tangent value.
+ @syntax:
+ <real> $math.atan(<tangent:real>)
+ @description:
+ Returns the angle in radiants that has the specified tangent value.
+*/
+MATH_KVS_1PARAM_FUNCTION(math_kvs_fnc_atan,"tangent",atan)
+
+/*
+ @doc: math.sqrt
+ @type:
+ function
+ @title:
+ $math.sqrt
+ @short:
+ Returns the square root of a number
+ @syntax:
+ <real> $math.sqrt(<number:real>)
+ @description:
+ Returns the square root of the specified number
+*/
+MATH_KVS_1PARAM_FUNCTION(math_kvs_fnc_sqrt,"number",sqrt)
+
+/*
+ @doc: math.cbrt
+ @type:
+ function
+ @title:
+ $math.cbrt
+ @short:
+ Returns the cube root of a number
+ @syntax:
+ <real> $math.cbrt(<number:real>)
+ @description:
+ Returns the cube root of the specified number
+*/
+MATH_KVS_1PARAM_FUNCTION(math_kvs_fnc_cbrt,"number",cbrt)
+
+/*
+ @doc: math.abs
+ @type:
+ function
+ @title:
+ $math.abs
+ @short:
+ Returns the absolute value of a number
+ @syntax:
+ <real> $math.abs(<number:real>)
+ @description:
+ Returns the absolute value of the specified number
+*/
+MATH_KVS_1PARAM_FUNCTION(math_kvs_fnc_abs,"number",fabs)
+
+/*
+ @doc: math.floor
+ @type:
+ function
+ @title:
+ $math.floor
+ @short:
+ Rounds down to the nearest integer
+ @syntax:
+ <real> $math.floor(<number:real>)
+ @description:
+ Rounds down number to the nearest integer
+*/
+MATH_KVS_1PARAM_FUNCTION(math_kvs_fnc_floor,"number",floor)
+
+/*
+ @doc: math.ceil
+ @type:
+ function
+ @title:
+ $math.ceil
+ @short:
+ Rounds up to the nearest integer
+ @syntax:
+ <real> $math.ceil(<number:real>)
+ @description:
+ Rounds up number to the nearest integer
+*/
+MATH_KVS_1PARAM_FUNCTION(math_kvs_fnc_ceil,"number",ceil)
+
+/*
+ @doc: math.exp
+ @type:
+ function
+ @title:
+ $math.exp
+ @short:
+ Returns the exponential of the specified number
+ @syntax:
+ <real> $math.exp(<number:real>)
+ @description:
+ Returns the exponential of the specified number
+*/
+MATH_KVS_1PARAM_FUNCTION(math_kvs_fnc_exp,"number",exp)
+
+/*
+ @doc: math.log
+ @type:
+ function
+ @title:
+ $math.log
+ @short:
+ Returns the natural logarithm of the specified number
+ @syntax:
+ <real> $math.log(<number:real>)
+ @description:
+ Returns the natural (base e) logarithm of the specified number
+*/
+
+MATH_KVS_1PARAM_FUNCTION(math_kvs_fnc_log,"number",log)
+
+
+/*
+ @doc: math.log10
+ @type:
+ function
+ @title:
+ $math.log10
+ @short:
+ Returns the base 10 logarithm of the specified number
+ @syntax:
+ <real> $math.log10(<number:real>)
+ @description:
+ Returns the base 10 logarithm of the specified number
+*/
+MATH_KVS_1PARAM_FUNCTION(math_kvs_fnc_log10,"number",log10)
+
+/*
+ @doc: math.isnan
+ @type:
+ function
+ @title:
+ $math.isnan
+ @short:
+ Checks if the value is not a number
+ @syntax:
+ <boolean> $math.isnan(<value:real>)
+ @description:
+ Checks if the specified value is a valid number
+ or NaN (Not a Number). NaN is returned by several
+ math functions when the result would be undefined.
+*/
+static bool math_kvs_fnc_isnan(KviKvsModuleFunctionCall * c)
+{
+ kvs_real_t dReal;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("value",KVS_PT_REAL,0,dReal)
+ KVSM_PARAMETERS_END(c)
+ c->returnValue()->setBoolean(isnan(dReal));
+ return true;
+}
+
+/*
+ @doc: math.isinf
+ @type:
+ function
+ @title:
+ $math.isinf
+ @short:
+ Checks if the value is the infinity
+ @syntax:
+ <boolean> $math.isinf(<value:real>)
+ @description:
+ Checks if the specified value is the infinity.
+*/
+#ifdef COMPILE_ON_WINDOWS
+static bool math_kvs_fnc_isinf(KviKvsModuleFunctionCall * c)
+{
+ kvs_real_t dReal;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("value",KVS_PT_REAL,0,dReal)
+ KVSM_PARAMETERS_END(c)
+ c->returnValue()->setBoolean(sinf(dReal));
+ return true;
+}
+#else
+static bool math_kvs_fnc_isinf(KviKvsModuleFunctionCall * c)
+{
+ kvs_real_t dReal;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("value",KVS_PT_REAL,0,dReal)
+ KVSM_PARAMETERS_END(c)
+ c->returnValue()->setBoolean(isinf(dReal));
+ return true;
+}
+#endif //COMPILE_ON_WINDOWS
+/*
+ @doc: math.pow
+ @type:
+ function
+ @title:
+ $math.pow
+ @short:
+ Returns a to the power of b
+ @syntax:
+ <real> $math.pow(<a:real>,<b:real>)
+ @description:
+ Returns a to the power of b
+*/
+static bool math_kvs_fnc_pow(KviKvsModuleFunctionCall * c)
+{
+ kvs_real_t dA,dB;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("a",KVS_PT_REAL,0,dA)
+ KVSM_PARAMETER("b",KVS_PT_REAL,0,dB)
+ KVSM_PARAMETERS_END(c)
+ c->returnValue()->setReal(pow(dA,dB));
+ return true;
+}
+
+/*
+ @doc: math.pi
+ @type:
+ function
+ @title:
+ $math.pi
+ @short:
+ Returns the value of pi
+ @syntax:
+ <real> $math.pi()
+ @description:
+ Returns the value of pi
+*/
+#ifdef COMPILE_ON_WINDOWS
+static bool math_kvs_fnc_pi(KviKvsModuleFunctionCall * c)
+{
+ c->returnValue()->setReal(3.141592653589793238462643383279502884197169399375);
+ return true;
+}
+#else
+static bool math_kvs_fnc_pi(KviKvsModuleFunctionCall * c)
+{
+ c->returnValue()->setReal(M_PI);
+ return true;
+}
+#endif
+/*
+ @doc: math.e
+ @type:
+ function
+ @title:
+ $math.e
+ @short:
+ Returns the value of e
+ @syntax:
+ <real> $math.e()
+ @description:
+ Returns the value of the euler constant e
+*/
+
+
+#ifdef COMPILE_ON_WINDOWS
+static bool math_kvs_fnc_e(KviKvsModuleFunctionCall * c)
+{
+ c->returnValue()->setReal(1.56903485);
+ return true;
+}
+#else
+static bool math_kvs_fnc_e(KviKvsModuleFunctionCall * c)
+{
+ c->returnValue()->setReal(M_E);
+ return true;
+}
+#endif
+static bool math_module_init(KviModule * m)
+{
+ KVSM_REGISTER_FUNCTION(m,"sin",math_kvs_fnc_sin);
+ KVSM_REGISTER_FUNCTION(m,"cos",math_kvs_fnc_cos);
+ KVSM_REGISTER_FUNCTION(m,"tan",math_kvs_fnc_tan);
+ KVSM_REGISTER_FUNCTION(m,"asin",math_kvs_fnc_asin);
+ KVSM_REGISTER_FUNCTION(m,"acos",math_kvs_fnc_acos);
+ KVSM_REGISTER_FUNCTION(m,"atan",math_kvs_fnc_atan);
+ KVSM_REGISTER_FUNCTION(m,"sqrt",math_kvs_fnc_sqrt);
+ KVSM_REGISTER_FUNCTION(m,"cbrt",math_kvs_fnc_cbrt);
+ KVSM_REGISTER_FUNCTION(m,"abs",math_kvs_fnc_abs);
+ KVSM_REGISTER_FUNCTION(m,"floor",math_kvs_fnc_floor);
+ KVSM_REGISTER_FUNCTION(m,"ceil",math_kvs_fnc_ceil);
+ KVSM_REGISTER_FUNCTION(m,"pow",math_kvs_fnc_pow);
+ KVSM_REGISTER_FUNCTION(m,"exp",math_kvs_fnc_exp);
+ KVSM_REGISTER_FUNCTION(m,"log",math_kvs_fnc_log);
+ KVSM_REGISTER_FUNCTION(m,"log10",math_kvs_fnc_log10);
+ KVSM_REGISTER_FUNCTION(m,"pi",math_kvs_fnc_pi);
+ KVSM_REGISTER_FUNCTION(m,"e",math_kvs_fnc_e);
+ KVSM_REGISTER_FUNCTION(m,"isnan",math_kvs_fnc_isnan);
+ KVSM_REGISTER_FUNCTION(m,"isinf",math_kvs_fnc_isinf);
+ return true;
+}
+
+
+static bool math_module_cleanup(KviModule *m)
+{
+ return true;
+}
+
+KVIRC_MODULE(
+ "Math", // module name
+ "1.0.0", // module version
+ "Copyright (C) 2006 Szymon Stefanek (pragma at kvirc dot net),"\
+ "Tonino Imbesi (grifisx at barmes dot org)," \
+ "Alessandro Carbone (noldor at barmes dot org)",
+ "Mathematical function module",
+ math_module_init,
+ 0,
+ 0,
+ math_module_cleanup
+)
diff --git a/src/modules/mediaplayer/Makefile.am b/src/modules/mediaplayer/Makefile.am
new file mode 100644
index 00000000..af5caa60
--- /dev/null
+++ b/src/modules/mediaplayer/Makefile.am
@@ -0,0 +1,36 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkvimediaplayer.la
+
+#%.moc: %.h
+# $(SS_QT_MOC) $< -o $@
+
+libkvimediaplayer_la_LDFLAGS = -avoid-version -module
+
+libkvimediaplayer_la_SOURCES = libkvimediaplayer.cpp \
+ mp_amarokinterface.cpp \
+ mp_amipinterface.cpp \
+ mp_dcopinterface.cpp \
+ mp_interface.cpp \
+ mp_jukinterface.cpp \
+ mp_mp3.cpp \
+ mp_winampinterface.cpp \
+ mp_xmmsinterface.cpp
+
+libkvimediaplayer_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+noinst_HEADERS = mp_amarokinterface.h \
+ mp_amipinterface.h \
+ mp_dcopinterface.h \
+ mp_interface.h \
+ mp_jukinterface.h \
+ mp_mp3.h \
+ mp_winampinterface.h \
+ mp_xmmsinterface.h
+
+
diff --git a/src/modules/mediaplayer/libkvimediaplayer.cpp b/src/modules/mediaplayer/libkvimediaplayer.cpp
new file mode 100644
index 00000000..bd8a144f
--- /dev/null
+++ b/src/modules/mediaplayer/libkvimediaplayer.cpp
@@ -0,0 +1,1751 @@
+//=============================================================================
+//
+// File : libkvimediaplayer.cpp
+// Creation date : Sat Nov 3 19:28:25 2001 GMT by Szymon Stefanek
+// Renamed to file : libkvimediaplayer.cpp on Fri Mar 25 2005
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "mp_interface.h"
+#include "mp_xmmsinterface.h"
+#include "mp_amarokinterface.h"
+#include "mp_winampinterface.h"
+#include "mp_amipinterface.h"
+#include "mp_jukinterface.h"
+
+#include "kvi_module.h"
+#include "kvi_options.h"
+
+
+#include "kvi_locale.h"
+#include "kvi_out.h"
+
+static KviPointerList<KviMediaPlayerInterfaceDescriptor> * g_pDescriptorList = 0;
+
+static KviMediaPlayerInterface * g_pMPInterface = 0;
+
+static KviMediaPlayerInterface * auto_detect_player(KviWindow * pOut = 0)
+{
+ int iBest = 0;
+ KviMediaPlayerInterface * pBest = 0;
+ KviMediaPlayerInterfaceDescriptor * d;
+ KviMediaPlayerInterfaceDescriptor * pDBest = 0;
+ for(d = g_pDescriptorList->first();d;d = g_pDescriptorList->next())
+ {
+ KviMediaPlayerInterface * i = d->instance();
+ if(i)
+ {
+ int iScore = i->detect(false);
+ if(iScore > iBest)
+ {
+ iBest = iScore;
+ pBest = i;
+ pDBest = d;
+ }
+ if(pOut)
+ {
+ QString szOut;
+ QString szNam = d->name();
+ KviQString::sprintf(szOut,__tr2qs_ctx("Trying media player interface \"%Q\": score %d","mediaplayer"),&(szNam),iScore);
+ pOut->output(KVI_OUT_MULTIMEDIA,szOut);
+ }
+ }
+ }
+ if(iBest < 90)
+ {
+ if(pOut)
+ pOut->outputNoFmt(KVI_OUT_MULTIMEDIA,__tr2qs_ctx("Not sure about the results, trying a second, more agressive detection pass","mediaplayer"));
+ // no sure player found... try again with a destructive test
+ for(d = g_pDescriptorList->first();d;d = g_pDescriptorList->next())
+ {
+ KviMediaPlayerInterface * i = d->instance();
+ if(i)
+ {
+ int iScore = i->detect(true);
+ if(iScore > iBest)
+ {
+ iBest = iScore;
+ pBest = i;
+ pDBest = d;
+ }
+ if(pOut)
+ {
+ QString szOut;
+ QString szNam = d->name();
+ KviQString::sprintf(szOut,__tr2qs_ctx("Trying media player interface \"%Q\": score %d","mediaplayer"),&(szNam),iScore);
+ pOut->output(KVI_OUT_MULTIMEDIA,szOut);
+ }
+ }
+ }
+ }
+ if(pDBest)
+ {
+ KVI_OPTION_STRING(KviOption_stringPreferredMediaPlayer) = pDBest->name();
+ if(pOut)
+ pOut->output(KVI_OUT_MULTIMEDIA,__tr2qs_ctx("Choosing media player interface \"%Q\"","mediaplayer"),&(KVI_OPTION_STRING(KviOption_stringPreferredMediaPlayer)));
+ } else {
+ if(pOut)
+ pOut->outputNoFmt(KVI_OUT_MULTIMEDIA,__tr2qs_ctx("Seems that there is no usable media player on this machine","mediaplayer"));
+ }
+ return pBest;
+}
+
+
+
+ #define MP_KVS_FAIL_ON_NO_INTERFACE \
+ if(!g_pMPInterface) \
+ { \
+ c->warning(__tr2qs_ctx("No mediaplayer interface selected. Try /mediaplayer.detect","mediaplayer")); \
+ return true; \
+ } \
+
+ #define MP_KVS_COMMAND(__name) static bool mediaplayer_kvs_cmd_ ## __name (KviKvsModuleCommandCall * c)
+ #define MP_KVS_FUNCTION(__name) static bool mediaplayer_kvs_fnc_ ## __name (KviKvsModuleFunctionCall * c)
+
+ #define MP_KVS_SIMPLE_COMMAND(__name,__ifacecommand) \
+ MP_KVS_COMMAND(__name) \
+ { \
+ KVSM_PARAMETERS_BEGIN(c) \
+ KVSM_PARAMETERS_END(c) \
+ \
+ MP_KVS_FAIL_ON_NO_INTERFACE \
+ \
+ if(!g_pMPInterface->__ifacecommand()) \
+ { \
+ if(!c->hasSwitch('q',"quiet")) \
+ { \
+ c->warning(__tr2qs_ctx("The selected media player interface failed to execute the requested function","mediaplayer")); \
+ QString tmp = __tr2qs_ctx("Last interface error: ","mediaplayer"); \
+ tmp += g_pMPInterface->lastError(); \
+ c->warning(tmp); \
+ } \
+ }\
+ return true; \
+ }
+
+ #define MP_KVS_SIMPLE_STRING_FUNCTION(__name,__ifacecommand) \
+ MP_KVS_FUNCTION(__name) \
+ { \
+ MP_KVS_FAIL_ON_NO_INTERFACE \
+ QString szRet = g_pMPInterface->__ifacecommand(); \
+ c->returnValue()->setString(szRet); \
+ return true; \
+ }
+
+ #define MP_KVS_SIMPLE_INT_FUNCTION(__name,__ifacecommand) \
+ MP_KVS_FUNCTION(__name) \
+ { \
+ MP_KVS_FAIL_ON_NO_INTERFACE \
+ int iRet = g_pMPInterface->__ifacecommand(); \
+ c->returnValue()->setInteger(iRet); \
+ return true; \
+ }
+ // FINDME!
+ #define MP_KVS_SIMPLE_BOOL_FUNCTION(__name,__ifacecommand) \
+ MP_KVS_FUNCTION(__name) \
+ { \
+ MP_KVS_FAIL_ON_NO_INTERFACE \
+ bool bRet = g_pMPInterface->__ifacecommand(); \
+ c->returnValue()->setBoolean(bRet); \
+ return true; \
+ }
+
+
+/*
+ @doc: mediaplayer.play
+ @type:
+ command
+ @title:
+ mediaplayer.play
+ @short:
+ Starts media playback in the selected media player
+ @syntax:
+ mediaplayer.play [-q]
+ @description:
+ Starts playback in the remote instance of the currently selected media player.[br]
+ Take a look at the [module:mediaplayer]mediaplayer module documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module],
+ [cmd]mediaplayer.stop[/cmd],
+ [cmd]mediaplayer.pause[/cmd],
+ [cmd]mediaplayer.prev[/cmd],
+ [cmd]mediaplayer.next[/cmd],
+ [fnc]$mediaplayer.nowPlaying[/fnc],
+ [fnc]$mediaplayer.status[/fnc]
+*/
+
+MP_KVS_SIMPLE_COMMAND(play,play)
+
+/*
+ @doc: mediaplayer.hide
+ @type:
+ command
+ @title:
+ mediaplayer.hide
+ @short:
+ Hide the mediaplayer [-q]
+ @syntax:
+ mediaplayer.hide
+ @description:
+ Hide the player interface.[br]
+ Take a look at the [module:mediaplayer]mediaplayer module documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module],
+ [cmd]mediaplayer.quit[/cmd],
+ [cmd]mediaplayer.show[/cmd],
+ [cmd]mediaplayer.minimize[/cmd]
+*/
+
+MP_KVS_SIMPLE_COMMAND(hide,hide)
+
+/*
+ @doc: mediaplayer.show
+ @type:
+ command
+ @title:
+ mediaplayer.show
+ @short:
+ Show the mediaplayer.
+ @syntax:
+ mediaplayer.show [-q]
+ @description:
+ Show the player interface.[br]
+ When you use this function in your script, remember to reshow mediaplayer's window [br]
+ or quit the mediplayerwindow to the exit.[br]
+ Take a look at the [module:mediaplayer]mediaplayer module documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module],
+ [cmd]mediaplayer.quit[/cmd],
+ [cmd]mediaplayer.hide[/cmd],
+ [cmd]mediaplayer.minimize[/cmd]
+*/
+
+MP_KVS_SIMPLE_COMMAND(show,show)
+
+/*
+ @doc: mediaplayer.minimize
+ @type:
+ command
+ @title:
+ mediaplayer.minimize
+ @short:
+ Minimize the mediaplayer.
+ @syntax:
+ mediaplayer.minimize [-q]
+ @description:
+ Minimize the player interface.[br]
+ Take a look at the [module:mediaplayer]mediaplayer module documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module],
+ [cmd]mediaplayer.quit[/cmd],
+ [cmd]mediaplayer.hide[/cmd],
+ [cmd]mediaplayer.show[/cmd]
+*/
+
+MP_KVS_SIMPLE_COMMAND(minimize,minimize)
+
+/*
+ @doc: mediaplayer.stop
+ @type:
+ command
+ @title:
+ mediaplayer.stop
+ @short:
+ Stops media playback in the selected media player
+ @syntax:
+ mediaplayer.stop [-q]
+ @description:
+ Stops playback in the remote instance of the currently selected media player.[br]
+ Take a look at the [module:mediaplayer]mediaplayer module documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module],
+ [cmd]mediaplayer.play[/cmd],
+ [cmd]mediaplayer.pause[/cmd],
+ [cmd]mediaplayer.prev[/cmd],
+ [cmd]mediaplayer.next[/cmd],
+ [fnc]$mediaplayer.nowPlaying[/fnc],
+ [fnc]$mediaplayer.status[/fnc]
+*/
+
+MP_KVS_SIMPLE_COMMAND(stop,stop)
+
+/*
+ @doc: mediaplayer.next
+ @type:
+ command
+ @title:
+ mediaplayer.next
+ @short:
+ Starts playback of the next song (mediaplayer interface module)
+ @syntax:
+ mediaplayer.next [-q]
+ @description:
+ Starts playback of the next song in the remote instance of the slave media player.[br]
+ Take a look at the [module:mediaplayer]mediaplayer module documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module]
+ [cmd]mediaplayer.stop[/cmd],
+ [cmd]mediaplayer.pause[/cmd],
+ [cmd]mediaplayer.prev[/cmd],
+ [cmd]mediaplayer.play[/cmd],
+ [fnc]$mediaplayer.nowPlaying[/fnc],
+ [fnc]$mediaplayer.status[/fnc]
+*/
+
+MP_KVS_SIMPLE_COMMAND(next,next)
+
+/*
+ @doc: mediaplayer.prev
+ @type:
+ command
+ @title:
+ mediaplayer.prev
+ @short:
+ Starts playback of the previous song (mediaplayer interface module)
+ @syntax:
+ mediaplayer.prev [-q]
+ @description:
+ Starts playback of the previous song in the remote instance of the slave media player.[br]
+ Take a look at the [module:mediaplayer]mediaplayer module documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module]
+ [cmd]mediaplayer.stop[/cmd],
+ [cmd]mediaplayer.pause[/cmd],
+ [cmd]mediaplayer.play[/cmd],
+ [cmd]mediaplayer.next[/cmd],
+ [fnc]$mediaplayer.nowPlaying[/fnc],
+ [fnc]$mediaplayer.status[/fnc]
+*/
+
+MP_KVS_SIMPLE_COMMAND(prev,prev)
+
+/*
+ @doc: mediaplayer.quit
+ @type:
+ command
+ @title:
+ mediaplayer.quit
+ @short:
+ Quits the remote media player (mediaplayer interface module)
+ @syntax:
+ mediaplayer.quit [-q]
+ @description:
+ Quits the remote instance of the slave media player.[br]
+ Take a look at the [module:mediaplayer]mediaplayer module documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module]
+ [cmd]mediaplayer.stop[/cmd],
+ [cmd]mediaplayer.pause[/cmd],
+ [cmd]mediaplayer.prev[/cmd],
+ [cmd]mediaplayer.next[/cmd],
+ [fnc]$mediaplayer.nowPlaying[/fnc],
+ [fnc]$mediaplayer.status[/fnc]
+*/
+
+MP_KVS_SIMPLE_COMMAND(quit,quit)
+
+/*
+ @doc: mediaplayer.pause
+ @type:
+ command
+ @title:
+ mediaplayer.pause
+ @short:
+ Pauses playback (mediaplayer interface module)
+ @syntax:
+ mediaplayer.pause [-q]
+ @description:
+ Pauses playback in the remote instance of the slave media player.[br]
+ Take a look at the [module:mediaplayer]mediaplayer module documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module]
+ [cmd]mediaplayer.stop[/cmd],
+ [cmd]mediaplayer.pause[/cmd],
+ [cmd]mediaplayer.prev[/cmd],
+ [cmd]mediaplayer.next[/cmd],
+ [fnc]$mediaplayer.nowPlaying[/fnc],
+ [fnc]$mediaplayer.status[/fnc]
+*/
+
+MP_KVS_SIMPLE_COMMAND(pause,pause)
+
+/*
+ @doc: mediaplayer.detect
+ @type:
+ command
+ @title:
+ mediaplayer.detect
+ @short:
+ Detects the media player interface to use
+ @syntax:
+ mediaplayer.detect [-q]
+ @description:
+ Attempts to detect the best media player interface
+ for the current system. The -q switch causes the detection
+ algorithm to run quietly. This function may attempt to start
+ the media players in order to verify their presence on the system.
+ You can guide the function by starting the media player you
+ prefer before running it: if a running media player is found, it takes
+ precedence over the others.[br]
+ Take a look at the [module:mediaplayer]mediaplayer module documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module]
+ [cmd]mediaplayer.stop[/cmd], [cmd]mediaplayer.pause[/cmd],
+ [cmd]mediaplayer.prev[/cmd],
+ [cmd]mediaplayer.next[/cmd],
+ [fnc]$mediaplayer.nowPlaying[/fnc],
+ [fnc]$mediaplayer.status[/fnc],
+ [cmd]mediaplayer.setPlayer[/cmd],
+ [fnc]$mediaplayer.player[/fnc]
+*/
+
+MP_KVS_COMMAND(detect)
+{
+ g_pMPInterface = auto_detect_player(c->hasSwitch('q',"quiet") ? 0 : c->window());
+ return true;
+}
+
+/*
+ @doc: mediaplayer.setPlayer
+ @type:
+ command
+ @title:
+ mediaplayer.setPlayer
+ @short:
+ Sets the media player interface
+ @syntax:
+ mediaplayer.setPlayer <player_name>
+ @description:
+ Sets the media player interface to be used by the
+ mediaplayer module. <interface_name> must be one
+ of the player names returned by [fnc]$mediaplayer.playerList()[/fnc]
+ Take a look at the [module:mediaplayer]mediaplayer module documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module],
+ [cmd]mediaplayer.detect[/cmd], [fnc]$mediaplayer.player[/fnc]
+*/
+
+MP_KVS_COMMAND(setPlayer)
+{
+ QString szPlayer;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("player",KVS_PT_STRING,0,szPlayer)
+ KVSM_PARAMETERS_END(c)
+
+ for(KviMediaPlayerInterfaceDescriptor * d = g_pDescriptorList->first();d;d = g_pDescriptorList->next())
+ {
+ if(d->name() == szPlayer)
+ {
+ g_pMPInterface = d->instance();
+ KVI_OPTION_STRING(KviOption_stringPreferredMediaPlayer) = szPlayer;
+ return true;
+ }
+ }
+
+ return true;
+}
+
+/*
+ @doc: mediaplayer.player
+ @type:
+ function
+ @title:
+ $mediaplayer.player
+ @short:
+ Returns the currently set media player interface
+ @syntax:
+ $mediaplayer.player()
+ @description:
+ Returns the currently set media player interface.
+ Take a look at the [module:mediaplayer]mediaplayer module documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module],
+ [cmd]mediaplayer.detect[/cmd], [cmd]mediaplayer.setPlayer[/cmd]
+*/
+
+MP_KVS_FUNCTION(player)
+{
+ c->returnValue()->setString(KVI_OPTION_STRING(KviOption_stringPreferredMediaPlayer));
+ return true;
+}
+
+/*
+ @doc: mediaplayer.playerList
+ @type:
+ function
+ @title:
+ $mediaplayer.playerList
+ @short:
+ Returns a the list of the supported media player interfaces
+ @syntax:
+ $mediaplayer.playerList()
+ @description:
+ Returns an array containing the supported media player interfaces.
+ Take a look at the [module:mediaplayer]mediaplayer module documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module]
+ [cmd]mediaplayer.detect[/cmd], [cmd]mediaplayer.setPlayer[/cmd],
+ [fnc]$mediaplayer.player[/fnc]
+*/
+
+MP_KVS_FUNCTION(playerList)
+{
+ KviKvsArray* pArray = new KviKvsArray();
+ int id=0;
+
+ for(KviMediaPlayerInterfaceDescriptor * d = g_pDescriptorList->first();d;d = g_pDescriptorList->next())
+ {
+ pArray->set(id++,new KviKvsVariant(d->name()));
+ }
+ c->returnValue()->setArray(pArray);
+ return true;
+}
+/*
+ @doc: mediaplayer.playmrl
+ @type:
+ command
+ @title:
+ mediaplayer.playMrl
+ @short:
+ Plays the specified media on the selected media player
+ @syntax:
+ mediaplayer.playMrl <mrl>
+ @description:
+ Plays the media specified by the <mrl> on the currently
+ selected media player interface. <mrl> is a standard Media Resource
+ Locator. Examples of such locators are: 'file:///home/myfile.mp3' ,
+ 'http://streaming.server.top:123', 'dvd:// or dvb://channelname'.
+ Take a look at the [module:mediaplayer]mediaplayer module documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module],
+ [fnc]$mediaplayer.mrl[/fnc],
+ [fnc]$mediaplayer.localFile[/fnc],
+ [cmd]mediaplayer.play[/cmd]
+*/
+
+MP_KVS_COMMAND(playMrl)
+{
+ QString szMrl;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("player",KVS_PT_STRING,0,szMrl)
+ KVSM_PARAMETERS_END(c)
+
+ MP_KVS_FAIL_ON_NO_INTERFACE
+ if(!g_pMPInterface->playMrl(szMrl))
+ {
+ if(!c->hasSwitch('q',"quiet"))
+ {
+ c->warning(__tr2qs_ctx("The selected media player interface failed to execute the requested function","mediaplayer"));
+ QString tmp = __tr2qs_ctx("Last interface error: ","mediaplayer");
+ tmp += g_pMPInterface->lastError();
+ c->warning(tmp);
+ }
+ }
+
+ return true;
+}
+
+MP_KVS_COMMAND(amipExec)
+{
+ QString szMrl;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("player",KVS_PT_STRING,0,szMrl)
+ KVSM_PARAMETERS_END(c)
+
+ MP_KVS_FAIL_ON_NO_INTERFACE
+ if(!g_pMPInterface->amipExec(szMrl))
+ {
+ if(!c->hasSwitch('q',"quiet"))
+ {
+ c->warning(__tr2qs_ctx("The selected media player interface failed to execute the requested function","mediaplayer"));
+ QString tmp = __tr2qs_ctx("Last interface error: ","mediaplayer");
+ tmp += g_pMPInterface->lastError();
+ c->warning(tmp);
+ }
+ }
+
+ return true;
+}
+
+
+/*
+ @doc: mediaplayer.jumpTo
+ @type:
+ command
+ @title:
+ mediaplayer.jumpTo
+ @short:
+ Sets the position in seconds of the current song.
+ @syntax:
+ mediaplayer.jumpTo [-q] <pos>
+ @description:
+ Sets the position in seconds of the current song .
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module],
+ [fnc]$mediaplayer.position[/fnc],
+ [fnc]$mediaplayer.lenght[/fnc],
+*/
+
+MP_KVS_COMMAND(jumpTo)
+{
+ int iPos;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("position",KVS_PT_INT,0,iPos)
+ KVSM_PARAMETERS_END(c)
+
+ MP_KVS_FAIL_ON_NO_INTERFACE
+ if(!g_pMPInterface->jumpTo(iPos))
+ {
+ if(!c->hasSwitch('q',"quiet"))
+ {
+ c->warning(__tr2qs_ctx("The selected media player interface failed to execute the requested function","mediaplayer"));
+ QString tmp = __tr2qs_ctx("Last interface error: ","mediaplayer");
+ tmp += g_pMPInterface->lastError();
+ c->warning(tmp);
+ }
+ }
+ return true;
+}
+
+/*
+ @doc: mediaplayer.setVol
+ @type:
+ command
+ @title:
+ mediaplayer.setVol
+ @short:
+ Set the media player volume to <vol> (from 0-255)
+ @syntax:
+ mediaplayer.setVol [-q] <vol>
+ @description:
+ Set the media player volume to <vol> (the valid range is from 0 to ....)
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module],
+ [fnc]$mediaplayer.getVol[/fnc]
+*/
+
+MP_KVS_COMMAND(setVol)
+{
+ kvs_int_t iVol;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("volume",KVS_PT_INT,0,iVol)
+ KVSM_PARAMETERS_END(c)
+
+ MP_KVS_FAIL_ON_NO_INTERFACE
+ if(!g_pMPInterface->setVol(iVol))
+ {
+ if(!c->hasSwitch('q',"quiet"))
+ {
+ c->warning(__tr2qs_ctx("The selected media player interface failed to execute the requested function","mediaplayer"));
+ QString tmp = __tr2qs_ctx("Last interface error: ","mediaplayer");
+ tmp += g_pMPInterface->lastError();
+ c->warning(tmp);
+ }
+ }
+ return true;
+}
+
+/*
+ @doc: mediaplayer.getVol
+ @type:
+ function
+ @title:
+ $mediaplayer.getVol
+ @short:
+ Returns the current volume of the media player
+ @syntax:
+ $mediaplayer.getVol()
+ @description:
+ Returns the current volume of the media player within 0 to 255.
+ Take a look at the [module:mediaplayer]mediaplayer module documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module],
+ [cmd]mediaplayer.setVol[/cmd]
+*/
+
+MP_KVS_SIMPLE_INT_FUNCTION(getVol,getVol)
+
+/*
+ @doc: mediaplayer.mute
+ @type:
+ command
+ @title:
+ mediaplayer.mute
+ @short:
+ Mute the volume selected media player
+ @syntax:
+ mediaplayer.mute
+ @description:
+ Mutes the volume selected media player.[br]
+ If already muted, it restores the volume.[br]
+ Take a look at the [module:mediaplayer]mediaplayer module documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module],
+ [cmd]mediaplayer.play[/cmd], [cmd]mediaplayer.pause[/cmd],
+ [cmd]mediaplayer.prev[/cmd],
+ [cmd]mediaplayer.next[/cmd],
+ [fnc]$mediaplayer.nowPlaying[/fnc],
+ [fnc]$mediaplayer.status[/fnc]
+*/
+
+MP_KVS_SIMPLE_COMMAND(mute,mute)
+
+
+/*
+ @doc: mediaplayer.mrl
+ @type:
+ function
+ @title:
+ $mediaplayer.mrl
+ @short:
+ Returns the mrl of the currently played media
+ @syntax:
+ $mediaplayer.mrl()
+ @description:
+ Returns the mrl of the media currently played by the selected media player interface.
+ The mrl is a standard Media Resource Locator.
+ Examples of such locators are: 'file:///home/myfile.mp3' ,
+ 'http://streaming.server.top:123', 'dvd:// or dvb://channelname'.
+ This means that the returned string may NOT refer to a local file:
+ it refers to the local file only if the 'file://' prefix is found ([fnc]$mediaplayer.localFile()[/fnc]
+ checks that for you).
+ The returned string is empty if the player isn't currently playing.[br]
+ Take a look at the [module:mediaplayer]mediaplayer module documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module],
+ [cmd]mediaplayer.playMrl[/cmd],
+ [fnc]$mediaplayer.localFile[/fnc]
+*/
+
+MP_KVS_SIMPLE_STRING_FUNCTION(mrl,mrl)
+
+/*
+ @doc: mediaplayer.nowPlaying
+ @type:
+ function
+ @title:
+ $mediaplayer.nowPlaying
+ @short:
+ Returns a descripting of the currently played media
+ @syntax:
+ $mediaplayer.nowPlaying()
+ @description:
+ Returns a description fo the media currently played
+ by the selected media player interface. The description
+ will usually contain the title of the media and eventually
+ some additional information like the artist name or album.
+ This function is granted to be implemented by all the media
+ player interfaces and return an empty string only
+ if the player is not currently playing or there is a communication
+ error.
+ Take a look at the [module:mediaplayer]mediaplayer module documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module],
+ [fnc]$mediaplayer.mrl[/fnc], [cmd]mediaplayer.playMrl[/cmd],
+ [cmd]mediaplayer.play[/cmd], [fnc]$mediaplayer.title[/fnc],
+ [fnc]$mediaplayer.artist[/fnc], [fnc]$mediaplayer.genre[/fnc],
+ [fnc]$mediaplayer.year[/fnc], [fnc]$mediaplayer.comment[/fnc],
+ [fnc]$mediaplayer.mediaType[/fnc],
+ [fnc]$mediaplayer.bitRate[/fnc],
+ [fnc]$mediaplayer.sampleRate[/fnc],
+ [fnc]$mediaplayer.length[/fnc],
+ [fnc]$mediaplayer.position[/fnc]
+*/
+
+MP_KVS_SIMPLE_STRING_FUNCTION(nowPlaying,nowPlaying)
+
+/*
+ @doc: mediaplayer.title
+ @type:
+ function
+ @title:
+ $mediaplayer.title
+ @short:
+ Returns the title of the current media
+ @syntax:
+ $mediaplayer.title()
+ @description:
+ Returns the title of the multimedia file being played by the
+ remote instance of the media player. This function is not granted
+ to work with all the player interfaces and all the media types:
+ if you want to write portable code you should use [fnc]$mediaplayer.nowPlaying[/fnc]
+ instead.[br]
+ Take a look at the [module:mediaplayer]mediaplayer module documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module],
+ [fnc]$mediaplayer.mrl[/fnc], [cmd]mediaplayer.playMrl[/cmd],
+ [cmd]mediaplayer.play[/cmd], [fnc]$mediaplayer.nowPlaying[/fnc],
+ [fnc]$mediaplayer.artist[/fnc], [fnc]$mediaplayer.genre[/fnc],
+ [fnc]$mediaplayer.year[/fnc], [fnc]$mediaplayer.comment[/fnc],
+ [fnc]$mediaplayer.mediaType[/fnc]
+*/
+
+MP_KVS_SIMPLE_STRING_FUNCTION(title,title)
+
+/*
+ @doc: mediaplayer.artist
+ @type:
+ function
+ @title:
+ $mediaplayer.artist
+ @short:
+ Returns the artist of the media player
+ @syntax:
+ $mediaplayer.artist()
+ @description:
+ Returns the artist property of the media currently played by
+ the selected media player interface. This function is not granted
+ to work with all the player interfaces and all the media types:
+ if you want to write portable code you should use [fnc]$mediaplayer.nowPlaying[/fnc]
+ instead.[br]
+ Take a look at the [module:mediaplayer]mediaplayer module documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module],
+ [fnc]$mediaplayer.mrl[/fnc], [cmd]mediaplayer.playMrl[/cmd],
+ [cmd]mediaplayer.play[/cmd], [fnc]$mediaplayer.nowPlaying[/fnc],
+ [fnc]$mediaplayer.title[/fnc], [fnc]$mediaplayer.genre[/fnc],
+ [fnc]$mediaplayer.year[/fnc], [fnc]$mediaplayer.comment[/fnc],
+ [fnc]$mediaplayer.mediaType[/fnc],
+ [fnc]$mediaplayer.album[/fnc],
+ [fnc]$mediaplayer.length[/fnc],
+ [fnc]$mediaplayer.position[/fnc]
+*/
+
+MP_KVS_SIMPLE_STRING_FUNCTION(artist,artist)
+
+/*
+ @doc: mediaplayer.genre
+ @type:
+ function
+ @title:
+ $mediaplayer.genre
+ @short:
+ Returns the genre of the media player
+ @syntax:
+ $mediaplayer.genre()
+ @description:
+ Returns the genre property of the media currently played by
+ the selected media player interface. This function is not granted
+ to work with all the player interfaces and all the media types:
+ if you want to write portable code you should use [fnc]$mediaplayer.nowPlaying[/fnc]
+ instead.[br]
+ Take a look at the [module:mediaplayer]mediaplayer module documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module],
+ [fnc]$mediaplayer.mrl[/fnc], [cmd]mediaplayer.playMrl[/cmd],
+ [cmd]mediaplayer.play[/cmd], [fnc]$mediaplayer.nowPlaying[/fnc],
+ [fnc]$mediaplayer.artist[/fnc], [fnc]$mediaplayer.artist[/fnc],
+ [fnc]$mediaplayer.year[/fnc], [fnc]$mediaplayer.comment[/fnc],
+ [fnc]$mediaplayer.mediaType[/fnc], [fnc]$mediaplayer.album[/fnc],
+ [fnc]$mediaplayer.length[/fnc], [fnc]$mediaplayer.position[/fnc]
+*/
+
+MP_KVS_SIMPLE_STRING_FUNCTION(genre,genre)
+
+/*
+ @doc: mediaplayer.year
+ @type:
+ function
+ @title:
+ $mediaplayer.year
+ @short:
+ Returns the year of the media player
+ @syntax:
+ $mediaplayer.year()
+ @description:
+ Returns the year property of the media currently played by
+ the selected media player interface. This function is not granted
+ to work with all the player interfaces and all the media types:
+ if you want to write portable code you should use [fnc]$mediaplayer.nowPlaying[/fnc]
+ instead.[br]
+ Take a look at the [module:mediaplayer]mediaplayer module documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module],
+ [fnc]$mediaplayer.mrl[/fnc], [cmd]mediaplayer.playMrl[/cmd],
+ [cmd]mediaplayer.play[/cmd], [fnc]$mediaplayer.nowPlaying[/fnc],
+ [fnc]$mediaplayer.artist[/fnc], [fnc]$mediaplayer.artist[/fnc],
+ [fnc]$mediaplayer.genre[/fnc], [fnc]$mediaplayer.comment[/fnc],
+ [fnc]$mediaplayer.mediaType[/fnc], [fnc]$mediaplayer.album[/fnc],
+ [fnc]$mediaplayer.length[/fnc], [fnc]$mediaplayer.position[/fnc]
+*/
+
+MP_KVS_SIMPLE_STRING_FUNCTION(year,year)
+
+/*
+ @doc: mediaplayer.comment
+ @type:
+ function
+ @title:
+ $mediaplayer.comment
+ @short:
+ Returns the comment of the media player
+ @syntax:
+ $mediaplayer.comment()
+ @description:
+ Returns the comment property of the media currently played by
+ the selected media player interface. This function is not granted
+ to work with all the player interfaces and all the media types:
+ if you want to write portable code you should use [fnc]$mediaplayer.nowPlaying[/fnc]
+ instead.[br]
+ Take a look at the [module:mediaplayer]mediaplayer module documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module],
+ [fnc]$mediaplayer.mrl[/fnc], [cmd]mediaplayer.playMrl[/cmd],
+ [cmd]mediaplayer.play[/cmd], [fnc]$mediaplayer.nowPlaying[/fnc],
+ [fnc]$mediaplayer.artist[/fnc], [fnc]$mediaplayer.artist[/fnc],
+ [fnc]$mediaplayer.year[/fnc], [fnc]$mediaplayer.year[/fnc],
+ [fnc]$mediaplayer.mediaType[/fnc], [fnc]$mediaplayer.album[/fnc],
+ [fnc]$mediaplayer.length[/fnc], [fnc]$mediaplayer.position[/fnc]
+*/
+
+MP_KVS_SIMPLE_STRING_FUNCTION(comment,comment)
+
+/*
+ @doc: mediaplayer.album
+ @type:
+ function
+ @title:
+ $mediaplayer.album
+ @short:
+ Returns the album of the media player
+ @syntax:
+ $mediaplayer.album()
+ @description:
+ Returns the album property of the media currently played by
+ the selected media player interface. This function is not granted
+ to work with all the player interfaces and all the media types:
+ if you want to write portable code you should use [fnc]$mediaplayer.nowPlaying[/fnc]
+ instead.[br]
+ Take a look at the [module:mediaplayer]mediaplayer module documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module],
+ [fnc]$mediaplayer.mrl[/fnc], [cmd]mediaplayer.playMrl[/cmd],
+ [cmd]mediaplayer.play[/cmd], [fnc]$mediaplayer.nowPlaying[/fnc],
+ [fnc]$mediaplayer.artist[/fnc], [fnc]$mediaplayer.artist[/fnc],
+ [fnc]$mediaplayer.year[/fnc], [fnc]$mediaplayer.comment[/fnc],
+ [fnc]$mediaplayer.mediaType[/fnc],
+ [fnc]$mediaplayer.bitRate[/fnc],
+ [fnc]$mediaplayer.sampleRate[/fnc],
+ [fnc]$mediaplayer.length[/fnc],
+ [fnc]$mediaplayer.position[/fnc]
+*/
+
+MP_KVS_SIMPLE_STRING_FUNCTION(album,album)
+
+/*
+ @doc: mediaplayer.mediaType
+ @type:
+ function
+ @title:
+ $mediaplayer.mediaType
+ @short:
+ Returns the currently played media type
+ @syntax:
+ $mediaplayer.medyaType()
+ @description:
+ Returns a string describing the media type currently played
+ by the selected media player interface. This function is not granted
+ to work with all the player interfaces and all the media types.
+ Take a look at the [module:mediaplayer]mediaplayer module documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module]
+ [fnc]$mediaplayer.mrl[/fnc], [cmd]mediaplayer.playMrl[/cmd],
+ [cmd]mediaplayer.play[/cmd], [fnc]$mediaplayer.nowPlaying[/fnc],
+ [fnc]$mediaplayer.artist[/fnc],
+ [fnc]$mediaplayer.artist[/fnc],
+ [fnc]$mediaplayer.year[/fnc], [fnc]$mediaplayer.comment[/fnc]
+*/
+
+MP_KVS_SIMPLE_STRING_FUNCTION(mediaType,mediaType)
+
+/*
+ @doc: mediaplayer.bitRate
+ @type:
+ function
+ @title:
+ $mediaplayer.bitRate
+ @short:
+ Returns the bit rate of the current song
+ @syntax:
+ $mediaplayer.bitRate
+ @description:
+ Returns the bit rate (in bits/sec) of the multimedia file being played by the
+ remote instance of the media player.This function is not granted
+ to work with all the player interfaces and all the media types so
+ you may get -1 or 0 in return sometimes.[br]
+ Take a look at the [module:mediaplayer]mediaplayer module documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module]
+ [fnc]$mediaplayer.mrl[/fnc], [cmd]mediaplayer.playMrl[/cmd],
+ [cmd]mediaplayer.play[/cmd], [fnc]$mediaplayer.nowPlaying[/fnc],
+ [fnc]$mediaplayer.artist[/fnc], [fnc]$mediaplayer.artist[/fnc],
+ [fnc]$mediaplayer.year[/fnc], [fnc]$mediaplayer.comment[/fnc],
+ [fnc]$mediaplayer.sampleRate[/fnc],
+ [fnc]$mediaplayer.length[/fnc],
+ [fnc]$mediaplayer.position[/fnc]
+*/
+
+MP_KVS_SIMPLE_INT_FUNCTION(bitRate,bitRate)
+
+
+/*
+ @doc: mediaplayer.sampleRate
+ @type:
+ function
+ @title:
+ $mediaplayer.sampleRate
+ @short:
+ Returns the sample rate of the current song
+ @syntax:
+ $mediaplayer.sampleRate
+ @description:
+ Returns the sample rate (in Hz) of the multimedia file being played by the
+ remote instance of the media player.This function is not granted
+ to work with all the player interfaces and all the media types so
+ you may get -1 or 0 in return sometimes.[br]
+ Take a look at the [module:mediaplayer]mediaplayer module documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module]
+ [fnc]$mediaplayer.mrl[/fnc], [cmd]mediaplayer.playMrl[/cmd],
+ [cmd]mediaplayer.play[/cmd], [fnc]$mediaplayer.nowPlaying[/fnc],
+ [fnc]$mediaplayer.artist[/fnc], [fnc]$mediaplayer.artist[/fnc],
+ [fnc]$mediaplayer.year[/fnc], [fnc]$mediaplayer.comment[/fnc],
+ [fnc]$mediaplayer.bitRate[/fnc], [fnc]$mediaplayer.length[/fnc],
+ [fnc]$mediaplayer.position[/fnc], [fnc]$mediaplayer.channels[/fnc]
+*/
+
+MP_KVS_SIMPLE_INT_FUNCTION(sampleRate,sampleRate)
+
+
+/*
+ @doc: mediaplayer.length
+ @type:
+ function
+ @title:
+ $mediaplayer.length
+ @short:
+ Returns the length of the current media
+ @syntax:
+ $mediaplayer.length()
+ @description:
+ Returns the length in milliseconds of the multimedia file being played by the
+ remote instance of the media player.[br]
+ Take a look at the [module:mediaplayer]mediaplayer module documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module],
+ [fnc]$mediaplayer.mrl[/fnc], [cmd]mediaplayer.playMrl[/cmd],
+ [cmd]mediaplayer.play[/cmd], [fnc]$mediaplayer.nowPlaying[/fnc],
+ [fnc]$mediaplayer.artist[/fnc],
+ [fnc]$mediaplayer.artist[/fnc],
+ [fnc]$mediaplayer.year[/fnc], [fnc]$mediaplayer.comment[/fnc],
+ [fnc]$mediaplayer.sampleRate[/fnc],
+ [fnc]$mediaplayer.bitRate[/fnc],
+ [fnc]$mediaplayer.position[/fnc]
+*/
+
+MP_KVS_SIMPLE_INT_FUNCTION(length,length)
+
+/*
+ @doc: mediaplayer.position
+ @type:
+ function
+ @title:
+ $mediaplayer.position
+ @short:
+ Returns the position of the current media
+ @syntax:
+ $mediaplayer.position()
+ @description:
+ Returns the currently elapsed time of the multimedia file being played by the
+ remote instance of the media player.
+ The time is expressed in milliseconds.[br]
+ Take a look at the [module:mediaplayer]mediaplayer module documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module]
+ [fnc]$mediaplayer.mrl[/fnc], [cmd]mediaplayer.playMrl[/cmd],
+ [cmd]mediaplayer.play[/cmd], [fnc]$mediaplayer.nowPlaying[/fnc],
+ [fnc]$mediaplayer.artist[/fnc], [fnc]$mediaplayer.artist[/fnc],
+ [fnc]$mediaplayer.year[/fnc], [fnc]$mediaplayer.comment[/fnc],
+ [fnc]$mediaplayer.sampleRate[/fnc],
+ [fnc]$mediaplayer.length[/fnc],
+ [fnc]$mediaplayer.bitRate[/fnc], [fnc]$mediaplayer.channels[/fnc]
+*/
+
+MP_KVS_SIMPLE_INT_FUNCTION(position,position)
+
+/*
+ @doc: mediaplayer.channels
+ @type:
+ function
+ @title:
+ $mediaplayer.channels
+ @short:
+ Returns the number of channels of the current song
+ @syntax:
+ $mediaplayer.channels()
+ @description:
+ Returns the number of channels of the multimedia file being played by the
+ remote instance of the media player.This function is not granted
+ to work with all the player interfaces and all the media types so
+ you may get -1 or 0 in return sometimes.[br]
+ Take a look at the [module:mediaplayer]mediaplayer module documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module]
+*/
+
+MP_KVS_SIMPLE_INT_FUNCTION(channels,channels)
+
+
+/*
+ @doc: mediaplayer.setPlayListPos
+ @type:
+ command
+ @title:
+ mediaplayer.setPlayListPos
+ @short:
+ Set the position for the current song.
+ @syntax:
+ mediaplayer.setPlayListPos [-q] <pos:integer>
+ @description:
+ Set the position in the player list for the current song to <pos>.[br]
+ Take a look at the [module:mediaplayer]mediaplayer module documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module],
+ [fnc]$mediaplayer.getPlayListPos[/fnc]
+*/
+
+MP_KVS_COMMAND(setPlayListPos)
+{
+ int iPos;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("position",KVS_PT_INT,0,iPos)
+ KVSM_PARAMETERS_END(c)
+
+ MP_KVS_FAIL_ON_NO_INTERFACE
+ if(!g_pMPInterface->setPlayListPos(iPos))
+ {
+ if(!c->hasSwitch('q',"quiet"))
+ {
+ c->warning(__tr2qs_ctx("The selected media player interface failed to execute the requested function","mediaplayer"));
+ QString tmp = __tr2qs_ctx("Last interface error: ","mediaplayer");
+ tmp += g_pMPInterface->lastError();
+ c->warning(tmp);
+ }
+ }
+ return true;
+}
+
+/*
+ @doc: mediaplayer.getPlayListPos
+ @type:
+ function
+ @title:
+ $mediaplayer.getPlayListPos
+ @short:
+ Get the position for the current song.
+ @syntax:
+ $mediaplayer.getPlayListPos()
+ @description:
+ Get the song's position in the player list.[br]
+ Take a look at the [module:mediaplayer]mediaplayer module documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module],
+ [cmd]mediaplayer.getPlayListPos[/cmd]
+*/
+
+MP_KVS_SIMPLE_INT_FUNCTION(getPlayListPos,getPlayListPos)
+
+/*
+ @doc: mediaplayer.getListLength
+ @type:
+ function
+ @title:
+ $mediaplayer.getListLength
+ @short:
+ Return the play list length.
+ @syntax:
+ $mediaplayer.getListLength()
+ @description:
+ Return the player list length.[br]
+ Take a look at the [module:mediaplayer]mediaplayer module documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module],
+*/
+
+MP_KVS_SIMPLE_INT_FUNCTION(getListLength,getListLength)
+
+
+/*
+ @doc: mediaplayer.getRepeat
+ @type:
+ function
+ @title:
+ $mediaplayer.getRepeat
+ @short:
+ Return if "Repeat" is on.
+ @syntax:
+ $mediaplayer.getRepeat()
+ @description:
+ Return the value of the Repeat flag for the current track (1 for ON, 0 for OFF.[br]
+ Take a look at the [module:mediaplayer]mediaplayer module documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module],
+ [cmd]mediaplayer.setRepeat[/cmd], [cmd]mediaplayer.setShuffle[/cmd],
+ [fnc]$mediaplayer.getShuffle[/fnc]
+*/
+
+MP_KVS_SIMPLE_INT_FUNCTION(getRepeat,getRepeat)
+
+
+/*
+ @doc: mediaplayer.getShuffle
+ @type:
+ function
+ @title:
+ $mediaplayer.getShuffle
+ @short:
+ Return if "Shuffle" is on.
+ @syntax:
+ $mediaplayer.getShuffle()
+ @description:
+ Return the value of the Shuffle flag (1 for ON, 0 for OFF.[br]
+ Take a look at the [module:mediaplayer]mediaplayer module documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module],
+ [cmd]mediaplayer.setShuffle[/cmd], [cmd]mediaplayer.setRepeat[/cmd],
+ [fnc]$mediaplayer.getRepeat[/fnc]
+*/
+
+MP_KVS_SIMPLE_BOOL_FUNCTION(getShuffle,getShuffle)
+
+/*
+ @doc: mediaplayer.getEqData
+ @type:
+ function
+ @title:
+ $mediaplayer.getEqData
+ @short:
+ Return the Equalizer Value.
+ @syntax:
+ $mediaplayer.getEqData(<item:integer>,<options:string>)
+ @description:
+ Return the value of the Eq <item>.[br]
+ if 'q' is given as an option, it runs in quiet mode.[br]
+ Take a look at the [module:mediaplayer]mediaplayer module documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module],
+ [cmd]mediaplayer.setShuffle[/cmd], [cmd]mediaplayer.setRepeat[/cmd],
+ [fnc]$mediaplayer.getRepeat[/fnc]
+
+*/
+
+MP_KVS_FUNCTION(getEqData)
+{
+ int iValue;
+ QString szOptions;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("item",KVS_PT_INT,0,iValue)
+ KVSM_PARAMETER("options",KVS_PT_STRING,KVS_PF_OPTIONAL,szOptions)
+ KVSM_PARAMETERS_END(c)
+
+ MP_KVS_FAIL_ON_NO_INTERFACE
+
+ bool bQuiet = szOptions.find('q',false) != -1;
+
+ int ret = g_pMPInterface->getEqData(iValue);
+
+ if(!ret && !bQuiet)
+ {
+ c->warning(__tr2qs_ctx("The selected media player interface failed to execute the requested function","mediaplayer"));
+ QString tmp = __tr2qs_ctx("Last interface error: ","mediaplayer");
+ tmp += g_pMPInterface->lastError();
+ c->warning(tmp);
+ }
+
+ c->returnValue()->setInteger(ret);
+ return true;
+}
+
+/*
+ @doc: mediaplayer.setEqData
+ @type:
+ command
+ @title:
+ mediaplayer.setEqData
+ @short:
+ Return the Equalizer Value.
+ @syntax:
+ mediaplayer.setEqData [-q] <item:integer> <value:integer>
+ @description:
+ Set the value of the Eq <item> to <value>.[br]
+ Take a look at the [module:mediaplayer]mediaplayer module documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module],
+ [fnc]$mediaplayer.getEqData[/fnc]
+*/
+
+MP_KVS_COMMAND(setEqData)
+{
+ int iPos;
+ int iValue;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("item",KVS_PT_INT,0,iPos)
+ KVSM_PARAMETER("value",KVS_PT_INT,0,iValue)
+ KVSM_PARAMETERS_END(c)
+
+ MP_KVS_FAIL_ON_NO_INTERFACE
+ if(!g_pMPInterface->setEqData(iPos,iValue))
+ {
+ if(!c->hasSwitch('q',"quiet"))
+ {
+ c->warning(__tr2qs_ctx("The selected media player interface failed to execute the requested function","mediaplayer"));
+ QString tmp = __tr2qs_ctx("Last interface error: ","mediaplayer");
+ tmp += g_pMPInterface->lastError();
+ c->warning(tmp);
+ }
+ }
+ return true;
+}
+
+/*
+ @doc: mediaplayer.localFile
+ @type:
+ function
+ @title:
+ $mediaplayer.localFile
+ @short:
+ Returns the name of the local file played by the media player
+ @syntax:
+ $mediaplayer.localFile()
+ @description:
+ Returns the name of the local file played by the currently
+ selected media player interface. This function returns
+ an empty string if the player is not playing, there is a communication
+ error or the media played is not a local file (e.g. a stream or another
+ kind of media).[br]
+ Take a look at the [module:mediaplayer]mediaplayer module documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module],
+ [fnc]$mediaplayer.mrl[/fnc], [cmd]mediaplayer.play[/cmd]
+*/
+
+MP_KVS_FUNCTION(localFile)
+{
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETERS_END(c)
+
+ MP_KVS_FAIL_ON_NO_INTERFACE
+ QString szRet = g_pMPInterface->mrl();
+ if(szRet.isEmpty())return true;
+ if(szRet.startsWith("file://",false))
+ {
+ szRet.remove(0,7);
+ c->returnValue()->setString(szRet);
+ }
+ return true;
+}
+
+MP_KVS_FUNCTION(amipEval)
+{
+ QString szMrl;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("player",KVS_PT_STRING,0,szMrl)
+ KVSM_PARAMETERS_END(c)
+
+ MP_KVS_FAIL_ON_NO_INTERFACE
+ QString szRet = g_pMPInterface->amipEval(szMrl);
+ if(szRet.isEmpty())return true;
+
+ c->returnValue()->setString(szRet);
+
+ return true;
+}
+
+/*
+ @doc: mediaplayer.status
+ @type:
+ function
+ @title:
+ $mediaplayer.status
+ @short:
+ Returns the status of the media player
+ @syntax:
+ $mediaplayer.status()
+ @description:
+ Returns the status if the currently selected media player: "playing",
+ "stopped", "paused" or "unknown".
+ Take a look at the [module:mediaplayer]mediaplayer module documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module],
+ [cmd]mediaplayer.play[/cmd]
+*/
+
+MP_KVS_FUNCTION(status)
+{
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETERS_END(c)
+
+ MP_KVS_FAIL_ON_NO_INTERFACE
+ KviMediaPlayerInterface::PlayerStatus eStat = g_pMPInterface->status();
+ switch(eStat)
+ {
+ case KviMediaPlayerInterface::Stopped:
+ c->returnValue()->setString("stopped");
+ break;
+ case KviMediaPlayerInterface::Playing:
+ c->returnValue()->setString("playing");
+ break;
+ case KviMediaPlayerInterface::Paused:
+ c->returnValue()->setString("paused");
+ break;
+ default:
+ c->returnValue()->setString("unknown");
+ break;
+ }
+ return true;
+}
+
+
+/*
+ @doc: mediaplayer
+ @type:
+ module
+ @short:
+ Interface to various media players
+ @title:
+ The mediaplayer interface module
+ @body:
+ The mediaplayer module is an interface to various popular media players.
+ It allows controlling them remotely to a certain degree and retrieving
+ the informations about the currently played media (in order to implement the nice /playing
+ scripts). The module has replaced the old mediaplayer module which after
+ years of development had developed some design flaws and needed a complete rewrite.
+ At the moment of writing the supported players are: xmms (unix), audacious (unix), winamp (windows),
+ amarok (kde) and juk (kde). You choose the player interface by either setting
+ the option in the settings dialog, by manually setting [cmd]option[/cmd] stringPreferredMediaPlayer
+ or by running [cmd]mediaplayer.detect[/cmd] that will guess the media player interface for you.[br]
+ If you're going to use the Winamp media player then you must install the "gen_kvirc.dll" plugin
+ (included in the kvirc distribution) as a "general" winamp plugin.
+ This is achieved by simpy copying the file gen_kvirc.dll
+ to the winamp plugins directory and restarting winamp.[br]
+ [br]
+ The commands and functions exported by this module serve mainly for two
+ purposes: control the playback and get informations about the currently played media.
+ Playback control is achieved by the means of [cmd]mediaplayer.play[/cmd],
+ [cmd]mediaplayer.stop[/cmd], [cmd]mediaplayer.pause[/cmd], [cmd]mediaplayer.next[/cmd],
+ [cmd]mediaplayer.prev[/cmd] and [fnc]$mediaplayer.status()[/fnc]. The
+ informations about the currently played media can be retrieved with
+ [fnc]$mediaplayer.nowplaying()[/fnc] and [fnc]$mediaplayer.mrl()[/fnc].
+ Several other informative function are available as well but they are not
+ granted to work with all the supported media players or media types (e.g.
+ with winamp you can play video files that probably have no album, genre
+ or sampleRate information...).[br]
+ If you intend to write portable code, you should check the return value
+ of the functions like [fnc]$mediaplayer.artist()[/fnc], [fnc]$mediaplayer.title()[/fnc]
+ or [fnc]$mediaplayer.channels()[/fnc] and be ready to discard it when it
+ does not appear to be meaningful. The functions that are granted
+ to work are [fnc]$mediaplayer.nowplaying()[/fnc], [fnc]$mediaplayer.mrl()[/fnc]
+ and [fnc]$mediaplayer.localFile()[/fnc].
+*/
+
+/*
+ @doc: mediaplayer.setRepeat
+ @type:
+ command
+ @title:
+ $mediaplayer.setRepeat
+ @short:
+ Set the repeat flag.
+ @syntax:
+ mediaplayer.getRepeat [-q] <repeat:bool>
+ @description:
+ Set the Repeat flag to "repeat" (1 for ON, 0 for OFF.[br]
+ Take a look at the [module:mediaplayer]mediaplayer module documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module],
+ [fnc]$mediaplayer.getRepeat[/fnc], [cmd]mediaplayer.setShuffle[/cmd],
+ [fnc]$mediaplayer.getShuffle[/fnc]
+*/
+
+MP_KVS_COMMAND(setRepeat)
+{
+ bool bVal;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("repeat",KVS_PT_BOOL,0,bVal)
+ KVSM_PARAMETERS_END(c)
+
+ MP_KVS_FAIL_ON_NO_INTERFACE
+ if(!g_pMPInterface->setRepeat(bVal))
+ {
+ if(!c->hasSwitch('q',"quiet"))
+ {
+ c->warning(__tr2qs_ctx("The selected media player interface failed to execute the requested function","mediaplayer"));
+ QString tmp = __tr2qs_ctx("Last interface error: ","mediaplayer");
+ tmp += g_pMPInterface->lastError();
+ c->warning(tmp);
+ }
+ }
+ return true;
+}
+
+
+/*
+ @doc: mediaplayer.setShuffle
+ @type:
+ command
+ @title:
+ $mediaplayer.setShuffle
+ @short:
+ Set the repeat flag.
+ @syntax:
+ mediaplayer.getShuffle [-q] <shuffle:bool>
+ @description:
+ Set the Shuffle flag to "shuffle" (1 for ON, 0 for OFF.[br]
+ Take a look at the [module:mediaplayer]mediaplayer module documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:mediaplayer]media player module documentation[/module],
+ [fnc]$mediaplayer.getShuffle[/fnc], [cmd]mediaplayer.setRepeat[/cmd],
+ [fnc]$mediaplayer.getRepeat[/fnc]
+*/
+
+MP_KVS_COMMAND(setShuffle)
+{
+ bool bVal;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("shuffle",KVS_PT_BOOL,0,bVal)
+ KVSM_PARAMETERS_END(c)
+
+ MP_KVS_FAIL_ON_NO_INTERFACE
+ if(!g_pMPInterface->setShuffle(bVal))
+ {
+ if(!c->hasSwitch('q',"quiet"))
+ {
+ c->warning(__tr2qs_ctx("The selected media player interface failed to execute the requested function","mediaplayer"));
+ QString tmp = __tr2qs_ctx("Last interface error: ","mediaplayer");
+ tmp += g_pMPInterface->lastError();
+ c->warning(tmp);
+ }
+ }
+ return true;
+}
+
+static bool mediaplayer_module_init( KviModule * m )
+{
+ g_pDescriptorList = new KviPointerList<KviMediaPlayerInterfaceDescriptor>;
+ g_pDescriptorList->setAutoDelete(true);
+
+#ifndef COMPILE_ON_WINDOWS
+ g_pDescriptorList->append(MP_CREATE_DESCRIPTOR(KviXmmsInterface));
+ g_pDescriptorList->append(MP_CREATE_DESCRIPTOR(KviAudaciousInterface));
+#endif
+
+#ifdef COMPILE_ON_WINDOWS
+ g_pDescriptorList->append(MP_CREATE_DESCRIPTOR(KviAmipInterface));
+ g_pDescriptorList->append(MP_CREATE_DESCRIPTOR(KviWinampInterface));
+#endif
+
+#ifdef COMPILE_KDE_SUPPORT
+ g_pDescriptorList->append(MP_CREATE_DESCRIPTOR(KviAmarokInterface));
+ g_pDescriptorList->append(MP_CREATE_DESCRIPTOR(KviJukInterface));
+#endif
+
+ g_pMPInterface = 0;
+
+ if(KVI_OPTION_STRING(KviOption_stringPreferredMediaPlayer) == "auto")
+ {
+ g_pMPInterface = auto_detect_player();
+ } else {
+ for(KviMediaPlayerInterfaceDescriptor * d = g_pDescriptorList->first();d;d = g_pDescriptorList->next())
+ {
+ if(d->name() == KVI_OPTION_STRING(KviOption_stringPreferredMediaPlayer))
+ {
+ g_pMPInterface = d->instance();
+ }
+ }
+ }
+
+ // check for "auto" interface too!
+
+
+ #define MP_KVS_REGCMD(__name,__stringname) KVSM_REGISTER_SIMPLE_COMMAND(m,__stringname,mediaplayer_kvs_cmd_ ## __name)
+ #define MP_KVS_REGFNC(__name,__stringname) KVSM_REGISTER_FUNCTION(m,__stringname,mediaplayer_kvs_fnc_ ## __name)
+
+ MP_KVS_REGCMD(play,"play");
+ MP_KVS_REGCMD(stop,"stop");
+ MP_KVS_REGCMD(next,"next");
+ MP_KVS_REGCMD(prev,"prev");
+ MP_KVS_REGCMD(quit,"quit");
+ MP_KVS_REGCMD(pause,"pause");
+ MP_KVS_REGCMD(detect,"detect");
+ MP_KVS_REGCMD(playMrl,"playMrl");
+ MP_KVS_REGCMD(amipExec,"amipExec");
+ MP_KVS_REGCMD(hide,"hide");
+ MP_KVS_REGCMD(show,"show");
+ MP_KVS_REGCMD(minimize,"minimize");
+ MP_KVS_REGCMD(jumpTo,"jumpTo");
+ MP_KVS_REGCMD(setPlayer,"setPlayer");
+ MP_KVS_REGCMD(setVol,"setVol");
+ MP_KVS_REGCMD(mute,"mute");
+ MP_KVS_REGCMD(setRepeat,"setRepeat");
+ MP_KVS_REGCMD(setShuffle,"setShuffle");
+ MP_KVS_REGCMD(setPlayListPos,"setPlayListPos");
+ MP_KVS_REGCMD(setEqData,"setEqData");
+
+ MP_KVS_REGFNC(nowPlaying,"nowPlaying");
+ MP_KVS_REGFNC(mrl,"mrl");
+ MP_KVS_REGFNC(title,"title");
+ MP_KVS_REGFNC(artist,"artist");
+ MP_KVS_REGFNC(genre,"genre");
+ MP_KVS_REGFNC(year,"year");
+ MP_KVS_REGFNC(comment,"comment");
+ MP_KVS_REGFNC(album,"album");
+ MP_KVS_REGFNC(mediaType,"mediaType");
+ MP_KVS_REGFNC(bitRate,"bitRate");
+ MP_KVS_REGFNC(sampleRate,"sampleRate");
+ MP_KVS_REGFNC(length,"length");
+ MP_KVS_REGFNC(position,"position");
+ MP_KVS_REGFNC(status,"status");
+ MP_KVS_REGFNC(player,"player");
+ MP_KVS_REGFNC(playerList,"playerList");
+ MP_KVS_REGFNC(localFile,"localFile");
+ MP_KVS_REGFNC(amipEval,"amipEval");
+ MP_KVS_REGFNC(channels,"channels");
+ MP_KVS_REGFNC(getListLength,"getListLength");
+ MP_KVS_REGFNC(getPlayListPos,"getPlayListPos");
+ MP_KVS_REGFNC(getEqData,"getEqData");
+ MP_KVS_REGFNC(getRepeat,"getRepeat");
+ MP_KVS_REGFNC(getShuffle,"getShuffle");
+ MP_KVS_REGFNC(getVol,"getVol");
+/*
+ // Crissi
+ m->registerFunction( "getmp3tag_date", mediaplayer_fnc_getmp3tag_date );
+ m->registerFunction( "getmp3tag_version", mediaplayer_fnc_getmp3tag_version );
+ m->registerFunction( "getmp3tag_layer", mediaplayer_fnc_getmp3tag_layer );
+ m->registerFunction( "getmp3tag_crc", mediaplayer_fnc_getmp3tag_crc );
+ m->registerFunction( "getmp3tag_copyright", mediaplayer_fnc_getmp3tag_copyright );
+ m->registerFunction( "getmp3tag_original", mediaplayer_fnc_getmp3tag_original );
+ m->registerFunction( "getmp3tag_emphasis", mediaplayer_fnc_getmp3tag_emphasis );
+ m->registerFunction( "getmp3tag_tracknumber", mediaplayer_fnc_getmp3tag_tracknumber );
+*/
+ return true;
+}
+
+static bool mediaplayer_module_cleanup( KviModule * m )
+{
+ delete g_pDescriptorList;
+ return true;
+}
+
+static bool mediaplayer_module_can_unload( KviModule * m )
+{
+ return true;
+}
+
+static bool mediaplayer_module_ctrl(KviModule * m,const char * operation,void * param)
+{
+ if(kvi_strEqualCI(operation,"getAvailableMediaPlayers"))
+ {
+ // we expect param to be a pointer to QStringList
+ QStringList * l = (QStringList *)param;
+ for(KviMediaPlayerInterfaceDescriptor * d = g_pDescriptorList->first();d;d = g_pDescriptorList->next())
+ {
+ l->append(d->name());
+ }
+ return true;
+ }
+ if(kvi_strEqualCI(operation,"detectMediaPlayer"))
+ {
+ auto_detect_player(0);
+ return true;
+ }
+ return false;
+}
+
+
+
+KVIRC_MODULE(
+ "mediaplayer",
+ "1.1.0",
+ "Copyright (C) 2001-2007 Szymon Stefanek (pragma at kvirc dot net), " \
+ "Christoph Thielecke (crissi99 at gmx dot de)," \
+ "Tonino Imbesi (grifisx at barmes dot org)," \
+ "Alessandro Carbone (noldor at barmes dot org)," \
+ "Alexey Uzhva (wizard at opendoor dot ru), " \
+ "Serge Baranov (sbaranov at gmail dot com)",
+ "Interface to various media players",
+ mediaplayer_module_init,
+ mediaplayer_module_can_unload,
+ mediaplayer_module_ctrl,
+ mediaplayer_module_cleanup
+)
diff --git a/src/modules/mediaplayer/mp_amarokinterface.cpp b/src/modules/mediaplayer/mp_amarokinterface.cpp
new file mode 100644
index 00000000..5c941d4f
--- /dev/null
+++ b/src/modules/mediaplayer/mp_amarokinterface.cpp
@@ -0,0 +1,189 @@
+//=============================================================================
+//
+// File : mp_amarokinterface.cpp
+// Created on Sun 27 Mar 2005 16:55:09 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "mp_amarokinterface.h"
+
+#ifdef COMPILE_KDE_SUPPORT
+
+#include "kvi_app.h"
+
+#include "dcopclient.h"
+#include "kurl.h"
+
+#include <qdatastream.h>
+#include <qvaluelist.h>
+
+#include "kvi_locale.h"
+
+MP_IMPLEMENT_DESCRIPTOR(
+ KviAmarokInterface,
+ "amarok",
+ __tr2qs_ctx(
+ "An interface to the AmaroK KDE media player."
+ ,
+ "mediaplayer"
+ )
+)
+
+
+KviAmarokInterface::KviAmarokInterface()
+ : KviDCOPHelper(true, "amarok")
+{
+}
+
+KviAmarokInterface::~KviAmarokInterface()
+{
+}
+
+int KviAmarokInterface::detect(bool bStart){ return detectApp("amarok",bStart,95,99); }
+
+bool KviAmarokInterface::prev(){ return voidRetVoidDCOPCall("player","prev()"); }
+bool KviAmarokInterface::next(){ return voidRetVoidDCOPCall("player","next()"); }
+bool KviAmarokInterface::play(){ return voidRetVoidDCOPCall("player","play()"); }
+bool KviAmarokInterface::stop(){ return voidRetVoidDCOPCall("player","stop()"); }
+bool KviAmarokInterface::pause(){ return voidRetVoidDCOPCall("player","pause()"); }
+bool KviAmarokInterface::mute(){ return voidRetVoidDCOPCall("player","mute()"); }
+bool KviAmarokInterface::quit(){ return voidRetVoidDCOPCall("MainApplication-Interface","quit()"); }
+
+bool KviAmarokInterface::jumpTo(kvs_int_t &iPos)
+{
+ return voidRetIntDCOPCall("player","seek(int)",iPos/1000);
+}
+bool KviAmarokInterface::setVol(kvs_int_t &iVol)
+{
+ return voidRetIntDCOPCall("player","setVolume(int)",100*iVol/255);
+}
+
+#define MP_DCOP_STRING_CALL(_fncname,_iface,_fnc) \
+QString KviAmarokInterface::_fncname() \
+{ \
+ QString ret; \
+ if(!stringRetVoidDCOPCall(_iface,_fnc,ret))return false; \
+ return ret; \
+}
+
+MP_DCOP_STRING_CALL(nowPlaying,"player","nowPlaying()")
+MP_DCOP_STRING_CALL(artist,"player","artist()")
+MP_DCOP_STRING_CALL(title,"player","title()")
+MP_DCOP_STRING_CALL(genre,"player","genre()")
+MP_DCOP_STRING_CALL(year,"player","year()")
+MP_DCOP_STRING_CALL(comment,"player","comment()")
+MP_DCOP_STRING_CALL(album,"player","album()")
+
+int KviAmarokInterface::getVol()
+{
+ int ret;
+ if(!intRetVoidDCOPCall("player","getVolume()",ret))return false;
+ return ret * 255 / 100;
+}
+
+int KviAmarokInterface::sampleRate()
+{
+ int ret;
+ if(!intRetVoidDCOPCall("player","sampleRate()",ret))return false;
+ return ret;
+}
+
+int KviAmarokInterface::length()
+{
+ int ret;
+ if(!intRetVoidDCOPCall("player","trackTotalTime()",ret))return false;
+ return ret * 1000;
+}
+
+int KviAmarokInterface::position()
+{
+ int ret;
+ if(!intRetVoidDCOPCall("player","trackCurrentTime()",ret))return false;
+ return ret * 1000;
+}
+
+bool KviAmarokInterface::getRepeat()
+{
+ bool ret;
+ if(!boolRetVoidDCOPCall("player","repeatTrackStatus()",ret))return false;
+ return ret;
+}
+
+bool KviAmarokInterface::getShuffle()
+{
+ bool ret;
+ if(!boolRetVoidDCOPCall("player","randomModeStatus()",ret))return false;
+ return ret;
+}
+
+bool KviAmarokInterface::setRepeat(bool &bVal)
+{
+ return voidRetBoolDCOPCall("player","enableRepeatTrack(bool)",bVal);
+}
+
+bool KviAmarokInterface::setShuffle(bool &bVal)
+{
+ return voidRetBoolDCOPCall("player","enableRandomMode(bool)",bVal);
+}
+
+KviMediaPlayerInterface::PlayerStatus KviAmarokInterface::status()
+{
+ int ret;
+ if(!intRetVoidDCOPCall("player","status()",ret))return KviMediaPlayerInterface::Unknown;
+ switch(ret)
+ {
+ case 0:
+ return KviMediaPlayerInterface::Stopped;
+ break;
+ case 1:
+ return KviMediaPlayerInterface::Paused;
+ break;
+ case 2:
+ return KviMediaPlayerInterface::Playing;
+ break;
+ default:
+ return KviMediaPlayerInterface::Unknown;
+ break;
+ }
+ return KviMediaPlayerInterface::Unknown;
+}
+
+QString KviAmarokInterface::mrl()
+{
+ QString ret;
+ if(!stringRetVoidDCOPCall("player","encodedURL()",ret))return false;
+ KURL url(ret);
+ return url.prettyURL();
+}
+
+bool KviAmarokInterface::playMrl(const QString &mrl)
+{
+ QString title;
+ QByteArray data, replyData;
+ KviQCString replyType;
+ QDataStream arg(data,IO_WriteOnly);
+ arg << KURL(mrl);
+ if(!g_pApp->dcopClient()->call(m_szAppId,"playlist","playMedia(KURL)",data,replyType,replyData))
+ return false;
+ return true;
+}
+
+
+#endif //COMPILE_KDE_SUPPORT
diff --git a/src/modules/mediaplayer/mp_amarokinterface.h b/src/modules/mediaplayer/mp_amarokinterface.h
new file mode 100644
index 00000000..ac856219
--- /dev/null
+++ b/src/modules/mediaplayer/mp_amarokinterface.h
@@ -0,0 +1,76 @@
+#ifndef _MP_AMAROKINTERFACE_H_
+#define _MP_AMAROKINTERFACE_H_
+//=============================================================================
+//
+// File : mp_amarokinterface.h
+// Created on Sun 27 Mar 2005 16:55:09 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+
+#ifdef COMPILE_KDE_SUPPORT
+
+ #include "kvi_dcophelper.h"
+ #include "mp_interface.h"
+
+ class KviAmarokInterface : public KviMediaPlayerInterface, private KviDCOPHelper
+ {
+ public:
+ KviAmarokInterface();
+ ~KviAmarokInterface();
+ public:
+ virtual int detect(bool bStart);
+ virtual bool prev();
+ virtual bool next();
+ virtual bool play();
+ virtual bool stop();
+ virtual bool pause();
+ virtual bool jumpTo(kvs_int_t &iPos);
+ virtual bool setVol(kvs_int_t &iVol);
+ virtual bool mute();
+ virtual int getVol();
+ virtual bool quit();
+ virtual QString nowPlaying();
+ virtual QString mrl();
+ virtual QString title();
+ virtual QString artist();
+ virtual QString genre();
+ virtual QString comment();
+ virtual QString year();
+ virtual QString album();
+ virtual int position();
+ virtual int length();
+ //virtual int bitRate(); unsupported
+ virtual int sampleRate();
+ virtual bool playMrl(const QString &mrl);
+ virtual KviMediaPlayerInterface::PlayerStatus status();
+ virtual bool getRepeat();
+ virtual bool getShuffle();
+ virtual bool setRepeat(bool &bVal);
+ virtual bool setShuffle(bool &bVal);
+ };
+
+ MP_DECLARE_DESCRIPTOR(KviAmarokInterface)
+
+#endif //COMPILE_KDE_SUPPORT
+
+#endif //!_MP_AMAROKINTERFACE_H_
diff --git a/src/modules/mediaplayer/mp_amipinterface.cpp b/src/modules/mediaplayer/mp_amipinterface.cpp
new file mode 100644
index 00000000..3a7094bc
--- /dev/null
+++ b/src/modules/mediaplayer/mp_amipinterface.cpp
@@ -0,0 +1,400 @@
+#include "mp_amipinterface.h"
+#include "kvi_options.h"
+
+#ifdef COMPILE_ON_WINDOWS
+
+#include <qtextcodec.h>
+
+#include "kvi_locale.h"
+#include "kvi_module.h"
+
+#include <windows.h>
+
+enum ac_StartMode
+{
+ AC_START_ALL = 0,
+ AC_START_CLIENT,
+ AC_START_SERVER,
+ AC_START_NONE
+};
+
+enum ac_ErrorCode
+{
+ AC_ERR_NOERROR = 0,
+ AC_ERR_CLIENTISNULL,
+ AC_ERR_EXCEPTION,
+ AC_ERR_CONNECTIONFAILED,
+ AC_ERR_SERVERNOTRUNNING
+};
+
+#define AC_BUFFER_SIZE 2048
+
+static HINSTANCE amip_dll = NULL;
+
+#define MP_AC_DYNPTR(__rettype,__func,__args) \
+ typedef __rettype (CALLBACK* lp_##__func)(__args); \
+ lp_##__func __func
+
+#define MP_AC_FUNC(__func) \
+ __func = (lp_##__func)GetProcAddress(amip_dll,#__func); \
+ if(!__func) { \
+ FreeLibrary(amip_dll); \
+ return false; \
+ }
+
+#define COMMA() ,
+
+MP_AC_DYNPTR(void, ac_init, int mode);
+MP_AC_DYNPTR(void, ac_uninit, void);
+MP_AC_DYNPTR(void, ac_getDestHost, char *out);
+MP_AC_DYNPTR(int, ac_getDestPort, void);
+MP_AC_DYNPTR(bool, ac_pingServer, const char *host COMMA() int port COMMA() int timeout);
+MP_AC_DYNPTR(int, ac_exec, const char *cmd);
+MP_AC_DYNPTR(int, ac_eval, const char *cmd COMMA() char *result);
+
+
+static bool loadAmipDll()
+{
+ amip_dll = LoadLibrary("ac.dll");
+ if (!amip_dll) return false;
+
+ MP_AC_FUNC(ac_init);
+ MP_AC_FUNC(ac_uninit);
+ MP_AC_FUNC(ac_getDestHost);
+ MP_AC_FUNC(ac_getDestPort);
+ MP_AC_FUNC(ac_pingServer);
+ MP_AC_FUNC(ac_eval);
+ MP_AC_FUNC(ac_exec);
+
+ return true;
+};
+
+static QTextCodec * mediaplayer_get_codec()
+{
+ QTextCodec * c= QTextCodec::codecForName(KVI_OPTION_STRING(KviOption_stringWinampTextEncoding));
+ if(!c)c = QTextCodec::codecForLocale();
+ return c;
+}
+
+MP_IMPLEMENT_DESCRIPTOR(
+ KviAmipInterface,
+ "amip",
+ __tr2qs_ctx(
+ "An interface to the AMIP plug-in.\n" \
+ "You can download it from http://amip.tools-for.net.\n" \
+ "To use this interface you must " \
+ "install AMIP plug-in for your player."
+ ,
+ "mediaplayer"
+ )
+)
+
+
+
+KviAmipInterface::KviAmipInterface()
+: KviMediaPlayerInterface()
+{
+ if(!amip_dll) {
+ bool res = loadAmipDll();
+ if(!res) {
+ amip_dll = NULL;
+ return;
+ }
+ ac_init(AC_START_CLIENT);
+ }
+}
+
+KviAmipInterface::~KviAmipInterface()
+{
+ if(!amip_dll) return;
+ ac_uninit();
+ FreeLibrary(amip_dll);
+ amip_dll = NULL;
+}
+
+
+int KviAmipInterface::detect(bool bStart)
+{
+ if(!amip_dll) return 0;
+ char host[AC_BUFFER_SIZE];
+ ac_getDestHost(host);
+ if(ac_pingServer(host, ac_getDestPort(), 5000)) return 99;
+ return 1;
+}
+
+#define MP_AMIP_COMMAND(__cmdname,__acmd) \
+ bool KviAmipInterface::__cmdname() \
+ { \
+ return (ac_exec(__acmd) == AC_ERR_NOERROR); \
+ }
+
+MP_AMIP_COMMAND(play,"control play")
+MP_AMIP_COMMAND(stop,"control stop")
+MP_AMIP_COMMAND(next,"control >")
+MP_AMIP_COMMAND(prev,"control <")
+MP_AMIP_COMMAND(pause,"control pause")
+MP_AMIP_COMMAND(quit,"control exit")
+
+// helper function for evaluating variables returning integers
+int eval_int(const char *var)
+{
+ if(!amip_dll) return -1;
+ char buff[AC_BUFFER_SIZE];
+ int res = -1;
+ if (AC_ERR_NOERROR == ac_eval(var, buff)) {
+ res = atoi(buff);
+ }
+ return res;
+}
+
+QString eval_str(const char *var)
+{
+ QString res;
+ if(!amip_dll) return res;
+ char buff[AC_BUFFER_SIZE];
+ if (AC_ERR_NOERROR == ac_eval(var, buff)) {
+ res.append(buff);
+ }
+ return res;
+}
+
+int KviAmipInterface::length()
+{
+ return eval_int("var_sl") * 1000;
+}
+
+int KviAmipInterface::position()
+{
+ return eval_int("var_psec") * 1000;
+}
+
+int KviAmipInterface::bitRate()
+{
+ return eval_int("var_br");
+}
+
+int KviAmipInterface::sampleRate()
+{
+ return eval_int("var_sr");
+}
+
+int KviAmipInterface::channels()
+{
+ int ret = -1;
+ if(eval_str("var_typ").startsWith("Stereo")) {
+ ret = 2;
+ } else if(eval_str("var_typ").startsWith("Mono")) {
+ ret = 1;
+ }
+ return ret;
+}
+
+KviMediaPlayerInterface::PlayerStatus KviAmipInterface::status()
+{
+ int ret = eval_int("var_stat");
+ switch(ret)
+ {
+ case 0:
+ return KviMediaPlayerInterface::Stopped;
+ break;
+ case 3:
+ return KviMediaPlayerInterface::Paused;
+ break;
+ case 1:
+ return KviMediaPlayerInterface::Playing;
+ break;
+ default:
+ return KviMediaPlayerInterface::Unknown;
+ break;
+ }
+ return KviMediaPlayerInterface::Unknown;
+}
+
+QString KviAmipInterface::mrl()
+{
+ QString ret;
+ QString fn = eval_str("var_fn");
+ QTextCodec *c=mediaplayer_get_codec();
+ if (c) ret = c->toUnicode(fn);
+ else ret=fn;
+ if(!ret.startsWith("http://",false))
+ ret.prepend("file://");
+
+ return ret;
+}
+
+QString getAmipString(const char * var) {
+ QString ret;
+ QString s = eval_str(var);
+ QTextCodec *c=mediaplayer_get_codec();
+ if (c) ret = c->toUnicode(s);
+ else ret=s;
+ return ret;
+}
+
+QString KviAmipInterface::nowPlaying()
+{
+ return getAmipString("var_s");
+}
+
+QString KviAmipInterface::artist()
+{
+ return getAmipString("var_1");
+}
+
+QString KviAmipInterface::title()
+{
+ return getAmipString("var_2");
+}
+
+QString KviAmipInterface::album()
+{
+ return getAmipString("var_4");
+}
+
+QString KviAmipInterface::year()
+{
+ return getAmipString("var_5");
+}
+
+QString KviAmipInterface::comment()
+{
+ return getAmipString("var_6");
+}
+
+QString KviAmipInterface::genre()
+{
+ return getAmipString("var_7");
+}
+
+bool KviAmipInterface::setVol(kvs_int_t &iVol)
+{
+ if(!amip_dll) return false;
+ char volcmd[AC_BUFFER_SIZE];
+ sprintf(volcmd, "control vol %d", iVol);
+ return (ac_exec(volcmd) == AC_ERR_NOERROR);
+}
+
+int KviAmipInterface::getVol()
+{
+ return eval_int("var_vol");
+}
+
+bool KviAmipInterface::jumpTo(kvs_int_t &iPos)
+{
+ if(!amip_dll) return false;
+ char jmpcmd[AC_BUFFER_SIZE];
+ sprintf(jmpcmd, "jumptotime %d", iPos/1000);
+ return (ac_exec(jmpcmd) == AC_ERR_NOERROR);
+}
+bool KviAmipInterface::hide()
+{
+ HWND hWinamp = (HWND)eval_int("var_phwnd");
+ if(hWinamp && hWinamp != (HWND)-1)
+ {
+ ShowWindow(hWinamp, SW_HIDE);
+ return true;
+ }
+ return false;
+}
+
+bool KviAmipInterface::show()
+{
+ HWND hWinamp = (HWND)eval_int("var_phwnd");
+ if(hWinamp && hWinamp != (HWND)-1)
+ {
+ ShowWindow(hWinamp, SW_SHOW);
+ return true;
+ }
+ return false;
+}
+
+bool KviAmipInterface::minimize()
+{
+ if(!amip_dll) return false;
+ return (ac_exec("control mimimize") == AC_ERR_NOERROR);
+}
+
+bool KviAmipInterface::setPlayListPos(kvs_int_t &iPos)
+{
+ if(!amip_dll) return false;
+ char jmpcmd[AC_BUFFER_SIZE];
+ sprintf(jmpcmd, "setplpos %d", iPos + 1);
+ return (ac_exec(jmpcmd) == AC_ERR_NOERROR);
+}
+
+int KviAmipInterface::getPlayListPos()
+{
+ return eval_int("var_pos");
+}
+
+int KviAmipInterface::getListLength()
+{
+ return eval_int("var_ll");
+}
+
+bool KviAmipInterface::getRepeat()
+{
+ return eval_str("var_repeat").startsWith("on");
+}
+
+bool KviAmipInterface::getShuffle()
+{
+ return eval_str("var_shuffle").startsWith("on");
+}
+
+bool KviAmipInterface::setShuffle(bool &bVal)
+{
+ if(!amip_dll) return false;
+ bool res;
+ if (bVal)
+ {
+ res = (ac_exec("setshuffle on") == AC_ERR_NOERROR);
+ }
+ else
+ {
+ res = (ac_exec("setshuffle off") == AC_ERR_NOERROR);
+ }
+ return res;
+}
+
+bool KviAmipInterface::setRepeat(bool &bVal)
+{
+ if(!amip_dll) return false;
+ bool res;
+ if (bVal)
+ {
+ res = (ac_exec("setrepeat on") == AC_ERR_NOERROR);
+ }
+ else
+ {
+ res = (ac_exec("setrepeat off") == AC_ERR_NOERROR);
+ }
+ return res;
+}
+
+bool KviAmipInterface::amipExec(const QString &cmd)
+{
+ if(!amip_dll) return false;
+ QTextCodec *c=mediaplayer_get_codec();
+ KviStr szCmd = c ? c->fromUnicode(cmd) : cmd.utf8();
+ return (ac_exec(szCmd) == AC_ERR_NOERROR);
+}
+
+QString KviAmipInterface::amipEval(const QString &cmd)
+{
+ QString ret;
+ if(!amip_dll) return ret;
+ QTextCodec *c=mediaplayer_get_codec();
+ KviStr szCmd = c ? c->fromUnicode(cmd) : cmd.utf8();
+ char buff[AC_BUFFER_SIZE];
+ if((ac_eval(szCmd, buff) == AC_ERR_NOERROR)) {
+ QString s = buff;
+ QTextCodec *c=mediaplayer_get_codec();
+ if (c) ret = c->toUnicode(s);
+ else ret=s;
+ }
+ return ret;
+}
+
+#endif //COMPILE_ON_WINDOWS
diff --git a/src/modules/mediaplayer/mp_amipinterface.h b/src/modules/mediaplayer/mp_amipinterface.h
new file mode 100644
index 00000000..22bbf9d5
--- /dev/null
+++ b/src/modules/mediaplayer/mp_amipinterface.h
@@ -0,0 +1,58 @@
+#ifndef _MP_AMIPINTERFACE_H_
+#define _MP_AMIPINTERFACE_H_
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_ON_WINDOWS
+
+ #include "mp_interface.h"
+
+ class KviAmipInterface : public KviMediaPlayerInterface
+ {
+ public:
+ KviAmipInterface();
+ ~KviAmipInterface();
+ public:
+ virtual int detect(bool bStart);
+ virtual bool prev();
+ virtual bool next();
+ virtual bool play();
+ virtual bool stop();
+ virtual bool pause();
+ virtual bool quit();
+ virtual QString nowPlaying();
+ virtual QString artist();
+ virtual QString title();
+ virtual QString genre();
+ virtual QString comment();
+ virtual QString album();
+ virtual QString year();
+ virtual QString mrl();
+ virtual int position();
+ virtual int length();
+ virtual bool setVol(kvs_int_t &iVol);
+ virtual int getVol();
+ virtual bool jumpTo(kvs_int_t &iPos);
+ virtual int sampleRate();
+ virtual int bitRate();
+ virtual int channels();
+ virtual bool hide();
+ virtual bool show();
+ virtual bool minimize();
+ virtual int getPlayListPos();
+ virtual bool setPlayListPos(kvs_int_t &iPos);
+ virtual int getListLength();
+ virtual bool getRepeat();
+ virtual bool getShuffle();
+ virtual bool setRepeat(bool &bVal);
+ virtual bool setShuffle(bool &bVal);
+ virtual bool amipExec(const QString &cmd);
+ virtual QString amipEval(const QString &cmd);
+ virtual KviMediaPlayerInterface::PlayerStatus status();
+ };
+
+ MP_DECLARE_DESCRIPTOR(KviAmipInterface)
+
+#endif //COMPILE_ON_WINDOWS
+
+#endif //!_MP_AMIPINTERFACE_H_
diff --git a/src/modules/mediaplayer/mp_dcopinterface.cpp b/src/modules/mediaplayer/mp_dcopinterface.cpp
new file mode 100644
index 00000000..7c86e420
--- /dev/null
+++ b/src/modules/mediaplayer/mp_dcopinterface.cpp
@@ -0,0 +1,224 @@
+//=============================================================================
+//
+// File : mp_dcopinterface.cpp
+// Created on Sun 27 Mar 2005 16:56:21 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "mp_dcopinterface.h"
+
+#ifdef COMPILE_KDE_SUPPORT
+
+#include "dcopclient.h"
+
+#include <qdatastream.h>
+#include <qvaluelist.h>
+
+#include "kvi_app.h"
+#include "kvi_thread.h"
+
+KviMediaPlayerDCOPInterface::KviMediaPlayerDCOPInterface(const KviQCString &szAppId)
+: KviMediaPlayerInterface()
+{
+ m_szAppId = szAppId;
+}
+
+KviMediaPlayerDCOPInterface::~KviMediaPlayerDCOPInterface()
+{
+}
+
+bool KviMediaPlayerDCOPInterface::ensureAppRunning(const QString &szApp)
+{
+ if(findRunningApp(m_szAppId))return true;
+ return startApp(m_szAppId,400);
+}
+
+
+bool KviMediaPlayerDCOPInterface::simpleDCOPCall(const KviQCString &szObj,const KviQCString &szFunc)
+{
+ if(!ensureAppRunning(m_szAppId))return false;
+ QByteArray data;
+ return g_pApp->dcopClient()->send(m_szAppId,szObj,szFunc,data);
+}
+
+bool KviMediaPlayerDCOPInterface::boolDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,bool bVal)
+{
+ if(!ensureAppRunning(m_szAppId))return false;
+ QByteArray data;
+ QDataStream arg(data, IO_WriteOnly);
+ arg << bVal;
+ return g_pApp->dcopClient()->send(m_szAppId,szObj,szFunc,data);
+}
+
+bool KviMediaPlayerDCOPInterface::intDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,int iVal)
+{
+ if(!ensureAppRunning(m_szAppId))return false;
+ QByteArray data;
+ QDataStream arg(data, IO_WriteOnly);
+ arg << iVal;
+ return g_pApp->dcopClient()->send(m_szAppId,szObj,szFunc,data);
+}
+
+bool KviMediaPlayerDCOPInterface::floatDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,float fVal)
+{
+ if(!ensureAppRunning(m_szAppId))return false;
+ QByteArray data;
+ QDataStream arg(data, IO_WriteOnly);
+ arg << fVal;
+ return g_pApp->dcopClient()->send(m_szAppId,szObj,szFunc,data);
+}
+
+bool KviMediaPlayerDCOPInterface::stringDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,QString szVal)
+{
+ if(!ensureAppRunning(m_szAppId))return false;
+ QByteArray data;
+ QDataStream arg(data, IO_WriteOnly);
+ arg << szVal;
+ return g_pApp->dcopClient()->send(m_szAppId,szObj,szFunc,data);
+}
+
+bool KviMediaPlayerDCOPInterface::stringRetDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,QString &ret)
+{
+ if(!ensureAppRunning(m_szAppId))return false;
+ QString title;
+ QByteArray data, replyData;
+ KviQCString replyType;
+ if(!g_pApp->dcopClient()->call(m_szAppId,szObj,szFunc,data,replyType,replyData))
+ return false;
+ QDataStream reply( replyData, IO_ReadOnly );
+ if(replyType == "QString")
+ {
+ reply >> ret;
+ return true;
+ }
+ return false;
+}
+
+bool KviMediaPlayerDCOPInterface::intRetDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,int &ret)
+{
+ if(!ensureAppRunning(m_szAppId))return false;
+ QString title;
+ QByteArray data, replyData;
+ KviQCString replyType;
+ if(!g_pApp->dcopClient()->call(m_szAppId,szObj,szFunc,data,replyType,replyData))
+ return false;
+ QDataStream reply( replyData, IO_ReadOnly );
+ if(replyType == "int")
+ {
+ reply >> ret;
+ return true;
+ }
+ return false;
+}
+
+bool KviMediaPlayerDCOPInterface::boolRetDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,bool &ret)
+{
+ if(!ensureAppRunning(m_szAppId))return false;
+ QString title;
+ QByteArray data, replyData;
+ KviQCString replyType;
+ if(!g_pApp->dcopClient()->call(m_szAppId,szObj,szFunc,data,replyType,replyData))
+ return false;
+ QDataStream reply( replyData, IO_ReadOnly );
+ if(replyType == "bool")
+ {
+ reply >> ret;
+ return true;
+ }
+ return false;
+}
+
+
+bool KviMediaPlayerDCOPInterface::findRunningApp(const QString &szApp)
+{
+ QValueList<KviQCString> allApps = g_pApp->dcopClient() ->registeredApplications();
+ QValueList<KviQCString>::iterator iterator;
+ KviQCString sz = szApp.local8Bit();
+ for(iterator = allApps.begin();iterator != allApps.end();iterator++)
+ {
+ if(*iterator == sz)return true;
+ }
+ return false;
+}
+
+int KviMediaPlayerDCOPInterface::detectApp(const QString &szApp,bool bStart,int iScoreWhenFound,int iScoreWhenStarted)
+{
+ // lookup the amarok interface
+ if(!g_pApp->dcopClient())return 0;
+ if(findRunningApp(szApp))return 95; // found a running amarok, no need to run further
+
+ // no amarok app found
+ if(bStart)
+ {
+ // try to start it
+ if(!startApp(szApp,5000))return 10; // very low possibility
+ return findRunningApp(szApp) ? 99 : 0; // try to find it again
+ }
+
+ return 30; // it still might be installed on the system but we're just unable to start it...
+}
+
+
+bool KviMediaPlayerDCOPInterface::startApp(const QString &szApp,int iWaitMSecs)
+{
+ // we could use KApplication::startServiceByDesktopName here
+ // but we want to be able to wait a defined amount of time
+ QStringList tmp;
+ QByteArray data, replyData;
+ KviQCString replyType;
+ QDataStream arg(data, IO_WriteOnly);
+ arg << szApp << tmp;
+ if(!g_pApp->dcopClient()->call(
+ "klauncher",
+ "klauncher",
+ "start_service_by_desktop_name(QString,QStringList)",
+ data,
+ replyType,
+ replyData))
+ {
+ return false;
+ } else {
+ QDataStream reply(replyData, IO_ReadOnly);
+ if(replyType != "serviceResult")return false;
+ int result;
+ KviQCString dcopName;
+ QString error;
+ reply >> result >> dcopName >> error;
+ if(result != 0)return false;
+ }
+ // ok , we seem to have started it.. but it might take some seconds
+ // for the app to get registered
+ // we wait up to five seconds
+ if(iWaitMSecs > 0)
+ {
+ int i = 0;
+ while(i < iWaitMSecs)
+ {
+ if(findRunningApp(szApp))return true;
+ KviThread::msleep(100);
+ i += 100;
+ }
+ return findRunningApp(szApp);
+ }
+ return true;
+}
+
+
+#endif //COMPILE_KDE_SUPPORT
diff --git a/src/modules/mediaplayer/mp_dcopinterface.h b/src/modules/mediaplayer/mp_dcopinterface.h
new file mode 100644
index 00000000..6ce8594d
--- /dev/null
+++ b/src/modules/mediaplayer/mp_dcopinterface.h
@@ -0,0 +1,57 @@
+#ifndef _MP_DCOPINTERFACE_H_
+#define _MP_DCOPINTERFACE_H_
+//=============================================================================
+//
+// File : mp_dcopinterface.h
+// Created on Sun 27 Mar 2005 16:56:21 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_KDE_SUPPORT
+
+#include "mp_interface.h"
+
+class KviMediaPlayerDCOPInterface : public KviMediaPlayerInterface
+{
+public:
+ KviMediaPlayerDCOPInterface(const KviQCString &szAppId);
+ ~KviMediaPlayerDCOPInterface();
+protected:
+ KviQCString m_szAppId;
+protected:
+ bool ensureAppRunning(const QString &szApp);
+ bool findRunningApp(const QString &szApp);
+ bool startApp(const QString &szApp,int iWaitMSecs = 0);
+ int detectApp(const QString &szApp,bool bStart,int iScoreWhenFound,int iScoreWhenStarted);
+ bool simpleDCOPCall(const KviQCString &szObj,const KviQCString &szFunc);
+ bool intDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,int iVal);
+ bool boolDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,bool bVal);
+ bool stringDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,QString szVal);
+ bool floatDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,float fVal);
+ bool stringRetDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,QString &ret);
+ bool intRetDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,int &ret);
+ bool boolRetDCOPCall(const KviQCString &szObj,const KviQCString &szFunc,bool &ret);
+};
+
+#endif //COMPILE_KDE_SUPPORT
+
+#endif //!_MP_DCOPINTERFACE_H_
diff --git a/src/modules/mediaplayer/mp_interface.cpp b/src/modules/mediaplayer/mp_interface.cpp
new file mode 100644
index 00000000..0894de05
--- /dev/null
+++ b/src/modules/mediaplayer/mp_interface.cpp
@@ -0,0 +1,277 @@
+//=============================================================================
+//
+// File : mp_interface.cpp
+// Creation date : Fri Mar 25 20:01:25 2005 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "mp_interface.h"
+#include "mp_mp3.h"
+#include "kvi_options.h"
+#include "kvi_locale.h"
+#include <qtextcodec.h>
+
+static QTextCodec * mediaplayer_get_codec()
+{
+ QTextCodec * c= QTextCodec::codecForName(KVI_OPTION_STRING(KviOption_stringWinampTextEncoding));
+ if(!c)c = QTextCodec::codecForLocale();
+ return c;
+
+}
+
+void KviMediaPlayerInterface::notImplemented()
+{
+ setLastError(__tr2qs_ctx("Function not implemented","mediaplayer"));
+}
+
+
+int KviMediaPlayerInterface::position()
+{
+ notImplemented();
+ return -1;
+}
+
+int KviMediaPlayerInterface::length()
+{
+ notImplemented();
+ return -1;
+}
+
+bool KviMediaPlayerInterface::quit()
+{
+ notImplemented();
+ return false;
+}
+
+bool KviMediaPlayerInterface::hide()
+{
+ notImplemented();
+ return false;
+}
+
+bool KviMediaPlayerInterface::show()
+{
+ notImplemented();
+ return false;
+}
+
+bool KviMediaPlayerInterface::minimize()
+{
+ notImplemented();
+ return false;
+}
+
+QString KviMediaPlayerInterface::getLocalFile()
+{
+ QString ret = mrl();
+ if(ret.isEmpty())return ret;
+ if(ret.startsWith("file://",false))
+ {
+ ret.remove(0,7);
+ return ret;
+ }
+ return QString::null;
+}
+
+QString KviMediaPlayerInterface::amipEval(const QString &cmd)
+{
+ return QString::null;
+}
+
+#define SCAN_MP3_FILE \
+ QString f = getLocalFile(); \
+ if(f.isEmpty())return QString::null; \
+ mp3info mp3; \
+ if(!scan_mp3_file(f,&mp3))return QString::null; \
+ QTextCodec *pCodec; \
+ pCodec=mediaplayer_get_codec();
+
+#define SCAN_MP3_FILE_RET_INT \
+ QString f = getLocalFile(); \
+ if(f.isEmpty())return -1; \
+ mp3info mp3; \
+ if(!scan_mp3_file(f,&mp3))return -1;
+
+
+QString KviMediaPlayerInterface::artist()
+{
+ SCAN_MP3_FILE
+ return pCodec->toUnicode(KviQCString(mp3.id3.artist));
+}
+
+QString KviMediaPlayerInterface::title()
+{
+ SCAN_MP3_FILE
+ return pCodec->toUnicode(KviQCString(mp3.id3.title));
+}
+
+
+QString KviMediaPlayerInterface::genre()
+{
+ SCAN_MP3_FILE
+ return pCodec->toUnicode(KviQCString(get_typegenre(mp3.id3.genre[0])));
+}
+
+QString KviMediaPlayerInterface::comment()
+{
+ SCAN_MP3_FILE
+ return pCodec->toUnicode(KviQCString(mp3.id3.comment));
+}
+
+QString KviMediaPlayerInterface::year()
+{
+ SCAN_MP3_FILE
+ return QString(mp3.id3.year);
+}
+
+QString KviMediaPlayerInterface::album()
+{
+ SCAN_MP3_FILE
+ return pCodec->toUnicode(KviQCString(mp3.id3.album));
+}
+
+bool KviMediaPlayerInterface::playMrl(const QString &mrl)
+{
+ notImplemented();
+ return false;
+}
+
+bool KviMediaPlayerInterface::amipExec(const QString &cmd)
+{
+ notImplemented();
+ return false;
+}
+
+bool KviMediaPlayerInterface::setVol(kvs_int_t &iVol)
+{
+ notImplemented();
+ return false;
+}
+
+int KviMediaPlayerInterface::getVol()
+{
+ notImplemented();
+ return -1;
+}
+
+bool KviMediaPlayerInterface::mute()
+{
+ notImplemented();
+ return false;
+}
+
+bool KviMediaPlayerInterface::jumpTo(int &iPos)
+{
+ notImplemented();
+ return false;
+}
+
+KviMediaPlayerInterface::PlayerStatus KviMediaPlayerInterface::status()
+{
+ notImplemented();
+ return KviMediaPlayerInterface::Unknown;
+}
+
+int KviMediaPlayerInterface::bitRate()
+{
+ SCAN_MP3_FILE_RET_INT
+ return header_bitrate(&(mp3.header));
+}
+
+int KviMediaPlayerInterface::sampleRate()
+{
+ SCAN_MP3_FILE_RET_INT
+ return header_frequency(&(mp3.header));
+}
+
+int KviMediaPlayerInterface::channels()
+{
+ SCAN_MP3_FILE_RET_INT
+ return header_channels(&(mp3.header));
+}
+
+int KviMediaPlayerInterface::getPlayListPos()
+{
+ notImplemented();
+ return -1;
+}
+
+bool KviMediaPlayerInterface::setPlayListPos(int &iPos)
+{
+ notImplemented();
+ return false;
+}
+
+int KviMediaPlayerInterface::getListLength()
+{
+ notImplemented();
+ return -1;
+}
+
+
+int KviMediaPlayerInterface::getEqData(int &ival)
+{
+ notImplemented();
+ return -1;
+}
+
+bool KviMediaPlayerInterface::setEqData(int &iPos, int &iVal)
+{
+ notImplemented();
+ return false;
+}
+
+bool KviMediaPlayerInterface::getRepeat()
+{
+ notImplemented();
+ return false;
+}
+
+bool KviMediaPlayerInterface::getShuffle()
+{
+ notImplemented();
+ return false;
+}
+
+bool KviMediaPlayerInterface::setRepeat(bool &bVal)
+{
+ notImplemented();
+ return false;
+}
+
+bool KviMediaPlayerInterface::setShuffle(bool &bVal)
+{
+ notImplemented();
+ return false;
+}
+
+QString KviMediaPlayerInterface::mediaType()
+{
+ QString ret = mrl();
+ if(ret.endsWith(".mp3",false))ret = "MPEG Layer 3";
+ else if(ret.endsWith(".ogg",false))ret = "OGG Vorbis";
+ else if(ret.endsWith(".avi",false))ret = "Audio Video Interleave";
+ else if(ret.endsWith(".mpeg",false))ret = "MPEG Video";
+ else if(ret.endsWith(".mpg",false))ret = "MPEG Video";
+ else if(ret.startsWith("http://",false))ret = "HTTP Audio Stream";
+ else ret = QString::null;
+ return ret;
+}
+
diff --git a/src/modules/mediaplayer/mp_interface.h b/src/modules/mediaplayer/mp_interface.h
new file mode 100644
index 00000000..44667309
--- /dev/null
+++ b/src/modules/mediaplayer/mp_interface.h
@@ -0,0 +1,238 @@
+#ifndef _MP_INTERFACE_H_
+#define _MP_INTERFACE_H_
+//=============================================================================
+//
+// File : mp_interface.h
+// Creation date : Fri Mar 25 20:01:25 2005 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_types.h"
+
+class KviMediaPlayerInterface
+{
+public:
+ // don't do any initialization in the constructor
+ // implement lazy initialization in each function instead
+ KviMediaPlayerInterface(){};
+ virtual ~KviMediaPlayerInterface(){};
+protected:
+ QString m_szLastError;
+public:
+ const QString & lastError(){ return m_szLastError; };
+
+ //
+ // mandatory interface
+ //
+
+ // This should attempt to detect if the player is available on the user's system
+ // and returning a score from 0 to 100 depending on how likely the player will work
+ // and how many of its functions are available. 100 means that the interface
+ // is absolutely sure that the player will start and play stuff.
+ // If bStart is true then the function is allowed to explicitly start the player,
+ // otherwise a startup attempt should not be made and different methods should be used.
+ // This function is used for auto-detection and is called twice: the first time
+ // with bStart set to false to determine the players that potentially could run.
+ // If no player returns a reasonably high value by just guessing, then
+ // a second loop may be attempted with the "bStart" parameter set to true.
+ // A level of 0 is considered total failure: in this case detect() should
+ // also set the last error to a descriptive string.
+ virtual int detect(bool bStart) = 0;
+
+ // play previous media, return false only on communication failure
+ virtual bool prev() = 0;
+ // play next media, return false only on communication failure
+ virtual bool next() = 0;
+ // start playback now, return false only on communication failure (i.e. return true when already playing)
+ virtual bool play() = 0;
+ // stop playback now, return false only on communication failure (i.e. return true when already stopped)
+ virtual bool stop() = 0;
+ // pause playback now (do NOT toggle pause, just pause), return false only on communication failure
+ virtual bool pause() = 0;
+
+ // current media related
+
+ // currently played media: it should include AT least the title
+ // but may also include other informations.
+ // this string MUST be non-empty when the player is playing something.
+ // If it is empty then either the player is not playing or there are
+ // communication errors.
+ virtual QString nowPlaying() = 0;
+ // currently played media resource locator
+ // file://<filepath> for local files, dvb:// for dvb media , dvd:// for dvd's
+ // http:// for audio streams etc...
+ // empty if player is not playing (or in the tragic case that the player
+ // can't determine the url).
+ virtual QString mrl() = 0;
+
+ // optional interface
+
+ // this should play the specified mrl
+ // the mrl may be (or may be not) added to the player's playlist
+ // the function should return false if the player doesn't support
+ // this function or there is a communication error
+ virtual bool playMrl(const QString &mrl);
+ // what is this ? :D
+ virtual bool amipExec(const QString &cmd);
+ virtual QString amipEval(const QString &cmd);
+ // this is functions to hide,show and minimize the player interface
+ virtual bool hide();
+ virtual bool show();
+ virtual bool minimize();
+ // set the volume of mediaplayer (0-255)
+ virtual bool setVol(kvs_int_t &iVol);
+ // get the pvolume value(0-255)
+ virtual int getVol();
+ //mute the volume
+ virtual bool mute();
+ // should quit the player if it's running
+ // return false only on communication failure
+ virtual bool quit();
+ // return the current player status
+ enum PlayerStatus { Unknown, Stopped, Playing, Paused };
+ virtual KviMediaPlayerInterface::PlayerStatus status();
+ // current position in the media (msecs)
+ // 0 if the player isn't playing anything and -1 if unknown
+ virtual int position();
+ // total length of the media (msecs)
+ // 0 if the player isn't playing anyting and -1 if unknown (e.g. a stream)
+ virtual int length();
+ // jump to position
+ virtual bool jumpTo(int &iPos);
+ // interface with a default implementation for certain types of media (read for mp3)
+ // reimplement only if the player knows better
+
+ // currently played media title (it's player choice if the title
+ // is to be derived from the media file name or from the informations
+ // stored inside the file like the ID3 tag...)
+ // If the player is not playing, the returned string should be empty
+ virtual QString title();
+ // currently played media artist's name
+ // If the player is not playing, the returned string should be empty
+ // If the player can't guess the artist it should return the string "unknown"
+ virtual QString artist();
+ // currently plaued media genre
+ // If the player is not playing, the returned string should be empty
+ // If the player can't guess the genre it should return the string "unknown"
+ virtual QString genre();
+ // currently played media comment.
+ // Empty string if the player isn't playing anything or there is no comment
+ virtual QString comment();
+ // currently played media year
+ // Empty string if the player isn't playing anything or the year is unknown
+ virtual QString year();
+ // currently played media album
+ // Empty string if the player isn't playing anything
+ // If the player can't guess the album/collection then this string should be "unknown"
+ virtual QString album();
+ // bit rate in bits/sec, 0 if unknown
+ virtual int bitRate();
+ // sample rate in samples/sec (Hz), 0 if unknown
+ virtual int sampleRate();
+ // number of channels
+ virtual int channels();
+ // frequency
+ // the type of the media (MPEG Layer 3, MPEG Layer 4, OGG Vorbis, AVI Stream etc..)
+ virtual QString mediaType();
+ // get the position in the playlist
+ virtual int getPlayListPos();
+ // set the position in the playlist
+ virtual bool setPlayListPos(int &iPos);
+ // return the list's length
+ virtual int getListLength();
+ // return the Eq(number) value
+ virtual int getEqData(int &i_val);
+ // set the Eq(iPos) to Eq(iVal) value
+ virtual bool setEqData(int &iPos, int &iVal);
+ // get the Repeat bool value
+ virtual bool getRepeat();
+ // get the shuffle bool value
+ virtual bool getShuffle();
+ // set the Repeat bool value
+ virtual bool setRepeat(bool &bVal);
+ // set the shuffle bool value
+ virtual bool setShuffle(bool &bVal);
+ void setLastError(const QString &szLastError){ m_szLastError = szLastError; };
+protected:
+ void notImplemented();
+ QString getLocalFile();
+};
+
+
+class KviMediaPlayerInterfaceDescriptor
+{
+public:
+ KviMediaPlayerInterfaceDescriptor(){};
+ virtual ~KviMediaPlayerInterfaceDescriptor(){};
+public:
+ virtual const QString & name() = 0;
+ virtual const QString & description() = 0;
+ virtual KviMediaPlayerInterface * instance() = 0;
+};
+
+
+#define MP_DECLARE_DESCRIPTOR(_interfaceclass) \
+ class _interfaceclass ## Descriptor : public KviMediaPlayerInterfaceDescriptor \
+ { \
+ public: \
+ _interfaceclass ## Descriptor(); \
+ virtual ~_interfaceclass ## Descriptor(); \
+ protected: \
+ _interfaceclass * m_pInstance; \
+ QString m_szName; \
+ QString m_szDescription; \
+ public: \
+ virtual const QString & name(); \
+ virtual const QString & description(); \
+ virtual KviMediaPlayerInterface * instance(); \
+ };
+
+#define MP_IMPLEMENT_DESCRIPTOR(_interfaceclass,_name,_description) \
+ _interfaceclass ## Descriptor::_interfaceclass ## Descriptor() \
+ : KviMediaPlayerInterfaceDescriptor() \
+ { \
+ m_pInstance = 0; \
+ m_szName = _name; \
+ m_szDescription = _description; \
+ } \
+ _interfaceclass ## Descriptor::~_interfaceclass ## Descriptor() \
+ { \
+ if(m_pInstance)delete m_pInstance; \
+ } \
+ const QString & _interfaceclass ## Descriptor::name() \
+ { \
+ return m_szName; \
+ } \
+ const QString & _interfaceclass ## Descriptor::description() \
+ { \
+ return m_szDescription; \
+ } \
+ KviMediaPlayerInterface * _interfaceclass ## Descriptor::instance() \
+ { \
+ if(!m_pInstance)m_pInstance = new _interfaceclass(); \
+ return m_pInstance; \
+ }
+
+#define MP_CREATE_DESCRIPTOR(_interfaceclass) \
+ new _interfaceclass ## Descriptor()
+
+#endif //!_MP_INTERFACE_H_
diff --git a/src/modules/mediaplayer/mp_jukinterface.cpp b/src/modules/mediaplayer/mp_jukinterface.cpp
new file mode 100644
index 00000000..d5a69a77
--- /dev/null
+++ b/src/modules/mediaplayer/mp_jukinterface.cpp
@@ -0,0 +1,185 @@
+//=============================================================================
+//
+// File : mp_jukinterface.cpp
+// Created on Tue 29 Mar 2005 01:38:34 by Szymon Stfeanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2005 Szymon Stfeanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "mp_jukinterface.h"
+
+#ifdef COMPILE_KDE_SUPPORT
+
+#include "kvi_app.h"
+
+#include "dcopclient.h"
+#include "kurl.h"
+
+#include <qdatastream.h>
+#include <qvaluelist.h>
+
+#include "kvi_locale.h"
+
+// the dcop interface of this player is incomplete :(
+
+MP_IMPLEMENT_DESCRIPTOR(
+ KviJukInterface,
+ "juk",
+ __tr2qs_ctx(
+ "An interface to the Juk KDE media player."
+ ,
+ "mediaplayer"
+ )
+)
+
+
+KviJukInterface::KviJukInterface()
+ : KviDCOPHelper(true, "amarok")
+{
+}
+
+KviJukInterface::~KviJukInterface()
+{
+}
+
+int KviJukInterface::detect(bool bStart){ return detectApp("juk",bStart,90,96); }
+
+bool KviJukInterface::prev(){ return voidRetVoidDCOPCall("Player","forward()"); }
+bool KviJukInterface::next(){ return voidRetVoidDCOPCall("Player","back()"); }
+bool KviJukInterface::play(){ return voidRetVoidDCOPCall("Player","play()"); }
+bool KviJukInterface::stop(){ return voidRetVoidDCOPCall("Player","stop()"); }
+bool KviJukInterface::pause(){ return voidRetVoidDCOPCall("Player","pause()"); }
+bool KviJukInterface::quit(){ return voidRetVoidDCOPCall("MainApplication-Interface","quit()"); }
+
+bool KviJukInterface::setVol(kvs_int_t &iVol)
+{
+ return voidRetFloatDCOPCall("player","setVolume(float)",(float)(iVol)/255.);
+}
+
+bool KviJukInterface::jumpTo(kvs_int_t &iPos)
+{
+ return voidRetIntDCOPCall("player","seek(int)",iPos/1000);
+}
+
+bool KviJukInterface::getShuffle()
+{
+ QString szMode;
+ if(!stringRetVoidDCOPCall("player","randomPlayMode()",szMode))return false;
+ return (szMode != "NoRandom");
+}
+
+bool KviJukInterface::setShuffle(bool &bVal)
+{
+ QString szMode;
+ if(bVal)
+ {
+ szMode = "Random";
+ } else {
+ szMode = "NoRandom";
+ }
+ if(!voidRetStringDCOPCall("player","setRandomPlayMode(QString)",szMode))return false;
+ return true;
+}
+
+
+#define MP_DCOP_STRING_CALL(_fncname,_iface,_fnc) \
+QString KviJukInterface::_fncname() \
+{ \
+ QString ret; \
+ if(!stringRetVoidDCOPCall(_iface,_fnc,ret))return false; \
+ return ret; \
+}
+
+MP_DCOP_STRING_CALL(nowPlaying,"Player","playingString()")
+
+/*
+ FIXME: there is trackProperty(propertyName) for these...
+MP_DCOP_STRING_CALL(artist,"player","artist()")
+MP_DCOP_STRING_CALL(title,"player","title()")
+MP_DCOP_STRING_CALL(genre,"player","genre()")
+MP_DCOP_STRING_CALL(year,"player","year()")
+MP_DCOP_STRING_CALL(comment,"player","comment()")
+MP_DCOP_STRING_CALL(album,"player","album()")
+
+
+int KviJukInterface::sampleRate()
+{
+ int ret;
+ if(!intRetVoidDCOPCall("player","sampleRate()",ret))return false;
+ return ret;
+}
+*/
+
+int KviJukInterface::length()
+{
+ int ret;
+ if(!intRetVoidDCOPCall("player","totalTime()",ret))return false;
+ return ret * 1000;
+}
+
+int KviJukInterface::position()
+{
+ int ret;
+ if(!intRetVoidDCOPCall("player","currentTime()",ret))return false;
+ return ret * 1000;
+}
+
+KviMediaPlayerInterface::PlayerStatus KviJukInterface::status()
+{
+ int ret;
+ if(!intRetVoidDCOPCall("player","status()",ret))return KviMediaPlayerInterface::Unknown;
+ switch(ret)
+ {
+ case 0:
+ return KviMediaPlayerInterface::Stopped;
+ break;
+ case 1:
+ return KviMediaPlayerInterface::Paused;
+ break;
+ case 2:
+ return KviMediaPlayerInterface::Playing;
+ break;
+ default:
+ return KviMediaPlayerInterface::Unknown;
+ break;
+ }
+ return KviMediaPlayerInterface::Unknown;
+}
+
+QString KviJukInterface::mrl()
+{
+ // ugh :/
+ QString ret;
+ return ret;
+}
+
+bool KviJukInterface::playMrl(const QString &mrl)
+{
+ QString title;
+ QByteArray data, replyData;
+ KviQCString replyType;
+ QDataStream arg(data,IO_WriteOnly);
+ arg << mrl;
+ if(!g_pApp->dcopClient()->call(m_szAppId,"playlist","play(QString)",data,replyType,replyData))
+ return false;
+ return true;
+}
+
+
+#endif //COMPILE_KDE_SUPPORT
diff --git a/src/modules/mediaplayer/mp_jukinterface.h b/src/modules/mediaplayer/mp_jukinterface.h
new file mode 100644
index 00000000..478a3c16
--- /dev/null
+++ b/src/modules/mediaplayer/mp_jukinterface.h
@@ -0,0 +1,77 @@
+#ifndef _MP_JUKINTERFACE_H_
+#define _MP_JUKINTERFACE_H_
+//=============================================================================
+//
+// File : mp_jukinterface.h
+// Created on Tue 29 Mar 2005 01:38:34 by Szymon Stfeanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2005 Szymon Stfeanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_KDE_SUPPORT
+
+ #include "kvi_dcophelper.h"
+ #include "mp_interface.h"
+
+ class KviJukInterface : public KviMediaPlayerInterface, private KviDCOPHelper
+ {
+ public:
+ KviJukInterface();
+ ~KviJukInterface();
+ public:
+ virtual int detect(bool bStart);
+ virtual bool prev();
+ virtual bool next();
+ virtual bool play();
+ virtual bool stop();
+ virtual bool pause();
+ virtual bool quit();
+ virtual bool jumpTo(kvs_int_t &iPos);
+ virtual bool setVol(kvs_int_t &iVol);
+ virtual QString nowPlaying();
+ virtual QString mrl();
+ /*
+ virtual QString title();
+ virtual QString artist();
+ virtual QString genre();
+ virtual QString comment();
+ virtual QString year();
+ virtual QString album();
+ */
+ virtual int position();
+ virtual int length();
+ /*
+ virtual int bitRate();
+ virtual int sampleRate();
+ */
+ virtual bool getShuffle();
+ virtual bool setShuffle(bool &bVal);
+
+ virtual bool playMrl(const QString &mrl);
+ virtual KviMediaPlayerInterface::PlayerStatus status();
+ };
+
+ MP_DECLARE_DESCRIPTOR(KviJukInterface)
+
+#endif //COMPILE_KDE_SUPPORT
+
+#endif //!_MP_JUKINTERFACE_H_
diff --git a/src/modules/mediaplayer/mp_mp3.cpp b/src/modules/mediaplayer/mp_mp3.cpp
new file mode 100644
index 00000000..6e27fa5f
--- /dev/null
+++ b/src/modules/mediaplayer/mp_mp3.cpp
@@ -0,0 +1,468 @@
+//=============================================================================
+//
+// File : mp_mp3.cpp
+// Creation date : Fri Mar 25 20:01:25 2005 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2005 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This file is based on the mp3tech.c. It is released under the original
+// license and the original copyright notice follows.
+//
+// mp3tech.c
+//
+// Copyright (C) 2000 Cedric Tefft <cedric@earthling.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.
+//
+// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// This file is based in part on:
+//
+// * MP3Info 0.5 by Ricardo Cerqueira <rmc@rccn.net>
+// * MP3Stat 0.9 by Ed Sweetman <safemode@voicenet.com> and
+// Johannes Overmann <overmann@iname.com>
+//
+// There has been also a remarkable work by Cristopher Tieckle (Crissi)
+//
+//=============================================================================
+
+#include "mp_mp3.h"
+#include "kvi_options.h"
+
+#include <qfileinfo.h>
+#include <qtextcodec.h>
+
+#define MAXGENRE 147
+#define GENREROWS 50
+
+/*
+ The Information is stored in the last 128 bytes of an MP3. The Tag
+ has got the following fields, and the offsets given here, are from
+ 0-127.
+
+ Field Length Offsets
+ Tag 3 0-2
+ Songname 30 3-32
+ Artist 30 33-62
+ Album 30 63-92
+ Year 4 93-96
+ Comment 30 97-126
+ Genre 1 127
+
+
+ The string-fields contain ASCII-data, coded in ISO-Latin 1 codepage.
+ Strings which are smaller than the field length are padded with zero-
+ bytes.
+
+ Tag: The tag is valid if this field contains the string "TAG". This
+ has to be uppercase!
+
+ Songname: This field contains the title of the MP3 (string as
+ above).
+
+ Artist: This field contains the artist of the MP3 (string as above).
+
+ Album: this field contains the album where the MP3 comes from
+ (string as above).
+
+ Year: this field contains the year when this song has originally
+ been released (string as above).
+
+ Comment: this field contains a comment for the MP3 (string as
+ above). Revision to this field has been made in ID3v1.1. See
+ A.4.
+
+ Genre: this byte contains the offset of a genre in a predefined
+ list the byte is treated as an unsigned byte. The offset is
+ starting from 0. See A.3.
+*/
+
+
+const char *typegenre [MAXGENRE+2] =
+{
+ "Blues","Classic Rock","Country","Dance","Disco","Funk","Grunge",
+ "Hip-Hop","Jazz","Metal","New Age","Oldies","Other","Pop","R&B",
+ "Rap","Reggae","Rock","Techno","Industrial","Alternative","Ska",
+ "Death Metal","Pranks","Soundtrack","Euro-Techno","Ambient",
+ "Trip-Hop","Vocal","Jazz+Funk","Fusion","Trance","Classical",
+ "Instrumental","Acid","House","Game","Sound Clip","Gospel","Noise",
+ "Alt. Rock","Bass","Soul","Punk","Space","Meditative",
+ "Instrumental Pop","Instrumental Rock","Ethnic","Gothic",
+ "Darkwave","Techno-Industrial","Electronic","Pop-Folk","Eurodance",
+ "Dream","Southern Rock","Comedy","Cult","Gangsta Rap","Top 40",
+ "Christian Rap","Pop/Funk","Jungle","Native American","Cabaret",
+ "New Wave","Psychedelic","Rave","Showtunes","Trailer","Lo-Fi",
+ "Tribal","Acid Punk","Acid Jazz","Polka","Retro","Musical",
+ "Rock & Roll","Hard Rock","Folk","Folk/Rock","National Folk",
+ "Swing","Fast-Fusion","Bebob","Latin","Revival","Celtic",
+ "Bluegrass","Avantgarde","Gothic Rock","Progressive Rock",
+ "Psychedelic Rock","Symphonic Rock","Slow Rock","Big Band",
+ "Chorus","Easy Listening","Acoustic","Humour","Speech","Chanson",
+ "Opera","Chamber Music","Sonata","Symphony","Booty Bass","Primus",
+ "Porn Groove","Satire","Slow Jam","Club","Tango","Samba",
+ "Folklore","Ballad","Power Ballad","Rhythmic Soul","Freestyle",
+ "Duet","Punk Rock","Drum Solo","A Cappella","Euro-House",
+ "Dance Hall","Goa","Drum & Bass","Club-House","Hardcore","Terror",
+ "Indie","BritPop","Negerpunk","Polsk Punk","Beat",
+ "Christian Gangsta Rap","Heavy Metal","Black Metal","Crossover",
+ "Contemporary Christian","Christian Rock","Merengue","Salsa",
+ "Thrash Metal","Anime","JPop","Synthpop",""
+};
+
+const char * get_typegenre(int idx)
+{
+ if(idx > MAXGENRE)return typegenre[12];
+ return typegenre[idx];
+}
+
+int galphagenreindex[MAXGENRE+2] =
+{
+ 148,123,74,73,34,99,40,20,26,145,90,
+ 116,41,135,85,96,138,89,0,107,132,65,88,
+ 104,102,97,136,61,141,1,32,128,112,57,140,
+ 2,139,58,125,3,50,22,4,55,127,122,120,
+ 98,52,48,124,25,54,84,81,115,80,119,5,
+ 30,36,59,126,38,91,49,6,79,129,137,7,
+ 35,100,131,19,46,47,33,146,29,8,63,86,
+ 71,45,142,9,77,82,64,133,10,66,39,11,
+ 103,12,75,134,53,62,13,109,117,23,108,92,
+ 93,67,121,43,14,15,68,16,76,87,118,78,
+ 17,143,114,110,69,21,111,95,105,42,37,24,
+ 56,44,101,83,94,106,147,113,51,18,130,144,
+ 60,70,31,72,27,28
+};
+
+int *alphagenreindex=&(galphagenreindex[1]);
+
+
+int layer_tab[4]= {0, 3, 2, 1};
+
+int frequencies[3][4] =
+{
+ {22050,24000,16000,50000}, /* MPEG 2.0 */
+ {44100,48000,32000,50000}, /* MPEG 1.0 */
+ {11025,12000,8000,50000} /* MPEG 2.5 */
+};
+
+int bitrate[2][3][14] =
+{
+ { /* MPEG 2.0 */
+ {32,48,56,64,80,96,112,128,144,160,176,192,224,256}, /* layer 1 */
+ {8,16,24,32,40,48,56,64,80,96,112,128,144,160}, /* layer 2 */
+ {8,16,24,32,40,48,56,64,80,96,112,128,144,160} /* layer 3 */
+ },
+ { /* MPEG 1.0 */
+ {32,64,96,128,160,192,224,256,288,320,352,384,416,448}, /* layer 1 */
+ {32,48,56,64,80,96,112,128,160,192,224,256,320,384}, /* layer 2 */
+ {32,40,48,56,64,80,96,112,128,160,192,224,256,320} /* layer 3 */
+ }
+};
+
+int frame_size_index[] = {24000, 72000, 72000};
+
+const char *mode_text[] =
+{
+ "Stereo", "Joint Stereo", "Dual Channel", "Mono"
+};
+
+const char *emphasis_text[] =
+{
+ "None", "50/15 Microseconds", "Reserved", "CCITT J 17"
+};
+void resetmp3infoStruct(mp3info *i)
+{
+ i->file=0;
+ i->datasize=0;
+ i->header_isvalid=0;
+ memset(&i->header,0,sizeof(i->header));
+ i->id3_isvalid=0;
+ memset(&i->id3,0,sizeof(i->id3));
+ i->vbr=0;
+ i->vbr_average=0;
+ i->seconds=0;
+ i->frames=0;
+ i->badframes=0;
+}
+
+int get_mp3_info(mp3info *mp3)
+{
+ int frame_type[15]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+ float seconds=0,total_rate=0;
+ int frames=0,frame_types=0,frames_so_far=0;
+ int l,vbr_median=-1;
+ int bitrate,lastrate;
+ int counter=0;
+// mp3header header;
+
+ int sample_pos,data_start=0;
+
+ QFile fi(mp3->filename);
+ mp3->datasize=fi.size();//filestat.st_size;
+
+ get_id3(mp3);
+
+ if(get_first_header(mp3,0L))
+ {
+ data_start=ftell(mp3->file);
+ lastrate=15-mp3->header.bitrate;
+ while((counter < NUM_SAMPLES) && lastrate)
+ {
+ sample_pos=(counter*(mp3->datasize/NUM_SAMPLES+1))+data_start;
+ if(get_first_header(mp3,sample_pos))
+ {
+ bitrate=15-mp3->header.bitrate;
+ } else {
+ bitrate=-1;
+ }
+
+ if(bitrate != lastrate)
+ {
+ mp3->vbr=1;
+ }
+ lastrate=bitrate;
+ counter++;
+
+ }
+ mp3->frames=(mp3->datasize-data_start)/(l=frame_length(&mp3->header));
+ mp3->seconds = (int)((float)(frame_length(&mp3->header)*mp3->frames)/
+ (float)(header_bitrate(&mp3->header)*125)+0.5);
+ mp3->vbr_average = (float)header_bitrate(&mp3->header);
+ }
+
+ return 0;
+}
+
+
+int get_first_header(mp3info *mp3, long startpos)
+{
+ int k, l=0,c;
+ mp3header h, h2;
+ long valid_start=0;
+
+ fseek(mp3->file,startpos,SEEK_SET);
+ while(1)
+ {
+ while((c=fgetc(mp3->file)) != 255 && (c != EOF));
+ if(c == 255)
+ {
+ ungetc(c,mp3->file);
+ valid_start=ftell(mp3->file);
+ if((l=get_header(mp3->file,&h)))
+ {
+ fseek(mp3->file,l-FRAME_HEADER_SIZE,SEEK_CUR);
+ for(k=1; (k < MIN_CONSEC_GOOD_FRAMES) && (mp3->datasize-ftell(mp3->file) >= FRAME_HEADER_SIZE); k++)
+ {
+ if(!(l=get_header(mp3->file,&h2))) break;
+ if(!sameConstant(&h,&h2)) break;
+ fseek(mp3->file,l-FRAME_HEADER_SIZE,SEEK_CUR);
+ }
+ if(k == MIN_CONSEC_GOOD_FRAMES)
+ {
+ fseek(mp3->file,valid_start,SEEK_SET);
+ memcpy(&(mp3->header), &h2, sizeof(mp3header));
+ mp3->header_isvalid = 1;
+ return 1;
+ }
+ }
+ } else {
+ return 0;
+ }
+ }
+ return 0;
+}
+
+
+// Get next MP3 frame header.
+// Return codes:
+// positive value = Frame Length of this header
+// 0 = No, we did not retrieve a valid frame header
+
+int get_header(FILE *file,mp3header *header)
+{
+ unsigned char buffer[FRAME_HEADER_SIZE];
+ int fl;
+
+ if(fread(&buffer,FRAME_HEADER_SIZE,1,file)<1)
+ {
+ header->sync=0;
+ return 0;
+ }
+ header->sync=(((int)buffer[0]<<4) | ((int)(buffer[1]&0xE0)>>4));
+ if(buffer[1] & 0x10) header->version=(buffer[1] >> 3) & 1;
+ else header->version=2;
+ header->layer=(buffer[1] >> 1) & 3;
+ if((header->sync != 0xFFE) || (header->layer != 1))
+ {
+ header->sync=0;
+ return 0;
+ }
+ header->crc=buffer[1] & 1;
+ header->bitrate=(buffer[2] >> 4) & 0x0F;
+ header->freq=(buffer[2] >> 2) & 0x3;
+ header->padding=(buffer[2] >>1) & 0x1;
+ header->extension=(buffer[2]) & 0x1;
+ header->mode=(buffer[3] >> 6) & 0x3;
+ header->mode_extension=(buffer[3] >> 4) & 0x3;
+ header->copyright=(buffer[3] >> 3) & 0x1;
+ header->original=(buffer[3] >> 2) & 0x1;
+ header->emphasis=(buffer[3]) & 0x3;
+
+ return ((fl=frame_length(header)) >= MIN_FRAME_SIZE ? fl : 0);
+}
+
+int frame_length(mp3header *header)
+{
+ return header->sync == 0xFFE ?
+ (frame_size_index[3-header->layer]*((header->version&1)+1)*
+ header_bitrate(header)/header_frequency(header))+
+ header->padding : 1;
+}
+
+int header_layer(mp3header *h)
+{
+ return layer_tab[h->layer];
+}
+
+int header_bitrate(mp3header *h)
+{
+ if(h->bitrate > 0)
+ return bitrate[h->version & 1][3-h->layer][h->bitrate-1];
+ else
+ return -1; // unknown
+}
+
+int header_frequency(mp3header *h)
+{
+ return frequencies[h->version][h->freq];
+}
+
+const char *header_emphasis(mp3header *h)
+{
+ return emphasis_text[h->emphasis];
+}
+
+const char *header_mode(mp3header *h)
+{
+ return mode_text[h->mode];
+}
+
+int header_channels(mp3header * h)
+{
+ return h->mode == 3 ? 1 : 2;
+}
+
+int header_crc(mp3header *h)
+{
+ return (!h->crc);
+}
+
+int sameConstant(mp3header *h1, mp3header *h2)
+{
+ if((*(uint*)h1) == (*(uint*)h2)) return 1;
+
+ if((h1->version == h2->version ) &&
+ (h1->layer == h2->layer ) &&
+ (h1->crc == h2->crc ) &&
+ (h1->freq == h2->freq ) &&
+ (h1->mode == h2->mode ) &&
+ (h1->copyright == h2->copyright ) &&
+ (h1->original == h2->original ) &&
+ (h1->emphasis == h2->emphasis ))
+ return 1;
+ else return 0;
+}
+
+
+int get_id3(mp3info *mp3)
+{
+ // this will read ID3v1 tags
+ int retcode=0;
+ char fbuf[4];
+
+ if(mp3->datasize >= 128)
+ {
+ if(fseek(mp3->file, -128, SEEK_END ))
+ {
+ retcode |= 4;
+ } else {
+ fread(fbuf,1,3,mp3->file); fbuf[3] = '\0';
+ mp3->id3.genre[0]=255;
+
+ if(!strcmp((const char *)"TAG",(const char *)fbuf))
+ {
+ mp3->id3_isvalid=1;
+ mp3->datasize -= 128;
+ fseek(mp3->file, -125, SEEK_END);
+ fread(mp3->id3.title,1,30,mp3->file); mp3->id3.title[30] = '\0';
+ fread(mp3->id3.artist,1,30,mp3->file); mp3->id3.artist[30] = '\0';
+ fread(mp3->id3.album,1,30,mp3->file); mp3->id3.album[30] = '\0';
+ fread(mp3->id3.year,1,4,mp3->file); mp3->id3.year[4] = '\0';
+ fread(mp3->id3.comment,1,30,mp3->file); mp3->id3.comment[30] = '\0';
+ if(mp3->id3.comment[28] == '\0')
+ {
+ mp3->id3.track[0] = mp3->id3.comment[29];
+ }
+ fread(mp3->id3.genre,1,1,mp3->file);
+ unpad(mp3->id3.title);
+ unpad(mp3->id3.artist);
+ unpad(mp3->id3.album);
+ unpad(mp3->id3.year);
+ unpad(mp3->id3.comment);
+ }
+ }
+ }
+ return retcode;
+}
+
+char *pad(char *string, int length)
+{
+ int l;
+
+ l=strlen(string);
+ while(l<length)
+ {
+ string[l] = ' ';
+ l++;
+ }
+
+ string[l]='\0';
+ return string;
+}
+
+// Remove trailing whitespace from the end of a string
+
+char *unpad(char *string)
+{
+ char *pos=string+strlen(string)-1;
+ while(isspace(pos[0])) (pos--)[0]=0;
+ return string;
+}
+
+bool scan_mp3_file(QString& szFileName,mp3info * i)
+{
+ //memset(i,0,sizeof(mp3info));
+ resetmp3infoStruct(i);
+
+
+ i->filename = "text";
+ i->file = fopen(QTextCodec::codecForLocale()->fromUnicode(i->filename).data(),"rb");
+ if(!i->file)return false;
+
+ get_mp3_info(i);
+
+ fclose(i->file);
+
+ return (i->id3_isvalid);
+}
+
diff --git a/src/modules/mediaplayer/mp_mp3.h b/src/modules/mediaplayer/mp_mp3.h
new file mode 100644
index 00000000..d42c5ef7
--- /dev/null
+++ b/src/modules/mediaplayer/mp_mp3.h
@@ -0,0 +1,137 @@
+//=============================================================================
+//
+// File : mp_mp3.h
+// Creation date : Fri Mar 25 20:01:25 2005 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2005 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This file is based on the mp3tech.h. It is released under the original
+// license and the original copyright notice follows.
+//
+// mp3tech.h
+//
+// Copyright (C) 2000 Cedric Tefft <cedric@earthling.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.
+//
+// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// This file is based in part on:
+//
+// * MP3Info 0.5 by Ricardo Cerqueira <rmc@rccn.net>
+// * MP3Stat 0.9 by Ed Sweetman <safemode@voicenet.com> and
+// Johannes Overmann <overmann@iname.com>
+//
+// There has been also a remarkable work by Cristopher Tieckle (Crissi)
+//
+//=============================================================================
+
+// MIN_CONSEC_GOOD_FRAMES defines how many consecutive valid MP3 frames
+// we need to see before we decide we are looking at a real MP3 file
+#define MIN_CONSEC_GOOD_FRAMES 4
+#define FRAME_HEADER_SIZE 4
+#define MIN_FRAME_SIZE 21
+#define NUM_SAMPLES 4
+#define TEXT_FIELD_LEN 30
+#define INT_FIELD_LEN 4
+
+
+#include "kvi_settings.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <qstring.h>
+
+#ifdef COMPILE_ON_WINDOWS
+ #include <windows.h>
+#else
+ #include <unistd.h>
+ #include <sys/stat.h>
+ #include <ctype.h>
+ #include <string.h>
+#endif
+
+
+enum VBR_REPORT { VBR_VARIABLE, VBR_AVERAGE, VBR_MEDIAN };
+
+typedef struct {
+ unsigned int sync;
+ unsigned int version;
+ unsigned int layer;
+ unsigned int crc;
+ unsigned int bitrate;
+ unsigned int freq;
+ unsigned int padding;
+ unsigned int extension;
+ unsigned int mode;
+ unsigned int mode_extension;
+ unsigned int copyright;
+ unsigned int original;
+ unsigned int emphasis;
+} mp3header;
+
+typedef struct {
+ char title[31];
+ char artist[31];
+ char album[31];
+ char year[5];
+ char comment[31];
+ unsigned char track[1];
+ unsigned char genre[1];
+} id3tag;
+
+typedef struct {
+ QString filename;
+ FILE *file;
+ unsigned int datasize;
+ int header_isvalid;
+ mp3header header;
+ int id3_isvalid;
+ id3tag id3;
+ int vbr;
+ float vbr_average;
+ int seconds;
+ int frames;
+ int badframes;
+} mp3info;
+
+// mode field:
+// 00 - Stereo
+// 01 - Joint stereo (Stereo)
+// 10 - Dual channel (2 mono channels)
+// 11 - Single channel (Mono)
+
+bool scan_mp3_file(QString& szFileName,mp3info * i);
+
+void resetmp3infoStruct(mp3info *i);
+
+int header_channels(mp3header *h);
+int header_frequency(mp3header *h);
+const char *header_emphasis(mp3header *h);
+const char *header_mode(mp3header *h);
+int header_layer(mp3header *h);
+int header_bitrate(mp3header *h);
+double header_version(mp3header *h);
+int header_crc(mp3header *h);
+int get_header(FILE *file,mp3header *header);
+int frame_length(mp3header *header);
+int sameConstant(mp3header *h1, mp3header *h2);
+int get_mp3_info(mp3info *mp3);
+int get_id3(mp3info *mp3);
+char *pad(char *string, int length);
+char *unpad(char *string);
+int get_first_header(mp3info *mp3,long startpos);
+//void tagedit_curs(char *filename, int filenum, int fileoutof, id3tag *tag);
+const char * get_typegenre(int idx);
+
diff --git a/src/modules/mediaplayer/mp_winampinterface.cpp b/src/modules/mediaplayer/mp_winampinterface.cpp
new file mode 100644
index 00000000..ae157782
--- /dev/null
+++ b/src/modules/mediaplayer/mp_winampinterface.cpp
@@ -0,0 +1,566 @@
+//=============================================================================
+//
+// File : mp_winampinterface.cpp
+// Created on Mon 28 Mar 2005 23:41:50 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "mp_winampinterface.h"
+#include "kvi_options.h"
+
+#ifdef COMPILE_ON_WINDOWS
+
+#include <qtextcodec.h>
+
+#include "kvi_locale.h"
+#include "kvi_module.h"
+
+#include <windows.h>
+
+#define IPC_STARTPLAY 102
+#define IPC_ISPLAYING 104
+
+#define IPC_GETOUTPUTTIME 105
+// ** int res = SendMessage(hwnd_winamp,WM_WA_IPC,mode,IPC_GETOUTPUTTIME);
+// **
+// ** IPC_GETOUTPUTTIME returns the position in milliseconds of the
+// ** current song (mode = 0), or the song length, in seconds (mode = 1).
+// ** Returns -1 if not playing or error.
+
+#define IPC_JUMPTOTIME 106
+// ** SendMessage(hwnd_winamp,WM_WA_IPC,ms,IPC_JUMPTOTIME);
+// ** IPC_JUMPTOTIME sets the position in milliseconds of the
+// ** current song (approximately).
+
+#define IPC_SETPLAYLISTPOS 121
+// ** SendMessage(hwnd_winamp,WM_WA_IPC,position,IPC_SETPLAYLISTPOS)
+// ** IPC_SETPLAYLISTPOS sets the playlsit position to 'position'.
+
+#define IPC_SETVOLUME 122
+// ** SendMessage(hwnd_winamp,WM_WA_IPC,volume,IPC_SETVOLUME);
+// ** IPC_SETVOLUME sets the volume of Winamp (from 0-255).
+
+#define IPC_GETLISTLENGTH 124
+// ** int length = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLISTLENGTH);
+// ** IPC_GETLISTLENGTH returns the length of the current playlist, in
+// ** tracks.
+
+#define IPC_GETEQDATA 127
+// ** int data=SendMessage(hwnd_winamp,WM_WA_IPC,pos,IPC_GETEQDATA);
+// ** IPC_GETEQDATA queries the status of the EQ.
+// ** The value returned depends on what 'pos' is set to:
+// ** Value Meaning
+// ** ------------------
+// ** 0-9 The 10 bands of EQ data. 0-63 (+20db - -20db)
+// ** 10 The preamp value. 0-63 (+20db - -20db)
+// ** 11 Enabled. zero if disabled, nonzero if enabled.
+// ** 12 Autoload. zero if disabled, nonzero if enabled.
+
+#define IPC_SETEQDATA 128
+// ** SendMessage(hwnd_winamp,WM_WA_IPC,pos,IPC_GETEQDATA);
+// ** SendMessage(hwnd_winamp,WM_WA_IPC,value,IPC_SETEQDATA);
+// ** IPC_SETEQDATA sets the value of the last position retrieved
+// ** by IPC_GETEQDATA. This is pretty lame, and we should provide
+// ** an extended version that lets you do a MAKELPARAM(pos,value).
+// ** someday...
+
+#define IPC_GETPLAYLISTFILE 211
+// ** (requires Winamp 2.04+, only usable from plug-ins (not external apps))
+// ** char *name=SendMessage(hwnd_winamp,WM_WA_IPC,index,IPC_GETPLAYLISTFILE);
+// ** IPC_GETPLAYLISTFILE gets the filename of the playlist entry [index].
+// ** returns a pointer to it. returns NULL on error.
+
+#define IPC_GETPLAYLISTTITLE 212
+// * (requires Winamp 2.04+, only usable from plug-ins (not external apps))
+// ** char *name=SendMessage(hwnd_winamp,WM_WA_IPC,index,IPC_GETPLAYLISTTITLE);
+// ** IPC_GETPLAYLISTTITLE gets the title of the playlist entry [index].
+// ** returns a pointer to it. returns NULL on error.
+
+#define IPC_GET_SHUFFLE 250
+// ** val=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GET_SHUFFLE);
+// **
+// ** IPC_GET_SHUFFLE returns the status of the Shuffle option (1 if set)
+
+#define IPC_GET_REPEAT 251
+// ** val=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GET_REPEAT);
+// **
+// ** IPC_GET_REPEAT returns the status of the Repeat option (1 if set)
+
+#define IPC_SET_SHUFFLE 252
+// ** SendMessage(hwnd_winamp,WM_WA_IPC,value,IPC_SET_SHUFFLE);
+// **
+// ** IPC_SET_SHUFFLE sets the status of the Shuffle option (1 to turn it on)
+
+#define IPC_SET_REPEAT 253
+// ** SendMessage(hwnd_winamp,WM_WA_IPC,value,IPC_SET_REPEAT);
+// **
+// ** IPC_SET_REPEAT sets the status of the Repeat option (1 to turn it on)
+
+#define IPC_GETLISTPOS 125
+// ** int pos=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLISTPOS);
+// ** IPC_GETLISTPOS returns the playlist position. A lot like IPC_WRITEPLAYLIST
+// ** only faster since it doesn't have to write out the list. Heh, silly me.
+
+#define IPC_GETINFO 126
+// ** int inf=SendMessage(hwnd_winamp,WM_WA_IPC,mode,IPC_GETINFO);
+// ** IPC_GETINFO returns info about the current playing song. The value
+// ** it returns depends on the value of 'mode'.
+// ** Mode Meaning
+// ** ------------------
+// ** 0 Samplerate (i.e. 44100)
+// ** 1 Bitrate (i.e. 128)
+// ** 2 Channels (i.e. 2)
+
+#define IPC_PLAYFILE 100
+// ** COPYDATASTRUCT cds;
+// ** cds.dwData = IPC_PLAYFILE;
+// ** cds.lpData = (void *) "file.mp3";
+// ** cds.cbData = strlen((char *) cds.lpData)+1; // include space for null char
+// ** SendMessage(hwnd_winamp,WM_COPYDATA,(WPARAM)NULL,(LPARAM)&cds);
+// **
+// ** This will play the file "file.mp3".
+
+#define IPC_ISPLAYING 104
+// ** int res = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_ISPLAYING);
+// ** IPC_ISPLAYING returns the status of playback.
+// ** If it returns 1, it is playing. if it returns 3, it is paused,
+// ** if it returns 0, it is not playing.
+
+// The following stuff needs PostMessage(hwnd_winamp,WM_COMMAND,id,0);
+#define WINAMP_BUTTON1 40044
+#define WINAMP_BUTTON2 40045
+#define WINAMP_BUTTON3 40046
+#define WINAMP_BUTTON4 40047
+#define WINAMP_BUTTON5 40048
+
+#define WINAMP_CMD_PREV WINAMP_BUTTON1
+#define WINAMP_CMD_PLAY WINAMP_BUTTON2
+#define WINAMP_CMD_PAUSE WINAMP_BUTTON3
+#define WINAMP_CMD_STOP WINAMP_BUTTON4
+#define WINAMP_CMD_NEXT WINAMP_BUTTON5
+
+#define WINAMP_CMD_QUIT 40001
+
+#define KVIRC_WM_USER 63112
+
+#define KVIRC_WM_USER_CHECK 13123
+#define KVIRC_WM_USER_CHECK_REPLY 13124
+#define KVIRC_WM_USER_GETTITLE 5000
+#define KVIRC_WM_USER_GETFILE 10000
+#define KVIRC_WM_USER_TRANSFER 15000
+
+
+static QTextCodec * mediaplayer_get_codec()
+{
+ QTextCodec * c= QTextCodec::codecForName(KVI_OPTION_STRING(KviOption_stringWinampTextEncoding));
+ if(!c)c = QTextCodec::codecForLocale();
+ return c;
+
+}
+
+static HWND find_winamp(KviWinampInterface * i)
+{
+ HWND hWnd = FindWindow("Winamp v1.x",NULL);
+ if(!hWnd)
+ {
+ // try to start the process ?
+ i->setLastError(__tr2qs_ctx("Can't find a running winamp window","mediaplayer"));
+ }
+ return hWnd;
+}
+
+
+MP_IMPLEMENT_DESCRIPTOR(
+ KviWinampInterface,
+ "winamp",
+ __tr2qs_ctx(
+ "An interface to the popupar Winamp media player.\n" \
+ "You can download it from http://www.winamp.com.\n" \
+ "To use all the features of this interface you must " \
+ "copy the gen_kvirc.dll plugin found in the KVIrc " \
+ "distribution directory to the Winamp plugins folder " \
+ "and restart winamp."
+ ,
+ "mediaplayer"
+ )
+)
+
+
+KviWinampInterface::KviWinampInterface()
+: KviMediaPlayerInterface()
+{
+}
+
+KviWinampInterface::~KviWinampInterface()
+{
+}
+
+
+int KviWinampInterface::detect(bool bStart)
+{
+ if(find_winamp(this))return 80;
+ // FIXME : check for Programs Folder\Winamp\Winamp.exe ?
+ // FIXME : if bStart try to start winamp.exe ?
+ return 50;
+}
+
+#define MP_WINAMP_SENDMESSAGE(__cmdname,__wmmsg,__lparam,__wparam) \
+ bool KviWinampInterface::__cmdname() \
+ { \
+ HWND hWinamp = find_winamp(this); \
+ if(hWinamp)SendMessage(hWinamp,__wmmsg,__lparam,__wparam); \
+ return hWinamp != 0; \
+ }
+
+#define MP_WINAMP_WM_USER(__cmdname,_ipcmsg) MP_WINAMP_SENDMESSAGE(__cmdname,WM_USER,0,_ipcmsg)
+#define MP_WINAMP_WM_COMMAND(__cmdname,_cmdmsg) MP_WINAMP_SENDMESSAGE(__cmdname,WM_COMMAND,_cmdmsg,0)
+
+MP_WINAMP_WM_USER(play,IPC_STARTPLAY)
+MP_WINAMP_WM_COMMAND(stop,WINAMP_CMD_STOP)
+MP_WINAMP_WM_COMMAND(next,WINAMP_CMD_NEXT)
+MP_WINAMP_WM_COMMAND(prev,WINAMP_CMD_PREV)
+MP_WINAMP_WM_COMMAND(pause,WINAMP_CMD_PAUSE)
+MP_WINAMP_WM_COMMAND(quit,WINAMP_CMD_QUIT)
+
+
+int KviWinampInterface::length()
+{
+ int leninsecs = -1;
+ HWND hWinamp = find_winamp(this);
+ if(hWinamp)leninsecs = SendMessage(hWinamp,WM_USER,1,IPC_GETOUTPUTTIME);
+ return leninsecs * 1000;
+}
+
+int KviWinampInterface::position()
+{
+ int leninmsecs = -1;
+ HWND hWinamp = find_winamp(this);
+ if(hWinamp)leninmsecs = SendMessage(hWinamp,WM_USER,0,IPC_GETOUTPUTTIME);
+ return leninmsecs;
+}
+
+int KviWinampInterface::bitRate()
+{
+ int ret = -1;
+ HWND hWinamp = find_winamp(this);
+ if(hWinamp)ret = SendMessage(hWinamp,WM_USER,1,IPC_GETINFO);
+ return ret;
+}
+
+int KviWinampInterface::sampleRate()
+{
+ int ret = -1;
+ HWND hWinamp = find_winamp(this);
+ if(hWinamp)ret = SendMessage(hWinamp,WM_USER,0,IPC_GETINFO);
+ return ret;
+}
+
+int KviWinampInterface::channels()
+{
+ int ret = -1;
+ HWND hWinamp = find_winamp(this);
+ if(hWinamp)ret = SendMessage(hWinamp,WM_USER,2,IPC_GETINFO);
+ return ret;
+}
+
+KviMediaPlayerInterface::PlayerStatus KviWinampInterface::status()
+{
+ HWND hWinamp = find_winamp(this);
+ int ret = 1000;
+ if(hWinamp)ret = SendMessage(hWinamp,WM_USER,0,IPC_ISPLAYING);
+ switch(ret)
+ {
+ case 0:
+ return KviMediaPlayerInterface::Stopped;
+ break;
+ case 3:
+ return KviMediaPlayerInterface::Paused;
+ break;
+ case 1:
+ return KviMediaPlayerInterface::Playing;
+ break;
+ default:
+ return KviMediaPlayerInterface::Unknown;
+ break;
+ }
+ return KviMediaPlayerInterface::Unknown;
+}
+
+QString KviWinampInterface::mrl()
+{
+ QString ret;
+ HWND hWinamp = find_winamp(this);
+ if(hWinamp)
+ {
+ int ret2 = SendMessage(hWinamp,WM_USER,KVIRC_WM_USER,KVIRC_WM_USER_CHECK);
+
+ if(ret2 =! KVIRC_WM_USER_CHECK_REPLY)
+ {
+ setLastError(__tr2qs_ctx("The winamp plugin has not been installed properly. Check /help mediaplayer.nowplaying","mediaplayer"));
+ return ret;
+ }
+
+ int len = SendMessage(hWinamp,WM_USER,KVIRC_WM_USER,KVIRC_WM_USER_GETFILE);
+
+ if(len < 4096)
+ {
+ char szBuffer[4096];
+
+ for(int i = 0;i < len;i++)
+ {
+ szBuffer[i] = SendMessage(hWinamp,WM_USER,KVIRC_WM_USER,KVIRC_WM_USER_TRANSFER + i);
+ }
+ szBuffer[len] = '\0';
+ QTextCodec *c=mediaplayer_get_codec();
+ if (c) ret = c->toUnicode(szBuffer);
+ else ret=szBuffer;
+ if(!ret.startsWith("http://",false))
+ ret.prepend("file://");
+ }
+ }
+ return ret;
+}
+
+QString KviWinampInterface::nowPlaying()
+{
+ QString ret;
+ HWND hWinamp = find_winamp(this);
+ if(hWinamp)
+ {
+ int retpippo = SendMessage(hWinamp,WM_USER,KVIRC_WM_USER,KVIRC_WM_USER_CHECK);
+ if(retpippo =! KVIRC_WM_USER_CHECK_REPLY)
+ {
+ setLastError(__tr2qs_ctx("The winamp plugin has not been installed properly. Check /help mediaplayer.nowplaying","mediaplayer") );
+ return ret;
+ }
+
+ int len = SendMessage(hWinamp,WM_USER,KVIRC_WM_USER,KVIRC_WM_USER_GETTITLE);
+
+ if(len < 4096)
+ {
+ char szBuffer[4096];
+
+ for(int i = 0;i < len;i++)
+ {
+ szBuffer[i] = SendMessage(hWinamp,WM_USER,KVIRC_WM_USER,KVIRC_WM_USER_TRANSFER + i);
+ }
+ szBuffer[ len ] = '\0';
+
+ QTextCodec *c=mediaplayer_get_codec();
+ if (c) ret = c->toUnicode(szBuffer);
+ else ret=szBuffer;
+ }
+ }
+ return ret;
+}
+
+bool KviWinampInterface::playMrl(const QString &mrl)
+{
+ HWND hWinamp = find_winamp(this);
+ if(hWinamp)
+ {
+ QTextCodec *c=mediaplayer_get_codec();
+ KviStr szMrl = c ? c->fromUnicode(mrl) : mrl.utf8();
+ COPYDATASTRUCT cds;
+ cds.dwData = IPC_PLAYFILE;
+ cds.lpData = (void *)szMrl.ptr();
+ cds.cbData = szMrl.len() + 1; // include space for null char
+ SendMessage(hWinamp,WM_COPYDATA,(WPARAM)NULL,(LPARAM) &cds);
+ return true;
+ }
+ return false;
+}
+
+bool KviWinampInterface::setVol(kvs_int_t &iVol)
+{
+ HWND hWinamp = find_winamp(this);
+ if(hWinamp)
+ {
+ SendMessage(hWinamp,WM_USER,iVol,IPC_SETVOLUME);
+ return true;
+ }
+ return false;
+}
+
+int KviWinampInterface::getVol()
+{
+ int ret = -1;
+ HWND hWinamp = find_winamp(this);
+ if(hWinamp)ret = SendMessage(hWinamp,WM_USER,-666,IPC_SETVOLUME);
+ return ret;
+}
+
+bool KviWinampInterface::jumpTo(kvs_int_t &iPos)
+{
+ HWND hWinamp = find_winamp(this);
+ if(hWinamp)
+ {
+ SendMessage(hWinamp,WM_USER,iPos,IPC_JUMPTOTIME);
+ return true;
+ }
+ return false;
+}
+bool KviWinampInterface::hide()
+{
+ HWND hWinamp = find_winamp(this);
+ HWND hWinampPE = FindWindow("Winamp PE",NULL); /*Playlist*/
+ HWND hWinampEQ = FindWindow("Winamp EQ",NULL); /*Equalizer*/
+ HWND hWinampMB = FindWindow("Winamp MB",NULL); /*MiniBrowser*/
+ HWND hWinampGen = FindWindow("Winamp Gen",NULL); /*Library*/
+ HWND hWinampVideo = FindWindow("Winamp Video",NULL); /*Video*/
+ if(hWinamp)
+ {
+ ShowWindow(hWinamp, SW_HIDE);
+ if(hWinampPE || hWinampEQ || hWinampMB || hWinampGen || hWinampVideo )
+ {
+ if(hWinampPE)
+ ShowWindow(hWinampPE, SW_HIDE);
+ if(hWinampEQ)
+ ShowWindow(hWinampEQ, SW_HIDE);
+ if(hWinampMB)
+ ShowWindow(hWinampMB, SW_HIDE);
+ if(hWinampGen)
+ ShowWindow(hWinampGen, SW_HIDE);
+ if(hWinampVideo)
+ ShowWindow(hWinampVideo, SW_HIDE);
+ return true;
+ }
+ return true;
+ }
+ return false;
+}
+
+bool KviWinampInterface::show()
+{
+ HWND hWinamp = find_winamp(this);
+ if(hWinamp)
+ {
+ ShowWindow(hWinamp, SW_SHOW);
+ return true;
+ }
+ return false;
+}
+
+bool KviWinampInterface::minimize()
+{
+ HWND hWinamp = find_winamp(this);
+ if(hWinamp)
+ {
+ ShowWindow(hWinamp, SW_SHOWMINIMIZED);
+ return true;
+ }
+ return false;
+}
+
+bool KviWinampInterface::setPlayListPos(int &iPos)
+{
+ HWND hWinamp = find_winamp(this);
+ if(hWinamp)
+ {
+ SendMessage(hWinamp,WM_USER,iPos,IPC_SETPLAYLISTPOS);
+ return true;
+ }
+ return false;
+}
+
+int KviWinampInterface::getPlayListPos()
+{
+ int ret = -1;
+ HWND hWinamp = find_winamp(this);
+ if(hWinamp)ret = SendMessage(hWinamp,WM_USER,2,IPC_GETLISTPOS);
+ return ret;
+}
+
+int KviWinampInterface::getListLength()
+{
+ int ret = -1;
+ HWND hWinamp = find_winamp(this);
+ if(hWinamp)ret = SendMessage(hWinamp,WM_USER,2,IPC_GETLISTLENGTH);
+ return ret;
+}
+
+bool KviWinampInterface::setEqData(int &iPos, int &iVal)
+{
+ HWND hWinamp = find_winamp(this);
+ if(hWinamp)
+ {
+ SendMessage(hWinamp,WM_USER,iPos,IPC_GETEQDATA);
+ SendMessage(hWinamp,WM_USER,iVal,IPC_SETEQDATA);
+ return true;
+ }
+ return false;
+}
+
+int KviWinampInterface::getEqData(int &ival)
+{
+ HWND hWinamp = find_winamp(this);
+ int ret = -1;
+ if(hWinamp)
+ {
+ ret = SendMessage(hWinamp,WM_USER,ival,IPC_GETEQDATA);
+ return ret;
+ }
+ return ret;
+}
+
+bool KviWinampInterface::getRepeat()
+{
+ HWND hWinamp = find_winamp(this);
+ if(hWinamp)
+ {
+ bool bRepeat = SendMessage(hWinamp,WM_USER,0,IPC_GET_REPEAT);
+ return bRepeat;
+ }
+ return false;
+}
+
+bool KviWinampInterface::getShuffle()
+{
+ HWND hWinamp = find_winamp(this);
+ if(hWinamp)
+ {
+ bool bShuffle = SendMessage(hWinamp,WM_USER,0,IPC_GET_SHUFFLE);
+ return bShuffle;
+ }
+ return false;
+}
+
+bool KviWinampInterface::setShuffle(bool &bVal)
+{
+ HWND hWinamp = find_winamp(this);
+ if(hWinamp)
+ {
+ bool bRepeat = SendMessage(hWinamp,WM_USER,bVal,IPC_SET_SHUFFLE);
+ return bRepeat;
+ }
+ return false;
+}
+
+bool KviWinampInterface::setRepeat(bool &bVal)
+{
+ HWND hWinamp = find_winamp(this);
+ if(hWinamp)
+ {
+ bool bShuffle = SendMessage(hWinamp,WM_USER,bVal,IPC_SET_REPEAT);
+ return bShuffle;
+ }
+ return false;
+}
+#endif //COMPILE_ON_WINDOWS
diff --git a/src/modules/mediaplayer/mp_winampinterface.h b/src/modules/mediaplayer/mp_winampinterface.h
new file mode 100644
index 00000000..ed2068db
--- /dev/null
+++ b/src/modules/mediaplayer/mp_winampinterface.h
@@ -0,0 +1,76 @@
+#ifndef _MP_WINAMPINTERFACE_H_
+#define _MP_WINAMPINTERFACE_H_
+//=============================================================================
+//
+// File : mp_winampinterface.h
+// Created on Mon 28 Mar 2005 23:41:50 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_ON_WINDOWS
+
+ #include "mp_interface.h"
+
+ class KviWinampInterface : public KviMediaPlayerInterface
+ {
+ public:
+ KviWinampInterface();
+ ~KviWinampInterface();
+ public:
+ virtual int detect(bool bStart);
+ virtual bool prev();
+ virtual bool next();
+ virtual bool play();
+ virtual bool stop();
+ virtual bool pause();
+ virtual bool quit();
+ virtual QString nowPlaying();
+ virtual QString mrl();
+ virtual int position();
+ virtual int length();
+ virtual bool playMrl(const QString &mrl);
+ virtual bool setVol(kvs_int_t &iVol);
+ virtual int getVol();
+ virtual bool jumpTo(kvs_int_t &iPos);
+ virtual int sampleRate();
+ virtual int bitRate();
+ virtual int channels();
+ virtual bool hide();
+ virtual bool show();
+ virtual bool minimize();
+ virtual int getPlayListPos();
+ virtual bool setPlayListPos(int &iPos);
+ virtual int getListLength();
+ virtual int getEqData(int &ival);
+ virtual bool setEqData(int &iPos, int &iVal);
+ virtual bool getRepeat();
+ virtual bool getShuffle();
+ virtual bool setRepeat(bool &bVal);
+ virtual bool setShuffle(bool &bVal);
+ virtual KviMediaPlayerInterface::PlayerStatus status();
+ };
+
+ MP_DECLARE_DESCRIPTOR(KviWinampInterface)
+
+#endif //COMPILE_ON_WINDOWS
+
+#endif //!_MP_WINAMPINTERFACE_H_
diff --git a/src/modules/mediaplayer/mp_xmmsinterface.cpp b/src/modules/mediaplayer/mp_xmmsinterface.cpp
new file mode 100644
index 00000000..532327af
--- /dev/null
+++ b/src/modules/mediaplayer/mp_xmmsinterface.cpp
@@ -0,0 +1,355 @@
+//=============================================================================
+//
+// File : mp_xmmsinterface.cpp
+// Created on Fri 25 Mar 2005 20:04:54 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2005-2007 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+// Thnx to Alexander Stillich <torque at pltn dot org> for Audacious
+// media player interface hints :)
+//
+//=============================================================================
+
+#include "mp_xmmsinterface.h"
+
+#ifndef COMPILE_ON_WINDOWS
+
+#include "kvi_locale.h"
+
+MP_IMPLEMENT_DESCRIPTOR(
+ KviXmmsInterface,
+ "xmms",
+ __tr2qs_ctx(
+ "An interface to the popular UNIX xmms media player.\n" \
+ "Download it from http://www.xmms.org\n"
+ ,
+ "mediaplayer"
+ )
+)
+
+MP_IMPLEMENT_DESCRIPTOR(
+ KviAudaciousInterface,
+ "audacious",
+ __tr2qs_ctx(
+ "An interface to the popular UNIX audacious media player.\n" \
+ "Download it from http://audacious-media-player.org\n"
+ ,
+ "mediaplayer"
+ )
+)
+
+static const char *xmms_lib_names[] =
+{
+ "libxmms.so",
+ "libxmms.so.1",
+ "/usr/lib/libxmms.so",
+ "/usr/lib/libxmms.so.1",
+ "/usr/local/lib/libxmms.so",
+ "/usr/local/lib/libxmms.so.1",
+ 0
+};
+
+static const char *audacious_lib_names[] =
+{
+ "libaudacious.so",
+ "libaudacious.so.4",
+ "/usr/lib/libaudacious.so",
+ "/usr/lib/libaudacious.so.4",
+ "/usr/local/lib/libaudacious.so",
+ "/usr/local/lib/libaudacious.so.4",
+ 0
+};
+
+
+
+KviXmmsInterface::KviXmmsInterface()
+: KviMediaPlayerInterface()
+{
+ m_hPlayerLibrary = 0;
+ m_szPlayerLibraryName = "libxmms.so";
+ m_pLibraryPaths = xmms_lib_names;
+}
+
+KviXmmsInterface::~KviXmmsInterface()
+{
+ if(m_hPlayerLibrary)
+ {
+ kvi_library_close(m_hPlayerLibrary);
+ m_hPlayerLibrary = 0;
+ }
+}
+
+KviAudaciousInterface::KviAudaciousInterface()
+: KviXmmsInterface()
+{
+ m_szPlayerLibraryName = "libaudacious.so";
+ m_pLibraryPaths = audacious_lib_names;
+}
+
+KviAudaciousInterface::~KviAudaciousInterface()
+{
+}
+
+bool KviXmmsInterface::loadPlayerLibrary()
+{
+ if(m_hPlayerLibrary)return true;
+
+ const char **lib_name = m_pLibraryPaths;
+ while(*lib_name)
+ {
+ m_hPlayerLibrary = kvi_library_load(*lib_name);
+ if(m_hPlayerLibrary)
+ {
+ m_szPlayerLibraryName = *lib_name;
+ break;
+ }
+ lib_name++;
+ }
+ return true;
+}
+
+void * KviXmmsInterface::lookupSymbol(const char * szSymbolName)
+{
+ if(!m_hPlayerLibrary)
+ {
+ if(!loadPlayerLibrary())
+ {
+ QString tmp;
+ KviQString::sprintf(tmp,__tr2qs_ctx("Can't load the player library (%Q)","mediaplayer"),&m_szPlayerLibraryName);
+ setLastError(tmp);
+ return 0;
+ }
+ }
+ void * symptr = kvi_library_symbol(m_hPlayerLibrary,szSymbolName);
+ if(!symptr)
+ {
+ QString tmp;
+ KviQString::sprintf(tmp,__tr2qs_ctx("Can't find symbol %s in %Q","mediaplayer"),szSymbolName,&m_szPlayerLibraryName);
+ setLastError(tmp);
+ }
+ return symptr;
+}
+
+
+int KviXmmsInterface::detect(bool bStart)
+{
+ void * sym = lookupSymbol("xmms_remote_play");
+ return sym ? 80 : 0;
+}
+
+#define XMMS_SIMPLE_CALL(__symname) \
+ void (*sym)(int) = (void (*)(int))lookupSymbol(__symname); \
+ if(!sym)return false; \
+ sym(0); \
+ return true;
+
+bool KviXmmsInterface::prev()
+{
+ XMMS_SIMPLE_CALL("xmms_remote_playlist_prev")
+}
+
+bool KviXmmsInterface::next()
+{
+ XMMS_SIMPLE_CALL("xmms_remote_playlist_next")
+}
+
+bool KviXmmsInterface::play()
+{
+ XMMS_SIMPLE_CALL("xmms_remote_play")
+}
+
+bool KviXmmsInterface::stop()
+{
+ XMMS_SIMPLE_CALL("xmms_remote_stop")
+}
+
+bool KviXmmsInterface::pause()
+{
+ XMMS_SIMPLE_CALL("xmms_remote_pause")
+}
+
+bool KviXmmsInterface::quit()
+{
+ XMMS_SIMPLE_CALL("xmms_remote_quit")
+}
+
+bool KviXmmsInterface::jumpTo(kvs_int_t &iPos)
+{
+ void (*sym)(int,int) = (void (*)(int,int))lookupSymbol("xmms_remote_jump_to_time");
+ if(!sym)return false;
+ sym(0,iPos);
+ return true;
+}
+
+bool KviXmmsInterface::setVol(kvs_int_t &iVol)
+{
+ void (*sym)(int,int) = (void (*)(int,int))lookupSymbol("xmms_remote_set_main_volume");
+ if(!sym)return false;
+ sym(0,100*iVol/255);
+ return true;
+}
+
+int KviXmmsInterface::getVol()
+{
+ int (*sym)(int) = (int (*)(int))lookupSymbol("xmms_remote_get_main_volume");
+ if(!sym)return -1;
+ int iVol = sym(0);
+ return iVol * 255 /100;
+}
+
+bool KviXmmsInterface::getRepeat()
+{
+ bool (*sym)(int) = (bool (*)(int))lookupSymbol("xmms_remote_is_repeat");
+ if(!sym)return false;
+ bool ret = sym(0);
+ return ret;
+}
+
+bool KviXmmsInterface::setRepeat(bool &bVal)
+{
+ bool (*sym1)(int) = (bool (*)(int))lookupSymbol("xmms_remote_is_repeat");
+ if(!sym1)return false;
+ bool bNow = sym1(0);
+ if(bNow != bVal)
+ {
+ void (*sym2)(int) = (void (*)(int))lookupSymbol("xmms_remote_toggle_repeat");
+ if(!sym2)return false;
+ sym2(0);
+ }
+ return true;
+}
+
+bool KviXmmsInterface::getShuffle()
+{
+ bool (*sym)(int) = (bool (*)(int))lookupSymbol("xmms_remote_is_shuffle");
+ if(!sym)return false;
+ bool ret = sym(0);
+ return ret;
+}
+
+bool KviXmmsInterface::setShuffle(bool &bVal)
+{
+ bool (*sym1)(int) = (bool (*)(int))lookupSymbol("xmms_remote_is_shuffle");
+ if(!sym1)return false;
+ bool bNow = sym1(0);
+ if(bNow != bVal)
+ {
+ void (*sym2)(int) = (void (*)(int))lookupSymbol("xmms_remote_toggle_shuffle");
+ if(!sym2)return false;
+ sym2(0);
+ }
+ return true;
+}
+
+KviMediaPlayerInterface::PlayerStatus KviXmmsInterface::status()
+{
+ bool (*sym1)(int) = (bool (*)(int))lookupSymbol("xmms_remote_is_paused");
+ if(sym1)
+ {
+ if(sym1(0))return KviMediaPlayerInterface::Paused;
+ bool (*sym2)(int) = (bool (*)(int))lookupSymbol("xmms_remote_is_playing");
+ if(sym2)
+ {
+ if(sym2(0))return KviMediaPlayerInterface::Playing;
+ else return KviMediaPlayerInterface::Stopped;
+ }
+ }
+
+ return KviMediaPlayerInterface::Unknown;
+}
+
+bool KviXmmsInterface::playMrl(const QString &mrl)
+{
+ void (*sym)(int,char *) = (void (*)(int,char *))lookupSymbol("xmms_remote_playlist_add_url_string");
+ KviQCString tmp = mrl.local8Bit();
+ if(!tmp.isEmpty())
+ {
+ if(sym)
+ {
+ sym(0,tmp.data());
+ int (*sym1)(int) = (int (*)(int))lookupSymbol("xmms_remote_get_playlist_length");
+ if(sym1)
+ {
+ int len = sym1(0);
+ if(len > 0)
+ {
+ void (*sym2)(int,int) = (void (*)(int,int))lookupSymbol("xmms_remote_set_playlist_pos");
+ if(sym2)
+ {
+ sym2(0,len - 1);
+ } else return false;
+ } else return false;
+ } else return false;
+ } else return false;
+ }
+ return true;
+}
+
+QString KviXmmsInterface::nowPlaying()
+{
+ int (*sym)(int) = (int (*)(int))lookupSymbol("xmms_remote_get_playlist_pos");
+ if(!sym)return QString::null;
+ int pos = sym(0);
+ char * (*sym2)(int,int) = (char * (*)(int,int))lookupSymbol("xmms_remote_get_playlist_title");
+ if(!sym2)return QString::null;
+ return QString::fromLocal8Bit(sym2(0,pos));
+}
+
+QString KviXmmsInterface::mrl()
+{
+ int (*sym)(int) = (int (*)(int))lookupSymbol("xmms_remote_get_playlist_pos");
+ if(!sym)return QString::null;
+ int pos = sym(0);
+ char * (*sym2)(int,int) = (char * (*)(int,int))lookupSymbol("xmms_remote_get_playlist_file");
+ if(!sym2)return QString::null;
+ QString ret = QString::fromLocal8Bit(sym2(0,pos));
+ if(ret.length() > 1)
+ if(ret[0] == '/')ret.prepend("file://");
+ return ret;
+}
+
+int KviXmmsInterface::position()
+{
+ int (*sym)(int) = (int (*)(int))lookupSymbol("xmms_remote_get_playlist_pos");
+ if(!sym)return -1;
+ int pos = sym(0);
+ int (*sym2)(int,int) = (int (*)(int,int))lookupSymbol("xmms_remote_get_output_time");
+ if(!sym2)return -1;
+ return sym2(0,pos);
+}
+
+int KviXmmsInterface::length()
+{
+ int (*sym)(int) = (int (*)(int))lookupSymbol("xmms_remote_get_playlist_pos");
+ if(!sym)return -1;
+ int pos = sym(0);
+ int (*sym2)(int,int) = (int (*)(int,int))lookupSymbol("xmms_remote_get_playlist_time");
+ if(!sym2)return -1;
+ return sym2(0,pos);
+}
+
+int KviXmmsInterface::getPlayListPos()
+{
+ int (*sym)(int) = (int (*)(int))lookupSymbol("xmms_remote_get_playlist_pos");
+ if(!sym)return -1;
+ return sym(0);
+}
+
+
+
+#endif //!COMPILE_ON_WINDOWS
diff --git a/src/modules/mediaplayer/mp_xmmsinterface.h b/src/modules/mediaplayer/mp_xmmsinterface.h
new file mode 100644
index 00000000..15f81811
--- /dev/null
+++ b/src/modules/mediaplayer/mp_xmmsinterface.h
@@ -0,0 +1,84 @@
+#ifndef _MP_XMMSINTERFACE_H_
+#define _MP_XMMSINTERFACE_H_
+//=============================================================================
+//
+// File : mp_xmmsinterface.h
+// Created on Fri 25 Mar 2005 20:04:54 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2005-2007 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+// Thnx to Alexander Stillich <torque at pltn dot org> for Audacious
+// media player interface hints :)
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "mp_interface.h"
+#include "kvi_library.h"
+
+#ifndef COMPILE_ON_WINDOWS
+ class KviXmmsInterface : public KviMediaPlayerInterface
+ {
+ public:
+ KviXmmsInterface();
+ virtual ~KviXmmsInterface();
+ protected:
+ kvi_library_t m_hPlayerLibrary;
+ QString m_szPlayerLibraryName;
+ const char ** m_pLibraryPaths;
+ public:
+ virtual int detect(bool bStart);
+ virtual bool prev();
+ virtual bool next();
+ virtual bool play();
+ virtual bool stop();
+ virtual bool pause();
+ virtual bool quit();
+ virtual bool jumpTo(kvs_int_t &iPos);
+ virtual bool setVol(kvs_int_t &iVol);
+ virtual int getVol();
+ virtual KviMediaPlayerInterface::PlayerStatus status();
+ virtual QString nowPlaying();
+ virtual bool playMrl(const QString &mrl);
+ virtual QString mrl();
+ virtual int getPlayListPos();
+ virtual int position();
+ virtual int length();
+ virtual bool getRepeat();
+ virtual bool getShuffle();
+ virtual bool setRepeat(bool &bVal);
+ virtual bool setShuffle(bool &bVal);
+ protected:
+ bool loadPlayerLibrary();
+ void * lookupSymbol(const char * szSymbolName);
+ };
+
+ MP_DECLARE_DESCRIPTOR(KviXmmsInterface)
+
+ class KviAudaciousInterface : public KviXmmsInterface
+ {
+ public:
+ KviAudaciousInterface();
+ virtual ~KviAudaciousInterface();
+ };
+
+ MP_DECLARE_DESCRIPTOR(KviAudaciousInterface)
+
+#endif //!COMPILE_ON_WINDOWS
+
+#endif //!_MP_XMMSINTERFACE_H_
diff --git a/src/modules/mircimport/Makefile.am b/src/modules/mircimport/Makefile.am
new file mode 100644
index 00000000..d47e88c7
--- /dev/null
+++ b/src/modules/mircimport/Makefile.am
@@ -0,0 +1,22 @@
+###############################################################################
+# KVirc IRC client Makefile- 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+SUBDIRS = caps pics
+
+pluglib_LTLIBRARIES = libkvimircimport.la
+
+libkvimircimport_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkvimircimport_la_SOURCES = libkvimircimport.cpp
+libkvimircimport_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+noinst_HEADERS= libkvimircimport.h
+
+%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
+
+libkvimircimport.cpp: libkvimircimport.moc
diff --git a/src/modules/mircimport/caps/Makefile.am b/src/modules/mircimport/caps/Makefile.am
new file mode 100644
index 00000000..151a1e0a
--- /dev/null
+++ b/src/modules/mircimport/caps/Makefile.am
@@ -0,0 +1,9 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+tmpdir = $(pluglibdir)/caps/serverimport/
+
+tmp_DATA= mircimport
+
+EXTRA_DIST = $(tmp_DATA)
diff --git a/src/modules/mircimport/caps/mircimport b/src/modules/mircimport/caps/mircimport
new file mode 100644
index 00000000..9788f702
--- /dev/null
+++ b/src/modules/mircimport/caps/mircimport
@@ -0,0 +1 @@
+timestamp
diff --git a/src/modules/mircimport/libkvimircimport.cpp b/src/modules/mircimport/libkvimircimport.cpp
new file mode 100644
index 00000000..4f3ac568
--- /dev/null
+++ b/src/modules/mircimport/libkvimircimport.cpp
@@ -0,0 +1,385 @@
+//
+// File : libkvimircimport.cpp
+// Creation date : Tue Aug 27 01:20:35 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "libkvimircimport.h"
+#include "kvi_module.h"
+
+#include "kvi_filedialog.h"
+#include "kvi_fileutils.h"
+#include "kvi_locale.h"
+#include "kvi_config.h"
+#include "kvi_app.h"
+#include "kvi_qstring.h"
+
+
+#include <qmessagebox.h>
+#include <qdir.h>
+#include <qpushbutton.h>
+#include "kvi_tal_vbox.h"
+
+KviMircServersIniImport * g_pMircServersIniImport = 0;
+KviRemoteMircServersIniImport * g_pRemoteMircServersIniImport = 0;
+
+
+KviMircServersIniImport::KviMircServersIniImport(KviModuleExtensionDescriptor * d)
+: KviMexServerImport(d)
+{
+}
+
+KviMircServersIniImport::~KviMircServersIniImport()
+{
+ g_pMircServersIniImport = 0;
+}
+
+int KviMircServersIniImport::doImport(const QString& filename)
+{
+ KviConfig cfg(filename,KviConfig::Read,true);
+ int iCount = 0;
+ if(cfg.hasGroup("servers"))
+ {
+ cfg.setGroup("servers");
+ int i = 0;
+ QString key;
+ QString entry;
+ do {
+ KviQString::sprintf(key,"n%d",i);
+ entry = cfg.readEntry(key,"");
+ if(!entry.isEmpty())
+ {
+ QString description;
+ QString serv;
+ QString port;
+ kvi_u32_t uPort = 0;
+ // <description>SERVER:<server:port>GROUP:<network>
+ int idx = KviQString::find(entry,"SERVER:");
+ if(idx != -1)
+ {
+ description = entry.left(idx);
+ entry.remove(0,idx + 7);
+ idx = KviQString::find(entry,"GROUP:");
+ if(idx != -1)
+ {
+ port = entry.left(idx);
+ entry.remove(0,idx + 6);
+ }
+ idx = KviQString::find(port,':');
+ if(idx != -1)
+ {
+ serv = port.left(idx);
+ port.remove(0,idx + 1);
+ bool bOk;
+ uPort = port.toUInt(&bOk);
+ if(!bOk)uPort = 6667;
+ } else {
+ serv = port;
+ uPort = 6667;
+ }
+ }
+ if(entry.isEmpty())entry = __tr("Standalone Servers");
+ if(!serv.isEmpty())
+ {
+ KviIrcServer s;
+ s.m_szHostname = serv;
+ s.m_szDescription = description;
+ s.m_uPort = uPort;
+ iCount++;
+ emit server(s,entry);
+ }
+ ++i;
+ }
+ } while(!entry.isEmpty());
+ } else {
+ QString tmp;
+ KviQString::sprintf(tmp,__tr2qs("%Q doesn't look like a servers.ini file.\nImport failed."),&filename);
+ QMessageBox::warning(0,__tr2qs("Warning - KVIrc"),tmp);
+ }
+ return iCount;
+}
+
+void KviMircServersIniImport::start()
+{
+ //KviStr buffer;
+ QString buffer;
+ if(!KviFileDialog::askForOpenFileName(buffer,__tr("Choose a servers.ini file"),0,"*.ini",false,true))return;
+
+ doImport(buffer);
+ delete this;
+}
+
+void KviMircServersIniImport::die()
+{
+ delete this;
+}
+
+
+
+
+
+
+
+#define KVI_WWWMIRCCOUK_SERVERSINI "http://www.mirc.co.uk/servers.ini"
+
+
+
+KviRemoteMircServerImportWizard::KviRemoteMircServerImportWizard(KviRemoteMircServersIniImport * f)
+: KviTalWizard(0)
+{
+ QString capt = __tr2qs("Remote mIRC servers.ini Import Wizard");
+ setCaption(capt);
+
+
+ m_pRequest = 0;
+ m_pFilter = f;
+
+ QLabel * l = new QLabel(this);
+ l->setText(__tr2qs("<center><b>Welcome!</b><br><br>This wizard will guide you in the process of " \
+ "downloading a list of IRC servers. Please click \"<b>Next</b>\" to begin the operation.</center>"));
+ addPage(l,capt);
+
+
+ KviTalVBox * vb = new KviTalVBox(this);
+ l = new QLabel(vb);
+ l->setText(__tr2qs("<center>Here you can modify the URL that the list will be downloaded from. In most cases the default URL is acceptable.</center>"));
+
+ vb->setStretchFactor(l,1);
+
+ m_pUrlEdit = new QLineEdit(vb);
+
+ m_pUrlEdit->setText(KVI_WWWMIRCCOUK_SERVERSINI);
+
+ addPage(vb,__tr2qs("URL Selection"));
+
+ vb = new KviTalVBox(this);
+
+ l = new QLabel(__tr2qs("Please wait while the list is being downloaded"),vb);
+ vb->setStretchFactor(l,1);
+
+ m_pOutput = new QLabel(vb);
+ m_pOutput->setFrameStyle(QFrame::WinPanel | QFrame::Sunken);
+
+ addPage(vb,__tr2qs("List Download"));
+
+ setBackEnabled(vb,false);
+ setNextEnabled(vb,false);
+ setFinishEnabled(vb,true);
+
+ connect(this,SIGNAL(selected(const QString &)),this,SLOT(pageSelected(const QString &)));
+}
+
+KviRemoteMircServerImportWizard::~KviRemoteMircServerImportWizard()
+{
+ if(m_pRequest)delete m_pRequest;
+}
+
+void KviRemoteMircServerImportWizard::pageSelected(const QString &title)
+{
+ if(title == __tr2qs("List Download"))
+ {
+ start();
+ }
+}
+
+void KviRemoteMircServerImportWizard::closeEvent(QCloseEvent *)
+{
+ m_pFilter->die();
+}
+
+void KviRemoteMircServerImportWizard::done(int r)
+{
+ m_pFilter->die();
+}
+
+
+void KviRemoteMircServerImportWizard::start()
+{
+ QString url = m_pUrlEdit->text();
+ if(url.isEmpty())url = KVI_WWWMIRCCOUK_SERVERSINI;
+
+ finishButton()->setEnabled(false);
+ if(m_pRequest)delete m_pRequest;
+
+ m_pRequest = new KviHttpRequest();
+ connect(m_pRequest,SIGNAL(terminated(bool)),this,SLOT(getListTerminated(bool)));
+ connect(m_pRequest,SIGNAL(status(const QString &)),this,SLOT(getListMessage(const QString &)));
+
+ g_pApp->getTmpFileName(m_szTmpFileName,"servers.ini");
+ if(!m_pRequest->get(KviUrl(url),KviHttpRequest::StoreToFile,m_szTmpFileName))
+ {
+ delete m_pRequest;
+ m_pRequest = 0;
+ m_pOutput->setText(__tr2qs("Failed to start the server list transfer :("));
+ finishButton()->setEnabled(true);
+ }
+}
+
+void KviRemoteMircServerImportWizard::getListMessage(const QString &message)
+{
+ if(!message.isEmpty())m_pOutput->setText(message);
+}
+
+
+void KviRemoteMircServerImportWizard::getListTerminated(bool bSuccess)
+{
+ if(!m_pRequest)return;
+ if(bSuccess)
+ {
+ m_pOutput->setText(__tr2qs("File downloaded: processing ..."));
+ m_pOutput->repaint();
+#ifndef COMPILE_ON_WINDOWS
+ g_pApp->syncX();
+#endif //!COMPILE_ON_WINDOWS
+
+ int iCount = m_pFilter->doImport(m_szTmpFileName);
+
+ QString tmp;
+ if(iCount > 0)
+ tmp = __tr2qs("%1 servers imported succesfully").arg(iCount);
+ else
+ tmp = __tr2qs("No servers imported");
+ m_pOutput->setText(tmp);
+
+ QDir d;
+ d.remove(m_szTmpFileName);
+ } else m_pOutput->setText(m_pRequest->lastError());
+
+ delete m_pRequest;
+ m_pRequest = 0;
+ cancelButton()->setEnabled(false);
+ finishButton()->setEnabled(true);
+}
+
+
+KviRemoteMircServersIniImport::KviRemoteMircServersIniImport(KviModuleExtensionDescriptor * d)
+: KviMircServersIniImport(d)
+{
+ m_pWizard = 0;
+}
+
+KviRemoteMircServersIniImport::~KviRemoteMircServersIniImport()
+{
+ if(m_pWizard)delete m_pWizard;
+ g_pRemoteMircServersIniImport = 0;
+}
+
+void KviRemoteMircServersIniImport::start()
+{
+ if(m_pWizard)delete m_pWizard;
+ m_pWizard = new KviRemoteMircServerImportWizard(this);
+ m_pWizard->show();
+}
+
+void KviRemoteMircServersIniImport::die()
+{
+ delete this;
+}
+
+
+static KviModuleExtension * mircimport_local_filter_alloc(KviModuleExtensionAllocStruct * s)
+{
+ if(g_pMircServersIniImport)delete g_pMircServersIniImport;
+ g_pMircServersIniImport = new KviMircServersIniImport(s->pDescriptor);
+ return g_pMircServersIniImport;
+}
+
+static KviModuleExtension * mircimport_remote_filter_alloc(KviModuleExtensionAllocStruct * s)
+{
+ if(g_pRemoteMircServersIniImport)delete g_pRemoteMircServersIniImport;
+ g_pRemoteMircServersIniImport = new KviRemoteMircServersIniImport(s->pDescriptor);
+ return g_pRemoteMircServersIniImport;
+}
+
+static bool mircimport_module_init(KviModule * m)
+{
+ QString szPath;
+ QPixmap * pix = 0;
+ if(g_pApp->findImage(szPath,"kvi_mircimport.png"))
+ {
+ pix = new QPixmap(szPath);
+ if(pix->isNull())
+ {
+ delete pix;
+ pix = 0;
+ }
+ }
+
+ KviModuleExtensionDescriptor * d = m->registerExtension("serverimport",
+ "mIRC servers.ini import filter",
+ __tr("Import from servers.ini"),
+ mircimport_local_filter_alloc);
+
+ if(d && pix)d->setIcon(*pix);
+
+ d = m->registerExtension("serverimport",
+ "Remote mIRC servers.ini import filter",
+ __tr("Import from http://www.mirc.co.uk/servers.ini"),
+ mircimport_remote_filter_alloc);
+
+ if(d && pix)d->setIcon(*pix);
+
+ if(pix)delete pix;
+ return true;
+}
+
+static bool mircimport_module_cleanup(KviModule *m)
+{
+ if(g_pMircServersIniImport)delete g_pMircServersIniImport;
+ if(g_pRemoteMircServersIniImport)delete g_pRemoteMircServersIniImport;
+ g_pMircServersIniImport = 0;
+ g_pRemoteMircServersIniImport = 0;
+
+ return true;
+}
+
+static bool mircimport_module_can_unload(KviModule * m)
+{
+ return ((!g_pMircServersIniImport) && (!g_pRemoteMircServersIniImport));
+}
+
+/*
+KVIMODULEEXPORTFUNC KviIrcServerImport * mircimport_module_createIrcServerImport(const char *filterName)
+{
+ if(kvi_strEqualCI(filterName,__tr("Import from servers.ini")))
+ {
+ if(!g_pMircServersIniImport)g_pMircServersIniImport = new KviMircServersIniImport();
+ return g_pMircServersIniImport;
+ } else {
+ if(!g_pRemoteMircServersIniImport)g_pRemoteMircServersIniImport = new KviRemoteMircServersIniImport("http://www.mirc.co.uk/servers.ini");
+ return g_pRemoteMircServersIniImport;
+ }
+ return 0;
+}
+*/
+
+
+
+KVIRC_MODULE(
+ "File", // module name
+ "1.0.0", // module version
+ "Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot net)", // author & (C)
+ "mIRC servers.ini importer",
+ mircimport_module_init,
+ mircimport_module_can_unload,
+ 0,
+ mircimport_module_cleanup
+)
+
+#include "libkvimircimport.moc"
diff --git a/src/modules/mircimport/libkvimircimport.h b/src/modules/mircimport/libkvimircimport.h
new file mode 100644
index 00000000..360e8346
--- /dev/null
+++ b/src/modules/mircimport/libkvimircimport.h
@@ -0,0 +1,82 @@
+#ifndef _LIBKVIMIRCIMPORT_H_
+#define _LIBKVIMIRCIMPORT_H_
+//
+// File : libkvimircimport.h
+// Creation date : Tue Aug 27 01:28:02 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_mexserverimport.h"
+#include "kvi_string.h"
+#include "kvi_http.h"
+
+#include <kvi_tal_wizard.h>
+#include <qlineedit.h>
+#include <qlabel.h>
+
+class KviMircServersIniImport : public KviMexServerImport
+{
+ Q_OBJECT
+public:
+ KviMircServersIniImport(KviModuleExtensionDescriptor * d);
+ ~KviMircServersIniImport();
+public:
+ int doImport(const QString& filename);
+ virtual void start();
+ virtual void die();
+};
+
+class KviRemoteMircServerImportWizard;
+
+class KviRemoteMircServersIniImport : public KviMircServersIniImport
+{
+ Q_OBJECT
+public:
+ KviRemoteMircServersIniImport(KviModuleExtensionDescriptor * d);
+ ~KviRemoteMircServersIniImport();
+protected:
+ KviRemoteMircServerImportWizard * m_pWizard;
+public:
+ virtual void start();
+ virtual void die();
+};
+
+class KviRemoteMircServerImportWizard : public KviTalWizard
+{
+ Q_OBJECT
+public:
+ KviRemoteMircServerImportWizard(KviRemoteMircServersIniImport * f);
+ ~KviRemoteMircServerImportWizard();
+protected:
+ QLineEdit * m_pUrlEdit;
+ QLabel * m_pOutput;
+ KviRemoteMircServersIniImport * m_pFilter;
+ KviHttpRequest * m_pRequest;
+ QString m_szTmpFileName;
+protected:
+ virtual void closeEvent(QCloseEvent *e);
+ virtual void done(int r);
+ void start();
+protected slots:
+ void getListMessage(const QString &message);
+ void getListTerminated(bool bSuccess);
+ void pageSelected(const QString &title);
+};
+
+#endif //_LIBKVIMIRCIMPORT_H_
diff --git a/src/modules/mircimport/pics/Makefile.am b/src/modules/mircimport/pics/Makefile.am
new file mode 100644
index 00000000..839e9668
--- /dev/null
+++ b/src/modules/mircimport/pics/Makefile.am
@@ -0,0 +1,9 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+tmpdir = $(picsdir)
+
+tmp_DATA= kvi_mircimport.png
+
+EXTRA_DIST = $(tmp_DATA)
diff --git a/src/modules/mircimport/pics/kvi_mircimport.png b/src/modules/mircimport/pics/kvi_mircimport.png
new file mode 100644
index 00000000..e671256f
--- /dev/null
+++ b/src/modules/mircimport/pics/kvi_mircimport.png
Binary files differ
diff --git a/src/modules/my/Makefile.am b/src/modules/my/Makefile.am
new file mode 100644
index 00000000..4c179e48
--- /dev/null
+++ b/src/modules/my/Makefile.am
@@ -0,0 +1,20 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkvimy.la
+
+libkvimy_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkvimy_la_SOURCES = libkvimy.cpp idle_x11.cpp idle_mac.cpp idle.cpp
+libkvimy_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+noinst_HEADERS= idle.h
+
+%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
+
+idle.cpp: idle.moc
diff --git a/src/modules/my/idle.cpp b/src/modules/my/idle.cpp
new file mode 100644
index 00000000..56720c77
--- /dev/null
+++ b/src/modules/my/idle.cpp
@@ -0,0 +1,133 @@
+/*
+ * idle.cpp - detect desktop idle time
+ * Copyright (C) 2003 Justin Karneges
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser 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"idle.h"
+
+#include<qcursor.h>
+#include<qdatetime.h>
+#include<qtimer.h>
+
+static IdlePlatform *platform = 0;
+static int platform_ref = 0;
+
+
+Idle::Idle()
+{
+ d = new Private;
+ d->active = false;
+ d->idleTime = 0;
+
+ // try to use platform idle
+ if(!platform) {
+ IdlePlatform *p = new IdlePlatform;
+ if(p->init())
+ platform = p;
+ else
+ delete p;
+ }
+ if(platform)
+ ++platform_ref;
+
+ connect(&d->checkTimer, SIGNAL(timeout()), SLOT(doCheck()));
+}
+
+Idle::~Idle()
+{
+ if(platform) {
+ --platform_ref;
+ if(platform_ref == 0) {
+ delete platform;
+ platform = 0;
+ }
+ }
+ delete d;
+}
+
+bool Idle::isActive() const
+{
+ return d->active;
+}
+
+bool Idle::usingPlatform() const
+{
+ return (platform ? true: false);
+}
+
+void Idle::start()
+{
+ d->startTime = QDateTime::currentDateTime();
+
+ if(!platform) {
+ // generic idle
+ d->lastMousePos = QCursor::pos();
+ d->idleSince = QDateTime::currentDateTime();
+ }
+
+ // poll every second (use a lower value if you need more accuracy)
+ d->checkTimer.start(1000);
+}
+
+void Idle::stop()
+{
+ d->checkTimer.stop();
+}
+
+int Idle::secondsIdle()
+{
+ int i;
+ if(platform)
+ i = platform->secondsIdle();
+ else {
+ QPoint curMousePos = QCursor::pos();
+ QDateTime curDateTime = QDateTime::currentDateTime();
+ if(d->lastMousePos != curMousePos) {
+ d->lastMousePos = curMousePos;
+ d->idleSince = curDateTime;
+ }
+ i = d->idleSince.secsTo(curDateTime);
+ }
+
+ // set 'beginIdle' to the beginning of the idle time (by backtracking 'i' seconds from now)
+ QDateTime beginIdle = QDateTime::currentDateTime().addSecs(-i);
+
+ // set 't' to hold the number of seconds between 'beginIdle' and 'startTime'
+ int t = beginIdle.secsTo(d->startTime);
+
+ // beginIdle later than (or equal to) startTime?
+ if(t <= 0) {
+ // scoot ourselves up to the new idle start
+ d->startTime = beginIdle;
+ }
+ // beginIdle earlier than startTime?
+ else if(t > 0) {
+ // do nothing
+ }
+
+ // how long have we been idle?
+ int idleTime = d->startTime.secsTo(QDateTime::currentDateTime());
+ return idleTime;
+}
+
+void Idle::doCheck()
+{
+ secondsIdle(secondsIdle());
+}
+
+#include "idle.moc"
diff --git a/src/modules/my/idle.h b/src/modules/my/idle.h
new file mode 100644
index 00000000..647b2691
--- /dev/null
+++ b/src/modules/my/idle.h
@@ -0,0 +1,84 @@
+/*
+ * idle.h - detect desktop idle time
+ * Copyright (C) 2003 Justin Karneges
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser 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 IDLE_H
+#define IDLE_H
+
+#include "kvi_settings.h"
+#include<qobject.h>
+#include<qcursor.h>
+#include<qdatetime.h>
+#include<qtimer.h>
+
+class IdlePlatform;
+
+class Idle : public QObject
+{
+ Q_OBJECT
+public:
+ Idle();
+ ~Idle();
+
+ bool isActive() const;
+ bool usingPlatform() const;
+ void start();
+ void stop();
+ int secondsIdle();
+
+signals:
+ void secondsIdle(int);
+
+private slots:
+ void doCheck();
+
+private:
+ class Private;
+ Private *d;
+};
+
+class IdlePlatform
+{
+public:
+ IdlePlatform();
+ ~IdlePlatform();
+
+ bool init();
+ int secondsIdle();
+
+private:
+ class Private;
+ Private *d;
+};
+
+class Idle::Private
+{
+public:
+ Private() {}
+
+ QPoint lastMousePos;
+ QDateTime idleSince;
+
+ bool active;
+ int idleTime;
+ QDateTime startTime;
+ QTimer checkTimer;
+};
+
+#endif
diff --git a/src/modules/my/idle_mac.cpp b/src/modules/my/idle_mac.cpp
new file mode 100644
index 00000000..92de564d
--- /dev/null
+++ b/src/modules/my/idle_mac.cpp
@@ -0,0 +1,162 @@
+/*
+ * idle_mac.cpp - detect desktop idle time
+ * Copyright (C) 2003 Tarkvara Design Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser 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
+ *
+ */
+
+#ifdef Q_OS_MACX
+
+#include"idle.h"
+#include <Carbon/Carbon.h>
+
+// Why does Apple have to make this so complicated?
+static OSStatus LoadFrameworkBundle(CFStringRef framework, CFBundleRef *bundlePtr) {
+ OSStatus err;
+ FSRef frameworksFolderRef;
+ CFURLRef baseURL;
+ CFURLRef bundleURL;
+
+ if ( bundlePtr == nil ) return( -1 );
+
+ *bundlePtr = nil;
+
+ baseURL = nil;
+ bundleURL = nil;
+
+ err = FSFindFolder(kOnAppropriateDisk, kFrameworksFolderType, true, &frameworksFolderRef);
+ if (err == noErr) {
+ baseURL = CFURLCreateFromFSRef(kCFAllocatorSystemDefault, &frameworksFolderRef);
+ if (baseURL == nil) {
+ err = coreFoundationUnknownErr;
+ }
+ }
+ if (err == noErr) {
+ bundleURL = CFURLCreateCopyAppendingPathComponent(kCFAllocatorSystemDefault, baseURL, framework, false);
+ if (bundleURL == nil) {
+ err = coreFoundationUnknownErr;
+ }
+ }
+ if (err == noErr) {
+ *bundlePtr = CFBundleCreate(kCFAllocatorSystemDefault, bundleURL);
+ if (*bundlePtr == nil) {
+ err = coreFoundationUnknownErr;
+ }
+ }
+ if (err == noErr) {
+ if ( ! CFBundleLoadExecutable( *bundlePtr ) ) {
+ err = coreFoundationUnknownErr;
+ }
+ }
+
+ // Clean up.
+ if (err != noErr && *bundlePtr != nil) {
+ CFRelease(*bundlePtr);
+ *bundlePtr = nil;
+ }
+ if (bundleURL != nil) {
+ CFRelease(bundleURL);
+ }
+ if (baseURL != nil) {
+ CFRelease(baseURL);
+ }
+
+ return err;
+}
+
+
+class IdlePlatform::Private {
+public:
+ EventLoopTimerRef mTimerRef;
+ int mSecondsIdle;
+
+ Private() : mTimerRef(0), mSecondsIdle(0) {}
+
+ static pascal void IdleTimerAction(EventLoopTimerRef, EventLoopIdleTimerMessage inState, void* inUserData);
+
+};
+
+
+pascal void IdlePlatform::Private::IdleTimerAction(EventLoopTimerRef, EventLoopIdleTimerMessage inState, void* inUserData) {
+ switch (inState) {
+ case kEventLoopIdleTimerStarted:
+ case kEventLoopIdleTimerStopped:
+ // Get invoked with this constant at the start of the idle period,
+ // or whenever user activity cancels the idle.
+ ((IdlePlatform::Private*)inUserData)->mSecondsIdle = 0;
+ break;
+ case kEventLoopIdleTimerIdling:
+ // Called every time the timer fires (i.e. every second).
+ ((IdlePlatform::Private*)inUserData)->mSecondsIdle++;
+ break;
+ }
+}
+
+
+IdlePlatform::IdlePlatform() {
+ d = new Private();
+}
+
+IdlePlatform::~IdlePlatform() {
+ RemoveEventLoopTimer(d->mTimerRef);
+ delete d;
+}
+
+
+// Typedef for the function we're getting back from CFBundleGetFunctionPointerForName.
+typedef OSStatus (*InstallEventLoopIdleTimerPtr)(EventLoopRef inEventLoop,
+ EventTimerInterval inFireDelay,
+ EventTimerInterval inInterval,
+ EventLoopIdleTimerUPP inTimerProc,
+ void * inTimerData,
+ EventLoopTimerRef * outTimer);
+
+
+bool IdlePlatform::init() {
+ // May already be init'ed.
+ if (d->mTimerRef) {
+ return true;
+ }
+
+ // According to the docs, InstallEventLoopIdleTimer is new in 10.2.
+ // According to the headers, it has been around since 10.0.
+ // One of them is lying. We'll play it safe and weak-link the function.
+
+ // Load the "Carbon.framework" bundle.
+ CFBundleRef carbonBundle;
+ if (LoadFrameworkBundle( CFSTR("Carbon.framework"), &carbonBundle ) != noErr) {
+ return false;
+ }
+
+ // Load the Mach-O function pointers for the routine we will be using.
+ InstallEventLoopIdleTimerPtr myInstallEventLoopIdleTimer = (InstallEventLoopIdleTimerPtr)CFBundleGetFunctionPointerForName(carbonBundle, CFSTR("InstallEventLoopIdleTimer"));
+ if (myInstallEventLoopIdleTimer == 0) {
+ return false;
+ }
+
+ EventLoopIdleTimerUPP timerUPP = NewEventLoopIdleTimerUPP(Private::IdleTimerAction);
+ if ((*myInstallEventLoopIdleTimer)(GetMainEventLoop(), kEventDurationSecond, kEventDurationSecond, timerUPP, 0, &d->mTimerRef)) {
+ return true;
+ }
+
+ return false;
+}
+
+
+int IdlePlatform::secondsIdle() {
+ return d->mSecondsIdle;
+}
+#endif \ No newline at end of file
diff --git a/src/modules/my/idle_x11.cpp b/src/modules/my/idle_x11.cpp
new file mode 100644
index 00000000..fa2f1f15
--- /dev/null
+++ b/src/modules/my/idle_x11.cpp
@@ -0,0 +1,113 @@
+/*
+ * idle_x11.cpp - detect desktop idle time
+ * Copyright (C) 2003 Justin Karneges
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser 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 Q_OS_MACX
+#ifndef COMPILE_ON_WINDOWS
+
+#include"idle.h"
+
+#ifndef COMPILE_XSS_SUPPORT
+
+IdlePlatform::IdlePlatform() {}
+IdlePlatform::~IdlePlatform() {}
+bool IdlePlatform::init() { return false; }
+int IdlePlatform::secondsIdle() { return 0; }
+
+#else
+
+#include<qapplication.h>
+
+#include<X11/Xlib.h>
+#include<X11/Xutil.h>
+#include<X11/extensions/scrnsaver.h>
+
+#ifdef COMPILE_USE_QT4
+ #include <qdesktopwidget.h>
+#endif
+
+static XErrorHandler old_handler = 0;
+extern "C" int xerrhandler(Display* dpy, XErrorEvent* err)
+{
+ if(err->error_code == BadDrawable)
+ return 0;
+
+ return (*old_handler)(dpy, err);
+}
+
+class IdlePlatform::Private
+{
+public:
+ Private() {}
+
+ XScreenSaverInfo *ss_info;
+};
+
+IdlePlatform::IdlePlatform()
+{
+ d = new Private;
+ d->ss_info = 0;
+}
+
+IdlePlatform::~IdlePlatform()
+{
+ if(d->ss_info)
+ XFree(d->ss_info);
+ if(old_handler) {
+ XSetErrorHandler(old_handler);
+ old_handler = 0;
+ }
+ delete d;
+}
+
+bool IdlePlatform::init()
+{
+ if(d->ss_info)
+ return true;
+
+ old_handler = XSetErrorHandler(xerrhandler);
+
+ int event_base, error_base;
+ if(XScreenSaverQueryExtension(QApplication::desktop()->screen()->x11Display(), &event_base, &error_base)) {
+ d->ss_info = XScreenSaverAllocInfo();
+ return true;
+ }
+ return false;
+}
+
+#ifdef COMPILE_USE_QT4
+ #include <qx11info_x11.h>
+#endif
+
+int IdlePlatform::secondsIdle()
+{
+ if(!d->ss_info)
+ return 0;
+#ifdef COMPILE_USE_QT4
+ if(!XScreenSaverQueryInfo(QApplication::desktop()->screen()->x11Display(), QX11Info::appRootWindow(), d->ss_info))
+#else
+ if(!XScreenSaverQueryInfo(QApplication::desktop()->screen()->x11Display(), qt_xrootwin(), d->ss_info))
+#endif
+ return 0;
+ return d->ss_info->idle / 1000;
+}
+
+#endif
+
+#endif
+#endif
diff --git a/src/modules/my/libkvimy.cpp b/src/modules/my/libkvimy.cpp
new file mode 100644
index 00000000..d98d44af
--- /dev/null
+++ b/src/modules/my/libkvimy.cpp
@@ -0,0 +1,430 @@
+//
+// File : libkvimy.cpp
+// Creation date : Mon Jul 1 02:46:49 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_module.h"
+
+#include "kvi_console.h"
+
+#include "kvi_app.h"
+#include "kvi_locale.h"
+#include "kvi_ircconnection.h"
+#include "kvi_ircconnectionuserinfo.h"
+#include "kvi_ircconnectionserverinfo.h"
+#include "kvi_ircserver.h"
+#include "idle.h"
+Idle* g_pIdle;
+#ifdef COMPILE_NEW_KVS
+#define GET_KVS_CONSOLE \
+ kvs_uint_t uiWnd; \
+ KviConsole *wnd =0; \
+ KVSM_PARAMETERS_BEGIN(c) \
+ KVSM_PARAMETER("context_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uiWnd) \
+ KVSM_PARAMETERS_END(c) \
+ if(!c->parameterList()->count()) \
+ { \
+ if(c->window()->console()) wnd = c->window()->console(); \
+ else c->warning(__tr2qs("This window has no associated irc context")); \
+ } \
+ else \
+ { \
+ wnd = g_pApp->findConsole(uiWnd); \
+ if(!wnd)c->warning(__tr2qs("No such irc context (%d)"),uiWnd); \
+ }
+#endif
+/*
+ @doc: my.nick
+ @type:
+ function
+ @title:
+ $my.nick
+ @short:
+ Returns the current nickname
+ @syntax:
+ <string> $my.nick([irc_context_id:uint])
+ @description:
+ Returns the nickname of the current irc context.[br]
+ If the irc context is not connected then an empty string is returned.[br]
+ If <irc_context_id> is specified this function returns acts as it was called
+ in that irc_context.[br]
+ Note that this function is different from [fnc]$me[/fnc] that will work also in a DCC CHAT.[br]
+*/
+
+
+static bool my_kvs_fnc_nick(KviKvsModuleFunctionCall * c)
+{
+ GET_KVS_CONSOLE
+ if(wnd)
+ {
+ if(wnd->connection())
+ c->returnValue()->setString(wnd->connection()->userInfo()->nickName());
+ }
+ return true;
+}
+
+/*
+ @doc: my.startIdleTimer
+ @type:
+ command
+ @title:
+ my.startIdleTimer
+ @short:
+ Starts a global idle hook
+ @syntax:
+ my.startIdleTimer()
+ @description:
+ Starts a global idle hook. Allows to detect a global user idle time
+*/
+
+static bool my_kvs_cmd_startIdleTimer(KviKvsModuleCommandCall * c)
+{
+ if(!g_pIdle)
+ g_pIdle = new Idle();
+ g_pIdle->start();
+ return true;
+}
+
+/*
+ @doc: my.stopIdleTimer
+ @type:
+ command
+ @title:
+ my.stopIdleTimer
+ @short:
+ Stops a global idle hook
+ @syntax:
+ my.stopIdleTimer()
+ @description:
+ Stops a global idle hook. Allows to detect a global user idle time
+*/
+
+static bool my_kvs_cmd_stopIdleTimer(KviKvsModuleCommandCall * c)
+{
+ if(!g_pIdle) return true;
+ g_pIdle->stop();
+ //delete g_pIdle;
+ return true;
+}
+
+/*
+ @doc: my.globalIdle
+ @type:
+ function
+ @title:
+ $my.globalIdle
+ @short:
+ Returns the current user global idle time
+ @syntax:
+ <int> $my.globalIdle()
+ @description:
+ Returns the current user global idle time
+*/
+
+static bool my_kvs_fnc_globalIdle(KviKvsModuleFunctionCall * c)
+{
+ if(g_pIdle)
+ {
+ c->returnValue()->setInteger(g_pIdle->secondsIdle());
+ } else {
+ c->error(__tr2qs("Global idle timer must be started before using $my.globalIdle function"));
+ }
+ return true;
+}
+
+/*
+ @doc: my.umode
+ @type:
+ function
+ @title:
+ $my.umode
+ @short:
+ Returns the current user mode flags
+ @syntax:
+ <string> $my.umode([irc_context_id:uint])
+ @description:
+ Returns the user mode flags of the current irc context.[br]
+ If the irc context is not connected then an empty string is returned.[br]
+ If <irc_context_id> is specified this function returns acts as it was called
+ in that irc_context.[br]
+*/
+
+static bool my_kvs_fnc_umode(KviKvsModuleFunctionCall * c)
+{
+ GET_KVS_CONSOLE
+ if(wnd)
+ {
+ if(wnd->connection())
+ c->returnValue()->setString(wnd->connection()->userInfo()->userMode());
+ }
+ return true;
+}
+
+/*
+ @doc: my.user
+ @type:
+ function
+ @title:
+ $my.user
+ @short:
+ Returns the current username
+ @syntax:
+ <string> $my.user([irc_context_id:uint])
+ @description:
+ Returns the username of the current irc context.[br]
+ If the irc context is not connected then an empty string is returned.[br]
+ If <irc_context_id> is specified this function returns acts as it was called
+ in that irc_context.[br]
+*/
+
+static bool my_kvs_fnc_user(KviKvsModuleFunctionCall * c)
+{
+ GET_KVS_CONSOLE
+ if(wnd)
+ {
+ if(wnd->connection())
+ c->returnValue()->setString(wnd->connection()->userInfo()->userName());
+ }
+ return true;
+}
+
+/*
+ @doc: my.host
+ @type:
+ function
+ @title:
+ $my.host
+ @short:
+ Returns the current hostname
+ @syntax:
+ <string> $my.host([irc_context_id:uint])
+ @description:
+ Returns the hostname of the current irc context as known by the IRC server.[br]
+ If the irc context is not connected then an empty string is returned.[br]
+ If <irc_context_id> is specified this function returns acts as it was called
+ in that irc_context.[br]
+*/
+
+
+static bool my_kvs_fnc_host(KviKvsModuleFunctionCall * c)
+{
+ GET_KVS_CONSOLE
+ if(wnd)
+ {
+ if(wnd->connection())
+ c->returnValue()->setString(wnd->connection()->userInfo()->hostName());
+ }
+ return true;
+}
+
+/*
+ @doc: my.ip
+ @type:
+ function
+ @title:
+ $my.ip
+ @short:
+ Returns the current ip address
+ @syntax:
+ <string> $my.ip([irc_context_id:uint])
+ @description:
+ Returns the ip address of the current irc context as known by the IRC server.[br]
+ The ip address is resolved as soon as the hostname is received from the server.
+ If the hostname is masked or there is an error in the DNS lookup then
+ you may get the real local host ip address as determined at connection startup.[br]
+ If the irc context is not connected then an empty string is returned.[br]
+ If <irc_context_id> is specified this function returns acts as it was called
+ in that irc_context.[br]
+*/
+
+
+static bool my_kvs_fnc_ip(KviKvsModuleFunctionCall * c)
+{
+ GET_KVS_CONSOLE
+ if(wnd)
+ {
+ if(wnd->connection())
+ c->returnValue()->setString(wnd->connection()->userInfo()->hostIp());
+ }
+ return true;
+}
+
+/*
+ @doc: my.serverIsIPV6
+ @type:
+ function
+ @title:
+ $my.serverIsSSL
+ @short:
+ Returns 1 if the current server connection use IPV6.
+ @syntax:
+ <boolean> $my.serverIsIPV6([irc_context_id:uint])
+ @description:
+ Returns 1 if the server connection use IPV6.[br]
+ If the irc context is not connected then an empty string is returned.[br]
+ If <irc_context_id> is specified this function returns acts as it was called
+ in that irc_context.[br]
+*/
+
+static bool my_kvs_fnc_serverIsIPV6(KviKvsModuleFunctionCall * c)
+{
+
+ GET_KVS_CONSOLE
+ if(wnd)
+ {
+ if(wnd->connection())
+ c->returnValue()->setBoolean(wnd->connection()->server()->isIpV6());
+ }
+ return true;
+}
+
+
+/*
+ @doc: my.serverIsSSL
+ @type:
+ function
+ @title:
+ $my.serverIsSSL
+ @short:
+ Returns 1 if the current server connection use SSL.
+ @syntax:
+ <boolean> $my.serverIsSSL([irc_context_id:uint])
+ @description:
+ Returns 1 if the server connection use SSL.[br]
+ If the irc context is not connected then an empty string is returned.[br]
+ If <irc_context_id> is specified this function returns acts as it was called
+ in that irc_context.[br]
+*/
+
+static bool my_kvs_fnc_serverIsSSL(KviKvsModuleFunctionCall * c)
+{
+
+ GET_KVS_CONSOLE
+ if(wnd)
+ {
+ if(wnd->connection())
+ c->returnValue()->setBoolean(wnd->connection()->socket()->usingSSL());
+ }
+ return true;
+}
+
+/*
+ @doc: my.server
+ @type:
+ function
+ @title:
+ $my.server
+ @short:
+ Returns the current server name
+ @syntax:
+ <string> $my.server([irc_context_id:uint])
+ @description:
+ Returns the server name of the current irc context.[br]
+ If the irc context is not connected then an empty string is returned.[br]
+ If <irc_context_id> is specified this function returns acts as it was called
+ in that irc_context.[br]
+ Please note that this function returns the name of the server as reported
+ by the server itself. Some servers report a bogus value for this field.
+ You should take a look at $context.serverIpAddress or $context.serverHostName
+ if you want a value that can be used to really reconnect to this server.
+*/
+
+static bool my_kvs_fnc_server(KviKvsModuleFunctionCall * c)
+{
+ GET_KVS_CONSOLE
+ if(wnd)
+ {
+ if(wnd->connection())
+ c->returnValue()->setString(wnd->connection()->serverInfo()->name());
+ }
+ return true;
+}
+
+/*
+ @doc: my.network
+ @type:
+ function
+ @title:
+ $my.network
+ @short:
+ Returns the current network name
+ @syntax:
+ <string> $my.network([irc_context_id:uint])
+ @description:
+ Returns the network name of the current irc context.[br]
+ If the irc context is not connected then an empty string is returned.[br]
+ If <irc_context_id> is specified this function returns acts as it was called
+ in that irc_context.[br]
+*/
+
+static bool my_kvs_fnc_network(KviKvsModuleFunctionCall * c)
+{
+ GET_KVS_CONSOLE
+ if(wnd)
+ {
+ if(wnd->connection())
+ c->returnValue()->setString(wnd->currentNetworkName().utf8().data());
+ }
+ return true;
+}
+
+static bool my_module_init(KviModule * m)
+{
+ g_pIdle = 0;
+ KVSM_REGISTER_FUNCTION(m,"nick",my_kvs_fnc_nick);
+ KVSM_REGISTER_FUNCTION(m,"user",my_kvs_fnc_user);
+ KVSM_REGISTER_FUNCTION(m,"host",my_kvs_fnc_host);
+ KVSM_REGISTER_FUNCTION(m,"ip",my_kvs_fnc_ip);
+ KVSM_REGISTER_FUNCTION(m,"server",my_kvs_fnc_server);
+ KVSM_REGISTER_FUNCTION(m,"network",my_kvs_fnc_network);
+ KVSM_REGISTER_FUNCTION(m,"umode",my_kvs_fnc_umode);
+ KVSM_REGISTER_FUNCTION(m,"serverIsSSL",my_kvs_fnc_serverIsSSL);
+ KVSM_REGISTER_FUNCTION(m,"serverIsIPV6",my_kvs_fnc_serverIsIPV6);
+
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"stopIdleTimer",my_kvs_cmd_stopIdleTimer);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"startIdleTimer",my_kvs_cmd_startIdleTimer);
+ return true;
+}
+
+static bool my_module_cleanup(KviModule *m)
+{
+ if(g_pIdle)
+ delete g_pIdle;
+ g_pIdle = 0;
+ return true;
+}
+
+static bool my_module_can_unload(KviModule *)
+{
+ return !g_pIdle;
+}
+
+KVIRC_MODULE(
+ "My", // module name
+ "1.0.0", // module version
+ "Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot net)" \
+ " (C) 2005 Tonino Imbesi (grifisx at barmes dot net)" \
+ " (C) 2005 Alessandro Carbone (noldor at barmes dot net)", // author & (C)
+ "Scripting irc-context related functions",
+ my_module_init,
+ my_module_can_unload,
+ 0,
+ my_module_cleanup
+)
diff --git a/src/modules/notifier/Makefile.am b/src/modules/notifier/Makefile.am
new file mode 100644
index 00000000..59639aca
--- /dev/null
+++ b/src/modules/notifier/Makefile.am
@@ -0,0 +1,44 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+SUBDIRS = pics
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkvinotifier.la
+
+libkvinotifier_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkvinotifier_la_SOURCES = libkvinotifier.cpp \
+ notifierwindow.cpp \
+ notifiermessage.cpp \
+ notifierwindowtabs.cpp \
+ notifierwindowbody.cpp \
+ notifierwindowborder.cpp \
+ notifierwindowprogressbar.cpp
+
+libkvinotifier_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+noinst_HEADERS= \
+ notifiersettings.h \
+ notifierwindow.h \
+ notifiermessage.h \
+ notifierwindowtabs.h \
+ notifierwindowbody.h \
+ notifierwindowborder.h \
+ notifierwindowprogressbar.h
+
+confdir = $(configmodulesdir)
+
+conf_DATA = libkvinotifier.kvc
+
+EXTRA_DIST = $(conf_DATA)
+
+m_%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
+
+notifierwindow.cpp: m_notifierwindow.moc
+notifierwindowtabs.cpp: m_notifierwindowtabs.moc
+
diff --git a/src/modules/notifier/libkvinotifier.cpp b/src/modules/notifier/libkvinotifier.cpp
new file mode 100644
index 00000000..edc27f0f
--- /dev/null
+++ b/src/modules/notifier/libkvinotifier.cpp
@@ -0,0 +1,323 @@
+//==================================================================================
+//
+// File : libkvinotifier.cpp
+// Creation date : Tue Jul 7 2004 20:21:12 CEST by Szymon Stefanek
+//
+// Copyright (C) 2005 Iacopo Palazzi < iakko(at)siena(dot)linux(dot)it >
+//
+// 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 opinion) 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.
+//
+//==================================================================================
+
+#include "kvi_module.h"
+
+
+#include "notifierwindow.h"
+#include "notifiermessage.h"
+
+#include "kvi_kvs_variant.h"
+#include "kvi_app.h"
+#include "kvi_frame.h"
+#include "kvi_window.h"
+#include "kvi_locale.h"
+#include "kvi_iconmanager.h"
+#include "kvi_time.h"
+#include "kvi_options.h"
+
+#include <qsplitter.h>
+
+KviNotifierWindow * g_pNotifierWindow = 0;
+kvi_time_t g_tNotifierDisabledUntil = 0;
+
+/*
+ @doc: notifier.message
+ @type:
+ command
+ @title:
+ notifier.message
+ @short:
+ Adds a message to the notifier window
+ @syntax:
+ notifier.message [-q|quiet] [-n|noanim] [-w[=<window_id:string>]!] [-i=<image_id:string>] [-t=<timeout:integer>] <messag:string>
+ @description:
+ Adds a message to the notifier window.
+ The notifier window is shown (if not already visible)
+ unless the -q switch is present.
+ The new message becomes the current message of the notifier
+ unless the user is already typing in the input window
+ and the typed message would be directed to a different window.
+ In that case the message is appended at the end of the
+ message queue and the user will be able to scroll to it
+ by using the proper notifier buttons.[br]
+ The &lt;message&gt; text can contain simple html tags: basically you are
+ allowed to use &lt;b&gt; and &lt;i&gt;. The usage of other
+ tags is possible but is discouraged since it tends to
+ mess up the message display. In particular you should avoid
+ any color and/or font specification since the notifier is
+ skinnable and you don't know which color will result in a visible text.
+ [b]Please note that the user can forcibly disable the notifier
+ for a limited period of time (a sort of "don't bug me" option).[/b]
+ @switches:
+ !sw: -n | --noanim
+ Do not animate
+ !sw: -w | --windowid
+ Causes the message gets attacched to the specified window and
+ the user is able to type commands in that window after
+ showing up the notifier input. If the "=&lt;window_id&gt;" part
+ is omitted then the current window is used.[br]
+ !sw: -i | --icon
+ If the -i=&lt;image_id&gt; switch is present then the
+ message has the specified image displayed.
+ See the [doc:image_id]documentation on the image identifier[/doc]
+ for more informations about the image_id parameter.[br]
+ !sw: -q | --quiet
+ If you use -q then you must explicitly call [cmd]notifier.show[/cmd] to
+ show the notifier. If the -n switch is present then
+ the show action will not be animated (the notifier
+ will be shown immediately instead of fading in).
+ Obviously -n has no meaning if -q is used.[br]
+ !sw: -t | --timeout
+ Set the message lifetime to <timeout>
+ Obviously this option has no meaning if the window is not going to be shown.
+ The timeout may be overriddent by new messages but only in the future.
+ If the timeout expires and is not overridden by any new message
+ then the window will be automatically hidden.
+ A zero timeout disables auto-hiding.
+ @seealso:
+ [cmd]notifier.show[/cmd] [cmd]notifier.hide[/cmd] [fnc]$notifier.isEnabled[/fnc]()
+ @examples:
+ [example]
+ notifier.message Hello world!
+ [cmd]notifier.hide[/cmd]
+ notifier.message -q This is a hidden message!
+ notifier.message -q -i=14 This is a second hidden message with an icon
+ [cmd]notifier.show[/cmd]
+ notifier.message -w This message has the current window associated
+ notifier.message -w=[fnc]$window[/fnc] This is equivalent to the above
+ notifier.message &lt;b&gt;Bold text&lt;/b&gt; and normal text
+ [cmd]notifier.hide[/cmd]
+ notifier.message -t=10 This message will be shown only for 10 seconds
+ [/example]
+*/
+
+static bool notifier_kvs_cmd_message(KviKvsModuleCommandCall * c)
+{
+ QString szMessage;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("message",KVS_PT_STRING,0,szMessage)
+ KVSM_PARAMETERS_END(c)
+
+ if(!g_pNotifierWindow)
+ g_pNotifierWindow = new KviNotifierWindow();
+
+ QString szIco="";
+ QString szWnd="";
+
+ KviWindow * pWnd = c->window();
+
+ if(c->hasSwitch('w',"window_id"))
+ {
+ c->switches()->getAsStringIfExisting('w',"window_id",szWnd);
+ if(!szWnd.isEmpty())
+ {
+ pWnd=g_pApp->findWindow(szWnd);
+ if(!pWnd)
+ c->warning(__tr2qs_ctx("The specified window does not exist","notifier"));
+ }
+ }
+ c->switches()->getAsStringIfExisting('i',"icon",szIco);
+ kvs_int_t uTime=0;
+ if(c->hasSwitch('t',"timeout"))
+ {
+ KviKvsVariant *time=c->getSwitch('t',"timeout");
+ if(time)
+ {
+ bool bOk=time->asInteger(uTime);
+ if(!bOk)
+ {
+ uTime = 0;
+ c->warning(__tr2qs_ctx("The specified timeout is not valid, assuming 0","notifier"));
+ }
+ } else {
+ c->warning(__tr2qs_ctx("The -t switch expects a timeout in seconds","notifier"));
+ }
+ }
+
+ g_pNotifierWindow->addMessage(pWnd,szIco,szMessage,uTime);
+
+ if(!c->hasSwitch('q',"quiet"))
+ g_pNotifierWindow->doShow(!(c->hasSwitch('n',"new")));
+ return true;
+}
+
+/*
+ @doc: notifier.hide
+ @type:
+ command
+ @title:
+ notifier.hide
+ @short:
+ Hides the notifier window
+ @syntax:
+ notifier.hide [-n|--noanim]
+ @switches:
+ !sw: -n
+ Causes the hide operation is not animated.
+ @description:
+ Hide the notifier window
+ [b]Please note that the user can forcibly disable the notifier
+ for a limited period of time (a sort of "don't bug me" option).[/b]
+ @seealso:
+ [cmd]notifier.show[/cmd] [cmd]notifier.message[/cmd] [fnc]$notifier.isEnabled[/fnc]
+*/
+
+static bool notifier_kvs_cmd_hide(KviKvsModuleCommandCall * c)
+{
+ if(g_pNotifierWindow) g_pNotifierWindow->doHide(!(c->hasSwitch('n',"notanimated")));
+ return true;
+}
+
+/*
+ @doc: notifier.show
+ @type:
+ command
+ @title:
+ notifier.show
+ @short:
+ Shows the notifier window
+ @syntax:
+ notifier.show [-n|--noanim]
+ @switches:
+ !sw: -n
+ Disables the animation
+ @description:
+ Shows the notifier window if it is not already visible
+ If the -n switch is present then the show operation is
+ not animated.[br]
+ The notifier is shown ONLY if it contains some messages.
+ [b]Please note that the user can forcibly disable the notifier
+ for a limited period of time (a sort of "don't bug me" option).[/b]
+ @seealso:
+ [cmd]notifier.hide[/cmd] [cmd]notifier.message[/cmd] [fnc]$notifier.isEnabled[/fnc]
+*/
+
+static bool notifier_kvs_cmd_show(KviKvsModuleCommandCall * c)
+{
+ if(!g_pNotifierWindow)return true;
+ if(!g_pNotifierWindow->countTabs())return true;
+
+ g_pNotifierWindow->setDisableHideOnMainWindowGotAttention(true);
+ g_pNotifierWindow->doShow(!(c->hasSwitch('n',"noanim")));
+
+ return true;
+}
+/*
+ @doc: notifier.isEnabled
+ @type:
+ function
+ @title:
+ $notifier.isEnabled
+ @short:
+ Returns 1 if the notifier window is enabled
+ @syntax:
+ <boolean> $notifier.isEnabled
+ @description:
+ Returns 1 if the notifier window is enabled and 0 otherwise.
+ The user can forcibly disable the notifier as a sort of "don't bug me"
+ feature for a limited period of time. When the notifier
+ is disabled the messages sent to it will not be shown.[br]
+ The only method that you (scripter) can use to forcibly
+ re-enable the notifier is to unload the module and
+ reload it...but [b]DON'T do it[/b] :)[br]
+ There is also a global option that allows forcibly disabling
+ the notifier forever, this option could be overridden with [cmd]option[/cmd]
+ instead.. but again [b]DON'T do it[/b] :)[br]
+
+*/
+
+static bool notifier_kvs_fnc_isEnabled(KviKvsModuleFunctionCall * c)
+{
+ bool bCheck;
+ if(KVI_OPTION_BOOL(KviOption_boolForciblyDisableNotifier))
+ bCheck=false;
+ else
+ bCheck=g_tNotifierDisabledUntil < kvi_unixTime();
+ c->returnValue()->setBoolean(bCheck);
+ return true;
+}
+
+static bool notifier_module_init(KviModule * m)
+{
+
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"message",notifier_kvs_cmd_message);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"show",notifier_kvs_cmd_show);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"hide",notifier_kvs_cmd_hide);
+ KVSM_REGISTER_FUNCTION(m,"isEnabled",notifier_kvs_fnc_isEnabled);
+
+ return true;
+}
+
+static bool notifier_module_cleanup(KviModule *m)
+{
+ if(g_pNotifierWindow)
+ {
+ delete g_pNotifierWindow;
+ g_pNotifierWindow = 0;
+ }
+ return true;
+}
+
+static bool notifier_module_can_unload(KviModule *m)
+{
+ return (!g_pNotifierWindow);
+}
+
+typedef struct _NotifierMessageSupaDupaParameterStruct
+{
+ KviWindow * pWindow;
+ QString szIcon;
+ QString szMessage;
+ unsigned int uMessageLifetime; // 0 means no hide
+} NotifierMessageSupaDupaParameterStruct;
+
+static bool notifier_module_ctrl(KviModule *,const char *operation,void *param)
+{
+ if(kvi_strEqualCI("notifier::message",operation))
+ {
+ NotifierMessageSupaDupaParameterStruct * p = (NotifierMessageSupaDupaParameterStruct *)param;
+ if(!p)return false;
+
+ if(!g_pNotifierWindow)
+ g_pNotifierWindow = new KviNotifierWindow();
+
+ g_pNotifierWindow->addMessage(p->pWindow,p->szIcon,p->szMessage,p->uMessageLifetime);
+ g_pNotifierWindow->doShow(KVI_OPTION_BOOL(KviOption_boolDisableNotifierFadein)?false:true);
+
+ return true;
+ }
+ return false;
+}
+
+KVIRC_MODULE(
+ "Notifier",
+ "2.0.0",
+ "Copyright (C) 2005:\n" \
+ " Iacopo Palazzi (iakko at siena dot linux dot it)",
+ "KVIrc Client - Taskbar Notifier",
+ notifier_module_init,
+ notifier_module_can_unload,
+ notifier_module_ctrl,
+ notifier_module_cleanup
+)
diff --git a/src/modules/notifier/libkvinotifier.kvc b/src/modules/notifier/libkvinotifier.kvc
new file mode 100644
index 00000000..4625fe3b
--- /dev/null
+++ b/src/modules/notifier/libkvinotifier.kvc
@@ -0,0 +1,28 @@
+[NotifierSkin]
+CloseX=233
+CloseY=5
+PrevX=233
+PrevY=26
+NextX=233
+NextY=82
+WriteX=233
+WriteY=103
+TextRect=6,22,223,97
+TitleRect=6,5,223,20
+TextFontFamily=Arial
+TextFontSize=9
+TitleFontFamily=Arial
+TitleFontSize=9
+CurTextColor=45,0,0
+OldTextColor1=40,20,20
+OldTextColor2=40,40,40
+OldTextColor3=60,60,60
+OldTextColor4=85,85,85
+OldTextColor5=90,90,90
+OldTextColor6=95,95,95
+HistoricTextColor=125,125,125
+TitleColor=120,70,70
+InputFontFamily=Arial
+InputFontSize=9
+InputHeight=19
+BlinkTimeout=650
diff --git a/src/modules/notifier/notifiermessage.cpp b/src/modules/notifier/notifiermessage.cpp
new file mode 100644
index 00000000..1e91b5de
--- /dev/null
+++ b/src/modules/notifier/notifiermessage.cpp
@@ -0,0 +1,107 @@
+//=============================================================================
+//
+// File : notifiermessage.cpp
+// Created on mar 02 nov 2004 02:41:18 by Iacopo
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2004 Iacopo <iakko@siena.linux.it>
+//
+// 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 opinion) 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.
+//
+//=============================================================================
+
+#include "notifiermessage.h"
+#include "notifierwindow.h"
+
+#include "kvi_iconmanager.h"
+#include "kvi_config.h"
+#include "kvi_app.h"
+#include "kvi_window.h"
+
+#include "kvi_locale.h"
+#include "kvi_frame.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_options.h"
+
+/*
+#ifdef COMPILE_ON_WINDOWS
+ #include <windows.h>
+#endif
+
+#ifdef COMPILE_KDE_SUPPORT
+ #include <netwm.h>
+#endif
+*/
+
+#include <qapplication.h>
+#include <qpainter.h>
+#include <qimage.h>
+#include <qdesktopwidget.h>
+#include <qtooltip.h>
+
+#ifdef COMPILE_USE_QT4
+ #define QPopupMenu Q3PopupMenu
+ #include <q3popupmenu.h>
+#else
+ #include <qpopupmenu.h>
+#endif
+
+extern kvi_time_t g_tNotifierDisabledUntil;
+
+KviNotifierMessage::KviNotifierMessage(KviNotifierWindow * pNotifierWindow, QPixmap * pImage, const QString &szText)
+{
+ m_pText = new QSimpleRichText(KviMircCntrl::stripControlBytes(szText),pNotifierWindow->defaultFont());
+ m_pText->setWidth(pNotifierWindow->textWidth());
+ m_pImage = pImage;
+ m_bHistoric = false;
+}
+
+KviNotifierMessage::~KviNotifierMessage()
+{
+ delete m_pText;
+ if(m_pImage)delete m_pImage;
+}
+
+static void increase_transparency(QImage &buffer,QImage &srcimg,int iDivisor)
+{
+ buffer.create(srcimg.width(),srcimg.height(),32);
+ buffer.setAlphaBuffer(true);
+
+ for(int y = 0;y < buffer.height();y++)
+ {
+ QRgb * dst = (QRgb *)buffer.scanLine(y);
+ QRgb * end = dst + buffer.width();
+ QRgb * src = (QRgb *)srcimg.scanLine(y);
+
+ while(dst < end)
+ {
+ *dst = qRgba(qRed(*src),qGreen(*src),qBlue(*src),qAlpha(*src) / iDivisor);
+ dst++;
+ src++;
+ }
+ }
+}
+
+void KviNotifierMessage::setHistoric()
+{
+ m_bHistoric = true;
+ if(!m_pImage)return;
+ if(!m_pImage->hasAlphaChannel())return;
+ QImage tmp;
+ QImage out = m_pImage->convertToImage();
+ increase_transparency(tmp,out,2);
+ m_pImage->convertFromImage(tmp);
+}
+
diff --git a/src/modules/notifier/notifiermessage.h b/src/modules/notifier/notifiermessage.h
new file mode 100644
index 00000000..da4a6df2
--- /dev/null
+++ b/src/modules/notifier/notifiermessage.h
@@ -0,0 +1,97 @@
+#ifndef _NOTIFIERMESSAGE_H_
+#define _NOTIFIERMESSAGE_H_
+//=============================================================================
+//
+// File : notifiermessage.h
+// Created on mar 02 nov 2004 02:41:18 by
+// Iacopo Palazzi < iakko(at)siena(dot)linux(dot)it >
+//
+// This file is part of the KVIrc distribution
+// Copyright (C) 2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+
+#include "kvi_settings.h"
+
+#include <qwidget.h>
+#include <qrect.h>
+#include <qtimer.h>
+#include <qpixmap.h>
+#include <qimage.h>
+#include <qfont.h>
+#include <qcolor.h>
+#include <qlineedit.h>
+
+#include "kvi_qstring.h"
+#include "kvi_pointerlist.h"
+#include "kvi_time.h"
+
+#ifdef COMPILE_USE_QT4
+ #define QSimpleRichText Q3SimpleRichText
+ #define QPopupMenu Q3PopupMenu
+ #include <q3popupmenu.h>
+ #include <q3simplerichtext.h>
+#else
+ #include <qsimplerichtext.h>
+#endif
+
+class KviWindow;
+class KviNotifierWindow;
+
+class QPopupMenu;
+
+class KviNotifierMessage
+{
+ friend class KviNotifierWindow;
+public:
+ KviNotifierMessage(KviNotifierWindow * pNotifierWindow, QPixmap * pImage, const QString &szText);
+ ~KviNotifierMessage();
+
+// ================================
+// Put members declaration below...
+// ================================
+private:
+
+public:
+
+protected:
+ KviWindow * m_pWindow;
+ QPixmap * m_pImage;
+ QSimpleRichText * m_pText;
+ bool m_bHistoric;
+
+// ================================
+// Put methods declaration below...
+// ================================
+private:
+
+public:
+ bool historic(){ return m_bHistoric; };
+ void setHistoric();
+ void setWindow(KviWindow * pWnd){ m_pWindow = pWnd; };
+ QPixmap * image(){ return m_pImage; };
+ QSimpleRichText * text(){ return m_pText; };
+
+protected:
+
+
+};
+
+#define NUM_OLD_COLORS 6
+
+#endif //!_NOTIFIERMESSAGE_H_
diff --git a/src/modules/notifier/notifiersettings.h b/src/modules/notifier/notifiersettings.h
new file mode 100644
index 00000000..b694dc59
--- /dev/null
+++ b/src/modules/notifier/notifiersettings.h
@@ -0,0 +1,66 @@
+#ifndef _NOTIFIER_SETTINGS_H_
+#define _NOTIFIER_SETTINGS_H_
+//=============================================================================
+//
+// File : kvinotifierwindowcaption.h
+// Created on gio 30 dic 2004 21:21:33 by Iacopo Palazzi
+//
+// This file is part of the Notifier - KVIrc Distribution distribution
+// Copyright (C) 2004 Iacopo Palazzi < iakko(at)siena(dot)linux(dot)it >
+//
+// 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 opinion) 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.
+//
+//=============================================================================
+
+// Global settings for KviNotifier
+
+
+
+#define WDG_MIN_WIDTH 370
+#define WDG_MIN_HEIGHT 150
+#define WDG_BORDER_THICKNESS 5
+#define SPACING 2
+
+#define WDG_ICON_OUT 0
+#define WDG_ICON_OVER 1
+#define WDG_ICON_CLICKED 2
+#define WDG_ICON_ON 3
+#define WDG_ICON_OFF 4
+
+#define NTF_TABS_FONT_BASELINE 8
+
+#define MAX_MESSAGES_IN_WINDOW 20
+// keep hidden messages for 600 seconds : 10 min
+#define MAX_MESSAGE_LIFETIME 600
+
+#define OPACITY_STEP 0.07
+
+#define NUM_OLD_COLORS 6
+
+#define WDG_UPSX 1
+#define WDG_UP 2
+#define WDG_UPDX 3
+#define WDG_DWNSX 4
+#define WDG_DWN 5
+#define WDG_DWNDX 6
+#define WDG_SX 7
+#define WDG_DX 8
+
+#define m_mac_bkgColor QColor(236,233,216) // Light-brown color of notifier background widget
+
+enum State { Hidden, Showing, Visible, Hiding , FocusingOff, FocusingOn };
+enum TabState { Normal, Highlighted, Changed };
+
+#endif //_NOTIFIER_SETTINGS_H_
diff --git a/src/modules/notifier/notifierwindow.cpp b/src/modules/notifier/notifierwindow.cpp
new file mode 100644
index 00000000..d275be23
--- /dev/null
+++ b/src/modules/notifier/notifierwindow.cpp
@@ -0,0 +1,1427 @@
+//==================================================================================
+//
+// File : notifierwindow.cpp
+// Creation date : Tue Jul 6 2004 20:25:12 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2004 Iacopo Palazzi < iakko(at)siena.linux.it >
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the linkss of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) 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.
+//
+//==================================================================================
+#include "kvi_settings.h"
+
+#ifdef COMPILE_USE_QT4
+ #define QPopupMenu Q3PopupMenu
+ #define QSimpleRichText Q3SimpleRichText
+
+ #include <q3popupmenu.h>
+ #include <q3simplerichtext.h>
+#else
+ #include <qpopupmenu.h>
+ #include <qsimplerichtext.h>
+#endif
+
+ #include <qpainter.h>
+
+#include "notifiermessage.h"
+#include "notifierwindow.h"
+
+#include "kvi_iconmanager.h"
+#include "kvi_config.h"
+#include "kvi_app.h"
+#include "kvi_window.h"
+
+#include "kvi_locale.h"
+#include "kvi_frame.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_options.h"
+#include "kvi_userinput.h"
+
+#include <qapplication.h>
+#include <qimage.h>
+#include <qdesktopwidget.h>
+#include <qtooltip.h>
+#include <qevent.h>
+#include <qpen.h>
+#include <qfontmetrics.h>
+#include <qregexp.h>
+
+#include "notifierwindowbody.h"
+#include "notifierwindowborder.h"
+#include "notifierwindowprogressbar.h"
+#include "notifierwindowtabs.h"
+
+extern KviNotifierWindow * g_pNotifierWindow;
+
+KviNotifierWindow::KviNotifierWindow()
+: QWidget(0,"kvirc_notifier_window",
+#ifdef COMPILE_ON_WINDOWS
+ Qt::WStyle_Customize |
+ Qt::WStyle_NoBorder |
+ Qt::WStyle_Tool |
+ Qt::WStyle_StaysOnTop)
+#else
+ Qt::WStyle_Customize |
+ Qt::WStyle_NoBorder |
+#ifndef Q_OS_MACX
+ Qt::WStyle_Tool |
+ Qt::WX11BypassWM |
+#endif
+ Qt::WStyle_StaysOnTop)
+#endif
+{
+
+ g_pNotifierWindow = this;
+
+ m_eState = Hidden;
+ m_dOpacity = 0.0;
+ m_pShowHideTimer = 0;
+ m_pBlinkTimer = 0;
+ m_tAutoHideAt = 0;
+ m_tStartedAt=0;
+ m_pAutoHideTimer = 0;
+ m_pProgressTimer = 0;
+
+ m_pWndBorder = new KviNotifierWindowBorder();
+
+ reloadImages();
+
+ KviStr buffer;
+ g_pApp->getReadOnlyConfigPath(buffer,"libkvinotifier.kvc",KviApp::ConfigPlugins,true);
+
+ KviConfig cfg(buffer.ptr(),KviConfig::Read);
+
+ cfg.setGroup("NotifierSkin");
+
+ QString szFamily = cfg.readEntry("TextFontFamily","Arial");
+ m_pDefaultFont = new QFont(szFamily,cfg.readIntEntry("TextFontSize",9));
+ szFamily = cfg.readEntry("TitleFontFamily","Arial");
+ m_pTitleFont = new QFont(szFamily,cfg.readIntEntry("TitleFontSize",9));
+
+ m_clrCurText = cfg.readColorEntry("CurTextColor",QColor(40,0,0));
+ m_clrHistoricText = cfg.readColorEntry("HistoricTextColor",QColor(125,125,125));
+ m_clrTitle = QColor(255,255,255); //cfg.readColorEntry("TitleColor",QColor(0,0,0));
+ for(int i=0;i<NUM_OLD_COLORS;i++)
+ {
+ KviStr szKey;
+ szKey.sprintf("OldTextColor%d",i + 1);
+ m_clrOldText[i] = cfg.readColorEntry(szKey.ptr(),QColor(90,90,90));
+ }
+
+ m_iBlinkTimeout = cfg.readIntEntry("BlinkTimeout",650);
+ if(m_iBlinkTimeout < 100)m_iBlinkTimeout = 100;
+ m_iInputHeight = cfg.readIntEntry("InputHeight",20);
+ if(m_iInputHeight < 10)m_iInputHeight = 10;
+
+ setBackgroundMode(Qt::NoBackground);
+#ifdef COMPILE_USE_QT4
+ setFocusPolicy(Qt::NoFocus);
+#else
+ setFocusPolicy(QWidget::NoFocus);
+#endif
+ setMouseTracking(true);
+ //setCursor(m_cursor);
+
+ hide();
+ m_pLineEdit = new QLineEdit(this);
+ m_pLineEdit->setGeometry(0,0,0,0);
+ m_pLineEdit->hide();
+ m_pLineEdit->installEventFilter(this);
+ connect(m_pLineEdit,SIGNAL(returnPressed()),this,SLOT(returnPressed()));
+
+ szFamily = cfg.readEntry("InputFontFamily","Arial");
+ m_pLineEdit->setFont(QFont(szFamily,cfg.readIntEntry("InputFontSize",9)));
+
+ m_bBlinkOn = false;
+
+ m_bCloseDown = false;
+ m_bPrevDown = false;
+ m_bNextDown = false;
+ m_bWriteDown = false;
+
+ m_bKeyShiftPressed = false;
+
+ m_bLeftButtonIsPressed = false;
+ m_bDiagonalResizing = false;
+ m_bResizing = false;
+
+ m_pContextPopup = 0;
+ m_pDisablePopup = 0;
+
+ m_bDragging = false;
+
+ m_bDisableHideOnMainWindowGotAttention = false;
+
+ // Positioning the notifier bottom-right
+ int iWidth = m_pixBackground.width();
+ int iHeight = m_pixBackground.height();
+ QDesktopWidget * w = QApplication::desktop();
+ QRect r = w->availableGeometry(w->primaryScreen()); //w->screenGeometry(w->primaryScreen());
+
+ /*debug("r.x(),r.y(): %d,%d",r.x(),r.y());
+ debug("r.width(),r.height(): %d,%d",r.width(),r.height());*/
+
+ m_wndRect.setRect( r.x() + r.width() - (iWidth + SPACING), r.y() + r.height() - (iHeight + SPACING), iWidth, iHeight );
+
+ //m_pWndBorder = new KviNotifierWindowBorder();
+ m_pWndTabs = new KviNotifierWindowTabs(m_pWndBorder->tabsRect());
+ m_pWndBody = new KviNotifierWindowBody(m_pWndBorder->bodyRect());
+
+ m_pProgressBar = new KviNotifierWindowProgressBar(m_pWndBorder->progressRect());
+
+ // FIXME: Ugly global-font initialization..
+ QFontMetrics titleFontMetrics(*m_pTitleFont);
+ m_pWndBorder->centerTitle(titleFontMetrics.height());
+
+ connect(g_pApp,SIGNAL(reloadImages()),this,SLOT(reloadImages()));
+}
+
+KviNotifierWindow::~KviNotifierWindow()
+{
+ stopShowHideTimer();
+ stopBlinkTimer();
+ stopAutoHideTimer();
+ delete m_pDefaultFont;
+ delete m_pTitleFont;
+ delete m_pWndBorder;
+ delete m_pWndTabs;
+ delete m_pWndBody;
+}
+
+int KviNotifierWindow::countTabs() {
+ return m_pWndTabs->count();
+}
+
+void KviNotifierWindow::reloadImages()
+{
+ m_pixBackground.resize(WDG_MIN_WIDTH,WDG_MIN_HEIGHT);
+ m_pixBackground.fill();
+ m_pixBackgroundHighlighted.resize(m_pixBackground.size());
+ m_pixBackgroundHighlighted.fill();
+
+ m_pWndBorder->resize(m_pixBackground.size());
+}
+
+
+void KviNotifierWindow::addMessage(KviWindow * pWnd,const QString &szImageId,const QString &szText,unsigned int uMessageTime)
+{
+ QPixmap * pIcon;
+ QString szMessage=szText;
+ szMessage.replace( QRegExp("\r([^\r])*\r([^\r])+\r"), "\\2" );
+ if(szImageId.isEmpty())pIcon = 0;
+ else pIcon = g_pIconManager->getImage(szImageId);
+
+ KviNotifierMessage * m = new KviNotifierMessage(this,pIcon ? new QPixmap(*pIcon) : 0,szMessage);
+
+ m_pWndTabs->addMessage(pWnd, m); // Adds a tab about the sender pWnd
+
+ if(!isActiveWindow())
+ startBlinking();
+
+ if(uMessageTime > 0)
+ {
+ kvi_time_t tAutoHide = kvi_unixTime() + uMessageTime;
+ if(m_tAutoHideAt < tAutoHide)
+ {
+ m_tAutoHideAt = tAutoHide;
+ if(m_eState == Visible)startAutoHideTimer();
+ }
+ } else {
+ // never hide
+ stopAutoHideTimer();
+ m_tAutoHideAt = 0;
+ }
+
+ if(pWnd)
+ {
+ if(pWnd->hasAttention())m_bDisableHideOnMainWindowGotAttention = true;
+ }
+
+ //m_pWndTabs->setCurrentMessage(m);
+ if(isVisible())update();
+ // else the line edit was hidden
+}
+
+
+int KviNotifierWindow::textWidth() {
+ return m_pWndBody->textRect().width() - 20;
+};
+
+void KviNotifierWindow::stopShowHideTimer()
+{
+ if(!m_pShowHideTimer)return;
+ delete m_pShowHideTimer;
+ m_pShowHideTimer = 0;
+}
+
+void KviNotifierWindow::stopBlinkTimer()
+{
+ if(!m_pBlinkTimer)return;
+ delete m_pBlinkTimer;
+ m_pBlinkTimer = 0;
+}
+
+void KviNotifierWindow::stopAutoHideTimer()
+{
+ if(m_pProgressTimer) delete m_pProgressTimer;
+ m_pProgressTimer = 0;
+
+ if(!m_pAutoHideTimer)return;
+ delete m_pAutoHideTimer;
+ m_pAutoHideTimer = 0;
+ m_pProgressBar->setProgress(0);
+}
+
+void KviNotifierWindow::computeRect()
+{
+ int iWidth = m_pixBackground.width();
+ int iHeight = m_pixBackground.height();
+ m_pWndBorder->setGeometry(QPoint(x(),y()), QSize(iWidth,iHeight));
+ update();
+}
+
+void KviNotifierWindow::doShow(bool bDoAnimate)
+{
+ if(KVI_OPTION_BOOL(KviOption_boolForciblyDisableNotifier))return;
+
+ kvi_time_t tNow = kvi_unixTime();
+ if(g_tNotifierDisabledUntil > tNow)return;
+ g_tNotifierDisabledUntil = 0;
+
+ switch(m_eState)
+ {
+ case Showing:
+ // already showing up
+ return;
+ break;
+ case Visible:
+ // already visible
+ return;
+ break;
+ case Hiding:
+ // ops.. hiding!
+ m_eState = Showing;
+ break;
+ case Hidden:
+ stopShowHideTimer();
+ stopBlinkTimer();
+
+ m_bDragging = false;
+ m_bCloseDown = false;
+ m_bPrevDown = false;
+ m_bNextDown = false;
+ m_bWriteDown = false;
+ m_bBlinkOn = false;
+ #if (!defined COMPILE_USE_QT4) || !(defined(COMPILE_USE_QT4) && (defined(COMPILE_ON_WINDOWS) || defined(Q_OS_MACX)))
+ m_imgDesktop = QPixmap::grabWindow(
+ QApplication::desktop()->winId(),
+ m_wndRect.x(),
+ m_wndRect.y(),
+ m_wndRect.width(),
+ m_wndRect.height()).convertToImage();
+ #endif
+ // QPixmap tmp = QPixmap::grabWindow( QApplication::desktop()->winId(),m_wndRect.x(), m_wndRect.y(), m_wndRect.width(), m_wndRect.height());
+ // tmp.save("/root/pix.png","PNG");
+ m_pixForeground.resize(m_pixBackground.size());
+ m_imgBuffer.create(m_pixBackground.width(),m_pixBackground.height(),32);
+ if(bDoAnimate)
+ {
+ m_pShowHideTimer = new QTimer();
+ connect(m_pShowHideTimer,SIGNAL(timeout()),this,SLOT(heartbeat()));
+ m_dOpacity = OPACITY_STEP;
+ m_eState = Showing;
+ m_bCrashShowWorkAround=true;
+ #if defined(COMPILE_USE_QT4) && (defined(COMPILE_ON_WINDOWS) || defined(Q_OS_MACX))
+ setWindowOpacity(m_dOpacity);
+ #endif
+ show();
+ #if defined(COMPILE_USE_QT4) && (defined(COMPILE_ON_WINDOWS) || defined(Q_OS_MACX))
+ m_pShowHideTimer->start(40);
+ #else
+ m_pShowHideTimer->start(100);
+ #endif
+ computeRect();
+ m_bCrashShowWorkAround=false;
+ //show();
+
+ } else {
+ m_dOpacity = 1.0;
+ m_eState = Visible;
+ show();
+ startBlinking();
+ startAutoHideTimer();
+ }
+ break;
+ }
+}
+
+bool KviNotifierWindow::shouldHideIfMainWindowGotAttention()
+{
+ if(m_bDisableHideOnMainWindowGotAttention)return false;
+ KviNotifierWindowTab * t = m_pWndTabs->currentTab();
+ if(!t)return false;
+ if(!t->window())return false;
+ return t->window()->hasAttention();
+}
+
+
+void KviNotifierWindow::heartbeat()
+
+{
+ bool bIncreasing;
+ double targetOpacity = 0; //qt4
+ switch(m_eState)
+ {
+ case Hidden:
+ hideNow();
+ break;
+ case Visible:
+ stopShowHideTimer();
+ m_dOpacity = 1.0;
+ if(!isVisible())show(); //!!!
+ break;
+ case Showing:
+ // if the main window got attention while
+ // showing up then just hide now
+ if(shouldHideIfMainWindowGotAttention())
+ {
+ m_eState = Hiding;
+ } else {
+ m_dOpacity += OPACITY_STEP;
+#ifdef COMPILE_USE_QT4
+ targetOpacity = isActiveWindow() ? KVI_OPTION_UINT(KviOption_uintNotifierActiveTransparency) : KVI_OPTION_UINT(KviOption_uintNotifierInactiveTransparency);
+
+ targetOpacity/=100;
+ if(m_dOpacity >= targetOpacity)
+ {
+ m_dOpacity = targetOpacity;
+#else
+ if(m_dOpacity >= 1.0)
+ {
+ m_dOpacity = 1.0;
+#endif
+ m_eState = Visible;
+ stopShowHideTimer();
+ startBlinking();
+ startAutoHideTimer();
+ }
+
+ if(!isVisible())show(); //!!!
+ if(m_pLineEdit->isVisible())m_pLineEdit->hide();
+ #if defined(COMPILE_USE_QT4) && (defined(COMPILE_ON_WINDOWS) || defined(Q_OS_MACX))
+ setWindowOpacity(m_dOpacity);
+ #endif
+ update();
+
+ }
+ break;
+#ifdef COMPILE_USE_QT4
+ case FocusingOn:
+ targetOpacity = KVI_OPTION_UINT(KviOption_uintNotifierActiveTransparency);
+ targetOpacity/=100;
+ bIncreasing = targetOpacity>m_dOpacity;
+ m_dOpacity += bIncreasing?
+ OPACITY_STEP : -(OPACITY_STEP);
+ if( (bIncreasing && (m_dOpacity >= targetOpacity) ) ||
+ (!bIncreasing && (m_dOpacity <= targetOpacity) )
+ )
+ {
+ m_dOpacity = targetOpacity;
+ m_eState = Visible;
+ stopShowHideTimer();
+ }
+
+ setWindowOpacity(m_dOpacity);
+ break;
+ case FocusingOff:
+ targetOpacity = KVI_OPTION_UINT(KviOption_uintNotifierInactiveTransparency);
+ targetOpacity/=100;
+ bIncreasing = targetOpacity>m_dOpacity;
+ m_dOpacity += bIncreasing ? OPACITY_STEP : -(OPACITY_STEP);
+ //debug("%f %f %i %i",m_dOpacity,targetOpacity,bIncreasing,(m_dOpacity >= targetOpacity));
+ if( (bIncreasing && (m_dOpacity >= targetOpacity) ) ||
+ (!bIncreasing && (m_dOpacity <= targetOpacity) )
+ )
+ {
+ m_dOpacity = targetOpacity;
+ m_eState = Visible;
+ stopShowHideTimer();
+ }
+
+ setWindowOpacity(m_dOpacity);
+ break;
+#endif
+ case Hiding:
+ m_dOpacity -= OPACITY_STEP;
+ #if defined(COMPILE_USE_QT4) && (defined(COMPILE_ON_WINDOWS) || defined(Q_OS_MACX))
+ setWindowOpacity(m_dOpacity);
+ #endif
+ if(m_pLineEdit->isVisible())m_pLineEdit->hide();
+ if(m_dOpacity <= 0.0)hideNow();
+ else update();
+ break;
+ }
+}
+
+void KviNotifierWindow::hideNow()
+{
+ stopBlinkTimer();
+ stopShowHideTimer();
+ stopAutoHideTimer();
+ m_eState = Hidden;
+ m_dOpacity = 0.0;
+ m_tAutoHideAt = 0;
+
+ if(m_pLineEdit->isVisible())m_pLineEdit->hide();
+ hide();//if(isVisible())hide();
+}
+
+void KviNotifierWindow::doHide(bool bDoAnimate)
+{
+ stopAutoHideTimer();
+ switch(m_eState)
+ {
+ case Hiding:
+ // already hiding up
+ if(!bDoAnimate)hideNow();
+ return;
+ break;
+ case Hidden:
+ // already hidden
+ if(isVisible())hideNow(); // !!!
+ return;
+ break;
+ case Showing:
+ // ops.. hiding!
+ if(!bDoAnimate)hideNow();
+ else {
+ // continue animating, but hide
+ m_eState = Hiding;
+ }
+ break;
+ case Visible:
+ stopBlinkTimer();
+ stopShowHideTimer();
+ if(m_pLineEdit->isVisible())m_pLineEdit->hide();
+ if((!bDoAnimate) || (x() != m_pWndBorder->x()) || (y() != m_pWndBorder->y()))
+ {
+
+ //debug ("just hide quickly with notifier x() %d and notifier y() % - WBorderx() %d and WBordery() %d and bDoanimate %d",x(),y(),m_pWndBorder->x(),m_pWndBorder->y(),bDoAnimate);
+ // the user asked to not animate or
+ // the window has been moved and the animation would suck anyway
+ // just hide quickly
+ hideNow();
+ } else {
+ //debug ("starting hide animation notifier x() %d and notifier y() % - WBorderx() %d and WBordery() %d and bDoanimate %d",x(),y(),m_pWndBorder->x(),m_pWndBorder->y(),bDoAnimate);
+ m_pShowHideTimer = new QTimer();
+ connect(m_pShowHideTimer,SIGNAL(timeout()),this,SLOT(heartbeat()));
+ m_dOpacity = 1.0 - OPACITY_STEP;
+ m_eState = Hiding;
+ #if defined(COMPILE_USE_QT4) && (defined(COMPILE_ON_WINDOWS) || defined(Q_OS_MACX))
+ setWindowOpacity(m_dOpacity);
+ update();
+ m_pShowHideTimer->start(40);
+ #else
+ update();
+ m_pShowHideTimer->start(100);
+ #endif
+
+
+ }
+ break;
+ }
+}
+
+void KviNotifierWindow::showEvent(QShowEvent *e)
+{
+ computeRect();
+ setGeometry(m_wndRect); // w_win = w_wndRect
+
+}
+
+void KviNotifierWindow::hideEvent(QHideEvent * e)
+{
+ if (m_bCrashShowWorkAround) return;
+ stopBlinkTimer();
+ stopShowHideTimer();
+ stopAutoHideTimer();
+ m_eState = Hidden; // make sure it's true
+ m_tAutoHideAt = 0; // make sure it's true
+ markAllMessagesAsHistoric();
+ m_bDisableHideOnMainWindowGotAttention = false;
+}
+
+void KviNotifierWindow::startBlinking()
+{
+ stopBlinkTimer();
+ m_bBlinkOn = false;
+
+
+ if(!KVI_OPTION_BOOL(KviOption_boolDisableNotifierFlashing))
+ {
+ m_pBlinkTimer = new QTimer();
+ connect(m_pBlinkTimer,SIGNAL(timeout()),this,SLOT(blink()));
+ m_iBlinkCount = 0;
+ m_pBlinkTimer->start(m_iBlinkTimeout);
+ }
+}
+
+void KviNotifierWindow::startAutoHideTimer()
+{
+ stopAutoHideTimer();
+ m_tStartedAt = kvi_unixTime();
+ m_qtStartedAt.start();
+ if(m_tAutoHideAt <= m_tStartedAt)return;
+
+ int nSecs = m_tAutoHideAt - m_tStartedAt;
+ if(nSecs < 5)nSecs = 5;
+ m_pAutoHideTimer = new QTimer();
+ connect(m_pAutoHideTimer,SIGNAL(timeout()),this,SLOT(autoHide()));
+ m_pAutoHideTimer->start(nSecs * 1000);
+
+ m_pProgressTimer= new QTimer();
+ connect(m_pProgressTimer,SIGNAL(timeout()),this,SLOT(progressUpdate()));
+ m_pProgressTimer->start(60);
+}
+
+void KviNotifierWindow::autoHide()
+{
+ m_tAutoHideAt = 0;
+ stopAutoHideTimer();
+ doHide(true);
+}
+
+void KviNotifierWindow::blink()
+{
+ m_iBlinkCount++;
+ m_bBlinkOn = !m_bBlinkOn;
+
+ if(m_iBlinkCount > 100)
+ {
+ // stop blinking at a certain point and remain highlighted
+ m_bBlinkOn = true;
+ stopBlinkTimer();
+ } else {
+ // if the main window got attention while
+ // showing up then just hide now
+ if(shouldHideIfMainWindowGotAttention())
+ {
+ doHide(false); // don't animate: the background has almost surely changed
+ return;
+ }
+ }
+ update();
+}
+
+void KviNotifierWindow::markAllMessagesAsHistoric()
+{
+ if (!m_pWndTabs) return;
+ m_pWndTabs->markAllMessagesAsHistoric();
+}
+
+
+static void blend_images(QImage &buffer,QImage &background,QImage &foreground,double dValue)
+{
+ for(int y = 0;y < buffer.height();y++)
+ {
+ QRgb * dst = (QRgb *)buffer.scanLine(y);
+ QRgb * end = dst + buffer.width();
+ QRgb * bkg = (QRgb *)background.scanLine(y);
+ QRgb * fgn = (QRgb *)foreground.scanLine(y);
+
+ double dRemaining = 1.0 - dValue;
+
+ while(dst < end)
+ {
+ *dst = qRgb(
+ (int)((qRed(*bkg) * dRemaining) + (qRed(*fgn) * dValue)),
+ (int)((qGreen(*bkg) * dRemaining) + (qGreen(*fgn) * dValue)),
+ (int)((qBlue(*bkg) * dRemaining) + (qBlue(*fgn) * dValue))
+ );
+ dst++;
+ bkg++;
+ fgn++;
+ }
+
+ }
+}
+
+void KviNotifierWindow::paintEvent(QPaintEvent * e)
+{
+
+/*
+ if(m_bBlinkOn)
+ bitBlt(&m_pixForeground,QPoint(0,0),&m_pixBackgroundHighlighted);
+ else
+ bitBlt(&m_pixForeground,QPoint(0,0),&m_pixBackground);
+
+ QPainter p(&m_pixForeground);
+*/
+ redrawWindow();
+ redrawText();
+ if(m_dOpacity < 1.0)
+ {
+ QPainter px(this);
+
+ #if defined(COMPILE_USE_QT4) && (defined(COMPILE_ON_WINDOWS) || defined(Q_OS_MACX))
+ px.drawPixmap(0,0,m_pixForeground);
+ #else
+ QImage temp_image = m_pixForeground.convertToImage();
+ blend_images(m_imgBuffer,m_imgDesktop,temp_image,m_dOpacity);
+ px.drawImage(0,0,m_imgBuffer);
+ #endif
+ px.end();
+ } else {
+#ifdef COMPILE_USE_QT4
+ QPainter px(this);
+ px.drawPixmap(0,0,m_pixForeground);
+#else
+ bitBlt(this,QPoint(0,0),&m_pixForeground);
+#endif
+ }
+}
+
+void KviNotifierWindow::redrawText()
+{
+ QPainter p(&m_pixForeground);
+
+ // the current tab
+ KviNotifierWindowTab * tab = m_pWndTabs->currentTab();
+ if(!tab)return;
+
+ // it's message list
+ KviPointerList<KviNotifierMessage> * l = tab->messageList();
+ if(!l)return;
+ if(l->isEmpty())return;
+
+ // the current message
+ KviNotifierMessage * cur = tab->currentMessage();
+ if(!cur)cur = l->last();
+
+ // this is useful in several places
+ KviNotifierMessage * last = l->last();
+
+ // make sure that we can loop
+ int iIdx = l->findRef(cur);
+ if(iIdx == -1)
+ {
+ tab->setCurrentMessage(last);
+ cur = last;
+ iIdx = l->findRef(cur);
+ }
+
+ int y = m_pWndBody->textRect().y() + m_pWndBody->textRect().height();
+
+ if(m_pLineEdit->isVisible())y -= (m_pLineEdit->height() + 4);
+
+ QColorGroup grp = colorGroup();
+
+ int idx = iIdx;
+ KviNotifierMessage * m = cur;
+ while(m && (y > m_pWndBody->textRect().y()))
+ {
+ int iHeight = m->text()->height();
+ if(iHeight < 18)iHeight = 18;
+ y -= iHeight;
+ if(m->historic())
+ {
+ grp.setColor(QColorGroup::Text,m_clrHistoricText);
+ } else {
+ if(m == last)
+ grp.setColor(QColorGroup::Text,m_clrCurText);
+ else {
+ int iClrIdx = l->count() - (idx + 2);
+ if(iClrIdx < 0)iClrIdx = 0;
+ else if(iClrIdx >= NUM_OLD_COLORS)iClrIdx = (NUM_OLD_COLORS - 1);
+ grp.setColor(QColorGroup::Text,m_clrOldText[iClrIdx]);
+ }
+ }
+ int iMaxY = y > m_pWndBody->textRect().y() ? y : m_pWndBody->textRect().y();
+ QRect clip(m_pWndBody->textRect().x() + 20,iMaxY,m_pWndBody->textRect().width() - 20,iHeight);
+
+ m->text()->draw(&p,m_pWndBody->textRect().x() + 20,y,clip,grp); //
+ if(y > m_pWndBody->textRect().y())
+ {
+ if(m->image())
+ p.drawPixmap(m_pWndBody->textRect().x() + 1,y + 1,*(m->image()),0,0,16,16);
+ }
+ m = l->prev();
+ idx--;
+ }
+
+ p.setPen(QPen(m_clrTitle));
+ p.setFont(*m_pTitleFont);
+ QString title;
+ KviQString::sprintf(title,"[%d/%d]",iIdx + 1,l->count());
+
+ if(tab->window())
+ {
+ title += " ";
+ title += tab->window()->plainTextCaption();
+ }
+ p.drawText(m_pWndBorder->titleRect(),Qt::AlignLeft | Qt::SingleLine,title);
+ p.end();
+}
+
+void KviNotifierWindow::mouseMoveEvent(QMouseEvent * e)
+{
+
+ //debug ("move on x,y: %d,%d", e->pos().x(), e->pos().y());
+
+ if (!m_bLeftButtonIsPressed) {
+
+ if(checkResizing(e->pos())) goto sartelo;
+
+ /* ### MOUSE-MOVE-EVENT -> m_pWndBorder ### */
+ if (m_pWndBorder->captionRect().contains(e->pos())) {
+ if (m_pWndBorder->closeRect().contains(e->pos())) {
+ m_pWndBorder->setCloseIcon(WDG_ICON_OVER);
+ } else {
+ m_pWndBorder->setCloseIcon(WDG_ICON_OUT);
+ }
+ goto sartelo;
+ }
+
+ if(m_pWndTabs->currentTab())
+ {
+ /* ### MOUSE-MOVE-EVENT -> m_pWndTabs ### */
+ if (m_pWndTabs->rect().contains(e->pos())) {
+ m_pWndTabs->mouseMoveEvent(e);
+ goto sartelo;
+ }
+
+ /* ### MOUSE-MOVE-EVENT -> m_pWndBody ### */
+ if (m_pWndBody->rect().contains(e->pos())) {
+ if (m_pWndBody->rctWriteIcon().contains(e->pos())) {
+ m_pWndBody->setWriteIcon(WDG_ICON_ON);
+ } else {
+ m_pWndBody->setWriteIcon(WDG_ICON_OFF);
+ }
+ goto sartelo;
+ }
+ }
+ /* ### END ### */
+
+sartelo:
+
+ update();
+
+ }
+
+ if(m_bDragging) {
+ setCursor(Qt::SizeAllCursor);
+
+ int w = m_wndRect.width();
+ int h = m_wndRect.height();
+
+ m_wndRect.setX( m_pntPos.x() + cursor().pos().x() - m_pntDrag.x() );
+ m_wndRect.setY( m_pntPos.y() + cursor().pos().y() - m_pntDrag.y() );
+
+ m_wndRect.setWidth(w);
+ m_wndRect.setHeight(h);
+
+ setGeometry(m_wndRect);
+
+ return;
+ } else if (m_bResizing) {
+ resize(e->pos());
+ }
+
+}
+
+void KviNotifierWindow::mousePressEvent(QMouseEvent * e)
+{
+
+ // stop blinking first of all :)
+ bool bWasBlinkOn = m_bBlinkOn;
+ m_bBlinkOn = false;
+ stopBlinkTimer();
+ m_tAutoHideAt = 0;
+ stopAutoHideTimer();
+
+ setActiveWindow();
+ setFocus();
+
+ m_pntClick = e->pos();
+
+ if(e->button() == Qt::RightButton)
+ {
+ contextPopup(mapToGlobal(e->pos()));
+ return;
+ } else if(e->button() == Qt::LeftButton) {
+ m_bLeftButtonIsPressed = true;
+ }
+
+ if(checkResizing(m_pntClick)) goto sartelo;
+
+ if(m_pWndTabs->rect().contains(e->pos()))
+ {
+ m_pWndTabs->mousePressEvent(e);
+ goto sartelo;
+ }
+
+ if(m_pWndBorder->captionRect().contains(e->pos())) {
+ //debug ("Clicked on m_pWndBorder->rect()");
+ if(m_pWndBorder->closeRect().contains(e->pos())) {
+ //debug ("\tClicked on m_pWndBorder->closeRect()");
+ m_bCloseDown = true;
+ m_pWndBorder->setCloseIcon(WDG_ICON_CLICKED);
+ goto sartelo;
+ }
+
+ if( !m_bResizing) {
+ m_bDragging = true;
+ m_pntDrag = cursor().pos();
+ m_pntPos = pos();
+ goto sartelo;
+ }
+ }
+
+ //debug ("x,y: %d,%d - width,height: %d,%d", m_pWndBorder->rect().x(),m_pWndBorder->rect().y(),m_pWndBorder->rect().width(),m_pWndBorder->rect().height());
+
+ if (m_pWndBorder->rect().contains(e->pos())) {
+ if(m_pWndTabs->currentTab())
+ {
+ //debug ("Clicked on m_pWndBody->textRect()");
+ if(m_pWndBody->rctWriteIcon().contains(e->pos()))
+ {
+ m_pWndBody->setWriteIcon(WDG_ICON_CLICKED);
+ showLineEdit(!(m_pLineEdit->isVisible()));
+ }
+
+ if(m_pWndBody->rctPrevIcon().contains(e->pos()) && m_pWndBody->prevIconState()!=WDG_ICON_OFF)
+ {
+ m_bPrevDown = true;
+ m_pWndBody->setPrevIcon(WDG_ICON_CLICKED);
+ prevButtonClicked();
+ }
+
+ if(m_pWndBody->rctNextIcon().contains(e->pos()) && m_pWndBody->nextIconState()!=WDG_ICON_OFF)
+ {
+ m_bNextDown = true;
+ m_pWndBody->setNextIcon(WDG_ICON_CLICKED);
+ nextButtonClicked();
+ }
+ }
+ goto sartelo;
+ }
+
+ if(bWasBlinkOn) goto sartelo; else return;
+
+sartelo:
+ update();
+
+}
+
+void KviNotifierWindow::mouseReleaseEvent(QMouseEvent * e)
+{
+ m_bWriteDown = false;
+ m_bNextDown = false;
+ m_bPrevDown = false;
+ m_bCloseDown = false;
+ m_bLeftButtonIsPressed = false;
+ m_bResizing = false;
+
+ //m_pWndBody->setWriteIcon(WDG_ICON_ON);
+ m_pWndBody->setNextIcon(WDG_ICON_ON);
+ m_pWndBody->setPrevIcon(WDG_ICON_ON);
+ m_pWndTabs->setCloseTabIcon(WDG_ICON_OFF);
+
+ if(m_bDragging)
+ {
+ m_bDragging = false;
+ if(QApplication::overrideCursor()) QApplication::restoreOverrideCursor();
+ return;
+ }
+
+ if(m_pWndBorder->captionRect().contains(e->pos())) {
+
+ if(m_pWndBorder->closeRect().contains(e->pos())) {
+ //debug ("hide now from release event");
+ hideNow();
+ } else {
+ update();
+ }
+
+ }
+
+ if(m_pWndTabs->rect().contains(e->pos()))
+ {
+ m_pWndTabs->mouseReleaseEvent(e);
+ }
+
+ setCursor(-1);
+
+}
+
+void KviNotifierWindow::mouseDoubleClickEvent(QMouseEvent * e)
+{
+ if(!m_pWndBody->textRect().contains(e->pos()))
+ {
+ QWidget::mouseDoubleClickEvent(e);
+ return;
+ }
+
+ KviNotifierWindowTab * tab = m_pWndTabs->currentTab();
+ if(!tab)return;
+
+ if(!tab->window())return;
+
+ hideNow();
+ delayedRaise(tab->window());
+}
+
+void KviNotifierWindow::keyPressEvent(QKeyEvent * e)
+{
+ if (e->key()==Qt::Key_Shift) {
+ m_bKeyShiftPressed = true;
+ return;
+ }
+
+ if (e->key()==Qt::Key_Left && m_bKeyShiftPressed) {
+ m_pWndTabs->prev();
+ return;
+ }
+ if (e->key()==Qt::Key_Right && m_bKeyShiftPressed) {
+ m_pWndTabs->next();
+ return;
+ }
+
+ if (e->key()==Qt::Key_Escape) {
+ hideNow();
+ return;
+ }
+}
+
+void KviNotifierWindow::keyReleaseEvent(QKeyEvent * e)
+{
+ if (e->key()==Qt::Key_Shift) {
+ m_bKeyShiftPressed = false;
+ }
+}
+
+void KviNotifierWindow::delayedRaise(KviWindow * pWnd)
+{
+ m_pWindowToRaise = pWnd;
+ QTimer::singleShot(0,this,SLOT(delayedRaiseSlot()));
+}
+
+void KviNotifierWindow::delayedRaiseSlot()
+{
+ if(!m_pWindowToRaise)return;
+ if(!g_pApp->windowExists(m_pWindowToRaise))return;
+
+ if(m_pWindowToRaise->mdiParent())
+ {
+ if(!m_pWindowToRaise->frame()->isVisible())
+ m_pWindowToRaise->frame()->show();
+
+ m_pWindowToRaise->frame()->raise();
+ //((QWidget *)(m_pWindowToRaise->frame()))->setActiveWindow();
+ m_pWindowToRaise->frame()->setFocus();
+ }
+
+ m_pWindowToRaise->delayedAutoRaise();
+}
+
+bool KviNotifierWindow::checkResizing(QPoint e)
+{
+ if (e.y()<WDG_BORDER_THICKNESS) {
+ if (e.x()<WDG_BORDER_THICKNESS) {
+ //// UP LEFT CORNER ////
+ setCursor(Qt::SizeFDiagCursor);
+ if (m_bLeftButtonIsPressed) {
+ m_bResizing = true;
+ m_whereResizing = WDG_UPSX;
+ }
+ } else if (e.x() > (size().width()-WDG_BORDER_THICKNESS)) {
+ //// UP RIGHT CORNER ////
+ setCursor(Qt::SizeBDiagCursor);
+ if (m_bLeftButtonIsPressed) {
+ m_bResizing = true;
+ m_whereResizing = WDG_UPDX;
+ }
+ } else {
+ //// UP SIDE ////
+ setCursor(Qt::SizeVerCursor);
+ if (m_bLeftButtonIsPressed) {
+ m_bResizing = true;
+ m_whereResizing = WDG_UP;
+ } }
+ } else if (e.y() > (size().height()-WDG_BORDER_THICKNESS)) {
+ if (e.x()<WDG_BORDER_THICKNESS) {
+ //// DOWN LEFT CORNER ////
+ setCursor(Qt::SizeBDiagCursor);
+ if (m_bLeftButtonIsPressed) {
+ m_bResizing = true;
+ m_whereResizing = WDG_DWNSX;
+ }
+ } else if (e.x() > (size().width()-WDG_BORDER_THICKNESS)) {
+ //// DOWN RIGHT CORNER ////
+ setCursor(Qt::SizeFDiagCursor);
+ if (m_bLeftButtonIsPressed) {
+ m_bResizing = true;
+ m_whereResizing = WDG_DWNDX;
+ }
+ } else {
+ //// DOWN SIDE ////
+ setCursor(Qt::SizeVerCursor);
+ if (m_bLeftButtonIsPressed) {
+ m_bResizing = true;
+ m_whereResizing = WDG_DWN;
+ }
+ }
+ } else {
+ if (e.x()<WDG_BORDER_THICKNESS) {
+ //// LEFT SIZE ////
+ setCursor(Qt::SizeHorCursor);
+ if (m_bLeftButtonIsPressed) {
+ m_bResizing = true;
+ m_whereResizing = WDG_SX;
+ }
+ } else if (e.x() > (size().width()-WDG_BORDER_THICKNESS)) {
+ //// RIGHT SIZE ////
+ setCursor(Qt::SizeHorCursor);
+ if (m_bLeftButtonIsPressed) {
+ m_bResizing = true;
+ m_whereResizing = WDG_DX;
+ }
+ } else {
+ //// ELSEWHERE ////
+ m_whereResizing = 0;
+ m_bResizing = false;
+ setCursor(-1);
+ }
+ }
+ return m_bResizing;
+};
+
+
+
+void KviNotifierWindow::resize(QPoint p, bool up)
+{
+ //QPoint aux = mapToGlobal(p);
+
+ if (m_whereResizing==WDG_UPSX || m_whereResizing==WDG_SX || m_whereResizing==WDG_DWNSX) {
+ if ((x() + width() - cursor().pos().x()) < WDG_MIN_WIDTH)
+ m_wndRect.setLeft(x() + width() - WDG_MIN_WIDTH);
+ else
+ m_wndRect.setLeft(cursor().pos().x());
+ }
+
+ if (m_whereResizing == WDG_UPSX || m_whereResizing == WDG_UP || m_whereResizing == WDG_UPDX) {
+ if (y()+height()-cursor().pos().y() < WDG_MIN_HEIGHT)
+ m_wndRect.setTop(y() + height() - WDG_MIN_HEIGHT);
+ else
+ m_wndRect.setTop(cursor().pos().y());
+ }
+
+ if (m_whereResizing == WDG_DX || m_whereResizing == WDG_UPDX || m_whereResizing == WDG_DWNDX) {
+ if ((cursor().pos().x() - x()) > WDG_MIN_WIDTH)
+ m_wndRect.setRight(cursor().pos().x());
+ else
+ m_wndRect.setRight(x() + WDG_MIN_WIDTH);
+ }
+
+ if (m_whereResizing == WDG_DWN || m_whereResizing == WDG_DWNDX || m_whereResizing == WDG_DWNSX) {
+ if ((cursor().pos().y() - y()) > WDG_MIN_HEIGHT)
+ m_wndRect.setBottom(cursor().pos().y());
+ else
+ m_wndRect.setBottom(y() + WDG_MIN_HEIGHT);
+ }
+
+ showLineEdit(m_pLineEdit->isVisible());
+ setGeometry(m_wndRect);
+}
+
+void KviNotifierWindow::redrawWindow()
+{
+ if(m_pixBackground.size()!=m_wndRect.size())
+ {
+ // Redraw only if size was modified..
+ m_pixBackground.resize(m_wndRect.size());
+ m_pixForeground.resize(m_wndRect.size());
+ m_pixBackgroundHighlighted.resize(m_wndRect.size());
+
+ m_pWndBorder->resize( m_wndRect.size() );
+ m_pWndTabs->setWidth( m_pWndBorder->tabsRect().width() );
+ m_pWndBody->resize( m_pWndBorder->bodyRect() );
+ m_pProgressBar->setHeight(m_pWndBorder->bodyRect().height() + m_pWndBorder->tabsRect().height());
+ }
+
+ QPainter paint;
+ if(m_bBlinkOn)
+ {
+ m_pWndBorder->touch();
+ m_pWndTabs->touch();
+ m_pWndBody->touch();
+ paint.begin(&m_pixBackgroundHighlighted);
+ m_pWndBorder->draw(&paint,true);
+ m_pWndTabs->draw(&paint);
+ m_pWndBody->draw(&paint);
+ m_pProgressBar->draw(&paint);
+ paint.end();
+ bitBlt(&m_pixForeground, 0,0, &m_pixBackgroundHighlighted);
+ m_pWndBorder->touch();
+ m_pWndTabs->touch();
+ m_pWndBody->touch();
+ } else {
+ paint.begin(&m_pixBackground);
+ m_pWndBorder->draw(&paint);
+ m_pWndTabs->draw(&paint);
+ m_pWndBody->draw(&paint);
+ m_pProgressBar->draw(&paint);
+ paint.end();
+ bitBlt(&m_pixForeground, 0,0, &m_pixBackground);
+ }
+
+}
+
+inline void KviNotifierWindow::setCursor(int cur) {
+ if (m_cursor.shape() != cur) {
+ if(QApplication::overrideCursor()) QApplication::restoreOverrideCursor();
+ m_cursor.setShape((Qt::CursorShape)cur);
+ QApplication::setOverrideCursor(m_cursor);
+ } else if (cur==-1)
+ if(QApplication::overrideCursor()) QApplication::restoreOverrideCursor();
+}
+
+void KviNotifierWindow::enterEvent(QEvent * e)
+{
+#ifdef COMPILE_USE_QT4
+ if(!m_pShowHideTimer) {
+ m_pShowHideTimer = new QTimer();
+ connect(m_pShowHideTimer,SIGNAL(timeout()),this,SLOT(heartbeat()));
+ }
+ m_eState = FocusingOn;
+ m_pShowHideTimer->start(40);
+#endif
+}
+
+void KviNotifierWindow::leaveEvent(QEvent * e)
+{
+ // Leaving the widget area, restore default cursor
+ m_pWndBorder->resetIcons();
+ m_pWndTabs->resetIcons();
+ if (!m_bResizing)
+ setCursor(-1);
+#ifdef COMPILE_USE_QT4
+ if(!m_pShowHideTimer) {
+ m_pShowHideTimer = new QTimer();
+ connect(m_pShowHideTimer,SIGNAL(timeout()),this,SLOT(heartbeat()));
+ }
+ m_eState = FocusingOff;
+ m_pShowHideTimer->start(40);
+#endif
+}
+
+void KviNotifierWindow::contextPopup(const QPoint &pos)
+{
+ if(!m_pContextPopup)
+ {
+ m_pContextPopup = new QPopupMenu(this);
+ connect(m_pContextPopup,SIGNAL(aboutToShow()),this,SLOT(fillContextPopup()));
+ m_pDisablePopup = new QPopupMenu(this);
+ }
+
+ m_pContextPopup->popup(pos);
+}
+
+void KviNotifierWindow::fillContextPopup()
+{
+ m_pContextPopup->clear();
+
+ m_pContextPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CLOSE)),__tr2qs_ctx("Hide","notifier"),this,SLOT(hideNow()));
+ m_pContextPopup->insertSeparator();
+ m_pDisablePopup->clear();
+ m_pDisablePopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TIME)),__tr2qs_ctx("1 Minute","notifier"),this,SLOT(disableFor1Minute()));
+ m_pDisablePopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TIME)),__tr2qs_ctx("5 Minutes","notifier"),this,SLOT(disableFor5Minutes()));
+ m_pDisablePopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TIME)),__tr2qs_ctx("15 Minutes","notifier"),this,SLOT(disableFor15Minutes()));
+ m_pDisablePopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TIME)),__tr2qs_ctx("30 Minutes","notifier"),this,SLOT(disableFor30Minutes()));
+ m_pDisablePopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TIME)),__tr2qs_ctx("1 Hour","notifier"),this,SLOT(disableFor60Minutes()));
+ m_pDisablePopup->insertSeparator();
+ m_pDisablePopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_QUIT)),__tr2qs_ctx("Until KVIrc is Restarted","notifier"),this,SLOT(disableUntilKVIrcRestarted()));
+ m_pDisablePopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_QUIT)),__tr2qs_ctx("Permanently (Until Explicitly Enabled)","notifier"),this,SLOT(disablePermanently()));
+
+ m_pContextPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_QUIT)),__tr2qs_ctx("Disable","notifier"),m_pDisablePopup);
+}
+
+void KviNotifierWindow::disableFor15Minutes()
+{
+ kvi_time_t tNow = kvi_unixTime();
+ g_tNotifierDisabledUntil = tNow + (60 * 15);
+
+ hideNow();
+}
+
+void KviNotifierWindow::disableFor5Minutes()
+{
+ kvi_time_t tNow = kvi_unixTime();
+ g_tNotifierDisabledUntil = tNow + (60 * 5);
+
+ hideNow();
+}
+
+
+void KviNotifierWindow::disableFor1Minute()
+{
+ kvi_time_t tNow = kvi_unixTime();
+ g_tNotifierDisabledUntil = tNow + 60;
+
+ hideNow();
+}
+
+void KviNotifierWindow::disableFor30Minutes()
+{
+ kvi_time_t tNow = kvi_unixTime();
+ g_tNotifierDisabledUntil = tNow + (60 * 30);
+
+ hideNow();
+}
+
+void KviNotifierWindow::disableFor60Minutes()
+{
+ kvi_time_t tNow = kvi_unixTime();
+ g_tNotifierDisabledUntil = tNow + (60 * 60);
+
+ hideNow();
+}
+
+void KviNotifierWindow::disableUntilKVIrcRestarted()
+{
+ kvi_time_t tNow = kvi_unixTime();
+ // in fact we just disable for one year
+ g_tNotifierDisabledUntil = tNow + (3600 * 24 * 360); // one year :D
+ // this will NOT work if the module is forcibly unloaded with /notifier.unload
+ // but the user should never do it :D
+ hideNow();
+}
+
+void KviNotifierWindow::disablePermanently()
+{
+ KVI_OPTION_BOOL(KviOption_boolForciblyDisableNotifier) = true;
+ hideNow();
+}
+
+void KviNotifierWindow::wheelEvent(QWheelEvent * e)
+{
+ if(e->delta() > 0)prevButtonClicked();
+ else nextButtonClicked();
+}
+
+
+void KviNotifierWindow::prevButtonClicked()
+{
+ KviNotifierWindowTab * tab = m_pWndTabs->currentTab();
+ if(!tab)return;
+ tab->setPrevMessageAsCurrent();
+ update();
+}
+
+void KviNotifierWindow::nextButtonClicked()
+{
+ KviNotifierWindowTab * tab = m_pWndTabs->currentTab();
+ if(!tab)return;
+ tab->setNextMessageAsCurrent();
+ update();
+}
+
+void KviNotifierWindow::showLineEdit(bool bShow)
+{
+ if(bShow)
+ {
+ //if(m_pLineEdit->isVisible())return;
+ if(!m_pWndTabs->currentMessage())return;
+ if(!m_pWndTabs->currentTab()->window())return;
+ QToolTip::remove(m_pLineEdit);
+ QString tip = __tr2qs_ctx("Write text or commands to window","notifier");
+ tip += " \"";
+ tip += m_pWndTabs->currentTab()->window()->plainTextCaption();
+ tip += "\"";
+ QToolTip::add(m_pLineEdit,tip);
+ m_pLineEdit->setGeometry(m_pWndBody->textRect().x(),m_pWndBody->textRect().y() + m_pWndBody->textRect().height() - m_iInputHeight,m_pWndBody->textRect().width(),m_iInputHeight);
+ m_pLineEdit->show();
+ m_pLineEdit->setFocus();
+ redrawWindow();
+ setActiveWindow();
+ } else {
+ if(!m_pLineEdit->isVisible())return;
+ m_pLineEdit->hide();
+ setFocus();
+ KviNotifierWindowTab * tab = m_pWndTabs->currentTab();
+ if(tab)tab->setLastMessageAsCurrent();
+ update();
+ }
+}
+
+bool KviNotifierWindow::eventFilter(QObject * pEdit,QEvent * e)
+{
+ if(pEdit != (QObject *)m_pLineEdit)return false; // huh ?
+ if(!m_pLineEdit->isVisible())return false;
+ if(e->type() == QEvent::MouseButtonPress)
+ {
+ bool bWasBlinkOn = m_bBlinkOn;
+ m_bBlinkOn = false;
+ m_tAutoHideAt = 0;
+ stopAutoHideTimer();
+ stopBlinkTimer();
+ setActiveWindow();
+ m_pLineEdit->setFocus();
+ if(bWasBlinkOn)update();
+ return true;
+ }
+ if(e->type() == QEvent::KeyPress)
+ {
+ if(((QKeyEvent *)e)->key() == Qt::Key_Escape)
+ {
+ hideNow();
+ return true;
+ }
+ }
+ return false;
+}
+
+void KviNotifierWindow::returnPressed()
+{
+ if(!m_pLineEdit->isVisible())return;
+
+ KviNotifierWindowTab * tab = m_pWndTabs->currentTab();
+ if(!tab)return;
+ if(!tab->currentMessage())return;
+ if(!tab->window())return;
+
+ QString txt = m_pLineEdit->text();
+ if(txt.isEmpty())return;
+ QString html = txt;
+ html.replace("<","&lt;");
+ html.replace(">","&gt;");
+ KviStr tmp(KviStr::Format,"%d",KVI_SMALLICON_OWNPRIVMSG);
+
+ addMessage(tab->window(),tmp.ptr(),html,0); //m_pCurrentFocusedWindowTab on place of m_pCurrentMessage->window()
+ m_pLineEdit->setText("");
+ KviUserInput::parse(txt,tab->window(),QString::null,1);
+}
+
+void KviNotifierWindow::progressUpdate()
+{
+ double dProgress = m_qtStartedAt.elapsed()/(m_tAutoHideAt - m_tStartedAt);
+ dProgress/=1000;
+ m_pProgressBar->setProgress(dProgress);
+ QPainter p(this);
+ m_pProgressBar->draw(&p);
+}
+#include "m_notifierwindow.moc"
+
diff --git a/src/modules/notifier/notifierwindow.h b/src/modules/notifier/notifierwindow.h
new file mode 100644
index 00000000..be5e3b6e
--- /dev/null
+++ b/src/modules/notifier/notifierwindow.h
@@ -0,0 +1,194 @@
+#ifndef _NOTIFIERWINDOW_H_
+#define _NOTIFIERWINDOW_H_
+//==================================================================================
+//
+// File : notifierwindow.h
+// Creation date : Tue Jul 6 2004 20:25:12 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2005 Iacopo Palazzi < iakko(at)siena(dot)linux(dot)it >
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the linkss of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) 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.
+//
+//==================================================================================
+
+#include "kvi_settings.h"
+
+#include <qbitmap.h>
+#include <qcolor.h>
+#include <qcursor.h>
+#include <qdatetime.h>
+#include <qfont.h>
+#include <qimage.h>
+#include <qlineedit.h>
+#include <qpixmap.h>
+#include <qrect.h>
+#include <qtimer.h>
+#include <qwidget.h>
+
+#include "kvi_qstring.h"
+#include "kvi_pointerlist.h"
+#include "kvi_time.h"
+
+#include "notifiersettings.h"
+
+class KviWindow;
+class KviNotifierMessage;
+
+class KviNotifierWindowBody;
+class KviNotifierWindowBorder;
+class KviNotifierWindowProgressBar;
+class KviNotifierWindowTabs;
+
+class QPainter;
+class QPopupMenu;
+
+extern kvi_time_t g_tNotifierDisabledUntil;
+
+class KviNotifierWindow : public QWidget
+{
+ Q_OBJECT
+public:
+ KviNotifierWindow();
+ ~KviNotifierWindow();
+protected:
+ QTimer * m_pShowHideTimer;
+ QTimer * m_pProgressTimer;
+ QTimer * m_pBlinkTimer;
+ QTimer * m_pAutoHideTimer;
+ State m_eState;
+ bool m_bBlinkOn;
+ double m_dOpacity;
+ QImage m_imgDesktop; // the desktop screenshot
+ QPixmap m_pixBackground; // our background image
+ QPixmap m_pixBackgroundHighlighted;
+ QPixmap m_pixForeground; // we paint the stuff HERE
+
+ // Notifier graphic layout
+ QPixmap m_pixBckgrnd;
+
+ QImage m_imgBuffer; // here we merge the two images
+
+ bool m_bCloseDown;
+ bool m_bPrevDown;
+ bool m_bNextDown;
+ bool m_bWriteDown;
+ bool m_bCrashShowWorkAround;
+
+ bool m_bKeyShiftPressed;
+
+ QFont * m_pDefaultFont;
+ QFont * m_pTitleFont;
+
+ QRect m_wndRect;
+
+ QColor m_clrCurText;
+ QColor m_clrOldText[NUM_OLD_COLORS];
+ QColor m_clrHistoricText;
+ QColor m_clrTitle;
+
+ KviNotifierMessage * m_pCurrentMessage;
+ QLineEdit * m_pLineEdit;
+
+ bool m_bDragging;
+ bool m_bLeftButtonIsPressed;
+ bool m_bDiagonalResizing;
+ bool m_bResizing;
+
+ int m_whereResizing;
+
+ QPoint m_pntDrag;
+ QPoint m_pntPos;
+ QPoint m_pntClick;
+ int m_iInputHeight;
+ int m_iBlinkTimeout;
+ int m_iBlinkCount;
+ QPopupMenu * m_pContextPopup;
+ QPopupMenu * m_pDisablePopup;
+ KviWindow * m_pWindowToRaise;
+ kvi_time_t m_tAutoHideAt;
+ kvi_time_t m_tStartedAt;
+ QTime m_qtStartedAt;
+ bool m_bDisableHideOnMainWindowGotAttention;
+ //bool m_bForceShowing;
+
+ QCursor m_cursor;
+
+ KviNotifierWindowTabs * m_pWndTabs;
+ KviNotifierWindowProgressBar * m_pProgressBar;
+ KviNotifierWindowBody * m_pWndBody;
+ KviNotifierWindowBorder * m_pWndBorder;
+public:
+ void doShow(bool bDoAnimate);
+ void doHide(bool bDoAnimate);
+ const QFont & defaultFont(){ return *m_pDefaultFont; };
+ int textWidth();
+ void addMessage(KviWindow * pWnd,const QString &szImageId,const QString &szText,unsigned int uMessageTime);
+ State state() { return m_eState; };
+ void setDisableHideOnMainWindowGotAttention(bool b){ m_bDisableHideOnMainWindowGotAttention = b; };
+ int countTabs();
+ void showLineEdit(bool bShow);
+protected:
+ virtual void showEvent(QShowEvent *e);
+ virtual void hideEvent(QHideEvent * e);
+ virtual void paintEvent(QPaintEvent * e);
+ virtual void mousePressEvent(QMouseEvent * e);
+ virtual void mouseReleaseEvent(QMouseEvent * e);
+ virtual void mouseMoveEvent(QMouseEvent * e);
+ virtual void leaveEvent(QEvent * e);
+ virtual void enterEvent(QEvent * e);
+ virtual void mouseDoubleClickEvent(QMouseEvent * e);
+ virtual void wheelEvent(QWheelEvent * e);
+ virtual bool eventFilter(QObject * pEdit,QEvent * e);
+ virtual void keyPressEvent ( QKeyEvent * e );
+ virtual void keyReleaseEvent ( QKeyEvent * e );
+protected slots:
+ void blink();
+ void heartbeat();
+ void returnPressed();
+ void reloadImages();
+ void fillContextPopup();
+ void hideNow();
+ void disableFor1Minute();
+ void disableFor5Minutes();
+ void disableFor15Minutes();
+ void disableFor30Minutes();
+ void disableFor60Minutes();
+ void disableUntilKVIrcRestarted();
+ void disablePermanently();
+ void delayedRaiseSlot();
+ void autoHide();
+ void progressUpdate();
+private:
+ void contextPopup(const QPoint &pos);
+ void startBlinking();
+ void markAllMessagesAsHistoric();
+ void computeRect();
+ void stopShowHideTimer();
+ void stopBlinkTimer();
+ void stopAutoHideTimer();
+ void startAutoHideTimer();
+ void delayedRaise(KviWindow * pWnd);
+ void prevButtonClicked();
+ void nextButtonClicked();
+ bool shouldHideIfMainWindowGotAttention();
+ void setCursor(int);
+ void resize(QPoint p, bool = true);
+ void redrawWindow();
+ void redrawText();
+ bool checkResizing(QPoint);
+};
+
+#endif //_NOTIFIERWINDOW_H_
diff --git a/src/modules/notifier/notifierwindowbody.cpp b/src/modules/notifier/notifierwindowbody.cpp
new file mode 100644
index 00000000..7449aa9e
--- /dev/null
+++ b/src/modules/notifier/notifierwindowbody.cpp
@@ -0,0 +1,232 @@
+//=============================================================================
+//
+// File : kvinotifierwindowbody.cpp
+// Created on dom 02 gen 2005 17:53:29 by Iacopo Palazzi
+//
+// This file is part of the KVIrc distribution
+// Copyright (C) 2005 Iacopo Palazzi < iakko(at)siena(dot)linux(dot)it >
+//
+// 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 opinion) 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.
+//
+//=============================================================================
+
+#include "notifierwindowbody.h"
+
+#include "kvi_iconmanager.h"
+
+#include <qbrush.h>
+#include <qcolor.h>
+#include <qpainter.h>
+
+/*
+#ifdef QT3_SUPPORT
+ #include <Q3Painter>
+#else
+ #include <qpainter.h>
+#endif
+*/
+
+KviNotifierWindowBody::KviNotifierWindowBody(QRect r)
+{
+ loadImages();
+ setHeight(r.height());
+ setWidth(r.width());
+ m_pnt.setX(r.x());
+ m_pnt.setY(r.y());
+ recalculatePositions();
+}
+
+KviNotifierWindowBody::~KviNotifierWindowBody()
+{
+}
+
+
+void KviNotifierWindowBody::loadImages()
+{
+ QPixmap * p;
+ if((p = g_pIconManager->getPixmap("notifier_pix_body_dx.png")))
+ m_pixDX = *p;
+ if((p = g_pIconManager->getPixmap("notifier_pix_body_sx.png")))
+ m_pixSX = *p;
+ if((p = g_pIconManager->getPixmap("notifier_pix_body_dwnsx.png")))
+ m_pixDWNSX = *p;
+ if((p = g_pIconManager->getPixmap("notifier_pix_body_dwndx.png")))
+ m_pixDWNDX = *p;
+ if((p = g_pIconManager->getPixmap("notifier_pix_body_dwn.png")))
+ m_pixDWN = *p;
+ if((p = g_pIconManager->getPixmap("notifier_pix_body_kvirc_sx.png")))
+ m_pixKVIrcSX = *p;
+ if((p = g_pIconManager->getPixmap("notifier_pix_body_kvirc_dwn.png")))
+ m_pixKVIrcDWN = *p;
+ if((p = g_pIconManager->getPixmap("notifier_pix_body_kvirc.png")))
+ m_pixKVIrc = *p;
+
+ if((p = g_pIconManager->getPixmap("notifier_icon_body_prev_off.png")))
+ m_pixIconPrev_off = *p;
+ if((p = g_pIconManager->getPixmap("notifier_icon_body_prev_on.png")))
+ m_pixIconPrev_on = *p;
+ if((p = g_pIconManager->getPixmap("notifier_icon_body_prev_clicked.png")))
+ m_pixIconPrev_clicked = *p;
+
+ m_pixIconPrev = m_pixIconPrev_off;
+
+ if((p = g_pIconManager->getPixmap("notifier_icon_body_next_off.png")))
+ m_pixIconNext_off = *p;
+ if((p = g_pIconManager->getPixmap("notifier_icon_body_next_on.png")))
+ m_pixIconNext_on = *p;
+ if((p = g_pIconManager->getPixmap("notifier_icon_body_next_clicked.png")))
+ m_pixIconNext_clicked = *p;
+
+ m_pixIconNext = m_pixIconNext_off;
+
+ if((p = g_pIconManager->getPixmap("notifier_icon_body_write_off.png")))
+ m_pixIconWrite_off = *p;
+ if((p = g_pIconManager->getPixmap("notifier_icon_body_write_on.png")))
+ m_pixIconWrite_on = *p;
+ if((p = g_pIconManager->getPixmap("notifier_icon_body_write_clicked.png")))
+ m_pixIconWrite_clicked = *p;
+
+ m_pixIconWrite = m_pixIconWrite_off;
+
+ needToRedraw();
+
+ m_prevIconState = WDG_ICON_OFF;
+ m_nextIconState = WDG_ICON_OFF;
+ m_writeIconState = WDG_ICON_OFF;
+
+}
+
+void KviNotifierWindowBody::setWidth(int w)
+{
+ m_rct.setWidth(w);
+ recalculatePositions();
+}
+
+void KviNotifierWindowBody::setHeight(int h)
+{
+ m_rct.setHeight(h);
+ recalculatePositions();
+}
+
+void KviNotifierWindowBody::recalculatePositions()
+{
+ m_textRect.setX(m_pnt.x()+m_pixSX.width());
+ m_textRect.setY(m_pnt.y());
+ m_textRect.setWidth(m_rct.width()-m_pixSX.width()-m_pixDX.width()-m_pixIconPrev.width());
+ m_textRect.setHeight(m_rct.height()-m_pixDWN.height());
+
+ m_rctWriteIcon.setX(m_textRect.x()+m_textRect.width());
+ m_rctWriteIcon.setY(m_pnt.y()+m_textRect.height()-m_pixIconWrite.height());
+ m_rctWriteIcon.setWidth(m_pixIconWrite.width());
+ m_rctWriteIcon.setHeight(m_pixIconWrite.height());
+
+ m_rctPrevIcon.setX(m_textRect.x()+m_textRect.width());
+ m_rctPrevIcon.setY(m_pnt.y()+2); //FIXME: Maybe the spacing should be calculated?
+ m_rctPrevIcon.setWidth(m_pixIconPrev.width());
+ m_rctPrevIcon.setHeight(m_pixIconPrev.height());
+
+ m_rctNextIcon.setX(m_textRect.x()+m_textRect.width());
+ m_rctNextIcon.setY(m_pnt.y()+m_textRect.height()-m_pixIconNext.height()-m_pixIconWrite.height());
+ m_rctNextIcon.setWidth(m_pixIconNext.width());
+ m_rctNextIcon.setHeight(m_pixIconNext.height());
+
+ needToRedraw();
+}
+
+void KviNotifierWindowBody::setPrevIcon(int state)
+{
+ //if (m_prevIconState==WDG_ICON_OFF && state!=WDG_ICON_OFF)
+ if (m_prevIconState!=state) {
+ switch (state) {
+ case WDG_ICON_ON: m_pixIconPrev = m_pixIconPrev_on; break;
+ case WDG_ICON_OFF: m_pixIconPrev = m_pixIconPrev_off; break;
+ case WDG_ICON_CLICKED: m_pixIconPrev = m_pixIconPrev_clicked; break;
+ };
+
+ m_prevIconState=state;
+ needToRedraw();
+ }
+};
+
+void KviNotifierWindowBody::setNextIcon(int state) {
+
+ //if (m_nextIconState==WDG_ICON_OFF && state!=WDG_ICON_OFF)
+ if (m_nextIconState!=state) {
+ switch (state) {
+ case WDG_ICON_ON: m_pixIconNext = m_pixIconNext_on; break;
+ case WDG_ICON_OFF: m_pixIconNext = m_pixIconNext_off; break;
+ case WDG_ICON_CLICKED: m_pixIconNext = m_pixIconNext_clicked; break;
+ };
+
+ needToRedraw();
+ m_nextIconState=state;
+ }
+};
+
+void KviNotifierWindowBody::setWriteIcon(int state) {
+
+ //if (m_writeIconState==WDG_ICON_OFF && state!=WDG_ICON_OFF)
+ if (m_writeIconState!=state) {
+ switch (state) {
+ case WDG_ICON_ON: m_pixIconWrite = m_pixIconWrite_on; break;
+ case WDG_ICON_OFF: m_pixIconWrite = m_pixIconWrite_off; break;
+ case WDG_ICON_CLICKED: m_pixIconWrite = m_pixIconWrite_clicked; break;};
+
+ needToRedraw();
+ m_writeIconState=state;
+ }
+};
+
+void KviNotifierWindowBody::draw(QPainter * p) {
+
+ if (m_bNeedToRedraw) {
+
+ p->fillRect(QRect(m_pnt,m_rct.size()),m_mac_bkgColor);
+
+ // Autotiled borders
+ p->drawTiledPixmap(m_pnt.x(), m_pnt.y(), m_pixSX.width(), m_rct.height() - m_pixDWNSX.height() - m_pixKVIrcSX.height(), m_pixSX);
+ p->drawTiledPixmap(m_pnt.x() + m_rct.width() - m_pixDX.width(), m_pnt.y(),m_pixDX.width(), m_rct.height() - m_pixDWNDX.height(), m_pixDX);
+ p->drawTiledPixmap(m_pnt.x() + m_pixKVIrcDWN.width() + m_pixDWNSX.width(), m_pnt.y() + m_rct.height() - m_pixDWN.height(), m_rct.width() - m_pixKVIrcDWN.width() - m_pixDWNSX.width() - m_pixDWNDX.width(), m_pixDWN.height(), m_pixDWN);
+
+ // Bottom corners
+ p->drawPixmap(m_pnt.x(), m_pnt.y() + m_rct.height() - m_pixDWNSX.height(), m_pixDWNSX);
+ p->drawPixmap(m_pnt.x() + m_rct.width() - m_pixDWNSX.width(), m_pnt.y() + m_rct.height() - m_pixDWNDX.height(), m_pixDWNDX);
+
+ // KVIrc image
+ p->drawPixmap(m_pnt.x(), m_pnt.y() + m_rct.height() - m_pixKVIrcSX.height() - m_pixDWNSX.height(), m_pixKVIrcSX);
+ p->drawPixmap(m_pnt.x() + m_pixKVIrcSX.width(), m_pnt.y() + m_rct.height() - m_pixKVIrcDWN.height(), m_pixKVIrcDWN);
+ p->drawPixmap(m_pnt.x() + m_pixKVIrcSX.width(), m_pnt.y() + m_rct.height() - m_pixKVIrc.height() - m_pixKVIrcDWN.height(), m_pixKVIrc, 0, 0, m_pixKVIrc.width(), m_pixKVIrc.height());
+
+ // Draw Icons
+ p->drawPixmap(m_rctPrevIcon.x(), m_rctPrevIcon.y(), m_pixIconPrev);
+ p->drawPixmap(m_rctNextIcon.x(), m_rctNextIcon.y(), m_pixIconNext);
+ p->drawPixmap(m_rctWriteIcon.x(), m_rctWriteIcon.y(), m_pixIconWrite);
+
+ m_bNeedToRedraw = false;
+
+ }
+}
+
+void KviNotifierWindowBody::mouseMoveEvent(QMouseEvent * e) {
+
+}
+
+void KviNotifierWindowBody::mousePressEvent(QMouseEvent * e) {
+
+}
+
+void KviNotifierWindowBody::mouseReleaseEvent(QMouseEvent * e) {
+
+}
diff --git a/src/modules/notifier/notifierwindowbody.h b/src/modules/notifier/notifierwindowbody.h
new file mode 100644
index 00000000..e59df9f9
--- /dev/null
+++ b/src/modules/notifier/notifierwindowbody.h
@@ -0,0 +1,147 @@
+#ifndef _KVINOTIFIERWINDOWBODY_H_
+#define _KVINOTIFIERWINDOWBODY_H_
+//=============================================================================
+//
+// File : kvinotifierwindowbody.h
+// Created on dom 02 gen 2005 17:53:29 by Iacopo Palazzi
+//
+// This file is part of the KVIrc distribution
+// Copyright (C) 2005 Iacopo Palazzi < iakko(at)siena(dot)linux(dot)it >
+//
+// 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 opinion) 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.
+//
+//=============================================================================
+
+#include <qevent.h>
+#include <qrect.h>
+#include <qpoint.h>
+#include <qpixmap.h>
+
+#include "notifiersettings.h"
+
+/*
+#ifdef QT3_SUPPORT
+ #define QPainter Q3Painter
+#endif
+*/
+
+class QPainter;
+
+class KviNotifierWindowBody
+{
+public:
+ KviNotifierWindowBody(QRect r);
+ ~KviNotifierWindowBody();
+
+// ================================
+// Put members declaration below...
+// ================================
+private:
+ QRect m_rct;
+ QPoint m_pnt;
+
+ QRect m_textRect;
+
+ QRect m_rctWriteIcon;
+ QRect m_rctPrevIcon;
+ QRect m_rctNextIcon;
+ QRect m_rctCloseTabIcon;
+
+ // Pictures
+ QPixmap m_pixDX;
+ QPixmap m_pixSX;
+ QPixmap m_pixDWNSX;
+ QPixmap m_pixDWNDX;
+ QPixmap m_pixDWN;
+ QPixmap m_pixKVIrcSX;
+ QPixmap m_pixKVIrcDWN;
+ QPixmap m_pixKVIrc;
+
+ QPixmap m_pixIconPrev;
+ QPixmap m_pixIconPrev_off;
+ QPixmap m_pixIconPrev_on;
+ QPixmap m_pixIconPrev_clicked;
+
+ QPixmap m_pixIconNext;
+ QPixmap m_pixIconNext_off;
+ QPixmap m_pixIconNext_on;
+ QPixmap m_pixIconNext_clicked;
+
+ QPixmap m_pixIconWrite;
+ QPixmap m_pixIconWrite_off;
+ QPixmap m_pixIconWrite_on;
+ QPixmap m_pixIconWrite_clicked;
+
+ bool m_bNeedToRedraw;
+
+ int m_prevIconState;
+ int m_nextIconState;
+ int m_writeIconState;
+
+public:
+
+protected:
+
+
+// ================================
+// Put methods declaration below...
+// ================================
+private:
+ void loadImages();
+
+public:
+ void setWidth(int w);
+ void setHeight(int h);
+ void resize(int w, int h) { setWidth(w); setHeight(h); };
+ void resize(QRect r) { setWidth(r.width()); setHeight(r.height()); };
+ void setPoint(int x, int y) { m_pnt.setX(x); m_pnt.setY(y); };
+
+ void setPrevIcon(int state);
+ void setNextIcon(int state);
+ void setWriteIcon(int state);
+
+ int nextIconState() { return m_nextIconState; };
+ int prevIconState() { return m_prevIconState; };
+ int writeIconState() { return m_writeIconState; };
+
+ int x() { return m_pnt.x(); };
+ int y() { return m_pnt.y(); };
+ int width() { return m_rct.width(); };
+ int height() { return m_rct.height(); };
+ int baseLine() { return (y()+height()); };
+
+ QRect rect() { return m_rct; };
+ QRect textRect() { return m_textRect; };
+ QRect rctPrevIcon() { return m_rctPrevIcon; };
+ QRect rctNextIcon() { return m_rctNextIcon; };
+ QRect rctWriteIcon() { return m_rctWriteIcon; };
+
+ void needToRedraw() { m_bNeedToRedraw = true; };
+
+ void recalculatePositions();
+ void touch() { m_bNeedToRedraw = true; };
+ void draw(QPainter *);
+
+ void mouseMoveEvent(QMouseEvent * e);
+ void mousePressEvent(QMouseEvent * e);
+ void mouseReleaseEvent(QMouseEvent * e);
+
+
+
+protected:
+
+};
+
+#endif //!_KVINOTIFIERWINDOWBODY_H_
diff --git a/src/modules/notifier/notifierwindowborder.cpp b/src/modules/notifier/notifierwindowborder.cpp
new file mode 100644
index 00000000..efd9ec0d
--- /dev/null
+++ b/src/modules/notifier/notifierwindowborder.cpp
@@ -0,0 +1,220 @@
+//=============================================================================
+//
+// File : kvinotifierwindowborder.cpp
+// Created on lun 03 gen 2005 02:27:22 by Iacopo Palazzi
+//
+// This file is part of the KVIrc distribution
+// Copyright (C) 2005 Iacopo Palazzi < iakko(at)siena(dot)linux(dot)it >
+//
+// 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 opinion) 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.
+//
+//=============================================================================
+
+#include "notifierwindowborder.h"
+#include "notifierwindowtabs.h"
+#include "kvi_iconmanager.h"
+
+#include <qpainter.h>
+
+KviNotifierWindowBorder::KviNotifierWindowBorder(QSize s)
+{
+ loadImages();
+ resize(s);
+}
+
+KviNotifierWindowBorder::~KviNotifierWindowBorder()
+{
+}
+
+void KviNotifierWindowBorder::loadImages() {
+
+ // Normal Border
+
+ QPixmap * p;
+
+ if((p = g_pIconManager->getPixmap("notifier_pix_wnd_sx.png")))
+ m_pixSX_N = *p;
+ if((p = g_pIconManager->getPixmap("notifier_pix_wnd_dx.png")))
+ m_pixDX_N = *p;
+ if((p = g_pIconManager->getPixmap("notifier_pix_wnd_dwn.png")))
+ m_pixDWN_N = *p;
+ if((p = g_pIconManager->getPixmap("notifier_pix_wnd_dwndx.png")))
+ m_pixDWNDX_N = *p;
+ if((p = g_pIconManager->getPixmap("notifier_pix_wnd_dwnsx.png")))
+ m_pixDWNSX_N = *p;
+ if((p = g_pIconManager->getPixmap("notifier_pix_caption_sx.png")))
+ m_pixCaptionSX_N = *p;
+ if((p = g_pIconManager->getPixmap("notifier_pix_caption_dx.png")))
+ m_pixCaptionDX_N = *p;
+ if((p = g_pIconManager->getPixmap("notifier_pix_caption_bkg.png")))
+ m_pixCaptionBKG_N = *p;
+
+ if((p = g_pIconManager->getPixmap("notifier_icon_close_out.png")))
+ m_pixIconClose_out_N = *p;
+ if((p = g_pIconManager->getPixmap("notifier_icon_close_over.png")))
+ m_pixIconClose_over_N = *p;
+ if((p = g_pIconManager->getPixmap("notifier_icon_close_clicked.png")))
+ m_pixIconClose_clicked_N = *p;
+
+ // Highlighted Border
+
+ if((p = g_pIconManager->getPixmap("notifier_pix_wnd_sx_hl.png")))
+ m_pixSX_HL = *p;
+ if((p = g_pIconManager->getPixmap("notifier_pix_wnd_dx_hl.png")))
+ m_pixDX_HL = *p;
+ if((p = g_pIconManager->getPixmap("notifier_pix_wnd_dwn_hl.png")))
+ m_pixDWN_HL = *p;
+ if((p = g_pIconManager->getPixmap("notifier_pix_wnd_dwndx_hl.png")))
+ m_pixDWNDX_HL = *p;
+ if((p = g_pIconManager->getPixmap("notifier_pix_wnd_dwnsx_hl.png")))
+ m_pixDWNSX_HL = *p;
+ if((p = g_pIconManager->getPixmap("notifier_pix_caption_sx_hl.png")))
+ m_pixCaptionSX_HL = *p;
+ if((p = g_pIconManager->getPixmap("notifier_pix_caption_dx_hl.png")))
+ m_pixCaptionDX_HL = *p;
+ if((p = g_pIconManager->getPixmap("notifier_pix_caption_bkg_hl.png")))
+ m_pixCaptionBKG_HL = *p;
+
+ if((p = g_pIconManager->getPixmap("notifier_icon_close_out_hl.png")))
+ m_pixIconClose_out_HL = *p;
+ if((p = g_pIconManager->getPixmap("notifier_icon_close_over_hl.png")))
+ m_pixIconClose_over_HL = *p;
+ if((p = g_pIconManager->getPixmap("notifier_icon_close_clicked_hl.png")))
+ m_pixIconClose_clicked_HL = *p;
+
+ setPics();
+ setCloseIcon(WDG_ICON_OUT);
+
+ if ( m_pixCaptionDX->height()==m_pixCaptionSX->height() && m_pixCaptionDX->height()==m_pixCaptionBKG->height()) // just to be sure that the height is fitting
+ m_captionRect.setHeight(m_pixCaptionDX->height());
+
+ // We want to see the tabs height to calculate the appropriate rect..
+ if((p = g_pIconManager->getPixmap("notifier_pix_tab_sx.png")))
+ m_iTabsHeight = p->height();
+ else
+ m_iTabsHeight = 10;
+
+ m_bNeedToRedraw = true;
+
+}
+
+void KviNotifierWindowBorder::setPics(bool b)
+{
+ if (b) {
+ m_pixSX = &m_pixSX_HL;
+ m_pixDX = &m_pixDX_HL;
+ m_pixDWN = &m_pixDWN_HL;
+ m_pixDWNSX = &m_pixDWNSX_HL;
+ m_pixDWNDX = &m_pixDWNDX_HL;
+ m_pixCaptionSX = &m_pixCaptionSX_HL;
+ m_pixCaptionDX = &m_pixCaptionDX_HL;
+ m_pixCaptionBKG = &m_pixCaptionBKG_HL;
+ m_pixIconClose_out = &m_pixIconClose_out_HL;
+ m_pixIconClose_over = &m_pixIconClose_over_HL;
+ m_pixIconClose_clicked = &m_pixIconClose_clicked_HL;
+ } else {
+ m_pixSX = &m_pixSX_N;
+ m_pixDX = &m_pixDX_N;
+ m_pixDWN = &m_pixDWN_N;
+ m_pixDWNSX = &m_pixDWNSX_N;
+ m_pixDWNDX = &m_pixDWNDX_N;
+ m_pixCaptionSX = &m_pixCaptionSX_N;
+ m_pixCaptionDX = &m_pixCaptionDX_N;
+ m_pixCaptionBKG = &m_pixCaptionBKG_N;
+ m_pixIconClose_out = &m_pixIconClose_out_N;
+ m_pixIconClose_over = &m_pixIconClose_over_N;
+ m_pixIconClose_clicked = &m_pixIconClose_clicked_N;
+ }
+}
+
+void KviNotifierWindowBorder::setWidth(int w) {
+ m_iRctWidth = w;
+ recalculatePositions();
+}
+
+void KviNotifierWindowBorder::setHeight(int h) {
+ m_iRctHeight = h;
+ recalculatePositions();
+}
+
+void KviNotifierWindowBorder::recalculatePositions()
+{
+ m_rct.setHeight(m_iRctHeight);
+ m_rct.setWidth(m_iRctWidth);
+ m_rct.setTopLeft(QPoint(0,0));
+
+ m_closeIconRect.setX(m_rct.width()-m_pixCaptionDX->width()-m_pixIconClose->width());
+ m_closeIconRect.setY(2);
+ m_closeIconRect.setWidth(m_pixIconClose->width());
+ m_closeIconRect.setHeight(m_pixIconClose->height());
+
+ m_captionRect.setTopLeft( m_rct.topLeft() );
+ m_captionRect.setSize( QSize(m_rct.width(),m_pixCaptionDX->height()) );
+
+ m_tabsRect.setTopLeft( QPoint(m_pixCaptionDX->width()+7,m_captionRect.height()) );
+ m_tabsRect.setSize( QSize(m_captionRect.width()-(2*m_pixCaptionDX->width())-7,m_iTabsHeight) );
+
+ m_bodyRect.setTopLeft( QPoint(m_pixCaptionDX->width()+7,m_captionRect.height()+m_tabsRect.height()) );
+ m_bodyRect.setSize( QSize(m_captionRect.width()-(2*m_pixCaptionDX->width())-7,m_rct.height()-m_captionRect.height()-m_pixDWN->height()-m_tabsRect.height()) );
+
+ m_titleRect.setTopLeft( QPoint(m_pixCaptionSX->width(), (m_captionRect.height()-m_iTitleFontHeight)/2 ) );
+ m_titleRect.setSize( QSize(m_rct.width()-m_pixCaptionSX->width()-m_pixCaptionDX->width(),m_iTitleFontHeight) );
+
+ m_progressRect.setTopLeft( QPoint(m_pixCaptionDX->width(),m_pixCaptionDX->height()));
+ m_progressRect.setSize( QSize(6,m_iRctHeight-m_pixCaptionDX->height()-m_pixDWN->height()));
+
+ m_bNeedToRedraw = true;
+}
+
+void KviNotifierWindowBorder::setCloseIcon(int state) {
+ m_bNeedToRedraw = true; m_eIconState = state;
+ switch (m_eIconState) {
+ case WDG_ICON_OUT: m_pixIconClose = m_pixIconClose_out; break;
+ case WDG_ICON_OVER: m_pixIconClose = m_pixIconClose_over; break;
+ case WDG_ICON_CLICKED: m_pixIconClose = m_pixIconClose_clicked; break;
+ };
+}
+
+void KviNotifierWindowBorder::resetIcons() {
+ setCloseIcon(WDG_ICON_OUT);
+}
+
+void KviNotifierWindowBorder::draw(QPainter * p, bool b) {
+
+ if (m_bNeedToRedraw) {
+ setPics(b);
+ setCloseIcon(m_eIconState);
+
+ // Draw the caption
+ p->drawPixmap(m_captionRect.x(), m_captionRect.y(), *m_pixCaptionSX);
+ p->drawTiledPixmap(m_pixCaptionSX->width(), 0, m_captionRect.width() - (m_pixCaptionSX->width() + m_pixCaptionDX->width()), m_captionRect.height(), *m_pixCaptionBKG);
+ p->drawPixmap(m_captionRect.width() - m_pixCaptionDX->width(), 0, *m_pixCaptionDX);
+
+ // Draw the tiled borders
+ p->drawTiledPixmap(0, m_captionRect.height(), m_pixSX->width(), m_bodyRect.height() + m_iTabsHeight, *m_pixSX);
+ p->drawTiledPixmap(m_bodyRect.width() + m_bodyRect.x(), m_captionRect.height(), m_pixDX->width(), m_bodyRect.height() + m_iTabsHeight, *m_pixDX);
+ p->drawTiledPixmap(m_pixDWNSX->width(), m_captionRect.height() + m_bodyRect.height() + m_iTabsHeight, m_bodyRect.width() + m_progressRect.width() + 1, m_pixDWN->height(), *m_pixDWN);
+
+ // Draw down corners
+ p->drawPixmap(0, m_captionRect.height() + m_bodyRect.height() + m_iTabsHeight, *m_pixDWNSX);
+ p->drawPixmap(m_bodyRect.width() + m_bodyRect.x(), m_captionRect.height() + m_bodyRect.height() + m_iTabsHeight, *m_pixDWNDX);
+
+ //Drawing icons
+ p->drawPixmap(m_closeIconRect.x(), m_closeIconRect.y(), *m_pixIconClose);
+
+ m_bNeedToRedraw = false;
+ }
+
+}
diff --git a/src/modules/notifier/notifierwindowborder.h b/src/modules/notifier/notifierwindowborder.h
new file mode 100644
index 00000000..5c36827b
--- /dev/null
+++ b/src/modules/notifier/notifierwindowborder.h
@@ -0,0 +1,154 @@
+#ifndef _KVINOTIFIERWINDOWBORDER_H_
+#define _KVINOTIFIERWINDOWBORDER_H_
+//=============================================================================
+//
+// File : kvinotifierwindowborder.h
+// Created on lun 03 gen 2005 02:27:22 by Iacopo Palazzi
+//
+// This file is part of the KVIrc distribution
+// Copyright (C) 2005 Iacopo Palazzi < iakko(at)siena(dot)linux(dot)it >
+//
+// 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 opinion) 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.
+//
+//=============================================================================
+
+#include "notifiersettings.h"
+
+#include <qsize.h>
+#include <qrect.h>
+#include <qpixmap.h>
+
+class QPainter;
+
+class KviNotifierWindowBorder
+{
+public:
+ KviNotifierWindowBorder(QSize = QSize(WDG_MIN_WIDTH,WDG_MIN_HEIGHT));
+ ~KviNotifierWindowBorder();
+
+// ================================
+// Put members declaration below...
+// ================================
+private:
+ QRect m_rct;
+ QPoint m_pnt;
+
+ QRect m_closeIconRect;
+
+ QRect m_captionRect;
+ QRect m_bodyRect;
+ QRect m_tabsRect;
+ QRect m_titleRect;
+
+ QRect m_progressRect;
+
+ // Pictures
+ QPixmap * m_pixSX;
+ QPixmap * m_pixDX;
+ QPixmap * m_pixDWN;
+ QPixmap * m_pixDWNSX;
+ QPixmap * m_pixDWNDX;
+ QPixmap * m_pixCaptionSX;
+ QPixmap * m_pixCaptionDX;
+ QPixmap * m_pixCaptionBKG;
+ QPixmap * m_pixIconClose_out;
+ QPixmap * m_pixIconClose_over;
+ QPixmap * m_pixIconClose_clicked;
+ QPixmap * m_pixIconClose;
+
+ QPixmap m_pixSX_N;
+ QPixmap m_pixDX_N;
+ QPixmap m_pixDWN_N;
+ QPixmap m_pixDWNSX_N;
+ QPixmap m_pixDWNDX_N;
+ QPixmap m_pixCaptionSX_N;
+ QPixmap m_pixCaptionDX_N;
+ QPixmap m_pixCaptionBKG_N;
+ QPixmap m_pixIconClose_out_N;
+ QPixmap m_pixIconClose_over_N;
+ QPixmap m_pixIconClose_clicked_N;
+
+ QPixmap m_pixSX_HL;
+ QPixmap m_pixDX_HL;
+ QPixmap m_pixDWN_HL;
+ QPixmap m_pixDWNSX_HL;
+ QPixmap m_pixDWNDX_HL;
+ QPixmap m_pixCaptionSX_HL;
+ QPixmap m_pixCaptionDX_HL;
+ QPixmap m_pixCaptionBKG_HL;
+ QPixmap m_pixIconClose_out_HL;
+ QPixmap m_pixIconClose_over_HL;
+ QPixmap m_pixIconClose_clicked_HL;
+
+ int m_iTabsHeight;
+ int m_iTitleFontHeight;
+ int m_eIconState;
+ int m_iRctWidth;
+ int m_iRctHeight;
+
+ bool m_bNeedToRedraw;
+
+public:
+protected:
+
+
+// ================================
+// Put methods declaration below...
+// ================================
+private:
+ void loadImages();
+ void recalculatePositions();
+
+public:
+ // reading methods...
+ void setWidth(int w);
+ void setHeight(int h);
+ void resize(int w, int h) { setWidth(w); setHeight(h); };
+ void resize(QSize r) { setWidth(r.width()); setHeight(r.height()); };
+ void setGeometry(QRect r) { r.topLeft(); r.size(); /*debug("x,y: %d,%d", r.x(), r.y()); debug("w,h: %d,%d", r.width(), r.height());*/ };
+ void setGeometry(QPoint p, QSize s) { setPoint (p.x(), p.y()); setWidth (s.width()); setHeight (s.height()); };
+
+ void setPoint(int x, int y) { m_pnt.setX(x); m_pnt.setY(y); m_rct.setX(x); m_rct.setY(y); };
+
+ void setCloseIcon(int state);
+ void resetIcons();
+
+ // writing methods...
+ int x() { return m_pnt.x(); };
+ int y() { return m_pnt.y(); };
+ int width() { return m_rct.width(); };
+ int height() { return m_rct.height(); };
+ int baseLine() { return (y()+height()); };
+
+ QRect bodyRect() { return m_bodyRect; };
+ QRect tabsRect() { return m_tabsRect; };
+ QRect captionRect() { return m_captionRect; };
+ QRect rect() { return m_rct; };
+ QRect closeRect() { return m_closeIconRect; };
+ QRect titleRect() { return m_titleRect; };
+ QRect progressRect() { return m_progressRect; };
+
+ void centerTitle(int h) { m_iTitleFontHeight = h; };
+
+ void touch() { m_bNeedToRedraw = true; };
+
+ void draw(QPainter *, bool b = false);
+ void setPics(bool b = false);
+
+protected:
+
+};
+
+#endif //!_KVINOTIFIERWINDOWBORDER_H_
diff --git a/src/modules/notifier/notifierwindowprogressbar.cpp b/src/modules/notifier/notifierwindowprogressbar.cpp
new file mode 100644
index 00000000..72bbdecf
--- /dev/null
+++ b/src/modules/notifier/notifierwindowprogressbar.cpp
@@ -0,0 +1,51 @@
+//=============================================================================
+//
+// File : notifierwindowprogressbar.cpp
+// Created on Tue 17 Apr 2007 10:24:01 by Iacopo Palazzi
+//
+// This file is part of the KVIrc distribution
+// Copyright (C) 2007 Iacopo Palazzi < iakko(at)siena.linux.it >
+//
+// 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 opinion) 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.
+//
+//=============================================================================
+
+#include "notifierwindowprogressbar.h"
+
+KviNotifierWindowProgressBar::KviNotifierWindowProgressBar(QRect r)
+: m_rect(r)
+{
+
+}
+
+KviNotifierWindowProgressBar::~KviNotifierWindowProgressBar()
+{
+ m_dProgress = 0;
+}
+
+void KviNotifierWindowProgressBar::draw(QPainter *p)
+{
+ p->fillRect(m_rect, QColor(236, 233, 216));
+ p->fillRect(
+ QRect(
+ m_rect.x()+1,
+ m_rect.y()+1 + m_rect.height() * (1 - m_dProgress),
+ m_rect.width() - 2,
+ (m_rect.height() - 2) * m_dProgress
+ ),
+ QColor(175, 28, 95)
+ );
+ p->drawRect(m_rect);
+}
diff --git a/src/modules/notifier/notifierwindowprogressbar.h b/src/modules/notifier/notifierwindowprogressbar.h
new file mode 100644
index 00000000..ec527d2e
--- /dev/null
+++ b/src/modules/notifier/notifierwindowprogressbar.h
@@ -0,0 +1,67 @@
+#ifndef _NOTIFIERWINDOWPROGRESSBAR_H_
+#define _NOTIFIERWINDOWPROGRESSBAR_H_
+//=============================================================================
+//
+// File : notifierwindowprogressbar.h
+// Created on Tue 17 Apr 2007 10:24:01 by Iacopo Palazzi
+//
+// This file is part of the KVIrc distribution
+// Copyright (C) 2007 Iacopo Palazzi < iakko(at)siena.linux.it >
+//
+// 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 opinion) 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.
+//
+//=============================================================================
+
+#include <qrect.h>
+#include <qpainter.h>
+
+class KviNotifierWindowProgressBar
+{
+public:
+ KviNotifierWindowProgressBar(QRect r);
+ ~KviNotifierWindowProgressBar();
+
+// ================================
+// Put members declaration below...
+// ================================
+private:
+
+public:
+
+protected:
+ QRect m_rect;
+ double m_dProgress;
+
+// ================================
+// Put methods declaration below...
+// ================================
+private:
+
+public:
+ int x() { return m_rect.x(); };
+ int y() { return m_rect.y(); };
+ int width() { return m_rect.width(); };
+ int height() { return m_rect.height(); };
+
+ void setHeight(int p_iHeight) { m_rect.setHeight(p_iHeight); };
+ void setProgress(double progress) { m_dProgress=progress; };
+ void draw(QPainter *);
+
+protected:
+
+
+};
+
+#endif //!_NOTIFIERWINDOWPROGRESSBAR_H_
diff --git a/src/modules/notifier/notifierwindowtabs.cpp b/src/modules/notifier/notifierwindowtabs.cpp
new file mode 100644
index 00000000..9eaa2f12
--- /dev/null
+++ b/src/modules/notifier/notifierwindowtabs.cpp
@@ -0,0 +1,705 @@
+//=============================================================================
+//
+// File : kvinotifierwindowtabs.cpp
+// Created on dom 02 gen 2005 15:30:50 by Iacopo Palazzi
+//
+// This file is part of the KVIrc irc client distribution
+// Copyright (C) 2005 Iacopo Palazzi < iakko(at)siena(dot)linux(dot)it >
+//
+// 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_app.h"
+#include "kvi_config.h"
+#include "kvi_qstring.h"
+#include "kvi_iconmanager.h"
+#include "kvi_locale.h"
+#include "kvi_options.h"
+#include "kvi_window.h"
+
+#include <qevent.h>
+#include <qpainter.h>
+#include <qbrush.h>
+#include <qcolor.h>
+#include <qfontmetrics.h>
+
+#include "notifiermessage.h"
+#include "notifierwindowtabs.h"
+
+extern KviNotifierWindow * g_pNotifierWindow;
+KviNotifierWindowTabs * g_pTabs;
+
+
+// --- tab object definition class
+
+KviNotifierWindowTab::KviNotifierWindowTab(KviWindow * pWnd, QString label)
+{
+ m_pWnd = pWnd;
+ m_label = label;
+ m_pMessageList = new KviPointerList<KviNotifierMessage>;
+ m_pMessageList->setAutoDelete(true);
+ m_bFocused = false;
+ m_pCurrentMessage = 0;
+
+ KviStr buffer;
+ g_pApp->getReadOnlyConfigPath(buffer,"libkvinotifier.kvc",KviApp::ConfigPlugins,true);
+ KviConfig cfg(buffer.ptr(),KviConfig::Read);
+ cfg.setGroup("NotifierSkin");
+ m_clrHighlightedLabel = cfg.readColorEntry("HighlightedTabLablerColor",QColor(200,0,0));
+ m_clrNormalLabel = cfg.readColorEntry("NormalTabLablerColor",QColor(0,0,0));
+ m_clrChangedLabel = cfg.readColorEntry("ChangedTabLablerColor",QColor(0,0,100));
+
+ if(pWnd)
+ {
+ connect(pWnd,SIGNAL(windowNameChanged()),this,SLOT(labelChanged()));
+ connect(pWnd,SIGNAL(destroyed()),this,SLOT(closeMe()));
+ }
+}
+
+KviNotifierWindowTab::~KviNotifierWindowTab()
+{
+ delete m_pMessageList;
+}
+
+void KviNotifierWindowTab::setNextMessageAsCurrent()
+{
+ if(!m_pCurrentMessage)return;
+ if(m_pMessageList->findRef(m_pCurrentMessage) == -1)return;
+ m_pCurrentMessage = m_pMessageList->next();
+ if(!m_pCurrentMessage)m_pCurrentMessage = m_pMessageList->last();
+}
+
+void KviNotifierWindowTab::setPrevMessageAsCurrent()
+{
+ if(!m_pCurrentMessage)return;
+ if(!m_pMessageList->findRef(m_pCurrentMessage) == -1)return;
+ m_pCurrentMessage = m_pMessageList->prev();
+ if(!m_pCurrentMessage)m_pCurrentMessage = m_pMessageList->first();
+}
+
+void KviNotifierWindowTab::setLastMessageAsCurrent()
+{
+ m_pCurrentMessage = m_pMessageList->last();
+}
+
+void KviNotifierWindowTab::appendMessage(KviNotifierMessage * m)
+{
+ if(m_pCurrentMessage == m_pMessageList->last())m_pCurrentMessage = m;
+ m_pMessageList->append(m);
+ // avoid having too much messages floating around
+ while(m_pMessageList->count() > MAX_MESSAGES_IN_WINDOW)
+ {
+ m = m_pMessageList->first();
+ m_pMessageList->removeFirst();
+ if(m == m_pCurrentMessage)
+ m_pCurrentMessage = m_pMessageList->first();
+ }
+ if(focused())setState(Normal);
+ else setState(Highlighted);
+}
+
+void KviNotifierWindowTab::labelChanged()
+{
+ if(!m_pWnd)return;
+ m_label = m_pWnd->windowName();
+ setState(Changed);
+ g_pTabs->needToRedraw();
+ g_pNotifierWindow->update();
+}
+
+void KviNotifierWindowTab::closeMe()
+{
+ g_pTabs->closeTab(this);
+}
+
+void KviNotifierWindowTab::setFocused(bool b)
+{
+ m_bFocused = b;
+ if(m_bFocused)setState(Normal);
+}
+
+void KviNotifierWindowTab::setState(TabState state)
+{
+ m_eState=state;
+ switch (m_eState) {
+ case Normal:
+ m_cLabel = m_clrNormalLabel;
+ break;
+ case Highlighted:
+ m_cLabel = m_clrHighlightedLabel;
+ break;
+ case Changed:
+ m_cLabel = m_clrChangedLabel;
+ break;
+ }
+};
+
+int KviNotifierWindowTab::width(bool b) {
+ int width = 0;
+ QFont * font;
+
+ QPixmap * sx;
+ QPixmap * dx;
+
+ if (focused()) {
+ font = g_pTabs->fontFocused();
+ sx = g_pTabs->tabFocusedPixSx();
+ dx = g_pTabs->tabFocusedPixSx();
+ } else {
+ sx = g_pTabs->tabUnfocusedPixSx();
+ dx = g_pTabs->tabUnfocusedPixSx();
+ font = g_pTabs->fontUnfocused();
+ }
+
+ QFontMetrics fm(*font);
+ width = fm.width(label())+2;
+ if (!b) width += sx->width() + dx->width();
+
+ return width;
+}
+
+// ##################################################################################à
+// ### end of tab object definition class
+// ##################################################################################à
+
+
+KviNotifierWindowTabs::KviNotifierWindowTabs(QRect r)
+{
+ g_pTabs = this;
+ m_pPixmap = new QPixmap();
+ m_pPainter = new QPainter();
+ m_pTabFocused = 0;
+ m_pWndTabFocused = 0;
+ m_iTabToStartFrom = 0;
+
+ m_tabPtrList.setAutoDelete(false); // FIXME: should take a closer look at this
+ m_lastVisitedTabPtrList.setAutoDelete(false);
+
+ loadImages();
+ initConfig();
+ resize(r);
+}
+
+KviNotifierWindowTabs::~KviNotifierWindowTabs()
+{
+ QMap<KviWindow *, KviNotifierWindowTab *>::Iterator tab;
+ for(tab = m_tabMap.begin(); tab != m_tabMap.end(); tab++ )
+ delete tab.data();
+ m_tabMap.clear();
+ delete m_pFocusedFont;
+ delete m_pUnfocusedFont;
+ delete m_pPainter;
+ delete m_pPixmap;
+}
+
+void KviNotifierWindowTabs::initConfig()
+{
+ KviStr buffer;
+ g_pApp->getReadOnlyConfigPath(buffer,"libkvinotifier.kvc",KviApp::ConfigPlugins,true);
+
+ KviConfig cfg(buffer.ptr(),KviConfig::Read);
+
+ cfg.setGroup("NotifierSkin");
+
+ QString szFamily = cfg.readEntry("TextFontFocusedTab","Arial");
+ m_pFocusedFont = new QFont(szFamily,cfg.readIntEntry("TextFocusedFontSize",10));
+ m_pFocusedFont->setBold(true);
+ szFamily = cfg.readEntry("TextFontUnfocusedTab","Arial");
+ m_pUnfocusedFont = new QFont(szFamily,cfg.readIntEntry("TextUnfocusedFontSize",9));
+}
+
+void KviNotifierWindowTabs::loadImages()
+{
+ QPixmap * p;
+ if((p = g_pIconManager->getPixmap("notifier_pix_tab_dx.png")))
+ m_pixDX = *p;
+ if((p = g_pIconManager->getPixmap("notifier_pix_tab_sx.png")))
+ m_pixSX = *p;
+ if((p = g_pIconManager->getPixmap("notifier_pix_tab_bkg.png")))
+ m_pixBKG = *p;
+ if((p = g_pIconManager->getPixmap("notifier_pix_tab_focused_sx.png")))
+ m_pixSXFocused = *p;
+ if((p = g_pIconManager->getPixmap("notifier_pix_tab_focused_dx.png")))
+ m_pixDXFocused = *p;
+ if((p = g_pIconManager->getPixmap("notifier_pix_tab_focused_bkg.png")))
+ m_pixBKGFocused = *p;
+ if((p = g_pIconManager->getPixmap("notifier_pix_tab_unfocused_sx.png")))
+ m_pixSXUnfocused = *p;
+ if((p = g_pIconManager->getPixmap("notifier_pix_tab_unfocused_dx.png")))
+ m_pixDXUnfocused = *p;
+ if((p = g_pIconManager->getPixmap("notifier_pix_tab_unfocused_bkg.png")))
+ m_pixBKGUnfocused = *p;
+
+ if((p = g_pIconManager->getPixmap("notifier_icon_tab_next_out.png")))
+ m_pixIconTabNext_out = *p;
+ if((p = g_pIconManager->getPixmap("notifier_icon_tab_next_over.png")))
+ m_pixIconTabNext_over = *p;
+ if((p = g_pIconManager->getPixmap("notifier_icon_tab_next_clicked.png")))
+ m_pixIconTabNext_clicked = *p;
+
+ m_pixIconTabNext = m_pixIconTabNext_out;
+
+ if((p = g_pIconManager->getPixmap("notifier_icon_tab_prev_out.png")))
+ m_pixIconTabPrev_out = *p;
+ if((p = g_pIconManager->getPixmap("notifier_icon_tab_prev_over.png")))
+ m_pixIconTabPrev_over = *p;
+ if((p = g_pIconManager->getPixmap("notifier_icon_tab_prev_clicked.png")))
+ m_pixIconTabPrev_clicked = *p;
+
+ m_pixIconTabPrev = m_pixIconTabPrev_out;
+
+ if((p = g_pIconManager->getPixmap("notifier_icon_tab_close_off.png")))
+ m_pixIconCloseTab_off = *p;
+ if((p = g_pIconManager->getPixmap("notifier_icon_tab_close_on.png")))
+ m_pixIconCloseTab_on = *p;
+ if((p = g_pIconManager->getPixmap("notifier_icon_tab_close_clicked.png")))
+ m_pixIconCloseTab_clicked = *p;
+
+ m_pixIconCloseTab = m_pixIconCloseTab_off;
+
+ m_closeTabIconState = WDG_ICON_OFF;
+
+}
+
+
+
+void KviNotifierWindowTabs::addMessage(KviWindow * pWnd, KviNotifierMessage * message)
+{
+ QString sender = pWnd ? pWnd->windowName() : "----";
+
+ // Qui servirebbe anche una lista... perche' quando si inserisce
+ // un tab lui lo piazza dove gli pare nell'ordine
+ // e quindi iterando i tab nuovi possono trovarsi PRIMA dei tab vecchi
+ // il che' confonde un po
+ KviNotifierWindowTab * tab;
+ if (!m_tabMap.contains(pWnd)) {
+ m_tabMap.insert(pWnd, tab = new KviNotifierWindowTab(pWnd, sender));
+ m_tabPtrList.append(tab);
+ } else {
+ tab = m_tabMap[pWnd];
+ }
+
+ tab->appendMessage(message);
+
+ if((g_pNotifierWindow->state()==Hidden) || (!m_pTabFocused))
+ {
+ setFocusOn(tab);
+ } else {
+ needToRedraw();
+ }
+}
+
+void KviNotifierWindowTabs::resize(QRect r)
+{
+ m_rct.setX(r.x());
+ m_rct.setY(r.y());
+ m_rct.setHeight(r.height());
+ setWidth(r.width());
+
+ recalculatePositions();
+}
+
+void KviNotifierWindowTabs::setWidth(int w) {
+ m_rct.setWidth(w);
+ recalculatePositions();
+}
+
+void KviNotifierWindowTabs::recalculatePositions()
+{
+ m_rctCloseTabIcon.setX(m_rct.x()+m_rct.width()-m_pixIconCloseTab.width());
+ m_rctCloseTabIcon.setY(m_rct.y());
+ m_rctCloseTabIcon.setWidth(m_pixIconCloseTab.width());
+ m_rctCloseTabIcon.setHeight(m_pixIconCloseTab.height());
+ // The sensible area for the Close Icon
+ m_rctCloseTabIconHotArea.setX(m_rctCloseTabIcon.x()+6);
+ m_rctCloseTabIconHotArea.setY(m_rctCloseTabIcon.y()+3);
+ m_rctCloseTabIconHotArea.setWidth(16);
+ m_rctCloseTabIconHotArea.setHeight(16);
+
+ if (m_bIsOverRightBound) {
+ m_rctNextIcon.setX(m_rct.x() + m_rct.width() - m_rctCloseTabIcon.width() - m_pixIconTabNext.width());
+ m_rctNextIcon.setY(m_rct.y());
+ m_rctNextIcon.setWidth(m_pixIconTabNext.width());
+ m_rctNextIcon.setHeight(m_pixIconTabNext.height());
+ }
+
+ if (m_bIsOverLeftBound) {
+ m_rctPrevIcon.setX(m_rct.x());
+ m_rctPrevIcon.setY(m_rct.y());
+ m_rctPrevIcon.setWidth(m_pixIconTabPrev.width());
+ m_rctPrevIcon.setHeight(m_pixIconTabPrev.height());
+ }
+
+ int tmpX, tmpWidth;
+
+ tmpWidth = m_rctCloseTabIcon.x() - m_rct.x();
+
+ if (m_bIsOverRightBound) {
+ tmpWidth -= m_rctNextIcon.width();
+ }
+
+ if (m_bIsOverLeftBound) {
+ tmpWidth -= m_rctPrevIcon.width();
+ tmpX = m_rct.x() + m_rctPrevIcon.width();
+ } else {
+ tmpX = m_rct.x();
+ }
+
+ m_rctTabs.setX(tmpX);
+ m_rctTabs.setY(m_rct.y());
+
+ m_rctTabs.setWidth(tmpWidth);
+ m_rctTabs.setHeight(m_rct.height());
+
+ needToRedraw();
+}
+
+void KviNotifierWindowTabs::prev()
+{
+ if(!m_pTabFocused)return;
+
+ KviNotifierWindowTab * tab;
+ KviPointerListIterator<KviNotifierWindowTab> tabIterator (m_tabPtrList);
+
+ tab = m_tabMap[m_pTabFocused->wnd()];
+
+ tabIterator.moveFirst();
+
+ while ((tabIterator.current()) != tab) {
+ ++tabIterator;
+ }
+
+ if (!tabIterator.moveFirst()) {
+ --tabIterator;
+ tab = tabIterator.current();
+ setFocusOn(tab);
+ }
+
+}
+
+void KviNotifierWindowTabs::next()
+{
+ if(!m_pTabFocused)return;
+
+ KviNotifierWindowTab * tab;
+ KviPointerListIterator<KviNotifierWindowTab> tabIterator (m_tabPtrList);
+
+ tab = m_tabMap[m_pTabFocused->wnd()];
+ tabIterator.moveFirst();
+ while ((tabIterator.current()) != tab) {
+ ++tabIterator;
+ }
+
+ if (!tabIterator.moveLast()) {
+ ++tabIterator;
+ tab = tabIterator.current();
+ setFocusOn(tab);
+ }
+
+}
+
+void KviNotifierWindowTabs::mousePressEvent(QMouseEvent * e) {
+
+ if (m_bIsOverRightBound && m_rctNextIcon.contains(e->pos())) {
+ return;
+ }
+
+ if (m_bIsOverLeftBound && m_rctPrevIcon.contains(e->pos())) {
+ return;
+ }
+
+ if(m_rctTabs.contains(e->pos()))
+ {
+ QMap<KviWindow *, KviNotifierWindowTab *>::Iterator tab;
+ for (tab = m_tabMap.begin(); tab != m_tabMap.end(); tab++ ) {
+ if (tab.data()->rect().contains(e->pos())) {
+ setFocusOn(tab.data());
+ return;
+ }
+ }
+ }
+
+ if (m_rctCloseTabIconHotArea.contains(e->pos())) {
+ setCloseTabIcon(WDG_ICON_CLICKED);
+ return;
+ }
+
+}
+
+void KviNotifierWindowTabs::mouseMoveEvent(QMouseEvent * e)
+{
+ if (m_rctCloseTabIconHotArea.contains(e->pos()))
+ {
+ setCloseTabIcon(WDG_ICON_ON);
+ } else {
+ if (closeTabIconState()!=WDG_ICON_OFF)
+ setCloseTabIcon(WDG_ICON_OFF);
+ }
+}
+
+void KviNotifierWindowTabs::mouseReleaseEvent(QMouseEvent * e)
+{
+
+ if (m_bIsOverRightBound && m_rctNextIcon.contains(e->pos())) {
+ scrollTabsLeft();
+ return;
+ }
+
+ if (m_bIsOverLeftBound && m_rctPrevIcon.contains(e->pos())) {
+ scrollTabsRight();
+ return;
+ }
+
+ if(currentTab())
+ {
+ if (rctCloseTabIconHotArea().contains(e->pos()))
+ {
+ closeCurrentTab();
+ g_pNotifierWindow->update();
+ }
+ }
+
+}
+
+void KviNotifierWindowTabs::scrollTabsLeft() {
+ if (m_bIsOverRightBound) {
+ m_iTabToStartFrom++;
+ }
+ needToRedraw();
+ g_pNotifierWindow->update();
+};
+
+void KviNotifierWindowTabs::scrollTabsRight() {
+ if (m_bIsOverLeftBound) {
+ m_iTabToStartFrom--;
+ }
+ needToRedraw();
+ g_pNotifierWindow->update();
+};
+
+void KviNotifierWindowTabs::setCloseTabIcon(int state) {
+
+ //if (m_writeIconState==WDG_ICON_OFF && state!=WDG_ICON_OFF)
+ if (m_closeTabIconState!=state) {
+ switch (state) {
+ case WDG_ICON_ON: m_pixIconCloseTab = m_pixIconCloseTab_on; break;
+ case WDG_ICON_OFF: m_pixIconCloseTab = m_pixIconCloseTab_off; break;
+ case WDG_ICON_CLICKED: m_pixIconCloseTab = m_pixIconCloseTab_clicked; break;
+ }
+ needToRedraw();
+ m_closeTabIconState = state;
+ }
+}
+
+void KviNotifierWindowTabs::resetIcons()
+{
+ setCloseTabIcon(WDG_ICON_OFF);
+}
+
+void KviNotifierWindowTabs::setFocusOn(KviNotifierWindowTab * tab)
+{
+ if(m_pTabFocused)m_pTabFocused->setFocused(false);
+ m_pTabFocused = tab;
+ if(m_pTabFocused)m_pTabFocused->setFocused();
+
+ m_lastVisitedTabPtrList.removeRef(tab);
+
+ m_lastVisitedTabPtrList.insert(0, tab);
+
+ needToRedraw();
+
+ g_pNotifierWindow->update();
+}
+
+void KviNotifierWindowTabs::draw(QPainter * p)
+{
+ if(!m_bNeedToRedraw)return;
+
+ m_pPixmap->resize(m_rct.width(), m_rct.height());
+
+ m_pPainter->begin(m_pPixmap);
+
+ QFont tmpFont;
+ tmpFont = p->font();
+
+ m_pPainter->setFont(tmpFont);
+
+ QString str;
+
+ bool isBigger = false;
+
+ int offset = 0;
+
+ int closeIcon_X = m_rct.width() - m_rctCloseTabIcon.width();
+ int nextIcon_X = closeIcon_X - m_pixIconTabNext_out.width();
+ int prevIcon_X = m_rct.x();
+
+ int tmpTabsWidth = 0;
+
+ m_pPainter->drawPixmap(0,0,m_pixSX);
+ m_pPainter->drawPixmap(m_rct.width()-m_pixDX.width(),0,m_pixDX);
+ m_pPainter->drawTiledPixmap(m_pixSX.width(),0,m_rct.width()-m_pixSX.width()-m_pixDX.width(),m_rct.height(),m_pixBKG);
+
+ KviPointerListIterator<KviNotifierWindowTab> tabIterator (m_tabPtrList);
+
+ //m_tabPtrList.findRef(m_tabMap[m_pTabFocused->wnd()]);
+
+// QMap<KviWindow *, KviNotifierWindowTab *>::Iterator tab;
+ KviNotifierWindowTab * tab;
+ //for (tab = m_tabMap.begin(); tab != m_tabMap.end() && !isBigger; tab++ )
+ tabIterator.moveFirst();
+
+ int i = 0;
+ while(m_iTabToStartFrom!=i) {
+ i++;
+ ++tabIterator;
+ }
+
+ while ( ((tab = tabIterator.current()) != 0) && !isBigger)
+ {
+ ++tabIterator;
+
+ if (tab->focused()) {
+
+ m_pPainter->setFont(*m_pFocusedFont);
+
+ tab->setRect(m_rct.x() + offset, m_rctTabs.y(), tab->width(), m_rctTabs.height());
+
+ m_pPainter->drawPixmap(offset,0,m_pixSXFocused);
+ m_pPainter->drawTiledPixmap(offset+m_pixSXFocused.width(),0,tab->width(true),m_rctTabs.height(),m_pixBKGFocused);
+ m_pPainter->drawPixmap(offset+m_pixSXFocused.width()+tab->width(true),0,m_pixDXFocused);
+ QPen tmpP = m_pPainter->pen(); m_pPainter->setPen(tab->labelColor());
+ m_pPainter->drawText(offset+m_pixSXFocused.width()+1,m_rctTabs.height()-NTF_TABS_FONT_BASELINE,tab->label());
+ m_pPainter->setPen(tmpP);
+
+ offset += tab->width();
+
+ } else {
+
+ m_pPainter->setFont(*m_pUnfocusedFont);
+
+ tab->setRect(m_rct.x() + offset, m_rctTabs.y(), tab->width(), m_rctTabs.height());
+
+ m_pPainter->drawPixmap(offset, 0, m_pixSXUnfocused);
+ m_pPainter->drawTiledPixmap(offset+m_pixSXUnfocused.width(), 0, tab->width(true), m_rctTabs.height(), m_pixBKGUnfocused);
+ m_pPainter->drawPixmap(offset+m_pixSXUnfocused.width()+tab->width(true), 0, m_pixDXUnfocused);
+ QPen tmpP = m_pPainter->pen(); m_pPainter->setPen(tab->labelColor());
+ m_pPainter->drawText(offset+m_pixSXUnfocused.width()+1,m_rctTabs.height()-NTF_TABS_FONT_BASELINE+1,tab->label());
+ m_pPainter->setPen(tmpP);
+ offset += tab->width();
+ }
+
+ if (offset > m_rctTabs.width()) isBigger = true; else isBigger = false;
+ }
+
+ if (m_iTabToStartFrom) {
+ // Draw the left arrow for more tabs
+ m_bIsOverLeftBound = true;
+ m_pPainter->drawPixmap(0, 0, m_pixIconTabPrev);
+ } else {
+ m_bIsOverLeftBound = false;
+ }
+
+ if (isBigger) {
+ // Draw the right arrow for more tabs
+ m_bIsOverRightBound = true;
+ m_pPainter->drawPixmap(nextIcon_X, 0, m_pixIconTabNext);
+ } else {
+ m_bIsOverRightBound = false;
+ }
+
+ m_pPainter->drawPixmap(closeIcon_X, 0, m_pixIconCloseTab);
+
+ m_pPainter->end();
+
+ p->drawPixmap(m_rct.x(), m_rct.y(), *m_pPixmap, 0, 0, m_pPixmap->width(), m_pPixmap->height());
+
+ m_bNeedToRedraw = false;
+
+}
+
+void KviNotifierWindowTabs::markAllMessagesAsHistoric()
+{
+/*
+ QMap<KviWindow *, KviNotifierWindowTab *>::Iterator tab;
+ // Iterating every tab
+ for (tab = m_tabMap.begin(); tab != m_tabMap.end(); ++tab) {
+
+ if (!tab.value()) break;
+
+ KviPointerList<KviNotifierMessage> * tmpMessageList = tab.value()->messageList();
+
+ if (!tmpMessageList) break;
+
+ for(KviNotifierMessage * m = tmpMessageList->last(); m; m = tmpMessageList->prev()) {
+ if(m->historic()) break;;
+ m->setHistoric();
+ }
+ }
+*/
+}
+
+void KviNotifierWindowTabs::closeTab(KviWindow * pWnd)
+{
+ KviNotifierWindowTab * pTab = m_tabMap.find(pWnd).data();
+ closeTab(pWnd, pTab);
+}
+
+void KviNotifierWindowTabs::closeTab(KviNotifierWindowTab * pTab)
+{
+ KviWindow * pWnd = pTab->wnd();
+ closeTab(pWnd, pTab);
+}
+
+void KviNotifierWindowTabs::closeCurrentTab()
+{
+ // Paranoic checks...
+ if (!m_pTabFocused) return; // The current tab is null? Please, kill me...
+ KviNotifierWindowTab * pTab = m_pTabFocused;
+ if (m_tabMap.isEmpty()) return; // Empty??? The World is ending...
+ KviWindow * pWnd = pTab->wnd();
+ if (!m_tabMap.contains(pWnd)) return; // The current tab is not on the map??? Call 911!!
+ // End paranoic stuff, go back to sanity...
+
+ closeTab(pWnd, pTab);
+}
+
+void KviNotifierWindowTabs::closeTab(KviWindow * pWnd, KviNotifierWindowTab * pTab)
+{
+ // Ok, we should be sure to delete the right tab...
+ m_tabPtrList.removeRef(pTab);
+ m_lastVisitedTabPtrList.removeRef(pTab);
+ m_tabMap.remove(pWnd);
+ delete pTab;
+
+ if(m_tabMap.empty())
+ {
+ m_pTabFocused = 0;
+ g_pNotifierWindow->showLineEdit(false);
+ g_pNotifierWindow->doHide(false);
+ } else {
+
+ if (m_lastVisitedTabPtrList.count()) {
+ m_pTabFocused = m_lastVisitedTabPtrList.first();
+ } else {
+ m_pTabFocused = m_tabPtrList.last();
+ }
+
+ m_pTabFocused->setFocused(true);
+ }
+}
+
+#include "m_notifierwindowtabs.moc"
diff --git a/src/modules/notifier/notifierwindowtabs.h b/src/modules/notifier/notifierwindowtabs.h
new file mode 100644
index 00000000..555906b8
--- /dev/null
+++ b/src/modules/notifier/notifierwindowtabs.h
@@ -0,0 +1,263 @@
+#ifndef _KVINOTIFIERWINDOWTABS_H_
+#define _KVINOTIFIERWINDOWTABS_H_
+//=============================================================================
+//
+// File : kvinotifierwindowtabs.h
+// Created on dom 02 gen 2005 15:30:50 by Iacopo Palazzi
+//
+// This file is part of the KVIrc distribution
+// Copyright (C) 2005 Iacopo Palazzi < iakko(at)siena.linux.it >
+//
+// 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 opinion) 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.
+//
+//=============================================================================
+
+#include <qfont.h>
+#include <qmap.h>
+#include <qobject.h>
+#include <qpixmap.h>
+#include <qpoint.h>
+#include <qrect.h>
+#include "kvi_settings.h"
+#include "kvi_pointerlist.h"
+#include "notifiersettings.h"
+#include "notifierwindow.h"
+
+#include "notifiermessage.h"
+
+
+class QPainter;
+class KviWindow;
+class KviNotifierWindowTab;
+
+typedef struct wndTabPair_s {
+ KviNotifierWindowTab * pTab;
+ KviWindow * pWnd;
+} wndTabPair;
+
+class KviNotifierWindowTab : public QObject // this class defines an object for every single tab about the tabs area
+{
+ Q_OBJECT
+public:
+ KviNotifierWindowTab(KviWindow *, QString);
+ ~KviNotifierWindowTab();
+
+// ================================
+// Put members declaration below...
+// ================================
+private:
+ bool m_bFocused;
+
+ QColor m_cLabel;
+ QColor m_clrHighlightedLabel;
+ QColor m_clrNormalLabel;
+ QColor m_clrChangedLabel;
+
+ QRect m_rect;
+
+ QString m_label;
+
+ KviPointerList<KviNotifierMessage> * m_pMessageList;
+ KviWindow * m_pWnd;
+ KviNotifierMessage * m_pCurrentMessage;
+
+ TabState m_eState;
+
+public:
+
+protected:
+
+
+// ================================
+// Put methods declaration below...
+// ================================
+private:
+
+private slots:
+ void labelChanged();
+ void closeMe();
+
+public:
+ bool focused() { return m_bFocused; };
+
+ int countMessage() { return m_pMessageList->count(); };
+ int width(bool b = false);
+
+ void appendMessage(KviNotifierMessage * m);
+ void setCurrentMessage(KviNotifierMessage * m) { m_pCurrentMessage = m; };
+ void setFocused(bool b = true);
+ void setLastMessageAsCurrent();
+ void setNextMessageAsCurrent();
+ void setPrevMessageAsCurrent();
+ void setState(TabState state);
+ void setRect(int x, int y, int w, int h) { m_rect.setX(x); m_rect.setY(y); m_rect.setWidth(w); m_rect.setHeight(h); };
+
+ QColor labelColor() {return m_cLabel; }
+ QRect rect() { return m_rect; };
+ QString label() { return m_label; };
+
+ KviNotifierMessage * currentMessage() { return m_pCurrentMessage; };
+ KviPointerList<KviNotifierMessage> * messageList() { return m_pMessageList; };
+ KviWindow * window() { return m_pWnd; };
+ KviWindow * wnd() {return m_pWnd; };
+
+ TabState state() { return m_eState; };
+
+protected:
+
+
+
+};
+
+
+//####################################################################################################
+//## Tabs Manager
+//####################################################################################################
+
+
+class KviNotifierWindowTabs // this class defines the tabs area
+{
+public:
+ KviNotifierWindowTabs(QRect r);
+ ~KviNotifierWindowTabs();
+
+// ================================
+// Put members declaration below...
+// ================================
+private:
+ QRect m_rct;
+ QPoint m_pnt;
+
+ QMap<KviWindow *, KviNotifierWindowTab *> m_tabMap;
+ KviPointerList<KviNotifierWindowTab> m_tabPtrList;
+ KviPointerList<KviNotifierWindowTab> m_lastVisitedTabPtrList;
+
+ QFont * m_pFocusedFont;
+ QFont * m_pUnfocusedFont;
+
+ KviNotifierWindowTab * m_pTabFocused;
+ KviWindow * m_pWndTabFocused;
+
+ QRect m_rctNextIcon;
+ QRect m_rctPrevIcon;
+ QRect m_rctCloseTabIcon;
+ QRect m_rctCloseTabIconHotArea;
+ QRect m_rctTabs;
+
+ QPainter * m_pPainter;
+ QPixmap * m_pPixmap;
+
+ QPixmap m_pixDX;
+ QPixmap m_pixSX;
+ QPixmap m_pixBKG;
+ QPixmap m_pixSXFocused;
+ QPixmap m_pixDXFocused;
+ QPixmap m_pixBKGFocused;
+ QPixmap m_pixSXUnfocused;
+ QPixmap m_pixDXUnfocused;
+ QPixmap m_pixBKGUnfocused;
+
+ QPixmap m_pixIconTabPrev;
+ QPixmap m_pixIconTabPrev_out;
+ QPixmap m_pixIconTabPrev_over;
+ QPixmap m_pixIconTabPrev_clicked;
+
+ QPixmap m_pixIconTabNext;
+ QPixmap m_pixIconTabNext_out;
+ QPixmap m_pixIconTabNext_over;
+ QPixmap m_pixIconTabNext_clicked;
+
+ QPixmap m_pixIconCloseTab;
+ QPixmap m_pixIconCloseTab_off;
+ QPixmap m_pixIconCloseTab_on;
+ QPixmap m_pixIconCloseTab_clicked;
+
+ int m_closeTabIconState;
+ int m_iTabToStartFrom;
+
+ bool m_bIsOverLeftBound;
+ bool m_bIsOverRightBound;
+ bool m_bNeedToRedraw;
+
+public:
+
+protected:
+
+
+// ================================
+// Put methods declaration below...
+// ================================
+private:
+ void initConfig();
+ void loadImages();
+
+public:
+ void addMessage(KviWindow *, KviNotifierMessage *);
+ void closeCurrentTab();
+ void closeTab(KviWindow * pWnd); // referes to void closeTab(KviWindow * pWnd, KviNotifierWindowTab * pTab);
+ void closeTab(KviNotifierWindowTab * pTab); // referes to void closeTab(KviWindow * pWnd, KviNotifierWindowTab * pTab);
+ void closeTab(KviWindow * pWnd, KviNotifierWindowTab * pTab);
+ void draw(QPainter *);
+ void needToRedraw() { m_bNeedToRedraw = true; };
+ void markAllMessagesAsHistoric();
+ void mouseMoveEvent(QMouseEvent * e);
+ void mousePressEvent(QMouseEvent * e);
+ void mouseReleaseEvent(QMouseEvent * e);
+ void next();
+ void prev();
+ void recalculatePositions();
+ void resetIcons();
+ void resize(QRect);
+ void scrollTabsLeft();
+ void scrollTabsRight();
+ void setCloseTabIcon(int state);
+ void setCurrentMessage(KviNotifierMessage * m) { if(m_pTabFocused)m_pTabFocused->setCurrentMessage(m); };
+ void setFocusOn(KviNotifierWindowTab *);
+ void setPoint(int x, int y) { m_pnt.setX(x); m_pnt.setY(y); };
+ void setWidth(int w);
+ void touch() { m_bNeedToRedraw = true; };
+
+ int baseLine() { return (y()+height()); };
+ int closeTabIconState() { return m_closeTabIconState; };
+ int count() { return (int)m_tabMap.count(); };
+ int height() { return m_rct.height(); };
+ int width() { return m_rct.width(); };
+ int x() { return m_pnt.x(); };
+ int y() { return m_pnt.y(); };
+
+ QFont * fontFocused() { return m_pFocusedFont; };
+ QFont * fontUnfocused() { return m_pUnfocusedFont; };
+
+ QPixmap * tabFocusedPixSx() {return &m_pixSXFocused; };
+ QPixmap * tabFocusedPixDx() {return &m_pixDXFocused; };
+ QPixmap * tabUnfocusedPixSx() {return &m_pixSXUnfocused; };
+ QPixmap * tabUnfocusedPixDx() {return &m_pixDXUnfocused; };
+
+ QRect rect() {return m_rct;};
+ QRect rctCloseTabIconHotArea() {return m_rctCloseTabIconHotArea; };
+
+ KviNotifierWindowTab * currentTab() { return m_pTabFocused; };
+
+ KviNotifierMessage * currentMessage() { return m_pTabFocused ? m_pTabFocused->currentMessage() : 0; };
+
+ KviWindow * window() { return m_pTabFocused->wnd(); };
+
+
+
+protected:
+
+};
+
+#endif //!_KVINOTIFIERWINDOWTABS_H_
diff --git a/src/modules/notifier/pics/Makefile.am b/src/modules/notifier/pics/Makefile.am
new file mode 100755
index 00000000..26f8bf9b
--- /dev/null
+++ b/src/modules/notifier/pics/Makefile.am
@@ -0,0 +1,9 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+tmpdir = $(picsdir)
+
+tmp_DATA= *.png
+
+EXTRA_DIST = $(tmp_DATA)
diff --git a/src/modules/notifier/pics/notifier_background.png b/src/modules/notifier/pics/notifier_background.png
new file mode 100755
index 00000000..2787f64c
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_background.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_close.png b/src/modules/notifier/pics/notifier_close.png
new file mode 100644
index 00000000..95ce3d8b
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_close.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_down.png b/src/modules/notifier/pics/notifier_down.png
new file mode 100644
index 00000000..01e11383
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_down.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_icon_body_next_clicked.png b/src/modules/notifier/pics/notifier_icon_body_next_clicked.png
new file mode 100644
index 00000000..2cab5af8
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_icon_body_next_clicked.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_icon_body_next_off.png b/src/modules/notifier/pics/notifier_icon_body_next_off.png
new file mode 100644
index 00000000..6a93e780
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_icon_body_next_off.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_icon_body_next_on.png b/src/modules/notifier/pics/notifier_icon_body_next_on.png
new file mode 100644
index 00000000..86dfe01e
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_icon_body_next_on.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_icon_body_prev_clicked.png b/src/modules/notifier/pics/notifier_icon_body_prev_clicked.png
new file mode 100644
index 00000000..ab8a9af3
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_icon_body_prev_clicked.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_icon_body_prev_off.png b/src/modules/notifier/pics/notifier_icon_body_prev_off.png
new file mode 100644
index 00000000..af9e5307
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_icon_body_prev_off.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_icon_body_prev_on.png b/src/modules/notifier/pics/notifier_icon_body_prev_on.png
new file mode 100644
index 00000000..10cc8f18
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_icon_body_prev_on.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_icon_body_write_clicked.png b/src/modules/notifier/pics/notifier_icon_body_write_clicked.png
new file mode 100644
index 00000000..1dc06165
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_icon_body_write_clicked.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_icon_body_write_off.png b/src/modules/notifier/pics/notifier_icon_body_write_off.png
new file mode 100644
index 00000000..1096b7a8
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_icon_body_write_off.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_icon_body_write_on.png b/src/modules/notifier/pics/notifier_icon_body_write_on.png
new file mode 100644
index 00000000..55fe9d9e
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_icon_body_write_on.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_icon_close_clicked.png b/src/modules/notifier/pics/notifier_icon_close_clicked.png
new file mode 100644
index 00000000..f68f16f0
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_icon_close_clicked.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_icon_close_clicked_hl.png b/src/modules/notifier/pics/notifier_icon_close_clicked_hl.png
new file mode 100644
index 00000000..d7bcc291
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_icon_close_clicked_hl.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_icon_close_out.png b/src/modules/notifier/pics/notifier_icon_close_out.png
new file mode 100644
index 00000000..ccec0bdb
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_icon_close_out.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_icon_close_out_hl.png b/src/modules/notifier/pics/notifier_icon_close_out_hl.png
new file mode 100644
index 00000000..89917dae
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_icon_close_out_hl.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_icon_close_over.png b/src/modules/notifier/pics/notifier_icon_close_over.png
new file mode 100644
index 00000000..e3cffc0f
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_icon_close_over.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_icon_close_over_hl.png b/src/modules/notifier/pics/notifier_icon_close_over_hl.png
new file mode 100644
index 00000000..6a7f1bc0
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_icon_close_over_hl.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_icon_tab_close_clicked.png b/src/modules/notifier/pics/notifier_icon_tab_close_clicked.png
new file mode 100644
index 00000000..ac647250
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_icon_tab_close_clicked.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_icon_tab_close_off.png b/src/modules/notifier/pics/notifier_icon_tab_close_off.png
new file mode 100644
index 00000000..105c728b
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_icon_tab_close_off.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_icon_tab_close_on.png b/src/modules/notifier/pics/notifier_icon_tab_close_on.png
new file mode 100644
index 00000000..dfd87ffe
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_icon_tab_close_on.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_icon_tab_next_clicked.png b/src/modules/notifier/pics/notifier_icon_tab_next_clicked.png
new file mode 100644
index 00000000..b6d98d3e
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_icon_tab_next_clicked.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_icon_tab_next_out.png b/src/modules/notifier/pics/notifier_icon_tab_next_out.png
new file mode 100644
index 00000000..4e4cf075
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_icon_tab_next_out.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_icon_tab_next_over.png b/src/modules/notifier/pics/notifier_icon_tab_next_over.png
new file mode 100644
index 00000000..9f1f8f90
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_icon_tab_next_over.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_icon_tab_prev_clicked.png b/src/modules/notifier/pics/notifier_icon_tab_prev_clicked.png
new file mode 100644
index 00000000..a24139b5
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_icon_tab_prev_clicked.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_icon_tab_prev_out.png b/src/modules/notifier/pics/notifier_icon_tab_prev_out.png
new file mode 100644
index 00000000..20e4a06f
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_icon_tab_prev_out.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_icon_tab_prev_over.png b/src/modules/notifier/pics/notifier_icon_tab_prev_over.png
new file mode 100644
index 00000000..68b390f7
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_icon_tab_prev_over.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_left.png b/src/modules/notifier/pics/notifier_left.png
new file mode 100644
index 00000000..b0887a7f
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_left.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_pen.png b/src/modules/notifier/pics/notifier_pen.png
new file mode 100644
index 00000000..31978d1b
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_pen.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_pix_body_dwn.png b/src/modules/notifier/pics/notifier_pix_body_dwn.png
new file mode 100644
index 00000000..4a96de08
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_pix_body_dwn.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_pix_body_dwndx.png b/src/modules/notifier/pics/notifier_pix_body_dwndx.png
new file mode 100644
index 00000000..5b8ca523
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_pix_body_dwndx.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_pix_body_dwnsx.png b/src/modules/notifier/pics/notifier_pix_body_dwnsx.png
new file mode 100644
index 00000000..ffa3c980
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_pix_body_dwnsx.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_pix_body_dx.png b/src/modules/notifier/pics/notifier_pix_body_dx.png
new file mode 100644
index 00000000..c2ca5ce0
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_pix_body_dx.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_pix_body_kvirc.png b/src/modules/notifier/pics/notifier_pix_body_kvirc.png
new file mode 100644
index 00000000..1a304b0a
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_pix_body_kvirc.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_pix_body_kvirc_dwn.png b/src/modules/notifier/pics/notifier_pix_body_kvirc_dwn.png
new file mode 100644
index 00000000..37168c57
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_pix_body_kvirc_dwn.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_pix_body_kvirc_sx.png b/src/modules/notifier/pics/notifier_pix_body_kvirc_sx.png
new file mode 100644
index 00000000..acd39ab5
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_pix_body_kvirc_sx.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_pix_body_sx.png b/src/modules/notifier/pics/notifier_pix_body_sx.png
new file mode 100644
index 00000000..c1a5315a
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_pix_body_sx.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_pix_caption_bkg.png b/src/modules/notifier/pics/notifier_pix_caption_bkg.png
new file mode 100644
index 00000000..96b691df
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_pix_caption_bkg.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_pix_caption_bkg_hl.png b/src/modules/notifier/pics/notifier_pix_caption_bkg_hl.png
new file mode 100644
index 00000000..0c5f155c
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_pix_caption_bkg_hl.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_pix_caption_dx.png b/src/modules/notifier/pics/notifier_pix_caption_dx.png
new file mode 100644
index 00000000..76a37a61
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_pix_caption_dx.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_pix_caption_dx_hl.png b/src/modules/notifier/pics/notifier_pix_caption_dx_hl.png
new file mode 100644
index 00000000..ceca1a1d
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_pix_caption_dx_hl.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_pix_caption_sx.png b/src/modules/notifier/pics/notifier_pix_caption_sx.png
new file mode 100644
index 00000000..2939f96b
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_pix_caption_sx.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_pix_caption_sx_hl.png b/src/modules/notifier/pics/notifier_pix_caption_sx_hl.png
new file mode 100644
index 00000000..78be4e71
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_pix_caption_sx_hl.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_pix_tab_bkg.png b/src/modules/notifier/pics/notifier_pix_tab_bkg.png
new file mode 100644
index 00000000..3918b044
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_pix_tab_bkg.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_pix_tab_dx.png b/src/modules/notifier/pics/notifier_pix_tab_dx.png
new file mode 100644
index 00000000..112d9604
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_pix_tab_dx.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_pix_tab_focused_bkg.png b/src/modules/notifier/pics/notifier_pix_tab_focused_bkg.png
new file mode 100644
index 00000000..ef42ef68
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_pix_tab_focused_bkg.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_pix_tab_focused_dx.png b/src/modules/notifier/pics/notifier_pix_tab_focused_dx.png
new file mode 100644
index 00000000..e8dee6b9
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_pix_tab_focused_dx.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_pix_tab_focused_sx.png b/src/modules/notifier/pics/notifier_pix_tab_focused_sx.png
new file mode 100644
index 00000000..f94cbb55
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_pix_tab_focused_sx.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_pix_tab_sx.png b/src/modules/notifier/pics/notifier_pix_tab_sx.png
new file mode 100644
index 00000000..0f693bdd
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_pix_tab_sx.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_pix_tab_unfocused_bkg.png b/src/modules/notifier/pics/notifier_pix_tab_unfocused_bkg.png
new file mode 100644
index 00000000..36a5f22e
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_pix_tab_unfocused_bkg.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_pix_tab_unfocused_dx.png b/src/modules/notifier/pics/notifier_pix_tab_unfocused_dx.png
new file mode 100644
index 00000000..f7ba1ee1
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_pix_tab_unfocused_dx.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_pix_tab_unfocused_sx.png b/src/modules/notifier/pics/notifier_pix_tab_unfocused_sx.png
new file mode 100644
index 00000000..aa01c4c6
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_pix_tab_unfocused_sx.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_pix_wnd_dwn.png b/src/modules/notifier/pics/notifier_pix_wnd_dwn.png
new file mode 100644
index 00000000..7f94fef4
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_pix_wnd_dwn.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_pix_wnd_dwn_hl.png b/src/modules/notifier/pics/notifier_pix_wnd_dwn_hl.png
new file mode 100644
index 00000000..6090316b
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_pix_wnd_dwn_hl.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_pix_wnd_dwndx.png b/src/modules/notifier/pics/notifier_pix_wnd_dwndx.png
new file mode 100644
index 00000000..429fa4a0
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_pix_wnd_dwndx.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_pix_wnd_dwndx_hl.png b/src/modules/notifier/pics/notifier_pix_wnd_dwndx_hl.png
new file mode 100644
index 00000000..2c392742
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_pix_wnd_dwndx_hl.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_pix_wnd_dwnsx.png b/src/modules/notifier/pics/notifier_pix_wnd_dwnsx.png
new file mode 100644
index 00000000..3fb987ef
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_pix_wnd_dwnsx.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_pix_wnd_dwnsx_hl.png b/src/modules/notifier/pics/notifier_pix_wnd_dwnsx_hl.png
new file mode 100644
index 00000000..eb51c09a
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_pix_wnd_dwnsx_hl.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_pix_wnd_dx.png b/src/modules/notifier/pics/notifier_pix_wnd_dx.png
new file mode 100644
index 00000000..0a1c4f4b
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_pix_wnd_dx.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_pix_wnd_dx_hl.png b/src/modules/notifier/pics/notifier_pix_wnd_dx_hl.png
new file mode 100644
index 00000000..24d1cde6
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_pix_wnd_dx_hl.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_pix_wnd_sx.png b/src/modules/notifier/pics/notifier_pix_wnd_sx.png
new file mode 100644
index 00000000..01fb63fd
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_pix_wnd_sx.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_pix_wnd_sx_hl.png b/src/modules/notifier/pics/notifier_pix_wnd_sx_hl.png
new file mode 100644
index 00000000..9a18f058
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_pix_wnd_sx_hl.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_right.png b/src/modules/notifier/pics/notifier_right.png
new file mode 100644
index 00000000..85819102
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_right.png
Binary files differ
diff --git a/src/modules/notifier/pics/notifier_up.png b/src/modules/notifier/pics/notifier_up.png
new file mode 100644
index 00000000..f846b624
--- /dev/null
+++ b/src/modules/notifier/pics/notifier_up.png
Binary files differ
diff --git a/src/modules/objects/Makefile.am b/src/modules/objects/Makefile.am
new file mode 100644
index 00000000..c4574582
--- /dev/null
+++ b/src/modules/objects/Makefile.am
@@ -0,0 +1,143 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkviobjects.la
+
+libkviobjects_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkviobjects_la_SOURCES = libkviobjects.cpp \
+ class_button.cpp \
+ class_buttongroup.cpp \
+ class_checkbox.cpp \
+ class_combobox.cpp \
+ class_dialog.cpp \
+ class_dockwindow.cpp \
+ class_file.cpp \
+ class_groupbox.cpp \
+ class_label.cpp \
+ class_layout.cpp \
+ class_lcd.cpp \
+ class_lineedit.cpp \
+ class_list.cpp \
+ class_listbox.cpp \
+ class_listview.cpp \
+ class_listviewitem.cpp \
+ class_mainwindow.cpp \
+ class_menubar.cpp \
+ class_multilineedit.cpp \
+ class_popupmenu.cpp \
+ class_process.cpp \
+ class_progressbar.cpp \
+ class_radiobutton.cpp \
+ class_slider.cpp \
+ class_socket.cpp \
+ class_spinbox.cpp \
+ class_tabwidget.cpp \
+ class_toolbar.cpp \
+ class_toolbutton.cpp \
+ class_painter.cpp \
+ class_pixmap.cpp \
+ class_tbrowser.cpp \
+ class_widget.cpp \
+ class_window.cpp \
+ class_wizard.cpp \
+ class_workspace.cpp \
+ class_wrapper.cpp \
+ class_urllabel.cpp \
+ class_xmlreader.cpp \
+ class_vbox.cpp \
+ class_hbox.cpp
+
+
+libkviobjects_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+noinst_HEADERS= class_button.h \
+ class_buttongroup.h \
+ class_checkbox.h \
+ class_combobox.h \
+ class_dialog.h \
+ class_dockwindow.h \
+ class_file.h \
+ class_groupbox.h \
+ class_label.h \
+ class_layout.h \
+ class_lcd.h \
+ class_lineedit.h \
+ class_list.h \
+ class_listbox.h \
+ class_listview.h \
+ class_listviewitem.h \
+ class_mainwindow.h \
+ class_menubar.h \
+ class_multilineedit.h \
+ class_painter.h \
+ class_pixmap.h \
+ class_popupmenu.h \
+ class_process.h \
+ class_progressbar.h \
+ class_radiobutton.h \
+ class_slider.h \
+ class_socket.h \
+ class_spinbox.h \
+ class_tabwidget.h \
+ class_tbrowser.h \
+ class_toolbar.h \
+ class_toolbutton.h \
+ class_urllabel.h \
+ class_widget.h \
+ class_window.h \
+ class_wizard.h \
+ class_workspace.h \
+ class_wrapper.h \
+ class_xmlreader.h \
+ class_vbox.h \
+ class_hbox.h \
+ object_macros.h
+
+m_%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
+
+class_checkbox.cpp: m_class_checkbox.moc
+class_combobox.cpp: m_class_combobox.moc
+class_button.cpp: m_class_button.moc
+class_dialog.cpp: m_class_dialog.moc
+class_dockwindow.cpp: m_class_dockwindow.moc
+class_file.cpp: m_class_file.moc
+class_groupbox.cpp: m_class_groupbox.moc
+class_label.cpp: m_class_label.moc
+class_layout.cpp: m_class_layout.moc
+class_lcd.cpp: m_class_lcd.moc
+class_lineedit.cpp: m_class_lineedit.moc
+class_list.cpp: m_class_list.moc
+class_listbox.cpp: m_class_listbox.moc
+class_listview.cpp: m_class_listview.moc
+class_listviewitem.cpp: m_class_listviewitem.moc
+class_listbox.cpp: m_class_listbox.moc
+class_mainwindow.cpp: m_class_mainwindow.moc
+class_menubar.cpp: m_class_menubar.moc
+class_multilineedit.cpp: m_class_multilineedit.moc
+class_painter.cpp: m_class_painter.moc
+class_pixmap.cpp: m_class_pixmap.moc
+class_popupmenu.cpp: m_class_popupmenu.moc
+class_process.cpp: m_class_process.moc
+class_progressbar.cpp: m_class_progressbar.moc
+class_radiobutton.cpp: m_class_radiobutton.moc
+class_slider.cpp: m_class_slider.moc
+class_socket.cpp: m_class_socket.moc
+class_spinbox.cpp: m_class_spinbox.moc
+class_tabwidget.cpp: m_class_tabwidget.moc
+class_tbrowser.cpp: m_class_tbrowser.moc
+class_toolbar.cpp: m_class_toolbar.moc
+class_toolbutton.cpp: m_class_toolbutton.moc
+class_urllabel.cpp: m_class_urllabel.moc
+class_widget.cpp: m_class_widget.moc
+class_window.cpp: m_class_window.moc
+class_wizard.cpp: m_class_wizard.moc
+class_workspace.cpp: m_class_workspace.moc
+class_wrapper.cpp: m_class_wrapper.moc
+class_xmlreader.cpp: m_class_xmlreader.moc
+
diff --git a/src/modules/objects/class_button.cpp b/src/modules/objects/class_button.cpp
new file mode 100644
index 00000000..54d1525a
--- /dev/null
+++ b/src/modules/objects/class_button.cpp
@@ -0,0 +1,178 @@
+//
+// File : class_button.cpp
+// Creation date : Wed 13 Sep 2000 02:42:05 CEST by Krzysztof Godlewski
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_debug.h"
+
+
+#include "kvi_error.h"
+#include <qiconset.h>
+#include "kvi_iconmanager.h"
+
+#include "class_button.h"
+
+KVSO_BEGIN_REGISTERCLASS(KviKvsObject_button,"button","widget")
+
+ KVSO_REGISTER_HANDLER(KviKvsObject_button,"setText", functionSetText)
+ KVSO_REGISTER_HANDLER(KviKvsObject_button,"text", functionText)
+ KVSO_REGISTER_HANDLER(KviKvsObject_button,"setAutoDefault", functionSetAutoDefault)
+ KVSO_REGISTER_HANDLER(KviKvsObject_button,"setToggleButton", functionSetToggleButton)
+ KVSO_REGISTER_HANDLER(KviKvsObject_button,"setOn", functionSetOn)
+ KVSO_REGISTER_HANDLER(KviKvsObject_button,"isOn", functionIsOn)
+ KVSO_REGISTER_HANDLER(KviKvsObject_button,"toggle", functionToggle)
+ KVSO_REGISTER_HANDLER(KviKvsObject_button,"setIsMenuButton", functionSetIsMenuButton)
+ KVSO_REGISTER_HANDLER(KviKvsObject_button,"isMenuButton", functionIsMenuButton)
+ KVSO_REGISTER_HANDLER(KviKvsObject_button,"clickEvent", functionclickEvent)
+ KVSO_REGISTER_HANDLER(KviKvsObject_button,"setImage", functionSetImage)
+
+
+KVSO_END_REGISTERCLASS(KviKvsObject_button)
+
+KVSO_BEGIN_CONSTRUCTOR(KviKvsObject_button,KviKvsObject_widget)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_button)
+
+
+KVSO_BEGIN_DESTRUCTOR(KviKvsObject_button)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_button)
+
+bool KviKvsObject_button::init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams)
+{
+ setObject(new QPushButton(parentScriptWidget(),name()),true);
+ connect(widget(),SIGNAL(clicked()),this,SLOT(slotClicked()));
+ return true;
+}
+
+bool KviKvsObject_button::functionText(KviKvsObjectFunctionCall *c)
+{
+ if(widget()) c->returnValue()->setString(((QPushButton *)widget())->text());
+ return true;
+}
+
+bool KviKvsObject_button::functionSetText(KviKvsObjectFunctionCall *c)
+{
+ QString szText;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("text",KVS_PT_STRING,0,szText)
+ KVSO_PARAMETERS_END(c)
+ if (widget())
+ ((QPushButton *)widget())->setText(szText);
+ return true;
+}
+bool KviKvsObject_button::functionSetAutoDefault(KviKvsObjectFunctionCall *c)
+{
+ bool bEnabled;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bEnabled",KVS_PT_BOOL,0,bEnabled)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ ((QPushButton *)widget())->setAutoDefault(bEnabled);
+ return true;
+}
+bool KviKvsObject_button::functionSetToggleButton(KviKvsObjectFunctionCall *c)
+{
+ bool bEnabled;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bEnabled",KVS_PT_BOOL,0,bEnabled)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ ((QPushButton *)widget())->setToggleButton(bEnabled);
+ return true;
+}
+bool KviKvsObject_button::functionSetOn(KviKvsObjectFunctionCall *c)
+{
+ bool bEnabled;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bEnabled",KVS_PT_BOOL,0,bEnabled)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ ((QPushButton *)widget())->setOn(bEnabled);
+ return true;
+}
+// FIX ME
+bool KviKvsObject_button::functionSetIsMenuButton(KviKvsObjectFunctionCall *c)
+{
+ bool bEnabled;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bEnabled",KVS_PT_BOOL,0,bEnabled)
+ KVSO_PARAMETERS_END(c)
+ /*if(widget())
+ ((QPushButton *)widget())->setIsMenuButton(bEnabled);
+ */
+
+ return true;
+}
+bool KviKvsObject_button::functionIsMenuButton(KviKvsObjectFunctionCall *c)
+{
+ if (widget()) c->returnValue()->setBoolean(((QPushButton *)widget())->isMenuButton());
+ return true;
+}
+//
+bool KviKvsObject_button::functionIsOn(KviKvsObjectFunctionCall *c)
+{
+ if (widget()) c->returnValue()->setBoolean(((QPushButton *)widget())->isOn());
+ return true;
+}
+bool KviKvsObject_button::functionToggle(KviKvsObjectFunctionCall *c)
+{
+ if(widget()) ((QPushButton *)widget())->toggle();
+ return true;
+}
+// FIX ME
+bool KviKvsObject_button::functionSetImage(KviKvsObjectFunctionCall *c)
+{
+ QString icon;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("icon",KVS_PT_STRING,0,icon)
+ KVSO_PARAMETERS_END(c)
+ if (!widget()) return true;
+ QPixmap * pix = g_pIconManager->getImage(icon);
+ if(pix){
+ #ifdef COMPILE_USE_QT4
+ ((QPushButton *)widget())->setIconSet(*pix);
+ #else
+ ((QPushButton *)widget())->setIconSet(QIconSet(*pix,QIconSet::Small));
+ #endif
+ }
+ else{
+ #ifdef COMPILE_USE_QT4
+ ((QPushButton *)widget())->setIcon(QIconSet());
+ #else
+ ((QPushButton *)widget())->setIconSet(QIconSet());
+ #endif
+ }
+ return true;
+}
+bool KviKvsObject_button::functionclickEvent(KviKvsObjectFunctionCall *c)
+{
+ emitSignal("clicked",c);
+ return true;
+}
+
+void KviKvsObject_button::slotClicked()
+{
+ KviKvsVariantList *params=0;
+ callFunction(this,"clickEvent",params);
+}
+
+
+#include "m_class_button.moc"
diff --git a/src/modules/objects/class_button.h b/src/modules/objects/class_button.h
new file mode 100644
index 00000000..5c752e48
--- /dev/null
+++ b/src/modules/objects/class_button.h
@@ -0,0 +1,58 @@
+#ifndef _CLASS_BUTTON_H_
+#define _CLASS_BUTTON_H_
+//
+// File : class_button.h
+// Creation date : Wed 13 Sep 2000 02:42:05 CEST by Krzysztof Godlewski
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+
+#include <qpushbutton.h>
+#include "class_widget.h"
+#include "object_macros.h"
+
+class KviKvsObject_button : public KviKvsObject_widget
+{
+ Q_OBJECT
+public:
+ KVSO_DECLARE_OBJECT(KviKvsObject_button)
+public:
+ QWidget * widget() { return (QWidget *)object(); };
+protected:
+ virtual bool init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams);
+
+ bool functionSetText(KviKvsObjectFunctionCall *c);
+ bool functionIsChecked(KviKvsObjectFunctionCall *c);
+ bool functionText(KviKvsObjectFunctionCall *c);
+ bool functionSetAutoDefault(KviKvsObjectFunctionCall *c);
+ bool functionSetToggleButton(KviKvsObjectFunctionCall *c);
+ bool functionSetOn(KviKvsObjectFunctionCall *c);
+ bool functionIsOn(KviKvsObjectFunctionCall *c);
+ bool functionToggle(KviKvsObjectFunctionCall *c);
+ bool functionSetIsMenuButton(KviKvsObjectFunctionCall *c);
+ bool functionIsMenuButton(KviKvsObjectFunctionCall *c);
+ bool functionSetImage(KviKvsObjectFunctionCall *c);
+ bool functionclickEvent(KviKvsObjectFunctionCall *c);
+
+protected slots:
+ void slotClicked();
+};
+
+#endif // !_CLASS_BUTTON_H_
diff --git a/src/modules/objects/class_buttongroup.cpp b/src/modules/objects/class_buttongroup.cpp
new file mode 100644
index 00000000..5f9f1756
--- /dev/null
+++ b/src/modules/objects/class_buttongroup.cpp
@@ -0,0 +1,87 @@
+//
+// File : class_buttongroup.cpp
+// Creation date : Fri Jan 28 14:21:48 CEST 2005
+// by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include <qbuttongroup.h>
+#include "class_buttongroup.h"
+#include <qradiobutton.h>
+#include "kvi_error.h"
+#include "kvi_debug.h"
+
+#include "kvi_locale.h"
+#include "kvi_iconmanager.h"
+
+
+/*
+ @doc: buttongroup
+ @keyterms:
+ buttongroup object class,
+ @title:
+ buttongroup class
+ @type:
+ class
+ @short:
+ Provides a buttongroup bar.
+ @inherits:
+ [class]groupbox[/class]
+ [class]object[/class]
+ [class]widget[/class]
+ @description:
+ This widget organizes buttons in a group.
+ It will be usually a parent for other child controls.
+ You can either use a child layout to manage the children geometries
+ or use $setColumnLayout function to manage the layout automatically.
+ The class ineriths groupbox.
+
+ @functions:
+
+*/
+
+KVSO_BEGIN_REGISTERCLASS(KviKvsObject_buttongroup,"buttongroup","groupbox")
+
+KVSO_END_REGISTERCLASS(KviKvsObject_buttongroup)
+
+KVSO_BEGIN_CONSTRUCTOR(KviKvsObject_buttongroup,KviKvsObject_groupbox)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_buttongroup)
+
+
+KVSO_BEGIN_DESTRUCTOR(KviKvsObject_buttongroup)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_buttongroup)
+
+// CHECK ME
+bool KviKvsObject_buttongroup::init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams)
+{
+ #ifdef COMPILE_USE_QT4
+ QButtonGroup *group=new QButtonGroup(parentScriptWidget());
+ group->setObjectName(name());
+ setObject(group,true);
+ #else
+ setObject(new QButtonGroup(name(),parentScriptWidget()), true);
+ #endif
+
+
+ return true;
+}
+
+
diff --git a/src/modules/objects/class_buttongroup.h b/src/modules/objects/class_buttongroup.h
new file mode 100644
index 00000000..472051ec
--- /dev/null
+++ b/src/modules/objects/class_buttongroup.h
@@ -0,0 +1,44 @@
+#ifndef _CLASS_BUTTONGROUP_H_
+#define _CLASS_BUTTONGROUP_H_
+//
+// File : class_buttongroup.h
+// Creation date : Jan 23 CEST 2007
+// by Alessandro Carbone(Noldor)
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+
+#include <qbuttongroup.h>
+#include "class_groupbox.h"
+#include "object_macros.h"
+
+class KviKvsObject_buttongroup : public KviKvsObject_groupbox
+{
+public:
+ KVSO_DECLARE_OBJECT(KviKvsObject_buttongroup)
+public:
+ QWidget * widget() { return (QWidget *)object(); };
+protected:
+ virtual bool init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams);
+
+
+};
+#endif //!_CLASS_GROUPBOX_H_
+
diff --git a/src/modules/objects/class_checkbox.cpp b/src/modules/objects/class_checkbox.cpp
new file mode 100644
index 00000000..a651adb8
--- /dev/null
+++ b/src/modules/objects/class_checkbox.cpp
@@ -0,0 +1,128 @@
+//vim: ts=8
+// File : class_checkbox.cpp
+// Creation date : Wed Sep 20 23:01:47 CEST 2000 by Krzysztof Godlewski
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+#include "kvi_error.h"
+#include "kvi_debug.h"
+
+#include "kvi_locale.h"
+#include "kvi_styled_controls.h"
+
+#include "class_checkbox.h"
+
+/*
+ @doc: checkbox
+ @title:
+ checkbox class
+ @type:
+ class
+ @short:
+ Check box with a text description
+ @inherits:
+ [class]object[/class]
+ [class]button[/class]
+ @description:
+ This widget provides a check box - it is a kind of a toggle
+ button. It can have two states: on (checked) and off
+ (unchecked).
+ @functions:
+ !fn: <bool> $isChecked()
+ Returns '1' if the check box is checked, '0' otherwise.[br]
+ See also [classfnc]$setChecked[/classfnc]().
+ !fn: $setChecked([<bChecked:bool>])
+ Sets the check box 'checked state' to <bool>.
+ !fn: $setText([<text:string>])
+ Sets the check box 'checked state' to <bool>.[br]
+ See also [classfnc]$isChecked[/classfnc]().
+ !fn: $toggleEvent(<bToggled:bool>)
+ Called by KVIrc when the checkbox state is toggled.
+ The default implementation emits the toggled(<bool>) signal.
+*/
+
+//---------------------------------------------------------------------------------
+
+KVSO_BEGIN_REGISTERCLASS(KviKvsObject_checkbox,"checkbox","button")
+ // appearance
+ KVSO_REGISTER_HANDLER(KviKvsObject_checkbox,"setChecked",function_setChecked)
+ KVSO_REGISTER_HANDLER(KviKvsObject_checkbox,"isChecked",function_isChecked)
+ KVSO_REGISTER_HANDLER(KviKvsObject_checkbox,"toggleEvent",function_toggleEvent)
+ KVSO_REGISTER_HANDLER(KviKvsObject_checkbox,"setText",function_setText)
+KVSO_END_REGISTERCLASS(KviKvsObject_checkbox)
+
+KVSO_BEGIN_CONSTRUCTOR(KviKvsObject_checkbox,KviKvsObject_button)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_checkbox)
+
+
+KVSO_BEGIN_DESTRUCTOR(KviKvsObject_checkbox)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_checkbox)
+
+bool KviKvsObject_checkbox::init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams)
+{
+ KviStyledCheckBox * cb = new KviStyledCheckBox(parentScriptWidget(), name());
+ setObject(cb, true);
+ connect(cb,SIGNAL(toggled(bool)),this,SLOT(toggled(bool)));
+ connect(widget(),SIGNAL(clicked()),this,SLOT(slotClicked()));
+ return true;
+}
+
+bool KviKvsObject_checkbox::function_isChecked(KviKvsObjectFunctionCall *c)
+{
+ if(widget()) c->returnValue()->setBoolean(((KviStyledCheckBox *)widget())->isChecked());
+ return true;
+}
+
+bool KviKvsObject_checkbox::function_setChecked(KviKvsObjectFunctionCall *c)
+{
+ bool bChecked;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bChecked",KVS_PT_BOOL,KVS_PF_OPTIONAL,bChecked)
+ KVSO_PARAMETERS_END(c)
+ if(widget()) ((KviStyledCheckBox *)widget())->setChecked(bChecked);
+ return true;
+}
+
+bool KviKvsObject_checkbox::function_setText(KviKvsObjectFunctionCall *c)
+{
+ QString szText;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("text",KVS_PT_STRING,0,szText)
+ KVSO_PARAMETERS_END(c)
+ if(widget()) ((KviStyledCheckBox *)widget())->setText(szText);
+ return true;
+}
+
+bool KviKvsObject_checkbox::function_toggleEvent(KviKvsObjectFunctionCall *c)
+{
+ emitSignal("toggled",c,c->params());
+ return true;
+}
+
+void KviKvsObject_checkbox::toggled(bool b)
+{
+ KviKvsVariantList params(new KviKvsVariant(b));
+ callFunction(this,"toggleEvent",&params);
+}
+
+
+#include "m_class_checkbox.moc"
diff --git a/src/modules/objects/class_checkbox.h b/src/modules/objects/class_checkbox.h
new file mode 100644
index 00000000..1d19a432
--- /dev/null
+++ b/src/modules/objects/class_checkbox.h
@@ -0,0 +1,48 @@
+#ifndef _CLASS_CHECKBOX_H_
+#define _CLASS_CHECKBOX_H_
+
+//vim: ts=8
+// File : class_checkbox.h
+// Creation date : Wed Sep 20 23:02:11 CEST 2000 by Krzysztof Godlewski
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+
+#include <qcheckbox.h>
+#include "class_button.h"
+#include "object_macros.h"
+
+class KviKvsObject_checkbox : public KviKvsObject_button
+{
+ Q_OBJECT
+public:
+ KVSO_DECLARE_OBJECT(KviKvsObject_checkbox)
+public:
+ QWidget * widget() { return (QWidget *)object(); };
+protected:
+ virtual bool init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams);
+ bool function_setChecked(KviKvsObjectFunctionCall *c);
+ bool function_isChecked(KviKvsObjectFunctionCall *c);
+ bool function_toggleEvent(KviKvsObjectFunctionCall *c);
+ bool function_setText(KviKvsObjectFunctionCall *c);
+protected slots:
+ void toggled(bool b);
+};
+#endif // !_CLASS_CHECKBOX_H_
diff --git a/src/modules/objects/class_combobox.cpp b/src/modules/objects/class_combobox.cpp
new file mode 100644
index 00000000..9c8ffadf
--- /dev/null
+++ b/src/modules/objects/class_combobox.cpp
@@ -0,0 +1,368 @@
+//vim: ts=8
+// File : class_combobox.cpp
+// Creation date : Thu Mar 22 20:57:45 CET 2001 by Krzysztof Godlewski
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+#include "kvi_error.h"
+#include "kvi_locale.h"
+#include "kvi_debug.h"
+
+
+#include "class_list.h"
+#include "class_combobox.h"
+#include <qlineedit.h>
+#include <qstring.h>
+
+/*
+ @doc: combobox
+ @keyterms:
+ combobox object class, selection
+ @title:
+ combobox class
+ @type:
+ class
+ @short:
+ Combined button and popup list
+ @inherits:
+ [class]object[/class]
+ [class]widget[/class]
+ @description:
+ @functions:
+ !fn: $insertItem(<text:string>, <index:int>)
+ Inserts a text item at position <index>. If index is negative or
+ not specified the item is appended.
+ !fn: $changeItem(<text:string>, <index:uint>)
+ Changes text of item at <index> to <text>.
+ !fn: $removeItem(<index:uint>)
+ Removes item at given index.
+ !fn: $setMaxCount(<num:uint>)
+ Sets the maximum number of items the combo box can hold to
+ <num>. If <num> is smaller than the current number of items,
+ the list is truncated at the end. There is no limit by default.
+ !fn: <integer> $maxCount()
+ Returns the current maximum number of items in the combo box.
+ !fn: <integer> $count()
+ Returns number of items in the widget.
+ !fn: <string> $current()
+ Returns currently selected item.
+ !fn: <integer> $currentItem()
+ Returns index of currently selected item.
+ !fn: $setEditable(<bflag:boolean>)
+ Make the input field editable, if <bflag>. Otherwise the
+ user may only choose one of the items in the combo box.[br]
+ If the parameter is ommited, it is assumed to be false.
+ !fn: <boolean> $editable()
+ Returns whether the combobox is editable or not.
+ !fn: $setEditText(<text:string>,[<quiet:bool>])
+ Sets the text in the embedded line edit to newText without
+ changing the combo's contents. Does nothing if the combo
+ isn't editable. If the optional quiet parameter is true no warning will be print if text will be empty.
+ !fn: $clear()
+ Removes all the items from the combo box
+ !fn: $textAt(<index:uint>)
+ Returns item at given index.
+ !fn: $setCurrentItem(<index:uint>)
+ Sets the current combobox item. This is the item to be
+ displayed on the combobox button.
+ !fn: $activatedEvent(<index:integer>)
+ This function is called by the framework when a new item has activated. The index value is the position of the new item.[br]
+ The default implementation emits the [classfnc]$activated[/classfnc]() signal,
+ !fn: $textChangedEvent(<text:string>)
+ This function is called when the text in an editable combobox has changed.[br]
+ The function return the new text in its argument.[br]
+ The default implementation emits the [classfnc]$textChanged[/classfnc]() signal.
+ @signals:
+ !sg: $textChanged()
+ This signal is emitted by the default implementation of [classfnc]$textChangedEvent[/classfnc]().
+ !sg: $activated()
+ This signal is emitted by the default implementation of [classfnc]$activatedEvent[/classfnc]().
+
+*/
+KVSO_BEGIN_REGISTERCLASS(KviKvsObject_combobox,"combobox","widget")
+ KVSO_REGISTER_HANDLER(KviKvsObject_combobox,"insertItem", functioninsertItem)
+ KVSO_REGISTER_HANDLER(KviKvsObject_combobox,"changeItem", functionchangeItem)
+ KVSO_REGISTER_HANDLER(KviKvsObject_combobox,"removeItem", functionremoveItem)
+ KVSO_REGISTER_HANDLER(KviKvsObject_combobox,"clear", functionclear)
+ KVSO_REGISTER_HANDLER(KviKvsObject_combobox,"setMaxCount", functionsetMaxCount)
+ KVSO_REGISTER_HANDLER(KviKvsObject_combobox,"maxCount", functionmaxCount)
+ KVSO_REGISTER_HANDLER(KviKvsObject_combobox,"count", functioncount)
+ KVSO_REGISTER_HANDLER(KviKvsObject_combobox,"current", functioncurrent)
+ KVSO_REGISTER_HANDLER(KviKvsObject_combobox,"currentItem", functioncurrentItem)
+ KVSO_REGISTER_HANDLER(KviKvsObject_combobox,"setEditable", functionsetEditable);
+ KVSO_REGISTER_HANDLER(KviKvsObject_combobox,"editable", functioneditable)
+ KVSO_REGISTER_HANDLER(KviKvsObject_combobox,"setEditText", functionsetEditText)
+ KVSO_REGISTER_HANDLER(KviKvsObject_combobox,"textAt", functiontextAt)
+ KVSO_REGISTER_HANDLER(KviKvsObject_combobox,"textLineEdit", functiontextLineEdit)
+ KVSO_REGISTER_HANDLER(KviKvsObject_combobox,"setTextLineEdit", functionsetTextLineEdit)
+ KVSO_REGISTER_HANDLER(KviKvsObject_combobox,"setCurrentItem", functionsetCurrentItem)
+ KVSO_REGISTER_HANDLER(KviKvsObject_combobox,"popup", functionpopup)
+
+ KVSO_REGISTER_HANDLER(KviKvsObject_combobox,"setInsertionPolicy", functionsetInsertionPolicy)
+ KVSO_REGISTER_HANDLER(KviKvsObject_combobox,"textChangedEvent", functiontextChangedEvent)
+ KVSO_REGISTER_HANDLER(KviKvsObject_combobox,"activatedEvent", functionactivatedEvent)
+
+KVSO_END_REGISTERCLASS(KviKvsObject_combobox)
+
+KVSO_BEGIN_CONSTRUCTOR(KviKvsObject_combobox,KviKvsObject_widget)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_combobox)
+
+
+KVSO_BEGIN_DESTRUCTOR(KviKvsObject_combobox)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_combobox)
+
+bool KviKvsObject_combobox::init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams)
+{
+ setObject(new QComboBox(parentScriptWidget(), name()), true);
+ connect (((QComboBox *)widget()),SIGNAL(activated( int )),this,SLOT(slotActivated( int )));
+ return true;
+}
+
+bool KviKvsObject_combobox::functioninsertItem(KviKvsObjectFunctionCall *c)
+{
+ kvs_int_t iIndex;
+ QString szItem;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("item",KVS_PT_STRING,0,szItem)
+ KVSO_PARAMETER("index",KVS_PT_INT,KVS_PF_OPTIONAL,iIndex)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ if(c->paramCount()==1)
+ ((QComboBox *)widget())->insertItem(szItem);
+ else
+ ((QComboBox *)widget())->insertItem(szItem, iIndex);
+ return true;
+}
+bool KviKvsObject_combobox::functionclear(KviKvsObjectFunctionCall *c)
+{
+ if (widget()) ((QComboBox *)widget())->clear();
+ return true;
+}
+bool KviKvsObject_combobox::functionchangeItem(KviKvsObjectFunctionCall *c)
+{
+
+ kvs_uint_t uIndex,cnt;
+ QString szText;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("text",KVS_PT_STRING,0,szText)
+ KVSO_PARAMETER("index",KVS_PT_UNSIGNEDINTEGER,0,uIndex)
+ KVSO_PARAMETERS_END(c)
+ if(!widget()) return true;
+ if (szText.isEmpty()) c->warning(__tr2qs("No string parameter given - using empty string"));
+ if(uIndex >= (cnt = ((QComboBox *)widget())->count()))
+ {
+ c->warning(__tr2qs("Item index [%d] is too big - defaulting to " \
+ "$count() - 1 [%d]"), uIndex, cnt);
+ uIndex = cnt - 1;
+ }
+
+ ((QComboBox *)widget())->changeItem(szText, uIndex);
+
+ return true;
+
+}
+bool KviKvsObject_combobox::functionremoveItem(KviKvsObjectFunctionCall *c)
+{
+
+ kvs_uint_t uIndex,cnt;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("index",KVS_PT_UNSIGNEDINTEGER,0,uIndex)
+ KVSO_PARAMETERS_END(c)
+ if(!widget()) return true;
+ if(uIndex >= (cnt = ((QComboBox *)widget())->count()))
+ {
+ c->warning(__tr2qs("Item index [%d] is too big - defaulting to " \
+ "$count() - 1 [%d]"), uIndex, cnt);
+ uIndex = cnt - 1;
+ }
+
+ ((QComboBox *)widget())->removeItem(uIndex);
+
+ return true;
+
+}
+bool KviKvsObject_combobox::functionsetMaxCount(KviKvsObjectFunctionCall *c)
+{
+
+ kvs_uint_t iMax;
+ QString szText;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("count",KVS_PT_UNSIGNEDINTEGER,0,iMax)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ ((QComboBox *)widget())->setMaxCount(iMax);
+ return true;
+}
+bool KviKvsObject_combobox::functionmaxCount(KviKvsObjectFunctionCall *c)
+{
+ if (widget()) c->returnValue()->setInteger(((QComboBox *)widget())->maxCount());
+ return true;
+}
+bool KviKvsObject_combobox::functioncount(KviKvsObjectFunctionCall *c)
+{
+ if (widget()) c->returnValue()->setInteger(((QComboBox *)widget())->count());
+ return true;
+}
+bool KviKvsObject_combobox::functioncurrent(KviKvsObjectFunctionCall *c)
+{
+ if (widget()) c->returnValue()->setString(((QComboBox *)widget())->currentText().local8Bit().data());
+ return true;
+}
+bool KviKvsObject_combobox::functioncurrentItem(KviKvsObjectFunctionCall *c)
+{
+ if (widget()) c->returnValue()->setInteger(((QComboBox *)widget())->currentItem());
+ return true;
+}
+bool KviKvsObject_combobox::functiontextLineEdit(KviKvsObjectFunctionCall *c)
+{
+ if (widget()) c->returnValue()->setString(((QComboBox *)widget())->lineEdit()->text());
+ return true;
+}
+
+bool KviKvsObject_combobox::functionsetEditable(KviKvsObjectFunctionCall *c)
+{
+ bool bFlag;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bflag",KVS_PT_BOOLEAN,0,bFlag)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ {
+ ((QComboBox *)widget())->setEditable(bFlag);
+ if (bFlag) connect (((QComboBox *)widget())->lineEdit(),SIGNAL(textChanged(const QString & )),this,SLOT(slottextChanged(const QString & )));
+ else
+ disconnect (((QComboBox *)widget())->lineEdit(),SIGNAL(textChanged(const QString & )),this,SLOT(slottextChanged(const QString & )));
+ }
+
+ return true;
+}
+bool KviKvsObject_combobox::functionsetTextLineEdit(KviKvsObjectFunctionCall *c)
+{
+ QString szText;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("text",KVS_PT_STRING,0,szText)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ ((QComboBox *)widget())->lineEdit()->setText(szText);
+ return true;
+}
+
+bool KviKvsObject_combobox::functioneditable(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ c->returnValue()->setBoolean(((QComboBox *)widget())->editable());
+ return true;
+}
+bool KviKvsObject_combobox::functionsetEditText(KviKvsObjectFunctionCall *c)
+{
+ QString szText;
+ bool bQuiet=false;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("text",KVS_PT_STRING,0,szText)
+ KVSO_PARAMETER("quiet",KVS_PT_BOOLEAN,KVS_PF_OPTIONAL,bQuiet)
+ KVSO_PARAMETERS_END(c)
+ if(!widget()) return true;
+ if (szText.isEmpty() && !bQuiet) c->warning("No string parameter given - using empty string");
+ ((QComboBox *)widget())->setEditText(szText);
+ return true;
+}
+bool KviKvsObject_combobox::functiontextAt(KviKvsObjectFunctionCall *c)
+{
+
+ kvs_uint_t uIndex;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("index",KVS_PT_UNSIGNEDINTEGER,0,uIndex)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ c->returnValue()->setString(((QComboBox *)widget())->text(uIndex));
+ return true;
+}
+bool KviKvsObject_combobox::functionsetCurrentItem(KviKvsObjectFunctionCall *c)
+{
+ kvs_uint_t uIndex;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("index",KVS_PT_UNSIGNEDINTEGER,0,uIndex)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ ((QComboBox *)widget())->setCurrentItem(uIndex);
+ return true;
+}
+bool KviKvsObject_combobox::functionpopup(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ ((QComboBox *)widget())->popup();
+ return true;
+}
+bool KviKvsObject_combobox::functionsetInsertionPolicy(KviKvsObjectFunctionCall *c)
+{
+ QString szPolicy;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("policy",KVS_PT_STRING,0,szPolicy)
+ KVSO_PARAMETERS_END(c)
+ if(!widget()) return true;
+ if(KviQString::equalCI(szPolicy,"NoInsertion"))
+ ((QComboBox *)widget())->setInsertionPolicy(QComboBox::NoInsertion);
+ else if(KviQString::equalCI(szPolicy,"AtTop"))
+ ((QComboBox *)widget())->setInsertionPolicy(QComboBox::AtTop);
+ else if(KviQString::equalCI(szPolicy,"AtBotton"))
+ ((QComboBox *)widget())->setInsertionPolicy(QComboBox::AtBottom);
+ else if(KviQString::equalCI(szPolicy,"AtCurrent"))
+ ((QComboBox *)widget())->setInsertionPolicy(QComboBox::AtCurrent);
+ else if(KviQString::equalCI(szPolicy,"AfterCurrent"))
+ ((QComboBox *)widget())->setInsertionPolicy(QComboBox::AfterCurrent);
+ else if(KviQString::equalCI(szPolicy,"BeforeCurrent"))
+ ((QComboBox *)widget())->setInsertionPolicy(QComboBox::BeforeCurrent);
+ else c->warning(__tr2qs("Invalid insertion Policy %Q"),&szPolicy);
+ return true;
+}
+
+
+
+bool KviKvsObject_combobox::functiontextChangedEvent(KviKvsObjectFunctionCall *c)
+{
+
+ emitSignal("textChanged",c,c->params());
+ return true;
+
+}
+
+void KviKvsObject_combobox::slottextChanged(const QString &text)
+{
+ KviKvsVariantList params(new KviKvsVariant(text));
+ callFunction(this,"textChangedEvent",&params);
+}
+
+bool KviKvsObject_combobox::functionactivatedEvent(KviKvsObjectFunctionCall *c)
+{
+
+ emitSignal("activated",c,c->params());
+ return true;
+
+}
+
+void KviKvsObject_combobox::slotActivated(int i)
+{
+ KviKvsVariantList params(new KviKvsVariant((kvs_int_t)i));
+ callFunction(this,"activatedEvent",&params);
+}
+
+
+#include "m_class_combobox.moc"
diff --git a/src/modules/objects/class_combobox.h b/src/modules/objects/class_combobox.h
new file mode 100644
index 00000000..d4da7c6b
--- /dev/null
+++ b/src/modules/objects/class_combobox.h
@@ -0,0 +1,71 @@
+#ifndef _CLASS_COMBOBOX_H_
+#define _CLASS_COMBOBOX_H_
+
+//vim: ts=8
+// File : class_combobox.h
+// Creation date : Thu Mar 22 20:57:28 CET 2001 by Krzysztof Godlewski
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+#include <qcombobox.h>
+#include "class_widget.h"
+#include "object_macros.h"
+
+class KviKvsObject_combobox : public KviKvsObject_widget
+{
+ Q_OBJECT
+public:
+ KVSO_DECLARE_OBJECT(KviKvsObject_combobox)
+public:
+ QWidget * widget() { return (QWidget *)object(); };
+protected:
+ virtual bool init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams);
+
+ bool functioninsertItem(KviKvsObjectFunctionCall *c);
+ bool functionchangeItem(KviKvsObjectFunctionCall *c);
+ bool functionremoveItem(KviKvsObjectFunctionCall *c);
+ bool functionclear(KviKvsObjectFunctionCall *c);
+//#warning "$insertPixItem"
+//#warning "$changePixItem"
+
+ bool functioncount(KviKvsObjectFunctionCall *c);
+ bool functionsetMaxCount(KviKvsObjectFunctionCall *c);
+ bool functionmaxCount(KviKvsObjectFunctionCall *c);
+ bool functioncurrent(KviKvsObjectFunctionCall *c);
+ bool functioncurrentItem(KviKvsObjectFunctionCall *c);
+ bool functionsetEditable(KviKvsObjectFunctionCall *c);
+ bool functioneditable(KviKvsObjectFunctionCall *c);
+ bool functionsetEditText(KviKvsObjectFunctionCall *c);
+ bool functiontextAt(KviKvsObjectFunctionCall *c);
+ bool functiontextLineEdit(KviKvsObjectFunctionCall *c);
+ bool functionsetTextLineEdit(KviKvsObjectFunctionCall *c);
+
+ bool functionsetInsertionPolicy(KviKvsObjectFunctionCall *c);
+
+ bool functionsetCurrentItem(KviKvsObjectFunctionCall *c);
+ bool functionpopup(KviKvsObjectFunctionCall *c);
+ bool functiontextChangedEvent(KviKvsObjectFunctionCall *c);
+ bool functionactivatedEvent(KviKvsObjectFunctionCall *c);
+protected slots:
+ void slottextChanged(const QString &);
+ void slotActivated(int);
+};
+
+#endif // !_CLASS_COMBOBOX_H_
diff --git a/src/modules/objects/class_dialog.cpp b/src/modules/objects/class_dialog.cpp
new file mode 100644
index 00000000..f062f004
--- /dev/null
+++ b/src/modules/objects/class_dialog.cpp
@@ -0,0 +1,89 @@
+//
+// File : class_dialog.cpp
+// Creation date : Sun Apr 10 22:51:48 CEST 2002 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "class_dialog.h"
+
+#include "kvi_error.h"
+#include "kvi_debug.h"
+
+#include "kvi_locale.h"
+#include "kvi_frame.h"
+#include "kvi_app.h"
+
+#include <qdialog.h>
+
+
+/*
+ @doc: dialog
+ @title:
+ dialog class
+ @type:
+ class
+ @short:
+ A toplevel dialog object
+ @inherits:
+ [class]object[/class]
+ [class]widget[/class]
+ @description:
+ Rappresents a dialog object. The class is really
+ similar to the widget class, it has only a couple of minor differences.
+ A dialog is always a top-level widget, but if it has a parent, its default
+ location is centered on top of the parent. It will also share the parent's taskbar entry.
+ If you call $setModal(1) then the dialog will have non-blocking modal behaviour:
+ it will appear above its parent widget and block its input until it's closed.
+ @functions:
+*/
+
+KVSO_BEGIN_REGISTERCLASS(KviKvsObject_dialog,"dialog","widget")
+ KVSO_REGISTER_HANDLER(KviKvsObject_dialog,"setModal",functionSetModal)
+KVSO_END_REGISTERCLASS(KviKvsObject_dialog)
+
+KVSO_BEGIN_CONSTRUCTOR(KviKvsObject_dialog,KviKvsObject_widget)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_dialog)
+
+
+KVSO_BEGIN_DESTRUCTOR(KviKvsObject_dialog)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_dialog)
+
+bool KviKvsObject_dialog::init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams)
+{
+ QWidget * w = g_pApp->activeModalWidget();
+ if(!w)w = g_pFrame;
+ QDialog * d = new QDialog(parentScriptWidget() ? parentScriptWidget() : w,name());
+ //d->setModal(true);
+ setObject(d);
+ return true;
+}
+bool KviKvsObject_dialog::functionSetModal(KviKvsObjectFunctionCall *c)
+{
+ bool bEnabled;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bEnabled",KVS_PT_BOOL,0,bEnabled)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ ((QDialog *)widget())->setModal(bEnabled);
+ return true;
+}
+
+
diff --git a/src/modules/objects/class_dialog.h b/src/modules/objects/class_dialog.h
new file mode 100644
index 00000000..b284baf3
--- /dev/null
+++ b/src/modules/objects/class_dialog.h
@@ -0,0 +1,44 @@
+#ifndef _CLASS_DIALOG_H_
+#define _CLASS_DIALOG_H_
+//
+// File : class_dialog.h
+// Creation date : Sun Apr 10 22:51:48 CEST 2002 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "class_widget.h"
+
+class QDialog;
+
+#include "object_macros.h"
+
+class KviKvsObject_dialog : public KviKvsObject_widget
+{
+
+public:
+ KVSO_DECLARE_OBJECT(KviKvsObject_dialog)
+public:
+ QWidget * widget() { return (QWidget *)object(); };
+protected:
+ virtual bool init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams);
+ bool functionSetModal(KviKvsObjectFunctionCall *c);
+};
+
+#endif // !_CLASS_DIALOG_H_
+
diff --git a/src/modules/objects/class_dockwindow.cpp b/src/modules/objects/class_dockwindow.cpp
new file mode 100644
index 00000000..fc439b23
--- /dev/null
+++ b/src/modules/objects/class_dockwindow.cpp
@@ -0,0 +1,276 @@
+//=============================================================================
+//
+// File : class_dockwindow.cpp
+// Created on Thu 29 Dec 2005 23:45:11 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "class_dockwindow.h"
+
+#include "kvi_frame.h"
+#include "kvi_locale.h"
+#include "kvi_qstring.h"
+#ifdef COMPILE_USE_QT4
+ #include <QDockWidget>
+ #define QT_DOCK_WINDOW QDockWidget
+#else
+ #include <qdockwindow.h>
+ #define QT_DOCK_WINDOW QDockWindow
+#endif
+#include <qlayout.h>
+
+/*
+ @doc: dockwindow
+ @title:
+ dockwindow class
+ @type:
+ class
+ @short:
+ A window dockable to the KVIrc main frame
+ @inherits:
+ [class]object[/class]
+ [class]widget[/class]
+ @description:
+ A window dockable to the KVIrc main frame borders (like a toolbar).
+ The window has an implicit layout that will automatically manage
+ the children depending on the dock window's orientation.
+ @functions:
+ !fn: $addWidget(<widget:hobject>)
+ Adds <widget> to the internal layout of this dock window.[br]
+ The widget must be a child of this dock window (otherwise strange things may happen).
+ !fn: <string> $orientation()
+ Returns the string "vertical" or "horizontal" depending on the orientation of this dock window.
+ !fn: $setOrientation(<orientation:string>)
+ Forces the orentation of this dock window. <ordientation> must be either "horizontal" or "vertical".[br]
+ Please note that KVIrc sets the orientation automatically when it is moved between the main frame docks by the user.
+ !fn: <bool> $resizeEnabled()
+ Returns $true if resizing of this window is enabled and false otherwise.
+ !fn: $setResizeEnabled(<bEnabled:bool>)
+ Enabled or disabled resizing of this window.
+ !fn: $setAllowedDockAreas(<docks:string>)
+ Sets the allowed main window dock areas for this dock window.[br]
+ <docks> must be a combination of "l","r","t","b","f" and "m".[br]
+ "l" stands for left dock area, "r" stands for right dock area, "t" stands for the top dock areas, "b" stands for the bottom dock area, "f" stands for "floating" and "m" for "minimized".[br]
+ If a flag is present then the related block area is enabled,otherwise it is disabled.
+ !fn: $dock(<dockarea:string>)
+ Docks this dock window to the specified dockarea of the main KVIrc window which can be one of "l" (left dock area), "t" (top dock area), "r" (right dock area), "b" (bottom dock area), "f" (floating) and "m" (minimized).
+*/
+
+
+KVSO_BEGIN_REGISTERCLASS(KviKvsObject_dockwindow,"dockwindow","widget")
+ KVSO_REGISTER_HANDLER(KviKvsObject_dockwindow,"addWidget",function_addWidget)
+ KVSO_REGISTER_HANDLER(KviKvsObject_dockwindow,"orientation",function_orientation)
+ KVSO_REGISTER_HANDLER(KviKvsObject_dockwindow,"setOrientation",function_setOrientation)
+ KVSO_REGISTER_HANDLER(KviKvsObject_dockwindow,"resizeEnabled",function_resizeEnabled)
+ KVSO_REGISTER_HANDLER(KviKvsObject_dockwindow,"setResizeEnabled",function_setResizeEnabled)
+ KVSO_REGISTER_HANDLER(KviKvsObject_dockwindow,"setAllowedDockAreas",function_setAllowedDockAreas)
+ KVSO_REGISTER_HANDLER(KviKvsObject_dockwindow,"dock",function_dock)
+KVSO_END_REGISTERCLASS(KviKvsObject_dockwindow)
+
+
+KVSO_BEGIN_CONSTRUCTOR(KviKvsObject_dockwindow,KviKvsObject_widget)
+KVSO_END_CONSTRUCTOR(KviKvsObject_dockwindow)
+
+
+KVSO_BEGIN_DESTRUCTOR(KviKvsObject_dockwindow)
+KVSO_END_DESTRUCTOR(KviKvsObject_dockwindow)
+
+#define _pDockWindow ((QT_DOCK_WINDOW *)widget())
+
+bool KviKvsObject_dockwindow::init(KviKvsRunTimeContext * pContext,KviKvsVariantList * pParams)
+{
+#ifdef COMPILE_USE_QT4
+ QDockWidget * pWidget = new QDockWidget(g_pFrame);
+ pWidget->setObjectName(getName());
+ setObject(pWidget);
+#else //!COMPILE_USE_QT4
+ setObject(new QT_DOCK_WINDOW(g_pFrame,getName()),true);
+#endif //!COMPILE_USE_QT4
+ return true;
+}
+
+bool KviKvsObject_dockwindow::function_addWidget(KviKvsObjectFunctionCall *c)
+{
+ kvs_hobject_t hWidget;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("widget",KVS_PT_HOBJECT,0,hWidget)
+ KVSO_PARAMETERS_END(c)
+
+ if(!widget())return true; // hum ? dead ?
+
+ if(hWidget == (kvs_hobject_t)0)
+ {
+ // null widget ?
+ c->warning(__tr2qs("Can't add a null object"));
+ return true;
+ }
+
+ KviKvsObject * pWidget = KviKvsKernel::instance()->objectController()->lookupObject(hWidget);
+ if(!pWidget)
+ {
+ c->warning(__tr2qs("Invalid object handle passed as parameter (the object is no longer existing ?)"));
+ return true;
+ }
+
+ if(!pWidget->object())
+ {
+ c->warning(__tr2qs("Object in invalid state"));
+ return true;
+ }
+
+ if(!pWidget->object()->isWidgetType())
+ {
+ c->warning(__tr2qs("Can't set a non-widget object to be the main widget of a dock window"));
+ return true;
+ }
+
+ if(((QWidget *)(pWidget->object()))->parent() != (QObject *)_pDockWindow)
+ {
+ c->warning(__tr2qs("The added widget is not a child of this dock window"));
+ }
+
+#ifdef COMPILE_USE_QT4
+ _pDockWindow->setWidget((QWidget *)(pWidget->object()));
+#else //!COMPILE_USE_QT4
+ _pDockWindow->boxLayout()->addWidget((QWidget *)(pWidget->object()));
+ ((QWidget *)(pWidget->object()))->show();
+#endif //!COMPILE_USE_QT4
+ return true;
+}
+
+bool KviKvsObject_dockwindow::function_orientation(KviKvsObjectFunctionCall * c)
+{
+ if(!widget())return true; // hum ? dead ?
+#ifdef COMPILE_USE_QT4
+ c->returnValue()->setString(QString("horizontal"));
+#else //!COMPILE_USE_QT4
+ c->returnValue()->setString(_pDockWindow->orientation() == Qt::Horizontal ? QString("horizontal") : QString("vertical"));
+#endif //!COMPILE_USE_QT4
+ return true;
+}
+
+bool KviKvsObject_dockwindow::function_setOrientation(KviKvsObjectFunctionCall * c)
+{
+ QString szOrientation;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("orientation",KVS_PT_NONEMPTYSTRING,0,szOrientation)
+ KVSO_PARAMETERS_END(c)
+
+ if(!widget())return true; // hum ? dead ?
+#ifndef COMPILE_USE_QT4
+ _pDockWindow->setOrientation(KviQString::equalCI(szOrientation,"vertical") ? Qt::Vertical : Qt::Horizontal);
+#endif //!COMPILE_USE_QT4
+ return true;
+}
+
+bool KviKvsObject_dockwindow::function_resizeEnabled(KviKvsObjectFunctionCall * c)
+{
+ if(!widget())return true; // hum ? dead ?
+#ifdef COMPILE_USE_QT4
+ c->returnValue()->setBoolean(false);
+#else //!COMPILE_USE_QT4
+ c->returnValue()->setBoolean(_pDockWindow->isResizeEnabled());
+#endif //!COMPILE_USE_QT4
+ return true;
+}
+
+bool KviKvsObject_dockwindow::function_setResizeEnabled(KviKvsObjectFunctionCall * c)
+{
+ bool bResizeEnabled;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bEnabled",KVS_PT_BOOL,0,bResizeEnabled)
+ KVSO_PARAMETERS_END(c)
+
+ if(!widget())return true; // hum ? dead ?
+
+#ifndef COMPILE_USE_QT4
+ _pDockWindow->setResizeEnabled(bResizeEnabled);
+#endif //!COMPILE_USE_QT4
+ return true;
+}
+
+bool KviKvsObject_dockwindow::function_setAllowedDockAreas(KviKvsObjectFunctionCall * c)
+{
+ QString szFlags;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("docks",KVS_PT_STRING,0,szFlags)
+ KVSO_PARAMETERS_END(c)
+
+ if(!widget())return true; // hum ? dead ?
+
+#ifdef COMPILE_USE_QT4
+ Qt::DockWidgetAreas fAreas = Qt::NoDockWidgetArea;
+ if(szFlags.find('t',false))fAreas |= Qt::TopDockWidgetArea;
+ if(szFlags.find('l',false))fAreas |= Qt::LeftDockWidgetArea;
+ if(szFlags.find('r',false))fAreas |= Qt::RightDockWidgetArea;
+ if(szFlags.find('b',false))fAreas |= Qt::BottomDockWidgetArea;
+ _pDockWindow->setAllowedAreas(fAreas);
+ QDockWidget::DockWidgetFeatures fFeatures = _pDockWindow->features();
+ if(szFlags.find('f',false))
+ fFeatures |= QDockWidget::DockWidgetFloatable;
+ else
+ fFeatures &= ~QDockWidget::DockWidgetFloatable;
+ // no support for minimized dock widgets
+ _pDockWindow->setFeatures(fFeatures);
+#else //!COMPILE_USE_QT4
+ g_pFrame->setDockEnabled(_pDockWindow,Qt::DockTop,szFlags.find('t',false) != -1);
+ g_pFrame->setDockEnabled(_pDockWindow,Qt::DockLeft,szFlags.find('l',false) != -1);
+ g_pFrame->setDockEnabled(_pDockWindow,Qt::DockRight,szFlags.find('r',false) != -1);
+ g_pFrame->setDockEnabled(_pDockWindow,Qt::DockBottom,szFlags.find('b',false) != -1);
+ g_pFrame->setDockEnabled(_pDockWindow,Qt::DockTornOff,szFlags.find('f',false) != -1);
+ g_pFrame->setDockEnabled(_pDockWindow,Qt::DockMinimized,szFlags.find('m',false) != -1);
+#endif //!COMPILE_USE_QT4
+
+ return true;
+}
+
+
+bool KviKvsObject_dockwindow::function_dock(KviKvsObjectFunctionCall * c)
+{
+ QString szDock;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("dock",KVS_PT_STRING,0,szDock)
+ KVSO_PARAMETERS_END(c)
+
+ if(!widget())return true; // hum ? dead ?
+#ifdef COMPILE_USE_QT4
+ g_pFrame->removeDockWidget(_pDockWindow);
+ if(szDock.find('m',false) == -1)_pDockWindow->setFloating(false);
+ if(szDock.find('t',false) != -1)g_pFrame->addDockWidget(Qt::TopDockWidgetArea,_pDockWindow);
+ else if(szDock.find('l',false) != -1)g_pFrame->addDockWidget(Qt::LeftDockWidgetArea,_pDockWindow);
+ else if(szDock.find('r',false) != -1)g_pFrame->addDockWidget(Qt::RightDockWidgetArea,_pDockWindow);
+ else if(szDock.find('b',false) != -1)g_pFrame->addDockWidget(Qt::BottomDockWidgetArea,_pDockWindow);
+ else if(szDock.find('f',false) != -1)_pDockWindow->setFloating(true);
+ else if(szDock.find('m',false) != -1)qDebug("Sorry: no support for minimized dock widgets in Qt4");
+ else c->warning(__tr2qs("Invalid dock area specified"));
+
+#else //!COMPILE_USE_QT4
+ if(szDock.find('t',false) != -1)g_pFrame->moveDockWindow(_pDockWindow,Qt::DockTop,false,100);
+ else if(szDock.find('l',false) != -1)g_pFrame->moveDockWindow(_pDockWindow,Qt::DockLeft,false,100);
+ else if(szDock.find('r',false) != -1)g_pFrame->moveDockWindow(_pDockWindow,Qt::DockRight,false,100);
+ else if(szDock.find('b',false) != -1)g_pFrame->moveDockWindow(_pDockWindow,Qt::DockBottom,false,100);
+ else if(szDock.find('f',false) != -1)g_pFrame->moveDockWindow(_pDockWindow,Qt::DockTornOff,false,100);
+ else if(szDock.find('m',false) != -1)g_pFrame->moveDockWindow(_pDockWindow,Qt::DockMinimized,false,100);
+ else c->warning(__tr2qs("Invalid dock area specified"));
+#endif //!COMPILE_USE_QT4
+ return true;
+}
+
+#include "m_class_dockwindow.moc"
diff --git a/src/modules/objects/class_dockwindow.h b/src/modules/objects/class_dockwindow.h
new file mode 100644
index 00000000..4576a43d
--- /dev/null
+++ b/src/modules/objects/class_dockwindow.h
@@ -0,0 +1,49 @@
+#ifndef _CLASS_DOCKWINDOW_H_
+#define _CLASS_DOCKWINDOW_H_
+//=============================================================================
+//
+// File : class_dockwindow.h
+// Created on Thu 29 Dec 2005 23:45:11 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "object_macros.h"
+
+#include "class_widget.h"
+
+class KviKvsObject_dockwindow : public KviKvsObject_widget
+{
+ Q_OBJECT
+public:
+ KVSO_DECLARE_OBJECT(KviKvsObject_dockwindow)
+protected:
+ virtual bool init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams);
+
+ bool function_addWidget(KviKvsObjectFunctionCall *c);
+ bool function_orientation(KviKvsObjectFunctionCall *c);
+ bool function_setOrientation(KviKvsObjectFunctionCall *c);
+ bool function_resizeEnabled(KviKvsObjectFunctionCall *c);
+ bool function_setResizeEnabled(KviKvsObjectFunctionCall * c);
+ bool function_setAllowedDockAreas(KviKvsObjectFunctionCall * c);
+ bool function_dock(KviKvsObjectFunctionCall * c);
+};
+
+#endif //!_CLASS_DOCKWINDOW_H_
diff --git a/src/modules/objects/class_file.cpp b/src/modules/objects/class_file.cpp
new file mode 100644
index 00000000..3429278e
--- /dev/null
+++ b/src/modules/objects/class_file.cpp
@@ -0,0 +1,488 @@
+//vim: ts=8
+// File : class_file.cpp
+// Creation date : Thu Sep 21 04:42:16 CEST 2000 by Krzysztof Godlewski
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+//#warning "Add QFILEINFO to this stuff ?"
+
+#include "class_file.h"
+#include "kvi_debug.h"
+
+#include "kvi_locale.h"
+#include "kvi_error.h"
+#include "kvi_fileutils.h"
+#include <qstringlist.h>
+
+
+// needed for $open()
+const char * const mod_tbl[] = {
+ "Raw",
+ "ReadOnly",
+ "WriteOnly",
+ "ReadWrite",
+ "Append",
+ "Truncate"
+ };
+#ifdef COMPILE_USE_QT4
+#define IO_RAW QIODevice::Unbuffered
+#define IO_READONLY QIODevice::ReadOnly
+#define IO_WRITEONLY QIODevice::WriteOnly
+#define IO_READWRITE QIODevice::ReadWrite
+#define IO_APPEND QIODevice::Append
+#define IO_TRUNCATE QIODevice::Truncate
+//#define IO_TRANSLATE QIODevice::Text
+#else
+#define IO_RAW IO_Raw
+#define IO_READONLY IO_ReadOnly
+#define IO_WRITEONLY IO_WriteOnly
+#define IO_READWRITE IO_ReadWrite
+#define IO_APPEND IO_Append
+#define IO_TRUNCATE IO_Truncate
+#endif
+#ifdef COMPILE_USE_QT4
+const QIODevice::OpenMode mod_cod[] = {
+#else
+const int mod_cod[] = {
+#endif
+ IO_RAW,
+ IO_READONLY,
+ IO_WRITEONLY,
+ IO_READWRITE,
+ IO_APPEND,
+ IO_TRUNCATE
+ };
+
+#define mod_num (sizeof(mod_tbl) / sizeof(mod_tbl[0]))
+
+/*
+ @doc: file
+ @keyterms:
+ file object class, creating files
+ @title:
+ file class
+ @type:
+ class
+ @short:
+ I/O device that operates on files
+ @inherits:
+ [class]object[/class]
+ @description:
+ This object class provides access to files - basic I/O
+ operations, copying, removing etc...
+ @functions:
+ !fn: $setName(<file_name:string>)
+ Sets the file name to <file_name>. It does [b]not move[/b] the file,
+ it just changes the file the object is "pointing to". You can
+ not change names of already open files.[br]
+ See also: [classfnc]$open[/classfnc](),
+ [classfnc]$name[/classfnc]().
+ !fn: <string> $name()
+ Returns name set by [classfnc]$setName[/classfnc]().[br]
+ See also: [classfnc]$setName[/classfnc]().
+ !fn: $open(<mode1:string>, <mode2:string>)
+ Attempts to open the file in specified mode or modes "sum".
+ Valid modes are:[br]
+ [pre]
+ Raw - raw, non-buffered access[br]
+ ReadOnly - opens the file read-only[br]
+ WriteOnly - opens the file write-only[br]
+ ReadWrite - opens the file in read-write mode[br]
+ Append - opens the file in append mode. The file index is set to the end of the file.[br]
+ Truncate - truncates the file[br]
+ [/pre]
+ If you call this function without any parameters, the file is
+ opened in ReadOnly mode.[br]
+ When working with buffered files, data is not written directly
+ to the file at once. You must call [classfnc]$flush[/classfnc]() to force it.[br]
+ See also: [classfnc]$close[/classfnc](),
+ [classfnc]$flush[/classfnc]().
+ !fn: <boolean> $isOpen()
+ Returns '1' if the file is open, '0' otherwise.
+ !fn: $close()
+ Closes the file, flushing the buffers first.[br]
+ See also: [classfnc]$flush[/classfnc]().
+ !fn: $flush()
+ Flushes the file buffer to disk. Calling this after opening the
+ file in 'Raw' mode doesn't make much sense.[br]
+ See also: [classfnc]$open[/classfnc](),
+ [classfnc]$close[/classfnc]().
+ !fn: <integer> $size()
+ Returns current file size.
+ !fn: <boolean> $atEnd()
+ Returns '1' if you have reached end of the file, '0' otherwise.
+ [br]See also: [classfnc]$seek[/classfnc](),
+ [classfnc]$where[/classfnc]().
+ !fn: <integer> $where()
+ Returns current position in the file (file index).[br]
+ See also: [classfnc]$seek[/classfnc]().
+ !fn: $seek(<index:integer>)
+ Sets the file index to <index>.[br]
+ See also: [classfnc]$where[/classfnc](),
+ [classfnc]$atEnd[/classfnc]().
+ !fn: $putch(<char>)
+ Writes character <char> to the file and increments file
+ index.[br]
+ See also: [classfnc]$getch[/classfnc](),
+ [classfnc]$ungetch[/classfnc]().
+ !fn: <char> $getch()
+ Reads a character from the file and increments file index.[br]
+ See also: [classfnc]$putch[/classfnc](),
+ [classfnc]$ungetch[/classfnc]().
+ !fn: $ungetch(<char>)
+ Puts the character <char> back to the file and
+ decrements the file index. This is usually called to undo a
+ $getch() call.[br]
+ See also: [classfnc]$getch[/classfnc],
+ [classfnc]$putch[/classfnc]().
+ !fn: $readLine(<text_line:string>)
+ Reads a line of text from the file and increments file index.
+ !fn: $writeLine(<text_line:string>)
+ Appends a line of text to the end of the file.
+ $readBlock()
+ $writeBlock()
+ $writeHex()
+ $readHex()
+*/
+
+
+//---------------------------------------------------------------------------------
+
+KVSO_BEGIN_REGISTERCLASS(KviKvsObject_file,"file","object")
+ KVSO_REGISTER_HANDLER(KviKvsObject_file,"setName", functionsetName)
+ KVSO_REGISTER_HANDLER(KviKvsObject_file,"name", functionname)
+ KVSO_REGISTER_HANDLER(KviKvsObject_file,"open", functionopen)
+ KVSO_REGISTER_HANDLER(KviKvsObject_file,"isOpen", functionisOpen)
+ KVSO_REGISTER_HANDLER(KviKvsObject_file,"close", functionclose)
+ KVSO_REGISTER_HANDLER(KviKvsObject_file,"flush", functionflush)
+ KVSO_REGISTER_HANDLER(KviKvsObject_file,"size", functionsize)
+ KVSO_REGISTER_HANDLER(KviKvsObject_file,"atEnd", functionatEnd)
+ KVSO_REGISTER_HANDLER(KviKvsObject_file,"where", functionwhere)
+
+ KVSO_REGISTER_HANDLER(KviKvsObject_file,"seek", functionseek)
+ KVSO_REGISTER_HANDLER(KviKvsObject_file,"putch", functionputch)
+ KVSO_REGISTER_HANDLER(KviKvsObject_file,"getch", functiongetch)
+ KVSO_REGISTER_HANDLER(KviKvsObject_file,"ungetch", functionunGetch)
+ KVSO_REGISTER_HANDLER(KviKvsObject_file,"readBlock", functionreadBlock)
+ KVSO_REGISTER_HANDLER(KviKvsObject_file,"writeBlock", functionwriteBlock)
+ KVSO_REGISTER_HANDLER(KviKvsObject_file,"readLine", functionreadLine)
+ KVSO_REGISTER_HANDLER(KviKvsObject_file,"writeLine", functionwriteLine)
+/* KVSO_REGISTER_HANDLER(KviKvsObject_file,"hexWrite", functionHexWrite)
+ KVSO_REGISTER_HANDLER(KviKvsObject_file,"hexRead", functionHexRead)
+*/
+ KVSO_END_REGISTERCLASS(KviKvsObject_file)
+
+KVSO_BEGIN_CONSTRUCTOR(KviKvsObject_file,KviKvsObject)
+ m_pFile = new QFile();
+KVSO_END_CONSTRUCTOR(KviKvsObject_file)
+
+KVSO_BEGIN_DESTRUCTOR(KviKvsObject_file)
+if (m_pFile) delete m_pFile;
+m_pFile=0;
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_file)
+
+
+bool KviKvsObject_file::functionsetName(KviKvsObjectFunctionCall *c)
+{
+ QString szName;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("file_name",KVS_PT_STRING,0,szName)
+ KVSO_PARAMETERS_END(c)
+ if (m_pFile) m_pFile->setName(szName);
+ return true;
+}
+bool KviKvsObject_file::functionname(KviKvsObjectFunctionCall *c)
+{
+ if (m_pFile) c->returnValue()->setString(m_pFile->name());
+ return true;
+}
+
+bool KviKvsObject_file::functionopen(KviKvsObjectFunctionCall *c)
+{
+ QStringList modes;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("file_mode",KVS_PT_STRINGLIST,KVS_PF_OPTIONAL,modes)
+ KVSO_PARAMETERS_END(c)
+ if (!m_pFile) return true;
+ if(m_pFile->name().isEmpty())
+ {
+ c->warning(__tr2qs("Empty filename string"));
+ return true;
+ }
+ #ifdef COMPILE_USE_QT4
+ QIODevice::OpenMode mod,sum;
+ if (modes.empty()) sum = IO_READONLY; // if no parameters given, default to ReadWrite | Append
+ else
+ {
+ for ( int idx=0;idx<modes.count();idx++)
+ {
+ mod = IO_ReadOnly;
+ for(unsigned int j = 0; j < mod_num; j++)
+ {
+ if(KviQString::equalCI(modes.at(idx), mod_tbl[j]))
+ {
+ mod=mod_cod[j];
+ break;
+ }
+ }
+ if(mod!=IO_ReadOnly)
+ sum = sum | mod;
+ else
+ c->warning(__tr2qs("No such open mode: '%Q'"),&modes.at(idx));
+ }
+ }
+#else
+ int mod,sum=0;
+if (!modes.first()) sum = IO_READONLY; // if no parameters given, default to ReadWrite | Append
+ else
+ {
+ for ( QStringList::Iterator it = modes.begin(); it != modes.end(); ++it )
+ {
+
+ mod = 0;
+ for(unsigned int j = 0; j < mod_num; j++)
+ {
+ if(KviQString::equalCI((*it), mod_tbl[j]))
+ {
+ mod=mod_cod[j];
+ break;
+ }
+ }
+ if(mod)
+ sum = sum | mod;
+ else
+ c->warning(__tr2qs("No such open mode: '%Q'"),&(*it));
+ }
+ }
+#endif
+ m_pFile->open(sum);
+ return true;
+}
+
+bool KviKvsObject_file::functionisOpen(KviKvsObjectFunctionCall *c)
+{
+ if (m_pFile) c->returnValue()->setBoolean(m_pFile->isOpen());
+ return true;
+}
+
+bool KviKvsObject_file::functionclose(KviKvsObjectFunctionCall *c)
+{
+ if (!m_pFile->isOpen()) c->warning(__tr2qs("File is not open!"));
+ else m_pFile->close();
+ return true;
+}
+bool KviKvsObject_file::functionflush(KviKvsObjectFunctionCall *c)
+{
+ if (!m_pFile->isOpen()) c->warning(__tr2qs("File is not open!"));
+ else m_pFile->flush();
+ return true;
+}
+
+bool KviKvsObject_file::functionsize(KviKvsObjectFunctionCall *c)
+{
+ if (m_pFile) c->returnValue()->setInteger((kvs_int_t)(m_pFile->size()));
+ return true;
+}
+bool KviKvsObject_file::functionatEnd(KviKvsObjectFunctionCall *c)
+{
+ if (m_pFile) c->returnValue()->setInteger((kvs_int_t)(m_pFile->size()));
+ return true;
+}
+
+
+bool KviKvsObject_file::functionwhere(KviKvsObjectFunctionCall *c)
+{
+ if (!m_pFile->isOpen()) c->warning(__tr2qs("File is not open!"));
+ else c->returnValue()->setInteger((kvs_int_t)(m_pFile->at()));
+ return true;
+}
+bool KviKvsObject_file::functionseek(KviKvsObjectFunctionCall *c)
+{
+ kvs_uint_t uIndex;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("index",KVS_PT_UNSIGNEDINTEGER,0,uIndex)
+ KVSO_PARAMETERS_END(c)
+ if (!m_pFile) return true;
+ if(!m_pFile->isOpen())
+ c->warning(__tr("File is not open !"));
+ else m_pFile->at(uIndex);
+ return true;
+}
+
+bool KviKvsObject_file::functionputch(KviKvsObjectFunctionCall *c)
+{
+ QString szChar;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("char",KVS_PT_STRING,KVS_PF_OPTIONAL,szChar)
+ KVSO_PARAMETERS_END(c)
+ if (m_pFile)
+ {
+ if (szChar.length()>1)c->warning(__tr2qs("Argument to long, using only first char"));
+ const char *ch=szChar;
+ if (m_pFile->putch(ch[0])<0) c->warning(__tr2qs("Write error occured !"));
+ }
+
+ return true;
+}
+bool KviKvsObject_file::functiongetch(KviKvsObjectFunctionCall *c)
+{
+ if (!m_pFile) return true;
+ if(!m_pFile->isOpen())
+ c->warning(__tr("File is not open !"));
+ else
+ {
+ int chInt=m_pFile->getch();
+ if (chInt<0) c->warning(__tr("Read error occured !")); // c->error ?
+ QString szChar = QChar(chInt);
+ c->returnValue()->setString(szChar);
+ }
+ return true;
+}
+bool KviKvsObject_file::functionunGetch(KviKvsObjectFunctionCall *c)
+{
+ QString szChar;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("char",KVS_PT_STRING,0,szChar)
+ KVSO_PARAMETERS_END(c)
+ if (!m_pFile) return true;
+ if(!m_pFile->isOpen())
+ c->warning(__tr("File is not open !"));
+ else
+ {
+ if (szChar.length()>1) c->warning(__tr2qs("Argument to long, using only first char"));
+ const char *ch=szChar;
+ if (m_pFile->ungetch(ch[0])<0) c->warning(__tr2qs("An error occured !"));// c->error ?
+ }
+ return true;
+}
+bool KviKvsObject_file::functionreadBlock(KviKvsObjectFunctionCall *c)
+{
+ kvs_uint_t uLen;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("lenght",KVS_PT_UNSIGNEDINTEGER,0,uLen)
+ KVSO_PARAMETERS_END(c)
+ if (!m_pFile) return true;
+ if(!m_pFile->isOpen())
+ c->warning(__tr("File is not open !"));
+ else
+ {
+ char * buff = new char[uLen + 1];
+ m_pFile->flush(); // advice from QFile man page (to avoid trash)
+ int rlen = m_pFile->readBlock(buff, uLen);
+ buff[rlen] = '\0';
+ QString szBlock(buff);
+ c->returnValue()->setString(szBlock);
+ }
+ return true;
+}
+
+bool KviKvsObject_file::functionwriteBlock(KviKvsObjectFunctionCall *c)
+{
+ QString szBlock;
+ kvs_uint_t uLen;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("lenght",KVS_PT_UNSIGNEDINTEGER,0,uLen)
+ KVSO_PARAMETER("text_block",KVS_PT_STRING,0,szBlock)
+ KVSO_PARAMETERS_END(c)
+ if (!m_pFile) return true;
+ if(!m_pFile->isOpen())
+ c->warning(__tr("File is not open !"));
+ const char *block=szBlock;
+ int rlen = m_pFile->writeBlock(block, uLen);
+ c->returnValue()->setInteger(rlen);
+ m_pFile->flush();
+ return true;
+}
+bool KviKvsObject_file::functionreadLine(KviKvsObjectFunctionCall *c)
+{
+ if (!m_pFile) return true;
+ if(!m_pFile->isOpen())
+ c->warning(__tr("File is not open !"));
+ else
+ {
+ QString buffer;
+ KviFileUtils::readLine(m_pFile,buffer);
+ c->returnValue()->setString(buffer);
+ }
+ return true;
+}
+bool KviKvsObject_file::functionwriteLine(KviKvsObjectFunctionCall *c)
+{
+ QString szLine;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("text_line",KVS_PT_STRING,0,szLine)
+ KVSO_PARAMETERS_END(c)
+ if (!m_pFile) return true;
+ if(!m_pFile->isOpen())
+ c->warning(__tr("File is not open !"));
+ else
+ {
+ QTextStream ts(m_pFile);
+ ts << szLine;
+ }
+ return true;
+}
+// fixme
+/*
+
+bool KviScriptFileObject::functionHexWrite(KviCommand * c, KviParameterList * p,
+ KviStr & b)
+{
+ ENTER_STACK_FRAME(c, "file::hexWrite");
+ if(!p->count())
+ return c->error(KviError_notEnoughParameters);
+
+ char * val = 0;
+ int len = p->first()->hexToBuffer(&val,false);
+
+ if(len < 1)
+ {
+ c->warning(__tr("Nothing to write"));
+ return c->leaveStackFrame();
+ }
+
+ if(!m_pFile->isOpen())
+ c->warning(__tr("File is not open !"));
+
+ if(m_pFile->putch(*val) < 0)
+ c->warning(__tr("Write error occured !")); // c->error ?
+
+ KviStr::freeBuffer(val);
+
+ return c->leaveStackFrame();
+}
+
+bool KviScriptFileObject::functionHexRead(KviCommand * c, KviParameterList * p,
+ KviStr & b)
+{
+ if(!m_pFile->isOpen())
+ c->warning(__tr("File is not open !"));
+
+ char ch = m_pFile->getch();
+
+ KviStr tmp;
+ tmp.bufferToHex(&ch, 1);
+ b.append(tmp);
+
+ return true;
+}
+
+*/
+#include "m_class_file.moc"
diff --git a/src/modules/objects/class_file.h b/src/modules/objects/class_file.h
new file mode 100644
index 00000000..01a54d19
--- /dev/null
+++ b/src/modules/objects/class_file.h
@@ -0,0 +1,113 @@
+#ifndef _CLASS_FILE_H_
+#define _CLASS_FILE_H_
+//vim: ts=8
+// File : class_file.h
+// Creation date : Thu Sep 21 04:43:01 CEST 2000 by Krzysztof Godlewski
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+
+#include <qfile.h>
+#include <qtextstream.h>
+#include "kvi_string.h"
+
+
+/*
+//class KviCommand;
+class KviParameterList;
+
+class KviScriptFileObject : public KviScriptObject
+{
+ Q_OBJECT
+public:
+ KviScriptFileObject(KviScriptObjectClass *, KviScriptObject *, const char *);
+ virtual ~KviScriptFileObject();
+
+ static void registerSelf();
+ static void unregisterSelf();
+
+protected:
+ bool functionSetName(KviCommand *, KviParameterList *, KviStr &);
+ bool functionName(KviCommand *, KviParameterList *, KviStr &);
+ bool functionOpen(KviCommand *, KviParameterList *, KviStr &);
+ bool functionIsOpen(KviCommand *, KviParameterList *, KviStr &);
+ bool functionClose(KviCommand *, KviParameterList *, KviStr &);
+ bool functionFlush(KviCommand *, KviParameterList *, KviStr &);
+ bool functionSize(KviCommand *, KviParameterList *, KviStr &);
+
+ bool functionAtEnd(KviCommand *, KviParameterList *, KviStr &);
+ // int QFile at() const
+ bool functionWhere(KviCommand *, KviParameterList *, KviStr &);
+ // void QFile at(int)
+ bool functionSeek(KviCommand *, KviParameterList *, KviStr &);
+ bool functionPutch(KviCommand *, KviParameterList *, KviStr &);
+ bool functionGetch(KviCommand *, KviParameterList *, KviStr &);
+ bool functionUngetch(KviCommand *, KviParameterList *, KviStr &);
+
+ bool functionReadBlock(KviCommand *, KviParameterList *, KviStr &);
+ bool functionWriteBlock(KviCommand *, KviParameterList *, KviStr &);
+
+ bool functionReadLine(KviCommand *, KviParameterList *, KviStr &);
+ bool functionWriteLine(KviCommand *, KviParameterList *, KviStr &);
+ bool functionHexWrite(KviCommand *, KviParameterList *, KviStr &);
+ bool functionHexRead(KviCommand *, KviParameterList *, KviStr &);
+
+protected:
+ QFile * m_pFile;
+};
+
+*/
+
+#include "object_macros.h"
+
+class KviKvsObject_file : public KviKvsObject
+{
+public:
+ KVSO_DECLARE_OBJECT(KviKvsObject_file)
+protected:
+ bool functionsetName(KviKvsObjectFunctionCall *c);
+ bool functionname(KviKvsObjectFunctionCall *c);
+ bool functionopen(KviKvsObjectFunctionCall *c);
+ bool functionisOpen(KviKvsObjectFunctionCall *c);
+ bool functionclose(KviKvsObjectFunctionCall *c);
+ bool functionflush(KviKvsObjectFunctionCall *c);
+ bool functionsize(KviKvsObjectFunctionCall *c);
+
+ bool functionatEnd(KviKvsObjectFunctionCall *c);
+ // int QFile at() const
+ bool functionwhere(KviKvsObjectFunctionCall *c);
+ // void QFile at(int)
+ bool functionseek(KviKvsObjectFunctionCall *c);
+ bool functionputch(KviKvsObjectFunctionCall *c);
+ bool functiongetch(KviKvsObjectFunctionCall *c);
+ bool functionunGetch(KviKvsObjectFunctionCall *c);
+
+ bool functionreadBlock(KviKvsObjectFunctionCall *c);
+ bool functionwriteBlock(KviKvsObjectFunctionCall *c);
+
+ bool functionreadLine(KviKvsObjectFunctionCall *c);
+ bool functionwriteLine(KviKvsObjectFunctionCall *c);
+/* bool functionHexWrite(KviKvsObjectFunctionCall *c);
+ bool functionHexRead(KviKvsObjectFunctionCall *c);
+*/
+protected:
+ QFile * m_pFile;
+};
+#endif // !_CLASS_FILE_H_
diff --git a/src/modules/objects/class_groupbox.cpp b/src/modules/objects/class_groupbox.cpp
new file mode 100644
index 00000000..14e640d1
--- /dev/null
+++ b/src/modules/objects/class_groupbox.cpp
@@ -0,0 +1,376 @@
+//
+// File : class_groupbox.cpp
+// Creation date : Fri Jan 28 14:21:48 CEST 2005
+// by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include <kvi_tal_groupbox.h>
+#include "class_groupbox.h"
+#include "kvi_error.h"
+#include "kvi_debug.h"
+
+#include "kvi_locale.h"
+#include "kvi_iconmanager.h"
+
+// Tables used in $setAlignment , $alignment and in $setOrientation & $orientation
+
+const char * const align_tbl[] = {
+ "Left",
+ "Right",
+ "HCenter"
+ };
+const int align_cod[] = {
+ Qt::AlignLeft,
+ Qt::AlignRight,
+ Qt::AlignHCenter
+ };
+#define align_num (sizeof(align_tbl) / sizeof(align_tbl[0]))
+
+
+/*
+ @doc: groupbox
+ @keyterms:
+ groupbox object class,
+ @title:
+ groupbox class
+ @type:
+ class
+ @short:
+ Provides a groupbox bar.
+ @inherits:
+ [class]object[/class]
+ [class]widget[/class]
+ @description:
+ This widget can be used to display a groupbox.
+ It will be usually a parent for other child controls.
+ You can either use a child layout to manage the children geometries
+ or use $setColumnLayout to manage the layout automatically.
+ @functions:
+ !fn: $setTitle(<text:String>)
+ Sets the group box title to <text>.
+ !fn: <string> $title()
+ Returns the group box title text.
+ !fn: $setFlat(<bflag:boolean>)
+ Sets whether the group box is painted flat. Valid Values are 1 or 0.
+ !fn: <boolean> $isFlat()
+ Returns 1 (TRUE) if the group box is painted flat; otherwise returns 0 (FALSE).
+ !fn: <boolean> $isCheckable()
+ Returns 1 (TRUE) if the group box has a checkbox in its title; otherwise returns 0 (FALSE).
+ !fn: $setCheckable(<bflag:boolean>)
+ Sets whether the group box has a checkbox in its title: Valid values are 1 or 0.
+ !fn: $setInsideMargin(<margin:uint>)
+ Sets the the width of the inside margin to m pixels.
+ !fn: <integer> $insideMargin()
+ Returns the width of the empty space between the items in the group and margin of groupbox.
+ !fn: $setInsideSpacing(<spacing:uint>)
+ Sets the width of the empty space between each of the items in the group to m pixels.
+ !fn: <integer> $insideSpacing()
+ Returns the width of the empty space between each of the items in the group.
+ !fn: $setColumns(<columns:uint>)
+ Sets the number of columns or rows (depending of the orientation) in the group box.
+ !fn: <integer> $columns()
+ Returns the number of columns or rows in the groupbox.
+ !fn: $addSpace()
+ Adds an empty cell at the next free position.
+ !fn: <string> $alignment()
+ Returns the alignment of the group box title.
+ !fn: $setAlignment(<alignment:string>)
+ Set the alignment of the groupbox; Valid values are Left,Right,HCenter.
+ !fn: $setOrientation<orientation:string>
+ Sets the group box's orientation. Valid values are: Horizontal, Vertical.
+ !fn: $setColumnLayout(<columns:integer>,<orientation:string>)
+ Enables the automatic layout management. The children are arranged in n columns with the specified orientation.[br]
+ Valid values for <orientation> are: Horizontal, Vertical.
+ @examples:
+ [example]
+ |-Start:[br]
+ #Let's start.[br]
+ #first we'll create the main widget.[br]
+ %widget=$new(widget)[br]
+ [br]
+ #then the groupbox [br]
+ %gb=$new(groupbox,%widget)[br]
+ %gb->$setTitle(Login)[br]
+ %gb->$setAlignment("Left")[br]
+ [br]
+ #now we create the labels and lineedits.[br]
+ %labeluser=$new(label,%gb)[br]
+ %labeluser->$settext(User: )[br]
+ %labelpass=$new(label,%gb)[br]
+ %labelpass->$settext(Pass: )[br]
+ %inputuser=$new(lineedit,%gb)[br]
+ %inputpass=$new(lineedit,%gb)[br]
+ %inputpass->$setechomode("password")[br]
+ [br]
+ #now lets' layouting the groupbox's element's.[br]
+ %layoutgb=$new(layout,%gb)[br]
+ %layoutgb->$setmargin(20)[br]
+ %layoutgb->$addwidget(%labeluser,0,0)[br]
+ %layoutgb->$addwidget(%labelpass,1,0)[br]
+ %layoutgb->$addwidget(%inputuser,0,1)[br]
+ %layoutgb->$addwidget(%inputpass,1,1)[br]
+ [br]
+ # now we create a fake widget and managing the two buttons layout.[br]
+ %fakewidget=$new(widget,%widget)[br]
+ %layoutbtn=$new(layout,%fakewidget)[br]
+ %btnok=$new(button,%fakewidget)[br]
+ %btnok->$settext("OK")[br]
+ %btncancel=$new(button,%fakewidget)[br]
+ %btncancel->$settext("Cancel")[br]
+ %layoutbtn->$addwidget(%btnok,0,0)[br]
+ %layoutbtn->$addwidget(%btncancel,0,1)[br]
+ [br]
+ #And finally we create a main layout with the groupbox (and its "children")[br]
+ #and fakewiget (with its buttons children).
+ %mainlayout=$new(layout,%widget)[br]
+ %mainlayout->$setspacing(10)[br]
+ %mainlayout->$setmargin(10)[br]
+ %mainlayout->$addwidget(%gb,0,0)[br]
+ %mainlayout->$addwidget(%fakewidget,1,0)[br]
+ [br]
+ #Let's show our nice login request =D ! [br]
+ %widget->$show()[br]
+ [/example]
+
+*/
+
+KVSO_BEGIN_REGISTERCLASS(KviKvsObject_groupbox,"groupbox","widget")
+ KVSO_REGISTER_HANDLER(KviKvsObject_groupbox,"setTitle", functionSetTitle)
+ KVSO_REGISTER_HANDLER(KviKvsObject_groupbox,"title", functionTitle)
+ KVSO_REGISTER_HANDLER(KviKvsObject_groupbox,"setFlat", functionSetFlat)
+ KVSO_REGISTER_HANDLER(KviKvsObject_groupbox,"isFlat", functionIsFlat)
+ KVSO_REGISTER_HANDLER(KviKvsObject_groupbox,"setCheckable", functionSetCheckable)
+ KVSO_REGISTER_HANDLER(KviKvsObject_groupbox,"isCheckable", functionIsCheckable)
+ KVSO_REGISTER_HANDLER(KviKvsObject_groupbox,"setInsideMargin", functionSetInsideMargin)
+ KVSO_REGISTER_HANDLER(KviKvsObject_groupbox,"insideMargin", functionInsideMargin)
+ KVSO_REGISTER_HANDLER(KviKvsObject_groupbox,"setInsideSpacing", functionSetInsideSpacing)
+ KVSO_REGISTER_HANDLER(KviKvsObject_groupbox,"insideSpacing", functionInsideSpacing)
+ KVSO_REGISTER_HANDLER(KviKvsObject_groupbox,"setColumns", functionSetColumns)
+ KVSO_REGISTER_HANDLER(KviKvsObject_groupbox,"columns", functionColumns)
+ KVSO_REGISTER_HANDLER(KviKvsObject_groupbox,"addSpace", functionAddSpace)
+ KVSO_REGISTER_HANDLER(KviKvsObject_groupbox,"alignment", functionAlignment)
+ KVSO_REGISTER_HANDLER(KviKvsObject_groupbox,"setAlignment", functionSetAlignment)
+ KVSO_REGISTER_HANDLER(KviKvsObject_groupbox,"setOrientation", functionSetOrientation)
+ KVSO_REGISTER_HANDLER(KviKvsObject_groupbox,"isChecked", functionIsChecked)
+ KVSO_REGISTER_HANDLER(KviKvsObject_groupbox,"setChecked", functionSetChecked)
+ KVSO_REGISTER_HANDLER(KviKvsObject_groupbox,"setColumnLayout",functionSetColumnLayout)
+KVSO_END_REGISTERCLASS(KviKvsObject_groupbox)
+
+KVSO_BEGIN_CONSTRUCTOR(KviKvsObject_groupbox,KviKvsObject_widget)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_groupbox)
+
+
+KVSO_BEGIN_DESTRUCTOR(KviKvsObject_groupbox)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_groupbox)
+
+bool KviKvsObject_groupbox::init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams)
+{
+#ifdef COMPILE_USE_QT4
+ KviTalGroupBox *groupbox=new KviTalGroupBox(name(),parentScriptWidget());
+ groupbox->setObjectName(name());
+ setObject(groupbox,true);
+#else
+ setObject(new KviTalGroupBox(name(),parentScriptWidget()), true);
+#endif
+ return true;
+}
+
+bool KviKvsObject_groupbox::functionSetTitle(KviKvsObjectFunctionCall *c)
+{
+ QString szTitle;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("title",KVS_PT_STRING,0,szTitle)
+ KVSO_PARAMETERS_END(c)
+ if (widget())
+ ((KviTalGroupBox *)widget())->setTitle(szTitle);
+ return true;
+}
+bool KviKvsObject_groupbox::functionTitle(KviKvsObjectFunctionCall *c)
+{
+ if (widget()) c->returnValue()->setString(((KviTalGroupBox *)widget())->title());
+ return true;
+}
+bool KviKvsObject_groupbox::functionSetFlat(KviKvsObjectFunctionCall *c)
+{
+ bool bEnabled;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bFlag",KVS_PT_BOOL,0,bEnabled)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ ((KviTalGroupBox *)widget())->setFlat(bEnabled);
+ return true;
+}
+bool KviKvsObject_groupbox::functionIsFlat(KviKvsObjectFunctionCall *c)
+{
+ if (widget()) c->returnValue()->setBoolean(((KviTalGroupBox *)widget())->isFlat());
+ return true;
+}
+bool KviKvsObject_groupbox::functionSetCheckable(KviKvsObjectFunctionCall *c)
+{
+ bool bEnabled;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bFlag",KVS_PT_BOOL,0,bEnabled)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ ((KviTalGroupBox *)widget())->setCheckable(bEnabled);
+ return true;
+}
+bool KviKvsObject_groupbox::functionIsCheckable(KviKvsObjectFunctionCall *c)
+{
+ if (widget()) c->returnValue()->setBoolean(((KviTalGroupBox *)widget())->isCheckable());
+ return true;
+}
+bool KviKvsObject_groupbox::functionSetChecked(KviKvsObjectFunctionCall *c)
+{
+ bool bEnabled;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bFlag",KVS_PT_BOOL,0,bEnabled)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ ((KviTalGroupBox *)widget())->setChecked(bEnabled);
+ return true;
+}
+bool KviKvsObject_groupbox::functionIsChecked(KviKvsObjectFunctionCall *c)
+{
+ if (widget()) c->returnValue()->setBoolean(((KviTalGroupBox *)widget())->isChecked());
+ return true;
+}
+bool KviKvsObject_groupbox::functionSetInsideMargin(KviKvsObjectFunctionCall *c)
+{
+ kvs_uint_t uMargin;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("margin",KVS_PT_UNSIGNEDINTEGER,0,uMargin)
+ KVSO_PARAMETERS_END(c)
+ if (widget()) ((KviTalGroupBox *)widget())->setInsideMargin(uMargin);
+ return true;
+}
+bool KviKvsObject_groupbox::functionInsideMargin(KviKvsObjectFunctionCall *c)
+{
+ if (widget()) c->returnValue()->setInteger(((KviTalGroupBox *)widget())->insideMargin());
+ return true;
+}
+bool KviKvsObject_groupbox::functionSetInsideSpacing(KviKvsObjectFunctionCall *c)
+{
+ kvs_uint_t uSpacing;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("spacing",KVS_PT_UNSIGNEDINTEGER,0,uSpacing)
+ KVSO_PARAMETERS_END(c)
+ if (widget()) ((KviTalGroupBox *)widget())->setInsideSpacing(uSpacing);
+ return true;
+}
+bool KviKvsObject_groupbox::functionInsideSpacing(KviKvsObjectFunctionCall *c)
+{
+ if (widget()) c->returnValue()->setInteger(((KviTalGroupBox *)widget())->insideSpacing());
+ return true;
+}
+bool KviKvsObject_groupbox::functionSetColumns(KviKvsObjectFunctionCall *c)
+{
+ kvs_uint_t uColums;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("colums",KVS_PT_UNSIGNEDINTEGER,0,uColums)
+ KVSO_PARAMETERS_END(c)
+ if (widget()) ((KviTalGroupBox *)widget())->setColumns(uColums);
+ return true;
+}
+bool KviKvsObject_groupbox::functionColumns(KviKvsObjectFunctionCall *c)
+{
+ if (widget()) c->returnValue()->setInteger(((KviTalGroupBox *)widget())->columns());
+ return true;
+}
+bool KviKvsObject_groupbox::functionAddSpace(KviKvsObjectFunctionCall *c)
+{
+ kvs_uint_t iSpace;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("colums",KVS_PT_UNSIGNEDINTEGER,0,iSpace)
+ KVSO_PARAMETERS_END(c)
+ if (widget()) (((KviTalGroupBox *)widget())->addSpace(iSpace));
+ return true;
+}
+
+bool KviKvsObject_groupbox::functionSetAlignment(KviKvsObjectFunctionCall *c)
+{
+ QString szAlign;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("alignment",KVS_PT_STRING,0,szAlign)
+ KVSO_PARAMETERS_END(c)
+ if (!widget()) return true;
+ for(unsigned int i = 0; i < align_num; i++)
+ {
+ if(KviQString::equalCI(szAlign, align_tbl[i]))
+ {
+ ((KviTalGroupBox *)widget())->setAlignment(align_cod[i]);
+ return true;
+ }
+ }
+ c->warning(__tr2qs("Unknown alignment"));
+ return true;
+}
+bool KviKvsObject_groupbox::functionAlignment(KviKvsObjectFunctionCall *c)
+{
+ int mode = ((KviTalGroupBox *)widget())->alignment();
+ QString szAlignment="";
+ for(unsigned int i = 0; i < align_num; i++)
+ {
+ if(mode == align_cod[i])
+ {
+ szAlignment=align_tbl[i];
+ break;
+ }
+ }
+ c->returnValue()->setString(szAlignment);
+ return true;
+}
+
+bool KviKvsObject_groupbox::functionSetOrientation(KviKvsObjectFunctionCall *c)
+{
+ QString szMode;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("orientation",KVS_PT_STRING,0,szMode)
+ KVSO_PARAMETERS_END(c)
+ if(!widget())return true;
+ if(KviQString::equalCI(szMode, "Horizontal"))
+ ((KviTalGroupBox *)widget())->setOrientation(Qt::Horizontal);
+ else
+ if(KviQString::equalCI(szMode, "Vertical"))
+ ((KviTalGroupBox *)widget())->setOrientation(Qt::Vertical);
+ else c->warning( __tr2qs("Unknown orientation: "));
+ return true;
+}
+
+bool KviKvsObject_groupbox::functionSetColumnLayout(KviKvsObjectFunctionCall *c)
+{
+ QString szMode;
+ kvs_uint_t uCol;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("columns",KVS_PT_UNSIGNEDINTEGER,0,uCol)
+ KVSO_PARAMETER("orientation",KVS_PT_STRING,0,szMode)
+ KVSO_PARAMETERS_END(c)
+ if(!widget())return true;
+ if(szMode=="Horizontal")
+ ((KviTalGroupBox *)widget())->setColumnLayout(uCol,Qt::Horizontal);
+ else
+ if(szMode=="Vertical")
+ ((KviTalGroupBox *)widget())->setColumnLayout(uCol,Qt::Vertical);
+ else c->warning( __tr2qs("Unknown orientation: "));
+ return true;
+}
+
diff --git a/src/modules/objects/class_groupbox.h b/src/modules/objects/class_groupbox.h
new file mode 100644
index 00000000..c63bb46b
--- /dev/null
+++ b/src/modules/objects/class_groupbox.h
@@ -0,0 +1,64 @@
+#ifndef _CLASS_GROUPBOX_H_
+#define _CLASS_GROUPBOX_H_
+//
+// File : class_groupbox.h
+// Creation date : Fri Jan 28 14:21:48 CEST 2005
+// by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+
+#include <kvi_tal_groupbox.h>
+#include "class_widget.h"
+#include "object_macros.h"
+
+class KviKvsObject_groupbox : public KviKvsObject_widget
+{
+public:
+ KVSO_DECLARE_OBJECT(KviKvsObject_groupbox)
+public:
+ QWidget * widget() { return (QWidget *)object(); };
+protected:
+ virtual bool init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams);
+
+
+ bool functionSetTitle(KviKvsObjectFunctionCall *c);
+ bool functionTitle(KviKvsObjectFunctionCall *c);
+ bool functionSetFlat(KviKvsObjectFunctionCall *c);
+ bool functionIsFlat(KviKvsObjectFunctionCall *c);
+ bool functionSetCheckable(KviKvsObjectFunctionCall *c);
+ bool functionIsCheckable(KviKvsObjectFunctionCall *c);
+ bool functionSetInsideMargin(KviKvsObjectFunctionCall *c);
+ bool functionInsideMargin(KviKvsObjectFunctionCall *c);
+ bool functionSetInsideSpacing(KviKvsObjectFunctionCall *c);
+ bool functionInsideSpacing(KviKvsObjectFunctionCall *c);
+ bool functionSetColumns(KviKvsObjectFunctionCall *c);
+ bool functionColumns(KviKvsObjectFunctionCall *c);
+ bool functionAddSpace(KviKvsObjectFunctionCall *c);
+ bool functionAlignment(KviKvsObjectFunctionCall *c);
+ bool functionSetAlignment(KviKvsObjectFunctionCall *c);
+ bool functionSetOrientation(KviKvsObjectFunctionCall *c);
+ bool functionIsChecked(KviKvsObjectFunctionCall *c);
+ bool functionSetChecked(KviKvsObjectFunctionCall *c);
+ bool functionSetColumnLayout(KviKvsObjectFunctionCall *c);
+
+};
+#endif //!_CLASS_GROUPBOX_H_
+
diff --git a/src/modules/objects/class_hbox.cpp b/src/modules/objects/class_hbox.cpp
new file mode 100644
index 00000000..48174312
--- /dev/null
+++ b/src/modules/objects/class_hbox.cpp
@@ -0,0 +1,128 @@
+//
+// File : class_hbox.cpp
+// Creation date : Wed Mar 01 2005 23:00:01 by Alessandro Carbone & Tonino Imbesi
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002-2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+#define _KVI_DEBUG_CHECK_RANGE_
+#include "kvi_debug.h"
+
+#include "kvi_locale.h"
+
+#include "class_hbox.h"
+
+/*
+ @doc: hbox
+ @keyterms:
+ hbox object class, child widgets
+ @title:
+ hbox class
+ @type:
+ class
+ @short:
+ Manages child widget horizontal geometry
+ @inherits:
+ [class]object[/class]
+ @description:
+ The hbox class widget provides horizontal geometry management for its child widgets.
+ @functions:
+ !fn: $setSpacing(<spacing:uint>)
+ Sets the default spacing of the widgets in pixels
+ !fn: $setMargin(<margin:uint>)
+ Sets the dimension of the layout margin : the distance from the border to the outermost child widget edges.
+ !fn: $setStretchFactor(<widget:hobject>,<stretch:uint>)
+ Sets the stretch factor of widget to stretch.
+*/
+
+
+KVSO_BEGIN_REGISTERCLASS(KviKvsObject_hbox,"hbox","widget")
+ KVSO_REGISTER_HANDLER(KviKvsObject_hbox,"setMargin", functionsetMargin)
+ KVSO_REGISTER_HANDLER(KviKvsObject_hbox,"setSpacing", functionsetSpacing)
+ KVSO_REGISTER_HANDLER(KviKvsObject_hbox,"setStretchFactor", functionsetStretchFactor )
+KVSO_END_REGISTERCLASS(KviKvsObject_hbox)
+
+KVSO_BEGIN_CONSTRUCTOR(KviKvsObject_hbox,KviKvsObject_widget)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_hbox)
+
+
+KVSO_BEGIN_DESTRUCTOR(KviKvsObject_hbox)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_hbox)
+
+bool KviKvsObject_hbox::init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams)
+{
+
+ setObject(new KviTalHBox(parentScriptWidget()), true);
+ return true;
+}
+bool KviKvsObject_hbox::functionsetMargin(KviKvsObjectFunctionCall *c)
+{
+ kvs_uint_t uMargin;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("margin",KVS_PT_UNSIGNEDINTEGER,0,uMargin)
+ KVSO_PARAMETERS_END(c)
+ if (widget()) ((KviTalHBox *)widget())->setMargin(uMargin);
+ return true;
+}
+
+bool KviKvsObject_hbox::functionsetSpacing(KviKvsObjectFunctionCall *c)
+{
+ kvs_uint_t uSpacing;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("spacing",KVS_PT_UNSIGNEDINTEGER,0,uSpacing)
+ KVSO_PARAMETERS_END(c)
+ if (widget()) ((KviTalHBox *)widget())->setSpacing(uSpacing);
+ return true;
+}
+bool KviKvsObject_hbox::functionsetStretchFactor(KviKvsObjectFunctionCall *c)
+{
+ KviKvsObject * pObject;
+ kvs_hobject_t hObject;
+ kvs_uint_t uStretch;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("widget",KVS_PT_HOBJECT,0,hObject)
+ KVSO_PARAMETER("stretch",KVS_PT_UNSIGNEDINTEGER,0,uStretch)
+ KVSO_PARAMETERS_END(c)
+ pObject=KviKvsKernel::instance()->objectController()->lookupObject(hObject);
+ if(!widget())return true;
+ if (!pObject)
+ {
+ c->warning(__tr2qs("Widget parameter is not an object"));
+ return true;
+ }
+ if (!pObject->object())
+ {
+ c->warning(__tr2qs("Widget parameter is not a valid object"));
+ return true;
+ }
+ if(!pObject->object()->isWidgetType())
+ {
+ c->warning(__tr2qs("Can't add a non-widget object"));
+ return true;
+ }
+ if(((KviKvsObject_widget *)pObject)->widget()->parentWidget() != widget())
+ {
+ c->warning(__tr2qs("The widget must be a child of this hbox"));
+ return true;
+ }
+ ((KviTalHBox *)widget())->setStretchFactor(((QWidget *)(pObject->object())),uStretch);
+ return true;
+}
+
+
diff --git a/src/modules/objects/class_hbox.h b/src/modules/objects/class_hbox.h
new file mode 100644
index 00000000..c0489f28
--- /dev/null
+++ b/src/modules/objects/class_hbox.h
@@ -0,0 +1,47 @@
+#ifndef _CLASS_HBOX_H_
+#define _CLASS_HBOX_H_
+//
+// File : class_hbox.h
+// Creation date : Wed Mar 01 2005 23:00:01 by Alessandro Carbone & Tonino Imbesi
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002-2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+#include "kvi_string.h"
+
+#include "kvi_tal_hbox.h"
+#include "object_macros.h"
+#include "class_widget.h"
+
+class KviKvsObject_hbox : public KviKvsObject_widget
+{
+public:
+ KVSO_DECLARE_OBJECT(KviKvsObject_hbox)
+public:
+ QWidget * widget() { return (QWidget *)object(); };
+protected:
+ virtual bool init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams);
+
+ bool functionsetMargin(KviKvsObjectFunctionCall *c);
+ bool functionsetSpacing(KviKvsObjectFunctionCall *c);
+ bool functionsetStretchFactor(KviKvsObjectFunctionCall *c);
+
+
+};
+
+
+#endif //_CLASS_HBOX_H_
diff --git a/src/modules/objects/class_label.cpp b/src/modules/objects/class_label.cpp
new file mode 100644
index 00000000..9c629818
--- /dev/null
+++ b/src/modules/objects/class_label.cpp
@@ -0,0 +1,409 @@
+//vim: ts=8
+// File : class_label.cpp
+// Creation date : Mon Sep 18 14:21:48 CEST 2000 by Krzysztof Godlewski
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Krzysztof Godlewski
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include <qfont.h>
+#include <qpixmap.h>
+#include <qmessagebox.h>
+#include "class_label.h"
+//#include "kvi_fileutils.h"
+#include "kvi_error.h"
+#include "kvi_debug.h"
+
+#include "kvi_locale.h"
+#include "kvi_iconmanager.h"
+
+
+
+// Tables used in $setAlignment & $alignment
+const char * const align_tbl[] = {
+ "Left",
+ "Right",
+ "HCenter",
+ "VCenter",
+ "Center",
+ "Top",
+ "Bottom",
+ "WordBreak"
+ };
+#ifdef COMPILE_USE_QT4
+ #define QT_LABEL_ALIGNLEFT Qt::AlignLeft
+ #define QT_LABEL_ALIGNRIGHT Qt::AlignRight
+ #define QT_LABEL_ALIGNHCENTER Qt::AlignHCenter
+ #define QT_LABEL_ALIGNVCENTER Qt::AlignVCenter
+ #define QT_LABEL_ALIGNCENTER Qt::AlignCenter
+ #define QT_LABEL_ALIGNTOP Qt::AlignTop
+ #define QT_LABEL_ALIGNBOTTOM Qt::AlignBottom
+ #define QT_LABEL_JUSTIFY Qt::AlignJustify
+#else
+ #define QT_LABEL_ALIGNLEFT QLabel::AlignLeft
+ #define QT_LABEL_ALIGNRIGHT QLabel::AlignRight
+ #define QT_LABEL_ALIGNHCENTER QLabel::AlignHCenter
+ #define QT_LABEL_ALIGNVCENTER QLabel::AlignVCenter
+ #define QT_LABEL_ALIGNCENTER QLabel::AlignCenter
+ #define QT_LABEL_ALIGNTOP QLabel::AlignTop
+ #define QT_LABEL_ALIGNBOTTOM QLabel::AlignBottom
+ #define QT_LABEL_JUSTIFY QLabel::WordBreak
+#endif
+
+const int align_cod[] = {
+ QT_LABEL_ALIGNLEFT,
+ QT_LABEL_ALIGNRIGHT,
+ QT_LABEL_ALIGNHCENTER,
+ QT_LABEL_ALIGNVCENTER,
+ QT_LABEL_ALIGNCENTER,
+ QT_LABEL_ALIGNTOP,
+ QT_LABEL_ALIGNBOTTOM,
+ QT_LABEL_JUSTIFY,
+ };
+
+#define align_num (sizeof(align_tbl) / sizeof(align_tbl[0]))
+
+// used in $frameStyle & $setFrameStyle
+const char * const frame_tbl[] = {
+ "NoFrame",
+ "Box",
+ "Panel",
+ "WinPanel",
+ "Hline",
+ // shadow styles
+ "Plain",
+ "Raised",
+ "Sunken"
+ };
+
+const int frame_cod[] = {
+ QFrame::NoFrame,
+ QFrame::Box,
+ QFrame::Panel,
+ QFrame::WinPanel,
+ QFrame::HLine,
+ QFrame::Plain,
+ QFrame::Raised,
+ QFrame::Sunken
+ };
+
+#define frame_num (sizeof(frame_tbl) / sizeof(frame_tbl[0]))
+
+
+/*
+ @doc: label
+ @keyterms:
+ label object class, show image
+ @title:
+ label class
+ @type:
+ class
+ @short:
+ Displays text or an image
+ @inherits:
+ [class]object[/class]
+ [class]widget[/class]
+ @description:
+ This widget can be used to display a text or an image. It can
+ have different frame styles and text/image alignment.
+ @functions:
+ !fn: $setText(<text:string>)
+ Sets the text to be displayed by the label.
+ The text can contain limited html tags.
+ See also [classfnc]$text[/classfnc]().
+ !fn: <string> $text()
+ Returns the text currently displayed by the label.
+ See also [classfnc]$setText[/classfnc]().
+ !fn: <integer> $margin()
+ Returns current value of margin for this label (default is 0).
+ See also [classfnc]$setMargin[/classfnc]().
+ !fn: $setMargin(<margin:uint>)
+ Sets margin width / height to <margin>.
+ See also [classfnc]$margin[/classfnc]().
+ !fn: <boolean> $autoResize()
+ Returns 1, if auto-resize ability of the label is enabled.
+ See also [classfnc]$setAutoResize[/classfnc]().
+ !fn: $setAutoResize(<benabled:boolean>)
+ Sets auto-resize ability to enabled (if <benabled> is 1) or disabled
+ (if <benabled> is 0). If auto-resize is enabled, the label will
+ automagically resize itself accordingly to the 'size' of the
+ text it contains.
+ See also [classfnc]$autoResize[/classfnc]().
+ !fn: <string> $alignment()
+ Returns a string containing alignment flags that are set for
+ this label. The flags are separated by commas. An example output
+ could look like this:[br]
+ [pre]Bottom, Right[/pre][br]
+ See [classfnc]$setAlignment[/classfnc]() for explanation of all
+ alignment flags.
+ !fn: $setAlignment(<flag1:string>, <flag2:string>, ...)
+ This function sets alignment flags, given as parameters, for
+ this label. Valid flags are:
+ [pre]
+ Right - Text is aligned to right border[br]
+ Left - Text is aligned to left border[br]
+ Top - Text is aligned to the top border[br]
+ Bottom - Text is aligned to the bottom border[br]
+ HCenter - Text is horizontally centered[br]
+ VCenter - Text is vertically centered[br]
+ Center - Equals HCenter + VCenter[br]
+ WordBreak - Enables automatic word breaking[br]
+ [/pre]
+ It is obvious that you can not set for example [i]Right[/i]
+ and [i]Left[/i] simoultaneously - this will [b]NOT[/b]
+ result in an error message - this will simply not work :)
+ !fn: $clear()
+ Clears the label. Equal to calling
+ [classfnc]$setText[/classfnc]("")
+ !fn: $frameStyle()
+ Returns a string containing this label's frame-style flags,
+ separated with commas. Output from this function could look like
+ this:
+ [pre]Panel, Raised[/pre]
+ See [classfnc]$setFrameStyle[/classfnc]() for a list of all
+ frame-style flags and their explenation.
+ !fn: $setFrameStyle(<flag1>, <flag2>, ...)
+ Sets the frame-style flags to the ones passed as arguments.
+ The flags can either decide of the shape or shadow of the
+ label's frame. Valid shape flags are:[br]
+ [pre]
+ NoFrame - draw no frame. You shouldn't specify a shadow when
+ using this.[br]
+ Box - draws a rectangular box. Its borders can be
+ [i]Raised[/i] or [i]Sunken[/i][br]
+ Panel - draws a rectangular panel which can be
+ [i]Raised[/i] or [i]Sunken[/i][br]
+ WinPanel - similar to [i]Panel[/i], but is more in Win95
+ style[br]
+ Hline - draws a horizontal line that frames nothing (useful as separator)
+ [/pre]
+ Valid shadow flags are:[br]
+ [pre]
+ Plain - no 3D effect (draws using foreground color)[br]
+ Raised - makes the label look like it was raised above the
+ parent widget[br]
+ Sunken - makes the label look like it was "pushed" inside
+ the parent widget[br]
+ [/pre]
+ !fn: $setImage(<image_id>)
+ Sets the image to be displayed on this label.
+ Giving empty argument clears the pixmap[br]
+ See the [doc:image_id]image identifier[/doc] documentation for
+ the explaination of the <image_id> parameter.
+
+*/
+
+
+KVSO_BEGIN_REGISTERCLASS(KviKvsObject_label,"label","widget")
+ KVSO_REGISTER_HANDLER(KviKvsObject_label,"setText",functionSetText)
+ KVSO_REGISTER_HANDLER(KviKvsObject_label,"text", functionText)
+ KVSO_REGISTER_HANDLER(KviKvsObject_label,"margin", functionMargin)
+ KVSO_REGISTER_HANDLER(KviKvsObject_label,"setMargin", functionSetMargin)
+ KVSO_REGISTER_HANDLER(KviKvsObject_label,"autoResize", functionAutoResize)
+ KVSO_REGISTER_HANDLER(KviKvsObject_label,"setAutoResize", functionSetAutoResize)
+ KVSO_REGISTER_HANDLER(KviKvsObject_label,"alignment", functionAlignment)
+ KVSO_REGISTER_HANDLER(KviKvsObject_label,"setAlignment", functionSetAlignment)
+ KVSO_REGISTER_HANDLER(KviKvsObject_label,"clear", functionClear)
+ KVSO_REGISTER_HANDLER(KviKvsObject_label,"frameStyle", functionFrameStyle)
+ KVSO_REGISTER_HANDLER(KviKvsObject_label,"setFrameStyle", functionSetFrameStyle)
+ KVSO_REGISTER_HANDLER(KviKvsObject_label,"setImage", functionSetImage)
+KVSO_END_REGISTERCLASS(KviKvsObject_label)
+
+KVSO_BEGIN_CONSTRUCTOR(KviKvsObject_label,KviKvsObject_widget)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_label)
+
+
+KVSO_BEGIN_DESTRUCTOR(KviKvsObject_label)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_label)
+
+bool KviKvsObject_label::init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams)
+{
+ setObject(new QLabel(parentScriptWidget(), name()), true);
+ return true;
+}
+
+bool KviKvsObject_label::functionSetText(KviKvsObjectFunctionCall *c)
+{
+ QString szText;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("text",KVS_PT_STRING,0,szText)
+ KVSO_PARAMETERS_END(c)
+ if (widget())
+ ((QLabel *)widget())->setText(szText);
+ return true;
+}
+bool KviKvsObject_label::functionText(KviKvsObjectFunctionCall *c)
+{
+ if (widget()) c->returnValue()->setString(((QLabel *)widget())->text());
+ return true;
+}
+
+bool KviKvsObject_label::functionSetMargin(KviKvsObjectFunctionCall *c)
+{
+ kvs_uint_t iMargin;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("margin",KVS_PT_UNSIGNEDINTEGER,0,iMargin)
+ KVSO_PARAMETERS_END(c)
+ if (widget()) ((QLabel *)widget())->setMargin(iMargin);
+ return true;
+}
+bool KviKvsObject_label::functionMargin(KviKvsObjectFunctionCall *c)
+{
+ if (widget()) c->returnValue()->setInteger(((QLabel *)widget())->margin());
+ return true;
+}
+
+// FIX ME
+bool KviKvsObject_label::functionSetAutoResize(KviKvsObjectFunctionCall *c)
+{
+ bool bEnabled;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bEnabled",KVS_PT_BOOL,0,bEnabled)
+ KVSO_PARAMETERS_END(c)
+ #ifdef COMPILE_USE_QT4
+ return true;
+ #else
+ if(widget())
+ ((QLabel *)widget())->setAutoResize(bEnabled);
+ return true;
+ #endif
+}
+bool KviKvsObject_label::functionAutoResize(KviKvsObjectFunctionCall *c)
+{
+ #ifdef COMPILE_USE_QT4
+ if (widget()) c->returnValue()->setBoolean(true);
+ #else
+ if (widget()) c->returnValue()->setBoolean(((QLabel *)widget())->autoResize());
+ #endif
+ return true;
+}
+//
+bool KviKvsObject_label::functionSetAlignment(KviKvsObjectFunctionCall *c)
+{
+ QStringList alignment;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("alignment",KVS_PT_STRINGLIST,KVS_PF_OPTIONAL,alignment)
+ KVSO_PARAMETERS_END(c)
+ if (!widget()) return true;
+ int align,sum=0;
+ for ( QStringList::Iterator it = alignment.begin(); it != alignment.end(); ++it )
+ {
+
+ align = 0;
+ for(unsigned int j = 0; j < align_num; j++)
+ {
+ if(KviQString::equalCI((*it), align_tbl[j]))
+ {
+ align=align_cod[j];
+ break;
+ }
+ }
+ if(align)
+ sum = sum | align;
+ else
+ c->warning(__tr2qs("Unknown alignment: '%Q'"),&(*it));
+
+ }
+ ((QLabel *)widget())->setAlignment(sum);
+ return true;
+}
+bool KviKvsObject_label::functionAlignment(KviKvsObjectFunctionCall *c)
+{
+ int mode = ((QLabel *)widget())->alignment();
+ QString szAlignment="";
+ for(unsigned int i = 0; i < align_num; i++)
+ {
+ if(mode == align_cod[i])
+ {
+ szAlignment=align_tbl[i];
+ break;
+ }
+ }
+ c->returnValue()->setString(szAlignment);
+ return true;
+}
+bool KviKvsObject_label::functionClear(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ ((QLabel *)widget())->clear();
+ return true;
+}
+
+
+bool KviKvsObject_label::functionSetFrameStyle(KviKvsObjectFunctionCall *c)
+{
+
+ QStringList style;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("style",KVS_PT_STRINGLIST,KVS_PF_OPTIONAL,style)
+ KVSO_PARAMETERS_END(c)
+ if (!widget()) return true;
+ int framestyle,sum=0;
+ for ( QStringList::Iterator it = style.begin(); it != style.end(); ++it )
+ {
+ framestyle = 0;
+ for(unsigned int j = 0; j < align_num; j++)
+ {
+ if(KviQString::equalCI((*it), frame_tbl[j]))
+ {
+ framestyle=frame_cod[j];
+ break;
+ }
+ }
+ if(framestyle)
+ sum = sum | framestyle;
+ else
+ c->warning(__tr2qs("Unknown style: '%Q'"),&(*it));
+
+ }
+ ((QLabel *)widget())->setFrameStyle(sum);
+ return true;
+
+
+
+
+}
+bool KviKvsObject_label::functionFrameStyle(KviKvsObjectFunctionCall *c)
+{
+ int mode = ((QLabel *)widget())->frameStyle();
+ QString szStyle="";
+ for(unsigned int i = 0; i < frame_num; i++)
+ {
+ if(mode == frame_cod[i])
+ {
+ szStyle=frame_tbl[i];
+ break;
+ }
+ }
+ c->returnValue()->setString(szStyle);
+ return true;
+}
+bool KviKvsObject_label::functionSetImage(KviKvsObjectFunctionCall *c)
+{
+
+ QString icon;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("icon",KVS_PT_STRING,0,icon)
+ KVSO_PARAMETERS_END(c)
+ if(!widget())return true;
+ QPixmap * pix = g_pIconManager->getImage(icon);
+ if(pix) ((QLabel *)widget())->setPixmap(*pix);
+ return true;
+}
diff --git a/src/modules/objects/class_label.h b/src/modules/objects/class_label.h
new file mode 100644
index 00000000..38fa58a3
--- /dev/null
+++ b/src/modules/objects/class_label.h
@@ -0,0 +1,54 @@
+#ifndef _CLASS_LABEL_H_
+#define _CLASS_LABEL_H_
+//vim: ts=8
+// File : class_label.h
+// Creation date : Mon Sep 18 14:21:48 CEST 2000 by Krzysztof Godlewski
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+
+#include <qlabel.h>
+#include "class_widget.h"
+#include "object_macros.h"
+
+class KviKvsObject_label : public KviKvsObject_widget
+{
+public:
+ KVSO_DECLARE_OBJECT(KviKvsObject_label)
+public:
+ QWidget * widget() { return (QWidget *)object(); };
+protected:
+ virtual bool init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams);
+
+ bool functionSetTitle(KviKvsObjectFunctionCall *c);
+ bool functionSetText(KviKvsObjectFunctionCall *c);
+ bool functionText(KviKvsObjectFunctionCall *c);
+ bool functionMargin(KviKvsObjectFunctionCall *c);
+ bool functionSetMargin(KviKvsObjectFunctionCall *c);
+ bool functionAutoResize(KviKvsObjectFunctionCall *c);
+ bool functionSetAutoResize(KviKvsObjectFunctionCall *c);
+ bool functionAlignment(KviKvsObjectFunctionCall *c);
+ bool functionSetAlignment(KviKvsObjectFunctionCall *c);
+ bool functionClear(KviKvsObjectFunctionCall *c);
+ bool functionFrameStyle(KviKvsObjectFunctionCall *c);
+ bool functionSetFrameStyle(KviKvsObjectFunctionCall *c);
+ bool functionSetImage(KviKvsObjectFunctionCall *c);
+};
+#endif // !_CLASS_LABEL_H_
diff --git a/src/modules/objects/class_layout.cpp b/src/modules/objects/class_layout.cpp
new file mode 100644
index 00000000..900b9856
--- /dev/null
+++ b/src/modules/objects/class_layout.cpp
@@ -0,0 +1,274 @@
+//
+// File : class_layout.cpp
+// Creation date : Fri Now 22 2002 00:50:01 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+#define _KVI_DEBUG_CHECK_RANGE_
+#include "kvi_debug.h"
+
+#include "kvi_locale.h"
+
+#include "class_layout.h"
+
+#ifdef COMPILE_USE_QT4
+#define QLAYOUT_AUTO_CONSTRAINT QLayout::SetDefaultConstraint
+#define QLAYOUT_FIXED QLayout::SetFixedSize
+#define QLAYOUT_FREE_RESIZE QLayout::SetNoConstraint
+#define QLAYOUT_MINIMUM QLayout::SetMinimumSize
+#else
+#define QLAYOUT_AUTO_CONSTRAINT QLayout::Auto
+#define QLAYOUT_FIXED QLayout::Fixed
+#define QLAYOUT_FREE_RESIZE QLayout::FreeResize
+#define QLAYOUT_MINIMUM QLayout::Minimum
+#endif
+
+
+/*
+ @doc: layout
+ @keyterms:
+ layout object class, child widgets
+ @title:
+ layout class
+ @type:
+ class
+ @short:
+ Manages child widget geometry
+ @inherits:
+ [class]object[/class]
+ @description:
+ The layout is a geometry management tool for child widgets.
+ You create a layout , give it some widgets to manage and it will layout them
+ automatically.[br]
+ The parent of the layout must be the widget for which child widget geometries have to be managed.
+ A layout is a grid of NxM cells in which you insert child widgets with [classfnc:layout]$addWidget[/classfnc]().[br]
+ Widgets that must span multiple cells can be added to the layout with [classfnc:layout]$addMultiCellWidget[/classfnc]().[br]
+ @functions:
+ !fn: $addWidget(<widget:object widget>,<row:uint>,<column:uint>)
+ Adds a widget to this layout placing it at position <row>,<column> in the grid
+ !fn: $addMultiCellWidget(<widget:object widget>,<start_row:uint>,<end_row:uint>,<start_col:uint>,<end_col:uint>)
+ Adds a widget to this layout spanning multiple grid cells
+ !fn: $setRowStretch(<row:uint>,<stretch:uint>)
+ Sets the stretch value for a particular row of this layout. The <stretch_value>
+ must be a positive integer. The rows with bigger stretch values will take more space
+ in the layout.
+ !fn: $setColStretch(<column:uint>,<stretch:uint>)
+ Sets the stretch value for a particular column in this layout. The <stretch_value>
+ must be a positive integer. The rows with bigger stretch values will take more space
+ in the layout.
+ !fn: $addRowSpacing(<row:uint>,<spacing:uint>)
+ Sets the minimum height of the specified <row> to <spacing> which must be a positive integer
+ !fn: $addColSpacing(<column:uint>,<spacing:uint>)
+ Sets the minimum width of the specigfied <column> to <spacing> which must be a positive integer
+ !fn: $setSpacing(<spacing:uint>)
+ Sets the default spacing of the widgets in pixels
+ !fn: $setMargin(<margin:uint>)
+ Sets the dimension of the layout margin : the distance from the border to the outermost child widget edges.
+ !fn: $setResizeMode(<resize_mode:string>)
+ Sets the resize mode of the parent widget in relation to this layout.
+ <mode> can be one of:[br]
+ -Auto: this is the default[br]
+ -Fixed: the parent widget of this layout is resized to the "sizeHint" value and it cannot be resized by the user.[br]
+ -Minimum: the minimum size of the parent widget of this layout is set to minimumSize() and it cannot be smaller[br]
+ -FreeResize: the parent widget of this layout is not constrained at all[br]
+*/
+
+
+KVSO_BEGIN_REGISTERCLASS(KviKvsObject_layout,"layout","object")
+ KVSO_REGISTER_HANDLER(KviKvsObject_layout,"addWidget", functionAddWidget)
+ KVSO_REGISTER_HANDLER(KviKvsObject_layout,"addMultiCellWidget", functionAddMultiCellWidget)
+ KVSO_REGISTER_HANDLER(KviKvsObject_layout,"setRowStretch", functionSetRowStretch)
+ KVSO_REGISTER_HANDLER(KviKvsObject_layout,"setColStretch", functionSetColStretch)
+ KVSO_REGISTER_HANDLER(KviKvsObject_layout,"addRowSpacing", functionAddRowSpacing)
+ KVSO_REGISTER_HANDLER(KviKvsObject_layout,"addColSpacing", functionAddColSpacing)
+ KVSO_REGISTER_HANDLER(KviKvsObject_layout,"setMargin", functionSetMargin)
+ KVSO_REGISTER_HANDLER(KviKvsObject_layout,"setSpacing", functionSetSpacing)
+ KVSO_REGISTER_HANDLER(KviKvsObject_layout,"setResizeMode", functionSetResizeMode)
+KVSO_END_REGISTERCLASS(KviKvsObject_layout)
+
+KVSO_BEGIN_CONSTRUCTOR(KviKvsObject_layout,KviKvsObject)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_layout)
+
+
+KVSO_BEGIN_DESTRUCTOR(KviKvsObject_layout)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_layout)
+
+bool KviKvsObject_layout::init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams)
+{
+ QWidget * w = parentScriptWidget();
+
+ if(!w)
+ {
+ pContext->warning(__tr2qs("The parent of a layout must be a widget!"));
+ return false;
+ }
+ setObject(new QGridLayout(w));
+ return true;
+}
+
+bool KviKvsObject_layout::functionAddWidget(KviKvsObjectFunctionCall *c)
+{
+ KviKvsObject * pObject;
+ kvs_hobject_t hObject;
+ kvs_uint_t uCol,uRow;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("widget",KVS_PT_HOBJECT,0,hObject)
+ KVSO_PARAMETER("row",KVS_PT_UNSIGNEDINTEGER,0,uRow)
+ KVSO_PARAMETER("col",KVS_PT_UNSIGNEDINTEGER,0,uCol)
+ KVSO_PARAMETERS_END(c)
+ pObject=KviKvsKernel::instance()->objectController()->lookupObject(hObject);
+ if(!widget())return true;
+ if (!pObject)
+ {
+ c->warning(__tr2qs("Widget parameter is not an object"));
+ return true;
+ }
+ if (!pObject->object())
+ {
+ c->warning(__tr2qs("Widget parameter is not a valid object"));
+ return true;
+ }
+ if(!pObject->object()->isWidgetType())
+ {
+ c->warning(__tr2qs("Can't add a non-widget object"));
+ return true;
+ }
+ ((QGridLayout *)object())->addWidget(((QWidget *)(pObject->object())),uRow,uCol);
+ return true;
+}
+bool KviKvsObject_layout::functionAddMultiCellWidget(KviKvsObjectFunctionCall *c)
+{
+ KviKvsObject * pObject;
+ kvs_hobject_t hObject;
+ kvs_uint_t uStartCol,uStartRow,uEndCol,uEndRow;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("widget",KVS_PT_HOBJECT,0,hObject)
+ KVSO_PARAMETER("start_row",KVS_PT_UNSIGNEDINTEGER,0,uStartRow)
+ KVSO_PARAMETER("end_row",KVS_PT_UNSIGNEDINTEGER,0,uEndRow)
+ KVSO_PARAMETER("start_column",KVS_PT_UNSIGNEDINTEGER,0,uStartCol)
+ KVSO_PARAMETER("end_column",KVS_PT_UNSIGNEDINTEGER,0,uEndCol)
+ KVSO_PARAMETERS_END(c)
+ pObject=KviKvsKernel::instance()->objectController()->lookupObject(hObject);
+ if(!widget())return true;
+ if (!pObject)
+ {
+ c->warning(__tr2qs("Widget parameter is not an object"));
+ return true;
+ }
+ if (!pObject->object())
+ {
+ c->warning(__tr2qs("Widget parameter is not a valid object"));
+ return true;
+ }
+ if(!pObject->object()->isWidgetType())
+ {
+ c->warning(__tr2qs("Can't add a non-widget object"));
+ return true;
+ }
+ ((QGridLayout *)object())->addMultiCellWidget(((QWidget *)(pObject->object())),uStartRow,uEndRow,uStartCol,uEndCol);
+ return true;
+}
+bool KviKvsObject_layout::functionSetRowStretch(KviKvsObjectFunctionCall *c)
+{
+ kvs_uint_t uRow,uStretch;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("row",KVS_PT_UNSIGNEDINTEGER,0,uRow)
+ KVSO_PARAMETER("stretch",KVS_PT_UNSIGNEDINTEGER,0,uStretch)
+ KVSO_PARAMETERS_END(c)
+ if(!widget())return true;
+ ((QGridLayout *)object())->setRowStretch(uRow,uStretch);
+ return true;
+}
+bool KviKvsObject_layout::functionSetColStretch(KviKvsObjectFunctionCall *c)
+{
+ kvs_uint_t uCol,uStretch;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("column",KVS_PT_UNSIGNEDINTEGER,0,uCol)
+ KVSO_PARAMETER("stretch",KVS_PT_UNSIGNEDINTEGER,0,uStretch)
+ KVSO_PARAMETERS_END(c)
+ if(!widget())return true;
+ ((QGridLayout *)object())->setColStretch(uCol,uStretch);
+ return true;
+}
+
+bool KviKvsObject_layout::functionSetMargin(KviKvsObjectFunctionCall *c)
+{
+ kvs_uint_t uMargin;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("margin",KVS_PT_UNSIGNEDINTEGER,0,uMargin)
+ KVSO_PARAMETERS_END(c)
+ if (widget()) ((QGridLayout *)object())->setMargin(uMargin);
+ return true;
+}
+
+bool KviKvsObject_layout::functionSetSpacing(KviKvsObjectFunctionCall *c)
+{
+ kvs_uint_t uSpacing;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("spacing",KVS_PT_UNSIGNEDINTEGER,0,uSpacing)
+ KVSO_PARAMETERS_END(c)
+ if (widget()) ((QGridLayout *)object())->setSpacing(uSpacing);
+ return true;
+}
+
+
+bool KviKvsObject_layout::functionAddRowSpacing(KviKvsObjectFunctionCall *c)
+{
+ kvs_uint_t uSpacing,uRow;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("row",KVS_PT_UNSIGNEDINTEGER,0,uRow)
+ KVSO_PARAMETER("spacing",KVS_PT_UNSIGNEDINTEGER,0,uSpacing)
+ KVSO_PARAMETERS_END(c)
+ if (widget()) ((QGridLayout *)object())->addRowSpacing(uRow,uSpacing);
+ return true;
+}
+
+bool KviKvsObject_layout::functionAddColSpacing(KviKvsObjectFunctionCall *c)
+{
+ kvs_uint_t uSpacing,uCol;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("column",KVS_PT_UNSIGNEDINTEGER,0,uCol)
+ KVSO_PARAMETER("spacing",KVS_PT_UNSIGNEDINTEGER,0,uSpacing)
+ KVSO_PARAMETERS_END(c)
+ if (widget()) ((QGridLayout *)object())->addColSpacing(uCol,uSpacing);
+ return true;
+}
+
+bool KviKvsObject_layout::functionSetResizeMode(KviKvsObjectFunctionCall *c)
+{
+ QString szMode;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("resize_mode",KVS_PT_STRING,0,szMode)
+ KVSO_PARAMETERS_END(c)
+ if(!widget())return true;
+#ifdef COMPILE_USE_QT4
+ QLayout::SizeConstraint r = QLAYOUT_AUTO_CONSTRAINT;
+#else
+ QLayout::ResizeMode r = QLAYOUT_AUTO_CONSTRAINT;
+#endif
+ if(KviQString::equalCI(szMode,"FreeResize")) r = QLAYOUT_FREE_RESIZE;
+ else if(KviQString::equalCI(szMode,"Minimum")) r = QLAYOUT_MINIMUM;
+ else if(KviQString::equalCI(szMode,"Fixed"))r = QLAYOUT_FIXED;
+ else c->warning(__tr2qs("Invalid resize mode defaulting to Auto"));
+ ((QGridLayout *)object())->setResizeMode(r);
+ return true;
+
+}
+
diff --git a/src/modules/objects/class_layout.h b/src/modules/objects/class_layout.h
new file mode 100644
index 00000000..e821316a
--- /dev/null
+++ b/src/modules/objects/class_layout.h
@@ -0,0 +1,52 @@
+#ifndef _CLASS_LAYOUT_H_
+#define _CLASS_LAYOUT_H_
+//
+// File : class_layout.h
+// Creation date : Fri Now 22 2002 00:50:01 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+#include "kvi_string.h"
+
+#include <qlayout.h>
+#include "object_macros.h"
+
+class KviKvsObject_layout : public KviKvsObject
+{
+public:
+ KVSO_DECLARE_OBJECT(KviKvsObject_layout)
+public:
+ QWidget * widget() { return (QWidget *)object(); };
+protected:
+ virtual bool init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams);
+
+ bool functionAddWidget(KviKvsObjectFunctionCall *c);
+ bool functionAddMultiCellWidget(KviKvsObjectFunctionCall *c);
+ bool functionSetRowStretch(KviKvsObjectFunctionCall *c);
+ bool functionSetColStretch(KviKvsObjectFunctionCall *c);
+ bool functionSetMargin(KviKvsObjectFunctionCall *c);
+ bool functionSetSpacing(KviKvsObjectFunctionCall *c);
+ bool functionAddRowSpacing(KviKvsObjectFunctionCall *c);
+ bool functionAddColSpacing(KviKvsObjectFunctionCall *c);
+ bool functionSetResizeMode(KviKvsObjectFunctionCall *c);
+
+
+};
+
+
+#endif //_CLASS_LAYOUT_H_
diff --git a/src/modules/objects/class_lcd.cpp b/src/modules/objects/class_lcd.cpp
new file mode 100644
index 00000000..0f0ba49a
--- /dev/null
+++ b/src/modules/objects/class_lcd.cpp
@@ -0,0 +1,180 @@
+//
+// File : class_lcd.cpp
+// Creation date : Mon Gen 27 14:30:48 CEST 2005 by Tonino Imbesi(Grifisx)
+// and Alessandro Carbone(Noldor)
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+#include "class_lcd.h"
+#include "kvi_error.h"
+#include "kvi_debug.h"
+
+#include "kvi_locale.h"
+#include "kvi_iconmanager.h"
+
+/*
+ @doc: lcdnumber
+ @keyterms:
+ lcdnumber object class, lcd
+ @title:
+ lcdnumber class
+ @type:
+ class
+ @short:
+ The lcdNumber widget displays a number with LCD-like digits.
+ @inherits:
+
+ @description:
+ It can display a number in just about any size. It can display decimal,
+ hexadecimal, octal or binary numbers.
+ @functions:
+ !fn: $setDisplayStr(<number:string>)
+ Displays the number represented by the string s.
+ !fn: $setDisplayInt(<number:integer>)
+ Sets the displayed value rounded to the nearest integer to number.
+ !fn: $setDisplayDouble(<number:double>)
+ Sets the displayed value to number (double).
+ !fn: $setMode(<mode:string>)
+ Sets the current display mode (number base): valid mode are HEX,BIN,OCT,DEC.
+ !fn: $setSegmentStyles(<style:string>)
+ Sets the style of the lcdnumber, valid styles are: Outline,Filled,Flat.
+ !fn: $setNumDigits(<number:integer>)
+ Sets the lcd number value.
+ !fn: <boolean> $checkOverflow()
+ Returns TRUE if num is too big to be displayed in its entirety;
+ otherwise returns FALSE.
+ !fn: $setSmallDecimalPoint(<bflag:boolean>)
+ Sets the the decimal point style, valid bool values are 1 or 0.
+ !fn: <boolean> $checkOverflow(<number:integer>)
+ Returns 1 (TRUE) if num is too big to be displayed in its entirety; otherwise returns 0 (FALSE).
+*/
+
+KVSO_BEGIN_REGISTERCLASS(KviKvsObject_lcd,"lcdnumber","widget")
+
+ KVSO_REGISTER_HANDLER(KviKvsObject_lcd,"setDisplayStr", functiondisplayStr)
+ KVSO_REGISTER_HANDLER(KviKvsObject_lcd,"setDisplayInt", functiondisplayInt)
+ KVSO_REGISTER_HANDLER(KviKvsObject_lcd,"setDisplayDouble", functiondisplayDouble)
+ KVSO_REGISTER_HANDLER(KviKvsObject_lcd,"setMode", functionsetMode)
+ KVSO_REGISTER_HANDLER(KviKvsObject_lcd,"setSegmentStyle", functionsetSegmentStyle)
+ KVSO_REGISTER_HANDLER(KviKvsObject_lcd,"setNumDigits", functionsetNumDigits)
+ KVSO_REGISTER_HANDLER(KviKvsObject_lcd,"setSmallDecimalPoint",functionsetSmallDecimalPoint)
+ KVSO_REGISTER_HANDLER(KviKvsObject_lcd,"checkOverflow", functioncheckOverflow)
+KVSO_END_REGISTERCLASS(KviKvsObject_lcd)
+
+KVSO_BEGIN_CONSTRUCTOR(KviKvsObject_lcd,KviKvsObject_widget)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_lcd)
+
+
+KVSO_BEGIN_DESTRUCTOR(KviKvsObject_lcd)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_lcd)
+
+bool KviKvsObject_lcd::init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams)
+{
+ setObject(new QLCDNumber(parentScriptWidget(), name()), true);
+ return true;
+}
+
+bool KviKvsObject_lcd::functiondisplayInt(KviKvsObjectFunctionCall *c)
+{
+ kvs_int_t iDigit;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("number",KVS_PT_INT,0,iDigit)
+ KVSO_PARAMETERS_END(c)
+ if(widget())((QLCDNumber *)widget())->display((int)iDigit);
+ return true;
+}
+
+bool KviKvsObject_lcd::functiondisplayStr(KviKvsObjectFunctionCall *c)
+{
+ QString szText;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("number",KVS_PT_STRING,0,szText)
+ KVSO_PARAMETERS_END(c)
+ if(widget()) ((QLCDNumber *)widget())->display(szText);
+ return true;
+}
+
+bool KviKvsObject_lcd::functiondisplayDouble(KviKvsObjectFunctionCall *c)
+{
+ kvs_real_t dDigit;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("number",KVS_PT_DOUBLE,0,dDigit)
+ KVSO_PARAMETERS_END(c)
+ if(widget()) ((QLCDNumber *)widget())->display(dDigit);
+ return true;
+}
+bool KviKvsObject_lcd::functionsetMode(KviKvsObjectFunctionCall *c)
+{
+ QString szMode;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("mode",KVS_PT_STRING,0,szMode)
+ KVSO_PARAMETERS_END(c)
+ if(!widget())return true;
+ if(KviQString::equalCI(szMode, "HEX")) ((QLCDNumber *)widget())->setHexMode();
+ else if(KviQString::equalCI(szMode, "DEC")) ((QLCDNumber *)widget())->setDecMode();
+ else if(KviQString::equalCI(szMode, "BIN")) ((QLCDNumber *)widget())->setBinMode();
+ else if(KviQString::equalCI(szMode, "OCT")) ((QLCDNumber *)widget())->setOctMode();
+ else c->warning( __tr2qs("Unknown mode "));
+ return true;
+}
+bool KviKvsObject_lcd::functionsetSegmentStyle(KviKvsObjectFunctionCall *c)
+{
+ QString szStyle;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("style",KVS_PT_STRING,0,szStyle)
+ KVSO_PARAMETERS_END(c)
+ if(!widget())return true;
+ if(KviQString::equalCI(szStyle, "Outline")) ((QLCDNumber *)widget())->setSegmentStyle(QLCDNumber::Outline);
+ else if(KviQString::equalCI(szStyle, "Filled")) ((QLCDNumber *)widget())->setSegmentStyle(QLCDNumber::Filled);
+ else if(KviQString::equalCI(szStyle, "Flat")) ((QLCDNumber *)widget())->setSegmentStyle(QLCDNumber::Flat);
+ else c->warning( __tr2qs("Unknown segment style "));
+ return true;
+}
+bool KviKvsObject_lcd::functionsetNumDigits(KviKvsObjectFunctionCall *c)
+{
+ kvs_real_t digit;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("digit",KVS_PT_DOUBLE,0,digit)
+ KVSO_PARAMETERS_END(c)
+ if(widget()) ((QLCDNumber *)widget())->setNumDigits(digit);
+ return true;
+}
+bool KviKvsObject_lcd::functionsetSmallDecimalPoint(KviKvsObjectFunctionCall *c)
+{
+ bool bFlag;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bflag",KVS_PT_BOOLEAN,0,bFlag)
+ KVSO_PARAMETERS_END(c)
+ if(widget()) ((QLCDNumber *)widget())->setSmallDecimalPoint(bFlag);
+ return true;
+}
+bool KviKvsObject_lcd::functioncheckOverflow(KviKvsObjectFunctionCall *c)
+{
+ kvs_real_t iDigit;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("digit",KVS_PT_DOUBLE,0,iDigit)
+ KVSO_PARAMETERS_END(c)
+ if(widget())c->returnValue()->setBoolean(((QLCDNumber *)widget())->checkOverflow(iDigit));
+ return true;
+}
+
+
diff --git a/src/modules/objects/class_lcd.h b/src/modules/objects/class_lcd.h
new file mode 100644
index 00000000..4976850a
--- /dev/null
+++ b/src/modules/objects/class_lcd.h
@@ -0,0 +1,51 @@
+#ifndef _CLASS_LCD_H_
+#define _CLASS_LCD_H_
+
+// File : class_lcd.h
+// Creation date : Mon Gen 27 14:30:48 CEST 2005 by Tonino Imbesi(Grifisx)
+// and Alessandro Carbone(Noldor)
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+
+#include <qlcdnumber.h>
+#include "class_widget.h"
+
+
+class KviKvsObject_lcd : public KviKvsObject_widget
+{
+public:
+ KVSO_DECLARE_OBJECT(KviKvsObject_lcd)
+public:
+ QWidget * widget() { return (QWidget *)object(); };
+protected:
+ virtual bool init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams);
+
+ bool functiondisplayStr(KviKvsObjectFunctionCall *c);
+ bool functionsetMode(KviKvsObjectFunctionCall *c);
+ bool functionsetSegmentStyle(KviKvsObjectFunctionCall *c);
+ bool functionsetNumDigits(KviKvsObjectFunctionCall *c);
+ bool functionsetSmallDecimalPoint(KviKvsObjectFunctionCall *c);
+ bool functioncheckOverflow(KviKvsObjectFunctionCall *c);
+ bool functiondisplayInt(KviKvsObjectFunctionCall *c);
+ bool functiondisplayDouble(KviKvsObjectFunctionCall *c);
+};
+
+#endif // !_CLASS_LCD_H_
diff --git a/src/modules/objects/class_lineedit.cpp b/src/modules/objects/class_lineedit.cpp
new file mode 100644
index 00000000..c8ba58ff
--- /dev/null
+++ b/src/modules/objects/class_lineedit.cpp
@@ -0,0 +1,461 @@
+//vim: ts=8
+// File : class_lineedit.cpp
+// Creation date : Wed 20 Sep 2000 04:34:40 CEST by Krzysztof Godlewski
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+#include "kvi_error.h"
+#include "kvi_debug.h"
+
+#include "kvi_locale.h"
+
+#include "class_lineedit.h"
+
+static const char * mode_tbl[] = {
+ "Normal",
+ "NoEcho",
+ "Password"
+ };
+
+static const int mode_cod[] = {
+ QLineEdit::Normal,
+ QLineEdit::NoEcho,
+ QLineEdit::Password
+ };
+
+#define mode_num (sizeof(mode_tbl) / sizeof(mode_tbl[0]))
+
+
+/*
+ @doc: lineedit
+ @keyterms:
+ lineedit object class, line editor, input
+ @title:
+ lineedit class
+ @type:
+ class
+ @short:
+ Simple line editor for inputting short text
+ @inherits:
+ [class]object[/class]
+ [class]widget[/class]
+ @description:
+ This is a simple, one-line editor usually used for inputting
+ short text like names, phone numbers etc. It can display text
+ in three echo modes (see [classfnc]$setEchoMode[/classfnc]()
+ for details).
+ @functions:
+ !fn: <string> $text()
+ Returns text contained by the widget.[br]
+ See also [classfnc]$setText[/classfnc]().
+ !fn: $setText(<text:string>)
+ Sets editor text to <text>.[br]
+ See also [classfnc]$text[/classfnc]().
+ !fn: $setEchoMode(<echo_mode:string>)
+ Sets the line edit's echo mode. Possible value are:[br]
+ -Normal: display chars as they entered[br]
+ -Noecho : do not display anything[br]
+ -Password : display asterisks instead of the characters actually entered[br]
+ See also [classfnc]$echoMode[/classfnc]().
+ !fn: <string> $echoMode()
+ Return the line edit's echo mode.
+ See also [classfnc]$setEchoMode[/classfnc]().
+ !fn: <integer> $maxLength()
+ Returns the current maximum length of the text that can be typed
+ in the editor.[br]
+ See also [classfnc]$setMaxLength[/classfnc]().
+ !fn: $setMaxLength(<max_lenght:integer>)
+ Sets maximum length of the text that can be typed in the
+ editor.[br]
+ See also [classfnc]$maxLength[/classfnc]().
+ !fn: <boolean> $frame()
+ Returns '1' if the editor is drawn inside a frame, which is 2
+ pixels wide, '0' otherwise.[br]
+ See also [classfnc]$setFrame[/classfnc]().
+ !fn: $setFrame(<bframe:boolean>)
+ Sets editor frame drawing to <bool>.[br]
+ See also [classfnc]$frame[/classfnc]().
+ !fn: <integer> $cursorPosition()
+ Returns current cursor position in the editor.[br]
+ See also [classfnc]$setCursorPosition[/classfnc]().
+ !fn: $setCursorPosition(<index:integer>)
+ Moves the cursor to place pointed by <index>.[br]
+ See also [classfnc]$cursorPosition[/classfnc]().
+ !fn: $selectAll()
+ Selects whole text inside the editor.[br]
+ See also [classfnc]$setSelection[/classfnc](),
+ [classfnc]$cut[/classfnc](), [classfnc]$copy[/classfnc](),
+ [classfnc]$paste[/classfnc]().
+ !fn: $setSelection(<start:integer>, <length:integer>)
+ Selects <length> characters in the editor starting at position
+ <start>.[br]
+ See also [classfnc]$selectAll[/classfnc](),
+ [classfnc]$cut[/classfnc](), [classfnc]$copy[/classfnc](),
+ [classfnc]$paste[/classfnc]().
+ !fn: $copy()
+ Copies selected text in the editor to the clipboard.[br]
+ See also [classfnc]$setSelection[/classfnc](),
+ [classfnc]$cut[/classfnc](), [classfnc]$paste[/classfnc]().
+ !fn: $cut()
+ Cuts selected text from the editor to the clipboard.[br]
+ See also [classfnc]$setSelection[/classfnc](),
+ [classfnc]$copy[/classfnc](), [classfnc]$paste[/classfnc]().
+ !fn: $paste()
+ Pastes text from the clipboard into the editor. The pasted text
+ will start at cursor position.[br]
+ See also [classfnc]$setSelection[/classfnc](),
+ [classfnc]$copy[/classfnc](), [classfnc]$cut[/classfnc]().
+ !fn: $clear()
+ Deletes all text from the editor. Equal to calling [classfnc]$setText[/classfnc]("").
+ !fn: $setDragEnabled(<bEnabled:bool>)
+ With this property user can drag text in the lineedit.
+ !fn: $setReadOnly(<bReadonly:boolean>)
+ Sets the lineedit to read only mode.
+ !fn: $setInputMask(<mask:string>)
+ Sets the validation input mask to inputMask.[br]
+ Example:[br]
+ [br]
+ %esempio->$setInputMask( "+99 99 99 99 99;_" );[br]
+ %esempio->$setInputMask( "000.000.000.000;_" );[br]
+ %esempio->Ip Number Mask.[br]
+ %esempio->setInputMask( ">AAAAA-AAAAA-AAAAA-AAAAA-AAAAA;#" );[br]
+ [br]
+ The mask format understands these mask characters:[br]
+ Character Meaning[br]
+ A ASCII alphabetic character required. A-Z, a-z.[br]
+ a ASCII alphabetic character permitted but not required.[br]
+ N ASCII alphanumeric character required. A-Z, a-z, 0-9.[br]
+ n ASCII alphanumeric character permitted but not required.[br]
+ X Any character required.[br]
+ x Any character permitted but not required.[br]
+ 9 ASCII digit required. 0-9.[br]
+ 0 ASCII digit permitted but not required.[br]
+ D ASCII digit required. 1-9.[br]
+ d ASCII digit permitted but not required.[br]
+ # ASCII digit or plus/minus sign permitted but not required.[br]
+ > All following alphabetic characters are uppercased.[br]
+ < All following alphabetic characters are lowercased.[br]
+ ! Switch off case conversion.[br]
+ \ Use \ to escape the special characters listed above to use them as separators.[br]
+ [br]
+ The mask consists of a string of mask characters and separators, optionally[br]
+ followed by a semi-colon and the character used for blanks: the blank characters [br]
+ are always removed from the text after editing. The default blank character is space. [br]
+ !fn: $returnPressedEvent()
+ This function is called by the framework when the enter key is pressed.
+ !fn: $lostFocusEvent()
+ Called when the lineedit lost focus.
+ !fn: $textChangedEvent(<new text:string>)
+ This event is called when the text changed, In $0 there is the new text.
+ @signals:
+ !sg: $returnPressed()
+ This signal is emitted by the default implementation of [classfnc]$returnPressedEvent[/classfnc]().
+ !sg: $lostFocus()
+ This signal is emitted by the default implementation of [classfnc]$lostFocusEvent[/classfnc]().
+ !sg: $textChanged()
+ This signal is emitted by the default implementation of [classfnc]$textChangedEvent[/classfnc]().
+
+*/
+
+
+
+KVSO_BEGIN_REGISTERCLASS(KviKvsObject_lineedit,"lineedit","widget")
+
+ KVSO_REGISTER_HANDLER(KviKvsObject_lineedit,"text", functionText)
+ KVSO_REGISTER_HANDLER(KviKvsObject_lineedit,"setText", functionSetText)
+ KVSO_REGISTER_HANDLER(KviKvsObject_lineedit,"maxLength", functionMaxLength)
+ KVSO_REGISTER_HANDLER(KviKvsObject_lineedit,"setMaxLength", functionSetMaxLength)
+ KVSO_REGISTER_HANDLER(KviKvsObject_lineedit,"frame", functionFrame)
+ KVSO_REGISTER_HANDLER(KviKvsObject_lineedit,"setCursorPosition", functionSetCursorPosition)
+ KVSO_REGISTER_HANDLER(KviKvsObject_lineedit,"cursorPosition", functionCursorPosition)
+ KVSO_REGISTER_HANDLER(KviKvsObject_lineedit,"setFrame", functionSetFrame)
+ KVSO_REGISTER_HANDLER(KviKvsObject_lineedit,"selectAll" , functionSelectAll)
+ KVSO_REGISTER_HANDLER(KviKvsObject_lineedit,"setSelection", functionSetSelection)
+ KVSO_REGISTER_HANDLER(KviKvsObject_lineedit,"copy", functionCopy)
+ KVSO_REGISTER_HANDLER(KviKvsObject_lineedit,"cut", functionCut)
+ KVSO_REGISTER_HANDLER(KviKvsObject_lineedit,"paste", functionPaste)
+
+ KVSO_REGISTER_HANDLER(KviKvsObject_lineedit,"echoMode", functionEchoMode)
+ KVSO_REGISTER_HANDLER(KviKvsObject_lineedit,"setEchoMode", functionSetEchoMode)
+ KVSO_REGISTER_HANDLER(KviKvsObject_lineedit,"clear", functionClear)
+ KVSO_REGISTER_HANDLER(KviKvsObject_lineedit,"setDragEnabled", functionDragAndDrop)
+ KVSO_REGISTER_HANDLER(KviKvsObject_lineedit,"setInputMask", functionSetInputMask)
+ KVSO_REGISTER_HANDLER(KviKvsObject_lineedit,"setReadOnly", functionSetReadOnly)
+ KVSO_REGISTER_HANDLER(KviKvsObject_lineedit,"returnPressedEvent", functionreturnPressedEvent)
+ KVSO_REGISTER_HANDLER(KviKvsObject_lineedit,"lostFocusEvent", functionlostFocusEvent)
+ KVSO_REGISTER_HANDLER(KviKvsObject_lineedit,"textChangedEvent", functiontextChangedEvent)
+
+
+KVSO_END_REGISTERCLASS(KviKvsObject_lineedit)
+
+
+KVSO_BEGIN_CONSTRUCTOR(KviKvsObject_lineedit,KviKvsObject_widget)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_lineedit)
+
+
+KVSO_BEGIN_DESTRUCTOR(KviKvsObject_lineedit)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_lineedit)
+
+
+bool KviKvsObject_lineedit::init(KviKvsRunTimeContext * pContext,KviKvsVariantList * pParams)
+{
+ setObject(new QLineEdit(parentScriptWidget(),getName()),true);
+ connect(widget(),SIGNAL(returnPressed()),this,SLOT(slotreturnPressed()));
+ connect(widget(),SIGNAL(lostFocus()),this,SLOT(slotlostFocus()));
+ connect(widget(),SIGNAL(textChanged(const QString & )),this,SLOT(slottextChanged(const QString & )));
+ return true;
+}
+
+bool KviKvsObject_lineedit::functionText(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ c->returnValue()->setString(((QLineEdit *)widget())->text());
+ return true;
+}
+
+bool KviKvsObject_lineedit::functionSetText(KviKvsObjectFunctionCall *c)
+{
+ QString szText;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("text",KVS_PT_STRING,0,szText)
+ KVSO_PARAMETERS_END(c)
+ if (widget())
+ ((QLineEdit *)widget())->setText(szText);
+ return true;
+}
+
+bool KviKvsObject_lineedit::functionMaxLength(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ c->returnValue()->setInteger(((QLineEdit *)widget())->maxLength());
+ return true;
+}
+
+bool KviKvsObject_lineedit::functionSetMaxLength(KviKvsObjectFunctionCall *c)
+{
+ kvs_uint_t iMaxlen;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("maxlen",KVS_PT_UNSIGNEDINTEGER,0,iMaxlen)
+ KVSO_PARAMETERS_END(c)
+ if (widget())
+ ((QLineEdit *)widget())->setMaxLength(iMaxlen);
+ return true;
+}
+
+bool KviKvsObject_lineedit::functionFrame(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ c->returnValue()->setBoolean(((QLineEdit *)widget())->frame());
+ return true;
+}
+
+bool KviKvsObject_lineedit::functionSetFrame(KviKvsObjectFunctionCall *c)
+{
+ bool bFrame;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bframe",KVS_PT_BOOL,0,bFrame)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ ((QLineEdit *)widget())->setFrame(bFrame);
+ return true;
+}
+
+bool KviKvsObject_lineedit::functionCursorPosition(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ c->returnValue()->setInteger(((QLineEdit *)widget())->cursorPosition());
+ return true;
+}
+
+bool KviKvsObject_lineedit::functionSetCursorPosition(KviKvsObjectFunctionCall *c)
+{
+ kvs_uint_t iPos;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("position",KVS_PT_UNSIGNEDINTEGER,0,iPos)
+ KVSO_PARAMETERS_END(c)
+ if (widget())
+ ((QLineEdit *)widget())->setCursorPosition(iPos);
+ return true;
+}
+
+bool KviKvsObject_lineedit::functionSelectAll(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ ((QLineEdit *)widget())->selectAll();
+ return true;
+}
+
+bool KviKvsObject_lineedit::functionSetSelection(KviKvsObjectFunctionCall *c)
+{
+ kvs_uint_t uStart,uLen;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("start",KVS_PT_UNSIGNEDINTEGER,0,uStart)
+ KVSO_PARAMETER("len",KVS_PT_UNSIGNEDINTEGER,0,uLen)
+ KVSO_PARAMETERS_END(c)
+ if (widget())
+ ((QLineEdit *)widget())->setSelection(uStart, uLen);
+ return true;
+}
+
+bool KviKvsObject_lineedit::functionCopy(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ ((QLineEdit *)widget())->copy();
+ return true;
+}
+
+bool KviKvsObject_lineedit::functionCut(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ ((QLineEdit *)widget())->cut();
+ return true;
+}
+
+bool KviKvsObject_lineedit::functionPaste(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ ((QLineEdit *)widget())->paste();
+ return true;
+}
+
+bool KviKvsObject_lineedit::functionEchoMode(KviKvsObjectFunctionCall *c)
+{
+ int mode = ((QLineEdit *)widget())->echoMode();
+ QString szEchomode="";
+ for(unsigned int i = 0; i < mode_num; i++)
+ {
+ if(mode == mode_cod[i])
+ {
+ szEchomode=mode_tbl[i];
+ break;
+ }
+ }
+ c->returnValue()->setString(szEchomode);
+ return true;
+}
+
+bool KviKvsObject_lineedit::functionSetEchoMode(KviKvsObjectFunctionCall *c)
+{
+ QString szMode;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("mode",KVS_PT_STRING,0,szMode)
+ KVSO_PARAMETERS_END(c)
+ if (!widget()) return true;
+ for(unsigned int i = 0; i < mode_num; i++)
+ {
+ if(KviQString::equalCI(szMode, mode_tbl[i]))
+ {
+ ((QLineEdit *)widget())->setEchoMode( \
+ ((QLineEdit::EchoMode)mode_cod[i]));
+ return true;
+ }
+ }
+ c->warning(__tr2qs("Unknown echo mode %Q"),&szMode);
+ return true;
+}
+
+bool KviKvsObject_lineedit::functionClear(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ ((QLineEdit *)widget())->clear();
+ return true;
+}
+
+//-| Grifisx & Noldor |-Start:
+bool KviKvsObject_lineedit::functionDragAndDrop(KviKvsObjectFunctionCall *c)
+{
+ bool bEnabled;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bEnabled",KVS_PT_BOOL,0,bEnabled)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ ((QLineEdit *)widget())->setDragEnabled(bEnabled);
+ return true;
+}
+
+bool KviKvsObject_lineedit::functionSetReadOnly(KviKvsObjectFunctionCall *c)
+{
+ bool bEnabled;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bReadonly",KVS_PT_BOOL,0,bEnabled)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ ((QLineEdit *)widget())->setReadOnly(bEnabled);
+ return true;
+}
+
+bool KviKvsObject_lineedit::functionSetInputMask(KviKvsObjectFunctionCall *c)
+{
+ QString szMask;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("mask",KVS_PT_STRING,0,szMask)
+ KVSO_PARAMETERS_END(c)
+ if (widget())
+ ((QLineEdit *)widget())->setInputMask(szMask);
+ return true;
+}
+
+bool KviKvsObject_lineedit::functionreturnPressedEvent(KviKvsObjectFunctionCall *c)
+{
+
+ emitSignal("returnPressed",c);
+ return true;
+
+}
+
+void KviKvsObject_lineedit::slotreturnPressed()
+{
+ KviKvsVariantList * params = 0;
+ callFunction(this,"returnPressedEvent",params);
+
+}
+// FIND ME
+bool KviKvsObject_lineedit::functionlostFocusEvent(KviKvsObjectFunctionCall *c)
+{
+
+
+ emitSignal("lostFocus",c);
+ return true;
+
+}
+
+void KviKvsObject_lineedit::slotlostFocus()
+{
+ KviKvsVariantList * params = 0;
+ callFunction(this,"lostFocusEvent",params);
+}
+/////
+bool KviKvsObject_lineedit::functiontextChangedEvent(KviKvsObjectFunctionCall *c)
+{
+ emitSignal("textChanged",c,c->params());
+ return true;
+
+}
+
+void KviKvsObject_lineedit::slottextChanged(const QString &text)
+{
+ KviKvsVariantList params(new KviKvsVariant(text));
+ callFunction(this,"textChangedEvent",&params);
+}
+
+
+#include "m_class_lineedit.moc"
diff --git a/src/modules/objects/class_lineedit.h b/src/modules/objects/class_lineedit.h
new file mode 100644
index 00000000..d7036824
--- /dev/null
+++ b/src/modules/objects/class_lineedit.h
@@ -0,0 +1,81 @@
+#ifndef _CLASS_LINEEDIT_H_
+#define _CLASS_LINEEDIT_H_
+//vim: ts=8
+// File : class_lineedit.h
+// Creation date : Wed 20 Sep 2000 04:34:22 CEST by Krzysztof Godlewski
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+
+#include <qlineedit.h>
+#include "class_widget.h"
+
+//#warning "Signals !"
+
+#include "object_macros.h"
+
+class KviKvsObject_lineedit : public KviKvsObject_widget
+{
+ Q_OBJECT
+public:
+ KVSO_DECLARE_OBJECT(KviKvsObject_lineedit)
+public:
+ QWidget * widget() { return (QWidget *)object(); };
+protected:
+ virtual bool init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams);
+
+
+
+ bool functionText(KviKvsObjectFunctionCall *c);
+ bool functionSetText(KviKvsObjectFunctionCall *c);
+ bool functionMaxLength(KviKvsObjectFunctionCall *c);
+ bool functionSetMaxLength(KviKvsObjectFunctionCall *c);
+ bool functionFrame(KviKvsObjectFunctionCall *c);
+ bool functionSetCursorPosition(KviKvsObjectFunctionCall *c);
+ bool functionCursorPosition(KviKvsObjectFunctionCall *c);
+ bool functionSetFrame(KviKvsObjectFunctionCall *c);
+ bool functionSelectAll(KviKvsObjectFunctionCall *c);
+ bool functionSetSelection(KviKvsObjectFunctionCall *c);
+ bool functionCopy(KviKvsObjectFunctionCall *c);
+ bool functionCut(KviKvsObjectFunctionCall *c);
+
+ bool functionPaste(KviKvsObjectFunctionCall *c);
+ bool functionEchoMode(KviKvsObjectFunctionCall *c);
+ bool functionSetEchoMode(KviKvsObjectFunctionCall *c);
+ bool functionClear(KviKvsObjectFunctionCall *c);
+ bool functionDragAndDrop(KviKvsObjectFunctionCall *c);
+ bool functionSetInputMask(KviKvsObjectFunctionCall *c);
+ bool functionSetReadOnly(KviKvsObjectFunctionCall *c);
+
+ bool functionreturnPressedEvent(KviKvsObjectFunctionCall *c);
+
+ bool functionlostFocusEvent(KviKvsObjectFunctionCall *c);
+
+ bool functiontextChangedEvent(KviKvsObjectFunctionCall *c);
+
+protected slots:
+ void slotreturnPressed();
+ void slotlostFocus();
+ void slottextChanged(const QString &);
+
+};
+
+
+#endif // ! _CLASS_LINEEDIT_H_
diff --git a/src/modules/objects/class_list.cpp b/src/modules/objects/class_list.cpp
new file mode 100644
index 00000000..2d6c9e84
--- /dev/null
+++ b/src/modules/objects/class_list.cpp
@@ -0,0 +1,392 @@
+//=============================================================================
+//
+// File : class_list.cpp
+// Creation date : Wed Sep 09 2000 21:07:55 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//============================================================================
+
+#include "kvi_debug.h"
+
+#include "kvi_malloc.h"
+#include "kvi_locale.h"
+
+#include "class_list.h"
+
+#include <stdlib.h>
+
+
+/*
+ @doc: list
+ @keyterms:
+ list object class, sorted list
+ @title:
+ list class
+ @type:
+ class
+ @short:
+ Abstracts a double linked list of strings
+ @inherits:
+ [class]object[/class]
+ @description:
+
+
+ This object class abstracts a double linked list of strings.
+ You can insert/remove items by zero based position, at the end (tail) or at the
+ beginning (head). The list incorporates an efficient iteration
+ method by using the [classfnc:list]$moveFirst[/classfnc](),[classfnc:list]$moveLast[/classfnc](),
+ [classfnc:list]$moveNext[/classfnc](),[classfnc:list]$movePrev[/classfnc](),
+ [classfnc:list]$current[/classfnc]() and [classfnc:list]$eof[/classfnc]() functions.
+ @functions:
+ !fn: <integer> $count()
+ Returns the number of items in the list
+
+ !fn: <boolean> $isEmpty()
+ Returns $true if the list is empty, $false otherwise.
+
+ !fn: $clear()
+ Removes all the items from the list.This is the same as
+ [classfnc:list]$removeAll[/classfnc]().
+
+ !fn: $removeAll()
+ Removes all the items from the list. This is the same as
+ [classfnc:list]$clear[/classfnc]().
+
+ !fn: $append(<item:variant>)
+ Inserts the <item> at the end (tail) of the list.
+
+ !fn: $prepend(<item:variant>)
+ Inserts the <item> at the beginning (head) of the list.
+
+ !fn: $insert(<index:uint>,<item:variant>)
+ Inserts the <item> at zero-based position <index> in the list.
+ If <index> is greater or equal to [classfnc:list]$count[/classfnc]()
+ then the item is simply appended to the end of the list.
+
+ !fn: $add(<index:uint>,<item:variant>)
+ This is exactly the same as [classfnc:list]$insert[/classfnc]().
+
+ !fn: <variant> $item(<index:uint>)
+ Returns the item at zero-based <index>. If <index> is greater
+ or equal to [classfnc:list]$count[/classfnc]() (beyond the end of the list)
+ then [fnc]$nothing[/fnc] is returned.
+
+ !fn: <boolean> $remove(<index:uint>)
+ Removes the item at zero-based <index>. Returns $true
+ if the item was succesfully removed and $false otherwise (i.e. <index>
+ pointed beyond the end of the list).
+
+ !fn: <boolean> $removeFirst()
+ Removes the first item from the list. Returns $true
+ if the item was succesfully removed (the list was not empty)
+ and $false otherwise.
+
+ !fn: <boolean> $removeLast()
+ Removes the last item from the list. Returns $true
+ if the item was succesfully removed (the list was not empty)
+ and $false otherwise.
+
+ !fn: <boolean> $removeCurrent()
+ Removes the current item from the list. Returns $true
+ if the item was succesfully removed or $false otherwise.
+ Invalidates any iteration operation.
+
+ !fn: <boolean> $moveFirst()
+ Moves the iterator to the first item in the list and returns
+ $true if the move was succesfull (i.e., the list is not empty)
+ and $false otherwise.
+
+ !fn: <boolean> $moveLast()
+ Moves the iterator to the last item in the list and returns
+ $true if the move was succesfull (i.e., the list is not empty)
+ and $false otherwise.
+
+ !fn: <boolean> $movePrev()
+ Moves the iterator to the previous item and returns $true
+ if the move was succesfull (i.e., there IS a previous item)
+ and $false otherwise.
+
+ !fn: <boolean> $moveNext()
+ Moves the iterator to the next item and returns $true
+ if the move was succesfull (i.e., there IS a next item)
+ and $false otherwise.
+
+ !fn: <boolean> $eof()
+ Returns $true if the iterator points to a valid
+ item in the list (and thus [classfnc:list]$current[/classfnc]()
+ would return a valid value) and $false otherwise.
+
+ !fn: <boolean> $current()
+ Returns the item pointed by the current iterator
+ or [fnc]$nothing[/fnc] is the iterator is not valid (points
+ beyond the end of the list).
+*/
+
+
+KVSO_BEGIN_REGISTERCLASS(KviKvsObject_list,"list","object")
+ KVSO_REGISTER_HANDLER(KviKvsObject_list,"count",function_count)
+ KVSO_REGISTER_HANDLER(KviKvsObject_list,"isEmpty",function_isEmpty)
+ KVSO_REGISTER_HANDLER(KviKvsObject_list,"clear",function_clear)
+ KVSO_REGISTER_HANDLER(KviKvsObject_list,"removeAll",function_clear)
+ KVSO_REGISTER_HANDLER(KviKvsObject_list,"append",function_append)
+ KVSO_REGISTER_HANDLER(KviKvsObject_list,"prepend",function_prepend)
+ KVSO_REGISTER_HANDLER(KviKvsObject_list,"insert",function_insert)
+ KVSO_REGISTER_HANDLER(KviKvsObject_list,"add",function_insert)
+ KVSO_REGISTER_HANDLER(KviKvsObject_list,"at",function_at)
+ KVSO_REGISTER_HANDLER(KviKvsObject_list,"item",function_at)
+ KVSO_REGISTER_HANDLER(KviKvsObject_list,"remove",function_remove)
+ KVSO_REGISTER_HANDLER(KviKvsObject_list,"removeFirst",function_removeFirst)
+ KVSO_REGISTER_HANDLER(KviKvsObject_list,"removeLast",function_removeLast)
+ KVSO_REGISTER_HANDLER(KviKvsObject_list,"removeCurrent",function_removeCurrent)
+ KVSO_REGISTER_HANDLER(KviKvsObject_list,"moveFirst",function_moveFirst)
+ KVSO_REGISTER_HANDLER(KviKvsObject_list,"moveNext",function_moveNext)
+ KVSO_REGISTER_HANDLER(KviKvsObject_list,"movePrev",function_movePrev)
+ KVSO_REGISTER_HANDLER(KviKvsObject_list,"moveLast",function_moveLast)
+ KVSO_REGISTER_HANDLER(KviKvsObject_list,"sort",function_sort)
+ KVSO_REGISTER_HANDLER(KviKvsObject_list,"eof",function_eof)
+ KVSO_REGISTER_HANDLER(KviKvsObject_list,"current",function_current)
+KVSO_END_REGISTERCLASS(KviKvsObject_list)
+
+
+KVSO_BEGIN_CONSTRUCTOR(KviKvsObject_list,KviKvsObject)
+ m_pDataList = new KviPointerList<KviKvsVariant>;
+ m_pDataList->setAutoDelete(true);
+KVSO_END_CONSTRUCTOR(KviKvsObject_list)
+
+
+KVSO_BEGIN_DESTRUCTOR(KviKvsObject_list)
+ delete m_pDataList;
+ m_pDataList = 0;
+KVSO_END_CONSTRUCTOR(KviKvsObject_list)
+
+bool KviKvsObject_list::function_current(KviKvsObjectFunctionCall *c)
+{
+ if(!m_pDataList)
+ {
+ c->returnValue()->setNothing();
+ return true;
+ }
+ KviKvsVariant * v = m_pDataList->current();
+ if(v)c->returnValue()->copyFrom(*v);
+ else c->returnValue()->setNothing();
+ return true;
+}
+
+bool KviKvsObject_list::function_eof(KviKvsObjectFunctionCall *c)
+{
+ if(!m_pDataList)
+ {
+ c->returnValue()->setBoolean(true);
+ return true;
+ }
+ c->returnValue()->setBoolean(m_pDataList->current() != 0);
+ return true;
+}
+
+bool KviKvsObject_list::function_moveLast(KviKvsObjectFunctionCall *c)
+{
+ if(!m_pDataList)
+ {
+ c->returnValue()->setBoolean(false);
+ return true;
+ }
+ c->returnValue()->setBoolean(m_pDataList->last() != 0);
+ return true;
+}
+
+bool KviKvsObject_list::function_movePrev(KviKvsObjectFunctionCall *c)
+{
+ if(!m_pDataList)
+ {
+ c->returnValue()->setBoolean(false);
+ return true;
+ }
+ c->returnValue()->setBoolean(m_pDataList->prev() != 0);
+ return true;
+}
+
+bool KviKvsObject_list::function_moveNext(KviKvsObjectFunctionCall *c)
+{
+ if(!m_pDataList)
+ {
+ c->returnValue()->setBoolean(false);
+ return true;
+ }
+ c->returnValue()->setBoolean(m_pDataList->next() != 0);
+ return true;
+}
+
+bool KviKvsObject_list::function_moveFirst(KviKvsObjectFunctionCall *c)
+{
+ if(!m_pDataList)
+ {
+ c->returnValue()->setBoolean(false);
+ return true;
+ }
+ c->returnValue()->setBoolean(m_pDataList->first() != 0);
+ return true;
+}
+
+bool KviKvsObject_list::function_removeLast(KviKvsObjectFunctionCall *c)
+{
+ if(!m_pDataList)
+ {
+ c->returnValue()->setBoolean(false);
+ return true;
+ }
+ c->returnValue()->setBoolean(m_pDataList->removeLast());
+ return true;
+}
+
+bool KviKvsObject_list::function_removeCurrent(KviKvsObjectFunctionCall *c)
+{
+ if(!m_pDataList)
+ {
+ c->returnValue()->setBoolean(false);
+ return true;
+ }
+ if(m_pDataList->current())
+ {
+ m_pDataList->removeCurrent();
+ c->returnValue()->setBoolean(true);
+ } else {
+ c->returnValue()->setBoolean(false);
+ }
+ return true;
+}
+
+bool KviKvsObject_list::function_removeFirst(KviKvsObjectFunctionCall *c)
+{
+ if(!m_pDataList)
+ {
+ c->returnValue()->setBoolean(false);
+ return true;
+ }
+ c->returnValue()->setBoolean(m_pDataList->removeFirst());
+ return true;
+}
+
+bool KviKvsObject_list::function_remove(KviKvsObjectFunctionCall *c)
+{
+ kvs_uint_t uIndex;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("index",KVS_PT_UINT,0,uIndex)
+ KVSO_PARAMETERS_END(c)
+ if(!m_pDataList)
+ {
+ c->returnValue()->setBoolean(false);
+ return true;
+ }
+ c->returnValue()->setBoolean(m_pDataList->remove(uIndex));
+ return true;
+}
+
+bool KviKvsObject_list::function_at(KviKvsObjectFunctionCall *c)
+{
+ kvs_uint_t uIndex;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("index",KVS_PT_UINT,0,uIndex)
+ KVSO_PARAMETERS_END(c)
+ if(!m_pDataList)
+ {
+ c->returnValue()->setNothing();
+ return true;
+ }
+ KviKvsVariant * v = m_pDataList->at(uIndex);
+ if(v)c->returnValue()->copyFrom(*v);
+ else c->returnValue()->setNothing();
+ return true;
+}
+
+bool KviKvsObject_list::function_insert(KviKvsObjectFunctionCall *c)
+{
+ kvs_uint_t uIndex;
+ KviKvsVariant * pVar;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("index",KVS_PT_UINT,0,uIndex)
+ KVSO_PARAMETER("item",KVS_PT_VARIANT,0,pVar)
+ KVSO_PARAMETERS_END(c)
+ if(!m_pDataList)return true;
+ m_pDataList->insert(uIndex,new KviKvsVariant(*pVar));
+ return true;
+}
+
+bool KviKvsObject_list::function_prepend(KviKvsObjectFunctionCall *c)
+{
+ KviKvsVariant * pVar;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("item",KVS_PT_VARIANT,0,pVar)
+ KVSO_PARAMETERS_END(c)
+ if(!m_pDataList)return true;
+ m_pDataList->prepend(new KviKvsVariant(*pVar));
+ return true;
+}
+
+bool KviKvsObject_list::function_append(KviKvsObjectFunctionCall *c)
+{
+ KviKvsVariant * pVar;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("item",KVS_PT_VARIANT,0,pVar)
+ KVSO_PARAMETERS_END(c)
+ if(!m_pDataList)return true;
+ m_pDataList->append(new KviKvsVariant(*pVar));
+ return true;
+}
+
+bool KviKvsObject_list::function_clear(KviKvsObjectFunctionCall *c)
+{
+ if(!m_pDataList)return true;
+ m_pDataList->clear();
+ return true;
+}
+
+inline int kvi_compare(const KviKvsVariant * p1,const KviKvsVariant * p2)
+{
+ return p1->compare(p2);
+}
+
+bool KviKvsObject_list::function_sort(KviKvsObjectFunctionCall *c)
+{
+ if(!m_pDataList)return true;
+ m_pDataList->sort();
+ return true;
+}
+
+bool KviKvsObject_list::function_isEmpty(KviKvsObjectFunctionCall *c)
+{
+ if(!m_pDataList)
+ {
+ c->returnValue()->setBoolean(true);
+ return true;
+ }
+ c->returnValue()->setBoolean(m_pDataList->isEmpty());
+ return true;
+}
+
+bool KviKvsObject_list::function_count(KviKvsObjectFunctionCall *c)
+{
+ if(!m_pDataList)
+ {
+ c->returnValue()->setInteger(0);
+ return true;
+ }
+ c->returnValue()->setInteger(m_pDataList->count());
+ return true;
+}
+
diff --git a/src/modules/objects/class_list.h b/src/modules/objects/class_list.h
new file mode 100644
index 00000000..41d2816e
--- /dev/null
+++ b/src/modules/objects/class_list.h
@@ -0,0 +1,64 @@
+#ifndef _CLASS_LIST_H_
+#define _CLASS_LIST_H_
+//=========================================================================================
+//
+// File : class_list.h
+// Creation date : Wed Sep 09 2000 21:07:01 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=========================================================================================
+
+#include "kvi_settings.h"
+#include "kvi_string.h"
+#include "kvi_pointerlist.h"
+#include "kvi_kvs_variant.h"
+#include "object_macros.h"
+
+
+class KviKvsObject_list : public KviKvsObject
+{
+public:
+ KVSO_DECLARE_OBJECT(KviKvsObject_list)
+protected:
+ KviPointerList<KviKvsVariant> * m_pDataList;
+protected:
+ KviPointerList<KviKvsVariant> * dataList() const { return m_pDataList; };
+public:
+ bool function_count(KviKvsObjectFunctionCall *c);
+ bool function_isEmpty(KviKvsObjectFunctionCall *c);
+ bool function_clear(KviKvsObjectFunctionCall *c);
+ bool function_append(KviKvsObjectFunctionCall *c);
+ bool function_prepend(KviKvsObjectFunctionCall *c);
+ bool function_insert(KviKvsObjectFunctionCall *c);
+ bool function_at(KviKvsObjectFunctionCall *c);
+ bool function_remove(KviKvsObjectFunctionCall *c);
+ bool function_removeFirst(KviKvsObjectFunctionCall *c);
+ bool function_removeLast(KviKvsObjectFunctionCall *c);
+ bool function_removeCurrent(KviKvsObjectFunctionCall *c);
+ bool function_moveFirst(KviKvsObjectFunctionCall *c);
+ bool function_moveNext(KviKvsObjectFunctionCall *c);
+ bool function_movePrev(KviKvsObjectFunctionCall *c);
+ bool function_moveLast(KviKvsObjectFunctionCall *c);
+ bool function_eof(KviKvsObjectFunctionCall *c);
+ bool function_current(KviKvsObjectFunctionCall *c);
+ bool function_sort(KviKvsObjectFunctionCall *c);
+};
+
+
+#endif //_CLASS_LIST_H_
diff --git a/src/modules/objects/class_listbox.cpp b/src/modules/objects/class_listbox.cpp
new file mode 100644
index 00000000..111f7952
--- /dev/null
+++ b/src/modules/objects/class_listbox.cpp
@@ -0,0 +1,390 @@
+//vim: ts=8
+// File : class_listbox.cpp
+// Creation date : Sat Oct 2 03:40:28 CET 2004 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+#include "kvi_error.h"
+#include "kvi_locale.h"
+#include "kvi_debug.h"
+
+
+#include "kvi_tal_listbox.h"
+
+#include "class_list.h"
+#include "class_listbox.h"
+
+/*
+ @doc: listbox
+ @keyterms:
+ listbox object class
+ @title:
+ listbox class
+ @type:
+ class
+ @short:
+ A widget displaying a list of items
+ @inherits:
+ [class]object[/class]
+ [class]widget[/class]
+ @description:
+ The listbox class is a widget displaying a list of string items.[br]
+ The listbox can operate in four selection modes: single, multi, extended
+ and none. In the "single" mode only one item can be selected at a time
+ and that item is also the current one. In the "multi" mode multiple
+ items can be selected and unselected and the current item may or may not
+ be one of the selected items. In the "extended" mode multiple items
+ can be selected but they must be selected in a single mouse action
+ or by keeping the shift button pressed while clicking on the item.
+ In this mode the current item is always one of the selected items.[br]
+ In the "none" mode no items can be selected and the current item
+ may be any item in the list.[br]
+ In most situations you will operate the listbox in "single" mode
+ (and this is the default mode set at widget creation).
+ @functions:
+ !fn: $setSelectionMode(<selection_mode:string>)
+ Sets the current selection mode specified by the parameter <mode>
+ that can be one of the following string:[br]
+ "single" : only one item can be selected at a time[br]
+ "multi" : multiple items can be selected at a time[br]
+ "extended" : multiple items can be selected but only in a single mouse interaction[br]
+ "none" : no items can be selected[br]
+ The default mode is "single"
+ !fn: <string> $selectionMode()
+ Returns the current selection mode
+ !fn: $insertItem(<text:string>, <index:uint>)
+ Inserts a text item at position <index>. If index is negative or
+ not specified the item is appended.
+ !fn: $changeItem(<text:string>, <index:uint>)
+ Changes text of item at <index> to <text>.
+ !fn: $removeItem(<index:uindex>)
+ Removes item at given index.
+ !fn: $count()
+ Returns number of items in the widget.
+ !fn: <string> $currentText()
+ Returns the text of the currently selected item.
+ !fn: <integer> $currentItem()
+ Returns index of current item or -1 if no item is current.
+ !fn: $textAt(<index:integer>)
+ Returns item at given index.
+ !fn: $setCurrentItem(<index:integer>)
+ Sets the current listbox item.
+ !fn: $clear()
+ Removes all the items
+ !fn: <boolean> $isSelected(<index:integer>)
+ Returns 1 if the item at <index> is selected and 0 otherwise
+ !fn: $setSelected(<index:integer>,<bSelected:boolean>)
+ Changes the selection status of the item at <index> to the value
+ specified by <bSelected>. If <bSelected> is 1 the item is selected,
+ if <bSelected> is 0 the item is unselected.
+ !fn: $selectionChangeEvent()
+ This function is called by KVIrc when the selection in the listbox changes.
+ !fn: $currentItemChangeEvent()
+ This function is called by KVIrc when the current item changes.
+ !fn: <index:integer> $onItemEvent()
+ This function is called by KVIrc when the current item pointed by the mouse changes and gives in $0 the item index.
+ !fn: <array:x,y,width,height> $itemRect(<item:index>)
+ Returns the rectangle on the screen that item occupies, or an invalid rectangle if item is 0 or is not currently visible.
+
+ @signals:
+ !sg: <string> $currentItemChange()
+ This signal is emitted by the default implementation of [classfnc]$currentItemChangeEvent[/classfnc]().[br]
+ !sg: <string> $onItem()
+ This signal is emitted by the default implementation of [classfnc]$onItemEvent[/classfnc]().[br]
+
+ */
+
+
+KVSO_BEGIN_REGISTERCLASS(KviKvsObject_listbox,"listbox","widget")
+ KVSO_REGISTER_HANDLER(KviKvsObject_listbox,"insertItem", functioninsertItem)
+ KVSO_REGISTER_HANDLER(KviKvsObject_listbox,"changeItem", functionchangeItem)
+ KVSO_REGISTER_HANDLER(KviKvsObject_listbox,"removeItem", functionremoveItem)
+ KVSO_REGISTER_HANDLER(KviKvsObject_listbox,"clear", functionclear)
+ KVSO_REGISTER_HANDLER(KviKvsObject_listbox,"count", functioncount)
+ KVSO_REGISTER_HANDLER(KviKvsObject_listbox,"currentText", functioncurrentText)
+ KVSO_REGISTER_HANDLER(KviKvsObject_listbox,"currentItem", functioncurrentItem)
+ KVSO_REGISTER_HANDLER(KviKvsObject_listbox,"textAt", functiontextAt);
+ KVSO_REGISTER_HANDLER(KviKvsObject_listbox,"itemAt", functionitemAt);
+ KVSO_REGISTER_HANDLER(KviKvsObject_listbox,"itemRect", functionitemRect);
+ KVSO_REGISTER_HANDLER(KviKvsObject_listbox,"setCurrentItem", functionsetCurrentItem);
+
+
+ KVSO_REGISTER_HANDLER(KviKvsObject_listbox,"setSelectionMode",functionsetSelectionMode);
+ KVSO_REGISTER_HANDLER(KviKvsObject_listbox,"selectionMode",functionselectionMode);
+ KVSO_REGISTER_HANDLER(KviKvsObject_listbox,"setSelected",functionsetSelected);
+ KVSO_REGISTER_HANDLER(KviKvsObject_listbox,"isSelected",functionisSelected);
+ KVSO_REGISTER_HANDLER(KviKvsObject_listbox,"currentItemChangeEvent",functioncurrentItemChangeEvent);
+ KVSO_REGISTER_HANDLER(KviKvsObject_listbox,"onItemEvent",functiononItemEvent);
+
+
+ KVSO_REGISTER_STANDARD_NOTHINGRETURN_HANDLER(KviKvsObject_listbox,"selectionChangeEvent")
+
+
+KVSO_END_REGISTERCLASS(KviKvsObject_listbox)
+
+KVSO_BEGIN_CONSTRUCTOR(KviKvsObject_listbox,KviKvsObject_widget)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_listbox)
+
+
+KVSO_BEGIN_DESTRUCTOR(KviKvsObject_listbox)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_listbox)
+
+bool KviKvsObject_listbox::init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams)
+{
+ KviTalListBox * b = new KviTalListBox(parentScriptWidget());
+ b->setSelectionMode(KviTalListBox::Single);
+ connect(b,SIGNAL(selectionChanged()),this,SLOT(selectionChanged()));
+ connect(b,SIGNAL(currentChanged(KviTalListBoxItem *)),this,SLOT(currentItemChanged(KviTalListBoxItem *)));
+
+ connect(b,SIGNAL(onItem(KviTalListBoxItem *)),this,SLOT(onItem(KviTalListBoxItem *)));
+
+ setObject(b,true);;
+ return true;
+}
+
+bool KviKvsObject_listbox::functioninsertItem(KviKvsObjectFunctionCall *c)
+{
+ kvs_int_t iIndex;
+ QString szItem;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("text",KVS_PT_STRING,0,szItem)
+ KVSO_PARAMETER("index",KVS_PT_INT,KVS_PF_OPTIONAL,iIndex)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ ((KviTalListBox *)widget())->insertItem(szItem, iIndex);
+ return true;
+}
+bool KviKvsObject_listbox::functionclear(KviKvsObjectFunctionCall *c)
+{
+ if (widget()) ((KviTalListBox *)widget())->clear();
+ return true;
+}
+bool KviKvsObject_listbox::functionchangeItem(KviKvsObjectFunctionCall *c)
+{
+
+ kvs_uint_t uIndex,cnt;
+ QString szText;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("text",KVS_PT_STRING,0,szText)
+ KVSO_PARAMETER("index",KVS_PT_UNSIGNEDINTEGER,0,uIndex)
+ KVSO_PARAMETERS_END(c)
+ if(!widget()) return true;
+ if (szText.isEmpty()) c->warning(__tr2qs("No string parameter given - using empty string"));
+ if(uIndex >= (cnt = ((KviTalListBox *)widget())->count()))
+ {
+ c->warning(__tr2qs("Item index [%d] is too big - defaulting to " \
+ "$count() - 1 [%d]"), uIndex, cnt);
+ uIndex = cnt - 1;
+ }
+
+ ((KviTalListBox *)widget())->changeItem(szText, uIndex);
+
+ return true;
+
+}
+bool KviKvsObject_listbox::functionremoveItem(KviKvsObjectFunctionCall *c)
+{
+
+ kvs_uint_t uIndex,cnt;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("index",KVS_PT_UNSIGNEDINTEGER,0,uIndex)
+ KVSO_PARAMETERS_END(c)
+ if(!widget()) return true;
+ if(uIndex >= (cnt = ((KviTalListBox *)widget())->count()))
+ {
+ c->warning(__tr2qs("Item index [%d] is too big - defaulting to " \
+ "$count() - 1 [%d]"), uIndex, cnt);
+ uIndex = cnt - 1;
+ }
+
+ ((KviTalListBox *)widget())->removeItem(uIndex);
+
+ return true;
+
+}
+
+bool KviKvsObject_listbox::functioncount(KviKvsObjectFunctionCall *c)
+{
+ if (widget()) c->returnValue()->setInteger(((KviTalListBox *)widget())->count());
+ return true;
+}
+bool KviKvsObject_listbox::functioncurrentText(KviKvsObjectFunctionCall *c)
+{
+ if (widget()) c->returnValue()->setString(((KviTalListBox *)widget())->currentText().local8Bit().data());
+ return true;
+}
+bool KviKvsObject_listbox::functioncurrentItem(KviKvsObjectFunctionCall *c)
+{
+ if (widget()) c->returnValue()->setInteger(((KviTalListBox *)widget())->currentItem());
+ return true;
+}
+
+bool KviKvsObject_listbox::functiontextAt(KviKvsObjectFunctionCall *c)
+{
+
+ kvs_uint_t uIndex;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("index",KVS_PT_UNSIGNEDINTEGER,0,uIndex)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ c->returnValue()->setString(((KviTalListBox *)widget())->text(uIndex));
+ return true;
+}
+bool KviKvsObject_listbox::functionsetCurrentItem(KviKvsObjectFunctionCall *c)
+{
+ kvs_uint_t uIndex;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("index",KVS_PT_UNSIGNEDINTEGER,0,uIndex)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ ((KviTalListBox *)widget())->setCurrentItem(uIndex);
+ return true;
+}
+bool KviKvsObject_listbox::functionsetSelectionMode(KviKvsObjectFunctionCall *c)
+{
+ QString szMode;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("selection_mode",KVS_PT_STRING,0,szMode)
+ KVSO_PARAMETERS_END(c)
+ if(!widget()) return true;
+ KviTalListBox::SelectionMode iMode = KviTalListBox::Single;
+
+ if(KviQString::equalCI(szMode,"single")) iMode = KviTalListBox::Single;
+
+ else if(KviQString::equalCI(szMode,"multi")) iMode = KviTalListBox::Multi;
+
+ else if(KviQString::equalCI(szMode,"extended")) iMode = KviTalListBox::Extended;
+
+ else if(KviQString::equalCI(szMode,"none")) iMode = KviTalListBox::NoSelection;
+
+ else c->warning(__tr2qs("Invalid selection mode '%Q' assuming single"),&szMode);
+ ((KviTalListBox *)widget())->setSelectionMode(iMode);
+
+ return true;
+}
+bool KviKvsObject_listbox::functionselectionMode(KviKvsObjectFunctionCall *c)
+{
+
+ if(!widget()) return true;
+ switch(((KviTalListBox *)widget())->selectionMode())
+ {
+ case KviTalListBox::Single: c->returnValue()->setString("single"); break;
+ case KviTalListBox::Multi: c->returnValue()->setString("multi"); break;
+ case KviTalListBox::Extended: c->returnValue()->setString("extended"); break;
+ case KviTalListBox::NoSelection: c->returnValue()->setString("none"); break;
+ default: c->returnValue()->setString("single"); break;
+ }
+ return true;
+}
+
+bool KviKvsObject_listbox::functionisSelected(KviKvsObjectFunctionCall *c)
+{
+
+ kvs_uint_t uIndex;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("index",KVS_PT_UNSIGNEDINTEGER,0,uIndex)
+ KVSO_PARAMETERS_END(c)
+ if(widget())c->returnValue()->setBoolean(((KviTalListBox *)widget())->isSelected(uIndex));
+ return true;
+}
+bool KviKvsObject_listbox::functionsetSelected(KviKvsObjectFunctionCall *c)
+{
+ bool bSel;
+ kvs_uint_t uIndex;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("index",KVS_PT_UNSIGNEDINTEGER,0,uIndex)
+ KVSO_PARAMETER("benabled",KVS_PT_BOOLEAN,0,bSel)
+ KVSO_PARAMETERS_END(c)
+ if(widget()) ((KviTalListBox *)widget())->setSelected(uIndex,bSel);
+ return true;
+}
+bool KviKvsObject_listbox::functionitemAt(KviKvsObjectFunctionCall *c)
+{
+ kvs_uint_t uX,uY;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("uX",KVS_PT_UNSIGNEDINTEGER,0,uX)
+ KVSO_PARAMETER("uY",KVS_PT_UNSIGNEDINTEGER,0,uY)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ c->returnValue()->setInteger(((KviTalListBox *)widget())->index(((KviTalListBox *)widget())->itemAt(QPoint(uX,uY))));
+ return true;
+}
+
+bool KviKvsObject_listbox::functioncurrentItemChangeEvent(KviKvsObjectFunctionCall *c)
+{
+ emitSignal("currentItemChange",c,c->params());
+
+ return true;
+}
+
+void KviKvsObject_listbox::selectionChanged()
+{
+ KviKvsVariantList *params=0;
+ callFunction(this,"selectionChangeEvent",0,0);
+}
+
+void KviKvsObject_listbox::currentItemChanged(KviTalListBoxItem *item)
+{
+ if (!item) callFunction(this,"currentItemChangeEvent",0,0);
+ else
+ {
+ KviKvsVariantList params(new KviKvsVariant(item->text()));
+ callFunction(this,"currentItemChangeEvent",0,&params);
+ }
+
+}
+bool KviKvsObject_listbox::functiononItemEvent(KviKvsObjectFunctionCall *c)
+{
+ emitSignal("onItem",c,c->params());
+
+ return true;
+}
+
+void KviKvsObject_listbox::onItem(KviTalListBoxItem *item)
+{
+ KviTalListBox *lbx = (KviTalListBox *)(item->listBox());
+ KviKvsVariantList params(new KviKvsVariant((kvs_int_t)lbx->index(item)));
+ callFunction(this,"onItemEvent",0,&params);
+}
+
+
+bool KviKvsObject_listbox::functionitemRect(KviKvsObjectFunctionCall *c)
+{
+kvs_uint_t uIndex;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("uIndex",KVS_PT_UNSIGNEDINTEGER,0,uIndex)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ {
+ QRect rect=((KviTalListBox *)widget())->itemRect(((KviTalListBox *)widget())->item(uIndex));
+ KviKvsArray * a = new KviKvsArray();
+ a->set(0,new KviKvsVariant((kvs_int_t)rect.left()));
+ a->set(1,new KviKvsVariant((kvs_int_t)rect.top()));
+ a->set(2,new KviKvsVariant((kvs_int_t)rect.width()));
+ a->set(3,new KviKvsVariant((kvs_int_t)rect.height()));
+ c->returnValue()->setArray(a);
+ }
+ return true;
+}
+
+
+#include "m_class_listbox.moc"
diff --git a/src/modules/objects/class_listbox.h b/src/modules/objects/class_listbox.h
new file mode 100644
index 00000000..471337fd
--- /dev/null
+++ b/src/modules/objects/class_listbox.h
@@ -0,0 +1,70 @@
+#ifndef _CLASS_LISTBOX_H_
+#define _CLASS_LISTBOX_H_
+
+//vim: ts=8
+// File : class_listbox.h
+// Creation date : Sat Oct 2 03:40:28 CET 2004 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+#include "class_widget.h"
+
+class KviTalListBox;
+class KviTalListBoxItem;
+
+#include "object_macros.h"
+
+class KviKvsObject_listbox: public KviKvsObject_widget
+{
+ Q_OBJECT
+public:
+ KVSO_DECLARE_OBJECT(KviKvsObject_listbox)
+public:
+ QWidget * widget() { return (QWidget *)object(); };
+protected:
+ virtual bool init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams);
+
+
+ bool functioninsertItem(KviKvsObjectFunctionCall *c);
+ bool functionchangeItem(KviKvsObjectFunctionCall *c);
+ bool functionremoveItem(KviKvsObjectFunctionCall *c);
+ bool functioncount(KviKvsObjectFunctionCall *c);
+ bool functioncurrentText(KviKvsObjectFunctionCall *c);
+ bool functioncurrentItem(KviKvsObjectFunctionCall *c);
+ bool functiontextAt(KviKvsObjectFunctionCall *c);
+ bool functionsetCurrentItem(KviKvsObjectFunctionCall *c);
+ bool functionclear(KviKvsObjectFunctionCall *c);
+ bool functionsetSelectionMode(KviKvsObjectFunctionCall *c);
+ bool functionselectionMode(KviKvsObjectFunctionCall *c);
+ bool functionsetSelected(KviKvsObjectFunctionCall *c);
+ bool functionisSelected(KviKvsObjectFunctionCall *c);
+ bool functioncurrentItemChangeEvent(KviKvsObjectFunctionCall *c);
+ bool functiononItemEvent(KviKvsObjectFunctionCall *c);
+
+ bool functionitemAt(KviKvsObjectFunctionCall *c);
+ bool functionitemRect(KviKvsObjectFunctionCall *c);
+protected slots:
+ void selectionChanged();
+ void currentItemChanged(KviTalListBoxItem *);
+ void onItem(KviTalListBoxItem *);
+};
+
+
+#endif // !_CLASS_COMBOBOX_H_
diff --git a/src/modules/objects/class_listview.cpp b/src/modules/objects/class_listview.cpp
new file mode 100644
index 00000000..f571788c
--- /dev/null
+++ b/src/modules/objects/class_listview.cpp
@@ -0,0 +1,557 @@
+//=================================================================================
+//
+// File : class_listview.cpp
+// Creation date : Fri Jan 28 14:21:48 CEST 2005
+// by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2006 Szymon Stefanek (pragma at kvirc dot net)
+// Copyright (C) 2005-2006 Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
+//
+// 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 opinion) 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.
+//
+//=================================================================================
+
+
+#include "kvi_tal_listview.h"
+#ifdef COMPILE_USE_QT4
+#include <q3header.h>
+#include <qevent.h>
+#else
+#include <qheader.h>
+#endif
+#include "class_listview.h"
+#include "kvi_error.h"
+#include "kvi_debug.h"
+
+#include "kvi_locale.h"
+#include "kvi_iconmanager.h"
+
+
+
+/*
+ @doc: listview
+ @keyterms:
+ listview widget class
+ @title:
+ listview class
+ @type:
+ class
+ @short:
+ A listview class
+ @inherits:
+ [class]widget[/class]
+ @description:
+ It can display and control a hierarchy of multi-column items, and provides the ability to add new items at any time.
+ The items are added by creating children [class]listviewitem[/class] objects: simply allocating them with $new
+ will add the items to the listview and simply deleting them will remove them.
+ Allocating a [class]listviewitem[/class] item2 as a child of item1 will insert it to the same listview creating
+ a subtree of items spannig from item1. The subtree can be opened or closed by a simple click either
+ on the parent item or on the little plus sign on the side of it (when [classfnc:listview]$setRootIsDecorated[/classfnc]
+ is set to $true. The listview can be in Single, Multi, Extended or NoSelection selection mode.
+ In single selection mode there can be only one selected item at a time and the selected item is also
+ the current item (this mode is the default). In Multi and Extended selection mode there can be multiple selected items
+ and the current item is one of them. The difference between Multi and Extended is in the way
+ that items can be selected by the mouse actions: experiment with the two modes :).
+ The NoSelection mode has obviously no selection at all.
+ @functions:
+ !fn: $addColumn(<text_label:string> <width:unsigned integer>)
+ Adds a width pixels wide column with the column header label to the list view.
+
+ !fn: $setSorting(<column:integer>,<bAscending:boolean>)
+ Sets the list view to be sorted by column column in ascending order if ascending is 1 or descending order if it is FALSE.
+ If column is -1, sorting is disabled and the user cannot sort columns by clicking on the column headers
+
+ !fn: $hideListViewHeader()
+ Hide the listview column header.
+
+ !fn: $showListViewHeader()
+ Show the listview column header.
+
+ !fn: <boolean> $isListViewHeaderVisible()
+ Returns '1' if the listview header is currently visible. Otherwise this function returns '0'.
+
+ !fn: $setAllColumnsShowFocus(<bAllColumnsShowFocus:boolean>)
+ When the argument is $true, causes the listview to display the focus and selection
+ by highlighting all the columns of the item. When the argument is $false then
+ only the first column is selected/highlighted.
+
+ !fn: $setSelectionMode(<mode:string>)
+ Sets the selection mode for this listview. <mode> can be one of "Single","NoSelection","Multi" or "Extended".
+
+ !fn: <listviewitem> $selectedItem()
+ Returns the currently selected [class]listviewitem[/class] or $null if no items are selected.
+ This function works only if the list view is in single selection mode.
+
+ !fn: <listviewitem> $currentItem()
+ Returns the current [class]listviewitem[/class] or $null if no item is current at the moment.
+
+ !fn: <listviewitem> $firstChild()
+ Returns the first child [class]listviewitem[/class] of this listview or $null if there are no items at all.
+
+ !fn: $clickEvent(<item:object>)
+ This function is called when the user clicks in the list view.
+ In its argument the [class]listviewitem[/class] object clicked or 0 if the user didn't click on an item.[br]
+ The default implementation emits the [classfnc]$clicked[/classfnc]() signal.
+
+ !fn: $selectionChangedEvent(<item:object>)
+ This event handle whenever the set of selected items has changed.
+ The argument is the newly selected item if the listview is in single selection mode.[br]
+ When the listview is in Multi or Extended selection mode then item is always $null.[br]
+ The default implementation emits the [classfnc]$selectionChanged[/classfnc]() signal.
+
+ !fn: $currentChangedEvent(<item:object>)
+ This event are called whenever the current item has changed.
+ In its argument is the newly selected item or 0 if the change made no item current.[br]
+ The default implementation emits the [classfnc]$currentChanged[/classfnc]() signal.
+
+ !fn: $returnPressedEvent(<item:object>)
+ This function is called by the framework when the enter key is pressed.[br]
+ In its arument the currrent item.[br]
+ The default implementation emits the [classfnc]$returnPressed[/classfnc]() signal.
+
+ !fn: $spacePressedEvent(<item:object>)
+ This function is called by the framework when the space key is pressed.[br]
+ In its arument the currrent item.[br]
+ The default implementation emits the [classfnc]$spacePressed[/classfnc]() signal.
+
+ !fn: $onItemEvent(<item:object)
+ This event is called by framwork when the user moves the mouse cursor onto item.
+ The default implementation emits the [classfnc]$onItem[/classfnc]() signal.
+
+ !fn: $itemExpandedEvent(<item:object>)
+ This event is called when an item has been expanded, i.e. when the children of item are shown.
+ The default implementation emits the [classfnc]$expanded[/classfnc]() signal.
+
+ !fn: $itemCollapsedEvent(<item:object>)
+ This event is called when an item has been collapsed, i.e. when the children of item are hidden.
+ The default implementation emits the [classfnc]$collapsed[/classfnc]() signal.
+
+ !fn: $itemRenamedEvent(<item:object>,<col:integer>,<text:string>)
+ This event is called when the item has been renamed in text, e.g. by in in-place renaming, in column col.[br]
+ The default implementation emits the [classfnc]$itemRenamed[/classfnc]() signal.
+
+ !fn: $rightButtonClickEvent(<item:object>,<x:integer>,>y:integer>)
+ This signal is emitted when the right button is clicked.[br]
+ The arguments are the relevant item (may be 0), the point in global coordinates and the relevant column (or -1 if the click was outside the list).
+ The default implementation emits the [classfnc]$rightButtonClicked[/classfnc]() signal.
+ @signals:
+ !sg: $clicked()
+ This signal is emitted by the default implementation of [classfnc]$clickEvent[/classfnc]().
+ !sg: $selectionChanged()
+ This signal is emitted by the default implementation of [classfnc]$selectionChangedEvent[/classfnc]().
+ !sg: $currentChanged()
+ This signal is emitted by the default implementation of [classfnc]$currentChangedEvent[/classfnc]().
+ !sg: $returnPressed()
+ This signal is emitted by the default implementation of [classfnc]$returnPressedEvent[/classfnc]().
+ !sg: $spacePressed()
+ This signal is emitted by the default implementation of [classfnc]$spacePredssedEvent[/classfnc]().
+ !sg: $onItem()
+ This signal is emitted by the default implementation of [classfnc]$onItemEvent[/classfnc]().
+ !sg: $itemExpanded()
+ This signal is emitted by the default implementation of [classfnc]$itemExpandedEvent[/classfnc]().
+ !sg: $itemCollapsed()
+ This signal is emitted by the default implementation of [classfnc]$itemCollapsedEvent[/classfnc]().
+ !sg: $itemRenamed()
+ This signal is emitted by the default implementation of [classfnc]$itemRenamedEvent[/classfnc]().
+ !sg: $rightButtonClicked()
+ This signal is emitted by the default implementation of [classfnc]$rightButtonClickedEvent[/classfnc]().
+
+
+*/
+
+//---------------------------------------------------------------------------------
+
+KVSO_BEGIN_REGISTERCLASS(KviKvsObject_listview,"listview","widget")
+
+ KVSO_REGISTER_HANDLER(KviKvsObject_listview,"addColumn",function_addColumn)
+ KVSO_REGISTER_HANDLER(KviKvsObject_listview,"setColumnText",function_setColumnText)
+ KVSO_REGISTER_HANDLER(KviKvsObject_listview,"setSorting",function_setSorting)
+ KVSO_REGISTER_HANDLER(KviKvsObject_listview,"setRootIsDecorated",function_setRootIsDecorated)
+ KVSO_REGISTER_HANDLER(KviKvsObject_listview,"setAllColumnsShowFocus",function_setAllColumnsShowFocus)
+ KVSO_REGISTER_HANDLER(KviKvsObject_listview,"clear",function_clear)
+ KVSO_REGISTER_HANDLER(KviKvsObject_listview,"selectedItem",function_selectedItem)
+ KVSO_REGISTER_HANDLER(KviKvsObject_listview,"currentItem",function_currentItem)
+ KVSO_REGISTER_HANDLER(KviKvsObject_listview,"setSelectionMode",function_setSelectionMode)
+ KVSO_REGISTER_HANDLER(KviKvsObject_listview,"listViewHeaderIsVisible",function_listViewHeaderIsVisible)
+
+
+ KVSO_REGISTER_HANDLER(KviKvsObject_listview,"hideListViewHeader",function_hideListViewHeader)
+ KVSO_REGISTER_HANDLER(KviKvsObject_listview,"showListViewHeader",function_showListViewHeader)
+ KVSO_REGISTER_HANDLER(KviKvsObject_listview,"firstChild",function_firstChild)
+ KVSO_REGISTER_HANDLER(KviKvsObject_listview,"selectionChangedEvent",function_selectionChangedEvent);
+ KVSO_REGISTER_HANDLER(KviKvsObject_listview,"currentChangedEvent",function_currentChangedEvent);
+ KVSO_REGISTER_HANDLER(KviKvsObject_listview,"returnPressedEvent",function_returnPressedEvent);
+ KVSO_REGISTER_HANDLER(KviKvsObject_listview,"spacePressedEvent",function_spacePressedEvent);
+ KVSO_REGISTER_HANDLER(KviKvsObject_listview,"onItemEvent",function_onItemEvent);
+ KVSO_REGISTER_HANDLER(KviKvsObject_listview,"itemClickedEvent",function_itemClickedEvent);
+ KVSO_REGISTER_HANDLER(KviKvsObject_listview,"itemExpandedEvent",function_itemExpandedEvent);
+ KVSO_REGISTER_HANDLER(KviKvsObject_listview,"itemCollapsedEvent",function_itemCollapsedEvent);
+ KVSO_REGISTER_HANDLER(KviKvsObject_listview,"itemRenamedEvent",function_itemRenamedEvent);
+ KVSO_REGISTER_HANDLER(KviKvsObject_listview,"rightButtonClickedEvent",function_rightButtonClickedEvent);
+
+ KVSO_REGISTER_STANDARD_NOTHINGRETURN_HANDLER(KviKvsObject_listview,"fileDroppedEvent")
+
+KVSO_END_REGISTERCLASS(KviKvsObject_listview)
+
+KVSO_BEGIN_CONSTRUCTOR(KviKvsObject_listview,KviKvsObject_widget)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_listview)
+
+
+KVSO_BEGIN_DESTRUCTOR(KviKvsObject_listview)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_listview)
+
+bool KviKvsObject_listview::init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams)
+{
+ setObject(new KviKvsMdmListView(parentScriptWidget(),name(),this),true);
+ connect(widget(),SIGNAL(clicked(KviTalListViewItem *)),this,SLOT(slotClicked(KviTalListViewItem *)));
+ connect(widget(),SIGNAL(selectionChanged(KviTalListViewItem *)),this,SLOT(slotSelectionChanged(KviTalListViewItem *)));
+ connect(widget(),SIGNAL(selectionChanged()),this,SLOT(slotMultipleSelectionChanged()));
+ connect(widget(),SIGNAL(currentChanged(KviTalListViewItem *)),this,SLOT(slotCurrentChanged(KviTalListViewItem *)));
+ connect(widget(),SIGNAL(returnPressed(KviTalListViewItem *)),this,SLOT(slotReturnPressed(KviTalListViewItem *)));
+ connect(widget(),SIGNAL(spacePressed(KviTalListViewItem *)),this,SLOT(slotSpacePressed(KviTalListViewItem *)));
+ connect(widget(),SIGNAL(onItem(KviTalListViewItem *)),this,SLOT(slotOnItem(KviTalListViewItem *)));
+ connect(widget(),SIGNAL(expanded(KviTalListViewItem *)),this,SLOT(slotItemExpanded(KviTalListViewItem *)));
+ connect(widget(),SIGNAL(collapsed(KviTalListViewItem *)),this,SLOT(slotItemCollapsed(KviTalListViewItem *)));
+ connect(widget(),SIGNAL(rightButtonClicked(KviTalListViewItem *,const QPoint &,int)),this,SLOT(slotRightButtonClicked(KviTalListViewItem *,const QPoint &,int)));
+ connect(widget(),SIGNAL(itemRenamed(KviTalListViewItem *,int,const QString &)),this,SLOT(slotItemRenamed(KviTalListViewItem *,int,const QString &)));
+ return true;
+}
+
+bool KviKvsObject_listview::function_addColumn(KviKvsObjectFunctionCall *c)
+{
+ QString szLabel;
+ kvs_int_t iW;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("label",KVS_PT_STRING,0,szLabel)
+ KVSO_PARAMETER("width",KVS_PT_INT,0,iW)
+ KVSO_PARAMETERS_END(c)
+ if (widget())
+ ((KviTalListView *)object())->addColumn(szLabel,iW);
+ return true;
+}
+/*
+bool KviKvsObject_listview::function_setAcceptDrops(KviKvsObjectFunctionCall *c)
+{
+ bool bEnable;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bEnable",KVS_PT_BOOLEAN,0,bEnable)
+ KVSO_PARAMETERS_END(c)
+ if (widget())
+ ((KviTalListView *)object())->setAcceptDrops(bEnable);
+ return true;
+}
+*/
+bool KviKvsObject_listview::function_clear(KviKvsObjectFunctionCall *c)
+{
+ if (widget())
+ ((KviTalListView *)object())->clear();
+ return true;
+}
+
+bool KviKvsObject_listview::function_selectedItem(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ c->returnValue()->setHObject(KviKvsObject_listviewitem::itemToHandle(((KviTalListView *)widget())->selectedItem()));
+ else
+ c->returnValue()->setHObject((kvs_hobject_t)0);
+ return true;
+}
+
+bool KviKvsObject_listview::function_firstChild(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ c->returnValue()->setHObject(KviKvsObject_listviewitem::itemToHandle(((KviTalListView *)widget())->firstChild()));
+ else
+ c->returnValue()->setHObject((kvs_hobject_t)0);
+ return true;
+}
+
+bool KviKvsObject_listview::function_currentItem(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ c->returnValue()->setHObject(KviKvsObject_listviewitem::itemToHandle(((KviTalListView *)widget())->currentItem()));
+ else
+ c->returnValue()->setHObject((kvs_hobject_t)0);
+ return true;
+}
+
+bool KviKvsObject_listview::function_setColumnText(KviKvsObjectFunctionCall *c)
+{
+ kvs_int_t uCol;
+ QString szText;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("column",KVS_PT_UNSIGNEDINTEGER,0,uCol)
+ KVSO_PARAMETER("text",KVS_PT_STRING,0,szText)
+ KVSO_PARAMETERS_END(c)
+ if (widget())((KviTalListView *)widget())->setColumnText(uCol,szText);
+ return true;
+}
+
+bool KviKvsObject_listview::function_setSelectionMode(KviKvsObjectFunctionCall *c)
+{
+ QString szMode;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("mode",KVS_PT_NONEMPTYSTRING,0,szMode)
+ KVSO_PARAMETERS_END(c)
+ if(!widget())return true;
+ if(KviQString::equalCI(szMode,"NoSelection"))
+ ((KviTalListView *)widget())->setSelectionMode(KviTalListView::NoSelection);
+ else if(KviQString::equalCI(szMode,"Multi"))
+ ((KviTalListView *)widget())->setSelectionMode(KviTalListView::Multi);
+ else if(KviQString::equalCI(szMode,"Extended"))
+ ((KviTalListView *)widget())->setSelectionMode(KviTalListView::Extended);
+ else if(KviQString::equalCI(szMode,"Single"))
+ ((KviTalListView *)widget())->setSelectionMode(KviTalListView::Single);
+ else c->warning(__tr2qs("Invalid selection mode '%Q'"),&szMode);
+ return true;
+}
+
+bool KviKvsObject_listview::function_setSorting(KviKvsObjectFunctionCall *c)
+{
+ kvs_int_t iCol;
+ bool bEnabled;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("column",KVS_PT_INT,0,iCol)
+ KVSO_PARAMETER("benabled",KVS_PT_BOOL,0,bEnabled)
+ KVSO_PARAMETERS_END(c)
+ if (widget()) ((KviTalListView *)widget())->setSorting(iCol,bEnabled);
+ return true;
+}
+
+
+bool KviKvsObject_listview::function_setRootIsDecorated(KviKvsObjectFunctionCall *c)
+{
+ bool bEnabled;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bEnabled",KVS_PT_BOOL,0,bEnabled)
+ KVSO_PARAMETERS_END(c)
+ if (widget()) ((KviTalListView *)widget())->setRootIsDecorated(bEnabled);
+ return true;
+}
+
+bool KviKvsObject_listview::function_setAllColumnsShowFocus(KviKvsObjectFunctionCall *c)
+{
+ bool bEnabled;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bAllColumnsShowFocus",KVS_PT_BOOL,0,bEnabled)
+ KVSO_PARAMETERS_END(c)
+ if (widget())((KviTalListView *)widget())->setAllColumnsShowFocus(bEnabled);
+ return true;
+}
+
+bool KviKvsObject_listview::function_hideListViewHeader(KviKvsObjectFunctionCall *c)
+{
+// ((KviTalListView *)widget())->header()->hide();
+ return true;
+}
+bool KviKvsObject_listview::function_showListViewHeader(KviKvsObjectFunctionCall *c)
+{
+// ((KviTalListView *)widget())->header()->show();
+ return true;
+}
+bool KviKvsObject_listview::function_listViewHeaderIsVisible(KviKvsObjectFunctionCall *c)
+{
+ c->returnValue()->setBoolean(((KviTalListView *)widget())->header()->isVisible());
+ return true;
+}
+
+bool KviKvsObject_listview::function_itemClickedEvent(KviKvsObjectFunctionCall *c)
+{
+ emitSignal("itemClicked",c,c->params());
+ return true;
+}
+
+void KviKvsObject_listview::slotClicked(KviTalListViewItem * i)
+{
+ KviKvsVariantList params(new KviKvsVariant(KviKvsObject_listviewitem::itemToHandle(i)));
+ callFunction(this,"itemClickedEvent",0,&params);
+}
+
+bool KviKvsObject_listview::function_selectionChangedEvent(KviKvsObjectFunctionCall *c)
+{
+ emitSignal("selectionChanged",c,c->params());
+ return true;
+}
+
+void KviKvsObject_listview::slotSelectionChanged(KviTalListViewItem * i)
+{
+ KviKvsVariantList params(new KviKvsVariant(KviKvsObject_listviewitem::itemToHandle(i)));
+ callFunction(this,"selectionChangedEvent",0,&params);
+}
+
+void KviKvsObject_listview::slotMultipleSelectionChanged()
+{
+ KviKvsVariantList params(new KviKvsVariant((kvs_hobject_t)0));
+ callFunction(this,"selectionChangedEvent",0,&params);
+}
+
+
+bool KviKvsObject_listview::function_currentChangedEvent(KviKvsObjectFunctionCall *c)
+{
+ emitSignal("currentChanged",c,c->params());
+ return true;
+}
+
+void KviKvsObject_listview::slotCurrentChanged(KviTalListViewItem * i)
+{
+ KviKvsVariantList params(new KviKvsVariant(KviKvsObject_listviewitem::itemToHandle(i)));
+ callFunction(this,"currentChangedEvent",0,&params);
+}
+
+
+bool KviKvsObject_listview::function_returnPressedEvent(KviKvsObjectFunctionCall *c)
+{
+ emitSignal("returnPressed",c,c->params());
+ return true;
+}
+
+void KviKvsObject_listview::slotReturnPressed(KviTalListViewItem * i)
+{
+ KviKvsVariantList params(new KviKvsVariant(KviKvsObject_listviewitem::itemToHandle(i)));
+ callFunction(this,"returnPressedEvent",0,&params);
+}
+
+bool KviKvsObject_listview::function_spacePressedEvent(KviKvsObjectFunctionCall *c)
+{
+ emitSignal("spacePressed",c,c->params());
+ return true;
+}
+
+void KviKvsObject_listview::slotSpacePressed(KviTalListViewItem * i)
+{
+ KviKvsVariantList params(new KviKvsVariant(KviKvsObject_listviewitem::itemToHandle(i)));
+ callFunction(this,"spacePressedEvent",0,&params);
+}
+
+bool KviKvsObject_listview::function_onItemEvent(KviKvsObjectFunctionCall *c)
+{
+ emitSignal("onItem",c,c->params());
+ return true;
+}
+
+void KviKvsObject_listview::slotOnItem(KviTalListViewItem * i)
+{
+ KviKvsVariantList params(new KviKvsVariant(KviKvsObject_listviewitem::itemToHandle(i)));
+ callFunction(this,"onItemEvent",0,&params);
+}
+
+
+bool KviKvsObject_listview::function_itemExpandedEvent(KviKvsObjectFunctionCall *c)
+{
+ emitSignal("itemExpanded",c,c->params());
+ return true;
+}
+
+void KviKvsObject_listview::slotItemExpanded(KviTalListViewItem * i)
+{
+ KviKvsVariantList params(new KviKvsVariant(KviKvsObject_listviewitem::itemToHandle(i)));
+ callFunction(this,"itemExpandedEvent",0,&params);
+}
+
+bool KviKvsObject_listview::function_itemCollapsedEvent(KviKvsObjectFunctionCall *c)
+{
+ emitSignal("itemCollapsed",c,c->params());
+ return true;
+}
+
+void KviKvsObject_listview::slotItemCollapsed(KviTalListViewItem * i)
+{
+ KviKvsVariantList params(new KviKvsVariant(KviKvsObject_listviewitem::itemToHandle(i)));
+ callFunction(this,"itemCollapsedEvent",0,&params);
+}
+
+bool KviKvsObject_listview::function_rightButtonClickedEvent(KviKvsObjectFunctionCall *c)
+{
+ emitSignal("rightButtonClicked",c,c->params());
+ return true;
+}
+
+void KviKvsObject_listview::slotRightButtonClicked(KviTalListViewItem * i,const QPoint &coor, int col)
+{
+ KviKvsVariant *xpos=new KviKvsVariant((kvs_int_t)coor.x());
+ KviKvsVariant *ypos=new KviKvsVariant((kvs_int_t)coor.y());
+ KviKvsVariant *column=new KviKvsVariant((kvs_int_t)col);
+ KviKvsVariantList params(new KviKvsVariant(KviKvsObject_listviewitem::itemToHandle(i)),xpos,ypos,column);
+ callFunction(this,"rightButtonClickedEvent",0,&params);
+}
+
+bool KviKvsObject_listview::function_itemRenamedEvent(KviKvsObjectFunctionCall *c)
+{
+ emitSignal("itemRenamed",c,c->params());
+ return true;
+}
+
+void KviKvsObject_listview::slotItemRenamed(KviTalListViewItem *item,int col,const QString & szText)
+{
+ KviKvsVariant *column=new KviKvsVariant((kvs_int_t)col);
+ KviKvsVariant *txt=new KviKvsVariant(szText);
+ KviKvsVariantList params(new KviKvsVariant(KviKvsObject_listviewitem::itemToHandle(item)),column,txt);
+ callFunction(this,"itemRenamedEvent",0,&params);
+}
+void KviKvsObject_listview::fileDropped(QString &szFile,KviTalListViewItem *item)
+{
+ KviKvsVariant *file=new KviKvsVariant(szFile);
+ KviKvsVariantList params(new KviKvsVariant(KviKvsObject_listviewitem::itemToHandle(item)),file);
+ callFunction(this,"fileDroppedEvent",0,&params);
+}
+
+KviKvsMdmListView::KviKvsMdmListView(QWidget * par,const char * name,KviKvsObject_listview *parent)
+:KviTalListView(par)
+{
+ m_pParentScript=parent;
+ setAcceptDrops(true);
+ viewport()->setAcceptDrops( TRUE );
+
+}
+KviKvsMdmListView::~KviKvsMdmListView()
+{
+}
+
+void KviKvsMdmListView::contentsDragEnterEvent( QDragEnterEvent *e )
+{
+ if ( !KviUriDrag::canDecode(e))
+ {
+ e->ignore();
+ return;
+ }
+
+}
+
+
+void KviKvsMdmListView::contentsDropEvent(QDropEvent *e)
+{
+ QStringList list;
+ if(KviUriDrag::decodeLocalFiles(e,list))
+ {
+ if(!list.isEmpty())
+ {
+ QStringList::ConstIterator it = list.begin(); //kewl ! :)
+ for( ; it != list.end(); ++it )
+ {
+ QString tmp = *it; //wow :)
+ #ifndef COMPILE_ON_WINDOWS
+ if(tmp[0] != '/')tmp.prepend("/"); //HACK HACK HACK for Qt bug (?!?)
+ #endif
+ KviTalListViewItem *i = itemAt( contentsToViewport(e->pos()) );
+ m_pParentScript->fileDropped(tmp,i);
+ }
+ }
+ }
+
+}
+#include "m_class_listview.moc"
diff --git a/src/modules/objects/class_listview.h b/src/modules/objects/class_listview.h
new file mode 100644
index 00000000..7849f36c
--- /dev/null
+++ b/src/modules/objects/class_listview.h
@@ -0,0 +1,102 @@
+#ifndef _CLASS_LISTVIEW_H_
+#define _CLASS_LISTVIEW_H_
+//=================================================================================
+//
+// File : class_listview.h
+// Creation date : Fri Jan 28 14:21:48 CEST 2005
+// by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2006 Szymon Stefanek (pragma at kvirc dot net)
+// Copyright (C) 2005-2006 Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
+//
+// 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 opinion) 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.
+//
+//=================================================================================
+
+#include "kvi_tal_listview.h"
+#include "kvi_draganddrop.h"
+#include "class_widget.h"
+#include "class_listviewitem.h"
+
+#include "object_macros.h"
+
+class KviKvsObject_listview : public KviKvsObject_widget
+{
+ Q_OBJECT
+public:
+ KVSO_DECLARE_OBJECT(KviKvsObject_listview)
+
+public:
+ QWidget * widget() { return (QWidget *)object(); };
+ void fileDropped(QString &,KviTalListViewItem *);
+protected:
+ virtual bool init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams);
+
+ bool function_addColumn(KviKvsObjectFunctionCall *c);
+ bool function_setColumnText(KviKvsObjectFunctionCall *c);
+ bool function_takeItem(KviKvsObjectFunctionCall *c);
+ bool function_setSorting(KviKvsObjectFunctionCall *c);
+ bool function_setRootIsDecorated(KviKvsObjectFunctionCall *c);
+ bool function_clear(KviKvsObjectFunctionCall *c);
+ bool function_setAllColumnsShowFocus(KviKvsObjectFunctionCall *c);
+ bool function_itemClickedEvent(KviKvsObjectFunctionCall *c);
+ bool function_selectionChangedEvent(KviKvsObjectFunctionCall *c);
+ bool function_currentChangedEvent(KviKvsObjectFunctionCall *c);
+ bool function_returnPressedEvent(KviKvsObjectFunctionCall *c);
+ bool function_spacePressedEvent(KviKvsObjectFunctionCall *c);
+ bool function_onItemEvent(KviKvsObjectFunctionCall *c);
+ bool function_itemExpandedEvent(KviKvsObjectFunctionCall *c);
+ bool function_itemCollapsedEvent(KviKvsObjectFunctionCall *c);
+ bool function_itemRenamedEvent(KviKvsObjectFunctionCall *c);
+ bool function_rightButtonClickedEvent(KviKvsObjectFunctionCall *c);
+ bool function_selectedItem(KviKvsObjectFunctionCall *c);
+ bool function_currentItem(KviKvsObjectFunctionCall *c);
+ bool function_setSelectionMode(KviKvsObjectFunctionCall *c);
+ bool function_firstChild(KviKvsObjectFunctionCall *c);
+ bool function_listViewHeaderIsVisible(KviKvsObjectFunctionCall *c);
+ bool function_showListViewHeader(KviKvsObjectFunctionCall *c);
+ bool function_hideListViewHeader(KviKvsObjectFunctionCall *c);
+
+ bool function_setAcceptDrops(KviKvsObjectFunctionCall *c);
+
+protected slots:
+ void slotClicked(KviTalListViewItem *);
+ void slotSelectionChanged(KviTalListViewItem *);
+ void slotMultipleSelectionChanged();
+ void slotCurrentChanged(KviTalListViewItem *);
+ void slotReturnPressed(KviTalListViewItem *);
+ void slotSpacePressed(KviTalListViewItem *);
+ void slotOnItem(KviTalListViewItem *);
+ void slotItemExpanded(KviTalListViewItem *);
+ void slotItemCollapsed(KviTalListViewItem *);
+ void slotItemRenamed(KviTalListViewItem *,int,const QString &);
+ void slotRightButtonClicked(KviTalListViewItem * i,const QPoint &coor, int col);
+};
+
+class KviKvsMdmListView : public KviTalListView
+{
+ Q_OBJECT
+public:
+ KviKvsMdmListView(QWidget * par,const char * name,KviKvsObject_listview *);
+
+ virtual ~KviKvsMdmListView();
+protected:
+ KviKvsObject_listview *m_pParentScript;
+ void contentsDropEvent(QDropEvent *e);
+ void contentsDragEnterEvent( QDragEnterEvent *e );
+
+};
+#endif //!_CLASS_LISTVIEW_H_
diff --git a/src/modules/objects/class_listviewitem.cpp b/src/modules/objects/class_listviewitem.cpp
new file mode 100644
index 00000000..31df9020
--- /dev/null
+++ b/src/modules/objects/class_listviewitem.cpp
@@ -0,0 +1,421 @@
+//mdm:
+// File : class_ListViewItem.h
+// Creation date : Thu Feb 1 14:39:48 CEST 2005
+// by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+
+#include "class_listviewitem.h"
+#include "class_pixmap.h"
+#include "kvi_error.h"
+#include "kvi_debug.h"
+
+#include "kvi_locale.h"
+#include "kvi_iconmanager.h"
+
+
+
+/*
+ @doc: listviewitem
+ @keyterms:
+ listview listviewitem class
+ @title:
+ listviewitem class
+ @type:
+ class
+ @short:
+ A listviewitem class
+ @inherits:
+ [class]listviewitem[/class]
+ @description:
+ The listviewitem class implements a list view item.
+ A list view item is a multi-column object capable of displaying itself in a [class]listview[/class].
+ To use this class you must instantiate it with another listviewitem or a [class]listview[/class]
+ as parent. The item will be automatically displayed.
+ You can set the text and a pixmap in each column and you can make it checkable
+ with [classfnc:listviewitem]$setCheckable[/classfnc]().
+ A checkable listviewitem will display a small check mark in the first column.
+ @functions:
+ !fn: $setText(<column:integer>,<text:string>)
+ Sets the text in column column to text, if column is a valid column number and text is different from the existing text.
+
+ !fn: <string> $text(<column:integer>)
+ Returs the text of the specified column.
+
+ !fn: $setPixmap(<column:integer>,<pixmap:hobject or imageID>)
+ Sets the pixmap in column column to pm, if pm is non-null and different from the current pixmap, and if column is non-negative.
+ Pixmap can be a Kvirc imageid, an image file or a [class]pixmap[/class] object.
+
+ !fn: $setRenameEnabled(<col:integer>,<bEnabled:boolean>)
+ If b is TRUE (1), this item can be in-place renamed in the column col by the user; otherwise it cannot be renamed in-place.
+
+ !fn: $setEnabled(<bEnabled:boolean>)
+ Enables or disables the item
+
+ !fn: $isEnabled()
+ Returns $true if this item is enabled and $false otherwise
+
+ !fn: $setOpen(<bOpen:boolean>)
+ Opens or closes the item to show its children items
+
+ !fn: $isOpen()
+ Returns the open state of this item
+
+ !fn: $setCheckable(<bCheckable:boolean>)
+ Makes this item checkable or not. This function should be called immediately
+ after the item creation: changing this property later at runtime may have
+ strange results (like the item being moved inside the list, text disappearing,
+ hidden children etc... don't do it :D ).
+
+ !fn: $isCheckable()
+ Returns $true if this item is checkable and $false otherwise
+
+ !fn: $setChecked(<bChecked:boolean>)
+ Sets this item to be checked or not. [classfnc:listviewitem]$setCheckable[/classfnc]() must
+ have been previously called.
+
+ !fn: $isChecked()
+ Returns the check status of this item. [classfnc:listviewitem]$setCheckable[/classfnc]() must
+ have been previously called.
+
+ !fn: <listviewitem> $firstChild()
+ Returns the first child item of this listviewitem or $null if this item has no children.
+
+ !fn: <listviewitem> $nextSibling()
+ Returns the next sibling item of this listviewitem or $null if there are no sibling items.
+ Next sibling stands for the item at the same tree level coming just after :)
+*/
+
+
+//===========================================================================================
+
+KVSO_BEGIN_REGISTERCLASS(KviKvsObject_listviewitem,"listviewitem","object")
+ KVSO_REGISTER_HANDLER(KviKvsObject_listviewitem,"setText",function_setText)
+ KVSO_REGISTER_HANDLER(KviKvsObject_listviewitem,"text",function_text)
+ KVSO_REGISTER_HANDLER(KviKvsObject_listviewitem,"setPixmap",function_setPixmap);
+ KVSO_REGISTER_HANDLER(KviKvsObject_listviewitem,"setRenameEnabled",function_setRenameEnabled);
+ KVSO_REGISTER_HANDLER(KviKvsObject_listviewitem,"setEnabled",function_setEnabled);
+ KVSO_REGISTER_HANDLER(KviKvsObject_listviewitem,"isEnabled",function_isEnabled);
+ KVSO_REGISTER_HANDLER(KviKvsObject_listviewitem,"setOpen",function_setOpen);
+ KVSO_REGISTER_HANDLER(KviKvsObject_listviewitem,"isOpen",function_isOpen);
+ KVSO_REGISTER_HANDLER(KviKvsObject_listviewitem,"setCheckable",function_setCheckable);
+ KVSO_REGISTER_HANDLER(KviKvsObject_listviewitem,"isCheckable",function_isCheckable);
+ KVSO_REGISTER_HANDLER(KviKvsObject_listviewitem,"setChecked",function_setChecked);
+ KVSO_REGISTER_HANDLER(KviKvsObject_listviewitem,"isChecked",function_isChecked);
+ KVSO_REGISTER_HANDLER(KviKvsObject_listviewitem,"firstChild",function_firstChild);
+ KVSO_REGISTER_HANDLER(KviKvsObject_listviewitem,"nextSibling",function_nextSibling);
+KVSO_END_REGISTERCLASS(KviKvsObject_listviewitem)
+
+
+KVSO_BEGIN_CONSTRUCTOR(KviKvsObject_listviewitem,KviKvsObject)
+
+ m_pListViewItem = 0;
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_listviewitem)
+
+
+KVSO_BEGIN_DESTRUCTOR(KviKvsObject_listviewitem)
+
+ if(m_pListViewItem)delete m_pListViewItem;
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_listviewitem)
+
+bool KviKvsObject_listviewitem::init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams)
+{
+ if (!parentObject())
+ {
+ pContext->error(__tr2qs("The listviewitem cannot be parentless"));
+ return false;
+ }
+ if(parentObject()->inherits("KviKvsObject_listviewitem"))
+ {
+ m_pListViewItem = new KviKvsMdmStandardListViewItem(this,((KviKvsObject_listviewitem *)parentObject())->m_pListViewItem);
+ } else {
+ if(parentObject()->inherits("KviKvsObject_listview"))
+ m_pListViewItem = new KviKvsMdmStandardListViewItem(this,((KviTalListView *)parentScriptWidget()));
+ else {
+ pContext->error(__tr2qs("The parent of the listviewitem must be either another listviewitem or a listview"));
+ return false;
+ }
+ }
+ return true;
+}
+
+void KviKvsObject_listviewitem::childDestroyed()
+{
+ if(m_pListViewItem == 0)return;
+ m_pListViewItem = 0;
+ die();
+}
+
+KviKvsMdmStandardListViewItem::KviKvsMdmStandardListViewItem(KviKvsObject_listviewitem * ob,KviTalListView * par)
+:KviTalListViewItem(par), m_pMasterObject(ob)
+{
+}
+
+KviKvsMdmStandardListViewItem::KviKvsMdmStandardListViewItem(KviKvsObject_listviewitem * ob,KviTalListViewItem * par)
+:KviTalListViewItem(par), m_pMasterObject(ob)
+{
+}
+
+KviKvsMdmStandardListViewItem::~KviKvsMdmStandardListViewItem()
+{
+ if(m_pMasterObject)m_pMasterObject->childDestroyed();
+}
+
+
+
+KviKvsMdmCheckListViewItem::KviKvsMdmCheckListViewItem(KviKvsObject_listviewitem * ob,KviTalListView * par)
+:KviTalCheckListItem(par,QString::null,KviTalCheckListItem::CheckBox), m_pMasterObject(ob)
+{
+}
+
+KviKvsMdmCheckListViewItem::KviKvsMdmCheckListViewItem(KviKvsObject_listviewitem * ob,KviTalListViewItem * par)
+:KviTalCheckListItem(par,QString::null,KviTalCheckListItem::CheckBox), m_pMasterObject(ob)
+{
+}
+
+KviKvsMdmCheckListViewItem::~KviKvsMdmCheckListViewItem()
+{
+ if(m_pMasterObject)m_pMasterObject->childDestroyed();
+}
+
+
+kvs_hobject_t KviKvsObject_listviewitem::itemToHandle(KviTalListViewItem * it)
+{
+ if(!it)return (kvs_hobject_t)0;
+ KviKvsObject_listviewitem * pObject;
+ if(it->rtti() == 1)pObject = ((KviKvsMdmCheckListViewItem *)it)->masterObject();
+ else pObject = ((KviKvsMdmStandardListViewItem *)it)->masterObject();
+ if(!pObject)return (kvs_hobject_t)0;
+ return pObject->handle();
+}
+
+
+bool KviKvsObject_listviewitem::function_setText(KviKvsObjectFunctionCall *c)
+{
+ kvs_uint_t uCol;
+ QString szText;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("column",KVS_PT_UNSIGNEDINTEGER,0,uCol)
+ KVSO_PARAMETER("text",KVS_PT_STRING,0,szText)
+ KVSO_PARAMETERS_END(c)
+ if(m_pListViewItem)
+ m_pListViewItem->setText(uCol,szText);
+ return true;
+}
+
+bool KviKvsObject_listviewitem::function_firstChild(KviKvsObjectFunctionCall *c)
+{
+ if(m_pListViewItem)
+ c->returnValue()->setHObject(itemToHandle(m_pListViewItem->firstChild()));
+ else
+ c->returnValue()->setHObject((kvs_hobject_t)0);
+ return true;
+}
+
+bool KviKvsObject_listviewitem::function_nextSibling(KviKvsObjectFunctionCall *c)
+{
+ if(m_pListViewItem)
+ c->returnValue()->setHObject(itemToHandle(m_pListViewItem->nextSibling()));
+ else
+ c->returnValue()->setHObject((kvs_hobject_t)0);
+ return true;
+}
+
+
+bool KviKvsObject_listviewitem::function_setRenameEnabled(KviKvsObjectFunctionCall *c)
+{
+ kvs_uint_t uCol;
+ bool bEnabled;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("column",KVS_PT_UNSIGNEDINTEGER,0,uCol)
+ KVSO_PARAMETER("bEnabled",KVS_PT_BOOL,0,bEnabled)
+ KVSO_PARAMETERS_END(c)
+ if(m_pListViewItem)
+ m_pListViewItem->setRenameEnabled(uCol,bEnabled);
+ return true;
+}
+
+bool KviKvsObject_listviewitem::function_setEnabled(KviKvsObjectFunctionCall *c)
+{
+ bool bEnabled;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bEnabled",KVS_PT_BOOL,0,bEnabled)
+ KVSO_PARAMETERS_END(c)
+ if(m_pListViewItem)
+ m_pListViewItem->setEnabled(bEnabled);
+ return true;
+}
+
+bool KviKvsObject_listviewitem::function_isEnabled(KviKvsObjectFunctionCall *c)
+{
+ if(!m_pListViewItem)
+ {
+ c->returnValue()->setBoolean(false);
+ return true;
+ }
+ c->returnValue()->setBoolean(m_pListViewItem->isEnabled());
+ return true;
+}
+
+bool KviKvsObject_listviewitem::function_setOpen(KviKvsObjectFunctionCall *c)
+{
+ bool bEnabled;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bEnabled",KVS_PT_BOOL,0,bEnabled)
+ KVSO_PARAMETERS_END(c)
+ if(m_pListViewItem)
+ m_pListViewItem->setOpen(bEnabled);
+ return true;
+}
+
+bool KviKvsObject_listviewitem::function_isOpen(KviKvsObjectFunctionCall *c)
+{
+ if(!m_pListViewItem)
+ {
+ c->returnValue()->setBoolean(false);
+ return true;
+ }
+ c->returnValue()->setBoolean(m_pListViewItem->isOpen());
+ return true;
+}
+
+
+bool KviKvsObject_listviewitem::function_setChecked(KviKvsObjectFunctionCall *c)
+{
+ bool bChecked;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bChecked",KVS_PT_BOOL,0,bChecked)
+ KVSO_PARAMETERS_END(c)
+ if(!m_pListViewItem)return true;
+ if(m_pListViewItem->rtti() != 1)return true; // not a QCheckListItem
+ ((KviKvsMdmCheckListViewItem *)m_pListViewItem)->setOn(bChecked);
+ return true;
+}
+
+bool KviKvsObject_listviewitem::function_isChecked(KviKvsObjectFunctionCall *c)
+{
+ if(!m_pListViewItem)
+ {
+ c->returnValue()->setBoolean(false);
+ return true;
+ }
+ if(m_pListViewItem->rtti() != 1)
+ {
+ c->returnValue()->setBoolean(false);
+ return true;
+ }
+ c->returnValue()->setBoolean(((KviKvsMdmCheckListViewItem *)m_pListViewItem)->isOn());
+ return true;
+}
+
+bool KviKvsObject_listviewitem::function_setCheckable(KviKvsObjectFunctionCall *c)
+{
+ bool bCheckable;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bCheckable",KVS_PT_BOOL,0,bCheckable)
+ KVSO_PARAMETERS_END(c)
+ if(!m_pListViewItem)return true;
+ if(bCheckable)
+ {
+ if(m_pListViewItem->rtti() == 1)return true; // a QCheckListItem already
+ KviTalListViewItem * pParent = m_pListViewItem->parent();
+ KviTalListView * pLV = (KviTalListView *)m_pListViewItem->listView();
+ // swap the items, so we don't die now
+ KviTalListViewItem * pThis = m_pListViewItem;
+ m_pListViewItem = 0;
+ delete pThis;
+ if(pParent)
+ m_pListViewItem = new KviKvsMdmCheckListViewItem(this,pParent);
+ else
+ m_pListViewItem = new KviKvsMdmCheckListViewItem(this,pLV);
+ } else {
+ if(m_pListViewItem->rtti() != 1)return true; // not a QCheckListItem yet
+ KviTalListViewItem * pParent = m_pListViewItem->parent();
+ KviTalListView * pLV = (KviTalListView *)m_pListViewItem->listView();
+ // swap the items, so we don't die now
+ KviTalListViewItem * pThis = m_pListViewItem;
+ m_pListViewItem = 0;
+ delete pThis;
+ if(pParent)
+ m_pListViewItem = new KviKvsMdmStandardListViewItem(this,pParent);
+ else
+ m_pListViewItem = new KviKvsMdmStandardListViewItem(this,pLV);
+ }
+ return true;
+}
+
+bool KviKvsObject_listviewitem::function_isCheckable(KviKvsObjectFunctionCall *c)
+{
+ if(!m_pListViewItem)
+ {
+ c->returnValue()->setBoolean(false);
+ return true;
+ }
+ c->returnValue()->setBoolean(m_pListViewItem->rtti() == 1);
+ return true;
+}
+
+bool KviKvsObject_listviewitem::function_text(KviKvsObjectFunctionCall *c)
+{
+ kvs_uint_t uCol;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("column",KVS_PT_UNSIGNEDINTEGER,0,uCol)
+ KVSO_PARAMETERS_END(c)
+ if(m_pListViewItem)
+ c->returnValue()->setString(m_pListViewItem->text(uCol));
+ return true;
+}
+
+bool KviKvsObject_listviewitem::function_setPixmap(KviKvsObjectFunctionCall *c)
+{
+ kvs_uint_t uCol;
+ KviKvsObject *obPixmap;
+ kvs_hobject_t obHpixmap;
+ KviKvsVariant * vPixmap;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("column",KVS_PT_UNSIGNEDINTEGER,0,uCol)
+ KVSO_PARAMETER("pixmap",KVS_PT_VARIANT,0,vPixmap)
+ KVSO_PARAMETERS_END(c)
+ QPixmap *pix = 0;
+ if(vPixmap->isHObject())
+ {
+ vPixmap->asHObject(obHpixmap);
+ obPixmap=KviKvsKernel::instance()->objectController()->lookupObject(obHpixmap);
+ if (!obPixmap->inherits("KviKvsObject_pixmap"))
+ {
+ c->warning(__tr2qs("Pixmap object or image Id required"));
+ return true;
+ }
+ pix=((KviKvsObject_pixmap *)obPixmap)->getPixmap();
+ } else {
+ QString szPix;
+ vPixmap->asString(szPix);
+ pix=g_pIconManager->getImage(szPix);
+ if(!pix)
+ {
+ c->warning(__tr2qs("Error occured: the suitable file '%Q' is not of the correct format or it is not a valid icon number."),&szPix);
+ return true;
+ }
+ }
+ m_pListViewItem->setPixmap(uCol,*pix);
+ return true;
+}
+
+#include "m_class_listviewitem.moc"
diff --git a/src/modules/objects/class_listviewitem.h b/src/modules/objects/class_listviewitem.h
new file mode 100644
index 00000000..eb806324
--- /dev/null
+++ b/src/modules/objects/class_listviewitem.h
@@ -0,0 +1,88 @@
+#ifndef _CLASS_LISTVIEWITEM_H_
+#define _CLASS_LISTVIEWITEM_H_
+//mdm:
+// File : class_ListViewItem.h
+// Creation date : Thu Feb 1 14:39:48 CEST 2005
+// by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+
+#include "kvi_tal_listview.h"
+#include "class_widget.h"
+
+
+
+#include "object_macros.h"
+
+class KviKvsObject_listviewitem : public KviKvsObject
+{
+ Q_OBJECT
+public:
+ KVSO_DECLARE_OBJECT(KviKvsObject_listviewitem)
+ void childDestroyed();
+protected:
+ KviTalListViewItem * m_pListViewItem;
+protected:
+ virtual bool init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams);
+protected:
+ bool function_setText(KviKvsObjectFunctionCall *c);
+ bool function_insertItem(KviKvsObjectFunctionCall *c);
+ bool function_setPixmap(KviKvsObjectFunctionCall *c);
+ bool function_setRenameEnabled(KviKvsObjectFunctionCall *c);
+ bool function_setEnabled(KviKvsObjectFunctionCall *c);
+ bool function_isEnabled(KviKvsObjectFunctionCall *c);
+ bool function_setOpen(KviKvsObjectFunctionCall *c);
+ bool function_isOpen(KviKvsObjectFunctionCall *c);
+ bool function_text(KviKvsObjectFunctionCall *c);
+ bool function_setCheckable(KviKvsObjectFunctionCall *c);
+ bool function_isCheckable(KviKvsObjectFunctionCall *c);
+ bool function_setChecked(KviKvsObjectFunctionCall *c);
+ bool function_isChecked(KviKvsObjectFunctionCall *c);
+ bool function_firstChild(KviKvsObjectFunctionCall *c);
+ bool function_nextSibling(KviKvsObjectFunctionCall *c);
+public:
+ static kvs_hobject_t itemToHandle(KviTalListViewItem * it);
+};
+
+
+
+class KviKvsMdmStandardListViewItem : public KviTalListViewItem
+{
+public:
+ KviKvsMdmStandardListViewItem(KviKvsObject_listviewitem * ob,KviTalListView * par);
+ KviKvsMdmStandardListViewItem(KviKvsObject_listviewitem * ob,KviTalListViewItem * par);
+ virtual ~KviKvsMdmStandardListViewItem();
+protected:
+ KviKvsObject_listviewitem * m_pMasterObject;
+public:
+ KviKvsObject_listviewitem * masterObject(){ return m_pMasterObject; }
+};
+
+class KviKvsMdmCheckListViewItem : public KviTalCheckListItem
+{
+public:
+ KviKvsMdmCheckListViewItem(KviKvsObject_listviewitem * ob,KviTalListView * par);
+ KviKvsMdmCheckListViewItem(KviKvsObject_listviewitem * ob,KviTalListViewItem * par);
+ virtual ~KviKvsMdmCheckListViewItem();
+protected:
+ KviKvsObject_listviewitem * m_pMasterObject;
+public:
+ KviKvsObject_listviewitem * masterObject(){ return m_pMasterObject; }
+};
+
+#endif // !_CLASS_LISTVIEWITEM_H_
diff --git a/src/modules/objects/class_mainwindow.cpp b/src/modules/objects/class_mainwindow.cpp
new file mode 100644
index 00000000..e30f480b
--- /dev/null
+++ b/src/modules/objects/class_mainwindow.cpp
@@ -0,0 +1,158 @@
+//mdm:
+// File : class_mainwindow.cpp
+// Creation date : Mon Feb 28 14:21:48 CEST 2005
+// by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_tal_mainwindow.h"
+#include "class_mainwindow.h"
+#include "kvi_error.h"
+#include "kvi_debug.h"
+
+#include "kvi_locale.h"
+#include "kvi_iconmanager.h"
+
+
+/*
+ @doc: mainwindow
+ @keyterms:
+ mainwindow object class,
+ @title:
+ mainwindow class
+ @type:
+ class
+ @short:
+ Provides a mainwindow.
+ @inherits:
+ [class]object[/class]
+ [class]widget[/class]
+ @description:
+ The mainwindow class provides a main application window, with menubar, toolbars.
+ @functions:
+ !fn: $setCentralWidget(<widget:object>)
+ Sets the central widget for the main window to <wid>.
+*/
+
+KVSO_BEGIN_REGISTERCLASS(KviKvsObject_mainwindow,"mainwindow","widget")
+ KVSO_REGISTER_HANDLER(KviKvsObject_mainwindow,"setCentralWidget",functionsetCentralWidget)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mainwindow,"setDockEnabled",functionsetDockEnabled)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mainwindow,"isDockEnabled",functionisDockEnabled)
+
+KVSO_END_REGISTERCLASS(KviKvsObject_mainwindow)
+
+KVSO_BEGIN_CONSTRUCTOR(KviKvsObject_mainwindow,KviKvsObject_widget)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_mainwindow)
+
+
+KVSO_BEGIN_DESTRUCTOR(KviKvsObject_mainwindow)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_mainwindow)
+
+bool KviKvsObject_mainwindow::init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams)
+{
+ setObject(new KviTalMainWindow(parentScriptWidget(), name()), true);
+ return true;
+}
+
+bool KviKvsObject_mainwindow::functionsetCentralWidget(KviKvsObjectFunctionCall *c)
+{
+ KviKvsObject * pObject;
+ kvs_hobject_t hObject;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("widget",KVS_PT_HOBJECT,0,hObject)
+ KVSO_PARAMETERS_END(c)
+ pObject=KviKvsKernel::instance()->objectController()->lookupObject(hObject);
+ if (!pObject)
+ {
+ c->warning(__tr2qs("Widget parameter is not an object"));
+ return true;
+ }
+ if (!pObject->object())
+ {
+ c->warning(__tr2qs("Widget parameter is not a valid object"));
+ return true;
+ }
+ if(!pObject->object()->inherits("KviKvsObject_widget"))
+ {
+ c->warning(__tr2qs("Widget object required"));
+ return TRUE;
+ }
+ if(widget()) ((KviTalMainWindow *)widget())->setCentralWidget(((QWidget *)(pObject->object())));
+ return true;
+}
+bool KviKvsObject_mainwindow::functionsetDockEnabled(KviKvsObjectFunctionCall *c)
+{
+ QString szDockarea;
+ bool bFlag;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("dock area",KVS_PT_STRING,0,szDockarea)
+ KVSO_PARAMETER("bool enabled",KVS_PT_BOOL,0,bFlag)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ {
+#ifndef COMPILE_USE_QT4
+ if(KviQString::equalCI(szDockarea,"Top"))
+ ((KviTalMainWindow *)widget())->setDockEnabled(Qt::DockTop,bFlag);
+ else if(KviQString::equalCI(szDockarea,"Left"))
+ ((KviTalMainWindow *)widget())->setDockEnabled(Qt::DockLeft,bFlag);
+ else if(KviQString::equalCI(szDockarea,"Right"))
+ ((KviTalMainWindow *)widget())->setDockEnabled(Qt::DockRight,bFlag);
+ else if(KviQString::equalCI(szDockarea,"Bottom"))
+ ((KviTalMainWindow *)widget())->setDockEnabled(Qt::DockBottom,bFlag);
+ else if(KviQString::equalCI(szDockarea,"Minimized"))
+ ((KviTalMainWindow *)widget())->setDockEnabled(Qt::DockMinimized,bFlag);
+ else if(KviQString::equalCI(szDockarea,"TornOff"))
+ ((KviTalMainWindow *)widget())->setDockEnabled(Qt::DockTornOff,bFlag);
+ else if(KviQString::equalCI(szDockarea,"Unmanaged"))
+ ((KviTalMainWindow *)widget())->setDockEnabled(Qt::DockUnmanaged,bFlag);
+ else c->warning(__tr2qs("Unknown dock area '%Q'"),&szDockarea);
+#endif
+ }
+ return true;
+
+}
+bool KviKvsObject_mainwindow::functionisDockEnabled(KviKvsObjectFunctionCall *c)
+{
+
+ QString szDockarea;
+ bool bFlag = false;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("dock_area",KVS_PT_STRING,0,szDockarea)
+ KVSO_PARAMETERS_END(c)
+ if(!widget()) return true;
+#ifndef COMPILE_USE_QT4
+ if(KviQString::equalCI(szDockarea,"Top")) bFlag=((KviTalMainWindow *)widget())->isDockEnabled(Qt::DockTop);
+ else if(KviQString::equalCI(szDockarea,"Left")) bFlag=((KviTalMainWindow *)widget())->isDockEnabled(Qt::DockLeft);
+ else if(KviQString::equalCI(szDockarea,"Right")) bFlag=((KviTalMainWindow *)widget())->isDockEnabled(Qt::DockRight);
+ else if(KviQString::equalCI(szDockarea,"Bottom"))bFlag=((KviTalMainWindow *)widget())->isDockEnabled(Qt::DockBottom);
+ else if(KviQString::equalCI(szDockarea,"Minimized")) bFlag=((KviTalMainWindow *)widget())->isDockEnabled(Qt::DockMinimized);
+ else if(KviQString::equalCI(szDockarea,"TornOff")) bFlag=((KviTalMainWindow *)widget())->isDockEnabled(Qt::DockTornOff);
+ else if(KviQString::equalCI(szDockarea,"Unmanaged")) bFlag=((KviTalMainWindow *)widget())->isDockEnabled(Qt::DockUnmanaged);
+ else
+ {
+ c->warning(__tr2qs("Unknown dock area '%Q'"),&szDockarea);
+ return true;
+ }
+#endif
+ c->returnValue()->setBoolean(bFlag);
+ return true;
+
+}
diff --git a/src/modules/objects/class_mainwindow.h b/src/modules/objects/class_mainwindow.h
new file mode 100644
index 00000000..7afddf8c
--- /dev/null
+++ b/src/modules/objects/class_mainwindow.h
@@ -0,0 +1,47 @@
+#ifndef _CLASS_MAINWINDOW_H_
+#define _CLASS_MAINWINDOW_H_
+//
+// File : class_mainwindow.h
+// Creation date : Fri Jan 28 14:21:48 CEST 2005
+// by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+//#include <qmainwindow.h>
+#include "class_widget.h"
+#include "object_macros.h"
+
+class KviKvsObject_mainwindow : public KviKvsObject_widget
+{
+public:
+ KVSO_DECLARE_OBJECT(KviKvsObject_mainwindow)
+public:
+ QWidget * widget() { return (QWidget *)object(); };
+protected:
+ virtual bool init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams);
+
+ bool functionsetCentralWidget(KviKvsObjectFunctionCall *c);
+ bool functionsetDockEnabled(KviKvsObjectFunctionCall *c);
+ bool functionisDockEnabled(KviKvsObjectFunctionCall *c);
+
+};
+
+
+#endif //!_CLASS_MAINWINDOW_H_
+
diff --git a/src/modules/objects/class_menubar.cpp b/src/modules/objects/class_menubar.cpp
new file mode 100644
index 00000000..90ad0e7d
--- /dev/null
+++ b/src/modules/objects/class_menubar.cpp
@@ -0,0 +1,76 @@
+//
+// File : class_menubar.cpp
+// Creation date : Tue Now 26 13:16:59 CEST 2002 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+
+#include "class_menubar.h"
+#include "kvi_error.h"
+#include "kvi_debug.h"
+
+#include "kvi_locale.h"
+
+/*
+ @doc: menubar
+ @title:
+ menubar class
+ @type:
+ class
+ @short:
+ A menu bar object implementation
+ @inherits:
+ [class]object[/class]
+ [class]widget[/class]
+ @description:
+
+ @functions:
+ !fn: <integer> $insertItem(<text:string>)
+ Returns an integer that identifies the inserted item.
+*/
+
+KVSO_BEGIN_REGISTERCLASS(KviKvsObject_menubar,"menubar","widget")
+ KVSO_REGISTER_HANDLER(KviKvsObject_menubar,"inserItem",functionInsertItem)
+KVSO_END_REGISTERCLASS(KviKvsObject_menubar)
+
+KVSO_BEGIN_CONSTRUCTOR(KviKvsObject_menubar,KviKvsObject_widget)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_menubar)
+
+
+KVSO_BEGIN_DESTRUCTOR(KviKvsObject_menubar)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_menubar)
+
+bool KviKvsObject_menubar::init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams)
+{
+ setObject(new QMenuBar(parentScriptWidget(), name()));
+ return true;
+}
+
+bool KviKvsObject_menubar::functionInsertItem(KviKvsObjectFunctionCall *c)
+{
+ QString szItem;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("item",KVS_PT_STRING,0,szItem)
+ KVSO_PARAMETERS_END(c)
+ if (widget()) ((QMenuBar *)widget())->insertItem(szItem);
+ return true;
+}
diff --git a/src/modules/objects/class_menubar.h b/src/modules/objects/class_menubar.h
new file mode 100644
index 00000000..c959d272
--- /dev/null
+++ b/src/modules/objects/class_menubar.h
@@ -0,0 +1,40 @@
+#ifndef _CLASS_MENUBAR_H_
+#define _CLASS_MENUBAR_H_
+//
+// File : class_menubar.h
+// Creation date : Tue Now 26 13:15:48 CEST 2002 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include <qmenubar.h>
+#include "class_widget.h"
+#include "object_macros.h"
+
+class KviKvsObject_menubar : public KviKvsObject_widget
+{
+public:
+ KVSO_DECLARE_OBJECT(KviKvsObject_menubar)
+public:
+ QWidget * widget() { return (QWidget *)object(); };
+protected:
+ virtual bool init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams);
+
+ bool functionInsertItem(KviKvsObjectFunctionCall *c);
+};
+#endif // !_CLASS_MENUBAR_H_
diff --git a/src/modules/objects/class_multilineedit.cpp b/src/modules/objects/class_multilineedit.cpp
new file mode 100644
index 00000000..6b2f8af9
--- /dev/null
+++ b/src/modules/objects/class_multilineedit.cpp
@@ -0,0 +1,1217 @@
+//vim: ts=8
+// File : class_multilineedit.cpp
+// Creation date : Mon Feb 19 00:45:34 CET by Krzysztof Godlewski
+//
+// Modification date: Thu 15 Feb 2005 22:00 :00
+// by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+#include "kvi_error.h"
+#include "kvi_debug.h"
+#include "kvi_locale.h"
+#include "kvi_malloc.h"
+#include <qfile.h>
+#ifdef COMPILE_USE_QT4
+ #include <q3multilineedit.h>
+#include <QTextStream>
+
+#include <q3stylesheet.h>
+#define KviTalMultiLineEdit Q3MultiLineEdit
+#define QTEXTEDIT_AUTO_ALL Q3TextEdit::AutoAll
+#define QTEXTEDIT_AUTO_NONE Q3TextEdit::AutoNone
+#define QTEXTEDIT_AUTO_BULLET_LIST Q3TextEdit::AutoBulletList
+
+#else
+ #include <qtextstream.h>
+
+ #include <qmultilineedit.h>
+ #define KviTalMultiLineEdit QMultiLineEdit
+ #define QTEXTEDIT_AUTO_ALL QTextEdit::AutoAll
+ #define QTEXTEDIT_AUTO_NONE QTextEdit::AutoNone
+ #define QTEXTEDIT_AUTO_BULLET_LIST QTextEdit::AutoBulletList
+
+#endif
+
+
+#include "class_multilineedit.h"
+
+
+//->Tables for Text Format
+static char * const mod_tbl[] = {
+ "PlainText",
+ "RichText",
+ "AutoText",
+ "LogText"
+ };
+
+static int mod_cod[] = {
+ Qt::PlainText,
+ Qt::RichText,
+ Qt::AutoText,
+ Qt::LogText
+ };
+
+#define mod_num (sizeof(mod_tbl) / sizeof(mod_tbl[0]))
+
+
+
+/*
+ @doc: multilineedit
+ @keyterms:
+ multilineedit object class, line editor, input
+ @title:
+ multilineedit class
+ @type:
+ class
+ @short:
+ An editor for inputting larger portions of text
+ @inherits:
+ [class]object[/class]
+ [class]widget[/class]
+ @description:
+ This is class an editor for inputting larger portions of text.
+ Besides that, it has unfinished docs.
+ @functions:
+ !fn: <string> $textLine(<line:integer>)
+ Returns the string at line <line>. Note that it can be an empty
+ string.
+ !fn: $insertLine(<text:string>, <line:integer>)
+ Inserts <text> at line number <line>. If line is less than
+ zero, or larger than the number of rows, the new text is
+ put at the end. If txt contains newline characters, several
+ lines are inserted. The <line> parameter is optional. If it is
+ ommited, the line is put at end.
+ !fn: $removeLine(<line:integer>)
+ Removes line number <line>.
+ !fn: $insertAt(<txt:string>, <line:uinteger>, <col:uinteger>)
+ Inserts txt at line number line, after character number col in
+ the line. If txt contains newline characters, new lines are
+ inserted.
+ !fn: <integer> $numLines()
+ Returns number of lines in the widget.
+ !fn: $setCursorPosition(<line:integer>, <col:uinteger>, <mark:boolean>)
+ Sets the cursor position to character number col in line
+ number line. The parameters are adjusted to lie within the
+ legal range.[br]
+ If mark is 1, the selection is cleared. otherwise it
+ is extended
+ !fn: <line,col:integer> $cursorPosition()
+ Returns current cursor position in "<line:uinteger>, <col:uinteger>" format.
+ !fn: $setReadOnly(<bReadOnly:boolean>)
+ Sets the editor to be read-only if bReadOnly is 1 or
+ removes the read-only status is ReadOnly is 0
+ !fn: <boolean> $atBeginning()
+ Returns 1(TRUE) if the cursor is placed at the beginning of the text; otherwise returns 0(FALSE).
+ !fn: <boolean> $atEnd()
+ Returns 1(TRUE) if the cursor is placed at the end of the text; otherwise returns 0(FALSE).
+ !fn: $setWordWrap(<wrap_mode:string>)
+ Sets the word wrap mode to mode. Valid Values are:[br]
+ - NoWrap - Do not wrap the text.[br]
+ - WidgetWidth - Wrap the text at the current width of the widget.[br]
+ - FixedPixelWidth - Wrap the text at a fixed number of pixels from the widget's left side.[br]
+ - FixedColumnWidth - Wrap the text at a fixed number of character columns from the widget's left side.
+ !fn: <string> $wordWrap()
+ Returns the word wrap mode. NoWrap, WidgetWidth, FixedPixelWidth, FixedColumnWidth.
+ !fn: <string> $text()
+ Returns the multiline edit's text.
+ !fn: <integer> $length()
+ Returns the number of characters in the text This function ignores newlines.
+ !fn: $setMaxLines(<mac_lines:integer>)
+ Sets the max number of the lines to <a>
+ !fn: <integer> $maxLines()
+ Returns the max number of the lines in the multiline edit.
+ !fn: $insert(<text:string>)
+ Inserts text at the current cursor position.
+ !fn: $append(<text:string>)
+ Appends a new paragraph with text to the end of the multiline edit.
+ !fn: $copy()
+ Copies any selected text from selection to the clipboard.
+ !fn: $cut()
+ Copies the selected text from selection to the clipboard and deletes it from the multiline edit.
+ !fn: $paste()
+ Pastes the text from the clipboard into the multiline edit at the current cursor position.
+ !fn: $setFamily(<font_family:string>)
+ Sets the font family of the current format to fontFamily.
+ !fn: $setItalic(<bItalic:boolean>)
+ If the bool value is 1 sets the current format to italic; otherwise, if it's 0 sets the current format to no-italic.
+ !fn: $setBold(<bBold:boolean>)
+ If the bool value is 1 sets the current format to bold; otherwise, if it's 0 sets the current format to no-bold.
+ !fn: $setUnderline(<bUnderline:boolean>)
+ If the bool value is 1 sets the current format to underline; otherwise, if it's 0 sets the current format to no-underline.
+ !fn: <boolean> $italic()
+ Returns 1(TRUE) if the current format is italic; otherwise returns 0(FALSE).
+ !fn: <boolean> $bold()
+ Returns 1(TRUE) if the current format is bold; otherwise returns 0(FALSE).
+ !fn: <boolean> $underline()
+ Returns 1(TRUE) if the current format is underline; otherwise returns 0(FALSE).
+ !fn: $zoomIn(<zoom_range:integer>)
+ Zooms in on the text by making the base font size range points larger.
+ !fn: $zoomOut(<zoom_range:integer>)
+ Zooms out on the text by making the base font size range points smaller.
+ !fn: $zoomTo(<zoom_size:integer>)
+ Zooms the text by making the base font size <size> points.
+ !fn: $undo()
+ Undoes the last operation.
+ !fn: $redo()
+ Redoes the last operation.
+ !fn: $clear()
+ Deletes all the text in the multiline edit.
+ !fn: $setUndoRedoEnabled(<bUndoRedo:boolean>)
+ Sets whether undo/redo is enabled to the bool value.
+ !fn: $setUndoDepth(<undo_depth:integer>)
+ Sets the depth of the undo history to x.
+ !fn: <boolean> $isUndoRedoEnabled()
+ Returns 1 (TRUE) if undo/redo is enabled; otherwise returns 0 (FALSE).
+ !fn: <integer> $undoDepth()
+ Returns the depth of the undo history.
+ !fn: $indent()
+ Re-indents the current paragraph.
+ !fn: $setText(<txt:string>)
+ Sets the text edit's text to txt.
+ !fn: $setPointSize(<point_size:integer))
+ Sets the point size of the font.
+ // findme
+ !fn: $setColor(<rgb_value>)
+ Sets the foreground color of this widget to <rgb_value>:valid values are:
+ - hex string: must be a string with 6 hexadecimal digits (like the ones used to
+ specify colors in html pages). The first two digits specify
+ the RED component, the third and fourth digit specify the GREEN component
+ and the last two specify the BLUE component.
+ For example "FFFF00" means full red, full green and no blue that gives
+ a yellow color, "808000" designates a brown color (dark yellow),
+ "A000A0" is a kind of violet.
+ - array(red:integer,green:integer,blue:integer)
+ - red:integer,green:integer,blue:integer.
+ !fn: $setModified(<bModified:boolean>)
+ Sets whether the document has been modified by the user. Valid Values are 1(TRUE) or 0(FALSE)
+ !fn: $insertParagraph(<text:string>,<paragraph:integer>)
+ Inserts text as a new paragraph at position <paragraph>.
+ !fn: $removeParagraph(<paragraph:integer>)
+ Removes the paragraph <paragraph>.
+ !fn: $setLinkUnderline(<bLinkUnderline:boolean>)
+ Sets to 1 if you want that hypertext links will be underlined; otherwise sets to 0.
+ !fn: $setOverwriteMode(<bOverwrite:boolean>)
+ Sets the Multilineedit edit's overwrite mode to b (1=Enabled or 0=Disabled) .
+ !fn: $setTextFormat(<textformat:string>)
+ Sets the text format. Correct values are RichText, PlainText, LogText or AutoText.
+ !fn: <string> $textFormat()
+ Returns the text format: rich text, plain text, log text or auto text.
+ // findme
+ !fn: $setParagraphBackgroundColor(<paragraph:integer>,<exadecimal color value>)
+ Sets the background color of the paragraph <paragraph> to color value specified.[br]
+ Example: %mymultiline->$setParagraphBackgroundColor(2,0C686F)
+ !fn: $clearParagraphBackground(<paragraph:integer>)
+ Clear the background color of the paragraph <paragraph>.
+ !fn: $loadFile(<path:string>)
+ Load the file specified in the <path>, also html files.
+ !fn: <boolean> $isUndoAvailable ()
+ Returns 1(TRUE) if undo is available; otherwise returns 0(FALSE).
+ !fn: <boolean> $isRedoAvailable ()
+ Returns 1(TRUE) if redo is available; otherwise returns 0(FALSE).
+ !fn: $setAlignment(<alignment:string>)
+ Sets the alignment of the current paragraph to <alignment>. Valid values are:[br]
+ - AlignAuto - Aligns according to the language.[br]
+ - Qt::AlignLeft - Aligns with the left edge.[br]
+ - Qt::AlignRight - Aligns with the right edge.[br]
+ - Qt::AlignCenter - Centers in both dimensions.
+ !fn: $setVerticalAlignment(<vertical_alignment:string>)
+ Sets the vertical alignment of the current format to <Valignemnt>. Valid Values are:[br]
+ - AlignNormal - Normal alignment.[br]
+ - AlignSuperScript - Superscript.[br]
+ - AlignSubScript - Subscript.
+ !fn: $setAutoFormatting(<afvalue:string>)
+ Sets the enabled set of auto formatting features to afvalue. Valid values are: [br]
+ - AutoNone - Do not perform any automatic formatting[br]
+ - AutoBulletList - Only automatically format bulletted lists[br]
+ - AutoAll - Apply all available autoformatting
+ !fn: $setWrapPolicy(<wraph_policy:string>)
+ Sets the word wrap policy, at <wrpl>. Valid values are:[br]
+ - AtWhiteSpace - Don't use this deprecated value (it is a synonym for AtWordBoundary which you should use instead).[br]
+ - Anywhere - Break anywhere, including within words.[br]
+ - AtWordBoundary - Break lines at word boundaries, e.g. spaces or newlines[br]
+ - AtWordOrDocumentBoundary - Break lines at whitespace, e.g. spaces or newlines if possible. Break it anywhere otherwise.[br]
+ !fn: <integer> $paragraphs()
+ Returns the number of paragraphs in the text.
+ !fn: <integer> $lines()
+ Returns the number of lines in the multilineedit.
+ !fn: <integer> $linesOfParagraph(<paragraph:integer>)
+ Returns the number of lines in paragraph <paragraph>, or -1 if there is no paragraph with index <paragraph>.
+ !fn: <integer> $lineOfChar(<paragraph:integer>,<index:integer>)
+ Returns the line number of the line in paragraph par in which the character at position index appears.[br]
+ If there is no such paragraph or no such character at the index position -1 is returned.
+ !fn: <integer> $paragraphLenght(<paragraph:integer>)
+ Returns the length of the paragraph par, or -1 if there is no paragraph with index par.
+
+*/
+
+
+KVSO_BEGIN_REGISTERCLASS(KviKvsObject_mledit,"multilineedit","widget")
+
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"textLine", functionTextLine)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"insertLine", functionInsertLine)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"removeLine", functionRemoveLine)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"insertAt", functionInsertAt)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"numLines", functionNumLines)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"setCursorPosition", functionSetCursorPosition)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"cursorPosition", functionCursorPosition)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"atBeginning", functionAtBeginning)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"atEnd", functionAtEnd)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"setWordWrap", functionSetWordWrap)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"wordWrap", functionWordWrap)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"text", functionText)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"length", functionLength);
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"setMaxLines", functionSetMaxLines)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"maxLines", functionMaxLines)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"insert", functionInsert)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"append", functionAppend)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"copy", functionCopy)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"cut", functionCut)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"paste", functionPaste)
+
+//->Set Style
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"setFamily" , functionsetFamily)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"setItalic", functionsetItalic)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"setBold", functionsetBold)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"setUnderline", functionsetUnderline)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"italic", functionitalic)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"bold", functionbold)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"underline", functionunderline)
+//->Zoom In, Out, To
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"zoomIn", functionzoomIn)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"zoomOut", functionzoomOut)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"zoomTo", functionzoomTo)
+//->Undo & Redo
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"undo", functionundo)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"redo", functionredo)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"del", functiondel)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"clear", functionclear)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"setUndoRedoEnabled", functionsetUndoRedoEnabled)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"setUndoDepth", functionsetUndoDepth)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"isUndoRedoEnabled", functionsetUndoRedoEnabled)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"undoDepth", functionundoDepth)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"indent", functionundoDepth)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"isUndoAvailable", functionisUndoAvailable)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"isUndoRedoAvailable", functionisRedoAvailable)
+//->Text color & others
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"setText", functionsetText)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"setPointSize", functionsetPointSize)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"setColor", functionsetColor)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"setModified" , functionsetModified)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"setLinkUnderline" , functionsetLinkUnderline)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"setOverwriteMode" , functionsetOverwriteMode)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"setReadOnly",functionSetReadOnly)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"setTextFormat" , functionsetTextFormat)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"textFormat" , functiontextFormat)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"setParagraphBackgroundColor", functionsetParagraphBackgroundColor)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"clearParagraphBackgroundColor", functionsetParagraphBackgroundColor)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"loadFile" , functionloadFile); // let's fantasy
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"setAlignment" , functionsetAlignment)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"setAutoFormatting" , functionsetAutoFormatting)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"setVerticalAlignment" , functionsetVerticalAlignment)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"setWrapPolicy" , functionsetWrapPolicy)
+//->Paragraph & line
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"paragraphs" , functionparagraphs)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"paragraphLength" , functionparagraphLength)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"insertParagraph" , functioninsertParagraph)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"removeParagraph" , functionremoveParagraph)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"lines" , functionlines)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"lineOfChar" , functionlineOfChar)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"linesOfParagraph" , functionlinesOfParagraph)
+ KVSO_REGISTER_HANDLER(KviKvsObject_mledit,"selectAll" , functionselectAll)
+
+
+KVSO_END_REGISTERCLASS(KviKvsObject_mledit)
+
+
+KVSO_BEGIN_CONSTRUCTOR(KviKvsObject_mledit,KviKvsObject_widget)
+
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_mledit)
+
+
+KVSO_BEGIN_DESTRUCTOR(KviKvsObject_mledit)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_mledit)
+
+bool KviKvsObject_mledit::init(KviKvsRunTimeContext * pContext,KviKvsVariantList * pParams)
+{
+ setObject(new KviTalMultiLineEdit(parentScriptWidget(),getName()),true);
+ return true;
+}
+
+
+bool KviKvsObject_mledit::functionSetReadOnly(KviKvsObjectFunctionCall *c)
+
+{
+ bool bEnabled;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bEnabled",KVS_PT_BOOL,0,bEnabled)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ ((KviTalMultiLineEdit *)widget())->setReadOnly(bEnabled);
+ return true;
+}
+
+
+bool KviKvsObject_mledit::functionTextLine(KviKvsObjectFunctionCall *c)
+
+{
+ kvs_int_t iLine;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("line",KVS_PT_INT,0,iLine)
+ KVSO_PARAMETERS_END(c)
+ if(!widget())return true;
+ if(iLine > ((KviTalMultiLineEdit *)widget())->numLines() || iLine < 0) c->warning(__tr2qs("No such line number"));
+ else
+ c->returnValue()->setString(((KviTalMultiLineEdit *)widget())->textLine(iLine));
+ return true;
+}
+
+bool KviKvsObject_mledit::functionInsertLine(KviKvsObjectFunctionCall *c)
+
+{
+ kvs_int_t iLine;
+ QString szInsert;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("text",KVS_PT_STRING,0,szInsert)
+ KVSO_PARAMETER("line",KVS_PT_INT,KVS_PF_OPTIONAL,iLine)
+ KVSO_PARAMETERS_END(c)
+ if(!widget())return true;
+ ((KviTalMultiLineEdit *)widget())->insertLine(szInsert,iLine);
+ return true;
+}
+
+bool KviKvsObject_mledit::functionRemoveLine(KviKvsObjectFunctionCall *c)
+{
+ kvs_int_t iLine;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("line",KVS_PT_INT,0,iLine)
+ KVSO_PARAMETERS_END(c)
+ if(!widget())return true;
+ if(iLine > ((KviTalMultiLineEdit *)widget())->numLines() || iLine < 0)
+ c->warning("No such line number");
+ else ((KviTalMultiLineEdit *)widget())->removeLine(iLine);
+ return true;
+}
+
+bool KviKvsObject_mledit::functionInsertAt(KviKvsObjectFunctionCall *c)
+
+{
+ kvs_uint_t iLine,iCol;
+ QString szInsert;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("text",KVS_PT_STRING,0,szInsert)
+ KVSO_PARAMETER("line",KVS_PT_UNSIGNEDINTEGER,0,iLine)
+ KVSO_PARAMETER("col",KVS_PT_UNSIGNEDINTEGER,0,iCol)
+ KVSO_PARAMETERS_END(c)
+ if(!widget())return true;
+ if(iLine < 0 || iCol < 0 || iLine > ((KviTalMultiLineEdit *)widget())->numLines())
+ c->warning("No such line number");
+ else
+ ((KviTalMultiLineEdit *)widget())->insertAt(szInsert,iLine,iCol);
+ return true;
+}
+
+bool KviKvsObject_mledit::functionNumLines(KviKvsObjectFunctionCall *c)
+
+{
+ if(widget()) c->returnValue()->setInteger(((KviTalMultiLineEdit *)widget())->numLines());
+ return true;
+}
+
+bool KviKvsObject_mledit::functionSetCursorPosition(KviKvsObjectFunctionCall *c)
+{
+
+ bool bFlag;
+ kvs_uint_t iLine,iCol;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("line",KVS_PT_UNSIGNEDINTEGER,0,iLine)
+ KVSO_PARAMETER("col",KVS_PT_UNSIGNEDINTEGER,0,iCol)
+ KVSO_PARAMETER("mark",KVS_PT_BOOL,0,bFlag)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ ((KviTalMultiLineEdit *)widget())->setCursorPosition(iLine, iCol, bFlag);
+ return true;
+}
+
+bool KviKvsObject_mledit::functionCursorPosition(KviKvsObjectFunctionCall *c)
+{
+ if(!widget()) return true;
+ int line, col;
+ #if QT_VERSION >= 300
+ ((KviTalMultiLineEdit *)widget())->getCursorPosition(&line, &col);
+ #else
+ ((KviTalMultiLineEdit *)widget())->cursorPosition(&line, &col);
+ #endif
+ KviKvsArray * a = new KviKvsArray();
+ a->set(0,new KviKvsVariant((kvs_int_t)line));
+ a->set(1,new KviKvsVariant((kvs_int_t)col));
+ c->returnValue()->setArray(a);
+ return true;
+}
+
+bool KviKvsObject_mledit::functionAtBeginning(KviKvsObjectFunctionCall *c)
+{
+ if(!widget()) return true;
+ c->returnValue()->setBoolean(((KviTalMultiLineEdit *)widget())->atBeginning());
+ return true;
+}
+
+bool KviKvsObject_mledit::functionAtEnd(KviKvsObjectFunctionCall *c)
+{
+ if(!widget()) return true;
+ c->returnValue()->setBoolean(((KviTalMultiLineEdit *)widget())->atEnd());
+ return true;
+}
+
+bool KviKvsObject_mledit::functionSetWordWrap(KviKvsObjectFunctionCall *c)
+{
+ if(!widget())return true;
+ QString szWrap;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("word_wrap",KVS_PT_STRING,0,szWrap)
+ KVSO_PARAMETERS_END(c)
+ if(KviQString::equalCI(szWrap,"NoWrap"))
+ ((KviTalMultiLineEdit *)widget())->setWordWrap(KviTalMultiLineEdit::NoWrap);
+ else if(KviQString::equalCI(szWrap,"WidgetWidth"))
+ ((KviTalMultiLineEdit *)widget())->setWordWrap(KviTalMultiLineEdit::WidgetWidth);
+ else if(KviQString::equalCI(szWrap,"FixedPixelWidth"))
+ ((KviTalMultiLineEdit *)widget())->setWordWrap(KviTalMultiLineEdit::FixedPixelWidth);
+ else if(KviQString::equalCI(szWrap,"FixedColumnWidth"))
+ ((KviTalMultiLineEdit *)widget())->setWordWrap(KviTalMultiLineEdit::FixedColumnWidth);
+ else c->warning(__tr2qs("Unknown word wrap '%Q'"),&szWrap);
+ return true;
+}
+
+bool KviKvsObject_mledit::functionsetWrapPolicy(KviKvsObjectFunctionCall *c)
+{
+ if(!widget())return true;
+ QString szPolicy;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("wrap_policy",KVS_PT_STRING,0,szPolicy)
+ KVSO_PARAMETERS_END(c)
+ if(KviQString::equalCI(szPolicy,"AtWhiteSpace)"))
+ ((KviTalMultiLineEdit *)widget())->setWrapPolicy(KviTalMultiLineEdit::AtWhiteSpace);
+ else if(KviQString::equalCI(szPolicy,"Anywhere"))
+ ((KviTalMultiLineEdit *)widget())->setWrapPolicy(KviTalMultiLineEdit::Anywhere);
+ else if(KviQString::equalCI(szPolicy,"AtWordBoundary"))
+ ((KviTalMultiLineEdit *)widget())->setWrapPolicy(KviTalMultiLineEdit::AtWordBoundary);
+ else if(KviQString::equalCI(szPolicy,"AtWordOrDocumentBoundary"))
+ ((KviTalMultiLineEdit *)widget())->setWrapPolicy(KviTalMultiLineEdit::AtWordOrDocumentBoundary);
+ else c->warning(__tr2qs("Unknown wrap policy'%Q'"),&szPolicy);
+ return true;
+}
+
+bool KviKvsObject_mledit::functionWordWrap(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ c->returnValue()->setBoolean(((KviTalMultiLineEdit *)widget())->wordWrap() & KviTalMultiLineEdit::WidgetWidth);
+ return true;
+}
+
+bool KviKvsObject_mledit::functionText(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ c->returnValue()->setString(((KviTalMultiLineEdit *)widget())->text());
+ return true;
+}
+
+bool KviKvsObject_mledit::functionLength(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ c->returnValue()->setInteger(((KviTalMultiLineEdit *)widget())->length());
+ return true;
+}
+
+bool KviKvsObject_mledit::functionSetMaxLines(KviKvsObjectFunctionCall *c)
+{
+
+ kvs_uint_t imaxLines;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("max_lines",KVS_PT_UNSIGNEDINTEGER,0,imaxLines)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ ((KviTalMultiLineEdit *)widget())->setMaxLines(imaxLines);
+ return true;
+}
+
+bool KviKvsObject_mledit::functionMaxLines(KviKvsObjectFunctionCall *c)
+
+{
+ if(widget())
+ c->returnValue()->setInteger(((KviTalMultiLineEdit *)widget())->maxLines());
+ return true;
+}
+
+bool KviKvsObject_mledit::functionInsert(KviKvsObjectFunctionCall *c)
+
+{
+ QString szInsert;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("text",KVS_PT_STRING,0,szInsert)
+ KVSO_PARAMETERS_END(c)
+ if (widget())
+ ((KviTalMultiLineEdit *)widget())->insert(szInsert);
+ return true;
+}
+
+bool KviKvsObject_mledit::functionAppend(KviKvsObjectFunctionCall *c)
+
+{
+ QString szAppend;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("text",KVS_PT_STRING,0,szAppend)
+ KVSO_PARAMETERS_END(c)
+ if (widget())
+ ((KviTalMultiLineEdit *)widget())->append(szAppend);
+ return true;
+}
+
+bool KviKvsObject_mledit::functionCopy(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ ((KviTalMultiLineEdit *)widget())->copy();
+ return true;
+}
+
+bool KviKvsObject_mledit::functionCut(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ ((KviTalMultiLineEdit *)widget())->cut();
+ return true;
+}
+
+bool KviKvsObject_mledit::functionPaste(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ ((KviTalMultiLineEdit *)widget())->paste();
+ return true;
+}
+//->Set Bold, Italic, Underline
+bool KviKvsObject_mledit::functionsetBold(KviKvsObjectFunctionCall *c)
+{
+ bool bFlag;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bBold",KVS_PT_BOOL,0,bFlag)
+ KVSO_PARAMETERS_END(c)
+ if (widget())
+ ((KviTalMultiLineEdit *)widget())->setBold(bFlag);
+ return true;
+}
+bool KviKvsObject_mledit::functionsetUnderline(KviKvsObjectFunctionCall *c)
+{
+ bool bFlag;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bUnderline",KVS_PT_BOOL,0,bFlag)
+ KVSO_PARAMETERS_END(c)
+ if (widget())
+ ((KviTalMultiLineEdit *)widget())->setUnderline(bFlag);
+ return true;
+}
+
+bool KviKvsObject_mledit::functionsetItalic(KviKvsObjectFunctionCall *c)
+{
+ bool bFlag;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bItalic",KVS_PT_BOOL,0,bFlag)
+ KVSO_PARAMETERS_END(c)
+ if (widget())
+ ((KviTalMultiLineEdit *)widget())->setItalic(bFlag);
+ return true;
+}
+
+
+//-->Returns Italic , Bold, Underline.
+bool KviKvsObject_mledit::functionbold(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ c->returnValue()->setBoolean(((KviTalMultiLineEdit *)widget())->bold());
+ return true;
+}
+bool KviKvsObject_mledit::functionitalic(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ c->returnValue()->setBoolean(((KviTalMultiLineEdit *)widget())->italic());
+ return true;
+}
+bool KviKvsObject_mledit::functionunderline(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ c->returnValue()->setBoolean(((KviTalMultiLineEdit *)widget())->underline());
+ return true;
+}
+//->Zoom In, out at
+bool KviKvsObject_mledit::functionzoomIn(KviKvsObjectFunctionCall *c)
+{
+ kvs_int_t iZoom;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("zoom_value",KVS_PT_INT,KVS_PF_OPTIONAL,iZoom)
+ KVSO_PARAMETERS_END(c)
+ if (!widget()) return true;
+ if (!iZoom)
+ ((KviTalMultiLineEdit *)object())->zoomIn();
+ else
+ ((KviTalMultiLineEdit *)object())->zoomIn(iZoom);
+ return true;
+}
+
+bool KviKvsObject_mledit::functionzoomOut(KviKvsObjectFunctionCall *c)
+{
+ kvs_int_t iZoom;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("zoom_value",KVS_PT_INT,KVS_PF_OPTIONAL,iZoom)
+ KVSO_PARAMETERS_END(c)
+ if (!widget()) return true;
+ if (!iZoom)
+ ((KviTalMultiLineEdit *)object())->zoomOut();
+ else
+ ((KviTalMultiLineEdit *)object())->zoomOut(iZoom);
+ return true;
+}
+bool KviKvsObject_mledit::functionzoomTo(KviKvsObjectFunctionCall *c)
+{
+ kvs_int_t iZoom;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("zoom_size",KVS_PT_INT,0,iZoom)
+ KVSO_PARAMETERS_END(c)
+ if (widget())
+ ((KviTalMultiLineEdit *)object())->zoomTo(iZoom);
+ return true;
+}
+//-> Undo & Redo functions
+
+bool KviKvsObject_mledit::functionundo(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ ((KviTalMultiLineEdit *)widget())->undo();
+ return true;
+}
+bool KviKvsObject_mledit::functionredo(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ ((KviTalMultiLineEdit *)widget())->redo();
+ return true;
+}
+bool KviKvsObject_mledit::functionclear(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ ((KviTalMultiLineEdit *)widget())->clear();
+ return true;
+}
+bool KviKvsObject_mledit::functiondel(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ ((KviTalMultiLineEdit *)widget())->del();
+ return true;
+}
+bool KviKvsObject_mledit::functionindent(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ ((KviTalMultiLineEdit *)widget())->indent();
+ return true;
+}
+
+bool KviKvsObject_mledit::functionsetUndoRedoEnabled(KviKvsObjectFunctionCall *c)
+{
+ bool bFlag;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bUndoredo",KVS_PT_BOOL,0,bFlag)
+ KVSO_PARAMETERS_END(c)
+ if (widget())
+ ((KviTalMultiLineEdit *)widget())->setUndoRedoEnabled(bFlag);
+ return true;
+}
+
+bool KviKvsObject_mledit::functionisUndoRedoEnabled(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ c->returnValue()->setBoolean(((KviTalMultiLineEdit *)widget())->isUndoRedoEnabled());
+ return true;
+}
+bool KviKvsObject_mledit::functionisUndoAvailable(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ c->returnValue()->setBoolean(((KviTalMultiLineEdit *)widget())->isUndoAvailable());
+ return true;
+}
+bool KviKvsObject_mledit::functionisRedoAvailable(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ c->returnValue()->setBoolean(((KviTalMultiLineEdit *)widget())->isRedoAvailable());
+ return true;
+}
+bool KviKvsObject_mledit::functionsetUndoDepth(KviKvsObjectFunctionCall *c)
+{
+ kvs_int_t iDepth;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("undo_depth",KVS_PT_UNSIGNEDINTEGER,0,iDepth)
+ KVSO_PARAMETERS_END(c)
+ if (widget())
+ ((KviTalMultiLineEdit *)object())->setUndoDepth(iDepth);
+ return true;
+
+}
+bool KviKvsObject_mledit::functionundoDepth(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ c->returnValue()->setInteger(((KviTalMultiLineEdit *)widget())->undoDepth());
+ return true;
+}
+
+//-->Text & Color & Family
+// Findme
+bool KviKvsObject_mledit::functionsetText(KviKvsObjectFunctionCall *c)
+{
+ QString szText;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("text",KVS_PT_STRING,0,szText)
+ KVSO_PARAMETERS_END(c)
+ if (widget())
+ ((KviTalMultiLineEdit *)widget())->setText(szText);
+ return true;
+}
+bool KviKvsObject_mledit::functionsetColor(KviKvsObjectFunctionCall *c)
+{
+ KviKvsVariant * pColArray;
+ kvs_int_t iColR,iColG,iColB;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("red_or_array",KVS_PT_VARIANT,0,pColArray)
+ KVSO_PARAMETER("green",KVS_PT_INT,KVS_PF_OPTIONAL,iColG)
+ KVSO_PARAMETER("blue",KVS_PT_INT,KVS_PF_OPTIONAL,iColB)
+ KVSO_PARAMETERS_END(c)
+ if(pColArray->isArray())
+ {
+ if(pColArray->array()->size() < 3)
+ {
+ c->error(__tr2qs("The array passed as parameter must contain at least 3 elements"));
+ return false;
+ }
+ KviKvsVariant * pColR = pColArray->array()->at(0);
+ KviKvsVariant * pColG = pColArray->array()->at(1);
+ KviKvsVariant * pColB = pColArray->array()->at(2);
+
+ if(!(pColR && pColG && pColB))
+ {
+ c->error(__tr2qs("One of the colors array parameters is empty"));
+ return false;
+ }
+ if(!(pColR->asInteger(iColR) && pColG->asInteger(iColG) && pColB->asInteger(iColB)))
+ {
+ c->error(__tr2qs("One of the colors array parameters didn't evaluate to an integer"));
+ return false;
+ }
+
+ } else {
+ if (c->params()->count()==1)
+ {
+ bool bOk,bOk1,bOk2;
+ QString value;
+ pColArray->asString(value);
+ int i=0;
+ if (value.length()!=6)
+ {
+ c->warning(__tr2qs("A string of 6 digits hex is required"));
+ return true;
+ }
+ QString buffer(value.mid(0,2));
+ iColR=buffer.toInt(&bOk,16);
+ buffer=value.mid(2,2);
+ iColG=buffer.toInt(&bOk1,16);
+ buffer=value.mid(4,2);
+ iColB=buffer.toInt(&bOk2,16);
+ if (!bOk || !bOk1 || !bOk2)
+ {
+ c->warning(__tr2qs("Not an hex digits"));
+ return true;
+ }
+ if (widget()) ((KviTalMultiLineEdit *)widget())->setColor(QColor(iColR,iColG,iColB));
+ return true;
+ }
+ if(c->params()->count() < 3)
+ {
+ c->error(__tr2qs("$setColor requires either an array as first parameter or three integers"));
+ return false;
+ }
+ if(!pColArray->asInteger(iColR))
+ {
+ c->error(__tr2qs("The first parameter didn't evaluate to an array nor an integer"));
+ return false;
+ }
+ }
+ if (widget()) ((KviTalMultiLineEdit *)widget())->setColor(QColor(iColR,iColG,iColB));
+ return true;
+}
+
+bool KviKvsObject_mledit::functionsetPointSize(KviKvsObjectFunctionCall *c)
+{
+ kvs_uint_t uPointSize;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("point_size",KVS_PT_UNSIGNEDINTEGER,0,uPointSize)
+ KVSO_PARAMETERS_END(c)
+ if (widget())
+ ((KviTalMultiLineEdit *)widget())->setPointSize(uPointSize);
+ return true;
+}
+
+bool KviKvsObject_mledit::functionsetLinkUnderline(KviKvsObjectFunctionCall *c)
+{
+ bool bFlag;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bLinkunderline",KVS_PT_BOOL,0,bFlag)
+ KVSO_PARAMETERS_END(c)
+ if (widget())
+ ((KviTalMultiLineEdit *)widget())->setLinkUnderline(bFlag);
+ return true;
+}
+
+bool KviKvsObject_mledit::functionsetFamily(KviKvsObjectFunctionCall *c)
+{
+ QString szFamily;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("family",KVS_PT_STRING,0,szFamily)
+ KVSO_PARAMETERS_END(c)
+ if (widget())
+ ((KviTalMultiLineEdit *)widget())->setFamily(szFamily);
+ return true;
+}
+
+bool KviKvsObject_mledit::functionsetModified(KviKvsObjectFunctionCall *c)
+{
+ bool bFlag;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bModified",KVS_PT_BOOL,0,bFlag)
+ KVSO_PARAMETERS_END(c)
+ if (widget())
+ ((KviTalMultiLineEdit *)widget())->setModified(bFlag);
+ return true;
+}
+
+bool KviKvsObject_mledit::functioninsertParagraph(KviKvsObjectFunctionCall *c)
+{
+ kvs_int_t iParagraph;
+ QString szText;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("text",KVS_PT_STRING,0,szText)
+ KVSO_PARAMETER("paragraph",KVS_PT_INT,0,iParagraph)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ ((KviTalMultiLineEdit *)widget())->insertParagraph(szText,iParagraph);
+ return true;
+}
+
+bool KviKvsObject_mledit::functionremoveParagraph(KviKvsObjectFunctionCall *c)
+{
+ kvs_int_t iParagraph;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("paragraph",KVS_PT_INT,0,iParagraph)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ ((KviTalMultiLineEdit*)widget())->removeParagraph(iParagraph);
+ return true;
+}
+
+bool KviKvsObject_mledit::functionsetOverwriteMode(KviKvsObjectFunctionCall *c)
+{
+ bool bFlag;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bOverwritemode",KVS_PT_BOOL,0,bFlag)
+ KVSO_PARAMETERS_END(c)
+ if (widget())
+ ((KviTalMultiLineEdit *)widget())->setOverwriteMode(bFlag);
+ return true;
+}
+
+bool KviKvsObject_mledit::functiontextFormat(KviKvsObjectFunctionCall *c)
+
+{
+ if(!widget())return true;
+ int fstyle = ((KviTalMultiLineEdit *)widget())->textFormat();
+ QString format="";
+ for(unsigned int i = 0; i < mod_num; i++)
+ {
+ if(fstyle & mod_cod[i])
+ {
+ format=mod_tbl[i];
+ }
+ }
+ c->returnValue()->setString(format);
+ return true;
+
+}
+bool KviKvsObject_mledit::functionsetTextFormat(KviKvsObjectFunctionCall *c)
+
+{
+ QString szFormat;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("textformat",KVS_PT_STRING,0,szFormat)
+ KVSO_PARAMETERS_END(c)
+ if(!widget()) return true;
+ if(KviQString::equalCI(szFormat,"PlainText"))
+ ((KviTalMultiLineEdit *)widget())->setTextFormat(Qt::PlainText);
+ else if(KviQString::equalCI(szFormat,"RichText"))
+ ((KviTalMultiLineEdit *)widget())->setTextFormat(Qt::RichText);
+ else if(KviQString::equalCI(szFormat,"LogText"))
+ ((KviTalMultiLineEdit *)widget())->setTextFormat(Qt::LogText);
+ else if(KviQString::equalCI(szFormat,"AutoText"))
+ ((KviTalMultiLineEdit *)widget())->setTextFormat(Qt::AutoText);
+ else c->warning(__tr2qs("Unknown text format '%Q'"),&szFormat);
+ return true;
+}
+// findme
+bool KviKvsObject_mledit::functionsetParagraphBackgroundColor(KviKvsObjectFunctionCall *c)
+{
+ KviKvsVariant * pColArray;
+ kvs_int_t iParagraph,iColR,iColG,iColB;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("paragraph",KVS_PT_INT,0,iParagraph)
+ KVSO_PARAMETER("red_or_array",KVS_PT_VARIANT,0,pColArray)
+ KVSO_PARAMETER("green",KVS_PT_INT,KVS_PF_OPTIONAL,iColG)
+ KVSO_PARAMETER("blue",KVS_PT_INT,KVS_PF_OPTIONAL,iColB)
+ KVSO_PARAMETERS_END(c)
+ if(pColArray->isArray())
+ {
+ if(pColArray->array()->size() < 3)
+ {
+ c->error(__tr2qs("The array passed as parameter must contain at least 3 elements"));
+ return false;
+ }
+ KviKvsVariant * pColR = pColArray->array()->at(0);
+ KviKvsVariant * pColG = pColArray->array()->at(1);
+ KviKvsVariant * pColB = pColArray->array()->at(2);
+
+ if(!(pColR && pColG && pColB))
+ {
+ c->error(__tr2qs("One of the colors array parameters is empty"));
+ return false;
+ }
+ if(!(pColR->asInteger(iColR) && pColG->asInteger(iColG) && pColB->asInteger(iColB)))
+ {
+ c->error(__tr2qs("One of the colors array parameters didn't evaluate to an integer"));
+ return false;
+ }
+
+ } else {
+ if (c->params()->count()==1)
+ {
+ bool bOk,bOk1,bOk2;
+ QString value;
+ pColArray->asString(value);
+ int i=0;
+ if (value.length()!=6)
+ {
+ c->warning(__tr2qs("A string of 6 digits hex is required"));
+ return true;
+ }
+ QString buffer(value.mid(0,2));
+ iColR=buffer.toInt(&bOk,16);
+ buffer=value.mid(2,2);
+ iColG=buffer.toInt(&bOk1,16);
+ buffer=value.mid(4,2);
+ iColB=buffer.toInt(&bOk2,16);
+ if (!bOk || !bOk1 || !bOk2)
+ {
+ c->warning(__tr2qs("Not an hex digits"));
+ return true;
+ }
+ if (widget()) ((KviTalMultiLineEdit *)widget())->setParagraphBackgroundColor(iParagraph,QColor(iColR,iColG,iColB));
+ return true;
+ }
+ if(c->params()->count() < 3)
+ {
+ c->error(__tr2qs("$setColor requires either an array as first parameter or three integers"));
+ return false;
+ }
+ if(!pColArray->asInteger(iColR))
+ {
+ c->error(__tr2qs("The first parameter didn't evaluate to an array nor an integer"));
+ return false;
+ }
+ }
+ if (widget()) ((KviTalMultiLineEdit *)widget())->setParagraphBackgroundColor(iParagraph,QColor(iColR,iColG,iColB));
+ return true;
+}
+
+bool KviKvsObject_mledit::functionclearParagraphBackground(KviKvsObjectFunctionCall *c)
+{
+ kvs_int_t iParagraph;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("paragraph",KVS_PT_INT,0,iParagraph)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ ((KviTalMultiLineEdit*)widget())->clearParagraphBackground(iParagraph);
+ return true;
+}
+
+bool KviKvsObject_mledit::functionloadFile(KviKvsObjectFunctionCall *c)
+{
+ QString szFile;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("file_name",KVS_PT_STRING,0,szFile)
+ KVSO_PARAMETERS_END(c)
+ if ( !QFile::exists(szFile))
+ {
+ c->warning(__tr2qs(" I can't find the specified file '%Q'."),&szFile);
+ return true;
+ }
+
+ QFile file( szFile );
+ if ( !file.open( IO_ReadOnly ) )
+ {
+ c->warning(__tr2qs(" I cannot read the file %Q'."),&szFile);
+ return true;
+ }
+
+ QTextStream ts( &file );
+ QString txt = ts.read();
+#ifdef COMPILE_USE_QT4
+ if ( !Q3StyleSheet::mightBeRichText( txt ) )
+ txt = Q3StyleSheet::convertFromPlainText( txt, Q3StyleSheetItem::WhiteSpacePre );
+#else
+ if ( !QStyleSheet::mightBeRichText( txt ) )
+ txt = QStyleSheet::convertFromPlainText( txt, QStyleSheetItem::WhiteSpacePre );
+#endif
+ ((KviTalMultiLineEdit *)widget())->setText( txt );
+
+ file.close();
+ return true;
+}
+
+bool KviKvsObject_mledit::functionsetAlignment(KviKvsObjectFunctionCall *c)
+
+{
+ QString szAlignment;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("alignment",KVS_PT_STRING,0,szAlignment)
+ KVSO_PARAMETERS_END(c)
+ if(!widget()) return true;
+ if(KviQString::equalCI(szAlignment,"Left"))
+ ((KviTalMultiLineEdit *)widget())->setAlignment(Qt::AlignLeft);
+ else if(KviQString::equalCI(szAlignment,"Right"))
+ ((KviTalMultiLineEdit *)widget())->setAlignment(Qt::AlignRight);
+ else if(KviQString::equalCI(szAlignment,"Center"))
+ ((KviTalMultiLineEdit *)widget())->setAlignment(Qt::AlignCenter);
+ else if(KviQString::equalCI(szAlignment,"Justify"))
+ ((KviTalMultiLineEdit *)widget())->setAlignment(Qt::AlignJustify);
+ else c->warning(__tr2qs("Unknown alignment '%Q'"),&szAlignment);
+ return true;
+}
+
+bool KviKvsObject_mledit::functionsetAutoFormatting(KviKvsObjectFunctionCall *c)
+
+{
+ QString szAutoformatting;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("autoformatting",KVS_PT_STRING,0,szAutoformatting)
+ KVSO_PARAMETERS_END(c)
+ if(!widget()) return true;
+ if(KviQString::equalCI(szAutoformatting,"AutoNone"))
+ ((KviTalMultiLineEdit *)widget())->setAutoFormatting(QTEXTEDIT_AUTO_NONE);
+ else if(KviQString::equalCI(szAutoformatting,"BulletList"))
+ ((KviTalMultiLineEdit *)widget())->setAutoFormatting(QTEXTEDIT_AUTO_BULLET_LIST);
+ else if(KviQString::equalCI(szAutoformatting,"AutoAll"))
+ ((KviTalMultiLineEdit *)widget())->setAutoFormatting(QTEXTEDIT_AUTO_ALL);
+ else c->warning(__tr2qs("Unknown auto formatting mode '%Q'"),&szAutoformatting);
+ return true;
+}
+
+bool KviKvsObject_mledit::functionsetVerticalAlignment(KviKvsObjectFunctionCall *c)
+
+{
+ QString szValignment;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("alignment",KVS_PT_STRING,0,szValignment)
+ KVSO_PARAMETERS_END(c)
+ if(!widget()) return true;
+ if(KviQString::equalCI(szValignment,"Normal"))
+ ((KviTalMultiLineEdit *)widget())->setVerticalAlignment(KviTalMultiLineEdit::AlignNormal);
+ else if(KviQString::equalCI(szValignment,"SuperScript"))
+ ((KviTalMultiLineEdit *)widget())->setVerticalAlignment(KviTalMultiLineEdit::AlignSuperScript);
+ else if(KviQString::equalCI(szValignment,"SubScript"))
+ ((KviTalMultiLineEdit *)widget())->setVerticalAlignment(KviTalMultiLineEdit::AlignSubScript);
+ else c->warning(__tr2qs("Unknown vertical alignment '%Q'"),&szValignment);
+ return true;
+}
+
+bool KviKvsObject_mledit::functionparagraphs(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ c->returnValue()->setInteger(((KviTalMultiLineEdit *)widget())->paragraphs());
+ return true;
+
+}
+
+bool KviKvsObject_mledit::functionlines(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ c->returnValue()->setInteger(((KviTalMultiLineEdit *)widget())->lines());
+ return true;
+}
+
+bool KviKvsObject_mledit::functionlineOfChar(KviKvsObjectFunctionCall *c)
+{
+ kvs_int_t iPara,iIndex;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("paragraph",KVS_PT_INT,0,iPara)
+ KVSO_PARAMETER("index",KVS_PT_INT,0,iIndex)
+ KVSO_PARAMETERS_END(c)
+ if (widget())
+ c->returnValue()->setInteger(((KviTalMultiLineEdit *)widget())->lineOfChar(iPara,iIndex));
+ return true;
+}
+
+bool KviKvsObject_mledit::functionlinesOfParagraph(KviKvsObjectFunctionCall *c)
+{
+ kvs_int_t iLine;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("paragraph",KVS_PT_INT,0,iLine)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ c->returnValue()->setInteger(((KviTalMultiLineEdit *)widget())->linesOfParagraph(iLine));
+ return true;
+}
+
+
+bool KviKvsObject_mledit::functionparagraphLength(KviKvsObjectFunctionCall *c)
+{
+ kvs_int_t iParagraph;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("paragraph",KVS_PT_INT,0,iParagraph)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ c->returnValue()->setInteger(((KviTalMultiLineEdit *)widget())->paragraphLength(iParagraph));
+ return true;
+
+}
+
+bool KviKvsObject_mledit::functionselectAll(KviKvsObjectFunctionCall *c)
+{
+ bool bFlag;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bSelectall",KVS_PT_BOOL,0,bFlag)
+ KVSO_PARAMETERS_END(c)
+ if (widget())
+ ((KviTalMultiLineEdit *)widget())->selectAll(bFlag);
+ return true;
+}
+
+
+
+#include "m_class_multilineedit.moc"
diff --git a/src/modules/objects/class_multilineedit.h b/src/modules/objects/class_multilineedit.h
new file mode 100644
index 00000000..8639266e
--- /dev/null
+++ b/src/modules/objects/class_multilineedit.h
@@ -0,0 +1,110 @@
+#ifndef _CLASS_MULTILINEEDIT_H_
+#define _CLASS_MULTILINEEDIT_H_
+//vim: ts=8
+// File : class_multilineedit.cpp
+// Creation date : Mon Feb 19 00:45:34 CET by Krzysztof Godlewski
+//
+// Modification date: Thu 15 Feb 2005 22:00 :00
+// by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+#include "class_widget.h"
+#include "object_macros.h"
+
+class KviKvsObject_mledit : public KviKvsObject_widget
+{
+ Q_OBJECT
+public:
+ KVSO_DECLARE_OBJECT(KviKvsObject_mledit)
+public:
+ QWidget * widget() { return (QWidget *)object(); };
+protected:
+ virtual bool init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams);
+ bool functionTextLine(KviKvsObjectFunctionCall *c);
+ bool functionInsertLine(KviKvsObjectFunctionCall *c);
+ bool functionRemoveLine(KviKvsObjectFunctionCall *c);
+ bool functionInsertAt(KviKvsObjectFunctionCall *c);
+ bool functionNumLines(KviKvsObjectFunctionCall *c);
+ bool functionSetCursorPosition(KviKvsObjectFunctionCall *c);
+ bool functionAtBeginning(KviKvsObjectFunctionCall *c);
+ bool functionAtEnd(KviKvsObjectFunctionCall *c);
+ bool functionSetWordWrap(KviKvsObjectFunctionCall *c);
+ bool functionWordWrap(KviKvsObjectFunctionCall *c);
+ bool functionCursorPosition(KviKvsObjectFunctionCall *c);
+ bool functionText(KviKvsObjectFunctionCall *c);
+ bool functionLength(KviKvsObjectFunctionCall *c);
+ bool functionSetMaxLines(KviKvsObjectFunctionCall *c);
+ bool functionMaxLines(KviKvsObjectFunctionCall *c);
+ bool functionSetReadOnly(KviKvsObjectFunctionCall *c);
+ bool functionInsert(KviKvsObjectFunctionCall *c);
+ bool functionAppend(KviKvsObjectFunctionCall *c);
+ bool functionCopy(KviKvsObjectFunctionCall *c);
+ bool functionPaste(KviKvsObjectFunctionCall *c);
+ bool functionCut(KviKvsObjectFunctionCall *c);
+// |-G&N add-|
+ bool functionsetItalic(KviKvsObjectFunctionCall *c);
+ bool functionitalic(KviKvsObjectFunctionCall *c);
+ bool functionsetBold(KviKvsObjectFunctionCall *c);
+ bool functionbold(KviKvsObjectFunctionCall *c);
+ bool functionsetUnderline(KviKvsObjectFunctionCall *c);
+ bool functionunderline(KviKvsObjectFunctionCall *c);
+ bool functionzoomIn(KviKvsObjectFunctionCall *c);
+ bool functionzoomOut(KviKvsObjectFunctionCall *c);
+ bool functionzoomTo(KviKvsObjectFunctionCall *c);
+ bool functionundo(KviKvsObjectFunctionCall *c);
+ bool functionredo(KviKvsObjectFunctionCall *c);
+ bool functiondel(KviKvsObjectFunctionCall *c);
+ bool functionclear(KviKvsObjectFunctionCall *c);
+ bool functionindent(KviKvsObjectFunctionCall *c);
+ bool functionsetUndoRedoEnabled(KviKvsObjectFunctionCall *c);
+ bool functionsetUndoDepth(KviKvsObjectFunctionCall *c);
+ bool functionisUndoRedoEnabled(KviKvsObjectFunctionCall *c);
+ bool functionundoDepth(KviKvsObjectFunctionCall *c);
+ bool functionsetText(KviKvsObjectFunctionCall *c);
+ bool functionsetPointSize(KviKvsObjectFunctionCall *c);
+ bool functionsetColor(KviKvsObjectFunctionCall *c);
+ bool functionisUndoAvailable(KviKvsObjectFunctionCall *c);
+ bool functionisRedoAvailable(KviKvsObjectFunctionCall *c);
+ bool functionsetLinkUnderline(KviKvsObjectFunctionCall *c);
+ bool functionsetFamily(KviKvsObjectFunctionCall *c);
+ bool functionsetModified(KviKvsObjectFunctionCall *c);
+ bool functioninsertParagraph(KviKvsObjectFunctionCall *c);
+ bool functionremoveParagraph(KviKvsObjectFunctionCall *c);
+ bool functionsetOverwriteMode(KviKvsObjectFunctionCall *c);
+ bool functionsetTextFormat(KviKvsObjectFunctionCall *c);
+ bool functiontextFormat(KviKvsObjectFunctionCall *c);
+ bool functionsetParagraphBackgroundColor(KviKvsObjectFunctionCall *c);
+ bool functionclearParagraphBackground(KviKvsObjectFunctionCall *c);
+ bool functionloadFile(KviKvsObjectFunctionCall *c);
+ bool functionsetAlignment(KviKvsObjectFunctionCall *c);
+ bool functionsetAutoFormatting(KviKvsObjectFunctionCall *c);
+ bool functionsetVerticalAlignment(KviKvsObjectFunctionCall *c);
+ bool functionsetWrapPolicy(KviKvsObjectFunctionCall *c);
+ bool functionparagraphs(KviKvsObjectFunctionCall *c);
+ bool functionparagraphLength(KviKvsObjectFunctionCall *c);
+ bool functionlines(KviKvsObjectFunctionCall *c);
+ bool functionlineOfChar(KviKvsObjectFunctionCall *c);
+ bool functionlinesOfParagraph(KviKvsObjectFunctionCall *c);
+ bool functionselectAll(KviKvsObjectFunctionCall *c);
+
+};
+
+#endif //!_CLASS_MULTILINEEDIT_H_
diff --git a/src/modules/objects/class_painter.cpp b/src/modules/objects/class_painter.cpp
new file mode 100644
index 00000000..b27a24a3
--- /dev/null
+++ b/src/modules/objects/class_painter.cpp
@@ -0,0 +1,1007 @@
+//mdm:
+// Painter : class_painter.cpp
+// Creation date : Fri Mar 18 14:30:48 CEST 2005
+// by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
+// Lucia Papini (^ashura^) English Translation.
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "class_painter.h"
+#include "class_pixmap.h"
+#include "class_widget.h"
+#include "kvi_debug.h"
+
+#include "kvi_locale.h"
+#include "kvi_error.h"
+#include "kvi_iconmanager.h"
+#include "kvi_malloc.h"
+
+
+/*
+ @doc: painter
+ @keyterms:
+ painter object class, line editor, input
+ @title:
+ painter class
+ @type:
+ class
+ @short:
+ This class provide a painter to paint line and shapes.
+ @inherits:
+ [class]object[/class]
+ [class]widget[/class]
+ @description:
+ With this class you can draw many graphics objects from simple lines to complex shapes like pies and chords.[br]
+ It can also draw aligned text and pixmaps. Normally, it draws in a "natural" coordinate system, but it can also do view and world transformation.[br]
+ The class need to be implemented into a [classfnc]$paintEvent[/classfnc]();
+ @functions:
+ !fn: $drawLine(<x1:integer>,<y1_integer>,<x2:integer>,<y2:integer>)
+ Draws a line from (x1, y1) to (x2, y2) and sets the current pen position to (x2, y2).
+ !fn: $begin(<paint_device:object>)
+ Begins painting the paint device <paint_device>: the parameter MUST be a widget or a pixmap.[br]
+ Warning: A paint device can only be painted by one painter at a time.
+ !fn: $end()
+ Ends painting. Any resources used while painting are released.
+ !fn: $setPen(<rgb or hsv array value or [<red>,<green>,<blue>][<hue>,<saturation>,<value>],[system color:RGB or HSV)
+ The pen defines the lines or text, color. You can set it with Red,Green,Blue, or H,S,V value[br]
+ All parameters are in integer form.
+ The HSV system, like RGB, has three components:[br]
+ * H, for hue, is either 0-359 if the color is chromatic (not gray), or meaningless if it is gray.[br]
+ It represents degrees on the color wheel familiar to most people. Red is 0 (degrees), green is 120 and blue is 240.[br]
+ * S, for saturation, is 0-255, and the bigger it is, the stronger the color is. Grayish colors have saturation near 0; very strong colors have saturation near 255.[br]
+ * V, for value, is 0-255 and represents lightness or brightness of the color. 0 is black; 255 is as far from black as possible.[br]
+ Examples: RED is H=0, S=255, V=255.[br]
+ Light RED could have H about 0, S about 50-100, and S=255.
+ ES: $setPen(00,00,00) for black;[br]
+ Default color mode is RGB;
+ !fn: $setBrush(<rgb or hsv array value or [<red>,<green>,<blue>][<hue>,<saturation>,<value>],[system color:RGB or HSV)
+ Sets the painter's brush to have the specified color.[br]
+ Example:[br]
+ class (wdg,widget)[br]
+ {[br]
+ paintevent()[br]
+ {[br]
+ %b=$new(painter)[br]
+ %b->$setBackgroundMode(Opaque)[br]
+ %b->$setBrush(0,250,250)[br]
+ %b->$begin($$)[br]
+ %b->$drawEllipse(50,50,100,50)[br]
+ }[br]
+ }[br]
+ %aa=$new(wdg)[br]
+ %aa->$show()[br]
+ !fn: $drawRect(<x:integer>,<y:integer>,<w:unsigned integer>,<h:unsigned integer>)
+ Draws a rectangle with upper left corner at (x, y) and with width w and height h.
+ !fn: $drawWinFocusRect(<x:integer>,<y:integer>,<w:unsigned integer>,<h:unsigned integer>)
+ Draws a Windows focus rectangle with upper left corner at (x, y) and with width w and height h.[br]
+ This function draws nothing if the coordinate system has been rotated or sheared.
+ !fn: $drawRoundRect(<x:integer>,<y:integer>,<w:unsigned integer>,<h:unsigned integer>,<xCor:integer>,<yCor:integer>)
+ Draws a rectangle with rounded corners at (x, y), with width w and height h.[rb]
+ The xCor and yCor arguments specify how rounded the corners should be (range is 0->99).
+ !fn: $drawPie(<x:integer>,<y:integer>,<w:unsigned integer>,<h:unsigned integer>,<angle:integer>,<alen:integer>)
+ Draws a pie defined by the rectangle (x, y, w, h), the start angle a and the arc length alen.[br]
+ The angles <angle> and <alen> are 1/16th of a degree, i.e. a full circle equals 5760 (16*360).
+ !fn: $drawArc(<x:integer>,<y:integer>,<w:unsigned integer>,<h:unsigned integer>,<angle:integer>,<alen:integer>)
+ Draws an arc defined by the rectangle (x, y, w, h), the start angle a and the arc length alen.[br]
+ The angles <angle> and <alen> are 1/16th of a degree, i.e. a full circle equals 5760 (16*360).
+ !fn: $drawPoint(<x:integer>,<y:integer>)
+ Draws a point at x and y coordinates.
+ !fn: $drawEllipse(<x:integer>,<y:integer>,<sizew:unsigned integer>,<sizeh:unsigned integer>)
+ Draws an ellipse with center at (x + w/2, y + h/2) and size (w, h).
+ !fn: $drawChord(<x:integer>,<y:integer>,<w:unsigned integer>,<h:unsigned integer>,<angle:integer>,<alen:integer>)
+ Draws a chord defined by the rectangle (x, y, w, h), the start angle a and the arc length alen.[br]
+ The angles <angle> and <alen> are 1/16th of a degree, i.e. a full circle equals 5760 (16*360).
+ !fn: $drawText(<x:integer>,<y:integer>,<text:string>,<nr chars:integer>,<dir:enum>)
+ Draws the given <text> at position <x>, <y>.[br]
+ If <len> is -1 (the default) all the text is drawn, otherwise the first <len> characters are drawn.
+ The text's direction is given by <dir>, valid flag are:[br]
+ [pre]
+ Auto [br]
+ RTL (right to left) [br]
+ LTR (left to right) [br]
+ [/pre]
+ !fn: $drawPixmap(<x:integer>,<y:integer>,<pixmap:hobject>,<sx:integer>,<sy:integer>,<ex:integer>,<ey:integer>)
+ Draws a pixmap at x,y coordinates[br]
+ !fn: $setFont(<size:unsigned integer>,<family:string>,<style:enum>)[br]
+ Set the font's size, family and stile, valid flag for style are:[br]
+ [pre]
+ italic [br]
+ bold [br]
+ underline [br]
+ overline [br]
+ strikeout [br]
+ fixedpitch [br]
+ [/pre]
+ !fn: $setFontSize(<size:unsigned integer>)[br]
+ Set the current painter font's size.[br]
+ !fn: <integer>$fontAscent()
+ Return the distance from the baseline to the highest position characters extend to.
+ !fn: <integer>$fontDescent()
+ Return the distance from the baseline to the lowest point characters extend to.
+ !fn: <integer>$fontMetricsWidth(<text:string>)
+ Returns the font metrics width for the painter's current font.
+ !fn: <integer>$fontMetricsHeight()
+ Returns the font metrics height for the painter's current font.
+ !fn: $rotate(<angle:real>)
+ Rotates the coordinate system a degrees counterclockwise.
+ !fn: $translate(<dx:real>,<dy:real>)
+ Translates the coordinate system by <dx>, <dy>.
+ !fn: $shear(<dh:real>,<dv:real>)
+ Shears the coordinate system by <dh>, <dv>.
+ !fn: $scale(<dh:real>,<dw:real>)
+ Scales the coordinate system by <dh>, <dv>.
+ !fn: $setBackgroundMode(<bgMode:enum>)
+ Sets the background mode of the painter to <bgMode>: valid values are:[br]
+ - Transparent (that is the default value);[br]
+ - Opaque.[br]
+ !fn: $setOpacity(<opacity_factor:real>) [QT4 ONLY]
+ Sets the painter opacity that affects all painter operations (drawpixmap, drawtext...). Valid values range are from 0 (total transparency) to 1 (total opacity)[br]
+ You must invoke the [classfnc]$begin[/classfnc] before using it.
+ !fn: $setTextAntialiasing(<boolean>) [QT4 ONLY]
+ Enable/disable antialias in text if possible.
+ You must call the [classfnc]$begin[/classfnc] before using it.
+ !fn: $setAntialiasing(<boolean>) [QT4 ONLY]
+ Enable/disable antialias in edges of primitives if possible.
+ You must call the [classfnc]$begin[/classfnc] before using it.
+ !fn: $setSmoothPixmapTransform(<boolean>) [QT4 ONLY]
+ Enable/disable smooth bilinear pixmap transformation algorithm (such as bilinear).
+ You must call the [classfnc]$begin[/classfnc] before using it.
+ Example:[br]
+ [br]
+ class (hello,widget)[br]
+ {[br]
+ constructor()[br]
+ {[br]
+ $$->%sintbl[]= $array( 0, 38, 71, 92, 100, 92, 71, 38,0, -38, -71, -92, -100, -92, -71, -38);[br]
+ $$->%index=0[br]
+ $$->$starttimer( 30 );[br]
+ $$->$resize(800,600 );[br]
+ $$->%string=$0[br]
+ $$->%waitfor=1;[br]
+ $$->%nextanim=0[br]
+ [br]
+ #zoom and rotation anim[br]
+ $$->%Zoomindex=11[br]
+ $$->%degree=0[br]
+ $$->%Noanim=0[br]
+ $$->%scrollright=-450[br]
+ [br]
+ #anim effect init[br]
+ $$->%xoffset=4[br]
+ $$->%yoffset=3[br]
+ $$->%xstart=270[br]
+ $$->%ystart=200[br]
+ $$->%b=0[br]
+ $$->%yoffs=400[br]
+ [br]
+ #parallax parameter[br]
+ $$->%Off=400[br]
+ $$->%roll=1[br]
+ }[br]
+ timerevent()[br]
+ {[br]
+ $$->%b = $(($$->%b + 1) & 15);[br]
+ if ($$->%nextanim == 1) $$->$repaint(1);[br]
+ $$->$repaint(0);[br]
+ }[br]
+ drawAnim()[br]
+ {[br]
+ %P->$setFont(32,"times",bold);[br]
+ %w=$(%P->$fontMetricsWidth($$->%string[$$->%index]) + 20);[br]
+ %h=$(%P->$fontMetricsHeight * 2);[br]
+ %pmx = $(($$->$width/2) -%w/2);[br]
+ %pmy = $(($$->$height()/2) - %h/2);[br]
+ %x = 10;[br]
+ %y= $((%h/2) + $$->$fontDescent());[br]
+ %i=0[br]
+ while ( $str.mid("Grifisx/Noldor",%i,1) != "") [br]
+ {[br]
+ %i16 = $(($$->%b+%i) & 15);[br]
+ %char=$str.mid("Grifisx/Noldor",%i,1)[br]
+ %P->$setPen($((15-%i16)*16),$((15-%i16)*16),$((15-%i16)*16) );[br]
+ %P->$drawText( $(%x+$$->%xstart),$($$->%ystart+%y-$$->%sintbl[%i16]*%h/800),%char,1,Auto);[br]
+ %x += %P->$fontMetricsWidth(%char);[br]
+ %i++;[br]
+ }[br]
+ }[br]
+ matrixeffect()[br]
+ {[br]
+ if (($$->%Zoomindex == 99) && ($$->%degree==360)) return %P->$drawPixmap($(400-32),$(300-32),"kvirc.png",0,0,-1,-1)[br]
+ %P->$scale(0.$$->%Zoomindex,0.$$->%Zoomindex)[br]
+ if ($$->%Zoomindex != 99) $$->%Zoomindex++;[br]
+ %P->$rotate($$->%degree)[br]
+ %P->$translate(400,300)[br]
+ %P->$drawPixmap(-32,-32,"kvirc.png",0,0,-1,-1)[br]
+ %P->$setFont(28,"times",bold);[br]
+ %P->$reset()[br]
+ if ($$->%scrollright >= 550) return[br]
+ %P->$scale(0.$$->%Zoomindex,0.$$->%Zoomindex)[br]
+ %P->$translate(400,350)[br]
+ %P->$drawText($$->%scrollright,10,"Another cool class brought to you by...",-1,Auto) [br]
+ $$->%scrollright += 3;[br]
+ %P->$reset()[br]
+ }[br]
+ nextanim()[br]
+ {[br]
+ %p=$new(painter)[br]
+ %p->$setBackgroundMode(Opaque)[br]
+ %p->$setBrush($rand(255),$rand(255),$rand(255))[br]
+ %p->$begin($$)[br]
+ %rand=$rand(5)[br]
+ %p->$drawrect($rand(800),$rand(400),120,200)[br]
+ %p->$drawArc($rand(800),$rand(400),120,200,20,$(16*20))[br]
+ %p->$drawPie($rand(800),$rand(400),120,200,20,$(16*20))[br]
+ %p->$drawChord($rand(800),$rand(400),120,200,20,$(16*20))[br]
+ %p->$drawEllipse($rand(800),$rand(400),100,30)[br]
+ %p->$end()[br]
+ delete %p[br]
+ }[br]
+ paintEvent()[br]
+ {[br]
+ if ($$->%nextanim ==1) return $$->$nextanim()[br]
+ # pixmap creation: every effect will be painted on it then copied on widget[br]
+ %pixmap=$new(pixmap)[br]
+ %pixmap->$resize($$->$width(),$$->$height())[br]
+ [br]
+ # painter creation [br]
+ %P=$new(painter);[br]
+ %P->$begin(%pixmap);[br]
+ $$->$drawanim[br]
+ $$->$matrixeffect[br]
+ %i=0[br]
+ while (%i != 100)[br]
+ {[br]
+ %i16 = $(($$->%b+%i) & 15);[br]
+ %P->$setPen($((15-%i16)*16),$((15-%i16)*16),$((15-%i16)*16) );[br]
+ %P->$drawpoint($rand(800),$rand(600))[br]
+ %i++[br]
+ }[br]
+ [br]
+ # sets the animations order to manage the parallax effect[br]
+ %P->$end[br]
+ objects.bitBlt $$ 0 0 %pixmap[br]
+ delete %pixmap[br]
+ delete %P[br]
+ if (%Pauseflag == 1) return[br]
+ [br]
+ # manage the animations parameters[br]
+ if (($$->%Off<=60) && ($$->%roll<182)) $$->%roll += 2;[br]
+ if ($$->%roll>182) $$->%waitfor=0[br]
+ if ($$->%Noanim != 1) $$->%degree += 16;[br]
+ if ($$->%degree >= 360)[br]
+ {[br]
+ $$->%degree=0;[br]
+ if ($$->%Zoomindex == 99) $$->%Noanim=1[br]
+ } [br]
+ if ($$->%Noanim != 1) return[br]
+ [br]
+ #sinusoid animation[br]
+ if (($$->%xstart <1) && ($$->%xoffset == -4)) $$->%xoffset=4;[br]
+ if (($$->%xstart >$($$->$width()-%P->$fontMetricsWidth("Grifisx/Noldor"))) && ($$->%xoffset == 4)) $$->%xoffset=-4;[br]
+ if (($$->%ystart <1) && ($$->%yoffset == -3)) $$->%yoffset=3;[br]
+ if (($$->%ystart >$($$->$height()-60)) && ($$->%yoffset == 3)) $$->%yoffset=-3;[br]
+ $$->%xstart += $$->%xoffset;[br]
+ $$->%ystart += $$->%yoffset;[br]
+ }[br]
+ }[br]
+ [br]
+ %Hello=$new(hello)[br]
+ %Hello->$setcaption("Painter effects" );[br]
+ %Hello->$setFont(28,"times",bold);[br]
+ %Btn=$new(button,%Hello)[br]
+ %Btn->$setmaximumwidth(80)[br]
+ %Btn->$setmaximumheight(30)[br]
+ %Btn->$setFont(8,"times",bold);[br]
+ %Btn->$settext(Next)[br]
+ [br]
+ privateimpl(%Btn,mousepressevent)[br]
+ {[br]
+ if ($$->$parent->%nextanim==0) [br]
+ {[br]
+ $$->$parent->%nextanim=1[br]
+ $$->$settext(Prev)[br]
+ } [br]
+ else[br]
+ {[br]
+ $$->$parent->%nextanim=0[br]
+ $$->$settext(Next)[br]
+ }[br]
+ }[br]
+ [br]
+ %lay=$new(layout,%Hello)[br]
+ %lay->$addwidget(%Btn,4,0)[br]
+ %Hello->$setBackgroundColor("000000");[br]
+ %Hello->$setmaximumwidth(800)[br]
+ %Hello->$setminimumwidth(780)[br]
+ %Hello->$setmaximumheight(600)[br]
+ %Hello->$setminimumheight(600)[br]
+ %Hello->$move(10,10)[br]
+ %Hello->$show();[br] [br]
+
+*/
+
+// ========================================================================
+KVSO_BEGIN_REGISTERCLASS(KviKvsObject_painter,"painter","object")
+
+ // Fonts
+ KVSO_REGISTER_HANDLER(KviKvsObject_painter,"setFont",functionSetFont)
+ KVSO_REGISTER_HANDLER(KviKvsObject_painter,"setFontSize",functionSetFontSize)
+
+ KVSO_REGISTER_HANDLER(KviKvsObject_painter,"setBrush",functionsetBrush)
+ KVSO_REGISTER_HANDLER(KviKvsObject_painter,"setPen",functionsetPen)
+ KVSO_REGISTER_HANDLER(KviKvsObject_painter,"fontAscent",functionfontAscent)
+ KVSO_REGISTER_HANDLER(KviKvsObject_painter,"fontDescent",functionfontDescent)
+ KVSO_REGISTER_HANDLER(KviKvsObject_painter,"fontMetricsHeight",functionfontMetricsHeight)
+ KVSO_REGISTER_HANDLER(KviKvsObject_painter,"fontMetricsWidth",functionfontMetricsWidth)
+ // Draws
+ KVSO_REGISTER_HANDLER(KviKvsObject_painter,"setBackGroundMode",functionsetBackGroundMode)
+ KVSO_REGISTER_HANDLER(KviKvsObject_painter,"drawRect",functiondrawRect)
+ KVSO_REGISTER_HANDLER(KviKvsObject_painter,"drawLine",functiondrawLine)
+ KVSO_REGISTER_HANDLER(KviKvsObject_painter,"drawRoundRect",functiondrawRoundRect)
+ KVSO_REGISTER_HANDLER(KviKvsObject_painter,"drawWinFocusRect",functiondrawWinFocusRect)
+ KVSO_REGISTER_HANDLER(KviKvsObject_painter,"drawPoint",functiondrawPoint)
+ KVSO_REGISTER_HANDLER(KviKvsObject_painter,"drawArc",functiondrawArc)
+ KVSO_REGISTER_HANDLER(KviKvsObject_painter,"drawEllipse",functiondrawEllipse)
+ KVSO_REGISTER_HANDLER(KviKvsObject_painter,"drawPie",functiondrawPie)
+ KVSO_REGISTER_HANDLER(KviKvsObject_painter,"drawChord",functiondrawChord)
+ // Text & Pixmap
+ KVSO_REGISTER_HANDLER(KviKvsObject_painter,"drawText",functiondrawText)
+ KVSO_REGISTER_HANDLER(KviKvsObject_painter,"drawPixmap",functiondrawPixmap)
+
+
+ // MAtrix Operation
+ KVSO_REGISTER_HANDLER(KviKvsObject_painter,"rotate",functionrotateMatrix)
+ KVSO_REGISTER_HANDLER(KviKvsObject_painter,"shear",functionshearMatrix)
+ KVSO_REGISTER_HANDLER(KviKvsObject_painter,"scale",functionscaleMatrix)
+ KVSO_REGISTER_HANDLER(KviKvsObject_painter,"translate",functiontranslateMatrix)
+ KVSO_REGISTER_HANDLER(KviKvsObject_painter,"reset",functionresetMatrix)
+
+#ifdef COMPILE_USE_QT4
+ KVSO_REGISTER_HANDLER(KviKvsObject_painter,"setOpacity",functionsetOpacity)
+ KVSO_REGISTER_HANDLER(KviKvsObject_painter,"setTextAntialiasing",functionsetTextAntialiasing)
+ KVSO_REGISTER_HANDLER(KviKvsObject_painter,"setAntialiasing",functionsetAntialiasing)
+ KVSO_REGISTER_HANDLER(KviKvsObject_painter,"setSmoothPixmapTransform",functionsetSmoothPixmapTransform)
+#endif
+
+ KVSO_REGISTER_HANDLER(KviKvsObject_painter,"begin",functionbegin)
+ KVSO_REGISTER_HANDLER(KviKvsObject_painter,"end",functionend)
+
+
+KVSO_END_REGISTERCLASS(KviKvsObject_painter)
+
+
+KVSO_BEGIN_CONSTRUCTOR(KviKvsObject_painter,KviKvsObject)
+
+ m_pPainter = new QPainter();
+
+ m_pDeviceObject=0;
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_painter)
+
+KVSO_BEGIN_DESTRUCTOR(KviKvsObject_painter)
+
+ if (m_pPainter) delete m_pPainter;
+ m_pPainter = 0;
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_painter)
+
+#define KVSO_PARAMETERS_PAINTER(__pXOrArray,__iY,__iW,__iH)\
+if(__pXOrArray->isArray())\
+ {\
+ if(__pXOrArray->array()->size() < 4)\
+ {\
+ c->error(__tr2qs("The array passed as parameter must contain at least 4 elements"));\
+ return false;\
+ }\
+ KviKvsVariant * pX = __pXOrArray->array()->at(0);\
+ KviKvsVariant * pY = __pXOrArray->array()->at(1);\
+ KviKvsVariant * pW = __pXOrArray->array()->at(2);\
+ KviKvsVariant * pH = __pXOrArray->array()->at(3);\
+ if(!(pX && pY && pW && pH))\
+ {\
+ c->error(__tr2qs("One of the geometry array parameters is empty"));\
+ return false;\
+ }\
+ if(!(pX->asInteger(iX) && pY->asInteger(__iY) && pW->asInteger(__iW) && pH->asInteger(__iH)))\
+ {\
+ c->error(__tr2qs("One of the geometry array parameters didn't evaluate to an integer"));\
+ return false;\
+ }\
+ } else {\
+ if(c->params()->count() < 4)\
+ {\
+ QString error=function+" requires either an array as first parameter or four integers";\
+ c->error(__tr2qs(error));\
+ return false;\
+ }\
+ if(!__pXOrArray->asInteger(iX))\
+ {\
+ c->error(__tr2qs("The first parameter didn't evaluate to an array nor an integer"));\
+ return false;\
+ }\
+ }\
+
+#define KVSO_2ARRAYPARAMETERS(__pXOrArray,__iY)\
+if(__pXOrArray->isArray())\
+ {\
+ if(__pXOrArray->array()->size() < 2)\
+ {\
+ c->error(__tr2qs("The array passed as parameter must contain at least 2 elements"));\
+ return false;\
+ }\
+ KviKvsVariant * pX = __pXOrArray->array()->at(0);\
+ KviKvsVariant * pY = __pXOrArray->array()->at(1);\
+ if(!(pX && pY ))\
+ {\
+ c->error(__tr2qs("One of the array parameters is empty"));\
+ return false;\
+ }\
+ if(!(pX->asInteger(iX) && pY->asInteger(__iY)))\
+ {\
+ c->error(__tr2qs("One of the array parameters didn't evaluate to an integer"));\
+ return false;\
+ }\
+ } else {\
+ if(c->params()->count() < 2)\
+ {\
+ QString error=function+" requires either an array as first parameter or two integers";\
+ c->error(__tr2qs(error));\
+ return false;\
+ }\
+ if(!__pXOrArray->asInteger(iX))\
+ {\
+ c->error(__tr2qs("The first parameter didn't evaluate to an array nor an integer"));\
+ return false;\
+ }\
+ }\
+
+#define KVSO_3ARRAYPARAMETERS(__pCol1OrArray,__iCol2,__iCol3)\
+if(__pCol1OrArray->isArray())\
+ {\
+ if(__pCol1OrArray->array()->size() < 3)\
+ {\
+ c->error(__tr2qs("The array passed as parameter must contain at least 3 elements"));\
+ return false;\
+ }\
+ KviKvsVariant * c1 = __pCol1OrArray->array()->at(0);\
+ KviKvsVariant * c2 = __pCol1OrArray->array()->at(1);\
+ KviKvsVariant * c3 = __pCol1OrArray->array()->at(2);\
+ if(!(c1 && c2 && c3))\
+ {\
+ c->error(__tr2qs("One of the array parameters is empty"));\
+ return false;\
+ }\
+ if(!(c1->asInteger(iCol1) && c2->asInteger(__iCol2) && c3->asInteger(__iCol3)))\
+ {\
+ c->error(__tr2qs("One of the array parameters didn't evaluate to an integer"));\
+ return false;\
+ }\
+ } else {\
+ if(c->params()->count() < 3)\
+ {\
+ QString error=function+" requires either an array as first parameter or 3 integers";\
+ c->error(__tr2qs(error));\
+ return false;\
+ }\
+ if(!__pCol1OrArray->asInteger(iCol1))\
+ {\
+ c->error(__tr2qs("The first parameter didn't evaluate to an array nor an integer"));\
+ return false;\
+ }\
+ }\
+
+bool KviKvsObject_painter::functionSetFont(KviKvsObjectFunctionCall *c)
+{
+ QString szFamily,szStyle;
+ kvs_int_t uSize;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("size",KVS_PT_UNSIGNEDINTEGER,0,uSize)
+ KVSO_PARAMETER("family",KVS_PT_STRING,0,szFamily)
+ KVSO_PARAMETER("style",KVS_PT_STRING,0,szStyle)
+ KVSO_PARAMETERS_END(c)
+ if(!m_pPainter)return true;
+ QFont font=m_pPainter->font();
+ font.setFamily(szFamily);
+ font.setPointSize(uSize);
+ if(KviQString::equalCI(szStyle,"italic")) font.setItalic(TRUE);
+ if(KviQString::equalCI(szStyle,"bold")) font.setBold(TRUE);
+ if(KviQString::equalCI(szStyle,"underline"))font.setUnderline(TRUE);
+ if(KviQString::equalCI(szStyle,"overline")) font.setOverline(TRUE);
+ if(KviQString::equalCI(szStyle,"strikeout"))font.setStrikeOut(TRUE);
+ if(KviQString::equalCI(szStyle,"fixedpitch")) font.setFixedPitch(TRUE);
+ m_pPainter->setFont(font);
+ return true;
+}
+bool KviKvsObject_painter::functionSetFontSize(KviKvsObjectFunctionCall *c)
+{
+ kvs_uint_t uSize;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("size",KVS_PT_UNSIGNEDINTEGER,0,uSize)
+ KVSO_PARAMETERS_END(c)
+ if(!m_pPainter)return true;
+ QFont font=m_pPainter->font();
+ font.setPointSize(uSize);
+ m_pPainter->setFont(font);
+ return true;
+}
+bool KviKvsObject_painter::functionsetBackGroundMode(KviKvsObjectFunctionCall *c)
+{
+ QString szMode;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("background mode",KVS_PT_STRING,0,szMode)
+ KVSO_PARAMETERS_END(c)
+ if(!m_pPainter)return true;
+ if(KviQString::equalCI(szMode,"Transparent")) m_pPainter->setBackgroundMode(Qt::TransparentMode);
+ else if(KviQString::equalCI(szMode,"Opaque")) m_pPainter->setBackgroundMode(Qt::OpaqueMode);
+ else c->warning( __tr2qs("Unknown orientation"));
+ return true;
+
+}
+
+bool KviKvsObject_painter::functiondrawLine(KviKvsObjectFunctionCall *c)
+{
+ KviKvsVariant * pXOrArray;
+ kvs_int_t iX,iY,iW,iH;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("x_or_array",KVS_PT_VARIANT,0,pXOrArray)
+ KVSO_PARAMETER("y",KVS_PT_INT,KVS_PF_OPTIONAL,iY)
+ KVSO_PARAMETER("w",KVS_PT_INT,KVS_PF_OPTIONAL,iW)
+ KVSO_PARAMETER("h",KVS_PT_INT,KVS_PF_OPTIONAL,iH)
+ KVSO_PARAMETERS_END(c)
+ QString function="$drawLine";
+ KVSO_PARAMETERS_PAINTER(pXOrArray,iY,iW,iH)
+ if(m_pPainter) m_pPainter->drawLine(iX,iY,iW,iH);
+ return true;
+}
+bool KviKvsObject_painter::functiondrawRect(KviKvsObjectFunctionCall *c)
+{
+ KviKvsVariant * pXOrArray;
+ kvs_int_t iX,iY,iW,iH;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("x_or_array",KVS_PT_VARIANT,0,pXOrArray)
+ KVSO_PARAMETER("y",KVS_PT_INT,KVS_PF_OPTIONAL,iY)
+ KVSO_PARAMETER("w",KVS_PT_INT,KVS_PF_OPTIONAL,iW)
+ KVSO_PARAMETER("h",KVS_PT_INT,KVS_PF_OPTIONAL,iH)
+ KVSO_PARAMETERS_END(c)
+ QString function="$drawRect";
+ KVSO_PARAMETERS_PAINTER(pXOrArray,iY,iW,iH)
+ if(m_pPainter) m_pPainter->drawRect(iX,iY,iW,iH);
+ return true;
+}
+// FIX ME: REMOVE functiondrawWinFocusRect
+bool KviKvsObject_painter::functiondrawWinFocusRect(KviKvsObjectFunctionCall *c)
+{
+ KviKvsVariant * pXOrArray;
+ kvs_int_t iX,iY,iW,iH;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("x_or_array",KVS_PT_VARIANT,0,pXOrArray)
+ KVSO_PARAMETER("y",KVS_PT_INT,KVS_PF_OPTIONAL,iY)
+ KVSO_PARAMETER("w",KVS_PT_INT,KVS_PF_OPTIONAL,iW)
+ KVSO_PARAMETER("h",KVS_PT_INT,KVS_PF_OPTIONAL,iH)
+ KVSO_PARAMETERS_END(c)
+ QString function="$drawWinFocusRect";
+ KVSO_PARAMETERS_PAINTER(pXOrArray,iY,iW,iH)
+#ifndef COMPILE_USE_QT4
+ if(m_pPainter) m_pPainter->drawWinFocusRect(iX,iY,iW,iH);
+#endif
+ return true;
+}
+bool KviKvsObject_painter::functiondrawEllipse(KviKvsObjectFunctionCall *c)
+{
+ KviKvsVariant * pXOrArray;
+ kvs_int_t iX,iY,iW,iH;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("x_or_array",KVS_PT_VARIANT,0,pXOrArray)
+ KVSO_PARAMETER("y",KVS_PT_INT,KVS_PF_OPTIONAL,iY)
+ KVSO_PARAMETER("w",KVS_PT_INT,KVS_PF_OPTIONAL,iW)
+ KVSO_PARAMETER("h",KVS_PT_INT,KVS_PF_OPTIONAL,iH)
+ KVSO_PARAMETERS_END(c)
+ QString function="$drawEllipse";
+ KVSO_PARAMETERS_PAINTER(pXOrArray,iY,iW,iH)
+ if(m_pPainter) m_pPainter->drawEllipse(iX,iY,iW,iH);
+ return true;
+}
+bool KviKvsObject_painter::functiondrawRoundRect(KviKvsObjectFunctionCall *c)
+{
+ KviKvsVariant * pXOrArray;
+ kvs_int_t iXrnd,iYrnd,iX,iY,iW,iH;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("x_round",KVS_PT_INT,0,iXrnd)
+ KVSO_PARAMETER("y_round",KVS_PT_INT,0,iYrnd)
+ KVSO_PARAMETER("x_or_array",KVS_PT_VARIANT,0,pXOrArray)
+ KVSO_PARAMETER("y",KVS_PT_INT,KVS_PF_OPTIONAL,iY)
+ KVSO_PARAMETER("w",KVS_PT_INT,KVS_PF_OPTIONAL,iW)
+ KVSO_PARAMETER("h",KVS_PT_INT,KVS_PF_OPTIONAL,iH)
+ KVSO_PARAMETERS_END(c)
+ QString function="$drawRoundRect";
+ KVSO_PARAMETERS_PAINTER(pXOrArray,iY,iW,iH)
+ if(m_pPainter)
+ m_pPainter->drawRoundRect(iX,iY,iW,iH,iXrnd,iYrnd);
+ return true;
+}
+bool KviKvsObject_painter::functiondrawArc(KviKvsObjectFunctionCall *c)
+{
+ KviKvsVariant * pXOrArray;
+ kvs_int_t iSangle,iLena,iX,iY,iW,iH;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("start_angle",KVS_PT_INT,0,iSangle)
+ KVSO_PARAMETER("a_lenght",KVS_PT_INT,0,iLena)
+ KVSO_PARAMETER("x_or_array",KVS_PT_VARIANT,0,pXOrArray)
+ KVSO_PARAMETER("y",KVS_PT_INT,KVS_PF_OPTIONAL,iY)
+ KVSO_PARAMETER("w",KVS_PT_INT,KVS_PF_OPTIONAL,iW)
+ KVSO_PARAMETER("h",KVS_PT_INT,KVS_PF_OPTIONAL,iH)
+ KVSO_PARAMETERS_END(c)
+ QString function="$drawArc";
+ KVSO_PARAMETERS_PAINTER(pXOrArray,iY,iW,iH)
+ if(m_pPainter)
+ m_pPainter->drawArc(iX,iY,iW,iH,iSangle,iLena);
+ return true;
+}
+bool KviKvsObject_painter::functiondrawChord(KviKvsObjectFunctionCall *c)
+{
+ KviKvsVariant * pXOrArray;
+ kvs_int_t iSangle,iLena,iX,iY,iW,iH;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("start_angle",KVS_PT_INT,0,iSangle)
+ KVSO_PARAMETER("a_lenght",KVS_PT_INT,0,iLena)
+ KVSO_PARAMETER("x_or_array",KVS_PT_VARIANT,0,pXOrArray)
+ KVSO_PARAMETER("y",KVS_PT_INT,KVS_PF_OPTIONAL,iY)
+ KVSO_PARAMETER("w",KVS_PT_INT,KVS_PF_OPTIONAL,iW)
+ KVSO_PARAMETER("h",KVS_PT_INT,KVS_PF_OPTIONAL,iH)
+ KVSO_PARAMETERS_END(c)
+ QString function="$drawChord";
+ KVSO_PARAMETERS_PAINTER(pXOrArray,iY,iW,iH)
+ if(m_pPainter)
+ m_pPainter->drawChord(iX,iY,iW,iH,iSangle,iLena);
+ return true;
+}
+bool KviKvsObject_painter::functionsetBrush(KviKvsObjectFunctionCall *c)
+{
+ KviKvsVariant * pCol1OrArray;
+ kvs_int_t iCol1,iCol2,iCol3;
+ QString szColorMode;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("Col1_or_array",KVS_PT_VARIANT,0,pCol1OrArray)
+ KVSO_PARAMETER("Color_2",KVS_PT_INT,KVS_PF_OPTIONAL,iCol2)
+ KVSO_PARAMETER("Colo3_3",KVS_PT_INT,KVS_PF_OPTIONAL,iCol3)
+ KVSO_PARAMETER("color_mode",KVS_PT_STRING,KVS_PF_OPTIONAL,szColorMode)
+ KVSO_PARAMETERS_END(c)
+ QString function="$drawChord";
+ KVSO_3ARRAYPARAMETERS(pCol1OrArray,iCol2,iCol3)
+ if(!m_pPainter) return true;
+ if(KviQString::equalCI(szColorMode, "HSV"))
+ m_pPainter->setBrush(QColor(iCol1,iCol2,iCol3,QColor::Hsv));
+ else
+ m_pPainter->setBrush(QColor(iCol1,iCol2,iCol3,QColor::Rgb));
+ return true;
+}
+bool KviKvsObject_painter::functionsetPen(KviKvsObjectFunctionCall *c)
+{
+ KviKvsVariant * pCol1OrArray;
+ kvs_int_t iCol1,iCol2,iCol3;
+ QString szColorMode;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("Col1_or_array",KVS_PT_VARIANT,0,pCol1OrArray)
+ KVSO_PARAMETER("Color_2",KVS_PT_INT,KVS_PF_OPTIONAL,iCol2)
+ KVSO_PARAMETER("Colo3_3",KVS_PT_INT,KVS_PF_OPTIONAL,iCol3)
+ KVSO_PARAMETER("color_mode",KVS_PT_STRING,KVS_PF_OPTIONAL,szColorMode)
+ KVSO_PARAMETERS_END(c)
+ QString function="$setPen";
+ KVSO_3ARRAYPARAMETERS(pCol1OrArray,iCol2,iCol3)
+ if(!m_pPainter) return true;
+ if(KviQString::equalCI(szColorMode, "HSV"))
+ m_pPainter->setPen(QColor(iCol1,iCol2,iCol3,QColor::Hsv));
+ else
+ m_pPainter->setPen(QColor(iCol1,iCol2,iCol3,QColor::Rgb));
+
+ return true;
+}
+bool KviKvsObject_painter::functiondrawPie(KviKvsObjectFunctionCall *c)
+{
+ KviKvsVariant * pXOrArray;
+ kvs_int_t iSangle,iLena,iX,iY,iW,iH;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("start_angle",KVS_PT_INT,0,iSangle)
+ KVSO_PARAMETER("a_lenght",KVS_PT_INT,0,iLena)
+ KVSO_PARAMETER("x_or_array",KVS_PT_VARIANT,0,pXOrArray)
+ KVSO_PARAMETER("y",KVS_PT_INT,KVS_PF_OPTIONAL,iY)
+ KVSO_PARAMETER("w",KVS_PT_INT,KVS_PF_OPTIONAL,iW)
+ KVSO_PARAMETER("h",KVS_PT_INT,KVS_PF_OPTIONAL,iH)
+ KVSO_PARAMETERS_END(c)
+ QString function="$drawPie";
+ KVSO_PARAMETERS_PAINTER(pXOrArray,iY,iW,iH)
+ if(m_pPainter)
+ m_pPainter->drawPie(iX,iY,iW,iH,iSangle,iLena);
+ return true;
+}
+bool KviKvsObject_painter::functiondrawPoint(KviKvsObjectFunctionCall *c)
+{
+ KviKvsVariant * pXOrArray;
+ kvs_int_t iX,iY;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("x_or_array",KVS_PT_VARIANT,0,pXOrArray)
+ KVSO_PARAMETER("y",KVS_PT_INT,KVS_PF_OPTIONAL,iY)
+ KVSO_PARAMETERS_END(c)
+ QString function="$drawPoint";
+ KVSO_2ARRAYPARAMETERS(pXOrArray,iY)
+ if(m_pPainter)
+ m_pPainter->drawPoint(iX,iY);
+ return true;
+}
+bool KviKvsObject_painter::functionfontDescent(KviKvsObjectFunctionCall * c)
+{
+ if(m_pPainter)
+ c->returnValue()->setInteger(m_pPainter->fontMetrics().descent());
+ return true;
+}
+
+bool KviKvsObject_painter::functionfontAscent(KviKvsObjectFunctionCall * c)
+{
+ if(m_pPainter)
+ c->returnValue()->setInteger(m_pPainter->fontMetrics().ascent());
+ return true;
+
+}
+
+bool KviKvsObject_painter::functionfontMetricsWidth(KviKvsObjectFunctionCall * c)
+{
+ QString szText;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("text",KVS_PT_STRING,0,szText)
+ KVSO_PARAMETERS_END(c)
+ if(m_pPainter)
+ c->returnValue()->setInteger(m_pPainter->fontMetrics().width(szText));
+ return true;
+}
+
+bool KviKvsObject_painter::functionfontMetricsHeight(KviKvsObjectFunctionCall * c)
+{
+ if(m_pPainter)
+ c->returnValue()->setInteger(m_pPainter->fontMetrics().height());
+ return true;
+}
+bool KviKvsObject_painter::functionbegin(KviKvsObjectFunctionCall *c)
+{
+ KviKvsObject * pObject;
+ kvs_hobject_t hObject;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("paint_device",KVS_PT_HOBJECT,0,hObject)
+ KVSO_PARAMETERS_END(c)
+ pObject=KviKvsKernel::instance()->objectController()->lookupObject(hObject);
+ if(!m_pPainter)return true;
+ if (!pObject)
+ {
+ c->warning(__tr2qs("Pixmap or Widget parameter is not an object"));
+ return true;
+ }
+
+ QPaintDevice * pd = 0;
+ if(pObject->inherits("KviKvsObject_pixmap"))pd =((KviKvsObject_pixmap *)pObject)->getPixmap();
+ else if (pObject->inherits("KviKvsObject_widget")) pd=((KviKvsObject_widget *)pObject)->widget();
+
+ if (!pd)
+ c->warning(__tr2qs("Widget or Pixmap required "));
+ else {
+ attachDevice(pObject,pd);
+ // m_pPainter->setOpacity(0.4);
+ if (pObject->inherits("KviKvsObject_pixmap")) ((KviKvsObject_pixmap *)pObject)->pixmapChanged();
+ }
+ return true;
+}
+void KviKvsObject_painter::attachDevice(KviKvsObject * o,QPaintDevice * p)
+{
+ if(!m_pPainter)return;
+ if(m_pDeviceObject)detachDevice();
+ m_pDeviceObject = o;
+ // KviKvsObject_pixmap and KviKvsObject_widget object have this signal
+ // it is emitted BEFORE the real QPaintDevice is deleted, so we can eventually
+ // call m_pPainter->end() in time
+
+ QObject::connect(m_pDeviceObject,SIGNAL(aboutToDie()),this,SLOT(detachDevice()));
+ m_pPainter->begin(p);
+}
+
+void KviKvsObject_painter::detachDevice()
+{
+ if(!m_pDeviceObject)return;
+ if(!m_pPainter)return;
+ disconnect(m_pDeviceObject,SIGNAL(aboutToDie()),this,SLOT(detachDevice()));
+ m_pPainter->end();
+ m_pDeviceObject = 0;
+}
+
+bool KviKvsObject_painter::functionend(KviKvsObjectFunctionCall *c)
+{
+ detachDevice();
+ return true;
+}
+
+bool KviKvsObject_painter::functiondrawText(KviKvsObjectFunctionCall *c)
+{
+ QString szText,szMode;
+ kvs_int_t iX,iY,iLen;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("x",KVS_PT_INT,0,iX)
+ KVSO_PARAMETER("y",KVS_PT_INT,0,iY)
+ KVSO_PARAMETER("text",KVS_PT_STRING,0,szText)
+ KVSO_PARAMETER("length",KVS_PT_INT,0,iLen)
+ KVSO_PARAMETER("mode",KVS_PT_STRING,KVS_PF_OPTIONAL,szMode)
+ KVSO_PARAMETERS_END(c)
+ if(!m_pPainter)return true;
+#ifdef COMPILE_USE_QT4
+ if (!szMode.isEmpty()){
+ if(KviQString::equalCI(szMode,"RTL"))m_pPainter->setLayoutDirection(Qt::RightToLeft);
+ else if(KviQString::equalCI(szMode,"LTR"))m_pPainter->setLayoutDirection(Qt::LeftToRight);
+ else
+ {
+ c->warning(__tr2qs("Invalid mode '%Q'"),&szMode);
+ return true;
+ }
+ }
+
+ m_pPainter->drawText(iX,iY,szText);
+#else
+ if(KviQString::equalCI(szMode,"Auto")) m_pPainter->drawText(iX,iY,szText,iLen,QPainter::Auto);
+ else if(KviQString::equalCI(szMode,"RTL")) m_pPainter->drawText(iX,iY,szText,iLen,QPainter::RTL);
+ else if(KviQString::equalCI(szMode,"LTR"))m_pPainter->drawText(iX,iY,szText,iLen,QPainter::LTR);
+ else c->warning(__tr2qs("Invalid mode '%Q'"),&szMode);
+
+#endif
+ return true;
+}
+
+bool KviKvsObject_painter::functiondrawPixmap(KviKvsObjectFunctionCall *c)
+{
+ kvs_int_t iX,iY,iStartx,iStarty,iEndx,iEndy;
+ KviKvsObject *obj;
+ kvs_hobject_t hObject;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("x",KVS_PT_INT,0,iX)
+ KVSO_PARAMETER("y",KVS_PT_INT,0,iY)
+ KVSO_PARAMETER("pixmap",KVS_PT_HOBJECT,0,hObject)
+ KVSO_PARAMETER("start_x",KVS_PT_INT,0,iStartx)
+ KVSO_PARAMETER("start_y",KVS_PT_INT,0,iStarty)
+ KVSO_PARAMETER("end_x",KVS_PT_INT,0,iEndx)
+ KVSO_PARAMETER("end_y",KVS_PT_INT,0,iEndy)
+ KVSO_PARAMETERS_END(c)
+ obj=KviKvsKernel::instance()->objectController()->lookupObject(hObject);
+ if(!m_pPainter)return true;
+ if (!obj)
+ {
+ c->warning(__tr2qs("Pixmap parameter is not an object"));
+ return true;
+ }
+ if (!obj->inherits("KviKvsObject_pixmap"))
+ {
+ c->warning(__tr2qs("Pixmap object required"));
+ return true;
+ }
+ QPixmap * pm=((KviKvsObject_pixmap *)obj)->getPixmap();
+ m_pPainter->drawPixmap(iX,iY,*((KviKvsObject_pixmap *)obj)->getPixmap(),iStartx,iStarty,iEndx,iEndy);
+ return true;
+}
+
+bool KviKvsObject_painter::functionrotateMatrix(KviKvsObjectFunctionCall *c)
+{
+ kvs_real_t dAngle;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("angle",KVS_PT_DOUBLE,0,dAngle)
+ KVSO_PARAMETERS_END(c)
+ if(!m_pPainter)return true;
+ m_pMatrix.rotate(dAngle);
+ m_pPainter->setWorldMatrix( m_pMatrix,false );
+ return true;
+}
+bool KviKvsObject_painter::functiontranslateMatrix(KviKvsObjectFunctionCall *c)
+{
+ kvs_real_t dXtrasl,dYtrasl;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("trasl_x",KVS_PT_DOUBLE,0,dXtrasl)
+ KVSO_PARAMETER("trasl_y",KVS_PT_DOUBLE,0,dYtrasl)
+ KVSO_PARAMETERS_END(c)
+ if(!m_pPainter)return true;
+ QWMatrix tmpMatrix;
+ tmpMatrix.translate(dXtrasl,dYtrasl);
+ tmpMatrix = m_pMatrix * tmpMatrix;
+ m_pPainter->setWorldMatrix( tmpMatrix );
+ m_pMatrix=tmpMatrix;
+ return true;
+}
+bool KviKvsObject_painter::functionshearMatrix(KviKvsObjectFunctionCall *c)
+{
+ kvs_real_t dShearh,dShearv;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("shear_h",KVS_PT_DOUBLE,0,dShearh)
+ KVSO_PARAMETER("shear_v",KVS_PT_DOUBLE,0,dShearv)
+ KVSO_PARAMETERS_END(c)
+ if(!m_pPainter)return true;
+ m_pMatrix.shear(dShearh,dShearv);
+ m_pPainter->setWorldMatrix(m_pMatrix);
+ return true;
+}
+bool KviKvsObject_painter::functionscaleMatrix(KviKvsObjectFunctionCall *c)
+{
+ kvs_real_t dScalex,dScaley;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("scale_x",KVS_PT_DOUBLE,0,dScalex)
+ KVSO_PARAMETER("scale_y",KVS_PT_DOUBLE,0,dScaley)
+ KVSO_PARAMETERS_END(c)
+ if(!m_pPainter)return true;
+ m_pMatrix.scale(dScalex,dScaley);
+ m_pPainter->setWorldMatrix(m_pMatrix);
+ return true;
+}
+bool KviKvsObject_painter::functionresetMatrix(KviKvsObjectFunctionCall *c)
+
+{
+ if(!m_pPainter)return true;
+ m_pMatrix.reset();
+ m_pPainter->setWorldMatrix( m_pMatrix );
+ return true;
+}
+
+#ifdef COMPILE_USE_QT4
+bool KviKvsObject_painter::functionsetOpacity(KviKvsObjectFunctionCall *c)
+{
+ if(!m_pPainter)return true;
+ kvs_real_t dOpacity;
+
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("opacity_factor",KVS_PT_DOUBLE,0,dOpacity)
+ KVSO_PARAMETERS_END(c)
+ m_pPainter->setOpacity(dOpacity);
+ return true;
+}
+bool KviKvsObject_painter::functionsetTextAntialiasing(KviKvsObjectFunctionCall *c)
+{
+ if(!m_pPainter)return true;
+
+ bool bEnabled;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bEnabled",KVS_PT_BOOL,0,bEnabled)
+ KVSO_PARAMETERS_END(c)
+ m_pPainter->setRenderHint(QPainter::TextAntialiasing,bEnabled);
+ return true;
+}
+bool KviKvsObject_painter::functionsetAntialiasing(KviKvsObjectFunctionCall *c)
+{
+ if(!m_pPainter)return true;
+
+ bool bEnabled;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bEnabled",KVS_PT_BOOL,0,bEnabled)
+ KVSO_PARAMETERS_END(c)
+ m_pPainter->setRenderHint(QPainter::Antialiasing,bEnabled);
+ return true;
+}
+bool KviKvsObject_painter::functionsetSmoothPixmapTransform(KviKvsObjectFunctionCall *c)
+{
+ if(!m_pPainter)return true;
+
+ bool bEnabled;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bEnabled",KVS_PT_BOOL,0,bEnabled)
+ KVSO_PARAMETERS_END(c)
+ m_pPainter->setRenderHint(QPainter::SmoothPixmapTransform,bEnabled);
+ return true;
+}
+#endif
+
+
+
+#include "m_class_painter.moc"
diff --git a/src/modules/objects/class_painter.h b/src/modules/objects/class_painter.h
new file mode 100644
index 00000000..2ee8a5bb
--- /dev/null
+++ b/src/modules/objects/class_painter.h
@@ -0,0 +1,96 @@
+#ifndef _CLASS_PAINTER_H_
+#define _CLASS_PAINTER_H_
+//mdm:
+// Painter : class_painter.h
+// Creation date : Fri Mar 18 14:30:48 CEST 2005
+// by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+#include <qpainter.h>
+#include <qpaintdevice.h>
+#include "kvi_string.h"
+
+
+#include "object_macros.h"
+
+
+class KviKvsObject_painter : public KviKvsObject
+{
+ Q_OBJECT
+public:
+ KVSO_DECLARE_OBJECT(KviKvsObject_painter)
+protected:
+ QPainter * m_pPainter;
+ QWMatrix m_pMatrix;
+public:
+ bool functionSetFont(KviKvsObjectFunctionCall *c);
+ bool functionSetFontSize(KviKvsObjectFunctionCall *c);
+
+ bool functionfontAscent(KviKvsObjectFunctionCall *c);
+ bool functionfontDescent(KviKvsObjectFunctionCall *c);
+ bool functionfontMetricsWidth(KviKvsObjectFunctionCall *c);
+ bool functionfontMetricsHeight(KviKvsObjectFunctionCall *c);
+ bool functionsetBrush(KviKvsObjectFunctionCall *c);
+ bool functionsetPen(KviKvsObjectFunctionCall *c);
+ bool functionsetBackGroundMode(KviKvsObjectFunctionCall *c);
+
+ bool functiondrawRect(KviKvsObjectFunctionCall *c);
+ bool functiondrawWinFocusRect(KviKvsObjectFunctionCall *c);
+ bool functiondrawLine(KviKvsObjectFunctionCall *c);
+ bool functiondrawRoundRect(KviKvsObjectFunctionCall *c);
+ bool functiondrawPoint(KviKvsObjectFunctionCall *c);
+ bool functiondrawArc(KviKvsObjectFunctionCall *c);
+ bool functiondrawChord(KviKvsObjectFunctionCall *c);
+ bool functiondrawPie(KviKvsObjectFunctionCall *c);
+ bool functiondrawEllipse(KviKvsObjectFunctionCall *c);
+
+ bool functiondrawText(KviKvsObjectFunctionCall *c);
+ bool functiondrawPixmap(KviKvsObjectFunctionCall *c);
+
+
+ bool functionbegin(KviKvsObjectFunctionCall *c);
+ bool functionend(KviKvsObjectFunctionCall *c);
+
+ bool functionscaleMatrix(KviKvsObjectFunctionCall *c);
+ bool functionshearMatrix(KviKvsObjectFunctionCall *c);
+ bool functionrotateMatrix(KviKvsObjectFunctionCall *c);
+ bool functionresetMatrix(KviKvsObjectFunctionCall *c);
+ bool functiontranslateMatrix(KviKvsObjectFunctionCall *c);
+
+#ifdef COMPILE_USE_QT4
+ bool functionsetOpacity(KviKvsObjectFunctionCall *c);
+ bool functionsetSmoothPixmapTransform(KviKvsObjectFunctionCall *c);
+ bool functionsetTextAntialiasing(KviKvsObjectFunctionCall *c);
+ bool functionsetAntialiasing(KviKvsObjectFunctionCall *c);
+#endif
+
+
+
+protected:
+ void attachDevice(KviKvsObject * o,QPaintDevice * p);
+protected slots:
+ void detachDevice();
+private:
+ KviKvsObject * m_pDeviceObject;
+};
+#endif // !_CLASS_PAINTER_H_
+
+
+
diff --git a/src/modules/objects/class_pixmap.cpp b/src/modules/objects/class_pixmap.cpp
new file mode 100644
index 00000000..48aeb1e8
--- /dev/null
+++ b/src/modules/objects/class_pixmap.cpp
@@ -0,0 +1,317 @@
+//mdm:
+// Painter : class_pixmap.h
+// Creation date : Fri Mar 18 14:30:48 CEST 2005
+// by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
+// Lucia Papini (^ashura^) English Translation.
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "class_pixmap.h"
+#include "kvi_debug.h"
+
+#include "kvi_locale.h"
+#include <qfile.h>
+
+/*
+ @doc: pixmap
+ @keyterms:
+ pixmap object class
+ @title:
+ pixmap class
+ @type:
+ class
+ @short:
+ This class provide a pixmap.
+ @inherits:
+ [class]object[/class]
+ [class]widget[/class]
+ @description:
+ The pixmap class is an off-screen, pixel-based paint device.
+ @functions:
+ !fn: $fill(<widget:object>,<x_offset:integer>,<y:offset>)
+ Fills the pixmap with the widget's background color or pixmap.[br]
+ Note that x_offset, y_offest are offsets in the widget.
+ !fn: $resize(<width:integer>,<height:integer>)
+ Resizes the pixmap to w width and h height. Set wh or hg to 0, to have a null pixmap.
+ !fn: $scale(<sx:real>,<sy:real>)
+ Scales the pixmap by sx horizontally and sy vertically.
+ !fn: $rotate(<a:real>)
+ Rotates the pixmap by a degrees.
+ !fn: $load(<file_name:string>)
+ Load a pixmap from the <file>.
+ !fn: <integer> $height()
+ Return the height of the pixmap.
+ !fn: <integer> $width()
+ Return the width of the pixmap.
+
+*/
+
+
+KVSO_BEGIN_REGISTERCLASS(KviKvsObject_pixmap,"pixmap","object")
+
+ KVSO_REGISTER_HANDLER(KviKvsObject_pixmap,"fill",functionfill)
+ KVSO_REGISTER_HANDLER(KviKvsObject_pixmap,"resize",functionresize)
+ KVSO_REGISTER_HANDLER(KviKvsObject_pixmap,"load",functionload)
+ KVSO_REGISTER_HANDLER(KviKvsObject_pixmap,"height",functionheight)
+ KVSO_REGISTER_HANDLER(KviKvsObject_pixmap,"width",functionwidth)
+ KVSO_REGISTER_HANDLER(KviKvsObject_pixmap,"setOpacity",functionsetOpacity)
+ KVSO_REGISTER_HANDLER(KviKvsObject_pixmap,"scale",functionscale)
+ KVSO_REGISTER_HANDLER(KviKvsObject_pixmap,"rotate",functionrotate)
+
+KVSO_END_REGISTERCLASS(KviKvsObject_pixmap)
+
+
+KVSO_BEGIN_CONSTRUCTOR(KviKvsObject_pixmap,KviKvsObject)
+ m_pPixmap=new QPixmap();
+ m_pImage=new QImage();
+ bPixmapModified=false;
+ bImageModified=false;
+KVSO_END_CONSTRUCTOR(KviKvsObject_pixmap)
+
+
+KVSO_BEGIN_DESTRUCTOR(KviKvsObject_pixmap)
+
+ emit aboutToDie();
+ delete m_pPixmap;
+ if (m_pImage) delete m_pImage;
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_pixmap)
+
+
+bool KviKvsObject_pixmap::functionfill(KviKvsObjectFunctionCall *c)
+{
+ KviKvsObject *ob;
+ kvs_int_t iXoffset,iYoffset;
+ kvs_hobject_t hObject;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("widget",KVS_PT_HOBJECT,0,hObject)
+ KVSO_PARAMETER("x_offset",KVS_PT_INT,0,iXoffset)
+ KVSO_PARAMETER("y_offset",KVS_PT_INT,0,iYoffset)
+ KVSO_PARAMETERS_END(c)
+
+ ob=KviKvsKernel::instance()->objectController()->lookupObject(hObject);
+ if (!ob)
+ {
+ c->warning(__tr2qs("Widget parameter is not an object"));
+ return true;
+ }
+ if(!ob->object()->isWidgetType())
+ {
+ c->warning(__tr2qs("Widget object required"));
+ return true;
+ }
+ bPixmapModified=true;
+ m_pPixmap->fill(((QWidget *)(ob->object())),iXoffset,iYoffset);
+ return true;
+}
+
+bool KviKvsObject_pixmap::functionscale(KviKvsObjectFunctionCall *c)
+{
+ kvs_real_t uScaleX,uScaleY;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("sx",KVS_PT_REAL,0,uScaleX)
+ KVSO_PARAMETER("sy",KVS_PT_REAL,0,uScaleY)
+ KVSO_PARAMETERS_END(c)
+ #ifdef COMPILE_USE_QT4
+ *m_pPixmap = m_pPixmap->scaled((m_pPixmap->width() * uScaleX), (m_pPixmap->height() * uScaleX));
+ #else
+ QWMatrix wm;
+ wm.scale(uScaleX, uScaleY);
+ *m_pPixmap = m_pPixmap->xForm(wm);
+ #endif
+ bPixmapModified=true;
+ return true;
+}
+
+bool KviKvsObject_pixmap::functionrotate(KviKvsObjectFunctionCall *c)
+{
+ kvs_real_t uDegrees;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("a",KVS_PT_REAL,0,uDegrees)
+ KVSO_PARAMETERS_END(c)
+ #ifdef COMPILE_USE_QT4
+ QMatrix m;
+ m.rotate(uDegrees);
+ *m_pPixmap = m_pPixmap->transformed(m);
+ #else
+ QWMatrix wm;
+ wm.rotate(uDegrees);
+ *m_pPixmap = m_pPixmap->xForm(wm);
+ #endif
+ bPixmapModified=true;
+ return true;
+}
+
+bool KviKvsObject_pixmap::functionresize(KviKvsObjectFunctionCall *c)
+{
+ kvs_int_t uWidth,uHeight;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("width",KVS_PT_UNSIGNEDINTEGER,0,uWidth)
+ KVSO_PARAMETER("height",KVS_PT_UNSIGNEDINTEGER,0,uHeight)
+ KVSO_PARAMETERS_END(c)
+ m_pPixmap->resize(uWidth,uHeight);
+ bPixmapModified=true;
+ return true;
+}
+
+
+bool KviKvsObject_pixmap::functionload(KviKvsObjectFunctionCall *c)
+{
+ QString szFile;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("file",KVS_PT_STRING,0,szFile)
+ KVSO_PARAMETERS_END(c)
+
+ if(!QFile::exists(szFile))
+ {
+ c->warning(__tr2qs("I can't find the specified file %Q."),&szFile);
+ return true;
+ }
+ m_pPixmap->load(szFile);
+ bPixmapModified=true;
+ return true;
+}
+bool KviKvsObject_pixmap::functionheight(KviKvsObjectFunctionCall *c)
+{
+ c->returnValue()->setInteger(m_pPixmap->height());
+ return true;
+}
+bool KviKvsObject_pixmap::functionwidth(KviKvsObjectFunctionCall *c)
+{
+ c->returnValue()->setInteger(m_pPixmap->width());
+ return true;
+}
+bool KviKvsObject_pixmap::functionsetOpacity(KviKvsObjectFunctionCall *c)
+{
+ if(!m_pPixmap)return true;
+ kvs_real_t dOpacity;
+ kvs_uint_t uXoffset,uYoffset;
+ kvs_uint_t uWidth,uHeight;
+
+ KviKvsObject * pObDest;
+ kvs_hobject_t hObject;
+
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("opacity_factor",KVS_PT_DOUBLE,0,dOpacity)
+ KVSO_PARAMETER("destination",KVS_PT_HOBJECT,0,hObject)
+
+ KVSO_PARAMETER("x_offset",KVS_PT_UNSIGNEDINTEGER,KVS_PF_OPTIONAL,uXoffset)
+ KVSO_PARAMETER("y_offset",KVS_PT_UNSIGNEDINTEGER,KVS_PF_OPTIONAL,uYoffset)
+ KVSO_PARAMETER("width",KVS_PT_UNSIGNEDINTEGER,KVS_PF_OPTIONAL,uWidth)
+ KVSO_PARAMETER("height",KVS_PT_UNSIGNEDINTEGER,KVS_PF_OPTIONAL,uHeight)
+ KVSO_PARAMETERS_END(c)
+ pObDest=KviKvsKernel::instance()->objectController()->lookupObject(hObject);
+
+ if (!pObDest)
+ {
+ c->warning(__tr2qs("Destination parameter is not an object"));
+ return true;
+ }
+
+ if(!pObDest->inherits("KviKvsObject_pixmap"))
+ {
+ c->warning(__tr2qs("Destination must be a pixmap object"));
+ return true;
+ }
+ QImage *buffer=((KviKvsObject_pixmap *)pObDest)->getImage();
+ ((KviKvsObject_pixmap *)pObDest)->imageChanged();
+ if (bPixmapModified) {
+ *m_pImage=m_pPixmap->convertToImage();
+ }
+ if (uWidth>buffer->width() || uHeight>buffer->height())
+ {
+ c->warning(__tr2qs("Area dimensions are out of destination size "));
+ return true;
+ }
+ if (!uWidth){
+ if(m_pImage->width()>buffer->width())
+ {
+ c->warning(__tr2qs("Pixmap dimensions are out of destination size "));
+ return true;
+ }
+ }
+
+ if (!uHeight)
+ {
+ if(m_pImage->height()>buffer->height())
+ {
+ c->warning(__tr2qs("Pixmap dimensions are out of destination size "));
+ return true;
+ }
+ }
+
+
+if(uXoffset+uWidth>m_pImage->width())
+ {
+ c->warning(__tr2qs("Offset width area is out of pixmap size "));
+ return true;
+ }
+ if( uYoffset+uHeight>m_pImage->height())
+ {
+ c->warning(__tr2qs("Offset height area is out of pixmap size "));
+ return true;
+ }
+
+ buffer->setAlphaBuffer(true);
+ int iHedge=uHeight?uHeight:m_pImage->height();
+ int iWedge=uWidth?uWidth:m_pImage->width();
+
+ for(int y = uYoffset;y<iHedge;y++)
+ {
+ QRgb * dst = (QRgb *)buffer->scanLine(y);
+ QRgb * src = (QRgb *)m_pImage->scanLine(y);
+ src += uXoffset;
+ QRgb * end;
+ end = src + iWedge;
+ while(src < end)
+ {
+ *dst = qRgba(
+ (int)(qRed(*src)),
+ (int)(qGreen(*src)),
+ (int)(qBlue(*src)),
+ (int)(qAlpha(*src)*dOpacity)
+ );
+ src++;
+ dst++;
+ }
+ }
+ return true;
+}
+
+
+QPixmap * KviKvsObject_pixmap::getPixmap()
+{
+ if (bImageModified) {
+ m_pPixmap->convertFromImage(*m_pImage);
+ bImageModified=false;
+ }
+ return m_pPixmap;
+}
+QImage * KviKvsObject_pixmap::getImage()
+{
+ if (bPixmapModified) {
+ *m_pImage=m_pPixmap->convertToImage();
+ //debug ("image info2 %d and %d",test.width(),test.height());
+
+ bPixmapModified=false;
+ }
+
+ return m_pImage;
+}
+
+#include "m_class_pixmap.moc"
diff --git a/src/modules/objects/class_pixmap.h b/src/modules/objects/class_pixmap.h
new file mode 100644
index 00000000..22d1b95d
--- /dev/null
+++ b/src/modules/objects/class_pixmap.h
@@ -0,0 +1,72 @@
+#ifndef _CLASS_PIXMAP_H_
+#define _CLASS_PIXMAP_H_
+//vim: ts=8
+// Pixmap : class_pixmap.h
+// Creation date : Thu Sep 21 04:43:01 CEST 2000 by Krzysztof Godlewski
+//
+// This pixmap is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+
+#include <qpixmap.h>
+#include <qimage.h>
+#ifdef COMPILE_USE_QT4
+ #include <QMatrix>
+#else
+ #include <qwmatrix.h>
+#endif
+#include "kvi_string.h"
+
+
+#include "object_macros.h"
+
+
+class KviKvsObject_pixmap : public KviKvsObject
+{
+ Q_OBJECT
+// Q_PROPERTY(QPixmap pixmap READ getPixmap)
+public:
+ KVSO_DECLARE_OBJECT(KviKvsObject_pixmap);
+ QPixmap * getPixmap();
+ QImage * getImage();
+ void pixmapChanged(){bPixmapModified=true;}
+ void imageChanged(){bImageModified=true;}
+
+ QPixmap * pixmap(){ return m_pPixmap; }
+protected:
+ QPixmap * m_pPixmap;
+ QImage * m_pImage;
+ bool bImageModified;
+ bool bPixmapModified;
+signals:
+ void aboutToDie();
+
+protected:
+ bool functionfill(KviKvsObjectFunctionCall *c);
+ bool functionresize(KviKvsObjectFunctionCall *c);
+ bool functionscale(KviKvsObjectFunctionCall *c);
+ bool functionrotate(KviKvsObjectFunctionCall *c);
+ bool functionload(KviKvsObjectFunctionCall *c);
+ bool functionheight(KviKvsObjectFunctionCall *c);
+ bool functionwidth(KviKvsObjectFunctionCall *c);
+ bool functionsetOpacity(KviKvsObjectFunctionCall *c);
+
+ };
+
+#endif // !_CLASS_PIXMAP_H_
diff --git a/src/modules/objects/class_popupmenu.cpp b/src/modules/objects/class_popupmenu.cpp
new file mode 100644
index 00000000..a3db5339
--- /dev/null
+++ b/src/modules/objects/class_popupmenu.cpp
@@ -0,0 +1,361 @@
+//mdm :
+// File : class_popupmenu.cpp
+// Creation date : Mon Feb 01 21:30:48 CEST 2005
+// by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
+// Lucia Papini (^ashura^) English Translation.
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+#include "class_popupmenu.h"
+#include "kvi_error.h"
+
+#include "kvi_debug.h"
+
+#include "kvi_locale.h"
+#include "kvi_iconmanager.h"
+
+
+/*
+ @doc: popupmenu
+ @keyterms:
+ popupmenu object class,
+ @title:
+ popupmenu class
+ @type:
+ class
+ @short:
+ Provides a popup menu.
+ @inherits:
+ [class]object[/class]
+ [class]widget[/class]
+ @description:
+ This widget can be used to display a popup menu.Technically, a popup menu consists of a list of menu items.[br]
+ You add items with insertItem(). An item is either a string. In addition, items can have an optional icon drawn on the very left side.[br]
+ @functions:
+ !fn: $insertItem(<text:string>,[icon_id:string])
+ Inserts menu items into a popup menu with optional icon and return the popup identifier.
+ !fn: $insertWidget(<widget:object>)[br]
+ Inserts widget items int a popup menu and return the popup identifier.[br]
+ The widget is treats as a separator; this means that the item is not selectable and you can, for example, simply insert a label if you need a popup menu with a title.
+ !fn: $insertHandle(<text_label:string>,<popupmenu:object>,[icon])
+ Inserts a submenu with optional icon into the popup menu.
+ !fn: $exec([<widget:objects>,<x:uinteger>,<y:integer>])
+ If called without paramaters show the popup menu at the current pointer position.[br]
+ With the optional parameters show the popup menu at the coordinate x,y widget parameter relative.
+ !fn: $removeItem(<popup_id:Uinteger>)
+ Removes the menu item that has the identifier id.
+ !fn: $removeItemAt(<index:uinteger>)
+ Removes the menu item at position index.
+ !fn: $insertSeparator(<index:uinteger>)
+ Inserts a separator at position index.[br]
+ If the index is negative the separator becomes the last menu item.
+ !fn: $activatedEvent(<popup_id:uinteger>)
+ This function is called when a menu item and return the the item id.[br]
+ The default implementation emits the [classfnc]$activated[/classfnc]() signal.
+ !fn: $highligthtedEvent(<popup_id:uinteger>)
+ This function is called when a menu item is highlighted and return the item id.[br]
+ The default implementation emits the [classfnc]$highlighted[/classfnc]() signal.
+ @signals:
+ !sg: $activated()
+ This signal is emitted by the default implementation of [classfnc]$activatedEvent[/classfnc]().
+ !sg: $highlighted()
+ This signal is emitted by the default implementation of [classfnc]$highlightedEvent[/classfnc]().
+ [br]
+ |-EXAMPLE POPUP MENU-|[br]
+ |--Start:
+ # First of all we create an array wich will be used to create random colors.[br]
+ %Hex[]=$array(0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F)[br]
+ [br]
+ class (ws,widget)[br]
+ {[br]
+ #In the constructor we create everything that belong to the single widget.[br]
+ constructor[br]
+ {[br]
+ #Geometry of the widget and setting-up of popupmenu [br]
+ $$->$setGeometry(%X,%Y,100,100)[br]
+ $$->%lay=$new(layout,$$)[br]
+ #Here we generate a cicle to create our labels inside the widget.[br]
+ %i=0[br]
+ while (%i<10)[br]
+ {[br]
+ $$->%label=$new(label,$$)[br]
+ $$->%label->$settext("Another class by N\&G")[br]
+ #We set our foreground's coulor using the hex arrey in random way.[br]
+ %color=%Hex[$rand(14)]%Hex[$rand(14)]%Hex[$rand(14)]%Hex[$rand(14)]%Hex[$rand(14)]%Hex[$rand(14)][br]
+ $$->%label->$setforegroundcolor(%color)[br]
+ $$->%label->$setautoresize(1)[br]
+ #We add the label to the widget's popupmenu.[br]
+ $$->%lay->$addwidget($$->%label,%i,0)[br]
+ %i++;[br]
+ }[br]
+ #We make the popupmenu relative to this widget: this is merely demonstrative.[br]
+ #because it creates 25 identical popups.[br]
+ $$->%Popupmenu=$new(popupmenu,$$)[br]
+ #we create the label widget wich will be used as popup's title[br]
+ $$->%Popuptitle=$new(label)[br]
+ $$->%Popuptitle->$settext(<B><U>"Windows Options"</B></U>)[br]
+ $$->%Popuptitle->$setAlignment(Center)[br]
+ #and we add it.[br]
+ %A=$$->%Popuptitle[br]
+ $$->%Popupmenu->$insertwidget(%A)[br]
+ #Here we keep the various IDs in the arrays[br]
+ %Tile[%I]=$$->%Popupmenu->$insertItem("Tile",118)[br]
+ %Cascade[%I]=$$->%Popupmenu->$insertItem("Cascade",115)[br]
+ $$->%Popupmenu->$insertSeparator(3)[br]
+ %Closeactw[%I]=$$->%Popupmenu->$insertItem("Close Active Window",08)[br]
+ %Closeallw[%I]=$$->%Popupmenu->$insertItem("Close All Window",58)[br]
+ $$->$show()[br]
+ privateimpl($$->%Popupmenu,activatedEvent)[br]
+ {[br]
+ %id=$0[br]
+ %i = 0[br]
+ #with this cicle we control wich of the items has been called comparing the id given back by the event with our arrays created before;[br]
+ while (%i<20)[br]
+ {[br]
+ if (%id == %Tile[%i]) return %Workspace->$tile()[br]
+ if (%id == %Cascade[%i]) return %Workspace->$cascade()[br]
+ if (%id == %Closeactw[%i]) return %Workspace->$closeactivewindow()[br]
+ if (%id == %Closeallw[%i]) return %Workspace->$closeallwindows()[br]
+ %i ++[br]
+ }[br]
+ }[br]
+ }[br]
+ #we activate the popup pushing the right mouse button on the widget[br]
+ mousepressevent[br]
+ {[br]
+ if ($0 == 1) $$->%Popupmenu->$exec()[br]
+ }[br]
+ }[br]
+ %Workspace=$new(workspace)[br]
+ %Workspace->$resize(640,480)[br]
+ %I=0[br]
+ %Cicle=1[br]
+ while (%I<20)[br]
+ {[br]
+ %X=$rand(500)[br]
+ %Y=$rand(480)[br]
+ %Widget=$new(ws,%Workspace)[br]
+ %I++[br]
+ }[br]
+ #Let's show!
+ %Workspace->$show[br]
+ |--End.[br][br]
+*/
+
+KVSO_BEGIN_REGISTERCLASS(KviKvsObject_popupmenu,"popupmenu","widget")
+ KVSO_REGISTER_HANDLER(KviKvsObject_popupmenu,"insertItem", functioninsertItem)
+ KVSO_REGISTER_HANDLER(KviKvsObject_popupmenu,"insertWidget", functioninsertWidget)
+ KVSO_REGISTER_HANDLER(KviKvsObject_popupmenu,"insertHandle", functioninsertHandle)
+ KVSO_REGISTER_HANDLER(KviKvsObject_popupmenu,"exec", functionexec)
+ KVSO_REGISTER_HANDLER(KviKvsObject_popupmenu,"insertSeparator", functioninsertSeparator)
+ KVSO_REGISTER_HANDLER(KviKvsObject_popupmenu,"removeItem", functionremoveItem)
+ KVSO_REGISTER_HANDLER(KviKvsObject_popupmenu,"removeItemAt", functionremoveItemAt)
+
+ // events
+ KVSO_REGISTER_HANDLER(KviKvsObject_popupmenu,"highlightedEvent", functionhighlightedEvent)
+ KVSO_REGISTER_HANDLER(KviKvsObject_popupmenu,"activatedEvent", functionactivatedEvent)
+
+KVSO_END_REGISTERCLASS(KviKvsObject_popupmenu)
+
+KVSO_BEGIN_CONSTRUCTOR(KviKvsObject_popupmenu,KviKvsObject_widget)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_popupmenu)
+
+
+KVSO_BEGIN_DESTRUCTOR(KviKvsObject_popupmenu)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_popupmenu)
+
+bool KviKvsObject_popupmenu::init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams)
+{
+ setObject(new KviTalPopupMenu(parentScriptWidget(), name()), true);
+ connect(widget(),SIGNAL(activated(int)),this,SLOT(slotactivated(int)));
+ connect(widget(),SIGNAL(highlighted(int)),this,SLOT(slothighlighted(int)));
+ return true;
+}
+
+bool KviKvsObject_popupmenu::functioninsertItem(KviKvsObjectFunctionCall *c)
+{
+ QString szItem,szIcon;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("text",KVS_PT_STRING,0,szItem)
+ KVSO_PARAMETER("icon_id",KVS_PT_STRING,KVS_PF_OPTIONAL,szIcon)
+ KVSO_PARAMETERS_END(c)
+ if(!widget())return true;
+ QPixmap *pix = 0;
+ int id=0;
+ if(!szIcon.isEmpty())
+ {
+ pix = g_pIconManager->getImage(szIcon);
+ if (pix) id=((KviTalPopupMenu *)widget())->insertItem(*pix,szItem);
+ else c->warning(__tr2qs("pix '%Q' doesn't exists"),&szIcon);
+
+ }
+ else
+ id=((KviTalPopupMenu *)widget())->insertItem(szItem);
+ c->returnValue()->setInteger(id);
+ return true;
+}
+bool KviKvsObject_popupmenu::functioninsertWidget(KviKvsObjectFunctionCall *c)
+{
+ KviKvsObject *pObject;
+ kvs_hobject_t hObject;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("widget",KVS_PT_HOBJECT,0,hObject)
+ KVSO_PARAMETERS_END(c)
+ pObject=KviKvsKernel::instance()->objectController()->lookupObject(hObject);
+ if (!pObject)
+ {
+ c->warning(__tr2qs("Widget parameter is not an object"));
+ return true;
+ }
+ if (!pObject->object())
+ {
+ c->warning(__tr2qs("Widget parameter is not a valid object"));
+ return true;
+ }
+ if(!pObject->object()->isWidgetType())
+ {
+ c->warning(__tr2qs("Can't add a non-widget object"));
+ return TRUE;
+ }
+ if (widget()) ((KviTalPopupMenu *)widget())->insertItem(((KviTalPopupMenu *)(pObject->object())));
+ return true;
+}
+bool KviKvsObject_popupmenu::functioninsertHandle(KviKvsObjectFunctionCall *c)
+{
+ KviKvsObject *ob;
+ QString szLabel,szIcon;
+ kvs_hobject_t hObject;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("text_label",KVS_PT_STRING,0,szLabel)
+ KVSO_PARAMETER("widget",KVS_PT_HOBJECT,0,hObject)
+ KVSO_PARAMETER("icon_id",KVS_PT_STRING,KVS_PF_OPTIONAL,szIcon)
+ KVSO_PARAMETERS_END(c)
+ ob=KviKvsKernel::instance()->objectController()->lookupObject(hObject);
+ if(!ob->object()->inherits("KviKvsObject_popupmenu"))
+ {
+ c->warning(__tr2qs("Can't add a non - popupmenu object"));
+ return TRUE;
+ }
+ if(!widget())return true;
+ QPixmap *pix = 0;
+ int id=0;
+ if(!szIcon.isEmpty())
+ {
+ pix = g_pIconManager->getImage(szIcon);
+ if (pix) id=((KviTalPopupMenu *)widget())->insertItem(*pix,szLabel,((KviTalPopupMenu *)(ob->object())));
+ else c->warning(__tr2qs("pix '%Q' doesn't exists"),&szIcon);
+
+ }
+ else
+ id=((KviTalPopupMenu *)widget())->insertItem(szLabel,((KviTalPopupMenu *)(ob->object())));
+ c->returnValue()->setInteger(id);
+ return true;
+}
+bool KviKvsObject_popupmenu::functionexec(KviKvsObjectFunctionCall *c)
+{
+ if(!c->params()->count())
+ {
+ ((KviTalPopupMenu *)widget())->exec(QCursor::pos());
+ return true;
+ }
+
+ KviKvsObject *pObject;
+ kvs_uint_t iX,iY;
+ QString szLabel,szIcon;
+ kvs_hobject_t hObject;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("widget",KVS_PT_HOBJECT,0,hObject)
+ KVSO_PARAMETER("x",KVS_PT_UNSIGNEDINTEGER,0,iX)
+ KVSO_PARAMETER("y",KVS_PT_UNSIGNEDINTEGER,0,iY)
+ KVSO_PARAMETERS_END(c)
+ pObject=KviKvsKernel::instance()->objectController()->lookupObject(hObject);
+ if (!pObject)
+ {
+ c->warning(__tr2qs("Widget parameter is not an object"));
+ return true;
+ }
+ if (!pObject->object())
+ {
+ c->warning(__tr2qs("Widget parameter is not a valid object"));
+ return true;
+ }
+ if(!pObject->object()->isWidgetType())
+ {
+ c->warning(__tr2qs("Doesn't a widget object"));
+ return true;
+ }
+
+ ((KviTalPopupMenu *)widget())->exec(((QWidget *)(pObject->object()))->mapToGlobal(QPoint(iX,iY)) );
+
+ return true;
+}
+bool KviKvsObject_popupmenu::functionremoveItem(KviKvsObjectFunctionCall *c)
+{
+ kvs_uint_t uItem;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("item_id",KVS_PT_UNSIGNEDINTEGER,0,uItem)
+ KVSO_PARAMETERS_END(c)
+ if(widget()) ((KviTalPopupMenu *)widget())->removeItem(uItem);
+ return true;
+}
+bool KviKvsObject_popupmenu::functionremoveItemAt(KviKvsObjectFunctionCall *c)
+{
+ kvs_uint_t uIndex;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("index",KVS_PT_UNSIGNEDINTEGER,0,uIndex)
+ KVSO_PARAMETERS_END(c)
+ if(widget())((KviTalPopupMenu *)widget())->removeItemAt(uIndex);
+ return true;
+}
+
+bool KviKvsObject_popupmenu::functioninsertSeparator(KviKvsObjectFunctionCall *c)
+{
+ kvs_uint_t uIndex;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("index",KVS_PT_UNSIGNEDINTEGER,0,uIndex)
+ KVSO_PARAMETERS_END(c)
+ if(widget())((KviTalPopupMenu *)widget())->insertSeparator(uIndex);
+ return true;
+}
+
+void KviKvsObject_popupmenu::slothighlighted(int i)
+{
+ KviKvsVariantList params(new KviKvsVariant((kvs_int_t)i));
+ callFunction(this,"highlightedEvent",&params);
+}
+bool KviKvsObject_popupmenu::functionhighlightedEvent(KviKvsObjectFunctionCall *c)
+{
+ emitSignal("highlighted",c,c->params());
+ return true;
+}
+void KviKvsObject_popupmenu::slotactivated(int i)
+{
+ KviKvsVariantList params(new KviKvsVariant((kvs_int_t)i));
+ callFunction(this,"activatedEvent",&params);
+}
+bool KviKvsObject_popupmenu::functionactivatedEvent(KviKvsObjectFunctionCall *c)
+{
+ emitSignal("activated",c,c->params());
+ return true;
+}
+
+
+#include "m_class_popupmenu.moc"
diff --git a/src/modules/objects/class_popupmenu.h b/src/modules/objects/class_popupmenu.h
new file mode 100644
index 00000000..e5960119
--- /dev/null
+++ b/src/modules/objects/class_popupmenu.h
@@ -0,0 +1,58 @@
+#ifndef _CLASS_POPUPMENU_H_
+#define _CLASS_POPUPMENU_H_
+//mdm:
+// File : class_popupMenu.h
+// Creation date : Mon Gen 27 14:30:48 CEST 2005
+// by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+#include "kvi_tal_popupmenu.h"
+#include <qcursor.h>
+#include "class_widget.h"
+#include "object_macros.h"
+
+class KviKvsObject_popupmenu : public KviKvsObject_widget
+{
+ Q_OBJECT
+public:
+ KVSO_DECLARE_OBJECT(KviKvsObject_popupmenu)
+public:
+ QWidget * widget() { return (QWidget *)object(); };
+protected:
+ virtual bool init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams);
+
+ bool functioninsertItem(KviKvsObjectFunctionCall *c);
+ bool functioninsertWidget(KviKvsObjectFunctionCall *c);
+ bool functioninsertHandle(KviKvsObjectFunctionCall *c);
+ bool functionexec(KviKvsObjectFunctionCall *c);
+ bool functionremoveItem(KviKvsObjectFunctionCall *c);
+ bool functionremoveItemAt(KviKvsObjectFunctionCall *c);
+ bool functioninsertSeparator(KviKvsObjectFunctionCall *c);
+ bool functionactivatedEvent(KviKvsObjectFunctionCall *c);
+ bool functionhighlightedEvent(KviKvsObjectFunctionCall *c);
+
+protected slots:
+ void slotactivated(int);
+ void slothighlighted(int);
+};
+
+#endif // !_CLASS_POPUPMENU_H_
+
diff --git a/src/modules/objects/class_process.cpp b/src/modules/objects/class_process.cpp
new file mode 100644
index 00000000..81efaae4
--- /dev/null
+++ b/src/modules/objects/class_process.cpp
@@ -0,0 +1,317 @@
+//mdm:
+// File : class_process.h
+// Creation date : Thu Feb 1 14:39:48 CEST 2005
+// by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+
+#include "class_process.h"
+#include "kvi_error.h"
+#include "kvi_debug.h"
+#include "kvi_settings.h"
+#include "kvi_locale.h"
+#include <qtimer.h>
+#ifdef COMPILE_USE_QT4
+#include <q3process.h>
+#else
+#include <qprocess.h>
+#endif
+
+/*
+ @doc: process
+ @keyterms:
+ process object class, process
+ @title:
+ process class
+ @type:
+ class
+ @short:
+ A class to manage process.
+ @inherits:
+ [class]object[/class]
+ @description:
+ The Process class is used to start external programs and to communicate with them.[br]
+ !WARNING AT LAST YOU HAVE TO CLOSE THE PROCESS!
+ @functions:
+ !fn: $addArg(<process-name:string>)
+ With this command you give the process name (or more arguments) for comunication.
+ Es: see the next example.
+ !fn: $start()
+ Tries to run the process.[br]
+ Es: [br]
+ %process=$new(process);[br]
+ %process->$addArg("cmd.exe");[br]
+ %process->$start();[br]
+ !fn: <string> $readStdout()
+ Reads the data that the process has written to standard output.
+ !fn: <string> $readStderr()
+ Reads the data that the process has written to standard error.
+ Es:[br]
+ -------------------Start:[br]
+ class (test,object)[br]
+ {[br]
+ slotReadStdout()[br]
+ {[br]
+ %stdo = %Process->$readStdout()[br]
+ #%Aoutput->$append(%stdo);// coming soon in the new texteditor class[br]
+ %Aoutput->$settext(%stdo);[br]
+ }[br]
+ slotReadStderr()[br]
+ {[br]
+ %stderr= %Process->$readStderr()[br]
+ #%Aoutput->$append(%stderr);// coming soon in the new texteditor class[br]
+ %Aoutput->$settext(%stderr);[br]
+ }[br]
+ }[br]
+
+ %tt=$new(test)[br]
+ %A=$new(widget)[br]
+ %A->$setGeometry(100,100,400,300)[br]
+ %layoutA=$new(layout,%A)[br]
+ %Ainput=$new(lineedit,%A)[br]
+ #%Aoutput=$new(textedit,%A)// coming soon in the new texteditor class[br]
+ %Aoutput=$new(label,%A)[br]
+ %bclosekill=$new(button,%A)[br]
+ %bclosekill->$settext("&CloseKill ")[br]
+ %bkill=$new(button,%A)[br]
+ %bkill->$settext("&Kill ")[br]
+ %bterminate=$new(button,%A)[br]
+ %bterminate->$settext("&Ask to Terminate ")[br]
+ %layoutA->$addwidget(%Ainput,0,0)[br]
+ %layoutA->$addwidget(%Aoutput,1,0)[br]
+ %layoutA->$addwidget(%bclosekill,3,0)[br]
+ %layoutA->$addwidget(%bkill,4,0,)[br]
+ %layoutA->$addwidget(%bterminate,5,0)[br]
+
+ %Process=$new(process)[br]
+ %Process->$addArg("cmd.exe")[br]
+ %Process->$start();[br]
+
+ connect %Process readyReadStdout %tt slotReadStdout[br]
+ connect %Process readyReadStderr %tt slotReadStderr[br]
+ privateimpl(%Ainput,returnPressedEvent)[br]
+ {
+ %command=%Ainput->$text() "\r\n"[br]
+ %Process->$writeToStdin(%command);[br]
+ %Ainput->$setText("");[br]
+ }[br]
+
+ privateimpl(%bclosekill,mousepressevent)[br]
+ {[br]
+ %Process->$closekill();[br]
+ delete %A;[br]
+ }[br]
+ privateimpl(%bkill,mousepressevent)[br]
+ {[br]
+ %Process->$kill();[br]
+ delete %A;[br]
+ }[br]
+ privateimpl(%bterminate,mousepressevent)[br]
+ {[br]
+ %Process->$tryTerminate();[br]
+ delete %A;[br]
+ }[br]
+ %A->$show();[br]
+ --------------------End.[br]
+ !fn: $writeToStdin(<command:string>)
+ Whit this command you send a command to the process:
+ !fn: $closekill()
+ This tries to terminate the process the nice way.[br]
+ If the process is still running after 5 seconds, it terminates the process the hard way.[br]
+ (I think that this is the better way.)[br]
+ Es:
+ %Process->close_kill();
+ !fn: $kill()
+ Kill the process in hard way.(Bad Idea)
+ !fn: $tryTerminate()
+ Tries to terminate the process.(It could be well but...)
+ !fn: $closeStdin()
+ Close the standard Input.
+ !fn: <boolean> $isRunning()
+ Return 1 if the process is running, else return 0.
+ !fn: <boolean> $normalExit()
+ Returns TRUE if the process has exited normally; otherwise returns FALSE.
+ !fn: $readyReadStdoutEvent()
+ This function is invoched by the process when there are new datas.[br]
+ The default implementation emits the [classfnc]$readyReadStdout[/classfnc]() signal.
+ !fn: $readyReadStderrEvent()
+ This function is invoched by the process when there are new error messages.[br]
+ The default implementation emits the [classfnc]$readyReadStderr[/classfnc]() signal.
+
+ @signals:
+ !sg: $readyReadStdout()
+ This signal is emitted by the default implementation of [classfnc]$readyReadStdoutEvent[/classfnc]().[br]
+ If you reimplement that function you will have to emit the signal manually (if you still need it).
+ !sg: $readyReadStderr()
+ This signal is emitted by the default implementation of [classfnc]$readyReadStderrEvent[/classfnc]().
+*/
+
+KVSO_BEGIN_REGISTERCLASS(KviKvsObject_process,"process","object")
+
+ KVSO_REGISTER_HANDLER(KviKvsObject_process,"addArg", functionaddArgument);
+ KVSO_REGISTER_HANDLER(KviKvsObject_process,"start", functionstartProcess);
+ KVSO_REGISTER_HANDLER(KviKvsObject_process,"readStdout", functionreadStdout);
+ KVSO_REGISTER_HANDLER(KviKvsObject_process,"readStderr", functionreadStderr);
+ KVSO_REGISTER_HANDLER(KviKvsObject_process,"writeToStdin", functionwriteToStdin);
+ KVSO_REGISTER_HANDLER(KviKvsObject_process,"closekill", functionclosekill);
+ KVSO_REGISTER_HANDLER(KviKvsObject_process,"kill", functionkill);
+ KVSO_REGISTER_HANDLER(KviKvsObject_process,"tryTerminate", functiontryTerminate);
+ KVSO_REGISTER_HANDLER(KviKvsObject_process,"closeStdin", functioncloseStdin);
+ KVSO_REGISTER_HANDLER(KviKvsObject_process,"isRunning",functionisRunning);
+ KVSO_REGISTER_HANDLER(KviKvsObject_process,"normalExit",functionnormalExit);
+
+ // Events
+ KVSO_REGISTER_HANDLER(KviKvsObject_process,"readyReadStdoutEvent",functionreadyReadStdoutEvent);
+ KVSO_REGISTER_HANDLER(KviKvsObject_process,"readyReadStderrEvent",functionreadyReadStderrEvent);
+
+ KVSO_END_REGISTERCLASS(KviKvsObject_process)
+
+
+KVSO_BEGIN_CONSTRUCTOR(KviKvsObject_process,KviKvsObject)
+
+#ifdef COMPILE_USE_QT4
+ m_pProcess = new Q3Process();
+#else
+ m_pProcess = new QProcess();
+#endif
+ connect(m_pProcess,SIGNAL(readyReadStdout()),this,SLOT(slotReadStdout()));
+ connect(m_pProcess,SIGNAL(readyReadStderr()),this,SLOT(slotReadStderr()));
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_process)
+
+KVSO_BEGIN_DESTRUCTOR(KviKvsObject_process)
+
+ delete m_pProcess;
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_process)
+
+
+
+bool KviKvsObject_process::functionaddArgument(KviKvsObjectFunctionCall *c)
+{
+
+ QString szArgument;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("argument",KVS_PT_NONEMPTYSTRING,0,szArgument)
+ KVSO_PARAMETERS_END(c)
+ if (m_pProcess) m_pProcess->addArgument(szArgument);
+ return true;
+}
+
+//->Start the process.
+bool KviKvsObject_process::functionstartProcess(KviKvsObjectFunctionCall *c)
+{
+
+ if(!(m_pProcess->start()))
+ c->warning( __tr2qs("Process could not be starded."));
+ return true;
+}
+//-->Read the standard output.
+bool KviKvsObject_process::functionreadStderr(KviKvsObjectFunctionCall *c)
+{
+ QString ng_Process =m_pProcess->readStderr();
+ c->returnValue()->setString(ng_Process);
+ return true;
+}
+
+//-->Read the standard error.
+bool KviKvsObject_process::functionreadStdout(KviKvsObjectFunctionCall *c)
+{
+ QString ng_Process =m_pProcess->readStdout();
+ c->returnValue()->setString(ng_Process);
+ return true;
+}
+//-->Signals and slot to manage reading output and error from the process.
+bool KviKvsObject_process::functionreadyReadStdoutEvent(KviKvsObjectFunctionCall *c)
+{
+
+ emitSignal("readyReadStdout",c);
+ return true;
+
+}
+
+bool KviKvsObject_process::functionreadyReadStderrEvent(KviKvsObjectFunctionCall *c)
+{
+
+ emitSignal("readyReadStderr",c);
+ return true;
+
+}
+bool KviKvsObject_process::functionwriteToStdin(KviKvsObjectFunctionCall *c)
+{
+
+ QString szCommand;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("command",KVS_PT_STRING,0,szCommand)
+ KVSO_PARAMETERS_END(c)
+ if (m_pProcess) m_pProcess->writeToStdin(szCommand);
+
+ return true;
+}
+//-->The 3 Closing process functions
+bool KviKvsObject_process::functionclosekill(KviKvsObjectFunctionCall *c)
+{
+ //I try to to terminate the process the nice way....
+ m_pProcess->tryTerminate();
+ //If the process is still running after 5 seconds, I'll terminate the process in the hard way.
+ QTimer::singleShot( 5000, m_pProcess, SLOT( kill() ) );
+ return true;
+}
+bool KviKvsObject_process::functionkill(KviKvsObjectFunctionCall *c)
+{
+ m_pProcess->kill();
+ return true;
+}
+bool KviKvsObject_process::functiontryTerminate(KviKvsObjectFunctionCall *c)
+{
+ m_pProcess->tryTerminate();
+ return true;
+}
+//-->Close the standard input.
+bool KviKvsObject_process::functioncloseStdin(KviKvsObjectFunctionCall *c)
+{
+
+ m_pProcess->closeStdin();
+ return true;
+}
+//->Returns if the process still runnig
+bool KviKvsObject_process::functionisRunning(KviKvsObjectFunctionCall *c)
+{
+ c->returnValue()->setBoolean(m_pProcess->isRunning());
+ return true;
+}
+//->Returns if the process exited.
+bool KviKvsObject_process::functionnormalExit(KviKvsObjectFunctionCall *c)
+{
+ c->returnValue()->setBoolean(m_pProcess->normalExit());
+ return true;
+}
+
+void KviKvsObject_process::slotReadStdout()
+{
+ KviKvsVariantList *params=0;
+ callFunction(this,"readyReadStdoutEvent",params);
+}
+
+void KviKvsObject_process::slotReadStderr()
+{
+ KviKvsVariantList *params=0;
+ callFunction(this,"readyReadStderrEvent",params);
+}
+
+#include "m_class_process.moc"
diff --git a/src/modules/objects/class_process.h b/src/modules/objects/class_process.h
new file mode 100644
index 00000000..70842950
--- /dev/null
+++ b/src/modules/objects/class_process.h
@@ -0,0 +1,74 @@
+#ifndef _CLASS_PROCESS_H_
+#define _CLASS_PROCESS_H_
+//mdm:
+// File : class_process.h
+// Creation date : Thu Feb 1 14:39:48 CEST 2005
+// by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+
+
+#include <qtimer.h>
+#include "class_widget.h"
+
+
+#include "object_macros.h"
+#ifdef COMPILE_USE_QT4
+#include <q3process.h>
+#else
+#include <qprocess.h>
+#endif
+
+
+class KviKvsObject_process : public KviKvsObject
+{
+ Q_OBJECT
+public:
+ KVSO_DECLARE_OBJECT(KviKvsObject_process)
+protected:
+
+#ifdef COMPILE_USE_QT4
+ Q3Process * m_pProcess;
+#else
+ QProcess * m_pProcess;
+#endif
+
+public:
+
+ bool functionaddArgument(KviKvsObjectFunctionCall *c);
+ bool functionstartProcess(KviKvsObjectFunctionCall *c);
+ bool functionreadStdout(KviKvsObjectFunctionCall *c);
+ bool functionreadStderr(KviKvsObjectFunctionCall *c);
+ bool functionwriteToStdin(KviKvsObjectFunctionCall *c);
+ bool functionclosekill(KviKvsObjectFunctionCall *c);
+ bool functioncloseStdin(KviKvsObjectFunctionCall *c);
+ bool functionkill(KviKvsObjectFunctionCall *c);
+ bool functiontryTerminate(KviKvsObjectFunctionCall *c);
+ bool functionnormalExit(KviKvsObjectFunctionCall *c);
+ bool functionisRunning(KviKvsObjectFunctionCall *c);
+
+ bool functionreadyReadStdoutEvent(KviKvsObjectFunctionCall *c);
+ bool functionreadyReadStderrEvent(KviKvsObjectFunctionCall *c);
+
+protected slots:
+ void slotReadStdout();
+ void slotReadStderr();
+};
+
+
+#endif // !_CLASS_PROCESS_H_
diff --git a/src/modules/objects/class_progressbar.cpp b/src/modules/objects/class_progressbar.cpp
new file mode 100644
index 00000000..12fc5b39
--- /dev/null
+++ b/src/modules/objects/class_progressbar.cpp
@@ -0,0 +1,162 @@
+//
+// File : class_progressbar.cpp
+// Creation date : Fri Jan 28 14:21:48 CEST 2005
+// by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "class_progressbar.h"
+#include "kvi_error.h"
+#include "kvi_debug.h"
+
+#include "kvi_locale.h"
+#include "kvi_iconmanager.h"
+#ifdef COMPILE_USE_QT4
+#include <q3progressbar.h>
+#define KVI_PROGRESS_BAR Q3ProgressBar
+#else
+#include <qprogressbar.h>
+#define KVI_PROGRESS_BAR QProgressBar
+#endif
+
+/*
+ @doc: progressbar
+ @keyterms:
+ progressbar object class,
+ @title:
+ progressbar class
+ @type:
+ class
+ @short:
+ Provides a horizontal progress bar.
+ @inherits:
+ [class]object[/class]
+ [class]widget[/class]
+ @description:
+ This widget can be used to display a horizontal progress bar.
+ @functions:
+ !fn: $setProgress(<steps_value:uinteger>)
+ Set the amount of steps completed.
+ See also [classfnc]$settotalSteps[/classfnc]()
+ !fn: $settotalSteps(<total_steps:uinteger>)
+ The progress bar uses the concept of steps; you give it the total number of steps
+ and the number of steps completed so far and it will display the percentage of steps that have been completed.
+ See also [classfnc]$setProgress[/classfnc]()
+ !fn: $reset()
+ Reset the progress bar.
+ !fn: $setCenterIndicator(<bEnabled:boolean>)
+ Sets whether the indicator string should be centered to on.
+ See also [classfnc]$isCenterIndicator[/classfnc]()
+ !fn: <boolean> $isCenterIndicator()
+ This property holds whether the indicator string should be centered.
+ See also [classfnc]$setCenterIndicator[/classfnc]()
+ !fn: $setPercentageVisible(<bVisible,boolean>)
+ Sets whether the current progress value is displayed.
+ See also [classfnc]$isPercentageVisible[/classfnc]()
+ !fn: <boolean> $ispercentageVisible()
+ This property holds whether the current progress value is displayed.
+ See also [classfnc]$setPercentageVisible[/classfnc]()
+*/
+
+KVSO_BEGIN_REGISTERCLASS(KviKvsObject_progressbar,"progressbar","widget")
+ KVSO_REGISTER_HANDLER(KviKvsObject_progressbar,"setProgress", functionSetProgress)
+ KVSO_REGISTER_HANDLER(KviKvsObject_progressbar,"setTotalSteps", functionSetTotalSteps)
+ KVSO_REGISTER_HANDLER(KviKvsObject_progressbar,"reset", functionReset)
+ KVSO_REGISTER_HANDLER(KviKvsObject_progressbar,"setCenterIndicator", functionSetCenterIndicator)
+ KVSO_REGISTER_HANDLER(KviKvsObject_progressbar,"setPercentageVisible", functionSetPercentageVisible)
+ KVSO_REGISTER_HANDLER(KviKvsObject_progressbar,"isCenterIndicator", functionCenterIndicator)
+ KVSO_REGISTER_HANDLER(KviKvsObject_progressbar,"isPercentageVisible", functionPercentageVisible)
+KVSO_END_REGISTERCLASS(KviKvsObject_progressbar)
+
+KVSO_BEGIN_CONSTRUCTOR(KviKvsObject_progressbar,KviKvsObject_widget)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_progressbar)
+
+
+KVSO_BEGIN_DESTRUCTOR(KviKvsObject_progressbar)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_progressbar)
+
+bool KviKvsObject_progressbar::init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams)
+{
+ #ifdef COMPILE_USE_QT4
+ Q3ProgressBar *pbar=new Q3ProgressBar(parentScriptWidget());
+ pbar->setObjectName(name());
+ setObject(pbar,true);
+ #else
+ setObject(new QProgressBar(parentScriptWidget(), name()), true);
+ #endif
+return true;
+}
+
+bool KviKvsObject_progressbar::functionSetProgress(KviKvsObjectFunctionCall *c)
+{
+ kvs_uint_t iProgress;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("step_value",KVS_PT_UNSIGNEDINTEGER,0,iProgress)
+ KVSO_PARAMETERS_END(c)
+ if (widget()) ((KVI_PROGRESS_BAR *)widget())->setProgress(iProgress);
+ return true;
+}
+bool KviKvsObject_progressbar::functionSetTotalSteps(KviKvsObjectFunctionCall *c)
+{
+ kvs_uint_t iSteps;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("total_steps",KVS_PT_UNSIGNEDINTEGER,0,iSteps)
+ KVSO_PARAMETERS_END(c)
+ if (widget()) ((KVI_PROGRESS_BAR *)widget())->setTotalSteps(iSteps);
+ return true;
+}
+
+bool KviKvsObject_progressbar::functionReset(KviKvsObjectFunctionCall *c)
+{
+ if (widget()) ((KVI_PROGRESS_BAR *)widget())->reset();
+ return true;
+}
+
+bool KviKvsObject_progressbar::functionSetCenterIndicator(KviKvsObjectFunctionCall *c)
+{
+ bool bFlag;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bEnabled",KVS_PT_BOOL,0,bFlag)
+ KVSO_PARAMETERS_END(c)
+ if(widget()) ((KVI_PROGRESS_BAR *)widget())->setCenterIndicator(bFlag);
+ return true;
+}
+bool KviKvsObject_progressbar::functionCenterIndicator(KviKvsObjectFunctionCall *c)
+{
+ if (widget()) c->returnValue()->setBoolean(((KVI_PROGRESS_BAR *)widget())->centerIndicator());
+ return true;
+}
+
+bool KviKvsObject_progressbar::functionSetPercentageVisible(KviKvsObjectFunctionCall *c)
+{
+ bool bEnabled;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bEnabled",KVS_PT_BOOL,0,bEnabled)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ ((KVI_PROGRESS_BAR *)widget())->setPercentageVisible(bEnabled);
+ return true;
+}
+bool KviKvsObject_progressbar::functionPercentageVisible(KviKvsObjectFunctionCall *c)
+{
+ if (widget()) c->returnValue()->setBoolean(((KVI_PROGRESS_BAR *)widget())->percentageVisible());
+ return true;
+}
diff --git a/src/modules/objects/class_progressbar.h b/src/modules/objects/class_progressbar.h
new file mode 100644
index 00000000..44c4eac8
--- /dev/null
+++ b/src/modules/objects/class_progressbar.h
@@ -0,0 +1,51 @@
+#ifndef _CLASS_PROGRESSBAR_H_
+
+#define _CLASS_PROGRESSBAR_H_
+//
+// File : class_progressbar.h
+// Creation date : Fri Jan 28 14:21:48 CEST 2005
+// by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+//#include <qprogressbar.h>
+#include "class_widget.h"
+#include "object_macros.h"
+
+class KviKvsObject_progressbar : public KviKvsObject_widget
+{
+public:
+ KVSO_DECLARE_OBJECT(KviKvsObject_progressbar)
+public:
+ QWidget * widget() { return (QWidget *)object(); };
+protected:
+ virtual bool init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams);
+
+ bool functionSetProgress(KviKvsObjectFunctionCall *c);
+ bool functionSetTotalSteps(KviKvsObjectFunctionCall *c);
+ bool functionReset(KviKvsObjectFunctionCall *c);
+ bool functionSetPercentageVisible(KviKvsObjectFunctionCall *c);
+ bool functionSetCenterIndicator(KviKvsObjectFunctionCall *c);
+ bool functionCenterIndicator(KviKvsObjectFunctionCall *c);
+ bool functionPercentageVisible(KviKvsObjectFunctionCall *c);
+};
+
+
+#endif //!_CLASS_PROGRESSBAR_H_
+
diff --git a/src/modules/objects/class_radiobutton.cpp b/src/modules/objects/class_radiobutton.cpp
new file mode 100644
index 00000000..08211e12
--- /dev/null
+++ b/src/modules/objects/class_radiobutton.cpp
@@ -0,0 +1,138 @@
+//
+// File : class_radiobutton.cpp
+// Creation date : Thu Feb 08 14:21:48 CEST 2005
+// by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+#include "class_radiobutton.h"
+#include "kvi_error.h"
+#include "kvi_debug.h"
+
+#include "kvi_locale.h"
+#include "kvi_iconmanager.h"
+
+/*
+ @doc: radiobutton
+ @keyterms:
+ radiobutton widget class
+ @title:
+ radiobutton class
+ @type:
+ class
+ @short:
+ A radiobutton class
+ @inherits:
+ [class]widget[/class]
+ @description:
+ The RadioButton widget provides a radio button with a text or pixmap label.
+ @functions:
+ !fn: $settext(<text:string>)
+ Sets the text that will appear in the radiobutton.
+ !fn: <boolean> $isChecked()
+ Returns 1 (TRUE) if the radio button is checked; otherwise returns 0 (FALSE).
+ !fn: $setChecked(<bChecked:boolean>)
+ Sets whether the radio button is checked to check.
+ !fn: $setPixmap(<image_id>)
+ Sets the pixmap shown on the radiobutton..See the [doc:image_id]image identifier[/doc] documentation for the explaination
+ of the <image_id> parameter.
+ !fn: <bool>$toggleEvent()
+ Called by KVIrc when the radibutton state is toggled.
+ The default implementation emits the toggled(<bool>) signal.
+ !sg: $toggled()
+ This signal is emitted by the default implementation of [classfnc]$toggleEvent[/classfnc]().[br]
+
+
+*/
+
+
+KVSO_BEGIN_REGISTERCLASS(KviKvsObject_radiobutton,"radiobutton","widget")
+
+ KVSO_REGISTER_HANDLER(KviKvsObject_radiobutton,"setText", functionSetText)
+ KVSO_REGISTER_HANDLER(KviKvsObject_radiobutton,"setChecked", functionSetChecked)
+ KVSO_REGISTER_HANDLER(KviKvsObject_radiobutton,"isChecked", functionIsChecked)
+ KVSO_REGISTER_HANDLER(KviKvsObject_radiobutton,"setImage", functionSetImage)
+ KVSO_REGISTER_HANDLER(KviKvsObject_radiobutton,"toggleEvent",function_toggleEvent)
+
+KVSO_END_REGISTERCLASS(KviKvsObject_radiobutton)
+
+KVSO_BEGIN_CONSTRUCTOR(KviKvsObject_radiobutton,KviKvsObject_widget)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_radiobutton)
+
+
+KVSO_BEGIN_DESTRUCTOR(KviKvsObject_radiobutton)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_radiobutton)
+
+bool KviKvsObject_radiobutton::init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams)
+{
+ setObject(new QRadioButton(parentScriptWidget(),name()),true);
+ connect(widget(),SIGNAL(toggled(bool)),this,SLOT(toggled(bool)));
+ return true;
+}
+bool KviKvsObject_radiobutton::functionSetText(KviKvsObjectFunctionCall *c)
+{
+ QString szText;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("text",KVS_PT_STRING,0,szText)
+ KVSO_PARAMETERS_END(c)
+ if (widget())
+ ((QRadioButton *)widget())->setText(szText);
+ return true;
+}
+bool KviKvsObject_radiobutton::functionIsChecked(KviKvsObjectFunctionCall *c)
+{
+ if(widget()) c->returnValue()->setBoolean(((QRadioButton *)widget())->isChecked());
+ return true;
+}
+
+bool KviKvsObject_radiobutton::functionSetChecked(KviKvsObjectFunctionCall *c)
+{
+ bool bChecked;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bChecked",KVS_PT_BOOL,0,bChecked)
+ KVSO_PARAMETERS_END(c)
+ if(widget()) ((QRadioButton *)widget())->setChecked(bChecked);
+ return true;
+}
+bool KviKvsObject_radiobutton::functionSetImage(KviKvsObjectFunctionCall *c)
+{
+ QString icon;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("icon_id",KVS_PT_STRING,0,icon)
+ KVSO_PARAMETERS_END(c)
+ if (!widget()) return true;
+ QPixmap * pix = g_pIconManager->getImage(icon);
+ if(pix)widget()->setIcon(*pix);
+ return true;
+}
+bool KviKvsObject_radiobutton::function_toggleEvent(KviKvsObjectFunctionCall *c)
+{
+ emitSignal("toggled",c,c->params());
+ return true;
+}
+
+void KviKvsObject_radiobutton::toggled(bool b)
+{
+ KviKvsVariantList params(new KviKvsVariant(b));
+ callFunction(this,"toggleEvent",&params);
+}
+
+
+#include "m_class_radiobutton.moc"
diff --git a/src/modules/objects/class_radiobutton.h b/src/modules/objects/class_radiobutton.h
new file mode 100644
index 00000000..127af8cd
--- /dev/null
+++ b/src/modules/objects/class_radiobutton.h
@@ -0,0 +1,51 @@
+#ifndef _CLASS_RADIOBUTTON_H_
+#define _CLASS_RADIOBUTTON_H_
+//mdm:
+// File : class_radiobutton.h
+// Creation date :Thu Feb 08 14:21:48 CEST 2005
+// by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+#include <qradiobutton.h>
+#include "class_widget.h"
+
+
+#include "object_macros.h"
+
+class KviKvsObject_radiobutton : public KviKvsObject_widget
+{
+ Q_OBJECT
+public:
+ KVSO_DECLARE_OBJECT(KviKvsObject_radiobutton)
+public:
+ QWidget * widget() { return (QWidget *)object(); };
+protected:
+ virtual bool init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams);
+
+ bool functionSetText(KviKvsObjectFunctionCall *c);
+ bool functionIsChecked(KviKvsObjectFunctionCall *c);
+ bool functionSetChecked(KviKvsObjectFunctionCall *c);
+ bool functionSetImage(KviKvsObjectFunctionCall *c);
+ bool function_toggleEvent(KviKvsObjectFunctionCall *c);
+protected slots:
+ void toggled(bool b);
+
+};
+
+#endif //!_CLASS_RADIOBUTTON_H_
diff --git a/src/modules/objects/class_slider.cpp b/src/modules/objects/class_slider.cpp
new file mode 100644
index 00000000..603e4c9a
--- /dev/null
+++ b/src/modules/objects/class_slider.cpp
@@ -0,0 +1,287 @@
+//mdm :
+// File : class_Slider.cpp
+// Creation date : Mon Gen 27 21:30:48 CEST 2005
+// by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+#include "class_slider.h"
+#include "kvi_error.h"
+
+#include "kvi_debug.h"
+
+#include "kvi_locale.h"
+#include "kvi_iconmanager.h"
+
+
+/*
+@doc: slider
+ @keyterms:
+ slider object class
+ @title:
+ slider class
+ @type:
+ class
+ @short:
+ The slider widget provides a vertical or horizontal slider.
+ @inherits:
+ [class]object[/class]
+ [class]widget[/class]
+ @description:
+ The slider is the classic widget for controlling a bounded value.[br]
+ It lets the user move a slider along a horizontal or vertical groove [br]
+ and translates the slider's position into an integer value within the legal range.[/classfnc]()
+ @functions:
+ !fn: $setOrientation(<orientation:string>)
+ Sets the slider's orientation.[br]
+ Orientation value can be "Horizontal" or "Vertical".
+ !fn: $setTracking(<bTracking:boolean>)
+ Sets whether slider tracking is enabled to enable.[br]
+ Value can be 1 or 0.
+ !fn: $setMaxValue(<value:integer>)
+ Sets maximum value for slider's range.
+ !fn: $setMinValue(<minv_value:integer>)
+ Sets minimum value for slider's range.
+ !fn: $setLineStep(<line_step:integer>)
+ Sets the line step to <line_step>.
+ !fn: $setPageStep(<page_step:integer>)
+ Sets the page step to <page_step>.
+ !fn: $setTickmarks(<tick_marks:string>)
+ Sets the tickmark settings for this slider.[br]
+ Values are:[br]
+ NoMarks - do not draw any tickmarks.[br]
+ Both - draw tickmarks on both sides of the groove.[br]
+ Above - draw tickmarks above the (horizontal) slider[br]
+ Below - draw tickmarks below the (horizontal) slider[br]
+ Left - draw tickmarks to the left of the (vertical) slider[br]
+ Right - draw tickmarks to the right of the (vertical) slider
+ !fn: $setTickInterval(<value>)
+ Sets the interval between tickmarks.
+ !fn: <integer> $value()
+ Returns slider value.
+ !fn: <integer> $minValue()
+ Returns slider minValue.
+ !fn: <integer> $maxValue()
+ Returns slider maxValue.
+ !fn: <integer> $lineStep()
+ Returns slider lineStep value.
+ !fn: <integer>$pageStep()
+ Returns slider pageStep value.
+ !fn: $valueChangedEvent(<new slider value:integer>)
+ This function is called by the framework when the slider value is changed and return the new slider value as its argument.[br]
+ The default implementation emits the [classfnc]$valueChanged[/classfnc]() signal,
+ so it is easy to handle the values from many sliders without reimplementing
+ the [classfnc]$valueChangedEvent[/classfnc]() for every one.[br]
+ Note: If you reimplement this function to catch the slider value, you will have to emit the signal by yourself (if you still need it, obviously).
+ @signals:
+ !sg: $valueChanged()
+ This signal is emitted by the default implementation of [classfnc]valueChangedEvent[/classfnc]().[br]
+ If you reimplement that function you will have to emit the signal manually (if you still need it).
+
+*/
+
+
+
+KVSO_BEGIN_REGISTERCLASS(KviKvsObject_slider,"slider","widget")
+
+
+ KVSO_REGISTER_HANDLER(KviKvsObject_slider,"setTracking", functionsetTracking);
+ KVSO_REGISTER_HANDLER(KviKvsObject_slider,"setValue", functionsetValue);
+ KVSO_REGISTER_HANDLER(KviKvsObject_slider,"setMinValue", functionsetMinValue);
+ KVSO_REGISTER_HANDLER(KviKvsObject_slider,"setMaxValue", functionsetMaxValue);
+ KVSO_REGISTER_HANDLER(KviKvsObject_slider,"setLineStep", functionsetLineStep);
+ KVSO_REGISTER_HANDLER(KviKvsObject_slider,"setPageStep", functionsetPageStep);
+ KVSO_REGISTER_HANDLER(KviKvsObject_slider,"setTickInterval", functionsetTickInterval);
+ KVSO_REGISTER_HANDLER(KviKvsObject_slider,"value",functionvalue);
+ KVSO_REGISTER_HANDLER(KviKvsObject_slider,"minValue", functionminValue);
+ KVSO_REGISTER_HANDLER(KviKvsObject_slider,"maxValue", functionmaxValue);
+ KVSO_REGISTER_HANDLER(KviKvsObject_slider,"lineStep", functionlineStep);
+ KVSO_REGISTER_HANDLER(KviKvsObject_slider,"pageStep", functionpageStep);
+ KVSO_REGISTER_HANDLER(KviKvsObject_slider,"setTickmarks", functionsetTickmarks);
+ KVSO_REGISTER_HANDLER(KviKvsObject_slider,"setOrientation", functionsetOrientation);
+
+
+ KVSO_REGISTER_HANDLER(KviKvsObject_slider,"valueChangedEvent", functionvalueChangedEvent);
+KVSO_END_REGISTERCLASS(KviKvsObject_slider)
+
+KVSO_BEGIN_CONSTRUCTOR(KviKvsObject_slider,KviKvsObject_widget)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_slider)
+
+
+KVSO_BEGIN_DESTRUCTOR(KviKvsObject_slider)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_slider)
+
+bool KviKvsObject_slider::init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams)
+{
+ setObject(new QSlider(parentScriptWidget(), name()), true);
+ connect(widget(),SIGNAL(valueChanged(int)),this,SLOT(valueChanged(int)));
+ return true;
+}
+
+bool KviKvsObject_slider::functionsetTracking(KviKvsObjectFunctionCall *c)
+{
+ bool bEnabled;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bEnabled",KVS_PT_BOOL,0,bEnabled)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ ((QSlider *)widget())->setTracking(bEnabled);
+ return true;
+}
+
+
+bool KviKvsObject_slider::functionsetValue(KviKvsObjectFunctionCall *c)
+{
+ kvs_int_t iValue;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("value",KVS_PT_INT,0,iValue)
+ KVSO_PARAMETERS_END(c)
+ if (widget()) ((QSlider *)widget())->setValue(iValue);
+ return true;
+}
+bool KviKvsObject_slider::functionsetMinValue(KviKvsObjectFunctionCall *c)
+{
+ kvs_int_t iMinvalue;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("minimum_value",KVS_PT_INT,0,iMinvalue)
+ KVSO_PARAMETERS_END(c)
+ if (widget()) ((QSlider *)widget())->setMinValue(iMinvalue);
+ return true;
+}
+bool KviKvsObject_slider::functionsetMaxValue(KviKvsObjectFunctionCall *c)
+{
+ kvs_int_t iMaxvalue;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("max_value",KVS_PT_INT,0,iMaxvalue)
+ KVSO_PARAMETERS_END(c)
+ if (widget()) ((QSlider *)widget())->setMaxValue(iMaxvalue);
+ return true;
+}
+
+bool KviKvsObject_slider::functionsetLineStep(KviKvsObjectFunctionCall *c)
+{
+ kvs_int_t iLinestep;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("line_step",KVS_PT_INT,0,iLinestep)
+ KVSO_PARAMETERS_END(c)
+ if (widget()) ((QSlider *)widget())->setLineStep(iLinestep);
+ return true;
+}
+bool KviKvsObject_slider::functionsetPageStep(KviKvsObjectFunctionCall *c)
+{
+ kvs_int_t iPagestep;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("page_step",KVS_PT_INT,0,iPagestep)
+ KVSO_PARAMETERS_END(c)
+ if (widget()) ((QSlider *)widget())->setPageStep(iPagestep);
+ return true;
+}
+
+bool KviKvsObject_slider::functionsetTickInterval(KviKvsObjectFunctionCall *c)
+{
+ kvs_int_t iInterval;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("tick_interval",KVS_PT_INT,0,iInterval)
+ KVSO_PARAMETERS_END(c)
+ if (widget()) ((QSlider *)widget())->setTickInterval(iInterval);
+ return true;
+}
+
+bool KviKvsObject_slider::functionvalue(KviKvsObjectFunctionCall *c)
+{
+ if (widget()) c->returnValue()->setInteger(((QSlider *)widget())->value());
+ return true;
+}
+
+bool KviKvsObject_slider::functionminValue(KviKvsObjectFunctionCall *c)
+{
+ if (widget()) c->returnValue()->setInteger(((QSlider *)widget())->minValue());
+ return true;
+}
+bool KviKvsObject_slider::functionmaxValue(KviKvsObjectFunctionCall *c)
+{
+ if (widget()) c->returnValue()->setInteger(((QSlider *)widget())->maxValue());
+ return true;
+}
+bool KviKvsObject_slider::functionlineStep(KviKvsObjectFunctionCall *c)
+{
+ if (widget()) c->returnValue()->setInteger(((QSlider *)widget())->lineStep());
+ return true;
+}
+
+bool KviKvsObject_slider::functionpageStep(KviKvsObjectFunctionCall *c)
+{
+ if (widget()) c->returnValue()->setInteger(((QSlider *)widget())->pageStep());
+ return true;
+}
+
+
+bool KviKvsObject_slider::functionsetTickmarks(KviKvsObjectFunctionCall *c)
+{
+
+ QString szTick;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("tick_marks",KVS_PT_STRING,0,szTick)
+ KVSO_PARAMETERS_END(c)
+ if(!widget())return true;
+ if(KviQString::equalCI(szTick,"NoMarks"))
+ ((QSlider *)widget())->setTickmarks(QSlider::NoMarks);
+ else if(KviQString::equalCI(szTick,"Both"))
+ ((QSlider *)widget())->setTickmarks(QSlider::Both);
+ else if(KviQString::equalCI(szTick,"Above"))
+ ((QSlider *)widget())->setTickmarks(QSlider::Above);
+ else if(KviQString::equalCI(szTick,"Below"))
+ ((QSlider *)widget())->setTickmarks(QSlider::Below);
+ else if(KviQString::equalCI(szTick,"Left"))
+ ((QSlider *)widget())->setTickmarks(QSlider::Left);
+ else if(KviQString::equalCI(szTick,"Right"))
+ ((QSlider *)widget())->setTickmarks(QSlider::Right);
+ else c->warning( __tr2qs("Unknown tickmark '%Q'"),&szTick);
+ return true;
+}
+bool KviKvsObject_slider::functionsetOrientation(KviKvsObjectFunctionCall *c)
+{
+
+ QString szOrientation;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("orientation",KVS_PT_STRING,0,szOrientation)
+ KVSO_PARAMETERS_END(c)
+ if(!widget())return true;
+ if(KviQString::equalCI(szOrientation,"Horizontal"))
+ ((QSlider *)widget())->setOrientation(Qt::Horizontal);
+ else if(KviQString::equalCI(szOrientation,"Vertical"))
+ ((QSlider *)widget())->setOrientation(Qt::Vertical);
+ else c->warning( __tr2qs("Unknown orientation '%Q'"),&szOrientation);
+ return true;
+}
+bool KviKvsObject_slider::functionvalueChangedEvent(KviKvsObjectFunctionCall *c)
+{
+ emitSignal("valueChanged",c,c->params());
+ return true;
+}
+
+void KviKvsObject_slider::valueChanged(int value)
+{
+ KviKvsVariantList params(new KviKvsVariant((kvs_int_t)value));
+ callFunction(this,"valueChangedEvent",&params);
+}
+
+
+#include "m_class_slider.moc"
diff --git a/src/modules/objects/class_slider.h b/src/modules/objects/class_slider.h
new file mode 100644
index 00000000..e2c8c397
--- /dev/null
+++ b/src/modules/objects/class_slider.h
@@ -0,0 +1,64 @@
+#ifndef _CLASS_SLIDER_H_
+#define _CLASS_SLIDER_H_
+//mdm:
+// File : class_Slider.h
+// Creation date : Mon Gen 27 14:30:48 CEST 2005
+// by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+#include <qslider.h>
+#include "class_widget.h"
+
+
+#include "object_macros.h"
+
+class KviKvsObject_slider : public KviKvsObject_widget
+{
+ Q_OBJECT
+public:
+ KVSO_DECLARE_OBJECT(KviKvsObject_slider)
+public:
+ QWidget * widget() { return (QWidget *)object(); };
+protected:
+ virtual bool init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams);
+
+ bool functionsetTracking(KviKvsObjectFunctionCall *c);
+ bool functionsetValue(KviKvsObjectFunctionCall *c);
+ bool functionsetMinValue(KviKvsObjectFunctionCall *c);
+ bool functionsetMaxValue(KviKvsObjectFunctionCall *c);
+ bool functionsetLineStep(KviKvsObjectFunctionCall *c);
+ bool functionsetPageStep(KviKvsObjectFunctionCall *c);
+ bool functionsetTickInterval(KviKvsObjectFunctionCall *c);
+ bool functionvalue(KviKvsObjectFunctionCall *c);
+ bool functionminValue(KviKvsObjectFunctionCall *c);
+ bool functionmaxValue(KviKvsObjectFunctionCall *c);
+ bool functionlineStep(KviKvsObjectFunctionCall *c);
+ bool functionpageStep(KviKvsObjectFunctionCall *c);
+ bool functionsetTickmarks(KviKvsObjectFunctionCall *c);
+ bool functionsetOrientation(KviKvsObjectFunctionCall *c);
+ bool functionvalueChangedEvent(KviKvsObjectFunctionCall *c);
+
+protected slots:
+ void valueChanged(int);
+};
+
+
+
+#endif // !_CLASS_SLIDER_H_
+
diff --git a/src/modules/objects/class_socket.cpp b/src/modules/objects/class_socket.cpp
new file mode 100644
index 00000000..f0afe3a5
--- /dev/null
+++ b/src/modules/objects/class_socket.cpp
@@ -0,0 +1,1331 @@
+//
+// File : class_socket.cpp
+// Creation date : Sun Nov 11 03:13:45 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+
+#define _KVI_DEBUG_CHECK_RANGE_
+#include "kvi_debug.h"
+
+
+#include "kvi_locale.h"
+#include "kvi_error.h"
+#include "kvi_netutils.h"
+#include "kvi_dns.h"
+#include "kvi_error.h"
+#include "kvi_socket.h"
+#include "kvi_malloc.h"
+#include "kvi_memmove.h"
+#include "kvi_databuffer.h"
+#include "kvi_qcstring.h"
+
+#include "class_socket.h"
+
+//#include <stdlib.h>
+
+#define KVI_IN_BUFFER_ALLOC_CHUNK 4096
+#define KVI_READ_CHUNK 1024
+/*
+static KviScriptObjectClass * g_pSocketClass = 0;
+
+static KviScriptObject * socketClassCreateInstance(KviScriptObjectClass * cls,KviScriptObject *par,const char * nam)
+{
+ return new KviScriptSocketObject(cls,par,nam);
+}
+
+KviScriptSocketObject::KviScriptSocketObject(KviScriptObjectClass * cla,KviScriptObject * par,const char * nam)
+: KviScriptObject(cla,par,nam)
+{
+ m_uConnectionId = 0;
+ m_sock = KVI_INVALID_SOCKET;
+ m_iStatus = KVI_SCRIPT_SOCKET_STATUS_DISCONNECTED;
+ m_uRemotePort = 0;
+ m_uSecondaryPort = 0;
+ m_pSn = 0;
+ m_pDns = 0;
+ m_pDelayTimer = 0;
+ m_uConnectTimeout = 60000;
+ m_pInBuffer = 0;
+ m_uInBufferLen = 0;
+ m_uInDataLen = 0;
+ m_pOutBuffer = new KviDataBuffer();
+ m_pFlushTimer = new QTimer();
+ m_bIpV6 = false;
+ m_uLocalPort = 0;
+ m_secondarySock = KVI_INVALID_SOCKET;
+ connect(m_pFlushTimer,SIGNAL(timeout()),this,SLOT(tryFlush()));
+}
+
+KviScriptSocketObject::~KviScriptSocketObject()
+{
+ delete m_pOutBuffer;
+ delete m_pFlushTimer;
+
+ if(m_pInBuffer)kvi_free(m_pInBuffer);
+ if(m_pDelayTimer)delete m_pDelayTimer;
+ if(m_pDns)delete m_pDns;
+ if(m_pSn)delete m_pSn;
+ if(m_sock != KVI_INVALID_SOCKET)kvi_socket_close(m_sock);
+ if(m_secondarySock != KVI_INVALID_SOCKET)kvi_socket_close(m_secondarySock);
+}
+
+void KviScriptSocketObject::reset()
+{
+ m_uConnectionId++; // this is the only place where this is incremented!
+ if(m_pDelayTimer)
+ {
+ delete m_pDelayTimer;
+ m_pDelayTimer = 0;
+ }
+ if(m_pDns)
+ {
+ delete m_pDns;
+ m_pDns = 0;
+ }
+ if(m_pSn)
+ {
+ delete m_pSn;
+ m_pSn = 0;
+ }
+ if(m_sock != KVI_INVALID_SOCKET)
+ {
+ kvi_socket_close(m_sock);
+ m_sock = KVI_INVALID_SOCKET;
+ }
+ if(m_pInBuffer)
+ {
+ kvi_free(m_pInBuffer);
+ m_pInBuffer = 0;
+ }
+ if(m_secondarySock)
+ {
+ kvi_socket_close(m_secondarySock);
+ m_secondarySock = KVI_INVALID_SOCKET;
+ }
+ m_uSecondaryPort = 0;
+ m_szSecondaryIp.clear();
+ delete m_pOutBuffer;
+ if(m_pFlushTimer->isActive())m_pFlushTimer->stop();
+ m_pOutBuffer = new KviDataBuffer();
+ m_uInBufferLen = 0;
+ m_uInDataLen = 0;
+ m_iStatus = KVI_SCRIPT_SOCKET_STATUS_DISCONNECTED;
+ m_uRemotePort = 0;
+ m_szRemoteIp.clear();
+ m_uLocalPort = 0;
+ m_szLocalIp.clear();
+ m_bIpV6 = false;
+}
+
+/*
+ @doc: socket
+ @keyterms:
+ socket object class
+ @title:
+ socket class
+ @type:
+ class
+ @short:
+ A Ipv4/Ipv6 TCP socket
+ @inherits:
+ [class]object[/class]
+ @description:
+ This class provides a standard TCP/IP socket functionality.[br]
+ It can be used either for connecting to a remote host or to listening for incoming connections.[br]
+ If the KVIrc executable has been compiled with the IPV6 protocol support , this socket also supports it.[br]
+ @functions:
+ !fn: $status()
+ Returns the status of the socket :[br]
+ 4=connected[br]
+ 3=listening[br]
+ 2=connecting[br]
+ 1=in dns call[br]
+ 0=disconnected
+
+ !fn: $connectTimeout()
+ Returns the value of the connect attempt timeout in milliseconds.[br]
+ This is the timeout after that a connection attempt will be considered as failed if the remote
+ host is not responding. You can set it with [classfnc:socket]$setConnectTimeout[/classfnc]().
+
+ !fn: $setConnectTimeout(<timeout>)
+ Sets the connect timeout for this socket. <timeout> must be a positive value in milliseconds.[br]
+ The default timeout is 60000.
+
+ !fn: $connect(<host>,<port>)
+ Attempts a connection to <host> on port <port>.[br]
+ <host> can be a numeric internet address (either Ipv4 or Ipv6 (if supported)) or a hostname.[br]
+ If a hostname is used, a DNS lookup is performed (the socket enters the "dns call" state).[br]
+ This function returns 1 if the connect attempt can be succesfully initiated,
+ 0 otherwise.[br] In fact , this function returns 0 only if the supplied <port> parameter
+ is invalid or the socket is in an incoherent state (already connected or listening):
+ for a newly created socket and with a valid <port> number you can safely ignore
+ the return value.[br]
+ Please note that the connection is asynchronous: when this function returns
+ the socket is NOT connected: it has just initiated the connect attempt
+ and you will be notified of the attempt result by an asynchronous event call:
+ in case of failure , $connectFailedEvent() will be called , in case of
+ succes , $connectEvent() will be called.
+
+ !fn: $listen([<port>[,<interface>[,<force_ipv6>]]])
+ Attempts to listen on the specified <port> and <interface>.[br]
+ If <port> is not passed it is assumed to be 0 , if <interface> is not passed , it is assumed to be
+ "any interface" (INADDR_ANY).[br] Port 0 means that the kernel should choose a "random" port to listen on.[br]
+ If the <interface> is recognized as IPV6 address , and IPV6 is supported , the socket listens
+ in IPV6 mode. If <interface> is an empty string and <force_ipv6> is 1 the socket listens
+ on "any ipv6 interface".[br]
+ This function returns '1' in case of success and '0' in case of failure.[br]
+ On some systems listening in the IPV6 namespace allows to accept also IPV4 connections (this includes
+ linux but not windows afaik).[br]
+ When an incoming connection will arrive , $incomingConnectionEvent() will be called.
+
+ !fn: $accept(<socketId>)
+ This function can be called only from inside $incomingConnectionEvent().[br]
+ <socketId> must be a newly created socket sub-class instance object.[br]
+ The passed object will be set up to handle the incoming connection and this object
+ will remain in listening state (unless you explicitly close it).[br]
+ This function returns '1' in case of success and '0' in case of failure.
+
+ !fn: $connectEvent()
+ This function is called when a connection attempt has been succesfully completed.
+ The socket is actually connected to [classfnc:socket]$remoteIp[/classfnc]() on
+ [classfnc:socket]$remotePort[/classfnc](). You can start
+ writing data and you may expect [classfnc:socket]$dataAvailableEvent[/classfnc]() to be
+ triggered.
+
+ !fn: $incomingConnectionEvent()
+ This function is called when an incoming connection arrives over a socket in listening state.[br]
+ You must call [classfnc:socket]$accept[/classfnc]() passing a newly created socket object
+ to accept and handle the connection.[br] If you don't call [classfnc:socket]$accept[/classfnc]()
+ the incoming connection will be automatically terminated.
+
+ !fn: $connectFailedEvent(<reason>)
+ This function is called when a connection attempt fails for some reason. <reason> contains
+ the error string.[br]
+ This function may be called only between a call to [classfnc:socket]$connect[/classfnc]() and
+ the [classfnc:socket]$connectEvent[/classfnc]().
+
+ !fn: $disconnectEvent([error])
+ This function is called when a connection is terminated either cleanly or because of an error.[br]
+ [error] is an empty string in case of a "clean" termination (connection closed by the remote host)
+ or is a message describing the socket error that caused the connection to be interrupted.
+
+ !fn: $dataAvailableEvent(<data_length>)
+ This function is called when some data is available to be read: the <data_length> parameter specifies
+ the length of the available data in bytes.[br]
+ You can use one of the $read* functions to obtain the data.
+
+ !fn: $read(<length>)
+ Reads at most <length> bytes of data from the socket. If <length> is anything "outside" the
+ available data range (<length> < 0 or <length> > available_data_length), this function
+ returns all the available data.[br]
+ Please note that this function can't deal withi binary data: NULL characters are transformed to
+ ASCII characters 255.
+
+ !fn: $readHex(<length>)
+ Reads at most <length> bytes of data from the socket. If <length> is anything "outside" the
+ available data range (<length> < 0 or <length> > available_data_length), this function
+ returns all the available data.[br]
+ Returns the data encoded as hexadecimal digit string: this function can deal with binary data too.
+
+ !fn: $write(<data>)
+ Writes <data> to the socket.[br]
+ This function can't deal with binary data (you can't send a NULL character)[br]
+ Please note that when this function finishes it does not mean that the data has reached the remote end.[br]
+ Basically it does not even mean that the data has been sent to the remote host.[br]
+ The data is enqueued for sending and will be sent as soon as possible.[br]
+ If you're going to [cmd]delete[/cmd] this object just after the $write call, you should
+ call [classfnc:socket]$close[/classfnc]() just before [cmd]delete[/cmd] to ensure the data delivery.
+
+ !fn: $writeHex(<hex_data>)
+ Writes <data> to the socket.[br]
+ <data> is expected to be a hexadecimal rappresentation of the bytes to be sent (two HEX characters
+ for each byte). This means that the length of <hex_data> string must be a multiple of 2.[br]
+ Returns the length of the actually decoded and sent data in bytes or -1 in case of error (the string
+ was not a valid hexadecimla rappresentation).[br]
+ Please note that when this function finishes it does not mean that the data has reached the remote end.[br]
+ Basically it does not even mean that the data has been sent to the remote host.[br]
+ The data is enqueued for sending and will be sent as soon as possible.[br]
+ If you're going to [cmd]delete[/cmd] this object just after the $writeHex call, you should
+ call [classfnc:socket]$close[/classfnc]() just before [cmd]delete[/cmd] to ensure the data delivery.
+
+ !fn: $close()
+ Resets this socket state: kills any pending or active connection. After a close() call
+ the socket may be used for a new connection.[br]
+ If there is an active connection, there is a last attempt to flush the pending outgoing data.[br]
+ You don't need to call $close() if you [cmd]delete[/cmd] the socket: KVIrc will
+ reset the socket state automatically and free the memory. But if you want to ensure data delivery
+ after a $write call sequece and just before a [cmd]delete[/cmd], $close() is the only chance to do it.
+
+ !fn: $remoteIp()
+ Returns the IP address of the remote end of this socket.[br]
+ The return value is meaningful only if the socket is in connected or connecting state.
+
+ !fn: $setProtocol(<protocol>)
+ Let KVIrc use TCP jr UDP protocol
+
+ !fn: $remotePort()
+ Returns the port of the remote end of this socket.[br]
+ The return value is meaningful only if the socket is in connected or connecting state.
+
+ !fn: $localIp()
+ Returns the IP address of the local end of this socket.[br]
+ The return value is meaningful only if the socket is in connected , listening or connecting state.
+
+ !fn: $localPort()
+ Returns the port of the local end of this socket.[br]
+ The return value is meaningful only if the socket is in connected , listening or connecting state.
+
+@examples:
+ [example]
+ #Server socket: listen 80 port and answer to requests (multi-threaded)[br]
+[br]
+ class (webserver,socket) {[br]
+ constructor () {[br]
+ $$->$listen(80, "127.0.0.1")[br]
+ }[br]
+ incomingConnectionEvent()[br]
+ {[br]
+ %tmp = $new(socket)[br]
+ $$->$accept(%tmp)[br]
+ echo "Webserver incoming Conection from: %tmp->$remoteIp : %tmp->$remotePort"[br]
+ %tmp->$write("HTTP/1.1 200 OK\n\n<html><head></head><body><h1>KVIrc Webserver</h1></body></html>\n")[br]
+ %tmp->$close()[br]
+ delete %tmp[br]
+ }[br]
+ }[br]
+ [br]
+ #finally start webserver[br]
+ %WebS = $new(webserver)[br]
+ [br]
+ [/example]
+ [example]
+ #Client socket - go to google and grab request header[br]
+ class (httprequest,socket) {[br]
+ constructor () [br]
+ {[br]
+ # connect to the server[br]
+ $$->$connect("www.google.de",80)[br]
+ }[br]
+ destructor()[br]
+ {[br]
+ # if the socket is still open close it[br]
+ if($$->$status() == 4) $$->$close()[br]
+ }[br]
+ connectFailedEvent() [br]
+ {[br]
+ # the connection to the server failed[br]
+ echo "Connection failed: "$0[br]
+ delete $$[br]
+ }[br]
+ connectEvent() [br]
+ {[br]
+ # connection is complete[br]
+ # send a request to receive the headers only from http://www.google.de/[br]
+ $$->$write("HEAD / HTTP/1.1\r\nHost: www.google.de\r\nConnction: Close\r\nUser-Agent: KVIrc socket\r\n\r\n");[br]
+ }[br]
+ dataAvailableEvent() [br]
+ {[br]
+ # reading the received data[br]
+ %newdata = $$->$read($0)[br]
+ echo %newdata[br]
+ #close and delete the socket[br]
+ $$->$close()[br]
+ delete $$[br]
+ }[br]
+ disconnectEvent() [br]
+ {[br]
+ # connection has been closed[br]
+ echo "Connection closed"[br]
+ delete $$[br]
+ }[br]
+}[br]
+
+#Creating the socket[br]
+%Temp = $new(httprequest)[br]
+ [/example]
+*/
+
+KVSO_BEGIN_REGISTERCLASS(KviKvsObject_socket,"socket","object")
+
+ KVSO_REGISTER_HANDLER(KviKvsObject_socket,"status",functionStatus)
+ KVSO_REGISTER_HANDLER(KviKvsObject_socket,"remotePort",functionRemotePort)
+ KVSO_REGISTER_HANDLER(KviKvsObject_socket,"remoteIp",functionRemoteIp)
+ KVSO_REGISTER_HANDLER(KviKvsObject_socket,"localIp",functionLocalIp)
+ KVSO_REGISTER_HANDLER(KviKvsObject_socket,"localPort",functionLocalPort)
+ KVSO_REGISTER_HANDLER(KviKvsObject_socket,"connect",functionConnect)
+ KVSO_REGISTER_HANDLER(KviKvsObject_socket,"connectTimeout",functionConnectTimeout)
+ KVSO_REGISTER_HANDLER(KviKvsObject_socket,"setConnectTimeout",functionSetConnectTimeout)
+ KVSO_REGISTER_HANDLER(KviKvsObject_socket,"close",functionClose)
+ KVSO_REGISTER_HANDLER(KviKvsObject_socket,"read",functionRead)
+ KVSO_REGISTER_HANDLER(KviKvsObject_socket,"readHex",functionReadHex)
+ KVSO_REGISTER_HANDLER(KviKvsObject_socket,"write",functionWrite)
+ KVSO_REGISTER_HANDLER(KviKvsObject_socket,"writeHex",functionWriteHex)
+ KVSO_REGISTER_HANDLER(KviKvsObject_socket,"setProtocol",functionSetProtocol)
+ KVSO_REGISTER_HANDLER(KviKvsObject_socket,"listen",functionListen)
+ KVSO_REGISTER_HANDLER(KviKvsObject_socket,"accept",functionAccept)
+
+ KVSO_REGISTER_STANDARD_NOTHINGRETURN_HANDLER(KviKvsObject_socket,"connectEvent")
+ KVSO_REGISTER_STANDARD_NOTHINGRETURN_HANDLER(KviKvsObject_socket,"connectFailedEvent")
+ KVSO_REGISTER_STANDARD_NOTHINGRETURN_HANDLER(KviKvsObject_socket,"disconnectEvent")
+ KVSO_REGISTER_STANDARD_NOTHINGRETURN_HANDLER(KviKvsObject_socket,"dataAvailableEvent")
+ KVSO_REGISTER_STANDARD_NOTHINGRETURN_HANDLER(KviKvsObject_socket,"incomingConnectionEvent")
+
+KVSO_END_REGISTERCLASS(KviKvsObject_socket)
+
+
+KVSO_BEGIN_CONSTRUCTOR(KviKvsObject_socket,KviKvsObject)
+
+
+ m_bUdp = false;
+ m_uConnectionId = 0;
+ m_sock = KVI_INVALID_SOCKET;
+ m_iStatus = KVI_SCRIPT_SOCKET_STATUS_DISCONNECTED;
+ m_uRemotePort = 0;
+ m_uSecondaryPort = 0;
+ m_pSn = 0;
+ m_pDns = 0;
+ m_pDelayTimer = 0;
+ m_uConnectTimeout = 60000;
+ m_pInBuffer = 0;
+ m_uInBufferLen = 0;
+ m_uInDataLen = 0;
+ m_pOutBuffer = new KviDataBuffer();
+ m_pFlushTimer = new QTimer();
+ m_bIpV6 = false;
+ m_uLocalPort = 0;
+ m_secondarySock = KVI_INVALID_SOCKET;
+ connect(m_pFlushTimer,SIGNAL(timeout()),this,SLOT(tryFlush()));
+KVSO_END_CONSTRUCTOR(KviKvsObject_socket)
+
+KVSO_BEGIN_DESTRUCTOR(KviKvsObject_socket)
+ delete m_pOutBuffer;
+ delete m_pFlushTimer;
+
+ if(m_pInBuffer)kvi_free(m_pInBuffer);
+ if(m_pDelayTimer)delete m_pDelayTimer;
+ if(m_pDns)delete m_pDns;
+ if(m_pSn)delete m_pSn;
+ if(m_sock != KVI_INVALID_SOCKET)kvi_socket_close(m_sock);
+ if(m_secondarySock != KVI_INVALID_SOCKET)kvi_socket_close(m_secondarySock);
+KVSO_END_DESTRUCTOR(KviKvsObject_socket)
+//----------------------
+
+
+bool KviKvsObject_socket::functionStatus(KviKvsObjectFunctionCall *c)
+{
+ c->returnValue()->setInteger(m_iStatus);
+ return true;
+}
+
+bool KviKvsObject_socket::functionClose(KviKvsObjectFunctionCall *c)
+{
+ if((m_pOutBuffer->size() != 0) && (m_iStatus == KVI_SCRIPT_SOCKET_STATUS_CONNECTED))
+ tryFlush();
+
+ reset();
+ return true;
+}
+
+bool KviKvsObject_socket::functionConnectTimeout(KviKvsObjectFunctionCall *c)
+{
+ c->returnValue()->setInteger(m_uConnectTimeout);
+ return true;
+}
+
+bool KviKvsObject_socket::functionSetConnectTimeout(KviKvsObjectFunctionCall *c)
+{
+ kvs_uint_t uTimeout;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("time_out",KVS_PT_UNSIGNEDINTEGER,0,uTimeout)
+ KVSO_PARAMETERS_END(c)
+ m_uConnectTimeout = uTimeout;
+ return true;
+}
+
+bool KviKvsObject_socket::functionRemotePort(KviKvsObjectFunctionCall *c)
+{
+ c->returnValue()->setInteger(m_uRemotePort);
+ return true;
+}
+
+bool KviKvsObject_socket::functionRemoteIp(KviKvsObjectFunctionCall *c)
+{
+ c->returnValue()->setString(m_szRemoteIp);
+ return true;
+}
+
+bool KviKvsObject_socket::functionLocalPort(KviKvsObjectFunctionCall *c)
+{
+ c->returnValue()->setInteger(m_uLocalPort);
+ return true;
+}
+
+bool KviKvsObject_socket::functionLocalIp(KviKvsObjectFunctionCall *c)
+{
+ c->returnValue()->setString(m_szLocalIp);
+ return true;
+}
+
+bool KviKvsObject_socket::functionAccept(KviKvsObjectFunctionCall *c)
+{
+ KviKvsObject * pObject;
+ kvs_hobject_t hObject;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("object_socket",KVS_PT_HOBJECT,0,hObject)
+ KVSO_PARAMETERS_END(c)
+
+ pObject = KviKvsKernel::instance()->objectController()->lookupObject(hObject);
+
+ if(!pObject)
+ {
+ c->warning(__tr2qs("No socket object specified"));
+ return true;
+ }
+
+ if(!pObject->inherits("KviKvsObject_socket"))
+ {
+ c->warning(__tr2qs("Invalid socket object specified (it doesn't inherit from socket)"));
+ return true;
+ }
+
+ if(m_secondarySock != KVI_INVALID_SOCKET)
+ {
+ ((KviKvsObject_socket *)pObject)->acceptConnection(m_secondarySock,m_uSecondaryPort,m_szSecondaryIp);
+
+ m_secondarySock = KVI_INVALID_SOCKET;
+ m_uSecondaryPort = 0;
+ m_szSecondaryIp="";
+ } else {
+ c->warning(__tr2qs("There is no connection to accept!"));
+ }
+ return true;
+}
+
+
+bool KviKvsObject_socket::functionSetProtocol(KviKvsObjectFunctionCall *c)
+{
+ QString m_szHex;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("hex_string",KVS_PT_STRING,0,m_szHex)
+ KVSO_PARAMETERS_END(c)
+
+ m_bUdp=KviQString::equalCI(m_szHex,"udp");
+ return false;
+}
+
+bool KviKvsObject_socket::functionWriteHex(KviKvsObjectFunctionCall *c)
+{
+ QString m_szHex;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("hex_string",KVS_PT_STRING,0,m_szHex)
+ KVSO_PARAMETERS_END(c)
+
+ if(m_szHex.length() > 0)
+ {
+ bool bOk;
+ QString szTmp;
+ szTmp=m_szHex.setNum(m_szHex.toInt(&bOk,16),16);
+ if(szTmp.length()>0)
+ {
+ KviQCString szData8 = szTmp.utf8();
+ m_pOutBuffer->append((const unsigned char *)(szData8.data()),szData8.length());
+ delayedFlush(0);
+ c->returnValue()->setInteger(szData8.length());
+ }
+ }
+
+ /*
+ if(pszData)
+ {
+ if(pszData->len() > 0)
+ {
+ char * ptr;
+ len = pszData->hexToBuffer(&ptr);
+ if(len > 0)
+ {
+ m_pOutBuffer->append((const unsigned char *)(ptr),len);
+ delayedFlush(0);
+ KviStr::freeBuffer(ptr);
+ }
+ }
+ }
+ buffer.append(KviStr::Format,"%d",len);
+*/
+ return true;
+}
+
+
+
+
+
+bool KviKvsObject_socket::functionConnect(KviKvsObjectFunctionCall *c)
+{
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("remote_ip",KVS_PT_STRING,0,m_szRemoteIp)
+ KVSO_PARAMETER("remote_port",KVS_PT_UNSIGNEDINTEGER,0,m_uRemotePort)
+ KVSO_PARAMETERS_END(c)
+ debug ("Function connect");
+
+
+ if (m_uRemotePort>65535)
+ {
+ c->warning(__tr2qs("Value %d for port is out of range (values allowed are from 0 to 65535"),m_uRemotePort);
+ return true;
+ }
+ if((m_sock != KVI_INVALID_SOCKET) || (m_iStatus != KVI_SCRIPT_SOCKET_STATUS_DISCONNECTED))
+ {
+ c->warning(__tr2qs("Another connection in progress"));
+ c->returnValue()->setBoolean(true);
+ return true;
+ }
+
+
+#ifdef COMPILE_IPV6_SUPPORT
+ if(kvi_isValidStringIp(m_szRemoteIp) || kvi_isValidStringIp_V6(m_szRemoteIp))
+#else
+ if(kvi_isValidStringIp(m_szRemoteIp))
+#endif
+ {
+ debug ("ok connecting");
+ debug ("connectinhg on ip %s ",m_szRemoteIp.latin1());
+ debug ("non so ip");
+ m_iStatus = KVI_SCRIPT_SOCKET_STATUS_CONNECTING;
+ delayedConnect();
+ } else {
+ debug ("connectinhg on ip %s port %d",m_szRemoteIp.latin1(),m_uRemotePort);
+ m_iStatus = KVI_SCRIPT_SOCKET_STATUS_DNS;
+ delayedLookupRemoteIp();
+ }
+ c->returnValue()->setBoolean(true);
+ return true;
+}
+
+
+
+
+
+
+bool KviKvsObject_socket::functionListen(KviKvsObjectFunctionCall *c)
+{
+ if((m_sock != KVI_INVALID_SOCKET) || (m_iStatus != KVI_SCRIPT_SOCKET_STATUS_DISCONNECTED))
+ {
+ c->warning(__tr2qs("Another connection in progress"));
+ c->returnValue()->setBoolean(false);
+ return true;
+ }
+ kvs_uint_t uLocalPort;
+ QString m_szLocalIp;
+ bool m_bIpV6;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("local_port",KVS_PT_UNSIGNEDINTEGER,0,uLocalPort)
+ KVSO_PARAMETER("local_ip",KVS_PT_STRING,KVS_PF_OPTIONAL,m_szLocalIp)
+ KVSO_PARAMETER("bool_ipV6",KVS_PT_BOOLEAN,KVS_PF_OPTIONAL,m_bIpV6)
+ KVSO_PARAMETERS_END(c)
+ m_uLocalPort=uLocalPort;
+
+#ifndef COMPILE_IPV6_SUPPORT
+ if(m_bIpV6)
+ {
+ c->warning(__tr2qs("No IPV6 support in this executable"));
+ c->returnValue()->setBoolean(false);
+ reset();
+ return true;
+ }
+#endif
+
+ bool bGotIp = false;
+
+ if(!m_szLocalIp.isEmpty())
+ {
+
+ // Check the address type
+ if(kvi_isValidStringIp(m_szLocalIp))bGotIp = true;
+ else {
+#ifdef COMPILE_IPV6_SUPPORT
+ if(kvi_isValidStringIp_V6(m_szLocalIp))
+ {
+ bGotIp = true;
+ m_bIpV6 = true;
+ } else {
+#else
+ c->warning(__tr2qs("Invalid IP address specified ('%Q')"),&m_szLocalIp);
+ c->returnValue()->setBoolean(false);
+ reset();
+ return true;
+#endif
+#ifdef COMPILE_IPV6_SUPPORT
+ }
+#endif
+ }
+ }
+
+
+#ifdef COMPILE_IPV6_SUPPORT
+ m_sock = kvi_socket_create(m_bIpV6 ? KVI_SOCKET_PF_INET6 : KVI_SOCKET_PF_INET,
+ m_bUdp ? KVI_SOCKET_TYPE_DGRAM : KVI_SOCKET_TYPE_STREAM,KVI_SOCKET_PROTO_TCP);
+#else
+ m_sock = kvi_socket_create(KVI_SOCKET_PF_INET,m_bUdp ? KVI_SOCKET_TYPE_DGRAM : KVI_SOCKET_TYPE_STREAM,KVI_SOCKET_PROTO_TCP);
+#endif
+
+ if(m_sock == KVI_INVALID_SOCKET)
+ {
+ c->warning(__tr2qs("Socket creation failed"));
+ c->returnValue()->setBoolean(false);
+ reset();
+ return true;
+ }
+
+ if(!m_szLocalIp.isEmpty())
+ {
+#ifdef COMPILE_IPV6_SUPPORT
+ KviSockaddr sa(m_szLocalIp,m_uLocalPort,m_bIpV6,m_bUdp);
+#else
+ KviSockaddr sa(m_szLocalIp,m_uLocalPort,false,m_bUdp);
+#endif
+ if(!sa.socketAddress())
+ {
+ c->warning(__tr2qs("Invalid socket address"));
+ reset();
+ c->returnValue()->setBoolean(false);
+ return true;
+ }
+
+ if(!kvi_socket_bind(m_sock,sa.socketAddress(),((int)(sa.addressLength()))))
+ {
+ c->warning(__tr2qs("Bind failure"));
+ reset();
+ c->returnValue()->setBoolean(false);
+ return true;
+ }
+ } else {
+#ifdef COMPILE_IPV6_SUPPORT
+ KviSockaddr sa(m_uLocalPort,m_bIpV6,m_bUdp);
+#else
+ KviSockaddr sa(m_uLocalPort,false,m_bUdp);
+#endif
+ if(!sa.socketAddress())
+ {
+ c->warning(__tr2qs("Invalid socket address"));
+ reset();
+ c->returnValue()->setBoolean(false);
+ return true;
+ }
+
+ if(!kvi_socket_bind(m_sock,sa.socketAddress(),((int)(sa.addressLength()))))
+ {
+ c->warning(__tr2qs("Bind failure"));
+ reset();
+ c->returnValue()->setBoolean(false);
+ return true;
+ }
+ }
+
+
+ if(!kvi_socket_listen(m_sock,5))
+ {
+ c->warning(__tr2qs("Listen failure"));
+ reset();
+ c->returnValue()->setBoolean(false);
+ return true;
+ }
+
+
+ // Reread the port in case we're binding to a random one (0)
+
+#ifdef COMPILE_IPV6_SUPPORT
+ KviSockaddr sareal(0,m_bIpV6,m_bUdp);
+#else
+ KviSockaddr sareal(0,false,m_bUdp);
+#endif
+
+ int size = (int)sareal.addressLength();
+
+ if(kvi_socket_getsockname(m_sock,sareal.socketAddress(),&size))
+ {
+ m_uLocalPort = sareal.port();
+ sareal.getStringAddress(m_szLocalIp);
+ }
+
+ // and setup the READ notifier...
+ m_pSn = new QSocketNotifier(m_sock,QSocketNotifier::Read);
+ QObject::connect(m_pSn,SIGNAL(activated(int)),this,SLOT(incomingConnection(int)));
+ m_pSn->setEnabled(true);
+
+ m_iStatus = KVI_SCRIPT_SOCKET_STATUS_LISTENING;
+
+ c->returnValue()->setBoolean(true);
+ return true;
+}
+
+void KviKvsObject_socket::incomingConnection(int)
+{
+#ifdef COMPILE_IPV6_SUPPORT
+ struct sockaddr_in6 hostSockAddr6;
+#endif
+ struct sockaddr_in hostSockAddr;
+
+ int size = sizeof(hostSockAddr);
+ struct sockaddr * addr = (struct sockaddr *)&hostSockAddr;
+
+#ifdef COMPILE_IPV6_SUPPORT
+ if(m_bIpV6)
+ {
+ addr = (struct sockaddr *)&hostSockAddr6;
+ size = sizeof(hostSockAddr6);
+ }
+#endif
+
+ // Incoming connection
+ m_secondarySock = kvi_socket_accept(m_sock,addr,&size);
+ if(m_secondarySock != KVI_INVALID_SOCKET)
+ {
+ // Connected
+#ifdef COMPILE_IPV6_SUPPORT
+ if(m_bIpV6)
+ {
+ m_uSecondaryPort = ntohs(((struct sockaddr_in6 *)addr)->sin6_port);
+ if(!kvi_binaryIpToStringIp_V6(((struct sockaddr_in6 *)addr)->sin6_addr,m_szSecondaryIp))
+ m_szSecondaryIp = __tr("unknown");
+ } else {
+#endif
+ m_uSecondaryPort = ntohs(((struct sockaddr_in *)addr)->sin_port);
+ if(!kvi_binaryIpToStringIp(((struct sockaddr_in *)addr)->sin_addr,m_szSecondaryIp))
+ m_szSecondaryIp = __tr("unknown");
+#ifdef COMPILE_IPV6_SUPPORT
+ }
+#endif
+ KviKvsVariantList *params=0;
+ callFunction(this,"incomingConnectionEvent",params);
+ if(m_secondarySock != KVI_INVALID_SOCKET)
+ {
+ kvi_socket_close(m_secondarySock);
+ m_secondarySock = KVI_INVALID_SOCKET;
+ m_uSecondaryPort = 0;
+ m_szSecondaryIp="";
+ }
+
+ } // else..huh ?... wait for the next notifier call
+}
+
+void KviKvsObject_socket::acceptConnection(kvi_socket_t s,kvi_u32_t uPort,const char * szIp)
+{
+ reset();
+ m_sock = s;
+ m_uRemotePort = uPort;
+ m_szRemoteIp = szIp;
+#ifdef COMPILE_IPV6_SUPPORT
+ KviSockaddr sareal(0,m_bIpV6,m_bUdp);
+#else
+ KviSockaddr sareal(0,false,m_bUdp);
+#endif
+
+ int size = (int)sareal.addressLength();
+
+ if(kvi_socket_getsockname(m_sock,sareal.socketAddress(),&size))
+ {
+ m_uLocalPort = sareal.port();
+ sareal.getStringAddress(m_szLocalIp);
+ }
+
+ m_iStatus = KVI_SCRIPT_SOCKET_STATUS_CONNECTED;
+
+ m_pSn = new QSocketNotifier((int)m_sock,QSocketNotifier::Read);
+ QObject::connect(m_pSn,SIGNAL(activated(int)),this,SLOT(readNotifierFired(int)));
+ m_pSn->setEnabled(true);
+}
+
+void KviKvsObject_socket::delayedConnect()
+{
+ if(m_pDelayTimer)delete m_pDelayTimer;
+ m_pDelayTimer = new QTimer();
+ connect(m_pDelayTimer,SIGNAL(timeout()),this,SLOT(doConnect()));
+ m_pDelayTimer->start(0,true);
+}
+
+void KviKvsObject_socket::doConnect()
+{
+ debug ("doConnect function");
+ if(m_pDelayTimer)delete m_pDelayTimer;
+ m_pDelayTimer = 0;
+
+
+ KviSockaddr sa(m_szRemoteIp,m_uRemotePort,!kvi_isValidStringIp(m_szRemoteIp),m_bUdp);
+
+ if(!sa.socketAddress())
+ {
+ unsigned int uOldConnectionId = m_uConnectionId;
+ QString ipAddressError=__tr2qs("Invalid ip address ");
+
+ ipAddressError.append(m_szRemoteIp);
+
+ KviKvsVariantList params;
+ QString tmp;
+ KviQString::sprintf(tmp,__tr2qs("Invalid ip address (%Q)"),&m_szRemoteIp);
+ params.append(new KviKvsVariant(tmp));
+ callFunction(this,"connectFailedEvent",&params);
+ /* callEventFunction("connectFailedEvent",0,new KviParameterList(
+ new KviStr(KviStr::Format,__tr("Invalid ip address (%s)"),m_szRemoteIp.ptr())));
+ */ if(m_uConnectionId == uOldConnectionId)reset();
+ // else it has already been called!
+ return;
+ }
+debug ("Socket created");
+
+ // create the socket
+#ifdef COMPILE_IPV6_SUPPORT
+ m_bIpV6 = sa.isIpV6();
+ m_sock = kvi_socket_create(sa.isIpV6() ? KVI_SOCKET_PF_INET6 : KVI_SOCKET_PF_INET,m_bUdp ? KVI_SOCKET_TYPE_DGRAM : KVI_SOCKET_TYPE_STREAM,KVI_SOCKET_PROTO_TCP);
+#else
+ m_bIpV6 = false;
+ m_sock = kvi_socket_create(KVI_SOCKET_PF_INET,m_bUdp ? KVI_SOCKET_TYPE_DGRAM : KVI_SOCKET_TYPE_STREAM,KVI_SOCKET_PROTO_TCP);
+#endif
+
+ if(m_sock == KVI_INVALID_SOCKET)
+ {
+ unsigned int uOldConnectionId = m_uConnectionId;
+ callFunction(this,"connectFailedEvent",new KviKvsVariantList(
+ new KviKvsVariant(__tr2qs("Failed to create the socket"))));
+ if(m_uConnectionId == uOldConnectionId)reset();
+ // else it has already been called!
+ return;
+ }
+ debug ("Valid socket");
+
+ if(!kvi_socket_setNonBlocking(m_sock))
+ {
+ unsigned int uOldConnectionId = m_uConnectionId;
+
+ callFunction(this,"connectFailedEvent",new KviKvsVariantList(
+ new KviKvsVariant(__tr2qs("Failed to setup a nonblocking socket"))));
+ if(m_uConnectionId == uOldConnectionId)reset();
+ // else it has already been called!
+ return;
+ }
+
+ if(!kvi_socket_connect(m_sock,sa.socketAddress(),((int)(sa.addressLength()))))
+ {
+ int err = kvi_socket_error();
+ if(!kvi_socket_recoverableConnectError(err))
+ {
+ // Ops...
+ int sockError=err;
+ if(sockError==0)
+ {
+ // Zero error ?...let's look closer
+ int iSize=sizeof(int);
+ if(!kvi_socket_getsockopt(m_sock,SOL_SOCKET,SO_ERROR,
+ (void *)&sockError,&iSize))sockError=0;
+ }
+ unsigned int uOldConnectionId = m_uConnectionId;
+ QString callBackError=__tr2qs("Connect failure: ");
+
+ callBackError.append((KviError::getDescription(KviError::translateSystemError(sockError)).utf8().data()));
+ callFunction(this,"connectFailedEvent",new KviKvsVariantList(
+ new KviKvsVariant(callBackError)));
+
+/* callEventFunction("connectFailedEvent",0,new KviParameterList(
+ new KviStr(KviStr::Format,__tr("Connect failure: %s"),KviError::getDescription(KviError::translateSystemError(sockError)).utf8().data())));
+*/ if(m_uConnectionId == uOldConnectionId)reset();
+ // else it has already been called!
+ return;
+ }
+ }
+ debug ("Socket connected");
+ m_pDelayTimer = new QTimer();
+ connect(m_pDelayTimer,SIGNAL(timeout()),this,SLOT(connectTimeout()));
+ m_pDelayTimer->start(m_uConnectTimeout,true);
+
+ m_pSn = new QSocketNotifier((int)m_sock,QSocketNotifier::Write);
+ QObject::connect(m_pSn,SIGNAL(activated(int)),this,SLOT(writeNotifierFired(int)));
+ m_pSn->setEnabled(true);
+}
+
+void KviKvsObject_socket::connectTimeout()
+{
+ unsigned int uOldConnectionId = m_uConnectionId;
+
+ callFunction(this,"connectFailedEvent",new KviKvsVariantList(
+ new KviKvsVariant(__tr2qs("Connect attempt timed out"))));
+ if(m_uConnectionId == uOldConnectionId)reset();
+ // else it has already been called!
+}
+
+void KviKvsObject_socket::delayedLookupRemoteIp()
+{
+ if(m_pDelayTimer)delete m_pDelayTimer;
+ m_pDelayTimer = new QTimer();
+ connect(m_pDelayTimer,SIGNAL(timeout()),this,SLOT(lookupRemoteIp()));
+ m_pDelayTimer->start(0,true);
+}
+
+void KviKvsObject_socket::lookupRemoteIp()
+{
+ debug ("Resolve dns");
+ if(m_pDelayTimer)delete m_pDelayTimer;
+ m_pDelayTimer = 0;
+ if(m_pDns)delete m_pDns;
+ m_pDns = new KviDns();
+ connect(m_pDns,SIGNAL(lookupDone(KviDns *)),this,SLOT(lookupDone(KviDns *)));
+ if(!m_pDns->lookup(m_szRemoteIp,KviDns::Any))
+ {
+ unsigned int uOldConnectionId = m_uConnectionId;
+
+ callFunction(this,"connectFailedEvent",new KviKvsVariantList(
+ new KviKvsVariant(__tr2qs("Can't start the DNS thread"))));
+ if(m_uConnectionId == uOldConnectionId)reset();
+ // else it has already been called!
+ }
+}
+
+void KviKvsObject_socket::lookupDone(KviDns *pDns)
+{
+
+ if(pDns->state() != KviDns::Success)
+ {
+ unsigned int uOldConnectionId = m_uConnectionId;
+
+ callFunction(this,"connectFailedEvent",new KviKvsVariantList(
+ new KviKvsVariant(KviError::getDescription(pDns->error()))));
+
+ if(m_uConnectionId == uOldConnectionId)reset();
+ // else it has already been called!
+ return;
+ }
+ m_szRemoteIp = pDns->firstIpAddress();
+ debug ("Dns resolved in %s",m_szRemoteIp.latin1());
+
+ delete m_pDns;
+ m_pDns = 0;
+ doConnect();
+}
+
+void KviKvsObject_socket::writeNotifierFired(int)
+{
+ debug ("Here in the writeNotifierFired");
+ if(m_pSn)
+ {
+ delete m_pSn;
+ m_pSn = 0;
+ }
+ if(m_pDelayTimer)
+ {
+ delete m_pDelayTimer;
+ m_pDelayTimer = 0;
+ }
+
+ // Check for errors...
+ int sockError;
+ int iSize=sizeof(int);
+ if(!kvi_socket_getsockopt(m_sock,SOL_SOCKET,SO_ERROR,(void *)&sockError,&iSize))sockError = -1;
+ //sockError = 0;
+ if(sockError != 0)
+ {
+ //debug("Failed here %d",sockError);
+ //failed
+ if(sockError > 0)sockError = KviError::translateSystemError(sockError);
+ else sockError = KviError_unknownError; //Error 0 ?
+ unsigned int uOldConnectionId = m_uConnectionId;
+ callFunction(this,"connectFailedEvent",new KviKvsVariantList(
+ new KviKvsVariant(KviError::getDescription(sockError))));
+ if(m_uConnectionId == uOldConnectionId)reset();
+ // else it has already been called!
+ } else {
+ // Succesfully connected
+ // create the correct read notifier now...
+ m_pSn = new QSocketNotifier((int)m_sock,QSocketNotifier::Read);
+ QObject::connect(m_pSn,SIGNAL(activated(int)),this,SLOT(readNotifierFired(int)));
+ m_pSn->setEnabled(true);
+
+#ifdef COMPILE_IPV6_SUPPORT
+ KviSockaddr sareal(0,m_bIpV6,m_bUdp);
+#else
+ KviSockaddr sareal(0,false,m_bUdp);
+#endif
+ int size = (int)sareal.addressLength();
+ if(kvi_socket_getsockname(m_sock,sareal.socketAddress(),&size))
+ {
+ m_uLocalPort = sareal.port();
+ sareal.getStringAddress(m_szLocalIp);
+ }
+ unsigned int uOldConnectionId = m_uConnectionId;
+ KviKvsVariantList *params=0;
+ callFunction(this,"connectEvent",params);
+ if(m_uConnectionId == uOldConnectionId)
+ m_iStatus = KVI_SCRIPT_SOCKET_STATUS_CONNECTED;
+ // else the connection has been already changed!
+ }
+}
+
+void KviKvsObject_socket::readNotifierFired(int)
+{
+ debug ("here in the readNotifierFired");
+ //read data
+ if((m_uInBufferLen - m_uInDataLen) < KVI_READ_CHUNK)
+ {
+ m_uInBufferLen += KVI_IN_BUFFER_ALLOC_CHUNK;
+ m_pInBuffer = (char *)kvi_realloc(m_pInBuffer,m_uInBufferLen);
+ }
+
+ int readLength = kvi_socket_recv(m_sock,m_pInBuffer + m_uInDataLen,KVI_READ_CHUNK);
+
+ if(readLength <= 0)
+ {
+ if(readLength==0)
+ {
+ unsigned int uOldConnectionId = m_uConnectionId;
+ KviKvsVariantList *params=0;
+ callFunction(this,"disconnectEvent",params);
+ if(m_uConnectionId == uOldConnectionId)reset();
+ // else it has already been called!
+ return;
+ } else {
+ //check for transmission errors
+ int err = kvi_socket_error();
+#ifdef COMPILE_ON_WINDOWS
+ if((err != EAGAIN) && (err != EINTR) && (err != WSAEWOULDBLOCK))
+#else
+ if((err != EAGAIN) && (err != EINTR))
+#endif
+ {
+ unsigned int uOldConnectionId = m_uConnectionId;
+ if(err > 0)
+
+ {
+ // QString error=KviError::translateSystemError(err);
+ callFunction(this,"disconnectEvent",new KviKvsVariantList(
+ new KviKvsVariant((kvs_int_t)KviError::translateSystemError(err))));
+ } else {
+ callFunction(this,"disconnectEvent",new KviKvsVariantList(
+ new KviKvsVariant(KviError::getDescription(KviError_remoteEndClosedConnection))));
+
+ }
+ if(m_uConnectionId == uOldConnectionId)reset();
+ // else it has already been called!
+ return;
+ } //else transient error...wait again...
+ }
+ return; // can do nothing
+ }
+ // readLength > 0
+ m_uInDataLen += readLength;
+
+ //KviStr * s = new KviStr();
+ QString s;
+ s.setNum(m_uInDataLen);
+
+
+ unsigned int uOldConnectionId = m_uConnectionId;
+ callFunction(this,"dataAvailableEvent",new KviKvsVariantList(new KviKvsVariant(s)));
+ if(m_uConnectionId == uOldConnectionId)
+ {
+ if(m_uInDataLen > (4096 * 1024)) // too much data in buffer (not reading)
+ {
+ callFunction(this,"disconnectEvent",new KviKvsVariantList(
+ new KviKvsVariant(__tr2qs("Too much unprocessed incoming data (you've left this socket unmanaged ?)"))));
+ reset();
+ }
+ }
+}
+
+void KviKvsObject_socket::eatInData(unsigned int uLen)
+{
+ if(uLen > m_uInDataLen)uLen = m_uInDataLen;
+
+ m_uInDataLen -= uLen;
+
+ if(m_uInDataLen > 0)
+ {
+ kvi_memmove(m_pInBuffer,m_pInBuffer + uLen,m_uInDataLen);
+ }
+
+ unsigned int uSpace = m_uInBufferLen - m_uInDataLen;
+
+ if(uSpace > KVI_IN_BUFFER_ALLOC_CHUNK)
+ {
+ m_uInBufferLen -= KVI_IN_BUFFER_ALLOC_CHUNK;
+ m_pInBuffer = (char *)kvi_realloc(m_pInBuffer,m_uInBufferLen);
+ }
+}
+
+void KviKvsObject_socket::delayedFlush(unsigned int uTimeout)
+{
+ if(m_pFlushTimer->isActive())m_pFlushTimer->stop();
+ m_pFlushTimer->start(uTimeout);
+}
+
+void KviKvsObject_socket::tryFlush()
+{
+ if(m_pFlushTimer->isActive())m_pFlushTimer->stop();
+
+ if(m_pOutBuffer->size() == 0)
+ {
+ return;
+ }
+
+ int result = kvi_socket_send(m_sock,m_pOutBuffer->data(),m_pOutBuffer->size());
+
+ if(result >= 0)
+ {
+ if(result == m_pOutBuffer->size())
+ {
+ m_pOutBuffer->clear();
+ } else {
+ if(result > 0)m_pOutBuffer->remove(result);
+ delayedFlush(500);
+ }
+ } else {
+ // Oops...error ?
+ int err = kvi_socket_error();
+#ifdef COMPILE_ON_WINDOWS
+ if((err == EAGAIN) || (err == EINTR) || (err = WSAEWOULDBLOCK))
+#else
+ if((err == EAGAIN)||(err == EINTR))
+#endif
+ {
+ // Transient error...partial send as before...
+ // Async continue...
+ delayedFlush(500);
+ return;
+ } else {
+ // Disconnected... :(
+ unsigned int uOldConnectionId = m_uConnectionId;
+ callFunction(this,"disconnectEvent",0,new KviKvsVariantList(
+ new KviKvsVariant(KviError::getDescription(KviError::translateSystemError(err)))));
+ if(m_uConnectionId == uOldConnectionId)reset();
+ // else it has already been called!
+ return;
+ }
+ }
+}
+void KviKvsObject_socket::reset()
+{
+ m_uConnectionId++; // this is the only place where this is incremented!
+ if(m_pDelayTimer)
+ {
+ delete m_pDelayTimer;
+ m_pDelayTimer = 0;
+ }
+ if(m_pDns)
+ {
+ delete m_pDns;
+ m_pDns = 0;
+ }
+ if(m_pSn)
+ {
+ delete m_pSn;
+ m_pSn = 0;
+ }
+ if(m_sock != KVI_INVALID_SOCKET)
+ {
+ kvi_socket_close(m_sock);
+ m_sock = KVI_INVALID_SOCKET;
+ }
+ if(m_pInBuffer)
+ {
+ kvi_free(m_pInBuffer);
+ m_pInBuffer = 0;
+ }
+ if(m_secondarySock)
+ {
+ kvi_socket_close(m_secondarySock);
+ m_secondarySock = KVI_INVALID_SOCKET;
+ }
+ m_uSecondaryPort = 0;
+ m_szSecondaryIp="";
+ delete m_pOutBuffer;
+ if(m_pFlushTimer->isActive())m_pFlushTimer->stop();
+ m_pOutBuffer = new KviDataBuffer();
+ m_uInBufferLen = 0;
+ m_uInDataLen = 0;
+ m_iStatus = KVI_SCRIPT_SOCKET_STATUS_DISCONNECTED;
+ m_uRemotePort = 0;
+ m_szRemoteIp="";
+ m_uLocalPort = 0;
+ m_szLocalIp="";
+ m_bIpV6 = false;
+}
+unsigned int KviKvsObject_socket::readGetLength(KviKvsObjectFunctionCall *c)
+{
+ kvs_uint_t uLen;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("length",KVS_PT_UNSIGNEDINTEGER,KVS_PF_OPTIONAL,uLen)
+ KVSO_PARAMETERS_END(c)
+ if (uLen>m_uInDataLen || !uLen) return m_uInDataLen;
+ else return uLen;
+ }
+
+bool KviKvsObject_socket::functionRead(KviKvsObjectFunctionCall *c)
+{
+ unsigned int uLen = readGetLength(c);
+
+ if(uLen > 0)
+ {
+ // convert NULLS to char 255
+ for(unsigned int i = 0;i < uLen;i++)
+ {
+ if(!m_pInBuffer[i])m_pInBuffer[i] = (char)(255);
+ }
+ QString tmpBuffer = QString::fromUtf8(m_pInBuffer,uLen);
+ c->returnValue()->setString(tmpBuffer);
+
+ eatInData(uLen);
+ }
+ return true;
+}
+
+bool KviKvsObject_socket::functionReadHex(KviKvsObjectFunctionCall *c)
+{
+ //??? funzioner�
+ unsigned int uLen = readGetLength(c);
+ bool bOk;
+ if(uLen > 0)
+ {
+ QString szTmp;
+ szTmp =m_pInBuffer;
+ szTmp.toInt(&bOk,16);
+ c->returnValue()->setString(szTmp);
+ eatInData(uLen);
+ }
+ return true;
+}
+
+bool KviKvsObject_socket::functionWrite(KviKvsObjectFunctionCall *c)
+{
+ QString szData;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("szData",KVS_PT_STRING,0,szData)
+ KVSO_PARAMETERS_END(c)
+
+KviQCString szData8 = szData.utf8();
+ if(szData8.length() > 0)
+ {
+ m_pOutBuffer->append((const unsigned char*)szData8.data(),szData8.length());
+ delayedFlush(0);
+ }
+ return true;
+}
+
+
+
+//--------------
+
+#include "m_class_socket.moc"
diff --git a/src/modules/objects/class_socket.h b/src/modules/objects/class_socket.h
new file mode 100644
index 00000000..7ed2e421
--- /dev/null
+++ b/src/modules/objects/class_socket.h
@@ -0,0 +1,185 @@
+#ifndef _CLASS_SOCKET_H_
+#define _CLASS_SOCKET_H_
+//
+// File : class_socket.h
+// Creation date : Sun Nov 11 03:13:46 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+#include "kvi_socket.h"
+
+
+
+#include "kvi_pointerlist.h"
+#include <qsocketnotifier.h>
+#include <qtimer.h>
+
+#define KVI_SCRIPT_SOCKET_STATUS_DISCONNECTED 0
+#define KVI_SCRIPT_SOCKET_STATUS_DNS 1
+#define KVI_SCRIPT_SOCKET_STATUS_CONNECTING 2
+#define KVI_SCRIPT_SOCKET_STATUS_LISTENING 3
+#define KVI_SCRIPT_SOCKET_STATUS_CONNECTED 4
+
+class KviDns;
+class KviDataBuffer;
+/*
+class KviScriptSocketObject : public KviScriptObject
+{
+ Q_OBJECT
+public:
+ KviScriptSocketObject(KviScriptObjectClass * cla,KviScriptObject * par,const char * nam);
+ virtual ~KviScriptSocketObject();
+protected:
+ kvi_socket_t m_sock;
+ int m_iStatus;
+ KviStr m_szRemoteIp;
+ unsigned short int m_uRemotePort;
+ KviStr m_szLocalIp;
+ unsigned short int m_uLocalPort;
+ unsigned int m_uConnectTimeout;
+ QSocketNotifier * m_pSn;
+ KviDns * m_pDns;
+ QTimer * m_pDelayTimer;
+ char * m_pInBuffer;
+ unsigned int m_uInBufferLen;
+ unsigned int m_uInDataLen;
+ bool m_bIpV6;
+ unsigned int m_uConnectionId;
+
+ KviDataBuffer * m_pOutBuffer;
+ QTimer * m_pFlushTimer;
+
+ kvi_socket_t m_secondarySock;
+ unsigned short int m_uSecondaryPort;
+ KviStr m_szSecondaryIp;
+protected:
+ bool functionStatus(KviCommand *c,KviParameterList * params,KviStr &buffer);
+ bool functionRemotePort(KviCommand *c,KviParameterList * params,KviStr &buffer);
+ bool functionRemoteIp(KviCommand *c,KviParameterList * params,KviStr &buffer);
+ bool functionLocalPort(KviCommand *c,KviParameterList * params,KviStr &buffer);
+ bool functionLocalIp(KviCommand *c,KviParameterList * params,KviStr &buffer);
+ bool functionConnect(KviCommand *c,KviParameterList * params,KviStr &buffer);
+ bool functionSetConnectTimeout(KviCommand *c,KviParameterList * params,KviStr &buffer);
+ bool functionConnectTimeout(KviCommand *c,KviParameterList * params,KviStr &buffer);
+ bool functionClose(KviCommand *c,KviParameterList * params,KviStr &buffer);
+ bool functionRead(KviCommand *c,KviParameterList * params,KviStr &buffer);
+ bool functionReadHex(KviCommand *c,KviParameterList * params,KviStr &buffer);
+ bool functionWrite(KviCommand *c,KviParameterList * params,KviStr &buffer);
+ bool functionWriteHex(KviCommand *c,KviParameterList * params,KviStr &buffer);
+ bool functionListen(KviCommand *c,KviParameterList * params,KviStr &buffer);
+ bool functionAccept(KviCommand *c,KviParameterList * params,KviStr &buffer);
+
+ void delayedConnect();
+ void delayedLookupRemoteIp();
+ void delayedFlush(unsigned int uTimeout);
+
+ void eatInData(unsigned int uLen);
+ unsigned int readGetLength(KviParameterList * params);
+
+ void acceptConnection(kvi_socket_t s,unsigned short int uPort,const char * szIp);
+
+ void reset();
+protected slots:
+ void doConnect();
+ void lookupRemoteIp();
+ void lookupDone(KviDns * pDns);
+ void connectTimeout();
+ void writeNotifierFired(int);
+ void readNotifierFired(int);
+ void tryFlush();
+ void incomingConnection(int);
+public:
+ static void registerSelf();
+ static void unregisterSelf();
+};
+*/
+//===============================================================
+#include "object_macros.h"
+
+
+class KviKvsObject_socket : public KviKvsObject
+{
+ Q_OBJECT
+public:
+ KVSO_DECLARE_OBJECT(KviKvsObject_socket)
+protected:
+ bool m_bUdp;
+ kvi_socket_t m_sock;
+ int m_iStatus;
+ QString m_szRemoteIp;
+// unsigned short int m_uRemotePort;
+ QString m_szLocalIp;
+ kvi_u32_t m_uLocalPort;
+ unsigned int m_uConnectTimeout;
+ QSocketNotifier * m_pSn;
+ KviDns * m_pDns;
+ QTimer * m_pDelayTimer;
+ char * m_pInBuffer;
+ unsigned int m_uInBufferLen;
+ unsigned int m_uInDataLen;
+ bool m_bIpV6;
+ unsigned int m_uConnectionId;
+ kvs_uint_t m_uRemotePort;
+ KviDataBuffer * m_pOutBuffer;
+ QTimer * m_pFlushTimer;
+
+ kvi_socket_t m_secondarySock;
+ kvi_u32_t m_uSecondaryPort;
+ QString m_szSecondaryIp;
+protected:
+ bool functionStatus(KviKvsObjectFunctionCall *c);
+ bool functionRemotePort(KviKvsObjectFunctionCall *c);
+ bool functionRemoteIp(KviKvsObjectFunctionCall *c);
+ bool functionLocalPort(KviKvsObjectFunctionCall *c);
+ bool functionLocalIp(KviKvsObjectFunctionCall *c);
+ bool functionConnect(KviKvsObjectFunctionCall *c);
+ bool functionSetConnectTimeout(KviKvsObjectFunctionCall *c);
+ bool functionConnectTimeout(KviKvsObjectFunctionCall *c);
+
+ bool functionClose(KviKvsObjectFunctionCall *c);
+ bool functionRead(KviKvsObjectFunctionCall *c);
+ bool functionReadHex(KviKvsObjectFunctionCall *c);
+ bool functionWrite(KviKvsObjectFunctionCall *c);
+ bool functionWriteHex(KviKvsObjectFunctionCall *c);
+
+ bool functionSetProtocol(KviKvsObjectFunctionCall *c);
+
+ bool functionListen(KviKvsObjectFunctionCall *c);
+ bool functionAccept(KviKvsObjectFunctionCall *c);
+
+ void delayedConnect();
+ void delayedLookupRemoteIp();
+ void delayedFlush(unsigned int uTimeout);
+
+ void eatInData(unsigned int uLen);
+ unsigned int readGetLength(KviKvsObjectFunctionCall * params);
+
+ void acceptConnection(kvi_socket_t s,kvi_u32_t uPort,const char * szIp);
+
+ void reset();
+protected slots:
+ void doConnect();
+ void lookupRemoteIp();
+ void lookupDone(KviDns * pDns);
+ void connectTimeout();
+ void writeNotifierFired(int);
+ void readNotifierFired(int);
+ void tryFlush();
+ void incomingConnection(int);
+};
+#endif //_CLASS_SOCKET_H_
diff --git a/src/modules/objects/class_spinbox.cpp b/src/modules/objects/class_spinbox.cpp
new file mode 100644
index 00000000..f87a3a51
--- /dev/null
+++ b/src/modules/objects/class_spinbox.cpp
@@ -0,0 +1,265 @@
+//
+// File : class_progressbar.cpp
+// Creation date : Fri Jan 30 14:21:48 CEST 2005
+// by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include <qspinbox.h>
+#include "class_spinbox.h"
+#include "kvi_error.h"
+#include "kvi_debug.h"
+
+#include "kvi_locale.h"
+#include "kvi_iconmanager.h"
+
+/*
+ @doc: spinbox
+ @keyterms:
+ spinbox object class,
+ @title:
+ spinbox class
+ @type:
+ class
+ @short:
+ Provides a simple spin button.
+ @inherits:
+ [class]object[/class]
+ [class]widget[/class]
+ @description:
+ This widget allows the user to choose a value either by clicking the up/down buttons
+ to increase/decrease the value currently displayed or by typing the value directly into the spin box.
+ @functions:
+ !fn: $setValue(<value:integer>)
+ Sets the value of the spin box.[br]
+ See also [classfnc]$value[/classfnc]()
+ !fn: $setMinValue(<min_value:integer>)
+ Sets the minimum value of the spin box.
+ See also [classfnc]$MinValue[/classfnc]()
+ !fn: $setMaxValue(<max_value:integer>)
+ Sets the maximum value of the spin box.[br]
+ See also [classfnc]$maxValue[/classfnc]()
+ !fn: $setLineStep(<line_step:integer>)
+ Sets the line step: when the user uses the arrows to change the spin box's value the value will be
+ incremented/decremented by the amount of the line step.
+ See also [classfnc]$lineStep[/classfnc]()
+ !fn: $setSpecialValueText(<text:string>)
+ Sets the special-value text.
+ If set, the spin box will display this text instead of a numeric value whenever the current value is equal to [classfnc]$minValue[/classfnc]().
+ See also [classfnc]$setSpecialValueText[/classfnc]()
+ !fn: $setPrefix(<text:string>)
+ This property holds the spin box's prefix.[br]
+ The prefix is prepended to the start of the displayed value.[br]
+ Typical use is to display a unit of measurement or a currency symbol.
+ See also [classfnc]$setSuffix[/classfnc]()
+ !fn: $setSuffix(<text:string>);
+ This property holds the suffix of the spin box.[br]
+ The suffix is appended to the end of the displayed value.[br]
+ See also [classfnc]$setPrefix[/classfnc]()
+ !fn: <integer> $value()
+ Returns the value of the spin box.
+ See also [classfnc]$setValue[/classfnc]()
+ !fn: <integer> $minValue
+ Returns the minimum value of the spin box.
+ See also [classfnc]$setMinValue[/classfnc]()
+ !fn: <integer> $maxValue
+ Returns the maximum value of the spin box.
+ See also [classfnc]$setMaxValue[/classfnc]()
+ !fn: <integer> $lineStep()
+ Return the linestep.
+ !fn: <string> $specialValueText()
+ Returns the special-value text.
+ See also [classfnc]$setSpecialValueText[/classfnc]()
+ !fn: $valueChangedEvent(<new value:integer>)
+ This function is called by the framework when the spinbox value is changed and return the new slider value as its argument.[br]
+ The default implementation emits the [classfnc]$valueChanged[/classfnc]() signal,
+ so it is easy to handle the values from many spinboxes without reimplementing
+ the [classfnc]$valueChangedEvent[/classfnc]() for every one.[br]
+ Note: If you reimplement this function to catch the spinbox value, you will have to emit the signal by yourself (if you still need it, obviously).
+ @signals:
+ !sg: $valueChanged()
+ This signal is emitted by the default implementation of [classfnc]valueChangedEvent[/classfnc]().[br]
+ If you reimplement that function you will have to emit the signal manually (if you still need it).
+*/
+
+
+KVSO_BEGIN_REGISTERCLASS(KviKvsObject_spinbox,"spinbox","widget")
+
+
+
+ KVSO_REGISTER_HANDLER(KviKvsObject_spinbox,"setValue", functionsetValue);
+ KVSO_REGISTER_HANDLER(KviKvsObject_spinbox,"setMinValue", functionsetMinValue);
+ KVSO_REGISTER_HANDLER(KviKvsObject_spinbox,"setMaxValue", functionsetMaxValue);
+ KVSO_REGISTER_HANDLER(KviKvsObject_spinbox,"setLineStep", functionsetLineStep);
+ KVSO_REGISTER_HANDLER(KviKvsObject_spinbox,"setSpecialValueText", functionsetSpecialValueText);
+ KVSO_REGISTER_HANDLER(KviKvsObject_spinbox,"value",functionvalue);
+ KVSO_REGISTER_HANDLER(KviKvsObject_spinbox,"minValue", functionminValue);
+ KVSO_REGISTER_HANDLER(KviKvsObject_spinbox,"maxValue", functionmaxValue);
+ KVSO_REGISTER_HANDLER(KviKvsObject_spinbox,"lineStep", functionlineStep);
+ KVSO_REGISTER_HANDLER(KviKvsObject_spinbox,"specialValueText", functionspecialValueText);
+
+ KVSO_REGISTER_HANDLER(KviKvsObject_spinbox,"setPrefix", functionsetPrefix);
+ KVSO_REGISTER_HANDLER(KviKvsObject_spinbox,"setSuffix", functionsetSuffix);
+
+
+ KVSO_REGISTER_HANDLER(KviKvsObject_spinbox,"valueChangedEvent", functionvalueChangedEvent);
+KVSO_END_REGISTERCLASS(KviKvsObject_spinbox)
+
+KVSO_BEGIN_CONSTRUCTOR(KviKvsObject_spinbox,KviKvsObject_widget)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_spinbox)
+
+
+KVSO_BEGIN_DESTRUCTOR(KviKvsObject_spinbox)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_spinbox)
+
+bool KviKvsObject_spinbox::init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams)
+{
+ setObject(new QSpinBox(parentScriptWidget(), name()), true);
+ connect(widget(),SIGNAL(valueChanged(int)),this,SLOT(valueChanged(int)));
+ return true;
+}
+
+
+
+bool KviKvsObject_spinbox::functionsetValue(KviKvsObjectFunctionCall *c)
+{
+ kvs_int_t iValue;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("value",KVS_PT_INT,0,iValue)
+ KVSO_PARAMETERS_END(c)
+ if (widget()) ((QSpinBox *)widget())->setValue(iValue);
+ return true;
+}
+bool KviKvsObject_spinbox::functionsetMinValue(KviKvsObjectFunctionCall *c)
+{
+ kvs_int_t iMinvalue;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("min_value",KVS_PT_INT,0,iMinvalue)
+ KVSO_PARAMETERS_END(c)
+ if (widget()) ((QSpinBox *)widget())->setMinValue(iMinvalue);
+ return true;
+}
+bool KviKvsObject_spinbox::functionsetMaxValue(KviKvsObjectFunctionCall *c)
+{
+ kvs_int_t iMaxvalue;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("max_value",KVS_PT_INT,0,iMaxvalue)
+ KVSO_PARAMETERS_END(c)
+ if (widget()) ((QSpinBox *)widget())->setMaxValue(iMaxvalue);
+ return true;
+}
+
+bool KviKvsObject_spinbox::functionsetLineStep(KviKvsObjectFunctionCall *c)
+{
+ kvs_int_t iLinestep;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("line_step",KVS_PT_INT,0,iLinestep)
+ KVSO_PARAMETERS_END(c)
+ if (widget()) ((QSpinBox *)widget())->setLineStep(iLinestep);
+ return true;
+}
+
+
+bool KviKvsObject_spinbox::functionvalue(KviKvsObjectFunctionCall *c)
+{
+ if (widget()) c->returnValue()->setInteger(((QSpinBox *)widget())->value());
+ return true;
+}
+
+bool KviKvsObject_spinbox::functionminValue(KviKvsObjectFunctionCall *c)
+{
+ if (widget()) c->returnValue()->setInteger(((QSpinBox *)widget())->minValue());
+ return true;
+}
+bool KviKvsObject_spinbox::functionmaxValue(KviKvsObjectFunctionCall *c)
+{
+ if (widget()) c->returnValue()->setInteger(((QSpinBox *)widget())->maxValue());
+ return true;
+}
+bool KviKvsObject_spinbox::functionlineStep(KviKvsObjectFunctionCall *c)
+{
+ if (widget())
+ {
+ #ifdef COMPILE_USE_QT4
+ c->returnValue()->setInteger(((QSpinBox *)widget())->singleStep());
+ #else
+ c->returnValue()->setInteger(((QSpinBox *)widget())->lineStep());
+ #endif
+ }
+
+ return true;
+}
+
+
+bool KviKvsObject_spinbox::functionspecialValueText(KviKvsObjectFunctionCall *c)
+{
+ if (widget()) c->returnValue()->setString(((QSpinBox *)widget())->specialValueText());
+ return true;
+}
+
+
+bool KviKvsObject_spinbox::functionsetSpecialValueText(KviKvsObjectFunctionCall *c)
+{
+
+ QString szText;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("text",KVS_PT_STRING,0,szText)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ ((QSpinBox *)widget())->setSpecialValueText(szText);
+ return true;
+}
+bool KviKvsObject_spinbox::functionsetPrefix(KviKvsObjectFunctionCall *c)
+{
+
+ QString szPrefix;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("text",KVS_PT_STRING,0,szPrefix)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ ((QSpinBox *)widget())->setPrefix(szPrefix);
+ return true;
+}
+bool KviKvsObject_spinbox::functionsetSuffix(KviKvsObjectFunctionCall *c)
+{
+
+ QString szSuffix;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("text",KVS_PT_STRING,0,szSuffix)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ ((QSpinBox *)widget())->setSuffix(szSuffix);
+ return true;
+}
+
+bool KviKvsObject_spinbox::functionvalueChangedEvent(KviKvsObjectFunctionCall *c)
+{
+ emitSignal("valueChanged",c,c->params());
+ return true;
+}
+
+void KviKvsObject_spinbox::valueChanged(int value)
+{
+ KviKvsVariantList params(new KviKvsVariant((kvs_int_t)value));
+ callFunction(this,"valueChangedEvent",&params);
+}
+
+#include "m_class_spinbox.moc"
diff --git a/src/modules/objects/class_spinbox.h b/src/modules/objects/class_spinbox.h
new file mode 100644
index 00000000..d5a6ee94
--- /dev/null
+++ b/src/modules/objects/class_spinbox.h
@@ -0,0 +1,64 @@
+#ifndef _CLASS_SPINBOX_H_
+#define _CLASS_SPINBOX_H_
+//
+// File : class_progressbar.h
+// Creation date : Fri Jan 30 14:21:48 CEST 2005
+// by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+
+#include <qspinbox.h>
+#include "class_widget.h"
+
+#include "object_macros.h"
+
+class KviKvsObject_spinbox : public KviKvsObject_widget
+{
+ Q_OBJECT
+public:
+ KVSO_DECLARE_OBJECT(KviKvsObject_spinbox)
+public:
+ QWidget * widget() { return (QWidget *)object(); };
+protected:
+ virtual bool init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams);
+
+ bool functionsetTracking(KviKvsObjectFunctionCall *c);
+
+ bool functionsetValue(KviKvsObjectFunctionCall *c);
+ bool functionsetMinValue(KviKvsObjectFunctionCall *c);
+ bool functionsetMaxValue(KviKvsObjectFunctionCall *c);
+ bool functionsetLineStep(KviKvsObjectFunctionCall *c);
+ bool functionsetPrefix(KviKvsObjectFunctionCall *c);
+ bool functionsetSuffix(KviKvsObjectFunctionCall *c);
+ bool functionvalue(KviKvsObjectFunctionCall *c);
+ bool functionminValue(KviKvsObjectFunctionCall *c);
+ bool functionmaxValue(KviKvsObjectFunctionCall *c);
+ bool functionlineStep(KviKvsObjectFunctionCall *c);
+ bool functionsetSpecialValueText(KviKvsObjectFunctionCall *c);
+ bool functionspecialValueText(KviKvsObjectFunctionCall *c);
+
+ bool functionvalueChangedEvent(KviKvsObjectFunctionCall *c);
+
+protected slots:
+ void valueChanged(int);
+};
+
+#endif //!_CLASS_SPINBOX_H_
diff --git a/src/modules/objects/class_tabwidget.cpp b/src/modules/objects/class_tabwidget.cpp
new file mode 100644
index 00000000..c5e97b60
--- /dev/null
+++ b/src/modules/objects/class_tabwidget.cpp
@@ -0,0 +1,541 @@
+//mdm:
+// File : class_tabwidget.cpp
+// Creation date : Fri Feb 11 10:21:48 CEST 2005
+// by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+#include "class_tabwidget.h"
+#include "kvi_error.h"
+#include "kvi_debug.h"
+
+#include "kvi_locale.h"
+#include "kvi_iconmanager.h"
+
+/*
+ @doc: tabwidget
+ @keyterms:
+ tabwidget object class,
+ @title:
+ tabwidget class
+ @type:
+ class
+ @short:
+ Provides a Tab Widget.
+ @inherits:
+ [class]object[/class]
+ [class]widget[/class]
+ @description:
+ The tabwidget class provides a stack of tabbed widgets.[br]
+ Each tab is associated with a different widget (called a `page').[br]
+ Only the current tab's page is shown in the page area; all the others tabs pages are hidden.[br]
+ The user can show a different page by clicking on its tab.[br]
+ @functions:
+ !fn: $addTab(<widget:object>,<text_label:string>,[<icon_id>])
+ Adds another page to the tab view with the text label and optional icon.
+ !fn: $insertTab(<widget:object>,<tex_label:string>,<index:uinteger>)
+ Inserts another tab and page to the tab view with name and label-text specified.[br]
+ If index is not specified, the tab is simply appended.[br]
+ Otherwise the new tab is inserted at the specified position.
+ !fn: $setTabToolTip(<tab_widget:object>,<tooltip:string>)
+ Sets the tab tool tip for the tabwidget to <tooltip>.
+ !fn: $removeTabToolTip(<tab_widget:object>)
+ Removes the tab tool tip for the tab. If the page does not have a tip, nothing happens.
+ !fn: $setTabLabel(<tab_widget>, <label:string>)
+ Sets the tab label for <tab_widget> to label.
+ !fn: $changeTab(<tab_widget:object>,<label:text>,[<icon_id>])
+ Defines a new label, and optional icon, for the tab .
+ !fn: $setCurrentPage(<index:uinteger>)
+ Sets the index position of the current tab page to <index>.
+ !fn: <integer> $currentPageIndex()
+ Returns the current page index.
+ !fn: <string> $label(<index:uinteger>)
+ Retunrs the label to the <index>.
+ !fn: <string> $currentTabLabel()
+ Returns the label of the current tab.
+ !fn: $setMargin(<margin:integer>)
+ Sets the margin in this tab widget to <margin>.
+ !fn: <integer> $margin()
+ Returns the margin in this tab widget.
+ !fn: $removePage(<tab_widget:object>)
+ Remove the page <tab_widget>.
+ !fn: $setTabPosition(<tab_position:string>)
+ Sets TabPosition. Valid parameters are : Top, Bottom.
+ !fn: <integer> $count()
+ This property holds the number of tabs in the tab bar.
+ !fn: $currentChangedEvent()
+ This function is invoched when the current tab was changed.[br]
+ The default implementation emits the [classfnc]$currentChange[/classfnc]() signal.
+ @examples:
+ [example]
+ # First we'll create the main tabwidget.
+ %Tabwidget=$new(tabwidget)
+ %Tabwidget->$setToolTip("Example of TabWidget class")
+ %Tabwidget->$setMargin(30)
+ %Tabwidget->$setTabPosition(Top)
+
+ # Now we'll create the new widgets and put they in to the main tabwidget.
+ %firsttab=$new(widget,%Tabwidget)
+ %secondtab=$new(widget,%Tabwidget)
+
+ # Now we'll create the item to put in to tab's pages.
+ %layoutfirsttab=$new(layout,%firsttab)
+ %labelbt=$new(label,%firsttab)
+ %labelbt->$settext(Botton Tab)
+ %labeltt=$new(label,%firsttab)
+ %labeltt->$settext(Top Tab)
+ %buttontb=$new(button,%firsttab)
+ %buttontb->$settext("To &Botton")
+ %buttontt=$new(button,%firsttab)
+ %buttontt->$settext("To &Top")
+
+ # Now we'll give a layout to all items.
+ # This also allows to use privateimpl without making buttons global variables
+ %layoutfirsttab->$addwidget(%labelbt,0,0)
+ %layoutfirsttab->$addwidget(%labeltt,0,1)
+ %layoutfirsttab->$addwidget(%buttontb,1,0)
+ %layoutfirsttab->$addwidget(%buttontt,1,1)
+
+ # Add the page to the main tab.
+ %Tabwidget->$addTab(%firsttab,Top&Button,33)
+
+ # Implementing the action to do when the user click the buttons.
+ privateimpl(%buttontb,mousepressevent)
+ {
+ %Tabwidget->$setTabPosition(Bottom)
+ }
+ privateimpl(%buttontt,mousepressevent)
+ {
+ %Tabwidget->$setTabPosition(Top)
+ }
+
+ # We do the same work with the second tab's page.
+ %layoutsecondtab=$new(layout,%secondtab)
+ %labelwp=$new(label,%secondtab)
+ %labelwp->$settext("Enjoy the new Class provided by")
+ %layoutsecondtab->$addwidget(%labelwp,0,0)
+ %labelwp->$setalignment("Center")
+ %labelgen=$new(label,%secondtab)
+ %labelgen->$settext(Grifisx \& Noldor)
+ %labelgen->$setalignment("Center")
+ %layoutsecondtab->$addwidget(%labelgen,1,0)
+ %Tabwidget->$addTab(%secondtab,&About,50)
+
+ # Let's show our example.
+ %Tabwidget->$show()
+ [/example]
+ @signals:
+ !sg: $currentChange()
+ This signal is emitted by the default implementation of [classfnc]$currentChangedEvent[/classfnc]().[br]
+ If you reimplement that function you will have to emit the signal manually (if you still need it).[br]
+*/
+
+KVSO_BEGIN_REGISTERCLASS(KviKvsObject_tabwidget,"tabwidget","widget")
+
+ KVSO_REGISTER_HANDLER(KviKvsObject_tabwidget,"addTab", functionaddTab)
+ KVSO_REGISTER_HANDLER(KviKvsObject_tabwidget,"insertTab", functioninsertTab)
+ KVSO_REGISTER_HANDLER(KviKvsObject_tabwidget,"setTabToolTip", functionsetTabToolTip)
+ KVSO_REGISTER_HANDLER(KviKvsObject_tabwidget,"removeTabToolTip", functionremoveTabToolTip)
+ KVSO_REGISTER_HANDLER(KviKvsObject_tabwidget,"setTabLabel", functionsetTabLabel)
+ KVSO_REGISTER_HANDLER(KviKvsObject_tabwidget,"changeTab", functionchangeTab)
+ KVSO_REGISTER_HANDLER(KviKvsObject_tabwidget,"setCurrentPage", functionsetCurrentPage)
+ KVSO_REGISTER_HANDLER(KviKvsObject_tabwidget,"currentPageIndex", functioncurrentPageIndex)
+ KVSO_REGISTER_HANDLER(KviKvsObject_tabwidget,"label", functiontabLabel)
+ KVSO_REGISTER_HANDLER(KviKvsObject_tabwidget,"currentTabLabel", functioncurrentTabLabel)
+
+ KVSO_REGISTER_HANDLER(KviKvsObject_tabwidget,"setMargin", functionsetMargin);
+ KVSO_REGISTER_HANDLER(KviKvsObject_tabwidget,"margin", functionmargin)
+ KVSO_REGISTER_HANDLER(KviKvsObject_tabwidget,"count", functioncount)
+ KVSO_REGISTER_HANDLER(KviKvsObject_tabwidget,"removePage", functionremovePage)
+ KVSO_REGISTER_HANDLER(KviKvsObject_tabwidget,"setTabPosition", functionsetTabPosition)
+
+ // events
+ KVSO_REGISTER_HANDLER(KviKvsObject_tabwidget,"currentChangedEvent", functionCurrentChangedEvent)
+
+
+
+KVSO_END_REGISTERCLASS(KviKvsObject_tabwidget)
+
+KVSO_BEGIN_CONSTRUCTOR(KviKvsObject_tabwidget,KviKvsObject_widget)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_tabwidget)
+
+
+KVSO_BEGIN_DESTRUCTOR(KviKvsObject_tabwidget)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_tabwidget)
+
+bool KviKvsObject_tabwidget::init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams)
+{
+ setObject(new QTabWidget(parentScriptWidget(), name()), true);
+ connect(widget(),SIGNAL(currentChanged(int)),this,SLOT(slotcurrentChanged(int)));
+ return true;
+}
+bool KviKvsObject_tabwidget::functionaddTab(KviKvsObjectFunctionCall *c)
+{
+ KviKvsObject *ob;
+ QString szLabel,szIcon;
+ kvs_hobject_t hObject;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("widget",KVS_PT_HOBJECT,0,hObject)
+ KVSO_PARAMETER("label",KVS_PT_STRING,0,szLabel)
+ KVSO_PARAMETER("icon_id",KVS_PT_STRING,KVS_PF_OPTIONAL,szIcon)
+ KVSO_PARAMETERS_END(c)
+ ob=KviKvsKernel::instance()->objectController()->lookupObject(hObject);
+ if(!widget())return true;
+ if (!ob)
+ {
+ c->warning(__tr2qs("Widget parameter is not an object"));
+ return true;
+ }
+ if (!ob->object())
+ {
+ c->warning(__tr2qs("Widget parameter is not a valid object"));
+ return true;
+ }
+ if(!ob->object()->isWidgetType())
+ {
+ c->warning(__tr2qs("Can't add a non-widget object"));
+ return true;
+ }
+ QPixmap * pix = g_pIconManager->getImage(szIcon);
+
+ if(pix){
+#ifdef COMPILE_USE_QT4
+ ((QTabWidget *)widget())->addTab(((QWidget *)(ob->object())),QIconSet(*pix),szLabel);
+#else
+ ((QTabWidget *)widget())->addTab(((QWidget *)(ob->object())),QIconSet(*pix,QIconSet::Small),szLabel);
+#endif
+ }
+ else((QTabWidget *)widget())->addTab(((QWidget *)(ob->object())),szLabel);
+ return true;
+}
+
+bool KviKvsObject_tabwidget::functioninsertTab(KviKvsObjectFunctionCall *c)
+{
+ KviKvsObject *ob;
+ QString szLabel,szIcon;
+ kvs_uint_t uIndex;
+ kvs_hobject_t hObject;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("tab_widget",KVS_PT_HOBJECT,0,hObject)
+ KVSO_PARAMETER("label",KVS_PT_STRING,0,szLabel)
+ KVSO_PARAMETER("index",KVS_PT_UNSIGNEDINTEGER,0,uIndex)
+ KVSO_PARAMETER("icon_id",KVS_PT_STRING,KVS_PF_OPTIONAL,szIcon)
+ KVSO_PARAMETERS_END(c)
+ ob=KviKvsKernel::instance()->objectController()->lookupObject(hObject);
+ if(!widget())return true;
+ if (!ob)
+ {
+ c->warning(__tr2qs("Widget parameter is not an object"));
+ return true;
+ }
+ if (!ob->object())
+ {
+ c->warning(__tr2qs("Widget parameter is not a valid object"));
+ return true;
+ }
+ if(!ob->object()->isWidgetType())
+ {
+ c->warning(__tr2qs("Can't add a non-widget object"));
+ return true;
+ }
+ QPixmap * pix = g_pIconManager->getImage(szIcon);
+ if(pix){
+ #ifdef COMPILE_USE_QT4
+ ((QTabWidget *)widget())->insertTab( ((QWidget *)(ob->object())),QIconSet(*pix),szLabel,uIndex);
+ #else
+ ((QTabWidget *)widget())->insertTab(((QWidget *)(ob->object())),QIconSet(*pix,QIconSet::Small),szLabel,uIndex);
+ #endif
+ }
+ else ((QTabWidget *)widget())->insertTab(((QWidget *)(ob->object())),szLabel,uIndex);
+ return true;
+}
+
+bool KviKvsObject_tabwidget::functionsetCurrentPage(KviKvsObjectFunctionCall *c)
+{
+ kvs_uint_t uIndex;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("index",KVS_PT_UNSIGNEDINTEGER,0,uIndex)
+ KVSO_PARAMETERS_END(c)
+ if (widget()) ((QTabWidget *)widget())->setCurrentPage(uIndex);
+ return true;
+}
+bool KviKvsObject_tabwidget::functionsetTabToolTip(KviKvsObjectFunctionCall *c)
+{
+ KviKvsObject *ob;
+ QString szTooltip;
+ kvs_hobject_t hObject;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("tab_widget",KVS_PT_HOBJECT,0,hObject)
+ KVSO_PARAMETER("tooltip",KVS_PT_STRING,0,szTooltip)
+ KVSO_PARAMETERS_END(c)
+ ob=KviKvsKernel::instance()->objectController()->lookupObject(hObject);
+ if(!widget())return true;
+ if (!ob)
+ {
+ c->warning(__tr2qs("Widget parameter is not an object"));
+ return true;
+ }
+ if (!ob->object())
+ {
+ c->warning(__tr2qs("Widget parameter is not a valid object"));
+ return true;
+ }
+ if(!ob->object()->isWidgetType())
+ {
+ c->warning(__tr2qs("Not a widget object"));
+ return true;
+ }
+ int ctrl = ((QTabWidget *)widget())->indexOf (((QWidget *)(ob->object())));
+ if (ctrl == -1)
+ {
+ c->warning(__tr2qs("Can't find the tab "));
+ return true;
+ }
+ ((QTabWidget *)widget())->setTabToolTip(((QWidget *)(ob->object())),szTooltip);
+ return true;
+}
+bool KviKvsObject_tabwidget::functionremoveTabToolTip(KviKvsObjectFunctionCall *c)
+{
+ KviKvsObject *ob;
+ kvs_hobject_t hObject;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("tab_widget",KVS_PT_HOBJECT,0,hObject)
+ KVSO_PARAMETERS_END(c)
+ ob=KviKvsKernel::instance()->objectController()->lookupObject(hObject);
+ if (!ob)
+ {
+ c->warning(__tr2qs("Widget parameter is not an object"));
+ return true;
+ }
+ if (!ob->object())
+ {
+ c->warning(__tr2qs("Widget parameter is not a valid object"));
+ return true;
+ }
+ if(!widget()) return true;
+ if(!ob->object()->isWidgetType())
+ {
+ c->warning(__tr2qs("Not a widget object"));
+ return true;
+ }
+ if (((QTabWidget *)widget())->indexOf (((QWidget *)(ob->object()))) == -1)
+ {
+ c->warning(__tr2qs("Can't find the tab "));
+ return true;
+ }
+ ((QTabWidget *)widget())->removeTabToolTip(((QWidget *)(ob->object())));
+ return true;
+}
+
+bool KviKvsObject_tabwidget::functionsetTabLabel(KviKvsObjectFunctionCall *c)
+{
+ KviKvsObject *ob;
+ QString szLabel;
+ kvs_hobject_t hObject;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("tab_widget",KVS_PT_HOBJECT,0, hObject)
+ KVSO_PARAMETER("tooltip",KVS_PT_STRING,0,szLabel)
+ KVSO_PARAMETERS_END(c)
+ ob=KviKvsKernel::instance()->objectController()->lookupObject(hObject);
+ if (!ob)
+ {
+ c->warning(__tr2qs("Widget parameter is not an object"));
+ return true;
+ }
+ if (!ob->object())
+ {
+ c->warning(__tr2qs("Widget parameter is not a valid object"));
+ return true;
+ }
+ if(!widget())return true;
+ if(!ob->object()->isWidgetType())
+ {
+ c->warning(__tr2qs("Not a widget object"));
+ return true;
+ }
+ int ctrl = ((QTabWidget *)widget())->indexOf (((QWidget *)(ob->object())));
+ if (ctrl == -1)
+ {
+ c->warning(__tr2qs("Can't find the tab "));
+ return true;
+ }
+ ((QTabWidget *)widget())->setTabLabel(((QWidget *)(ob->object())),szLabel);
+ return true;
+}
+bool KviKvsObject_tabwidget::functioncurrentPageIndex(KviKvsObjectFunctionCall *c)
+{
+ int index=((QTabWidget *)widget())->currentPageIndex();
+ if (widget()) c->returnValue()->setInteger(index);
+ return true;
+}
+bool KviKvsObject_tabwidget::functiontabLabel(KviKvsObjectFunctionCall *c)
+{
+ kvs_uint_t uIndex;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("index",KVS_PT_INT,0,uIndex)
+ KVSO_PARAMETERS_END(c)
+ if (!widget()) return true;
+ QString label=((QTabWidget *)widget())->label(uIndex);
+ c->returnValue()->setString(label);
+ return true;
+}
+bool KviKvsObject_tabwidget::functionsetMargin(KviKvsObjectFunctionCall *c)
+{
+ kvs_int_t iMargin;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("margin",KVS_PT_INT,0,iMargin)
+ KVSO_PARAMETERS_END(c)
+ if (widget()) ((QTabWidget *)widget())->setMargin(iMargin);
+ return true;
+}
+bool KviKvsObject_tabwidget::functionmargin(KviKvsObjectFunctionCall *c)
+{
+
+ if (widget()) c->returnValue()->setInteger(((QTabWidget *)widget())->margin());
+ return true;
+}
+
+bool KviKvsObject_tabwidget::functioncount(KviKvsObjectFunctionCall *c)
+{
+ if (!widget()) return true;
+ int count = ((QTabWidget *)widget())->count();
+ c->returnValue()->setInteger(count);
+ return true;
+}
+
+bool KviKvsObject_tabwidget::functioncurrentTabLabel(KviKvsObjectFunctionCall *c)
+{
+ if (widget())
+ {
+ int i= ((QTabWidget *)widget())->currentPageIndex();
+ QString label=((QTabWidget *)widget())->label(i);
+ c->returnValue()->setString(label);
+ }
+ return true;
+}
+bool KviKvsObject_tabwidget::functionremovePage(KviKvsObjectFunctionCall *c)
+{
+ KviKvsObject *ob;
+ kvs_hobject_t hObject;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("tab_widget",KVS_PT_HOBJECT,0,hObject)
+ KVSO_PARAMETERS_END(c)
+ ob=KviKvsKernel::instance()->objectController()->lookupObject(hObject);
+ if(!widget())return true;
+ if (!ob)
+ {
+ c->warning(__tr2qs("Widget parameter is not an object"));
+ return true;
+ }
+ if (!ob->object())
+ {
+ c->warning(__tr2qs("Widget parameter is not a valid object"));
+ return true;
+ }
+ if(!ob->object()->isWidgetType())
+ {
+ c->warning(__tr2qs("Not a widget object"));
+ return true;
+ }
+ int ctrl = ((QTabWidget *)widget())->indexOf (((QWidget *)(ob->object())));
+ if (ctrl == -1)
+ {
+ c->warning(__tr2qs("Can't find the tab "));
+ return true;
+ }
+ ((QTabWidget *)widget())->removePage(((QWidget *)(ob->object())));
+ return true;
+}
+
+bool KviKvsObject_tabwidget::functionchangeTab(KviKvsObjectFunctionCall *c)
+{
+ KviKvsObject *ob;
+ QString szLabel,szIcon;
+ kvs_hobject_t hObject;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("tab_widget",KVS_PT_HOBJECT,0,hObject)
+ KVSO_PARAMETER("label",KVS_PT_STRING,0,szLabel)
+ KVSO_PARAMETER("icon_id",KVS_PT_STRING,KVS_PF_OPTIONAL,szIcon)
+ KVSO_PARAMETERS_END(c)
+ ob=KviKvsKernel::instance()->objectController()->lookupObject(hObject);
+ if (!ob)
+ {
+ c->warning(__tr2qs("Widget parameter is not an object"));
+ return true;
+ }
+ if (!ob->object())
+ {
+ c->warning(__tr2qs("Widget parameter is not a valid object"));
+ return true;
+ }
+ if(!widget())return true;
+ if(!ob->object()->isWidgetType())
+ {
+ c->warning(__tr2qs("Not a widget object"));
+ return true;
+ }
+ int ctrl = ((QTabWidget *)widget())->indexOf (((QWidget *)(ob->object())));
+ if (ctrl == -1)
+ {
+ c->warning(__tr2qs("Can't find the tab "));
+ return true;
+ }
+ QPixmap * pix = g_pIconManager->getImage(szIcon);
+ if(pix){
+ #ifdef COMPILE_USE_QT4
+ ((QTabWidget *)widget())->changeTab(((QWidget *)(ob->object())),QIconSet(*pix),szLabel);
+ #else
+ ((QTabWidget *)widget())->changeTab(((QWidget *)(ob->object())),QIconSet(*pix,QIconSet::Small),szLabel);
+ #endif
+ }
+ else ((QTabWidget *)widget())->changeTab(((QWidget *)(ob->object())),szLabel);
+ return true;
+}
+bool KviKvsObject_tabwidget::functionsetTabPosition(KviKvsObjectFunctionCall *c)
+{
+ QString szPos;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("tab_position",KVS_PT_STRING,0,szPos)
+ KVSO_PARAMETERS_END(c)
+ if(!widget())return true;
+ if(KviQString::equalCI(szPos,"Top"))
+ ((QTabWidget *)widget())->setTabPosition(QTabWidget::Top);
+ else if(KviQString::equalCI(szPos,"Bottom"))
+ ((QTabWidget *)widget())->setTabPosition(QTabWidget::Bottom);
+ else c->warning( __tr2qs("Unknown position 'Q%'"),&szPos);
+ return true;
+}
+
+
+
+bool KviKvsObject_tabwidget::functionCurrentChangedEvent(KviKvsObjectFunctionCall *c)
+{
+
+ emitSignal("valueChanged",c,c->params());
+ return true;
+}
+
+void KviKvsObject_tabwidget::slotCurrentChanged(int value)
+{
+ KviKvsVariantList params(new KviKvsVariant((kvs_int_t)value));
+ callFunction(this,"currentChangedEvent",&params);
+}
+
+#include "m_class_tabwidget.moc"
diff --git a/src/modules/objects/class_tabwidget.h b/src/modules/objects/class_tabwidget.h
new file mode 100644
index 00000000..acc76d36
--- /dev/null
+++ b/src/modules/objects/class_tabwidget.h
@@ -0,0 +1,61 @@
+#ifndef _CLASS_TABWIDGET_H_
+#define _CLASS_TABWIDGET_H_
+//mdm:
+// File : class_tabwidget.h
+// Creation date : Fri Feb 11 10:21:48 CEST 2005
+// by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+#include <qtabwidget.h>
+#include "class_widget.h"
+
+#include "object_macros.h"
+
+class KviKvsObject_tabwidget : public KviKvsObject_widget
+{
+ Q_OBJECT
+public:
+ KVSO_DECLARE_OBJECT(KviKvsObject_tabwidget)
+public:
+ QWidget * widget() { return (QWidget *)object(); };
+protected:
+ virtual bool init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams);
+
+ bool functionaddTab(KviKvsObjectFunctionCall *c);
+ bool functioninsertTab(KviKvsObjectFunctionCall *c);
+ bool functionsetTabToolTip(KviKvsObjectFunctionCall *c);
+ bool functionremoveTabToolTip(KviKvsObjectFunctionCall *c);
+ bool functionsetTabLabel(KviKvsObjectFunctionCall *c);
+ bool functionsetCurrentPage(KviKvsObjectFunctionCall *c);
+ bool functioncurrentPageIndex(KviKvsObjectFunctionCall *c);
+ bool functiontabLabel(KviKvsObjectFunctionCall *c);
+ bool functioncurrentTabLabel(KviKvsObjectFunctionCall *c);
+ bool functionsetMargin(KviKvsObjectFunctionCall *c);
+ bool functionmargin(KviKvsObjectFunctionCall *c);
+ bool functioncount(KviKvsObjectFunctionCall *c);
+ bool functionchangeTab(KviKvsObjectFunctionCall *c);
+ bool functionCurrentChangedEvent(KviKvsObjectFunctionCall *c);
+ bool functionremovePage(KviKvsObjectFunctionCall *c);
+ bool functionsetTabPosition(KviKvsObjectFunctionCall *c);
+
+protected slots:
+ void slotCurrentChanged(int);
+};
+
+#endif //!_CLASS_TABWIDGET_H_
diff --git a/src/modules/objects/class_tbrowser.cpp b/src/modules/objects/class_tbrowser.cpp
new file mode 100644
index 00000000..67dce8cb
--- /dev/null
+++ b/src/modules/objects/class_tbrowser.cpp
@@ -0,0 +1,143 @@
+//mdm:
+// File : class_tbrowser.cpp
+// Creation date : Fri Jan 28 14:21:48 CEST 2005
+// by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include <qtextbrowser.h>
+#include "class_tbrowser.h"
+#include "kvi_error.h"
+#include "kvi_debug.h"
+
+#include "kvi_locale.h"
+#include "kvi_iconmanager.h"
+
+/*
+ @doc: textbrowser
+ @keyterms:
+ textbrowser browser widget class,
+ @title:
+ textbrowser class
+ @type:
+ class
+ @short:
+ Provides a class that can display html pages.
+ @inherits:
+ [class]widget[/class]
+ @description:
+ Provides a class that can display html pages with hypertext navigation.
+ @functions:
+ !fn: $setSource(<file_name:string>)
+ With this you can display the page at szFile location (szFile include the path).
+ !fn: $backward()
+ Changes the document displayed to the previous document in the list of documents built by navigating links.
+ !fn: $forward()
+ Changes the document displayed to the next document in the list of documents built by navigating links.
+ !fn: $home()
+ Changes the document displayed to be the first document the browser displayed.
+ !fn: $reload()
+ Reloads the current set source.
+ !fn: $linkClickedEvent(<link_href:string>)
+ Triggered when a link is clicked by the user. The default implementation of this function
+ emits the "linkClicked" signal.
+ @signals:
+ !sg: $linkClicked(<link_href:string>)
+ This signal is emitted by the default implementation of the [classfnc]$linkClickedEvent[/classfnc]() function.
+*/
+
+KVSO_BEGIN_REGISTERCLASS(KviKvsObject_textbrowser,"textbrowser","multilineedit")
+ KVSO_REGISTER_HANDLER(KviKvsObject_textbrowser,"setSource",function_setSource)
+ KVSO_REGISTER_HANDLER(KviKvsObject_textbrowser,"forward",function_forward)
+ KVSO_REGISTER_HANDLER(KviKvsObject_textbrowser,"backward",function_backward)
+ KVSO_REGISTER_HANDLER(KviKvsObject_textbrowser,"home",function_home)
+ KVSO_REGISTER_HANDLER(KviKvsObject_textbrowser,"reload",function_reload)
+ KVSO_REGISTER_HANDLER(KviKvsObject_textbrowser,"linkClickedEvent",function_linkClickedEvent)
+KVSO_END_REGISTERCLASS(KviKvsObject_textbrowser)
+
+KVSO_BEGIN_CONSTRUCTOR(KviKvsObject_textbrowser,KviKvsObject_mledit)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_textbrowser)
+
+
+KVSO_BEGIN_DESTRUCTOR(KviKvsObject_textbrowser)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_textbrowser)
+
+bool KviKvsObject_textbrowser::init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams)
+{
+ QTextBrowser * tb = new QTextBrowser(parentScriptWidget(), name());
+ setObject(tb, true);
+ connect(tb,SIGNAL(anchorClicked(const QString &,const QString &)),this,SLOT(anchorClicked(const QString &,const QString &)));
+ return true;
+}
+
+bool KviKvsObject_textbrowser::function_setSource(KviKvsObjectFunctionCall *c)
+{
+ QString szFile;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("file_name",KVS_PT_STRING,0,szFile)
+ KVSO_PARAMETERS_END(c)
+ if(!QFile::exists(szFile))
+ {
+ c->warning(__tr2qs("I can't find the specified file '%Q'."),&szFile);
+ return true;
+ }
+
+ if (widget()) ((QTextBrowser *)widget())->setSource(szFile);
+ return true;
+}
+
+bool KviKvsObject_textbrowser::function_forward(KviKvsObjectFunctionCall *c)
+{
+ if (widget()) ((QTextBrowser *)widget())->forward();
+ return true;
+}
+
+bool KviKvsObject_textbrowser::function_backward(KviKvsObjectFunctionCall *c)
+{
+ if (widget()) ((QTextBrowser *)widget())->backward();
+ return true;
+}
+
+bool KviKvsObject_textbrowser::function_home(KviKvsObjectFunctionCall *c)
+{
+ if (widget()) ((QTextBrowser *)widget())->home();
+ return true;
+}
+
+bool KviKvsObject_textbrowser::function_reload(KviKvsObjectFunctionCall *c)
+{
+ if (widget()) ((QTextBrowser *)widget())->reload();
+ return true;
+}
+
+void KviKvsObject_textbrowser::anchorClicked(const QString &szName,const QString &szLink)
+{
+ KviKvsVariantList parms(new KviKvsVariant(szLink));
+ callFunction(this,"linkClickedEvent",0,&parms);
+}
+
+bool KviKvsObject_textbrowser::function_linkClickedEvent(KviKvsObjectFunctionCall *c)
+{
+ emitSignal("linkClicked",c,c->params());
+ return true;
+}
+
+#include "m_class_tbrowser.moc"
diff --git a/src/modules/objects/class_tbrowser.h b/src/modules/objects/class_tbrowser.h
new file mode 100644
index 00000000..980bdc28
--- /dev/null
+++ b/src/modules/objects/class_tbrowser.h
@@ -0,0 +1,52 @@
+#ifndef _CLASS_TBROWSER_H_
+#define _CLASS_TBROWSER_H_
+//mdm:
+// File : class_tbrowser.h
+// Creation date : Fri Feb 28 14:21:48 CEST 2005
+// by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include <qtextbrowser.h>
+#include "class_widget.h"
+#include <qfile.h>
+#include "class_multilineedit.h"
+#include "object_macros.h"
+
+class KviKvsObject_textbrowser : public KviKvsObject_mledit
+{
+ Q_OBJECT
+public:
+ KVSO_DECLARE_OBJECT(KviKvsObject_textbrowser)
+public:
+ QWidget * widget() { return (QWidget *)object(); };
+protected:
+ virtual bool init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams);
+
+ bool function_setSource(KviKvsObjectFunctionCall *c);
+ bool function_forward(KviKvsObjectFunctionCall *c);
+ bool function_backward(KviKvsObjectFunctionCall *c);
+ bool function_home(KviKvsObjectFunctionCall *c);
+ bool function_reload(KviKvsObjectFunctionCall *c);
+ bool function_linkClickedEvent(KviKvsObjectFunctionCall *c);
+protected slots:
+ void anchorClicked(const QString &szName,const QString &szLink);
+};
+
+#endif //!_CLASS_TBROWSER_H_
diff --git a/src/modules/objects/class_toolbar.cpp b/src/modules/objects/class_toolbar.cpp
new file mode 100644
index 00000000..ed280bd0
--- /dev/null
+++ b/src/modules/objects/class_toolbar.cpp
@@ -0,0 +1,156 @@
+//mdm:
+// File : class_toolbar.cpp
+// Creation date : Tue Feb 22 22:12:55 CEST 2005
+// by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "class_toolbar.h"
+#include "kvi_error.h"
+#include "kvi_debug.h"
+#include "kvi_tal_toolbar.h"
+#include "kvi_tal_mainwindow.h"
+#include "kvi_locale.h"
+#include "kvi_iconmanager.h"
+#include "class_mainwindow.h"
+
+/*
+ @doc: toolbar
+ @keyterms:
+ toolbar object class,
+ @title:
+ toolbar class
+ @type:
+ class
+ @short:
+ Provides a toolbar for mainwindow widget.
+ @inherits:
+ [class]object[/class]
+ [class]widget[/class]
+ @description:
+ The toolbar class provides a movable panel containing widgets such as tool buttons.
+ @functions:
+ !fn: $addSeparator()
+ Adds a separator to the right/bottom of the toolbar.
+ !fn: $setLabel(<text:string>)
+ Sets the toolbar's label.
+ !fn: <string> $label()
+ Returns the toolbar's label.
+ !fn: $setStretchableWidget(<widget:object>)
+ Sets the <widget> to be expanded.
+ !fn: $clear()
+ Deletes all the toolbar's child widgets.
+
+*/
+
+
+KVSO_BEGIN_REGISTERCLASS(KviKvsObject_toolbar,"toolbar","object")
+ KVSO_REGISTER_HANDLER(KviKvsObject_toolbar,"addSeparator", functionaddSeparator)
+ KVSO_REGISTER_HANDLER(KviKvsObject_toolbar,"setLabel", functionsetLabel)
+ KVSO_REGISTER_HANDLER(KviKvsObject_toolbar,"label", functionlabel)
+ KVSO_REGISTER_HANDLER(KviKvsObject_toolbar,"setStretchableWidget", functionsetStretchableWidget)
+ KVSO_REGISTER_HANDLER(KviKvsObject_toolbar,"clear", functionclear)
+KVSO_END_REGISTERCLASS(KviKvsObject_toolbar)
+
+KVSO_BEGIN_CONSTRUCTOR(KviKvsObject_toolbar,KviKvsObject_widget)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_toolbar)
+
+
+KVSO_BEGIN_DESTRUCTOR(KviKvsObject_toolbar)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_toolbar)
+
+bool KviKvsObject_toolbar::init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams)
+{
+ if (!parentObject())
+ {
+ pContext->warning(__tr2qs("the toolbar cannot be a parent-widget!"));
+ return true;
+ }
+ if(parentObject()->inherits("KviKvsObject_mainwindow"))
+ {
+ setObject(new KviTalToolBar(name(), ((KviTalMainWindow *)parentScriptWidget())), true);
+ }
+ else
+ {
+ pContext->warning(__tr2qs("The parent-widget isn't a MainWindow."));
+ }
+
+ return true;
+}
+
+bool KviKvsObject_toolbar::functionaddSeparator(KviKvsObjectFunctionCall *c)
+{
+ if(widget()) ((KviTalToolBar *)widget())->addSeparator();
+ return true;
+}
+bool KviKvsObject_toolbar::functionsetLabel(KviKvsObjectFunctionCall *c)
+{
+ QString szLabel;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("label",KVS_PT_STRING,0,szLabel)
+ KVSO_PARAMETERS_END(c)
+ if (widget()) ((KviTalToolBar *)widget())->setLabel(szLabel);
+ return true;
+}
+bool KviKvsObject_toolbar::functionlabel(KviKvsObjectFunctionCall *c)
+{
+ if (widget()) c->returnValue()->setString(((KviTalToolBar *)widget())->label());
+ return true;
+}
+bool KviKvsObject_toolbar::functionsetStretchableWidget(KviKvsObjectFunctionCall *c)
+{
+ KviKvsObject *ob;
+ kvs_hobject_t hObject;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("widget",KVS_PT_HOBJECT,0,hObject)
+ KVSO_PARAMETERS_END(c)
+ ob=KviKvsKernel::instance()->objectController()->lookupObject(hObject);
+ if (!widget()) return true;
+ if (!ob)
+ {
+ c->warning(__tr2qs("Widget parameter is not an object"));
+ return true;
+ }
+ if (!ob->object())
+ {
+ c->warning(__tr2qs("Widget parameter is not a valid object"));
+ return true;
+ }
+ if(!ob->object()->inherits("KviKvsObject_widget"))
+ {
+ c->warning(__tr2qs("Widget object required"));
+ return TRUE;
+ }
+#ifndef COMPILE_USE_QT4
+ // FIXME: no support for this in Qt4 ?
+ if(widget()) ((KviTalToolBar *)widget())->setStretchableWidget(((QWidget *)(ob->object())));
+#endif //!COMPILE_USE_QT4
+ return true;
+}
+bool KviKvsObject_toolbar::functionclear(KviKvsObjectFunctionCall *c)
+{
+ if (widget())
+ ((KviTalToolBar *)object())->clear();
+ return true;
+}
+
+#include "m_class_toolbar.moc"
+
diff --git a/src/modules/objects/class_toolbar.h b/src/modules/objects/class_toolbar.h
new file mode 100644
index 00000000..1912e639
--- /dev/null
+++ b/src/modules/objects/class_toolbar.h
@@ -0,0 +1,50 @@
+#ifndef _CLASS_TOOLBAR_H_
+#define _CLASS_TOOLBAR_H_
+//mdm:
+// File : class_toolbar.h
+// Creation date : Tue Feb 22 22:12:48 CEST 2005
+// by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+
+
+#include "class_widget.h"
+#include "object_macros.h"
+
+class KviKvsObject_toolbar : public KviKvsObject_widget
+{
+ Q_OBJECT
+public:
+ KVSO_DECLARE_OBJECT(KviKvsObject_toolbar)
+public:
+ QWidget * widget() { return (QWidget *)object(); };
+protected:
+ virtual bool init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams);
+
+ bool functionaddSeparator(KviKvsObjectFunctionCall *c);
+ bool functionsetLabel(KviKvsObjectFunctionCall *c);
+ bool functionlabel(KviKvsObjectFunctionCall *c);
+ bool functionsetStretchableWidget(KviKvsObjectFunctionCall *c);
+ bool functionclear(KviKvsObjectFunctionCall *c);
+};
+
+
+#endif //!_CLASS_TOOLBAR_H_
diff --git a/src/modules/objects/class_toolbutton.cpp b/src/modules/objects/class_toolbutton.cpp
new file mode 100644
index 00000000..032b0c60
--- /dev/null
+++ b/src/modules/objects/class_toolbutton.cpp
@@ -0,0 +1,341 @@
+//mdm:
+// File : class_toolbutton.cpp
+// Creation date : Wed Feb 23 16:39:48 CEST 2005
+// by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "class_toolbutton.h"
+#include "kvi_error.h"
+#include "kvi_debug.h"
+
+#include "kvi_locale.h"
+#include "kvi_iconmanager.h"
+#include "kvi_tal_popupmenu.h"
+/*
+ @doc: toolbutton
+ @keyterms:
+ toolbutton object class,
+ @title:
+ toolbutton class
+ @type:
+ class
+ @short:
+ Provides a toolbutton for toolbar widget.
+ @inherits:
+ [class]object[/class]
+ [class]widget[/class]
+ @description:
+ The toolbutton class provides a quick-access button to commands or options, usually used inside a ToolBar.
+ @functions:
+ !fn:$setImage(<icon_id:string>)
+ Sets the image for this button.
+ !fn:$setUsesBigPixmap(<bEnabled:boolean>)
+ Sets whether this toolbutton uses big pixmaps to enable.
+ !fn:$usesBigPixmap(<bEnabled:boolean>)
+ This property holds whether this toolbutton uses big pixmaps.
+ !fn:setUsesTextLabel(<bEnabled:boolean>)
+ Sets whether the toolbutton show a texlabel below the pixmap of the button.
+ !fn:$usesTextLabel()
+ Return 1 if the setUsesTextLabel is enabled, otherwise return 0.
+ !fn:$setTextLabel(<text:String>,[tooltip:string])
+ Sets the label of this button to <text> and automatically sets it as a tool tip if <tip> is TRUE.
+ !fn:<string> $textLabel()
+ Returns the label of tthe button.
+ !fn:$setAutoRaise(<bAutoraise:boolean>)
+ Sets whether auto-raising is enabled.
+ !fn:<boolean> $autoRaise()
+ Returns 1 if autoRaise is enabled, otherwise returns 0.
+ !fn:$setToggleButton(<bToggle:boolean>)
+ Sets whether the tool button is a toggle button 1 enable, 0 disable.
+ !fn:<boolean> $toggle()
+ Toggles the state of the tool button.
+ !fn:$setOn(<bEnabled:boolean>)
+ Sets whether the tool button is on to the bool value: 1 enable, 0 disable.
+ // findme
+ !fn:$setPopup (<toolbutton:object>)
+ !fn:$setPopupDelay (<int delay>)
+ Sets the time delay between pressing the button and the appearance of the associated popup menu in milliseconds to delay.[br]
+ A good value is 100.
+ !fn:<integer> $pupupDelay()
+ Returns the time delay between pressing the button and the appearance of the associated popup menu in milliseconds.
+ !fn:$openPopup()
+ Opens the associated popup menu. If there is no such menu, this function does nothing.
+ !fn:setTextPosition(<text_position:string>)
+ Sets the position of the tool button's textLabel in relation to the tool button's icon.[br]
+ Valid texpos values are:[br]
+ - BesideIcon : The text appears beside the icon.[br]
+ - BelowIcon : The text appears below the icon.
+ !fn:<string> $textPosition()
+ Returns the position of the text label of this button.
+ !fn: $clickEvent()
+ This function is called when the toolbutton is clicked.[br]
+ You can reimplement it to handle the user click events.[br]
+ The default implementation emits the [classfnc]$clicked[/classfnc]() signal.
+ @signals:
+ !sg: $clicked()
+ This signal is emitted by the default implementation of [classfnc]$clickEvent[/classfnc]().[br]
+*/
+
+KVSO_BEGIN_REGISTERCLASS(KviKvsObject_toolbutton,"toolbutton","widget")
+ KVSO_REGISTER_HANDLER(KviKvsObject_toolbutton,"setImage", functionsetImage)
+ KVSO_REGISTER_HANDLER(KviKvsObject_toolbutton,"setUsesBigPixmap", functionsetUsesBigPixmap)
+ KVSO_REGISTER_HANDLER(KviKvsObject_toolbutton,"usesBigPixmap", functionusesBigPixmap)
+ KVSO_REGISTER_HANDLER(KviKvsObject_toolbutton,"setUsesTextLabel", functionsetUsesTextLabel)
+ KVSO_REGISTER_HANDLER(KviKvsObject_toolbutton,"usesTextLabel", functionusesTextLabel)
+ KVSO_REGISTER_HANDLER(KviKvsObject_toolbutton,"setAutoRaise", function_setAutoRaise)
+ KVSO_REGISTER_HANDLER(KviKvsObject_toolbutton,"autoRaise", function_autoRaise)
+ KVSO_REGISTER_HANDLER(KviKvsObject_toolbutton,"setTextLabel", functionsetTextLabel)
+ KVSO_REGISTER_HANDLER(KviKvsObject_toolbutton,"textLabel", functiontextLabel)
+ KVSO_REGISTER_HANDLER(KviKvsObject_toolbutton,"setPopup", functionsetPopup)
+ KVSO_REGISTER_HANDLER(KviKvsObject_toolbutton,"openPopup", functionopenPopup)
+
+ KVSO_REGISTER_HANDLER(KviKvsObject_toolbutton,"setToggleButton", functionsetToggleButton)
+ KVSO_REGISTER_HANDLER(KviKvsObject_toolbutton,"toggle", functiontoggle)
+ KVSO_REGISTER_HANDLER(KviKvsObject_toolbutton,"setOn", functionsetOn)
+
+ KVSO_REGISTER_HANDLER(KviKvsObject_toolbutton,"setPopupDelay", functionsetPopupDelay)
+ KVSO_REGISTER_HANDLER(KviKvsObject_toolbutton,"popupDelay", functionpopupDelay)
+ KVSO_REGISTER_HANDLER(KviKvsObject_toolbutton,"setTextPosition", functionsetTextPosition)
+ KVSO_REGISTER_HANDLER(KviKvsObject_toolbutton,"textPosition", functiontextPosition)
+
+ KVSO_REGISTER_HANDLER(KviKvsObject_toolbutton,"clickEvent",function_clickEvent)
+KVSO_END_REGISTERCLASS(KviKvsObject_toolbutton)
+
+KVSO_BEGIN_CONSTRUCTOR(KviKvsObject_toolbutton,KviKvsObject_widget)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_toolbutton)
+
+
+KVSO_BEGIN_DESTRUCTOR(KviKvsObject_toolbutton)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_toolbutton)
+
+bool KviKvsObject_toolbutton::init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams)
+{
+ setObject(new QToolButton(parentScriptWidget(), name()), true);
+ connect(widget(),SIGNAL(clicked()),this,SLOT(slotClicked()));
+ return true;
+}
+
+bool KviKvsObject_toolbutton::functionsetImage(KviKvsObjectFunctionCall *c)
+{
+ QString icon;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("icon_id",KVS_PT_STRING,0,icon)
+ KVSO_PARAMETERS_END(c)
+ if (!widget()) return true;
+ QPixmap * pix = g_pIconManager->getImage(icon);
+ if(pix){
+ #ifdef COMPILE_USE_QT4
+ ((QToolButton *)widget())->setIconSet(QIconSet(*pix));
+ #else
+ ((QToolButton *)widget())->setIconSet(QIconSet(*pix,QIconSet::Small));
+ #endif
+ }
+ else
+ ((QToolButton *)widget())->setIconSet(QIconSet());
+ return true;
+}
+bool KviKvsObject_toolbutton::functionsetUsesBigPixmap(KviKvsObjectFunctionCall *c)
+{
+ bool bEnabled;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bEnabled",KVS_PT_BOOL,0,bEnabled)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ ((QToolButton *)widget())->setUsesBigPixmap(bEnabled);
+ return true;
+}
+bool KviKvsObject_toolbutton::functionusesBigPixmap(KviKvsObjectFunctionCall *c)
+{
+ if (widget())
+ c->returnValue()->setBoolean(((QToolButton *)widget())->usesBigPixmap());
+ return true;
+}
+bool KviKvsObject_toolbutton::functionsetUsesTextLabel(KviKvsObjectFunctionCall *c)
+{
+ bool bEnabled;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bEnabled",KVS_PT_BOOL,0,bEnabled)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ ((QToolButton *)widget())->setUsesTextLabel(bEnabled);
+ return true;
+}
+bool KviKvsObject_toolbutton::functionusesTextLabel(KviKvsObjectFunctionCall *c)
+{
+ if (widget())
+ c->returnValue()->setBoolean(((QToolButton *)widget())->usesTextLabel());
+ return true;
+}
+bool KviKvsObject_toolbutton::function_setAutoRaise(KviKvsObjectFunctionCall *c)
+{
+ bool bEnabled;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bEnabled",KVS_PT_BOOL,0,bEnabled)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ ((QToolButton *)widget())->setAutoRaise(bEnabled);
+ return true;
+}
+bool KviKvsObject_toolbutton::function_autoRaise(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ c->returnValue()->setBoolean(((QToolButton *)widget())->autoRaise());
+ return true;
+}
+bool KviKvsObject_toolbutton::functionsetOn(KviKvsObjectFunctionCall *c)
+{
+ bool bEnabled;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bEnabled",KVS_PT_BOOL,0,bEnabled)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ ((QToolButton *)widget())->setOn(bEnabled);
+ return true;
+}
+
+bool KviKvsObject_toolbutton::functionsetToggleButton(KviKvsObjectFunctionCall *c)
+{
+ bool bEnabled;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bEnabled",KVS_PT_BOOL,0,bEnabled)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ ((QToolButton *)widget())->setToggleButton(bEnabled);
+ return true;
+}
+bool KviKvsObject_toolbutton::functiontoggle(KviKvsObjectFunctionCall *c)
+{
+ if (widget())
+ ((QToolButton *)widget())->toggle();
+ return true;
+}
+
+bool KviKvsObject_toolbutton::functionsetTextLabel(KviKvsObjectFunctionCall *c)
+{
+ QString szLabel,szTip;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("label",KVS_PT_STRING,0,szLabel)
+ KVSO_PARAMETER("tooltip",KVS_PT_STRING,KVS_PF_OPTIONAL,szTip)
+ KVSO_PARAMETERS_END(c)
+ if(!widget()) return true;
+
+ #ifdef COMPILE_USE_QT4
+ ((QToolButton *)widget())->setText(szLabel);
+ if (!szTip.isEmpty()) ((QToolButton *)widget())->setToolTip(szTip);
+ #else
+ if (szTip.isEmpty()) ((QToolButton *)widget())->setTextLabel(szLabel);
+ else ((QToolButton *)widget())->setTextLabel(szLabel,szTip);
+ #endif
+ return true;
+}
+bool KviKvsObject_toolbutton::functiontextLabel(KviKvsObjectFunctionCall *c)
+{
+ if (widget())
+ c->returnValue()->setString(((QToolButton *)widget())->textLabel());
+ return true;
+}
+bool KviKvsObject_toolbutton::functionsetPopup(KviKvsObjectFunctionCall *c)
+{
+ KviKvsObject *ob;
+ kvs_hobject_t hObject;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("widget",KVS_PT_HOBJECT,0,hObject)
+ KVSO_PARAMETERS_END(c)
+ ob=KviKvsKernel::instance()->objectController()->lookupObject(hObject);
+ if (!ob)
+ {
+ c->warning(__tr2qs("Widget parameter is not an object"));
+ return true;
+ }
+ if (!ob->object())
+ {
+ c->warning(__tr2qs("Widget parameter is not a valid object"));
+ return true;
+ }
+ if(!ob->object()->inherits("KviKvsObject_popupmenu"))
+ {
+ c->warning(__tr2qs("Can't add a non - popupmenu object"));
+ return TRUE;
+ }
+ if(widget())
+ ((QToolButton *)widget())->setPopup(((KviTalPopupMenu *)(ob->object())));
+ return true;
+}
+bool KviKvsObject_toolbutton::functionopenPopup(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ ((QToolButton *)widget())->openPopup();
+ return true;
+}
+bool KviKvsObject_toolbutton::functionsetPopupDelay(KviKvsObjectFunctionCall *c)
+{
+ kvs_int_t uDelay;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("delay",KVS_PT_UNSIGNEDINTEGER,0,uDelay)
+ KVSO_PARAMETERS_END(c)
+ if (widget())
+ ((QToolButton *)widget())->setPopupDelay(uDelay);
+ return true;
+}
+bool KviKvsObject_toolbutton::functionpopupDelay(KviKvsObjectFunctionCall *c)
+{
+ if (widget())
+ c->returnValue()->setInteger(((QToolButton *)widget())->popupDelay());
+ return true;
+}
+bool KviKvsObject_toolbutton::functionsetTextPosition(KviKvsObjectFunctionCall *c)
+{
+ QString szPos;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("position",KVS_PT_STRING,0,szPos)
+ KVSO_PARAMETERS_END(c)
+ if(!widget())return true;
+ if(KviQString::equalCI(szPos,"BesideIcon"))
+ ((QToolButton *)widget())->setTextPosition(QToolButton::BesideIcon);
+ else if(KviQString::equalCI(szPos,"BelowIcon"))
+ ((QToolButton *)widget())->setTextPosition(QToolButton::BelowIcon);
+ else c->warning(__tr2qs("Unknown text position '%Q'"),&szPos);
+ return true;
+}
+bool KviKvsObject_toolbutton::functiontextPosition(KviKvsObjectFunctionCall *c)
+{
+ if(!widget()) return true;
+ QString szPos="BelowIcon";
+ if ((((QToolButton *)widget())->textPosition())==(QToolButton::BesideIcon))
+ szPos="BesideIcon";
+ c->returnValue()->setString(szPos);
+ return true;
+}
+bool KviKvsObject_toolbutton::function_clickEvent(KviKvsObjectFunctionCall *c)
+{
+ emitSignal("clicked",c);
+ return true;
+}
+
+void KviKvsObject_toolbutton::slotClicked()
+{
+ KviKvsVariantList *params=0;
+ callFunction(this,"clickEvent",params);
+}
+
+#include "m_class_toolbutton.moc"
+
diff --git a/src/modules/objects/class_toolbutton.h b/src/modules/objects/class_toolbutton.h
new file mode 100644
index 00000000..2cd4dfec
--- /dev/null
+++ b/src/modules/objects/class_toolbutton.h
@@ -0,0 +1,69 @@
+#ifndef _CLASS_TOOLBUTTON_H_
+#define _CLASS_TOOLBUTTON_H_
+
+//mdm:
+// File : class_toolbutton.h
+// Creation date : Wed Feb 23 16:39:48 CEST 2005
+// by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+#include <qtoolbutton.h>
+#include "class_widget.h"
+#include "object_macros.h"
+
+class KviKvsObject_toolbutton : public KviKvsObject_widget
+{
+ Q_OBJECT
+public:
+ KVSO_DECLARE_OBJECT(KviKvsObject_toolbutton)
+public:
+ QWidget * widget() { return (QWidget *)object(); };
+protected:
+ virtual bool init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams);
+
+ bool functionsetImage(KviKvsObjectFunctionCall *c);
+ bool functionsetUsesBigPixmap(KviKvsObjectFunctionCall *c);
+ bool functionusesBigPixmap(KviKvsObjectFunctionCall *c);
+ bool functionsetUsesTextLabel(KviKvsObjectFunctionCall *c);
+ bool functionusesTextLabel(KviKvsObjectFunctionCall *c);
+ bool functionsetTextLabel(KviKvsObjectFunctionCall *c);
+ bool functiontextLabel(KviKvsObjectFunctionCall *c);
+ bool functionsetPopup(KviKvsObjectFunctionCall *c);
+ bool functionopenPopup(KviKvsObjectFunctionCall *c);
+ bool functionsetOn(KviKvsObjectFunctionCall *c);
+ bool functionsetToggleButton(KviKvsObjectFunctionCall *c);
+ bool functiontoggle(KviKvsObjectFunctionCall *c);
+ bool functionsetPopupDelay(KviKvsObjectFunctionCall *c);
+ bool functionpopupDelay(KviKvsObjectFunctionCall *c);
+ bool functionsetTextPosition(KviKvsObjectFunctionCall *c);
+ bool functiontextPosition(KviKvsObjectFunctionCall *c);
+
+ bool function_setAutoRaise(KviKvsObjectFunctionCall *c);
+ bool function_autoRaise(KviKvsObjectFunctionCall *c);
+ bool function_clickEvent(KviKvsObjectFunctionCall *c);
+signals:
+ void clicked();
+protected slots:
+ void slotClicked();
+};
+
+
+#endif //!_CLASS_TOOLBUTTON_H_
diff --git a/src/modules/objects/class_urllabel.cpp b/src/modules/objects/class_urllabel.cpp
new file mode 100644
index 00000000..544153c2
--- /dev/null
+++ b/src/modules/objects/class_urllabel.cpp
@@ -0,0 +1,330 @@
+//vim: ts=8
+// File : class_urllabel.cpp
+// Creation date : Thu Feb 18 1:27:44 CEST 2001 by Krzysztof Godlewski
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Krzysztof Godlewski
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+#include "class_urllabel.h"
+
+#include "kvi_debug.h"
+#include "kvi_locale.h"
+#include "kvi_error.h"
+
+#include "kvi_app.h"
+
+#include "kvi_window.h"
+#include "kvi_kvs_script.h"
+#ifdef COMPILE_USE_QT4
+#include <QMouseEvent>
+#define QT_LEFT_BUTTON Qt::LeftButton
+#else
+#define QT_LEFT_BUTTON QEvent::LeftButton
+#endif
+//#warning "Functions to change colors for different states"
+//#warning "$setUnderline(), $underline()"
+
+//extern KviApp * g_pApp;
+/*static KviScriptObjectClass * g_pUrlLabelClass = 0;
+
+static KviScriptObject * urlLabelClassCreateInstance(KviScriptObjectClass * c,
+ KviScriptObject * p, const char * n)
+{
+ return new KviScriptUrlLabelObject(c, p, n);
+}
+
+KviScriptUrlLabelObject::KviScriptUrlLabelObject(KviScriptObjectClass * c, \
+KviScriptObject * p, const char *n) : KviScriptLabelObject(c, p, n)
+{
+ m_normalClr = QColor("black");
+ m_enterClr = QColor("blue");
+ m_activeClr = QColor("red");
+ m_useSingleClick = true;
+// ((QLabel *)widget())->setAutoResize(true);
+ //widget()->setCursor(Qt::pointingHandCursor);
+ //((KviScriptWidgetObject: * )p)->widget()->setCursor(Qt::pointingHandCursor);
+}
+
+KviScriptUrlLabelObject::~KviScriptUrlLabelObject()
+{
+}
+
+bool KviScriptUrlLabelObject::eventFilter(QObject * o, QEvent * e)
+{
+ QPalette pal = ((QLabel *)widget())->palette();
+
+ switch(e->type())
+ {
+ case QEvent::Enter:
+ pal.setColor(QColorGroup::Foreground, m_enterClr);
+ break;
+ case QEvent::Leave:
+ // this doesn't work...
+ if(((QMouseEvent *)e)->state() & QEvent::LeftButton)
+ pal.setColor(QColorGroup::Foreground, \
+ m_activeClr);
+ else
+ pal.setColor(QColorGroup::Foreground, \
+ m_normalClr);
+ break;
+ case QEvent::MouseButtonRelease:
+ pal.setColor(QColorGroup::Foreground, m_enterClr);
+ // perform actions here
+ if(!m_lastClickWasDbl && !m_useSingleClick)
+ break;
+ if(!m_action.isEmpty())
+ {
+
+ }
+ break;
+ case QEvent::MouseButtonPress:
+ m_lastClickWasDbl = false;
+ if(!((QMouseEvent * )e)->button() & \
+ QEvent::LeftButton || !m_useSingleClick)
+ break;
+ pal.setColor(QColorGroup::Foreground, m_activeClr);
+ break;
+ case QEvent::MouseButtonDblClick:
+ m_lastClickWasDbl = true;
+ if(m_useSingleClick)
+ break;
+ pal.setColor(QColorGroup::Foreground, m_activeClr);
+ break;
+ default: // make gcc happy
+ break;
+ }
+
+ ((QLabel *)widget())->setPalette(pal);
+
+ return false;
+}
+*/
+//#warning "Docs for urllabel"
+
+/*
+ @doc: urllabel
+ @keyterms:
+ display url, link
+ @title:
+ urllabel class
+ @type:
+ class
+ @short:
+ Displays an URI allowing to perform actions on click
+ @inherits:
+ [class]object[/class]
+ [class]widget[/class]
+ [class]label[/class]
+ @description:
+ This widget allows you to bind specific action on click. It can
+ open an url, or execute any KVI++ code. The text color reacts on
+ cursor movements and clicks.
+ @functions:
+ !fn: $setUrl(<text:string>)
+ Sets the url to be opened when the links is activated. The way
+ the label opens the url is defined in KVirc config dialog.
+ !fn: <string> $url()
+ Returns the currently set url.
+ !fn: $setAction(<text:string>)
+ Sets the action to be performed when the link is triggered. It
+ can be any valid KVI++ code. Note that all KVirc commands must
+ be prefixed with a '/', just as if you typed them in the input
+ widget.
+ !fn: <string> $action()
+ Returns currently set action string.
+ !fn: $setText(<text>)
+ Sets the label's text. Reimplemented from internal reasons.
+ !fn: $setCursorChange(<bEnabled:boolean>)
+ Tells the label wheather to change or not the shape of cursor,
+ when it is above the widget. Default is false.
+ !fn: <boolean> $cursorChange()
+ Returns true if the cursor changes over the label, false if not.
+ !fn: $setUseSingleClick(<bEnabled:boolean>)
+ If <bEnabled> is true, the label will react on single clicks,
+ otherwise only double clicks will trigger the link.
+ !fn: <boolean> $useSingleClick()
+ Returns true if the label reacts on single clicks, false if it
+ reacts only on double clicks.
+*/
+
+KVSO_BEGIN_REGISTERCLASS(KviKvsObject_urlabel,"urllabel","label")
+
+ KVSO_REGISTER_HANDLER(KviKvsObject_urlabel,"setUrl",functionsetUrl)
+ KVSO_REGISTER_HANDLER(KviKvsObject_urlabel,"url",functionurl)
+ KVSO_REGISTER_HANDLER(KviKvsObject_urlabel,"setAction",functionsetAction)
+ KVSO_REGISTER_HANDLER(KviKvsObject_urlabel,"action",functionaction)
+ KVSO_REGISTER_HANDLER(KviKvsObject_urlabel,"setText",functionsetText)
+ KVSO_REGISTER_HANDLER(KviKvsObject_urlabel,"setCursorChange",functionsetCursorChange)
+ KVSO_REGISTER_HANDLER(KviKvsObject_urlabel,"cursorChange",functioncursorChange)
+ KVSO_REGISTER_HANDLER(KviKvsObject_urlabel,"setUseSingleClick",functionsetUseSingleClick)
+ KVSO_REGISTER_HANDLER(KviKvsObject_urlabel,"useSingleClick",functionuseSingleClick)
+
+KVSO_END_REGISTERCLASS(KviKvsObject_urlabel)
+
+
+KVSO_BEGIN_CONSTRUCTOR(KviKvsObject_urlabel,KviKvsObject_label)
+
+ m_normalClr = QColor("black");
+ m_enterClr = QColor("blue");
+ m_activeClr = QColor("red");
+ m_useSingleClick = true;
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_urlabel)
+
+KVSO_BEGIN_DESTRUCTOR(KviKvsObject_urlabel)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_urlabel)
+
+bool KviKvsObject_urlabel::eventFilter(QObject * o, QEvent * e)
+{
+ QPalette pal = ((QLabel *)widget())->palette();
+
+ switch(e->type())
+ {
+ case QEvent::Enter:
+ pal.setColor(QColorGroup::Foreground, m_enterClr);
+ break;
+ case QEvent::Leave:
+ // this doesn't work...
+ if(((QMouseEvent *)e)->state() & QT_LEFT_BUTTON)
+ pal.setColor(QColorGroup::Foreground, \
+ m_activeClr);
+ else
+ pal.setColor(QColorGroup::Foreground, \
+ m_normalClr);
+ break;
+ case QEvent::MouseButtonRelease:
+ pal.setColor(QColorGroup::Foreground, m_enterClr);
+ // perform actions here
+ if(!m_lastClickWasDbl && !m_useSingleClick)
+ break;
+ if(!m_action.isEmpty())
+ {
+ KviKvsScript kvs("commandline",m_action);
+ kvs.run(g_pActiveWindow,0,0/*,KviKvsScript::AssumeLocals*/);
+
+ } else if(!m_url.isEmpty()) {
+ KviKvsScript kvs("commandline","openurl "+m_url);
+ kvs.run(g_pActiveWindow,0,0/*,KviKvsScript::AssumeLocals*/);
+ }
+ break;
+ case QEvent::MouseButtonPress:
+ m_lastClickWasDbl = false;
+ if(!((QMouseEvent * )e)->button() & \
+ QT_LEFT_BUTTON || !m_useSingleClick)
+ break;
+ pal.setColor(QColorGroup::Foreground, m_activeClr);
+ break;
+ case QEvent::MouseButtonDblClick:
+ m_lastClickWasDbl = true;
+ if(m_useSingleClick)
+ break;
+ pal.setColor(QColorGroup::Foreground, m_activeClr);
+ break;
+ default: // make gcc happy
+ break;
+ }
+
+ ((QLabel *)widget())->setPalette(pal);
+
+ return false;
+}
+bool KviKvsObject_urlabel::functionsetUrl(KviKvsObjectFunctionCall *c)
+{
+ QString szUrl;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("url",KVS_PT_STRING,0,szUrl)
+ KVSO_PARAMETERS_END(c)
+ if(!widget()) return true;
+ if(szUrl.isEmpty()){
+ c->error(__tr2qs("Not Enough Parameters"));
+ return false;
+ }
+ m_url = szUrl;
+ return true;
+}
+bool KviKvsObject_urlabel::functionurl(KviKvsObjectFunctionCall *c)
+{
+ c->returnValue()->setString(m_url);
+ return true;
+}
+bool KviKvsObject_urlabel::functionsetAction(KviKvsObjectFunctionCall *c)
+{
+ QString szAction;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("action",KVS_PT_STRING,0,szAction)
+ KVSO_PARAMETERS_END(c)
+ if(!widget()) return true;
+ if(szAction.isEmpty()){
+ c->error(__tr2qs("Not Enough Parameters"));
+ return false;
+ }
+ m_action = szAction;
+ return true;
+}
+bool KviKvsObject_urlabel::functionsetText(KviKvsObjectFunctionCall *c)
+{
+ QString szText;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("text",KVS_PT_STRING,0,szText)
+ KVSO_PARAMETERS_END(c)
+ if(!widget()) return true;
+ ((QLabel *)widget())->setText(szText);
+ ((QLabel *)widget())->setFixedSize(((QLabel *)widget())->sizeHint());
+ return true;
+}
+bool KviKvsObject_urlabel::functionaction(KviKvsObjectFunctionCall *c)
+{
+ c->returnValue()->setString(m_action);
+ return true;
+}
+bool KviKvsObject_urlabel::functionsetCursorChange(KviKvsObjectFunctionCall *c)
+{
+ bool bFlag;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bEnabled",KVS_PT_BOOLEAN,0,bFlag)
+ KVSO_PARAMETERS_END(c)
+ if(!widget())
+ return true;
+ if(m_changeCursor = bFlag)
+ widget()->setCursor(Qt::pointingHandCursor);
+ else
+ widget()->setCursor(Qt::arrowCursor);
+ return true;
+}
+bool KviKvsObject_urlabel::functionsetUseSingleClick(KviKvsObjectFunctionCall *c)
+{
+ bool bFlag;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bEnabled",KVS_PT_BOOLEAN,0,bFlag)
+ KVSO_PARAMETERS_END(c)
+ m_useSingleClick = bFlag;
+ return true;
+}
+bool KviKvsObject_urlabel::functionuseSingleClick(KviKvsObjectFunctionCall *c)
+{
+ c->returnValue()->setBoolean(m_useSingleClick);
+ return true;
+}
+bool KviKvsObject_urlabel::functioncursorChange(KviKvsObjectFunctionCall *c)
+{
+ c->returnValue()->setBoolean(m_changeCursor);
+ return true;
+}
diff --git a/src/modules/objects/class_urllabel.h b/src/modules/objects/class_urllabel.h
new file mode 100644
index 00000000..b9ee35d6
--- /dev/null
+++ b/src/modules/objects/class_urllabel.h
@@ -0,0 +1,64 @@
+#ifndef _CLASS_URLLABEL_H_
+#define _CLASS_URLLABEL_H_
+//vim: ts=8
+// File : class_urllabel.h
+// Creation date : Thu Feb 18 1:28:23 CEST 2001 by Krzysztof Godlewski
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Krzysztof Godlewski
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+
+#include "class_label.h"
+#include "object_macros.h"
+
+class KviKvsObject_urlabel : public KviKvsObject_label
+{
+public:
+ KVSO_DECLARE_OBJECT(KviKvsObject_urlabel)
+public:
+ QWidget * widget() { return (QWidget *)object(); };
+protected:
+ virtual bool eventFilter(QObject *, QEvent *);
+
+ bool functionsetUrl(KviKvsObjectFunctionCall *c);
+ bool functionsetAction(KviKvsObjectFunctionCall *c);
+ bool functionurl(KviKvsObjectFunctionCall *c);
+ bool functionaction(KviKvsObjectFunctionCall *c);
+ bool functionsetText(KviKvsObjectFunctionCall *c);
+ bool functionsetCursorChange(KviKvsObjectFunctionCall *c);
+ bool functioncursorChange(KviKvsObjectFunctionCall *c);
+ bool functionsetUseSingleClick(KviKvsObjectFunctionCall *c);
+ bool functionuseSingleClick(KviKvsObjectFunctionCall *c);
+
+ QString m_url;
+ QString m_action;
+
+ QColor m_normalClr;
+ QColor m_enterClr;
+ QColor m_activeClr;
+
+ bool m_changeCursor;
+ bool m_useSingleClick;
+
+ bool m_lastClickWasDbl;
+
+};
+
+#endif // !_CLASS_URLLABEL_H_
diff --git a/src/modules/objects/class_vbox.cpp b/src/modules/objects/class_vbox.cpp
new file mode 100644
index 00000000..477a5b69
--- /dev/null
+++ b/src/modules/objects/class_vbox.cpp
@@ -0,0 +1,128 @@
+//
+// File : class_vbox.cpp
+// Creation date : Wed Mar 01 2005 23:00:01 by Alessandro Carbone & Tonino Imbesi
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002-2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+#define _KVI_DEBUG_CHECK_RANGE_
+#include "kvi_debug.h"
+
+#include "kvi_locale.h"
+
+#include "class_vbox.h"
+
+/*
+ @doc: vbox
+ @keyterms:
+ vbox object class, child widgets
+ @title:
+ vbox class
+ @type:
+ class
+ @short:
+ Manages child widget vertical geometry
+ @inherits:
+ [class]object[/class]
+ @description:
+ The vbox class widget provides vertical geometry management for its child widgets.
+ @functions:
+ !fn: $setSpacing(<spacing:int>)
+ Sets the default spacing of the widgets in pixels
+ !fn: $setMargin(<margin:int>)
+ Sets the dimension of the layout margin : the distance from the border to the outermost child widget edges.
+ !fn: $setStretchFactor(<widget:hobject>,<stretch:uint>)
+ Sets the stretch factor of widget to stretch.
+*/
+
+
+KVSO_BEGIN_REGISTERCLASS(KviKvsObject_vbox,"vbox","widget")
+ KVSO_REGISTER_HANDLER(KviKvsObject_vbox,"setMargin", functionsetMargin)
+ KVSO_REGISTER_HANDLER(KviKvsObject_vbox,"setSpacing", functionsetSpacing)
+ KVSO_REGISTER_HANDLER(KviKvsObject_vbox,"setStretchFactor", functionsetStretchFactor )
+KVSO_END_REGISTERCLASS(KviKvsObject_vbox)
+
+KVSO_BEGIN_CONSTRUCTOR(KviKvsObject_vbox,KviKvsObject_widget)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_vbox)
+
+
+KVSO_BEGIN_DESTRUCTOR(KviKvsObject_vbox)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_vbox)
+
+bool KviKvsObject_vbox::init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams)
+{
+ setObject(new KviTalVBox(parentScriptWidget()), true);
+ return true;
+}
+
+bool KviKvsObject_vbox::functionsetMargin(KviKvsObjectFunctionCall *c)
+{
+ kvs_int_t iMargin;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("margin",KVS_PT_INT,0,iMargin)
+ KVSO_PARAMETERS_END(c)
+ if (widget()) ((KviTalVBox *)widget())->setMargin(iMargin);
+ return true;
+}
+
+bool KviKvsObject_vbox::functionsetSpacing(KviKvsObjectFunctionCall *c)
+{
+ kvs_int_t iSpacing;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("spacing",KVS_PT_INT,0,iSpacing)
+ KVSO_PARAMETERS_END(c)
+ if (widget()) ((KviTalVBox *)widget())->setSpacing(iSpacing);
+ return true;
+}
+
+bool KviKvsObject_vbox::functionsetStretchFactor(KviKvsObjectFunctionCall *c)
+{
+ KviKvsObject * pObject;
+ kvs_hobject_t hObject;
+ kvs_uint_t uStretch;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("widget",KVS_PT_HOBJECT,0,hObject)
+ KVSO_PARAMETER("stretch",KVS_PT_UNSIGNEDINTEGER,0,uStretch)
+ KVSO_PARAMETERS_END(c)
+ pObject=KviKvsKernel::instance()->objectController()->lookupObject(hObject);
+ if(!widget())return true;
+ if (!pObject)
+ {
+ c->warning(__tr2qs("Widget parameter is not an object"));
+ return true;
+ }
+ if (!pObject->object())
+ {
+ c->warning(__tr2qs("Widget parameter is not a valid object"));
+ return true;
+ }
+ if(!pObject->object()->isWidgetType())
+ {
+ c->warning(__tr2qs("Can't add a non-widget object"));
+ return true;
+ }
+
+ if(((KviKvsObject_widget *)pObject)->widget()->parentWidget() != widget())
+ {
+ c->warning(__tr2qs("The widget must be a child of this vbox"));
+ return true;
+ }
+ ((KviTalVBox *)widget())->setStretchFactor(((QWidget *)(pObject->object())),uStretch);
+ return true;
+} \ No newline at end of file
diff --git a/src/modules/objects/class_vbox.h b/src/modules/objects/class_vbox.h
new file mode 100644
index 00000000..d6b9d1cf
--- /dev/null
+++ b/src/modules/objects/class_vbox.h
@@ -0,0 +1,45 @@
+#ifndef _CLASS_VBOX_H_
+#define _CLASS_VBOX_H_
+//
+// File : class_vbox.h
+// Creation date : Wed Mar 01 2005 23:00:01 by Alessandro Carbone & Tonino Imbesi
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002-2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+#include "kvi_string.h"
+
+#include "class_widget.h"
+#include "kvi_tal_vbox.h"
+#include "object_macros.h"
+
+class KviKvsObject_vbox : public KviKvsObject_widget
+{
+public:
+ KVSO_DECLARE_OBJECT(KviKvsObject_vbox)
+public:
+ QWidget * widget() { return (QWidget *)object(); };
+protected:
+ virtual bool init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams);
+ bool functionsetMargin(KviKvsObjectFunctionCall *c);
+ bool functionsetSpacing(KviKvsObjectFunctionCall *c);
+ bool functionsetStretchFactor(KviKvsObjectFunctionCall *c);
+
+};
+
+
+#endif //_CLASS_HBOX_H_
diff --git a/src/modules/objects/class_widget.cpp b/src/modules/objects/class_widget.cpp
new file mode 100644
index 00000000..d248c98b
--- /dev/null
+++ b/src/modules/objects/class_widget.cpp
@@ -0,0 +1,1745 @@
+//=============================================================================
+//
+// File : class_widget.cpp
+// Creation date : Mon Sep 11 16:35:32 CET 2000 by Krzysztof Godlewski
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_malloc.h"
+#include "kvi_debug.h"
+
+#include "kvi_error.h"
+#include "kvi_locale.h"
+#include "kvi_iconmanager.h"
+#include "kvi_window.h"
+#include "kvi_out.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_app.h"
+#include "kvi_string.h"
+#include <qcursor.h>
+#include <qiconset.h>
+#include <qcolor.h>
+#include <qlayout.h>
+#include <qbitmap.h>
+#include <qmetaobject.h>
+#include "class_widget.h"
+#include "class_pixmap.h"
+
+#ifdef COMPILE_USE_QT4
+ #include <QKeyEvent>
+ #include <QDesktopWidget>
+#else
+ #include <qwidgetlist.h>
+#endif
+
+#include <qwidget.h>
+#include <qtooltip.h>
+#include <qfont.h>
+#include <qvariant.h>
+
+// FIX ME: WFLAGS
+const char * const widgettypes_tbl[] = {
+ "TopLevel",
+ "Dialog",
+ "Popup",
+ "Desktop",
+ "Customize",
+ "Title",
+ "StaysOnTop",
+ "SysMenu",
+ "Minimize",
+ "Maximize",
+ "NoAutoErase"
+ };
+#ifdef COMPILE_USE_QT4
+const Qt::WidgetAttribute widgetattributes_cod[]= {
+ Qt::WA_OpaquePaintEvent,
+ Qt::WA_NoSystemBackground,
+ Qt::WA_PaintOnScreen,
+ Qt::WA_NoMousePropagation,
+};
+
+const char * const widgetattributes_tbl[] = {
+ "opaquePaintEvent",
+ "noSystemBackground",
+ "paintOnScreen",
+ "noMousePropagation",
+};
+#define widgetattributes_num (sizeof(widgetattributes_tbl) / sizeof(widgetattributes_tbl[0]))
+
+
+const Qt::WindowType widgettypes_cod[] = {
+#else
+const int widgettypes_cod[] = {
+#endif
+ Qt::WType_TopLevel,
+ Qt::WType_Dialog,
+ Qt::WType_Popup,
+ Qt::WType_Desktop,
+ Qt::WStyle_Customize,
+ Qt::WStyle_Title,
+ Qt::WStyle_StaysOnTop,
+ Qt::WStyle_SysMenu,
+ Qt::WStyle_Minimize,
+ Qt::WStyle_Maximize,
+ Qt::WNoAutoErase
+};
+
+
+#ifdef COMPILE_USE_QT4
+
+ #define QT_WIDGET_TABFOCUS Qt::TabFocus
+ #define QT_WIDGET_CLICKFOCUS Qt::ClickFocus
+ #define QT_WIDGET_STRONGFOCUS Qt::StrongFocus
+ #define QT_WIDGET_NOFOCUS Qt::NoFocus
+
+#else
+ #define QT_WIDGET_TABFOCUS QWidget::TabFocus
+ #define QT_WIDGET_CLICKFOCUS QWidget::ClickFocus
+ #define QT_WIDGET_STRONGFOCUS QWidget::StrongFocus
+ #define QT_WIDGET_NOFOCUS QWidget::NoFocus
+#endif
+
+
+#define widgettypes_num (sizeof(widgettypes_tbl) / sizeof(widgettypes_tbl[0]))
+
+/*
+ @doc: widget
+ @keyterms:
+ widget object class
+ @title:
+ widget class
+ @type:
+ class
+ @short:
+ Base class for all widgets
+ @inherits:
+ [class]object[/class]
+ @description:
+ This object class is the rappresentation of a widget.
+ All the other widget-type classes inherit from this one.
+ @functions:
+ !fn: $show()
+ Shows this widget and the children.
+ See also [classfnc]$hide[/classfnc]() and [classfnc]$isVisible[/classfnc].
+ !fn: $hide()
+ Hides this widget (and conseguently all the children).
+ See also [classfnc]$show[/classfnc]() and [classfnc]$isVisible[/classfnc].
+ !fn: $repaint(<bool erase>)
+ Repaints the widget directly by calling [classfnc]$paintEvent[/classfnc]() immediately.[br]
+ If erase is TRUE, erases the widget before the $paintEvent() call.
+ !fn: $x()
+ Returns the x coordinate of the upper-left corner
+ of this widget relative to the parent widget,
+ or to the desktop if this widget is a toplevel one.
+ !fn: $y()
+ Returns the y coordinate of the uspper-left corner
+ of this widget relative to the parent widget,
+ or to the desktop if this widget is a toplevel one.
+ !fn: $width()
+ Returns the width of this widget in pixels.
+ !fn: $height()
+ Returns the height of this widget in pixels.
+ !fn: $geometry()
+ Returns the widget geometry in this form:[br]
+ x, y, width, height.
+ !fn: $setGeometry(<x_or_array>,[<y>,<width>,<heigth>])
+ Sets the geometry of this widget. <x> and <y> are relative
+ to the parent widget or to the desktop (if this widget is
+ a toplevel one). All the parameters are in pixels.
+ !fn: $setMinimumWidth(<value>)
+ Sets the minimum width of this widget to <value>.
+ The user will not be able to resize the widget to a smaller
+ value. This value is also used by the [class:layout]layout class[/class].
+ !fn: $setMinimumHeight(<value>)
+ Sets the minimum height of this widget to <value>.
+ The user will not be able to resize the widget to a smaller
+ value. This value is also used by the [class:layout]layout class[/class].
+ !fn: $setMaximumWidth(<value>)
+ Sets the maximum width of this widget to <value>.
+ The user will not be able to resize the widget to a bigger
+ value. This value is also used by the [class:layout]layout class[/class].
+ !fn: $setMaximumHeight(<value>)
+ Sets the maximum height of this widget to <value>.
+ The user will not be able to resize the widget to a bigger
+ value. This value is also used by the [class:layout]layout class[/class].
+ !fn: $move(<x_or_array>[,<y>])
+ Moves this widget to the coordinate <x> and <y> relative to its
+ parent widget (or the desktop if this widget is a toplevel one).
+ This is equivalent to [classfnc]$setGeometry[/classfnc](<x>,<y>,
+ [classfnc]$width[/classfnc](),[classfnc]$height[/classfnc]()).
+ !fn: $resize(<w_or_array>,[height])
+ Changes the widget's width to <width> and height to <height>.
+ See also [classfnc]$setGeometry[/classfnc]().
+ !fn: $isEnabled()
+ Returns '1' if the widget is enabled , '0' otherwise.
+ See also [classfnc:widget]$setEnabled[/classfnc]().
+ !fn: $setEnabled(<bool>)
+ Sets the widget state to enabled or disabled if <bool> is 1 or 0 respectively.
+ A disabled widget does not receive keyboard nor mouse input.
+ !fn: $setCaption(<text>)
+ Sets the caption of this widget to <text>.
+ This is meaningful for toplevel widgets only.
+ !fn: $setToolTip(<tooltip_text>)
+ Set the tooltip of this widget; the text can contain HTML formatting.
+ !fn: $window.caption()
+ Returns the caption text of this widget.
+ !fn: $isTopLevel()
+ Returns '1' if this widget is a toplevel (parentless) one,
+ '0' otherwise.
+ !fn: $isVisible()
+ Returns '1' if this widget is currently visible (read: is managed
+ by the window manager and displayed by the X server; the widget
+ may be hidden behind other widgets). If the widget is not visible
+ this function returns '0'.
+ See also [classfnc]$show[/classfnc]() and [classfnc]$hide[/classfnc]().
+ !fn: $raise()
+ Moves this widget to the top of the stack of the widgets relative
+ to its parent. See also [classfnc]$lower[/classfnc].
+ !fn: $lower()
+ Moves this widget to the bottom of the stack of the widgets relative
+ to its parent. See also [classfnc]$raise[/classfnc]
+ !fn: $hasFocus()
+ Returns '1' if this widget has the keyboard focus.
+ See also [classfnc]$setFocus[/classfnc].
+ !fn: $setFocus()
+ Sets this widget to be the one that receives keyboard events.
+ See also [classfnc]$hasFocus[/classfnc]
+ !fn: $parentWidget()
+ Returns the object id of the parent widget, or '0' if this
+ widget is a toplevel one.
+ !fn: $backgroundColor()
+ Returns the background color of this widget in hexadecimal
+ html-like format. For example , for a black bacground you will get
+ the string "000000" , for a red one , "FF0000", for a white one
+ "FFFFFF". See also [classfnc]$setBackgroundColor[/classfnc]()
+ !fn: $setBackgroundColor(<rgb(hex string)_array(red:integer,green:integer,blue_integer)_or_red>,[geen:integer],[blue:integer])
+ Sets the background color of this widget to <rgb_value>:valid values are:
+ - hex string: must be a string with 6 hexadecimal digits (like the ones used to
+ specify colors in html pages). The first two digits specify
+ the RED component, the third and fourth digit specify the GREEN component
+ and the last two specify the BLUE component.
+ For example "FFFF00" means full red, full green and no blue that gives
+ a yellow color, "808000" designates a brown color (dark yellow),
+ "A000A0" is a kind of violet.
+ - array(red:integer,green:integer,blue:integer)
+ - red:integer,green:integer,blue:integer.
+ See also [classfnc]$foregroundColor[/classfnc].
+ !fn: $setForegroundColor(<rgb(hex string)_array(red:integer,green:integer,blue_integer)_or_red>,[geen:integer],[blue:integer])
+ Sets the foreground color of this widget to <rgb_value>:valid values are:
+ - hex string: must be a string with 6 hexadecimal digits (like the ones used to
+ specify colors in html pages). The first two digits specify
+ the RED component, the third and fourth digit specify the GREEN component
+ and the last two specify the BLUE component.
+ For example "FFFF00" means full red, full green and no blue that gives
+ a yellow color, "808000" designates a brown color (dark yellow),
+ "A000A0" is a kind of violet.
+ - array(red:integer,green:integer,blue:integer)
+ - red:integer,green:integer,blue:integer.
+ See also [classfnc]$foregroundColor[/classfnc].
+ !fn: $foregroundColor()
+ Returns the foreground color of this widget in hexadecimal
+ html-like format.
+ See also [classfnc]$setForegroundColor[/classfnc].
+ !fn: $setMouseTracking(<bool>)
+ Enables or disables the mouse tracking if <bool> is '1' or '0' respectively.
+ When mouse tracking is enabled you will receive mouse move events
+ even if no button is pressed, otherwise you will receive it only
+ when a mouse button is being pressed (so after a mousePressEvent).
+ !fn: $mousePressEvent(<button>,<x>,<y>)
+ This function is called when a mouse button is pressed while
+ the cursor is in this widget. <button> is 0 if the pressed button
+ is the left one, 1 if the button is the right one and 2 if it is the middle one.
+ The <x> and <y> coordinates are relative to this widget upper-left corner
+ and are expressed in pixels.
+ If you call "[cmd]setreturn[/cmd] 1" you will stop the internal processing
+ of this event. The default implementation does nothing.
+ !fn: $mouseReleaseEvent(<button>,<x>,<y>)
+ This function is called when a mouse button is released while
+ the cursor is in this widget. <button> is 0 if the released button
+ is the left one, 1 if the button is the right one and 2 if it is the middle one.
+ The <x> and <y> coordinates are relative to this widget upper-left corner
+ and are expressed in pixels.
+ If you call "[cmd]setreturn[/cmd] 1" you will stop the internal processing
+ of this event. The default implementation does nothing.
+ !fn: $mouseDoubleClickEvent(<button>,<x>,<y>)
+ This function is called when a mouse button is double clicked while
+ the cursor is in this widget. <button> is 0 if the double clicked button
+ is the left one, 1 if the button is the right one and 2 if it is the middle one.
+ The <x> and <y> coordinates are relative to this widget upper-left corner
+ and are expressed in pixels.
+ If you call "[cmd]setreturn[/cmd] 1" you will stop the internal processing
+ of this event. The default implementation does nothing.
+ !fn: $mouseMoveEvent(<button>,<x>,<y>)
+ This function is called when the mouse cursor moves inside this widget.
+ <button> is 0 if the pressed button
+ is the left one, 1 if the button is the right one and 2 if it is the middle one.
+ The special value of -1 indicates that no button is being pressed.
+ The <x> and <y> coordinates are relative to this widget upper-left corner
+ and are expressed in pixels.
+ Normally you will receive this event only if a mouse button is being pressed
+ while moving. If you want to receive it also when the mouse buttons are not
+ pressed, call [classfnc]$setMouseTracking[/classfnc]().
+ If you call "[cmd]return[/cmd]$true" you will stop the internal processing
+ of this event. The default implementation does nothing.
+ !fn: $focusInEvent()
+ This function is called when this widget gains keyboard focus.
+ If you call "[cmd]return[/cmd] $true" you will stop the internal processing
+ of this event. The default implementation does nothing.
+ !fn: $focusOutEvent()
+ This function is called when this widget looses keyboard focus.
+ If you call "[cmd]return[/cmd] $true" you will stop the internal processing
+ of this event. The default implementation does nothing.
+ !fn: $mouseLeaveEvent()
+ This function is called when the mouse leaves this widget.
+ If you call "[cmd]return[/cmd] $true" you will stop the internal processing
+ of this event. The default implementation does nothing.
+ !fn: $mouseEnterEvent()
+ This function is called when the mouse enters this widget.
+ If you call "[cmd]return[/cmd] $true" you will stop the internal processing
+ of this event. The default implementation does nothing.
+ !fn: $showEvent()
+ This function is called when this widget is being shown.
+ If you call "[cmd]return[/cmd] $true" you will stop the internal processing
+ of this event. The default implementation does nothing.
+ !fn: $hideEvent()
+ This function is called when this widget is being hidden.
+ If you call "[cmd]return[/cmd] $true" you will stop the internal processing
+ of this event. The default implementation does nothing.
+ !fn: $closeEvent()
+ This function is called when this widget is going to be closed.
+ If you call "[cmd]return[/cmd] $true" you will ignore the close event.
+ The default implementation does nothing.
+ !fn: $resizeEvent()
+ This function is called immediately after this widget has been resized.
+ If you call "[cmd]return[/cmd] $true" you will stop the internal processing
+ of this event. The default implementation does nothing.
+ !fn: $moveEvent()
+ This function is called immediately after this widget has been moved.
+ If you call "[cmd]return[/cmd] $true" you will stop the internal processing
+ of this event. The default implementation does nothing.
+ !fn: <tip:string> $maybeTipEvent(<x_tip_pos:integer>,<y_tip_pos:integer>)[QT4 only]
+ This event handler is called when a eventualy tip is going to be show.
+ You can be reimplement this event and set a dynamic tool tip by using "[cmd]return[/cmd] <tooltip_string>".
+ If a tooltip has setted with [classfnc]$setTooltip[/classfnc] the dynamic tooltip will be ignored.
+ The default implementation does nothing.
+ !fn: $paintEvent()
+ This event handler can be reimplemented to repaint all or part of the widget.
+ It's needed by the Painter class.
+ It's very useful for drawing flicker free animations or low level special graphic effects.
+ If you call "[cmd]return[/cmd] $true" you will stop the internal processing
+ of this event.
+ The default implementation does nothing.
+ !fn: $setIcon(<image_id>)
+ Sets the icon for this widget. This is meaningful only for toplevel widgets.
+ See the [doc:image_id]image identifier[/doc] documentation for the explaination
+ of the <image_id> parameter.
+ !fn: $setBackgroundImage(<image_id>)
+ Sets the background image for this widget.
+ See the [doc:image_id]image identifier[/doc] documentation for the explaination
+ of the <image_id> parameter.
+ For some kind of widgets, setting a background pixmap may have no effect or
+ have strange results. Experiment with it.
+ To unset the background image call [classfnc]$setBackgroundColor[/classfnc]
+ !fn: $setFont(<size>,<family>,<style>)[br]
+ Set the font's size, family and stile, valid flag for style are:[br]
+ [pre]
+ italic [br]
+ bold [br]
+ underline [br]
+ overline [br]
+ strikeout [br]
+ fixedpitch [br]
+ [/pre]
+ !fn: $setWFlags(<flag1>, <flag2>, ...)
+ This function sets widget flags, given as parameters.
+ Valid flags are:
+ [pre]
+ TopLevel - indicates that this widget is a top-level widget[br]
+ Dialog - indicates that this widget is a top-level window that should be decorated as a dialog[br]
+ Desktop - indicates that this widget is the desktop[br]
+ Popup - indicates that this widget is a popup top-level window[br]
+ NoAutoErase - indicates that this widget paints all its pixels. Updating, resizing, scrolling and focus changes should therefore not erase the widget.
+ Customize - let's the user to customize the style of the widget.[br]
+ [br]
+ Valid parameter for a customized widget are:[br]
+ Title - gives the window a title bar[br]
+ StaysOnTop - window stays on top [br]
+ SysMenu - add a windows system menu[br]
+ Minimize - add a minimize button for the sysmenu style[br]
+ Maximize - add a maximixe button for the sysmenu style[br]
+ [/pre]
+ !fn: $centerToScreen()
+ Centers the window on the screen (useful only for toplevel widgets).[br]
+ The best place to call this function is in $showEvent()
+ !fn: $setFocusPolicy(<key focus>)
+ Sets the way the widget accepts keyboard focus.[br]
+ Valid parameters are:
+ [pre]
+ - TabFocus; (widget accepts keyboard focus by tabbing)[br]
+ - ClickFocus; (widget accepts keyboard focus by clicking)[br]
+ - StrongFocus; (widget accepts both tabbing/clicking)[br]
+ - No Focus; (widget does not accept focus at all; this is the default value)[br]
+ [/pre]
+ !fn: $keyPressEvent(<key>)
+ If widget accepts keyboard focus (see [classfnc]$setFocusPolicy[/classfnc] ) this function handles for keys;
+ In its argument the key pressed.[br]
+ Special keys are:
+ [pre]
+ - Return [br]
+ - Enter [br]
+ - Down (cursor arrow down) [br]
+ - Up (cursor arrow up) [br]
+ - Left (cursor arrow left) [br]
+ - Right (cursor arrow right) [br]
+ - Shift [br]
+ - Ctrl [br]
+ - Alt [br]
+ - CapsLock [br]
+ - Backspace [br]
+ - Del [br]
+ - Esc [br]
+ - 0 [br]
+ - 1 [br]
+ - 2 [br]
+ - 3 [br]
+ - 4 [br]
+ - 5 [br]
+ - 6 [br]
+ - 7 [br]
+ - 8 [br]
+ - 9 [br]
+ - + [br]
+ - - [br]
+ - * [br]
+ - / [br]
+ - ( [br]
+ - ) [br]
+ - = [br]
+ - . [br]
+ - ^ [br]
+
+ [/pre]
+ !fn: $mapFromGlobal(<x>,<y>)
+ Translates the global screen coordinate pos to widget coordinates.
+ !fn: $mapToGlobal(<x>,<y>)
+ Translates widget coordinates into the global screen coordinate pos.
+ !fn: integer $globalCursorX()
+ Return the x coordinate of mouse pointer global position.
+ !fn: integer $globalCursorY()
+ Return the y coordinate of the mo>use pointer global position.
+ @examples:
+ [example]
+ %Widget = $new(widget)
+ # This is the main container for other elements.
+
+ %Widget->$setCaption("This is the widget title")
+
+ %Widget->$setGeometry(100,200,170,290)
+ # 100 and 200 are distance (pixel) from the left and the top of father widget (in this case the KVIrc window)
+ # 300 and 400 are the weight and the height of the widget
+
+ %Widget->%label = $new(label,%Widget)
+ %Widget->%label->$setText("This is a text label")
+ %Widget->%label->$setGeometry(10,10,150,20)
+
+ %Widget->%lineedit = $new(lineedit,%Widget)
+ %Widget->%lineedit->$setText("This is a lineedit")
+ %Widget->%lineedit->$setGeometry(10,40,150,20)
+
+ %Widget->%multilineedit = $new(multilineedit,%Widget)
+ %Widget->%multilineedit->$setText("This is a multilineedit")
+ %Widget->%multilineedit->$setGeometry(10,70,150,40)
+
+ %Widget->%checkbox = $new(checkbox,%Widget)
+ %Widget->%checkbox->$setText("This is a checkbox")
+ %Widget->%checkbox->$setGeometry(10,120,150,20)
+
+ %Widget->%combobox = $new(combobox,%Widget)
+ %Widget->%combobox->$setGeometry(10,150,150,20)
+ %Widget->%combobox->$insertItem("This is a combobox")
+ %Widget->%combobox->$insertItem("This is a combobox's item")
+
+ %Widget->%listbox = $new(listbox,%Widget)
+ %Widget->%listbox->$setGeometry(10,180,150,40)
+ %Widget->%listbox->$insertItem("This is another item")
+ %Widget->%listbox->$insertItem("This is a listbox's item")
+ %Widget->%listbox->$insertItem("This is a listbox")
+
+ %Widget->%radiobutton = $new(radiobutton,%Widget)
+ %Widget->%radiobutton->$setGeometry(10,230,150,20)
+ %Widget->%radiobutton->$setText("This is a radiobutton")
+
+ %Widget->%button = $new(button, %Widget)
+ %Widget->%button->$setText("Close me")
+ %Widget->%button->$setGeometry(10,260,150,20)
+
+ %Widget->$show()
+ # This shows the widget
+
+ privateimpl(%Widget->%button, mousePressEvent) {
+ delete %Widget
+ # This closes the widget automatically
+ }
+ # privateimpl is triggered when user press the button.
+ # To do that, widget must be a global variable.
+ [/example]
+
+*/
+
+
+
+
+//
+// If you never call c->error() , c->warning() (your function never fails)
+// and never call a function that can call c->error() or c->warning()
+// you can avoid ENTER_STACK_FRAME and c->leaveStackFrame()
+// Just return true.
+// c->error() should be called only in really critical situations
+// (we have to define better "critical situation")
+// if possible , leave the things go after just a c->warning()
+//
+
+ // widget() will be never 0 in THIS class
+ // but in derived classes WILL be
+ // ... now that I think about it , it
+ // may happen that widget() will be zero here too:
+ // If the Qt "physical" widget gets destroyed
+ // by some external factor (for example when children
+ // of a wrapper widget destroyed by KVIrc).
+ //
+ // as a convention:
+ // if widget() can be 0 in a class
+ // the user must have a function to check it
+ // (sth as object::$hasObject() could do the trick)
+ // obviously this will happen only in well defined cases
+ // as in a qtwrapper not yet wrapped or failed to wrap (so
+ // qtwrapper::$wrap() returned '0' for example)
+ // or after the widget has been destroyed...
+ // if widget() is 0 , the functions perform no actions
+ // return no errors and results that have to be assumed
+ // as invalid (this allows the minimum overhead: if widget()
+
+//=============================================================================================================
+
+
+
+KVSO_BEGIN_REGISTERCLASS(KviKvsObject_widget,"widget","object")
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"reparent",function_reparent)
+ // apparence
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"show",function_show)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"hide",function_hide)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"repaint",function_repaint)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"isTopLevel",function_isTopLevel)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"isVisible",function_isVisible)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"raise",function_raise)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"lower",function_lower)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"setEnabled",function_setEnabled)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"isEnabled",function_isEnabled)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"setMouseTracking",function_setMouseTracking)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"setCaption",function_setCaption)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"caption",function_caption)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"hasFocus",function_hasFocus)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"setFocus",function_setFocus)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"setToolTip",function_setToolTip)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"setWFlags",function_setWFlags)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"setIcon",function_setIcon)
+ // fonts
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"fontDescent",function_fontDescent)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"fontAscent",function_fontAscent)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"fontMetricsWidth",function_fontMetricsWidth)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"fontMetricsHeight",function_fontMetricsHeight)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"setFont",function_setFont)
+ // geometry
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"screenResolution",function_screenResolution)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"centerToScreen",function_centerToScreen)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"geometry",function_geometry)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"setGeometry",function_setGeometry)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"mapToGlobal",function_mapToGlobal)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"mapFromGlobal",function_mapFromGlobal)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"y",function_y)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"x",function_x)
+
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"globalCursorX",function_globalCursorX)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"globalCursorY",function_globalCursorY)
+
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"width",function_width)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"height",function_height)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"setMinimumWidth",function_setMinimumWidth)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"setMinimumHeight",function_setMinimumHeight)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"setMaximumWidth",function_setMaximumWidth)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"setMaximumHeight",function_setMaximumHeight)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"move",function_move)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"sizeHint",function_sizeHint)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"resize",function_resize)
+
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"setFocusPolicy",function_setFocusPolicy)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"addWidgetToWrappedLayout",function_addWidgetToWrappedLayout)
+
+ // colors and image
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"setForegroundColor",function_setPaletteForeground)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"setBackgroundColor",function_setBackgroundColor)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"setBackgroundImage",function_setBackgroundImage)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"backgroundColor",function_backgroundColor)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"foregroundColor",function_foregroundColor)
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"setMask",function_setMask)
+
+ // QT4 only
+#ifdef COMPILE_USE_QT4
+ KVSO_REGISTER_HANDLER(KviKvsObject_widget,"setAttribute",function_setAttribute)
+#endif
+
+ // events
+ KVSO_REGISTER_STANDARD_NOTHINGRETURN_HANDLER(KviKvsObject_widget,"mousePressEvent")
+ KVSO_REGISTER_STANDARD_NOTHINGRETURN_HANDLER(KviKvsObject_widget,"mouseReleaseEvent")
+ KVSO_REGISTER_STANDARD_NOTHINGRETURN_HANDLER(KviKvsObject_widget,"mouseDoubleClickEvent")
+ KVSO_REGISTER_STANDARD_NOTHINGRETURN_HANDLER(KviKvsObject_widget,"mouseMoveEvent")
+ KVSO_REGISTER_STANDARD_NOTHINGRETURN_HANDLER(KviKvsObject_widget,"focusInEvent")
+ KVSO_REGISTER_STANDARD_NOTHINGRETURN_HANDLER(KviKvsObject_widget,"focusOutEvent")
+ KVSO_REGISTER_STANDARD_NOTHINGRETURN_HANDLER(KviKvsObject_widget,"mouseLeaveEvent")
+ KVSO_REGISTER_STANDARD_NOTHINGRETURN_HANDLER(KviKvsObject_widget,"mouseEnterEvent")
+ KVSO_REGISTER_STANDARD_NOTHINGRETURN_HANDLER(KviKvsObject_widget,"showEvent")
+ KVSO_REGISTER_STANDARD_NOTHINGRETURN_HANDLER(KviKvsObject_widget,"hideEvent")
+ KVSO_REGISTER_STANDARD_NOTHINGRETURN_HANDLER(KviKvsObject_widget,"closeEvent")
+ KVSO_REGISTER_STANDARD_NOTHINGRETURN_HANDLER(KviKvsObject_widget,"resizeEvent")
+ KVSO_REGISTER_STANDARD_NOTHINGRETURN_HANDLER(KviKvsObject_widget,"moveEvent")
+ KVSO_REGISTER_STANDARD_NOTHINGRETURN_HANDLER(KviKvsObject_widget,"paintEvent")
+ KVSO_REGISTER_STANDARD_NOTHINGRETURN_HANDLER(KviKvsObject_widget,"keyPressEvent")
+#ifdef COMPILE_USE_QT4
+ KVSO_REGISTER_STANDARD_NOTHINGRETURN_HANDLER(KviKvsObject_widget,"maybeTipEvent")
+#endif
+
+
+KVSO_END_REGISTERCLASS(KviKvsObject_widget)
+
+
+KVSO_BEGIN_CONSTRUCTOR(KviKvsObject_widget,KviKvsObject)
+KVSO_END_CONSTRUCTOR(KviKvsObject_widget)
+
+KVSO_BEGIN_DESTRUCTOR(KviKvsObject_widget)
+ emit aboutToDie();
+KVSO_END_CONSTRUCTOR(KviKvsObject_widget)
+
+bool KviKvsObject_widget::init(KviKvsRunTimeContext * pContext,KviKvsVariantList * pParams)
+{
+ setObject(new QWidget(parentScriptWidget(),getName()),true);
+ return true;
+}
+
+bool KviKvsObject_widget::eventFilter(QObject *o,QEvent *e)
+{
+ if(o == object())
+ {
+ bool ret=false;
+ int aparam;
+ bool brokenhandler=false;
+ KviKvsVariant *retv=new KviKvsVariant(ret);
+
+ switch(e->type())
+ {
+ #ifdef COMPILE_USE_QT4
+ case QEvent::ToolTip:
+ {
+ QHelpEvent *helpEvent = static_cast<QHelpEvent *>(e);
+ QPoint point=helpEvent->pos();
+ QString szTooltip;
+ KviKvsVariant *tipret=new KviKvsVariant(szTooltip);
+ KviKvsVariantList params(new KviKvsVariant((kvs_int_t)point.x()),new KviKvsVariant((kvs_int_t)point.y()));
+ callFunction(this,"maybeTipEvent",tipret,&params);
+ tipret->asString(szTooltip);
+ QToolTip::showText(helpEvent->globalPos(),szTooltip);
+ break;
+ }
+ #endif
+ case QEvent::Paint:
+ {
+ QRect rect=((QPaintEvent *)e)->rect();
+ KviKvsVariantList params(new KviKvsVariant((kvs_int_t)rect.x()),new KviKvsVariant((kvs_int_t)rect.y()),new KviKvsVariant((kvs_int_t)rect.width()),new KviKvsVariant((kvs_int_t)rect.height()));
+ callFunction(this,"paintEvent",retv,&params);
+ break;
+ }
+
+ case QEvent::KeyPress:
+ {
+ QString tmp="";
+ switch(((QKeyEvent *)e)->key())
+ {
+ case Qt::Key_Return:
+ tmp="Return";
+ break;
+ case Qt::Key_Down:
+ tmp="Down";
+ break;
+ case Qt::Key_Up:
+ tmp="Up";
+ break;
+ case Qt::Key_Left:
+ tmp="Left";
+ break;
+ case Qt::Key_Right:
+ tmp="Right";
+ break;
+ case Qt::Key_Shift:
+ tmp="Shift";
+ break;
+ case Qt::Key_Control:
+ tmp="Ctrl";
+ break;
+ case Qt::Key_Alt:
+ tmp="Alt";
+ break;
+ case Qt::Key_CapsLock:
+ tmp="CapsLock";
+ break;
+ case Qt::Key_Backspace:
+ tmp="Backspace";
+ break;
+ case Qt::Key_Delete:
+ tmp="Del";
+ break;
+
+ case Qt::Key_Enter:
+ tmp="Enter";
+ break;
+ case Qt::Key_Escape:
+ tmp="Esc";
+ break;
+ case Qt::Key_0:
+ tmp="0";
+ case Qt::Key_1:
+ tmp="1";
+ break;
+ case Qt::Key_2:
+ tmp="2";
+ break;
+ case Qt::Key_3:
+ tmp="3";
+ break;
+ case Qt::Key_4:
+ tmp="4";
+ break;
+ case Qt::Key_5:
+ tmp="5";
+ break;
+ case Qt::Key_6:
+ tmp="6";
+ break;
+ case Qt::Key_7:
+ tmp="7";
+ break;
+ case Qt::Key_8:
+ tmp="8";
+ break;
+ case Qt::Key_9:
+ tmp="9";
+ break;
+ case Qt::Key_Plus:
+ tmp="+";
+ break;
+ case Qt::Key_Minus:
+ tmp="-";
+ break;
+ case Qt::Key_Slash:
+ tmp="/";
+ break;
+ case Qt::Key_Asterisk:
+ tmp="*";
+ break;
+ case Qt::Key_Period:
+ tmp=".";
+ break;
+ case Qt::Key_ParenLeft:
+ tmp="(";
+ break;
+ case Qt::Key_ParenRight:
+ tmp=")";
+ break;
+ case Qt::Key_Equal:
+ tmp="=";
+ break;
+ case Qt::Key_AsciiCircum:
+ tmp="^";
+ break;
+ default:
+ if (!((QKeyEvent *)e)->text().isEmpty()) tmp = ((QKeyEvent *)e)->text();
+ }
+
+ KviKvsVariantList params(new KviKvsVariant(tmp));
+ callFunction(this,"keyPressEvent",0,&params);
+ }
+ break;
+ case QEvent::MouseButtonPress:
+ if(((QMouseEvent *)e)->button() & Qt::LeftButton)aparam = 0;
+ else {
+ if(((QMouseEvent *)e)->button() & Qt::RightButton)aparam = 1;
+ else aparam = 2;
+ }
+ if(!callFunction(this,"mousePressEvent",retv,new KviKvsVariantList(new KviKvsVariant((kvs_int_t)aparam),new KviKvsVariant((kvs_int_t)((QMouseEvent *)e)->pos().x()),new KviKvsVariant((kvs_int_t)((QMouseEvent *)e)->pos().y())
+ ))) brokenhandler = true; // ignore results of a broken event handler
+ break;
+ case QEvent::MouseButtonRelease:
+ if(((QMouseEvent *)e)->button() & Qt::LeftButton)aparam = 0;
+ else {
+ if(((QMouseEvent *)e)->button() & Qt::RightButton)aparam = 1;
+ else aparam = 2;
+ }
+ if(!callFunction(this,"mouseReleaseEvent",retv,new KviKvsVariantList(new KviKvsVariant((kvs_int_t)aparam),new KviKvsVariant((kvs_int_t)((QMouseEvent *)e)->pos().x()),new KviKvsVariant((kvs_int_t)((QMouseEvent *)e)->pos().y())
+ ))) brokenhandler = true; // ignore results of a broken event handler
+ break;
+ case QEvent::MouseButtonDblClick:
+ if(( (QMouseEvent *)e)->button() & Qt::LeftButton)aparam = 0;
+ else {
+ if(((QMouseEvent *)e)->button() & Qt::RightButton)aparam = 1;
+ else aparam = 2;
+ }
+ if(!callFunction(this,"mouseDoubleClickEvent",retv,new KviKvsVariantList(new KviKvsVariant((kvs_int_t)aparam),new KviKvsVariant((kvs_int_t)((QMouseEvent *)e)->pos().x()),new KviKvsVariant((kvs_int_t)((QMouseEvent *)e)->pos().y())
+ ))) brokenhandler = true; // ignore results of a broken event handler
+
+ break;
+ case QEvent::MouseMove:
+ if( (((QMouseEvent *)e)->state()) & Qt::LeftButton) aparam = 0;
+ else
+ {
+ if(((QMouseEvent *)e)->state() & Qt::RightButton)aparam = 1;
+ else
+ {
+ if(((QMouseEvent *)e)->state() & Qt::MidButton)aparam = 2;
+ else aparam = -1;
+ }
+ }
+ if(!callFunction(this,"mouseMoveEvent",retv,new KviKvsVariantList(new KviKvsVariant((kvs_int_t)aparam),new KviKvsVariant((kvs_int_t)((QMouseEvent *)e)->pos().x()),new KviKvsVariant((kvs_int_t)((QMouseEvent *)e)->pos().y())
+ ))) brokenhandler = true; // ignore results of a broken event handler
+ break;
+ case QEvent::FocusIn:
+ if(!callFunction(this,"focusInEvent",retv,0))brokenhandler = true;
+ break;
+ case QEvent::FocusOut:
+ if(!callFunction(this,"focusOutEvent",retv,0))brokenhandler = true;
+ break;
+ case QEvent::Resize:
+ if(!callFunction(this,"resizeEvent",retv,0))brokenhandler = true;
+ break;
+ case QEvent::Move:
+ if(!callFunction(this,"moveEvent",retv,0))brokenhandler = true;
+ break;
+ case QEvent::Close:
+ if(!callFunction(this,"closeEvent",retv,0))brokenhandler = true;
+ break;
+ case QEvent::Enter:
+ if(!callFunction(this,"mouseEnterEvent",retv,0))brokenhandler = true;
+ break;
+ case QEvent::Leave:
+ if(!callFunction(this,"mouseLeaveEvent",retv,0))brokenhandler = true;
+ break;
+ case QEvent::Show:
+ if(!callFunction(this,"showEvent",retv,0))brokenhandler = true;
+ break;
+ case QEvent::Hide:
+ if(!callFunction(this,"hideEvent",retv,0))ret =false;
+ break;
+ default:
+ return KviKvsObject::eventFilter(o,e);
+ break;
+
+ }
+ if (!brokenhandler) ret=retv->asBoolean();
+ delete retv;
+ return ret;
+ /*
+ if(ret.length() == 1)
+ {
+ if(KviQString::equalCI("1",ret))return true;
+ }
+ */
+ }
+
+ return KviKvsObject::eventFilter(o,e);
+}
+
+
+bool KviKvsObject_widget::function_show(KviKvsObjectFunctionCall *c)
+{
+ if(!widget())return true; // should we warn here ?
+ widget()->show();
+ return true;
+}
+
+bool KviKvsObject_widget::function_setEnabled(KviKvsObjectFunctionCall *c)
+{
+ bool bEnabled;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bEnabled",KVS_PT_BOOL,0,bEnabled)
+ KVSO_PARAMETERS_END(c)
+ if(!widget())return true;
+ widget()->setEnabled(bEnabled);
+ return true;
+}
+bool KviKvsObject_widget::function_isEnabled(KviKvsObjectFunctionCall *c)
+{
+ if(!widget()) return true;
+ c->returnValue()->setBoolean(widget()->isEnabled());
+ return true;
+}
+bool KviKvsObject_widget::function_fontDescent(KviKvsObjectFunctionCall * c)
+{
+ if(!widget()) return true;
+ QFontMetrics fm = widget()->fontMetrics();
+ int d = fm.descent();
+ c->returnValue()->setInteger(d);
+ return true;
+}
+
+bool KviKvsObject_widget::function_fontAscent(KviKvsObjectFunctionCall * c)
+{
+ if(!widget()) return true;
+ QFontMetrics fm = widget()->fontMetrics();
+ int d = fm.ascent();
+ c->returnValue()->setInteger(d);
+ return true;
+
+}
+
+bool KviKvsObject_widget::function_repaint(KviKvsObjectFunctionCall * c)
+{
+ bool bEnabled;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bEnabled",KVS_PT_BOOL,0,bEnabled)
+ KVSO_PARAMETERS_END(c)
+ if(!widget()) return true;
+ widget()->repaint(bEnabled);
+ return true;
+}
+
+bool KviKvsObject_widget::function_fontMetricsWidth(KviKvsObjectFunctionCall * c)
+{
+ QString m_szStr;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("string",KVS_PT_STRING,0,m_szStr)
+ KVSO_PARAMETERS_END(c)
+ if(!widget()) return true;
+// int fm = widget()->fontMetrics().width(m_szStr);
+ c->returnValue()->setInteger(widget()->fontMetrics().width(m_szStr));
+ return true;
+}
+
+bool KviKvsObject_widget::function_fontMetricsHeight(KviKvsObjectFunctionCall * c)
+{
+ if(!widget())return true;
+ int fm = widget()->fontMetrics().height();
+ c->returnValue()->setInteger(fm);
+ return true;
+}
+bool KviKvsObject_widget::function_screenResolution(KviKvsObjectFunctionCall * c)
+{
+ KviKvsArray * a = new KviKvsArray();
+ a->set(0,new KviKvsVariant((kvs_int_t)g_pApp->desktop()->width()));
+ a->set(1,new KviKvsVariant((kvs_int_t)g_pApp->desktop()->height()));
+ c->returnValue()->setArray(a);
+ return true;
+}
+
+bool KviKvsObject_widget::function_geometry(KviKvsObjectFunctionCall *c)
+{
+ QRect r = widget() ? widget()->geometry() : QRect(0,0,0,0);
+ KviKvsArray * a = new KviKvsArray();
+ a->set(0,new KviKvsVariant((kvs_int_t)r.x()));
+ a->set(1,new KviKvsVariant((kvs_int_t)r.y()));
+ a->set(2,new KviKvsVariant((kvs_int_t)r.width()));
+ a->set(3,new KviKvsVariant((kvs_int_t)r.height()));
+ c->returnValue()->setArray(a);
+ return true;
+}
+
+bool KviKvsObject_widget::function_setGeometry(KviKvsObjectFunctionCall *c)
+{
+ KviKvsVariant * pXOrArray;
+ kvs_int_t iX,iY,iW,iH;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("x_or_array",KVS_PT_VARIANT,0,pXOrArray)
+ KVSO_PARAMETER("y",KVS_PT_INT,KVS_PF_OPTIONAL,iY)
+ KVSO_PARAMETER("w",KVS_PT_INT,KVS_PF_OPTIONAL,iW)
+ KVSO_PARAMETER("h",KVS_PT_INT,KVS_PF_OPTIONAL,iH)
+ KVSO_PARAMETERS_END(c)
+
+ // this is a little bit tricky: we accept two syntax versions
+ // (this is something like a C++ overload)
+ // $setGeometry(x,y,w,h) OR $setGeometry($array(x,y,w,h))
+
+ // For this purpose we ask the parameter processing engine
+ // to return the first parameter as variant and we manually check its data typoe
+ // We also set the following three parameters as optional
+ // so the user can either pass one or four parameters.
+
+ // Because of this trick, we must check the parameter consistency
+ // manually.
+
+ if(pXOrArray->isArray())
+ {
+ // the user has passed a complete geometry array as first parameter
+ // make sure it has at least 4 elements
+ if(pXOrArray->array()->size() < 4)
+ {
+ c->error(__tr2qs("The array passed as parameter must contain at least 4 elements"));
+ return false;
+ }
+ // we must also manually extract the data from the array
+ KviKvsVariant * pX = pXOrArray->array()->at(0);
+ KviKvsVariant * pY = pXOrArray->array()->at(1);
+ KviKvsVariant * pW = pXOrArray->array()->at(2);
+ KviKvsVariant * pH = pXOrArray->array()->at(3);
+ // note that some of the array elements may be empty in fact
+ // a null value returned by KviKvsArray::at() means that
+ // no parameter was set in that place
+ if(!(pX && pY && pW && pH))
+ {
+ c->error(__tr2qs("One of the geometry array parameters is empty"));
+ return false;
+ }
+ if(!(pX->asInteger(iX) && pY->asInteger(iY) && pW->asInteger(iW) && pH->asInteger(iH)))
+ {
+ c->error(__tr2qs("One of the geometry array parameters didn't evaluate to an integer"));
+ return false;
+ }
+ // ok: the params are correct
+ } else {
+ // The user passed something else as first parameter
+ // make sure that it is an integer.
+ // Also make sure that we really have 4 parameters
+ if(c->params()->count() < 4)
+ {
+ c->error(__tr2qs("$setGeometry() requires either an array as first parameter or four integers"));
+ return false;
+ }
+ if(!pXOrArray->asInteger(iX))
+ {
+ c->error(__tr2qs("The first parameter didn't evaluate to an array nor an integer"));
+ return false;
+ }
+ // ok: the params are correct
+ }
+
+ if(widget())
+ widget()->setGeometry(iX,iY,iW,iH);
+
+ return true;
+}
+bool KviKvsObject_widget::function_mapToGlobal(KviKvsObjectFunctionCall *c)
+
+{
+ if(!widget())return true;
+ kvs_int_t iX,iY;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("x",KVS_PT_INT,0,iX)
+ KVSO_PARAMETER("y",KVS_PT_INT,0,iY)
+ KVSO_PARAMETERS_END(c)
+ QPoint point=widget()->mapToGlobal(QPoint(iX,iY));
+ KviKvsArray * a = new KviKvsArray();
+ a->set(0,new KviKvsVariant((kvs_int_t)point.x()));
+ a->set(1,new KviKvsVariant((kvs_int_t)point.y()));
+ c->returnValue()->setArray(a);
+ return true;
+}
+
+bool KviKvsObject_widget::function_mapFromGlobal(KviKvsObjectFunctionCall *c)
+
+{
+ if(!widget())return true;
+ kvs_int_t iX,iY;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("x",KVS_PT_INT,0,iX)
+ KVSO_PARAMETER("y",KVS_PT_INT,0,iY)
+ KVSO_PARAMETERS_END(c)
+ QPoint point=widget()->mapFromGlobal(QPoint(iX,iY));
+ KviKvsArray * a = new KviKvsArray();
+ a->set(0,new KviKvsVariant((kvs_int_t)point.x()));
+ a->set(1,new KviKvsVariant((kvs_int_t)point.y()));
+ c->returnValue()->setArray(a);
+ return true;
+}
+bool KviKvsObject_widget::function_centerToScreen(KviKvsObjectFunctionCall *c)
+{
+ if(widget()) widget()->move((g_pApp->desktop()->width() - widget()->width())/2,(g_pApp->desktop()->height() - widget()->height())/2);
+ return true;
+}
+
+bool KviKvsObject_widget::function_setPaletteForeground(KviKvsObjectFunctionCall *c)
+{
+ KviKvsVariant * pColArray;
+ kvs_int_t iColR,iColG,iColB;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("hex_rgb_array_or_red",KVS_PT_VARIANT,0,pColArray)
+ KVSO_PARAMETER("green",KVS_PT_INT,KVS_PF_OPTIONAL,iColG)
+ KVSO_PARAMETER("blue",KVS_PT_INT,KVS_PF_OPTIONAL,iColB)
+ KVSO_PARAMETERS_END(c)
+
+ if(pColArray->isArray())
+ {
+ if(pColArray->array()->size() < 3)
+ {
+ c->error(__tr2qs("The array passed as parameter must contain at least 3 elements"));
+ return false;
+ }
+ KviKvsVariant * pColR = pColArray->array()->at(0);
+ KviKvsVariant * pColG = pColArray->array()->at(1);
+ KviKvsVariant * pColB = pColArray->array()->at(2);
+
+ if(!(pColR && pColG && pColB))
+ {
+ c->error(__tr2qs("One of the colors array parameters is empty"));
+ return false;
+ }
+ if(!(pColR->asInteger(iColR) && pColG->asInteger(iColG) && pColB->asInteger(iColB)))
+ {
+ c->error(__tr2qs("One of the colors array parameters didn't evaluate to an integer"));
+ return false;
+ }
+
+ } else {
+ if (c->params()->count()==1)
+ {
+ bool bOk,bOk1,bOk2;
+ QString value;
+ pColArray->asString(value);
+ int i=0;
+ if (value.length()!=6)
+ {
+ c->warning(__tr2qs("A string of 6 digits hex is required"));
+ return true;
+ }
+ QString buffer(value.mid(0,2));
+ iColR=buffer.toInt(&bOk,16);
+ buffer=value.mid(2,2);
+ iColG=buffer.toInt(&bOk1,16);
+ buffer=value.mid(4,2);
+ iColB=buffer.toInt(&bOk2,16);
+ if (!bOk || !bOk1 || !bOk2)
+ {
+ c->warning(__tr2qs("Not an hex digits"));
+ return true;
+ }
+ if (widget()) widget()->setPaletteForegroundColor(QColor(iColR,iColG,iColB));
+ return true;
+ }
+
+ if(c->params()->count() < 3)
+ {
+
+ c->error(__tr2qs("$setForegroundColor requires either an array as first parameter, one hex string or three integers"));
+ return false;
+ }
+ if(!pColArray->asInteger(iColR))
+ {
+ c->error(__tr2qs("The first parameter didn't evaluate to an array nor an integer"));
+ return false;
+ }
+ }
+ if (widget()) widget()->setPaletteForegroundColor(QColor(iColR,iColG,iColB));
+ return true;
+}
+
+bool KviKvsObject_widget::function_setBackgroundColor(KviKvsObjectFunctionCall *c)
+{
+ KviKvsVariant * pColArray;
+ kvs_int_t iColR,iColG,iColB;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("hex_rgb_array_or_red",KVS_PT_VARIANT,0,pColArray)
+ KVSO_PARAMETER("green",KVS_PT_INT,KVS_PF_OPTIONAL,iColG)
+ KVSO_PARAMETER("blue",KVS_PT_INT,KVS_PF_OPTIONAL,iColB)
+ KVSO_PARAMETERS_END(c)
+
+ if(pColArray->isArray())
+ {
+ if(pColArray->array()->size() < 3)
+ {
+ c->error(__tr2qs("The array passed as parameter must contain at least 3 elements"));
+ return false;
+ }
+ KviKvsVariant * pColR = pColArray->array()->at(0);
+ KviKvsVariant * pColG = pColArray->array()->at(1);
+ KviKvsVariant * pColB = pColArray->array()->at(2);
+
+ if(!(pColR && pColG && pColB))
+ {
+ c->error(__tr2qs("One of the colors array parameters is empty"));
+ return false;
+ }
+ if(!(pColR->asInteger(iColR) && pColG->asInteger(iColG) && pColB->asInteger(iColB)))
+ {
+ c->error(__tr2qs("One of the colors array parameters didn't evaluate to an integer"));
+ return false;
+ }
+
+ } else {
+ if (c->params()->count()==1)
+ {
+ bool bOk,bOk1,bOk2;
+ QString value;
+ pColArray->asString(value);
+ int i=0;
+ if (value.length()!=6)
+ {
+ c->warning(__tr2qs("A string of 6 digits hex is required"));
+ return true;
+ }
+ QString buffer(value.mid(0,2));
+ iColR=buffer.toInt(&bOk,16);
+ buffer=value.mid(2,2);
+ iColG=buffer.toInt(&bOk1,16);
+ buffer=value.mid(4,2);
+ iColB=buffer.toInt(&bOk2,16);
+ if (!bOk || !bOk1 || !bOk2)
+ {
+ c->warning(__tr2qs("Not an hex digits"));
+ return true;
+ }
+ if (widget()) widget()->setBackgroundColor(QColor(iColR,iColG,iColB));
+ return true;
+ }
+
+ if(c->params()->count() < 3)
+ {
+
+ c->error(__tr2qs("$setBackgroundColor requires either an array as first parameter, one hex string or three integers"));
+ return false;
+ }
+ if(!pColArray->asInteger(iColR))
+ {
+ c->error(__tr2qs("The first parameter didn't evaluate to an array nor an integer"));
+ return false;
+ }
+ }
+ if (widget()) widget()->setBackgroundColor(QColor(iColR,iColG,iColB));
+ return true;
+}
+
+bool KviKvsObject_widget::function_backgroundColor(KviKvsObjectFunctionCall *c)
+{
+ if(!widget())return true;
+ QColor col = widget()->backgroundColor();
+ KviKvsArray * a = new KviKvsArray();
+ a->set(0,new KviKvsVariant((kvs_int_t)col.red()));
+ a->set(1,new KviKvsVariant((kvs_int_t)col.green()));
+ a->set(2,new KviKvsVariant((kvs_int_t)col.blue()));
+ c->returnValue()->setArray(a);
+ return true;
+}
+
+bool KviKvsObject_widget::function_foregroundColor(KviKvsObjectFunctionCall *c)
+{
+ if(!widget())return true;
+ QColor col = widget()->foregroundColor();
+ KviKvsArray * a = new KviKvsArray();
+ a->set(0,new KviKvsVariant((kvs_int_t)col.red()));
+ a->set(1,new KviKvsVariant((kvs_int_t)col.green()));
+ a->set(2,new KviKvsVariant((kvs_int_t)col.blue()));
+ c->returnValue()->setArray(a);
+ return true;
+}
+
+bool KviKvsObject_widget::function_parentWidget(KviKvsObjectFunctionCall *c)
+{
+ if(!widget())return true;
+ if(parentScriptWidget()) c->returnValue()->setHObject(parentObject()->handle());
+ else
+ c->returnValue()->setHObject((kvs_hobject_t)0);
+ return true;
+
+}
+bool KviKvsObject_widget::function_setMouseTracking(KviKvsObjectFunctionCall *c)
+{
+ bool bEnabled;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bEnabled",KVS_PT_BOOL,0,bEnabled)
+ KVSO_PARAMETERS_END(c)
+ if(widget()) widget()->setMouseTracking(bEnabled);
+ return true;
+}
+
+bool KviKvsObject_widget::function_setCaption(KviKvsObjectFunctionCall *c)
+{
+ QString szCaption;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("caption",KVS_PT_STRING,0,szCaption)
+ KVSO_PARAMETERS_END(c)
+ if(widget()) widget()->setCaption(szCaption);
+ return true;
+}
+
+bool KviKvsObject_widget::function_caption(KviKvsObjectFunctionCall *c)
+{
+ if(widget()) c->returnValue()->setString(widget()->caption().utf8().data());
+ return true;
+}
+
+bool KviKvsObject_widget::function_isTopLevel(KviKvsObjectFunctionCall *c)
+{
+ if(widget()) c->returnValue()->setBoolean(widget()->isTopLevel());
+ return true;
+}
+
+bool KviKvsObject_widget::function_isVisible(KviKvsObjectFunctionCall *c)
+{
+ if(widget()) c->returnValue()->setBoolean(widget()->isVisible());
+ return true;
+}
+
+bool KviKvsObject_widget::function_raise(KviKvsObjectFunctionCall *)
+{
+ if(widget()) widget()->raise();
+ return true;
+}
+
+bool KviKvsObject_widget::function_lower(KviKvsObjectFunctionCall *)
+{
+ if(widget())widget()->lower();
+ return true;
+}
+
+bool KviKvsObject_widget::function_hasFocus(KviKvsObjectFunctionCall *c)
+{
+ if(widget()) c->returnValue()->setBoolean(widget()->hasFocus());
+ return true;
+}
+
+bool KviKvsObject_widget::function_setFocus(KviKvsObjectFunctionCall *c)
+{
+ if (widget())widget()->setFocus();
+ return true;
+}
+bool KviKvsObject_widget::function_hide(KviKvsObjectFunctionCall *)
+{
+ if(widget())widget()->hide();
+ return true;
+}
+
+bool KviKvsObject_widget::function_setToolTip(KviKvsObjectFunctionCall *c)
+{
+ QString szTooltip;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("tooltip",KVS_PT_STRING,0,szTooltip)
+ KVSO_PARAMETERS_END(c)
+ if(widget())QToolTip::add( widget(), szTooltip );
+ return true;
+}
+
+bool KviKvsObject_widget::function_x(KviKvsObjectFunctionCall *c)
+{
+ if(widget()) c->returnValue()->setInteger(widget()->x());
+ return true;
+}
+
+bool KviKvsObject_widget::function_y(KviKvsObjectFunctionCall *c)
+{
+ if(widget())c->returnValue()->setInteger(widget()->y());
+ return true;
+}
+
+bool KviKvsObject_widget::function_width(KviKvsObjectFunctionCall *c)
+{
+ if(widget())c->returnValue()->setInteger(widget()->width());
+ return true;
+}
+
+bool KviKvsObject_widget::function_height(KviKvsObjectFunctionCall *c)
+{
+ if(widget())c->returnValue()->setInteger(widget()->height());
+ return true;
+}
+
+bool KviKvsObject_widget::function_setMinimumWidth(KviKvsObjectFunctionCall *c)
+{
+ kvs_int_t iW;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("w",KVS_PT_INT,0,iW)
+ KVSO_PARAMETERS_END(c)
+ if (widget()) widget()->setMinimumWidth(iW);
+ return true;
+}
+
+bool KviKvsObject_widget::function_setMinimumHeight(KviKvsObjectFunctionCall *c)
+{
+ kvs_int_t iH;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("h",KVS_PT_INT,0,iH)
+ KVSO_PARAMETERS_END(c)
+ if (widget()) widget()->setMinimumHeight(iH);
+ return true;
+}
+
+bool KviKvsObject_widget::function_setMaximumWidth(KviKvsObjectFunctionCall *c)
+{
+ kvs_int_t iW;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("w",KVS_PT_INT,0,iW)
+ KVSO_PARAMETERS_END(c)
+ if (widget()) widget()->setMaximumWidth(iW);
+ return true;
+}
+
+bool KviKvsObject_widget::function_setMaximumHeight(KviKvsObjectFunctionCall *c)
+{
+ kvs_int_t iH;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("h",KVS_PT_INT,0,iH)
+ KVSO_PARAMETERS_END(c)
+ if(widget()) widget()->setMaximumHeight(iH);
+ return true;
+}
+
+bool KviKvsObject_widget::function_move(KviKvsObjectFunctionCall *c)
+{
+ kvs_int_t iX,iY;
+
+ KviKvsVariant * pXOrArray;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("x_or_array",KVS_PT_VARIANT,0,pXOrArray)
+ KVSO_PARAMETER("y",KVS_PT_INT,KVS_PF_OPTIONAL,iY)
+ KVSO_PARAMETERS_END(c)
+ if(pXOrArray->isArray())
+ {
+ if(pXOrArray->array()->size() < 2)
+ {
+ c->error(__tr2qs("The array passed as parameter must contain at least 2 elements"));
+ return false;
+ }
+ KviKvsVariant * pX = pXOrArray->array()->at(0);
+ KviKvsVariant * pY = pXOrArray->array()->at(1);
+ if(!(pX && pY))
+ {
+ c->error(__tr2qs("One of the move array parameters is empty"));
+ return false;
+ }
+ if(!(pX->asInteger(iX) && pY->asInteger(iY)))
+ {
+ c->error(__tr2qs("One of the move array parameters didn't evaluate to an integer"));
+ return false;
+ }
+ // ok: the params are correct
+ } else {
+ if(c->params()->count() < 2)
+ {
+ c->error(__tr2qs("$move() requires either an array as first parameter or two integers"));
+ return false;
+ }
+ if(!pXOrArray->asInteger(iX))
+ {
+ c->error(__tr2qs("The first parameter didn't evaluate to an array nor an integer"));
+ return false;
+ }
+ // ok: the params are correct
+ }
+
+ if(!widget())return true;
+ widget()->move(QPoint(iX,iY));
+ return true;
+}
+bool KviKvsObject_widget::function_sizeHint(KviKvsObjectFunctionCall *c)
+{
+ if(!widget())return true;
+ QSize sizehint = widget()->sizeHint();
+ KviKvsArray * a = new KviKvsArray();
+ a->set(0,new KviKvsVariant((kvs_int_t)sizehint.width()));
+ a->set(1,new KviKvsVariant((kvs_int_t)sizehint.height()));
+ c->returnValue()->setArray(a);
+ return true;
+}
+
+bool KviKvsObject_widget::function_resize(KviKvsObjectFunctionCall *c)
+{
+ KviKvsVariant * pWOrArray;
+ kvs_int_t iW,iH;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("width_or_array",KVS_PT_VARIANT,0,pWOrArray)
+ KVSO_PARAMETER("height",KVS_PT_INT,KVS_PF_OPTIONAL,iH)
+ KVSO_PARAMETERS_END(c)
+ if(pWOrArray->isArray())
+ {
+ if(pWOrArray->array()->size() < 2)
+ {
+ c->error(__tr2qs("The array passed as parameter must contain at least 2 elements"));
+ return false;
+ }
+ KviKvsVariant * pW = pWOrArray->array()->at(0);
+ KviKvsVariant * pH = pWOrArray->array()->at(1);
+ if(!(pW && pH))
+ {
+ c->error(__tr2qs("One of the resize array parameters is empty"));
+ return false;
+ }
+ if(!(pW->asInteger(iW) && pH->asInteger(iH)))
+ {
+ c->error(__tr2qs("One of the resize array parameters didn't evaluate to an integer"));
+ return false;
+ }
+ // ok: the params are correct
+ } else {
+ if(c->params()->count() < 2)
+ {
+ c->error(__tr2qs("$resize() requires either an array as first parameter or two integers"));
+ return false;
+ }
+ if(!pWOrArray->asInteger(iW))
+ {
+ c->error(__tr2qs("The first parameter didn't evaluate to an array nor an integer"));
+ return false;
+ }
+ // ok: the params are correct
+ }
+
+ if(!widget())return true;
+ widget()->resize(QSize(iW,iH));
+ return true;
+}
+bool KviKvsObject_widget::function_setFocusPolicy(KviKvsObjectFunctionCall *c)
+{
+ QString szMode;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("focus",KVS_PT_STRING,0,szMode)
+ KVSO_PARAMETERS_END(c)
+ if(!widget())return true;
+ if(KviQString::equalCI(szMode, "TabFocus"))
+ widget()->setFocusPolicy(QT_WIDGET_TABFOCUS);
+ else
+ if(KviQString::equalCI(szMode, "ClickFocus"))
+ widget()->setFocusPolicy(QT_WIDGET_CLICKFOCUS);
+ else
+ if(KviQString::equalCI(szMode, "StrongFocus"))
+ widget()->setFocusPolicy(QT_WIDGET_STRONGFOCUS);
+ else
+ if(KviQString::equalCI(szMode, "NoFocus"))
+ widget()->setFocusPolicy(QT_WIDGET_NOFOCUS);
+ else c->warning(__tr2qs("Invalid parameters"));
+ return true;
+}
+
+bool KviKvsObject_widget::function_setWFlags(KviKvsObjectFunctionCall *c)
+{
+ QStringList wflags;
+ //Qt::WindowType sum;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("widget_flags",KVS_PT_STRINGLIST,KVS_PF_OPTIONAL,wflags)
+ KVSO_PARAMETERS_END(c)
+ if (!widget()) return true;
+ #ifdef COMPILE_USE_QT4
+ Qt::WindowFlags flag,sum=0;
+ #else
+ int flag,sum=0;
+ #endif
+ for ( QStringList::Iterator it = wflags.begin(); it != wflags.end(); ++it )
+ {
+
+ flag=0;
+ for(unsigned int j = 0; j < widgettypes_num; j++)
+ {
+ if(KviQString::equalCI((*it), widgettypes_tbl[j]))
+ {
+ flag=widgettypes_cod[j];
+ break;
+ }
+ }
+ if(flag)
+ sum = sum | flag;
+ else
+ c->warning(__tr2qs("Unknown widget flag '%Q'"),&(*it));
+
+ }
+
+#ifdef COMPILE_USE_QT4
+ widget()->setWindowFlags(sum);
+#else
+ widget()->reparent(widget()->parentWidget(),sum,QPoint(widget()->x(),widget()->y()));
+#endif
+ return true;
+}
+
+bool KviKvsObject_widget::function_setFont(KviKvsObjectFunctionCall *c)
+{
+
+ QString szFamily,szStyle;
+ kvs_int_t uSize;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("size",KVS_PT_UNSIGNEDINTEGER,0,uSize)
+ KVSO_PARAMETER("family",KVS_PT_STRING,0,szFamily)
+ KVSO_PARAMETER("style",KVS_PT_STRING,0,szStyle)
+ KVSO_PARAMETERS_END(c)
+ if(!widget())return true;
+ QFont font=widget()->font();
+ font.setFamily(szFamily);
+ font.setPointSize(uSize);
+ if(KviQString::equalCI(szStyle,"italic")) font.setItalic(TRUE);
+ else if(KviQString::equalCI(szStyle,"bold")) font.setBold(TRUE);
+ else if(KviQString::equalCI(szStyle,"underline"))font.setUnderline(TRUE);
+ else if(KviQString::equalCI(szStyle,"overline")) font.setOverline(TRUE);
+ else if(KviQString::equalCI(szStyle,"strikeout"))font.setStrikeOut(TRUE);
+ else if(KviQString::equalCI(szStyle,"fixedpitch")) font.setFixedPitch(TRUE);
+ else c->warning(__tr2qs("Unknown style '%Q'"),&szStyle);
+ widget()->setFont(font);
+ return true;
+}
+
+bool KviKvsObject_widget::function_addWidgetToWrappedLayout(KviKvsObjectFunctionCall *c)
+{
+ KviKvsObject *ob;
+ kvs_int_t uCol,uRow;
+ kvs_hobject_t hObject;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("widget",KVS_PT_HOBJECT,0,hObject)
+ KVSO_PARAMETER("col",KVS_PT_UNSIGNEDINTEGER,0,uCol)
+ KVSO_PARAMETER("row",KVS_PT_UNSIGNEDINTEGER,0,uRow)
+ KVSO_PARAMETERS_END(c)
+ ob=KviKvsKernel::instance()->objectController()->lookupObject(hObject);
+ if(!widget())return true;
+ if (!ob)
+ {
+ c->warning(__tr2qs("Widget parameter is not an object"));
+ return true;
+ }
+ if (!ob->object())
+ {
+ c->warning(__tr2qs("Widget parameter is not a valid object"));
+ return true;
+ }
+ QLayout *lay=widget()->layout();
+ if (!lay)
+ {
+ c->warning(__tr2qs("No Layout associated to the widget "));
+ return true;
+ }
+ if(!ob->object()->isWidgetType())
+ {
+ c->warning(__tr2qs("Can't add a non-widget object"));
+ return true;
+ }
+ lay->add(((QWidget *)(ob->object())));
+ return true;
+}
+bool KviKvsObject_widget::function_reparent(KviKvsObjectFunctionCall *c)
+{
+ KviKvsObject *ob;
+ kvs_hobject_t hObject;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("widget",KVS_PT_HOBJECT,KVS_PF_OPTIONAL,hObject)
+ KVSO_PARAMETERS_END(c)
+ ob=KviKvsKernel::instance()->objectController()->lookupObject(hObject);
+ if(!widget()) return true;
+ if(!ob)
+ {
+ widget()->reparent(0,QPoint(widget()->x(),widget()->y()));
+ return true;
+ }
+ else
+ if(!ob->object()->isWidgetType())
+ {
+ c->warning(__tr("Parent must be a widget object"));
+ return true;
+ }
+ widget()->reparent(((QWidget *)(ob->object())),QPoint(((QWidget *)(ob->object()))->x(),((QWidget *)(ob->object()))->y()));
+ return true;
+}
+bool KviKvsObject_widget::function_setIcon(KviKvsObjectFunctionCall *c)
+{
+
+ QString icon;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("icon",KVS_PT_STRING,0,icon)
+ KVSO_PARAMETERS_END(c)
+ if(!widget())return true;
+ QPixmap * pix = g_pIconManager->getImage(icon);
+ if(pix)widget()->setIcon(*pix);
+ return true;
+}
+
+bool KviKvsObject_widget::function_setBackgroundImage(KviKvsObjectFunctionCall *c)
+{
+ QString image;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("image",KVS_PT_STRING,0,image)
+ KVSO_PARAMETERS_END(c)
+ if(!widget())return true;
+ QPixmap * pix = g_pIconManager->getImage(image);
+ if(pix)widget()->setPaletteBackgroundPixmap(*pix);
+ return true;
+}
+bool KviKvsObject_widget::function_globalCursorX(KviKvsObjectFunctionCall *c)
+{
+ if(widget())c->returnValue()->setInteger(QCursor::pos().x());
+ return true;
+}
+bool KviKvsObject_widget::function_globalCursorY(KviKvsObjectFunctionCall *c)
+{
+ if(widget())c->returnValue()->setInteger(QCursor::pos().y());
+ return true;
+}
+bool KviKvsObject_widget::function_setMask(KviKvsObjectFunctionCall *c)
+{
+ KviKvsObject *obj;
+ kvs_hobject_t hObject;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("pixmap",KVS_PT_HOBJECT,0,hObject)
+ KVSO_PARAMETERS_END(c)
+ obj=KviKvsKernel::instance()->objectController()->lookupObject(hObject);
+ if(!widget())return true;
+ if (!obj)
+ {
+ c->warning(__tr2qs("Pixmap parameter is not an object"));
+ return true;
+ }
+ if (!obj->inherits("KviKvsObject_pixmap"))
+ {
+ c->warning(__tr2qs("Pixmap object required"));
+ return true;
+ }
+ QPixmap * pm=((KviKvsObject_pixmap *)obj)->getPixmap();
+#ifdef COMPILE_USE_QT4
+ QBitmap mask(pm->mask());
+#else
+ QBitmap mask(*pm->mask());
+#endif
+ if (mask.isNull()) c->warning(__tr2qs("Null mask"));
+ widget()->setMask(mask);
+ return true;
+}
+#ifdef COMPILE_USE_QT4
+bool KviKvsObject_widget::function_setAttribute(KviKvsObjectFunctionCall *c)
+{
+ QString attribute;
+ bool bFlag;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("widget_atribute",KVS_PT_STRING,0,attribute)
+ KVSO_PARAMETER("bool_flag",KVS_PT_BOOLEAN,0,bFlag)
+ KVSO_PARAMETERS_END(c)
+ if (!widget()) return true;
+ bool found=false;
+ unsigned int j = 0;
+ for(; j < widgetattributes_num; j++)
+ {
+ if(KviQString::equalCI(attribute, widgetattributes_tbl[j]))
+ {
+ found=true;
+ break;
+ }
+ }
+ if(found)widget()->setAttribute(widgetattributes_cod[j],bFlag);
+ else c->warning(__tr2qs("Unknown widget attribute '%Q'"),&attribute);
+ return true;
+}
+#endif
+
+#include "m_class_widget.moc"
diff --git a/src/modules/objects/class_widget.h b/src/modules/objects/class_widget.h
new file mode 100644
index 00000000..ecd87bba
--- /dev/null
+++ b/src/modules/objects/class_widget.h
@@ -0,0 +1,113 @@
+#ifndef _CLASS_WIDGET_H_
+#define _CLASS_WIDGET_H_
+//vim: ts=8
+// File : class_widget.h
+// Creation date : Mon 11 Sep 16:34:36 CET 2000 by Krzysztof Godlewski
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+#include <kvi_tal_tooltip.h>
+#include "kvi_string.h"
+#include "qtooltip.h"
+#include "object_macros.h"
+
+
+class KviKvsObject_widget : public KviKvsObject
+{
+ Q_OBJECT
+public:
+ KVSO_DECLARE_OBJECT(KviKvsObject_widget)
+public:
+ QWidget * widget() { return (QWidget *)object(); };
+protected:
+ virtual bool init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams);
+
+ virtual bool eventFilter(QObject *o,QEvent *e);
+
+ // ok, it is clear that we're messing with the naming conventions for the
+ // object classes :D
+ // let's try to use this one:
+ // function_isEnabled
+ // function_setEnabled..
+ // ... etc
+ // so the name of the C++ function matches exactly the name of the KVS function at this point
+
+ // let's also try to keep alphabetic order for the functions here.. so one can find them quickly
+
+ bool function_addWidgetToWrappedLayout(KviKvsObjectFunctionCall *c);
+ bool function_backgroundColor(KviKvsObjectFunctionCall *c);
+ bool function_caption(KviKvsObjectFunctionCall *c);
+ bool function_centerToScreen(KviKvsObjectFunctionCall *c);
+ bool function_fontAscent(KviKvsObjectFunctionCall * c);
+ bool function_fontDescent(KviKvsObjectFunctionCall * c);
+ bool function_fontMetricsHeight(KviKvsObjectFunctionCall * c);
+ bool function_fontMetricsWidth(KviKvsObjectFunctionCall * c);
+ bool function_foregroundColor(KviKvsObjectFunctionCall *c);
+ bool function_geometry(KviKvsObjectFunctionCall *c);
+ bool function_globalCursorX(KviKvsObjectFunctionCall *c);
+ bool function_globalCursorY(KviKvsObjectFunctionCall *c);
+ bool function_hasFocus(KviKvsObjectFunctionCall *c);
+ bool function_height(KviKvsObjectFunctionCall *);
+ bool function_hide(KviKvsObjectFunctionCall *);
+ bool function_isEnabled(KviKvsObjectFunctionCall *c);
+ bool function_isTopLevel(KviKvsObjectFunctionCall *c);
+ bool function_isVisible(KviKvsObjectFunctionCall *c);
+ bool function_lower(KviKvsObjectFunctionCall *);
+ bool function_mapFromGlobal(KviKvsObjectFunctionCall *c);
+ bool function_mapToGlobal(KviKvsObjectFunctionCall *c);
+ bool function_move(KviKvsObjectFunctionCall *c);
+ bool function_parentWidget(KviKvsObjectFunctionCall *c);
+ bool function_raise(KviKvsObjectFunctionCall *);
+ bool function_repaint(KviKvsObjectFunctionCall *c);
+ bool function_reparent(KviKvsObjectFunctionCall *c);
+ bool function_resize(KviKvsObjectFunctionCall *c);
+ bool function_screenResolution(KviKvsObjectFunctionCall * c);
+ bool function_setBackgroundColor(KviKvsObjectFunctionCall *c);
+ bool function_setBackgroundImage(KviKvsObjectFunctionCall *c);
+ bool function_setCaption(KviKvsObjectFunctionCall *c);
+ bool function_setEnabled(KviKvsObjectFunctionCall *c);
+ bool function_setFocus(KviKvsObjectFunctionCall *c);
+ bool function_setFocusPolicy(KviKvsObjectFunctionCall *c);
+ bool function_setFont(KviKvsObjectFunctionCall *c);
+ bool function_setIcon(KviKvsObjectFunctionCall *c);
+ bool function_setMaximumWidth(KviKvsObjectFunctionCall *c);
+ bool function_setMaximumHeight(KviKvsObjectFunctionCall *c);
+ bool function_setMinimumWidth(KviKvsObjectFunctionCall *c);
+ bool function_setMinimumHeight(KviKvsObjectFunctionCall *c);
+ bool function_setMouseTracking(KviKvsObjectFunctionCall *c);
+ bool function_setPaletteForeground(KviKvsObjectFunctionCall *c);
+ bool function_setToolTip(KviKvsObjectFunctionCall *);
+ bool function_setGeometry(KviKvsObjectFunctionCall *c);
+ bool function_setWFlags(KviKvsObjectFunctionCall *c);
+ bool function_show(KviKvsObjectFunctionCall *c);
+ bool function_sizeHint(KviKvsObjectFunctionCall *c);
+ bool function_width(KviKvsObjectFunctionCall *);
+ bool function_x(KviKvsObjectFunctionCall *);
+ bool function_y(KviKvsObjectFunctionCall *);
+ bool function_setMask(KviKvsObjectFunctionCall *c);
+
+
+#ifdef COMPILE_USE_QT4
+bool function_setAttribute(KviKvsObjectFunctionCall *c);
+#endif
+
+signals:
+ void aboutToDie();
+};
+
+#endif // !_CLASS_WIDGET_H_
diff --git a/src/modules/objects/class_window.cpp b/src/modules/objects/class_window.cpp
new file mode 100644
index 00000000..9218cb8f
--- /dev/null
+++ b/src/modules/objects/class_window.cpp
@@ -0,0 +1,158 @@
+//
+// File : class_window.cpp
+// Creation date : Tue Now 26 21:39:59 CEST 2002 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+
+#include "class_window.h"
+
+#include "kvi_error.h"
+#include "kvi_debug.h"
+
+#include "kvi_locale.h"
+#include "kvi_frame.h"
+
+
+
+KviKvsScriptWindowWindow::KviKvsScriptWindowWindow(KviFrame * pParent,const QString &szName)
+: KviWindow(KVI_WINDOW_TYPE_SCRIPTOBJECT,pParent,szName)
+{
+ m_pCentralWidget = 0;
+ #ifdef COMPILE_USE_QT4
+ setBackgroundMode(Qt::NoBackground);
+ #else
+ setBackgroundMode(QWidget::NoBackground);
+ #endif
+}
+
+KviKvsScriptWindowWindow::~KviKvsScriptWindowWindow()
+{
+}
+
+void KviKvsScriptWindowWindow::setCentralWidget(KviKvsObject_widget *o,QWidget * w)
+{
+ m_pCentralWidgetObject = o;
+ m_pCentralWidget = w;
+}
+
+void KviKvsScriptWindowWindow::resizeEvent(QResizeEvent *e)
+{
+ if(m_pCentralWidget)
+ m_pCentralWidget->setGeometry(0,0,width(),height());
+}
+
+void KviKvsScriptWindowWindow::centralWidgetObjectDestroyed()
+{
+ m_pCentralWidget = 0;
+ m_pCentralWidgetObject = 0;
+}
+
+void KviKvsScriptWindowWindow::centralWidgetDestroyed()
+{
+ m_pCentralWidget = 0;
+ m_pCentralWidgetObject = 0;
+}
+
+
+
+
+/*
+ @doc: window
+ @title:
+ window class
+ @type:
+ class
+ @short:
+ A MDI window object
+ @inherits:
+ [class]object[/class]
+ [class]widget[/class]
+ @description:
+ This class rappresents a MDI window in a KVIrc frame.
+ Regardless of the parent object passed, the window will be always
+ a "physical" child of the frame window: you can't embed a window object
+ inside a widget or another window. The parent object will just "own" this
+ window object and eventually destroy it when it dies.
+ This class can manage only a single central child widget that must
+ be set with $setCentralWidget().
+ The central widget MUST be set before you initially call show()
+ @functions:
+*/
+
+
+KVSO_BEGIN_REGISTERCLASS(KviKvsObject_window,"window","widget")
+
+ KVSO_REGISTER_HANDLER(KviKvsObject_window,"setCaption", functionsetCaption)
+ KVSO_REGISTER_HANDLER(KviKvsObject_window,"setCentralWidget", functionsetCentralWidget)
+// KVSO_REGISTER_HANDLER(KviKvsObject_window,"setIcon", functionsetIcon)
+KVSO_END_REGISTERCLASS(KviKvsObject_window)
+
+KVSO_BEGIN_CONSTRUCTOR(KviKvsObject_window,KviKvsObject_widget)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_window)
+
+
+KVSO_BEGIN_DESTRUCTOR(KviKvsObject_window)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_window)
+
+bool KviKvsObject_window::init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams)
+{
+ KviWindow * w = new KviKvsScriptWindowWindow(pContext->window()->frame(),name());
+ setObject(w);
+ pContext->window()->frame()->addWindow(w,false);
+ w->minimize(); // must be minimized before children are added, otherwise the focus handling goes nuts...
+
+ return true;
+}
+bool KviKvsObject_window::functionsetCaption(KviKvsObjectFunctionCall *c)
+{
+ QString szCaption;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("caption",KVS_PT_STRING,0,szCaption)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ ((KviKvsScriptWindowWindow *)widget())->setCaptionString(szCaption);
+ return true;
+}
+bool KviKvsObject_window::functionsetCentralWidget(KviKvsObjectFunctionCall *c)
+{
+ KviKvsObject *ob;
+ kvs_hobject_t hObject;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("widget",KVS_PT_HOBJECT,0,hObject)
+ KVSO_PARAMETERS_END(c)
+ ob=KviKvsKernel::instance()->objectController()->lookupObject(hObject);
+ if(!widget())return true;
+ if(!ob->object()->isWidgetType())
+ {
+ c->warning(__tr2qs("Can't add a non-widget object"));
+ return true;
+ }
+ if(!ob->inherits("KviKvsObject_widget"))
+ {
+ c->warning(__tr2qs("Can't add a non-widget object"));
+ return true;
+ }
+ ((KviKvsScriptWindowWindow *)widget())->setCentralWidget((KviKvsObject_widget *)ob,((KviKvsObject_widget *)ob)->widget());
+ return true;
+}
+#include "m_class_window.moc"
diff --git a/src/modules/objects/class_window.h b/src/modules/objects/class_window.h
new file mode 100644
index 00000000..1f2ae482
--- /dev/null
+++ b/src/modules/objects/class_window.h
@@ -0,0 +1,64 @@
+#ifndef _CLASS_WINDOW_H_
+#define _CLASS_WINDOW_H_
+//
+// File : class_window.h
+// Creation date : Tue Nov 26 21:37:48 CEST 2002 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "class_widget.h"
+#include "kvi_window.h"
+
+#include "object_macros.h"
+
+class KviKvsObject_window : public KviKvsObject_widget
+{
+public:
+ KVSO_DECLARE_OBJECT(KviKvsObject_window)
+public:
+ QWidget * widget() { return (QWidget *)object(); };
+
+protected:
+ virtual bool init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams);
+
+ bool functionsetCaption(KviKvsObjectFunctionCall *c);
+ bool functionsetCentralWidget(KviKvsObjectFunctionCall *c);
+
+};
+
+
+class KviKvsScriptWindowWindow : public KviWindow
+{
+ Q_OBJECT
+public:
+ KviKvsScriptWindowWindow(KviFrame * pParent,const QString &szName);
+ ~KviKvsScriptWindowWindow();
+protected:
+ KviKvsObject_widget * m_pCentralWidgetObject;
+ QWidget * m_pCentralWidget;
+public:
+ void setCentralWidget(KviKvsObject_widget *o,QWidget * w);
+ void setCaptionString(const QString &s){ setFixedCaption(s); };
+ virtual void resizeEvent(QResizeEvent *e);
+protected slots:
+ void centralWidgetObjectDestroyed();
+ void centralWidgetDestroyed();
+};
+
+#endif // !_CLASS_WINDOW_H_
diff --git a/src/modules/objects/class_wizard.cpp b/src/modules/objects/class_wizard.cpp
new file mode 100644
index 00000000..091b3065
--- /dev/null
+++ b/src/modules/objects/class_wizard.cpp
@@ -0,0 +1,371 @@
+//mdm:
+// File : class_wizard.cpp
+// Creation date : Mon Apr 10 19:21:48 CEST 2005
+// by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include <kvi_tal_wizard.h>
+#include <qpushbutton.h>
+#include "class_wizard.h"
+#include "kvi_error.h"
+#include "kvi_debug.h"
+
+#include "kvi_locale.h"
+
+
+
+/*
+ @doc: wizard
+ @keyterms:
+ wizard object class,
+ @title:
+ wizard class
+ @type:
+ class
+ @short:
+ The wizard class provides a framework for wizard dialogs.
+ @inherits:
+ [class]object[/class]
+ [class]widget[/class]
+ @description:
+ A wizard is an input dialog that consists of a sequence of dialog pages.It walks the user through a process step by step.[br]
+ @functions:
+ !fn: $addPage(<page_widget:object>,<title:string>)
+ Add a page with title.<page_widget> must be a widget's object.
+ !fn: $insertPage(<page_widget>,<title:string>,<index:integer>)
+ Inserts a page at the position <index>. If index is -1, page will appended to the end of the wizard's page sequenze.
+ !fn: $setTitle(<page>,<title:string>)
+ Sets the title for page page to title text.
+ !fn: $setBackEnabled(<page_widget>,<bEnabled:boolean>)
+ If enable is set to 1, page page has a Back button; otherwise page has no Back button.[br]
+ By default all pages have this button.
+ !fn: $setNextEnabled(<page_widget>,<bEnabled:boolean>)
+ If enable is set to 1, page page has a Next button; otherwise the Next button on page is disabled.[br]
+ By default all pages have this button.
+ !fn: $setFinishEnabled(<page_widget>,<bEnabled:boolean>)
+ If enable is set to 1, page page has a Finish button; otherwise the Finish button on page is disabled.[br]
+ By default NO pages have this button.
+ !fn: $setHelpEnabled(<page_widget>,<bEnabled:boolean>)
+ If enable is set to 1, page page has a Help button; otherwise the Help button on page is disabled.[br]
+ By default all pages have this button.
+ !fn: $setNextBtnText(<text:string>)
+ Set the text for button Next.
+ !fn: $setBackBtnText(<text:string>)
+ Set the text for button Back.
+ !fn: $setFinishBtnText(<text:string>)
+ Set the text for button Finish.
+ !fn: $setHelpBtnText(<text:string>)
+ Set the text for button Help.
+ !fn: $acceptEvent()
+ This function is called when the user click on the Finish button.
+ !fn: $rejectEvent()
+ This function is called when thie user click on the Reject button.
+ !fn: $nextClickedEvent()
+ This function is called when the user click on the Next button.
+ !fn: $backClickedEvent()
+ This function is called when thie user click on the Back button.
+ @signals:
+ !sg: $nextClicked()
+ This signal is emitted by the default implementation of [classfnc]$nextClickedEvent[/classfnc]().
+ !sg: $backClicked()
+ This signal is emitted by the default implementation of [classfnc]$backClickedEvent[/classfnc]().
+
+*/
+
+KVSO_BEGIN_REGISTERCLASS(KviKvsObject_wizard,"wizard","widget")
+
+ KVSO_REGISTER_HANDLER(KviKvsObject_wizard,"addPage", functionaddPage)
+ KVSO_REGISTER_HANDLER(KviKvsObject_wizard,"insertPage", functioninsertPage)
+ KVSO_REGISTER_HANDLER(KviKvsObject_wizard,"setTitle", functionsetTitle)
+
+ KVSO_REGISTER_HANDLER(KviKvsObject_wizard,"setBackEnabled", functionsetBackEnabled);
+ KVSO_REGISTER_HANDLER(KviKvsObject_wizard,"setNextEnabled", functionsetNextEnabled);
+ KVSO_REGISTER_HANDLER(KviKvsObject_wizard,"setFinishEnabled", functionsetFinishEnabled);
+ KVSO_REGISTER_HANDLER(KviKvsObject_wizard,"setHelpEnabled", functionsetHelpEnabled);
+
+ KVSO_REGISTER_HANDLER(KviKvsObject_wizard,"setBackBtnText", functionsetBackBtnText);
+ KVSO_REGISTER_HANDLER(KviKvsObject_wizard,"setNextBtnText", functionsetNextBtnText);
+ KVSO_REGISTER_HANDLER(KviKvsObject_wizard,"setFinishBtnText", functionsetFinishBtnText);
+ KVSO_REGISTER_HANDLER(KviKvsObject_wizard,"setHelpBtnText", functionsetHelpBtnText);
+ KVSO_REGISTER_HANDLER(KviKvsObject_wizard,"nextClickedEvent", functionnextClickedEvent);
+ KVSO_REGISTER_HANDLER(KviKvsObject_wizard,"backClickedEvent", functionbackClickedEvent);
+
+
+ KVSO_REGISTER_STANDARD_NOTHINGRETURN_HANDLER(KviKvsObject_wizard,"acceptEvent")
+ KVSO_REGISTER_STANDARD_NOTHINGRETURN_HANDLER(KviKvsObject_wizard,"rejectEvent")
+
+KVSO_END_REGISTERCLASS(KviKvsObject_wizard)
+
+KVSO_BEGIN_CONSTRUCTOR(KviKvsObject_wizard,KviKvsObject_widget)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_wizard)
+
+
+KVSO_BEGIN_DESTRUCTOR(KviKvsObject_wizard)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_wizard)
+
+bool KviKvsObject_wizard::init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams)
+{
+ setObject(new KviKvsMdmWizard(parentScriptWidget(), name(),this), true);
+
+ return true;
+}
+bool KviKvsObject_wizard::functionaddPage(KviKvsObjectFunctionCall *c)
+{
+ KviKvsObject *ob;
+ QString szLabel;
+ kvs_hobject_t hObject;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("page_widget",KVS_PT_HOBJECT,0,hObject)
+ KVSO_PARAMETER("label",KVS_PT_STRING,0,szLabel)
+ KVSO_PARAMETERS_END(c)
+ ob=KviKvsKernel::instance()->objectController()->lookupObject(hObject);
+ if(!widget())return true;
+ if(!ob->object()->isWidgetType())
+ {
+ c->warning(__tr2qs("Can't add a non-widget object"));
+ return true;
+ }
+ ((KviTalWizard *)widget())->addPage(((QWidget *)(ob->object())),szLabel);
+ return true;
+}
+bool KviKvsObject_wizard::functioninsertPage(KviKvsObjectFunctionCall *c)
+{
+ KviKvsObject *ob;
+ QString szLabel;
+ kvs_int_t uIndex;
+ kvs_hobject_t hObject;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("page_widget",KVS_PT_HOBJECT,0,hObject)
+ KVSO_PARAMETER("label",KVS_PT_STRING,0,szLabel)
+ KVSO_PARAMETER("index",KVS_PT_UNSIGNEDINTEGER,0,uIndex)
+ KVSO_PARAMETERS_END(c)
+ ob=KviKvsKernel::instance()->objectController()->lookupObject(hObject);
+ if(!widget())return true;
+ if(!ob->object()->isWidgetType())
+ {
+ c->warning(__tr2qs("Can't add a non-widget object"));
+ return true;
+ }
+ ((KviTalWizard *)widget())->insertPage(((QWidget *)(ob->object())),szLabel,uIndex);
+ return true;
+}
+
+
+bool KviKvsObject_wizard::functionsetTitle(KviKvsObjectFunctionCall *c)
+{
+ KviKvsObject *ob;
+ QString szTitle;
+ kvs_hobject_t hObject;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("page_widget",KVS_PT_HOBJECT,0,hObject)
+ KVSO_PARAMETER("title",KVS_PT_STRING,0,szTitle)
+ KVSO_PARAMETERS_END(c)
+ ob=KviKvsKernel::instance()->objectController()->lookupObject(hObject);
+ if(!widget())return true;
+ if(!ob->object()->isWidgetType())
+ {
+ c->warning(__tr2qs("Widget object required"));
+ return true;
+ }
+ ((KviTalWizard *)widget())->setPageTitle(((QWidget *)(ob->object())),szTitle);
+ return true;
+}
+bool KviKvsObject_wizard::functionsetBackEnabled(KviKvsObjectFunctionCall *c)
+{
+ bool bEnabled;
+ KviKvsObject *ob;
+ kvs_hobject_t hObject;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("page_widget",KVS_PT_HOBJECT,0,hObject)
+ KVSO_PARAMETER("bEnabled",KVS_PT_BOOL,0,bEnabled)
+ KVSO_PARAMETERS_END(c)
+ ob=KviKvsKernel::instance()->objectController()->lookupObject(hObject);
+ if(!widget())return true;
+ if(!ob->object()->isWidgetType())
+ {
+ c->warning(__tr2qs("Widget object required"));
+ return true;
+ }
+ ((KviTalWizard *)widget())->setBackEnabled(((QWidget *)(ob->object())),bEnabled);
+ return true;
+}
+
+bool KviKvsObject_wizard::functionsetNextEnabled(KviKvsObjectFunctionCall *c)
+{
+ bool bEnabled;
+ KviKvsObject *ob;
+ kvs_hobject_t hObject;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("page_widget",KVS_PT_HOBJECT,0,hObject)
+ KVSO_PARAMETER("bEnabled",KVS_PT_BOOL,0,bEnabled)
+ KVSO_PARAMETERS_END(c)
+ ob=KviKvsKernel::instance()->objectController()->lookupObject(hObject);
+ if(!widget())return true;
+ if(!ob->object()->isWidgetType())
+ {
+ c->warning(__tr2qs("Widget object required"));
+ return true;
+ }
+ ((KviTalWizard *)widget())->setNextEnabled(((QWidget *)(ob->object())),bEnabled);
+ return true;
+}
+bool KviKvsObject_wizard::functionsetFinishEnabled(KviKvsObjectFunctionCall *c)
+{
+ bool bEnabled;
+ KviKvsObject *ob;
+ kvs_hobject_t hObject;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("page_widget",KVS_PT_HOBJECT,0,hObject)
+ KVSO_PARAMETER("bEnabled",KVS_PT_BOOL,0,bEnabled)
+ KVSO_PARAMETERS_END(c)
+ ob=KviKvsKernel::instance()->objectController()->lookupObject(hObject);
+ if(!widget())return true;
+ if(!ob->object()->isWidgetType())
+ {
+ c->warning(__tr2qs("Widget object required"));
+ return true;
+ }
+ ((KviTalWizard *)widget())->setFinishEnabled(((QWidget *)(ob->object())),bEnabled);
+ return true;
+}
+bool KviKvsObject_wizard::functionsetHelpEnabled(KviKvsObjectFunctionCall *c)
+{
+ bool bEnabled;
+ KviKvsObject *ob;
+ kvs_hobject_t hObject;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("page_widget",KVS_PT_HOBJECT,0,hObject)
+ KVSO_PARAMETER("bEnabled",KVS_PT_BOOL,0,bEnabled)
+ KVSO_PARAMETERS_END(c)
+ ob=KviKvsKernel::instance()->objectController()->lookupObject(hObject);
+ if(!widget())return true;
+ if(!ob->object()->isWidgetType())
+ {
+ c->warning(__tr2qs("Widget object required"));
+ return true;
+ }
+ ((KviTalWizard *)widget())->setHelpEnabled(((QWidget *)(ob->object())),bEnabled);
+ return true;
+}
+bool KviKvsObject_wizard::functionsetBackBtnText(KviKvsObjectFunctionCall *c)
+{
+ QString szText;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("text",KVS_PT_STRING,0,szText)
+ KVSO_PARAMETERS_END(c)
+ if (widget())
+ ((KviTalWizard *)widget())->KviTalWizard::backButton()->setText(szText);
+ return true;
+}
+bool KviKvsObject_wizard::functionsetNextBtnText(KviKvsObjectFunctionCall *c)
+{
+ QString szText;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("text",KVS_PT_STRING,0,szText)
+ KVSO_PARAMETERS_END(c)
+ if (widget())
+ ((KviTalWizard *)widget())->KviTalWizard::nextButton()->setText(szText);
+ return true;
+}
+bool KviKvsObject_wizard::functionsetHelpBtnText(KviKvsObjectFunctionCall *c)
+{
+ QString szText;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("text",KVS_PT_STRING,0,szText)
+ KVSO_PARAMETERS_END(c)
+ if (widget())
+ ((KviTalWizard *)widget())->KviTalWizard::helpButton()->setText(szText);
+ return true;
+}
+bool KviKvsObject_wizard::functionsetFinishBtnText(KviKvsObjectFunctionCall *c)
+{
+ QString szText;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("text",KVS_PT_STRING,0,szText)
+ KVSO_PARAMETERS_END(c)
+ if (widget())
+ ((KviTalWizard *)widget())->KviTalWizard::finishButton()->setText(szText);
+ return true;
+}
+bool KviKvsObject_wizard::accept()
+{
+ KviKvsVariantList * pParams = 0;
+ callFunction(this,"acceptEvent",0,pParams);
+ return true;
+}
+bool KviKvsObject_wizard::reject()
+{
+ KviKvsVariantList * pParams = 0;
+ callFunction(this,"rejectEvent",0,pParams);
+ return true;
+}
+bool KviKvsObject_wizard::functionnextClickedEvent(KviKvsObjectFunctionCall *c)
+{
+ emitSignal("nextClicked",c);
+ return true;
+}
+
+void KviKvsObject_wizard::nextClicked()
+{
+ KviKvsVariantList *params=0;
+ callFunction(this,"nextClickedEvent",params);
+}
+bool KviKvsObject_wizard::functionbackClickedEvent(KviKvsObjectFunctionCall *c)
+{
+ emitSignal("backClicked",c);
+ return true;
+}
+
+void KviKvsObject_wizard::backClicked()
+{
+ KviKvsVariantList *params=0;
+ callFunction(this,"backClickedEvent",params);
+}
+KviKvsMdmWizard::KviKvsMdmWizard(QWidget * par,const char * name,KviKvsObject_wizard * parent)
+:KviTalWizard(par)
+{
+ m_pParentScript=parent;
+ connect (this->backButton(),SIGNAL(clicked()),this,SLOT(slotBackClicked()));
+ connect (this->nextButton(),SIGNAL(clicked()),this,SLOT(slotNextClicked()));
+}
+void KviKvsMdmWizard::accept()
+{
+ if(m_pParentScript->accept())KviTalWizard::accept();
+
+}
+void KviKvsMdmWizard::reject()
+{
+ if(m_pParentScript->reject())KviTalWizard::reject();
+
+}
+void KviKvsMdmWizard::slotNextClicked()
+{
+ m_pParentScript->nextClicked();
+}
+void KviKvsMdmWizard::slotBackClicked()
+{
+ m_pParentScript->backClicked();
+}
+KviKvsMdmWizard::~KviKvsMdmWizard()
+{
+}
+#include "m_class_wizard.moc"
diff --git a/src/modules/objects/class_wizard.h b/src/modules/objects/class_wizard.h
new file mode 100644
index 00000000..0c605efe
--- /dev/null
+++ b/src/modules/objects/class_wizard.h
@@ -0,0 +1,79 @@
+#ifndef _CLASS_WIZARD_H_
+#define _CLASS_WIZARD_H_
+//
+// File : class_wizard.h
+// Creation date : Fri Jan 28 14:21:48 CEST 2005
+// by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+#include <kvi_tal_wizard.h>
+#include "class_widget.h"
+
+
+#include "object_macros.h"
+
+class KviKvsObject_wizard : public KviKvsObject_widget
+{
+public:
+ KVSO_DECLARE_OBJECT(KviKvsObject_wizard)
+public:
+ QWidget * widget() { return (QWidget *)object(); };
+ bool accept();
+ bool reject();
+ void nextClicked();
+ void backClicked();
+
+
+protected:
+ virtual bool init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams);
+
+ bool functionaddPage(KviKvsObjectFunctionCall *c);
+ bool functioninsertPage(KviKvsObjectFunctionCall *c);
+ bool functionremovePage(KviKvsObjectFunctionCall *c);
+ bool functionsetTitle(KviKvsObjectFunctionCall *c);
+ bool functionsetBackEnabled(KviKvsObjectFunctionCall *c);
+ bool functionsetNextEnabled(KviKvsObjectFunctionCall *c);
+ bool functionsetFinishEnabled(KviKvsObjectFunctionCall *c);
+ bool functionsetHelpEnabled(KviKvsObjectFunctionCall *c);
+
+ bool functionsetBackBtnText(KviKvsObjectFunctionCall *c);
+ bool functionsetNextBtnText(KviKvsObjectFunctionCall *c);
+ bool functionsetFinishBtnText(KviKvsObjectFunctionCall *c);
+ bool functionsetHelpBtnText(KviKvsObjectFunctionCall *c);
+
+ bool functionnextClickedEvent(KviKvsObjectFunctionCall *c);
+ bool functionbackClickedEvent(KviKvsObjectFunctionCall *c);
+
+};
+class KviKvsMdmWizard : public KviTalWizard
+
+{
+ Q_OBJECT
+public:
+ KviKvsMdmWizard(QWidget * par,const char * name,KviKvsObject_wizard *);
+ void accept();
+ void reject();
+ virtual ~KviKvsMdmWizard();
+protected:
+ KviKvsObject_wizard *m_pParentScript;
+protected slots:
+ void slotNextClicked();
+ void slotBackClicked();
+};
+#endif //!_CLASS_WIZARD_H_
diff --git a/src/modules/objects/class_workspace.cpp b/src/modules/objects/class_workspace.cpp
new file mode 100644
index 00000000..1f6d8a3e
--- /dev/null
+++ b/src/modules/objects/class_workspace.cpp
@@ -0,0 +1,262 @@
+//mdm:
+// File : class_workspace.cpp
+// Creation date : Sat Feb 12 23:01:48 CEST 2005
+// by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor).
+// Thanks to Lucia Papini (^ashura^) for English help.
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+
+#include <qworkspace.h>
+#include "class_workspace.h"
+#include "kvi_error.h"
+#include "kvi_debug.h"
+
+#include "kvi_locale.h"
+#include "kvi_iconmanager.h"
+
+/*
+ @doc: workspace
+ @keyterms:
+ workspace object class,
+ @title:
+ workspace class
+ @type:
+ class
+ @short:
+ Provides a MDI workspace object
+ @inherits:
+ [class]object[/class]
+ [class]widget[/class]
+ @description:
+ This widget provides a workspace window that can contain decorated window.
+ @functions:
+ !fn: <object> $activeWindow()
+ Returns the active window, or 0 if no window is active.
+ !fn: <boolean> $scrollBarsEnabled()
+ Returns TRUE if the workspace provides scrollbars; otherwise returns FALSE.
+ !fn: $setscrollBarsEnabled(<bEnabled:boolean>)
+ Sets whether the workspace provides scrollbars to enable. (bEnabled 1 or 0)
+ !fn: $cascade()
+ Arranges all the child windows in a cascade pattern.
+ !fn: $tile()
+ Arranges all child windows in a tile pattern.
+ !fn: $closeActiveWindow()
+ Closes the child window that is currently active.
+ !fn: $closeAllWindows()
+ Closes all child windows.
+ !fn: $activateNextWindow()
+ Activates the next window in the child window chain.
+ !fn: $activatePrevWindow()
+ Activates the prev window in the child window chain.[br]
+
+ |----CLASS EXAMPLE----|[br]
+ |-Start:[br]
+ #Let's start.[br]
+ #We start the main class creation, in the constructor we do the[br]
+ #widget's showing, to give a particular pop-up[br]
+ #creation appearance.[br]
+ class (ws,widget)[br]
+ {[br]
+ constructor[br]
+ {[br]
+ $$->$setGeometry(%X,%Y,100,100)[br]
+ $$->%label=$new(label,$$)[br]
+ $$->%label->$settext("Another class by N\&G")[br]
+ $$->%label->$setautoresize(1)[br]
+ $$->$show()[br]
+ }[br]
+ }[br]
+ #We create the new workspace, and we set a 640x480 size with widget $resize[br]
+ #command.[br]
+ %Workspace=$new(workspace)[br]
+ %Workspace->$resize(640,480)[br]
+ #Now we make a cycling costruction of the widgets(look at the class),[br]
+ #and give to the widgets a random X and Y coordinates.[br]
+ #It takes few seconds to show the effects, be patient.[br]
+ %I=0[br]
+ while (%I<100)[br]
+ {[br]
+ %X=$rand(500)[br]
+ %Y=$rand(480)[br]
+ %Widget=$new(ws,%Workspace)[br]
+ %I++[br]
+ }[br]
+ #Let's show the fireworks! EnJoY![br]
+ %Workspace->$show()[br]
+ |-Start:[br]
+ |-|EXAMPLE n2:[br]
+ #This is like the first example but it has a particular animation effect.[br]
+ %Hex[]=$array(0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F)[br]
+ class (ws,widget)[br]
+ {[br]
+ constructor[br]
+ {[br]
+ $$->$setGeometry(%X,%Y,100,100)[br]
+ $$->%lay=$new(layout,$$)[br]
+ %i=0[br]
+ while (%i<10)[br]
+ {[br]
+ $$->%label=$new(label,$$)[br]
+ $$->%label->$settext("Another class by N\&G")[br]
+ %color=%Hex[$rand(15)]%Hex[$rand(15)]%Hex[$rand(15)]%Hex[$rand(15)]%Hex[$rand(15)]%Hex[$rand(15)][br]
+ $$->%label->$setforegroundcolor(%color)[br]
+ $$->%label->$setautoresize(1)[br]
+ $$->%lay->$addwidget($$->%label,%i,0)[br]
+ %i++;[br]
+ }[br]
+ $$->$show()[br]
+ }[br]
+ mousepressevent[br]
+ {[br]
+ if ($istimer(cycle) == 1) killtimer cycle[br]
+ }[br]
+ }[br]
+ %Workspace=$new(workspace)[br]
+ %Workspace->$resize(640,480)[br]
+ %Workspace->$setCaption("Hit the mouse to stop cycling windows....")[br]
+ %I=0[br]
+ %Cicle=1[br]
+ while (%I<20)[br]
+ {[br]
+ %X=$rand(500)[br]
+ %Y=$rand(480)[br]
+ %Widget=$new(ws,%Workspace)[br]
+ %I++[br]
+ }[br]
+ %Workspace->$show[br]
+ timer (cycle,3000)[br]
+ {[br]
+ if (%Cicle==1) %Workspace->$tile()[br]
+ if (%Cicle==2)[br]
+ {[br]
+ %Workspace->$cascade()[br]
+ %Cicle=1[br]
+ return[br]
+ }[br]
+ %Cicle++[br]
+ }[br]
+ privateimpl(%Workspace,mousepressevent)[br]
+ {[br]
+ if ($istimer(cycle) == 1) killtimer cycle[br]
+ }[br]
+ #-|End.[br]
+
+*/
+
+KVSO_BEGIN_REGISTERCLASS(KviKvsObject_workspace,"workspace","widget")
+ KVSO_REGISTER_HANDLER(KviKvsObject_workspace,"activeWindow", functionactiveWindow);
+ KVSO_REGISTER_HANDLER(KviKvsObject_workspace,"scrollBarsEnabled", functionscrollBarsEnabled);
+ KVSO_REGISTER_HANDLER(KviKvsObject_workspace,"setscrollBarsEnabled", functionsetscrollBarsEnabled);
+ KVSO_REGISTER_HANDLER(KviKvsObject_workspace,"cascade", functioncascade);
+ KVSO_REGISTER_HANDLER(KviKvsObject_workspace,"tile", functiontile);
+ KVSO_REGISTER_HANDLER(KviKvsObject_workspace,"closeActiveWindow", functioncloseActiveWindow);
+ KVSO_REGISTER_HANDLER(KviKvsObject_workspace,"closeAllWindows", functioncloseAllWindows);
+ KVSO_REGISTER_HANDLER(KviKvsObject_workspace,"activateNextWindow", functionactivateNextWindow);
+ KVSO_REGISTER_HANDLER(KviKvsObject_workspace,"activatePrevWindow", functionactivatePrevWindow);
+KVSO_END_REGISTERCLASS(KviKvsObject_workspace)
+
+KVSO_BEGIN_CONSTRUCTOR(KviKvsObject_workspace,KviKvsObject_widget)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_workspace)
+
+
+KVSO_BEGIN_DESTRUCTOR(KviKvsObject_workspace)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_workspace)
+
+bool KviKvsObject_workspace::init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams)
+{
+ setObject(new QWorkspace(parentScriptWidget(), name()), true);
+ return true;
+}
+
+bool KviKvsObject_workspace::functionactiveWindow(KviKvsObjectFunctionCall *c)
+{
+ //if(widget()) c->returnValue()->setHObject((unsigned long)(((QWorkspace *)widget())->activeWindow()));
+ // FIXME!
+ c->returnValue()->setHObject(0);
+ return true; //?pFIX ME?
+}
+
+bool KviKvsObject_workspace::functionscrollBarsEnabled(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ c->returnValue()->setBoolean(((QWorkspace *)widget())->scrollBarsEnabled());
+ return true;
+}
+
+bool KviKvsObject_workspace::functionsetscrollBarsEnabled(KviKvsObjectFunctionCall *c)
+{
+ bool bEnabled;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("bEnabled",KVS_PT_BOOL,0,bEnabled)
+ KVSO_PARAMETERS_END(c)
+ if(widget())
+ ((QWorkspace *)widget())->setScrollBarsEnabled(bEnabled);
+ return true;
+}
+
+bool KviKvsObject_workspace::functioncascade(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ ((QWorkspace *)widget())->cascade();
+ return true;
+}
+
+bool KviKvsObject_workspace::functiontile(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ ((QWorkspace *)widget())->tile();
+ return true;
+}
+
+bool KviKvsObject_workspace::functioncloseActiveWindow(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ ((QWorkspace *)widget())->closeActiveWindow();
+ return true;
+}
+
+bool KviKvsObject_workspace::functioncloseAllWindows(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ ((QWorkspace *)widget())->closeAllWindows();
+ return true;
+}
+
+bool KviKvsObject_workspace::functionactivateNextWindow(KviKvsObjectFunctionCall *c)
+{
+ if(widget())
+ ((QWorkspace *)widget())->activateNextWindow();
+ return true;
+}
+
+bool KviKvsObject_workspace::functionactivatePrevWindow(KviKvsObjectFunctionCall *c)
+{
+ if(widget()){
+ #ifdef COMPILE_USE_QT4
+ ((QWorkspace *)widget())->activatePreviousWindow();
+ #else
+ ((QWorkspace *)widget())->activatePrevWindow();
+ #endif
+ }
+ return true;
+}
diff --git a/src/modules/objects/class_workspace.h b/src/modules/objects/class_workspace.h
new file mode 100644
index 00000000..c18264df
--- /dev/null
+++ b/src/modules/objects/class_workspace.h
@@ -0,0 +1,53 @@
+#ifndef _CLASS_WORKSPACE_H_
+#define _CLASS_WORKSPACE_H_
+//mdm:
+// File : class_workspace.h
+// Creation date : Sat Feb 12 23:05:58 CEST 2005
+// by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+
+
+#include <qworkspace.h>
+#include "class_widget.h"
+
+class KviKvsObject_workspace : public KviKvsObject_widget
+{
+public:
+ KVSO_DECLARE_OBJECT(KviKvsObject_workspace)
+public:
+ QWidget * widget() { return (QWidget *)object(); };
+protected:
+
+ virtual bool init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams);
+
+ bool functionactiveWindow(KviKvsObjectFunctionCall *c);
+ bool functionscrollBarsEnabled(KviKvsObjectFunctionCall *c);
+ bool functionsetscrollBarsEnabled(KviKvsObjectFunctionCall *c);
+ bool functioncascade(KviKvsObjectFunctionCall *c);
+ bool functiontile(KviKvsObjectFunctionCall *c);
+ bool functioncloseActiveWindow(KviKvsObjectFunctionCall *c);
+ bool functioncloseAllWindows(KviKvsObjectFunctionCall *c);
+ bool functionactivateNextWindow(KviKvsObjectFunctionCall *c);
+ bool functionactivatePrevWindow(KviKvsObjectFunctionCall *c);
+};
+
+#endif //!_CLASS_WORKSPACE_H_
diff --git a/src/modules/objects/class_wrapper.cpp b/src/modules/objects/class_wrapper.cpp
new file mode 100644
index 00000000..02ff632c
--- /dev/null
+++ b/src/modules/objects/class_wrapper.cpp
@@ -0,0 +1,269 @@
+//mdm:
+// File : class_wrapper.cpp
+// Creation date : Fri Jan 28 14:21:48 CEST 2005
+// by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "class_wrapper.h"
+#include "kvi_error.h"
+#include "kvi_debug.h"
+
+#include "kvi_locale.h"
+#include "kvi_iconmanager.h"
+
+#include "class_widget.h"
+#include <qwidget.h>
+#ifndef COMPILE_USE_QT4
+ #include <qobjectlist.h>
+ #include <qwidgetlist.h>
+#endif
+#include "kvi_app.h"
+#include "kvi_frame.h"
+
+
+/*
+ @doc: wrapper
+ @keyterms:
+ wrapper object class,
+ @title:
+ wrapper class
+ @type:
+ class
+ @short:
+ Provides a wrapper class that hooks to an existing Qt graphic object modifying it.
+ @inherits:
+ [class]object[/class]
+ [class]widget[/class]
+ @description:
+ This is a class for advanced KVIrc scripting.[br]
+ It can wrap any existing KVIrc widget.[br]
+ This class allows some unbelievable changes to the whole graphic environment of the kvirc,[br]
+ in fact, could hook every widget, you can modify the property or you can be inserted other widget as child of this...[br]
+ in short you have absolute liberty. [br]
+ The power of this class is fantastic, because it allows the change at "run time" of almost all the elements of the Kvirc.[br]
+ But to use this class in optimal way and to exploit its power, you have to know the Qt.... so you won't have limits [br]
+ The KVIrc Qt widgets are arranged in trees (just as the objects).[br]
+ The difference is that there are more toplevel widgets (and so more than one tree).[br]
+ You can use [fnc]$objects.dump()[/fnc] to take a look at the KVIrc Qt objects tree.[br]
+ Here is a part of the tree:[br][br]
+ Ptr 14332520: top level object: kvirc_frame, class KviFrame, visible, rect = -4, -4, 1024, 708
+ Ptr 17296024: object: qt_top_dock, class QDockArea
+ Ptr 14882136: object: qt_custom_toolbar, class KviCustomToolBar
+ Ptr 18143368: object: qt_dockwidget_internal, class QDockWindowTitleBar
+ [br][br]
+ Every listed widget has a "name", a "class" and a set of properties.[br]
+ The first entry in this example is a KVIrc server window, class "KviFrame" and name "kvirc_frame":
+ it is a toplevel widget.[br]
+ The "qt_top_dock", "qt_custom_toolbar" and the "qt_dockwidget_internal" are
+ direct children of that widget.[br]
+ To indicate a specific widget we will use the "class::name" form.[br]
+ So to indicate the main KVIrc frame you will use "KviFrame::kvirc_main_frame".
+ Look at this example:[br]
+ %A=$new(wrapper,0,test,KviFrame::kvirc_frame,KviStatusBar::unnamed)[br]
+ %A->$setBackGroundColor(FFFFFF)[br]
+ For first thing we create an object type wrapper,then we flow the tree that there from the command /object.dump and we will have:[br]
+ . [br]
+ . [br]
+ Ptr 14196288: top level object: kvirc_frame, class KviFrame, visible, rect = -4, -4, 1024, 712 [br]
+. [br]
+ Ptr 17197360: object: unnamed, class KviStatusBar [br]
+ . [br]
+ . [br]
+ in this way we can follow the order, father->child from the top-level widget(KviFrame::kvirc_frame)[br]
+ to reach the child that interests us (KviStatusBar::unnamed)[br]
+ Then, following the syntax we will have:
+ %A=$new(wrapper,0,test,KviFrame::kvirc_frame,KviStatusBar::unnamed)
+ Now %A. will be point to the wrapped object, therefore we could modify its property or to consider it as if it were an object created by us in scripting. [br]
+ Obviously, deleting the created object (for example %A) you don't will delete the object of Kvirc (in this case the statusbar). [br]
+ Another example could be this:[br]
+ %A=$new(wrapper,0,test,KviFrame::kvirc_frame,QToolButton::kvirc.identityoptions)[br]
+ %A->$setProperty(usesBigPixmap,0)[br]
+ In this fool example with the function $setProperty, we has setted the property usesBigPixmap to False, making to become the small icons of the ToolBar.[br]
+ [br]
+ The wrapping object search can optionally start with a window
+ identifier with the following syntax: WinId::<window_id>.
+
+*/
+
+
+
+KVSO_BEGIN_REGISTERCLASS(KviKvsObject_wrapper,"wrapper","widget")
+
+KVSO_END_REGISTERCLASS(KviKvsObject_wrapper)
+
+KVSO_BEGIN_CONSTRUCTOR(KviKvsObject_wrapper,KviKvsObject_widget)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_wrapper)
+
+
+KVSO_BEGIN_DESTRUCTOR(KviKvsObject_wrapper)
+
+KVSO_END_CONSTRUCTOR(KviKvsObject_wrapper)
+
+bool KviKvsObject_wrapper::init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams)
+{
+ if( !pParams ) return false;
+
+ debug ("ci sono i parametri");
+ QWidget *pWidget = 0;
+ int i=0;
+ while(i!=pParams->count())
+ {
+ QString szClass;
+ QString szName;
+ QString s=0;
+ pParams->at(i)->asString(s);
+ if (!s.isEmpty())
+ {
+ int idx = s.find("::");
+ if( idx != -1 ) {
+ szClass = s.left(idx);
+ szName = s.right(s.length() - idx - 2);
+ } else {
+ szClass = s;
+ szName = "";
+ }
+ debug ("szClass %s",szClass.latin1());
+ debug ("szName %s",szName.latin1());
+ debug ("s %s",s.latin1());
+
+ if(KviQString::equalCI(szClass,"WinId"))
+ {
+ if(pWidget)
+ {
+ pContext->warning(__tr2qs("The window identifier preceeded by WinId must be the first object in the search path"));
+ return false;
+ } else {
+ pWidget = g_pApp->findWindow(szName);
+ }
+ } else {
+ if(pWidget) {
+ pWidget = findWidgetToWrap(
+ !szClass.isEmpty() ? szClass : KviQString::empty, !szName.isEmpty() ? szName : KviQString::empty, pWidget
+ );
+ } else {
+ pWidget = findTopLevelWidgetToWrap(szClass.isEmpty() ? szClass : KviQString::empty, !szName.isEmpty() ? szName : KviQString::empty);
+ }
+ }
+ if( !pWidget )
+ {
+ pContext->warning(__tr2qs("Failed to find one of the wrap path widgets (%Q::%Q)"),&szClass,&szName);
+ return false;
+ }
+ }
+ i++;
+
+ }
+ if( !pWidget )
+ {
+ pContext->warning(__tr2qs("Failed to find the widget to wrap"));
+ return false;
+ }
+ setObject(pWidget,false);
+
+ return true;
+}
+QWidget *KviKvsObject_wrapper::findTopLevelWidgetToWrap(const QString szClass, const QString szName)
+{
+#ifdef COMPILE_USE_QT4
+ QWidgetList list = g_pApp->topLevelWidgets();
+ if( !list.count() ) return 0;
+ for(int idx=0;idx<list.count();idx++)
+ {
+ bool bNameMatch = false;
+ bool bClassMatch = false;
+ if( !szName.isEmpty() )
+ bNameMatch = KviQString::equalCI(list.at(idx)->name(), szName);
+ else
+ bNameMatch = true;
+ if( !szClass.isEmpty())
+ bClassMatch = KviQString::equalCI(list.at(idx)->className(), szClass);
+ else
+ bClassMatch = true;
+ if( bNameMatch && bClassMatch ) {
+ QWidget *w = list.at(idx);
+ return w;
+ }
+ }
+ return 0;
+#else
+
+ QWidgetList *list = g_pApp->topLevelWidgets();
+ if( !list ) return 0;
+
+ QWidgetListIt it(*list);
+ while( it.current() ) {
+ bool bNameMatch = false;
+ bool bClassMatch = false;
+ if( szName )
+ bNameMatch = KviQString::equalCI(it.current()->name(), szName);
+ else
+ bNameMatch = true;
+ if( szClass )
+ bClassMatch = KviQString::equalCI(it.current()->className(), szClass);
+ else
+ bClassMatch = true;
+ if( bNameMatch && bClassMatch ) {
+ QWidget *w = it.current();
+ delete list;
+ return w;
+ }
+ ++it;
+ }
+ delete list;
+
+ return 0;
+#endif
+}
+
+QWidget *KviKvsObject_wrapper::findWidgetToWrap(const char *szClass, const char *szName, QWidget *childOf)
+{
+#ifdef COMPILE_USE_QT4
+ QObjectList list = childOf->queryList(szClass ? szClass : 0, szName ? szName : 0, false, true);
+ if( !list.count() ) return 0;
+ for(int idx=0;idx<list.count();idx++)
+ {
+ if( list.at(idx)->isWidgetType() ) {
+ QWidget *w = (QWidget *)list.at(idx);
+ return w;
+ }
+
+ }
+ return 0;
+#else
+
+ QObjectList *list = childOf->queryList(szClass ? szClass : 0, szName ? szName : 0, false, true);
+ if( !list ) return 0;
+
+ QObjectListIt it(*list);
+ while( it.current() ) {
+ if( it.current()->isWidgetType() ) {
+ QWidget *w = (QWidget *) it.current();
+ delete list;
+ return w;
+ }
+ ++it;
+ }
+ delete list;
+ return 0;
+#endif
+}
+
+#include "m_class_wrapper.moc"
diff --git a/src/modules/objects/class_wrapper.h b/src/modules/objects/class_wrapper.h
new file mode 100644
index 00000000..900b0672
--- /dev/null
+++ b/src/modules/objects/class_wrapper.h
@@ -0,0 +1,53 @@
+#ifndef _CLASS_WRAPPER_H_
+#define _CLASS_WRAPPER_H_
+//
+// File : class_wrapper.h
+// Creation date : Fri Jan 28 14:21:48 CEST 2005
+// by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor)
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+
+
+#include "class_widget.h"
+#include "qlistview.h"
+
+
+
+
+#include "object_macros.h"
+
+class KviKvsObject_wrapper : public KviKvsObject_widget
+{
+ Q_OBJECT
+public:
+ KVSO_DECLARE_OBJECT(KviKvsObject_wrapper)
+public:
+ QWidget * widget() { return (QWidget *)object(); };
+protected:
+ virtual bool init(KviKvsRunTimeContext * pContext,KviKvsVariantList *pParams);
+ QWidget * findTopLevelWidgetToWrap(const QString szClass, const QString szName);
+ QWidget * findWidgetToWrap(const char *szClass, const char *szName, QWidget *childOf);
+
+};
+
+
+
+#endif //!_CLASS_WRAPPER_H_
diff --git a/src/modules/objects/class_xmlreader.cpp b/src/modules/objects/class_xmlreader.cpp
new file mode 100644
index 00000000..f4bccc8f
--- /dev/null
+++ b/src/modules/objects/class_xmlreader.cpp
@@ -0,0 +1,343 @@
+//=============================================================================
+//
+// File : class_xmlreader.cpp
+// Created on Tue 27 Dec 2005 00:14:09 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "class_xmlreader.h"
+
+#include "kvi_locale.h"
+
+#include "kvi_kvs_variantlist.h"
+#include "kvi_kvs_hash.h"
+
+#include "kvi_qstring.h"
+
+
+/*
+ @doc: xmlreader
+ @keyterms:
+ xml
+ @title:
+ xmlreader class
+ @type:
+ class
+ @short:
+ A simple xml document parser
+ @inherits:
+ [class]object[/class]
+ @description:
+ This class implements a really simple xml document parser.
+ You will usually derive your own class from this one and reimplement
+ some of the events that it triggers.
+ You will typically reimplement [classfnc:xmlparser]onElementStart[/classfnc]()
+ and [classfnc:xmlparser]onElementEnd[/classfnc]() that will be called
+ during the execution of [classfnc:xmlparser]$parse[/classfnc]() in an order
+ reflecting the order of elements in the parsed document.
+ @functions:
+ !fn: <boolean> $parse(<xml_data:string>)
+ Call this function to parse a string that contains an XML document.
+ A typical call for this method will look like:
+ [example]
+ %x = [fnc]$new[/fnc](xmlparser)
+ %x->$parse([fnc]$file.read[/fnc]("/home/somefile.xml"))
+ [/example]
+ During the call the <xml_data> string will be parsed and the
+ relevant on* events (see below) will be triggered.
+ $parse will return $true when the parsing terminates succesfully
+ or $false if it aborts for some reason (unrecoverable error
+ in the document, user abort etc...).
+ If this function return $false then you can call $lastError() to
+ obtain a descriptive error message.
+
+ !fn: <string> $lastError()
+ Returns the last error occured inside the parser.
+ You will typically call this function when $parse() above returns $false.
+
+ !fn: <boolean> $onDocumentStart()
+ This function is called when the document parsing starts.
+ You can reimplement it in order to handle this notification.
+ You should return $true if you want document parsing to continue
+ and $false if you want it to be aborted.
+ The default implementation does nothing besides returning $true.
+
+ !fn: <boolean> $onDocumentEnd()
+ This function is called when the document parsing terminates succesfully.
+ You can reimplement it in order to handle this notification.
+ You should return $true if you want document parsing to continue
+ and $false if you want it to be aborted.
+ The default implementation does nothing besides returning $true.
+
+ !fn: <boolean> $onElementStart(<qualified_name:string>,<attributes:hash>,<namespace:string>,<local_name:string>)
+ This function is called when an element opening tag is encountered.
+ The <qualified_name> of the tag is passed as the first parameter.
+ The <attributes> are passed in the form of a hash with attribute
+ values indexed by their names.
+ When the <qualified_name> contains a namespace then it is also reported
+ in the splitted <namespace> <local_name> pair.
+ You should return $true if you want document parsing to continue
+ and $false if you want it to be aborted.
+ The default implementation does nothing besides returning $true.
+
+ !fn: <boolean> $onElementEnd(<qualified_name:string>,<namespace:string>,<local_name:string>)
+ This function is called when an element closing tag is encountered.
+ The <qualified_name> of the tag is passed as the first parameter.
+ When the <qualified_name> contains a namespace then it is also reported
+ in the splitted <namespace> <local_name> pair.
+ You should return $true if you want document parsing to continue
+ and $false if you want it to be aborted.
+ The default implementation does nothing besides returning $true.
+
+ !fn: <boolean> $onText($0 = <text:string>)
+ This function is called when a chunk of text is encountered inside the document.
+ The parsed <text> chunk is passed as the first parameter.
+ You should return $true if you want document parsing to continue
+ and $false if you want it to be aborted.
+ The default implementation does nothing besides returning $true.
+
+ !fn: <boolean> $onWarning(<message:string>)
+ This function is called when the parser generates a recoverable error.
+ The error <message> is passed as the first parameter.
+ You should return $true if you want document parsing to continue
+ and $false if you want it to be aborted.
+ The default implementation does nothing besides returning $true.
+
+ !fn: <boolean> $onError(<message:string>)
+ This function is called when the parser generates an unrecoverable error.
+ The error <message> is passed as the first parameter.
+ The document parsing can't continue.
+ The default implementation does nothing besides returning $true.
+*/
+
+
+#ifndef QT_NO_XML
+
+#include <qxml.h>
+
+class KviXmlHandler : public QXmlDefaultHandler
+{
+protected:
+ KviKvsObject_xmlreader * m_pReader;
+ QString m_szErrorString;
+public:
+ KviXmlHandler(KviKvsObject_xmlreader * pReader)
+ {
+ m_pReader = pReader;
+ }
+ ~KviXmlHandler()
+ {
+ }
+private:
+ bool kvsCodeFailure()
+ {
+ m_szErrorString = __tr2qs("Error in KVS class implementation: processing aborted");
+ return false;
+ }
+ bool kvsCodeAbort()
+ {
+ m_szErrorString = __tr2qs("Processing aborted");
+ return false;
+ }
+ void decodeException(QString &szMsg,bool bError,const QXmlParseException &exception)
+ {
+ if(bError)
+ KviQString::sprintf(szMsg,__tr2qs("Error near line %d, column %d"),exception.lineNumber(),exception.columnNumber());
+ else
+ KviQString::sprintf(szMsg,__tr2qs("Warning near line %d, column %d"),exception.lineNumber(),exception.columnNumber());
+ szMsg += ": ";
+ szMsg += exception.message();
+ }
+ bool handleKvsCallReturnValue(KviKvsVariant * pRetVal)
+ {
+ if(!pRetVal->asBoolean())return kvsCodeAbort();
+ return true;
+ }
+public:
+ virtual bool startDocument()
+ {
+ KviKvsVariant ret;
+ if(!m_pReader->callFunction(m_pReader,"onDocumentStart",&ret))
+ return kvsCodeFailure();
+ return handleKvsCallReturnValue(&ret);
+ }
+
+ virtual bool endDocument()
+ {
+ KviKvsVariant ret;
+ if(!m_pReader->callFunction(m_pReader,"onDocumentEnd",&ret))
+ return kvsCodeFailure();
+ return handleKvsCallReturnValue(&ret);
+ }
+
+ virtual bool startElement(const QString &szNamespaceUri,const QString &szLocalName,const QString &szQualifiedName,const QXmlAttributes &attrs)
+ {
+ KviKvsVariant ret;
+ KviKvsVariantList par;
+ par.setAutoDelete(true);
+ par.append(new KviKvsVariant(szQualifiedName));
+ KviKvsHash * pHash = new KviKvsHash();
+ par.append(new KviKvsVariant(pHash));
+ par.append(new KviKvsVariant(szNamespaceUri));
+ par.append(new KviKvsVariant(szLocalName));
+ int c = attrs.count();
+ for(int i=0;i<c;i++)
+ pHash->set(attrs.qName(i),new KviKvsVariant(attrs.value(i)));
+ if(!m_pReader->callFunction(m_pReader,"onElementStart",&ret,&par))
+ return kvsCodeFailure();
+ return handleKvsCallReturnValue(&ret);
+ }
+
+ virtual bool endElement(const QString &szNamespaceUri,const QString &szLocalName,const QString &szQualifiedName)
+ {
+ KviKvsVariant ret;
+ KviKvsVariantList par;
+ par.setAutoDelete(true);
+ par.append(new KviKvsVariant(szQualifiedName));
+ par.append(new KviKvsVariant(szNamespaceUri));
+ par.append(new KviKvsVariant(szLocalName));
+ if(!m_pReader->callFunction(m_pReader,"onElementEnd",&ret,&par))
+ return kvsCodeFailure();
+ return handleKvsCallReturnValue(&ret);
+ }
+
+ virtual bool characters(const QString &szChars)
+ {
+ KviKvsVariant ret;
+ KviKvsVariantList par;
+ par.setAutoDelete(true);
+ par.append(new KviKvsVariant(szChars));
+ if(!m_pReader->callFunction(m_pReader,"onText",&ret,&par))
+ return kvsCodeFailure();
+ return handleKvsCallReturnValue(&ret);
+ }
+
+ virtual bool warning(const QXmlParseException &exception)
+ {
+ // recoverable
+ QString szMsg;
+ decodeException(szMsg,false,exception);
+
+ KviKvsVariant ret;
+ KviKvsVariantList par;
+ par.setAutoDelete(true);
+ par.append(new KviKvsVariant(szMsg));
+ if(!m_pReader->callFunction(m_pReader,"onWarning",&ret,&par))
+ return kvsCodeFailure();
+ return handleKvsCallReturnValue(&ret);
+ }
+
+ virtual bool error(const QXmlParseException &exception)
+ {
+ // recoverable
+ QString szMsg;
+ decodeException(szMsg,false,exception);
+
+ KviKvsVariant ret;
+ KviKvsVariantList par;
+ par.setAutoDelete(true);
+ par.append(new KviKvsVariant(szMsg));
+ if(!m_pReader->callFunction(m_pReader,"onWarning",&ret,&par))
+ return kvsCodeFailure();
+ return handleKvsCallReturnValue(&ret);
+ }
+
+ virtual bool fatalError(const QXmlParseException &exception)
+ {
+ QString szMsg;
+ decodeException(szMsg,true,exception);
+ m_pReader->fatalError(szMsg);
+ return true;
+ }
+
+ virtual QString errorString()
+ {
+ return m_szErrorString;
+ }
+};
+
+#endif // !QT_NO_XML
+
+
+KVSO_BEGIN_REGISTERCLASS(KviKvsObject_xmlreader,"xmlreader","object")
+ KVSO_REGISTER_HANDLER(KviKvsObject_xmlreader,"lastError",function_lastError)
+ KVSO_REGISTER_HANDLER(KviKvsObject_xmlreader,"parse",function_parse)
+
+ KVSO_REGISTER_STANDARD_TRUERETURN_HANDLER(KviKvsObject_xmlreader,"onDocumentStart")
+ KVSO_REGISTER_STANDARD_TRUERETURN_HANDLER(KviKvsObject_xmlreader,"onDocumentEnd")
+ KVSO_REGISTER_STANDARD_TRUERETURN_HANDLER(KviKvsObject_xmlreader,"onElementStart")
+ KVSO_REGISTER_STANDARD_TRUERETURN_HANDLER(KviKvsObject_xmlreader,"onElementEnd")
+ KVSO_REGISTER_STANDARD_TRUERETURN_HANDLER(KviKvsObject_xmlreader,"onText")
+ KVSO_REGISTER_STANDARD_TRUERETURN_HANDLER(KviKvsObject_xmlreader,"onWarning")
+ KVSO_REGISTER_STANDARD_TRUERETURN_HANDLER(KviKvsObject_xmlreader,"onError")
+KVSO_END_REGISTERCLASS(KviKvsObject_xmlreader)
+
+KVSO_BEGIN_CONSTRUCTOR(KviKvsObject_xmlreader,KviKvsObject)
+KVSO_END_CONSTRUCTOR(KviKvsObject_xmlreader)
+
+KVSO_BEGIN_DESTRUCTOR(KviKvsObject_xmlreader)
+KVSO_END_DESTRUCTOR(KviKvsObject_xmlreader)
+
+void KviKvsObject_xmlreader::fatalError(const QString &szError)
+{
+ m_szLastError = szError;
+
+ KviKvsVariantList vArgs;
+ vArgs.append(new KviKvsVariant(m_szLastError));
+ callFunction(this,"onError",&vArgs);
+}
+
+bool KviKvsObject_xmlreader::function_parse(KviKvsObjectFunctionCall *c)
+{
+ QString szString;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("string",KVS_PT_STRING,0,szString)
+ KVSO_PARAMETERS_END(c)
+
+#ifdef QT_NO_XML
+ fatalError(__tr2qs("XML support not available in the Qt library"));
+ c->returnValue()->setBoolean(false);
+#else
+ m_szLastError = "";
+ KviXmlHandler handler(this);
+ QXmlInputSource source;
+ // We have a problem here.. most kvirc functions already interpret the data
+ // read from files. We should have binary data handling features to get this to work correctly.
+ // The following snippet of code tries to provide a best-effort workaround.
+ KviQCString utf8data = KviQString::toUtf8(szString);
+ QByteArray data = utf8data;
+ data.truncate(utf8data.length()); // don't include the null terminator in data
+ source.setData(data);
+ //debug("PARSING(%s) LEN(%d)",szString.utf8().data(),szString.utf8().length());
+ QXmlSimpleReader reader;
+ reader.setContentHandler(&handler);
+ reader.setErrorHandler(&handler);
+ c->returnValue()->setBoolean(reader.parse(source));
+#endif
+ return true;
+}
+
+bool KviKvsObject_xmlreader::function_lastError(KviKvsObjectFunctionCall *c)
+{
+ c->returnValue()->setString(m_szLastError);
+ return true;
+}
+
+#include "m_class_xmlreader.moc"
diff --git a/src/modules/objects/class_xmlreader.h b/src/modules/objects/class_xmlreader.h
new file mode 100644
index 00000000..dca69333
--- /dev/null
+++ b/src/modules/objects/class_xmlreader.h
@@ -0,0 +1,46 @@
+#ifndef _CLASS_XMLREADER_H_
+#define _CLASS_XMLREADER_H_
+//=============================================================================
+//
+// File : class_xmlreader.h
+// Created on Tue 27 Dec 2005 00:14:09 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+
+#include "object_macros.h"
+
+class KviKvsObject_xmlreader : public KviKvsObject
+{
+ Q_OBJECT
+public:
+ KVSO_DECLARE_OBJECT(KviKvsObject_xmlreader)
+public:
+ bool function_parse(KviKvsObjectFunctionCall *c);
+ bool function_lastError(KviKvsObjectFunctionCall *c);
+
+ void fatalError(const QString &szError);
+protected:
+ QString m_szLastError;
+};
+
+#endif //!_CLASS_XMLREADER_H_
diff --git a/src/modules/objects/libkviobjects.cpp b/src/modules/objects/libkviobjects.cpp
new file mode 100644
index 00000000..73eacace
--- /dev/null
+++ b/src/modules/objects/libkviobjects.cpp
@@ -0,0 +1,1066 @@
+//=============================================================================
+//
+// File : libkviobjects.cpp
+// Creation date : Wed Sep 09 2000 20:59:01 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_tal_listview.h"
+#include <qimage.h>
+#include "kvi_iconmanager.h"
+#include "kvi_window.h"
+#include "kvi_out.h"
+#include "kvi_mirccntrl.h"
+
+#include "kvi_app.h"
+
+#include "kvi_module.h"
+
+#include "kvi_locale.h"
+#include "kvi_error.h"
+#include "kvi_cmdformatter.h"
+#include "kvi_out.h"
+#include "kvi_app.h"
+#include "kvi_fileutils.h"
+#ifndef COMPILE_USE_QT4
+ #include <qwidgetlist.h>
+ #include <qobjectlist.h>
+#endif
+
+#include <qdir.h>
+
+#include "class_button.h"
+#include "class_checkbox.h"
+#include "class_urllabel.h"
+#include "class_lineedit.h"
+#include "class_multilineedit.h"
+#include "class_combobox.h"
+#include "class_widget.h"
+#include "class_list.h"
+#include "class_file.h"
+#include "class_socket.h"
+#include "class_layout.h"
+#include "class_menubar.h"
+#include "class_window.h"
+#include "class_listbox.h"
+#include "class_progressbar.h"
+#include "class_slider.h"
+#include "class_spinbox.h"
+#include "class_lcd.h"
+#include "class_radiobutton.h"
+#include "class_process.h"
+#include "class_groupbox.h"
+#include "class_buttongroup.h"
+#include "class_tabwidget.h"
+#include "class_workspace.h"
+#include "class_popupmenu.h"
+#include "class_listview.h"
+#include "class_listviewitem.h"
+#include "class_toolbar.h"
+#include "class_mainwindow.h"
+#include "class_toolbutton.h"
+#include "class_wizard.h"
+#include "class_tbrowser.h"
+#include "class_painter.h"
+#include "class_pixmap.h"
+#include "class_wrapper.h"
+#include "class_dialog.h"
+#include "class_xmlreader.h"
+#include "class_dockwindow.h"
+#include "class_vbox.h"
+#include "class_hbox.h"
+static void dumpChildObjects(KviWindow *pWnd, QObject *parent, const char *spacing, bool bWidgetsOnly, KviKvsArray *n, int &idx);
+
+static bool objects_module_cleanup(KviModule *m)
+{
+ KviKvsObject_process::unregisterSelf();
+ KviKvsObject_socket::unregisterSelf();
+ KviKvsObject_xmlreader::unregisterSelf();
+ KviKvsObject_wrapper::unregisterSelf();
+ KviKvsObject_file::unregisterSelf();
+ KviKvsObject_progressbar::unregisterSelf();
+ KviKvsObject_dockwindow::unregisterSelf();
+ KviKvsObject_wizard::unregisterSelf();
+ KviKvsObject_window::unregisterSelf();
+ KviKvsObject_urlabel::unregisterSelf();
+ KviKvsObject_toolbutton::unregisterSelf();
+ KviKvsObject_toolbar::unregisterSelf();
+ KviKvsObject_tabwidget::unregisterSelf();
+ KviKvsObject_spinbox::unregisterSelf();
+ KviKvsObject_slider::unregisterSelf();
+ KviKvsObject_radiobutton::unregisterSelf();
+ KviKvsObject_popupmenu::unregisterSelf();
+ KviKvsObject_pixmap::unregisterSelf();
+ KviKvsObject_painter::unregisterSelf();
+ KviKvsObject_mainwindow::unregisterSelf();
+ KviKvsObject_listviewitem::unregisterSelf();
+ KviKvsObject_listview::unregisterSelf();
+ KviKvsObject_listbox::unregisterSelf();
+ KviKvsObject_combobox::unregisterSelf();
+ KviKvsObject_workspace::unregisterSelf();
+ KviKvsObject_menubar::unregisterSelf();
+ KviKvsObject_lineedit::unregisterSelf();
+ KviKvsObject_lcd::unregisterSelf();
+ KviKvsObject_layout::unregisterSelf();
+ KviKvsObject_hbox::unregisterSelf();
+ KviKvsObject_vbox::unregisterSelf();
+ KviKvsObject_label::unregisterSelf();
+ KviKvsObject_buttongroup::unregisterSelf();
+ KviKvsObject_groupbox::unregisterSelf();
+ KviKvsObject_dialog::unregisterSelf();
+ KviKvsObject_checkbox::unregisterSelf();
+ KviKvsObject_textbrowser::unregisterSelf();
+ KviKvsObject_mledit::unregisterSelf();
+ KviKvsObject_button::unregisterSelf();
+ KviKvsObject_widget::unregisterSelf();
+ KviKvsObject_list::unregisterSelf();
+
+ return true;
+}
+
+
+static bool objects_kvs_cmd_killClass(KviKvsModuleCommandCall * c)
+{
+ /*
+ @doc: objects.killclass
+ @title:
+ objects.killclass
+ @type:
+ command
+ @short:
+ Removes a class definition
+ @syntax:
+ objects.killclass [-q] <classname:string>
+ @switches:
+ !sw: -q | --quiet
+ Suppresses any warning message
+ @description:
+ Removes the definition of the class <class_name>.[br]
+ All the instances of the class are killed (thus children objects are killed too).[br]
+ All the derived class definitions are removed as well.[br]
+ Builtin class definitions cannot be removed and this commands
+ kills only all the instances of that class (derived class definitions
+ and instances in this case are NOT killed).[br]
+ @seealso:
+ [cmd]class[/cmd], [cmd]objects.clear[/cmd], [fnc]$classDefined[/fnc](),
+ [doc:objects]Objects documentation[/doc]
+ */
+
+
+ QString szClass;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("class",KVS_PT_NONEMPTYSTRING,0,szClass)
+ KVSM_PARAMETERS_END(c)
+ KviKvsObjectClass * pClass=KviKvsKernel::instance()->objectController()->lookupClass(szClass);
+ if(pClass)
+ {
+ if(pClass->isBuiltin())
+ {
+ KviKvsKernel::instance()->objectController()->killAllObjectsWithClass(pClass);
+ } else {
+ KviKvsKernel::instance()->objectController()->deleteClass(pClass); //Yahoo!!
+ }
+ }
+ else if(!c->hasSwitch('q',"quiet"))c->warning(__tr2qs("Class '%Q' is not definited"),&szClass);
+ return true;
+}
+
+
+static bool objects_kvs_cmd_clearObjects(KviKvsModuleCommandCall * c)
+{
+ /*
+ @doc: objects.clear
+ @title:
+ objects.clear
+ @type:
+ command
+ @short:
+ Removes all the user class definitions
+ @syntax:
+ objects.clear [-i]
+ @description:
+ Removes the definition of all the user classes and kill all the object
+ instances (also instances of the builtin classes).[br]
+ If the -i switch is used, only the object instances are cleared
+ but the class definitions are left unchanged.[br]
+ This command should be used only for debugging & testing purposes
+ and in particular should be NEVER used from inside an object
+ function handler (leads to SIGSEGV :).[br]
+ @seealso:
+ [cmd]class[/cmd], [cmd]objects.killclass[/cmd],
+ [doc:objects]Objects documentation[/doc]
+ */
+
+ KviKvsKernel::instance()->objectController()->clearInstances();
+ if(!c->switches()->find('i',"ii")) KviKvsKernel::instance()->objectController()->clearUserClasses();
+ return true;
+}
+
+
+static bool objects_kvs_cmd_connect(KviKvsModuleCommandCall * c)
+{
+
+ /*
+ @doc: objects.connect
+ @title:
+ objects.connect
+ @type:
+ command
+ @short:
+ Connects a signal to a slot
+ @syntax:
+ objects.connect <source_object:hobject> <signal_name:string> <target_object:hobject> <slot_name:string>
+ @description:
+ Connects the <source_object>'s signal <signal_name> to the
+ <target_object>'s slot <slot_name>.
+ When one of the two objects is destroyed, the signal/slot
+ connection is automatically removed.[br]
+ WARNING: This command name collides with the [doc:rfc2812]RFC2812[/doc]
+ CONNECT IRC Op command: this IRC command is available to operators only
+ and is rather rarely used: you can use it by the means of [doc:raw]raw[/doc].
+ @seealso:
+ [cmd]class[/cmd], [cmd]object.disconnect[/cmd], [doc:objects]objects documentation[/doc]
+ */
+
+
+ KviKvsObject *obSrc;
+ KviKvsObject *obTrg;
+ QString szSignal,szSlot;
+ kvs_hobject_t hSrc,hTrg;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("object source",KVS_PT_HOBJECT,0,hSrc)
+ KVSM_PARAMETER("signal name",KVS_PT_NONEMPTYSTRING,0,szSignal)
+ KVSO_PARAMETER("object target",KVS_PT_HOBJECT,0,hTrg)
+ KVSM_PARAMETER("slot",KVS_PT_NONEMPTYSTRING,0,szSlot)
+ KVSM_PARAMETERS_END(c)
+ obTrg=KviKvsKernel::instance()->objectController()->lookupObject(hTrg);
+ obSrc=KviKvsKernel::instance()->objectController()->lookupObject(hSrc);
+ if(!obTrg)
+ {
+ c->warning(__tr2qs("Inexisting target object for objects.connect"));
+ return true;
+ }
+ if(!obSrc)
+ {
+ c->warning(__tr2qs("Inexisting source object for objects.connect"));
+ return true;
+ }
+ obSrc->connectSignal(szSignal,obTrg,szSlot);
+ return true;
+}
+
+
+static bool objects_kvs_fnc_exists(KviKvsModuleFunctionCall * c)
+{
+ /*
+ @doc: objects.exists
+ @title:
+ objects.exists
+ @type:
+ command
+ @short:
+ Check if an object exists.
+ @syntax:
+ <boolean> $object.exists(<obejct id:hobject>)
+ @description:
+ Check if an objects exists and return a boolean value.
+ @seealso:
+ [doc:objects]objects documentation[/doc]
+ */
+
+
+ kvs_hobject_t hObj;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("object",KVS_PT_HOBJECT,0,hObj)
+ KVSM_PARAMETERS_END(c)
+ KviKvsObject *ob=KviKvsKernel::instance()->objectController()->lookupObject(hObj);
+ c->returnValue()->setBoolean(ob ? true : false);
+ return true;
+}
+
+static bool objects_kvs_fnc_instances(KviKvsModuleFunctionCall * c)
+{
+ /*
+ @doc: objects.instances
+ @title:
+ objects.instances
+ @type:
+ command
+ @short:
+ List object instances
+ @syntax:
+ <array> $object.instances(<class name:string>[,<flags:string>])
+ @description:
+ Returns an array with the instance handles of
+ of objects of the specified class. <flags> is a
+ string containing modifiers for the function behaviour.[br]
+ If <flags> contains the letter "s" then
+ only unsubclassed instances of the specified
+ class are returned. This means that if B is
+ a subclass of A then when asked for instances
+ of A without the flag "s" this function will return
+ both instances of A and B, and with the flag "s"
+ this function will return only instances of A (and not B).
+ If the class name does not define a valid class
+ then an empty array is returned and a warning is
+ printed unless the "q" flag is used.
+ @examples:
+ [example]
+ foreach(%x,$objects.instances(object))
+ {
+ echo "OBJECT WITH CLASS" %x->$className() "AND NAME \""%x->$name()"\""
+ }
+ [/example]
+ @seealso:
+ [doc:objects]objects documentation[/doc]
+ */
+
+ QString szClassName;
+ QString szFlags;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("class name",KVS_PT_NONEMPTYSTRING,0,szClassName)
+ KVSO_PARAMETER("flags",KVS_PT_STRING,KVS_PF_OPTIONAL,szFlags)
+ KVSM_PARAMETERS_END(c)
+
+ KviKvsArray * pArry = new KviKvsArray();
+ c->returnValue()->setArray(pArry);
+
+ KviKvsObjectClass * pClass = KviKvsKernel::instance()->objectController()->lookupClass(szClassName);
+ if(!pClass)
+ {
+ if(!szFlags.contains(QChar('q')))
+ c->warning(__tr2qs("The class '%Q' does not exist"),&szClassName);
+ return true;
+ }
+ KviPointerHashTable<void *,KviKvsObject> * od = KviKvsKernel::instance()->objectController()->objectDict();
+
+ KviPointerHashTableIterator<void *,KviKvsObject> it(*od);
+ kvs_uint_t uIdx = 0;
+ if(szFlags.contains(QChar('s')))
+ {
+ while(KviKvsObject * ob = it.current())
+ {
+ if(ob->getExactClass() == pClass)
+ {
+ pArry->set(uIdx,new KviKvsVariant(ob->handle()));
+ uIdx++;
+ }
+ ++it;
+ }
+ } else {
+ while(KviKvsObject * ob = it.current())
+ {
+ if(ob->inheritsClass(pClass))
+ {
+ pArry->set(uIdx,new KviKvsVariant(ob->handle()));
+ uIdx++;
+ }
+ ++it;
+ }
+ }
+ return true;
+}
+/*
+ @doc: objects.variables
+ @title:
+ objects.variables
+ @type:
+ command
+ @short:
+ List object's variables.
+ @syntax:
+ <hash> objects.variables(<hobject>)
+ @description:
+ Returns an hash with the object's variables(useful only for debugging).
+ @seealso:
+ [doc:objects]objects documentation[/doc]
+ */
+static bool objects_kvs_fnc_variables(KviKvsModuleFunctionCall * c)
+{
+ kvs_hobject_t hObj;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("object",KVS_PT_HOBJECT,0,hObj)
+ KVSM_PARAMETERS_END(c)
+ KviKvsObject *ob=KviKvsKernel::instance()->objectController()->lookupObject(hObj);
+ if (!ob)
+ {
+ c->warning(__tr2qs("Object does not exists"));
+ return true;
+ }
+ KviPointerHashTableIterator<QString,KviKvsVariant> it(* ob->dataContainer()->dict());
+ KviKvsHash* pHash = new KviKvsHash();
+ c->returnValue()->setHash(pHash);
+ while(KviKvsVariant * t = it.current())
+ {
+ pHash->set(it.currentKey(),new KviKvsVariant(*t));
+ ++it;
+ }
+ return true;
+
+
+
+}
+/*
+ @doc: objects.classAllHandlers
+ @title:
+ objects.classAllHandlers
+ @type:
+ function
+ @short:
+ List all the functions .
+ @syntax:
+ <hash> objects.classAllHandlers(<class name:string>)
+ @description:
+ Returns an hash with the class's functions(useful only for debugging).
+ @seealso:
+ [doc:objects]objects documentation[/doc]
+ */
+static bool objects_kvs_fnc_classAllHandlers(KviKvsModuleFunctionCall * c)
+{
+ QString szClassName;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("class name",KVS_PT_NONEMPTYSTRING,0,szClassName)
+ KVSM_PARAMETERS_END(c)
+ KviKvsObjectClass * pClass = KviKvsKernel::instance()->objectController()->lookupClass(szClassName);
+ if(!pClass)
+ {
+ c->warning(__tr2qs("The class '%Q' does not exist"),&szClassName);
+ return true;
+ }
+
+ KviPointerHashTableIterator<QString,KviKvsObjectFunctionHandler> it(* pClass->getHandlers());
+ KviKvsHash* pHash = new KviKvsHash();
+ c->returnValue()->setHash(pHash);
+ while(KviKvsObjectFunctionHandler * t = it.current())
+ {
+ QString szCode;
+ KviKvsObjectFunctionHandler *handler=pClass->lookupFunctionHandler(it.currentKey());
+ pClass->getFunctionCode(szCode,*handler);
+ pHash->set(it.currentKey(),new KviKvsVariant(szCode));
+ ++it;
+ }
+
+ return true;
+}
+static bool objects_kvs_fnc_classes(KviKvsModuleFunctionCall * c)
+{
+
+ /*
+ @doc: objects.classes
+ @title:
+ objects.classes
+ @type:
+ command
+ @short:
+ List user defined classes
+ @syntax:
+ <array> $object.classes()
+ @description:
+ Returns an array with the user defined classes.
+ @seealso:
+ [doc:objects]objects documentation[/doc]
+ */
+
+ KviKvsArray * pArry = new KviKvsArray();
+ c->returnValue()->setArray(pArry);
+ int uIdx=0;
+ KviPointerHashTableIterator<QString,KviKvsObjectClass> it(*KviKvsKernel::instance()->objectController()->classDict());
+ KviPointerHashTable<QString,bool> *classdict=new KviPointerHashTable<QString,bool>;
+ classdict->setAutoDelete(false);
+ bool bFake=true;
+ while(KviKvsObjectClass * pClass=it.current())
+ {
+ if (!pClass->isBuiltin())classdict->insert(it.currentKey(),&bFake);
+ ++it;
+ }
+ QString szPath;
+ g_pApp->getLocalKvircDirectory(szPath,KviApp::Classes);
+ QDir d(szPath);
+ QStringList sl;
+ sl = d.entryList(QDir::Files);
+ for(QStringList::Iterator it2 = sl.begin();it2 != sl.end();++it2)
+ {
+ QString szName=*it2;
+ szName.replace("--","::");
+ if (szName!=".." && szName!=".") classdict->insert(szName.left(szName.length()-4),&bFake);
+ }
+ KviKvsArray* pArray = new KviKvsArray();
+ c->returnValue()->setArray(pArray);
+ int idx=0;
+ KviPointerHashTableIterator<QString,bool> strIt(*classdict);
+ while(strIt.current())
+ {
+ pArray->set(idx,new KviKvsVariant(strIt.currentKey()));
+ idx++;
+ ++strIt;
+ }
+ delete classdict;
+ return true;
+
+}
+
+static bool objects_kvs_cmd_disconnect(KviKvsModuleCommandCall * c)
+{
+ /*
+ @doc: objects.disconnect
+ @title:
+ objects.disconnect
+ @type:
+ command
+ @short:
+ Disconnects a signal from a slot
+ @syntax:
+ disconnect <source_object:hobject> <signal_name:string> <target_object:hobject> <slot_name:string>
+ @description:
+ Disconnects the <source_object>'s signal <signal_name> from the
+ <target_object>'s slot <slot_name>.
+ When one of the two objects is destroyed, the signal/slot
+ connection is automatically removed.
+ @seealso:
+ [cmd]class[/cmd], [cmd]objects.connect[/cmd], [doc:objects]objects documentation[/doc]
+ */
+
+
+
+
+ KviKvsObject *obSrc;
+ KviKvsObject *obTrg;
+ QString szSignal,szSlot;
+ kvs_hobject_t hSrc,hTrg;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("object source",KVS_PT_HOBJECT,0,hSrc)
+ KVSM_PARAMETER("signal name",KVS_PT_NONEMPTYSTRING,0,szSignal)
+ KVSO_PARAMETER("object target",KVS_PT_HOBJECT,0,hTrg)
+ KVSM_PARAMETER("slot",KVS_PT_NONEMPTYSTRING,0,szSlot)
+ KVSM_PARAMETERS_END(c)
+ obTrg=KviKvsKernel::instance()->objectController()->lookupObject(hTrg);
+ obSrc=KviKvsKernel::instance()->objectController()->lookupObject(hSrc);
+ if(!obTrg)
+ {
+ c->warning(__tr2qs("Inexisting target object for objects.disconnect"));
+ return true;
+ }
+ if(!obSrc)
+ {
+ c->warning(__tr2qs("Inexisting source object for objects.disconnect"));
+ return true;
+ }
+ obSrc->disconnectSignal(szSignal,obTrg,szSlot);
+ return true;
+}
+
+
+
+static bool objects_kvs_cmd_bitBlt(KviKvsModuleCommandCall * c)
+{
+ /*
+ @doc: objects.bitblt
+ @type:
+ command
+ @title:
+ objects.bitblt
+ @keyterms:
+ widget pixmap painter
+ @short:
+ Copies a block of pixels from a source to a destination.
+ @syntax:
+ objects.bitblt <source> <x> <y> <destination>
+ @description:
+ Copies a block of pixels from <source> to <destination> at the coordinates <x>,<y> .[br]
+ Source and destination must be a widget or pixmap.[br]
+
+ */
+
+ KviKvsObject *obSrc;
+ KviKvsObject *obDst;
+ kvs_int_t iXdst,iYdst,iXsrc,iYsrc,uW,uH;
+ kvs_hobject_t hDst,hSrc;
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("destination",KVS_PT_HOBJECT,0,hDst)
+ KVSO_PARAMETER("x offset dest",KVS_PT_INT,0,iXdst)
+ KVSO_PARAMETER("y offset dest",KVS_PT_INT,0,iYdst)
+ KVSO_PARAMETER("source",KVS_PT_HOBJECT,0,hSrc)
+ KVSO_PARAMETER("x offset source",KVS_PT_INT,0,iXsrc)
+ KVSO_PARAMETER("y offset source",KVS_PT_INT,0,iYsrc)
+ KVSO_PARAMETER("width",KVS_PT_UNSIGNEDINTEGER,0,uW)
+ KVSO_PARAMETER("height",KVS_PT_UNSIGNEDINTEGER,0,uH)
+ KVSO_PARAMETERS_END(c)
+ obSrc=KviKvsKernel::instance()->objectController()->lookupObject(hSrc);
+ if (!obSrc)
+ {
+ c->warning(__tr2qs("Source is not an object"));
+ return true;
+ }
+ obDst=KviKvsKernel::instance()->objectController()->lookupObject(hDst);
+ if (!obDst)
+ {
+ c->warning(__tr2qs("Destination is not an object"));
+ return true;
+ }
+
+ QImage * imgSource=0;
+ QPaintDevice * pdSource = 0;
+
+ if(obSrc->inherits("KviKvsObject_pixmap")) pdSource =((KviKvsObject_pixmap *)obSrc)->getPixmap();
+ else if (obSrc->inherits("KviKvsObject_widget")) pdSource=((KviKvsObject_widget *)obSrc)->widget();
+ if (!pdSource)
+ {
+ c->warning(__tr2qs("Widget, Image or Pixmap required "));
+ return true;
+ }
+ QPaintDevice * pdDest = 0;
+ if(obDst->inherits("KviKvsObject_pixmap")){
+ pdDest= ((KviKvsObject_pixmap *)obDst)->getPixmap();
+ }
+ else if (obDst->inherits("KviKvsObject_widget")) pdDest=((KviKvsObject_widget *)obDst)->widget();
+ if (!pdDest)
+ {
+ c->warning(__tr2qs("Widget or Pixmap required"));
+ return true;
+ }
+ if(obDst->inherits("KviKvsObject_pixmap")){
+ ((KviKvsObject_pixmap *)obDst)->pixmapChanged();
+ }
+#ifdef COMPILE_USE_QT4
+ /*QPainter p(pdDest);
+ QRect rectdest(iXdst,iYdst,uW,uH);
+ QRect rectsrc(iXsrc,iYsrc,uW,uH);
+
+ p.drawPixmap(rectdest,pdSource,rectsrc);
+*/
+ #else
+ bitBlt(pdDest,iXdst,iYdst,pdSource,iXsrc,iYsrc,uW,uH);
+#endif
+ return true;
+}
+ /*
+ @doc: objects.blend
+ @type:
+ command
+ @title:
+ objects.blend
+ @keyterms:
+ widget pixmap image
+ @short:
+ Blends two images to a destination.
+ @syntax:
+ objects.blend <background: image hobject> <x_offset_bkg:unsigned integer> <y_offset_bkg:unsigned integer>
+ <foreground: image hobject> <x_offset_fgr:unsigned integer> <y_offset_fgr:unsigned integer>
+ <destination: image, pixmap. widget hobject> <x_offset_dest:unsigned integer> <y_offset_dest:unsigned integer> <width:unsigned integer> <height:unsigned integer> <blend_factor>
+ @description:
+ Blends two images <background> and <foreground> and copy the result to <destination> at the coordinates <x_offset>,<y_offset> with a <blend_factor> value .[br]
+ Destination must be a widget or pixmap.[br]
+
+ */
+
+static bool objects_kvs_cmd_blend(KviKvsModuleCommandCall * c)
+{
+
+ KviKvsObject *obFor;
+ KviKvsObject *obBck;
+ KviKvsObject *obDest;
+
+ kvs_int_t iBkX,iBkY;
+ kvs_int_t iFoX,iFoY;
+ kvs_int_t iDesX,iDesY,uW,uH;
+ kvs_real_t dBlend;
+
+ kvs_hobject_t hBk,hFo,hDest;
+
+ KVSO_PARAMETERS_BEGIN(c)
+ KVSO_PARAMETER("destination",KVS_PT_HOBJECT,0,hDest)
+ KVSO_PARAMETER("x_offset_dest",KVS_PT_INT,0,iDesX)
+ KVSO_PARAMETER("y_offset_dest",KVS_PT_INT,0,iDesY)
+
+ KVSO_PARAMETER("image_background",KVS_PT_HOBJECT,0,hBk)
+ KVSO_PARAMETER("x_offset_background",KVS_PT_UNSIGNEDINTEGER,0,iBkX)
+ KVSO_PARAMETER("y_offset_background",KVS_PT_UNSIGNEDINTEGER,0,iBkY)
+ KVSO_PARAMETER("image_foreground",KVS_PT_HOBJECT,0,hFo)
+ KVSO_PARAMETER("x_offset_foreground",KVS_PT_UNSIGNEDINTEGER,0,iFoX)
+ KVSO_PARAMETER("y_offset_foreground",KVS_PT_UNSIGNEDINTEGER,0,iFoY)
+ KVSO_PARAMETER("width",KVS_PT_UNSIGNEDINTEGER,0,uW)
+ KVSO_PARAMETER("height",KVS_PT_UNSIGNEDINTEGER,0,uH)
+
+ KVSO_PARAMETER("blend_value",KVS_PT_REAL,0,dBlend)
+
+
+
+ KVSO_PARAMETERS_END(c)
+
+ obFor=KviKvsKernel::instance()->objectController()->lookupObject(hFo);
+
+
+ obBck=KviKvsKernel::instance()->objectController()->lookupObject(hBk);
+ obDest=KviKvsKernel::instance()->objectController()->lookupObject(hDest);
+ if (!obFor || !obBck || !obDest)
+ {
+ c->warning(__tr2qs("One o more of background, foreground or destination aren't objects"));
+ return true;
+ }
+
+ if (!obBck->inherits("KviKvsObject_pixmap") || !obFor->inherits("KviKvsObject_pixmap"))
+ {
+ c->warning(__tr2qs("Pixmap objects required"));
+ return true;
+ }
+
+ QPaintDevice * pdDest = 0;
+ if(obDest->inherits("KviKvsObject_pixmap")) pdDest = ((KviKvsObject_pixmap *)obDest)->getPixmap();
+ else if (obDest->inherits("KviKvsObject_widget")) pdDest=((KviKvsObject_widget *)obDest)->widget();
+
+ if (!pdDest)
+ {
+ c->warning(__tr2qs("Widget or Pixmap required "));
+ return true;
+ }
+
+ if(obDest->inherits("KviKvsObject_pixmap")) ((KviKvsObject_pixmap *)obDest)->pixmapChanged();
+
+
+ QImage *img_back=((KviKvsObject_pixmap *)obBck)->getImage();
+ QImage *img_fore=((KviKvsObject_pixmap *)obFor)->getImage();
+
+ // check size
+ if ((iBkX+uW>img_back->width())||(iBkY+uH>img_back->height()))
+ {
+ c->warning(__tr2qs("Values for background are out of image size "));
+ return true;
+ }
+ if ((iFoX+uW>img_fore->width())||(iFoY+uH>img_fore->height()))
+ {
+ c->warning(__tr2qs("Values for foreground are out of image size "));
+ return true;
+ }
+ QImage buffer;
+ buffer.create(uW,uH,32);
+ buffer.setAlphaBuffer(true);
+ for(int y = 0;y < buffer.height();y++)
+ {
+ QRgb * dst = (QRgb *)buffer.scanLine(y);
+ QRgb * end = dst + buffer.width();
+ QRgb * bkg = (QRgb *)img_back->scanLine(y+iBkY);
+ bkg += iBkX;
+ QRgb * fgn = (QRgb *)img_fore->scanLine(y+iFoY);
+ fgn += iFoX;
+ double dRemaining = 1.0 - dBlend;
+ int a=0;
+ while(dst < end)
+ {
+
+
+ *dst = qRgba(
+ (int)((qRed(*bkg) * dRemaining) + (qRed(*fgn) * dBlend)),
+ (int)((qGreen(*bkg) * dRemaining) + (qGreen(*fgn) * dBlend)),
+ (int)((qBlue(*bkg) * dRemaining) + (qBlue(*fgn) * dBlend)),
+ (int)((qAlpha(*bkg) * dRemaining) + (qAlpha(*fgn) * dBlend))
+ );
+
+ dst++;
+ bkg++;
+ fgn++;
+ }
+
+
+ }
+#ifdef COMPILE_USE_QT4
+ QPainter p(pdDest);
+ QRect rect(iDesX,iDesY,buffer.width(),buffer.height());
+ p.drawImage(rect,buffer);
+#else
+ bitBlt(pdDest,iDesX,iDesY,&buffer,0,0,buffer.width(),buffer.height());
+#endif
+ return true;
+
+}
+
+// ASSASSINI! LA DOVETE INDENTARE PER BENE :D
+
+
+static bool objects_kvs_fnc_listObjects(KviKvsModuleFunctionCall * cmd)
+{
+/*
+ @doc: objects.dump
+ @type:
+ function
+ @title:
+ $objects.dump
+ @keyterms:
+ dump objects
+ @short:
+ Dump the kvirc widgets.
+ @syntax:
+ $objects.dump(<flag b>)
+ @description:
+ This function returns the tree of the widgets of the kvirc, if the flag <b> is planned to 1,[br]
+ will return it on the currente window, if it' is planned to 0 instead it will return it as a string.[br]
+ ES:
+ %A[]=$str.split("\|",$objects.dump(0))
+ %i=0
+ while (%i != %A[]#)
+ {
+ echo %A[%i]
+ %i++
+ }
+*/
+
+
+ bool bFlag;
+ KVSO_PARAMETERS_BEGIN(cmd)
+ KVSO_PARAMETER("flag on video",KVS_PT_BOOL,0,bFlag)
+ KVSO_PARAMETERS_END(cmd)
+ if (bFlag) cmd->window()->output(80, "Objects dump:");
+ #ifdef COMPILE_USE_QT4
+ QWidgetList list = g_pApp->topLevelWidgets();
+
+ KviStr spacing = ">";
+ QString szTemp;
+ KviKvsArray * n = new KviKvsArray();
+ int idx=0;
+ for(int i=0;i<list.count();i++)
+ {
+ if( list.at(i)->isWidgetType())
+ {
+ if (bFlag)
+ {
+ cmd->window()->output(80, "Ptr %u: top level object: %c%s%c, class %s, %s, rect = %d, %d, %d, %d",
+ list.at(i),
+ KVI_TEXT_BOLD, list.at(i)->name(), KVI_TEXT_BOLD,
+ list.at(i)->className(),
+ list.at(i)->isVisible() ? "visible" : "hidden",
+ list.at(i)->x(), list.at(i)->y(), list.at(i)->width(), list.at(i)->height());
+ }
+ QString szClass=list.at(i)->className();
+ QString szObj=list.at(i)->name();
+ QString szTemp;
+ szTemp = szClass + "::" + szObj;
+ KviKvsVariant v;
+ v.setString(szTemp);
+ n->set(idx,new KviKvsVariant(v));
+ debug ("string %s",szTemp.latin1());
+ debug ("class %s",szClass.latin1());
+ debug ("Obj %s",szObj.latin1());
+
+ idx++;
+
+ dumpChildObjects(cmd->window(), list.at(i), spacing.ptr(), bFlag,n,idx);
+ }
+ //++it;
+ }
+
+#else
+ QWidgetList *l = g_pApp->topLevelWidgets();
+ l->setAutoDelete(false);
+ QWidgetListIt it(*l);
+ KviStr spacing = ">";
+ QString szTemp;
+ KviKvsArray * n = new KviKvsArray();
+ int idx=0;
+ while( it.current() )
+ {
+ if( it.current()->isWidgetType())
+ {
+ if (bFlag)
+ {
+ cmd->window()->output(80, "Ptr %u: top level object: %c%s%c, class %s, %s, rect = %d, %d, %d, %d",
+ it.current(),
+ KVI_TEXT_BOLD, it.current()->name(), KVI_TEXT_BOLD,
+ it.current()->className(),
+ it.current()->isVisible() ? "visible" : "hidden",
+ it.current()->x(), it.current()->y(), it.current()->width(), it.current()->height());
+ }
+ QString szClass=it.current()->className();
+ QString szObj=it.current()->name();
+ QString szTemp;
+ szTemp = szClass + "::" + szObj;
+ KviKvsVariant v;
+ v.setString(szTemp);
+ n->set(idx,new KviKvsVariant(v));
+ debug ("string %s",szTemp.latin1());
+ debug ("class %s",szClass.latin1());
+ debug ("Obj %s",szObj.latin1());
+
+ idx++;
+
+ dumpChildObjects(cmd->window(), it.current(), spacing.ptr(), bFlag,n,idx);
+
+
+ }
+ ++it;
+ }
+
+#endif
+ cmd->returnValue()->setArray(n);
+ return true;
+}
+
+static void dumpChildObjects(KviWindow *pWnd, QObject *parent, const char *spacing, bool bFlag, KviKvsArray *n, int &idx)
+{
+#ifdef COMPILE_USE_QT4
+ const QObjectList list = parent->children();
+ if( !list.count() ) return;
+ QString sp(spacing);
+ sp.append(">");
+ for(int i=0;i<list.count();i++)
+ {
+ if( list.at(i)->isWidgetType() )
+ {
+ if (bFlag)
+ {
+ pWnd->output(80, "%sPtr %u: object: %c%s%c, class %s",
+ spacing, list.at(i), KVI_TEXT_BOLD,
+ list.at(i)->name(), KVI_TEXT_BOLD, list.at(i)->className()
+ );
+ }
+ QString szClass=list.at(i)->className();
+ QString szObj=list.at(i)->name();
+ QString szTemp;
+ szTemp=spacing+szClass+"::"+szObj;
+ KviKvsVariant v;
+ v.setString(szTemp);
+ n->set(idx,new KviKvsVariant(v));
+ debug ("string %s",szTemp.latin1());
+ idx++;
+ dumpChildObjects(pWnd, list.at(i), sp, bFlag, n, idx );
+ }
+ }
+
+#else
+ const QObjectList *l = parent->children();
+ if( !l ) return;
+ if( l->isEmpty() ) return;
+ QObjectListIt it(*l);
+ QString sp(spacing);
+ sp.append(">");
+ while( it.current() )
+ {
+ if( it.current()->isWidgetType() )
+ {
+ if (bFlag)
+ {
+ pWnd->output(80, "%sPtr %u: object: %c%s%c, class %s",
+ spacing, it.current(), KVI_TEXT_BOLD,
+ it.current()->name(), KVI_TEXT_BOLD, it.current()->className()
+ );
+ }
+ QString szClass=it.current()->className();
+ QString szObj=it.current()->name();
+ QString szTemp;
+ szTemp=spacing+szClass+"::"+szObj;
+ KviKvsVariant v;
+ v.setString(szTemp);
+ n->set(idx,new KviKvsVariant(v));
+ debug ("string %s",szTemp.latin1());
+ idx++;
+ dumpChildObjects(pWnd, it.current(), sp, bFlag, n, idx );
+ }
+ ++it;
+ }
+#endif
+}
+
+static bool objects_module_can_unload(KviModule *m)
+{
+ // Actually this object remains locked in memory
+ // FIXME: unlock when no more instances & derived classes!
+ return false;
+}
+static bool objects_module_init(KviModule * m)
+{
+ // functions
+ KVSM_REGISTER_FUNCTION(m,"exists",objects_kvs_fnc_exists);
+ KVSM_REGISTER_FUNCTION(m,"instances",objects_kvs_fnc_instances);
+ KVSM_REGISTER_FUNCTION(m,"classes",objects_kvs_fnc_classes);
+ KVSM_REGISTER_FUNCTION(m,"dump",objects_kvs_fnc_listObjects);
+ KVSM_REGISTER_FUNCTION(m,"variables",objects_kvs_fnc_variables);
+ KVSM_REGISTER_FUNCTION(m,"classAllHandlers",objects_kvs_fnc_classAllHandlers);
+
+ // commands
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"connect",objects_kvs_cmd_connect);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"disconnect",objects_kvs_cmd_disconnect);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"killClass",objects_kvs_cmd_killClass);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"bitblt",objects_kvs_cmd_bitBlt);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"blend",objects_kvs_cmd_blend);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"clearObjects",objects_kvs_cmd_clearObjects);
+
+ KviKvsObject_list::registerSelf();
+
+ KviKvsObject_widget::registerSelf();
+ KviKvsObject_button::registerSelf();
+ KviKvsObject_mledit::registerSelf();
+
+ KviKvsObject_textbrowser::registerSelf();
+ KviKvsObject_checkbox::registerSelf();
+ KviKvsObject_dialog::registerSelf();
+ KviKvsObject_groupbox::registerSelf();
+ KviKvsObject_buttongroup::registerSelf();
+ KviKvsObject_label::registerSelf();
+ KviKvsObject_vbox::registerSelf();
+ KviKvsObject_hbox::registerSelf();
+ KviKvsObject_layout::registerSelf();
+ KviKvsObject_lcd::registerSelf();
+ KviKvsObject_lineedit::registerSelf();
+ KviKvsObject_menubar::registerSelf();
+ KviKvsObject_workspace::registerSelf();
+
+
+
+ KviKvsObject_combobox::registerSelf();
+ KviKvsObject_listbox::registerSelf();
+ KviKvsObject_listview::registerSelf();
+ KviKvsObject_listviewitem::registerSelf();
+ KviKvsObject_mainwindow::registerSelf();
+ KviKvsObject_painter::registerSelf();
+ KviKvsObject_pixmap::registerSelf();
+ KviKvsObject_popupmenu::registerSelf();
+ KviKvsObject_radiobutton::registerSelf();
+ KviKvsObject_slider::registerSelf();
+ KviKvsObject_spinbox::registerSelf();
+ KviKvsObject_tabwidget::registerSelf();
+ KviKvsObject_toolbar::registerSelf();
+ KviKvsObject_toolbutton::registerSelf();
+ KviKvsObject_urlabel::registerSelf();
+ KviKvsObject_window::registerSelf();
+ KviKvsObject_wizard::registerSelf();
+ KviKvsObject_dockwindow::registerSelf();
+ KviKvsObject_progressbar::registerSelf();
+ KviKvsObject_file::registerSelf();
+ KviKvsObject_wrapper::registerSelf();
+ KviKvsObject_xmlreader::registerSelf();
+ KviKvsObject_socket::registerSelf();
+ KviKvsObject_process::registerSelf();
+
+
+ return true;
+}
+
+KVIRC_MODULE(
+ "Objects",
+ "2.0.0",
+ "Copyright (C) 2000-2006:\n" \
+ " Szymon Stefanek (pragma at kvirc dot net)\n" \
+ " Krzysztof Godlewski (kristoff at poczta dot wprost dot pl)\n" \
+ " Tonino Imbesi (grifisx at barmes dot org)\n" \
+ " Alessandro Carbone (noldor at barmes dot org)",
+ "Object classes for KVIrc scripting language\n",
+ objects_module_init,
+ objects_module_can_unload,
+ 0,
+ objects_module_cleanup
+)
diff --git a/src/modules/objects/object_macros.h b/src/modules/objects/object_macros.h
new file mode 100644
index 00000000..9c0360b2
--- /dev/null
+++ b/src/modules/objects/object_macros.h
@@ -0,0 +1,90 @@
+#ifndef _OBJECT_MACROS_H_
+#define _OBJECT_MACROS_H_
+//=========================================================================================
+//
+// File : object_macros.h
+// Creation date : Sat Jun 18 2005 15:32:01 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=========================================================================================
+
+#include "kvi_kvs_object.h"
+#include "kvi_kvs_object_class.h"
+#include "kvi_kvs_kernel.h"
+#include "kvi_kvs_object_controller.h"
+#include "kvi_kvs_object_functioncall.h"
+
+#define KVSO_DECLARE_OBJECT(__className) \
+ __className(KviKvsObjectClass * pClass,KviKvsObject * pParent,const QString &szName); \
+ ~__className(); \
+ static void registerSelf(); \
+ static void unregisterSelf();
+
+
+#define KVSO_REGISTER_HANDLER(__className,__szName,__proc) \
+ g_pKvs##__className##Class->registerFunctionHandler(__szName,(KviKvsObjectFunctionHandlerProc)(KVI_PTR2MEMBER(__className::__proc)));
+
+#define KVSO_REGISTER_STANDARD_NOTHINGRETURN_HANDLER(__className,__szName) \
+ g_pKvs##__className##Class->registerStandardNothingReturnFunctionHandler(__szName);
+
+#define KVSO_REGISTER_STANDARD_TRUERETURN_HANDLER(__className,__szName) \
+ g_pKvs##__className##Class->registerStandardTrueReturnFunctionHandler(__szName);
+
+#define KVSO_REGISTER_STANDARD_FALSERETURN_HANDLER(__className,__szName) \
+ g_pKvs##__className##Class->registerStandardFalseReturnFunctionHandler(__szName);
+
+#define KVSO_BEGIN_REGISTERCLASS(__className,__stringName,__baseClass) \
+ static KviKvsObjectClass * g_pKvs##__className##Class = 0; \
+ static KviKvsObject * kvs_##__className##_createInstance(KviKvsObjectClass * pClass,KviKvsObject * pParent,const QString &szName) \
+ { \
+ return new __className(pClass,pParent,szName); \
+ } \
+ void __className::unregisterSelf() \
+ { \
+ delete g_pKvs##__className##Class; \
+ g_pKvs##__className##Class = 0; \
+ } \
+ void __className::registerSelf() \
+ { \
+ KviKvsObjectClass * base = KviKvsKernel::instance()->objectController()->lookupClass(__baseClass); \
+ g_pKvs##__className##Class = new KviKvsObjectClass(base,__stringName,kvs_##__className##_createInstance,true);
+
+
+
+#define KVSO_END_REGISTERCLASS(__className) \
+ }
+
+
+#define KVSO_BEGIN_CONSTRUCTOR(__className,__baseClass) \
+ __className::__className(KviKvsObjectClass * pClass,KviKvsObject * pParent,const QString &szName) \
+ : __baseClass(pClass,pParent,szName) \
+ {
+
+#define KVSO_END_CONSTRUCTOR(__className) \
+ }
+
+#define KVSO_BEGIN_DESTRUCTOR(__className) \
+ __className::~__className() \
+ {
+
+#define KVSO_END_DESTRUCTOR(__className) \
+ }
+
+
+#endif
diff --git a/src/modules/options/Makefile.am b/src/modules/options/Makefile.am
new file mode 100644
index 00000000..53c0988c
--- /dev/null
+++ b/src/modules/options/Makefile.am
@@ -0,0 +1,157 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+EXTRA_DIST = mkcreateinstanceproc.sh
+
+pluglib_LTLIBRARIES = libkvioptions.la
+
+libkvioptions_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkvioptions_la_SOURCES = libkvioptions.cpp \
+ container.cpp \
+ dialog.cpp \
+ instances.cpp \
+ optw_antispam.cpp \
+ optw_avatar.cpp \
+ optw_connection.cpp \
+ optw_ctcp.cpp \
+ optw_ctcpfloodprotection.cpp \
+ optw_dcc.cpp \
+ optw_generalopt.cpp \
+ optw_highlighting.cpp \
+ optw_ident.cpp \
+ optw_identity.cpp \
+ optw_ignore.cpp \
+ optw_input.cpp \
+ optw_interfacefeatures.cpp \
+ optw_interfacelookglobal.cpp \
+ optw_irc.cpp \
+ optw_ircoutput.cpp \
+ optw_ircview.cpp \
+ optw_lag.cpp \
+ optw_logging.cpp \
+ optw_mediatypes.cpp \
+ optw_messages.cpp \
+ optw_nickserv.cpp \
+ optw_notify.cpp \
+ optw_protection.cpp \
+ optw_proxy.cpp \
+ optw_query.cpp \
+ optw_servers.cpp \
+ optw_sound.cpp \
+ optw_ssl.cpp \
+ optw_taskbar.cpp \
+ optw_textencoding.cpp \
+ optw_texticons.cpp \
+ optw_theme.cpp \
+ optw_tools.cpp \
+ optw_transport.cpp \
+ optw_topiclabel.cpp \
+ optw_away.cpp \
+ optw_uparser.cpp \
+ optw_urlhandlers.cpp \
+ optw_userlist.cpp \
+ optw_tray.cpp
+
+libkvioptions_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+noinst_HEADERS= container.h \
+ dialog.h \
+ instances.h \
+ optw_antispam.h \
+ optw_avatar.h \
+ optw_connection.h \
+ optw_ctcp.h \
+ optw_ctcpfloodprotection.h \
+ optw_dcc.h \
+ optw_generalopt.h \
+ optw_highlighting.h \
+ optw_ident.h \
+ optw_identity.h \
+ optw_ignore.h \
+ optw_input.h \
+ optw_interfacefeatures.h \
+ optw_interfacelookglobal.h \
+ optw_irc.h \
+ optw_ircoutput.h \
+ optw_ircview.h \
+ optw_lag.h \
+ optw_logging.h \
+ optw_mediatypes.h \
+ optw_messages.h \
+ optw_nickserv.h \
+ optw_notify.h \
+ optw_protection.h \
+ optw_proxy.h \
+ optw_query.h \
+ optw_servers.h \
+ optw_sound.h \
+ optw_ssl.h \
+ optw_taskbar.h \
+ optw_textencoding.h \
+ optw_texticons.h \
+ optw_theme.h \
+ optw_tools.h \
+ optw_transport.h \
+ optw_topiclabel.h \
+ optw_away.h \
+ optw_uparser.h \
+ optw_urlhandlers.h \
+ optw_userlist.h \
+ optw_tray.h
+
+instances.h: optw_*.h mkcreateinstanceproc.sh
+ ./mkcreateinstanceproc.sh
+
+m_%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
+
+container.cpp: m_container.moc
+dialog.cpp: m_dialog.moc
+instances.cpp: m_instances.moc
+optw_antispam.cpp: m_optw_antispam.moc
+optw_avatar.cpp: m_optw_avatar.moc
+optw_away.cpp: m_optw_away.moc
+optw_connection.cpp: m_optw_connection.moc
+optw_ctcp.cpp: m_optw_ctcp.moc
+optw_ctcpfloodprotection.cpp: m_optw_ctcpfloodprotection.moc
+optw_dcc.cpp: m_optw_dcc.moc
+optw_generalopt.cpp: m_optw_generalopt.moc
+optw_highlighting.cpp: m_optw_highlighting.moc
+optw_ident.cpp: m_optw_ident.moc
+optw_identity.cpp: m_optw_identity.moc
+optw_ignore.cpp: m_optw_ignore.moc
+optw_input.cpp: m_optw_input.moc
+optw_interfacefeatures.cpp: m_optw_interfacefeatures.moc
+optw_interfacelookglobal.cpp: m_optw_interfacelookglobal.moc
+optw_irc.cpp: m_optw_irc.moc
+optw_ircoutput.cpp: m_optw_ircoutput.moc
+optw_ircview.cpp: m_optw_ircview.moc
+optw_lag.cpp: m_optw_lag.moc
+optw_logging.cpp: m_optw_logging.moc
+optw_look.cpp: m_optw_look.moc
+optw_mediatypes.cpp: m_optw_mediatypes.moc
+optw_messages.cpp: m_optw_messages.moc
+optw_nickserv.cpp: m_optw_nickserv.moc
+optw_notify.cpp: m_optw_notify.moc
+optw_protection.cpp: m_optw_protection.moc
+optw_proxy.cpp: m_optw_proxy.moc
+optw_query.cpp: m_optw_query.moc
+optw_servers.cpp: m_optw_servers.moc
+optw_sound.cpp: m_optw_sound.moc
+optw_ssl.cpp: m_optw_ssl.moc
+optw_taskbar.cpp: m_optw_taskbar.moc
+optw_textencoding.cpp: m_optw_textencoding.moc
+optw_texticons.cpp: m_optw_texticons.moc
+optw_transport.cpp: m_optw_transport.moc
+optw_theme.cpp: m_optw_theme.moc
+optw_topiclabel.cpp: m_optw_topiclabel.moc
+optw_tools.cpp: m_optw_tools.moc
+optw_uparser.cpp: m_optw_uparser.moc
+optw_urlhandlers.cpp: m_optw_urlhandlers.moc
+optw_userlist.cpp: m_optw_userlist.moc
+optw_tray.cpp : m_optw_tray.moc
diff --git a/src/modules/options/container.cpp b/src/modules/options/container.cpp
new file mode 100644
index 00000000..7e2272c1
--- /dev/null
+++ b/src/modules/options/container.cpp
@@ -0,0 +1,123 @@
+//
+// File : container.cpp
+// Creation date : Wed Nov 21 17:09:49 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "container.h"
+#include "instances.h"
+
+#include "kvi_locale.h"
+#include "kvi_iconmanager.h"
+#include "kvi_app.h"
+
+#include <qlayout.h>
+#include <qpushbutton.h>
+#include "kvi_tal_tooltip.h"
+#include <qevent.h>
+
+#ifdef COMPILE_USE_QT4
+ #include <qdesktopwidget.h>
+#endif
+
+extern KviOptionsInstanceManager * g_pOptionsInstanceManager;
+
+KviOptionsWidgetContainer::KviOptionsWidgetContainer(QWidget * par,bool bModal)
+: QDialog(par,"container","options")
+{
+ m_pOptionsWidget = 0;
+ setModal(bModal);
+}
+
+KviOptionsWidgetContainer::~KviOptionsWidgetContainer()
+{
+ if(m_pOptionsWidget)delete m_pOptionsWidget;
+}
+
+void KviOptionsWidgetContainer::setup(KviOptionsWidget * w)
+{
+ QGridLayout * g = new QGridLayout(this,2,3,4,8);
+
+ g->addMultiCellWidget(w,0,0,0,2);
+
+
+ QPushButton * b = new QPushButton(__tr2qs_ctx("&OK","options"),this);
+ KviTalToolTip::add(b,__tr2qs_ctx("Close this dialog, accepting all changes.","options"));
+ //b->setMinimumWidth(m_pCancel->sizeHint().width());
+ g->addWidget(b,1,1);
+ b->setDefault(true);
+ connect(b,SIGNAL(clicked()),this,SLOT(okClicked()));
+ b->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_ACCEPT)));
+
+ m_pCancel = new QPushButton(__tr2qs_ctx("Cancel","options"),this);
+ KviTalToolTip::add(m_pCancel,__tr2qs_ctx("Close this dialog, discarding all changes.","options"));
+ g->addWidget(m_pCancel,1,2);
+ connect(m_pCancel,SIGNAL(clicked()),this,SLOT(cancelClicked()));
+ m_pCancel->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_DISCARD)));
+
+
+ g->setRowStretch(0,1);
+ g->setColStretch(0,1);
+
+ KviOptionsWidgetInstanceEntry * e = g_pOptionsInstanceManager->findInstanceEntry(w->className());
+ if(e)
+ {
+ //KviStr caption(KviStr::Format,"%s - KVIrc",e->szName);
+ setIcon(*(g_pIconManager->getSmallIcon(e->iIcon)));
+ setCaption(e->szName);
+ }
+ m_pOptionsWidget = w;
+
+}
+
+void KviOptionsWidgetContainer::closeEvent(QCloseEvent *e)
+{
+ e->ignore();
+ cancelClicked();
+}
+
+void KviOptionsWidgetContainer::showEvent(QShowEvent *e)
+{
+ if(parent() == 0)
+ {
+ move((g_pApp->desktop()->width() - width()) / 2,
+ (g_pApp->desktop()->height() - height()) / 2);
+ }
+ QWidget::showEvent(e);
+ m_pCancel->setFocus();
+}
+
+void KviOptionsWidgetContainer::reject()
+{
+ cancelClicked();
+}
+
+void KviOptionsWidgetContainer::okClicked()
+{
+ if(m_pOptionsWidget)m_pOptionsWidget->commit();
+ g_pApp->saveOptions();
+ delete this;
+}
+
+void KviOptionsWidgetContainer::cancelClicked()
+{
+ deleteLater();
+}
+
+#include "m_container.moc"
diff --git a/src/modules/options/container.h b/src/modules/options/container.h
new file mode 100644
index 00000000..10ae69de
--- /dev/null
+++ b/src/modules/options/container.h
@@ -0,0 +1,53 @@
+#ifndef _CONTAINER_H_
+#define _CONTAINER_H_
+//
+// File : container.h
+// Creation date : Wed Nov 21 17:09:50 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+#include "kvi_optionswidget.h"
+#include <qdialog.h>
+
+class QPushButton;
+
+class KviOptionsWidgetContainer : public QDialog
+{
+ Q_OBJECT
+public:
+ KviOptionsWidgetContainer(QWidget * par,bool bModal = false);
+ ~KviOptionsWidgetContainer();
+protected:
+ KviOptionsWidget * m_pOptionsWidget;
+ QPushButton * m_pCancel;
+public:
+ void setup(KviOptionsWidget * w);
+protected:
+ virtual void closeEvent(QCloseEvent *e);
+ virtual void showEvent(QShowEvent *e);
+ virtual void reject();
+protected slots:
+ void okClicked();
+ void cancelClicked();
+};
+
+
+
+#endif //_CONTAINER_H_
diff --git a/src/modules/options/dialog.cpp b/src/modules/options/dialog.cpp
new file mode 100644
index 00000000..bebcae3e
--- /dev/null
+++ b/src/modules/options/dialog.cpp
@@ -0,0 +1,675 @@
+//=============================================================================
+//
+// File : dialog.cpp
+// Created on Fri 10 Feb 2006 18:52:18 by Szymon Stefanek
+// Based on dlg_options.cpp: Tue Jun 11 2000 02:39:12 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2000-2006 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "dialog.h"
+
+#include "kvi_app.h"
+#include "kvi_options.h"
+#include "kvi_locale.h"
+#include "kvi_iconmanager.h"
+#include "kvi_module.h"
+#include "kvi_styled_controls.h"
+#include "kvi_pointerhashtable.h"
+#include <qlayout.h>
+#include "kvi_accel.h"
+#include <qlabel.h>
+#include "kvi_tal_vbox.h"
+#include <qsplitter.h>
+#include "kvi_tal_widgetstack.h"
+#include <qpushbutton.h>
+#include "kvi_tal_tooltip.h"
+
+#ifdef COMPILE_USE_QT4
+ #include <q3header.h>
+#else
+ #include <qheader.h>
+ #include <qobjectlist.h>
+#endif
+#include "kvi_tal_popupmenu.h"
+#include <qtoolbutton.h>
+#include <qcheckbox.h>
+#include <kvi_tal_groupbox.h>
+#include <qpainter.h>
+#include <qfont.h>
+#include <qevent.h>
+
+//extern KviModule * g_pOptionsModule;
+extern KviPointerHashTable<QString,KviOptionsDialog> * g_pOptionsDialogDict;
+
+extern KVIRC_API KviApp * g_pApp;
+extern KviOptionsInstanceManager * g_pOptionsInstanceManager;
+
+KviGeneralOptionsFrontWidget::KviGeneralOptionsFrontWidget(QWidget *parent,const QString &szText)
+:KviOptionsWidget(parent,"general_options_front_widget")
+{
+ createLayout(1,1);
+ QLabel * l = new QLabel(szText,this);
+#ifdef COMPILE_USE_QT4
+ l->setWordWrap(true);
+#endif
+ l->setAlignment(Qt::AlignTop);
+ layout()->addWidget(l,0,0);
+}
+
+KviGeneralOptionsFrontWidget::~KviGeneralOptionsFrontWidget()
+{
+}
+
+
+
+
+KviOptionsListViewItem::KviOptionsListViewItem(KviTalListView *parent,KviOptionsWidgetInstanceEntry * e)
+:KviTalListViewItem(parent,e->szName)
+{
+ m_pInstanceEntry = e;
+ m_pOptionsWidget = 0;
+ m_bHighlighted = false;
+ setPixmap(0,*(g_pIconManager->getSmallIcon(e->iIcon)));
+}
+
+KviOptionsListViewItem::KviOptionsListViewItem(KviTalListViewItem *parent,KviOptionsWidgetInstanceEntry * e)
+:KviTalListViewItem(parent,e->szName)
+{
+ m_pInstanceEntry = e;
+ m_pOptionsWidget = 0;
+ m_bHighlighted = false;
+ setPixmap(0,*(g_pIconManager->getSmallIcon(e->iIcon)));
+}
+
+KviOptionsListViewItem::~KviOptionsListViewItem()
+{
+}
+
+void KviOptionsListViewItem::paintCell(QPainter * p,const QColorGroup & cg,int column,int width,int align)
+{
+ if(m_bHighlighted)
+ {
+ QColorGroup tmp(cg);
+ tmp.setColor(QColorGroup::Base,Qt::red);
+ tmp.setColor(QColorGroup::Background,Qt::red);
+ tmp.setColor(QColorGroup::Text,Qt::yellow);
+ KviTalListViewItem::paintCell(p,tmp,column,width,align);
+ } else {
+ KviTalListViewItem::paintCell(p,cg,column,width,align);
+ }
+}
+
+
+KviOptionsDialog::KviOptionsDialog(QWidget * par,const QString &szGroup)
+: QDialog(par,"general_options_dialog")
+{
+ setIcon(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_KVIRC)));
+
+ m_szGroup = szGroup;
+
+ QString szDialogTitle;
+
+ if(szGroup.isEmpty() || KviQString::equalCI(szGroup,"general"))
+ {
+ szDialogTitle = __tr2qs_ctx("General Preferences","options");
+ } else if(KviQString::equalCI(szGroup,"theme"))
+ {
+ szDialogTitle = __tr2qs_ctx("Theme Preferences","options");
+ } else {
+ szDialogTitle = __tr2qs_ctx("KVIrc Preferences","options");
+ }
+
+ QString szDialog = __tr2qs_ctx("This dialog contains a set of KVIrc settings.<br> Use the icons " \
+ "on the left to navigate through the option pages. The text box in the " \
+ "bottom left corner is a small search engine. It will highlight the " \
+ "pages that contain options related to the search term you have entered.","options");
+
+
+ QString szInfoTips;
+#ifdef COMPILE_INFO_TIPS
+ szInfoTips = __tr2qs_ctx("Many settings have tooltips that can be shown by holding " \
+ "the cursor over their label for a few seconds.","options");
+#else
+ szInfoTips = "";
+#endif
+ QString szOkCancelButtons = __tr2qs_ctx("When you have finished, click \"<b>OK</b>\" to accept your changes " \
+ "or \"<b>Cancel</b>\" to discard them. Clicking \"<b>Apply</b>\" will commit your " \
+ "changes without closing the window.","options");
+
+
+ QString szFrontText = QString(
+ "<table width=\"100%\" height=\"100%\" valign=\"top\" align=\"center\" cellpadding=\"4\">" \
+ "<tr>" \
+ "<td bgcolor=\"#303030\" valign=\"top\">" \
+ "<center><h1><font color=\"#FFFFFF\">%1</font></h1></center>" \
+ "</td>" \
+ "</tr>" \
+ "<tr>" \
+ "<td valign=\"bottom\">" \
+ "<br>" \
+ "<br>" \
+ "<p>" \
+ "%2" \
+ "</p>" \
+ "<br>" \
+ "<p>" \
+ "%3" \
+ "</p>" \
+ "<br>" \
+ "<p>" \
+ "%4" \
+ "</p>" \
+ "</td>" \
+ "</tr>" \
+ "</table>"
+ ).arg(szDialogTitle).arg(szDialog).arg(szInfoTips).arg(szOkCancelButtons);
+
+ QString szCaption = szDialogTitle + " - KVIrc";
+ setCaption(szCaption);
+
+ QGridLayout * g1 = new QGridLayout(this,2,5,8,8);
+ QSplitter * spl = new QSplitter(Qt::Horizontal,this);
+
+ g1->addMultiCellWidget(spl,0,0,0,4);
+
+ KviTalVBox * vbox = new KviTalVBox(spl);
+ vbox->setSpacing(2);
+ vbox->setMargin(0);
+
+ // Controlling list view
+ m_pListView = new KviTalListView(vbox);
+ m_pListView->addColumn("");
+ m_pListView->header()->hide();
+ m_pListView->setRootIsDecorated(true);
+ m_pListView->setSorting(-1);
+ connect(m_pListView,SIGNAL(selectionChanged(KviTalListViewItem *)),this,SLOT(listViewItemSelectionChanged(KviTalListViewItem *)));
+
+ KviTalHBox * hbox = new KviTalHBox(vbox);
+ vbox->setSpacing(2);
+ vbox->setMargin(0);
+
+ m_pSearchLineEdit = new QLineEdit(hbox);
+ connect(m_pSearchLineEdit,SIGNAL(returnPressed()),this,SLOT(searchClicked()));
+ m_pSearchButton = new KviStyledToolButton(hbox);
+ m_pSearchButton->setUsesBigPixmap(false);
+ m_pSearchButton->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_SEARCH)));
+ connect(m_pSearchButton,SIGNAL(clicked()),this,SLOT(searchClicked()));
+ connect(m_pSearchLineEdit,SIGNAL(textChanged(const QString &)),this,SLOT(searchLineEditTextChanged(const QString &)));
+
+#ifdef COMPILE_INFO_TIPS
+ QString szTip = __tr2qs_ctx("<p>This is the search tool for this options dialog.</p>" \
+ "<p>You can enter a search term either in your native " \
+ "language or in english and press the button on the right. " \
+ "The pages that contain some options related to the " \
+ "search term will be highlighted and you will be able " \
+ "to quickly find them.</p><p>Try \"nickname\" for example.</p>","options");
+ KviTalToolTip::add(m_pSearchLineEdit,szTip);
+ KviTalToolTip::add(m_pSearchButton,szTip);
+#endif
+
+ vbox = new KviTalVBox(spl);
+ vbox->setSpacing(2);
+ vbox->setMargin(0);
+
+ m_pCategoryLabel = new QLabel("<b>&nbsp;</b>",vbox,"labgeneraloptions");
+ //m_pCategoryLabel->setMargin(3);
+
+ QFrame * f = new QFrame(vbox);
+ f->setFrameStyle(QFrame::HLine | QFrame::Sunken);
+
+ // Widget stack
+ m_pWidgetStack = new KviTalWidgetStack(vbox);
+ vbox->setStretchFactor(m_pWidgetStack,1);
+
+ // First widget visible
+ m_pFrontWidget = new KviGeneralOptionsFrontWidget(m_pWidgetStack,szFrontText);
+ m_pWidgetStack->addWidget(m_pFrontWidget,0);
+ m_pWidgetStack->raiseWidget(m_pFrontWidget);
+
+// Ok,Cancel,Help
+
+ QPushButton * b = new QPushButton(__tr2qs_ctx("&OK","options"),this,"btnok");
+ KviTalToolTip::add(b,__tr2qs_ctx("Close this dialog, accepting all changes.","options"));
+ connect(b,SIGNAL(clicked()),this,SLOT(okClicked()));
+ //b->setMinimumWidth(whatIsThisWidth);
+ b->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_ACCEPT)));
+ g1->addWidget(b,1,2);
+
+ b = new QPushButton(__tr2qs_ctx("&Apply","options"),this,"btnapply");
+ KviTalToolTip::add(b,__tr2qs_ctx("Commit all changes immediately.","options"));
+ connect(b,SIGNAL(clicked()),this,SLOT(applyClicked()));
+ b->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_ACCEPT)));
+ g1->addWidget(b,1,3);
+
+ b = new QPushButton(__tr2qs_ctx("Cancel","options"),this,"btncancel");
+ KviTalToolTip::add(b,__tr2qs_ctx("Close this dialog, discarding all changes.","options"));
+ b->setDefault(true);
+ //b->setMinimumWidth(whatIsThisWidth);
+ connect(b,SIGNAL(clicked()),this,SLOT(cancelClicked()));
+ b->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_DISCARD)));
+ g1->addWidget(b,1,4);
+
+ g1->setRowStretch(0,1);
+ g1->setColStretch(1,1);
+
+
+ fillListView(0,g_pOptionsInstanceManager->instanceEntryTree(),szGroup);
+
+ if(!parent())
+ {
+
+ if(KVI_OPTION_RECT(KviOption_rectGeneralOptionsDialogGeometry).y() < 5)
+ {
+ KVI_OPTION_RECT(KviOption_rectGeneralOptionsDialogGeometry).setY(5);
+ }
+ //setGeometry(KVI_OPTION_RECT(KviOption_rectGeneralOptionsDialogGeometry));
+ resize(KVI_OPTION_RECT(KviOption_rectGeneralOptionsDialogGeometry).width(),
+ KVI_OPTION_RECT(KviOption_rectGeneralOptionsDialogGeometry).height());
+ move(KVI_OPTION_RECT(KviOption_rectGeneralOptionsDialogGeometry).x(),
+ KVI_OPTION_RECT(KviOption_rectGeneralOptionsDialogGeometry).y());
+ }
+
+ KviAccel *a = new KviAccel( this );
+ a->connectItem( a->insertItem(Qt::Key_Escape), this,SLOT(close()) );
+
+}
+
+KviOptionsDialog::~KviOptionsDialog()
+{
+ if(!parent())KVI_OPTION_RECT(KviOption_rectGeneralOptionsDialogGeometry) = QRect(pos().x(),pos().y(),
+ size().width(),size().height());
+ if(g_pOptionsDialogDict)
+ g_pOptionsDialogDict->remove(m_szGroup);
+}
+
+
+void KviOptionsDialog::searchLineEditTextChanged(const QString &)
+{
+ QString txt = m_pSearchLineEdit->text().stripWhiteSpace();
+ m_pSearchButton->setEnabled(txt.length() > 0);
+}
+
+bool KviOptionsDialog::recursiveSearch(KviOptionsListViewItem * pItem,const QStringList &lKeywords)
+{
+ //debug("recursive search:");
+ if(!pItem)return false;
+
+ if(!pItem->m_pOptionsWidget)
+ {
+ pItem->m_pOptionsWidget = g_pOptionsInstanceManager->getInstance(pItem->m_pInstanceEntry,m_pWidgetStack);
+ m_pWidgetStack->addWidget(pItem->m_pOptionsWidget,0);
+ }
+
+ bool bFoundSomethingHere = false;
+ KviPointerHashTable<void *,bool> lOptionWidgetsToMark;
+ lOptionWidgetsToMark.setAutoDelete(true);
+ QTabWidget * pTabWidgetToMark = 0;
+
+ QObject * o;
+#ifdef COMPILE_USE_QT4
+ QObjectList ol = pItem->m_pOptionsWidget->queryList();
+ if(ol.count() > 0)
+ {
+ for(QObjectList::Iterator it = ol.begin();it != ol.end();++it)
+ {
+ o = *it;
+#else
+ QObjectList * ol = pItem->m_pOptionsWidget->queryList();
+ if(ol)
+ {
+ QObjectListIt it(*ol);
+ while((o = it.current())/* && (!bFoundSomethingHere)*/)
+ {
+#endif
+ QString szText;
+ if(o->inherits("QLabel"))szText = ((QLabel *)o)->text();
+ else if(o->inherits("QCheckBox"))szText = ((QCheckBox *)o)->text();
+ else if(o->inherits("KviTalGroupBox"))szText = ((KviTalGroupBox *)o)->title();
+#ifdef COMPILE_INFO_TIPS
+ if(o->inherits("QWidget"))
+#ifdef COMPILE_USE_QT4
+ szText.append(((QWidget *)o)->toolTip());
+#else
+ szText.append(QToolTip::textFor((QWidget*)o));
+#endif
+#endif
+ if(!szText.isEmpty())
+ {
+ bool bOk = true;
+ for(int j=0;j<lKeywords.count();j++)
+ {
+#ifdef COMPILE_USE_QT4
+ if(szText.find(lKeywords.at(j),0,false) == -1)
+#else
+ if(szText.find(*(lKeywords.at(j)),0,false) == -1)
+#endif
+ {
+ bOk = false;
+ break;
+ }
+ }
+ if(bOk)
+ {
+ bFoundSomethingHere = true;
+ }
+
+ if(o->inherits("QWidget"))
+ {
+ QWidget* pWidget=(QWidget*)o;
+ QFont font = pWidget->font();
+ font.setBold(bOk);
+ font.setUnderline(bOk);
+ pWidget->setFont(font);
+
+ // if there is a QTabWidget in the parent chain, signal it in the tab text
+ QObject * pParent = pWidget->parent();
+ while(pParent)
+ {
+ if(pParent->inherits("QTabWidget"))
+ {
+ pTabWidgetToMark = (QTabWidget *)pParent;
+ break;
+ }
+ pParent = pParent->parent();
+ }
+
+ if(pTabWidgetToMark)
+ {
+ // lookup the KviOptionsWidget parent
+ pParent = pWidget->parent();
+ while(pParent)
+ {
+ if(pParent->inherits("KviOptionsWidget"))
+ {
+ bool * pExistingBool = lOptionWidgetsToMark.find(pParent);
+ if(pExistingBool)
+ {
+ if(bOk)
+ *pExistingBool = true;
+ } else {
+ lOptionWidgetsToMark.insert(pParent,new bool(bOk));
+ }
+ break;
+ }
+ pParent = pParent->parent();
+ }
+ }
+ }
+ }
+
+#ifndef COMPILE_USE_QT4
+ ++it;
+#endif
+ }
+#ifndef COMPILE_USE_QT4
+ delete ol;
+#endif
+ }
+
+ if(pTabWidgetToMark)
+ {
+ KviPointerHashTableIterator<void *,bool> it(lOptionWidgetsToMark);
+ while(bool * pBool = it.current())
+ {
+ KviOptionsWidget * pOptionsWidget = (KviOptionsWidget *)it.currentKey();
+ QString szTxt = pTabWidgetToMark->tabLabel(pOptionsWidget);
+ if(KviQString::equalCIN(szTxt,">>> ",4))
+ {
+ szTxt.replace(">>> ","");
+ szTxt.replace(" <<<","");
+ }
+ if(*pBool)
+ {
+ szTxt.insert(0,">>> ");
+ szTxt += QString(" <<<");
+ }
+ pTabWidgetToMark->setTabLabel(pOptionsWidget,szTxt);
+ ++it;
+ }
+ }
+
+ pItem->setHighlighted(bFoundSomethingHere);
+
+ KviOptionsListViewItem * pChild = (KviOptionsListViewItem *)pItem->firstChild();
+ bool bFoundSomethingInside = false;
+ while(pChild)
+ {
+ bool bRet = recursiveSearch(pChild,lKeywords);
+ if(bRet)bFoundSomethingInside = true;
+ pChild = (KviOptionsListViewItem *)(pChild->nextSibling());
+ }
+ pItem->setSelected(false);
+ m_pListView->setOpen(pItem,bFoundSomethingInside);
+ return (bFoundSomethingInside || bFoundSomethingHere);
+}
+
+void KviOptionsDialog::search(const QStringList &lKeywords)
+{
+ m_pListView->setUpdatesEnabled(false);
+
+ KviOptionsListViewItem * pChild = (KviOptionsListViewItem *)(m_pListView->firstChild());
+ bool bFoundSomethingInside = false;
+ while(pChild)
+ {
+ bFoundSomethingInside = recursiveSearch(pChild,lKeywords);
+ pChild = (KviOptionsListViewItem *)(pChild->nextSibling());
+ }
+ m_pListView->setUpdatesEnabled(true);
+ m_pListView->triggerUpdate();
+}
+
+void KviOptionsDialog::search(const QString &szKeywords)
+{
+ QStringList lKeywords = QStringList::split(" ",szKeywords,false);
+ search(lKeywords);
+}
+
+void KviOptionsDialog::searchClicked()
+{
+ QString szTxt = m_pSearchLineEdit->text().stripWhiteSpace();
+ if(!szTxt.isEmpty())
+ search(szTxt);
+}
+
+void KviOptionsDialog::fillListView(KviTalListViewItem * p,KviPointerList<KviOptionsWidgetInstanceEntry> * l,const QString &szGroup,bool bNotContainedOnly)
+{
+ if(!l)return;
+
+ KviOptionsListViewItem * it;
+ KviOptionsWidgetInstanceEntry * e;
+
+ KviPointerList<KviOptionsWidgetInstanceEntry> tmp;
+ tmp.setAutoDelete(false);
+
+
+ for(e = l->first();e;e = l->next())
+ {
+ // must be in the correct group
+ // if we want only containers then well.. must be one
+ e->bDoInsert = KviQString::equalCI(szGroup,e->szGroup) && ((!bNotContainedOnly) || e->bIsContainer || e->bIsNotContained);
+ KviOptionsWidgetInstanceEntry * ee = tmp.first();
+ int idx = 0;
+ while(ee)
+ {
+ if(ee->iPriority >= e->iPriority)break;
+ idx++;
+ ee = tmp.next();
+ }
+ tmp.insert(idx,e);
+ }
+
+ for(e = tmp.first();e;e = tmp.next())
+ {
+ if(e->bDoInsert)
+ {
+ if(p)it = new KviOptionsListViewItem(p,e);
+ else it = new KviOptionsListViewItem(m_pListView,e);
+ if(!it->m_pOptionsWidget)
+ {
+ it->m_pOptionsWidget = g_pOptionsInstanceManager->getInstance(it->m_pInstanceEntry,m_pWidgetStack);
+ m_pWidgetStack->addWidget(it->m_pOptionsWidget,0);
+ }
+ } else {
+ it = (KviOptionsListViewItem *)p;
+ }
+
+ if(e->pChildList)
+ {
+ if(e->bIsContainer)
+ {
+ // it's a container: add only eventual not contained children (containers or explicitly marked as not contained)
+ fillListView(it,e->pChildList,szGroup,true);
+ } else {
+ // it's not a container, add any children
+ fillListView(it,e->pChildList,szGroup,false);
+ }
+ }
+ }
+}
+
+void KviOptionsDialog::listViewItemSelectionChanged(KviTalListViewItem *it)
+{
+ if(it)
+ {
+ QString str = it->text(0);
+ KviTalListViewItem * par = it->parent();
+
+ while(par)
+ {
+ str.prepend(" :: ");
+ str.prepend(par->text(0));
+ par = par->parent();
+ }
+ str.prepend("<b>");
+ str += "</b>";
+
+ KviOptionsListViewItem *i = (KviOptionsListViewItem *)it;
+ if(!i->m_pOptionsWidget)
+ {
+ i->m_pOptionsWidget = g_pOptionsInstanceManager->getInstance(i->m_pInstanceEntry,m_pWidgetStack);
+ m_pWidgetStack->addWidget(i->m_pOptionsWidget,0);
+ }
+
+ m_pWidgetStack->raiseWidget(i->m_pOptionsWidget);
+ m_pCategoryLabel->setText(str);
+ }
+}
+
+KviOptionsListViewItem * KviOptionsDialog::findItemByPage(KviOptionsListViewItem *it,KviOptionsWidget * pPage)
+{
+ if(!it)return 0;
+ if(it->m_pOptionsWidget == pPage)return it;
+
+ KviOptionsListViewItem *i;
+ // run through the children
+ i = (KviOptionsListViewItem *)(it->firstChild());
+ if(i)
+ {
+ i = findItemByPage(i,pPage);
+ if(i)return i;
+ }
+
+ // not found in the children tree.. look in the next sibling
+ i = (KviOptionsListViewItem *)(it->nextSibling());
+ if(i)
+ {
+ i = findItemByPage(i,pPage);
+ if(i)return i;
+ }
+ return 0;
+}
+
+
+void KviOptionsDialog::pageWantsToSwitchToAdvancedPage(KviOptionsWidget * pPage)
+{
+ // unused
+}
+
+void KviOptionsDialog::applyClicked()
+{
+ apply(false);
+}
+
+void KviOptionsDialog::apply(bool bDialogAboutToClose)
+{
+
+ KviOptionsListViewItem *it = (KviOptionsListViewItem *)m_pListView->firstChild();
+ while(it)
+ {
+ recursiveCommit(it);
+ it = (KviOptionsListViewItem *)it->nextSibling();
+ }
+
+ if(!bDialogAboutToClose)
+ {
+ // bring up the current widget again!
+ it = (KviOptionsListViewItem *)m_pListView->currentItem();
+ if(it)listViewItemSelectionChanged(it);
+ }
+
+ g_pApp->saveConfiguration();
+
+}
+
+void KviOptionsDialog::okClicked()
+{
+ apply(true);
+ delete this;
+}
+
+void KviOptionsDialog::cancelClicked()
+{
+ delete this;
+}
+
+void KviOptionsDialog::closeEvent(QCloseEvent *e)
+{
+ e->ignore();
+ delete this;
+}
+
+void KviOptionsDialog::recursiveCommit(KviOptionsListViewItem *it)
+{
+ // First commit the children
+ if(!it) return;
+ KviOptionsListViewItem *it2 = (KviOptionsListViewItem *)it->firstChild();
+ while(it2)
+ {
+ recursiveCommit(it2);
+ it2 = (KviOptionsListViewItem *)it2->nextSibling();
+ }
+ // then the parents
+ if(it->m_pOptionsWidget)
+ {
+ it->m_pOptionsWidget->commit();
+ delete it->m_pOptionsWidget;
+ it->m_pOptionsWidget = 0;
+ }
+ //refreshListView(); // <-- this tends to jump into infinite recursion
+}
+void KviOptionsDialog::keyPressEvent( QKeyEvent * e )
+{
+ if(e->key()==Qt::Key_Return)
+ e->accept();
+ else
+ e->ignore();
+}
+
+#include "m_dialog.moc"
diff --git a/src/modules/options/dialog.h b/src/modules/options/dialog.h
new file mode 100644
index 00000000..b342ca51
--- /dev/null
+++ b/src/modules/options/dialog.h
@@ -0,0 +1,104 @@
+#ifndef _DIALOG_H_
+#define _DIALOG_H_
+//=============================================================================
+//
+// File : dialog.h
+// Created on Fri 10 Feb 2006 18:52:18 by Szymon Stefanek
+// Based on dlg_options.h: Tue Jun 11 2000 02:39:12 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2000-2006 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+
+#include <qdialog.h>
+#include "kvi_tal_listview.h"
+#include <qstringlist.h>
+#include "kvi_optionswidget.h"
+
+#include "instances.h"
+
+class QLabel;
+class KviTalWidgetStack;
+class QPushButton;
+class QLineEdit;
+class QToolButton;
+
+class KviGeneralOptionsFrontWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviGeneralOptionsFrontWidget(QWidget *parent,const QString &szText);
+ ~KviGeneralOptionsFrontWidget();
+};
+
+class KviOptionsListViewItem : public KviTalListViewItem
+{
+public:
+ KviOptionsListViewItem(KviTalListView *parent,KviOptionsWidgetInstanceEntry * e);
+ KviOptionsListViewItem(KviTalListViewItem *parent,KviOptionsWidgetInstanceEntry * e);
+ ~KviOptionsListViewItem();
+public:
+ KviOptionsWidgetInstanceEntry * m_pInstanceEntry;
+ KviOptionsWidget * m_pOptionsWidget;
+ bool m_bHighlighted;
+public:
+ void setHighlighted(bool b){ m_bHighlighted = b; };
+protected:
+ virtual void paintCell(QPainter * p,const QColorGroup & cg,int column,int width,int align);
+};
+
+class KviOptionsDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ KviOptionsDialog(QWidget * par,const QString &szGroup);
+ ~KviOptionsDialog();
+private:
+ KviTalListView * m_pListView;
+ QLabel * m_pCategoryLabel;
+ KviTalWidgetStack * m_pWidgetStack;
+ KviGeneralOptionsFrontWidget* m_pFrontWidget;
+ QString m_szGroup;
+ QLineEdit * m_pSearchLineEdit;
+ QToolButton * m_pSearchButton;
+private:
+ void recursiveCommit(KviOptionsListViewItem *it);
+ void fillListView(KviTalListViewItem * p,KviPointerList<KviOptionsWidgetInstanceEntry> * l,const QString &szGroup,bool bNotContainedOnly = false);
+ //KviOptionsListViewItem * showHiddenChildren(KviTalListViewItem * p,KviPointerList<KviOptionsWidgetInstanceEntry> * l);
+ KviOptionsListViewItem * findItemByPage(KviOptionsListViewItem *it,KviOptionsWidget * pPage);
+private slots:
+ void listViewItemSelectionChanged(KviTalListViewItem *it);
+ void applyClicked();
+ void okClicked();
+ void cancelClicked();
+ void pageWantsToSwitchToAdvancedPage(KviOptionsWidget * pPage);
+ void searchClicked();
+ void searchLineEditTextChanged(const QString &);
+protected:
+ void apply(bool bDialogAboutToClose);
+ virtual void closeEvent(QCloseEvent *e);
+ virtual void keyPressEvent( QKeyEvent * e );
+ bool recursiveSearch(KviOptionsListViewItem * pItem,const QStringList &lKeywords);
+public:
+ void search(const QString &szKeywords);
+ void search(const QStringList &lKeywords);
+};
+
+
+#endif //!_DIALOG_H_
diff --git a/src/modules/options/instances.cpp b/src/modules/options/instances.cpp
new file mode 100644
index 00000000..aa23e7be
--- /dev/null
+++ b/src/modules/options/instances.cpp
@@ -0,0 +1,3590 @@
+
+
+//
+// File : instances.cpp
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (stefanek@tin.it)
+//
+// 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 opinion) 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.
+//
+
+//
+// Instance creation routines for the KVIrc options module
+// DO NOT EDIT THIS FILE!! ALL CHANGES WILL BE LOST!!
+// This file is automatically generated by mkcreateinstanceproc.sh
+// so any change should go in that script
+//
+
+#include "optw_antispam.h"
+#include "optw_avatar.h"
+#include "optw_away.h"
+#include "optw_connection.h"
+#include "optw_ctcp.h"
+#include "optw_ctcpfloodprotection.h"
+#include "optw_dcc.h"
+#include "optw_generalopt.h"
+#include "optw_highlighting.h"
+#include "optw_ident.h"
+#include "optw_identity.h"
+#include "optw_ignore.h"
+#include "optw_input.h"
+#include "optw_interfacefeatures.h"
+#include "optw_interfacelookglobal.h"
+#include "optw_irc.h"
+#include "optw_ircoutput.h"
+#include "optw_ircview.h"
+#include "optw_lag.h"
+#include "optw_logging.h"
+#include "optw_mediatypes.h"
+#include "optw_messages.h"
+#include "optw_nickserv.h"
+#include "optw_notify.h"
+#include "optw_protection.h"
+#include "optw_proxy.h"
+#include "optw_query.h"
+#include "optw_servers.h"
+#include "optw_sound.h"
+#include "optw_ssl.h"
+#include "optw_taskbar.h"
+#include "optw_textencoding.h"
+#include "optw_texticons.h"
+#include "optw_theme.h"
+#include "optw_tools.h"
+#include "optw_topiclabel.h"
+#include "optw_transport.h"
+#include "optw_tray.h"
+#include "optw_uparser.h"
+#include "optw_urlhandlers.h"
+#include "optw_userlist.h"
+
+#include "kvi_locale.h"
+#include "kvi_iconmanager.h"
+#include "instances.h"
+
+int g_iOptionWidgetInstances = 0;
+
+KviOptionsWidget * classKviAntispamOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviAntispamOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviAvatarAdvancedOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviAvatarAdvancedOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviAwayOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviAwayOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviConnectionOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviConnectionOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviConnectionAdvancedOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviConnectionAdvancedOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviSSLOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviSSLOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviTransportOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviTransportOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviIdentOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviIdentOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviCtcpOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviCtcpOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviCtcpFloodProtectionOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviCtcpFloodProtectionOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviDccOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviDccOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviDccGeneralOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviDccGeneralOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviDccAdvancedOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviDccAdvancedOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviDccSendOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviDccSendOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviDccSendGeneralOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviDccSendGeneralOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviDccSendAdvancedOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviDccSendAdvancedOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviDccChatOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviDccChatOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviDccVoiceOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviDccVoiceOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviGeneralOptOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviGeneralOptOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviAlertHighlightingOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviAlertHighlightingOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviHighlightingOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviHighlightingOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviAlertOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviAlertOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviIdentityOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviIdentityOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviIdentityGeneralOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviIdentityGeneralOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviIdentityAvatarOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviIdentityAvatarOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviIdentityAdvancedOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviIdentityAdvancedOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviIgnoreOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviIgnoreOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviInputLookOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviInputLookOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviInputFeaturesOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviInputFeaturesOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviInterfaceFeaturesOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviInterfaceFeaturesOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviThemeGeneralOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviThemeGeneralOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviThemeTransparencyOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviThemeTransparencyOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviThemeMdiCaptionsOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviThemeMdiCaptionsOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviThemeMdiAreaOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviThemeMdiAreaOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviThemeToolBarAppletsOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviThemeToolBarAppletsOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviIrcOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviIrcOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviIrcGeneralOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviIrcGeneralOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviIrcAdvancedOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviIrcAdvancedOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviChannelOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviChannelOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviChannelGeneralOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviChannelGeneralOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviChannelAdvancedOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviChannelAdvancedOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviIrcOutputOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviIrcOutputOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviIrcViewThemeOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviIrcViewThemeOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviIrcViewLookOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviIrcViewLookOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviIrcViewFeaturesOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviIrcViewFeaturesOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviLagOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviLagOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviLoggingOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviLoggingOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviMediaTypesOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviMediaTypesOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviMessageOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviMessageOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviPrivmsgOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviPrivmsgOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviTimestampOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviTimestampOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviMessageColorsOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviMessageColorsOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviStandardColorsOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviStandardColorsOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviNickServOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviNickServOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviNotifyOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviNotifyOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviNotifierOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviNotifierOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviProtectionOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviProtectionOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviProxyOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviProxyOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviQueryOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviQueryOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviServerOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviServerOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviSoundOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviSoundOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviSoundGeneralOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviSoundGeneralOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviSoundsOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviSoundsOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviTaskBarOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviTaskBarOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviTreeTaskBarOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviTreeTaskBarOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviTreeTaskBarForegroundOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviTreeTaskBarForegroundOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviTreeTaskBarBackgroundOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviTreeTaskBarBackgroundOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviTreeTaskBarFeaturesOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviTreeTaskBarFeaturesOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviClassicTaskBarOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviClassicTaskBarOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviTextEncodingOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviTextEncodingOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviTextIconsOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviTextIconsOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviToolsOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviToolsOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviTopicLabelLookOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviTopicLabelLookOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviTrayOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviTrayOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviUParserOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviUParserOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviUrlHandlersOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviUrlHandlersOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviUserListLookOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviUserListLookOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviUserListLookBackgroundOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviUserListLookBackgroundOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviUserListLookForegroundOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviUserListLookForegroundOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviUserListGridOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviUserListGridOptionsWidget(parent);
+}
+
+KviOptionsWidget * classKviUserListFeaturesOptionsWidget_createInstanceProc(QWidget * parent)
+{
+ return new KviUserListFeaturesOptionsWidget(parent);
+}
+
+
+
+static const char * g_szName_KviAntispamOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviAntispamOptionsWidget;
+static const char * g_szClassName_KviAntispamOptionsWidget = "KviAntispamOptionsWidget";
+static const char * g_szName_KviAvatarAdvancedOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviAvatarAdvancedOptionsWidget;
+static const char * g_szClassName_KviAvatarAdvancedOptionsWidget = "KviAvatarAdvancedOptionsWidget";
+static const char * g_szName_KviAwayOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviAwayOptionsWidget;
+static const char * g_szClassName_KviAwayOptionsWidget = "KviAwayOptionsWidget";
+static const char * g_szName_KviConnectionOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviConnectionOptionsWidget;
+static const char * g_szClassName_KviConnectionOptionsWidget = "KviConnectionOptionsWidget";
+static const char * g_szName_KviConnectionAdvancedOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviConnectionAdvancedOptionsWidget;
+static const char * g_szClassName_KviConnectionAdvancedOptionsWidget = "KviConnectionAdvancedOptionsWidget";
+static const char * g_szName_KviSSLOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviSSLOptionsWidget;
+static const char * g_szClassName_KviSSLOptionsWidget = "KviSSLOptionsWidget";
+static const char * g_szName_KviTransportOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviTransportOptionsWidget;
+static const char * g_szClassName_KviTransportOptionsWidget = "KviTransportOptionsWidget";
+static const char * g_szName_KviIdentOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviIdentOptionsWidget;
+static const char * g_szClassName_KviIdentOptionsWidget = "KviIdentOptionsWidget";
+static const char * g_szName_KviCtcpOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviCtcpOptionsWidget;
+static const char * g_szClassName_KviCtcpOptionsWidget = "KviCtcpOptionsWidget";
+static const char * g_szName_KviCtcpFloodProtectionOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviCtcpFloodProtectionOptionsWidget;
+static const char * g_szClassName_KviCtcpFloodProtectionOptionsWidget = "KviCtcpFloodProtectionOptionsWidget";
+static const char * g_szName_KviDccOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviDccOptionsWidget;
+static const char * g_szClassName_KviDccOptionsWidget = "KviDccOptionsWidget";
+static const char * g_szName_KviDccGeneralOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviDccGeneralOptionsWidget;
+static const char * g_szClassName_KviDccGeneralOptionsWidget = "KviDccGeneralOptionsWidget";
+static const char * g_szName_KviDccAdvancedOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviDccAdvancedOptionsWidget;
+static const char * g_szClassName_KviDccAdvancedOptionsWidget = "KviDccAdvancedOptionsWidget";
+static const char * g_szName_KviDccSendOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviDccSendOptionsWidget;
+static const char * g_szClassName_KviDccSendOptionsWidget = "KviDccSendOptionsWidget";
+static const char * g_szName_KviDccSendGeneralOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviDccSendGeneralOptionsWidget;
+static const char * g_szClassName_KviDccSendGeneralOptionsWidget = "KviDccSendGeneralOptionsWidget";
+static const char * g_szName_KviDccSendAdvancedOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviDccSendAdvancedOptionsWidget;
+static const char * g_szClassName_KviDccSendAdvancedOptionsWidget = "KviDccSendAdvancedOptionsWidget";
+static const char * g_szName_KviDccChatOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviDccChatOptionsWidget;
+static const char * g_szClassName_KviDccChatOptionsWidget = "KviDccChatOptionsWidget";
+static const char * g_szName_KviDccVoiceOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviDccVoiceOptionsWidget;
+static const char * g_szClassName_KviDccVoiceOptionsWidget = "KviDccVoiceOptionsWidget";
+static const char * g_szName_KviGeneralOptOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviGeneralOptOptionsWidget;
+static const char * g_szClassName_KviGeneralOptOptionsWidget = "KviGeneralOptOptionsWidget";
+static const char * g_szName_KviAlertHighlightingOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviAlertHighlightingOptionsWidget;
+static const char * g_szClassName_KviAlertHighlightingOptionsWidget = "KviAlertHighlightingOptionsWidget";
+static const char * g_szName_KviHighlightingOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviHighlightingOptionsWidget;
+static const char * g_szClassName_KviHighlightingOptionsWidget = "KviHighlightingOptionsWidget";
+static const char * g_szName_KviAlertOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviAlertOptionsWidget;
+static const char * g_szClassName_KviAlertOptionsWidget = "KviAlertOptionsWidget";
+static const char * g_szName_KviIdentityOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviIdentityOptionsWidget;
+static const char * g_szClassName_KviIdentityOptionsWidget = "KviIdentityOptionsWidget";
+static const char * g_szName_KviIdentityGeneralOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviIdentityGeneralOptionsWidget;
+static const char * g_szClassName_KviIdentityGeneralOptionsWidget = "KviIdentityGeneralOptionsWidget";
+static const char * g_szName_KviIdentityAvatarOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviIdentityAvatarOptionsWidget;
+static const char * g_szClassName_KviIdentityAvatarOptionsWidget = "KviIdentityAvatarOptionsWidget";
+static const char * g_szName_KviIdentityAdvancedOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviIdentityAdvancedOptionsWidget;
+static const char * g_szClassName_KviIdentityAdvancedOptionsWidget = "KviIdentityAdvancedOptionsWidget";
+static const char * g_szName_KviIgnoreOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviIgnoreOptionsWidget;
+static const char * g_szClassName_KviIgnoreOptionsWidget = "KviIgnoreOptionsWidget";
+static const char * g_szName_KviInputLookOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviInputLookOptionsWidget;
+static const char * g_szClassName_KviInputLookOptionsWidget = "KviInputLookOptionsWidget";
+static const char * g_szName_KviInputFeaturesOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviInputFeaturesOptionsWidget;
+static const char * g_szClassName_KviInputFeaturesOptionsWidget = "KviInputFeaturesOptionsWidget";
+static const char * g_szName_KviInterfaceFeaturesOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviInterfaceFeaturesOptionsWidget;
+static const char * g_szClassName_KviInterfaceFeaturesOptionsWidget = "KviInterfaceFeaturesOptionsWidget";
+static const char * g_szName_KviThemeGeneralOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviThemeGeneralOptionsWidget;
+static const char * g_szClassName_KviThemeGeneralOptionsWidget = "KviThemeGeneralOptionsWidget";
+static const char * g_szName_KviThemeTransparencyOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviThemeTransparencyOptionsWidget;
+static const char * g_szClassName_KviThemeTransparencyOptionsWidget = "KviThemeTransparencyOptionsWidget";
+static const char * g_szName_KviThemeMdiCaptionsOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviThemeMdiCaptionsOptionsWidget;
+static const char * g_szClassName_KviThemeMdiCaptionsOptionsWidget = "KviThemeMdiCaptionsOptionsWidget";
+static const char * g_szName_KviThemeMdiAreaOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviThemeMdiAreaOptionsWidget;
+static const char * g_szClassName_KviThemeMdiAreaOptionsWidget = "KviThemeMdiAreaOptionsWidget";
+static const char * g_szName_KviThemeToolBarAppletsOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviThemeToolBarAppletsOptionsWidget;
+static const char * g_szClassName_KviThemeToolBarAppletsOptionsWidget = "KviThemeToolBarAppletsOptionsWidget";
+static const char * g_szName_KviIrcOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviIrcOptionsWidget;
+static const char * g_szClassName_KviIrcOptionsWidget = "KviIrcOptionsWidget";
+static const char * g_szName_KviIrcGeneralOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviIrcGeneralOptionsWidget;
+static const char * g_szClassName_KviIrcGeneralOptionsWidget = "KviIrcGeneralOptionsWidget";
+static const char * g_szName_KviIrcAdvancedOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviIrcAdvancedOptionsWidget;
+static const char * g_szClassName_KviIrcAdvancedOptionsWidget = "KviIrcAdvancedOptionsWidget";
+static const char * g_szName_KviChannelOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviChannelOptionsWidget;
+static const char * g_szClassName_KviChannelOptionsWidget = "KviChannelOptionsWidget";
+static const char * g_szName_KviChannelGeneralOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviChannelGeneralOptionsWidget;
+static const char * g_szClassName_KviChannelGeneralOptionsWidget = "KviChannelGeneralOptionsWidget";
+static const char * g_szName_KviChannelAdvancedOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviChannelAdvancedOptionsWidget;
+static const char * g_szClassName_KviChannelAdvancedOptionsWidget = "KviChannelAdvancedOptionsWidget";
+static const char * g_szName_KviIrcOutputOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviIrcOutputOptionsWidget;
+static const char * g_szClassName_KviIrcOutputOptionsWidget = "KviIrcOutputOptionsWidget";
+static const char * g_szName_KviIrcViewThemeOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviIrcViewThemeOptionsWidget;
+static const char * g_szClassName_KviIrcViewThemeOptionsWidget = "KviIrcViewThemeOptionsWidget";
+static const char * g_szName_KviIrcViewLookOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviIrcViewLookOptionsWidget;
+static const char * g_szClassName_KviIrcViewLookOptionsWidget = "KviIrcViewLookOptionsWidget";
+static const char * g_szName_KviIrcViewFeaturesOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviIrcViewFeaturesOptionsWidget;
+static const char * g_szClassName_KviIrcViewFeaturesOptionsWidget = "KviIrcViewFeaturesOptionsWidget";
+static const char * g_szName_KviLagOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviLagOptionsWidget;
+static const char * g_szClassName_KviLagOptionsWidget = "KviLagOptionsWidget";
+static const char * g_szName_KviLoggingOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviLoggingOptionsWidget;
+static const char * g_szClassName_KviLoggingOptionsWidget = "KviLoggingOptionsWidget";
+static const char * g_szName_KviMediaTypesOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviMediaTypesOptionsWidget;
+static const char * g_szClassName_KviMediaTypesOptionsWidget = "KviMediaTypesOptionsWidget";
+static const char * g_szName_KviMessageOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviMessageOptionsWidget;
+static const char * g_szClassName_KviMessageOptionsWidget = "KviMessageOptionsWidget";
+static const char * g_szName_KviPrivmsgOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviPrivmsgOptionsWidget;
+static const char * g_szClassName_KviPrivmsgOptionsWidget = "KviPrivmsgOptionsWidget";
+static const char * g_szName_KviTimestampOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviTimestampOptionsWidget;
+static const char * g_szClassName_KviTimestampOptionsWidget = "KviTimestampOptionsWidget";
+static const char * g_szName_KviMessageColorsOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviMessageColorsOptionsWidget;
+static const char * g_szClassName_KviMessageColorsOptionsWidget = "KviMessageColorsOptionsWidget";
+static const char * g_szName_KviStandardColorsOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviStandardColorsOptionsWidget;
+static const char * g_szClassName_KviStandardColorsOptionsWidget = "KviStandardColorsOptionsWidget";
+static const char * g_szName_KviNickServOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviNickServOptionsWidget;
+static const char * g_szClassName_KviNickServOptionsWidget = "KviNickServOptionsWidget";
+static const char * g_szName_KviNotifyOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviNotifyOptionsWidget;
+static const char * g_szClassName_KviNotifyOptionsWidget = "KviNotifyOptionsWidget";
+static const char * g_szName_KviNotifierOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviNotifierOptionsWidget;
+static const char * g_szClassName_KviNotifierOptionsWidget = "KviNotifierOptionsWidget";
+static const char * g_szName_KviProtectionOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviProtectionOptionsWidget;
+static const char * g_szClassName_KviProtectionOptionsWidget = "KviProtectionOptionsWidget";
+static const char * g_szName_KviProxyOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviProxyOptionsWidget;
+static const char * g_szClassName_KviProxyOptionsWidget = "KviProxyOptionsWidget";
+static const char * g_szName_KviQueryOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviQueryOptionsWidget;
+static const char * g_szClassName_KviQueryOptionsWidget = "KviQueryOptionsWidget";
+static const char * g_szName_KviServerOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviServerOptionsWidget;
+static const char * g_szClassName_KviServerOptionsWidget = "KviServerOptionsWidget";
+static const char * g_szName_KviSoundOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviSoundOptionsWidget;
+static const char * g_szClassName_KviSoundOptionsWidget = "KviSoundOptionsWidget";
+static const char * g_szName_KviSoundGeneralOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviSoundGeneralOptionsWidget;
+static const char * g_szClassName_KviSoundGeneralOptionsWidget = "KviSoundGeneralOptionsWidget";
+static const char * g_szName_KviSoundsOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviSoundsOptionsWidget;
+static const char * g_szClassName_KviSoundsOptionsWidget = "KviSoundsOptionsWidget";
+static const char * g_szName_KviTaskBarOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviTaskBarOptionsWidget;
+static const char * g_szClassName_KviTaskBarOptionsWidget = "KviTaskBarOptionsWidget";
+static const char * g_szName_KviTreeTaskBarOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviTreeTaskBarOptionsWidget;
+static const char * g_szClassName_KviTreeTaskBarOptionsWidget = "KviTreeTaskBarOptionsWidget";
+static const char * g_szName_KviTreeTaskBarForegroundOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviTreeTaskBarForegroundOptionsWidget;
+static const char * g_szClassName_KviTreeTaskBarForegroundOptionsWidget = "KviTreeTaskBarForegroundOptionsWidget";
+static const char * g_szName_KviTreeTaskBarBackgroundOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviTreeTaskBarBackgroundOptionsWidget;
+static const char * g_szClassName_KviTreeTaskBarBackgroundOptionsWidget = "KviTreeTaskBarBackgroundOptionsWidget";
+static const char * g_szName_KviTreeTaskBarFeaturesOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviTreeTaskBarFeaturesOptionsWidget;
+static const char * g_szClassName_KviTreeTaskBarFeaturesOptionsWidget = "KviTreeTaskBarFeaturesOptionsWidget";
+static const char * g_szName_KviClassicTaskBarOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviClassicTaskBarOptionsWidget;
+static const char * g_szClassName_KviClassicTaskBarOptionsWidget = "KviClassicTaskBarOptionsWidget";
+static const char * g_szName_KviTextEncodingOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviTextEncodingOptionsWidget;
+static const char * g_szClassName_KviTextEncodingOptionsWidget = "KviTextEncodingOptionsWidget";
+static const char * g_szName_KviTextIconsOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviTextIconsOptionsWidget;
+static const char * g_szClassName_KviTextIconsOptionsWidget = "KviTextIconsOptionsWidget";
+static const char * g_szName_KviToolsOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviToolsOptionsWidget;
+static const char * g_szClassName_KviToolsOptionsWidget = "KviToolsOptionsWidget";
+static const char * g_szName_KviTopicLabelLookOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviTopicLabelLookOptionsWidget;
+static const char * g_szClassName_KviTopicLabelLookOptionsWidget = "KviTopicLabelLookOptionsWidget";
+static const char * g_szName_KviTrayOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviTrayOptionsWidget;
+static const char * g_szClassName_KviTrayOptionsWidget = "KviTrayOptionsWidget";
+static const char * g_szName_KviUParserOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviUParserOptionsWidget;
+static const char * g_szClassName_KviUParserOptionsWidget = "KviUParserOptionsWidget";
+static const char * g_szName_KviUrlHandlersOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviUrlHandlersOptionsWidget;
+static const char * g_szClassName_KviUrlHandlersOptionsWidget = "KviUrlHandlersOptionsWidget";
+static const char * g_szName_KviUserListLookOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviUserListLookOptionsWidget;
+static const char * g_szClassName_KviUserListLookOptionsWidget = "KviUserListLookOptionsWidget";
+static const char * g_szName_KviUserListLookBackgroundOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviUserListLookBackgroundOptionsWidget;
+static const char * g_szClassName_KviUserListLookBackgroundOptionsWidget = "KviUserListLookBackgroundOptionsWidget";
+static const char * g_szName_KviUserListLookForegroundOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviUserListLookForegroundOptionsWidget;
+static const char * g_szClassName_KviUserListLookForegroundOptionsWidget = "KviUserListLookForegroundOptionsWidget";
+static const char * g_szName_KviUserListGridOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviUserListGridOptionsWidget;
+static const char * g_szClassName_KviUserListGridOptionsWidget = "KviUserListGridOptionsWidget";
+static const char * g_szName_KviUserListFeaturesOptionsWidget = KVI_OPTIONS_WIDGET_NAME_KviUserListFeaturesOptionsWidget;
+static const char * g_szClassName_KviUserListFeaturesOptionsWidget = "KviUserListFeaturesOptionsWidget";
+
+KviOptionsInstanceManager::KviOptionsInstanceManager()
+: QObject(0)
+{
+
+ //debug("Instantiating");
+ // Create the global widget dict : case sensitive , do not copy keys
+ m_pInstanceTree = new KviPointerList<KviOptionsWidgetInstanceEntry>;
+ m_pInstanceTree->setAutoDelete(true);
+
+
+ KviOptionsWidgetInstanceEntry * e0;
+ e0 = new KviOptionsWidgetInstanceEntry;
+ e0->createProc = &classKviConnectionOptionsWidget_createInstanceProc;
+ e0->pWidget = 0;
+ e0->szClassName = g_szClassName_KviConnectionOptionsWidget;
+ e0->iIcon = KVI_OPTIONS_WIDGET_ICON_KviConnectionOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviConnectionOptionsWidget
+ e0->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviConnectionOptionsWidget;
+ #else
+ e0->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviConnectionOptionsWidget
+ e0->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviConnectionOptionsWidget;
+ e0->szKeywords = __tr2qs_ctx_no_xgettext(e0->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviConnectionOptionsWidget
+ e0->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviConnectionOptionsWidget;
+ #else
+ e0->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviConnectionOptionsWidget
+ e0->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviConnectionOptionsWidget;
+ #else
+ e0->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviConnectionOptionsWidget
+ e0->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviConnectionOptionsWidget;
+ #else
+ e0->bIsNotContained = false;
+ #endif
+ e0->szNameNoLocale = g_szName_KviConnectionOptionsWidget;
+ e0->szName = __tr2qs_ctx_no_xgettext(g_szName_KviConnectionOptionsWidget,"options");
+ m_pInstanceTree->append(e0);
+
+ e0->pChildList = new KviPointerList<KviOptionsWidgetInstanceEntry>;
+ e0->pChildList->setAutoDelete(true);
+
+ KviOptionsWidgetInstanceEntry * e1;
+ e1 = new KviOptionsWidgetInstanceEntry;
+ e1->createProc = &classKviConnectionAdvancedOptionsWidget_createInstanceProc;
+ e1->pWidget = 0;
+ e1->szClassName = g_szClassName_KviConnectionAdvancedOptionsWidget;
+ e1->iIcon = KVI_OPTIONS_WIDGET_ICON_KviConnectionAdvancedOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviConnectionAdvancedOptionsWidget
+ e1->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviConnectionAdvancedOptionsWidget;
+ #else
+ e1->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviConnectionAdvancedOptionsWidget
+ e1->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviConnectionAdvancedOptionsWidget;
+ e1->szKeywords = __tr2qs_ctx_no_xgettext(e1->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviConnectionAdvancedOptionsWidget
+ e1->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviConnectionAdvancedOptionsWidget;
+ #else
+ e1->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviConnectionAdvancedOptionsWidget
+ e1->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviConnectionAdvancedOptionsWidget;
+ #else
+ e1->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviConnectionAdvancedOptionsWidget
+ e1->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviConnectionAdvancedOptionsWidget;
+ #else
+ e1->bIsNotContained = false;
+ #endif
+ e1->szNameNoLocale = g_szName_KviConnectionAdvancedOptionsWidget;
+ e1->szName = __tr2qs_ctx_no_xgettext(g_szName_KviConnectionAdvancedOptionsWidget,"options");
+ e0->pChildList->append(e1);
+
+ e1->pChildList = new KviPointerList<KviOptionsWidgetInstanceEntry>;
+ e1->pChildList->setAutoDelete(true);
+
+ KviOptionsWidgetInstanceEntry * e2;
+ e2 = new KviOptionsWidgetInstanceEntry;
+ e2->createProc = &classKviSSLOptionsWidget_createInstanceProc;
+ e2->pWidget = 0;
+ e2->szClassName = g_szClassName_KviSSLOptionsWidget;
+ e2->iIcon = KVI_OPTIONS_WIDGET_ICON_KviSSLOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviSSLOptionsWidget
+ e2->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviSSLOptionsWidget;
+ #else
+ e2->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviSSLOptionsWidget
+ e2->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviSSLOptionsWidget;
+ e2->szKeywords = __tr2qs_ctx_no_xgettext(e2->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviSSLOptionsWidget
+ e2->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviSSLOptionsWidget;
+ #else
+ e2->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviSSLOptionsWidget
+ e2->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviSSLOptionsWidget;
+ #else
+ e2->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviSSLOptionsWidget
+ e2->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviSSLOptionsWidget;
+ #else
+ e2->bIsNotContained = false;
+ #endif
+ e2->szNameNoLocale = g_szName_KviSSLOptionsWidget;
+ e2->szName = __tr2qs_ctx_no_xgettext(g_szName_KviSSLOptionsWidget,"options");
+ e1->pChildList->append(e2);
+ e2->pChildList = 0;
+
+ e2 = new KviOptionsWidgetInstanceEntry;
+ e2->createProc = &classKviTransportOptionsWidget_createInstanceProc;
+ e2->pWidget = 0;
+ e2->szClassName = g_szClassName_KviTransportOptionsWidget;
+ e2->iIcon = KVI_OPTIONS_WIDGET_ICON_KviTransportOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviTransportOptionsWidget
+ e2->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviTransportOptionsWidget;
+ #else
+ e2->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviTransportOptionsWidget
+ e2->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviTransportOptionsWidget;
+ e2->szKeywords = __tr2qs_ctx_no_xgettext(e2->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviTransportOptionsWidget
+ e2->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviTransportOptionsWidget;
+ #else
+ e2->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviTransportOptionsWidget
+ e2->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviTransportOptionsWidget;
+ #else
+ e2->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviTransportOptionsWidget
+ e2->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviTransportOptionsWidget;
+ #else
+ e2->bIsNotContained = false;
+ #endif
+ e2->szNameNoLocale = g_szName_KviTransportOptionsWidget;
+ e2->szName = __tr2qs_ctx_no_xgettext(g_szName_KviTransportOptionsWidget,"options");
+ e1->pChildList->append(e2);
+ e2->pChildList = 0;
+
+ e2 = new KviOptionsWidgetInstanceEntry;
+ e2->createProc = &classKviIdentOptionsWidget_createInstanceProc;
+ e2->pWidget = 0;
+ e2->szClassName = g_szClassName_KviIdentOptionsWidget;
+ e2->iIcon = KVI_OPTIONS_WIDGET_ICON_KviIdentOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviIdentOptionsWidget
+ e2->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviIdentOptionsWidget;
+ #else
+ e2->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviIdentOptionsWidget
+ e2->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviIdentOptionsWidget;
+ e2->szKeywords = __tr2qs_ctx_no_xgettext(e2->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviIdentOptionsWidget
+ e2->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviIdentOptionsWidget;
+ #else
+ e2->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviIdentOptionsWidget
+ e2->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviIdentOptionsWidget;
+ #else
+ e2->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviIdentOptionsWidget
+ e2->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviIdentOptionsWidget;
+ #else
+ e2->bIsNotContained = false;
+ #endif
+ e2->szNameNoLocale = g_szName_KviIdentOptionsWidget;
+ e2->szName = __tr2qs_ctx_no_xgettext(g_szName_KviIdentOptionsWidget,"options");
+ e1->pChildList->append(e2);
+ e2->pChildList = 0;
+
+ e1 = new KviOptionsWidgetInstanceEntry;
+ e1->createProc = &classKviProxyOptionsWidget_createInstanceProc;
+ e1->pWidget = 0;
+ e1->szClassName = g_szClassName_KviProxyOptionsWidget;
+ e1->iIcon = KVI_OPTIONS_WIDGET_ICON_KviProxyOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviProxyOptionsWidget
+ e1->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviProxyOptionsWidget;
+ #else
+ e1->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviProxyOptionsWidget
+ e1->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviProxyOptionsWidget;
+ e1->szKeywords = __tr2qs_ctx_no_xgettext(e1->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviProxyOptionsWidget
+ e1->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviProxyOptionsWidget;
+ #else
+ e1->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviProxyOptionsWidget
+ e1->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviProxyOptionsWidget;
+ #else
+ e1->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviProxyOptionsWidget
+ e1->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviProxyOptionsWidget;
+ #else
+ e1->bIsNotContained = false;
+ #endif
+ e1->szNameNoLocale = g_szName_KviProxyOptionsWidget;
+ e1->szName = __tr2qs_ctx_no_xgettext(g_szName_KviProxyOptionsWidget,"options");
+ e0->pChildList->append(e1);
+ e1->pChildList = 0;
+
+ e0 = new KviOptionsWidgetInstanceEntry;
+ e0->createProc = &classKviDccOptionsWidget_createInstanceProc;
+ e0->pWidget = 0;
+ e0->szClassName = g_szClassName_KviDccOptionsWidget;
+ e0->iIcon = KVI_OPTIONS_WIDGET_ICON_KviDccOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviDccOptionsWidget
+ e0->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviDccOptionsWidget;
+ #else
+ e0->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviDccOptionsWidget
+ e0->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviDccOptionsWidget;
+ e0->szKeywords = __tr2qs_ctx_no_xgettext(e0->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviDccOptionsWidget
+ e0->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviDccOptionsWidget;
+ #else
+ e0->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviDccOptionsWidget
+ e0->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviDccOptionsWidget;
+ #else
+ e0->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviDccOptionsWidget
+ e0->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviDccOptionsWidget;
+ #else
+ e0->bIsNotContained = false;
+ #endif
+ e0->szNameNoLocale = g_szName_KviDccOptionsWidget;
+ e0->szName = __tr2qs_ctx_no_xgettext(g_szName_KviDccOptionsWidget,"options");
+ m_pInstanceTree->append(e0);
+
+ e0->pChildList = new KviPointerList<KviOptionsWidgetInstanceEntry>;
+ e0->pChildList->setAutoDelete(true);
+
+ e1 = new KviOptionsWidgetInstanceEntry;
+ e1->createProc = &classKviDccGeneralOptionsWidget_createInstanceProc;
+ e1->pWidget = 0;
+ e1->szClassName = g_szClassName_KviDccGeneralOptionsWidget;
+ e1->iIcon = KVI_OPTIONS_WIDGET_ICON_KviDccGeneralOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviDccGeneralOptionsWidget
+ e1->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviDccGeneralOptionsWidget;
+ #else
+ e1->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviDccGeneralOptionsWidget
+ e1->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviDccGeneralOptionsWidget;
+ e1->szKeywords = __tr2qs_ctx_no_xgettext(e1->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviDccGeneralOptionsWidget
+ e1->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviDccGeneralOptionsWidget;
+ #else
+ e1->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviDccGeneralOptionsWidget
+ e1->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviDccGeneralOptionsWidget;
+ #else
+ e1->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviDccGeneralOptionsWidget
+ e1->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviDccGeneralOptionsWidget;
+ #else
+ e1->bIsNotContained = false;
+ #endif
+ e1->szNameNoLocale = g_szName_KviDccGeneralOptionsWidget;
+ e1->szName = __tr2qs_ctx_no_xgettext(g_szName_KviDccGeneralOptionsWidget,"options");
+ e0->pChildList->append(e1);
+ e1->pChildList = 0;
+
+ e1 = new KviOptionsWidgetInstanceEntry;
+ e1->createProc = &classKviDccAdvancedOptionsWidget_createInstanceProc;
+ e1->pWidget = 0;
+ e1->szClassName = g_szClassName_KviDccAdvancedOptionsWidget;
+ e1->iIcon = KVI_OPTIONS_WIDGET_ICON_KviDccAdvancedOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviDccAdvancedOptionsWidget
+ e1->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviDccAdvancedOptionsWidget;
+ #else
+ e1->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviDccAdvancedOptionsWidget
+ e1->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviDccAdvancedOptionsWidget;
+ e1->szKeywords = __tr2qs_ctx_no_xgettext(e1->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviDccAdvancedOptionsWidget
+ e1->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviDccAdvancedOptionsWidget;
+ #else
+ e1->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviDccAdvancedOptionsWidget
+ e1->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviDccAdvancedOptionsWidget;
+ #else
+ e1->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviDccAdvancedOptionsWidget
+ e1->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviDccAdvancedOptionsWidget;
+ #else
+ e1->bIsNotContained = false;
+ #endif
+ e1->szNameNoLocale = g_szName_KviDccAdvancedOptionsWidget;
+ e1->szName = __tr2qs_ctx_no_xgettext(g_szName_KviDccAdvancedOptionsWidget,"options");
+ e0->pChildList->append(e1);
+ e1->pChildList = 0;
+
+ e1 = new KviOptionsWidgetInstanceEntry;
+ e1->createProc = &classKviDccSendOptionsWidget_createInstanceProc;
+ e1->pWidget = 0;
+ e1->szClassName = g_szClassName_KviDccSendOptionsWidget;
+ e1->iIcon = KVI_OPTIONS_WIDGET_ICON_KviDccSendOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviDccSendOptionsWidget
+ e1->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviDccSendOptionsWidget;
+ #else
+ e1->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviDccSendOptionsWidget
+ e1->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviDccSendOptionsWidget;
+ e1->szKeywords = __tr2qs_ctx_no_xgettext(e1->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviDccSendOptionsWidget
+ e1->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviDccSendOptionsWidget;
+ #else
+ e1->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviDccSendOptionsWidget
+ e1->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviDccSendOptionsWidget;
+ #else
+ e1->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviDccSendOptionsWidget
+ e1->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviDccSendOptionsWidget;
+ #else
+ e1->bIsNotContained = false;
+ #endif
+ e1->szNameNoLocale = g_szName_KviDccSendOptionsWidget;
+ e1->szName = __tr2qs_ctx_no_xgettext(g_szName_KviDccSendOptionsWidget,"options");
+ e0->pChildList->append(e1);
+
+ e1->pChildList = new KviPointerList<KviOptionsWidgetInstanceEntry>;
+ e1->pChildList->setAutoDelete(true);
+
+ e2 = new KviOptionsWidgetInstanceEntry;
+ e2->createProc = &classKviDccSendGeneralOptionsWidget_createInstanceProc;
+ e2->pWidget = 0;
+ e2->szClassName = g_szClassName_KviDccSendGeneralOptionsWidget;
+ e2->iIcon = KVI_OPTIONS_WIDGET_ICON_KviDccSendGeneralOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviDccSendGeneralOptionsWidget
+ e2->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviDccSendGeneralOptionsWidget;
+ #else
+ e2->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviDccSendGeneralOptionsWidget
+ e2->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviDccSendGeneralOptionsWidget;
+ e2->szKeywords = __tr2qs_ctx_no_xgettext(e2->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviDccSendGeneralOptionsWidget
+ e2->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviDccSendGeneralOptionsWidget;
+ #else
+ e2->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviDccSendGeneralOptionsWidget
+ e2->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviDccSendGeneralOptionsWidget;
+ #else
+ e2->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviDccSendGeneralOptionsWidget
+ e2->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviDccSendGeneralOptionsWidget;
+ #else
+ e2->bIsNotContained = false;
+ #endif
+ e2->szNameNoLocale = g_szName_KviDccSendGeneralOptionsWidget;
+ e2->szName = __tr2qs_ctx_no_xgettext(g_szName_KviDccSendGeneralOptionsWidget,"options");
+ e1->pChildList->append(e2);
+ e2->pChildList = 0;
+
+ e2 = new KviOptionsWidgetInstanceEntry;
+ e2->createProc = &classKviDccSendAdvancedOptionsWidget_createInstanceProc;
+ e2->pWidget = 0;
+ e2->szClassName = g_szClassName_KviDccSendAdvancedOptionsWidget;
+ e2->iIcon = KVI_OPTIONS_WIDGET_ICON_KviDccSendAdvancedOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviDccSendAdvancedOptionsWidget
+ e2->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviDccSendAdvancedOptionsWidget;
+ #else
+ e2->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviDccSendAdvancedOptionsWidget
+ e2->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviDccSendAdvancedOptionsWidget;
+ e2->szKeywords = __tr2qs_ctx_no_xgettext(e2->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviDccSendAdvancedOptionsWidget
+ e2->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviDccSendAdvancedOptionsWidget;
+ #else
+ e2->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviDccSendAdvancedOptionsWidget
+ e2->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviDccSendAdvancedOptionsWidget;
+ #else
+ e2->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviDccSendAdvancedOptionsWidget
+ e2->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviDccSendAdvancedOptionsWidget;
+ #else
+ e2->bIsNotContained = false;
+ #endif
+ e2->szNameNoLocale = g_szName_KviDccSendAdvancedOptionsWidget;
+ e2->szName = __tr2qs_ctx_no_xgettext(g_szName_KviDccSendAdvancedOptionsWidget,"options");
+ e1->pChildList->append(e2);
+ e2->pChildList = 0;
+
+ e1 = new KviOptionsWidgetInstanceEntry;
+ e1->createProc = &classKviDccChatOptionsWidget_createInstanceProc;
+ e1->pWidget = 0;
+ e1->szClassName = g_szClassName_KviDccChatOptionsWidget;
+ e1->iIcon = KVI_OPTIONS_WIDGET_ICON_KviDccChatOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviDccChatOptionsWidget
+ e1->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviDccChatOptionsWidget;
+ #else
+ e1->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviDccChatOptionsWidget
+ e1->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviDccChatOptionsWidget;
+ e1->szKeywords = __tr2qs_ctx_no_xgettext(e1->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviDccChatOptionsWidget
+ e1->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviDccChatOptionsWidget;
+ #else
+ e1->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviDccChatOptionsWidget
+ e1->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviDccChatOptionsWidget;
+ #else
+ e1->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviDccChatOptionsWidget
+ e1->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviDccChatOptionsWidget;
+ #else
+ e1->bIsNotContained = false;
+ #endif
+ e1->szNameNoLocale = g_szName_KviDccChatOptionsWidget;
+ e1->szName = __tr2qs_ctx_no_xgettext(g_szName_KviDccChatOptionsWidget,"options");
+ e0->pChildList->append(e1);
+ e1->pChildList = 0;
+
+ e1 = new KviOptionsWidgetInstanceEntry;
+ e1->createProc = &classKviDccVoiceOptionsWidget_createInstanceProc;
+ e1->pWidget = 0;
+ e1->szClassName = g_szClassName_KviDccVoiceOptionsWidget;
+ e1->iIcon = KVI_OPTIONS_WIDGET_ICON_KviDccVoiceOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviDccVoiceOptionsWidget
+ e1->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviDccVoiceOptionsWidget;
+ #else
+ e1->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviDccVoiceOptionsWidget
+ e1->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviDccVoiceOptionsWidget;
+ e1->szKeywords = __tr2qs_ctx_no_xgettext(e1->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviDccVoiceOptionsWidget
+ e1->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviDccVoiceOptionsWidget;
+ #else
+ e1->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviDccVoiceOptionsWidget
+ e1->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviDccVoiceOptionsWidget;
+ #else
+ e1->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviDccVoiceOptionsWidget
+ e1->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviDccVoiceOptionsWidget;
+ #else
+ e1->bIsNotContained = false;
+ #endif
+ e1->szNameNoLocale = g_szName_KviDccVoiceOptionsWidget;
+ e1->szName = __tr2qs_ctx_no_xgettext(g_szName_KviDccVoiceOptionsWidget,"options");
+ e0->pChildList->append(e1);
+ e1->pChildList = 0;
+
+ e0 = new KviOptionsWidgetInstanceEntry;
+ e0->createProc = &classKviGeneralOptOptionsWidget_createInstanceProc;
+ e0->pWidget = 0;
+ e0->szClassName = g_szClassName_KviGeneralOptOptionsWidget;
+ e0->iIcon = KVI_OPTIONS_WIDGET_ICON_KviGeneralOptOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviGeneralOptOptionsWidget
+ e0->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviGeneralOptOptionsWidget;
+ #else
+ e0->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviGeneralOptOptionsWidget
+ e0->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviGeneralOptOptionsWidget;
+ e0->szKeywords = __tr2qs_ctx_no_xgettext(e0->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviGeneralOptOptionsWidget
+ e0->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviGeneralOptOptionsWidget;
+ #else
+ e0->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviGeneralOptOptionsWidget
+ e0->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviGeneralOptOptionsWidget;
+ #else
+ e0->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviGeneralOptOptionsWidget
+ e0->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviGeneralOptOptionsWidget;
+ #else
+ e0->bIsNotContained = false;
+ #endif
+ e0->szNameNoLocale = g_szName_KviGeneralOptOptionsWidget;
+ e0->szName = __tr2qs_ctx_no_xgettext(g_szName_KviGeneralOptOptionsWidget,"options");
+ m_pInstanceTree->append(e0);
+
+ e0->pChildList = new KviPointerList<KviOptionsWidgetInstanceEntry>;
+ e0->pChildList->setAutoDelete(true);
+
+ e1 = new KviOptionsWidgetInstanceEntry;
+ e1->createProc = &classKviMediaTypesOptionsWidget_createInstanceProc;
+ e1->pWidget = 0;
+ e1->szClassName = g_szClassName_KviMediaTypesOptionsWidget;
+ e1->iIcon = KVI_OPTIONS_WIDGET_ICON_KviMediaTypesOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviMediaTypesOptionsWidget
+ e1->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviMediaTypesOptionsWidget;
+ #else
+ e1->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviMediaTypesOptionsWidget
+ e1->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviMediaTypesOptionsWidget;
+ e1->szKeywords = __tr2qs_ctx_no_xgettext(e1->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviMediaTypesOptionsWidget
+ e1->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviMediaTypesOptionsWidget;
+ #else
+ e1->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviMediaTypesOptionsWidget
+ e1->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviMediaTypesOptionsWidget;
+ #else
+ e1->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviMediaTypesOptionsWidget
+ e1->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviMediaTypesOptionsWidget;
+ #else
+ e1->bIsNotContained = false;
+ #endif
+ e1->szNameNoLocale = g_szName_KviMediaTypesOptionsWidget;
+ e1->szName = __tr2qs_ctx_no_xgettext(g_szName_KviMediaTypesOptionsWidget,"options");
+ e0->pChildList->append(e1);
+ e1->pChildList = 0;
+
+ e1 = new KviOptionsWidgetInstanceEntry;
+ e1->createProc = &classKviSoundOptionsWidget_createInstanceProc;
+ e1->pWidget = 0;
+ e1->szClassName = g_szClassName_KviSoundOptionsWidget;
+ e1->iIcon = KVI_OPTIONS_WIDGET_ICON_KviSoundOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviSoundOptionsWidget
+ e1->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviSoundOptionsWidget;
+ #else
+ e1->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviSoundOptionsWidget
+ e1->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviSoundOptionsWidget;
+ e1->szKeywords = __tr2qs_ctx_no_xgettext(e1->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviSoundOptionsWidget
+ e1->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviSoundOptionsWidget;
+ #else
+ e1->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviSoundOptionsWidget
+ e1->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviSoundOptionsWidget;
+ #else
+ e1->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviSoundOptionsWidget
+ e1->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviSoundOptionsWidget;
+ #else
+ e1->bIsNotContained = false;
+ #endif
+ e1->szNameNoLocale = g_szName_KviSoundOptionsWidget;
+ e1->szName = __tr2qs_ctx_no_xgettext(g_szName_KviSoundOptionsWidget,"options");
+ e0->pChildList->append(e1);
+
+ e1->pChildList = new KviPointerList<KviOptionsWidgetInstanceEntry>;
+ e1->pChildList->setAutoDelete(true);
+
+ e2 = new KviOptionsWidgetInstanceEntry;
+ e2->createProc = &classKviSoundGeneralOptionsWidget_createInstanceProc;
+ e2->pWidget = 0;
+ e2->szClassName = g_szClassName_KviSoundGeneralOptionsWidget;
+ e2->iIcon = KVI_OPTIONS_WIDGET_ICON_KviSoundGeneralOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviSoundGeneralOptionsWidget
+ e2->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviSoundGeneralOptionsWidget;
+ #else
+ e2->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviSoundGeneralOptionsWidget
+ e2->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviSoundGeneralOptionsWidget;
+ e2->szKeywords = __tr2qs_ctx_no_xgettext(e2->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviSoundGeneralOptionsWidget
+ e2->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviSoundGeneralOptionsWidget;
+ #else
+ e2->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviSoundGeneralOptionsWidget
+ e2->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviSoundGeneralOptionsWidget;
+ #else
+ e2->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviSoundGeneralOptionsWidget
+ e2->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviSoundGeneralOptionsWidget;
+ #else
+ e2->bIsNotContained = false;
+ #endif
+ e2->szNameNoLocale = g_szName_KviSoundGeneralOptionsWidget;
+ e2->szName = __tr2qs_ctx_no_xgettext(g_szName_KviSoundGeneralOptionsWidget,"options");
+ e1->pChildList->append(e2);
+ e2->pChildList = 0;
+
+ e2 = new KviOptionsWidgetInstanceEntry;
+ e2->createProc = &classKviSoundsOptionsWidget_createInstanceProc;
+ e2->pWidget = 0;
+ e2->szClassName = g_szClassName_KviSoundsOptionsWidget;
+ e2->iIcon = KVI_OPTIONS_WIDGET_ICON_KviSoundsOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviSoundsOptionsWidget
+ e2->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviSoundsOptionsWidget;
+ #else
+ e2->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviSoundsOptionsWidget
+ e2->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviSoundsOptionsWidget;
+ e2->szKeywords = __tr2qs_ctx_no_xgettext(e2->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviSoundsOptionsWidget
+ e2->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviSoundsOptionsWidget;
+ #else
+ e2->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviSoundsOptionsWidget
+ e2->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviSoundsOptionsWidget;
+ #else
+ e2->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviSoundsOptionsWidget
+ e2->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviSoundsOptionsWidget;
+ #else
+ e2->bIsNotContained = false;
+ #endif
+ e2->szNameNoLocale = g_szName_KviSoundsOptionsWidget;
+ e2->szName = __tr2qs_ctx_no_xgettext(g_szName_KviSoundsOptionsWidget,"options");
+ e1->pChildList->append(e2);
+ e2->pChildList = 0;
+
+ e1 = new KviOptionsWidgetInstanceEntry;
+ e1->createProc = &classKviTextEncodingOptionsWidget_createInstanceProc;
+ e1->pWidget = 0;
+ e1->szClassName = g_szClassName_KviTextEncodingOptionsWidget;
+ e1->iIcon = KVI_OPTIONS_WIDGET_ICON_KviTextEncodingOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviTextEncodingOptionsWidget
+ e1->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviTextEncodingOptionsWidget;
+ #else
+ e1->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviTextEncodingOptionsWidget
+ e1->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviTextEncodingOptionsWidget;
+ e1->szKeywords = __tr2qs_ctx_no_xgettext(e1->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviTextEncodingOptionsWidget
+ e1->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviTextEncodingOptionsWidget;
+ #else
+ e1->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviTextEncodingOptionsWidget
+ e1->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviTextEncodingOptionsWidget;
+ #else
+ e1->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviTextEncodingOptionsWidget
+ e1->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviTextEncodingOptionsWidget;
+ #else
+ e1->bIsNotContained = false;
+ #endif
+ e1->szNameNoLocale = g_szName_KviTextEncodingOptionsWidget;
+ e1->szName = __tr2qs_ctx_no_xgettext(g_szName_KviTextEncodingOptionsWidget,"options");
+ e0->pChildList->append(e1);
+ e1->pChildList = 0;
+
+ e1 = new KviOptionsWidgetInstanceEntry;
+ e1->createProc = &classKviUParserOptionsWidget_createInstanceProc;
+ e1->pWidget = 0;
+ e1->szClassName = g_szClassName_KviUParserOptionsWidget;
+ e1->iIcon = KVI_OPTIONS_WIDGET_ICON_KviUParserOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviUParserOptionsWidget
+ e1->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviUParserOptionsWidget;
+ #else
+ e1->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviUParserOptionsWidget
+ e1->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviUParserOptionsWidget;
+ e1->szKeywords = __tr2qs_ctx_no_xgettext(e1->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviUParserOptionsWidget
+ e1->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviUParserOptionsWidget;
+ #else
+ e1->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviUParserOptionsWidget
+ e1->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviUParserOptionsWidget;
+ #else
+ e1->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviUParserOptionsWidget
+ e1->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviUParserOptionsWidget;
+ #else
+ e1->bIsNotContained = false;
+ #endif
+ e1->szNameNoLocale = g_szName_KviUParserOptionsWidget;
+ e1->szName = __tr2qs_ctx_no_xgettext(g_szName_KviUParserOptionsWidget,"options");
+ e0->pChildList->append(e1);
+ e1->pChildList = 0;
+
+ e1 = new KviOptionsWidgetInstanceEntry;
+ e1->createProc = &classKviUrlHandlersOptionsWidget_createInstanceProc;
+ e1->pWidget = 0;
+ e1->szClassName = g_szClassName_KviUrlHandlersOptionsWidget;
+ e1->iIcon = KVI_OPTIONS_WIDGET_ICON_KviUrlHandlersOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviUrlHandlersOptionsWidget
+ e1->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviUrlHandlersOptionsWidget;
+ #else
+ e1->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviUrlHandlersOptionsWidget
+ e1->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviUrlHandlersOptionsWidget;
+ e1->szKeywords = __tr2qs_ctx_no_xgettext(e1->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviUrlHandlersOptionsWidget
+ e1->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviUrlHandlersOptionsWidget;
+ #else
+ e1->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviUrlHandlersOptionsWidget
+ e1->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviUrlHandlersOptionsWidget;
+ #else
+ e1->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviUrlHandlersOptionsWidget
+ e1->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviUrlHandlersOptionsWidget;
+ #else
+ e1->bIsNotContained = false;
+ #endif
+ e1->szNameNoLocale = g_szName_KviUrlHandlersOptionsWidget;
+ e1->szName = __tr2qs_ctx_no_xgettext(g_szName_KviUrlHandlersOptionsWidget,"options");
+ e0->pChildList->append(e1);
+ e1->pChildList = 0;
+
+ e0 = new KviOptionsWidgetInstanceEntry;
+ e0->createProc = &classKviIdentityOptionsWidget_createInstanceProc;
+ e0->pWidget = 0;
+ e0->szClassName = g_szClassName_KviIdentityOptionsWidget;
+ e0->iIcon = KVI_OPTIONS_WIDGET_ICON_KviIdentityOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviIdentityOptionsWidget
+ e0->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviIdentityOptionsWidget;
+ #else
+ e0->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviIdentityOptionsWidget
+ e0->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviIdentityOptionsWidget;
+ e0->szKeywords = __tr2qs_ctx_no_xgettext(e0->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviIdentityOptionsWidget
+ e0->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviIdentityOptionsWidget;
+ #else
+ e0->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviIdentityOptionsWidget
+ e0->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviIdentityOptionsWidget;
+ #else
+ e0->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviIdentityOptionsWidget
+ e0->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviIdentityOptionsWidget;
+ #else
+ e0->bIsNotContained = false;
+ #endif
+ e0->szNameNoLocale = g_szName_KviIdentityOptionsWidget;
+ e0->szName = __tr2qs_ctx_no_xgettext(g_szName_KviIdentityOptionsWidget,"options");
+ m_pInstanceTree->append(e0);
+
+ e0->pChildList = new KviPointerList<KviOptionsWidgetInstanceEntry>;
+ e0->pChildList->setAutoDelete(true);
+
+ e1 = new KviOptionsWidgetInstanceEntry;
+ e1->createProc = &classKviIdentityGeneralOptionsWidget_createInstanceProc;
+ e1->pWidget = 0;
+ e1->szClassName = g_szClassName_KviIdentityGeneralOptionsWidget;
+ e1->iIcon = KVI_OPTIONS_WIDGET_ICON_KviIdentityGeneralOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviIdentityGeneralOptionsWidget
+ e1->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviIdentityGeneralOptionsWidget;
+ #else
+ e1->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviIdentityGeneralOptionsWidget
+ e1->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviIdentityGeneralOptionsWidget;
+ e1->szKeywords = __tr2qs_ctx_no_xgettext(e1->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviIdentityGeneralOptionsWidget
+ e1->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviIdentityGeneralOptionsWidget;
+ #else
+ e1->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviIdentityGeneralOptionsWidget
+ e1->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviIdentityGeneralOptionsWidget;
+ #else
+ e1->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviIdentityGeneralOptionsWidget
+ e1->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviIdentityGeneralOptionsWidget;
+ #else
+ e1->bIsNotContained = false;
+ #endif
+ e1->szNameNoLocale = g_szName_KviIdentityGeneralOptionsWidget;
+ e1->szName = __tr2qs_ctx_no_xgettext(g_szName_KviIdentityGeneralOptionsWidget,"options");
+ e0->pChildList->append(e1);
+ e1->pChildList = 0;
+
+ e1 = new KviOptionsWidgetInstanceEntry;
+ e1->createProc = &classKviIdentityAvatarOptionsWidget_createInstanceProc;
+ e1->pWidget = 0;
+ e1->szClassName = g_szClassName_KviIdentityAvatarOptionsWidget;
+ e1->iIcon = KVI_OPTIONS_WIDGET_ICON_KviIdentityAvatarOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviIdentityAvatarOptionsWidget
+ e1->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviIdentityAvatarOptionsWidget;
+ #else
+ e1->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviIdentityAvatarOptionsWidget
+ e1->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviIdentityAvatarOptionsWidget;
+ e1->szKeywords = __tr2qs_ctx_no_xgettext(e1->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviIdentityAvatarOptionsWidget
+ e1->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviIdentityAvatarOptionsWidget;
+ #else
+ e1->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviIdentityAvatarOptionsWidget
+ e1->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviIdentityAvatarOptionsWidget;
+ #else
+ e1->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviIdentityAvatarOptionsWidget
+ e1->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviIdentityAvatarOptionsWidget;
+ #else
+ e1->bIsNotContained = false;
+ #endif
+ e1->szNameNoLocale = g_szName_KviIdentityAvatarOptionsWidget;
+ e1->szName = __tr2qs_ctx_no_xgettext(g_szName_KviIdentityAvatarOptionsWidget,"options");
+ e0->pChildList->append(e1);
+ e1->pChildList = 0;
+
+ e1 = new KviOptionsWidgetInstanceEntry;
+ e1->createProc = &classKviIdentityAdvancedOptionsWidget_createInstanceProc;
+ e1->pWidget = 0;
+ e1->szClassName = g_szClassName_KviIdentityAdvancedOptionsWidget;
+ e1->iIcon = KVI_OPTIONS_WIDGET_ICON_KviIdentityAdvancedOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviIdentityAdvancedOptionsWidget
+ e1->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviIdentityAdvancedOptionsWidget;
+ #else
+ e1->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviIdentityAdvancedOptionsWidget
+ e1->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviIdentityAdvancedOptionsWidget;
+ e1->szKeywords = __tr2qs_ctx_no_xgettext(e1->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviIdentityAdvancedOptionsWidget
+ e1->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviIdentityAdvancedOptionsWidget;
+ #else
+ e1->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviIdentityAdvancedOptionsWidget
+ e1->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviIdentityAdvancedOptionsWidget;
+ #else
+ e1->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviIdentityAdvancedOptionsWidget
+ e1->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviIdentityAdvancedOptionsWidget;
+ #else
+ e1->bIsNotContained = false;
+ #endif
+ e1->szNameNoLocale = g_szName_KviIdentityAdvancedOptionsWidget;
+ e1->szName = __tr2qs_ctx_no_xgettext(g_szName_KviIdentityAdvancedOptionsWidget,"options");
+ e0->pChildList->append(e1);
+ e1->pChildList = 0;
+
+ e0 = new KviOptionsWidgetInstanceEntry;
+ e0->createProc = &classKviInputLookOptionsWidget_createInstanceProc;
+ e0->pWidget = 0;
+ e0->szClassName = g_szClassName_KviInputLookOptionsWidget;
+ e0->iIcon = KVI_OPTIONS_WIDGET_ICON_KviInputLookOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviInputLookOptionsWidget
+ e0->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviInputLookOptionsWidget;
+ #else
+ e0->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviInputLookOptionsWidget
+ e0->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviInputLookOptionsWidget;
+ e0->szKeywords = __tr2qs_ctx_no_xgettext(e0->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviInputLookOptionsWidget
+ e0->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviInputLookOptionsWidget;
+ #else
+ e0->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviInputLookOptionsWidget
+ e0->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviInputLookOptionsWidget;
+ #else
+ e0->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviInputLookOptionsWidget
+ e0->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviInputLookOptionsWidget;
+ #else
+ e0->bIsNotContained = false;
+ #endif
+ e0->szNameNoLocale = g_szName_KviInputLookOptionsWidget;
+ e0->szName = __tr2qs_ctx_no_xgettext(g_szName_KviInputLookOptionsWidget,"options");
+ m_pInstanceTree->append(e0);
+ e0->pChildList = 0;
+
+ e0 = new KviOptionsWidgetInstanceEntry;
+ e0->createProc = &classKviInterfaceFeaturesOptionsWidget_createInstanceProc;
+ e0->pWidget = 0;
+ e0->szClassName = g_szClassName_KviInterfaceFeaturesOptionsWidget;
+ e0->iIcon = KVI_OPTIONS_WIDGET_ICON_KviInterfaceFeaturesOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviInterfaceFeaturesOptionsWidget
+ e0->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviInterfaceFeaturesOptionsWidget;
+ #else
+ e0->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviInterfaceFeaturesOptionsWidget
+ e0->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviInterfaceFeaturesOptionsWidget;
+ e0->szKeywords = __tr2qs_ctx_no_xgettext(e0->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviInterfaceFeaturesOptionsWidget
+ e0->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviInterfaceFeaturesOptionsWidget;
+ #else
+ e0->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviInterfaceFeaturesOptionsWidget
+ e0->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviInterfaceFeaturesOptionsWidget;
+ #else
+ e0->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviInterfaceFeaturesOptionsWidget
+ e0->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviInterfaceFeaturesOptionsWidget;
+ #else
+ e0->bIsNotContained = false;
+ #endif
+ e0->szNameNoLocale = g_szName_KviInterfaceFeaturesOptionsWidget;
+ e0->szName = __tr2qs_ctx_no_xgettext(g_szName_KviInterfaceFeaturesOptionsWidget,"options");
+ m_pInstanceTree->append(e0);
+
+ e0->pChildList = new KviPointerList<KviOptionsWidgetInstanceEntry>;
+ e0->pChildList->setAutoDelete(true);
+
+ e1 = new KviOptionsWidgetInstanceEntry;
+ e1->createProc = &classKviInputFeaturesOptionsWidget_createInstanceProc;
+ e1->pWidget = 0;
+ e1->szClassName = g_szClassName_KviInputFeaturesOptionsWidget;
+ e1->iIcon = KVI_OPTIONS_WIDGET_ICON_KviInputFeaturesOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviInputFeaturesOptionsWidget
+ e1->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviInputFeaturesOptionsWidget;
+ #else
+ e1->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviInputFeaturesOptionsWidget
+ e1->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviInputFeaturesOptionsWidget;
+ e1->szKeywords = __tr2qs_ctx_no_xgettext(e1->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviInputFeaturesOptionsWidget
+ e1->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviInputFeaturesOptionsWidget;
+ #else
+ e1->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviInputFeaturesOptionsWidget
+ e1->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviInputFeaturesOptionsWidget;
+ #else
+ e1->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviInputFeaturesOptionsWidget
+ e1->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviInputFeaturesOptionsWidget;
+ #else
+ e1->bIsNotContained = false;
+ #endif
+ e1->szNameNoLocale = g_szName_KviInputFeaturesOptionsWidget;
+ e1->szName = __tr2qs_ctx_no_xgettext(g_szName_KviInputFeaturesOptionsWidget,"options");
+ e0->pChildList->append(e1);
+ e1->pChildList = 0;
+
+ e1 = new KviOptionsWidgetInstanceEntry;
+ e1->createProc = &classKviNotifierOptionsWidget_createInstanceProc;
+ e1->pWidget = 0;
+ e1->szClassName = g_szClassName_KviNotifierOptionsWidget;
+ e1->iIcon = KVI_OPTIONS_WIDGET_ICON_KviNotifierOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviNotifierOptionsWidget
+ e1->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviNotifierOptionsWidget;
+ #else
+ e1->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviNotifierOptionsWidget
+ e1->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviNotifierOptionsWidget;
+ e1->szKeywords = __tr2qs_ctx_no_xgettext(e1->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviNotifierOptionsWidget
+ e1->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviNotifierOptionsWidget;
+ #else
+ e1->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviNotifierOptionsWidget
+ e1->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviNotifierOptionsWidget;
+ #else
+ e1->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviNotifierOptionsWidget
+ e1->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviNotifierOptionsWidget;
+ #else
+ e1->bIsNotContained = false;
+ #endif
+ e1->szNameNoLocale = g_szName_KviNotifierOptionsWidget;
+ e1->szName = __tr2qs_ctx_no_xgettext(g_szName_KviNotifierOptionsWidget,"options");
+ e0->pChildList->append(e1);
+ e1->pChildList = 0;
+
+ e1 = new KviOptionsWidgetInstanceEntry;
+ e1->createProc = &classKviTrayOptionsWidget_createInstanceProc;
+ e1->pWidget = 0;
+ e1->szClassName = g_szClassName_KviTrayOptionsWidget;
+ e1->iIcon = KVI_OPTIONS_WIDGET_ICON_KviTrayOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviTrayOptionsWidget
+ e1->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviTrayOptionsWidget;
+ #else
+ e1->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviTrayOptionsWidget
+ e1->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviTrayOptionsWidget;
+ e1->szKeywords = __tr2qs_ctx_no_xgettext(e1->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviTrayOptionsWidget
+ e1->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviTrayOptionsWidget;
+ #else
+ e1->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviTrayOptionsWidget
+ e1->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviTrayOptionsWidget;
+ #else
+ e1->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviTrayOptionsWidget
+ e1->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviTrayOptionsWidget;
+ #else
+ e1->bIsNotContained = false;
+ #endif
+ e1->szNameNoLocale = g_szName_KviTrayOptionsWidget;
+ e1->szName = __tr2qs_ctx_no_xgettext(g_szName_KviTrayOptionsWidget,"options");
+ e0->pChildList->append(e1);
+ e1->pChildList = 0;
+
+ e0 = new KviOptionsWidgetInstanceEntry;
+ e0->createProc = &classKviThemeGeneralOptionsWidget_createInstanceProc;
+ e0->pWidget = 0;
+ e0->szClassName = g_szClassName_KviThemeGeneralOptionsWidget;
+ e0->iIcon = KVI_OPTIONS_WIDGET_ICON_KviThemeGeneralOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviThemeGeneralOptionsWidget
+ e0->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviThemeGeneralOptionsWidget;
+ #else
+ e0->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviThemeGeneralOptionsWidget
+ e0->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviThemeGeneralOptionsWidget;
+ e0->szKeywords = __tr2qs_ctx_no_xgettext(e0->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviThemeGeneralOptionsWidget
+ e0->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviThemeGeneralOptionsWidget;
+ #else
+ e0->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviThemeGeneralOptionsWidget
+ e0->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviThemeGeneralOptionsWidget;
+ #else
+ e0->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviThemeGeneralOptionsWidget
+ e0->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviThemeGeneralOptionsWidget;
+ #else
+ e0->bIsNotContained = false;
+ #endif
+ e0->szNameNoLocale = g_szName_KviThemeGeneralOptionsWidget;
+ e0->szName = __tr2qs_ctx_no_xgettext(g_szName_KviThemeGeneralOptionsWidget,"options");
+ m_pInstanceTree->append(e0);
+ e0->pChildList = 0;
+
+ e0 = new KviOptionsWidgetInstanceEntry;
+ e0->createProc = &classKviThemeTransparencyOptionsWidget_createInstanceProc;
+ e0->pWidget = 0;
+ e0->szClassName = g_szClassName_KviThemeTransparencyOptionsWidget;
+ e0->iIcon = KVI_OPTIONS_WIDGET_ICON_KviThemeTransparencyOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviThemeTransparencyOptionsWidget
+ e0->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviThemeTransparencyOptionsWidget;
+ #else
+ e0->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviThemeTransparencyOptionsWidget
+ e0->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviThemeTransparencyOptionsWidget;
+ e0->szKeywords = __tr2qs_ctx_no_xgettext(e0->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviThemeTransparencyOptionsWidget
+ e0->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviThemeTransparencyOptionsWidget;
+ #else
+ e0->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviThemeTransparencyOptionsWidget
+ e0->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviThemeTransparencyOptionsWidget;
+ #else
+ e0->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviThemeTransparencyOptionsWidget
+ e0->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviThemeTransparencyOptionsWidget;
+ #else
+ e0->bIsNotContained = false;
+ #endif
+ e0->szNameNoLocale = g_szName_KviThemeTransparencyOptionsWidget;
+ e0->szName = __tr2qs_ctx_no_xgettext(g_szName_KviThemeTransparencyOptionsWidget,"options");
+ m_pInstanceTree->append(e0);
+ e0->pChildList = 0;
+
+ e0 = new KviOptionsWidgetInstanceEntry;
+ e0->createProc = &classKviThemeMdiCaptionsOptionsWidget_createInstanceProc;
+ e0->pWidget = 0;
+ e0->szClassName = g_szClassName_KviThemeMdiCaptionsOptionsWidget;
+ e0->iIcon = KVI_OPTIONS_WIDGET_ICON_KviThemeMdiCaptionsOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviThemeMdiCaptionsOptionsWidget
+ e0->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviThemeMdiCaptionsOptionsWidget;
+ #else
+ e0->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviThemeMdiCaptionsOptionsWidget
+ e0->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviThemeMdiCaptionsOptionsWidget;
+ e0->szKeywords = __tr2qs_ctx_no_xgettext(e0->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviThemeMdiCaptionsOptionsWidget
+ e0->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviThemeMdiCaptionsOptionsWidget;
+ #else
+ e0->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviThemeMdiCaptionsOptionsWidget
+ e0->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviThemeMdiCaptionsOptionsWidget;
+ #else
+ e0->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviThemeMdiCaptionsOptionsWidget
+ e0->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviThemeMdiCaptionsOptionsWidget;
+ #else
+ e0->bIsNotContained = false;
+ #endif
+ e0->szNameNoLocale = g_szName_KviThemeMdiCaptionsOptionsWidget;
+ e0->szName = __tr2qs_ctx_no_xgettext(g_szName_KviThemeMdiCaptionsOptionsWidget,"options");
+ m_pInstanceTree->append(e0);
+ e0->pChildList = 0;
+
+ e0 = new KviOptionsWidgetInstanceEntry;
+ e0->createProc = &classKviThemeMdiAreaOptionsWidget_createInstanceProc;
+ e0->pWidget = 0;
+ e0->szClassName = g_szClassName_KviThemeMdiAreaOptionsWidget;
+ e0->iIcon = KVI_OPTIONS_WIDGET_ICON_KviThemeMdiAreaOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviThemeMdiAreaOptionsWidget
+ e0->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviThemeMdiAreaOptionsWidget;
+ #else
+ e0->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviThemeMdiAreaOptionsWidget
+ e0->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviThemeMdiAreaOptionsWidget;
+ e0->szKeywords = __tr2qs_ctx_no_xgettext(e0->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviThemeMdiAreaOptionsWidget
+ e0->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviThemeMdiAreaOptionsWidget;
+ #else
+ e0->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviThemeMdiAreaOptionsWidget
+ e0->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviThemeMdiAreaOptionsWidget;
+ #else
+ e0->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviThemeMdiAreaOptionsWidget
+ e0->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviThemeMdiAreaOptionsWidget;
+ #else
+ e0->bIsNotContained = false;
+ #endif
+ e0->szNameNoLocale = g_szName_KviThemeMdiAreaOptionsWidget;
+ e0->szName = __tr2qs_ctx_no_xgettext(g_szName_KviThemeMdiAreaOptionsWidget,"options");
+ m_pInstanceTree->append(e0);
+ e0->pChildList = 0;
+
+ e0 = new KviOptionsWidgetInstanceEntry;
+ e0->createProc = &classKviThemeToolBarAppletsOptionsWidget_createInstanceProc;
+ e0->pWidget = 0;
+ e0->szClassName = g_szClassName_KviThemeToolBarAppletsOptionsWidget;
+ e0->iIcon = KVI_OPTIONS_WIDGET_ICON_KviThemeToolBarAppletsOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviThemeToolBarAppletsOptionsWidget
+ e0->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviThemeToolBarAppletsOptionsWidget;
+ #else
+ e0->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviThemeToolBarAppletsOptionsWidget
+ e0->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviThemeToolBarAppletsOptionsWidget;
+ e0->szKeywords = __tr2qs_ctx_no_xgettext(e0->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviThemeToolBarAppletsOptionsWidget
+ e0->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviThemeToolBarAppletsOptionsWidget;
+ #else
+ e0->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviThemeToolBarAppletsOptionsWidget
+ e0->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviThemeToolBarAppletsOptionsWidget;
+ #else
+ e0->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviThemeToolBarAppletsOptionsWidget
+ e0->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviThemeToolBarAppletsOptionsWidget;
+ #else
+ e0->bIsNotContained = false;
+ #endif
+ e0->szNameNoLocale = g_szName_KviThemeToolBarAppletsOptionsWidget;
+ e0->szName = __tr2qs_ctx_no_xgettext(g_szName_KviThemeToolBarAppletsOptionsWidget,"options");
+ m_pInstanceTree->append(e0);
+ e0->pChildList = 0;
+
+ e0 = new KviOptionsWidgetInstanceEntry;
+ e0->createProc = &classKviIrcOptionsWidget_createInstanceProc;
+ e0->pWidget = 0;
+ e0->szClassName = g_szClassName_KviIrcOptionsWidget;
+ e0->iIcon = KVI_OPTIONS_WIDGET_ICON_KviIrcOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviIrcOptionsWidget
+ e0->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviIrcOptionsWidget;
+ #else
+ e0->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviIrcOptionsWidget
+ e0->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviIrcOptionsWidget;
+ e0->szKeywords = __tr2qs_ctx_no_xgettext(e0->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviIrcOptionsWidget
+ e0->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviIrcOptionsWidget;
+ #else
+ e0->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviIrcOptionsWidget
+ e0->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviIrcOptionsWidget;
+ #else
+ e0->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviIrcOptionsWidget
+ e0->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviIrcOptionsWidget;
+ #else
+ e0->bIsNotContained = false;
+ #endif
+ e0->szNameNoLocale = g_szName_KviIrcOptionsWidget;
+ e0->szName = __tr2qs_ctx_no_xgettext(g_szName_KviIrcOptionsWidget,"options");
+ m_pInstanceTree->append(e0);
+
+ e0->pChildList = new KviPointerList<KviOptionsWidgetInstanceEntry>;
+ e0->pChildList->setAutoDelete(true);
+
+ e1 = new KviOptionsWidgetInstanceEntry;
+ e1->createProc = &classKviIrcGeneralOptionsWidget_createInstanceProc;
+ e1->pWidget = 0;
+ e1->szClassName = g_szClassName_KviIrcGeneralOptionsWidget;
+ e1->iIcon = KVI_OPTIONS_WIDGET_ICON_KviIrcGeneralOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviIrcGeneralOptionsWidget
+ e1->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviIrcGeneralOptionsWidget;
+ #else
+ e1->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviIrcGeneralOptionsWidget
+ e1->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviIrcGeneralOptionsWidget;
+ e1->szKeywords = __tr2qs_ctx_no_xgettext(e1->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviIrcGeneralOptionsWidget
+ e1->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviIrcGeneralOptionsWidget;
+ #else
+ e1->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviIrcGeneralOptionsWidget
+ e1->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviIrcGeneralOptionsWidget;
+ #else
+ e1->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviIrcGeneralOptionsWidget
+ e1->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviIrcGeneralOptionsWidget;
+ #else
+ e1->bIsNotContained = false;
+ #endif
+ e1->szNameNoLocale = g_szName_KviIrcGeneralOptionsWidget;
+ e1->szName = __tr2qs_ctx_no_xgettext(g_szName_KviIrcGeneralOptionsWidget,"options");
+ e0->pChildList->append(e1);
+ e1->pChildList = 0;
+
+ e1 = new KviOptionsWidgetInstanceEntry;
+ e1->createProc = &classKviIrcAdvancedOptionsWidget_createInstanceProc;
+ e1->pWidget = 0;
+ e1->szClassName = g_szClassName_KviIrcAdvancedOptionsWidget;
+ e1->iIcon = KVI_OPTIONS_WIDGET_ICON_KviIrcAdvancedOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviIrcAdvancedOptionsWidget
+ e1->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviIrcAdvancedOptionsWidget;
+ #else
+ e1->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviIrcAdvancedOptionsWidget
+ e1->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviIrcAdvancedOptionsWidget;
+ e1->szKeywords = __tr2qs_ctx_no_xgettext(e1->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviIrcAdvancedOptionsWidget
+ e1->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviIrcAdvancedOptionsWidget;
+ #else
+ e1->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviIrcAdvancedOptionsWidget
+ e1->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviIrcAdvancedOptionsWidget;
+ #else
+ e1->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviIrcAdvancedOptionsWidget
+ e1->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviIrcAdvancedOptionsWidget;
+ #else
+ e1->bIsNotContained = false;
+ #endif
+ e1->szNameNoLocale = g_szName_KviIrcAdvancedOptionsWidget;
+ e1->szName = __tr2qs_ctx_no_xgettext(g_szName_KviIrcAdvancedOptionsWidget,"options");
+ e0->pChildList->append(e1);
+ e1->pChildList = 0;
+
+ e1 = new KviOptionsWidgetInstanceEntry;
+ e1->createProc = &classKviChannelOptionsWidget_createInstanceProc;
+ e1->pWidget = 0;
+ e1->szClassName = g_szClassName_KviChannelOptionsWidget;
+ e1->iIcon = KVI_OPTIONS_WIDGET_ICON_KviChannelOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviChannelOptionsWidget
+ e1->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviChannelOptionsWidget;
+ #else
+ e1->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviChannelOptionsWidget
+ e1->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviChannelOptionsWidget;
+ e1->szKeywords = __tr2qs_ctx_no_xgettext(e1->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviChannelOptionsWidget
+ e1->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviChannelOptionsWidget;
+ #else
+ e1->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviChannelOptionsWidget
+ e1->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviChannelOptionsWidget;
+ #else
+ e1->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviChannelOptionsWidget
+ e1->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviChannelOptionsWidget;
+ #else
+ e1->bIsNotContained = false;
+ #endif
+ e1->szNameNoLocale = g_szName_KviChannelOptionsWidget;
+ e1->szName = __tr2qs_ctx_no_xgettext(g_szName_KviChannelOptionsWidget,"options");
+ e0->pChildList->append(e1);
+
+ e1->pChildList = new KviPointerList<KviOptionsWidgetInstanceEntry>;
+ e1->pChildList->setAutoDelete(true);
+
+ e2 = new KviOptionsWidgetInstanceEntry;
+ e2->createProc = &classKviChannelGeneralOptionsWidget_createInstanceProc;
+ e2->pWidget = 0;
+ e2->szClassName = g_szClassName_KviChannelGeneralOptionsWidget;
+ e2->iIcon = KVI_OPTIONS_WIDGET_ICON_KviChannelGeneralOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviChannelGeneralOptionsWidget
+ e2->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviChannelGeneralOptionsWidget;
+ #else
+ e2->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviChannelGeneralOptionsWidget
+ e2->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviChannelGeneralOptionsWidget;
+ e2->szKeywords = __tr2qs_ctx_no_xgettext(e2->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviChannelGeneralOptionsWidget
+ e2->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviChannelGeneralOptionsWidget;
+ #else
+ e2->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviChannelGeneralOptionsWidget
+ e2->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviChannelGeneralOptionsWidget;
+ #else
+ e2->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviChannelGeneralOptionsWidget
+ e2->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviChannelGeneralOptionsWidget;
+ #else
+ e2->bIsNotContained = false;
+ #endif
+ e2->szNameNoLocale = g_szName_KviChannelGeneralOptionsWidget;
+ e2->szName = __tr2qs_ctx_no_xgettext(g_szName_KviChannelGeneralOptionsWidget,"options");
+ e1->pChildList->append(e2);
+ e2->pChildList = 0;
+
+ e2 = new KviOptionsWidgetInstanceEntry;
+ e2->createProc = &classKviChannelAdvancedOptionsWidget_createInstanceProc;
+ e2->pWidget = 0;
+ e2->szClassName = g_szClassName_KviChannelAdvancedOptionsWidget;
+ e2->iIcon = KVI_OPTIONS_WIDGET_ICON_KviChannelAdvancedOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviChannelAdvancedOptionsWidget
+ e2->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviChannelAdvancedOptionsWidget;
+ #else
+ e2->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviChannelAdvancedOptionsWidget
+ e2->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviChannelAdvancedOptionsWidget;
+ e2->szKeywords = __tr2qs_ctx_no_xgettext(e2->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviChannelAdvancedOptionsWidget
+ e2->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviChannelAdvancedOptionsWidget;
+ #else
+ e2->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviChannelAdvancedOptionsWidget
+ e2->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviChannelAdvancedOptionsWidget;
+ #else
+ e2->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviChannelAdvancedOptionsWidget
+ e2->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviChannelAdvancedOptionsWidget;
+ #else
+ e2->bIsNotContained = false;
+ #endif
+ e2->szNameNoLocale = g_szName_KviChannelAdvancedOptionsWidget;
+ e2->szName = __tr2qs_ctx_no_xgettext(g_szName_KviChannelAdvancedOptionsWidget,"options");
+ e1->pChildList->append(e2);
+ e2->pChildList = 0;
+
+ e1 = new KviOptionsWidgetInstanceEntry;
+ e1->createProc = &classKviIrcOutputOptionsWidget_createInstanceProc;
+ e1->pWidget = 0;
+ e1->szClassName = g_szClassName_KviIrcOutputOptionsWidget;
+ e1->iIcon = KVI_OPTIONS_WIDGET_ICON_KviIrcOutputOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviIrcOutputOptionsWidget
+ e1->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviIrcOutputOptionsWidget;
+ #else
+ e1->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviIrcOutputOptionsWidget
+ e1->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviIrcOutputOptionsWidget;
+ e1->szKeywords = __tr2qs_ctx_no_xgettext(e1->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviIrcOutputOptionsWidget
+ e1->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviIrcOutputOptionsWidget;
+ #else
+ e1->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviIrcOutputOptionsWidget
+ e1->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviIrcOutputOptionsWidget;
+ #else
+ e1->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviIrcOutputOptionsWidget
+ e1->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviIrcOutputOptionsWidget;
+ #else
+ e1->bIsNotContained = false;
+ #endif
+ e1->szNameNoLocale = g_szName_KviIrcOutputOptionsWidget;
+ e1->szName = __tr2qs_ctx_no_xgettext(g_szName_KviIrcOutputOptionsWidget,"options");
+ e0->pChildList->append(e1);
+ e1->pChildList = 0;
+
+ e1 = new KviOptionsWidgetInstanceEntry;
+ e1->createProc = &classKviProtectionOptionsWidget_createInstanceProc;
+ e1->pWidget = 0;
+ e1->szClassName = g_szClassName_KviProtectionOptionsWidget;
+ e1->iIcon = KVI_OPTIONS_WIDGET_ICON_KviProtectionOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviProtectionOptionsWidget
+ e1->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviProtectionOptionsWidget;
+ #else
+ e1->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviProtectionOptionsWidget
+ e1->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviProtectionOptionsWidget;
+ e1->szKeywords = __tr2qs_ctx_no_xgettext(e1->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviProtectionOptionsWidget
+ e1->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviProtectionOptionsWidget;
+ #else
+ e1->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviProtectionOptionsWidget
+ e1->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviProtectionOptionsWidget;
+ #else
+ e1->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviProtectionOptionsWidget
+ e1->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviProtectionOptionsWidget;
+ #else
+ e1->bIsNotContained = false;
+ #endif
+ e1->szNameNoLocale = g_szName_KviProtectionOptionsWidget;
+ e1->szName = __tr2qs_ctx_no_xgettext(g_szName_KviProtectionOptionsWidget,"options");
+ e0->pChildList->append(e1);
+
+ e1->pChildList = new KviPointerList<KviOptionsWidgetInstanceEntry>;
+ e1->pChildList->setAutoDelete(true);
+
+ e2 = new KviOptionsWidgetInstanceEntry;
+ e2->createProc = &classKviAntispamOptionsWidget_createInstanceProc;
+ e2->pWidget = 0;
+ e2->szClassName = g_szClassName_KviAntispamOptionsWidget;
+ e2->iIcon = KVI_OPTIONS_WIDGET_ICON_KviAntispamOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviAntispamOptionsWidget
+ e2->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviAntispamOptionsWidget;
+ #else
+ e2->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviAntispamOptionsWidget
+ e2->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviAntispamOptionsWidget;
+ e2->szKeywords = __tr2qs_ctx_no_xgettext(e2->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviAntispamOptionsWidget
+ e2->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviAntispamOptionsWidget;
+ #else
+ e2->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviAntispamOptionsWidget
+ e2->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviAntispamOptionsWidget;
+ #else
+ e2->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviAntispamOptionsWidget
+ e2->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviAntispamOptionsWidget;
+ #else
+ e2->bIsNotContained = false;
+ #endif
+ e2->szNameNoLocale = g_szName_KviAntispamOptionsWidget;
+ e2->szName = __tr2qs_ctx_no_xgettext(g_szName_KviAntispamOptionsWidget,"options");
+ e1->pChildList->append(e2);
+ e2->pChildList = 0;
+
+ e2 = new KviOptionsWidgetInstanceEntry;
+ e2->createProc = &classKviCtcpFloodProtectionOptionsWidget_createInstanceProc;
+ e2->pWidget = 0;
+ e2->szClassName = g_szClassName_KviCtcpFloodProtectionOptionsWidget;
+ e2->iIcon = KVI_OPTIONS_WIDGET_ICON_KviCtcpFloodProtectionOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviCtcpFloodProtectionOptionsWidget
+ e2->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviCtcpFloodProtectionOptionsWidget;
+ #else
+ e2->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviCtcpFloodProtectionOptionsWidget
+ e2->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviCtcpFloodProtectionOptionsWidget;
+ e2->szKeywords = __tr2qs_ctx_no_xgettext(e2->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviCtcpFloodProtectionOptionsWidget
+ e2->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviCtcpFloodProtectionOptionsWidget;
+ #else
+ e2->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviCtcpFloodProtectionOptionsWidget
+ e2->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviCtcpFloodProtectionOptionsWidget;
+ #else
+ e2->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviCtcpFloodProtectionOptionsWidget
+ e2->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviCtcpFloodProtectionOptionsWidget;
+ #else
+ e2->bIsNotContained = false;
+ #endif
+ e2->szNameNoLocale = g_szName_KviCtcpFloodProtectionOptionsWidget;
+ e2->szName = __tr2qs_ctx_no_xgettext(g_szName_KviCtcpFloodProtectionOptionsWidget,"options");
+ e1->pChildList->append(e2);
+ e2->pChildList = 0;
+
+ e2 = new KviOptionsWidgetInstanceEntry;
+ e2->createProc = &classKviIgnoreOptionsWidget_createInstanceProc;
+ e2->pWidget = 0;
+ e2->szClassName = g_szClassName_KviIgnoreOptionsWidget;
+ e2->iIcon = KVI_OPTIONS_WIDGET_ICON_KviIgnoreOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviIgnoreOptionsWidget
+ e2->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviIgnoreOptionsWidget;
+ #else
+ e2->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviIgnoreOptionsWidget
+ e2->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviIgnoreOptionsWidget;
+ e2->szKeywords = __tr2qs_ctx_no_xgettext(e2->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviIgnoreOptionsWidget
+ e2->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviIgnoreOptionsWidget;
+ #else
+ e2->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviIgnoreOptionsWidget
+ e2->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviIgnoreOptionsWidget;
+ #else
+ e2->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviIgnoreOptionsWidget
+ e2->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviIgnoreOptionsWidget;
+ #else
+ e2->bIsNotContained = false;
+ #endif
+ e2->szNameNoLocale = g_szName_KviIgnoreOptionsWidget;
+ e2->szName = __tr2qs_ctx_no_xgettext(g_szName_KviIgnoreOptionsWidget,"options");
+ e1->pChildList->append(e2);
+ e2->pChildList = 0;
+
+ e1 = new KviOptionsWidgetInstanceEntry;
+ e1->createProc = &classKviQueryOptionsWidget_createInstanceProc;
+ e1->pWidget = 0;
+ e1->szClassName = g_szClassName_KviQueryOptionsWidget;
+ e1->iIcon = KVI_OPTIONS_WIDGET_ICON_KviQueryOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviQueryOptionsWidget
+ e1->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviQueryOptionsWidget;
+ #else
+ e1->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviQueryOptionsWidget
+ e1->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviQueryOptionsWidget;
+ e1->szKeywords = __tr2qs_ctx_no_xgettext(e1->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviQueryOptionsWidget
+ e1->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviQueryOptionsWidget;
+ #else
+ e1->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviQueryOptionsWidget
+ e1->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviQueryOptionsWidget;
+ #else
+ e1->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviQueryOptionsWidget
+ e1->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviQueryOptionsWidget;
+ #else
+ e1->bIsNotContained = false;
+ #endif
+ e1->szNameNoLocale = g_szName_KviQueryOptionsWidget;
+ e1->szName = __tr2qs_ctx_no_xgettext(g_szName_KviQueryOptionsWidget,"options");
+ e0->pChildList->append(e1);
+ e1->pChildList = 0;
+
+ e1 = new KviOptionsWidgetInstanceEntry;
+ e1->createProc = &classKviToolsOptionsWidget_createInstanceProc;
+ e1->pWidget = 0;
+ e1->szClassName = g_szClassName_KviToolsOptionsWidget;
+ e1->iIcon = KVI_OPTIONS_WIDGET_ICON_KviToolsOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviToolsOptionsWidget
+ e1->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviToolsOptionsWidget;
+ #else
+ e1->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviToolsOptionsWidget
+ e1->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviToolsOptionsWidget;
+ e1->szKeywords = __tr2qs_ctx_no_xgettext(e1->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviToolsOptionsWidget
+ e1->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviToolsOptionsWidget;
+ #else
+ e1->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviToolsOptionsWidget
+ e1->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviToolsOptionsWidget;
+ #else
+ e1->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviToolsOptionsWidget
+ e1->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviToolsOptionsWidget;
+ #else
+ e1->bIsNotContained = false;
+ #endif
+ e1->szNameNoLocale = g_szName_KviToolsOptionsWidget;
+ e1->szName = __tr2qs_ctx_no_xgettext(g_szName_KviToolsOptionsWidget,"options");
+ e0->pChildList->append(e1);
+
+ e1->pChildList = new KviPointerList<KviOptionsWidgetInstanceEntry>;
+ e1->pChildList->setAutoDelete(true);
+
+ e2 = new KviOptionsWidgetInstanceEntry;
+ e2->createProc = &classKviAvatarAdvancedOptionsWidget_createInstanceProc;
+ e2->pWidget = 0;
+ e2->szClassName = g_szClassName_KviAvatarAdvancedOptionsWidget;
+ e2->iIcon = KVI_OPTIONS_WIDGET_ICON_KviAvatarAdvancedOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviAvatarAdvancedOptionsWidget
+ e2->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviAvatarAdvancedOptionsWidget;
+ #else
+ e2->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviAvatarAdvancedOptionsWidget
+ e2->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviAvatarAdvancedOptionsWidget;
+ e2->szKeywords = __tr2qs_ctx_no_xgettext(e2->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviAvatarAdvancedOptionsWidget
+ e2->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviAvatarAdvancedOptionsWidget;
+ #else
+ e2->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviAvatarAdvancedOptionsWidget
+ e2->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviAvatarAdvancedOptionsWidget;
+ #else
+ e2->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviAvatarAdvancedOptionsWidget
+ e2->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviAvatarAdvancedOptionsWidget;
+ #else
+ e2->bIsNotContained = false;
+ #endif
+ e2->szNameNoLocale = g_szName_KviAvatarAdvancedOptionsWidget;
+ e2->szName = __tr2qs_ctx_no_xgettext(g_szName_KviAvatarAdvancedOptionsWidget,"options");
+ e1->pChildList->append(e2);
+ e2->pChildList = 0;
+
+ e2 = new KviOptionsWidgetInstanceEntry;
+ e2->createProc = &classKviAwayOptionsWidget_createInstanceProc;
+ e2->pWidget = 0;
+ e2->szClassName = g_szClassName_KviAwayOptionsWidget;
+ e2->iIcon = KVI_OPTIONS_WIDGET_ICON_KviAwayOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviAwayOptionsWidget
+ e2->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviAwayOptionsWidget;
+ #else
+ e2->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviAwayOptionsWidget
+ e2->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviAwayOptionsWidget;
+ e2->szKeywords = __tr2qs_ctx_no_xgettext(e2->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviAwayOptionsWidget
+ e2->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviAwayOptionsWidget;
+ #else
+ e2->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviAwayOptionsWidget
+ e2->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviAwayOptionsWidget;
+ #else
+ e2->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviAwayOptionsWidget
+ e2->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviAwayOptionsWidget;
+ #else
+ e2->bIsNotContained = false;
+ #endif
+ e2->szNameNoLocale = g_szName_KviAwayOptionsWidget;
+ e2->szName = __tr2qs_ctx_no_xgettext(g_szName_KviAwayOptionsWidget,"options");
+ e1->pChildList->append(e2);
+ e2->pChildList = 0;
+
+ e2 = new KviOptionsWidgetInstanceEntry;
+ e2->createProc = &classKviCtcpOptionsWidget_createInstanceProc;
+ e2->pWidget = 0;
+ e2->szClassName = g_szClassName_KviCtcpOptionsWidget;
+ e2->iIcon = KVI_OPTIONS_WIDGET_ICON_KviCtcpOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviCtcpOptionsWidget
+ e2->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviCtcpOptionsWidget;
+ #else
+ e2->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviCtcpOptionsWidget
+ e2->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviCtcpOptionsWidget;
+ e2->szKeywords = __tr2qs_ctx_no_xgettext(e2->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviCtcpOptionsWidget
+ e2->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviCtcpOptionsWidget;
+ #else
+ e2->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviCtcpOptionsWidget
+ e2->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviCtcpOptionsWidget;
+ #else
+ e2->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviCtcpOptionsWidget
+ e2->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviCtcpOptionsWidget;
+ #else
+ e2->bIsNotContained = false;
+ #endif
+ e2->szNameNoLocale = g_szName_KviCtcpOptionsWidget;
+ e2->szName = __tr2qs_ctx_no_xgettext(g_szName_KviCtcpOptionsWidget,"options");
+ e1->pChildList->append(e2);
+ e2->pChildList = 0;
+
+ e2 = new KviOptionsWidgetInstanceEntry;
+ e2->createProc = &classKviAlertHighlightingOptionsWidget_createInstanceProc;
+ e2->pWidget = 0;
+ e2->szClassName = g_szClassName_KviAlertHighlightingOptionsWidget;
+ e2->iIcon = KVI_OPTIONS_WIDGET_ICON_KviAlertHighlightingOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviAlertHighlightingOptionsWidget
+ e2->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviAlertHighlightingOptionsWidget;
+ #else
+ e2->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviAlertHighlightingOptionsWidget
+ e2->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviAlertHighlightingOptionsWidget;
+ e2->szKeywords = __tr2qs_ctx_no_xgettext(e2->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviAlertHighlightingOptionsWidget
+ e2->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviAlertHighlightingOptionsWidget;
+ #else
+ e2->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviAlertHighlightingOptionsWidget
+ e2->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviAlertHighlightingOptionsWidget;
+ #else
+ e2->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviAlertHighlightingOptionsWidget
+ e2->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviAlertHighlightingOptionsWidget;
+ #else
+ e2->bIsNotContained = false;
+ #endif
+ e2->szNameNoLocale = g_szName_KviAlertHighlightingOptionsWidget;
+ e2->szName = __tr2qs_ctx_no_xgettext(g_szName_KviAlertHighlightingOptionsWidget,"options");
+ e1->pChildList->append(e2);
+
+ e2->pChildList = new KviPointerList<KviOptionsWidgetInstanceEntry>;
+ e2->pChildList->setAutoDelete(true);
+
+ KviOptionsWidgetInstanceEntry * e3;
+ e3 = new KviOptionsWidgetInstanceEntry;
+ e3->createProc = &classKviHighlightingOptionsWidget_createInstanceProc;
+ e3->pWidget = 0;
+ e3->szClassName = g_szClassName_KviHighlightingOptionsWidget;
+ e3->iIcon = KVI_OPTIONS_WIDGET_ICON_KviHighlightingOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviHighlightingOptionsWidget
+ e3->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviHighlightingOptionsWidget;
+ #else
+ e3->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviHighlightingOptionsWidget
+ e3->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviHighlightingOptionsWidget;
+ e3->szKeywords = __tr2qs_ctx_no_xgettext(e3->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviHighlightingOptionsWidget
+ e3->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviHighlightingOptionsWidget;
+ #else
+ e3->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviHighlightingOptionsWidget
+ e3->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviHighlightingOptionsWidget;
+ #else
+ e3->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviHighlightingOptionsWidget
+ e3->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviHighlightingOptionsWidget;
+ #else
+ e3->bIsNotContained = false;
+ #endif
+ e3->szNameNoLocale = g_szName_KviHighlightingOptionsWidget;
+ e3->szName = __tr2qs_ctx_no_xgettext(g_szName_KviHighlightingOptionsWidget,"options");
+ e2->pChildList->append(e3);
+ e3->pChildList = 0;
+
+ e3 = new KviOptionsWidgetInstanceEntry;
+ e3->createProc = &classKviAlertOptionsWidget_createInstanceProc;
+ e3->pWidget = 0;
+ e3->szClassName = g_szClassName_KviAlertOptionsWidget;
+ e3->iIcon = KVI_OPTIONS_WIDGET_ICON_KviAlertOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviAlertOptionsWidget
+ e3->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviAlertOptionsWidget;
+ #else
+ e3->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviAlertOptionsWidget
+ e3->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviAlertOptionsWidget;
+ e3->szKeywords = __tr2qs_ctx_no_xgettext(e3->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviAlertOptionsWidget
+ e3->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviAlertOptionsWidget;
+ #else
+ e3->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviAlertOptionsWidget
+ e3->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviAlertOptionsWidget;
+ #else
+ e3->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviAlertOptionsWidget
+ e3->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviAlertOptionsWidget;
+ #else
+ e3->bIsNotContained = false;
+ #endif
+ e3->szNameNoLocale = g_szName_KviAlertOptionsWidget;
+ e3->szName = __tr2qs_ctx_no_xgettext(g_szName_KviAlertOptionsWidget,"options");
+ e2->pChildList->append(e3);
+ e3->pChildList = 0;
+
+ e2 = new KviOptionsWidgetInstanceEntry;
+ e2->createProc = &classKviLagOptionsWidget_createInstanceProc;
+ e2->pWidget = 0;
+ e2->szClassName = g_szClassName_KviLagOptionsWidget;
+ e2->iIcon = KVI_OPTIONS_WIDGET_ICON_KviLagOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviLagOptionsWidget
+ e2->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviLagOptionsWidget;
+ #else
+ e2->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviLagOptionsWidget
+ e2->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviLagOptionsWidget;
+ e2->szKeywords = __tr2qs_ctx_no_xgettext(e2->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviLagOptionsWidget
+ e2->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviLagOptionsWidget;
+ #else
+ e2->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviLagOptionsWidget
+ e2->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviLagOptionsWidget;
+ #else
+ e2->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviLagOptionsWidget
+ e2->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviLagOptionsWidget;
+ #else
+ e2->bIsNotContained = false;
+ #endif
+ e2->szNameNoLocale = g_szName_KviLagOptionsWidget;
+ e2->szName = __tr2qs_ctx_no_xgettext(g_szName_KviLagOptionsWidget,"options");
+ e1->pChildList->append(e2);
+ e2->pChildList = 0;
+
+ e2 = new KviOptionsWidgetInstanceEntry;
+ e2->createProc = &classKviLoggingOptionsWidget_createInstanceProc;
+ e2->pWidget = 0;
+ e2->szClassName = g_szClassName_KviLoggingOptionsWidget;
+ e2->iIcon = KVI_OPTIONS_WIDGET_ICON_KviLoggingOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviLoggingOptionsWidget
+ e2->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviLoggingOptionsWidget;
+ #else
+ e2->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviLoggingOptionsWidget
+ e2->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviLoggingOptionsWidget;
+ e2->szKeywords = __tr2qs_ctx_no_xgettext(e2->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviLoggingOptionsWidget
+ e2->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviLoggingOptionsWidget;
+ #else
+ e2->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviLoggingOptionsWidget
+ e2->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviLoggingOptionsWidget;
+ #else
+ e2->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviLoggingOptionsWidget
+ e2->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviLoggingOptionsWidget;
+ #else
+ e2->bIsNotContained = false;
+ #endif
+ e2->szNameNoLocale = g_szName_KviLoggingOptionsWidget;
+ e2->szName = __tr2qs_ctx_no_xgettext(g_szName_KviLoggingOptionsWidget,"options");
+ e1->pChildList->append(e2);
+ e2->pChildList = 0;
+
+ e2 = new KviOptionsWidgetInstanceEntry;
+ e2->createProc = &classKviNickServOptionsWidget_createInstanceProc;
+ e2->pWidget = 0;
+ e2->szClassName = g_szClassName_KviNickServOptionsWidget;
+ e2->iIcon = KVI_OPTIONS_WIDGET_ICON_KviNickServOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviNickServOptionsWidget
+ e2->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviNickServOptionsWidget;
+ #else
+ e2->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviNickServOptionsWidget
+ e2->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviNickServOptionsWidget;
+ e2->szKeywords = __tr2qs_ctx_no_xgettext(e2->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviNickServOptionsWidget
+ e2->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviNickServOptionsWidget;
+ #else
+ e2->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviNickServOptionsWidget
+ e2->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviNickServOptionsWidget;
+ #else
+ e2->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviNickServOptionsWidget
+ e2->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviNickServOptionsWidget;
+ #else
+ e2->bIsNotContained = false;
+ #endif
+ e2->szNameNoLocale = g_szName_KviNickServOptionsWidget;
+ e2->szName = __tr2qs_ctx_no_xgettext(g_szName_KviNickServOptionsWidget,"options");
+ e1->pChildList->append(e2);
+ e2->pChildList = 0;
+
+ e2 = new KviOptionsWidgetInstanceEntry;
+ e2->createProc = &classKviNotifyOptionsWidget_createInstanceProc;
+ e2->pWidget = 0;
+ e2->szClassName = g_szClassName_KviNotifyOptionsWidget;
+ e2->iIcon = KVI_OPTIONS_WIDGET_ICON_KviNotifyOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviNotifyOptionsWidget
+ e2->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviNotifyOptionsWidget;
+ #else
+ e2->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviNotifyOptionsWidget
+ e2->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviNotifyOptionsWidget;
+ e2->szKeywords = __tr2qs_ctx_no_xgettext(e2->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviNotifyOptionsWidget
+ e2->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviNotifyOptionsWidget;
+ #else
+ e2->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviNotifyOptionsWidget
+ e2->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviNotifyOptionsWidget;
+ #else
+ e2->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviNotifyOptionsWidget
+ e2->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviNotifyOptionsWidget;
+ #else
+ e2->bIsNotContained = false;
+ #endif
+ e2->szNameNoLocale = g_szName_KviNotifyOptionsWidget;
+ e2->szName = __tr2qs_ctx_no_xgettext(g_szName_KviNotifyOptionsWidget,"options");
+ e1->pChildList->append(e2);
+ e2->pChildList = 0;
+
+ e2 = new KviOptionsWidgetInstanceEntry;
+ e2->createProc = &classKviTextIconsOptionsWidget_createInstanceProc;
+ e2->pWidget = 0;
+ e2->szClassName = g_szClassName_KviTextIconsOptionsWidget;
+ e2->iIcon = KVI_OPTIONS_WIDGET_ICON_KviTextIconsOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviTextIconsOptionsWidget
+ e2->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviTextIconsOptionsWidget;
+ #else
+ e2->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviTextIconsOptionsWidget
+ e2->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviTextIconsOptionsWidget;
+ e2->szKeywords = __tr2qs_ctx_no_xgettext(e2->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviTextIconsOptionsWidget
+ e2->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviTextIconsOptionsWidget;
+ #else
+ e2->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviTextIconsOptionsWidget
+ e2->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviTextIconsOptionsWidget;
+ #else
+ e2->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviTextIconsOptionsWidget
+ e2->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviTextIconsOptionsWidget;
+ #else
+ e2->bIsNotContained = false;
+ #endif
+ e2->szNameNoLocale = g_szName_KviTextIconsOptionsWidget;
+ e2->szName = __tr2qs_ctx_no_xgettext(g_szName_KviTextIconsOptionsWidget,"options");
+ e1->pChildList->append(e2);
+ e2->pChildList = 0;
+
+ e0 = new KviOptionsWidgetInstanceEntry;
+ e0->createProc = &classKviIrcViewThemeOptionsWidget_createInstanceProc;
+ e0->pWidget = 0;
+ e0->szClassName = g_szClassName_KviIrcViewThemeOptionsWidget;
+ e0->iIcon = KVI_OPTIONS_WIDGET_ICON_KviIrcViewThemeOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviIrcViewThemeOptionsWidget
+ e0->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviIrcViewThemeOptionsWidget;
+ #else
+ e0->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviIrcViewThemeOptionsWidget
+ e0->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviIrcViewThemeOptionsWidget;
+ e0->szKeywords = __tr2qs_ctx_no_xgettext(e0->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviIrcViewThemeOptionsWidget
+ e0->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviIrcViewThemeOptionsWidget;
+ #else
+ e0->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviIrcViewThemeOptionsWidget
+ e0->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviIrcViewThemeOptionsWidget;
+ #else
+ e0->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviIrcViewThemeOptionsWidget
+ e0->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviIrcViewThemeOptionsWidget;
+ #else
+ e0->bIsNotContained = false;
+ #endif
+ e0->szNameNoLocale = g_szName_KviIrcViewThemeOptionsWidget;
+ e0->szName = __tr2qs_ctx_no_xgettext(g_szName_KviIrcViewThemeOptionsWidget,"options");
+ m_pInstanceTree->append(e0);
+
+ e0->pChildList = new KviPointerList<KviOptionsWidgetInstanceEntry>;
+ e0->pChildList->setAutoDelete(true);
+
+ e1 = new KviOptionsWidgetInstanceEntry;
+ e1->createProc = &classKviIrcViewLookOptionsWidget_createInstanceProc;
+ e1->pWidget = 0;
+ e1->szClassName = g_szClassName_KviIrcViewLookOptionsWidget;
+ e1->iIcon = KVI_OPTIONS_WIDGET_ICON_KviIrcViewLookOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviIrcViewLookOptionsWidget
+ e1->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviIrcViewLookOptionsWidget;
+ #else
+ e1->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviIrcViewLookOptionsWidget
+ e1->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviIrcViewLookOptionsWidget;
+ e1->szKeywords = __tr2qs_ctx_no_xgettext(e1->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviIrcViewLookOptionsWidget
+ e1->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviIrcViewLookOptionsWidget;
+ #else
+ e1->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviIrcViewLookOptionsWidget
+ e1->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviIrcViewLookOptionsWidget;
+ #else
+ e1->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviIrcViewLookOptionsWidget
+ e1->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviIrcViewLookOptionsWidget;
+ #else
+ e1->bIsNotContained = false;
+ #endif
+ e1->szNameNoLocale = g_szName_KviIrcViewLookOptionsWidget;
+ e1->szName = __tr2qs_ctx_no_xgettext(g_szName_KviIrcViewLookOptionsWidget,"options");
+ e0->pChildList->append(e1);
+ e1->pChildList = 0;
+
+ e1 = new KviOptionsWidgetInstanceEntry;
+ e1->createProc = &classKviIrcViewFeaturesOptionsWidget_createInstanceProc;
+ e1->pWidget = 0;
+ e1->szClassName = g_szClassName_KviIrcViewFeaturesOptionsWidget;
+ e1->iIcon = KVI_OPTIONS_WIDGET_ICON_KviIrcViewFeaturesOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviIrcViewFeaturesOptionsWidget
+ e1->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviIrcViewFeaturesOptionsWidget;
+ #else
+ e1->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviIrcViewFeaturesOptionsWidget
+ e1->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviIrcViewFeaturesOptionsWidget;
+ e1->szKeywords = __tr2qs_ctx_no_xgettext(e1->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviIrcViewFeaturesOptionsWidget
+ e1->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviIrcViewFeaturesOptionsWidget;
+ #else
+ e1->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviIrcViewFeaturesOptionsWidget
+ e1->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviIrcViewFeaturesOptionsWidget;
+ #else
+ e1->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviIrcViewFeaturesOptionsWidget
+ e1->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviIrcViewFeaturesOptionsWidget;
+ #else
+ e1->bIsNotContained = false;
+ #endif
+ e1->szNameNoLocale = g_szName_KviIrcViewFeaturesOptionsWidget;
+ e1->szName = __tr2qs_ctx_no_xgettext(g_szName_KviIrcViewFeaturesOptionsWidget,"options");
+ e0->pChildList->append(e1);
+ e1->pChildList = 0;
+
+ e0 = new KviOptionsWidgetInstanceEntry;
+ e0->createProc = &classKviMessageOptionsWidget_createInstanceProc;
+ e0->pWidget = 0;
+ e0->szClassName = g_szClassName_KviMessageOptionsWidget;
+ e0->iIcon = KVI_OPTIONS_WIDGET_ICON_KviMessageOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviMessageOptionsWidget
+ e0->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviMessageOptionsWidget;
+ #else
+ e0->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviMessageOptionsWidget
+ e0->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviMessageOptionsWidget;
+ e0->szKeywords = __tr2qs_ctx_no_xgettext(e0->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviMessageOptionsWidget
+ e0->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviMessageOptionsWidget;
+ #else
+ e0->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviMessageOptionsWidget
+ e0->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviMessageOptionsWidget;
+ #else
+ e0->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviMessageOptionsWidget
+ e0->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviMessageOptionsWidget;
+ #else
+ e0->bIsNotContained = false;
+ #endif
+ e0->szNameNoLocale = g_szName_KviMessageOptionsWidget;
+ e0->szName = __tr2qs_ctx_no_xgettext(g_szName_KviMessageOptionsWidget,"options");
+ m_pInstanceTree->append(e0);
+
+ e0->pChildList = new KviPointerList<KviOptionsWidgetInstanceEntry>;
+ e0->pChildList->setAutoDelete(true);
+
+ e1 = new KviOptionsWidgetInstanceEntry;
+ e1->createProc = &classKviPrivmsgOptionsWidget_createInstanceProc;
+ e1->pWidget = 0;
+ e1->szClassName = g_szClassName_KviPrivmsgOptionsWidget;
+ e1->iIcon = KVI_OPTIONS_WIDGET_ICON_KviPrivmsgOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviPrivmsgOptionsWidget
+ e1->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviPrivmsgOptionsWidget;
+ #else
+ e1->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviPrivmsgOptionsWidget
+ e1->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviPrivmsgOptionsWidget;
+ e1->szKeywords = __tr2qs_ctx_no_xgettext(e1->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviPrivmsgOptionsWidget
+ e1->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviPrivmsgOptionsWidget;
+ #else
+ e1->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviPrivmsgOptionsWidget
+ e1->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviPrivmsgOptionsWidget;
+ #else
+ e1->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviPrivmsgOptionsWidget
+ e1->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviPrivmsgOptionsWidget;
+ #else
+ e1->bIsNotContained = false;
+ #endif
+ e1->szNameNoLocale = g_szName_KviPrivmsgOptionsWidget;
+ e1->szName = __tr2qs_ctx_no_xgettext(g_szName_KviPrivmsgOptionsWidget,"options");
+ e0->pChildList->append(e1);
+ e1->pChildList = 0;
+
+ e1 = new KviOptionsWidgetInstanceEntry;
+ e1->createProc = &classKviTimestampOptionsWidget_createInstanceProc;
+ e1->pWidget = 0;
+ e1->szClassName = g_szClassName_KviTimestampOptionsWidget;
+ e1->iIcon = KVI_OPTIONS_WIDGET_ICON_KviTimestampOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviTimestampOptionsWidget
+ e1->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviTimestampOptionsWidget;
+ #else
+ e1->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviTimestampOptionsWidget
+ e1->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviTimestampOptionsWidget;
+ e1->szKeywords = __tr2qs_ctx_no_xgettext(e1->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviTimestampOptionsWidget
+ e1->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviTimestampOptionsWidget;
+ #else
+ e1->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviTimestampOptionsWidget
+ e1->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviTimestampOptionsWidget;
+ #else
+ e1->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviTimestampOptionsWidget
+ e1->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviTimestampOptionsWidget;
+ #else
+ e1->bIsNotContained = false;
+ #endif
+ e1->szNameNoLocale = g_szName_KviTimestampOptionsWidget;
+ e1->szName = __tr2qs_ctx_no_xgettext(g_szName_KviTimestampOptionsWidget,"options");
+ e0->pChildList->append(e1);
+ e1->pChildList = 0;
+
+ e1 = new KviOptionsWidgetInstanceEntry;
+ e1->createProc = &classKviMessageColorsOptionsWidget_createInstanceProc;
+ e1->pWidget = 0;
+ e1->szClassName = g_szClassName_KviMessageColorsOptionsWidget;
+ e1->iIcon = KVI_OPTIONS_WIDGET_ICON_KviMessageColorsOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviMessageColorsOptionsWidget
+ e1->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviMessageColorsOptionsWidget;
+ #else
+ e1->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviMessageColorsOptionsWidget
+ e1->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviMessageColorsOptionsWidget;
+ e1->szKeywords = __tr2qs_ctx_no_xgettext(e1->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviMessageColorsOptionsWidget
+ e1->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviMessageColorsOptionsWidget;
+ #else
+ e1->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviMessageColorsOptionsWidget
+ e1->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviMessageColorsOptionsWidget;
+ #else
+ e1->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviMessageColorsOptionsWidget
+ e1->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviMessageColorsOptionsWidget;
+ #else
+ e1->bIsNotContained = false;
+ #endif
+ e1->szNameNoLocale = g_szName_KviMessageColorsOptionsWidget;
+ e1->szName = __tr2qs_ctx_no_xgettext(g_szName_KviMessageColorsOptionsWidget,"options");
+ e0->pChildList->append(e1);
+ e1->pChildList = 0;
+
+ e1 = new KviOptionsWidgetInstanceEntry;
+ e1->createProc = &classKviStandardColorsOptionsWidget_createInstanceProc;
+ e1->pWidget = 0;
+ e1->szClassName = g_szClassName_KviStandardColorsOptionsWidget;
+ e1->iIcon = KVI_OPTIONS_WIDGET_ICON_KviStandardColorsOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviStandardColorsOptionsWidget
+ e1->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviStandardColorsOptionsWidget;
+ #else
+ e1->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviStandardColorsOptionsWidget
+ e1->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviStandardColorsOptionsWidget;
+ e1->szKeywords = __tr2qs_ctx_no_xgettext(e1->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviStandardColorsOptionsWidget
+ e1->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviStandardColorsOptionsWidget;
+ #else
+ e1->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviStandardColorsOptionsWidget
+ e1->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviStandardColorsOptionsWidget;
+ #else
+ e1->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviStandardColorsOptionsWidget
+ e1->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviStandardColorsOptionsWidget;
+ #else
+ e1->bIsNotContained = false;
+ #endif
+ e1->szNameNoLocale = g_szName_KviStandardColorsOptionsWidget;
+ e1->szName = __tr2qs_ctx_no_xgettext(g_szName_KviStandardColorsOptionsWidget,"options");
+ e0->pChildList->append(e1);
+ e1->pChildList = 0;
+
+ e0 = new KviOptionsWidgetInstanceEntry;
+ e0->createProc = &classKviServerOptionsWidget_createInstanceProc;
+ e0->pWidget = 0;
+ e0->szClassName = g_szClassName_KviServerOptionsWidget;
+ e0->iIcon = KVI_OPTIONS_WIDGET_ICON_KviServerOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviServerOptionsWidget
+ e0->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviServerOptionsWidget;
+ #else
+ e0->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviServerOptionsWidget
+ e0->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviServerOptionsWidget;
+ e0->szKeywords = __tr2qs_ctx_no_xgettext(e0->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviServerOptionsWidget
+ e0->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviServerOptionsWidget;
+ #else
+ e0->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviServerOptionsWidget
+ e0->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviServerOptionsWidget;
+ #else
+ e0->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviServerOptionsWidget
+ e0->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviServerOptionsWidget;
+ #else
+ e0->bIsNotContained = false;
+ #endif
+ e0->szNameNoLocale = g_szName_KviServerOptionsWidget;
+ e0->szName = __tr2qs_ctx_no_xgettext(g_szName_KviServerOptionsWidget,"options");
+ m_pInstanceTree->append(e0);
+ e0->pChildList = 0;
+
+ e0 = new KviOptionsWidgetInstanceEntry;
+ e0->createProc = &classKviTaskBarOptionsWidget_createInstanceProc;
+ e0->pWidget = 0;
+ e0->szClassName = g_szClassName_KviTaskBarOptionsWidget;
+ e0->iIcon = KVI_OPTIONS_WIDGET_ICON_KviTaskBarOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviTaskBarOptionsWidget
+ e0->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviTaskBarOptionsWidget;
+ #else
+ e0->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviTaskBarOptionsWidget
+ e0->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviTaskBarOptionsWidget;
+ e0->szKeywords = __tr2qs_ctx_no_xgettext(e0->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviTaskBarOptionsWidget
+ e0->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviTaskBarOptionsWidget;
+ #else
+ e0->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviTaskBarOptionsWidget
+ e0->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviTaskBarOptionsWidget;
+ #else
+ e0->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviTaskBarOptionsWidget
+ e0->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviTaskBarOptionsWidget;
+ #else
+ e0->bIsNotContained = false;
+ #endif
+ e0->szNameNoLocale = g_szName_KviTaskBarOptionsWidget;
+ e0->szName = __tr2qs_ctx_no_xgettext(g_szName_KviTaskBarOptionsWidget,"options");
+ m_pInstanceTree->append(e0);
+
+ e0->pChildList = new KviPointerList<KviOptionsWidgetInstanceEntry>;
+ e0->pChildList->setAutoDelete(true);
+
+ e1 = new KviOptionsWidgetInstanceEntry;
+ e1->createProc = &classKviTreeTaskBarOptionsWidget_createInstanceProc;
+ e1->pWidget = 0;
+ e1->szClassName = g_szClassName_KviTreeTaskBarOptionsWidget;
+ e1->iIcon = KVI_OPTIONS_WIDGET_ICON_KviTreeTaskBarOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviTreeTaskBarOptionsWidget
+ e1->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviTreeTaskBarOptionsWidget;
+ #else
+ e1->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviTreeTaskBarOptionsWidget
+ e1->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviTreeTaskBarOptionsWidget;
+ e1->szKeywords = __tr2qs_ctx_no_xgettext(e1->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviTreeTaskBarOptionsWidget
+ e1->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviTreeTaskBarOptionsWidget;
+ #else
+ e1->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviTreeTaskBarOptionsWidget
+ e1->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviTreeTaskBarOptionsWidget;
+ #else
+ e1->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviTreeTaskBarOptionsWidget
+ e1->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviTreeTaskBarOptionsWidget;
+ #else
+ e1->bIsNotContained = false;
+ #endif
+ e1->szNameNoLocale = g_szName_KviTreeTaskBarOptionsWidget;
+ e1->szName = __tr2qs_ctx_no_xgettext(g_szName_KviTreeTaskBarOptionsWidget,"options");
+ e0->pChildList->append(e1);
+
+ e1->pChildList = new KviPointerList<KviOptionsWidgetInstanceEntry>;
+ e1->pChildList->setAutoDelete(true);
+
+ e2 = new KviOptionsWidgetInstanceEntry;
+ e2->createProc = &classKviTreeTaskBarForegroundOptionsWidget_createInstanceProc;
+ e2->pWidget = 0;
+ e2->szClassName = g_szClassName_KviTreeTaskBarForegroundOptionsWidget;
+ e2->iIcon = KVI_OPTIONS_WIDGET_ICON_KviTreeTaskBarForegroundOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviTreeTaskBarForegroundOptionsWidget
+ e2->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviTreeTaskBarForegroundOptionsWidget;
+ #else
+ e2->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviTreeTaskBarForegroundOptionsWidget
+ e2->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviTreeTaskBarForegroundOptionsWidget;
+ e2->szKeywords = __tr2qs_ctx_no_xgettext(e2->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviTreeTaskBarForegroundOptionsWidget
+ e2->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviTreeTaskBarForegroundOptionsWidget;
+ #else
+ e2->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviTreeTaskBarForegroundOptionsWidget
+ e2->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviTreeTaskBarForegroundOptionsWidget;
+ #else
+ e2->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviTreeTaskBarForegroundOptionsWidget
+ e2->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviTreeTaskBarForegroundOptionsWidget;
+ #else
+ e2->bIsNotContained = false;
+ #endif
+ e2->szNameNoLocale = g_szName_KviTreeTaskBarForegroundOptionsWidget;
+ e2->szName = __tr2qs_ctx_no_xgettext(g_szName_KviTreeTaskBarForegroundOptionsWidget,"options");
+ e1->pChildList->append(e2);
+ e2->pChildList = 0;
+
+ e2 = new KviOptionsWidgetInstanceEntry;
+ e2->createProc = &classKviTreeTaskBarBackgroundOptionsWidget_createInstanceProc;
+ e2->pWidget = 0;
+ e2->szClassName = g_szClassName_KviTreeTaskBarBackgroundOptionsWidget;
+ e2->iIcon = KVI_OPTIONS_WIDGET_ICON_KviTreeTaskBarBackgroundOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviTreeTaskBarBackgroundOptionsWidget
+ e2->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviTreeTaskBarBackgroundOptionsWidget;
+ #else
+ e2->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviTreeTaskBarBackgroundOptionsWidget
+ e2->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviTreeTaskBarBackgroundOptionsWidget;
+ e2->szKeywords = __tr2qs_ctx_no_xgettext(e2->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviTreeTaskBarBackgroundOptionsWidget
+ e2->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviTreeTaskBarBackgroundOptionsWidget;
+ #else
+ e2->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviTreeTaskBarBackgroundOptionsWidget
+ e2->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviTreeTaskBarBackgroundOptionsWidget;
+ #else
+ e2->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviTreeTaskBarBackgroundOptionsWidget
+ e2->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviTreeTaskBarBackgroundOptionsWidget;
+ #else
+ e2->bIsNotContained = false;
+ #endif
+ e2->szNameNoLocale = g_szName_KviTreeTaskBarBackgroundOptionsWidget;
+ e2->szName = __tr2qs_ctx_no_xgettext(g_szName_KviTreeTaskBarBackgroundOptionsWidget,"options");
+ e1->pChildList->append(e2);
+ e2->pChildList = 0;
+
+ e2 = new KviOptionsWidgetInstanceEntry;
+ e2->createProc = &classKviTreeTaskBarFeaturesOptionsWidget_createInstanceProc;
+ e2->pWidget = 0;
+ e2->szClassName = g_szClassName_KviTreeTaskBarFeaturesOptionsWidget;
+ e2->iIcon = KVI_OPTIONS_WIDGET_ICON_KviTreeTaskBarFeaturesOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviTreeTaskBarFeaturesOptionsWidget
+ e2->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviTreeTaskBarFeaturesOptionsWidget;
+ #else
+ e2->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviTreeTaskBarFeaturesOptionsWidget
+ e2->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviTreeTaskBarFeaturesOptionsWidget;
+ e2->szKeywords = __tr2qs_ctx_no_xgettext(e2->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviTreeTaskBarFeaturesOptionsWidget
+ e2->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviTreeTaskBarFeaturesOptionsWidget;
+ #else
+ e2->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviTreeTaskBarFeaturesOptionsWidget
+ e2->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviTreeTaskBarFeaturesOptionsWidget;
+ #else
+ e2->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviTreeTaskBarFeaturesOptionsWidget
+ e2->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviTreeTaskBarFeaturesOptionsWidget;
+ #else
+ e2->bIsNotContained = false;
+ #endif
+ e2->szNameNoLocale = g_szName_KviTreeTaskBarFeaturesOptionsWidget;
+ e2->szName = __tr2qs_ctx_no_xgettext(g_szName_KviTreeTaskBarFeaturesOptionsWidget,"options");
+ e1->pChildList->append(e2);
+ e2->pChildList = 0;
+
+ e1 = new KviOptionsWidgetInstanceEntry;
+ e1->createProc = &classKviClassicTaskBarOptionsWidget_createInstanceProc;
+ e1->pWidget = 0;
+ e1->szClassName = g_szClassName_KviClassicTaskBarOptionsWidget;
+ e1->iIcon = KVI_OPTIONS_WIDGET_ICON_KviClassicTaskBarOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviClassicTaskBarOptionsWidget
+ e1->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviClassicTaskBarOptionsWidget;
+ #else
+ e1->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviClassicTaskBarOptionsWidget
+ e1->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviClassicTaskBarOptionsWidget;
+ e1->szKeywords = __tr2qs_ctx_no_xgettext(e1->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviClassicTaskBarOptionsWidget
+ e1->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviClassicTaskBarOptionsWidget;
+ #else
+ e1->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviClassicTaskBarOptionsWidget
+ e1->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviClassicTaskBarOptionsWidget;
+ #else
+ e1->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviClassicTaskBarOptionsWidget
+ e1->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviClassicTaskBarOptionsWidget;
+ #else
+ e1->bIsNotContained = false;
+ #endif
+ e1->szNameNoLocale = g_szName_KviClassicTaskBarOptionsWidget;
+ e1->szName = __tr2qs_ctx_no_xgettext(g_szName_KviClassicTaskBarOptionsWidget,"options");
+ e0->pChildList->append(e1);
+ e1->pChildList = 0;
+
+ e0 = new KviOptionsWidgetInstanceEntry;
+ e0->createProc = &classKviTopicLabelLookOptionsWidget_createInstanceProc;
+ e0->pWidget = 0;
+ e0->szClassName = g_szClassName_KviTopicLabelLookOptionsWidget;
+ e0->iIcon = KVI_OPTIONS_WIDGET_ICON_KviTopicLabelLookOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviTopicLabelLookOptionsWidget
+ e0->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviTopicLabelLookOptionsWidget;
+ #else
+ e0->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviTopicLabelLookOptionsWidget
+ e0->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviTopicLabelLookOptionsWidget;
+ e0->szKeywords = __tr2qs_ctx_no_xgettext(e0->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviTopicLabelLookOptionsWidget
+ e0->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviTopicLabelLookOptionsWidget;
+ #else
+ e0->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviTopicLabelLookOptionsWidget
+ e0->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviTopicLabelLookOptionsWidget;
+ #else
+ e0->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviTopicLabelLookOptionsWidget
+ e0->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviTopicLabelLookOptionsWidget;
+ #else
+ e0->bIsNotContained = false;
+ #endif
+ e0->szNameNoLocale = g_szName_KviTopicLabelLookOptionsWidget;
+ e0->szName = __tr2qs_ctx_no_xgettext(g_szName_KviTopicLabelLookOptionsWidget,"options");
+ m_pInstanceTree->append(e0);
+ e0->pChildList = 0;
+
+ e0 = new KviOptionsWidgetInstanceEntry;
+ e0->createProc = &classKviUserListLookOptionsWidget_createInstanceProc;
+ e0->pWidget = 0;
+ e0->szClassName = g_szClassName_KviUserListLookOptionsWidget;
+ e0->iIcon = KVI_OPTIONS_WIDGET_ICON_KviUserListLookOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviUserListLookOptionsWidget
+ e0->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviUserListLookOptionsWidget;
+ #else
+ e0->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviUserListLookOptionsWidget
+ e0->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviUserListLookOptionsWidget;
+ e0->szKeywords = __tr2qs_ctx_no_xgettext(e0->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviUserListLookOptionsWidget
+ e0->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviUserListLookOptionsWidget;
+ #else
+ e0->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviUserListLookOptionsWidget
+ e0->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviUserListLookOptionsWidget;
+ #else
+ e0->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviUserListLookOptionsWidget
+ e0->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviUserListLookOptionsWidget;
+ #else
+ e0->bIsNotContained = false;
+ #endif
+ e0->szNameNoLocale = g_szName_KviUserListLookOptionsWidget;
+ e0->szName = __tr2qs_ctx_no_xgettext(g_szName_KviUserListLookOptionsWidget,"options");
+ m_pInstanceTree->append(e0);
+
+ e0->pChildList = new KviPointerList<KviOptionsWidgetInstanceEntry>;
+ e0->pChildList->setAutoDelete(true);
+
+ e1 = new KviOptionsWidgetInstanceEntry;
+ e1->createProc = &classKviUserListLookBackgroundOptionsWidget_createInstanceProc;
+ e1->pWidget = 0;
+ e1->szClassName = g_szClassName_KviUserListLookBackgroundOptionsWidget;
+ e1->iIcon = KVI_OPTIONS_WIDGET_ICON_KviUserListLookBackgroundOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviUserListLookBackgroundOptionsWidget
+ e1->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviUserListLookBackgroundOptionsWidget;
+ #else
+ e1->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviUserListLookBackgroundOptionsWidget
+ e1->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviUserListLookBackgroundOptionsWidget;
+ e1->szKeywords = __tr2qs_ctx_no_xgettext(e1->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviUserListLookBackgroundOptionsWidget
+ e1->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviUserListLookBackgroundOptionsWidget;
+ #else
+ e1->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviUserListLookBackgroundOptionsWidget
+ e1->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviUserListLookBackgroundOptionsWidget;
+ #else
+ e1->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviUserListLookBackgroundOptionsWidget
+ e1->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviUserListLookBackgroundOptionsWidget;
+ #else
+ e1->bIsNotContained = false;
+ #endif
+ e1->szNameNoLocale = g_szName_KviUserListLookBackgroundOptionsWidget;
+ e1->szName = __tr2qs_ctx_no_xgettext(g_szName_KviUserListLookBackgroundOptionsWidget,"options");
+ e0->pChildList->append(e1);
+ e1->pChildList = 0;
+
+ e1 = new KviOptionsWidgetInstanceEntry;
+ e1->createProc = &classKviUserListLookForegroundOptionsWidget_createInstanceProc;
+ e1->pWidget = 0;
+ e1->szClassName = g_szClassName_KviUserListLookForegroundOptionsWidget;
+ e1->iIcon = KVI_OPTIONS_WIDGET_ICON_KviUserListLookForegroundOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviUserListLookForegroundOptionsWidget
+ e1->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviUserListLookForegroundOptionsWidget;
+ #else
+ e1->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviUserListLookForegroundOptionsWidget
+ e1->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviUserListLookForegroundOptionsWidget;
+ e1->szKeywords = __tr2qs_ctx_no_xgettext(e1->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviUserListLookForegroundOptionsWidget
+ e1->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviUserListLookForegroundOptionsWidget;
+ #else
+ e1->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviUserListLookForegroundOptionsWidget
+ e1->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviUserListLookForegroundOptionsWidget;
+ #else
+ e1->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviUserListLookForegroundOptionsWidget
+ e1->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviUserListLookForegroundOptionsWidget;
+ #else
+ e1->bIsNotContained = false;
+ #endif
+ e1->szNameNoLocale = g_szName_KviUserListLookForegroundOptionsWidget;
+ e1->szName = __tr2qs_ctx_no_xgettext(g_szName_KviUserListLookForegroundOptionsWidget,"options");
+ e0->pChildList->append(e1);
+ e1->pChildList = 0;
+
+ e1 = new KviOptionsWidgetInstanceEntry;
+ e1->createProc = &classKviUserListGridOptionsWidget_createInstanceProc;
+ e1->pWidget = 0;
+ e1->szClassName = g_szClassName_KviUserListGridOptionsWidget;
+ e1->iIcon = KVI_OPTIONS_WIDGET_ICON_KviUserListGridOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviUserListGridOptionsWidget
+ e1->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviUserListGridOptionsWidget;
+ #else
+ e1->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviUserListGridOptionsWidget
+ e1->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviUserListGridOptionsWidget;
+ e1->szKeywords = __tr2qs_ctx_no_xgettext(e1->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviUserListGridOptionsWidget
+ e1->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviUserListGridOptionsWidget;
+ #else
+ e1->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviUserListGridOptionsWidget
+ e1->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviUserListGridOptionsWidget;
+ #else
+ e1->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviUserListGridOptionsWidget
+ e1->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviUserListGridOptionsWidget;
+ #else
+ e1->bIsNotContained = false;
+ #endif
+ e1->szNameNoLocale = g_szName_KviUserListGridOptionsWidget;
+ e1->szName = __tr2qs_ctx_no_xgettext(g_szName_KviUserListGridOptionsWidget,"options");
+ e0->pChildList->append(e1);
+ e1->pChildList = 0;
+
+ e1 = new KviOptionsWidgetInstanceEntry;
+ e1->createProc = &classKviUserListFeaturesOptionsWidget_createInstanceProc;
+ e1->pWidget = 0;
+ e1->szClassName = g_szClassName_KviUserListFeaturesOptionsWidget;
+ e1->iIcon = KVI_OPTIONS_WIDGET_ICON_KviUserListFeaturesOptionsWidget;
+ #ifdef KVI_OPTIONS_WIDGET_PRIORITY_KviUserListFeaturesOptionsWidget
+ e1->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_KviUserListFeaturesOptionsWidget;
+ #else
+ e1->iPriority = 0;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_KviUserListFeaturesOptionsWidget
+ e1->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_KviUserListFeaturesOptionsWidget;
+ e1->szKeywords = __tr2qs_ctx_no_xgettext(e1->szKeywordsNoLocale,"options");;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_GROUP_KviUserListFeaturesOptionsWidget
+ e1->szGroup = KVI_OPTIONS_WIDGET_GROUP_KviUserListFeaturesOptionsWidget;
+ #else
+ e1->szGroup = "general";
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_CONTAINER_KviUserListFeaturesOptionsWidget
+ e1->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_KviUserListFeaturesOptionsWidget;
+ #else
+ e1->bIsContainer = false;
+ #endif
+ #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_KviUserListFeaturesOptionsWidget
+ e1->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_KviUserListFeaturesOptionsWidget;
+ #else
+ e1->bIsNotContained = false;
+ #endif
+ e1->szNameNoLocale = g_szName_KviUserListFeaturesOptionsWidget;
+ e1->szName = __tr2qs_ctx_no_xgettext(g_szName_KviUserListFeaturesOptionsWidget,"options");
+ e0->pChildList->append(e1);
+ e1->pChildList = 0;
+
+}
+
+void KviOptionsInstanceManager::deleteInstanceTree(KviPointerList<KviOptionsWidgetInstanceEntry> * l)
+{
+ if(l)
+ {
+ for(KviOptionsWidgetInstanceEntry * e = l->first();e;e = l->next())
+ {
+ if(e->pWidget)
+ {
+ if(e->pWidget->parent()->inherits("KviOptionsWidgetContainer"))
+ {
+ disconnect(e->pWidget,SIGNAL(destroyed()),this,SLOT(widgetDestroyed()));
+ delete e->pWidget->parent();
+ e->pWidget = 0;
+ } else {
+ debug("Ops...i have deleted the options dialog ?");
+ }
+ } //else debug("Clas %s has no widget",e->szName);
+ if(e->pChildList)deleteInstanceTree(e->pChildList);
+ }
+ delete l;
+ }
+}
+
+
+KviOptionsInstanceManager::~KviOptionsInstanceManager()
+{
+ if(m_pInstanceTree)debug("Ops...KviOptionsInstanceManager::cleanup() not called ?");
+}
+
+void KviOptionsInstanceManager::cleanup(KviModule * m)
+{
+ deleteInstanceTree(m_pInstanceTree);
+ m_pInstanceTree = 0;
+}
+
+void KviOptionsInstanceManager::widgetDestroyed()
+{
+ KviOptionsWidgetInstanceEntry * e = findInstanceEntry(sender(),m_pInstanceTree);
+ if(e)e->pWidget = 0;
+ if(g_iOptionWidgetInstances > 0)g_iOptionWidgetInstances--;
+
+}
+
+KviOptionsWidget * KviOptionsInstanceManager::getInstance(KviOptionsWidgetInstanceEntry * e,QWidget * par)
+{
+ if(!e)return 0;
+ if(!(e->pWidget))
+ {
+ e->pWidget = e->createProc(par);
+ g_iOptionWidgetInstances++;
+ connect(e->pWidget,SIGNAL(destroyed()),this,SLOT(widgetDestroyed()));
+ }
+ if(e->pWidget->parent() != par)
+ {
+ QWidget * oldPar = (QWidget *)e->pWidget->parent();
+ e->pWidget->reparent(par,QPoint(0,0));
+ delete oldPar;
+ }
+ if(e->bIsContainer)
+ {
+ // need to create the container structure!
+ e->pWidget->createTabbedPage();
+ if(e->pChildList)
+ {
+ KviPointerList<KviOptionsWidgetInstanceEntry> tmp;
+ tmp.setAutoDelete(false);
+
+ for(KviOptionsWidgetInstanceEntry * e2 = e->pChildList->first();e2;e2 = e->pChildList->next())
+ {
+ // add only non containers and widgets not explicitly marked as noncontained
+ if((!e2->bIsContainer) && (!e2->bIsNotContained))
+ {
+ KviOptionsWidgetInstanceEntry * ee = tmp.first();
+ int idx = 0;
+ while(ee)
+ {
+ if(ee->iPriority >= e2->iPriority)break;
+ idx++;
+ ee = tmp.next();
+ }
+ tmp.insert(idx,e2);
+ }
+ }
+
+ for(KviOptionsWidgetInstanceEntry * e3 = tmp.last();e3;e3 = tmp.prev())
+ {
+ KviOptionsWidget * ow = getInstance(e3,e->pWidget->tabWidget());
+ e->pWidget->addOptionsWidget(e3->szName,*(g_pIconManager->getSmallIcon(e3->iIcon)),ow);
+ }
+ }
+ }
+ return e->pWidget;
+}
+
+KviOptionsWidgetInstanceEntry * KviOptionsInstanceManager::findInstanceEntry(const QObject * ptr,KviPointerList<KviOptionsWidgetInstanceEntry> * l)
+{
+ if(l)
+ {
+ for(KviOptionsWidgetInstanceEntry * e = l->first();e;e = l->next())
+ {
+ if(ptr == e->pWidget)return e;
+ if(e->pChildList)
+ {
+ KviOptionsWidgetInstanceEntry * e2 = findInstanceEntry(ptr,e->pChildList);
+ if(e2)return e2;
+ }
+ }
+ }
+ return 0;
+}
+
+KviOptionsWidgetInstanceEntry * KviOptionsInstanceManager::findInstanceEntry(const char * clName,KviPointerList<KviOptionsWidgetInstanceEntry> * l)
+{
+ if(l)
+ {
+ for(KviOptionsWidgetInstanceEntry * e = l->first();e;e = l->next())
+ {
+ if(kvi_strEqualCI(e->szClassName,clName))return e;
+ if(e->pChildList)
+ {
+ KviOptionsWidgetInstanceEntry * e2 = findInstanceEntry(clName,e->pChildList);
+ if(e2)return e2;
+ }
+ }
+ }
+ return 0;
+}
+
+KviOptionsWidgetInstanceEntry * KviOptionsInstanceManager::findInstanceEntry(const char * clName)
+{
+ return findInstanceEntry(clName,m_pInstanceTree);
+}
+
+
+#include "m_instances.moc"
+
diff --git a/src/modules/options/instances.h b/src/modules/options/instances.h
new file mode 100644
index 00000000..fc8674cc
--- /dev/null
+++ b/src/modules/options/instances.h
@@ -0,0 +1,83 @@
+
+
+#ifndef __OPTIONS_INSTANCES_H__
+#define __OPTIONS_INSTANCES_H__
+
+//
+// File : instances.h
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+//
+// Instance creation routines for the KVIrc options module
+// DO NOT EDIT THIS FILE!! ALL CHANGES WILL BE LOST!!
+// This file is automatically generated by mkcreateinstanceproc.sh
+// so any change should go in that script
+//
+
+#include "kvi_optionswidget.h"
+#include "kvi_module.h"
+#include "kvi_pointerlist.h"
+#include "kvi_qstring.h"
+
+typedef struct _KviOptionsWidgetInstanceEntry KviOptionsWidgetInstanceEntry;
+
+
+typedef struct _KviOptionsWidgetInstanceEntry
+{
+ KviOptionsWidget * (*createProc)(QWidget *);
+ KviOptionsWidget * pWidget; // singleton
+ int iIcon;
+ QString szName;
+ QString szNameNoLocale;
+ const char * szClassName;
+ int iPriority;
+ QString szKeywords;
+ QString szKeywordsNoLocale;
+ QString szGroup;
+ bool bIsContainer;
+ bool bIsNotContained;
+ KviPointerList<KviOptionsWidgetInstanceEntry> * pChildList;
+ bool bDoInsert; // a helper for KviOptionsDialog::fillListView()
+} KviOptionsWidgetInstanceEntry;
+
+
+class KviOptionsInstanceManager : public QObject
+{
+ Q_OBJECT
+public:
+ KviOptionsInstanceManager();
+ virtual ~KviOptionsInstanceManager();
+protected:
+ KviPointerList<KviOptionsWidgetInstanceEntry> * m_pInstanceTree;
+public:
+ KviPointerList<KviOptionsWidgetInstanceEntry> * instanceEntryTree(){ return m_pInstanceTree; };
+ KviOptionsWidget * getInstance(KviOptionsWidgetInstanceEntry * e,QWidget * par);
+ KviOptionsWidgetInstanceEntry * findInstanceEntry(const char * clName);
+ void cleanup(KviModule * m);
+protected:
+ KviOptionsWidgetInstanceEntry * findInstanceEntry(const char * clName,KviPointerList<KviOptionsWidgetInstanceEntry> * l);
+ KviOptionsWidgetInstanceEntry * findInstanceEntry(const QObject * ptr,KviPointerList<KviOptionsWidgetInstanceEntry> * l);
+ void deleteInstanceTree(KviPointerList<KviOptionsWidgetInstanceEntry> * l);
+protected slots:
+ void widgetDestroyed();
+};
+
+#endif //__OPTIONS_INSTANCES_H__
+
diff --git a/src/modules/options/libkvioptions.cpp b/src/modules/options/libkvioptions.cpp
new file mode 100644
index 00000000..175b61ff
--- /dev/null
+++ b/src/modules/options/libkvioptions.cpp
@@ -0,0 +1,324 @@
+//============================================================================================
+//
+// File : libkvioptions.cpp
+// Creation date : Fri Aug 18 2000 15:04:09 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//============================================================================================
+
+#include "kvi_module.h"
+#include "kvi_options.h"
+#include "kvi_app.h"
+#include "kvi_frame.h"
+#include "kvi_window.h"
+#include "kvi_locale.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_out.h"
+#include "kvi_splash.h"
+
+#include "container.h"
+#include "instances.h"
+
+#include "dialog.h"
+
+#include <qsplitter.h>
+#include "kvi_pointerhashtable.h"
+
+
+KviPointerHashTable<QString,KviOptionsDialog> * g_pOptionsDialogDict = 0;
+
+KviOptionsInstanceManager * g_pOptionsInstanceManager = 0;
+
+extern int g_iOptionWidgetInstances;
+
+/*
+ @doc: options.save
+ @type:
+ command
+ @title:
+ options.save
+ @short:
+ Saves the options to disk
+ @syntax:
+ options.save
+ @description:
+ Saves the options to disk; this includes aliases , popups ,
+ events and user preferences.
+*/
+
+static bool options_kvs_cmd_save(KviKvsModuleCommandCall * c)
+{
+ g_pApp->saveOptions();
+ return true;
+}
+
+
+/*
+ @doc: options.dialog
+ @type:
+ command
+ @title:
+ options.dialog
+ @short:
+ Shows the "options dialog"
+ @syntax:
+ options.dialog [-t] [options_group]
+ @description:
+ Shows the KVIrc options dialog for the specified options group.
+ If the [-t] switch is used , the dialog is opened as toplevel window,
+ otherwise it is opened as part of the current frame window.[br]
+ Valid values for [options_group] are "general" and "theme".
+ If [options_group] is omitted, the option group "general" is assumed.
+ This command is exported by the "options" module.
+ @seealso:
+ [fnc]$options.isDialog[/fnc]
+*/
+
+
+static bool options_kvs_cmd_dialog(KviKvsModuleCommandCall * c)
+{
+ QString szGroup;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("options_group",KVS_PT_STRING,KVS_PF_OPTIONAL,szGroup)
+ KVSM_PARAMETERS_END(c)
+ if(szGroup.isEmpty())szGroup = "general";
+ KviOptionsDialog * d = g_pOptionsDialogDict->find(szGroup);
+ if(d)
+ {
+ if(c->hasSwitch('t',"toplevel"))
+ {
+ if(d->parent())
+ {
+ d->reparent(0,QPoint(0,0),true);
+ }
+ } else {
+ if(d->parent() != c->window()->frame()->splitter())
+ {
+ d->reparent(c->window()->frame()->splitter(),QPoint(0,0),true);
+ }
+ }
+ } else {
+ if(c->hasSwitch('t',"toplevel"))
+ {
+ d = new KviOptionsDialog(0,szGroup);
+ } else {
+ d = new KviOptionsDialog(c->window()->frame()->splitter(),szGroup);
+ }
+ g_pOptionsDialogDict->insert(szGroup,d);
+ }
+ d->raise();
+ d->show();
+ d->setFocus();
+ return true;
+}
+
+/*
+ @doc: options.pages
+ @type:
+ command
+ @title:
+ options.pages
+ @short:
+ Lists the option pages
+ @syntax:
+ options.pages
+ @description:
+ Lists the option pages available for editing by the means of [cmd]options.edit[/cmd].
+ @seealso:
+*/
+
+
+static void options_kvs_module_print_pages(KviKvsModuleCommandCall * c,KviOptionsWidgetInstanceEntry * e,const char * prefix)
+{
+ c->window()->output(KVI_OUT_SYSTEMMESSAGE,"%s%c%s%c (%Q)",prefix,KVI_TEXT_BOLD,e->szClassName,KVI_TEXT_BOLD,&(e->szName));
+ KviStr szPre = prefix;
+ szPre.append(" ");
+ if(e->pChildList)
+ {
+ for(KviOptionsWidgetInstanceEntry * ex = e->pChildList->first();ex;ex = e->pChildList->next())
+ {
+ options_kvs_module_print_pages(c,ex,szPre.ptr());
+ }
+ }
+}
+static bool options_kvs_cmd_pages(KviKvsModuleCommandCall * c)
+{
+ KviPointerList<KviOptionsWidgetInstanceEntry> * l = g_pOptionsInstanceManager->instanceEntryTree();
+
+ for(KviOptionsWidgetInstanceEntry * e = l->first();e;e = l->next())
+ {
+ options_kvs_module_print_pages(c,e,"");
+ }
+
+ return true;
+}
+
+/*
+ @doc: options.edit
+ @type:
+ command
+ @title:
+ options.edit [-m]
+ @short:
+ Shows a single options page
+ @syntax:
+ options.edit <"options page class name">
+ @description:
+ Shows an options page as toplevel dialog.
+ The available option pages can be listed by using [cmd]options.pages[/cmd].
+ If the -m switch is used, the dialog will appear as modal, blocking input
+ to the main frame until it's closed.
+ @seealso:
+*/
+
+static bool options_kvs_cmd_edit(KviKvsModuleCommandCall * c)
+{
+ QString szOption;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("option",KVS_PT_STRING,0,szOption)
+ KVSM_PARAMETERS_END(c)
+ KviOptionsWidgetInstanceEntry * e = g_pOptionsInstanceManager->findInstanceEntry(szOption);
+ if(!e)
+ {
+ c->warning(__tr2qs_ctx("No such options page class name %Q","options"),&szOption);
+ return true;
+ }
+
+ if(e->pWidget)
+ {
+ //c->warning(__tr("The editor page is already open","options"));
+ e->pWidget->raise();
+ e->pWidget->setActiveWindow();
+ e->pWidget->setFocus();
+ return true;
+ }
+
+ QWidget * w;
+
+ if(c->hasSwitch('m',"modal"))
+ {
+ w = g_pApp->activeModalWidget();
+ if(!w)w = g_pFrame;
+ } else {
+ w = g_pFrame;
+ }
+
+ KviOptionsWidgetContainer * wc = new KviOptionsWidgetContainer(w,c->hasSwitch('m',"modal"));
+
+ wc->setup(g_pOptionsInstanceManager->getInstance(e,wc));
+
+ // a trick for the dialog covering the splash screen before the time (this is prolly a WM or Qt bug)
+ if(g_pSplashScreen)
+ {
+ if(g_pSplashScreen->isVisible()) // another bug: this ALWAYS RETURNS TRUE, even if the splash was hidden by a mouse click...
+ {
+ QObject::connect(g_pSplashScreen,SIGNAL(destroyed()),wc,SLOT(show()));
+ return true;
+ }
+ }
+
+ wc->show();
+ wc->raise();
+ return true;
+}
+
+/*
+ @doc: options.isdialog
+ @type:
+ function
+ @title:
+ $options.isdialog
+ @short:
+ Returns the options dialog state
+ @syntax:
+ <boolean> $options.isdialog([options_group:string])
+ @description:
+ Returns '1' if the options dialog for the specified options_group is open, '0' otherwise.[br]
+ If [options_group] is omitted then the group "general" is assumed.
+ At the moment of writing the valid [options_group] values are "general" and "theme".
+ This command is exported by the "options" module.
+ @seealso:
+ [cmd]options.dialog[/cmd]
+*/
+
+static bool options_kvs_fnc_isdialog(KviKvsModuleFunctionCall * c)
+{
+ QString szGroup;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("options_group",KVS_PT_STRING,KVS_PF_OPTIONAL,szGroup)
+ KVSM_PARAMETERS_END(c)
+ if(szGroup.isEmpty())szGroup = "general";
+ c->returnValue()->setBoolean(g_pOptionsDialogDict->find(szGroup));
+ return true;
+}
+
+
+static bool options_module_init(KviModule * m)
+{
+ g_pOptionsInstanceManager = new KviOptionsInstanceManager();
+
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"dialog",options_kvs_cmd_dialog);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"save",options_kvs_cmd_save);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"pages",options_kvs_cmd_pages);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"edit",options_kvs_cmd_edit);
+ KVSM_REGISTER_FUNCTION(m,"isDialog",options_kvs_fnc_isdialog);
+
+ g_pOptionsDialogDict = new KviPointerHashTable<QString,KviOptionsDialog>;
+ g_pOptionsDialogDict->setAutoDelete(false);
+
+ return true;
+}
+
+static bool options_module_cleanup(KviModule *m)
+{
+ KviPointerHashTableIterator<QString,KviOptionsDialog> it(*g_pOptionsDialogDict);
+ KviPointerList<KviOptionsDialog> l;
+ l.setAutoDelete(false);
+ KviOptionsDialog * d;
+ while(d = it.current())
+ {
+ l.append(d);
+ ++it;
+ }
+ for(d = l.first();d;d = l.next())delete d;
+ delete g_pOptionsDialogDict;
+ g_pOptionsDialogDict = 0;
+
+ g_pOptionsInstanceManager->cleanup(m);
+ delete g_pOptionsInstanceManager;
+ g_pOptionsInstanceManager = 0;
+
+ return true;
+}
+
+static bool options_module_can_unload(KviModule *m)
+{
+ return ((g_pOptionsDialogDict->isEmpty()) && (g_iOptionWidgetInstances == 0));
+}
+
+KVIRC_MODULE(
+ "Options", // module name
+ "1.0.0", // module version
+ "Copyright (C) 2000 Szymon Stefanek (pragma at kvirc dot net)", // author & (C)
+ "Options Dialog",
+ options_module_init,
+ options_module_can_unload,
+ 0,
+ options_module_cleanup
+)
diff --git a/src/modules/options/mkcreateinstanceproc.sh b/src/modules/options/mkcreateinstanceproc.sh
new file mode 100755
index 00000000..97be80b5
--- /dev/null
+++ b/src/modules/options/mkcreateinstanceproc.sh
@@ -0,0 +1,441 @@
+#!/bin/sh
+
+#####################################################################################################
+#
+# Generator for instances.h and instances.cpp
+#
+# This file is part of the KVirc irc client distribution
+# Copyright (C) 2001-2006 Szymon Stefanek (pragma at kvirc dot net)
+#
+#####################################################################################################
+
+
+echo "" > instances.h
+
+######################################################################################################
+cat >> instances.h <<EOF
+
+#ifndef __OPTIONS_INSTANCES_H__
+#define __OPTIONS_INSTANCES_H__
+
+//
+// File : instances.h
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+//
+// Instance creation routines for the KVIrc options module
+// DO NOT EDIT THIS FILE!! ALL CHANGES WILL BE LOST!!
+// This file is automatically generated by mkcreateinstanceproc.sh
+// so any change should go in that script
+//
+
+#include "kvi_optionswidget.h"
+#include "kvi_module.h"
+#include "kvi_pointerlist.h"
+#include "kvi_qstring.h"
+
+typedef struct _KviOptionsWidgetInstanceEntry KviOptionsWidgetInstanceEntry;
+
+
+typedef struct _KviOptionsWidgetInstanceEntry
+{
+ KviOptionsWidget * (*createProc)(QWidget *);
+ KviOptionsWidget * pWidget; // singleton
+ int iIcon;
+ QString szName;
+ QString szNameNoLocale;
+ const char * szClassName;
+ int iPriority;
+ QString szKeywords;
+ QString szKeywordsNoLocale;
+ QString szGroup;
+ bool bIsContainer;
+ bool bIsNotContained;
+ KviPointerList<KviOptionsWidgetInstanceEntry> * pChildList;
+ bool bDoInsert; // a helper for KviOptionsDialog::fillListView()
+} KviOptionsWidgetInstanceEntry;
+
+
+class KviOptionsInstanceManager : public QObject
+{
+ Q_OBJECT
+public:
+ KviOptionsInstanceManager();
+ virtual ~KviOptionsInstanceManager();
+protected:
+ KviPointerList<KviOptionsWidgetInstanceEntry> * m_pInstanceTree;
+public:
+ KviPointerList<KviOptionsWidgetInstanceEntry> * instanceEntryTree(){ return m_pInstanceTree; };
+ KviOptionsWidget * getInstance(KviOptionsWidgetInstanceEntry * e,QWidget * par);
+ KviOptionsWidgetInstanceEntry * findInstanceEntry(const char * clName);
+ void cleanup(KviModule * m);
+protected:
+ KviOptionsWidgetInstanceEntry * findInstanceEntry(const char * clName,KviPointerList<KviOptionsWidgetInstanceEntry> * l);
+ KviOptionsWidgetInstanceEntry * findInstanceEntry(const QObject * ptr,KviPointerList<KviOptionsWidgetInstanceEntry> * l);
+ void deleteInstanceTree(KviPointerList<KviOptionsWidgetInstanceEntry> * l);
+protected slots:
+ void widgetDestroyed();
+};
+
+#endif //__OPTIONS_INSTANCES_H__
+
+EOF
+######################################################################################################
+
+CLASS_LIST=`grep -h "[ ]*\:[ ]*public[ ]*KviOptionsWidget" optw_*.h | sed -e 's/[ ]*\:[ ]*public[ ]*KviOptionsWidget'//g | sed -e 's/[ ]*class[ ]*//g'`
+
+
+TARGET="instances.cpp"
+
+echo "" > $TARGET
+
+######################################################################################################
+cat >> instances.cpp <<EOF
+
+//
+// File : instances.cpp
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (stefanek@tin.it)
+//
+// 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 opinion) 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.
+//
+
+//
+// Instance creation routines for the KVIrc options module
+// DO NOT EDIT THIS FILE!! ALL CHANGES WILL BE LOST!!
+// This file is automatically generated by mkcreateinstanceproc.sh
+// so any change should go in that script
+//
+
+EOF
+######################################################################################################
+
+
+for afile in optw_*.h; do
+ echo "#include \"$afile\"" >> $TARGET
+done
+
+######################################################################################################
+cat >> instances.cpp <<EOF
+
+#include "kvi_locale.h"
+#include "kvi_iconmanager.h"
+#include "instances.h"
+
+int g_iOptionWidgetInstances = 0;
+
+EOF
+######################################################################################################
+
+
+for aclass in $CLASS_LIST; do
+ echo -n "KviOptionsWidget * class$aclass" >> $TARGET
+ echo "_createInstanceProc(QWidget * parent)" >> $TARGET
+ echo "{" >> $TARGET
+ echo " return new $aclass(parent);" >> $TARGET
+ echo "}" >> $TARGET
+ echo "" >> $TARGET
+done
+
+######################################################################################################
+cat >> instances.cpp <<EOF
+
+
+EOF
+######################################################################################################
+
+for aclass in $CLASS_LIST; do
+ echo "static const char * g_szName_$aclass = KVI_OPTIONS_WIDGET_NAME_$aclass;" >> $TARGET
+ echo "static const char * g_szClassName_$aclass = \"$aclass\";" >> $TARGET
+done
+
+######################################################################################################
+cat >> instances.cpp <<EOF
+
+KviOptionsInstanceManager::KviOptionsInstanceManager()
+: QObject(0)
+{
+
+ //debug("Instantiating");
+ // Create the global widget dict : case sensitive , do not copy keys
+ m_pInstanceTree = new KviPointerList<KviOptionsWidgetInstanceEntry>;
+ m_pInstanceTree->setAutoDelete(true);
+
+EOF
+######################################################################################################
+
+CLASSDIR=".classtmp"
+
+mkdir -p $CLASSDIR
+
+rm -f $CLASSDIR/*
+
+for aclass in $CLASS_LIST; do
+ PARENT=`grep -h "KVI_OPTIONS_WIDGET_PARENT_$aclass" optw_*.h | sed -e 's/#define//g' | sed -e s/KVI_OPTIONS_WIDGET_PARENT_$aclass//g | sed -e 's/[ ]*//g'`
+ if [ -z "$PARENT" ]; then
+ PARENT="NOPARENT"
+ fi
+ echo $aclass >> $CLASSDIR/$PARENT
+done
+
+SPACES=""
+
+printclass()
+{
+ echo "" >> $TARGET
+ found=
+ for anum in $DECLARED; do
+ if [ "$anum" = "$1" ]; then
+ found="yes"
+ break
+ fi
+ done
+ if [ -z "$found" ]; then
+ echo "$3 KviOptionsWidgetInstanceEntry * e$1;" >> $TARGET
+ DECLARED="$DECLARED $1"
+ fi
+ echo "$3 e$1 = new KviOptionsWidgetInstanceEntry;" >> $TARGET
+ echo -n "$3 e$1->createProc = &class$2" >> $TARGET
+ echo "_createInstanceProc;" >> $TARGET
+ echo "$3 e$1->pWidget = 0;" >> $TARGET
+ echo "$3 e$1->szClassName = g_szClassName_$2;" >> $TARGET
+ echo "$3 e$1->iIcon = KVI_OPTIONS_WIDGET_ICON_$2;" >> $TARGET
+
+ echo "$3 #ifdef KVI_OPTIONS_WIDGET_PRIORITY_$2" >> $TARGET
+ echo "$3 e$1->iPriority = KVI_OPTIONS_WIDGET_PRIORITY_$2;" >> $TARGET
+ echo "$3 #else" >> $TARGET
+ echo "$3 e$1->iPriority = 0;" >> $TARGET
+ echo "$3 #endif" >> $TARGET
+
+ echo "$3 #ifdef KVI_OPTIONS_WIDGET_KEYWORDS_$2" >> $TARGET
+ echo "$3 e$1->szKeywordsNoLocale = KVI_OPTIONS_WIDGET_KEYWORDS_$2;" >> $TARGET
+ echo "$3 e$1->szKeywords = __tr2qs_ctx_no_xgettext(e$1->szKeywordsNoLocale,\"options\");;" >> $TARGET
+ echo "$3 #endif" >> $TARGET
+
+ echo "$3 #ifdef KVI_OPTIONS_WIDGET_GROUP_$2" >> $TARGET
+ echo "$3 e$1->szGroup = KVI_OPTIONS_WIDGET_GROUP_$2;" >> $TARGET
+ echo "$3 #else" >> $TARGET
+ echo "$3 e$1->szGroup = \"general\";" >> $TARGET
+ echo "$3 #endif" >> $TARGET
+
+ echo "$3 #ifdef KVI_OPTIONS_WIDGET_CONTAINER_$2" >> $TARGET
+ echo "$3 e$1->bIsContainer = KVI_OPTIONS_WIDGET_CONTAINER_$2;" >> $TARGET
+ echo "$3 #else" >> $TARGET
+ echo "$3 e$1->bIsContainer = false;" >> $TARGET
+ echo "$3 #endif" >> $TARGET
+
+ echo "$3 #ifdef KVI_OPTIONS_WIDGET_NOTCONTAINED_$2" >> $TARGET
+ echo "$3 e$1->bIsNotContained = KVI_OPTIONS_WIDGET_NOTCONTAINED_$2;" >> $TARGET
+ echo "$3 #else" >> $TARGET
+ echo "$3 e$1->bIsNotContained = false;" >> $TARGET
+ echo "$3 #endif" >> $TARGET
+
+ echo "$3 e$1->szNameNoLocale = g_szName_$2;" >> $TARGET
+ echo "$3 e$1->szName = __tr2qs_ctx_no_xgettext(g_szName_$2,\"options\");" >> $TARGET
+
+ if [ "$1" = "0" ]; then
+ echo "$3 m_pInstanceTree->append(e$1);" >> $TARGET
+ else
+ VAL=`expr $1 - 1`
+ echo "$3 e$VAL->pChildList->append(e$1);" >> $TARGET
+ fi
+}
+
+addchildren()
+{
+ if [ -f "$CLASSDIR/$2" ]; then
+ LEVEL=`cat $CLASSDIR/$2`
+ for achild in $LEVEL; do
+ printclass $1 $achild "$3"
+ if [ -f "$CLASSDIR/$achild" ]; then
+ echo "" >> $TARGET
+ echo "$3 e$1->pChildList = new KviPointerList<KviOptionsWidgetInstanceEntry>;" >> $TARGET
+ echo "$3 e$1->pChildList->setAutoDelete(true);" >> $TARGET
+ NEXTLEVEL=`expr $1 + 1`
+ addchildren $NEXTLEVEL $achild "$3 "
+ else
+ echo "$3 e$1->pChildList = 0;" >> $TARGET
+ fi
+ done
+ fi
+}
+
+addchildren 0 NOPARENT ""
+
+
+rm -fr $CLASSDIR
+
+######################################################################################################
+cat >> $TARGET <<EOF
+
+}
+
+void KviOptionsInstanceManager::deleteInstanceTree(KviPointerList<KviOptionsWidgetInstanceEntry> * l)
+{
+ if(l)
+ {
+ for(KviOptionsWidgetInstanceEntry * e = l->first();e;e = l->next())
+ {
+ if(e->pWidget)
+ {
+ if(e->pWidget->parent()->inherits("KviOptionsWidgetContainer"))
+ {
+ disconnect(e->pWidget,SIGNAL(destroyed()),this,SLOT(widgetDestroyed()));
+ delete e->pWidget->parent();
+ e->pWidget = 0;
+ } else {
+ debug("Ops...i have deleted the options dialog ?");
+ }
+ } //else debug("Clas %s has no widget",e->szName);
+ if(e->pChildList)deleteInstanceTree(e->pChildList);
+ }
+ delete l;
+ }
+}
+
+
+KviOptionsInstanceManager::~KviOptionsInstanceManager()
+{
+ if(m_pInstanceTree)debug("Ops...KviOptionsInstanceManager::cleanup() not called ?");
+}
+
+void KviOptionsInstanceManager::cleanup(KviModule * m)
+{
+ deleteInstanceTree(m_pInstanceTree);
+ m_pInstanceTree = 0;
+}
+
+void KviOptionsInstanceManager::widgetDestroyed()
+{
+ KviOptionsWidgetInstanceEntry * e = findInstanceEntry(sender(),m_pInstanceTree);
+ if(e)e->pWidget = 0;
+ if(g_iOptionWidgetInstances > 0)g_iOptionWidgetInstances--;
+
+}
+
+KviOptionsWidget * KviOptionsInstanceManager::getInstance(KviOptionsWidgetInstanceEntry * e,QWidget * par)
+{
+ if(!e)return 0;
+ if(!(e->pWidget))
+ {
+ e->pWidget = e->createProc(par);
+ g_iOptionWidgetInstances++;
+ connect(e->pWidget,SIGNAL(destroyed()),this,SLOT(widgetDestroyed()));
+ }
+ if(e->pWidget->parent() != par)
+ {
+ QWidget * oldPar = (QWidget *)e->pWidget->parent();
+ e->pWidget->reparent(par,QPoint(0,0));
+ delete oldPar;
+ }
+ if(e->bIsContainer)
+ {
+ // need to create the container structure!
+ e->pWidget->createTabbedPage();
+ if(e->pChildList)
+ {
+ KviPointerList<KviOptionsWidgetInstanceEntry> tmp;
+ tmp.setAutoDelete(false);
+
+ for(KviOptionsWidgetInstanceEntry * e2 = e->pChildList->first();e2;e2 = e->pChildList->next())
+ {
+ // add only non containers and widgets not explicitly marked as noncontained
+ if((!e2->bIsContainer) && (!e2->bIsNotContained))
+ {
+ KviOptionsWidgetInstanceEntry * ee = tmp.first();
+ int idx = 0;
+ while(ee)
+ {
+ if(ee->iPriority >= e2->iPriority)break;
+ idx++;
+ ee = tmp.next();
+ }
+ tmp.insert(idx,e2);
+ }
+ }
+
+ for(KviOptionsWidgetInstanceEntry * e3 = tmp.last();e3;e3 = tmp.prev())
+ {
+ KviOptionsWidget * ow = getInstance(e3,e->pWidget->tabWidget());
+ e->pWidget->addOptionsWidget(e3->szName,*(g_pIconManager->getSmallIcon(e3->iIcon)),ow);
+ }
+ }
+ }
+ return e->pWidget;
+}
+
+KviOptionsWidgetInstanceEntry * KviOptionsInstanceManager::findInstanceEntry(const QObject * ptr,KviPointerList<KviOptionsWidgetInstanceEntry> * l)
+{
+ if(l)
+ {
+ for(KviOptionsWidgetInstanceEntry * e = l->first();e;e = l->next())
+ {
+ if(ptr == e->pWidget)return e;
+ if(e->pChildList)
+ {
+ KviOptionsWidgetInstanceEntry * e2 = findInstanceEntry(ptr,e->pChildList);
+ if(e2)return e2;
+ }
+ }
+ }
+ return 0;
+}
+
+KviOptionsWidgetInstanceEntry * KviOptionsInstanceManager::findInstanceEntry(const char * clName,KviPointerList<KviOptionsWidgetInstanceEntry> * l)
+{
+ if(l)
+ {
+ for(KviOptionsWidgetInstanceEntry * e = l->first();e;e = l->next())
+ {
+ if(kvi_strEqualCI(e->szClassName,clName))return e;
+ if(e->pChildList)
+ {
+ KviOptionsWidgetInstanceEntry * e2 = findInstanceEntry(clName,e->pChildList);
+ if(e2)return e2;
+ }
+ }
+ }
+ return 0;
+}
+
+KviOptionsWidgetInstanceEntry * KviOptionsInstanceManager::findInstanceEntry(const char * clName)
+{
+ return findInstanceEntry(clName,m_pInstanceTree);
+}
+
+
+#include "m_instances.moc"
+
+EOF
+######################################################################################################
+
diff --git a/src/modules/options/optw_antispam.cpp b/src/modules/options/optw_antispam.cpp
new file mode 100644
index 00000000..ba8180e6
--- /dev/null
+++ b/src/modules/options/optw_antispam.cpp
@@ -0,0 +1,64 @@
+//
+// File : optw_antispam.cpp
+// Creation date : Tue Oct 16 15:47:02 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "optw_antispam.h"
+
+#include <qlayout.h>
+
+#include "kvi_options.h"
+#include "kvi_locale.h"
+
+#include <qlabel.h>
+
+
+
+KviAntispamOptionsWidget::KviAntispamOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"antispam_options_widget")
+{
+ createLayout(3,1);
+
+ KviTalGroupBox *g = addGroupBox(0,0,0,0,1,Qt::Horizontal,__tr2qs_ctx("Enable Anti-spam For","options"));
+ m_b1 = addBoolSelector(g,__tr2qs_ctx("Private messages","options"),KviOption_boolUseAntiSpamOnPrivmsg);
+ connect(m_b1,SIGNAL(toggled(bool)),this,SLOT(reenableStuff(bool)));
+ m_b2 = addBoolSelector(g,__tr2qs_ctx("Private notices","options"),KviOption_boolUseAntiSpamOnNotice);
+ connect(m_b2,SIGNAL(toggled(bool)),this,SLOT(reenableStuff(bool)));
+
+ m_b3 = addBoolSelector(0,1,0,1,__tr2qs_ctx("Silent anti-spam (no warnings)","options"),KviOption_boolSilentAntiSpam);
+ m_sl = addStringListSelector(0,2,0,2,__tr2qs_ctx("Words considered spam:","options"),KviOption_stringlistSpamWords);
+
+ reenableStuff(true);
+
+ layout()->setRowStretch(2,1);
+}
+
+KviAntispamOptionsWidget::~KviAntispamOptionsWidget()
+{
+}
+
+void KviAntispamOptionsWidget::reenableStuff(bool)
+{
+ m_b3->setEnabled(m_b1->isChecked() || m_b2->isChecked());
+ m_sl->setEnabled(m_b1->isChecked() || m_b2->isChecked());
+}
+
+
+#include "m_optw_antispam.moc"
diff --git a/src/modules/options/optw_antispam.h b/src/modules/options/optw_antispam.h
new file mode 100644
index 00000000..28e51b41
--- /dev/null
+++ b/src/modules/options/optw_antispam.h
@@ -0,0 +1,47 @@
+#ifndef _OPTW_ANTISPAM_H_
+#define _OPTW_ANTISPAM_H_
+//
+// File : optw_antispam.h
+// Creation date : Tue Oct 16 15:47:03 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_optionswidget.h"
+
+#define KVI_OPTIONS_WIDGET_ICON_KviAntispamOptionsWidget KVI_SMALLICON_SPAM
+#define KVI_OPTIONS_WIDGET_NAME_KviAntispamOptionsWidget __tr2qs_no_lookup("Anti-spam")
+#define KVI_OPTIONS_WIDGET_PARENT_KviAntispamOptionsWidget KviProtectionOptionsWidget
+
+class KviAntispamOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviAntispamOptionsWidget(QWidget * parent);
+ ~KviAntispamOptionsWidget();
+protected:
+ KviBoolSelector * m_b1;
+ KviBoolSelector * m_b2;
+ KviBoolSelector * m_b3;
+ KviStringListSelector * m_sl;
+protected slots:
+ void reenableStuff(bool);
+};
+
+
+#endif //_OPTW_ANTISPAM_H_
diff --git a/src/modules/options/optw_avatar.cpp b/src/modules/options/optw_avatar.cpp
new file mode 100644
index 00000000..f93631fd
--- /dev/null
+++ b/src/modules/options/optw_avatar.cpp
@@ -0,0 +1,131 @@
+//=============================================================================
+//
+// File : optw_avatar.cpp
+// Creation date : Wed Nov 19 09:25:16 2005 GMT by Grifisx & Noldor
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003-2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "optw_avatar.h"
+
+#include "kvi_locale.h"
+#include "kvi_selectors.h"
+#include "kvi_options.h"
+
+#include "kvi_tal_tooltip.h"
+
+KviAvatarAdvancedOptionsWidget::KviAvatarAdvancedOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"avatar_advanced_options_widget")
+{
+ createLayout(4,1);
+ // AVATAR
+
+ // 1st Box
+ KviTalGroupBox *g = addGroupBox(0,0,0,0,1,Qt::Horizontal,__tr2qs_ctx("Scaling in userlist","options"));
+ KviBoolSelector *b = addBoolSelector(g,__tr2qs_ctx("Scale avatar images in userlist (recommended)","options"),KviOption_boolScaleAvatars);
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(b,__tr2qs_ctx("<center>This option will force KVIrc to scale avatars" \
+ " shown in the userlist.<br>" \
+ "Avatars will be scaled to fit the " \
+ "constraints set below. Better keep this option on. :)</center>","options"));
+#endif
+ addBoolSelector(g,__tr2qs_ctx("Do not scale avatar if it is less than required size","options"),KviOption_boolDoNotStretchAvatars);
+
+ KviUIntSelector *u = addUIntSelector(g,__tr2qs_ctx("Image width:","options"),KviOption_uintAvatarScaleWidth,0,512,80,KVI_OPTION_BOOL(KviOption_boolScaleAvatars));
+ connect(b,SIGNAL(toggled(bool)),u,SLOT(setEnabled(bool)));
+ u = addUIntSelector(g,__tr2qs_ctx("Image height:","options"),KviOption_uintAvatarScaleHeight,0,512,80,KVI_OPTION_BOOL(KviOption_boolScaleAvatars));
+ connect(b,SIGNAL(toggled(bool)),u,SLOT(setEnabled(bool)));
+
+ //2nd
+ g = addGroupBox(0,1,0,1,1,Qt::Horizontal,__tr2qs_ctx("Scaling on load (and in user tooltips)","options"));
+ b = addBoolSelector(g,__tr2qs_ctx("Scale avatar images on image load","options"),KviOption_boolScaleAvatarsOnLoad);
+
+ u = addUIntSelector(g,__tr2qs_ctx("Image width:","options"),KviOption_uintScaleAvatarsOnLoadWidth,0,1280,80,KVI_OPTION_BOOL(KviOption_boolScaleAvatarsOnLoad));
+ connect(b,SIGNAL(toggled(bool)),u,SLOT(setEnabled(bool)));
+ u = addUIntSelector(g,__tr2qs_ctx("Image height:","options"),KviOption_uintScaleAvatarsOnLoadHeight,0,1280,80,KVI_OPTION_BOOL(KviOption_boolScaleAvatarsOnLoad));
+ connect(b,SIGNAL(toggled(bool)),u,SLOT(setEnabled(bool)));
+
+ // 2st Box
+ KviTalGroupBox *gs = addGroupBox(0,2,0,2,1,Qt::Horizontal,__tr2qs_ctx("Request CTCP","options"));
+ KviBoolSelector * bs = addBoolSelector(g,__tr2qs_ctx("Request missing avatars","options"),KviOption_boolRequestMissingAvatars);
+ KviUIntSelector * us = addUIntSelector(g,__tr2qs_ctx("Maximum requested file size:","options"),KviOption_uintMaximumRequestedAvatarSize,0,1048576,102400,KVI_OPTION_BOOL(KviOption_boolRequestMissingAvatars));
+
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(bs,
+ __tr2qs_ctx("<center>This option will cause KVIrc to send a DCC GET request " \
+ "when someone sets an avatar and there is no cached copy available.</center>","options"));
+#endif
+ us->setSuffix(__tr2qs_ctx(" bytes","options"));
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(us,
+ __tr2qs_ctx("<center>This is the maximum size for avatar images that " \
+ "will be automatically requested.<br>" \
+ "A reasonable value might be 102400 bytes (100 K).</center>","options"));
+#endif
+ connect(bs,SIGNAL(toggled(bool)),us,SLOT(setEnabled(bool)));
+
+ bs = addBoolSelector(gs,__tr2qs_ctx("Automatically accept incoming avatars","options"),KviOption_boolAutoAcceptIncomingAvatars);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(
+ bs,
+ __tr2qs_ctx("<center>This option will cause KVIrc to auto-accept " \
+ "DCC SEND requests for incoming avatars.<br>" \
+ "If you're using the \"Request missing avatars\" option " \
+ "above, enabling this may by useful.<br>" \
+ "Avatars will be saved in the local KVIrc directory.</center>","options"));
+#endif
+
+ bs = addBoolSelector(gs,__tr2qs_ctx("Remember avatars for registered users","options"),KviOption_boolSetLastAvatarAsDefaultForRegisteredUsers);
+
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(
+ bs,
+ __tr2qs_ctx("<center>Use a user's last known avatar by default " \
+ "(only for users that are registered).</center>","options"));
+#endif
+
+ us = addUIntSelector(gs,__tr2qs_ctx("Avatar offer timeout:","options"),KviOption_uintAvatarOfferTimeoutInSecs,1,99999,60);
+ us->setSuffix(__tr2qs_ctx(" sec","options"));
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(us,
+ __tr2qs_ctx("<center>This is the amount of time to make an avatar available for transfer when requested.<br>" \
+ "When someone sends a CTCP AVATAR request, " \
+ "KVIrc will reply with a CTCP AVATAR message containing the name and size " \
+ "of your avatar image.<br>" \
+ "A time-limited file offer is added for the image file " \
+ "to the requesting user.</center>","options"));
+#endif
+
+ bs = addBoolSelector(gs,__tr2qs_ctx("Ignore requests if no avatar is set","options"),KviOption_boolIgnoreChannelAvatarRequestsWhenNoAvatarSet);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(bs,
+ __tr2qs_ctx("This option will cause KVIrc to ignore channel CTCP AVATAR requests " \
+ "when you have no avatar set. This is usually a good practice since " \
+ "it helps in reducing traffic by not sending a reply that would be empty.","options"));
+#endif
+
+ addRowSpacer(0,3,0,3);
+}
+
+KviAvatarAdvancedOptionsWidget::~KviAvatarAdvancedOptionsWidget()
+{
+}
+
+
+#include "m_optw_avatar.moc"
diff --git a/src/modules/options/optw_avatar.h b/src/modules/options/optw_avatar.h
new file mode 100644
index 00000000..2235a659
--- /dev/null
+++ b/src/modules/options/optw_avatar.h
@@ -0,0 +1,45 @@
+#ifndef _OPTW_AVATAR_H_
+#define _OPTW_AVATAR_H_
+
+//=============================================================================
+//
+// File : optw_avatar.cpp
+// Creation date : Wed Nov 19 09:25:16 2005 GMT by Grifisx & Noldor
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_optionswidget.h"
+
+
+#define KVI_OPTIONS_WIDGET_ICON_KviAvatarAdvancedOptionsWidget KVI_SMALLICON_AVATAR
+#define KVI_OPTIONS_WIDGET_NAME_KviAvatarAdvancedOptionsWidget __tr2qs_no_lookup("Avatars")
+#define KVI_OPTIONS_WIDGET_PARENT_KviAvatarAdvancedOptionsWidget KviToolsOptionsWidget
+#define KVI_OPTIONS_WIDGET_PRIORITY_KviAvatarAdvancedOptionsWidget 9
+#define KVI_OPTIONS_WIDGET_MINIMAL_USER_EXPERIENCE_LEVEL_KviAvatarAdvancedOptionsWidget 2
+
+class KviAvatarAdvancedOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviAvatarAdvancedOptionsWidget(QWidget * parent);
+ ~KviAvatarAdvancedOptionsWidget();
+};
+
+#endif //!_OPTW_AVATAR_H_
diff --git a/src/modules/options/optw_away.cpp b/src/modules/options/optw_away.cpp
new file mode 100644
index 00000000..151b8446
--- /dev/null
+++ b/src/modules/options/optw_away.cpp
@@ -0,0 +1,71 @@
+//
+// File : optw_away.cpp
+// Creation date : Mon Oct 29 15:37:16 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+#include "optw_away.h"
+
+#include <qlayout.h>
+
+#include "kvi_options.h"
+#include "kvi_locale.h"
+
+//#warning "Info tips"
+
+
+KviAwayOptionsWidget::KviAwayOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"away_options_widget")
+{
+ createLayout(4,1);
+
+ addStringSelector(0,0,0,0, __tr2qs_ctx("Default away message:","options"), KviOption_stringAwayMessage);
+
+ addBoolSelector(0,1,0,1, __tr2qs_ctx("User input exits away mode","options"), KviOption_boolExitAwayOnInput);
+
+ KviTalGroupBox *g = addGroupBox(0,2,0,2,1,Qt::Horizontal,__tr2qs_ctx("Away Nickname","options"));
+ m_pEnableAwayNick = addBoolSelector(g,__tr2qs_ctx("Change nickname on away","options"),KviOption_boolChangeNickAway);
+ connect(m_pEnableAwayNick,SIGNAL(toggled(bool)),this,SLOT(enableCustomAwayText(bool)));
+
+ m_pEnableCustomAwayNick = addBoolSelector(g,__tr2qs_ctx("Use automatic nickname ([5 letters]AWAY)","options"),KviOption_boolAutoGeneratedAwayNick,KVI_OPTION_BOOL(KviOption_boolChangeNickAway));
+ connect(m_pEnableAwayNick,SIGNAL(toggled(bool)),m_pEnableCustomAwayNick,SLOT(setEnabled(bool)));
+ connect(m_pEnableCustomAwayNick,SIGNAL(toggled(bool)),this,SLOT(enableCustomAwayText(bool)));
+
+ // m_p <-- stands for pointer
+ // m_sz <-- stands for a string :)
+// m_szCustomAwayNick = addStringSelector(0,4,0,4,__tr2qs_ctx("Custom away nick","options"),KviOption_stringCustomAwayNick,KVI_OPTION_BOOL(KviOption_boolChangeNickAway) && !(KVI_OPTION_BOOL(KviOption_boolAutoGeneratedAwayNick)));
+
+ m_pCustomAwayNick = addStringSelector(g,__tr2qs_ctx("Custom nickname (%%nick%% means a current nick):","options"),KviOption_stringCustomAwayNick,KVI_OPTION_BOOL(KviOption_boolChangeNickAway) && !(KVI_OPTION_BOOL(KviOption_boolAutoGeneratedAwayNick)));
+
+ addRowSpacer(0,3,0,3);
+}
+
+KviAwayOptionsWidget::~KviAwayOptionsWidget()
+{
+}
+
+void KviAwayOptionsWidget::enableCustomAwayText(bool)
+{
+ m_pCustomAwayNick->setEnabled(m_pEnableAwayNick->isChecked() && !(m_pEnableCustomAwayNick->isChecked()));
+
+}
+
+
+#include "m_optw_away.moc"
diff --git a/src/modules/options/optw_away.h b/src/modules/options/optw_away.h
new file mode 100644
index 00000000..e8892faa
--- /dev/null
+++ b/src/modules/options/optw_away.h
@@ -0,0 +1,46 @@
+#ifndef _OPTW_AWAY_H_
+#define _OPTW_AWAY_H_
+//
+// File : optw_away.h
+// Creation date : Mon Oct 29 15:37:18 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_optionswidget.h"
+
+#define KVI_OPTIONS_WIDGET_ICON_KviAwayOptionsWidget KVI_SMALLICON_AWAY
+#define KVI_OPTIONS_WIDGET_NAME_KviAwayOptionsWidget __tr2qs_no_lookup("Away")
+#define KVI_OPTIONS_WIDGET_PARENT_KviAwayOptionsWidget KviToolsOptionsWidget
+
+class KviAwayOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviAwayOptionsWidget(QWidget * parent);
+ ~KviAwayOptionsWidget();
+protected:
+ KviBoolSelector * m_pEnableAwayNick;
+ KviBoolSelector * m_pEnableCustomAwayNick;
+ KviStringSelector * m_pCustomAwayNick;
+public slots:
+ void enableCustomAwayText(bool);
+
+};
+
+#endif //_OPTW_AWAY_H_
diff --git a/src/modules/options/optw_connection.cpp b/src/modules/options/optw_connection.cpp
new file mode 100644
index 00000000..608b47bd
--- /dev/null
+++ b/src/modules/options/optw_connection.cpp
@@ -0,0 +1,321 @@
+//=============================================================================
+//
+// File : optw_connection.cpp
+// Creation date : Sat Nov 24 04:25:16 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "optw_connection.h"
+
+#include "kvi_settings.h"
+#include "kvi_locale.h"
+#include "kvi_options.h"
+#include "kvi_iconmanager.h"
+#include <qradiobutton.h>
+
+
+KviConnectionOptionsWidget::KviConnectionOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"connection_options_widget")
+{
+
+ createLayout(2,1);
+ KviTalGroupBox *gbox = addGroupBox(0,0,0,0,1,Qt::Horizontal,__tr2qs_ctx("On Disconnect","options"));
+
+
+ KviBoolSelector *b1 = addBoolSelector(gbox,__tr2qs_ctx("Keep channels open","options"),KviOption_boolKeepChannelsOpenOnDisconnect,true);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b1,__tr2qs_ctx("<center>This option will cause KVIrc to keep channels open after disconnect.</center>","options"));
+#endif
+
+ b1 = addBoolSelector(gbox,__tr2qs_ctx("Keep queries open","options"),KviOption_boolKeepQueriesOpenOnDisconnect,true);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b1,__tr2qs_ctx("<center>This option will cause KVIrc to keep queries open after disconnect.</center>","options"));
+#endif
+
+ gbox = addGroupBox(0,1,0,1,1,Qt::Horizontal,__tr2qs_ctx("On Unexpected Disconnect","options"));
+
+
+ b1 = addBoolSelector(gbox,__tr2qs_ctx("Keep channels open","options"),KviOption_boolKeepChannelsOpenOnUnexpectedDisconnect,true);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b1,__tr2qs_ctx("<center>This option will cause KVIrc to keep channels open after an unexpected disconnect.</center>","options"));
+#endif
+
+ b1 = addBoolSelector(gbox,__tr2qs_ctx("Keep queries open","options"),KviOption_boolKeepQueriesOpenOnUnexpectedDisconnect,true);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b1,__tr2qs_ctx("<center>This option will cause KVIrc to keep queries open after an unexpected disconnect.</center>","options"));
+#endif
+
+ b1 = addBoolSelector(gbox,__tr2qs_ctx("Rejoin channels after reconnect","options"),KviOption_boolRejoinChannelsAfterReconnect,KVI_OPTION_BOOL(KviOption_boolAutoReconnectOnUnexpectedDisconnect));
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b1,__tr2qs_ctx("<center>This option will cause KVIrc to rejoin channels after a successful reconnect attempt.</center>","options"));
+#endif
+ b1 = addBoolSelector(gbox,__tr2qs_ctx("Reopen queries after reconnect","options"),KviOption_boolReopenQueriesAfterReconnect,KVI_OPTION_BOOL(KviOption_boolAutoReconnectOnUnexpectedDisconnect));
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b1,__tr2qs_ctx("<center>This option will cause KVIrc to reopen query windows after a successful reconnect attempt.</center>","options"));
+#endif
+
+// gbox = addGroupBox(0,1,0,1,1,Qt::Horizontal,__tr2qs_ctx("On Unexpected Disconnect","options"));
+ KviBoolSelector * b = addBoolSelector(gbox,__tr2qs_ctx("Automatically reconnect","options"),KviOption_boolAutoReconnectOnUnexpectedDisconnect);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b,__tr2qs_ctx("<center>This option will enable auto-reconnecting after an unexpected disconnect. " \
+ "An unexpected disconnect is the <b>termination</b> of a <b>fully connected IRC session</b> " \
+ "that was <b>not requested by the user</b> by the means of the QUIT message." \
+ "<p><b>Warning:</b> If you use /RAW to send a QUIT message to the server, " \
+ "this option will not behave correctly, since does not detect the outgoing " \
+ "QUIT message and will attempt to reconnect after the server has closed the connection. " \
+ "For this reason, always use the /QUIT command to close your connections. " \
+ "This option may also behave incorrectly with bouncers that support " \
+ "detaching, in this case a solution could be to prepare an alias that sends the " \
+ "bouncer \"detach\" command immediately before the \"quit\" command.<br>" \
+ "<tt>alias(bncdetach){ raw bouncer detach; quit; }</tt></p></center>","options"));
+#endif
+ KviUIntSelector * u = addUIntSelector(gbox,__tr2qs_ctx("Maximum attempts (0: unlimited):","options"),
+ KviOption_uintMaxAutoReconnectAttempts,0,100,5,
+ KVI_OPTION_BOOL(KviOption_boolAutoReconnectOnUnexpectedDisconnect));
+ connect(b,SIGNAL(toggled(bool)),u,SLOT(setEnabled(bool)));
+
+ u = addUIntSelector(gbox,__tr2qs_ctx("Delay between attempts:","options"),
+ KviOption_uintAutoReconnectDelay,0,86400,5,
+ KVI_OPTION_BOOL(KviOption_boolAutoReconnectOnUnexpectedDisconnect));
+ u->setSuffix(__tr2qs_ctx(" sec","options"));
+ connect(b,SIGNAL(toggled(bool)),u,SLOT(setEnabled(bool)));
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(u,__tr2qs_ctx("<center>Minimum value: <b>0 sec</b><br>Maximum value: <b>86400 sec</b></center>","options"));
+#endif
+
+
+
+
+ addRowSpacer(0,2,4,2);
+}
+
+
+KviConnectionOptionsWidget::~KviConnectionOptionsWidget()
+{
+}
+
+
+
+
+KviSSLOptionsWidget::KviSSLOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"ssl_options_widget")
+{
+#ifdef COMPILE_SSL_SUPPORT
+ createLayout(3,1);
+
+ KviTalGroupBox * gbox = addGroupBox(0,0,0,0,1,Qt::Horizontal,__tr2qs_ctx("Certificate","options"));
+
+ KviBoolSelector * b = addBoolSelector(gbox,__tr2qs_ctx("Use SSL certificate (PEM format only)","options"),
+ &(KVI_OPTION_BOOL(KviOption_boolUseSSLCertificate)),true);
+ KviFileSelector * f = addFileSelector(gbox,__tr2qs_ctx("Certificate location:","options"),
+ &(KVI_OPTION_STRING(KviOption_stringSSLCertificatePath)),KVI_OPTION_BOOL(KviOption_boolUseSSLCertificate));
+ connect(b,SIGNAL(toggled(bool)),f,SLOT(setEnabled(bool)));
+ KviPasswordSelector * p = new KviPasswordSelector(gbox,__tr2qs_ctx("Certificate password:","options"),
+ &(KVI_OPTION_STRING(KviOption_stringSSLCertificatePass)),KVI_OPTION_BOOL(KviOption_boolUseSSLCertificate));
+ connect(b,SIGNAL(toggled(bool)),p,SLOT(setEnabled(bool)));
+
+ gbox = addGroupBox(0,1,0,1,1,Qt::Horizontal,__tr2qs_ctx("Private Key","options"));
+ b = addBoolSelector(gbox,__tr2qs_ctx("Use SSL private key","options"),
+ &(KVI_OPTION_BOOL(KviOption_boolUseSSLPrivateKey)),true);
+ f = addFileSelector(gbox,__tr2qs_ctx("Private key location:","options"),
+ &(KVI_OPTION_STRING(KviOption_stringSSLPrivateKeyPath)),KVI_OPTION_BOOL(KviOption_boolUseSSLPrivateKey));
+ connect(b,SIGNAL(toggled(bool)),f,SLOT(setEnabled(bool)));
+ p = addPasswordSelector(gbox,__tr2qs_ctx("Private key password:","options"),
+ &(KVI_OPTION_STRING(KviOption_stringSSLPrivateKeyPass)),KVI_OPTION_BOOL(KviOption_boolUseSSLPrivateKey));
+ connect(b,SIGNAL(toggled(bool)),p,SLOT(setEnabled(bool)));
+ addRowSpacer(0,2,0,2);
+#else
+ createLayout(1,1);
+ addLabel(0,0,0,0,__tr2qs_ctx("This executable has no SSL support.","options"));
+#endif
+}
+
+KviSSLOptionsWidget::~KviSSLOptionsWidget()
+{
+}
+
+
+
+
+
+
+KviTransportOptionsWidget::KviTransportOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"transport_options_widget")
+{
+ createLayout(5,1);
+ KviUIntSelector * u;
+
+ KviTalGroupBox * g = addGroupBox(0,0,0,0,1,Qt::Horizontal,__tr2qs_ctx("Timeout Values","options"),this);
+ u = addUIntSelector(g,__tr2qs_ctx("Connect timeout:","options"),KviOption_uintIrcSocketTimeout,5,6000,60);
+ u->setSuffix(__tr2qs_ctx(" sec","options"));
+ u = addUIntSelector(g,__tr2qs_ctx("Outgoing data queue flush timeout:","options"),KviOption_uintSocketQueueFlushTimeout,100,2000,500);
+ u->setSuffix(__tr2qs_ctx(" msec","options"));
+ KviBoolSelector * b = addBoolSelector(0,1,0,1,__tr2qs_ctx("Limit outgoing traffic","options"),KviOption_boolLimitOutgoingTraffic);
+ u = addUIntSelector(0,2,0,2,__tr2qs_ctx("Limit to 1 message every:","options"),
+ KviOption_uintOutgoingTrafficLimitUSeconds,10000,2000000,10000000,KVI_OPTION_BOOL(KviOption_boolLimitOutgoingTraffic));
+ u->setSuffix(__tr2qs_ctx(" usec","options"));
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(u,__tr2qs_ctx("<center>Minimum value: <b>10000 usec</b><br>Maximum value: <b>10000000 usec</b></center>","options"));
+#endif
+ connect(b,SIGNAL(toggled(bool)),u,SLOT(setEnabled(bool)));
+
+ g = addGroupBox(0,3,0,3,2,Qt::Horizontal,__tr2qs_ctx("Network Interfaces","options"));
+
+ b = addBoolSelector(g,__tr2qs_ctx("Bind IPv4 connections to:","options"),KviOption_boolBindIrcIpV4ConnectionsToSpecifiedAddress);
+ KviStringSelector * s = addStringSelector(g,"",KviOption_stringIpV4ConnectionBindAddress,KVI_OPTION_BOOL(KviOption_boolBindIrcIpV4ConnectionsToSpecifiedAddress));
+ connect(b,SIGNAL(toggled(bool)),s,SLOT(setEnabled(bool)));
+#ifdef COMPILE_IPV6_SUPPORT
+ b = addBoolSelector(g,__tr2qs_ctx("Bind IPv6 connections to:","options"),KviOption_boolBindIrcIpV6ConnectionsToSpecifiedAddress);
+ s = addStringSelector(g,"",KviOption_stringIpV6ConnectionBindAddress,KVI_OPTION_BOOL(KviOption_boolBindIrcIpV6ConnectionsToSpecifiedAddress));
+ connect(b,SIGNAL(toggled(bool)),s,SLOT(setEnabled(bool)));
+#endif //!COMPILE_IPV6_SUPPORT
+
+ addRowSpacer(0,4,0,4);
+}
+
+KviTransportOptionsWidget::~KviTransportOptionsWidget()
+{
+}
+
+
+
+
+
+
+
+
+
+KviIdentOptionsWidget::KviIdentOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"ident_options_widget")
+{
+ createLayout(6,1);
+
+ m_pEnableIdent = addBoolSelector(0,0,0,0,__tr2qs_ctx("Enable ident service (bad practice on UNIX!)","options"),KviOption_boolUseIdentService);
+ connect(m_pEnableIdent,SIGNAL(toggled(bool)),this,SLOT(enableIpv4InIpv6(bool)));
+
+ KviTalGroupBox * gbox = addGroupBox(0,1,0,1,1,Qt::Horizontal,__tr2qs_ctx("Output verbosity","options"),KVI_OPTION_BOOL(KviOption_boolUseIdentService));
+ connect(m_pEnableIdent,SIGNAL(toggled(bool)),gbox,SLOT(setEnabled(bool)));
+
+ addLabel(gbox,__tr2qs_ctx("Output identd messages to:","options"));
+
+ m_pActiveRadio = new QRadioButton(__tr2qs_ctx("Active window","options"),gbox);
+ m_pConsoleRadio = new QRadioButton(__tr2qs_ctx("Console","options"),gbox);
+ m_pQuietRadio = new QRadioButton(__tr2qs_ctx("Do not show any identd messages","options"),gbox);
+
+ switch(KVI_OPTION_UINT(KviOption_uintIdentdOutputMode))
+ {
+ case KviIdentdOutputMode::Quiet :
+ m_pQuietRadio->setChecked(true);
+ break;
+ case KviIdentdOutputMode::ToConsole :
+ m_pConsoleRadio->setChecked(true);
+ break;
+ case KviIdentdOutputMode::ToActiveWindow :
+ m_pActiveRadio->setChecked(true);
+ break;
+ }
+
+ gbox = addGroupBox(0,2,0,2,1,Qt::Horizontal,__tr2qs_ctx("Configuration","options"),KVI_OPTION_BOOL(KviOption_boolUseIdentService));
+
+ KviBoolSelector *b = addBoolSelector(gbox,__tr2qs_ctx("Enable ident service only while connecting to server","options"),KviOption_boolUseIdentServiceOnlyOnConnect);
+ connect(m_pEnableIdent,SIGNAL(toggled(bool)),b,SLOT(setEnabled(bool)));
+
+ KviStringSelector * s = addStringSelector(gbox,__tr2qs_ctx("Ident username:","options"),
+ KviOption_stringIdentdUser,KVI_OPTION_BOOL(KviOption_boolUseIdentService));
+
+ KviUIntSelector * u = addUIntSelector(gbox,__tr2qs_ctx("Service port:","options"),
+ KviOption_uintIdentdPort,0,65535,113,KVI_OPTION_BOOL(KviOption_boolUseIdentService));
+ connect(m_pEnableIdent,SIGNAL(toggled(bool)),u,SLOT(setEnabled(bool)));
+ connect(m_pEnableIdent,SIGNAL(toggled(bool)),gbox,SLOT(setEnabled(bool)));
+
+ gbox = addGroupBox(0,3,0,3,1,Qt::Horizontal,__tr2qs_ctx("IPv6 Settings","options"),KVI_OPTION_BOOL(KviOption_boolUseIdentService));
+ m_pEnableIpv6 = addBoolSelector(gbox,__tr2qs_ctx("Enable service for IPv6","options"),
+ KviOption_boolIdentdEnableIpV6,
+ KVI_OPTION_BOOL(KviOption_boolUseIdentService));
+#ifdef COMPILE_IPV6_SUPPORT
+ connect(m_pEnableIdent,SIGNAL(toggled(bool)),m_pEnableIpv6,SLOT(setEnabled(bool)));
+ connect(m_pEnableIpv6,SIGNAL(toggled(bool)),this,SLOT(enableIpv4InIpv6(bool)));
+#else
+ m_pEnableIpv6->setEnabled(false);
+#endif
+ m_pIpv4InIpv6 = addBoolSelector(gbox,__tr2qs_ctx("IP stack treats IPv4 as part of IPv6 namespace","options"),
+ KviOption_boolIdentdIpV6ContainsIpV4,
+ KVI_OPTION_BOOL(KviOption_boolUseIdentService) && KVI_OPTION_BOOL(KviOption_boolIdentdEnableIpV6));
+ connect(m_pEnableIdent,SIGNAL(toggled(bool)),gbox,SLOT(setEnabled(bool)));
+
+ addLabel(0,4,0,4,
+#ifdef COMPILE_ON_WINDOWS
+ __tr2qs_ctx("<p><b>Warning:</b><br>" \
+ "This is a <b>non RFC 1413 compliant</b> ident daemon that implements " \
+ "only a limited subset of the Identification Protocol specifications. If it is possible, install a " \
+ "real ident daemon.</p>","options")
+#else
+ __tr2qs_ctx("<p><b>Warning:</b><br>" \
+ "This is a <b>non RFC 1413 compliant</b> ident daemon that implements " \
+ "only a limited subset of the Identification Protocol specifications.<br>" \
+ "On UNIX, you may also need root privileges to bind to the auth port (113).<br>" \
+ "It is <b>highly recommended</b> that a <b>real</b> system-wide ident daemon be used instead, "\
+ "or none at all if ident is not required.</p>","options")
+#endif
+ );
+
+ addRowSpacer(0,5,0,5);
+}
+
+KviIdentOptionsWidget::~KviIdentOptionsWidget()
+{
+}
+
+void KviIdentOptionsWidget::commit()
+{
+ KviOptionsWidget::commit();
+ if(m_pConsoleRadio->isOn())
+ KVI_OPTION_UINT(KviOption_uintIdentdOutputMode)=KviIdentdOutputMode::ToConsole;
+ if(m_pActiveRadio->isOn())
+ KVI_OPTION_UINT(KviOption_uintIdentdOutputMode)=KviIdentdOutputMode::ToActiveWindow;
+ if(m_pQuietRadio->isOn())
+ KVI_OPTION_UINT(KviOption_uintIdentdOutputMode)=KviIdentdOutputMode::Quiet;
+}
+
+void KviIdentOptionsWidget::enableIpv4InIpv6(bool)
+{
+#ifdef COMPILE_IPV6_SUPPORT
+ m_pIpv4InIpv6->setEnabled(m_pEnableIdent->isChecked() && m_pEnableIpv6->isChecked());
+#endif
+}
+
+
+
+
+
+
+
+KviConnectionAdvancedOptionsWidget::KviConnectionAdvancedOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"connection_advanced_options_widget")
+{
+
+}
+
+KviConnectionAdvancedOptionsWidget::~KviConnectionAdvancedOptionsWidget()
+{
+
+}
+
+#include "m_optw_connection.moc"
diff --git a/src/modules/options/optw_connection.h b/src/modules/options/optw_connection.h
new file mode 100644
index 00000000..189ee4a0
--- /dev/null
+++ b/src/modules/options/optw_connection.h
@@ -0,0 +1,116 @@
+#ifndef _OPTW_CONNECTION_H_
+#define _OPTW_CONNECTION_H_
+//
+// File : optw_connection.h
+// Creation date : Sat Nov 24 04:25:12 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_optionswidget.h"
+
+#define KVI_OPTIONS_WIDGET_ICON_KviConnectionOptionsWidget KVI_SMALLICON_WORLD
+#define KVI_OPTIONS_WIDGET_NAME_KviConnectionOptionsWidget __tr2qs_no_lookup("Connection")
+#define KVI_OPTIONS_WIDGET_PRIORITY_KviConnectionOptionsWidget 98000
+
+class KviConnectionOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviConnectionOptionsWidget(QWidget * parent);
+ ~KviConnectionOptionsWidget();
+};
+
+
+#define KVI_OPTIONS_WIDGET_ICON_KviConnectionAdvancedOptionsWidget KVI_SMALLICON_WORLD
+#define KVI_OPTIONS_WIDGET_NAME_KviConnectionAdvancedOptionsWidget __tr2qs_no_lookup("Advanced")
+#define KVI_OPTIONS_WIDGET_PARENT_KviConnectionAdvancedOptionsWidget KviConnectionOptionsWidget
+#define KVI_OPTIONS_WIDGET_CONTAINER_KviConnectionAdvancedOptionsWidget true
+
+class KviConnectionAdvancedOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviConnectionAdvancedOptionsWidget(QWidget * parent);
+ ~KviConnectionAdvancedOptionsWidget();
+};
+
+
+#define KVI_OPTIONS_WIDGET_ICON_KviSSLOptionsWidget KVI_SMALLICON_SSL
+#define KVI_OPTIONS_WIDGET_NAME_KviSSLOptionsWidget __tr2qs_no_lookup("SSL")
+#define KVI_OPTIONS_WIDGET_PARENT_KviSSLOptionsWidget KviConnectionAdvancedOptionsWidget
+#define KVI_OPTIONS_WIDGET_PRIORITY_KviSSLOptionsWidget 30
+
+
+
+class KviSSLOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviSSLOptionsWidget(QWidget * parent);
+ ~KviSSLOptionsWidget();
+};
+
+
+
+#define KVI_OPTIONS_WIDGET_ICON_KviTransportOptionsWidget KVI_SMALLICON_SOCKETERROR
+#define KVI_OPTIONS_WIDGET_NAME_KviTransportOptionsWidget __tr2qs_no_lookup("Socket")
+#define KVI_OPTIONS_WIDGET_PARENT_KviTransportOptionsWidget KviConnectionAdvancedOptionsWidget
+#define KVI_OPTIONS_WIDGET_PRIORITY_KviTransportOptionsWidget 20
+
+
+class KviTransportOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviTransportOptionsWidget(QWidget * parent);
+ ~KviTransportOptionsWidget();
+};
+
+
+#define KVI_OPTIONS_WIDGET_ICON_KviIdentOptionsWidget KVI_SMALLICON_IDENT
+#define KVI_OPTIONS_WIDGET_NAME_KviIdentOptionsWidget __tr2qs_no_lookup("Ident Service")
+#define KVI_OPTIONS_WIDGET_PARENT_KviIdentOptionsWidget KviConnectionAdvancedOptionsWidget
+#define KVI_OPTIONS_WIDGET_PRIORITY_KviIdentOptionsWidget 10
+
+class QRadioButton;
+
+class KviIdentOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviIdentOptionsWidget(QWidget * parent);
+ ~KviIdentOptionsWidget();
+
+ virtual void commit();
+protected:
+ KviBoolSelector * m_pEnableIdent;
+ KviBoolSelector * m_pEnableIpv6;
+ KviBoolSelector * m_pIpv4InIpv6;
+
+ QRadioButton *m_pConsoleRadio;
+ QRadioButton *m_pActiveRadio;
+ QRadioButton *m_pQuietRadio;
+public slots:
+ void enableIpv4InIpv6(bool);
+};
+
+
+
+
+#endif //_OPTW_CONNECTION_H_
diff --git a/src/modules/options/optw_ctcp.cpp b/src/modules/options/optw_ctcp.cpp
new file mode 100644
index 00000000..3913751e
--- /dev/null
+++ b/src/modules/options/optw_ctcp.cpp
@@ -0,0 +1,90 @@
+//
+// File : optw_ctcp.cpp
+// Creation date : Sun Dec 2 20:40:43 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "optw_ctcp.h"
+
+#include "kvi_settings.h"
+#include "kvi_locale.h"
+#include "kvi_options.h"
+
+//#ifdef COMPILE_INFO_TIPS
+// #include "kvi_tal_tooltip.h"
+//#endif
+
+KviCtcpOptionsWidget::KviCtcpOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"ctcp_options_widget")
+{
+
+ createLayout(4,1);
+
+ QLabel * l;
+ l = addLabel(0,0,0,0,__tr2qs_ctx("<center><b>Settings for CTCP.</b></center>"\
+ "<p>The <b>Client-To-Client Protocol</b> (CTCP) " \
+ "is used to transmit special control messages over an IRC connection. " \
+ "These messages can request information from clients or negotiate file transfers." \
+ "<br><br></p>","options"));
+
+
+ KviTalGroupBox *gs = addGroupBox(0,1,0,1,1,Qt::Horizontal,__tr2qs_ctx("CTCP Replies","options"));
+ KviStringSelector * s = addStringSelector(gs, __tr2qs_ctx("Append to VERSION reply:","options"),KviOption_stringCtcpVersionPostfix);
+
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(s,
+ __tr2qs_ctx("<center>This text will be appended to the CTCP VERSION reply.<br>For example, you can place a script name here.</center>","options"));
+#endif
+
+ s = addStringSelector(gs, __tr2qs_ctx("Append to SOURCE reply:","options"),KviOption_stringCtcpSourcePostfix);
+
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(s,
+ __tr2qs_ctx("<center>This text will be appended to the CTCP SOURCE reply.<br>For example, you can place the source URL for a script here.</center>","options"));
+#endif
+
+// s = addStringSelector(gs, __tr2qs_ctx("USERINFO reply:","options"),KviOption_stringCtcpUserinfoReply);
+
+//#ifdef COMPILE_INFO_TIPS
+// mergeTip(s,
+// __tr2qs_ctx("<center>This is the CTCP USERINFO reply.<br>It can contain some information about yourself.</center>","options"));
+//#endif
+
+ s = addStringSelector(gs, __tr2qs_ctx("PAGE reply:","options"),KviOption_stringCtcpPageReply);
+
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(s,
+ __tr2qs_ctx("<center>This is the CTCP PAGE reply.<br>It should contain some sort of acknowledgement for CTCP PAGE messages.</center>","options"));
+#endif
+
+ addBoolSelector(gs,__tr2qs_ctx("Show the CTCP replies in the active window","options"),KviOption_boolCtcpRepliesToActiveWindow);
+
+ addBoolSelector(gs,__tr2qs_ctx("Show dialog for CTCP page requests","options"),KviOption_boolShowDialogOnCtcpPage);
+
+ addRowSpacer(0,3,0,3);
+
+}
+
+
+KviCtcpOptionsWidget::~KviCtcpOptionsWidget()
+{
+}
+
+
+#include "m_optw_ctcp.moc"
diff --git a/src/modules/options/optw_ctcp.h b/src/modules/options/optw_ctcp.h
new file mode 100644
index 00000000..55bdb238
--- /dev/null
+++ b/src/modules/options/optw_ctcp.h
@@ -0,0 +1,41 @@
+#ifndef _OPTW_CTCP_H_
+#define _OPTW_CTCP_H_
+//
+// File : optw_ctcp.h
+// Creation date : Sun Dec 2 20:40:43 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_optionswidget.h"
+
+#define KVI_OPTIONS_WIDGET_ICON_KviCtcpOptionsWidget KVI_SMALLICON_CTCPREQUESTREPLIED
+#define KVI_OPTIONS_WIDGET_NAME_KviCtcpOptionsWidget __tr2qs_no_lookup("CTCP")
+#define KVI_OPTIONS_WIDGET_PARENT_KviCtcpOptionsWidget KviToolsOptionsWidget
+#define KVI_OPTIONS_WIDGET_PRIORITY_KviCtcpOptionsWidget 70000
+
+class KviCtcpOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviCtcpOptionsWidget(QWidget * parent);
+ ~KviCtcpOptionsWidget();
+};
+
+
+#endif //_OPTW_CTCP_H_
diff --git a/src/modules/options/optw_ctcpfloodprotection.cpp b/src/modules/options/optw_ctcpfloodprotection.cpp
new file mode 100644
index 00000000..f814858e
--- /dev/null
+++ b/src/modules/options/optw_ctcpfloodprotection.cpp
@@ -0,0 +1,116 @@
+//
+// File : optw_ctcpfloodprotection.cpp
+// Creation date : Sun Jan 21 2001 14:35:06 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "optw_ctcpfloodprotection.h"
+
+#include <qlayout.h>
+
+#include "kvi_options.h"
+#include "kvi_locale.h"
+
+#include <qlabel.h>
+
+/*
+ @doc: ctcpfloodprotectionoptions
+ @type:
+ widget
+ @title:
+ CTCP flood protection options
+ @short:
+ Protection against CTCP flooding
+ @keyterms:
+ ctcp flood
+ @body:
+ Here, you can configure the CTCP flood protection system.[br]
+ The CTCP engine in IRC clients may be subject to an attack, called "CTCP flooding".[br]
+ Basically, the attackers (usually there is more than one offending client) sends a stream
+ of CTCP requests to the victim's client, and the client attempts to respond to all requests
+ by sending a stream of replies to the server, which causes the server to disconnect the user
+ due to "excess flood" for sending too many messages before the server can process them.[br]
+ Many user defined scripts choose to completely ignore all the CTCP requests in order to prevent such attacks.[br]
+ KVIrc offers an alternative method that allows you to take advantage of the CTCP protocol
+ and at the same time prevent the flood attacks.[br]
+ The method is really simple: The client will only respond to a limited number of CTCP requests within a
+ specified time interval.[br]
+ The "Use flood protection" option enables this protection method.[br]
+ In the "Allowed up to" field you should enter the maximum number of CTCP requests that KVIrc should
+ respond to within the interval of time defined in the second field.[br]
+ A strong protection against floods would be replying to 4 requests every 20 seconds.[br]
+ The minimum effective setting is about 3 messages every 6 seconds.[br]
+ Please note that 3 messages every 6 seconds is NOT the same as 10 messages every 20 seconds;
+ the first setting would allow 3 requests within one second, but the client would
+ ignore all the requests for the next 5 seconds, the second setting would allow 10 messages within one second
+ and ignore everything for the next 19 seconds. Therefore, 3/6 is a safer setting.[br]
+ The maximum protection you can set is 0 messages within any number of seconds; in that case any
+ CTCP request will be considered a flood and ignored.[br]
+ [br][br]
+ You can also decide to ignore specific CTCP requests. For example, if you don't want to reply to PING
+ requests, just select "PING" under the "Ignored Requests" section.[br]
+ [br][br]
+ Some specific protection options can be set also in other CTCP options sections:
+ see the [widget:ctcpavatarprotooptions]CTCP AVATAR protocol options[/widget] and [widget:ctcpdccprotooptions]CTCP DCC protocol options[/widget].[br]
+*/
+
+
+KviCtcpFloodProtectionOptionsWidget::KviCtcpFloodProtectionOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"ctcpfloodprotection_options_widget")
+{
+ createLayout(4,2);
+
+ KviBoolSelector * b = addBoolSelector(0,0,1,0,__tr2qs_ctx("Use flood protection (recommended)","options"),KviOption_boolUseCtcpFloodProtection);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b,__tr2qs_ctx("<center>This option makes KVIrc only respond to a limited number of CTCP requests within a specified time interval, to prevent \"flooding\" CTCP messages.</center>","options"));
+#endif
+ KviUIntSelector * u = addUIntSelector(0,1,0,1,__tr2qs_ctx("Allow up to:","options"),KviOption_uintMaxCtcpRequests,0,10000,3,KVI_OPTION_BOOL(KviOption_boolUseCtcpFloodProtection));
+ u->setSuffix(__tr2qs_ctx(" requests","options"));
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(u,__tr2qs_ctx("<center>Minimum value: <b>0 requests</b><br>Maximum value: <b>10000 requests</b></center>","options"));
+#endif
+ connect(b,SIGNAL(toggled(bool)),u,SLOT(setEnabled(bool)));
+ u = addUIntSelector(1,1,1,1,__tr2qs_ctx("within:","options"),KviOption_uintCtcpFloodCheckInterval,1,3600,6,KVI_OPTION_BOOL(KviOption_boolUseCtcpFloodProtection));
+ u->setSuffix(__tr2qs_ctx(" sec","options"));
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(u,__tr2qs_ctx("<center>Minimum value: <b>1 sec</b><br>Maximum value: <b>3600 sec</b></center>","options"));
+#endif
+ connect(b,SIGNAL(toggled(bool)),u,SLOT(setEnabled(bool)));
+
+ KviTalGroupBox * g = addGroupBox(0,2,1,2,2,Qt::Horizontal,__tr2qs_ctx("Ignored Requests","options"));
+ addBoolSelector(g,__tr2qs_ctx("PING","options"),KviOption_boolIgnoreCtcpPing);
+ addBoolSelector(g,__tr2qs_ctx("FINGER","options"),KviOption_boolIgnoreCtcpFinger);
+ addBoolSelector(g,__tr2qs_ctx("CLIENTINFO","options"),KviOption_boolIgnoreCtcpClientinfo);
+ addBoolSelector(g,__tr2qs_ctx("USERINFO","options"),KviOption_boolIgnoreCtcpUserinfo);
+ addBoolSelector(g,__tr2qs_ctx("VERSION","options"),KviOption_boolIgnoreCtcpVersion);
+ addBoolSelector(g,__tr2qs_ctx("SOURCE","options"),KviOption_boolIgnoreCtcpSource);
+ addBoolSelector(g,__tr2qs_ctx("TIME","options"),KviOption_boolIgnoreCtcpTime);
+ addBoolSelector(g,__tr2qs_ctx("PAGE","options"),KviOption_boolIgnoreCtcpPage);
+ addBoolSelector(g,__tr2qs_ctx("AVATAR","options"),KviOption_boolIgnoreCtcpAvatar);
+ addBoolSelector(g,__tr2qs_ctx("DCC/TDCC","options"),KviOption_boolIgnoreCtcpDcc);
+
+ addRowSpacer(0,3,1,3);
+}
+
+KviCtcpFloodProtectionOptionsWidget::~KviCtcpFloodProtectionOptionsWidget()
+{
+}
+
+
+#include "m_optw_ctcpfloodprotection.moc"
diff --git a/src/modules/options/optw_ctcpfloodprotection.h b/src/modules/options/optw_ctcpfloodprotection.h
new file mode 100644
index 00000000..43f28fbe
--- /dev/null
+++ b/src/modules/options/optw_ctcpfloodprotection.h
@@ -0,0 +1,41 @@
+#ifndef _OPTW_CTCPFLOODPROTECTION_H_
+#define _OPTW_CTCPFLOODPROTECTION_H_
+
+//
+// File : optw_ctcpfloodprotection.h
+// Creation date : Sun Jan 21 2000 14:34:12 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_optionswidget.h"
+
+#define KVI_OPTIONS_WIDGET_ICON_KviCtcpFloodProtectionOptionsWidget KVI_SMALLICON_CTCPREQUESTFLOOD
+#define KVI_OPTIONS_WIDGET_NAME_KviCtcpFloodProtectionOptionsWidget __tr2qs_no_lookup("Flood Protection")
+#define KVI_OPTIONS_WIDGET_PARENT_KviCtcpFloodProtectionOptionsWidget KviProtectionOptionsWidget
+
+class KviCtcpFloodProtectionOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+// Q_CLASSINFO("help","ctcpfloodprotectionoptions")
+public:
+ KviCtcpFloodProtectionOptionsWidget(QWidget * parent);
+ ~KviCtcpFloodProtectionOptionsWidget();
+};
+
+#endif //!_OPTW_CTCPFLOODPROTECTION_H_
diff --git a/src/modules/options/optw_dcc.cpp b/src/modules/options/optw_dcc.cpp
new file mode 100644
index 00000000..1b792da3
--- /dev/null
+++ b/src/modules/options/optw_dcc.cpp
@@ -0,0 +1,393 @@
+//=============================================================================
+//
+// File : optw_dcc.cpp
+// Creation date : Fri Aug 17 22:08:09 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "optw_dcc.h"
+
+#include <qlayout.h>
+
+#include "kvi_options.h"
+#include "kvi_locale.h"
+
+//#warning "Info tips"
+
+KviDccOptionsWidget::KviDccOptionsWidget(QWidget * pParent)
+: KviOptionsWidget(pParent)
+{
+}
+
+KviDccOptionsWidget::~KviDccOptionsWidget()
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+KviDccGeneralOptionsWidget::KviDccGeneralOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"dccgeneral_options_widget")
+{
+ createLayout(2,1);
+
+ KviBoolSelector * b = addBoolSelector(0,0,0,0,__tr2qs_ctx("Use workaround for firewall","options"),KviOption_boolCantAcceptIncomingDccConnections);
+
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b,__tr2qs_ctx("<center>Enable this option if you can't accept incoming connections.<br>" \
+ "KVIrc will try to use different methods to send and receive files.<br>" \
+ "Please note that these methods may NOT work when communicating with a non-KVIrc client.</center>","options"));
+#endif
+
+ addRowSpacer(0,1,0,1);
+}
+
+KviDccGeneralOptionsWidget::~KviDccGeneralOptionsWidget()
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+KviDccAdvancedOptionsWidget::KviDccAdvancedOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"dccgeneral_options_widget")
+{
+ createLayout(5,1);
+
+ KviTalGroupBox * g = addGroupBox(0,0,0,0,1,Qt::Horizontal,__tr2qs_ctx("Network Properties","options"));
+
+ KviBoolSelector * b = addBoolSelector(g,__tr2qs_ctx("Use user-defined address or network interface","options"),KviOption_boolDccListenOnSpecifiedInterfaceByDefault);
+
+
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b,__tr2qs_ctx("<center>Enable this option if you are on a multihost machine and want " \
+ "to force one of the available IP addresses to be used for outgoing DCCs.<br>This is especially useful " \
+ "when you use IPv6 and IPv4 addresses.<br>You can force KVIrc to always choose the IPv4 interface.</center>","options"));
+#endif
+
+ KviStringSelector * s = addStringSelector(g,__tr2qs_ctx("Listen on address/interface:","options"),KviOption_stringDccListenDefaultInterface,KVI_OPTION_BOOL(KviOption_boolDccListenOnSpecifiedInterfaceByDefault));
+
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(s,__tr2qs_ctx("<center>This is the IP address or name of the interface to use by default for outgoing DCC transfers.<br>" \
+ "On UNIX systems that support it, you can also specify IPv4 interface names (such as <b>ppp0</b>).<br>" \
+ "If you set it to <b>0.0.0.0</b>, KVIrc will try to use the first available IPv4 interface</center>","options"));
+#endif
+
+ connect(b,SIGNAL(toggled(bool)),s,SLOT(setEnabled(bool)));
+
+ b = addBoolSelector(g,__tr2qs_ctx("Use user-defined port range","options"),KviOption_boolUserDefinedPortRange);
+
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b,__tr2qs_ctx("<center>Enable this option if you want specify a local port range for DCC.</center>","options"));
+#endif
+
+ KviTalHBox * hb = new KviTalHBox(g);
+ hb->setSpacing(4);
+ KviUIntSelector * u = addUIntSelector(hb,__tr2qs_ctx("Lowest port:","options"),KviOption_uintDccMinPort,1,65535,5000,KVI_OPTION_BOOL(KviOption_boolUserDefinedPortRange));
+ connect(b,SIGNAL(toggled(bool)),u,SLOT(setEnabled(bool)));
+
+ u = addUIntSelector(hb,__tr2qs_ctx("Highest port:","options"),KviOption_uintDccMaxPort,1,65535,30000,KVI_OPTION_BOOL(KviOption_boolUserDefinedPortRange));
+ connect(b,SIGNAL(toggled(bool)),u,SLOT(setEnabled(bool)));
+
+ b = addBoolSelector(g,__tr2qs_ctx("Send a fixed address in requests","options"),KviOption_boolDccSendFakeAddressByDefault);
+
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b,__tr2qs_ctx("<center>Enable this option if you want to always send a fake IP address in your DCC requests.<br>" \
+ "This might be useful if you're behind a router with a static address that does network address translation (NAT) and forwards all or a range of ports.</center>","options"));
+#endif
+
+ s = addStringSelector(g,__tr2qs_ctx("Send address/interface:","options"),KviOption_stringDefaultDccFakeAddress,KVI_OPTION_BOOL(KviOption_boolDccSendFakeAddressByDefault));
+ connect(b,SIGNAL(toggled(bool)),s,SLOT(setEnabled(bool)));
+
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(s,__tr2qs_ctx("<center>This is the fixed address that will be sent with all DCC requests if you enable the option above.</center>","options"));
+#endif
+
+ KviBoolSelector * b2;
+ b2 = addBoolSelector(g,__tr2qs_ctx("Guess address from IRC server if unroutable","options"),
+ KviOption_boolDccGuessIpFromServerWhenLocalIsUnroutable,!KVI_OPTION_BOOL(KviOption_boolDccSendFakeAddressByDefault));
+ connect(b,SIGNAL(toggled(bool)),b2,SLOT(setNotEnabled(bool)));
+
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b2,__tr2qs_ctx("<center>You can enable this option if you are behind a router that forwards all or a range of ports.<br>" \
+ "KVIrc will try to guess the IP address to use for DCC by looking up the local hostname as seen " \
+ "by the IRC server you're connected to.<br>This method is an exclusive alternative to the \"fixed address\" above.<br>" \
+ "It might guess the correct address automatically if certain conditions are met (e.g. the IRC server does not mask hostnames).</center>","options"));
+#endif
+
+ b = addBoolSelector(g,__tr2qs_ctx("Use \"broken bouncer hack\" to detect address","options"),
+ KviOption_boolDccBrokenBouncerHack,KVI_OPTION_BOOL(KviOption_boolDccGuessIpFromServerWhenLocalIsUnroutable));
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b,__tr2qs_ctx("<center>When you're behind a dialup router and also tunneling through a psyBNC bouncer, " \
+ "you can use a bug in the bouncer to force KVIrc to bind the DCC connections to the dialup router's address.<br>" \
+ "It's an ugly hack - use it only if nothing else works.</center>","options"));
+#endif
+
+ connect(b2,SIGNAL(toggled(bool)),b,SLOT(setEnabled(bool)));
+
+ b = addBoolSelector(0,1,1,1,__tr2qs_ctx("Notify failed DCC handshakes to the remote end","options"),
+ KviOption_boolNotifyFailedDccHandshakes);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b,__tr2qs_ctx("<center>If you enable this option, when a DCC request from a remote " \
+ "user can't be satisfied KVIrc will notify him by a CTCP ERRMSG. This is " \
+ "a nice feature so it is a good idea to leave it on unless for some reason " \
+ "you have deactivated the antiflood system: in this case turning off this option " \
+ "might help if you often get attacked by CTCP floods.</center>","options"));
+#endif
+
+ u = addUIntSelector(0,2,1,2,__tr2qs_ctx("Maximum number of DCC sessions","options"),KviOption_uintMaxDccSlots,0,1000,64);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(u,__tr2qs_ctx("<center>This is the maximum number of concurrent DCC sessions " \
+ "and it includes all the DCC types (send,chat,recv...). " \
+ "KVIrc will refuse the requests when this limit is reached.</center>","options"));
+#endif
+
+ addUIntSelector(0,3,1,3,__tr2qs_ctx("DCC socket timeout:","options"),KviOption_uintDccSocketTimeout,10,65536,180);
+ u->setSuffix(__tr2qs_ctx(" sec","options"));
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(u,__tr2qs_ctx("<center>This is the amount of time that KVIrc will wait for a response before assuming that a DCC has failed " \
+ "because the remote client was unable to connect to our listening socket.</center>","options"));
+#endif
+
+ addRowSpacer(0,4,1,4);
+}
+
+KviDccAdvancedOptionsWidget::~KviDccAdvancedOptionsWidget()
+{
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+KviDccSendOptionsWidget::KviDccSendOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"dccsend_options_widget")
+{
+}
+
+KviDccSendOptionsWidget::~KviDccSendOptionsWidget()
+{
+}
+
+
+
+KviDccSendGeneralOptionsWidget::KviDccSendGeneralOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"dccsend_options_widget")
+{
+ createLayout(5,1);
+
+ KviBoolSelector * b;
+
+ KviTalGroupBox * g = addGroupBox(0,0,0,0,1,Qt::Horizontal,__tr2qs_ctx("On Incoming File","options"));
+ KviBoolSelector * b2 = addBoolSelector(g,__tr2qs_ctx("Automatically accept","options"),KviOption_boolAutoAcceptDccSend);
+ KviBoolSelector * b3 = addBoolSelector(g,__tr2qs_ctx("Open transfer window as minimized when auto-accepted","options"),KviOption_boolCreateMinimizedDccSendWhenAutoAccepted,!KVI_OPTION_BOOL(KviOption_boolCreateMinimizedDccSend));
+ KviBoolSelector * b4 = addBoolSelector(g,__tr2qs_ctx("Automatically resume when auto-accepted","options"),KviOption_boolAutoResumeDccSendWhenAutoAccepted,KVI_OPTION_BOOL(KviOption_boolAutoAcceptDccSend));
+
+ g = addGroupBox(0,1,0,1,1,Qt::Horizontal,__tr2qs_ctx("Save Location","options"));
+ addDirectorySelector(g,__tr2qs_ctx("Download folder:","options"),KviOption_stringIncomingPath);
+ addBoolSelector(g,__tr2qs_ctx("Sort saved files by nicknames (create subfolders)","options"),KviOption_boolSortReceivedByDccFilesByNicks);
+ addBoolSelector(g,__tr2qs_ctx("Guess save path from media type","options"),KviOption_boolUseIncomingDccMediaTypeSavePath);
+
+
+ g = addGroupBox(0,2,0,2,1,Qt::Horizontal,__tr2qs_ctx("On Download Completion","options"));
+ addBoolSelector(g,__tr2qs_ctx("Notify completion in console","options"),KviOption_boolNotifyDccSendSuccessInConsole);
+ addBoolSelector(g,__tr2qs_ctx("Notify completion in notifier","options"),KviOption_boolNotifyDccSendSuccessInNotifier);
+ b = addBoolSelector(g,__tr2qs_ctx("Automatically clear transfer","options"),KviOption_boolAutoCloseDccSendOnSuccess);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b,
+ __tr2qs_ctx("<center>This option will cause succesfully terminated transfers " \
+ "to be automatically removed from the transfer window.</center>","options"));
+#endif //COMPILE_INFO_TIPS
+
+
+ KviBoolSelector * b1 = addBoolSelector(0,3,0,3,__tr2qs_ctx("Always open transfer window as minimized","options"),KviOption_boolCreateMinimizedDccSend);
+
+ connect(b1,SIGNAL(toggled(bool)),b3,SLOT(setNotEnabled(bool)));
+ connect(b2,SIGNAL(toggled(bool)),b4,SLOT(setEnabled(bool)));
+
+ addRowSpacer(0,4,0,4);
+}
+
+KviDccSendGeneralOptionsWidget::~KviDccSendGeneralOptionsWidget()
+{
+}
+
+
+KviDccSendAdvancedOptionsWidget::KviDccSendAdvancedOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"dccsend_advanced_options_widget")
+{
+ createLayout(4,1);
+
+ KviTalGroupBox * g = addGroupBox(0,0,0,0,1,Qt::Horizontal,__tr2qs_ctx("Bug Compatibility","options"));
+ KviBoolSelector * b = addBoolSelector(g,__tr2qs_ctx("Send ACK for byte 0","options"),KviOption_boolSendZeroAckInDccRecv);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b,
+ __tr2qs_ctx("<center>This option causes KVIrc to send a zero-byte acknowledge to kick-start " \
+ "the DCC transfer with some buggy IRC clients.<br>" \
+ "Use it only if your DCC transfers stall just after establishing a connection without sending any data.</center>","options"));
+#endif //COMPILE_INFO_TIPS
+
+ b = addBoolSelector(g,__tr2qs_ctx("Accept broken RESUME (mIRC file.ext)","options"),KviOption_boolAcceptBrokenFileNameDccResumeRequests);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b,
+ __tr2qs_ctx("<center>This option causes KVIrc to accept RESUME requests with invalid filenames.<br>" \
+ "Use it if KVIrc fails to accept RESUME requests from other clients (e.g. some versions of mIRC).</center>","options"));
+#endif //COMPILE_INFO_TIPS
+
+ b = addBoolSelector(g,__tr2qs_ctx("Replace spaces with underscores in outgoing filenames","options"),KviOption_boolDCCFileTransferReplaceOutgoingSpacesWithUnderscores);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b,
+ __tr2qs_ctx("<center>This option causes KVIrc to replace spaces with underscores in filenames " \
+ "for all the outgoing file transfers. This will fix filename handling with some buggy clients (e.g. some versions of mIRC).","options"));
+#endif //COMPILE_INFO_TIPS
+
+
+ g = addGroupBox(0,1,0,1,1,Qt::Horizontal,__tr2qs_ctx("Limits","options"));
+
+ KviTalHBox * hb = new KviTalHBox(g);
+ b = addBoolSelector(hb,__tr2qs_ctx("Limit upload bandwidth to","options"),KviOption_boolLimitDccSendSpeed);
+ KviUIntSelector * u = addUIntSelector(hb,"",KviOption_uintMaxDccSendSpeed,0,0xffffff1,1024,KVI_OPTION_BOOL(KviOption_boolLimitDccSendSpeed));
+ u->setSuffix(" " + __tr2qs_ctx("bytes/sec","options"));
+ connect(b,SIGNAL(toggled(bool)),u,SLOT(setEnabled(bool)));
+
+ hb = new KviTalHBox(g);
+ b = addBoolSelector(hb,__tr2qs_ctx("Limit download bandwidth to","options"),KviOption_boolLimitDccRecvSpeed);
+ u = addUIntSelector(hb,"",KviOption_uintMaxDccRecvSpeed,0,0xffffff1,1024,KVI_OPTION_BOOL(KviOption_boolLimitDccRecvSpeed));
+ u->setSuffix(" " + __tr2qs_ctx("bytes/sec","options"));
+ connect(b,SIGNAL(toggled(bool)),u,SLOT(setEnabled(bool)));
+
+
+ u = addUIntSelector(g,__tr2qs_ctx("Maximum number of DCC transfers","options"),KviOption_uintMaxDccSendTransfers,0,1000,10);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(u,__tr2qs_ctx("<center>This is the maximum number of concurrent DCC transfers. " \
+ "KVIrc will refuse the requests when this limit is reached.</center>","options"));
+#endif
+
+ g = addGroupBox(0,2,0,2,1,Qt::Horizontal,__tr2qs_ctx("Tweaks","options"));
+
+ b = addBoolSelector(g,__tr2qs_ctx("Use fast send (send ahead)","options"),KviOption_boolUseFastDccSend);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b,
+ __tr2qs_ctx("<center>The \"send ahead\" DCC method allows data to be sent faster by breaking " \
+ "some of the rules of the original DCC SEND protocol specification.<br>" \
+ "Most clients can handle this kind of optimisation so disable it only if you have problems.</center>","options"));
+#endif //COMPILE_INFO_TIPS
+
+ hb = new KviTalHBox(g);
+
+ b = addBoolSelector(hb,__tr2qs_ctx("Force idle step","options"),KviOption_boolDccSendForceIdleStep);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b,
+ __tr2qs_ctx("<center>Enable this option when the dcc file transfers " \
+ "tend to block your computer by consuming too much CPU time. " \
+ "When this option is enabled the idle interval below will be " \
+ "forcibly inserted between each sent/received data packet.</center>","options"));
+#endif // COMPILE_INFO_TIPS
+
+ u = addUIntSelector(hb,__tr2qs_ctx("","options"),KviOption_uintDccSendIdleStepInMSec,1,65536,30,KVI_OPTION_BOOL(KviOption_boolDccSendForceIdleStep));
+ connect(b,SIGNAL(toggled(bool)),u,SLOT(setEnabled(bool)));
+ u->setSuffix(__tr2qs_ctx(" msec","options"));
+
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(u,
+ __tr2qs_ctx("<center>This parameter controls the average delay between two packets sent or received.<br>" \
+ "A smaller interval will cause you to send data faster but will also " \
+ "add load to your CPU, disk and network interface.<br>" \
+ "Reasonable values are from 5 to 50 milliseconds.</center>","options"));
+#endif //COMPILE_INFO_TIPS
+
+ u = addUIntSelector(g,__tr2qs_ctx("Packet size:","options"),KviOption_uintDccSendPacketSize,16,65536,1024);
+ u->setSuffix(__tr2qs_ctx(" bytes","options"));
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(u,
+ __tr2qs_ctx("<center>This parameter controls the packet size used for DCC SEND.<br>" \
+ "With bigger packets you will be probably send data faster, but " \
+ "you will also saturate your bandwidth and in some cases " \
+ "cause more disk activity.<br>" \
+ "Reasonable values are from 512 to 4096 bytes.</center>","options"));
+#endif //COMPILE_INFO_TIPS
+
+
+ addRowSpacer(0,3,0,3);
+
+}
+
+KviDccSendAdvancedOptionsWidget::~KviDccSendAdvancedOptionsWidget()
+{
+
+}
+
+
+//KviDccSendOptionsWidget::enableStuff(bool)
+//{
+// m_pOpenMinimizedAutoAccept->setEnabled(m_pAutoAccept->isChecked() && !m_pOpenMinimized->isChecked());
+//}
+
+
+KviDccChatOptionsWidget::KviDccChatOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"dccchat_options_widget")
+{
+ createLayout(3,1);
+
+ KviTalGroupBox * g = addGroupBox(0,0,0,0,1,Qt::Horizontal,__tr2qs_ctx("On Chat Request","options"));
+ KviBoolSelector * b = addBoolSelector(g,__tr2qs_ctx("Automatically accept","options"),KviOption_boolAutoAcceptDccChat);
+ b = addBoolSelector(g,__tr2qs_ctx("Open minimized when auto-accepted","options"),KviOption_boolCreateMinimizedDccChatWhenAutoAccepted,!KVI_OPTION_BOOL(KviOption_boolCreateMinimizedDccChat));
+
+ KviBoolSelector * b1 = addBoolSelector(0,1,0,1,__tr2qs_ctx("Always open as minimized","options"),KviOption_boolCreateMinimizedDccChat);
+
+ connect(b1,SIGNAL(toggled(bool)),b,SLOT(setNotEnabled(bool)));
+
+ addRowSpacer(0,2,0,2);
+}
+
+KviDccChatOptionsWidget::~KviDccChatOptionsWidget()
+{
+}
+
+
+KviDccVoiceOptionsWidget::KviDccVoiceOptionsWidget(QWidget *p):KviOptionsWidget(p)
+{
+ createLayout(8, 1);
+
+ KviBoolSelector * b1 = addBoolSelector(0,0,0,0,__tr2qs_ctx("Open all minimized","options"),KviOption_boolCreateMinimizedDccVoice);
+ KviTalGroupBox * g = addGroupBox(0,1,0,1,1,Qt::Horizontal,__tr2qs_ctx("On Voice Request","options"));
+ KviBoolSelector * b = addBoolSelector(g,__tr2qs_ctx("Automatically accept","options"),KviOption_boolAutoAcceptDccVoice);
+
+ b = addBoolSelector(g,__tr2qs_ctx("Open minimized when auto-accepted","options"),KviOption_boolCreateMinimizedDccVoiceWhenAutoAccepted,!KVI_OPTION_BOOL(KviOption_boolCreateMinimizedDccVoice));
+ connect(b1,SIGNAL(toggled(bool)),b,SLOT(setNotEnabled(bool)));
+
+ addBoolSelector(0,2,0,2,__tr2qs_ctx("Force half-duplex mode on sound device","options"), KviOption_boolDccVoiceForceHalfDuplex);
+ addBoolSelector(0,3,0,3,__tr2qs_ctx("Volume slider controls PCM, not Master","options"), KviOption_boolDccVoiceVolumeSliderControlsPCM);
+
+ addStringSelector(0,4,0,4,__tr2qs_ctx("Sound device:","options"), KviOption_stringDccVoiceSoundDevice);
+ addStringSelector(0,5,0,5,__tr2qs_ctx("Mixer device:","options"), KviOption_stringDccVoiceMixerDevice);
+
+ KviUIntSelector * u = addUIntSelector(0,6,0,6,__tr2qs_ctx("Pre-buffer size:","options"), KviOption_uintDccVoicePreBufferSize, 2048, 65536, 32000);
+ u->setSuffix(" bytes");
+
+
+ addRowSpacer(0,7,0,7);
+}
+
+KviDccVoiceOptionsWidget::~KviDccVoiceOptionsWidget()
+{
+}
+
+#include "m_optw_dcc.moc"
diff --git a/src/modules/options/optw_dcc.h b/src/modules/options/optw_dcc.h
new file mode 100644
index 00000000..5dc67424
--- /dev/null
+++ b/src/modules/options/optw_dcc.h
@@ -0,0 +1,139 @@
+#ifndef _OPTW_DCC_H_
+#define _OPTW_DCC_H_
+//
+// File : optw_dcc.h
+// Creation date : Fri Aug 17 22:08:08 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_optionswidget.h"
+
+#define KVI_OPTIONS_WIDGET_ICON_KviDccOptionsWidget KVI_SMALLICON_DCCERROR
+#define KVI_OPTIONS_WIDGET_NAME_KviDccOptionsWidget __tr2qs_no_lookup("DCC")
+#define KVI_OPTIONS_WIDGET_PRIORITY_KviDccOptionsWidget 70000
+#define KVI_OPTIONS_WIDGET_CONTAINER_KviDccOptionsWidget true
+
+class KviDccOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviDccOptionsWidget(QWidget * parent);
+ ~KviDccOptionsWidget();
+};
+
+
+
+#define KVI_OPTIONS_WIDGET_ICON_KviDccGeneralOptionsWidget KVI_SMALLICON_DCCERROR
+#define KVI_OPTIONS_WIDGET_NAME_KviDccGeneralOptionsWidget __tr2qs_no_lookup("General")
+#define KVI_OPTIONS_WIDGET_PRIORITY_KviDccGeneralOptionsWidget 70000
+#define KVI_OPTIONS_WIDGET_PARENT_KviDccGeneralOptionsWidget KviDccOptionsWidget
+
+class KviDccGeneralOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviDccGeneralOptionsWidget(QWidget * parent);
+ ~KviDccGeneralOptionsWidget();
+};
+
+#define KVI_OPTIONS_WIDGET_ICON_KviDccAdvancedOptionsWidget KVI_SMALLICON_DCCERROR
+#define KVI_OPTIONS_WIDGET_NAME_KviDccAdvancedOptionsWidget __tr2qs_no_lookup("Advanced")
+#define KVI_OPTIONS_WIDGET_PRIORITY_KviDccAdvancedOptionsWidget 70000
+#define KVI_OPTIONS_WIDGET_PARENT_KviDccAdvancedOptionsWidget KviDccOptionsWidget
+
+class KviDccAdvancedOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviDccAdvancedOptionsWidget(QWidget * parent);
+ ~KviDccAdvancedOptionsWidget();
+};
+
+
+
+
+#define KVI_OPTIONS_WIDGET_ICON_KviDccSendOptionsWidget KVI_SMALLICON_DCCMSG
+#define KVI_OPTIONS_WIDGET_NAME_KviDccSendOptionsWidget __tr2qs_no_lookup("File Transfer")
+#define KVI_OPTIONS_WIDGET_PARENT_KviDccSendOptionsWidget KviDccOptionsWidget
+#define KVI_OPTIONS_WIDGET_CONTAINER_KviDccSendOptionsWidget true
+
+
+class KviDccSendOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviDccSendOptionsWidget(QWidget * parent);
+ ~KviDccSendOptionsWidget();
+};
+
+#define KVI_OPTIONS_WIDGET_ICON_KviDccSendGeneralOptionsWidget KVI_SMALLICON_DCCMSG
+#define KVI_OPTIONS_WIDGET_NAME_KviDccSendGeneralOptionsWidget __tr2qs_no_lookup("General")
+#define KVI_OPTIONS_WIDGET_PARENT_KviDccSendGeneralOptionsWidget KviDccSendOptionsWidget
+
+
+class KviDccSendGeneralOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviDccSendGeneralOptionsWidget(QWidget * parent);
+ ~KviDccSendGeneralOptionsWidget();
+};
+
+
+#define KVI_OPTIONS_WIDGET_ICON_KviDccSendAdvancedOptionsWidget KVI_SMALLICON_DCCMSG
+#define KVI_OPTIONS_WIDGET_NAME_KviDccSendAdvancedOptionsWidget __tr2qs_no_lookup("Advanced")
+#define KVI_OPTIONS_WIDGET_PARENT_KviDccSendAdvancedOptionsWidget KviDccSendOptionsWidget
+
+class KviDccSendAdvancedOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviDccSendAdvancedOptionsWidget(QWidget * parent);
+ ~KviDccSendAdvancedOptionsWidget();
+};
+
+
+#define KVI_OPTIONS_WIDGET_ICON_KviDccChatOptionsWidget KVI_SMALLICON_DCCREQUEST
+#define KVI_OPTIONS_WIDGET_NAME_KviDccChatOptionsWidget __tr2qs_no_lookup("Chat")
+#define KVI_OPTIONS_WIDGET_PARENT_KviDccChatOptionsWidget KviDccOptionsWidget
+#define KVI_OPTIONS_WIDGET_NOTCONTAINED_KviDccChatOptionsWidget true
+
+class KviDccChatOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviDccChatOptionsWidget(QWidget * parent);
+ ~KviDccChatOptionsWidget();
+};
+
+#define KVI_OPTIONS_WIDGET_ICON_KviDccVoiceOptionsWidget KVI_SMALLICON_DCCVOICE
+#define KVI_OPTIONS_WIDGET_NAME_KviDccVoiceOptionsWidget __tr2qs_no_lookup("Voice")
+#define KVI_OPTIONS_WIDGET_PARENT_KviDccVoiceOptionsWidget KviDccOptionsWidget
+#define KVI_OPTIONS_WIDGET_NOTCONTAINED_KviDccVoiceOptionsWidget true
+
+class KviDccVoiceOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviDccVoiceOptionsWidget(QWidget *);
+ ~KviDccVoiceOptionsWidget();
+};
+
+
+#endif //_OPTW_DCC_H_
diff --git a/src/modules/options/optw_generalopt.cpp b/src/modules/options/optw_generalopt.cpp
new file mode 100644
index 00000000..18f86902
--- /dev/null
+++ b/src/modules/options/optw_generalopt.cpp
@@ -0,0 +1,51 @@
+//=============================================================================
+//
+// File : optw_generalopt.cpp
+// Creation date : Wed Nov 19 09:25:16 2005 GMT by Grifisx & Noldor
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2005 Grifisx & Noldor
+//
+// 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 opinion) 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.
+//
+//=============================================================================
+
+#include "optw_generalopt.h"
+
+#include "kvi_settings.h"
+#include "kvi_locale.h"
+#include "kvi_options.h"
+
+
+KviGeneralOptOptionsWidget::KviGeneralOptOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"generalopt_options_widget")
+{
+
+ createLayout(1,4);
+
+ QLabel * l;
+ l = addLabel(0,0,4,0,__tr2qs_ctx("This section contains the general client options<br>"\
+ "<p>like<b> sound, mediafiles, URL handler </b> etc... " \
+ "</p>","options"));
+ addAdvancedButton(4,1,4,1);
+}
+
+
+KviGeneralOptOptionsWidget::~KviGeneralOptOptionsWidget()
+{
+}
+
+
+#include "m_optw_generalopt.moc"
diff --git a/src/modules/options/optw_generalopt.h b/src/modules/options/optw_generalopt.h
new file mode 100644
index 00000000..fbaaf192
--- /dev/null
+++ b/src/modules/options/optw_generalopt.h
@@ -0,0 +1,39 @@
+#ifndef _OPTW_GENERALOPT_H_
+#define _OPTW_GENERALOPT_H_
+//
+// File : optw_generalopt.h
+// Creation date : Wed Nov 19 09:25:16 2005 GMT by Grifisx & Noldor
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2005 Grifisx & Noldor
+//
+// 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 opinion) 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.
+//
+
+#include "kvi_optionswidget.h"
+
+#define KVI_OPTIONS_WIDGET_ICON_KviGeneralOptOptionsWidget KVI_SMALLICON_OPTIONS
+#define KVI_OPTIONS_WIDGET_NAME_KviGeneralOptOptionsWidget __tr2qs_no_lookup("General options")
+#define KVI_OPTIONS_WIDGET_PRIORITY_KviGeneralOptOptionsWidget 40000
+
+class KviGeneralOptOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviGeneralOptOptionsWidget(QWidget * parent);
+ ~KviGeneralOptOptionsWidget();
+};
+
+#endif //_OPTW_CONNECTION_H_
diff --git a/src/modules/options/optw_highlighting.cpp b/src/modules/options/optw_highlighting.cpp
new file mode 100644
index 00000000..ef0f5442
--- /dev/null
+++ b/src/modules/options/optw_highlighting.cpp
@@ -0,0 +1,128 @@
+#ifndef _OPTW_HIGHLIGHTING_CPP_
+#define _OPTW_HIGHLIGHTING_CPP_
+//
+// File : optw_highlighting.cpp
+// Creation date : Sat Nov 3 18:09:35 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "optw_highlighting.h"
+
+#include <qlayout.h>
+
+#include "kvi_options.h"
+#include "kvi_locale.h"
+
+#include <qlabel.h>
+
+KviAlertHighlightingOptionsWidget::KviAlertHighlightingOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"highlighting_options_widget")
+{
+}
+
+KviAlertHighlightingOptionsWidget::~KviAlertHighlightingOptionsWidget()
+{
+}
+
+
+
+KviHighlightingOptionsWidget::KviHighlightingOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"highlighting_options_widget")
+{
+ createLayout(7,1);
+
+ KviBoolSelector * b;
+
+ connect(
+ addBoolSelector(0,0,0,0,__tr2qs_ctx("Enable word highlighting","options"),KviOption_boolUseWordHighlighting),
+ SIGNAL(toggled(bool)),
+ addStringListSelector(0,1,0,1,__tr2qs_ctx("Words to highlight:","options"),KviOption_stringlistHighlightWords,KVI_OPTION_BOOL(KviOption_boolUseWordHighlighting)),
+ SLOT(setEnabled(bool)));
+ addStringSelector(0,2,0,2,__tr2qs_ctx("Word splitters:","options"),KviOption_stringWordSplitters);
+ // This can be used even without Word highlighting
+ b = addBoolSelector(0,3,0,3,__tr2qs_ctx("Highlight messages containing my nickname","options"),KviOption_boolAlwaysHighlightNick);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b,__tr2qs_ctx("<center>If this option is enabled, KVIrc will highlight any user message containing your current nickname</center>","options"));
+#endif
+ b = addBoolSelector(0,4,0,4,__tr2qs_ctx("Flash the system taskbar entry on highlighted messages","options"),KviOption_boolFlashWindowOnHighlightedMessages);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b,__tr2qs_ctx("<center>If this option is enabled, KVIrc will (attempt to) flash the system taskbar entry when a highlighted message is printed and KVIrc is not the active window</center>","options"));
+#endif
+ b = addBoolSelector(0,5,0,5,__tr2qs_ctx("Popup the notifier window on highlighted messages","options"),KviOption_boolPopupNotifierOnHighlightedMessages);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b,__tr2qs_ctx("<center>If this option is enabled, KVIrc will popup a little notifier window in the low right corner of your desktop when a highlighted message is printed and KVIrc is not the active window</center>","options"));
+#endif
+
+ addRowSpacer(0,6,0,6);
+}
+
+KviHighlightingOptionsWidget::~KviHighlightingOptionsWidget()
+{
+}
+
+
+
+
+
+
+KviAlertOptionsWidget::KviAlertOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"highlighting_options_widget")
+{
+ createLayout(2,1);
+
+ KviBoolSelector * b;
+
+ KviTalGroupBox * g = addGroupBox(0,0,0,0,1,Qt::Horizontal,__tr2qs_ctx("Alert Restrictions","options"));
+ KviBoolSelector * b3 = addBoolSelector(g,__tr2qs_ctx("Restrict alert","options"),KviOption_boolHighlightOnlyNormalMsg);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b3, __tr2qs_ctx("<center>If this option is enabled, KVIrc will alert in the taskbar only if a normal message is received in a channel.<br>Actions like joins, parts and mode changes will be ignored.<br> This is useful if you are in channels with a high rate of traffic and only want to be alerted for messages that are interesting to you.</center>","options"));
+#endif
+ KviBoolSelector * b4 = addBoolSelector(g,__tr2qs_ctx("Alert for highlighted words","options"),KviOption_boolHighlightOnlyNormalMsgHighlightInChanToo,KVI_OPTION_BOOL(KviOption_boolHighlightOnlyNormalMsg));
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b4, __tr2qs_ctx("<center>If this option is enabled, the taskbar will also alert for messages which contain a word from the highlighted words list above.</center>","options"));
+#endif
+ KviBoolSelector * b5 = addBoolSelector(g,__tr2qs_ctx("Alert for query messages","options"),KviOption_boolHighlightOnlyNormalMsgQueryToo,KVI_OPTION_BOOL(KviOption_boolHighlightOnlyNormalMsg));
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b5, __tr2qs_ctx("<center>If this option is enabled, the taskbar will also alert for messages which are shown in queries.</center>","options"));
+#endif
+ connect(b3,SIGNAL(toggled(bool)),b4,SLOT(setEnabled(bool)));
+ connect(b3,SIGNAL(toggled(bool)),b5,SLOT(setEnabled(bool)));
+
+ KviBoolSelector * b6 = addBoolSelector(g,__tr2qs_ctx("Use custom alert level","options"),KviOption_boolHighlightOnlyAtCostumHighlightLevel);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b6, __tr2qs_ctx("<center>If this option is enabled, KVIrc will alert in the taskbar only if the specified alert level is reached.</center>","options"));
+#endif
+ KviUIntSelector * b7 = addUIntSelector(g,__tr2qs_ctx("Minimum alert level:","options"),KviOption_uintMinHighlightLevel,1,KVI_MSGTYPE_MAXLEVEL,KVI_MSGTYPE_MAXLEVEL,KVI_OPTION_UINT(KviOption_boolHighlightOnlyAtCostumHighlightLevel));
+ b7->setEnabled(KVI_OPTION_BOOL(KviOption_boolHighlightOnlyAtCostumHighlightLevel));
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b6, __tr2qs_ctx("<center>This option sets the minimum alert level for the taskbar.</center>","options"));
+#endif
+ connect(b6,SIGNAL(toggled(bool)),b7,SLOT(setEnabled(bool)));
+
+ addRowSpacer(0,1,0,1);
+}
+
+KviAlertOptionsWidget::~KviAlertOptionsWidget()
+{
+}
+
+
+#include "m_optw_highlighting.moc"
+
+#endif //_OPTW_HIGHLIGHTING_CPP_
diff --git a/src/modules/options/optw_highlighting.h b/src/modules/options/optw_highlighting.h
new file mode 100644
index 00000000..f222412e
--- /dev/null
+++ b/src/modules/options/optw_highlighting.h
@@ -0,0 +1,67 @@
+#ifndef _OPTW_HIGHLIGHTING_H_
+#define _OPTW_HIGHLIGHTING_H_
+//
+// File : optw_highlighting.h
+// Creation date : Sat Nov 3 18:09:37 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_optionswidget.h"
+
+#define KVI_OPTIONS_WIDGET_ICON_KviAlertHighlightingOptionsWidget KVI_SMALLICON_RAW
+#define KVI_OPTIONS_WIDGET_NAME_KviAlertHighlightingOptionsWidget __tr2qs_no_lookup("Alert/Highlight")
+#define KVI_OPTIONS_WIDGET_PARENT_KviAlertHighlightingOptionsWidget KviToolsOptionsWidget
+#define KVI_OPTIONS_WIDGET_CONTAINER_KviAlertHighlightingOptionsWidget true
+
+class KviAlertHighlightingOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviAlertHighlightingOptionsWidget(QWidget * parent);
+ ~KviAlertHighlightingOptionsWidget();
+};
+
+
+#define KVI_OPTIONS_WIDGET_ICON_KviHighlightingOptionsWidget KVI_SMALLICON_RAW
+#define KVI_OPTIONS_WIDGET_NAME_KviHighlightingOptionsWidget __tr2qs_no_lookup("Highlight")
+#define KVI_OPTIONS_WIDGET_PARENT_KviHighlightingOptionsWidget KviAlertHighlightingOptionsWidget
+
+class KviHighlightingOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviHighlightingOptionsWidget(QWidget * parent);
+ ~KviHighlightingOptionsWidget();
+};
+
+
+#define KVI_OPTIONS_WIDGET_ICON_KviAlertOptionsWidget KVI_SMALLICON_RAW
+#define KVI_OPTIONS_WIDGET_NAME_KviAlertOptionsWidget __tr2qs_no_lookup("Taskbar Alert")
+#define KVI_OPTIONS_WIDGET_PARENT_KviAlertOptionsWidget KviAlertHighlightingOptionsWidget
+
+class KviAlertOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviAlertOptionsWidget(QWidget * parent);
+ ~KviAlertOptionsWidget();
+};
+
+
+#endif //_OPTW_HIGHLIGHTING_H_
diff --git a/src/modules/options/optw_ident.cpp b/src/modules/options/optw_ident.cpp
new file mode 100644
index 00000000..7dafdd52
--- /dev/null
+++ b/src/modules/options/optw_ident.cpp
@@ -0,0 +1,37 @@
+//================================================================================
+//
+// File : optw_ident.cpp
+// Creation date : Mon Oct 29 15:48:42 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//================================================================================
+
+#include "optw_ident.h"
+
+#include <kvi_tal_groupbox.h>
+
+#include "kvi_options.h"
+#include "kvi_locale.h"
+#include "kvi_settings.h"
+
+//#warning "Info tips"
+
+
+
+#include "m_optw_ident.moc"
diff --git a/src/modules/options/optw_ident.h b/src/modules/options/optw_ident.h
new file mode 100644
index 00000000..89ea8975
--- /dev/null
+++ b/src/modules/options/optw_ident.h
@@ -0,0 +1,28 @@
+#ifndef _OPTW_IDENT_H_
+#define _OPTW_IDENT_H_
+//
+// File : optw_ident.h
+// Creation date : Mon Oct 29 15:48:40 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_optionswidget.h"
+
+
+#endif //_OPTW_IDENT_H_
diff --git a/src/modules/options/optw_identity.cpp b/src/modules/options/optw_identity.cpp
new file mode 100644
index 00000000..998ca5a4
--- /dev/null
+++ b/src/modules/options/optw_identity.cpp
@@ -0,0 +1,729 @@
+//============================================================================
+//
+// File : optw_identity.cpp
+// Creation date : Tue Nov 14 2000 23:06:53 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//============================================================================
+
+#include "optw_identity.h"
+
+#include <qlineedit.h>
+#include <qcheckbox.h>
+#include <qpushbutton.h>
+#include <qlayout.h>
+#include "kvi_tal_tooltip.h"
+#include <qtabwidget.h>
+#include <qcombobox.h>
+#include <qmessagebox.h>
+#include <qtimer.h>
+#include <qvalidator.h>
+
+#include "kvi_defaults.h"
+#include "kvi_settings.h"
+#include "kvi_options.h"
+#include "kvi_locale.h"
+#include "kvi_app.h"
+#include "kvi_window.h"
+#include "kvi_console.h"
+#include "kvi_optionswidget.h"
+#include "kvi_filedialog.h"
+#include "kvi_iconmanager.h"
+#include "kvi_http.h"
+
+
+//#warning "Info tips"
+
+
+KviNickAlternativesDialog::KviNickAlternativesDialog(QWidget * par,const QString &n1,const QString &n2,const QString &n3)
+: QDialog(par)
+{
+ QGridLayout * g = new QGridLayout(this,5,3,4,12);
+
+ setCaption(__tr2qs_ctx("Nickname alternatives","options"));
+
+ QLabel * l = new QLabel(this);
+ l->setText(__tr2qs_ctx("<center>Here you can choose up to three nicknames " \
+ "alternative to the primary one. KVIrc will use the alternatives " \
+ "if the primary nick is already used by someone else on a particular " \
+ "IRC network.</center>","options"));
+ g->addMultiCellWidget(l,0,0,0,2);
+
+ l = new QLabel(this);
+ l->setText(__tr2qs_ctx("Alt. Nickname 1:","options"));
+ g->addWidget(l,1,0);
+ m_pNickEdit1 = new QLineEdit(this);
+ g->addMultiCellWidget(m_pNickEdit1,1,1,1,2);
+ m_pNickEdit1->setText(n1);
+
+ l = new QLabel(this);
+ l->setText(__tr2qs_ctx("Alt. Nickname 2:","options"));
+ g->addWidget(l,2,0);
+ m_pNickEdit2 = new QLineEdit(this);
+ g->addMultiCellWidget(m_pNickEdit2,2,2,1,2);
+ m_pNickEdit2->setText(n2);
+
+ l = new QLabel(this);
+ l->setText(__tr2qs_ctx("Alt. Nickname 3:","options"));
+ g->addWidget(l,3,0);
+ m_pNickEdit3 = new QLineEdit(this);
+ g->addMultiCellWidget(m_pNickEdit3,3,3,1,2);
+ m_pNickEdit3->setText(n3);
+ KviTalHBox * h = new KviTalHBox(this);
+ h->setSpacing(8);
+ g->addWidget(h,4,2);
+
+ QPushButton * pb = new QPushButton(__tr2qs_ctx("Cancel","options"),h);
+ //g->addWidget(pb,4,2);
+ connect(pb,SIGNAL(clicked()),this,SLOT(reject()));
+
+ pb = new QPushButton(__tr2qs_ctx("Ok","options"),h);
+ pb->setDefault(true);
+ connect(pb,SIGNAL(clicked()),this,SLOT(accept()));
+
+ g->setColStretch(0,1);
+
+ //setMinimumSize(250,120);
+}
+
+KviNickAlternativesDialog::~KviNickAlternativesDialog()
+{
+}
+
+void KviNickAlternativesDialog::fill(QString &n1,QString &n2,QString &n3)
+{
+ n1 = m_pNickEdit1->text();
+ n2 = m_pNickEdit2->text();
+ n3 = m_pNickEdit3->text();
+}
+
+
+
+
+
+
+
+
+
+
+
+
+KviAvatarDownloadDialog::KviAvatarDownloadDialog(QWidget * par,const QString &szUrl)
+: QDialog(par)
+{
+ setCaption(__tr2qs_ctx("Avatar Download - KVIrc","options"));
+
+ m_szUrl = szUrl;
+
+ QGridLayout * g = new QGridLayout(this,2,2,4,8);
+
+ m_pOutput = new QLabel(__tr2qs_ctx("<center>Please wait while the avatar is being downloaded</center>","options"),this);
+ g->addMultiCellWidget(m_pOutput,0,0,0,1);
+
+ QPushButton * b = new QPushButton(__tr2qs_ctx("Abort","options"),this);
+ g->addWidget(b,1,1);
+ connect(b,SIGNAL(clicked()),this,SLOT(cancelClicked()));
+
+ m_pRequest = new KviHttpRequest();
+
+ QTimer::singleShot(0,this,SLOT(startDownload()));
+
+ g->setRowStretch(0,1);
+ g->setColStretch(0,1);
+
+ setMinimumSize(250,120);
+}
+
+KviAvatarDownloadDialog::~KviAvatarDownloadDialog()
+{
+ delete m_pRequest;
+}
+
+void KviAvatarDownloadDialog::startDownload()
+{
+ connect(m_pRequest,SIGNAL(terminated(bool)),this,SLOT(downloadTerminated(bool)));
+ connect(m_pRequest,SIGNAL(status(const char *)),this,SLOT(downloadMessage(const char *)));
+
+ QString tmp = m_szUrl;
+ g_pIconManager->urlToCachedFileName(tmp);
+ g_pApp->getLocalKvircDirectory(m_szLocalFileName,KviApp::Avatars,tmp);
+
+ m_pRequest->setExistingFileAction(KviHttpRequest::RenameExisting);
+ if(!m_pRequest->get(KviUrl(m_szUrl),KviHttpRequest::StoreToFile,m_szLocalFileName.utf8().data()))
+ {
+ m_szErrorMessage = __tr2qs_ctx("Failed to start the download","options");
+ reject();
+ }
+}
+
+void KviAvatarDownloadDialog::closeEvent(QCloseEvent * e)
+{
+ m_szErrorMessage = __tr2qs_ctx("Download aborted by user","options");
+ e->ignore();
+ reject();
+}
+
+void KviAvatarDownloadDialog::cancelClicked()
+{
+ m_szErrorMessage = __tr2qs_ctx("Download aborted by user","options");
+ reject();
+}
+
+void KviAvatarDownloadDialog::downloadMessage(const char * message)
+{
+ if(message)
+ {
+ QString txt = "<center>";
+ txt += message;
+ txt += "</center>";
+ m_pOutput->setText(message);
+ }
+}
+
+void KviAvatarDownloadDialog::downloadTerminated(bool bSuccess)
+{
+ if(bSuccess)
+ {
+ accept();
+ } else {
+ m_szErrorMessage = m_pRequest->lastError();
+ reject();
+ }
+}
+
+KviAvatarSelectionDialog::KviAvatarSelectionDialog(QWidget * par,const QString &szInitialPath)
+: QDialog(par)
+{
+ setCaption(__tr2qs_ctx("Choose Avatar - KVIrc","options"));
+
+ QGridLayout * g = new QGridLayout(this,3,3,4,8);
+
+
+ QString msg = "<center>";
+ msg += __tr2qs_ctx("Please select an avatar image. " \
+ "The full path to a local file or an image on the Web can be used.<br>" \
+ "If you wish to use a local image file, click the \"<b>Browse</b>\"" \
+ "button to browse local folders.<br>" \
+ "The full URL for an image (including <b>http://</b>) can be entered manually.","options");
+ msg += "</center><br>";
+
+ QLabel * l = new QLabel(msg,this);
+ l->setMinimumWidth(250);
+
+ g->addMultiCellWidget(l,0,0,0,2);
+
+ m_pLineEdit = new QLineEdit(this);
+ m_pLineEdit->setText(szInitialPath);
+ m_pLineEdit->setMinimumWidth(180);
+
+ g->addMultiCellWidget(m_pLineEdit,1,1,0,1);
+
+ QPushButton * b = new QPushButton(__tr2qs_ctx("&Browse...","options"),this);
+ connect(b,SIGNAL(clicked()),this,SLOT(chooseFileClicked()));
+ g->addWidget(b,1,2);
+ KviTalHBox * h = new KviTalHBox(this);h->setSpacing(8);g->addMultiCellWidget(h,2,2,1,2);
+ b = new QPushButton(__tr2qs_ctx("&OK","options"),h);
+ b->setMinimumWidth(80);
+ b->setDefault(true);
+ connect(b,SIGNAL(clicked()),this,SLOT(okClicked()));
+ //g->addWidget(b,2,1);
+
+ b = new QPushButton(__tr2qs_ctx("Cancel","options"),h);
+ b->setMinimumWidth(80);
+ connect(b,SIGNAL(clicked()),this,SLOT(cancelClicked()));
+ //g->addWidget(b,2,2);
+
+ g->setRowStretch(0,1);
+ g->setColStretch(0,1);
+ //setMinimumSize(250,120);
+}
+
+KviAvatarSelectionDialog::~KviAvatarSelectionDialog()
+{
+}
+
+void KviAvatarSelectionDialog::okClicked()
+{
+ m_szAvatarName = m_pLineEdit->text();
+ accept();
+}
+
+void KviAvatarSelectionDialog::cancelClicked()
+{
+ reject();
+}
+
+void KviAvatarSelectionDialog::chooseFileClicked()
+{
+ QString tmp;
+ if(KviFileDialog::askForOpenFileName(tmp,__tr2qs_ctx("Choose an Image File - KVIrc","options"),
+ QString::null,QString::null,false,true,this))
+ {
+ m_pLineEdit->setText(tmp);
+ }
+}
+
+void KviAvatarSelectionDialog::closeEvent(QCloseEvent * e)
+{
+ e->ignore();
+ reject();
+}
+
+
+
+
+
+
+KviIdentityOptionsWidget::KviIdentityOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent)
+{
+}
+
+KviIdentityOptionsWidget::~KviIdentityOptionsWidget()
+{
+}
+
+
+
+
+KviIdentityGeneralOptionsWidget::KviIdentityGeneralOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent)
+{
+ m_szAltNicknames[0] = KVI_OPTION_STRING(KviOption_stringNickname2);
+ m_szAltNicknames[1] = KVI_OPTION_STRING(KviOption_stringNickname3);
+ m_szAltNicknames[2] = KVI_OPTION_STRING(KviOption_stringNickname4);
+
+
+ createLayout(3,1);
+ layout()->setMargin(10);
+
+ KviTalGroupBox * gbox = addGroupBox(0,0,0,0,1,Qt::Horizontal,__tr2qs_ctx("Basic Properties","options"));
+ KviTalHBox * hb = new KviTalHBox(gbox);
+ hb->setSpacing(3);
+
+ KviStringSelector * sel = addStringSelector(hb,__tr2qs_ctx("Nickname:","options"),KviOption_stringNickname1);
+ sel->setMinimumLabelWidth(120);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(sel,__tr2qs_ctx("<center>Your <b>nickname</b> is your primary form of identification on IRC.<br>" \
+ "Since servers cannot accept multiple users sharing the same nickname " \
+ "(case insensitive), you can provide alternative nicknames to be used in case"\
+ "the server refuses to accept the default one.</center>","options"));
+#endif
+ QValidator * v = new QRegExpValidator(QRegExp("[^-0-9 ][^ ]*"),hb);
+ sel->setValidator(v);
+
+ QPushButton * pb = new QPushButton(__tr2qs_ctx("Alternatives...","options"),hb);
+ connect(pb,SIGNAL(clicked()),this,SLOT(setNickAlternatives()));
+
+ sel = addStringSelector(gbox,__tr2qs_ctx("Username:","options"),KviOption_stringUsername);
+ sel->setMinimumLabelWidth(120);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(sel,__tr2qs_ctx("<center>This is the <b>username</b> that you will use to connect to the server.<br>" \
+ "In the past, it was used as a form of authentication, but it normally has no special use now.<br>" \
+ "In addition to your nickname, you are identified on IRC by your <b>username@hostname</b>.</br>" \
+ "Basically, you can enter any word you like here. :D</center>","options"));
+#endif
+ sel = addStringSelector(gbox,__tr2qs_ctx("Real name:","options"),KviOption_stringRealname);
+ sel->setMinimumLabelWidth(120);
+
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(sel,__tr2qs_ctx("<center>This text will appear when someone does a /WHOIS on you.<br>" \
+ "It is intended to be your real name, but people tend to put random quotes and phrases here too.</center>","options"));
+#endif
+
+
+ QString szOptionalCtcpUserInfo = __tr2qs_ctx("This field is optional and will appear as part of the CTCP USERINFO reply.","options");
+ QString szCenterBegin("<center>");
+ QString szCenterEnd("</center>");
+ QString szTrailing = "<br><br>" + szOptionalCtcpUserInfo + szCenterEnd;
+
+ gbox = addGroupBox(0,1,0,1,1,Qt::Horizontal,__tr2qs_ctx("Profile","options"));
+
+ hb = new KviTalHBox(gbox);
+ hb->setSpacing(4);
+
+ QLabel * l = new QLabel(__tr2qs_ctx("Age:","options"),hb);
+ l->setMinimumWidth(120);
+
+ m_pAgeCombo = new QComboBox(hb);
+#ifdef COMPILE_INFO_TIPS
+ QString szTip1 = szCenterBegin + __tr2qs_ctx("Here you can specify your age.","options") + szTrailing;
+ KviTalToolTip::add(l,szTip1);
+ KviTalToolTip::add(m_pAgeCombo,szTip1);
+#endif
+ m_pAgeCombo->insertItem(__tr2qs_ctx("Unspecified","options"));
+ unsigned int i;
+ for(i=1;i<120;i++)
+ {
+ QString tmp;
+ tmp.setNum(i);
+ m_pAgeCombo->insertItem(tmp);
+ }
+
+ bool bOk;
+ i = KVI_OPTION_STRING(KviOption_stringCtcpUserInfoAge).toUInt(&bOk);
+ if(!bOk)i = 0;
+ if(i > 120)i = 120;
+ m_pAgeCombo->setCurrentItem(i);
+
+ hb->setStretchFactor(m_pAgeCombo,1);
+
+
+ hb = new KviTalHBox(gbox);
+ hb->setSpacing(4);
+
+ l = new QLabel(__tr2qs_ctx("Gender:","options"),hb);
+ l->setMinimumWidth(120);
+
+ m_pGenderCombo = new QComboBox(hb);
+#ifdef COMPILE_INFO_TIPS
+ QString szTip2 = szCenterBegin + __tr2qs_ctx("Here you can specify your gender.","options") + szTrailing;
+ KviTalToolTip::add(l,szTip2);
+ KviTalToolTip::add(m_pGenderCombo,szTip2);
+#endif
+
+ m_pGenderCombo->insertItem(__tr2qs_ctx("Unspecified","options"));
+ m_pGenderCombo->insertItem(__tr2qs_ctx("Female","options"));
+ m_pGenderCombo->insertItem(__tr2qs_ctx("Male","options"));
+
+ if(KviQString::equalCI(KVI_OPTION_STRING(KviOption_stringCtcpUserInfoGender),"Male"))
+ m_pGenderCombo->setCurrentItem(2);
+ else if(KviQString::equalCI(KVI_OPTION_STRING(KviOption_stringCtcpUserInfoGender),"Female"))
+ m_pGenderCombo->setCurrentItem(1);
+ else
+ m_pGenderCombo->setCurrentItem(0);
+
+ hb->setStretchFactor(m_pGenderCombo,1);
+
+ sel = addStringSelector(gbox,__tr2qs_ctx("Location:","options"),KviOption_stringCtcpUserInfoLocation);
+ sel->setMinimumLabelWidth(120);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(sel,szCenterBegin + __tr2qs_ctx("You can describe here your approximate physical location. " \
+ "Something like \"Region, Country\" will be ok. Please note that this information will be viewable " \
+ "by anyone so putting more data (like the exact address), generally, <b>is not a good idea</b>.","options") + szTrailing);
+#endif
+
+ sel = addStringSelector(gbox,__tr2qs_ctx("Languages:","options"),KviOption_stringCtcpUserInfoLanguages);
+ sel->setMinimumLabelWidth(120);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(sel,szCenterBegin + __tr2qs_ctx("You can put here the short names of the languages you can speak. " \
+ "An example might be \"EN,IT\" that would mean that you speak both Italian and English.","options") + szTrailing);
+#endif
+
+ sel = addStringSelector(gbox,__tr2qs_ctx("Other:","options"),KviOption_stringCtcpUserInfoOther);
+ sel->setMinimumLabelWidth(120);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(sel,szCenterBegin + __tr2qs_ctx("You can put here some additional personal data. " \
+ "It might be a funny quote or your homepage url... " \
+ "Please note that this information will be viewable " \
+ "by anyone so <b>don't put any sensible data</b> (passwords, telephone or credit card numbers).","options") + szTrailing);
+#endif
+
+ addRowSpacer(0,2,0,2);
+}
+
+KviIdentityGeneralOptionsWidget::~KviIdentityGeneralOptionsWidget()
+{
+}
+
+void KviIdentityGeneralOptionsWidget::setNickAlternatives()
+{
+ KviNickAlternativesDialog * dlg = new KviNickAlternativesDialog(this,m_szAltNicknames[0],m_szAltNicknames[1],m_szAltNicknames[2]);
+ if(dlg->exec() != QDialog::Accepted)return;
+ dlg->fill(m_szAltNicknames[0],m_szAltNicknames[1],m_szAltNicknames[2]);
+ delete dlg;
+}
+
+
+void KviIdentityGeneralOptionsWidget::commit()
+{
+ KviOptionsWidget::commit();
+
+ if(KVI_OPTION_STRING(KviOption_stringRealname).isEmpty()) KVI_OPTION_STRING(KviOption_stringUsername)=KVI_DEFAULT_REALNAME;
+ if(KVI_OPTION_STRING(KviOption_stringUsername).isEmpty()) KVI_OPTION_STRING(KviOption_stringUsername)=KVI_DEFAULT_USERNAME;
+
+ KVI_OPTION_STRING(KviOption_stringNickname2) = m_szAltNicknames[0];
+ KVI_OPTION_STRING(KviOption_stringNickname3) = m_szAltNicknames[1];
+ KVI_OPTION_STRING(KviOption_stringNickname4) = m_szAltNicknames[2];
+
+
+ int i = m_pAgeCombo->currentItem();
+ if(i < 0)i = 0;
+ if(i > 120)i = 120;
+ if(i <= 0)KVI_OPTION_STRING(KviOption_stringCtcpUserInfoAge) = "";
+ else KVI_OPTION_STRING(KviOption_stringCtcpUserInfoAge).setNum(i);
+
+ switch(m_pGenderCombo->currentItem())
+ {
+ case 1:
+ // this should be in english
+ KVI_OPTION_STRING(KviOption_stringCtcpUserInfoGender) = "Female";
+ break;
+ case 2:
+ // this should be in english
+ KVI_OPTION_STRING(KviOption_stringCtcpUserInfoGender) = "Male";
+ break;
+ default:
+ KVI_OPTION_STRING(KviOption_stringCtcpUserInfoGender) = "";
+ break;
+ }
+
+
+}
+
+
+KviIdentityAvatarOptionsWidget::KviIdentityAvatarOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent)
+{
+ createLayout(4,1);
+ layout()->setMargin(10);
+
+ m_pLocalAvatar = new KviPixmap(KVI_OPTION_PIXMAP(KviOption_pixmapMyAvatar));
+
+ bool bHaveAvatar = (!KVI_OPTION_STRING(KviOption_stringMyAvatar).isEmpty()) && m_pLocalAvatar->pixmap();
+
+#ifdef COMPILE_INFO_TIPS
+ QString szTip = __tr2qs_ctx("Here you can choose your avatar image. It will be visible<br>" \
+ "by other people that request it. Choose a nice image of yourself,<br>" \
+ "possibly avoiding obscenity and offending images. It is a good idea<br>" \
+ "to choose a relatively small file (say 150 Kb max) because<br>" \
+ "most clients have a limit on the size of avatars being downloaded.<br>" \
+ "The image also should be smaller than 800x600 pixels since<br>" \
+ "it will have to be viewable in everyone's monitor.","options");
+#endif
+
+ m_pUseAvatarCheck = new KviStyledCheckBox(__tr2qs_ctx("Use avatar","options"),this);
+ addWidgetToLayout(m_pUseAvatarCheck,0,0,0,0);
+ m_pUseAvatarCheck->setChecked(bHaveAvatar);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(m_pUseAvatarCheck,szTip);
+#endif
+
+ m_pAvatarPreview = new KviPixmapPreview(this);
+ addWidgetToLayout(m_pAvatarPreview,0,1,0,1);
+ m_pAvatarPreview->setPixmap(m_pLocalAvatar);
+ m_pAvatarPreview->setEnabled(bHaveAvatar);
+ connect(m_pUseAvatarCheck,SIGNAL(toggled(bool)),m_pAvatarPreview,SLOT(setEnabled(bool)));
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(m_pAvatarPreview,szTip);
+#endif
+
+ KviTalHBox * hb = new KviTalHBox(this);
+ hb->setSpacing(4);
+ addWidgetToLayout(hb,0,2,0,2);
+
+ m_pAvatarNameEdit = new QLineEdit(hb);
+ m_pAvatarNameEdit->setReadOnly(true);
+ m_pAvatarNameEdit->setEnabled(bHaveAvatar);
+ m_pAvatarNameEdit->setText(KVI_OPTION_STRING(KviOption_stringMyAvatar));
+ connect(m_pUseAvatarCheck,SIGNAL(toggled(bool)),m_pAvatarNameEdit,SLOT(setEnabled(bool)));
+
+ m_pChooseAvatarButton = new QPushButton(__tr2qs_ctx("Choose...","options"),hb);
+ m_pChooseAvatarButton->setEnabled(bHaveAvatar);
+ connect(m_pUseAvatarCheck,SIGNAL(toggled(bool)),m_pChooseAvatarButton,SLOT(setEnabled(bool)));
+
+ connect(m_pChooseAvatarButton,SIGNAL(clicked()),this,SLOT(chooseAvatar()));
+
+ layout()->setRowStretch(1,2);
+}
+
+KviIdentityAvatarOptionsWidget::~KviIdentityAvatarOptionsWidget()
+{
+ delete m_pLocalAvatar;
+}
+
+
+void KviIdentityAvatarOptionsWidget::commit(void)
+{
+ KviOptionsWidget::commit();
+
+ QString szAvatarName = m_pAvatarNameEdit->text();
+
+ if(m_pUseAvatarCheck->isChecked() && m_pLocalAvatar->pixmap() && (!szAvatarName.isEmpty()))
+ {
+ KVI_OPTION_STRING(KviOption_stringMyAvatar) = szAvatarName;
+ KVI_OPTION_PIXMAP(KviOption_pixmapMyAvatar) = *m_pLocalAvatar;
+ g_pApp->setAvatarFromOptions();
+ } else {
+ KVI_OPTION_STRING(KviOption_stringMyAvatar) = "";
+ KVI_OPTION_PIXMAP(KviOption_pixmapMyAvatar) = KviPixmap();
+ }
+
+}
+
+
+void KviIdentityAvatarOptionsWidget::chooseAvatar()
+{
+ QString szCurrent = m_pAvatarNameEdit->text();
+
+ KviAvatarSelectionDialog dlg(this,szCurrent);
+ if(dlg.exec() != QDialog::Accepted)return;
+
+ szCurrent = dlg.avatarName();
+ szCurrent.stripWhiteSpace();
+
+ if(KviQString::equalCIN(szCurrent,"http://",7))
+ {
+ // this is an url
+ // first check if we have it in the cache
+ KviAvatar * a = g_pIconManager->getAvatar(QString::null,szCurrent);
+ if(!a)
+ {
+ // no cache... try downloading
+ KviAvatarDownloadDialog dlg(this,szCurrent);
+ if(dlg.exec() == QDialog::Accepted)
+ {
+ // downloaded!
+ // try to load it
+ if(!m_pLocalAvatar->load(dlg.localFileName()))
+ {
+ // unloadable
+ szCurrent = "";
+ QMessageBox::warning(this,__tr2qs_ctx("Failed to Load Avatar - KVIrc","options"),
+ __tr2qs_ctx("Failed to load the avatar image.<br>" \
+ "It may be an unaccessible file or an " \
+ "unsupported image format.","options"),QMessageBox::Ok,QMessageBox::NoButton);
+ } // else loaded!
+ } else {
+ // unloadable
+ QString tmp;
+ KviQString::sprintf(tmp,__tr2qs_ctx("Failed to download the avatar image.<br>" \
+ "<b>%Q</b>","options"),&(dlg.errorMessage()));
+ QMessageBox::warning(this,__tr2qs_ctx("Avatar Download Failed - KVIrc","options"),tmp,QMessageBox::Ok,QMessageBox::NoButton);
+ szCurrent = "";
+ m_pLocalAvatar->setNull();
+ }
+ } else {
+ // else OK.. got it in the cache
+ m_pLocalAvatar->set(*(a->pixmap()),a->localPath());
+ delete a;
+ }
+ } else {
+ // this is a local path
+ if(m_pLocalAvatar->load(szCurrent))
+ {
+ // local path, loaded
+ QString tmp = szCurrent;
+ int idx = tmp.findRev("/");
+ if(idx != -1)
+ {
+ szCurrent = tmp.right(tmp.length() - (idx + 1));
+ tmp = szCurrent;
+ }
+ idx = tmp.findRev("\\");
+ if(idx != -1)
+ {
+ szCurrent = tmp.right(tmp.length() - (idx + 1));
+ tmp = szCurrent;
+ }
+ } else {
+ // unloadable
+ QMessageBox::warning(this,__tr2qs_ctx("Failed to Load Avatar - KVIrc","options"),
+ __tr2qs_ctx("Failed to load the avatar image.<br>" \
+ "It may be an unaccessible file or an " \
+ "unsupported image format.","options"),QMessageBox::Ok,QMessageBox::NoButton);
+ szCurrent = "";
+ }
+ }
+
+ if(m_pLocalAvatar->pixmap())
+ {
+ if((m_pLocalAvatar->pixmap()->width() > 1024) || (m_pLocalAvatar->pixmap()->height() > 768))
+ {
+ QMessageBox::warning(this,__tr2qs_ctx("Avatar Might Be Too Big - KVIrc","options"),
+ __tr2qs_ctx("The avatar you have choosen is bigger than 1024x768 pixels.<br>" \
+ "Such a big image will not be seen on all the user monitors<br>" \
+ "and will probably be scaled by the remote clients with poor quality<br>" \
+ "algorithms to improve performance. You *should* scale it manually<br>" \
+ "to a sane size (like 800x600) or choose a different image.","options"));
+ }
+ }
+
+ m_pAvatarNameEdit->setText(szCurrent);
+ m_pAvatarPreview->setPixmap(m_pLocalAvatar);
+}
+
+
+
+
+
+
+KviIdentityAdvancedOptionsWidget::KviIdentityAdvancedOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent)
+{
+ m_pISelector=0;
+ m_pWSelector=0;
+ m_pSSelector=0;
+
+ m_sModeStr = KVI_OPTION_STRING(KviOption_stringDefaultUserMode);
+ m_bI = m_sModeStr.contains('i');
+ m_bW = m_sModeStr.contains('w');
+ m_bS = m_sModeStr.contains('s');
+
+
+ createLayout(2,1);
+ layout()->setMargin(10);
+
+ KviTalGroupBox * gbox = addGroupBox(0,0,0,0,1,Qt::Horizontal,__tr2qs_ctx("User Mode","options"));
+ m_pISelector = addBoolSelector(gbox,__tr2qs_ctx("Invisible (+i)","options"),&m_bI);
+ m_pSSelector = addBoolSelector(gbox,__tr2qs_ctx("Server notices (+s)","options"),&m_bS);
+ m_pWSelector = addBoolSelector(gbox,__tr2qs_ctx("Wallops (+w)","options"),&m_bW);
+
+ gbox = addGroupBox(0,1,0,1,1,Qt::Horizontal,__tr2qs_ctx("Default Messages","options"));
+
+
+ KviStringSelector * sel = addStringSelector(gbox, __tr2qs_ctx("Part message:","options"),KviOption_stringPartMessage);
+ sel->setMinimumLabelWidth(120);
+
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(sel,__tr2qs_ctx("<center>This is the default part message that will be used when you<br>" \
+ "leave a channel by closing a channel window.</center>","options"));
+#endif
+
+ sel = addStringSelector(gbox, __tr2qs_ctx("Quit message:","options"),KviOption_stringQuitMessage);
+ sel->setMinimumLabelWidth(120);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(sel,__tr2qs_ctx("<center>This is the default quit message that will be used when you<br>" \
+ "quit your IRC session by closing the console window or disconnecting by pressing the disconnect button.</center>","options"));
+#endif
+
+ addRowSpacer(0,2,0,2);
+}
+
+KviIdentityAdvancedOptionsWidget::~KviIdentityAdvancedOptionsWidget()
+{
+}
+
+void KviIdentityAdvancedOptionsWidget::commit()
+{
+ KviOptionsWidget::commit();
+
+ m_sModeStr = m_bI ? "i" : "";
+ if(m_bS)m_sModeStr += "s";
+ if(m_bW)m_sModeStr += "w";
+
+ KVI_OPTION_STRING(KviOption_stringDefaultUserMode) = m_sModeStr.ptr();
+}
+
+
+
+
+
+
+#include "m_optw_identity.moc"
diff --git a/src/modules/options/optw_identity.h b/src/modules/options/optw_identity.h
new file mode 100644
index 00000000..479614c4
--- /dev/null
+++ b/src/modules/options/optw_identity.h
@@ -0,0 +1,192 @@
+#ifndef _OPTW_IDENTITY_H_
+#define _OPTW_IDENTITY_H_
+
+//=============================================================================
+//
+// File : optw_identity.h
+// Creation date : Tue Nov 14 2000 23:06:12 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+
+#include "kvi_optionswidget.h"
+#include "kvi_settings.h"
+#include "kvi_selectors.h"
+
+#include <qdialog.h>
+#include "kvi_pixmap.h"
+
+
+class QLineEdit;
+class QCheckBox;
+class QPushButton;
+class QComboBox;
+
+class KviNickAlternativesDialog : public QDialog
+{
+ friend class KviIdentityGeneralOptionsWidget;
+ Q_OBJECT
+protected:
+ KviNickAlternativesDialog(QWidget * par,const QString &n1,const QString &n2,const QString &n3);
+ ~KviNickAlternativesDialog();
+protected:
+ QLineEdit * m_pNickEdit1;
+ QLineEdit * m_pNickEdit2;
+ QLineEdit * m_pNickEdit3;
+protected:
+ void fill(QString &n1,QString &n2,QString &n3);
+};
+
+class KviAvatarSelectionDialog : public QDialog
+{
+ friend class KviIdentityAvatarOptionsWidget;
+ Q_OBJECT
+public:
+ KviAvatarSelectionDialog(QWidget * par,const QString &szInitialPath);
+ ~KviAvatarSelectionDialog();
+protected:
+ QLineEdit * m_pLineEdit;
+ QString m_szAvatarName;
+protected:
+ virtual void closeEvent(QCloseEvent * e);
+ const QString &avatarName(){ return m_szAvatarName; };
+protected slots:
+ void okClicked();
+ void cancelClicked();
+ void chooseFileClicked();
+};
+
+class KviHttpRequest;
+
+class KviAvatarDownloadDialog : public QDialog
+{
+ friend class KviIdentityAvatarOptionsWidget;
+ Q_OBJECT
+public:
+ KviAvatarDownloadDialog(QWidget * par,const QString &szUrl);
+ ~KviAvatarDownloadDialog();
+protected:
+ KviHttpRequest * m_pRequest;
+ QLabel * m_pOutput;
+ QString m_szErrorMessage;
+ QString m_szLocalFileName;
+ QString m_szUrl;
+protected:
+ virtual void closeEvent(QCloseEvent * e);
+ const QString & localFileName(){ return m_szLocalFileName; };
+ const QString & errorMessage(){ return m_szErrorMessage; };
+protected slots:
+ void startDownload();
+ void cancelClicked();
+ void downloadTerminated(bool bSuccess);
+ void downloadMessage(const char * msg);
+};
+
+
+#define KVI_OPTIONS_WIDGET_ICON_KviIdentityOptionsWidget KVI_SMALLICON_WHO
+#define KVI_OPTIONS_WIDGET_NAME_KviIdentityOptionsWidget __tr2qs_no_lookup("Identity")
+#define KVI_OPTIONS_WIDGET_PRIORITY_KviIdentityOptionsWidget 99998
+#define KVI_OPTIONS_WIDGET_CONTAINER_KviIdentityOptionsWidget true
+
+
+class KviIdentityOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviIdentityOptionsWidget(QWidget * parent);
+ ~KviIdentityOptionsWidget();
+};
+
+
+
+#define KVI_OPTIONS_WIDGET_ICON_KviIdentityGeneralOptionsWidget KVI_SMALLICON_WHO
+#define KVI_OPTIONS_WIDGET_NAME_KviIdentityGeneralOptionsWidget __tr2qs_no_lookup("General")
+#define KVI_OPTIONS_WIDGET_PRIORITY_KviIdentityGeneralOptionsWidget 90000
+#define KVI_OPTIONS_WIDGET_PARENT_KviIdentityGeneralOptionsWidget KviIdentityOptionsWidget
+
+
+class KviIdentityGeneralOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviIdentityGeneralOptionsWidget(QWidget * pParent);
+ ~KviIdentityGeneralOptionsWidget();
+protected:
+ QString m_szAltNicknames[3];
+
+ QComboBox * m_pAgeCombo;
+ QComboBox * m_pGenderCombo;
+protected slots:
+ void setNickAlternatives();
+protected:
+ virtual void commit(void);
+};
+
+
+#define KVI_OPTIONS_WIDGET_ICON_KviIdentityAvatarOptionsWidget KVI_SMALLICON_AVATAR
+#define KVI_OPTIONS_WIDGET_NAME_KviIdentityAvatarOptionsWidget __tr2qs_no_lookup("Avatar")
+#define KVI_OPTIONS_WIDGET_PRIORITY_KviIdentityAvatarOptionsWidget 80000
+#define KVI_OPTIONS_WIDGET_PARENT_KviIdentityAvatarOptionsWidget KviIdentityOptionsWidget
+
+
+class KviIdentityAvatarOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviIdentityAvatarOptionsWidget(QWidget * pParent);
+ ~KviIdentityAvatarOptionsWidget();
+protected:
+ QCheckBox * m_pUseAvatarCheck;
+ QLineEdit * m_pAvatarNameEdit;
+ QPushButton * m_pChooseAvatarButton;
+ KviPixmap * m_pLocalAvatar;
+ KviPixmapPreview * m_pAvatarPreview;
+protected slots:
+ void chooseAvatar();
+protected:
+ virtual void commit(void);
+};
+
+
+#define KVI_OPTIONS_WIDGET_ICON_KviIdentityAdvancedOptionsWidget KVI_SMALLICON_SPY
+#define KVI_OPTIONS_WIDGET_NAME_KviIdentityAdvancedOptionsWidget __tr2qs_no_lookup("Advanced")
+#define KVI_OPTIONS_WIDGET_PRIORITY_KviIdentityAdvancedOptionsWidget 70000
+#define KVI_OPTIONS_WIDGET_PARENT_KviIdentityAdvancedOptionsWidget KviIdentityOptionsWidget
+
+
+class KviIdentityAdvancedOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviIdentityAdvancedOptionsWidget(QWidget * pParent);
+ ~KviIdentityAdvancedOptionsWidget();
+protected:
+ bool m_bI;
+ bool m_bW;
+ bool m_bS;
+ KviStr m_sModeStr;
+ KviBoolSelector * m_pISelector;
+ KviBoolSelector * m_pWSelector;
+ KviBoolSelector * m_pSSelector;
+protected:
+ virtual void commit(void);
+};
+
+#endif //!_OPTW_IDENTITY_H_
diff --git a/src/modules/options/optw_ignore.cpp b/src/modules/options/optw_ignore.cpp
new file mode 100644
index 00000000..26e4c0d9
--- /dev/null
+++ b/src/modules/options/optw_ignore.cpp
@@ -0,0 +1,62 @@
+//
+// File : optw_ignore.h
+// Creation date : Thu Feb 12 15:11:29 2002 GMT by Juanjo lvarez
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "optw_ignore.h"
+
+#include <qlayout.h>
+
+#include "kvi_options.h"
+#include "kvi_locale.h"
+
+//#warning "Info tips"
+
+
+KviIgnoreOptionsWidget::KviIgnoreOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"ignore_options_widget")
+{
+ createLayout(3,1);
+
+ KviTalGroupBox *g = addGroupBox(0,0,0,0,1,Qt::Horizontal,__tr2qs_ctx("Enable Ignore For","options"));
+ m_pIgnorePrivmsg = addBoolSelector(g,__tr2qs_ctx("Private/channel messages","options"),KviOption_boolEnableIgnoreOnPrivMsg);
+ m_pIgnoreNotice = addBoolSelector(g,__tr2qs_ctx("Private/channel notices","options"),KviOption_boolEnableIgnoreOnNotice);
+
+ connect(m_pIgnorePrivmsg,SIGNAL(toggled(bool)),this,SLOT(enableVerbose(bool)));
+
+ m_pVerboseIgnore = addBoolSelector(0,1,0,1,__tr2qs_ctx("Use verbose ignore (show messages in console)","options"),
+ KviOption_boolVerboseIgnore,
+ KVI_OPTION_BOOL(KviOption_boolEnableIgnoreOnPrivMsg) || KVI_OPTION_BOOL(KviOption_boolEnableIgnoreOnNotice));
+
+ addRowSpacer(0,2,0,2);
+}
+
+KviIgnoreOptionsWidget::~KviIgnoreOptionsWidget()
+{
+}
+
+void KviIgnoreOptionsWidget::enableVerbose(bool)
+{
+ m_pVerboseIgnore->setEnabled(m_pIgnorePrivmsg->isChecked() || m_pIgnoreNotice->isChecked());
+}
+
+
+
+#include "m_optw_ignore.moc"
diff --git a/src/modules/options/optw_ignore.h b/src/modules/options/optw_ignore.h
new file mode 100644
index 00000000..cb7203f5
--- /dev/null
+++ b/src/modules/options/optw_ignore.h
@@ -0,0 +1,47 @@
+#ifndef _OPTW_IGNORE_H_
+#define _OPTW_IGNORE_H_
+//
+// File : optw_ignore.h
+// Creation date : Thu Feb 12 15:11:30 2002 GMT by Juanjo lvarez
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_optionswidget.h"
+#include "kvi_selectors.h"
+
+#define KVI_OPTIONS_WIDGET_ICON_KviIgnoreOptionsWidget KVI_SMALLICON_IGNORE
+#define KVI_OPTIONS_WIDGET_NAME_KviIgnoreOptionsWidget __tr2qs_no_lookup("Ignore")
+#define KVI_OPTIONS_WIDGET_PARENT_KviIgnoreOptionsWidget KviProtectionOptionsWidget
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviIgnoreOptionsWidget __tr2qs_no_lookup("protection")
+
+class KviIgnoreOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviIgnoreOptionsWidget(QWidget * parent);
+ ~KviIgnoreOptionsWidget();
+public:
+ KviBoolSelector * m_pIgnorePrivmsg;
+ KviBoolSelector * m_pIgnoreNotice;
+ KviBoolSelector * m_pVerboseIgnore;
+protected slots:
+ void enableVerbose(bool);
+};
+
+#endif //_OPTW_IGNORE_H_
diff --git a/src/modules/options/optw_input.cpp b/src/modules/options/optw_input.cpp
new file mode 100644
index 00000000..4dd73987
--- /dev/null
+++ b/src/modules/options/optw_input.cpp
@@ -0,0 +1,156 @@
+//
+// File : optw_input.cpp
+// Creation date : Sat Aug 11 2001 04:25:52 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+#include "optw_input.h"
+
+#include <qlayout.h>
+
+#include "kvi_options.h"
+#include "kvi_locale.h"
+
+//#warning "Info tips"
+
+KviInputLookOptionsWidget::KviInputLookOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"ircviewlook_options_widget")
+{
+ createLayout(10,2);
+
+ addFontSelector(0,0,1,0,__tr2qs_ctx("Font","options"),KviOption_fontInput);
+ addColorSelector(0,1,1,1,__tr2qs_ctx("Background color","options"),KviOption_colorInputBackground);
+ addColorSelector(0,2,1,2,__tr2qs_ctx("Foreground color","options"),KviOption_colorInputForeground);
+ addColorSelector(0,3,1,3,__tr2qs_ctx("Selection background color","options"),KviOption_colorInputSelectionBackground);
+ addColorSelector(0,4,1,4,__tr2qs_ctx("Selection foreground color","options"),KviOption_colorInputSelectionForeground);
+ addColorSelector(0,5,1,5,__tr2qs_ctx("Control char color","options"),KviOption_colorInputControl);
+ addColorSelector(0,6,1,6,__tr2qs_ctx("Cursor color","options"),KviOption_colorInputCursor);
+
+ addPixmapSelector(0,7,1,7,__tr2qs_ctx("Background image","options"),KviOption_pixmapInputBackground);
+
+ addLabel(0,8,0,8,__tr2qs_ctx("Horizontal align:","options"));
+ m_pHorizontalAlign=new QComboBox(this);
+ addWidgetToLayout(m_pHorizontalAlign,1,8,1,8);
+
+ addLabel(0,9,0,9,__tr2qs_ctx("Vertical align:","options"));
+ m_pVerticalAlign=new QComboBox(this);
+ addWidgetToLayout(m_pVerticalAlign,1,9,1,9);
+
+ m_pHorizontalAlign->insertItem(__tr2qs_ctx("Tile","options"));
+ m_pHorizontalAlign->insertItem(__tr2qs_ctx("Left","options"));
+ m_pHorizontalAlign->insertItem(__tr2qs_ctx("Right","options"));
+ m_pHorizontalAlign->insertItem(__tr2qs_ctx("Center","options"));
+
+ m_pVerticalAlign->insertItem(__tr2qs_ctx("Tile","options"));
+ m_pVerticalAlign->insertItem(__tr2qs_ctx("Top","options"));
+ m_pVerticalAlign->insertItem(__tr2qs_ctx("Bottom","options"));
+ m_pVerticalAlign->insertItem(__tr2qs_ctx("Center","options"));
+
+ switch( KVI_OPTION_UINT(KviOption_uintInputPixmapAlign) & Qt::AlignHorizontal_Mask)
+ {
+ case Qt::AlignLeft:
+ m_pHorizontalAlign->setCurrentItem(1);
+ break;
+ case Qt::AlignRight:
+ m_pHorizontalAlign->setCurrentItem(2);
+ break;
+ case Qt::AlignHCenter:
+ m_pHorizontalAlign->setCurrentItem(3);
+ break;
+ default:
+ m_pHorizontalAlign->setCurrentItem(0);
+ }
+
+ switch( KVI_OPTION_UINT(KviOption_uintInputPixmapAlign) & Qt::AlignVertical_Mask)
+ {
+ case Qt::AlignTop:
+ m_pVerticalAlign->setCurrentItem(1);
+ break;
+ case Qt::AlignBottom:
+ m_pVerticalAlign->setCurrentItem(2);
+ break;
+ case Qt::AlignVCenter:
+ m_pVerticalAlign->setCurrentItem(3);
+ break;
+ default:
+ m_pVerticalAlign->setCurrentItem(0);
+ }
+
+
+ layout()->setRowStretch(7,1);
+}
+
+KviInputLookOptionsWidget::~KviInputLookOptionsWidget()
+{
+}
+
+void KviInputLookOptionsWidget::commit()
+{
+ int iFlags=0;
+ switch(m_pHorizontalAlign->currentItem())
+ {
+ case 1:
+ iFlags|=Qt::AlignLeft;
+ break;
+ case 2:
+ iFlags|=Qt::AlignRight;
+ break;
+ case 3:
+ iFlags|=Qt::AlignHCenter;
+ break;
+ }
+ switch(m_pVerticalAlign->currentItem())
+ {
+ case 1:
+ iFlags|=Qt::AlignTop;
+ break;
+ case 2:
+ iFlags|=Qt::AlignBottom;
+ break;
+ case 3:
+ iFlags|=Qt::AlignVCenter;
+ break;
+ }
+
+ KVI_OPTION_UINT(KviOption_uintInputPixmapAlign)=iFlags;
+ KviOptionsWidget::commit();
+}
+
+
+
+KviInputFeaturesOptionsWidget::KviInputFeaturesOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"ircviewfeatures_options_widget")
+{
+ createLayout(6,1);
+
+ addBoolSelector(0,0,0,0,__tr2qs_ctx("Warp cursor at the end of line when browsing history","options"),KviOption_boolInputHistoryCursorAtEnd);
+ addBoolSelector(0,1,0,1,__tr2qs_ctx("Disable the input history window and it's log memory.","options"),KviOption_boolDisableInputHistory); //G&N 2005
+ addBoolSelector(0,2,0,2,__tr2qs_ctx("Hide input toolbuttons by default","options"),KviOption_boolHideInputToolButtons);
+ KviTalGroupBox * g = addGroupBox(0,3,0,3,1,Qt::Horizontal,__tr2qs_ctx("Nick completion","options"));
+ addBoolSelector(g,__tr2qs_ctx("Use bash-like nick completion","options"),KviOption_boolBashLikeNickCompletion);
+ addStringSelector(g,__tr2qs_ctx("Nick completion postfix string","options"),KviOption_stringNickCompletionPostfix);
+ addBoolSelector(g,__tr2qs_ctx("Use the completion postfix string for the first word only","options"),KviOption_boolUseNickCompletionPostfixForFirstWordOnly);
+ addBoolSelector(0,4,0,4,__tr2qs_ctx("Commandline in user-friendly mode by default","options"),KviOption_boolCommandlineInUserFriendlyModeByDefault);
+ addRowSpacer(0,5,0,5);
+}
+
+KviInputFeaturesOptionsWidget::~KviInputFeaturesOptionsWidget()
+{
+}
+
+#include "m_optw_input.moc"
diff --git a/src/modules/options/optw_input.h b/src/modules/options/optw_input.h
new file mode 100644
index 00000000..eb088460
--- /dev/null
+++ b/src/modules/options/optw_input.h
@@ -0,0 +1,61 @@
+#ifndef _OPTW_INPUT_H_
+#define _OPTW_INPUT_H_
+
+//==================================================================================
+//
+// File : optw_input.h
+// Creation date : Sat Aug 11 2001 04:25:01 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//==================================================================================
+
+#include "kvi_optionswidget.h"
+#include <qcombobox.h>
+
+#define KVI_OPTIONS_WIDGET_ICON_KviInputLookOptionsWidget KVI_SMALLICON_INPUT
+#define KVI_OPTIONS_WIDGET_NAME_KviInputLookOptionsWidget __tr2qs_no_lookup("Input")
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviInputLookOptionsWidget __tr2qs_no_lookup("theme,colors,text")
+#define KVI_OPTIONS_WIDGET_GROUP_KviInputLookOptionsWidget "theme"
+
+class KviInputLookOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+private:
+ QComboBox* m_pHorizontalAlign;
+ QComboBox* m_pVerticalAlign;
+public:
+ KviInputLookOptionsWidget(QWidget * parent);
+ ~KviInputLookOptionsWidget();
+
+ virtual void commit();
+};
+
+#define KVI_OPTIONS_WIDGET_ICON_KviInputFeaturesOptionsWidget KVI_SMALLICON_INPUT
+#define KVI_OPTIONS_WIDGET_NAME_KviInputFeaturesOptionsWidget __tr2qs_no_lookup("Input")
+#define KVI_OPTIONS_WIDGET_PARENT_KviInputFeaturesOptionsWidget KviInterfaceFeaturesOptionsWidget
+
+class KviInputFeaturesOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviInputFeaturesOptionsWidget(QWidget * parent);
+ ~KviInputFeaturesOptionsWidget();
+};
+
+#endif //!_OPTW_INPUT_H_
diff --git a/src/modules/options/optw_interfacefeatures.cpp b/src/modules/options/optw_interfacefeatures.cpp
new file mode 100644
index 00000000..3cae7662
--- /dev/null
+++ b/src/modules/options/optw_interfacefeatures.cpp
@@ -0,0 +1,88 @@
+//=============================================================================
+//
+// File : optw_interfacefeatures.cpp
+// Creation date : Sat Jun 2 2001 14:52:53 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "optw_interfacefeatures.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <string.h>
+
+#include "kvi_options.h"
+#include "kvi_locale.h"
+#include "kvi_app.h"
+#include "kvi_fileutils.h"
+
+KviInterfaceFeaturesOptionsWidget::KviInterfaceFeaturesOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"interfacefeatures_options_widget")
+{
+ createLayout(8,1);
+
+
+
+ addBoolSelector(0,0,0,0,__tr2qs_ctx("Minimize on startup","options"),KviOption_boolStartupMinimized);
+ addBoolSelector(0,1,0,1,__tr2qs_ctx("Confirm quit with active connections","options"),KviOption_boolConfirmCloseWhenThereAreConnections);
+ addBoolSelector(0,2,0,2,__tr2qs_ctx("Remember window properties","options"),KviOption_boolWindowsRememberProperties);
+
+ QString szSplashDisableFile;
+ g_pApp->getLocalKvircDirectory(szSplashDisableFile,KviApp::Pics,"disable-splash." KVI_VERSION);
+ bool bDisableSplash = KviFileUtils::fileExists(szSplashDisableFile);
+ m_pDisableSplash = new KviStyledCheckBox(__tr2qs_ctx("Disable splash screen","options"),this);
+ addWidgetToLayout(m_pDisableSplash,0,3,0,3);
+ m_pDisableSplash->setChecked(bDisableSplash);
+
+ addBoolSelector(0,4,0,4,__tr2qs_ctx("Enable visual effects","options"),KviOption_boolEnableVisualEffects);
+ addBoolSelector(0,5,0,5,__tr2qs_ctx("Hide Channel window tool buttons by default","options"),KviOption_boolHideWindowToolButtons);
+
+ KviTalGroupBox * g = addGroupBox(0,6,0,6,1,Qt::Horizontal,__tr2qs_ctx("Open Dialog Window For","options"));
+ addBoolSelector(g,__tr2qs_ctx("Preferences","options"),KviOption_boolShowGeneralOptionsDialogAsToplevel);
+ addBoolSelector(g,__tr2qs_ctx("Registered Users","options"),KviOption_boolShowRegisteredUsersDialogAsToplevel);
+ addBoolSelector(g,__tr2qs_ctx("Identity","options"),KviOption_boolShowIdentityDialogAsToplevel);
+ addBoolSelector(g,__tr2qs_ctx("Servers","options"),KviOption_boolShowServersConnectDialogAsToplevel);
+ addBoolSelector(g,__tr2qs_ctx("Join Channels","options"),KviOption_boolShowChannelsJoinDialogAsToplevel);
+ addRowSpacer(0,7,0,7);
+}
+
+KviInterfaceFeaturesOptionsWidget::~KviInterfaceFeaturesOptionsWidget()
+{
+}
+
+void KviInterfaceFeaturesOptionsWidget::commit()
+{
+ KviOptionsWidget::commit();
+
+ QString szSplashDisableFile;
+ g_pApp->getLocalKvircDirectory(szSplashDisableFile,KviApp::Pics,"disable-splash." KVI_VERSION);
+
+ if(m_pDisableSplash->isChecked())
+ {
+ if(!KviFileUtils::fileExists(szSplashDisableFile))
+ KviFileUtils::writeFile(szSplashDisableFile,"");
+ } else {
+ if(KviFileUtils::fileExists(szSplashDisableFile))
+ KviFileUtils::removeFile(szSplashDisableFile);
+ }
+
+}
+
+#include "m_optw_interfacefeatures.moc"
diff --git a/src/modules/options/optw_interfacefeatures.h b/src/modules/options/optw_interfacefeatures.h
new file mode 100644
index 00000000..f85dfb9e
--- /dev/null
+++ b/src/modules/options/optw_interfacefeatures.h
@@ -0,0 +1,48 @@
+#ifndef _OPTW_INTERFACEFEATURES_H_
+#define _OPTW_INTERFACEFEATURES_H_
+
+//=============================================================================
+//
+// File : optw_interfacefeatures.h
+// Creation date : Sat Jun 2 2001 14:50:01 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_optionswidget.h"
+
+#define KVI_OPTIONS_WIDGET_ICON_KviInterfaceFeaturesOptionsWidget KVI_SMALLICON_IDEA
+#define KVI_OPTIONS_WIDGET_NAME_KviInterfaceFeaturesOptionsWidget __tr2qs_no_lookup("Interface")
+#define KVI_OPTIONS_WIDGET_PRIORITY_KviInterfaceFeaturesOptionsWidget 50000
+
+class QCheckBox;
+
+class KviInterfaceFeaturesOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviInterfaceFeaturesOptionsWidget(QWidget * parent);
+ ~KviInterfaceFeaturesOptionsWidget();
+protected:
+ QCheckBox * m_pDisableSplash;
+public:
+ virtual void commit();
+};
+
+#endif //!_OPTW_INTERFACEFEATURES_H_
diff --git a/src/modules/options/optw_interfacelookglobal.cpp b/src/modules/options/optw_interfacelookglobal.cpp
new file mode 100644
index 00000000..50cf845f
--- /dev/null
+++ b/src/modules/options/optw_interfacelookglobal.cpp
@@ -0,0 +1,215 @@
+//
+// File : optw_interfacelookglobal.cpp
+// Creation date : Sun Jun 3 2001 20:50:13 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "optw_interfacelookglobal.h"
+
+#include <qlayout.h>
+
+#include "kvi_settings.h"
+#include "kvi_options.h"
+#include "kvi_locale.h"
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+KviThemeGeneralOptionsWidget::KviThemeGeneralOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent)
+{
+ createLayout(4,2);
+
+ KviBoolSelector * b = addBoolSelector(0,1,1,1,__tr2qs_ctx("Use global application font","options"),KviOption_boolUseGlobalApplicationFont);
+ KviBoolSelector * g = addBoolSelector(0,0,1,0,__tr2qs_ctx("Hide icons in Popup","options"),KviOption_boolDisablePopupIcons);
+ KviFontSelector * f = addFontSelector(0,2,1,2,__tr2qs_ctx("Global application font:","options"),KviOption_fontApplication,
+ KVI_OPTION_BOOL(KviOption_boolUseGlobalApplicationFont));
+
+ connect(b,SIGNAL(toggled(bool)),f,SLOT(setEnabled(bool)));
+
+ addRowSpacer(0,3,1,3);
+}
+
+KviThemeGeneralOptionsWidget::~KviThemeGeneralOptionsWidget()
+{
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+KviThemeTransparencyOptionsWidget::KviThemeTransparencyOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent)
+{
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+
+ #ifdef COMPILE_KDE_SUPPORT
+ createLayout(7,2);
+ #else
+ createLayout(5,2);
+ #endif
+
+ m_pUseTransparencyBoolSelector = addBoolSelector(0,0,1,0,__tr2qs_ctx("Enable fake transparency","options"),KviOption_boolUseGlobalPseudoTransparency);
+#ifdef COMPILE_INFO_TIPS
+ #ifdef COMPILE_KDE_SUPPORT
+ mergeTip(m_pUseTransparencyBoolSelector,
+ __tr2qs_ctx("<center>This option makes all KVIrc windows look " \
+ "transparent.<br>You must choose a blending " \
+ "background image to below or check the " \
+ "\"Use KDE desktop for transparency\" option.</center>","options"));
+ #else
+ mergeTip(m_pUseTransparencyBoolSelector,
+ __tr2qs_ctx("<center>This option makes all KVIrc windows look " \
+ "like transparent.<br>You must choose a blending " \
+ "background image to below.</center>","options"));
+ #endif
+#endif
+
+ KviUIntSelector * u = addUIntSelector(0,1,1,1,__tr2qs_ctx("Child window opacity:","options"),KviOption_uintGlobalTransparencyChildFadeFactor,
+ 0,100,35,KVI_OPTION_BOOL(KviOption_boolUseGlobalPseudoTransparency));
+ connect(m_pUseTransparencyBoolSelector,SIGNAL(toggled(bool)),u,SLOT(setEnabled(bool)));
+
+ u = addUIntSelector(0,2,1,2,__tr2qs_ctx("Parent window opacity:","options"),KviOption_uintGlobalTransparencyParentFadeFactor,
+ 0,100,10,KVI_OPTION_BOOL(KviOption_boolUseGlobalPseudoTransparency));
+ connect(m_pUseTransparencyBoolSelector,SIGNAL(toggled(bool)),u,SLOT(setEnabled(bool)));
+
+ KviColorSelector * c = addColorSelector(0,3,1,3,__tr2qs_ctx("Blend color:","options"),KviOption_colorGlobalTransparencyFade,
+ KVI_OPTION_BOOL(KviOption_boolUseGlobalPseudoTransparency));
+ connect(m_pUseTransparencyBoolSelector,SIGNAL(toggled(bool)),c,SLOT(setEnabled(bool)));
+
+// addRowSpacer(0,13,0,13);
+#ifdef COMPILE_KDE_SUPPORT
+ m_pObtainBackgroundFromKdeBoolSelector = addBoolSelector(0,4,1,4,__tr2qs_ctx("Use KDE desktop for transparency","options"),KviOption_boolObtainGlobalBackgroundFromKde,
+ KVI_OPTION_BOOL(KviOption_boolUseGlobalPseudoTransparency));
+ connect(m_pUseTransparencyBoolSelector,SIGNAL(toggled(bool)),m_pObtainBackgroundFromKdeBoolSelector,SLOT(setEnabled(bool)));
+ connect(m_pObtainBackgroundFromKdeBoolSelector,SIGNAL(toggled(bool)),this,SLOT(enableUpdateKdeBackgroundBoolSelector(bool)));
+
+ m_pUpdateKdeBackgroundOnChangeBoolSelector = addBoolSelector(0,5,1,5,__tr2qs_ctx("Keep in sync with KDE background changes","options"),KviOption_boolUpdateKdeBackgroundOnChange,
+ KVI_OPTION_BOOL(KviOption_boolUseGlobalPseudoTransparency) && KVI_OPTION_BOOL(KviOption_boolObtainGlobalBackgroundFromKde));
+
+ m_pGlobalBackgroundPixmapSelector = addPixmapSelector(0,6,1,6,__tr2qs_ctx("Transparency blend image:","options"),KviOption_pixmapGlobalTransparencyBackground,
+ KVI_OPTION_BOOL(KviOption_boolUseGlobalPseudoTransparency) && !KVI_OPTION_BOOL(KviOption_boolObtainGlobalBackgroundFromKde));
+ layout()->setRowStretch(6,1);
+ connect(m_pObtainBackgroundFromKdeBoolSelector,SIGNAL(toggled(bool)),this,SLOT(enableGlobalBackgroundPixmapSelector(bool)));
+
+#else //!COMPILE_KDE_SUPPORT
+ m_pGlobalBackgroundPixmapSelector = addPixmapSelector(0,4,1,4,__tr2qs_ctx("Transparency blend image:","options"),KviOption_pixmapGlobalTransparencyBackground,
+ KVI_OPTION_BOOL(KviOption_boolUseGlobalPseudoTransparency));
+ layout()->setRowStretch(4,1);
+#endif //!COMPILE_KDE_SUPPORT
+ connect(m_pUseTransparencyBoolSelector,SIGNAL(toggled(bool)),this,SLOT(enableGlobalBackgroundPixmapSelector(bool)));
+ connect(m_pUseTransparencyBoolSelector,SIGNAL(toggled(bool)),this,SLOT(enableUpdateKdeBackgroundBoolSelector(bool)));
+#else
+ createLayout(1,1);
+ addRowSpacer(0,0,0,0);
+#endif
+}
+
+KviThemeTransparencyOptionsWidget::~KviThemeTransparencyOptionsWidget()
+{
+}
+
+void KviThemeTransparencyOptionsWidget::enableGlobalBackgroundPixmapSelector(bool)
+{
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ #ifdef COMPILE_KDE_SUPPORT
+ m_pGlobalBackgroundPixmapSelector->setEnabled(m_pUseTransparencyBoolSelector->isChecked() && !(m_pObtainBackgroundFromKdeBoolSelector->isChecked()));
+ #else
+ m_pGlobalBackgroundPixmapSelector->setEnabled(m_pUseTransparencyBoolSelector->isChecked());
+ #endif
+#endif
+}
+
+void KviThemeTransparencyOptionsWidget::enableUpdateKdeBackgroundBoolSelector(bool)
+{
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ #ifdef COMPILE_KDE_SUPPORT
+ m_pUpdateKdeBackgroundOnChangeBoolSelector->setEnabled(m_pUseTransparencyBoolSelector->isChecked() && m_pObtainBackgroundFromKdeBoolSelector->isChecked());
+ #endif
+#endif
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+KviThemeMdiCaptionsOptionsWidget::KviThemeMdiCaptionsOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent)
+{
+ createLayout(7,1);
+
+ addColorSelector(0,0,0,0,__tr2qs_ctx("Active Background","options"),KviOption_colorMdiCaptionActive);
+ addColorSelector(0,1,0,1,__tr2qs_ctx("Inactive Background","options"),KviOption_colorMdiCaptionInactive);
+ addColorSelector(0,2,0,2,__tr2qs_ctx("Active Text (Primary)","options"),KviOption_colorCaptionTextActive);
+ addColorSelector(0,3,0,3,__tr2qs_ctx("Active Text (Secondary)","options"),KviOption_colorCaptionTextActive2);
+ addColorSelector(0,4,0,4,__tr2qs_ctx("Inactive Text (Primary)","options"),KviOption_colorCaptionTextInactive);
+ addColorSelector(0,5,0,5,__tr2qs_ctx("Inactive Text (Secondary)","options"),KviOption_colorCaptionTextInactive2);
+
+ addRowSpacer(0,6,0,6);
+}
+
+KviThemeMdiCaptionsOptionsWidget::~KviThemeMdiCaptionsOptionsWidget()
+{
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+KviThemeMdiAreaOptionsWidget::KviThemeMdiAreaOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent)
+{
+ createLayout(2,1);
+
+ addColorSelector(0,0,0,0,__tr2qs_ctx("Background","options"),KviOption_colorMdiBackground);
+ addPixmapSelector(0,1,0,1,__tr2qs_ctx("Background Image","options"),KviOption_pixmapMdiBackground);
+
+ layout()->setRowStretch(1,1);
+}
+
+KviThemeMdiAreaOptionsWidget::~KviThemeMdiAreaOptionsWidget()
+{
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+KviThemeToolBarAppletsOptionsWidget::KviThemeToolBarAppletsOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent)
+{
+ createLayout(9,1);
+
+ addFontSelector(0,0,0,0,__tr2qs_ctx("Font","options"),KviOption_fontIrcToolBarApplet);
+
+ addColorSelector(0,1,0,1,__tr2qs_ctx("Background","options"),KviOption_colorIrcToolBarAppletBackground);
+ addColorSelector(0,2,0,2,__tr2qs_ctx("Low-Contrast Foreground","options"),KviOption_colorIrcToolBarAppletForegroundLowContrast);
+ addColorSelector(0,3,0,3,__tr2qs_ctx("Mid-Contrast Foreground","options"),KviOption_colorIrcToolBarAppletForegroundMidContrast);
+ addColorSelector(0,4,0,4,__tr2qs_ctx("Active High-Contrast Foreground (Primary)","options"),KviOption_colorIrcToolBarAppletForegroundHighContrastActive1);
+ addColorSelector(0,5,0,5,__tr2qs_ctx("Active High-Contrast Foreground (Secondary)","options"),KviOption_colorIrcToolBarAppletForegroundHighContrastActive2);
+ addColorSelector(0,6,0,6,__tr2qs_ctx("Inactive High-Contrast Foreground (Primary)","options"),KviOption_colorIrcToolBarAppletForegroundHighContrastInactive1);
+ addColorSelector(0,7,0,7,__tr2qs_ctx("Inactive High-Contrast Foreground (Secondary)","options"),KviOption_colorIrcToolBarAppletForegroundHighContrastInactive2);
+
+ addPixmapSelector(0,8,0,8,__tr2qs_ctx("Background Image","options"),KviOption_pixmapIrcToolBarAppletBackground);
+
+ layout()->setRowStretch(8,1);
+}
+
+KviThemeToolBarAppletsOptionsWidget::~KviThemeToolBarAppletsOptionsWidget()
+{
+}
+
+
+#include "m_optw_interfacelookglobal.moc"
diff --git a/src/modules/options/optw_interfacelookglobal.h b/src/modules/options/optw_interfacelookglobal.h
new file mode 100644
index 00000000..ac4153b1
--- /dev/null
+++ b/src/modules/options/optw_interfacelookglobal.h
@@ -0,0 +1,113 @@
+#ifndef _OPTW_INTERFACELOOKGLOBAL_H_
+#define _OPTW_INTERFACELOOKGLOBAL_H_
+
+//
+// File : optw_interfacelookglobal.h
+// Creation date : Sun Jun 3 2001 20:49:02 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+#include "kvi_optionswidget.h"
+#include "kvi_selectors.h"
+
+
+#define KVI_OPTIONS_WIDGET_ICON_KviThemeGeneralOptionsWidget KVI_SMALLICON_GUI
+#define KVI_OPTIONS_WIDGET_NAME_KviThemeGeneralOptionsWidget __tr2qs_no_lookup("General")
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviThemeGeneralOptionsWidget __tr2qs_no_lookup("theme")
+#define KVI_OPTIONS_WIDGET_GROUP_KviThemeGeneralOptionsWidget "theme"
+
+
+class KviThemeGeneralOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviThemeGeneralOptionsWidget(QWidget * parent);
+ ~KviThemeGeneralOptionsWidget();
+};
+
+
+#define KVI_OPTIONS_WIDGET_ICON_KviThemeTransparencyOptionsWidget KVI_SMALLICON_TRANSPARENT
+#define KVI_OPTIONS_WIDGET_NAME_KviThemeTransparencyOptionsWidget __tr2qs_no_lookup("Transparency")
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviThemeTransparencyOptionsWidget __tr2qs_no_lookup("theme,background")
+#define KVI_OPTIONS_WIDGET_GROUP_KviThemeTransparencyOptionsWidget "theme"
+
+
+class KviThemeTransparencyOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviThemeTransparencyOptionsWidget(QWidget * parent);
+ ~KviThemeTransparencyOptionsWidget();
+protected:
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ KviPixmapSelector * m_pGlobalBackgroundPixmapSelector;
+ KviBoolSelector * m_pUseTransparencyBoolSelector;
+ #ifdef COMPILE_KDE_SUPPORT
+ KviBoolSelector * m_pObtainBackgroundFromKdeBoolSelector;
+ KviBoolSelector * m_pUpdateKdeBackgroundOnChangeBoolSelector;
+ #endif
+#endif
+protected slots:
+ void enableGlobalBackgroundPixmapSelector(bool);
+ void enableUpdateKdeBackgroundBoolSelector(bool);
+};
+
+
+#define KVI_OPTIONS_WIDGET_ICON_KviThemeMdiCaptionsOptionsWidget KVI_SMALLICON_CAPTION
+#define KVI_OPTIONS_WIDGET_NAME_KviThemeMdiCaptionsOptionsWidget __tr2qs_no_lookup("Window Captions")
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviThemeMdiCaptionsOptionsWidget __tr2qs_no_lookup("theme,mdi")
+#define KVI_OPTIONS_WIDGET_GROUP_KviThemeMdiCaptionsOptionsWidget "theme"
+
+class KviThemeMdiCaptionsOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviThemeMdiCaptionsOptionsWidget(QWidget * parent);
+ ~KviThemeMdiCaptionsOptionsWidget();
+};
+
+#define KVI_OPTIONS_WIDGET_ICON_KviThemeMdiAreaOptionsWidget KVI_SMALLICON_APPLET
+#define KVI_OPTIONS_WIDGET_NAME_KviThemeMdiAreaOptionsWidget __tr2qs_no_lookup("Workspace")
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviThemeMdiAreaOptionsWidget __tr2qs_no_lookup("theme,mdi")
+#define KVI_OPTIONS_WIDGET_GROUP_KviThemeMdiAreaOptionsWidget "theme"
+
+class KviThemeMdiAreaOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviThemeMdiAreaOptionsWidget(QWidget * parent);
+ ~KviThemeMdiAreaOptionsWidget();
+};
+
+#define KVI_OPTIONS_WIDGET_ICON_KviThemeToolBarAppletsOptionsWidget KVI_SMALLICON_APPLET
+#define KVI_OPTIONS_WIDGET_NAME_KviThemeToolBarAppletsOptionsWidget __tr2qs_no_lookup("ToolBar Applets")
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviThemeToolBarAppletsOptionsWidget __tr2qs_no_lookup("theme,toolbar")
+#define KVI_OPTIONS_WIDGET_GROUP_KviThemeToolBarAppletsOptionsWidget "theme"
+
+
+class KviThemeToolBarAppletsOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviThemeToolBarAppletsOptionsWidget(QWidget * parent);
+ ~KviThemeToolBarAppletsOptionsWidget();
+};
+
+#endif //!_OPTW_INTERFACELOOKGLOBAL_H_
diff --git a/src/modules/options/optw_irc.cpp b/src/modules/options/optw_irc.cpp
new file mode 100644
index 00000000..537fde9a
--- /dev/null
+++ b/src/modules/options/optw_irc.cpp
@@ -0,0 +1,220 @@
+//
+// File : optw_irc.cpp
+// Creation date : Sun Dec 2 18:59:48 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+#include "optw_irc.h"
+
+#include "kvi_settings.h"
+#include "kvi_locale.h"
+#include "kvi_options.h"
+#include "kvi_ircmask.h"
+
+#include <qcombobox.h>
+
+
+KviIrcOptionsWidget::KviIrcOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"irc_options_widget")
+{
+}
+
+
+KviIrcOptionsWidget::~KviIrcOptionsWidget()
+{
+}
+
+
+KviIrcGeneralOptionsWidget::KviIrcGeneralOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"irc_options_widget")
+{
+ createLayout(3,1);
+ KviBoolSelector *b = addBoolSelector(0,0,0,0,__tr2qs_ctx("Minimize console after successful login","options"),KviOption_boolMinimizeConsoleAfterConnect);
+
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b,__tr2qs_ctx("<center>This option will cause KVIrc to minimize the console window after successfully logging into a server.</center>","options"));
+#endif
+
+ b = addBoolSelector(0,1,0,1,__tr2qs_ctx("Show network name in console taskbar entry","options"),KviOption_boolShowNetworkNameForConsoleTaskBarEntry);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b,__tr2qs_ctx("<center>This option will cause KVIrc to show the network name as the console taskbar entry instead of the server name. This is nice to keep on unless your servers are not organized in networks or you often connect to two servers of the same network.</center>","options"));
+#endif
+
+
+ addRowSpacer(0,2,0,2);
+}
+
+
+KviIrcGeneralOptionsWidget::~KviIrcGeneralOptionsWidget()
+{
+}
+
+
+
+KviIrcAdvancedOptionsWidget::KviIrcAdvancedOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"irc_advanced_options_widget")
+{
+ createLayout(3,1);
+ KviBoolSelector *b = addBoolSelector(0,0,0,0,__tr2qs_ctx("Force immediate quit","options"),KviOption_boolForceBrutalQuit);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b,
+ __tr2qs_ctx("<center>This option causes KVIrc to close " \
+ "the connection immediately after sending the QUIT message.<br>" \
+ "When this option is disabled, KVIrc will wait for the server " \
+ "to close the connection.<br>" \
+ "Note that if you use this, your QUIT message may be not displayed.</center>","options"));
+#endif
+ addBoolSelector(0,1,0,1,__tr2qs_ctx("Prepend gender info to realname","options"),KviOption_boolPrependGenderInfoToRealname);
+}
+
+KviIrcAdvancedOptionsWidget::~KviIrcAdvancedOptionsWidget()
+{
+}
+
+
+
+
+
+KviChannelOptionsWidget::KviChannelOptionsWidget(QWidget * pParent)
+: KviOptionsWidget(pParent)
+{
+}
+
+KviChannelOptionsWidget::~KviChannelOptionsWidget()
+{
+}
+
+
+KviChannelGeneralOptionsWidget::KviChannelGeneralOptionsWidget(QWidget * pParent)
+: KviOptionsWidget(pParent)
+{
+ createLayout(5,1);
+
+ KviTalGroupBox * g = addGroupBox(0,0,0,0,1,Qt::Horizontal,__tr2qs_ctx("On Channel Kick","options"));
+
+ KviBoolSelector *b = addBoolSelector(g,__tr2qs_ctx("Rejoin channel","options"),KviOption_boolRejoinChannelOnKick);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b,
+ __tr2qs_ctx("<center>This option will cause KVIrc to attempt " \
+ "to rejoin a channel after being kicked.</center>","options"));
+#endif
+ b = addBoolSelector(g,__tr2qs_ctx("Keep channel open","options"),KviOption_boolKeepChannelOpenOnKick);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b,
+ __tr2qs_ctx("<center>This option will cause KVIrc to keep " \
+ "the channel window open after being kicked.<br>" \
+ "It might be a good idea to also enable the " \
+ "\"Rejoin channel\" option.</center>","options"));
+#endif
+
+ g = addGroupBox(0,1,0,1,1,Qt::Horizontal,__tr2qs_ctx("On Channel Part","options"));
+
+ b = addBoolSelector(g,__tr2qs_ctx("Keep channel open","options"),KviOption_boolKeepChannelOpenOnPart);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b,
+ __tr2qs_ctx("<center>This option will cause KVIrc to keep " \
+ "the channel window open after leaving it.</center>","options"));
+#endif
+
+ b = addBoolSelector(0,2,0,2,__tr2qs_ctx("Automatically join channel on invite","options"),KviOption_boolAutoJoinOnInvite);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b,
+ __tr2qs_ctx("<center>This option will cause KVIrc to automatically " \
+ "join a channel when an INVITE message for that channel is received.<br>" \
+ "<b>Warning:</b> This may help spammers harass you. :)</center>","options"));
+#endif
+
+ b = addBoolSelector(0,3,0,3, __tr2qs_ctx("Always open channels as minimized","options"),KviOption_boolCreateMinimizedChannels);
+
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b,
+ __tr2qs_ctx("<center>This option causes newly created " \
+ "channel windows to be immediately minimized.<br>" \
+ "Enable this if you don't like channels " \
+ "popping up while you're typing something in a channel. :D</center>","options"));
+#endif
+
+
+ addRowSpacer(0,4,0,4);
+}
+
+KviChannelGeneralOptionsWidget::~KviChannelGeneralOptionsWidget()
+{
+}
+
+
+KviChannelAdvancedOptionsWidget::KviChannelAdvancedOptionsWidget(QWidget * pParent)
+: KviOptionsWidget(pParent)
+{
+ createLayout(6,4);
+
+ KviBoolSelector * b = addBoolSelector(0,0,4,0,__tr2qs_ctx("Log joined channels history","options"),KviOption_boolLogChannelHistory);
+
+ addLabel(0,1,0,1,__tr2qs_ctx("Default ban mask:","options"));
+
+ m_pBanTypeCombo=new QComboBox(this);
+ addWidgetToLayout(m_pBanTypeCombo,1,1,4,1);
+
+ KviIrcMask hostmask("nick!user@machine.host.top");
+ KviIrcMask ipmask("nick!user@192.168.1.2");
+ QString tmp1;
+ QString tmp2;
+ for(int i=0;i<=26;i++)
+ {
+
+ hostmask.mask(tmp1,(KviIrcMask::MaskType)i);
+ ipmask.mask(tmp2,(KviIrcMask::MaskType)i);
+ m_pBanTypeCombo->insertItem(QString("%1 (%2)").arg(tmp1).arg(tmp2));
+ }
+ m_pBanTypeCombo->setCurrentItem(KVI_OPTION_UINT(KviOption_uintDefaultBanType));
+
+ KviTalGroupBox * g = addGroupBox(0,2,4,2,1,Qt::Horizontal,__tr2qs_ctx("On Channel Join","options"));
+ addBoolSelector(g,__tr2qs_ctx("Do not send /WHO request","options"),KviOption_boolDisableWhoRequestOnJoin);
+ addBoolSelector(g,__tr2qs_ctx("Do not request ban list","options"),KviOption_boolDisableBanListRequestOnJoin);
+ addBoolSelector(g,__tr2qs_ctx("Do not request ban exception list","options"),KviOption_boolDisableBanExceptionListRequestOnJoin);
+ addBoolSelector(g,__tr2qs_ctx("Do not request invite list","options"),KviOption_boolDisableInviteListRequestOnJoin);
+
+ b = addBoolSelector(0,3,4,3,__tr2qs_ctx("Do not update the away list","options"),KviOption_boolDisableAwayListUpdates);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b,
+ __tr2qs_ctx("<center>KVIrc sends out a channel /WHO message every now and then to keep " \
+ "the channel away list in sync. Use this option to disable this feature (and to save " \
+ "your IRC bandwidth.</center>","options"));
+#endif
+
+ g = addGroupBox(0,4,4,4,1,Qt::Horizontal,__tr2qs_ctx("On Channel Join","options"));
+ addBoolSelector(g,__tr2qs_ctx("Echo channel topic","options"),KviOption_boolEchoNumericTopic);
+ addBoolSelector(g,__tr2qs_ctx("Show channel sync time","options"),KviOption_boolShowChannelSyncTime);
+
+ addRowSpacer(0,5,4,5);
+}
+
+KviChannelAdvancedOptionsWidget::~KviChannelAdvancedOptionsWidget()
+{
+}
+
+void KviChannelAdvancedOptionsWidget::commit()
+{
+ KVI_OPTION_UINT(KviOption_uintDefaultBanType)=m_pBanTypeCombo->currentItem();
+ if((KVI_OPTION_UINT(KviOption_uintDefaultBanType)<0 )|| (KVI_OPTION_UINT(KviOption_uintDefaultBanType)>26)) KVI_OPTION_UINT(KviOption_uintDefaultBanType)=7;
+ KviOptionsWidget::commit();
+}
+
+#include "m_optw_irc.moc"
diff --git a/src/modules/options/optw_irc.h b/src/modules/options/optw_irc.h
new file mode 100644
index 00000000..cc33d284
--- /dev/null
+++ b/src/modules/options/optw_irc.h
@@ -0,0 +1,116 @@
+#ifndef _OPTW_IRC_H_
+#define _OPTW_IRC_H_
+//=============================================================================
+//
+// File : optw_irc.h
+// Creation date : Sun Dec 2 18:59:49 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_optionswidget.h"
+
+class QComboBox;
+
+#define KVI_OPTIONS_WIDGET_ICON_KviIrcOptionsWidget KVI_SMALLICON_IRC
+#define KVI_OPTIONS_WIDGET_NAME_KviIrcOptionsWidget __tr2qs_no_lookup("IRC")
+#define KVI_OPTIONS_WIDGET_PRIORITY_KviIrcOptionsWidget 80000
+#define KVI_OPTIONS_WIDGET_CONTAINER_KviIrcOptionsWidget true
+
+class KviIrcOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviIrcOptionsWidget(QWidget * parent);
+ ~KviIrcOptionsWidget();
+};
+
+#define KVI_OPTIONS_WIDGET_ICON_KviIrcGeneralOptionsWidget KVI_SMALLICON_IRC
+#define KVI_OPTIONS_WIDGET_NAME_KviIrcGeneralOptionsWidget __tr2qs_no_lookup("General")
+#define KVI_OPTIONS_WIDGET_PARENT_KviIrcGeneralOptionsWidget KviIrcOptionsWidget
+#define KVI_OPTIONS_WIDGET_PRIORITY_KviIrcGeneralOptionsWidget 80000
+
+class KviIrcGeneralOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviIrcGeneralOptionsWidget(QWidget * parent);
+ ~KviIrcGeneralOptionsWidget();
+};
+
+
+#define KVI_OPTIONS_WIDGET_ICON_KviIrcAdvancedOptionsWidget KVI_SMALLICON_IRC
+#define KVI_OPTIONS_WIDGET_NAME_KviIrcAdvancedOptionsWidget __tr2qs_no_lookup("Advanced")
+#define KVI_OPTIONS_WIDGET_PARENT_KviIrcAdvancedOptionsWidget KviIrcOptionsWidget
+#define KVI_OPTIONS_WIDGET_PRIORITY_KviIrcAdvancedOptionsWidget 50000
+
+class KviIrcAdvancedOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviIrcAdvancedOptionsWidget(QWidget * parent);
+ ~KviIrcAdvancedOptionsWidget();
+};
+
+
+#define KVI_OPTIONS_WIDGET_ICON_KviChannelOptionsWidget KVI_SMALLICON_CHANNEL
+#define KVI_OPTIONS_WIDGET_NAME_KviChannelOptionsWidget __tr2qs_no_lookup("Channel")
+#define KVI_OPTIONS_WIDGET_PARENT_KviChannelOptionsWidget KviIrcOptionsWidget
+#define KVI_OPTIONS_WIDGET_CONTAINER_KviChannelOptionsWidget true
+#define KVI_OPTIONS_WIDGET_NOTCONTAINED_KviChannelOptionsWidget true
+#define KVI_OPTIONS_WIDGET_PRIORITY_KviChannelOptionsWidget 90000
+
+class KviChannelOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviChannelOptionsWidget(QWidget * parent);
+ ~KviChannelOptionsWidget();
+};
+
+
+#define KVI_OPTIONS_WIDGET_ICON_KviChannelGeneralOptionsWidget KVI_SMALLICON_CHANNEL
+#define KVI_OPTIONS_WIDGET_NAME_KviChannelGeneralOptionsWidget __tr2qs_no_lookup("General")
+#define KVI_OPTIONS_WIDGET_PARENT_KviChannelGeneralOptionsWidget KviChannelOptionsWidget
+
+class KviChannelGeneralOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviChannelGeneralOptionsWidget(QWidget * parent);
+ ~KviChannelGeneralOptionsWidget();
+};
+
+#define KVI_OPTIONS_WIDGET_ICON_KviChannelAdvancedOptionsWidget KVI_SMALLICON_CHANNEL
+#define KVI_OPTIONS_WIDGET_NAME_KviChannelAdvancedOptionsWidget __tr2qs_no_lookup("Advanced")
+#define KVI_OPTIONS_WIDGET_PARENT_KviChannelAdvancedOptionsWidget KviChannelOptionsWidget
+
+class KviChannelAdvancedOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviChannelAdvancedOptionsWidget(QWidget * parent);
+ ~KviChannelAdvancedOptionsWidget();
+public:
+ virtual void commit();
+protected:
+ QComboBox * m_pBanTypeCombo;
+};
+
+#endif //_OPTW_IRC_H_
diff --git a/src/modules/options/optw_ircoutput.cpp b/src/modules/options/optw_ircoutput.cpp
new file mode 100644
index 00000000..cfa28456
--- /dev/null
+++ b/src/modules/options/optw_ircoutput.cpp
@@ -0,0 +1,94 @@
+//
+// File : optw_ircoutput.cpp
+// Creation date : Wed Nov 15 2000 11:45:06 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "optw_ircoutput.h"
+
+#include <qlayout.h>
+
+#include "kvi_settings.h"
+#include "kvi_options.h"
+#include "kvi_locale.h"
+
+#include <qcombobox.h>
+#include <qlabel.h>
+
+#ifdef COMPILE_INFO_TIPS
+ #include "kvi_tal_tooltip.h"
+#endif
+
+KviIrcOutputOptionsWidget::KviIrcOutputOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"ircoutput_options_widget")
+{
+ createLayout(7,2);
+
+ QLabel * l =new QLabel(__tr2qs_ctx("Output verbosity","options"),this);
+ addWidgetToLayout(l,0,0,0,0);
+
+ m_pVerbosityCombo = new QComboBox(false,this);
+ addWidgetToLayout(m_pVerbosityCombo,1,0,1,0);
+
+ m_pVerbosityCombo->insertItem(__tr2qs_ctx("Mute","options"));
+ m_pVerbosityCombo->insertItem(__tr2qs_ctx("Quiet","options"));
+ m_pVerbosityCombo->insertItem(__tr2qs_ctx("Normal","options"));
+ m_pVerbosityCombo->insertItem(__tr2qs_ctx("Verbose","options"));
+ m_pVerbosityCombo->insertItem(__tr2qs_ctx("Paranoic","options"));
+
+ if(KVI_OPTION_UINT(KviOption_uintOutputVerbosityLevel) > KVI_VERBOSITY_LEVEL_PARANOIC)
+ KVI_OPTION_UINT(KviOption_uintOutputVerbosityLevel) = KVI_VERBOSITY_LEVEL_NORMAL;
+ m_pVerbosityCombo->setCurrentItem(KVI_OPTION_UINT(KviOption_uintOutputVerbosityLevel));
+
+ KviTalGroupBox * g = addGroupBox(0,1,1,1,1,Qt::Horizontal,__tr2qs_ctx("Show in active window","options"));
+ addBoolSelector(g,__tr2qs_ctx("External messages","options"),KviOption_boolExternalMessagesToActiveWindow);
+ addBoolSelector(g,__tr2qs_ctx("External CTCP replies","options"),KviOption_boolCtcpRepliesToActiveWindow);
+ addBoolSelector(g,__tr2qs_ctx("Whois replies","options"),KviOption_boolWhoisRepliesToActiveWindow);
+ addBoolSelector(g,__tr2qs_ctx("ChanServ and NickServ notices","options"),KviOption_boolServicesNoticesToActiveWindow);
+ addBoolSelector(g,__tr2qs_ctx("Invite messages","options"),KviOption_boolInvitesToActiveWindow);
+ addBoolSelector(g,__tr2qs_ctx("Server replies","options"),KviOption_boolServerRepliesToActiveWindow);
+ addBoolSelector(g,__tr2qs_ctx("Server notices","options"),KviOption_boolServerNoticesToActiveWindow);
+ addBoolSelector(g,__tr2qs_ctx("Broadcast and WALLOPS messages","options"),KviOption_boolOperatorMessagesToActiveWindow);
+// if(KVI_OPTION_UINT(KviOption_uintUserExperienceLevel)>=2)
+// {
+ addBoolSelector(0,2,1,2,__tr2qs_ctx("Show extended server information","options"),KviOption_boolShowExtendedServerInfo);
+ addBoolSelector(0,3,1,3,__tr2qs_ctx("Show server pings","options"),KviOption_boolShowPingPong);
+ addBoolSelector(0,4,1,4,__tr2qs_ctx("Show own parts in the console","options"),KviOption_boolShowOwnParts);
+ addBoolSelector(0,5,1,5,__tr2qs_ctx("Show compact mode changes","options"),KviOption_boolShowCompactModeChanges);
+
+ addRowSpacer(0,6,1,6);
+// } else {
+// addRowSpacer(0,2,1,2);
+// }
+}
+
+KviIrcOutputOptionsWidget::~KviIrcOutputOptionsWidget()
+{
+}
+
+void KviIrcOutputOptionsWidget::commit()
+{
+ KviOptionsWidget::commit();
+
+ int i = m_pVerbosityCombo->currentItem();
+ if((i < 0) || (i > KVI_VERBOSITY_LEVEL_PARANOIC))i = KVI_VERBOSITY_LEVEL_NORMAL;
+ KVI_OPTION_UINT(KviOption_uintOutputVerbosityLevel) = i;
+}
+
+#include "m_optw_ircoutput.moc"
diff --git a/src/modules/options/optw_ircoutput.h b/src/modules/options/optw_ircoutput.h
new file mode 100644
index 00000000..27e5c4c8
--- /dev/null
+++ b/src/modules/options/optw_ircoutput.h
@@ -0,0 +1,49 @@
+#ifndef _OPTW_IRCOUTPUT_H_
+#define _OPTW_IRCOUTPUT_H_
+
+//
+// File : optw_ircoutput.h
+// Creation date : Wed Nov 15 2000 11:47:51 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_optionswidget.h"
+#include "kvi_tal_listview.h"
+
+class QComboBox;
+
+#define KVI_OPTIONS_WIDGET_ICON_KviIrcOutputOptionsWidget KVI_SMALLICON_RAW
+#define KVI_OPTIONS_WIDGET_NAME_KviIrcOutputOptionsWidget __tr2qs_no_lookup("Verbosity And Output")
+#define KVI_OPTIONS_WIDGET_PARENT_KviIrcOutputOptionsWidget KviIrcOptionsWidget
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviIrcOutputOptionsWidget __tr2qs_no_lookup("debug")
+#define KVI_OPTIONS_WIDGET_PRIORITY_KviIrcOutputOptionsWidget 75000
+
+class KviIrcOutputOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviIrcOutputOptionsWidget(QWidget * parent);
+ ~KviIrcOutputOptionsWidget();
+protected:
+ QComboBox * m_pVerbosityCombo;
+protected:
+ virtual void commit();
+};
+
+#endif //!_OPTW_IRCOUTPUT_H_
diff --git a/src/modules/options/optw_ircview.cpp b/src/modules/options/optw_ircview.cpp
new file mode 100644
index 00000000..860f80c5
--- /dev/null
+++ b/src/modules/options/optw_ircview.cpp
@@ -0,0 +1,168 @@
+//
+// File : optw_ircview.cpp
+// Creation date : Sat Aug 11 2001 03:29:52 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+#include "optw_ircview.h"
+
+#include <qlayout.h>
+#include "kvi_options.h"
+#include "kvi_locale.h"
+
+//#warning "Info tips"
+
+KviIrcViewThemeOptionsWidget::KviIrcViewThemeOptionsWidget(QWidget * pParent)
+: KviOptionsWidget(pParent)
+{
+}
+
+KviIrcViewThemeOptionsWidget::~KviIrcViewThemeOptionsWidget()
+{
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+KviIrcViewLookOptionsWidget::KviIrcViewLookOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"ircviewlook_options_widget")
+{
+ createLayout(6,2);
+
+ addFontSelector(0,0,1,0,__tr2qs_ctx("Font:","options"),KviOption_fontIrcView);
+ addColorSelector(0,1,1,1,__tr2qs_ctx("Background color:","options"),KviOption_colorIrcViewBackground);
+
+ addPixmapSelector(0,2,1,2,__tr2qs_ctx("Background image:","options"),KviOption_pixmapIrcViewBackground);
+
+ addLabel(0,3,0,3,__tr2qs_ctx("Horizontal align:","options"));
+ m_pHorizontalAlign=new QComboBox(this);
+ addWidgetToLayout(m_pHorizontalAlign,1,3,1,3);
+
+ addLabel(0,4,0,4,__tr2qs_ctx("Vertical align:","options"));
+ m_pVerticalAlign=new QComboBox(this);
+ addWidgetToLayout(m_pVerticalAlign,1,4,1,4);
+
+ addColorSelector(0,5,1,5,__tr2qs_ctx("Mark Line:","options"),KviOption_colorIrcViewMarkLine);
+
+ m_pHorizontalAlign->insertItem(__tr2qs_ctx("Tile","options"));
+ m_pHorizontalAlign->insertItem(__tr2qs_ctx("Left","options"));
+ m_pHorizontalAlign->insertItem(__tr2qs_ctx("Right","options"));
+ m_pHorizontalAlign->insertItem(__tr2qs_ctx("Center","options"));
+
+ m_pVerticalAlign->insertItem(__tr2qs_ctx("Tile","options"));
+ m_pVerticalAlign->insertItem(__tr2qs_ctx("Top","options"));
+ m_pVerticalAlign->insertItem(__tr2qs_ctx("Bottom","options"));
+ m_pVerticalAlign->insertItem(__tr2qs_ctx("Center","options"));
+
+ switch( KVI_OPTION_UINT(KviOption_uintIrcViewPixmapAlign) & Qt::AlignHorizontal_Mask)
+ {
+ case Qt::AlignLeft:
+ m_pHorizontalAlign->setCurrentItem(1);
+ break;
+ case Qt::AlignRight:
+ m_pHorizontalAlign->setCurrentItem(2);
+ break;
+ case Qt::AlignHCenter:
+ m_pHorizontalAlign->setCurrentItem(3);
+ break;
+ default:
+ m_pHorizontalAlign->setCurrentItem(0);
+ }
+
+ switch( KVI_OPTION_UINT(KviOption_uintIrcViewPixmapAlign) & Qt::AlignVertical_Mask)
+ {
+ case Qt::AlignTop:
+ m_pVerticalAlign->setCurrentItem(1);
+ break;
+ case Qt::AlignBottom:
+ m_pVerticalAlign->setCurrentItem(2);
+ break;
+ case Qt::AlignVCenter:
+ m_pVerticalAlign->setCurrentItem(3);
+ break;
+ default:
+ m_pVerticalAlign->setCurrentItem(0);
+ }
+
+ layout()->setRowStretch(2,1);
+}
+
+KviIrcViewLookOptionsWidget::~KviIrcViewLookOptionsWidget()
+{
+}
+
+void KviIrcViewLookOptionsWidget::commit()
+{
+ int iFlags=0;
+ switch(m_pHorizontalAlign->currentItem())
+ {
+ case 1:
+ iFlags|=Qt::AlignLeft;
+ break;
+ case 2:
+ iFlags|=Qt::AlignRight;
+ break;
+ case 3:
+ iFlags|=Qt::AlignHCenter;
+ break;
+ }
+ switch(m_pVerticalAlign->currentItem())
+ {
+ case 1:
+ iFlags|=Qt::AlignTop;
+ break;
+ case 2:
+ iFlags|=Qt::AlignBottom;
+ break;
+ case 3:
+ iFlags|=Qt::AlignVCenter;
+ break;
+ }
+
+ KVI_OPTION_UINT(KviOption_uintIrcViewPixmapAlign)=iFlags;
+ KviOptionsWidget::commit();
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+KviIrcViewFeaturesOptionsWidget::KviIrcViewFeaturesOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"ircviewfeatures_options_widget")
+{
+ createLayout(14,1);
+
+
+
+ addBoolSelector(0,7,0,7,__tr2qs_ctx("Enable URL highlighting","options"),KviOption_boolIrcViewUrlHighlighting);
+ addBoolSelector(0,8,0,8,__tr2qs_ctx("Use line wrap margin","options"),KviOption_boolIrcViewWrapMargin);
+ KviUIntSelector * s = addUIntSelector(0,9,0,9,__tr2qs_ctx("Maximum buffer size:","options"),KviOption_uintIrcViewMaxBufferSize,32,32767,2048);
+ s->setSuffix(__tr2qs_ctx(" lines","options"));
+ s = addUIntSelector(0,10,0,10,__tr2qs_ctx("Link tooltip show delay:","options"),KviOption_uintIrcViewToolTipTimeoutInMsec,256,10000,1800);
+ s->setSuffix(__tr2qs_ctx(" msec","options"));
+ s = addUIntSelector(0,11,0,11,__tr2qs_ctx("Link tooltip hide delay:","options"),KviOption_uintIrcViewToolTipHideTimeoutInMsec,256,10000,12000);
+ s->setSuffix(__tr2qs_ctx(" msec","options"));
+ addBoolSelector(0,12,0,12,__tr2qs_ctx("Track last read text line","options"),KviOption_boolTrackLastReadTextViewLine);
+ addRowSpacer(0,13,0,13);
+
+}
+
+KviIrcViewFeaturesOptionsWidget::~KviIrcViewFeaturesOptionsWidget()
+{
+}
+
+
+
+#include "m_optw_ircview.moc"
diff --git a/src/modules/options/optw_ircview.h b/src/modules/options/optw_ircview.h
new file mode 100644
index 00000000..3da03a5a
--- /dev/null
+++ b/src/modules/options/optw_ircview.h
@@ -0,0 +1,83 @@
+#ifndef _OPTW_IRCVIEW_H_
+#define _OPTW_IRCVIEW_H_
+
+//=============================================================================
+//
+// File : optw_ircview.h
+// Creation date : Sat Aug 11 2001 03:28:19 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+
+#include "kvi_optionswidget.h"
+#include <qcombobox.h>
+
+
+#define KVI_OPTIONS_WIDGET_ICON_KviIrcViewThemeOptionsWidget KVI_SMALLICON_IRCVIEW
+#define KVI_OPTIONS_WIDGET_NAME_KviIrcViewThemeOptionsWidget __tr2qs_no_lookup("Output")
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviIrcViewThemeOptionsWidget __tr2qs_no_lookup("theme,colors,output")
+#define KVI_OPTIONS_WIDGET_GROUP_KviIrcViewThemeOptionsWidget "theme"
+#define KVI_OPTIONS_WIDGET_CONTAINER_KviIrcViewThemeOptionsWidget true
+
+class KviIrcViewThemeOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviIrcViewThemeOptionsWidget(QWidget * pParent);
+ ~KviIrcViewThemeOptionsWidget();
+};
+
+#define KVI_OPTIONS_WIDGET_ICON_KviIrcViewLookOptionsWidget KVI_SMALLICON_IRCVIEW
+#define KVI_OPTIONS_WIDGET_NAME_KviIrcViewLookOptionsWidget __tr2qs_no_lookup("Look")
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviIrcViewLookOptionsWidget __tr2qs_no_lookup("theme,colors,output")
+#define KVI_OPTIONS_WIDGET_GROUP_KviIrcViewLookOptionsWidget "theme"
+#define KVI_OPTIONS_WIDGET_PARENT_KviIrcViewLookOptionsWidget KviIrcViewThemeOptionsWidget
+#define KVI_OPTIONS_WIDGET_PRIORITY_KviIrcViewLookOptionsWidget 30
+
+class KviIrcViewLookOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+private:
+ QComboBox* m_pHorizontalAlign;
+ QComboBox* m_pVerticalAlign;
+public:
+ KviIrcViewLookOptionsWidget(QWidget * parent);
+ ~KviIrcViewLookOptionsWidget();
+public:
+ virtual void commit();
+};
+
+#define KVI_OPTIONS_WIDGET_ICON_KviIrcViewFeaturesOptionsWidget KVI_SMALLICON_IRCVIEW
+#define KVI_OPTIONS_WIDGET_NAME_KviIrcViewFeaturesOptionsWidget __tr2qs_no_lookup("Features")
+#define KVI_OPTIONS_WIDGET_GROUP_KviIrcViewFeaturesOptionsWidget "theme"
+#define KVI_OPTIONS_WIDGET_PARENT_KviIrcViewFeaturesOptionsWidget KviIrcViewThemeOptionsWidget
+#define KVI_OPTIONS_WIDGET_PRIORITY_KviIrcViewFeaturesOptionsWidget 20
+
+class KviIrcViewFeaturesOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviIrcViewFeaturesOptionsWidget(QWidget * parent);
+ ~KviIrcViewFeaturesOptionsWidget();
+};
+
+
+
+#endif //!_OPTW_IRCVIEW_H_
diff --git a/src/modules/options/optw_lag.cpp b/src/modules/options/optw_lag.cpp
new file mode 100644
index 00000000..8c9cf201
--- /dev/null
+++ b/src/modules/options/optw_lag.cpp
@@ -0,0 +1,85 @@
+//
+// File : optw_lag.cpp
+// Creation date : Wed Cct 16 10:45:54 CEST 2002 by Juanjo lvarez (juanjux@yahoo.es)
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+#include "optw_lag.h"
+
+#include <qlayout.h>
+#include "kvi_tal_tooltip.h"
+
+#include "kvi_options.h"
+#include "kvi_locale.h"
+
+//#warning "Info tips"
+
+
+KviLagOptionsWidget::KviLagOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"lag_options_widget")
+{
+ createLayout(3,1);
+
+ KviBoolSelector * pUse = addBoolSelector(0,0,0,0, __tr2qs_ctx("Enable lag meter","options"), KviOption_boolUseLagMeterEngine);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(pUse,__tr2qs_ctx("<center>This enables the lag meter engine, which checks at regular intervals how much lag (latency) the server has.</center>","options"));
+#endif
+ KviTalGroupBox *g = addGroupBox(0,1,0,1,1,Qt::Horizontal,__tr2qs_ctx("Configuration","options"),KVI_OPTION_BOOL(KviOption_boolUseLagMeterEngine));
+ KviUIntSelector * pInterval = addUIntSelector(g, __tr2qs_ctx("Lag meter heartbeat:","options"),KviOption_uintLagMeterHeartbeat,2000,10000,5000,KVI_OPTION_BOOL(KviOption_boolUseLagMeterEngine));
+ pInterval->setSuffix(__tr2qs_ctx(" msec","options"));
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(pInterval,
+ __tr2qs_ctx("<center>This option allows you to set the lag meter heartbeat interval.<br>" \
+ "The lower the heartbeat interval the higher will be the accuracy of the lag check " \
+ "but also higher cpu usage and data traffic to the server.<br>" \
+ "Please note that this is NOT the interval between pings sent to the server: " \
+ "the pings (if any) will be sent really less often. " \
+ "5000 is a reasonable value.</center>","options"));
+#endif
+ connect(pUse,SIGNAL(toggled(bool)),pInterval,SLOT(setEnabled(bool)));
+
+ KviUIntSelector * pAlarm = addUIntSelector(g, __tr2qs_ctx("Trigger event if lag exceeds:","options"), KviOption_uintLagAlarmTime,5000,1000000,30000, KVI_OPTION_BOOL(KviOption_boolUseLagMeterEngine));
+ pAlarm->setSuffix(__tr2qs_ctx(" msec","options"));
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(pAlarm,__tr2qs_ctx("<center>This option controls the threshold for the " \
+ "OnLagAlarmTimeUp and OnLagAlarmTimeDown events. When the lag goes above " \
+ "the threshold OnLagAlarmTimeUp will be triggered and when the lag falls " \
+ "back below the threshold then OnLagAlarmTimeDown will be triggered</center>","options"));
+#endif
+ connect(pUse,SIGNAL(toggled(bool)),pAlarm,SLOT(setEnabled(bool)));
+
+ KviBoolSelector * pShow = addBoolSelector(g, __tr2qs_ctx("Show lag in IRC context display","options"), KviOption_boolShowLagOnContextDisplay, KVI_OPTION_BOOL(KviOption_boolUseLagMeterEngine));
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(pShow,__tr2qs_ctx("<center>This makes the IRC context display applet show the current lag after the user's nickname (in seconds)</center>","options"));
+#endif
+
+ connect(pUse,SIGNAL(toggled(bool)),pShow,SLOT(setEnabled(bool)));
+ connect(pUse,SIGNAL(toggled(bool)),g,SLOT(setEnabled(bool)));
+
+ addRowSpacer(0,2,0,2);
+
+}
+
+KviLagOptionsWidget::~KviLagOptionsWidget()
+{
+}
+
+
+#include "m_optw_lag.moc"
diff --git a/src/modules/options/optw_lag.h b/src/modules/options/optw_lag.h
new file mode 100644
index 00000000..7e49cafd
--- /dev/null
+++ b/src/modules/options/optw_lag.h
@@ -0,0 +1,40 @@
+#ifndef _OPTW_LAG_H_
+#define _OPTW_LAG_H_
+//
+// File : optw_lag.h
+// Creation date : wed oct 16 10:45:14 CEST 2002 by Juanjo �varez
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_optionswidget.h"
+
+#define KVI_OPTIONS_WIDGET_ICON_KviLagOptionsWidget KVI_SMALLICON_STATS
+#define KVI_OPTIONS_WIDGET_NAME_KviLagOptionsWidget __tr2qs_no_lookup("Lag")
+#define KVI_OPTIONS_WIDGET_PARENT_KviLagOptionsWidget KviToolsOptionsWidget
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviLagOptionsWidget __tr2qs_no_lookup("time,ping")
+
+class KviLagOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviLagOptionsWidget(QWidget * parent);
+ ~KviLagOptionsWidget();
+};
+
+#endif //_OPTW_LAG_H_
diff --git a/src/modules/options/optw_logging.cpp b/src/modules/options/optw_logging.cpp
new file mode 100644
index 00000000..9d77836d
--- /dev/null
+++ b/src/modules/options/optw_logging.cpp
@@ -0,0 +1,64 @@
+//
+// File : optw_logging.cpp
+// Creation date : Mon Oct 29 15:37:16 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+#include "optw_logging.h"
+
+#include <qlayout.h>
+
+#include "kvi_options.h"
+#include "kvi_locale.h"
+
+//#warning "Info tips"
+
+
+KviLoggingOptionsWidget::KviLoggingOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"logging_options_widget")
+{
+ createLayout(4,1);
+
+ KviTalGroupBox * g = addGroupBox(0,0,0,0,1,Qt::Horizontal,__tr2qs_ctx("Automatically Log","options"));
+ addBoolSelector(g,__tr2qs_ctx("Query windows","options"),KviOption_boolAutoLogQueries);
+ addBoolSelector(g,__tr2qs_ctx("Channel windows","options"),KviOption_boolAutoLogChannels);
+ addBoolSelector(g,__tr2qs_ctx("DCC Chat windows","options"),KviOption_boolAutoLogDccChat);
+ addBoolSelector(g,__tr2qs_ctx("Console windows","options"),KviOption_boolAutoLogConsole);
+#ifdef COMPILE_ZLIB_SUPPORT
+ addBoolSelector(0,1,0,1,__tr2qs_ctx("Gzip logs","options"),KviOption_boolGzipLogs);
+#endif
+ addBoolSelector(0,2,0,2,__tr2qs_ctx("Strip colors in logs","options"),KviOption_boolStripControlCodesInLogs);
+ KviUIntSelector* us = addUIntSelector(0,3,0,3,__tr2qs_ctx("Auto flush logs every","options"),KviOption_uintAutoFlushLogs,0,99999,0);
+ us->setSuffix(__tr2qs_ctx(" min","options"));
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(us,
+ __tr2qs_ctx("<center>Save logs with the current interval<br>" \
+ "Set to 0 to disable this feature</center>","options"));
+#endif
+ addRowSpacer(0,4,0,4);
+}
+
+KviLoggingOptionsWidget::~KviLoggingOptionsWidget()
+{
+}
+
+
+
+#include "m_optw_logging.moc"
diff --git a/src/modules/options/optw_logging.h b/src/modules/options/optw_logging.h
new file mode 100644
index 00000000..f3f3e1c4
--- /dev/null
+++ b/src/modules/options/optw_logging.h
@@ -0,0 +1,42 @@
+#ifndef _OPTW_LOGGING_H_
+#define _OPTW_LOGGING_H_
+//
+// File : optw_logging.h
+// Creation date : Mon Oct 29 15:37:18 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_optionswidget.h"
+
+#define KVI_OPTIONS_WIDGET_ICON_KviLoggingOptionsWidget KVI_SMALLICON_LOG
+#define KVI_OPTIONS_WIDGET_NAME_KviLoggingOptionsWidget __tr2qs_no_lookup("Logging")
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviLoggingOptionsWidget __tr2qs_no_lookup("save,output")
+#define KVI_OPTIONS_WIDGET_PARENT_KviLoggingOptionsWidget KviToolsOptionsWidget
+
+//noway #define KVI_OPTIONS_WIDGET_NO_PARENT_KviLoggingOptionsWidget KviIrcOptionsWidget
+
+class KviLoggingOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviLoggingOptionsWidget(QWidget * parent);
+ ~KviLoggingOptionsWidget();
+};
+
+#endif //_OPTW_LOGGING_H_
diff --git a/src/modules/options/optw_mediatypes.cpp b/src/modules/options/optw_mediatypes.cpp
new file mode 100644
index 00000000..c798a4eb
--- /dev/null
+++ b/src/modules/options/optw_mediatypes.cpp
@@ -0,0 +1,262 @@
+//
+// File : optw_mediatypes.cpp
+// Creation date : Sat Jan 20 2001 16:14:53 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "optw_mediatypes.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include "kvi_tal_tooltip.h"
+
+#include "kvi_options.h"
+#include "kvi_locale.h"
+
+// kvi_app.cpp
+extern KVIRC_API KviMediaManager * g_pMediaManager;
+
+static void copyMediaType(KviMediaType * dst,const KviMediaType * src)
+{
+ dst->szFileMask = src->szFileMask;
+ dst->szIanaType = src->szIanaType;
+ dst->szDescription = src->szDescription;
+ dst->szMagicBytes = src->szMagicBytes;
+ dst->szSavePath = src->szSavePath;
+ dst->szCommandline = src->szCommandline;
+ dst->szRemoteExecCommandline = src->szRemoteExecCommandline;
+ dst->szIcon = src->szIcon;
+}
+
+KviMediaTypeListViewItem::KviMediaTypeListViewItem(KviTalListView * w,KviMediaType * t)
+: KviTalListViewItem(w)
+{
+ copyData(t);
+}
+
+KviMediaTypeListViewItem::~KviMediaTypeListViewItem()
+{
+}
+
+void KviMediaTypeListViewItem::copyData(KviMediaType * t)
+{
+ copyMediaType(&m_data,t);
+ setText(0,m_data.szFileMask.ptr());
+ setText(1,m_data.szIanaType.ptr());
+ setText(2,m_data.szDescription.ptr());
+}
+
+KviMediaTypesOptionsWidget::KviMediaTypesOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"mediatypes_options_widget")
+{
+ createLayout(11,3);
+
+ m_pListView = new KviTalListView(this);
+ m_pListView->addColumn(__tr2qs_ctx("Pattern","options"));
+ m_pListView->addColumn(__tr2qs_ctx("MIME Type","options"));
+ m_pListView->addColumn(__tr2qs_ctx("Description","options"));
+ m_pListView->setAllColumnsShowFocus(true);
+
+
+
+ connect(m_pListView,SIGNAL(currentChanged(KviTalListViewItem *)),this,SLOT(currentItemChanged(KviTalListViewItem *)));
+
+ layout()->addMultiCellWidget(m_pListView,0,0,0,2);
+
+ QLabel * l = new QLabel(__tr2qs_ctx("Description:","options"),this);
+ layout()->addWidget(l,1,0);
+ m_pDescription = new QLineEdit(this);
+ layout()->addMultiCellWidget(m_pDescription,1,1,1,2);
+
+ l = new QLabel(__tr2qs_ctx("MIME type:","options"),this);
+ layout()->addWidget(l,2,0);
+ m_pIanaType = new QLineEdit(this);
+ layout()->addMultiCellWidget(m_pIanaType,2,2,1,2);
+
+ l = new QLabel(__tr2qs_ctx("File pattern:","options"),this);
+ layout()->addWidget(l,3,0);
+ m_pFileMask = new QLineEdit(this);
+ layout()->addMultiCellWidget(m_pFileMask,3,3,1,2);
+
+ l = new QLabel(__tr2qs_ctx("Magic bytes:","options"),this);
+ layout()->addWidget(l,4,0);
+ m_pMagicBytes = new QLineEdit(this);
+ layout()->addMultiCellWidget(m_pMagicBytes,4,4,1,2);
+
+ l = new QLabel(__tr2qs_ctx("Save path:","options"),this);
+ layout()->addWidget(l,5,0);
+ m_pSavePath = new QLineEdit(this);
+ layout()->addMultiCellWidget(m_pSavePath,5,5,1,2);
+
+ l = new QLabel(__tr2qs_ctx("Local open command:","options"),this);
+ layout()->addWidget(l,6,0);
+ m_pCommandline = new QLineEdit(this);
+ layout()->addMultiCellWidget(m_pCommandline,6,6,1,2);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(m_pCommandline,__tr2qs_ctx("<center>This field contains the command to execute to open a local file.<br>" \
+ "<tt>$0</tt> is used in place of the filename</center>","options"));
+#endif
+
+ l = new QLabel(__tr2qs_ctx("Remote open command:","options"),this);
+ layout()->addWidget(l,7,0);
+ m_pRemoteExecCommandline = new QLineEdit(this);
+ layout()->addMultiCellWidget(m_pRemoteExecCommandline,7,7,1,2);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(m_pRemoteExecCommandline,__tr2qs_ctx("<center>This field contains the command to execute when automatically opening a received file.<br>" \
+ "<tt>$0</tt> is used in place of the filename</center>","options"));
+#endif
+
+ l = new QLabel(__tr2qs_ctx("Icon","options"),this);
+ layout()->addWidget(l,8,0);
+ m_pIcon = new QLineEdit(this);
+ layout()->addMultiCellWidget(m_pIcon,8,8,1,2);
+
+ QFrame * f = new QFrame(this);
+ f->setFrameStyle(QFrame::Sunken | QFrame::HLine);
+ layout()->addMultiCellWidget(f,9,9,0,2);
+
+ QPushButton * b = new QPushButton(__tr2qs_ctx("&New","options"),this);
+ connect(b,SIGNAL(clicked()),this,SLOT(newMediaType()));
+ layout()->addWidget(b,10,1);
+
+ m_pDelete = new QPushButton(__tr2qs_ctx("Re&move","options"),this);
+ connect(m_pDelete,SIGNAL(clicked()),this,SLOT(delMediaType()));
+ layout()->addWidget(m_pDelete,10,2);
+
+
+ layout()->setColStretch(1,1);
+ layout()->setColStretch(2,1);
+ layout()->setRowStretch(0,1);
+
+ m_pLastItem = 0;
+
+ fillListView();
+}
+
+KviMediaTypesOptionsWidget::~KviMediaTypesOptionsWidget()
+{
+}
+
+void KviMediaTypesOptionsWidget::fillListView()
+{
+ m_pListView->clear();
+ g_pMediaManager->lock();
+ KviPointerList<KviMediaType> * l = g_pMediaManager->mediaTypeList();
+ KviMediaTypeListViewItem * it;
+ for(KviMediaType * t = l->first();t;t = l->next())
+ {
+ it = new KviMediaTypeListViewItem(m_pListView,t);
+ }
+ g_pMediaManager->unlock();
+ enableOrDisable();
+}
+
+void KviMediaTypesOptionsWidget::saveLastItem()
+{
+ if(m_pLastItem)
+ {
+ KviMediaType t;
+ t.szDescription = m_pDescription->text();
+ t.szIanaType = m_pIanaType->text();
+ t.szFileMask = m_pFileMask->text();
+ t.szSavePath = m_pSavePath->text();
+ t.szCommandline = m_pCommandline->text();
+ t.szMagicBytes = m_pMagicBytes->text();
+ t.szRemoteExecCommandline = m_pRemoteExecCommandline->text();
+ t.szIcon = m_pIcon->text();
+
+ if(t.szDescription.isEmpty())t.szDescription = __tr2qs_ctx("[Unknown Media Type]","options");
+
+ m_pLastItem->copyData(&t);
+ }
+}
+
+void KviMediaTypesOptionsWidget::enableOrDisable()
+{
+ m_pDescription->setEnabled(m_pLastItem);
+ m_pIanaType->setEnabled(m_pLastItem);
+ m_pFileMask->setEnabled(m_pLastItem);
+ m_pSavePath->setEnabled(m_pLastItem);
+ m_pCommandline->setEnabled(m_pLastItem);
+ m_pMagicBytes->setEnabled(m_pLastItem);
+ m_pRemoteExecCommandline->setEnabled(m_pLastItem);
+ m_pDelete->setEnabled(m_pLastItem);
+ m_pIcon->setEnabled(m_pLastItem);
+}
+
+void KviMediaTypesOptionsWidget::setLineEdits()
+{
+ m_pDescription->setText(m_pLastItem ? m_pLastItem->data()->szDescription.ptr() : "");
+ m_pIanaType->setText(m_pLastItem ? m_pLastItem->data()->szIanaType.ptr() : "");
+ m_pFileMask->setText(m_pLastItem ? m_pLastItem->data()->szFileMask.ptr() : "");
+ m_pSavePath->setText(m_pLastItem ? m_pLastItem->data()->szSavePath.ptr() : "");
+ m_pCommandline->setText(m_pLastItem ? m_pLastItem->data()->szCommandline.ptr() : "");
+ m_pMagicBytes->setText(m_pLastItem ? m_pLastItem->data()->szMagicBytes.ptr() : "");
+ m_pRemoteExecCommandline->setText(m_pLastItem ? m_pLastItem->data()->szRemoteExecCommandline.ptr() : "");
+ m_pIcon->setText(m_pLastItem ? m_pLastItem->data()->szIcon.ptr() : "");
+}
+
+void KviMediaTypesOptionsWidget::currentItemChanged(KviTalListViewItem *it)
+{
+ saveLastItem();
+ m_pLastItem = (KviMediaTypeListViewItem *)it;
+ if(it)
+ {
+ if(!it->isSelected())m_pListView->setSelected(it,true);
+ }
+ setLineEdits();
+ enableOrDisable();
+}
+
+void KviMediaTypesOptionsWidget::newMediaType()
+{
+ KviMediaType empty;
+ empty.szDescription = __tr2qs_ctx("New Media Type","options");
+ KviMediaTypeListViewItem * it = new KviMediaTypeListViewItem(m_pListView,&empty);
+ m_pListView->setCurrentItem(it);
+ m_pListView->setSelected(it,true);
+}
+
+void KviMediaTypesOptionsWidget::delMediaType()
+{
+ if(m_pLastItem)
+ {
+ KviMediaTypeListViewItem * it = m_pLastItem;
+ m_pLastItem = 0;
+ delete it;
+ }
+}
+
+void KviMediaTypesOptionsWidget::commit()
+{
+ saveLastItem();
+ KviMediaTypeListViewItem * it = (KviMediaTypeListViewItem *)m_pListView->firstChild();
+ g_pMediaManager->lock();
+ g_pMediaManager->clear();
+ while(it)
+ {
+ KviMediaType * t = new KviMediaType;
+ copyMediaType(t,it->data());
+ g_pMediaManager->insertMediaType(t);
+ it = (KviMediaTypeListViewItem *)it->nextSibling();
+ }
+ g_pMediaManager->unlock();
+}
+
+#include "m_optw_mediatypes.moc"
diff --git a/src/modules/options/optw_mediatypes.h b/src/modules/options/optw_mediatypes.h
new file mode 100644
index 00000000..22fab930
--- /dev/null
+++ b/src/modules/options/optw_mediatypes.h
@@ -0,0 +1,83 @@
+#ifndef _OPTW_MEDIATYPES_H_
+#define _OPTW_MEDIATYPES_H_
+
+//
+// File : optw_mediatypes.h
+// Creation date : Sat Jan 20 2001 16:12:10 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_optionswidget.h"
+#include "kvi_tal_listview.h"
+#include <qlineedit.h>
+#include <qpushbutton.h>
+
+#include "kvi_mediatype.h"
+
+class KviMediaTypeListViewItem : public KviTalListViewItem
+{
+public:
+ KviMediaTypeListViewItem(KviTalListView * w,KviMediaType * t);
+ ~KviMediaTypeListViewItem();
+private:
+ KviMediaType m_data;
+public:
+ void copyData(KviMediaType * t);
+ const KviMediaType * data(){ return &m_data; };
+};
+
+#define KVI_OPTIONS_WIDGET_ICON_KviMediaTypesOptionsWidget KVI_SMALLICON_FILE
+#define KVI_OPTIONS_WIDGET_NAME_KviMediaTypesOptionsWidget __tr2qs_no_lookup("Media Types")
+#define KVI_OPTIONS_WIDGET_PARENT_KviMediaTypesOptionsWidget KviGeneralOptOptionsWidget
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviMediaTypesOptionsWidget __tr2qs_no_lookup("file,audio,video,programs")
+#define KVI_OPTIONS_WIDGET_PRIORITY_KviMediaTypesOptionsWidget 60000
+//#define KVI_OPTIONS_WIDGET_HIDDEN_KviMediaTypesOptionsWidget true
+
+class KviMediaTypesOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviMediaTypesOptionsWidget(QWidget * parent);
+ ~KviMediaTypesOptionsWidget();
+private:
+ KviTalListView * m_pListView;
+ QLineEdit * m_pDescription;
+ QLineEdit * m_pIanaType;
+ QLineEdit * m_pFileMask;
+ QLineEdit * m_pSavePath;
+ QLineEdit * m_pCommandline;
+ QLineEdit * m_pMagicBytes;
+ QLineEdit * m_pRemoteExecCommandline;
+ QLineEdit * m_pIcon;
+ QPushButton * m_pDelete;
+ KviMediaTypeListViewItem * m_pLastItem;
+private:
+ void fillListView();
+ void saveLastItem();
+ void enableOrDisable();
+ void setLineEdits();
+private slots:
+ void currentItemChanged(KviTalListViewItem *it);
+ void newMediaType();
+ void delMediaType();
+public:
+ virtual void commit();
+};
+
+#endif //!_OPTW_IDENTITY_H_
diff --git a/src/modules/options/optw_messages.cpp b/src/modules/options/optw_messages.cpp
new file mode 100644
index 00000000..54b4629a
--- /dev/null
+++ b/src/modules/options/optw_messages.cpp
@@ -0,0 +1,693 @@
+//=============================================================================
+//
+// File : optw_messages.cpp
+// Creation date : Sat Aug 11 2001 18:12:00 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define _WANT_OPTION_FLAGS_
+
+#include "optw_messages.h"
+
+#include <qlayout.h>
+#include <qpushbutton.h>
+#include "kvi_tal_vbox.h"
+#include <qcursor.h>
+#include <qpainter.h>
+#include "kvi_styled_controls.h"
+
+#include "kvi_settings.h"
+
+#ifndef COMPILE_ON_WINDOWS
+ #include <unistd.h> // symlink()
+#endif
+
+#include "kvi_options.h"
+#include "kvi_app.h"
+#include "kvi_locale.h"
+#include "kvi_iconmanager.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_config.h"
+#include "kvi_filedialog.h"
+
+//#warning "Info tips"
+
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ extern KVIRC_API QPixmap * g_pShadedChildGlobalDesktopBackground;
+#endif
+
+
+KviMessageOptionsWidget::KviMessageOptionsWidget(QWidget * pParent)
+: KviOptionsWidget(pParent)
+{
+}
+
+KviMessageOptionsWidget::~KviMessageOptionsWidget()
+{
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+KviPrivmsgOptionsWidget::KviPrivmsgOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"privmsg_options_widget")
+{
+ createLayout(4,1);
+
+ KviBoolSelector * b1;
+ KviBoolSelector * b2;
+
+ KviTalGroupBox * g = addGroupBox(0,0,0,0,1,Qt::Horizontal,__tr2qs_ctx("General","options"));
+
+ addBoolSelector(g,__tr2qs_ctx("Show message icons","options"),KviOption_boolIrcViewShowImages);
+ addBoolSelector(g,__tr2qs_ctx("Draw some emoticons (smileys) as pictures","options"),KviOption_boolDrawEmoticons);
+ addBoolSelector(g,__tr2qs_ctx("Don't show colors in user messages","options"),KviOption_boolStripMircColorsInUserMessages);
+
+
+
+
+ g = addGroupBox(0,1,0,1,1,Qt::Horizontal,__tr2qs_ctx("Nicknames","options"));
+
+ b1 = addBoolSelector(g,__tr2qs_ctx("\"Smart\" nickname colors","options"),KviOption_boolColorNicks);
+ b2 = addBoolSelector(g,__tr2qs_ctx("Use same colors as in the userlist","options"),KviOption_boolUseUserListColorsAsNickColors,!KVI_OPTION_BOOL(KviOption_boolColorNicks));
+ connect(b1,SIGNAL(toggled(bool)),b2,SLOT(setNotEnabled(bool)));
+ addBoolSelector(g,__tr2qs_ctx("Show nicknames in bold","options"),KviOption_boolBoldedNicks);
+ addBoolSelector(g,__tr2qs_ctx("Show user and host","options"),KviOption_boolShowUserAndHostInPrivmsgView);
+ addBoolSelector(g,__tr2qs_ctx("Show channel mode prefix","options"),KviOption_boolShowChannelUserFlagInPrivmsgView);
+ KviBoolSelector * b = addBoolSelector(g,__tr2qs_ctx("User-defined prefix and postfix","options"),KviOption_boolUseExtendedPrivmsgView);
+
+ QLabel * l = addLabel(g,__tr2qs_ctx("[PREFIX]nickname[!user@host][POSTFIX] message","options"));
+
+ l->setEnabled(KVI_OPTION_BOOL(KviOption_boolUseExtendedPrivmsgView));
+ connect(b,
+ SIGNAL(toggled(bool)),
+ l,
+ SLOT(setEnabled(bool)));
+
+ KviTalVBox * vb = new KviTalVBox(g);
+ vb->setSpacing(5);
+
+ connect(
+ b,
+ SIGNAL(toggled(bool)),
+ addStringSelector(vb,__tr2qs_ctx("Prefix:","options"),KviOption_stringExtendedPrivmsgPrefix,KVI_OPTION_BOOL(KviOption_boolUseExtendedPrivmsgView)),
+ SLOT(setEnabled(bool)));
+ connect(
+ b,
+ SIGNAL(toggled(bool)),
+ addStringSelector(vb,__tr2qs_ctx("Postfix:","options"),KviOption_stringExtendedPrivmsgPostfix,KVI_OPTION_BOOL(KviOption_boolUseExtendedPrivmsgView)),
+ SLOT(setEnabled(bool)));
+ addRowSpacer(0,3,0,3);
+}
+
+KviPrivmsgOptionsWidget::~KviPrivmsgOptionsWidget()
+{
+
+}
+
+KviTimestampOptionsWidget::KviTimestampOptionsWidget(QWidget * pParent)
+: KviOptionsWidget(pParent)
+{
+ createLayout(5,1);
+ m_pUseTimestampSelector = addBoolSelector(0,0,0,0,__tr2qs_ctx("Show timestamp","options"),KviOption_boolIrcViewTimestamp);
+
+ connect(m_pUseTimestampSelector,SIGNAL(toggled(bool)),this,SLOT(enableDisableTimestampSelector(bool)));
+ KviBoolSelector* b = addBoolSelector(0,1,0,1,__tr2qs_ctx("Use UTC time for timestamp","options"),KviOption_boolIrcViewTimestampUTC,KVI_OPTION_BOOL(KviOption_boolIrcViewTimestamp));
+
+ connect(m_pUseTimestampSelector,SIGNAL(toggled(bool)),b,SLOT(setEnabled(bool)));
+
+ KviTalHBox *hb = new KviTalHBox(this);
+ addWidgetToLayout(hb,0,2,0,2);
+
+ m_pSpecialTimestampColorSelector = addBoolSelector(hb,__tr2qs_ctx("Use special color for timestamps","options"),KviOption_boolUseSpecialColorForTimestamp,KVI_OPTION_BOOL(KviOption_boolIrcViewTimestamp));
+ connect(m_pSpecialTimestampColorSelector,SIGNAL(toggled(bool)),this,SLOT(enableDisableTimestampSelector(bool)));
+ connect(m_pUseTimestampSelector,SIGNAL(toggled(bool)),m_pSpecialTimestampColorSelector,SLOT(setEnabled(bool)));
+
+ m_pTimestampColorSelector = addMircTextColorSelector(hb,"",KviOption_uintTimeStampForeground,KviOption_uintTimeStampBackground,KVI_OPTION_BOOL(KviOption_boolIrcViewTimestamp) && KVI_OPTION_BOOL(KviOption_boolUseSpecialColorForTimestamp));
+
+ KviStringSelector * st=addStringSelector(0,3,0,3,__tr2qs_ctx("Timestamp format:","options"),KviOption_stringIrcViewTimestampFormat);
+ connect(m_pUseTimestampSelector,SIGNAL(toggled(bool)),st,SLOT(setEnabled(bool)));
+
+ connect(m_pUseTimestampSelector,SIGNAL(toggled(bool)),m_pSpecialTimestampColorSelector,SLOT(setEnabled(bool)));
+ addRowSpacer(0,4,0,4);
+}
+
+KviTimestampOptionsWidget::~KviTimestampOptionsWidget()
+{
+}
+
+void KviTimestampOptionsWidget::enableDisableTimestampSelector(bool)
+{
+ m_pTimestampColorSelector->setEnabled(m_pUseTimestampSelector->isChecked() && m_pSpecialTimestampColorSelector->isChecked());
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+KviStandardColorsOptionsWidget::KviStandardColorsOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"stdcolors")
+{
+ createLayout(5,4);
+
+ addColorSelector(0,0,0,0,"0:",&(KVI_OPTION_MIRCCOLOR(0)));
+ addColorSelector(1,0,1,0,"1:",&(KVI_OPTION_MIRCCOLOR(1)));
+ addColorSelector(2,0,2,0,"2:",&(KVI_OPTION_MIRCCOLOR(2)));
+ addColorSelector(3,0,3,0,"3:",&(KVI_OPTION_MIRCCOLOR(3)));
+ addColorSelector(0,1,0,1,"4:",&(KVI_OPTION_MIRCCOLOR(4)));
+ addColorSelector(1,1,1,1,"5:",&(KVI_OPTION_MIRCCOLOR(5)));
+ addColorSelector(2,1,2,1,"6:",&(KVI_OPTION_MIRCCOLOR(6)));
+ addColorSelector(3,1,3,1,"7:",&(KVI_OPTION_MIRCCOLOR(7)));
+ addColorSelector(0,2,0,2,"8:",&(KVI_OPTION_MIRCCOLOR(8)));
+ addColorSelector(1,2,1,2,"9:",&(KVI_OPTION_MIRCCOLOR(9)));
+ addColorSelector(2,2,2,2,"10:",&(KVI_OPTION_MIRCCOLOR(10)));
+ addColorSelector(3,2,3,2,"11:",&(KVI_OPTION_MIRCCOLOR(11)));
+ addColorSelector(0,3,0,3,"12:",&(KVI_OPTION_MIRCCOLOR(12)));
+ addColorSelector(1,3,1,3,"13:",&(KVI_OPTION_MIRCCOLOR(13)));
+ addColorSelector(2,3,2,3,"14:",&(KVI_OPTION_MIRCCOLOR(14)));
+ addColorSelector(3,3,3,3,"15:",&(KVI_OPTION_MIRCCOLOR(15)));
+
+ addRowSpacer(0,4,3,4);
+
+ layout()->setRowStretch(4,1);
+}
+
+KviStandardColorsOptionsWidget::~KviStandardColorsOptionsWidget()
+{
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+KviMessageListView::KviMessageListView(QWidget * par)
+: KviTalListView(par)
+{
+ setItemMargin(2);
+}
+
+KviMessageListView::~KviMessageListView()
+{
+}
+
+
+void KviMessageListView::paintEmptyAreaInternal(QPainter * p,const QRect &viewportRect,const QRect &painterRect)
+{
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ if(g_pShadedChildGlobalDesktopBackground)
+ {
+ QPoint pnt = viewport()->mapToGlobal(viewportRect.topLeft());
+ p->drawTiledPixmap(painterRect.x(),painterRect.y(),painterRect.width(),painterRect.height(),*g_pShadedChildGlobalDesktopBackground,pnt.x(),pnt.y());
+ } else {
+#endif
+ QPixmap * pix = KVI_OPTION_PIXMAP(KviOption_pixmapIrcViewBackground).pixmap();
+ if(pix)
+ {
+ QPoint pnt = viewportToContents(viewportRect.topLeft());
+ p->fillRect(painterRect.x(),painterRect.y(),painterRect.width(),painterRect.height(),KVI_OPTION_COLOR(KviOption_colorIrcViewBackground));
+ p->drawTiledPixmap(painterRect.x(),painterRect.y(),painterRect.width(),painterRect.height(),*pix,pnt.x(),pnt.y());
+ } else {
+ p->fillRect(painterRect.x(),painterRect.y(),painterRect.width(),painterRect.height(),KVI_OPTION_COLOR(KviOption_colorIrcViewBackground));
+ }
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ }
+#endif
+}
+
+void KviMessageListView::paintEmptyArea(QPainter * p,const QRect &rct)
+{
+ paintEmptyAreaInternal(p,rct,rct);
+ KviTalListView::paintEmptyArea(p,rct);
+}
+
+
+
+
+
+
+KviMessageListViewItem::KviMessageListViewItem(KviTalListView * l,int optId)
+: KviTalListViewItem(l)
+{
+ m_iOptId = optId;
+ setText(0,"WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW");
+ m_pMsgType = new KviMsgType(KVI_OPTION_MSGTYPE(optId));
+ setPixmap(0,*(g_pIconManager->getSmallIcon(0))); // just a dummy one to ensure that the size of the item is at least 20 pixels (16 + 2 * margin)
+}
+
+KviMessageListViewItem::~KviMessageListViewItem()
+{
+ delete m_pMsgType;
+}
+
+void KviMessageListViewItem::paintCell(QPainter * p,const QColorGroup &,int,int w,int)
+{
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ if(g_pShadedChildGlobalDesktopBackground)
+ {
+ QPoint pnt = listView()->viewport()->mapToGlobal(QPoint(int(p->worldMatrix().dx()),int(p->worldMatrix().dy())));
+ p->drawTiledPixmap(0,0,w,height(),*g_pShadedChildGlobalDesktopBackground,pnt.x(),pnt.y());
+ } else {
+#endif
+ QPixmap * pix = KVI_OPTION_PIXMAP(KviOption_pixmapIrcViewBackground).pixmap();
+ if(pix)
+ {
+ QPoint pnt = listView()->viewportToContents(QPoint(int(p->worldMatrix().dx()),int(p->worldMatrix().dy())));
+ p->fillRect(0,0,w,height(),KVI_OPTION_COLOR(KviOption_colorIrcViewBackground));
+ p->drawTiledPixmap(0,0,w,height(),*pix,pnt.x(),pnt.y());
+ } else {
+ p->fillRect(0,0,w,height(),KVI_OPTION_COLOR(KviOption_colorIrcViewBackground));
+ }
+#ifdef COMPILE_PSEUDO_TRANSPARENCY
+ }
+#endif
+
+
+ p->drawPixmap(listView()->itemMargin(),(height() - 16) / 2,*(g_pIconManager->getSmallIcon(m_pMsgType->pixId())));
+ // draw the background
+ if(m_pMsgType->back() < 16)
+ {
+ QColor bColor = KVI_OPTION_MIRCCOLOR(m_pMsgType->back());
+ p->fillRect(22,listView()->itemMargin(),w - 24,height() - (listView()->itemMargin() * 2),bColor);
+ }
+ unsigned char ucFore = m_pMsgType->fore();
+ if(ucFore > 15)ucFore = 0;
+ p->setPen(QPen(KVI_OPTION_MIRCCOLOR(ucFore)));
+ // skip the msgtype prefix
+ QString txt = (g_msgtypeOptionsTable[m_iOptId].name + 7);
+ txt += " (";
+ txt += __tr2qs_no_xgettext(QString::fromUtf8(m_pMsgType->type()));
+ txt += ")";
+ p->drawText(24,listView()->itemMargin(),w - 24,height() - (listView()->itemMargin() * 2),Qt::AlignLeft | Qt::AlignVCenter,txt);
+ if(isSelected())
+ {
+#ifdef COMPILE_USE_QT4
+ QPen pen(KVI_OPTION_COLOR(KviOption_colorIrcViewBackground));
+ pen.setStyle(Qt::DashLine);
+ p->setPen( pen);
+ p->drawRect(0,0,w,height());
+ p->drawRect(1,1,w - 2,height() - 2);
+#else
+
+ p->drawWinFocusRect(0,0,w,height(),KVI_OPTION_COLOR(KviOption_colorIrcViewBackground));
+ p->drawWinFocusRect(1,1,w - 2,height() - 2,KVI_OPTION_COLOR(KviOption_colorIrcViewBackground));
+#endif
+ }
+}
+
+
+KviMessageColorListBoxItem::KviMessageColorListBoxItem(KviTalListBox * b,const QColor &clr,int idx)
+: KviTalListBoxText(b,QString::null)
+{
+ m_clr = clr;
+ m_iClrIdx = idx;
+ if((idx < 0) || (idx > 15))setText(__tr2qs_ctx("Transparent","options"));
+}
+
+KviMessageColorListBoxItem::~KviMessageColorListBoxItem()
+{
+}
+
+void KviMessageColorListBoxItem::paint(QPainter * p)
+{
+ QColor clr;
+
+ const KviTalListBox * lb = (const KviTalListBox *)listBox();
+
+ if((m_iClrIdx >= 0) && (m_iClrIdx <= 15))
+ {
+ clr = lb->isEnabled() ? KVI_OPTION_MIRCCOLOR(m_iClrIdx) : Qt::gray;
+ p->fillRect(0,0,width(lb),height(lb),clr);
+ } else {
+ clr = listBox()->colorGroup().background();
+ KviTalListBoxText::paint(p);
+ }
+#if QT_VERSION >= 300
+ if(isSelected())
+#else
+ if(selected())
+#endif
+ {
+#ifdef COMPILE_USE_QT4
+ QPen pen(clr);
+ pen.setStyle(Qt::DashLine);
+ p->setPen( pen);
+ p->drawRect(0,0,width(lb),height(lb));
+ p->drawRect(1,1,width(lb) - 2,height(lb) - 2);
+ p->drawRect(2,2,width(lb) - 4,height(lb) - 4);
+#else
+ p->drawWinFocusRect(0,0,width(lb),height(lb),clr);
+ p->drawWinFocusRect(1,1,width(lb) - 2,height(lb) - 2,clr);
+ p->drawWinFocusRect(2,2,width(lb) - 4,height(lb) - 4,clr);
+#endif
+ }
+}
+/*
+int KviMessageColorListBoxItem::width(const KviTalListBox * lb) const
+{
+ int w = lb->width();
+ if(w < 30)w = 30;
+ if(w > 150)w = 150;
+ return w;
+}
+
+int KviMessageColorListBoxItem::height(const KviTalListBox *) const
+{
+ return 30;
+}
+*/
+
+/*
+KviIrcColorsOptionsWidget::KviIrcColorsOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"irccolors","options")
+{
+ createLayout(5,4);
+
+ addRowSpacer(0,4,3,4);
+}
+
+KviIrcColorsOptionsWidget::~KviIrcColorsOptionsWidget()
+{
+}
+*/
+
+KviMessageColorsOptionsWidget::KviMessageColorsOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"messages")
+{
+ int i;
+
+ createLayout(2,4);
+
+ m_pLastItem = 0;
+
+
+ m_pListView = new KviMessageListView(this);
+ m_pListView->addColumn(__tr2qs_ctx("Message Type","options"));
+ m_pListView->setAllColumnsShowFocus(true);
+ m_pListView->setSelectionMode(KviTalListView::Single);
+ m_pListView->setFont(KVI_OPTION_FONT(KviOption_fontIrcView));
+ m_pListView->setStaticBackground(true);
+#ifdef COMPILE_USE_QT4
+ m_pListView->viewport()->setBackgroundMode(Qt::NoBackground);
+#else
+ m_pListView->viewport()->setBackgroundMode(QWidget::NoBackground);
+#endif
+
+ addWidgetToLayout(m_pListView,0,0,2,0);
+
+ KviTalVBox * box = new KviTalVBox(this);
+ addWidgetToLayout(box,3,0,3,0);
+
+ QLabel * l = new QLabel(__tr2qs_ctx("Background:","options"),box);
+
+ m_pBackListBox = new KviTalListBox(box);
+ m_pBackItems[16] = new KviMessageColorListBoxItem(m_pBackListBox,Qt::gray,KVI_TRANSPARENT);
+ for(i=0;i<16;i++)
+ {
+ m_pBackItems[i] = new KviMessageColorListBoxItem(m_pBackListBox,KVI_OPTION_MIRCCOLOR(i),i);
+ }
+
+ l = new QLabel(__tr2qs_ctx("Foreground:","options"),box);
+
+ m_pForeListBox = new KviTalListBox(box);
+ for(i=0;i<16;i++)
+ {
+ m_pForeItems[i] = new KviMessageColorListBoxItem(m_pForeListBox,KVI_OPTION_MIRCCOLOR(i),i);
+ }
+
+ l = new QLabel(__tr2qs_ctx("Alert level:","options"),box);
+
+ m_pLevelListBox = new KviTalListBox(box);
+ KviTalListBoxText * lbt;
+ for(i=0;i<6;i++)
+ {
+ QString tmpn;
+ tmpn.setNum(i);
+ lbt = new KviTalListBoxText(m_pLevelListBox,tmpn);
+ }
+
+ m_pIconButton = new KviStyledToolButton(box);
+ connect(m_pIconButton,SIGNAL(clicked()),this,SLOT(iconButtonClicked()));
+
+ m_pIconPopup = new KviTalPopupMenu(this);
+ KviIconWidget * iw = new KviIconWidget(m_pIconPopup);
+ connect(iw,SIGNAL(selected(int)),this,SLOT(newIconSelected(int)));
+ m_pIconPopup->insertItem(iw);
+
+
+ m_pEnableLogging = new KviStyledCheckBox(__tr2qs_ctx("Log this","options"),box);
+
+ KviTalHBox * h = new KviTalHBox(this);
+ addWidgetToLayout(h,0,1,3,1);
+ QPushButton * b = new QPushButton(__tr2qs_ctx("Load From...","options"),h);
+ connect(b,SIGNAL(clicked()),this,SLOT(load()));
+ b = new QPushButton(__tr2qs_ctx("Save As...","options"),h);
+ connect(b,SIGNAL(clicked()),this,SLOT(save()));
+
+
+ KviMessageListViewItem * it;
+
+ for(i=0;i<KVI_NUM_MSGTYPE_OPTIONS;i++)
+ {
+ it = new KviMessageListViewItem(m_pListView,i);
+ }
+
+ layout()->setRowStretch(0,1);
+ layout()->setColStretch(0,1);
+
+ connect(m_pListView,SIGNAL(selectionChanged(KviTalListViewItem *)),this,SLOT(itemChanged(KviTalListViewItem *)));
+ connect(m_pForeListBox,SIGNAL(selectionChanged(KviTalListBoxItem *)),this,SLOT(colorChanged(KviTalListBoxItem *)));
+ connect(m_pBackListBox,SIGNAL(selectionChanged(KviTalListBoxItem *)),this,SLOT(colorChanged(KviTalListBoxItem *)));
+
+ itemChanged(0);
+}
+
+KviMessageColorsOptionsWidget::~KviMessageColorsOptionsWidget()
+{
+}
+
+void KviMessageColorsOptionsWidget::newIconSelected(int iconId)
+{
+ if(!m_pLastItem)return;
+ if(iconId >= KVI_NUM_SMALL_ICONS)return;
+ m_pLastItem->msgType()->setPixId(iconId);
+ m_pIconButton->setIconSet(*(g_pIconManager->getSmallIcon(iconId)));
+ m_pListView->repaintItem(m_pLastItem);
+}
+
+void KviMessageColorsOptionsWidget::saveLastItem()
+{
+ if(!m_pLastItem)return;
+
+ int curIt = m_pForeListBox->currentItem();
+ if(curIt != -1)
+ {
+ //debug("Setting fore %d",curIt);
+ KviMessageColorListBoxItem * fore = (KviMessageColorListBoxItem *)m_pForeListBox->item(curIt);
+ //debug("And is %d",fore);
+ if(fore)m_pLastItem->msgType()->setFore(fore->m_iClrIdx);
+ }
+ curIt = m_pBackListBox->currentItem();
+ if(curIt != -1)
+ {
+ KviMessageColorListBoxItem * back = (KviMessageColorListBoxItem *)m_pBackListBox->item(curIt);
+ if(back)m_pLastItem->msgType()->setBack(back->m_iClrIdx);
+ }
+ m_pLastItem->msgType()->enableLogging(m_pEnableLogging->isChecked());
+ //debug("Updating","options");
+ curIt = m_pLevelListBox->currentItem();
+ if(curIt < 0 || curIt > 5)curIt = 1;
+ m_pLastItem->msgType()->setLevel(curIt);
+ m_pListView->repaintItem(m_pLastItem);
+}
+
+void KviMessageColorsOptionsWidget::itemChanged(KviTalListViewItem * it)
+{
+ //debug("Item changed","options");
+ if(m_pLastItem)saveLastItem();
+
+ m_pLastItem = 0; // do NOT save in this routine
+
+ m_pForeListBox->setEnabled(it);
+ m_pBackListBox->setEnabled(it);
+ m_pEnableLogging->setEnabled(it);
+ m_pIconButton->setEnabled(it);
+ m_pLevelListBox->setEnabled(it);
+
+ if(it)
+ {
+ int back = ((KviMessageListViewItem *)it)->msgType()->back();
+ int fore = ((KviMessageListViewItem *)it)->msgType()->fore();
+ if(fore >= 0 && fore <= 15)
+ {
+ m_pForeListBox->setCurrentItem(m_pForeItems[fore]);
+ }
+ if(back >= 0 && back <= 15)
+ {
+ m_pBackListBox->setCurrentItem(m_pBackItems[back]);
+ } else {
+ m_pBackListBox->setCurrentItem(m_pBackItems[16]);
+ }
+ m_pLevelListBox->setCurrentItem(((KviMessageListViewItem *)it)->msgType()->level());
+ m_pEnableLogging->setChecked(((KviMessageListViewItem *)it)->msgType()->logEnabled());
+ m_pIconButton->setIconSet(*(g_pIconManager->getSmallIcon(((KviMessageListViewItem *)it)->msgType()->pixId())));
+ }
+
+ // Ok...can save from now on
+ m_pLastItem = (KviMessageListViewItem *)it;
+
+}
+
+void KviMessageColorsOptionsWidget::colorChanged(KviTalListBoxItem *)
+{
+ if(m_pLastItem)saveLastItem();
+}
+
+void KviMessageColorsOptionsWidget::iconButtonClicked()
+{
+ m_pIconPopup->popup(QCursor::pos());
+}
+
+void KviMessageColorsOptionsWidget::commit()
+{
+ saveLastItem();
+
+ mergeResetFlag(KviOption_resetUpdateGui);
+
+ KviMessageListViewItem * it = (KviMessageListViewItem *)m_pListView->firstChild();
+ while(it)
+ {
+ KVI_OPTION_MSGTYPE(it->optionId()) = *(it->msgType());
+ it = (KviMessageListViewItem *)(it->nextSibling());
+ }
+
+ KviOptionsWidget::commit();
+}
+
+void KviMessageColorsOptionsWidget::save()
+{
+ QString szName;
+ QString szInit;
+ g_pApp->getLocalKvircDirectory(szInit,KviApp::MsgColors);
+
+ if(KviFileDialog::askForSaveFileName(szName,__tr2qs_ctx("Choose a Filename - KVIrc","options"),szInit))
+ {
+ if(m_pLastItem)saveLastItem();
+
+ KviConfig cfg(szName,KviConfig::Write);
+
+ cfg.setGroup("Messages");
+
+ KviStr tmp;
+
+
+ KviMessageListViewItem * it = (KviMessageListViewItem *)m_pListView->firstChild();
+
+ while(it)
+ {
+ tmp.sprintf("Fore%d",it->optionId());
+ cfg.writeEntry(tmp.ptr(),it->msgType()->fore());
+ tmp.sprintf("Back%d",it->optionId());
+ cfg.writeEntry(tmp.ptr(),it->msgType()->back());
+ tmp.sprintf("Icon%d",it->optionId());
+ cfg.writeEntry(tmp.ptr(),it->msgType()->pixId());
+ tmp.sprintf("Log%d",it->optionId());
+ cfg.writeEntry(tmp.ptr(),it->msgType()->logEnabled());
+ tmp.sprintf("Level%d",it->optionId());
+ cfg.writeEntry(tmp.ptr(),it->msgType()->level());
+ it = (KviMessageListViewItem *)(it->nextSibling());
+ }
+
+ }
+}
+
+//#include <errno.h>
+
+void KviMessageColorsOptionsWidget::load()
+{
+
+ //KviStr szName;
+ QString szName;
+ //KviStr szInit;
+ QString szInit;
+ g_pApp->getLocalKvircDirectory(szInit,KviApp::MsgColors);
+
+#ifndef COMPILE_ON_WINDOWS
+ // symlink local to global
+ //KviStr szGlobal;
+ QString szGlobal;
+ g_pApp->getGlobalKvircDirectory(szGlobal,KviApp::MsgColors);
+ //KviStr szLocal;
+ QString szLocal;
+ g_pApp->getLocalKvircDirectory(szLocal,KviApp::MsgColors,"presets");
+ //debug("SYMLINKING %s to %s",szGlobal.ptr(),szLocal.ptr());
+ //debug("SYMLINK RETURNS %d (%d)",::symlink(szGlobal.ptr(),szLocal.ptr()));
+ //debug("ERRNO (%d)",errno);
+ symlink(szGlobal,szLocal);
+ // FIXME: Do it also on windows...
+#endif
+
+ if(KviFileDialog::askForOpenFileName(szName,__tr2qs_ctx("Choose a Filename - KVIrc ","options"),szInit))
+ {
+
+ itemChanged(0);
+
+
+ KviConfig cfg(szName,KviConfig::Read);
+
+ cfg.setGroup("Messages");
+
+ //KviStr tmp;
+ QString tmp;
+ KviMessageListViewItem * it = (KviMessageListViewItem *)m_pListView->firstChild();
+
+ while(it)
+ {
+ tmp.sprintf("Fore%d",it->optionId());
+ int fore = cfg.readIntEntry(tmp,it->msgType()->fore());
+ if(fore < 0 || fore > 15)fore = 0;
+ it->msgType()->setFore(fore);
+
+ tmp.sprintf("Back%d",it->optionId());
+ int back = cfg.readIntEntry(tmp,it->msgType()->back());
+ if(back < 0 || back > 15)back = KVI_TRANSPARENT;
+ it->msgType()->setBack(back);
+
+ tmp.sprintf("Icon%d",it->optionId());
+ int ico = cfg.readIntEntry(tmp,it->msgType()->pixId());
+ if(ico < 0 || ico >= KVI_NUM_SMALL_ICONS)ico = 0;
+ it->msgType()->setPixId(ico);
+
+ tmp.sprintf("Log%d",it->optionId());
+ bool bLog = cfg.readBoolEntry(tmp,it->msgType()->logEnabled());
+ it->msgType()->enableLogging(bLog);
+
+ tmp.sprintf("Level%d",it->optionId());
+ int iLevel = cfg.readIntEntry(tmp,it->msgType()->level());
+ it->msgType()->setLevel(iLevel);
+
+ m_pListView->repaintItem(it);
+
+ it = (KviMessageListViewItem *)(it->nextSibling());
+ }
+
+ }
+}
+
+#include "m_optw_messages.moc"
diff --git a/src/modules/options/optw_messages.h b/src/modules/options/optw_messages.h
new file mode 100644
index 00000000..7f82a145
--- /dev/null
+++ b/src/modules/options/optw_messages.h
@@ -0,0 +1,186 @@
+#ifndef _OPTW_MESSAGES_H_
+#define _OPTW_MESSAGES_H_
+
+//
+// File : optw_messages.h
+// Creation date : Sat Aug 11 2001 18:11:21 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_optionswidget.h"
+
+#include "kvi_msgtype.h"
+
+#include "kvi_tal_listview.h"
+#include "kvi_tal_listbox.h"
+#include <qcheckbox.h>
+#include <qtoolbutton.h>
+#include "kvi_tal_popupmenu.h"
+
+#define KVI_OPTIONS_WIDGET_ICON_KviMessageOptionsWidget KVI_SMALLICON_MESSAGES
+#define KVI_OPTIONS_WIDGET_NAME_KviMessageOptionsWidget __tr2qs_no_lookup("Text")
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviMessageOptionsWidget __tr2qs_no_lookup("theme,colors,output")
+#define KVI_OPTIONS_WIDGET_GROUP_KviMessageOptionsWidget "theme"
+#define KVI_OPTIONS_WIDGET_CONTAINER_KviMessageOptionsWidget true
+
+class KviMessageOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviMessageOptionsWidget(QWidget * pParent);
+ ~KviMessageOptionsWidget();
+};
+
+
+#define KVI_OPTIONS_WIDGET_ICON_KviPrivmsgOptionsWidget KVI_SMALLICON_RAW
+#define KVI_OPTIONS_WIDGET_NAME_KviPrivmsgOptionsWidget __tr2qs_no_lookup("Message Style")
+#define KVI_OPTIONS_WIDGET_PARENT_KviPrivmsgOptionsWidget KviMessageOptionsWidget
+#define KVI_OPTIONS_WIDGET_PRIORITY_KviPrivmsgOptionsWidget 40
+#define KVI_OPTIONS_WIDGET_GROUP_KviPrivmsgOptionsWidget "theme"
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviPrivmsgOptionsWidget __tr2qs_no_lookup("theme,privmsg,output,format")
+
+class KviPrivmsgOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviPrivmsgOptionsWidget(QWidget * parent);
+ ~KviPrivmsgOptionsWidget();
+};
+
+#define KVI_OPTIONS_WIDGET_ICON_KviTimestampOptionsWidget KVI_SMALLICON_TIME
+#define KVI_OPTIONS_WIDGET_NAME_KviTimestampOptionsWidget __tr2qs_no_lookup("Timestamp")
+#define KVI_OPTIONS_WIDGET_PARENT_KviTimestampOptionsWidget KviMessageOptionsWidget
+#define KVI_OPTIONS_WIDGET_PRIORITY_KviTimestampOptionsWidget 20
+#define KVI_OPTIONS_WIDGET_GROUP_KviTimestampOptionsWidget "theme"
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviTimestampOptionsWidget __tr2qs_no_lookup("time,timestamp")
+
+class KviTimestampOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviTimestampOptionsWidget(QWidget * parent);
+ ~KviTimestampOptionsWidget();
+public:
+ KviBoolSelector * m_pUseTimestampSelector;
+ KviBoolSelector * m_pSpecialTimestampColorSelector;
+ KviMircTextColorSelector * m_pTimestampColorSelector;
+protected slots:
+ void enableDisableTimestampSelector(bool);
+};
+
+#define KVI_OPTIONS_WIDGET_ICON_KviMessageColorsOptionsWidget KVI_SMALLICON_MESSAGES
+#define KVI_OPTIONS_WIDGET_NAME_KviMessageColorsOptionsWidget __tr2qs_no_lookup("Message Colors")
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviMessageColorsOptionsWidget __tr2qs_no_lookup("theme,colors,messages,output")
+#define KVI_OPTIONS_WIDGET_GROUP_KviMessageColorsOptionsWidget "theme"
+#define KVI_OPTIONS_WIDGET_PARENT_KviMessageColorsOptionsWidget KviMessageOptionsWidget
+#define KVI_OPTIONS_WIDGET_PRIORITY_KviMessageColorsOptionsWidget 30
+
+class KviMessageListView : public KviTalListView
+{
+ Q_OBJECT
+public:
+ KviMessageListView(QWidget * par);
+ ~KviMessageListView();
+protected:
+ void paintEmptyAreaInternal(QPainter * p,const QRect &viewportRect,const QRect &painterRect);
+public:
+ void paintEmptyArea(QPainter * p,const QRect &rct);
+};
+
+
+class KviMessageListViewItem : public KviTalListViewItem
+{
+public:
+ KviMessageListViewItem(KviTalListView * l,int optId);
+ ~KviMessageListViewItem();
+private:
+ int m_iOptId;
+ KviMsgType * m_pMsgType;
+public:
+ int optionId(){ return m_iOptId; };
+ KviMsgType * msgType(){ return m_pMsgType; };
+ virtual void paintCell(QPainter * p,const QColorGroup &,int,int,int);
+};
+
+
+class KviMessageColorListBoxItem : public KviTalListBoxText
+{
+public:
+ KviMessageColorListBoxItem(KviTalListBox * b,const QColor & clr,int idx);
+ ~KviMessageColorListBoxItem();
+public:
+ int m_iClrIdx;
+ QColor m_clr;
+public:
+ virtual void paint(QPainter * p);
+ virtual int width(const KviTalListBox * lv) const { return 120; };
+};
+
+
+
+
+class KviMessageColorsOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviMessageColorsOptionsWidget(QWidget * parent);
+ ~KviMessageColorsOptionsWidget();
+public:
+ KviMessageListView * m_pListView;
+ KviTalListBox * m_pForeListBox;
+ KviTalListBox * m_pBackListBox;
+ KviTalListBox * m_pLevelListBox;
+ KviMessageColorListBoxItem * m_pForeItems[16];
+ KviMessageColorListBoxItem * m_pBackItems[17];
+ KviMessageListViewItem * m_pLastItem;
+ QCheckBox * m_pEnableLogging;
+ QToolButton * m_pIconButton;
+ KviTalPopupMenu * m_pIconPopup;
+public:
+ void saveLastItem();
+protected slots:
+ void itemChanged(KviTalListViewItem * it);
+ void colorChanged(KviTalListBoxItem *);
+ void iconButtonClicked();
+ void newIconSelected(int iconId);
+ virtual void commit();
+ virtual void save();
+ virtual void load();
+};
+
+#define KVI_OPTIONS_WIDGET_ICON_KviStandardColorsOptionsWidget KVI_SMALLICON_COLORS
+#define KVI_OPTIONS_WIDGET_NAME_KviStandardColorsOptionsWidget __tr2qs_no_lookup("Color Set")
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviStandardColorsOptionsWidget __tr2qs_no_lookup("theme,colors,messages,output")
+#define KVI_OPTIONS_WIDGET_GROUP_KviStandardColorsOptionsWidget "theme"
+#define KVI_OPTIONS_WIDGET_PRIORITY_KviStandardColorsOptionsWidget 20
+#define KVI_OPTIONS_WIDGET_PARENT_KviStandardColorsOptionsWidget KviMessageOptionsWidget
+
+class KviStandardColorsOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviStandardColorsOptionsWidget(QWidget * par);
+ ~KviStandardColorsOptionsWidget();
+
+};
+
+
+
+
+#endif //!_OPTW_MESSAGES_H_
diff --git a/src/modules/options/optw_nickserv.cpp b/src/modules/options/optw_nickserv.cpp
new file mode 100644
index 00000000..f182dc32
--- /dev/null
+++ b/src/modules/options/optw_nickserv.cpp
@@ -0,0 +1,368 @@
+//=============================================================================
+//
+// File : optw_nickserv.cpp
+// Creation date : Fri Aug 10 2001 03:38:10 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "optw_nickserv.h"
+
+#include <qlayout.h>
+#include "kvi_tal_tooltip.h"
+#include "kvi_tal_listview.h"
+#include <qlineedit.h>
+#include <qpushbutton.h>
+#include <qcheckbox.h>
+#include <qmessagebox.h>
+
+#include "kvi_qstring.h"
+#include "kvi_options.h"
+#include "kvi_locale.h"
+#include "kvi_nickserv.h"
+#include "kvi_ircmask.h"
+
+// kvi_app.cpp
+extern KVIRC_API KviNickServRuleSet * g_pNickServRuleSet;
+
+
+KviNickServRuleEditor::KviNickServRuleEditor(QWidget * par,bool bUseServerMaskField)
+: QDialog(par)
+{
+ setCaption(__tr2qs_ctx("NickServ Authentication Rule","options"));
+
+ QString html_center_begin = "<center>";
+ QString html_center_end = "</center>";
+
+ QGridLayout * gl = new QGridLayout(this,bUseServerMaskField ? 7 : 6,4,10,5);
+
+ QLabel * l = new QLabel(__tr2qs_ctx("Registered NickName","options"),this);
+ gl->addWidget(l,0,0);
+
+ m_pRegisteredNickEdit = new QLineEdit(this);
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pRegisteredNickEdit,html_center_begin + __tr2qs_ctx("Put here the nickname that you have registered with NickServ","options") + html_center_end);
+#endif
+ gl->addMultiCellWidget(m_pRegisteredNickEdit,0,0,1,3);
+
+ l = new QLabel(__tr2qs_ctx("NickServ Mask","options"),this);
+ gl->addWidget(l,1,0);
+
+ m_pNickServMaskEdit = new QLineEdit(this);
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pNickServMaskEdit,
+ html_center_begin + __tr2qs_ctx("This is the mask that NickServ must match to be correctly identified as the NickServ service. " \
+ "This usually will be something like <b>NickServ!service@services.dalnet</b>.<br>" \
+ "You can use wildcards for this field, but generally it is a security flaw. " \
+ "If you're 100%% sure that NO user on the network can use the nickname \"NickServ\", " \
+ "the mask <b>NickServ!*@*</b> may be safe to use in this field.","options") + html_center_end);
+#endif
+ gl->addMultiCellWidget(m_pNickServMaskEdit,1,1,1,3);
+
+ l = new QLabel(__tr2qs_ctx("Message Regexp","options"),this);
+ gl->addWidget(l,2,0);
+
+ m_pMessageRegexpEdit = new QLineEdit(this);
+ gl->addMultiCellWidget(m_pMessageRegexpEdit,2,2,1,3);
+
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pMessageRegexpEdit,
+ html_center_begin + __tr2qs_ctx("This is the simple regular expression that the identification request message " \
+ "from NickServ must match in order to be correctly recognized.<br>" \
+ "The message is usually something like \"To identify yourself please use /ns IDENTIFY password\" " \
+ "and it is sent when the NickServ wants you to authenticate yourself. " \
+ "You can use the * and ? wildcards.","options") + html_center_end);
+#endif
+ l = new QLabel(__tr2qs_ctx("Identify Command","options"),this);
+ gl->addWidget(l,3,0);
+
+ m_pIdentifyCommandEdit = new QLineEdit(this);
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pIdentifyCommandEdit,
+ html_center_begin + __tr2qs_ctx("This is the command that will be executed when NickServ requests authentication " \
+ "for the nickname described in this rule (if the both server and NickServ mask are matched). " \
+ "This usually will be something like <b>msg NickServ identify &lt;yourpassword&gt;</b>.<br>" \
+ "You can use <b>msg -q</b> if you don't want the password echoed on the screen. " \
+ "Please note that there is no leading slash in this command.","options") + html_center_end);
+#endif
+ gl->addMultiCellWidget(m_pIdentifyCommandEdit,3,3,1,3);
+
+
+ int iNextLine = 4;
+
+ if(bUseServerMaskField)
+ {
+ l = new QLabel(__tr2qs_ctx("Server mask","options"),this);
+ gl->addWidget(l,4,0);
+
+ m_pServerMaskEdit = new QLineEdit(this);
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pServerMaskEdit,
+ html_center_begin + __tr2qs_ctx("This is the mask that the current server must match in order " \
+ "for this rule to apply. It can contain * and ? wildcards.<br>Do NOT use simply \"*\" here...","options") + html_center_end);
+#endif
+ gl->addMultiCellWidget(m_pServerMaskEdit,4,4,1,3);
+ iNextLine++;
+ } else {
+ m_pServerMaskEdit = 0;
+ }
+
+
+#ifdef COMPILE_INFO_TIPS
+ l = new QLabel(html_center_begin + __tr2qs_ctx("Hint: Move the mouse cursor over the fields to get help","options") + html_center_end,this);
+#else
+ l = new QLabel("",this);
+#endif
+ l->setMargin(10);
+ gl->addMultiCellWidget(l,iNextLine,iNextLine,0,3);
+
+ iNextLine++;
+
+ QPushButton * p = new QPushButton(__tr2qs_ctx("Cancel","options"),this);
+ p->setMinimumWidth(100);
+ connect(p,SIGNAL(clicked()),this,SLOT(reject()));
+ gl->addWidget(p,iNextLine,2);
+
+ m_pOkButton = new QPushButton(__tr2qs_ctx("OK","options"),this);
+ m_pOkButton->setMinimumWidth(100);
+ m_pOkButton->setDefault(true);
+ connect(m_pOkButton,SIGNAL(clicked()),this,SLOT(okPressed()));
+ gl->addWidget(m_pOkButton,iNextLine,3);
+
+ gl->setColStretch(1,1);
+ gl->setRowStretch(bUseServerMaskField ? 5 : 4,1);
+
+ setMinimumWidth(250);
+}
+
+KviNickServRuleEditor::~KviNickServRuleEditor()
+{
+}
+
+
+
+bool KviNickServRuleEditor::validate()
+{
+ QString s = m_pRegisteredNickEdit->text();
+
+ QString m = __tr2qs_ctx("Invalid NickServ Rule","options");
+ QString o = __tr2qs_ctx("OK","options");
+
+ if(s.isEmpty())
+ {
+ QMessageBox::warning(this,m,__tr2qs_ctx("The Nickname field can't be empty!","options"),o);
+ return false;
+ }
+
+ if(s.find(QChar(' ')) != -1)
+ {
+ QMessageBox::warning(this,m,__tr2qs_ctx("The Nickname field can't contain spaces!","options"),o);
+ return false;
+ }
+
+ s = m_pNickServMaskEdit->text();
+
+ if(s.isEmpty())
+ {
+ QMessageBox::warning(this,m,__tr2qs_ctx("The NickServ mask can't be empty!<br>You must put at least * there.","options"),o);
+ return false;
+ }
+
+ s = m_pMessageRegexpEdit->text();
+
+ if(s.isEmpty())
+ {
+ QMessageBox::warning(this,m,__tr2qs_ctx("The Message Regexp can't be empty!<br>You must put at least * there.","options"),o);
+ return false;
+ }
+
+ s = m_pIdentifyCommandEdit->text();
+
+ if(s.isEmpty())
+ {
+ QMessageBox::warning(this,m,__tr2qs_ctx("The Identify Command can't be empty!","options"),o);
+ return false;
+ }
+
+ return true;
+}
+
+void KviNickServRuleEditor::okPressed()
+{
+ if(!validate())return;
+ accept();
+}
+
+
+bool KviNickServRuleEditor::editRule(KviNickServRule * r)
+{
+ m_pRegisteredNickEdit->setText(r->registeredNick().isEmpty() ? QString("MyNick") : r->registeredNick());
+ m_pNickServMaskEdit->setText(r->nickServMask().isEmpty() ? QString("NickServ!*@*") : r->nickServMask());
+ m_pMessageRegexpEdit->setText(r->messageRegexp().isEmpty() ? QString("*IDENTIFY*") : r->messageRegexp());
+ m_pIdentifyCommandEdit->setText(r->identifyCommand().isEmpty() ? QString("msg -q NickServ IDENTIFY <password>") : r->identifyCommand());
+ if(m_pServerMaskEdit)
+ m_pServerMaskEdit->setText(r->serverMask().isEmpty() ? QString("irc.yourserver.org") : r->serverMask());
+ m_pRegisteredNickEdit->selectAll();
+ if(exec() != QDialog::Accepted)return false;
+ r->setRegisteredNick(m_pRegisteredNickEdit->text());
+ r->setNickServMask(m_pNickServMaskEdit->text());
+ r->setMessageRegexp(m_pMessageRegexpEdit->text());
+ r->setIdentifyCommand(m_pIdentifyCommandEdit->text());
+ if(m_pServerMaskEdit)
+ r->setServerMask(m_pServerMaskEdit->text());
+ return true;
+}
+
+
+
+KviNickServOptionsWidget::KviNickServOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"nickserv_options_widget")
+{
+ createLayout(3,3);
+
+ QGridLayout * gl = layout();
+
+ KviNickServRuleSet * rs = g_pNickServRuleSet;
+ bool bNickServEnabled = rs ? (rs->isEnabled() && !rs->isEmpty()) : false;
+
+ m_pNickServCheck = new KviStyledCheckBox(__tr2qs_ctx("Enable NickServ Identification","options"),this);
+ gl->addMultiCellWidget(m_pNickServCheck,0,0,0,2);
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pNickServCheck,
+ __tr2qs_ctx("This check enables the automatic identification with NickServ","options"));
+#endif
+ m_pNickServCheck->setChecked(bNickServEnabled);
+
+ m_pNickServListView = new KviTalListView(this);
+ m_pNickServListView->setSelectionMode(KviTalListView::Single);
+ m_pNickServListView->setAllColumnsShowFocus(true);
+ m_pNickServListView->addColumn(__tr2qs_ctx("Nickname","options"));
+ m_pNickServListView->addColumn(__tr2qs_ctx("Server mask","options"));
+ m_pNickServListView->addColumn(__tr2qs_ctx("NickServ Mask","options"));
+ m_pNickServListView->addColumn(__tr2qs_ctx("NickServ Request Mask","options"));
+ m_pNickServListView->addColumn(__tr2qs_ctx("Identify Command","options"));
+ connect(m_pNickServListView,SIGNAL(selectionChanged()),this,SLOT(enableDisableNickServControls()));
+
+ gl->addMultiCellWidget(m_pNickServListView,1,1,0,2);
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pNickServListView,
+ __tr2qs_ctx("<center>This is a list of NickServ identification rules. " \
+ "KVIrc will use them to model its automatic interaction with NickServ on all the networks.<br>" \
+ "Please be aware that this feature can cause your NickServ passwords to be stolen " \
+ "if used improperly. Make sure that you fully understand the NickServ authentication protocol.<br>" \
+ "In other words, be sure to know what you're doing.<br>" \
+ "Also note that the password that you provide is stored as <b>PLAIN TEXT</b>.<br>" \
+ "KVIrc supports also per-network NickServ authentication rules that can be " \
+ "created in the \"Advanced...\" network options (accessible from the servers dialog)."
+ "</center>","options"));
+#endif
+
+ m_pAddRuleButton = new QPushButton(__tr2qs_ctx("Add Rule","options"),this);
+ connect(m_pAddRuleButton,SIGNAL(clicked()),this,SLOT(addNickServRule()));
+ gl->addWidget(m_pAddRuleButton,2,0);
+
+ m_pEditRuleButton = new QPushButton(__tr2qs_ctx("Edit Rule","options"),this);
+ connect(m_pEditRuleButton,SIGNAL(clicked()),this,SLOT(editNickServRule()));
+ gl->addWidget(m_pEditRuleButton,2,1);
+
+ m_pDelRuleButton = new QPushButton(__tr2qs_ctx("Delete Rule","options"),this);
+ connect(m_pDelRuleButton,SIGNAL(clicked()),this,SLOT(delNickServRule()));
+ gl->addWidget(m_pDelRuleButton,2,2);
+
+ connect(m_pNickServCheck,SIGNAL(toggled(bool)),this,SLOT(enableDisableNickServControls()));
+
+ if(rs && rs->rules())
+ {
+ KviPointerList<KviNickServRule> * ll = rs->rules();
+ for(KviNickServRule * rule = ll->first();rule;rule = ll->next())
+ {
+ (void)new KviTalListViewItem(m_pNickServListView,rule->registeredNick(),rule->serverMask(),rule->nickServMask(),rule->messageRegexp(),rule->identifyCommand());
+ }
+ }
+
+ enableDisableNickServControls();
+
+ gl->setRowStretch(1,1);
+
+
+}
+
+KviNickServOptionsWidget::~KviNickServOptionsWidget()
+{
+}
+
+void KviNickServOptionsWidget::editNickServRule()
+{
+ KviTalListViewItem * it = m_pNickServListView->currentItem();
+ if(!it)return;
+ KviNickServRule r(it->text(0),it->text(2),it->text(3),it->text(4),it->text(1));
+ KviNickServRuleEditor ed(this,true);
+ if(ed.editRule(&r))
+ {
+ it->setText(0,r.registeredNick());
+ it->setText(1,r.serverMask());
+ it->setText(2,r.nickServMask());
+ it->setText(3,r.messageRegexp());
+ it->setText(4,r.identifyCommand());
+ }
+}
+
+void KviNickServOptionsWidget::addNickServRule()
+{
+ KviNickServRule r;
+ KviNickServRuleEditor ed(this,true);
+ if(ed.editRule(&r))
+ (void)new KviTalListViewItem(m_pNickServListView,r.registeredNick(),r.serverMask(),r.nickServMask(),r.messageRegexp(),r.identifyCommand());
+}
+
+void KviNickServOptionsWidget::delNickServRule()
+{
+ KviTalListViewItem * it = m_pNickServListView->currentItem();
+ if(!it)return;
+ delete it;
+ enableDisableNickServControls();
+}
+
+void KviNickServOptionsWidget::enableDisableNickServControls()
+{
+ bool bEnabled = m_pNickServCheck->isChecked();
+ m_pNickServListView->setEnabled(bEnabled);
+ m_pAddRuleButton->setEnabled(bEnabled);
+ bEnabled = bEnabled && (m_pNickServListView->childCount() > 0) && m_pNickServListView->currentItem();
+ m_pDelRuleButton->setEnabled(bEnabled);
+ m_pEditRuleButton->setEnabled(bEnabled);
+}
+
+void KviNickServOptionsWidget::commit()
+{
+ g_pNickServRuleSet->clear();
+ if(m_pNickServListView->childCount() > 0)
+ {
+ g_pNickServRuleSet->setEnabled(m_pNickServCheck->isChecked());
+ KviTalListViewItem * it = m_pNickServListView->firstChild();
+ while(it)
+ {
+ g_pNickServRuleSet->addRule(KviNickServRule::createInstance(it->text(0),it->text(2),it->text(3),it->text(4),it->text(1)));
+ it = it->nextSibling();
+ }
+ }
+ KviOptionsWidget::commit();
+}
+
+#include "m_optw_nickserv.moc"
diff --git a/src/modules/options/optw_nickserv.h b/src/modules/options/optw_nickserv.h
new file mode 100644
index 00000000..b9e41e90
--- /dev/null
+++ b/src/modules/options/optw_nickserv.h
@@ -0,0 +1,89 @@
+#ifndef _OPTW_NICKSERV_H_
+#define _OPTW_NICKSERV_H_
+
+//=============================================================================
+//
+// File : optw_nickserv.h
+// Creation date : Fri Aug 10 2001 03:37:21 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+
+#include "kvi_settings.h"
+#include "kvi_optionswidget.h"
+
+#include <qdialog.h>
+
+#define KVI_OPTIONS_WIDGET_ICON_KviNickServOptionsWidget KVI_SMALLICON_NICKSERV
+#define KVI_OPTIONS_WIDGET_NAME_KviNickServOptionsWidget __tr2qs_no_lookup("NickServ")
+#define KVI_OPTIONS_WIDGET_PARENT_KviNickServOptionsWidget KviToolsOptionsWidget
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviNickServOptionsWidget __tr2qs_no_lookup("authentication,identify")
+#define KVI_OPTIONS_WIDGET_PRIORITY_KviNickServOptionsWidget 10000
+//#define KVI_OPTIONS_WIDGET_HIDDEN_KviNickServOptionsWidget true
+
+class QLineEdit;
+class QPushButton;
+class KviNickServRule;
+class KviTalListView;
+class QCheckBox;
+
+class KviNickServRuleEditor : public QDialog
+{
+ Q_OBJECT
+public:
+ KviNickServRuleEditor(QWidget * par,bool bUseServerMaskField = false);
+ ~KviNickServRuleEditor();
+protected:
+ QLineEdit * m_pRegisteredNickEdit;
+ QLineEdit * m_pNickServMaskEdit;
+ QLineEdit * m_pMessageRegexpEdit;
+ QLineEdit * m_pIdentifyCommandEdit;
+ QLineEdit * m_pServerMaskEdit;
+ QPushButton * m_pOkButton;
+public:
+ bool editRule(KviNickServRule * r);
+protected:
+ bool validate();
+protected slots:
+ void okPressed();
+};
+
+class KviNickServOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviNickServOptionsWidget(QWidget * parent);
+ ~KviNickServOptionsWidget();
+protected:
+ KviTalListView * m_pNickServListView;
+ QCheckBox * m_pNickServCheck;
+ QPushButton * m_pAddRuleButton;
+ QPushButton * m_pDelRuleButton;
+ QPushButton * m_pEditRuleButton;
+protected slots:
+ void enableDisableNickServControls();
+ void addNickServRule();
+ void delNickServRule();
+ void editNickServRule();
+public:
+ virtual void commit();
+};
+
+#endif //!_OPTW_NICKSERV_H_
diff --git a/src/modules/options/optw_notify.cpp b/src/modules/options/optw_notify.cpp
new file mode 100644
index 00000000..6ee5dc05
--- /dev/null
+++ b/src/modules/options/optw_notify.cpp
@@ -0,0 +1,134 @@
+//
+// File : optw_notify.cpp
+// Creation date : Sun Oct 28 15:11:29 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "optw_notify.h"
+
+#include <qlayout.h>
+#include "kvi_settings.h"
+#include "kvi_options.h"
+#include "kvi_locale.h"
+
+
+//#warning "Info tips"
+
+
+KviNotifyOptionsWidget::KviNotifyOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"notify_options_widget")
+{
+ createLayout(5,1);
+
+ KviBoolSelector * b = addBoolSelector(0,0,0,0,__tr2qs_ctx("Use online notify list","options"),KviOption_boolUseNotifyList);
+ KviTalGroupBox *g = addGroupBox(0,1,0,1,1,Qt::Horizontal,__tr2qs_ctx("Configuration","options"));
+ connect(b,SIGNAL(toggled(bool)),g,SLOT(setEnabled(bool)));
+
+ connect(b,
+ SIGNAL(toggled(bool)),
+ addBoolSelector(g,__tr2qs_ctx("Show notifications in active window","options"),
+ KviOption_boolNotifyListChangesToActiveWindow,KVI_OPTION_BOOL(KviOption_boolUseNotifyList)),
+ SLOT(setEnabled(bool)));
+ connect(b,
+ SIGNAL(toggled(bool)),
+ addBoolSelector(g,__tr2qs_ctx("Flash window when users are going online","options"),
+ KviOption_boolFlashWindowOnNotifyOnLine,KVI_OPTION_BOOL(KviOption_boolUseNotifyList)),
+ SLOT(setEnabled(bool)));
+ connect(b,
+ SIGNAL(toggled(bool)),
+ addBoolSelector(g,__tr2qs_ctx("Popup notifier when users are going online","options"),
+ KviOption_boolPopupNotifierOnNotifyOnLine,KVI_OPTION_BOOL(KviOption_boolUseNotifyList)),
+ SLOT(setEnabled(bool)));
+
+ g = addGroupBox(0,2,0,2,1,Qt::Horizontal,__tr2qs_ctx("Advanced configuration","options"));
+ connect(b,SIGNAL(toggled(bool)),g,SLOT(setEnabled(bool)));
+
+ connect(b,
+ SIGNAL(toggled(bool)),
+ addBoolSelector(g,__tr2qs_ctx("Check USERHOST for online users","options"),
+ KviOption_boolNotifyListSendUserhostForOnlineUsers,KVI_OPTION_BOOL(KviOption_boolUseNotifyList)),
+ SLOT(setEnabled(bool)));
+ connect(b,
+ SIGNAL(toggled(bool)),
+ addBoolSelector(g,__tr2qs_ctx("Use \"smart\" notify list manager","options"),
+ KviOption_boolUseIntelligentNotifyListManager,KVI_OPTION_BOOL(KviOption_boolUseNotifyList)),
+ SLOT(setEnabled(bool)));
+ connect(b,
+ SIGNAL(toggled(bool)),
+ addBoolSelector(g,__tr2qs_ctx("Use the WATCH method if available","options"),
+ KviOption_boolUseWatchListIfAvailable,KVI_OPTION_BOOL(KviOption_boolUseNotifyList)),
+ SLOT(setEnabled(bool)));
+ connect(b,
+ SIGNAL(toggled(bool)),
+ addUIntSelector(g,__tr2qs_ctx("Check interval (in seconds)","options"),
+ KviOption_uintNotifyListCheckTimeInSecs,
+ 5,3600,180,KVI_OPTION_BOOL(KviOption_boolUseNotifyList)),
+ SLOT(setEnabled(bool)));
+ connect(b,
+ SIGNAL(toggled(bool)),
+ addUIntSelector(g,__tr2qs_ctx("ISON delay (in seconds)","options"),
+ KviOption_uintNotifyListIsOnDelayTimeInSecs,
+ 5,180,6,KVI_OPTION_BOOL(KviOption_boolUseNotifyList)),
+ SLOT(setEnabled(bool)));
+ connect(b,
+ SIGNAL(toggled(bool)),
+ addUIntSelector(g,__tr2qs_ctx("USERHOST delay (in seconds)","options"),
+ KviOption_uintNotifyListUserhostDelayTimeInSecs,
+ 5,180,6,KVI_OPTION_BOOL(KviOption_boolUseNotifyList)),
+ SLOT(setEnabled(bool)));
+
+ addLabel(0,3,0,3,__tr2qs_ctx("<p><b>Note:</b><br>The notify list is managed using the \"Registered Users\" settings.</p>","options"));
+ addRowSpacer(0,4,0,4);
+}
+
+KviNotifyOptionsWidget::~KviNotifyOptionsWidget()
+{
+}
+
+
+
+
+KviNotifierOptionsWidget::KviNotifierOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"notifier_options_widget")
+{
+ createLayout(3,1);
+
+ KviBoolSelector * b = addBoolSelector(0,0,0,0,__tr2qs_ctx("Forcibly and completely disable the notifier","options"),KviOption_boolForciblyDisableNotifier);
+#ifdef COMPILE_INFO_TIPS
+ QString tip = "<center>";
+ tip += __tr2qs_ctx("This is an option for the impatient: it allows to forcibly and permanently disable " \
+ "the notifier window. Please note that if this option is activated then " \
+ "the notifier will NOT popup even if all the other options around specify " \
+ "to use it in response to particular events. Also note that this option " \
+ "will make all the /notifier.* commands fail silently.","options");
+ tip += "</center>";
+ mergeTip(b,tip);
+#endif
+ addBoolSelector(0,1,0,1,__tr2qs_ctx("Disable notifier window flashing","options"),KviOption_boolDisableNotifierFlashing);
+ addBoolSelector(0,2,0,2,__tr2qs_ctx("Disable notifier window fade effect","options"),KviOption_boolDisableNotifierFadein);
+
+ addRowSpacer(0,3,0,3);
+}
+
+KviNotifierOptionsWidget::~KviNotifierOptionsWidget()
+{
+}
+
+
+#include "m_optw_notify.moc"
diff --git a/src/modules/options/optw_notify.h b/src/modules/options/optw_notify.h
new file mode 100644
index 00000000..374ddc21
--- /dev/null
+++ b/src/modules/options/optw_notify.h
@@ -0,0 +1,54 @@
+#ifndef _OPTW_NOTIFY_H_
+#define _OPTW_NOTIFY_H_
+//
+// File : optw_notify.h
+// Creation date : Sun Oct 28 15:11:30 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_optionswidget.h"
+
+#define KVI_OPTIONS_WIDGET_ICON_KviNotifyOptionsWidget KVI_SMALLICON_REGUSERS
+#define KVI_OPTIONS_WIDGET_NAME_KviNotifyOptionsWidget __tr2qs_no_lookup("Contacts")
+#define KVI_OPTIONS_WIDGET_PARENT_KviNotifyOptionsWidget KviToolsOptionsWidget
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviNotifyOptionsWidget __tr2qs_no_lookup("notify,buddy,buddies,friends")
+#define KVI_OPTIONS_WIDGET_MINIMAL_USER_EXPERIENCE_LEVEL_KviNotifyOptionsWidget 2
+
+class KviNotifyOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviNotifyOptionsWidget(QWidget * parent);
+ ~KviNotifyOptionsWidget();
+};
+
+#define KVI_OPTIONS_WIDGET_ICON_KviNotifierOptionsWidget KVI_SMALLICON_ALERT
+#define KVI_OPTIONS_WIDGET_NAME_KviNotifierOptionsWidget __tr2qs_no_lookup("Notifier")
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviNotifierOptionsWidget __tr2qs_no_lookup("popup")
+#define KVI_OPTIONS_WIDGET_PARENT_KviNotifierOptionsWidget KviInterfaceFeaturesOptionsWidget
+
+class KviNotifierOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviNotifierOptionsWidget(QWidget * parent);
+ ~KviNotifierOptionsWidget();
+};
+
+#endif //_OPTW_NOTIFY_H_
diff --git a/src/modules/options/optw_protection.cpp b/src/modules/options/optw_protection.cpp
new file mode 100644
index 00000000..27a0f4b1
--- /dev/null
+++ b/src/modules/options/optw_protection.cpp
@@ -0,0 +1,50 @@
+//=============================================================================
+//
+// File : optw_protection.cpp
+// Creation date : Wed Ott 19 16:15:16 2005 GMT by Grifisx & Noldor
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2005 Grifisx & Noldor
+//
+// 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 opinion) 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.
+//
+//=============================================================================
+
+#include "optw_protection.h"
+
+#include <qlayout.h>
+
+#include "kvi_settings.h"
+#include "kvi_options.h"
+#include "kvi_locale.h"
+
+KviProtectionOptionsWidget::KviProtectionOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"protection_options_widget")
+{
+
+ createLayout(1,1);
+
+ QLabel * l;
+ l = addLabel(0,0,0,0,__tr2qs_ctx("This section contains irc protection tools<br>"\
+ "<p>like<b> flood, ignore, antispam. </b> " \
+ "</p>","options"));
+
+}
+
+KviProtectionOptionsWidget::~KviProtectionOptionsWidget()
+{
+}
+
+#include "m_optw_protection.moc"
diff --git a/src/modules/options/optw_protection.h b/src/modules/options/optw_protection.h
new file mode 100644
index 00000000..5ac37e43
--- /dev/null
+++ b/src/modules/options/optw_protection.h
@@ -0,0 +1,48 @@
+#ifndef _OPTW_PROTECTION_H_
+#define _OPTW_PROTECTION_H_
+
+//=============================================================================
+//
+// File : optw_protection.h
+//
+// This file is part of the KVirc irc client distribution
+// Creation date : Wed Ott 19 16:15:16 2005 GMT by Grifisx & Noldor
+//
+// Copyright (C) 2005 Grifisx & Noldor
+// 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_optionswidget.h"
+#include "kvi_selectors.h"
+
+#define KVI_OPTIONS_WIDGET_ICON_KviProtectionOptionsWidget KVI_SMALLICON_SPY
+#define KVI_OPTIONS_WIDGET_NAME_KviProtectionOptionsWidget __tr2qs_no_lookup("Protection")
+#define KVI_OPTIONS_WIDGET_PARENT_KviProtectionOptionsWidget KviIrcOptionsWidget
+#define KVI_OPTIONS_WIDGET_PRIORITY_KviProtectionOptionsWidget 60000
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviProtectionOptionsWidget __tr2qs_no_lookup("ctcp,flood")
+#define KVI_OPTIONS_WIDGET_CONTAINER_KviProtectionOptionsWidget true
+#define KVI_OPTIONS_WIDGET_NOTCONTAINED_KviProtectionOptionsWidget true
+
+class KviProtectionOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviProtectionOptionsWidget(QWidget * parent);
+ ~KviProtectionOptionsWidget();
+};
+
+#endif //!_OPTW_PROTECTION_H_
diff --git a/src/modules/options/optw_proxy.cpp b/src/modules/options/optw_proxy.cpp
new file mode 100644
index 00000000..523d3c79
--- /dev/null
+++ b/src/modules/options/optw_proxy.cpp
@@ -0,0 +1,367 @@
+//
+// File : optw_proxy.cpp
+// Creation date : Mon Jun 24 2000 22:02:11 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "optw_proxy.h"
+#include "kvi_locale.h"
+#include "kvi_iconmanager.h"
+#include "kvi_proxydb.h"
+#include "kvi_ipeditor.h"
+#include "kvi_netutils.h"
+#include "kvi_settings.h"
+#include "kvi_options.h"
+#include "kvi_styled_controls.h"
+
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qcombobox.h>
+#include <qcheckbox.h>
+#include <kvi_tal_groupbox.h>
+#include "kvi_tal_popupmenu.h"
+#include <qcursor.h>
+#include "kvi_tal_tooltip.h"
+#include <qtoolbutton.h>
+
+
+KviProxyOptionsListViewItem::KviProxyOptionsListViewItem(KviTalListView *parent,const QPixmap &pm,KviProxy * prx)
+: KviTalListViewItem(parent,prx->m_szHostname.ptr())
+{
+ setPixmap(0,pm);
+ m_pProxyData = new KviProxy(*prx);
+}
+
+KviProxyOptionsListViewItem::~KviProxyOptionsListViewItem()
+{
+ delete m_pProxyData;
+}
+
+KviProxyOptionsWidget::KviProxyOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"proxy_options_widget")
+{
+ createLayout(3,2);
+
+ addBoolSelector(0,0,1,0,__tr2qs_ctx("Use proxy","options"),KviOption_boolUseProxyHost);
+
+ m_pListView = new KviTalListView(this);
+ addWidgetToLayout(m_pListView,0,1,0,1);
+ m_pListView->addColumn(__tr2qs_ctx("Proxy","options"));
+ m_pListView->setRootIsDecorated(true);
+ m_pListView->setAllColumnsShowFocus(true);
+ m_pListView->setSelectionMode(KviTalListView::Single);
+
+ connect(m_pListView,SIGNAL(selectionChanged(KviTalListViewItem *)),
+ this,SLOT(listViewItemSelectionChanged(KviTalListViewItem *)));
+ connect(m_pListView,SIGNAL(rightButtonPressed(KviTalListViewItem *,const QPoint &,int)),
+ this,SLOT(listViewRightButtonPressed(KviTalListViewItem *,const QPoint &,int)));
+
+#ifdef COMPILE_INFO_TIPS
+ QString tiptxt = __tr2qs_ctx("<center>This is the list of available proxy servers.<br>" \
+ "Right-click on the list to add or remove proxies.</center>","options");
+ mergeTip(m_pListView,tiptxt);
+ mergeTip(m_pListView->viewport(),tiptxt);
+#endif
+
+ KviTalVBox * vbox = new KviTalVBox(this);
+ addWidgetToLayout(vbox,1,1,1,1);
+
+ QToolButton * tb = new KviStyledToolButton(vbox);
+ tb->setPixmap(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_PROXY)));
+ tb->setAutoRaise(true);
+ connect(tb,SIGNAL(clicked()),this,SLOT(newProxy()));
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(tb,__tr2qs_ctx("New Proxy","options"));
+#endif
+
+ tb = new KviStyledToolButton(vbox);
+ tb->setPixmap(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CUT)));
+ //tb->setEnabled(false);
+ tb->setAutoRaise(true);
+ connect(tb,SIGNAL(clicked()),this,SLOT(removeCurrent()));
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(tb,__tr2qs_ctx("Remove Proxy","options"));
+#endif
+
+ QFrame * lll = new QFrame(vbox);
+ vbox->setStretchFactor(lll,100);
+
+
+ KviTalGroupBox * gbox = addGroupBox(0,2,1,2,2,Qt::Horizontal,__tr2qs_ctx("Configuration","options"),this);
+ //QGridLayout * gl = new QGridLayout(gbox->layout());
+ //gl->setMargin(2);
+ //gl->setSpacing(4);
+
+ m_pProxyLabel = new QLabel(__tr2qs_ctx("Proxy:","options"),gbox);
+
+ m_pProxyEdit = new QLineEdit(gbox);
+
+ m_pPortLabel = new QLabel(__tr2qs_ctx("Port:","options"),gbox);
+
+ m_pPortEdit = new QLineEdit(gbox);
+
+ m_pIpLabel = new QLabel(__tr2qs_ctx("IP address:","options"),gbox);
+
+ m_pIpEditor = new KviIpEditor(gbox,KviIpEditor::IpV4);
+
+ m_pUserLabel = new QLabel(__tr2qs_ctx("Username:","options"),gbox);
+
+ m_pUserEdit = new QLineEdit(gbox);
+
+ m_pPassLabel = new QLabel(__tr2qs_ctx("Password:","options"),gbox);
+
+ m_pPassEdit = new QLineEdit(gbox);
+
+ m_pProtocolLabel = new QLabel(__tr2qs_ctx("Protocol:","options"),gbox);
+
+ m_pProtocolBox = new QComboBox(false,gbox);
+
+ QStringList l;
+ KviProxy::getSupportedProtocolNames(l);
+
+ m_pProtocolBox->insertStringList(l);
+
+ m_pIpV6Check = new KviStyledCheckBox(__tr2qs_ctx("Use IPv6 protocol","options"),gbox);
+ connect(m_pIpV6Check,SIGNAL(toggled(bool)),this,SLOT(ipV6CheckToggled(bool)));
+#ifndef COMPILE_IPV6_SUPPORT
+ m_pIpV6Check->setEnabled(false);
+#endif
+
+ m_pLastEditedItem = 0;
+
+ fillProxyList();
+
+ layout()->setRowStretch(0,1);
+ layout()->setColStretch(0,1);
+
+ m_pContextPopup = new KviTalPopupMenu(this);
+
+
+}
+
+KviProxyOptionsWidget::~KviProxyOptionsWidget()
+{
+}
+
+
+void KviProxyOptionsWidget::ipV6CheckToggled(bool bEnabled)
+{
+ m_pIpEditor->setAddressType(bEnabled ? KviIpEditor::IpV6 : KviIpEditor::IpV4);
+}
+
+void KviProxyOptionsWidget::fillProxyList()
+{
+ KviProxyOptionsListViewItem * prx;
+
+ KviPointerList<KviProxy> * l = g_pProxyDataBase->proxyList();
+
+ for(KviProxy * p = l->first();p;p = l->next())
+ {
+ prx = new KviProxyOptionsListViewItem(m_pListView,*(g_pIconManager->getSmallIcon(KVI_SMALLICON_PROXY)),p);
+ if(p == g_pProxyDataBase->currentProxy())
+ {
+ m_pListView->setSelected(prx,true);
+ m_pListView->ensureItemVisible(prx);
+ }
+ }
+ if(!(g_pProxyDataBase->currentProxy()))listViewItemSelectionChanged(0);
+}
+
+void KviProxyOptionsWidget::listViewItemSelectionChanged(KviTalListViewItem *it)
+{
+ if(m_pLastEditedItem)saveLastItem();
+ m_pLastEditedItem = (KviProxyOptionsListViewItem *)it;
+
+ m_pProxyLabel->setEnabled(m_pLastEditedItem);
+ m_pProxyEdit->setEnabled(m_pLastEditedItem);
+ m_pIpLabel->setEnabled(m_pLastEditedItem);
+ m_pIpEditor->setEnabled(m_pLastEditedItem);
+ m_pUserLabel->setEnabled(m_pLastEditedItem);
+ m_pUserEdit->setEnabled(m_pLastEditedItem);
+ m_pPassLabel->setEnabled(m_pLastEditedItem);
+ m_pPassEdit->setEnabled(m_pLastEditedItem);
+ m_pProtocolLabel->setEnabled(m_pLastEditedItem);
+ m_pProtocolBox->setEnabled(m_pLastEditedItem);
+ m_pPortLabel->setEnabled(m_pLastEditedItem);
+ m_pPortEdit->setEnabled(m_pLastEditedItem);
+
+#ifdef COMPILE_IPV6_SUPPORT
+ m_pIpV6Check->setEnabled(m_pLastEditedItem);
+#else
+ m_pIpV6Check->setEnabled(false);
+#endif
+ if(m_pLastEditedItem)
+ {
+ m_pProxyEdit->setText(m_pLastEditedItem->m_pProxyData->m_szHostname.ptr());
+
+ for(int i=0;i<m_pProtocolBox->count();i++)
+ {
+ KviStr txt = m_pProtocolBox->text(i);
+ if(kvi_strEqualCI(m_pLastEditedItem->m_pProxyData->protocolName(),txt.ptr()))
+ {
+ m_pProtocolBox->setCurrentItem(i);
+ break;
+ }
+ }
+
+#ifdef COMPILE_IPV6_SUPPORT
+ m_pIpV6Check->setChecked(m_pLastEditedItem->m_pProxyData->isIpV6());
+ m_pIpEditor->setAddressType(m_pLastEditedItem->m_pProxyData->isIpV6() ? KviIpEditor::IpV6 : KviIpEditor::IpV4);
+#else
+ m_pIpV6Check->setChecked(false);
+ m_pIpEditor->setAddressType(KviIpEditor::IpV4);
+#endif
+
+
+ if(!m_pIpEditor->setAddress(m_pLastEditedItem->m_pProxyData->m_szIp.ptr()))
+ {
+#ifdef COMPILE_IPV6_SUPPORT
+ m_pIpEditor->setAddress(m_pLastEditedItem->m_pProxyData->isIpV6() ? "0:0:0:0:0:0:0:0" : "0.0.0.0");
+#else
+ m_pIpEditor->setAddress("0.0.0.0");
+#endif
+ }
+
+ m_pUserEdit->setText(m_pLastEditedItem->m_pProxyData->m_szUser.ptr());
+ m_pPassEdit->setText(m_pLastEditedItem->m_pProxyData->m_szPass.ptr());
+ KviStr tmp(KviStr::Format,"%u",m_pLastEditedItem->m_pProxyData->m_uPort);
+ m_pPortEdit->setText(tmp.ptr());
+ } else {
+ m_pProxyEdit->setText("");
+ m_pUserEdit->setText("");
+ m_pPassEdit->setText("");
+ m_pPortEdit->setText("");
+ m_pIpEditor->setAddress("0.0.0.0");
+ m_pIpV6Check->setEnabled(false);
+ }
+}
+
+
+void KviProxyOptionsWidget::saveLastItem()
+{
+ if(m_pLastEditedItem)
+ {
+ KviStr tmp = m_pProxyEdit->text();
+ if(tmp.isEmpty())tmp = "irc.unknown.net";
+ m_pLastEditedItem->setText(0,tmp.ptr());
+ m_pLastEditedItem->m_pProxyData->m_szHostname = tmp;
+#ifdef COMPILE_IPV6_SUPPORT
+ m_pLastEditedItem->m_pProxyData->m_bIsIpV6 = m_pIpV6Check->isChecked();
+#else
+ m_pLastEditedItem->m_pProxyData->m_bIsIpV6 = false;
+#endif
+ m_pLastEditedItem->m_pProxyData->m_szIp = "";
+ KviStr tmpAddr = m_pIpEditor->address();
+
+ if(!m_pIpEditor->hasEmptyFields())
+ {
+#ifdef COMPILE_IPV6_SUPPORT
+ if(m_pIpV6Check->isChecked())
+ {
+ if((!kvi_strEqualCI(tmpAddr.ptr(),"0:0:0:0:0:0:0:0")) &&
+ kvi_isValidStringIp_V6(tmpAddr.ptr()))
+ {
+ m_pLastEditedItem->m_pProxyData->m_szIp = tmpAddr;
+ }
+ } else {
+#endif
+ if((!kvi_strEqualCI(tmpAddr.ptr(),"0.0.0.0")) &&
+ kvi_isValidStringIp(tmpAddr.ptr()))
+ {
+ m_pLastEditedItem->m_pProxyData->m_szIp = tmpAddr;
+ }
+#ifdef COMPILE_IPV6_SUPPORT
+ }
+#endif
+ }
+
+ m_pLastEditedItem->m_pProxyData->m_szPass = m_pPassEdit->text();
+ m_pLastEditedItem->m_pProxyData->m_szUser = m_pUserEdit->text();
+ tmp = m_pPortEdit->text();
+ bool bOk;
+ kvi_u32_t uPort = tmp.toUInt(&bOk);
+ if(!bOk)uPort = 1080;
+ m_pLastEditedItem->m_pProxyData->m_uPort = uPort;
+// m_pLastEditedItem->m_pProxyData->m_bSocksV5 = m_pSocks5Check->isChecked();
+ tmp = m_pProtocolBox->currentText();
+ m_pLastEditedItem->m_pProxyData->setNamedProtocol(tmp.ptr());
+ }
+}
+
+void KviProxyOptionsWidget::commit()
+{
+ saveLastItem();
+ g_pProxyDataBase->clear();
+ KviProxyOptionsListViewItem * it = (KviProxyOptionsListViewItem *)m_pListView->firstChild();
+ while(it)
+ {
+ KviStr tmp = it->text(0);
+ if(tmp.hasData())
+ {
+ KviProxy * prx = new KviProxy(*(((KviProxyOptionsListViewItem *)it)->m_pProxyData));
+ g_pProxyDataBase->insertProxy(prx);
+
+ if(it == m_pLastEditedItem)g_pProxyDataBase->setCurrentProxy(prx);
+ }
+ it = (KviProxyOptionsListViewItem *)it->nextSibling();
+ }
+
+ if(g_pProxyDataBase->currentProxy() == 0)
+ {
+ g_pProxyDataBase->setCurrentProxy(g_pProxyDataBase->proxyList()->first());
+ }
+
+ KviOptionsWidget::commit();
+}
+
+void KviProxyOptionsWidget::listViewRightButtonPressed(KviTalListViewItem *it,const QPoint &pnt,int col)
+{
+ m_pContextPopup->clear();
+ m_pContextPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_PROXY)),__tr2qs_ctx("&New Proxy","options"),this,SLOT(newProxy()));
+ m_pContextPopup->setItemEnabled(m_pContextPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CUT)),__tr2qs_ctx("Re&move Proxy","options"),this,SLOT(removeCurrent())),it);
+ m_pContextPopup->popup(QCursor::pos());
+}
+
+void KviProxyOptionsWidget::newProxy()
+{
+ KviProxy prx;
+ KviProxyOptionsListViewItem * it = new KviProxyOptionsListViewItem(m_pListView,*(g_pIconManager->getSmallIcon(KVI_SMALLICON_PROXY)),&prx);
+ m_pListView->setSelected(it,true);
+ m_pListView->ensureItemVisible(it);
+}
+
+
+void KviProxyOptionsWidget::removeCurrent()
+{
+ if(m_pLastEditedItem)
+ {
+ delete m_pLastEditedItem;
+ m_pLastEditedItem = 0;
+ KviTalListViewItem * it = m_pListView->firstChild();
+ if(it)
+ {
+ m_pListView->setSelected(it,true);
+ m_pListView->ensureItemVisible(it);
+ } else {
+ listViewItemSelectionChanged(0);
+ }
+ }
+}
+
+#include "m_optw_proxy.moc"
diff --git a/src/modules/options/optw_proxy.h b/src/modules/options/optw_proxy.h
new file mode 100644
index 00000000..a6f18ada
--- /dev/null
+++ b/src/modules/options/optw_proxy.h
@@ -0,0 +1,94 @@
+#ifndef _OPTW_PROXY_H_
+#define _OPTW_PROXY_H_
+
+//
+// File : optw_proxy.h
+// Creation date : Mon Jun 24 2000 21:58:25 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_optionswidget.h"
+#include "kvi_tal_listview.h"
+
+
+class KviProxy;
+class KviProxyDataBase;
+
+extern KVIRC_API KviProxyDataBase * g_pProxyDataBase;
+
+class KviProxyOptionsListViewItem : public KviTalListViewItem
+{
+public:
+ KviProxyOptionsListViewItem(KviTalListView *parent,const QPixmap &pm,KviProxy * prx);
+ ~KviProxyOptionsListViewItem();
+public:
+ KviProxy * m_pProxyData;
+};
+
+class QLabel;
+class QLineEdit;
+class KviIpEditor;
+class QCheckBox;
+class KviTalPopupMenu;
+class QComboBox;
+
+#define KVI_OPTIONS_WIDGET_ICON_KviProxyOptionsWidget KVI_SMALLICON_PROXY
+#define KVI_OPTIONS_WIDGET_NAME_KviProxyOptionsWidget __tr2qs_no_lookup("Proxy Hosts")
+#define KVI_OPTIONS_WIDGET_PARENT_KviProxyOptionsWidget KviConnectionOptionsWidget
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviProxyOptionsWidget __tr2qs_no_lookup("connection,servers")
+#define KVI_OPTIONS_WIDGET_PRIORITY_KviProxyOptionsWidget 70000
+
+class KviProxyOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviProxyOptionsWidget(QWidget * parent);
+ ~KviProxyOptionsWidget();
+protected:
+ KviTalListView * m_pListView;
+ QLabel * m_pProxyLabel;
+ QLineEdit * m_pProxyEdit;
+ QLabel * m_pIpLabel;
+ KviIpEditor * m_pIpEditor;
+ QLabel * m_pUserLabel;
+ QLineEdit * m_pUserEdit;
+ QLabel * m_pPassLabel;
+ QLineEdit * m_pPassEdit;
+ QLabel * m_pPortLabel;
+ QLineEdit * m_pPortEdit;
+ QLabel * m_pProtocolLabel;
+ QComboBox * m_pProtocolBox;
+ KviTalPopupMenu * m_pContextPopup;
+ QCheckBox * m_pIpV6Check;
+ KviProxyOptionsListViewItem * m_pLastEditedItem;
+private:
+
+ void fillProxyList();
+ void saveLastItem();
+protected slots:
+ void listViewItemSelectionChanged(KviTalListViewItem *it);
+ void listViewRightButtonPressed(KviTalListViewItem *it,const QPoint &pnt,int col);
+ void newProxy();
+ void removeCurrent();
+ void ipV6CheckToggled(bool bEnabled);
+public:
+ virtual void commit();
+};
+
+#endif //!_OPTW_PROXY_H_
diff --git a/src/modules/options/optw_query.cpp b/src/modules/options/optw_query.cpp
new file mode 100644
index 00000000..d0026c6e
--- /dev/null
+++ b/src/modules/options/optw_query.cpp
@@ -0,0 +1,115 @@
+//
+// File : optw_query.cpp
+// Creation date : Mon Oct 29 15:37:16 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+#include "optw_query.h"
+
+#include <qlayout.h>
+
+#include "kvi_options.h"
+#include "kvi_locale.h"
+#include "kvi_settings.h"
+
+
+#ifdef COMPILE_KDE_SUPPORT
+ #include <kdeversion.h>
+#endif
+
+KviQueryOptionsWidget::KviQueryOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"query_options_widget")
+{
+ createLayout(8,1);
+
+ KviTalGroupBox *g = addGroupBox(0,0,0,0,1,Qt::Horizontal,__tr2qs_ctx("Open Query For","options"));
+ KviBoolSelector *b = addBoolSelector(g, __tr2qs_ctx("Private messages","options"),KviOption_boolCreateQueryOnPrivmsg);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b,
+ __tr2qs_ctx("<center>This option enables query window creation " \
+ "when a private message (PRIVMSG) is received.<br>" \
+ "If you disable this, private messages will " \
+ "be shown in the active window or a common channel.</center>","options"));
+#endif
+
+ b = addBoolSelector(g, __tr2qs_ctx("Private notices","options"),KviOption_boolCreateQueryOnNotice);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b,
+ __tr2qs_ctx("<center>This option enables query window creation " \
+ "when a private notice (NOTICE) is received.<br>" \
+ "If you disable this, private notices will " \
+ "be shown in the active window or a common channel.</center>","options"));
+#endif
+
+
+ b = addBoolSelector(0,1,0,1,__tr2qs_ctx("Always open queries as minimized","options"),KviOption_boolCreateMinimizedQuery);
+
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b,
+ __tr2qs_ctx("<center>This option causes newly created " \
+ "query windows to be immediately minimized.<br>" \
+ "Enable this if you don't like queries " \
+ "popping up while you're typing something in a channel. :D</center>","options"));
+#endif
+
+
+
+ b = addBoolSelector(0,2,0,2, __tr2qs_ctx("Enable target user tracking","options"),KviOption_boolEnableQueryTracing);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b,
+ __tr2qs_ctx("<center>This option will enable target user tracking.<br>" \
+ "Some actions of the target user (e.g. joins and parts) " \
+ "will be displayed in the window.<br></center>","options"));
+#endif
+
+#if defined(COMPILE_ON_WINDOWS) || (defined(COMPILE_KDE_SUPPORT) && (KDE_VERSION_MAJOR >= 3) && (KDE_VERSION_MINOR >= 2))
+ b = addBoolSelector(0,3,0,3,__tr2qs_ctx("Flash system taskbar on new query message","options"),KviOption_boolFlashQueryWindowOnNewMessages);
+ #ifdef COMPILE_INFO_TIPS
+ mergeTip(b,
+ __tr2qs_ctx("<center>This option causes the system taskbar entry for KVIrc to flash when a new query message " \
+ "is received and the KVIrc window is not the active.</center>","options"));
+ #endif
+#endif
+
+ b = addBoolSelector(0,4,0,4, __tr2qs_ctx("Popup notifier on new query message","options"),KviOption_boolPopupNotifierOnNewQueryMessages);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b,
+ __tr2qs_ctx("<center>This option causes a small notifier window to pop up " \
+ "in the low right corner of the screen when a new message is received " \
+ "and the KVIrc window is not active.</center>","options"));
+#endif
+ b = addBoolSelector(0,5,0,5, __tr2qs_ctx("Show information about query target at the top of the query","options"),KviOption_boolShowExtendedInfoInQueryLabel);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b,
+ __tr2qs_ctx("<center>This option enables query window information " \
+ "label. It can show you known information about query target at the top of the window.<br>" \
+ "Uncheck if you think,that it wastes your query space/" \
+ "</center>","options"));
+#endif
+
+ addRowSpacer(0,6,0,6);
+}
+
+KviQueryOptionsWidget::~KviQueryOptionsWidget()
+{
+}
+
+
+#include "m_optw_query.moc"
diff --git a/src/modules/options/optw_query.h b/src/modules/options/optw_query.h
new file mode 100644
index 00000000..bae1c7bc
--- /dev/null
+++ b/src/modules/options/optw_query.h
@@ -0,0 +1,43 @@
+#ifndef _OPTW_QUERY_H_
+#define _OPTW_QUERY_H_
+//
+// File : optw_query.h
+// Creation date : Tue Mar 05 22:31:18 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma@kvirc.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 opinion) 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.
+//
+
+#include "kvi_optionswidget.h"
+
+#define KVI_OPTIONS_WIDGET_ICON_KviQueryOptionsWidget KVI_SMALLICON_QUERY
+#define KVI_OPTIONS_WIDGET_NAME_KviQueryOptionsWidget __tr2qs_no_lookup("Query")
+#define KVI_OPTIONS_WIDGET_PARENT_KviQueryOptionsWidget KviIrcOptionsWidget
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviQueryOptionsWidget __tr2qs_no_lookup("chat")
+#define KVI_OPTIONS_WIDGET_PRIORITY_KviQueryOptionsWidget 80000
+#define KVI_OPTIONS_WIDGET_NOTCONTAINED_KviQueryOptionsWidget true
+
+class KviQueryOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviQueryOptionsWidget(QWidget * parent);
+ ~KviQueryOptionsWidget();
+protected:
+};
+
+#endif //_OPTW_away_H_
diff --git a/src/modules/options/optw_servers.cpp b/src/modules/options/optw_servers.cpp
new file mode 100644
index 00000000..0b50bc78
--- /dev/null
+++ b/src/modules/options/optw_servers.cpp
@@ -0,0 +1,1712 @@
+//=============================================================================
+//
+// File : optw_servers.cpp
+// Creation date : Wed Jun 12 2000 03:29:51 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "optw_servers.h"
+#include "optw_proxy.h"
+#include "kvi_query.h"
+#include "kvi_channel.h"
+#include "kvi_locale.h"
+#include "kvi_iconmanager.h"
+#include "kvi_ircserverdb.h"
+#include "kvi_ipeditor.h"
+#include "kvi_netutils.h"
+#include "kvi_settings.h"
+#include "kvi_filedialog.h"
+#include "kvi_config.h"
+#include "kvi_scripteditor.h"
+#include "kvi_options.h"
+
+#include "kvi_app.h"
+#include "kvi_console.h"
+#include "kvi_ircurl.h"
+#include "kvi_module.h"
+#include "kvi_modulemanager.h"
+#include "kvi_moduleextension.h"
+#include "kvi_msgbox.h"
+#include "kvi_mexserverimport.h"
+#include "kvi_nickserv.h"
+#include "optw_nickserv.h" // for the NickServ rule editor
+#include "kvi_proxydb.h"
+#include "kvi_kvs_script.h"
+#include "kvi_styled_controls.h"
+
+#include <qtoolbutton.h>
+#include <qlineedit.h>
+#include <qcheckbox.h>
+#include "kvi_tal_popupmenu.h"
+#include <qcursor.h>
+#include "kvi_tal_tooltip.h"
+#include <qvalidator.h>
+#include <qmessagebox.h>
+#include "kvi_pointerhashtable.h"
+#include <qcombobox.h>
+#include <qbuttongroup.h>
+#include <qmessagebox.h>
+#include <qinputdialog.h>
+#include <qmessagebox.h>
+
+
+KviNetworkDetailsWidget::KviNetworkDetailsWidget(QWidget * par,KviIrcNetwork * n)
+ : QDialog(par,"network_details",true)
+{
+ m_pOnConnectEditor=0;
+ m_pOnLoginEditor=0;
+
+ m_pUserEditor=0;
+ m_pPassEditor=0;
+ m_pNickEditor=0;
+ m_pRealEditor=0;
+ m_pDescEditor=0;
+
+ m_pEncodingEditor=0;
+
+ m_pAutoConnectCheck=0;
+
+ m_pNickServListView=0;
+ m_pNickServCheck=0;
+ m_pAddRuleButton=0;
+ m_pDelRuleButton=0;
+ m_pEditRuleButton=0;
+
+ m_pChannelListSelector=0;
+
+ QGridLayout * g = new QGridLayout(this,4,4,10,4);
+
+ setCaption(__tr2qs_ctx("Network Details","options"));
+ setIcon(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_WORLD)));
+
+ QString szTmp = "<font size=\"+1\"><b>";
+ szTmp += n->name();
+ szTmp += "</b></font>";
+
+ QLabel * l = new QLabel(szTmp,this);
+ l->setFrameStyle(QFrame::Raised | QFrame::StyledPanel);
+ l->setAlignment(Qt::AlignCenter);
+ l->setMargin(10);
+ g->addMultiCellWidget(l,0,0,0,3);
+ l->setMinimumWidth(200);
+
+ l = new QLabel(__tr2qs_ctx("Description:","options"),this);
+ g->addWidget(l,1,0);
+ m_pDescEditor = new QLineEdit(this);
+ g->addMultiCellWidget(m_pDescEditor,1,1,1,3);
+ m_pDescEditor->setText(n->description());
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pDescEditor,__tr2qs_ctx("<center>Put here a brief description of the network.</center>","options"));
+#endif
+
+ // Identity tab
+
+ QTabWidget * tw = new QTabWidget(this);
+ g->addMultiCellWidget(tw,2,2,0,3);
+
+ QWidget * tab = new QWidget(tw);
+ QGridLayout * gl = new QGridLayout(tab,4,2,10,4);
+
+ KviTalGroupBox *gbox = new KviTalGroupBox(2,Qt::Horizontal,__tr2qs_ctx("Properties","options"),tab);
+ gl->addMultiCellWidget(gbox,0,0,0,1);
+
+ l = new QLabel(__tr2qs_ctx("Username:","options"),gbox);
+ m_pUserEditor = new QLineEdit(gbox);
+ m_pUserEditor->setText(n->userName());
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pUserEditor,__tr2qs_ctx("<center>This is the <b>username</b> that KVIrc will use to login to servers on this network.\n" \
+ "If this field is left empty (most common case), KVIrc will use the default username " \
+ "specified in the \"Identity\" options tab.</center>","options"));
+#endif
+
+ l = new QLabel(__tr2qs_ctx("Nickname:","options"),gbox);
+ m_pNickEditor = new QLineEdit(gbox);
+ QValidator * v = new QRegExpValidator(QRegExp("[^-0-9 ][^ ]*","options"),gbox);
+ m_pNickEditor->setValidator(v);
+ m_pNickEditor->setText(n->nickName());
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pNickEditor,__tr2qs_ctx("<center>You can specify a \"special\" <b>nickname</b> that will be used to log in to the servers on this network.<br>" \
+ "If this field is left empty (most common case), the default nickname (specified in the \"Identity\" settings) will be used.</center>","options"));
+#endif
+
+ l = new QLabel(__tr2qs_ctx("Real name:","options"),gbox);
+ m_pRealEditor = new QLineEdit(gbox);
+ m_pRealEditor->setText(n->realName());
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pRealEditor,__tr2qs_ctx("<center>You can specify a \"special\" <b>real name</b> that will be used to login with the servers on this network.<br>" \
+ "If you leave this field empty (most common case), the default \"real name\" (specified in the \"Identity\" settings) will be used.</center>","options"));
+#endif
+
+
+ l = new QLabel(__tr2qs_ctx("Encoding:","options"),tab);
+ gl->addWidget(l,1,0);
+ m_pEncodingEditor = new QComboBox(false,tab);
+ m_pEncodingEditor->setDuplicatesEnabled(false);
+ gl->addWidget(m_pEncodingEditor,1,1);
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pEncodingEditor,__tr2qs_ctx("<center>This box allows you to choose the preferred encoding for the servers in this network. " \
+ "If you choose \"Use System Encoding\" then the encoding will be set to the systemwide " \
+ "value that you choose in the \"Encoding\" page of the options dialog.</center>","options"));
+#endif
+
+ int i = 0;
+ int current = 0;
+ KviLocale::EncodingDescription * d = KviLocale::encodingDescription(i);
+ QString tmp;
+ m_pEncodingEditor->insertItem(__tr2qs_ctx("Use System Encoding","options"));
+ while(d->szName)
+ {
+ KviQString::sprintf(tmp,"%s (%s)",d->szName,d->szDescription);
+ m_pEncodingEditor->insertItem(tmp);
+ if(KviQString::equalCI(d->szName,n->encoding()))current = i + 1;
+ i = i + 1;
+ d = KviLocale::encodingDescription(i);
+ }
+
+ m_pEncodingEditor->setCurrentItem(current);
+
+ m_pAutoConnectCheck = new KviStyledCheckBox(__tr2qs_ctx("Connect to this network at startup","options"),tab);
+ m_pAutoConnectCheck->setChecked(n->autoConnect());
+ gl->addMultiCellWidget(m_pAutoConnectCheck,2,2,0,1);
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pAutoConnectCheck,__tr2qs_ctx("<center>This option will cause KVIrc to automatically connect to this network at startup</center>","options"));
+#endif
+
+
+ l = new QLabel("",tab);
+ gl->addWidget(l,3,0);
+
+ gl->setRowStretch(3,1);
+ gl->setColStretch(1,1);
+
+ tw->addTab(tab,__tr2qs_ctx("General","options"));
+
+ // after login join channels
+ tab = new QWidget(tw);
+
+ gl = new QGridLayout(tab,1,1,10,4);
+
+ if(n->autoJoinChannelList())
+ m_lstChannels = *(n->autoJoinChannelList());
+ m_pChannelListSelector = new KviCahnnelListSelector(tab,
+ __tr2qs_ctx("Channels to join automatically upon connect:","options"),&m_lstChannels,true);
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pChannelListSelector,__tr2qs_ctx("<center>Here you can set a list of channels to be joined automatically " \
+ "after a connection to a server in this network has been established. To add a channel, type its name in the " \
+ "text input below and click \"<b>Add</b>\".</center>","options"));
+#endif
+ gl->addWidget(m_pChannelListSelector,0,0);
+
+ tw->addTab(tab,__tr2qs_ctx("Join Channels","options"));
+
+ // after connect execute
+ tab = new QWidget(tw);
+ gl = new QGridLayout(tab,1,1,10,4);
+
+ m_pOnConnectEditor = KviScriptEditor::createInstance(tab);
+ gl->addWidget(m_pOnConnectEditor,0,0);
+ m_pOnConnectEditor->setText(n->onConnectCommand());
+ m_pOnConnectEditor->setMinimumHeight(150);
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pOnConnectEditor,__tr2qs_ctx("<center>The following commands will be executed after a connection to a server in this network has been established.<br>" \
+ "<b>Important:</b> Enter commands <b>without</b> a preceding slash (e.g. <tt>quote pass secret</tt> instead of <tt>/quote pass secret</tt>).<br>"\
+ "KVIrc will first send the USER command, then eventually PASS and NICK and then execute this " \
+ "command sequence.</center>","options"));
+#endif
+
+ tw->addTab(tab,__tr2qs_ctx("On Connect","options"));
+
+
+ // after login execute
+ tab = new QWidget(tw);
+ gl = new QGridLayout(tab,1,1,10,4);
+
+ m_pOnLoginEditor = KviScriptEditor::createInstance(tab);
+ gl->addWidget(m_pOnLoginEditor,0,0);
+ m_pOnLoginEditor->setText(n->onLoginCommand());
+
+ m_pOnLoginEditor->setMinimumHeight(150);
+
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pOnLoginEditor,
+ __tr2qs_ctx("<center>The following commands will be executed after a successful login to a server in this network.<br>" \
+ "<b>Important:</b> Enter commands <b>without</b> a preceding slash (e.g. <tt>quote privatelog</tt> instead of <tt>/quote privatelog</tt>).<br>"
+ "This is useful for automatically opening queries, setting variables, etc.</center>","options"));
+#endif
+
+ tw->addTab(tab,__tr2qs_ctx("On Login","options"));
+
+
+ // nick serv rules
+
+ tab = new QWidget(tw);
+ gl = new QGridLayout(tab,3,3,10,5);
+
+ KviNickServRuleSet * rs = n->nickServRuleSet();
+ bool bNickServEnabled = rs ? (rs->isEnabled() && !rs->isEmpty()) : false;
+
+ m_pNickServCheck = new KviStyledCheckBox(__tr2qs_ctx("Enable NickServ Identification","options"),tab);
+ gl->addMultiCellWidget(m_pNickServCheck,0,0,0,2);
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pNickServCheck,
+ __tr2qs_ctx("This check enables the automatic identification with NickServ","options"));
+#endif
+ m_pNickServCheck->setChecked(bNickServEnabled);
+
+ m_pNickServListView = new KviTalListView(tab);
+ m_pNickServListView->setSelectionMode(KviTalListView::Single);
+ m_pNickServListView->setAllColumnsShowFocus(true);
+ m_pNickServListView->addColumn(__tr2qs_ctx("Nickname","options"));
+ m_pNickServListView->addColumn(__tr2qs_ctx("NickServ Mask","options"));
+ m_pNickServListView->addColumn(__tr2qs_ctx("NickServ Request Mask","options"));
+ m_pNickServListView->addColumn(__tr2qs_ctx("Identify Command","options"));
+ connect(m_pNickServListView,SIGNAL(selectionChanged()),this,SLOT(enableDisableNickServControls()));
+
+ gl->addMultiCellWidget(m_pNickServListView,1,1,0,2);
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pNickServListView,
+ __tr2qs_ctx("<center>This is a list of NickServ identification rules. " \
+ "KVIrc will use them to model its automatic interaction with NickServ on this network.<br>" \
+ "Please be aware that this feature can cause your NickServ passwords to be stolen " \
+ "if used improperly. Make sure that you fully understand the NickServ authentication protocol.<br>" \
+ "In other words, be sure to know what you're doing.<br>" \
+ "Also note that the password that you provide is stored as <b>PLAIN TEXT</b>.</center>","options"));
+#endif
+
+ m_pAddRuleButton = new QPushButton(__tr2qs_ctx("Add Rule","options"),tab);
+ connect(m_pAddRuleButton,SIGNAL(clicked()),this,SLOT(addNickServRule()));
+ gl->addWidget(m_pAddRuleButton,2,0);
+
+
+ m_pEditRuleButton = new QPushButton(__tr2qs_ctx("Edit Rule","options"),tab);
+ connect(m_pEditRuleButton,SIGNAL(clicked()),this,SLOT(editNickServRule()));
+ gl->addWidget(m_pEditRuleButton,2,1);
+
+ m_pDelRuleButton = new QPushButton(__tr2qs_ctx("Delete Rule","options"),tab);
+ connect(m_pDelRuleButton,SIGNAL(clicked()),this,SLOT(delNickServRule()));
+ gl->addWidget(m_pDelRuleButton,2,2);
+
+ connect(m_pNickServCheck,SIGNAL(toggled(bool)),this,SLOT(enableDisableNickServControls()));
+
+ if(rs && rs->rules())
+ {
+ KviPointerList<KviNickServRule> * ll = rs->rules();
+ for(KviNickServRule * rule = ll->first();rule;rule = ll->next())
+ {
+ (void)new KviTalListViewItem(m_pNickServListView,rule->registeredNick(),rule->nickServMask(),rule->messageRegexp(),rule->identifyCommand());
+ }
+ }
+
+ enableDisableNickServControls();
+
+ gl->setRowStretch(1,1);
+
+ tw->addTab(tab,__tr2qs_ctx("NickServ","options"));
+
+ QPushButton * b = new QPushButton(__tr2qs_ctx("&OK","options"),this);
+ b->setMinimumWidth(80);
+ g->addWidget(b,3,2);
+ b->setDefault(true);
+ connect(b,SIGNAL(clicked()),this,SLOT(accept()));
+
+ b = new QPushButton(__tr2qs_ctx("Cancel","options"),this);
+ g->addWidget(b,3,3);
+ b->setMinimumWidth(80);
+ connect(b,SIGNAL(clicked()),this,SLOT(reject()));
+
+
+ g->setRowStretch(2,1);
+ g->setColStretch(1,1);
+
+ tw->setMinimumWidth(375);
+}
+
+
+
+KviNetworkDetailsWidget::~KviNetworkDetailsWidget()
+{
+ if(m_pOnConnectEditor) KviScriptEditor::destroyInstance(m_pOnConnectEditor);
+ if(m_pOnLoginEditor) KviScriptEditor::destroyInstance(m_pOnLoginEditor);
+}
+
+void KviNetworkDetailsWidget::editNickServRule()
+{
+ KviTalListViewItem * it = m_pNickServListView->currentItem();
+ if(!it)return;
+ KviNickServRule r(it->text(0),it->text(1),it->text(2),it->text(3));
+ KviNickServRuleEditor ed(this,false);
+ if(ed.editRule(&r))
+ {
+ it->setText(0,r.registeredNick());
+ it->setText(1,r.nickServMask());
+ it->setText(2,r.messageRegexp());
+ it->setText(3,r.identifyCommand());
+ }
+}
+
+void KviNetworkDetailsWidget::addNickServRule()
+{
+ KviNickServRule r;
+ KviNickServRuleEditor ed(this,false);
+ if(ed.editRule(&r))
+ (void)new KviTalListViewItem(m_pNickServListView,r.registeredNick(),r.nickServMask(),r.messageRegexp(),r.identifyCommand());
+}
+
+void KviNetworkDetailsWidget::delNickServRule()
+{
+ KviTalListViewItem * it = m_pNickServListView->currentItem();
+ if(!it)return;
+ delete it;
+ enableDisableNickServControls();
+}
+
+void KviNetworkDetailsWidget::enableDisableNickServControls()
+{
+ bool bEnabled = m_pNickServCheck->isChecked();
+ m_pNickServListView->setEnabled(bEnabled);
+ m_pAddRuleButton->setEnabled(bEnabled);
+ bEnabled = bEnabled && (m_pNickServListView->childCount() > 0) && m_pNickServListView->currentItem();
+ m_pDelRuleButton->setEnabled(bEnabled);
+ m_pEditRuleButton->setEnabled(bEnabled);
+}
+
+void KviNetworkDetailsWidget::fillData(KviIrcNetwork * n)
+{
+ n->setUserName(m_pUserEditor->text());
+ n->setNickName(m_pNickEditor->text());
+ n->setRealName(m_pRealEditor->text());
+ n->setDescription(m_pDescEditor->text());
+ if(m_pAutoConnectCheck)
+ n->setAutoConnect(m_pAutoConnectCheck->isChecked());
+ if(m_pEncodingEditor)
+ if(m_pEncodingEditor->currentItem() <= 0)n->setEncoding(QString::null);
+ else {
+ KviLocale::EncodingDescription * d = KviLocale::encodingDescription(m_pEncodingEditor->currentItem() - 1);
+ n->setEncoding(d->szName);
+ }
+ if(m_pChannelListSelector)
+ m_pChannelListSelector->commit();
+ if(m_lstChannels.isEmpty())n->setAutoJoinChannelList(0);
+ else n->setAutoJoinChannelList(new QStringList(m_lstChannels));
+ if(m_pNickServListView)
+ {
+ if(m_pNickServListView->childCount() > 0)
+ {
+ KviNickServRuleSet * rs = KviNickServRuleSet::createInstance();
+ rs->setEnabled(m_pNickServCheck->isChecked());
+ KviTalListViewItem * it = m_pNickServListView->firstChild();
+ while(it)
+ {
+ rs->addRule(KviNickServRule::createInstance(it->text(0),it->text(1),it->text(2),it->text(3)));
+ it = it->nextSibling();
+ }
+ n->setNickServRuleSet(rs);
+ } else n->setNickServRuleSet(0);
+ }
+ if(m_pOnConnectEditor)
+ {
+ QString tmp;
+ m_pOnConnectEditor->getText(tmp);
+ n->setOnConnectCommand(tmp);
+ }
+ if(m_pOnLoginEditor)
+ {
+ QString tmp;
+ m_pOnLoginEditor->getText(tmp);
+ n->setOnLoginCommand(tmp);
+ }
+}
+
+
+
+
+
+
+
+KviServerDetailsWidget::KviServerDetailsWidget(QWidget * par,KviIrcServer * s)
+ : QDialog(par,"server_details",true)
+{
+ m_szHostname = s->hostName();
+ QGridLayout * g = new QGridLayout(this,4,4,10,4);
+
+ setCaption(__tr2qs_ctx("Server Details","options"));
+ setIcon(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_SERVER)));
+
+ m_pHeaderLabel = new QLabel("",this); // the text will be set later
+ m_pHeaderLabel->setFrameStyle(QFrame::Raised | QFrame::StyledPanel);
+ m_pHeaderLabel->setAlignment(Qt::AlignCenter);
+ m_pHeaderLabel->setMargin(10);
+ g->addMultiCellWidget(m_pHeaderLabel,0,0,0,3);
+ m_pHeaderLabel->setMinimumWidth(200);
+
+ QLabel * l = new QLabel(__tr2qs_ctx("Description:","options"),this);
+ g->addWidget(l,1,0);
+ m_pDescEditor = new QLineEdit(this);
+ g->addMultiCellWidget(m_pDescEditor,1,1,1,3);
+ m_pDescEditor->setText(s->description());
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pDescEditor,__tr2qs_ctx("<center>This is a brief description of this server. " \
+ "This field has no restrictions but many server lists use it to describe the server's physical location</center>","options"));
+#endif
+
+ // Identity tab
+
+ QTabWidget * tw = new QTabWidget(this);
+ g->addMultiCellWidget(tw,2,2,0,3);
+
+ QWidget * tab = new QWidget(tw);
+ QGridLayout * gl = new QGridLayout(tab,3,1,10,4);
+
+ KviTalGroupBox *gbox = new KviTalGroupBox(2,Qt::Horizontal,__tr2qs_ctx("Properties","options"),tab);
+ gl->addWidget(gbox,0,0);
+
+ l = new QLabel(__tr2qs_ctx("Username:","options"),gbox);
+ m_pUserEditor = new QLineEdit(gbox);
+ m_pUserEditor->setText(s->userName());
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pUserEditor,__tr2qs_ctx("<center>This is the <b>username</b> that KVIrc will use to login to this server.\n" \
+ "If this field is left empty (most common case), KVIrc will first look if an username is specified " \
+ "for the network that this server belongs to, and if that is empty then KVIrc will use the default username " \
+ "specified in the \"Identity\" options tab.</center>","options"));
+#endif
+
+ l = new QLabel(__tr2qs_ctx("Password:","options"),gbox);
+ m_pPassEditor = new QLineEdit(gbox);
+ m_pPassEditor->setEchoMode(QLineEdit::Password);
+ m_pPassEditor->setText(s->password());
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pPassEditor,__tr2qs_ctx("<center>If this server requires a password, put it in this field, otherwise leave it empty.</center>","options"));
+#endif
+
+ l = new QLabel(__tr2qs_ctx("Nickname:","options"),gbox);
+ m_pNickEditor = new QLineEdit(gbox);
+ QValidator * v = new QRegExpValidator(QRegExp("[^-0-9 ][^ ]*"),gbox);
+ m_pNickEditor->setValidator(v);
+ m_pNickEditor->setText(s->nickName());
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pNickEditor,__tr2qs_ctx("<center>You can specify a \"special\" <b>nickname</b> that will be used to log in to this server.<br>" \
+ "If this field is left empty (most common case), KVIrc will first look if a nickname is specified " \
+ "for the network that this server belongs to, and if that is empty then the default nickname (specified in the \"Identity\" settings) will be used.</center>","options"));
+#endif
+
+ l = new QLabel(__tr2qs_ctx("Real name:","options"),gbox);
+ m_pRealEditor = new QLineEdit(gbox);
+ m_pRealEditor->setText(s->realName());
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pRealEditor,__tr2qs_ctx("<center>You can specify a \"special\" <b>real name</b> that will be used to login with this server.<br>" \
+ "If you leave this field empty (most common case), KVIrc will first look if a real name is specified " \
+ "for the network that this server belongs to, and if that is empty the default \"real name\" (specified in the \"Identity\" settings) will be used.</center>","options"));
+#endif
+ gbox = new KviTalGroupBox(1,Qt::Horizontal,__tr2qs_ctx("User Mode","options"),tab);
+ gl->addWidget(gbox,1,0);
+
+ m_pUseDefaultInitUMode = new KviStyledCheckBox(__tr2qs_ctx("Use default user mode","options"),gbox);
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pUseDefaultInitUMode,__tr2qs_ctx("<center>If this is enabled, the global initial <b>user mode</b> (configured from"\
+ " the identity dialog) will be used. If disabled, you can configure an initial user mode for this server","options"));
+#endif
+ bool bHasUmode = !(s->initUMode().isEmpty());
+ KviStr szDefUMode = KVI_OPTION_STRING(KviOption_stringDefaultUserMode);
+ m_pUseDefaultInitUMode->setChecked(!bHasUmode);
+ connect(m_pUseDefaultInitUMode,SIGNAL(toggled(bool)),this,SLOT(useDefaultInitUModeToggled(bool)));
+
+ m_pIMode = new KviStyledCheckBox(__tr2qs_ctx("Invisible (+i)","options"),gbox);
+ m_pIMode->setEnabled(bHasUmode);
+ m_pIMode->setChecked(bHasUmode ? s->initUMode().contains('i',false) : szDefUMode.contains('i',false));
+
+ m_pSMode = new KviStyledCheckBox(__tr2qs_ctx("Server notices (+s)","options"),gbox);
+ m_pSMode->setEnabled(bHasUmode);
+ m_pSMode->setChecked(bHasUmode ? s->initUMode().contains('s',false) : szDefUMode.contains('s',false));
+
+ m_pWMode = new KviStyledCheckBox(__tr2qs_ctx("Wallops (+w)","options"),gbox);
+ m_pWMode->setEnabled(bHasUmode);
+ m_pWMode->setChecked(bHasUmode ? s->initUMode().contains('w',false) : szDefUMode.contains('w',false));
+
+ l = new QLabel("",tab);
+ gl->addWidget(l,2,0);
+
+ gl->setRowStretch(2,1);
+ //gl->setColStretch(1,1);
+
+ tw->addTab(tab,*(g_pIconManager->getSmallIcon(KVI_SMALLICON_WHO)),__tr2qs_ctx("Identity","options"));
+
+ // Connection tab
+
+ tab = new QWidget(tw);
+ gl = new QGridLayout(tab,11,1,10,4);
+
+ l = new QLabel(__tr2qs_ctx("Port:","options"),tab);
+ gl->addWidget(l,0,0);
+
+
+ m_pPortEditor = new QLineEdit(tab);
+ gl->addWidget(m_pPortEditor,0,1);
+ QString tmpz;
+ tmpz.setNum(s->port());
+ m_pPortEditor->setText(tmpz);
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pPortEditor,__tr2qs_ctx("<center>This is the default <b>port</b> that this server will be contacted on.<br>Usually <b>6667</b> is OK.</center>","options"));
+#endif
+ connect(m_pPortEditor,SIGNAL(textChanged(const QString &)),this,SLOT(portEditorTextChanged(const QString &)));
+
+
+
+ l = new QLabel(__tr2qs_ctx("IP address:","options"),tab);
+ gl->addWidget(l,1,0);
+ m_pIpEditor = new KviIpEditor(tab,KviIpEditor::IpV4);
+ gl->addWidget(m_pIpEditor,1,1);
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pIpEditor,__tr2qs_ctx("<center>This is the <b>IP address</b> of this server, it is here for caching purposes.<br>" \
+ "If you leave this field empty, KVIrc will fill it in the first time it connects to the server. " \
+ "If you enable the \"cache IP address\" option below, KVIrc will use it as a \"cached result\" " \
+ "and avoid looking it up again.</center>","options"));
+#endif
+#ifdef COMPILE_IPV6_SUPPORT
+ m_pIpEditor->setAddressType(s->isIpV6() ? KviIpEditor::IpV6 : KviIpEditor::IpV4);
+#else
+ m_pIpEditor->setAddressType(KviIpEditor::IpV4);
+#endif
+
+ if(!m_pIpEditor->setAddress(s->m_szIp))
+ {
+#ifdef COMPILE_IPV6_SUPPORT
+ m_pIpEditor->setAddress(s->isIpV6() ? "0:0:0:0:0:0:0:0" : "0.0.0.0");
+#else
+ m_pIpEditor->setAddress("0.0.0.0");
+#endif
+ }
+
+ m_pCacheIpCheck = new KviStyledCheckBox(__tr2qs_ctx("Cache IP address","options"),tab);
+ gl->addMultiCellWidget(m_pCacheIpCheck,2,2,0,1);
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pCacheIpCheck,__tr2qs_ctx("<center>This check will enable <b>IP address caching</b> for this server:<br>" \
+ "DNS lookups can be time-consuming and might be blocking on some platforms; " \
+ "this option will cause KVIrc to look up the server hostname only once.<br><br> " \
+ "Advanced: you can also use this option to force a certain server name to resolve " \
+ "to a fixed ip address when either the dns for that server is temporairly " \
+ "unreachable or you want to avoid the round-robin lookups.</center>","options"));
+#endif
+ m_pCacheIpCheck->setChecked(s->cacheIp());
+
+
+ m_pUseIPV6Check = new KviStyledCheckBox(__tr2qs_ctx("Use IPv6 protocol","options"),tab);
+ gl->addMultiCellWidget(m_pUseIPV6Check,3,3,0,1);
+#ifdef COMPILE_IPV6_SUPPORT
+ m_pUseIPV6Check->setChecked(s->isIpV6());
+#else
+ m_pUseIPV6Check->setEnabled(false);
+#endif
+ connect(m_pUseIPV6Check,SIGNAL(toggled(bool)),this,SLOT(useIPV6CheckToggled(bool)));
+
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pUseIPV6Check,__tr2qs_ctx("<center>This check identifies IPv6 servers.<br>If enabled, KVIrc will attempt to use the IPv6 protocol " \
+ "(thus your OS <b>must</b> have a working IPv6 stack and you <b>must</b> have an IPv6 connection).</center>","options"));
+#endif
+
+
+ m_pUseSSLCheck = new KviStyledCheckBox(__tr2qs_ctx("Use SSL protocol","options"),tab);
+ gl->addMultiCellWidget(m_pUseSSLCheck,4,4,0,1);
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pUseSSLCheck,__tr2qs_ctx("<center>This check will cause the connection to use the <b>Secure Socket Layer</b> " \
+ "encryption support. Obviously, this server must have support for this, too. :)</center>","options"));
+#endif
+#ifndef COMPILE_SSL_SUPPORT
+ m_pUseSSLCheck->setEnabled(false);
+#endif
+ m_pUseSSLCheck->setChecked(s->useSSL());
+
+
+ m_pUseAutoConnect = new KviStyledCheckBox(__tr2qs_ctx("Connect to this server at startup","options"),tab);
+ m_pUseAutoConnect->setChecked(s->autoConnect());
+
+ gl->addMultiCellWidget(m_pUseAutoConnect,5,5,0,1);
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pUseAutoConnect,__tr2qs_ctx("<center>This option will cause KVIrc to connect to the IRC server when it is started.</center>","options"));
+#endif
+
+ l = new QLabel(__tr2qs_ctx("Encoding:","options"),tab);
+ gl->addWidget(l,6,0);
+ m_pEncodingEditor = new QComboBox(false,tab);
+ m_pEncodingEditor->setDuplicatesEnabled(false);
+ gl->addWidget(m_pEncodingEditor,6,1);
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pEncodingEditor,__tr2qs_ctx("<center>This box allows you to choose the preferred encoding for this sever. " \
+ "If you choose \"Use Network Encoding\" then the encoding will be inherited from the " \
+ "network that this server belongs to.</center>","options"));
+#endif
+
+ int i = 0;
+ int current = 0;
+ KviLocale::EncodingDescription * d = KviLocale::encodingDescription(i);
+ QString tmp;
+ m_pEncodingEditor->insertItem(__tr2qs_ctx("Use Network Encoding","options"));
+ while(d->szName)
+ {
+ KviQString::sprintf(tmp,"%s (%s)",d->szName,d->szDescription);
+ m_pEncodingEditor->insertItem(tmp);
+ if(KviQString::equalCI(d->szName,s->encoding()))current = i + 1;
+ i = i + 1;
+ d = KviLocale::encodingDescription(i);
+ }
+
+ m_pEncodingEditor->setCurrentItem(current);
+
+
+ l = new QLabel(__tr2qs_ctx("Link filter:","options"),tab);
+ gl->addWidget(l,7,0);
+ m_pLinkFilterEditor = new QComboBox(true,tab);
+ m_pLinkFilterEditor->setDuplicatesEnabled(false);
+ gl->addWidget(m_pLinkFilterEditor,7,1);
+
+ m_pLinkFilterEditor->insertItem("");
+
+ g_pModuleManager->loadModulesByCaps("linkfilter");
+ KviModuleExtensionDescriptorList * mexl = KviModuleExtensionManager::instance()->getExtensionList("linkfilter");
+
+
+
+ if(mexl)
+ {
+ for(KviModuleExtensionDescriptor * d = mexl->first();d;d = mexl->next())
+ m_pLinkFilterEditor->insertItem(d->name().ptr());
+ } else {
+ if(!s->linkFilter().isEmpty())
+ m_pLinkFilterEditor->insertItem(s->linkFilter());
+ }
+
+ if(!s->linkFilter().isEmpty())
+ m_pLinkFilterEditor->setCurrentText(s->linkFilter());
+ else
+ m_pLinkFilterEditor->setCurrentText("");
+
+
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pLinkFilterEditor,__tr2qs_ctx("<center>This field specifies the name of a module that exports a link filter for this type of server.<br>" \
+ "For plain IRC connections, you don't need any link filters; this is used for incompatible protocols.</center>","options"));
+#endif
+
+ l = new QLabel(__tr2qs_ctx("Id:","options"),tab);
+ gl->addWidget(l,8,0);
+ m_pIdEditor = new QLineEdit(tab);
+ if(s->id().isEmpty())s->generateUniqueId();
+ m_pIdEditor->setText(s->id());
+ gl->addWidget(m_pIdEditor,8,1);
+
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pIdEditor,__tr2qs_ctx("<center>This field allows you to specify a really unique id for this server. " \
+ "You will then be able to use /server -x &lt;this_id&gt; to make the connection. This is especially " \
+ "useful when you have multiple server entries with the same hostname and port in different networks (bouncers?)</center>","options"));
+#endif
+
+
+ l = new QLabel(__tr2qs_ctx("Proxy server:","options"),tab);
+ gl->addWidget(l,9,0);
+ m_pProxyEditor = new QComboBox(tab);
+ gl->addWidget(m_pProxyEditor,9,1);
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pProxyEditor,__tr2qs_ctx("<center>This is the <b>proxy</b> that KVIrc will use to connect to thos server.\n" \
+ "If this field is set in \"Default\" KVirc will use global proxy settings, if it is set in \"Direct connection\" " \
+ "KVirc will connect to this server without proxy. You can define new proxy server in global options' \"Proxy servers\" menu.</center>","options"));
+#endif
+
+ m_pProxyEditor->insertItem(__tr2qs_ctx("Default","options"));
+ m_pProxyEditor->insertItem(__tr2qs_ctx("Direct connection","options"));
+
+ KviPointerList<KviProxy> * proxylist = g_pProxyDataBase->proxyList();
+ for(KviProxy * p = proxylist->first();p;p = proxylist->next())
+ {
+ m_pProxyEditor->insertItem(QString("%1:%2").arg(p->hostname()).arg(p->port()));
+ }
+ if(m_pProxyEditor->count() > (s->proxy()+2))
+ m_pProxyEditor->setCurrentItem(s->proxy()+2);
+
+
+ l = new QLabel("",tab);
+ gl->addMultiCellWidget(l,10,10,0,1);
+
+ gl->setRowStretch(10,1);
+
+ tw->addTab(tab,*(g_pIconManager->getSmallIcon(KVI_SMALLICON_SOCKETWARNING)),__tr2qs_ctx("Connection","options"));
+
+ // after login join channels
+ tab = new QWidget(tw);
+
+ gl = new QGridLayout(tab,1,1,10,4);
+
+ if(s->autoJoinChannelList())
+ m_lstChannels = *(s->autoJoinChannelList());
+ m_pChannelListSelector = new KviCahnnelListSelector(tab,
+ __tr2qs_ctx("Channels to join automatically upon connect:","options"),&m_lstChannels,true);
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pChannelListSelector,__tr2qs_ctx("<center>Here you can set a list of channels to be joined automatically " \
+ "after a connection to this server has been established. To add a channel, type its name in the " \
+ "text input below and click \"<b>Add</b>\".</center>","options"));
+#endif
+ gl->addWidget(m_pChannelListSelector,0,0);
+
+ tw->addTab(tab,*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CHANNEL)),__tr2qs_ctx("Join Channels","options"));
+
+ // after connect execute
+ tab = new QWidget(tw);
+ gl = new QGridLayout(tab,1,1,10,4);
+
+
+ m_pOnConnectEditor = KviScriptEditor::createInstance(tab);
+ gl->addWidget(m_pOnConnectEditor,0,0);
+ m_pOnConnectEditor->setText(s->onConnectCommand());
+ m_pOnConnectEditor->setMinimumHeight(150);
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pOnConnectEditor,__tr2qs_ctx("<center>The following commands will be executed after a connection has been established.<br>" \
+ "<b>Important:</b> Enter commands <b>without</b> a preceding slash (e.g. <tt>quote pass secret</tt> instead of <tt>/quote pass secret</tt>).<br>"\
+ "KVIrc will first send the USER command, then eventually PASS and NICK and then execute this " \
+ "command sequence.<br>This is particularly useful for IRC bouncers that require login commands.</center>","options"));
+#endif
+
+ tw->addTab(tab,__tr2qs_ctx("On Connect","options"));
+ // after login execute
+
+ tab = new QWidget(tw);
+ gl = new QGridLayout(tab,1,1,10,4);
+
+ m_pOnLoginEditor = KviScriptEditor::createInstance(tab);
+ gl->addWidget(m_pOnLoginEditor,0,0);
+ m_pOnLoginEditor->setText(s->onLoginCommand());
+
+ m_pOnLoginEditor->setMinimumHeight(150);
+
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pOnLoginEditor,
+ __tr2qs_ctx("<center>The following commands will be executed after a successful login to this server.<br>" \
+ "<b>Important:</b> Enter commands <b>without</b> a preceding slash (e.g. <tt>quote privatelog</tt> instead of <tt>/quote privatelog</tt>).<br>"
+ "This is useful for automatically opening queries, setting variables, etc.</center>","options"));
+#endif
+
+ tw->addTab(tab,__tr2qs_ctx("On Login","options"));
+
+ QPushButton * b = new QPushButton(__tr2qs_ctx("OK","options"),this);
+ b->setMinimumWidth(80);
+ g->addWidget(b,3,2);
+ b->setDefault(true);
+ connect(b,SIGNAL(clicked()),this,SLOT(accept()));
+
+ b = new QPushButton(__tr2qs_ctx("Cancel","options"),this);
+ g->addWidget(b,3,3);
+ b->setMinimumWidth(80);
+ connect(b,SIGNAL(clicked()),this,SLOT(reject()));
+
+ g->setRowStretch(2,1);
+ g->setColStretch(1,1);
+
+ tw->setMinimumWidth(390);
+
+ setHeaderLabelText();
+}
+
+KviServerDetailsWidget::~KviServerDetailsWidget()
+{
+ if(m_pOnConnectEditor) KviScriptEditor::destroyInstance(m_pOnConnectEditor);
+ if(m_pOnLoginEditor) KviScriptEditor::destroyInstance(m_pOnLoginEditor);
+}
+
+void KviServerDetailsWidget::useIPV6CheckToggled(bool)
+{
+#ifdef COMPILE_IPV6_SUPPORT
+ m_pIpEditor->setAddressType(m_pUseIPV6Check->isChecked() ? KviIpEditor::IpV6 : KviIpEditor::IpV4);
+#else
+ m_pIpEditor->setAddressType(KviIpEditor::IpV4);
+#endif
+ setHeaderLabelText();
+}
+
+void KviServerDetailsWidget::portEditorTextChanged(const QString &)
+{
+ setHeaderLabelText();
+}
+
+void KviServerDetailsWidget::setHeaderLabelText()
+{
+ QString szTmp = "<font size=\"+1\"><b>irc";
+ if(m_pUseIPV6Check->isChecked())szTmp += "6";
+ szTmp += "://";
+ szTmp += m_szHostname;
+ szTmp += ":";
+
+ bool bOk;
+
+ QString num = m_pPortEditor->text();
+ unsigned int uPort = num.toUInt(&bOk);
+ if(!bOk)uPort = 6667;
+ num.setNum(uPort);
+ szTmp += num;
+ szTmp += "</b></font>";
+
+ m_pHeaderLabel->setText(szTmp);
+}
+
+void KviServerDetailsWidget::fillData(KviIrcServer * s)
+{
+ s->setUserName(m_pUserEditor->text());
+ s->setPassword(m_pPassEditor->text());
+ s->setNickName(m_pNickEditor->text());
+ s->setRealName(m_pRealEditor->text());
+ if(m_pDescEditor)
+ s->setDescription(m_pDescEditor->text());
+ if(m_pLinkFilterEditor)
+ s->setLinkFilter(m_pLinkFilterEditor->lineEdit()->text());
+ if(m_pEncodingEditor)
+ if(m_pEncodingEditor->currentItem() <= 0)s->m_szEncoding = "";
+ else {
+ KviLocale::EncodingDescription * d = KviLocale::encodingDescription(m_pEncodingEditor->currentItem() - 1);
+ s->m_szEncoding = d->szName;
+ }
+ s->setIpAddress("");
+ if(m_pCacheIpCheck)
+ s->setCacheIp(m_pCacheIpCheck->isChecked());
+ if(m_pUseSSLCheck)
+ s->setUseSSL(m_pUseSSLCheck->isChecked());
+ if(m_pIdEditor)
+ s->setId(m_pIdEditor->text());
+ if(s->id().isEmpty())s->generateUniqueId();
+
+ if(m_pUseDefaultInitUMode)
+ {
+ KviStr szUMode;
+ if(!m_pUseDefaultInitUMode->isChecked())
+ {
+ if(m_pIMode->isChecked())szUMode.append('i');
+ if(m_pWMode->isChecked())szUMode.append('w');
+ if(m_pSMode->isChecked())szUMode.append('s');
+ }
+ s->setInitUMode(szUMode.ptr());
+ }
+
+ QString tmp = m_pPortEditor->text();
+ bool bOk;
+ kvi_u32_t uPort = tmp.toUInt(&bOk);
+ if(!bOk)uPort = 6667;
+ s->m_uPort = uPort;
+#ifdef COMPILE_IPV6_SUPPORT
+ s->setIpV6(m_pUseIPV6Check->isChecked());
+#else
+ s->setIpV6(false);
+#endif
+
+ if(m_pIpEditor)
+ {
+ KviStr tmpAddr = m_pIpEditor->address();
+
+ if(!m_pIpEditor->hasEmptyFields())
+ {
+#ifdef COMPILE_IPV6_SUPPORT
+ if(s->isIpV6())
+ {
+ if((!kvi_strEqualCI(tmpAddr.ptr(),"0:0:0:0:0:0:0:0")) && kvi_isValidStringIp_V6(tmpAddr.ptr()))
+ {
+ s->setIpAddress(tmpAddr.ptr());
+ } else {
+ s->setCacheIp(false);
+ s->setIpAddress("");
+ }
+ } else {
+#endif
+ if((!kvi_strEqualCI(tmpAddr.ptr(),"0.0.0.0")) && kvi_isValidStringIp(tmpAddr.ptr()))
+ {
+ s->setIpAddress(tmpAddr.ptr());
+ } else {
+ s->setCacheIp(false);
+ s->setIpAddress("");
+ }
+#ifdef COMPILE_IPV6_SUPPORT
+ }
+#endif
+ } else {
+ s->setCacheIp(false);
+ s->setIpAddress("");
+ }
+ }
+ if(m_pOnConnectEditor)
+ {
+ QString tmp;
+ m_pOnConnectEditor->getText(tmp);
+ s->setOnConnectCommand(tmp);
+ }
+ if(m_pOnLoginEditor)
+ {
+ QString tmp;
+ m_pOnLoginEditor->getText(tmp);
+ s->setOnLoginCommand(tmp);
+ }
+ if(m_pChannelListSelector)
+ m_pChannelListSelector->commit();
+ if(m_lstChannels.isEmpty())s->setAutoJoinChannelList(0);
+ else s->setAutoJoinChannelList(new QStringList(m_lstChannels));
+ if(m_pUseAutoConnect)
+ s->setAutoConnect(m_pUseAutoConnect->isChecked());
+ if(m_pProxyEditor)
+ s->setProxy(m_pProxyEditor->currentItem()-2);
+}
+
+void KviServerDetailsWidget::useDefaultInitUModeToggled(bool b)
+{
+ m_pIMode->setEnabled(!b);
+ m_pWMode->setEnabled(!b);
+ m_pSMode->setEnabled(!b);
+}
+
+// kvi_app.cpp
+extern KVIRC_API KviIrcServerDataBase * g_pIrcServerDataBase;
+
+KviServerOptionsListViewItem::KviServerOptionsListViewItem(KviTalListView *parent,const QPixmap &pm,const KviIrcNetwork *n)
+ : KviTalListViewItem(parent)
+{
+ setPixmap(0,pm);
+ m_pServerData = 0;
+ m_pNetworkData = new KviIrcNetwork(*n);
+ setText(0,n->name());
+ setText(1,n->description());
+}
+
+KviServerOptionsListViewItem::KviServerOptionsListViewItem(KviTalListViewItem *parent,const QPixmap &pm,const KviIrcServer *s)
+ : KviTalListViewItem(parent)
+{
+ setPixmap(0,pm);
+ m_pServerData = new KviIrcServer(*s);
+ setText(0,s->hostName());
+ setText(1,s->description());
+ m_pNetworkData = 0;
+}
+
+KviServerOptionsListViewItem::~KviServerOptionsListViewItem()
+{
+ if(m_pServerData)delete m_pServerData;
+ if(m_pNetworkData)delete m_pNetworkData;
+}
+
+void KviServerOptionsListViewItem::updateVisibleStrings()
+{
+ if(m_pNetworkData)
+ {
+ setText(0,m_pNetworkData->name());
+ setText(1,m_pNetworkData->description());
+ return;
+ }
+ if(m_pServerData)
+ {
+ setText(0,m_pServerData->hostName());
+ setText(1,m_pServerData->description());
+ }
+}
+
+
+
+
+
+
+
+
+KviServerOptionsWidget::KviServerOptionsWidget(QWidget * parent)
+ : KviOptionsWidget(parent,"server_options_widget")
+{
+ createLayout(4,2);
+
+ m_pContextPopup = new KviTalPopupMenu(this);
+ m_pImportPopup = new KviTalPopupMenu(this);
+
+ connect(m_pImportPopup,SIGNAL(aboutToShow()),this,SLOT(importPopupAboutToShow()));
+ connect(m_pImportPopup,SIGNAL(activated(int)),this,SLOT(importPopupActivated(int)));
+
+ m_pServerDetailsDialog = 0;
+ m_pNetworkDetailsDialog = 0;
+ m_pImportFilter = 0;
+
+ m_pListView = new KviTalListView(this);
+ addWidgetToLayout(m_pListView,0,0,0,0);
+ m_pListView->addColumn(__tr2qs_ctx("Server","options"));
+ m_pListView->addColumn(__tr2qs_ctx("Description","options"));
+ m_pListView->setRootIsDecorated(true);
+ m_pListView->setAllColumnsShowFocus(true);
+ m_pListView->setSelectionMode(KviTalListView::Single);
+ connect(m_pListView,SIGNAL(selectionChanged(KviTalListViewItem *)),
+ this,SLOT(listViewItemSelectionChanged(KviTalListViewItem *)));
+ connect(m_pListView,SIGNAL(rightButtonPressed(KviTalListViewItem *,const QPoint &,int)),
+ this,SLOT(listViewRightButtonPressed(KviTalListViewItem *,const QPoint &,int)));
+ connect(m_pListView,SIGNAL(doubleClicked(KviTalListViewItem*, const QPoint&, int )),
+ this,SLOT(detailsClicked()));
+
+#ifdef COMPILE_INFO_TIPS
+ QString tiptxt = __tr2qs_ctx("<center>This is the list of available IRC servers.<br>" \
+ "Right-click on the list to add or remove servers and perform other actions.<br>"\
+ "Double-click on a item for advanced options.</center>","options");
+ KviTalToolTip::add(m_pListView,tiptxt);
+ KviTalToolTip::add(m_pListView->viewport(),tiptxt);
+#endif
+
+ KviTalVBox * vbox = new KviTalVBox(this);
+ addWidgetToLayout(vbox,1,0,1,0);
+
+ m_pNewNetworkButton = new KviStyledToolButton(vbox);
+ m_pNewNetworkButton->setPixmap(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_WORLD)));
+ m_pNewNetworkButton->setAutoRaise(true);
+ connect(m_pNewNetworkButton,SIGNAL(clicked()),this,SLOT(newNetwork()));
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pNewNetworkButton,__tr2qs_ctx("New Network","options"));
+#endif
+
+ m_pNewServerButton = new KviStyledToolButton(vbox);
+ m_pNewServerButton->setPixmap(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_SERVER)));
+ m_pNewServerButton->setAutoRaise(true);
+ connect(m_pNewServerButton,SIGNAL(clicked()),this,SLOT(newServer()));
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pNewServerButton,__tr2qs_ctx("New Server","options"));
+#endif
+
+ m_pRemoveButton = new KviStyledToolButton(vbox);
+ m_pRemoveButton->setPixmap(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CUT)));
+ m_pRemoveButton->setEnabled(false);
+ m_pRemoveButton->setAutoRaise(true);
+ connect(m_pRemoveButton,SIGNAL(clicked()),this,SLOT(removeCurrent()));
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pRemoveButton,__tr2qs_ctx("Remove Network/Server","options"));
+#endif
+
+ QFrame * f = new QFrame(vbox);
+ f->setFrameStyle(QFrame::Sunken | QFrame::HLine);
+
+ m_pCopyServerButton = new KviStyledToolButton(vbox);
+ m_pCopyServerButton->setPixmap(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_COPY)));
+ m_pCopyServerButton->setEnabled(false);
+ m_pCopyServerButton->setAutoRaise(true);
+ connect(m_pCopyServerButton,SIGNAL(clicked()),this,SLOT(copyServer()));
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pCopyServerButton,__tr2qs_ctx("Copy Server","options"));
+#endif
+
+ m_pPasteServerButton = new KviStyledToolButton(vbox);
+ m_pPasteServerButton->setPixmap(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_PASTE)));
+ m_pPasteServerButton->setEnabled(false);
+ m_pPasteServerButton->setAutoRaise(true);
+ connect(m_pPasteServerButton,SIGNAL(clicked()),this,SLOT(pasteServer()));
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pPasteServerButton,__tr2qs_ctx("Paste Server","options"));
+#endif
+
+ f = new QFrame(vbox);
+ f->setFrameStyle(QFrame::Sunken | QFrame::HLine);
+
+ m_pImportButton = new KviStyledToolButton(vbox);
+ m_pImportButton->setPixmap(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_FOLDER)));
+ m_pImportButton->setAutoRaise(true);
+ m_pImportButton->setPopup(m_pImportPopup);
+ m_pImportButton->setPopupDelay(1);
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pImportButton,__tr2qs_ctx("Import List","options"));
+#endif
+
+ QFrame * lll = new QFrame(vbox);
+ vbox->setStretchFactor(lll,100);
+
+ KviTalGroupBox *gbox = addGroupBox(0,1,1,1,3,Qt::Horizontal,__tr2qs_ctx("Active Configuration","options"));
+ m_pSrvNetLabel = new QLabel(__tr2qs_ctx("Server:","options"),gbox);
+
+ m_pSrvNetEdit = new QLineEdit(gbox);
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pSrvNetEdit,__tr2qs_ctx("<center>This is the name of the currently selected server or network</center>","options"));
+#endif
+
+/*
+ m_pIpV6Check = new KviStyledCheckBox(__tr2qs_ctx("Use IPv6 protocol","options"),gbox);
+
+#ifndef COMPILE_IPV6_SUPPORT
+ m_pIpV6Check->setEnabled(false);
+#endif
+
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pIpV6Check,__tr2qs_ctx("<center>This check identifies IPv6 servers.<br>If enabled, KVIrc will attempt to use the IPv6 protocol " \
+ "(thus your OS <b>must</b> have a working IPv6 stack and you <b>must</b> have an IPv6 connection).</center>","options"));
+#endif
+
+ m_pPortLabel = new QLabel(__tr2qs_ctx("Port:","options"),gbox);
+
+ m_pPortEdit = new QLineEdit(gbox);
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pPortEdit,__tr2qs_ctx("<center>This is the default <b>port</b> that this server will be contacted on.<br>Usually <b>6667</b> is OK.</center>","options"));
+#endif
+*/
+
+ m_pDetailsButton = new QPushButton(__tr2qs_ctx("Advanced...","options"),gbox);
+ connect(m_pDetailsButton,SIGNAL(clicked()),this,SLOT(detailsClicked()));
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pDetailsButton,__tr2qs_ctx("<center>Click here to edit advanced options for this entry</center>","options"));
+#endif
+
+ m_pConnectCurrent = new QPushButton(__tr2qs_ctx("Connect &Now","options"),this);
+ addWidgetToLayout(m_pConnectCurrent,0,2,0,2);
+ connect(m_pConnectCurrent,SIGNAL(clicked()),this,SLOT(connectCurrentClicked()));
+
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(m_pConnectCurrent,__tr2qs_ctx("<center>Hit this button to connect to the currently selected server.</center>","options"));
+#endif
+
+ m_pRecentPopup = new KviTalPopupMenu(this);
+ connect(m_pRecentPopup,SIGNAL(aboutToShow()),this,SLOT(recentServersPopupAboutToShow()));
+ connect(m_pRecentPopup,SIGNAL(activated(int)),this,SLOT(recentServersPopupClicked(int)));
+
+ QToolButton * tb = new KviStyledToolButton(this);
+ addWidgetToLayout(tb,1,2,1,2);
+ tb->setPixmap(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TIME)));
+ tb->setPopup(m_pRecentPopup);
+ tb->setPopupDelay(1);
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(tb,__tr2qs_ctx("<center>This button shows a list of recently used servers. It allows you to quickly find them in the list.</center>","options"));
+#endif
+
+
+ KviBoolSelector * b = addBoolSelector(0,3,1,3,__tr2qs_ctx("Show this dialog at startup","options"),KviOption_boolShowServersConnectDialogOnStart);
+
+#ifdef COMPILE_INFO_TIPS
+ KviTalToolTip::add(b,__tr2qs_ctx("<center>If this option is enabled, the Servers dialog will appear every time you start KVIrc</center>","options"));
+#endif
+
+ // KviBoolSelector * c = addBoolSelector(0,6,2,6,__tr("Close after connection","options"),KviOption_boolCloseServerWidgetAfterConnect);
+
+ m_pLastEditedItem = 0;
+
+ m_pClipboard = 0;
+
+ fillServerList();
+
+ layout()->setRowStretch(0,1);
+ //layout()->setColStretch(1,5);
+ //layout()->setColStretch(2,2);
+ layout()->setColStretch(0,1);
+ setMinimumWidth(320);
+}
+
+KviServerOptionsWidget::~KviServerOptionsWidget()
+{
+ if(m_pImportFilter)
+ {
+ disconnect(m_pImportFilter,0,this,0);
+ m_pImportFilter->die();
+ m_pImportFilter = 0;
+ }
+
+ if(m_pClipboard)delete m_pClipboard;
+ if(m_pServerDetailsDialog)delete m_pServerDetailsDialog;
+ if(m_pNetworkDetailsDialog)delete m_pNetworkDetailsDialog;
+}
+
+void KviServerOptionsWidget::recentServersPopupAboutToShow()
+{
+ g_pApp->fillRecentServersPopup(m_pRecentPopup);
+}
+
+void KviServerOptionsWidget::recentServersPopupClicked(int id)
+{
+ KviStr data = m_pRecentPopup->text(id);
+ data.cutToFirst('/');
+ while(data.firstCharIs('/'))data.cutLeft(1);
+ data.cutFromLast(':');
+ data.replaceAll("/","");
+ // we should have a full server name now , with no port
+
+ KviStr port = m_pRecentPopup->text(id);
+ port.cutToLast(':');
+ bool bOk;
+ kvi_u32_t uPort = port.toUInt(&bOk);
+ // we have the port too
+
+ KviTalListViewItem * pFoundNet = 0;
+ KviTalListViewItem * pFoundSrv = 0;
+
+ for(KviTalListViewItem * net = m_pListView->firstChild();net;net = net->nextSibling())
+ {
+ for(KviTalListViewItem * srv = net->firstChild();srv;srv = srv->nextSibling())
+ {
+ KviStr tmp = ((KviServerOptionsListViewItem *)srv)->m_pServerData->hostName();
+ if(kvi_strEqualCI(tmp.ptr(),data.ptr()))
+ {
+ if(((KviServerOptionsListViewItem *)srv)->m_pServerData->port() == uPort)
+ {
+ net->setOpen(true);
+ m_pListView->setCurrentItem(srv);
+ m_pListView->ensureItemVisible(srv);
+ return;
+ } else {
+ if(!pFoundNet)
+ {
+ // the port doesn't match.. check for
+ // another entry with the correct port
+ // but keep track of this entry in case we don't find it
+ pFoundNet = srv;
+ pFoundSrv = net;
+ }
+ }
+ }
+ }
+ }
+
+ // fallback to the server with the wrong port
+ if(pFoundNet)
+ {
+ pFoundNet->setOpen(true);
+ m_pListView->setCurrentItem(pFoundSrv);
+ m_pListView->ensureItemVisible(pFoundSrv);
+ }
+}
+
+
+void KviServerOptionsWidget::connectCurrentClicked()
+{
+ saveLastItem();
+ commit();
+ KviStr szServer = m_pSrvNetEdit->text();
+ if(szServer.isEmpty())return;
+ KviKvsScript::run("server -u",g_pApp->activeConsole());
+}
+
+
+void KviServerOptionsWidget::fillServerList()
+{
+ KviServerOptionsListViewItem * net;
+ KviServerOptionsListViewItem * srv;
+ KviServerOptionsListViewItem * cur = 0;
+
+ KviPointerHashTableIterator<QString,KviIrcServerDataBaseRecord> it(*(g_pIrcServerDataBase->recordDict()));
+
+ while(KviIrcServerDataBaseRecord * r = it.current())
+ {
+ net = new KviServerOptionsListViewItem(m_pListView,*(g_pIconManager->getSmallIcon(KVI_SMALLICON_WORLD)),r->network());
+ KviPointerList<KviIrcServer> * sl = r->serverList();
+ bool bCurrent = r->network()->name() == g_pIrcServerDataBase->currentNetworkName().utf8().data();
+ net->setOpen(bCurrent);
+ for(KviIrcServer * s = sl->first();s;s = sl->next())
+ {
+ srv = new KviServerOptionsListViewItem(net,*(g_pIconManager->getSmallIcon(KVI_SMALLICON_SERVER)),s);
+
+ if((s == r->currentServer()) && bCurrent)
+ {
+ m_pListView->setSelected(srv,true);
+ cur = srv;
+ }
+ }
+ ++it;
+ }
+ if(cur)m_pListView->ensureItemVisible(cur);
+}
+
+void KviServerOptionsWidget::listViewItemSelectionChanged(KviTalListViewItem *it)
+{
+ saveLastItem();
+ m_pLastEditedItem = (KviServerOptionsListViewItem *)it;
+
+ if(m_pLastEditedItem)
+ {
+ m_pSrvNetLabel->setEnabled(true);
+ m_pSrvNetEdit->setEnabled(true);
+ m_pDetailsButton->setEnabled(true);
+ m_pConnectCurrent->setEnabled(m_pLastEditedItem->m_pServerData);
+
+ m_pRemoveButton->setEnabled(true);
+ m_pCopyServerButton->setEnabled(m_pLastEditedItem->m_pServerData);
+
+ if(m_pLastEditedItem->m_pServerData)
+ {
+ m_pSrvNetLabel->setText(__tr2qs_ctx("Server:","options"));
+ m_pSrvNetEdit->setText(m_pLastEditedItem->m_pServerData->m_szHostname);
+ } else {
+ m_pSrvNetLabel->setText(__tr2qs_ctx("Network:","options"));
+ m_pSrvNetEdit->setText(it->text(0));
+ }
+ } else {
+ m_pRemoveButton->setEnabled(false);
+ m_pCopyServerButton->setEnabled(true);
+
+ m_pConnectCurrent->setEnabled(false);
+ m_pSrvNetLabel->setEnabled(false);
+ m_pSrvNetEdit->setEnabled(false);
+ m_pSrvNetEdit->setText(__tr2qs_ctx("No selection","options"));
+ m_pDetailsButton->setEnabled(false);
+ }
+}
+
+
+
+void KviServerOptionsWidget::saveLastItem()
+{
+ if(!m_pLastEditedItem)return;
+ if(m_pLastEditedItem->m_pServerData)
+ {
+ KviStr tmp = m_pSrvNetEdit->text();
+ if(tmp.isEmpty())tmp = "irc.unknown.net";
+ m_pLastEditedItem->m_pServerData->m_szHostname = tmp;
+ m_pLastEditedItem->updateVisibleStrings();
+ } else if(m_pLastEditedItem->m_pNetworkData)
+ {
+ QString tmp = m_pSrvNetEdit->text();
+ if(tmp.isEmpty())tmp = __tr2qs_ctx("UnknownNet","options");
+ m_pLastEditedItem->m_pNetworkData->setName(tmp);
+ m_pLastEditedItem->updateVisibleStrings();
+ }
+}
+
+void KviServerOptionsWidget::commit()
+{
+ saveLastItem();
+ g_pIrcServerDataBase->clear();
+ KviServerOptionsListViewItem * it = (KviServerOptionsListViewItem *)m_pListView->firstChild();
+ while(it)
+ {
+ QString tmp = it->m_pNetworkData ? it->m_pNetworkData->name() : QString::null;
+ if(!tmp.isEmpty())
+ {
+ KviIrcNetwork * net = 0;
+ KviIrcServerDataBaseRecord * r = g_pIrcServerDataBase->findRecord(tmp);
+ if(r)
+ {
+ net = r->network();
+ net->copyFrom(*(it->m_pNetworkData));
+ } else {
+ net = new KviIrcNetwork(tmp);
+ net->copyFrom(*(it->m_pNetworkData));
+ r = g_pIrcServerDataBase->insertNetwork(net);
+ }
+ if(it == m_pLastEditedItem)g_pIrcServerDataBase->setCurrentNetwork(net->name());
+
+ KviServerOptionsListViewItem * ch = (KviServerOptionsListViewItem *)it->firstChild();
+ KviIrcServer *srv;
+
+ while(ch)
+ {
+ if(ch->m_pServerData)
+ {
+ if(!ch->m_pServerData->m_szHostname.isEmpty())
+ {
+ srv = r->findServer(ch->m_pServerData);
+ if(!srv)
+ {
+ srv = new KviIrcServer(*(ch->m_pServerData));
+ r->insertServer(srv);
+ } else *srv = *(ch->m_pServerData);
+ if(srv->id().isEmpty())srv->generateUniqueId();
+ if(ch == m_pLastEditedItem)
+ {
+ g_pIrcServerDataBase->setCurrentNetwork(net->name());
+ r->setCurrentServer(srv);
+ }
+ }
+ }
+ ch = (KviServerOptionsListViewItem *)ch->nextSibling();
+ }
+ }
+ it = (KviServerOptionsListViewItem *)it->nextSibling();
+ }
+
+ KviOptionsWidget::commit();
+}
+
+void KviServerOptionsWidget::listViewRightButtonPressed(KviTalListViewItem *it,const QPoint &pnt,int col)
+{
+ int id;
+ bool bServer = (it && ((KviServerOptionsListViewItem *)it)->m_pServerData);
+ m_pContextPopup->clear();
+ m_pContextPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_WORLD)),__tr2qs_ctx("New Network","options"),this,SLOT(newNetwork()));
+ id = m_pContextPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CUT)),__tr2qs_ctx("Remove Network","options"),this,SLOT(removeCurrent()));
+ m_pContextPopup->setItemEnabled(id,!bServer);
+ m_pContextPopup->insertSeparator();
+ id = m_pContextPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_SERVER)),__tr2qs_ctx("&New Server","options"),this,SLOT(newServer()));
+ id = m_pContextPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CUT)),__tr2qs_ctx("Re&move Server","options"),this,SLOT(removeCurrent()));
+ m_pContextPopup->setItemEnabled(id,bServer);
+ id = m_pContextPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_COPY)),__tr2qs_ctx("&Copy Server","options"),this,SLOT(copyServer()));
+ m_pContextPopup->setItemEnabled(id,bServer);
+ id = m_pContextPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_PASTE)),__tr2qs_ctx("&Paste Server","options"),this,SLOT(pasteServer()));
+ m_pContextPopup->setItemEnabled(id,m_pClipboard);
+
+ m_pContextPopup->insertSeparator();
+ // m_pContextPopup->insertItem(__c2q(__tr("Merge list from server.ini","options")),this,SLOT(importFromIni()));
+ m_pContextPopup->insertItem(__tr2qs_ctx("Clear List","options"),this,SLOT(clearList()));
+ m_pContextPopup->insertSeparator();
+ m_pContextPopup->insertItem(__tr2qs_ctx("Import List","options"),m_pImportPopup);
+ m_pContextPopup->popup(QCursor::pos());
+}
+
+void KviServerOptionsWidget::importPopupAboutToShow()
+{
+ g_pModuleManager->loadModulesByCaps("serverimport");
+ m_pImportPopup->clear();
+
+ KviModuleExtensionDescriptorList * l = KviModuleExtensionManager::instance()->getExtensionList("serverimport");
+
+ if(!l)return;
+
+ int id;
+
+ for(KviModuleExtensionDescriptor * d = l->first();d;d = l->next())
+ {
+ if(d->icon())
+ id = m_pImportPopup->insertItem(*(d->icon()),d->visibleName());
+ else
+ id = m_pImportPopup->insertItem(d->visibleName());
+ m_pImportPopup->setItemParameter(id,d->id());
+ }
+}
+
+void KviServerOptionsWidget::importPopupActivated(int id)
+{
+ // ensure that we have all the modules : they could have been unloaded while the popup was displayed
+ g_pModuleManager->loadModulesByCaps("serverimport");
+
+ KviModuleExtensionDescriptorList * l = KviModuleExtensionManager::instance()->getExtensionList("serverimport");
+
+ if(!l)
+ {
+ // ops.. internal error: I thought to have a module capable of importing servers
+ // but actually it's not the case.. something weird happened (in the best case
+ // the user has just unloaded the module and removed it from disk ?)
+ KviMessageBox::warning(__tr2qs_ctx("Oops... something weird happened:<br>Can't find any module capable of importing servers.","options"));
+ return;
+ }
+
+ if(m_pImportFilter)
+ {
+ disconnect(m_pImportFilter,0,this,0);
+ m_pImportFilter->die();
+ m_pImportFilter = 0;
+ }
+
+ id = m_pImportPopup->itemParameter(id);
+
+ m_pImportFilter = (KviMexServerImport *)KviModuleExtensionManager::instance()->allocateExtension("serverimport",id,0);
+
+ if(!m_pImportFilter)
+ {
+ KviMessageBox::warning(__tr2qs_ctx("Oops... something weird happened:<br>Can't find the module that was capable of this import action. :(","options"));
+ return;
+ }
+
+ connect(m_pImportFilter,SIGNAL(server(const KviIrcServer &,const char *)),this,SLOT(importServer(const KviIrcServer &,const char *)));
+ connect(m_pImportFilter,SIGNAL(destroyed()),this,SLOT(importerDead()));
+
+ m_pImportFilter->start();
+}
+
+void KviServerOptionsWidget::importerDead()
+{
+ m_pImportFilter = 0;
+}
+
+void KviServerOptionsWidget::importServer(const KviIrcServer &s,const char * network)
+{
+ KviServerOptionsListViewItem * net = findNetItem(network);
+ if(!net)
+ {
+ KviIrcNetwork d(network);
+ net = new KviServerOptionsListViewItem(m_pListView,*(g_pIconManager->getSmallIcon(KVI_SMALLICON_WORLD)),&d);
+ net->setOpen(true);
+ }
+
+ for(KviServerOptionsListViewItem * srv = (KviServerOptionsListViewItem *)net->firstChild();srv;srv = (KviServerOptionsListViewItem *)srv->nextSibling())
+ {
+ if((srv)->m_pServerData->useSSL() == s.useSSL())
+ {
+ if(srv->m_pServerData->isIpV6() == s.isIpV6())
+ {
+ if(KviQString::equalCI(srv->m_pServerData->hostName(),s.hostName()))
+ {
+ // update the port
+ srv->m_pServerData->setPort(s.port());
+ if(!s.ipAddress().isEmpty())srv->m_pServerData->setIpAddress(s.ipAddress());
+ if(!s.password().isEmpty())srv->m_pServerData->setPassword(s.password());
+ if(!s.nickName().isEmpty())srv->m_pServerData->setNickName(s.nickName());
+ m_pListView->setCurrentItem(srv);
+ m_pListView->ensureItemVisible(srv);
+ return;
+ }
+ }
+ }
+ }
+
+ // not found : add it!
+ KviServerOptionsListViewItem * newServer = new KviServerOptionsListViewItem(net,*(g_pIconManager->getSmallIcon(KVI_SMALLICON_SERVER)),&s);
+ m_pListView->setCurrentItem(newServer);
+ m_pListView->ensureItemVisible(newServer);
+}
+
+void KviServerOptionsWidget::newNetwork()
+{
+ KviIrcNetwork d(__tr2qs_ctx("New Network","options"));
+ KviServerOptionsListViewItem * it = new KviServerOptionsListViewItem(m_pListView,*(g_pIconManager->getSmallIcon(KVI_SMALLICON_WORLD)),&d);
+ it->setOpen(true);
+ m_pListView->setSelected(it,true);
+ m_pListView->ensureItemVisible(it);
+}
+
+void KviServerOptionsWidget::newServer()
+{
+ if(m_pLastEditedItem)
+ {
+ KviServerOptionsListViewItem * net;
+ if(m_pLastEditedItem->m_pServerData)
+ {
+ net = (KviServerOptionsListViewItem *)m_pLastEditedItem->parent();
+ if(!net)return;
+ }
+ else net = m_pLastEditedItem;
+
+ KviIrcServer tmp;
+ tmp.m_szHostname = __tr2qs_ctx("irc.unknown.net","options");
+ tmp.setCacheIp(false);
+ tmp.generateUniqueId();
+
+ KviServerOptionsListViewItem * it = new KviServerOptionsListViewItem(net,
+ *(g_pIconManager->getSmallIcon(KVI_SMALLICON_SERVER)),&tmp);
+
+ net->setOpen(true);
+
+ m_pListView->setSelected(it,true);
+ m_pListView->ensureItemVisible(it);
+ }
+}
+
+void KviServerOptionsWidget::copyServer()
+{
+ if(m_pLastEditedItem)
+ {
+ if(m_pLastEditedItem->m_pServerData)
+ {
+ if(!m_pClipboard)m_pClipboard = new KviIrcServer();
+ *m_pClipboard = *(m_pLastEditedItem->m_pServerData);
+ m_pPasteServerButton->setEnabled(true);
+ }
+ }
+}
+
+void KviServerOptionsWidget::pasteServer()
+{
+ if(m_pClipboard)
+ {
+ if(m_pLastEditedItem)
+ {
+ KviServerOptionsListViewItem * net;
+ if(m_pLastEditedItem->m_pServerData)
+ {
+ net = (KviServerOptionsListViewItem *)m_pLastEditedItem->parent();
+ if(!net)return;
+ }
+ else net = m_pLastEditedItem;
+
+ KviServerOptionsListViewItem * it = new KviServerOptionsListViewItem(net,
+ *(g_pIconManager->getSmallIcon(KVI_SMALLICON_SERVER)),m_pClipboard);
+
+ net->setOpen(true);
+
+ m_pListView->setSelected(it,true);
+ m_pListView->ensureItemVisible(it);
+ }
+ }
+}
+
+void KviServerOptionsWidget::removeCurrent()
+{
+ if(m_pLastEditedItem)
+ {
+ KviTalListViewItem * it = m_pLastEditedItem->itemAbove();
+ if(!it)it = m_pLastEditedItem->firstChild() ? m_pLastEditedItem->nextSibling() : m_pLastEditedItem->itemBelow();
+ delete m_pLastEditedItem;
+ m_pLastEditedItem = 0;
+ if(!it)it = m_pListView->firstChild();
+ if(it)
+ {
+ m_pListView->setSelected(it,true);
+ m_pListView->ensureItemVisible(it);
+ }
+ }
+}
+
+KviServerOptionsListViewItem * KviServerOptionsWidget::findNetItem(const char * netname)
+{
+ KviServerOptionsListViewItem * it = (KviServerOptionsListViewItem *)m_pListView->firstChild();
+ while(it)
+ {
+ KviStr szNetName = it->text(0);
+ if(kvi_strEqualCI(szNetName.ptr(),netname))return it;
+ it = (KviServerOptionsListViewItem *)it->nextSibling();
+ }
+ return 0;
+}
+
+void KviServerOptionsWidget::clearList()
+{
+ m_pListView->clear();
+ m_pLastEditedItem = 0;
+ listViewItemSelectionChanged(0);
+}
+
+void KviServerOptionsWidget::detailsClicked()
+{
+ if(!m_pLastEditedItem)return;
+ if(m_pLastEditedItem->m_pServerData)
+ {
+ saveLastItem();
+
+ m_pServerDetailsDialog = new KviServerDetailsWidget(this,m_pLastEditedItem->m_pServerData);
+
+ int retCode = m_pServerDetailsDialog->exec();
+ if(retCode == QDialog::Accepted)
+ {
+ if(m_pLastEditedItem)
+ {
+ if(m_pLastEditedItem->m_pServerData)
+ {
+ m_pServerDetailsDialog->fillData(m_pLastEditedItem->m_pServerData);
+ saveLastItem();
+ }
+ }
+ }
+
+ delete m_pServerDetailsDialog;
+ m_pServerDetailsDialog = 0;
+ return;
+ }
+ if(m_pLastEditedItem->m_pNetworkData)
+ {
+ saveLastItem();
+
+ m_pNetworkDetailsDialog = new KviNetworkDetailsWidget(this,m_pLastEditedItem->m_pNetworkData);
+
+ int retCode = m_pNetworkDetailsDialog->exec();
+ if(retCode == QDialog::Accepted)
+ {
+ if(m_pLastEditedItem)
+ {
+ if(m_pLastEditedItem->m_pNetworkData)
+ {
+ m_pNetworkDetailsDialog->fillData(m_pLastEditedItem->m_pNetworkData);
+ saveLastItem();
+ }
+ }
+ }
+
+ delete m_pNetworkDetailsDialog;
+ m_pNetworkDetailsDialog = 0;
+ }
+}
+
+#include "m_optw_servers.moc"
diff --git a/src/modules/options/optw_servers.h b/src/modules/options/optw_servers.h
new file mode 100644
index 00000000..ea71c6d3
--- /dev/null
+++ b/src/modules/options/optw_servers.h
@@ -0,0 +1,210 @@
+#ifndef _OPTW_SERVERS_H_
+#define _OPTW_SERVERS_H_
+
+//=============================================================================
+//
+// File : optw_servers.h
+// Creation date : Wed Jun 12 2000 03:29:01 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_optionswidget.h"
+#include "kvi_tal_listview.h"
+#include <qdialog.h>
+#include <qbuttongroup.h>
+#include <qtabwidget.h>
+
+class KviIrcServer;
+class KviIrcNetwork;
+class KviIrcNetworkData;
+class KviMexServerImport;
+
+
+
+class KviServerOptionsListViewItem : public KviTalListViewItem
+{
+public:
+ KviServerOptionsListViewItem(KviTalListView *parent,const QPixmap &pm,const KviIrcNetwork *n);
+ KviServerOptionsListViewItem(KviTalListViewItem *parent,const QPixmap &pm,const KviIrcServer *s);
+ ~KviServerOptionsListViewItem();
+public:
+ KviIrcServer * m_pServerData;
+ KviIrcNetwork * m_pNetworkData;
+public:
+ void updateVisibleStrings();
+};
+
+class QLabel;
+class QLineEdit;
+class KviIpEditor;
+class KviIrcServer;
+class QCheckBox;
+class KviTalPopupMenu;
+class KviScriptEditor;
+class QComboBox;
+class QPushButton;
+class QToolButton;
+class KviNickServRule;
+class KviNickServRuleEditor;
+
+
+class KviNetworkDetailsWidget : public QDialog
+{
+ Q_OBJECT
+public:
+ KviNetworkDetailsWidget(QWidget * par,KviIrcNetwork * d);
+ ~KviNetworkDetailsWidget();
+protected:
+ KviScriptEditor * m_pOnConnectEditor;
+ KviScriptEditor * m_pOnLoginEditor;
+
+ QLineEdit * m_pUserEditor;
+ QLineEdit * m_pPassEditor;
+ QLineEdit * m_pNickEditor;
+ QLineEdit * m_pRealEditor;
+ QLineEdit * m_pDescEditor;
+
+ QComboBox * m_pEncodingEditor;
+
+ QCheckBox * m_pAutoConnectCheck;
+
+ KviTalListView * m_pNickServListView;
+ QCheckBox * m_pNickServCheck;
+ QPushButton * m_pAddRuleButton;
+ QPushButton * m_pDelRuleButton;
+ QPushButton * m_pEditRuleButton;
+
+ QStringList m_lstChannels;
+ KviCahnnelListSelector * m_pChannelListSelector;
+public:
+ void fillData(KviIrcNetwork * d);
+protected slots:
+ void enableDisableNickServControls();
+ void addNickServRule();
+ void delNickServRule();
+ void editNickServRule();
+};
+
+class KviServerDetailsWidget : public QDialog
+{
+ Q_OBJECT
+public:
+ KviServerDetailsWidget(QWidget * par,KviIrcServer * s);
+ ~KviServerDetailsWidget();
+protected:
+ QString m_szHostname;
+ QLabel * m_pHeaderLabel;
+ KviScriptEditor * m_pOnConnectEditor;
+ KviScriptEditor * m_pOnLoginEditor;
+ QLineEdit * m_pUserEditor;
+ QLineEdit * m_pPassEditor;
+ QLineEdit * m_pNickEditor;
+ QLineEdit * m_pRealEditor;
+ QLineEdit * m_pDescEditor;
+ QLineEdit * m_pIdEditor;
+ QComboBox * m_pLinkFilterEditor;
+ QComboBox * m_pEncodingEditor;
+ KviIpEditor * m_pIpEditor;
+ QCheckBox * m_pCacheIpCheck;
+ QCheckBox * m_pUseSSLCheck;
+ QCheckBox * m_pUseDefaultInitUMode;
+ QCheckBox * m_pIMode;
+ QCheckBox * m_pWMode;
+ QCheckBox * m_pSMode;
+ QCheckBox * m_pUseAutoConnect;
+ QCheckBox * m_pUseIPV6Check;
+ QLineEdit * m_pPortEditor;
+ QStringList m_lstChannels;
+ KviCahnnelListSelector * m_pChannelListSelector;
+
+ QComboBox * m_pProxyEditor;
+protected slots:
+ void useDefaultInitUModeToggled(bool);
+ void portEditorTextChanged(const QString &);
+ void useIPV6CheckToggled(bool);
+public:
+ void setHeaderLabelText();
+ void fillData(KviIrcServer *s);
+};
+
+
+#define KVI_OPTIONS_WIDGET_ICON_KviServerOptionsWidget KVI_SMALLICON_SERVER
+#define KVI_OPTIONS_WIDGET_NAME_KviServerOptionsWidget __tr2qs_no_lookup("Servers")
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviServerOptionsWidget __tr2qs_no_lookup("connection")
+//#define KVI_OPTIONS_WIDGET_NOPARENT_KviServerOptionsWidget KviConnectionOptionsWidget
+#define KVI_OPTIONS_WIDGET_PRIORITY_KviServerOptionsWidget 99000
+
+class KviServerOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviServerOptionsWidget(QWidget * parent);
+ ~KviServerOptionsWidget();
+protected:
+ KviTalListView * m_pListView;
+ QLabel * m_pSrvNetLabel;
+ QLineEdit * m_pSrvNetEdit;
+ //QLabel * m_pPortLabel;
+ //QLineEdit * m_pPortEdit;
+ QPushButton * m_pDetailsButton;
+ KviTalPopupMenu * m_pRecentPopup;
+ KviTalPopupMenu * m_pContextPopup;
+ KviTalPopupMenu * m_pImportPopup;
+ KviIrcServer * m_pClipboard;
+ //QCheckBox * m_pIpV6Check;
+ QPushButton * m_pConnectCurrent;
+ QPushButton * m_pConnectNew;
+ KviServerOptionsListViewItem * m_pLastEditedItem;
+ KviServerDetailsWidget * m_pServerDetailsDialog;
+ KviNetworkDetailsWidget * m_pNetworkDetailsDialog;
+ KviMexServerImport * m_pImportFilter;
+
+ QToolButton * m_pNewServerButton;
+ QToolButton * m_pNewNetworkButton;
+ QToolButton * m_pRemoveButton;
+ QToolButton * m_pCopyServerButton;
+ QToolButton * m_pPasteServerButton;
+ QToolButton * m_pImportButton;
+private:
+ void fillServerList();
+ void saveLastItem();
+ KviServerOptionsListViewItem * findNetItem(const char * netname);
+protected slots:
+ void importerDead();
+ void importServer(const KviIrcServer & s,const char * network);
+ void importPopupAboutToShow();
+ void listViewItemSelectionChanged(KviTalListViewItem *it);
+ void listViewRightButtonPressed(KviTalListViewItem *it,const QPoint &pnt,int col);
+ void newNetwork();
+ void removeCurrent();
+ void newServer();
+ void copyServer();
+ void pasteServer();
+ void clearList();
+ void detailsClicked();
+ void connectCurrentClicked();
+ void recentServersPopupAboutToShow();
+ void recentServersPopupClicked(int id);
+ void importPopupActivated(int id);
+public:
+ virtual void commit();
+};
+
+#endif //!_OPTW_SERVERS_H_
diff --git a/src/modules/options/optw_sound.cpp b/src/modules/options/optw_sound.cpp
new file mode 100644
index 00000000..9fec0a0c
--- /dev/null
+++ b/src/modules/options/optw_sound.cpp
@@ -0,0 +1,310 @@
+//=============================================================================
+//
+// File : optw_sound.cpp
+// Creation date : Fri Sep 6 02:18:23 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVsound sound client distribution
+// Copyright (C) 2002-2006 Szymon Stefanek (pragma at kvsound dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "optw_sound.h"
+
+#include "kvi_settings.h"
+#include "kvi_locale.h"
+#include "kvi_options.h"
+#include "kvi_modulemanager.h"
+#include "kvi_pointerlist.h"
+#include "kvi_string.h"
+
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include "kvi_tal_hbox.h"
+
+#ifdef COMPILE_INFO_TIPS
+ #include "kvi_tal_tooltip.h"
+#endif
+
+// FIXME: This module doesn't Cancel properly when auto-detection is performed!
+
+
+
+KviSoundOptionsWidget::KviSoundOptionsWidget(QWidget * pParent)
+: KviOptionsWidget(pParent)
+{
+}
+
+KviSoundOptionsWidget::~KviSoundOptionsWidget()
+{
+}
+
+
+KviSoundGeneralOptionsWidget::KviSoundGeneralOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"sound_system_options_widget")
+{
+#ifdef COMPILE_ON_WINDOWS
+ createLayout(4,1);
+#else
+ createLayout(3,1);
+#endif
+ KviTalGroupBox * g = addGroupBox(0,0,0,0,1,Qt::Horizontal,__tr2qs_ctx("Sound System","options"),true);
+
+ KviTalToolTip::add(g,__tr2qs_ctx("This allows you to select the sound system to be used with KVIrc.","options"));
+
+ KviTalHBox * h = new KviTalHBox(g);
+
+ m_pSoundSystemBox = new QComboBox(false,h);
+
+ m_pSoundAutoDetectButton = new QPushButton(__tr2qs_ctx("Auto-detect","options"),h);
+ connect(m_pSoundAutoDetectButton,SIGNAL(clicked()),this,SLOT(soundAutoDetect()));
+
+ m_pSoundTestButton = new QPushButton(__tr2qs_ctx("Test","options"),h);
+ connect(m_pSoundTestButton,SIGNAL(clicked()),this,SLOT(soundTest()));
+
+
+ g = addGroupBox(0,1,0,1,1,Qt::Horizontal,__tr2qs_ctx("Media Player","options"),true);
+
+ KviTalToolTip::add(g,__tr2qs_ctx("This allows you to select the preferred media player to be used with " \
+ "the mediaplayer.* module commands and functions.","options"));
+
+ h = new KviTalHBox(g);
+
+ m_pMediaPlayerBox = new QComboBox(false,h);
+
+ m_pMediaAutoDetectButton = new QPushButton(__tr2qs_ctx("Auto-detect","options"),h);
+ connect(m_pMediaAutoDetectButton,SIGNAL(clicked()),this,SLOT(mediaAutoDetect()));
+
+ m_pMediaTestButton = new QPushButton(__tr2qs_ctx("Test","options"),h);
+ connect(m_pMediaTestButton,SIGNAL(clicked()),this,SLOT(mediaTest()));
+
+ addRowSpacer(0,2,0,2);
+
+ soundFillBox();
+ mediaFillBox();
+ // FIXME!
+ m_pSoundTestButton->setEnabled(false);
+ m_pMediaTestButton->setEnabled(false);
+
+ g = addGroupBox(0,2,0,2,1,Qt::Horizontal,__tr2qs_ctx("ID3 tags' encoding","options"),true);
+
+ KviTalToolTip::add(g,__tr2qs_ctx("This allows you to select encoding of mp3 tags.","options"));
+
+ h = new KviTalHBox(g);
+
+ m_pTagsEncodingCombo = new QComboBox(false,h);
+ m_pTagsEncodingCombo->insertItem(__tr2qs_ctx("Use Language Encoding","options"));
+
+ int i = 0;
+ int iMatch = 0;
+
+ KviLocale::EncodingDescription * d = KviLocale::encodingDescription(i);
+ while(d->szName)
+ {
+ if(KviQString::equalCI(d->szName,KVI_OPTION_STRING(KviOption_stringMp3TagsEncoding)))iMatch = i + 1;
+ m_pTagsEncodingCombo->insertItem(d->szName);
+ i++;
+ d = KviLocale::encodingDescription(i);
+ }
+ m_pTagsEncodingCombo->setCurrentItem(iMatch);
+
+#ifdef COMPILE_ON_WINDOWS
+ g = addGroupBox(0,3,0,3,1,Qt::Horizontal,__tr2qs_ctx("Winamp messages ecoding","options"),true);
+
+ KviTalToolTip::add(g,__tr2qs_ctx("This allows you to select encoding of winamp messages.","options"));
+
+ h = new KviTalHBox(g);
+
+ m_pWinampEncodingCombo = new QComboBox(false,h);
+
+ m_pWinampEncodingCombo->insertItem(__tr2qs_ctx("Use Language Encoding","options"));
+ i = 0;
+ iMatch = 0;
+
+ d = KviLocale::encodingDescription(i);
+ while(d->szName)
+ {
+ if(KviQString::equalCI(d->szName,KVI_OPTION_STRING(KviOption_stringWinampTextEncoding)))iMatch = i + 1;
+ m_pWinampEncodingCombo->insertItem(d->szName);
+ i++;
+ d = KviLocale::encodingDescription(i);
+ }
+ m_pWinampEncodingCombo->setCurrentItem(iMatch);
+#endif
+}
+
+
+KviSoundGeneralOptionsWidget::~KviSoundGeneralOptionsWidget()
+{
+}
+
+void KviSoundGeneralOptionsWidget::soundTest()
+{
+}
+
+void KviSoundGeneralOptionsWidget::mediaTest()
+{
+}
+
+
+void KviSoundGeneralOptionsWidget::soundAutoDetect()
+{
+ KviModule * m = g_pModuleManager->getModule("snd");
+ if(!m)return;
+ m->ctrl("detectSoundSystem",0);
+ soundFillBox();
+}
+
+void KviSoundGeneralOptionsWidget::mediaAutoDetect()
+{
+ KviModule * m = g_pModuleManager->getModule("mediaplayer");
+ if(!m)return;
+ m->ctrl("detectMediaPlayer",0);
+ mediaFillBox();
+}
+
+
+void KviSoundGeneralOptionsWidget::soundFillBox()
+{
+
+ QStringList l;
+ QStringList::Iterator it;
+ int cnt;
+ int i;
+ KviModule * m = g_pModuleManager->getModule("snd");
+
+
+ if(!m)goto disable;
+
+
+ if(!m->ctrl("getAvailableSoundSystems",&l))goto disable;
+
+ m_pSoundSystemBox->clear();
+
+ for ( it = l.begin(); it != l.end(); ++it )
+ {
+ m_pSoundSystemBox->insertItem(*it);
+ }
+
+ cnt = m_pSoundSystemBox->count();
+
+ for(i=0;i<cnt;i++)
+ {
+ QString t = m_pSoundSystemBox->text(i);
+ if(KviQString::equalCI(t,KVI_OPTION_STRING(KviOption_stringSoundSystem)))
+ {
+ m_pSoundSystemBox->setCurrentItem(i);
+ break;
+ }
+ }
+
+ return;
+disable:
+ m_pSoundSystemBox->clear();
+ m_pSoundSystemBox->setEnabled(false);
+ m_pSoundTestButton->setEnabled(false);
+ m_pSoundAutoDetectButton->setEnabled(false);
+}
+
+void KviSoundGeneralOptionsWidget::mediaFillBox()
+{
+ QStringList l;
+ QStringList::Iterator it;
+ int cnt;
+ int i;
+ KviModule * m = g_pModuleManager->getModule("mediaplayer");
+
+ if(!m)goto disable;
+ if(!m->ctrl("getAvailableMediaPlayers",&l))goto disable;
+ m_pMediaPlayerBox->clear();
+ for ( it = l.begin(); it != l.end(); ++it )
+ {
+ m_pMediaPlayerBox->insertItem(*it);
+ }
+ cnt = m_pMediaPlayerBox->count();
+
+ for(i=0;i<cnt;i++)
+ {
+ QString t = m_pMediaPlayerBox->text(i);
+ if(KviQString::equalCI(t,KVI_OPTION_STRING(KviOption_stringPreferredMediaPlayer)))
+ {
+ m_pMediaPlayerBox->setCurrentItem(i);
+ break;
+ }
+ }
+
+ return;
+disable:
+ m_pMediaPlayerBox->clear();
+ m_pMediaPlayerBox->setEnabled(false);
+ m_pMediaTestButton->setEnabled(false);
+ m_pMediaAutoDetectButton->setEnabled(false);
+}
+
+
+void KviSoundGeneralOptionsWidget::commit()
+{
+ KviOptionsWidget::commit();
+ KVI_OPTION_STRING(KviOption_stringSoundSystem) = m_pSoundSystemBox->currentText();
+ KVI_OPTION_STRING(KviOption_stringPreferredMediaPlayer) = m_pMediaPlayerBox->currentText();
+
+ int idx = m_pTagsEncodingCombo->currentItem();
+ if(idx <= 0)
+ {
+ // guess from locale
+ KVI_OPTION_STRING(KviOption_stringMp3TagsEncoding) = "";
+ } else {
+ KVI_OPTION_STRING(KviOption_stringMp3TagsEncoding) = m_pTagsEncodingCombo->text(idx);
+ }
+
+
+#ifdef COMPILE_ON_WINDOWS
+ idx = m_pWinampEncodingCombo->currentItem();
+ if(idx <= 0)
+ {
+ // guess from locale
+ KVI_OPTION_STRING(KviOption_stringWinampTextEncoding) = "";
+ } else {
+ KVI_OPTION_STRING(KviOption_stringWinampTextEncoding) = m_pWinampEncodingCombo->text(idx);
+ }
+#endif
+}
+
+KviSoundsOptionsWidget::KviSoundsOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"sound_options_widget")
+{
+ createLayout(5,2);
+ addLabel(0,0,0,0,__tr2qs_ctx("New Query opened","options"));
+ addSoundSelector(1,0,1,0,"",KviOption_stringOnNewQueryOpenedSound);
+
+ addLabel(0,1,0,1,__tr2qs_ctx("New message in inactive query","options"));
+ addSoundSelector(1,1,1,1,"",KviOption_stringOnQueryMessageSound);
+
+ addLabel(0,2,0,2,__tr2qs_ctx("Highlighted message in inactive window","options"));
+ addSoundSelector(1,2,1,2,"",KviOption_stringOnHighlightedMessageSound);
+
+ addLabel(0,3,0,3,__tr2qs_ctx("Me have been kicked","options"));
+ addSoundSelector(1,3,1,3,"",KviOption_stringOnMeKickedSound);
+
+ addRowSpacer(0,4,1,4);
+
+}
+
+KviSoundsOptionsWidget::~KviSoundsOptionsWidget()
+{
+}
+
+#include "m_optw_sound.moc"
diff --git a/src/modules/options/optw_sound.h b/src/modules/options/optw_sound.h
new file mode 100644
index 00000000..37b3c0ed
--- /dev/null
+++ b/src/modules/options/optw_sound.h
@@ -0,0 +1,94 @@
+#ifndef _OPTW_SOUND_H_
+#define _OPTW_SOUND_H_
+//=============================================================================
+//
+// File : optw_sound.h
+// Creation date : Fri Sep 6 02:18:21 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002-2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_optionswidget.h"
+#include <qcombobox.h>
+#include <qpushbutton.h>
+
+#define KVI_OPTIONS_WIDGET_ICON_KviSoundOptionsWidget KVI_SMALLICON_SOUND
+#define KVI_OPTIONS_WIDGET_NAME_KviSoundOptionsWidget __tr2qs_no_lookup("Sound")
+#define KVI_OPTIONS_WIDGET_PARENT_KviSoundOptionsWidget KviGeneralOptOptionsWidget
+#define KVI_OPTIONS_WIDGET_CONTAINER_KviSoundOptionsWidget true
+
+
+class KviSoundOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviSoundOptionsWidget(QWidget * parent);
+ ~KviSoundOptionsWidget();
+};
+
+#define KVI_OPTIONS_WIDGET_ICON_KviSoundGeneralOptionsWidget KVI_SMALLICON_SOUND
+#define KVI_OPTIONS_WIDGET_NAME_KviSoundGeneralOptionsWidget __tr2qs_no_lookup("Sound System")
+#define KVI_OPTIONS_WIDGET_PARENT_KviSoundGeneralOptionsWidget KviSoundOptionsWidget
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviSoundGeneralOptionsWidget __tr2qs_no_lookup("sound,xmms,audio,play,amarok")
+#define KVI_OPTIONS_WIDGET_PRIORITY_KviSoundGeneralOptionsWidget 70000
+
+class KviSoundGeneralOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviSoundGeneralOptionsWidget(QWidget * parent);
+ ~KviSoundGeneralOptionsWidget();
+protected:
+ QComboBox * m_pSoundSystemBox;
+ QPushButton * m_pSoundTestButton;
+ QPushButton * m_pSoundAutoDetectButton;
+ QComboBox * m_pMediaPlayerBox;
+ QPushButton * m_pMediaTestButton;
+ QPushButton * m_pMediaAutoDetectButton;
+
+#ifdef COMPILE_ON_WINDOWS
+ QComboBox * m_pWinampEncodingCombo;
+#endif
+ QComboBox * m_pTagsEncodingCombo;
+protected:
+ void soundFillBox();
+ void mediaFillBox();
+ virtual void commit();
+protected slots:
+ void soundTest();
+ void soundAutoDetect();
+ void mediaTest();
+ void mediaAutoDetect();
+};
+
+#define KVI_OPTIONS_WIDGET_ICON_KviSoundsOptionsWidget KVI_SMALLICON_SOUND
+#define KVI_OPTIONS_WIDGET_NAME_KviSoundsOptionsWidget __tr2qs_no_lookup("Sounds")
+#define KVI_OPTIONS_WIDGET_PARENT_KviSoundsOptionsWidget KviSoundOptionsWidget
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviSoundsOptionsWidget __tr2qs_no_lookup("sound,events")
+#define KVI_OPTIONS_WIDGET_PRIORITY_KviSoundsOptionsWidget 80000
+
+class KviSoundsOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviSoundsOptionsWidget(QWidget * parent);
+ ~KviSoundsOptionsWidget();
+};
+
+#endif //_OPTW_SOUND_H_
diff --git a/src/modules/options/optw_ssl.cpp b/src/modules/options/optw_ssl.cpp
new file mode 100644
index 00000000..bf3ef46a
--- /dev/null
+++ b/src/modules/options/optw_ssl.cpp
@@ -0,0 +1,35 @@
+//
+// File : optw_ssl.cpp
+// Creation date : Thu Jul 20 20:52:30 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "optw_ssl.h"
+
+#include <qlayout.h>
+#include <kvi_tal_groupbox.h>
+
+#include "kvi_options.h"
+#include "kvi_locale.h"
+
+//#warning "Info tips"
+
+
+
+#include "m_optw_ssl.moc"
diff --git a/src/modules/options/optw_ssl.h b/src/modules/options/optw_ssl.h
new file mode 100644
index 00000000..9b7db6de
--- /dev/null
+++ b/src/modules/options/optw_ssl.h
@@ -0,0 +1,29 @@
+#ifndef _OPTW_SSL_H_
+#define _OPTW_SSL_H_
+//
+// File : optw_ssl.h
+// Creation date : Thu Jul 20 20:52:30 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_optionswidget.h"
+
+
+
+#endif //_OPTW_SSL_H_
diff --git a/src/modules/options/optw_taskbar.cpp b/src/modules/options/optw_taskbar.cpp
new file mode 100644
index 00000000..1b146d39
--- /dev/null
+++ b/src/modules/options/optw_taskbar.cpp
@@ -0,0 +1,255 @@
+//
+// File : optw_taskbar.cpp
+// Creation date : Wed Jan 16 04:30:39 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "optw_taskbar.h"
+
+#include "kvi_settings.h"
+#include "kvi_locale.h"
+#include "kvi_options.h"
+
+
+KviTaskBarOptionsWidget::KviTaskBarOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"taskbar_options_widget")
+{
+
+ createLayout(7,1);
+
+ addBoolSelector(0,0,0,0,__tr2qs_ctx("Use tree taskbar","options"),KviOption_boolUseTreeWindowListTaskBar);
+ addBoolSelector(0,1,0,1,__tr2qs_ctx("Sort windows by name","options"),KviOption_boolSortTaskBarItemsByName);
+ addBoolSelector(0,2,0,2,__tr2qs_ctx("Show window icons in taskbar","options"),KviOption_boolUseTaskBarIcons);
+ KviBoolSelector * b = addBoolSelector(0,3,0,3,__tr2qs_ctx("Show activity meter in taskbar","options"),KviOption_boolUseTaskBarActivityMeter);
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(b,__tr2qs_ctx("<center>This option enables the usage of the taskbar activity meter. " \
+ "Each window entry will have a small indicator of the activity that is going on in that window. " \
+ "The indicator is a small square that changes colors, dark colors mean low activity, " \
+ "while bright colors signal high activity. KVIrc also uses some heuristics to determine " \
+ "whether the activity is somewhat \"human\" or it is generated by automated entities (such as bots " \
+ "or IRC servers). \"Human\" activity causes the indicator to be shaded red while automated " \
+ "activity causes the indicator to be shaded blue.</center>","options"));
+#endif
+ addBoolSelector(0,4,0,4,__tr2qs_ctx("Show IRC context indicator in taskbar","options"),KviOption_boolUseTaskBarIrcContextIndicator);
+ addBoolSelector(0,5,0,5,__tr2qs_ctx("Enable window tooltips","options"),KviOption_boolShowTaskBarToolTips);
+ addRowSpacer(0,6,0,6);
+}
+
+
+KviTaskBarOptionsWidget::~KviTaskBarOptionsWidget()
+{
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+KviTreeTaskBarOptionsWidget::KviTreeTaskBarOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"treetaskbar_options_widget")
+{
+}
+
+KviTreeTaskBarOptionsWidget::~KviTreeTaskBarOptionsWidget()
+{
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+KviTreeTaskBarForegroundOptionsWidget::KviTreeTaskBarForegroundOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"treetaskbar_options_widget")
+{
+ createLayout(3,1);
+
+ KviTalGroupBox *g = addGroupBox(0,0,0,0,2,Qt::Horizontal,__tr2qs_ctx("Text/Alert Colors","options"));
+
+ addColorSelector(g,__tr2qs_ctx("Normal:","options"),KviOption_colorTreeTaskBarForeground);
+ addColorSelector(g,__tr2qs_ctx("Selected:","options"),KviOption_colorTreeTaskBarActiveForeground);
+ addColorSelector(g,__tr2qs_ctx("Alert Level 1:","options"),KviOption_colorTreeTaskBarHighlight1Foreground);
+ addColorSelector(g,__tr2qs_ctx("Alert Level 2:","options"),KviOption_colorTreeTaskBarHighlight2Foreground);
+ addColorSelector(g,__tr2qs_ctx("Alert Level 3:","options"),KviOption_colorTreeTaskBarHighlight3Foreground);
+ addColorSelector(g,__tr2qs_ctx("Alert Level 4:","options"),KviOption_colorTreeTaskBarHighlight4Foreground);
+ addColorSelector(g,__tr2qs_ctx("Alert Level 5:","options"),KviOption_colorTreeTaskBarHighlight5Foreground);
+
+ addColorSelector(0,1,0,1,__tr2qs_ctx("Progress bar color:","options"),KviOption_colorTreeTaskBarProgress);
+
+ addRowSpacer(0,2,0,2);
+}
+
+
+KviTreeTaskBarForegroundOptionsWidget::~KviTreeTaskBarForegroundOptionsWidget()
+{
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+KviTreeTaskBarBackgroundOptionsWidget::KviTreeTaskBarBackgroundOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"treetaskbar_options_widget")
+{
+ createLayout(4,2);
+
+ KviTalGroupBox * g = addGroupBox(0,0,1,0,2,Qt::Horizontal,__tr2qs_ctx("Background Colors","options"));
+ addColorSelector(g,__tr2qs_ctx("Normal:","options"),KviOption_colorTreeTaskBarBackground);
+ addColorSelector(g,__tr2qs_ctx("Selected:","options"),KviOption_colorTreeTaskBarActiveBackground);
+
+ addPixmapSelector(0,1,1,1,__tr2qs_ctx("Background image:","options"),KviOption_pixmapTreeTaskBarBackground);
+
+ addLabel(0,2,0,2,__tr2qs_ctx("Horizontal align:","options"));
+ m_pHorizontalAlign=new QComboBox(this);
+ addWidgetToLayout(m_pHorizontalAlign,1,2,1,2);
+
+ addLabel(0,3,0,3,__tr2qs_ctx("Vertical align:","options"));
+ m_pVerticalAlign=new QComboBox(this);
+ addWidgetToLayout(m_pVerticalAlign,1,3,1,3);
+
+ m_pHorizontalAlign->insertItem(__tr2qs_ctx("Tile","options"));
+ m_pHorizontalAlign->insertItem(__tr2qs_ctx("Left","options"));
+ m_pHorizontalAlign->insertItem(__tr2qs_ctx("Right","options"));
+ m_pHorizontalAlign->insertItem(__tr2qs_ctx("Center","options"));
+
+ m_pVerticalAlign->insertItem(__tr2qs_ctx("Tile","options"));
+ m_pVerticalAlign->insertItem(__tr2qs_ctx("Top","options"));
+ m_pVerticalAlign->insertItem(__tr2qs_ctx("Bottom","options"));
+ m_pVerticalAlign->insertItem(__tr2qs_ctx("Center","options"));
+
+ switch( KVI_OPTION_UINT(KviOption_uintTreeTaskBarPixmapAlign) & Qt::AlignHorizontal_Mask)
+ {
+ case Qt::AlignLeft:
+ m_pHorizontalAlign->setCurrentItem(1);
+ break;
+ case Qt::AlignRight:
+ m_pHorizontalAlign->setCurrentItem(2);
+ break;
+ case Qt::AlignHCenter:
+ m_pHorizontalAlign->setCurrentItem(3);
+ break;
+ default:
+ m_pHorizontalAlign->setCurrentItem(0);
+ }
+
+ switch( KVI_OPTION_UINT(KviOption_uintTreeTaskBarPixmapAlign) & Qt::AlignVertical_Mask)
+ {
+ case Qt::AlignTop:
+ m_pVerticalAlign->setCurrentItem(1);
+ break;
+ case Qt::AlignBottom:
+ m_pVerticalAlign->setCurrentItem(2);
+ break;
+ case Qt::AlignVCenter:
+ m_pVerticalAlign->setCurrentItem(3);
+ break;
+ default:
+ m_pVerticalAlign->setCurrentItem(0);
+ }
+
+ layout()->setRowStretch(1,1);
+}
+
+
+KviTreeTaskBarBackgroundOptionsWidget::~KviTreeTaskBarBackgroundOptionsWidget()
+{
+}
+
+void KviTreeTaskBarBackgroundOptionsWidget::commit()
+{
+ KviOptionsWidget::commit();
+
+ int iFlags=0;
+ switch(m_pHorizontalAlign->currentItem())
+ {
+ case 1:
+ iFlags|=Qt::AlignLeft;
+ break;
+ case 2:
+ iFlags|=Qt::AlignRight;
+ break;
+ case 3:
+ iFlags|=Qt::AlignHCenter;
+ break;
+ }
+ switch(m_pVerticalAlign->currentItem())
+ {
+ case 1:
+ iFlags|=Qt::AlignTop;
+ break;
+ case 2:
+ iFlags|=Qt::AlignBottom;
+ break;
+ case 3:
+ iFlags|=Qt::AlignVCenter;
+ break;
+ }
+
+ KVI_OPTION_UINT(KviOption_uintTreeTaskBarPixmapAlign)=iFlags;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+KviTreeTaskBarFeaturesOptionsWidget::KviTreeTaskBarFeaturesOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"treetaskbar_options_widget")
+{
+ createLayout(4,1);
+
+ addBoolSelector(0,0,1,0,__tr2qs_ctx("Show header","options"),KviOption_boolShowTreeTaskbarHeader);
+
+ addUIntSelector(0,1,0,1,__tr2qs_ctx("Minimum width:","options"),KviOption_uintTreeTaskBarMinimumWidth,24,1024,125);
+ addUIntSelector(0,2,0,2,__tr2qs_ctx("Maximum width:","options"),KviOption_uintTreeTaskBarMaximumWidth,24,9999,125);
+
+ addRowSpacer(0,3,0,3);
+}
+
+
+KviTreeTaskBarFeaturesOptionsWidget::~KviTreeTaskBarFeaturesOptionsWidget()
+{
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+KviClassicTaskBarOptionsWidget::KviClassicTaskBarOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"classictaskbar_options_widget")
+{
+ createLayout(8,1);
+ addFontSelector(0,0,0,0,__tr2qs_ctx("Font:","options"),KviOption_fontTaskbar);
+ KviTalGroupBox *g = addGroupBox(0,1,0,1,2,Qt::Horizontal,__tr2qs_ctx("Text/Alert Colors","options"));
+ addColorSelector(g,__tr2qs_ctx("Normal:","options"),KviOption_colorTaskBarNormalText);
+ addColorSelector(g,__tr2qs_ctx("Minimized:","options"), KviOption_colorTaskBarMinimizedText);
+ addColorSelector(g,__tr2qs_ctx("Alert Level 1:","options"),KviOption_colorTaskBarHighlight1Text);
+ addColorSelector(g,__tr2qs_ctx("Alert Level 2:","options"),KviOption_colorTaskBarHighlight2Text);
+ addColorSelector(g,__tr2qs_ctx("Alert Level 3:","options"),KviOption_colorTaskBarHighlight3Text);
+ addColorSelector(g,__tr2qs_ctx("Alert Level 4:","options"),KviOption_colorTaskBarHighlight4Text);
+ addColorSelector(g,__tr2qs_ctx("Alert Level 5:","options"),KviOption_colorTaskBarHighlight5Text);
+ addColorSelector(0,2,0,2,__tr2qs_ctx("Progress bar color:","options"),KviOption_colorTaskBarProgressBar);
+ addUIntSelector(0,3,0,3,__tr2qs_ctx("Minimum width of buttons:","options"),KviOption_uintTaskBarButtonMinWidth,24,9999,100);
+ //addUIntSelector(0,4,0,4,__tr2qs_ctx("Maximum number of rows:","options"),KviOption_uintTaskBarMaximumRows,1,16,2);
+ addBoolSelector(0,4,0,4,__tr2qs_ctx("Set maximum button width","options"),KviOption_boolClassicTaskBarSetMaximumButtonWidth);
+ addUIntSelector(0,5,0,5,__tr2qs_ctx("Maximum width of buttons:","options"),KviOption_uintClassicTaskBarMaximumButtonWidth,24,9999,100);
+ addBoolSelector(0,6,0,6,__tr2qs_ctx("Use flat buttons","options"),KviOption_boolUseFlatClassicTaskbarButtons);
+ addRowSpacer(0,7,0,7);
+}
+
+
+KviClassicTaskBarOptionsWidget::~KviClassicTaskBarOptionsWidget()
+{
+}
+
+#include "m_optw_taskbar.moc"
diff --git a/src/modules/options/optw_taskbar.h b/src/modules/options/optw_taskbar.h
new file mode 100644
index 00000000..66990c26
--- /dev/null
+++ b/src/modules/options/optw_taskbar.h
@@ -0,0 +1,125 @@
+#ifndef _OPTW_TASKBAR_H_
+#define _OPTW_TASKBAR_H_
+
+//===============================================================================
+//
+// File : optw_taskbar.h
+// Creation date : Wed Jan 16 04:30:41 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002-2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//===============================================================================
+
+
+#include "kvi_optionswidget.h"
+#include <qcombobox.h>
+
+#define KVI_OPTIONS_WIDGET_ICON_KviTaskBarOptionsWidget KVI_SMALLICON_CLASSICTASKBAR
+#define KVI_OPTIONS_WIDGET_NAME_KviTaskBarOptionsWidget __tr2qs_no_lookup("Taskbar")
+#define KVI_OPTIONS_WIDGET_MINIMAL_USER_EXPERIENCE_LEVEL_KviTaskBarOptionsWidget 2
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviTaskBarOptionsWidget __tr2qs_no_lookup("theme")
+#define KVI_OPTIONS_WIDGET_GROUP_KviTaskBarOptionsWidget "theme"
+
+class KviTaskBarOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviTaskBarOptionsWidget(QWidget * parent);
+ ~KviTaskBarOptionsWidget();
+};
+
+#define KVI_OPTIONS_WIDGET_ICON_KviTreeTaskBarOptionsWidget KVI_SMALLICON_TREETASKBAR
+#define KVI_OPTIONS_WIDGET_NAME_KviTreeTaskBarOptionsWidget __tr2qs_no_lookup("Tree Taskbar")
+#define KVI_OPTIONS_WIDGET_PARENT_KviTreeTaskBarOptionsWidget KviTaskBarOptionsWidget
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviTreeTaskBarOptionsWidget __tr2qs_no_lookup("theme")
+#define KVI_OPTIONS_WIDGET_GROUP_KviTreeTaskBarOptionsWidget "theme"
+#define KVI_OPTIONS_WIDGET_CONTAINER_KviTreeTaskBarOptionsWidget true
+
+class KviTreeTaskBarOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviTreeTaskBarOptionsWidget(QWidget * pParent);
+ ~KviTreeTaskBarOptionsWidget();
+};
+
+
+#define KVI_OPTIONS_WIDGET_ICON_KviTreeTaskBarForegroundOptionsWidget KVI_SMALLICON_TREETASKBAR
+#define KVI_OPTIONS_WIDGET_NAME_KviTreeTaskBarForegroundOptionsWidget __tr2qs_no_lookup("Foreground")
+#define KVI_OPTIONS_WIDGET_PARENT_KviTreeTaskBarForegroundOptionsWidget KviTreeTaskBarOptionsWidget
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviTreeTaskForegroundBarOptionsWidget __tr2qs_no_lookup("theme")
+#define KVI_OPTIONS_WIDGET_GROUP_KviTreeTaskBarForegroundOptionsWidget "theme"
+
+class KviTreeTaskBarForegroundOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviTreeTaskBarForegroundOptionsWidget(QWidget * parent);
+ ~KviTreeTaskBarForegroundOptionsWidget();
+};
+
+
+#define KVI_OPTIONS_WIDGET_ICON_KviTreeTaskBarBackgroundOptionsWidget KVI_SMALLICON_TREETASKBAR
+#define KVI_OPTIONS_WIDGET_NAME_KviTreeTaskBarBackgroundOptionsWidget __tr2qs_no_lookup("Background")
+#define KVI_OPTIONS_WIDGET_PARENT_KviTreeTaskBarBackgroundOptionsWidget KviTreeTaskBarOptionsWidget
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviTreeTaskBackgroundBarOptionsWidget __tr2qs_no_lookup("theme")
+#define KVI_OPTIONS_WIDGET_GROUP_KviTreeTaskBarBackgroundOptionsWidget "theme"
+
+class KviTreeTaskBarBackgroundOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+private:
+ QComboBox* m_pHorizontalAlign;
+ QComboBox* m_pVerticalAlign;
+public:
+ KviTreeTaskBarBackgroundOptionsWidget(QWidget * parent);
+ ~KviTreeTaskBarBackgroundOptionsWidget();
+
+ virtual void commit();
+};
+
+#define KVI_OPTIONS_WIDGET_ICON_KviTreeTaskBarFeaturesOptionsWidget KVI_SMALLICON_TREETASKBAR
+#define KVI_OPTIONS_WIDGET_NAME_KviTreeTaskBarFeaturesOptionsWidget __tr2qs_no_lookup("Features")
+#define KVI_OPTIONS_WIDGET_PARENT_KviTreeTaskBarFeaturesOptionsWidget KviTreeTaskBarOptionsWidget
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviTreeTaskFeaturesBarOptionsWidget __tr2qs_no_lookup("theme")
+#define KVI_OPTIONS_WIDGET_GROUP_KviTreeTaskBarFeaturesOptionsWidget "theme"
+
+class KviTreeTaskBarFeaturesOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviTreeTaskBarFeaturesOptionsWidget(QWidget * parent);
+ ~KviTreeTaskBarFeaturesOptionsWidget();
+};
+
+#define KVI_OPTIONS_WIDGET_ICON_KviClassicTaskBarOptionsWidget KVI_SMALLICON_CLASSICTASKBAR
+#define KVI_OPTIONS_WIDGET_NAME_KviClassicTaskBarOptionsWidget __tr2qs_no_lookup("Classic Taskbar")
+#define KVI_OPTIONS_WIDGET_PARENT_KviClassicTaskBarOptionsWidget KviTaskBarOptionsWidget
+#define KVI_OPTIONS_WIDGET_MINIMAL_USER_EXPERIENCE_LEVEL_KviClassicTaskBarOptionsWidget 2
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviClassicTaskBarOptionsWidget __tr2qs_no_lookup("theme")
+#define KVI_OPTIONS_WIDGET_GROUP_KviClassicTaskBarOptionsWidget "theme"
+
+class KviClassicTaskBarOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviClassicTaskBarOptionsWidget(QWidget * parent);
+ ~KviClassicTaskBarOptionsWidget();
+};
+
+#endif //_OPTW_TASKBAR_H_
diff --git a/src/modules/options/optw_textencoding.cpp b/src/modules/options/optw_textencoding.cpp
new file mode 100644
index 00000000..431cdad0
--- /dev/null
+++ b/src/modules/options/optw_textencoding.cpp
@@ -0,0 +1,139 @@
+//
+// File : optw_textencoding.cpp
+// Creation date : Sat Aug 11 2001 03:29:52 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+#include "optw_textencoding.h"
+
+#include "kvi_options.h"
+#include "kvi_locale.h"
+#include "kvi_qstring.h"
+#include "kvi_app.h"
+#include "kvi_fileutils.h"
+
+#include <qdir.h>
+#include <qmessagebox.h>
+
+QString g_szPrevSettedLocale;
+
+KviTextEncodingOptionsWidget::KviTextEncodingOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"textencoding_options_widget")
+{
+ createLayout(5,2);
+
+ addLabel(0,0,0,0,__tr2qs_ctx("Default text encoding:","options"));
+
+ m_pTextEncodingCombo = new QComboBox(this);
+ addWidgetToLayout(m_pTextEncodingCombo,1,0,1,0);
+
+ m_pTextEncodingCombo->insertItem(__tr2qs_ctx("Use Language Encoding","options"));
+ int i = 0;
+ int iMatch = 0;
+ KviLocale::EncodingDescription * d = KviLocale::encodingDescription(i);
+ while(d->szName)
+ {
+ if(KviQString::equalCI(d->szName,KVI_OPTION_STRING(KviOption_stringDefaultTextEncoding)))iMatch = i + 1;
+ m_pTextEncodingCombo->insertItem(d->szName);
+ i++;
+ d = KviLocale::encodingDescription(i);
+ }
+
+ m_pTextEncodingCombo->setCurrentItem(iMatch);
+
+ addLabel(0,1,0,1,__tr2qs_ctx("Force language:","options"));
+
+ m_pForcedLocaleCombo = new QComboBox(this);
+
+ addWidgetToLayout(m_pForcedLocaleCombo,1,1,1,1);
+
+ QLabel * l = new QLabel(__tr2qs_ctx("<b>Note:</b> You need to restart KVirc to apply a language changing","options"),this);
+ addWidgetToLayout(l,0,2,1,2);
+
+ m_pForcedLocaleCombo->insertItem(__tr2qs_ctx("Automatic detection","options"));
+ m_pForcedLocaleCombo->insertItem(__tr2qs_ctx("en","options"));
+
+ QString szLangFile=QString("%1/.kvirc_force_locale").arg(QDir::homeDirPath());
+
+ bool bIsDefaultLocale = !KviFileUtils::fileExists(szLangFile);
+ //We Have setted locale, but not restarted kvirc
+ if(!g_szPrevSettedLocale.isEmpty())
+ {
+ m_szLanguage=g_szPrevSettedLocale;
+ } else {
+ m_szLanguage=KviLocale::localeName();
+ }
+
+ QString szLocaleDir;
+ g_pApp->getGlobalKvircDirectory(szLocaleDir,KviApp::Locale);
+
+ QStringList list=QDir(szLocaleDir).entryList("kvirc_*.mo",QDir::Files);
+
+ i = 0;
+ iMatch = 0;
+
+ for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
+ QString szTmp=*it;
+ szTmp.replace("kvirc_","");
+ szTmp.replace(".mo","");
+ m_pForcedLocaleCombo->insertItem(szTmp);
+ if(KviQString::equalCI(szTmp,m_szLanguage))
+ iMatch = i + 2;
+ i++;
+ }
+ if(bIsDefaultLocale)
+ m_pForcedLocaleCombo->setCurrentItem(0);
+ else if(KviQString::equalCI(m_szLanguage,"en"))
+ m_pForcedLocaleCombo->setCurrentItem(1);
+ else
+ m_pForcedLocaleCombo->setCurrentItem(iMatch);
+ addRowSpacer(0,3,1,3);
+}
+
+KviTextEncodingOptionsWidget::~KviTextEncodingOptionsWidget()
+{
+}
+
+void KviTextEncodingOptionsWidget::commit()
+{
+ int idx = m_pTextEncodingCombo->currentItem();
+ if(idx <= 0)
+ {
+ // guess from locale
+ KVI_OPTION_STRING(KviOption_stringDefaultTextEncoding) = "";
+ } else {
+ KVI_OPTION_STRING(KviOption_stringDefaultTextEncoding) = m_pTextEncodingCombo->text(idx);
+ }
+
+ idx=m_pForcedLocaleCombo->currentItem();
+ QString szLangFile=QString("%1/.kvirc_force_locale").arg(QDir::homeDirPath());
+ if(idx==0) {
+ if(KviFileUtils::fileExists(szLangFile))
+ KviFileUtils::removeFile(szLangFile);
+ } else {
+ g_szPrevSettedLocale=m_pForcedLocaleCombo->text(idx);
+ if(!KviFileUtils::writeFile(szLangFile,m_pForcedLocaleCombo->text(idx)))
+ {
+ QMessageBox::critical(this,"KVIrc",__tr2qs_ctx("Unable to write language information to","options")+"\n"+szLangFile,__tr2qs_ctx("Ok","options"));
+ }
+ }
+/* if(!KviQString::equalCI(m_pForcedLocaleCombo->text(idx),m_szLanguage))
+ QMessageBox::information(0,"KVIrc",__tr2qs_ctx("You need to restart KVirc to apply a language changing","options"),QMessageBox::Ok);*/
+}
+
+#include "m_optw_textencoding.moc"
diff --git a/src/modules/options/optw_textencoding.h b/src/modules/options/optw_textencoding.h
new file mode 100644
index 00000000..75bdeb75
--- /dev/null
+++ b/src/modules/options/optw_textencoding.h
@@ -0,0 +1,50 @@
+#ifndef _OPTW_TEXTENCODING_H_
+#define _OPTW_TEXTENCODING_H_
+
+//
+// File : optw_textencoding.h
+// Creation date : Sat Mar 02 2002 12:09:19 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_optionswidget.h"
+
+#include <qcombobox.h>
+
+#define KVI_OPTIONS_WIDGET_ICON_KviTextEncodingOptionsWidget KVI_SMALLICON_TEXTENCODING
+#define KVI_OPTIONS_WIDGET_NAME_KviTextEncodingOptionsWidget __tr2qs_no_lookup("Language")
+#define KVI_OPTIONS_WIDGET_PRIORITY_KviTextEncodingOptionsWidget 50000
+#define KVI_OPTIONS_WIDGET_PARENT_KviTextEncodingOptionsWidget KviGeneralOptOptionsWidget
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviTextEncodingOptionsWidget __tr2qs_no_lookup("language,encoding,charset,codepage")
+
+class KviTextEncodingOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviTextEncodingOptionsWidget(QWidget * parent);
+ ~KviTextEncodingOptionsWidget();
+protected:
+ QString m_szLanguage;
+ QComboBox * m_pTextEncodingCombo;
+ QComboBox * m_pForcedLocaleCombo;
+public:
+ virtual void commit();
+};
+
+#endif //!_OPTW_TEXTENCODING_H_
diff --git a/src/modules/options/optw_texticons.cpp b/src/modules/options/optw_texticons.cpp
new file mode 100644
index 00000000..d1752c0f
--- /dev/null
+++ b/src/modules/options/optw_texticons.cpp
@@ -0,0 +1,244 @@
+//
+// File : optw_texticons.cpp
+// Creation date : Fri May 24 2002 00:16:13 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "optw_texticons.h"
+
+#include "kvi_iconmanager.h"
+#include "kvi_texticonmanager.h"
+#include "kvi_locale.h"
+#include "kvi_filedialog.h"
+
+#include <qlayout.h>
+#include <qcursor.h>
+#include "kvi_tal_hbox.h"
+
+
+KviTextIconEditor::KviTextIconEditor(QWidget * par,KviTextIcon * icon,KviTextIconTableItem* item)
+: KviTalHBox(par),m_pTableItem(item)
+{
+ m_pIconButton=new QToolButton(this);
+ m_pBrowseButton=new QToolButton(this);
+ m_pBrowseButton->setSizePolicy(QSizePolicy(QSizePolicy::Maximum,QSizePolicy::Maximum));
+ m_pBrowseButton->setText("...");
+ m_pIcon = icon;
+ m_pPopup = 0;
+ updateIcon();
+ connect(m_pIconButton,SIGNAL(clicked()),this,SLOT(doPopup()));
+ connect(m_pBrowseButton,SIGNAL(clicked()),this,SLOT(chooseFromFile()));
+}
+
+
+KviTextIconEditor::~KviTextIconEditor()
+{
+
+}
+
+void KviTextIconEditor::doPopup()
+{
+ if(!m_pPopup)
+ {
+ m_pPopup = new KviTalPopupMenu(this);
+ KviIconWidget * iw = new KviIconWidget(m_pPopup);
+ connect(iw,SIGNAL(selected(int)),this,SLOT(iconSelected(int)));
+ m_pPopup->insertItem(iw);
+ }
+ m_pPopup->popup(QCursor::pos());
+}
+
+void KviTextIconEditor::iconSelected(int id)
+{
+ m_pIcon->setId(id);
+ updateIcon();
+}
+
+void KviTextIconEditor::chooseFromFile()
+{
+ QString szFile;
+ KviFileDialog::askForOpenFileName(szFile,"Choose icon filename",QString::null,"*.png","options");
+ if(!szFile.isEmpty())
+ {
+ if(g_pIconManager->getPixmap(szFile))
+ {
+ m_pIcon->setFilename(szFile);
+// debug("%s %s %i |%s| %p",__FILE__,__FUNCTION__,__LINE__,m_pIcon->filename().utf8().data(),m_pIcon);
+ updateIcon();
+ }
+ }
+}
+
+void KviTextIconEditor::updateIcon()
+{
+ if(m_pIcon)
+ {
+ QPixmap* pix=m_pIcon->pixmap();
+ if(pix)
+ m_pIconButton->setPixmap(*pix);
+ }
+}
+
+KviTextIconTableItem::KviTextIconTableItem(KviTalTable * t,KviTextIcon * icon)
+: KviTalTableItem(t,KviTalTableItem::WhenCurrent,QString::null)
+{
+ if(icon)
+ m_pIcon=icon;
+ else
+ m_pIcon=new KviTextIcon(0);
+ QPixmap* pix=m_pIcon->pixmap();
+ if(pix)
+ setPixmap(*pix);
+}
+
+KviTextIconTableItem::~KviTextIconTableItem()
+{
+ delete m_pIcon;
+}
+
+void KviTextIconTableItem::setId(int id)
+{
+ m_pIcon->setId(id);
+ QPixmap* pix=m_pIcon->pixmap();
+ if(pix)
+ setPixmap(*pix);
+}
+
+QWidget * KviTextIconTableItem::createEditor() const
+{
+ return new KviTextIconEditor(table()->viewport(),m_pIcon,(KviTextIconTableItem*)this);
+}
+
+
+void KviTextIconTableItem::setContentFromEditor(QWidget * w)
+{
+ if(w->inherits("KviTextIconEditor"))
+ {
+ QPixmap* pix=m_pIcon->pixmap();
+ if(pix)
+ setPixmap(*pix);
+ }
+}
+
+KviTextIconsOptionsWidget::KviTextIconsOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"texticons_options_widget")
+{
+ createLayout(2,2);
+
+ KviPointerHashTableIterator<QString,KviTextIcon> it(*(g_pTextIconManager->textIconDict()));
+
+ m_pTable = new KviTalTable(g_pTextIconManager->textIconDict()->count(),2,this);
+
+#ifdef COMPILE_INFO_TIPS
+ mergeTip(m_pTable->viewport(),__tr2qs_ctx("This table contains the text icon associations.<br>" \
+ "KVirc will use them to display the CTRL+I escape sequences and eventually the " \
+ "emoticons.","options"));
+#endif
+
+ int idx = 0;
+ while(KviTextIcon * i = it.current())
+ {
+ m_pTable->setText(idx,0,it.currentKey());
+ m_pTable->setItem(idx,1,new KviTextIconTableItem(m_pTable,new KviTextIcon(i)));
+ ++idx;
+ ++it;
+ }
+
+ layout()->addMultiCellWidget(m_pTable,0,0,0,1);
+
+ m_pAdd = new QPushButton(__tr2qs_ctx("Add","options"),this);
+ layout()->addWidget(m_pAdd,1,0);
+ connect(m_pAdd,SIGNAL(clicked()),this,SLOT(addClicked()));
+
+ m_pDel = new QPushButton(__tr2qs_ctx("Delete","options"),this);
+ layout()->addWidget(m_pDel,1,1);
+ connect(m_pDel,SIGNAL(clicked()),this,SLOT(delClicked()));
+
+ m_pDel->setEnabled(false);
+
+ connect(m_pTable,SIGNAL(selectionChanged()),this,SLOT(selectionChanged()));
+}
+
+KviTextIconsOptionsWidget::~KviTextIconsOptionsWidget()
+{
+}
+
+void KviTextIconsOptionsWidget::selectionChanged()
+{
+ int i = m_pTable->currentRow();
+ m_pDel->setEnabled(i >= 0 && i < m_pTable->numRows());
+}
+
+void KviTextIconsOptionsWidget::addClicked()
+{
+ m_pTable->setNumRows(m_pTable->numRows() + 1);
+ m_pTable->setText(m_pTable->numRows() - 1,0,__tr2qs_ctx("unnamed","options"));
+ m_pTable->setItem(m_pTable->numRows() - 1,1,new KviTextIconTableItem(m_pTable,0));
+ m_pDel->setEnabled(true);
+}
+
+void KviTextIconsOptionsWidget::delClicked()
+{
+ int i = m_pTable->currentRow();
+
+ if((i > -1) && (i < m_pTable->numRows()))
+ {
+ // remove row i
+ m_pTable->clearCell(i,0);
+ m_pTable->clearCell(i,1);
+ m_pTable->clearCell(i,2);
+
+ for(;i < (m_pTable->numRows() - 1);i++)
+ {
+ m_pTable->swapRows(i,i+1);
+ }
+
+ m_pTable->setNumRows(m_pTable->numRows() - 1);
+ if(m_pTable->numRows() == 0)m_pDel->setEnabled(false);
+ }
+}
+
+void KviTextIconsOptionsWidget::commit()
+{
+
+ KviOptionsWidget::commit();
+ g_pTextIconManager->clear();
+ int n = m_pTable->numRows();
+ for(int i=0;i < n;i++)
+ {
+ QString szVal = m_pTable->text(i,0);
+ if(!szVal.isEmpty())
+ {
+ KviTextIconTableItem * it = (KviTextIconTableItem *)m_pTable->item(i,1);
+ if(it)
+ {
+ g_pTextIconManager->insert(szVal,*(it->icon()));
+ }
+ }
+ }
+ g_pTextIconManager->checkDefaultAssociations();
+
+ for(int i=0; i<n; i++)
+ for (int j=0; j<m_pTable->numCols(); j++)
+ if (m_pTable->item(i,j))
+ m_pTable->clearCell(i,j);
+
+}
+
+#include "m_optw_texticons.moc"
diff --git a/src/modules/options/optw_texticons.h b/src/modules/options/optw_texticons.h
new file mode 100644
index 00000000..652c7da9
--- /dev/null
+++ b/src/modules/options/optw_texticons.h
@@ -0,0 +1,105 @@
+#ifndef _OPTW_TEXTICONS_H_
+#define _OPTW_TEXTICONS_H_
+
+//
+// File : optw_texticons.h
+// Creation date : Fri May 24 2002 00:14:02 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_optionswidget.h"
+#include "kvi_texticonmanager.h"
+#define KVI_OPTIONS_WIDGET_ICON_KviTextIconsOptionsWidget KVI_SMALLICON_BIGGRIN
+#define KVI_OPTIONS_WIDGET_NAME_KviTextIconsOptionsWidget __tr2qs_no_lookup("Text icons")
+#define KVI_OPTIONS_WIDGET_PARENT_KviTextIconsOptionsWidget KviToolsOptionsWidget
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviTextIconsOptionsWidget __tr2qs_no_lookup("smileys,emoticons")
+
+
+
+#include <qtoolbutton.h>
+#include "kvi_tal_popupmenu.h"
+#include "kvi_tal_hbox.h"
+
+#ifdef COMPILE_USE_QT4
+#include <q3table.h>
+#define KviTalTable Q3Table
+#define KviTalTableItem Q3TableItem
+#else
+#include <qtable.h>
+#define KviTalTable QTable
+#define KviTalTableItem QTableItem
+#endif
+
+class KviTextIconTableItem;
+
+class KviTextIconEditor : public KviTalHBox
+{
+ Q_OBJECT
+public:
+ KviTextIconEditor(QWidget * par,KviTextIcon * icon,KviTextIconTableItem* item);
+ ~KviTextIconEditor();
+protected:
+ KviTextIconTableItem *m_pTableItem;
+ KviTextIcon *m_pIcon;
+ KviTalPopupMenu *m_pPopup;
+ QToolButton *m_pIconButton;
+ QToolButton *m_pBrowseButton;
+public:
+ void updateIcon();
+ KviTextIcon* icon() { return m_pIcon; };
+protected slots:
+ void iconSelected(int);
+ void doPopup();
+ void chooseFromFile();
+};
+
+class KviTextIconTableItem : public KviTalTableItem
+{
+ friend class KviTextIconsOptionsWidget;
+public:
+ KviTextIconTableItem(KviTalTable * t,KviTextIcon * icon);
+ ~KviTextIconTableItem();
+protected:
+ KviTextIcon * m_pIcon;
+public:
+ KviTextIcon * icon() { return m_pIcon; };
+ void setId(int id);
+ virtual QWidget * createEditor() const;
+ virtual void setContentFromEditor(QWidget * w);
+};
+
+class KviTextIconsOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviTextIconsOptionsWidget(QWidget * parent);
+ ~KviTextIconsOptionsWidget();
+protected:
+ KviTalTable * m_pTable;
+ QPushButton * m_pAdd;
+ QPushButton * m_pDel;
+public:
+ virtual void commit();
+protected slots:
+ void selectionChanged();
+ void addClicked();
+ void delClicked();
+};
+
+#endif //!_OPTW_TEXTICONS_H_
diff --git a/src/modules/options/optw_theme.cpp b/src/modules/options/optw_theme.cpp
new file mode 100644
index 00000000..e3afeba4
--- /dev/null
+++ b/src/modules/options/optw_theme.cpp
@@ -0,0 +1,26 @@
+//=============================================================================
+//
+// File : optw_theme.cpp
+// Creation date : Sun May 25 2003 18:00:00 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+
+#include "m_optw_theme.moc"
diff --git a/src/modules/options/optw_theme.h b/src/modules/options/optw_theme.h
new file mode 100644
index 00000000..ee8945c2
--- /dev/null
+++ b/src/modules/options/optw_theme.h
@@ -0,0 +1,30 @@
+#ifndef _OPTW_THEME_H_
+#define _OPTW_THEME_H_
+
+//=============================================================================
+//
+// File : optw_theme.h
+// Creation date : Sun May 25 2003 18:03:11 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003-2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+
+
+#endif //!_OPTW_THEME_H_
diff --git a/src/modules/options/optw_tools.cpp b/src/modules/options/optw_tools.cpp
new file mode 100644
index 00000000..b46b9a01
--- /dev/null
+++ b/src/modules/options/optw_tools.cpp
@@ -0,0 +1,50 @@
+//=============================================================================
+//
+// File : optw_tools.cpp
+// Creation date : Wed Ott 19 16:15:16 2005 GMT by Grifisx & Noldor
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2005 Grifisx & Noldor
+//
+// 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 opinion) 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.
+//
+//=============================================================================
+
+#include "optw_tools.h"
+
+#include <qlayout.h>
+
+#include "kvi_settings.h"
+#include "kvi_options.h"
+#include "kvi_locale.h"
+
+KviToolsOptionsWidget::KviToolsOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"tools_options_widget")
+{
+
+ createLayout(1,1);
+
+ QLabel * l;
+ l = addLabel(0,0,0,0,__tr2qs_ctx("This section contains irc tools<br>"\
+ "<p>like<b> away, lag and logging system. </b> " \
+ "</p>","options"));
+
+}
+
+KviToolsOptionsWidget::~KviToolsOptionsWidget()
+{
+}
+
+#include "m_optw_tools.moc"
diff --git a/src/modules/options/optw_tools.h b/src/modules/options/optw_tools.h
new file mode 100644
index 00000000..9ebf35e8
--- /dev/null
+++ b/src/modules/options/optw_tools.h
@@ -0,0 +1,46 @@
+#ifndef _OPTW_TOOLS_H_
+#define _OPTW_TOOLS_H_
+
+//=============================================================================
+//
+// File : optw_tools.h
+//
+// This file is part of the KVirc irc client distribution
+// Creation date : Wed Ott 19 16:15:16 2005 GMT by Grifisx & Noldor
+//
+// Copyright (C) 2005 Grifisx & Noldor
+// 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_optionswidget.h"
+#include "kvi_selectors.h"
+
+#define KVI_OPTIONS_WIDGET_ICON_KviToolsOptionsWidget KVI_SMALLICON_ADDONS
+#define KVI_OPTIONS_WIDGET_NAME_KviToolsOptionsWidget __tr2qs_no_lookup("Tools")
+#define KVI_OPTIONS_WIDGET_PARENT_KviToolsOptionsWidget KviIrcOptionsWidget
+#define KVI_OPTIONS_WIDGET_PRIORITY_KviToolsOptionsWidget 50000
+#define KVI_OPTIONS_WIDGET_NOTCONTAINED_KviToolsOptionsWidget true
+
+class KviToolsOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviToolsOptionsWidget(QWidget * parent);
+ ~KviToolsOptionsWidget();
+};
+
+#endif //!_OPTW_FOLDERS_H_
diff --git a/src/modules/options/optw_topiclabel.cpp b/src/modules/options/optw_topiclabel.cpp
new file mode 100644
index 00000000..71bc2b64
--- /dev/null
+++ b/src/modules/options/optw_topiclabel.cpp
@@ -0,0 +1,43 @@
+//
+// File : optw_topiclabel.cpp
+// Creation date : Mon Sep 24 02:44:55 CEST 2001 by Krzysztof Godlewski
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_options.h"
+#include "kvi_locale.h"
+#include "optw_topiclabel.h"
+
+KviTopicLabelLookOptionsWidget::KviTopicLabelLookOptionsWidget(QWidget *p):KviOptionsWidget(p, "topic_label_look_options_widget")
+{
+ createLayout(4, 1);
+
+ addFontSelector(0, 0, 0, 0, __tr2qs_ctx("Font","options"), KviOption_fontLabel);
+ addColorSelector(0, 1, 0, 1, __tr2qs_ctx("Foreground color","options"), KviOption_colorLabelForeground);
+ addColorSelector(0, 2, 0, 2, __tr2qs_ctx("Background color","options"), KviOption_colorLabelBackground);
+ addPixmapSelector(0, 3, 0, 3, __tr2qs_ctx("Background image","options"), KviOption_pixmapLabelBackground);
+
+ layout()->setRowStretch(3, 1);
+}
+
+KviTopicLabelLookOptionsWidget::~KviTopicLabelLookOptionsWidget()
+{
+}
+
+#include "m_optw_topiclabel.moc"
diff --git a/src/modules/options/optw_topiclabel.h b/src/modules/options/optw_topiclabel.h
new file mode 100644
index 00000000..1185fae6
--- /dev/null
+++ b/src/modules/options/optw_topiclabel.h
@@ -0,0 +1,41 @@
+//
+// File : optw_topiclabel.cpp
+// Creation date : Mon Sep 24 02:44:55 CEST 2001 by Krzysztof Godlewski
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#ifndef OPTW_TOPICLABEL_H
+#define OPTW_TOPICLABEL_H
+
+#include "kvi_optionswidget.h"
+
+#define KVI_OPTIONS_WIDGET_ICON_KviTopicLabelLookOptionsWidget KVI_SMALLICON_TOPIC
+#define KVI_OPTIONS_WIDGET_NAME_KviTopicLabelLookOptionsWidget __tr2qs_no_lookup("Labels")
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviTopicLabelLookOptionsWidget __tr2qs_no_lookup("theme,topic")
+#define KVI_OPTIONS_WIDGET_GROUP_KviTopicLabelLookOptionsWidget "theme"
+
+class KviTopicLabelLookOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviTopicLabelLookOptionsWidget(QWidget *);
+ ~KviTopicLabelLookOptionsWidget();
+};
+
+#endif /* !OPTW_TOPICLABEL_H */
diff --git a/src/modules/options/optw_transport.cpp b/src/modules/options/optw_transport.cpp
new file mode 100644
index 00000000..d7cf3971
--- /dev/null
+++ b/src/modules/options/optw_transport.cpp
@@ -0,0 +1,33 @@
+//
+// File : optw_transport.cpp
+// Creation date : Mon Nov 13 2000 14:14:22 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "optw_transport.h"
+
+#include <kvi_tal_groupbox.h>
+
+#include "kvi_options.h"
+#include "kvi_locale.h"
+
+
+
+
+#include "m_optw_transport.moc"
diff --git a/src/modules/options/optw_transport.h b/src/modules/options/optw_transport.h
new file mode 100644
index 00000000..971c215f
--- /dev/null
+++ b/src/modules/options/optw_transport.h
@@ -0,0 +1,29 @@
+#ifndef _OPTW_TRANSPORT_H_
+#define _OPTW_TRANSPORT_H_
+
+//
+// File : optw_transport.h
+// Creation date : Mon Nov 13 2000 14:13:11 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_optionswidget.h"
+#include "kvi_tal_listview.h"
+
+#endif //!_OPTW_TRANSPORT_H_
diff --git a/src/modules/options/optw_tray.cpp b/src/modules/options/optw_tray.cpp
new file mode 100644
index 00000000..e988ba54
--- /dev/null
+++ b/src/modules/options/optw_tray.cpp
@@ -0,0 +1,91 @@
+//
+// File : optw_tray.cpp
+// Creation date : Mon 14 Aug 2006 by Alexey Uzhva
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+#include "optw_tray.h"
+
+#include <qlayout.h>
+#include "kvi_tal_tooltip.h"
+
+#include "kvi_options.h"
+#include "kvi_locale.h"
+
+//#warning "Info tips"
+
+
+KviTrayOptionsWidget::KviTrayOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"tray_options_widget")
+{
+ createLayout(7,1);
+
+ m_pEnable = addBoolSelector(0,0,0,0, __tr2qs_ctx("Enable tray icon","options"), KviOption_boolShowDockExtension);
+ m_pCloseInTray = addBoolSelector(0,1,0,1,__tr2qs_ctx("Close in tray","options"),KviOption_boolCloseInTray);
+ m_pMinimizeInTray = addBoolSelector(0,2,0,2,__tr2qs_ctx("Minimize in tray","options"),KviOption_boolMinimizeInTray);
+
+ m_pEnableFlashing = addBoolSelector(0,3,0,3,__tr2qs_ctx("Enable tray icon flashing","options"),KviOption_boolEnableTrayIconFlashing);
+ m_pLevelBasedNotify = addBoolSelector(0,4,0,4,__tr2qs_ctx("Enable level-based message notification (not a message-type based)","options"),KviOption_boolUseLevelBasedTrayNotification);
+
+ m_pLevelsGroup = addGroupBox(0,5,0,5,1,Qt::Horizontal,__tr2qs_ctx("Select message levels to notify","options"));
+
+ addUIntSelector(m_pLevelsGroup,__tr2qs_ctx("Minimum level for low-priority messages","options"),
+ KviOption_uintMinTrayLowLevelMessage,
+ 1,5,1,true);
+
+ addUIntSelector(m_pLevelsGroup,__tr2qs_ctx("Minimum level for high-priority message","options"),
+ KviOption_uintMinTrayHighLevelMessage,
+ 1,5,4,true);
+
+ addRowSpacer(0,6,0,6);
+
+ connect(m_pEnable,SIGNAL(toggled(bool)),this,SLOT(setEnabled(bool)));
+ connect(m_pLevelBasedNotify,SIGNAL(toggled(bool)),this,SLOT(setEnabled(bool)));
+ setEnabled(true);
+}
+
+KviTrayOptionsWidget::~KviTrayOptionsWidget()
+{
+}
+
+void KviTrayOptionsWidget::setEnabled(bool bEnabled)
+{
+ if(m_pEnable->isChecked())
+ {
+ m_pEnableFlashing->setEnabled(true);
+ m_pLevelBasedNotify->setEnabled(true);
+ m_pCloseInTray->setEnabled(true);
+ m_pMinimizeInTray->setEnabled(true);
+ if(m_pLevelBasedNotify->isChecked())
+ m_pLevelsGroup->setEnabled(true);
+ else
+ m_pLevelsGroup->setEnabled(false);
+
+ } else {
+ m_pCloseInTray->setEnabled(false);
+ m_pMinimizeInTray->setEnabled(false);
+ m_pEnableFlashing->setEnabled(false);
+ m_pLevelBasedNotify->setEnabled(false);
+ m_pLevelsGroup->setEnabled(false);
+ }
+}
+
+
+#include "m_optw_tray.moc"
diff --git a/src/modules/options/optw_tray.h b/src/modules/options/optw_tray.h
new file mode 100644
index 00000000..5be68f36
--- /dev/null
+++ b/src/modules/options/optw_tray.h
@@ -0,0 +1,50 @@
+#ifndef _OPTW_TRAY_H_
+#define _OPTW_TRAY_H_
+//
+// File : optw_tray.h
+// Creation date : Mon 14 Aug 2006 by Alexey Uzhva
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_optionswidget.h"
+#include <qcombobox.h>
+
+#define KVI_OPTIONS_WIDGET_ICON_KviTrayOptionsWidget KVI_SMALLICON_DOCKWIDGET
+#define KVI_OPTIONS_WIDGET_NAME_KviTrayOptionsWidget __tr2qs_no_lookup("Tray icon")
+#define KVI_OPTIONS_WIDGET_PARENT_KviTrayOptionsWidget KviInterfaceFeaturesOptionsWidget
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviTrayOptionsWidget __tr2qs_no_lookup("tray,dockwidget")
+
+class KviTrayOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviTrayOptionsWidget(QWidget * parent);
+ ~KviTrayOptionsWidget();
+protected:
+ KviBoolSelector * m_pEnable;
+ KviBoolSelector * m_pEnableFlashing;
+ KviBoolSelector * m_pLevelBasedNotify;
+ KviBoolSelector * m_pMinimizeInTray;
+ KviBoolSelector * m_pCloseInTray;
+ KviTalGroupBox * m_pLevelsGroup;
+protected slots:
+ void setEnabled(bool);
+};
+
+#endif //_OPTW_TRAY_H_
diff --git a/src/modules/options/optw_uparser.cpp b/src/modules/options/optw_uparser.cpp
new file mode 100644
index 00000000..01036fb6
--- /dev/null
+++ b/src/modules/options/optw_uparser.cpp
@@ -0,0 +1,62 @@
+//
+// File : optw_uparser.cpp
+// Creation date : Sat Oct 27 16:32:26 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+#include "optw_uparser.h"
+
+#include <qlayout.h>
+
+#include "kvi_options.h"
+#include "kvi_locale.h"
+
+#include <qlabel.h>
+
+
+KviUParserOptionsWidget::KviUParserOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"uparser_options_widget")
+{
+ createLayout(11,1);
+
+ addBoolSelector(0,0,0,0,__tr2qs_ctx("Disable parser warnings","options"),KviOption_boolAvoidParserWarnings);
+ addBoolSelector(0,1,0,1,__tr2qs_ctx("Disable broken event handlers","options"),KviOption_boolDisableBrokenEventHandlers);
+ addBoolSelector(0,2,0,2,__tr2qs_ctx("Kill broken timers","options"),KviOption_boolKillBrokenTimers);
+ addBoolSelector(0,3,0,3,__tr2qs_ctx("Send unknown commands as /RAW","options"),KviOption_boolSendUnknownCommandsAsRaw);
+
+ addSeparator(0,4,0,4);
+
+ addBoolSelector(0,5,0,5,__tr2qs_ctx("Automatically unload unused modules","options"),KviOption_boolCleanupUnusedModules);
+ addBoolSelector(0,6,0,6,__tr2qs_ctx("Ignore module versions (dangerous)","options"),KviOption_boolIgnoreModuleVersions);
+
+ addSeparator(0,7,0,7);
+
+ addBoolSelector(0,8,0,8,__tr2qs_ctx("Relay errors and warnings to debug window","options"),KviOption_boolScriptErrorsToDebugWindow);
+ addBoolSelector(0,9,0,9,__tr2qs_ctx("Create minimized debug window","options"),KviOption_boolShowMinimizedDebugWindow);
+
+ addRowSpacer(0,10,0,10);
+}
+
+KviUParserOptionsWidget::~KviUParserOptionsWidget()
+{
+}
+
+
+#include "m_optw_uparser.moc"
diff --git a/src/modules/options/optw_uparser.h b/src/modules/options/optw_uparser.h
new file mode 100644
index 00000000..1e35fe92
--- /dev/null
+++ b/src/modules/options/optw_uparser.h
@@ -0,0 +1,40 @@
+#ifndef _OPTW_UPARSER_H_
+#define _OPTW_UPARSER_H_
+//
+// File : optw_uparser.h
+// Creation date : Sat Oct 27 16:32:27 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_optionswidget.h"
+
+#define KVI_OPTIONS_WIDGET_ICON_KviUParserOptionsWidget KVI_SMALLICON_PARSERWARNING
+#define KVI_OPTIONS_WIDGET_NAME_KviUParserOptionsWidget __tr2qs_no_lookup("Scripting Engine")
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviUParserOptionsWidget __tr2qs_no_lookup("scripting,kvs,debug")
+#define KVI_OPTIONS_WIDGET_PARENT_KviUParserOptionsWidget KviGeneralOptOptionsWidget
+
+class KviUParserOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviUParserOptionsWidget(QWidget * parent);
+ ~KviUParserOptionsWidget();
+};
+
+#endif //_OPTW_UPARSER_H_
diff --git a/src/modules/options/optw_urlhandlers.cpp b/src/modules/options/optw_urlhandlers.cpp
new file mode 100644
index 00000000..48ea2297
--- /dev/null
+++ b/src/modules/options/optw_urlhandlers.cpp
@@ -0,0 +1,127 @@
+#ifndef _OPTW_URLHANDLERS_CPP_
+#define _OPTW_URLHANDLERS_CPP_
+//
+// File : optw_urlhandlers.cpp
+// Creation date : Fri Aug 23 02:57:40 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "optw_urlhandlers.h"
+
+#include <qlayout.h>
+
+#include "kvi_options.h"
+#include "kvi_locale.h"
+
+#include <qlabel.h>
+
+
+KviUrlHandlersOptionsWidget::KviUrlHandlersOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"urlhandlers_options_widget")
+{
+#ifdef COMPILE_ON_WINDOWS
+ #define START_ROW 1
+#else
+ #define START_ROW 0
+#endif
+
+ createLayout(START_ROW+7,1);
+
+#ifdef COMPILE_ON_WINDOWS
+ KviBoolSelector *b = addBoolSelector(0,0,0,0,__tr2qs_ctx("Use system URL handlers","options"),KviOption_boolUseSystemUrlHandlers);
+#endif
+
+ m_pHttpHandler=addStringSelector(0,START_ROW+0,0,START_ROW+0,__tr2qs_ctx("<b>http://</b> handler command:","options"),KviOption_stringUrlHttpCommand);
+ m_pHttpsHandler=addStringSelector(0,START_ROW+1,0,START_ROW+1,__tr2qs_ctx("<b>https://</b> handler command:","options"),KviOption_stringUrlHttpsCommand);
+ m_pFtpHandler=addStringSelector(0,START_ROW+2,0,START_ROW+2,__tr2qs_ctx("<b>ftp://</b> handler command:","options"),KviOption_stringUrlFtpCommand);
+ m_pMailtoHandler=addStringSelector(0,START_ROW+3,0,START_ROW+3,__tr2qs_ctx("<b>mailto:</b> handler command:","options"),KviOption_stringUrlMailtoCommand);
+ m_pFileHandler=addStringSelector(0,START_ROW+4,0,START_ROW+4,__tr2qs_ctx("<b>file://</b> handler command:","options"),KviOption_stringUrlFileCommand);
+ m_pOtherHandler=addStringSelector(0,START_ROW+5,0,START_ROW+5,__tr2qs_ctx("Unknown protocol handler command:","options"),KviOption_stringUrlUnknownCommand);
+
+#ifdef COMPILE_ON_WINDOWS
+ m_pHttpHandler->setEnabled(!KVI_OPTION_BOOL(KviOption_boolUseSystemUrlHandlers));
+ m_pHttpsHandler->setEnabled(!KVI_OPTION_BOOL(KviOption_boolUseSystemUrlHandlers));
+ m_pFtpHandler->setEnabled(!KVI_OPTION_BOOL(KviOption_boolUseSystemUrlHandlers));
+ m_pFileHandler->setEnabled(!KVI_OPTION_BOOL(KviOption_boolUseSystemUrlHandlers));
+ m_pMailtoHandler->setEnabled(!KVI_OPTION_BOOL(KviOption_boolUseSystemUrlHandlers));
+ m_pOtherHandler->setEnabled(!KVI_OPTION_BOOL(KviOption_boolUseSystemUrlHandlers));
+
+ connect(b,SIGNAL(toggled(bool)),this,SLOT(toggleEditors(bool)));
+
+#endif
+
+ addRowSpacer(0,START_ROW+6,0,START_ROW+6);
+}
+
+KviUrlHandlersOptionsWidget::~KviUrlHandlersOptionsWidget()
+{
+}
+
+void KviUrlHandlersOptionsWidget::toggleEditors(bool bToggled)
+{
+ m_pHttpHandler->setEnabled(!bToggled);
+ m_pHttpsHandler->setEnabled(!bToggled);
+ m_pFtpHandler->setEnabled(!bToggled);
+ m_pFileHandler->setEnabled(!bToggled);
+ m_pMailtoHandler->setEnabled(!bToggled);
+ m_pOtherHandler->setEnabled(!bToggled);
+}
+
+void KviUrlHandlersOptionsWidget::commit()
+{
+ KviOptionsWidget::commit();
+
+#ifdef COMPILE_ON_WINDOWS
+ KVI_OPTION_STRING(KviOption_stringUrlHttpCommand).replace("\\\\","@MAGIC@","options");
+ KVI_OPTION_STRING(KviOption_stringUrlHttpCommand).replace("\\","\\\\","options");
+ KVI_OPTION_STRING(KviOption_stringUrlHttpCommand).replace("@MAGIC@","\\\\","options");
+
+ KVI_OPTION_STRING(KviOption_stringUrlHttpsCommand).replace("\\\\","@MAGIC@","options");
+ KVI_OPTION_STRING(KviOption_stringUrlHttpsCommand).replace("\\","\\\\","options");
+ KVI_OPTION_STRING(KviOption_stringUrlHttpsCommand).replace("@MAGIC@","\\\\","options");
+
+ KVI_OPTION_STRING(KviOption_stringUrlFtpCommand).replace("\\\\","@MAGIC@","options");
+ KVI_OPTION_STRING(KviOption_stringUrlFtpCommand).replace("\\","\\\\","options");
+ KVI_OPTION_STRING(KviOption_stringUrlFtpCommand).replace("@MAGIC@","\\\\","options");
+
+ KVI_OPTION_STRING(KviOption_stringUrlMailtoCommand).replace("\\\\","@MAGIC@","options");
+ KVI_OPTION_STRING(KviOption_stringUrlMailtoCommand).replace("\\","\\\\","options");
+ KVI_OPTION_STRING(KviOption_stringUrlMailtoCommand).replace("@MAGIC@","\\\\","options");
+
+ KVI_OPTION_STRING(KviOption_stringUrlFileCommand).replace("\\\\","@MAGIC@","options");
+ KVI_OPTION_STRING(KviOption_stringUrlFileCommand).replace("\\","\\\\","options");
+ KVI_OPTION_STRING(KviOption_stringUrlFileCommand).replace("@MAGIC@","\\\\","options");
+
+ KVI_OPTION_STRING(KviOption_stringUrlUnknownCommand).replace("\\\\","@MAGIC@","options");
+ KVI_OPTION_STRING(KviOption_stringUrlUnknownCommand).replace("\\","\\\\","options");
+ KVI_OPTION_STRING(KviOption_stringUrlUnknownCommand).replace("@MAGIC@","\\\\","options");
+
+ //Check for escaped " in url handler ( \" )
+ KVI_OPTION_STRING(KviOption_stringUrlHttpCommand).replace("\\\\\"","\\\"","options");
+ KVI_OPTION_STRING(KviOption_stringUrlHttpsCommand).replace("\\\\\"","\\\"","options");
+ KVI_OPTION_STRING(KviOption_stringUrlFtpCommand).replace("\\\\\"","\\\"","options");
+ KVI_OPTION_STRING(KviOption_stringUrlMailtoCommand).replace("\\\\\"","\\\"","options");
+ KVI_OPTION_STRING(KviOption_stringUrlFileCommand).replace("\\\\\"","\\\"","options");
+ KVI_OPTION_STRING(KviOption_stringUrlUnknownCommand).replace("\\\\\"","\\\"","options");
+#endif
+}
+
+#include "m_optw_urlhandlers.moc"
+
+#endif //_OPTW_URLHANDLERS_CPP_
diff --git a/src/modules/options/optw_urlhandlers.h b/src/modules/options/optw_urlhandlers.h
new file mode 100644
index 00000000..9ed6c188
--- /dev/null
+++ b/src/modules/options/optw_urlhandlers.h
@@ -0,0 +1,52 @@
+#ifndef _OPTW_URLHANDLERS_H_
+#define _OPTW_URLHANDLERS_H_
+//
+// File : optw_urlhandlers.h
+// Creation date : Fri Aug 23 02:57:41 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_optionswidget.h"
+
+#define KVI_OPTIONS_WIDGET_ICON_KviUrlHandlersOptionsWidget KVI_SMALLICON_WORLD
+#define KVI_OPTIONS_WIDGET_NAME_KviUrlHandlersOptionsWidget __tr2qs_no_lookup("URL handlers")
+#define KVI_OPTIONS_WIDGET_PARENT_KviUrlHandlersOptionsWidget KviGeneralOptOptionsWidget
+#define KVI_OPTIONS_WIDGET_PRIORITY_KviUrlHandlersOptionsWidget 70000
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviUrlHandlersOptionsWidget __tr2qs_no_lookup("url,programs")
+
+class KviUrlHandlersOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviUrlHandlersOptionsWidget(QWidget * parent);
+ ~KviUrlHandlersOptionsWidget();
+private:
+ KviStringSelector* m_pHttpHandler;
+ KviStringSelector* m_pHttpsHandler;
+ KviStringSelector* m_pFtpHandler;
+ KviStringSelector* m_pMailtoHandler;
+ KviStringSelector* m_pFileHandler;
+ KviStringSelector* m_pOtherHandler;
+public:
+ virtual void commit();
+public slots:
+ void toggleEditors(bool);
+};
+
+#endif //_OPTW_URLHANDLERS_H_
diff --git a/src/modules/options/optw_userlist.cpp b/src/modules/options/optw_userlist.cpp
new file mode 100644
index 00000000..07b39d0d
--- /dev/null
+++ b/src/modules/options/optw_userlist.cpp
@@ -0,0 +1,245 @@
+//
+// File : optw_userlist.cpp
+// Creation date : Sat Aug 11 2001 03:29:52 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+#include "optw_userlist.h"
+
+#include <qlayout.h>
+
+#include "kvi_options.h"
+#include "kvi_locale.h"
+#include "kvi_userlistview.h"
+
+//#warning "Info tips"
+
+KviUserListLookOptionsWidget::KviUserListLookOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"userlistlook_options_widget")
+{
+}
+
+KviUserListLookOptionsWidget::~KviUserListLookOptionsWidget()
+{
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+KviUserListLookForegroundOptionsWidget::KviUserListLookForegroundOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"userlistlook_foreground_options_widget")
+{
+ createLayout(2,2);
+
+ addFontSelector(0,0,1,0,__tr2qs_ctx("Font:","options"),KviOption_fontUserListView);
+
+ KviTalGroupBox * g = addGroupBox(0,1,1,1,1,Qt::Horizontal,__tr2qs_ctx("Nickname Colors","options"));
+ addColorSelector(g,__tr2qs_ctx("Normal:","options"),KviOption_colorUserListViewNormalForeground);
+ addColorSelector(g,__tr2qs_ctx("Selected:","options"),KviOption_colorUserListViewSelectionForeground);
+ addColorSelector(g,__tr2qs_ctx("Channel owner:","options"),KviOption_colorUserListViewChanOwnerForeground);
+ addColorSelector(g,__tr2qs_ctx("Channel admin:","options"),KviOption_colorUserListViewChanAdminForeground);
+ addColorSelector(g,__tr2qs_ctx("Op:","options"),KviOption_colorUserListViewOpForeground);
+ addColorSelector(g,__tr2qs_ctx("Half-op:","options"),KviOption_colorUserListViewHalfOpForeground);
+ addColorSelector(g,__tr2qs_ctx("Voice:","options"),KviOption_colorUserListViewVoiceForeground);
+ addColorSelector(g,__tr2qs_ctx("User-op:","options"),KviOption_colorUserListViewUserOpForeground);
+ addColorSelector(g,__tr2qs_ctx("Away:","options"),KviOption_colorUserListViewAwayForeground);
+
+ KviTalHBox * hb = new KviTalHBox(g);
+ hb->setSpacing(4);
+ KviBoolSelector * b = addBoolSelector(hb,__tr2qs_ctx("Use different color for own nick:","options"),KviOption_boolUseDifferentColorForOwnNick);
+ KviColorSelector * s = addColorSelector(hb,"",KviOption_colorUserListViewOwnForeground,KVI_OPTION_BOOL(KviOption_boolUseDifferentColorForOwnNick));
+ connect(b,SIGNAL(toggled(bool)),s,SLOT(setEnabled(bool)));
+
+ addRowSpacer(0,3,0,3);
+}
+
+KviUserListLookForegroundOptionsWidget::~KviUserListLookForegroundOptionsWidget()
+{
+}
+
+KviUserListGridOptionsWidget::KviUserListGridOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent)
+{
+ createLayout(5,1);
+ KviBoolSelector* b = addBoolSelector(0,0,0,0,__tr2qs_ctx("Draw nickname grid","options"),KviOption_boolUserListViewDrawGrid);
+
+ KviColorSelector* s = addColorSelector(0,1,0,1,__tr2qs_ctx("Grid color:","options"),KviOption_colorUserListViewGrid,KVI_OPTION_BOOL(KviOption_boolUserListViewDrawGrid));
+ connect(b,SIGNAL(toggled(bool)),s,SLOT(setEnabled(bool)));
+
+ KviTalHBox* hb = new KviTalHBox(this);
+ addWidgetToLayout(hb,0,2,0,2);
+ hb->setSpacing(4);
+
+ QLabel * l = new QLabel(__tr2qs_ctx("Grid type:","options"),hb);
+ l->setEnabled(KVI_OPTION_BOOL(KviOption_boolUserListViewDrawGrid));
+ connect(b,SIGNAL(toggled(bool)),l,SLOT(setEnabled(bool)));
+ m_pGridTypeCombo = new QComboBox(false,hb);
+ m_pGridTypeCombo->insertItem(__tr2qs_ctx("3D Grid","options"));
+ m_pGridTypeCombo->insertItem(__tr2qs_ctx("3D Buttons","options"));
+ m_pGridTypeCombo->insertItem(__tr2qs_ctx("Plain Grid","options"));
+ m_pGridTypeCombo->insertItem(__tr2qs_ctx("Dotted Grid","options"));
+ m_pGridTypeCombo->setCurrentItem(KVI_OPTION_UINT(KviOption_uintUserListViewGridType));
+ m_pGridTypeCombo->setEnabled(KVI_OPTION_BOOL(KviOption_boolUserListViewDrawGrid));
+ connect(b,SIGNAL(toggled(bool)),m_pGridTypeCombo,SLOT(setEnabled(bool)));
+ addRowSpacer(0,3,0,3);
+}
+
+KviUserListGridOptionsWidget::~KviUserListGridOptionsWidget()
+{
+}
+
+void KviUserListGridOptionsWidget::commit()
+{
+ KviOptionsWidget::commit();
+ KVI_OPTION_UINT(KviOption_uintUserListViewGridType) = m_pGridTypeCombo->currentItem();
+ if(KVI_OPTION_UINT(KviOption_uintUserListViewGridType) > KVI_USERLISTVIEW_GRIDTYPE_MAXIMUM)
+ KVI_OPTION_UINT(KviOption_uintUserListViewGridType) = KVI_USERLISTVIEW_GRIDTYPE_DEFAULT;
+
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+
+KviUserListLookBackgroundOptionsWidget::KviUserListLookBackgroundOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"userlistlook_background_options_widget")
+{
+ createLayout(3,2);
+
+ KviTalGroupBox * g = addGroupBox(0,0,1,0,1,Qt::Horizontal,__tr2qs_ctx("Background Colors","options"));
+ addColorSelector(g,__tr2qs_ctx("Normal:","options"),KviOption_colorUserListViewBackground);
+ addColorSelector(g,__tr2qs_ctx("Selected:","options"),KviOption_colorUserListViewSelectionBackground);
+
+
+ addPixmapSelector(0,1,1,1,__tr2qs_ctx("Background image:","options"),KviOption_pixmapUserListViewBackground);
+
+ addLabel(0,2,0,2,__tr2qs_ctx("Horizontal Alignment:","options"));
+ m_pHorizontalAlign=new QComboBox(this);
+ addWidgetToLayout(m_pHorizontalAlign,1,2,1,2);
+
+ addLabel(0,3,0,3,__tr2qs_ctx("Vertical Alignment:","options"));
+ m_pVerticalAlign=new QComboBox(this);
+ addWidgetToLayout(m_pVerticalAlign,1,3,1,3);
+
+ m_pHorizontalAlign->insertItem(__tr2qs_ctx("Tile","options"));
+ m_pHorizontalAlign->insertItem(__tr2qs_ctx("Left","options"));
+ m_pHorizontalAlign->insertItem(__tr2qs_ctx("Right","options"));
+ m_pHorizontalAlign->insertItem(__tr2qs_ctx("Center","options"));
+
+ m_pVerticalAlign->insertItem(__tr2qs_ctx("Tile","options"));
+ m_pVerticalAlign->insertItem(__tr2qs_ctx("Top","options"));
+ m_pVerticalAlign->insertItem(__tr2qs_ctx("Bottom","options"));
+ m_pVerticalAlign->insertItem(__tr2qs_ctx("Center","options"));
+
+ switch( KVI_OPTION_UINT(KviOption_uintUserListPixmapAlign) & Qt::AlignHorizontal_Mask)
+ {
+ case Qt::AlignLeft:
+ m_pHorizontalAlign->setCurrentItem(1);
+ break;
+ case Qt::AlignRight:
+ m_pHorizontalAlign->setCurrentItem(2);
+ break;
+ case Qt::AlignHCenter:
+ m_pHorizontalAlign->setCurrentItem(3);
+ break;
+ default:
+ m_pHorizontalAlign->setCurrentItem(0);
+ }
+
+ switch( KVI_OPTION_UINT(KviOption_uintUserListPixmapAlign) & Qt::AlignVertical_Mask)
+ {
+ case Qt::AlignTop:
+ m_pVerticalAlign->setCurrentItem(1);
+ break;
+ case Qt::AlignBottom:
+ m_pVerticalAlign->setCurrentItem(2);
+ break;
+ case Qt::AlignVCenter:
+ m_pVerticalAlign->setCurrentItem(3);
+ break;
+ default:
+ m_pVerticalAlign->setCurrentItem(0);
+ }
+
+
+
+ //layout()->setColStretch(0,1);
+ layout()->setRowStretch(1,1);
+}
+
+KviUserListLookBackgroundOptionsWidget::~KviUserListLookBackgroundOptionsWidget()
+{
+}
+
+
+void KviUserListLookBackgroundOptionsWidget::commit()
+{
+ KviOptionsWidget::commit();
+
+ int iFlags=0;
+ switch(m_pHorizontalAlign->currentItem())
+ {
+ case 1:
+ iFlags|=Qt::AlignLeft;
+ break;
+ case 2:
+ iFlags|=Qt::AlignRight;
+ break;
+ case 3:
+ iFlags|=Qt::AlignHCenter;
+ break;
+ }
+ switch(m_pVerticalAlign->currentItem())
+ {
+ case 1:
+ iFlags|=Qt::AlignTop;
+ break;
+ case 2:
+ iFlags|=Qt::AlignBottom;
+ break;
+ case 3:
+ iFlags|=Qt::AlignVCenter;
+ break;
+ }
+
+ KVI_OPTION_UINT(KviOption_uintUserListPixmapAlign)=iFlags;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+KviUserListFeaturesOptionsWidget::KviUserListFeaturesOptionsWidget(QWidget * parent)
+: KviOptionsWidget(parent,"userlistfeatures_options_widget")
+{
+ createLayout(7,1);
+
+ KviBoolSelector *b = addBoolSelector(0,0,0,0,__tr2qs_ctx("Show gender icons","options"),KviOption_boolDrawGenderIcons);
+ b = addBoolSelector(0,1,0,1,__tr2qs_ctx("Show user channel icons","options"),KviOption_boolShowUserChannelIcons);
+ b = addBoolSelector(0,2,0,2,__tr2qs_ctx("Show user channel activity indicator","options"),KviOption_boolShowUserChannelState);
+ b = addBoolSelector(0,3,0,3,__tr2qs_ctx("Hide users label","options"),KviOption_boolDisableUserListLabel);
+ b = addBoolSelector(0,4,0,4,__tr2qs_ctx("Enable user tooltips","options"),KviOption_boolShowUserListViewToolTips);
+ b = addBoolSelector(0,5,0,5,__tr2qs_ctx("Hide avatars","options"),KviOption_boolDisableAvatars);
+
+ addRowSpacer(0,6,0,6);
+}
+
+KviUserListFeaturesOptionsWidget::~KviUserListFeaturesOptionsWidget()
+{
+}
+
+#include "m_optw_userlist.moc"
diff --git a/src/modules/options/optw_userlist.h b/src/modules/options/optw_userlist.h
new file mode 100644
index 00000000..d5fd4c12
--- /dev/null
+++ b/src/modules/options/optw_userlist.h
@@ -0,0 +1,114 @@
+#ifndef _OPTW_USERLIST_H_
+#define _OPTW_USERLIST_H_
+
+//
+// File : optw_userlist.h
+// Creation date : Sat Mar 02 2002 12:09:19 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002-2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_optionswidget.h"
+#include <qcombobox.h>
+
+#define KVI_OPTIONS_WIDGET_ICON_KviUserListLookOptionsWidget KVI_SMALLICON_USERLIST
+#define KVI_OPTIONS_WIDGET_NAME_KviUserListLookOptionsWidget __tr2qs_no_lookup("Userlist")
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviUserListLookOptionsWidget __tr2qs_no_lookup("theme,userlist,channel")
+#define KVI_OPTIONS_WIDGET_GROUP_KviUserListLookOptionsWidget "theme"
+#define KVI_OPTIONS_WIDGET_CONTAINER_KviUserListLookOptionsWidget true
+
+class KviUserListLookOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviUserListLookOptionsWidget(QWidget * parent);
+ ~KviUserListLookOptionsWidget();
+};
+
+#define KVI_OPTIONS_WIDGET_ICON_KviUserListLookBackgroundOptionsWidget KVI_SMALLICON_TRANSPARENT
+#define KVI_OPTIONS_WIDGET_NAME_KviUserListLookBackgroundOptionsWidget __tr2qs_no_lookup("Background")
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviUserListLookBackgroundOptionsWidget __tr2qs_no_lookup("theme,userlist,channel,background")
+#define KVI_OPTIONS_WIDGET_GROUP_KviUserListLookBackgroundOptionsWidget "theme"
+#define KVI_OPTIONS_WIDGET_PARENT_KviUserListLookBackgroundOptionsWidget KviUserListLookOptionsWidget
+#define KVI_OPTIONS_WIDGET_PRIORITY_KviUserListLookBackgroundOptionsWidget 30
+
+
+class KviUserListLookBackgroundOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviUserListLookBackgroundOptionsWidget(QWidget * parent);
+ ~KviUserListLookBackgroundOptionsWidget();
+protected:
+ QComboBox* m_pHorizontalAlign;
+ QComboBox* m_pVerticalAlign;
+public:
+ virtual void commit();
+};
+
+#define KVI_OPTIONS_WIDGET_ICON_KviUserListLookForegroundOptionsWidget KVI_SMALLICON_USERLIST
+#define KVI_OPTIONS_WIDGET_NAME_KviUserListLookForegroundOptionsWidget __tr2qs_no_lookup("Foreground")
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviUserListLookForegroundOptionsWidget __tr2qs_no_lookup("theme,userlist,channel,colors")
+#define KVI_OPTIONS_WIDGET_GROUP_KviUserListLookForegroundOptionsWidget "theme"
+#define KVI_OPTIONS_WIDGET_PARENT_KviUserListLookForegroundOptionsWidget KviUserListLookOptionsWidget
+#define KVI_OPTIONS_WIDGET_PRIORITY_KviUserListLookForegroundOptionsWidget 20
+
+
+class KviUserListLookForegroundOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviUserListLookForegroundOptionsWidget(QWidget * parent);
+ ~KviUserListLookForegroundOptionsWidget();
+};
+
+#define KVI_OPTIONS_WIDGET_ICON_KviUserListGridOptionsWidget KVI_SMALLICON_GUI
+#define KVI_OPTIONS_WIDGET_NAME_KviUserListGridOptionsWidget __tr2qs_no_lookup("Nickname Grid")
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviUserListGridOptionsWidget __tr2qs_no_lookup("theme,userlist,channel,grid")
+#define KVI_OPTIONS_WIDGET_GROUP_KviUserListGridOptionsWidget "theme"
+#define KVI_OPTIONS_WIDGET_PARENT_KviUserListGridOptionsWidget KviUserListLookOptionsWidget
+#define KVI_OPTIONS_WIDGET_PRIORITY_KviUserListGridOptionsWidget 30
+
+
+class KviUserListGridOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviUserListGridOptionsWidget(QWidget * parent);
+ ~KviUserListGridOptionsWidget();
+protected:
+ QComboBox * m_pGridTypeCombo;
+public:
+ virtual void commit();
+};
+
+#define KVI_OPTIONS_WIDGET_ICON_KviUserListFeaturesOptionsWidget KVI_SMALLICON_GUI
+#define KVI_OPTIONS_WIDGET_NAME_KviUserListFeaturesOptionsWidget __tr2qs_no_lookup("Features")
+#define KVI_OPTIONS_WIDGET_KEYWORDS_KviUserListFeaturesOptionsWidget __tr2qs_no_lookup("userlist,channel")
+#define KVI_OPTIONS_WIDGET_PARENT_KviUserListFeaturesOptionsWidget KviUserListLookOptionsWidget
+#define KVI_OPTIONS_WIDGET_PRIORITY_KviUserListFeaturesOptionsWidget 10
+
+class KviUserListFeaturesOptionsWidget : public KviOptionsWidget
+{
+ Q_OBJECT
+public:
+ KviUserListFeaturesOptionsWidget(QWidget * parent);
+ ~KviUserListFeaturesOptionsWidget();
+};
+
+#endif //!_OPTW_USERLIST_H_
diff --git a/src/modules/perl/Makefile.am b/src/modules/perl/Makefile.am
new file mode 100644
index 00000000..ea5e4a5b
--- /dev/null
+++ b/src/modules/perl/Makefile.am
@@ -0,0 +1,18 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkviperl.la
+
+libkviperl_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkviperl_la_SOURCES = libkviperl.cpp
+libkviperl_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+# noinst_HEADERS=
+
+%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
diff --git a/src/modules/perl/libkviperl.cpp b/src/modules/perl/libkviperl.cpp
new file mode 100644
index 00000000..a898e43a
--- /dev/null
+++ b/src/modules/perl/libkviperl.cpp
@@ -0,0 +1,600 @@
+//=============================================================================
+//
+// File : libkviperl.cpp
+// Creation date : Tue Jul 13 13:03:31 2004 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2004-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_module.h"
+
+#include "kvi_fileutils.h"
+#include "kvi_locale.h"
+#include "kvi_app.h"
+#include "kvi_options.h"
+#include "kvi_modulemanager.h"
+#include "kvi_out.h"
+
+#ifdef COMPILE_PERL_SUPPORT
+ #include "../perlcore/perlcoreinterface.h"
+
+ static KviModule * g_pPerlCoreModule = 0;
+#endif // COMPILE_PERL_SUPPORT
+
+#ifdef COMPILE_PERL_SUPPORT
+ #define KVS_CHECK_PERLCORE(_m,_c) \
+ g_pPerlCoreModule = g_pModuleManager->getModule("perlcore"); \
+ if(!g_pPerlCoreModule) \
+ { \
+ if(!_c->switches()->find('q',"quiet")) \
+ { \
+ _c->warning(__tr2qs_ctx("The perlcore module can't be loaded: perl support not available","perl")); \
+ _c->warning(__tr2qs_ctx("To see more details about loading failure try /perlcore.load","perl")); \
+ return true; \
+ } \
+ }
+#else // !COMPILE_PERL_SUPPORT
+ #define KVS_CHECK_PERLCORE(_m,_c)
+#endif // !COMPILE_PERL_SUPPORT
+
+#ifdef COMPILE_PERL_SUPPORT
+ #define KVS_CHECK_MODULE_STATE(_m,_c) KVS_CHECK_PERLCORE(_m,_c)
+#else // !COMPILE_PERL_SUPPORT
+ #define KVS_CHECK_MODULE_STATE(_m,_c) \
+ if(!_c->switches()->find('q',"quiet")) \
+ _c->warning(__tr2qs_ctx("This KVIrc executable has been compiled without perl scripting support","perl")); \
+ return true;
+#endif // !COMPILE_PERL_SUPPORT
+
+/*
+ @doc: perl_and_kvs
+ @type:
+ language
+ @title:
+ Using perl from KVS and vice-versa.
+ @short:
+ How to use perl from KVS and KVS from perl.
+ @body:
+ [big]Introduction[/big][br]
+ Starting from version 3.0.2 you can include perl code snippets
+ in KVS code and you can use KVS commands from within perl.
+ This feature is present only if a working perl installation
+ has been found at ./configure time.[br]
+ [br]
+
+ [big]Using perl from KVS[/big][br]
+ Using perl from KVIrc is really easy: just enclose
+ your perl code snippet inside [cmd]perl.begin[/cmd] and [cmd]perl.end[/cmd].
+ [example]
+ [cmd]perl.begin[/cmd]
+ &lt;perl code goes here&gt;
+ [cmd]perl.end[/cmd]
+ [/example]
+ For example:[br]
+ [example]
+ [cmd]perl.begin[/cmd]
+ open(MYFILE,'>>myfile.txt') or die "Can't open myfile.txt!";
+ print MYFILE "foo!\n";
+ close(MYFILE);
+ [cmd]perl.end[/cmd]
+ [/example]
+ A perl code snippet can appear anywhere a KVS code snippet can
+ with the only restriction that i must be enclosed in [cmd]perl.begin[/cmd]
+ and [cmd]perl.end[/cmd]. This means that you can write perl code
+ in the commandline, in the aliases, the event handlers, popups...anywhere.[br]
+ If you have already encountered the KVIrc's [cmd]eval[/cmd] command
+ that you probably also know how to execute a perl code snippet from a file :)[br]
+ [br]
+
+ [big]Using KVS from perl[/big][br]
+ KVIrc exports several commands to the perl namespace
+ that allow you to invoke KVIrc's functions from inside the perl code snippet.[br]
+ The nicest example is KVIrc::echo():
+ [example]
+ [cmd]perl.begin[/cmd]
+ KVIrc::echo("Hello KVIrc world from perl!");
+ [cmd]perl.end[/cmd]
+ [/example]
+ KVIrc::echo() is the counterpart of the [cmd]echo[/cmd].
+ The exact syntax is:[br]
+ &nbsp; &nbsp; [b]KVIrc::echo(&lt;text&gt;[,&lt;colorset&gt;[,&lt;windowid&gt;]])[/b][br]
+ &lt;text&gt; is obviously the text to be printed. &lt;colorset&gt; is
+ the equivalent of the [cmd]echo[/cmd] -i option and &lt;windowid&gt;
+ is the equivalent of the -w option. Both &lt;colorset&gt; and &lt;windowid&gt;
+ can be omitted (in this case KVIrc will use a default colorset and the current window).[br]
+ [br]
+
+ [big]Perl execution contexts[/big][br]
+ The perl code snippets are executed by the means of a perl interpreter.
+ Each perl interpreter has its own context and thus it's own variables,
+ own function namespace etc.[br]
+ [br]
+ In the example above KVIrc creates an interpreter when [cmd]perl.begin[/cmd]
+ is invoked and destroys it at [cmd]perl.end[/cmd] parsing time.
+ In fact, KVIrc can mantain multiple persistent interpreters that will
+ allow you to preserve your context across [cmd]perl.begin[/cmd] invocations.[br]
+ You can invoke a specific perl context by passing it as parameter to the [cmd]perl.begin[/cmd]
+ command.[br]
+ [example]
+ [cmd]perl.begin("mycontext")[/cmd]
+ $myvariable = "mycontext";
+ KVIrc::echo("This perl code is executed from ".$myvariable);
+ [cmd]perl.end[/cmd]
+ [/example]
+ The nice thing is that at a later time you can invoke this context again
+ and discover that $mycontext has preserved its value:[br]
+ [example]
+ [cmd]perl.begin("mycontext")[/cmd]
+ KVIrc::echo("myvariable is still equal to ".$myvariable);
+ [cmd]perl.end[/cmd]
+ [/example]
+ The first time you invoke a named perl context it gets automatically created and
+ it persists until KVIrc terminates or the perl context is explicitly destroyed
+ by the means of [cmd]perl.destroy[/cmd].[br]
+ [br]
+ In fact there is a third possibility to destroy a context: it's when the
+ perlcore module is forcibly unloaded (by the means of /perlcore.unload) but
+ this is really a rare case and should be threated just like a KVIrc restart (the
+ user probably WANTS the contexts to be reinitialized).[br]
+ [br]
+ The nice thing is that not only your variables will get preserved
+ but also any perl function or class you declare in a context will persist.
+ It's just like executing a long perl script file with pauses inside.[br]
+ [br]
+ If you omit the perl context name in the [cmd]perl.begin[/cmd] command
+ (or if you use an empty string in it's place)
+ then KVIrc will create a temporary context for the snippet execution
+ and will destroy it immediately after [cmd]perl.end[/cmd] has been called.[br]
+ [br]
+ The major side effect of keeping persistent perl contexts is that
+ the perl's symbol table will grow and if not used carefully the interpreter
+ may become a memory hog. So if you're going to use persistent contexts
+ either try to keep the symbol table clean or explicitly call [cmd]perl.destroy[/cmd]
+ once in a while to recreate the interpreter.[br]
+ If you just execute occasional perl code snippets and don't need to keep persistent variables
+ then just use the nameless temporary context provided by [cmd]perl.begin[/cmd]("").[br]
+ [br]
+
+ [big]Passing parameters to the perl script[/big][br]
+ The easiest way to pass parameters to the perl code snippet
+ is to put them as [cmd]perl.begin[/cmd] arguments.
+ In fact the complete syntax of [cmd]perl.begin[/cmd] is:[br]
+ [b]perl.begin(&lt;perl context&gt;,&lt;arg0&gt;,&lt;arg1&gt;,...)[/b][br]
+ Where the &lt;arg0&gt;,&lt;arg1&gt;...&lt;argN&gt; parameters
+ are passed to the perl context as elements of the $_[] array.[br]
+ [example]
+ [cmd]perl.begin[/cmd]("","Hello world!","Now I CAN",1,2,3)
+ for($i=0;$i<5;$i++)
+ KVIrc::echo($_[i],40);
+ [cmd]perl.end[/cmd]
+ [/example]
+ [br]
+
+ [big]Accessing the KVIrc scripting context from perl[/big][br]
+ KVIrc exposes the following functions that manipulate the
+ variables of the KVIrc's current KVS execution context.[br]
+ &nbsp; &nbsp; [b]KVIrc::getLocal(&lt;x&gt;)[/b][br]
+ Returns the value of the KVIrc's local variable %x.[br]
+ &nbsp; &nbsp; [b]KVIrc::getGlobal(&lt;Y&gt;)[/b][br]
+ Returns the value of the KVIrc's global variable %Y.[br]
+ &nbsp; &nbsp; [b]KVIrc::setLocal(&lt;x&gt;,&lt;value&gt;)[/b][br]
+ Sets the KVIrc's global variable %x to &lt;value&gt;[br]
+ &nbsp; &nbsp; [b]KVIrc::setGlobal(&lt;Y&gt;,&lt;value&gt;)[/b][br]
+ Sets the KVIrc's global variable %Y to &lt;value&gt;[br]
+ The local variables interested belong to the current KVS exection context
+ while the global variables are visible everywhere.[br]
+ [example]
+ %pippo = test
+ %Pluto = 12345
+ [cmd]perl.begin[/cmd]
+ $mypippo = KVIrc::getLocal("pippo");
+ $mypippo =~ s/^pi/ze/g;
+ $mypluto = KVIrc::getGlobal("Pluto");
+ $mypluto =~ s/23/xx/g;
+ KVIrc::setLocal("pippo",$mypluto);
+ KVIrc::setGlobal("Pluto",$mypippo);
+ [cmd]perl.end[/cmd]
+ [cmd]echo[/cmd] "\%pippo is" %pippo
+ [cmd]echo[/cmd] "\%Pluto is" %Pluto
+ [/example]
+ [br]
+
+ [big]Executing arbitrary KVIrc commands from perl[/big][br]
+ You can execute arbitrary KVS commands from perl by the means of:[br]
+ &nbsp; &nbsp; [b]KVIrc::eval(&lt;code&gt;)[/b][br]
+ This function behaves exactly like the ${ &lt;code&gt; } KVS construct:
+ it executes &lt;code&gt; in a child context and returns it's evaluation retult.[br]
+ The following two code snippets have equivalent visible effects:[br]
+ [example]
+ [cmd]echo[/cmd] ${ return "Yeah!"; }
+ [/example]
+ [example]
+ [cmd]perl.begin[/cmd]
+ KVIrc::echo(KVIrc::eval("return \"Yeah!\""));
+ [cmd]perl.end[/cmd]
+ [/example]
+ You can "eval" composite command sequences and variable ones.[br]
+ Remember that the perl code snippet is evaluated in a child KVS context
+ and thus the local variables are NOT visible!.
+ The following code snippets may easily fool you:[br]
+ [example]
+ %x = 10
+ [cmd]perl.begin[/cmd]
+ KVIrc::eval("echo \"The value is %x\"");
+ [cmd]perl.end[/cmd]
+ [/example]
+ This will print "The value is " since %x is not accessible from the eval's context.
+ If you have tried to write something like this then you probably need to rewrite it as:[br]
+ [example]
+ %x = 10
+ [cmd]perl.begin[/cmd]
+ $x = KVIrc::getLocal("x");
+ KVIrc::eval("echo \"The value is ".$x."\"");
+ [cmd]perl.end[/cmd]
+ [/example]
+ [br]
+ Note also that you must either escape the $ at the beginning of the KVIrc identifiers
+ or use the single quotes to prevent perl from catching the $ as the beginning of
+ a variable.
+ [example]
+ [comment]# This will not work as expected[/comment]
+ [cmd]perl.begin[/cmd]
+ KVIrc::echo(KVIrc::eval("return $window.caption"));
+ [cmd]perl.end[/cmd]
+ [comment]# But these will do[/comment]
+ [cmd]perl.begin[/cmd]
+ KVIrc::echo(KVIrc::eval("return \$window.caption"));
+ KVIrc::echo(KVIrc::eval('return $window.caption'));
+ [cmd]perl.end[/cmd]
+ [/example]
+
+ [big]A shortcut for KVIrc::eval("/say...")[/big][br]
+ Since KVIrc::eval("/say...") is a common calling pattern then say
+ has been added to the KVIrc perl namespace. You can now call
+ [example]
+ KVIrc::say("Hi all!");
+ [/example]
+ and that will mimic the behaviour of
+ [example]
+ /[cmd]say[/cmd] Hi all!
+ [/example]
+ The complete syntax for KVIrc::say() is:[br]
+ &nbsp; &nbsp; [b]KVIrc::say(&lt;text&gt;[,&lt;windowid&gt;])[/b][br]
+ and the semantics are obvious (see also /[cmd]say[/cmd]).
+ [br]
+
+ [big]The perl script return values[/big][br]
+ The [cmd]perl.begin[/cmd] command propagates the perl code return
+ value to the KVIrc context (just like a setreturn() would do).[br]
+ In fact the perl snippet return value is the last "thing" that
+ the interpreter evaluates.[br]
+ In this way you can write perl aliases that return values
+ without doing any variable passing equilibrism.[br]
+ [br]
+
+ [big]Executing perl scripts from files[/big][br]
+ [example]
+ [cmd]alias[/cmd](perlexec)
+ {
+ %tmp = "perl.begin(\"\",$1,$2,$3,$4,$5)";
+ %tmp .= $file.read($0);
+ %tmp .= "perl.end";
+ eval %tmp;
+ }
+ perlexec "/home/pragma/myperlscript.pl" "param1" "param2" "param3"
+ [comment]# or even[/comment]
+ [cmd]echo[/cmd] $perlexec("/home/pragma/computeprimelargerthan.pl","10000")
+ [/example]
+ [br]
+
+ [big]Other tricks[/big][br]
+ An interesting feature of the persistent perl contexts is
+ that you can prepare a context for a later fast execution.[br]
+ The idea is to declare perl functions in a single perl code snippet
+ and to call the single functions when a fast execution is needed.[br]
+ For example you might parse the following snippet at KVIrc's startup:[br]
+ [example]
+ [cmd]perl.begin[/cmd]("persistent")
+ sub handler_for_event_1
+ {
+ do_complex_perl_stuff_here
+ }
+ sub handler_for_event_2
+ {
+ do_complex_perl_stuff_here
+ }
+ [cmd]perl.end[/cmd]
+ [/example]
+ and later simply call:
+ [example]
+ [cmd]perl.begin[/cmd]("persistent",param1,param2)
+ handler_for_event_1($_[0],$_[1])
+ [cmd]perl.end[/cmd]
+ [/example]
+ [br]
+
+ [big]Curiosity[/big][br]
+ The perl support in KVIrc is implemented as a master-slave module pair.
+ The perl.* module is the master while perlcore is the slave.
+ When the perl support isn't compiled in, the perl.* commands
+ print some warnings and exit gracefully while the perlcore module
+ refuses to be loaded. When perl support is compiled in but
+ for some reason the libperl.so can't be found or loaded
+ then perlcore fails the dynamic loading stage but perl.* still fails
+ gracefully with just some warning messages. This trick allows
+ the scripters to check for perl support with [fnc]perl.isAvailable[/fnc]
+ and to embed perl code snippets in KVS even if the support is missing.
+ The snippets will be just skipped.[br]
+ [br]
+ Happy perl hacking :)[br]
+*/
+
+/*
+ @doc: perl.begin
+ @type:
+ command
+ @title:
+ perl.begin
+ @keyterms:
+ Including perl code snippets in KVS
+ @short:
+ Starts a perl code snippet
+ @syntax:
+ perl.begin [-n] [-q] [(<perl_context>[,<arg0>[,<arg1>[...]]])]
+ <perl code>
+ perl.end
+ @switches:
+ !sw: -q | --quiet
+ Prevents the command from printing any warnings.
+ !sw: -n | --no-return
+ Prevents the perl script return value to be propagated
+ to the current context.
+ !sw: -f | --fail-on-error
+ Treat perl errors as KVS errors and abort execution of the
+ current script. Incompatible with -q
+ @description:
+ Indicates the beginning of a snipped of perl code.
+ The whole code part between perl.begin and perl.end
+ is executed in a perl interpreter.
+ If perl.end is omitted then it is implicitly assumed
+ that the code from perl.begin to the end of the command
+ buffer is perl.[br]
+ Each perl code execution is bound to a
+ perl context (that is in fact a particular instance
+ of a perl interpreter). If <perl_context> is not specified
+ or it is an empty string then temporary perl interpreter is created
+ and destroyed just after the code snippet has terminated execution.
+ If <perl_context> is specified then a perl interpreter
+ keyed to that context is used: if it was already existing
+ then it is reused otherwise it is created.
+ Any <perl_context> is persistent: it mantains the function
+ declarations and perl variable states until explicitly
+ destroyed with [cmd]perl.destroy[/cmd] (or the perlcore
+ module is forcibly unloaded).[br]
+ The <arg0>,<arg1>,... arguments, if present, are passed
+ to the perl code snippet in the @_ array (accessible as $_[0],$_[1]...).[br]
+ The return value of the perl code is propagated to the current
+ context (just like [cmd]setreturn[/cmd] was called on it) unless
+ the -n switch is used.[br]
+ The -q switch prevents from the command from printing any
+ warning.[br]
+ See the [doc:perl_and_kvs]perl scripting documentation[/doc]
+ for more information.
+ @examples:
+ [example]
+ perl.begin
+ KVIrc::eval("echo \"Hello World from perl!\"");
+ perl.end
+ [/example]
+ @seealso:
+*/
+
+/*
+ @doc: perl.end
+ @type:
+ command
+ @title:
+ perl.end
+ @short:
+ Ends a perl code snippet
+ @syntax:
+ perl.begin[(<perl_context>)]
+ <perl code>
+ perl.end
+ @description:
+ Ends a perl code snippet. See [cmd]perl.begin[/cmd].
+ @seealso:
+ [cmd]perl.begin[/cmd]
+*/
+
+static bool perl_kvs_cmd_begin(KviKvsModuleCommandCall * c)
+{
+ // This command is somewhat special in the fact that has a dedicated
+ // parsing routine in the KVS core parser.
+ // The parser sets the perl code as the first parameter of our call,
+ // the remaining params are the context name and the arguments
+
+ QString szCode,szContext;
+ KviKvsVariantList vList;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("code",KVS_PT_STRING,0,szCode)
+ KVSM_PARAMETER("context",KVS_PT_STRING,KVS_PF_OPTIONAL,szContext)
+ KVSM_PARAMETER("args",KVS_PT_VARIANTLIST,KVS_PF_OPTIONAL,vList)
+ KVSM_PARAMETERS_END(c)
+
+ KVS_CHECK_MODULE_STATE(m,c)
+
+#ifdef COMPILE_PERL_SUPPORT
+
+ KviPerlCoreCtrlCommand_execute ex;
+ ex.uSize = sizeof(KviPerlCoreCtrlCommand_execute);
+ ex.pKvsContext = c->context();
+ ex.szContext = szContext;
+ ex.szCode = szCode;
+ for(KviKvsVariant * v = vList.first();v;v = vList.next())
+ {
+ QString tmp;
+ v->asString(tmp);
+ ex.lArgs.append(tmp);
+ }
+ ex.bQuiet = c->switches()->find('q',"quiet");
+
+ if(!g_pPerlCoreModule->ctrl(KVI_PERLCORECTRLCOMMAND_EXECUTE,&ex))
+ {
+ if(!c->switches()->find('q',"quiet"))
+ c->warning(__tr2qs_ctx("The perlcore module failed to execute the code: something is wrong with the perl support","perl"));
+ return true;
+ }
+
+ if(!ex.lWarnings.isEmpty())
+ {
+ for(QStringList::Iterator it = ex.lWarnings.begin();it != ex.lWarnings.end();++it)
+ c->warning(*it);
+ }
+
+ if(!ex.bExitOk)
+ {
+ if(!c->switches()->find('q',"quiet"))
+ {
+
+ if(c->switches()->find('f',"fail-on-error"))
+ {
+ c->warning(__tr2qs_ctx("Perl execution error:","perl"));
+ c->warning(ex.szError);
+ return false;
+ } else {
+ c->warning(__tr2qs_ctx("Perl execution error:","perl"));
+ c->error(ex.szError);
+ }
+ }
+ }
+
+ if(!c->switches()->find('n',"no-return"))
+ c->context()->returnValue()->setString(ex.szRetVal);
+
+#endif //COMPILE_PERL_SUPPORT
+
+ return true;
+}
+
+/*
+ @doc: perl.destroy
+ @type:
+ command
+ @title:
+ perl.destroy
+ @short:
+ Destroys a perl execution context
+ @syntax:
+ perl.destroy [-q] <context_name:string>
+ @description:
+ Destroys the perl execution context <context_name>.
+ If the context is not existing then a warning is printed unless the
+ -q switch is used.[br]
+ The destruction will clear any state associated to the context
+ including the stored functions, classes and variable symbols.
+ You may want to destroy a context to re-initialize its state
+ or to simply clear it's memory when it's no longer needed.
+ @seealso:
+ [cmd]perl.begin[/cmd]
+*/
+
+static bool perl_kvs_cmd_destroy(KviKvsModuleCommandCall * c)
+{
+ QString szContext;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("context",KVS_PT_NONEMPTYSTRING,0,szContext)
+ KVSM_PARAMETERS_END(c)
+
+ KVS_CHECK_MODULE_STATE(m,c)
+
+#ifdef COMPILE_PERL_SUPPORT
+ KviPerlCoreCtrlCommand_destroy ex;
+ ex.uSize = sizeof(KviPerlCoreCtrlCommand_destroy);
+ ex.szContext = szContext;
+
+ if(!g_pPerlCoreModule->ctrl(KVI_PERLCORECTRLCOMMAND_DESTROY,&ex))
+ {
+ if(!c->switches()->find('q',"quiet"))
+ c->warning(__tr2qs_ctx("The perlcore module failed to execute the code: something is wrong with the perl support","perl"));
+ }
+#endif //COMPILE_PERL_SUPPORT
+
+ return true;
+}
+
+
+/*
+ @doc: perl.isAvailable
+ @type:
+ function
+ @title:
+ $perl.isAvailable
+ @short:
+ Check if perl scripting support is available
+ @syntax:
+ $perl.isAvailable
+ @description:
+ Returns 1 if the perl scripting support is available and 0 otherwise.
+*/
+
+static bool perl_kvs_fnc_isAvailable(KviKvsModuleFunctionCall * c)
+{
+#ifdef COMPILE_PERL_SUPPORT
+ g_pPerlCoreModule = g_pModuleManager->getModule("perlcore");
+ c->returnValue()->setBoolean(g_pPerlCoreModule ? true : false);
+#else //!COMPILE_PERL_SUPPORT
+ c->returnValue()->setBoolean(false);
+#endif //!COMPILE_PERL_SUPPORT
+ return true;
+}
+
+static bool perl_module_init(KviModule * m)
+{
+ // register the command anyway
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"begin",perl_kvs_cmd_begin);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"destroy",perl_kvs_cmd_destroy);
+
+ KVSM_REGISTER_FUNCTION(m,"isAvailable",perl_kvs_fnc_isAvailable);
+
+ // FIXME: perl.isSupported()
+#ifdef COMPILE_PERL_SUPPORT
+ g_pPerlCoreModule = g_pModuleManager->getModule("perlcore");
+#endif // COMPILE_PERL_SUPPORT
+ return true;
+}
+
+static bool perl_module_cleanup(KviModule *m)
+{
+#ifdef COMPILE_PERL_SUPPORT
+#endif // COMPILE_PERL_SUPPORT
+ return true;
+}
+
+KVIRC_MODULE(
+ "Perl", // module name
+ "1.0.0", // module version
+ "Copyright (C) 2004 Szymon Stefanek (pragma at kvirc dot net)", // author & (C)
+ "Perl scripting engine",
+ perl_module_init,
+ 0,
+ 0,
+ perl_module_cleanup
+)
diff --git a/src/modules/perlcore/KVIrc.xs b/src/modules/perlcore/KVIrc.xs
new file mode 100644
index 00000000..37b040cf
--- /dev/null
+++ b/src/modules/perlcore/KVIrc.xs
@@ -0,0 +1,139 @@
+MODULE = KVIrc PACKAGE = KVIrc
+
+void echo(text,colorset = 0,windowid = 0)
+ char * text
+ int colorset
+ char * windowid
+ CODE:
+ if(g_pCurrentKvsContext && text)
+ {
+ KviWindow * pWnd;
+ if(windowid)
+ {
+ pWnd = g_pApp->findWindow(windowid);
+ if(!pWnd)pWnd = g_pCurrentKvsContext->window();
+ } else {
+ pWnd = g_pCurrentKvsContext->window();
+ }
+ pWnd->outputNoFmt(colorset,QString::fromUtf8(text));
+ }
+
+void say(text,windowid = 0)
+ char * text
+ char * windowid
+ CODE:
+ if(g_pCurrentKvsContext && text)
+ {
+ KviWindow * pWnd;
+ if(windowid)
+ {
+ pWnd = g_pApp->findWindow(windowid);
+ if(!pWnd)pWnd = g_pCurrentKvsContext->window();
+ } else {
+ pWnd = g_pCurrentKvsContext->window();
+ }
+ QString tmp = QString::fromUtf8(text);
+ KviUserInput::parse(tmp,pWnd);
+ }
+
+void warning(text)
+ char * text
+ CODE:
+ if((!g_bExecuteQuiet) && g_pCurrentKvsContext)
+ g_pCurrentKvsContext->warning(text);
+
+void internalWarning(text)
+ char * text
+ CODE:
+ if(!g_bExecuteQuiet)
+ g_lWarningList.append(QString(text));
+
+
+char * getLocal(varname)
+ char * varname
+ CODE:
+ QString tmp;
+ KviStr hack;
+ if(g_pCurrentKvsContext)
+ {
+ KviKvsVariant * pVar = g_pCurrentKvsContext->localVariables()->find(varname);
+ if(pVar)
+ {
+ pVar->asString(tmp);
+ hack = tmp;
+ RETVAL = hack.ptr();
+ } else RETVAL = "";
+ }
+ OUTPUT:
+ RETVAL
+
+void setLocal(varname,value)
+ char * varname
+ char * value
+ CODE:
+ if(g_pCurrentKvsContext)
+ {
+ if(value && *value)
+ {
+ KviKvsVariant * pVar = g_pCurrentKvsContext->localVariables()->get(varname);
+ pVar->setString(value);
+ } else {
+ g_pCurrentKvsContext->localVariables()->unset(varname);
+ }
+ }
+
+char * getGlobal(varname)
+ char * varname
+ CODE:
+ QString tmp;
+ KviStr hack;
+ if(g_pCurrentKvsContext)
+ {
+ KviKvsVariant * pVar = g_pCurrentKvsContext->globalVariables()->find(varname);
+ if(pVar)
+ {
+ pVar->asString(tmp);
+ hack = tmp;
+ RETVAL = hack.ptr();
+ } else RETVAL = "";
+ }
+ OUTPUT:
+ RETVAL
+
+void setGlobal(varname,value)
+ char * varname
+ char * value
+ CODE:
+ if(g_pCurrentKvsContext)
+ {
+ if(value && *value)
+ {
+ KviKvsVariant * pVar = g_pCurrentKvsContext->globalVariables()->get(varname);
+ pVar->setString(value);
+ } else {
+ g_pCurrentKvsContext->localVariables()->unset(varname);
+ }
+ }
+
+
+char * eval(code)
+ char * code
+ CODE:
+ if(g_pCurrentKvsContext && code)
+ {
+ KviKvsVariant ret;
+ if(KviKvsScript::run(QString::fromUtf8(code),g_pCurrentKvsContext->window(),0,&ret))
+ {
+ QString tmp;
+ ret.asString(tmp);
+ g_szLastReturnValue = tmp;
+ } else {
+ g_szLastReturnValue = "";
+ }
+ RETVAL = g_szLastReturnValue.ptr();
+ } else {
+ RETVAL = "";
+ }
+ OUTPUT:
+ RETVAL
+
diff --git a/src/modules/perlcore/Makefile.am b/src/modules/perlcore/Makefile.am
new file mode 100644
index 00000000..a153262c
--- /dev/null
+++ b/src/modules/perlcore/Makefile.am
@@ -0,0 +1,23 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\" $(SS_PERL_CCFLAGS)
+
+pluglib_LTLIBRARIES = libkviperlcore.la
+
+libkviperlcore_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS) $(SS_PERL_LDFLAGS)
+
+libkviperlcore_la_SOURCES = libkviperlcore.cpp
+libkviperlcore_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+noinst_HEADERS = perlcoreinterface.h
+
+EXTRA_DIST = KVIrc.xs ppport.h xs.inc typemap
+
+%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
+
+xs:
+ xsubpp -noversioncheck -C++ -noprototypes KVIrc.xs > xs.inc
diff --git a/src/modules/perlcore/libkviperlcore.cpp b/src/modules/perlcore/libkviperlcore.cpp
new file mode 100644
index 00000000..a9196219
--- /dev/null
+++ b/src/modules/perlcore/libkviperlcore.cpp
@@ -0,0 +1,414 @@
+//=============================================================================
+//
+// File : libkviperlcore.cpp
+// Creation date : Tue Jul 13 13:03:31 2004 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_module.h"
+#include "kvi_settings.h"
+#include "kvi_locale.h"
+#include "kvi_out.h"
+#include "kvi_window.h"
+#include "kvi_app.h"
+
+#include "kvi_kvs_script.h"
+#include "kvi_kvs_variant.h"
+#include "kvi_userinput.h"
+#include "kvi_qcstring.h"
+#include "kvi_pointerhashtable.h"
+
+#ifdef DEBUG
+ #undef DEBUG
+#endif
+
+// I MUST say that the perl embedding process is somewhat ugly :(
+// First of all the man pages are somewhat unreadable even
+// for a non-novice perl user. The writer of each page assumed
+// that you have already read each other page...
+// Also browsing the pages with "man" is obviously out of mind
+// but this can be solved by looking up some html docs on the net.
+// Embedding multiple interpreters isn't that hard (after you
+// have read perlembed) but to start passing parameters
+// around you have to read at least perlembed, perlguts, perlxs,..
+// take a look at the perlinternals and have a good trip
+// around the web to find some examples for the functions
+// that aren't explained enough in the pages.
+// It gets even more weird when you attempt to include
+// some XS functions... (what the heck is boot_DynaLoader ?).
+
+// ... and I'm still convinced that I'm leaking memory with
+// the perl values, but well ...
+
+// anyway, once you struggled for a couple of days with all that
+// stuff then you start getting things done... and it rox :)
+
+#ifdef COMPILE_PERL_SUPPORT
+ #include <EXTERN.h>
+ #include <perl.h>
+ #include <XSUB.h>
+
+ #include "ppport.h"
+
+ #include "kvi_kvs_runtimecontext.h"
+
+ static KviKvsRunTimeContext * g_pCurrentKvsContext = 0;
+ static bool g_bExecuteQuiet = false;
+ static KviStr g_szLastReturnValue("");
+ static QStringList g_lWarningList;
+
+ #include "xs.inc"
+#endif // COMPILE_PERL_SUPPORT
+
+// perl redefines bool :///
+#ifdef bool
+ #undef bool
+#endif
+
+#ifdef COMPILE_PERL_SUPPORT
+
+#include "perlcoreinterface.h"
+
+// people ... are you mad ? ... what the heck is "my_perl" ?
+#define my_perl m_pInterpreter
+
+class KviPerlInterpreter
+{
+public:
+ KviPerlInterpreter(const QString &szContextName);
+ ~KviPerlInterpreter();
+protected:
+ QString m_szContextName;
+ PerlInterpreter * m_pInterpreter;
+public:
+ bool init(); // if this fails then well.. :D
+ void done();
+ bool execute(const QString &szCode,QStringList &args,QString &szRetVal,QString &szError,QStringList &lWarnings);
+ const QString & contextName(){ return m_szContextName; };
+protected:
+ QString svToQString(SV * sv);
+};
+
+KviPerlInterpreter::KviPerlInterpreter(const QString &szContextName)
+{
+ m_szContextName = szContextName;
+ m_pInterpreter = 0;
+}
+
+KviPerlInterpreter::~KviPerlInterpreter()
+{
+ done();
+}
+
+// this kinda sux :(
+// It SHOULD be mentioned somewhere that
+// this function is in DynaLoader.a in the perl
+// distribution and you MUST link it statically.
+extern "C" void boot_DynaLoader(pTHX_ CV* cv);
+
+extern "C" void xs_init(pTHX)
+{
+ char *file = __FILE__;
+ // boot up the DynaLoader
+ newXS("DynaLoader::boot_DynaLoader",boot_DynaLoader,file);
+ // now bootstrap the KVIrc module
+ // This stuff is simply cutted and pasted from xs.inc
+ // since I don't really know if it's safe to call
+ // something like
+ // CV * dummy;
+ // boot_KVIrc(aTHX,dummy);
+ // ...
+ newXS("KVIrc::echo", XS_KVIrc_echo, file);
+ newXS("KVIrc::say", XS_KVIrc_say, file);
+ newXS("KVIrc::warning", XS_KVIrc_warning, file);
+ newXS("KVIrc::getLocal", XS_KVIrc_getLocal, file);
+ newXS("KVIrc::setLocal", XS_KVIrc_setLocal, file);
+ newXS("KVIrc::getGlobal", XS_KVIrc_getGlobal, file);
+ newXS("KVIrc::setGlobal", XS_KVIrc_setGlobal, file);
+ newXS("KVIrc::eval", XS_KVIrc_eval, file);
+ newXS("KVIrc::internalWarning", XS_KVIrc_internalWarning, file);
+}
+
+bool KviPerlInterpreter::init()
+{
+ if(m_pInterpreter)done();
+ m_pInterpreter = perl_alloc();
+ if(!m_pInterpreter)return false;
+ PERL_SET_CONTEXT(m_pInterpreter);
+ PL_perl_destruct_level = 1;
+ perl_construct(m_pInterpreter);
+ char * daArgs[] = { "yo", "-e", "0", "-w" };
+ perl_parse(m_pInterpreter,xs_init,4,daArgs,NULL);
+ QString szInitCode;
+
+ // this part of the code seems to be unnecessary
+ // even if it is created by the perl make process...
+ // "our %EXPORT_TAGS = ('all' => [qw(echo)]);\n"
+ // "our @EXPORT_OK = (qw(echo));\n"
+ // "our @EXPORT = qw();\n"
+ // This is probably needed only if perl has to load
+ // the XS through XSLoader ?
+ // Maybe also the remaining part of the package
+ // declaration could be dropped as well...
+ // I just haven't tried :D
+
+ KviQString::sprintf(
+ szInitCode,
+ "{\n" \
+ "package KVIrc;\n" \
+ "require Exporter;\n" \
+ "our @ISA = qw(Exporter);\n" \
+ "1;\n" \
+ "}\n" \
+ "$g_szContext = \"%Q\";\n" \
+ "$g_bExecuteQuiet = 0;\n" \
+ "$SIG{__WARN__} = sub\n" \
+ "{\n" \
+ " my($p,$f,$l,$x);\n" \
+ " ($p,$f,$l) = caller;\n" \
+ " KVIrc::internalWarning(\"At line \".$l.\" of perl code: \");\n" \
+ " KVIrc::internalWarning(join(' ',@_));\n" \
+ "}\n",
+ &m_szContextName);
+
+ eval_pv(szInitCode.utf8().data(),false);
+ return true;
+}
+
+void KviPerlInterpreter::done()
+{
+ if(!m_pInterpreter)return;
+ PERL_SET_CONTEXT(m_pInterpreter);
+ PL_perl_destruct_level = 1;
+ perl_destruct(m_pInterpreter);
+ perl_free(m_pInterpreter);
+ m_pInterpreter = 0;
+}
+
+QString KviPerlInterpreter::svToQString(SV * sv)
+{
+ QString ret = "";
+ if(!sv)return ret;
+ STRLEN len;
+ char * ptr = SvPV(sv,len);
+ if(ptr)ret = ptr;
+ return ret;
+}
+
+bool KviPerlInterpreter::execute(
+ const QString &szCode,
+ QStringList &args,
+ QString &szRetVal,
+ QString &szError,
+ QStringList &lWarnings)
+{
+ if(!m_pInterpreter)
+ {
+ szError = __tr2qs_ctx("Internal error: perl interpreter not initialized","perlcore");
+ return false;
+ }
+
+ g_lWarningList.clear();
+
+ KviQCString szUtf8 = szCode.utf8();
+ PERL_SET_CONTEXT(m_pInterpreter);
+
+ // clear the _ array
+ AV * pArgs = get_av("_",1);
+ SV * pArg = av_shift(pArgs);
+ while(SvOK(pArg))
+ {
+ SvREFCNT_dec(pArg);
+ pArg = av_shift(pArgs);
+ }
+
+ if(args.count() > 0)
+ {
+ // set the args in the _ arry
+ av_unshift(pArgs,(I32)args.count());
+ int idx = 0;
+ for(QStringList::Iterator it = args.begin();it != args.end();++it)
+ {
+ QString tmp = *it;
+ const char * val = tmp.utf8().data();
+ if(val)
+ {
+ pArg = newSVpv(val,tmp.length());
+ if(!av_store(pArgs,idx,pArg))
+ SvREFCNT_dec(pArg);
+ }
+ idx++;
+ }
+ }
+
+ // call the code
+ SV * pRet = eval_pv(szUtf8.data(),false);
+
+ // clear the _ array again
+ pArgs = get_av("_",1);
+ pArg = av_shift(pArgs);
+ while(SvOK(pArg))
+ {
+ SvREFCNT_dec(pArg);
+ pArg = av_shift(pArgs);
+ }
+ av_undef(pArgs);
+
+ // get the ret value
+ if(pRet)
+ {
+ if(SvOK(pRet))
+ szRetVal = svToQString(pRet);
+ }
+
+ if(!g_lWarningList.isEmpty())
+ lWarnings = g_lWarningList;
+
+ // and the eventual error string
+ pRet = get_sv("@",false);
+ if(pRet)
+ {
+ if(SvOK(pRet))
+ {
+ szError = svToQString(pRet);
+ if(!szError.isEmpty())return false;
+ }
+ }
+
+ return true;
+}
+
+static KviPointerHashTable<QString,KviPerlInterpreter> * g_pInterpreters = 0;
+
+static KviPerlInterpreter * perlcore_get_interpreter(const QString &szContextName)
+{
+ KviPerlInterpreter * i = g_pInterpreters->find(szContextName);
+ if(i)return i;
+ i = new KviPerlInterpreter(szContextName);
+ if(!i->init())
+ {
+ delete i;
+ return 0;
+ }
+ g_pInterpreters->replace(szContextName,i);
+ return i;
+}
+
+static void perlcore_destroy_interpreter(const QString &szContextName)
+{
+ KviPerlInterpreter * i = g_pInterpreters->find(szContextName);
+ if(!i)return;
+ g_pInterpreters->remove(szContextName);
+ i->done();
+ delete i;
+}
+
+static void perlcore_destroy_all_interpreters()
+{
+ KviPointerHashTableIterator<QString,KviPerlInterpreter> it(*g_pInterpreters);
+
+ while(it.current())
+ {
+ KviPerlInterpreter * i = it.current();
+ i->done();
+ delete i;
+ ++it;
+ }
+ g_pInterpreters->clear();
+}
+
+#endif // COMPILE_PERL_SUPPORT
+
+static bool perlcore_module_ctrl(KviModule * m,const char * cmd,void * param)
+{
+#ifdef COMPILE_PERL_SUPPORT
+ if(kvi_strEqualCS(cmd,KVI_PERLCORECTRLCOMMAND_EXECUTE))
+ {
+ KviPerlCoreCtrlCommand_execute * ex = (KviPerlCoreCtrlCommand_execute *)param;
+ if(ex->uSize != sizeof(KviPerlCoreCtrlCommand_execute))return false;
+ g_pCurrentKvsContext = ex->pKvsContext;
+ g_bExecuteQuiet = ex->bQuiet;
+ if(ex->szContext.isEmpty())
+ {
+ KviPerlInterpreter * m = new KviPerlInterpreter("temporary");
+ if(!m->init())
+ {
+ delete m;
+ return false;
+ }
+ ex->bExitOk = m->execute(ex->szCode,ex->lArgs,ex->szRetVal,ex->szError,ex->lWarnings);
+ m->done();
+ delete m;
+ } else {
+ KviPerlInterpreter * m = perlcore_get_interpreter(ex->szContext);
+ ex->bExitOk = m->execute(ex->szCode,ex->lArgs,ex->szRetVal,ex->szError,ex->lWarnings);
+ }
+ return true;
+ }
+ if(kvi_strEqualCS(cmd,KVI_PERLCORECTRLCOMMAND_DESTROY))
+ {
+ KviPerlCoreCtrlCommand_destroy * de = (KviPerlCoreCtrlCommand_destroy *)param;
+ if(de->uSize != sizeof(KviPerlCoreCtrlCommand_destroy))return false;
+ perlcore_destroy_interpreter(de->szContext);
+ return true;
+ }
+#endif // COMPILE_PERL_SUPPORT
+ return false;
+}
+
+static bool perlcore_module_init(KviModule * m)
+{
+#ifdef COMPILE_PERL_SUPPORT
+ g_pInterpreters = new KviPointerHashTable<QString,KviPerlInterpreter>(17,false);
+ g_pInterpreters->setAutoDelete(false);
+ return true;
+#else // !COMPILE_PERL_SUPPORT
+ return false;
+#endif // !COMPILE_PERL_SUPPORT
+}
+
+static bool perlcore_module_cleanup(KviModule *m)
+{
+#ifdef COMPILE_PERL_SUPPORT
+ perlcore_destroy_all_interpreters();
+ delete g_pInterpreters;
+ g_pInterpreters = 0;
+#endif // COMPILE_PERL_SUPPORT
+ return true;
+}
+
+static bool perlcore_module_can_unload(KviModule *m)
+{
+#ifdef COMPILE_PERL_SUPPORT
+ return (g_pInterpreters->count() == 0);
+#endif // COMPILE_PERL_SUPPORT
+ return true;
+}
+
+KVIRC_MODULE(
+ "Perl", // module name
+ "1.0.0", // module version
+ "Copyright (C) 2004 Szymon Stefanek (pragma at kvirc dot net)", // author & (C)
+ "Perl scripting engine core",
+ perlcore_module_init,
+ perlcore_module_can_unload,
+ perlcore_module_ctrl,
+ perlcore_module_cleanup
+)
diff --git a/src/modules/perlcore/perlcoreinterface.h b/src/modules/perlcore/perlcoreinterface.h
new file mode 100644
index 00000000..a7ceb1fc
--- /dev/null
+++ b/src/modules/perlcore/perlcoreinterface.h
@@ -0,0 +1,59 @@
+#ifndef _PERLCOREINTERFACE_H_
+#define _PERLCOREINTERFACE_H_
+
+//=============================================================================
+//
+// File : perlcoreinterface.h
+// Creation date : Tue Jul 13 13:03:31 2004 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include "kvi_kvs_runtimecontext.h"
+
+#include <qstringlist.h>
+
+
+#define KVI_PERLCORECTRLCOMMAND_EXECUTE "execute"
+
+typedef struct _KviPerlCoreCtrlCommand_execute
+{
+ unsigned int uSize;
+ KviKvsRunTimeContext * pKvsContext;
+ QString szContext;
+ QString szCode;
+ bool bExitOk;
+ QString szRetVal;
+ QString szError;
+ QStringList lWarnings;
+ QStringList lArgs;
+ bool bQuiet;
+} KviPerlCoreCtrlCommand_execute;
+
+#define KVI_PERLCORECTRLCOMMAND_DESTROY "destroy"
+
+typedef struct _KviPerlCoreCtrlCommand_destroy
+{
+ unsigned int uSize;
+ QString szContext;
+} KviPerlCoreCtrlCommand_destroy;
+
+#endif // !_PERLCOREINTERFACE_H_
diff --git a/src/modules/perlcore/ppport.h b/src/modules/perlcore/ppport.h
new file mode 100644
index 00000000..2a802132
--- /dev/null
+++ b/src/modules/perlcore/ppport.h
@@ -0,0 +1,540 @@
+
+/* ppport.h -- Perl/Pollution/Portability Version 2.0002
+ *
+ * Automatically Created by Devel::PPPort on Tue Jul 13 13:16:39 2004
+ *
+ * Do NOT edit this file directly! -- Edit PPPort.pm instead.
+ *
+ * Version 2.x, Copyright (C) 2001, Paul Marquess.
+ * Version 1.x, Copyright (C) 1999, Kenneth Albanowski.
+ * This code may be used and distributed under the same license as any
+ * version of Perl.
+ *
+ * This version of ppport.h is designed to support operation with Perl
+ * installations back to 5.004, and has been tested up to 5.8.0.
+ *
+ * If this version of ppport.h is failing during the compilation of this
+ * module, please check if a newer version of Devel::PPPort is available
+ * on CPAN before sending a bug report.
+ *
+ * If you are using the latest version of Devel::PPPort and it is failing
+ * during compilation of this module, please send a report to perlbug@perl.com
+ *
+ * Include all following information:
+ *
+ * 1. The complete output from running "perl -V"
+ *
+ * 2. This file.
+ *
+ * 3. The name & version of the module you were trying to build.
+ *
+ * 4. A full log of the build that failed.
+ *
+ * 5. Any other information that you think could be relevant.
+ *
+ *
+ * For the latest version of this code, please retreive the Devel::PPPort
+ * module from CPAN.
+ *
+ */
+
+/*
+ * In order for a Perl extension module to be as portable as possible
+ * across differing versions of Perl itself, certain steps need to be taken.
+ * Including this header is the first major one, then using dTHR is all the
+ * appropriate places and using a PL_ prefix to refer to global Perl
+ * variables is the second.
+ *
+ */
+
+
+/* If you use one of a few functions that were not present in earlier
+ * versions of Perl, please add a define before the inclusion of ppport.h
+ * for a static include, or use the GLOBAL request in a single module to
+ * produce a global definition that can be referenced from the other
+ * modules.
+ *
+ * Function: Static define: Extern define:
+ * newCONSTSUB() NEED_newCONSTSUB NEED_newCONSTSUB_GLOBAL
+ *
+ */
+
+
+/* To verify whether ppport.h is needed for your module, and whether any
+ * special defines should be used, ppport.h can be run through Perl to check
+ * your source code. Simply say:
+ *
+ * perl -x ppport.h *.c *.h *.xs foo/bar*.c [etc]
+ *
+ * The result will be a list of patches suggesting changes that should at
+ * least be acceptable, if not necessarily the most efficient solution, or a
+ * fix for all possible problems. It won't catch where dTHR is needed, and
+ * doesn't attempt to account for global macro or function definitions,
+ * nested includes, typemaps, etc.
+ *
+ * In order to test for the need of dTHR, please try your module under a
+ * recent version of Perl that has threading compiled-in.
+ *
+ */
+
+
+/*
+#!/usr/bin/perl
+@ARGV = ("*.xs") if !@ARGV;
+%badmacros = %funcs = %macros = (); $replace = 0;
+foreach (<DATA>) {
+ $funcs{$1} = 1 if /Provide:\s+(\S+)/;
+ $macros{$1} = 1 if /^#\s*define\s+([a-zA-Z0-9_]+)/;
+ $replace = $1 if /Replace:\s+(\d+)/;
+ $badmacros{$2}=$1 if $replace and /^#\s*define\s+([a-zA-Z0-9_]+).*?\s+([a-zA-Z0-9_]+)/;
+ $badmacros{$1}=$2 if /Replace (\S+) with (\S+)/;
+}
+foreach $filename (map(glob($_),@ARGV)) {
+ unless (open(IN, "<$filename")) {
+ warn "Unable to read from $file: $!\n";
+ next;
+ }
+ print "Scanning $filename...\n";
+ $c = ""; while (<IN>) { $c .= $_; } close(IN);
+ $need_include = 0; %add_func = (); $changes = 0;
+ $has_include = ($c =~ /#.*include.*ppport/m);
+
+ foreach $func (keys %funcs) {
+ if ($c =~ /#.*define.*\bNEED_$func(_GLOBAL)?\b/m) {
+ if ($c !~ /\b$func\b/m) {
+ print "If $func isn't needed, you don't need to request it.\n" if
+ $changes += ($c =~ s/^.*#.*define.*\bNEED_$func\b.*\n//m);
+ } else {
+ print "Uses $func\n";
+ $need_include = 1;
+ }
+ } else {
+ if ($c =~ /\b$func\b/m) {
+ $add_func{$func} =1 ;
+ print "Uses $func\n";
+ $need_include = 1;
+ }
+ }
+ }
+
+ if (not $need_include) {
+ foreach $macro (keys %macros) {
+ if ($c =~ /\b$macro\b/m) {
+ print "Uses $macro\n";
+ $need_include = 1;
+ }
+ }
+ }
+
+ foreach $badmacro (keys %badmacros) {
+ if ($c =~ /\b$badmacro\b/m) {
+ $changes += ($c =~ s/\b$badmacro\b/$badmacros{$badmacro}/gm);
+ print "Uses $badmacros{$badmacro} (instead of $badmacro)\n";
+ $need_include = 1;
+ }
+ }
+
+ if (scalar(keys %add_func) or $need_include != $has_include) {
+ if (!$has_include) {
+ $inc = join('',map("#define NEED_$_\n", sort keys %add_func)).
+ "#include \"ppport.h\"\n";
+ $c = "$inc$c" unless $c =~ s/#.*include.*XSUB.*\n/$&$inc/m;
+ } elsif (keys %add_func) {
+ $inc = join('',map("#define NEED_$_\n", sort keys %add_func));
+ $c = "$inc$c" unless $c =~ s/^.*#.*include.*ppport.*$/$inc$&/m;
+ }
+ if (!$need_include) {
+ print "Doesn't seem to need ppport.h.\n";
+ $c =~ s/^.*#.*include.*ppport.*\n//m;
+ }
+ $changes++;
+ }
+
+ if ($changes) {
+ open(OUT,">/tmp/ppport.h.$$");
+ print OUT $c;
+ close(OUT);
+ open(DIFF, "diff -u $filename /tmp/ppport.h.$$|");
+ while (<DIFF>) { s!/tmp/ppport\.h\.$$!$filename.patched!; print STDOUT; }
+ close(DIFF);
+ unlink("/tmp/ppport.h.$$");
+ } else {
+ print "Looks OK\n";
+ }
+}
+__DATA__
+*/
+
+#ifndef _P_P_PORTABILITY_H_
+#define _P_P_PORTABILITY_H_
+
+#ifndef PERL_REVISION
+# ifndef __PATCHLEVEL_H_INCLUDED__
+# include "patchlevel.h"
+# endif
+# ifndef PERL_REVISION
+# define PERL_REVISION (5)
+ /* Replace: 1 */
+# define PERL_VERSION PATCHLEVEL
+# define PERL_SUBVERSION SUBVERSION
+ /* Replace PERL_PATCHLEVEL with PERL_VERSION */
+ /* Replace: 0 */
+# endif
+#endif
+
+#define PERL_BCDVERSION ((PERL_REVISION * 0x1000000L) + (PERL_VERSION * 0x1000L) + PERL_SUBVERSION)
+
+/* It is very unlikely that anyone will try to use this with Perl 6
+ (or greater), but who knows.
+ */
+#if PERL_REVISION != 5
+# error ppport.h only works with Perl version 5
+#endif /* PERL_REVISION != 5 */
+
+#ifndef ERRSV
+# define ERRSV perl_get_sv("@",FALSE)
+#endif
+
+#if (PERL_VERSION < 4) || ((PERL_VERSION == 4) && (PERL_SUBVERSION <= 5))
+/* Replace: 1 */
+# define PL_Sv Sv
+# define PL_compiling compiling
+# define PL_copline copline
+# define PL_curcop curcop
+# define PL_curstash curstash
+# define PL_defgv defgv
+# define PL_dirty dirty
+# define PL_dowarn dowarn
+# define PL_hints hints
+# define PL_na na
+# define PL_perldb perldb
+# define PL_rsfp_filters rsfp_filters
+# define PL_rsfpv rsfp
+# define PL_stdingv stdingv
+# define PL_sv_no sv_no
+# define PL_sv_undef sv_undef
+# define PL_sv_yes sv_yes
+/* Replace: 0 */
+#endif
+
+#ifdef HASATTRIBUTE
+# if defined(__GNUC__) && defined(__cplusplus)
+# define PERL_UNUSED_DECL
+# else
+# define PERL_UNUSED_DECL __attribute__((unused))
+# endif
+#else
+# define PERL_UNUSED_DECL
+#endif
+
+#ifndef dNOOP
+# define NOOP (void)0
+# define dNOOP extern int Perl___notused PERL_UNUSED_DECL
+#endif
+
+#ifndef dTHR
+# define dTHR dNOOP
+#endif
+
+#ifndef dTHX
+# define dTHX dNOOP
+# define dTHXa(x) dNOOP
+# define dTHXoa(x) dNOOP
+#endif
+
+#ifndef pTHX
+# define pTHX void
+# define pTHX_
+# define aTHX
+# define aTHX_
+#endif
+
+#ifndef UVSIZE
+# define UVSIZE IVSIZE
+#endif
+
+#ifndef NVTYPE
+# if defined(USE_LONG_DOUBLE) && defined(HAS_LONG_DOUBLE)
+# define NVTYPE long double
+# else
+# define NVTYPE double
+# endif
+typedef NVTYPE NV;
+#endif
+
+#ifndef INT2PTR
+
+#if (IVSIZE == PTRSIZE) && (UVSIZE == PTRSIZE)
+# define PTRV UV
+# define INT2PTR(any,d) (any)(d)
+#else
+# if PTRSIZE == LONGSIZE
+# define PTRV unsigned long
+# else
+# define PTRV unsigned
+# endif
+# define INT2PTR(any,d) (any)(PTRV)(d)
+#endif
+#define NUM2PTR(any,d) (any)(PTRV)(d)
+#define PTR2IV(p) INT2PTR(IV,p)
+#define PTR2UV(p) INT2PTR(UV,p)
+#define PTR2NV(p) NUM2PTR(NV,p)
+#if PTRSIZE == LONGSIZE
+# define PTR2ul(p) (unsigned long)(p)
+#else
+# define PTR2ul(p) INT2PTR(unsigned long,p)
+#endif
+
+#endif /* !INT2PTR */
+
+#ifndef boolSV
+# define boolSV(b) ((b) ? &PL_sv_yes : &PL_sv_no)
+#endif
+
+#ifndef gv_stashpvn
+# define gv_stashpvn(str,len,flags) gv_stashpv(str,flags)
+#endif
+
+#ifndef newSVpvn
+# define newSVpvn(data,len) ((len) ? newSVpv ((data), (len)) : newSVpv ("", 0))
+#endif
+
+#ifndef newRV_inc
+/* Replace: 1 */
+# define newRV_inc(sv) newRV(sv)
+/* Replace: 0 */
+#endif
+
+/* DEFSV appears first in 5.004_56 */
+#ifndef DEFSV
+# define DEFSV GvSV(PL_defgv)
+#endif
+
+#ifndef SAVE_DEFSV
+# define SAVE_DEFSV SAVESPTR(GvSV(PL_defgv))
+#endif
+
+#ifndef newRV_noinc
+# ifdef __GNUC__
+# define newRV_noinc(sv) \
+ ({ \
+ SV *nsv = (SV*)newRV(sv); \
+ SvREFCNT_dec(sv); \
+ nsv; \
+ })
+# else
+# if defined(USE_THREADS)
+static SV * newRV_noinc (SV * sv)
+{
+ SV *nsv = (SV*)newRV(sv);
+ SvREFCNT_dec(sv);
+ return nsv;
+}
+# else
+# define newRV_noinc(sv) \
+ (PL_Sv=(SV*)newRV(sv), SvREFCNT_dec(sv), (SV*)PL_Sv)
+# endif
+# endif
+#endif
+
+/* Provide: newCONSTSUB */
+
+/* newCONSTSUB from IO.xs is in the core starting with 5.004_63 */
+#if (PERL_VERSION < 4) || ((PERL_VERSION == 4) && (PERL_SUBVERSION < 63))
+
+#if defined(NEED_newCONSTSUB)
+static
+#else
+extern void newCONSTSUB(HV * stash, char * name, SV *sv);
+#endif
+
+#if defined(NEED_newCONSTSUB) || defined(NEED_newCONSTSUB_GLOBAL)
+void
+newCONSTSUB(stash,name,sv)
+HV *stash;
+char *name;
+SV *sv;
+{
+ U32 oldhints = PL_hints;
+ HV *old_cop_stash = PL_curcop->cop_stash;
+ HV *old_curstash = PL_curstash;
+ line_t oldline = PL_curcop->cop_line;
+ PL_curcop->cop_line = PL_copline;
+
+ PL_hints &= ~HINT_BLOCK_SCOPE;
+ if (stash)
+ PL_curstash = PL_curcop->cop_stash = stash;
+
+ newSUB(
+
+#if (PERL_VERSION < 3) || ((PERL_VERSION == 3) && (PERL_SUBVERSION < 22))
+ /* before 5.003_22 */
+ start_subparse(),
+#else
+# if (PERL_VERSION == 3) && (PERL_SUBVERSION == 22)
+ /* 5.003_22 */
+ start_subparse(0),
+# else
+ /* 5.003_23 onwards */
+ start_subparse(FALSE, 0),
+# endif
+#endif
+
+ newSVOP(OP_CONST, 0, newSVpv(name,0)),
+ newSVOP(OP_CONST, 0, &PL_sv_no), /* SvPV(&PL_sv_no) == "" -- GMB */
+ newSTATEOP(0, Nullch, newSVOP(OP_CONST, 0, sv))
+ );
+
+ PL_hints = oldhints;
+ PL_curcop->cop_stash = old_cop_stash;
+ PL_curstash = old_curstash;
+ PL_curcop->cop_line = oldline;
+}
+#endif
+
+#endif /* newCONSTSUB */
+
+#ifndef START_MY_CXT
+
+/*
+ * Boilerplate macros for initializing and accessing interpreter-local
+ * data from C. All statics in extensions should be reworked to use
+ * this, if you want to make the extension thread-safe. See ext/re/re.xs
+ * for an example of the use of these macros.
+ *
+ * Code that uses these macros is responsible for the following:
+ * 1. #define MY_CXT_KEY to a unique string, e.g. "DynaLoader_guts"
+ * 2. Declare a typedef named my_cxt_t that is a structure that contains
+ * all the data that needs to be interpreter-local.
+ * 3. Use the START_MY_CXT macro after the declaration of my_cxt_t.
+ * 4. Use the MY_CXT_INIT macro such that it is called exactly once
+ * (typically put in the BOOT: section).
+ * 5. Use the members of the my_cxt_t structure everywhere as
+ * MY_CXT.member.
+ * 6. Use the dMY_CXT macro (a declaration) in all the functions that
+ * access MY_CXT.
+ */
+
+#if defined(MULTIPLICITY) || defined(PERL_OBJECT) || \
+ defined(PERL_CAPI) || defined(PERL_IMPLICIT_CONTEXT)
+
+/* This must appear in all extensions that define a my_cxt_t structure,
+ * right after the definition (i.e. at file scope). The non-threads
+ * case below uses it to declare the data as static. */
+#define START_MY_CXT
+
+#if (PERL_VERSION < 4 || (PERL_VERSION == 4 && PERL_SUBVERSION < 68 ))
+/* Fetches the SV that keeps the per-interpreter data. */
+#define dMY_CXT_SV \
+ SV *my_cxt_sv = perl_get_sv(MY_CXT_KEY, FALSE)
+#else /* >= perl5.004_68 */
+#define dMY_CXT_SV \
+ SV *my_cxt_sv = *hv_fetch(PL_modglobal, MY_CXT_KEY, \
+ sizeof(MY_CXT_KEY)-1, TRUE)
+#endif /* < perl5.004_68 */
+
+/* This declaration should be used within all functions that use the
+ * interpreter-local data. */
+#define dMY_CXT \
+ dMY_CXT_SV; \
+ my_cxt_t *my_cxtp = INT2PTR(my_cxt_t*,SvUV(my_cxt_sv))
+
+/* Creates and zeroes the per-interpreter data.
+ * (We allocate my_cxtp in a Perl SV so that it will be released when
+ * the interpreter goes away.) */
+#define MY_CXT_INIT \
+ dMY_CXT_SV; \
+ /* newSV() allocates one more than needed */ \
+ my_cxt_t *my_cxtp = (my_cxt_t*)SvPVX(newSV(sizeof(my_cxt_t)-1));\
+ Zero(my_cxtp, 1, my_cxt_t); \
+ sv_setuv(my_cxt_sv, PTR2UV(my_cxtp))
+
+/* This macro must be used to access members of the my_cxt_t structure.
+ * e.g. MYCXT.some_data */
+#define MY_CXT (*my_cxtp)
+
+/* Judicious use of these macros can reduce the number of times dMY_CXT
+ * is used. Use is similar to pTHX, aTHX etc. */
+#define pMY_CXT my_cxt_t *my_cxtp
+#define pMY_CXT_ pMY_CXT,
+#define _pMY_CXT ,pMY_CXT
+#define aMY_CXT my_cxtp
+#define aMY_CXT_ aMY_CXT,
+#define _aMY_CXT ,aMY_CXT
+
+#else /* single interpreter */
+
+
+#define START_MY_CXT static my_cxt_t my_cxt;
+#define dMY_CXT_SV dNOOP
+#define dMY_CXT dNOOP
+#define MY_CXT_INIT NOOP
+#define MY_CXT my_cxt
+
+#define pMY_CXT void
+#define pMY_CXT_
+#define _pMY_CXT
+#define aMY_CXT
+#define aMY_CXT_
+#define _aMY_CXT
+
+#endif
+
+#endif /* START_MY_CXT */
+
+#ifndef IVdf
+# if IVSIZE == LONGSIZE
+# define IVdf "ld"
+# define UVuf "lu"
+# define UVof "lo"
+# define UVxf "lx"
+# define UVXf "lX"
+# else
+# if IVSIZE == INTSIZE
+# define IVdf "d"
+# define UVuf "u"
+# define UVof "o"
+# define UVxf "x"
+# define UVXf "X"
+# endif
+# endif
+#endif
+
+#ifndef NVef
+# if defined(USE_LONG_DOUBLE) && defined(HAS_LONG_DOUBLE) && \
+ defined(PERL_PRIfldbl) /* Not very likely, but let's try anyway. */
+# define NVef PERL_PRIeldbl
+# define NVff PERL_PRIfldbl
+# define NVgf PERL_PRIgldbl
+# else
+# define NVef "e"
+# define NVff "f"
+# define NVgf "g"
+# endif
+#endif
+
+#ifndef AvFILLp /* Older perls (<=5.003) lack AvFILLp */
+# define AvFILLp AvFILL
+#endif
+
+#ifdef SvPVbyte
+# if PERL_REVISION == 5 && PERL_VERSION < 7
+ /* SvPVbyte does not work in perl-5.6.1, borrowed version for 5.7.3 */
+# undef SvPVbyte
+# define SvPVbyte(sv, lp) \
+ ((SvFLAGS(sv) & (SVf_POK|SVf_UTF8)) == (SVf_POK) \
+ ? ((lp = SvCUR(sv)), SvPVX(sv)) : my_sv_2pvbyte(aTHX_ sv, &lp))
+ static char *
+ my_sv_2pvbyte(pTHX_ register SV *sv, STRLEN *lp)
+ {
+ sv_utf8_downgrade(sv,0);
+ return SvPV(sv,*lp);
+ }
+# endif
+#else
+# define SvPVbyte SvPV
+#endif
+
+#endif /* _P_P_PORTABILITY_H_ */
+
+/* End of File ppport.h */
diff --git a/src/modules/perlcore/typemap b/src/modules/perlcore/typemap
new file mode 100644
index 00000000..1124eb64
--- /dev/null
+++ b/src/modules/perlcore/typemap
@@ -0,0 +1,313 @@
+# basic C types
+int T_IV
+unsigned T_UV
+unsigned int T_UV
+long T_IV
+unsigned long T_UV
+short T_IV
+unsigned short T_UV
+char T_CHAR
+unsigned char T_U_CHAR
+char * T_PV
+unsigned char * T_PV
+const char * T_PV
+caddr_t T_PV
+wchar_t * T_PV
+wchar_t T_IV
+bool_t T_IV
+size_t T_UV
+ssize_t T_IV
+time_t T_NV
+unsigned long * T_OPAQUEPTR
+char ** T_PACKEDARRAY
+void * T_PTR
+Time_t * T_PV
+SV * T_SV
+SVREF T_SVREF
+AV * T_AVREF
+HV * T_HVREF
+CV * T_CVREF
+
+IV T_IV
+UV T_UV
+NV T_NV
+I32 T_IV
+I16 T_IV
+I8 T_IV
+STRLEN T_UV
+U32 T_U_LONG
+U16 T_U_SHORT
+U8 T_UV
+Result T_U_CHAR
+Boolean T_BOOL
+float T_FLOAT
+double T_DOUBLE
+SysRet T_SYSRET
+SysRetLong T_SYSRET
+FILE * T_STDIO
+PerlIO * T_INOUT
+FileHandle T_PTROBJ
+InputStream T_IN
+InOutStream T_INOUT
+OutputStream T_OUT
+bool T_BOOL
+
+#############################################################################
+INPUT
+T_SV
+ $var = $arg
+T_SVREF
+ if (SvROK($arg))
+ $var = (SV*)SvRV($arg);
+ else
+ Perl_croak(aTHX_ \"$var is not a reference\")
+T_AVREF
+ if (SvROK($arg) && SvTYPE(SvRV($arg))==SVt_PVAV)
+ $var = (AV*)SvRV($arg);
+ else
+ Perl_croak(aTHX_ \"$var is not an array reference\")
+T_HVREF
+ if (SvROK($arg) && SvTYPE(SvRV($arg))==SVt_PVHV)
+ $var = (HV*)SvRV($arg);
+ else
+ Perl_croak(aTHX_ \"$var is not a hash reference\")
+T_CVREF
+ if (SvROK($arg) && SvTYPE(SvRV($arg))==SVt_PVCV)
+ $var = (CV*)SvRV($arg);
+ else
+ Perl_croak(aTHX_ \"$var is not a code reference\")
+T_SYSRET
+ $var NOT IMPLEMENTED
+T_UV
+ $var = ($type)SvUV($arg)
+T_IV
+ $var = ($type)SvIV($arg)
+T_INT
+ $var = (int)SvIV($arg)
+T_ENUM
+ $var = ($type)SvIV($arg)
+T_BOOL
+ $var = (bool)SvTRUE($arg)
+T_U_INT
+ $var = (unsigned int)SvUV($arg)
+T_SHORT
+ $var = (short)SvIV($arg)
+T_U_SHORT
+ $var = (unsigned short)SvUV($arg)
+T_LONG
+ $var = (long)SvIV($arg)
+T_U_LONG
+ $var = (unsigned long)SvUV($arg)
+T_CHAR
+ $var = (char)*SvPV_nolen($arg)
+T_U_CHAR
+ $var = (unsigned char)SvUV($arg)
+T_FLOAT
+ $var = (float)SvNV($arg)
+T_NV
+ $var = ($type)SvNV($arg)
+T_DOUBLE
+ $var = (double)SvNV($arg)
+T_PV
+ $var = ($type)SvPV_nolen($arg)
+T_PTR
+ $var = INT2PTR($type,SvIV($arg))
+T_PTRREF
+ if (SvROK($arg)) {
+ IV tmp = SvIV((SV*)SvRV($arg));
+ $var = INT2PTR($type,tmp);
+ }
+ else
+ Perl_croak(aTHX_ \"$var is not a reference\")
+T_REF_IV_REF
+ if (sv_isa($arg, \"${ntype}\")) {
+ IV tmp = SvIV((SV*)SvRV($arg));
+ $var = *INT2PTR($type *, tmp);
+ }
+ else
+ Perl_croak(aTHX_ \"$var is not of type ${ntype}\")
+T_REF_IV_PTR
+ if (sv_isa($arg, \"${ntype}\")) {
+ IV tmp = SvIV((SV*)SvRV($arg));
+ $var = INT2PTR($type, tmp);
+ }
+ else
+ Perl_croak(aTHX_ \"$var is not of type ${ntype}\")
+T_PTROBJ
+ if (sv_derived_from($arg, \"${ntype}\")) {
+ IV tmp = SvIV((SV*)SvRV($arg));
+ $var = INT2PTR($type,tmp);
+ }
+ else
+ Perl_croak(aTHX_ \"$var is not of type ${ntype}\")
+T_PTRDESC
+ if (sv_isa($arg, \"${ntype}\")) {
+ IV tmp = SvIV((SV*)SvRV($arg));
+ ${type}_desc = (\U${type}_DESC\E*) tmp;
+ $var = ${type}_desc->ptr;
+ }
+ else
+ Perl_croak(aTHX_ \"$var is not of type ${ntype}\")
+T_REFREF
+ if (SvROK($arg)) {
+ IV tmp = SvIV((SV*)SvRV($arg));
+ $var = *INT2PTR($type,tmp);
+ }
+ else
+ Perl_croak(aTHX_ \"$var is not a reference\")
+T_REFOBJ
+ if (sv_isa($arg, \"${ntype}\")) {
+ IV tmp = SvIV((SV*)SvRV($arg));
+ $var = *INT2PTR($type,tmp);
+ }
+ else
+ Perl_croak(aTHX_ \"$var is not of type ${ntype}\")
+T_OPAQUE
+ $var = *($type *)SvPV_nolen($arg)
+T_OPAQUEPTR
+ $var = ($type)SvPV_nolen($arg)
+T_PACKED
+ $var = XS_unpack_$ntype($arg)
+T_PACKEDARRAY
+ $var = XS_unpack_$ntype($arg)
+T_CALLBACK
+ $var = make_perl_cb_$type($arg)
+T_ARRAY
+ U32 ix_$var = $argoff;
+ $var = $ntype(items -= $argoff);
+ while (items--) {
+ DO_ARRAY_ELEM;
+ ix_$var++;
+ }
+ /* this is the number of elements in the array */
+ ix_$var -= $argoff
+T_STDIO
+ $var = PerlIO_findFILE(IoIFP(sv_2io($arg)))
+T_IN
+ $var = IoIFP(sv_2io($arg))
+T_INOUT
+ $var = IoIFP(sv_2io($arg))
+T_OUT
+ $var = IoOFP(sv_2io($arg))
+#############################################################################
+OUTPUT
+T_SV
+ $arg = $var;
+T_SVREF
+ $arg = newRV((SV*)$var);
+T_AVREF
+ $arg = newRV((SV*)$var);
+T_HVREF
+ $arg = newRV((SV*)$var);
+T_CVREF
+ $arg = newRV((SV*)$var);
+T_IV
+ sv_setiv($arg, (IV)$var);
+T_UV
+ sv_setuv($arg, (UV)$var);
+T_INT
+ sv_setiv($arg, (IV)$var);
+T_SYSRET
+ if ($var != -1) {
+ if ($var == 0)
+ sv_setpvn($arg, "0 but true", 10);
+ else
+ sv_setiv($arg, (IV)$var);
+ }
+T_ENUM
+ sv_setiv($arg, (IV)$var);
+T_BOOL
+ $arg = boolSV($var);
+T_U_INT
+ sv_setuv($arg, (UV)$var);
+T_SHORT
+ sv_setiv($arg, (IV)$var);
+T_U_SHORT
+ sv_setuv($arg, (UV)$var);
+T_LONG
+ sv_setiv($arg, (IV)$var);
+T_U_LONG
+ sv_setuv($arg, (UV)$var);
+T_CHAR
+ sv_setpvn($arg, (char *)&$var, 1);
+T_U_CHAR
+ sv_setuv($arg, (UV)$var);
+T_FLOAT
+ sv_setnv($arg, (double)$var);
+T_NV
+ sv_setnv($arg, (NV)$var);
+T_DOUBLE
+ sv_setnv($arg, (double)$var);
+T_PV
+ sv_setpv((SV*)$arg, $var);
+T_PTR
+ sv_setiv($arg, PTR2IV($var));
+T_PTRREF
+ sv_setref_pv($arg, Nullch, (void*)$var);
+T_REF_IV_REF
+ sv_setref_pv($arg, \"${ntype}\", (void*)new $ntype($var));
+T_REF_IV_PTR
+ sv_setref_pv($arg, \"${ntype}\", (void*)$var);
+T_PTROBJ
+ sv_setref_pv($arg, \"${ntype}\", (void*)$var);
+T_PTRDESC
+ sv_setref_pv($arg, \"${ntype}\", (void*)new\U${type}_DESC\E($var));
+T_REFREF
+ NOT_IMPLEMENTED
+T_REFOBJ
+ NOT IMPLEMENTED
+T_OPAQUE
+ sv_setpvn($arg, (char *)&$var, sizeof($var));
+T_OPAQUEPTR
+ sv_setpvn($arg, (char *)$var, sizeof(*$var));
+T_PACKED
+ XS_pack_$ntype($arg, $var);
+T_PACKEDARRAY
+ XS_pack_$ntype($arg, $var, count_$ntype);
+T_DATAUNIT
+ sv_setpvn($arg, $var.chp(), $var.size());
+T_CALLBACK
+ sv_setpvn($arg, $var.context.value().chp(),
+ $var.context.value().size());
+T_ARRAY
+ {
+ U32 ix_$var;
+ EXTEND(SP,size_$var);
+ for (ix_$var = 0; ix_$var < size_$var; ix_$var++) {
+ ST(ix_$var) = sv_newmortal();
+ DO_ARRAY_ELEM
+ }
+ }
+T_STDIO
+ {
+ GV *gv = newGVgen("$Package");
+ PerlIO *fp = PerlIO_importFILE($var,0);
+ if ( fp && do_open(gv, "+<&", 3, FALSE, 0, 0, fp) )
+ sv_setsv($arg, sv_bless(newRV((SV*)gv), gv_stashpv("$Package",1)));
+ else
+ $arg = &PL_sv_undef;
+ }
+T_IN
+ {
+ GV *gv = newGVgen("$Package");
+ if ( do_open(gv, "<&", 2, FALSE, 0, 0, $var) )
+ sv_setsv($arg, sv_bless(newRV((SV*)gv), gv_stashpv("$Package",1)));
+ else
+ $arg = &PL_sv_undef;
+ }
+T_INOUT
+ {
+ GV *gv = newGVgen("$Package");
+ if ( do_open(gv, "+<&", 3, FALSE, 0, 0, $var) )
+ sv_setsv($arg, sv_bless(newRV((SV*)gv), gv_stashpv("$Package",1)));
+ else
+ $arg = &PL_sv_undef;
+ }
+T_OUT
+ {
+ GV *gv = newGVgen("$Package");
+ if ( do_open(gv, "+>&", 3, FALSE, 0, 0, $var) )
+ sv_setsv($arg, sv_bless(newRV((SV*)gv), gv_stashpv("$Package",1)));
+ else
+ $arg = &PL_sv_undef;
+ }
diff --git a/src/modules/perlcore/xs.inc b/src/modules/perlcore/xs.inc
new file mode 100644
index 00000000..5c31cb19
--- /dev/null
+++ b/src/modules/perlcore/xs.inc
@@ -0,0 +1,277 @@
+/*
+ * This file was generated automatically by xsubpp version 1.9508 from the
+ * contents of KVIrc.xs. Do not edit this file, edit KVIrc.xs instead.
+ *
+ * ANY CHANGES MADE HERE WILL BE LOST!
+ *
+ */
+
+#line 1 "KVIrc.xs"
+#line 11 "KVIrc.c"
+XS(XS_KVIrc_echo); /* prototype to pass -Wmissing-prototypes */
+XS(XS_KVIrc_echo)
+{
+ dXSARGS;
+ if (items < 1 || items > 3)
+ Perl_croak(aTHX_ "Usage: KVIrc::echo(text, colorset = 0, windowid = 0)");
+ {
+ char * text = (char *)SvPV_nolen(ST(0));
+ int colorset;
+ char * windowid;
+
+ if (items < 2)
+ colorset = 0;
+ else {
+ colorset = (int)SvIV(ST(1));
+ }
+
+ if (items < 3)
+ windowid = 0;
+ else {
+ windowid = (char *)SvPV_nolen(ST(2));
+ }
+#line 8 "KVIrc.xs"
+ if(g_pCurrentKvsContext && text)
+ {
+ KviWindow * pWnd;
+ if(windowid)
+ {
+ pWnd = g_pApp->findWindow(windowid);
+ if(!pWnd)pWnd = g_pCurrentKvsContext->window();
+ } else {
+ pWnd = g_pCurrentKvsContext->window();
+ }
+ pWnd->outputNoFmt(colorset,QString::fromUtf8(text));
+ }
+#line 47 "KVIrc.c"
+ }
+ XSRETURN_EMPTY;
+}
+
+XS(XS_KVIrc_say); /* prototype to pass -Wmissing-prototypes */
+XS(XS_KVIrc_say)
+{
+ dXSARGS;
+ if (items < 1 || items > 2)
+ Perl_croak(aTHX_ "Usage: KVIrc::say(text, windowid = 0)");
+ {
+ char * text = (char *)SvPV_nolen(ST(0));
+ char * windowid;
+
+ if (items < 2)
+ windowid = 0;
+ else {
+ windowid = (char *)SvPV_nolen(ST(1));
+ }
+#line 25 "KVIrc.xs"
+ if(g_pCurrentKvsContext && text)
+ {
+ KviWindow * pWnd;
+ if(windowid)
+ {
+ pWnd = g_pApp->findWindow(windowid);
+ if(!pWnd)pWnd = g_pCurrentKvsContext->window();
+ } else {
+ pWnd = g_pCurrentKvsContext->window();
+ }
+ QString tmp = QString::fromUtf8(text);
+ KviUserInput::parse(tmp,pWnd);
+ }
+#line 81 "KVIrc.c"
+ }
+ XSRETURN_EMPTY;
+}
+
+XS(XS_KVIrc_warning); /* prototype to pass -Wmissing-prototypes */
+XS(XS_KVIrc_warning)
+{
+ dXSARGS;
+ if (items != 1)
+ Perl_croak(aTHX_ "Usage: KVIrc::warning(text)");
+ {
+ char * text = (char *)SvPV_nolen(ST(0));
+#line 42 "KVIrc.xs"
+ if((!g_bExecuteQuiet) && g_pCurrentKvsContext)
+ g_pCurrentKvsContext->warning(text);
+#line 97 "KVIrc.c"
+ }
+ XSRETURN_EMPTY;
+}
+
+XS(XS_KVIrc_internalWarning); /* prototype to pass -Wmissing-prototypes */
+XS(XS_KVIrc_internalWarning)
+{
+ dXSARGS;
+ if (items != 1)
+ Perl_croak(aTHX_ "Usage: KVIrc::internalWarning(text)");
+ {
+ char * text = (char *)SvPV_nolen(ST(0));
+#line 48 "KVIrc.xs"
+ if(!g_bExecuteQuiet)
+ g_lWarningList.append(QString(text));
+#line 113 "KVIrc.c"
+ }
+ XSRETURN_EMPTY;
+}
+
+XS(XS_KVIrc_getLocal); /* prototype to pass -Wmissing-prototypes */
+XS(XS_KVIrc_getLocal)
+{
+ dXSARGS;
+ if (items != 1)
+ Perl_croak(aTHX_ "Usage: KVIrc::getLocal(varname)");
+ {
+ char * varname = (char *)SvPV_nolen(ST(0));
+ char * RETVAL;
+ dXSTARG;
+#line 55 "KVIrc.xs"
+ QString tmp;
+ KviStr hack;
+ if(g_pCurrentKvsContext)
+ {
+ KviKvsVariant * pVar = g_pCurrentKvsContext->localVariables()->find(varname);
+ if(pVar)
+ {
+ pVar->asString(tmp);
+ hack = tmp;
+ RETVAL = hack.ptr();
+ } else RETVAL = "";
+ }
+#line 141 "KVIrc.c"
+ sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG;
+ }
+ XSRETURN(1);
+}
+
+XS(XS_KVIrc_setLocal); /* prototype to pass -Wmissing-prototypes */
+XS(XS_KVIrc_setLocal)
+{
+ dXSARGS;
+ if (items != 2)
+ Perl_croak(aTHX_ "Usage: KVIrc::setLocal(varname, value)");
+ {
+ char * varname = (char *)SvPV_nolen(ST(0));
+ char * value = (char *)SvPV_nolen(ST(1));
+#line 74 "KVIrc.xs"
+ if(g_pCurrentKvsContext)
+ {
+ if(value && *value)
+ {
+ KviKvsVariant * pVar = g_pCurrentKvsContext->localVariables()->get(varname);
+ pVar->setString(value);
+ } else {
+ g_pCurrentKvsContext->localVariables()->unset(varname);
+ }
+ }
+#line 167 "KVIrc.c"
+ }
+ XSRETURN_EMPTY;
+}
+
+XS(XS_KVIrc_getGlobal); /* prototype to pass -Wmissing-prototypes */
+XS(XS_KVIrc_getGlobal)
+{
+ dXSARGS;
+ if (items != 1)
+ Perl_croak(aTHX_ "Usage: KVIrc::getGlobal(varname)");
+ {
+ char * varname = (char *)SvPV_nolen(ST(0));
+ char * RETVAL;
+ dXSTARG;
+#line 88 "KVIrc.xs"
+ QString tmp;
+ KviStr hack;
+ if(g_pCurrentKvsContext)
+ {
+ KviKvsVariant * pVar = g_pCurrentKvsContext->globalVariables()->find(varname);
+ if(pVar)
+ {
+ pVar->asString(tmp);
+ hack = tmp;
+ RETVAL = hack.ptr();
+ } else RETVAL = "";
+ }
+#line 195 "KVIrc.c"
+ sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG;
+ }
+ XSRETURN(1);
+}
+
+XS(XS_KVIrc_setGlobal); /* prototype to pass -Wmissing-prototypes */
+XS(XS_KVIrc_setGlobal)
+{
+ dXSARGS;
+ if (items != 2)
+ Perl_croak(aTHX_ "Usage: KVIrc::setGlobal(varname, value)");
+ {
+ char * varname = (char *)SvPV_nolen(ST(0));
+ char * value = (char *)SvPV_nolen(ST(1));
+#line 107 "KVIrc.xs"
+ if(g_pCurrentKvsContext)
+ {
+ if(value && *value)
+ {
+ KviKvsVariant * pVar = g_pCurrentKvsContext->globalVariables()->get(varname);
+ pVar->setString(value);
+ } else {
+ g_pCurrentKvsContext->localVariables()->unset(varname);
+ }
+ }
+#line 221 "KVIrc.c"
+ }
+ XSRETURN_EMPTY;
+}
+
+XS(XS_KVIrc_eval); /* prototype to pass -Wmissing-prototypes */
+XS(XS_KVIrc_eval)
+{
+ dXSARGS;
+ if (items != 1)
+ Perl_croak(aTHX_ "Usage: KVIrc::eval(code)");
+ {
+ char * code = (char *)SvPV_nolen(ST(0));
+ char * RETVAL;
+ dXSTARG;
+#line 122 "KVIrc.xs"
+ if(g_pCurrentKvsContext && code)
+ {
+ KviKvsVariant ret;
+ if(KviKvsScript::run(QString::fromUtf8(code),g_pCurrentKvsContext->window(),0,&ret))
+ {
+ QString tmp;
+ ret.asString(tmp);
+ g_szLastReturnValue = tmp;
+ } else {
+ g_szLastReturnValue = "";
+ }
+ RETVAL = g_szLastReturnValue.ptr();
+ } else {
+ RETVAL = "";
+ }
+#line 252 "KVIrc.c"
+ sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG;
+ }
+ XSRETURN(1);
+}
+
+#ifdef __cplusplus
+extern "C"
+#endif
+XS(boot_KVIrc); /* prototype to pass -Wmissing-prototypes */
+XS(boot_KVIrc)
+{
+ dXSARGS;
+ char* file = __FILE__;
+
+ newXS("KVIrc::echo", XS_KVIrc_echo, file);
+ newXS("KVIrc::say", XS_KVIrc_say, file);
+ newXS("KVIrc::warning", XS_KVIrc_warning, file);
+ newXS("KVIrc::internalWarning", XS_KVIrc_internalWarning, file);
+ newXS("KVIrc::getLocal", XS_KVIrc_getLocal, file);
+ newXS("KVIrc::setLocal", XS_KVIrc_setLocal, file);
+ newXS("KVIrc::getGlobal", XS_KVIrc_getGlobal, file);
+ newXS("KVIrc::setGlobal", XS_KVIrc_setGlobal, file);
+ newXS("KVIrc::eval", XS_KVIrc_eval, file);
+ XSRETURN_YES;
+}
+
diff --git a/src/modules/popupeditor/Makefile.am b/src/modules/popupeditor/Makefile.am
new file mode 100644
index 00000000..a9e2f1d7
--- /dev/null
+++ b/src/modules/popupeditor/Makefile.am
@@ -0,0 +1,17 @@
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkvipopupeditor.la
+
+libkvipopupeditor_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkvipopupeditor_la_SOURCES = libkvipopupeditor.cpp popupeditor.cpp
+nodist_libkvipopupeditor_la_SOURCES = moc_popupeditor.cpp
+
+noinst_HEADERS = popupeditor.h
+libkvipopupeditor_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+# noinst_HEADERS=
+
+moc_popupeditor.cpp: popupeditor.h
+ $(SS_QT_MOC) $< -o $@
diff --git a/src/modules/popupeditor/libkvipopupeditor.cpp b/src/modules/popupeditor/libkvipopupeditor.cpp
new file mode 100644
index 00000000..a223a1e7
--- /dev/null
+++ b/src/modules/popupeditor/libkvipopupeditor.cpp
@@ -0,0 +1,88 @@
+//
+// File : libkvipopupeditor.cpp
+// Creation date : Mon 23 Dec 2002 20:23:59 2002 GMT by Szymon Stefanek
+//
+// This toolbar is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_module.h"
+
+#include "kvi_locale.h"
+
+#include "kvi_frame.h"
+
+#include "popupeditor.h"
+
+KviPopupEditorWindow * g_pPopupEditorWindow = 0;
+
+
+/*
+ @doc: popupeditor.open
+ @type:
+ command
+ @title:
+ popupeditor.open
+ @short:
+ Shows the popup editor
+ @syntax:
+ toolbareditor.open
+ @description:
+ Opens the script popup editor dialog.
+*/
+
+static bool popupeditor_kvs_cmd_open(KviKvsModuleCommandCall * c)
+{
+ if(!g_pPopupEditorWindow)
+ {
+ g_pPopupEditorWindow = new KviPopupEditorWindow(c->window()->frame());
+ c->window()->frame()->addWindow(g_pPopupEditorWindow);
+ }
+
+ g_pPopupEditorWindow->setFocus();
+ return true;
+}
+
+static bool popupeditor_module_init(KviModule * m)
+{
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"open",popupeditor_kvs_cmd_open);
+ g_pPopupEditorWindow = 0;
+ return true;
+}
+
+static bool popupeditor_module_can_unload(KviModule * m)
+{
+ return (g_pPopupEditorWindow == 0);
+}
+
+static bool popupeditor_module_cleanup(KviModule *m)
+{
+ if(g_pPopupEditorWindow)delete g_pPopupEditorWindow;
+ g_pPopupEditorWindow = 0;
+ return true;
+}
+
+KVIRC_MODULE(
+ "PopupEditor", // module name
+ "1.0.0", // module version
+ "Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot net)", // author & (C)
+ "Editor for the script popups",
+ popupeditor_module_init,
+ popupeditor_module_can_unload,
+ 0,
+ popupeditor_module_cleanup
+)
diff --git a/src/modules/popupeditor/popupeditor.cpp b/src/modules/popupeditor/popupeditor.cpp
new file mode 100644
index 00000000..942b5b2f
--- /dev/null
+++ b/src/modules/popupeditor/popupeditor.cpp
@@ -0,0 +1,1433 @@
+//=============================================================================
+//
+// File : popupeditor.cpp
+// Creation date : Mon Dec 23 2002 20:28:18 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the linkss of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) 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.
+//
+//=============================================================================
+
+#include "popupeditor.h"
+
+#include "kvi_iconmanager.h"
+#include "kvi_options.h"
+#include "kvi_locale.h"
+#include "kvi_imagedialog.h"
+#include "kvi_config.h"
+#include "kvi_filedialog.h"
+#include "kvi_fileutils.h"
+#include "kvi_scripteditor.h"
+#include "kvi_debug.h"
+#include "kvi_locale.h"
+#include "kvi_app.h"
+#include "kvi_kvs_popupmanager.h"
+#include "kvi_kvs_popupmenu.h"
+#include "kvi_kvs_variantlist.h"
+//#include "kvi_parameterlist.h"
+
+#include <qmessagebox.h>
+#include <qdir.h>
+#include <qsplitter.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qtooltip.h>
+#include "kvi_pointerhashtable.h"
+#include <qpushbutton.h>
+#include "kvi_tal_vbox.h"
+
+extern KviPopupEditorWindow * g_pPopupEditorWindow;
+
+
+
+//KviPopupEntryItem
+KviPopupListViewItem::KviPopupListViewItem(KviTalListView * pListView,KviPopupListViewItem * after,Type t)
+: KviTalListViewItem(pListView,after)
+{
+ m_type = t;
+ init();
+}
+
+KviPopupListViewItem::KviPopupListViewItem(KviPopupListViewItem * parent,KviPopupListViewItem * after,Type t)
+: KviTalListViewItem(parent,after)
+{
+ m_type = t;
+ init();
+}
+
+void KviPopupListViewItem::init()
+{
+ switch(m_type)
+ {
+ case Item:
+ setText(1,__tr2qs("Item"));
+ break;
+ case Menu:
+ setText(1,__tr2qs("Submenu"));
+ break;
+ case ExtMenu:
+ setText(1,__tr2qs("External Menu"));
+ break;
+ case Separator:
+ setText(0,"-----------------------");
+ setText(1,__tr2qs("Separator"));
+ break;
+ case Label:
+ setText(1,__tr2qs("Label"));
+ break;
+ case Epilogue:
+ setText(0,__tr2qs("### Epilogue ###"));
+ setText(1,__tr2qs("Epilogue"));
+ break;
+ case Prologue:
+ setText(0,__tr2qs("### Prologue ###"));
+ setText(1,__tr2qs("Prologue"));
+ break;
+ default:
+ break;
+ }
+}
+
+void KviPopupListViewItem::setItemText(const QString & szText)
+{
+ switch(m_type)
+ {
+ case Item:
+ case Menu:
+ case Label:
+ case ExtMenu:
+ m_szText = szText;
+ setText(0,szText);
+ break;
+ default:
+ break;
+ }
+}
+
+void KviPopupListViewItem::setCondition(const QString & szCondition)
+{
+ switch(m_type)
+ {
+ case Item:
+ case Menu:
+ case Label:
+ case ExtMenu:
+ m_szCondition = szCondition;
+ break;
+ default:
+ break;
+ }
+}
+
+void KviPopupListViewItem::setCode(const QString & szCode)
+{
+ switch(m_type)
+ {
+ case Item:
+ case Epilogue:
+ case Prologue:
+ case ExtMenu:
+ m_szCode = szCode;
+ break;
+ default:
+ break;
+ }
+}
+
+void KviPopupListViewItem::setId(const QString & szId)
+{
+ m_szId = szId;
+}
+
+void KviPopupListViewItem::setIcon(const QString & szIcon)
+{
+ switch(m_type)
+ {
+ case Item:
+ case Menu:
+ case Label:
+ case ExtMenu:
+ m_szIcon = szIcon;
+ {
+ QPixmap * pix = g_pIconManager->getImage(szIcon);
+ if(pix)setPixmap(0,*pix);
+ else setPixmap(0,QPixmap());
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+KviSinglePopupEditor::KviSinglePopupEditor(QWidget * par)
+: QWidget(par)
+{
+ m_pLastSelectedItem = 0;
+ m_pContextPopup = new KviTalPopupMenu(this);
+ m_pClipboard = 0;
+ m_pTestPopup = 0;
+
+ QGridLayout * g = new QGridLayout(this,7,3,2,2);
+
+ m_pNameEditor = new QLineEdit(this);
+ QToolTip::add(m_pNameEditor,__tr2qs("Popup name"));
+
+ g->addMultiCellWidget(m_pNameEditor,0,0,0,1);
+
+ m_pMenuButton = new QPushButton(__tr2qs("Test"),this);
+ g->addWidget(m_pMenuButton,0,2);
+ connect(m_pMenuButton,SIGNAL(clicked()),this,SLOT(testPopup()));
+#ifdef COMPILE_USE_QT4
+ QSplitter * spl = new QSplitter(Qt::Vertical,this,"popupeditor");
+ spl->setOpaqueResize(false);
+#else
+ QSplitter * spl = new QSplitter(QSplitter::Vertical,this);
+#endif
+
+ m_pListView = new KviTalListView(spl);
+ m_pListView->addColumn(__tr2qs("Item"));
+ m_pListView->addColumn(__tr2qs("Type"));
+ m_pListView->setMultiSelection(false);
+ m_pListView->setAllColumnsShowFocus(true);
+ m_pListView->setRootIsDecorated(true);
+ m_pListView->setShowSortIndicator(false);
+ m_pListView->setSorting(-1);
+
+
+ connect(m_pListView,SIGNAL(selectionChanged(KviTalListViewItem *)),this,SLOT(selectionChanged(KviTalListViewItem *)));
+ connect(m_pListView,SIGNAL(rightButtonPressed(KviTalListViewItem *,const QPoint &,int)),
+ this,SLOT(itemPressed(KviTalListViewItem *,const QPoint &,int)));
+
+ m_pEditor = KviScriptEditor::createInstance(spl);
+
+ g->addMultiCellWidget(spl,1,1,0,2);
+
+ QLabel * l = new QLabel(__tr2qs("Text:"),this);
+ l->setMargin(2);
+ g->addWidget(l,2,0);
+
+ m_pTextEditor = new QLineEdit(this);
+ QToolTip::add(m_pTextEditor,
+ __tr2qs("<center><b>Visible text</b><br>May contain identifiers that will be evaluated at popup call time.<br>For labels, this text can contain also limited HTML tags.</center>"));
+ g->addMultiCellWidget(m_pTextEditor,2,2,1,2);
+
+ l = new QLabel(__tr2qs("Condition:"),this);
+ l->setMargin(2);
+ g->addWidget(l,3,0);
+
+ m_pConditionEditor = new QLineEdit(this);
+ QToolTip::add(m_pConditionEditor,
+ __tr2qs("<center><b>Boolean condition</b><br>Will be evaluated at popup call time in order to decide if this entry has to be shown.<br>An empty condition evaluates to true.</center>"));
+ g->addMultiCellWidget(m_pConditionEditor,3,3,1,2);
+
+ l = new QLabel(__tr2qs("Icon:"),this);
+ l->setMargin(2);
+ g->addWidget(l,4,0);
+
+ m_pIconEditor = new QLineEdit(this);
+ QToolTip::add(m_pIconEditor,
+ __tr2qs("<center><b>Icon identifier</b><br>May be an internal icon ID, an absolute path or a relative path.<br>Portable scripts should never use absolute paths.</center>"));
+ g->addMultiCellWidget(m_pIconEditor,4,4,1,2);
+
+ l = new QLabel(__tr2qs("External menu:"),this);
+ l->setMargin(2);
+ g->addWidget(l,5,0);
+
+ m_pExtNameEditor = new QLineEdit(this);
+ QToolTip::add(m_pExtNameEditor,
+ __tr2qs("<center><b>External menu name</b><br>This allows to nest externally defined popup menus. The popup menu with the specified name will be looked up at menu setup time.</center>"));
+ g->addMultiCellWidget(m_pExtNameEditor,5,5,1,2);
+
+ l = new QLabel(__tr2qs("Item Id:"),this);
+ l->setMargin(2);
+ g->addWidget(l,6,0);
+
+
+ m_pIdEditor = new QLineEdit(this);
+ QToolTip::add(m_pIdEditor,
+ __tr2qs("<center><b>Item id</b><br>This will allow you to use delpopupitem later.</center>"));
+ g->addMultiCellWidget(m_pIdEditor,6,6,1,2);
+
+
+ g->setColStretch(1,1);
+ g->setRowStretch(1,1);
+
+}
+
+KviSinglePopupEditor::~KviSinglePopupEditor()
+{
+ if(m_pClipboard)delete m_pClipboard;
+ if(m_pTestPopup)delete m_pTestPopup;
+ KviScriptEditor::destroyInstance(m_pEditor);
+}
+
+void KviSinglePopupEditor::testPopup()
+{
+
+ if(m_pTestPopup)delete m_pTestPopup;
+ m_pTestPopup = getMenu();
+ if(!m_pTestPopup)return;
+ connect(m_pTestPopup,SIGNAL(testModeItemClicked(KviKvsPopupMenuItem *)),this,SLOT(testModeMenuItemClicked(KviKvsPopupMenuItem *)));
+ QPoint pnt = m_pMenuButton->mapToGlobal(QPoint(0,m_pMenuButton->height()));
+ KviKvsVariantList * parms = new KviKvsVariantList();
+ parms->append(new KviKvsVariant(QString("test1")));
+ parms->append(new KviKvsVariant(QString("test2")));
+ parms->append(new KviKvsVariant(QString("test3")));
+ parms->append(new KviKvsVariant(QString("test4")));
+ m_pTestPopup->doPopup(pnt,g_pActiveWindow,parms,true);
+}
+
+KviPopupListViewItem * KviSinglePopupEditor::findMatchingItem(KviKvsPopupMenuItem * it,KviPopupListViewItem * item)
+{
+
+ if(it->type() != KviKvsPopupMenuItem::Item)goto not_this_one;
+ if(item->m_type != KviPopupListViewItem::Item)goto not_this_one;
+ if(it->name() != item->m_szId)goto not_this_one;
+ if(it->kvsText())
+ {
+ if(it->kvsText()->code() != item->m_szText)goto not_this_one;
+ } else {
+ if(!item->m_szText.isEmpty())goto not_this_one;
+ }
+ if(it->kvsCode())
+ {
+ if(it->kvsCode()->code() != item->m_szCode)goto not_this_one;
+ } else {
+ if(!item->m_szCode.isEmpty())goto not_this_one;
+ }
+ if(it->kvsIcon())
+ {
+ if(it->kvsIcon()->code() != item->m_szIcon)goto not_this_one;
+ } else {
+ if(!item->m_szIcon.isEmpty())goto not_this_one;
+ }
+ if(it->kvsCondition())
+ {
+ if(it->kvsCondition()->code() != item->m_szCondition)goto not_this_one;
+ } else {
+ if(!item->m_szCondition.isEmpty())goto not_this_one;
+ }
+
+ return item;
+
+not_this_one:
+ item = (KviPopupListViewItem *)item->firstChild();
+ while(item)
+ {
+ KviPopupListViewItem * found = findMatchingItem(it,item);
+ if(found)return found;
+ item = (KviPopupListViewItem *)item->nextSibling();
+ }
+
+ return 0;
+}
+
+void KviSinglePopupEditor::testModeMenuItemClicked(KviKvsPopupMenuItem * it)
+{
+
+ saveLastSelectedItem(); // that's the first thingie
+ // find the matching item and set it as current
+ KviPopupListViewItem * item = (KviPopupListViewItem *)m_pListView->firstChild();
+ while(item)
+ {
+ KviPopupListViewItem * found = findMatchingItem(it,item);
+ if(found)
+ {
+ // set the item as current
+ m_pListView->ensureItemVisible(found);
+ m_pListView->setCurrentItem(found);
+ selectionChanged(found);
+ return;
+ }
+ item = (KviPopupListViewItem *)item->nextSibling();
+ }
+
+}
+
+
+void KviSinglePopupEditor::itemPressed(KviTalListViewItem *it,const QPoint &pnt,int col)
+{
+ m_pContextPopup->clear();
+
+ KviPopupListViewItem * parentMenu = 0;
+ bool bIsMenu = false;
+
+ if(it)
+ {
+ parentMenu = (KviPopupListViewItem *) (((KviPopupListViewItem *)it)->parent());
+ bIsMenu = ((KviPopupListViewItem *)it)->m_type == KviPopupListViewItem::Menu;
+ }
+
+ m_pContextPopup->insertItem(__tr2qs("New Separator Below"),this,SLOT(contextNewSeparatorBelow()));
+ m_pContextPopup->setItemEnabled(
+ m_pContextPopup->insertItem(__tr2qs("New Separator Above"),this,SLOT(contextNewSeparatorAbove())),
+ it);
+ m_pContextPopup->setItemEnabled(
+ m_pContextPopup->insertItem(__tr2qs("New Separator Inside"),this,SLOT(contextNewSeparatorInside())),
+ it && bIsMenu);
+
+ m_pContextPopup->insertSeparator();
+
+ m_pContextPopup->insertItem(__tr2qs("New Label Below"),this,SLOT(contextNewLabelBelow()));
+ m_pContextPopup->setItemEnabled(
+ m_pContextPopup->insertItem(__tr2qs("New Label Above"),this,SLOT(contextNewLabelAbove())),
+ it);
+ m_pContextPopup->setItemEnabled(
+ m_pContextPopup->insertItem(__tr2qs("New Label Inside"),this,SLOT(contextNewLabelInside())),
+ it && bIsMenu);
+
+ m_pContextPopup->insertSeparator();
+
+ m_pContextPopup->insertItem(__tr2qs("New Item Below"),this,SLOT(contextNewItemBelow()));
+ m_pContextPopup->setItemEnabled(
+ m_pContextPopup->insertItem(__tr2qs("New Item Above"),this,SLOT(contextNewItemAbove())),
+ it);
+ m_pContextPopup->setItemEnabled(
+ m_pContextPopup->insertItem(__tr2qs("New Item Inside"),this,SLOT(contextNewItemInside())),
+ it && bIsMenu);
+
+ m_pContextPopup->insertSeparator();
+
+ m_pContextPopup->insertItem(__tr2qs("New Menu Below"),this,SLOT(contextNewMenuBelow()));
+ m_pContextPopup->setItemEnabled(
+ m_pContextPopup->insertItem(__tr2qs("New Menu Above"),this,SLOT(contextNewMenuAbove())),
+ it);
+ m_pContextPopup->setItemEnabled(
+ m_pContextPopup->insertItem(__tr2qs("New Menu Inside"),this,SLOT(contextNewMenuInside())),
+ it && bIsMenu);
+
+ m_pContextPopup->insertSeparator();
+
+ m_pContextPopup->insertItem(__tr2qs("New External Menu Below"),this,SLOT(contextNewExtMenuBelow()));
+ m_pContextPopup->setItemEnabled(
+ m_pContextPopup->insertItem(__tr2qs("New External Menu Above"),this,SLOT(contextNewExtMenuAbove())),
+ it);
+ m_pContextPopup->setItemEnabled(
+ m_pContextPopup->insertItem(__tr2qs("New External Menu Inside"),this,SLOT(contextNewExtMenuInside())),
+ it && bIsMenu);
+
+ m_pContextPopup->insertSeparator();
+
+ m_pContextPopup->setItemEnabled(
+ m_pContextPopup->insertItem(
+ *(g_pIconManager->getSmallIcon(KVI_SMALLICON_CUT)),
+ __tr2qs("Cu&t"),
+ this,SLOT(contextCut())),
+ it);
+ m_pContextPopup->setItemEnabled(
+ m_pContextPopup->insertItem(
+ *(g_pIconManager->getSmallIcon(KVI_SMALLICON_COPY)),
+ __tr2qs("&Copy"),
+ this,SLOT(contextCopy())),
+ it);
+ m_pContextPopup->setItemEnabled(
+ m_pContextPopup->insertItem(
+ *(g_pIconManager->getSmallIcon(KVI_SMALLICON_PASTE)),
+ __tr2qs("&Paste Below"),this,SLOT(contextPasteBelow())),
+ m_pClipboard);
+ m_pContextPopup->setItemEnabled(
+ m_pContextPopup->insertItem(
+ *(g_pIconManager->getSmallIcon(KVI_SMALLICON_PASTE)),
+ __tr2qs("Paste Above"),this,SLOT(contextPasteAbove())),
+ it && m_pClipboard);
+ m_pContextPopup->setItemEnabled(
+ m_pContextPopup->insertItem(
+ *(g_pIconManager->getSmallIcon(KVI_SMALLICON_PASTE)),
+ __tr2qs("Paste Inside"),this,SLOT(contextPasteInside())),
+ it && bIsMenu && m_pClipboard);
+
+
+ bool bSeparatorInserted = false;
+
+// if(!findPrologue(parentMenu))
+// {
+ m_pContextPopup->insertSeparator();
+ bSeparatorInserted = true;
+ m_pContextPopup->insertItem(
+ *(g_pIconManager->getSmallIcon(KVI_SMALLICON_PROLOGUE)),
+ __tr2qs("New Menu Prologue"),this,SLOT(contextNewPrologue()));
+// }
+
+// if(!findEpilogue(parentMenu))
+// {
+ if(!bSeparatorInserted)m_pContextPopup->insertSeparator();
+ m_pContextPopup->insertItem(
+ *(g_pIconManager->getSmallIcon(KVI_SMALLICON_EPILOGUE)),
+ __tr2qs("New Menu Epilogue"),this,SLOT(contextNewEpilogue()));
+// }
+
+ m_pContextPopup->popup(pnt);
+}
+
+void KviSinglePopupEditor::createNewItemAboveLastSelected(KviPopupListViewItem::Type t)
+{
+ m_pListView->setCurrentItem(newItemAbove(m_pLastSelectedItem,t));
+}
+
+void KviSinglePopupEditor::createNewItemBelowLastSelected(KviPopupListViewItem::Type t)
+{
+ m_pListView->setCurrentItem(newItemBelow(m_pLastSelectedItem,t));
+}
+
+void KviSinglePopupEditor::createNewItemInsideLastSelected(KviPopupListViewItem::Type t)
+{
+ if(m_pLastSelectedItem)m_pLastSelectedItem->setOpen(true);
+ m_pListView->setCurrentItem(newItemInside(m_pLastSelectedItem,t));
+}
+
+void KviSinglePopupEditor::contextNewSeparatorAbove()
+{
+ createNewItemAboveLastSelected(KviPopupListViewItem::Separator);
+}
+
+void KviSinglePopupEditor::contextNewSeparatorBelow()
+{
+ createNewItemBelowLastSelected(KviPopupListViewItem::Separator);
+}
+
+void KviSinglePopupEditor::contextNewSeparatorInside()
+{
+ createNewItemInsideLastSelected(KviPopupListViewItem::Separator);
+}
+
+void KviSinglePopupEditor::contextNewItemBelow()
+{
+ createNewItemBelowLastSelected(KviPopupListViewItem::Item);
+}
+
+void KviSinglePopupEditor::contextNewItemAbove()
+{
+ createNewItemAboveLastSelected(KviPopupListViewItem::Item);
+}
+
+void KviSinglePopupEditor::contextNewItemInside()
+{
+ createNewItemInsideLastSelected(KviPopupListViewItem::Item);
+}
+
+void KviSinglePopupEditor::contextNewMenuBelow()
+{
+ createNewItemBelowLastSelected(KviPopupListViewItem::Menu);
+}
+
+void KviSinglePopupEditor::contextNewMenuAbove()
+{
+ createNewItemAboveLastSelected(KviPopupListViewItem::Menu);
+}
+
+void KviSinglePopupEditor::contextNewMenuInside()
+{
+ createNewItemInsideLastSelected(KviPopupListViewItem::Menu);
+}
+
+void KviSinglePopupEditor::contextNewExtMenuBelow()
+{
+ createNewItemBelowLastSelected(KviPopupListViewItem::ExtMenu);
+}
+
+void KviSinglePopupEditor::contextNewExtMenuAbove()
+{
+ createNewItemAboveLastSelected(KviPopupListViewItem::ExtMenu);
+}
+void KviSinglePopupEditor::contextNewExtMenuInside()
+{
+ createNewItemInsideLastSelected(KviPopupListViewItem::ExtMenu);
+}
+
+
+void KviSinglePopupEditor::contextNewLabelBelow()
+{
+ createNewItemBelowLastSelected(KviPopupListViewItem::Label);
+}
+
+void KviSinglePopupEditor::contextNewLabelAbove()
+{
+ createNewItemAboveLastSelected(KviPopupListViewItem::Label);
+}
+
+void KviSinglePopupEditor::contextNewLabelInside()
+{
+ createNewItemInsideLastSelected(KviPopupListViewItem::Label);
+}
+
+KviPopupListViewItem * KviSinglePopupEditor::newItem(KviPopupListViewItem * par,KviPopupListViewItem * after,KviPopupListViewItem::Type t)
+{
+ if(par)return new KviPopupListViewItem(par,after,t);
+ return new KviPopupListViewItem(m_pListView,after,t);
+}
+
+KviPopupListViewItem * KviSinglePopupEditor::newItemBelow(KviPopupListViewItem * it,KviPopupListViewItem::Type t)
+{
+ if(!it)return newItem(0,0,t);
+ return newItem((KviPopupListViewItem *)it->parent(),it,t);
+}
+
+KviPopupListViewItem * KviSinglePopupEditor::newItemAbove(KviPopupListViewItem * it,KviPopupListViewItem::Type t)
+{
+ if(!it)return newItem(0,0,t);
+ return newItem((KviPopupListViewItem *)it->parent(),(KviPopupListViewItem *)it->itemAbove(),t);
+}
+
+KviPopupListViewItem * KviSinglePopupEditor::newItemInside(KviPopupListViewItem * it,KviPopupListViewItem::Type t)
+{
+ if(it)
+ {
+ if(it->m_type != KviPopupListViewItem::Menu)
+ {
+ return newItemBelow(it,t);
+ }
+ }
+ return newItem(it,it,t);
+}
+
+void KviSinglePopupEditor::contextNewPrologue()
+{
+ KviPopupListViewItem * it = m_pLastSelectedItem ? (KviPopupListViewItem *)m_pLastSelectedItem->parent() : 0;
+// if(!findPrologue(it))
+// {
+ m_pListView->setCurrentItem(newItem(it,it,KviPopupListViewItem::Prologue));
+// }
+}
+
+void KviSinglePopupEditor::contextNewEpilogue()
+{
+ KviPopupListViewItem * it = m_pLastSelectedItem ? (KviPopupListViewItem *)m_pLastSelectedItem->parent() : 0;
+// if(!findEpilogue(it))
+// {
+ KviPopupListViewItem * after = it ? (KviPopupListViewItem *)it->firstChild() : (KviPopupListViewItem *)m_pListView->firstChild();
+ if(after)
+ {
+ while(after->nextSibling())after = (KviPopupListViewItem *)after->nextSibling();
+ } else {
+ after = it;
+ }
+ m_pListView->setCurrentItem(newItem(it,after,KviPopupListViewItem::Epilogue));
+// }
+}
+
+void KviSinglePopupEditor::contextCopy()
+{
+ if(!m_pLastSelectedItem)return;
+ if(m_pClipboard)delete m_pClipboard;
+ m_pClipboard = new KviKvsPopupMenu("clipboard");
+ addItemToMenu(m_pClipboard,m_pLastSelectedItem);
+}
+
+void KviSinglePopupEditor::contextCut()
+{
+ if(!m_pLastSelectedItem)return;
+ contextCopy();
+
+ KviPopupListViewItem * it = m_pLastSelectedItem;
+ m_pLastSelectedItem = 0;
+ delete it;
+ if(!m_pLastSelectedItem)selectionChanged(0);
+}
+
+
+void KviSinglePopupEditor::contextPasteBelow()
+{
+ if(!m_pClipboard)return;
+ KviPopupListViewItem * par = m_pLastSelectedItem ? (KviPopupListViewItem *)m_pLastSelectedItem->parent() : 0;
+ populateMenu(m_pClipboard,par,m_pLastSelectedItem);
+}
+
+void KviSinglePopupEditor::contextPasteAbove()
+{
+ if(!m_pClipboard)return;
+ KviPopupListViewItem * par = m_pLastSelectedItem ? (KviPopupListViewItem *)m_pLastSelectedItem->parent() : 0;
+ KviPopupListViewItem * above = m_pLastSelectedItem ? (KviPopupListViewItem *)m_pLastSelectedItem->itemAbove() : 0;
+ populateMenu(m_pClipboard,par,above);
+
+}
+
+void KviSinglePopupEditor::contextPasteInside()
+{
+ if(!m_pClipboard)return;
+ if(m_pLastSelectedItem)
+ {
+ if(m_pLastSelectedItem->m_type != KviPopupListViewItem::Menu)
+ {
+ contextPasteBelow();
+ return;
+ }
+ m_pLastSelectedItem->setOpen(true);
+ }
+ populateMenu(m_pClipboard,m_pLastSelectedItem,0);
+}
+
+void KviSinglePopupEditor::saveLastSelectedItem()
+{
+ if(!m_pLastSelectedItem)return;
+
+ QString tmp;
+
+ switch(m_pLastSelectedItem->m_type)
+ {
+ case KviPopupListViewItem::Prologue:
+ case KviPopupListViewItem::Epilogue:
+ case KviPopupListViewItem::Item:
+ {
+ QString tmpx;
+ m_pEditor->getText(tmpx);
+ m_pLastSelectedItem->setCode(tmpx);
+ }
+ break;
+ default:
+ break;
+ }
+
+ m_pLastSelectedItem->setId(m_pIdEditor->text());
+
+ switch(m_pLastSelectedItem->m_type)
+ {
+ case KviPopupListViewItem::Menu:
+ case KviPopupListViewItem::ExtMenu:
+ case KviPopupListViewItem::Item:
+ m_pLastSelectedItem->setIcon(m_pIconEditor->text());
+ break;
+ default:
+ break;
+ }
+
+ switch(m_pLastSelectedItem->m_type)
+ {
+ case KviPopupListViewItem::Menu:
+ case KviPopupListViewItem::Item:
+ case KviPopupListViewItem::Label:
+ case KviPopupListViewItem::ExtMenu:
+ m_pLastSelectedItem->setItemText(m_pTextEditor->text());
+ m_pLastSelectedItem->setCondition(m_pConditionEditor->text());
+ break;
+ default:
+ break;
+ }
+
+ if(m_pLastSelectedItem->m_type == KviPopupListViewItem::ExtMenu)
+ {
+ m_pLastSelectedItem->setCode(m_pExtNameEditor->text());
+ }
+}
+
+void KviSinglePopupEditor::addItemToMenu(KviKvsPopupMenu * p,KviPopupListViewItem *it)
+{
+ it->m_szId.stripWhiteSpace();
+ switch(it->m_type)
+ {
+ case KviPopupListViewItem::Prologue:
+ it->m_szCode.stripWhiteSpace();
+ p->addPrologue(it->m_szId,it->m_szCode);
+ break;
+ case KviPopupListViewItem::Epilogue:
+ it->m_szCode.stripWhiteSpace();
+ p->addEpilogue(it->m_szId,it->m_szCode);
+ break;
+ case KviPopupListViewItem::Separator:
+ it->m_szCondition.stripWhiteSpace();
+ p->addSeparator(it->m_szId,it->m_szCondition);
+ break;
+ case KviPopupListViewItem::Label:
+ it->m_szText.stripWhiteSpace();
+ it->m_szCondition.stripWhiteSpace();
+ it->m_szIcon.stripWhiteSpace();
+ p->addLabel(it->m_szId,it->m_szText,it->m_szIcon,it->m_szCondition);
+ break;
+ case KviPopupListViewItem::Item:
+ it->m_szText.stripWhiteSpace();
+ it->m_szIcon.stripWhiteSpace();
+ it->m_szCondition.stripWhiteSpace();
+ it->m_szCode.stripWhiteSpace();
+ p->addItem(it->m_szId,it->m_szCode,it->m_szText,it->m_szIcon,it->m_szCondition);
+ break;
+ case KviPopupListViewItem::ExtMenu:
+ it->m_szText.stripWhiteSpace();
+ it->m_szIcon.stripWhiteSpace();
+ it->m_szCondition.stripWhiteSpace();
+ it->m_szCode.stripWhiteSpace();// <-- this is the ext name in fact
+ p->addExtPopup(it->m_szId,it->m_szCode,it->m_szText,it->m_szIcon,it->m_szCondition);
+ break;
+ case KviPopupListViewItem::Menu:
+ {
+ it->m_szText.stripWhiteSpace();
+ it->m_szIcon.stripWhiteSpace();
+ it->m_szCondition.stripWhiteSpace();
+ KviKvsPopupMenu * menu = p->addPopup(it->m_szId,it->m_szText,it->m_szIcon,it->m_szCondition);
+ for(KviPopupListViewItem * item = (KviPopupListViewItem *)it->firstChild();item;item = (KviPopupListViewItem *)item->nextSibling())
+ {
+ addItemToMenu(menu,item);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+KviKvsPopupMenu * KviSinglePopupEditor::getMenu()
+{
+ saveLastSelectedItem();
+
+ QString tmp = m_pNameEditor->text();
+ tmp.stripWhiteSpace();
+
+ KviKvsPopupMenu * p = new KviKvsPopupMenu(tmp);
+ for(KviPopupListViewItem * it = (KviPopupListViewItem *)m_pListView->firstChild();it;it = (KviPopupListViewItem *)it->nextSibling())
+ {
+ addItemToMenu(p,it);
+ }
+ return p;
+}
+
+void KviSinglePopupEditor::selectionChanged(KviTalListViewItem * it)
+{
+ saveLastSelectedItem();
+
+ bool bEditorEnabled = false;
+ bool bIconEditorEnabled = false;
+ bool bConditionEditorEnabled = false;
+ bool bTextEditorEnabled = false;
+ bool bNameEditorEnabled = false;
+
+ if(it)
+ {
+ m_pIdEditor->setText(((KviPopupListViewItem *)it)->m_szId);
+
+ switch(((KviPopupListViewItem *)it)->m_type)
+ {
+ case KviPopupListViewItem::Prologue:
+ case KviPopupListViewItem::Epilogue:
+ case KviPopupListViewItem::Item:
+ m_pEditor->setText(((KviPopupListViewItem *)it)->m_szCode);
+ bEditorEnabled = true;
+ break;
+ default:
+ break;
+ }
+
+ switch(((KviPopupListViewItem *)it)->m_type)
+ {
+ case KviPopupListViewItem::Menu:
+ case KviPopupListViewItem::Item:
+ case KviPopupListViewItem::Label:
+ case KviPopupListViewItem::ExtMenu:
+ m_pIconEditor->setText(((KviPopupListViewItem *)it)->m_szIcon);
+ bIconEditorEnabled = true;
+ break;
+ default:
+ break; }
+
+ switch(((KviPopupListViewItem *)it)->m_type)
+ {
+ case KviPopupListViewItem::Menu:
+ case KviPopupListViewItem::Item:
+ case KviPopupListViewItem::Label:
+ case KviPopupListViewItem::ExtMenu:
+ m_pConditionEditor->setText(((KviPopupListViewItem *)it)->m_szCondition);
+ bConditionEditorEnabled = true;
+ m_pTextEditor->setText(((KviPopupListViewItem *)it)->m_szText);
+ bTextEditorEnabled = true;
+ break;
+ default:
+ break;
+ }
+
+ if(((KviPopupListViewItem *)it)->m_type == KviPopupListViewItem::ExtMenu)
+ {
+ m_pExtNameEditor->setText(((KviPopupListViewItem *)it)->m_szCode);
+ bNameEditorEnabled =true;
+ }
+ }
+
+ m_pLastSelectedItem = (KviPopupListViewItem *)it;
+
+ if(!bEditorEnabled)m_pEditor->setText("");
+ m_pEditor->setEnabled(bEditorEnabled);
+ if(!bIconEditorEnabled)m_pIconEditor->setText("");
+ m_pIconEditor->setEnabled(bIconEditorEnabled);
+ if(!bConditionEditorEnabled)m_pConditionEditor->setText("");
+ m_pConditionEditor->setEnabled(bConditionEditorEnabled);
+ if(!bTextEditorEnabled)m_pTextEditor->setText("");
+ m_pTextEditor->setEnabled(bTextEditorEnabled);
+ m_pExtNameEditor->setEnabled(bNameEditorEnabled);
+ if(!bNameEditorEnabled)m_pExtNameEditor->setText("");
+ if(!it)m_pIdEditor->setText("");
+ m_pIdEditor->setEnabled(it);
+}
+
+void KviSinglePopupEditor::populateMenu(KviKvsPopupMenu * pop,KviPopupListViewItem * par,KviPopupListViewItem * theItem)
+{
+ if(!pop)return;
+
+ for(KviKvsScript * sp = pop->prologues()->first();sp;sp = pop->prologues()->next())
+ {
+ if(par)theItem = new KviPopupListViewItem(par,theItem,KviPopupListViewItem::Prologue);
+ else theItem = new KviPopupListViewItem(m_pListView,theItem,KviPopupListViewItem::Prologue);
+ theItem->setCode(sp->code());
+ theItem->setId(sp->name());
+ }
+
+ for(KviKvsPopupMenuItem * item = pop->m_pItemList->first();item;item = pop->m_pItemList->next())
+ {
+ switch(item->type())
+ {
+ case KviKvsPopupMenuItem::Item:
+ if(par)theItem = new KviPopupListViewItem(par,theItem,KviPopupListViewItem::Item);
+ else theItem = new KviPopupListViewItem(m_pListView,theItem,KviPopupListViewItem::Item);
+ theItem->setIcon(item->kvsIcon() ? item->kvsIcon()->code() : QString::null);
+ theItem->setItemText(item->kvsText() ? item->kvsText()->code() : QString::null);
+ theItem->setCondition(item->kvsCondition() ? item->kvsCondition()->code() : QString::null);
+ theItem->setCode(item->kvsCode() ? item->kvsCode()->code() : QString::null);
+ theItem->setId(item->name());
+ break;
+ case KviKvsPopupMenuItem::ExtMenu:
+ if(par)theItem = new KviPopupListViewItem(par,theItem,KviPopupListViewItem::ExtMenu);
+ else theItem = new KviPopupListViewItem(m_pListView,theItem,KviPopupListViewItem::ExtMenu);
+ theItem->setIcon(item->kvsIcon() ? item->kvsIcon()->code() : QString::null);
+ theItem->setItemText(item->kvsText() ? item->kvsText()->code() : QString::null);
+ theItem->setCondition(item->kvsCondition() ? item->kvsCondition()->code() : QString::null);
+ theItem->setCode(((KviKvsPopupMenuItemExtMenu *)item)->extName());
+ theItem->setId(item->name());
+ break;
+ case KviKvsPopupMenuItem::Label:
+ if(par)theItem = new KviPopupListViewItem(par,theItem,KviPopupListViewItem::Label);
+ else theItem = new KviPopupListViewItem(m_pListView,theItem,KviPopupListViewItem::Label);
+ theItem->setIcon(item->kvsIcon() ? item->kvsIcon()->code() : QString::null);
+ theItem->setItemText(item->kvsText() ? item->kvsText()->code() : QString::null);
+ theItem->setCondition(item->kvsCondition() ? item->kvsCondition()->code() : QString::null);
+ theItem->setId(item->name());
+ break;
+ case KviKvsPopupMenuItem::Separator:
+ if(par)theItem = new KviPopupListViewItem(par,theItem,KviPopupListViewItem::Separator);
+ else theItem = new KviPopupListViewItem(m_pListView,theItem,KviPopupListViewItem::Separator);
+ theItem->setId(item->name());
+ break;
+ case KviKvsPopupMenuItem::Menu:
+ if(par)theItem = new KviPopupListViewItem(par,theItem,KviPopupListViewItem::Menu);
+ else theItem = new KviPopupListViewItem(m_pListView,theItem,KviPopupListViewItem::Menu);
+ theItem->setIcon(item->kvsIcon() ? item->kvsIcon()->code() : QString::null);
+ theItem->setItemText(item->kvsText() ? item->kvsText()->code() : QString::null);
+ theItem->setCondition(item->kvsCondition() ? item->kvsCondition()->code() : QString::null);
+ theItem->setId(item->name());
+ populateMenu(((KviKvsPopupMenuItemMenu *)item)->menu(),theItem,0);
+ break;
+ default:
+ break;
+ }
+ }
+
+ for(KviKvsScript * se = pop->epilogues()->first();se;se = pop->epilogues()->next())
+ {
+ if(par)theItem = new KviPopupListViewItem(par,theItem,KviPopupListViewItem::Epilogue);
+ else theItem = new KviPopupListViewItem(m_pListView,theItem,KviPopupListViewItem::Epilogue);
+ theItem->setCode(se->code());
+ theItem->setId(se->name());
+ }
+}
+
+
+
+void KviSinglePopupEditor::edit(KviMenuListViewItem * it)
+{
+ saveLastSelectedItem();
+
+ m_pLastSelectedItem = 0;
+
+ m_pListView->clear();
+
+ selectionChanged(0);
+
+ if(it)
+ {
+ m_pNameEditor->setText(it->m_pPopup->popupName());
+
+ populateMenu(it->m_pPopup,0,0);
+
+ } else {
+ m_pIconEditor->setText("");
+ m_pIconEditor->setEnabled(false);
+ m_pIdEditor->setText("");
+ m_pIdEditor->setEnabled(false);
+ m_pConditionEditor->setText("");
+ m_pConditionEditor->setEnabled(false);
+ m_pTextEditor->setText("");
+ m_pTextEditor->setEnabled(false);
+ m_pEditor->setText("");
+ m_pEditor->setEnabled(false);
+ m_pNameEditor->setText("");
+ m_pExtNameEditor->setText("");
+ m_pExtNameEditor->setEnabled(false);
+ }
+ m_pListView->setEnabled(it);
+ m_pNameEditor->setEnabled(it);
+ m_pMenuButton->setEnabled(it);
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+KviMenuListViewItem::KviMenuListViewItem(KviTalListView * par,KviKvsPopupMenu * popup)
+: KviTalListViewItem(par)
+{
+ setPixmap(0,*(g_pIconManager->getSmallIcon(KVI_SMALLICON_POPUP)));
+ setText(0,popup->name());
+ m_pPopup = popup;
+}
+
+KviMenuListViewItem::~KviMenuListViewItem()
+{
+ delete m_pPopup;
+}
+
+void KviMenuListViewItem::replacePopup(KviKvsPopupMenu * popup)
+{
+ delete m_pPopup;
+ m_pPopup = popup;
+}
+
+
+KviPopupEditor::KviPopupEditor(QWidget * par)
+: QWidget(par)
+{
+ QGridLayout * l = new QGridLayout(this,1,1,0,2);
+#ifdef COMPILE_USE_QT4
+ QSplitter * spl = new QSplitter(Qt::Horizontal,this,"popupeditor");
+ spl->setOpaqueResize(false);
+#else
+ QSplitter * spl = new QSplitter(QSplitter::Horizontal,this);
+#endif
+ l->addWidget(spl,0,0);
+
+ KviTalVBox * box = new KviTalVBox(spl);
+
+ m_pListView = new KviTalListView(box);
+ m_pListView->addColumn(__tr2qs("Popup"));
+ m_pListView->setSelectionMode(KviTalListView::Extended);
+ m_pListView->setShowSortIndicator(true);
+
+ QPushButton * pb = new QPushButton(__tr2qs("&Export All To..."),box);
+ connect(pb,SIGNAL(clicked()),this,SLOT(exportAll()));
+ QPushButton * gn = new QPushButton(__tr2qs("&Export selected To..."),box);
+ connect(gn,SIGNAL(clicked()),this,SLOT(exportSelected()));
+
+ m_pEditor = new KviSinglePopupEditor(spl);
+
+ m_bOneTimeSetupDone = false;
+ m_pLastEditedItem = 0;
+
+ m_pContextPopup = new KviTalPopupMenu(this);
+
+ currentItemChanged(0);
+}
+
+KviPopupEditor::~KviPopupEditor()
+{
+}
+
+void KviPopupEditor::oneTimeSetup()
+{
+ if(m_bOneTimeSetupDone)return;
+ m_bOneTimeSetupDone = true;
+
+ const KviPointerHashTable<QString,KviKvsPopupMenu> * a = KviKvsPopupManager::instance()->popupDict();
+ if(!a)return;
+
+ KviPointerHashTableIterator<QString,KviKvsPopupMenu> it(*a);
+
+ KviMenuListViewItem * item;
+
+ while(it.current())
+ {
+ KviKvsPopupMenu * popup = it.current();
+ KviKvsPopupMenu * copy = new KviKvsPopupMenu(popup->popupName());
+ copy->copyFrom(popup);
+ item = new KviMenuListViewItem(m_pListView,copy);
+ ++it;
+ }
+
+ connect(m_pListView,SIGNAL(currentChanged(KviTalListViewItem *)),this,SLOT(currentItemChanged(KviTalListViewItem *)));
+ connect(m_pListView,SIGNAL(rightButtonPressed(KviTalListViewItem *,const QPoint &,int)),
+ this,SLOT(itemPressed(KviTalListViewItem *,const QPoint &,int)));
+
+}
+
+void KviPopupEditor::itemPressed(KviTalListViewItem *it,const QPoint &pnt,int col)
+{
+ __range_valid(m_bOneTimeSetupDone);
+ m_pContextPopup->clear();
+
+ m_pContextPopup->insertItem(
+ *(g_pIconManager->getSmallIcon(KVI_SMALLICON_POPUP)),
+ __tr2qs("&New Popup"),
+ this,SLOT(newPopup()));
+
+ m_pContextPopup->setItemEnabled(
+ m_pContextPopup->insertItem(
+ *(g_pIconManager->getSmallIcon(KVI_SMALLICON_QUIT)),
+ __tr2qs("Re&move Popup"),
+ this,SLOT(removeCurrentPopup())),
+ it);
+
+ m_pContextPopup->setItemEnabled(
+ m_pContextPopup->insertItem(
+ *(g_pIconManager->getSmallIcon(KVI_SMALLICON_FOLDER)),
+ __tr2qs("&Export Popup To..."),
+ this,SLOT(exportCurrentPopup())),
+ it);
+
+ m_pContextPopup->popup(pnt);
+}
+
+
+void KviPopupEditor::exportCurrentPopup()
+{
+ if(!m_pLastEditedItem)return;
+ saveLastEditedItem();
+ if(!m_pLastEditedItem)return;
+
+ QString szName = QDir::homeDirPath();
+ if(!szName.endsWith(QString(KVI_PATH_SEPARATOR)))szName += KVI_PATH_SEPARATOR;
+ szName += m_pLastEditedItem->popup()->name();
+ szName += ".kvs";
+
+ QString szFile;
+
+ if(!KviFileDialog::askForSaveFileName(szFile,__tr2qs("Choose a Filename - KVIrc"),szName,"*.kvs",true,true,true))return;
+
+ QString szOut;
+ m_pLastEditedItem->popup()->generateDefPopup(szOut);
+
+ if(!KviFileUtils::writeFile(szFile,szOut))
+ {
+ QMessageBox::warning(this,__tr2qs("Write Failed - KVIrc"),__tr2qs("Unable to write to the popup file."),__tr2qs("Ok"));
+ }
+}
+
+void KviPopupEditor::exportAll()
+{
+ bool bSelectedOnly=true;
+ exportPopups(bSelectedOnly);
+}
+
+void KviPopupEditor::exportSelected()
+{
+ bool bSelectedOnly=false;
+ exportPopups(bSelectedOnly);
+}
+
+void KviPopupEditor::exportPopups(bool bSelectedOnly)
+{
+ saveLastEditedItem();
+
+ KviMenuListViewItem * it = (KviMenuListViewItem *)m_pListView->firstChild();
+
+ QString out;
+
+ int count=0;
+ KviTalListViewItemIterator itv( m_pListView );
+ while( itv.current() )
+ {
+ if ( (itv.current()->isSelected()) || (bSelectedOnly == true) )
+ {
+ count ++;
+ QString tmp;
+ it->popup()->generateDefPopup(tmp);
+ out += tmp;
+ out += "\n";
+ }
+ it = (KviMenuListViewItem *)it->nextSibling();
+ ++itv;
+ }
+ if (!count && bSelectedOnly==false) return;
+
+ QString szName = QDir::homeDirPath();
+ if(!szName.endsWith(QString(KVI_PATH_SEPARATOR)))szName += KVI_PATH_SEPARATOR;
+ szName += "popups.kvs";
+
+ QString szFile;
+
+ if(!KviFileDialog::askForSaveFileName(szFile,__tr2qs("Choose a Filename - KVIrc"),szName,"*.kvs",true,true,true))return;
+
+ if(!KviFileUtils::writeFile(szFile,out))
+ {
+ QMessageBox::warning(this,__tr2qs("Write Failed - KVIrc"),__tr2qs("Unable to write to the alias file."),__tr2qs("Ok"));
+ }
+}
+
+
+void KviPopupEditor::removeCurrentPopup()
+{
+ if(m_pLastEditedItem)
+ {
+ KviMenuListViewItem * it = m_pLastEditedItem;
+ m_pLastEditedItem = 0;
+ delete it;
+ if(!m_pLastEditedItem)currentItemChanged(0);
+ }
+}
+
+void KviPopupEditor::newPopup()
+{
+ QString newName;
+ getUniquePopupName(0,newName);
+ KviMenuListViewItem * it = new KviMenuListViewItem(m_pListView,new KviKvsPopupMenu(newName));
+ m_pListView->setCurrentItem(it);
+}
+
+void KviPopupEditor::saveLastEditedItem()
+{
+ if(m_pLastEditedItem == 0)return;
+
+ KviKvsPopupMenu * m = m_pEditor->getMenu();
+ QString tmp = m->popupName();
+ QString old = m_pLastEditedItem->m_pPopup->popupName();
+ if(!KviQString::equalCI(tmp,old))
+ {
+ getUniquePopupName(m_pLastEditedItem,tmp);
+ m->setPopupName(tmp);
+ }
+
+ m_pLastEditedItem->replacePopup(m);
+ m_pLastEditedItem->setText(0,m->popupName());
+}
+
+void KviPopupEditor::currentItemChanged(KviTalListViewItem *it)
+{
+ saveLastEditedItem();
+
+ m_pLastEditedItem = (KviMenuListViewItem *)it;
+
+ m_pEditor->edit(m_pLastEditedItem);
+}
+
+void KviPopupEditor::showEvent(QShowEvent *e)
+{
+ oneTimeSetup();
+ QWidget::showEvent(e);
+}
+
+void KviPopupEditor::commit()
+{
+ if(!m_bOneTimeSetupDone)return;
+
+ saveLastEditedItem();
+
+ //KviKvsPopupManager::instance()->clear();
+
+ KviMenuListViewItem * it = (KviMenuListViewItem *)m_pListView->firstChild();
+
+ // Copy the original popup dict
+ KviPointerHashTable<QString,KviKvsPopupMenu> copy(*(KviKvsPopupManager::instance()->popupDict()));
+ copy.setAutoDelete(false);
+
+ while(it)
+ {
+ KviKvsPopupMenu * p = KviKvsPopupManager::instance()->get(it->m_pPopup->popupName());
+ p->doClear();
+ p->copyFrom(it->m_pPopup);
+ it = (KviMenuListViewItem *)it->nextSibling();
+ // remove it from the original copy
+ copy.remove(p->popupName());
+ }
+
+ // the remaining elements in the copy need to be removed from
+ // the "new" dictionary (they are no longer used)
+ KviPointerHashTableIterator<QString,KviKvsPopupMenu> iter(copy);
+
+ while(iter.current())
+ {
+ KviKvsPopupManager::instance()->remove(iter.currentKey());
+ ++iter;
+ }
+
+
+ g_pApp->savePopups();
+}
+
+
+void KviPopupEditor::getUniquePopupName(KviMenuListViewItem *item,QString &buffer)
+{
+ __range_valid(m_bOneTimeSetupDone);
+
+ if(buffer.isEmpty())buffer = __tr2qs("unnamed");
+ QString newName = buffer;
+
+ bool bFound = true;
+ int idx = 1;
+
+ while(bFound)
+ {
+ bFound = false;
+
+ for(KviMenuListViewItem * ch = (KviMenuListViewItem *)(m_pListView->firstChild());ch;ch = (KviMenuListViewItem *)ch->nextSibling())
+ {
+ if(KviQString::equalCI(newName,ch->m_pPopup->popupName()) && (ch != item))
+ {
+ bFound = true;
+ KviQString::sprintf(newName,"%Q.%d",&buffer,idx);
+ idx++;
+ break;
+ }
+ }
+
+ }
+
+ buffer = newName;
+}
+
+
+
+KviPopupEditorWindow::KviPopupEditorWindow(KviFrame * lpFrm)
+: KviWindow(KVI_WINDOW_TYPE_SCRIPTEDITOR,lpFrm,"popupeditor",0)
+{
+ g_pPopupEditorWindow = this;
+
+ m_pEditor = new KviPopupEditor(this);
+
+ m_pBase = new QWidget(this);
+ QGridLayout * g = new QGridLayout(m_pBase,1,4,4,4);
+
+ QPushButton * btn = new QPushButton(__tr2qs("&OK"),m_pBase);
+ connect(btn,SIGNAL(clicked()),this,SLOT(okClicked()));
+ btn->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_ACCEPT)));
+ g->addWidget(btn,0,1);
+
+ btn = new QPushButton(__tr2qs("&Apply"),m_pBase);
+ connect(btn,SIGNAL(clicked()),this,SLOT(applyClicked()));
+ btn->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_ACCEPT)));
+ g->addWidget(btn,0,2);
+
+ btn = new QPushButton(__tr2qs("Cancel"),m_pBase);
+ connect(btn,SIGNAL(clicked()),this,SLOT(cancelClicked()));
+ btn->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_DISCARD)));
+ g->addWidget(btn,0,3);
+
+ g->setColStretch(0,1);
+}
+
+KviPopupEditorWindow::~KviPopupEditorWindow()
+{
+ g_pPopupEditorWindow = 0;
+}
+
+void KviPopupEditorWindow::okClicked()
+{
+ m_pEditor->commit();
+ close();
+}
+
+void KviPopupEditorWindow::applyClicked()
+{
+ m_pEditor->commit();
+}
+
+void KviPopupEditorWindow::cancelClicked()
+{
+ close();
+}
+
+
+QPixmap * KviPopupEditorWindow::myIconPtr()
+{
+ return g_pIconManager->getSmallIcon(KVI_SMALLICON_POPUP);
+}
+
+void KviPopupEditorWindow::resizeEvent(QResizeEvent *e)
+{
+ int hght = m_pBase->sizeHint().height();
+ m_pEditor->setGeometry(0,0,width(),height()- hght);
+ m_pBase->setGeometry(0,height() - hght,width(),hght);
+}
+
+void KviPopupEditorWindow::fillCaptionBuffers()
+{
+ m_szPlainTextCaption = __tr2qs("Popup Editor");
+
+ static QString p1("<nobr><font color=\"");
+ static QString p2("\"><b>");
+ static QString p3("</b></font></nobr>");
+
+ m_szHtmlActiveCaption = p1;
+ m_szHtmlActiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextActive).name();
+ m_szHtmlActiveCaption += p2;
+ m_szHtmlActiveCaption += m_szPlainTextCaption;
+ m_szHtmlActiveCaption += p3;
+
+ m_szHtmlInactiveCaption = p1;
+ m_szHtmlInactiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextInactive).name();
+ m_szHtmlInactiveCaption += p2;
+ m_szHtmlInactiveCaption += m_szPlainTextCaption;
+ m_szHtmlInactiveCaption += p3;
+
+}
+
+
+void KviPopupEditorWindow::getConfigGroupName(KviStr &szName)
+{
+ szName = "popupeditor";
+}
+
+
+void KviPopupEditorWindow::saveProperties(KviConfig *cfg)
+{
+/*
+#ifdef COMPILE_SCRIPTTOOLBAR
+ cfg->writeEntry("Sizes",m_pEditor->sizes());
+ cfg->writeEntry("LastPopup",m_pEditor->lastEditedPopup().ptr());
+ //debug("LAST EDITED=%s",m_pEditor->lastEditedPopup().ptr());
+#endif // COMPILE_SCRIPTTOOLBAR
+*/
+}
+
+void KviPopupEditorWindow::loadProperties(KviConfig *cfg)
+{
+/*
+#ifdef COMPILE_SCRIPTTOOLBAR
+ QValueList<int> def;
+ def.append(20);
+ def.append(80);
+ m_pEditor->setSizes(cfg->readIntListEntry("Sizes",def));
+ KviStr tmp = cfg->readEntry("LastPopup","");
+ m_pEditor->editPopup(tmp);
+ //debug("LAST EDITED WAS %s",tmp.ptr());
+#endif // COMPILE_SCRIPTTOOLBAR
+*/
+}
diff --git a/src/modules/popupeditor/popupeditor.h b/src/modules/popupeditor/popupeditor.h
new file mode 100644
index 00000000..3560ffa7
--- /dev/null
+++ b/src/modules/popupeditor/popupeditor.h
@@ -0,0 +1,206 @@
+#ifndef _POPUPEDITOR_H_
+#define _POPUPEDITOR_H_
+//
+// File : popupeditor.h
+// Creation date : Mon Dec 23 2002 20:24:55 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the linkss of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) 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.
+//
+
+#include "kvi_window.h"
+#include "kvi_string.h"
+
+
+#include <qwidget.h>
+#include "kvi_tal_listview.h"
+#include <qlineedit.h>
+#include "kvi_tal_popupmenu.h"
+#include <qpushbutton.h>
+
+class KviKvsPopupMenu;
+class KviKvsPopupMenuItem;
+
+// KviPopupListViewItem
+class KviPopupListViewItem : public KviTalListViewItem
+{
+public:
+ enum Type { Item , Menu , Separator , Label , Epilogue , Prologue , ExtMenu };
+public:
+ KviPopupListViewItem(KviTalListView * pListView,KviPopupListViewItem * after,Type t);
+ KviPopupListViewItem(KviPopupListViewItem * parent,KviPopupListViewItem * after,Type t);
+public:
+ Type m_type;
+ QString m_szText;
+ QString m_szCondition;
+ QString m_szIcon;
+ QString m_szCode;
+ QString m_szId;
+private:
+ void init();
+public:
+ void setItemText(const QString & szText);
+ void setCondition(const QString & szCondition);
+ void setIcon(const QString & szIcon);
+ void setCode(const QString & szCode);
+ void setId(const QString & szId);
+};
+
+
+
+class KviScriptEditor;
+
+class KviMenuListViewItem;
+
+class KviSinglePopupEditor : public QWidget
+{
+ Q_OBJECT
+public:
+ KviSinglePopupEditor(QWidget * par);
+ ~KviSinglePopupEditor();
+protected:
+ QPushButton * m_pMenuButton;
+ KviKvsPopupMenu * m_pClipboard;
+ KviKvsPopupMenu * m_pTestPopup;
+ KviPopupListViewItem * m_pLastSelectedItem;
+ KviTalListView * m_pListView;
+ QLineEdit * m_pNameEditor;
+ KviScriptEditor * m_pEditor;
+ QLineEdit * m_pTextEditor;
+ QLineEdit * m_pIdEditor;
+ QLineEdit * m_pIconEditor;
+ QLineEdit * m_pConditionEditor;
+ QLineEdit * m_pExtNameEditor;
+ KviTalPopupMenu * m_pContextPopup;
+public:
+ void edit(KviMenuListViewItem * it);
+ KviKvsPopupMenu * getMenu();
+protected:
+ // theItem is the item above the first item that has to be inserted
+ void populateMenu(KviKvsPopupMenu * pop,KviPopupListViewItem * par,KviPopupListViewItem * theItem = 0);
+ void saveLastSelectedItem();
+ void addItemToMenu(KviKvsPopupMenu * pop,KviPopupListViewItem * par);
+ KviPopupListViewItem * newItem(KviPopupListViewItem * par,KviPopupListViewItem * after,KviPopupListViewItem::Type t);
+ KviPopupListViewItem * newItemBelow(KviPopupListViewItem * it,KviPopupListViewItem::Type t);
+ KviPopupListViewItem * newItemAbove(KviPopupListViewItem * it,KviPopupListViewItem::Type t);
+ KviPopupListViewItem * newItemInside(KviPopupListViewItem * it,KviPopupListViewItem::Type t);
+ void createNewItemAboveLastSelected(KviPopupListViewItem::Type t);
+ void createNewItemBelowLastSelected(KviPopupListViewItem::Type t);
+ void createNewItemInsideLastSelected(KviPopupListViewItem::Type t);
+ KviPopupListViewItem * findMatchingItem(KviKvsPopupMenuItem * it,KviPopupListViewItem * item);
+protected slots:
+ void contextCut();
+ void contextCopy();
+ void contextPasteBelow();
+ void contextPasteAbove();
+ void contextPasteInside();
+ void contextNewSeparatorBelow();
+ void contextNewSeparatorAbove();
+ void contextNewSeparatorInside();
+ void contextNewItemBelow();
+ void contextNewItemAbove();
+ void contextNewItemInside();
+ void contextNewMenuBelow();
+ void contextNewMenuAbove();
+ void contextNewMenuInside();
+ void contextNewExtMenuBelow();
+ void contextNewExtMenuAbove();
+ void contextNewExtMenuInside();
+ void contextNewLabelBelow();
+ void contextNewLabelAbove();
+ void contextNewLabelInside();
+ void contextNewPrologue();
+ void contextNewEpilogue();
+ void selectionChanged(KviTalListViewItem * it);
+ void itemPressed(KviTalListViewItem *it,const QPoint &pnt,int col);
+ void testPopup();
+ void testModeMenuItemClicked(KviKvsPopupMenuItem * it);
+};
+
+
+
+class KviMenuListViewItem : public KviTalListViewItem
+{
+public:
+ KviMenuListViewItem(KviTalListView * par,KviKvsPopupMenu * popup);
+ ~KviMenuListViewItem();
+public:
+ KviKvsPopupMenu * m_pPopup;
+public:
+ KviKvsPopupMenu * popup(){ return m_pPopup; };
+public:
+ void replacePopup(KviKvsPopupMenu * popup);
+};
+
+
+class KviPopupEditor : public QWidget
+{
+ Q_OBJECT
+public:
+ KviPopupEditor(QWidget * par);
+ ~KviPopupEditor();
+public:
+ KviSinglePopupEditor * m_pEditor;
+ KviTalListView * m_pListView;
+ KviMenuListViewItem * m_pLastEditedItem;
+ bool m_bOneTimeSetupDone;
+ KviTalPopupMenu * m_pContextPopup;
+public:
+ void commit();
+ void exportPopups(bool);
+protected slots:
+ void currentItemChanged(KviTalListViewItem *it);
+ void newPopup();
+ void exportAll();
+ void exportSelected();
+ void exportCurrentPopup();
+ void removeCurrentPopup();
+ void itemPressed(KviTalListViewItem *it,const QPoint &pnt,int col);
+protected:
+ void showEvent(QShowEvent *e);
+ void getExportPopupBuffer(QString &buffer,KviMenuListViewItem * it);
+private:
+ void oneTimeSetup();
+ void saveLastEditedItem();
+ void getUniquePopupName(KviMenuListViewItem * it,QString &buffer);
+};
+
+
+
+class KviPopupEditorWindow : public KviWindow
+{
+ Q_OBJECT
+public:
+ KviPopupEditorWindow(KviFrame * lpFrm);
+ ~KviPopupEditorWindow();
+protected:
+ KviPopupEditor * m_pEditor;
+ QWidget * m_pBase;
+protected:
+ virtual QPixmap * myIconPtr();
+ virtual void fillCaptionBuffers();
+ virtual void resizeEvent(QResizeEvent *e);
+ virtual void getConfigGroupName(KviStr &szName);
+ virtual void saveProperties(KviConfig *);
+ virtual void loadProperties(KviConfig *);
+protected slots:
+ void cancelClicked();
+ void okClicked();
+ void applyClicked();
+};
+
+#endif //_POPUPEDITOR_H_
diff --git a/src/modules/raweditor/Makefile.am b/src/modules/raweditor/Makefile.am
new file mode 100644
index 00000000..74c64e9b
--- /dev/null
+++ b/src/modules/raweditor/Makefile.am
@@ -0,0 +1,17 @@
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkviraweditor.la
+
+libkviraweditor_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkviraweditor_la_SOURCES = libkviraweditor.cpp raweditor.cpp
+nodist_libkviraweditor_la_SOURCES = moc_raweditor.cpp
+
+noinst_HEADERS = raweditor.h
+libkviraweditor_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+# noinst_HEADERS=
+
+moc_raweditor.cpp: raweditor.h
+ $(SS_QT_MOC) $< -o $@
diff --git a/src/modules/raweditor/libkviraweditor.cpp b/src/modules/raweditor/libkviraweditor.cpp
new file mode 100644
index 00000000..9f6975f5
--- /dev/null
+++ b/src/modules/raweditor/libkviraweditor.cpp
@@ -0,0 +1,87 @@
+//
+// File : libkviraweditor.cpp
+// Creation date : Mon 23 Dec 2002 20:23:59 2002 GMT by Szymon Stefanek
+//
+// This toolbar is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_module.h"
+#include "kvi_locale.h"
+#include "kvi_frame.h"
+
+#include "raweditor.h"
+
+KviRawEditorWindow * g_pRawEditorWindow = 0;
+
+
+/*
+ @doc: raweditor.open
+ @type:
+ command
+ @title:
+ raweditor.open
+ @short:
+ Shows the raw events editor
+ @syntax:
+ toolbareditor.open
+ @description:
+ Opens the script raw events editor dialog.
+*/
+
+static bool raweditor_kvs_cmd_open(KviKvsModuleCommandCall * c)
+{
+ if(!g_pRawEditorWindow)
+ {
+ g_pRawEditorWindow = new KviRawEditorWindow(c->window()->frame());
+ c->window()->frame()->addWindow(g_pRawEditorWindow);
+ }
+ g_pRawEditorWindow->setFocus();
+ return true;
+}
+
+
+static bool raweditor_module_init(KviModule * m)
+{
+
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"open",raweditor_kvs_cmd_open);
+ g_pRawEditorWindow = 0;
+ return true;
+}
+
+static bool raweditor_module_can_unload(KviModule * m)
+{
+ return (g_pRawEditorWindow == 0);
+}
+
+static bool raweditor_module_cleanup(KviModule *m)
+{
+ if(g_pRawEditorWindow)delete g_pRawEditorWindow;
+ g_pRawEditorWindow = 0;
+ return true;
+}
+
+KVIRC_MODULE(
+ "RawEditor", // module name
+ "1.0.0", // module version
+ "Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot net)", // author & (C)
+ "Editor for the script raw events",
+ raweditor_module_init,
+ raweditor_module_can_unload,
+ 0,
+ raweditor_module_cleanup
+)
diff --git a/src/modules/raweditor/raweditor.cpp b/src/modules/raweditor/raweditor.cpp
new file mode 100644
index 00000000..72b3888b
--- /dev/null
+++ b/src/modules/raweditor/raweditor.cpp
@@ -0,0 +1,563 @@
+//
+// File : raweditor.cpp
+// Creation date : Mon Dec 23 2002 20:28:18 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the linkss of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) 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.
+//
+#include "raweditor.h"
+
+#include "kvi_iconmanager.h"
+#include "kvi_options.h"
+#include "kvi_locale.h"
+#include "kvi_imagedialog.h"
+#include "kvi_config.h"
+#include "kvi_filedialog.h"
+#include "kvi_fileutils.h"
+#include "kvi_scripteditor.h"
+#include "kvi_debug.h"
+//#include "kvi_event.h"
+#include "kvi_app.h"
+#include "kvi_cmdformatter.h"
+#include "kvi_kvs_eventmanager.h"
+#include "kvi_kvs_eventhandler.h"
+
+#include <qmessagebox.h>
+#include <qsplitter.h>
+#include <qlayout.h>
+#include "kvi_tal_vbox.h"
+#include "kvi_tal_popupmenu.h"
+#include <qtooltip.h>
+#include <qinputdialog.h>
+#include <qpushbutton.h>
+
+extern KviRawEditorWindow * g_pRawEditorWindow;
+
+
+
+KviRawListViewItem::KviRawListViewItem(KviTalListView *par,int idx)
+: KviTalListViewItem(par)
+{
+ m_iIdx = idx;
+ m_szName.setNum(idx);
+ if(idx < 100)m_szName.prepend('0');
+ if(idx < 10)m_szName.prepend('0');
+};
+
+const QPixmap * KviRawListViewItem::pixmap(int col) const
+{
+ return g_pIconManager->getSmallIcon(firstChild() ? KVI_SMALLICON_RAWEVENT : KVI_SMALLICON_RAWEVENTNOHANDLERS);
+}
+
+const QPixmap * KviRawHandlerListViewItem::pixmap(int col) const
+{
+ return g_pIconManager->getSmallIcon(m_bEnabled ? KVI_SMALLICON_HANDLER : KVI_SMALLICON_HANDLERDISABLED);
+}
+
+
+
+KviRawEditor::KviRawEditor(QWidget * par)
+: QWidget(par,"raw_event_editor")
+{
+ QGridLayout * l = new QGridLayout(this,1,1,2,2);
+#ifdef COMPILE_USE_QT4
+ QSplitter * spl = new QSplitter(Qt::Horizontal,this,"raweditorv");
+ spl->setOpaqueResize(false);
+#else
+ QSplitter * spl = new QSplitter(QSplitter::Horizontal,this);
+#endif
+ l->addWidget(spl,0,0);
+
+ KviTalVBox * boxi = new KviTalVBox(spl);
+ m_pListView = new KviTalListView(boxi);
+ m_pListView->addColumn(__tr2qs("Raw Event"));
+ m_pListView->setMultiSelection(false);
+ m_pListView->setShowSortIndicator(true);
+ m_pListView->setRootIsDecorated(true);
+
+ QPushButton * pb = new QPushButton(__tr2qs("&Export All To..."),boxi);
+ connect(pb,SIGNAL(clicked()),this,SLOT(exportAllEvents()));
+
+ KviTalVBox * box = new KviTalVBox(spl);
+ m_pNameEditor = new QLineEdit(box);
+ QToolTip::add(m_pNameEditor,__tr2qs("Edit the raw event handler name."));
+ m_pEditor = KviScriptEditor::createInstance(box);
+
+ m_bOneTimeSetupDone = false;
+ m_pLastEditedItem = 0;
+}
+
+KviRawEditor::~KviRawEditor()
+{
+ KviScriptEditor::destroyInstance(m_pEditor);
+}
+
+void KviRawEditor::oneTimeSetup()
+{
+ if(m_bOneTimeSetupDone)return;
+ m_bOneTimeSetupDone = true;
+
+ KviRawListViewItem * it;
+ KviRawHandlerListViewItem * ch;
+
+ for(unsigned int i = 0;i < 999;i++)
+ {
+ KviPointerList<KviKvsEventHandler> * l = KviKvsEventManager::instance()->rawHandlers(i);
+ if(l)
+ {
+ it = new KviRawListViewItem(m_pListView,i);
+ for(KviKvsEventHandler * s = l->first();s;s = l->next())
+ {
+ if(s->type() == KviKvsEventHandler::Script)
+ {
+ ch = new KviRawHandlerListViewItem(it,((KviKvsScriptEventHandler *)s)->name(),
+ ((KviKvsScriptEventHandler *)s)->code(),((KviKvsScriptEventHandler *)s)->isEnabled());
+ }
+ }
+ it->setOpen(true);
+ }
+ }
+
+
+ m_pContextPopup = new KviTalPopupMenu(this);
+
+ connect(m_pListView,SIGNAL(selectionChanged(KviTalListViewItem *)),this,SLOT(selectionChanged(KviTalListViewItem *)));
+ connect(m_pListView,SIGNAL(rightButtonPressed(KviTalListViewItem *,const QPoint &,int)),
+ this,SLOT(itemPressed(KviTalListViewItem *,const QPoint &,int)));
+}
+
+void KviRawEditor::itemPressed(KviTalListViewItem *it,const QPoint &pnt,int col)
+{
+ __range_valid(m_bOneTimeSetupDone);
+ m_pContextPopup->clear();
+ if(it)
+ {
+ if(it->parent())
+ {
+ if(!(((KviRawHandlerListViewItem *)it)->m_bEnabled))
+ m_pContextPopup->insertItem(
+ *(g_pIconManager->getSmallIcon(KVI_SMALLICON_HANDLER)),
+ __tr2qs("&Enable Handler"),this,SLOT(toggleCurrentHandlerEnabled()));
+ else
+ m_pContextPopup->insertItem(
+ *(g_pIconManager->getSmallIcon(KVI_SMALLICON_HANDLERDISABLED)),
+ __tr2qs("&Disable Handler"),this,SLOT(toggleCurrentHandlerEnabled()));
+
+ m_pContextPopup->insertItem(
+ *(g_pIconManager->getSmallIcon(KVI_SMALLICON_QUIT)),
+ __tr2qs("Re&move Handler"),
+ this,SLOT(removeCurrentHandler()));
+ m_pContextPopup->insertItem(
+ *(g_pIconManager->getSmallIcon(KVI_SMALLICON_FOLDER)),
+ __tr2qs("&Export Handler To..."),
+ this,SLOT(exportCurrentHandler()));
+ } else {
+ m_pContextPopup->insertItem(
+ *(g_pIconManager->getSmallIcon(KVI_SMALLICON_HANDLER)),
+ __tr2qs("&New Handler"),
+ this,SLOT(addHandlerForCurrentRaw()));
+ }
+ }
+
+ m_pContextPopup->insertSeparator();
+ m_pContextPopup->insertItem(
+ *(g_pIconManager->getSmallIcon(KVI_SMALLICON_RAWEVENT)),
+ __tr2qs("&Add Raw Event..."),
+ this,SLOT(addRaw()));
+
+ m_pContextPopup->popup(pnt);
+}
+
+void KviRawEditor::getUniqueHandlerName(KviRawListViewItem *it,QString &buffer)
+{
+ __range_valid(m_bOneTimeSetupDone);
+
+ QString newName = buffer;
+ if(newName.isEmpty())newName = __tr2qs("unnamed");
+
+ bool bFound = true;
+ int idx = 1;
+
+ while(bFound)
+ {
+ bFound = false;
+
+ for(KviRawHandlerListViewItem * ch = (KviRawHandlerListViewItem *)(it->firstChild());ch;ch = (KviRawHandlerListViewItem *)ch->nextSibling())
+ {
+ if(KviQString::equalCI(newName,ch->m_szName))
+ {
+ bFound = true;
+ KviQString::sprintf(newName,"%Q_%d",&buffer,idx);
+ idx++;
+ break;
+ }
+ }
+
+ }
+
+ buffer = newName;
+}
+
+void KviRawEditor::addRaw()
+{
+ bool bOk = false;
+
+ int iIdx = QInputDialog::getInteger(__tr2qs("New Raw Event"),__tr2qs("Enter the numeric code of the message (0-999)"),0,0,999,1,&bOk,this);
+
+ if(!bOk)return;
+
+ KviRawListViewItem * it;
+ for(it = (KviRawListViewItem *)m_pListView->firstChild();it;it = (KviRawListViewItem *)it->nextSibling())
+ {
+ if(it->m_iIdx == iIdx)
+ {
+ m_pListView->setSelected(it,true);
+ goto add_handler;
+ }
+ }
+
+ it = new KviRawListViewItem(m_pListView,iIdx);
+ m_pListView->setSelected(it,true);
+
+add_handler:
+ addHandlerForCurrentRaw();
+
+}
+
+void KviRawEditor::addHandlerForCurrentRaw()
+{
+ __range_valid(m_pOneTimeSetupDone);
+
+ KviTalListViewItem * it = m_pListView->selectedItem();
+ if(it)
+ {
+ if(it->parent() == 0)
+ {
+ QString buffer = __tr2qs("default");
+ getUniqueHandlerName((KviRawListViewItem *)it,buffer);
+ KviTalListViewItem * ch = new KviRawHandlerListViewItem(it,buffer,"",true);
+ it->setOpen(true);
+ m_pListView->setSelected(ch,true);
+ }
+ }
+}
+
+void KviRawEditor::removeCurrentHandler()
+{
+ __range_valid(m_pOneTimeSetupDone);
+ if(m_pLastEditedItem)
+ {
+ KviTalListViewItem * it = m_pLastEditedItem;
+ m_pLastEditedItem = 0;
+ delete it;
+ m_pEditor->setEnabled(false);
+ m_pNameEditor->setEnabled(false);
+ }
+}
+
+void KviRawEditor::toggleCurrentHandlerEnabled()
+{
+ __range_valid(m_pOneTimeSetupDone);
+ if(m_pLastEditedItem)
+ {
+ m_pLastEditedItem->m_bEnabled = !(m_pLastEditedItem->m_bEnabled);
+ m_pListView->repaintItem(m_pLastEditedItem);
+ selectionChanged(m_pLastEditedItem);
+ }
+}
+
+void KviRawEditor::commit()
+{
+ if(!m_bOneTimeSetupDone)return; // nothing to commit
+
+ saveLastEditedItem();
+ KviKvsEventManager::instance()->removeAllScriptRawHandlers();
+ for(KviTalListViewItem * it = m_pListView->firstChild();it;it = it->nextSibling())
+ {
+ if(it->firstChild())
+ {
+ QString szContext;
+ for(KviTalListViewItem * ch = it->firstChild();ch;ch = ch->nextSibling())
+ {
+
+ KviQString::sprintf(szContext,"RawEvent%d::%Q",&(((KviRawListViewItem *)it)->m_iIdx),&(((KviRawHandlerListViewItem *)ch)->m_szName));
+ KviKvsScriptEventHandler * s = new KviKvsScriptEventHandler(
+ ((KviRawHandlerListViewItem *)ch)->m_szName,
+ szContext,
+ ((KviRawHandlerListViewItem *)ch)->m_szBuffer,
+ ((KviRawHandlerListViewItem *)ch)->m_bEnabled
+ );
+
+ KviKvsEventManager::instance()->addRawHandler(((KviRawListViewItem *)it)->m_iIdx,s);
+ }
+ }
+ }
+
+ g_pApp->saveRawEvents(); // otherwise this page has never been shown
+}
+
+void KviRawEditor::saveLastEditedItem()
+{
+ __range_valid(m_bOneTimeSetupDone);
+ if(!m_pLastEditedItem)return;
+
+ QString buffer = m_pNameEditor->text();
+ if(!KviQString::equalCI(buffer,m_pLastEditedItem->m_szName))
+ {
+ getUniqueHandlerName((KviRawListViewItem *)(m_pLastEditedItem->parent()),buffer);
+ }
+
+ m_pLastEditedItem->m_szName = buffer;
+ QString tmp;
+ m_pEditor->getText(tmp);
+
+ m_pLastEditedItem->m_szBuffer = tmp;
+}
+
+void KviRawEditor::selectionChanged(KviTalListViewItem * it)
+{
+ __range_valid(m_bOneTimeSetupDone);
+ saveLastEditedItem();
+ if(it->parent())
+ {
+ m_pLastEditedItem = (KviRawHandlerListViewItem *)it;
+ m_pNameEditor->setEnabled(true);
+ m_pNameEditor->setText(it->text(0));
+ m_pEditor->setEnabled(true);
+ m_pEditor->setText(((KviRawHandlerListViewItem *)it)->m_szBuffer);
+ } else {
+ m_pLastEditedItem = 0;
+ m_pNameEditor->setEnabled(false);
+ m_pNameEditor->setText("");
+ m_pEditor->setEnabled(false);
+ }
+}
+
+void KviRawEditor::showEvent(QShowEvent *e)
+{
+ oneTimeSetup();
+ QWidget::showEvent(e);
+}
+
+void KviRawEditor::getExportEventBuffer(QString &buffer,KviRawHandlerListViewItem * it)
+{
+ if(!it->parent())return;
+
+ QString szBuf = it->m_szBuffer;
+
+ KviCommandFormatter::blockFromBuffer(szBuf);
+
+ buffer = "event(";
+ buffer += ((KviRawListViewItem *)(it->parent()))->m_szName;
+ buffer += ",";
+ buffer += it->m_szName;
+ buffer += ")\n";
+ buffer += szBuf;
+ buffer += "\n";
+
+ if(!it->m_bEnabled)
+ {
+ buffer += "\n";
+ buffer += "eventctl -d ";
+ buffer += ((KviRawListViewItem *)(it->parent()))->m_szName;
+ buffer += " ";
+ buffer += it->m_szName;
+ }
+}
+
+void KviRawEditor::exportCurrentHandler()
+{
+ if(!m_pLastEditedItem)return;
+ saveLastEditedItem();
+ if(!m_pLastEditedItem)return;
+
+ QString szName = QDir::homeDirPath();
+ if(!szName.endsWith(QString(KVI_PATH_SEPARATOR)))szName += KVI_PATH_SEPARATOR;
+ szName += "raw";
+ szName += ((KviRawListViewItem *)(m_pLastEditedItem->parent()))->m_szName;
+ szName += ".";
+ szName += m_pLastEditedItem->m_szName;
+ szName += ".kvs";
+
+ QString szFile;
+
+ if(!KviFileDialog::askForSaveFileName(szFile,__tr2qs("Choose a Filename - KVIrc"),szName,"*.kvs",true,true,true))return;
+
+ QString szOut;
+ getExportEventBuffer(szOut,m_pLastEditedItem);
+
+ if(!KviFileUtils::writeFile(szFile,szOut))
+ {
+ QMessageBox::warning(this,__tr2qs("Write Failed - KVIrc"),__tr2qs("Unable to write to the raw event file."),__tr2qs("&OK"));
+ }
+}
+
+void KviRawEditor::exportAllEvents()
+{
+ saveLastEditedItem();
+
+ KviRawListViewItem * it = (KviRawListViewItem *)m_pListView->firstChild();
+
+ QString out;
+
+ while(it)
+ {
+ KviRawHandlerListViewItem * item = (KviRawHandlerListViewItem *)it->firstChild();
+ while(item)
+ {
+ QString tmp;
+ getExportEventBuffer(tmp,item);
+ out += tmp;
+ out += "\n";
+ item = (KviRawHandlerListViewItem *)item->nextSibling();
+ }
+ it = (KviRawListViewItem *)it->nextSibling();
+ }
+
+ QString szName = QDir::homeDirPath();
+ if(!szName.endsWith(QString(KVI_PATH_SEPARATOR)))szName += KVI_PATH_SEPARATOR;
+ szName += "rawevents.kvs";
+
+ QString szFile;
+
+ if(!KviFileDialog::askForSaveFileName(szFile,__tr2qs("Choose a Filename - KVIrc"),szName,"*.kvs",true,true,true))return;
+
+ if(!KviFileUtils::writeFile(szFile,out))
+ {
+ QMessageBox::warning(this,__tr2qs("Write Failed - KVIrc"),__tr2qs("Unable to write to the raw events file."),__tr2qs("Ok"));
+ }
+}
+
+
+
+
+KviRawEditorWindow::KviRawEditorWindow(KviFrame * lpFrm)
+: KviWindow(KVI_WINDOW_TYPE_SCRIPTEDITOR,lpFrm,"raweditor",0)
+{
+ g_pRawEditorWindow = this;
+
+ m_pEditor = new KviRawEditor(this);
+
+ m_pBase = new QWidget(this);
+ QGridLayout * g = new QGridLayout(m_pBase,1,4,4,4);
+
+ QPushButton * btn = new QPushButton(__tr2qs("&OK"),m_pBase);
+ connect(btn,SIGNAL(clicked()),this,SLOT(okClicked()));
+ btn->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_ACCEPT)));
+ g->addWidget(btn,0,1);
+
+ btn = new QPushButton(__tr2qs("&Apply"),m_pBase);
+ connect(btn,SIGNAL(clicked()),this,SLOT(applyClicked()));
+ btn->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_ACCEPT)));
+ g->addWidget(btn,0,2);
+
+ btn = new QPushButton(__tr2qs("Cancel"),m_pBase);
+ connect(btn,SIGNAL(clicked()),this,SLOT(cancelClicked()));
+ btn->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_DISCARD)));
+ g->addWidget(btn,0,3);
+
+ g->setColStretch(0,1);
+}
+
+KviRawEditorWindow::~KviRawEditorWindow()
+{
+ g_pRawEditorWindow = 0;
+}
+
+void KviRawEditorWindow::okClicked()
+{
+ m_pEditor->commit();
+ close();
+}
+
+void KviRawEditorWindow::applyClicked()
+{
+ m_pEditor->commit();
+}
+
+void KviRawEditorWindow::cancelClicked()
+{
+ close();
+}
+
+
+QPixmap * KviRawEditorWindow::myIconPtr()
+{
+ return g_pIconManager->getSmallIcon(KVI_SMALLICON_RAWEVENT);
+}
+
+void KviRawEditorWindow::resizeEvent(QResizeEvent *e)
+{
+ int hght = m_pBase->sizeHint().height();
+ m_pEditor->setGeometry(0,0,width(),height()- hght);
+ m_pBase->setGeometry(0,height() - hght,width(),hght);
+}
+
+void KviRawEditorWindow::fillCaptionBuffers()
+{
+ m_szPlainTextCaption = __tr2qs("Raw Editor");
+
+ static QString p1("<nobr><font color=\"");
+ static QString p2("\"><b>");
+ static QString p3("</b></font></nobr>");
+
+ m_szHtmlActiveCaption = p1;
+ m_szHtmlActiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextActive).name();
+ m_szHtmlActiveCaption += p2;
+ m_szHtmlActiveCaption += m_szPlainTextCaption;
+ m_szHtmlActiveCaption += p3;
+
+ m_szHtmlInactiveCaption = p1;
+ m_szHtmlInactiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextInactive).name();
+ m_szHtmlInactiveCaption += p2;
+ m_szHtmlInactiveCaption += m_szPlainTextCaption;
+ m_szHtmlInactiveCaption += p3;
+
+}
+
+
+void KviRawEditorWindow::getConfigGroupName(KviStr &szName)
+{
+ szName = "raweditor";
+}
+
+
+void KviRawEditorWindow::saveProperties(KviConfig *cfg)
+{
+/*
+#ifdef COMPILE_SCRIPTTOOLBAR
+ cfg->writeEntry("Sizes",m_pEditor->sizes());
+ cfg->writeEntry("LastRaw",m_pEditor->lastEditedRaw().ptr());
+ //debug("LAST EDITED=%s",m_pEditor->lastEditedRaw().ptr());
+#endif // COMPILE_SCRIPTTOOLBAR
+*/
+}
+
+void KviRawEditorWindow::loadProperties(KviConfig *cfg)
+{
+/*
+#ifdef COMPILE_SCRIPTTOOLBAR
+ QValueList<int> def;
+ def.append(20);
+ def.append(80);
+ m_pEditor->setSizes(cfg->readIntListEntry("Sizes",def));
+ KviStr tmp = cfg->readEntry("LastRaw","");
+ m_pEditor->editRaw(tmp);
+ //debug("LAST EDITED WAS %s",tmp.ptr());
+#endif // COMPILE_SCRIPTTOOLBAR
+*/
+}
diff --git a/src/modules/raweditor/raweditor.h b/src/modules/raweditor/raweditor.h
new file mode 100644
index 00000000..7adf2213
--- /dev/null
+++ b/src/modules/raweditor/raweditor.h
@@ -0,0 +1,118 @@
+#ifndef _RAWEDITOR_H_
+#define _RAWEDITOR_H_
+//
+// File : eventeditor.h
+// Creation date : Mon Dec 23 2002 20:24:55 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the linkss of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) 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.
+//
+
+#include "kvi_window.h"
+#include "kvi_qstring.h"
+
+#include <qwidget.h>
+#include "kvi_tal_listview.h"
+#include <qlineedit.h>
+
+class KviScriptEditor;
+
+class KviRawListViewItem : public KviTalListViewItem
+{
+public:
+ int m_iIdx;
+ QString m_szName;
+public:
+ KviRawListViewItem(KviTalListView * par,int idx);
+ ~KviRawListViewItem() {};
+public:
+ virtual QString text(int col) const { return m_szName; };
+ virtual const QPixmap * pixmap(int col) const;
+};
+
+class KviRawHandlerListViewItem : public KviTalListViewItem
+{
+public:
+ KviRawHandlerListViewItem(KviTalListViewItem * par,const QString & name,const QString & buffer,bool bEnabled)
+ : KviTalListViewItem(par), m_szName(name) , m_szBuffer(buffer) , m_bEnabled(bEnabled) {};
+ ~KviRawHandlerListViewItem() {};
+public:
+ QString m_szName;
+ QString m_szBuffer;
+ bool m_bEnabled;
+ virtual QString text(int col) const { return m_szName; };
+ virtual const QPixmap * pixmap(int col) const;
+};
+
+class KviTalPopupMenu;
+
+class KviRawEditor : public QWidget
+{
+ Q_OBJECT
+public:
+ KviRawEditor(QWidget * par);
+ ~KviRawEditor();
+public:
+ KviScriptEditor * m_pEditor;
+ KviTalListView * m_pListView;
+ QLineEdit * m_pNameEditor;
+ KviTalPopupMenu * m_pContextPopup;
+ KviRawHandlerListViewItem * m_pLastEditedItem;
+ bool m_bOneTimeSetupDone;
+public:
+ void commit();
+ void saveLastEditedItem();
+ void getUniqueHandlerName(KviRawListViewItem *it,QString &buffer);
+ void getExportEventBuffer(QString &szBuffer,KviRawHandlerListViewItem * it);
+protected slots:
+ void selectionChanged(KviTalListViewItem *it);
+ void itemPressed(KviTalListViewItem *it,const QPoint &pnt,int col);
+ void toggleCurrentHandlerEnabled();
+ void removeCurrentHandler();
+ void addHandlerForCurrentRaw();
+ void addRaw();
+ void exportAllEvents();
+ void exportCurrentHandler();
+protected:
+ void showEvent(QShowEvent *e);
+private:
+ void oneTimeSetup();
+};
+
+class KviRawEditorWindow : public KviWindow
+{
+ Q_OBJECT
+public:
+ KviRawEditorWindow(KviFrame * lpFrm);
+ ~KviRawEditorWindow();
+protected:
+ KviRawEditor * m_pEditor;
+ QWidget * m_pBase;
+protected:
+ virtual QPixmap * myIconPtr();
+ virtual void fillCaptionBuffers();
+ virtual void resizeEvent(QResizeEvent *e);
+ virtual void getConfigGroupName(KviStr &szName);
+ virtual void saveProperties(KviConfig *);
+ virtual void loadProperties(KviConfig *);
+protected slots:
+ void cancelClicked();
+ void okClicked();
+ void applyClicked();
+};
+
+#endif //_RAWEDITOR_H_
diff --git a/src/modules/regchan/Makefile.am b/src/modules/regchan/Makefile.am
new file mode 100644
index 00000000..c46f64aa
--- /dev/null
+++ b/src/modules/regchan/Makefile.am
@@ -0,0 +1,18 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkviregchan.la
+
+libkviregchan_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkviregchan_la_SOURCES = libkviregchan.cpp
+libkviregchan_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+#noinst_HEADERS= edituser.h
+
+%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
diff --git a/src/modules/regchan/libkviregchan.cpp b/src/modules/regchan/libkviregchan.cpp
new file mode 100644
index 00000000..eaa53268
--- /dev/null
+++ b/src/modules/regchan/libkviregchan.cpp
@@ -0,0 +1,426 @@
+//======================================================================================
+//
+// File : libkviregchan.cpp
+// Creation date : Sat Jun 29 02:55:18 2002 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//======================================================================================
+// incomplete
+#include "kvi_module.h"
+
+
+#include "kvi_regchan.h"
+#include "kvi_locale.h"
+#include "kvi_out.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_window.h"
+
+
+// kvi_app.cpp
+extern KVIRC_API KviRegisteredChannelDataBase * g_pRegisteredChannelDataBase;
+
+/*
+ @doc: regchan.add
+ @type:
+ command
+ @title:
+ regchan.add
+ @keyterms:
+ registering channels
+ @short:
+ Registers a channel
+ @syntax:
+ regchan.add <channel:string> [netmask:string]
+ @description:
+ Registers the <channel> with the specified [netmask].
+ [netmask] can be a full network name or a wildcard string
+ tht will be matched against network names.
+ For example, if you want to register #kvirc on IRCNet
+ you can use regchan.add #kvirc IRCNet.
+ If you want to handle #kvirc on all the IRC networks then
+ you can use regchan.add #kvirc *[br]
+ Obviously if you register both #kvirc/IRCNet and #kvirc/*
+ then #kvirc/IRCNet will be looked first.
+ If netmask is not passed a netmask of * is assumed.[br]
+ @examples:
+ [example]
+ regchan.add #kvirc openprojects
+ [/example]
+ @seealso:
+*/
+
+static bool regchan_kvs_cmd_add(KviKvsModuleCommandCall * c)
+{
+ QString szChan,szNetmask;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("channel name",KVS_PT_NONEMPTYSTRING,0,szChan)
+ KVSM_PARAMETER("netmask",KVS_PT_STRING,KVS_PF_OPTIONAL,szNetmask)
+ KVSM_PARAMETERS_END(c)
+ if(szNetmask.isEmpty())szNetmask="*";
+ g_pRegisteredChannelDataBase->add(new KviRegisteredChannel(szChan,szNetmask));
+ return true;
+}
+
+/*
+ @doc: regchan.remove
+ @type:
+ command
+ @title:
+ regchan.remove
+ @keyterms:
+ unregistering channels
+ @short:
+ Unregisters a channel
+ @syntax:
+ regchan.remove [-q|--quiet] [-e|--exactly] <channel:string> <network:string>
+ @description:
+ Unregisters the channel named <channel> that best matches <network>
+ with its netmask.[br]
+ If no match for <channel>/<network> is found in the database then
+ a warning is printed unless -q is used.[br]
+ If -e is specified then <network> is not matched against the
+ netmasks in the database but is compared directly. This means
+ that <network> must be exactly the netmask used to register a channel.
+ @examples:
+ [example]
+ regchan.remove #kvirc openprojects
+ [/example]
+ @seealso:
+ [cmd]regchan.add[/cmd]
+*/
+static bool regchan_kvs_cmd_remove(KviKvsModuleCommandCall * c)
+{
+ QString szChan,szNetwork;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("channel name",KVS_PT_NONEMPTYSTRING,0,szChan)
+ KVSM_PARAMETER("network",KVS_PT_NONEMPTYSTRING,0,szNetwork)
+ KVSM_PARAMETERS_END(c)
+ KviRegisteredChannel * ch;
+ if(c->hasSwitch('e',"exactly"))ch = g_pRegisteredChannelDataBase->findExact(szChan,szNetwork);
+ else ch = g_pRegisteredChannelDataBase->find(szChan,szNetwork);
+ if(ch)
+ {
+ g_pRegisteredChannelDataBase->remove(ch);
+ } else {
+ if(!c->hasSwitch('q',"quiet"))c->warning(__tr2qs("No such channel/netmask entry in the database"));
+ }
+ return true;
+}
+
+/*
+ @doc: regchan.setproperty
+ @type:
+ command
+ @title:
+ regchan.setproperty
+ @short:
+ Sets a property for a registered channel
+ @syntax:
+ regchan.setproperty [-e|--exactly] [-q|--quiet] <channel:string> <network:string> <property:string> <value:string>
+ @description:
+ Sets the <property> for the registered <channel> that best
+ matches <network> to <value>.[br]
+ If <value> is an empty string the <property> is removed.[br]
+ If no match for <channel>/<network> is found in the database then
+ a warning is printed unless -q is used.[br]
+ @switches:
+ !fn: -q|--quiet
+ No warning on screen.
+ !fn: -e|--exactly
+ If -e is specified then <network> is not matched against the
+ netmasks in the database but is compared directly. This means
+ that <network> must be exactly the netmask used to register a channel.
+ @examples:
+ [example]
+ regchan.setproperty #kvirc openprojects autojoin true
+ [/example]
+ @seealso:
+ [cmd]regchan.add[/cmd]
+*/
+
+static bool regchan_kvs_cmd_setProperty(KviKvsModuleCommandCall * c)
+{
+ QString szChan,szNetwork,szProperty,szValue;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("channel name",KVS_PT_NONEMPTYSTRING,0,szChan)
+ KVSM_PARAMETER("network",KVS_PT_NONEMPTYSTRING,0,szNetwork)
+ KVSM_PARAMETER("property name",KVS_PT_NONEMPTYSTRING,0,szProperty)
+ KVSM_PARAMETER("value",KVS_PT_STRING,0,szValue)
+ KVSM_PARAMETERS_END(c)
+ KviRegisteredChannel * ch;
+ if(c->hasSwitch('e',"exactly"))ch = g_pRegisteredChannelDataBase->findExact(szChan,szNetwork);
+ else ch = g_pRegisteredChannelDataBase->find(szChan,szNetwork);
+ if(ch)
+ {
+ if(!szValue.isEmpty())
+ {
+ ch->setProperty(szProperty.utf8().data(),new KviStr(szValue));
+ } else {
+ ch->removeProperty(szProperty);
+ }
+ } else {
+ if(!c->hasSwitch('q',"quiet")) c->warning(__tr2qs("No such channel/netmask entry in the database"));
+ }
+ return true;
+}
+/*
+ @doc: regchan.showlist
+ @type:
+ command
+ @title:
+ regchan.showlist
+ @short:
+ Lists the registered channels
+ @syntax:
+ regchan.showlist
+ @description:
+ Lists the registered channels with their description
+*/
+
+static bool regchan_kvs_cmd_showlist(KviKvsModuleCommandCall * c)
+{
+ c->window()->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Registered channel list:"));
+
+ int tot = 0;
+
+ KviPointerHashTableIterator<const char *,KviRegisteredChannelList> it(*(g_pRegisteredChannelDataBase->channelDict()));
+ while(KviRegisteredChannelList * l = it.current())
+ {
+ for(KviRegisteredChannel * ch = l->first();ch;ch = l->next())
+ {
+ tot++;
+ c->window()->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Channel: %c%s@%s"),
+ KVI_TEXT_BOLD,ch->name().ptr(),ch->netMask().ptr());
+ KviPointerHashTableIterator<const char *,KviStr> pit(*(ch->propertyDict()));
+ while(KviStr * s = pit.current())
+ {
+ c->window()->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs(" Property: %s=%s"),pit.currentKey(),s->ptr());
+ ++pit;
+ }
+ }
+ ++it;
+ }
+
+ c->window()->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Total %d channels"),tot);
+ return true;
+}
+
+/*
+ @doc: regchan.list
+ @type:
+ function
+ @title:
+ $regchan.list
+ @short:
+ Get a list of registered channels
+ @syntax:
+ <array> $regchan.list([<channel_mask:string>],[<network_mask:string>])
+ @description:
+ Returns an array of the channel@netmask entries in the registered
+ channels database.[br]
+ Please note that <network_mask> is a wildcard string that will match
+ wildcard strings.[br]
+ @examples:
+ [example]
+ echo $regchan.list(#kvirc*,[fnc]$my.network[/fnc])
+ [/example]
+*/
+
+static bool regchan_kvs_fnc_list(KviKvsModuleFunctionCall * c)
+{
+ QString szChan,szNetmask;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("channel name",KVS_PT_STRING,KVS_PF_OPTIONAL,szChan)
+ KVSM_PARAMETER("netmask",KVS_PT_STRING,KVS_PF_OPTIONAL,szNetmask)
+ KVSM_PARAMETERS_END(c)
+
+ KviKvsArray* pArray = new KviKvsArray();
+// KviKvsArray* pArrayCN = new KviKvsArray();
+// pArrayCN->set(0,new KviKvsVariant(QString("")));
+// pArrayCN->set(1,new KviKvsVariant(QString("")));
+ int aid=0;
+
+ if(szChan.isEmpty())szChan="*";
+ if(szNetmask.isEmpty())szNetmask="*";
+
+ KviPointerHashTable<const char *,KviRegisteredChannelList> * d = g_pRegisteredChannelDataBase->channelDict();
+ KviPointerHashTableIterator<const char *,KviRegisteredChannelList> it(*d);
+
+ while(KviRegisteredChannelList * l = it.current())
+ {
+ for(KviRegisteredChannel * ch = l->first();ch;ch = l->next())
+ if(KviQString::matchWildExpressionsCI(ch->name().ptr(),szChan) &&
+ KviQString::matchWildExpressionsCI(ch->netMask().ptr(),szNetmask))
+ {
+// FIXME: WE NEED TO RETURN AN ARRAY OF 2-ELEMENT ARRAYS (chan name, netmask)
+ pArray->set(aid,new KviKvsVariant(QString(ch->name()+"@"+ch->netMask())));
+// pArray->set(aid,new KviKvsVariant(QString(ch->name()));
+// pArrayCN->set(0,new KviKvsVariant(QString(ch->name())));
+// pArrayCN->set(1,new KviKvsVariant(QString(ch->netMask())));
+// pArray->set(aid,new KviKvsVariant(pArrayCN));
+ aid++;
+ }
+ ++it;
+ }
+ c->returnValue()->setArray(pArray);
+ return true;
+}
+
+/*
+ @doc: regchan.property
+ @type:
+ function
+ @title:
+ $regchan.property
+ @short:
+ Returns a property of an entry in the registered channels database
+ @syntax:
+ <string> $regchan.property(<channel_name:string>,<network:string>,<property_name:string>)
+ @description:
+ Returns the value of the property identified by <property_name> and
+ bound to the channel identified by <channel_name> and best
+ matched by <network>.[br]
+ If the property is not set or if there is no matching channel entry an empty string is returned.[br]
+ @examples:
+ [example]
+ echo $regchan.property(#kvirc,[fnc]$my.network[/fnc],autojoin)
+ [/example]
+*/
+
+static bool regchan_kvs_fnc_property(KviKvsModuleFunctionCall * c)
+{
+ QString szChan,szNetwork,szPropertyName;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("channel name",KVS_PT_STRING,0,szChan)
+ KVSM_PARAMETER("network",KVS_PT_STRING,0,szNetwork)
+ KVSM_PARAMETER("property name",KVS_PT_NONEMPTYSTRING,0,szPropertyName)
+ KVSM_PARAMETERS_END(c)
+ KviRegisteredChannel * ch = g_pRegisteredChannelDataBase->find(szChan,szNetwork);
+ if(ch)
+ {
+ KviStr * p = ch->property(szPropertyName);
+ if(p)c->returnValue()->setString(p->ptr());
+ } //else c->warning(__tr("User %s not found"),parms->safeFirstParam());
+ return true;
+}
+/*
+ @doc: regchan.match
+ @type:
+ function
+ @title:
+ $regchan.match
+ @short:
+ Checks if a channel is registered
+ @syntax:
+ <boolean> $regchan.match(<channel_name:string>,<network:string>)
+ @description:
+ Returns 1 if <channel_name> and <network> match a registered channel entry
+ and 0 otherwise.
+ @examples:
+ [example]
+ echo $regchan.match(#kvirc,IRCNet)
+ echo $regchan.match(#kvirc,$my.network)
+ [/example]
+ @seealso:
+ [fnc]$regchan.find[/fnc]
+*/
+
+
+static bool regchan_kvs_fnc_match(KviKvsModuleFunctionCall * c)
+{
+ QString szChan,szNetwork;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("channel name",KVS_PT_STRING,0,szChan)
+ KVSM_PARAMETER("network",KVS_PT_STRING,0,szNetwork)
+ KVSM_PARAMETERS_END(c)
+ KviRegisteredChannel * ch = g_pRegisteredChannelDataBase->find(szChan,szNetwork);
+ c->returnValue()->setBoolean(ch);
+ return true;
+}
+
+/*
+ @doc: regchan.find
+ @type:
+ function
+ @title:
+ $regchan.find
+ @short:
+ Checks if a channel is registered
+ @syntax:
+ <boolean> $regchan.find(<channel_name:string>,<netmask:string>)
+ @description:
+ Returns 1 if the channel identified by <channel_name> and <netmask>
+ is registered and 0 otherwise. This function is similar to $regchan.match
+ but for $regchan.find the second parameter is the exact netmask
+ of the registered channel entry.
+ @examples:
+ [example]
+ echo $regchan.find(#kvirc,IRCNet)
+ echo $regchan.find(#kvirc,*)
+ [/example]
+ @seealso:
+ [fnc]$regchan.match[/fnc]
+*/
+
+static bool regchan_kvs_fnc_find(KviKvsModuleFunctionCall * c)
+{
+ QString szChan,szNetmask;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("channel name",KVS_PT_STRING,0,szChan)
+ KVSM_PARAMETER("netmask",KVS_PT_STRING,0,szNetmask)
+ KVSM_PARAMETERS_END(c)
+ KviRegisteredChannel * ch = g_pRegisteredChannelDataBase->find(szChan,szNetmask);
+ c->returnValue()->setBoolean(ch);
+ return true;
+}
+
+static bool regchan_module_init(KviModule * m)
+{
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"add",regchan_kvs_cmd_add);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"showlist",regchan_kvs_cmd_showlist);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"remove",regchan_kvs_cmd_remove);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"setProperty",regchan_kvs_cmd_setProperty);
+ KVSM_REGISTER_FUNCTION(m,"property",regchan_kvs_fnc_property);
+ KVSM_REGISTER_FUNCTION(m,"match",regchan_kvs_fnc_match);
+ KVSM_REGISTER_FUNCTION(m,"find",regchan_kvs_fnc_find);
+ KVSM_REGISTER_FUNCTION(m,"list",regchan_kvs_fnc_list);
+
+ return true;
+}
+
+static bool regchan_module_cleanup(KviModule *m)
+{
+ return true;
+}
+
+static bool regchan_module_can_unload(KviModule *)
+{
+ return true;
+}
+
+KVIRC_MODULE(
+ "RegChan", // module name
+ "1.0.0", // module version
+ "Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot net)", // author & (C)
+ "Script interface to the registered channels database",
+ regchan_module_init,
+ regchan_module_can_unload,
+ 0,
+ regchan_module_cleanup
+)
diff --git a/src/modules/reguser/Makefile.am b/src/modules/reguser/Makefile.am
new file mode 100644
index 00000000..93aea872
--- /dev/null
+++ b/src/modules/reguser/Makefile.am
@@ -0,0 +1,25 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkvireguser.la
+
+libkvireguser_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkvireguser_la_SOURCES = libkvireguser.cpp edituser.cpp wizard.cpp dialog.cpp
+libkvireguser_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+noinst_HEADERS= edituser.h wizard.h dialog.h
+nodist_libkvireguser_la_SOURCES = moc_dialog.cpp
+
+%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
+
+moc_dialog.cpp: dialog.h
+ $(SS_QT_MOC) $< -o $@
+
+edituser.cpp: edituser.moc
+wizard.cpp: wizard.moc
diff --git a/src/modules/reguser/dialog.cpp b/src/modules/reguser/dialog.cpp
new file mode 100644
index 00000000..b8d02fe2
--- /dev/null
+++ b/src/modules/reguser/dialog.cpp
@@ -0,0 +1,903 @@
+//=============================================================================
+//
+// File : edituser.cpp
+// Creation date : Tue Dec 26 2000 12:24:12 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+#define _WANT_OPTION_FLAGS_
+
+#include "edituser.h"
+#include "kvi_regusersdb.h"
+
+#include "kvi_locale.h"
+#include "kvi_ircmask.h"
+#include "kvi_debug.h"
+#include "kvi_iconmanager.h"
+#include "kvi_app.h"
+#include "kvi_options.h"
+#include "kvi_file.h"
+#include "kvi_filedialog.h"
+#include "kvi_msgbox.h"
+#include "kvi_fileutils.h"
+#include "kvi_settings.h"
+#include "kvi_stringconversion.h"
+#include "kvi_options.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#ifdef COMPILE_USE_QT4
+#include <q3header.h>
+#include <qevent.h>
+#include <QImageWriter>
+#include <QImageReader>
+
+#else
+#include <qheader.h>
+#endif
+#include "kvi_pointerhashtable.h"
+#include <qimage.h>
+#include <qstring.h>
+#include <qcombobox.h>
+
+
+#include <qstyle.h>
+#include <qpainter.h>
+#include "kvi_tal_hbox.h"
+#include "kvi_tal_vbox.h"
+#include <qinputdialog.h>
+
+#include "wizard.h"
+#include "dialog.h"
+
+
+#ifdef COMPILE_INFO_TIPS
+ #include <qtooltip.h>
+#endif // COMPILE_INFO_TIPS
+
+
+#define LVI_ICON_SIZE 32
+#define LVI_BORDER 4
+#define LVI_SPACING 8
+#define LVI_MINIMUM_TEXT_WIDTH 300
+#define LVI_MINIMUM_CELL_WIDTH (LVI_MINIMUM_TEXT_WIDTH + LVI_BORDER + LVI_ICON_SIZE + LVI_SPACING + LVI_BORDER)
+
+
+extern KviRegisteredUsersDialog * g_pRegisteredUsersDialog;
+
+KviRegisteredUsersDialogItem::KviRegisteredUsersDialogItem(KviTalListViewItem * par,KviRegisteredUser * u)
+: KviRegisteredUsersDialogItemBase(User,par), m_pUser(u)
+{
+ QString szTmp;
+ QString t = "<nobr><b>";
+ t += u->name();
+ t += "</b> [";
+ szTmp = m_pUser->getProperty("notify");
+ if(szTmp.isEmpty())
+ {
+ t += __tr2qs("Notify disabled");
+ } else {
+ t += __tr2qs("Notify as: ");
+ t += szTmp;
+
+ }
+ t += "]</nobr>";
+ t += "<br><nobr><font size=\"-1\">";
+ szTmp = m_pUser->getProperty("comment");
+ if(szTmp.isEmpty())
+ {
+ t += __tr2qs("No comment set");
+ } else {
+ t += __tr2qs("Comment: ");
+ t += m_pUser->getProperty("comment");
+ }
+ t += "</font></nobr>";
+ m_pText = new QSimpleRichText(t,listView()->font());
+
+ //setText(0,u->name());
+}
+
+KviRegisteredUsersDialogItem::~KviRegisteredUsersDialogItem()
+{
+ delete m_pText;
+}
+
+QString KviRegisteredUsersDialogItem::key(int,bool) const
+{
+ return m_pUser->name();
+}
+
+void KviRegisteredUsersDialogItem::paintCell(QPainter * p,const QColorGroup &cg,int column,int width,int align)
+{
+ KviTalListViewItem::paintCell(p,cg,column,width,align);
+ if(column==0)
+ {
+ p->drawPixmap(LVI_BORDER,LVI_BORDER, *(g_pIconManager->getBigIcon(QString(KVI_BIGICON_REGUSERS))) );
+ int afterIcon = LVI_BORDER + LVI_ICON_SIZE + LVI_SPACING;
+ int www = listView()->visibleWidth() - (afterIcon + LVI_BORDER);
+ m_pText->setWidth(www);
+ if(isSelected())
+ {
+ QColorGroup cg2(cg);
+ cg2.setColor(QColorGroup::HighlightedText,cg.text());
+ m_pText->draw(p,afterIcon,LVI_BORDER,QRect(afterIcon,LVI_BORDER,www,height() - (LVI_BORDER * 2)),cg2);
+ } else {
+ m_pText->draw(p,afterIcon,LVI_BORDER,QRect(afterIcon,LVI_BORDER,www,height() - (LVI_BORDER * 2)),cg);
+ }
+ } else {
+ if(m_pUser)
+ {
+ if(!m_pUser->getProperty("notify").isEmpty())
+ p->drawPixmap(LVI_BORDER,LVI_BORDER,*(g_pIconManager->getSmallIcon(KVI_SMALLICON_NOTIFYONLINE)));
+ if(m_pUser->ignoreEnagled())
+ p->drawPixmap(LVI_BORDER,2*LVI_BORDER+16,*(g_pIconManager->getSmallIcon(KVI_SMALLICON_IGNORE)));
+ }
+ }
+}
+
+void KviRegisteredUsersDialogItem::setup()
+{
+ KviTalListViewItem::setup();
+ int iWidth = listView()->visibleWidth();
+ if(iWidth < LVI_MINIMUM_CELL_WIDTH)iWidth = LVI_MINIMUM_CELL_WIDTH;
+ iWidth -= LVI_BORDER + LVI_ICON_SIZE + LVI_SPACING + LVI_BORDER;
+ m_pText->setWidth(iWidth);
+ int iHeight = m_pText->height() + (2 * LVI_BORDER);
+ if(iHeight < (LVI_ICON_SIZE + (2 * LVI_BORDER)))iHeight = LVI_ICON_SIZE + (2 * LVI_BORDER);
+ setHeight(iHeight);
+}
+
+
+KviRegisteredUsersDialog::KviRegisteredUsersDialog(QWidget * par)
+: QWidget(par)
+{
+ g_pRegisteredUsersDialog = this;
+
+ g_pLocalRegisteredUserDataBase = new KviRegisteredUserDataBase();
+ g_pLocalRegisteredUserDataBase->copyFrom(g_pRegisteredUserDataBase);
+
+ setIcon(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_REGUSERS)));
+ setCaption(__tr2qs("Registered Users - KVIrc"));
+
+ QGridLayout * g = new QGridLayout(this,4,3,4,4);
+
+
+ m_pListView = new KviTalListView(this);
+
+ m_pListView->addColumn(__tr2qs("Name"),200);
+ m_pListView->addColumn(__tr2qs("Flags"),20);
+
+ m_pListView->setAllColumnsShowFocus(true);
+
+ m_pListView->setSelectionMode(KviTalListView::Extended);
+ m_pListView->setRootIsDecorated(TRUE);
+
+#ifdef COMPILE_INFO_TIPS
+ QToolTip::add(m_pListView,__tr2qs("<center>This is the list of registered users. " \
+ "KVIrc can automatically recognize and associate properties to them.<br>" \
+ "Use the buttons on the right to add, edit and remove entries. " \
+ "The \"notify\" column allows you to quickly add users to the notify list. " \
+ "Notify list fine-tuning can be performed by editing the entry properties.</center>"));
+#endif // COMPILE_INFO_TIPS
+
+ connect(m_pListView,SIGNAL(pressed(KviTalListViewItem *,const QPoint &,int)),this,SLOT(itemPressed(KviTalListViewItem *,const QPoint &,int)));
+ connect(m_pListView,SIGNAL(doubleClicked(KviTalListViewItem *)),this,SLOT(itemDoubleClicked(KviTalListViewItem *)));
+
+ g->addMultiCellWidget(m_pListView,0,1,0,1);
+
+ KviTalVBox * vbox = new KviTalVBox(this);
+ vbox->setSpacing(4);
+ g->addWidget(vbox,0,2);
+
+ m_pWizardAddButton = new QPushButton(__tr2qs("Add (Wizard)..."),vbox);
+ connect(m_pWizardAddButton,SIGNAL(clicked()),this,SLOT(addWizardClicked()));
+#ifdef COMPILE_INFO_TIPS
+ QToolTip::add(m_pWizardAddButton,__tr2qs("Add a registered user by means of a user-friendly wizard."));
+#endif // COMPILE_INFO_TIPS
+ m_pWizardAddButton->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_NEWITEMBYWIZARD)));
+
+
+ m_pAddButton = new QPushButton(__tr2qs("&Add..."),vbox);
+ connect(m_pAddButton,SIGNAL(clicked()),this,SLOT(addClicked()));
+#ifdef COMPILE_INFO_TIPS
+ QToolTip::add(m_pAddButton,__tr2qs("Open the edit dialog to create a new user entry."));
+#endif // COMPILE_INFO_TIPS
+ m_pAddButton->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_NEWITEM)));
+
+ m_pAddGroupButton = new QPushButton(__tr2qs("&Add Group..."),vbox);
+ connect(m_pAddGroupButton,SIGNAL(clicked()),this,SLOT(addGroupClicked()));
+#ifdef COMPILE_INFO_TIPS
+ QToolTip::add(m_pAddGroupButton,__tr2qs("Adds a new group"));
+#endif // COMPILE_INFO_TIPS
+ m_pAddGroupButton->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_NEWITEM)));
+
+ m_pRemoveButton = new QPushButton(__tr2qs("Re&move"),vbox);
+ connect(m_pRemoveButton,SIGNAL(clicked()),this,SLOT(removeClicked()));
+ m_pRemoveButton->setEnabled(false);
+#ifdef COMPILE_INFO_TIPS
+ QToolTip::add(m_pRemoveButton,__tr2qs("Remove the currently selected entries."));
+#endif // COMPILE_INFO_TIPS
+ m_pRemoveButton->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_DELETEITEM)));
+
+
+ m_pEditButton = new QPushButton(__tr2qs("&Edit..."),vbox);
+ connect(m_pEditButton,SIGNAL(clicked()),this,SLOT(editClicked()));
+ m_pEditButton->setEnabled(false);
+#ifdef COMPILE_INFO_TIPS
+ QToolTip::add(m_pEditButton,__tr2qs("Edit the first selected entry."));
+#endif // COMPILE_INFO_TIPS
+ m_pEditButton->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_EDITITEM)));
+
+ QFrame * f = new QFrame(vbox);
+ f->setFrameStyle(QFrame::HLine | QFrame::Sunken);
+
+ m_pExportButton = new QPushButton(__tr("Export To..."),vbox);
+ m_pExportButton->setEnabled(false);
+ connect(m_pExportButton,SIGNAL(clicked()),this,SLOT(exportClicked()));
+#ifdef COMPILE_INFO_TIPS
+ QToolTip::add(m_pExportButton,__tr2qs("Export the selected entries to a file.<br>All the data associated with the selected registered users will be exported.<br>You (or anyone else) can later import the entries by using the \"Import\" button."));
+#endif // COMPILE_INFO_TIPS
+ m_pExportButton->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_FLOPPY)));
+
+
+ m_pImportButton = new QPushButton(__tr("Import From..."),vbox);
+ connect(m_pImportButton,SIGNAL(clicked()),this,SLOT(importClicked()));
+#ifdef COMPILE_INFO_TIPS
+ QToolTip::add(m_pImportButton,__tr2qs("Import entries from a file exported earlier by the \"export\" function of this dialog."));
+#endif // COMPILE_INFO_TIPS
+ m_pImportButton->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_FOLDER)));
+
+
+ KviTalHBox * hbox = new KviTalHBox(this);
+ hbox->setSpacing(4);
+ g->addMultiCellWidget(hbox,3,3,1,2);
+
+ QPushButton * b;
+
+
+ b = new QPushButton(__tr2qs("&OK"),hbox);
+ connect(b,SIGNAL(clicked()),this,SLOT(okClicked()));
+ b->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_ACCEPT)));
+ //b->setMinimumWidth(120);
+
+ b = new QPushButton(__tr2qs("Cancel"),hbox);
+ connect(b,SIGNAL(clicked()),this,SLOT(cancelClicked()));
+ b->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_DISCARD)));
+ //b->setMinimumWidth(120);
+
+
+ g->addRowSpacing(2,15);
+
+ g->setColStretch(0,1);
+ g->setRowStretch(1,1);
+
+ connect(m_pListView,SIGNAL(selectionChanged()),this,SLOT(selectionChanged()));
+ connect(m_pListView,SIGNAL(rightButtonClicked ( KviTalListViewItem *, const QPoint &, int ) ),this,SLOT(listViewRightButtonClicked ( KviTalListViewItem *, const QPoint &, int )));
+
+ fillList();
+
+ if(!parent())
+ {
+ if(KVI_OPTION_RECT(KviOption_rectRegisteredUsersDialogGeometry).y() < 5)
+ {
+ KVI_OPTION_RECT(KviOption_rectRegisteredUsersDialogGeometry).setY(5);
+ }
+ //setGeometry(KVI_OPTION_RECT(KviOption_rectRegisteredUsersDialogGeometry));
+ resize(KVI_OPTION_RECT(KviOption_rectRegisteredUsersDialogGeometry).width(),
+ KVI_OPTION_RECT(KviOption_rectRegisteredUsersDialogGeometry).height());
+ move(KVI_OPTION_RECT(KviOption_rectRegisteredUsersDialogGeometry).x(),
+ KVI_OPTION_RECT(KviOption_rectRegisteredUsersDialogGeometry).y());
+ }
+}
+
+KviRegisteredUsersDialog::~KviRegisteredUsersDialog()
+{
+#ifndef Q_OS_MACX
+ if(!parent())KVI_OPTION_RECT(KviOption_rectRegisteredUsersDialogGeometry) = QRect(pos().x(),pos().y(),
+ size().width(),size().height());
+#else
+ if(!parent())KVI_OPTION_RECT(KviOption_rectRegisteredUsersDialogGeometry) = geometry();
+#endif
+
+ g_pRegisteredUsersDialog = 0;
+
+ delete g_pLocalRegisteredUserDataBase;
+ g_pLocalRegisteredUserDataBase = 0;
+}
+
+void KviRegisteredUsersDialog::itemPressed(KviTalListViewItem *it,const QPoint &pnt,int c)
+{
+ if(!it)return;
+ KviRegisteredUsersDialogItemBase* b=(KviRegisteredUsersDialogItemBase*)it;
+ if(b->type()==KviRegisteredUsersDialogItemBase::User)
+ {
+ KviRegisteredUsersDialogItem *i = (KviRegisteredUsersDialogItem *)it;
+
+ QRect r = m_pListView->itemRect(i);
+ int daw = m_pListView->columnWidth(0);
+
+ QPoint ppp = m_pListView->mapFromGlobal(pnt);
+
+ if((c == 1) && (ppp.x() < (r.height() + 5 + daw)))
+ {
+ // notify list toggle
+ if(i->user()->getProperty("notify").isEmpty())
+ {
+ i->user()->setProperty("notify",""); // kill that
+ } else {
+ // try to find the nicknames to be notified
+ QString szMask;
+
+ for(KviIrcMask * m = i->user()->maskList()->first();m;m = i->user()->maskList()->next())
+ {
+ QString tmp = m->nick();
+ if((tmp.find('*') == -1) && (tmp.find('?') == -1) && (!tmp.isEmpty()))
+ {
+ if(!szMask.isEmpty())szMask.append(' ');
+ szMask.append(tmp);
+ }
+ }
+ // if the nickname list is still empty , build a dummy nick to notify
+ szMask = i->user()->name();
+ szMask.replace(" ","");
+ szMask.replace("'","");
+ szMask.replace("&","");
+ szMask.replace(",","");
+
+ i->user()->setProperty("notify",szMask);
+ }
+ m_pListView->update();
+ }
+ }
+}
+
+void KviRegisteredUsersDialog::itemDoubleClicked(KviTalListViewItem *it)
+{
+ if(!it)return;
+ KviRegisteredUsersDialogItemBase* b=(KviRegisteredUsersDialogItemBase*)it;
+ if(b->type()==KviRegisteredUsersDialogItemBase::User)
+ {
+ editItem((KviRegisteredUsersDialogItem *)it);
+ } else {
+ KviRegisteredUsersGroupItem *i = (KviRegisteredUsersGroupItem *)b;
+ editGroup(i->group());
+ }
+}
+
+void KviRegisteredUsersDialog::addGroupClicked()
+{
+ bool ok;
+ QString text = QInputDialog::getText(
+ "KVIrc", __tr("Group name:"), QLineEdit::Normal,
+ QString::null, &ok, this );
+ if ( ok && !text.isEmpty() ) {
+ g_pLocalRegisteredUserDataBase->addGroup(text);
+ fillList();
+ }
+}
+void KviRegisteredUsersDialog::editGroup(KviRegisteredUserGroup* group)
+{
+ bool ok;
+
+ QString text = QInputDialog::getText(
+ "KVIrc", __tr("Group name:"), QLineEdit::Normal,
+ group->name(), &ok, this );
+ if ( ok && !text.isEmpty() ) {
+ QString szOldGroup=group->name();
+ g_pLocalRegisteredUserDataBase->groupDict()->setAutoDelete(0);
+ g_pLocalRegisteredUserDataBase->groupDict()->remove(szOldGroup);
+ g_pLocalRegisteredUserDataBase->groupDict()->setAutoDelete(1);
+ group->setName(text);
+ g_pLocalRegisteredUserDataBase->groupDict()->insert(text,group);
+
+ KviPointerHashTable<QString,KviRegisteredUser> * d = g_pLocalRegisteredUserDataBase->userDict();
+
+ for(KviRegisteredUser * u = d->first();u;u = d->next())
+ {
+ if(u->group()==szOldGroup)
+ u->setGroup(text);
+ }
+
+
+ fillList();
+ }
+}
+
+void KviRegisteredUsersDialog::listViewRightButtonClicked ( KviTalListViewItem * pItem, const QPoint & point, int )
+{
+ if(pItem)
+ {
+ KviRegisteredUsersDialogItemBase* b=(KviRegisteredUsersDialogItemBase*)pItem;
+ if(b->type()==KviRegisteredUsersDialogItemBase::User)
+ {
+ KviTalPopupMenu *groups = new KviTalPopupMenu;
+
+ KviPointerHashTable<QString,KviRegisteredUserGroup> * pGroups = g_pLocalRegisteredUserDataBase->groupDict();
+ m_TmpDict.clear();
+ for(KviPointerHashTableEntry<QString,KviRegisteredUserGroup> * g = pGroups->firstEntry();g;g = pGroups->nextEntry())
+ {
+ int id=groups->insertItem(g->key());
+ m_TmpDict.replace(id,g->data());
+ }
+
+ connect(groups,SIGNAL(activated ( int )),this,SLOT(moveToGroupMenuClicked(int)));
+
+ KviTalPopupMenu *mainPopup = new KviTalPopupMenu;
+ mainPopup->insertItem(__tr("Move to group"),groups);
+ mainPopup->exec(point);
+ }
+ }
+}
+
+void KviRegisteredUsersDialog::moveToGroupMenuClicked(int id)
+{
+ QString szGroup=m_TmpDict.find(id)->name();
+ KviTalListViewItemIterator it( m_pListView, KviTalListViewItemIterator::Selected );
+ while ( it.current() ) {
+ KviRegisteredUsersDialogItemBase* b=(KviRegisteredUsersDialogItemBase*)(it.current());
+ if(b->type()==KviRegisteredUsersDialogItemBase::User)
+ {
+ ((KviRegisteredUsersDialogItem *)(it.current()))->user()->setGroup(szGroup);
+ }
+ ++it;
+ }
+ fillList();
+}
+
+void KviRegisteredUsersDialog::fillList()
+{
+ m_pListView->clear();
+ KviPointerHashTable<QString,KviRegisteredUsersGroupItem> groupItems(5,false);
+ groupItems.setAutoDelete(false);
+
+ KviPointerHashTable<QString,KviRegisteredUserGroup> * pGroups = g_pLocalRegisteredUserDataBase->groupDict();
+ for(KviRegisteredUserGroup * g = pGroups->first();g;g = pGroups->next())
+ {
+ KviRegisteredUsersGroupItem* pCur = new KviRegisteredUsersGroupItem(m_pListView,g);
+ groupItems.insert(g->name(),pCur);
+ pCur->setOpen(TRUE);
+ }
+
+ KviPointerHashTable<QString,KviRegisteredUser> * d = g_pLocalRegisteredUserDataBase->userDict();
+ KviRegisteredUsersDialogItem * item;
+
+ for(KviRegisteredUser * u = d->first();u;u = d->next())
+ {
+ if(u->group().isEmpty())
+ u->setGroup(__tr("Default"));
+ if(groupItems.find(u->group()))
+ item = new KviRegisteredUsersDialogItem(groupItems.find(u->group()),u);
+ else if(groupItems.find(__tr("Default")))
+ item = new KviRegisteredUsersDialogItem(groupItems.find(__tr("Default")),u);
+ else { //should never be called
+ KviRegisteredUserGroup* pGroup = g_pLocalRegisteredUserDataBase->addGroup(__tr("Default"));
+ KviRegisteredUsersGroupItem* pCur = new KviRegisteredUsersGroupItem(m_pListView,pGroup);
+ groupItems.insert(__tr("Default"),pCur);
+ item = new KviRegisteredUsersDialogItem(pCur,u);
+ }
+ }
+ if(m_pListView->firstChild())
+ {
+ m_pListView->setSelected(m_pListView->firstChild(),true);
+ m_pListView->setCurrentItem(m_pListView->firstChild());
+ }
+}
+
+void KviRegisteredUsersDialog::closeEvent(QCloseEvent *e)
+{
+ m_pListView->clear();
+ e->accept();
+ okClicked();
+ //delete this;
+}
+
+void KviRegisteredUsersDialog::okClicked()
+{
+ m_pListView->clear();
+ g_pRegisteredUserDataBase->copyFrom(g_pLocalRegisteredUserDataBase);
+ g_pApp->restartNotifyLists();
+ delete this;
+}
+
+void KviRegisteredUsersDialog::cancelClicked()
+{
+ m_pListView->clear();
+ delete this;
+}
+
+void KviRegisteredUsersDialog::addClicked()
+{
+ KviRegisteredUserEntryDialog * dlg = new KviRegisteredUserEntryDialog(this,0);
+ int ret = dlg->exec();
+ delete dlg;
+
+ if(!g_pRegisteredUsersDialog)return; // we have been deleted!
+
+ if(ret == QDialog::Accepted)
+ {
+ fillList();
+ }
+}
+
+void KviRegisteredUsersDialog::addWizardClicked()
+{
+ KviRegistrationWizard * w = new KviRegistrationWizard("",g_pLocalRegisteredUserDataBase,this,true);
+ int ret = w->exec();
+ delete w;
+ if(!g_pRegisteredUsersDialog)return; // we have been deleted!
+ if(ret == QDialog::Accepted)
+ {
+ fillList();
+ }
+}
+
+void KviRegisteredUsersDialog::removeClicked()
+{
+ KviTalListViewItemIterator it( m_pListView, KviTalListViewItemIterator::Selected );
+ while ( it.current() ) {
+ KviRegisteredUsersDialogItemBase* b=(KviRegisteredUsersDialogItemBase*)(it.current());
+ if(b->type()==KviRegisteredUsersDialogItemBase::User)
+ {
+ g_pLocalRegisteredUserDataBase->removeUser(((KviRegisteredUsersDialogItem *)(it.current()))->user()->name());
+ } else {
+ g_pLocalRegisteredUserDataBase->removeGroup(((KviRegisteredUsersGroupItem *)(it.current()))->group()->name());
+ }
+ ++it;
+ }
+ fillList();
+// KviRegisteredUsersDialogItem *it = (KviRegisteredUsersDialogItem *)m_pListView->firstChild();
+// KviRegisteredUsersDialogItemBase* b=(KviRegisteredUsersDialogItemBase*)it;
+// if(b->type()==KviRegisteredUsersDialogItemBase::User)
+// {
+// KviPointerList<KviRegisteredUsersDialogItem> l;
+// l.setAutoDelete(false);
+// while(it)
+// {
+// if(it->isSelected())l.append(it);
+// it = (KviRegisteredUsersDialogItem *)it->nextSibling();
+// }
+//
+// for(KviRegisteredUsersDialogItem * i = l.first();i;i = l.next())
+// {
+// //g_pLocalRegisteredUserDataBase->removeUser(i->user()->name());
+// delete i;
+// }
+// } else {
+//
+// }
+}
+
+void KviRegisteredUsersDialog::editClicked()
+{
+ KviRegisteredUsersDialogItemBase* b=(KviRegisteredUsersDialogItemBase*)(m_pListView->currentItem());
+ if(!b)return;
+ if(b->type()==KviRegisteredUsersDialogItemBase::User)
+ {
+ KviRegisteredUsersDialogItem *i = (KviRegisteredUsersDialogItem *)b;
+ editItem(i);
+ } else {
+ KviRegisteredUsersGroupItem *i = (KviRegisteredUsersGroupItem *)b;
+ editGroup(i->group());
+ }
+}
+
+void KviRegisteredUsersDialog::editItem(KviRegisteredUsersDialogItem * i)
+{
+ KviRegisteredUser * u = i->user();
+
+ i->setUser(0);
+
+ QString szName = u->name();
+
+ KviRegisteredUserEntryDialog * dlg = new KviRegisteredUserEntryDialog(this,u);
+ int res = dlg->exec();
+ delete dlg;
+
+ if(!g_pRegisteredUsersDialog)return; // we have been deleted!
+
+ if(res == QDialog::Accepted)
+ {
+ fillList();
+
+ // select the last edited item
+ KviTalListViewItem * i = m_pListView->firstChild();
+ while(i)
+ {
+ QString szTmp = i->text(0);
+ if(KviQString::equalCI(szTmp,szName))
+ {
+ m_pListView->setSelected(i,true);
+ m_pListView->setCurrentItem(i);
+ break;
+ }
+ i = i->nextSibling();
+ }
+
+ return;
+ }
+
+ i->setUser(u);
+ m_pListView->update();
+}
+
+
+void KviRegisteredUsersDialog::selectionChanged()
+{
+ bool bHaveSelected = !m_pListView->selectedItem();
+
+ m_pEditButton->setEnabled(bHaveSelected);
+ m_pRemoveButton->setEnabled(bHaveSelected);
+ m_pExportButton->setEnabled(bHaveSelected);
+}
+
+
+#define KVI_REGUSER_DB_FILE_MAGIC 0x5334DBDB
+#define KVI_REGUSER_DB_FILE_VERSION 1
+
+typedef struct _KviReguserDbFileHeader
+{
+ unsigned int magic;
+ unsigned int version;
+ unsigned int nentries;
+} KviReguserDbFileHeader;
+
+void KviRegisteredUsersDialog::exportClicked()
+{
+ unsigned int nEntries = 0;
+
+ KviTalListViewItemIterator it( m_pListView, KviTalListViewItemIterator::Selected );
+ KviTalListViewItemIterator cit( m_pListView, KviTalListViewItemIterator::Selected );
+ while ( cit.current() ) {
+ if(((KviRegisteredUsersDialogItemBase *)(cit.current()))->type() == KviRegisteredUsersDialogItemBase::User)
+ nEntries++;
+ ++cit;
+ }
+
+ if(nEntries < 1)
+ {
+ KviMessageBox::warning(__tr("No entries selected."));
+ return;
+ }
+
+ QString buffer;
+
+ if(!KviFileDialog::askForSaveFileName(buffer,__tr("Choose a Filename - KVIrc"),0,0,true,true))return;
+
+ if(!g_pRegisteredUsersDialog)return; // we have been deleted!
+
+ KviFile f(buffer);
+ if(!f.open(IO_WriteOnly | IO_Truncate))
+ {
+ KviMessageBox::warning(__tr("Can't open file %Q for writing."),&buffer);
+ return;
+ }
+
+ KviReguserDbFileHeader hf;
+ hf.magic = KVI_REGUSER_DB_FILE_MAGIC;
+ hf.version = KVI_REGUSER_DB_FILE_VERSION;
+ hf.nentries = nEntries;
+
+ if(f.writeBlock((const char *)&hf,sizeof(KviReguserDbFileHeader)) != sizeof(KviReguserDbFileHeader))goto write_error;
+
+ while ( it.current() ) {
+ KviRegisteredUsersDialogItemBase *pBase = (KviRegisteredUsersDialogItemBase *)(it.current());
+ if(pBase->type()!=KviRegisteredUsersDialogItemBase::User) continue;
+ QString szName = it.current()->text(0);
+ KviRegisteredUser * u = ((KviRegisteredUsersDialogItem *)(it.current()))->user();
+ if(u)
+ {
+ if(!f.save(szName))goto write_error;
+ KviPointerHashTable<QString,QString> * pd = u->propertyDict();
+ if(pd)
+ {
+ if(!f.save(pd->count()))goto write_error;
+ for(KviPointerHashTableEntry<QString,QString> * pCur = pd->firstEntry();pCur;pCur = pd->nextEntry())
+ {
+ QString key = pCur->key();
+ if(!f.save(key))goto write_error;
+ if(!f.save(*(pCur->data())))goto write_error;
+ }
+ } else {
+ if(!f.save(0))goto write_error;
+ }
+
+ KviPointerList<KviIrcMask> * ml = u->maskList();
+ if(ml)
+ {
+ if(!f.save(ml->count()))goto write_error;
+ for(KviIrcMask * m = ml->first();m;m = ml->next())
+ {
+ QString fullMask;
+ m->mask(fullMask,KviIrcMask::NickUserHost);
+ if(!f.save(fullMask))goto write_error;
+ }
+ } else {
+ if(!f.save(0))goto write_error;
+ }
+
+ QString avatar;
+ if(u->getProperty("avatar",avatar))
+ {
+ KviAvatar * av = g_pIconManager->getAvatar(QString::null,avatar);
+ if(av)
+ {
+ if(!av->pixmap()->isNull())
+ {
+ if(!f.save(1))goto write_error;
+#ifdef COMPILE_USE_QT4
+ QImageWriter io;
+ io.setDevice(&f);
+ io.setFormat("PNG");
+ if(!io.write(av->pixmap()->convertToImage()))goto write_error;
+#else
+ QImageIO io;
+ io.setImage(av->pixmap()->convertToImage());
+ io.setIODevice(&f);
+ io.setFormat("PNG");
+ if(!io.write())goto write_error;
+#endif
+ } else {
+ if(!f.save(0))goto write_error;
+ }
+ } else {
+ if(!f.save(0))goto write_error;
+ }
+ } else {
+ if(!f.save(0))goto write_error;
+ }
+ }
+ ++it;
+ }
+
+ goto succesfull_export;
+
+
+write_error:
+ KviMessageBox::warning(__tr("Can't export the registered users database: Write error."));
+ f.close();
+ return;
+
+succesfull_export:
+
+ f.close();
+}
+
+void KviRegisteredUsersDialog::importClicked()
+{
+ //KviStr buffer;
+ QString buffer;
+
+ if(!KviFileDialog::askForOpenFileName(buffer,__tr("Choose a Filename - KVIrc")))return;
+
+ if(!g_pRegisteredUsersDialog)return; // we have been deleted!
+
+ KviFile f(buffer);
+ if(!f.open(IO_ReadOnly))
+ {
+ KviMessageBox::warning(__tr2qs("Can't open file %s for reading."),&buffer);
+ return;
+ }
+
+ KviReguserDbFileHeader hf;
+ unsigned int idx;
+
+ if(f.readBlock((char *)&hf,sizeof(KviReguserDbFileHeader)) != sizeof(KviReguserDbFileHeader))goto read_error;
+
+ if(hf.magic != KVI_REGUSER_DB_FILE_MAGIC)
+ {
+ KviMessageBox::warning(__tr2qs("The file %s doesn't appear to be a valid registered users database."),&buffer);
+ f.close();
+ return;
+ }
+
+ if(hf.version != KVI_REGUSER_DB_FILE_VERSION)
+ {
+ KviMessageBox::warning(__tr2qs("The file %s contains an invalid registered users database version."),&buffer);
+ f.close();
+ return;
+ }
+
+
+
+ for(idx = 0;idx < hf.nentries;idx++)
+ {
+ QString szName;
+ if(!f.load(szName))goto read_error;
+ KviRegisteredUser * u = g_pLocalRegisteredUserDataBase->getUser(szName);
+ unsigned int count = 0;
+ if(!f.load(count))goto read_error;
+ for(unsigned int up = 0;up < count;up++)
+ {
+ QString szKey,szValue;
+ if(!f.load(szKey))goto read_error;
+ if(!f.load(szValue))goto read_error;
+ u->setProperty(szKey,szValue);
+ }
+ if(!f.load(count))goto read_error;
+ for(unsigned int um = 0;um < count;um++)
+ {
+ QString szMask;
+ if(!f.load(szMask))goto read_error;
+ if(!szMask.isEmpty())
+ {
+ KviIrcMask * m = new KviIrcMask(szMask);
+ g_pLocalRegisteredUserDataBase->addMask(u,m);
+ }
+ }
+ if(!f.load(count))goto read_error;
+ if(count)
+ {
+ // there is an avatar
+ QImage img;
+#ifdef COMPILE_USE_QT4
+ QImageReader io;
+ io.setDevice(&f);
+ io.setFormat("PNG");
+ img=io.read();
+// if(io.read())goto read_error;
+
+#else
+ QImageIO io;
+ io.setImage(img);
+ io.setIODevice(&f);
+ io.setFormat("PNG");
+
+ if(!io.read())goto read_error;
+
+ img = io.image();
+#endif
+ if(img.isNull())debug("Ops.. readed a null image ?");
+
+ KviStr fName = u->name();
+ kvi_encodeFileName(fName);
+
+ KviStr fPath;
+ int rnm = 0 ;
+ do
+ {
+ g_pApp->getLocalKvircDirectory(fPath,KviApp::Avatars,fName.ptr());
+ fPath.append(KviStr::Format,"%d.png",rnm);
+ rnm++;
+ } while(KviFileUtils::fileExists(fPath.ptr()));
+
+ if(!img.save(fPath.ptr(),"PNG"))
+ {
+ debug("Can't save image %s",fPath.ptr());
+ } else {
+ u->setProperty("avatar",fPath.ptr());
+ }
+ }
+ }
+
+ goto succesfull_import;
+
+
+read_error:
+ KviMessageBox::warning(__tr("Can't import the registered users database: Read error."));
+ f.close();
+ return;
+
+succesfull_import:
+
+ f.close();
+ fillList();
+}
+#if defined(COMPILE_USE_QT4) && defined(COMPILE_ON_WINDOWS)
+#include "dialog.moc"
+#endif
diff --git a/src/modules/reguser/dialog.h b/src/modules/reguser/dialog.h
new file mode 100644
index 00000000..c292adc4
--- /dev/null
+++ b/src/modules/reguser/dialog.h
@@ -0,0 +1,148 @@
+#ifndef _DIALOG_H_
+#define _DIALOG_H_
+//=============================================================================
+//
+// File : edituser.h
+// Creation date : Sun Dec 24 2000 15:16:17 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+#include "kvi_string.h"
+#include "kvi_regusersdb.h"
+#include "kvi_selectors.h"
+
+#include <qwidget.h>
+#include <qlineedit.h>
+#include <qpushbutton.h>
+#include "kvi_tal_listview.h"
+#include "kvi_tal_listbox.h"
+#include "kvi_pointerhashtable.h"
+#include "kvi_tal_popupmenu.h"
+#ifdef COMPILE_USE_QT4
+ #include <q3intdict.h>
+ #include <q3simplerichtext.h>
+ #define QSimpleRichText Q3SimpleRichText
+#else
+ #include <qsimplerichtext.h>
+ #include <qintdict.h>
+
+
+#endif
+
+class KviRegisteredUsersDialogItemBase : public KviTalListViewItem
+{
+public:
+ enum Types { User,Group };
+protected:
+ KviRegisteredUsersDialogItemBase(Types type,KviTalListView * par)
+ :KviTalListViewItem(par),m_iType(type)
+ {
+ };
+ KviRegisteredUsersDialogItemBase(Types type,KviTalListViewItem * par)
+ :KviTalListViewItem(par),m_iType(type)
+ {
+ };
+ ~KviRegisteredUsersDialogItemBase()
+ {
+ };
+
+private:
+ KviRegisteredUsersDialogItemBase::Types m_iType;
+public:
+ KviRegisteredUsersDialogItemBase::Types type() { return m_iType; };
+};
+
+class KviRegisteredUsersGroupItem : public KviRegisteredUsersDialogItemBase
+{
+protected:
+ KviRegisteredUserGroup * m_pGroup;
+public:
+ KviRegisteredUsersGroupItem(KviTalListView * par,KviRegisteredUserGroup * g)
+ :KviRegisteredUsersDialogItemBase(Group,par), m_pGroup(g)
+ {
+ setText(0,m_pGroup->name());
+ }
+ ~KviRegisteredUsersGroupItem()
+ {
+ }
+ KviRegisteredUserGroup * group() { return m_pGroup; };
+};
+
+class KviRegisteredUsersDialogItem : public KviRegisteredUsersDialogItemBase
+{
+protected:
+ KviRegisteredUser * m_pUser;
+ QSimpleRichText * m_pText;
+public:
+ KviRegisteredUsersDialogItem(KviTalListViewItem * par,KviRegisteredUser * u);
+ ~KviRegisteredUsersDialogItem();
+public:
+ KviRegisteredUser * user(){ return m_pUser; };
+ void setUser(KviRegisteredUser * u){ m_pUser = u; };
+ virtual void paintCell(QPainter * p,const QColorGroup &cg,int column,int width,int align);
+ virtual void setup();
+ virtual QString key(int,bool) const;
+};
+
+class KviRegisteredUsersDialog : public QWidget
+{
+ Q_OBJECT
+public:
+ KviRegisteredUsersDialog(QWidget * par = 0);
+ ~KviRegisteredUsersDialog();
+public:
+ KviTalListView * m_pListView;
+ QPushButton * m_pAddButton;
+ QPushButton * m_pWizardAddButton;
+ QPushButton * m_pRemoveButton;
+ QPushButton * m_pEditButton;
+ QPushButton * m_pImportButton;
+ QPushButton * m_pExportButton;
+ QPushButton * m_pAddGroupButton;
+#ifdef COMPILE_USE_QT4
+ Q3IntDict<KviRegisteredUserGroup> m_TmpDict;
+#else
+ QIntDict<KviRegisteredUserGroup> m_TmpDict;
+#endif
+
+ protected slots:
+ void itemPressed(KviTalListViewItem *it,const QPoint &pnt,int c);
+ void itemDoubleClicked(KviTalListViewItem *it);
+protected:
+ void fillList();
+protected:
+ virtual void closeEvent(QCloseEvent *);
+ void editItem(KviRegisteredUsersDialogItem * i);
+ void editGroup(KviRegisteredUserGroup* group);
+protected slots:
+ void cancelClicked();
+ void okClicked();
+ void addClicked();
+ void removeClicked();
+ void editClicked();
+ void selectionChanged();
+ void importClicked();
+ void exportClicked();
+ void addWizardClicked();
+ void addGroupClicked();
+ void listViewRightButtonClicked ( KviTalListViewItem *, const QPoint &, int );
+ void moveToGroupMenuClicked(int);
+};
+
+#endif
diff --git a/src/modules/reguser/edituser.cpp b/src/modules/reguser/edituser.cpp
new file mode 100644
index 00000000..f0d6d6b9
--- /dev/null
+++ b/src/modules/reguser/edituser.cpp
@@ -0,0 +1,781 @@
+//=============================================================================
+//
+// File : edituser.cpp
+// Creation date : Tue Dec 26 2000 12:24:12 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+#define _WANT_OPTION_FLAGS_
+#define _EDITUSER_CPP_
+
+#include "edituser.h"
+#include "kvi_regusersdb.h"
+
+#include "kvi_locale.h"
+#include "kvi_ircmask.h"
+#include "kvi_debug.h"
+#include "kvi_iconmanager.h"
+#include "kvi_app.h"
+#include "kvi_options.h"
+#include "kvi_file.h"
+#include "kvi_filedialog.h"
+#include "kvi_msgbox.h"
+#include "kvi_fileutils.h"
+#include "kvi_settings.h"
+#include "kvi_stringconversion.h"
+#include "kvi_options.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qgroupbox.h>
+#ifdef COMPILE_USE_QT4
+#include <qevent.h>
+#include <q3header.h>
+#include <q3vbox.h>
+#else
+#include <qheader.h>
+#endif
+#include "kvi_pointerhashtable.h"
+#include <qimage.h>
+#include <qstring.h>
+#include <qcombobox.h>
+
+
+#include <qstyle.h>
+#include <qpainter.h>
+#include "kvi_tal_hbox.h"
+#include "kvi_tal_vbox.h"
+#include <qinputdialog.h>
+
+#include "wizard.h"
+#include "dialog.h"
+
+
+#ifdef COMPILE_INFO_TIPS
+ #include <qtooltip.h>
+#endif // COMPILE_INFO_TIPS
+
+// kvi_app.cpp
+extern KviRegisteredUsersDialog * g_pRegisteredUsersDialog;
+
+KviRegisteredUserDataBase * g_pLocalRegisteredUserDataBase; // local copy!
+
+
+
+KviReguserPropertiesDialog::KviReguserPropertiesDialog(QWidget * p,KviPointerHashTable<QString,QString> * dict)
+: QDialog(p,"property_editor",true)
+{
+ m_pPropertyDict = dict;
+
+ setCaption(__tr2qs("Property Editor"));
+ setIcon(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_LINUX)));
+
+ QGridLayout * g = new QGridLayout(this,3,3,4,4);
+
+#ifdef COMPILE_USE_QT4
+ m_pTable = new Q3Table(this);
+#else
+ m_pTable = new QTable(this);
+#endif
+ g->addMultiCellWidget(m_pTable,0,1,0,1);
+
+ m_pTable->setNumCols(2);
+ m_pTable->setSelectionMode(Kvi_Tal_Table::NoSelection);
+
+ m_pTable->horizontalHeader()->setLabel(0,__tr2qs("Property"));
+ m_pTable->horizontalHeader()->setLabel(1,__tr2qs("Value"));
+
+ m_pTable->setMinimumSize(250,250);
+ //connect(m_pTable,SIGNAL(valueChanged(int,int)),this,SLOT(propertyValueChanged(int,int)));
+
+ KviTalVBox * vb = new KviTalVBox(this);
+ vb->setSpacing(4);
+ g->addWidget(vb,0,2);
+
+ m_pAddButton = new QPushButton(__tr2qs("&New"),vb);
+ connect(m_pAddButton,SIGNAL(clicked()),this,SLOT(addClicked()));
+ m_pAddButton->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_NEWITEM)));
+
+ m_pDelButton = new QPushButton(__tr2qs("&Remove"),vb);
+ connect(m_pDelButton,SIGNAL(clicked()),this,SLOT(delClicked()));
+ m_pDelButton->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_DELETEITEM)));
+
+ KviTalHBox * b = new KviTalHBox(this);
+ b->setSpacing(4);
+ g->addMultiCellWidget(b,2,2,1,2);
+
+ QPushButton * pb = new QPushButton(__tr2qs("&OK"),b);
+ connect(pb,SIGNAL(clicked()),this,SLOT(okClicked()));
+ pb->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_ACCEPT)));
+
+
+ pb = new QPushButton(__tr2qs("Cancel"),b);
+ connect(pb,SIGNAL(clicked()),this,SLOT(reject()));
+ pb->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_DISCARD)));
+
+ g->setRowStretch(1,1);
+ g->setColStretch(0,1);
+
+ fillData();
+}
+
+KviReguserPropertiesDialog::~KviReguserPropertiesDialog()
+{
+}
+
+void KviReguserPropertiesDialog::closeEvent(QCloseEvent *e)
+{
+ e->accept();
+ //delete this;
+}
+
+void KviReguserPropertiesDialog::fillData()
+{
+ m_pTable->setNumRows(m_pPropertyDict->count());
+ KviPointerHashTableIterator<QString,QString> it(*m_pPropertyDict);
+ int row = 0;
+ while(it.current())
+ {
+ m_pTable->setItem(row,0,new Kvi_Tal_TableItem(m_pTable,Kvi_Tal_TableItem::OnTyping,it.currentKey()));
+ m_pTable->setItem(row,1,new Kvi_Tal_TableItem(m_pTable,Kvi_Tal_TableItem::OnTyping,*(it.current())));
+ ++row;
+ ++it;
+ }
+ if(m_pTable->numRows() == 0)m_pDelButton->setEnabled(false);
+}
+
+void KviReguserPropertiesDialog::okClicked()
+{
+ m_pPropertyDict->clear();
+
+ int n = m_pTable->numRows();
+ for(int i=0;i<n;i++)
+ {
+ QString szName = m_pTable->text(i,0);
+ QString szValue = m_pTable->text(i,1);
+ if((!szName.isEmpty()) && (!szValue.isEmpty()))
+ {
+ m_pPropertyDict->replace(szName,new QString(szValue));
+ }
+ }
+
+ accept();
+}
+
+
+void KviReguserPropertiesDialog::addClicked()
+{
+ m_pTable->setNumRows(m_pTable->numRows() + 1);
+ m_pTable->setItem(m_pTable->numRows() - 1,0,new Kvi_Tal_TableItem(m_pTable,Kvi_Tal_TableItem::OnTyping,""));
+ m_pTable->setItem(m_pTable->numRows() - 1,1,new Kvi_Tal_TableItem(m_pTable,Kvi_Tal_TableItem::OnTyping,""));
+ m_pDelButton->setEnabled(true);
+}
+
+void KviReguserPropertiesDialog::delClicked()
+{
+ int i = m_pTable->currentRow();
+
+ if((i > -1) && (i < m_pTable->numRows()))
+ {
+ // remove row i
+ m_pTable->clearCell(i,0);
+ m_pTable->clearCell(i,1);
+
+ for(;i < (m_pTable->numRows() - 1);i++)
+ {
+ m_pTable->swapRows(i,i+1);
+ }
+ m_pTable->setNumRows(m_pTable->numRows() - 1);
+ if(m_pTable->numRows() == 0)m_pDelButton->setEnabled(false);
+ }
+}
+
+
+KviReguserMaskDialog::KviReguserMaskDialog(QWidget * p,KviIrcMask * m)
+: QDialog(p,"reguser_mask_editor",true)
+{
+ m_pMask = m;
+
+ setCaption(__tr2qs("Mask Editor"));
+
+ QGridLayout * g = new QGridLayout(this,3,2,4,4);
+
+ QLabel * l = new QLabel(__tr2qs("Insert a mask for this user.<br>It can contain the wildcard characters '*' and '?'."),this);
+ //l->setAlignment(Qt::AlignCenter);
+ g->addMultiCellWidget(l,0,0,0,1);
+
+ KviTalHBox * b = new KviTalHBox(this);
+ g->addMultiCellWidget(b,1,1,0,1);
+
+ m_pNickEdit = new QLineEdit(b);
+ //m_pNickEdit->setMinimumWidth(120);
+ m_pNickEdit->setAlignment(Qt::AlignRight);
+#ifdef COMPILE_INFO_TIPS
+ QToolTip::add(m_pNickEdit,__tr2qs("<center>This the <b>nickname</b> that will match this user, default value is the registered name.</center>"));
+#endif
+
+ l = new QLabel("<center><b>!</b></center>",b);
+ l->setAlignment(Qt::AlignCenter);
+ //l->setMinimumWidth(40);
+
+ m_pUserEdit = new QLineEdit(b);
+ //m_pUserEdit->setMinimumWidth(120);
+ m_pUserEdit->setAlignment(Qt::AlignCenter);
+#ifdef COMPILE_INFO_TIPS
+ QToolTip::add(m_pUserEdit,__tr2qs("<center>This the <b>username</b> that will match this user. <b>*</b> will match any username.</center>"));
+#endif
+
+ l = new QLabel("<center><b>@</b></center>",b);
+ l->setAlignment(Qt::AlignCenter);
+ //l->setMinimumWidth(40);
+
+ m_pHostEdit = new QLineEdit(b);
+ //m_pHostEdit->setMinimumWidth(120);
+ m_pHostEdit->setAlignment(Qt::AlignLeft);
+#ifdef COMPILE_INFO_TIPS
+ QToolTip::add(m_pHostEdit,__tr2qs("<center>This the <b>hostname</b> that will match this user. <b>*</b> will match any hostname.</center>"));
+#endif
+
+ // just a spacer
+// l = new QLabel("<nobr>&nbsp;<nobr>",this);
+// g->addMultiCellWidget(l,2,2,0,1);
+
+// QFrame * f = new QFrame(this);
+// f->setFrameStyle(QFrame::HLine | QFrame::Sunken);
+// g->addMultiCellWidget(f,3,3,0,1);
+
+ b = new KviTalHBox(this);
+ b->setSpacing(4);
+ g->addWidget(b,2,1);
+
+ QPushButton * pb = new QPushButton(__tr2qs("&OK"),b);
+ connect(pb,SIGNAL(clicked()),this,SLOT(okClicked()));
+ //pb->setMinimumWidth(120);
+
+ pb = new QPushButton(__tr2qs("Cancel"),b);
+ connect(pb,SIGNAL(clicked()),this,SLOT(reject()));
+ //pb->setMinimumWidth(120);
+
+
+
+ g->setColStretch(0,1);
+ g->setRowStretch(0,1);
+
+ m_pNickEdit->setText(m->nick());
+ m_pUserEdit->setText(m->user());
+ m_pHostEdit->setText(m->host());
+}
+
+KviReguserMaskDialog::~KviReguserMaskDialog()
+{
+}
+
+void KviReguserMaskDialog::closeEvent(QCloseEvent *e)
+{
+ e->accept();
+ //delete this;
+}
+
+void KviReguserMaskDialog::okClicked()
+{
+ KviStr szTmp = m_pNickEdit->text();
+ if(szTmp.isEmpty())szTmp = "*";
+ m_pMask->setNick(szTmp.ptr());
+
+ szTmp = m_pUserEdit->text();
+ if(szTmp.isEmpty())szTmp = "*";
+ m_pMask->setUsername(szTmp.ptr());
+
+ szTmp = m_pHostEdit->text();
+ if(szTmp.isEmpty())szTmp = "*";
+ m_pMask->setHost(szTmp.ptr());
+
+ accept();
+}
+
+
+
+
+KviRegisteredUserEntryDialog::KviRegisteredUserEntryDialog(QWidget *p,KviRegisteredUser * r,bool bModal)
+: KviTalTabDialog(p,"reguser_entry_editor",bModal)
+{
+ m_pUser = r;
+ m_pCustomColor = new QColor();
+
+ if(r)
+ {
+ QString col=r->getProperty("customColor");
+ KviStringConversion::fromString(col,(*m_pCustomColor));
+ }
+
+ m_pPropertyDict = new KviPointerHashTable<QString,QString>(17,false);
+ m_pPropertyDict->setAutoDelete(true);
+
+ //setMinimumSize(400,450);
+
+ setIcon(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_LINUX)));
+ setCaption(__tr2qs("Registered User Entry"));
+
+ QWidget * p1 = new QWidget(this);
+
+ QGridLayout * g = new QGridLayout(p1,6,2,4,4);
+
+ QLabel * l = new QLabel(__tr2qs("Name:"),p1);
+ g->addWidget(l,0,0);
+
+ m_pNameEdit = new QLineEdit(p1);
+ g->addWidget(m_pNameEdit,0,1);
+
+ l = new QLabel(__tr2qs("Comment:"),p1);
+ g->addWidget(l,1,0);
+
+ m_pCommentEdit = new QLineEdit(p1);
+ g->addWidget(m_pCommentEdit,1,1);
+
+ QFrame * f = new QFrame(p1);
+ g->addMultiCellWidget(f,2,2,0,1);
+ f->setFrameStyle(QFrame::HLine | QFrame::Sunken);
+
+ l = new QLabel(__tr2qs("Masks:"),p1);
+ g->addMultiCellWidget(l,3,3,0,1);
+
+ m_pMaskListBox = new KviTalListBox(p1);
+ connect(m_pMaskListBox,SIGNAL(currentChanged(KviTalListBoxItem *)),this,SLOT(maskCurrentChanged(KviTalListBoxItem *)));
+ m_pMaskListBox->setMinimumSize(300,200);
+
+ g->addMultiCellWidget(m_pMaskListBox,4,4,0,1);
+
+ KviTalHBox * b = new KviTalHBox(p1);
+ g->addMultiCellWidget(b,5,5,0,1);
+ b->setSpacing(4);
+
+ m_pAddMaskButton = new QPushButton(__tr2qs("&Add..."),b);
+ connect(m_pAddMaskButton,SIGNAL(clicked()),this,SLOT(addMaskClicked()));
+ m_pAddMaskButton->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_NEWITEM)));
+
+ m_pDelMaskButton = new QPushButton(__tr2qs("Re&move"),b);
+ m_pDelMaskButton->setEnabled(false);
+ connect(m_pDelMaskButton,SIGNAL(clicked()),this,SLOT(delMaskClicked()));
+ m_pDelMaskButton->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_DELETEITEM)));
+
+ m_pEditMaskButton = new QPushButton(__tr2qs("&Edit"),b);
+ m_pEditMaskButton->setEnabled(false);
+ connect(m_pEditMaskButton,SIGNAL(clicked()),this,SLOT(editMaskClicked()));
+ m_pEditMaskButton->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_EDITITEM)));
+
+ g->setRowStretch(4,1);
+ g->setColStretch(1,1);
+
+ addTab(p1,__tr2qs("Identity"));
+
+
+
+ QWidget * p2 = new QWidget(this);
+
+ g = new QGridLayout(p2,6,3,5,2);
+
+ m_pNotifyCheck = new KviStyledCheckBox(__tr2qs("Notify when user is online"),p2);
+ g->addMultiCellWidget(m_pNotifyCheck,0,0,0,2);
+
+ l = new QLabel(__tr2qs("Notify nicknames:"),p2);
+ l->setEnabled(m_pNotifyCheck->isChecked());
+ g->addWidget(l,1,0);
+ connect(m_pNotifyCheck,SIGNAL(toggled(bool)),l,SLOT(setEnabled(bool)));
+#ifdef COMPILE_INFO_TIPS
+ QToolTip::add(m_pNotifyCheck,__tr2qs("<center>You can enter a space separated list of nicknames.</center>"));
+#endif
+
+
+ m_pNotifyNick = new QLineEdit(p2);
+ m_pNotifyNick->setEnabled(false);
+ g->addMultiCellWidget(m_pNotifyNick,1,1,1,2);
+ connect(m_pNotifyCheck,SIGNAL(toggled(bool)),m_pNotifyNick,SLOT(setEnabled(bool)));
+
+
+ f = new QFrame(p2);
+ f->setFrameStyle(QFrame::HLine | QFrame::Sunken);
+ g->addMultiCellWidget(f,2,2,0,2);
+
+ m_pAvatar = 0;
+ if(r)
+ {
+ const char * av = r->getProperty("avatar");
+ if(av)
+ {
+ m_pAvatar = new KviPixmap(av);
+ }
+ }
+ if(!m_pAvatar)m_pAvatar = new KviPixmap();
+
+ m_pAvatarSelector = new KviPixmapSelector(p2,__tr2qs("Avatar"),m_pAvatar,true);
+ g->addMultiCellWidget(m_pAvatarSelector,3,3,0,2);
+
+ f = new QFrame(p2);
+ f->setFrameStyle(QFrame::HLine | QFrame::Sunken);
+ g->addMultiCellWidget(f,4,4,0,2);
+
+ m_pCustomColorCheck = new KviStyledCheckBox(__tr2qs("Use custom color in userlist"),p2);
+ if(r)
+ m_pCustomColorCheck->setChecked(r->getBoolProperty("useCustomColor"));
+ g->addMultiCellWidget(m_pCustomColorCheck,5,5,0,1);
+
+ m_pCustomColorSelector = new KviColorSelector(p2,QString::null,m_pCustomColor,1);
+ g->addWidget(m_pCustomColorSelector,5,2);
+
+ QPushButton * pb = new QPushButton(__tr2qs("All Properties..."),p2);
+ connect(pb,SIGNAL(clicked()),this,SLOT(editAllPropertiesClicked()));
+ g->addWidget(pb,6,2);
+
+ g->setColStretch(1,1);
+ g->setRowStretch(3,1);
+
+ addTab(p2,__tr2qs("Properties"));
+
+ // Ignore TAB
+#ifdef COMPILE_USE_QT4
+ Q3VBox * vb = new Q3VBox(this);
+#else
+ QVBox * vb = new QVBox(this);
+#endif
+ vb->setMargin(10);
+
+ m_pIgnoreEnabled = new KviStyledCheckBox(__tr2qs("Enable ignore for this user"),vb);
+
+ QGroupBox * gb = new QGroupBox(__tr2qs("Ignore features"),vb);
+ connect(m_pIgnoreEnabled,SIGNAL(toggled(bool)),gb,SLOT(setEnabled(bool)));
+
+ QVBoxLayout * layout = new QVBoxLayout(gb,20,3);
+
+ m_pIgnoreQuery = new KviStyledCheckBox(__tr2qs("Ignore query-messages"),gb);
+ layout->addWidget(m_pIgnoreQuery);
+
+ m_pIgnoreChannel = new KviStyledCheckBox(__tr2qs("Ignore channel-messages"),gb);
+ layout->addWidget(m_pIgnoreChannel);
+
+ m_pIgnoreNotice = new KviStyledCheckBox(__tr2qs("Ignore notice-messages"),gb);
+ layout->addWidget(m_pIgnoreNotice);
+
+ m_pIgnoreCtcp = new KviStyledCheckBox(__tr2qs("Ignore ctcp-messages"),gb);
+ layout->addWidget(m_pIgnoreCtcp);
+
+ m_pIgnoreInvite = new KviStyledCheckBox(__tr2qs("Ignore invites"),gb);
+ layout->addWidget(m_pIgnoreInvite);
+
+ m_pIgnoreDcc = new KviStyledCheckBox(__tr2qs("Ignore DCCs"),gb);
+ layout->addWidget(m_pIgnoreDcc);
+
+ QWidget *w = new QWidget(vb);
+ w->setSizePolicy(QSizePolicy::Ignored,QSizePolicy::Ignored);
+
+ addTab(vb,__tr2qs("Ignore"));
+
+ setCancelButton(__tr2qs("Cancel"));
+ setOkButton(__tr2qs("&OK"));
+ connect(this,SIGNAL(applyButtonPressed()),this,SLOT(okClicked()));
+ connect(this,SIGNAL(cancelButtonPressed()),this,SLOT(reject()));
+
+ if(r)
+ {
+ m_pNameEdit->setText(r->name());
+ m_pCommentEdit->setText(r->getProperty("comment"));
+ for(KviIrcMask * m = r->maskList()->first();m;m = r->maskList()->next())
+ {
+ QString mk = m->nick();
+ mk += QChar('!');
+ mk += m->user();
+ mk += QChar('@');
+ mk += m->host();
+ m_pMaskListBox->insertItem(mk);
+ }
+
+ QString szNotifyNicks = r->getProperty("notify");
+ if(!szNotifyNicks.isEmpty())
+ {
+ m_pNotifyCheck->setChecked(true);
+ m_pNotifyNick->setText(szNotifyNicks);
+ m_pNotifyNick->setEnabled(true);
+ }
+
+ if(r->propertyDict())
+ {
+ KviPointerHashTableIterator<QString,QString> it(*(r->propertyDict()));
+ while(QString *s = it.current())
+ {
+ m_pPropertyDict->insert(it.currentKey(),new QString(*s));
+ ++it;
+ }
+ }
+
+ m_pIgnoreEnabled->setChecked(r->ignoreEnagled());
+
+ gb->setEnabled(r->ignoreEnagled());
+
+ m_pIgnoreQuery->setChecked(r->ignoreFlags() & KviRegisteredUser::Query);
+ m_pIgnoreChannel->setChecked(r->ignoreFlags() & KviRegisteredUser::Channel);
+ m_pIgnoreNotice->setChecked(r->ignoreFlags() & KviRegisteredUser::Notice);
+ m_pIgnoreCtcp->setChecked(r->ignoreFlags() & KviRegisteredUser::Ctcp);
+ m_pIgnoreInvite->setChecked(r->ignoreFlags() & KviRegisteredUser::Invite);
+ m_pIgnoreDcc->setChecked(r->ignoreFlags() & KviRegisteredUser::Dcc);
+ } else {
+ // default values
+ if(!m_pIgnoreEnabled->isChecked())
+ {
+ gb->setEnabled(false);
+ }
+ }
+}
+
+void KviRegisteredUserEntryDialog::closeEvent(QCloseEvent *e)
+{
+ e->accept();
+ okClicked();
+ //delete this;
+}
+
+KviRegisteredUserEntryDialog::~KviRegisteredUserEntryDialog()
+{
+ delete m_pAvatar;
+ delete m_pPropertyDict;
+ delete m_pCustomColor;
+}
+
+void KviRegisteredUserEntryDialog::maskCurrentChanged(KviTalListBoxItem *it)
+{
+ m_pDelMaskButton->setEnabled(it);
+ m_pEditMaskButton->setEnabled(it);
+}
+
+void KviRegisteredUserEntryDialog::okClicked()
+{
+ QString szGroup;
+ if(m_pUser)
+ {
+ szGroup=m_pUser->group();
+ g_pLocalRegisteredUserDataBase->removeUser(m_pUser->name());
+ }
+
+ QString name = m_pNameEdit->text();
+
+ if(name.isEmpty())name = "user";
+
+ KviRegisteredUser * u;
+
+ QString szNameOk = name;
+
+ int idx = 1;
+
+ do {
+ u = g_pLocalRegisteredUserDataBase->findUserByName(szNameOk);
+ if(u)
+ {
+ KviQString::sprintf(szNameOk,"%Q%d",&name,idx);
+ idx++;
+ }
+ } while(u);
+
+
+ u = g_pLocalRegisteredUserDataBase->addUser(szNameOk);
+ u->setGroup(szGroup);
+
+ if(!u)
+ {
+ // ops... no way
+ // FIXME: spit an error message ?
+ debug("Ops.. something wrong with the regusers db");
+ accept();
+ return;
+ }
+
+ int cnt = m_pMaskListBox->count();
+ idx = 0;
+ while(cnt > 0)
+ {
+ QString mask = m_pMaskListBox->text(idx);
+ KviIrcMask * mk = new KviIrcMask(mask);
+ g_pLocalRegisteredUserDataBase->removeMask(*mk);
+ g_pLocalRegisteredUserDataBase->addMask(u,mk);
+ cnt--;
+ idx++;
+ }
+ u->setProperty("comment",m_pCommentEdit->text());
+
+ m_pAvatarSelector->commit();
+
+ if(!m_pAvatar->isNull())
+ {
+ QString szPath = m_pAvatar->path();
+ u->setProperty("avatar",szPath);
+ }
+
+ if(m_pNotifyCheck->isChecked())
+ {
+ QString szNicks = m_pNotifyNick->text();
+
+ if(!szNicks.isEmpty())
+ {
+ u->setProperty("notify",szNicks);
+ }
+ }
+
+ m_pPropertyDict->remove("notify");
+ m_pPropertyDict->remove("avatar");
+
+ KviPointerHashTableIterator<QString,QString> it(*m_pPropertyDict);
+ while(QString *s = it.current())
+ {
+ u->setProperty(it.currentKey(),*s);
+ ++it;
+ }
+
+ u->setProperty("useCustomColor",m_pCustomColorCheck->isChecked());
+
+ QString col;
+ KviStringConversion::toString(m_pCustomColorSelector->getColor(),col);
+ u->setProperty("customColor",col);
+
+
+ int iIgnoreFlags=0;
+ u->setIgnoreEnabled(m_pIgnoreEnabled->isChecked());
+ if(m_pIgnoreQuery->isChecked())
+ iIgnoreFlags |= KviRegisteredUser::Query;
+ if(m_pIgnoreChannel->isChecked())
+ iIgnoreFlags |= KviRegisteredUser::Channel;
+ if(m_pIgnoreNotice->isChecked())
+ iIgnoreFlags |= KviRegisteredUser::Notice;
+ if(m_pIgnoreCtcp->isChecked())
+ iIgnoreFlags |= KviRegisteredUser::Ctcp;
+ if(m_pIgnoreInvite->isChecked())
+ iIgnoreFlags |= KviRegisteredUser::Invite;
+ if(m_pIgnoreDcc->isChecked())
+ iIgnoreFlags |= KviRegisteredUser::Dcc;
+
+ u->setIgnoreFlags(iIgnoreFlags);
+ accept();
+ g_pApp->optionResetUpdate(KviOption_resetUpdateGui);
+}
+
+
+void KviRegisteredUserEntryDialog::addMaskClicked()
+{
+ KviIrcMask mk;
+ KviReguserMaskDialog * dlg = new KviReguserMaskDialog(this,&mk);
+ if(dlg->exec() == QDialog::Accepted)
+ {
+ QString m = mk.nick();
+ m += QChar('!');
+ m += mk.user();
+ m += QChar('@');
+ m += mk.host();
+ m_pMaskListBox->insertItem(m);
+ }
+ delete dlg;
+}
+
+void KviRegisteredUserEntryDialog::delMaskClicked()
+{
+ int idx = m_pMaskListBox->currentItem();
+ if(idx == -1)return;
+ m_pMaskListBox->removeItem(idx);
+}
+
+void KviRegisteredUserEntryDialog::editMaskClicked()
+{
+ int idx = m_pMaskListBox->currentItem();
+ if(idx == -1)return;
+ KviStr szM = m_pMaskListBox->text(idx);
+ if(szM.isEmpty())return;
+
+ KviIrcMask mk(szM.ptr());
+ KviReguserMaskDialog * dlg = new KviReguserMaskDialog(this,&mk);
+ if(dlg->exec() == QDialog::Accepted)
+ {
+ QString m = mk.nick();
+ m += QChar('!');
+ m += mk.user();
+ m += QChar('@');
+ m += mk.host();
+ m_pMaskListBox->changeItem(m,idx);
+ }
+ delete dlg;
+}
+
+void KviRegisteredUserEntryDialog::editAllPropertiesClicked()
+{
+ m_pAvatarSelector->commit();
+
+ if(m_pAvatar->isNull())
+ {
+ m_pPropertyDict->remove("avatar");
+ } else {
+ KviStr szPath = m_pAvatar->path();
+ if(szPath.isEmpty())m_pPropertyDict->remove("avatar");
+ else m_pPropertyDict->replace("avatar",new QString(szPath));
+ }
+
+ if(m_pNotifyCheck->isChecked())
+ {
+ QString szNicks = m_pNotifyNick->text();
+
+ if(!szNicks.isEmpty())
+ {
+ m_pPropertyDict->replace("notify",new QString(szNicks));
+ } else {
+ m_pPropertyDict->remove("notify");
+ }
+ } else {
+ m_pPropertyDict->remove("notify");
+ }
+
+
+ KviReguserPropertiesDialog * dlg = new KviReguserPropertiesDialog(this,m_pPropertyDict);
+ if(dlg->exec() != QDialog::Accepted)
+ {
+ delete dlg;
+ return;
+ }
+ delete dlg;
+
+ QString * notify = m_pPropertyDict->find("notify");
+ bool bGotIt = false;
+ if(notify)
+ {
+ if(!notify->isEmpty())
+ {
+ bGotIt = true;
+ m_pNotifyNick->setText(*notify);
+ }
+ }
+ m_pNotifyCheck->setChecked(bGotIt);
+ m_pNotifyNick->setEnabled(bGotIt);
+ if(!bGotIt)m_pNotifyNick->setText("");
+
+ QString * avatar = m_pPropertyDict->find("avatar");
+ bGotIt = false;
+ if(avatar)
+ {
+ if(!avatar->isEmpty())
+ m_pAvatarSelector->setImagePath(*avatar);
+ }
+
+}
+
+
+
+
+#include "edituser.moc"
diff --git a/src/modules/reguser/edituser.h b/src/modules/reguser/edituser.h
new file mode 100644
index 00000000..fecbbf09
--- /dev/null
+++ b/src/modules/reguser/edituser.h
@@ -0,0 +1,152 @@
+#ifndef _EDITUSER_H_
+#define _EDITUSER_H_
+//=============================================================================
+//
+// File : edituser.h
+// Creation date : Sun Dec 24 2000 15:16:17 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_string.h"
+#include "kvi_regusersdb.h"
+#include "kvi_selectors.h"
+
+#include <qwidget.h>
+#include <qlineedit.h>
+#include <qpushbutton.h>
+#include "kvi_tal_listview.h"
+#include "kvi_tal_listbox.h"
+#include "kvi_pointerhashtable.h"
+#include <kvi_tal_tabdialog.h>
+#ifdef COMPILE_USE_QT4
+#include <q3table.h>
+#define Kvi_Tal_Table Q3Table
+#define Kvi_Tal_TableItem Q3TableItem
+
+#else
+#include <qtable.h>
+#define Kvi_Tal_Table QTable
+#define Kvi_Tal_TableItem QTableItem
+
+#endif
+#include "kvi_tal_popupmenu.h"
+
+#ifndef _EDITUSER_CPP_
+ extern KviRegisteredUserDataBase * g_pLocalRegisteredUserDataBase;
+#endif
+
+class KviRegisteredUser;
+
+class KviReguserPropertiesDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ KviReguserPropertiesDialog(QWidget *p,KviPointerHashTable<QString,QString> * dict);
+ ~KviReguserPropertiesDialog();
+protected:
+#ifdef COMPILE_USE_QT4
+ Q3Table *m_pTable;
+#else
+ QTable * m_pTable;
+#endif
+ KviPointerHashTable<QString,QString> * m_pPropertyDict;
+ QPushButton * m_pDelButton;
+ QPushButton * m_pAddButton;
+protected:
+ void fillData();
+ virtual void closeEvent(QCloseEvent *);
+protected slots:
+ void okClicked();
+ void addClicked();
+ void delClicked();
+};
+
+
+class KviReguserMaskDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ KviReguserMaskDialog(QWidget * p,KviIrcMask * m);
+ ~KviReguserMaskDialog();
+protected:
+ KviIrcMask * m_pMask;
+
+ QLineEdit * m_pNickEdit;
+ QLineEdit * m_pUserEdit;
+ QLineEdit * m_pHostEdit;
+
+ virtual void closeEvent(QCloseEvent *);
+protected slots:
+ void okClicked();
+};
+
+
+class KviRegisteredUserEntryDialog : public KviTalTabDialog
+{
+ Q_OBJECT
+public:
+ KviRegisteredUserEntryDialog(QWidget * p,KviRegisteredUser * r,bool bModal = true);
+ virtual ~KviRegisteredUserEntryDialog();
+protected:
+ KviRegisteredUser * m_pUser;
+
+ QLineEdit * m_pNameEdit;
+ QLineEdit * m_pCommentEdit;
+
+ KviTalListBox * m_pMaskListBox;
+
+ QPushButton * m_pDelMaskButton;
+ QPushButton * m_pEditMaskButton;
+ QPushButton * m_pAddMaskButton;
+
+ QCheckBox * m_pNotifyCheck;
+ QLineEdit * m_pNotifyNick;
+
+ KviPixmap * m_pAvatar;
+ KviPixmapSelector * m_pAvatarSelector;
+
+ KviPointerHashTable<QString,QString> * m_pPropertyDict;
+
+ QCheckBox * m_pCustomColorCheck;
+ QColor * m_pCustomColor;
+ KviColorSelector * m_pCustomColorSelector;
+
+ //Ignore TAB
+ QCheckBox * m_pIgnoreEnabled;
+ QCheckBox * m_pIgnoreQuery;
+ QCheckBox * m_pIgnoreChannel;
+ QCheckBox * m_pIgnoreNotice;
+ QCheckBox * m_pIgnoreCtcp;
+ QCheckBox * m_pIgnoreInvite;
+ QCheckBox * m_pIgnoreDcc;
+
+ virtual void closeEvent(QCloseEvent *);
+protected slots:
+ void okClicked();
+ void addMaskClicked();
+ void delMaskClicked();
+ void editMaskClicked();
+ void editAllPropertiesClicked();
+ void maskCurrentChanged(KviTalListBoxItem *it);
+};
+
+
+
+#endif //_EDITUSER_H_
diff --git a/src/modules/reguser/libkvireguser.cpp b/src/modules/reguser/libkvireguser.cpp
new file mode 100644
index 00000000..49e4a204
--- /dev/null
+++ b/src/modules/reguser/libkvireguser.cpp
@@ -0,0 +1,1239 @@
+//=============================================================================
+//
+// File : libkvireguser.cpp
+// Creation date : Fri Dec 01 2000 14:53:10 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_module.h"
+
+#include "kvi_regusersdb.h"
+#include "kvi_ircuserdb.h"
+#include "kvi_out.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_window.h"
+#include "kvi_locale.h"
+#include "kvi_app.h"
+#include "kvi_window.h"
+#include "kvi_frame.h"
+
+#include "edituser.h"
+#include "wizard.h"
+#include "kvi_ircconnection.h"
+#include "dialog.h"
+
+#include "kvi_pointerlist.h"
+#include <qsplitter.h> // FIXME: REmove this!
+
+//#warning "$reguser.matches..."
+//#warning "$reguser.clear"
+
+//#warning "THIS MODULE HAS TO BE REVISED (notify list consistency!!!)"
+
+// kvi_app.cpp
+
+
+extern KVIRC_API KviRegisteredUserDataBase * g_pRegisteredUserDataBase;
+
+KviPointerList<KviRegistrationWizard> * g_pRegistrationWizardList = 0;
+
+KviRegisteredUsersDialog * g_pRegisteredUsersDialog = 0;
+
+/*
+ @doc: reguser
+ @type:
+ module
+ @short:
+ Interface to the registered users database
+ @title:
+ The reguser module
+ @body:
+ The reguser module is the scripting interface to the [doc:registered_users]registered users database[/doc].[br]
+ It provides the following set of commands:[br]
+ [cmd]reguser.add[/cmd]: adds an user entry to the database[br]
+ [cmd]reguser.addmask[/cmd]: adds an user's mask to the database[br]
+ [cmd]reguser.remove[/cmd]: removes an user entry from the database[br]
+ [fnc]$reguser.list[/fnc]: lists the entries[br]
+ [cmd]reguser.setproperty[/cmd]: sets a property associated to an entry[br]
+ [cmd]reguser.edit[/cmd]: shows an editor for an user entry
+ [fnc]$reguser.match[/fnc](): finds an entry by matching masks[br]
+ [fnc]$reguser.exactMatch[/fnc](): finds an entry by comparing masks[br]
+ [fnc]$reguser.property[/fnc](): finds a property associated to an entry[br]
+ [fnc]$reguser.matchProperty[/fnc](): shortcut for [fnc]$reguser.property[/fnc]([fnc]$reguser.match[/fnc]())[br]
+ [fnc]$reguser.mask[/fnc](): returns the registration masks for an entry
+*/
+
+/*
+ @doc: reguser.edit
+ @type:
+ command
+ @title:
+ reguser.edit
+ @keyterms:
+ registering users
+ @short:
+ Opens the registeredusers dialog
+ @syntax:
+ reguser.edit [-t]
+ @switches:
+ !sw: -t | --toplevel
+ the editor is created as a toplevel window (dialog)
+ @description:
+ Shows the registered user database editor.[br]
+ If the [-t] switch is passed, the editor is created as a toplevel window (dialog), otherwise
+ it is created as part of the current main window.[br]
+ @examples:
+ @seealso:
+ [module:reguser]Registered users database interface[/module],
+ [doc:registered_users]Registered users database[/doc],
+ [cmd]reguser.add[/cmd],
+ [cmd]reguser.remove[/cmd],
+ [cmd]reguser.addmask[/cmd],
+ [fnc]$reguser.list[/fnc]
+*/
+
+static bool reguser_kvs_cmd_edit(KviKvsModuleCommandCall * c)
+{
+ if(g_pRegisteredUsersDialog)
+ {
+ if(c->hasSwitch('t',"toplevel"))
+ {
+ if(g_pRegisteredUsersDialog->parent())
+ {
+ g_pRegisteredUsersDialog->reparent(0,QPoint(0,0),true);
+ }
+ } else {
+ if(g_pRegisteredUsersDialog->parent() != c->window()->frame()->splitter())
+ {
+ g_pRegisteredUsersDialog->reparent(c->window()->frame()->splitter(),QPoint(0,0),true);
+ }
+ }
+ } else {
+ if(c->hasSwitch('t',"toplevel"))
+ {
+ g_pRegisteredUsersDialog = new KviRegisteredUsersDialog(0);
+ } else {
+ g_pRegisteredUsersDialog = new KviRegisteredUsersDialog(c->window()->frame()->splitter());
+ }
+ }
+ g_pRegisteredUsersDialog->show();
+ g_pRegisteredUsersDialog->raise();
+ g_pRegisteredUsersDialog->setFocus();
+ return true;
+}
+
+/*
+ @doc: reguser.add
+ @type:
+ command
+ @title:
+ reguser.add
+ @keyterms:
+ registering users
+ @short:
+ Registers an user
+ @syntax:
+ reguser.add [-r] [-f] [-q] [-g=group] <name> [mask]
+ @description:
+ Adds a new entry with the specified <name> to the database.[br]
+ If the database contains an entry with the same <name>, this command just prints
+ a warning and returns.[br]
+ If no [mask] is given the new entry has no registration masks: so it can't be "matched" yet. You have to add
+ at least one mask with [cmd]reguser.addmask[/cmd].
+ If [mask] is given, then it is added to the entry mask list.[br]
+ The <name> parameter may contain any character: even spaces are allowed (obviously you have to
+ use quotes in that case).[br]
+ If the '-r' switch is given , the new entry replaces any previous one with the same <name> (the old entry is removed).[br]
+ If the '-f' switch is given , and there is an existing entry with the same name , no warning is printed
+ and the old entry is treated just like it has been just added (thus the [mask] is eventually added to its mask list).[br]
+ The '-q' switch causes the command to run in "quiet" mode and print no warning.[br]
+ @examples:
+ [example]
+ reguser.add Pragma
+ [/example]
+ @seealso:
+ [module:reguser]Registered users database interface[/module],
+ [doc:registered_users]Registered users database[/doc],
+ [cmd]reguser.remove[/cmd],
+ [cmd]reguser.addmask[/cmd],
+ [fnc]$reguser.list[/fnc]
+*/
+
+static bool reguser_kvs_cmd_add(KviKvsModuleCommandCall * c)
+{
+ QString szName;
+ QString szMask;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("name",KVS_PT_STRING,0,szName)
+ KVSM_PARAMETER("mask",KVS_PT_STRING,0,szMask)
+ KVSM_PARAMETERS_END(c)
+ if(szName.isEmpty())
+ {
+ if(!c->hasSwitch('q',"quiet"))c->warning(__tr2qs("No name specified"));
+ return true;
+ }
+
+ if(c->hasSwitch('r',"replace"))g_pRegisteredUserDataBase->removeUser(szName);
+
+
+ KviRegisteredUser * u = g_pRegisteredUserDataBase->addUser(szName);
+ QString group;
+ if(c->hasSwitch('g',"group"))
+ {
+ c->switches()->getAsStringIfExisting('g',"group",group);
+ u->setGroup(group);
+ }
+ if(u == 0)
+ {
+ if(c->hasSwitch('f',"force"))
+ {
+ u = g_pRegisteredUserDataBase->findUserByName(szName);
+ } else {
+ if(!c->hasSwitch('q',"quiet"))c->warning(__tr2qs("User already registered: found exact name match"));
+ }
+ }
+
+
+ if(u)
+ {
+ if(!szMask.isEmpty())
+ {
+ KviIrcMask * m = new KviIrcMask(szMask);
+ u = g_pRegisteredUserDataBase->addMask(u,m);
+ if(u != 0)
+ {
+ if(!c->hasSwitch('q',"quiet"))c->warning(__tr2qs("Mask %Q is already used to identify user %s"),&szMask,u->name().utf8().data());
+ }
+ }
+ }
+ return true;
+}
+
+/*
+ @doc: reguser.remove
+ @type:
+ command
+ @title:
+ reguser.remove
+ @keyterms:
+ unregistering users
+ @short:
+ Removes an entry from the regusers database
+ @syntax:
+ reguser.remove [-q] [-n] <name>
+ @description:
+ Removes the regusers database entry with the specified <name>.[br]
+ If the -n switch is given, and there is a removed entry,
+ this command will restart all the running "notify lists".
+ If the -q switch is used , no warning is printed if the <name>
+ does not identify an existing entry.
+ @examples:
+ [example]
+ [cmd]reguser.add[/cmd] Pragma
+ reguser.remove Pragma
+ [example]
+ @seealso:
+ [module:reguser]Registered users database interface[/module],
+ [doc:registered_users]Registered users database[/doc],
+ [cmd]reguser.add[/cmd],
+ [cmd]reguser.addmask[/cmd],
+ [fnc]$reguser.list[/fnc]
+*/
+
+static bool reguser_kvs_cmd_remove(KviKvsModuleCommandCall * c)
+{
+ QString szName;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("name",KVS_PT_STRING,0,szName)
+ KVSM_PARAMETERS_END(c)
+
+ if(szName.isEmpty())
+ {
+ if(!c->hasSwitch('q',"quiet"))c->warning(__tr2qs("No name specified"));
+ return true;
+ }
+
+ if(!(g_pRegisteredUserDataBase->removeUser(szName)))
+ {
+ c->warning(__tr2qs("User not found (%Q)"),&szName);
+ } else {
+ if(c->hasSwitch('n',"restartnotifylists"))g_pApp->restartNotifyLists();
+ }
+ return true;
+}
+
+/*
+ @doc: reguser.addmask
+ @type:
+ command
+ @title:
+ reguser.addmask
+ @keyterms:
+ registering users
+ @short:
+ Adds a mask to a registered user
+ @syntax:
+ reguser.addmask [-f] <name> <mask>
+ @description:
+ Adds a registration mask to the database entry with name <name>.[br]
+ The <mask> has the common [doc:irc_masks]irc mask[/doc] format.[br]
+ The only restriction on the <mask> is that it must be unique inside the
+ regusers database: you can't match two users with the same mask (it would
+ have rather undefined results).[br]
+ If -f is used , KVIrc ensures that the mask is unique in the database
+ and associates is to THIS registered user (breaking the previous associations).<br>
+ Once at least one mask has been added, the user can be "matched"
+ by using the [fnc]$reguser.match[/fnc]() function.[br]
+ Each database entry can have an unlimited number of masks.[br]
+ @examples:
+ [example]
+ [cmd]reguser.add[/cmd] "Szymon Stefanek"
+ reguser.addmask "Szymon Stefanek" Pragma!*@*.it
+ [/example]
+ @seealso:
+ [module:reguser]Registered users database interface[/module],
+ [doc:registered_users]Registered users database[/doc],
+ [cmd]reguser.add[cmd],
+ [cmd]reguser.remove[/cmd],
+ [cmd]reguser.delmask[/cmd],
+ [fnc]$reguser.list[/fnc],
+ [fnc]$reguser.match[/fnc],
+ [fnc]$reguser.exactMatch[/fnc]
+*/
+
+static bool reguser_kvs_cmd_addmask(KviKvsModuleCommandCall * c)
+{
+ QString szName;
+ QString szMask;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("name",KVS_PT_STRING,0,szName)
+ KVSM_PARAMETER("mask",KVS_PT_STRING,0,szMask)
+ KVSM_PARAMETERS_END(c)
+
+ if(szName.isEmpty())
+ {
+ c->warning(__tr2qs("No name specified"));
+ return true;
+ }
+
+ if(szMask.isEmpty())
+ {
+ c->warning(__tr2qs("No mask specified"));
+ return true;
+ }
+
+ KviRegisteredUser * u = g_pRegisteredUserDataBase->findUserByName(szName);
+ if(!u)
+ {
+ c->warning(__tr2qs("User %Q not found"),&szName);
+ return true;
+ }
+
+ KviIrcMask * mk = new KviIrcMask(szMask);
+
+ if(c->hasSwitch('f',"force"))g_pRegisteredUserDataBase->removeMask(*mk);
+
+ u = g_pRegisteredUserDataBase->addMask(u,mk);
+
+ if(u != 0)c->warning(__tr2qs("Mask %Q already used to identify user %Q"),&szMask,&(u->name()));
+ return true;
+}
+
+/*
+ @doc: reguser.delmask
+ @type:
+ command
+ @title:
+ reguser.delmask
+ @keyterms:
+ registering users
+ @short:
+ Removes a mask from the regusers database
+ @syntax:
+ reguser.delmask <mask>
+ @description:
+ Removes a mask from the regusers database.[br]
+ Since masks are unique in the database , you don't need to pass
+ an <user> parameter: if an <user> entry has the <mask>, removing that <mask>
+ will surely remove it from that <user> entry. (contorsions ?)[br]
+ @examples:
+ [example]
+ [cmd]reguser.add[/cmd] "Szymon Stefanek"
+ [cmd]reguser.addmask[/cmd] "Szymon Stefanek" Pragma!*@*.it
+ reguser.delmask Pragma!*@*.it
+ [fnc]$reguser.list[/fnc]
+ [/example]
+ @seealso:
+ [module:reguser]Registered users database interface[/module],
+ [doc:registered_users]Registered users database[/doc],
+ [cmd]reguser.add[/cmd],
+ [cmd]reguser.remove[/cmd],
+ [cmd]reguser.addmask[/cmd],
+ [fnc]$reguser.list[/fnc],
+ [fnc]$reguser.match[/fnc],
+ [fnc]$reguser.exactMatch[/fnc]
+*/
+
+static bool reguser_kvs_cmd_delmask(KviKvsModuleCommandCall * c)
+{
+ QString szMask;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("mask",KVS_PT_STRING,0,szMask)
+ KVSM_PARAMETERS_END(c)
+
+ if(szMask.isEmpty())
+ {
+ c->warning(__tr2qs("No mask specified"));
+ return true;
+ }
+
+ KviIrcMask mk(szMask);
+ if(!g_pRegisteredUserDataBase->removeMask(mk))
+ {
+ c->warning(__tr2qs("Mask %Q not found"),&szMask);
+ }
+
+ return true;
+}
+
+/*
+ @doc: reguser.setIgnoreEnabled
+ @type:
+ command
+ @title:
+ reguser.setIgnoreEnabled
+ @keyterms:
+ enable/disable ignoring of this user
+ @short:
+ Enable/disable ignoring of this user
+ @syntax:
+ reguser.setIgnoreEnabled [-q] <name:string> <isEnabled:bool>
+ @description:
+
+ @examples:
+ [example]
+ reguser.setproperty "Alexey" $true
+ [/example]
+ @seealso:
+ [module:reguser]Registered users database interface[/module],
+ [doc:registered_users]Registered users database[/doc],
+ [fnc]$reguser.matchProperty[/fnc],
+ [fnc]$reguser.property[/fnc]
+*/
+
+static bool reguser_kvs_cmd_setIgnoreEnabled(KviKvsModuleCommandCall * c)
+{
+ QString szName;
+ bool bEnabled;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("name",KVS_PT_STRING,0,szName)
+ KVSM_PARAMETER("isEnabled",KVS_PT_BOOL,0,bEnabled)
+ KVSM_PARAMETERS_END(c)
+
+ if(szName.isEmpty())
+ {
+ if(!c->hasSwitch('q',"quiet"))c->warning(__tr2qs("No name specified"));
+ return true;
+ }
+
+ KviRegisteredUser * u = g_pRegisteredUserDataBase->findUserByName(szName);
+ if(!u)
+ {
+ if(!c->hasSwitch('q',"quiet"))c->warning(__tr2qs("User %Q not found"),&szName);
+ } else {
+ u->setIgnoreEnabled(bEnabled);
+ }
+ return true;
+}
+
+
+/*
+ @doc: reguser.setIgnoreFlags
+ @type:
+ command
+ @title:
+ reguser.setIgnoreFlags
+ @keyterms:
+ Sets ignore flags for registered user
+ @short:
+ Sets ignore flags for registered user
+ @syntax:
+ reguser.setIgnoreFlags [-p|--query] [-c|--channel] [-n|--notice] [-t|--ctcp] [-i|--invite] [-d|--dcc] [-q] <name:string>
+ @switches:
+ !sw: -q | --quiet
+ Don't warn if the specified user doesn't exist. Just continue silently.
+ !sw: -p | --query
+ Sets ignore for query messages and actions
+ !sw: -c | --channel
+ Sets ignore for channel messages and actions
+ !sw: -n | --notice
+ Sets ignore for notices
+ !sw: -t | --ctcp
+ Sets ignore for CTCP's
+ !sw: -i | --invite
+ Sets ignore for invites
+ !sw: -d | --dcc
+ Sets ignore for DCC's
+
+ @description:
+ Sets ignore flags for registered user
+ @examples:
+ [example]
+ reguser.setproperty "Alexey" $true
+ [/example]
+ @seealso:
+ [module:reguser]Registered users database interface[/module],
+ [doc:registered_users]Registered users database[/doc],
+ [fnc]$reguser.matchProperty[/fnc],
+ [fnc]$reguser.property[/fnc]
+*/
+
+static bool reguser_kvs_cmd_setIgnoreFlags(KviKvsModuleCommandCall * c)
+{
+ QString szName;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("name",KVS_PT_STRING,0,szName)
+ KVSM_PARAMETERS_END(c)
+
+ if(szName.isEmpty())
+ {
+ if(!c->hasSwitch('q',"quiet"))c->warning(__tr2qs("No name specified"));
+ return true;
+ }
+
+ KviRegisteredUser * u = g_pRegisteredUserDataBase->findUserByName(szName);
+ if(!u)
+ {
+ if(!c->hasSwitch('q',"quiet"))c->warning(__tr2qs("User %Q not found"),&szName);
+ } else {
+ int iIgnoreFlags=0;
+ if(c->hasSwitch('p',"query"))
+ iIgnoreFlags |= KviRegisteredUser::Query;
+ if(c->hasSwitch('c',"channel"))
+ iIgnoreFlags |= KviRegisteredUser::Channel;
+ if(c->hasSwitch('n',"notice"))
+ iIgnoreFlags |= KviRegisteredUser::Notice;
+ if(c->hasSwitch('t',"ctcp"))
+ iIgnoreFlags |= KviRegisteredUser::Ctcp;
+ if(c->hasSwitch('i',"invite"))
+ iIgnoreFlags |= KviRegisteredUser::Invite;
+ if(c->hasSwitch('d',"dcc"))
+ iIgnoreFlags |= KviRegisteredUser::Dcc;
+ u->setIgnoreFlags(iIgnoreFlags);
+ }
+ return true;
+}
+
+/*
+ @doc: reguser.getIgnoreFlags
+ @type:
+ function
+ @title:
+ $reguser.getIgnoreFlags
+ @short:
+ Returns ignore flags for registered user
+ @syntax:
+ $reguser.getIgnoreFlags(<name:string>)
+ @description:
+ Returns the ignore flags for registered user. Flags are string of letters:[br]
+ p - query ignore[br]
+ c - channel ignore[br]
+ t - ctcp ignore[br]
+ n - notice ignore[br]
+ d - dcc ignore[br]
+ i - invite ignore[br]
+ @seealso:
+ [module:reguser]Registered users database interface[/module],
+ [doc:registered_users]Registered users database[/doc],
+ [cmd]reguser.add[/cmd],
+ [cmd]reguser.remove[/cmd],
+ [cmd]reguser.addmask[/cmd],
+ [cmd]reguser.delmask[/cmd],
+ [fnc]$reguser.list[/fnc],
+ [fnc]$reguser.match[/fnc],
+ [fnc]$reguser.matchProperty[/fnc]
+*/
+
+static bool reguser_kvs_fnc_getIgnoreFlags(KviKvsModuleFunctionCall * c)
+{
+ QString szName;
+ QString szFlags;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("name",KVS_PT_STRING,0,szName)
+ KVSM_PARAMETERS_END(c)
+
+ KviKvsArray* pArray = new KviKvsArray();
+ int aid=0;
+ KviRegisteredUser * u = g_pRegisteredUserDataBase->findUserByName(szName);
+ if(u)
+ {
+ if(u->ignoreFlags() & KviRegisteredUser::Query)
+ szFlags+='q';
+ if(u->ignoreFlags() & KviRegisteredUser::Channel)
+ szFlags+='c';
+ if(u->ignoreFlags() & KviRegisteredUser::Notice)
+ szFlags+='n';
+ if(u->ignoreFlags() & KviRegisteredUser::Ctcp)
+ szFlags+='t';
+ if(u->ignoreFlags() & KviRegisteredUser::Invite)
+ szFlags+='i';
+ if(u->ignoreFlags() & KviRegisteredUser::Dcc)
+ szFlags+='d';
+ c->returnValue()->setString(szFlags);
+
+ }
+ return true;
+}
+
+/*
+ @doc: reguser.isIgnoreEnabled
+ @type:
+ function
+ @title:
+ $reguser.isIgnoreEnabled
+ @short:
+ Returns if ignore enabled registered user
+ @syntax:
+ $reguser.isIgnoreEnabled(<name:string>)
+ @description:
+ Returns if ignore enabled registered user
+ @seealso:
+ [module:reguser]Registered users database interface[/module],
+ [doc:registered_users]Registered users database[/doc],
+ [cmd]reguser.add[/cmd],
+ [cmd]reguser.remove[/cmd],
+ [cmd]reguser.addmask[/cmd],
+ [cmd]reguser.delmask[/cmd],
+ [fnc]$reguser.list[/fnc],
+ [fnc]$reguser.match[/fnc],
+ [fnc]$reguser.matchProperty[/fnc]
+*/
+
+static bool reguser_kvs_fnc_isIgnoreEnabled(KviKvsModuleFunctionCall * c)
+{
+ QString szName;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("name",KVS_PT_STRING,0,szName)
+ KVSM_PARAMETERS_END(c)
+
+ KviKvsArray* pArray = new KviKvsArray();
+ int aid=0;
+ KviRegisteredUser * u = g_pRegisteredUserDataBase->findUserByName(szName);
+ if(u)
+ {
+ c->returnValue()->setBoolean(u->ignoreEnagled());
+
+ }
+ return true;
+}
+
+/*
+ @doc: reguser.setproperty
+ @type:
+ command
+ @title:
+ reguser.setproperty
+ @keyterms:
+ setting user properties
+ @short:
+ Sets a property of a registered user
+ @syntax:
+ reguser.setproperty [-n] [-a] [-q] <name> <property> [value]
+ @description:
+ Adds a property to the registered users database entry with name <name>.[br]
+ The property <property> is set to the specified <value> or is unset if <value>
+ is not given (or is an empty string).[br]
+ If the '-n' switch is used , and the user entry has been found in the database,
+ all the [doc:notify_list]notify lists[/doc] are restarted.[br]
+ If the '-a' switch is used , and there are users on IRC currently matched
+ by this reguser entry then their avatar is reset.
+ This is useful when you're changing someone's notify property.[br]
+ If the -q switch is used , the command runs in "quiet" mode and prints no warnings.[br]
+ @examples:
+ [example]
+ [cmd]reguser.add[/cmd] "Szymon Stefanek"
+ reguser.setproperty -n "Szymon Stefanek" notify Pragma
+ [fnc]$reguser.list[/fnc]
+ [/example]
+ @seealso:
+ [module:reguser]Registered users database interface[/module],
+ [doc:registered_users]Registered users database[/doc],
+ [fnc]$reguser.matchProperty[/fnc],
+ [fnc]$reguser.property[/fnc]
+*/
+
+static bool reguser_kvs_cmd_setproperty(KviKvsModuleCommandCall * c)
+{
+ QString szName;
+ QString szProperty;
+ QString szValue;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("mask",KVS_PT_STRING,0,szName)
+ KVSM_PARAMETER("property",KVS_PT_STRING,0,szProperty)
+ KVSM_PARAMETER("value",KVS_PT_STRING,KVS_PF_OPTIONAL,szValue)
+ KVSM_PARAMETERS_END(c)
+
+ if(szName.isEmpty())
+ {
+ if(!c->hasSwitch('q',"quiet"))c->warning(__tr2qs("No name specified"));
+ return true;
+ }
+
+ if(szProperty.isEmpty())
+ {
+ if(!c->hasSwitch('q',"quiet"))c->warning(__tr2qs("No property specified"));
+ return true;
+ }
+
+ KviRegisteredUser * u = g_pRegisteredUserDataBase->findUserByName(szName);
+ if(!u)
+ {
+ if(!c->hasSwitch('q',"quiet"))c->warning(__tr2qs("User %Q not found"),&szName);
+ } else {
+ u->setProperty(szProperty,szValue);
+ if(c->hasSwitch('n',"restartnotifylists"))g_pApp->restartNotifyLists();
+ if(c->hasSwitch('a',"resetavatar"))g_pApp->resetAvatarForMatchingUsers(u);
+ }
+ return true;
+}
+/*
+ @doc: reguser.list
+ @type:
+ function
+ @title:
+ $reguser.list
+ @short:
+ Get a list of registered user masks
+ @syntax:
+ $reguser.list([mask])
+ @description:
+ Returns an array of the entries in the registered users database.[br]
+ If <mask> is specified, only entries matching the <mask>
+ and the entries with no registration masks are listed.[br]
+ Please note that <mask> is a wildcard string that will match
+ wildcard strings... don't get messed with that :D[br]
+ @seealso:
+ [module:reguser]Registered users database interface[/module],
+ [doc:registered_users]Registered users database[/doc],
+ [cmd]reguser.add[/cmd],
+ [cmd]reguser.remove[/cmd],
+ [cmd]reguser.addmask[/cmd],
+ [fnc]$reguser.list[/fnc],
+ [fnc]$reguser.exactMatch[/fnc]
+*/
+
+static bool reguser_kvs_fnc_list(KviKvsModuleFunctionCall * c)
+{
+ QString szMask;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("user_mask",KVS_PT_STRING,KVS_PF_OPTIONAL,szMask)
+ KVSM_PARAMETERS_END(c)
+
+ KviIrcMask mask(szMask);
+ KviKvsArray* pArray = new KviKvsArray();
+ int aid=0;
+
+ int cnt = 0;
+
+ KviPointerHashTable<QString,KviRegisteredUser> * d = g_pRegisteredUserDataBase->userDict();
+ KviPointerHashTableIterator<QString,KviRegisteredUser> it(*d);
+
+ while(KviRegisteredUser * u = it.current())
+ {
+ KviPointerList<KviIrcMask> * ml = u->maskList();
+ if(u->matches(mask) || (ml->count() == 0))
+ {
+ pArray->set(aid,new KviKvsVariant(u->name()));
+ aid++;
+ }
+ ++it;
+ }
+ c->returnValue()->setArray(pArray);
+ return true;
+}
+
+/*
+ @doc: reguser.showlist
+ @type:
+ command
+ @title:
+ reguser.showlist
+ @keyterms:
+ registered users
+ @short:
+ Lists the registered users
+ @syntax:
+ reguser.showlist [mask]
+ @description:
+ Lists the entries in the registered users database.[br]
+ If <mask> is specified, only entries matching the <mask>
+ and the entries with no registration masks are listed.[br]
+ Please note that <mask> is a wildcard string that will match
+ wildcard strings... don't get messed with that :D[br]
+ @seealso:
+ [module:reguser]Registered users database interface[/module],
+ [doc:registered_users]Registered users database[/doc],
+ [cmd]reguser.add[/cmd],
+ [cmd]reguser.remove[/cmd],
+ [fnc]$reguser.match[/fnc],
+ [fnc]$reguser.exactMatch[/fnc]
+*/
+
+static bool reguser_kvs_cmd_showlist(KviKvsModuleCommandCall * c)
+{
+ QString szMask;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("mask",KVS_PT_STRING,KVS_PF_OPTIONAL,szMask)
+ KVSM_PARAMETERS_END(c)
+
+ KviIrcMask mask(szMask);
+ c->window()->outputNoFmt(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Registered users database dump:"));
+
+ int count = 0;
+
+ KviPointerHashTable<QString,KviRegisteredUser> * d = g_pRegisteredUserDataBase->userDict();
+ KviPointerHashTableIterator<QString,KviRegisteredUser> it(*d);
+ while(KviRegisteredUser * u = it.current())
+ {
+ KviPointerList<KviIrcMask> * ml = u->maskList();
+ if(u->matches(mask) || (ml->count() == 0))
+ {
+ c->window()->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs(" User: %c%Q"),KVI_TEXT_BOLD,&(u->name()));
+
+ if(ml->count() == 0)
+ {
+ c->window()->output(KVI_OUT_SYSTEMWARNING,__tr2qs(" Warning: this user has no registration masks"));
+ } else {
+ for(KviIrcMask * m = ml->first();m;m = ml->next())
+ {
+ c->window()->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs(" Mask: %Q!%Q@%Q"),&(m->nick()),&(m->user()),&(m->host()));
+ }
+ }
+
+ KviPointerHashTable<QString,QString> * pd = u->propertyDict();
+ if(pd)
+ {
+ KviPointerHashTableIterator<QString,QString> pdit(*pd);
+ while(pdit.current())
+ {
+ QString key = pdit.currentKey();
+ c->window()->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs(" Property: %Q=%Q"),&(key),pdit.current());
+ ++pdit;
+ }
+ } else c->window()->outputNoFmt(KVI_OUT_SYSTEMMESSAGE,__tr2qs(" No properties"));
+ count++;
+ }
+ ++it;
+ }
+
+ c->window()->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Total: %d matching users (of %d in the database)"),count,d->count());
+ return true;
+}
+
+
+
+/*
+ @doc: reguser.match
+ @type:
+ function
+ @title:
+ $reguser.match
+ @short:
+ Returns an entry in the registered user database
+ @syntax:
+ $reguser.match(<user_mask>)
+ @description:
+ Returns the name of the first entry matching <user_mask> in the registered user database.[br]
+ The <user_mask> has the common [doc:irc_masks]irc mask[/doc] format but can't contain wildcards.[br]
+ @seealso:
+ [module:reguser]Registered users database interface[/module],
+ [doc:registered_users]Registered users database[/doc],
+ [cmd]reguser.add[/cmd],
+ [cmd]reguser.remove[/cmd],
+ [cmd]reguser.addmask[/cmd],
+ [fnc]$reguser.list[/fnc],
+ [fnc]$reguser.exactMatch[/fnc]
+*/
+
+static bool reguser_kvs_fnc_match(KviKvsModuleFunctionCall * c)
+{
+ QString szMask;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("user_mask",KVS_PT_STRING,0,szMask)
+ KVSM_PARAMETERS_END(c)
+ KviIrcMask mask(szMask);
+//FIXME: it crashes kvirc KviRegisteredUser * u = c->context()->connection()->userDataBase()->registeredUser(mask.nick(),mask.user(),mask.host());
+ KviRegisteredUser * u = g_pRegisteredUserDataBase->findMatchingUser(mask.nick(),mask.user(),mask.host());
+ if(u) c->returnValue()->setString(u->name());
+ return true;
+}
+
+/*
+ @doc: reguser.exactmatch
+ @type:
+ function
+ @title:
+ $reguser.exactMatch
+ @short:
+ Returns an entry in the registered user database
+ @syntax:
+ $reguser.exactMatch(<user_mask>)
+ @description:
+ Returns the name of the registered user database entry that has <user_mask> in its registration mask list.[br]
+ The <user_mask> has the common [doc:irc_masks]wild irc mask[/doc] format and can contain wildcards.[br]
+ @seealso:
+ [module:reguser]Registered users database interface[/module],
+ [doc:registered_users]Registered users database[/doc],
+ [cmd]reguser.add[/cmd],
+ [cmd]reguser.remove[/cmd],
+ [cmd]reguser.addmask[/cmd],
+ [fnc]$reguser.list[/fnc],
+ [fnc]$reguser.match[/fnc]
+*/
+
+static bool reguser_kvs_fnc_exactMatch(KviKvsModuleFunctionCall * c)
+{
+ QString szMask;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("user_mask",KVS_PT_STRING,0,szMask)
+ KVSM_PARAMETERS_END(c)
+ KviIrcMask mask(szMask);
+ KviRegisteredUser * u = g_pRegisteredUserDataBase->findUserWithMask(mask);
+ if(u) c->returnValue()->setString(u->name());
+ return true;
+}
+
+///*
+// @doc: reguser.matches
+// @type:
+// function
+// @title:
+// $reguser.matches
+// @short:
+// Returns entries in the registered user database
+// @syntax:
+// $reguser.matches(<user_mask>)
+// @description:
+// Returns a comma separated list of registered user masks that match <user_mask>.[br]
+// User mask must be in the format <nick>!<user>@<host> , where <user> and
+// <host> may contain '*' wildcards.[br]
+// If no registered mask matches the <user_mask> an empty string is returned.[br]
+// @seealso:
+// [module:reguser]reguser module documentation[/module]
+//*/
+
+//static void search_reguser_list(KviRegisteredUserList * l,KviWindow * w,const char * mask,KviStr & buffer)
+//{
+// for(KviRegisteredUser * u = l->first();u;u = l->next())
+// {
+// if(u->matches(mask))
+// {
+// if(buffer.hasData())buffer.append(',');
+// buffer.append(u->mask());
+// }
+// }
+//}
+
+//static bool reguser_module_fnc_matches(KviModule *m,KviCommand *c,KviParameterList * parms,KviStr &buffer)
+//{
+// ENTER_STACK_FRAME(c,"reguser.matches");
+//
+// KviStr list;
+//
+// const KviPointerHashTable<const char *,KviRegisteredUserList> * d = g_pRegisteredUserDataBase->nickDict();
+// KviPointerHashTableIterator<const char *,KviRegisteredUserList> it(*d);
+// while(KviRegisteredUserList * l = it.current())
+// {
+// search_reguser_list(l,c->window(),parms->safeFirstParam(),list);
+// ++it;
+// }
+//
+// search_reguser_list(g_pRegisteredUserDataBase->wildList(),c->window(),parms->safeFirstParam(),list);
+//
+// buffer.append(list);
+//
+// return c->leaveStackFrame();
+//}
+
+
+/*
+ @doc: reguser.mask
+ @type:
+ function
+ @title:
+ $reguser.mask
+ @short:
+ Returns the registration masks for a db entry
+ @syntax:
+ $reguser.mask(<name>[,<N>])
+ @description:
+ Returns the <N>th registration mask for the registered user database record identified
+ by <name>. If <N> is not given , returns an array of registration masks for that entry.[br]
+ If <name> does not identify a valid entry an empty string is returned;
+ if <N> is out of range (or there are no masks at all) , an empty string is returned.[br]
+ <N> is a ZERO BASED index.[br]
+ @examples:
+ [example]
+ [cmd]reguser.add[/cmd] Pragma
+ [cmd]reguser.addmask[/cmd] Pragma Pragma!*@*.it
+ [cmd]echo[/cmd] $reguser.mask(Pragma,0)
+ [/example]
+ @seealso:
+ [module:reguser]Registered users database interface[/module],
+ [doc:registered_users]Registered users database[/doc],
+ [cmd]reguser.add[/cmd],
+ [cmd]reguser.remove[/cmd],
+ [cmd]reguser.addmask[/cmd],
+ [cmd]reguser.delmask[/cmd],
+ [fnc]$reguser.list[/fnc],
+ [fnc]$reguser.match[/fnc],
+ [fnc]$reguser.matchProperty[/fnc]
+*/
+
+static bool reguser_kvs_fnc_mask(KviKvsModuleFunctionCall * c)
+{
+ QString szName;
+ QString szN;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("name",KVS_PT_STRING,0,szName)
+ KVSM_PARAMETER("N",KVS_PT_STRING,KVS_PF_OPTIONAL,szN)
+ KVSM_PARAMETERS_END(c)
+
+ KviKvsArray* pArray = new KviKvsArray();
+ int aid=0;
+ KviRegisteredUser * u = g_pRegisteredUserDataBase->findUserByName(szName);
+ if(u)
+ {
+ KviStr n = szName;
+ if(n.hasData() && n.isUnsignedNum())
+ {
+ KviIrcMask * m = u->maskList()->at(n.toInt());
+ if(m) c->returnValue()->setString(m->nick()+"!"+m->user()+"@"+m->host());
+ } else {
+ int id=0;
+ for(KviIrcMask * m = u->maskList()->first();m;m = u->maskList()->next())
+ {
+ pArray->set(aid,new KviKvsVariant(QString(m->nick()+"!"+m->user()+"@"+m->host())));
+ aid++;
+ }
+ c->returnValue()->setArray(pArray);
+ }
+ }
+ return true;
+}
+/*
+ @doc: reguser.property
+ @type:
+ function
+ @title:
+ $reguser.property
+ @short:
+ Returns a property of an entry in the registered user database
+ @syntax:
+ $reguser.property(<user_name>,<property_name>)
+ @description:
+ Returns the value of the property identified by <property_name> and
+ bound to the entry identified by <user_name>.[br]
+ If the property is not set or if there is no entry with <user_name> an empty string is returned.[br]
+ @examples:
+ [example]
+ [cmd]reguser.add[/cmd] Pragma
+ [cmd]reguser.addmask[/cmd] Pragma Pragma!*@*.it
+ [cmd]reguser.setproperty[/cmd] Pragma isDev 1
+ [cmd]echo[/cmd] $reguser.property(Pragma,isDev)
+ [/example]
+ @seealso:
+ [module:reguser]Registered users database interface[/module],
+ [doc:registered_users]Registered users database[/doc],
+ [cmd]reguser.add[/cmd],
+ [cmd]reguser.remove[/cmd],
+ [cmd]reguser.addmask[/cmd],
+ [fnc]$reguser.list[/fnc],
+ [fnc]$reguser.match[/fnc],
+ [fnc]$reguser.matchProperty[/fnc]
+*/
+
+static bool reguser_kvs_fnc_property(KviKvsModuleFunctionCall * c)
+{
+ QString szName;
+ QString szProperty;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("user_name",KVS_PT_STRING,0,szName)
+ KVSM_PARAMETER("property_name",KVS_PT_STRING,KVS_PF_OPTIONAL,szProperty)
+ KVSM_PARAMETERS_END(c)
+
+ KviRegisteredUser * u = g_pRegisteredUserDataBase->findUserByName(szName);
+ if(u)
+ {
+ QString tmp;
+ u->getProperty(szProperty,tmp);
+ c->returnValue()->setString(tmp);
+ }
+ return true;
+}
+/*
+ @doc: reguser.matchproperty
+ @type:
+ function
+ @title:
+ $reguser.matchProperty
+ @short:
+ Returns a property of an entry in the registered user database
+ @syntax:
+ $reguser.matchProperty(<user_mask>,<property_name>)
+ @description:
+ Returns the value of the property identified by <property_name> and
+ bound to the first entry matched by by <user_mask>.[br]
+ If the property is not set, an empty string is returned.[br]
+ If no entry matches <user_mask> this function returns an empty string
+ and does not print any error.[br]
+ [example]
+ %property = $reguser.matchProperty(<user_mask>,<property_name>)
+ [/example]
+ Is actually a shortcut for:[br]
+ [example]
+ %tmp = [fnc]$reguser.match[/fnc](<user_mask>)
+ if("%tmp" != "")%property = $reguser.property(%tmp,<property_name>)
+ [/example]
+ @seealso:
+ [module:reguser]Registered users database interface[/module],
+ [doc:registered_users]Registered users database[/doc],
+ [cmd]reguser.add[/cmd],
+ [cmd]reguser.remove[/cmd],
+ [cmd]reguser.addmask[/cmd],
+ [fnc]$reguser.list[/fnc],
+ [fnc]$reguser.match[/fnc],
+ [fnc]$reguser.property[/fnc]
+*/
+
+static bool reguser_kvs_fnc_matchProperty(KviKvsModuleFunctionCall * c)
+{
+ QString szMask;
+ QString szProperty;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("user_mask",KVS_PT_STRING,0,szMask)
+ KVSM_PARAMETER("property_name",KVS_PT_STRING,KVS_PF_OPTIONAL,szProperty)
+ KVSM_PARAMETERS_END(c)
+
+ KviIrcMask mask(szMask);
+//FIXME: it crashes kvirc KviRegisteredUser * u = c->context()->connection()->userDataBase()->registeredUser(mask.nick(),mask.user(),mask.host());
+ KviRegisteredUser * u = g_pRegisteredUserDataBase->findMatchingUser(mask.nick(),mask.user(),mask.host());
+ if(u)
+ {
+ QString tmp;
+ u->getProperty(szProperty,tmp);
+ c->returnValue()->setString(tmp);
+ }
+ return true;
+}
+
+/*
+ @doc: reguser.wizard
+ @type:
+ command
+ @title:
+ reguser.wizard
+ @keyterms:
+ registering users, registration wizard
+ @short:
+ Shows a registration wizard dialog
+ @syntax:
+ reguser.wizard [mask]
+ @description:
+ Allows registering an user with an intuitive and easy to use interface.
+ If [mask] is specified , it is used as inital mask in the dialog.
+ @seealso:
+ [module:reguser]Registered users database interface[/module],
+ [doc:registered_users]Registered users database[/doc],
+ [cmd]reguser.add[/cmd],
+*/
+
+static bool reguser_kvs_cmd_wizard(KviKvsModuleCommandCall * c)
+{
+ QString szMask;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("mask",KVS_PT_STRING,KVS_PF_OPTIONAL,szMask)
+ KVSM_PARAMETERS_END(c)
+
+ KviRegistrationWizard * w = new KviRegistrationWizard(szMask);
+ w->show();
+ return true;
+}
+
+static bool reguser_module_init(KviModule * m)
+{
+ g_pLocalRegisteredUserDataBase = 0;
+ g_pRegistrationWizardList = new KviPointerList<KviRegistrationWizard>;
+ g_pRegistrationWizardList->setAutoDelete(true);
+
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"add",reguser_kvs_cmd_add);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"remove",reguser_kvs_cmd_remove);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"addmask",reguser_kvs_cmd_addmask);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"delmask",reguser_kvs_cmd_delmask);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"edit",reguser_kvs_cmd_edit);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"showlist",reguser_kvs_cmd_showlist);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"setproperty",reguser_kvs_cmd_setproperty);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"wizard",reguser_kvs_cmd_wizard);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"setIgnoreEnabled",reguser_kvs_cmd_setIgnoreEnabled);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"setIgnoreFlags",reguser_kvs_cmd_setIgnoreFlags);
+
+ KVSM_REGISTER_FUNCTION(m,"match",reguser_kvs_fnc_match);
+ KVSM_REGISTER_FUNCTION(m,"list",reguser_kvs_fnc_list);
+ KVSM_REGISTER_FUNCTION(m,"exactMatch",reguser_kvs_fnc_exactMatch);
+ KVSM_REGISTER_FUNCTION(m,"mask",reguser_kvs_fnc_mask);
+ KVSM_REGISTER_FUNCTION(m,"property",reguser_kvs_fnc_property);
+ KVSM_REGISTER_FUNCTION(m,"matchProperty",reguser_kvs_fnc_matchProperty);
+ KVSM_REGISTER_FUNCTION(m,"getIgnoreFlags",reguser_kvs_fnc_getIgnoreFlags);
+ KVSM_REGISTER_FUNCTION(m,"isIgnoreEnabled",reguser_kvs_fnc_isIgnoreEnabled);
+
+ return true;
+}
+
+static bool reguser_module_cleanup(KviModule *m)
+{
+ if(g_pRegisteredUsersDialog)delete g_pRegisteredUsersDialog;
+ g_pRegisteredUsersDialog = 0;
+
+ while(KviRegistrationWizard * w = g_pRegistrationWizardList->first())delete w;
+ delete g_pRegistrationWizardList;
+ g_pRegistrationWizardList = 0;
+
+ // FIXME: UNREGISTER THE METAOBJECTS
+ return true;
+}
+
+static bool reguser_module_can_unload(KviModule *)
+{
+ return ((g_pRegistrationWizardList->isEmpty()) && (g_pRegisteredUsersDialog == 0));
+}
+
+KVIRC_MODULE(
+ "Reguser", // module name
+ "1.0.0", // module version
+ "Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot net)", // author & (C)
+ "Script interface to the registered users database",
+ reguser_module_init,
+ reguser_module_can_unload,
+ 0,
+ reguser_module_cleanup
+)
diff --git a/src/modules/reguser/wizard.cpp b/src/modules/reguser/wizard.cpp
new file mode 100644
index 00000000..1777621d
--- /dev/null
+++ b/src/modules/reguser/wizard.cpp
@@ -0,0 +1,464 @@
+//
+// File : wizard.cpp
+// Creation date : Fri Jun 26 2002 21:21:21 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+#include "wizard.h"
+
+#include "kvi_locale.h"
+#include "kvi_pointerlist.h"
+#include "kvi_app.h"
+#include "kvi_ircmask.h"
+#include "kvi_selectors.h"
+#include "kvi_pixmap.h"
+#include "kvi_regusersdb.h"
+#include "kvi_iconmanager.h"
+#ifdef COMPILE_USE_QT4
+#include <QDesktopWidget>
+#endif
+
+#include <qcheckbox.h>
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qpushbutton.h>
+#include <qwidget.h>
+#include <qlayout.h>
+#include <qvariant.h>
+#include <qframe.h>
+
+
+extern KVIRC_API KviRegisteredUserDataBase * g_pRegisteredUserDataBase;
+extern KviPointerList<KviRegistrationWizard> * g_pRegistrationWizardList;
+
+KviRegistrationWizard::KviRegistrationWizard(const char * startMask,KviRegisteredUserDataBase * db,QWidget * par,bool bModal)
+: KviTalWizard(par)
+{
+ m_pDb = db;
+
+ setModal(bModal);
+
+ m_bModal = bModal;
+
+ KviIrcMask mask(startMask ? startMask : "*!*@*");
+
+ g_pRegistrationWizardList->append(this);
+
+ QGridLayout* m_pPage1Layout;
+ QGridLayout* m_pPage2Layout;
+ QGridLayout* m_pPage3Layout;
+ QGridLayout* m_pPage4Layout;
+ QGridLayout* m_pPage5Layout;
+
+ QLabel* TextLabel10_2;
+ QLabel* TextLabel10;
+ QLabel* TextLabel10_3;
+ QLabel* TextLabel10_3_2;
+
+ QFrame * f;
+
+// resize( 490, 456 );
+ setCaption(__tr2qs("User Registration Wizard - KVIrc"));
+ setIcon(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_LINUX)));
+
+ setSizeGripEnabled( TRUE );
+
+ m_pPage1 = new QWidget(this);
+ m_pPage1Layout = new QGridLayout(m_pPage1);
+ m_pPage1Layout->setSpacing(4);
+ m_pPage1Layout->setMargin(8);
+
+ m_pLabel1 = new QLabel(m_pPage1);
+ m_pLabel1->setText(__tr2qs("<p>Welcome to the user registration wizard.<br>This process allows you to add an IRC user to the database and set properties for that user. KVIrc will be (hopefully) able to recognize the user, add him to the notify list, and display the associated avatar.<br><br>First of all, you must insert an <b>entry name or real name</b> for the user you're going to register. The name will be used to identify the database entry and has no specific requirements, it can be a given name, nickname, or just some text to remind you of the real person.<br>Examples: \"George W Bush\", \"Dubya\".\n</p>" ));
+
+ m_pPage1Layout->addWidget(m_pLabel1, 0, 0);
+
+ m_pEditRealName = new QLineEdit(m_pPage1);
+ //m_pEditRealName->setAlignment(int(QLineEdit::AlignHCenter));
+
+ m_pPage1Layout->addWidget(m_pEditRealName,1,0);
+ addPage( m_pPage1,__tr2qs("Step 1: Entry Name"));
+
+ if(mask.nick() != "*")m_pEditRealName->setText(mask.nick());
+
+ connect(m_pEditRealName,SIGNAL(textChanged(const QString &)),this,SLOT(realNameChanged(const QString &)));
+
+ // PAGE 2
+
+
+ m_pPage2 = new QWidget(this);
+ m_pPage2Layout = new QGridLayout( m_pPage2 );
+ m_pPage2Layout->setSpacing( 4 );
+ m_pPage2Layout->setMargin( 8 );
+
+ m_pLabel2 = new QLabel( m_pPage2);
+ m_pLabel2->setText(__tr2qs("<p>A registered user is identified by one or more <b>IRC masks</b>.<br>A mask must be in the following form:<br><b>nickname!username@hostname</b><br>and can contain wildcard characters '*' and '?'. Be careful in choosing the masks, as they are the only way to verify the identity of a registered user.<br><br>You can enter at most two masks here, if you wish to add more masks, use the \"<b>Edit</b>\" button in the Registered Users dialog. You must enter at least one mask.</p>"));
+
+ m_pPage2Layout->addMultiCellWidget(m_pLabel2,0,0,0,4);
+
+ //KviStr szMask;
+
+ //mask.mask(szMask,11);
+
+ //KviIrcMask masktempl(szMask.ptr());
+
+ m_pNicknameEdit1 = new QLineEdit(m_pPage2);
+ m_pNicknameEdit1->setAlignment(Qt::AlignRight);
+ if(mask.nick() != "*")m_pNicknameEdit1->setText(mask.nick());
+ connect(m_pNicknameEdit1,SIGNAL(textChanged(const QString &)),this,SLOT(maskChanged(const QString &)));
+ m_pPage2Layout->addWidget( m_pNicknameEdit1, 1, 0 );
+
+ m_pUsernameEdit1 = new QLineEdit(m_pPage2);
+ m_pUsernameEdit1->setAlignment(Qt::AlignHCenter);
+ if(mask.hasUser())m_pUsernameEdit1->setText(mask.user());
+ connect(m_pUsernameEdit1,SIGNAL(textChanged(const QString &)),this,SLOT(maskChanged(const QString &)));
+ m_pPage2Layout->addWidget(m_pUsernameEdit1,1,2);
+
+ m_pHostEdit1 = new QLineEdit(m_pPage2);
+ if(mask.hasHost())m_pHostEdit1->setText(mask.host());
+ connect(m_pHostEdit1,SIGNAL(textChanged(const QString &)),this,SLOT(maskChanged(const QString &)));
+ m_pPage2Layout->addWidget(m_pHostEdit1,1,4);
+
+ m_pNicknameEdit2 = new QLineEdit(m_pPage2);
+ m_pNicknameEdit2->setAlignment(Qt::AlignRight);
+ m_pPage2Layout->addWidget(m_pNicknameEdit2,2,0);
+
+ m_pUsernameEdit2 = new QLineEdit(m_pPage2);
+ m_pUsernameEdit2->setAlignment(Qt::AlignHCenter);
+ m_pPage2Layout->addWidget(m_pUsernameEdit2,2,2);
+
+ m_pHostEdit2 = new QLineEdit(m_pPage2);
+ m_pPage2Layout->addWidget(m_pHostEdit2,2,4);
+
+ TextLabel10_2 = new QLabel(m_pPage2);
+ TextLabel10_2->setText("<center><b>!</b></center>");
+ TextLabel10_2->setAlignment(int(Qt::AlignCenter));
+ m_pPage2Layout->addWidget(TextLabel10_2,2,1);
+
+ TextLabel10 = new QLabel(m_pPage2);
+ TextLabel10->setText("<center><b>!</b></center>");
+ TextLabel10->setAlignment(int(Qt::AlignCenter));
+ m_pPage2Layout->addWidget(TextLabel10,1,1);
+
+ TextLabel10_3 = new QLabel(m_pPage2);
+ TextLabel10_3->setText("<center><b>@</b></center>");
+ TextLabel10_3->setAlignment(int(Qt::AlignCenter));
+ m_pPage2Layout->addWidget(TextLabel10_3,1,3);
+
+ TextLabel10_3_2 = new QLabel(m_pPage2);
+ TextLabel10_3_2->setText("<center><b>@</b></center>");
+ TextLabel10_3_2->setAlignment(int(Qt::AlignCenter));
+ m_pPage2Layout->addWidget(TextLabel10_3_2,2,3);
+
+ addPage(m_pPage2,__tr2qs("Step 2: Mask Selection"));
+
+
+
+
+
+ m_pPage3 = new QWidget(this);
+ m_pPage3Layout = new QGridLayout(m_pPage3);
+ m_pPage3Layout->setSpacing(4);
+ m_pPage3Layout->setMargin(8);
+
+ m_pLabel3 = new QLabel(m_pPage3);
+ m_pLabel3->setText(__tr2qs("<p>If you want to store an avatar image for this user, you can set it here. KVIrc will show the avatar in the userlist next to the user's nickname.<br>An avatar can be in any supported image format (PNG is recommended). Keep in mind that KVIrc stores avatars in memory and has to resize them to fit in the userlist, thus it's better to use small, low-resolution images.</p>"));
+ m_pPage3Layout->addWidget(m_pLabel3,0,0);
+
+ f = new QFrame(m_pPage3);
+ f->setFrameStyle(QFrame::HLine | QFrame::Sunken);
+ m_pPage3Layout->addWidget(f,1,0);
+
+ m_pAvatar = new KviPixmap();
+ m_pAvatarSelector = new KviPixmapSelector(m_pPage3,__tr2qs("Store an avatar for this user"),m_pAvatar,true);
+ m_pPage3Layout->addWidget(m_pAvatarSelector,2,0);
+
+ m_pPage3Layout->setRowStretch(0,1);
+
+ addPage(m_pPage3,__tr2qs( "Step 3: Avatar Selection"));
+
+
+
+
+ m_pPage4 = new QWidget(this);
+ m_pPage4Layout = new QGridLayout(m_pPage4);
+ m_pPage4Layout->setSpacing(4);
+ m_pPage4Layout->setMargin(8);
+
+ m_pLabel4 = new QLabel(m_pPage4);
+ m_pLabel4->setText(__tr2qs("<p>If you want to be notified when this user is online or goes offline, you must specify the list of nicknames that KVIrc will look for.<br><br>You can enter at most two nicknames here, if you wish to add more nicknames, use the \"<b>Edit</b>\" button in the Registered Users dialog.</p>"));
+ m_pPage4Layout->addMultiCellWidget(m_pLabel4,0,0,0,1);
+
+
+ f = new QFrame(m_pPage4);
+ f->setFrameStyle(QFrame::HLine | QFrame::Sunken);
+ m_pPage4Layout->addMultiCellWidget(f,1,1,0,1);
+
+ m_pNotifyCheck = new QCheckBox(m_pPage4);
+ m_pNotifyCheck->setText(__tr2qs("Add this user to the notify list"));
+ m_pNotifyCheck->setChecked(false);
+ connect(m_pNotifyCheck,SIGNAL(toggled(bool)),this,SLOT(notifyCheckToggled(bool)));
+ m_pPage4Layout->addMultiCellWidget(m_pNotifyCheck,2,2,0,1);
+
+ m_pNotifyNickLabel1 = new QLabel(m_pPage4);
+ m_pNotifyNickLabel1->setText(__tr2qs("Nickname:"));
+ m_pPage4Layout->addWidget(m_pNotifyNickLabel1,3,0);
+
+ m_pNotifyNickLabel2 = new QLabel(m_pPage4);
+ m_pNotifyNickLabel2->setText(__tr2qs("Nickname 2:"));
+ m_pPage4Layout->addWidget(m_pNotifyNickLabel2,4,0);
+
+ m_pNotifyNickEdit1 = new QLineEdit(m_pPage4);
+ if(mask.nick() != "*")m_pNotifyNickEdit1->setText(mask.nick());
+ connect(m_pNotifyNickEdit1,SIGNAL(textChanged(const QString &)),this,SLOT(notifyNickChanged(const QString &)));
+ m_pPage4Layout->addWidget(m_pNotifyNickEdit1,3,1);
+
+ m_pNotifyNickEdit2 = new QLineEdit(m_pPage4);
+ connect(m_pNotifyNickEdit2,SIGNAL(textChanged(const QString &)),this,SLOT(notifyNickChanged(const QString &)));
+ m_pPage4Layout->addWidget(m_pNotifyNickEdit2,4,1);
+
+ m_pPage4Layout->setRowStretch(0,1);
+
+ addPage(m_pPage4,__tr2qs("Step 4: Notify List"));
+
+
+
+
+
+ m_pPage5 = new QWidget(this);
+ m_pPage5Layout = new QGridLayout(m_pPage5);
+ m_pPage5Layout->setSpacing(4);
+ m_pPage5Layout->setMargin(8);
+
+ m_pTextLabel5 = new QLabel(m_pPage5);
+ m_pTextLabel5->setText(__tr2qs("<p>That's it. The user registration has been completed.<br><br>Click \"<b>Finish</b>\" to close this dialog.</p>"));
+ m_pPage5Layout->addWidget(m_pTextLabel5,0,0);
+
+ addPage(m_pPage5,__tr2qs("Registration Complete"));
+
+ setFinishEnabled(m_pPage5,true);
+ QString dummy;
+ maskChanged(dummy);
+ realNameChanged(dummy);
+ notifyCheckToggled(false);
+
+ setMinimumSize(QSize(350,420));
+
+ // signals and slots connections
+}
+
+KviRegistrationWizard::~KviRegistrationWizard()
+{
+ delete m_pAvatar;
+ g_pRegistrationWizardList->setAutoDelete(false);
+ g_pRegistrationWizardList->removeRef(this);
+ g_pRegistrationWizardList->setAutoDelete(true);
+}
+
+void KviRegistrationWizard::reject()
+{
+ KviTalWizard::reject();
+ if(!m_bModal)delete this;
+// hide();
+// g_pApp->collectGarbage(this);
+}
+
+void KviRegistrationWizard::accept()
+{
+ bool bLocalDb = true;
+ if(!m_pDb)
+ {
+ bLocalDb = false;
+ m_pDb = g_pRegisteredUserDataBase;
+ }
+
+ QString szName = m_pEditRealName->text();
+ KviRegisteredUser * u;
+
+
+ if(bLocalDb)
+ {
+ if(szName.isEmpty()) szName = "user";
+
+ QString szNameOk = szName;
+
+ int idx = 1;
+
+ do {
+ u = m_pDb->findUserByName(szNameOk);
+ if(u)
+ {
+ KviQString::sprintf(szNameOk,"%Q%d",&szNameOk,idx);
+ idx++;
+ }
+ } while(u);
+
+ u = m_pDb->addUser(szNameOk);
+
+ } else {
+ u = m_pDb->findUserByName(szName);
+ if(!u)u = m_pDb->addUser(szName);
+ }
+
+ if(!u)
+ {
+ // ops... no way
+ // FIXME: spit an error message ?
+ debug("Ops.. something wrong with the regusers db");
+ //delete this;
+ return;
+ }
+
+ QString m1 = m_pNicknameEdit1->text();
+ QString m2 = m_pUsernameEdit1->text();
+ QString m3 = m_pHostEdit1->text();
+ KviIrcMask * mk = new KviIrcMask(m1,m2,m3);
+ m_pDb->removeMask(*mk);
+ m_pDb->addMask(u,mk);
+
+
+ m1 = m_pNicknameEdit2->text();
+ m2 = m_pUsernameEdit2->text();
+ if(m2.isEmpty())m2 = "*";
+ if(m3.isEmpty())m3 = "*";
+ m3 = m_pHostEdit2->text();
+ mk = new KviIrcMask(m1,m2,m3);
+
+ m_pDb->removeMask(*mk);
+ m_pDb->addMask(u,mk);
+
+ m_pAvatarSelector->commit();
+
+ bool bSetAvatar = false;
+
+ if(!m_pAvatar->isNull())
+ {
+ QString szPath = m_pAvatar->path();
+ u->setProperty("avatar",szPath);
+ bSetAvatar = true;
+ }
+
+ if(m_pNotifyCheck->isChecked())
+ {
+ m1 = m_pNotifyNickEdit1->text();
+ m2 = m_pNotifyNickEdit2->text();
+ if(!m2.isEmpty())
+ {
+ if(!m1.isEmpty())
+ m1.append(' ');
+ m1.append(m2);
+ }
+
+ if(!m1.isEmpty())
+ {
+ u->setProperty("notify",m1);
+ if(!bLocalDb)g_pApp->restartNotifyLists();
+ }
+ }
+
+ if(bSetAvatar && !bLocalDb)
+ g_pApp->resetAvatarForMatchingUsers(u);
+
+ KviTalWizard::accept();
+
+// if(!m_bModal)delete this;
+// hide();
+// g_pApp->collectGarbage(this);
+}
+
+
+void KviRegistrationWizard::showEvent(QShowEvent *e)
+{
+ if(height() < 420)resize(width(),420);
+ move((g_pApp->desktop()->width() - width())/2,(g_pApp->desktop()->height() - height())/2);
+ KviTalWizard::showEvent(e);
+}
+
+void KviRegistrationWizard::maskChanged(const QString &)
+{
+ KviStr tmp1 = m_pNicknameEdit1->text();
+ KviStr tmp2 = m_pUsernameEdit1->text();
+ KviStr tmp3 = m_pHostEdit1->text();
+
+ if(tmp1.isEmpty())
+ {
+ setNextEnabled(m_pPage2,false);
+ return;
+ }
+
+ if(tmp2.isEmpty())
+ {
+ setNextEnabled(m_pPage2,false);
+ return;
+ }
+
+ if(tmp3.isEmpty())
+ {
+ setNextEnabled(m_pPage2,false);
+ return;
+ }
+
+ KviStr mask(KviStr::Format,"%s!%s@%s",tmp1.ptr(),tmp2.ptr(),tmp3.ptr());
+
+ //KviIrcMask m(mask.ptr());
+
+ setNextEnabled(m_pPage2,mask!="*!*@*");
+}
+
+void KviRegistrationWizard::realNameChanged(const QString &)
+{
+ QString tmp = m_pEditRealName->text();
+ setNextEnabled(m_pPage1,!(tmp.isEmpty() || tmp.isNull()));
+}
+
+void KviRegistrationWizard::notifyNickChanged(const QString &)
+{
+ bool bYes = !m_pNotifyCheck->isChecked();
+
+ if(!bYes)
+ {
+ // we need at least one nickname then :)
+ KviStr tmp = m_pNotifyNickEdit1->text();
+ if(tmp.hasData())
+ {
+ bYes = true;
+ } else {
+ tmp = m_pNotifyNickEdit2->text();
+ if(tmp.hasData())bYes = true;
+ }
+ }
+
+ setNextEnabled(m_pPage4,bYes);
+}
+
+void KviRegistrationWizard::notifyCheckToggled(bool)
+{
+ bool bYes = m_pNotifyCheck->isChecked();
+
+ m_pNotifyNickEdit1->setEnabled(bYes);
+ m_pNotifyNickEdit2->setEnabled(bYes);
+ m_pNotifyNickLabel1->setEnabled(bYes);
+ m_pNotifyNickLabel2->setEnabled(bYes);
+
+ QString dummy;
+ notifyNickChanged(dummy);
+}
+
+#include "wizard.moc"
diff --git a/src/modules/reguser/wizard.h b/src/modules/reguser/wizard.h
new file mode 100644
index 00000000..f1446ec6
--- /dev/null
+++ b/src/modules/reguser/wizard.h
@@ -0,0 +1,89 @@
+#ifndef _WIZARD_H_
+#define _WIZARD_H_
+//
+// File : wizard.h
+// Creation date : Fri Jun 26 2002 21:21:21 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_string.h"
+
+#include <kvi_tal_wizard.h>
+
+class KviPixmap;
+class KviPixmapSelector;
+class KviTalVBoxLayout;
+class KviTalHBoxLayout;
+class QGridLayout;
+class QCheckBox;
+class QLabel;
+class QLineEdit;
+class QWidget;
+class KviRegisteredUserDataBase;
+
+class KviRegistrationWizard : public KviTalWizard
+{
+ Q_OBJECT
+public:
+ KviRegistrationWizard(const char * startMask,KviRegisteredUserDataBase * db = 0,QWidget * par = 0,bool bModal = false);
+ ~KviRegistrationWizard();
+
+ KviRegisteredUserDataBase * m_pDb;
+
+ KviStr m_szStartMask;
+
+ bool m_bModal;
+
+ QWidget* m_pPage1;
+ QLabel* m_pLabel1;
+ QLineEdit* m_pEditRealName;
+ QWidget* m_pPage2;
+ QLabel* m_pLabel2;
+ QLineEdit* m_pNicknameEdit1;
+ QLineEdit* m_pNicknameEdit2;
+ QLineEdit* m_pHostEdit1;
+ QLineEdit* m_pHostEdit2;
+ QLineEdit* m_pUsernameEdit1;
+ QLineEdit* m_pUsernameEdit2;
+ QWidget* m_pPage3;
+ QLabel* m_pLabel3;
+ KviPixmapSelector * m_pAvatarSelector;
+ QWidget* m_pPage4;
+ QCheckBox* m_pNotifyCheck;
+ QLabel* m_pNotifyNickLabel1;
+ QLabel* m_pNotifyNickLabel2;
+ QLabel* m_pLabel4;
+ QLineEdit* m_pNotifyNickEdit1;
+ QLineEdit* m_pNotifyNickEdit2;
+ QWidget* m_pPage5;
+ QLabel* m_pTextLabel5;
+
+ KviPixmap * m_pAvatar;
+protected:
+ virtual void showEvent(QShowEvent *e);
+ virtual void accept();
+ virtual void reject();
+protected slots:
+ void realNameChanged(const QString &str);
+ void maskChanged(const QString &str);
+ void notifyNickChanged(const QString &);
+ void notifyCheckToggled(bool);
+};
+
+#endif // _WIZARD_H_
diff --git a/src/modules/rijndael/Makefile.am b/src/modules/rijndael/Makefile.am
new file mode 100644
index 00000000..69b2fe01
--- /dev/null
+++ b/src/modules/rijndael/Makefile.am
@@ -0,0 +1,23 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+SUBDIRS = caps
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkvirijndael.la
+
+libkvirijndael_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkvirijndael_la_SOURCES = libkvirijndael.cpp rijndael.cpp ablowfish.cpp
+libkvirijndael_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+noinst_HEADERS= libkvirijndael.h rijndael.h ablowfish.h
+
+
+%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
+
+libkvirijndael.cpp: libkvirijndael.moc
diff --git a/src/modules/rijndael/ablowfish.cpp b/src/modules/rijndael/ablowfish.cpp
new file mode 100644
index 00000000..c56ff36a
--- /dev/null
+++ b/src/modules/rijndael/ablowfish.cpp
@@ -0,0 +1,632 @@
+//
+// File : ablowfish.cpp
+// Creation date : Wed Jan 13 2005 02:04:10 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "ablowfish.h"
+#include "kvi_memmove.h"
+
+#ifdef COMPILE_CRYPT_SUPPORT
+
+
+//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 BlowFish::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 BlowFish::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
+BlowFish::BlowFish(unsigned char* ucKey, unsigned int 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;
+ kvi_fastmove(aucLocalKey, ucKey, keysize);
+ //Reflexive Initialization of the Blowfish.
+ //Generating the Subkeys from the Key flood P and S boxes with PI
+ kvi_fastmove(m_auiP, scm_auiInitP, sizeof(m_auiP));
+ kvi_fastmove(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
+ int iCount = 0;
+ for(i=0; i<18; i++)
+ {
+ x=0;
+ for(int n=4; n--; )
+ {
+ x <<= 8;
+ x |= *(p++);
+ iCount++;
+ if(iCount == ((int)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 BlowFish::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 BlowFish::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 BlowFish::Encrypt(unsigned char* buf, unsigned int 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 BlowFish::Decrypt(unsigned char* buf, unsigned int 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 BlowFish::Encrypt(const unsigned char* in, unsigned char* out, unsigned int 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 BlowFish::Decrypt(const unsigned char* in, unsigned char* out, unsigned int 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);
+ }
+ }
+}
+
+#endif //COMPILE_CRYPT_SUPPORT
diff --git a/src/modules/rijndael/ablowfish.h b/src/modules/rijndael/ablowfish.h
new file mode 100644
index 00000000..862477dc
--- /dev/null
+++ b/src/modules/rijndael/ablowfish.h
@@ -0,0 +1,141 @@
+#ifndef _BLOWFISH_H_
+#define _BLOWFISH_H_
+//=============================================================================
+//
+// File : ablowfish.h
+// Creation date : Wed Jan 13 2005 02:04:10 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+//
+// This code is adapted from the MircCryption engine suite by Dark Raichu
+// Original comments follow.
+//
+
+//---------------------------------------------------------------------------
+// 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
+//---------------------------------------------------------------------------
+
+
+//
+// BLOWFISH ENCRYPTION ALGORITHM
+//
+// Implementation of Bruce Schneier's BLOWFISH algorithm from "Applied
+// Cryptography", Second Edition.
+//
+// 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.
+//
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_CRYPT_SUPPORT
+
+
+//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 BlowFish
+{
+public:
+ enum { ECB=0, CBC=1, CFB=2 };
+
+ //Constructor - Initialize the P and S boxes for a given Key
+ BlowFish(unsigned char* ucKey, unsigned int 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, unsigned int n, int iMode=ECB);
+ void Decrypt(unsigned char* buf, unsigned int n, int iMode=ECB);
+
+ // Encrypt/Decrypt from Input Buffer to Output Buffer
+ void Encrypt(const unsigned char* in, unsigned char* out, unsigned int n, int iMode=ECB);
+ void Decrypt(const unsigned char* in, unsigned char* out, unsigned int 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 BlowFish::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 //COMPILE_CRYPT_SUPPORT
+
+#endif //!_BLOWFISH_H_
diff --git a/src/modules/rijndael/caps/Makefile.am b/src/modules/rijndael/caps/Makefile.am
new file mode 100644
index 00000000..663f77a8
--- /dev/null
+++ b/src/modules/rijndael/caps/Makefile.am
@@ -0,0 +1,9 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+tmpdir = $(pluglibdir)/caps/crypt/
+
+tmp_DATA= rijndael
+
+EXTRA_DIST = $(tmp_DATA)
diff --git a/src/modules/rijndael/caps/rijndael b/src/modules/rijndael/caps/rijndael
new file mode 100644
index 00000000..9788f702
--- /dev/null
+++ b/src/modules/rijndael/caps/rijndael
@@ -0,0 +1 @@
+timestamp
diff --git a/src/modules/rijndael/libkvirijndael.cpp b/src/modules/rijndael/libkvirijndael.cpp
new file mode 100644
index 00000000..0a678437
--- /dev/null
+++ b/src/modules/rijndael/libkvirijndael.cpp
@@ -0,0 +1,853 @@
+//
+// File : libkvirijndael.cpp
+// Creation date : Sat Now 4 2000 15:33:12 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Till Bush (buti@geocities.com)
+//
+// 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 opinion) 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.
+//
+
+#include "libkvirijndael.h"
+
+#include "rijndael.h"
+
+#include "kvi_module.h"
+#include "kvi_debug.h"
+#include "kvi_locale.h"
+
+#include "kvi_mirccntrl.h"
+#include "kvi_time.h"
+
+//#warning "Other engines: mircStrip koi2win colorizer lamerizer etc.."
+
+/*
+ @doc: rijndael
+ @type:
+ module
+ @short:
+ The Rijndael cryptographic engines
+ @title:
+ The rijndael module
+ @body:
+ The rijndael module exports six [doc:crypt_engines]cryptographic engines[/doc] based
+ on the Advanced Encryptiong Standard algorithm called Rijndael. Rijndael was
+ originally written by Joan Daemen and Vincent Rijmen. The original Rijndael
+ description is available at http://www.esat.kuleuven.ac.be/~rijmen/rijndael/.[br]
+ It is a private key block cipher that has been designed to replace
+ the widely used DES, and it should provide at leas a decent security agains
+ common attacks. Theoretically the best attack that one can perform on this cipher
+ is the "brute force" attack that requires a really massive parallel computation:
+ actually out of the possibilities of a common "hacker".[br]
+ My implementation allows the usage of 128, 192 and 256 bit keys
+ on 128 bit data blocks. The encrypted binary data buffer is then converted
+ into an ascii-string by using the base64 conversion or hex-digit-string rappresentation.
+ The six engines are the six possible combinations of the key lengths and ascii-string
+ conversions.
+*/
+
+
+
+#ifdef COMPILE_CRYPT_SUPPORT
+
+ #include "kvi_memmove.h"
+ #include "kvi_malloc.h"
+
+ #include "kvi_pointerlist.h"
+
+ static KviPointerList<KviCryptEngine> * g_pEngineList = 0;
+
+
+
+
+ KviRijndaelEngine::KviRijndaelEngine()
+ : KviCryptEngine()
+ {
+ g_pEngineList->append(this);
+ m_pEncryptCipher = 0;
+ m_pDecryptCipher = 0;
+ }
+
+ KviRijndaelEngine::~KviRijndaelEngine()
+ {
+ g_pEngineList->removeRef(this);
+ if(m_pEncryptCipher)delete m_pEncryptCipher;
+ if(m_pDecryptCipher)delete m_pDecryptCipher;
+ }
+
+ bool KviRijndaelEngine::init(const char *encKey,int encKeyLen,const char *decKey,int decKeyLen)
+ {
+ if(m_pEncryptCipher)
+ {
+ delete m_pEncryptCipher;
+ m_pEncryptCipher = 0;
+ }
+ if(m_pDecryptCipher)
+ {
+ delete m_pDecryptCipher;
+ m_pDecryptCipher = 0;
+ }
+
+ if(encKey && (encKeyLen > 0))
+ {
+ if(!(decKey && (decKeyLen > 0)))
+ {
+ decKey = encKey;
+ decKeyLen = encKeyLen;
+ } // else all
+ } else {
+ // no encrypt key specified...
+ if(decKey && decKeyLen)
+ {
+ encKey = decKey;
+ encKeyLen = decKeyLen;
+ } else {
+ // both keys missing
+ setLastError(__tr("Missing both encrypt and decrypt key: at least one is needed"));
+ return false;
+ }
+ }
+
+ int defLen = getKeyLen();
+
+ char * encryptKey = (char *)kvi_malloc(defLen);
+ char * decryptKey = (char *)kvi_malloc(defLen);
+
+ if(encKeyLen > defLen)encKeyLen = defLen;
+ kvi_memmove(encryptKey,encKey,encKeyLen);
+ if(encKeyLen < defLen)kvi_memset(encryptKey + encKeyLen,'0',defLen - encKeyLen);
+
+ if(decKeyLen > defLen)decKeyLen = defLen;
+ kvi_memmove(decryptKey,decKey,decKeyLen);
+ if(decKeyLen < defLen)kvi_memset(decryptKey + decKeyLen,'0',defLen - decKeyLen);
+
+ m_pEncryptCipher = new Rijndael();
+ int retVal = m_pEncryptCipher->init(Rijndael::CBC,Rijndael::Encrypt,(unsigned char *)encryptKey,getKeyLenId());
+ kvi_free(encryptKey);
+ if(retVal != RIJNDAEL_SUCCESS)
+ {
+ kvi_free(decryptKey);
+ delete m_pEncryptCipher;
+ m_pEncryptCipher = 0;
+ setLastErrorFromRijndaelErrorCode(retVal);
+ return false;
+ }
+
+ m_pDecryptCipher = new Rijndael();
+ retVal = m_pDecryptCipher->init(Rijndael::CBC,Rijndael::Decrypt,(unsigned char *)decryptKey,getKeyLenId());
+ kvi_free(decryptKey);
+ if(retVal != RIJNDAEL_SUCCESS)
+ {
+ delete m_pEncryptCipher;
+ m_pEncryptCipher = 0;
+ delete m_pDecryptCipher;
+ m_pDecryptCipher = 0;
+ setLastErrorFromRijndaelErrorCode(retVal);
+ return false;
+ }
+
+ return true;
+ }
+
+ void KviRijndaelEngine::setLastErrorFromRijndaelErrorCode(int errCode)
+ {
+ switch(errCode)
+ {
+ case RIJNDAEL_SUCCESS: setLastError(__tr("Error 0: Success ?")); break;
+ case RIJNDAEL_UNSUPPORTED_MODE: setLastError(__tr("Unsupported crypt mode")); break;
+ case RIJNDAEL_UNSUPPORTED_DIRECTION: setLastError(__tr("Unsupported direction")); break;
+ case RIJNDAEL_UNSUPPORTED_KEY_LENGTH: setLastError(__tr("Unsupported key length")); break;
+ case RIJNDAEL_BAD_KEY: setLastError(__tr("Bad key data")); break;
+ case RIJNDAEL_NOT_INITIALIZED: setLastError(__tr("Engine not initialized")); break;
+ case RIJNDAEL_BAD_DIRECTION: setLastError(__tr("Invalid direction for this engine")); break;
+ case RIJNDAEL_CORRUPTED_DATA: setLastError(__tr("Corrupted message data or invalid decrypt key")); break;
+ default: setLastError(__tr("Unknown error")); break;
+ }
+ }
+
+ KviCryptEngine::EncryptResult KviRijndaelEngine::encrypt(const char * plainText,KviStr &outBuffer)
+ {
+ if(!m_pEncryptCipher)
+ {
+ setLastError(__tr("Ops...encrypt cipher not initialized"));
+ return KviCryptEngine::EncryptError;
+ }
+ int len = (int)kvi_strLen(plainText);
+ char * buf = (char *)kvi_malloc(len + 16);
+
+ int retVal = m_pEncryptCipher->padEncrypt((const unsigned char *)plainText,len,(unsigned char *)buf);
+ if(retVal < 0)
+ {
+ kvi_free(buf);
+ setLastErrorFromRijndaelErrorCode(retVal);
+ return KviCryptEngine::EncryptError;
+ }
+
+ if(!binaryToAscii(buf,retVal,outBuffer))
+ {
+ kvi_free(buf);
+ return KviCryptEngine::EncryptError;
+ }
+ kvi_free(buf);
+
+ if(outBuffer.len() > maxEncryptLen())
+ {
+ if(maxEncryptLen() > 0)
+ {
+ setLastError(__tr("Data buffer too long"));
+ return KviCryptEngine::EncryptError;
+ }
+ }
+ outBuffer.prepend(KVI_TEXT_CRYPTESCAPE);
+ return KviCryptEngine::Encrypted;
+ }
+
+ KviCryptEngine::DecryptResult KviRijndaelEngine::decrypt(const char * inBuffer,KviStr &plainText)
+ {
+ if(!m_pDecryptCipher)
+ {
+ setLastError(__tr("Ops...decrypt cipher not initialized"));
+ return KviCryptEngine::DecryptError;
+ }
+
+ if(*inBuffer != KVI_TEXT_CRYPTESCAPE)
+ {
+ plainText = inBuffer;
+ return KviCryptEngine::DecryptOkWasPlainText;
+ }
+
+ inBuffer++;
+
+ if(!*inBuffer)
+ {
+ plainText = inBuffer;
+ return KviCryptEngine::DecryptOkWasPlainText; // empty buffer
+ }
+
+ int len;
+ char * binary;
+
+ if(!asciiToBinary(inBuffer,&len,&binary))return KviCryptEngine::DecryptError;
+
+ char * buf = (char *)kvi_malloc(len + 1);
+
+ int retVal = m_pDecryptCipher->padDecrypt((const unsigned char *)binary,len,(unsigned char *)buf);
+ kvi_free(binary);
+
+ if(retVal < 0)
+ {
+ kvi_free(buf);
+ setLastErrorFromRijndaelErrorCode(retVal);
+ return KviCryptEngine::DecryptError;
+ }
+
+ buf[retVal] = '\0';
+
+ plainText = buf;
+
+ kvi_free(buf);
+ return KviCryptEngine::DecryptOkWasEncrypted;
+ }
+
+ bool KviRijndaelHexEngine::binaryToAscii(const char * inBuffer,int len,KviStr &outBuffer)
+ {
+ outBuffer.bufferToHex(inBuffer,len);
+ return true;
+ }
+
+ bool KviRijndaelHexEngine::asciiToBinary(const char * inBuffer,int * len,char ** outBuffer)
+ {
+ KviStr hex(inBuffer);
+ char * tmpBuf;
+ *len = hex.hexToBuffer(&tmpBuf,false);
+ if(*len < 0)
+ {
+ setLastError(__tr("The message is not a hexadecimal string: this is not my stuff"));
+ return false;
+ } else {
+ if(len > 0)
+ {
+ *outBuffer = (char *)kvi_malloc(*len);
+ kvi_memmove(*outBuffer,tmpBuf,*len);
+ KviStr::freeBuffer(tmpBuf);
+ }
+ }
+ return true;
+ }
+
+ bool KviRijndaelBase64Engine::binaryToAscii(const char * inBuffer,int len,KviStr &outBuffer)
+ {
+ outBuffer.bufferToBase64(inBuffer,len);
+ return true;
+ }
+
+ bool KviRijndaelBase64Engine::asciiToBinary(const char * inBuffer,int * len,char ** outBuffer)
+ {
+ KviStr base64(inBuffer);
+ char * tmpBuf;
+ *len = base64.base64ToBuffer(&tmpBuf,false);
+ if(*len < 0)
+ {
+ setLastError(__tr("The message is not a base64 string: this is not my stuff"));
+ return false;
+ } else {
+ if(len > 0)
+ {
+ *outBuffer = (char *)kvi_malloc(*len);
+ kvi_memmove(*outBuffer,tmpBuf,*len);
+ KviStr::freeBuffer(tmpBuf);
+ }
+ }
+ return true;
+ }
+
+ static KviCryptEngine * allocRijndael128HexEngine()
+ {
+ return new KviRijndael128HexEngine();
+ }
+
+ static KviCryptEngine * allocRijndael192HexEngine()
+ {
+ return new KviRijndael192HexEngine();
+ }
+
+ static KviCryptEngine * allocRijndael256HexEngine()
+ {
+ return new KviRijndael256HexEngine();
+ }
+
+ static KviCryptEngine * allocRijndael128Base64Engine()
+ {
+ return new KviRijndael128Base64Engine();
+ }
+
+ static KviCryptEngine * allocRijndael192Base64Engine()
+ {
+ return new KviRijndael192Base64Engine();
+ }
+
+ static KviCryptEngine * allocRijndael256Base64Engine()
+ {
+ return new KviRijndael256Base64Engine();
+ }
+
+ static void deallocRijndaelCryptEngine(KviCryptEngine * e)
+ {
+ delete e;
+ }
+
+
+
+
+
+ // Mircryption stuff
+
+ #include "ablowfish.h"
+
+ KviMircryptionEngine::KviMircryptionEngine()
+ : KviCryptEngine()
+ {
+ g_pEngineList->append(this);
+ }
+
+ KviMircryptionEngine::~KviMircryptionEngine()
+ {
+ g_pEngineList->removeRef(this);
+ }
+
+ bool KviMircryptionEngine::init(const char * encKey,int encKeyLen,const char * decKey,int decKeyLen)
+ {
+ if(encKey && (encKeyLen > 0))
+ {
+ if(!(decKey && (decKeyLen > 0)))
+ {
+ decKey = encKey;
+ decKeyLen = encKeyLen;
+ } // else all
+ } else {
+ // no encrypt key specified...
+ if(decKey && decKeyLen)
+ {
+ encKey = decKey;
+ encKeyLen = decKeyLen;
+ } else {
+ // both keys missing
+ setLastError(__tr("Missing both encrypt and decrypt key: at least one is needed"));
+ return false;
+ }
+ }
+ m_szEncryptKey = KviStr(encKey,encKeyLen);
+ m_szDecryptKey = KviStr(decKey,decKeyLen);
+ if(kvi_strEqualCIN("cbc:",m_szEncryptKey.ptr(),4) && (m_szEncryptKey.len() > 4))
+ m_szEncryptKey.cutLeft(4);
+ else
+ m_bEncryptCBC = false;
+ if(kvi_strEqualCIN("cbc:",m_szDecryptKey.ptr(),4) && (m_szDecryptKey.len() > 4))
+ m_szDecryptKey.cutLeft(4);
+ else
+ m_bDecryptCBC = false;
+ return true;
+ }
+
+ KviCryptEngine::EncryptResult KviMircryptionEngine::encrypt(const char * plainText,KviStr &outBuffer)
+ {
+ KviStr szPlain = plainText;
+ outBuffer = "";
+ if(m_bEncryptCBC)
+ {
+ if(!doEncryptCBC(szPlain,outBuffer))return KviCryptEngine::EncryptError;
+ } else {
+ if(!doEncryptECB(szPlain,outBuffer))return KviCryptEngine::EncryptError;
+ }
+ outBuffer.prepend("+OK ");
+
+ if(outBuffer.len() > maxEncryptLen())
+ {
+ if(maxEncryptLen() > 0)
+ {
+ setLastError(__tr("Data buffer too long"));
+ return KviCryptEngine::EncryptError;
+ }
+ }
+
+ //outBuffer = MCPS2_STARTTAG;
+ //outBuffer += MCPS2_ENDTAG;
+ return KviCryptEngine::Encrypted;
+ }
+
+ KviCryptEngine::DecryptResult KviMircryptionEngine::decrypt(const char * inBuffer,KviStr &plainText)
+ {
+ plainText = "";
+ KviStr szIn = inBuffer;
+ // various old versions
+ if(kvi_strEqualCSN(inBuffer,"mcps ",5))
+ szIn.cutLeft(5);
+ else if(kvi_strEqualCSN(inBuffer,"+OK ",4))
+ szIn.cutLeft(4);
+ else {
+ plainText = szIn;
+ return KviCryptEngine::DecryptOkWasPlainText;
+ }
+
+ if(m_bDecryptCBC)return doDecryptCBC(szIn,plainText) ? KviCryptEngine::DecryptOkWasEncrypted : KviCryptEngine::DecryptError;
+ return doDecryptECB(szIn,plainText) ? KviCryptEngine::DecryptOkWasEncrypted : KviCryptEngine::DecryptError;
+
+ /*
+ int len1 = kvi_strLen(MCPS2_STARTTAG);
+ int len2 = kvi_strLen(MCPS2_ENDTAG);
+ while(szIn.len() > 0)
+ {
+ int idx = szIn.findFirstIdx(MCPS2_STARTTAG);
+ if(idx == -1)
+ {
+ // no more encrypted stuff
+ plainText += szIn;
+ return true;
+ }
+ if(idx > 0) // a non encrypted block
+ plainText += szIn.left(idx);
+ szIn.cutLeft(idx + len1);
+
+ idx = szIn.findFirstIdx(MCPS2_ENDTAG);
+ if(idx != -1)
+ {
+ KviStr toDecrypt = szIn.left(idx);
+ if(!doDecrypt(toDecrypt,plainText))return false;
+ }
+ szIn.cutLeft(idx + len2);
+ }
+ */
+ }
+
+ static unsigned char fake_base64[]="./0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+ unsigned int fake_base64dec(unsigned char c)
+ {
+ 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[fake_base64[i]]=i;
+ didinit=true;
+ }
+
+ return base64unmap[c];
+ }
+
+ static void byteswap_buffer(unsigned char * p,int len)
+ {
+ while(len > 0)
+ {
+ unsigned char aux = p[0];
+ p[0] = p[3];
+ p[3] = aux;
+ aux = p[1];
+ p[1] = p[2];
+ p[2] = aux;
+ p += 4;
+ len -= 4;
+ }
+ }
+
+ bool KviMircryptionEngine::doEncryptECB(KviStr &plain,KviStr &encoded)
+ {
+ // make sure it is a multiple of 8 bytes (eventually pad with zeroes)
+ if(plain.len() % 8)
+ {
+ int oldL = plain.len();
+ plain.setLength(plain.len() + (8 - (plain.len() % 8)));
+ char * padB = plain.ptr() + oldL;
+ char * padE = plain.ptr() + plain.len();
+ while(padB < padE)*padB++ = 0;
+ }
+
+ //byteswap_buffer((unsigned char *)plain.ptr(),plain.len());
+
+ unsigned char * out =(unsigned char *)kvi_malloc(plain.len()); // we use this to avoid endiannes problems
+
+ BlowFish bf((unsigned char *)m_szEncryptKey.ptr(),m_szEncryptKey.len());
+ bf.ResetChain();
+ bf.Encrypt((unsigned char *)plain.ptr(),out,plain.len(),BlowFish::ECB);
+
+ // FIXME: this is probably needed only on LittleEndian machines!
+ byteswap_buffer((unsigned char *)out,plain.len());
+
+ // da uglybase64 encoding
+ unsigned char * outb = out;
+ unsigned char * oute = out + plain.len();
+
+ int ll = (plain.len() * 3) / 2;
+ encoded.setLength(ll);
+
+ unsigned char * p = (unsigned char *)encoded.ptr();
+ while(outb < oute)
+ {
+ Q_UINT32 * dd1 = (Q_UINT32 *)outb;
+ outb += 4;
+ Q_UINT32 * dd2 = (Q_UINT32 *)outb;
+ outb += 4;
+ *p++ = fake_base64[*dd2 & 0x3f]; *dd2 >>= 6;
+ *p++ = fake_base64[*dd2 & 0x3f]; *dd2 >>= 6;
+ *p++ = fake_base64[*dd2 & 0x3f]; *dd2 >>= 6;
+ *p++ = fake_base64[*dd2 & 0x3f]; *dd2 >>= 6;
+ *p++ = fake_base64[*dd2 & 0x3f]; *dd2 >>= 6;
+ *p++ = fake_base64[*dd2 & 0x3f];
+
+ *p++ = fake_base64[*dd1 & 0x3f]; *dd1 >>= 6;
+ *p++ = fake_base64[*dd1 & 0x3f]; *dd1 >>= 6;
+ *p++ = fake_base64[*dd1 & 0x3f]; *dd1 >>= 6;
+ *p++ = fake_base64[*dd1 & 0x3f]; *dd1 >>= 6;
+ *p++ = fake_base64[*dd1 & 0x3f]; *dd1 >>= 6;
+ *p++ = fake_base64[*dd1 & 0x3f];
+ }
+
+ kvi_free(out);
+ return true;
+ }
+
+ bool KviMircryptionEngine::doDecryptECB(KviStr &encoded,KviStr &plain)
+ {
+ // encoded is in this strange base64...
+ // make sure its length is multiple of 12 (eventually pad with zeroes)
+ if(encoded.len() % 12)
+ {
+ int oldL = encoded.len();
+ encoded.setLength(encoded.len() + (12 - (encoded.len() % 12)));
+ char * padB = encoded.ptr() + oldL;
+ char * padE = encoded.ptr() + encoded.len();
+ while(padB < padE)*padB++ = 0;
+ }
+
+ // a fake base64 decoding algo, use a different character set
+ // and stuff 6 bytes at a time into a 32 bit long...
+ int ll = (encoded.len() * 2) / 3;
+
+ unsigned char * buf = (unsigned char *)kvi_malloc(ll);
+ unsigned char * p = (unsigned char *)encoded.ptr();
+ unsigned char * e = p + encoded.len();
+ int i;
+ unsigned char * bufp = buf;
+ while(p < e)
+ {
+ Q_UINT32 * dw1 = (Q_UINT32 *)bufp;
+ bufp += 4;
+ Q_UINT32 * dw2 = (Q_UINT32 *)bufp;
+ bufp += 4;
+ *dw2 = 0;
+ for(i=0;i < 6;i++)*dw2 |= (fake_base64dec(*p++)) << (i * 6);
+ *dw1 = 0;
+ for(i=0;i < 6;i++)*dw1 |= (fake_base64dec(*p++)) << (i * 6);
+ }
+
+ // FIXME: this is probably needed only on LittleEndian machines!
+ byteswap_buffer((unsigned char *)buf,ll);
+
+ plain.setLength(ll);
+ BlowFish bf((unsigned char *)m_szDecryptKey.ptr(),m_szDecryptKey.len());
+ bf.ResetChain();
+ bf.Decrypt(buf,(unsigned char *)plain.ptr(),ll,BlowFish::ECB);
+
+ //byteswap_buffer((unsigned char *)plain.ptr(),ll);
+
+ kvi_free(buf);
+
+ return true;
+ }
+
+ bool KviMircryptionEngine::doEncryptCBC(KviStr &plain,KviStr &encoded)
+ {
+ // make sure it is a multiple of 8 bytes (eventually pad with zeroes)
+ if(plain.len() % 8)
+ {
+ int oldL = plain.len();
+ plain.setLength(plain.len() + (8 - (plain.len() % 8)));
+ char * padB = plain.ptr() + oldL;
+ char * padE = plain.ptr() + plain.len();
+ while(padB < padE)*padB++ = 0;
+ }
+
+ int ll = plain.len() + 8;
+ unsigned char * in = (unsigned char *)kvi_malloc(ll);
+
+ // choose an IV
+ static bool bDidInit = false;
+
+ int t = (int)kvi_unixTime();
+
+ if(!bDidInit)
+ {
+ srand(t);
+ bDidInit = true;
+ }
+
+ for(int i=0;i<8;i++)in[i] = (unsigned char)(rand() % 256);
+
+ kvi_fastmove(in+8,plain.ptr(),plain.len());
+
+ // encrypt
+ unsigned char * out = (unsigned char *)kvi_malloc(ll);
+ BlowFish bf((unsigned char *)m_szEncryptKey.ptr(),m_szEncryptKey.len());
+ bf.ResetChain();
+ bf.Encrypt(in,out,ll,BlowFish::CBC);
+ kvi_free(in);
+
+ encoded.bufferToBase64((const char *)out,ll);
+ kvi_free(out);
+
+ encoded.prepend('*'); // prepend the signature
+
+ return true;
+ }
+
+ bool KviMircryptionEngine::doDecryptCBC(KviStr &encoded,KviStr &plain)
+ {
+ if(*(encoded.ptr()) != '*')
+ {
+ debug("WARNING: Specified a CBC key but the incoming message doesn't seem to be a CBC one");
+ return doDecryptECB(encoded,plain);
+ }
+ encoded.cutLeft(1);
+
+ char * tmpBuf;
+ int len = encoded.base64ToBuffer(&tmpBuf,false);
+ if(len < 0)
+ {
+ setLastError(__tr("The message is not a base64 string: this is not my stuff"));
+ return false;
+ }
+ if((len < 8) || (len % 8))
+ {
+ setLastError(__tr("The message doesn't seem to be encoded with CBC Mircryption"));
+ if(len > 0)KviStr::freeBuffer(tmpBuf);
+ return false;
+ }
+
+ plain.setLength(len);
+ BlowFish bf((unsigned char *)m_szDecryptKey.ptr(),m_szDecryptKey.len());
+ bf.ResetChain();
+ bf.Decrypt((unsigned char *)tmpBuf,(unsigned char *)plain.ptr(),len,BlowFish::CBC);
+
+ // kill the first 8 bytes (random IV)
+ plain.cutLeft(8);
+
+ KviStr::freeBuffer(tmpBuf);
+
+ return true;
+ }
+
+
+ static KviCryptEngine * allocMircryptionEngine()
+ {
+ return new KviMircryptionEngine();
+ }
+
+#endif
+
+
+// =======================================
+// module routines
+// =======================================
+static bool rijndael_module_init(KviModule * m)
+{
+#ifdef COMPILE_CRYPT_SUPPORT
+ g_pEngineList = new KviPointerList<KviCryptEngine>;
+ g_pEngineList->setAutoDelete(false);
+
+ KviStr format = __tr("Cryptographic engine based on the\n" \
+ "Advanced Encryption Standard (AES)\n" \
+ "algorithm called Rijndael.\n" \
+ "The text is first encrypted with rijndael\n" \
+ "and then converted to %s notation.\n" \
+ "The keys used are %d bit long and will be padded\n" \
+ "with zeros if you provide shorter ones.\n" \
+ "If only one key is provided, this engine\n" \
+ "will use it for both encrypting and decrypting.\n" \
+ "See the rijndael module documentation\n" \
+ "for more info on the algorithm used.\n");
+
+ // FIXME: Maybe convert this repeated code to a function eh ?
+
+ KviCryptEngineDescription * d = new KviCryptEngineDescription;
+ d->szName = "Rijndael128Hex";
+ d->szAuthor = "Szymon Stefanek";
+ d->szDescription.sprintf(format.ptr(),__tr("hexadecimal"),128);
+ d->iFlags = KVI_CRYPTENGINE_CAN_ENCRYPT | KVI_CRYPTENGINE_CAN_DECRYPT |
+ KVI_CRYPTENGINE_WANT_ENCRYPT_KEY | KVI_CRYPTENGINE_WANT_DECRYPT_KEY;
+ d->allocFunc = allocRijndael128HexEngine;
+ d->deallocFunc = deallocRijndaelCryptEngine;
+ m->registerCryptEngine(d);
+
+ d = new KviCryptEngineDescription;
+ d->szName = "Rijndael192Hex";
+ d->szAuthor = "Szymon Stefanek";
+ d->szDescription.sprintf(format.ptr(),__tr("hexadecimal"),192);
+ d->iFlags = KVI_CRYPTENGINE_CAN_ENCRYPT | KVI_CRYPTENGINE_CAN_DECRYPT |
+ KVI_CRYPTENGINE_WANT_ENCRYPT_KEY | KVI_CRYPTENGINE_WANT_DECRYPT_KEY;
+ d->allocFunc = allocRijndael192HexEngine;
+ d->deallocFunc = deallocRijndaelCryptEngine;
+ m->registerCryptEngine(d);
+
+ d = new KviCryptEngineDescription;
+ d->szName = "Rijndael256Hex";
+ d->szAuthor = "Szymon Stefanek";
+ d->szDescription.sprintf(format.ptr(),__tr("hexadecimal"),256);
+ d->iFlags = KVI_CRYPTENGINE_CAN_ENCRYPT | KVI_CRYPTENGINE_CAN_DECRYPT |
+ KVI_CRYPTENGINE_WANT_ENCRYPT_KEY | KVI_CRYPTENGINE_WANT_DECRYPT_KEY;
+ d->allocFunc = allocRijndael256HexEngine;
+ d->deallocFunc = deallocRijndaelCryptEngine;
+ m->registerCryptEngine(d);
+
+ d = new KviCryptEngineDescription;
+ d->szName = "Rijndael128Base64";
+ d->szAuthor = "Szymon Stefanek";
+ d->szDescription.sprintf(format.ptr(),__tr("base64"),128);
+ d->iFlags = KVI_CRYPTENGINE_CAN_ENCRYPT | KVI_CRYPTENGINE_CAN_DECRYPT |
+ KVI_CRYPTENGINE_WANT_ENCRYPT_KEY | KVI_CRYPTENGINE_WANT_DECRYPT_KEY;
+ d->allocFunc = allocRijndael128Base64Engine;
+ d->deallocFunc = deallocRijndaelCryptEngine;
+ m->registerCryptEngine(d);
+
+ d = new KviCryptEngineDescription;
+ d->szName = "Rijndael192Base64";
+ d->szAuthor = "Szymon Stefanek";
+ d->szDescription.sprintf(format.ptr(),__tr("base64"),192);
+ d->iFlags = KVI_CRYPTENGINE_CAN_ENCRYPT | KVI_CRYPTENGINE_CAN_DECRYPT |
+ KVI_CRYPTENGINE_WANT_ENCRYPT_KEY | KVI_CRYPTENGINE_WANT_DECRYPT_KEY;
+ d->allocFunc = allocRijndael192Base64Engine;
+ d->deallocFunc = deallocRijndaelCryptEngine;
+ m->registerCryptEngine(d);
+
+ d = new KviCryptEngineDescription;
+ d->szName = "Rijndael256Base64";
+ d->szAuthor = "Szymon Stefanek";
+ d->szDescription.sprintf(format.ptr(),__tr("base64"),256);
+ d->iFlags = KVI_CRYPTENGINE_CAN_ENCRYPT | KVI_CRYPTENGINE_CAN_DECRYPT |
+ KVI_CRYPTENGINE_WANT_ENCRYPT_KEY | KVI_CRYPTENGINE_WANT_DECRYPT_KEY;
+ d->allocFunc = allocRijndael256Base64Engine;
+ d->deallocFunc = deallocRijndaelCryptEngine;
+ m->registerCryptEngine(d);
+
+
+ d = new KviCryptEngineDescription;
+ d->szName = "Mircryption";
+ d->szAuthor = "Szymon Stefanek";
+ d->szDescription = __tr("Popular cryptographic engine based on the\n" \
+ "old Blowfish encryption algorithm.\n" \
+ "The text is first encrypted with Blowfish \n" \
+ "and then converted to base64 notation.\n" \
+ "The keys used have variable length and\n" \
+ "are specified as character strings.\n" \
+ "You can specify keys long up to 56 bytes (448 bits).\n" \
+ "If only one key is provided, this engine\n" \
+ "will use it for both encrypting and decrypting.\n" \
+ "This engine works in ECB mode by default:\n" \
+ "if you want to use CBC mode you must prefix\n" \
+ "your key(s) with \"cbc:\".\n");
+ d->iFlags = KVI_CRYPTENGINE_CAN_ENCRYPT | KVI_CRYPTENGINE_CAN_DECRYPT |
+ KVI_CRYPTENGINE_WANT_ENCRYPT_KEY | KVI_CRYPTENGINE_WANT_DECRYPT_KEY;
+ d->allocFunc = allocMircryptionEngine;
+ d->deallocFunc = deallocRijndaelCryptEngine;
+ m->registerCryptEngine(d);
+
+
+ return true;
+#else
+ return false;
+#endif
+}
+
+static bool rijndael_module_cleanup(KviModule *m)
+{
+#ifdef COMPILE_CRYPT_SUPPORT
+ while(g_pEngineList->first())delete g_pEngineList->first();
+ delete g_pEngineList;
+ g_pEngineList = 0;
+ m->unregisterCryptEngines();
+ return true;
+#else
+ return false;
+#endif
+}
+
+static bool rijndael_module_can_unload(KviModule *)
+{
+#ifdef COMPILE_CRYPT_SUPPORT
+ return g_pEngineList->isEmpty();
+#else
+ return true;
+#endif
+}
+
+// =======================================
+// plugin definition structure
+// =======================================
+KVIRC_MODULE(
+ "Rijndael crypt engine",
+ "1.0.0",
+ "Szymon Stefanek <pragma at kvirc dot net>" ,
+ "Exports the rijndael crypt engine",
+ rijndael_module_init ,
+ rijndael_module_can_unload,
+ 0,
+ rijndael_module_cleanup
+)
+
+#ifdef COMPILE_CRYPT_SUPPORT
+ #include "libkvirijndael.moc"
+#endif
diff --git a/src/modules/rijndael/libkvirijndael.h b/src/modules/rijndael/libkvirijndael.h
new file mode 100644
index 00000000..900ff252
--- /dev/null
+++ b/src/modules/rijndael/libkvirijndael.h
@@ -0,0 +1,169 @@
+#ifndef _LIBKVIRIJNDAEL_H_
+#define _LIBKVIRIJNDAEL_H_
+//
+// File : libkvirijndael.h
+// Creation date : Sat Now 4 2000 15:41:41 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Till Bush (buti@geocities.com)
+//
+// 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_CRYPT_SUPPORT
+
+ #include "kvi_crypt.h"
+ #include "rijndael.h"
+
+ class KviRijndaelEngine : public KviCryptEngine
+ {
+ Q_OBJECT
+ public:
+ KviRijndaelEngine();
+ virtual ~KviRijndaelEngine();
+ private:
+ Rijndael * m_pEncryptCipher;
+ Rijndael * m_pDecryptCipher;
+ public:
+ virtual bool init(const char *encKey,int encKeyLen,const char *decKey,int decKeyLen);
+ virtual KviCryptEngine::EncryptResult encrypt(const char * plainText,KviStr &outBuffer);
+ virtual KviCryptEngine::DecryptResult decrypt(const char * inBuffer,KviStr &plainText);
+ protected:
+ virtual bool binaryToAscii(const char * inBuffer,int len,KviStr &outBuffer){ return false; };
+ virtual bool asciiToBinary(const char * inBuffer,int * len,char ** outBuffer){ return false; };
+ virtual int getKeyLen(){ return 32; };
+ virtual Rijndael::KeyLength getKeyLenId(){ return Rijndael::Key32Bytes; };
+ private:
+ void setLastErrorFromRijndaelErrorCode(int errCode);
+ };
+
+ class KviRijndaelHexEngine : public KviRijndaelEngine
+ {
+ Q_OBJECT
+ public:
+ KviRijndaelHexEngine() : KviRijndaelEngine() {};
+ virtual ~KviRijndaelHexEngine(){};
+ protected:
+ virtual bool binaryToAscii(const char * inBuffer,int len,KviStr &outBuffer);
+ virtual bool asciiToBinary(const char * inBuffer,int * len,char ** outBuffer);
+ };
+
+ class KviRijndael128HexEngine : public KviRijndaelHexEngine
+ {
+ Q_OBJECT
+ public:
+ KviRijndael128HexEngine() : KviRijndaelHexEngine() {};
+ virtual ~KviRijndael128HexEngine(){};
+ protected:
+ virtual int getKenLen(){ return 16; };
+ virtual Rijndael::KeyLength getKeyLenId(){ return Rijndael::Key16Bytes; };
+ };
+
+ class KviRijndael192HexEngine : public KviRijndaelHexEngine
+ {
+ Q_OBJECT
+ public:
+ KviRijndael192HexEngine() : KviRijndaelHexEngine() {};
+ virtual ~KviRijndael192HexEngine(){};
+ protected:
+ virtual int getKenLen(){ return 24; };
+ virtual Rijndael::KeyLength getKeyLenId(){ return Rijndael::Key24Bytes; };
+ };
+
+ class KviRijndael256HexEngine : public KviRijndaelHexEngine
+ {
+ Q_OBJECT
+ public:
+ KviRijndael256HexEngine() : KviRijndaelHexEngine() {};
+ virtual ~KviRijndael256HexEngine(){};
+ protected:
+ virtual int getKenLen(){ return 32; };
+ };
+
+ class KviRijndaelBase64Engine : public KviRijndaelEngine
+ {
+ Q_OBJECT
+ public:
+ KviRijndaelBase64Engine() : KviRijndaelEngine() {};
+ virtual ~KviRijndaelBase64Engine(){};
+ protected:
+ virtual bool binaryToAscii(const char * inBuffer,int len,KviStr &outBuffer);
+ virtual bool asciiToBinary(const char * inBuffer,int * len,char ** outBuffer);
+ };
+
+ class KviRijndael128Base64Engine : public KviRijndaelBase64Engine
+ {
+ Q_OBJECT
+ public:
+ KviRijndael128Base64Engine() : KviRijndaelBase64Engine() {};
+ virtual ~KviRijndael128Base64Engine(){};
+ protected:
+ virtual int getKenLen(){ return 16; };
+ virtual Rijndael::KeyLength getKeyLenId(){ return Rijndael::Key16Bytes; };
+ };
+
+ class KviRijndael192Base64Engine : public KviRijndaelBase64Engine
+ {
+ Q_OBJECT
+ public:
+ KviRijndael192Base64Engine() : KviRijndaelBase64Engine() {};
+ virtual ~KviRijndael192Base64Engine(){};
+ protected:
+ virtual int getKenLen(){ return 24; };
+ virtual Rijndael::KeyLength getKeyLenId(){ return Rijndael::Key24Bytes; };
+ };
+
+ class KviRijndael256Base64Engine : public KviRijndaelBase64Engine
+ {
+ Q_OBJECT
+ public:
+ KviRijndael256Base64Engine() : KviRijndaelBase64Engine() {};
+ virtual ~KviRijndael256Base64Engine(){};
+ protected:
+ virtual int getKenLen(){ return 32; };
+ };
+
+ // Mircyption stuff
+ #define MCPS2_STARTTAG "\xABm\xAB"
+ #define MCPS2_ENDTAG "\xBBm\xBB"
+
+ class KviMircryptionEngine : public KviCryptEngine
+ {
+ Q_OBJECT
+ public:
+ KviMircryptionEngine();
+ ~KviMircryptionEngine();
+ protected:
+ KviStr m_szEncryptKey;
+ bool m_bEncryptCBC;
+ KviStr m_szDecryptKey;
+ bool m_bDecryptCBC;
+ public:
+ virtual bool isCryptographicEngine(){ return false; }; // we need to return false since it doesn't use the Qt::CTRL+P escape
+ virtual bool init(const char *encKey,int encKeyLen,const char *decKey,int decKeyLen);
+ virtual KviCryptEngine::EncryptResult encrypt(const char * plainText,KviStr &outBuffer);
+ virtual KviCryptEngine::DecryptResult decrypt(const char * inBuffer,KviStr &plainText);
+ protected:
+ bool doDecryptECB(KviStr &encoded,KviStr &plain);
+ bool doDecryptCBC(KviStr &encoded,KviStr &plain);
+ bool doEncryptECB(KviStr &plain,KviStr &encoded);
+ bool doEncryptCBC(KviStr &plain,KviStr &encoded);
+ };
+
+#endif // COMPILE_CRYPT_SUPPORT
+
+#endif // _LIBKVIRIJNDAEL_H_
diff --git a/src/modules/rijndael/rijndael.cpp b/src/modules/rijndael/rijndael.cpp
new file mode 100644
index 00000000..8adbf926
--- /dev/null
+++ b/src/modules/rijndael/rijndael.cpp
@@ -0,0 +1,1626 @@
+//
+// File : rijndael.cpp
+// Creation date : Sun Nov 5 2000 03:22:10 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+//
+// Another implementation of the Rijndael cipher.
+// This is intended to be an easily usable library file.
+// Based on the Vincent Rijmen and K.U.Leuven implementation 2.4.
+//
+
+//
+// Original Copyright notice:
+//
+// rijndael-alg-fst.c v2.4 April '2000
+// rijndael-alg-fst.h
+// rijndael-api-fst.c
+// rijndael-api-fst.h
+//
+// Optimised ANSI C code
+//
+// authors: v1.0: Antoon Bosselaers
+// v2.0: Vincent Rijmen, K.U.Leuven
+// v2.3: Paulo Barreto
+// v2.4: Vincent Rijmen, K.U.Leuven
+//
+// This code is placed in the public domain.
+//
+
+//
+// This implementation works on 128 , 192 , 256 bit keys
+// and on 128 bit blocks
+//
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_CRYPT_SUPPORT
+
+#define _RIJNDAEL_CPP_
+
+#include "rijndael.h"
+
+#include "kvi_memmove.h"
+
+//#include <stdio.h>
+//#include <stdlib.h>
+
+static UINT8 S[256]=
+{
+ 99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118,
+ 202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192,
+ 183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21,
+ 4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117,
+ 9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132,
+ 83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207,
+ 208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168,
+ 81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210,
+ 205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115,
+ 96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219,
+ 224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121,
+ 231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8,
+ 186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138,
+ 112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158,
+ 225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223,
+ 140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22
+};
+
+
+static UINT8 T1[256][4]=
+{
+ 0xc6,0x63,0x63,0xa5, 0xf8,0x7c,0x7c,0x84, 0xee,0x77,0x77,0x99, 0xf6,0x7b,0x7b,0x8d,
+ 0xff,0xf2,0xf2,0x0d, 0xd6,0x6b,0x6b,0xbd, 0xde,0x6f,0x6f,0xb1, 0x91,0xc5,0xc5,0x54,
+ 0x60,0x30,0x30,0x50, 0x02,0x01,0x01,0x03, 0xce,0x67,0x67,0xa9, 0x56,0x2b,0x2b,0x7d,
+ 0xe7,0xfe,0xfe,0x19, 0xb5,0xd7,0xd7,0x62, 0x4d,0xab,0xab,0xe6, 0xec,0x76,0x76,0x9a,
+ 0x8f,0xca,0xca,0x45, 0x1f,0x82,0x82,0x9d, 0x89,0xc9,0xc9,0x40, 0xfa,0x7d,0x7d,0x87,
+ 0xef,0xfa,0xfa,0x15, 0xb2,0x59,0x59,0xeb, 0x8e,0x47,0x47,0xc9, 0xfb,0xf0,0xf0,0x0b,
+ 0x41,0xad,0xad,0xec, 0xb3,0xd4,0xd4,0x67, 0x5f,0xa2,0xa2,0xfd, 0x45,0xaf,0xaf,0xea,
+ 0x23,0x9c,0x9c,0xbf, 0x53,0xa4,0xa4,0xf7, 0xe4,0x72,0x72,0x96, 0x9b,0xc0,0xc0,0x5b,
+ 0x75,0xb7,0xb7,0xc2, 0xe1,0xfd,0xfd,0x1c, 0x3d,0x93,0x93,0xae, 0x4c,0x26,0x26,0x6a,
+ 0x6c,0x36,0x36,0x5a, 0x7e,0x3f,0x3f,0x41, 0xf5,0xf7,0xf7,0x02, 0x83,0xcc,0xcc,0x4f,
+ 0x68,0x34,0x34,0x5c, 0x51,0xa5,0xa5,0xf4, 0xd1,0xe5,0xe5,0x34, 0xf9,0xf1,0xf1,0x08,
+ 0xe2,0x71,0x71,0x93, 0xab,0xd8,0xd8,0x73, 0x62,0x31,0x31,0x53, 0x2a,0x15,0x15,0x3f,
+ 0x08,0x04,0x04,0x0c, 0x95,0xc7,0xc7,0x52, 0x46,0x23,0x23,0x65, 0x9d,0xc3,0xc3,0x5e,
+ 0x30,0x18,0x18,0x28, 0x37,0x96,0x96,0xa1, 0x0a,0x05,0x05,0x0f, 0x2f,0x9a,0x9a,0xb5,
+ 0x0e,0x07,0x07,0x09, 0x24,0x12,0x12,0x36, 0x1b,0x80,0x80,0x9b, 0xdf,0xe2,0xe2,0x3d,
+ 0xcd,0xeb,0xeb,0x26, 0x4e,0x27,0x27,0x69, 0x7f,0xb2,0xb2,0xcd, 0xea,0x75,0x75,0x9f,
+ 0x12,0x09,0x09,0x1b, 0x1d,0x83,0x83,0x9e, 0x58,0x2c,0x2c,0x74, 0x34,0x1a,0x1a,0x2e,
+ 0x36,0x1b,0x1b,0x2d, 0xdc,0x6e,0x6e,0xb2, 0xb4,0x5a,0x5a,0xee, 0x5b,0xa0,0xa0,0xfb,
+ 0xa4,0x52,0x52,0xf6, 0x76,0x3b,0x3b,0x4d, 0xb7,0xd6,0xd6,0x61, 0x7d,0xb3,0xb3,0xce,
+ 0x52,0x29,0x29,0x7b, 0xdd,0xe3,0xe3,0x3e, 0x5e,0x2f,0x2f,0x71, 0x13,0x84,0x84,0x97,
+ 0xa6,0x53,0x53,0xf5, 0xb9,0xd1,0xd1,0x68, 0x00,0x00,0x00,0x00, 0xc1,0xed,0xed,0x2c,
+ 0x40,0x20,0x20,0x60, 0xe3,0xfc,0xfc,0x1f, 0x79,0xb1,0xb1,0xc8, 0xb6,0x5b,0x5b,0xed,
+ 0xd4,0x6a,0x6a,0xbe, 0x8d,0xcb,0xcb,0x46, 0x67,0xbe,0xbe,0xd9, 0x72,0x39,0x39,0x4b,
+ 0x94,0x4a,0x4a,0xde, 0x98,0x4c,0x4c,0xd4, 0xb0,0x58,0x58,0xe8, 0x85,0xcf,0xcf,0x4a,
+ 0xbb,0xd0,0xd0,0x6b, 0xc5,0xef,0xef,0x2a, 0x4f,0xaa,0xaa,0xe5, 0xed,0xfb,0xfb,0x16,
+ 0x86,0x43,0x43,0xc5, 0x9a,0x4d,0x4d,0xd7, 0x66,0x33,0x33,0x55, 0x11,0x85,0x85,0x94,
+ 0x8a,0x45,0x45,0xcf, 0xe9,0xf9,0xf9,0x10, 0x04,0x02,0x02,0x06, 0xfe,0x7f,0x7f,0x81,
+ 0xa0,0x50,0x50,0xf0, 0x78,0x3c,0x3c,0x44, 0x25,0x9f,0x9f,0xba, 0x4b,0xa8,0xa8,0xe3,
+ 0xa2,0x51,0x51,0xf3, 0x5d,0xa3,0xa3,0xfe, 0x80,0x40,0x40,0xc0, 0x05,0x8f,0x8f,0x8a,
+ 0x3f,0x92,0x92,0xad, 0x21,0x9d,0x9d,0xbc, 0x70,0x38,0x38,0x48, 0xf1,0xf5,0xf5,0x04,
+ 0x63,0xbc,0xbc,0xdf, 0x77,0xb6,0xb6,0xc1, 0xaf,0xda,0xda,0x75, 0x42,0x21,0x21,0x63,
+ 0x20,0x10,0x10,0x30, 0xe5,0xff,0xff,0x1a, 0xfd,0xf3,0xf3,0x0e, 0xbf,0xd2,0xd2,0x6d,
+ 0x81,0xcd,0xcd,0x4c, 0x18,0x0c,0x0c,0x14, 0x26,0x13,0x13,0x35, 0xc3,0xec,0xec,0x2f,
+ 0xbe,0x5f,0x5f,0xe1, 0x35,0x97,0x97,0xa2, 0x88,0x44,0x44,0xcc, 0x2e,0x17,0x17,0x39,
+ 0x93,0xc4,0xc4,0x57, 0x55,0xa7,0xa7,0xf2, 0xfc,0x7e,0x7e,0x82, 0x7a,0x3d,0x3d,0x47,
+ 0xc8,0x64,0x64,0xac, 0xba,0x5d,0x5d,0xe7, 0x32,0x19,0x19,0x2b, 0xe6,0x73,0x73,0x95,
+ 0xc0,0x60,0x60,0xa0, 0x19,0x81,0x81,0x98, 0x9e,0x4f,0x4f,0xd1, 0xa3,0xdc,0xdc,0x7f,
+ 0x44,0x22,0x22,0x66, 0x54,0x2a,0x2a,0x7e, 0x3b,0x90,0x90,0xab, 0x0b,0x88,0x88,0x83,
+ 0x8c,0x46,0x46,0xca, 0xc7,0xee,0xee,0x29, 0x6b,0xb8,0xb8,0xd3, 0x28,0x14,0x14,0x3c,
+ 0xa7,0xde,0xde,0x79, 0xbc,0x5e,0x5e,0xe2, 0x16,0x0b,0x0b,0x1d, 0xad,0xdb,0xdb,0x76,
+ 0xdb,0xe0,0xe0,0x3b, 0x64,0x32,0x32,0x56, 0x74,0x3a,0x3a,0x4e, 0x14,0x0a,0x0a,0x1e,
+ 0x92,0x49,0x49,0xdb, 0x0c,0x06,0x06,0x0a, 0x48,0x24,0x24,0x6c, 0xb8,0x5c,0x5c,0xe4,
+ 0x9f,0xc2,0xc2,0x5d, 0xbd,0xd3,0xd3,0x6e, 0x43,0xac,0xac,0xef, 0xc4,0x62,0x62,0xa6,
+ 0x39,0x91,0x91,0xa8, 0x31,0x95,0x95,0xa4, 0xd3,0xe4,0xe4,0x37, 0xf2,0x79,0x79,0x8b,
+ 0xd5,0xe7,0xe7,0x32, 0x8b,0xc8,0xc8,0x43, 0x6e,0x37,0x37,0x59, 0xda,0x6d,0x6d,0xb7,
+ 0x01,0x8d,0x8d,0x8c, 0xb1,0xd5,0xd5,0x64, 0x9c,0x4e,0x4e,0xd2, 0x49,0xa9,0xa9,0xe0,
+ 0xd8,0x6c,0x6c,0xb4, 0xac,0x56,0x56,0xfa, 0xf3,0xf4,0xf4,0x07, 0xcf,0xea,0xea,0x25,
+ 0xca,0x65,0x65,0xaf, 0xf4,0x7a,0x7a,0x8e, 0x47,0xae,0xae,0xe9, 0x10,0x08,0x08,0x18,
+ 0x6f,0xba,0xba,0xd5, 0xf0,0x78,0x78,0x88, 0x4a,0x25,0x25,0x6f, 0x5c,0x2e,0x2e,0x72,
+ 0x38,0x1c,0x1c,0x24, 0x57,0xa6,0xa6,0xf1, 0x73,0xb4,0xb4,0xc7, 0x97,0xc6,0xc6,0x51,
+ 0xcb,0xe8,0xe8,0x23, 0xa1,0xdd,0xdd,0x7c, 0xe8,0x74,0x74,0x9c, 0x3e,0x1f,0x1f,0x21,
+ 0x96,0x4b,0x4b,0xdd, 0x61,0xbd,0xbd,0xdc, 0x0d,0x8b,0x8b,0x86, 0x0f,0x8a,0x8a,0x85,
+ 0xe0,0x70,0x70,0x90, 0x7c,0x3e,0x3e,0x42, 0x71,0xb5,0xb5,0xc4, 0xcc,0x66,0x66,0xaa,
+ 0x90,0x48,0x48,0xd8, 0x06,0x03,0x03,0x05, 0xf7,0xf6,0xf6,0x01, 0x1c,0x0e,0x0e,0x12,
+ 0xc2,0x61,0x61,0xa3, 0x6a,0x35,0x35,0x5f, 0xae,0x57,0x57,0xf9, 0x69,0xb9,0xb9,0xd0,
+ 0x17,0x86,0x86,0x91, 0x99,0xc1,0xc1,0x58, 0x3a,0x1d,0x1d,0x27, 0x27,0x9e,0x9e,0xb9,
+ 0xd9,0xe1,0xe1,0x38, 0xeb,0xf8,0xf8,0x13, 0x2b,0x98,0x98,0xb3, 0x22,0x11,0x11,0x33,
+ 0xd2,0x69,0x69,0xbb, 0xa9,0xd9,0xd9,0x70, 0x07,0x8e,0x8e,0x89, 0x33,0x94,0x94,0xa7,
+ 0x2d,0x9b,0x9b,0xb6, 0x3c,0x1e,0x1e,0x22, 0x15,0x87,0x87,0x92, 0xc9,0xe9,0xe9,0x20,
+ 0x87,0xce,0xce,0x49, 0xaa,0x55,0x55,0xff, 0x50,0x28,0x28,0x78, 0xa5,0xdf,0xdf,0x7a,
+ 0x03,0x8c,0x8c,0x8f, 0x59,0xa1,0xa1,0xf8, 0x09,0x89,0x89,0x80, 0x1a,0x0d,0x0d,0x17,
+ 0x65,0xbf,0xbf,0xda, 0xd7,0xe6,0xe6,0x31, 0x84,0x42,0x42,0xc6, 0xd0,0x68,0x68,0xb8,
+ 0x82,0x41,0x41,0xc3, 0x29,0x99,0x99,0xb0, 0x5a,0x2d,0x2d,0x77, 0x1e,0x0f,0x0f,0x11,
+ 0x7b,0xb0,0xb0,0xcb, 0xa8,0x54,0x54,0xfc, 0x6d,0xbb,0xbb,0xd6, 0x2c,0x16,0x16,0x3a
+};
+
+static UINT8 T2[256][4]=
+{
+ 0xa5,0xc6,0x63,0x63, 0x84,0xf8,0x7c,0x7c, 0x99,0xee,0x77,0x77, 0x8d,0xf6,0x7b,0x7b,
+ 0x0d,0xff,0xf2,0xf2, 0xbd,0xd6,0x6b,0x6b, 0xb1,0xde,0x6f,0x6f, 0x54,0x91,0xc5,0xc5,
+ 0x50,0x60,0x30,0x30, 0x03,0x02,0x01,0x01, 0xa9,0xce,0x67,0x67, 0x7d,0x56,0x2b,0x2b,
+ 0x19,0xe7,0xfe,0xfe, 0x62,0xb5,0xd7,0xd7, 0xe6,0x4d,0xab,0xab, 0x9a,0xec,0x76,0x76,
+ 0x45,0x8f,0xca,0xca, 0x9d,0x1f,0x82,0x82, 0x40,0x89,0xc9,0xc9, 0x87,0xfa,0x7d,0x7d,
+ 0x15,0xef,0xfa,0xfa, 0xeb,0xb2,0x59,0x59, 0xc9,0x8e,0x47,0x47, 0x0b,0xfb,0xf0,0xf0,
+ 0xec,0x41,0xad,0xad, 0x67,0xb3,0xd4,0xd4, 0xfd,0x5f,0xa2,0xa2, 0xea,0x45,0xaf,0xaf,
+ 0xbf,0x23,0x9c,0x9c, 0xf7,0x53,0xa4,0xa4, 0x96,0xe4,0x72,0x72, 0x5b,0x9b,0xc0,0xc0,
+ 0xc2,0x75,0xb7,0xb7, 0x1c,0xe1,0xfd,0xfd, 0xae,0x3d,0x93,0x93, 0x6a,0x4c,0x26,0x26,
+ 0x5a,0x6c,0x36,0x36, 0x41,0x7e,0x3f,0x3f, 0x02,0xf5,0xf7,0xf7, 0x4f,0x83,0xcc,0xcc,
+ 0x5c,0x68,0x34,0x34, 0xf4,0x51,0xa5,0xa5, 0x34,0xd1,0xe5,0xe5, 0x08,0xf9,0xf1,0xf1,
+ 0x93,0xe2,0x71,0x71, 0x73,0xab,0xd8,0xd8, 0x53,0x62,0x31,0x31, 0x3f,0x2a,0x15,0x15,
+ 0x0c,0x08,0x04,0x04, 0x52,0x95,0xc7,0xc7, 0x65,0x46,0x23,0x23, 0x5e,0x9d,0xc3,0xc3,
+ 0x28,0x30,0x18,0x18, 0xa1,0x37,0x96,0x96, 0x0f,0x0a,0x05,0x05, 0xb5,0x2f,0x9a,0x9a,
+ 0x09,0x0e,0x07,0x07, 0x36,0x24,0x12,0x12, 0x9b,0x1b,0x80,0x80, 0x3d,0xdf,0xe2,0xe2,
+ 0x26,0xcd,0xeb,0xeb, 0x69,0x4e,0x27,0x27, 0xcd,0x7f,0xb2,0xb2, 0x9f,0xea,0x75,0x75,
+ 0x1b,0x12,0x09,0x09, 0x9e,0x1d,0x83,0x83, 0x74,0x58,0x2c,0x2c, 0x2e,0x34,0x1a,0x1a,
+ 0x2d,0x36,0x1b,0x1b, 0xb2,0xdc,0x6e,0x6e, 0xee,0xb4,0x5a,0x5a, 0xfb,0x5b,0xa0,0xa0,
+ 0xf6,0xa4,0x52,0x52, 0x4d,0x76,0x3b,0x3b, 0x61,0xb7,0xd6,0xd6, 0xce,0x7d,0xb3,0xb3,
+ 0x7b,0x52,0x29,0x29, 0x3e,0xdd,0xe3,0xe3, 0x71,0x5e,0x2f,0x2f, 0x97,0x13,0x84,0x84,
+ 0xf5,0xa6,0x53,0x53, 0x68,0xb9,0xd1,0xd1, 0x00,0x00,0x00,0x00, 0x2c,0xc1,0xed,0xed,
+ 0x60,0x40,0x20,0x20, 0x1f,0xe3,0xfc,0xfc, 0xc8,0x79,0xb1,0xb1, 0xed,0xb6,0x5b,0x5b,
+ 0xbe,0xd4,0x6a,0x6a, 0x46,0x8d,0xcb,0xcb, 0xd9,0x67,0xbe,0xbe, 0x4b,0x72,0x39,0x39,
+ 0xde,0x94,0x4a,0x4a, 0xd4,0x98,0x4c,0x4c, 0xe8,0xb0,0x58,0x58, 0x4a,0x85,0xcf,0xcf,
+ 0x6b,0xbb,0xd0,0xd0, 0x2a,0xc5,0xef,0xef, 0xe5,0x4f,0xaa,0xaa, 0x16,0xed,0xfb,0xfb,
+ 0xc5,0x86,0x43,0x43, 0xd7,0x9a,0x4d,0x4d, 0x55,0x66,0x33,0x33, 0x94,0x11,0x85,0x85,
+ 0xcf,0x8a,0x45,0x45, 0x10,0xe9,0xf9,0xf9, 0x06,0x04,0x02,0x02, 0x81,0xfe,0x7f,0x7f,
+ 0xf0,0xa0,0x50,0x50, 0x44,0x78,0x3c,0x3c, 0xba,0x25,0x9f,0x9f, 0xe3,0x4b,0xa8,0xa8,
+ 0xf3,0xa2,0x51,0x51, 0xfe,0x5d,0xa3,0xa3, 0xc0,0x80,0x40,0x40, 0x8a,0x05,0x8f,0x8f,
+ 0xad,0x3f,0x92,0x92, 0xbc,0x21,0x9d,0x9d, 0x48,0x70,0x38,0x38, 0x04,0xf1,0xf5,0xf5,
+ 0xdf,0x63,0xbc,0xbc, 0xc1,0x77,0xb6,0xb6, 0x75,0xaf,0xda,0xda, 0x63,0x42,0x21,0x21,
+ 0x30,0x20,0x10,0x10, 0x1a,0xe5,0xff,0xff, 0x0e,0xfd,0xf3,0xf3, 0x6d,0xbf,0xd2,0xd2,
+ 0x4c,0x81,0xcd,0xcd, 0x14,0x18,0x0c,0x0c, 0x35,0x26,0x13,0x13, 0x2f,0xc3,0xec,0xec,
+ 0xe1,0xbe,0x5f,0x5f, 0xa2,0x35,0x97,0x97, 0xcc,0x88,0x44,0x44, 0x39,0x2e,0x17,0x17,
+ 0x57,0x93,0xc4,0xc4, 0xf2,0x55,0xa7,0xa7, 0x82,0xfc,0x7e,0x7e, 0x47,0x7a,0x3d,0x3d,
+ 0xac,0xc8,0x64,0x64, 0xe7,0xba,0x5d,0x5d, 0x2b,0x32,0x19,0x19, 0x95,0xe6,0x73,0x73,
+ 0xa0,0xc0,0x60,0x60, 0x98,0x19,0x81,0x81, 0xd1,0x9e,0x4f,0x4f, 0x7f,0xa3,0xdc,0xdc,
+ 0x66,0x44,0x22,0x22, 0x7e,0x54,0x2a,0x2a, 0xab,0x3b,0x90,0x90, 0x83,0x0b,0x88,0x88,
+ 0xca,0x8c,0x46,0x46, 0x29,0xc7,0xee,0xee, 0xd3,0x6b,0xb8,0xb8, 0x3c,0x28,0x14,0x14,
+ 0x79,0xa7,0xde,0xde, 0xe2,0xbc,0x5e,0x5e, 0x1d,0x16,0x0b,0x0b, 0x76,0xad,0xdb,0xdb,
+ 0x3b,0xdb,0xe0,0xe0, 0x56,0x64,0x32,0x32, 0x4e,0x74,0x3a,0x3a, 0x1e,0x14,0x0a,0x0a,
+ 0xdb,0x92,0x49,0x49, 0x0a,0x0c,0x06,0x06, 0x6c,0x48,0x24,0x24, 0xe4,0xb8,0x5c,0x5c,
+ 0x5d,0x9f,0xc2,0xc2, 0x6e,0xbd,0xd3,0xd3, 0xef,0x43,0xac,0xac, 0xa6,0xc4,0x62,0x62,
+ 0xa8,0x39,0x91,0x91, 0xa4,0x31,0x95,0x95, 0x37,0xd3,0xe4,0xe4, 0x8b,0xf2,0x79,0x79,
+ 0x32,0xd5,0xe7,0xe7, 0x43,0x8b,0xc8,0xc8, 0x59,0x6e,0x37,0x37, 0xb7,0xda,0x6d,0x6d,
+ 0x8c,0x01,0x8d,0x8d, 0x64,0xb1,0xd5,0xd5, 0xd2,0x9c,0x4e,0x4e, 0xe0,0x49,0xa9,0xa9,
+ 0xb4,0xd8,0x6c,0x6c, 0xfa,0xac,0x56,0x56, 0x07,0xf3,0xf4,0xf4, 0x25,0xcf,0xea,0xea,
+ 0xaf,0xca,0x65,0x65, 0x8e,0xf4,0x7a,0x7a, 0xe9,0x47,0xae,0xae, 0x18,0x10,0x08,0x08,
+ 0xd5,0x6f,0xba,0xba, 0x88,0xf0,0x78,0x78, 0x6f,0x4a,0x25,0x25, 0x72,0x5c,0x2e,0x2e,
+ 0x24,0x38,0x1c,0x1c, 0xf1,0x57,0xa6,0xa6, 0xc7,0x73,0xb4,0xb4, 0x51,0x97,0xc6,0xc6,
+ 0x23,0xcb,0xe8,0xe8, 0x7c,0xa1,0xdd,0xdd, 0x9c,0xe8,0x74,0x74, 0x21,0x3e,0x1f,0x1f,
+ 0xdd,0x96,0x4b,0x4b, 0xdc,0x61,0xbd,0xbd, 0x86,0x0d,0x8b,0x8b, 0x85,0x0f,0x8a,0x8a,
+ 0x90,0xe0,0x70,0x70, 0x42,0x7c,0x3e,0x3e, 0xc4,0x71,0xb5,0xb5, 0xaa,0xcc,0x66,0x66,
+ 0xd8,0x90,0x48,0x48, 0x05,0x06,0x03,0x03, 0x01,0xf7,0xf6,0xf6, 0x12,0x1c,0x0e,0x0e,
+ 0xa3,0xc2,0x61,0x61, 0x5f,0x6a,0x35,0x35, 0xf9,0xae,0x57,0x57, 0xd0,0x69,0xb9,0xb9,
+ 0x91,0x17,0x86,0x86, 0x58,0x99,0xc1,0xc1, 0x27,0x3a,0x1d,0x1d, 0xb9,0x27,0x9e,0x9e,
+ 0x38,0xd9,0xe1,0xe1, 0x13,0xeb,0xf8,0xf8, 0xb3,0x2b,0x98,0x98, 0x33,0x22,0x11,0x11,
+ 0xbb,0xd2,0x69,0x69, 0x70,0xa9,0xd9,0xd9, 0x89,0x07,0x8e,0x8e, 0xa7,0x33,0x94,0x94,
+ 0xb6,0x2d,0x9b,0x9b, 0x22,0x3c,0x1e,0x1e, 0x92,0x15,0x87,0x87, 0x20,0xc9,0xe9,0xe9,
+ 0x49,0x87,0xce,0xce, 0xff,0xaa,0x55,0x55, 0x78,0x50,0x28,0x28, 0x7a,0xa5,0xdf,0xdf,
+ 0x8f,0x03,0x8c,0x8c, 0xf8,0x59,0xa1,0xa1, 0x80,0x09,0x89,0x89, 0x17,0x1a,0x0d,0x0d,
+ 0xda,0x65,0xbf,0xbf, 0x31,0xd7,0xe6,0xe6, 0xc6,0x84,0x42,0x42, 0xb8,0xd0,0x68,0x68,
+ 0xc3,0x82,0x41,0x41, 0xb0,0x29,0x99,0x99, 0x77,0x5a,0x2d,0x2d, 0x11,0x1e,0x0f,0x0f,
+ 0xcb,0x7b,0xb0,0xb0, 0xfc,0xa8,0x54,0x54, 0xd6,0x6d,0xbb,0xbb, 0x3a,0x2c,0x16,0x16
+};
+
+static UINT8 T3[256][4]=
+{
+ 0x63,0xa5,0xc6,0x63, 0x7c,0x84,0xf8,0x7c, 0x77,0x99,0xee,0x77, 0x7b,0x8d,0xf6,0x7b,
+ 0xf2,0x0d,0xff,0xf2, 0x6b,0xbd,0xd6,0x6b, 0x6f,0xb1,0xde,0x6f, 0xc5,0x54,0x91,0xc5,
+ 0x30,0x50,0x60,0x30, 0x01,0x03,0x02,0x01, 0x67,0xa9,0xce,0x67, 0x2b,0x7d,0x56,0x2b,
+ 0xfe,0x19,0xe7,0xfe, 0xd7,0x62,0xb5,0xd7, 0xab,0xe6,0x4d,0xab, 0x76,0x9a,0xec,0x76,
+ 0xca,0x45,0x8f,0xca, 0x82,0x9d,0x1f,0x82, 0xc9,0x40,0x89,0xc9, 0x7d,0x87,0xfa,0x7d,
+ 0xfa,0x15,0xef,0xfa, 0x59,0xeb,0xb2,0x59, 0x47,0xc9,0x8e,0x47, 0xf0,0x0b,0xfb,0xf0,
+ 0xad,0xec,0x41,0xad, 0xd4,0x67,0xb3,0xd4, 0xa2,0xfd,0x5f,0xa2, 0xaf,0xea,0x45,0xaf,
+ 0x9c,0xbf,0x23,0x9c, 0xa4,0xf7,0x53,0xa4, 0x72,0x96,0xe4,0x72, 0xc0,0x5b,0x9b,0xc0,
+ 0xb7,0xc2,0x75,0xb7, 0xfd,0x1c,0xe1,0xfd, 0x93,0xae,0x3d,0x93, 0x26,0x6a,0x4c,0x26,
+ 0x36,0x5a,0x6c,0x36, 0x3f,0x41,0x7e,0x3f, 0xf7,0x02,0xf5,0xf7, 0xcc,0x4f,0x83,0xcc,
+ 0x34,0x5c,0x68,0x34, 0xa5,0xf4,0x51,0xa5, 0xe5,0x34,0xd1,0xe5, 0xf1,0x08,0xf9,0xf1,
+ 0x71,0x93,0xe2,0x71, 0xd8,0x73,0xab,0xd8, 0x31,0x53,0x62,0x31, 0x15,0x3f,0x2a,0x15,
+ 0x04,0x0c,0x08,0x04, 0xc7,0x52,0x95,0xc7, 0x23,0x65,0x46,0x23, 0xc3,0x5e,0x9d,0xc3,
+ 0x18,0x28,0x30,0x18, 0x96,0xa1,0x37,0x96, 0x05,0x0f,0x0a,0x05, 0x9a,0xb5,0x2f,0x9a,
+ 0x07,0x09,0x0e,0x07, 0x12,0x36,0x24,0x12, 0x80,0x9b,0x1b,0x80, 0xe2,0x3d,0xdf,0xe2,
+ 0xeb,0x26,0xcd,0xeb, 0x27,0x69,0x4e,0x27, 0xb2,0xcd,0x7f,0xb2, 0x75,0x9f,0xea,0x75,
+ 0x09,0x1b,0x12,0x09, 0x83,0x9e,0x1d,0x83, 0x2c,0x74,0x58,0x2c, 0x1a,0x2e,0x34,0x1a,
+ 0x1b,0x2d,0x36,0x1b, 0x6e,0xb2,0xdc,0x6e, 0x5a,0xee,0xb4,0x5a, 0xa0,0xfb,0x5b,0xa0,
+ 0x52,0xf6,0xa4,0x52, 0x3b,0x4d,0x76,0x3b, 0xd6,0x61,0xb7,0xd6, 0xb3,0xce,0x7d,0xb3,
+ 0x29,0x7b,0x52,0x29, 0xe3,0x3e,0xdd,0xe3, 0x2f,0x71,0x5e,0x2f, 0x84,0x97,0x13,0x84,
+ 0x53,0xf5,0xa6,0x53, 0xd1,0x68,0xb9,0xd1, 0x00,0x00,0x00,0x00, 0xed,0x2c,0xc1,0xed,
+ 0x20,0x60,0x40,0x20, 0xfc,0x1f,0xe3,0xfc, 0xb1,0xc8,0x79,0xb1, 0x5b,0xed,0xb6,0x5b,
+ 0x6a,0xbe,0xd4,0x6a, 0xcb,0x46,0x8d,0xcb, 0xbe,0xd9,0x67,0xbe, 0x39,0x4b,0x72,0x39,
+ 0x4a,0xde,0x94,0x4a, 0x4c,0xd4,0x98,0x4c, 0x58,0xe8,0xb0,0x58, 0xcf,0x4a,0x85,0xcf,
+ 0xd0,0x6b,0xbb,0xd0, 0xef,0x2a,0xc5,0xef, 0xaa,0xe5,0x4f,0xaa, 0xfb,0x16,0xed,0xfb,
+ 0x43,0xc5,0x86,0x43, 0x4d,0xd7,0x9a,0x4d, 0x33,0x55,0x66,0x33, 0x85,0x94,0x11,0x85,
+ 0x45,0xcf,0x8a,0x45, 0xf9,0x10,0xe9,0xf9, 0x02,0x06,0x04,0x02, 0x7f,0x81,0xfe,0x7f,
+ 0x50,0xf0,0xa0,0x50, 0x3c,0x44,0x78,0x3c, 0x9f,0xba,0x25,0x9f, 0xa8,0xe3,0x4b,0xa8,
+ 0x51,0xf3,0xa2,0x51, 0xa3,0xfe,0x5d,0xa3, 0x40,0xc0,0x80,0x40, 0x8f,0x8a,0x05,0x8f,
+ 0x92,0xad,0x3f,0x92, 0x9d,0xbc,0x21,0x9d, 0x38,0x48,0x70,0x38, 0xf5,0x04,0xf1,0xf5,
+ 0xbc,0xdf,0x63,0xbc, 0xb6,0xc1,0x77,0xb6, 0xda,0x75,0xaf,0xda, 0x21,0x63,0x42,0x21,
+ 0x10,0x30,0x20,0x10, 0xff,0x1a,0xe5,0xff, 0xf3,0x0e,0xfd,0xf3, 0xd2,0x6d,0xbf,0xd2,
+ 0xcd,0x4c,0x81,0xcd, 0x0c,0x14,0x18,0x0c, 0x13,0x35,0x26,0x13, 0xec,0x2f,0xc3,0xec,
+ 0x5f,0xe1,0xbe,0x5f, 0x97,0xa2,0x35,0x97, 0x44,0xcc,0x88,0x44, 0x17,0x39,0x2e,0x17,
+ 0xc4,0x57,0x93,0xc4, 0xa7,0xf2,0x55,0xa7, 0x7e,0x82,0xfc,0x7e, 0x3d,0x47,0x7a,0x3d,
+ 0x64,0xac,0xc8,0x64, 0x5d,0xe7,0xba,0x5d, 0x19,0x2b,0x32,0x19, 0x73,0x95,0xe6,0x73,
+ 0x60,0xa0,0xc0,0x60, 0x81,0x98,0x19,0x81, 0x4f,0xd1,0x9e,0x4f, 0xdc,0x7f,0xa3,0xdc,
+ 0x22,0x66,0x44,0x22, 0x2a,0x7e,0x54,0x2a, 0x90,0xab,0x3b,0x90, 0x88,0x83,0x0b,0x88,
+ 0x46,0xca,0x8c,0x46, 0xee,0x29,0xc7,0xee, 0xb8,0xd3,0x6b,0xb8, 0x14,0x3c,0x28,0x14,
+ 0xde,0x79,0xa7,0xde, 0x5e,0xe2,0xbc,0x5e, 0x0b,0x1d,0x16,0x0b, 0xdb,0x76,0xad,0xdb,
+ 0xe0,0x3b,0xdb,0xe0, 0x32,0x56,0x64,0x32, 0x3a,0x4e,0x74,0x3a, 0x0a,0x1e,0x14,0x0a,
+ 0x49,0xdb,0x92,0x49, 0x06,0x0a,0x0c,0x06, 0x24,0x6c,0x48,0x24, 0x5c,0xe4,0xb8,0x5c,
+ 0xc2,0x5d,0x9f,0xc2, 0xd3,0x6e,0xbd,0xd3, 0xac,0xef,0x43,0xac, 0x62,0xa6,0xc4,0x62,
+ 0x91,0xa8,0x39,0x91, 0x95,0xa4,0x31,0x95, 0xe4,0x37,0xd3,0xe4, 0x79,0x8b,0xf2,0x79,
+ 0xe7,0x32,0xd5,0xe7, 0xc8,0x43,0x8b,0xc8, 0x37,0x59,0x6e,0x37, 0x6d,0xb7,0xda,0x6d,
+ 0x8d,0x8c,0x01,0x8d, 0xd5,0x64,0xb1,0xd5, 0x4e,0xd2,0x9c,0x4e, 0xa9,0xe0,0x49,0xa9,
+ 0x6c,0xb4,0xd8,0x6c, 0x56,0xfa,0xac,0x56, 0xf4,0x07,0xf3,0xf4, 0xea,0x25,0xcf,0xea,
+ 0x65,0xaf,0xca,0x65, 0x7a,0x8e,0xf4,0x7a, 0xae,0xe9,0x47,0xae, 0x08,0x18,0x10,0x08,
+ 0xba,0xd5,0x6f,0xba, 0x78,0x88,0xf0,0x78, 0x25,0x6f,0x4a,0x25, 0x2e,0x72,0x5c,0x2e,
+ 0x1c,0x24,0x38,0x1c, 0xa6,0xf1,0x57,0xa6, 0xb4,0xc7,0x73,0xb4, 0xc6,0x51,0x97,0xc6,
+ 0xe8,0x23,0xcb,0xe8, 0xdd,0x7c,0xa1,0xdd, 0x74,0x9c,0xe8,0x74, 0x1f,0x21,0x3e,0x1f,
+ 0x4b,0xdd,0x96,0x4b, 0xbd,0xdc,0x61,0xbd, 0x8b,0x86,0x0d,0x8b, 0x8a,0x85,0x0f,0x8a,
+ 0x70,0x90,0xe0,0x70, 0x3e,0x42,0x7c,0x3e, 0xb5,0xc4,0x71,0xb5, 0x66,0xaa,0xcc,0x66,
+ 0x48,0xd8,0x90,0x48, 0x03,0x05,0x06,0x03, 0xf6,0x01,0xf7,0xf6, 0x0e,0x12,0x1c,0x0e,
+ 0x61,0xa3,0xc2,0x61, 0x35,0x5f,0x6a,0x35, 0x57,0xf9,0xae,0x57, 0xb9,0xd0,0x69,0xb9,
+ 0x86,0x91,0x17,0x86, 0xc1,0x58,0x99,0xc1, 0x1d,0x27,0x3a,0x1d, 0x9e,0xb9,0x27,0x9e,
+ 0xe1,0x38,0xd9,0xe1, 0xf8,0x13,0xeb,0xf8, 0x98,0xb3,0x2b,0x98, 0x11,0x33,0x22,0x11,
+ 0x69,0xbb,0xd2,0x69, 0xd9,0x70,0xa9,0xd9, 0x8e,0x89,0x07,0x8e, 0x94,0xa7,0x33,0x94,
+ 0x9b,0xb6,0x2d,0x9b, 0x1e,0x22,0x3c,0x1e, 0x87,0x92,0x15,0x87, 0xe9,0x20,0xc9,0xe9,
+ 0xce,0x49,0x87,0xce, 0x55,0xff,0xaa,0x55, 0x28,0x78,0x50,0x28, 0xdf,0x7a,0xa5,0xdf,
+ 0x8c,0x8f,0x03,0x8c, 0xa1,0xf8,0x59,0xa1, 0x89,0x80,0x09,0x89, 0x0d,0x17,0x1a,0x0d,
+ 0xbf,0xda,0x65,0xbf, 0xe6,0x31,0xd7,0xe6, 0x42,0xc6,0x84,0x42, 0x68,0xb8,0xd0,0x68,
+ 0x41,0xc3,0x82,0x41, 0x99,0xb0,0x29,0x99, 0x2d,0x77,0x5a,0x2d, 0x0f,0x11,0x1e,0x0f,
+ 0xb0,0xcb,0x7b,0xb0, 0x54,0xfc,0xa8,0x54, 0xbb,0xd6,0x6d,0xbb, 0x16,0x3a,0x2c,0x16
+};
+
+static UINT8 T4[256][4]=
+{
+ 0x63,0x63,0xa5,0xc6, 0x7c,0x7c,0x84,0xf8, 0x77,0x77,0x99,0xee, 0x7b,0x7b,0x8d,0xf6,
+ 0xf2,0xf2,0x0d,0xff, 0x6b,0x6b,0xbd,0xd6, 0x6f,0x6f,0xb1,0xde, 0xc5,0xc5,0x54,0x91,
+ 0x30,0x30,0x50,0x60, 0x01,0x01,0x03,0x02, 0x67,0x67,0xa9,0xce, 0x2b,0x2b,0x7d,0x56,
+ 0xfe,0xfe,0x19,0xe7, 0xd7,0xd7,0x62,0xb5, 0xab,0xab,0xe6,0x4d, 0x76,0x76,0x9a,0xec,
+ 0xca,0xca,0x45,0x8f, 0x82,0x82,0x9d,0x1f, 0xc9,0xc9,0x40,0x89, 0x7d,0x7d,0x87,0xfa,
+ 0xfa,0xfa,0x15,0xef, 0x59,0x59,0xeb,0xb2, 0x47,0x47,0xc9,0x8e, 0xf0,0xf0,0x0b,0xfb,
+ 0xad,0xad,0xec,0x41, 0xd4,0xd4,0x67,0xb3, 0xa2,0xa2,0xfd,0x5f, 0xaf,0xaf,0xea,0x45,
+ 0x9c,0x9c,0xbf,0x23, 0xa4,0xa4,0xf7,0x53, 0x72,0x72,0x96,0xe4, 0xc0,0xc0,0x5b,0x9b,
+ 0xb7,0xb7,0xc2,0x75, 0xfd,0xfd,0x1c,0xe1, 0x93,0x93,0xae,0x3d, 0x26,0x26,0x6a,0x4c,
+ 0x36,0x36,0x5a,0x6c, 0x3f,0x3f,0x41,0x7e, 0xf7,0xf7,0x02,0xf5, 0xcc,0xcc,0x4f,0x83,
+ 0x34,0x34,0x5c,0x68, 0xa5,0xa5,0xf4,0x51, 0xe5,0xe5,0x34,0xd1, 0xf1,0xf1,0x08,0xf9,
+ 0x71,0x71,0x93,0xe2, 0xd8,0xd8,0x73,0xab, 0x31,0x31,0x53,0x62, 0x15,0x15,0x3f,0x2a,
+ 0x04,0x04,0x0c,0x08, 0xc7,0xc7,0x52,0x95, 0x23,0x23,0x65,0x46, 0xc3,0xc3,0x5e,0x9d,
+ 0x18,0x18,0x28,0x30, 0x96,0x96,0xa1,0x37, 0x05,0x05,0x0f,0x0a, 0x9a,0x9a,0xb5,0x2f,
+ 0x07,0x07,0x09,0x0e, 0x12,0x12,0x36,0x24, 0x80,0x80,0x9b,0x1b, 0xe2,0xe2,0x3d,0xdf,
+ 0xeb,0xeb,0x26,0xcd, 0x27,0x27,0x69,0x4e, 0xb2,0xb2,0xcd,0x7f, 0x75,0x75,0x9f,0xea,
+ 0x09,0x09,0x1b,0x12, 0x83,0x83,0x9e,0x1d, 0x2c,0x2c,0x74,0x58, 0x1a,0x1a,0x2e,0x34,
+ 0x1b,0x1b,0x2d,0x36, 0x6e,0x6e,0xb2,0xdc, 0x5a,0x5a,0xee,0xb4, 0xa0,0xa0,0xfb,0x5b,
+ 0x52,0x52,0xf6,0xa4, 0x3b,0x3b,0x4d,0x76, 0xd6,0xd6,0x61,0xb7, 0xb3,0xb3,0xce,0x7d,
+ 0x29,0x29,0x7b,0x52, 0xe3,0xe3,0x3e,0xdd, 0x2f,0x2f,0x71,0x5e, 0x84,0x84,0x97,0x13,
+ 0x53,0x53,0xf5,0xa6, 0xd1,0xd1,0x68,0xb9, 0x00,0x00,0x00,0x00, 0xed,0xed,0x2c,0xc1,
+ 0x20,0x20,0x60,0x40, 0xfc,0xfc,0x1f,0xe3, 0xb1,0xb1,0xc8,0x79, 0x5b,0x5b,0xed,0xb6,
+ 0x6a,0x6a,0xbe,0xd4, 0xcb,0xcb,0x46,0x8d, 0xbe,0xbe,0xd9,0x67, 0x39,0x39,0x4b,0x72,
+ 0x4a,0x4a,0xde,0x94, 0x4c,0x4c,0xd4,0x98, 0x58,0x58,0xe8,0xb0, 0xcf,0xcf,0x4a,0x85,
+ 0xd0,0xd0,0x6b,0xbb, 0xef,0xef,0x2a,0xc5, 0xaa,0xaa,0xe5,0x4f, 0xfb,0xfb,0x16,0xed,
+ 0x43,0x43,0xc5,0x86, 0x4d,0x4d,0xd7,0x9a, 0x33,0x33,0x55,0x66, 0x85,0x85,0x94,0x11,
+ 0x45,0x45,0xcf,0x8a, 0xf9,0xf9,0x10,0xe9, 0x02,0x02,0x06,0x04, 0x7f,0x7f,0x81,0xfe,
+ 0x50,0x50,0xf0,0xa0, 0x3c,0x3c,0x44,0x78, 0x9f,0x9f,0xba,0x25, 0xa8,0xa8,0xe3,0x4b,
+ 0x51,0x51,0xf3,0xa2, 0xa3,0xa3,0xfe,0x5d, 0x40,0x40,0xc0,0x80, 0x8f,0x8f,0x8a,0x05,
+ 0x92,0x92,0xad,0x3f, 0x9d,0x9d,0xbc,0x21, 0x38,0x38,0x48,0x70, 0xf5,0xf5,0x04,0xf1,
+ 0xbc,0xbc,0xdf,0x63, 0xb6,0xb6,0xc1,0x77, 0xda,0xda,0x75,0xaf, 0x21,0x21,0x63,0x42,
+ 0x10,0x10,0x30,0x20, 0xff,0xff,0x1a,0xe5, 0xf3,0xf3,0x0e,0xfd, 0xd2,0xd2,0x6d,0xbf,
+ 0xcd,0xcd,0x4c,0x81, 0x0c,0x0c,0x14,0x18, 0x13,0x13,0x35,0x26, 0xec,0xec,0x2f,0xc3,
+ 0x5f,0x5f,0xe1,0xbe, 0x97,0x97,0xa2,0x35, 0x44,0x44,0xcc,0x88, 0x17,0x17,0x39,0x2e,
+ 0xc4,0xc4,0x57,0x93, 0xa7,0xa7,0xf2,0x55, 0x7e,0x7e,0x82,0xfc, 0x3d,0x3d,0x47,0x7a,
+ 0x64,0x64,0xac,0xc8, 0x5d,0x5d,0xe7,0xba, 0x19,0x19,0x2b,0x32, 0x73,0x73,0x95,0xe6,
+ 0x60,0x60,0xa0,0xc0, 0x81,0x81,0x98,0x19, 0x4f,0x4f,0xd1,0x9e, 0xdc,0xdc,0x7f,0xa3,
+ 0x22,0x22,0x66,0x44, 0x2a,0x2a,0x7e,0x54, 0x90,0x90,0xab,0x3b, 0x88,0x88,0x83,0x0b,
+ 0x46,0x46,0xca,0x8c, 0xee,0xee,0x29,0xc7, 0xb8,0xb8,0xd3,0x6b, 0x14,0x14,0x3c,0x28,
+ 0xde,0xde,0x79,0xa7, 0x5e,0x5e,0xe2,0xbc, 0x0b,0x0b,0x1d,0x16, 0xdb,0xdb,0x76,0xad,
+ 0xe0,0xe0,0x3b,0xdb, 0x32,0x32,0x56,0x64, 0x3a,0x3a,0x4e,0x74, 0x0a,0x0a,0x1e,0x14,
+ 0x49,0x49,0xdb,0x92, 0x06,0x06,0x0a,0x0c, 0x24,0x24,0x6c,0x48, 0x5c,0x5c,0xe4,0xb8,
+ 0xc2,0xc2,0x5d,0x9f, 0xd3,0xd3,0x6e,0xbd, 0xac,0xac,0xef,0x43, 0x62,0x62,0xa6,0xc4,
+ 0x91,0x91,0xa8,0x39, 0x95,0x95,0xa4,0x31, 0xe4,0xe4,0x37,0xd3, 0x79,0x79,0x8b,0xf2,
+ 0xe7,0xe7,0x32,0xd5, 0xc8,0xc8,0x43,0x8b, 0x37,0x37,0x59,0x6e, 0x6d,0x6d,0xb7,0xda,
+ 0x8d,0x8d,0x8c,0x01, 0xd5,0xd5,0x64,0xb1, 0x4e,0x4e,0xd2,0x9c, 0xa9,0xa9,0xe0,0x49,
+ 0x6c,0x6c,0xb4,0xd8, 0x56,0x56,0xfa,0xac, 0xf4,0xf4,0x07,0xf3, 0xea,0xea,0x25,0xcf,
+ 0x65,0x65,0xaf,0xca, 0x7a,0x7a,0x8e,0xf4, 0xae,0xae,0xe9,0x47, 0x08,0x08,0x18,0x10,
+ 0xba,0xba,0xd5,0x6f, 0x78,0x78,0x88,0xf0, 0x25,0x25,0x6f,0x4a, 0x2e,0x2e,0x72,0x5c,
+ 0x1c,0x1c,0x24,0x38, 0xa6,0xa6,0xf1,0x57, 0xb4,0xb4,0xc7,0x73, 0xc6,0xc6,0x51,0x97,
+ 0xe8,0xe8,0x23,0xcb, 0xdd,0xdd,0x7c,0xa1, 0x74,0x74,0x9c,0xe8, 0x1f,0x1f,0x21,0x3e,
+ 0x4b,0x4b,0xdd,0x96, 0xbd,0xbd,0xdc,0x61, 0x8b,0x8b,0x86,0x0d, 0x8a,0x8a,0x85,0x0f,
+ 0x70,0x70,0x90,0xe0, 0x3e,0x3e,0x42,0x7c, 0xb5,0xb5,0xc4,0x71, 0x66,0x66,0xaa,0xcc,
+ 0x48,0x48,0xd8,0x90, 0x03,0x03,0x05,0x06, 0xf6,0xf6,0x01,0xf7, 0x0e,0x0e,0x12,0x1c,
+ 0x61,0x61,0xa3,0xc2, 0x35,0x35,0x5f,0x6a, 0x57,0x57,0xf9,0xae, 0xb9,0xb9,0xd0,0x69,
+ 0x86,0x86,0x91,0x17, 0xc1,0xc1,0x58,0x99, 0x1d,0x1d,0x27,0x3a, 0x9e,0x9e,0xb9,0x27,
+ 0xe1,0xe1,0x38,0xd9, 0xf8,0xf8,0x13,0xeb, 0x98,0x98,0xb3,0x2b, 0x11,0x11,0x33,0x22,
+ 0x69,0x69,0xbb,0xd2, 0xd9,0xd9,0x70,0xa9, 0x8e,0x8e,0x89,0x07, 0x94,0x94,0xa7,0x33,
+ 0x9b,0x9b,0xb6,0x2d, 0x1e,0x1e,0x22,0x3c, 0x87,0x87,0x92,0x15, 0xe9,0xe9,0x20,0xc9,
+ 0xce,0xce,0x49,0x87, 0x55,0x55,0xff,0xaa, 0x28,0x28,0x78,0x50, 0xdf,0xdf,0x7a,0xa5,
+ 0x8c,0x8c,0x8f,0x03, 0xa1,0xa1,0xf8,0x59, 0x89,0x89,0x80,0x09, 0x0d,0x0d,0x17,0x1a,
+ 0xbf,0xbf,0xda,0x65, 0xe6,0xe6,0x31,0xd7, 0x42,0x42,0xc6,0x84, 0x68,0x68,0xb8,0xd0,
+ 0x41,0x41,0xc3,0x82, 0x99,0x99,0xb0,0x29, 0x2d,0x2d,0x77,0x5a, 0x0f,0x0f,0x11,0x1e,
+ 0xb0,0xb0,0xcb,0x7b, 0x54,0x54,0xfc,0xa8, 0xbb,0xbb,0xd6,0x6d, 0x16,0x16,0x3a,0x2c
+};
+
+static UINT8 T5[256][4]=
+{
+ 0x51,0xf4,0xa7,0x50, 0x7e,0x41,0x65,0x53, 0x1a,0x17,0xa4,0xc3, 0x3a,0x27,0x5e,0x96,
+ 0x3b,0xab,0x6b,0xcb, 0x1f,0x9d,0x45,0xf1, 0xac,0xfa,0x58,0xab, 0x4b,0xe3,0x03,0x93,
+ 0x20,0x30,0xfa,0x55, 0xad,0x76,0x6d,0xf6, 0x88,0xcc,0x76,0x91, 0xf5,0x02,0x4c,0x25,
+ 0x4f,0xe5,0xd7,0xfc, 0xc5,0x2a,0xcb,0xd7, 0x26,0x35,0x44,0x80, 0xb5,0x62,0xa3,0x8f,
+ 0xde,0xb1,0x5a,0x49, 0x25,0xba,0x1b,0x67, 0x45,0xea,0x0e,0x98, 0x5d,0xfe,0xc0,0xe1,
+ 0xc3,0x2f,0x75,0x02, 0x81,0x4c,0xf0,0x12, 0x8d,0x46,0x97,0xa3, 0x6b,0xd3,0xf9,0xc6,
+ 0x03,0x8f,0x5f,0xe7, 0x15,0x92,0x9c,0x95, 0xbf,0x6d,0x7a,0xeb, 0x95,0x52,0x59,0xda,
+ 0xd4,0xbe,0x83,0x2d, 0x58,0x74,0x21,0xd3, 0x49,0xe0,0x69,0x29, 0x8e,0xc9,0xc8,0x44,
+ 0x75,0xc2,0x89,0x6a, 0xf4,0x8e,0x79,0x78, 0x99,0x58,0x3e,0x6b, 0x27,0xb9,0x71,0xdd,
+ 0xbe,0xe1,0x4f,0xb6, 0xf0,0x88,0xad,0x17, 0xc9,0x20,0xac,0x66, 0x7d,0xce,0x3a,0xb4,
+ 0x63,0xdf,0x4a,0x18, 0xe5,0x1a,0x31,0x82, 0x97,0x51,0x33,0x60, 0x62,0x53,0x7f,0x45,
+ 0xb1,0x64,0x77,0xe0, 0xbb,0x6b,0xae,0x84, 0xfe,0x81,0xa0,0x1c, 0xf9,0x08,0x2b,0x94,
+ 0x70,0x48,0x68,0x58, 0x8f,0x45,0xfd,0x19, 0x94,0xde,0x6c,0x87, 0x52,0x7b,0xf8,0xb7,
+ 0xab,0x73,0xd3,0x23, 0x72,0x4b,0x02,0xe2, 0xe3,0x1f,0x8f,0x57, 0x66,0x55,0xab,0x2a,
+ 0xb2,0xeb,0x28,0x07, 0x2f,0xb5,0xc2,0x03, 0x86,0xc5,0x7b,0x9a, 0xd3,0x37,0x08,0xa5,
+ 0x30,0x28,0x87,0xf2, 0x23,0xbf,0xa5,0xb2, 0x02,0x03,0x6a,0xba, 0xed,0x16,0x82,0x5c,
+ 0x8a,0xcf,0x1c,0x2b, 0xa7,0x79,0xb4,0x92, 0xf3,0x07,0xf2,0xf0, 0x4e,0x69,0xe2,0xa1,
+ 0x65,0xda,0xf4,0xcd, 0x06,0x05,0xbe,0xd5, 0xd1,0x34,0x62,0x1f, 0xc4,0xa6,0xfe,0x8a,
+ 0x34,0x2e,0x53,0x9d, 0xa2,0xf3,0x55,0xa0, 0x05,0x8a,0xe1,0x32, 0xa4,0xf6,0xeb,0x75,
+ 0x0b,0x83,0xec,0x39, 0x40,0x60,0xef,0xaa, 0x5e,0x71,0x9f,0x06, 0xbd,0x6e,0x10,0x51,
+ 0x3e,0x21,0x8a,0xf9, 0x96,0xdd,0x06,0x3d, 0xdd,0x3e,0x05,0xae, 0x4d,0xe6,0xbd,0x46,
+ 0x91,0x54,0x8d,0xb5, 0x71,0xc4,0x5d,0x05, 0x04,0x06,0xd4,0x6f, 0x60,0x50,0x15,0xff,
+ 0x19,0x98,0xfb,0x24, 0xd6,0xbd,0xe9,0x97, 0x89,0x40,0x43,0xcc, 0x67,0xd9,0x9e,0x77,
+ 0xb0,0xe8,0x42,0xbd, 0x07,0x89,0x8b,0x88, 0xe7,0x19,0x5b,0x38, 0x79,0xc8,0xee,0xdb,
+ 0xa1,0x7c,0x0a,0x47, 0x7c,0x42,0x0f,0xe9, 0xf8,0x84,0x1e,0xc9, 0x00,0x00,0x00,0x00,
+ 0x09,0x80,0x86,0x83, 0x32,0x2b,0xed,0x48, 0x1e,0x11,0x70,0xac, 0x6c,0x5a,0x72,0x4e,
+ 0xfd,0x0e,0xff,0xfb, 0x0f,0x85,0x38,0x56, 0x3d,0xae,0xd5,0x1e, 0x36,0x2d,0x39,0x27,
+ 0x0a,0x0f,0xd9,0x64, 0x68,0x5c,0xa6,0x21, 0x9b,0x5b,0x54,0xd1, 0x24,0x36,0x2e,0x3a,
+ 0x0c,0x0a,0x67,0xb1, 0x93,0x57,0xe7,0x0f, 0xb4,0xee,0x96,0xd2, 0x1b,0x9b,0x91,0x9e,
+ 0x80,0xc0,0xc5,0x4f, 0x61,0xdc,0x20,0xa2, 0x5a,0x77,0x4b,0x69, 0x1c,0x12,0x1a,0x16,
+ 0xe2,0x93,0xba,0x0a, 0xc0,0xa0,0x2a,0xe5, 0x3c,0x22,0xe0,0x43, 0x12,0x1b,0x17,0x1d,
+ 0x0e,0x09,0x0d,0x0b, 0xf2,0x8b,0xc7,0xad, 0x2d,0xb6,0xa8,0xb9, 0x14,0x1e,0xa9,0xc8,
+ 0x57,0xf1,0x19,0x85, 0xaf,0x75,0x07,0x4c, 0xee,0x99,0xdd,0xbb, 0xa3,0x7f,0x60,0xfd,
+ 0xf7,0x01,0x26,0x9f, 0x5c,0x72,0xf5,0xbc, 0x44,0x66,0x3b,0xc5, 0x5b,0xfb,0x7e,0x34,
+ 0x8b,0x43,0x29,0x76, 0xcb,0x23,0xc6,0xdc, 0xb6,0xed,0xfc,0x68, 0xb8,0xe4,0xf1,0x63,
+ 0xd7,0x31,0xdc,0xca, 0x42,0x63,0x85,0x10, 0x13,0x97,0x22,0x40, 0x84,0xc6,0x11,0x20,
+ 0x85,0x4a,0x24,0x7d, 0xd2,0xbb,0x3d,0xf8, 0xae,0xf9,0x32,0x11, 0xc7,0x29,0xa1,0x6d,
+ 0x1d,0x9e,0x2f,0x4b, 0xdc,0xb2,0x30,0xf3, 0x0d,0x86,0x52,0xec, 0x77,0xc1,0xe3,0xd0,
+ 0x2b,0xb3,0x16,0x6c, 0xa9,0x70,0xb9,0x99, 0x11,0x94,0x48,0xfa, 0x47,0xe9,0x64,0x22,
+ 0xa8,0xfc,0x8c,0xc4, 0xa0,0xf0,0x3f,0x1a, 0x56,0x7d,0x2c,0xd8, 0x22,0x33,0x90,0xef,
+ 0x87,0x49,0x4e,0xc7, 0xd9,0x38,0xd1,0xc1, 0x8c,0xca,0xa2,0xfe, 0x98,0xd4,0x0b,0x36,
+ 0xa6,0xf5,0x81,0xcf, 0xa5,0x7a,0xde,0x28, 0xda,0xb7,0x8e,0x26, 0x3f,0xad,0xbf,0xa4,
+ 0x2c,0x3a,0x9d,0xe4, 0x50,0x78,0x92,0x0d, 0x6a,0x5f,0xcc,0x9b, 0x54,0x7e,0x46,0x62,
+ 0xf6,0x8d,0x13,0xc2, 0x90,0xd8,0xb8,0xe8, 0x2e,0x39,0xf7,0x5e, 0x82,0xc3,0xaf,0xf5,
+ 0x9f,0x5d,0x80,0xbe, 0x69,0xd0,0x93,0x7c, 0x6f,0xd5,0x2d,0xa9, 0xcf,0x25,0x12,0xb3,
+ 0xc8,0xac,0x99,0x3b, 0x10,0x18,0x7d,0xa7, 0xe8,0x9c,0x63,0x6e, 0xdb,0x3b,0xbb,0x7b,
+ 0xcd,0x26,0x78,0x09, 0x6e,0x59,0x18,0xf4, 0xec,0x9a,0xb7,0x01, 0x83,0x4f,0x9a,0xa8,
+ 0xe6,0x95,0x6e,0x65, 0xaa,0xff,0xe6,0x7e, 0x21,0xbc,0xcf,0x08, 0xef,0x15,0xe8,0xe6,
+ 0xba,0xe7,0x9b,0xd9, 0x4a,0x6f,0x36,0xce, 0xea,0x9f,0x09,0xd4, 0x29,0xb0,0x7c,0xd6,
+ 0x31,0xa4,0xb2,0xaf, 0x2a,0x3f,0x23,0x31, 0xc6,0xa5,0x94,0x30, 0x35,0xa2,0x66,0xc0,
+ 0x74,0x4e,0xbc,0x37, 0xfc,0x82,0xca,0xa6, 0xe0,0x90,0xd0,0xb0, 0x33,0xa7,0xd8,0x15,
+ 0xf1,0x04,0x98,0x4a, 0x41,0xec,0xda,0xf7, 0x7f,0xcd,0x50,0x0e, 0x17,0x91,0xf6,0x2f,
+ 0x76,0x4d,0xd6,0x8d, 0x43,0xef,0xb0,0x4d, 0xcc,0xaa,0x4d,0x54, 0xe4,0x96,0x04,0xdf,
+ 0x9e,0xd1,0xb5,0xe3, 0x4c,0x6a,0x88,0x1b, 0xc1,0x2c,0x1f,0xb8, 0x46,0x65,0x51,0x7f,
+ 0x9d,0x5e,0xea,0x04, 0x01,0x8c,0x35,0x5d, 0xfa,0x87,0x74,0x73, 0xfb,0x0b,0x41,0x2e,
+ 0xb3,0x67,0x1d,0x5a, 0x92,0xdb,0xd2,0x52, 0xe9,0x10,0x56,0x33, 0x6d,0xd6,0x47,0x13,
+ 0x9a,0xd7,0x61,0x8c, 0x37,0xa1,0x0c,0x7a, 0x59,0xf8,0x14,0x8e, 0xeb,0x13,0x3c,0x89,
+ 0xce,0xa9,0x27,0xee, 0xb7,0x61,0xc9,0x35, 0xe1,0x1c,0xe5,0xed, 0x7a,0x47,0xb1,0x3c,
+ 0x9c,0xd2,0xdf,0x59, 0x55,0xf2,0x73,0x3f, 0x18,0x14,0xce,0x79, 0x73,0xc7,0x37,0xbf,
+ 0x53,0xf7,0xcd,0xea, 0x5f,0xfd,0xaa,0x5b, 0xdf,0x3d,0x6f,0x14, 0x78,0x44,0xdb,0x86,
+ 0xca,0xaf,0xf3,0x81, 0xb9,0x68,0xc4,0x3e, 0x38,0x24,0x34,0x2c, 0xc2,0xa3,0x40,0x5f,
+ 0x16,0x1d,0xc3,0x72, 0xbc,0xe2,0x25,0x0c, 0x28,0x3c,0x49,0x8b, 0xff,0x0d,0x95,0x41,
+ 0x39,0xa8,0x01,0x71, 0x08,0x0c,0xb3,0xde, 0xd8,0xb4,0xe4,0x9c, 0x64,0x56,0xc1,0x90,
+ 0x7b,0xcb,0x84,0x61, 0xd5,0x32,0xb6,0x70, 0x48,0x6c,0x5c,0x74, 0xd0,0xb8,0x57,0x42
+};
+
+static UINT8 T6[256][4]=
+{
+ 0x50,0x51,0xf4,0xa7, 0x53,0x7e,0x41,0x65, 0xc3,0x1a,0x17,0xa4, 0x96,0x3a,0x27,0x5e,
+ 0xcb,0x3b,0xab,0x6b, 0xf1,0x1f,0x9d,0x45, 0xab,0xac,0xfa,0x58, 0x93,0x4b,0xe3,0x03,
+ 0x55,0x20,0x30,0xfa, 0xf6,0xad,0x76,0x6d, 0x91,0x88,0xcc,0x76, 0x25,0xf5,0x02,0x4c,
+ 0xfc,0x4f,0xe5,0xd7, 0xd7,0xc5,0x2a,0xcb, 0x80,0x26,0x35,0x44, 0x8f,0xb5,0x62,0xa3,
+ 0x49,0xde,0xb1,0x5a, 0x67,0x25,0xba,0x1b, 0x98,0x45,0xea,0x0e, 0xe1,0x5d,0xfe,0xc0,
+ 0x02,0xc3,0x2f,0x75, 0x12,0x81,0x4c,0xf0, 0xa3,0x8d,0x46,0x97, 0xc6,0x6b,0xd3,0xf9,
+ 0xe7,0x03,0x8f,0x5f, 0x95,0x15,0x92,0x9c, 0xeb,0xbf,0x6d,0x7a, 0xda,0x95,0x52,0x59,
+ 0x2d,0xd4,0xbe,0x83, 0xd3,0x58,0x74,0x21, 0x29,0x49,0xe0,0x69, 0x44,0x8e,0xc9,0xc8,
+ 0x6a,0x75,0xc2,0x89, 0x78,0xf4,0x8e,0x79, 0x6b,0x99,0x58,0x3e, 0xdd,0x27,0xb9,0x71,
+ 0xb6,0xbe,0xe1,0x4f, 0x17,0xf0,0x88,0xad, 0x66,0xc9,0x20,0xac, 0xb4,0x7d,0xce,0x3a,
+ 0x18,0x63,0xdf,0x4a, 0x82,0xe5,0x1a,0x31, 0x60,0x97,0x51,0x33, 0x45,0x62,0x53,0x7f,
+ 0xe0,0xb1,0x64,0x77, 0x84,0xbb,0x6b,0xae, 0x1c,0xfe,0x81,0xa0, 0x94,0xf9,0x08,0x2b,
+ 0x58,0x70,0x48,0x68, 0x19,0x8f,0x45,0xfd, 0x87,0x94,0xde,0x6c, 0xb7,0x52,0x7b,0xf8,
+ 0x23,0xab,0x73,0xd3, 0xe2,0x72,0x4b,0x02, 0x57,0xe3,0x1f,0x8f, 0x2a,0x66,0x55,0xab,
+ 0x07,0xb2,0xeb,0x28, 0x03,0x2f,0xb5,0xc2, 0x9a,0x86,0xc5,0x7b, 0xa5,0xd3,0x37,0x08,
+ 0xf2,0x30,0x28,0x87, 0xb2,0x23,0xbf,0xa5, 0xba,0x02,0x03,0x6a, 0x5c,0xed,0x16,0x82,
+ 0x2b,0x8a,0xcf,0x1c, 0x92,0xa7,0x79,0xb4, 0xf0,0xf3,0x07,0xf2, 0xa1,0x4e,0x69,0xe2,
+ 0xcd,0x65,0xda,0xf4, 0xd5,0x06,0x05,0xbe, 0x1f,0xd1,0x34,0x62, 0x8a,0xc4,0xa6,0xfe,
+ 0x9d,0x34,0x2e,0x53, 0xa0,0xa2,0xf3,0x55, 0x32,0x05,0x8a,0xe1, 0x75,0xa4,0xf6,0xeb,
+ 0x39,0x0b,0x83,0xec, 0xaa,0x40,0x60,0xef, 0x06,0x5e,0x71,0x9f, 0x51,0xbd,0x6e,0x10,
+ 0xf9,0x3e,0x21,0x8a, 0x3d,0x96,0xdd,0x06, 0xae,0xdd,0x3e,0x05, 0x46,0x4d,0xe6,0xbd,
+ 0xb5,0x91,0x54,0x8d, 0x05,0x71,0xc4,0x5d, 0x6f,0x04,0x06,0xd4, 0xff,0x60,0x50,0x15,
+ 0x24,0x19,0x98,0xfb, 0x97,0xd6,0xbd,0xe9, 0xcc,0x89,0x40,0x43, 0x77,0x67,0xd9,0x9e,
+ 0xbd,0xb0,0xe8,0x42, 0x88,0x07,0x89,0x8b, 0x38,0xe7,0x19,0x5b, 0xdb,0x79,0xc8,0xee,
+ 0x47,0xa1,0x7c,0x0a, 0xe9,0x7c,0x42,0x0f, 0xc9,0xf8,0x84,0x1e, 0x00,0x00,0x00,0x00,
+ 0x83,0x09,0x80,0x86, 0x48,0x32,0x2b,0xed, 0xac,0x1e,0x11,0x70, 0x4e,0x6c,0x5a,0x72,
+ 0xfb,0xfd,0x0e,0xff, 0x56,0x0f,0x85,0x38, 0x1e,0x3d,0xae,0xd5, 0x27,0x36,0x2d,0x39,
+ 0x64,0x0a,0x0f,0xd9, 0x21,0x68,0x5c,0xa6, 0xd1,0x9b,0x5b,0x54, 0x3a,0x24,0x36,0x2e,
+ 0xb1,0x0c,0x0a,0x67, 0x0f,0x93,0x57,0xe7, 0xd2,0xb4,0xee,0x96, 0x9e,0x1b,0x9b,0x91,
+ 0x4f,0x80,0xc0,0xc5, 0xa2,0x61,0xdc,0x20, 0x69,0x5a,0x77,0x4b, 0x16,0x1c,0x12,0x1a,
+ 0x0a,0xe2,0x93,0xba, 0xe5,0xc0,0xa0,0x2a, 0x43,0x3c,0x22,0xe0, 0x1d,0x12,0x1b,0x17,
+ 0x0b,0x0e,0x09,0x0d, 0xad,0xf2,0x8b,0xc7, 0xb9,0x2d,0xb6,0xa8, 0xc8,0x14,0x1e,0xa9,
+ 0x85,0x57,0xf1,0x19, 0x4c,0xaf,0x75,0x07, 0xbb,0xee,0x99,0xdd, 0xfd,0xa3,0x7f,0x60,
+ 0x9f,0xf7,0x01,0x26, 0xbc,0x5c,0x72,0xf5, 0xc5,0x44,0x66,0x3b, 0x34,0x5b,0xfb,0x7e,
+ 0x76,0x8b,0x43,0x29, 0xdc,0xcb,0x23,0xc6, 0x68,0xb6,0xed,0xfc, 0x63,0xb8,0xe4,0xf1,
+ 0xca,0xd7,0x31,0xdc, 0x10,0x42,0x63,0x85, 0x40,0x13,0x97,0x22, 0x20,0x84,0xc6,0x11,
+ 0x7d,0x85,0x4a,0x24, 0xf8,0xd2,0xbb,0x3d, 0x11,0xae,0xf9,0x32, 0x6d,0xc7,0x29,0xa1,
+ 0x4b,0x1d,0x9e,0x2f, 0xf3,0xdc,0xb2,0x30, 0xec,0x0d,0x86,0x52, 0xd0,0x77,0xc1,0xe3,
+ 0x6c,0x2b,0xb3,0x16, 0x99,0xa9,0x70,0xb9, 0xfa,0x11,0x94,0x48, 0x22,0x47,0xe9,0x64,
+ 0xc4,0xa8,0xfc,0x8c, 0x1a,0xa0,0xf0,0x3f, 0xd8,0x56,0x7d,0x2c, 0xef,0x22,0x33,0x90,
+ 0xc7,0x87,0x49,0x4e, 0xc1,0xd9,0x38,0xd1, 0xfe,0x8c,0xca,0xa2, 0x36,0x98,0xd4,0x0b,
+ 0xcf,0xa6,0xf5,0x81, 0x28,0xa5,0x7a,0xde, 0x26,0xda,0xb7,0x8e, 0xa4,0x3f,0xad,0xbf,
+ 0xe4,0x2c,0x3a,0x9d, 0x0d,0x50,0x78,0x92, 0x9b,0x6a,0x5f,0xcc, 0x62,0x54,0x7e,0x46,
+ 0xc2,0xf6,0x8d,0x13, 0xe8,0x90,0xd8,0xb8, 0x5e,0x2e,0x39,0xf7, 0xf5,0x82,0xc3,0xaf,
+ 0xbe,0x9f,0x5d,0x80, 0x7c,0x69,0xd0,0x93, 0xa9,0x6f,0xd5,0x2d, 0xb3,0xcf,0x25,0x12,
+ 0x3b,0xc8,0xac,0x99, 0xa7,0x10,0x18,0x7d, 0x6e,0xe8,0x9c,0x63, 0x7b,0xdb,0x3b,0xbb,
+ 0x09,0xcd,0x26,0x78, 0xf4,0x6e,0x59,0x18, 0x01,0xec,0x9a,0xb7, 0xa8,0x83,0x4f,0x9a,
+ 0x65,0xe6,0x95,0x6e, 0x7e,0xaa,0xff,0xe6, 0x08,0x21,0xbc,0xcf, 0xe6,0xef,0x15,0xe8,
+ 0xd9,0xba,0xe7,0x9b, 0xce,0x4a,0x6f,0x36, 0xd4,0xea,0x9f,0x09, 0xd6,0x29,0xb0,0x7c,
+ 0xaf,0x31,0xa4,0xb2, 0x31,0x2a,0x3f,0x23, 0x30,0xc6,0xa5,0x94, 0xc0,0x35,0xa2,0x66,
+ 0x37,0x74,0x4e,0xbc, 0xa6,0xfc,0x82,0xca, 0xb0,0xe0,0x90,0xd0, 0x15,0x33,0xa7,0xd8,
+ 0x4a,0xf1,0x04,0x98, 0xf7,0x41,0xec,0xda, 0x0e,0x7f,0xcd,0x50, 0x2f,0x17,0x91,0xf6,
+ 0x8d,0x76,0x4d,0xd6, 0x4d,0x43,0xef,0xb0, 0x54,0xcc,0xaa,0x4d, 0xdf,0xe4,0x96,0x04,
+ 0xe3,0x9e,0xd1,0xb5, 0x1b,0x4c,0x6a,0x88, 0xb8,0xc1,0x2c,0x1f, 0x7f,0x46,0x65,0x51,
+ 0x04,0x9d,0x5e,0xea, 0x5d,0x01,0x8c,0x35, 0x73,0xfa,0x87,0x74, 0x2e,0xfb,0x0b,0x41,
+ 0x5a,0xb3,0x67,0x1d, 0x52,0x92,0xdb,0xd2, 0x33,0xe9,0x10,0x56, 0x13,0x6d,0xd6,0x47,
+ 0x8c,0x9a,0xd7,0x61, 0x7a,0x37,0xa1,0x0c, 0x8e,0x59,0xf8,0x14, 0x89,0xeb,0x13,0x3c,
+ 0xee,0xce,0xa9,0x27, 0x35,0xb7,0x61,0xc9, 0xed,0xe1,0x1c,0xe5, 0x3c,0x7a,0x47,0xb1,
+ 0x59,0x9c,0xd2,0xdf, 0x3f,0x55,0xf2,0x73, 0x79,0x18,0x14,0xce, 0xbf,0x73,0xc7,0x37,
+ 0xea,0x53,0xf7,0xcd, 0x5b,0x5f,0xfd,0xaa, 0x14,0xdf,0x3d,0x6f, 0x86,0x78,0x44,0xdb,
+ 0x81,0xca,0xaf,0xf3, 0x3e,0xb9,0x68,0xc4, 0x2c,0x38,0x24,0x34, 0x5f,0xc2,0xa3,0x40,
+ 0x72,0x16,0x1d,0xc3, 0x0c,0xbc,0xe2,0x25, 0x8b,0x28,0x3c,0x49, 0x41,0xff,0x0d,0x95,
+ 0x71,0x39,0xa8,0x01, 0xde,0x08,0x0c,0xb3, 0x9c,0xd8,0xb4,0xe4, 0x90,0x64,0x56,0xc1,
+ 0x61,0x7b,0xcb,0x84, 0x70,0xd5,0x32,0xb6, 0x74,0x48,0x6c,0x5c, 0x42,0xd0,0xb8,0x57
+};
+
+static UINT8 T7[256][4]=
+{
+ 0xa7,0x50,0x51,0xf4, 0x65,0x53,0x7e,0x41, 0xa4,0xc3,0x1a,0x17, 0x5e,0x96,0x3a,0x27,
+ 0x6b,0xcb,0x3b,0xab, 0x45,0xf1,0x1f,0x9d, 0x58,0xab,0xac,0xfa, 0x03,0x93,0x4b,0xe3,
+ 0xfa,0x55,0x20,0x30, 0x6d,0xf6,0xad,0x76, 0x76,0x91,0x88,0xcc, 0x4c,0x25,0xf5,0x02,
+ 0xd7,0xfc,0x4f,0xe5, 0xcb,0xd7,0xc5,0x2a, 0x44,0x80,0x26,0x35, 0xa3,0x8f,0xb5,0x62,
+ 0x5a,0x49,0xde,0xb1, 0x1b,0x67,0x25,0xba, 0x0e,0x98,0x45,0xea, 0xc0,0xe1,0x5d,0xfe,
+ 0x75,0x02,0xc3,0x2f, 0xf0,0x12,0x81,0x4c, 0x97,0xa3,0x8d,0x46, 0xf9,0xc6,0x6b,0xd3,
+ 0x5f,0xe7,0x03,0x8f, 0x9c,0x95,0x15,0x92, 0x7a,0xeb,0xbf,0x6d, 0x59,0xda,0x95,0x52,
+ 0x83,0x2d,0xd4,0xbe, 0x21,0xd3,0x58,0x74, 0x69,0x29,0x49,0xe0, 0xc8,0x44,0x8e,0xc9,
+ 0x89,0x6a,0x75,0xc2, 0x79,0x78,0xf4,0x8e, 0x3e,0x6b,0x99,0x58, 0x71,0xdd,0x27,0xb9,
+ 0x4f,0xb6,0xbe,0xe1, 0xad,0x17,0xf0,0x88, 0xac,0x66,0xc9,0x20, 0x3a,0xb4,0x7d,0xce,
+ 0x4a,0x18,0x63,0xdf, 0x31,0x82,0xe5,0x1a, 0x33,0x60,0x97,0x51, 0x7f,0x45,0x62,0x53,
+ 0x77,0xe0,0xb1,0x64, 0xae,0x84,0xbb,0x6b, 0xa0,0x1c,0xfe,0x81, 0x2b,0x94,0xf9,0x08,
+ 0x68,0x58,0x70,0x48, 0xfd,0x19,0x8f,0x45, 0x6c,0x87,0x94,0xde, 0xf8,0xb7,0x52,0x7b,
+ 0xd3,0x23,0xab,0x73, 0x02,0xe2,0x72,0x4b, 0x8f,0x57,0xe3,0x1f, 0xab,0x2a,0x66,0x55,
+ 0x28,0x07,0xb2,0xeb, 0xc2,0x03,0x2f,0xb5, 0x7b,0x9a,0x86,0xc5, 0x08,0xa5,0xd3,0x37,
+ 0x87,0xf2,0x30,0x28, 0xa5,0xb2,0x23,0xbf, 0x6a,0xba,0x02,0x03, 0x82,0x5c,0xed,0x16,
+ 0x1c,0x2b,0x8a,0xcf, 0xb4,0x92,0xa7,0x79, 0xf2,0xf0,0xf3,0x07, 0xe2,0xa1,0x4e,0x69,
+ 0xf4,0xcd,0x65,0xda, 0xbe,0xd5,0x06,0x05, 0x62,0x1f,0xd1,0x34, 0xfe,0x8a,0xc4,0xa6,
+ 0x53,0x9d,0x34,0x2e, 0x55,0xa0,0xa2,0xf3, 0xe1,0x32,0x05,0x8a, 0xeb,0x75,0xa4,0xf6,
+ 0xec,0x39,0x0b,0x83, 0xef,0xaa,0x40,0x60, 0x9f,0x06,0x5e,0x71, 0x10,0x51,0xbd,0x6e,
+ 0x8a,0xf9,0x3e,0x21, 0x06,0x3d,0x96,0xdd, 0x05,0xae,0xdd,0x3e, 0xbd,0x46,0x4d,0xe6,
+ 0x8d,0xb5,0x91,0x54, 0x5d,0x05,0x71,0xc4, 0xd4,0x6f,0x04,0x06, 0x15,0xff,0x60,0x50,
+ 0xfb,0x24,0x19,0x98, 0xe9,0x97,0xd6,0xbd, 0x43,0xcc,0x89,0x40, 0x9e,0x77,0x67,0xd9,
+ 0x42,0xbd,0xb0,0xe8, 0x8b,0x88,0x07,0x89, 0x5b,0x38,0xe7,0x19, 0xee,0xdb,0x79,0xc8,
+ 0x0a,0x47,0xa1,0x7c, 0x0f,0xe9,0x7c,0x42, 0x1e,0xc9,0xf8,0x84, 0x00,0x00,0x00,0x00,
+ 0x86,0x83,0x09,0x80, 0xed,0x48,0x32,0x2b, 0x70,0xac,0x1e,0x11, 0x72,0x4e,0x6c,0x5a,
+ 0xff,0xfb,0xfd,0x0e, 0x38,0x56,0x0f,0x85, 0xd5,0x1e,0x3d,0xae, 0x39,0x27,0x36,0x2d,
+ 0xd9,0x64,0x0a,0x0f, 0xa6,0x21,0x68,0x5c, 0x54,0xd1,0x9b,0x5b, 0x2e,0x3a,0x24,0x36,
+ 0x67,0xb1,0x0c,0x0a, 0xe7,0x0f,0x93,0x57, 0x96,0xd2,0xb4,0xee, 0x91,0x9e,0x1b,0x9b,
+ 0xc5,0x4f,0x80,0xc0, 0x20,0xa2,0x61,0xdc, 0x4b,0x69,0x5a,0x77, 0x1a,0x16,0x1c,0x12,
+ 0xba,0x0a,0xe2,0x93, 0x2a,0xe5,0xc0,0xa0, 0xe0,0x43,0x3c,0x22, 0x17,0x1d,0x12,0x1b,
+ 0x0d,0x0b,0x0e,0x09, 0xc7,0xad,0xf2,0x8b, 0xa8,0xb9,0x2d,0xb6, 0xa9,0xc8,0x14,0x1e,
+ 0x19,0x85,0x57,0xf1, 0x07,0x4c,0xaf,0x75, 0xdd,0xbb,0xee,0x99, 0x60,0xfd,0xa3,0x7f,
+ 0x26,0x9f,0xf7,0x01, 0xf5,0xbc,0x5c,0x72, 0x3b,0xc5,0x44,0x66, 0x7e,0x34,0x5b,0xfb,
+ 0x29,0x76,0x8b,0x43, 0xc6,0xdc,0xcb,0x23, 0xfc,0x68,0xb6,0xed, 0xf1,0x63,0xb8,0xe4,
+ 0xdc,0xca,0xd7,0x31, 0x85,0x10,0x42,0x63, 0x22,0x40,0x13,0x97, 0x11,0x20,0x84,0xc6,
+ 0x24,0x7d,0x85,0x4a, 0x3d,0xf8,0xd2,0xbb, 0x32,0x11,0xae,0xf9, 0xa1,0x6d,0xc7,0x29,
+ 0x2f,0x4b,0x1d,0x9e, 0x30,0xf3,0xdc,0xb2, 0x52,0xec,0x0d,0x86, 0xe3,0xd0,0x77,0xc1,
+ 0x16,0x6c,0x2b,0xb3, 0xb9,0x99,0xa9,0x70, 0x48,0xfa,0x11,0x94, 0x64,0x22,0x47,0xe9,
+ 0x8c,0xc4,0xa8,0xfc, 0x3f,0x1a,0xa0,0xf0, 0x2c,0xd8,0x56,0x7d, 0x90,0xef,0x22,0x33,
+ 0x4e,0xc7,0x87,0x49, 0xd1,0xc1,0xd9,0x38, 0xa2,0xfe,0x8c,0xca, 0x0b,0x36,0x98,0xd4,
+ 0x81,0xcf,0xa6,0xf5, 0xde,0x28,0xa5,0x7a, 0x8e,0x26,0xda,0xb7, 0xbf,0xa4,0x3f,0xad,
+ 0x9d,0xe4,0x2c,0x3a, 0x92,0x0d,0x50,0x78, 0xcc,0x9b,0x6a,0x5f, 0x46,0x62,0x54,0x7e,
+ 0x13,0xc2,0xf6,0x8d, 0xb8,0xe8,0x90,0xd8, 0xf7,0x5e,0x2e,0x39, 0xaf,0xf5,0x82,0xc3,
+ 0x80,0xbe,0x9f,0x5d, 0x93,0x7c,0x69,0xd0, 0x2d,0xa9,0x6f,0xd5, 0x12,0xb3,0xcf,0x25,
+ 0x99,0x3b,0xc8,0xac, 0x7d,0xa7,0x10,0x18, 0x63,0x6e,0xe8,0x9c, 0xbb,0x7b,0xdb,0x3b,
+ 0x78,0x09,0xcd,0x26, 0x18,0xf4,0x6e,0x59, 0xb7,0x01,0xec,0x9a, 0x9a,0xa8,0x83,0x4f,
+ 0x6e,0x65,0xe6,0x95, 0xe6,0x7e,0xaa,0xff, 0xcf,0x08,0x21,0xbc, 0xe8,0xe6,0xef,0x15,
+ 0x9b,0xd9,0xba,0xe7, 0x36,0xce,0x4a,0x6f, 0x09,0xd4,0xea,0x9f, 0x7c,0xd6,0x29,0xb0,
+ 0xb2,0xaf,0x31,0xa4, 0x23,0x31,0x2a,0x3f, 0x94,0x30,0xc6,0xa5, 0x66,0xc0,0x35,0xa2,
+ 0xbc,0x37,0x74,0x4e, 0xca,0xa6,0xfc,0x82, 0xd0,0xb0,0xe0,0x90, 0xd8,0x15,0x33,0xa7,
+ 0x98,0x4a,0xf1,0x04, 0xda,0xf7,0x41,0xec, 0x50,0x0e,0x7f,0xcd, 0xf6,0x2f,0x17,0x91,
+ 0xd6,0x8d,0x76,0x4d, 0xb0,0x4d,0x43,0xef, 0x4d,0x54,0xcc,0xaa, 0x04,0xdf,0xe4,0x96,
+ 0xb5,0xe3,0x9e,0xd1, 0x88,0x1b,0x4c,0x6a, 0x1f,0xb8,0xc1,0x2c, 0x51,0x7f,0x46,0x65,
+ 0xea,0x04,0x9d,0x5e, 0x35,0x5d,0x01,0x8c, 0x74,0x73,0xfa,0x87, 0x41,0x2e,0xfb,0x0b,
+ 0x1d,0x5a,0xb3,0x67, 0xd2,0x52,0x92,0xdb, 0x56,0x33,0xe9,0x10, 0x47,0x13,0x6d,0xd6,
+ 0x61,0x8c,0x9a,0xd7, 0x0c,0x7a,0x37,0xa1, 0x14,0x8e,0x59,0xf8, 0x3c,0x89,0xeb,0x13,
+ 0x27,0xee,0xce,0xa9, 0xc9,0x35,0xb7,0x61, 0xe5,0xed,0xe1,0x1c, 0xb1,0x3c,0x7a,0x47,
+ 0xdf,0x59,0x9c,0xd2, 0x73,0x3f,0x55,0xf2, 0xce,0x79,0x18,0x14, 0x37,0xbf,0x73,0xc7,
+ 0xcd,0xea,0x53,0xf7, 0xaa,0x5b,0x5f,0xfd, 0x6f,0x14,0xdf,0x3d, 0xdb,0x86,0x78,0x44,
+ 0xf3,0x81,0xca,0xaf, 0xc4,0x3e,0xb9,0x68, 0x34,0x2c,0x38,0x24, 0x40,0x5f,0xc2,0xa3,
+ 0xc3,0x72,0x16,0x1d, 0x25,0x0c,0xbc,0xe2, 0x49,0x8b,0x28,0x3c, 0x95,0x41,0xff,0x0d,
+ 0x01,0x71,0x39,0xa8, 0xb3,0xde,0x08,0x0c, 0xe4,0x9c,0xd8,0xb4, 0xc1,0x90,0x64,0x56,
+ 0x84,0x61,0x7b,0xcb, 0xb6,0x70,0xd5,0x32, 0x5c,0x74,0x48,0x6c, 0x57,0x42,0xd0,0xb8
+};
+
+static UINT8 T8[256][4]=
+{
+ 0xf4,0xa7,0x50,0x51, 0x41,0x65,0x53,0x7e, 0x17,0xa4,0xc3,0x1a, 0x27,0x5e,0x96,0x3a,
+ 0xab,0x6b,0xcb,0x3b, 0x9d,0x45,0xf1,0x1f, 0xfa,0x58,0xab,0xac, 0xe3,0x03,0x93,0x4b,
+ 0x30,0xfa,0x55,0x20, 0x76,0x6d,0xf6,0xad, 0xcc,0x76,0x91,0x88, 0x02,0x4c,0x25,0xf5,
+ 0xe5,0xd7,0xfc,0x4f, 0x2a,0xcb,0xd7,0xc5, 0x35,0x44,0x80,0x26, 0x62,0xa3,0x8f,0xb5,
+ 0xb1,0x5a,0x49,0xde, 0xba,0x1b,0x67,0x25, 0xea,0x0e,0x98,0x45, 0xfe,0xc0,0xe1,0x5d,
+ 0x2f,0x75,0x02,0xc3, 0x4c,0xf0,0x12,0x81, 0x46,0x97,0xa3,0x8d, 0xd3,0xf9,0xc6,0x6b,
+ 0x8f,0x5f,0xe7,0x03, 0x92,0x9c,0x95,0x15, 0x6d,0x7a,0xeb,0xbf, 0x52,0x59,0xda,0x95,
+ 0xbe,0x83,0x2d,0xd4, 0x74,0x21,0xd3,0x58, 0xe0,0x69,0x29,0x49, 0xc9,0xc8,0x44,0x8e,
+ 0xc2,0x89,0x6a,0x75, 0x8e,0x79,0x78,0xf4, 0x58,0x3e,0x6b,0x99, 0xb9,0x71,0xdd,0x27,
+ 0xe1,0x4f,0xb6,0xbe, 0x88,0xad,0x17,0xf0, 0x20,0xac,0x66,0xc9, 0xce,0x3a,0xb4,0x7d,
+ 0xdf,0x4a,0x18,0x63, 0x1a,0x31,0x82,0xe5, 0x51,0x33,0x60,0x97, 0x53,0x7f,0x45,0x62,
+ 0x64,0x77,0xe0,0xb1, 0x6b,0xae,0x84,0xbb, 0x81,0xa0,0x1c,0xfe, 0x08,0x2b,0x94,0xf9,
+ 0x48,0x68,0x58,0x70, 0x45,0xfd,0x19,0x8f, 0xde,0x6c,0x87,0x94, 0x7b,0xf8,0xb7,0x52,
+ 0x73,0xd3,0x23,0xab, 0x4b,0x02,0xe2,0x72, 0x1f,0x8f,0x57,0xe3, 0x55,0xab,0x2a,0x66,
+ 0xeb,0x28,0x07,0xb2, 0xb5,0xc2,0x03,0x2f, 0xc5,0x7b,0x9a,0x86, 0x37,0x08,0xa5,0xd3,
+ 0x28,0x87,0xf2,0x30, 0xbf,0xa5,0xb2,0x23, 0x03,0x6a,0xba,0x02, 0x16,0x82,0x5c,0xed,
+ 0xcf,0x1c,0x2b,0x8a, 0x79,0xb4,0x92,0xa7, 0x07,0xf2,0xf0,0xf3, 0x69,0xe2,0xa1,0x4e,
+ 0xda,0xf4,0xcd,0x65, 0x05,0xbe,0xd5,0x06, 0x34,0x62,0x1f,0xd1, 0xa6,0xfe,0x8a,0xc4,
+ 0x2e,0x53,0x9d,0x34, 0xf3,0x55,0xa0,0xa2, 0x8a,0xe1,0x32,0x05, 0xf6,0xeb,0x75,0xa4,
+ 0x83,0xec,0x39,0x0b, 0x60,0xef,0xaa,0x40, 0x71,0x9f,0x06,0x5e, 0x6e,0x10,0x51,0xbd,
+ 0x21,0x8a,0xf9,0x3e, 0xdd,0x06,0x3d,0x96, 0x3e,0x05,0xae,0xdd, 0xe6,0xbd,0x46,0x4d,
+ 0x54,0x8d,0xb5,0x91, 0xc4,0x5d,0x05,0x71, 0x06,0xd4,0x6f,0x04, 0x50,0x15,0xff,0x60,
+ 0x98,0xfb,0x24,0x19, 0xbd,0xe9,0x97,0xd6, 0x40,0x43,0xcc,0x89, 0xd9,0x9e,0x77,0x67,
+ 0xe8,0x42,0xbd,0xb0, 0x89,0x8b,0x88,0x07, 0x19,0x5b,0x38,0xe7, 0xc8,0xee,0xdb,0x79,
+ 0x7c,0x0a,0x47,0xa1, 0x42,0x0f,0xe9,0x7c, 0x84,0x1e,0xc9,0xf8, 0x00,0x00,0x00,0x00,
+ 0x80,0x86,0x83,0x09, 0x2b,0xed,0x48,0x32, 0x11,0x70,0xac,0x1e, 0x5a,0x72,0x4e,0x6c,
+ 0x0e,0xff,0xfb,0xfd, 0x85,0x38,0x56,0x0f, 0xae,0xd5,0x1e,0x3d, 0x2d,0x39,0x27,0x36,
+ 0x0f,0xd9,0x64,0x0a, 0x5c,0xa6,0x21,0x68, 0x5b,0x54,0xd1,0x9b, 0x36,0x2e,0x3a,0x24,
+ 0x0a,0x67,0xb1,0x0c, 0x57,0xe7,0x0f,0x93, 0xee,0x96,0xd2,0xb4, 0x9b,0x91,0x9e,0x1b,
+ 0xc0,0xc5,0x4f,0x80, 0xdc,0x20,0xa2,0x61, 0x77,0x4b,0x69,0x5a, 0x12,0x1a,0x16,0x1c,
+ 0x93,0xba,0x0a,0xe2, 0xa0,0x2a,0xe5,0xc0, 0x22,0xe0,0x43,0x3c, 0x1b,0x17,0x1d,0x12,
+ 0x09,0x0d,0x0b,0x0e, 0x8b,0xc7,0xad,0xf2, 0xb6,0xa8,0xb9,0x2d, 0x1e,0xa9,0xc8,0x14,
+ 0xf1,0x19,0x85,0x57, 0x75,0x07,0x4c,0xaf, 0x99,0xdd,0xbb,0xee, 0x7f,0x60,0xfd,0xa3,
+ 0x01,0x26,0x9f,0xf7, 0x72,0xf5,0xbc,0x5c, 0x66,0x3b,0xc5,0x44, 0xfb,0x7e,0x34,0x5b,
+ 0x43,0x29,0x76,0x8b, 0x23,0xc6,0xdc,0xcb, 0xed,0xfc,0x68,0xb6, 0xe4,0xf1,0x63,0xb8,
+ 0x31,0xdc,0xca,0xd7, 0x63,0x85,0x10,0x42, 0x97,0x22,0x40,0x13, 0xc6,0x11,0x20,0x84,
+ 0x4a,0x24,0x7d,0x85, 0xbb,0x3d,0xf8,0xd2, 0xf9,0x32,0x11,0xae, 0x29,0xa1,0x6d,0xc7,
+ 0x9e,0x2f,0x4b,0x1d, 0xb2,0x30,0xf3,0xdc, 0x86,0x52,0xec,0x0d, 0xc1,0xe3,0xd0,0x77,
+ 0xb3,0x16,0x6c,0x2b, 0x70,0xb9,0x99,0xa9, 0x94,0x48,0xfa,0x11, 0xe9,0x64,0x22,0x47,
+ 0xfc,0x8c,0xc4,0xa8, 0xf0,0x3f,0x1a,0xa0, 0x7d,0x2c,0xd8,0x56, 0x33,0x90,0xef,0x22,
+ 0x49,0x4e,0xc7,0x87, 0x38,0xd1,0xc1,0xd9, 0xca,0xa2,0xfe,0x8c, 0xd4,0x0b,0x36,0x98,
+ 0xf5,0x81,0xcf,0xa6, 0x7a,0xde,0x28,0xa5, 0xb7,0x8e,0x26,0xda, 0xad,0xbf,0xa4,0x3f,
+ 0x3a,0x9d,0xe4,0x2c, 0x78,0x92,0x0d,0x50, 0x5f,0xcc,0x9b,0x6a, 0x7e,0x46,0x62,0x54,
+ 0x8d,0x13,0xc2,0xf6, 0xd8,0xb8,0xe8,0x90, 0x39,0xf7,0x5e,0x2e, 0xc3,0xaf,0xf5,0x82,
+ 0x5d,0x80,0xbe,0x9f, 0xd0,0x93,0x7c,0x69, 0xd5,0x2d,0xa9,0x6f, 0x25,0x12,0xb3,0xcf,
+ 0xac,0x99,0x3b,0xc8, 0x18,0x7d,0xa7,0x10, 0x9c,0x63,0x6e,0xe8, 0x3b,0xbb,0x7b,0xdb,
+ 0x26,0x78,0x09,0xcd, 0x59,0x18,0xf4,0x6e, 0x9a,0xb7,0x01,0xec, 0x4f,0x9a,0xa8,0x83,
+ 0x95,0x6e,0x65,0xe6, 0xff,0xe6,0x7e,0xaa, 0xbc,0xcf,0x08,0x21, 0x15,0xe8,0xe6,0xef,
+ 0xe7,0x9b,0xd9,0xba, 0x6f,0x36,0xce,0x4a, 0x9f,0x09,0xd4,0xea, 0xb0,0x7c,0xd6,0x29,
+ 0xa4,0xb2,0xaf,0x31, 0x3f,0x23,0x31,0x2a, 0xa5,0x94,0x30,0xc6, 0xa2,0x66,0xc0,0x35,
+ 0x4e,0xbc,0x37,0x74, 0x82,0xca,0xa6,0xfc, 0x90,0xd0,0xb0,0xe0, 0xa7,0xd8,0x15,0x33,
+ 0x04,0x98,0x4a,0xf1, 0xec,0xda,0xf7,0x41, 0xcd,0x50,0x0e,0x7f, 0x91,0xf6,0x2f,0x17,
+ 0x4d,0xd6,0x8d,0x76, 0xef,0xb0,0x4d,0x43, 0xaa,0x4d,0x54,0xcc, 0x96,0x04,0xdf,0xe4,
+ 0xd1,0xb5,0xe3,0x9e, 0x6a,0x88,0x1b,0x4c, 0x2c,0x1f,0xb8,0xc1, 0x65,0x51,0x7f,0x46,
+ 0x5e,0xea,0x04,0x9d, 0x8c,0x35,0x5d,0x01, 0x87,0x74,0x73,0xfa, 0x0b,0x41,0x2e,0xfb,
+ 0x67,0x1d,0x5a,0xb3, 0xdb,0xd2,0x52,0x92, 0x10,0x56,0x33,0xe9, 0xd6,0x47,0x13,0x6d,
+ 0xd7,0x61,0x8c,0x9a, 0xa1,0x0c,0x7a,0x37, 0xf8,0x14,0x8e,0x59, 0x13,0x3c,0x89,0xeb,
+ 0xa9,0x27,0xee,0xce, 0x61,0xc9,0x35,0xb7, 0x1c,0xe5,0xed,0xe1, 0x47,0xb1,0x3c,0x7a,
+ 0xd2,0xdf,0x59,0x9c, 0xf2,0x73,0x3f,0x55, 0x14,0xce,0x79,0x18, 0xc7,0x37,0xbf,0x73,
+ 0xf7,0xcd,0xea,0x53, 0xfd,0xaa,0x5b,0x5f, 0x3d,0x6f,0x14,0xdf, 0x44,0xdb,0x86,0x78,
+ 0xaf,0xf3,0x81,0xca, 0x68,0xc4,0x3e,0xb9, 0x24,0x34,0x2c,0x38, 0xa3,0x40,0x5f,0xc2,
+ 0x1d,0xc3,0x72,0x16, 0xe2,0x25,0x0c,0xbc, 0x3c,0x49,0x8b,0x28, 0x0d,0x95,0x41,0xff,
+ 0xa8,0x01,0x71,0x39, 0x0c,0xb3,0xde,0x08, 0xb4,0xe4,0x9c,0xd8, 0x56,0xc1,0x90,0x64,
+ 0xcb,0x84,0x61,0x7b, 0x32,0xb6,0x70,0xd5, 0x6c,0x5c,0x74,0x48, 0xb8,0x57,0x42,0xd0
+};
+
+static UINT8 S5[256]=
+{
+ 0x52,0x09,0x6a,0xd5,
+ 0x30,0x36,0xa5,0x38,
+ 0xbf,0x40,0xa3,0x9e,
+ 0x81,0xf3,0xd7,0xfb,
+ 0x7c,0xe3,0x39,0x82,
+ 0x9b,0x2f,0xff,0x87,
+ 0x34,0x8e,0x43,0x44,
+ 0xc4,0xde,0xe9,0xcb,
+ 0x54,0x7b,0x94,0x32,
+ 0xa6,0xc2,0x23,0x3d,
+ 0xee,0x4c,0x95,0x0b,
+ 0x42,0xfa,0xc3,0x4e,
+ 0x08,0x2e,0xa1,0x66,
+ 0x28,0xd9,0x24,0xb2,
+ 0x76,0x5b,0xa2,0x49,
+ 0x6d,0x8b,0xd1,0x25,
+ 0x72,0xf8,0xf6,0x64,
+ 0x86,0x68,0x98,0x16,
+ 0xd4,0xa4,0x5c,0xcc,
+ 0x5d,0x65,0xb6,0x92,
+ 0x6c,0x70,0x48,0x50,
+ 0xfd,0xed,0xb9,0xda,
+ 0x5e,0x15,0x46,0x57,
+ 0xa7,0x8d,0x9d,0x84,
+ 0x90,0xd8,0xab,0x00,
+ 0x8c,0xbc,0xd3,0x0a,
+ 0xf7,0xe4,0x58,0x05,
+ 0xb8,0xb3,0x45,0x06,
+ 0xd0,0x2c,0x1e,0x8f,
+ 0xca,0x3f,0x0f,0x02,
+ 0xc1,0xaf,0xbd,0x03,
+ 0x01,0x13,0x8a,0x6b,
+ 0x3a,0x91,0x11,0x41,
+ 0x4f,0x67,0xdc,0xea,
+ 0x97,0xf2,0xcf,0xce,
+ 0xf0,0xb4,0xe6,0x73,
+ 0x96,0xac,0x74,0x22,
+ 0xe7,0xad,0x35,0x85,
+ 0xe2,0xf9,0x37,0xe8,
+ 0x1c,0x75,0xdf,0x6e,
+ 0x47,0xf1,0x1a,0x71,
+ 0x1d,0x29,0xc5,0x89,
+ 0x6f,0xb7,0x62,0x0e,
+ 0xaa,0x18,0xbe,0x1b,
+ 0xfc,0x56,0x3e,0x4b,
+ 0xc6,0xd2,0x79,0x20,
+ 0x9a,0xdb,0xc0,0xfe,
+ 0x78,0xcd,0x5a,0xf4,
+ 0x1f,0xdd,0xa8,0x33,
+ 0x88,0x07,0xc7,0x31,
+ 0xb1,0x12,0x10,0x59,
+ 0x27,0x80,0xec,0x5f,
+ 0x60,0x51,0x7f,0xa9,
+ 0x19,0xb5,0x4a,0x0d,
+ 0x2d,0xe5,0x7a,0x9f,
+ 0x93,0xc9,0x9c,0xef,
+ 0xa0,0xe0,0x3b,0x4d,
+ 0xae,0x2a,0xf5,0xb0,
+ 0xc8,0xeb,0xbb,0x3c,
+ 0x83,0x53,0x99,0x61,
+ 0x17,0x2b,0x04,0x7e,
+ 0xba,0x77,0xd6,0x26,
+ 0xe1,0x69,0x14,0x63,
+ 0x55,0x21,0x0c,0x7d
+};
+
+static UINT8 U1[256][4]=
+{
+ 0x00,0x00,0x00,0x00, 0x0e,0x09,0x0d,0x0b, 0x1c,0x12,0x1a,0x16, 0x12,0x1b,0x17,0x1d,
+ 0x38,0x24,0x34,0x2c, 0x36,0x2d,0x39,0x27, 0x24,0x36,0x2e,0x3a, 0x2a,0x3f,0x23,0x31,
+ 0x70,0x48,0x68,0x58, 0x7e,0x41,0x65,0x53, 0x6c,0x5a,0x72,0x4e, 0x62,0x53,0x7f,0x45,
+ 0x48,0x6c,0x5c,0x74, 0x46,0x65,0x51,0x7f, 0x54,0x7e,0x46,0x62, 0x5a,0x77,0x4b,0x69,
+ 0xe0,0x90,0xd0,0xb0, 0xee,0x99,0xdd,0xbb, 0xfc,0x82,0xca,0xa6, 0xf2,0x8b,0xc7,0xad,
+ 0xd8,0xb4,0xe4,0x9c, 0xd6,0xbd,0xe9,0x97, 0xc4,0xa6,0xfe,0x8a, 0xca,0xaf,0xf3,0x81,
+ 0x90,0xd8,0xb8,0xe8, 0x9e,0xd1,0xb5,0xe3, 0x8c,0xca,0xa2,0xfe, 0x82,0xc3,0xaf,0xf5,
+ 0xa8,0xfc,0x8c,0xc4, 0xa6,0xf5,0x81,0xcf, 0xb4,0xee,0x96,0xd2, 0xba,0xe7,0x9b,0xd9,
+ 0xdb,0x3b,0xbb,0x7b, 0xd5,0x32,0xb6,0x70, 0xc7,0x29,0xa1,0x6d, 0xc9,0x20,0xac,0x66,
+ 0xe3,0x1f,0x8f,0x57, 0xed,0x16,0x82,0x5c, 0xff,0x0d,0x95,0x41, 0xf1,0x04,0x98,0x4a,
+ 0xab,0x73,0xd3,0x23, 0xa5,0x7a,0xde,0x28, 0xb7,0x61,0xc9,0x35, 0xb9,0x68,0xc4,0x3e,
+ 0x93,0x57,0xe7,0x0f, 0x9d,0x5e,0xea,0x04, 0x8f,0x45,0xfd,0x19, 0x81,0x4c,0xf0,0x12,
+ 0x3b,0xab,0x6b,0xcb, 0x35,0xa2,0x66,0xc0, 0x27,0xb9,0x71,0xdd, 0x29,0xb0,0x7c,0xd6,
+ 0x03,0x8f,0x5f,0xe7, 0x0d,0x86,0x52,0xec, 0x1f,0x9d,0x45,0xf1, 0x11,0x94,0x48,0xfa,
+ 0x4b,0xe3,0x03,0x93, 0x45,0xea,0x0e,0x98, 0x57,0xf1,0x19,0x85, 0x59,0xf8,0x14,0x8e,
+ 0x73,0xc7,0x37,0xbf, 0x7d,0xce,0x3a,0xb4, 0x6f,0xd5,0x2d,0xa9, 0x61,0xdc,0x20,0xa2,
+ 0xad,0x76,0x6d,0xf6, 0xa3,0x7f,0x60,0xfd, 0xb1,0x64,0x77,0xe0, 0xbf,0x6d,0x7a,0xeb,
+ 0x95,0x52,0x59,0xda, 0x9b,0x5b,0x54,0xd1, 0x89,0x40,0x43,0xcc, 0x87,0x49,0x4e,0xc7,
+ 0xdd,0x3e,0x05,0xae, 0xd3,0x37,0x08,0xa5, 0xc1,0x2c,0x1f,0xb8, 0xcf,0x25,0x12,0xb3,
+ 0xe5,0x1a,0x31,0x82, 0xeb,0x13,0x3c,0x89, 0xf9,0x08,0x2b,0x94, 0xf7,0x01,0x26,0x9f,
+ 0x4d,0xe6,0xbd,0x46, 0x43,0xef,0xb0,0x4d, 0x51,0xf4,0xa7,0x50, 0x5f,0xfd,0xaa,0x5b,
+ 0x75,0xc2,0x89,0x6a, 0x7b,0xcb,0x84,0x61, 0x69,0xd0,0x93,0x7c, 0x67,0xd9,0x9e,0x77,
+ 0x3d,0xae,0xd5,0x1e, 0x33,0xa7,0xd8,0x15, 0x21,0xbc,0xcf,0x08, 0x2f,0xb5,0xc2,0x03,
+ 0x05,0x8a,0xe1,0x32, 0x0b,0x83,0xec,0x39, 0x19,0x98,0xfb,0x24, 0x17,0x91,0xf6,0x2f,
+ 0x76,0x4d,0xd6,0x8d, 0x78,0x44,0xdb,0x86, 0x6a,0x5f,0xcc,0x9b, 0x64,0x56,0xc1,0x90,
+ 0x4e,0x69,0xe2,0xa1, 0x40,0x60,0xef,0xaa, 0x52,0x7b,0xf8,0xb7, 0x5c,0x72,0xf5,0xbc,
+ 0x06,0x05,0xbe,0xd5, 0x08,0x0c,0xb3,0xde, 0x1a,0x17,0xa4,0xc3, 0x14,0x1e,0xa9,0xc8,
+ 0x3e,0x21,0x8a,0xf9, 0x30,0x28,0x87,0xf2, 0x22,0x33,0x90,0xef, 0x2c,0x3a,0x9d,0xe4,
+ 0x96,0xdd,0x06,0x3d, 0x98,0xd4,0x0b,0x36, 0x8a,0xcf,0x1c,0x2b, 0x84,0xc6,0x11,0x20,
+ 0xae,0xf9,0x32,0x11, 0xa0,0xf0,0x3f,0x1a, 0xb2,0xeb,0x28,0x07, 0xbc,0xe2,0x25,0x0c,
+ 0xe6,0x95,0x6e,0x65, 0xe8,0x9c,0x63,0x6e, 0xfa,0x87,0x74,0x73, 0xf4,0x8e,0x79,0x78,
+ 0xde,0xb1,0x5a,0x49, 0xd0,0xb8,0x57,0x42, 0xc2,0xa3,0x40,0x5f, 0xcc,0xaa,0x4d,0x54,
+ 0x41,0xec,0xda,0xf7, 0x4f,0xe5,0xd7,0xfc, 0x5d,0xfe,0xc0,0xe1, 0x53,0xf7,0xcd,0xea,
+ 0x79,0xc8,0xee,0xdb, 0x77,0xc1,0xe3,0xd0, 0x65,0xda,0xf4,0xcd, 0x6b,0xd3,0xf9,0xc6,
+ 0x31,0xa4,0xb2,0xaf, 0x3f,0xad,0xbf,0xa4, 0x2d,0xb6,0xa8,0xb9, 0x23,0xbf,0xa5,0xb2,
+ 0x09,0x80,0x86,0x83, 0x07,0x89,0x8b,0x88, 0x15,0x92,0x9c,0x95, 0x1b,0x9b,0x91,0x9e,
+ 0xa1,0x7c,0x0a,0x47, 0xaf,0x75,0x07,0x4c, 0xbd,0x6e,0x10,0x51, 0xb3,0x67,0x1d,0x5a,
+ 0x99,0x58,0x3e,0x6b, 0x97,0x51,0x33,0x60, 0x85,0x4a,0x24,0x7d, 0x8b,0x43,0x29,0x76,
+ 0xd1,0x34,0x62,0x1f, 0xdf,0x3d,0x6f,0x14, 0xcd,0x26,0x78,0x09, 0xc3,0x2f,0x75,0x02,
+ 0xe9,0x10,0x56,0x33, 0xe7,0x19,0x5b,0x38, 0xf5,0x02,0x4c,0x25, 0xfb,0x0b,0x41,0x2e,
+ 0x9a,0xd7,0x61,0x8c, 0x94,0xde,0x6c,0x87, 0x86,0xc5,0x7b,0x9a, 0x88,0xcc,0x76,0x91,
+ 0xa2,0xf3,0x55,0xa0, 0xac,0xfa,0x58,0xab, 0xbe,0xe1,0x4f,0xb6, 0xb0,0xe8,0x42,0xbd,
+ 0xea,0x9f,0x09,0xd4, 0xe4,0x96,0x04,0xdf, 0xf6,0x8d,0x13,0xc2, 0xf8,0x84,0x1e,0xc9,
+ 0xd2,0xbb,0x3d,0xf8, 0xdc,0xb2,0x30,0xf3, 0xce,0xa9,0x27,0xee, 0xc0,0xa0,0x2a,0xe5,
+ 0x7a,0x47,0xb1,0x3c, 0x74,0x4e,0xbc,0x37, 0x66,0x55,0xab,0x2a, 0x68,0x5c,0xa6,0x21,
+ 0x42,0x63,0x85,0x10, 0x4c,0x6a,0x88,0x1b, 0x5e,0x71,0x9f,0x06, 0x50,0x78,0x92,0x0d,
+ 0x0a,0x0f,0xd9,0x64, 0x04,0x06,0xd4,0x6f, 0x16,0x1d,0xc3,0x72, 0x18,0x14,0xce,0x79,
+ 0x32,0x2b,0xed,0x48, 0x3c,0x22,0xe0,0x43, 0x2e,0x39,0xf7,0x5e, 0x20,0x30,0xfa,0x55,
+ 0xec,0x9a,0xb7,0x01, 0xe2,0x93,0xba,0x0a, 0xf0,0x88,0xad,0x17, 0xfe,0x81,0xa0,0x1c,
+ 0xd4,0xbe,0x83,0x2d, 0xda,0xb7,0x8e,0x26, 0xc8,0xac,0x99,0x3b, 0xc6,0xa5,0x94,0x30,
+ 0x9c,0xd2,0xdf,0x59, 0x92,0xdb,0xd2,0x52, 0x80,0xc0,0xc5,0x4f, 0x8e,0xc9,0xc8,0x44,
+ 0xa4,0xf6,0xeb,0x75, 0xaa,0xff,0xe6,0x7e, 0xb8,0xe4,0xf1,0x63, 0xb6,0xed,0xfc,0x68,
+ 0x0c,0x0a,0x67,0xb1, 0x02,0x03,0x6a,0xba, 0x10,0x18,0x7d,0xa7, 0x1e,0x11,0x70,0xac,
+ 0x34,0x2e,0x53,0x9d, 0x3a,0x27,0x5e,0x96, 0x28,0x3c,0x49,0x8b, 0x26,0x35,0x44,0x80,
+ 0x7c,0x42,0x0f,0xe9, 0x72,0x4b,0x02,0xe2, 0x60,0x50,0x15,0xff, 0x6e,0x59,0x18,0xf4,
+ 0x44,0x66,0x3b,0xc5, 0x4a,0x6f,0x36,0xce, 0x58,0x74,0x21,0xd3, 0x56,0x7d,0x2c,0xd8,
+ 0x37,0xa1,0x0c,0x7a, 0x39,0xa8,0x01,0x71, 0x2b,0xb3,0x16,0x6c, 0x25,0xba,0x1b,0x67,
+ 0x0f,0x85,0x38,0x56, 0x01,0x8c,0x35,0x5d, 0x13,0x97,0x22,0x40, 0x1d,0x9e,0x2f,0x4b,
+ 0x47,0xe9,0x64,0x22, 0x49,0xe0,0x69,0x29, 0x5b,0xfb,0x7e,0x34, 0x55,0xf2,0x73,0x3f,
+ 0x7f,0xcd,0x50,0x0e, 0x71,0xc4,0x5d,0x05, 0x63,0xdf,0x4a,0x18, 0x6d,0xd6,0x47,0x13,
+ 0xd7,0x31,0xdc,0xca, 0xd9,0x38,0xd1,0xc1, 0xcb,0x23,0xc6,0xdc, 0xc5,0x2a,0xcb,0xd7,
+ 0xef,0x15,0xe8,0xe6, 0xe1,0x1c,0xe5,0xed, 0xf3,0x07,0xf2,0xf0, 0xfd,0x0e,0xff,0xfb,
+ 0xa7,0x79,0xb4,0x92, 0xa9,0x70,0xb9,0x99, 0xbb,0x6b,0xae,0x84, 0xb5,0x62,0xa3,0x8f,
+ 0x9f,0x5d,0x80,0xbe, 0x91,0x54,0x8d,0xb5, 0x83,0x4f,0x9a,0xa8, 0x8d,0x46,0x97,0xa3
+};
+
+static UINT8 U2[256][4]=
+{
+ 0x00,0x00,0x00,0x00, 0x0b,0x0e,0x09,0x0d, 0x16,0x1c,0x12,0x1a, 0x1d,0x12,0x1b,0x17,
+ 0x2c,0x38,0x24,0x34, 0x27,0x36,0x2d,0x39, 0x3a,0x24,0x36,0x2e, 0x31,0x2a,0x3f,0x23,
+ 0x58,0x70,0x48,0x68, 0x53,0x7e,0x41,0x65, 0x4e,0x6c,0x5a,0x72, 0x45,0x62,0x53,0x7f,
+ 0x74,0x48,0x6c,0x5c, 0x7f,0x46,0x65,0x51, 0x62,0x54,0x7e,0x46, 0x69,0x5a,0x77,0x4b,
+ 0xb0,0xe0,0x90,0xd0, 0xbb,0xee,0x99,0xdd, 0xa6,0xfc,0x82,0xca, 0xad,0xf2,0x8b,0xc7,
+ 0x9c,0xd8,0xb4,0xe4, 0x97,0xd6,0xbd,0xe9, 0x8a,0xc4,0xa6,0xfe, 0x81,0xca,0xaf,0xf3,
+ 0xe8,0x90,0xd8,0xb8, 0xe3,0x9e,0xd1,0xb5, 0xfe,0x8c,0xca,0xa2, 0xf5,0x82,0xc3,0xaf,
+ 0xc4,0xa8,0xfc,0x8c, 0xcf,0xa6,0xf5,0x81, 0xd2,0xb4,0xee,0x96, 0xd9,0xba,0xe7,0x9b,
+ 0x7b,0xdb,0x3b,0xbb, 0x70,0xd5,0x32,0xb6, 0x6d,0xc7,0x29,0xa1, 0x66,0xc9,0x20,0xac,
+ 0x57,0xe3,0x1f,0x8f, 0x5c,0xed,0x16,0x82, 0x41,0xff,0x0d,0x95, 0x4a,0xf1,0x04,0x98,
+ 0x23,0xab,0x73,0xd3, 0x28,0xa5,0x7a,0xde, 0x35,0xb7,0x61,0xc9, 0x3e,0xb9,0x68,0xc4,
+ 0x0f,0x93,0x57,0xe7, 0x04,0x9d,0x5e,0xea, 0x19,0x8f,0x45,0xfd, 0x12,0x81,0x4c,0xf0,
+ 0xcb,0x3b,0xab,0x6b, 0xc0,0x35,0xa2,0x66, 0xdd,0x27,0xb9,0x71, 0xd6,0x29,0xb0,0x7c,
+ 0xe7,0x03,0x8f,0x5f, 0xec,0x0d,0x86,0x52, 0xf1,0x1f,0x9d,0x45, 0xfa,0x11,0x94,0x48,
+ 0x93,0x4b,0xe3,0x03, 0x98,0x45,0xea,0x0e, 0x85,0x57,0xf1,0x19, 0x8e,0x59,0xf8,0x14,
+ 0xbf,0x73,0xc7,0x37, 0xb4,0x7d,0xce,0x3a, 0xa9,0x6f,0xd5,0x2d, 0xa2,0x61,0xdc,0x20,
+ 0xf6,0xad,0x76,0x6d, 0xfd,0xa3,0x7f,0x60, 0xe0,0xb1,0x64,0x77, 0xeb,0xbf,0x6d,0x7a,
+ 0xda,0x95,0x52,0x59, 0xd1,0x9b,0x5b,0x54, 0xcc,0x89,0x40,0x43, 0xc7,0x87,0x49,0x4e,
+ 0xae,0xdd,0x3e,0x05, 0xa5,0xd3,0x37,0x08, 0xb8,0xc1,0x2c,0x1f, 0xb3,0xcf,0x25,0x12,
+ 0x82,0xe5,0x1a,0x31, 0x89,0xeb,0x13,0x3c, 0x94,0xf9,0x08,0x2b, 0x9f,0xf7,0x01,0x26,
+ 0x46,0x4d,0xe6,0xbd, 0x4d,0x43,0xef,0xb0, 0x50,0x51,0xf4,0xa7, 0x5b,0x5f,0xfd,0xaa,
+ 0x6a,0x75,0xc2,0x89, 0x61,0x7b,0xcb,0x84, 0x7c,0x69,0xd0,0x93, 0x77,0x67,0xd9,0x9e,
+ 0x1e,0x3d,0xae,0xd5, 0x15,0x33,0xa7,0xd8, 0x08,0x21,0xbc,0xcf, 0x03,0x2f,0xb5,0xc2,
+ 0x32,0x05,0x8a,0xe1, 0x39,0x0b,0x83,0xec, 0x24,0x19,0x98,0xfb, 0x2f,0x17,0x91,0xf6,
+ 0x8d,0x76,0x4d,0xd6, 0x86,0x78,0x44,0xdb, 0x9b,0x6a,0x5f,0xcc, 0x90,0x64,0x56,0xc1,
+ 0xa1,0x4e,0x69,0xe2, 0xaa,0x40,0x60,0xef, 0xb7,0x52,0x7b,0xf8, 0xbc,0x5c,0x72,0xf5,
+ 0xd5,0x06,0x05,0xbe, 0xde,0x08,0x0c,0xb3, 0xc3,0x1a,0x17,0xa4, 0xc8,0x14,0x1e,0xa9,
+ 0xf9,0x3e,0x21,0x8a, 0xf2,0x30,0x28,0x87, 0xef,0x22,0x33,0x90, 0xe4,0x2c,0x3a,0x9d,
+ 0x3d,0x96,0xdd,0x06, 0x36,0x98,0xd4,0x0b, 0x2b,0x8a,0xcf,0x1c, 0x20,0x84,0xc6,0x11,
+ 0x11,0xae,0xf9,0x32, 0x1a,0xa0,0xf0,0x3f, 0x07,0xb2,0xeb,0x28, 0x0c,0xbc,0xe2,0x25,
+ 0x65,0xe6,0x95,0x6e, 0x6e,0xe8,0x9c,0x63, 0x73,0xfa,0x87,0x74, 0x78,0xf4,0x8e,0x79,
+ 0x49,0xde,0xb1,0x5a, 0x42,0xd0,0xb8,0x57, 0x5f,0xc2,0xa3,0x40, 0x54,0xcc,0xaa,0x4d,
+ 0xf7,0x41,0xec,0xda, 0xfc,0x4f,0xe5,0xd7, 0xe1,0x5d,0xfe,0xc0, 0xea,0x53,0xf7,0xcd,
+ 0xdb,0x79,0xc8,0xee, 0xd0,0x77,0xc1,0xe3, 0xcd,0x65,0xda,0xf4, 0xc6,0x6b,0xd3,0xf9,
+ 0xaf,0x31,0xa4,0xb2, 0xa4,0x3f,0xad,0xbf, 0xb9,0x2d,0xb6,0xa8, 0xb2,0x23,0xbf,0xa5,
+ 0x83,0x09,0x80,0x86, 0x88,0x07,0x89,0x8b, 0x95,0x15,0x92,0x9c, 0x9e,0x1b,0x9b,0x91,
+ 0x47,0xa1,0x7c,0x0a, 0x4c,0xaf,0x75,0x07, 0x51,0xbd,0x6e,0x10, 0x5a,0xb3,0x67,0x1d,
+ 0x6b,0x99,0x58,0x3e, 0x60,0x97,0x51,0x33, 0x7d,0x85,0x4a,0x24, 0x76,0x8b,0x43,0x29,
+ 0x1f,0xd1,0x34,0x62, 0x14,0xdf,0x3d,0x6f, 0x09,0xcd,0x26,0x78, 0x02,0xc3,0x2f,0x75,
+ 0x33,0xe9,0x10,0x56, 0x38,0xe7,0x19,0x5b, 0x25,0xf5,0x02,0x4c, 0x2e,0xfb,0x0b,0x41,
+ 0x8c,0x9a,0xd7,0x61, 0x87,0x94,0xde,0x6c, 0x9a,0x86,0xc5,0x7b, 0x91,0x88,0xcc,0x76,
+ 0xa0,0xa2,0xf3,0x55, 0xab,0xac,0xfa,0x58, 0xb6,0xbe,0xe1,0x4f, 0xbd,0xb0,0xe8,0x42,
+ 0xd4,0xea,0x9f,0x09, 0xdf,0xe4,0x96,0x04, 0xc2,0xf6,0x8d,0x13, 0xc9,0xf8,0x84,0x1e,
+ 0xf8,0xd2,0xbb,0x3d, 0xf3,0xdc,0xb2,0x30, 0xee,0xce,0xa9,0x27, 0xe5,0xc0,0xa0,0x2a,
+ 0x3c,0x7a,0x47,0xb1, 0x37,0x74,0x4e,0xbc, 0x2a,0x66,0x55,0xab, 0x21,0x68,0x5c,0xa6,
+ 0x10,0x42,0x63,0x85, 0x1b,0x4c,0x6a,0x88, 0x06,0x5e,0x71,0x9f, 0x0d,0x50,0x78,0x92,
+ 0x64,0x0a,0x0f,0xd9, 0x6f,0x04,0x06,0xd4, 0x72,0x16,0x1d,0xc3, 0x79,0x18,0x14,0xce,
+ 0x48,0x32,0x2b,0xed, 0x43,0x3c,0x22,0xe0, 0x5e,0x2e,0x39,0xf7, 0x55,0x20,0x30,0xfa,
+ 0x01,0xec,0x9a,0xb7, 0x0a,0xe2,0x93,0xba, 0x17,0xf0,0x88,0xad, 0x1c,0xfe,0x81,0xa0,
+ 0x2d,0xd4,0xbe,0x83, 0x26,0xda,0xb7,0x8e, 0x3b,0xc8,0xac,0x99, 0x30,0xc6,0xa5,0x94,
+ 0x59,0x9c,0xd2,0xdf, 0x52,0x92,0xdb,0xd2, 0x4f,0x80,0xc0,0xc5, 0x44,0x8e,0xc9,0xc8,
+ 0x75,0xa4,0xf6,0xeb, 0x7e,0xaa,0xff,0xe6, 0x63,0xb8,0xe4,0xf1, 0x68,0xb6,0xed,0xfc,
+ 0xb1,0x0c,0x0a,0x67, 0xba,0x02,0x03,0x6a, 0xa7,0x10,0x18,0x7d, 0xac,0x1e,0x11,0x70,
+ 0x9d,0x34,0x2e,0x53, 0x96,0x3a,0x27,0x5e, 0x8b,0x28,0x3c,0x49, 0x80,0x26,0x35,0x44,
+ 0xe9,0x7c,0x42,0x0f, 0xe2,0x72,0x4b,0x02, 0xff,0x60,0x50,0x15, 0xf4,0x6e,0x59,0x18,
+ 0xc5,0x44,0x66,0x3b, 0xce,0x4a,0x6f,0x36, 0xd3,0x58,0x74,0x21, 0xd8,0x56,0x7d,0x2c,
+ 0x7a,0x37,0xa1,0x0c, 0x71,0x39,0xa8,0x01, 0x6c,0x2b,0xb3,0x16, 0x67,0x25,0xba,0x1b,
+ 0x56,0x0f,0x85,0x38, 0x5d,0x01,0x8c,0x35, 0x40,0x13,0x97,0x22, 0x4b,0x1d,0x9e,0x2f,
+ 0x22,0x47,0xe9,0x64, 0x29,0x49,0xe0,0x69, 0x34,0x5b,0xfb,0x7e, 0x3f,0x55,0xf2,0x73,
+ 0x0e,0x7f,0xcd,0x50, 0x05,0x71,0xc4,0x5d, 0x18,0x63,0xdf,0x4a, 0x13,0x6d,0xd6,0x47,
+ 0xca,0xd7,0x31,0xdc, 0xc1,0xd9,0x38,0xd1, 0xdc,0xcb,0x23,0xc6, 0xd7,0xc5,0x2a,0xcb,
+ 0xe6,0xef,0x15,0xe8, 0xed,0xe1,0x1c,0xe5, 0xf0,0xf3,0x07,0xf2, 0xfb,0xfd,0x0e,0xff,
+ 0x92,0xa7,0x79,0xb4, 0x99,0xa9,0x70,0xb9, 0x84,0xbb,0x6b,0xae, 0x8f,0xb5,0x62,0xa3,
+ 0xbe,0x9f,0x5d,0x80, 0xb5,0x91,0x54,0x8d, 0xa8,0x83,0x4f,0x9a, 0xa3,0x8d,0x46,0x97
+};
+
+static UINT8 U3[256][4]=
+{
+ 0x00,0x00,0x00,0x00, 0x0d,0x0b,0x0e,0x09, 0x1a,0x16,0x1c,0x12, 0x17,0x1d,0x12,0x1b,
+ 0x34,0x2c,0x38,0x24, 0x39,0x27,0x36,0x2d, 0x2e,0x3a,0x24,0x36, 0x23,0x31,0x2a,0x3f,
+ 0x68,0x58,0x70,0x48, 0x65,0x53,0x7e,0x41, 0x72,0x4e,0x6c,0x5a, 0x7f,0x45,0x62,0x53,
+ 0x5c,0x74,0x48,0x6c, 0x51,0x7f,0x46,0x65, 0x46,0x62,0x54,0x7e, 0x4b,0x69,0x5a,0x77,
+ 0xd0,0xb0,0xe0,0x90, 0xdd,0xbb,0xee,0x99, 0xca,0xa6,0xfc,0x82, 0xc7,0xad,0xf2,0x8b,
+ 0xe4,0x9c,0xd8,0xb4, 0xe9,0x97,0xd6,0xbd, 0xfe,0x8a,0xc4,0xa6, 0xf3,0x81,0xca,0xaf,
+ 0xb8,0xe8,0x90,0xd8, 0xb5,0xe3,0x9e,0xd1, 0xa2,0xfe,0x8c,0xca, 0xaf,0xf5,0x82,0xc3,
+ 0x8c,0xc4,0xa8,0xfc, 0x81,0xcf,0xa6,0xf5, 0x96,0xd2,0xb4,0xee, 0x9b,0xd9,0xba,0xe7,
+ 0xbb,0x7b,0xdb,0x3b, 0xb6,0x70,0xd5,0x32, 0xa1,0x6d,0xc7,0x29, 0xac,0x66,0xc9,0x20,
+ 0x8f,0x57,0xe3,0x1f, 0x82,0x5c,0xed,0x16, 0x95,0x41,0xff,0x0d, 0x98,0x4a,0xf1,0x04,
+ 0xd3,0x23,0xab,0x73, 0xde,0x28,0xa5,0x7a, 0xc9,0x35,0xb7,0x61, 0xc4,0x3e,0xb9,0x68,
+ 0xe7,0x0f,0x93,0x57, 0xea,0x04,0x9d,0x5e, 0xfd,0x19,0x8f,0x45, 0xf0,0x12,0x81,0x4c,
+ 0x6b,0xcb,0x3b,0xab, 0x66,0xc0,0x35,0xa2, 0x71,0xdd,0x27,0xb9, 0x7c,0xd6,0x29,0xb0,
+ 0x5f,0xe7,0x03,0x8f, 0x52,0xec,0x0d,0x86, 0x45,0xf1,0x1f,0x9d, 0x48,0xfa,0x11,0x94,
+ 0x03,0x93,0x4b,0xe3, 0x0e,0x98,0x45,0xea, 0x19,0x85,0x57,0xf1, 0x14,0x8e,0x59,0xf8,
+ 0x37,0xbf,0x73,0xc7, 0x3a,0xb4,0x7d,0xce, 0x2d,0xa9,0x6f,0xd5, 0x20,0xa2,0x61,0xdc,
+ 0x6d,0xf6,0xad,0x76, 0x60,0xfd,0xa3,0x7f, 0x77,0xe0,0xb1,0x64, 0x7a,0xeb,0xbf,0x6d,
+ 0x59,0xda,0x95,0x52, 0x54,0xd1,0x9b,0x5b, 0x43,0xcc,0x89,0x40, 0x4e,0xc7,0x87,0x49,
+ 0x05,0xae,0xdd,0x3e, 0x08,0xa5,0xd3,0x37, 0x1f,0xb8,0xc1,0x2c, 0x12,0xb3,0xcf,0x25,
+ 0x31,0x82,0xe5,0x1a, 0x3c,0x89,0xeb,0x13, 0x2b,0x94,0xf9,0x08, 0x26,0x9f,0xf7,0x01,
+ 0xbd,0x46,0x4d,0xe6, 0xb0,0x4d,0x43,0xef, 0xa7,0x50,0x51,0xf4, 0xaa,0x5b,0x5f,0xfd,
+ 0x89,0x6a,0x75,0xc2, 0x84,0x61,0x7b,0xcb, 0x93,0x7c,0x69,0xd0, 0x9e,0x77,0x67,0xd9,
+ 0xd5,0x1e,0x3d,0xae, 0xd8,0x15,0x33,0xa7, 0xcf,0x08,0x21,0xbc, 0xc2,0x03,0x2f,0xb5,
+ 0xe1,0x32,0x05,0x8a, 0xec,0x39,0x0b,0x83, 0xfb,0x24,0x19,0x98, 0xf6,0x2f,0x17,0x91,
+ 0xd6,0x8d,0x76,0x4d, 0xdb,0x86,0x78,0x44, 0xcc,0x9b,0x6a,0x5f, 0xc1,0x90,0x64,0x56,
+ 0xe2,0xa1,0x4e,0x69, 0xef,0xaa,0x40,0x60, 0xf8,0xb7,0x52,0x7b, 0xf5,0xbc,0x5c,0x72,
+ 0xbe,0xd5,0x06,0x05, 0xb3,0xde,0x08,0x0c, 0xa4,0xc3,0x1a,0x17, 0xa9,0xc8,0x14,0x1e,
+ 0x8a,0xf9,0x3e,0x21, 0x87,0xf2,0x30,0x28, 0x90,0xef,0x22,0x33, 0x9d,0xe4,0x2c,0x3a,
+ 0x06,0x3d,0x96,0xdd, 0x0b,0x36,0x98,0xd4, 0x1c,0x2b,0x8a,0xcf, 0x11,0x20,0x84,0xc6,
+ 0x32,0x11,0xae,0xf9, 0x3f,0x1a,0xa0,0xf0, 0x28,0x07,0xb2,0xeb, 0x25,0x0c,0xbc,0xe2,
+ 0x6e,0x65,0xe6,0x95, 0x63,0x6e,0xe8,0x9c, 0x74,0x73,0xfa,0x87, 0x79,0x78,0xf4,0x8e,
+ 0x5a,0x49,0xde,0xb1, 0x57,0x42,0xd0,0xb8, 0x40,0x5f,0xc2,0xa3, 0x4d,0x54,0xcc,0xaa,
+ 0xda,0xf7,0x41,0xec, 0xd7,0xfc,0x4f,0xe5, 0xc0,0xe1,0x5d,0xfe, 0xcd,0xea,0x53,0xf7,
+ 0xee,0xdb,0x79,0xc8, 0xe3,0xd0,0x77,0xc1, 0xf4,0xcd,0x65,0xda, 0xf9,0xc6,0x6b,0xd3,
+ 0xb2,0xaf,0x31,0xa4, 0xbf,0xa4,0x3f,0xad, 0xa8,0xb9,0x2d,0xb6, 0xa5,0xb2,0x23,0xbf,
+ 0x86,0x83,0x09,0x80, 0x8b,0x88,0x07,0x89, 0x9c,0x95,0x15,0x92, 0x91,0x9e,0x1b,0x9b,
+ 0x0a,0x47,0xa1,0x7c, 0x07,0x4c,0xaf,0x75, 0x10,0x51,0xbd,0x6e, 0x1d,0x5a,0xb3,0x67,
+ 0x3e,0x6b,0x99,0x58, 0x33,0x60,0x97,0x51, 0x24,0x7d,0x85,0x4a, 0x29,0x76,0x8b,0x43,
+ 0x62,0x1f,0xd1,0x34, 0x6f,0x14,0xdf,0x3d, 0x78,0x09,0xcd,0x26, 0x75,0x02,0xc3,0x2f,
+ 0x56,0x33,0xe9,0x10, 0x5b,0x38,0xe7,0x19, 0x4c,0x25,0xf5,0x02, 0x41,0x2e,0xfb,0x0b,
+ 0x61,0x8c,0x9a,0xd7, 0x6c,0x87,0x94,0xde, 0x7b,0x9a,0x86,0xc5, 0x76,0x91,0x88,0xcc,
+ 0x55,0xa0,0xa2,0xf3, 0x58,0xab,0xac,0xfa, 0x4f,0xb6,0xbe,0xe1, 0x42,0xbd,0xb0,0xe8,
+ 0x09,0xd4,0xea,0x9f, 0x04,0xdf,0xe4,0x96, 0x13,0xc2,0xf6,0x8d, 0x1e,0xc9,0xf8,0x84,
+ 0x3d,0xf8,0xd2,0xbb, 0x30,0xf3,0xdc,0xb2, 0x27,0xee,0xce,0xa9, 0x2a,0xe5,0xc0,0xa0,
+ 0xb1,0x3c,0x7a,0x47, 0xbc,0x37,0x74,0x4e, 0xab,0x2a,0x66,0x55, 0xa6,0x21,0x68,0x5c,
+ 0x85,0x10,0x42,0x63, 0x88,0x1b,0x4c,0x6a, 0x9f,0x06,0x5e,0x71, 0x92,0x0d,0x50,0x78,
+ 0xd9,0x64,0x0a,0x0f, 0xd4,0x6f,0x04,0x06, 0xc3,0x72,0x16,0x1d, 0xce,0x79,0x18,0x14,
+ 0xed,0x48,0x32,0x2b, 0xe0,0x43,0x3c,0x22, 0xf7,0x5e,0x2e,0x39, 0xfa,0x55,0x20,0x30,
+ 0xb7,0x01,0xec,0x9a, 0xba,0x0a,0xe2,0x93, 0xad,0x17,0xf0,0x88, 0xa0,0x1c,0xfe,0x81,
+ 0x83,0x2d,0xd4,0xbe, 0x8e,0x26,0xda,0xb7, 0x99,0x3b,0xc8,0xac, 0x94,0x30,0xc6,0xa5,
+ 0xdf,0x59,0x9c,0xd2, 0xd2,0x52,0x92,0xdb, 0xc5,0x4f,0x80,0xc0, 0xc8,0x44,0x8e,0xc9,
+ 0xeb,0x75,0xa4,0xf6, 0xe6,0x7e,0xaa,0xff, 0xf1,0x63,0xb8,0xe4, 0xfc,0x68,0xb6,0xed,
+ 0x67,0xb1,0x0c,0x0a, 0x6a,0xba,0x02,0x03, 0x7d,0xa7,0x10,0x18, 0x70,0xac,0x1e,0x11,
+ 0x53,0x9d,0x34,0x2e, 0x5e,0x96,0x3a,0x27, 0x49,0x8b,0x28,0x3c, 0x44,0x80,0x26,0x35,
+ 0x0f,0xe9,0x7c,0x42, 0x02,0xe2,0x72,0x4b, 0x15,0xff,0x60,0x50, 0x18,0xf4,0x6e,0x59,
+ 0x3b,0xc5,0x44,0x66, 0x36,0xce,0x4a,0x6f, 0x21,0xd3,0x58,0x74, 0x2c,0xd8,0x56,0x7d,
+ 0x0c,0x7a,0x37,0xa1, 0x01,0x71,0x39,0xa8, 0x16,0x6c,0x2b,0xb3, 0x1b,0x67,0x25,0xba,
+ 0x38,0x56,0x0f,0x85, 0x35,0x5d,0x01,0x8c, 0x22,0x40,0x13,0x97, 0x2f,0x4b,0x1d,0x9e,
+ 0x64,0x22,0x47,0xe9, 0x69,0x29,0x49,0xe0, 0x7e,0x34,0x5b,0xfb, 0x73,0x3f,0x55,0xf2,
+ 0x50,0x0e,0x7f,0xcd, 0x5d,0x05,0x71,0xc4, 0x4a,0x18,0x63,0xdf, 0x47,0x13,0x6d,0xd6,
+ 0xdc,0xca,0xd7,0x31, 0xd1,0xc1,0xd9,0x38, 0xc6,0xdc,0xcb,0x23, 0xcb,0xd7,0xc5,0x2a,
+ 0xe8,0xe6,0xef,0x15, 0xe5,0xed,0xe1,0x1c, 0xf2,0xf0,0xf3,0x07, 0xff,0xfb,0xfd,0x0e,
+ 0xb4,0x92,0xa7,0x79, 0xb9,0x99,0xa9,0x70, 0xae,0x84,0xbb,0x6b, 0xa3,0x8f,0xb5,0x62,
+ 0x80,0xbe,0x9f,0x5d, 0x8d,0xb5,0x91,0x54, 0x9a,0xa8,0x83,0x4f, 0x97,0xa3,0x8d,0x46
+};
+
+static UINT8 U4[256][4]=
+{
+ 0x00,0x00,0x00,0x00, 0x09,0x0d,0x0b,0x0e, 0x12,0x1a,0x16,0x1c, 0x1b,0x17,0x1d,0x12,
+ 0x24,0x34,0x2c,0x38, 0x2d,0x39,0x27,0x36, 0x36,0x2e,0x3a,0x24, 0x3f,0x23,0x31,0x2a,
+ 0x48,0x68,0x58,0x70, 0x41,0x65,0x53,0x7e, 0x5a,0x72,0x4e,0x6c, 0x53,0x7f,0x45,0x62,
+ 0x6c,0x5c,0x74,0x48, 0x65,0x51,0x7f,0x46, 0x7e,0x46,0x62,0x54, 0x77,0x4b,0x69,0x5a,
+ 0x90,0xd0,0xb0,0xe0, 0x99,0xdd,0xbb,0xee, 0x82,0xca,0xa6,0xfc, 0x8b,0xc7,0xad,0xf2,
+ 0xb4,0xe4,0x9c,0xd8, 0xbd,0xe9,0x97,0xd6, 0xa6,0xfe,0x8a,0xc4, 0xaf,0xf3,0x81,0xca,
+ 0xd8,0xb8,0xe8,0x90, 0xd1,0xb5,0xe3,0x9e, 0xca,0xa2,0xfe,0x8c, 0xc3,0xaf,0xf5,0x82,
+ 0xfc,0x8c,0xc4,0xa8, 0xf5,0x81,0xcf,0xa6, 0xee,0x96,0xd2,0xb4, 0xe7,0x9b,0xd9,0xba,
+ 0x3b,0xbb,0x7b,0xdb, 0x32,0xb6,0x70,0xd5, 0x29,0xa1,0x6d,0xc7, 0x20,0xac,0x66,0xc9,
+ 0x1f,0x8f,0x57,0xe3, 0x16,0x82,0x5c,0xed, 0x0d,0x95,0x41,0xff, 0x04,0x98,0x4a,0xf1,
+ 0x73,0xd3,0x23,0xab, 0x7a,0xde,0x28,0xa5, 0x61,0xc9,0x35,0xb7, 0x68,0xc4,0x3e,0xb9,
+ 0x57,0xe7,0x0f,0x93, 0x5e,0xea,0x04,0x9d, 0x45,0xfd,0x19,0x8f, 0x4c,0xf0,0x12,0x81,
+ 0xab,0x6b,0xcb,0x3b, 0xa2,0x66,0xc0,0x35, 0xb9,0x71,0xdd,0x27, 0xb0,0x7c,0xd6,0x29,
+ 0x8f,0x5f,0xe7,0x03, 0x86,0x52,0xec,0x0d, 0x9d,0x45,0xf1,0x1f, 0x94,0x48,0xfa,0x11,
+ 0xe3,0x03,0x93,0x4b, 0xea,0x0e,0x98,0x45, 0xf1,0x19,0x85,0x57, 0xf8,0x14,0x8e,0x59,
+ 0xc7,0x37,0xbf,0x73, 0xce,0x3a,0xb4,0x7d, 0xd5,0x2d,0xa9,0x6f, 0xdc,0x20,0xa2,0x61,
+ 0x76,0x6d,0xf6,0xad, 0x7f,0x60,0xfd,0xa3, 0x64,0x77,0xe0,0xb1, 0x6d,0x7a,0xeb,0xbf,
+ 0x52,0x59,0xda,0x95, 0x5b,0x54,0xd1,0x9b, 0x40,0x43,0xcc,0x89, 0x49,0x4e,0xc7,0x87,
+ 0x3e,0x05,0xae,0xdd, 0x37,0x08,0xa5,0xd3, 0x2c,0x1f,0xb8,0xc1, 0x25,0x12,0xb3,0xcf,
+ 0x1a,0x31,0x82,0xe5, 0x13,0x3c,0x89,0xeb, 0x08,0x2b,0x94,0xf9, 0x01,0x26,0x9f,0xf7,
+ 0xe6,0xbd,0x46,0x4d, 0xef,0xb0,0x4d,0x43, 0xf4,0xa7,0x50,0x51, 0xfd,0xaa,0x5b,0x5f,
+ 0xc2,0x89,0x6a,0x75, 0xcb,0x84,0x61,0x7b, 0xd0,0x93,0x7c,0x69, 0xd9,0x9e,0x77,0x67,
+ 0xae,0xd5,0x1e,0x3d, 0xa7,0xd8,0x15,0x33, 0xbc,0xcf,0x08,0x21, 0xb5,0xc2,0x03,0x2f,
+ 0x8a,0xe1,0x32,0x05, 0x83,0xec,0x39,0x0b, 0x98,0xfb,0x24,0x19, 0x91,0xf6,0x2f,0x17,
+ 0x4d,0xd6,0x8d,0x76, 0x44,0xdb,0x86,0x78, 0x5f,0xcc,0x9b,0x6a, 0x56,0xc1,0x90,0x64,
+ 0x69,0xe2,0xa1,0x4e, 0x60,0xef,0xaa,0x40, 0x7b,0xf8,0xb7,0x52, 0x72,0xf5,0xbc,0x5c,
+ 0x05,0xbe,0xd5,0x06, 0x0c,0xb3,0xde,0x08, 0x17,0xa4,0xc3,0x1a, 0x1e,0xa9,0xc8,0x14,
+ 0x21,0x8a,0xf9,0x3e, 0x28,0x87,0xf2,0x30, 0x33,0x90,0xef,0x22, 0x3a,0x9d,0xe4,0x2c,
+ 0xdd,0x06,0x3d,0x96, 0xd4,0x0b,0x36,0x98, 0xcf,0x1c,0x2b,0x8a, 0xc6,0x11,0x20,0x84,
+ 0xf9,0x32,0x11,0xae, 0xf0,0x3f,0x1a,0xa0, 0xeb,0x28,0x07,0xb2, 0xe2,0x25,0x0c,0xbc,
+ 0x95,0x6e,0x65,0xe6, 0x9c,0x63,0x6e,0xe8, 0x87,0x74,0x73,0xfa, 0x8e,0x79,0x78,0xf4,
+ 0xb1,0x5a,0x49,0xde, 0xb8,0x57,0x42,0xd0, 0xa3,0x40,0x5f,0xc2, 0xaa,0x4d,0x54,0xcc,
+ 0xec,0xda,0xf7,0x41, 0xe5,0xd7,0xfc,0x4f, 0xfe,0xc0,0xe1,0x5d, 0xf7,0xcd,0xea,0x53,
+ 0xc8,0xee,0xdb,0x79, 0xc1,0xe3,0xd0,0x77, 0xda,0xf4,0xcd,0x65, 0xd3,0xf9,0xc6,0x6b,
+ 0xa4,0xb2,0xaf,0x31, 0xad,0xbf,0xa4,0x3f, 0xb6,0xa8,0xb9,0x2d, 0xbf,0xa5,0xb2,0x23,
+ 0x80,0x86,0x83,0x09, 0x89,0x8b,0x88,0x07, 0x92,0x9c,0x95,0x15, 0x9b,0x91,0x9e,0x1b,
+ 0x7c,0x0a,0x47,0xa1, 0x75,0x07,0x4c,0xaf, 0x6e,0x10,0x51,0xbd, 0x67,0x1d,0x5a,0xb3,
+ 0x58,0x3e,0x6b,0x99, 0x51,0x33,0x60,0x97, 0x4a,0x24,0x7d,0x85, 0x43,0x29,0x76,0x8b,
+ 0x34,0x62,0x1f,0xd1, 0x3d,0x6f,0x14,0xdf, 0x26,0x78,0x09,0xcd, 0x2f,0x75,0x02,0xc3,
+ 0x10,0x56,0x33,0xe9, 0x19,0x5b,0x38,0xe7, 0x02,0x4c,0x25,0xf5, 0x0b,0x41,0x2e,0xfb,
+ 0xd7,0x61,0x8c,0x9a, 0xde,0x6c,0x87,0x94, 0xc5,0x7b,0x9a,0x86, 0xcc,0x76,0x91,0x88,
+ 0xf3,0x55,0xa0,0xa2, 0xfa,0x58,0xab,0xac, 0xe1,0x4f,0xb6,0xbe, 0xe8,0x42,0xbd,0xb0,
+ 0x9f,0x09,0xd4,0xea, 0x96,0x04,0xdf,0xe4, 0x8d,0x13,0xc2,0xf6, 0x84,0x1e,0xc9,0xf8,
+ 0xbb,0x3d,0xf8,0xd2, 0xb2,0x30,0xf3,0xdc, 0xa9,0x27,0xee,0xce, 0xa0,0x2a,0xe5,0xc0,
+ 0x47,0xb1,0x3c,0x7a, 0x4e,0xbc,0x37,0x74, 0x55,0xab,0x2a,0x66, 0x5c,0xa6,0x21,0x68,
+ 0x63,0x85,0x10,0x42, 0x6a,0x88,0x1b,0x4c, 0x71,0x9f,0x06,0x5e, 0x78,0x92,0x0d,0x50,
+ 0x0f,0xd9,0x64,0x0a, 0x06,0xd4,0x6f,0x04, 0x1d,0xc3,0x72,0x16, 0x14,0xce,0x79,0x18,
+ 0x2b,0xed,0x48,0x32, 0x22,0xe0,0x43,0x3c, 0x39,0xf7,0x5e,0x2e, 0x30,0xfa,0x55,0x20,
+ 0x9a,0xb7,0x01,0xec, 0x93,0xba,0x0a,0xe2, 0x88,0xad,0x17,0xf0, 0x81,0xa0,0x1c,0xfe,
+ 0xbe,0x83,0x2d,0xd4, 0xb7,0x8e,0x26,0xda, 0xac,0x99,0x3b,0xc8, 0xa5,0x94,0x30,0xc6,
+ 0xd2,0xdf,0x59,0x9c, 0xdb,0xd2,0x52,0x92, 0xc0,0xc5,0x4f,0x80, 0xc9,0xc8,0x44,0x8e,
+ 0xf6,0xeb,0x75,0xa4, 0xff,0xe6,0x7e,0xaa, 0xe4,0xf1,0x63,0xb8, 0xed,0xfc,0x68,0xb6,
+ 0x0a,0x67,0xb1,0x0c, 0x03,0x6a,0xba,0x02, 0x18,0x7d,0xa7,0x10, 0x11,0x70,0xac,0x1e,
+ 0x2e,0x53,0x9d,0x34, 0x27,0x5e,0x96,0x3a, 0x3c,0x49,0x8b,0x28, 0x35,0x44,0x80,0x26,
+ 0x42,0x0f,0xe9,0x7c, 0x4b,0x02,0xe2,0x72, 0x50,0x15,0xff,0x60, 0x59,0x18,0xf4,0x6e,
+ 0x66,0x3b,0xc5,0x44, 0x6f,0x36,0xce,0x4a, 0x74,0x21,0xd3,0x58, 0x7d,0x2c,0xd8,0x56,
+ 0xa1,0x0c,0x7a,0x37, 0xa8,0x01,0x71,0x39, 0xb3,0x16,0x6c,0x2b, 0xba,0x1b,0x67,0x25,
+ 0x85,0x38,0x56,0x0f, 0x8c,0x35,0x5d,0x01, 0x97,0x22,0x40,0x13, 0x9e,0x2f,0x4b,0x1d,
+ 0xe9,0x64,0x22,0x47, 0xe0,0x69,0x29,0x49, 0xfb,0x7e,0x34,0x5b, 0xf2,0x73,0x3f,0x55,
+ 0xcd,0x50,0x0e,0x7f, 0xc4,0x5d,0x05,0x71, 0xdf,0x4a,0x18,0x63, 0xd6,0x47,0x13,0x6d,
+ 0x31,0xdc,0xca,0xd7, 0x38,0xd1,0xc1,0xd9, 0x23,0xc6,0xdc,0xcb, 0x2a,0xcb,0xd7,0xc5,
+ 0x15,0xe8,0xe6,0xef, 0x1c,0xe5,0xed,0xe1, 0x07,0xf2,0xf0,0xf3, 0x0e,0xff,0xfb,0xfd,
+ 0x79,0xb4,0x92,0xa7, 0x70,0xb9,0x99,0xa9, 0x6b,0xae,0x84,0xbb, 0x62,0xa3,0x8f,0xb5,
+ 0x5d,0x80,0xbe,0x9f, 0x54,0x8d,0xb5,0x91, 0x4f,0x9a,0xa8,0x83, 0x46,0x97,0xa3,0x8d
+};
+
+static UINT32 rcon[30]=
+{
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20,
+ 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8,
+ 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc,
+ 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4,
+ 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91
+};
+
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// API
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+Rijndael::Rijndael()
+{
+ m_state = Invalid;
+}
+
+Rijndael::~Rijndael()
+{
+ // nothing here
+}
+
+int Rijndael::init(Mode mode,Direction dir,const UINT8 * key,KeyLength keyLen,UINT8 * initVector)
+{
+ // Not initialized yet
+ m_state = Invalid;
+
+ // Check the mode
+ if((mode != CBC) && (mode != ECB) && (mode != CFB1))return RIJNDAEL_UNSUPPORTED_MODE;
+ m_mode = mode;
+
+ // And the direction
+ if((dir != Encrypt) && (dir != Decrypt))return RIJNDAEL_UNSUPPORTED_DIRECTION;
+ m_direction = dir;
+
+ // Allow to set an init vector
+ if(initVector)
+ {
+ // specified init vector
+ for(int i = 0;i < MAX_IV_SIZE;i++)
+ {
+ m_initVector[i] = initVector[i];
+ }
+ } else {
+ // zero init vector
+ for(int i = 0;i < MAX_IV_SIZE;i++)
+ {
+ m_initVector[i] = 0;
+ }
+ }
+
+ UINT32 uKeyLenInBytes;
+
+ // And check the key length
+ switch(keyLen)
+ {
+ case Key16Bytes:
+ uKeyLenInBytes = 16;
+ m_uRounds = 10;
+ break;
+ case Key24Bytes:
+ uKeyLenInBytes = 24;
+ m_uRounds = 12;
+ break;
+ case Key32Bytes:
+ uKeyLenInBytes = 32;
+ m_uRounds = 14;
+ break;
+ default:
+ return RIJNDAEL_UNSUPPORTED_KEY_LENGTH;
+ break;
+ }
+ // The number of rounds is calculated as
+ // m_uRounds = (m_uKeyLenInBits / 32) + 6;
+
+ if(!key)return RIJNDAEL_BAD_KEY;
+
+ UINT8 keyMatrix[_MAX_KEY_COLUMNS][4];
+
+ for(UINT32 i = 0;i < uKeyLenInBytes;i++)keyMatrix[i >> 2][i & 3] = key[i];
+
+ keySched(keyMatrix);
+
+ if(m_direction == Decrypt)keyEncToDec();
+
+ m_state = Valid;
+
+ return RIJNDAEL_SUCCESS;
+}
+
+int Rijndael::blockEncrypt(const UINT8 *input,int inputLen,UINT8 *outBuffer)
+{
+ int i, k, numBlocks;
+ UINT8 block[16], iv[4][4];
+
+ if(m_state != Valid)return RIJNDAEL_NOT_INITIALIZED;
+ if(m_direction != Encrypt)return RIJNDAEL_BAD_DIRECTION;
+
+ if(input == 0 || inputLen <= 0)return 0;
+
+ numBlocks = inputLen/128;
+
+ switch(m_mode){
+ case ECB:
+ for(i = numBlocks;i > 0;i--)
+ {
+ encrypt(input,outBuffer);
+ input += 16;
+ outBuffer += 16;
+ }
+ break;
+ case CBC:
+ ((UINT32*)block)[0] = ((UINT32*)m_initVector)[0] ^ ((UINT32*)input)[0];
+ ((UINT32*)block)[1] = ((UINT32*)m_initVector)[1] ^ ((UINT32*)input)[1];
+ ((UINT32*)block)[2] = ((UINT32*)m_initVector)[2] ^ ((UINT32*)input)[2];
+ ((UINT32*)block)[3] = ((UINT32*)m_initVector)[3] ^ ((UINT32*)input)[3];
+ encrypt(block,outBuffer);
+ input += 16;
+ for(i = numBlocks - 1;i > 0;i--)
+ {
+ ((UINT32*)block)[0] = ((UINT32*)outBuffer)[0] ^ ((UINT32*)input)[0];
+ ((UINT32*)block)[1] = ((UINT32*)outBuffer)[1] ^ ((UINT32*)input)[1];
+ ((UINT32*)block)[2] = ((UINT32*)outBuffer)[2] ^ ((UINT32*)input)[2];
+ ((UINT32*)block)[3] = ((UINT32*)outBuffer)[3] ^ ((UINT32*)input)[3];
+ outBuffer += 16;
+ encrypt(block,outBuffer);
+ input += 16;
+ }
+ break;
+ case CFB1:
+#if STRICT_ALIGN
+ kvi_memmove(iv,m_initVector,16);
+#else /* !STRICT_ALIGN */
+ *((UINT32*)iv[0]) = *((UINT32*)(m_initVector ));
+ *((UINT32*)iv[1]) = *((UINT32*)(m_initVector + 4));
+ *((UINT32*)iv[2]) = *((UINT32*)(m_initVector + 8));
+ *((UINT32*)iv[3]) = *((UINT32*)(m_initVector +12));
+#endif /* ?STRICT_ALIGN */
+ for(i = numBlocks; i > 0; i--)
+ {
+ for(k = 0; k < 128; k++)
+ {
+ *((UINT32*) block ) = *((UINT32*)iv[0]);
+ *((UINT32*)(block+ 4)) = *((UINT32*)iv[1]);
+ *((UINT32*)(block+ 8)) = *((UINT32*)iv[2]);
+ *((UINT32*)(block+12)) = *((UINT32*)iv[3]);
+ encrypt(block,block);
+ outBuffer[k/8] ^= (block[0] & 0x80) >> (k & 7);
+ iv[0][0] = (iv[0][0] << 1) | (iv[0][1] >> 7);
+ iv[0][1] = (iv[0][1] << 1) | (iv[0][2] >> 7);
+ iv[0][2] = (iv[0][2] << 1) | (iv[0][3] >> 7);
+ iv[0][3] = (iv[0][3] << 1) | (iv[1][0] >> 7);
+ iv[1][0] = (iv[1][0] << 1) | (iv[1][1] >> 7);
+ iv[1][1] = (iv[1][1] << 1) | (iv[1][2] >> 7);
+ iv[1][2] = (iv[1][2] << 1) | (iv[1][3] >> 7);
+ iv[1][3] = (iv[1][3] << 1) | (iv[2][0] >> 7);
+ iv[2][0] = (iv[2][0] << 1) | (iv[2][1] >> 7);
+ iv[2][1] = (iv[2][1] << 1) | (iv[2][2] >> 7);
+ iv[2][2] = (iv[2][2] << 1) | (iv[2][3] >> 7);
+ iv[2][3] = (iv[2][3] << 1) | (iv[3][0] >> 7);
+ iv[3][0] = (iv[3][0] << 1) | (iv[3][1] >> 7);
+ iv[3][1] = (iv[3][1] << 1) | (iv[3][2] >> 7);
+ iv[3][2] = (iv[3][2] << 1) | (iv[3][3] >> 7);
+ iv[3][3] = (iv[3][3] << 1) | (outBuffer[k/8] >> (7-(k&7))) & 1;
+ }
+ }
+ break;
+ default:
+ return -1;
+ break;
+ }
+
+ return 128 * numBlocks;
+}
+
+int Rijndael::padEncrypt(const UINT8 *input, int inputOctets, UINT8 *outBuffer)
+{
+ int i, numBlocks, padLen;
+ UINT8 block[16], *iv;
+
+ if(m_state != Valid)return RIJNDAEL_NOT_INITIALIZED;
+ if(m_direction != Encrypt)return RIJNDAEL_NOT_INITIALIZED;
+
+ if(input == 0 || inputOctets <= 0)return 0;
+
+ numBlocks = inputOctets/16;
+
+ switch(m_mode)
+ {
+ case ECB:
+ for(i = numBlocks; i > 0; i--)
+ {
+ encrypt(input, outBuffer);
+ input += 16;
+ outBuffer += 16;
+ }
+ padLen = 16 - (inputOctets - 16*numBlocks);
+// assert(padLen > 0 && padLen <= 16);
+ kvi_memmove(block, input, 16 - padLen);
+ kvi_memset(block + 16 - padLen, padLen, padLen);
+ encrypt(block,outBuffer);
+ break;
+ case CBC:
+ iv = m_initVector;
+ for(i = numBlocks; i > 0; i--)
+ {
+ ((UINT32*)block)[0] = ((UINT32*)input)[0] ^ ((UINT32*)iv)[0];
+ ((UINT32*)block)[1] = ((UINT32*)input)[1] ^ ((UINT32*)iv)[1];
+ ((UINT32*)block)[2] = ((UINT32*)input)[2] ^ ((UINT32*)iv)[2];
+ ((UINT32*)block)[3] = ((UINT32*)input)[3] ^ ((UINT32*)iv)[3];
+ encrypt(block, outBuffer);
+ iv = outBuffer;
+ input += 16;
+ outBuffer += 16;
+ }
+ padLen = 16 - (inputOctets - 16*numBlocks);
+// assert(padLen > 0 && padLen <= 16); // DO SOMETHING HERE ?
+ for (i = 0; i < 16 - padLen; i++) {
+ block[i] = input[i] ^ iv[i];
+ }
+ for (i = 16 - padLen; i < 16; i++) {
+ block[i] = (UINT8)padLen ^ iv[i];
+ }
+ encrypt(block,outBuffer);
+ break;
+ default:
+ return -1;
+ break;
+ }
+
+ return 16*(numBlocks + 1);
+}
+
+int Rijndael::blockDecrypt(const UINT8 *input, int inputLen, UINT8 *outBuffer)
+{
+ int i, k, numBlocks;
+ UINT8 block[16], iv[4][4];
+
+ if(m_state != Valid)return RIJNDAEL_NOT_INITIALIZED;
+ if((m_mode != CFB1) && (m_direction == Encrypt))return RIJNDAEL_BAD_DIRECTION;
+
+ if (input == 0 || inputLen <= 0)return 0;
+
+ numBlocks = inputLen/128;
+
+ switch(m_mode)
+ {
+ case ECB:
+ for (i = numBlocks; i > 0; i--)
+ {
+ decrypt(input,outBuffer);
+ input += 16;
+ outBuffer += 16;
+ }
+ break;
+ case CBC:
+#if STRICT_ALIGN
+ kvi_memmove(iv,m_initVector,16);
+#else
+ *((UINT32*)iv[0]) = *((UINT32*)(m_initVector ));
+ *((UINT32*)iv[1]) = *((UINT32*)(m_initVector+ 4));
+ *((UINT32*)iv[2]) = *((UINT32*)(m_initVector+ 8));
+ *((UINT32*)iv[3]) = *((UINT32*)(m_initVector+12));
+#endif
+ for (i = numBlocks; i > 0; i--)
+ {
+ decrypt(input, block);
+ ((UINT32*)block)[0] ^= *((UINT32*)iv[0]);
+ ((UINT32*)block)[1] ^= *((UINT32*)iv[1]);
+ ((UINT32*)block)[2] ^= *((UINT32*)iv[2]);
+ ((UINT32*)block)[3] ^= *((UINT32*)iv[3]);
+#if STRICT_ALIGN
+ kvi_memmove(iv, input, 16);
+ kvi_memmove(outBuf, block, 16);
+#else
+ *((UINT32*)iv[0]) = ((UINT32*)input)[0]; ((UINT32*)outBuffer)[0] = ((UINT32*)block)[0];
+ *((UINT32*)iv[1]) = ((UINT32*)input)[1]; ((UINT32*)outBuffer)[1] = ((UINT32*)block)[1];
+ *((UINT32*)iv[2]) = ((UINT32*)input)[2]; ((UINT32*)outBuffer)[2] = ((UINT32*)block)[2];
+ *((UINT32*)iv[3]) = ((UINT32*)input)[3]; ((UINT32*)outBuffer)[3] = ((UINT32*)block)[3];
+#endif
+ input += 16;
+ outBuffer += 16;
+ }
+ break;
+ case CFB1:
+#if STRICT_ALIGN
+ kvi_memmove(iv, m_initVector, 16);
+#else
+ *((UINT32*)iv[0]) = *((UINT32*)(m_initVector));
+ *((UINT32*)iv[1]) = *((UINT32*)(m_initVector+ 4));
+ *((UINT32*)iv[2]) = *((UINT32*)(m_initVector+ 8));
+ *((UINT32*)iv[3]) = *((UINT32*)(m_initVector+12));
+#endif
+ for(i = numBlocks; i > 0; i--)
+ {
+ for(k = 0; k < 128; k++)
+ {
+ *((UINT32*) block ) = *((UINT32*)iv[0]);
+ *((UINT32*)(block+ 4)) = *((UINT32*)iv[1]);
+ *((UINT32*)(block+ 8)) = *((UINT32*)iv[2]);
+ *((UINT32*)(block+12)) = *((UINT32*)iv[3]);
+ encrypt(block, block);
+ iv[0][0] = (iv[0][0] << 1) | (iv[0][1] >> 7);
+ iv[0][1] = (iv[0][1] << 1) | (iv[0][2] >> 7);
+ iv[0][2] = (iv[0][2] << 1) | (iv[0][3] >> 7);
+ iv[0][3] = (iv[0][3] << 1) | (iv[1][0] >> 7);
+ iv[1][0] = (iv[1][0] << 1) | (iv[1][1] >> 7);
+ iv[1][1] = (iv[1][1] << 1) | (iv[1][2] >> 7);
+ iv[1][2] = (iv[1][2] << 1) | (iv[1][3] >> 7);
+ iv[1][3] = (iv[1][3] << 1) | (iv[2][0] >> 7);
+ iv[2][0] = (iv[2][0] << 1) | (iv[2][1] >> 7);
+ iv[2][1] = (iv[2][1] << 1) | (iv[2][2] >> 7);
+ iv[2][2] = (iv[2][2] << 1) | (iv[2][3] >> 7);
+ iv[2][3] = (iv[2][3] << 1) | (iv[3][0] >> 7);
+ iv[3][0] = (iv[3][0] << 1) | (iv[3][1] >> 7);
+ iv[3][1] = (iv[3][1] << 1) | (iv[3][2] >> 7);
+ iv[3][2] = (iv[3][2] << 1) | (iv[3][3] >> 7);
+ iv[3][3] = (iv[3][3] << 1) | (input[k/8] >> (7-(k&7))) & 1;
+ outBuffer[k/8] ^= (block[0] & 0x80) >> (k & 7);
+ }
+ }
+ break;
+ default:
+ return -1;
+ break;
+ }
+
+ return 128*numBlocks;
+}
+
+int Rijndael::padDecrypt(const UINT8 *input, int inputOctets, UINT8 *outBuffer)
+{
+ int i, numBlocks, padLen;
+ UINT8 block[16];
+ UINT32 iv[4];
+
+ if(m_state != Valid)return RIJNDAEL_NOT_INITIALIZED;
+ if(m_direction != Decrypt)return RIJNDAEL_BAD_DIRECTION;
+
+ if(input == 0 || inputOctets <= 0)return 0;
+
+ if((inputOctets % 16) != 0)return RIJNDAEL_CORRUPTED_DATA;
+
+ numBlocks = inputOctets/16;
+
+ switch(m_mode){
+ case ECB:
+ for (i = numBlocks - 1; i > 0; i--)
+ {
+ decrypt(input, outBuffer);
+ input += 16;
+ outBuffer += 16;
+ }
+
+ decrypt(input, block);
+ padLen = block[15];
+ if (padLen >= 16)return RIJNDAEL_CORRUPTED_DATA;
+ for(i = 16 - padLen; i < 16; i++)
+ {
+ if(block[i] != padLen)return RIJNDAEL_CORRUPTED_DATA;
+ }
+ kvi_memmove(outBuffer, block, 16 - padLen);
+ break;
+ case CBC:
+ kvi_memmove(iv, m_initVector, 16);
+ /* all blocks but last */
+ for (i = numBlocks - 1; i > 0; i--)
+ {
+ decrypt(input, block);
+ ((UINT32*)block)[0] ^= iv[0];
+ ((UINT32*)block)[1] ^= iv[1];
+ ((UINT32*)block)[2] ^= iv[2];
+ ((UINT32*)block)[3] ^= iv[3];
+ kvi_memmove(iv, input, 16);
+ kvi_memmove(outBuffer, block, 16);
+ input += 16;
+ outBuffer += 16;
+ }
+ /* last block */
+ decrypt(input, block);
+ ((UINT32*)block)[0] ^= iv[0];
+ ((UINT32*)block)[1] ^= iv[1];
+ ((UINT32*)block)[2] ^= iv[2];
+ ((UINT32*)block)[3] ^= iv[3];
+ padLen = block[15];
+ if(padLen <= 0 || padLen > 16)return RIJNDAEL_CORRUPTED_DATA;
+ for(i = 16 - padLen; i < 16; i++)
+ {
+ if(block[i] != padLen)return RIJNDAEL_CORRUPTED_DATA;
+ }
+ kvi_memmove(outBuffer, block, 16 - padLen);
+ break;
+
+ default:
+ return -1;
+ break;
+ }
+
+ return 16*numBlocks - padLen;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// ALGORITHM
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+void Rijndael::keySched(UINT8 key[_MAX_KEY_COLUMNS][4])
+{
+ int j,rconpointer = 0;
+
+ // Calculate the necessary round keys
+ // The number of calculations depends on keyBits and blockBits
+ int uKeyColumns = m_uRounds - 6;
+
+ UINT8 tempKey[_MAX_KEY_COLUMNS][4];
+
+ // Copy the input key to the temporary key matrix
+
+ for(j = 0;j < uKeyColumns;j++)
+ {
+ *((UINT32*)(tempKey[j])) = *((UINT32*)(key[j]));
+ }
+
+ unsigned int r = 0;
+ int t = 0;
+
+ // copy values into round key array
+ for(j = 0;(j < uKeyColumns) && (r <= m_uRounds); )
+ {
+ for(;(j < uKeyColumns) && (t < 4); j++, t++)
+ {
+ *((UINT32*)m_expandedKey[r][t]) = *((UINT32*)tempKey[j]);
+ }
+
+
+ if(t == 4)
+ {
+ r++;
+ t = 0;
+ }
+ }
+
+ while(r <= m_uRounds)
+ {
+ tempKey[0][0] ^= S[tempKey[uKeyColumns-1][1]];
+ tempKey[0][1] ^= S[tempKey[uKeyColumns-1][2]];
+ tempKey[0][2] ^= S[tempKey[uKeyColumns-1][3]];
+ tempKey[0][3] ^= S[tempKey[uKeyColumns-1][0]];
+ tempKey[0][0] ^= rcon[rconpointer++];
+
+ if (uKeyColumns != 8)
+ {
+ for(j = 1; j < uKeyColumns; j++)
+ {
+ *((UINT32*)tempKey[j]) ^= *((UINT32*)tempKey[j-1]);
+ }
+ } else {
+ for(j = 1; j < uKeyColumns/2; j++)
+ {
+ *((UINT32*)tempKey[j]) ^= *((UINT32*)tempKey[j-1]);
+ }
+ tempKey[uKeyColumns/2][0] ^= S[tempKey[uKeyColumns/2 - 1][0]];
+ tempKey[uKeyColumns/2][1] ^= S[tempKey[uKeyColumns/2 - 1][1]];
+ tempKey[uKeyColumns/2][2] ^= S[tempKey[uKeyColumns/2 - 1][2]];
+ tempKey[uKeyColumns/2][3] ^= S[tempKey[uKeyColumns/2 - 1][3]];
+ for(j = uKeyColumns/2 + 1; j < uKeyColumns; j++)
+ {
+ *((UINT32*)tempKey[j]) ^= *((UINT32*)tempKey[j-1]);
+ }
+ }
+ for(j = 0; (j < uKeyColumns) && (r <= m_uRounds); )
+ {
+ for(; (j < uKeyColumns) && (t < 4); j++, t++)
+ {
+ *((UINT32*)m_expandedKey[r][t]) = *((UINT32*)tempKey[j]);
+ }
+ if(t == 4)
+ {
+ r++;
+ t = 0;
+ }
+ }
+ }
+}
+
+void Rijndael::keyEncToDec()
+{
+ UINT8 *w;
+
+ for(unsigned int r = 1; r < m_uRounds; r++)
+ {
+ w = m_expandedKey[r][0];
+ *((UINT32*)w) = *((UINT32*)U1[w[0]]) ^ *((UINT32*)U2[w[1]]) ^ *((UINT32*)U3[w[2]]) ^ *((UINT32*)U4[w[3]]);
+ w = m_expandedKey[r][1];
+ *((UINT32*)w) = *((UINT32*)U1[w[0]]) ^ *((UINT32*)U2[w[1]]) ^ *((UINT32*)U3[w[2]]) ^ *((UINT32*)U4[w[3]]);
+ w = m_expandedKey[r][2];
+ *((UINT32*)w) = *((UINT32*)U1[w[0]]) ^ *((UINT32*)U2[w[1]]) ^ *((UINT32*)U3[w[2]]) ^ *((UINT32*)U4[w[3]]);
+ w = m_expandedKey[r][3];
+ *((UINT32*)w) = *((UINT32*)U1[w[0]]) ^ *((UINT32*)U2[w[1]]) ^ *((UINT32*)U3[w[2]]) ^ *((UINT32*)U4[w[3]]);
+ }
+}
+
+void Rijndael::encrypt(const UINT8 a[16], UINT8 b[16])
+{
+ unsigned int r;
+ UINT8 temp[4][4];
+
+ *((UINT32*)temp[0]) = *((UINT32*)(a )) ^ *((UINT32*)m_expandedKey[0][0]);
+ *((UINT32*)temp[1]) = *((UINT32*)(a+ 4)) ^ *((UINT32*)m_expandedKey[0][1]);
+ *((UINT32*)temp[2]) = *((UINT32*)(a+ 8)) ^ *((UINT32*)m_expandedKey[0][2]);
+ *((UINT32*)temp[3]) = *((UINT32*)(a+12)) ^ *((UINT32*)m_expandedKey[0][3]);
+ *((UINT32*)(b )) = *((UINT32*)T1[temp[0][0]])
+ ^ *((UINT32*)T2[temp[1][1]])
+ ^ *((UINT32*)T3[temp[2][2]])
+ ^ *((UINT32*)T4[temp[3][3]]);
+ *((UINT32*)(b + 4)) = *((UINT32*)T1[temp[1][0]])
+ ^ *((UINT32*)T2[temp[2][1]])
+ ^ *((UINT32*)T3[temp[3][2]])
+ ^ *((UINT32*)T4[temp[0][3]]);
+ *((UINT32*)(b + 8)) = *((UINT32*)T1[temp[2][0]])
+ ^ *((UINT32*)T2[temp[3][1]])
+ ^ *((UINT32*)T3[temp[0][2]])
+ ^ *((UINT32*)T4[temp[1][3]]);
+ *((UINT32*)(b +12)) = *((UINT32*)T1[temp[3][0]])
+ ^ *((UINT32*)T2[temp[0][1]])
+ ^ *((UINT32*)T3[temp[1][2]])
+ ^ *((UINT32*)T4[temp[2][3]]);
+ for(r = 1; r < m_uRounds-1; r++)
+ {
+ *((UINT32*)temp[0]) = *((UINT32*)(b )) ^ *((UINT32*)m_expandedKey[r][0]);
+ *((UINT32*)temp[1]) = *((UINT32*)(b+ 4)) ^ *((UINT32*)m_expandedKey[r][1]);
+ *((UINT32*)temp[2]) = *((UINT32*)(b+ 8)) ^ *((UINT32*)m_expandedKey[r][2]);
+ *((UINT32*)temp[3]) = *((UINT32*)(b+12)) ^ *((UINT32*)m_expandedKey[r][3]);
+
+ *((UINT32*)(b )) = *((UINT32*)T1[temp[0][0]])
+ ^ *((UINT32*)T2[temp[1][1]])
+ ^ *((UINT32*)T3[temp[2][2]])
+ ^ *((UINT32*)T4[temp[3][3]]);
+ *((UINT32*)(b + 4)) = *((UINT32*)T1[temp[1][0]])
+ ^ *((UINT32*)T2[temp[2][1]])
+ ^ *((UINT32*)T3[temp[3][2]])
+ ^ *((UINT32*)T4[temp[0][3]]);
+ *((UINT32*)(b + 8)) = *((UINT32*)T1[temp[2][0]])
+ ^ *((UINT32*)T2[temp[3][1]])
+ ^ *((UINT32*)T3[temp[0][2]])
+ ^ *((UINT32*)T4[temp[1][3]]);
+ *((UINT32*)(b +12)) = *((UINT32*)T1[temp[3][0]])
+ ^ *((UINT32*)T2[temp[0][1]])
+ ^ *((UINT32*)T3[temp[1][2]])
+ ^ *((UINT32*)T4[temp[2][3]]);
+ }
+ *((UINT32*)temp[0]) = *((UINT32*)(b )) ^ *((UINT32*)m_expandedKey[m_uRounds-1][0]);
+ *((UINT32*)temp[1]) = *((UINT32*)(b+ 4)) ^ *((UINT32*)m_expandedKey[m_uRounds-1][1]);
+ *((UINT32*)temp[2]) = *((UINT32*)(b+ 8)) ^ *((UINT32*)m_expandedKey[m_uRounds-1][2]);
+ *((UINT32*)temp[3]) = *((UINT32*)(b+12)) ^ *((UINT32*)m_expandedKey[m_uRounds-1][3]);
+ b[ 0] = T1[temp[0][0]][1];
+ b[ 1] = T1[temp[1][1]][1];
+ b[ 2] = T1[temp[2][2]][1];
+ b[ 3] = T1[temp[3][3]][1];
+ b[ 4] = T1[temp[1][0]][1];
+ b[ 5] = T1[temp[2][1]][1];
+ b[ 6] = T1[temp[3][2]][1];
+ b[ 7] = T1[temp[0][3]][1];
+ b[ 8] = T1[temp[2][0]][1];
+ b[ 9] = T1[temp[3][1]][1];
+ b[10] = T1[temp[0][2]][1];
+ b[11] = T1[temp[1][3]][1];
+ b[12] = T1[temp[3][0]][1];
+ b[13] = T1[temp[0][1]][1];
+ b[14] = T1[temp[1][2]][1];
+ b[15] = T1[temp[2][3]][1];
+ *((UINT32*)(b )) ^= *((UINT32*)m_expandedKey[m_uRounds][0]);
+ *((UINT32*)(b+ 4)) ^= *((UINT32*)m_expandedKey[m_uRounds][1]);
+ *((UINT32*)(b+ 8)) ^= *((UINT32*)m_expandedKey[m_uRounds][2]);
+ *((UINT32*)(b+12)) ^= *((UINT32*)m_expandedKey[m_uRounds][3]);
+}
+
+void Rijndael::decrypt(const UINT8 a[16], UINT8 b[16])
+{
+ int r;
+ UINT8 temp[4][4];
+
+ *((UINT32*)temp[0]) = *((UINT32*)(a )) ^ *((UINT32*)m_expandedKey[m_uRounds][0]);
+ *((UINT32*)temp[1]) = *((UINT32*)(a+ 4)) ^ *((UINT32*)m_expandedKey[m_uRounds][1]);
+ *((UINT32*)temp[2]) = *((UINT32*)(a+ 8)) ^ *((UINT32*)m_expandedKey[m_uRounds][2]);
+ *((UINT32*)temp[3]) = *((UINT32*)(a+12)) ^ *((UINT32*)m_expandedKey[m_uRounds][3]);
+
+ *((UINT32*)(b )) = *((UINT32*)T5[temp[0][0]])
+ ^ *((UINT32*)T6[temp[3][1]])
+ ^ *((UINT32*)T7[temp[2][2]])
+ ^ *((UINT32*)T8[temp[1][3]]);
+ *((UINT32*)(b+ 4)) = *((UINT32*)T5[temp[1][0]])
+ ^ *((UINT32*)T6[temp[0][1]])
+ ^ *((UINT32*)T7[temp[3][2]])
+ ^ *((UINT32*)T8[temp[2][3]]);
+ *((UINT32*)(b+ 8)) = *((UINT32*)T5[temp[2][0]])
+ ^ *((UINT32*)T6[temp[1][1]])
+ ^ *((UINT32*)T7[temp[0][2]])
+ ^ *((UINT32*)T8[temp[3][3]]);
+ *((UINT32*)(b+12)) = *((UINT32*)T5[temp[3][0]])
+ ^ *((UINT32*)T6[temp[2][1]])
+ ^ *((UINT32*)T7[temp[1][2]])
+ ^ *((UINT32*)T8[temp[0][3]]);
+ for(r = m_uRounds-1; r > 1; r--)
+ {
+ *((UINT32*)temp[0]) = *((UINT32*)(b )) ^ *((UINT32*)m_expandedKey[r][0]);
+ *((UINT32*)temp[1]) = *((UINT32*)(b+ 4)) ^ *((UINT32*)m_expandedKey[r][1]);
+ *((UINT32*)temp[2]) = *((UINT32*)(b+ 8)) ^ *((UINT32*)m_expandedKey[r][2]);
+ *((UINT32*)temp[3]) = *((UINT32*)(b+12)) ^ *((UINT32*)m_expandedKey[r][3]);
+ *((UINT32*)(b )) = *((UINT32*)T5[temp[0][0]])
+ ^ *((UINT32*)T6[temp[3][1]])
+ ^ *((UINT32*)T7[temp[2][2]])
+ ^ *((UINT32*)T8[temp[1][3]]);
+ *((UINT32*)(b+ 4)) = *((UINT32*)T5[temp[1][0]])
+ ^ *((UINT32*)T6[temp[0][1]])
+ ^ *((UINT32*)T7[temp[3][2]])
+ ^ *((UINT32*)T8[temp[2][3]]);
+ *((UINT32*)(b+ 8)) = *((UINT32*)T5[temp[2][0]])
+ ^ *((UINT32*)T6[temp[1][1]])
+ ^ *((UINT32*)T7[temp[0][2]])
+ ^ *((UINT32*)T8[temp[3][3]]);
+ *((UINT32*)(b+12)) = *((UINT32*)T5[temp[3][0]])
+ ^ *((UINT32*)T6[temp[2][1]])
+ ^ *((UINT32*)T7[temp[1][2]])
+ ^ *((UINT32*)T8[temp[0][3]]);
+ }
+
+ *((UINT32*)temp[0]) = *((UINT32*)(b )) ^ *((UINT32*)m_expandedKey[1][0]);
+ *((UINT32*)temp[1]) = *((UINT32*)(b+ 4)) ^ *((UINT32*)m_expandedKey[1][1]);
+ *((UINT32*)temp[2]) = *((UINT32*)(b+ 8)) ^ *((UINT32*)m_expandedKey[1][2]);
+ *((UINT32*)temp[3]) = *((UINT32*)(b+12)) ^ *((UINT32*)m_expandedKey[1][3]);
+ b[ 0] = S5[temp[0][0]];
+ b[ 1] = S5[temp[3][1]];
+ b[ 2] = S5[temp[2][2]];
+ b[ 3] = S5[temp[1][3]];
+ b[ 4] = S5[temp[1][0]];
+ b[ 5] = S5[temp[0][1]];
+ b[ 6] = S5[temp[3][2]];
+ b[ 7] = S5[temp[2][3]];
+ b[ 8] = S5[temp[2][0]];
+ b[ 9] = S5[temp[1][1]];
+ b[10] = S5[temp[0][2]];
+ b[11] = S5[temp[3][3]];
+ b[12] = S5[temp[3][0]];
+ b[13] = S5[temp[2][1]];
+ b[14] = S5[temp[1][2]];
+ b[15] = S5[temp[0][3]];
+ *((UINT32*)(b )) ^= *((UINT32*)m_expandedKey[0][0]);
+ *((UINT32*)(b+ 4)) ^= *((UINT32*)m_expandedKey[0][1]);
+ *((UINT32*)(b+ 8)) ^= *((UINT32*)m_expandedKey[0][2]);
+ *((UINT32*)(b+12)) ^= *((UINT32*)m_expandedKey[0][3]);
+}
+
+#endif // COMPILE_CRYPT_SUPPORT
diff --git a/src/modules/rijndael/rijndael.h b/src/modules/rijndael/rijndael.h
new file mode 100644
index 00000000..e720df3e
--- /dev/null
+++ b/src/modules/rijndael/rijndael.h
@@ -0,0 +1,153 @@
+#ifndef _RIJNDAEL_H_
+#define _RIJNDAEL_H_
+
+//
+// File : rijndael.h
+// Creation date : Sun Nov 5 2000 15:42:14 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+//
+// Another implementation of the Rijndael cipher.
+// This is intended to be an easily usable library file.
+// Based on the Vincent Rijmen and K.U.Leuven implementation 2.4.
+//
+
+//
+// Original Copyright notice:
+//
+// rijndael-alg-fst.c v2.4 April '2000
+// rijndael-alg-fst.h
+// rijndael-api-fst.c
+// rijndael-api-fst.h
+//
+// Optimised ANSI C code
+//
+// authors: v1.0: Antoon Bosselaers
+// v2.0: Vincent Rijmen, K.U.Leuven
+// v2.3: Paulo Barreto
+// v2.4: Vincent Rijmen, K.U.Leuven
+//
+// This code is placed in the public domain.
+//
+
+//
+// This implementation works on 128 , 192 , 256 bit keys
+// and on 128 bit blocks
+//
+
+//
+// Example of usage:
+//
+// // Input data
+// unsigned char key[32]; // The key
+// initializeYour256BitKey(); // Obviously initialized with sth
+// const unsigned char * plainText = getYourPlainText(); // Your plain text
+// int plainTextLen = strlen(plainText); // Plain text length
+//
+// // Encrypting
+// Rijndael rin;
+// unsigned char output[plainTextLen + 16];
+//
+// rin.init(Rijndael::CBC,Rijndael::Encrypt,key,Rijndael::Key32Bytes);
+// // It is a good idea to check the error code
+// int len = rin.padEncrypt(plainText,len,output);
+// if(len >= 0)useYourEncryptedText();
+// else encryptError(len);
+//
+// // Decrypting: we can reuse the same object
+// unsigned char output2[len];
+// rin.init(Rijndael::ECB,Rijndael::Decrypt,keyMaterial,Rijndael::Key32Bytes));
+// len = rin.padDecrypt(output,len,output2);
+// if(len >= 0)useYourDecryptedText();
+// else decryptError(len);
+//
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_CRYPT_SUPPORT
+
+#define _MAX_KEY_COLUMNS (256/32)
+#define _MAX_ROUNDS 14
+//#define BITSPERBLOCK 128 /* Default number of bits in a cipher block */
+#define MAX_IV_SIZE 16
+
+// We assume that unsigned int is 32 bits long....
+typedef unsigned char UINT8;
+typedef unsigned int UINT32;
+typedef unsigned short UINT16;
+
+#define RIJNDAEL_SUCCESS 0
+#define RIJNDAEL_UNSUPPORTED_MODE -1
+#define RIJNDAEL_UNSUPPORTED_DIRECTION -2
+#define RIJNDAEL_UNSUPPORTED_KEY_LENGTH -3
+#define RIJNDAEL_BAD_KEY -4
+#define RIJNDAEL_NOT_INITIALIZED -5
+#define RIJNDAEL_BAD_DIRECTION -6
+#define RIJNDAEL_CORRUPTED_DATA -7
+
+class Rijndael
+{
+public:
+ enum Direction { Encrypt , Decrypt };
+ enum Mode { ECB , CBC , CFB1 };
+ enum KeyLength { Key16Bytes , Key24Bytes , Key32Bytes };
+
+ Rijndael();
+ ~Rijndael();
+protected:
+ enum State { Valid , Invalid };
+
+ State m_state;
+ Mode m_mode;
+ Direction m_direction;
+ UINT8 m_initVector[MAX_IV_SIZE];
+ UINT32 m_uRounds;
+ UINT8 m_expandedKey[_MAX_ROUNDS+1][4][4];
+public:
+ // Initializes the crypt session
+ // Returns RIJNDAEL_SUCCESS or an error code
+ int init(Mode mode,Direction dir,const UINT8 *key,KeyLength keyLen,UINT8 * initVector = 0);
+ // Input len is in BITS!
+ // Encrypts inputLen / 128 blocks of input and puts it in outBuffer
+ // outBuffer must be at least inputLen / 8 bytes long.
+ // Returns the encrypted buffer length in BITS or an error code < 0 in case of error
+ int blockEncrypt(const UINT8 *input, int inputLen, UINT8 *outBuffer);
+ // Input len is in BYTES!
+ // outBuffer must be at least inputLen + 16 bytes long
+ // Returns the encrypted buffer length in BYTES or an error code < 0 in case of error
+ int padEncrypt(const UINT8 *input, int inputOctets, UINT8 *outBuffer);
+ // Input len is in BITS!
+ // outBuffer must be at least inputLen / 8 bytes long
+ // Returns the decrypted buffer length in BITS and an error code < 0 in case of error
+ int blockDecrypt(const UINT8 *input, int inputLen, UINT8 *outBuffer);
+ // Input len is in BYTES!
+ // outBuffer must be at least inputLen bytes long
+ // Returns the decrypted buffer length in BYTES and an error code < 0 in case of error
+ int padDecrypt(const UINT8 *input, int inputOctets, UINT8 *outBuffer);
+protected:
+ void keySched(UINT8 key[_MAX_KEY_COLUMNS][4]);
+ void keyEncToDec();
+ void encrypt(const UINT8 a[16], UINT8 b[16]);
+ void decrypt(const UINT8 a[16], UINT8 b[16]);
+};
+
+#endif // COMPILE_CRYPT_SUPPORT
+
+#endif // _RIJNDAEL_H_
diff --git a/src/modules/setup/Makefile.am b/src/modules/setup/Makefile.am
new file mode 100644
index 00000000..73e3bcec
--- /dev/null
+++ b/src/modules/setup/Makefile.am
@@ -0,0 +1,26 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkvisetup.la
+
+libkvisetup_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkvisetup_la_SOURCES = libkvisetup.cpp setupwizard.cpp
+libkvisetup_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+noinst_HEADERS= setupwizard.h
+
+#datadir = $(picsdir)
+
+#data_DATA = kvi_dock.png
+
+#EXTRA_DIST = $(data_DATA)
+
+%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
+
+setupwizard.cpp: setupwizard.moc
diff --git a/src/modules/setup/libkvisetup.cpp b/src/modules/setup/libkvisetup.cpp
new file mode 100644
index 00000000..7f5bad25
--- /dev/null
+++ b/src/modules/setup/libkvisetup.cpp
@@ -0,0 +1,158 @@
+//=============================================================================
+//
+// File : libkvisetup.cpp
+// Creation date : Sat Oct 6 02:08:24 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_module.h"
+
+#include "setupwizard.h"
+
+#include <qstring.h>
+#include <qfile.h>
+
+#include "kvi_options.h"
+#include "kvi_defaults.h"
+#include "kvi_app.h"
+#include "kvi_kvs_script.h"
+#include "kvi_kvs_variantlist.h"
+#include "kvi_window.h"
+#include "kvi_theme.h"
+#include "kvi_ircserverdb.h"
+
+// this will be choosen during the setup process
+QString g_szChoosenIncomingDirectory;
+//int g_iThemeToApply = THEME_APPLY_NONE;
+bool bNeedToApplyDefaults;
+unsigned int uPort;
+QString szHost;
+QString szUrl;
+QString szMircServers;
+QString szMircIni;
+
+
+
+
+// this is called by KviApp when no local kvirc directory has been found
+// we have nothing to rely on yet... (settings have not been loaded yet)
+KVIMODULEEXPORTFUNC bool setup_begin()
+{
+ // FIXME: try to guess the user's .kvirc directory
+ // and the preferred nickname from a previous installation
+
+ KviSetupWizard * w = new KviSetupWizard();
+ int retcode = w->exec();
+ delete w;
+ return (retcode == QDialog::Accepted);
+}
+
+
+// this is called just after the first startup
+// all the subsystems are up and running (we even have a nice console
+// to write on if needed).
+// all the options are loaded.
+KVIMODULEEXPORTFUNC void setup_finish()
+{
+ if(bNeedToApplyDefaults)
+ {
+ KVI_OPTION_STRING(KviOption_stringIncomingPath) = g_szChoosenIncomingDirectory;
+ // Reset the quit message and the real name... if they contain the KVIrc version
+ // then probably the user hasn't even edited them.
+ if(KVI_OPTION_STRING(KviOption_stringQuitMessage).find("KVIrc",0,false) != -1)
+ KVI_OPTION_STRING(KviOption_stringQuitMessage) = KVI_DEFAULT_QUIT_MESSAGE;
+ // We deserve to change the user's part message in something nice :)
+ KVI_OPTION_STRING(KviOption_stringPartMessage) = KVI_DEFAULT_PART_MESSAGE;
+
+ // FIXME: Should we also change these ?
+ // #define KVI_DEFAULT_CTCP_USERINFO_REPLY "I'm too lazy to edit this field."
+ // #define KVI_DEFAULT_AWAY_MESSAGE "I'm off to see the wizard."
+
+ // Apply the choosen default theme
+ QString szDir;
+/* switch(g_iThemeToApply)
+ {
+ case THEME_APPLY_HIRES:
+ g_pApp->getGlobalKvircDirectory(szDir,KviApp::Themes,"default.hires");
+ g_pApp->loadTheme(szDir);
+ break;
+ case THEME_APPLY_LORES:
+ g_pApp->getGlobalKvircDirectory(szDir,KviApp::Themes,"default.lores");
+ g_pApp->loadTheme(szDir);
+ break;
+ // default: no theme
+ }*/
+
+ g_pApp->getGlobalKvircDirectory(szDir,KviApp::Themes,"silverirc");
+ KviThemeInfo out;
+ KviTheme::load(szDir,out);
+
+ if(!szMircServers.isEmpty())
+ {
+ g_pIrcServerDataBase->loadFromMircIni(szMircServers,szMircIni,
+ KVI_OPTION_STRINGLIST(KviOption_stringlistRecentServers));
+ g_pApp->saveIrcServerDataBase();
+ }
+
+ g_pApp->loadDefaultScript();
+ if(!szUrl.isEmpty())
+ {
+ KviKvsVariantList * pParams = new KviKvsVariantList();
+ pParams->append(szUrl);
+ KviKvsScript::run("openurl $0",g_pActiveWindow,pParams);
+ delete pParams;
+ KVI_OPTION_BOOL(KviOption_boolShowServersConnectDialogOnStart) = TRUE;
+ } else if(!szHost.isEmpty()) {
+ KviKvsVariantList * pParams = new KviKvsVariantList();
+ pParams->append(szHost);
+ pParams->append((kvs_int_t)uPort);
+ KviKvsScript::run("server $0 $1",g_pActiveWindow,pParams);
+ delete pParams;
+ KVI_OPTION_BOOL(KviOption_boolShowServersConnectDialogOnStart) = TRUE;
+ }
+ }
+}
+
+static bool setup_module_init(KviModule *m)
+{
+ bNeedToApplyDefaults=true;
+ return true;
+}
+
+static bool setup_module_cleanup(KviModule *m)
+{
+ return true;
+}
+
+static bool setup_module_can_unload(KviModule *m)
+{
+ return true; // can be always unloaded...this module does basically nothing
+}
+
+KVIRC_MODULE(
+ "Setup wizard",
+ "1.0.0",
+ "Szymon Stefanek <pragma at kvirc dot net>" ,
+ "First-time-run setup wizard",
+ setup_module_init ,
+ setup_module_can_unload,
+ 0,
+ setup_module_cleanup
+)
diff --git a/src/modules/setup/setupwizard.cpp b/src/modules/setup/setupwizard.cpp
new file mode 100644
index 00000000..5b8c1ff7
--- /dev/null
+++ b/src/modules/setup/setupwizard.cpp
@@ -0,0 +1,1132 @@
+//===============================================================================
+//
+// File : setupwizard.cpp
+// Creation date : Sat Oct 6 02:06:53 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//==============================================================================
+
+bool g_bFoundMirc;
+
+#include "setupwizard.h"
+
+#include "kvi_app.h"
+#include "kvi_locale.h"
+#include "kvi_fileutils.h"
+#include "kvi_defaults.h"
+#include "kvi_msgbox.h"
+#include "kvi_tal_filedialog.h"
+#include "kvi_qstring.h"
+#include "kvi_env.h"
+#include "kvi_options.h"
+#include "kvi_config.h"
+
+#include <kvi_tal_textedit.h>
+#include <qmessagebox.h>
+#include <qdir.h>
+#include <qpushbutton.h>
+#include <qvalidator.h>
+#include <qtextcodec.h>
+#include <qlayout.h>
+#include "kvi_tal_hbox.h"
+
+#ifdef COMPILE_ON_WINDOWS
+ #include <windows.h>
+ #include <winnls.h> // for MultiByteToWideChar
+ #include <objbase.h> // CoCreateInstance , CoInitialize & CO.
+ #include <shlobj.h> // IShellLink IPersistFile & CO.
+#else
+ #include <unistd.h> // for symlink()
+#endif
+
+#ifdef COMPILE_USE_QT4
+ #include <QDesktopWidget>
+#endif
+
+// libkvisetup.cpp
+extern QString g_szChoosenIncomingDirectory;
+//extern int g_iThemeToApply;
+extern bool bNeedToApplyDefaults;
+extern unsigned int uPort;
+extern QString szHost;
+extern QString szUrl;
+extern QString szMircServers;
+extern QString szMircIni;
+
+#ifdef COMPILE_ON_WINDOWS
+ #define KVI_LOCAL_KVIRC_SUBDIRECTORY_NAME "KVIrc"
+#else
+ #define KVI_LOCAL_KVIRC_SUBDIRECTORY_NAME ".kvirc"
+#endif
+
+KviSetupPage::KviSetupPage(KviSetupWizard * w)
+: QWidget(w)
+{
+ QGridLayout * g = new QGridLayout(this);
+
+ //setBackgroundColor(QColor(255,0,0));
+
+ // we need this to set localized text on buttons (see QT doc/ KviTalWizard class)
+ w->KviTalWizard::backButton()->setText(__tr2qs("< &Back"));
+ w->KviTalWizard::nextButton()->setText(__tr2qs("&Next >"));
+ w->KviTalWizard::finishButton()->setText(__tr2qs("Finish"));
+ w->KviTalWizard::cancelButton()->setText(__tr2qs("Cancel"));
+ //w->KviTalWizard::helpButton()->setText(__tr2qs("Help"));
+
+ m_pPixmapLabel = new QLabel(this);
+ g->addWidget(m_pPixmapLabel,0,0);
+
+ m_pPixmapLabel->setPixmap(*(w->m_pLabelPixmap));
+ m_pPixmapLabel->setFixedSize(w->m_pLabelPixmap->size());
+ m_pPixmapLabel->setFrameStyle(QFrame::Sunken | QFrame::StyledPanel);
+ m_pPixmapLabel->setMargin(0);
+
+ g->setSpacing(8);
+ g->setMargin(0);
+
+ m_pVBox = new KviTalVBox(this);
+ m_pVBox->setSpacing(4);
+ m_pVBox->setMargin(0);
+ //m_pVBox->setSizePolicy(QSizePolicy(QSizePolicy::Expanding));
+ //m_pVBox->setBackgroundColor(QColor(0,80,0));
+ //m_pVBox->setMaximumHeight(450);
+ g->addWidget(m_pVBox,0,1);
+
+ g->setColStretch(1,1);
+
+ QLabel * l = new QLabel(m_pVBox);
+ l->setAlignment(Qt::AlignAuto | Qt::AlignTop);
+ /*
+ QString szHeader = "<table border=\"0\" cellpadding=\"4\" cellspacing=\"0\" style=\"margin:0px;padding:0px;\" width=\"100%\"><tr><td bgcolor=\"#303030\">" \
+ "<h1><font color=\"#FFFFFF\">KVIrc " KVI_VERSION "</font></h1>" \
+ "</td></tr></table>";
+ */
+ QString szHeader = "<h1><font color=\"#FFFFFF\">&nbsp;KVIrc " KVI_VERSION "</font></h1>";
+ l->setText(szHeader);
+ l->setFrameStyle(QFrame::Sunken | QFrame::StyledPanel);
+ l->setAlignment(Qt::AlignAuto | Qt::AlignVCenter);
+ l->setMargin(0);
+ l->setBackgroundColor(QColor(48,48,48));
+
+ m_pTextLabel = new QLabel(m_pVBox);
+#ifdef COMPILE_USE_QT4
+ m_pTextLabel->setWordWrap(true);
+#endif
+ m_pTextLabel->setAlignment(Qt::AlignJustify | Qt::AlignTop);
+ m_pVBox->setStretchFactor(m_pTextLabel,1);
+}
+
+KviSetupPage::~KviSetupPage()
+{
+}
+
+
+KviSetupWizard::KviSetupWizard()
+: KviTalWizard(0)
+{
+ setModal(true);
+
+ g_bFoundMirc = false;
+ QString szLabelText;
+
+ QString szImagePath;
+ g_pApp->getGlobalKvircDirectory(szImagePath,KviApp::Pics,"kvi_setup_label.png");
+
+ m_pLabelPixmap = new QPixmap(szImagePath);
+ if(m_pLabelPixmap->isNull())
+ {
+ delete m_pLabelPixmap;
+ m_pLabelPixmap = new QPixmap(250,450);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // Welcome
+
+ m_pWelcome = new KviSetupPage(this);
+
+ // here we go...
+ QString szText = __tr2qs("<p>" \
+ "<h2>Welcome :)</h2>" \
+ "This is your first time running this version of KVIrc.<br>" \
+ "This wizard will guide you through the few steps " \
+ "required to complete the setup.<br><br>" \
+ "If you had a previous version of KVIrc installed, no worries. You will " \
+ "have a chance to preserve the old configuration." \
+ "</p>" \
+ "<p>Click \"<b>Next</b>\" to proceed.</p>");
+
+ m_pWelcome->m_pTextLabel->setText(szText);
+
+ addPage(m_pWelcome,__tr2qs("Welcome to KVIrc"));
+
+ setBackEnabled(m_pWelcome,false);
+ setHelpEnabled(m_pWelcome,false);
+
+
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // License
+#ifndef COMPILE_ON_WINDOWS //it have been already shown by installer
+ KviSetupPage * m_pLicense = new KviSetupPage(this);
+ m_pLicense->m_pTextLabel->setText(__tr2qs( \
+ "<p>All of the files in this distribution are covered by the GPL. " \
+ "In human terms this can be read as follows:<br>" \
+ "<ul>" \
+ "<li><b>KVIrc is free</b>, use it, have fun! <b>:)</b></li>" \
+ "<li>If you use <b>any</b> part of KVIrc in your own project, you <b>must</b> release that project under the same license.</li>" \
+ "</ul></p>" \
+ "<p>The \"legalese\" version of the license is shown in the box below.</p>"));
+
+ KviTalTextEdit * ed = new KviTalTextEdit(m_pLicense->m_pVBox);
+ ed->setReadOnly(true);
+ ed->setWordWrap(KviTalTextEdit::NoWrap);
+ QString szLicense;
+ QString szLicensePath;
+ g_pApp->getGlobalKvircDirectory(szLicensePath,KviApp::License,"EULA");
+ if(!KviFileUtils::loadFile(szLicensePath,szLicense))
+ {
+ szLicense = __tr("Oops... can't find the license file.\n" \
+ "It MUST be included in the distribution...\n" \
+ "Please report to <pragma at kvirc dot net>");
+ }
+ ed->setText(szLicense);
+
+ m_pLicense->m_pVBox->setStretchFactor(ed,1);
+
+ addPage(m_pLicense,__tr2qs("Dreaded License Agreement"));
+
+ setHelpEnabled(m_pLicense,false);
+
+ setCaption(__tr2qs("KVIrc Setup"));
+#else
+ m_pLicense = 0;
+#endif
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // Directories
+
+ m_pDirectory = new KviSetupPage(this);
+
+ m_pDirectory->m_pTextLabel->setText(__tr2qs("<p>Please choose a folder for " \
+ "KVIrc to store its settings and other data, and another for downloaded files. " \
+ "Make sure that you have permission to write to both folders.<br><br>" \
+ "The suggested locations are fine in most cases, so if you don't know what " \
+ "is this about, just click \"<b>Next</b>\".<br><br>" \
+ "If you had a previous version of KVIrc installed, you can choose " \
+ "the existing directory for the settings, and your configuration " \
+ "will be preserved." \
+ "</p>"));
+
+ addPage(m_pDirectory,__tr2qs("Application Folders"));
+
+ QString tmp;
+
+ m_pDirButtonGroup = new KviTalVButtonGroup(__tr2qs("Store configuration in folder"),m_pDirectory->m_pVBox);
+ m_pDirUsePrev = new QRadioButton(__tr2qs("Use settings folder from previous installation"),m_pDirButtonGroup);
+ connect(m_pDirUsePrev,SIGNAL(clicked()),this,SLOT(oldDirClicked()));
+
+ m_pOldPathBox = new KviTalHBox(m_pDirButtonGroup);
+ m_pOldDataPathEdit = new QLineEdit(m_pOldPathBox);
+ connect(m_pOldDataPathEdit,SIGNAL(textChanged ( const QString & )),this,SLOT(oldDataTextChanged ( const QString & )));
+
+ QPushButton * pb = new QPushButton(__tr2qs("&Browse..."),m_pOldPathBox);
+ connect(pb,SIGNAL(clicked()),this,SLOT(chooseOldDataPath()));
+ m_pOldPathBox->setSpacing(3);
+ m_pOldPathBox->setStretchFactor(m_pOldDataPathEdit,1);
+
+ m_pDirUseNew = new QRadioButton(__tr2qs("Use new settings folder"),m_pDirButtonGroup);
+ connect(m_pDirUseNew,SIGNAL(clicked()),this,SLOT(newDirClicked()));
+
+ QLabel* l = new QLabel(m_pDirButtonGroup);
+ l->setText(__tr2qs("Settings folder:"));
+
+ m_pNewPathBox = new KviTalHBox(m_pDirButtonGroup);
+ m_pDataPathEdit = new QLineEdit(m_pNewPathBox);
+
+ pb = new QPushButton(__tr2qs("&Browse..."),m_pNewPathBox);
+ connect(pb,SIGNAL(clicked()),this,SLOT(chooseDataPath()));
+
+ m_pNewPathBox->setSpacing(3);
+ m_pNewPathBox->setStretchFactor(m_pDataPathEdit,1);
+
+#ifdef COMPILE_ON_WINDOWS
+ tmp = QTextCodec::codecForLocale()->toUnicode(getenv( "APPDATA" ));
+ if(tmp.isEmpty())
+ tmp = QDir::homeDirPath();
+#else
+ tmp = QDir::homeDirPath();
+#endif //COMPILE_ON_WINDOWS
+ KviQString::ensureLastCharIs(tmp,KVI_PATH_SEPARATOR_CHAR);
+ tmp.append(KVI_LOCAL_KVIRC_SUBDIRECTORY_NAME);
+ KviFileUtils::adjustFilePath(tmp);
+ m_pDataPathEdit->setText(tmp);
+
+
+
+ l = new QLabel(m_pDirButtonGroup);
+ l->setText(__tr2qs("Download files to folder:"));
+
+
+ m_pNewIncomingBox = new KviTalHBox(m_pDirButtonGroup);
+
+ m_pIncomingPathEdit = new QLineEdit(m_pNewIncomingBox);
+
+ pb = new QPushButton(__tr2qs("&Browse..."),m_pNewIncomingBox);
+ connect(pb,SIGNAL(clicked()),this,SLOT(chooseIncomingPath()));
+
+ m_pNewIncomingBox->setSpacing(3);
+ m_pNewIncomingBox->setStretchFactor(m_pIncomingPathEdit,1);
+
+ tmp = QDir::homeDirPath();
+ KviQString::ensureLastCharIs(tmp,KVI_PATH_SEPARATOR_CHAR);
+ tmp.append(KVI_DEFAULT_INCOMING_SUBDIRECTORY_NAME);
+ KviFileUtils::adjustFilePath(tmp);
+ m_pIncomingPathEdit->setText(tmp);
+
+ m_pDirUseNew->toggle();
+ newDirClicked();
+
+#ifdef COMPILE_ON_WINDOWS
+ m_pDirMakePortable = new QRadioButton(__tr2qs("All settings in shared program folder (portable)")
+ ,m_pDirButtonGroup);
+#endif
+ // Pragma: Unused, takes only space.
+ //m_pDirRestore = new QRadioButton(__tr2qs("Restore from backup archive"),m_pDirButtonGroup);
+ //m_pDirRestore->setEnabled(FALSE);
+
+ //l = new QLabel(m_pDirectory->m_pVBox,"<b> </b>");
+
+ //m_pDirectory->m_pVBox->setStretchFactor(m_pDirectory->m_pTextLabel,1);
+
+ setHelpEnabled(m_pDirectory,false);
+
+ connect(m_pDataPathEdit,SIGNAL(textChanged ( const QString & )),this,SLOT(newDataTextChanged ( const QString & )));
+ connect(m_pIncomingPathEdit,SIGNAL(textChanged ( const QString & )),this,SLOT(newIncomingTextChanged ( const QString & )));
+
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // Identity
+
+ m_pIdentity = new KviSetupPage(this);
+
+ m_pIdentity->m_pTextLabel->setText(__tr2qs("Please choose a Nickname.<br><br>" \
+ "Your nickname is the name that other IRC users will know you by. " \
+ "It can't contain spaces or punctuation. Some IRC networks will shorten your nickname if it is more than 32 characters " \
+ "long.<br><br>"
+ "If in doubt, just enter the first nick that comes to mind. " \
+ "You will be able to change it later in the Identity properties, or with the /NICK command."));
+
+ QString nick;
+ char * nnn = kvi_getenv("USER");
+ if(nnn)nick = nnn;
+ else nick = "newbie";
+ if(nick.isEmpty())nick = "newbie";
+ if(nick == "root")nick = "newbie";
+//m_pIdentity->m_pVBox
+//__tr2qs("Basic Properties")
+ KviTalGroupBox * gbox = new KviTalGroupBox(1,Qt::Horizontal,QString(),m_pIdentity->m_pVBox);
+
+ m_pNickSelector = new KviStringSelector(gbox,__tr2qs("Nickname:"),&(KVI_OPTION_STRING(KviOption_stringNickname1)),true);
+ m_pNickSelector->setMinimumLabelWidth(120);
+
+ QValidator * v = new QRegExpValidator(QRegExp("[^-0-9 ][^ ]*"),gbox);
+ m_pNickSelector->setValidator(v);
+
+ QString szOptionalCtcpUserInfo = __tr2qs("This field is optional and will appear as part of the CTCP USERINFO reply.");
+ QString szCenterBegin("<center>");
+ QString szCenterEnd("</center>");
+ QString szTrailing = "<br><br>" + szOptionalCtcpUserInfo + szCenterEnd;
+
+ gbox = new KviTalGroupBox(1,Qt::Horizontal,__tr2qs("Profile"),m_pIdentity->m_pVBox);
+
+ m_pRealNameSelector = new KviStringSelector(gbox,__tr2qs("Real name:"),&(KVI_OPTION_STRING(KviOption_stringRealname)),true);
+ m_pRealNameSelector->setMinimumLabelWidth(120);
+
+ KviTalHBox* hb = new KviTalHBox(gbox);
+ hb->setSpacing(4);
+
+ l = new QLabel(__tr2qs("Age:"),hb);
+ l->setMinimumWidth(120);
+
+ m_pAgeCombo = new QComboBox(hb);
+
+ m_pAgeCombo->insertItem(__tr2qs("Unspecified"));
+ unsigned int i;
+ for(i=1;i<120;i++)
+ {
+ QString tmp;
+ tmp.setNum(i);
+ m_pAgeCombo->insertItem(tmp);
+ }
+
+ bool bOk;
+ i = KVI_OPTION_STRING(KviOption_stringCtcpUserInfoAge).toUInt(&bOk);
+ if(!bOk)i = 0;
+ if(i > 120)i = 120;
+ m_pAgeCombo->setCurrentItem(i);
+
+ hb->setStretchFactor(m_pAgeCombo,1);
+
+
+ hb = new KviTalHBox(gbox);
+ hb->setSpacing(4);
+
+ l = new QLabel(__tr2qs("Gender:"),hb);
+ l->setMinimumWidth(120);
+
+ m_pGenderCombo = new QComboBox(hb);
+
+ m_pGenderCombo->insertItem(__tr2qs("Unspecified"));
+ m_pGenderCombo->insertItem(__tr2qs("Female"));
+ m_pGenderCombo->insertItem(__tr2qs("Male"));
+
+ if(KviQString::equalCI(KVI_OPTION_STRING(KviOption_stringCtcpUserInfoGender),"Male"))
+ m_pGenderCombo->setCurrentItem(2);
+ else if(KviQString::equalCI(KVI_OPTION_STRING(KviOption_stringCtcpUserInfoGender),"Female"))
+ m_pGenderCombo->setCurrentItem(1);
+ else
+ m_pGenderCombo->setCurrentItem(0);
+
+ hb->setStretchFactor(m_pGenderCombo,1);
+
+ m_pLocationSelector = new KviStringSelector(gbox,__tr2qs("Location:"),&(KVI_OPTION_STRING(KviOption_stringCtcpUserInfoLocation)),true);
+ m_pLocationSelector->setMinimumLabelWidth(120);
+
+ m_pLanguagesSelector = new KviStringSelector(gbox,__tr2qs("Languages:"),&(KVI_OPTION_STRING(KviOption_stringCtcpUserInfoLanguages)),true);
+ m_pLanguagesSelector->setMinimumLabelWidth(120);
+
+ //m_pOtherInfoSelector = new KviStringSelector(gbox,__tr2qs("Other:"),&(KVI_OPTION_STRING(KviOption_stringCtcpUserInfoOther)),true);
+ //m_pOtherInfoSelector->setMinimumLabelWidth(120);
+
+ addPage(m_pIdentity,__tr2qs("Identity"));
+
+ //l = new QLabel(m_pIdentity->m_pVBox,"<b> </b>");
+
+ setHelpEnabled(m_pIdentity,false);
+
+
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // Default theme
+/* m_pTheme = new KviSetupPage(this);
+ m_pTheme->m_pTextLabel->setText(__tr2qs( \
+ "<p>Here you can choose the default appearance of KVIrc.<br><br>" \
+ "The Fancy Theme uses icons, a transparent background and a lot of colors. " \
+ "The Minimalist Theme is designed for low-color displays " \
+ "or for \"console\" extremists; it's more or less white text on a black background.<br><br>" \
+ "If you had a previous version of KVIrc installed, you can choose to not apply any theme " \
+ "in order to preserve your current visual settings.<br><br>" \
+ "If you don't know what to choose, just use the default.</p>"));
+
+ m_pThemeButtonGroup = new KviTalVButtonGroup(m_pTheme->m_pVBox);
+
+ KviTalHBox* pThemesHb = new KviTalHBox(m_pThemeButtonGroup);
+
+ KviTalVBox* pThemesVb = new KviTalVBox(pThemesHb);
+
+ QString szThemeImagePath;
+ g_pApp->getGlobalKvircDirectory(szThemeImagePath,KviApp::Pics,"kvi_setup_theme_hires.png");
+
+ QPixmap* pHiResPixmap = new QPixmap(szThemeImagePath);
+ if(pHiResPixmap->isNull())
+ {
+ delete pHiResPixmap;
+ pHiResPixmap= new QPixmap(250,200);
+ }
+
+ QLabel* pPixmapLabelHiRes = new QLabel(pThemesVb);
+
+ pPixmapLabelHiRes->setPixmap(*pHiResPixmap);
+ pPixmapLabelHiRes->setFixedSize(pHiResPixmap->size());
+ pPixmapLabelHiRes->setFrameStyle(QFrame::Sunken | QFrame::StyledPanel);
+ pPixmapLabelHiRes->setMargin(0);
+
+ m_pThemeHiRes = new QRadioButton(__tr2qs("&Fancy Theme"),pThemesVb);
+
+ pThemesVb = new KviTalVBox(pThemesHb);
+ g_pApp->getGlobalKvircDirectory(szThemeImagePath,KviApp::Pics,"kvi_setup_theme_lowres.png");
+ QPixmap* pLowResPixmap = new QPixmap(szThemeImagePath);
+ if(pLowResPixmap->isNull())
+ {
+ delete pLowResPixmap;
+ pLowResPixmap= new QPixmap(250,200);
+ }
+
+ QLabel* pPixmapLabelLowRes = new QLabel(pThemesVb);
+
+ pPixmapLabelLowRes->setPixmap(*pLowResPixmap);
+ pPixmapLabelLowRes->setFixedSize(pLowResPixmap->size());
+ pPixmapLabelLowRes->setFrameStyle(QFrame::Sunken | QFrame::StyledPanel);
+ pPixmapLabelLowRes->setMargin(0);
+
+ m_pThemeLoRes = new QRadioButton(__tr2qs("&Minimalist Theme"),pThemesVb);
+ m_pThemeNone = new QRadioButton(__tr2qs("&Don't apply any theme"),m_pThemeButtonGroup);
+ m_pThemeButtonGroup->insert(m_pThemeHiRes);
+ m_pThemeButtonGroup->insert(m_pThemeLoRes);
+
+ m_pThemeHiRes->setChecked(true);
+
+ addPage(m_pTheme,__tr2qs("Default Theme"));
+
+ setHelpEnabled(m_pTheme,false);*/
+
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // Desktop integration
+
+ m_pDesktopIntegration = new KviSetupPage(this);
+
+ szText = __tr2qs( \
+ "<p>" \
+ "Here you can choose how much KVIrc will integrate with " \
+ "your system." \
+ "<br><br>" \
+ "The default settings are fine for most users so if " \
+ "you're in doubt just click \"<b>Next</b>\" and go to the next screen." \
+ "</p>");
+
+ m_pDesktopIntegration->m_pTextLabel->setText(szText);
+
+ addPage(m_pDesktopIntegration,__tr2qs("Desktop Integration"));
+
+#ifdef COMPILE_ON_WINDOWS
+ m_pCreateUrlHandlers = new QCheckBox(__tr2qs("Make KVIrc default IRC client"),m_pDesktopIntegration->m_pVBox);
+ m_pCreateUrlHandlers->setChecked(true);
+#endif
+#ifdef COMPILE_KDE_SUPPORT
+ m_pCreateDesktopShortcut = new QCheckBox(__tr2qs("Create desktop shortcut"),m_pDesktopIntegration->m_pVBox);
+ m_pCreateDesktopShortcut->setChecked(true);
+#endif
+
+#ifdef COMPILE_ON_WINDOWS
+ m_pUseMircServerList = new QRadioButton(__tr2qs("Import server list from mIRC"),m_pDesktopIntegration->m_pVBox);
+ m_pUseMircServerList->setEnabled(false);
+#endif
+
+ setHelpEnabled(m_pDesktopIntegration,false);
+
+ /*
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // Server config
+ m_pServers = new KviSetupPage(this);
+
+ m_pServers->m_pTextLabel->setText(__tr2qs( \
+ "Now you should specify an IRC server, to be connected to it"));
+
+
+ m_pServersButtonGroup = new KviTalVButtonGroup(__tr2qs("Choose a server to connect"),m_pServers->m_pVBox);
+
+ m_pServersChooseFromList = new QRadioButton(__tr2qs("Choose from built-in server list"),m_pServersButtonGroup);
+
+ m_pServersSpecifyManually = new QRadioButton(__tr2qs("Specify server manually"),m_pServersButtonGroup);
+ hb = new KviTalHBox(m_pServersButtonGroup);
+
+ m_uServerPort=6667;
+ m_pServerHostSelector = new KviStringSelector(hb,__tr2qs("Server:"),&m_szServerHost,true);
+ m_pServerPortSelector = new KviUIntSelector(hb,__tr2qs("Port:"),&m_uServerPort,1,65536,6667,true,false);
+
+
+ m_pServersOpenIrcUrl = new QRadioButton(__tr2qs("Open irc:// or irc6:// URL"),m_pServersButtonGroup);
+ m_szServerUrl="irc://";
+ m_pServerUrlSelector = new KviStringSelector(m_pServersButtonGroup,__tr2qs("URL:"),&m_szServerUrl,true);
+
+ */
+/*
+ m_pServersLoadConfig = new QRadioButton(__tr2qs("Use server config"),m_pServersButtonGroup);
+ m_pServersLoadConfig->setEnabled(FALSE);
+ m_pServerConfigSelector = new KviFileSelector(m_pServersButtonGroup,__tr2qs("Config file:"),&m_szServerConfigFile,true);
+ m_pServerConfigSelector->setEnabled(FALSE);
+*/
+ /*
+ m_pServersChooseFromList->toggle();
+ addPage(m_pServers,__tr2qs("Choose a server to connect"));
+ */
+ setFinishEnabled(m_pDesktopIntegration,true);
+ setHelpEnabled(m_pDesktopIntegration,false);
+
+ // Preconfigured values
+#ifdef COMPILE_ON_WINDOWS
+ QString szTmp;
+ g_pApp->getGlobalKvircDirectory(szTmp,KviApp::Config,"preinstalled.kvc");
+ if(KviFileUtils::fileExists(szTmp))
+ {
+ KviConfig cfg(szTmp,KviConfig::Read);
+ cfg.setGroup("Setup");
+ if(cfg.readBoolEntry("hideServerList",FALSE))
+ {
+ //setPageEnabled(m_pServers,false);
+ //setFinishEnabled(m_pIdentity,true);
+ KVI_OPTION_BOOL(KviOption_boolShowChannelsJoinOnIrc) = false;
+ KVI_OPTION_BOOL(KviOption_boolShowServersConnectDialogOnStart) = false;
+ }
+ int iDir;
+ iDir=cfg.readIntEntry("settingsDir",-1);
+ if(iDir>0) {
+ switch(iDir)
+ {
+ case 1:
+ m_pDirUseNew->toggle();
+ setPageEnabled(m_pDirectory,false);
+ break;
+ case 2:
+ m_pDirMakePortable->toggle();
+ setPageEnabled(m_pDirectory,false);
+ break;
+ }
+ }
+ }
+
+ //mIRC import
+ #define QUERY_BUFFER 2048
+ char* buffer;
+ DWORD len = QUERY_BUFFER;
+ buffer = (char*)malloc(len*sizeof(char));
+ HKEY hKey;
+ QString szMircDir;
+
+ if(RegOpenKeyEx(HKEY_CLASSES_ROOT,"ChatFile\\DefaultIcon",0,KEY_READ,&hKey) == ERROR_SUCCESS )
+ {
+ if( RegQueryValueEx( hKey,0,0,0,(LPBYTE)buffer,&len) == ERROR_SUCCESS)
+ {
+ szMircDir = QString::fromLocal8Bit(buffer,len);
+
+ szMircDir.remove('"');
+ QString szMircFile = KviFileUtils::extractFileName(szMircDir);
+ szMircFile = szMircFile.left(szMircFile.length()-4); //cut off ".exe"
+ szMircDir = KviFileUtils::extractFilePath(szMircDir);
+
+ szMircIni = szMircDir + "/" + szMircFile + ".ini";
+
+ if(!KviFileUtils::fileExists(szMircIni))
+ szMircIni = szMircDir + "/mirc.ini";
+
+ if(!KviFileUtils::fileExists(szMircIni))
+ szMircIni = szMircDir + "/pirc.ini";
+
+ if(KviFileUtils::fileExists(szMircIni)){
+ KviConfig cfg(szMircIni,KviConfig::Read,true);
+ if(cfg.hasGroup("mirc"))
+ {
+ g_bFoundMirc = true;
+ cfg.setGroup("mirc");
+ m_pNickSelector->setText(cfg.readQStringEntry("nick",KVI_OPTION_STRING(KviOption_stringNickname1)));
+ m_pRealNameSelector->setText(cfg.readQStringEntry("user",KVI_OPTION_STRING(KviOption_stringRealname)));
+ KVI_OPTION_STRING(KviOption_stringNickname2) =
+ cfg.readQStringEntry("anick",KVI_OPTION_STRING(KviOption_stringNickname2));
+ KVI_OPTION_STRING(KviOption_stringUsername) =
+ cfg.readQStringEntry("email",KVI_OPTION_STRING(KviOption_stringUsername)).section('@',0,0);
+
+ if(cfg.hasGroup("files"))
+ {
+ m_szMircServerIniFile = cfg.readQStringEntry("servers","servers.ini");
+ m_szMircServerIniFile.prepend('/');
+ m_szMircServerIniFile.prepend(szMircDir);
+ if(KviFileUtils::fileExists(m_szMircServerIniFile))
+ {
+ m_pUseMircServerList->setEnabled(true);
+ m_pUseMircServerList->setChecked(true);
+ }
+ }
+ //KviMessageBox::information(__tr2qs("Setup found existing mIRC installation. It will try to import "
+ // "some of mIRC settings and serverlist. If you don't want to do it, unselect import in setup pages"));
+ }
+ }
+ }
+ }
+ free(buffer);
+
+#endif
+
+ //setMinimumSize(630,450);
+}
+
+
+KviSetupWizard::~KviSetupWizard()
+{
+ delete m_pLabelPixmap;
+}
+
+void KviSetupWizard::showEvent(QShowEvent *e)
+{
+ int w = QApplication::desktop()->width();
+ int h = QApplication::desktop()->height();
+
+ int ww = width();
+ int wh = height();
+
+ if(w < 800)
+ {
+ // 640x480
+ if(ww < 630)ww = 630;
+ } else {
+ if(ww < 770)ww = 770;
+ }
+
+ //wh = sizeHint().height();
+
+ setGeometry((w - ww) / 2,(h - wh) / 2,ww,wh);
+
+ KviTalWizard::showEvent(e);
+}
+
+void KviSetupWizard::oldDirClicked()
+{
+ m_pOldPathBox->setEnabled(true);
+ m_pNewPathBox->setEnabled(false);
+ m_pNewIncomingBox->setEnabled(false);
+
+ if(m_pIdentity) setPageEnabled(m_pIdentity,false);
+// if(m_pTheme) setPageEnabled(m_pTheme,false);
+ if(m_pServers) setPageEnabled(m_pServers,false);
+
+ if(m_pOldDataPathEdit->text().isEmpty()) setNextEnabled(m_pDirectory,false);
+ else setNextEnabled(m_pDirectory,true);
+}
+
+void KviSetupWizard::oldDataTextChanged ( const QString & str)
+{
+ setNextEnabled(m_pDirectory,!str.isEmpty());
+}
+
+void KviSetupWizard::newDataTextChanged ( const QString & str)
+{
+ setNextEnabled(m_pDirectory,!str.isEmpty() && !m_pIncomingPathEdit->text().isEmpty());
+}
+
+void KviSetupWizard::newIncomingTextChanged ( const QString & str)
+{
+ setNextEnabled(m_pDirectory,!str.isEmpty() && !m_pDataPathEdit->text().isEmpty());
+}
+
+void KviSetupWizard::newDirClicked()
+{
+ m_pOldPathBox->setEnabled(false);
+ m_pNewPathBox->setEnabled(true);
+ m_pNewIncomingBox->setEnabled(true);
+
+ if(m_pIdentity) setPageEnabled(m_pIdentity,true);
+// if(m_pTheme) setPageEnabled(m_pTheme,true);
+ if(m_pServers) setPageEnabled(m_pServers,true);
+
+ if(m_pDataPathEdit->text().isEmpty() || m_pIncomingPathEdit->text().isEmpty()) setNextEnabled(m_pDirectory,false);
+ else setNextEnabled(m_pDirectory,true);
+}
+void KviSetupWizard::chooseOldDataPath()
+{
+ QString szBuffer = KviTalFileDialog::getExistingDirectoryPath(m_pDataPathEdit->text(),__tr2qs("Choose an Old Configuration Folder - KVIrc Setup"),0);
+ if(!szBuffer.isEmpty())
+ {
+ KviQString::ensureLastCharIs(szBuffer,KVI_PATH_SEPARATOR_CHAR);
+ if(!g_pApp->checkLocalKvircDirectory(szBuffer))
+ {
+ if(
+ QMessageBox::question(
+ this,
+ __tr2qs("Do not overwrite folder? - KVIrc"),
+ tr("A folder %1 seems to be not a valid KVIrc settings folder."
+ "Do you want to use it anyway?")
+ .arg( szBuffer ),
+ __tr2qs("&Yes"), __tr2qs("&No"),
+ QString::null, 0, 1 ) == 0
+ ) {
+ m_pOldDataPathEdit->setText(szBuffer);
+ }
+ } else {
+ m_pOldDataPathEdit->setText(szBuffer);
+ }
+ }
+}
+
+void KviSetupWizard::chooseDataPath()
+{
+ QString szBuffer = KviTalFileDialog::getExistingDirectoryPath(m_pDataPathEdit->text(),__tr2qs("Choose a Configuration Folder - KVIrc Setup"),0);
+ if(!szBuffer.isEmpty())
+ {
+ KviQString::ensureLastCharIs(szBuffer,KVI_PATH_SEPARATOR_CHAR);
+ m_pDataPathEdit->setText(szBuffer);
+ }
+}
+
+void KviSetupWizard::chooseIncomingPath()
+{
+ //QString szBuffer = QFileDialog::getExistingDirectory(m_pIncomingPathEdit->text(),0,0,__tr2qs("Choose the download folder"));
+ QString szBuffer = KviTalFileDialog::getExistingDirectoryPath(m_pIncomingPathEdit->text(),__tr2qs("Choose a Download Folder - KVIrc Setup"),0);
+ if(!szBuffer.isEmpty())
+ {
+ m_pIncomingPathEdit->setText(szBuffer);
+ }
+}
+
+
+void KviSetupWizard::makeLink()
+{
+#ifdef COMPILE_ON_WINDOWS
+ // Let's make a link on the desktop :)
+ // You need this horrible snippet of code to create a shortcut!!!!
+ //
+ // you have to:
+ // - dig in the registry ,
+ // - trigger the entire COM subsystem
+ // - bring up a couple of OLE interfaces....
+ // - use some obscure functions like MultiByteToWideChar
+ // - and the finally drop the entire OLE+COM interface in the garbadge
+ // ...
+ // Isn't this horrible ? (compared to symlink()!)
+ //
+
+ // Well..let's go (please note that we don't handle most possible errors!
+ // otherwise there would be 150 lines for a stupid symlink!)
+
+ HKEY hCU;
+ DWORD lpType;
+ ULONG ulSize = MAX_PATH;
+ char szLink[MAX_PATH];
+
+ // Dig in the registry looking up the Desktop path
+ if(RegOpenKeyEx(HKEY_CURRENT_USER,
+ "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders",
+ 0,KEY_QUERY_VALUE,&hCU) == ERROR_SUCCESS)
+ {
+ RegQueryValueEx(hCU,"Desktop",NULL,&lpType,
+ (unsigned char *)&szLink,&ulSize);
+ RegCloseKey(hCU);
+ }
+
+ // Build our paths
+ QString szLinkTarget = szLink;
+ szLinkTarget.append("\\kvirc.lnk");
+
+ QString szKvircExec = g_pApp->m_szGlobalKvircDir;
+ szKvircExec.append("\\kvirc.exe");
+
+ // Trigger a horrible machinery
+ CoInitialize(NULL); // we need COM+OLE
+
+ // Fiddle with an obscure shell interface
+ IShellLink* psl;
+
+ // Get a pointer to the IShellLink interface: this is kinda ugly :)
+ if(CoCreateInstance(CLSID_ShellLink,NULL,CLSCTX_INPROC_SERVER,
+ IID_IShellLink,(void **)&psl) == S_OK)
+ {
+ // just for fun , lookup another shell interface
+
+ IPersistFile* ppf;
+
+ // Query IShellLink for the IPersistFile interface for
+ // saving the shell link in persistent storage.
+ if(psl->QueryInterface(IID_IPersistFile,(void **)&ppf) == S_OK)
+ {
+ WORD wsz[MAX_PATH];
+ // Set the path to the shell link target.
+ psl->SetPath(QTextCodec::codecForLocale()->fromUnicode(szKvircExec).data());
+ // Set the description of the shell link.
+ psl->SetDescription("kvirc");
+ // Ensure string is ANSI.
+ MultiByteToWideChar(CP_ACP,0,QTextCodec::codecForLocale()->fromUnicode(szLinkTarget).data(),-1,(LPWSTR)wsz,MAX_PATH);
+ // Save the link via the IPersistFile::Save method.
+ ppf->Save((LPCOLESTR)wsz,true);
+ ppf->Release();
+ }
+ psl->Release();
+ }
+ // And throw OLE & Co. in the garbadge
+ CoUninitialize();
+#endif //COMPILE_ON_WINDOWS
+
+#ifdef COMPILE_KDE_SUPPORT
+ QString tmp = QDir::homeDirPath();
+ KviQString::ensureLastCharIs(tmp,KVI_PATH_SEPARATOR_CHAR);
+ tmp.append("Desktop");
+ KviQString::ensureLastCharIs(tmp,KVI_PATH_SEPARATOR_CHAR);
+ tmp.append("kvirc.desktop");
+
+ QString contents = "[Desktop Entry]\n" \
+ "GenericName=IRC Client\n" \
+ "Comment=Connect to Internet Relay Chat\n" \
+ "Exec=kvirc -m %u\n" \
+ "Icon=kvirc\n" \
+ "MapNotify=true\n" \
+ "Name=KVIrc 3\n" \
+ "Terminal=false\n" \
+ "Type=Application\n" \
+ "X-KDE-SubstituteUID=false\n";
+
+ KviFileUtils::writeFile(tmp,contents,false);
+#endif //COMPILE_KDE_SUPPORT
+
+}
+
+void KviSetupWizard::setUrlHandlers()
+{
+#ifdef COMPILE_ON_WINDOWS
+ QString szReg = "REGEDIT4\r\n" \
+ "\r\n" \
+ "[HKEY_CLASSES_ROOT\\irc]\r\n" \
+ "@=\"URL:IRC Protocol\"\r\n" \
+ "\"IRC Protocol\"=\"http://www.kvirc.net/\"\r\n" \
+ "\"EditFlags\"=hex:02,00,00,00\r\n" \
+ "\"URL Protocol\"=""\r\n" \
+ "\r\n" \
+ "[HKEY_CLASSES_ROOT\\irc\\DefaultIcon]\r\n" \
+ "@=\"\\\"@KVIRCEXECUTABLE@\\\"\"\r\n" \
+ "\r\n" \
+ "[HKEY_CLASSES_ROOT\\irc\\shell]\r\n" \
+ "@=\"\"\r\n" \
+ "\r\n" \
+ "[HKEY_CLASSES_ROOT\\irc\\shell\\open]\r\n" \
+ "\"EditFlags\"=hex:01,00,00,00\r\n" \
+ "\r\n" \
+ "[HKEY_CLASSES_ROOT\\irc\\shell\\open\\command]\r\n" \
+ "@=\"\\\"@KVIRCEXECUTABLE@\\\" %1\"\r\n" \
+ "\r\n" \
+ "[HKEY_CLASSES_ROOT\\irc6]\r\n" \
+ "@=\"URL:IRC6 Protocol\"\r\n" \
+ "\"IRC6 Protocol\"=\"http://www.kvirc.net/\"\r\n" \
+ "\"EditFlags\"=hex:02,00,00,00\r\n" \
+ "\"URL Protocol\"=""\r\n" \
+ "\r\n" \
+ "[HKEY_CLASSES_ROOT\\irc6\\DefaultIcon]\r\n" \
+ "@=\"\\\"@KVIRCEXECUTABLE@\\\"\"\r\n" \
+ "\r\n" \
+ "[HKEY_CLASSES_ROOT\\irc6\\shell]\r\n" \
+ "@=\"\"\r\n" \
+ "\r\n" \
+ "[HKEY_CLASSES_ROOT\\irc6\\shell\\open]\r\n" \
+ "\"EditFlags\"=hex:01,00,00,00\r\n" \
+ "\r\n" \
+ "[HKEY_CLASSES_ROOT\\irc6\\shell\\open\\command]\r\n" \
+ "@=\"\\\"@KVIRCEXECUTABLE@\\\" %1\"\r\n";
+
+ QString szKvircExec = g_pApp->m_szGlobalKvircDir;
+ szKvircExec.append("\\kvirc.exe");
+ szKvircExec.replace("\\","\\\\");
+
+ szReg.replace("@KVIRCEXECUTABLE@",QTextCodec::codecForLocale()->fromUnicode(szKvircExec));
+
+ QString szRegFile = g_pApp->m_szGlobalKvircDir;
+ szRegFile.append("\\kvirc.reg");
+
+ KviFileUtils::writeFile(szRegFile,szReg,false);
+
+ QString szCmd = "regedit /S \"";
+ szCmd += szRegFile;
+ szCmd += "\"";
+
+ WinExec(QTextCodec::codecForLocale()->fromUnicode(szCmd).data(),SW_SHOW);
+#endif
+}
+
+void KviSetupWizard::reject()
+{
+ if(QMessageBox::warning(this,__tr2qs("Abort Setup - KVIrc Setup"),
+ __tr2qs("You have chosen to abort the setup.<br>KVIrc cannot run until you complete this procedure.<br><br>Do you really wish to abort?"),
+ QMessageBox::Yes,QMessageBox::No|QMessageBox::Default|QMessageBox::Escape) != QMessageBox::Yes)return;
+
+ KviTalWizard::reject();
+}
+
+void KviSetupWizard::accept()
+{
+ QString szDir;
+
+ if(m_pDirUsePrev->isOn())
+ {
+ bNeedToApplyDefaults=false;
+ g_pApp->m_szLocalKvircDir = m_pOldDataPathEdit->text();
+ } else {
+ bNeedToApplyDefaults=true;
+ if(m_pDirUseNew->isOn()) {
+ szDir = m_pDataPathEdit->text();
+ }
+#ifdef COMPILE_ON_WINDOWS
+ else { //portable
+ szDir = g_pApp->applicationDirPath()+KVI_PATH_SEPARATOR_CHAR+"Settings";
+ }
+#endif
+
+ KviFileUtils::adjustFilePath(szDir);
+ KviQString::ensureLastCharIs(szDir,KVI_PATH_SEPARATOR_CHAR);
+ if(!KviFileUtils::directoryExists(szDir))
+ {
+ if(!KviFileUtils::makeDir(szDir))
+ {
+ KviMessageBox::warning(__tr("Cannot create directory %s.\n" \
+ "You may not have write permission " \
+ "for that path. Please go back and choose another directory."));
+ setCurrentPage(m_pDirectory);
+ return;
+ }
+ } /*else {
+ kvi_infoBox(__tr("Kvirc setup"),
+ __tr("The directory '%s' already exists.\n" \
+ "(maybe from a previous Kvirc installation)\n"\
+ "If you experience any problems try deleting the old directory:\n" \
+ "the setup program will be started automatically again."),szDir.ptr());
+ }*/
+
+ g_pApp->m_szLocalKvircDir = szDir;
+ KviFileUtils::adjustFilePath(g_pApp->m_szLocalKvircDir);
+
+ if(m_pDirUseNew->isOn()) {
+ szDir = m_pIncomingPathEdit->text();
+ }
+#ifdef COMPILE_ON_WINDOWS
+ else { //portable
+ szDir = g_pApp->applicationDirPath()+KVI_PATH_SEPARATOR_CHAR+"Downloads";
+ }
+#endif
+
+ KviFileUtils::adjustFilePath(szDir);
+ if(!KviFileUtils::directoryExists(szDir))
+ {
+ if(!KviFileUtils::makeDir(szDir))
+ {
+ KviMessageBox::warning(__tr("Cannot create directory %s.\n" \
+ "You may not have write permission " \
+ "for that path. Please go back and choose another directory."));
+ setCurrentPage(m_pDirectory);
+ return;
+ }
+ }
+
+ g_szChoosenIncomingDirectory = szDir;
+
+#ifndef COMPILE_ON_WINDOWS
+ // Make local->global link
+ QString localPath = QString("%1/global").arg(g_pApp->m_szLocalKvircDir);
+ unlink(QTextCodec::codecForLocale()->fromUnicode(localPath).data());
+ symlink(QTextCodec::codecForLocale()->fromUnicode(g_pApp->m_szGlobalKvircDir).data(),QTextCodec::codecForLocale()->fromUnicode(localPath).data());
+#endif
+
+#ifdef COMPILE_KDE_SUPPORT
+ if(m_pCreateDesktopShortcut->isChecked())
+ makeLink();
+#endif
+
+#ifdef COMPILE_ON_WINDOWS
+ if(m_pCreateUrlHandlers->isChecked())
+ setUrlHandlers();
+#endif
+
+/* if(m_pTheme)
+ {
+ if(m_pThemeButtonGroup->selected() == m_pThemeHiRes)
+ {
+ g_iThemeToApply = THEME_APPLY_HIRES;
+ } else if(m_pThemeButtonGroup->selected() == m_pThemeLoRes)
+ {
+ g_iThemeToApply = THEME_APPLY_LORES;
+ } else {
+ g_iThemeToApply = THEME_APPLY_NONE;
+ }
+ }
+*/
+ if(m_pIdentity)
+ {
+ m_pNickSelector->commit();
+ m_pRealNameSelector->commit();
+ m_pLocationSelector->commit();
+ m_pLanguagesSelector->commit();
+ //m_pOtherInfoSelector->commit();
+
+ KVI_OPTION_STRING(KviOption_stringNickname1).stripWhiteSpace();
+ KVI_OPTION_STRING(KviOption_stringNickname1).replace(" ","");
+
+ if(KVI_OPTION_STRING(KviOption_stringNickname1).length() > 32)
+ {
+ QString tmp = KVI_OPTION_STRING(KviOption_stringNickname1).left(32);
+ KVI_OPTION_STRING(KviOption_stringNickname1) = tmp;
+ }
+
+ if(KVI_OPTION_STRING(KviOption_stringNickname1).isEmpty())KVI_OPTION_STRING(KviOption_stringNickname1) = "newbie";
+
+ QString szNickPart;
+ if(KVI_OPTION_STRING(KviOption_stringNickname1).length() < 31)
+ {
+ szNickPart = KVI_OPTION_STRING(KviOption_stringNickname1);
+ } else {
+ szNickPart = KVI_OPTION_STRING(KviOption_stringNickname1).left(30);
+ }
+
+ QString alt = szNickPart;
+ alt.prepend("|"); // <-- this is an erroneous nickname on IrcNet :/
+ alt.append("|");
+ if(!g_bFoundMirc)
+ KVI_OPTION_STRING(KviOption_stringNickname2) = alt;
+ alt = szNickPart;
+ alt.prepend("_");
+ alt.append("_");
+ KVI_OPTION_STRING(KviOption_stringNickname3) = alt;
+ alt = szNickPart;
+ alt.append("2");
+ KVI_OPTION_STRING(KviOption_stringNickname4) = alt;
+
+ int i = m_pAgeCombo->currentItem();
+ if(i < 0)i = 0;
+ if(i > 120)i = 120;
+ if(i <= 0)KVI_OPTION_STRING(KviOption_stringCtcpUserInfoAge) = "";
+ else KVI_OPTION_STRING(KviOption_stringCtcpUserInfoAge).setNum(i);
+
+ switch(m_pGenderCombo->currentItem())
+ {
+ case 1:
+ // this should be in english
+ KVI_OPTION_STRING(KviOption_stringCtcpUserInfoGender) = "Female";
+ break;
+ case 2:
+ // this should be in english
+ KVI_OPTION_STRING(KviOption_stringCtcpUserInfoGender) = "Male";
+ break;
+ default:
+ KVI_OPTION_STRING(KviOption_stringCtcpUserInfoGender) = "";
+ break;
+ }
+ /*
+ m_pServerHostSelector->commit();
+ m_pServerUrlSelector->commit();
+ //m_pServerConfigSelector->commit();
+ m_pServerPortSelector->commit();
+
+ if(m_pServersSpecifyManually->isOn())
+ {
+ KVI_OPTION_BOOL(KviOption_boolShowServersConnectDialogOnStart) = FALSE;
+ szHost = m_szServerHost;
+ uPort=m_uServerPort;
+ } else if(m_pServersOpenIrcUrl->isOn())
+ {
+ KVI_OPTION_BOOL(KviOption_boolShowServersConnectDialogOnStart) = FALSE;
+ szUrl=m_szServerUrl;
+ }
+ */
+#ifdef COMPILE_ON_WINDOWS
+ if(m_pUseMircServerList->isEnabled() && m_pUseMircServerList->isOn())
+ szMircServers = m_szMircServerIniFile;
+#endif
+ }
+ }
+#ifdef COMPILE_ON_WINDOWS
+ if(m_pDirMakePortable->isOn())
+ {
+ KviFileUtils::writeFile(g_pApp->applicationDirPath()+KVI_PATH_SEPARATOR_CHAR+"portable","true");
+ } else {
+#endif
+ g_pApp->saveKvircDirectory();
+#ifdef COMPILE_ON_WINDOWS
+ }
+#endif
+ KviTalWizard::accept();
+}
+
+#include "setupwizard.moc"
diff --git a/src/modules/setup/setupwizard.h b/src/modules/setup/setupwizard.h
new file mode 100644
index 00000000..2492007a
--- /dev/null
+++ b/src/modules/setup/setupwizard.h
@@ -0,0 +1,164 @@
+#ifndef _SETUPWIZARD_H_
+#define _SETUPWIZARD_H_
+//=============================================================================
+//
+// File : setupwizard.h
+// Creation date : Sat Oct 6 02:06:51 2001 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+
+#include <kvi_tal_wizard.h>
+#include "kvi_tal_vbox.h"
+#include "kvi_tal_hbox.h"
+#include "kvi_tal_groupbox.h"
+#include <qlabel.h>
+#include <qpixmap.h>
+#include <qlineedit.h>
+#ifdef COMPILE_USE_QT4
+#include <q3buttongroup.h>
+#define KviTalVButtonGroup Q3VButtonGroup
+#else
+ #include <qvbuttongroup.h>
+#define KviTalVButtonGroup QVButtonGroup
+#endif
+#include <qradiobutton.h>
+#include <qcombobox.h>
+#include <qcheckbox.h>
+
+#include "kvi_settings.h"
+#include "kvi_string.h"
+#include "kvi_selectors.h"
+
+class KviSetupWizard;
+
+class KviSetupPage : public QWidget
+{
+ Q_OBJECT
+public:
+ KviSetupPage(KviSetupWizard * w);
+ ~KviSetupPage();
+public:
+ KviTalVBox * m_pVBox;
+ QLabel * m_pPixmapLabel;
+ QLabel * m_pTextLabel;
+
+};
+
+
+#define THEME_APPLY_NONE 0
+#define THEME_APPLY_HIRES 1
+#define THEME_APPLY_LORES 2
+
+class KviSetupWizard : public KviTalWizard
+{
+ Q_OBJECT
+public:
+ KviSetupWizard();
+ ~KviSetupWizard();
+public:
+ QPixmap * m_pLabelPixmap;
+
+ KviSetupPage * m_pWelcome;
+ KviSetupPage * m_pLicense;
+ KviSetupPage * m_pDirectory;
+ KviSetupPage * m_pIdentity;
+// KviSetupPage * m_pTheme;
+ KviSetupPage * m_pDesktopIntegration;
+ KviSetupPage * m_pServers;
+
+ // Theme
+ KviTalVButtonGroup * m_pThemeButtonGroup;
+
+ QRadioButton * m_pThemeHiRes;
+ QRadioButton * m_pThemeLoRes;
+ QRadioButton * m_pThemeNone;
+
+ // Welcome
+ QCheckBox * m_pCreateUrlHandlers;
+ QCheckBox * m_pCreateDesktopShortcut;
+
+ //Dir
+ QLineEdit * m_pDataPathEdit;
+ QLineEdit * m_pIncomingPathEdit;
+ KviTalVButtonGroup * m_pDirButtonGroup;
+ QRadioButton * m_pDirUsePrev;
+ QRadioButton * m_pDirUseNew;
+#ifdef COMPILE_ON_WINDOWS
+ QRadioButton * m_pDirMakePortable;
+#endif
+ //QRadioButton * m_pDirRestore;
+ QLineEdit * m_pOldDataPathEdit;
+ KviTalHBox * m_pOldPathBox;
+ KviTalHBox * m_pNewPathBox;
+ KviTalHBox * m_pNewIncomingBox;
+
+ //Identify
+ QComboBox * m_pAgeCombo;
+ QComboBox * m_pGenderCombo;
+
+ KviStringSelector * m_pNickSelector;
+ KviStringSelector * m_pRealNameSelector;
+ KviStringSelector * m_pLocationSelector;
+ KviStringSelector * m_pLanguagesSelector;
+ //KviStringSelector * m_pOtherInfoSelector;
+
+ //Servers
+ //KviTalVButtonGroup * m_pServersButtonGroup;
+ //QRadioButton * m_pServersChooseFromList;
+ //QRadioButton * m_pServersSpecifyManually;
+ //QRadioButton * m_pServersOpenIrcUrl;
+ //QRadioButton * m_pServersLoadConfig;
+#ifdef COMPILE_ON_WINDOWS
+ QString m_szMircServerIniFile;
+ QRadioButton * m_pUseMircServerList;
+#endif
+
+ QString m_szServerConfigFile;
+ QString m_szServerUrl;
+ QString m_szServerHost;
+ unsigned int m_uServerPort;
+
+ KviStringSelector * m_pServerHostSelector;
+ KviStringSelector * m_pServerUrlSelector;
+ //KviFileSelector * m_pServerConfigSelector;
+ KviUIntSelector *m_pServerPortSelector;
+
+protected:
+ void makeLink();
+ void setUrlHandlers();
+ virtual void showEvent(QShowEvent *e);
+public slots:
+ void chooseOldDataPath();
+ void chooseDataPath();
+ void chooseIncomingPath();
+ virtual void accept();
+ virtual void reject();
+
+ void oldDirClicked();
+ void newDirClicked();
+
+ void oldDataTextChanged ( const QString & );
+ void newDataTextChanged ( const QString & );
+ void newIncomingTextChanged ( const QString & );
+};
+
+
+#endif //_SETUPWIZARD_H_
diff --git a/src/modules/sharedfile/Makefile.am b/src/modules/sharedfile/Makefile.am
new file mode 100644
index 00000000..5c4ace3b
--- /dev/null
+++ b/src/modules/sharedfile/Makefile.am
@@ -0,0 +1,18 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkvisharedfile.la
+
+libkvisharedfile_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkvisharedfile_la_SOURCES = libkvisharedfile.cpp
+libkvisharedfile_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+#noinst_HEADERS= sharedfilewindow.h
+
+m_%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
diff --git a/src/modules/sharedfile/libkvisharedfile.cpp b/src/modules/sharedfile/libkvisharedfile.cpp
new file mode 100644
index 00000000..93959f77
--- /dev/null
+++ b/src/modules/sharedfile/libkvisharedfile.cpp
@@ -0,0 +1,281 @@
+//=============================================================================
+//
+// File : libkvisharedfile.cpp (orig : libkvioffer.cpp)
+// Creation date : Wed Sep 27 2000 20:59:02 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_module.h"
+
+#include "kvi_sharedfiles.h"
+#include "kvi_ircmask.h"
+#include "kvi_fileutils.h"
+#include "kvi_locale.h"
+
+#include "kvi_out.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_window.h"
+#include "kvi_frame.h"
+
+
+#include <time.h>
+#include "kvi_pointerhashtable.h"
+
+extern KVIRC_API KviSharedFilesManager * g_pSharedFilesManager;
+
+
+/*
+ @doc: sharedfile.add
+ @type:
+ command
+ @title:
+ sharedfile.add
+ @keyterms:
+ trading files by dcc
+ @short:
+ Adds a file sharedfile
+ @syntax:
+ sharedfile.add [-t=<timeout:integer>] [-n=<visible name>] <filename> [user_mask]
+ @switches:
+ !sw: -t=<timeout> | --timeout=<timeout>
+ Specified the timeout after that the share will be automatically removed
+ !sw: -n=<visible name> | --name=<visible name>
+ Explicitly specifies the visible name of the share
+ @description:
+ Adds <filename> to the list of the active shared files.
+ The users will be able to request the file via [cmd]dcc.get[/cmd].
+ If [user_mask] is specified , the access to the file is limited
+ to the users that match this mask, otherwise the mask will
+ be automatically set to '*!*@*'.[br]
+ If the 't' switch is used, the sharedfile will be removed after
+ <timeout> seconds. If the 'n' switch is used, the sharedfile
+ will be visible to the oter users as <visible name> instead
+ of the real <filename> (stripped of the leading path).
+ <filename> must be an absolute path.
+ @seealso:
+ [cmd]sharedfile.remove[/cmd], [cmd]sharedfile.list[/cmd],
+ [cmd]dcc.get[/cmd]
+*/
+
+static bool sharedfile_kvs_cmd_add(KviKvsModuleCommandCall * c)
+{
+ QString szFileName,szUserMask;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("filename",KVS_PT_NONEMPTYSTRING,0,szFileName)
+ KVSM_PARAMETER("user_mask",KVS_PT_NONEMPTYSTRING,KVS_PF_OPTIONAL,szUserMask)
+ KVSM_PARAMETERS_END(c)
+
+ if(!KviFileUtils::isReadable(szFileName))
+ {
+ c->warning(__tr2qs_ctx("The file '%Q' is not readable","sharedfile"),&szFileName);
+ return true;
+ }
+
+ if(szUserMask.isEmpty())szUserMask="*!*@*";
+ KviIrcMask u(szUserMask);
+
+ QString szm;
+ u.mask(szm);
+
+ kvs_int_t timeout = 0;
+
+ if(KviKvsVariant * v = c->switches()->find('t',"timeout"))
+ {
+ if(!v->asInteger(timeout))
+ {
+ c->warning(__tr2qs_ctx("Invalid timeout, ignoring","sharedfile"));
+ timeout = 0;
+ }
+ }
+
+ QString szVisibleName = szFileName;
+ KviQString::cutToLast(szVisibleName,'/');
+
+ if(KviKvsVariant * n = c->switches()->find('n',"name"))
+ {
+ QString tmp;
+ n->asString(tmp);
+ if(tmp.isEmpty())
+ {
+ c->warning(__tr2qs_ctx("Invalid visible name: using default","sharedfile"));
+ } else szVisibleName = tmp;
+ }
+
+ if(!g_pSharedFilesManager->addSharedFile(szVisibleName,szFileName,szUserMask,timeout))
+ {
+ c->warning(__tr2qs_ctx("Ops..failed to add the sharedfile...","sharedfile"));
+ }
+
+ return true;
+}
+
+
+/*
+ @doc: sharedfile.remove
+ @type:
+ command
+ @title:
+ sharedfile.remove
+ @keyterms:
+ trading files by dcc
+ @short:
+ Removes a shared file
+ @syntax:
+ sharedfile.remove <visible name:string> <user mask:string> [filesize:integer]
+ @description:
+ Removes the shared file that matches <visible name> and <user mask>.
+ If [filesize] is specified, then it must be matched by the entry
+ to be removed.
+ @seealso:
+ [cmd]sharedfile.add[/cmd], [cmd]sharedfile.list[/cmd], [cmd]sharedfile.clear[/cmd]
+*/
+
+static bool sharedfile_kvs_cmd_remove(KviKvsModuleCommandCall * c)
+{
+ QString szVisibleName,szUserMask;
+ kvs_uint_t uSize;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("visible_name",KVS_PT_NONEMPTYSTRING,0,szVisibleName)
+ KVSM_PARAMETER("user_mask",KVS_PT_NONEMPTYSTRING,0,szUserMask)
+ KVSM_PARAMETER("filesize",KVS_PT_UINT,KVS_PF_OPTIONAL,uSize)
+ KVSM_PARAMETERS_END(c)
+
+ if(!g_pSharedFilesManager->removeSharedFile(szVisibleName,szUserMask,uSize))
+ c->warning(__tr2qs_ctx("No sharedfile with visible name '%Q' and user mask '%Q'","sharedfile"),&szVisibleName,&szUserMask);
+
+ return true;
+}
+
+
+
+/*
+ @doc: sharedfile.clear
+ @type:
+ command
+ @title:
+ sharedfile.clear
+ @keyterms:
+ trading files by dcc, shared files
+ @short:
+ Clears the shared files list
+ @syntax:
+ sharedfile.clear
+ @description:
+ Clears the shared files list
+ @seealso:
+ [cmd]sharedfile.add[/cmd], [cmd]sharedfile.list[/cmd], [cmd]sharedfile.remove[/cmd]
+*/
+
+static bool sharedfile_kvs_cmd_clear(KviKvsModuleCommandCall * c)
+{
+ g_pSharedFilesManager->clear();
+ return true;
+}
+
+
+/*
+ @doc: sharedfile.list
+ @type:
+ command
+ @title:
+ sharedfile.list
+ @keyterms:
+ trading files by dcc
+ @short:
+ Lists the active file sharedfile
+ @syntax:
+ sharedfile.list
+ @description:
+ Lists the active file sharedfile.
+ @seealso:
+ [cmd]sharedfile.add[/cmd], [cmd]sharedfile.remove[/cmd]
+*/
+
+static bool sharedfile_kvs_cmd_list(KviKvsModuleCommandCall * c)
+{
+ KviPointerHashTableIterator<QString,KviSharedFileList> it(*(g_pSharedFilesManager->sharedFileListDict()));
+
+ int idx = 0;
+
+ while(KviSharedFileList * l = it.current())
+ {
+ for(KviSharedFile * o = l->first();o;o = l->next())
+ {
+ c->window()->output(KVI_OUT_NONE,"%c%d. %s",
+ KVI_TEXT_BOLD,idx + 1,it.currentKey().utf8().data());
+ c->window()->output(KVI_OUT_NONE,__tr2qs_ctx(" File: %s (%u bytes)","sharedfile"),
+ o->absFilePath().utf8().data(),o->fileSize());
+ c->window()->output(KVI_OUT_NONE,__tr2qs_ctx(" Mask: %s","sharedfile"),
+ o->userMask().utf8().data());
+ if(o->expireTime() > 0)
+ {
+ int secs = ((int)(o->expireTime())) - ((int)(time(0)));
+ int hour = secs / 3600;
+ secs = secs % 3600;
+ int mins = secs / 60;
+ secs = secs % 60;
+ c->window()->output(KVI_OUT_NONE,__tr2qs_ctx(" Expires in %d hours %d minutes %d seconds","sharedfile"),
+ hour,mins,secs);
+ }
+ ++idx;
+ }
+ ++it;
+ }
+
+//#warning "FIND A BETTER KVI_OUT_*"
+
+ if(idx == 0)c->window()->outputNoFmt(KVI_OUT_NONE,__tr2qs_ctx("No active file sharedfile","sharedfile"));
+ else c->window()->output(KVI_OUT_NONE,__tr2qs_ctx("Total: %d sharedfile","sharedfile"),idx);
+
+ return true;
+}
+
+
+static bool sharedfile_module_init(KviModule * m)
+{
+
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"add",sharedfile_kvs_cmd_add);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"remove",sharedfile_kvs_cmd_remove);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"list",sharedfile_kvs_cmd_list);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"clear",sharedfile_kvs_cmd_clear);
+
+ return true;
+}
+
+static bool sharedfile_module_can_unload(KviModule *m)
+{
+ return true;
+}
+
+static bool sharedfile_module_cleanup(KviModule *m)
+{
+ return true;
+}
+
+KVIRC_MODULE(
+ "Offer", // module name
+ "1.0.0", // module version
+ "Copyright (C) 2000-2003 Szymon Stefanek (pragma at kvirc dot net)", // author & (C)
+ "User interface to the file sharing system",
+ sharedfile_module_init,
+ sharedfile_module_can_unload,
+ 0,
+ sharedfile_module_cleanup
+)
diff --git a/src/modules/sharedfileswindow/Makefile.am b/src/modules/sharedfileswindow/Makefile.am
new file mode 100644
index 00000000..f43e1e67
--- /dev/null
+++ b/src/modules/sharedfileswindow/Makefile.am
@@ -0,0 +1,22 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+SUBDIRS = caps
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkvisharedfileswindow.la
+
+libkvisharedfileswindow_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkvisharedfileswindow_la_SOURCES = libkvisharedfileswindow.cpp sharedfileswindow.cpp
+libkvisharedfileswindow_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+noinst_HEADERS= sharedfileswindow.h
+
+m_%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
+
+sharedfileswindow.cpp: m_sharedfileswindow.moc
diff --git a/src/modules/sharedfileswindow/caps/Makefile.am b/src/modules/sharedfileswindow/caps/Makefile.am
new file mode 100644
index 00000000..bc03ac24
--- /dev/null
+++ b/src/modules/sharedfileswindow/caps/Makefile.am
@@ -0,0 +1,9 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+tmpdir = $(pluglibdir)/caps/tool/
+
+tmp_DATA= sharedfileswindow
+
+EXTRA_DIST = $(tmp_DATA)
diff --git a/src/modules/sharedfileswindow/caps/sharedfileswindow b/src/modules/sharedfileswindow/caps/sharedfileswindow
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/modules/sharedfileswindow/caps/sharedfileswindow
diff --git a/src/modules/sharedfileswindow/libkvisharedfileswindow.cpp b/src/modules/sharedfileswindow/libkvisharedfileswindow.cpp
new file mode 100644
index 00000000..a7cab111
--- /dev/null
+++ b/src/modules/sharedfileswindow/libkvisharedfileswindow.cpp
@@ -0,0 +1,158 @@
+//==================================================================================
+//
+// File : libkvisharedfileswindow.cpp
+// Creation date : Mon Apr 21 2003 23:14:12 CEST by Szymon Stefanek
+//
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//==================================================================================
+
+#include "kvi_module.h"
+
+
+#include "sharedfileswindow.h"
+
+#include "kvi_app.h"
+#include "kvi_frame.h"
+#include "kvi_window.h"
+#include "kvi_locale.h"
+#include "kvi_iconmanager.h"
+
+#include <qsplitter.h>
+
+#define KVI_SHARED_FILES_WINDOW_EXTENSION_NAME "Shared files window extension"
+
+KviSharedFilesWindow * g_pSharedFilesWindow = 0;
+
+static KviModuleExtension * sharedfileswindow_extension_alloc(KviModuleExtensionAllocStruct * s)
+{
+ bool bCreateMinimized = false;
+ bool bNoRaise = false;
+
+ if(!g_pSharedFilesWindow)
+ {
+ if(s->pParams)
+ {
+ if(QVariant * v = s->pParams->find("bCreateMinimized"))
+ {
+ if(v->isValid())
+ {
+ if(v->type() == QVariant::Bool)
+ {
+ bCreateMinimized = v->toBool();
+ }
+ }
+ }
+ }
+
+ g_pSharedFilesWindow = new KviSharedFilesWindow(s->pDescriptor,g_pFrame);
+ g_pFrame->addWindow(g_pSharedFilesWindow,!bCreateMinimized);
+ if(bCreateMinimized)g_pSharedFilesWindow->minimize();
+ return g_pSharedFilesWindow;
+ }
+
+ if(s->pParams)
+ {
+ if(QVariant * v = s->pParams->find("bNoRaise"))
+ {
+ if(v)
+ {
+ if(v->isValid() && v->type() == QVariant::Bool)
+ bNoRaise = v->toBool();
+ }
+ }
+ }
+
+ if(!bNoRaise)g_pSharedFilesWindow->delayedAutoRaise();
+ return g_pSharedFilesWindow;
+}
+
+
+/*
+ @doc: sharedfileswindow.open
+ @type:
+ command
+ @title:
+ sharedfileswindow.open
+ @short:
+ Opens the shared files window
+ @syntax:
+ sharedfileswindow.open [-m] [-n]
+ @switches:
+ !sw: -m
+ Causes the window to be created as minimized
+ !sw: -n
+ Causes the window to be not raised if already open
+ @description:
+ Opens the shared files window
+*/
+
+static bool sharedfileswindow_kvs_cmd_open(KviKvsModuleCommandCall * c)
+{
+ KviModuleExtensionDescriptor * d = c->module()->findExtensionDescriptor("tool",KVI_SHARED_FILES_WINDOW_EXTENSION_NAME);
+ if(d)
+ {
+ KviPointerHashTable<QString,QVariant> dict(17,true);
+ dict.setAutoDelete(true);
+ dict.replace("bCreateMinimized",new QVariant(c->hasSwitch('m',"minimized")));
+ dict.replace("bNoRaise",new QVariant(c->hasSwitch('n',"noraise")));
+
+ d->allocate(c->window(),&dict,0);
+ } else {
+ c->warning("Ops.. internal error");
+ }
+ return true;
+}
+
+static bool sharedfileswindow_module_init(KviModule * m)
+{
+ KviModuleExtensionDescriptor * d = m->registerExtension("tool",
+ KVI_SHARED_FILES_WINDOW_EXTENSION_NAME,
+ __tr2qs_ctx("Manage S&hared Files","sharedfileswindow"),
+ sharedfileswindow_extension_alloc);
+
+ if(d)d->setIcon(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_SHAREDFILES)));
+
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"open",sharedfileswindow_kvs_cmd_open);
+ return true;
+}
+
+static bool sharedfileswindow_module_cleanup(KviModule *m)
+{
+ if(g_pSharedFilesWindow)
+ {
+ delete g_pSharedFilesWindow;
+ g_pSharedFilesWindow = 0;
+ }
+ return true;
+}
+
+static bool sharedfileswindow_module_can_unload(KviModule *m)
+{
+ return (!g_pSharedFilesWindow);
+}
+
+KVIRC_MODULE(
+ "SharedFilesWindow",
+ "1.0.0",
+ "Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot net)",
+ "Shared files window extension",
+ sharedfileswindow_module_init,
+ sharedfileswindow_module_can_unload,
+ 0,
+ sharedfileswindow_module_cleanup
+)
diff --git a/src/modules/sharedfileswindow/sharedfileswindow.cpp b/src/modules/sharedfileswindow/sharedfileswindow.cpp
new file mode 100644
index 00000000..aa851684
--- /dev/null
+++ b/src/modules/sharedfileswindow/sharedfileswindow.cpp
@@ -0,0 +1,742 @@
+//==================================================================================
+//
+// File : sharedfileswindow.cpp
+// Creation date : Mon Apr 21 2003 23:14:12 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2001 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the linkss of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) 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.
+//
+//==================================================================================
+
+#include "sharedfileswindow.h"
+
+#include "kvi_debug.h"
+#include "kvi_iconmanager.h"
+#include "kvi_ircview.h"
+#include "kvi_out.h"
+#include "kvi_options.h"
+#include "kvi_locale.h"
+#include "kvi_out.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_themedlabel.h"
+#include "kvi_input.h"
+#include "kvi_filedialog.h"
+#include "kvi_styled_controls.h"
+
+#include <qdatetimeedit.h>
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qpushbutton.h>
+#include <qsplitter.h>
+#include "kvi_tal_hbox.h"
+#include "kvi_tal_vbox.h"
+#include <qlayout.h>
+#include <qcheckbox.h>
+#include <qmessagebox.h>
+#include <qfileinfo.h>
+
+extern KviSharedFilesWindow * g_pSharedFilesWindow;
+extern KVIRC_API KviSharedFilesManager * g_pSharedFilesManager;
+
+KviSharedFileEditDialog::KviSharedFileEditDialog(QWidget * par,KviSharedFile * f)
+: QDialog(par,"shared_file_editor",true)
+{
+ QGridLayout * g = new QGridLayout(this,1,1,11,6);
+
+ setCaption(__tr2qs_ctx("Edit Shared File - KVIrc","sharedfileswindow"));
+
+ QLabel * l = new QLabel(__tr2qs_ctx("Share name:","sharedfileswindow"),this);
+ g->addWidget(l, 0, 0 );
+
+ m_pShareNameEdit = new QLineEdit(this);
+ g->addMultiCellWidget( m_pShareNameEdit, 0, 0, 1, 3 );
+
+ l = new QLabel(__tr2qs_ctx("File path:","sharedfileswindow"),this);
+ g->addWidget(l, 1, 0 );
+
+ m_pFilePathEdit = new QLineEdit(this);
+ g->addMultiCellWidget( m_pFilePathEdit, 1, 1, 1, 2 );
+
+ m_pBrowseButton = new QPushButton(__tr2qs_ctx("&Browse...","sharedfileswindow"),this);
+ g->addWidget( m_pBrowseButton, 1, 3 );
+ connect(m_pBrowseButton,SIGNAL(clicked()),this,SLOT(browse()));
+
+ l = new QLabel(__tr2qs_ctx("User mask:","sharedfileswindow"),this);
+ g->addWidget(l, 2, 0 );
+
+ m_pUserMaskEdit = new QLineEdit(this);
+ g->addMultiCellWidget( m_pUserMaskEdit, 2, 2, 1, 3 );
+
+ m_pExpireCheckBox = new KviStyledCheckBox(__tr2qs_ctx("Expire at:","sharedfileswindow"),this);
+ g->addWidget(m_pExpireCheckBox,3,0);
+
+ m_pExpireDateTimeEdit = new QDateTimeEdit(this);
+ g->addMultiCellWidget(m_pExpireDateTimeEdit, 3, 3, 1, 3 );
+
+ connect(m_pExpireCheckBox,SIGNAL(toggled(bool)),m_pExpireDateTimeEdit,SLOT(setEnabled(bool)));
+
+ QPushButton * pb;
+
+ pb = new QPushButton(__tr2qs_ctx("&OK","sharedfileswindow"),this);
+ connect(pb,SIGNAL(clicked()),this,SLOT(okClicked()));
+ pb->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_ACCEPT)));
+ g->addWidget(pb,5,2);
+ pb = new QPushButton(__tr2qs_ctx("Cancel","sharedfileswindow"),this);
+ connect(pb,SIGNAL(clicked()),this,SLOT(reject()));
+ pb->setIconSet(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_DISCARD)));
+ g->addWidget(pb,5,3);
+
+ g->setRowStretch(4,1);
+ g->setColStretch(0,1);
+
+ if(f)
+ {
+ m_pShareNameEdit->setText(f->name());
+ m_pFilePathEdit->setText(f->absFilePath());
+ m_pUserMaskEdit->setText(f->userMask());
+ QDateTime dt;
+ dt.setTime_t(f->expireTime());
+ m_pExpireDateTimeEdit->setDateTime(dt);
+ m_pExpireCheckBox->setChecked(f->expires());
+ m_pExpireDateTimeEdit->setEnabled(f->expires());
+ } else {
+ m_pExpireCheckBox->setChecked(false);
+ m_pExpireDateTimeEdit->setDateTime(QDateTime::currentDateTime());
+ m_pExpireDateTimeEdit->setEnabled(false);
+ }
+
+}
+
+KviSharedFileEditDialog::~KviSharedFileEditDialog()
+{
+
+}
+
+void KviSharedFileEditDialog::browse()
+{
+ QString szBuf;
+ QString szTxt = m_pFilePathEdit->text();
+ if(!KviFileDialog::askForOpenFileName(szBuf,__tr2qs("Choose the file to share"),szTxt))return;
+ m_pFilePathEdit->setText(szBuf);
+}
+
+KviSharedFile * KviSharedFileEditDialog::getResult()
+{
+ QString szName = m_pShareNameEdit->text();
+ QString szPath = m_pFilePathEdit->text();
+ QString szMask = m_pUserMaskEdit->text();
+ QDateTime dt = m_pExpireDateTimeEdit->dateTime();
+ bool bExpires = m_pExpireCheckBox->isChecked();
+ QFileInfo f(szPath);
+ return new KviSharedFile(szName,szPath,szMask,bExpires ? dt.toTime_t() : (time_t)0,f.size());
+}
+
+void KviSharedFileEditDialog::okClicked()
+{
+ QString szName = m_pShareNameEdit->text();
+ QString szPath = m_pFilePathEdit->text();
+ QDateTime dt = m_pExpireDateTimeEdit->dateTime();
+ bool bExpires = m_pExpireCheckBox->isChecked();
+ if(bExpires && (dt <= QDateTime::currentDateTime()))
+ {
+ QMessageBox::warning(this,__tr2qs_ctx("Invalid expire time","sharedfileswindow"),
+ __tr2qs_ctx("The expire date/time is in the past: please either remove the \"expires\"" \
+ "check mark or specify a expire date/time in the future","sharedfileswindow"),
+ __tr2qs_ctx("OK","sharedfileswindow"));
+ return;
+ }
+
+ if(szName.isEmpty())
+ {
+ QMessageBox::warning(this,__tr2qs_ctx("Invalid share name","sharedfileswindow"),
+ __tr2qs_ctx("The share name can't be empty, please correct it","sharedfileswindow"),
+ __tr2qs_ctx("OK","sharedfileswindow"));
+ return;
+ }
+
+ QFileInfo f(szPath);
+ if(!(f.exists() && f.isFile() && f.isReadable()))
+ {
+ QMessageBox::warning(this,__tr2qs_ctx("Can't open the file","sharedfileswindow"),
+ __tr2qs_ctx("The file doesn't exist or it is not readable, please check the path","sharedfileswindow"),
+ __tr2qs_ctx("OK","sharedfileswindow"));
+ return;
+ }
+
+ accept();
+}
+
+
+KviSharedFilesListViewItem::KviSharedFilesListViewItem(KviTalListView * lv,KviSharedFile * f)
+: KviTalListViewItem(lv,f->name())
+{
+ setText(1,f->absFilePath());
+ setText(2,f->userMask());
+ if(f->expires())
+ {
+ QDateTime dt;
+ dt.setTime_t(f->expireTime());
+ setText(3,dt.toString());
+ } else {
+ setText(3,__tr2qs_ctx("Never","sharedfileswindow"));
+ }
+ m_pSharedFilePointer = f;
+}
+
+KviSharedFilesListViewItem::~KviSharedFilesListViewItem()
+{
+}
+
+
+KviSharedFilesWindow::KviSharedFilesWindow(KviModuleExtensionDescriptor * d,KviFrame * lpFrm)
+: KviWindow(KVI_WINDOW_TYPE_TOOL,lpFrm,"shared files window",0) , KviModuleExtension(d)
+{
+ g_pSharedFilesWindow = this;
+#ifdef COMPILE_USE_QT4
+ m_pSplitter = new QSplitter(Qt::Horizontal,this,"splitter");
+#else
+ m_pSplitter = new QSplitter(QSplitter::Horizontal,this,"splitter");
+#endif
+
+ KviTalVBox * vbox = new KviTalVBox(m_pSplitter);
+
+ m_pListView = new KviTalListView(vbox);
+ //m_pListView->header()->hide();
+ m_pListView->setAllColumnsShowFocus(true);
+ m_pListView->addColumn(__tr2qs_ctx("Name","sharedfileswindow"),200);
+ m_pListView->addColumn(__tr2qs_ctx("Filename","sharedfileswindow"),300);
+ m_pListView->addColumn(__tr2qs_ctx("Mask","sharedfileswindow"),200);
+ m_pListView->addColumn(__tr2qs_ctx("Expires","sharedfileswindow"),200);
+ m_pListView->setSelectionMode(KviTalListView::Single);
+ connect(m_pListView,SIGNAL(selectionChanged()),this,SLOT(enableButtons()));
+
+ connect(g_pSharedFilesManager,SIGNAL(sharedFilesChanged()),this,SLOT(fillFileView()));
+ connect(g_pSharedFilesManager,SIGNAL(sharedFileAdded(KviSharedFile *)),this,SLOT(sharedFileAdded(KviSharedFile *)));
+ connect(g_pSharedFilesManager,SIGNAL(sharedFileRemoved(KviSharedFile *)),this,SLOT(sharedFileRemoved(KviSharedFile *)));
+
+ KviTalHBox * b = new KviTalHBox(vbox);
+
+ m_pAddButton = new QPushButton(__tr2qs_ctx("&Add...","sharedfileswindow"),b);
+ connect(m_pAddButton,SIGNAL(clicked()),this,SLOT(addClicked()));
+ m_pRemoveButton = new QPushButton(__tr2qs_ctx("Re&move","sharedfileswindow"),b);
+ connect(m_pRemoveButton,SIGNAL(clicked()),this,SLOT(removeClicked()));
+ m_pEditButton = new QPushButton(__tr2qs_ctx("&Edit","sharedfileswindow"),b);
+ connect(m_pEditButton,SIGNAL(clicked()),this,SLOT(editClicked()));
+
+ fillFileView();
+}
+
+KviSharedFilesWindow::~KviSharedFilesWindow()
+{
+ g_pSharedFilesWindow = 0;
+}
+
+void KviSharedFilesWindow::enableButtons()
+{
+ KviTalListViewItem * it = m_pListView->currentItem();
+ m_pEditButton->setEnabled(it);
+ m_pRemoveButton->setEnabled(it);
+}
+
+void KviSharedFilesWindow::removeClicked()
+{
+ KviSharedFilesListViewItem * it = (KviSharedFilesListViewItem *)m_pListView->currentItem();
+ if(!it)return;
+
+ g_pSharedFilesManager->removeSharedFile(it->readOnlySharedFilePointer()->name(),it->readOnlySharedFilePointer());
+}
+
+void KviSharedFilesWindow::addClicked()
+{
+ KviSharedFileEditDialog dlg(0);
+ if(dlg.exec() != QDialog::Accepted)return;
+
+ KviSharedFile * f = dlg.getResult();
+ if(!f)return;
+ g_pSharedFilesManager->addSharedFile(f);
+}
+
+void KviSharedFilesWindow::editClicked()
+{
+ KviSharedFilesListViewItem * it = (KviSharedFilesListViewItem *)m_pListView->currentItem();
+ if(!it)return;
+
+ KviSharedFileEditDialog dlg(0,it->readOnlySharedFilePointer());
+ if(dlg.exec() != QDialog::Accepted)return;
+
+ KviSharedFilesListViewItem * it2 = (KviSharedFilesListViewItem *)m_pListView->currentItem();
+ if(it2 != it)return; // ooops ?
+ KviSharedFile * f = dlg.getResult();
+ if(!f)return; // ooops 2 ?
+
+ g_pSharedFilesManager->removeSharedFile(it->readOnlySharedFilePointer()->name(),it->readOnlySharedFilePointer());
+ g_pSharedFilesManager->addSharedFile(f);
+}
+
+void KviSharedFilesWindow::fillFileView()
+{
+ m_pListView->clear();
+ KviPointerHashTableIterator<QString,KviSharedFileList> it(*(g_pSharedFilesManager->sharedFileListDict()));
+
+ KviSharedFilesListViewItem * itm;
+
+ while(KviSharedFileList * l = it.current())
+ {
+ for(KviSharedFile * o = l->first();o;o = l->next())
+ {
+ itm = new KviSharedFilesListViewItem(m_pListView,o);
+ }
+ ++it;
+ }
+ enableButtons();
+}
+
+void KviSharedFilesWindow::sharedFileAdded(KviSharedFile * f)
+{
+ KviSharedFilesListViewItem * it;
+ it = new KviSharedFilesListViewItem(m_pListView,f);
+ enableButtons();
+}
+
+void KviSharedFilesWindow::sharedFileRemoved(KviSharedFile * f)
+{
+ KviTalListViewItem * it = m_pListView->firstChild();
+ while(it)
+ {
+ if(((KviSharedFilesListViewItem *)it)->readOnlySharedFilePointer() == f)
+ {
+ delete ((KviSharedFilesListViewItem *)it);
+ return;
+ }
+ it = it->nextSibling();
+ }
+ enableButtons();
+}
+
+
+
+/*
+void KviSharedFilesWindow::tipRequest(KviDynamicToolTip * tip,const QPoint &pnt)
+{
+
+ KviSharedFilesItem * it = (KviSharedFilesItem *)m_pListView->itemAt(pnt);
+ if(!it)return;
+ QString txt = it->transfer()->tipText();
+ tip->tip(m_pListView->itemRect(it),txt);
+
+}
+*/
+/*
+void KviSharedFilesWindow::fillTransferView()
+{
+ KviPointerList<KviSharedFiles> * l = KviSharedFilesManager::instance()->transferList();
+ if(!l)return;
+ KviSharedFilesItem * it;
+ for(KviSharedFiles * t = l->first();t;t = l->next())
+ {
+ it = new KviSharedFilesItem(m_pListView,t);
+ t->setDisplayItem(it);
+ }
+}
+
+KviSharedFilesItem * KviSharedFilesWindow::findItem(KviSharedFiles * t)
+{
+ KviSharedFilesItem * it = (KviSharedFilesItem *)m_pListView->firstChild();
+ while(it)
+ {
+ if(it->transfer() == t)return it;
+ it = (KviSharedFilesItem *)(it->nextSibling());
+ }
+ return 0;
+}
+
+void KviSharedFilesWindow::transferRegistered(KviSharedFiles * t)
+{
+ KviSharedFilesItem * it = new KviSharedFilesItem(m_pListView,t);
+ //t->setDisplayItem(it);
+}
+
+void KviSharedFilesWindow::transferUnregistering(KviSharedFiles * t)
+{
+ KviSharedFilesItem * it = findItem(t);
+ //t->setDisplayItem(0);
+ if(it)delete it;
+}
+
+void KviSharedFilesWindow::rightButtonPressed(KviTalListViewItem *it,const QPoint &pnt,int col)
+{
+ if(!m_pContextPopup)m_pContextPopup = new KviTalPopupMenu(this);
+ if(!m_pLocalFilePopup)m_pLocalFilePopup = new KviTalPopupMenu(this);
+ if(!m_pOpenFilePopup)
+ {
+ m_pOpenFilePopup= new KviTalPopupMenu(this);
+ connect(m_pOpenFilePopup,SIGNAL(activated(int)),this,SLOT(openFilePopupActivated(int)));
+ }
+
+ m_pContextPopup->clear();
+
+ int id;
+
+
+ if(it)
+ {
+ KviSharedFilesItem * i = (KviSharedFilesItem *)it;
+ if(i->transfer())
+ {
+
+ QString szFile = i->transfer()->localFileName();
+ if(!szFile.isEmpty())
+ {
+ m_pLocalFilePopup->clear();
+
+ QString tmp = "<b>file:/";
+ tmp += szFile;
+ tmp += "</b><br>";
+
+ QFileInfo fi(szFile);
+ if(fi.exists())
+ {
+ tmp += "<nobr>";
+ tmp += __tr2qs_ctx("Size: %1 bytes","filetransferwindow").arg(fi.size());
+ tmp += "</nobr><br>";
+ }
+
+#ifdef COMPILE_KDE_SUPPORT
+ tmp += "<nobr>Mime: ";
+ tmp += KMimeType::findByPath(szFile)->name();
+ tmp += "</nobr>";
+#endif //COMPILE_KDE_SUPPORT
+
+ QLabel * l = new QLabel(tmp,m_pLocalFilePopup);
+ l->setFrameStyle(QFrame::Raised | QFrame::Panel);
+ m_pLocalFilePopup->insertItem(l);
+
+#ifdef COMPILE_KDE_SUPPORT
+ QString mimetype = KMimeType::findByPath(szFile)->name();
+ KServiceTypeProfile::OfferList offers = KServiceTypeProfile::offers(mimetype,"Application");
+
+ m_pOpenFilePopup->clear();
+
+ int id;
+ int idx = 0;
+
+ for(KServiceTypeProfile::OfferList::Iterator itOffers = offers.begin();
+ itOffers != offers.end(); ++itOffers)
+ {
+ id = m_pOpenFilePopup->insertItem((*itOffers).service()->pixmap(KIcon::Small),(*itOffers).service()->name());
+ m_pOpenFilePopup->setItemParameter(id,idx);
+ idx++;
+ }
+
+ m_pOpenFilePopup->insertSeparator();
+
+ id = m_pOpenFilePopup->insertItem(__tr2qs_ctx("Default application","filetransferwindow"),this,SLOT(openLocalFile()));
+ m_pOpenFilePopup->setItemParameter(id,-1);
+ id = m_pOpenFilePopup->insertItem(__tr2qs_ctx("&Other...","filetransferwindow"),this,SLOT(openLocalFileWith()));
+ m_pOpenFilePopup->setItemParameter(id,-1);
+
+ m_pLocalFilePopup->insertItem(__tr2qs_ctx("Open with","filetransferwindow"),m_pOpenFilePopup);
+ m_pLocalFilePopup->insertSeparator();
+ m_pLocalFilePopup->insertItem(__tr2qs_ctx("Open folder","filetransferwindow"),this,SLOT(openLocalFileFolder()));
+ m_pLocalFilePopup->insertItem(__tr2qs_ctx("Reach in terminal","filetransferwindow"),this,SLOT(openLocalFileTerminal()));
+ m_pLocalFilePopup->insertSeparator();
+#endif //COMPILE_KDE_SUPPORT
+ m_pLocalFilePopup->insertItem(__tr2qs_ctx("Copy path to clipboard","filetransferwindow"),this,SLOT(copyLocalFileToClipboard()));
+
+ m_pContextPopup->insertItem(__tr2qs_ctx("Local file","filetransferwindow"),m_pLocalFilePopup);
+ }
+
+ i->transfer()->fillContextPopup(m_pContextPopup,col);
+ m_pContextPopup->insertSeparator();
+ }
+ }
+
+
+ bool bHaveTerminated = false;
+ KviSharedFilesItem * item = (KviSharedFilesItem *)m_pListView->firstChild();
+ while(item)
+ {
+ if(item->transfer()->terminated())
+ {
+ bHaveTerminated = true;
+ break;
+ }
+ item = (KviSharedFilesItem *)item->nextSibling();
+ }
+
+ id = m_pContextPopup->insertItem(__tr2qs_ctx("Clear terminated","filetransferwindow"),this,SLOT(clearTerminated()));
+ m_pContextPopup->setItemEnabled(id,bHaveTerminated);
+
+ id = m_pContextPopup->insertItem(__tr2qs_ctx("Clear all","filetransferwindow"),this,SLOT(clearAll()));
+ m_pContextPopup->setItemEnabled(id,it);
+
+ m_pContextPopup->popup(pnt);
+}
+
+
+KviSharedFiles * KviSharedFilesWindow::selectedTransfer()
+{
+ KviTalListViewItem * it = m_pListView->selectedItem();
+ if(!it)return 0;
+ KviSharedFilesItem * i = (KviSharedFilesItem *)it;
+ return i->transfer();
+}
+
+void KviSharedFilesWindow::openFilePopupActivated(int id)
+{
+#ifdef COMPILE_KDE_SUPPORT
+ int ip = m_pOpenFilePopup->itemParameter(id);
+ if(ip < 0)return;
+ QString txt = m_pOpenFilePopup->text(id);
+
+ KviSharedFiles * t = selectedTransfer();
+ if(!t)return;
+ QString tmp = t->localFileName();
+ if(tmp.isEmpty())return;
+
+ QString mimetype = KMimeType::findByPath(tmp)->name();
+ KServiceTypeProfile::OfferList offers = KServiceTypeProfile::offers(mimetype,"Application");
+
+ for(KServiceTypeProfile::OfferList::Iterator itOffers = offers.begin();
+ itOffers != offers.end(); ++itOffers)
+ {
+ if(txt == (*itOffers).service()->name())
+ {
+ KURL::List lst;
+ KURL url;
+ url.setPath(tmp);
+ lst.append(url);
+ KRun::run(*((*itOffers).service()), lst);
+ break;
+ }
+ }
+#endif //COMPILE_KDE_SUPPORT
+}
+
+void KviSharedFilesWindow::openLocalFileTerminal()
+{
+#ifdef COMPILE_KDE_SUPPORT
+ KviSharedFiles * t = selectedTransfer();
+ if(!t)return;
+ QString tmp = t->localFileName();
+ if(tmp.isEmpty())return;
+
+ int idx = tmp.findRev("/");
+ if(idx == -1)return;
+ tmp = tmp.left(idx);
+
+ tmp.prepend("konsole --workdir=\"");
+ tmp.append("\"");
+
+ KRun::runCommand(tmp);
+#endif //COMPILE_KDE_SUPPORT
+}
+
+void KviSharedFilesWindow::openLocalFile()
+{
+#ifdef COMPILE_KDE_SUPPORT
+ KviSharedFiles * t = selectedTransfer();
+ if(!t)return;
+ QString tmp = t->localFileName();
+ if(tmp.isEmpty())return;
+
+ QString mimetype = KMimeType::findByPath(tmp)->name();
+ KService::Ptr offer = KServiceTypeProfile::preferredService(mimetype,"Application");
+ if(!offer)
+ {
+ openLocalFileWith();
+ return;
+ }
+
+ KURL::List lst;
+ KURL url;
+ url.setPath(tmp);
+ lst.append(url);
+ KRun::run(*offer, lst);
+#endif //COMPILE_KDE_SUPPORT
+}
+
+void KviSharedFilesWindow::openLocalFileWith()
+{
+#ifdef COMPILE_KDE_SUPPORT
+ KviSharedFiles * t = selectedTransfer();
+ if(!t)return;
+ QString tmp = t->localFileName();
+ if(tmp.isEmpty())return;
+
+ KURL::List lst;
+ KURL url;
+ url.setPath(tmp);
+ lst.append(url);
+ KRun::displayOpenWithDialog(lst);
+#endif //COMPILE_KDE_SUPPORT
+}
+
+void KviSharedFilesWindow::copyLocalFileToClipboard()
+{
+ KviSharedFiles * t = selectedTransfer();
+ if(!t)return;
+ QString tmp = t->localFileName();
+ if(tmp.isEmpty())return;
+ QApplication::clipboard()->setSelectionMode(false);
+ QApplication::clipboard()->setText(tmp);
+ QApplication::clipboard()->setSelectionMode(true);
+ QApplication::clipboard()->setText(tmp);
+}
+
+void KviSharedFilesWindow::openLocalFileFolder()
+{
+#ifdef COMPILE_KDE_SUPPORT
+ KviSharedFiles * t = selectedTransfer();
+ if(!t)return;
+ QString tmp = t->localFileName();
+ if(tmp.isEmpty())return;
+
+ int idx = tmp.findRev("/");
+ if(idx == -1)return;
+ tmp = tmp.left(idx);
+
+ QString mimetype = KMimeType::findByPath(tmp)->name(); // inode/directory
+ KService::Ptr offer = KServiceTypeProfile::preferredService(mimetype,"Application");
+ if(!offer)return;
+
+ KURL::List lst;
+ KURL url;
+ url.setPath(tmp);
+ lst.append(url);
+ KRun::run(*offer, lst);
+#endif //COMPILE_KDE_SUPPORT
+}
+
+void KviSharedFilesWindow::heartbeat()
+{
+ if(m_pListView->childCount() < 1)return;
+
+ KviTalListViewItem * i1;
+ KviTalListViewItem * i2;
+
+ i1 = m_pListView->itemAt(QPoint(1,1));
+ if(!i1)
+ {
+ m_pListView->viewport()->update();
+ return;
+ }
+ i2 = m_pListView->itemAt(QPoint(1,m_pListView->viewport()->height() - 2));
+ if(i2)i2 = i2->nextSibling();
+
+ while(i1 && (i1 != i2))
+ {
+ if(((KviSharedFilesItem *)i1)->transfer()->active())
+ {
+ m_pListView->repaintItem(i1);
+ }
+ i1 = i1->nextSibling();
+ }
+}
+
+void KviSharedFilesWindow::clearAll()
+{
+ if(QMessageBox::information(this,__tr2qs_ctx("Clear all transfers","filetransferwindow"),
+ __tr2qs_ctx("Remove all the transfers including the running ones ?","filetransferwindow"),
+ __tr2qs_ctx("Yes","filetransferwindow"),__tr2qs_ctx("No","filetransferwindow")) != 0)return;
+
+ KviSharedFilesManager::instance()->killAllTransfers();
+}
+
+void KviSharedFilesWindow::clearTerminated()
+{
+ KviSharedFilesManager::instance()->killTerminatedTransfers();
+}
+*/
+void KviSharedFilesWindow::getBaseLogFileName(KviStr &buffer)
+{
+ buffer.sprintf("SHAREDFILES");
+}
+
+QPixmap * KviSharedFilesWindow::myIconPtr()
+{
+ return g_pIconManager->getSmallIcon(KVI_SMALLICON_SHAREDFILES);
+}
+
+void KviSharedFilesWindow::resizeEvent(QResizeEvent *e)
+{
+ //int h = m_pInput->heightHint();
+ m_pSplitter->setGeometry(0,0,width(),height());
+ //m_pInput->setGeometry(0,height() - h,width(),h);
+}
+
+QSize KviSharedFilesWindow::sizeHint() const
+{
+ return m_pSplitter->sizeHint();
+}
+
+void KviSharedFilesWindow::fillCaptionBuffers()
+{
+ m_szPlainTextCaption = __tr2qs_ctx("Shared Files","sharedfileswindow");
+
+ m_szHtmlActiveCaption = "<nobr><font color=\"";
+ m_szHtmlActiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextActive).name();
+ m_szHtmlActiveCaption += "\"><b>";
+ m_szHtmlActiveCaption += m_szPlainTextCaption;
+ m_szHtmlActiveCaption += "</b></font></nobr>";
+
+ m_szHtmlInactiveCaption = "<nobr><font color=\"";
+ m_szHtmlInactiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextInactive).name();
+ m_szHtmlInactiveCaption += "\"><b>";
+ m_szHtmlInactiveCaption += m_szPlainTextCaption;
+ m_szHtmlInactiveCaption += "</b></font></nobr>";
+
+}
+
+void KviSharedFilesWindow::die()
+{
+ close();
+}
+
+
+
+//#warning "Load & save properties of this kind of window"
+
+//void KviSharedFilesWindow::saveProperties()
+//{
+// KviWindowProperty p;
+// p.rect = externalGeometry();
+// p.isDocked = isAttacched();
+// QValueList<int> l(m_pSplitter->sizes());
+// if(l.count() >= 1)p.splitWidth1 = *(l.at(0));
+// if(l.count() >= 2)p.splitWidth2 = *(l.at(1));
+// p.timestamp = m_pView->timestamp();
+// p.imagesVisible = m_pView->imagesVisible();
+// p.isMaximized = isAttacched() && isMaximized();
+// p.topSplitWidth1 = 0;
+// p.topSplitWidth2 = 0;
+// p.topSplitWidth3 = 0;
+// g_pOptions->m_pWinPropertiesList->setProperty(caption(),&p);
+//}
+//
+//void KviSharedFilesWindow::setProperties(KviWindowProperty *p)
+//{
+// QValueList<int> l;
+// l.append(p->splitWidth1);
+// l.append(p->splitWidth2);
+// m_pVertSplitter->setSizes(l);
+// m_pIrcView->setTimestamp(p->timestamp);
+// m_pIrcView->setShowImages(p->imagesVisible);
+//}
+
+
+#include "m_sharedfileswindow.moc"
diff --git a/src/modules/sharedfileswindow/sharedfileswindow.h b/src/modules/sharedfileswindow/sharedfileswindow.h
new file mode 100644
index 00000000..f46bd6df
--- /dev/null
+++ b/src/modules/sharedfileswindow/sharedfileswindow.h
@@ -0,0 +1,114 @@
+#ifndef _SHAREDFILESWINDOW_H_
+#define _SHAREDFILESWINDOW_H_
+//==================================================================================
+//
+// File : sharedfileswindow.h
+// Creation date : Mon Apr 21 2003 23:14:12 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the linkss of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) 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.
+//
+//==================================================================================
+
+#include "kvi_window.h"
+#include "kvi_string.h"
+#include "kvi_sparser.h"
+#include "kvi_console.h"
+#include "kvi_moduleextension.h"
+#include "kvi_sharedfiles.h"
+#include "kvi_styled_controls.h"
+
+#include "kvi_tal_listview.h"
+#include <qdialog.h>
+
+class QGridLayout;
+class QDateTimeEdit;
+class QLabel;
+class QLineEdit;
+class QPushButton;
+
+class KviSharedFilesListViewItem : public KviTalListViewItem
+{
+public:
+ KviSharedFilesListViewItem(KviTalListView * lv,KviSharedFile * f);
+ ~KviSharedFilesListViewItem();
+protected:
+ KviSharedFile * m_pSharedFilePointer; // THIS IS READ ONLY!
+public:
+ KviSharedFile * readOnlySharedFilePointer(){ return m_pSharedFilePointer; };
+};
+
+
+
+class KviSharedFileEditDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ KviSharedFileEditDialog(QWidget* par,KviSharedFile * f = 0);
+ ~KviSharedFileEditDialog();
+
+ QDateTimeEdit * m_pExpireDateTimeEdit;
+ QLineEdit * m_pFilePathEdit;
+ QLineEdit * m_pUserMaskEdit;
+ QPushButton * m_pBrowseButton;
+ QLineEdit * m_pShareNameEdit;
+ KviStyledCheckBox * m_pExpireCheckBox;
+public:
+ KviSharedFile * getResult();
+protected slots:
+ void okClicked();
+ void browse();
+};
+
+
+
+
+class KviSharedFilesWindow : public KviWindow , public KviModuleExtension
+{
+ friend class KviSharedFilesItem;
+ Q_OBJECT
+public:
+ KviSharedFilesWindow(KviModuleExtensionDescriptor * d,KviFrame * lpFrm);
+ ~KviSharedFilesWindow();
+protected:
+ QSplitter * m_pVertSplitter;
+
+ KviTalListView * m_pListView;
+
+ QPushButton * m_pRemoveButton;
+ QPushButton * m_pEditButton;
+ QPushButton * m_pAddButton;
+public: // Methods
+ virtual void die();
+protected:
+ virtual QPixmap * myIconPtr();
+ virtual void fillCaptionBuffers();
+ virtual void resizeEvent(QResizeEvent *e);
+ virtual void getBaseLogFileName(KviStr &buffer);
+public:
+ virtual QSize sizeHint() const;
+protected slots:
+ void fillFileView();
+ void sharedFileAdded(KviSharedFile * f);
+ void sharedFileRemoved(KviSharedFile * f);
+ void enableButtons();
+ void removeClicked();
+ void addClicked();
+ void editClicked();
+};
+
+#endif //_SHAREDFILESWINDOW_H_
diff --git a/src/modules/snd/Makefile.am b/src/modules/snd/Makefile.am
new file mode 100644
index 00000000..d5776010
--- /dev/null
+++ b/src/modules/snd/Makefile.am
@@ -0,0 +1,22 @@
+###############################################################################
+# KVirc IRC client Makestr - 10.03.2002 Juanjo lvarez <juanjux@yahoo.es>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+-I/usr/include/kde/arts\
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkvisnd.la
+
+libkvisnd_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkvisnd_la_SOURCES = libkvisnd.cpp
+libkvisnd_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+
+noinst_HEADERS= libkvisnd.h
+
+%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
+
+libkvisnd.cpp: libkvisnd.moc
diff --git a/src/modules/snd/libkvisnd.cpp b/src/modules/snd/libkvisnd.cpp
new file mode 100644
index 00000000..bf0d2eab
--- /dev/null
+++ b/src/modules/snd/libkvisnd.cpp
@@ -0,0 +1,744 @@
+//=============================================================================
+//
+// File : libkvisnd.cpp
+// Creation date : Thu Dec 27 2002 17:13:12 GMT by Juanjo �varez
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Juanjo �varez (juanjux at yahoo dot es)
+// Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "libkvisnd.h"
+#include "kvi_module.h"
+#include "kvi_debug.h"
+
+#include "kvi_fileutils.h"
+#include "kvi_malloc.h"
+#include "kvi_window.h"
+#include "kvi_out.h"
+#include "kvi_locale.h"
+#include "kvi_qstring.h"
+
+#include <qsound.h>
+
+#ifdef COMPILE_ON_WINDOWS
+ #include <mmsystem.h>
+#else //!COMPILE_ON_WINDOWS
+
+ #include <qfile.h>
+ #include <unistd.h>
+ #include <errno.h>
+
+ #ifdef COMPILE_ESD_SUPPORT
+ #include <esd.h>
+ #endif //COMPILE_ESD_SUPPORT
+
+ #ifdef COMPILE_OSS_SUPPORT
+ #include <fcntl.h>
+ #include <sys/ioctl.h>
+ #ifdef HAVE_LINUX_SOUNDCARD_H
+ #include <linux/soundcard.h>
+ #else
+ // Hint by Andy Fawcett: Thnx :)
+ #ifdef HAVE_SYS_SOUNDCARD_H
+ #include <sys/soundcard.h>
+ #else
+ #warning "Ops.. have no soundcard.h ? ... we're going to fail here :/"
+ #endif
+ #endif
+ #ifdef COMPILE_AUDIOFILE_SUPPORT
+ #include <audiofile.h>
+ #endif //COMPILE_AUDIOFILE_SUPPORT
+ #endif //COMPILE_OSS_SUPPORT
+
+ #ifdef COMPILE_ARTS_SUPPORT
+ #include <arts/soundserver.h>
+
+ static Arts::Dispatcher * g_pArtsDispatcher = 0;
+
+ #endif //COMPILE_ARTS_SUPPORT
+
+#endif
+
+static KviSoundPlayer * g_pSoundPlayer = 0;
+
+KviSoundPlayer::KviSoundPlayer()
+: QObject()
+{
+ m_pThreadList = new KviPointerList<KviSoundThread>;
+ m_pThreadList->setAutoDelete(true);
+
+ m_pSoundSystemDict = new KviPointerHashTable<QString,SoundSystemRoutine>(17,false);
+ m_pSoundSystemDict->setAutoDelete(true);
+
+#ifdef COMPILE_ON_WINDOWS
+ m_pSoundSystemDict->insert("winmm",new SoundSystemRoutine(KVI_PTR2MEMBER(KviSoundPlayer::playWinmm)));
+#else //!COMPILE_ON_WINDOWS
+ #ifdef COMPILE_OSS_SUPPORT
+ #ifdef COMPILE_AUDIOFILE_SUPPORT
+ m_pSoundSystemDict->insert("oss+audiofile",new SoundSystemRoutine(KVI_PTR2MEMBER(KviSoundPlayer::playOssAudiofile)));
+ #endif //COMPILE_AUDIOFILE_SUPPORT
+ m_pSoundSystemDict->insert("oss",new SoundSystemRoutine(KVI_PTR2MEMBER(KviSoundPlayer::playOss)));
+ #endif //COMPILE_OSS_SUPPORT
+ #ifdef COMPILE_ESD_SUPPORT
+ m_pSoundSystemDict->insert("esd",new SoundSystemRoutine(KVI_PTR2MEMBER(KviSoundPlayer::playEsd)));
+ #endif //COMPILE_ESD_SUPPORT
+ #ifdef COMPILE_ARTS_SUPPORT
+ m_pSoundSystemDict->insert("arts",new SoundSystemRoutine(KVI_PTR2MEMBER(KviSoundPlayer::playArts)));
+ #endif //COMPILE_ARTS_SUPPORT
+#endif //!COMPILE_ON_WINDOWS
+
+#if QT_VERSION >= 0x030100
+ if(QSound::isAvailable())
+ m_pSoundSystemDict->insert("qt",new SoundSystemRoutine(KVI_PTR2MEMBER(KviSoundPlayer::playQt)));
+#else
+ if(QSound::available())
+ m_pSoundSystemDict->insert("qt",new SoundSystemRoutine(KVI_PTR2MEMBER(KviSoundPlayer::playQt)));
+#endif
+
+ m_pSoundSystemDict->insert("null",new SoundSystemRoutine(KVI_PTR2MEMBER(KviSoundPlayer::playNull)));
+
+}
+
+KviSoundPlayer::~KviSoundPlayer()
+{
+ m_pThreadList->setAutoDelete(false);
+ while(KviSoundThread * t = m_pThreadList->first())delete t;
+ delete m_pThreadList;
+ KviThreadManager::killPendingEvents(this);
+ delete m_pSoundSystemDict;
+
+#ifndef COMPILE_ON_WINDOWS
+ #ifdef COMPILE_ARTS_SUPPORT
+ if(g_pArtsDispatcher)delete g_pArtsDispatcher;
+ g_pArtsDispatcher = 0;
+ #endif
+#endif //!COMPILE_ON_WINDOWS
+ g_pSoundPlayer = 0;
+}
+
+void KviSoundPlayer::getAvailableSoundSystems(QStringList *l)
+{
+ KviPointerHashTableIterator<QString,SoundSystemRoutine> it(*m_pSoundSystemDict);
+ while(it.current())
+ {
+ l->append(it.currentKey());
+ ++it;
+ }
+}
+
+
+bool KviSoundPlayer::havePlayingSounds()
+{
+ return (m_pThreadList->count() > 0);
+}
+
+void KviSoundPlayer::registerSoundThread(KviSoundThread * t)
+{
+ m_pThreadList->append(t);
+}
+
+void KviSoundPlayer::unregisterSoundThread(KviSoundThread * t)
+{
+ m_pThreadList->removeRef(t);
+}
+
+bool KviSoundPlayer::event(QEvent * e)
+{
+ if(e->type() == KVI_THREAD_EVENT)
+ {
+ KviThread * t = ((KviThreadEvent *)e)->sender();
+ if(!t)return true; // huh ?
+ delete (KviSoundThread *)t;
+ return true;
+ }
+ return QObject::event(e);
+}
+
+
+void KviSoundPlayer::detectSoundSystem()
+{
+#ifdef COMPILE_ON_WINDOWS
+ KVI_OPTION_STRING(KviOption_stringSoundSystem) = "winmm";
+#else
+ #ifdef COMPILE_ARTS_SUPPORT
+ if(!g_pArtsDispatcher)g_pArtsDispatcher = new Arts::Dispatcher();
+
+ Arts::SimpleSoundServer *server = new Arts::SimpleSoundServer(Arts::Reference("global:Arts_SimpleSoundServer"));
+ if(!server->isNull())
+ {
+ //Don't change the order of those deletes!
+ KVI_OPTION_STRING(KviOption_stringSoundSystem) = "arts";
+ delete server;
+ return;
+ }
+ delete server;
+ #endif //COMPILE_ARTS_SUPPORT
+ #ifdef COMPILE_ESD_SUPPORT
+ esd_format_t format = ESD_BITS16 | ESD_STREAM | ESD_PLAY | ESD_MONO;
+ int esd_fd = esd_play_stream(format, 8012, NULL, "kvirc");
+ if(esd_fd >= 0)
+ {
+ KVI_OPTION_STRING(KviOption_stringSoundSystem) = "esd";
+ return;
+ }
+ #endif
+ #ifdef COMPILE_OSS_SUPPORT
+ #ifdef COMPILE_AUDIOFILE_SUPPORT
+ KVI_OPTION_STRING(KviOption_stringSoundSystem) = "oss+audiofile";
+ return;
+ #endif
+ KVI_OPTION_STRING(KviOption_stringSoundSystem) = "oss";
+ #endif
+
+#if QT_VERSION >= 0x030100
+ if(QSound::isAvailable())
+#else
+ if(QSound::available())
+#endif
+ {
+ KVI_OPTION_STRING(KviOption_stringSoundSystem) = "qt";
+ return;
+ }
+
+ KVI_OPTION_STRING(KviOption_stringSoundSystem) = "null";
+#endif
+}
+
+#ifdef COMPILE_ON_WINDOWS
+ bool KviSoundPlayer::playWinmm(const QString &szFileName)
+ {
+ if(isMuted()) return true;
+ sndPlaySound(szFileName.local8Bit().data(),SND_ASYNC | SND_NODEFAULT);
+ return true;
+ }
+#else //!COMPILE_ON_WINDOWS
+ #ifdef COMPILE_OSS_SUPPORT
+ #ifdef COMPILE_AUDIOFILE_SUPPORT
+ bool KviSoundPlayer::playOssAudiofile(const QString &szFileName)
+ {
+ if(isMuted()) return true;
+ KviOssAudiofileSoundThread * t = new KviOssAudiofileSoundThread(szFileName);
+ if(!t->start())
+ {
+ delete t;
+ return false;
+ }
+ return true;
+ }
+ #endif //COMPILE_AUDIOFILE_SUPPORT
+ bool KviSoundPlayer::playOss(const QString &szFileName)
+ {
+ if(isMuted()) return true;
+ KviOssSoundThread * t = new KviOssSoundThread(szFileName);
+ if(!t->start())
+ {
+ delete t;
+ return false;
+ }
+ return true;
+ }
+ #endif //COMPILE_OSS_SUPPORT
+ #ifdef COMPILE_ESD_SUPPORT
+ bool KviSoundPlayer::playEsd(const QString &szFileName)
+ {
+ if(isMuted()) return true;
+ KviEsdSoundThread * t = new KviEsdSoundThread(szFileName);
+ if(!t->start())
+ {
+ delete t;
+ return false;
+ }
+ return true;
+ }
+ #endif //COMPILE_ESD_SUPPORT
+ #ifdef COMPILE_ARTS_SUPPORT
+ bool KviSoundPlayer::playArts(const QString &szFileName)
+ {
+ if(isMuted()) return true;
+ KviArtsSoundThread * t = new KviArtsSoundThread(szFileName);
+ if(!t->start())
+ {
+ delete t;
+ return false;
+ }
+ return true;
+ }
+ #endif //COMPILE_ARTS_SUPPORT
+#endif //!COMPILE_ON_WINDOWS
+
+bool KviSoundPlayer::playQt(const QString &szFileName)
+{
+ if(isMuted()) return true;
+ QSound::play(szFileName);
+ return true;
+}
+
+bool KviSoundPlayer::playNull(const QString &szFileName)
+{
+ // null sound system
+ return true;
+}
+
+
+bool KviSoundPlayer::play(const QString &szFileName)
+{
+ if(isMuted()) return true;
+ SoundSystemRoutine * r = m_pSoundSystemDict->find(KVI_OPTION_STRING(KviOption_stringSoundSystem));
+
+ if(!r)
+ {
+ if(KviQString::equalCI(KVI_OPTION_STRING(KviOption_stringSoundSystem),"unknown"))
+ {
+ detectSoundSystem();
+ r = m_pSoundSystemDict->find(KVI_OPTION_STRING(KviOption_stringSoundSystem));
+ if(!r)return false;
+ } else {
+ return false;
+ }
+ }
+
+ return (this->*(*r))(szFileName);
+}
+
+
+
+
+KviSoundThread::KviSoundThread(const QString &szFileName)
+: KviThread()
+{
+ g_pSoundPlayer->registerSoundThread(this);
+ m_szFileName = szFileName;
+}
+
+KviSoundThread::~KviSoundThread()
+{
+ g_pSoundPlayer->unregisterSoundThread(this);
+}
+
+void KviSoundThread::play()
+{
+}
+
+void KviSoundThread::run()
+{
+ play();
+#ifndef COMPILE_ON_WINDOWS
+ postEvent(g_pSoundPlayer,new KviThreadEvent(KVI_THREAD_EVENT_SUCCESS));
+#endif
+}
+
+
+#ifndef COMPILE_ON_WINDOWS
+ #ifdef COMPILE_OSS_SUPPORT
+ #ifdef COMPILE_AUDIOFILE_SUPPORT
+ KviOssAudiofileSoundThread::KviOssAudiofileSoundThread(const QString &szFileName)
+ : KviSoundThread(szFileName)
+ {
+ }
+
+ KviOssAudiofileSoundThread::~KviOssAudiofileSoundThread()
+ {
+ }
+
+ void KviOssAudiofileSoundThread::play()
+ {
+ #define BUFFER_FRAMES 4096
+
+ AFfilehandle file;
+ AFframecount framesRead;
+ int sampleFormat, sampleWidth, channelCount, format, freq;
+ float frameSize;
+ void * buffer;
+
+ file = afOpenFile(m_szFileName.utf8().data(),"r",NULL);
+ afGetVirtualSampleFormat(file, AF_DEFAULT_TRACK, &sampleFormat, &sampleWidth);
+ frameSize = afGetVirtualFrameSize(file, AF_DEFAULT_TRACK, 1);
+ channelCount = afGetVirtualChannels(file, AF_DEFAULT_TRACK);
+ buffer = kvi_malloc(int(BUFFER_FRAMES * frameSize));
+
+ int audiofd_c = open("/dev/dsp", O_WRONLY | O_EXCL | O_NDELAY);
+ QFile audiofd;
+ audiofd.open(IO_WriteOnly,audiofd_c);
+
+ if(audiofd_c < 0)
+ {
+ debug("Could not open audio devive /dev/dsp! [OSS]");
+ debug("(the device is probably busy)");
+ goto exit_thread;
+ }
+
+ if (sampleWidth == 8) format = AFMT_U8;
+ else if (sampleWidth == 16)format = AFMT_S16_NE;
+
+ if (ioctl(audiofd.handle(),SNDCTL_DSP_SETFMT, &format) == -1)
+ {
+ debug("Could not set format width to DSP! [OSS]");
+ goto exit_thread;
+ }
+
+ if (ioctl(audiofd.handle(), SNDCTL_DSP_CHANNELS, &channelCount) == -1)
+ {
+ debug("Could not set DSP channels! [OSS]");
+ goto exit_thread;
+ }
+
+ freq = (int) afGetRate(file, AF_DEFAULT_TRACK);
+ if (ioctl(audiofd.handle(), SNDCTL_DSP_SPEED, &freq) == -1)
+ {
+ debug("Could not set DSP speed %d! [OSS]",freq);
+ goto exit_thread;
+ }
+
+ framesRead = afReadFrames(file, AF_DEFAULT_TRACK, buffer, BUFFER_FRAMES);
+
+ while(framesRead > 0)
+ {
+ audiofd.writeBlock((char *)buffer,(int)(framesRead * frameSize));
+ framesRead = afReadFrames(file, AF_DEFAULT_TRACK, buffer,BUFFER_FRAMES);
+ }
+
+ exit_thread:
+ audiofd.close();
+ if(audiofd_c >= 0)close(audiofd_c);
+ afCloseFile(file);
+ kvi_free(buffer);
+ }
+ #endif //COMPILE_AUDIOFILE_SUPPORT
+
+
+ KviOssSoundThread::KviOssSoundThread(const QString &szFileName)
+ : KviSoundThread(szFileName)
+ {
+ }
+
+ KviOssSoundThread::~KviOssSoundThread()
+ {
+ }
+
+ void KviOssSoundThread::play()
+ {
+ #define OSS_BUFFER_SIZE 16384
+
+ QFile f(m_szFileName);
+ int fd = -1;
+ char buf[OSS_BUFFER_SIZE];
+ int iDataLen = 0;
+ int iSize = 0;
+
+ if(!f.open(IO_ReadOnly))
+ {
+ debug("Could not open sound file %s! [OSS]",m_szFileName.utf8().data());
+ return;
+ }
+
+ iSize = f.size();
+
+ if(iSize < 24)
+ {
+ debug("Could not play sound, file %s too small! [OSS]",m_szFileName.utf8().data());
+ goto exit_thread;
+ }
+
+ if(f.readBlock(buf,24) < 24)
+ {
+ debug("Error while reading the sound file header (%s)! [OSS]",m_szFileName.utf8().data());
+ goto exit_thread;
+ }
+
+ iSize -= 24;
+
+ fd = open("/dev/audio", O_WRONLY | O_EXCL | O_NDELAY);
+ if(fd < 0)
+ {
+ debug("Could not open device file /dev/audio!");
+ debug("Maybe other program is using the device? Hint: fuser -uv /dev/audio");
+ goto exit_thread;
+ }
+
+
+ while(iSize > 0)
+ {
+ int iCanRead = OSS_BUFFER_SIZE - iDataLen;
+ if(iCanRead > 0)
+ {
+ int iToRead = iSize > iCanRead ? iCanRead : iSize;
+ int iReaded = f.readBlock(buf + iDataLen,iToRead);
+ if(iReaded < 1)
+ {
+ debug("Error while reading the file data (%s)! [OSS]",m_szFileName.utf8().data());
+ goto exit_thread;
+ }
+ iSize -= iReaded;
+ iDataLen += iReaded;
+ }
+ if(iDataLen > 0)
+ {
+ int iWritten = write(fd,buf,iDataLen);
+ if(iWritten < 0)
+ {
+ if((errno != EINTR) && (errno != EAGAIN))
+ {
+ debug("Error while writing the audio data (%s)! [OSS]",m_szFileName.utf8().data());
+ goto exit_thread;
+ }
+ }
+ iDataLen -= iWritten;
+ } else {
+ // nothing to write ????
+ goto exit_thread;
+ }
+ }
+
+ exit_thread:
+ f.close();
+ if(fd > 0)close(fd);
+ }
+
+
+ #endif //COMPILE_OSS_SUPPORT
+
+ #ifdef COMPILE_ESD_SUPPORT
+
+ KviEsdSoundThread::KviEsdSoundThread(const QString &szFileName)
+ : KviSoundThread(szFileName)
+ {
+ }
+
+ KviEsdSoundThread::~KviEsdSoundThread()
+ {
+ }
+
+ void KviEsdSoundThread::play()
+ {
+ // ESD has a really nice API
+ if(!esd_play_file(NULL,m_szFileName.utf8().data(),1))
+ debug("Could not play sound %s! [ESD]",m_szFileName.utf8().data());
+ }
+
+ #endif //COMPILE_ESD_SUPPORT
+
+ #ifdef COMPILE_ARTS_SUPPORT
+
+ KviArtsSoundThread::KviArtsSoundThread(const QString &szFileName)
+ : KviSoundThread(szFileName)
+ {
+ }
+
+ KviArtsSoundThread::~KviArtsSoundThread()
+ {
+ }
+
+ void KviArtsSoundThread::play()
+ {
+ if(!g_pArtsDispatcher)g_pArtsDispatcher = new Arts::Dispatcher;
+
+ Arts::SimpleSoundServer *server = new Arts::SimpleSoundServer(Arts::Reference("global:Arts_SimpleSoundServer"));
+ if(server->isNull())
+ {
+ debug("Can't connect to sound server to play file %s",m_szFileName.utf8().data());
+ } else {
+ server->play(m_szFileName);
+ }
+ delete server;
+ }
+ #endif
+
+
+#endif //!COMPILE_ON_WINDOWS
+
+
+/*
+ @doc: snd.play
+ @type:
+ command
+ @title:
+ snd.play
+ @short:
+ Play a sound file from the disk
+ @syntax:
+ snd.play [-q|quiet] <filename:string>
+ @description:
+ Play a file, using the sound system specified by the user in the options.[br]
+ The supported file formats vary from one sound system to another, but the best
+ bet could be Au Law (.au) files. Artsd, EsounD and Linux/OSS with audiofile support also
+ support other formats like .wav files but in OSS without audiofile only .au files are
+ supported.
+ On windows the supported file formats are determined by the drivers installed.
+ You should be able to play at least *.wav files.[br]
+ (This is a task where the Windows interface is really well done, I must say that :)
+ @switches:
+ !sw: -q | --quiet
+ Causes the command to run quietly (no complains about missing files, invalid formats...
+*/
+
+static bool snd_kvs_cmd_play(KviKvsModuleCommandCall * c)
+{
+ QString szFile;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("file name",KVS_PT_STRING,0,szFile)
+ KVSM_PARAMETERS_END(c)
+ if(szFile.isEmpty() || (!KviFileUtils::fileExists(szFile)))
+ {
+ if(!c->hasSwitch('q',"quiet"))c->warning(__tr2qs("Sound file '%Q' not found"),&szFile);
+ return true;
+ }
+
+ if(!g_pSoundPlayer->play(szFile))
+ {
+ if(!c->hasSwitch('q',"quiet"))c->warning(__tr2qs("Unable to play sound '%Q'"),&szFile);
+ }
+
+ return true;
+}
+
+static bool snd_kvs_cmd_autodetect(KviKvsModuleCommandCall * c)
+{
+ g_pSoundPlayer->detectSoundSystem();
+ if(KviQString::equalCI(KVI_OPTION_STRING(KviOption_stringSoundSystem),"null"))
+ {
+ c->window()->outputNoFmt(KVI_OUT_SYSTEMERROR,__tr2qs("Sorry , I can't find a sound system to use on this machine"));
+ } else {
+ c->window()->output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Sound system detected to: %s"),KVI_OPTION_STRING(KviOption_stringSoundSystem).utf8().data());
+ }
+ return true;
+}
+
+
+/*
+ @doc: snd.mute
+ @type:
+ command
+ @title:
+ snd.mute
+ @short:
+ Mute all sounds
+ @syntax:
+ snd.mute
+ @description:
+ Mute all sounds
+*/
+
+static bool snd_kvs_cmd_mute(KviKvsModuleCommandCall * c)
+{
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETERS_END(c)
+ g_pSoundPlayer->setMuted(TRUE);
+ return true;
+}
+
+/*
+ @doc: snd.unmute
+ @type:
+ command
+ @title:
+ snd.unmute
+ @short:
+ UnMute all sounds
+ @syntax:
+ snd.mute
+ @description:
+ UnMute all sounds
+*/
+
+static bool snd_kvs_cmd_unmute(KviKvsModuleCommandCall * c)
+{
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETERS_END(c)
+ g_pSoundPlayer->setMuted(FALSE);
+ return true;
+}
+
+/*
+ @doc: snd.isMuted
+ @type:
+ function
+ @title:
+ $snd.isMuted
+ @short:
+ Returns if the sounds muted
+ @syntax:
+ <bool> $snd.isMuted()
+ @description:
+ Returns if the sounds muted
+*/
+
+
+static bool snd_kvs_fnc_ismuted(KviKvsModuleFunctionCall * c)
+{
+ c->returnValue()->setBoolean(g_pSoundPlayer->isMuted());
+ return true;
+}
+
+static bool snd_module_init(KviModule * m)
+{
+ g_pSoundPlayer = new KviSoundPlayer();
+
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"autodetect",snd_kvs_cmd_autodetect);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"play",snd_kvs_cmd_play);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"mute",snd_kvs_cmd_mute);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"unmute",snd_kvs_cmd_unmute);
+
+ KVSM_REGISTER_FUNCTION(m,"isMuted",snd_kvs_fnc_ismuted);
+
+ return true;
+}
+
+static bool snd_module_cleanup(KviModule *m)
+{
+ delete g_pSoundPlayer;
+ g_pSoundPlayer = 0;
+ return true;
+}
+
+static bool snd_module_can_unload(KviModule *m)
+{
+ return !(g_pSoundPlayer->havePlayingSounds());
+}
+
+static bool snd_module_ctrl(KviModule * m,const char * operation,void * param)
+{
+ if(kvi_strEqualCI(operation,"getAvailableSoundSystems"))
+ {
+ // we expect param to be a pointer to QStringList
+ QStringList *l=(QStringList *)param;
+ g_pSoundPlayer->getAvailableSoundSystems(l);
+ return true;
+ }
+ if(kvi_strEqualCI(operation,"detectSoundSystem"))
+ {
+ g_pSoundPlayer->detectSoundSystem();
+ return true;
+ }
+ return false;
+}
+
+
+KVIRC_MODULE(
+ "Sound", // module name
+ "1.0.0", // module version
+ "(C) 2002 Szymon Stefanek (pragma at kvirc dot net)," \
+ "Juanjo Alvarez (juanjux at yahoo dot es)", // author & (C)
+ "Sound playing commands",
+ snd_module_init,
+ snd_module_can_unload,
+ snd_module_ctrl,
+ snd_module_cleanup
+)
+
+#include "libkvisnd.moc"
diff --git a/src/modules/snd/libkvisnd.h b/src/modules/snd/libkvisnd.h
new file mode 100644
index 00000000..6becfa38
--- /dev/null
+++ b/src/modules/snd/libkvisnd.h
@@ -0,0 +1,213 @@
+#ifndef _LIBKVISND_H_
+#define _LIBKVISND_H_
+
+//
+// File : libkvisnd.h
+// Creation date : Apr 21 2002 12:30:25 CEST by Juan Jos��varez
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+
+#include <qobject.h>
+
+#include "kvi_thread.h"
+#include "kvi_string.h"
+
+#include "kvi_pointerlist.h"
+#include "kvi_pointerhashtable.h"
+#include "kvi_options.h"
+
+//class KviWavSoundFileReader
+//{
+//public:
+// KviWavSoundFileReader(QFile * f);
+// ~KviWavSoundFileReader();
+//protected:
+// QFile * m_pFile;
+//public:
+// static bool recognize(KviFile * f);
+// bool readHeader();
+//};
+
+
+//bool KviWavSoundFileReader::recognize(KviFile * f)
+//{
+// kvi_u32_t tag;
+// if(!f->load(tag))return false;
+//
+// f->at(0);
+//}
+
+//bool KviWavSoundFileReader::readHeader()
+//{
+//
+//
+// tag = get_le32(pb);
+//
+// if (tag != MKTAG('R', 'I', 'F', 'F'))
+// return -1;
+// get_le32(pb); /* file size */
+// tag = get_le32(pb);
+// if (tag != MKTAG('W', 'A', 'V', 'E'))
+// return -1;
+//
+// size = find_tag(pb, MKTAG('f', 'm', 't', ' '));
+// if (size < 0)
+// return -1;
+// id = get_le16(pb);
+// channels = get_le16(pb);
+// rate = get_le32(pb);
+// bit_rate = get_le32(pb) * 8;
+// get_le16(pb); /* block align */
+// get_le16(pb); /* bits per sample */
+// if (size >= 18) {
+// /* wav_extra_size */
+// extra_size = get_le16(pb);
+// /* skip unused data */
+// url_fseek(pb, size - 18, SEEK_CUR);
+// }
+//
+// size = find_tag(pb, MKTAG('d', 'a', 't', 'a'));
+// if (size < 0)
+// return -1;
+//
+// /* now we are ready: build format streams */
+// st = malloc(sizeof(AVStream));
+// if (!st)
+// return -1;
+// s->nb_streams = 1;
+// s->streams[0] = st;
+//
+// st->id = 0;
+//
+// st->codec.codec_type = CODEC_TYPE_AUDIO;
+// st->codec.codec_tag = id;
+// st->codec.codec_id = codec_get_id(codec_wav_tags, id);
+// st->codec.channels = channels;
+// st->codec.sample_rate = rate;
+//}
+
+class KviSoundThread : public KviThread
+{
+public:
+ KviSoundThread(const QString &szFileName);
+ virtual ~KviSoundThread();
+protected:
+ QString m_szFileName;
+protected:
+ virtual void play();
+ virtual void run();
+};
+
+#ifndef COMPILE_ON_WINDOWS
+ #ifdef COMPILE_OSS_SUPPORT
+ class KviOssSoundThread : public KviSoundThread
+ {
+ public:
+ KviOssSoundThread(const QString &szFileName);
+ virtual ~KviOssSoundThread();
+ protected:
+ virtual void play();
+ };
+
+ #ifdef COMPILE_AUDIOFILE_SUPPORT
+ class KviOssAudiofileSoundThread : public KviSoundThread
+ {
+ public:
+ KviOssAudiofileSoundThread(const QString &szFileName);
+ virtual ~KviOssAudiofileSoundThread();
+ protected:
+ virtual void play();
+ };
+ #endif //COMPILE_AUDIOFILE_SUPPORT
+ #endif //COMPILE_OSS_SUPPORT
+
+ #ifdef COMPILE_ESD_SUPPORT
+ class KviEsdSoundThread : public KviSoundThread
+ {
+ public:
+ KviEsdSoundThread(const QString &szFileName);
+ virtual ~KviEsdSoundThread();
+ protected:
+ virtual void play();
+ };
+ #endif //COMPILE_ESD_SUPPORT
+
+ #ifdef COMPILE_ARTS_SUPPORT
+ class KviArtsSoundThread : public KviSoundThread
+ {
+ public:
+ KviArtsSoundThread(const QString &szFileName);
+ virtual ~KviArtsSoundThread();
+ protected:
+ virtual void play();
+ };
+ #endif //COMPILE_ARTS_SUPPORT
+#endif //!COMPILE_ON_WINDOWS
+
+class KviSoundPlayer;
+
+typedef bool (KviSoundPlayer::*SoundSystemRoutine)(const QString &szFileName);
+
+class KviSoundPlayer : public QObject
+{
+ friend class KviSoundThread;
+ Q_OBJECT
+public:
+ KviSoundPlayer();
+ virtual ~KviSoundPlayer();
+public:
+ bool play(const QString &szFileName);
+ void detectSoundSystem();
+ bool havePlayingSounds();
+ //void getAvailableSoundSystems(KviPointerList<QString> * l);
+ void getAvailableSoundSystems(QStringList * l);
+ bool isMuted() {return KVI_OPTION_BOOL(KviOption_boolMuteAllSounds); };
+ void setMuted(bool muted) {KVI_OPTION_BOOL(KviOption_boolMuteAllSounds)=muted;};
+protected:
+ KviPointerList<KviSoundThread> * m_pThreadList;
+ KviPointerHashTable<QString,SoundSystemRoutine> * m_pSoundSystemDict;
+protected:
+ void registerSoundThread(KviSoundThread * t);
+ void unregisterSoundThread(KviSoundThread * t);
+ virtual bool event(QEvent *e);
+protected:
+#ifdef COMPILE_ON_WINDOWS
+ bool playWinmm(const QString &szFileName);
+#else //!COMPILE_ON_WINDOWS
+ #ifdef COMPILE_OSS_SUPPORT
+ bool playOss(const QString &szFileName);
+ #ifdef COMPILE_AUDIOFILE_SUPPORT
+ bool playOssAudiofile(const QString &szFileName);
+ #endif //COMPILE_AUDIOFILE_SUPPORT
+ #endif //COMPILE_OSS_SUPPORT
+ #ifdef COMPILE_ARTS_SUPPORT
+ bool playArts(const QString &szFileName);
+ #endif //COMPILE_ARTS_SUPPORT
+ #ifdef COMPILE_ESD_SUPPORT
+ bool playEsd(const QString &szFileName);
+ #endif //COMPILE_ESD_SUPPORT
+#endif //!COMPILE_ON_WINDOWS
+ bool playQt(const QString &szFileName);
+ bool playNull(const QString &szFileName);
+};
+
+
+#endif // _KVISND_H_
diff --git a/src/modules/socketspy/Makefile.am b/src/modules/socketspy/Makefile.am
new file mode 100644
index 00000000..7e0a4b6b
--- /dev/null
+++ b/src/modules/socketspy/Makefile.am
@@ -0,0 +1,20 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkvisocketspy.la
+
+libkvisocketspy_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkvisocketspy_la_SOURCES = libkvisocketspy.cpp socketspywindow.cpp
+libkvisocketspy_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+noinst_HEADERS= socketspywindow.h
+
+m_%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
+
+socketspywindow.cpp: m_socketspywindow.moc
diff --git a/src/modules/socketspy/libkvisocketspy.cpp b/src/modules/socketspy/libkvisocketspy.cpp
new file mode 100644
index 00000000..c4076620
--- /dev/null
+++ b/src/modules/socketspy/libkvisocketspy.cpp
@@ -0,0 +1,92 @@
+//
+// File : libkvisocketspy.cpp
+// Creation date : Sun Nov 26 2000 13:05:00 CEST by Szymon Stefanek
+//
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+
+#include "kvi_module.h"
+
+
+#include "socketspywindow.h"
+
+#include "kvi_frame.h"
+#include "kvi_window.h"
+#include "kvi_locale.h"
+
+#include <qsplitter.h>
+
+KviPointerList<KviSocketSpyWindow> * g_pSocketSpyWindowList = 0;
+
+
+/*
+ @doc: socketspy.open
+ @type:
+ command
+ @title:
+ socketspy.open
+ @short:
+ Opens a SocketSpy window
+ @syntax:
+ socketspy.open
+ @description:
+ Creates a new socketspy window. A SocketSpy window
+ monitors the incoming and outgoing raw data on the
+ irc socket of the current irc context.
+*/
+
+static bool socketspy_kvs_cmd_open(KviKvsModuleCommandCall * c)
+{
+ if(!c->window()->console())return c->context()->errorNoIrcContext();
+ KviSocketSpyWindow *w = new KviSocketSpyWindow(c->window()->frame(),c->window()->console());
+ c->window()->frame()->addWindow(w);
+ return true;
+}
+
+static bool socketspy_module_init(KviModule * m)
+{
+ g_pSocketSpyWindowList = new KviPointerList<KviSocketSpyWindow>;
+ g_pSocketSpyWindowList->setAutoDelete(false);
+
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"open",socketspy_kvs_cmd_open);
+ return true;
+}
+
+static bool socketspy_module_cleanup(KviModule *m)
+{
+ while(g_pSocketSpyWindowList->first())g_pSocketSpyWindowList->first()->die();
+ delete g_pSocketSpyWindowList;
+ g_pSocketSpyWindowList = 0;
+ return true;
+}
+
+static bool socketspy_module_can_unload(KviModule *m)
+{
+ return (g_pSocketSpyWindowList->isEmpty());
+}
+
+KVIRC_MODULE(
+ "SocketSpy", // module name
+ "1.0.0", // module version
+ "Copyright (C) 2000 Szymon Stefanek (pragma at kvirc dot net)", // author & (C)
+ "SocketSpy irc socket traffic monitor",
+ socketspy_module_init,
+ socketspy_module_can_unload,
+ 0,
+ socketspy_module_cleanup
+)
diff --git a/src/modules/socketspy/socketspywindow.cpp b/src/modules/socketspy/socketspywindow.cpp
new file mode 100644
index 00000000..4d59b5aa
--- /dev/null
+++ b/src/modules/socketspy/socketspywindow.cpp
@@ -0,0 +1,125 @@
+//
+// File : socketspywindow.cpp
+// Creation date : Thu Aug 31 2000 15:02:22 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the socketspys of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) 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.
+//
+#include "socketspywindow.h"
+
+#include "kvi_iconmanager.h"
+#include "kvi_ircview.h"
+#include "kvi_out.h"
+#include "kvi_options.h"
+#include "kvi_locale.h"
+#include "kvi_console.h"
+
+#include <qsplitter.h>
+//#include "kvi_module.h"
+
+extern KviPointerList<KviSocketSpyWindow> * g_pSocketSpyWindowList;
+
+KviSocketSpyWindow::KviSocketSpyWindow(KviFrame * lpFrm,KviConsole * lpConsole)
+: KviWindow(KVI_WINDOW_TYPE_SOCKETSPY,lpFrm,"socket_spy",lpConsole) , KviIrcDataStreamMonitor(lpConsole->context())
+{
+ g_pSocketSpyWindowList->append(this);
+ #ifdef COMPILE_USE_QT4
+ m_pSplitter = new QSplitter(Qt::Horizontal,this,"splitter");
+ #else
+ m_pSplitter = new QSplitter(QSplitter::Horizontal,this,"splitter");
+#endif
+ m_pIrcView = new KviIrcView(m_pSplitter,lpFrm,this);
+ // Ensure proper focusing
+ //setFocusHandler(m_pIrcView,this);
+}
+
+KviSocketSpyWindow::~KviSocketSpyWindow()
+{
+ g_pSocketSpyWindowList->removeRef(this);
+}
+
+void KviSocketSpyWindow::die()
+{
+ close();
+}
+
+QPixmap * KviSocketSpyWindow::myIconPtr()
+{
+ return g_pIconManager->getSmallIcon(KVI_SMALLICON_SPY);
+}
+
+void KviSocketSpyWindow::resizeEvent(QResizeEvent *e)
+{
+ m_pSplitter->setGeometry(0,0,width(),height());
+}
+
+QSize KviSocketSpyWindow::sizeHint() const
+{
+ return m_pIrcView->sizeHint();
+}
+
+void KviSocketSpyWindow::getBaseLogFileName(KviStr &buffer)
+{
+ buffer.sprintf("SOCKETSPY_%d",console()->ircContextId());
+}
+
+void KviSocketSpyWindow::fillCaptionBuffers()
+{
+ KviQString::sprintf(m_szPlainTextCaption,__tr2qs("Socket Spy [IRC Context %u]"),m_pConsole->ircContextId());
+
+ KviQString::sprintf(m_szHtmlActiveCaption,
+ __tr2qs("<nobr><font color=\"%s\"><b>Socket Spy</b></font> " \
+ "<font color=\"%s\">[IRC Context %u]</font></nobr>"),
+ KVI_OPTION_COLOR(KviOption_colorCaptionTextActive).name().ascii(),
+ KVI_OPTION_COLOR(KviOption_colorCaptionTextActive2).name().ascii(),
+ m_pConsole->ircContextId());
+
+ KviQString::sprintf(m_szHtmlInactiveCaption,
+ __tr2qs("<nobr><font color=\"%s\"><b>Socket Spy</b></font> " \
+ "<font color=\"%s\">[IRC Context %u]</font></nobr>"),
+ KVI_OPTION_COLOR(KviOption_colorCaptionTextInactive).name().ascii(),
+ KVI_OPTION_COLOR(KviOption_colorCaptionTextInactive2).name().ascii(),
+ m_pConsole->ircContextId());
+}
+
+void KviSocketSpyWindow::incomingMessage(const char * message)
+{
+ outputNoFmt(KVI_OUT_SOCKETMESSAGE,console()->decodeText(message));
+}
+
+void KviSocketSpyWindow::outgoingMessage(const char * message,int len)
+{
+ KviStr str(message,len);
+ outputNoFmt(KVI_OUT_RAW,console()->decodeText(str.ptr()));
+}
+
+void KviSocketSpyWindow::connectionInitiated()
+{
+ output(KVI_OUT_SOCKETWARNING,__tr2qs("Socket open"));
+}
+
+void KviSocketSpyWindow::connectionTerminated()
+{
+ output(KVI_OUT_SOCKETWARNING,__tr2qs("Socket closed"));
+}
+
+void KviSocketSpyWindow::applyOptions()
+{
+ m_pIrcView->applyOptions();
+ KviWindow::applyOptions();
+}
+#include "m_socketspywindow.moc"
diff --git a/src/modules/socketspy/socketspywindow.h b/src/modules/socketspy/socketspywindow.h
new file mode 100644
index 00000000..ab516d3e
--- /dev/null
+++ b/src/modules/socketspy/socketspywindow.h
@@ -0,0 +1,53 @@
+#ifndef _SOCKETSPYWINDOW_H_
+#define _SOCKETSPYWINDOW_H_
+//
+// File : socketspywindow.h
+// Creation date : Sun Nov 26 2000 13:13:00 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the socketspys of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) 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.
+//
+
+#include "kvi_window.h"
+#include "kvi_string.h"
+#include "kvi_ircdatastreammonitor.h"
+
+class KviConsole;
+
+class KviSocketSpyWindow : public KviWindow, public KviIrcDataStreamMonitor
+{
+ Q_OBJECT
+public:
+ KviSocketSpyWindow(KviFrame * lpFrm,KviConsole * lpConsole);
+ ~KviSocketSpyWindow();
+protected:
+ virtual QPixmap * myIconPtr();
+ virtual void fillCaptionBuffers();
+ virtual void resizeEvent(QResizeEvent *e);
+ virtual void getBaseLogFileName(KviStr &buffer);
+ virtual void applyOptions();
+public:
+ virtual QSize sizeHint() const;
+ virtual void incomingMessage(const char * message);
+ // message is NOT null terminated! For proxy connections it might spit out binary data!
+ virtual void outgoingMessage(const char * message,int len);
+ virtual void connectionInitiated();
+ virtual void connectionTerminated();
+ virtual void die();
+};
+
+#endif //_KVI_SOCKETSPYWINDOW_H_
diff --git a/src/modules/spaste/Makefile.am b/src/modules/spaste/Makefile.am
new file mode 100644
index 00000000..f1a6f719
--- /dev/null
+++ b/src/modules/spaste/Makefile.am
@@ -0,0 +1,24 @@
+###############################################################################
+# KVirc IRC client Makestr - 10.03.2002 Juanjo lvarez <juanjux@yahoo.es>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+-I/usr/include/kde/arts\
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+#ARTS_LD_FLAGS = -DPIC -fPIC
+#ARTS_C_FLAGS = -L/usr/lib -ldl -lartsc -lpthread
+pluglib_LTLIBRARIES = libkvispaste.la
+
+libkvispaste_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkvispaste_la_SOURCES = libkvispaste.cpp controller.cpp
+libkvispaste_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+
+noinst_HEADERS= controller.h libkvispaste.h
+
+%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
+
+controller.cpp: controller.moc
diff --git a/src/modules/spaste/controller.cpp b/src/modules/spaste/controller.cpp
new file mode 100644
index 00000000..5a132dbd
--- /dev/null
+++ b/src/modules/spaste/controller.cpp
@@ -0,0 +1,121 @@
+// File : controller.cpp
+// Creation date : Thu Apr 30 2002 17:13:12 GMT by Juanjo lvarez
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Juanjo lvarez (juanjux@yahoo.es)
+// Copyright (C) 2002 Szymon Stefanek (kvirc@tin.it)
+//
+// 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 opinion) 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.
+
+#include "controller.h"
+#include "kvi_window.h"
+#include "kvi_console.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_app.h"
+#include "kvi_options.h"
+
+#include <qtimer.h>
+#include <qstringlist.h>
+#include <qclipboard.h>
+
+extern KviPointerList<SPasteController> * g_pControllerList;
+
+SPasteController::SPasteController(KviWindow * w,int id)
+ : m_pClipBuff(NULL),m_pFile(NULL),m_pId(id),m_pWindow(w)
+{
+ g_pControllerList->append(this);
+ //m_pWindow = w;
+ m_pTimer = new QTimer(this);
+}
+
+SPasteController::~SPasteController()
+{
+ g_pControllerList->removeRef(this);
+ if(m_pFile)
+ {
+ m_pFile->close();
+ delete m_pFile;
+ }
+ if(m_pTimer)
+ {
+ m_pTimer->stop();
+ delete m_pTimer;
+ }
+ if(m_pClipBuff)
+ delete m_pClipBuff;
+}
+
+bool SPasteController::pasteFileInit(QString &fileName)
+{
+ if(m_pClipBuff)return false; // can't paste a file while pasting the clipboard
+ if(m_pFile)return false; // can't paste two files at a time
+ m_pFile = new QFile(fileName);
+ if(!m_pFile->open(IO_ReadOnly))return false;
+ connect(m_pTimer,SIGNAL(timeout()),this,SLOT(pasteFile()));
+ m_pTimer->start(KVI_OPTION_UINT(KviOption_uintPasteDelay));
+ return true;
+}
+
+bool SPasteController::pasteClipboardInit(void)
+{
+ if(m_pFile)return false; // can't paste clipboard while pasting a file
+ QString tmp(g_pApp->clipboard()->text());
+ if(m_pClipBuff)
+ {
+ (*m_pClipBuff) += QStringList::split("\n",tmp,true);
+ } else {
+ m_pClipBuff = new QStringList(QStringList::split("\n",tmp,true));
+ m_clipBuffIterator = m_pClipBuff->begin();
+ }
+ connect(m_pTimer,SIGNAL(timeout()),this,SLOT(pasteClipboard()));
+ m_pTimer->start(KVI_OPTION_UINT(KviOption_uintPasteDelay));
+ return true;
+}
+
+void SPasteController::pasteFile(void)
+{
+#ifndef COMPILE_USE_QT4
+ QString line;
+ if(m_pFile->readLine(line,999) != -1)
+ {
+ if(line.isEmpty())
+ line = QChar(KVI_TEXT_RESET);
+ if( (!g_pApp->windowExists(m_pWindow)) || m_pWindow->console()->isNotConnected() )
+ {
+ m_pFile->close();
+ delete this;
+ } else m_pWindow->ownMessage(line.ascii());
+ } else { //File finished
+ m_pFile->close();
+ delete this;
+ }
+#endif
+}
+
+void SPasteController::pasteClipboard(void)
+{
+ if(m_clipBuffIterator != m_pClipBuff->end())
+ {
+ if((!g_pApp->windowExists(m_pWindow)) || m_pWindow->console()->isNotConnected() )
+ delete this;
+ else {
+ if((*m_clipBuffIterator).isEmpty())(*m_clipBuffIterator) = QChar(KVI_TEXT_RESET);
+ m_pWindow->ownMessage((*m_clipBuffIterator).ascii()); // <-- not good :/
+ ++m_clipBuffIterator;
+ }
+ } else delete this;//Clipboard finished
+}
+
+#include "controller.moc"
diff --git a/src/modules/spaste/controller.h b/src/modules/spaste/controller.h
new file mode 100644
index 00000000..55aeeaab
--- /dev/null
+++ b/src/modules/spaste/controller.h
@@ -0,0 +1,59 @@
+// File : controller.h
+// Creation date : Thu Apr 30 2002 17:13:12 GMT by Juanjo lvarez
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Juanjo lvarez (juanjux@yahoo.es)
+// Copyright (C) 2002 Szymon Stefanek (kvirc@tin.it)
+//
+// 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 opinion) 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.
+
+#ifndef SPASTE_CONTROLLER_H
+#define SPASTE_CONTROLLER_H
+
+#include "kvi_window.h"
+#include "kvi_string.h"
+
+#include <qobject.h>
+#include <qstringlist.h>
+#include <qfile.h>
+
+class SPasteController : public QObject
+{
+ Q_OBJECT
+public:
+ SPasteController(KviWindow * w,int id);
+ ~SPasteController();
+
+ //bool pasteFileInit(KviStr * fileName);
+ bool pasteFileInit(QString &fileName);
+ bool pasteClipboardInit(void);
+ int getId(void){return m_pId;};
+ KviWindow * window(void){return m_pWindow;};
+ //void stop(void);
+protected slots:
+ void pasteFile(void);
+ void pasteClipboard(void);
+
+private:
+ QStringList *m_pClipBuff;
+ QFile *m_pFile;
+ int m_pId;
+ KviWindow *m_pWindow;
+ QTimer *m_pTimer;
+ QStringList::Iterator m_clipBuffIterator;
+};
+
+#endif //SPASTE_CONTROLLER_H
+
diff --git a/src/modules/spaste/libkvispaste.cpp b/src/modules/spaste/libkvispaste.cpp
new file mode 100644
index 00000000..6b310324
--- /dev/null
+++ b/src/modules/spaste/libkvispaste.cpp
@@ -0,0 +1,346 @@
+// File : libkvispaste.cpp
+// Creation date : Thu Dec 27 2002 17:13:12 GMT by Juanjo �varez
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Juanjo �varez (juanjux@yahoo.es)
+// Copyright (C) 2002 Szymon Stefanek (kvirc@tin.it)
+//
+// 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 opinion) 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.
+//
+
+
+#include "libkvispaste.h"
+#include "controller.h"
+
+#include "kvi_module.h"
+
+#include "kvi_fileutils.h"
+#include "kvi_app.h"
+#include "kvi_locale.h"
+
+#include "kvi_console.h"
+#include "kvi_options.h"
+#include "kvi_out.h"
+
+#include <qfile.h>
+#include <qclipboard.h>
+
+#ifndef COMPILE_ON_WINDOWS
+ #include <unistd.h>
+#endif
+
+KviPointerList<SPasteController> * g_pControllerList = 0;
+int ctrlId = 0;
+
+static SPasteController * spaste_find_controller(KviWindow * w)
+{
+ for(SPasteController * spc = g_pControllerList->first();spc;spc = g_pControllerList->next())
+ {
+ if(spc->window() == w)return spc;
+ }
+ return 0;
+}
+
+static KviWindow * spaste_kvs_find_window(QString &win, KviKvsModuleCommandCall * c)
+{
+ KviWindow * w;
+ if(!win.isEmpty())w = g_pApp->findWindow(win);
+ else w = c->window();
+ if(!w)
+ {
+ c->warning(__tr("Window with ID '%Q' not found"),&win);
+ return 0;
+ }
+ if((w->type() == KVI_WINDOW_TYPE_CHANNEL) || (w->type() == KVI_WINDOW_TYPE_QUERY) || (w->type() == KVI_WINDOW_TYPE_DCCCHAT))return w;
+ c->warning(__tr2qs("The specified window (%Q) is not a channel/query/DCC chat"),&win);
+ return 0;
+}
+//-------------------------------------------------
+/*
+ @doc: spaste.file
+ @type:
+ command
+ @title:
+ spaste.file
+ @short:
+ Sends the contents of a file to a window, with a delay between each line
+ @syntax:
+ spaste.file <filename:string> [window:string]
+ @description:
+ Sends the contents of a file to a conversation window doing a pause between each line. [br]
+ the optional window parameter must be a channel, query or DCC chat window, if [br]
+ no window is specified the text will be send to the current window.
+ @seealso:
+ [cmd]spaste.clipboard[/cmd],
+ [cmd]spaste.stop[/cmd],
+ [cmd]spaste.list[/cmd],
+ [cmd]spaste.setdelay[/cmd]
+*/
+//-------------------------------------------
+// spaste.file
+//-------------------------------------------
+
+static bool spaste_kvs_cmd_file(KviKvsModuleCommandCall * c)
+{
+ QString szFile,szWindow;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("file name",KVS_PT_STRING,0,szFile)
+ KVSM_PARAMETER("window",KVS_PT_STRING,KVS_PF_OPTIONAL,szWindow)
+ KVSM_PARAMETERS_END(c)
+
+ KviWindow * window = spaste_kvs_find_window(szWindow,c);
+ if( (!window) || window->console()->isNotConnected())return false;
+
+ if(szFile.isEmpty() || (!KviFileUtils::fileExists(szFile.ascii())))
+ {
+ c->warning(__tr2qs("File not found or empty"));
+ return false;
+ }
+
+ QFile tmp(szFile);
+ if(!tmp.open(IO_ReadOnly)) {
+ c->warning(__tr2qs("I can't open that file"));
+ return false;
+ }
+ tmp.close();
+
+ SPasteController * controller = spaste_find_controller(window);
+ if(!controller)controller = new SPasteController(window,++ctrlId);
+ if(!controller->pasteFileInit(szFile)) {
+ c->warning(__tr2qs("Could not paste file"));
+ return false;
+ }
+ return true;
+}
+
+
+/*
+ @doc: spaste.clipboard
+ @type:
+ command
+ @title:
+ spaste.clipboard
+ @short:
+ Sends the contents of the clipboard to a window, pausing between each line
+ @syntax:
+ spaste.clipboard [window:string]
+ @description:
+ Sends the contents of the clipboard to a conversation window, with a delay between each line. [br]
+ the optional window parameter must be a channel, query or DCC chat window. [br]
+ If no window is specified, the text will be sent to the current window.
+ @seealso:
+ [cmd]spaste.file[/cmd],
+ [cmd]spaste.stop[/cmd],
+ [cmd]spaste.list[/cmd],
+ [cmd]spaste.setdelay[/cmd]
+*/
+//-------------------------------------------------
+// spaste.clipboard
+//-------------------------------------------------
+
+static bool spaste_kvs_cmd_clipboard(KviKvsModuleCommandCall * c)
+{
+ QString szWindow;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("window",KVS_PT_STRING,KVS_PF_OPTIONAL,szWindow)
+ KVSM_PARAMETERS_END(c)
+ KviWindow * window = spaste_kvs_find_window(szWindow,c);
+ if( (!window) || window->console()->isNotConnected())return false;
+
+ SPasteController * controller = spaste_find_controller(window);
+ if(!controller)controller = new SPasteController(window,++ctrlId);
+ controller->pasteClipboardInit();
+ return true;
+}
+
+/*
+ @doc: spaste.stop
+ @type:
+ command
+ @title:
+ spaste.stop
+ @short:
+ Stops one or more slow-paste process.
+ @syntax:
+ spaste.stop [-a] [id:integer]
+ @description:
+ This commands stop one or more slow-paste processes. It can operate in three ways. The first, [br]
+ without any parameter or switch, stops all slow-paste processes running in the same window [br]
+ as the command. The second, using the -a switch, stops all slow paste processes running [br]
+ on all windows. The third form, without the switch and specifying a numerical slow paste process ID [br]
+ (which you can obtain with the [cmd]spaste.list[/cmd] command), stops only that process ID.
+ @switches:
+ !sw: -a | --all
+ Stops all slow paste processes running
+ @seealso:
+ [cmd]spaste.clipboard[/cmd],
+ [cmd]spaste.file[/cmd],
+ [cmd]spaste.list[/cmd],
+ [cmd]spaste.setdelay[/cmd]
+
+*/
+//--------------------------------------------------
+// spaste.stop
+//--------------------------------------------------
+
+static bool spaste_kvs_cmd_stop(KviKvsModuleCommandCall * c)
+{
+ kvs_int_t iId=0;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("delay",KVS_PT_UNSIGNEDINTEGER,KVS_PF_OPTIONAL,iId)
+ KVSM_PARAMETERS_END(c)
+
+ if(c->hasSwitch('a',"all")) //Delete all spaste's
+ {
+ while(g_pControllerList->first()) delete g_pControllerList->first();
+ return true;
+ } else {
+ KviPointerListIterator<SPasteController> it(*g_pControllerList);
+ SPasteController *item;
+
+ if(!iId) //Delete all spaste's from the current window
+ {
+ if((c->window()->type() != KVI_WINDOW_TYPE_CHANNEL) && (c->window()->type() != KVI_WINDOW_TYPE_QUERY) && (c->window()->type() != KVI_WINDOW_TYPE_DCCCHAT))
+ {
+ QString szWinId = c->window()->id();
+ c->warning(__tr2qs("The specified window (%Q) is not a channel/query/dcc"),&szWinId);
+ return false;
+ } else {
+ while( (item = it.current()) != 0)
+ {
+ ++it;
+ if(kvi_strEqualCS(item->window()->id(),c->window()->id()))delete item;
+ }
+ }
+ } else //Delete the spaste with the given id
+ {
+ while( (item = it.current()) != 0)
+ {
+ ++it;
+ if(item->getId() == iId)delete item;
+ }
+ }
+ return true;
+ }
+}
+
+/*
+ @doc: spaste.list
+ @type:
+ command
+ @title:
+ spaste.list
+ @short:
+ Lists all the running spaste processes.
+ @syntax:
+ spaste.list
+ @description:
+ This command will list in the window where it is executed all the current slow-paste [br]
+ processes, their identification numbers, and the windows where they are running. [br]
+ @seealso:
+ [cmd]spaste.clipboard[/cmd],
+ [cmd]spaste.file[/cmd],
+ [cmd]spaste.stop[/cmd],
+ [cmd]spaste.setdelay[/cmd]
+*/
+//--------------------------------------------------
+// spaste.list
+//--------------------------------------------------
+
+static bool spaste_kvs_cmd_list(KviKvsModuleCommandCall * c)
+{
+ KviPointerListIterator<SPasteController> it(*g_pControllerList);
+ SPasteController *item;
+
+ while( (item = it.current()) != 0)
+ {
+ ++it;
+ QString szWinId = item->window()->id();
+ c->window()->output(KVI_OUT_NONE,__tr2qs("Slow-paste ID:%d Window:%Q"),item->getId(),&szWinId);
+ }
+ return true;
+}
+
+/*
+ @doc: spaste.setdelay
+ @type:
+ command
+ @title:
+ spaste.setdelay
+ @short:
+ Sets the delay time in miliseconds for the spaste module command delay
+ @syntax:
+ spaste.setdelay <time_in_msecs:integer>
+ @description:
+ Sets the delay time in milliseconds for the spaste module command delay.
+ @seealso:
+ [cmd]spaste.clipboard[/cmd],
+ [cmd]spaste.file[/cmd],
+ [cmd]spaste.stop[/cmd],
+ [cmd]spaste.list[/cmd]
+*/
+//-------------------------------------------------
+// spaste.setdelay
+//-------------------------------------------------
+
+
+static bool spaste_kvs_cmd_setdelay(KviKvsModuleCommandCall * c)
+{
+ kvs_int_t delay;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("delay",KVS_PT_INTEGER,0,delay)
+ KVSM_PARAMETERS_END(c)
+ KVI_OPTION_UINT(KviOption_uintPasteDelay) = delay;
+ return true;
+}
+
+//-------------------------------------------------
+static bool spaste_module_init(KviModule * m)
+{
+ g_pControllerList = new KviPointerList<SPasteController>;
+ g_pControllerList->setAutoDelete(false);
+
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"file",spaste_kvs_cmd_file);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"clipboard",spaste_kvs_cmd_clipboard);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"setdelay",spaste_kvs_cmd_setdelay);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"stop",spaste_kvs_cmd_stop);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"list",spaste_kvs_cmd_list);
+ return true;
+}
+//-------------------------------------------------
+static bool spaste_module_cleanup(KviModule *m)
+{
+ while(g_pControllerList->first()) delete g_pControllerList->first();
+ delete g_pControllerList;
+ g_pControllerList = 0;
+
+ return true;
+}
+//-------------------------------------------------
+static bool spaste_module_can_unload(KviModule *m)
+{
+ return (g_pControllerList->isEmpty());
+}
+//-------------------------------------------------
+KVIRC_MODULE(
+ "SPaste", // module name
+ "1.0.0", // module version
+ " (C) 2002 Juanjo Alvarez (juanjux@yahoo.es)", // author & (C)
+ "Delayed paste commands",
+ spaste_module_init,
+ spaste_module_can_unload,
+ 0,
+ spaste_module_cleanup
+)
diff --git a/src/modules/spaste/libkvispaste.h b/src/modules/spaste/libkvispaste.h
new file mode 100644
index 00000000..53724c2d
--- /dev/null
+++ b/src/modules/spaste/libkvispaste.h
@@ -0,0 +1,13 @@
+#ifndef KVISPASTE_H
+#define KVISPASTE_H
+
+#include "kvi_window.h"
+
+typedef struct _SPasteThreadData {
+ QString * strData;
+ KviWindow * win;
+} SPasteThreadData;
+
+
+
+#endif
diff --git a/src/modules/str/Makefile.am b/src/modules/str/Makefile.am
new file mode 100644
index 00000000..7fe7e93a
--- /dev/null
+++ b/src/modules/str/Makefile.am
@@ -0,0 +1,18 @@
+###############################################################################
+# KVirc IRC client Makestr - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkvistr.la
+
+libkvistr_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkvistr_la_SOURCES = libkvistr.cpp
+libkvistr_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+# noinst_HEADERS=
+
+%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
diff --git a/src/modules/str/libkvistr.cpp b/src/modules/str/libkvistr.cpp
new file mode 100644
index 00000000..58549f57
--- /dev/null
+++ b/src/modules/str/libkvistr.cpp
@@ -0,0 +1,2330 @@
+//=============================================================================
+//
+// File : libkvistr.cpp
+// Creation date : Thu Dec 27 2001 17:13:12 GMT by Szymon Stefanek
+//
+// This str is part of the KVirc irc client distribution
+// Copyright (C) 2001-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+//#warning: FIXME: Incomplete documentation ('seealso', 'example', etc)
+
+#include "kvi_module.h"
+
+#include "kvi_locale.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_qstring.h"
+#include "kvi_debug.h"
+#include "kvi_settings.h"
+#include "kvi_malloc.h"
+
+#include "kvi_kvs_arraycast.h"
+#include <qregexp.h>
+#include <qclipboard.h>
+
+#ifdef COMPILE_SSL_SUPPORT
+ #include <openssl/evp.h>
+#endif
+
+/*
+ @doc: str.section
+ @type:
+ function
+ @title:
+ $str.section
+ @short:
+ Returns a section of the string.
+ @syntax:
+ <string> $str.section(<string_to_split:string>,<separator:string>,<pos_from:int>,<pos_to:int>)
+ @description:
+ Returns a section of the string.
+ The <string_to_split> is treated as a sequence of fields separated by <separator>.[br]
+ The returned string consists of the fields from position start <pos_from> to position end <pos_to>.[br]
+ Fields are numbered 0, 1, 2, etc., counting from the left, and -1, -2, etc., counting from right to left.[br]
+ @examples:
+ [example]
+ %s = $str.section( "forename**middlename**surname**phone","**", 2, 2 );
+ %s is "surname".
+ [/example]
+*/
+
+static bool str_kvs_fnc_section(KviKvsModuleFunctionCall * c)
+{
+ QString szString, szSeparator,szSplittedString;
+ kvs_int_t iPosFrom, iPosTo;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("string_to_split",KVS_PT_STRING,0,szString)
+ KVSM_PARAMETER("separator",KVS_PT_NONEMPTYSTRING,0,szSeparator)
+ KVSM_PARAMETER("pos_from",KVS_PT_INT,0,iPosFrom)
+ KVSM_PARAMETER("pos_to",KVS_PT_INT,0,iPosTo)
+ KVSM_PARAMETERS_END(c)
+ c->returnValue()->setString(szString.section(szSeparator,iPosFrom,iPosTo));
+ return true;
+}
+
+/*
+ @doc: str.fromClipboard
+ @type:
+ function
+ @title:
+ $str.fromClipboard
+ @short:
+ Returns a string from clipboard.
+ @syntax:
+ <string> $str.fromClipboard()
+ @description:
+ Returns clipboard's contents.
+ @examples:
+ [example]
+ %s = $str.fromClipboard();
+ [/example]
+ @seealso:
+ [cmd]str.toClipboard[/cmd]
+*/
+
+static bool str_kvs_fnc_fromclipboard(KviKvsModuleFunctionCall * c)
+{
+ QString szString;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETERS_END(c)
+ QClipboard *cb = QApplication::clipboard();
+ szString = cb->text(QClipboard::Clipboard);
+ c->returnValue()->setString(szString);
+ return true;
+}
+
+/*
+ @doc: system.toClipboard
+ @type:
+ command
+ @title:
+ system.toClipboard
+ @keyterms:
+ OS clipboard
+ @short:
+ Sets the OS clipboard contents
+ @syntax:
+ system.setenv <value:string>
+ @description:
+ Sets the OS clipboard contents
+ @seealso:
+ [fnc]$str.fromClipboard[/fnc]
+*/
+
+static bool str_kvs_cmd_toClipboard(KviKvsModuleCommandCall * c)
+{
+ QString szValue;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("value",KVS_PT_STRING,KVS_PF_OPTIONAL,szValue)
+ KVSM_PARAMETERS_END(c)
+ QClipboard *cb = QApplication::clipboard();
+ cb->setText(szValue, QClipboard::Clipboard );
+ return true;
+}
+
+/*
+ @doc: str.len
+ @type:
+ function
+ @title:
+ $str.len
+ @short:
+ Returns the lenght of the given string
+ @syntax:
+ <uint> $str.len(<data:string>)
+ @description:
+ Returns the lenght (that is, number of characters) of the given string.
+ This function is internally aliased to [fnc]$str.length[/fnc]() too.
+*/
+
+/*
+ @doc: str.length
+ @type:
+ function
+ @title:
+ $str.length
+ @short:
+ Returns the lenght of the given string
+ @syntax:
+ <uint> $str.length(<data:string>)
+ @description:
+ Returns the lenght (that is, number of characters) of the given string.
+ This function is internally aliased to [fnc]$str.len[/fnc]() too.
+*/
+
+static bool str_kvs_fnc_len(KviKvsModuleFunctionCall * c)
+{
+ QString szString;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("data",KVS_PT_STRING,0,szString)
+ KVSM_PARAMETERS_END(c)
+ c->returnValue()->setInteger(szString.length());
+ return true;
+}
+
+/*
+ @doc: str.lowcase
+ @type:
+ function
+ @title:
+ $str.lowcase
+ @short:
+ Returns the given string with all characters turned to lower case
+ @syntax:
+ <string> $str.lowcase(<string_to_convert:string>)
+ @description:
+ Returns the <string_to_convert> with all characters turned to lower case.
+ Warning: this function uses ISO-8859-1 locale to make the case translation.
+ If you want to use a locale aware translation mapping then please
+ use localelowcase.
+*/
+
+static bool str_kvs_fnc_lowcase(KviKvsModuleFunctionCall * c)
+{
+ QString szString;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("string_to_convert",KVS_PT_STRING,0,szString)
+ KVSM_PARAMETERS_END(c)
+ c->returnValue()->setString(KviQString::lowerISO88591(szString));
+ return true;
+}
+/*
+ @doc: str.upcase
+ @type:
+ function
+ @title:
+ $str.upcase
+ @short:
+ Returns the given string with all characters turned to upper case
+ @syntax:
+ <string> $str.upcase(<string_to_convert:string>)
+ @description:
+ Returns the given <string_to_convert> with all characters turned to lower case.
+ Warning: this function uses ISO-8859-1 locale to make the case translation.
+ If you want to use a locale aware translation mapping then please
+ use $str.localeupcase.
+*/
+
+static bool str_kvs_fnc_upcase(KviKvsModuleFunctionCall * c)
+{
+ QString szString;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("string_to_convert",KVS_PT_STRING,0,szString)
+ KVSM_PARAMETERS_END(c)
+ c->returnValue()->setString(KviQString::upperISO88591(szString));
+ return true;
+}
+/*
+ @doc: str.localelowcase
+ @type:
+ function
+ @title:
+ $str.localelowcase
+ @short:
+ Returns the given string with all characters turned to lower case
+ @syntax:
+ <string> $str.localelowcase(<string_to_convert:string>)
+ @description:
+ Returns the given <string_to_convert> with all characters turned to lower case.
+ Warning: this function is locale aware and it may produce unexpected
+ results in locales that contain strange exceptions (like Turkish which maps
+ i to Y with an accent). For IRC interaction you might prefer using $str.lowcase
+*/
+
+static bool str_kvs_fnc_localelowcase(KviKvsModuleFunctionCall * c)
+{
+ QString szString;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("string_to_convert",KVS_PT_STRING,0,szString)
+ KVSM_PARAMETERS_END(c)
+ c->returnValue()->setString(szString.lower());
+ return true;
+}
+
+/*
+ @doc: str.localeupcase
+ @type:
+ function
+ @title:
+ $str.localeupcase
+ @short:
+ Returns the given string with all characters turned to upper case
+ @syntax:
+ <string> $str.localeupcase(<string_to_convert:string>)
+ @description:
+ Returns the given <string_to_convert> with all characters turned to lower case.
+ Warning: this function is locale aware and it may produce unexpected
+ results in locales that contain strange exceptions (like Turkish which maps
+ i to Y with an accent). For IRC interaction you might prefer using $str.upcase
+*/
+
+static bool str_kvs_fnc_localeupcase(KviKvsModuleFunctionCall * c)
+{
+ QString szString;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("string_to_convert",KVS_PT_STRING,0,szString)
+ KVSM_PARAMETERS_END(c)
+ c->returnValue()->setString(szString.upper());
+ return true;
+}
+
+/*
+ @doc: str.isnumber
+ @type:
+ function
+ @title:
+ $str.isnumber
+ @short:
+ Returns 1 if the given string represents a number
+ @syntax:
+ <bool> $str.isnumber(<givenstring:string>)
+ @description:
+ Returns 1 if the given string represents a number, 0 if not.
+*/
+
+static bool str_kvs_fnc_isnumber(KviKvsModuleFunctionCall * c)
+{
+ KviKvsVariant * v;
+ KviKvsNumber num;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("givenstring",KVS_PT_VARIANT,0,v)
+ KVSM_PARAMETERS_END(c)
+ c->returnValue()->setBoolean(v->asNumber(num));
+ return true;
+}
+
+
+/*
+ @doc: str.isunsignednumber
+ @type:
+ function
+ @title:
+ $str.isunsignednumber
+ @short:
+ Returns 1 if the given string represents an unsigned number
+ @syntax:
+ <bool> $str.isunsignednumber(<givenstring:string>)
+ @description:
+ Returns 1 if the given string represents an unsigned number, 0 if not.
+*/
+
+static bool str_kvs_fnc_isunsignednumber(KviKvsModuleFunctionCall * c)
+{
+ KviKvsVariant * v;
+ KviKvsNumber nNum;
+ bool bRet;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("givenstring",KVS_PT_VARIANT,0,v)
+ KVSM_PARAMETERS_END(c)
+ if(!v->asNumber(nNum)) bRet = false;
+ else
+ {
+ if(nNum.isInteger())
+ {
+ bRet = nNum.integer() >= 0;
+ }
+ else
+ {
+ bRet = nNum.real() >= 0.0;
+ }
+ }
+ c->returnValue()->setBoolean(bRet);
+ return true;
+}
+
+/*
+ @doc: str.isempty
+ @type:
+ function
+ @title:
+ $str.isempty
+ @short:
+ Returns 1 if the given string don't have any character.
+ @syntax:
+ <string> $str.isEmpty(<givenstring:string>)
+ @description:
+ Returns 1 if the given string don't have any character (that is, is empty).
+ This function is almost useless since it is equivalent to the
+ comparison with an empty string...
+*/
+
+static bool str_kvs_fnc_isempty(KviKvsModuleFunctionCall * c)
+{
+ QString v;
+ bool bRet;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("datastring",KVS_PT_STRING,0,v)
+ KVSM_PARAMETERS_END(c)
+ if(v.isEmpty()) bRet = true;
+ else bRet = false;
+ c->returnValue()->setBoolean(bRet);
+ return true;
+}
+
+/*
+ @doc: str.contains
+ @type:
+ function
+ @title:
+ $str.contains
+ @short:
+ Returns 1 if the first parameter contains the second
+ @syntax:
+ <bool> $str.contains(<container:string>,<tofind:string>)
+ @description:
+ Returns 1 if the first string parameter contains the second string parameter.
+ This function is case sensitive.
+ @seealso:
+ [fnc]$str.containsnocase[/fnc]()
+*/
+
+
+static bool str_kvs_fnc_contains(KviKvsModuleFunctionCall * c)
+{
+ QString szString,szSubString;
+ bool bIs;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("container",KVS_PT_STRING,0,szString)
+ KVSM_PARAMETER("tofind",KVS_PT_STRING,0,szSubString)
+ KVSM_PARAMETERS_END(c)
+ bIs = szString.find(szSubString) != -1;
+ c->returnValue()->setBoolean(bIs);
+ return true;
+}
+
+/*
+ @doc: str.containsnocase
+ @type:
+ function
+ @title:
+ $str.containsnocase
+ @short:
+ Returns 1 if the first parameter contains the second, case insensitive
+ @syntax:
+ <bool> $str.containsnocase(<container:string>,<tofind:string>)
+ @description:
+ Returns 1 if the first string parameter contains the second string parameter
+ whithout taking in consideration the case of the characters in the string.
+ @seealso:
+ [fnc]$str.contains[/fnc]
+*/
+
+static bool str_kvs_fnc_containsnocase(KviKvsModuleFunctionCall * c)
+{
+ QString szString,szSubString;
+ bool bIs;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("container",KVS_PT_STRING,0,szString)
+ KVSM_PARAMETER("tofind",KVS_PT_STRING,0,szSubString)
+ KVSM_PARAMETERS_END(c)
+ bIs = szString.find(szSubString,0,false) != -1;
+ c->returnValue()->setBoolean(bIs);
+ return true;
+}
+
+/*
+ @doc: str.equal
+ @type:
+ function
+ @title:
+ $str.equal
+ @short:
+ Returns 1 if the two string parameters are equal
+ @syntax:
+ <bool> $str.equal(<fromcompare:string>,<tocompare:string>)
+ @description:
+ Returns 1 if the two string parameters are equal. This function is case sensitive.
+ @seealso:
+ [fnc]$str.equalnocase[/fnc]()
+*/
+
+static bool str_kvs_fnc_equal(KviKvsModuleFunctionCall * c)
+{
+ QString szString,szString2;
+ bool bIs;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("fromcompare",KVS_PT_STRING,0,szString)
+ KVSM_PARAMETER("tocompare",KVS_PT_STRING,0,szString2)
+ KVSM_PARAMETERS_END(c)
+ bIs = KviQString::equalCS(szString,szString2);
+ c->returnValue()->setBoolean(bIs);
+ return true;
+}
+/*
+ @doc: str.equalnocase
+ @type:
+ function
+ @title:
+ $str.equalnocase
+ @short:
+ Returns 1 if the two string parameters are equal, case insensitive
+ @syntax:
+ <bool> $str.equalnocase(<fromcompare:string>,<tocompare:string>)
+ @description:
+ Returns 1 if the two strngs parameters are equal, without taking the case of the
+ characters in consideration.
+ @seealso:
+ [fnc]$str.equal[/fnc]()
+*/
+
+static bool str_kvs_fnc_equalnocase(KviKvsModuleFunctionCall * c)
+{
+ QString szString,szString2;
+ bool bIs;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("fromcompare",KVS_PT_STRING,0,szString)
+ KVSM_PARAMETER("tocompare",KVS_PT_STRING,0,szString2)
+ KVSM_PARAMETERS_END(c)
+ bIs = KviQString::equalCI(szString,szString2);
+ c->returnValue()->setBoolean(bIs);
+ return true;
+}
+
+/*
+ @doc: str.cmp
+ @type:
+ function
+ @title:
+ $str.cmp
+ @short:
+ Compare two strings alphabetically
+ @syntax:
+ <bool> $str.cmp(<fromcompare:string>,<tocompare:string>)
+ @description:
+ This function compares two strings alphabetically. If the first string is 'greater'
+ than the second, it will return a positive number, a negative number is the second is
+ greater and 0 if the two strings are equal.
+ @seealso:
+ [fnc]$str.cmpnocase[/fnc]()
+*/
+
+static bool str_kvs_fnc_cmp(KviKvsModuleFunctionCall * c)
+{
+ QString szString,szString2;
+ int iCmp;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("fromcompare",KVS_PT_STRING,0,szString)
+ KVSM_PARAMETER("tocompare",KVS_PT_STRING,0,szString2)
+ KVSM_PARAMETERS_END(c)
+ iCmp = KviQString::cmpCS(szString,szString2);
+ c->returnValue()->setInteger(iCmp);
+ return true;
+}
+
+/*
+ @doc: str.cmpnocase
+ @type:
+ function
+ @title:
+ $str.cmpnocase
+ @short:
+ Compare two strings alphabetically, case insensitive.
+ @syntax:
+ <bool> $str.cmpnocase(<fromcompare:string>,<tocompare:string>)
+ @description:
+ This function compares two strings alphabetically. If the first string is 'greater'
+ than the second, it will return a positive number, a negative number is the second is
+ greater and 0 if the two strings are equal. This function is case insensitive.
+ @seealso:
+ [fnc]$str.cmp[/fnc]()
+*/
+static bool str_kvs_fnc_cmpnocase(KviKvsModuleFunctionCall * c)
+{
+ QString szString,szString2;
+ int iCmp;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("fromcompare",KVS_PT_STRING,0,szString)
+ KVSM_PARAMETER("tocompare",KVS_PT_STRING,0,szString2)
+ KVSM_PARAMETERS_END(c)
+ iCmp = KviQString::cmpCI(szString,szString2);
+ c->returnValue()->setInteger(iCmp);
+ return true;
+}
+
+/*
+ @doc: str.find
+ @type:
+ function
+ @title:
+ $str.find
+ @short:
+ Find the index of the nth ocurrence of a substring in a string
+ @syntax:
+ <int> $str.find(<findIn:string>,<tofind:string>[,ocurrence:int])
+ @description:
+ This function search in the string given as the first parameter for the string
+ given as his second parameter, and will return the index where the nth ocurrence
+ given as the third parameter is found or -1 if it's not located. It starts
+ counting at 0. If occurence is not specified then the first occurence
+ is searched. WARNING: The occurente number starts from 1! (Yes, that's a bug, but
+ for backward compatibility it must remain as it is :( ).[br]
+ FIXME: The semantics of this function are totally broken :(
+*/
+
+static bool str_kvs_fnc_find(KviKvsModuleFunctionCall * c)
+{
+ QString szFindIn, szToFind;
+ kvs_int_t iOcurence;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("findIn",KVS_PT_STRING,0,szFindIn)
+ KVSM_PARAMETER("tofind",KVS_PT_STRING,0,szToFind)
+ KVSM_PARAMETER("ocurrence",KVS_PT_INTEGER,KVS_PF_OPTIONAL,iOcurence)
+ KVSM_PARAMETERS_END(c)
+ int pos = 1;
+ if(iOcurence!=0)
+ pos = iOcurence;
+ if(pos<1)
+ {
+ c->returnValue()->setInteger(-1);
+ return true;
+ }
+ if(szFindIn.isEmpty())
+ {
+ c->returnValue()->setInteger(-1);
+ return true;
+ }
+ if(szToFind.isEmpty())
+ {
+ c->returnValue()->setInteger(-1);
+ return true;
+ }
+ int cnt = 1;
+ int idx;
+ int totalIdx = 0;
+
+ while (cnt<=pos)
+ {
+ idx = szFindIn.right(szFindIn.length() - totalIdx).find(szToFind);
+ if(idx == -1)
+ {
+ c->returnValue()->setInteger(-1);
+ return true;
+ }
+ //Idx only gives the index until the pos _before_ the matched string so if this is
+ //not the match we want (cont != 0) we skip it
+ totalIdx += (idx + (cnt == pos ? 0 : szToFind.length()));
+ ++cnt;
+ }
+ c->returnValue()->setInteger(totalIdx);
+ return true;
+}
+/*
+ @doc: str.findfirst
+ @type:
+ function
+ @title:
+ $str.findfirst
+ @short:
+ Find the index of a substring in a string
+ @syntax:
+ <int> $str.findfirst(<findIn:string>,<toFind:string>)
+ @description:
+ This function search in the string given as the first parameter for the string
+ given as his second parameter, and will return the index where is first located or
+ -1 if it's not located. It starts counting at 0.
+*/
+
+static bool str_kvs_fnc_findfirst(KviKvsModuleFunctionCall * c)
+{
+ QString szString,szString2;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("findIn",KVS_PT_STRING,0,szString)
+ KVSM_PARAMETER("toFind",KVS_PT_STRING,0,szString2)
+ KVSM_PARAMETERS_END(c)
+ c->returnValue()->setInteger(szString.find(szString2));
+ return true;
+}
+/*
+ @doc: str.findfirstnocase
+ @type:
+ function
+ @title:
+ $str.findfirstnocase
+ @short:
+ Find the index of a substring in a string, case insensitive
+ @syntax:
+ <int> $str.findfirstnocase(<findIn:string>,<toFind:string>)
+ @description:
+ This function search in the string given as the first parameter for the string
+ given as his second parameter, and will return the index where is first located or
+ -1 if it's not located. This function is case insensitive.
+*/
+
+static bool str_kvs_fnc_findfirstnocase(KviKvsModuleFunctionCall * c)
+{
+ QString szString,szString2;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("findIn",KVS_PT_STRING,0,szString)
+ KVSM_PARAMETER("toFind",KVS_PT_STRING,0,szString2)
+ KVSM_PARAMETERS_END(c)
+ c->returnValue()->setInteger(szString.find(szString2,0,false));
+ return true;
+}
+/*
+ @doc: str.findlast
+ @type:
+ function
+ @title:
+ $str.findlast
+ @short:
+ Find the last index of a substring in a string
+ @syntax:
+ <int> $str.findlast(<findIn:string>,<toFind:string>)
+ @description:
+ This function search in the string given as the first parameter for the string
+ given as his second parameter, and will return the index where is last located or
+ -1 if it's not located.
+*/
+
+static bool str_kvs_fnc_findlast(KviKvsModuleFunctionCall * c)
+{
+ QString szString,szString2;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("findIn",KVS_PT_STRING,0,szString)
+ KVSM_PARAMETER("toFind",KVS_PT_STRING,0,szString2)
+ KVSM_PARAMETERS_END(c)
+ c->returnValue()->setInteger(szString.findRev(szString2));
+ return true;
+}
+/*
+ @doc: str.findlastnocase
+ @type:
+ function
+ @title:
+ $str.findlastnocase
+ @short:
+ Find the last index of a substring in a string, case insensitive
+ @syntax:
+ <int> $str.findlastnocase(<findIn:string>,<toFind:string>)
+ @description:
+ This function search in the string given as the first parameter for the string
+ given as his second parameter, and will return the index where is last located or
+ -1 if it's not located. This function is case insensitive.
+*/
+
+static bool str_kvs_fnc_findlastnocase(KviKvsModuleFunctionCall * c)
+{
+ QString szString,szString2;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("findIn",KVS_PT_STRING,0,szString)
+ KVSM_PARAMETER("toFind",KVS_PT_STRING,0,szString2)
+ KVSM_PARAMETERS_END(c)
+ c->returnValue()->setInteger(szString.findRev(szString2,-1,false));
+ return true;
+}
+/*
+ @doc: str.left
+ @type:
+ function
+ @title:
+ $str.left
+ @short:
+ Returns a substring starting from the left until the given index.
+ @syntax:
+ <string> $str.left(<data:string>,<index:int>)
+ @description:
+ This function returns a substring of the first string parameter which is the
+ string starting from the left until the index specified in the second parameter.
+*/
+
+static bool str_kvs_fnc_left(KviKvsModuleFunctionCall * c)
+{
+ QString szString;
+ kvs_int_t iIdx;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("data",KVS_PT_STRING,0,szString)
+ KVSM_PARAMETER("index",KVS_PT_INTEGER,0,iIdx)
+ KVSM_PARAMETERS_END(c)
+ c->returnValue()->setString(szString.left(iIdx));
+ return true;
+}
+/*
+ @doc: str.right
+ @type:
+ function
+ @title:
+ $str.right
+ @short:
+ Returns a substring starting from the right until the given index.
+ @syntax:
+ <string> $str.right(<data:string>,<index:int>)
+ @description:
+ This function returns a substring of the first string parameter which is the
+ string starting from the right until the index specified in the second parameter.
+ The index start counting at the last character and increase until the first.
+*/
+
+static bool str_kvs_fnc_right(KviKvsModuleFunctionCall * c)
+{
+ QString szString;
+ kvs_int_t iIdx;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("data",KVS_PT_STRING,0,szString)
+ KVSM_PARAMETER("index",KVS_PT_INTEGER,0,iIdx)
+ KVSM_PARAMETERS_END(c)
+ c->returnValue()->setString(szString.right(iIdx));
+ return true;
+}
+/*
+ @doc: str.mid
+ @type:
+ function
+ @title:
+ $str.mid
+ @short:
+ Returns a substring starting from a given index.
+ @syntax:
+ <string> $str.mid(<data:string>,<startidx:int>,<nchars:int>)
+ @description:
+ This function returns a substring of the first string parameter wich is the
+ string starting at the (numeric) index given with startidx and counting nchars
+ forward.
+*/
+
+static bool str_kvs_fnc_mid(KviKvsModuleFunctionCall * c)
+{
+ QString szString;
+ kvs_int_t iIdx,iNchars;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("data",KVS_PT_STRING,0,szString)
+ KVSM_PARAMETER("startidx",KVS_PT_INTEGER,0,iIdx)
+ KVSM_PARAMETER("nchars",KVS_PT_INTEGER,0,iNchars)
+ KVSM_PARAMETERS_END(c)
+ c->returnValue()->setString(szString.mid(iIdx,iNchars));
+ return true;
+}
+/*
+ @doc: str.append
+ @type:
+ function
+ @title:
+ $str.append
+ @short:
+ Append one string to another.
+ @syntax:
+ <string> $str.append(<string:string>,<toappend:string>)
+ @description:
+ This function returns a string created appending the second string parameter
+ to the end of the first string parameter.
+*/
+
+static bool str_kvs_fnc_append(KviKvsModuleFunctionCall * c)
+{
+ QString szString,szString2;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("string",KVS_PT_STRING,0,szString)
+ KVSM_PARAMETER("toappend",KVS_PT_STRING,0,szString2)
+ KVSM_PARAMETERS_END(c)
+ c->returnValue()->setString(szString.append(szString2));
+ return true;
+}
+/*
+ @doc: str.prepend
+ @type:
+ function
+ @title:
+ $str.prepend
+ @short:
+ Prepend one string to another.
+ @syntax:
+ <string> $str.prepend(<string:string>,<toprepend:string>)
+ @description:
+ This function returns a string created prepending the second string parameter
+ to the start of the first string parameter.
+*/
+
+static bool str_kvs_fnc_prepend(KviKvsModuleFunctionCall * c)
+{
+ QString szString,szString2;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("string",KVS_PT_STRING,0,szString)
+ KVSM_PARAMETER("toprepend",KVS_PT_STRING,0,szString2)
+ KVSM_PARAMETERS_END(c)
+ c->returnValue()->setString(szString.prepend(szString2));
+ return true;
+}
+/*
+ @doc: str.insert
+ @type:
+ function
+ @title:
+ $str.insert
+ @short:
+ Inserts a substring in a string at a given index
+ @syntax:
+ <string> $str.insert(<string:string>,<substring:string>,<index:int>)
+ @description:
+ Inserts the substring given in the second parameter in the string given in the
+ first parameter at the index given in the third parameter, then returns the
+ resulting string.
+*/
+
+static bool str_kvs_fnc_insert(KviKvsModuleFunctionCall * c)
+{
+ QString szString,szString2;
+ kvs_int_t iIdx;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("string",KVS_PT_STRING,0,szString)
+ KVSM_PARAMETER("substring",KVS_PT_STRING,0,szString2)
+ KVSM_PARAMETER("nchars",KVS_PT_INTEGER,0,iIdx)
+ KVSM_PARAMETERS_END(c)
+ c->returnValue()->setString(szString.insert(iIdx,szString2));
+ return true;
+}
+/*
+ @doc: str.strip
+ @type:
+ function
+ @title:
+ $str.strip
+ @short:
+ Returns a whitespace stripped string
+ @syntax:
+ <string> $str.strip(<string:string>)
+ @description:
+ Returns a left and right whitespace stripped version of the string given as the
+ first parameter.
+*/
+
+static bool str_kvs_fnc_strip(KviKvsModuleFunctionCall * c)
+{
+ QString szString;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("string",KVS_PT_STRING,0,szString)
+ KVSM_PARAMETERS_END(c)
+ c->returnValue()->setString(szString.stripWhiteSpace());
+ return true;
+}
+/*
+ @doc: str.stripleft
+ @type:
+ function
+ @title:
+ $str.stripleft
+ @short:
+ Returns a left whitespace stripped string
+ @syntax:
+ <string> $str.stripleft(<string:string>)
+ @description:
+ Returns a left whitespace stripped version of the string given as the
+ first parameter.
+*/
+
+static bool str_kvs_fnc_stripleft(KviKvsModuleFunctionCall * c)
+{
+ QString szString;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("string",KVS_PT_STRING,0,szString)
+ KVSM_PARAMETERS_END(c)
+ if(szString.length() > 0)
+ {
+ int idx = 0;
+ while(szString[idx].isSpace())idx++;
+ if(idx > 0)szString.remove(0,idx);
+ }
+ c->returnValue()->setString(szString);
+ return true;
+}
+/*
+ @doc: str.stripright
+ @type:
+ function
+ @title:
+ $str.stripright
+ @short:
+ Returns a right whitespace stripped string
+ @syntax:
+ <string> $str.stripright(<string:string>)
+ @description:
+ Returns a right whitespace stripped version of the string given as the
+ first parameter.
+*/
+
+static bool str_kvs_fnc_stripright(KviKvsModuleFunctionCall * c)
+{
+ QString szString;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("string",KVS_PT_STRING,0,szString)
+ KVSM_PARAMETERS_END(c)
+ int iIdx = 0;
+ while(szString.at(szString.length() - (iIdx+1)).isSpace()) iIdx++;
+ if(iIdx > 0)szString.remove(szString.length() - iIdx,iIdx);
+ c->returnValue()->setString(szString);
+ return true;
+}
+
+/*
+ @doc: str.stripcolors
+ @type:
+ function
+ @title:
+ $str.stripcolors
+ @short:
+ Returns a mirc color codes stripped string
+ @syntax:
+ <string> $str.stripcolors(<string:string>)
+ @description:
+ Removes all mirc color codes from a string, including also bold, underline, reverse,
+ icon, crypting and ctcp control codes.
+*/
+
+static bool str_kvs_fnc_stripcolors(KviKvsModuleFunctionCall * c)
+{
+ QString szString;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("string",KVS_PT_STRING,0,szString)
+ KVSM_PARAMETERS_END(c)
+ c->returnValue()->setString(KviMircCntrl::stripControlBytes(szString));
+ return true;
+}
+
+/*
+ @doc: str.replace
+ @type:
+ function
+ @title:
+ $str.replace
+ @short:
+ Replace substrings in a string
+ @syntax:
+ <string> $str.replace(<string:string>,<replacewith:string>,<toreplace:string>)
+ @description:
+ This function returns a string created replacing all ocurrences of the third parameter
+ ('toreplace') in the string given as the first parameter ('string') with the string
+ given as the second parameter ('replacewith').
+ The string replacement is case sensitive!.
+ FIXME: The order of the parameters in this function is illogical (and probably incompatible
+ with any other scripting language) :D
+ @examples:
+ [example]
+ echo $str.replace("I like big networks","neural","big")
+ [/example]
+*/
+
+static bool str_kvs_fnc_replace(KviKvsModuleFunctionCall * c)
+{
+ QString szString,szNewstr,szToreplace;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("string",KVS_PT_STRING,0,szString)
+ KVSM_PARAMETER("newstr",KVS_PT_STRING,0,szNewstr)
+ KVSM_PARAMETER("toreplace",KVS_PT_STRING,0,szToreplace)
+ KVSM_PARAMETERS_END(c)
+ szString.replace(szToreplace,szNewstr);
+ c->returnValue()->setString(szString);
+ return true;
+}
+
+/*
+ @doc: str.replacenocase
+ @type:
+ function
+ @title:
+ $str.replacenocase
+ @short:
+ Replace substrings in a string ignoring case
+ @syntax:
+ <string> $str.replacenocase(<string:string>,<newstr:string>,<toreplace:string>)
+ @description:
+ This function returns a string created replacing all ocurrences of the third parameter
+ ('toreplace') in the string given as the first parameter ('string') with the string
+ given as the second parameter ('newstr').[br]
+ The replacement is case insensitive.[br]
+ FIXME: The order of the parameters in this function is illogical (and probably incompatible
+ with any other scripting language) :D
+*/
+
+static bool str_kvs_fnc_replacenocase(KviKvsModuleFunctionCall * c)
+{
+ QString szString,szNewstr,szToreplace;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("string",KVS_PT_STRING,0,szString)
+ KVSM_PARAMETER("newstr",KVS_PT_STRING,0,szNewstr)
+ KVSM_PARAMETER("toreplace",KVS_PT_STRING,0,szToreplace)
+ KVSM_PARAMETERS_END(c)
+ szString.replace(szToreplace,szNewstr,false);
+ c->returnValue()->setString(szString);
+ return true;
+}
+
+/*
+ @doc: str.urlencode
+ @type:
+ function
+ @title:
+ $str.urlencode
+ @short:
+ Returns a browser formatted string
+ @syntax:
+ <string> $str.urlencode(<string:string>)
+ @description:
+ This function returns a string created replacing all ocurrences in the parameter ('string') with their respective html entities.[br]
+ The replacement is case insensitive.[br]
+ FIXME: This function use the same replace order as $str.replace so it incompatible
+ with any other scripting language) :D
+*/
+
+static bool str_kvs_fnc_urlencode(KviKvsModuleFunctionCall * c)
+{
+ QString szString,szNewstr;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("string",KVS_PT_STRING,0,szString)
+ KVSM_PARAMETERS_END(c)
+
+ char * toReplace[]={" ", "#", "$", "&", "/", ":", "<", "=", ">", "?", "@", "[", "\\", "]", "^", "`", "{", "|", "}", "~"};
+ char * newStr[]={"%20", "%23", "%24", "&amp;", "%2F", "%3A", "&lt;", "%3D", "&gt;", "%3F", "%40", "%5B", "%5C", "%5D", "%5E", "%60", "%7B", "%7C", "%7D", "%7E"};
+
+ /*
+ for(int idx=0,idx<22,idx++)
+ szNewstr=szString.replace(toReplace[idx],newStr[idx],false);
+ */
+
+ int idx=0;
+ while(idx<20){
+ szNewstr=szString.replace(toReplace[idx],newStr[idx],false);
+ idx++;
+ }
+
+ c->returnValue()->setString(szNewstr);
+ return true;
+}
+
+/*
+ @doc: str.lefttofirst
+ @type:
+ function
+ @title:
+ $str.lefttofirst
+ @short:
+ Returns the left part of a string until a given substring
+ @syntax:
+ <string> $str.lefttofirst(<string:string>,<substring:string>)
+ @description:
+ This function returns the left part of the string given as the first parameter
+ from the start until the string given as the second parameter is found. It don't
+ include the substring of the second parameter in the returned value. If the second
+ parameter is not found, the entire string is returned.
+ The match is case insensitive.
+*/
+
+static bool str_kvs_fnc_lefttofirst(KviKvsModuleFunctionCall * c)
+{
+ QString szString,szNewstr;
+ int where;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("string",KVS_PT_STRING,0,szString)
+ KVSM_PARAMETER("substring",KVS_PT_STRING,0,szNewstr)
+ KVSM_PARAMETERS_END(c)
+ where = szString.find(szNewstr,false);
+ if(where != -1) c->returnValue()->setString(szString.left(where));
+ else c->returnValue()->setString(szString);
+ return true;
+}
+/*
+ @doc: str.lefttolast
+ @type:
+ function
+ @title:
+ $str.lefttolast
+ @short:
+ Returns the left part of a string until the last ocurrence of a given substring
+ @syntax:
+ <string> $str.lefttolast(<string:string>,<substring:string>)
+ @description:
+ This function returns the left part of the string given as the first parameter
+ from the start until the last ocurrence of the string given as the second parameter
+ is found. It don't include the substring of the second parameter in the returned value.
+ If the second parameter is not found, the entire string is returned.
+ The match is case insensitive
+*/
+
+static bool str_kvs_fnc_lefttolast(KviKvsModuleFunctionCall * c)
+{
+ QString szString,szNewstr;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("string",KVS_PT_STRING,0,szString)
+ KVSM_PARAMETER("substring",KVS_PT_STRING,0,szNewstr)
+ KVSM_PARAMETERS_END(c)
+ int where = szString.findRev(szNewstr,-1,false);
+ if(where != -1) c->returnValue()->setString(szString.left(where));
+ else c->returnValue()->setString(szString);
+ return true;
+}
+/*
+ @doc: str.rightfromfirst
+ @type:
+ function
+ @title:
+ $str.rightfromfirst
+ @short:
+ Returns the right part of a string from the first ocurrence of a given substring
+ @syntax:
+ <string> $str.rightfromfirst(<string:string>,<substring:string>)
+ @description:
+ This function returns the right part of the string given as the first parameter
+ from the position where the first ocurrence of the string given as the second parameter
+ is found. It don't include the substring of the second parameter in the returned value.
+ If the second parameter is not found, an empty string is returned..
+ The match is case insensitive
+*/
+
+static bool str_kvs_fnc_rightfromfirst(KviKvsModuleFunctionCall * c)
+{
+ QString szString,szNewstr;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("string",KVS_PT_STRING,0,szString)
+ KVSM_PARAMETER("substring",KVS_PT_STRING,0,szNewstr)
+ KVSM_PARAMETERS_END(c)
+ int idx = szString.find(szNewstr,false);
+ if(idx != -1) c->returnValue()->setString(szString.right(szString.length()-(idx+szNewstr.length())));
+ else c->returnValue()->setString("");
+ return true;
+}
+/*
+ @doc: str.rightfromlast
+ @type:
+ function
+ @title:
+ $str.rightfromlast
+ @short:
+ Returns the right part of a string from the last ocurrence of a given substring
+ @syntax:
+ <string> $str.rightfromlast(<string:string>,<substring:string>)
+ @description:
+ This function returns the right part of the string given as the first parameter
+ from the position where the last ocurrence of the string given as the second parameter
+ is found. It don't include the substring of the second parameter in the returned value.
+ If the second parameter is not found, an empty string is returned..
+ The match is case insensitive.
+*/
+
+
+static bool str_kvs_fnc_rightfromlast(KviKvsModuleFunctionCall * c)
+{
+ QString szString,szNewstr;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("string",KVS_PT_STRING,0,szString)
+ KVSM_PARAMETER("substring",KVS_PT_STRING,0,szNewstr)
+ KVSM_PARAMETERS_END(c)
+ int idx = szString.findRev(szNewstr,-1,false);
+ if(idx != -1) c->returnValue()->setString(szString.right(szString.length()-(idx+szNewstr.length())));
+ else c->returnValue()->setString("");
+ return true;
+}
+
+/*
+ @doc: str.match
+ @type:
+ function
+ @title:
+ $str.match
+ @short:
+ Matches a fixed string against a wildcard expression
+ @syntax:
+ <bool> $str.match(<expression:string>,<string:string>[,<flags:string>])
+ @description:
+ Returns 1 if the fixed <string> matches the <expression>, 0 otherwise.[br]
+ If <flags> contains the flag 'r' then <expression> is treated as a full
+ regular expression otherwise it is treated as a simple wildcard expression containing
+ the classic wildcards '*' and '?'.[br]
+ If <flags> contains the flag 'e' then only an exact match is considered (e.g. the full
+ <string> is exactly matched by <expression>), otherwise partial matches are allowed too (e.g.
+ <expression> is found inside <string>).[br]
+ The match is case sensitive.[br]
+ @examples:
+ [example]
+ %test = "Hello! My nickname is Pragma"
+ [cmd]if[/cmd]($str.match(Pragma*,%test))[cmd]echo[/cmd] "Matches Pragma*"
+ [cmd]if[/cmd]($str.match(*Pragma,%test))[cmd]echo[/cmd] "Matches *Pragma"
+ [cmd]if[/cmd]($str.match(H*y*i?k*a,%test))[cmd]echo[/cmd] "Matches H*y*i?k*a"
+ [cmd]if[/cmd]($str.match(H*y*i?K*a,%test))[cmd]echo[/cmd] "Matches H*y*i?K*a"
+ [/example]
+ @seealso:
+ [fnc]$str.matchnocase[/fnc]
+*/
+
+static bool str_kvs_fnc_match(KviKvsModuleFunctionCall * c)
+{
+ QString szWildcard,szString,szFlags;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("wildcard",KVS_PT_NONEMPTYSTRING,0,szWildcard)
+ KVSM_PARAMETER("string",KVS_PT_STRING,0,szString)
+ KVSM_PARAMETER("flags",KVS_PT_STRING,KVS_PF_OPTIONAL,szFlags)
+ KVSM_PARAMETERS_END(c)
+ bool bRegExp = (szFlags.find(QChar('r')) != -1) || (szFlags.find(QChar('R')) != -1);
+ bool bExact = (szFlags.find(QChar('e')) != -1) || (szFlags.find(QChar('E')) != -1);
+ c->returnValue()->setBoolean(KviQString::matchStringCS(szWildcard,szString,bRegExp,bExact));
+ return true;
+}
+
+/*
+ @doc: str.matchnocase
+ @type:
+ function
+ @title:
+ $str.matchnocase
+ @short:
+ Matches a fixed string against a wildcard expression (case insensitive)
+ @syntax:
+ <bool> $str.matchnocase(<expression>,<string:string>[,<flags:string>])
+ @description:
+ Returns 1 if the fixed <string> matches the <expression>, 0 otherwise.[br]
+ If <flags> contains the flag 'r' then <expression> is treated as a full
+ regular expression otherwise it is treated as a simple wildcard expression containing
+ the classic wildcards '*' and '?'.[br]
+ If <flags> contains the flag 'e' then only an exact match is considered (e.g. the full
+ <string> is exactly matched by <expression>), otherwise partial matches are allowed too (e.g.
+ <expression> is found inside <string>).[br]
+ The match is case insensitive.[br]
+ @examples:
+ [example]
+ %test = "Hello! My nickname is Pragma"
+ [cmd]if[/cmd]($str.match(pragma*,%test))[cmd]echo[/cmd] "Matches pragma*"
+ [cmd]if[/cmd]($str.match(*pragma,%test))[cmd]echo[/cmd] "Matches *pragma"
+ [cmd]if[/cmd]($str.match(H*y*i?k*a,%test))[cmd]echo[/cmd] "Matches H*y*i?k*a"
+ [cmd]if[/cmd]($str.match(H*y*i?K*a,%test))[cmd]echo[/cmd] "Matches H*y*i?K*a"
+ [cmd]if[/cmd]($str.match(G*if?sx,%test))[cmd]echo[/cmd] "Matches G*if?sx"
+ [/example]
+ @seealso:
+ [fnc]$str.match[/fnc]
+*/
+
+static bool str_kvs_fnc_matchnocase(KviKvsModuleFunctionCall * c)
+{
+ QString szWildcard,szString,szFlags;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("wildcard",KVS_PT_NONEMPTYSTRING,0,szWildcard)
+ KVSM_PARAMETER("string",KVS_PT_STRING,0,szString)
+ KVSM_PARAMETER("flags",KVS_PT_STRING,KVS_PF_OPTIONAL,szFlags)
+ KVSM_PARAMETERS_END(c)
+ bool bRegExp = (szFlags.find(QChar('r')) != -1) || (szFlags.find(QChar('R')) != -1);
+ bool bExact = (szFlags.find(QChar('e')) != -1) || (szFlags.find(QChar('E')) != -1);
+ c->returnValue()->setBoolean(KviQString::matchStringCI(szWildcard,szString,bRegExp,bExact));
+ return true;
+}
+
+/*
+
+ @doc: str.word
+ @type:
+ function
+ @title:
+ $str.word
+ @short:
+ Returns the nth word in a string
+ @syntax:
+ <string> $str.word(<n:int>,<string:string>)
+ @description:
+ Returns the nth word inside the <string> (with n starting from 0!)[br]
+ A word is a substring not containing spaces (ASCII chars 32, carriage returns , tabs etc...).[br]
+ If the string contains less than n+1 words then an empty string is returned.[br]
+ This function is faster than a call to [fnc]split[/fnc]() and array indexing
+ if you need a single word to be extracted from a complex string.[br]
+ If you need to manage more than one word from the string then the [fnc]split[/fnc]()
+ method is more efficient.[br]
+ This function is a special case of [fnc]$str.token[/fnc]() and it runs a bit faster.
+ @examples:
+ [example]
+ %test = "this is a string full of words"
+ [cmd]echo[/cmd] $str.word(4,%test)
+ [/example]
+ @seealso:
+ [fnc]$str.token[/fnc]
+*/
+
+static bool str_kvs_fnc_word(KviKvsModuleFunctionCall * c)
+{
+ QString szString;
+ kvs_int_t iOccurence;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("occurence",KVS_PT_INT,0,iOccurence)
+ KVSM_PARAMETER("string",KVS_PT_STRING,0,szString)
+ KVSM_PARAMETERS_END(c)
+ int idx = 0;
+ int cnt = 0;
+ int begin;
+ int len = szString.length();
+ while (idx<len)
+ {
+ QChar szTmp = szString[idx].unicode();
+ while (szTmp.isSpace())
+ {
+ idx++;
+ szTmp = szString[idx].unicode();
+ }
+ begin = idx;
+ while (idx<len && !szTmp.isSpace())
+ {
+ idx++;
+ szTmp = szString[idx].unicode();
+ }
+ if (iOccurence == (kvs_int_t)cnt)
+ {
+ c->returnValue()->setString(szString.mid(begin,idx-begin));
+ return true;
+ }
+ cnt ++;
+ }
+ return true;
+
+}
+/*
+ @doc: str.token
+ @type:
+ function
+ @title:
+ $str.token
+ @short:
+ Returns the nth token in a string
+ @syntax:
+ <string> $str.token(<n:int>,<separator:string>,<string:string>)
+ @description:
+ Returns the nth token inside the <string> (with n starting from 0!)[br]
+ A token is a substring not containing the characters listed in <separators>.[br]
+ If the string contains less than n+1 tokens then an empty string is returned.[br]
+ [fnc]$str.word[/fnc]() is an optimized function dedicated to the special case
+ in that <separators> is a string containing all the whitespace characters.[br]
+ Please note that this function is SLOW. You might want to take a look at [fnc]$str.word[/fnc]()
+ or even better to [fnc]$str.split[/fnc]().[br]
+ This function is case sensitive: you need to specify both cases in the <separators> string
+ if you want to do a case insensitive tokenization.[br]
+ @examples:
+ [example]
+ %test = "21 hours 10 minutes 15 seconds"
+ [cmd]echo[/cmd] $str.token(1," hoursmintecd",%test)
+ [/example]
+ @seealso:
+ [fnc]$str.word[/fnc][br]
+ [fnc]$str.split[/fnc][br]
+*/
+
+static bool str_kvs_fnc_token(KviKvsModuleFunctionCall * c)
+{
+ QString szString,sep;
+ kvs_uint_t n;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("n",KVS_PT_UINT,0,n)
+ KVSM_PARAMETER("separator",KVS_PT_STRING,0,sep)
+ KVSM_PARAMETER("string",KVS_PT_STRING,0,szString)
+ KVSM_PARAMETERS_END(c)
+ if(sep.isEmpty())
+ {
+ c->returnValue()->setString(szString);
+ return true;
+ }
+
+ int idx = 0;
+ int cnt = 0;
+ int begin;
+ int len = szString.length();
+ while (idx<len)
+ {
+ QChar szTmp = szString[idx].unicode();
+// while (szTmp==sep)
+ while (sep.contains(szTmp))
+ {
+ idx++;
+ szTmp = szString[idx].unicode();
+ }
+ begin = idx;
+ while (idx<len && !sep.contains(szTmp))
+ {
+ idx++;
+ szTmp = szString[idx].unicode();
+ }
+ if (n == cnt)
+ {
+ c->returnValue()->setString(szString.mid(begin,idx-begin));
+ return true;
+ }
+ cnt ++;
+ }
+ return true;
+}
+
+/*
+ @doc: str.charsum
+ @type:
+ function
+ @title:
+ $str.charsum
+ @short:
+ Returns the sum of the character codes of the string
+ @syntax:
+ <int> $str.charsum(<data:string>[,<bCaseInsensitive:boolean>])
+ @description:
+ Returns the sum of the character codes of the parameter <string>.
+ The sum is suitable for implementing a simple hashing algorithm.[br]
+ If <bCaseInsensitive> is specified and $true then the string
+ will be converted to lowercase first.
+*/
+
+
+static bool str_kvs_fnc_charsum(KviKvsModuleFunctionCall * c)
+{
+ QString szString;
+ bool bCaseInsensitive;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("data",KVS_PT_STRING,0,szString)
+ KVSM_PARAMETER("bCaseInsensitive",KVS_PT_BOOL,KVS_PF_OPTIONAL,bCaseInsensitive)
+ KVSM_PARAMETERS_END(c)
+ unsigned int sum = 0;
+ int idx = 0;
+ int len = szString.length();
+ if(bCaseInsensitive)
+ {
+ while(idx < len)
+ {
+ sum += szString[idx].lower().unicode();
+ idx++;
+ }
+ } else {
+ while(idx < len)
+ {
+ sum += szString[idx].unicode();
+ idx++;
+ }
+ }
+ c->returnValue()->setInteger(sum);
+ return true;
+}
+
+
+/*
+ @doc: str.digest
+ @type:
+ function
+ @title:
+ $str.digest
+ @short:
+ Returns the sum of the character codes of the string
+ @syntax:
+ <string> $str.digest(<data:string>[,<algorythm:string>])
+ @description:
+ Calculates digest for given string using algorithm passed as 2nd argument.
+ Currently supported: md5, md4, md2, sha1, mdc2, ripemd160, dss1
+ Default is md5. Requires OpenSSL support
+*/
+
+
+static bool str_kvs_fnc_digest(KviKvsModuleFunctionCall * c)
+{
+#ifdef COMPILE_SSL_SUPPORT
+ QString szString,szType,szResult;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("data",KVS_PT_NONEMPTYSTRING,0,szString)
+ KVSM_PARAMETER("algorythm",KVS_PT_NONEMPTYSTRING,KVS_PF_OPTIONAL,szType)
+ KVSM_PARAMETERS_END(c)
+
+ if(szType.isEmpty()) szType="md5";
+
+ EVP_MD_CTX mdctx;
+ const EVP_MD *md;
+ unsigned char md_value[EVP_MAX_MD_SIZE];
+ unsigned int md_len, i;
+ char buff[3];
+ OpenSSL_add_all_digests();
+
+ md = EVP_get_digestbyname(szType.utf8().data());
+ if(!md) {
+ c->warning(__tr2qs("%Q algorytm is not supported"),&szType);
+ return true;
+ }
+
+ EVP_MD_CTX_init(&mdctx);
+ EVP_DigestInit_ex(&mdctx, md, NULL);
+ EVP_DigestUpdate(&mdctx, szString.utf8().data(), szString.utf8().length());
+ EVP_DigestFinal_ex(&mdctx, md_value, &md_len);
+ EVP_MD_CTX_cleanup(&mdctx);
+
+ for(i = 0; i < md_len; i++)
+ {
+#ifdef COMPILE_ON_WINDOWS
+ _snprintf(buff,3,"%02x",md_value[i]);
+#else
+ snprintf(buff,3,"%02x",md_value[i]);
+#endif
+ szResult.append(buff);
+ }
+
+ c->returnValue()->setString(szResult);
+#else
+ c->warning(__tr2qs("KVIrc is compiled without OpenSSL support. $str.digest function disabled"));
+#endif
+
+ return true;
+}
+
+/*
+ @doc: str.join
+ @type:
+ function
+ @title:
+ $str.join
+ @short:
+ Returns a string joined from several strings
+ @syntax:
+ <string> $str.join(<separator:string>,<data:array>[,<flags:string>])
+ @description:
+ Joins all the string in the <data> array by using
+ the specified <separator> and returns the result.
+ If <flags> contains the character "n" then empty strings in teh <data>
+ array are skipped.
+
+*/
+
+
+static bool str_kvs_fnc_join(KviKvsModuleFunctionCall * c)
+{
+ QString szSep;
+ KviKvsArrayCast ac;
+ QString szFlags;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("separator",KVS_PT_STRING,0,szSep)
+ KVSM_PARAMETER("data",KVS_PT_ARRAYCAST,0,ac)
+ KVSM_PARAMETER("flags",KVS_PT_STRING,KVS_PF_OPTIONAL,szFlags)
+ KVSM_PARAMETERS_END(c)
+
+ QString szRet;
+ bool bSkipEmpty = szFlags.find('n',0,false) != -1;
+
+ bool bFirst = true;
+
+ if(KviKvsArray * a = ac.array())
+ {
+ kvs_uint_t uIdx = 0;
+ kvs_uint_t uSize = a->size();
+ while(uIdx < uSize)
+ {
+ KviKvsVariant * v = a->at(uIdx);
+ if(v)
+ {
+ QString tmp;
+ v->asString(tmp);
+ if(bFirst)
+ {
+ szRet = tmp;
+ bFirst = false;
+ } else {
+ szRet += szSep;
+ szRet += tmp;
+ }
+ } else {
+ if(!bSkipEmpty)
+ {
+ if(bFirst)
+ {
+ bFirst = false;
+ } else {
+ szRet += szSep;
+ }
+ }
+ }
+ uIdx++;
+ }
+ }
+
+ c->returnValue()->setString(szRet);
+ return true;
+}
+
+
+/*
+ @doc: str.grep
+ @type:
+ function
+ @title:
+ $str.grep
+ @short:
+ Emulates the GNU Regular Expression Parser
+ @syntax:
+ <array> $str.grep(<match:string>,<strings:array>[,<flags:string>])
+ @description:
+ Returns an array with the elements of <strings> which match the string <match>.
+ <flags> can be any combination of the characters 's','w' and 'r'.[br]
+ If the flag 'w' is specified then <match> is assumed to be a wildcard regular
+ expression (with * and ? wildcards). If the flag 'r' is specified
+ then <match> is assumed to be a standard regular expression. If none of
+ 'w' and 'r' is specified then <match> is treated as a simple string to be
+ searched in each element of the <strings> array. 'r' takes precedence over 'w'.
+ If the flag 's' is specified the matches are case sensitive.[br]
+ Note that since almost any other variable type can be automatically cast
+ to an array, then you can use this function also on scalars or hashes.
+ @examples:
+ [example]
+ [comment]# Find all the nicknames starting with the letter A or a[/comment]
+ [cmd]echo[/cmd] $str.grep("^a",[fnc]$chan.users[/fnc],"r")
+ [comment]# Find the current CPU speed (on UNIX like machines only)[/comment]
+ [cmd]echo[/cmd] $str.grep("MHz",[fnc]$str.split[/fnc]([fnc]$lf[/fnc],[fnc]$file.read[/fnc]("/proc/cpuinfo")))
+ [comment]# simply check if the specified string matches a regular expression[/comment]
+ [comment]# (this in fact is a little tricky, but you will probably not notice it :D)[/comment]
+ [cmd]if[/cmd]($str.grep("[st]+","test string","r"))[cmd]echo[/cmd] "Yeah, it matches!"
+ [/example]
+ @seealso:
+ [fnc]$array[/fnc]
+*/
+
+static bool str_kvs_fnc_grep(KviKvsModuleFunctionCall * c)
+{
+ KviKvsArrayCast ac;
+ QString szMatch,szFlags;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("match",KVS_PT_STRING,0,szMatch)
+ KVSM_PARAMETER("strings",KVS_PT_ARRAYCAST,0,ac)
+ KVSM_PARAMETER("flags",KVS_PT_STRING,KVS_PF_OPTIONAL,szFlags)
+ KVSM_PARAMETERS_END(c)
+
+ KviKvsArray * n = new KviKvsArray();
+ c->returnValue()->setArray(n);
+
+ KviKvsArray * a = ac.array();
+
+ bool bCaseSensitive = szFlags.find('s',0,false) != -1;
+ bool bRegexp = szFlags.find('r',0,false) != -1;
+ bool bWild = szFlags.find('w',0,false) != -1;
+ int idx = 0;
+ int cnt = a->size();
+
+ int i = 0;
+ if(bRegexp || bWild)
+ {
+ QRegExp re(szMatch,bCaseSensitive,bWild);
+ while(idx < cnt)
+ {
+ KviKvsVariant * v = a->at(idx);
+ if(v)
+ {
+ QString sz;
+ v->asString(sz);
+ if(re.search(sz) != -1)
+ {
+ n->set(i,new KviKvsVariant(sz));
+ i++;
+ }
+ }
+ idx++;
+ }
+ } else {
+ while(idx < cnt)
+ {
+ KviKvsVariant * v = a->at(idx);
+ if(v)
+ {
+ QString sz;
+ v->asString(sz);
+ if(sz.find(szMatch,0,bCaseSensitive) != -1)
+ {
+ n->set(i,new KviKvsVariant(sz));
+ i++;
+ }
+ }
+ idx++;
+ }
+ }
+
+ return true;
+}
+
+
+/*
+ @doc: str.split
+ @type:
+ function
+ @title:
+ $str.split
+ @short:
+ Splits a string to an array
+ @syntax:
+ <array> $str.split(<separator:string>,<data:string>[,<flags:string>[,<maxfields:integer>]])
+ @description:
+ Splits the <data> string by <separator> and returns an array of substrings.[br]
+ <flags> may be a combination of the characters 's', 'w', 'r' and 'n'.[br]
+ If s is specified, <separator> matching is case sensitive, otherwise is case insensitive.[br]
+ If w is specified, <separator> is treated as a wildcard-type regular expression
+ (with * and ? wildcars).[br]
+ If r is specified, <separator> is treated as a extended-type regular expression
+ (with character classes, special escapes etc..).[br]
+ If both w and r are specified w takes precedence.[br]
+ If none of w and r are specified <separator> is treated as a simple string to be matched.[br]
+ If 'n' is specified then eventual empty fields are discarded.[br]
+ If <maxfield> is specified then at most <maxfields> items are returned in the array (i.e. the last
+ item may be not splitted completly).
+ @examples:
+ [example]
+ [comment]# Split the fields[/comment]
+ %test[] = $str.split(!,"Field0!Field1!Field2!Field3!!Field5")
+ echo %test[]
+ %i = 0
+ [cmd]while[/cmd](%i < %test[]#)
+ {
+ [cmd]echo[/cmd] "Field %i: %test[%i]"
+ %i++;
+ }
+ [/example]
+ Regexp splitting:
+ [example]
+ %Test[] = $str.split("[ ]*[0-9][0-9]*-","AllOfThem: 1-Balboy 2-Pragma 3-Iakkolo 4-Crocodile",r)
+ echo %Test[]
+ %Test[] = $str.split("Y*H","hihiYeaHhohohoyeahYepYEAHhi",sw)
+ echo %Test[]
+ [/example]
+ If used in "non-array" context it returns just a comma separated list of substrings:[br]
+ [example]
+ [cmd]echo[/cmd] $str.split("[ ]*","Condense spaces and change &nbsp; &nbsp; all &nbsp; &nbsp; &nbsp; it in commas",r)
+ [/example]
+*/
+
+static bool str_kvs_fnc_split(KviKvsModuleFunctionCall * c)
+{
+ QString szSep,szStr,szFla;
+ kvs_int_t iMaxItems;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("separator",KVS_PT_STRING,0,szSep)
+ KVSM_PARAMETER("string",KVS_PT_STRING,0,szStr)
+ KVSM_PARAMETER("flags",KVS_PT_STRING,KVS_PF_OPTIONAL,szFla)
+ KVSM_PARAMETER("maxitems",KVS_PT_INTEGER,KVS_PF_OPTIONAL,iMaxItems)
+ KVSM_PARAMETERS_END(c)
+
+ if(c->params()->count() < 4)iMaxItems = -1;
+
+ KviKvsArray * a = new KviKvsArray();
+ c->returnValue()->setArray(a);
+
+ if(szSep.isEmpty())
+ {
+ a->set(0,new KviKvsVariant(szStr));
+ return true;
+ }
+
+ if(iMaxItems == 0)return true;
+
+ bool bWild = szFla.find('w',0,false) != -1;
+ bool bContainsR = szFla.find('r',0,false) != -1;
+ bool bCaseSensitive = szFla.find('s',0,false) != -1;
+ bool bNoEmpty = szFla.find('n',0,false) != -1;
+
+ int id = 0;
+
+ int iMatch = 0;
+ int iStrLen = szStr.length();
+ int iBegin = 0;
+
+ if(bContainsR || bWild)
+ {
+ QRegExp re(szSep,bCaseSensitive,bWild);
+
+ while((iMatch != -1) && (iMatch < iStrLen) && ((id < (iMaxItems-1)) || (iMaxItems < 0)))
+ {
+ iMatch = re.search(szStr,iBegin);
+ if(iMatch != -1)
+ {
+ int len = re.matchedLength();
+ if((len == 0) && (iBegin == iMatch))iMatch++; // safety measure for empty string matching
+
+ QString tmp = szStr.mid(iBegin,iMatch - iBegin);
+ if(bNoEmpty)
+ {
+ if(!tmp.isEmpty())
+ {
+ a->set(id,new KviKvsVariant(tmp));
+ id++;
+ }
+ } else {
+ a->set(id,new KviKvsVariant(tmp));
+ id++;
+ }
+
+ iMatch += len;
+ iBegin = iMatch;
+ }
+ }
+ } else {
+ while((iMatch != -1) && (iMatch < iStrLen) && ((id < (iMaxItems-1)) || (iMaxItems < 0)))
+ {
+ iMatch = szStr.find(szSep,iBegin,bCaseSensitive);
+ if(iMatch != -1)
+ {
+ QString tmp = szStr.mid(iBegin,iMatch - iBegin);
+ if(bNoEmpty)
+ {
+ if(!tmp.isEmpty())
+ {
+ a->set(id,new KviKvsVariant(tmp));
+ id++;
+ }
+ } else {
+ a->set(id,new KviKvsVariant(tmp));
+ id++;
+ }
+
+ iMatch += szSep.length();
+ iBegin = iMatch;
+ }
+ }
+ }
+
+ if(iBegin < iStrLen)
+ {
+ QString tmpx = szStr.right(iStrLen-iBegin);
+ if(bNoEmpty)
+ {
+ if(!tmpx.isEmpty())
+ a->set(id,new KviKvsVariant(tmpx));
+ } else {
+ a->set(id,new KviKvsVariant(tmpx));
+ }
+ } else {
+ if(!bNoEmpty)
+ a->set(id,new KviKvsVariant(QString::null)); // empty string at the end
+ }
+
+ return true;
+}
+
+/*
+ @doc: str.printf
+ @type:
+ function
+ @title:
+ $str.printf
+ @short:
+ Returns a formatted string in a C sprintf-like fashion.
+ @syntax:
+ <string> $str.printf(<format:string>[,<parameter:variant>[...]]);
+ @description:
+ This function acts like the C sprintf(): it returns
+ a string formatted by following the specification in <format>
+ and by using the following corresponding variadic parameters.
+ Since the percent sign is used as variable prefix in KVIrc,
+ this function uses the question mark '?' instead.[br]
+ The <format> string can contain the following escape sequences:[br]
+ [br]
+ [table]
+ [tr][td][b]?s[/b][/td][td]The next parameter is evaluated as a string and substituted in place of ?s[/td][/tr]
+ [tr][td][b]?d[/b][/td][td]The next parameter is evaluated as a signed integer and substituted in place of ?d[/td][/tr]
+ [tr][td][b]?i[/b][/td][td]Same as ?d[/td][/tr]
+ [tr][td][b]?u[/b][/td][td]The next parameter is evaluated as an unsigned signed integer and substituted in place of ?d[/td][/tr]
+ [tr][td][b]?x[/b][/td][td]The next parameter is evaluated as an unsigned integer and its hexadecimal rappresentation
+ is substituted in place of ?x[/td][/tr]
+ [tr][td][b]?h[/b][/td][td]Same as ?x[/td][/tr]
+ [tr][td][b]?X[/b][/td][td]Same as ?x but uppercase hexadecimal digits are used[/td][/tr]
+ [tr][td][b]?H[/b][/td][td]Same as ?X[/td][/tr]
+ [tr][td][b]??[/b][/td][td]A literal question mark[/td][/tr]
+ [tr][td][b]?[.N]f[/b][/td][td]The next parameter is evaluated as a real floating point value
+ and its rappresentation substituted in place of ?f. The optional [.N] modifier,
+ where N is an unsigned integer, rappresents the desired precision.[/td][/tr]
+ [tr][td][b]?[.N]e[/b][/td][td]The next parameter is evaluated as a real floating point value
+ and its scientific rappresentation substituted in place of ?e. The optional [.N] modifier,
+ where N is an unsigned integer, rappresents the desired precision.[/td][/tr]
+ [tr][td][b]?[.N]E[/b][/td][td]Same as ?e but an uppercase E is used as the exponent prefix[/td][/tr]
+ [/table]
+ @examples:
+ [example]
+ %val = $(1.0 / 3.0);
+ $str.printf("1/3 with a precision of 3 digits is ?.3f, while in scientific notation it's ?e",%val,%val)
+ [/example]
+*/
+
+
+static bool str_kvs_fnc_printf(KviKvsModuleFunctionCall * c)
+{
+ QString szFormat;
+ KviKvsVariantList vArgs;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("format",KVS_PT_STRING,0,szFormat)
+ KVSM_PARAMETER("vArgs",KVS_PT_VARIANTLIST,0,vArgs)
+ KVSM_PARAMETERS_END(c)
+
+ QString s;
+
+#define MEMINCREMENT 32
+
+ int reallen = 0;
+ int allocsize = MEMINCREMENT;
+
+ //s.setLength(allocsize);
+
+ const QChar * fmt = KviQString::nullTerminatedArray(szFormat);
+
+ if(fmt)
+ {
+ QChar * buffer = (QChar *)kvi_malloc(sizeof(QChar) * allocsize);
+ //QChar * p = (QChar *)s.unicode();
+
+ //9999999999999999999999999999999\0
+ char numberBuffer[1024];
+ char *pNumBuf;
+ kvs_uint_t tmp;
+ kvs_int_t argValue;
+ kvs_uint_t argUValue;
+ kvs_real_t argRValue;
+
+ QChar * p = buffer;
+
+ #define INCREMENT_MEM \
+ { \
+ allocsize += MEMINCREMENT; \
+ buffer = (QChar *)kvi_realloc(buffer,sizeof(QChar) * allocsize); \
+ p = buffer + reallen; \
+ }
+
+ #define INCREMENT_MEM_BY(numchars) \
+ { \
+ allocsize += numchars + MEMINCREMENT; \
+ buffer = (QChar *)kvi_realloc(buffer,sizeof(QChar) * allocsize); \
+ p = buffer + reallen; \
+ }
+
+ KviKvsVariant * pVar;
+
+ pVar = vArgs.first();
+
+ for(; fmt->unicode() ; ++fmt)
+ {
+ if(reallen == allocsize)INCREMENT_MEM
+
+ //copy up to a '?'
+ if(fmt->unicode() != '?')
+ {
+ *p++ = *fmt;
+ reallen++;
+ continue;
+ }
+
+ ++fmt; //skip this '?'
+ switch(fmt->unicode())
+ {
+ case 's':
+ {
+ QString sz;
+ if(pVar)pVar->asString(sz);
+ if(sz.isEmpty())continue;
+ int len = sz.length();
+ if((allocsize - reallen) < len)INCREMENT_MEM_BY(len)
+ const QChar * ch = sz.unicode();
+ while(len--)*p++ = *ch++;
+ reallen += sz.length();
+ pVar = vArgs.next();
+ continue;
+ }
+ case 'd': //signed integer
+ {
+ if(pVar)
+ {
+ if(!pVar->asInteger(argValue))
+ {
+ c->warning(__tr2qs("Invalid argument for ?d escape sequence, 0 assumed"));
+ argValue = 0;
+ }
+ } else {
+ c->warning(__tr2qs("Missing argument for ?d escape sequence, 0 assumed"));
+ argValue = 0;
+ }
+ argValue = 0;
+ if(argValue < 0)
+ { //negative integer
+ *p++ = '-';
+ reallen++;
+ argValue = -argValue; //need to have it positive
+ // most negative integer exception (avoid completely senseless (non digit) responses)
+ if(argValue < 0)argValue = 0; //we get -0 here
+ }
+ //write the number in a temporary buffer
+ pNumBuf = numberBuffer;
+ do {
+ tmp = argValue / 10;
+ *pNumBuf++ = argValue - (tmp * 10) + '0';
+ } while((argValue = tmp));
+ //copy now....
+ argUValue = pNumBuf - numberBuffer; //length of the number string
+ if((allocsize - reallen) < (int)argUValue)INCREMENT_MEM_BY(argUValue)
+ do { *p++ = QChar(*--pNumBuf); } while(pNumBuf != numberBuffer);
+ reallen += argUValue;
+ pVar = vArgs.next();
+ continue;
+ }
+ case 'u': //unsigned integer
+ {
+ if(pVar)
+ {
+ if(!pVar->asInteger(argValue))
+ {
+ c->warning(__tr2qs("Invalid argument for ?u escape sequence, 0 assumed"));
+ argValue = 0;
+ }
+ } else {
+ c->warning(__tr2qs("Missing argument for ?u escape sequence, 0 assumed"));
+ argValue = 0;
+ }
+ argUValue = (kvs_uint_t)argValue;
+ //write the number in a temporary buffer
+ pNumBuf = numberBuffer;
+ do {
+ tmp = argUValue / 10;
+ *pNumBuf++ = argUValue - (tmp * 10) + '0';
+ } while((argUValue = tmp));
+ //copy now....
+ argValue = pNumBuf - numberBuffer; //length of the number string
+ if((allocsize - reallen) < argValue)INCREMENT_MEM_BY(argValue)
+ do { *p++ = *--pNumBuf; } while(pNumBuf != numberBuffer);
+ reallen += argValue;
+ pVar = vArgs.next();
+ continue;
+ }
+ case 'h':
+ case 'x': // hexadecimal unsigned integer
+ {
+ static char hexsmalldigits[]="0123456789abcdef";
+
+ if(pVar)
+ {
+ if(!pVar->asInteger(argValue))
+ {
+ c->warning(__tr2qs("Invalid argument for ?x escape sequence, 0 assumed"));
+ argValue = 0;
+ }
+ } else {
+ c->warning(__tr2qs("Missing argument for ?x escape sequence, 0 assumed"));
+ argValue = 0;
+ }
+ argUValue = (kvs_uint_t)argValue;
+
+ //write the number in a temporary buffer
+ pNumBuf = numberBuffer;
+ do {
+ tmp = argUValue / 16;
+ *pNumBuf++ = hexsmalldigits[argUValue - (tmp * 16)];
+ } while((argUValue = tmp));
+ //copy now....
+ argValue = pNumBuf - numberBuffer; //length of the number string
+ if((allocsize - reallen) < argValue)INCREMENT_MEM_BY(argValue)
+ do { *p++ = *--pNumBuf; } while(pNumBuf != numberBuffer);
+ reallen += argValue;
+ pVar = vArgs.next();
+ continue;
+ }
+ case 'H':
+ case 'X': // hexadecimal unsigned integer
+ {
+ static char hexbigdigits[]="0123456789ABCDEF";
+ if(pVar)
+ {
+ if(!pVar->asInteger(argValue))
+ {
+ c->warning(__tr2qs("Invalid argument for ?X escape sequence, 0 assumed"));
+ argValue = 0;
+ }
+ } else {
+ c->warning(__tr2qs("Missing argument for ?X escape sequence, 0 assumed"));
+ argValue = 0;
+ }
+ argUValue = (kvs_uint_t)argValue;
+ //write the number in a temporary buffer
+ pNumBuf = numberBuffer;
+ do {
+ tmp = argUValue / 16;
+ *pNumBuf++ = hexbigdigits[argUValue - (tmp * 16)];
+ } while((argUValue = tmp));
+ //copy now....
+ argValue = pNumBuf - numberBuffer; //length of the number string
+ if((allocsize - reallen) < argValue)INCREMENT_MEM_BY(argValue)
+ do { *p++ = *--pNumBuf; } while(pNumBuf != numberBuffer);
+ reallen += argValue;
+ pVar = vArgs.next();
+ continue;
+ }
+ case '?':
+ {
+ if(fmt->unicode())
+ {
+ if(reallen == allocsize)INCREMENT_MEM
+ *p++ = *fmt;
+ reallen++;
+ }
+ continue;
+ }
+ break;
+ case '.':
+ {
+ // precision mark
+ const QChar * save = fmt;
+ fmt++;
+ unsigned int uPrecision = 0;
+
+ char fmtbuffer[8];
+ fmtbuffer[0] = '%';
+ fmtbuffer[1] = '.';
+
+ int idx = 2;
+
+ while((fmt->unicode() >= '0') && (fmt->unicode() <= '9') && (idx < 6))
+ {
+ uPrecision *= 10;
+ fmtbuffer[idx] = fmt->unicode();
+ uPrecision += fmtbuffer[idx] - '0';
+ fmt++;
+ idx++;
+ }
+ fmtbuffer[idx] = fmt->unicode();
+ fmtbuffer[idx+1] = 0;
+
+ if(pVar)
+ {
+ if(!pVar->asReal(argRValue))
+ {
+ c->warning(__tr2qs("Invalid argument for a floating point escape sequence, 0.0 assumed"));
+ argRValue = 0.0;
+ }
+ } else {
+ c->warning(__tr2qs("Missing argument for a floating point escape sequence, 0.0 assumed"));
+ argRValue = 0;
+ }
+ switch(fmt->unicode())
+ {
+ case 'e':
+ case 'E':
+ case 'F':
+ case 'f':
+ ::sprintf(numberBuffer,fmtbuffer,argRValue);
+ //copy now....
+ argValue = kvi_strLen(numberBuffer);
+ if((allocsize - reallen) < argValue)INCREMENT_MEM_BY(argValue)
+ pNumBuf = numberBuffer;
+ while(*pNumBuf){ *p++ = *pNumBuf++; }
+ reallen += argValue;
+ break;
+ default:
+ // anything else is crap.. invalid format
+ fmt = save;
+ *p++ = '?'; //write it
+ reallen++;
+ if(fmt->unicode())
+ {
+ if(reallen == allocsize)INCREMENT_MEM
+ *p++ = *fmt;
+ reallen++;
+ }
+ break;
+ }
+ pVar = vArgs.next();
+ continue;
+ }
+ break;
+ default: //a normal ? followed by some char
+ {
+ *p++ = '?'; //write it
+ reallen++;
+ if(fmt->unicode())
+ {
+ if(reallen == allocsize)INCREMENT_MEM
+ *p++ = *fmt;
+ reallen++;
+ }
+ continue;
+ }
+ }
+ }
+
+ s.setUnicode(buffer,reallen);
+ kvi_free(buffer);
+ }
+
+ c->returnValue()->setString(s);
+ return true;
+}
+
+
+
+/*********************************************************************/
+// Module stuff
+/********************************************************************/
+
+static bool str_module_init(KviModule * m)
+{
+ KVSM_REGISTER_FUNCTION(m,"split",str_kvs_fnc_split);
+ KVSM_REGISTER_FUNCTION(m,"grep",str_kvs_fnc_grep);
+ KVSM_REGISTER_FUNCTION(m,"charsum",str_kvs_fnc_charsum);
+ KVSM_REGISTER_FUNCTION(m,"len",str_kvs_fnc_len);
+ KVSM_REGISTER_FUNCTION(m,"length",str_kvs_fnc_len);
+ KVSM_REGISTER_FUNCTION(m,"isempty",str_kvs_fnc_isempty);
+ KVSM_REGISTER_FUNCTION(m,"join",str_kvs_fnc_join);
+
+ KVSM_REGISTER_FUNCTION(m,"section",str_kvs_fnc_section);
+ KVSM_REGISTER_FUNCTION(m,"lowcase",str_kvs_fnc_lowcase);
+ KVSM_REGISTER_FUNCTION(m,"upcase",str_kvs_fnc_upcase);
+ KVSM_REGISTER_FUNCTION(m,"localeupcase",str_kvs_fnc_localeupcase);
+ KVSM_REGISTER_FUNCTION(m,"localelowcase",str_kvs_fnc_localelowcase);
+ KVSM_REGISTER_FUNCTION(m,"isnumber",str_kvs_fnc_isnumber);
+ KVSM_REGISTER_FUNCTION(m,"isunsignednumber",str_kvs_fnc_isunsignednumber);
+ KVSM_REGISTER_FUNCTION(m,"contains",str_kvs_fnc_contains);
+ KVSM_REGISTER_FUNCTION(m,"containsnocase",str_kvs_fnc_containsnocase);
+ KVSM_REGISTER_FUNCTION(m,"equal",str_kvs_fnc_equal);
+ KVSM_REGISTER_FUNCTION(m,"equalnocase",str_kvs_fnc_equalnocase);
+ KVSM_REGISTER_FUNCTION(m,"cmp",str_kvs_fnc_cmp);
+ KVSM_REGISTER_FUNCTION(m,"cmpnocase",str_kvs_fnc_cmpnocase);
+ KVSM_REGISTER_FUNCTION(m,"find",str_kvs_fnc_find);
+ KVSM_REGISTER_FUNCTION(m,"findfirst",str_kvs_fnc_findfirst);
+ KVSM_REGISTER_FUNCTION(m,"findfirstnocase",str_kvs_fnc_findfirstnocase);
+ KVSM_REGISTER_FUNCTION(m,"findlast",str_kvs_fnc_findlast);
+ KVSM_REGISTER_FUNCTION(m,"findlastnocase",str_kvs_fnc_findlastnocase);
+ KVSM_REGISTER_FUNCTION(m,"left",str_kvs_fnc_left);
+ KVSM_REGISTER_FUNCTION(m,"right",str_kvs_fnc_right);
+ KVSM_REGISTER_FUNCTION(m,"mid",str_kvs_fnc_mid);
+ KVSM_REGISTER_FUNCTION(m,"append",str_kvs_fnc_append);
+ KVSM_REGISTER_FUNCTION(m,"prepend",str_kvs_fnc_prepend);
+ KVSM_REGISTER_FUNCTION(m,"insert",str_kvs_fnc_insert);
+ KVSM_REGISTER_FUNCTION(m,"strip",str_kvs_fnc_strip);
+ KVSM_REGISTER_FUNCTION(m,"stripright",str_kvs_fnc_stripright);
+ KVSM_REGISTER_FUNCTION(m,"stripleft",str_kvs_fnc_stripleft);
+ KVSM_REGISTER_FUNCTION(m,"stripcolors",str_kvs_fnc_stripcolors);
+ KVSM_REGISTER_FUNCTION(m,"replace",str_kvs_fnc_replace);
+ KVSM_REGISTER_FUNCTION(m,"replacenocase",str_kvs_fnc_replacenocase);
+ KVSM_REGISTER_FUNCTION(m,"urlencode",str_kvs_fnc_urlencode);
+ KVSM_REGISTER_FUNCTION(m,"lefttolast",str_kvs_fnc_lefttolast);
+ KVSM_REGISTER_FUNCTION(m,"lefttofirst",str_kvs_fnc_lefttofirst);
+ KVSM_REGISTER_FUNCTION(m,"rightfromfirst",str_kvs_fnc_rightfromfirst);
+ KVSM_REGISTER_FUNCTION(m,"rightfromlast",str_kvs_fnc_rightfromlast);
+ KVSM_REGISTER_FUNCTION(m,"match",str_kvs_fnc_match);
+ KVSM_REGISTER_FUNCTION(m,"matchnocase",str_kvs_fnc_matchnocase);
+ KVSM_REGISTER_FUNCTION(m,"word",str_kvs_fnc_word);
+ KVSM_REGISTER_FUNCTION(m,"token",str_kvs_fnc_token);
+ KVSM_REGISTER_FUNCTION(m,"fromClipboard",str_kvs_fnc_fromclipboard);
+ KVSM_REGISTER_FUNCTION(m,"digest",str_kvs_fnc_digest);
+ KVSM_REGISTER_FUNCTION(m,"printf",str_kvs_fnc_printf);
+
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"toClipboard",str_kvs_cmd_toClipboard);
+ return true;
+}
+
+static bool str_module_cleanup(KviModule *m)
+{
+ return true;
+}
+
+KVIRC_MODULE(
+ "File", // module name
+ "1.0.0", // module version
+ "Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot net)"\
+ " (C) 2002 Juanjo Alvarez (juanjux@yahoo.es)" \
+ " (C) 2005 Tonino Imbesi (grifisx at barmes dot org)" \
+ " (C) 2005 Alessandro Carbone (noldor at barmes dot org)", // author & (C)
+ "Interface to the str system",
+ str_module_init,
+ 0,
+ 0,
+ str_module_cleanup
+)
diff --git a/src/modules/system/Makefile.am b/src/modules/system/Makefile.am
new file mode 100644
index 00000000..69302d13
--- /dev/null
+++ b/src/modules/system/Makefile.am
@@ -0,0 +1,18 @@
+###############################################################################
+# KVirc IRC client Makesystem - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkvisystem.la
+
+libkvisystem_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkvisystem_la_SOURCES = libkvisystem.cpp plugin.cpp
+libkvisystem_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+noinst_HEADERS = plugin.h
+
+%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
diff --git a/src/modules/system/libkvisystem.cpp b/src/modules/system/libkvisystem.cpp
new file mode 100644
index 00000000..54ada405
--- /dev/null
+++ b/src/modules/system/libkvisystem.cpp
@@ -0,0 +1,749 @@
+//=============================================================================
+//
+// File : libkvisystem.cpp
+// Creation date : Fri Nov 16 03:50:12 2001 GMT by Szymon Stefanek
+//
+// This system is part of the KVirc irc client distribution
+// Copyright (C) 2001-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_module.h"
+#include "kvi_string.h"
+#include "kvi_library.h"
+#include "kvi_thread.h"
+
+#include "kvi_locale.h"
+#include "kvi_qcstring.h"
+#include "kvi_app.h"
+#include "kvi_env.h"
+#include "kvi_osinfo.h"
+#include "kvi_qcstring.h"
+
+#include <qclipboard.h>
+
+#ifndef COMPILE_ON_WINDOWS
+ #include <sys/utsname.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+#endif
+
+#ifdef COMPILE_KDE_SUPPORT
+ #include <dcopclient.h>
+#endif
+
+#include "kvi_modulemanager.h"
+
+#include "plugin.h"
+
+KviPluginManager * g_pPluginManager;
+
+/*
+ @doc: system.ostype
+ @type:
+ function
+ @title:
+ $system.ostype
+ @short:
+ Returns the type of the operating system
+ @syntax:
+ <string> $system.ostype()
+ @description:
+ Returns the current type of operating system: unix,macosx or windows.[br]
+*/
+
+static bool system_kvs_fnc_ostype(KviKvsModuleFunctionCall * c)
+{
+ c->returnValue()->setString(KviOsInfo::type());
+ return true;
+}
+/*
+ @doc: system.osname
+ @type:
+ function
+ @title:
+ $system.osname
+ @short:
+ Returns the name of the operating system
+ @syntax:
+ <string> $system.osname()
+ @description:
+ Returns the name of the operating system. On UNIX like machines
+ this is the field sysname of the utsname structure returned by
+ the uname() syscall.
+*/
+
+static bool system_kvs_fnc_osname(KviKvsModuleFunctionCall *c)
+{
+ c->returnValue()->setString(KviOsInfo::name());
+ return true;
+}
+
+
+/*
+ @doc: system.osversion
+ @type:
+ function
+ @title:
+ $system.osversion
+ @short:
+ Returns the version of the operating system
+ @syntax:
+ <string> $system.osversion()
+ @description:
+ Returns the version of the operating system.[br]
+*/
+
+static bool system_kvs_fnc_osversion(KviKvsModuleFunctionCall *c)
+{
+ // no params to process
+ c->returnValue()->setString(KviOsInfo::version());
+ return true;
+}
+
+/*
+ @doc: system.osrelease
+ @type:
+ function
+ @title:
+ $system.osrelease
+ @short:
+ Returns the release of the operating system
+ @syntax:
+ <string> $system.osrelease()
+ @description:
+ Returns the release of the operating system.[br]
+*/
+
+static bool system_kvs_fnc_osrelease(KviKvsModuleFunctionCall *c)
+{
+ // no params to process
+ c->returnValue()->setString(KviOsInfo::release());
+ return true;
+}
+
+/*
+ @doc: system.osmachine
+ @type:
+ function
+ @title:
+ $system.osmachine
+ @short:
+ Returns the machine of the operating system
+ @syntax:
+ <string> $system.osmachine()
+ @description:
+ Returns the machine of the operating system.[br]
+*/
+
+static bool system_kvs_fnc_osmachine(KviKvsModuleFunctionCall *c)
+{
+ // no params to process
+ c->returnValue()->setString(KviOsInfo::machine());
+ return true;
+}
+
+/*
+ @doc: system.osnodename
+ @type:
+ function
+ @title:
+ $system.osnodename
+ @short:
+ Returns the nodename of the operating system
+ @syntax:
+ <string> $system.osnodename()
+ @description:
+ Returns the nodename of the operating system.[br]
+*/
+
+static bool system_kvs_fnc_osnodename(KviKvsModuleFunctionCall *c)
+{
+ // no params to process
+ c->returnValue()->setString(KviOsInfo::nodename());
+ return true;
+}
+
+/*
+ @doc: system.getenv
+ @keyterms:
+ Enviroinement variables
+ @type:
+ function
+ @title:
+ $system.getenv
+ @short:
+ Returns the value of an enviroinement variable
+ @syntax:
+ <string> $system.getenv(<variable:string>)
+ @description:
+ Returns the value of the enviroinement <variable>.[br]
+*/
+
+static bool system_kvs_fnc_getenv(KviKvsModuleFunctionCall *c)
+{
+ QString szVariable;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("variable",KVS_PT_NONEMPTYSTRING,0,szVariable)
+ KVSM_PARAMETERS_END(c)
+
+ KviQCString szVar = szVariable.local8Bit();
+#ifdef COMPILE_ON_WINDOWS
+ QString env = getenv(szVar.data());
+ QString def = __tr2qs("No environment variable found, please don't use the %% in the request");
+ c->returnValue()->setString(env.isEmpty() ? QString::fromLocal8Bit(env) : QString::fromLocal8Bit(def));
+#else
+ char * b = kvi_getenv(szVar.data());
+ c->returnValue()->setString(b ? QString::fromLocal8Bit(b) : QString::null);
+#endif
+ return true;
+}
+
+/*
+ @doc: system.clipboard
+ @keyterms:
+ Clipboard management
+ @type:
+ function
+ @title:
+ $system.clipboard
+ @short:
+ Returns the value of the system clipboard
+ @syntax:
+ <string> $system.clipboard()
+ @description:
+ Returns the current value of the system clipboard.
+ Please note that there are systems that have the concept
+ of "selection" (most notably X11) which is NOT the same as the clipboard.
+ See [fnc]$system.selection[/fnc]().
+ @seealso:
+ [fnc]$system.selection[/fnc],
+ [cmd]system.setClipboard[/cmd],
+ [cmd]system.setSelection[/cmd]
+*/
+
+static bool system_kvs_fnc_clipboard(KviKvsModuleFunctionCall *c)
+{
+ c->returnValue()->setString(g_pApp->clipboard()->text(QClipboard::Clipboard));
+ return true;
+}
+
+
+/*
+ @doc: system.setClipboard
+ @type:
+ command
+ @title:
+ system.setClipboard
+ @keyterms:
+ Clipboard management
+ @short:
+ Sets the current system clipboard contents
+ @syntax:
+ system.setClipboard <data:string>
+ @description:
+ Sets the system clipboard contents to the string <data>.
+ Please note that there are systems that have the concept
+ of "selection" (most notably X11) which is NOT the same as the clipboard.
+ See [fnc]$system.selection[/fnc]().
+ @seealso:
+ [fnc]$system.selection[/fnc],
+ [fnc]$system.clipboard[/fnc],
+ [cmd]system.setSelection[/cmd]
+*/
+
+static bool system_kvs_cmd_setClipboard(KviKvsModuleCommandCall * c)
+{
+ QString szValue;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("data",KVS_PT_STRING,KVS_PF_OPTIONAL,szValue)
+ KVSM_PARAMETERS_END(c)
+ g_pApp->clipboard()->setText(szValue,QClipboard::Clipboard);
+ return true;
+}
+
+/*
+ @doc: system.setSelection
+ @type:
+ command
+ @title:
+ system.setSelection
+ @keyterms:
+ Clipboard management
+ @short:
+ Sets the current system selection contents
+ @syntax:
+ system.setSelection <data:string>
+ @description:
+ Sets the system selection contents to the string <data>.
+ Please note that this command will work only on systems that have the concept
+ of "selection" (most notably X11) which is NOT the same as the clipboard.
+ @seealso:
+ [fnc]$system.selection[/fnc],
+ [fnc]$system.clipboard[/fnc],
+ [cmd]system.setClipboard[/cmd]
+*/
+
+static bool system_kvs_cmd_setSelection(KviKvsModuleCommandCall * c)
+{
+ QString szValue;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("data",KVS_PT_STRING,KVS_PF_OPTIONAL,szValue)
+ KVSM_PARAMETERS_END(c)
+ g_pApp->clipboard()->setText(szValue,QClipboard::Selection);
+ return true;
+}
+
+/*
+ @doc: system.selection
+ @keyterms:
+ Clipboard management
+ @type:
+ function
+ @title:
+ $system.selection
+ @short:
+ Returns the value of the system selection
+ @syntax:
+ <string> $system.selection()
+ @description:
+ Returns the current value of the system selection.
+ This function will work only on systems that have the concept
+ of "selection" (most notably X11) which is NOT the same as clipboard.
+ On other systems this function will always return an empty string.
+ See [fnc]$system.clipboard[/fnc]().
+ @seealso:
+ [fnc]$system.clipboard[/fnc],
+ [cmd]system.setClipboard[/cmd],
+ [cmd]system.setSelection[/cmd]
+*/
+
+static bool system_kvs_fnc_selection(KviKvsModuleFunctionCall *c)
+{
+ c->returnValue()->setString(g_pApp->clipboard()->text(QClipboard::Selection));
+ return true;
+}
+
+
+/*
+ @doc: system.checkModule
+ @keyterms:
+ Module checking
+ @type:
+ function
+ @title:
+ $system.checkModule
+ @short:
+ Checks if a KVIrc module is loadable
+ @syntax:
+ <boolean> $system.checkModule(<module_name:string>)
+ @description:
+ Attempts to load the specified module and returns
+ $true if succesfull and $false otherwise. This can
+ be effectively used to test if a KVIrc exension module
+ is present on the system and can be loaded by the
+ KVIrc engine.
+*/
+
+static bool system_kvs_fnc_checkModule(KviKvsModuleFunctionCall *c)
+{
+ QString szModuleName;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("module_name",KVS_PT_STRING,0,szModuleName)
+ KVSM_PARAMETERS_END(c)
+
+ c->returnValue()->setBoolean(g_pModuleManager->loadModule(szModuleName.utf8().data()));
+ return true;
+}
+
+
+/*
+ @doc: system.hostname
+ @keyterms:
+ System information
+ @type:
+ function
+ @title:
+ $system.hostname
+ @short:
+ Returns the hostname of the machine that KVIrc is running on
+ @syntax:
+ <string> $system.hostname()
+ @description:
+ Returns the hostname of the machine that KVIrc is running on.[br]
+*/
+
+static bool system_kvs_fnc_hostname(KviKvsModuleFunctionCall *c)
+{
+ // no params to process
+ c->returnValue()->setString(KviOsInfo::hostname());
+ return true;
+}
+
+
+/*
+ @doc: system.dcop
+ @keyterms:
+ System information
+ @type:
+ function
+ @title:
+ $system.dcop
+ @short:
+ Performs a DCOP call
+ @syntax:
+ <variant> $system.dcop(<application:string>,<objectid:string>,<function:string>[,<parameter1:string>[,<parameter2:string>[,...]]])
+ @description:
+ This function allows performing simple DCOP calls without executing
+ an external process. This feature is available ONLY when KDE support
+ is compiled in the executable: this means that this function is absolutely
+ non portable (don't use it in scripts that you're going to distribute).
+ <application> is the name of the application being called, <objectid> is the
+ identifier of the object called, <function> is the function to be executed
+ on the remote object and <parameter1>,<parameter2>,... is the list of
+ parameters to be passed. The <function> name must contain the
+ trailing parenthesis and parameter specification (see examples).
+ The parameters MUST be in the form "type=value"
+ where "type" is the C++ type of the parameter and value
+ is the string rappresentation of the parameter data. Currently
+ KVIrc supports only QString,KviQCString,bool,int and uint data types.[br]
+ The returned value is the string rappresentation of the returned
+ data if the return type is known, otherwise it is the name of the data type returned.
+ [br]
+ If the application name is prefixed with "?" then the call is performed in "remote test"
+ mode: no "remote" errors are printed and the function returns 1 if the call executed
+ succesfully and 0 if the call failed. This can be used with the very first
+ call to programmaticaly test if the remote application is running.
+ @examples:
+ [example]
+ echo $system.dcop("kdesktop","KBackgroundIface","currentWallpaper(int)","int=0")
+ echo $system.dcop("kdesktop","KScreensaverIface","lock()")
+ # we can also ignore the return value in several ways
+ %dummy = $system.dcop("kicker","kicker","showKMenu()")
+ $system.dcop("kdesktop","KScreensaverIface","save()")
+ $system.dcop("kicker","Panel","addBrowserButton(QString)","QString=/")
+ # runtime test if a call would work (i.e. , kicker is running at all, parameters are right etc...)
+ if($system.dcop("?kicker","kicker","showKMenu()"))echo "Can't make dcop calls to kicker!"
+ [/example]
+*/
+
+static bool system_kvs_fnc_dcop(KviKvsModuleFunctionCall *c)
+{
+ bool bTestMode = false;
+
+ KviQCString szApp,szObj,szFun;
+ QStringList parms;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("application",KVS_PT_NONEMPTYCSTRING,0,szApp)
+ KVSM_PARAMETER("objectid",KVS_PT_NONEMPTYCSTRING,0,szObj)
+ KVSM_PARAMETER("function",KVS_PT_NONEMPTYCSTRING,0,szFun)
+ KVSM_PARAMETER("parameter_list",KVS_PT_STRINGLIST,KVS_PF_OPTIONAL,parms)
+ KVSM_PARAMETERS_END(c)
+
+ if((szApp.data()) && (szApp.length() > 1))
+ {
+ if(*(szApp.data()) == '?')
+ {
+ bTestMode = true;
+ szApp.remove(0,1);
+ }
+ }
+
+#ifdef COMPILE_KDE_SUPPORT
+
+ QByteArray ba;
+ QDataStream ds(ba, IO_WriteOnly);
+
+ for ( QStringList::Iterator it = parms.begin(); it != parms.end(); ++it )
+ {
+ KviStr tmp = *it;
+
+ if(tmp.isEmpty())
+ {
+ c->warning(__tr2qs("Invalid DCOP parameter syntax"));
+ return false;
+ }
+
+ KviStr szType = tmp.leftToFirst('=',false);
+ tmp.cutToFirst('=',true);
+ if(szType.isEmpty())szType = "int";
+ bool bOk;
+ if(kvi_strEqualCI("int",szType.ptr()) || kvi_strEqualCI("long",szType.ptr()))
+ {
+ int iii = tmp.toInt(&bOk);
+ if(!bOk)
+ {
+ c->warning(__tr2qs("The specified parameter is not an integer"));
+ return false;
+ }
+ ds << iii;
+ } else if(kvi_strEqualCI("QString",szType.ptr()))
+ {
+ QString ddd = tmp.ptr();
+ ds << ddd;
+ } else if(kvi_strEqualCI("KviQCString",szType.ptr()))
+ {
+ KviQCString qcs = tmp.ptr();
+ ds << qcs;
+ } else if(kvi_strEqualCI("bool",szType.ptr()))
+ {
+ bool bbb = kvi_strEqualCI(tmp.ptr(),"true");
+ ds << bbb;
+ } else if(kvi_strEqualCI("unsigned int",szType.ptr()) || kvi_strEqualCI("uint",szType.ptr()) || kvi_strEqualCI("Q_UINT32",szType.ptr()))
+ {
+ unsigned int uii = tmp.toUInt(&bOk);
+ if(!bOk)
+ {
+ c->warning(__tr2qs("The specified parameter is not an integer"));
+ return false;
+ }
+ ds << uii;
+ } else {
+ c->warning(__tr2qs("Unsupported DCOP parameter type %s"),tmp.ptr());
+ return false;
+ }
+ }
+
+ QByteArray rba;
+ KviQCString szRetType;
+
+ bool bRet = g_pApp->dcopClient()->call(szApp,szObj,szFun,ba,szRetType,rba);
+
+ if(!bRet)
+ {
+ if(!bTestMode)
+ c->warning(__tr2qs("DCOP call failed"));
+ c->returnValue()->setInteger(0);
+ } else {
+ if(bTestMode)
+ c->returnValue()->setInteger(1);
+ else {
+ QDataStream ret(rba, IO_ReadOnly);
+ if(szRetType == "bool")
+ {
+ bool bqw;
+ ret >> bqw;
+ c->returnValue()->setInteger(bqw ? 1 : 0);
+ } else if(szRetType == "QString")
+ {
+ QString szz;
+ ret >> szz;
+ c->returnValue()->setString(szz);
+ } else if(szRetType == "QCString")
+ {
+ KviQCString sss;
+ ret >> sss;
+ c->returnValue()->setString(sss.data());
+ } else if((szRetType == "uint") || (szRetType == "unsigned int") || (szRetType == "Q_UINT32"))
+ {
+ unsigned int ui3;
+ ret >> ui3;
+ c->returnValue()->setInteger(ui3);
+ } else if((szRetType == "int") || (szRetType == "long"))
+ {
+ int iii;
+ ret >> iii;
+ c->returnValue()->setInteger(iii);
+ } else if(szRetType == "QCStringList")
+ {
+#ifndef COMPILE_USE_QT4
+ QCStringList csl;
+ ret >> csl;
+ KviKvsArray * arry = new KviKvsArray();
+ int idx = 0;
+ for(QCStringList::Iterator iter = csl.begin();iter != csl.end();++iter)
+ {
+ arry->set(idx,new KviKvsVariant(QString(*iter)));
+ idx++;
+ }
+ c->returnValue()->setArray(arry);
+#endif
+ } else if(szRetType == "QStringList")
+ {
+ QStringList csl;
+ ret >> csl;
+ KviKvsArray * arry = new KviKvsArray();
+ int idx = 0;
+ for(QStringList::Iterator iter = csl.begin();iter != csl.end();++iter)
+ {
+ arry->set(idx,new KviKvsVariant(*iter));
+ idx++;
+ }
+ c->returnValue()->setArray(arry);
+ } else {
+ c->returnValue()->setString(szRetType.data());
+ }
+ }
+ }
+#else
+ if(!bTestMode)
+ c->warning(__tr2qs("DCOP calls are available only when KDE support is compiled in"));
+ c->returnValue()->setInteger(0);
+#endif
+
+ return true;
+}
+
+
+/*
+ @doc: system.setenv
+ @type:
+ command
+ @title:
+ system.setenv
+ @keyterms:
+ Enviroinement variables
+ @short:
+ Sets an enviroinement variable
+ @syntax:
+ system.setenv <variable:string> [<value:string>]
+ @description:
+ Sets the enviroinement <variable> to the <value> string.[br]
+ If <value> is not given , the <variable> is unset.[br]
+ @seealso:
+ [fnc]$system.getenv[/fnc]
+*/
+
+
+static bool system_kvs_cmd_setenv(KviKvsModuleCommandCall * c)
+{
+ QString szVariable,szValue;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("variable",KVS_PT_NONEMPTYSTRING,0,szVariable)
+ KVSM_PARAMETER("value",KVS_PT_STRING,KVS_PF_OPTIONAL,szValue)
+ KVSM_PARAMETERS_END(c)
+
+ KviQCString szVar = szVariable.local8Bit();
+ KviQCString szVal = szValue.local8Bit();
+
+ if(szVal.isEmpty())kvi_unsetenv(szVar.data());
+ else
+ {
+/*#ifdef COMPILE_ON_WINDOWS
+ QString Var,Val,VarAndVal;
+ Val = szVar.data();
+ Var = szVal.data();
+ VarAndVal = Var+"="+Val;
+ putenv(VarAndVal);
+#else*/ // <-- this stuff is implicit in kvi_setenv: that's why we have the kvi_ version.
+ kvi_setenv(szVar.data(),szVal.data());
+/*#endif*/
+ }
+ return true;
+}
+
+/*
+ @doc: system.call
+ @keyterms:
+ call plugin
+ @type:
+ function
+ @title:
+ $system.call
+ @short:
+ Allows to call functions of a plugin
+ @syntax:
+ <string> $system.call(<plugin:string>, <function:string>[,<parameters:string>,...])
+ @description:
+ This function allows you to call simple functions of "easyplugins" (dll/so) and
+ get the result of this function. The easyplugins have to be coded in a special way.
+ If you want to write your own easyplugins, have a look on the easyplugins documentation.
+ [br]
+ [br]
+ The function needs a minimum of 2 parameters. The others are optional and not limited.[br]
+ The first one is the complete name like "example.dll" or "example.so"
+ If you have a relative path or only the filename KVIrc looks for the easyplugins in the following dirs:[br]
+ In a subdir called "easyplugins" in the local and global KVIrc directory.
+ If you give an absolute path KVIrc will load it directly.
+ [br]
+ [br]
+ You are free to add more parameters, they will be given to the easyplugin.[br]
+ The easyplugin decides how much parameters you need in addition to the first 2.
+ [br]
+ [br]
+ [b]Warning: Only use easyplugins of known and trustable sources![/b]
+ @examples:
+ [example]
+ echo $system.call("my.dll","myfunction")
+ echo $system.call("my.dll","myfunction","parameter1","parameter2")
+ echo $system.call("c:/my.dll","myfunction")
+ echo $system.call("my.so","myfunction","parameter1")
+ [/example]
+*/
+
+
+static bool system_kvs_fnc_plugin_call(KviKvsModuleFunctionCall *c)
+{
+ return g_pPluginManager->pluginCall(c);
+}
+
+static bool system_module_init(KviModule * m)
+{
+ KVSM_REGISTER_FUNCTION(m,"ostype",system_kvs_fnc_ostype);
+ KVSM_REGISTER_FUNCTION(m,"osname",system_kvs_fnc_osname);
+ KVSM_REGISTER_FUNCTION(m,"osversion",system_kvs_fnc_osversion);
+ KVSM_REGISTER_FUNCTION(m,"osrelease",system_kvs_fnc_osrelease);
+ KVSM_REGISTER_FUNCTION(m,"osmachine",system_kvs_fnc_osmachine);
+ KVSM_REGISTER_FUNCTION(m,"osnodename",system_kvs_fnc_osnodename);
+ KVSM_REGISTER_FUNCTION(m,"getenv",system_kvs_fnc_getenv);
+ KVSM_REGISTER_FUNCTION(m,"hostname",system_kvs_fnc_hostname);
+ KVSM_REGISTER_FUNCTION(m,"dcop",system_kvs_fnc_dcop);
+ KVSM_REGISTER_FUNCTION(m,"clipboard",system_kvs_fnc_clipboard);
+ KVSM_REGISTER_FUNCTION(m,"selection",system_kvs_fnc_selection);
+ KVSM_REGISTER_FUNCTION(m,"checkModule",system_kvs_fnc_checkModule);
+ KVSM_REGISTER_FUNCTION(m,"call",system_kvs_fnc_plugin_call);
+
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"setenv",system_kvs_cmd_setenv);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"setClipboard",system_kvs_cmd_setClipboard);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"setSelection",system_kvs_cmd_setSelection);
+
+ g_pPluginManager = new(KviPluginManager);
+
+ return true;
+}
+
+static bool system_module_cleanup(KviModule *m)
+{
+ g_pPluginManager->unloadAll();
+ delete g_pPluginManager;
+ return true;
+}
+
+static bool system_module_can_unload(KviModule *m)
+{
+ if(!g_pPluginManager->checkUnload()) return false;
+ return true;
+}
+
+KVIRC_MODULE(
+ "System", // module name
+ "1.0.0", // module version
+ "Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot net)" \
+ " (C) 2005 Tonino Imbesi (grifisx at barmes dot org)"\
+ " (C) 2005 Alessandro Carbone (noldor at barmes dot org)",// author & (C)
+ "System informations module",
+ system_module_init,
+ system_module_can_unload,
+ 0,
+ system_module_cleanup
+)
diff --git a/src/modules/system/plugin.cpp b/src/modules/system/plugin.cpp
new file mode 100644
index 00000000..b14b18c0
--- /dev/null
+++ b/src/modules/system/plugin.cpp
@@ -0,0 +1,427 @@
+//=============================================================================
+//
+// File : plugin.cpp
+// Creation date : Wed Apr 11 04 2007 00:54:00 GMT+1 by TheXception
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "plugin.h"
+
+#include "kvi_module.h"
+#include "kvi_string.h"
+#include "kvi_library.h"
+#include "kvi_thread.h"
+#include "kvi_locale.h"
+#include "kvi_app.h"
+#include "kvi_fileutils.h"
+
+#include <qdir.h>
+#include <qfileinfo.h>
+/*
+ @doc: easyplugins
+ @type:
+ generic
+ @keyterms:
+ easyplugins
+ @title:
+ Easyplugins
+ @short:
+ Small plugins which can be called in scripts
+ @body:
+ If you want to know how to call easyplugins please have a look at: $system.call()[br]
+ This part of the documentation handles only the way how to write an easyplugin. An easyplugin is simply a dll/so. You can create one like you normally make such so/dll files. The important thing is that these so/dll-files export some of the following functions.
+ [br][br]
+ [b]Exported functions by easyplugin (C/C++-Examples):[/b][br]
+ [br][b]_free function[/b] [i] (needed)[/i][br]
+ This function is important! Since KVIrc can not free directly the memory of the dll, the plugins need the _free function so that the memory can be freed by the plugin to prevent memory-leaks.[br]
+ [example]
+ int _free(void * p)[br]
+ {[br]
+ // Always free the memory here![br]
+ free(p);[br]
+ return 0;[br]
+ }[br]
+ [/example]
+
+ [br][b]_load function[/b] [i](optional)[/i][br]
+ After the plugin has be loaded, KVIrc will call the _load-function. Here you can prepare your plugin stuff.
+ [example]
+ int _load()[br]
+ {[br]
+ return 0;[br]
+ }[br]
+ [/example]
+
+ [br][b]_unload function[/b] [i]((optional)[/i][br]
+ This function will be called before the plugins is unloaded. In this function you can clean up memory or other things.
+ After this call there is no guarantee that the plugin will be kept in memory.[br]
+ [example]
+ int _unload()[br]
+ {[br]
+ return 0;[br]
+ }[br]
+ [/example]
+
+ [br][b]_canunload function[/b] [i](optional)[/i][br]
+ The _canunload-function will be called by KVIrc to check if it may unload the plugin.
+ If return value is true KVIrc will unload the plugin, false means he will try unloading it at the next check.[br]
+ Important: KVIrc will ignore this if unload of plugins will be forced! So you have to be sure that the _unload function of your plugins cleans up![br]
+ [example]
+ int _canunload()[br]
+ {[br]
+ return 0; [br]
+ }[br]
+ [/example]
+
+ [br][b]user function[/b][br]
+ This is the general structure of a user function call.[br]
+ The important thing here is the handling of return values. To return a value to KVIrc you have to allocate memory and write the pointer to it into pBuffer. Have a look at the example for more details.[br]
+ [example]
+ int about(int argc, char * argv[], char ** pBuffer)[br]
+ {[br]
+ *pBuffer = (char*)malloc(1024);[br]
+ sprintf((char*)*pBuffer, "Hello World"); [br]
+ return 1;[br]
+ }[br]
+ [/example]
+*/
+
+KviPlugin::KviPlugin(kvi_library_t pLib, const QString& name)
+{
+ m_Plugin = pLib;
+ m_szName = name;
+}
+
+KviPlugin::~KviPlugin()
+{
+}
+
+KviPlugin* KviPlugin::load(const QString& szFileName)
+{
+ kvi_library_t pLibrary = kvi_library_open(szFileName.local8Bit());
+ if (!pLibrary)
+ {
+ return 0;
+ }
+
+ KviPlugin* pPlugin = new KviPlugin(pLibrary,KviFileUtils::extractFileName(szFileName));
+
+ plugin_load function_load;
+
+ function_load = (plugin_unload)kvi_library_symbol(pLibrary,"_load");
+ if (function_load)
+ {
+ //TODO: THREAD
+ function_load();
+ }
+ return pPlugin;
+}
+
+bool KviPlugin::pfree(char * pBuffer)
+{
+ plugin_free function_free;
+
+ function_free = (plugin_free)kvi_library_symbol(m_Plugin,"_free");
+ if (function_free)
+ {
+ //TODO: THREAD
+ if(pBuffer) function_free(pBuffer);
+ return true;
+ }
+ return false;
+}
+
+bool KviPlugin::unload()
+{
+ plugin_unload function_unload;
+
+ function_unload = (plugin_unload)kvi_library_symbol(m_Plugin,"_unload");
+ if (function_unload)
+ {
+ //TODO: THREAD
+ function_unload();
+ }
+
+ if(m_Plugin)
+ {
+ kvi_library_close(m_Plugin);
+ }
+
+ return true;
+}
+
+bool KviPlugin::canunload()
+{
+ plugin_canunload function_canunload;
+
+ function_canunload = (plugin_canunload)kvi_library_symbol(m_Plugin,"_canunload");
+ if (function_canunload)
+ {
+ //TODO: THREAD
+ if(!function_canunload())
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+int KviPlugin::call(const QString& pszFunctionName, int argc, char * argv[], char ** pBuffer)
+{
+ int r;
+ plugin_function function_call;
+ function_call = (plugin_function)kvi_library_symbol(m_Plugin,pszFunctionName.local8Bit());
+ if (!function_call)
+ {
+ return -1;
+ } else {
+ //TODO: THREAD
+ r = function_call(argc,argv,pBuffer);
+ }
+ if (r < 0) r = 0; // negative numbers are for error handling.
+ return r;
+}
+
+QString KviPlugin::name()
+{
+ return m_szName;
+}
+
+void KviPlugin::setName(const QString& Name)
+{
+ m_szName = Name;
+}
+
+
+KviPluginManager::KviPluginManager()
+{
+ m_pPluginDict = new KviPointerHashTable<QString,KviPlugin>(5,false);
+ m_pPluginDict->setAutoDelete(false);
+
+ m_bCanUnload = true;
+}
+
+KviPluginManager::~KviPluginManager()
+{
+ delete m_pPluginDict;
+}
+
+bool KviPluginManager::pluginCall(KviKvsModuleFunctionCall *c)
+{
+ // /echo $system.call("traffic.dll",about)
+ QString szPluginPath; //contains full path and plugin name like "c:/plugin.dll"
+ QString szFunctionName;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("plugin_path",KVS_PT_NONEMPTYSTRING,0,szPluginPath)
+ KVSM_PARAMETER("function",KVS_PT_NONEMPTYSTRING,0,szFunctionName)
+ KVSM_PARAMETERS_END(c)
+
+ //Check if there is such a plugin
+ if(!findPlugin(szPluginPath))
+ {
+ c->error(__tr2qs("Plugin not found. Please check the plugin-name and path."));
+ return true;
+ }
+
+ //Load plugin or check it in cache
+ if(!loadPlugin(szPluginPath))
+ {
+ c->error(__tr2qs("Error while loading plugin."));
+ return true;
+ }
+
+ //Parsing more Parameters
+ int iArgc = 0;
+ char ** ppArgv;
+ char * pArgvBuffer;
+
+ //Preparing argv buffer
+ if(c->parameterCount() > 2)
+ {
+ iArgc = c->parameterCount() - 2;
+ }
+
+ if (iArgc > 0)
+ {
+ int i = 2;
+ QString tmp;
+ int iSize = 0;
+
+ //Calculate buffer size
+ while (i < (iArgc + 2) )
+ {
+ c->params()->at(i)->asString(tmp);
+ iSize += tmp.length()+1; //+1 for the \0 characters
+ i++;
+ }
+
+ //Allocate buffer
+ ppArgv = (char**)malloc(iArgc*sizeof(char*));
+ pArgvBuffer = (char*)malloc(iSize);
+
+ i = 2;
+ char * x = 0;
+ x = pArgvBuffer;
+ while (i < (iArgc + 2) )
+ {
+ ppArgv[i-2] = x;
+ c->params()->at(i)->asString(tmp);
+ strcpy(x,tmp.local8Bit());
+ x += tmp.length();
+
+ *x = 0;
+ x++;
+ i++;
+ }
+
+ } else {
+ //Avoid using unfilled variables
+ ppArgv = 0;
+ pArgvBuffer = 0;
+ iArgc = 0;
+ }
+
+ //Preparing return buffer
+ char * returnBuffer;
+ KviPlugin * plugin;
+
+ plugin = getPlugin(szPluginPath);
+ int r = plugin->call(szFunctionName,iArgc,ppArgv,&returnBuffer);
+
+ if(r == -1)
+ {
+ c->error(__tr2qs("This plugin does not export the desired function."));
+ return true;
+ }
+ if (r > 0)
+ {
+ c->returnValue()->setString(QString::fromLocal8Bit(returnBuffer));
+ }
+
+
+ //Clean up
+ if(pArgvBuffer) free(pArgvBuffer);
+ if(ppArgv) free(ppArgv);
+ if(returnBuffer)
+ {
+ if (!plugin->pfree(returnBuffer))
+ {
+ c->warning(__tr2qs("The plugin has no function to free memory. This can result in Memory Leaks!"));
+ }
+ }
+
+
+
+ return true;
+}
+
+bool KviPluginManager::checkUnload()
+{
+ /*
+ Always called when system module should be unloaded
+ Checking here if all small "modules" can be unloaded
+ */
+ KviPointerHashTableIterator<QString,KviPlugin> it(*m_pPluginDict);
+
+ m_bCanUnload = true;
+
+ while(it.current())
+ {
+ if(it.current()->canunload())
+ {
+ it.current()->unload();
+ m_pPluginDict->remove(it.currentKey());
+ } else {
+ m_pPluginDict++;
+ m_bCanUnload = false;
+ }
+ }
+
+ return m_bCanUnload;
+}
+
+void KviPluginManager::unloadAll()
+{
+ KviPointerHashTableIterator<QString,KviPlugin> it(*m_pPluginDict);
+
+ while(it.current())
+ {
+ it.current()->unload();
+ m_pPluginDict->remove(it.currentKey());
+ }
+}
+
+bool KviPluginManager::findPlugin(QString& szPath)
+{
+ QString szFileName(KviFileUtils::extractFileName(szPath));
+// szFileName.detach();
+ if(KviFileUtils::isAbsolutePath(szPath) && KviFileUtils::fileExists(szPath))
+ {
+ // Ok,
+ return true;
+ } else {
+ //Plugin not found in direct way. Looking in kvirc local dir
+ g_pApp->getGlobalKvircDirectory(szPath,KviApp::EasyPlugins,szFileName);
+
+ if(!KviFileUtils::fileExists(szPath))
+ {
+ //Plugin not found in kvirc local dir. Looking in kvirc global dir
+ g_pApp->getLocalKvircDirectory(szPath,KviApp::EasyPlugins,szFileName);
+
+ if(!KviFileUtils::fileExists(szPath))
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+bool KviPluginManager::isPluginLoaded(const QString& pSingleName)
+{
+ KviPlugin * p = m_pPluginDict->find(pSingleName);
+ if (!p)
+ return false;
+ else
+ return true;
+}
+
+bool KviPluginManager::loadPlugin(const QString& szPluginPath)
+{
+ if(isPluginLoaded(szPluginPath))
+ {
+ return getPlugin(szPluginPath)!=0;
+ } else {
+ KviPlugin * plugin = KviPlugin::load(szPluginPath);
+ if(plugin)
+ {
+ m_pPluginDict->insert(szPluginPath,plugin);
+ return true;
+ }
+ }
+ return false;
+}
+
+KviPlugin * KviPluginManager::getPlugin(const QString& szPluginPath)
+{
+ KviPlugin * p = m_pPluginDict->find(szPluginPath);
+ return p;
+} \ No newline at end of file
diff --git a/src/modules/system/plugin.h b/src/modules/system/plugin.h
new file mode 100644
index 00000000..64b1723a
--- /dev/null
+++ b/src/modules/system/plugin.h
@@ -0,0 +1,80 @@
+#ifndef _PLUGIN_H_
+#define _PLUGIN_H_
+//=============================================================================
+//
+// File : plugin.h
+// Creation date : Wed Apr 11 04 2007 00:54:00 GMT+1 by TheXception
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_module.h"
+#include "kvi_pointerhashtable.h"
+
+typedef int (*plugin_function)(int argc, char* argv[], char ** buffer);
+typedef int (*plugin_unload)();
+typedef int (*plugin_canunload)();
+typedef int (*plugin_load)();
+typedef int (*plugin_free)(char * pBuffer);
+
+class KviPlugin
+{
+protected:
+ // You have to create plugin instance by calling KviPlugin::load()
+ KviPlugin(kvi_library_t pLib, const QString& name);
+public:
+ ~KviPlugin();
+private:
+ // shared
+ // internal
+ kvi_library_t m_Plugin;
+ QString m_szName;
+public:
+ static KviPlugin* load(const QString& szFileName);
+ bool pfree(char * pBuffer);
+ bool unload();
+ bool canunload();
+ int call(const QString& szFunctionName, int argc, char * argv[], char ** pBuffer);
+ QString name();
+ void setName(const QString& szName);
+protected:
+};
+
+class KviPluginManager
+{
+ public:
+ KviPluginManager();
+ ~KviPluginManager();
+ private:
+ // shared
+ bool m_bCanUnload;
+ // internal
+ KviPointerHashTable<QString,KviPlugin> * m_pPluginDict;
+ public:
+ bool pluginCall(KviKvsModuleFunctionCall *c);
+ bool checkUnload();
+ void unloadAll();
+ protected:
+ bool findPlugin(QString& szName);
+ bool isPluginLoaded(const QString& szFileNameOrPathToLoad);
+ bool loadPlugin(const QString& szPluginPath);
+ KviPlugin * getPlugin(const QString& szPluginPath);
+};
+
+#endif //_PLUGIN_H_ \ No newline at end of file
diff --git a/src/modules/term/Makefile.am b/src/modules/term/Makefile.am
new file mode 100644
index 00000000..1567e615
--- /dev/null
+++ b/src/modules/term/Makefile.am
@@ -0,0 +1,21 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkviterm.la
+
+libkviterm_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkviterm_la_SOURCES = libkviterm.cpp termwidget.cpp termwindow.cpp
+libkviterm_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+noinst_HEADERS= termwidget.h termwindow.h
+
+%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
+
+termwidget.cpp: termwidget.moc
+termwindow.cpp: termwindow.moc
diff --git a/src/modules/term/libkviterm.cpp b/src/modules/term/libkviterm.cpp
new file mode 100644
index 00000000..742aaa62
--- /dev/null
+++ b/src/modules/term/libkviterm.cpp
@@ -0,0 +1,167 @@
+//
+// File : libkviterm.cpp
+// Creation date : Wed Aug 30 2000 15:29:02 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+
+#include "kvi_module.h"
+
+#include "kvi_window.h"
+
+#include "kvi_frame.h"
+
+#include <qsplitter.h>
+#include "kvi_pointerlist.h"
+
+#ifdef COMPILE_KDE_SUPPORT
+
+ #include "termwidget.h"
+ #include "termwindow.h"
+
+ #include "ktrader.h"
+
+// #include "kparts/part.h"
+// #include "kparts/factory.h"
+// #include "klibloader.h"
+
+#endif
+
+KviModule * g_pTermModule = 0;
+
+#ifdef COMPILE_KDE_SUPPORT
+ KviPointerList<KviTermWidget> * g_pTermWidgetList = 0;
+ KviPointerList<KviTermWindow> * g_pTermWindowList = 0;
+ KviStr g_szKonsoleLibraryName = "";
+#endif
+
+/*
+ @doc: term.open
+ @type:
+ command
+ @title:
+ term.open
+ @short:
+ Shows a terminal emulator
+ @syntax:
+ term.open [-m]
+ @switches:
+ !sw: -m | --mdi
+ creates terminal as a MDI window
+ @description:
+ Opens a new terminal window (If the service is available).
+ if the -m switch is present, the created terminal as a MDI window,
+ otherwise it is a static window.[br]
+ This command is exported by the "term" module.[br]
+ Note: At the time that this module was written, the
+ KDE terminal emulator module was quite unstable; no extensive
+ testings have been made on this.
+*/
+
+static bool term_kvs_cmd_open(KviKvsModuleCommandCall * c)
+{
+#ifdef COMPILE_KDE_SUPPORT
+ if(g_szKonsoleLibraryName.hasData())
+ {
+ c->module()->lock(); // multiple locks are allowed
+ if(c->hasSwitch('m',"mdi"))
+ {
+ KviTermWindow *w = new KviTermWindow(c->window()->frame(),"Terminal emulator");
+ c->window()->frame()->addWindow(w);
+ } else {
+ KviTermWidget *w = new KviTermWidget(c->window()->frame()->splitter(),
+ c->window()->frame(),true);
+ w->show();
+ }
+ } else {
+ c->warning("No terminal emulation service available");
+ }
+#else
+ c->warning("Terminal emulation service not supported (non-KDE compilation)");
+#endif
+ return true;
+}
+
+static bool term_module_init(KviModule * m)
+{
+ g_pTermModule = m;
+
+#ifdef COMPILE_KDE_SUPPORT
+ g_pTermWidgetList = new KviPointerList<KviTermWidget>;
+ g_pTermWidgetList->setAutoDelete(false);
+ g_pTermWindowList = new KviPointerList<KviTermWindow>;
+ g_pTermWindowList->setAutoDelete(false);
+
+// KTrader::OfferList offers = KTrader::self()->query("Browser/View","KonsolePart");
+// KTrader::OfferList offers = KTrader::self()->query("Browser/View","");
+// if(offers.count() > 0)
+// {
+// KTrader::OfferList::Iterator it = offers.begin();
+// while(it != offers.end())
+// {
+// KviStr tmp = (*it)->name();
+// KviStr tmp2 = (*it)->type();
+// KviStr tmp3 = (*it)->library();
+// debug("Got Service name:%s type:%s library:%s",tmp.ptr(),tmp2.ptr(),tmp3.ptr());
+// ++it;
+// }
+// }
+// KService::Ptr service = *offers.begin();
+ KService::Ptr pKonsoleService = KService::serviceByName("Terminal Emulator");
+ if(!pKonsoleService)pKonsoleService = KService::serviceByName("KonsolePart");
+ if(!pKonsoleService)pKonsoleService = KService::serviceByName("Terminal *");
+ if(pKonsoleService)
+ {
+ g_szKonsoleLibraryName = pKonsoleService->library();
+// debug("KONSOLE LIB %s",g_szKonsoleLibraryName.ptr());
+ }
+// delete pKonsoleService;
+#endif
+
+// m->registerCommand("open",term_module_cmd_open);
+#ifdef COMPILE_NEW_KVS
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"open",term_kvs_cmd_open);
+#endif
+ return true;
+}
+
+static bool term_module_cleanup(KviModule *m)
+{
+#ifdef COMPILE_KDE_SUPPORT
+ while(g_pTermWidgetList->first())delete g_pTermWidgetList->first();
+ delete g_pTermWidgetList;
+ g_pTermWidgetList = 0;
+ while(g_pTermWindowList->first())g_pTermWindowList->first()->close();
+ delete g_pTermWindowList;
+ g_pTermWindowList = 0;
+#endif
+ return true;
+}
+
+KVIRC_MODULE(
+ "Term", // module name
+ "1.0.0", // module version
+ "Copyright (C) 2000 Szymon Stefanek (pragma at kvirc dot net)", // author & (C)
+ "Terminal emulator extension based on the KonsolePart KDE class",
+ term_module_init,
+ 0,
+ 0,
+ term_module_cleanup
+)
diff --git a/src/modules/term/termwidget.cpp b/src/modules/term/termwidget.cpp
new file mode 100644
index 00000000..45bf63a0
--- /dev/null
+++ b/src/modules/term/termwidget.cpp
@@ -0,0 +1,179 @@
+//
+// File : termwidget.cpp
+// Creation date : Thu Aug 10 2000 17:42:12 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2000-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "termwidget.h"
+#include "termwindow.h"
+
+#include "kvi_module.h"
+#include "kvi_frame.h"
+#include "kvi_iconmanager.h"
+#include "kvi_locale.h"
+
+#include <qlabel.h>
+#include "kvi_pointerlist.h"
+#include <qtooltip.h>
+#include <qtimer.h>
+
+#ifdef COMPILE_KDE_SUPPORT
+
+#include "klibloader.h"
+#include "kparts/part.h"
+#include "kparts/factory.h"
+
+extern KviModule * g_pTermModule;
+extern KviPointerList<KviTermWidget> * g_pTermWidgetList;
+extern KviPointerList<KviTermWindow> * g_pTermWindowList;
+extern KviStr g_szKonsoleLibraryName;
+
+KviTermWidget::KviTermWidget(QWidget * par,KviFrame * lpFrm,bool bIsStandalone)
+: QFrame(par,"term_widget")
+{
+ if(bIsStandalone)g_pTermWidgetList->append(this);
+ m_bIsStandalone = bIsStandalone;
+
+ m_pKonsolePart = 0;
+ m_pKonsoleWidget = 0;
+
+ if(bIsStandalone)
+ {
+ m_pHBox = new KviTalHBox(this);
+ m_pTitleLabel = new QLabel(__tr2qs("Terminal emulator"),m_pHBox);
+ m_pTitleLabel->setFrameStyle(QFrame::Raised | QFrame::WinPanel);
+ m_pCloseButton = new QPushButton("",m_pHBox);
+ m_pCloseButton->setPixmap(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_CLOSE)));
+ QToolTip::add(m_pCloseButton,__tr2qs("Close this window"));
+ m_pHBox->setStretchFactor(m_pTitleLabel,2);
+ connect(m_pCloseButton,SIGNAL(clicked()),this,SLOT(closeClicked()));
+ } else {
+ m_pHBox = 0;
+ m_pTitleLabel = 0;
+ m_pCloseButton = 0;
+ }
+
+ setFrameStyle(QFrame::Sunken | QFrame::Panel);
+
+ KParts::Factory * pKonsoleFactory = static_cast<KParts::Factory *>(
+ KLibLoader::self()->factory(g_szKonsoleLibraryName.ptr()));
+
+ if(pKonsoleFactory)
+ {
+// debug("FACTORY %d",pKonsoleFactory);
+ m_pKonsolePart = static_cast<KParts::Part *>(pKonsoleFactory->createPart(
+ this,"terminal emulator",this,"the konsole part"));
+
+ if(m_pKonsolePart)
+ {
+// debug("PART %d",m_pKonsolePart);
+ m_pKonsoleWidget = m_pKonsolePart->widget();
+ connect(m_pKonsoleWidget,SIGNAL(destroyed()),this,SLOT(konsoleDestroyed()));
+// debug("Widget %d",m_pKonsoleWidget);
+ } else {
+ m_pKonsoleWidget = new QLabel(this,
+ __tr2qs("Can't create the terminal emulation part"));
+ }
+
+ } else {
+ m_pKonsoleWidget = new QLabel(this,
+ __tr2qs("Can't retrieve the terminal emulation factory"));
+ }
+}
+
+KviTermWidget::~KviTermWidget()
+{
+ if(m_pKonsoleWidget)
+ disconnect(m_pKonsoleWidget,SIGNAL(destroyed()),this,SLOT(konsoleDestroyed()));
+
+ if(m_bIsStandalone)g_pTermWidgetList->removeRef(this);
+ if(g_pTermWindowList->isEmpty() && g_pTermWidgetList->isEmpty())g_pTermModule->unlock();
+
+// debug("DELETING KONSOLE WIDGET");
+// if(m_pKonsoleWidget)delete m_pKonsoleWidget; <--// Qt will delete it
+// debug("DELETING KONSOLE PART");
+// if(m_pKonsolePart)delete m_pKonsolePart; <--// the part will delete self when the widget will die
+// debug("KONSOLE PART DELETED");
+}
+
+void KviTermWidget::resizeEvent(QResizeEvent *e)
+{
+ int hght = 0;
+ if(m_bIsStandalone)
+ {
+ hght = m_pCloseButton->sizeHint().height();
+ m_pHBox->setGeometry(1,1,width() - 2,hght + 1);
+
+ }
+ if(m_pKonsoleWidget)m_pKonsoleWidget->setGeometry(1,hght + 1,width() - 2,height() - (hght + 2));
+}
+
+void KviTermWidget::closeClicked()
+{
+ // this is called only in standalone mode
+ delete this;
+}
+
+void KviTermWidget::konsoleDestroyed()
+{
+ m_pKonsoleWidget = 0;
+ m_pKonsolePart = 0;
+ hide();
+ QTimer::singleShot(0,this,SLOT(autoClose()));
+}
+
+void KviTermWidget::autoClose()
+{
+ if(m_bIsStandalone)delete this;
+ else ((KviWindow *)parent())->close();
+}
+
+void KviTermWidget::changeTitle(int i,const QString& str)
+{
+ if(m_bIsStandalone)m_pTitleLabel->setText(str);
+}
+
+void KviTermWidget::notifySize(int,int)
+{
+}
+
+void KviTermWidget::changeColumns(int)
+{
+}
+
+QSize KviTermWidget::sizeHint() const
+{
+ int hght = 0;
+ int wdth = 0;
+ if(m_pKonsoleWidget)
+ {
+ hght += m_pKonsoleWidget->sizeHint().height();
+ wdth = m_pKonsoleWidget->sizeHint().width();
+ }
+ if(m_pCloseButton)
+ {
+ hght += m_pCloseButton->sizeHint().height();
+ }
+
+ return QSize(wdth + 2,hght + 2);
+}
+
+#include "termwidget.moc"
+
+#endif //COMPILE_KDE_SUPPORT
diff --git a/src/modules/term/termwidget.h b/src/modules/term/termwidget.h
new file mode 100644
index 00000000..88e9d9a7
--- /dev/null
+++ b/src/modules/term/termwidget.h
@@ -0,0 +1,72 @@
+#ifndef _HELPWIDGET_H_
+#define _HELPWIDGET_H_
+//
+// File : termwidget.h
+// Creation date : Wed Aug 30 2000 15:34:20 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_KDE_SUPPORT
+
+#include <qframe.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include "kvi_tal_hbox.h"
+
+#include "kparts/part.h"
+
+
+class KviFrame;
+
+class KviTermWidget : public QFrame
+{
+ Q_OBJECT
+ Q_PROPERTY( int KviProperty_ChildFocusOwner READ dummy )
+public:
+ KviTermWidget(QWidget * par,KviFrame * lpFrm,bool bIsStandalone = false);
+ ~KviTermWidget();
+private:
+ KviTalHBox * m_pHBox;
+ QLabel * m_pTitleLabel;
+ QPushButton * m_pCloseButton;
+ KParts::Part * m_pKonsolePart;
+ bool m_bIsStandalone;
+ QWidget * m_pKonsoleWidget;
+protected:
+ virtual void resizeEvent(QResizeEvent *e);
+protected slots:
+ void closeClicked();
+ void changeTitle(int i,const QString& str);
+ void notifySize(int,int);
+ void changeColumns(int);
+public:
+ QWidget * konsoleWidget(){ return m_pKonsoleWidget ? m_pKonsoleWidget : this; };
+ virtual QSize sizeHint() const;
+ int dummy() const { return 0; };
+protected slots:
+ void konsoleDestroyed();
+ void autoClose();
+};
+
+#endif
+
+
+#endif //_HELPWIDGET_H_
diff --git a/src/modules/term/termwindow.cpp b/src/modules/term/termwindow.cpp
new file mode 100644
index 00000000..39b6cc1a
--- /dev/null
+++ b/src/modules/term/termwindow.cpp
@@ -0,0 +1,84 @@
+//
+// File : termwindow.cpp
+// Creation date : Thu Aug 31 2000 15:02:22 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+#include "termwindow.h"
+#include "termwidget.h"
+
+#ifdef COMPILE_KDE_SUPPORT
+
+
+#include "kvi_iconmanager.h"
+#include "kvi_options.h"
+#include "kvi_locale.h"
+#include "kvi_module.h"
+
+extern KviModule * g_pTermModule;
+extern KviPointerList<KviTermWindow> * g_pTermWindowList;
+extern KviPointerList<KviTermWidget> * g_pTermWidgetList;
+
+KviTermWindow::KviTermWindow(KviFrame * lpFrm,const char * name)
+: KviWindow(KVI_WINDOW_TYPE_TERM,lpFrm,name)
+{
+ g_pTermWindowList->append(this);
+ m_pTermWidget = 0;
+ m_pTermWidget = new KviTermWidget(this,lpFrm);
+ // Ensure proper focusing
+// setFocusHandler(m_pTermWidget->konsoleWidget(),this);
+}
+
+KviTermWindow::~KviTermWindow()
+{
+ g_pTermWindowList->removeRef(this);
+ if(g_pTermWindowList->isEmpty() && g_pTermWidgetList->isEmpty())g_pTermModule->unlock();
+}
+
+QPixmap * KviTermWindow::myIconPtr()
+{
+ return g_pIconManager->getSmallIcon(KVI_SMALLICON_RAW);
+}
+
+void KviTermWindow::resizeEvent(QResizeEvent *e)
+{
+ if(m_pTermWidget)m_pTermWidget->setGeometry(0,0,width(),height());
+}
+
+QSize KviTermWindow::sizeHint() const
+{
+ return m_pTermWidget ? m_pTermWidget->sizeHint() : KviWindow::sizeHint();
+}
+
+void KviTermWindow::fillCaptionBuffers()
+{
+ m_szPlainTextCaption.sprintf(__tr("Terminal"));
+
+ m_szHtmlActiveCaption.sprintf(
+ __tr("<nobr><font color=\"%s\"><b>Terminal</b></font></nobr>"),
+ KVI_OPTION_COLOR(KviOption_colorCaptionTextActive).name().ascii(),
+ KVI_OPTION_COLOR(KviOption_colorCaptionTextActive2).name().ascii());
+ m_szHtmlInactiveCaption.sprintf(
+ __tr("<nobr><font color=\"%s\"><b>Terminal</b></font></nobr>"),
+ KVI_OPTION_COLOR(KviOption_colorCaptionTextInactive).name().ascii(),
+ KVI_OPTION_COLOR(KviOption_colorCaptionTextInactive2).name().ascii());
+}
+
+#include "termwindow.moc"
+
+#endif
diff --git a/src/modules/term/termwindow.h b/src/modules/term/termwindow.h
new file mode 100644
index 00000000..e3a9d556
--- /dev/null
+++ b/src/modules/term/termwindow.h
@@ -0,0 +1,54 @@
+#ifndef _TERMWINDOW_H_
+#define _TERMWINDOW_H_
+//
+// File : termwindow.h
+// Creation date : Thu Aug 31 2000 15:00:00 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "kvi_settings.h"
+
+#ifdef COMPILE_KDE_SUPPORT
+
+
+#include "kvi_window.h"
+#include "kvi_string.h"
+
+class KviTermWidget;
+
+class KviTermWindow : public KviWindow
+{
+ Q_OBJECT
+public:
+ KviTermWindow(KviFrame * lpFrm,const char * name);
+ ~KviTermWindow();
+protected:
+ KviTermWidget * m_pTermWidget;
+protected:
+ virtual QPixmap * myIconPtr();
+ virtual void fillCaptionBuffers();
+ virtual void resizeEvent(QResizeEvent *e);
+public:
+ virtual QSize sizeHint() const;
+};
+
+
+#endif
+
+#endif //_KVI_HELPWINDOW_H_
diff --git a/src/modules/texticons/Makefile.am b/src/modules/texticons/Makefile.am
new file mode 100644
index 00000000..77646abd
--- /dev/null
+++ b/src/modules/texticons/Makefile.am
@@ -0,0 +1,18 @@
+###############################################################################
+# KVirc IRC client Makemath - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkvitexticons.la
+
+libkvitexticons_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkvitexticons_la_SOURCES = libkvitexticons.cpp
+libkvitexticons_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+# noinst_HEADERS=
+
+%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
diff --git a/src/modules/texticons/libkvitexticons.cpp b/src/modules/texticons/libkvitexticons.cpp
new file mode 100644
index 00000000..2179bf41
--- /dev/null
+++ b/src/modules/texticons/libkvitexticons.cpp
@@ -0,0 +1,161 @@
+//=============================================================================
+//
+// File : libkvitexticons.cpp
+// Creation date : Wed May 10 14:00:12 2006 GMT by Alexey Uzhva
+//
+// This math is part of the KVirc irc client distribution
+// Copyright (C) 2006 Alexey Uzhva (wizard at opendoor dot ru)
+//
+// 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_module.h"
+#include "kvi_texticonmanager.h"
+
+/*
+ @doc: texticons.get
+ @type:
+ function
+ @title:
+ $texticons.get
+ @short:
+ Retreives texticon data
+ @syntax:
+ <hash> $texticons.get()
+ <string> $texticons.get(<iconName:string>)
+ <integer> $texticons.get(<iconName:string>)
+ @description:
+ if <iconName:string> is setted returns integer icon id or string filename, associciated with <iconName:string>[br]
+ if <iconName:string> isn't set returns hash where keys are the icon names, and values are the icon id's or filenames
+ @seealso:
+ [fnc]$texticons.get[/fnc]
+*/
+
+static bool texticons_kvs_fnc_get(KviKvsModuleFunctionCall * c)
+{
+ QString szIcon;
+ KviTextIcon* pIcon=0;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("iconName",KVS_PT_NONEMPTYSTRING,KVS_PF_OPTIONAL,szIcon)
+ KVSM_PARAMETERS_END(c)
+ if(!szIcon.isNull())
+ {
+ pIcon=g_pTextIconManager->lookupTextIcon(szIcon);
+ if(!pIcon)
+ {
+ c->warning("Icon '%s' not found",szIcon.utf8().data());
+ } else {
+ if(pIcon->id()!=-1)
+ c->returnValue()->setInteger(pIcon->id());
+ else
+ c->returnValue()->setString(pIcon->filename());
+ }
+ } else {
+ KviKvsHash* hash = new KviKvsHash();
+
+ KviPointerHashTableIterator<QString,KviTextIcon> it(*(g_pTextIconManager->textIconDict()));
+
+ while(KviTextIcon * i = it.current())
+ {
+ if(i->id()!=-1)
+ hash->set(it.currentKey(),new KviKvsVariant( (kvs_int_t)(i->id()) ));
+ else
+ hash->set(it.currentKey(),new KviKvsVariant(i->filename()));
+ ++it;
+ }
+ c->returnValue()->setHash(hash);
+ }
+ return true;
+}
+
+/*
+ @doc: texticons.set
+ @type:
+ command
+ @title:
+ $texticons.set
+ @short:
+ Sets texticon data
+ @syntax:
+ texticons.set <iconName:string>
+ texticons.set <iconName:string> <iconFile:string>
+ texticons.set <iconName:string> <iconId:integer>
+ @description:
+ if command gets only 1 argument it removes <iconName:string> from list of texticons[br]
+ if it gets an integer second parameters, command associates <iconName:string> icon with builin icon, having id <iconId:integer>[br]
+ if it gets a string second parameters, command associates <iconName:string> icon with the filename <iconFile:string>
+ @seealso:
+ [fnc]$texticons.get[/fnc]
+*/
+
+static bool texticons_kvs_cmd_set(KviKvsModuleCommandCall * c)
+{
+ QString szName,szIcon;
+ KviTextIcon* pIcon=0;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("iconName",KVS_PT_NONEMPTYSTRING,0,szName)
+ KVSM_PARAMETER("iconIdOrFile",KVS_PT_STRING,KVS_PF_OPTIONAL,szIcon)
+ KVSM_PARAMETERS_END(c)
+ if(szIcon.isNull())
+ {
+ g_pTextIconManager->textIconDict()->remove(szName);
+ } else {
+ pIcon=g_pTextIconManager->lookupTextIcon(szName);
+ if(!pIcon)
+ {
+ KviTextIcon* pTmpIcon=new KviTextIcon(-1);
+ g_pTextIconManager->insert(szName,*pTmpIcon);
+ delete pTmpIcon;
+ pIcon=g_pTextIconManager->lookupTextIcon(szName);
+ if(!pIcon) return false;
+ }
+
+ bool bOk;
+ unsigned int iResult=szIcon.toUInt(&bOk);
+ if(bOk)
+ pIcon->setId(iResult);
+ else
+ pIcon->setFilename(szIcon);
+
+ }
+ g_pTextIconManager->checkDefaultAssociations();
+ return true;
+}
+
+static bool texticons_module_init(KviModule * m)
+{
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"set",texticons_kvs_cmd_set);
+
+ KVSM_REGISTER_FUNCTION(m,"get",texticons_kvs_fnc_get);
+ return true;
+}
+
+
+static bool texticons_module_cleanup(KviModule *m)
+{
+ return true;
+}
+
+KVIRC_MODULE(
+ "Texticons", // module name
+ "1.0.0", // module version
+ "Copyright (C) 2006 Alexey Uzhva (wizard at opendoor dot ru)",
+ "Texticons handling functions module",
+ texticons_module_init,
+ 0,
+ 0,
+ texticons_module_cleanup
+)
diff --git a/src/modules/theme/Makefile.am b/src/modules/theme/Makefile.am
new file mode 100644
index 00000000..5417e9e5
--- /dev/null
+++ b/src/modules/theme/Makefile.am
@@ -0,0 +1,36 @@
+###############################################################################
+# KVirc IRC client Makefile - 30.12.2006 Szymon Stefanek <pragma at kvirc dot net>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkvitheme.la
+
+libkvitheme_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkvitheme_la_SOURCES = libkvitheme.cpp \
+ managementdialog.cpp \
+ packthemedialog.cpp \
+ savethemedialog.cpp \
+ themefunctions.cpp
+
+nodist_libkvitheme_la_SOURCES = moc_managementdialog.cpp \
+ moc_packthemedialog.cpp \
+ moc_savethemedialog.cpp
+
+libkvitheme_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+noinst_HEADERS= managementdialog.h \
+ packthemedialog.h \
+ savethemedialog.h \
+ themefunctions.h
+
+moc_managementdialog.cpp: managementdialog.h
+ $(SS_QT_MOC) $< -o $@
+
+moc_packthemedialog.cpp: packthemedialog.h
+ $(SS_QT_MOC) $< -o $@
+
+moc_savethemedialog.cpp: savethemedialog.h
+ $(SS_QT_MOC) $< -o $@
diff --git a/src/modules/theme/libkvitheme.cpp b/src/modules/theme/libkvitheme.cpp
new file mode 100644
index 00000000..cba1b4e8
--- /dev/null
+++ b/src/modules/theme/libkvitheme.cpp
@@ -0,0 +1,193 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// File : libkvitheme.cpp
+// Created on Sat 30 Dec 2006 14:54:56 by Szymon Stefanek
+//
+// This toolbar is part of the KVirc irc client distribution
+// Copyright (C) 2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "kvi_module.h"
+#include "kvi_locale.h"
+#include "kvi_qstring.h"
+#include "kvi_parameterlist.h"
+#include "kvi_cmdformatter.h"
+#include "kvi_qstring.h"
+#include "kvi_error.h"
+#include "kvi_out.h"
+#include "kvi_iconmanager.h"
+#include "kvi_mirccntrl.h"
+#include "kvi_config.h"
+#include "kvi_sourcesdate.h"
+#include "kvi_fileutils.h"
+#include "kvi_filedialog.h"
+
+#include "managementdialog.h"
+#include "themefunctions.h"
+
+#include <qfileinfo.h>
+
+QRect g_rectManagementDialogGeometry(0,0,0,0);
+
+
+/*
+ @doc: theme.install
+ @type:
+ command
+ @title:
+ theme.install
+ @short:
+ Shows the theme theme management editor
+ @syntax:
+ theme.install <package_path:string>
+ @description:
+ Attempts to install the themes in the package specified by <package_path>.
+*/
+
+static bool theme_kvs_cmd_install(KviKvsModuleCommandCall * c)
+{
+ QString szThemePackFile;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("package_path",KVS_PT_STRING,0,szThemePackFile)
+ KVSM_PARAMETERS_END(c)
+
+ QString szError;
+ if(!KviThemeFunctions::installThemePackage(szThemePackFile,szError))
+ {
+ c->error(__tr2qs_ctx("Error installing theme package: %Q","theme"),&szError);
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ @doc: theme.screenshot
+ @type:
+ command
+ @title:
+ theme.screenshot
+ @short:
+ Makes a screenshot of the KVIrc window
+ @syntax:
+ theme.screenshot [file_name_path:string]
+ @description:
+ Makes a screenshot of the KVIrc main window
+ and saves it in the specified file. If [file_name_path]
+ is not specified then a save file dialog is shown.
+*/
+
+static bool theme_kvs_cmd_screenshot(KviKvsModuleCommandCall * c)
+{
+ QString szFileName;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("file_name_path",KVS_PT_STRING,KVS_PF_OPTIONAL,szFileName)
+ KVSM_PARAMETERS_END(c)
+
+
+ KviFileUtils::adjustFilePath(szFileName);
+
+ QString szTmp;
+ c->enterBlockingSection();
+
+ bool bResult = KviFileDialog::askForSaveFileName(szTmp,__tr2qs_ctx("Choose a file to save the screenshot to","theme"),szFileName,"*.png");
+
+ if(!c->leaveBlockingSection())return false; // need to stop immediately
+ if(!bResult)return true;
+
+ szFileName = szTmp;
+
+ if(szFileName.isEmpty())return true; // done
+ KviFileUtils::adjustFilePath(szFileName);
+ if(QFileInfo(szFileName).extension(false)!="png")
+ szFileName+=".png";
+
+ QString szError;
+ if(!KviThemeFunctions::makeKVIrcScreenshot(szFileName))
+ {
+ c->error(__tr2qs_ctx("Error making screenshot","theme")); // FIXME: a nicer error ?
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ @doc: theme.dialog
+ @type:
+ command
+ @title:
+ theme.dialog
+ @short:
+ Shows the theme theme management editor
+ @syntax:
+ theme.dialog
+ @description:
+ Shows the theme theme management editor
+*/
+
+static bool theme_kvs_cmd_dialog(KviKvsModuleCommandCall * c)
+{
+ KviThemeManagementDialog::display();
+ return true;
+}
+
+static bool theme_module_init(KviModule *m)
+{
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"dialog",theme_kvs_cmd_dialog);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"install",theme_kvs_cmd_install);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"screenshot",theme_kvs_cmd_screenshot);
+
+ QString szBuf;
+ m->getDefaultConfigFileName(szBuf);
+ KviConfig cfg(szBuf,KviConfig::Read);
+ g_rectManagementDialogGeometry = cfg.readRectEntry("EditorGeometry",QRect(10,10,390,440));
+
+ return true;
+}
+
+static bool theme_module_cleanup(KviModule *m)
+{
+ KviThemeManagementDialog::cleanup();
+
+ QString szBuf;
+ m->getDefaultConfigFileName(szBuf);
+ KviConfig cfg(szBuf,KviConfig::Write);
+ cfg.writeEntry("EditorGeometry",g_rectManagementDialogGeometry);
+
+ return true;
+}
+
+static bool theme_module_can_unload(KviModule * m)
+{
+ return (!KviThemeManagementDialog::instance());
+}
+
+
+KVIRC_MODULE(
+ "theme", // module name
+ "1.0.0", // module version
+ "Copyright (C) 2006 Szymon Stefanek (pragma at kvirc dot net)", // author & (C)
+ "Theme management functions",
+ theme_module_init,
+ theme_module_can_unload,
+ 0,
+ theme_module_cleanup
+)
diff --git a/src/modules/theme/managementdialog.cpp b/src/modules/theme/managementdialog.cpp
new file mode 100644
index 00000000..bfd75283
--- /dev/null
+++ b/src/modules/theme/managementdialog.cpp
@@ -0,0 +1,459 @@
+//=============================================================================
+//
+// File : managementdialog.cpp
+// Created on Sat 30 Dec 2006 14:54:56 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2006 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#define LVI_ICON_SIZE 32
+#define LVI_BORDER 4
+#define LVI_SPACING 8
+#define LVI_MINIMUM_TEXT_WIDTH 300
+#define LVI_MINIMUM_CELL_WIDTH (LVI_MINIMUM_TEXT_WIDTH + LVI_BORDER + LVI_ICON_SIZE + LVI_SPACING + LVI_BORDER)
+
+#include "managementdialog.h"
+#include "packthemedialog.h"
+#include "savethemedialog.h"
+#include "themefunctions.h"
+
+#include "kvi_iconmanager.h"
+#include "kvi_msgbox.h"
+
+
+#include <qlayout.h>
+#include <qpushbutton.h>
+#include "kvi_tal_listbox.h"
+#include <qlineedit.h>
+#include <kvi_tal_textedit.h>
+#include <qregexp.h>
+#include <qmessagebox.h>
+#include <qdir.h>
+#include <qstringlist.h>
+#include <qdatetime.h>
+#include <qfiledialog.h>
+#include "kvi_tal_popupmenu.h"
+#include <qcombobox.h>
+#include <qpainter.h>
+#include <qtooltip.h>
+#include <qimage.h>
+#include <kvi_tal_textedit.h>
+//#include <qmultilineedit.h>
+#ifdef COMPILE_USE_QT4
+#include <QCloseEvent>
+#endif
+#include <qbuffer.h>
+
+#include "kvi_options.h"
+#include "kvi_locale.h"
+#include "kvi_config.h"
+#include "kvi_fileutils.h"
+#include "kvi_app.h"
+#include "kvi_frame.h"
+#include "kvi_iconmanager.h"
+#include "kvi_internalcmd.h"
+#include "kvi_styled_controls.h"
+#include "kvi_doublebuffer.h"
+#include "kvi_packagefile.h"
+#include "kvi_fileextensions.h"
+#include "kvi_filedialog.h"
+#include "kvi_dynamictooltip.h"
+
+#include <stdlib.h> // rand & srand
+
+extern QRect g_rectManagementDialogGeometry;
+
+
+
+KviThemeListBoxItem::KviThemeListBoxItem(KviTalListBox * box,KviThemeInfo * inf)
+: KviTalListBoxText(box)
+{
+ m_pThemeInfo = inf;
+ QString t;
+ t = "<nobr><b>";
+ t += inf->name();
+ t += "</b>";
+
+ if(!inf->version().isEmpty()) {
+ t += "[";
+ t += inf->version();
+ t += "]";
+ }
+
+ if(!inf->author().isEmpty()) {
+ t += " <font color=\"#a0a0a0\"> ";
+ t += __tr2qs_ctx("by","theme");
+ t += " ";
+ t += inf->author();
+ t += "</font>";
+ }
+
+ t += "</nobr>";
+ t += "<br><nobr><font size=\"-1\">";
+ t += inf->description();
+ t += "</font></nobr>";
+ m_pText = new KviTalSimpleRichText(t,box->font());
+ int iWidth = box->visibleWidth();
+ if(iWidth < LVI_MINIMUM_CELL_WIDTH)iWidth = LVI_MINIMUM_CELL_WIDTH;
+ iWidth -= LVI_BORDER + LVI_ICON_SIZE + LVI_SPACING + LVI_BORDER;
+ m_pText->setWidth(iWidth);
+}
+
+KviThemeListBoxItem::~KviThemeListBoxItem()
+{
+ delete m_pThemeInfo;
+ delete m_pText;
+}
+
+void KviThemeListBoxItem::paint(QPainter * p)
+{
+ KviTalListBoxText::paint(p);
+ p->drawPixmap(LVI_BORDER,LVI_BORDER, *(g_pIconManager->getBigIcon(QString(KVI_BIGICON_THEME))) );
+ int afterIcon = LVI_BORDER + LVI_ICON_SIZE + LVI_SPACING;
+ int www = p->window().width() - (afterIcon + LVI_BORDER);
+ m_pText->setWidth(www);
+ m_pText->draw(p,afterIcon,LVI_BORDER,QRect(afterIcon,LVI_BORDER,www,p->window().height() - (LVI_BORDER * 2)),listBox()->viewport()->colorGroup());
+}
+
+int KviThemeListBoxItem::height(const KviTalListBox * lb) const
+{
+ int iHeight = m_pText->height() + (2 * LVI_BORDER);
+ if(iHeight < (LVI_ICON_SIZE + (2 * LVI_BORDER)))iHeight = LVI_ICON_SIZE + (2 * LVI_BORDER);
+ return iHeight;
+}
+
+KviThemeManagementDialog * KviThemeManagementDialog::m_pInstance = 0;
+
+
+KviThemeManagementDialog::KviThemeManagementDialog(QWidget * parent)
+: QDialog(parent,"theme_options_widget")
+{
+ setCaption(__tr2qs_ctx("Manage Themes - KVIrc","theme"));
+ setIcon(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_THEME)));
+
+ setModal(true);
+
+ m_pInstance = this;
+
+ QGridLayout * g = new QGridLayout(this,3,2,4,4);
+
+ KviTalHBox *hb = new KviTalHBox(this);
+ g->addMultiCellWidget(hb,0,0,0,1);
+
+ KviStyledToolButton * tb;
+ QFrame * sep;
+
+ tb = new KviStyledToolButton(hb);
+ tb->setIconSet(*(g_pIconManager->getBigIcon(KVI_BIGICON_SAVE)));
+ tb->setUsesBigPixmap(true);
+ QToolTip::add(tb,__tr2qs_ctx("Save Current Theme...","theme"));
+ connect(tb,SIGNAL(clicked()),this,SLOT(saveCurrentTheme()));
+
+ sep = new QFrame(hb);
+ sep->setFrameStyle(QFrame::VLine | QFrame::Sunken);
+ sep->setMinimumWidth(12);
+
+ m_pPackThemeButton = new KviStyledToolButton(hb);
+ m_pPackThemeButton->setIconSet(*(g_pIconManager->getBigIcon(KVI_BIGICON_PACK)));
+ m_pPackThemeButton->setUsesBigPixmap(true);
+ QToolTip::add(m_pPackThemeButton,__tr2qs_ctx("Export Selected Themes to a Distributable Package","theme"));
+ connect(m_pPackThemeButton,SIGNAL(clicked()),this,SLOT(packTheme()));
+
+ m_pDeleteThemeButton = new KviStyledToolButton(hb);
+ m_pDeleteThemeButton->setIconSet(*(g_pIconManager->getBigIcon(KVI_BIGICON_REMOVE)));
+ m_pDeleteThemeButton->setUsesBigPixmap(true);
+ QToolTip::add(m_pDeleteThemeButton,__tr2qs_ctx("Delete Selected Themes","theme"));
+ connect(m_pDeleteThemeButton,SIGNAL(clicked()),this,SLOT(deleteTheme()));
+
+ sep = new QFrame(hb);
+ sep->setFrameStyle(QFrame::VLine | QFrame::Sunken);
+ sep->setMinimumWidth(12);
+
+ tb = new KviStyledToolButton(hb);
+ tb->setIconSet(*(g_pIconManager->getBigIcon(KVI_BIGICON_OPEN)));
+ tb->setUsesBigPixmap(true);
+ QToolTip::add(tb,__tr2qs_ctx("Install Theme Package From Disk","theme"));
+ connect(tb,SIGNAL(clicked()),this,SLOT(installFromFile()));
+
+ tb = new KviStyledToolButton(hb);
+ tb->setIconSet(*(g_pIconManager->getBigIcon(KVI_BIGICON_WWW)));
+ tb->setUsesBigPixmap(true);
+ QToolTip::add(tb,__tr2qs_ctx("Get More Themes...","theme"));
+ connect(tb,SIGNAL(clicked()),this,SLOT(getMoreThemes()));
+
+ QWidget *w= new QWidget(hb);
+ w->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Minimum);
+
+ m_pListBox = new KviTalListBox(this);
+ m_pListBox->setMinimumHeight(400);
+ m_pListBox->setMinimumWidth(400);
+ m_pListBox->setSelectionMode(KviTalListBox::Extended);
+ connect(m_pListBox,SIGNAL(doubleClicked(KviTalListBoxItem *)),this,SLOT(applyTheme(KviTalListBoxItem *)));
+ connect(m_pListBox,SIGNAL(contextMenuRequested(KviTalListBoxItem *,const QPoint &)),
+ this,SLOT(contextMenuRequested(KviTalListBoxItem *,const QPoint &)));
+ connect(m_pListBox,SIGNAL(selectionChanged()),this,SLOT(enableDisableButtons()));
+ g->addMultiCellWidget(m_pListBox,1,1,0,1);
+
+ KviDynamicToolTip * tip = new KviDynamicToolTip(m_pListBox);
+ connect(tip,SIGNAL(tipRequest(KviDynamicToolTip *,const QPoint &)),this,SLOT(tipRequest(KviDynamicToolTip *,const QPoint &)));
+
+ QPushButton * b = new QPushButton(__tr2qs("Close"),this);
+ connect(b,SIGNAL(clicked()),this,SLOT(closeClicked()));
+ g->addWidget(b,2,1);
+
+ g->setRowStretch(1,0);
+ g->setColStretch(0,1);
+
+ fillThemeBox();
+ m_pContextPopup = new KviTalPopupMenu(this);
+
+ if(g_rectManagementDialogGeometry.y() < 5)
+ {
+ g_rectManagementDialogGeometry.setY(5);
+ }
+ resize(g_rectManagementDialogGeometry.width(),
+ g_rectManagementDialogGeometry.height());
+ move(g_rectManagementDialogGeometry.x(),
+ g_rectManagementDialogGeometry.y());
+}
+
+KviThemeManagementDialog::~KviThemeManagementDialog()
+{
+ g_rectManagementDialogGeometry = QRect(pos().x(),pos().y(),size().width(),size().height());
+ m_pInstance = 0;
+}
+
+void KviThemeManagementDialog::closeClicked()
+{
+ delete this;
+ m_pInstance = 0;
+}
+
+
+void KviThemeManagementDialog::display()
+{
+ if(!m_pInstance)
+ m_pInstance = new KviThemeManagementDialog(g_pFrame);
+ m_pInstance->show();
+}
+
+void KviThemeManagementDialog::cleanup()
+{
+ if(!m_pInstance)return;
+ delete m_pInstance;
+ m_pInstance = 0;
+}
+
+void KviThemeManagementDialog::packTheme()
+{
+ KviPointerList<KviThemeInfo> dl;
+ dl.setAutoDelete(false);
+ for(KviThemeListBoxItem * it = (KviThemeListBoxItem *)m_pListBox->firstItem();it;it = (KviThemeListBoxItem *)it->next())
+ {
+ if(it->isSelected())
+ dl.append(it->themeInfo());
+ }
+ if(dl.isEmpty())return;
+
+ KviPackThemeDialog * pDialog = new KviPackThemeDialog(this,&dl);
+ pDialog->exec();
+ delete pDialog;
+
+}
+
+void KviThemeManagementDialog::contextMenuRequested(KviTalListBoxItem * it,const QPoint & pos)
+{
+ if(it)
+ {
+ m_pListBox->setCurrentItem(it);
+ m_pContextPopup->clear();
+ m_pContextPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_MINUS)),__tr2qs_ctx("&Remove Theme","theme"),this,SLOT(deleteTheme()));
+ m_pContextPopup->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_ACCEPT)),__tr2qs_ctx("&Apply Theme","theme"),this,SLOT(applyCurrentTheme()));
+ m_pContextPopup->popup(pos);
+ }
+}
+
+void KviThemeManagementDialog::applyTheme ( KviTalListBoxItem * it)
+{
+ if(it)m_pListBox->setCurrentItem(it);
+ applyCurrentTheme();
+}
+
+void KviThemeManagementDialog::applyCurrentTheme()
+{
+ KviThemeListBoxItem * it = (KviThemeListBoxItem *)m_pListBox->item(m_pListBox->currentItem());
+ if(!it)return;
+
+ if(KviMessageBox::yesNo(__tr2qs_ctx("Apply theme - KVIrc","theme"),
+ __tr2qs_ctx("Do you wish to apply theme \"%Q\" (version %Q)?","theme"),
+ &(it->themeInfo()->name()),&(it->themeInfo()->version())))
+ {
+ QString szPath = it->themeInfo()->absoluteDirectory();
+ if(szPath.isEmpty())return;
+
+ KviThemeInfo out;
+ if(!KviTheme::load(szPath,out))
+ {
+ QString szErr = out.lastError();
+ QString szMsg;
+ KviQString::sprintf(szMsg,__tr2qs_ctx("Failed to apply the specified theme: %Q","theme"),&szErr);
+ QMessageBox::critical(this,__tr2qs_ctx("Apply theme - KVIrc","theme"),szMsg,
+ QMessageBox::Ok,QMessageBox::NoButton,QMessageBox::NoButton);
+
+ }
+ }
+}
+
+void KviThemeManagementDialog::deleteTheme()
+{
+ for(KviThemeListBoxItem * pItem = (KviThemeListBoxItem *)m_pListBox->firstItem();pItem;pItem = (KviThemeListBoxItem *)pItem->next())
+ {
+ if(pItem->isSelected())
+ {
+ if(!KviMessageBox::yesNo(__tr2qs_ctx("Delete Theme - KVIrc","theme"),
+ __tr2qs_ctx("Do you really wish to delete theme \"%Q\" (version %Q)?","theme"),
+ &(pItem->themeInfo()->name()),&(pItem->themeInfo()->version())))goto jump_out;
+
+ KviFileUtils::deleteDir(pItem->themeInfo()->absoluteDirectory());
+ }
+ }
+jump_out:
+ fillThemeBox();
+}
+
+void KviThemeManagementDialog::installFromFile()
+{
+ int iThemeCount=0;
+ QString szFileName;
+ QString szError;
+
+ if(!KviFileDialog::askForOpenFileName(szFileName,__tr2qs_ctx("Open Theme - KVIrc","theme"),QString::null,"*.kvt"))
+ return;
+
+ if(!KviThemeFunctions::installThemePackage(szFileName,szError,this))
+ {
+ KviMessageBox::information(szError);
+ return;
+ }
+ fillThemeBox();
+}
+
+void KviThemeManagementDialog::getMoreThemes()
+{
+ if(!g_pFrame)return;
+ g_pFrame->executeInternalCommand(KVI_INTERNALCOMMAND_OPENURL_KVIRC_THEMES);
+}
+
+void KviThemeManagementDialog::saveCurrentTheme()
+{
+ KviSaveThemeDialog * pSaveThemeDialog = new KviSaveThemeDialog(this);
+ pSaveThemeDialog->exec();
+ delete pSaveThemeDialog;
+ fillThemeBox();
+}
+
+void KviThemeManagementDialog::fillThemeBox(const QString &szDir)
+{
+ QDir d(szDir);
+
+ QStringList sl = d.entryList(QDir::Dirs);
+
+ for(QStringList::Iterator it = sl.begin();it != sl.end();++it)
+ {
+ if(*it == ".")continue;
+ if(*it == "..")continue;
+
+ QString szTest = szDir;
+ szTest += KVI_PATH_SEPARATOR_CHAR;
+ szTest += *it;
+
+ KviThemeInfo * inf = new KviThemeInfo();
+ if(inf->loadFromDirectory(szTest))
+ {
+ inf->setSubdirectory(*it);
+ KviThemeListBoxItem * item = 0;
+ item = new KviThemeListBoxItem(m_pListBox,inf);
+ } else {
+ delete inf;
+ }
+ }
+}
+
+void KviThemeManagementDialog::fillThemeBox()
+{
+ m_pListBox->clear();
+
+ QString szDir;
+ g_pApp->getGlobalKvircDirectory(szDir,KviApp::Themes);
+ fillThemeBox(szDir);
+ g_pApp->getLocalKvircDirectory(szDir,KviApp::Themes);
+ fillThemeBox(szDir);
+
+ enableDisableButtons();
+}
+
+bool KviThemeManagementDialog::hasSelectedItems()
+{
+ for(KviTalListBoxItem * it = m_pListBox->firstItem();it;it = it->next())
+ {
+ if(it->isSelected())return true;
+ }
+ return false;
+}
+
+
+void KviThemeManagementDialog::enableDisableButtons()
+{
+ bool b = hasSelectedItems();
+ m_pPackThemeButton->setEnabled(b);
+ m_pDeleteThemeButton->setEnabled(b);
+}
+
+void KviThemeManagementDialog::closeEvent(QCloseEvent * e)
+{
+ e->ignore();
+ delete this;
+}
+
+void KviThemeManagementDialog::tipRequest(KviDynamicToolTip *pTip,const QPoint &pnt)
+{
+ KviThemeListBoxItem * it = (KviThemeListBoxItem *)(m_pListBox->itemAt(pnt));
+
+ if(!it)return;
+
+ KviThemeInfo * pThemeInfo = it->themeInfo();
+
+ QString szThemeDescription;
+
+ KviThemeFunctions::getThemeHtmlDescription(
+ szThemeDescription,
+ pThemeInfo->name(),
+ pThemeInfo->version(),
+ pThemeInfo->description(),
+ pThemeInfo->subdirectory(),
+ pThemeInfo->application(),
+ pThemeInfo->author(),
+ pThemeInfo->date(),
+ pThemeInfo->themeEngineVersion(),
+ pThemeInfo->mediumScreenshot(),
+ 0
+ );
+
+ pTip->tip(m_pListBox->itemRect(it),szThemeDescription);
+}
diff --git a/src/modules/theme/managementdialog.h b/src/modules/theme/managementdialog.h
new file mode 100644
index 00000000..52ae0f86
--- /dev/null
+++ b/src/modules/theme/managementdialog.h
@@ -0,0 +1,109 @@
+#ifndef _MANAGEMENTDIALOG_H_
+#define _MANAGEMENTDIALOG_H_
+//=============================================================================
+//
+// File : managementdialog.h
+// Created on Sat 30 Dec 2006 14:54:56 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2006 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_optionswidget.h"
+#include "kvi_pointerlist.h"
+#include "kvi_theme.h"
+
+#include <qdialog.h>
+#ifdef COMPILE_USE_QT4
+#include <q3simplerichtext.h>
+#define KviTalSimpleRichText Q3SimpleRichText
+#else
+#include <qsimplerichtext.h>
+#define KviTalSimpleRichText QSimpleRichText
+#endif
+#include "kvi_tal_listbox.h"
+#include <qcombobox.h>
+#include "kvi_tal_popupmenu.h"
+#include <qcursor.h>
+#include <kvi_tal_wizard.h>
+
+
+class QLineEdit;
+class KviTalTextEdit;
+class QPushButton;
+class QLabel;
+class QCheckBox;
+
+//class QMultiLineEdit;
+
+class KviDynamicToolTip;
+class KviStyledToolButton;
+
+
+class KviThemeListBoxItem : public KviTalListBoxText
+{
+public:
+ KviThemeListBoxItem(KviTalListBox * box,KviThemeInfo * inf);
+ virtual ~KviThemeListBoxItem();
+public:
+ KviThemeInfo * m_pThemeInfo;
+ KviTalSimpleRichText * m_pText;
+public:
+ KviThemeInfo * themeInfo(){ return m_pThemeInfo; };
+ virtual int height ( const KviTalListBox * lb ) const ;
+protected:
+ virtual void paint ( QPainter * painter );
+};
+
+
+class KviThemeManagementDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ KviThemeManagementDialog(QWidget * parent);
+ virtual ~KviThemeManagementDialog();
+protected:
+ static KviThemeManagementDialog * m_pInstance;
+ KviTalListBox * m_pListBox;
+ KviTalPopupMenu * m_pContextPopup;
+ KviStyledToolButton * m_pDeleteThemeButton;
+ KviStyledToolButton * m_pPackThemeButton;
+public:
+ static KviThemeManagementDialog * instance(){ return m_pInstance; };
+ static void display();
+ static void cleanup();
+protected:
+ void fillThemeBox(const QString &szDir);
+ bool hasSelectedItems();
+ virtual void closeEvent(QCloseEvent * e);
+protected slots:
+ void saveCurrentTheme();
+ void getMoreThemes();
+ void installFromFile();
+ void fillThemeBox();
+ void deleteTheme();
+ void closeClicked();
+ void packTheme();
+ void applyTheme(KviTalListBoxItem *);
+ void applyCurrentTheme();
+ void enableDisableButtons();
+ void contextMenuRequested(KviTalListBoxItem * item, const QPoint & pos);
+ void tipRequest(KviDynamicToolTip *pTip,const QPoint &pnt);
+};
+
+#endif //!_MANAGEMENTDIALOG_H_
diff --git a/src/modules/theme/packthemedialog.cpp b/src/modules/theme/packthemedialog.cpp
new file mode 100644
index 00000000..88b248a8
--- /dev/null
+++ b/src/modules/theme/packthemedialog.cpp
@@ -0,0 +1,489 @@
+//=============================================================================
+//
+// File : packthemedialog.cpp
+// Created on Wed 03 Jan 2007 01:11:44 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2007 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "packthemedialog.h"
+#include "themefunctions.h"
+
+#include <qlayout.h>
+#include <qpushbutton.h>
+#include <qlineedit.h>
+#include <qregexp.h>
+#include <qmessagebox.h>
+#include <qdir.h>
+#include <qcombobox.h>
+#include <qpainter.h>
+#include <qtooltip.h>
+#include <qimage.h>
+#include <kvi_tal_textedit.h>
+#ifdef COMPILE_USE_QT4
+#include <q3multilineedit.h>
+#include <QDateTime>
+#else
+#include <qmultilineedit.h>
+#endif
+#include <qbuffer.h>
+#include <qlabel.h>
+#include <qregexp.h>
+
+
+#include "kvi_options.h"
+#include "kvi_locale.h"
+#include "kvi_config.h"
+#include "kvi_fileutils.h"
+#include "kvi_app.h"
+#include "kvi_frame.h"
+#include "kvi_iconmanager.h"
+#include "kvi_styled_controls.h"
+#include "kvi_packagefile.h"
+#include "kvi_fileextensions.h"
+#include "kvi_filedialog.h"
+#include "kvi_msgbox.h"
+#include "kvi_selectors.h"
+#include "kvi_miscutils.h"
+#include "kvi_sourcesdate.h"
+
+
+
+KviPackThemeDialog::KviPackThemeDialog(QWidget * pParent,KviPointerList<KviThemeInfo> * pThemeInfoList)
+: KviTalWizard(pParent)
+{
+ m_pThemeInfoList = pThemeInfoList;
+
+ KviThemeInfo * pThemeInfo;
+ QString szPackageName;
+ QString szPackageAuthor;
+ QString szPackageDescription;
+ QString szPackageVersion;
+
+ m_szPackagePath = QDir::homeDirPath();
+ KviQString::ensureLastCharIs(m_szPackagePath,QChar(KVI_PATH_SEPARATOR_CHAR));
+
+ bool bPackagePathSet = false;
+
+ if(m_pThemeInfoList->count() > 1)
+ {
+ szPackageName = "MyThemes";
+ szPackageAuthor = __tr2qs_ctx("Your name here","theme");
+ szPackageVersion = "1.0.0";
+ szPackageDescription = __tr2qs_ctx("Put a package description here...","theme");
+ } else {
+ if(m_pThemeInfoList->count() > 0)
+ {
+ pThemeInfo = m_pThemeInfoList->first();
+ szPackageName = pThemeInfo->subdirectory();
+ szPackageAuthor = pThemeInfo->author();
+ szPackageDescription = pThemeInfo->description();
+ szPackageVersion = pThemeInfo->version();
+
+ m_szPackagePath += pThemeInfo->subdirectory();
+ if(m_szPackagePath.find(QRegExp("[0-9]\\.[0-9]")) == -1)
+ {
+ m_szPackagePath += "-";
+ m_szPackagePath += szPackageVersion;
+ }
+ m_szPackagePath += ".";
+ m_szPackagePath += KVI_FILEEXTENSION_THEMEPACKAGE;
+
+ bPackagePathSet = true;
+ }
+ }
+
+ if(!bPackagePathSet)
+ {
+ m_szPackagePath += szPackageName;
+ m_szPackagePath += "-";
+ m_szPackagePath += szPackageVersion;
+ m_szPackagePath += ".";
+ m_szPackagePath += KVI_FILEEXTENSION_THEMEPACKAGE;
+ }
+
+ setCaption(__tr2qs_ctx("Export Theme - KVIrc","theme"));
+ setMinimumSize(400,350);
+
+ // welcome page ==================================================================================
+ QWidget * pPage = new QWidget(this);
+ QGridLayout * pLayout = new QGridLayout(pPage,2,1,4,4);
+
+ QLabel * pLabel = new QLabel(pPage);
+ QString szText = "<p>";
+ szText += __tr2qs_ctx("This procedure allows you to export the selected themes to a single package. It is useful when you want to distribute your themes to the public.","theme");
+ szText += "</p><p>";
+ szText += __tr2qs_ctx("You will be asked to provide a package name, a description and, if you want, an icon/screenshot.","theme");
+ szText += "</p><p>";
+ szText += __tr2qs_ctx("Hit the \"Next\" button to begin.","theme");
+ szText += "<p>";
+
+ pLabel->setText(szText);
+ pLayout->addWidget(pLabel,0,0);
+ pLayout->setRowStretch(1,1);
+
+ addPage(pPage,__tr2qs_ctx("Welcome","theme"));
+ setBackEnabled(pPage,false);
+ setNextEnabled(pPage,true);
+ setHelpEnabled(pPage,false);
+ setFinishEnabled(pPage,false);
+
+ // theme data name ================================================================================
+
+ pPage = new QWidget(this);
+ pLayout = new QGridLayout(pPage,2,1,4,4);
+
+ pLabel = new QLabel(pPage);
+ pLabel->setText(__tr2qs_ctx("This is the information list for the themes you're packaging. If it looks OK press \"Next\" to continue, otherwise press \"Cancel\" and rewiew your themes first.","theme"));
+ pLabel->setTextFormat(Qt::RichText);
+ pLayout->addWidget(pLabel,0,0);
+
+ QString szThemesDescription = "<html><body bgcolor=\"#ffffff\">";
+
+ int iIdx = 0;
+ QPixmap pixScreenshot;
+ QString szScreenshotPath;
+
+ for(pThemeInfo = m_pThemeInfoList->first();pThemeInfo;pThemeInfo = m_pThemeInfoList->next())
+ {
+ QString szThemeDescription;
+
+ if(pixScreenshot.isNull())
+ {
+ pixScreenshot = pThemeInfo->smallScreenshot();
+ if(!pixScreenshot.isNull())
+ szScreenshotPath = pThemeInfo->smallScreenshotPath();
+ }
+
+ KviThemeFunctions::getThemeHtmlDescription(
+ szThemeDescription,
+ pThemeInfo->name(),
+ pThemeInfo->version(),
+ pThemeInfo->description(),
+ pThemeInfo->subdirectory(),
+ pThemeInfo->application(),
+ pThemeInfo->author(),
+ pThemeInfo->date(),
+ pThemeInfo->themeEngineVersion(),
+ pThemeInfo->smallScreenshot(),
+ iIdx
+ );
+
+ if(iIdx > 0)
+ szThemesDescription += "<hr>";
+ szThemesDescription += szThemeDescription;
+ iIdx++;
+ }
+
+ szThemesDescription += "</body></html>";
+
+ KviTalTextEdit * pTextEdit = new KviTalTextEdit(pPage);
+ pTextEdit->setPaper(QBrush(QColor(255,255,255)));
+ pTextEdit->setReadOnly(true);
+ pTextEdit->setText(szThemesDescription);
+ pLayout->addWidget(pTextEdit,1,0);
+ pLayout->setRowStretch(1,1);
+
+ addPage(pPage,__tr2qs_ctx("Theme Data","theme"));
+ setBackEnabled(pPage,true);
+ setHelpEnabled(pPage,false);
+ setNextEnabled(pPage,true);
+ setFinishEnabled(pPage,false);
+
+ // packager informations ================================================================================
+
+ pPage = new QWidget(this);
+ pLayout = new QGridLayout(pPage,5,2,4,4);
+
+ pLabel = new QLabel(pPage);
+ pLabel->setText(__tr2qs_ctx("Here you need to provide informations about you (the packager) and a short description of the package you're creating.","theme"));
+ pLabel->setTextFormat(Qt::RichText);
+ pLayout->addMultiCellWidget(pLabel,0,0,0,1);
+
+ pLabel = new QLabel(pPage);
+ pLabel->setText(__tr2qs_ctx("Package Name:","theme"));
+ pLayout->addWidget(pLabel,1,0);
+
+ m_pPackageNameEdit = new QLineEdit(pPage);
+ m_pPackageNameEdit->setText(szPackageName);
+ pLayout->addWidget(m_pPackageNameEdit,1,1);
+
+ pLabel = new QLabel(pPage);
+ pLabel->setText(__tr2qs_ctx("Version:","theme"));
+ pLayout->addWidget(pLabel,2,0);
+
+ m_pPackageVersionEdit = new QLineEdit(pPage);
+ m_pPackageVersionEdit->setText(szPackageVersion);
+ pLayout->addWidget(m_pPackageVersionEdit,2,1);
+
+ pLabel = new QLabel(pPage);
+ pLabel->setText(__tr2qs_ctx("Description:","theme"));
+ pLayout->addWidget(pLabel,3,0);
+
+ m_pPackageDescriptionEdit = new KviTalTextEdit(pPage);
+ m_pPackageDescriptionEdit->setText(szPackageDescription);
+ pLayout->addWidget(m_pPackageDescriptionEdit,3,1);
+
+ pLabel = new QLabel(pPage);
+ pLabel->setText(__tr2qs_ctx("Package Author:","theme"));
+ pLayout->addWidget(pLabel,4,0);
+
+ m_pPackagerNameEdit = new QLineEdit(pPage);
+ m_pPackagerNameEdit->setText(szPackageAuthor);
+ pLayout->addWidget(m_pPackagerNameEdit,4,1);
+
+
+ pLayout->setRowStretch(3,1);
+ pLayout->setColStretch(1,1);
+
+ addPage(pPage,__tr2qs_ctx("Package Informations","theme"));
+ setBackEnabled(pPage,true);
+ setHelpEnabled(pPage,false);
+ setNextEnabled(pPage,true);
+ setFinishEnabled(pPage,false);
+
+ // screenshot/logo/icon ================================================================================
+
+ pPage = new QWidget(this);
+ pLayout = new QGridLayout(pPage,3,1,4,4);
+
+ pLabel = new QLabel(pPage);
+ pLabel->setText(__tr2qs_ctx("Here you can choose the image that will appear in the installation dialog for your theme package. It can be an icon, a logo or a screenshot and it should be not larger than 300x225. If you don't provide an image a simple default icon will be used at installation stage.","theme"));
+ pLabel->setTextFormat(Qt::RichText);
+ pLayout->addWidget(pLabel,0,0);
+
+ m_pImageLabel = new QLabel(pPage);
+ m_pImageLabel->setFrameStyle(QFrame::Sunken | QFrame::Panel);
+ m_pImageLabel->setMinimumSize(300,225);
+ m_pImageLabel->setAlignment(Qt::AlignCenter | Qt::AlignVCenter);
+ pLayout->addWidget(m_pImageLabel,1,0);
+
+ QString szFilter = "*.png *.jpg *.xpm";
+ m_pImageSelector = new KviFileSelector(pPage,"",&m_szImagePath,true,0,szFilter);
+ connect(m_pImageSelector,SIGNAL(selectionChanged(const QString &)),this,SLOT(imageSelectionChanged(const QString &)));
+ pLayout->addWidget(m_pImageSelector,2,0);
+ pLayout->setRowStretch(1,1);
+
+ m_pImageSelectionPage = pPage;
+ addPage(pPage,__tr2qs_ctx("Icon/Screenshot","theme"));
+ setBackEnabled(pPage,true);
+ setHelpEnabled(pPage,false);
+ setNextEnabled(pPage,true);
+ setFinishEnabled(pPage,false);
+
+ // save file name ================================================================================
+
+ pPage = new QWidget(this);
+ pLayout = new QGridLayout(pPage,4,1,4,4);
+
+ pLabel = new QLabel(pPage);
+ pLabel->setText(__tr2qs_ctx("Here you must choose the file name for the theme package. It should have a *.%1 extension.","theme").arg(KVI_FILEEXTENSION_THEMEPACKAGE));
+ pLabel->setTextFormat(Qt::RichText);
+ pLayout->addWidget(pLabel,0,0);
+
+ szFilter = "*.";
+ szFilter += KVI_FILEEXTENSION_THEMEPACKAGE;
+ m_pPathSelector = new KviFileSelector(pPage,"",&m_szPackagePath,true,KviFileSelector::ChooseSaveFileName,szFilter);
+ pLayout->addWidget(m_pPathSelector,1,0);
+
+ pLabel = new QLabel(pPage);
+ pLabel->setText(__tr2qs_ctx("Finally hit the \"Finish\" button to complete the packaging operation.","theme"));
+ pLabel->setTextFormat(Qt::RichText);
+ pLayout->addWidget(pLabel,3,0);
+
+ pLayout->setRowStretch(2,1);
+
+ addPage(pPage,__tr2qs_ctx("Package Path","theme"));
+ setBackEnabled(pPage,true);
+ setHelpEnabled(pPage,false);
+ setNextEnabled(pPage,false);
+ setFinishEnabled(pPage,true);
+
+ if(!szScreenshotPath.isEmpty())
+ {
+ m_pImageSelector->setSelection(szScreenshotPath);
+ imageSelectionChanged(szScreenshotPath);
+ }
+}
+
+KviPackThemeDialog::~KviPackThemeDialog()
+{
+}
+
+void KviPackThemeDialog::imageSelectionChanged(const QString &szImagePath)
+{
+ QImage pix(szImagePath);
+ if(!pix.isNull())
+ {
+ QPixmap out;
+ if(pix.width() > 300 || pix.height() > 225)
+#ifdef COMPILE_USE_QT4
+ out.convertFromImage(pix.scaled(300,225,Qt::KeepAspectRatio,Qt::SmoothTransformation));
+#else
+ out.convertFromImage(pix.smoothScale(300,225,QImage::ScaleMin));
+#endif
+ else
+ out.convertFromImage(pix);
+ m_pImageLabel->setPixmap(out);
+ return;
+ }
+
+ QMessageBox::critical(this,__tr2qs_ctx("Export Theme - KVIrc","theme"),__tr2qs_ctx("Failed to load the selected image","theme"),
+ QMessageBox::Ok,QMessageBox::NoButton,QMessageBox::NoButton);
+
+ m_pImageSelector->setSelection("");
+ m_pImageLabel->setPixmap(QPixmap());
+}
+
+
+void KviPackThemeDialog::accept()
+{
+ if(!packTheme())return;
+ KviTalWizard::accept();
+}
+
+
+bool KviPackThemeDialog::packTheme()
+{
+ m_pImageSelector->commit();
+ m_pPathSelector->commit();
+
+ QString szPackageAuthor = m_pPackagerNameEdit->text();
+ QString szPackageName = m_pPackageNameEdit->text();
+ QString szPackageDescription = m_pPackageDescriptionEdit->text();
+ QString szPackageVersion = m_pPackageVersionEdit->text();
+
+ QImage pix(m_szImagePath);
+ QPixmap out;
+ if(!pix.isNull())
+ {
+ if(pix.width() > 300 || pix.height() > 225)
+ #ifdef COMPILE_USE_QT4
+ out.convertFromImage(pix.scaled(300,225,Qt::KeepAspectRatio));
+ #else
+ out.convertFromImage(pix.smoothScale(300,225,QImage::ScaleMin));
+#endif
+ else
+ out.convertFromImage(pix);
+ } else {
+ if(!m_szImagePath.isEmpty())
+ {
+ QMessageBox::critical(this,__tr2qs_ctx("Export Theme - KVIrc","theme"),__tr2qs_ctx("Failed to load the selected image: please fix it","theme"),
+ QMessageBox::Ok,QMessageBox::NoButton,QMessageBox::NoButton);
+ setCurrentPage(m_pImageSelectionPage);
+ return false;
+ }
+ }
+
+ KviPackageWriter f;
+
+ QString szTmp = QDateTime::currentDateTime().toString();
+
+ f.addInfoField("PackageType","ThemePack");
+ f.addInfoField("ThemePackVersion","1");
+ f.addInfoField("Name",szPackageName);
+ f.addInfoField("Version",szPackageVersion);
+ f.addInfoField("Author",szPackageAuthor);
+ f.addInfoField("Description",szPackageDescription);
+ f.addInfoField("Date",szTmp);
+ f.addInfoField("Application","KVIrc " KVI_VERSION "." KVI_SOURCES_DATE);
+
+ if(!out.isNull())
+ {
+ QByteArray * pba = new QByteArray();
+#ifdef COMPILE_USE_QT4
+ QBuffer buffer(pba,0);
+#else
+ QBuffer buffer(*pba);
+#endif
+ buffer.open(IO_WriteOnly);
+ out.save(&buffer,"PNG");
+ buffer.close();
+ f.addInfoField("Image",pba); // cool :) [no disk access needed]
+ }
+
+ szTmp.setNum(m_pThemeInfoList->count());
+ f.addInfoField("ThemeCount",szTmp);
+
+ int iIdx = 0;
+ for(KviThemeInfo * pInfo = m_pThemeInfoList->first();pInfo;pInfo = m_pThemeInfoList->next())
+ {
+ KviQString::sprintf(szTmp,"Theme%dName",iIdx);
+ f.addInfoField(szTmp,pInfo->name());
+ KviQString::sprintf(szTmp,"Theme%dVersion",iIdx);
+ f.addInfoField(szTmp,pInfo->version());
+ KviQString::sprintf(szTmp,"Theme%dDescription",iIdx);
+ f.addInfoField(szTmp,pInfo->description());
+ KviQString::sprintf(szTmp,"Theme%dDate",iIdx);
+ f.addInfoField(szTmp,pInfo->date());
+ KviQString::sprintf(szTmp,"Theme%dSubdirectory",iIdx);
+ f.addInfoField(szTmp,pInfo->subdirectory());
+ KviQString::sprintf(szTmp,"Theme%dAuthor",iIdx);
+ f.addInfoField(szTmp,pInfo->author());
+ KviQString::sprintf(szTmp,"Theme%dApplication",iIdx);
+ f.addInfoField(szTmp,pInfo->application());
+ KviQString::sprintf(szTmp,"Theme%dThemeEngineVersion",iIdx);
+ f.addInfoField(szTmp,pInfo->themeEngineVersion());
+ QPixmap pixScreenshot = pInfo->smallScreenshot();
+ if(!pixScreenshot.isNull())
+ {
+ KviQString::sprintf(szTmp,"Theme%dScreenshot",iIdx);
+ QByteArray * pba = new QByteArray();
+#ifdef COMPILE_USE_QT4
+ QBuffer bufferz(pba,0);
+#else
+ QBuffer bufferz(*pba);
+#endif
+ bufferz.open(IO_WriteOnly);
+ pixScreenshot.save(&bufferz,"PNG");
+ bufferz.close();
+ f.addInfoField(szTmp,pba);
+ }
+
+ if(!f.addDirectory(pInfo->absoluteDirectory(),pInfo->subdirectory()))
+ {
+ szTmp = __tr2qs_ctx("Packaging failed","theme");
+ szTmp += ": ";
+ szTmp += f.lastError();
+ QMessageBox::critical(this,__tr2qs_ctx("Export Theme - KVIrc","theme"),szTmp,
+ QMessageBox::Ok,QMessageBox::NoButton,QMessageBox::NoButton);
+ }
+
+ iIdx++;
+ }
+
+ if(!f.pack(m_szPackagePath))
+ {
+ szTmp = __tr2qs_ctx("Packaging failed","theme");
+ szTmp += ": ";
+ szTmp += f.lastError();
+ QMessageBox::critical(this,__tr2qs_ctx("Export Theme - KVIrc","theme"),szTmp,
+ QMessageBox::Ok,QMessageBox::NoButton,QMessageBox::NoButton);
+ return false;
+ }
+
+ //KviPackageReader r;
+ //r.unpack("/root/test.kvt","/root/unpacked_test_kvt");
+
+ QMessageBox::information(this,__tr2qs_ctx("Export Theme - KVIrc","theme"),__tr2qs("Package saved succesfully"),
+ QMessageBox::Ok,QMessageBox::NoButton,QMessageBox::NoButton);
+
+ return true;
+}
+
diff --git a/src/modules/theme/packthemedialog.h b/src/modules/theme/packthemedialog.h
new file mode 100644
index 00000000..7731cc30
--- /dev/null
+++ b/src/modules/theme/packthemedialog.h
@@ -0,0 +1,66 @@
+#ifndef _PACKTHEMEDIALOG_H_
+#define _PACKTHEMEDIALOG_H_
+//=============================================================================
+//
+// File : packthemedialog.h
+// Created on Wed 03 Jan 2007 01:11:44 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2007 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_pointerlist.h"
+#include "kvi_theme.h"
+
+#include <qdialog.h>
+#include <kvi_tal_wizard.h>
+
+class QLineEdit;
+class KviTalTextEdit;
+class QLabel;
+class QMultiLineEdit;
+class KviFileSelector;
+
+
+class KviPackThemeDialog : public KviTalWizard
+{
+ Q_OBJECT
+public:
+ KviPackThemeDialog(QWidget * pParent,KviPointerList<KviThemeInfo> * pThemeInfoList);
+ virtual ~KviPackThemeDialog();
+protected:
+ QString m_szImagePath;
+ KviFileSelector * m_pImageSelector;
+ QString m_szPackagePath;
+ KviFileSelector * m_pPathSelector;
+ QLabel * m_pImageLabel;
+ KviPointerList<KviThemeInfo> * m_pThemeInfoList;
+ QLineEdit * m_pPackageNameEdit;
+ KviTalTextEdit * m_pPackageDescriptionEdit;
+ QLineEdit * m_pPackageVersionEdit;
+ QLineEdit * m_pPackagerNameEdit;
+ QWidget * m_pImageSelectionPage;
+protected:
+ virtual void accept();
+ bool packTheme();
+protected slots:
+ void imageSelectionChanged(const QString &szImagePath);
+};
+
+#endif //!_PACKTHEMEDIALOG_H_
diff --git a/src/modules/theme/savethemedialog.cpp b/src/modules/theme/savethemedialog.cpp
new file mode 100644
index 00000000..79319e60
--- /dev/null
+++ b/src/modules/theme/savethemedialog.cpp
@@ -0,0 +1,301 @@
+//=============================================================================
+//
+// File : savethemedialog.cpp
+// Created on Wed 03 Jan 2007 03:01:34 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2007 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "savethemedialog.h"
+#include "themefunctions.h"
+
+#include <qlayout.h>
+#include <qpushbutton.h>
+#include <qlineedit.h>
+#include <qregexp.h>
+#include <qmessagebox.h>
+#include <qdir.h>
+#include <qcombobox.h>
+#include <qpainter.h>
+#include <qtooltip.h>
+#include <qimage.h>
+#include <kvi_tal_textedit.h>
+#ifdef COMPILE_USE_QT4
+#include <q3multilineedit.h>
+#include <QDateTime>
+#else
+#include <qmultilineedit.h>
+#endif
+#include <qbuffer.h>
+#include <qlabel.h>
+
+
+#include "kvi_options.h"
+#include "kvi_locale.h"
+#include "kvi_config.h"
+#include "kvi_fileutils.h"
+#include "kvi_app.h"
+#include "kvi_frame.h"
+#include "kvi_iconmanager.h"
+#include "kvi_styled_controls.h"
+#include "kvi_packagefile.h"
+#include "kvi_fileextensions.h"
+#include "kvi_filedialog.h"
+#include "kvi_msgbox.h"
+#include "kvi_selectors.h"
+#include "kvi_miscutils.h"
+#include "kvi_sourcesdate.h"
+
+
+
+KviSaveThemeDialog::KviSaveThemeDialog(QWidget * pParent)
+: KviTalWizard(pParent)
+{
+ setCaption(__tr2qs_ctx("Save Current Theme - KVIrc","theme"));
+ setMinimumSize(400,350);
+
+ // welcome page ==================================================================================
+ QWidget * pPage = new QWidget(this);
+ QGridLayout * pLayout = new QGridLayout(pPage,2,1,4,4);
+
+ QLabel * pLabel = new QLabel(pPage);
+ QString szText = "<p>";
+ szText += __tr2qs_ctx("This procedure allows you to save the current theme settings to a single directory. It is useful if you want to apply other themes or play with the theme settings and later come back to this theme with a single click. It will also allow you to manually modify the theme settings and later export them to a distributable package.","theme");
+ szText += "</p><p>";
+ szText += __tr2qs_ctx("You will be asked to provide a theme name, a description and, if you want, a screenshot.","theme");
+ szText += "</p><p>";
+ szText += __tr2qs_ctx("Hit the \"Next\" button to begin.","theme");
+ szText += "<p>";
+
+ pLabel->setText(szText);
+ pLayout->addWidget(pLabel,0,0);
+ pLayout->setRowStretch(1,1);
+
+ addPage(pPage,__tr2qs_ctx("Welcome","theme"));
+ setBackEnabled(pPage,false);
+ setNextEnabled(pPage,true);
+ setHelpEnabled(pPage,false);
+ setFinishEnabled(pPage,false);
+
+ // packager informations ================================================================================
+
+ pPage = new QWidget(this);
+ pLayout = new QGridLayout(pPage,5,2,4,4);
+
+ pLabel = new QLabel(pPage);
+ pLabel->setText(__tr2qs_ctx("Here you need to provide informations about you (the author) and a short description of the theme you're creating.","theme"));
+ pLabel->setTextFormat(Qt::RichText);
+ pLayout->addMultiCellWidget(pLabel,0,0,0,1);
+
+ pLabel = new QLabel(pPage);
+ pLabel->setText(__tr2qs_ctx("Theme Name:","theme"));
+ pLayout->addWidget(pLabel,1,0);
+
+ m_pThemeNameEdit = new QLineEdit(pPage);
+ //m_pThemeNameEdit->setText(szThemeName);
+ pLayout->addWidget(m_pThemeNameEdit,1,1);
+
+ pLabel = new QLabel(pPage);
+ pLabel->setText(__tr2qs_ctx("Version:","theme"));
+ pLayout->addWidget(pLabel,2,0);
+
+ m_pThemeVersionEdit = new QLineEdit(pPage);
+ //m_pThemeVersionEdit->setText(szThemeVersion);
+ pLayout->addWidget(m_pThemeVersionEdit,2,1);
+
+ pLabel = new QLabel(pPage);
+ pLabel->setText(__tr2qs_ctx("Description:","theme"));
+ pLayout->addWidget(pLabel,3,0);
+
+ m_pThemeDescriptionEdit = new KviTalTextEdit(pPage);
+ //m_pThemeDescriptionEdit->setText(szThemeDescription);
+ pLayout->addWidget(m_pThemeDescriptionEdit,3,1);
+
+ pLabel = new QLabel(pPage);
+ pLabel->setText(__tr2qs_ctx("Theme Author:","theme"));
+ pLayout->addWidget(pLabel,4,0);
+
+ m_pAuthorNameEdit = new QLineEdit(pPage);
+ //m_pAuthorNameEdit->setText(szThemeAuthor);
+ pLayout->addWidget(m_pAuthorNameEdit,4,1);
+
+
+ pLayout->setRowStretch(3,1);
+ pLayout->setColStretch(1,1);
+
+ addPage(pPage,__tr2qs_ctx("Theme Informations","theme"));
+ setBackEnabled(pPage,true);
+ setHelpEnabled(pPage,false);
+ setNextEnabled(pPage,true);
+ setFinishEnabled(pPage,false);
+
+ // screenshot/logo/icon ================================================================================
+
+ pPage = new QWidget(this);
+ pLayout = new QGridLayout(pPage,4,1,4,4);
+
+ pLabel = new QLabel(pPage);
+ pLabel->setText(__tr2qs_ctx("Here you can either choose a screenshot image from disk or make one now. The screenshot will be displayed in the tooltips of the theme management dialog and will be also visible in the package installation dialog if you will export the theme to a distributable package.","theme"));
+ pLabel->setTextFormat(Qt::RichText);
+ pLayout->addWidget(pLabel,0,0);
+
+ m_pImageLabel = new QLabel(pPage);
+ m_pImageLabel->setFrameStyle(QFrame::Sunken | QFrame::Panel);
+ m_pImageLabel->setMinimumSize(300,225);
+ m_pImageLabel->setAlignment(Qt::AlignCenter | Qt::AlignVCenter);
+ pLayout->addWidget(m_pImageLabel,1,0);
+
+ QString szFilter = "*.png *.jpg *.xpm";
+ m_pImageSelector = new KviFileSelector(pPage,"",&m_szScreenshotPath,true,0,szFilter);
+ connect(m_pImageSelector,SIGNAL(selectionChanged(const QString &)),this,SLOT(imageSelectionChanged(const QString &)));
+ pLayout->addWidget(m_pImageSelector,2,0);
+
+ QPushButton * pButton = new QPushButton(pPage);
+ pButton->setText(__tr2qs_ctx("Make Screenshot Now","theme"));
+ connect(pButton,SIGNAL(clicked()),this,SLOT(makeScreenshot()));
+ pLayout->addWidget(pButton,3,0);
+
+ pLayout->setRowStretch(1,1);
+
+ m_pImageSelectionPage = pPage;
+ addPage(pPage,__tr2qs_ctx("Screenshot","theme"));
+ setBackEnabled(pPage,true);
+ setHelpEnabled(pPage,false);
+ setNextEnabled(pPage,true);
+ setFinishEnabled(pPage,true);
+}
+
+KviSaveThemeDialog::~KviSaveThemeDialog()
+{
+}
+
+void KviSaveThemeDialog::imageSelectionChanged(const QString &szImagePath)
+{
+ QImage pix(szImagePath);
+ if(!pix.isNull())
+ {
+ QPixmap out;
+ if(pix.width() > 300 || pix.height() > 225)
+ #ifdef COMPILE_USE_QT4
+ out.convertFromImage(pix.scaled(300,225,Qt::KeepAspectRatio));
+ #else
+ out.convertFromImage(pix.smoothScale(300,225,QImage::ScaleMin));
+#endif
+ else
+ out.convertFromImage(pix);
+ m_pImageLabel->setPixmap(out);
+ return;
+ }
+
+ QMessageBox::critical(this,__tr2qs_ctx("Save Current Theme - KVIrc","theme"),__tr2qs_ctx("Failed to load the selected image","theme"),
+ QMessageBox::Ok,QMessageBox::NoButton,QMessageBox::NoButton);
+
+ m_pImageSelector->setSelection("");
+ m_pImageLabel->setPixmap(QPixmap());
+}
+
+
+void KviSaveThemeDialog::accept()
+{
+ if(!saveTheme())return;
+ KviTalWizard::accept();
+}
+
+
+void KviSaveThemeDialog::makeScreenshot()
+{
+ QString szFileName;
+ g_pApp->getTmpFileName(szFileName,"screenshot.png");
+ if(!KviThemeFunctions::makeKVIrcScreenshot(szFileName))
+ {
+ QMessageBox::critical(this,__tr2qs_ctx("Acquire Screenshot - KVIrc","theme"),__tr2qs_ctx("Failed to make screenshot","theme"),
+ QMessageBox::Ok,QMessageBox::NoButton,QMessageBox::NoButton);
+ return;
+ }
+ m_pImageSelector->setSelection(szFileName);
+ imageSelectionChanged(szFileName);
+}
+
+bool KviSaveThemeDialog::saveTheme()
+{
+ m_pImageSelector->commit();
+
+ KviThemeInfo sto;
+ sto.setName(m_pThemeNameEdit->text());
+ if(sto.name().isEmpty())
+ {
+ QMessageBox::critical(this,__tr2qs_ctx("Save Current Theme - KVIrc","theme"),__tr2qs_ctx("You must choose a theme name!","theme"),QMessageBox::Ok,
+ QMessageBox::NoButton,QMessageBox::NoButton);
+ return false;
+ }
+
+ sto.setAuthor(m_pAuthorNameEdit->text());
+ sto.setDescription(m_pThemeDescriptionEdit->text());
+ sto.setDate(QDateTime::currentDateTime().toString());
+ sto.setVersion(m_pThemeVersionEdit->text());
+ sto.setApplication("KVIrc " KVI_VERSION "." KVI_SOURCES_DATE);
+
+ if(sto.version().isEmpty())sto.setVersion("1.0.0");
+
+ QString szSubdir = sto.name() + QString("-") + sto.version();
+ szSubdir.replace(QRegExp("[ \\\\/:][ \\\\/:]*"),"_");
+ sto.setSubdirectory(szSubdir);
+
+ QString szAbsDir;
+ g_pApp->getLocalKvircDirectory(szAbsDir,KviApp::Themes,sto.subdirectory(),true);
+ if(!KviFileUtils::makeDir(szAbsDir))
+ {
+ QMessageBox::critical(this,__tr2qs_ctx("Save Current Theme - KVIrc","theme"),__tr2qs_ctx("Unable to create theme directory.","theme"),
+ QMessageBox::Ok,QMessageBox::NoButton,QMessageBox::NoButton);
+ return false;
+ }
+
+ sto.setAbsoluteDirectory(szAbsDir);
+
+ if(!KviTheme::save(sto))
+ {
+ QString szMsg2;
+ QString szErr = sto.lastError();
+ KviQString::sprintf(szMsg2,__tr2qs_ctx("Unable to save theme: %Q","theme"),&szErr);
+ QMessageBox::critical(this,__tr2qs_ctx("Save Current Theme - KVIrc","theme"),szMsg2,
+ QMessageBox::Ok,QMessageBox::NoButton,QMessageBox::NoButton);
+ return false;
+ }
+ // write down the screenshot, if needed
+
+ if(!m_szScreenshotPath.isEmpty())
+ {
+ if(!KviTheme::saveScreenshots(sto,m_szScreenshotPath))
+ {
+ QMessageBox::critical(this,__tr2qs_ctx("Save Current Theme - KVIrc","theme"),__tr2qs_ctx("Failed to load the selected screenshot image: please fix it","theme"),
+ QMessageBox::Ok,QMessageBox::NoButton,QMessageBox::NoButton);
+ setCurrentPage(m_pImageSelectionPage);
+ return false;
+ }
+ }
+
+ QString szMsg = __tr2qs_ctx("Theme saved successfully to ","theme");
+ szMsg += sto.absoluteDirectory();
+
+ QMessageBox::information(this,__tr2qs_ctx("Save Theme - KVIrc","theme"),szMsg,QMessageBox::Ok,
+ QMessageBox::NoButton,QMessageBox::NoButton);
+
+ return true;
+}
+
diff --git a/src/modules/theme/savethemedialog.h b/src/modules/theme/savethemedialog.h
new file mode 100644
index 00000000..df55ee92
--- /dev/null
+++ b/src/modules/theme/savethemedialog.h
@@ -0,0 +1,71 @@
+#ifndef _SAVETHEMEDIALOG_H_
+#define _SAVETHEMEDIALOG_H_
+//=============================================================================
+//
+// File : savethemedialog.h
+// Created on Wed 03 Jan 2007 03:01:34 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2007 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_pointerlist.h"
+#include "kvi_theme.h"
+
+#include <qdialog.h>
+#include <kvi_tal_wizard.h>
+
+
+class QLineEdit;
+class KviTalTextEdit;
+class QPushButton;
+class QCheckBox;
+class QLabel;
+class QMultiLineEdit;
+class KviFileSelector;
+
+
+class KviSaveThemeDialog : public KviTalWizard
+{
+ Q_OBJECT
+public:
+ KviSaveThemeDialog(QWidget * pParent);
+ virtual ~KviSaveThemeDialog();
+protected:
+ QString m_szScreenshotPath;
+ KviFileSelector * m_pImageSelector;
+ QLabel * m_pImageLabel;
+ QLineEdit * m_pThemeNameEdit;
+ KviTalTextEdit * m_pThemeDescriptionEdit;
+ QLineEdit * m_pThemeVersionEdit;
+ QLineEdit * m_pAuthorNameEdit;
+ QWidget * m_pImageSelectionPage;
+ QPushButton * m_pOkButton;
+protected:
+ virtual void accept();
+ bool saveTheme();
+protected slots:
+ void makeScreenshot();
+ void imageSelectionChanged(const QString &szImagePath);
+ //void themeNameChanged(const QString &txt);
+};
+
+
+
+#endif //!_SAVETHEMEDIALOG_H_
diff --git a/src/modules/theme/themefunctions.cpp b/src/modules/theme/themefunctions.cpp
new file mode 100644
index 00000000..0a011956
--- /dev/null
+++ b/src/modules/theme/themefunctions.cpp
@@ -0,0 +1,396 @@
+//=============================================================================
+//
+// File : themefunctions.cpp
+// Created on Wed 03 Jan 2007 03:14:07 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2007 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "themefunctions.h"
+
+#include "kvi_packagefile.h"
+#include "kvi_locale.h"
+#include "kvi_msgbox.h"
+#include "kvi_app.h"
+#include "kvi_htmldialog.h"
+#include "kvi_iconmanager.h"
+#include "kvi_miscutils.h"
+#include "kvi_sourcesdate.h"
+#include "kvi_theme.h"
+#include "kvi_frame.h"
+#ifdef COMPILE_USE_QT4
+#define KviTalMimeSourceFactory Q3MimeSourceFactory
+#include <q3mimefactory.h>
+#else
+#define KviTalMimeSourceFactory QMimeSourceFactory
+#endif
+#include <qmime.h>
+
+namespace KviThemeFunctions
+{
+
+ static bool notAValidThemePackage(QString &szError)
+ {
+ KviQString::sprintf(szError,__tr2qs_ctx("The selected file does not seem to be a valid KVIrc theme package","theme"));
+ return false;
+ }
+
+ bool installThemePackage(const QString &szThemePackageFileName,QString &szError,QWidget * pDialogParent)
+ {
+ KviPointerHashTable<QString,QString> * pInfoFields;
+ QString * pValue;
+ bool bInstall;
+ QPixmap pix;
+ QByteArray * pByteArray;
+ KviHtmlDialogData hd;
+
+ const char * check_fields[] = { "Name", "Version", "Author", "Description", "Date", "Application" };
+
+ // check if it is a valid theme file
+ KviPackageReader r;
+ if(!r.readHeader(szThemePackageFileName))
+ {
+ QString szErr = r.lastError();
+ KviQString::sprintf(szError,__tr2qs_ctx("The selected file does not seem to be a valid KVIrc package: %Q","theme"),&szErr);
+ return false;
+ }
+
+ pInfoFields = r.stringInfoFields();
+
+ pValue = pInfoFields->find("PackageType");
+ if(!pValue)return notAValidThemePackage(szError);
+ if(!KviQString::equalCI(*pValue,"ThemePack"))return notAValidThemePackage(szError);
+ pValue = pInfoFields->find("ThemePackVersion");
+ if(!pValue)return notAValidThemePackage(szError);
+ if(!KviQString::equalCI(*pValue,"1"))return notAValidThemePackage(szError);
+
+ // make sure the default fields exist
+ for(int i=0;i<6;i++)
+ {
+ pValue = pInfoFields->find(check_fields[i]);
+ if(!pValue)return notAValidThemePackage(szError);
+ }
+
+ pValue = pInfoFields->find("ThemeCount");
+ if(!pValue)return notAValidThemePackage(szError);
+ bool bOk;
+ int iThemeCount = pValue->toInt(&bOk);
+ if(!bOk)return notAValidThemePackage(szError);
+ if(iThemeCount < 1)return notAValidThemePackage(szError);
+
+ // ok.. it should be really valid at this point
+
+ // load its picture
+ pByteArray = r.binaryInfoFields()->find("Image");
+ if(pByteArray)
+ pix.loadFromData(*pByteArray,0,0);
+
+ if(pix.isNull())
+ {
+ // load the default icon
+ pix = *(g_pIconManager->getBigIcon(KVI_BIGICON_THEME));
+ }
+
+ QString szPackageName;
+ QString szPackageVersion;
+ QString szPackageAuthor;
+ QString szPackageDescription;
+ QString szPackageDate;
+ QString szPackageThemeEngineVersion;
+ QString szPackageApplication;
+
+ QString szAuthor = __tr2qs_ctx("Author","theme");
+ QString szCreatedAt = __tr2qs_ctx("Created at","theme");
+ QString szCreatedOn = __tr2qs_ctx("Created with","theme");
+
+ r.getStringInfoField("Name",szPackageName);
+ r.getStringInfoField("Version",szPackageVersion);
+ r.getStringInfoField("Author",szPackageAuthor);
+ r.getStringInfoField("Description",szPackageDescription);
+ r.getStringInfoField("Application",szPackageApplication);
+ r.getStringInfoField("Date",szPackageDate);
+
+ QString szWarnings;
+ QString szDetails = "<html><body bgcolor=\"#ffffff\">";
+ QString szTmp;
+
+ int iIdx = 0;
+ int iValidThemeCount = iThemeCount;
+
+ while(iIdx < iThemeCount)
+ {
+ bool bValid = true;
+
+ QString szThemeName;
+ QString szThemeVersion;
+ QString szThemeDescription;
+ QString szThemeDate;
+ QString szThemeSubdirectory;
+ QString szThemeAuthor;
+ QString szThemeThemeEngineVersion;
+ QString szThemeApplication;
+
+ KviQString::sprintf(szTmp,"Theme%dName",iIdx);
+ r.getStringInfoField(szTmp,szThemeName);
+ KviQString::sprintf(szTmp,"Theme%dVersion",iIdx);
+ r.getStringInfoField(szTmp,szThemeVersion);
+ KviQString::sprintf(szTmp,"Theme%dApplication",iIdx);
+ r.getStringInfoField(szTmp,szThemeApplication);
+ KviQString::sprintf(szTmp,"Theme%dDescription",iIdx);
+ r.getStringInfoField(szTmp,szThemeDescription);
+ KviQString::sprintf(szTmp,"Theme%dDate",iIdx);
+ r.getStringInfoField(szTmp,szThemeDate);
+ KviQString::sprintf(szTmp,"Theme%dSubdirectory",iIdx);
+ r.getStringInfoField(szTmp,szThemeSubdirectory);
+ KviQString::sprintf(szTmp,"Theme%dAuthor",iIdx);
+ r.getStringInfoField(szTmp,szThemeAuthor);
+ KviQString::sprintf(szTmp,"Theme%dThemeEngineVersion",iIdx);
+ r.getStringInfoField(szTmp,szThemeThemeEngineVersion);
+ KviQString::sprintf(szTmp,"Theme%dScreenshot",iIdx);
+ QPixmap pixScreenshot;
+ pByteArray = r.binaryInfoFields()->find(szTmp);
+ if(pByteArray)
+ pixScreenshot.loadFromData(*pByteArray,0,0);
+
+ if(szThemeName.isEmpty() || szThemeVersion.isEmpty() || szThemeSubdirectory.isEmpty() || szThemeThemeEngineVersion.isEmpty())
+ bValid = false;
+ if(KviMiscUtils::compareVersions(szThemeThemeEngineVersion,KVI_CURRENT_THEME_ENGINE_VERSION) < 0)
+ bValid = false;
+
+ QString szDetailsBuffer;
+
+ getThemeHtmlDescription(
+ szDetailsBuffer,
+ szThemeName,
+ szThemeVersion,
+ szThemeDescription,
+ szThemeSubdirectory,
+ szThemeApplication,
+ szThemeAuthor,
+ szThemeDate,
+ szThemeThemeEngineVersion,
+ pixScreenshot,
+ iIdx
+ );
+
+ if(iIdx > 0)
+ szDetails += "<hr>";
+
+ szDetails += szDetailsBuffer;
+
+ if(!bValid)
+ {
+ szDetails += "<p><center><font color=\"#ff0000\"><b>";
+ szDetails += __tr2qs_ctx("Warning: The theme might be incompatible with this version of KVIrc","theme");
+ szDetails += "</b></font></center></p>";
+ iValidThemeCount--;
+ }
+
+ iIdx++;
+ }
+
+ szDetails += "<br><p><center><a href=\"theme_dialog_main\">";
+ szDetails += __tr2qs_ctx("Go Back to Package Data","theme");
+ szDetails += "</a></center></p>";
+ szDetails += "</body></html>";
+
+ if(iValidThemeCount < iThemeCount)
+ {
+ szWarnings += "<p><center><font color=\"#ff0000\"><b>";
+ szWarnings += __tr2qs_ctx("Warning: Some of the theme contained in this package might be either corrupted or incompatible with this version of KVIrc","theme");
+ szWarnings += "</b></font></center></p>";
+ }
+
+ QString szShowDetails = __tr2qs_ctx("Show Details","theme");
+
+ KviQString::sprintf(hd.szHtmlText,
+ "<html bgcolor=\"#ffffff\">" \
+ "<body bgcolor=\"#ffffff\">" \
+ "<p><center>" \
+ "<h2>%Q %Q</h2>" \
+ "</center></p>" \
+ "<p><center>" \
+ "<img src=\"theme_dialog_pack_image\">" \
+ "</center></p>" \
+ "<p><center>" \
+ "<i>%Q</i>" \
+ "</center></p>" \
+ "<p><center>" \
+ "%Q: <b>%Q</b><br>" \
+ "%Q: <b>%Q</b><br>" \
+ "</center></p>" \
+ "<p><center>" \
+ "<font color=\"#808080\">" \
+ "%Q: %Q<br>" \
+ "</font>" \
+ "</center></p>" \
+ "%Q" \
+ "<br>" \
+ "<p><center>" \
+ "<a href=\"theme_dialog_details\">%Q</a>" \
+ "</center></p>" \
+ "</body>" \
+ "</html>",
+ &szPackageName,
+ &szPackageVersion,
+ &szPackageDescription,
+ &szAuthor,
+ &szPackageAuthor,
+ &szCreatedAt,
+ &szPackageDate,
+ &szCreatedOn,
+ &szPackageApplication,
+ &szWarnings,
+ &szShowDetails
+ );
+
+
+
+ KviTalMimeSourceFactory::defaultFactory()->setPixmap("theme_dialog_pack_image",pix);
+ KviTalMimeSourceFactory::defaultFactory()->setText("theme_dialog_details",szDetails);
+ KviTalMimeSourceFactory::defaultFactory()->setText("theme_dialog_main",hd.szHtmlText);
+
+ QString beginCenter = "<center>";
+ QString endCenter = "</center>";
+
+ hd.szCaption = __tr2qs_ctx("Install Theme Pack - KVIrc","theme");
+ hd.szUpperLabelText = beginCenter + __tr2qs_ctx("You're about to install the following theme package","theme") + endCenter;
+ hd.szLowerLabelText = beginCenter + __tr2qs_ctx("Do you want to proceed with the installation ?","theme") + endCenter;
+ hd.szButton1Text = __tr2qs_ctx("Do Not Install","theme");
+ hd.szButton2Text = __tr2qs_ctx("Yes, Proceed","theme");
+ hd.iDefaultButton = 2;
+ hd.iCancelButton = 1;
+ hd.pixIcon = *(g_pIconManager->getSmallIcon(KVI_SMALLICON_THEME));
+ hd.iMinimumWidth = 350;
+ hd.iMinimumHeight = 420;
+ hd.iFlags = KviHtmlDialogData::ForceMinimumSize;
+
+ bInstall = KviHtmlDialog::display(pDialogParent,&hd) == 2;
+
+ if(bInstall)
+ {
+ QString szUnpackPath;
+ g_pApp->getLocalKvircDirectory(szUnpackPath,KviApp::Themes);
+ if(!r.unpack(szThemePackageFileName,szUnpackPath))
+ {
+ QString szErr2 = r.lastError();
+ KviQString::sprintf(szError,__tr2qs_ctx("Failed to unpack the selected file: %Q","theme"),&szErr2);
+ return true;
+ }
+ }
+
+ return true;
+ }
+
+
+ void getThemeHtmlDescription(
+ QString &szBuffer,
+ const QString &szThemeName,
+ const QString &szThemeVersion,
+ const QString &szThemeDescription,
+ const QString &szThemeSubdirectory,
+ const QString &szThemeApplication,
+ const QString &szThemeAuthor,
+ const QString &szThemeDate,
+ const QString &szThemeThemeEngineVersion,
+ const QPixmap &pixScreenshot,
+ int iUniqueIndexInDocument
+ )
+ {
+ QString szAuthor = __tr2qs_ctx("Author","theme");
+ QString szCreatedAt = __tr2qs_ctx("Created at","theme");
+ QString szCreatedOn = __tr2qs_ctx("Created with","theme");
+ QString szThemeEngineVersion = __tr2qs_ctx("Theme Engine Version","theme");
+ QString szSubdirectory = __tr2qs_ctx("Subdirectory","theme");
+
+ QString szScreenshot;
+ if(!pixScreenshot.isNull())
+ {
+ KviQString::sprintf(szScreenshot,"<p><center><img src=\"theme_shot%d\"></center></p>",iUniqueIndexInDocument);
+ QString szTmp;
+ KviQString::sprintf(szTmp,"theme_shot%d",iUniqueIndexInDocument);
+ KviTalMimeSourceFactory::defaultFactory()->setPixmap(szTmp,pixScreenshot);
+ } else {
+ szScreenshot = "";
+ }
+
+ KviQString::sprintf(
+ szBuffer,
+ "<p><center>" \
+ "<h2>%Q %Q</h2>" \
+ "</center></p>" \
+ "%Q" \
+ "<p><center>" \
+ "<i>%Q</i>" \
+ "</center></p>" \
+ "<p><center>" \
+ "%Q: <b>%Q</b><br>" \
+ "%Q: <b>%Q</b><br>" \
+ "</center></p>" \
+ "<p><center>" \
+ "<font color=\"#808080\">" \
+ "%Q: %Q<br>" \
+ "%Q: %Q<br>" \
+ "%Q: %Q<br>" \
+ "</font>" \
+ "</center></p>",
+ &szThemeName,
+ &szThemeVersion,
+ &szScreenshot,
+ &szThemeDescription,
+ &szAuthor,
+ &szThemeAuthor,
+ &szCreatedAt,
+ &szThemeDate,
+ &szCreatedOn,
+ &szThemeApplication,
+ &szThemeEngineVersion,
+ &szThemeThemeEngineVersion,
+ &szSubdirectory,
+ &szThemeSubdirectory
+ );
+ }
+
+ bool makeKVIrcScreenshot(const QString &szSavePngFilePath,bool bMaximizeFrame)
+ {
+ if(bMaximizeFrame)
+ {
+ if(g_pFrame->isMaximized())
+ bMaximizeFrame = false;
+ }
+
+ if(bMaximizeFrame)
+ g_pFrame->showMaximized();
+
+ QPixmap pix = QPixmap::grabWidget(g_pFrame);
+ bool bResult = true;
+
+ if(pix.isNull())
+ bResult = false;
+ else {
+ if(!pix.save(szSavePngFilePath,"PNG",100))
+ bResult = false;
+ }
+
+ if(bMaximizeFrame)
+ g_pFrame->showNormal();
+ return bResult;
+ }
+};
+
diff --git a/src/modules/theme/themefunctions.h b/src/modules/theme/themefunctions.h
new file mode 100644
index 00000000..124a65f6
--- /dev/null
+++ b/src/modules/theme/themefunctions.h
@@ -0,0 +1,54 @@
+#ifndef _THEMEFUNCTIONS_H_
+#define _THEMEFUNCTIONS_H_
+//=============================================================================
+//
+// File : themefunctions.h
+// Created on Wed 03 Jan 2007 03:14:07 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC Client distribution
+// Copyright (C) 2007 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+
+#include <qwidget.h>
+#include <qpixmap.h>
+
+namespace KviThemeFunctions
+{
+ bool installThemePackage(const QString &szThemePackageFileName,QString &szError,QWidget * pDialogParent = 0);
+ void getThemeHtmlDescription(
+ QString &szBuffer,
+ const QString &szThemeName,
+ const QString &szThemeVersion,
+ const QString &szThemeDescription,
+ const QString &szThemeSubdirectory,
+ const QString &szThemeApplication,
+ const QString &szThemeAuthor,
+ const QString &szThemeDate,
+ const QString &szThemeThemeEngineVersion,
+ const QPixmap &pixScreenshot,
+ int iUniqueIndexInDocument = 0
+ );
+ bool makeKVIrcScreenshot(const QString &szSavePngFilePath,bool bMaximizeFrame = false);
+};
+
+
+
+#endif //!_THEMEFUNCTIONS_H_
diff --git a/src/modules/tip/Makefile.am b/src/modules/tip/Makefile.am
new file mode 100644
index 00000000..2a9fbbcb
--- /dev/null
+++ b/src/modules/tip/Makefile.am
@@ -0,0 +1,30 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkvitip.la
+
+libkvitip_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkvitip_la_SOURCES = libkvitip.cpp
+libkvitip_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+noinst_HEADERS= libkvitip.h
+
+tmpdir = $(picsdir)
+
+tmp_DATA = kvi_tip.png
+
+confdir = $(configmodulesdir)
+
+conf_DATA = libkvitip.kvc libkvitip_it.kvc libkvitip_cs.kvc libkvitip_ru.kvc
+
+EXTRA_DIST = $(tmp_DATA) $(conf_DATA)
+
+%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
+
+libkvitip.cpp: libkvitip.moc
diff --git a/src/modules/tip/kvi_tip.png b/src/modules/tip/kvi_tip.png
new file mode 100644
index 00000000..29312d4a
--- /dev/null
+++ b/src/modules/tip/kvi_tip.png
Binary files differ
diff --git a/src/modules/tip/libkvitip.cpp b/src/modules/tip/libkvitip.cpp
new file mode 100644
index 00000000..ac23d914
--- /dev/null
+++ b/src/modules/tip/libkvitip.cpp
@@ -0,0 +1,309 @@
+//
+// File : libkvitip.cpp
+// Creation date : Thu May 10 2001 13:50:11 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include "libkvitip.h"
+#include "kvi_module.h"
+#include "kvi_styled_controls.h"
+
+#include "kvi_locale.h"
+#include "kvi_app.h"
+
+#include "kvi_iconmanager.h"
+#include "kvi_options.h"
+#include "kvi_fileutils.h"
+
+#include <qpushbutton.h>
+
+#ifdef COMPILE_USE_QT4
+#include <q3simplerichtext.h>
+#include <QDesktopWidget>
+#include <QCloseEvent>
+#define KviTalSimpleRichText Q3SimpleRichText
+#else
+#include <qsimplerichtext.h>
+#define KviTalSimpleRichText QSimpleRichText
+#endif
+
+#include <qfont.h>
+#include <qtextcodec.h>
+#include <qpainter.h>
+
+KviTipWindow * g_pTipWindow = 0;
+
+#define KVI_TIP_WINDOW_HEIGHT 200
+#define KVI_TIP_WINDOW_WIDTH 500
+#define KVI_TIP_WINDOW_BUTTON_WIDTH 80
+#define KVI_TIP_WINDOW_BUTTON_HEIGHT 30
+#define KVI_TIP_WINDOW_BORDER 5
+#define KVI_TIP_WINDOW_DOUBLE_BORDER 10
+#define KVI_TIP_WINDOW_SPACING 2
+
+
+KviTipFrame::KviTipFrame(QWidget * par)
+: QFrame(par)
+{
+ KviStr buffer;
+ g_pApp->findImage(buffer,"kvi_tip.png");
+ m_pTipPixmap = new QPixmap(buffer.ptr());
+#ifdef COMPILE_USE_QT4
+ setBackgroundMode(Qt::NoBackground);
+#else
+ setBackgroundMode(QWidget::NoBackground);
+#endif
+ setFrameStyle(QFrame::Sunken | QFrame::WinPanel);
+}
+
+KviTipFrame::~KviTipFrame()
+{
+ delete m_pTipPixmap;
+}
+
+void KviTipFrame::setText(const QString &text)
+{
+ m_szText = "<center><font color=\"#FFFFFF\">";
+ m_szText += text;
+ m_szText += "</font></center>";
+ update();
+}
+
+void KviTipFrame::drawContents(QPainter *p)
+{
+ p->fillRect(contentsRect(),QColor(0,0,0));
+ p->drawPixmap(5,(height() - m_pTipPixmap->height()) / 2,*m_pTipPixmap);
+
+ QFont f = QFont();
+ f.setStyleHint(QFont::SansSerif);
+ f.setPointSize(12);
+
+ KviTalSimpleRichText doc(m_szText,f);
+ doc.setWidth(width() - 80);
+
+ QRegion reg(0,0,1000,20000);
+
+#if QT_VERSION >= 300
+ doc.draw(p,70,10,reg,colorGroup());
+#else
+ doc.draw(p,70,10,reg,palette());
+#endif
+}
+
+KviTipWindow::KviTipWindow()
+: QWidget(0,"kvirc_tip_window" /*,WStyle_Customize | WStyle_Title | WStyle_DialogBorder | WStyle_StaysOnTop*/ )
+{
+ m_pConfig = 0;
+
+
+ m_pTipFrame = new KviTipFrame(this);
+ m_pTipFrame->setGeometry(
+ KVI_TIP_WINDOW_BORDER,
+ KVI_TIP_WINDOW_BORDER,
+ KVI_TIP_WINDOW_WIDTH - KVI_TIP_WINDOW_DOUBLE_BORDER,
+ KVI_TIP_WINDOW_HEIGHT - (KVI_TIP_WINDOW_DOUBLE_BORDER + KVI_TIP_WINDOW_BUTTON_HEIGHT + KVI_TIP_WINDOW_SPACING));
+
+ QPushButton * pb = new QPushButton(">>",this);
+ pb->setGeometry(
+ KVI_TIP_WINDOW_WIDTH - ((KVI_TIP_WINDOW_BUTTON_WIDTH * 2)+ KVI_TIP_WINDOW_BORDER + KVI_TIP_WINDOW_SPACING),
+ KVI_TIP_WINDOW_HEIGHT - (KVI_TIP_WINDOW_BUTTON_HEIGHT + KVI_TIP_WINDOW_BORDER),
+ KVI_TIP_WINDOW_BUTTON_WIDTH,
+ KVI_TIP_WINDOW_BUTTON_HEIGHT
+ );
+ connect(pb,SIGNAL(clicked()),this,SLOT(nextTip()));
+
+ pb = new QPushButton(__tr2qs("Close"),this);
+ pb->setGeometry(
+ KVI_TIP_WINDOW_WIDTH - (KVI_TIP_WINDOW_BUTTON_WIDTH + KVI_TIP_WINDOW_BORDER),
+ KVI_TIP_WINDOW_HEIGHT - (KVI_TIP_WINDOW_BUTTON_HEIGHT + KVI_TIP_WINDOW_BORDER),
+ KVI_TIP_WINDOW_BUTTON_WIDTH,
+ KVI_TIP_WINDOW_BUTTON_HEIGHT
+ );
+ connect(pb,SIGNAL(clicked()),this,SLOT(close()));
+ pb->setDefault(true);
+
+ m_pShowAtStartupCheck = new KviStyledCheckBox(__tr2qs("Show at startup"),this);
+ m_pShowAtStartupCheck->setChecked(KVI_OPTION_BOOL(KviOption_boolShowTipAtStartup));
+ m_pShowAtStartupCheck->setGeometry(
+ KVI_TIP_WINDOW_BORDER,
+ KVI_TIP_WINDOW_HEIGHT - (KVI_TIP_WINDOW_BUTTON_HEIGHT + KVI_TIP_WINDOW_BORDER),
+ KVI_TIP_WINDOW_WIDTH - ((KVI_TIP_WINDOW_BORDER + KVI_TIP_WINDOW_BUTTON_WIDTH + KVI_TIP_WINDOW_SPACING) * 2),
+ KVI_TIP_WINDOW_BUTTON_HEIGHT
+ );
+
+ setFixedSize(KVI_TIP_WINDOW_WIDTH,KVI_TIP_WINDOW_HEIGHT);
+
+ setIcon(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_IDEA)));
+
+ setCaption(__tr2qs("Did you know..."));
+
+ pb->setFocus();
+
+}
+
+KviTipWindow::~KviTipWindow()
+{
+ KVI_OPTION_BOOL(KviOption_boolShowTipAtStartup) = m_pShowAtStartupCheck->isChecked();
+ if(m_pConfig)closeConfig();
+}
+
+bool KviTipWindow::openConfig(const char * filename,bool bEnsureExists)
+{
+ if(m_pConfig)closeConfig();
+
+ m_szConfigFileName = filename;
+// m_szConfigFileName.cutToLast('/');
+
+ KviStr buffer;
+ g_pApp->getReadOnlyConfigPath(buffer,m_szConfigFileName.ptr(),KviApp::ConfigPlugins,true);
+
+ if(bEnsureExists)
+ {
+ if(!KviFileUtils::fileExists(buffer.ptr()))return false;
+ }
+
+ m_pConfig = new KviConfig(buffer.ptr(),KviConfig::Read);
+
+ return true;
+}
+
+void KviTipWindow::closeConfig()
+{
+ KviStr buffer;
+ g_pApp->getLocalKvircDirectory(buffer,KviApp::ConfigPlugins,m_szConfigFileName.ptr());
+ m_pConfig->setSavePath(buffer.ptr());
+ delete m_pConfig;
+ m_pConfig = 0;
+}
+
+void KviTipWindow::nextTip()
+{
+ if(!m_pConfig)
+ {
+ KviStr szLocale = KviLocale::localeName();
+ KviStr szFile;
+ szFile.sprintf("libkvitip_%s.kvc",szLocale.ptr());
+ if(!openConfig(szFile.ptr(),true))
+ {
+ szLocale.cutFromFirst('.');
+ szLocale.cutFromFirst('_');
+ szLocale.cutFromFirst('@');
+ szFile.sprintf("libkvitip_%s.kvc",szLocale.ptr());
+ if(!openConfig(szFile.ptr(),true))
+ {
+ openConfig("libkvitip.kvc",false);
+ }
+ }
+ }
+
+ unsigned int uNumTips = m_pConfig->readUIntEntry("uNumTips",0);
+ unsigned int uNextTip = m_pConfig->readUIntEntry("uNextTip",0);
+
+
+ KviStr tmp(KviStr::Format,"%u",uNextTip);
+ QString szTip = m_pConfig->readEntry(tmp.ptr(),__tr2qs("<b>Can't find any tip... :(</b>"));
+
+ //debug("REDECODED=%s",szTip.utf8().data());
+
+ uNextTip++;
+ if(uNextTip >= uNumTips)uNextTip = 0;
+ m_pConfig->writeEntry("uNextTip",uNextTip);
+
+ m_pTipFrame->setText(szTip);
+}
+
+void KviTipWindow::showEvent(QShowEvent *e)
+{
+ resize(KVI_TIP_WINDOW_WIDTH,KVI_TIP_WINDOW_HEIGHT);
+ move((g_pApp->desktop()->width() - KVI_TIP_WINDOW_WIDTH) / 2,
+ (g_pApp->desktop()->height() - KVI_TIP_WINDOW_HEIGHT) / 2);
+ QWidget::showEvent(e);
+}
+
+void KviTipWindow::closeEvent(QCloseEvent *e)
+{
+ e->ignore();
+ delete this;
+ g_pTipWindow = 0;
+}
+
+/*
+ @doc: tip.open
+ @type:
+ command
+ @title:
+ tip.open
+ @short:
+ Opens the "did you know..." tip window
+ @syntax:
+ tip.open [tip_file_name:string]
+ @description:
+ Opens the "did you know..." tip window.<br>
+ If <tip_file_name> is specified , that tip is used instead of
+ the default tips provided with kvirc.<br>
+ <tip_file_name> must be a file name with no path and must refer to a
+ standard KVIrc configuration file found in the global or local
+ KVIrc plugin configuration directory ($KVIrcDir/config/modules).<br>
+ Once the window has been opened, the next tip avaiable in the config file is shown.<br>
+ This command works even if the tip window is already opened.<br>
+*/
+
+
+static bool tip_kvs_cmd_open(KviKvsModuleCommandCall * c)
+{
+ QString szTipfilename;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("filename",KVS_PT_STRING,KVS_PF_OPTIONAL,szTipfilename)
+ KVSM_PARAMETERS_END(c)
+ if(!g_pTipWindow)g_pTipWindow = new KviTipWindow();
+ if (!szTipfilename.isEmpty()) g_pTipWindow->openConfig(szTipfilename);
+ g_pTipWindow->nextTip();
+ g_pTipWindow->show();
+ return true;
+}
+
+static bool tip_module_init(KviModule *m)
+{
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"open",tip_kvs_cmd_open);
+ return true;
+}
+
+static bool tip_module_cleanup(KviModule *m)
+{
+ if(g_pTipWindow)g_pTipWindow->close();
+ return true;
+}
+
+static bool tip_module_can_unload(KviModule *m)
+{
+ return (g_pTipWindow == 0);
+}
+
+KVIRC_MODULE(
+ "Tip", // module name
+ "1.0.0", // module version
+ "Copyright (C) 2000 Szymon Stefanek (pragma at kvirc dot net)", // author & (C)
+ "\"Did you know...\" tip",
+ tip_module_init,
+ tip_module_can_unload,
+ 0,
+ tip_module_cleanup
+)
+
+#include "libkvitip.moc"
diff --git a/src/modules/tip/libkvitip.h b/src/modules/tip/libkvitip.h
new file mode 100644
index 00000000..1387f8df
--- /dev/null
+++ b/src/modules/tip/libkvitip.h
@@ -0,0 +1,71 @@
+#ifndef _LIBKVITIP_H_
+#define _LIBKVITIP_H_
+
+//
+// File : kvi_tip.cpp
+// Creation date : Thu May 10 2001 13:49:12 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+
+#include <qwidget.h>
+#include <qframe.h>
+#include <qpixmap.h>
+#include <qcheckbox.h>
+
+#include "kvi_styled_controls.h"
+#include "kvi_string.h"
+#include "kvi_config.h"
+
+class KviTipFrame : public QFrame
+{
+ Q_OBJECT
+public:
+ KviTipFrame(QWidget * par);
+ ~KviTipFrame();
+protected:
+ QString m_szText;
+ QPixmap * m_pTipPixmap;
+protected:
+ virtual void drawContents(QPainter *p);
+public:
+ void setText(const QString &text);
+};
+
+class KviTipWindow : public QWidget
+{
+ Q_OBJECT
+public:
+ KviTipWindow();
+ ~KviTipWindow();
+protected:
+ KviTipFrame * m_pTipFrame;
+ KviStyledCheckBox * m_pShowAtStartupCheck;
+ KviConfig * m_pConfig;
+ KviStr m_szConfigFileName; // no path!
+protected:
+ virtual void showEvent(QShowEvent *e);
+ virtual void closeEvent(QCloseEvent *e);
+public:
+ bool openConfig(const char * filename,bool bEnsureExists = true);
+ void closeConfig();
+public slots:
+ void nextTip();
+};
+
+#endif //_LIBKVITIP_H_
diff --git a/src/modules/tip/libkvitip.kvc b/src/modules/tip/libkvitip.kvc
new file mode 100644
index 00000000..94db1571
--- /dev/null
+++ b/src/modules/tip/libkvitip.kvc
@@ -0,0 +1,28 @@
+[KVIrc]
+uNextTip=0
+uNumTips=25
+TranslatorHint=This-file-MUST-be-encoded-in-UTF8
+0=You can open connections to multiple servers in a single KVIrc window, just select "New IRC Context" from the KVIrc menu.<br>The original style of devoting a KVIrc frame window to each connection is still supported, just select "New Frame Window" from the same menu.
+1=IPv6 is now fully supported, even for DCC transfers.<br><b>/server -i &lt;servername&gt;</b> is the command. :)
+2=KVIrc supports SSL encryption.<br>SSL encrypted IRC connections can be established by using <b>/server -s</b>, and DCC connections by using <b>/dcc.chat -s</b><br>It also works over IPv6.
+3=An <b>IRC context</b> is a set of resources dealing with a single server connection. It has an associated <b>Console</b> window that displays system and server messages.
+4=KVIrc is a highly modular application. Modules are loaded and unloaded transparently to the user (and even to the scripter!). You can also write your own modules that extend the scripting language, or add other features.
+5=The <b>gnutella</b> module has been removed from the KVIrc source tree, and is now shipped as a separate package.
+6=KVIrc supports multiple handler scripts for a single event. This allows multiple scripts to be installed at the same time, avoids handler collisions and helps in adding/removing and activating/deactivating script sections.
+7=KVIrc supports the <b>irc://</b> Uniform Resource Locator (URL). Run the command: <br><b>kvirc irc://irc.yourserver.org:6667/channel</b><br> to connect to that server.<br>The general syntax is:<br><b>irc[6]://&lt;server-name&gt;[:&lt;port&gt;][/[&lt;channel&gt;[?&lt;pass&gt;]]]</b>
+8=The KVIrc executable acts like the "netscape -remote" command, if an instance of KVIrc is already running, the command line parameters are passed to that instance via IPC. You can override this behaviour with the <b>-f</b> switch.
+9=KVIrc can be your browser's handler for <b>irc://</b> URLs. If KVIrc has KDE support, you should be able to run it by simply typing an <b>irc://</b> URL into Konqueror's Location bar.<br>Try <b>irc://irc.freenode.net/kvirc</b> :)
+10=URLs can also be made for IPv6 IRC servers, the following syntax applies in this case:<br><b>irc6://&lt;ipv6-server-name&gt;[:&lt;port&gt;][/[&lt;channel&gt;[?&lt;pass&gt;]]]</b>
+11=You can switch between windows pressing <b>Ctrl+Left/Right</b>. <b>Alt+Left/Right</b> cycles only between windows in the current context.
+12=A quick method for connecting to a server in a new IRC context is <b>/server -n &lt;servername&gt;</b>
+13=KVIrc is portable between Windows and various flavours of Unix machines. If you're a good scripter, your scripts will be portable too!
+14=Want to automatically join a channel on connect?<br>Easy!<br>Just click "Advanced" in the server settings and add the channel in the "Join Channels" tab. For something that works for all servers, try <b>/event(OnIrc,autojoin){ join #yourchannel; }</b>
+15=Do you know what an avatar is? Check out <b>/help avatar</b>
+16=The DCC settings page has a lot of options that can help you solve many common DCC connection problems. People behind firewalls might be able to send data, too. It's just a matter of setting things up. :)
+17=There is a separate OpenNap compatibility module (<b>opennap</b>) that enables OpenNap-based chatting with KVIrc.
+18=KVIrc supports many 8-bit character encodings. You can "speak" KOI8-R based Russian on one channel and Japanese on another over the same connection (with appropriate fonts). We strongly encourage you to use <b>Unicode</b> (UTF-8), which supports almost every language in the world.
+19=To avoid excessive DCC transfers, it is recommended that you make your avatars available on the Web. You can also use any existing image on the Web as an avatar.<br><b>/avatar #yourchan http://funnyhost.com/funny/funny.png</b> will work!
+20=KVIrc has a built-in HTTP client, and you can download files from the Web by using the <b>/http.get</b> command.
+21=Don't like the window tree taskbar mode? You can opt for a traditional taskbar (similar to mIRC) in the taskbar settings page under the preferences.
+22=You can copy text from the text window to the clipboard by simply selecting it with the mouse. If you also keep Shift pressed then the color codes will be copied as well.
+23=This is the last tip. You can add your own tips - Check out <b>/help tip.open</b>. Feel free to submit more tips (in any language) to <b>trisk-kvirc(at)quasarnet.org</b>.
diff --git a/src/modules/tip/libkvitip_cs.kvc b/src/modules/tip/libkvitip_cs.kvc
new file mode 100644
index 00000000..ab169fe7
--- /dev/null
+++ b/src/modules/tip/libkvitip_cs.kvc
@@ -0,0 +1,29 @@
+[KVIrc]
+uNextTip=0
+uNumTips=25
+Encoding=UTF8
+0=Můžete otevřít více spojení s více servery v jednom KVIrc okně, jen vyberte "Nový IRC Kontext" v KVIrc menu.<br>Původní styl vnořeného okna KVIrcu pro každé spojení je stále podporován, stačí vybrat "Nové okno s rámcem" ze stejné nabídky.
+1=IPv6 je nyní plně podporováno, dokonce pro DCC přenosy.<br><b>/server -i &lt;název_serveru&gt;</b> je příkaz. :)
+2=KVIrc podporuje Šifrování SSL.<br>IRC spojení šifrovaná pomocí SSL mohou být navázána příkazem <b>/server -s</b>, a DCC spojení použitím <b>/dcc.chat -s</b><br>Funguje také na IPv6.
+3=<b>IRC context</b> je soubor zdrojů patřících k jednomu spojení se serverem. Má přiřazené okno <b>Console</b> které ukazuje systémové zprávy a zprávy serveru.
+4=KVIrc je vysoce modulární aplikace. Moduly jsou načítány a vypínány transparentně pro uživatele (i pro skriptora!). Můžete také napsat vlastní moduly pro rozšíření skriptovacího jazyka, nebo rozšíření funkcí KVIrc.
+5=Modul <b>gnutella</b> byl odstraněn ze zdrojového stromu KVIrc a je dodáván jako samostatný balíček.
+6=KVIrc Podporuje několikanásobné zpracování skriptů pro jednu událost. To dovoluje mít nainstalováno více skriptů současně, aniž by spolu kolidovaly a usnadnuje přidávání/odebírání a aktivaci/deaktivaci částí skriptu.
+7=KVIrc podporuje <b>irc://</b> Uniform Resource Locator (URL). Spusťte příkaz: <br><b>kvirc irc://irc.vášserver.org:6667/kanál</b><br> pro připojení k tomuto serveru.<br>Obecná syntaxe je:<br><b>irc[6]://&lt;jméno-serveru&gt;[:&lt;port&gt;][/[&lt;kanál&gt;[?&lt;heslo&gt;]]]</b>
+8=Spuštěný soubor KVIrcu pracuje jako příkaz "netscape -remote", pokud již KVIrc běží, parametry příkazového řádku jsou předány běžícímu KVIrcu přes IPC. Můžete obejít toto chování použitím parametru <b>-f</b>.
+9=KVIrc může zpracovávat URL <b>irc://</b> z Vašeho prohlížeče. Pokud má KVIrc podporu KDE, můžete jo spustit pouhým zadáním <b>irc://</b> URL do adresního řádku Konqueroru.<br>Zkuste <b>irc://irc.freenode.net/kvirc</b> :)
+10=URL mohou být také použita pro IPv6 IRC servery, v tom připadě je syntaxe:<br><b>irc6://&lt;název-ipv6-serveru&gt;[:&lt;port&gt;][/[&lt;kanál&gt;[?&lt;heslo&gt;]]]</b>
+11=Můžete přepínat mezi okny stiskem <b>Ctrl+Vlevo/Vpravo</b>. <b>Alt+Vlevo/Vpravo</b> přepíná pouze mezi okny v aktuálním kontextu.
+12=Rychlý způsob pro připojení k serveru v novém IRC kontextu je <b>/server -n &lt;název-serveru&gt;</b>
+13=KVIrc je přenositelný mezi Windows a různými Unixovými stroji. Pokud jste dobrý skriptor, Vaše skripty budou přenositelné také!
+14=Chcete automaticky vstoupit do kanálu při připojení?<br>Snadné!<br>Stačí kliknout na "Pokročilé" v nastavení serveru a přidat kanál do "Příchod do kanálů". Pro něco co funguje na všech serverech, zkuste <b>/event(OnIrc,autojoin){ join #váškanál; }</b>
+15=Víte co je Avatar? Mrkněte na <b>/help avatar</b>
+16=Nastavení DCC má mnoho možností, které Vám pomohou vyřešit mnoho běžných problémů s DCC spojením. Lidé za firewallem mohou také posílat data. Je to jen otázka správného nastavení. :)
+17=K dispozici je samostatný OpenNap modul (<b>opennap</b>), který umožnuje chat založený na OpenNap s KVIrc.
+18=KVIrc podporuje mnoho 8-bitových znakových sad. Můžete "mluvit" KOI8-R Ruštinou na jednom kanále a Japonsky na jiném při stejném spojení (s příslušnými fonty). Doporučujeme použít <b>Unicode</b> (UTF-8), který podporuje téměř každý světový jazyk.
+19=Abyste předešli mnohým DCC přenosům, doporučuje se dát si Avatar online na Web. Můžete také použít libovolný existující obrázek na webu jako Avatar.<br><b>/avatar #váškanál http://funnyhost.com/funny/funny.png</b> funguje!
+20=KVIrc má vestavěný HTTP klient, takže můžete stahovat soubory z Webu pomocí příkazu <b>/http.get</b>.
+21=Nelíbí se vám taskbar ve stromu? Můžete si nastavit tradiční taskbar (podobný mIRC) v Nastavení taskbaru.
+22=Můžete kopírovat text z okna do schránky pouhým označením myší. Pokud podržíte Shift, budou zkopírovány i barevné kódy.
+23=Můžete zkopírovat text kanálu nebo query jen jeho pouhým vybráním. Pokud podržíte Shift, tak se zkopírují i barvy.
+24=Toto je poslední tip. Můžete přidat vlastní tipy - Mrkněte na <b>/help tip.open</b>. Klidně pošlete více tipů (v libovolném jazyce) na <b>trisk-kvirc(at)quasarnet.org</b>.
diff --git a/src/modules/tip/libkvitip_it.kvc b/src/modules/tip/libkvitip_it.kvc
new file mode 100644
index 00000000..edabad68
--- /dev/null
+++ b/src/modules/tip/libkvitip_it.kvc
@@ -0,0 +1,28 @@
+[KVIrc]
+uNextTip=0
+uNumTips=25
+TranslatorHint=This-file-MUST-be-encoded-in-UTF8
+0=Puoi aprire connessioni verso server multipli: scegli "Nuovo IRC Context" dal menu KVIrc.<br>Il vecchio metodo di una finestra per connessione ovviamente ancora supportato: scegli "Nuova finestra" dallo stesso menù
+1=IPv6 ora è supportato completamente, anche per le connessioni DCC.<br>Il comando è <b>/server -i &lt;nomeserver&gt;</b> :)
+2=KVIrc supporta crittazione SSL.<br>Le connessioni IRC crittate con SSL possono essere stabilite usando <b>/server -s</b>, e connessioni DCC usando <b>/dcc.chat -s</b><br>Funziona anche usando IPv6.
+3=Un <b>contesto IRC</b> è un set di risorse che dialogano con una singola connessione server. Ha associato una finestra <b>Console</b> che mostra i messaggi di sistema e del server.
+4=KVIrc è un'applicazione altamente modulare. I moduli sono caricati e scaricati trasparentemente all'utente (ed anche allo scripter!). Puoi anche scrivere i tuoi moduli personali che estendono il linguaggio di scripting o aggiungono altre funzionalità.
+5=Il modulo <b>gnutella</b> è stato rimosso dai sorgenti di KVIrc ed è ora distribuito in un pacchetto separato.
+6=KVIrc supporta diversi gestori per lo stesso evento. Questo permette di avere diversi script installati allo stesso momento, evitare collisioni tra gestori ed aiutare ad aggiungere/rimuovere e attivare/disattivare gli script.
+7=KVIrc supporta gli URL (Uniform Resource Locator) <b>irc://</b>. Lancia il comando:<br><b>kvirc irc://irc.tuoserver.org:6667/canale</b><br> per connettere a quel server.<br>La sintassi generale è:<br><b>irc[6]://&lt;nome-server&gt;[:&lt;porta&gt;][/[&lt;canale&gt;[?&lt;password&gt;]]]</b>
+8=L'eseguibile KVIrc agisce come il comando "netscape -remote", se c'è già un'istanza di KVIrc avviata, i parametri a linea di comando saranno passato a quell'istanza usando IPC. Puoi sovrascrivere questo comportamento con l'opzione <b>-f</b>.
+9=KVIrc può essere il tuo gestore del browser per gli URL <b>irc://</b>. Se KVIrc ha il supporto KDE, dovresti poterlo lanciare semplicemente scrivendo un URL <b>irc://</b> nella barra degli URL di Konqueror.<br>Prova <b>irc://irc.freenode.net/kvirc</b> :)
+10=Gli URL possono anche essere fatti da server IRC IPv6, la sintassi seguente funzionerà in questo caso:<br><b>irc6://&lt;nome-server-ipv6&gt;[:&lt;porta&gt;][/[&lt;canale&gt;[?&lt;password&gt;]]]</b>
+11=Puoi navigare tra le finestre premendo <b>Ctrl+Sinistra/Destra</b>. <b>Alt+Sinistra/Destra</b> cambia solo finestra nel contesto corrente.
+12=Un metodo veloce per connettere a un server in un nuovo contesto IRC è <b>/server -n &lt;nomeserver&gt;</b>
+13=KVIrc è portabile tra diverse macchine UNIX (compreso Mac) e Windows. Se sei un bravo scripter, anche i tuoi script saranno portabili!
+14=Vuoi entrare in un canale automaticamente alla connessione?<br>Facile!<br>Clicca su "Avanzate" nella configurazione del server e aggiungi il canale nella scheda "Entra nei Canali". Per qualcosa che funzioni per ogni server, prova <b>/event(OnIrc,autojoin){ join #tuocanale; }</b>
+15=Sai cos'è un avatar? Prova <b>/help avatar</b>
+16=La pagina di configurazione delle DCC ha un sacco di opzioni che possono aiutarti a risolvere i problemi di connessione più comuni. Le persone dietro un firewall potrebbero anche volere inviare dei dati. E' giusto una questione di configurazione :)
+17=C'è un modulo separato per la compatibilità con OpenNAP (<b>opennap</b>) che abiita le chat basate su OpenNAP con KVIrc.
+18=KVIrc supporta diverse codifiche a 8-bit. Puoi "parlare" russo KOI8-R su un canale e giapponese in un altro con la stessa connessione (e dei font appropriati). Noi incoraggiamo fortemente l'uso di <b>Unicode</b> (UTF-8), che supporta quasi tutte le lingue del mondo.
+19=Per evitare trasferimenti DCC eccessivi, è raccomandato che metti il tuo avatar sul Web. Puoi anche usare una qualsiasi immagine sul Web come avatar.<br><b>/avatar #tuocanale http://sito.com/immagini/immagine.png</b> funzionerà!
+20=KVIrc ha un client HTTP integrato, e puoi scaricare file dal Web usando il comando <b>/http.get</b>.
+21=Non ti piacciono le finestre disposte ad albero? Puoi optare per una visualizzazione tradizionale (simile a mIRC) nella pagina di configurazione delle finestre nelle preferenze.
+22=Puoi copiare il testo dalla finestra di chat agli appunti semplicemente selezionandolo col mouse. Se tieni anche premuto lo Shift verranno copiati anche i codici colore.
+23=Questo è l'ultimo suggerimento. Puoi aggiungere i tuoi suggerimenti personali - Prova <b>/help tip.open</b>. Sentiti libero di mandare nuovi suggerimenti (in qualsiasi lingua) a <b>trisk-kvirc(at)quasarnet.org</b>.
diff --git a/src/modules/tip/libkvitip_ru.kvc b/src/modules/tip/libkvitip_ru.kvc
new file mode 100644
index 00000000..a9f982f6
--- /dev/null
+++ b/src/modules/tip/libkvitip_ru.kvc
@@ -0,0 +1,29 @@
+[KVIrc]
+uNextTip=0
+uNumTips=25
+TranslatorHint=This-file-MUST-be-encoded-in-UTF8
+0=Вы можете скопировать текст из окна в буфер обмена просто выделив его мышью. Если удерживать нажатым Shift, то коды цветов также будут скопированы.
+1=Если вы хотите использовать озвучивание событий в KVIrc, откройте редактор событий, добавьте на нужные события обработчики и впишите в них <b>snd.play /путь/к/звуковому/файлу</b>. также для некоторых событий вы можете просто установить звук, указав звуковой файл в диалоге опций, на странице Общие настройки->Звуки.
+2=IPv6 теперь полностью поддерживается, даже для DCC передач.<br><b>/server -i &lt;servername&gt;</b> команда. :)
+3=KVIrc поддерживает SSL шифрование.<br>SSL шифрованные IRC соединения можно установить, используя <b>/server -s</b>, и DCC соединения используя <b>/dcc.chat -s</b><br>Это также работает через IPv6.
+4=<b>IRC контекст</b> это ресурсы, которые относятся только к одному соединению с сервером. У него есть связанное окно <b>Консоль</b>, которое отображает сообщения системы и сервера.
+5=KVIrc является полностью модульным приложением. Модули загружаются и выгружаются прозрачно для пользователя (даже в скриптах!). Вы можете также писать свои собственные модули, которые расширяют скриптовый язык или добавляют новые возможности.
+6=KVIrc поддерживает пространства имен (namespaces), которые позволяют скриптерам не забититься о том, что имена созданных ими команд будут конфликтовать со скриптами других авторов.
+7=KVIrc поддерживает множественные обработчики для каждого события. Это позволяет использовать множество сценариев установленных в одно и то же время, исключает конфликты обработчиков, и помогает удалять/добавлять и включать/выключать секции сценариев.
+8=KVIrc поддерживает <b>irc://</b> Uniform Resource Locator (URL). Выполните команду: <br><b>kvirc irc://irc.yourserver.org:6667/channel</b><br> для подключения к серверу. Общий синтаксис:<br><b>irc[6]://&lt;имя.сервера&gt;[:&lt;порт&gt;][/[&lt;канал&gt;[?&lt;пароль&gt;]]]</b>
+9=Запуск KVIrc действует подобно команде <br>"netscape -remote", если KVIrc уже запущен параметры командной строки передаются в запущеное приложение через IPC. Вы можете отменить это используя ключ <b>-f</b>.
+10=KVIrc может быть вашим обработчиком протокола <b>irc://</b> в КДЕ. Если KVIrc собран с поддержкой KDE, вы можете запустить его просто набрав <b>irc://</b> URL в строке адреса Конкверора.<br>Например <b>irc://irc.freenode.net/kvirc</b> :)
+11=URL-ы могут быть оформлены и для IPv6 IRC серверов с помощью следующего синтаксиса:<br><b>irc6://&lt;ipv6-сервер&gt;[:&lt;порт&gt;][/[&lt;канал&gt;[?&lt;пароль&gt;]]]</b>
+12=Вы можете переключаться между окнами с помощью <b>Ctrl+Left/Right</b>. <b>Alt+Left/Right</b> - по циклу только между окнами текущего контекста.
+13=Быстрый способ для подключения к серверу в новом контексте IRC <b>/server -n &lt;имясервера&gt;</b>
+14=KVIrc является мультиплатформеннм приложением - существуют сборки под Unix, Windows и Mac. Если вы будете правильно писать сценарии, то они тоже будут портируемы!
+15=Хотите автоматически входить на канал при коннекте? Нет ничего проще!<br>Кликните на кнопке "Дополнительно" в настройках сервера и добавьте канал к списку на вкладке "Входить на каналы"
+16=Вы не знаете как пользоваться аватаром? Наберите <b>/help avatar</b>
+17=Секция настроек DCC имеет множество опций, которые помогут вам решить разные проблемы, возникающие при использовании DCC соединений. Даже если вы находитесь за фаерволом, то тоже сможете передавать данные. Всё дело в правильных настройках. :)
+18=KVIrc поддерживает множество 8-битных кодировок. Вы можете на одном канале "разговаривать" по русски в KOI8-R, а на другом по японски (если у вас имеются соответствующие шрифты ). Мы очень рекомендуем вам использовать <b>Unicode</b> (UTF-8), который поддерживает практически все языки мира.
+19=Чтобы избежать дополнительного траффика DCC, мы рекомендуем использовать аватары, находящиеся в интернете.<br><b>/avatar #yourchan http://funnyhost.com/funny/funny.png</b> будет работать!
+20=KVIrc имеет встроенный клиент HTTP, и вы можете загрузить файлы из интернета используя команду <b>/http.get</b>.
+21=Вам не нравится окно с деревом панели задач? Вы можете выбрать традиционную панель задач (такую же как в mIRC) в секции настроек панели задач.
+22=Вы можете открыть соединения для многих серверов в одном окне KVIrc, просто выберите "Новый IRC контекст" в меню KVIrc.
+23=KVIrc имеет встроенный гибкий механизм идентификации на NickServ. Если вы заинтересованы в его использовании, но не можете настроить самостоятельно, советуем прочитать инструкции на сайте http://www.kvirc.ru в разделе статьи.
+24=Это последний совет. Вы можете добавлять свои собственные советы - наберите <b>/help tip.open</b>. Вы можете отослать свои советы (на любом языке) по адресу <b>alexey@kvirc.ru</b>.
diff --git a/src/modules/tmphighlight/Makefile.am b/src/modules/tmphighlight/Makefile.am
new file mode 100644
index 00000000..6e5a02ac
--- /dev/null
+++ b/src/modules/tmphighlight/Makefile.am
@@ -0,0 +1,22 @@
+###############################################################################
+# KVirc IRC client Makestr - 10.03.2002 Juanjo lvarez <juanjux@yahoo.es>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+-I/usr/include/kde/arts\
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+#ARTS_LD_FLAGS = -DPIC -fPIC
+#ARTS_C_FLAGS = -L/usr/lib -ldl -lartsc -lpthread
+pluglib_LTLIBRARIES = libkvitmphighlight.la
+
+libkvitmphighlight_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkvitmphighlight_la_SOURCES = libkvitmphighlight.cpp
+libkvitmphighlight_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+
+#noinst_HEADERS=
+
+%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
diff --git a/src/modules/tmphighlight/libkvitmphighlight.cpp b/src/modules/tmphighlight/libkvitmphighlight.cpp
new file mode 100644
index 00000000..17f4ce17
--- /dev/null
+++ b/src/modules/tmphighlight/libkvitmphighlight.cpp
@@ -0,0 +1,174 @@
+// File : libkvitmphighlight.cpp
+// Creation date : Oct 10 01:06:09 CEST 2002 by Juanjo �varez
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2002 Juanjo �varez (juanjux@yahoo.es)
+// Copyright (C) 2002 Szymon Stefanek (kvirc@tin.it)
+//
+// 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 opinion) 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.
+//
+
+
+#include "kvi_module.h"
+
+#include "kvi_locale.h"
+#include "kvi_channel.h"
+
+//-------------------------------------------------
+/*
+ @doc: tmphighlight.add
+ @type:
+ command
+ @title:
+ tmphighlight.add
+ @short:
+ Adds a user to the channel temporary highlight list
+ @syntax:
+ tmphighlight.add <nick:string>
+ @description:
+ This command adds a user to the channel temporary highlight list, so that user messages[br]
+ will be highlighted until you close the channel. This is useful when you are in a very crowded [br]
+ channel with lots of conversations running in parallel and you want to follow one of them.[br]
+ @seealso:
+ [fnc]$tmphighlight.remove[/fnc]
+ [fnc]$tmphighlight.ishighlighted[/fnc]
+*/
+//-------------------------------------------
+// tmphighlight.add
+//-------------------------------------------
+static bool tmphighlight_kvs_cmd_add(KviKvsModuleCommandCall * c)
+{
+
+ QString szNick;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("nick",KVS_PT_NONEMPTYSTRING,0,szNick)
+ KVSM_PARAMETERS_END(c)
+ if( ( !c->window()->console()) || c->window()->console()->isNotConnected() )return c->context()->errorNoIrcContext();
+ if(!c->window()->type() == KVI_WINDOW_TYPE_CHANNEL)
+ {
+ c->warning(__tr2qs("Current window is not a channel"));
+ return false;
+ }
+
+ ((KviChannel *)c->window())->addHighlightedUser(szNick);
+
+ return true;
+}
+//-------------------------------------------------
+/*
+ @doc: tmphighlight.remove
+ @type:
+ command
+ @title:
+ tmphighlight.remove
+ @short:
+ Remove a user from the channel temporary highlight list
+ @syntax:
+ tmphighlight.remove <nick:string>
+ @description:
+ This command remove a user from the channel temporary highlight list, so that user messages[br]
+ stop being highlighted.
+ @seealso:
+ [fnc]$tmphighlight.add[/fnc]
+ [fnc]$tmphighlight.ishighlighted[/fnc]
+*/
+//-------------------------------------------
+// tmphighlight.remove
+//-------------------------------------------
+
+static bool tmphighlight_kvs_cmd_remove(KviKvsModuleCommandCall * c)
+{
+ QString szNick;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("nick",KVS_PT_NONEMPTYSTRING,0,szNick)
+ KVSM_PARAMETERS_END(c)
+ if( ( !c->window()->console()) || c->window()->console()->isNotConnected() )return c->context()->errorNoIrcContext();
+ if(!c->window()->type() == KVI_WINDOW_TYPE_CHANNEL)
+ {
+ c->warning(__tr2qs("Current window is not a channel"));
+ return false;
+ }
+
+ ((KviChannel *)c->window())->removeHighlightedUser(szNick);
+ return true;
+}
+//-------------------------------------------------
+/*
+ @doc: tmphighlight.ishighlighted
+ @type:
+ function
+ @title:
+ $tmphighlight.ishighlighted
+ @short:
+ Returns 1 if the user is highlighted on this channel, 0 otherwise
+ @syntax:
+ <boolean> $tmphighlight.ishighlighted <nick:string>
+ @description:
+ This command returns 1 if the user is highlighted on this channel and on this session of 0 otherwise.
+ @seealso:
+ [fnc]$tmphighlight.add[/fnc]
+ [fnc]$tmphighlight.remove[/fnc]
+
+*/
+//-------------------------------------------
+// tmphighlight.ishighlighted
+//-------------------------------------------
+
+static bool tmphighlight_kvs_fnc_ishighlighted(KviKvsModuleFunctionCall * c)
+{
+ QString szNick;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("nick",KVS_PT_NONEMPTYSTRING,0,szNick)
+ KVSM_PARAMETERS_END(c)
+ if( ( !c->window()->console()) || c->window()->console()->isNotConnected() )return c->context()->errorNoIrcContext();
+ if(!c->window()->type() == KVI_WINDOW_TYPE_CHANNEL)
+ {
+ c->warning(__tr2qs("Current window is not a channel"));
+ return false;
+ }
+ c->returnValue()->setBoolean(((KviChannel *)c->window())->isHighlightedUser(szNick));
+ return true;
+}
+
+//-------------------------------------------------
+static bool tmphighlight_module_init(KviModule * m)
+{
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"add",tmphighlight_kvs_cmd_add);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"remove",tmphighlight_kvs_cmd_remove);
+ KVSM_REGISTER_FUNCTION(m,"isHighVisible",tmphighlight_kvs_fnc_ishighlighted);
+ KVSM_REGISTER_FUNCTION(m,"isHighLighted",tmphighlight_kvs_fnc_ishighlighted);
+ return true;
+}
+//-------------------------------------------------
+static bool tmphighlight_module_cleanup(KviModule *m)
+{
+ return true;
+}
+//-------------------------------------------------
+static bool tmphighlight_module_can_unload(KviModule *m)
+{
+ return true;
+}
+//-------------------------------------------------
+KVIRC_MODULE(
+ "TmpHighlight", // module name
+ "1.0.0", // module version
+ " (C) 2002 Juanjo Alvarez (juanjux@yahoo.es)", // author & (C)
+ "Temporal Highlightining of channel users",
+ tmphighlight_module_init,
+ tmphighlight_module_can_unload,
+ 0,
+ tmphighlight_module_cleanup
+)
diff --git a/src/modules/toolbar/Makefile.am b/src/modules/toolbar/Makefile.am
new file mode 100644
index 00000000..e009e306
--- /dev/null
+++ b/src/modules/toolbar/Makefile.am
@@ -0,0 +1,18 @@
+###############################################################################
+# KVirc IRC client Maketoolbar - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkvitoolbar.la
+
+libkvitoolbar_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkvitoolbar_la_SOURCES = libkvitoolbar.cpp
+libkvitoolbar_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+# noinst_HEADERS=
+
+%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
diff --git a/src/modules/toolbar/libkvitoolbar.cpp b/src/modules/toolbar/libkvitoolbar.cpp
new file mode 100644
index 00000000..a72949ca
--- /dev/null
+++ b/src/modules/toolbar/libkvitoolbar.cpp
@@ -0,0 +1,602 @@
+//=============================================================================//
+//
+// File : libkvitoolbar.cpp
+// Creation date : Wed 6 Nov 22:51:59 2002 GMT by Szymon Stefanek
+//
+// This toolbar is part of the KVirc irc client distribution
+// Copyright (C) 2002-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_module.h"
+
+#include "kvi_locale.h"
+
+#include "kvi_window.h"
+#include "kvi_app.h"
+#include "kvi_error.h"
+#include "kvi_cmdformatter.h"
+#include "kvi_customtoolbar.h"
+#include "kvi_customtoolbardescriptor.h"
+#include "kvi_customtoolbarmanager.h"
+#include "kvi_actionmanager.h"
+#include "kvi_kvs_useraction.h"
+
+/*
+ @doc: toolbar.create
+ @type:
+ command
+ @title:
+ toolbar.create
+ @keyterms:
+ Creating toolbars
+ @short:
+ Creates a toolbar
+ @syntax:
+ toolbar.create [-p] <id:string> <label:string> [icon_id:string]
+ @switches:
+ !sw: -p | --preserve
+ Preserve the existing toolbar, if any
+ @description:
+ Creates a toolbar with the specified <id> and with the visible <label> (caption).[br]
+ If a toolbar with the same <id> already exists then this command is equivalent to the
+ sequence of [cmd]toolbar.hide[/cmd], [cmd]toolbar.clear[/cmd] and [cmd]toolbar.setlabel[/cmd] unless the -p
+ switch is specified that causes the [cmd]toolbar.clear[/cmd] call to be skipped (contents preserved).[br]
+ This command doesn't show the toolbar (you need to use [cmd]toolbar.show[/cmd]).[br]
+ Toolbars are saved and preserved across KVIrc sessions thus you don't need to create them
+ on application startup: you only create them once.
+ If [icon_id] is specified then it is interpreted as an [doc:image_id]image identifier[/doc]
+ for the small (16x16) icon that will be put in the toolbar listing popup menu.
+ The toolbar will exist until [cmd]toolbar.destroy[/cmd] is called (you might want to add
+ an "uninstall" feature to your script).[br]
+ @seealso:
+ [fnc]$toolbar.exists[/fnc],
+ [cmd]toolbar.remove[/cmd],
+ [cmd]toolbar.show[/cmd],
+ [cmd]toolbar.destroy[/cmd]
+*/
+
+static bool toolbar_kvs_cmd_create(KviKvsModuleCommandCall * c)
+{
+ QString szId,szLabel,szIconId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("id",KVS_PT_NONEMPTYSTRING,0,szId)
+ KVSM_PARAMETER("label",KVS_PT_STRING,KVS_PF_OPTIONAL,szLabel)
+ KVSM_PARAMETER("icon_id",KVS_PT_NONEMPTYSTRING,KVS_PF_OPTIONAL,szIconId)
+ KVSM_PARAMETERS_END(c)
+
+/* if(!c->getParameterCode(1,szLabel))
+ {
+ c->error(__tr2qs("Internal error: call a head-shrinker"));
+ return false;
+ }
+*/
+ if(szLabel.isEmpty())szLabel = "$tr(Unnamed)";
+
+ KviCustomToolBarDescriptor * d = KviCustomToolBarManager::instance()->find(szId);
+ if(d)
+ {
+ if(!c->switches()->find('p',"preserve"))d->clear();
+ d->rename(szLabel);
+ } else {
+ d = KviCustomToolBarManager::instance()->create(szId,szLabel);
+ }
+
+ if(!szIconId.isEmpty())
+ d->setIconId(szIconId);
+
+ return true;
+}
+
+/*
+ @doc: toolbar.clear
+ @type:
+ command
+ @title:
+ toolbar.clear
+ @short:
+ Clears a toolbar
+ @syntax:
+ toolbar.clear [-q] <id:string>
+ @switches:
+ !sw: -q | --quiet
+ Run quietly
+ @description:
+ Clears the contents of the toolbar specified by <id>. If the
+ toolbar does not exist then a warning is printed unless the -q switch is used.[br]
+ @seealso:
+ [fnc]$toolbar.exists[/fnc],
+ [cmd]toolbar.remove[/cmd],
+ [cmd]toolbar.show[/cmd],
+ [cmd]toolbar.destroy[/cmd]
+*/
+
+static bool toolbar_kvs_cmd_clear(KviKvsModuleCommandCall * c)
+{
+ QString szId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("id",KVS_PT_NONEMPTYSTRING,0,szId)
+ KVSM_PARAMETERS_END(c)
+
+ KviCustomToolBarDescriptor * d = KviCustomToolBarManager::instance()->find(szId);
+ if(d)d->clear();
+ else {
+ if(!c->switches()->find('q',"quiet"))
+ c->warning(__tr2qs("The specified toolbar doesn't exist"));
+ }
+
+ return true;
+}
+
+
+/*
+ @doc: toolbar.destroy
+ @type:
+ command
+ @title:
+ toolbar.destroy
+ @keyterms:
+ Destroying a toolbar
+ @short:
+ Destroys a toolbar
+ @syntax:
+ toolbar.destroy [-q] <id:string>
+ @switches:
+ !sw: -q | --quiet
+ Run quietly
+ @description:
+ Destroys the toolbar with the specified <id>.[br]
+ The toolbar definition is definitively destroyed with all the items contained.[br]
+ If the -q switch is specified then this command runs in quiet mode and
+ does not warn if the toolbar was not existing.
+ @seealso:
+ [fnc]$toolbar.exists[/fnc],
+ [cmd]toolbar.create[/cmd]
+*/
+
+
+static bool toolbar_kvs_cmd_destroy(KviKvsModuleCommandCall * c)
+{
+ QString szId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("id",KVS_PT_NONEMPTYSTRING,0,szId)
+ KVSM_PARAMETERS_END(c)
+
+ if(!KviCustomToolBarManager::instance()->destroyDescriptor(szId))
+ {
+ if(!c->switches()->find('q',"quiet"))
+ c->warning(__tr2qs("The specified toolbar doesn't exist"));
+ }
+
+ return true;
+}
+
+
+/*
+ @doc: toolbar.show
+ @type:
+ command
+ @title:
+ toolbar.show
+ @short:
+ Shows a toolbar
+ @syntax:
+ toolbar.show [-q] <id:string>
+ @switches:
+ !sw: -q | --quiet
+ Run quietly
+ @description:
+ Shows the toolbar with the specified <id>.[br]
+ If -q is specified the command runs in quiet mode and does not complain if the
+ specified toolbar doesn't exist.[br]
+ Please note that you don't need to show the toolbar at application startup: KVIrc will
+ take care of this for you (if the user chooses to keep the toolbar visible).[br]
+ You should execute this command only if you create the toolbar after KVIrc has been
+ started.[br]
+ @seealso:
+ [fnc]$toolbar.exists[/fnc],
+ [cmd]toolbar.create[/cmd]
+*/
+
+static bool toolbar_kvs_cmd_show(KviKvsModuleCommandCall * c)
+{
+ QString szId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("id",KVS_PT_NONEMPTYSTRING,0,szId)
+ KVSM_PARAMETERS_END(c)
+
+ KviCustomToolBarDescriptor * d = KviCustomToolBarManager::instance()->find(szId);
+
+ if(!d)
+ {
+ if(!c->switches()->find('q',"quiet"))
+ c->warning(__tr2qs("The specified toolbar doesn't exist"));
+ return true;
+ }
+
+ if(!d->toolBar())
+ d->createToolBar();
+
+ return true;
+}
+
+/*
+ @doc: toolbar.hide
+ @type:
+ command
+ @title:
+ toolbar.hide
+ @short:
+ Hides a toolbar
+ @syntax:
+ toolbar.hide [-q] <id:string>
+ @switches:
+ !sw: -q | --quiet
+ Run quietly
+ @description:
+ Hides the toolbar with the specified <id>.[br]
+ If -q is specified the command runs in quiet mode and does not complain if the
+ specified toolbar doesn't exist.[br]
+ Please note that this command doesn't destroy the toolbar definition: the toolbar
+ can be shown again by using [cmd]toolbar.show[/cmd].[br]
+ If you want to completely remove the toolbar definition use [cmd]toolbar.destroy[/cmd].[br]
+ @seealso:
+ [fnc]$toolbar.exists[/fnc],
+ [cmd]toolbar.create[/cmd],
+ [cmd]toolbar.destroy[/cmd]
+*/
+
+
+static bool toolbar_kvs_cmd_hide(KviKvsModuleCommandCall * c)
+{
+ QString szId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("id",KVS_PT_NONEMPTYSTRING,0,szId)
+ KVSM_PARAMETERS_END(c)
+
+ KviCustomToolBarDescriptor * d = KviCustomToolBarManager::instance()->find(szId);
+
+ if(!d)
+ {
+ if(!c->switches()->find('q',"quiet"))
+ c->warning(__tr2qs("The specified toolbar doesn't exist"));
+ return true;
+ }
+
+ if(d->toolBar()) KviCustomToolBarManager::instance()->destroyDescriptor(d->id());
+
+ return true;
+}
+
+/*
+ @doc: toolbar.exists
+ @type:
+ function
+ @title:
+ $toolbar.exists
+ @short:
+ Checks if a toolbar exists
+ @syntax:
+ <boolean> $toolbar.exists(<id:string>)
+ @description:
+ Returns 1 if the toolbar with the specified <id> has been defined.[br]
+ Note that this doesn't mean that the toolbar is visible!
+ @seealso:
+ [cmd]toolbar.create[/cmd]
+*/
+
+
+static bool toolbar_kvs_fnc_exists(KviKvsModuleFunctionCall * c)
+{
+ QString szId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("id",KVS_PT_NONEMPTYSTRING,0,szId)
+ KVSM_PARAMETERS_END(c)
+
+ c->returnValue()->setBoolean(KviCustomToolBarManager::instance()->find(szId) ? true : false);
+ return true;
+}
+
+/*
+ @doc: toolbar.isVisible
+ @type:
+ function
+ @title:
+ $toolbar.isVisible
+ @short:
+ Checks if a toolbar is visible
+ @syntax:
+ <boolean> $toolbar.isVisible(<id:string>)
+ @description:
+ Returns 1 if the toolbar with the specified <id> is actually visible and 0 otherwise.[br]
+ If the toolbar is not defined at all this function still returns 0.[br]
+ @seealso:
+ [cmd]toolbar.show[/cmd]
+*/
+
+static bool toolbar_kvs_fnc_isVisible(KviKvsModuleFunctionCall * c)
+{
+ QString szId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("id",KVS_PT_NONEMPTYSTRING,0,szId)
+ KVSM_PARAMETERS_END(c)
+ KviCustomToolBarDescriptor * d = KviCustomToolBarManager::instance()->find(szId);
+ c->returnValue()->setBoolean(d ? (d->toolBar() ? true : false) : false);
+ return true;
+}
+
+/*
+ @doc: toolbar.list
+ @type:
+ function
+ @title:
+ $toolbar.list
+ @short:
+ Returns a list of defined toolbars
+ @syntax:
+ <array> $toolbar.list()
+ @description:
+ Returns a list of defined toolbar identifiers.[br]
+ You can use this function to loop thru all the toolbar definitions.[br]
+ @seealso:
+*/
+
+static bool toolbar_kvs_fnc_list(KviKvsModuleFunctionCall * c)
+{
+ KviKvsArray * a = new KviKvsArray();
+
+ KviPointerHashTableIterator<QString,KviCustomToolBarDescriptor> it(*(KviCustomToolBarManager::instance()->descriptors()));
+
+ kvs_uint_t id = 0;
+
+ while(KviCustomToolBarDescriptor * d = it.current())
+ {
+ a->set(id,new KviKvsVariant(d->id()));
+ id++;
+ ++it;
+ }
+
+ c->returnValue()->setArray(a);
+ return true;
+}
+
+
+
+/*
+ @doc: toolbar.remove
+ @type:
+ command
+ @title:
+ toolbar.remove
+ @keyterms:
+ Removing toolbar items
+ @short:
+ Removes a toolbar item
+ @syntax:
+ toolbar.remove [-q] [-i] <toolbarid:string> <action:variant>
+ @switches:
+ !sw: -q | --quiet
+ Run quietly
+ !sw: -i | --index
+ Treat <action> as the zero-based index of the action to be removed
+ instead of the action name.
+ @description:
+ Removes the specified <action> from the toolbar with the specified <toolbarid>.[br]
+ If no such item exists in the specified toolbar this command does nothing.[br]
+ If the <toolbar> parameter doesn't identify an existing toolbar then
+ a warning is printed unless the -q switch is used.[br]
+ If the -i switch is specified the <action> is interpreted as zero based
+ index of the action to be removed (instead of the action name).[br]
+ Please note that this is an expensive operation if the toolbar is visible (basically
+ the toolbar needs to be cleared and filled back again). It is a good idea to hide
+ the toolbar before removing items.[br]
+ @seealso:
+*/
+
+static bool toolbar_kvs_cmd_removeitem(KviKvsModuleCommandCall * c)
+{
+ QString szId;
+ KviKvsVariant * pvAction;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("id",KVS_PT_NONEMPTYSTRING,0,szId)
+ KVSM_PARAMETER("action",KVS_PT_VARIANT,0,pvAction)
+ KVSM_PARAMETERS_END(c)
+
+ KviCustomToolBarDescriptor * d = KviCustomToolBarManager::instance()->find(szId);
+
+ if(!pvAction)
+ {
+ if(!c->switches()->find('q',"quiet"))
+ c->error(__tr2qs("No action name/index specified")); // syntax error
+ return false;
+ }
+
+ if(!d)
+ {
+ if(!c->switches()->find('q',"quiet"))
+ c->warning(__tr2qs("The specified toolbar doesn't exist"));
+ return true;
+ }
+
+ if(c->switches()->find('i',"index"))
+ {
+ kvs_int_t iAction;
+ if(!pvAction->asInteger(iAction))
+ {
+ if(!c->switches()->find('q',"quiet"))
+ c->warning(__tr2qs("The action parameter didn't evaluate to an index"));
+ } else {
+ if(!d->removeAction(iAction))
+ {
+ if(!c->switches()->find('q',"quiet"))
+ c->warning(__tr2qs("The toolbar does not contain the specified item"));
+ }
+ }
+ } else {
+ QString szAction;
+ pvAction->asString(szAction);
+ if(!d->removeAction(szAction))
+ {
+ if(!c->switches()->find('q',"quiet"))
+ c->warning(__tr2qs("The toolbar does not contain the specified item"));
+ }
+ }
+
+ return true;
+}
+
+/*
+ @doc: toolbar.additem
+ @type:
+ command
+ @title:
+ toolbar.additem
+ @keyterms:
+ Adding toolbar items
+ @short:
+ Adds a new item to a toolbar
+ @syntax:
+ toolbar.additem [-q] <toolbarid:string> <action:string>
+ @switches:
+ !sw: -q | --quiet
+ Run quietly
+ @description:
+ Adds the specified <action> from the toolbar with the specified <toolbarid>.[br]
+ If no such action exists this command does nothing (beside printing a warning unless -q is used).[br]
+ If the <toolbar> parameter doesn't identify an existing toolbar then
+ a warning is printed unless the -q switch is used.[br]
+ @examples:
+ [example]
+ toolbar.create test $tr("My Toolbar")
+ toolbar.additem test connect
+ toolbar.additem test separator
+ toolbar.additem test optionsdialog
+ toolbar.show test
+ [/example]
+ @seealso:
+*/
+
+static bool toolbar_kvs_cmd_additem(KviKvsModuleCommandCall * c)
+{
+ QString szId;
+ QString szAction;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("id",KVS_PT_NONEMPTYSTRING,0,szId)
+ KVSM_PARAMETER("action",KVS_PT_NONEMPTYSTRING,0,szAction)
+ KVSM_PARAMETERS_END(c)
+
+ KviCustomToolBarDescriptor * d = KviCustomToolBarManager::instance()->find(szId);
+
+ if(!d)
+ {
+ if(!c->switches()->find('q',"quiet"))
+ c->warning(__tr2qs("The specified toolbar doesn't exist"));
+ return true;
+ }
+
+ if(!d->addAction(szAction))
+ {
+ if(!c->switches()->find('q',"quiet"))c->warning(__tr2qs("The action \"%Q\" doesn't exist"),&szAction);
+ }
+
+ return true;
+}
+
+
+/*
+ @doc: toolbar.items
+ @type:
+ function
+ @title:
+ $toolbar.items
+ @short:
+ Returns the list of items in a specified toolbar
+ @syntax:
+ <array> $toolbar.items(<toolbarid:string>)
+ @description:
+ Returns the array of items in the specified toolbar.
+ If the toolbar doesn't exist then an empty list is returned.
+ @seealso:
+*/
+
+static bool toolbar_kvs_fnc_items(KviKvsModuleFunctionCall * c)
+{
+ QString szId;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("id",KVS_PT_NONEMPTYSTRING,0,szId)
+ KVSM_PARAMETERS_END(c)
+
+ KviCustomToolBarDescriptor * d = KviCustomToolBarManager::instance()->find(szId);
+
+ if(!d)
+ {
+ c->warning(__tr2qs("The specified toolbar doesn't exist"));
+ return true;
+ }
+
+ KviKvsArray * a = new KviKvsArray();
+
+ KviPointerHashTableIterator<QString,KviCustomToolBarDescriptor> it(*(KviCustomToolBarManager::instance()->descriptors()));
+
+ kvs_uint_t id = 0;
+
+ for(QString * s = d->actions()->first();s;s = d->actions()->next())
+ {
+ a->set(id,new KviKvsVariant(*s));
+ id++;
+ ++it;
+ }
+
+ c->returnValue()->setArray(a);
+ return true;
+}
+
+
+
+static bool toolbar_module_init(KviModule * m)
+{
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"create",toolbar_kvs_cmd_create)
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"clear",toolbar_kvs_cmd_clear)
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"destroy",toolbar_kvs_cmd_destroy)
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"additem",toolbar_kvs_cmd_additem)
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"remove",toolbar_kvs_cmd_removeitem)
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"show",toolbar_kvs_cmd_show)
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"hide",toolbar_kvs_cmd_hide)
+
+ KVSM_REGISTER_FUNCTION(m,"exists",toolbar_kvs_fnc_exists)
+ KVSM_REGISTER_FUNCTION(m,"isVisible",toolbar_kvs_fnc_isVisible)
+ KVSM_REGISTER_FUNCTION(m,"list",toolbar_kvs_fnc_list)
+ KVSM_REGISTER_FUNCTION(m,"items",toolbar_kvs_fnc_items)
+
+ return true;
+}
+
+static bool toolbar_module_cleanup(KviModule *m)
+{
+ return true;
+}
+
+KVIRC_MODULE(
+ "toolbar", // module name
+ "1.0.0", // module version
+ "Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot net)", // author & (C)
+ "Interface to the scriptable toolbars",
+ toolbar_module_init,
+ 0,
+ 0,
+ toolbar_module_cleanup
+)
diff --git a/src/modules/toolbareditor/Makefile.am b/src/modules/toolbareditor/Makefile.am
new file mode 100644
index 00000000..a578e10c
--- /dev/null
+++ b/src/modules/toolbareditor/Makefile.am
@@ -0,0 +1,20 @@
+###############################################################################
+# KVirc IRC client Maketoolbareditor - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+
+pluglib_LTLIBRARIES = libkvitoolbareditor.la
+
+libkvitoolbareditor_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkvitoolbareditor_la_SOURCES = libkvitoolbareditor.cpp toolbareditor.cpp
+nodist_libkvitoolbareditor_la_SOURCES = moc_toolbareditor.cpp
+
+noinst_HEADERS = toolbareditor.h
+libkvitoolbareditor_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+moc_toolbareditor.cpp: toolbareditor.h
+ $(SS_QT_MOC) $< -o $@
diff --git a/src/modules/toolbareditor/libkvitoolbareditor.cpp b/src/modules/toolbareditor/libkvitoolbareditor.cpp
new file mode 100644
index 00000000..b4f9e258
--- /dev/null
+++ b/src/modules/toolbareditor/libkvitoolbareditor.cpp
@@ -0,0 +1,96 @@
+//=============================================================================
+//
+// File : libkvitoolbareditor.cpp
+// Creation date : Sun 10 Nov 2002 23:25:59 2002 GMT by Szymon Stefanek
+//
+// This toolbar is part of the KVirc irc client distribution
+// Copyright (C) 2002-2004 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "toolbareditor.h"
+#include "kvi_module.h"
+
+#include "kvi_locale.h"
+
+#include "kvi_frame.h"
+#include "kvi_actionmanager.h"
+#include "kvi_config.h"
+#include "kvi_app.h"
+
+QRect g_rectToolBarEditorDialogGeometry(0,0,0,0);
+
+/*
+ @doc: toolbareditor.open
+ @type:
+ command
+ @title:
+ toolbareditor.open
+ @short:
+ Shows the script toolbar editor
+ @syntax:
+ toolbareditor.open
+ @description:
+ Opens the script toolbar editor dialog.
+*/
+
+
+static bool toolbareditor_kvs_cmd_open(KviKvsModuleCommandCall * c)
+{
+ KviCustomizeToolBarsDialog::display();
+ return true;
+}
+
+static bool toolbareditor_module_init(KviModule * m)
+{
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"open",toolbareditor_kvs_cmd_open);
+ QString szBuf;
+ m->getDefaultConfigFileName(szBuf);
+ KviConfig cfg(szBuf,KviConfig::Read);
+ g_rectToolBarEditorDialogGeometry = cfg.readRectEntry("EditorGeometry",QRect(10,10,390,440));
+
+
+ return true;
+}
+
+static bool toolbareditor_module_can_unload(KviModule * m)
+{
+ return (!KviCustomizeToolBarsDialog::instance());
+}
+
+static bool toolbareditor_module_cleanup(KviModule *m)
+{
+ KviCustomizeToolBarsDialog::cleanup();
+
+ QString szBuf;
+ m->getDefaultConfigFileName(szBuf);
+ KviConfig cfg(szBuf,KviConfig::Write);
+ cfg.writeEntry("EditorGeometry",g_rectToolBarEditorDialogGeometry);
+
+ return true;
+}
+
+KVIRC_MODULE(
+ "ToolbarEditor", // module name
+ "1.0.0", // module version
+ "Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot net)", // author & (C)
+ "Editor for the scriptable toolbars",
+ toolbareditor_module_init,
+ toolbareditor_module_can_unload,
+ 0,
+ toolbareditor_module_cleanup
+)
diff --git a/src/modules/toolbareditor/toolbareditor.cpp b/src/modules/toolbareditor/toolbareditor.cpp
new file mode 100644
index 00000000..5b00f47a
--- /dev/null
+++ b/src/modules/toolbareditor/toolbareditor.cpp
@@ -0,0 +1,537 @@
+//=============================================================================//
+// File : toolbareditor.cpp
+// Created on Wed 01 Dec 2004 14:42:20 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "toolbareditor.h"
+#include "kvi_actiondrawer.h"
+#include "kvi_locale.h"
+#include "kvi_frame.h"
+#include "kvi_iconmanager.h"
+#include "kvi_actionmanager.h"
+#include "kvi_customtoolbar.h"
+#include "kvi_customtoolbarmanager.h"
+#include "kvi_customtoolbardescriptor.h"
+#include "kvi_imagedialog.h"
+#include "kvi_fileutils.h"
+#include "kvi_filedialog.h"
+#include "kvi_kvs_useraction.h"
+#include "kvi_draganddrop.h"
+
+#include <qpushbutton.h>
+#include <qlayout.h>
+#include <qapplication.h>
+#include <qtooltip.h>
+
+#include <qlineedit.h>
+#include <qlabel.h>
+#include <qmessagebox.h>
+#include <qframe.h>
+#include <qdir.h>
+#include <qtimer.h>
+#include <qevent.h>
+
+KviCustomizeToolBarsDialog * KviCustomizeToolBarsDialog::m_pInstance = 0;
+extern QRect g_rectToolBarEditorDialogGeometry;
+
+
+
+KviTrashcanLabel::KviTrashcanLabel(QWidget * p)
+: QLabel(p)
+{
+ setPixmap(*(g_pIconManager->getBigIcon("kvi_bigicon_trashcan.png")));
+ QToolTip::add(this,__tr2qs("Drop here the icons from the toolbars to remove them"));
+ setFrameStyle(QFrame::Sunken | QFrame::WinPanel);
+ setAcceptDrops(true);
+ setAlignment(Qt::AlignCenter);
+ setMinimumSize(40,40);
+ m_uFlashCount = 0;
+ m_pFlashTimer = 0;
+ m_clrOriginal = paletteBackgroundColor();
+ connect(KviActionManager::instance(),SIGNAL(removeActionsHintRequest()),this,SLOT(flash()));
+}
+
+KviTrashcanLabel::~KviTrashcanLabel()
+{
+ if(m_pFlashTimer)
+ {
+ m_pFlashTimer->stop();
+ delete m_pFlashTimer;
+ }
+}
+
+void KviTrashcanLabel::flash()
+{
+ m_uFlashCount = 0;
+ if(m_pFlashTimer)return;
+ m_pFlashTimer = new QTimer();
+ connect(m_pFlashTimer,SIGNAL(timeout()),this,SLOT(heartbeat()));
+ m_pFlashTimer->start(200);
+}
+
+void KviTrashcanLabel::heartbeat()
+{
+ m_uFlashCount++;
+ if(m_uFlashCount % 2)
+ setPaletteBackgroundColor(QColor(0,0,0));
+ else
+ setPaletteBackgroundColor(m_clrOriginal);
+ update();
+ if(m_uFlashCount == 8)
+ {
+ m_pFlashTimer->stop();
+ delete m_pFlashTimer;
+ m_pFlashTimer = 0;
+ }
+}
+
+void KviTrashcanLabel::dropEvent(QDropEvent * e)
+{
+ if(KviTextDrag::canDecode(e))
+ e->accept();
+}
+
+void KviTrashcanLabel::dragEnterEvent(QDragEnterEvent * e)
+{
+ QString s;
+ if(KviTextDrag::decode(e,s))
+ e->accept();
+}
+
+
+
+KviCustomToolBarPropertiesDialog::KviCustomToolBarPropertiesDialog(QWidget * p,const QString &szText,const QString &szId,const QString &szLabel,const QString &szIconId)
+: QDialog(p)
+{
+ m_szId = szId;
+ m_szOriginalId = szId;
+ m_szLabel = szLabel;
+
+ setCaption(__tr2qs("ToolBar Properties"));
+ setIcon(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TOOLBAR)));
+
+ QGridLayout * g = new QGridLayout(this,5,6,5,3);
+
+ QLabel * l = new QLabel(szText,this);
+ g->addMultiCellWidget(l,0,0,0,5);
+
+ l = new QLabel(__tr2qs("Label") + ":",this);
+ g->addWidget(l,1,0);
+
+ m_pLabelEdit = new QLineEdit(this);
+ g->addMultiCellWidget(m_pLabelEdit,1,1,1,5);
+ m_pLabelEdit->setText(szLabel);
+ connect(m_pLabelEdit,SIGNAL(textChanged(const QString &)),this,SLOT(labelTextChanged(const QString &)));
+
+ l = new QLabel(__tr2qs("Icon") + ":",this);
+ g->addWidget(l,2,0);
+
+ m_pIconEdit = new QLineEdit(this);
+ m_pIconEdit->setReadOnly(true);
+ g->addMultiCellWidget(m_pIconEdit,2,2,1,4);
+
+ m_pIconButton = new QPushButton(this);
+ g->addMultiCellWidget(m_pIconButton,2,2,5,5);
+ connect(m_pIconButton,SIGNAL(clicked()),this,SLOT(iconButtonClicked()));
+
+ iconSelected(szIconId);
+
+ m_pAdvanced = new QWidget(this);
+ QGridLayout * ag = new QGridLayout(m_pAdvanced,1,2,0,3);
+
+ l = new QLabel(__tr2qs("Id") + ":",m_pAdvanced);
+ l->setMinimumWidth(100);
+ ag->addWidget(l,0,0);
+
+ m_pIdEdit = new QLineEdit(m_pAdvanced);
+ ag->addWidget(m_pIdEdit,0,1);
+ ag->setRowStretch(0,1);
+
+ m_pIdEdit->setText(szId);
+
+ g->addMultiCellWidget(m_pAdvanced,3,3,0,5);
+ m_pAdvanced->hide();
+
+ m_pLabelEdit->setFocus();
+
+ QPushButton * pb = new QPushButton(__tr2qs("OK"),this);
+ connect(pb,SIGNAL(clicked()),this,SLOT(okClicked()));
+ pb->setMinimumWidth(80);
+ g->addMultiCellWidget(pb,4,4,4,5);
+
+ pb = new QPushButton(__tr2qs("Cancel"),this);
+ connect(pb,SIGNAL(clicked()),this,SLOT(reject()));
+ pb->setMinimumWidth(80);
+ g->addWidget(pb,4,3);
+
+ m_pAdvancedButton = new QPushButton(__tr2qs("Advanced..."),this);
+ connect(m_pAdvancedButton,SIGNAL(clicked()),this,SLOT(advancedClicked()));
+ m_pAdvancedButton->setMinimumWidth(100);
+ g->addMultiCellWidget(m_pAdvancedButton,4,4,0,1);
+
+ g->setRowStretch(0,1);
+ g->setColStretch(2,1);
+
+
+}
+
+KviCustomToolBarPropertiesDialog::~KviCustomToolBarPropertiesDialog()
+{
+}
+
+void KviCustomToolBarPropertiesDialog::iconSelected(const QString &szIconId)
+{
+ QPixmap * p = g_pIconManager->getImage(szIconId.utf8().data());
+ if(p)
+ {
+ m_pIconButton->setPixmap(*p);
+ m_szIconId = szIconId;
+ m_pIconEdit->setText(szIconId);
+ } else {
+ m_pIconButton->setText("...");
+ m_szIconId = "";
+ m_pIconEdit->setText("");
+ }
+}
+
+void KviCustomToolBarPropertiesDialog::iconButtonClicked()
+{
+ KviImageDialog * dlg = new KviImageDialog(this,__tr2qs("Please choose the icon for the ToolBar"));
+ if(dlg->exec() != QDialog::Accepted)
+ {
+ delete dlg;
+ return;
+ }
+ QString s = dlg->selectedImage();
+ delete dlg;
+ iconSelected(s);
+}
+
+
+void KviCustomToolBarPropertiesDialog::labelTextChanged(const QString &s)
+{
+ if(m_szOriginalId.isEmpty())
+ {
+ QString szId = KviCustomToolBarManager::instance()->idForNewToolBar(s);
+ m_pIdEdit->setText(szId);
+ }
+}
+
+
+void KviCustomToolBarPropertiesDialog::okClicked()
+{
+ if(m_szLabel.isEmpty())
+ {
+ QMessageBox::information(this,__tr2qs("Invalid ToolBar Label"),__tr2qs("The ToolBar Label can't be empty!"),__tr2qs("OK"));
+ return;
+ }
+
+ if(m_szId.isEmpty())
+ {
+ m_szId = KviCustomToolBarManager::instance()->idForNewToolBar(m_szLabel);
+ }
+
+ if(KviCustomToolBarManager::instance()->find(m_szId))
+ {
+ if(m_szId != m_szOriginalId)
+ {
+ if(QMessageBox::information(this,__tr2qs("Duplicate ToolBar Id"),
+ __tr2qs("The specified ToolBar Id already exists.<br>" \
+ "Would you like KVIrc to assign it automatically (so it doesn't "
+ "collide with any other toolbar) or you prefer to do it manually ?"),
+ __tr2qs("Manually"),__tr2qs("Automatically")) == 0)return;
+ m_szId = KviCustomToolBarManager::instance()->idForNewToolBar(m_szLabel);
+ }
+ }
+
+ m_szId = m_pIdEdit->text();
+ m_szLabel = m_pLabelEdit->text();
+ accept();
+}
+
+void KviCustomToolBarPropertiesDialog::advancedClicked()
+{
+ if(m_pAdvanced->isVisible())
+ {
+ m_pAdvanced->hide();
+ m_pAdvancedButton->setText(__tr2qs("Advanced..."));
+ } else {
+ m_pAdvanced->show();
+ m_pAdvancedButton->setText(__tr2qs("Hide Advanced"));
+ }
+
+}
+
+
+KviCustomizeToolBarsDialog::KviCustomizeToolBarsDialog(QWidget * p)
+: QDialog(p,"" /*,WType_TopLevel | WStyle_Customize | WStyle_Title | WStyle_StaysOnTop | WStyle_DialogBorder*/)
+{
+ setCaption(__tr2qs("Customize Toolbars"));
+ setIcon(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TOOLBAR)));
+
+ m_pInstance = this;
+
+ QGridLayout * g = new QGridLayout(this,8,2,4,5);
+ m_pDrawer = new KviActionDrawer(this);
+ g->addMultiCellWidget(m_pDrawer,0,6,0,0);
+
+ QPushButton * b = new QPushButton(__tr2qs("New ToolBar"),this);
+ connect(b,SIGNAL(clicked()),this,SLOT(newToolBar()));
+ g->addWidget(b,0,1);
+
+ m_pDeleteToolBarButton = new QPushButton(__tr2qs("Delete ToolBar"),this);
+ connect(m_pDeleteToolBarButton,SIGNAL(clicked()),this,SLOT(deleteToolBar()));
+ g->addWidget(m_pDeleteToolBarButton,1,1);
+
+ m_pRenameToolBarButton = new QPushButton(__tr2qs("Edit ToolBar"),this);
+ connect(m_pRenameToolBarButton,SIGNAL(clicked()),this,SLOT(renameToolBar()));
+ g->addWidget(m_pRenameToolBarButton,2,1);
+
+ QFrame * f = new QFrame(this);
+ f->setFrameStyle(QFrame::HLine | QFrame::Sunken);
+ g->addWidget(f,3,1);
+
+ m_pExportToolBarButton = new QPushButton(__tr2qs("Export ToolBar"),this);
+ connect(m_pExportToolBarButton,SIGNAL(clicked()),this,SLOT(exportToolBar()));
+ g->addWidget(m_pExportToolBarButton,4,1);
+
+ KviTrashcanLabel * t = new KviTrashcanLabel(this);
+ g->addWidget(t,6,1);
+
+ b = new QPushButton(__tr2qs("Close"),this);
+ connect(b,SIGNAL(clicked()),this,SLOT(closeClicked()));
+ g->addWidget(b,7,1);
+
+ g->setRowStretch(5,1);
+ g->setColStretch(0,1);
+
+ m_pDrawer->fill();
+
+ connect(KviActionManager::instance(),SIGNAL(currentToolBarChanged()),this,SLOT(currentToolBarChanged()));
+ KviActionManager::instance()->customizeToolBarsDialogCreated();
+
+ currentToolBarChanged();
+
+ if(g_rectToolBarEditorDialogGeometry.y() < 5)
+ {
+ g_rectToolBarEditorDialogGeometry.setY(5);
+ }
+ //setGeometry(KVI_OPTION_RECT(KviOption_rectRegisteredUsersDialogGeometry));
+ resize(g_rectToolBarEditorDialogGeometry.width(),
+ g_rectToolBarEditorDialogGeometry.height());
+ move(g_rectToolBarEditorDialogGeometry.x(),
+ g_rectToolBarEditorDialogGeometry.y());
+}
+
+KviCustomizeToolBarsDialog::~KviCustomizeToolBarsDialog()
+{
+ g_rectToolBarEditorDialogGeometry = QRect(pos().x(),pos().y(),size().width(),size().height());
+
+ KviActionManager::instance()->customizeToolBarsDialogDestroyed();
+ m_pInstance = 0;
+}
+
+void KviCustomizeToolBarsDialog::currentToolBarChanged()
+{
+ m_pDeleteToolBarButton->setEnabled(KviActionManager::instance()->currentToolBar());
+ m_pRenameToolBarButton->setEnabled(KviActionManager::instance()->currentToolBar());
+}
+
+void KviCustomizeToolBarsDialog::showEvent(QShowEvent * e)
+{
+// repaintContents();
+// QRect r = parentWidget() ? parentWidget()->rect() : QApplication::desktop()->rect();
+// int x = (r.width() - width()) / 2;
+// int y = (r.height() - height()) / 2;
+// move(x,y);
+}
+
+
+void KviCustomizeToolBarsDialog::deleteToolBar()
+{
+ KviCustomToolBar * t = KviActionManager::currentToolBar();
+ if(!t)return;
+ if(QMessageBox::question(this,
+ __tr2qs("Confirm ToolBar Deletion"),
+ __tr2qs("Do you really want to delete toolbar \"%1\" ?").arg(t->label()),
+ __tr2qs("No"),
+ __tr2qs("Yes")) == 0)return;
+ KviCustomToolBarManager::instance()->destroyDescriptor(t->descriptor()->id());
+}
+
+void KviCustomizeToolBarsDialog::exportToolBar()
+{
+ KviCustomToolBar * t = KviActionManager::currentToolBar();
+ if(!t)return;
+
+ QString szName = QDir::homeDirPath();
+ if(!szName.endsWith(QString(KVI_PATH_SEPARATOR)))szName += KVI_PATH_SEPARATOR;
+ szName += t->descriptor()->id();
+ szName += ".kvs";
+
+ QString szFile;
+
+ if(!KviFileDialog::askForSaveFileName(szFile,__tr2qs("Choose a Filename - KVIrc"),szName,"*.kvs",true,true,true))return;
+
+ QString szCode;
+
+ int ret = QMessageBox::question(this,
+ __tr2qs("ToolBar Export"),
+ __tr2qs("Do you want the associated actions to be exported with the toolbar ?"),
+ __tr2qs("Yes"),
+ __tr2qs("No"),
+ __tr2qs("Cancel"));
+
+ if(ret == 2)return;
+
+ bool bExportActions = ret == 0;
+
+ if(bExportActions)
+ {
+ KviPointerList<QString> * a = t->descriptor()->actions();
+ if(a)
+ {
+ for(QString * s = a->first();s;s = a->next())
+ {
+ KviAction * act = KviActionManager::instance()->getAction(*s);
+ if(act)
+ {
+ if(act->isKviUserActionNeverOverrideThis())
+ {
+ ((KviKvsUserAction *)act)->exportToKvs(szCode);
+ szCode += "\n\n";
+ }
+ }
+ }
+ }
+ }
+
+ szCode += "toolbar.create ";
+ szCode += t->descriptor()->id();
+ szCode += " ";
+ szCode += t->descriptor()->labelCode();
+ szCode += " ";
+ szCode += t->descriptor()->iconId();
+ szCode += "\n";
+
+ KviPointerList<QString> * aa = t->descriptor()->actions();
+ if(aa)
+ {
+ for(QString * ss = aa->first();ss;ss = aa->next())
+ {
+ szCode += "toolbar.additem ";
+ szCode += t->descriptor()->id();
+ szCode += " ";
+ szCode += *ss;
+ szCode += "\n";
+ }
+ }
+
+ szCode += "toolbar.show ";
+ szCode += t->descriptor()->id();
+ szCode += "\n";
+
+ if(!KviFileUtils::writeFile(szFile,szCode))
+ {
+ QMessageBox::warning(this,__tr2qs("Write Failed - KVIrc"),__tr2qs("Unable to write to the toolbar file."),__tr2qs("OK"));
+ }
+
+}
+
+void KviCustomizeToolBarsDialog::renameToolBar()
+{
+ KviCustomToolBar * t = KviActionManager::currentToolBar();
+ if(!t)return;
+
+ KviCustomToolBarPropertiesDialog * dlg = new KviCustomToolBarPropertiesDialog(this,
+ __tr2qs("Please specify the properties for the toolbar \"%1\"").arg(t->label()),
+ t->descriptor()->id(),
+ t->descriptor()->labelCode(),
+ t->descriptor()->iconId());
+
+ dlg->show();
+ if(dlg->exec() != QDialog::Accepted)
+ {
+ delete dlg;
+ return;
+ }
+
+ QString id = dlg->id();
+ QString label = dlg->label();
+ QString icon = dlg->iconId();
+ delete dlg;
+
+ if((id == t->descriptor()->id()) && (label == t->descriptor()->labelCode()) && (icon == t->descriptor()->iconId()))return;
+
+ KviCustomToolBarManager::instance()->renameDescriptor(t->descriptor()->id(),id,label);
+ t->descriptor()->setIconId(icon);
+}
+
+void KviCustomizeToolBarsDialog::newToolBar()
+{
+ KviCustomToolBarPropertiesDialog * dlg = new KviCustomToolBarPropertiesDialog(this,
+ __tr2qs("Please specify the properties for the new toolbar"),
+ KviCustomToolBarManager::instance()->idForNewToolBar(__tr2qs("My ToolBar")),
+ __tr2qs("My ToolBar"));
+
+ dlg->show();
+ if(dlg->exec() != QDialog::Accepted)
+ {
+ delete dlg;
+ return;
+ }
+
+ QString id = dlg->id();
+ QString label = dlg->label();
+ QString icon = dlg->iconId();
+ delete dlg;
+
+ KviCustomToolBarDescriptor * d = KviCustomToolBarManager::instance()->create(id,label);
+ d->setIconId(icon);
+ KviCustomToolBar * t = d->createToolBar();
+ KviActionManager::instance()->setCurrentToolBar(t);
+}
+
+void KviCustomizeToolBarsDialog::closeClicked()
+{
+ delete this;
+}
+
+void KviCustomizeToolBarsDialog::cleanup()
+{
+ if(!m_pInstance)return;
+ delete m_pInstance;
+ m_pInstance = 0;
+}
+
+void KviCustomizeToolBarsDialog::display()
+{
+ if(m_pInstance)return;
+ m_pInstance = new KviCustomizeToolBarsDialog(g_pFrame);
+ m_pInstance->show();
+}
+
+void KviCustomizeToolBarsDialog::closeEvent(QCloseEvent * e)
+{
+ e->ignore();
+ delete this;
+}
+
diff --git a/src/modules/toolbareditor/toolbareditor.h b/src/modules/toolbareditor/toolbareditor.h
new file mode 100644
index 00000000..2c44178c
--- /dev/null
+++ b/src/modules/toolbareditor/toolbareditor.h
@@ -0,0 +1,119 @@
+#ifndef _TOOLBAREDITOR_H_
+#define _TOOLBAREDITOR_H_
+//=============================================================================
+//
+// File : toolbareditor.h
+// Created on Wed 01 Dec 2004 14:42:20 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include <qwidget.h>
+#include <qlabel.h>
+#include <qdialog.h>
+#include <qcolor.h>
+
+class QPushButton;
+class KviActionDrawer;
+
+class KviCustomizeToolBarsDialog : public QDialog
+{
+ Q_OBJECT
+protected:
+ KviCustomizeToolBarsDialog(QWidget * p);
+public:
+ ~KviCustomizeToolBarsDialog();
+protected:
+ KviActionDrawer * m_pDrawer;
+ static KviCustomizeToolBarsDialog * m_pInstance;
+ QPushButton * m_pDeleteToolBarButton;
+ QPushButton * m_pRenameToolBarButton;
+ QPushButton * m_pExportToolBarButton;
+public:
+ static KviCustomizeToolBarsDialog * instance(){ return m_pInstance; };
+ static void display();
+ static void cleanup();
+protected:
+ virtual void showEvent(QShowEvent * e);
+ virtual void closeEvent(QCloseEvent *e);
+protected slots:
+ void closeClicked();
+ void newToolBar();
+ void deleteToolBar();
+ void renameToolBar();
+ void exportToolBar();
+ void currentToolBarChanged();
+};
+
+class QLineEdit;
+class QPushButton;
+
+class KviCustomToolBarPropertiesDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ KviCustomToolBarPropertiesDialog(QWidget * p,const QString &szText,const QString &szId = QString::null,const QString &szLabel = QString::null,const QString &szIconId = QString::null);
+ ~KviCustomToolBarPropertiesDialog();
+protected:
+ QString m_szId;
+ QString m_szOriginalId;
+ QString m_szLabel;
+ QString m_szIconId;
+ QWidget * m_pAdvanced;
+ QLineEdit * m_pIdEdit;
+ QLineEdit * m_pLabelEdit;
+ QLineEdit * m_pIconEdit;
+ QPushButton * m_pIconButton;
+ QPushButton * m_pAdvancedButton;
+public:
+ const QString &id(){ return m_szId; };
+ const QString &label(){ return m_szLabel; };
+ const QString &iconId(){ return m_szIconId; };
+protected slots:
+ void okClicked();
+ void advancedClicked();
+ void iconButtonClicked();
+ void labelTextChanged(const QString &s);
+protected:
+ void iconSelected(const QString &szIconId);
+};
+
+class QTimer;
+
+class KviTrashcanLabel : public QLabel
+{
+ Q_OBJECT
+public:
+ KviTrashcanLabel(QWidget * p);
+ virtual ~KviTrashcanLabel();
+protected:
+ unsigned int m_uFlashCount;
+ QTimer * m_pFlashTimer;
+ QColor m_clrOriginal;
+protected:
+ virtual void dragEnterEvent(QDragEnterEvent * e);
+ virtual void dropEvent(QDropEvent * e);
+public slots:
+ void flash();
+protected slots:
+ void heartbeat();
+};
+
+#endif //!_TOOLBAREDITOR_H_
diff --git a/src/modules/torrent/Makefile.am b/src/modules/torrent/Makefile.am
new file mode 100644
index 00000000..ab0d80cb
--- /dev/null
+++ b/src/modules/torrent/Makefile.am
@@ -0,0 +1,30 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkvitorrent.la
+
+#%.moc: %.h
+# $(SS_QT_MOC) $< -o $@
+
+libkvitorrent_la_LDFLAGS = -avoid-version -module
+
+libkvitorrent_la_SOURCES = libkvitorrent.cpp \
+ tc_interface.cpp \
+ tc_ktorrentdcopinterface.cpp \
+ tc_statusbarapplet.cpp
+
+libkvitorrent_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+noinst_HEADERS = tc_interface.h \
+ tc_ktorrentdcopinterface.h \
+ tc_statusbarapplet.h
+
+%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
+
+tc_ktorrentdcopinterface.cpp: tc_ktorrentdcopinterface.moc
+tc_statusbarapplet.cpp: tc_statusbarapplet.moc
diff --git a/src/modules/torrent/libkvitorrent.cpp b/src/modules/torrent/libkvitorrent.cpp
new file mode 100644
index 00000000..9a929483
--- /dev/null
+++ b/src/modules/torrent/libkvitorrent.cpp
@@ -0,0 +1,904 @@
+//=============================================================================
+//
+// File : libkvitorrent.cpp
+// Creation date : Fri Jan 1 15:42:25 2007 GMT by Alexander Stillich
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_module.h"
+#include "kvi_options.h"
+#include "kvi_frame.h"
+
+#include "tc_interface.h"
+#include "tc_ktorrentdcopinterface.h"
+#include "tc_statusbarapplet.h"
+
+#include "kvi_locale.h"
+#include "kvi_out.h"
+
+
+static KviPointerList<KviTorrentInterfaceDescriptor> * g_pDescriptorList = 0;
+
+static KviTorrentInterface *auto_detect_torrent_client(KviWindow * pOut = 0)
+{
+ int iBest = 0;
+ KviTorrentInterface * pBest = 0;
+ KviTorrentInterfaceDescriptor * d;
+ KviTorrentInterfaceDescriptor * pDBest = 0;
+
+ for (d=g_pDescriptorList->first(); d!=0; d=g_pDescriptorList->next())
+ {
+ // instance gets deleted by descriptor later
+ KviTorrentInterface *i = d->instance();
+ if (i)
+ {
+ int iScore = i->detect();
+ if(iScore > iBest)
+ {
+ iBest = iScore;
+ pBest = i;
+ pDBest = d;
+ }
+
+ if(pOut)
+ {
+ pOut->output(KVI_OUT_TORRENT,
+ __tr2qs_ctx("Trying torrent client interface \"%Q\": score %d", "torrent"),
+ &d->name(),
+ iScore);
+ }
+ }
+ }
+
+/* if(iBest < 90)
+ {
+ if(pOut)
+ pOut->outputNoFmt(KVI_OUT_MULTIMEDIA,__tr2qs_ctx("Not sure about the results, trying a second, more agressive detection pass","mediaplayer"));
+ // no sure player found... try again with a destructive test
+ for(d = g_pDescriptorList->first();d;d = g_pDescriptorList->next())
+ {
+ KviMediaPlayerInterface * i = d->instance();
+ if(i)
+ {
+ int iScore = i->detect(true);
+ if(iScore > iBest)
+ {
+ iBest = iScore;
+ pBest = i;
+ pDBest = d;
+ }
+ if(pOut)
+ {
+ QString szOut;
+ QString szNam = d->name();
+ KviQString::sprintf(szOut,__tr2qs_ctx("Trying media player interface \"%Q\": score %d","mediaplayer"),&(szNam),iScore);
+ pOut->output(KVI_OUT_MULTIMEDIA,szOut);
+ }
+ }
+ }
+ }
+*/
+ if(pDBest)
+ {
+ KVI_OPTION_STRING(KviOption_stringPreferredTorrentClient) = pDBest->name();
+ if(pOut)
+ pOut->output(KVI_OUT_TORRENT,
+ __tr2qs_ctx("Choosing torrent client interface \"%Q\"", "torrent"),
+ &pDBest->name());
+
+ } else
+ {
+ if(pOut)
+ pOut->outputNoFmt(KVI_OUT_TORRENT,
+ __tr2qs_ctx("Seems that there is no usable torrent client on this machine", "torrent"));
+ }
+
+ return pBest;
+}
+
+#define TC_KVS_FAIL_ON_NO_INTERFACE \
+ if (!KviTorrentInterface::selected()) \
+ { \
+ c->warning(__tr2qs_ctx("No torrent client interface selected. Try /torrent.detect", "torrent")); \
+ return true; \
+ }
+
+#define TC_KVS_COMMAND(__name) static bool torrent_kvs_cmd_ ## __name (KviKvsModuleCommandCall * c)
+#define TC_KVS_FUNCTION(__name) static bool torrent_kvs_fnc_ ## __name (KviKvsModuleFunctionCall * c)
+
+#define TC_KVS_COMMAND_ERROR \
+ if (!c->hasSwitch('q',"quiet")) \
+ { \
+ c->warning(__tr2qs_ctx("The selected torrent client interface failed to execute the requested function", "torrent")); \
+ QString tmp = __tr2qs_ctx("Last interface error: ", "torrent"); \
+ tmp += KviTorrentInterface::selected()->lastError(); \
+ c->warning(tmp); \
+ } \
+
+#define TC_KVS_SIMPLE_COMMAND(__name, __ifacecommand) \
+ TC_KVS_COMMAND(__name) \
+ { \
+ KVSM_PARAMETERS_BEGIN(c) \
+ KVSM_PARAMETERS_END(c) \
+ \
+ TC_KVS_FAIL_ON_NO_INTERFACE \
+ \
+ if (!KviTorrentInterface::selected()->__ifacecommand()) \
+ { \
+ TC_KVS_COMMAND_ERROR \
+ } \
+ return true; \
+ }
+
+#define TC_KVS_INT_COMMAND(__name, __ifacecommand, __argname) \
+ TC_KVS_COMMAND(__name) \
+ { \
+ kvs_int_t arg; \
+ KVSM_PARAMETERS_BEGIN(c) \
+ KVSM_PARAMETER(__argname, KVS_PT_INT, 0, arg) \
+ KVSM_PARAMETERS_END(c) \
+ \
+ TC_KVS_FAIL_ON_NO_INTERFACE \
+ \
+ if (!KviTorrentInterface::selected()->__ifacecommand(arg)) \
+ { \
+ TC_KVS_COMMAND_ERROR \
+ } \
+ return true; \
+ }
+
+#define TC_KVS_INT_INT_STRING_COMMAND(__name, __ifacecommand, __argname1, __argname2, __argname3) \
+ TC_KVS_COMMAND(__name) \
+ { \
+ kvs_int_t arg1; \
+ kvs_int_t arg2; \
+ QString arg3; \
+ KVSM_PARAMETERS_BEGIN(c) \
+ KVSM_PARAMETER(__argname1, KVS_PT_INT, 0, arg1) \
+ KVSM_PARAMETER(__argname2, KVS_PT_INT, 0, arg2) \
+ KVSM_PARAMETER(__argname3, KVS_PT_STRING, 0, arg3) \
+ KVSM_PARAMETERS_END(c) \
+ \
+ TC_KVS_FAIL_ON_NO_INTERFACE \
+ \
+ if (!KviTorrentInterface::selected()->__ifacecommand(arg1, arg2, arg3)) \
+ { \
+ TC_KVS_COMMAND_ERROR \
+ } \
+ return true; \
+ }
+
+// TODO: error handling for functions
+
+#define TC_KVS_STRINGRET_FUNCTION(__name, __ifacecommand) \
+ TC_KVS_FUNCTION(__name) \
+ { \
+ TC_KVS_FAIL_ON_NO_INTERFACE \
+ QString szRet = KviTorrentInterface::selected()->__ifacecommand(); \
+ c->returnValue()->setString(szRet); \
+ return true; \
+ }
+
+#define TC_KVS_INTRET_FUNCTION(__name, __ifacecommand) \
+ TC_KVS_FUNCTION(__name) \
+ { \
+ TC_KVS_FAIL_ON_NO_INTERFACE \
+ kvs_int_t ret = KviTorrentInterface::selected()->__ifacecommand(); \
+ c->returnValue()->setInteger(ret); \
+ return true; \
+ }
+
+#define TC_KVS_FLOATRET_FUNCTION(__name, __ifacecommand) \
+ TC_KVS_FUNCTION(__name) \
+ { \
+ TC_KVS_FAIL_ON_NO_INTERFACE \
+ kvs_real_t ret = KviTorrentInterface::selected()->__ifacecommand(); \
+ c->returnValue()->setReal(ret); \
+ return true; \
+ }
+
+#define TC_KVS_INTRET_INT_FUNCTION(__name, __ifacecommand, __argname) \
+ TC_KVS_FUNCTION(__name) \
+ { \
+ kvs_int_t arg; \
+ KVSM_PARAMETERS_BEGIN(c) \
+ KVSM_PARAMETER(__argname, KVS_PT_INT, 0, arg) \
+ KVSM_PARAMETERS_END(c) \
+ TC_KVS_FAIL_ON_NO_INTERFACE \
+ kvs_int_t ret = KviTorrentInterface::selected()->__ifacecommand(arg); \
+ c->returnValue()->setInteger(ret); \
+ return true; \
+ }
+
+#define TC_KVS_STRINGRET_INT_FUNCTION(__name, __ifacecommand, __argname) \
+ TC_KVS_FUNCTION(__name) \
+ { \
+ kvs_int_t arg; \
+ KVSM_PARAMETERS_BEGIN(c) \
+ KVSM_PARAMETER(__argname, KVS_PT_INT, 0, arg) \
+ KVSM_PARAMETERS_END(c) \
+ TC_KVS_FAIL_ON_NO_INTERFACE \
+ QString szRet = KviTorrentInterface::selected()->__ifacecommand(arg); \
+ c->returnValue()->setString(szRet); \
+ return true; \
+ }
+
+#define TC_KVS_STRINGRET_INT_INT_FUNCTION(__name, __ifacecommand, __argname1, __argname2) \
+ TC_KVS_FUNCTION(__name) \
+ { \
+ kvs_int_t arg1; \
+ kvs_int_t arg2; \
+ KVSM_PARAMETERS_BEGIN(c) \
+ KVSM_PARAMETER(__argname1, KVS_PT_INT, 0, arg1) \
+ KVSM_PARAMETER(__argname2, KVS_PT_INT, 0, arg2) \
+ KVSM_PARAMETERS_END(c) \
+ TC_KVS_FAIL_ON_NO_INTERFACE \
+ QString szRet = KviTorrentInterface::selected()->__ifacecommand(arg1, arg2); \
+ c->returnValue()->setString(szRet); \
+ return true; \
+ }
+
+#define TC_KVS_INTRET_INT_INT_FUNCTION(__name, __ifacecommand, __argname1, __argname2) \
+ TC_KVS_FUNCTION(__name) \
+ { \
+ kvs_int_t arg1; \
+ kvs_int_t arg2; \
+ KVSM_PARAMETERS_BEGIN(c) \
+ KVSM_PARAMETER(__argname1, KVS_PT_INT, 0, arg1) \
+ KVSM_PARAMETER(__argname2, KVS_PT_INT, 0, arg2) \
+ KVSM_PARAMETERS_END(c) \
+ TC_KVS_FAIL_ON_NO_INTERFACE \
+ kvs_int_t ret = KviTorrentInterface::selected()->__ifacecommand(arg1, arg2); \
+ c->returnValue()->setInteger(ret); \
+ return true; \
+ }
+
+TC_KVS_COMMAND(detect)
+{
+ KviTorrentInterface::select(auto_detect_torrent_client(c->hasSwitch('q',"quiet") ? 0 : c->window()));
+ return true;
+}
+
+/*
+ @doc: torrent.maxUploadSpeed
+ @type:
+ function
+ @title:
+ $torrent.maxUploadSpeed
+ @short:
+ Returns maximum upload speed set in client.
+ @syntax:
+ $torrent.maxUploadSpeed()
+ @description:
+ Returns maximum upload speed set in client.
+ Take a look at the [module:torrent]torrent client documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:torrent]torrent client documentation[/module],
+*/
+TC_KVS_INTRET_FUNCTION(maxUploadSpeed, maxUploadSpeed)
+
+
+/*
+ @doc: torrent.maxDownloadSpeed
+ @type:
+ function
+ @title:
+ $torrent.maxDownloadSpeed
+ @short:
+ Returns maximum download speed set in client.
+ @syntax:
+ $torrent.maxDownloadSpeed()
+ @description:
+ Returns maximum download speed set in client.
+ Take a look at the [module:torrent]torrent client documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:torrent]torrent client documentation[/module],
+*/
+TC_KVS_INTRET_FUNCTION(maxDownloadSpeed, maxDownloadSpeed)
+
+/*
+ @doc: torrent.setMaxUploadSpeed
+ @type:
+ command
+ @title:
+ torrent.setMaxUploadSpeed
+ @short:
+ Sets maximum upload speed
+ @syntax:
+ torrent.setMaxUploadSpeed <kbytes_per_sec>
+ @description:
+ Sets maximum upload speed
+ Take a look at the [module:torrent]torrent client documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:torrent]torrent client documentation[/module],
+*/
+TC_KVS_INT_COMMAND(setMaxUploadSpeed, setMaxUploadSpeed, "kbytes_per_sec")
+
+/*
+ @doc: torrent.setMaxDownloadSpeed
+ @type:
+ command
+ @title:
+ torrent.setMaxDownloadSpeed
+ @short:
+ Sets maximum download speed
+ @syntax:
+ torrent.setMaxDownloadSpeed <kbytes_per_sec>
+ @description:
+ Sets maximum download speed
+ Take a look at the [module:torrent]torrent client documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:torrent]torrent client documentation[/module],
+*/
+TC_KVS_INT_COMMAND(setMaxDownloadSpeed, setMaxDownloadSpeed, "kbytes_per_sec")
+
+/*
+ @doc: torrent.speedUp
+ @type:
+ function
+ @title:
+ $torrent.speedUp
+ @short:
+ Returns current total upload speed
+ @syntax:
+ $torrent.speedUp()
+ @description:
+ Returns current total upload speed
+ Take a look at the [module:torrent]torrent client documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:torrent]torrent client documentation[/module],
+*/
+TC_KVS_FLOATRET_FUNCTION(speedUp, speedUp)
+
+/*
+ @doc: torrent.speedDown
+ @type:
+ function
+ @title:
+ $torrent.speedDown
+ @short:
+ Returns current total download speed
+ @syntax:
+ $torrent.speedDown()
+ @description:
+ Returns current total download speed
+ Take a look at the [module:torrent]torrent client documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:torrent]torrent client documentation[/module],
+*/
+TC_KVS_FLOATRET_FUNCTION(speedDown, speedDown)
+
+/*
+ @doc: torrent.trafficUp
+ @type:
+ function
+ @title:
+ $torrent.trafficUp
+ @short:
+ Returns the total number of bytes uploaded
+ @syntax:
+ $torrent.trafficUp()
+ @description:
+ Returns the total number of bytes uploaded
+ Take a look at the [module:torrent]torrent client documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:torrent]torrent client documentation[/module],
+*/
+TC_KVS_FLOATRET_FUNCTION(trafficUp, trafficUp)
+
+/*
+ @doc: torrent.trafficDown
+ @type:
+ function
+ @title:
+ $torrent.trafficDown
+ @short:
+ Returns the total number of bytes download
+ @syntax:
+ $torrent.trafficDown()
+ @description:
+ Returns the total number of bytes download
+ Take a look at the [module:torrent]torrent client documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:torrent]torrent client documentation[/module],
+*/
+TC_KVS_FLOATRET_FUNCTION(trafficDown, trafficDown)
+
+/*
+ @doc: torrent.count
+ @type:
+ function
+ @title:
+ $torrent.count
+ @short:
+ Returns number of torrents in client
+ @syntax:
+ $torrent.name()
+ @description:
+ Returns number of torrents in client
+ Take a look at the [module:torrent]torrent client documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:torrent]torrent client documentation[/module],
+*/
+TC_KVS_INTRET_FUNCTION(count, count)
+
+/*
+ @doc: torrent.name
+ @type:
+ function
+ @title:
+ $torrent.name
+ @short:
+ Returns torrent name as displayed in client
+ @syntax:
+ $torrent.name(torrent_number)
+ @description:
+ Returns torrent name as displayed in client
+ Take a look at the [module:torrent]torrent client documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:torrent]torrent client documentation[/module],
+*/
+TC_KVS_STRINGRET_INT_FUNCTION(name, name, "torrent_number")
+
+/*
+ @doc: torrent.start
+ @type:
+ command
+ @title:
+ torrent.start
+ @short:
+ Starts downloading of torrent <torrent_number>
+ @syntax:
+ torrent.start <torrent_number>
+ @description:
+ Starts downloading of torrent <torrent_number>
+ Take a look at the [module:torrent]torrent client documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:torrent]torrent client documentation[/module],
+ [cmd]torrent.stop[/cmd], [cmd]torrent.stopAll[/cmd],
+ [cmd]torrent.startAll[/cmd]
+*/
+TC_KVS_INT_COMMAND(start, start, "torrent_number")
+
+/*
+ @doc: torrent.stop
+ @type:
+ command
+ @title:
+ torrent.stop
+ @short:
+ Stops downloading of torrent <torrent_number>
+ @syntax:
+ torrent.stop <torrent_number>
+ @description:
+ Stops downloading of torrent <torrent_number>
+ Take a look at the [module:torrent]torrent client documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:torrent]torrent client documentation[/module],
+ [cmd]torrent.stopAll[/cmd], [cmd]torrent.startAll[/cmd],
+ [cmd]torrent.start[/cmd]
+*/
+TC_KVS_INT_COMMAND(stop, stop, "torrent_number")
+
+/*
+ @doc: torrent.announce
+ @type:
+ command
+ @title:
+ torrent.announce
+ @short:
+ Manually announces torrent to tracker
+ @syntax:
+ torrent.announce <torrent_number>
+ @description:
+ Manually announces torrent to tracker
+ Take a look at the [module:torrent]torrent client documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:torrent]torrent client documentation[/module],
+*/
+TC_KVS_INT_COMMAND(announce, announce, "torrent_number")
+
+/*
+ @doc: torrent.fileCount
+ @type:
+ function
+ @title:
+ $torrent.fileCount
+ @short:
+ Returns the number of files in a torrent.
+ @syntax:
+ $torrent.fileCount <torrent_number>
+ @description:
+ Returns the number of files in a torrent.
+ Take a look at the [module:torrent]torrent client documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:torrent]torrent client documentation[/module],
+*/
+TC_KVS_INTRET_INT_FUNCTION(fileCount, fileCount, "torrent_number")
+
+/*
+ @doc: torrent.fileName
+ @type:
+ function
+ @title:
+ $torrent.fileName
+ @short:
+ Returns the name of a file in a torrent.
+ @syntax:
+ $torrent.fileName <torrent_number> <file_number>
+ @description:
+ Returns the name of a file in a torrent.
+ Take a look at the [module:torrent]torrent client documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:torrent]torrent client documentation[/module],
+*/
+TC_KVS_STRINGRET_INT_INT_FUNCTION(fileName, fileName, "torrent_number", "file_number")
+
+/*
+ @doc: torrent.filePriority
+ @type:
+ function
+ @title:
+ $torrent.filePriority
+ @short:
+ Returns the priority of a file in a torrent.
+ @syntax:
+ $torrent.filePriority <torrent_number> <file_number>
+ @description:
+ Returns the priority of a file in a torrent.
+ Take a look at the [module:torrent]torrent client documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:torrent]torrent client documentation[/module],
+*/
+TC_KVS_STRINGRET_INT_INT_FUNCTION(filePriority, filePriority, "torrent_number", "file_number")
+
+/*
+ @doc: torrent.setFilePriority
+ @type:
+ command
+ @title:
+ torrent.setFilePriority
+ @short:
+ Sets the priority of a file in a torrent.
+ @syntax:
+ torrent.setFilePriority <torrent_number> <file_number>
+ @description:
+ Sets the priority of a file in a torrent.
+ Take a look at the [module:torrent]torrent client documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:torrent]torrent client documentation[/module],
+*/
+TC_KVS_INT_INT_STRING_COMMAND(setFilePriority, setFilePriority, "torrent_number", "file_number", "priority")
+
+/*
+ @doc: torrent.startAll
+ @type:
+ command
+ @title:
+ torrent.startAll
+ @short:
+ Starts downloading of all torrents
+ @syntax:
+ torrent.startAll
+ @description:
+ Starts downloading of all torrents
+ Take a look at the [module:torrent]torrent client documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:torrent]torrent client documentation[/module],
+ [cmd]torrent.stopAll[/cmd], [cmd]torrent.start[/cmd],
+ [cmd]torrent.stop[/cmd]
+*/
+
+TC_KVS_SIMPLE_COMMAND(startAll, startAll)
+
+/*
+ @doc: torrent.stopAll
+ @type:
+ command
+ @title:
+ torrent.stopAll
+ @short:
+ Stops downloading of all torrents
+ @syntax:
+ torrent.stopAll
+ @description:
+ Stops downloading of all torrents
+ Take a look at the [module:torrent]torrent client documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:torrent]torrent client documentation[/module],
+ [cmd]torrent.startAll[/cmd], [cmd]torrent.start[/cmd],
+ [cmd]torrent.stop[/cmd]
+*/
+
+TC_KVS_SIMPLE_COMMAND(stopAll, stopAll)
+
+
+/*
+ @doc: torrent.list
+ @type:
+ function
+ @title:
+ torrent.list
+ @short:
+ Returns a list of all torrents
+ @syntax:
+ $torrent.list()
+ @description:
+ Returns a list of all torrents
+ Take a look at the [module:torrent]torrent client documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:torrent]torrent client documentation[/module],
+ [cmd]torrent.startAll[/cmd], [cmd]torrent.start[/cmd],
+ [cmd]torrent.stop[/cmd]
+*/
+
+//MP_KVS_SIMPLE_COMMAND(list,list)
+
+/*
+ @doc: torrent.setClient
+ @type:
+ command
+ @title:
+ torrent.setClient
+ @short:
+ Sets the torrent client interface
+ @syntax:
+ torrent.setClient <client_name>
+ @description:
+ Sets the torrent client interface to be used by the
+ torrent interface module. <interface_name> must be one
+ of the client names returned by [cmd]torrent.clientList[/cmd]
+ Take a look at the [module:torrent]torrent client documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:torrent]torrent client documentation[/module],
+ [cmd]torrent.detect[/cmd], [fnc]$torrent.client[/fnc]
+*/
+
+TC_KVS_COMMAND(setClient)
+{
+ QString client;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("client", KVS_PT_STRING, 0, client)
+ KVSM_PARAMETERS_END(c)
+
+ for (KviTorrentInterfaceDescriptor *d = g_pDescriptorList->first(); d; d=g_pDescriptorList->next())
+ {
+ if (d->name() == client)
+ {
+ KviTorrentInterface::select(d->instance());
+ KVI_OPTION_STRING(KviOption_stringPreferredTorrentClient) = client;
+
+ if (!c->hasSwitch('q',"quiet"))
+ c->window()->output(KVI_OUT_TORRENT,
+ __tr2qs_ctx("Using client interface \"%Q\".", "torrent"),
+ &client);
+ return true;
+ }
+ }
+
+ if (!c->hasSwitch('q',"quiet"))
+ c->window()->output(KVI_OUT_TORRENT,
+ __tr2qs_ctx("Invalid client interface \"%Q\"!", "torrent"),
+ &client);
+
+ return false;
+}
+
+
+/*
+ @doc: torrent.client
+ @type:
+ function
+ @title:
+ $torrent.client
+ @short:
+ Returns the currently set torrent client interface
+ @syntax:
+ $torrent.client()
+ @description:
+ Returns the currently set torrent client interface.
+ Take a look at the [module:torrent]torrent client documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:torrent]torrent client documentation[/module],
+ [cmd]torrent.detect[/cmd], [cmd]torrent.setClient[/cmd]
+*/
+TC_KVS_FUNCTION(client)
+{
+ c->returnValue()->setString(KVI_OPTION_STRING(KviOption_stringPreferredTorrentClient));
+ return true;
+}
+
+/*
+ @doc: torrent.clientList
+ @type:
+ function
+ @title:
+ $torrent.clientList
+ @short:
+ Returns a list of all supported clients.
+ @syntax:
+ $torrent.clientList()
+ @description:
+ Returns a list of all supported clients.
+ Take a look at the [module:torrent]torrent client documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:torrent]torrent client documentation[/module],
+ [cmd]torrent.detect[/cmd], [cmd]torrent.setClient[/cmd],
+ [cmd]torrent.client[/cmd]
+*/
+TC_KVS_FUNCTION(clientList)
+{
+ KviKvsArray *pArray = new KviKvsArray();
+ int id=0;
+
+ for (KviTorrentInterfaceDescriptor *d=g_pDescriptorList->first(); d; d=g_pDescriptorList->next())
+ pArray->set(id++, new KviKvsVariant(d->name()));
+
+ c->returnValue()->setArray(pArray);
+ return true;
+}
+
+/*
+ @doc: torrent.state
+ @type:
+ function
+ @title:
+ $torrent.state
+ @short:
+ Returns state of torrent (Stopped, Stalled, Seeding, Downloading)
+ @syntax:
+ $torrent.state <torrent_number>
+ @description:
+ Returns state of torrent (Stopped, Stalled, Seeding, Downloading)
+ Take a look at the [module:torrent]torrent client documentation[/module]
+ for more details about how it works.[br]
+ @seealso:
+ [module:torrent]torrent client documentation[/module],
+*/
+TC_KVS_STRINGRET_INT_FUNCTION(state, state, "torrent_number")
+
+static bool torrent_module_init(KviModule *m)
+{
+ #define TC_KVS_REGCMD(__name,__stringname) KVSM_REGISTER_SIMPLE_COMMAND(m, __stringname, torrent_kvs_cmd_ ## __name)
+ #define TC_KVS_REGFNC(__name,__stringname) KVSM_REGISTER_FUNCTION(m, __stringname, torrent_kvs_fnc_ ## __name)
+
+ TC_KVS_REGCMD(detect, "detect");
+ TC_KVS_REGCMD(setClient, "setClient");
+ TC_KVS_REGCMD(start, "start")
+ TC_KVS_REGCMD(stop, "stop")
+ TC_KVS_REGCMD(announce, "announce")
+ TC_KVS_REGCMD(startAll, "startAll")
+ TC_KVS_REGCMD(stopAll, "stopAll")
+ TC_KVS_REGCMD(setMaxUploadSpeed, "setMaxUploadSpeed")
+ TC_KVS_REGCMD(setMaxDownloadSpeed, "setMaxDownloadSpeed")
+ TC_KVS_REGCMD(setFilePriority, "setFilePriority")
+ TC_KVS_REGFNC(client, "client")
+ TC_KVS_REGFNC(clientList, "clientList")
+ TC_KVS_REGFNC(maxUploadSpeed, "maxUploadSpeed")
+ TC_KVS_REGFNC(maxDownloadSpeed, "maxDownloadSpeed")
+ TC_KVS_REGFNC(speedUp, "speedUp")
+ TC_KVS_REGFNC(speedDown, "speedDown")
+ TC_KVS_REGFNC(trafficUp, "trafficUp")
+ TC_KVS_REGFNC(trafficDown, "trafficDown")
+ TC_KVS_REGFNC(count, "count")
+ TC_KVS_REGFNC(name, "name")
+ TC_KVS_REGFNC(state, "state")
+ TC_KVS_REGFNC(fileCount, "fileCount")
+ TC_KVS_REGFNC(fileName, "fileName")
+ TC_KVS_REGFNC(filePriority, "filePriority")
+
+ g_pDescriptorList = new KviPointerList<KviTorrentInterfaceDescriptor>;
+ g_pDescriptorList->setAutoDelete(true);
+
+#ifdef COMPILE_KDE_SUPPORT
+ g_pDescriptorList->append(new KviKTorrentDCOPInterfaceDescriptor);
+#endif // COMPILE_KDE_SUPPORT
+
+ KviTorrentInterface::select(0);
+
+ if (g_pFrame->mainStatusBar())
+ KviTorrentStatusBarApplet::selfRegister(g_pFrame->mainStatusBar());
+
+
+ if(KVI_OPTION_STRING(KviOption_stringPreferredMediaPlayer) == "auto")
+ {
+ KviTorrentInterface::select(auto_detect_torrent_client());
+
+ } else
+ {
+ for (KviTorrentInterfaceDescriptor *d=g_pDescriptorList->first(); d; d=g_pDescriptorList->next())
+ {
+ if (d->name() == KVI_OPTION_STRING(KviOption_stringPreferredTorrentClient))
+ KviTorrentInterface::select(d->instance());
+ }
+ }
+
+ return true;
+}
+
+static bool torrent_module_cleanup( KviModule * m )
+{
+ delete g_pDescriptorList;
+ return true;
+}
+
+static bool torrent_module_can_unload( KviModule * m )
+{
+ return true;
+}
+
+static bool torrent_module_ctrl(KviModule * m,const char * operation,void * param)
+{
+ debug("torrent module ctrl");
+/* if(kvi_strEqualCI(operation,"getAvailableMediaPlayers"))
+ {
+ // we expect param to be a pointer to QStringList
+ QStringList * l = (QStringList *)param;
+ for(KviMediaPlayerInterfaceDescriptor * d = g_pDescriptorList->first();d;d = g_pDescriptorList->next())
+ {
+ l->append(d->name());
+ }
+ return true;
+ }
+ if(kvi_strEqualCI(operation,"detectMediaPlayer"))
+ {
+ auto_detect_player(0);
+ return true;
+ }
+*/
+ return false;
+}
+
+
+
+KVIRC_MODULE(
+ "torrent",
+ "1.0.0",
+ "Copyright (C) 2007 Alexander Stillich (torque at pltn dot org)",
+ "Interface to various torrent clients",
+ torrent_module_init,
+ torrent_module_can_unload,
+ torrent_module_ctrl,
+ torrent_module_cleanup
+)
diff --git a/src/modules/torrent/tc_interface.cpp b/src/modules/torrent/tc_interface.cpp
new file mode 100644
index 00000000..9474a254
--- /dev/null
+++ b/src/modules/torrent/tc_interface.cpp
@@ -0,0 +1,31 @@
+//=============================================================================
+//
+// Common interface for BitTorrent clients.
+//
+// File : tc_interface.cpp
+// Creation date : Fri Jan 1 15:42:25 2007 GMT by Alexander Stillich
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2005 Szymon Stefanek (pragma at kvirc dot net)
+// Copyright (C) 2007 Alexander Stillich (torque at pltn dot org)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) 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.
+//
+//=============================================================================
+
+#include "tc_interface.h"
+#include "kvi_locale.h"
+
+KviTorrentInterface *KviTorrentInterface::m_selected = 0;
diff --git a/src/modules/torrent/tc_interface.h b/src/modules/torrent/tc_interface.h
new file mode 100644
index 00000000..797ea428
--- /dev/null
+++ b/src/modules/torrent/tc_interface.h
@@ -0,0 +1,164 @@
+#ifndef _TC_INTERFACE_H_
+#define _TC_INTERFACE_H_
+
+//=============================================================================
+//
+// Common interface for BitTorrent clients.
+//
+// File : tc_interface.h
+// Creation date : Fri Jan 1 15:42:25 2007 GMT by Alexander Stillich
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2005 Szymon Stefanek (pragma at kvirc dot net)
+// Copyright (C) 2007 Alexander Stillich (torque at pltn dot org)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_qstring.h"
+#include <qobject.h>
+
+class KviTorrentInterface : public QObject
+{
+
+public:
+
+ KviTorrentInterface() {}
+ virtual ~KviTorrentInterface() {}
+
+ virtual int detect() = 0;
+
+ // returns number of torrents in client
+ virtual int count()=0;
+
+/*
+ // path of torrent file
+ virtual QCString getTorrentFile(int i)=0;
+
+ // directory where data is downloaded to
+ virtual QCString getTorrentDataDir(int i)=0;
+*/
+ // number of files in torrent
+ virtual int fileCount(int i)=0;
+ // name of file in torrent
+ virtual QString fileName(int i, int file)=0;
+ // returns file priority (low, normal, high)
+ virtual QString filePriority(int i, int file)=0;
+ // sets file priority
+ virtual bool setFilePriority(int i, int file, const QString &prio)=0;
+
+ virtual bool start(int i)=0;
+ virtual bool stop(int i)=0;
+
+ virtual bool announce(int i)=0;
+
+ virtual bool startAll()=0;
+ virtual bool stopAll()=0;
+/*
+ // remove torrent from client
+ virtual bool removeTorrent(int i)=0;
+
+ virtual bool addTorrent(const QCString &mrl);
+*/
+ // returns state of torrent number i (Stopped, Stalled, Seeding, Downloading)
+ // this uses getTorrentInfo() to obtain the state and then
+ // returns it as string
+ virtual QString state(int i)=0;
+
+ // name of torrent as displayed in client
+ // uses getTorrentInfo()
+ virtual QString name(int i)=0;
+
+ virtual float speedUp()=0;
+ virtual float speedDown()=0;
+
+ virtual float trafficUp()=0;
+ virtual float trafficDown()=0;
+
+ virtual int maxUploadSpeed()=0;
+ virtual int maxDownloadSpeed()=0;
+
+ virtual bool setMaxUploadSpeed(int kbytes_per_sec)=0;
+ virtual bool setMaxDownloadSpeed(int kbytes_per_sec)=0;
+
+ QString lastError() { return m_lastError; }
+
+ static void select(KviTorrentInterface *i) { m_selected = i; }
+ static KviTorrentInterface *selected() { return m_selected; }
+
+protected:
+
+ QString m_lastError;
+
+ static KviTorrentInterface *m_selected;
+};
+
+class KviTorrentInterfaceDescriptor
+{
+public:
+ KviTorrentInterfaceDescriptor() {};
+ virtual ~KviTorrentInterfaceDescriptor() {};
+public:
+ virtual const QString & name() = 0;
+ virtual const QString & description() = 0;
+ virtual KviTorrentInterface * instance() = 0;
+};
+
+#define TORR_DECLARE_DESCRIPTOR(_interfaceclass) \
+ class _interfaceclass ## Descriptor : public KviTorrentInterfaceDescriptor \
+ { \
+ public: \
+ _interfaceclass ## Descriptor(); \
+ virtual ~_interfaceclass ## Descriptor(); \
+ protected: \
+ _interfaceclass * m_pInstance; \
+ QString m_szName; \
+ QString m_szDescription; \
+ public: \
+ virtual const QString & name(); \
+ virtual const QString & description(); \
+ virtual KviTorrentInterface * instance(); \
+ };
+
+#define TORR_IMPLEMENT_DESCRIPTOR(_interfaceclass,_name,_description) \
+ _interfaceclass ## Descriptor::_interfaceclass ## Descriptor() \
+ : KviTorrentInterfaceDescriptor() \
+ { \
+ m_pInstance = 0; \
+ m_szName = _name; \
+ m_szDescription = _description; \
+ } \
+ _interfaceclass ## Descriptor::~_interfaceclass ## Descriptor() \
+ { \
+ delete m_pInstance; \
+ } \
+ const QString & _interfaceclass ## Descriptor::name() \
+ { \
+ return m_szName; \
+ } \
+ const QString & _interfaceclass ## Descriptor::description() \
+ { \
+ return m_szDescription; \
+ } \
+ KviTorrentInterface * _interfaceclass ## Descriptor::instance() \
+ { \
+ if (!m_pInstance) m_pInstance = new _interfaceclass(); \
+ return m_pInstance; \
+ }
+
+#endif // _TC_INTERFACE_H_
+
diff --git a/src/modules/torrent/tc_ktorrentdcopinterface.cpp b/src/modules/torrent/tc_ktorrentdcopinterface.cpp
new file mode 100644
index 00000000..8e770bfc
--- /dev/null
+++ b/src/modules/torrent/tc_ktorrentdcopinterface.cpp
@@ -0,0 +1,500 @@
+//=============================================================================
+//
+// Common interface for BitTorrent clients.
+//
+// File : torr_ktorrentdcopinterface.cpp
+// Creation date : Fri Jan 1 15:42:25 2007 GMT by Alexander Stillich
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2005 Szymon Stefanek (pragma at kvirc dot net)
+// Copyright (C) 2007 Alexander Stillich (torque at pltn dot org)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) 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.
+//
+//=============================================================================
+
+#ifdef COMPILE_KDE_SUPPORT
+
+#include "kvi_app.h"
+
+
+#include "dcopclient.h" // <-- this include should be hidden in kvilib
+
+#include "tc_ktorrentdcopinterface.h"
+
+
+#include "kvi_locale.h"
+#include <qtimer.h>
+
+TORR_IMPLEMENT_DESCRIPTOR(
+ KviKTorrentDCOPInterface,
+ "ktorrentdcop",
+ __tr2qs_ctx(
+ "An interface to KDE's excellent KTorrent client.\n" \
+ "Download it from http://www.ktorrent.org\n",
+ "torrent"
+ )
+)
+
+#define ERROR_MSG \
+ QCString msg; \
+ if (!findRunningApp(m_szAppId)) \
+ msg = "KTorrent's isn't running!"; \
+ else \
+ msg = "Something's wrong here! KTorrent's DCOP interface has probably changed."; \
+ m_lastError = __tr2qs_ctx(QString(msg), "torrent"); \
+ debug("%s (%s:%d): %s", __PRETTY_FUNCTION__, __FILE__, __LINE__, (const char*)msg); \
+
+#define ERROR_MSG_RANGE(I, SIZE) \
+ KviQString::sprintf(m_lastError, __tr2qs_ctx("Index out of range: %d [0-%d]!", "torrent"), I, (SIZE>0)?(SIZE-1):0); \
+ debug("%s (%s:%d): Index out of range: %d [0-%d]!", __PRETTY_FUNCTION__ , __FILE__, __LINE__, I, (SIZE>0)?(SIZE-1):0);
+
+#define ERROR_RET_BOOL \
+ { \
+ ERROR_MSG \
+ return false; \
+ }
+
+#define ERROR_RET_NUM \
+ { \
+ ERROR_MSG \
+ return -1; \
+ }
+
+// TODO: unused?
+#define ERROR_RET_STRING \
+ { \
+ ERROR_MSG \
+ return ""; \
+ }
+
+#define ERROR_RET_VOID \
+ { \
+ ERROR_MSG \
+ return; \
+ }
+
+#define CHECK_RANGE_BOOL(I, SIZE) \
+ if (I<0 || I>=SIZE) \
+ { \
+ ERROR_MSG_RANGE(I, SIZE) \
+ return false; \
+ }
+
+#define CHECK_RANGE_INT(I, SIZE) \
+ if (I<0 || I>=SIZE) \
+ { \
+ ERROR_MSG_RANGE(I, SIZE) \
+ return -1; \
+ }
+
+#define CHECK_RANGE_STRING(I, SIZE) \
+ if (I<0 || I>=SIZE) \
+ { \
+ ERROR_MSG_RANGE(I, SIZE) \
+ return ""; \
+ }
+
+KviKTorrentDCOPInterface::KviKTorrentDCOPInterface()
+ : KviDCOPHelper(false, "ktorrent")
+{
+ printf("KviKTorrentDCOPInterface\n");
+
+ QTimer *timer = new QTimer(this);
+ connect(timer, SIGNAL(timeout()), this, SLOT(slotTimer()));
+ timer->start(250, FALSE);
+
+ // make sure we have a list of files,
+ // otherwise functions dealing would
+ // fail if called the first time
+ slotTimer();
+}
+
+KviKTorrentDCOPInterface::~KviKTorrentDCOPInterface()
+{
+ printf("~KviKTorrentDCOPInterface\n");
+}
+
+void KviKTorrentDCOPInterface::slotTimer()
+{
+ if (!findRunningApp(m_szAppId))
+ return;
+
+ m_ti.clear();
+
+ KviValueList<int> ret;
+ if (!qvalueListIntRetIntDCOPCall("KTorrent", "getTorrentNumbers(int)", ret, 0))
+ ERROR_RET_VOID
+
+ for (int i=0; i<ret.size(); i++)
+ {
+ KviQCStringList info;
+ if (!qcstringListRetIntDCOPCall("KTorrent", "getTorrentInfo(int)", info, ret[i]))
+ ERROR_RET_VOID
+
+ if (info.size() == 0)
+ continue;
+
+ TorrentInfo item;
+ if (!makeTorrentInfo(item, info))
+ return;
+
+ item.num = ret[i];
+ m_ti.append(item);
+ }
+
+ qHeapSort(m_ti);
+}
+
+int KviKTorrentDCOPInterface::detect()
+{
+ if (!findRunningApp(m_szAppId))
+ return 0;
+
+ return 100;
+}
+
+bool makeSize(float &sz, const QString &s, const QString &u)
+{
+ bool ok;
+ sz = s.toFloat(&ok);
+ if (!ok)
+ return false;
+
+ if (u == "B")
+ ;
+ else
+ if (u == "KB")
+ sz = sz * 1024.0;
+ else
+ if (u == "MB")
+ sz = sz * 1024.0 * 1024.0;
+ else
+ if (u == "GB")
+ sz = sz * 1024.0 * 1024.0 * 1024.0;
+ else
+ return false;
+
+ return true;
+}
+
+bool KviKTorrentDCOPInterface::start(int i)
+{
+ CHECK_RANGE_BOOL(i, m_ti.size())
+
+ debug("starting %s [%d]", (const char*)m_ti[i].name, m_ti[i].num);
+ if (!voidRetIntDCOPCall("KTorrent", "start(int)", m_ti[i].num))
+ ERROR_RET_BOOL
+
+ return true;
+}
+
+bool KviKTorrentDCOPInterface::stop(int i)
+{
+ CHECK_RANGE_BOOL(i, m_ti.size())
+
+ debug("stopping %s [%d]", (const char*)m_ti[i].name, m_ti[i].num);
+ if (!voidRetIntBoolDCOPCall("KTorrent", "stop(int, bool)", m_ti[i].num, true))
+ ERROR_RET_BOOL
+
+ return true;
+}
+
+bool KviKTorrentDCOPInterface::announce(int i)
+{
+ CHECK_RANGE_BOOL(i, m_ti.size())
+
+ debug("announcing %s [%d]", (const char*)m_ti[i].name, m_ti[i].num);
+ if (!voidRetIntDCOPCall("KTorrent", "announce(int)", m_ti[i].num))
+ ERROR_RET_BOOL
+ return true;
+}
+
+QString KviKTorrentDCOPInterface::state(int i)
+{
+ CHECK_RANGE_STRING(i, m_ti.size())
+
+ return m_ti[i].state;
+}
+
+QString KviKTorrentDCOPInterface::name(int i)
+{
+ CHECK_RANGE_STRING(i, m_ti.size())
+
+ return m_ti[i].name;
+}
+
+int KviKTorrentDCOPInterface::fileCount(int i)
+{
+ CHECK_RANGE_INT(i, m_ti.size())
+
+ int ret;
+ if (!intRetIntDCOPCall("KTorrent", "getFileCount(int)", ret, m_ti[i].num))
+ ERROR_RET_NUM
+
+ return ret;
+}
+
+QString KviKTorrentDCOPInterface::fileName(int i, int file)
+{
+ CHECK_RANGE_STRING(i, m_ti.size())
+
+ QCStringList ret;
+ if (!qcstringListRetIntDCOPCall("KTorrent", "getFileNames(int)", ret, m_ti[i].num))
+ ERROR_RET_STRING
+
+ CHECK_RANGE_STRING(file, ret.size())
+
+ return ret[file];
+}
+
+QString KviKTorrentDCOPInterface::filePriority(int i, int file)
+{
+ CHECK_RANGE_STRING(i, m_ti.size())
+
+ QValueList<int> ret;
+ if (!qvalueListIntRetIntDCOPCall("KTorrent", "getFilePriorities(int)",ret, m_ti[i].num))
+ ERROR_RET_STRING
+
+ CHECK_RANGE_STRING(file, ret.size())
+
+ debug("prio: %d", ret[file]);
+ switch (ret[file])
+ {
+ case 1: return "low";
+ case 2: return "normal";
+ case 3: return "high";
+ }
+
+ ERROR_RET_STRING
+}
+
+bool KviKTorrentDCOPInterface::setFilePriority(int i, int file, const QString &prio)
+{
+ CHECK_RANGE_BOOL(i, m_ti.size())
+
+ int prion;
+ if (prio == "low")
+ prion = 1;
+ else
+ if (prio == "normal")
+ prion = 2;
+ else
+ if (prio == "high")
+ prion = 1;
+ else
+ ERROR_RET_BOOL
+
+ if (!voidRetIntIntIntDCOPCall("KTorrent", "setFilePriority(int,int,int)", m_ti[i].num, file, prion))
+ ERROR_RET_BOOL
+
+ return true;
+}
+
+bool KviKTorrentDCOPInterface::startAll()
+{
+ if (!voidRetIntDCOPCall("KTorrent", "startAll(int)", 3))
+ ERROR_RET_BOOL
+
+ return true;
+}
+
+bool KviKTorrentDCOPInterface::stopAll()
+{
+ if (!voidRetIntDCOPCall("KTorrent", "stopAll(int)", 3))
+ ERROR_RET_BOOL
+
+ return true;
+}
+
+int KviKTorrentDCOPInterface::count()
+{
+ return m_ti.size();
+}
+
+float KviKTorrentDCOPInterface::speedUp()
+{
+ KviQCStringList ret;
+ if (!qcstringListRetVoidDCOPCall("KTorrent", "getInfo()", ret))
+ ERROR_RET_NUM
+
+ QStringList tmp = QStringList::split(" ", ret[2]);
+ if (tmp.size() != 8)
+ ERROR_RET_NUM
+
+ bool ok;
+ float f = tmp[6].toFloat(&ok);
+ if (!ok)
+ ERROR_RET_NUM
+
+ return f;
+}
+
+float KviKTorrentDCOPInterface::speedDown()
+{
+ KviQCStringList ret;
+ if (!qcstringListRetVoidDCOPCall("KTorrent", "getInfo()", ret))
+ ERROR_RET_NUM
+
+ QStringList tmp = QStringList::split(" ", ret[2]);
+ if (tmp.size() != 8)
+ ERROR_RET_NUM
+
+ bool ok;
+ float f = tmp[2].toFloat(&ok);
+ if (!ok)
+ ERROR_RET_NUM
+
+ return f;
+}
+
+float KviKTorrentDCOPInterface::trafficUp()
+{
+ KviQCStringList ret;
+ if (!qcstringListRetVoidDCOPCall("KTorrent", "getInfo()", ret))
+ ERROR_RET_NUM
+
+ QStringList tmp = QStringList::split(" ", ret[1]);
+ if (tmp.size() != 8)
+ ERROR_RET_NUM
+
+ float f;
+ if (!makeSize(f, tmp[6], tmp[7]))
+ ERROR_RET_NUM
+
+ return f;
+}
+
+float KviKTorrentDCOPInterface::trafficDown()
+{
+ KviQCStringList ret;
+ if (!qcstringListRetVoidDCOPCall("KTorrent", "getInfo()", ret))
+ ERROR_RET_NUM
+
+ QStringList tmp = QStringList::split(" ", ret[1]);
+ if (tmp.size() != 8)
+ ERROR_RET_NUM
+
+ float f;
+ if (!makeSize(f, tmp[2], tmp[3]))
+ ERROR_RET_NUM
+
+ return f;
+}
+
+bool KviKTorrentDCOPInterface::makeTorrentInfo(TorrentInfo &ti, const KviQCStringList &ret)
+{
+ if (ret.size() != 10)
+ ERROR_RET_BOOL
+
+ ti.name = ret[0];
+ if (ret[1] == "Seeding")
+ ti.state = "Seeding";
+ else
+ if (ret[1] == "Stalled")
+ ti.state = "Stalled";
+ else
+ if (ret[1] == "Downloading")
+ ti.state = "Downloading";
+ else
+ ti.state = "Stopped";
+
+
+ QStringList tmp;
+ tmp = QStringList::split(" ", ret[2]);
+ if (tmp.size()!=2 || !makeSize(ti.trafficDown, tmp[0], tmp[1]))
+ ERROR_RET_BOOL
+
+ tmp = QStringList::split(" ", ret[3]);
+ if (tmp.size()!=2 || !makeSize(ti.size, tmp[0], tmp[1]))
+ ERROR_RET_BOOL
+
+ tmp = QStringList::split(" ", ret[4]);
+ if (tmp.size()!=2 || !makeSize(ti.trafficUp, tmp[0], tmp[1]))
+ ERROR_RET_BOOL
+
+
+ bool ok;
+ tmp = QStringList::split(" ", ret[5]);
+ if (tmp.size()!=2)
+ ERROR_RET_BOOL
+ ti.speedDown = tmp[0].toFloat(&ok);
+ if (!ok)
+ ERROR_RET_BOOL
+
+ tmp = QStringList::split(" ", ret[6]);
+ if (tmp.size()!=2)
+ ERROR_RET_BOOL
+ ti.speedUp = tmp[0].toFloat(&ok);
+ if (!ok)
+ ERROR_RET_BOOL
+
+
+ // torrent name, status, downloaded, size, uploaded, down spd, up spd, none, peers, % complete
+ ti.peers = ret[8].toInt(&ok);
+ if (!ok)
+ ERROR_RET_BOOL
+
+ tmp = QStringList::split(" ", ret[9]);
+ if (tmp.size()!=2)
+ ERROR_RET_BOOL
+ ti.percent = tmp[0].toFloat(&ok);
+ if (!ok)
+ ERROR_RET_BOOL
+
+ return true;
+}
+
+int KviKTorrentDCOPInterface::maxUploadSpeed()
+{
+ int ret;
+ if (!intRetVoidDCOPCall("KTorrent", "maxUploadRate()", ret))
+ {
+ ERROR_MSG
+ return -1;
+ }
+ return ret;
+}
+
+int KviKTorrentDCOPInterface::maxDownloadSpeed()
+{
+ int ret;
+ if (!intRetVoidDCOPCall("KTorrent", "maxDownloadRate()", ret))
+ {
+ ERROR_MSG
+ return -1;
+ }
+ return ret;
+}
+
+bool KviKTorrentDCOPInterface::setMaxUploadSpeed(int kbytes_per_sec)
+{
+ if (!voidRetIntDCOPCall("KTorrent", "setMaxUploadSpeed(int)", kbytes_per_sec))
+ ERROR_RET_BOOL
+ return true;
+}
+
+bool KviKTorrentDCOPInterface::setMaxDownloadSpeed(int kbytes_per_sec)
+{
+ if (!voidRetIntDCOPCall("KTorrent", "setMaxDownloadSpeed(int)", kbytes_per_sec))
+ ERROR_RET_BOOL
+ return true;
+}
+
+
+#include "tc_ktorrentdcopinterface.moc"
+
+#endif // COMPILE_KDE_SUPPORT
+
diff --git a/src/modules/torrent/tc_ktorrentdcopinterface.h b/src/modules/torrent/tc_ktorrentdcopinterface.h
new file mode 100644
index 00000000..8f39810f
--- /dev/null
+++ b/src/modules/torrent/tc_ktorrentdcopinterface.h
@@ -0,0 +1,131 @@
+#ifndef _TC_KTORRENTDCOPINTERFACE_H_
+#define _TC_KTORRENTDCOPINTERFACE_H_
+
+//=============================================================================
+//
+// DCOP interface for KTorrent client.
+//
+// File : torr_ktorrentdcopinterface.h
+// Creation date : Fri Jan 1 15:42:25 2007 GMT by Alexander Stillich
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2005 Szymon Stefanek (pragma at kvirc dot net)
+// Copyright (C) 2007 Alexander Stillich (torque at pltn dot org)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) 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.
+//
+//=============================================================================
+
+
+#include "tc_interface.h"
+
+#ifdef COMPILE_KDE_SUPPORT
+
+#include <kvi_dcophelper.h>
+
+// DCOP interface to KTorrent. this has 'DCOP' in its name
+// because in kde4 there will be a D-BUS interface.
+class KviKTorrentDCOPInterface : public KviTorrentInterface,
+ private KviDCOPHelper
+{
+ Q_OBJECT
+
+public:
+
+ KviKTorrentDCOPInterface();
+ virtual ~KviKTorrentDCOPInterface();
+
+ virtual int detect();
+
+ virtual int count();
+
+ virtual bool start(int i);
+ virtual bool stop(int i);
+ virtual bool announce(int i);
+ virtual QString state(int i);
+ virtual QString name(int i);
+
+ virtual int fileCount(int i);
+ virtual QString fileName(int i, int file);
+ virtual QString filePriority(int i, int file);
+ virtual bool setFilePriority(int i, int file, const QString &prio);
+
+ virtual bool startAll();
+ virtual bool stopAll();
+
+ virtual int maxUploadSpeed();
+ virtual int maxDownloadSpeed();
+
+ virtual bool setMaxUploadSpeed(int kbytes_per_sec);
+ virtual bool setMaxDownloadSpeed(int kbytes_per_sec);
+
+ virtual float speedUp();
+ virtual float speedDown();
+
+ virtual float trafficUp();
+ virtual float trafficDown();
+
+private slots:
+
+ // polls client and extracts information.
+ // this is done because the order of torrents returned changes
+ // each time a torrent's state changes.
+ // we want to present a consistent list (in terms of indices) to
+ // the user, so we extract the info and sort it by name.
+ // otherwise the user would have a hard time figuring out what's
+ // going on. we could sort each time a function working with
+ // torrents is called, but this would be horribly slow ...
+ void slotTimer();
+
+private:
+
+ struct TorrentInfo
+ {
+ // internal number
+ int num;
+ // name displayed in ktorrent
+ QString name;
+ // state of torrent
+ QString state;
+ // bytes
+ float size;
+ // bytes
+ float trafficUp;
+ // bytes
+ float trafficDown;
+ // KB/s
+ float speedUp;
+ // KB/s
+ float speedDown;
+ // percent complete
+ float percent;
+ // number of peers
+ int peers;
+
+ bool operator<(const TorrentInfo &ti) { return name < ti.name; }
+ };
+
+ QValueList<TorrentInfo> m_ti;
+
+private:
+
+ bool makeTorrentInfo(TorrentInfo &ti, const KviQCStringList &ret);
+};
+
+TORR_DECLARE_DESCRIPTOR(KviKTorrentDCOPInterface)
+
+#endif // COMPILE_KDE_SUPPORT
+
+#endif // _TC_KTORRENTDCOPINTERFACE_H_
diff --git a/src/modules/torrent/tc_statusbarapplet.cpp b/src/modules/torrent/tc_statusbarapplet.cpp
new file mode 100644
index 00000000..5d23a299
--- /dev/null
+++ b/src/modules/torrent/tc_statusbarapplet.cpp
@@ -0,0 +1,69 @@
+#include "qtimer.h"
+#include "kvi_locale.h"
+#include "kvi_iconmanager.h"
+#include "tc_interface.h"
+#include "tc_statusbarapplet.h"
+
+KviTorrentStatusBarApplet::KviTorrentStatusBarApplet(KviStatusBar *parent, KviStatusBarAppletDescriptor *desc)
+ : KviStatusBarApplet(parent, desc)
+{
+ QTimer *timer = new QTimer(this);
+ connect(timer, SIGNAL(timeout()), this, SLOT(update()));
+ timer->start(250, FALSE);
+// updateDisplay();
+//
+ setText("torrent client");
+}
+
+KviTorrentStatusBarApplet::~KviTorrentStatusBarApplet()
+{
+}
+
+static KviStatusBarApplet *CreateTorrentClientApplet(KviStatusBar *bar, KviStatusBarAppletDescriptor *desc)
+{
+ debug("CreateTorrentClientApplet");
+ return new KviTorrentStatusBarApplet(bar, desc);
+}
+
+void KviTorrentStatusBarApplet::selfRegister(KviStatusBar *bar)
+{
+ KviStatusBarAppletDescriptor *d = new KviStatusBarAppletDescriptor(
+ __tr2qs("Torrent Client"),
+ "torrentapplet",
+ CreateTorrentClientApplet,
+ "torrent", *(g_pIconManager->getSmallIcon(KVI_SMALLICON_AWAY)));
+
+ bar->registerAppletDescriptor(d);
+}
+
+QString formatSize(float sz)
+{
+ if (sz >= 1024.0f*1024.0f*1024.0f)
+ return QString("%1 GB").arg(sz / (1024.0f*1024.0f*1024.0f), 2, 'f', 2);
+ if (sz >= 1024.0f*1024.0f)
+ return QString("%1 MB").arg(sz / (1024.0f*1024.0f), 2, 'f', 2);
+ if (sz >= 1024.0f)
+ return QString("%1 KB").arg(sz / 1024.0f, 2, 'f', 2);
+ return QString("%1 B").arg(sz, 2, 'f', 2);
+}
+
+void KviTorrentStatusBarApplet::update()
+{
+ if (KviTorrentInterface::selected())
+ {
+ QString msg = QString("up: %1 K/s (%2), dn: %3 K/s (%4)")
+ .arg(KviTorrentInterface::selected()->speedUp(), 2)
+ .arg(formatSize(KviTorrentInterface::selected()->trafficUp()))
+ .arg(KviTorrentInterface::selected()->speedDown(), 2)
+ .arg(formatSize(KviTorrentInterface::selected()->trafficDown()));
+
+ setText(msg);
+
+ } else
+ {
+ setText(__tr2qs_ctx("No client selected!", "torrent"));
+ }
+}
+
+#include "tc_statusbarapplet.moc"
+
diff --git a/src/modules/torrent/tc_statusbarapplet.h b/src/modules/torrent/tc_statusbarapplet.h
new file mode 100644
index 00000000..03dd6d0d
--- /dev/null
+++ b/src/modules/torrent/tc_statusbarapplet.h
@@ -0,0 +1,26 @@
+#ifndef _TC_STATUSBARAPPLET_H_
+#define _TC_STATUSBARAPPLET_H_
+
+#include "kvi_statusbar.h"
+#include "kvi_statusbarapplet.h"
+
+// TODO: check if it gets destroyed
+// TODO: proper icon!
+class KviTorrentStatusBarApplet : public KviStatusBarApplet
+{
+ Q_OBJECT
+
+public:
+
+ KviTorrentStatusBarApplet(KviStatusBar *parent, KviStatusBarAppletDescriptor *desc);
+ virtual ~KviTorrentStatusBarApplet();
+
+ static void selfRegister(KviStatusBar *bar);
+
+private slots:
+
+ void update();
+
+};
+
+#endif // _TC_STATUSBARAPPLET_H_
diff --git a/src/modules/url/Makefile.am b/src/modules/url/Makefile.am
new file mode 100644
index 00000000..c2d88957
--- /dev/null
+++ b/src/modules/url/Makefile.am
@@ -0,0 +1,23 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+SUBDIRS = caps
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkviurl.la
+
+libkviurl_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+libkviurl_la_SOURCES = libkviurl.cpp
+libkviurl_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+
+noinst_HEADERS= libkviurl.h icons.h
+
+%.moc: %.h
+ $(SS_QT_MOC) $< -o $@
+
+libkviurl.cpp: libkviurl.moc
diff --git a/src/modules/url/caps/Makefile.am b/src/modules/url/caps/Makefile.am
new file mode 100644
index 00000000..231fa79c
--- /dev/null
+++ b/src/modules/url/caps/Makefile.am
@@ -0,0 +1,9 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+tmpdir = $(pluglibdir)/caps/action/
+
+tmp_DATA= url
+
+EXTRA_DIST = $(tmp_DATA)
diff --git a/src/modules/url/caps/url b/src/modules/url/caps/url
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/modules/url/caps/url
diff --git a/src/modules/url/icons.h b/src/modules/url/icons.h
new file mode 100644
index 00000000..20cc7823
--- /dev/null
+++ b/src/modules/url/icons.h
@@ -0,0 +1,554 @@
+const char * url_icon_xpm[] = {
+"16 16 104 2",
+" c None",
+". c #FFFFFF",
+"+ c #F7F7F7",
+"@ c #EFEFEF",
+"# c #E7E7E7",
+"$ c #DFDFDF",
+"% c #D7D7D7",
+"& c #CFCFCF",
+"* c #C7C7C7",
+"= c #BFBFBF",
+"- c #B7B7B7",
+"; c #AFAFAF",
+"> c #A7A7A7",
+", c #9F9F9F",
+"' c #979797",
+") c #8F8F8F",
+"! c #878787",
+"~ c #000000",
+"{ c #090909",
+"] c #121212",
+"^ c #1B1B1B",
+"/ c #242424",
+"( c #2D2D2D",
+"_ c #363636",
+": c #3F3F3F",
+"< c #484848",
+"[ c #515151",
+"} c #5B5B5B",
+"| c #646464",
+"1 c #6D6D6D",
+"2 c #767676",
+"3 c #7F7F7F",
+"4 c #C0C0C0",
+"5 c #AEAEAE",
+"6 c #A5A5A5",
+"7 c #9B9B9B",
+"8 c #929292",
+"9 c #898989",
+"0 c #777777",
+"a c #A7BED2",
+"b c #97C5EC",
+"c c #95C8F4",
+"d c #96BDE0",
+"e c #929DA7",
+"f c #8B96A0",
+"g c #90B7D9",
+"h c #90BDE4",
+"i c #798FA3",
+"j c #888888",
+"k c #6F6F6F",
+"l c #8AACCA",
+"m c #738493",
+"n c #5A5A5A",
+"o c #919191",
+"p c #676767",
+"q c #A3A8AD",
+"r c #94BBDE",
+"s c #8CB3D5",
+"t c #66727B",
+"u c #9A9A9A",
+"v c #5F5F5F",
+"w c #99AAB8",
+"x c #91B3D0",
+"y c #A3A3A3",
+"z c #575757",
+"A c #94B6D3",
+"B c #8697A6",
+"C c #7EA0BD",
+"D c #3E3E3E",
+"E c #ADADAD",
+"F c #4F4F4F",
+"G c #92B9DC",
+"H c #797F83",
+"I c #636363",
+"J c #748A9E",
+"K c #728EA7",
+"L c #353535",
+"M c #B6B6B6",
+"N c #474747",
+"O c #85ADCF",
+"P c #515C65",
+"Q c #2C2C2C",
+"R c #91BEE5",
+"S c #5F6B74",
+"T c #81A9CB",
+"U c #222222",
+"V c #C8C8C8",
+"W c #373737",
+"X c #7A8B9A",
+"Y c #8FBCE3",
+"Z c #87AFD1",
+"` c #3F4549",
+" . c #191919",
+".. c #D1D1D1",
+"+. c #2F2F2F",
+"@. c #101010",
+"#. c #DADADA",
+"$. c #272727",
+"%. c #060606",
+"&. c #E3E3E3",
+"*. c #1F1F1F",
+"=. c #ECECEC",
+"-. c #171717",
+";. c #0F0F0F",
+". + @ # $ % & * = - ; > , ' ) ! ",
+"+ ~ { ] ^ / ( _ : < [ } | 1 2 3 ",
+"@ { 4 4 4 - 5 6 7 8 9 3 2 1 3 0 ",
+"# ] 4 4 a b c d e f g c h i j k ",
+"$ ^ 4 - 5 c c 8 9 3 l c m n o p ",
+"% / - 5 q c r 9 3 2 s c t [ u v ",
+"& ( 5 6 w c x 3 2 1 c c [ < y z ",
+"* _ 6 7 A c B 2 1 m c C < D E F ",
+"= : 7 8 G c H 1 I J c K D L M N ",
+"- < 8 9 c c 1 I n O c P L Q = : ",
+"; [ 9 3 R c I n S c T L Q U V W ",
+"> } 3 2 X Y Z C c T ` Q U ...+.",
+", | 2 1 I n [ < D L Q U .@.#.$.",
+"' 1 1 I n [ < D L Q U .@.%.&.*.",
+") 2 3 j o u y E M = V ..#.&.=.-.",
+"! 3 0 k p v z F N : W +.$.*.-.;."};
+
+const char * url_toolbar_xpm[] = {
+"32 32 38 1",
+" c None",
+". c #000000",
+"+ c #FFFBFF",
+"@ c #B6C3FF",
+"# c #B6C3A6",
+"$ c #FFFFFF",
+"% c #836977",
+"& c #710818",
+"* c #20000E",
+"= c #710018",
+"- c #B60818",
+"; c #710000",
+"> c #A36B7E",
+", c #20050E",
+"' c #FFDFCF",
+") c #B60018",
+"! c #B60800",
+"~ c #B60000",
+"{ c #B62018",
+"] c #B64118",
+"^ c #FF2018",
+"/ c #B62000",
+"( c #B66B7E",
+"_ c #040001",
+": c #FF4118",
+"< c #B66908",
+"[ c #58321C",
+"} c #FF6918",
+"| c #B64100",
+"1 c #FFC3A6",
+"2 c #20252F",
+"3 c #FF4100",
+"4 c #EA6B7E",
+"5 c #713051",
+"6 c #A25E06",
+"7 c #B6727E",
+"8 c #B64151",
+"9 c #4A3211",
+"................+@..............",
+"................++..............",
+"................++..............",
+"................+++.............",
+"................+++.............",
+"................+++.............",
+"................#++@...#$#......",
+"................@+++..@+++@.....",
+"................#+++..+++++.....",
+"................@++++#+++++%....",
+"................#++++++++++#....",
+"......++@.......++++++++++$.....",
+".....++++@......++++++.+++......",
+".&..@++++++....+++++++..........",
+"&&&*++++++++...+++++++..........",
+"&&=++++++++++.+++++++++.........",
+"-;>++&&.#++++++++++++++.........",
+";-+>=&&&,'+++++++++++++#........",
+");-;=;&&&*#++++++$$.#+++........",
+"!-~-)-=-&&,+++++++...+++........",
+".{{!-;);-;&=#+++++@...++#.......",
+"..]^!-~-;-=&='+++++...@++.......",
+"...{{/{~);-;=;>+++++...++.......",
+".....{/^!-~-)-=#++++@...+@......",
+"......{/^!-!-;);(++++_...+......",
+"........]:/^!-~-;#+++@,..@......",
+".........<:/{!-~);(+++&*,.......",
+"..........[}|:/^!-~1+++-&&......",
+"............}|:/^!-~(++>&;&2....",
+".............[3:|:/^!4++;-=5....",
+"...............<6|:/{!7+#;-;8...",
+"................9}|}|:/1+-~-)..."};
+
+const char * urlhigh_toolbar_xpm[] = {
+"32 32 33 1",
+" c None",
+". c #000000",
+"+ c #D4FF00",
+"@ c #E1FF3A",
+"# c #710818",
+"$ c #20000E",
+"% c #710018",
+"& c #B60818",
+"* c #710000",
+"= c #20050E",
+"- c #B60018",
+"; c #B60800",
+"> c #B60000",
+", c #B62018",
+"' c #B64118",
+") c #FF2018",
+"! c #B62000",
+"~ c #A36B7E",
+"{ c #B66B7E",
+"] c #040001",
+"^ c #FF4118",
+"/ c #B66908",
+"( c #58321C",
+"_ c #FF6918",
+": c #B64100",
+"< c #20252F",
+"[ c #FF4100",
+"} c #EA6B7E",
+"| c #713051",
+"1 c #A25E06",
+"2 c #B6727E",
+"3 c #B64151",
+"4 c #4A3211",
+"................+@..............",
+"................++..............",
+"................++..............",
+"................+++.............",
+"................+++.............",
+"................+++.............",
+"................@++@...@+@......",
+"................@+++..@+++@.....",
+"................@+++..+++++.....",
+"................@++++@+++++@....",
+"................@++++++++++@....",
+"......++@.......+++++++++++.....",
+".....++++@......++++++.+++......",
+".#..@++++++....+++++++..........",
+"###$++++++++...+++++++..........",
+"##%++++++++++.+++++++++.........",
+"&*@++##.@++++++++++++++.........",
+"*&@@%###=@+++++++++++++@........",
+"-*&*%*###$@++++++++.@+++........",
+";&>&-&%&##=+++++++...+++........",
+".,,;&*-*&*#%@+++++@...++@.......",
+"..');&>&*&%#%@+++++...@++.......",
+"...,,!,>-*&*%*~+++++...++.......",
+".....,!);&>&-&%@++++@...+@......",
+"......,!);&;&*-*{++++]...@......",
+"........'^!);&>&*@@++@=..@......",
+"........./^!,;&>-*{+++#$=.......",
+"..........(_:^!);&>@+++&##......",
+"............_:^!);&>{++~#*#<....",
+".............([^:^!);}++*&%|....",
+".............../1:^!,;2+@*&*3...",
+"................4_:_:^!@@&>&-..."};
+
+const char * urlconf_toolbar_xpm[] = {
+"32 32 256 2",
+" c None",
+". c #000000",
+"+ c #FFFBFF",
+"@ c #B6C3FF",
+"# c #B6C3A6",
+"$ c #FFFFFF",
+"% c #836977",
+"& c #710818",
+"* c #F8F5F8",
+"= c #212121",
+"- c #0F0F0F",
+"; c #060606",
+"> c #20000E",
+", c #EAE7EA",
+"' c #D3D2D3",
+") c #E3E1E3",
+"! c #FCF9FC",
+"~ c #BEBCBE",
+"{ c #858585",
+"] c #545454",
+"^ c #323232",
+"/ c #010101",
+"( c #710018",
+"_ c #FEFAFE",
+": c #C3C1C3",
+"< c #9E9E9E",
+"[ c #B7B7B7",
+"} c #A5A5A5",
+"| c #C0BFC0",
+"1 c #EEECEE",
+"2 c #848384",
+"3 c #757575",
+"4 c #828282",
+"5 c #4A4A4A",
+"6 c #83C6C6",
+"7 c #B60818",
+"8 c #710000",
+"9 c #A36B7E",
+"0 c #FCF8FC",
+"a c #767576",
+"b c #272727",
+"c c #3D3D3D",
+"d c #707070",
+"e c #9B9B9B",
+"f c #ABABAB",
+"g c #9D9D9D",
+"h c #8A8A8A",
+"i c #999999",
+"j c #9E9D9E",
+"k c #CDCBCD",
+"l c #FBF7FB",
+"m c #F1EEF1",
+"n c #EEEBEE",
+"o c #A46D80",
+"p c #703441",
+"q c #242020",
+"r c #353535",
+"s c #888888",
+"t c #A3A3A3",
+"u c #949494",
+"v c #959595",
+"w c #A3A1A3",
+"x c #A09FA0",
+"y c #868586",
+"z c #FAF7FA",
+"A c #B60018",
+"B c #720303",
+"C c #B91221",
+"D c #770C0C",
+"E c #883446",
+"F c #948888",
+"G c #6A6A6A",
+"H c #6D6D6D",
+"I c #9F9F9F",
+"J c #AAAAAA",
+"K c #A1A1A1",
+"L c #A4A4A4",
+"M c #A0A0A0",
+"N c #939393",
+"O c #898989",
+"P c #6B6B6B",
+"Q c #C9C9C9",
+"R c #B60800",
+"S c #B1303C",
+"T c #8B5151",
+"U c #A06D72",
+"V c #B28D91",
+"W c #B6B3B3",
+"X c #9C9C9C",
+"Y c #B1B1B1",
+"Z c #B3B3B3",
+"` c #AFAFAF",
+" . c #A6A59E",
+".. c #B5A874",
+"+. c #B3A46A",
+"@. c #949287",
+"#. c #919191",
+"$. c #939293",
+"%. c #171717",
+"&. c #A85752",
+"*. c #686463",
+"=. c #8C8C8C",
+"-. c #BBBBBB",
+";. c #C2C2C2",
+">. c #BEBEBE",
+",. c #BDBDBD",
+"'. c #ADACAC",
+"). c #8F7E3D",
+"!. c #D1B440",
+"~. c #CDAF39",
+"{. c #BDA64A",
+"]. c #9F9E98",
+"^. c #989898",
+"/. c #7F7F7F",
+"(. c #B7C2F5",
+"_. c #414141",
+":. c #525151",
+"<. c #616161",
+"[. c #7A7A7A",
+"}. c #B6B6B6",
+"|. c #C3C3C3",
+"1. c #85847F",
+"2. c #A58F3B",
+"3. c #E5C752",
+"4. c #D7BA47",
+"5. c #CBAE3C",
+"6. c #9F9981",
+"7. c #A2A2A2",
+"8. c #7E7E7E",
+"9. c #CFCDCF",
+"0. c #0D0D0D",
+"a. c #2C2C2C",
+"b. c #141414",
+"c. c #100C0C",
+"d. c #505050",
+"e. c #C6C6C6",
+"f. c #CACACA",
+"g. c #A9A9A7",
+"h. c #5A5027",
+"i. c #D4BB58",
+"j. c #E8CB57",
+"k. c #D0B651",
+"l. c #99968B",
+"m. c #979797",
+"n. c #6F6F6F",
+"o. c #070707",
+"p. c #202020",
+"q. c #2F2F2F",
+"r. c #383838",
+"s. c #585858",
+"t. c #7C7C7C",
+"u. c #969696",
+"v. c #CECECE",
+"w. c #C3C2C2",
+"x. c #888784",
+"y. c #44433C",
+"z. c #89805E",
+"A. c #8F8D83",
+"B. c #8F8F8F",
+"C. c #3A3A3A",
+"D. c #9DA4C6",
+"E. c #343434",
+"F. c #575757",
+"G. c #909090",
+"H. c #D0D0D0",
+"I. c #D5D5D5",
+"J. c #CBCBCB",
+"K. c #BFBFBF",
+"L. c #C4C4C4",
+"M. c #AEAEAE",
+"N. c #BABABA",
+"O. c #B0B0B0",
+"P. c #666666",
+"Q. c #2D2D2D",
+"R. c #C0BEC0",
+"S. c #040001",
+"T. c #020202",
+"U. c #373737",
+"V. c #363636",
+"W. c #565656",
+"X. c #D4D4D4",
+"Y. c #C1C1C1",
+"Z. c #C7C7C7",
+"`. c #C5C5C5",
+" + c #C0C0C0",
+".+ c #B2B2B2",
+"++ c #696968",
+"@+ c #B8B6B8",
+"#+ c #F2EEF2",
+"$+ c #FDF9FD",
+"%+ c #20050E",
+"&+ c #404040",
+"*+ c #4D4D4D",
+"=+ c #646464",
+"-+ c #5F5F5F",
+";+ c #5D5D5D",
+">+ c #929292",
+",+ c #8D8A8A",
+"'+ c #AA808A",
+")+ c #080808",
+"!+ c #424242",
+"~+ c #2E2E2E",
+"{+ c #1A1A1A",
+"]+ c #313131",
+"^+ c #3C3C3C",
+"/+ c #4B4B4B",
+"(+ c #C8C8C8",
+"_+ c #A6A6A6",
+":+ c #484848",
+"<+ c #633636",
+"[+ c #FFC7AB",
+"}+ c #303030",
+"|+ c #3B3B3B",
+"1+ c #1D1D1D",
+"2+ c #282828",
+"3+ c #393939",
+"4+ c #7D7D7D",
+"5+ c #262423",
+"6+ c #1B1A19",
+"7+ c #191919",
+"8+ c #4B2B2E",
+"9+ c #BC1515",
+"0+ c #B66B7E",
+"a+ c #20252F",
+"b+ c #040404",
+"c+ c #0E0E0E",
+"d+ c #0B0B0B",
+"e+ c #252525",
+"f+ c #403C3B",
+"g+ c #9F5036",
+"h+ c #743B2F",
+"i+ c #1A1918",
+"j+ c #342A28",
+"k+ c #974736",
+"l+ c #FF261E",
+"m+ c #EA6B7E",
+"n+ c #713051",
+"o+ c #030303",
+"p+ c #333333",
+"q+ c #090909",
+"r+ c #BA751F",
+"s+ c #866132",
+"t+ c #9E542B",
+"u+ c #FE4821",
+"v+ c #B62000",
+"w+ c #B62018",
+"x+ c #B6727E",
+"y+ c #B64151",
+"z+ c #242424",
+"A+ c #2A2A2A",
+"B+ c #4A3211",
+"C+ c #FF6918",
+"D+ c #B64100",
+"E+ c #FF4118",
+"F+ c #FFC3A6",
+"G+ c #B60000",
+". . . . . . . . . . . . . . . . + @ . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . + + . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . + + . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . + + + . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . + + + . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . + + + . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . # + + @ . . . # $ # . . . . . . ",
+". . . . . . . . . . . . . . . . @ + + + . . @ + + + @ . . . . . ",
+". . . . . . . . . . . . . . . . # + + + . . + + + + + . . . . . ",
+". . . . . . . . . . . . . . . . @ + + + + # + + + + + % . . . . ",
+". . . . . . . . . . . . . . . . # + + + + + + + + + + # . . . . ",
+". . . . . . + + @ . . . . . . . + + + + + + + + + + $ . . . . . ",
+". . . . . + + + + @ . . . . . . + + + + + + . + + + . . . . . . ",
+". & . . @ + + + + + * = - ; . + + + + + + + . . . . . . . . . . ",
+"& & & > + , ' ) ! + ~ { ] ^ / + + + + + + + . . . . . . . . . . ",
+"& & ( _ : < [ } | 1 2 3 4 5 + 6 + + + + + + + . . . . . . . . . ",
+"7 8 9 0 a b c d e f g h i j k l m n + + + + + . . . . . . . . . ",
+"8 7 + o p q r c s t u e u v 4 w x y z + + + + # . . . . . . . . ",
+"A B C D E F G H I J K L M I N h O P Q / # + + + . . . . . . . . ",
+"R S T U V W X i Y Z ` ...+.@.#.v $.%.. . + + + . . . . . . . . ",
+". &.*.=.-.;.;.>.,.,.'.).!.~.{.].^./.(.. . . + + # . . . . . . . ",
+". _.:.<.] 5 [.}.|.>.1.2.3.4.5.6.7.8.9.b 0.. @ + + . . . . . . . ",
+". a.b.c.%.d.g e.f.f.g.h.i.j.k.l.m.X ^.n.= . . + + . . . . . . . ",
+". o.p.q.r.s.t.u.f.v.w.x.y.z.A.B.J 8.C.r.D.. . . + @ . . . . . . ",
+". . . ; E.c F.G.H.I.J.K.>.L.M.N.O.P.= Q.R.S.. . . + . . . . . . ",
+". . . T.U.V.W.L X.K Y.Z.`.Q +Y..+++@+#+$+@ %+. . @ . . . . . . ",
+". . / p.&+*+=+-+;+r.F.>+Z.,.I H B.,+'++ + + & > %+. . . . . . . ",
+". . )+r ^ !+5 ~+{+]+^+/+(+_+r ~+]+:+<+[++ + + 7 & & . . . . . . ",
+". . / a.}+r |+U.%.1+2+3+4+d 5+6+7+}+8+9+0++ + 9 & 8 & a+. . . . ",
+". . . b+a.}+c+d+2+}+e+^+^+f+g+h+i+j+k+l+R m++ + 8 7 ( n+. . . . ",
+". . . . T.o+. . T.2+q.E.p+r.q+r+s+t+u+v+w+R x++ # 8 7 8 y+. . . ",
+". . . . . . . . . z+A+p.1+}+/ . B+C+D+C+D+E+v+F++ 7 G+7 A . . . "};
diff --git a/src/modules/url/libkviurl.cpp b/src/modules/url/libkviurl.cpp
new file mode 100644
index 00000000..16430c67
--- /dev/null
+++ b/src/modules/url/libkviurl.cpp
@@ -0,0 +1,910 @@
+//
+// This file is part of the KVIrc irc client distribution
+// Copyright (C) 1999-2002 Andrea Parrella (yap@kvirc.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 opinion) 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.
+//
+
+#include "kvi_styled_controls.h"
+#include "kvi_module.h"
+#include "libkviurl.h"
+#include "kvi_app.h"
+#include "kvi_frame.h"
+#include "kvi_kvs_eventmanager.h"
+#include "kvi_tal_popupmenu.h"
+
+#include "kvi_menubar.h"
+#include "kvi_internalcmd.h"
+#include "kvi_iconmanager.h"
+#include "kvi_action.h"
+#include "kvi_actionmanager.h"
+#include "kvi_taskbar.h"
+#include "icons.h"
+#include "kvi_pointerlist.h"
+#include <qfiledialog.h>
+#include <qmessagebox.h>
+#include <qcursor.h>
+#include <qdatetime.h>
+
+#ifdef COMPILE_USE_QT4
+ #include <q3textstream.h>
+ #include <QTextStream>
+#endif
+
+static QPixmap * g_pUrlIconPixmap = 0;
+static KviUrlAction * g_pUrlAction = 0;
+
+typedef struct _UrlDlgList
+{
+ UrlDialog *dlg;
+ int menu_id;
+} UrlDlgList;
+
+const char *g_pUrlListFilename = "/list.kviurl";
+const char *g_pBanListFilename = "/list.kviban";
+
+KviPointerList<KviUrl> *g_pList;
+KviPointerList<UrlDlgList> *g_pUrlDlgList;
+KviPointerList<KviStr> *g_pBanList;
+ConfigDialog *g_pConfigDialog;
+
+KviStr szConfigPath;
+
+void saveUrlList();
+void loadUrlList();
+void saveBanList();
+void loadBanList();
+UrlDlgList * findFrame();
+bool urllist();
+void url_module_help();
+
+
+#define KVI_URL_EXTENSION_NAME "URL module extenstion"
+
+static KviModuleExtension * url_extension_alloc(KviModuleExtensionAllocStruct * s)
+{
+ urllist();
+ return 0;
+}
+
+
+KviUrlAction::KviUrlAction(QObject * pParent)
+: KviKvsAction(pParent,
+ "url.list",
+ "url.list",
+ __tr2qs("Show URL List"),
+ __tr2qs("Shows the URL list window"),
+ KviActionManager::categoryGeneric())
+{
+ m_pBigIcon = new QPixmap(url_toolbar_xpm);
+ m_pSmallIcon = new QPixmap(url_icon_xpm);
+}
+
+KviUrlAction::~KviUrlAction()
+{
+ delete m_pBigIcon;
+ delete m_pSmallIcon;
+}
+
+QPixmap * KviUrlAction::bigIcon()
+{
+ return m_pBigIcon;
+}
+
+QPixmap * KviUrlAction::smallIcon()
+{
+ return m_pSmallIcon;
+}
+
+// ---------------------------- CLASS URLDIALOG ------------------------begin //
+
+UrlDialog::UrlDialog(KviPointerList<KviUrl> *g_pList)
+:KviWindow(KVI_WINDOW_TYPE_TOOL,g_pFrame,"URL List")
+{
+ m_pMenuBar = new KviTalMenuBar(this,"url menu");
+ m_pUrlList = new KviTalListView(this);
+ //m_pUrlList = new KviListView(this,"list");
+ KviConfig cfg(szConfigPath.ptr(),KviConfig::Read);
+
+ KviTalPopupMenu *pop;
+
+ pop = new KviTalPopupMenu(this);
+ pop->insertItem(__tr2qs("&Configure"),this,SLOT(config()));
+ pop->insertItem(__tr2qs("&Help"),this,SLOT(help()));
+ pop->insertItem(__tr2qs("Clo&se"),this,SLOT(close_slot()));
+ m_pMenuBar->insertItem(__tr2qs("&Module"),pop);
+
+ pop = new KviTalPopupMenu(this);
+ pop->insertItem(__tr2qs("&Load"),this,SLOT(loadList()));
+ pop->insertItem(__tr2qs("&Save"),this,SLOT(saveList()));
+ pop->insertItem(__tr2qs("&Clear"),this,SLOT(clear()));
+ m_pMenuBar->insertItem(__tr2qs("&List"),pop);
+
+ m_pUrlList->setShowSortIndicator(true);
+ m_pUrlList->addColumn(__tr2qs("URL"));
+ m_pUrlList->addColumn(__tr2qs("Window"));
+ m_pUrlList->addColumn(__tr2qs("Count"));
+ m_pUrlList->addColumn(__tr2qs("Timestamp"));
+
+ cfg.setGroup("colsWidth");
+ m_pUrlList->setColumnWidth(0,cfg.readIntEntry("Url",170));
+ m_pUrlList->setColumnWidth(1,cfg.readIntEntry("Window",130));
+ m_pUrlList->setColumnWidth(2,cfg.readIntEntry("Count",70));
+ m_pUrlList->setColumnWidth(3,cfg.readIntEntry("Timestamp",70));
+
+ connect(m_pUrlList,SIGNAL(doubleClicked(KviTalListViewItem *)),SLOT(dblclk_url(KviTalListViewItem *)));
+ connect(m_pUrlList,SIGNAL(rightButtonPressed(KviTalListViewItem *, const QPoint &, int)),SLOT(popup(KviTalListViewItem *, const QPoint &, int)));
+
+// setFocusHandlerNoChildren(m_pUrlList);
+#ifdef COMPILE_USE_QT4
+ m_pUrlList->setFocusPolicy(Qt::StrongFocus);
+#else
+ m_pUrlList->setFocusPolicy(QWidget::StrongFocus);
+#endif
+ m_pUrlList->setFocus();
+}
+
+void UrlDialog::config()
+{
+ if (!g_pConfigDialog) g_pConfigDialog = new ConfigDialog();
+}
+
+void UrlDialog::help()
+{
+//#warning "help"
+// m_pFrm->requestHelpOn("doc_plugin_url.kvihelp");
+}
+
+void UrlDialog::saveList()
+{
+ saveUrlList();
+}
+
+void UrlDialog::loadList()
+{
+ loadUrlList();
+}
+
+void UrlDialog::clear()
+{
+ g_pList->clear();
+ for (UrlDlgList *tmpitem=g_pUrlDlgList->first();tmpitem;tmpitem=g_pUrlDlgList->next()) {
+ if (tmpitem->dlg) tmpitem->dlg->m_pUrlList->clear();
+ }
+}
+
+/*
+void UrlDialog::saveProperties()
+{
+
+ KviWindowProperty p;
+ p.rect = externalGeometry();
+ p.isDocked = isAttached();
+ p.splitWidth1 = 0;
+ p.splitWidth2 = 0;
+ p.timestamp = 0;
+ p.imagesVisible = 0;
+ KviWindow * w = m_pFrm->activeWindow();
+ p.isMaximized = isAttached() && w ? w->isMaximized() : isMaximized();
+ p.topSplitWidth1 = 0;
+ p.topSplitWidth2 = 0;
+ p.topSplitWidth3 = 0;
+ g_pOptions->m_pWinPropertiesList->setProperty(caption(),&p);
+}
+*/
+
+void UrlDialog::close_slot()
+{
+ close();
+}
+
+void UrlDialog::remove()
+{
+ if (!m_pUrlList->currentItem()) {
+ QMessageBox::warning(0,__tr2qs("Warning - KVIrc"),__tr2qs("Select an URL."),QMessageBox::Ok,QMessageBox::NoButton,QMessageBox::NoButton);
+ return;
+ }
+
+ for(KviUrl *tmp=g_pList->first();tmp;tmp=g_pList->next())
+ {
+ if (tmp->url == m_pUrlList->currentItem()->text(0)) {
+ g_pList->removeRef(tmp);
+ m_pUrlList->takeItem(m_pUrlList->currentItem());
+ return;
+ }
+ }
+}
+
+void UrlDialog::findtext()
+{
+//#warning "find text"
+/*
+ if (!m_pUrlList->currentItem()) {
+ kvirc_plugin_warning_box(__tr("Select an URL"));
+ return;
+ }
+ for(KviUrl *tmp=g_pList->first();tmp;tmp=g_pList->next())
+ {
+ if (tmp->url == KviStr(m_pUrlList->currentItem()->text(0))) {
+ g_pList->find(tmp);
+ KviStr ft="findtext %";
+ ft.replaceAll('%',tmp->url.ptr());
+ KviWindow *wnd = m_pFrm->findWindow(tmp->window.ptr());
+ if (wnd) {
+ if (kvirc_plugin_execute_command(wnd,ft.ptr())) {
+ if (wnd->mdiParent()) m_pFrm->m_pMdi->setTopChild(wnd->mdiParent(),true);
+ }
+ } else kvirc_plugin_warning_box(__tr("Window not found"));
+ }
+
+ }
+*/
+}
+
+void UrlDialog::dblclk_url(KviTalListViewItem *item)
+{
+ QString cmd="openurl ";
+ cmd.append(item->text(0));
+ KviKvsScript::run(cmd,this);
+}
+
+void UrlDialog::popup(KviTalListViewItem *item, const QPoint &point, int col)
+{
+ if (col == 0) {
+ m_szUrl = item->text(0);
+ KviTalPopupMenu p(0,"menu");
+ p.insertItem(__tr2qs("&Remove"),this,SLOT(remove()));
+ p.insertItem(__tr2qs("&Find Text"),this,SLOT(findtext()));
+ p.insertSeparator();
+ m_pListPopup = new KviTalPopupMenu(0,"list");
+ int i=0;
+ for(KviWindow *w=g_pFrame->windowList()->first();w;w=g_pFrame->windowList()->next()){
+ if ((w->type() <= 2) || (w->type() == 2) || (w->type() == 6)) { // values defined in kvi_define.h (console,channel,query,chat,uwindow)
+ m_pListPopup->insertItem(QString(w->plainTextCaption()),i);
+ m_pListPopup->connectItem(i,this,SLOT(sayToWin(int)));
+ i++;
+ }
+ }
+ p.insertItem(__tr2qs("&Say to Window"),m_pListPopup);
+ p.exec(QCursor::pos());
+ }
+}
+
+void UrlDialog::sayToWin(int itemID)
+{
+ KviWindow *wnd = g_pApp->findWindowByCaption(m_pListPopup->text(itemID).utf8().data());
+ QString say=QString("PRIVMSG %1 %2").arg(wnd->windowName()).arg(m_szUrl.ptr());
+ if (wnd) {
+ KviKvsScript::run(say,wnd);
+ wnd->raise();
+ wnd->setActiveWindow();
+ wnd->setFocus();
+ } else QMessageBox::warning(0,__tr2qs("Warning - KVIrc"),__tr2qs("Window not found."),QMessageBox::Ok,QMessageBox::NoButton,QMessageBox::NoButton);
+}
+
+QPixmap *UrlDialog::myIconPtr()
+{
+ //QPixmap *icon = new QPixmap(url_icon_xpm);
+ //return icon;
+ return g_pUrlIconPixmap;
+}
+
+void UrlDialog::addUrl(QString url, QString window, QString count, QString timestamp)
+{
+ KviTalListViewItem *UrlItem = new KviTalListViewItem(m_pUrlList);
+
+ UrlItem->setText(0, url);
+ UrlItem->setText(1, window);
+ UrlItem->setText(2, count);
+ UrlItem->setText(3, timestamp);
+}
+
+void UrlDialog::resizeEvent(QResizeEvent *)
+{
+ int hght = m_pMenuBar->heightForWidth(width());
+ m_pMenuBar->setGeometry(0,0,width(),hght);
+ m_pUrlList->setGeometry(0,hght,width(),height() - hght);
+}
+
+UrlDialog::~UrlDialog()
+{
+ KviConfig cfg(szConfigPath.ptr(),KviConfig::Write);
+ cfg.setGroup("ConfigDialog");
+ if (cfg.readBoolEntry("SaveColumnWidthOnClose",false)) {
+ cfg.setGroup("ColsWidth");
+ cfg.writeEntry("Url",m_pUrlList->columnWidth(0));
+ cfg.writeEntry("Window",m_pUrlList->columnWidth(1));
+ cfg.writeEntry("Count",m_pUrlList->columnWidth(2));
+ cfg.writeEntry("Timestamp",m_pUrlList->columnWidth(3));
+ }
+
+ delete m_pUrlList;
+/* if (m_pListPopup) delete m_pListPopup;
+ m_pListPopup = 0;
+ if (m_pMenuBar) delete m_pMenuBar;
+ m_pMenuBar = 0;*/
+ UrlDlgList *tmpitem = findFrame();
+ tmpitem->dlg = 0;
+}
+
+// ----------------------------- CLASS URLDIALOG -------------------------end //
+
+// --------------------------- CLASS CONFIGDIALOG ----------------------begin //
+
+ConfigDialog::ConfigDialog()
+:QDialog()
+{
+ setCaption(__tr2qs("URL Module Configuration"));
+
+ QGridLayout *g = new QGridLayout(this,4,2,10,10);
+
+ KviConfig *cfg = new KviConfig(szConfigPath.ptr(),KviConfig::Read);
+ cfg->setGroup("ConfigDialog");
+
+ cb[0] = new KviStyledCheckBox(__tr2qs("Save URL list on module unload"),this);
+ cb[0]->setChecked(cfg->readBoolEntry("SaveUrlListOnUnload",false));
+ g->addMultiCellWidget(cb[0],0,0,0,1);
+
+ cb[1] = new KviStyledCheckBox(__tr2qs("Save columns width on URL list close"),this);
+ cb[1]->setChecked(cfg->readBoolEntry("SaveColumnWidthOnClose",false));
+ g->addMultiCellWidget(cb[1],1,1,0,1);
+
+ bool tmp = cfg->readBoolEntry("BanEnabled",false);
+ delete cfg;
+
+ m_pBanFrame = new BanFrame(this,"banlist",tmp);
+ g->addMultiCellWidget(m_pBanFrame,3,3,0,1);
+
+ QPushButton *b;
+ // configure buttons
+ b = new QPushButton(__tr2qs("&Cancel"),this,"discard");
+ connect(b,SIGNAL(clicked()),this,SLOT(discardbtn()));
+ g->addWidget(b,4,0);
+
+ b = new QPushButton(__tr2qs("&OK"),this,"accept");
+ connect(b,SIGNAL(clicked()),this,SLOT(acceptbtn()));
+ g->addWidget(b,4,1);
+
+ show();
+}
+
+void ConfigDialog::discardbtn()
+{
+ delete this;
+}
+
+void ConfigDialog::acceptbtn()
+{
+ if (m_pBanFrame) m_pBanFrame->saveBans();
+
+ KviConfig *cfg = new KviConfig(szConfigPath.ptr(),KviConfig::Write);
+ cfg->setGroup("ConfigDialog");
+ cfg->writeEntry("SaveUrlListOnUnload",cb[0]->isChecked());
+ cfg->writeEntry("SaveColumnWidthOnClose",cb[1]->isChecked());
+ delete cfg;
+
+ delete this;
+}
+
+void ConfigDialog::closeEvent(QCloseEvent *)
+{
+ delete this;
+}
+
+ConfigDialog::~ConfigDialog()
+{
+ for(int i=0;i<cbnum;i++) delete cb[i];
+ g_pConfigDialog = 0;
+}
+
+// --------------------------- CLASS CONFIGDIALOG ------------------------end //
+
+// ---------------------------- CLASS BANFRAME ------------------------begin //
+
+BanFrame::BanFrame(QWidget *parent, const char *name, bool banEnabled)
+:QFrame(parent,name)
+{
+ setFrameStyle(QFrame::Panel | QFrame::Raised);
+
+ QGridLayout *g = new QGridLayout(this,2,2,10,10);
+
+ m_pEnable = new KviStyledCheckBox(__tr2qs("Enable URL ban list"),this);
+ connect(m_pEnable,SIGNAL(clicked()),this,SLOT(enableClicked()));
+ m_pEnable->setChecked(banEnabled);
+ g->addMultiCellWidget(m_pEnable,0,0,0,1);
+
+ m_pBanList = new KviTalListBox(this);
+ m_pBanList->setMinimumHeight(100);
+ loadBanList();
+ for(KviStr *tmp=g_pBanList->first();tmp;tmp=g_pBanList->next()) m_pBanList->insertItem(tmp->ptr()); // load ban list into listbox
+ m_pBanList->setEnabled(m_pEnable->isChecked());
+ g->addMultiCellWidget(m_pBanList,1,1,0,1);
+
+ m_pAddBtn = new QPushButton(__tr2qs("&Add Ban"),this,"add");
+ connect(m_pAddBtn,SIGNAL(clicked()),this,SLOT(addBan()));
+ m_pAddBtn->setEnabled(m_pEnable->isChecked());
+ g->addWidget(m_pAddBtn,2,0);
+
+ m_pRemoveBtn = new QPushButton(__tr2qs("&Remove Selected"),this,"remove");
+ connect(m_pRemoveBtn,SIGNAL(clicked()),this,SLOT(removeBan()));
+ m_pRemoveBtn->setEnabled(m_pEnable->isChecked());
+ g->addWidget(m_pRemoveBtn,2,1);
+}
+
+void BanFrame::enableClicked()
+{
+ m_pBanList->setEnabled(m_pEnable->isChecked());
+ m_pAddBtn->setEnabled(m_pEnable->isChecked());
+ m_pRemoveBtn->setEnabled(m_pEnable->isChecked());
+}
+
+void BanFrame::addBan()
+{
+ bool ok = false;
+ KviStr *text = new KviStr(QInputDialog::getText(__tr2qs("URL Ban List"),__tr2qs("Add"),QLineEdit::Normal,QString::null,&ok,this));
+ if (ok && !text->isEmpty()) {
+ g_pBanList->append(text);
+ m_pBanList->insertItem(text->ptr());
+ }
+}
+
+void BanFrame::removeBan()
+{
+ uint i = 0;
+ while ((!m_pBanList->isSelected(i)) && (i < m_pBanList->count())) i++;
+ if (!m_pBanList->isSelected(i)) {
+ QMessageBox::warning(0,__tr2qs("Warning - KVIrc"),__tr2qs("Select a ban."),QMessageBox::Ok,QMessageBox::NoButton,QMessageBox::NoButton);
+ return;
+ }
+ KviStr item(m_pBanList->text(i).utf8().data());
+ for(KviStr *tmp=g_pBanList->first();tmp;tmp=g_pBanList->next())
+ {
+ if (*tmp == item)
+ {
+ g_pBanList->removeCurrent();
+ return;
+ }
+ }
+
+ m_pBanList->removeItem(i);
+
+}
+
+void BanFrame::saveBans()
+{
+ if (m_pEnable->isChecked()) saveBanList();
+ KviConfig *cfg = new KviConfig(szConfigPath.ptr(),KviConfig::Write);
+ cfg->setGroup("ConfigDialog");
+ cfg->writeEntry("BanEnabled",m_pEnable->isChecked());
+ delete cfg;
+}
+
+BanFrame::~BanFrame()
+{
+
+}
+
+// ---------------------------- CLASS URLTOOLBAR -------------------------end //
+
+void saveUrlList()
+{
+ QString urllist;
+ g_pApp->getLocalKvircDirectory(urllist,KviApp::ConfigPlugins);
+ urllist += g_pUrlListFilename;
+ QFile file;
+ file.setName(urllist);
+ file.open(IO_WriteOnly);
+
+ QTextStream stream(&file);
+
+ stream << g_pList->count() << endl;
+
+ for(KviUrl *tmp=g_pList->first();tmp;tmp=g_pList->next())
+ {
+ stream << tmp->url << endl;
+ stream << tmp->window << endl;
+ stream << tmp->count << endl;
+ stream << tmp->timestamp << endl;
+ }
+ file.flush();
+ file.close();
+}
+
+void loadUrlList()
+{
+ KviStr urllist;
+ g_pApp->getLocalKvircDirectory(urllist,KviApp::ConfigPlugins);
+ urllist += g_pUrlListFilename;
+ QFile file;
+ file.setName(QString::fromUtf8(urllist.ptr()));
+ if (!file.open(IO_ReadOnly))return;
+#ifdef COMPILE_USE_QT4
+ Q3TextStream stream(&file);
+#else
+ QTextStream stream(&file);
+#endif
+
+
+ g_pList->clear();
+
+ for (UrlDlgList *tmpitem=g_pUrlDlgList->first();tmpitem;tmpitem=g_pUrlDlgList->next()) {
+ if (tmpitem->dlg) tmpitem->dlg->m_pUrlList->clear();
+ }
+ KviUrl *tmp;
+ int i=0;
+ int num = stream.readLine().toInt();
+ while ((!stream.eof()) && (i<num)){
+ tmp = new KviUrl();
+ tmp->url = stream.readLine();
+ tmp->window = stream.readLine();
+ tmp->count = stream.readLine().toInt();
+ tmp->timestamp = stream.readLine();
+
+ g_pList->append(tmp);
+
+ for (UrlDlgList *tmpitem=g_pUrlDlgList->first();tmpitem;tmpitem=g_pUrlDlgList->next()) {
+ if (tmpitem->dlg) {
+ QString tmpCount;
+ tmpCount.setNum(tmp->count);
+ tmpitem->dlg->addUrl(QString(tmp->url), QString(tmp->window), tmpCount, QString(tmp->timestamp));
+ }
+ }
+ i++;
+ }
+ file.close();
+}
+
+void saveBanList()
+{
+ KviStr banlist;
+ g_pApp->getLocalKvircDirectory(banlist,KviApp::ConfigPlugins);
+ banlist += g_pBanListFilename;
+ QFile file;
+ file.setName(QString::fromUtf8(banlist.ptr()));
+ file.open(IO_WriteOnly);
+
+ QTextStream stream(&file);
+
+ stream << g_pBanList->count() << endl;
+ for(KviStr *tmp=g_pBanList->first();tmp;tmp=g_pBanList->next())
+ {
+ stream << tmp->ptr() << endl;
+ }
+ file.flush();
+ file.close();
+}
+
+void loadBanList()
+{
+ KviStr banlist;
+ g_pApp->getLocalKvircDirectory(banlist,KviApp::ConfigPlugins);
+ banlist += g_pBanListFilename;
+ QFile file;
+ file.setName(QString::fromUtf8(banlist.ptr()));
+ if (!file.open(IO_ReadOnly))return;
+#ifdef COMPILE_USE_QT4
+ Q3TextStream stream(&file);
+#else
+ QTextStream stream(&file);
+#endif
+ g_pBanList->clear();
+
+ int i=0;
+ int num = stream.readLine().toInt();
+ while ((!stream.eof()) && (i<num)){
+ KviStr *tmp = new KviStr(stream.readLine());
+ g_pBanList->append(tmp);
+ i++;
+ }
+ file.close();
+}
+
+
+/*
+ @doc: url.list
+ @type:
+ command
+ @title:
+ url.list
+ @short:
+ Opens url list
+ @syntax:
+ url.list
+ @description:
+ This command opens a window containing the urls' list.
+ In the list there is other information:[br]
+ [U]Window[/U] : window where the url has been shown last[br]
+ [U]Count[/U] : number of urls shown[br]
+ [U]Timestamp[/U] : date/time when the url has been shown first[br]
+ Clicking right on the url column of the list a menu will popup, through it
+ you can remove the selected item, find the url in the window it appeared last, and
+ say it to: [I]@Console, Channels, Querys, DCC Chats[/I] and [I]User windows[/I].[br]
+ The list is saved to file when you click on the menu item or when you unload the plugin
+ on condition that you have checked the relative checkbox in configuration dialog.[br]
+ You can also open the url in your web browser double clicking on it in the url list window.[br][br]
+
+ */
+
+static bool url_kvs_cmd_list(KviKvsModuleCommandCall * c)
+{
+ urllist();
+ return true;
+}
+
+
+UrlDlgList *findFrame()
+{
+ UrlDlgList *tmpitem = g_pUrlDlgList->first();
+ if (!tmpitem) {
+ UrlDlgList *udl = new UrlDlgList();
+ udl->dlg = 0;
+ udl->menu_id = -1;
+ g_pUrlDlgList->append(udl);
+ tmpitem = g_pUrlDlgList->current();
+ }
+ return tmpitem;
+}
+
+bool urllist()
+{
+ UrlDlgList *tmpitem = findFrame();
+ if (tmpitem->dlg) return false;
+
+ tmpitem->dlg = new UrlDialog(g_pList);
+ g_pFrame->addWindow(tmpitem->dlg);
+
+ for(KviUrl *tmp=g_pList->first();tmp;tmp=g_pList->next())
+ {
+ QString tmpCount;
+ tmpCount.setNum(tmp->count);
+ tmpitem->dlg->addUrl(QString(tmp->url), QString(tmp->window), tmpCount, QString(tmp->timestamp));
+ }
+ return true;
+}
+
+
+/*
+ @doc: url.config
+ @type:
+ command
+ @title:
+ url.config
+ @short:
+ Loads URL list module
+ @syntax:
+ url.config
+ @description:
+ This command opens a configuration window where it is possible
+ to setup plugin's parameters. You can also open this window by
+ using popup menu in the url list window or by clicking on the "configure plugin" button
+ in plugins options.<BR><BR>
+ <H3>Configure dialog options:</H3>
+ There is also a ban list widget, which allows to have a list of words that plugin mustn't catch.<BR><BR>
+ <I>E.g.<BR>
+ <blockquote>if the word "ftp" is inserted in the ban list and if in a window there is an output like "ftp.kvirc.net",
+ the url will not be catched.</blockquote></I>
+ <HR>
+ */
+
+static bool url_kvs_cmd_config(KviKvsModuleCommandCall * c)
+{
+ if (!g_pConfigDialog) g_pConfigDialog = new ConfigDialog();
+ return true;
+}
+
+int check_url(KviWindow *w,const QString &szUrl) // return 0 if no occurence of the url were found
+{
+ int tmp = 0;
+
+ for(KviStr *tmpi=g_pBanList->first();tmpi;tmpi=g_pBanList->next())
+ {
+ if (szUrl.find(QString(tmpi->ptr())) != -1) tmp++;
+ }
+ if (tmp > 0) return tmp;
+
+ for(KviUrl *u = g_pList->first();u;u=g_pList->next())
+ {
+ if (u->url == szUrl) {
+ u->window = w->plainTextCaption();
+ u->count++;
+ tmp++;
+ }
+ }
+
+ for (UrlDlgList *tmpitem=g_pUrlDlgList->first();tmpitem;tmpitem=g_pUrlDlgList->next()) {
+ if (tmpitem->dlg) {
+ KviTalListViewItemIterator lvi(tmpitem->dlg->m_pUrlList);
+ for(;lvi.current();++lvi)
+ {
+ if (lvi.current()->text(0) == szUrl) {
+ int tmpCount = lvi.current()->text(2).toInt();
+ tmpCount++;
+ QString tmpStr;
+ tmpStr.setNum(tmpCount);
+ lvi.current()->setText(2,tmpStr);
+ lvi.current()->setText(1,w->plainTextCaption());
+ }
+ }
+ }
+ }
+ return tmp;
+}
+
+bool urllist_module_event_onUrl(KviKvsModuleEventCall * c)
+{
+ KviKvsVariant * vUrl = c->firstParam();
+ QString szUrl;
+ if(vUrl)vUrl->asString(szUrl);
+
+ if (check_url(c->window(),szUrl) == 0)
+ {
+
+ KviUrl *tmp = new KviUrl;
+ KviStr tmpTimestamp;
+ QDate d = QDate::currentDate();
+ KviStr date(KviStr::Format,"%d-%d%d-%d%d",d.year(),d.month() / 10,d.month() % 10,d.day() / 10,d.day() % 10);
+ tmpTimestamp = "["+date+"]"+" [";
+ tmpTimestamp += QTime::currentTime().toString()+"]";
+ tmp->url = szUrl;
+ tmp->window = c->window()->plainTextCaption();
+ tmp->count = 1;
+ tmp->timestamp = tmpTimestamp;
+
+ g_pList->append(tmp);
+ for (UrlDlgList *tmpitem=g_pUrlDlgList->first();tmpitem;tmpitem=g_pUrlDlgList->next()) {
+ if (tmpitem->dlg) {
+ QString tmpCount;
+ tmpCount.setNum(tmp->count);
+ tmpitem->dlg->addUrl(QString(tmp->url), QString(tmp->window), tmpCount, QString(tmp->timestamp));
+ tmpitem->dlg->taskBarItem()->highlight(false);
+ }
+ }
+ }
+ return true;
+}
+
+
+/* @doc: url.load
+ @type:
+ command
+ @title:
+ url.load
+ @short:
+ Loads URL list module
+ @syntax:
+ url.load
+ @description:
+ Loads the URL list module which keeps track of all urls shown in kvirc windows.
+*/
+
+
+static bool url_module_init(KviModule *m)
+{
+ KviModuleExtensionDescriptor * d = m->registerExtension("tool",
+ KVI_URL_EXTENSION_NAME,
+ __tr2qs("View URL list"),
+ url_extension_alloc);
+ if(d)d->setIcon(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_URL)));
+
+ g_pList = new KviPointerList<KviUrl>;
+ g_pList->setAutoDelete(true);
+
+ g_pUrlDlgList = new KviPointerList<UrlDlgList>;
+ g_pUrlDlgList->setAutoDelete(true);
+
+ g_pBanList = new KviPointerList<KviStr>;
+ g_pBanList->setAutoDelete(true);
+
+ g_pUrlIconPixmap = new QPixmap(url_icon_xpm);
+
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"list",url_kvs_cmd_list);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"config",url_kvs_cmd_config);
+ g_pUrlAction = new KviUrlAction(KviActionManager::instance());
+ KviActionManager::instance()->registerAction(g_pUrlAction);
+
+ m->kvsRegisterAppEventHandler(KviEvent_OnUrl,urllist_module_event_onUrl);
+
+ g_pApp->getLocalKvircDirectory(szConfigPath,KviApp::ConfigPlugins,"url.conf");
+
+ loadUrlList();
+ loadBanList();
+
+ UrlDlgList *udl = new UrlDlgList();
+ udl->dlg = 0;
+ g_pUrlDlgList->append(udl);
+
+ return true;
+}
+
+static bool url_module_cleanup(KviModule *m)
+{
+ KviConfig cfg(szConfigPath.ptr(),KviConfig::Read);
+ cfg.setGroup("ConfigDialog");
+ if (cfg.readBoolEntry("SaveUrlListOnUnload",false) == true) saveUrlList();
+ for (UrlDlgList *tmpitem=g_pUrlDlgList->first();tmpitem;tmpitem=g_pUrlDlgList->next()) {
+ if (tmpitem->dlg) tmpitem->dlg->close();
+ }
+
+ delete g_pList;
+ g_pList = 0;
+ delete g_pBanList;
+ g_pBanList = 0;
+
+ delete g_pUrlDlgList;
+ g_pUrlDlgList = 0;
+ delete g_pUrlAction;
+ g_pUrlAction = 0;
+
+
+ delete g_pUrlIconPixmap;
+ g_pUrlIconPixmap = 0;
+
+ return true;
+}
+
+static bool url_module_can_unload(KviModule *m)
+{
+ // FIXME: really ugly :/
+ return false;
+}
+
+void url_module_config()
+{
+ if (!g_pConfigDialog) g_pConfigDialog = new ConfigDialog();
+}
+
+/*
+ @doc: url
+ @type:
+ module
+ @short:
+ The URL list module: keeps track of all urls shown in kvirc windows
+ @title:
+ The URL list module
+ @body:
+ This plugin keeps track of all urls shown in kvirc windows.
+ <H3>Exported commands:</H3>
+ <B>/url.list</B> : this command opens a window containing the urls' list.
+ In the list there is other information:<BR>
+ <U>Window</U> : window where the url has been shown last<BR>
+ <U>Count</U> : number of urls shown<BR>
+ <U>Timestamp</U> : date/time when the url has been shown first<BR>
+ Clicking right on the url column of the list a menu will popup, through it
+ you can remove the selected item, find the url in the window it appeared last, and
+ say it to: <I>@Console, Channels, Querys, DCC Chats</I> and <I>User windows</I>.<BR>
+ The list is saved to file when you click on the menu item or when you unload the plugin
+ on condition that you have checked the relative checkbox in configuration dialog.<BR>
+ You can also open the url in your web browser double clicking on it in the url list window.<BR><BR>
+
+ Mail me if you have any suggestion or you want to notice a bug.<BR>
+ <B>Andrea 'YaP' Parrella</B> &lt;anandrea@iname.com&gt;<BR><BR>
+ Thanks to:<BR>
+ <B>Szymon Stefanek</B> and <B>Till Bush</B> for their help.<BR>
+ <B>Ted Podgurski</B> for toolbar's icons.
+*/
+
+
+KVIRC_MODULE(
+ "URL",
+ "1.0.0" ,
+ "Copyright (C) 2002 Andrea Parrella <yap@yapsoft.it>" ,
+ "url list module for KVIrc",
+ url_module_init,
+ url_module_can_unload,
+ 0,
+ url_module_cleanup
+)
+
+#include "libkviurl.moc"
diff --git a/src/modules/url/libkviurl.h b/src/modules/url/libkviurl.h
new file mode 100644
index 00000000..05d56ce8
--- /dev/null
+++ b/src/modules/url/libkviurl.h
@@ -0,0 +1,144 @@
+#ifndef _H_URLDLG
+#define _H_URLDLG
+
+//
+// This file is part of the KVIrc irc client distribution
+// Copyright (C) 1999-2000 Andrea Parrella (anandrea@iname.com)
+//
+// 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 opinion) 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.
+//
+
+
+#include <qdialog.h>
+#include <qlayout.h>
+#include "kvi_tal_listview.h"
+#include <qstring.h>
+#include <qpushbutton.h>
+#include <qfile.h>
+#ifdef COMPILE_USE_QT4
+ #include <q3textstream.h>
+#else
+ #include <qtextstream.h>
+#endif
+#include <qcheckbox.h>
+#include "kvi_tal_listbox.h"
+#include <qmenubar.h>
+#include <qinputdialog.h>
+#include <qtoolbutton.h>
+#include <qiconset.h>
+
+#include "kvi_locale.h"
+#include "kvi_config.h"
+#include "kvi_irctoolbar.h"
+#include "kvi_imagelib.h"
+#include "kvi_window.h"
+#include "kvi_tal_menubar.h"
+#include "kvi_mextoolbar.h"
+#include "kvi_styled_controls.h"
+
+#include <qpixmap.h>
+
+typedef struct _KviUrl
+{
+ QString url;
+ QString window;
+ int count;
+ QString timestamp;
+} KviUrl;
+
+
+class UrlDialog : public KviWindow
+{
+ Q_OBJECT
+public:
+ UrlDialog(KviPointerList<KviUrl> *g_pList);
+ ~UrlDialog();
+private:
+ KviTalMenuBar *m_pMenuBar;
+ KviTalPopupMenu *m_pListPopup; // dynamic popup menu
+ KviStr m_szUrl; // used to pass urls to sayToWin slot
+protected:
+ QPixmap *myIconPtr();
+ void resizeEvent(QResizeEvent *);
+public:
+ KviTalListView *m_pUrlList;
+ void addUrl(QString url, QString window, QString count, QString timestamp);
+// void saveProperties();
+protected slots:
+ void config();
+ void help();
+ void saveList();
+ void loadList();
+ void clear();
+ void close_slot();
+ void remove();
+ void findtext();
+ void dblclk_url(KviTalListViewItem *item);
+ void popup(KviTalListViewItem *item, const QPoint &p, int col);
+ void sayToWin(int);
+};
+
+class BanFrame : public QFrame
+{
+ Q_OBJECT
+public:
+ BanFrame(QWidget *parent=0, const char *name=0, bool banEnable = false);
+ ~BanFrame();
+ void saveBans();
+private:
+ KviStyledCheckBox *m_pEnable;
+ KviTalListBox *m_pBanList;
+ QPushButton *m_pAddBtn;
+ QPushButton *m_pRemoveBtn;
+protected slots:
+ void enableClicked();
+ void addBan();
+ void removeBan();
+};
+
+#define cbnum 2
+
+class ConfigDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ ConfigDialog();
+ ~ConfigDialog();
+private:
+ KviStyledCheckBox *cb[cbnum];
+ BanFrame *m_pBanFrame;
+ void closeEvent(QCloseEvent *);
+protected slots:
+ void acceptbtn();
+ void discardbtn();
+};
+
+#include "kvi_kvs_action.h"
+
+class KviUrlAction : public KviKvsAction
+{
+ Q_OBJECT
+public:
+ KviUrlAction(QObject * pParent);
+ ~KviUrlAction();
+protected:
+ QPixmap * m_pBigIcon;
+ QPixmap * m_pSmallIcon;
+public:
+ virtual QPixmap * bigIcon();
+ virtual QPixmap * smallIcon();
+};
+
+#endif
diff --git a/src/modules/window/Makefile.am b/src/modules/window/Makefile.am
new file mode 100644
index 00000000..52912925
--- /dev/null
+++ b/src/modules/window/Makefile.am
@@ -0,0 +1,21 @@
+###############################################################################
+# KVirc IRC client Makefile - 10.03.2000 Szymon Stefanek <stefanek@tin.it>
+###############################################################################
+
+AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \
+$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\"
+
+pluglib_LTLIBRARIES = libkviwindow.la
+
+libkviwindow_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS)
+
+nodist_libkviwindow_la_SOURCES = moc_userwindow.cpp
+
+libkviwindow_la_SOURCES = libkviwindow.cpp userwindow.cpp
+
+libkviwindow_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la
+
+noinst_HEADERS= userwindow.h
+
+moc_%.cpp: %.h
+ $(SS_QT_MOC) $< -o $@
diff --git a/src/modules/window/libkviwindow.cpp b/src/modules/window/libkviwindow.cpp
new file mode 100644
index 00000000..abef0dd9
--- /dev/null
+++ b/src/modules/window/libkviwindow.cpp
@@ -0,0 +1,1547 @@
+//=================================================================================
+//
+// File : kvi_window.cpp
+// Creation date : Sat Sep 01 2001 17:13:12 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2005 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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.
+//
+//=================================================================================
+
+#include "kvi_module.h"
+
+#include "kvi_console.h"
+#include "kvi_options.h"
+#include "kvi_ircsocket.h"
+#include "kvi_frame.h"
+#include "kvi_locale.h"
+#include "kvi_app.h"
+#include "kvi_error.h"
+#include "kvi_ircview.h"
+#include "kvi_input.h"
+#include "kvi_iconmanager.h"
+#include "kvi_modulemanager.h"
+#include "kvi_memmove.h"
+#include "kvi_malloc.h"
+
+#include "kvi_channel.h"
+#include "userwindow.h"
+
+#include "kvi_pointerhashtable.h"
+#include <qtimer.h>
+
+
+#ifdef COMPILE_CRYPT_SUPPORT
+ #include "kvi_crypt.h"
+ #include "kvi_cryptcontroller.h"
+ // kvi_app.cpp
+ extern KVIRC_API KviCryptEngineManager * g_pCryptEngineManager;
+#endif
+
+
+// kvi_app.cpp
+extern KVIRC_API KviPointerHashTable<const char *,KviWindow> * g_pGlobalWindowDict;
+KviPointerList<KviUserWindow> * g_pUserWindowList = 0;
+
+// $window.caption $window.x $window.y $window.width $window.height $window.isActive $window.type
+// $window.input.text $window.input.cursorpos $window.input.textlen
+
+
+#define GET_KVS_WINDOW_ID \
+ QString szWnd; \
+ KviWindow * pWnd; \
+ KVSM_PARAMETERS_BEGIN(c) \
+ KVSM_PARAMETER("window_id",KVS_PT_STRING,KVS_PF_OPTIONAL,szWnd) \
+ KVSM_PARAMETERS_END(c) \
+ if(c->parameterList()->count() == 0) \
+ { \
+ pWnd = c->window(); \
+ } else { \
+ pWnd = g_pApp->findWindow(szWnd.utf8().data()); \
+ if(!pWnd) \
+ { \
+ if(!c->hasSwitch('q',"quiet")) \
+ c->warning(__tr2qs("The window with id '%s' does not exist"),szWnd.utf8().data()); \
+ return true; \
+ } \
+ }
+
+#define GET_KVS_FNC_WINDOW_ID \
+ QString szWnd; \
+ KviWindow * pWnd; \
+ KVSM_PARAMETERS_BEGIN(c) \
+ KVSM_PARAMETER("window_id",KVS_PT_STRING,KVS_PF_OPTIONAL,szWnd) \
+ KVSM_PARAMETERS_END(c) \
+ if(c->parameterList()->count() == 0) \
+ { \
+ pWnd = c->window(); \
+ } else { \
+ pWnd = g_pApp->findWindow(szWnd.utf8().data()); \
+ if(!pWnd) \
+ return true; \
+ }
+
+/*
+ @doc: window.clearOutput
+ @type:
+ command
+ @title:
+ window.clearOutput
+ @short:
+ Clears the output a window
+ @syntax:
+ window.clearOutput [-f] [-q] [window_id]
+ @switches:
+ !sw: -q | --quiet
+ Don't warn if the specified window doesn't exist. Just continue silently.
+ @description:
+ Clears the text output of the window specified by window_id. If window_id is missing then
+ the current window is used. If the window has no text output then no operation is performed.
+ If the specified window does not exist a warning is printed (unless the -q switch is used)
+ but the execution continues normally.
+ @seealso:
+ [fnc]$window.hasOutput[/fnc]
+*/
+
+static bool window_kvs_cmd_clearOutput(KviKvsModuleCommandCall * c)
+{
+ GET_KVS_WINDOW_ID
+ if(pWnd)
+ {
+ if(pWnd->view())pWnd->view()->emptyBuffer(true);
+ if(pWnd->type() == KVI_WINDOW_TYPE_CHANNEL)
+ {
+ KviChannel *chan = (KviChannel *)pWnd;
+ if(chan->messageView()) chan->messageView()->emptyBuffer(true);
+ }
+ }
+ return true;
+}
+
+/*
+ @doc: window.close
+ @type:
+ command
+ @title:
+ window.close
+ @short:
+ Closes a window
+ @syntax:
+ window.close [-q] [window_id]
+ @description:
+ Closes the window specified by window_id. If window_id is missing then
+ the current window is closed. The close operation is asynchronous: it is
+ performed immediately after the script has terminated the execution and
+ the control is returned to the main KVIrc core. If the specified window
+ does not exist a warning is printed unless the -q switch is used.
+*/
+
+static bool window_kvs_cmd_close(KviKvsModuleCommandCall * c)
+{
+ GET_KVS_WINDOW_ID
+ if(pWnd)
+ {
+ pWnd->delayedClose();
+ }
+ return true;
+}
+
+/*
+ @doc: window.dock
+ @type:
+ command
+ @title:
+ window.dock
+ @short:
+ Docks a window
+ @syntax:
+ window.dock [-q] [window_id]
+ @description:
+ Docks the window specified by window_id. If window_id is missing then
+ the current window is docked. If the specified window was already docked then
+ no operation is performed. If the specified window
+ does not exist a warning is printed unless the -q switch is used.
+ @seealso:
+ [cmd]window.undock[/cmd]
+*/
+
+static bool window_kvs_cmd_dock(KviKvsModuleCommandCall * c)
+{
+ GET_KVS_WINDOW_ID
+ if(pWnd)
+ {
+ pWnd->dock();
+ }
+ return true;
+}
+
+/*
+ @doc: window.undock
+ @type:
+ command
+ @title:
+ window.undock
+ @short:
+ Undocks a window
+ @syntax:
+ window.undock [-q] [window_id]
+ @description:
+ Undocks the window specified by window_id. If window_id is missing then
+ the current window is undocked. If the specified window was already undocked then
+ no operation is performed. If the specified window
+ does not exist a warning is printed unless the -q switch is used.
+ @seealso:
+ [cmd]window.dock[/cmd]
+*/
+
+static bool window_kvs_cmd_undock(KviKvsModuleCommandCall * c)
+{
+ GET_KVS_WINDOW_ID
+ if(pWnd)
+ {
+ pWnd->undock();
+ }
+ return true;
+}
+
+/*
+ @doc: window.maximize
+ @type:
+ command
+ @title:
+ window.maximize
+ @short:
+ Maximizes a window
+ @syntax:
+ window.maximize [-q] [window_id]
+ @description:
+ Maximizes the window specified by window_id. If window_id is missing then
+ the current window is maximized. If the specified window was already maximized then
+ no operation is performed. If the specified window
+ does not exist a warning is printed unless the -q switch is used.
+ @seealso:
+ [cmd]window.minimize[/cmd], [cmd]window.restore[/cmd], [fnc]$window.isMaxmimized[/fnc],
+ [fnc]$window.isMinimized[/fnc]
+*/
+
+static bool window_kvs_cmd_maximize(KviKvsModuleCommandCall * c)
+{
+ GET_KVS_WINDOW_ID
+ if(pWnd)
+ {
+ pWnd->maximize();
+ }
+ return true;
+}
+
+/*
+ @doc: window.minimize
+ @type:
+ command
+ @title:
+ window.minimize
+ @short:
+ Minimizes a window
+ @syntax:
+ window.minimize [-q] [window_id]
+ @description:
+ Minimizes the window specified by window_id. If window_id is missing then
+ the current window is minimized. If the specified window was already minimized then
+ no operation is performed. If the specified window
+ does not exist a warning is printed unless the -q switch is used.
+ @seealso:
+ [cmd]window.maximize[/cmd], [cmd]window.restore[/cmd], [fnc]$window.isMaxmimized[/fnc],
+ [fnc]$window.isMinimized[/fnc]
+*/
+
+static bool window_kvs_cmd_minimize(KviKvsModuleCommandCall * c)
+{
+ GET_KVS_WINDOW_ID
+ if(pWnd)
+ {
+ pWnd->minimize();
+ }
+ return true;
+}
+
+/*
+ @doc: window.restore
+ @type:
+ command
+ @title:
+ window.restore
+ @short:
+ Restores a window
+ @syntax:
+ window.restore [-q] [window_id]
+ @description:
+ Restores the window specified by window_id. If window_id is missing then
+ the current window is restored. If the specified window was already restored then
+ no operation is performed. If the specified window
+ does not exist a warning is printed unless the -q switch is used.
+ @seealso:
+ [cmd]window.maximize[/cmd], [cmd]window.minimize[/cmd], [fnc]$window.isMaxmimized[/fnc],
+ [fnc]$window.isMinimized[/fnc]
+*/
+
+static bool window_kvs_cmd_restore(KviKvsModuleCommandCall * c)
+{
+ GET_KVS_WINDOW_ID
+ if(pWnd)
+ {
+ pWnd->restore();
+ }
+ return true;
+}
+
+/*
+ @doc: window.activate
+ @type:
+ command
+ @title:
+ window.activate
+ @short:
+ Activates a window
+ @syntax:
+ window.activate [-q] [window_id]
+ @description:
+ Activates the window specified by window_id. If window_id is missing then
+ the current window is activated. If the specified window
+ does not exist a warning is printed unless the -q switch is used.
+ Please note that if the window is currently docked to a frame then this
+ command will NOT raise the frame window. If you're interested in
+ the user's attention then you might be interested in [cmd]window.demandAttention[/cmd].
+ @seealso:
+ [cmd]window.demandAttention[/cmd]
+*/
+
+static bool window_kvs_cmd_activate(KviKvsModuleCommandCall * c)
+{
+ GET_KVS_WINDOW_ID
+ if(pWnd)
+ {
+ pWnd->autoRaise();
+ }
+ return true;
+}
+
+/*
+ @doc: window.demandAttention
+ @type:
+ command
+ @title:
+ window.demandAttention
+ @short:
+ Flashes a window's system taskbar entry
+ @syntax:
+ window.demandAttention [-q] [window_id]
+ @description:
+ Flashes the system taskbar entry of the window
+ specified by the window_id. If window_id is missing then
+ the current window's system taskbar entry is flashed. If the specified window
+ does not exist a warning is printed unless the -q switch is used.
+ If the window is currently docked in a frame then the frame's
+ system taskbar entry will be flashed.
+ Please note that this command is highly system dependant:
+ on systems that do not have a system taskbar or there
+ is no way to flash an etry this command will do nothing.
+ At the time of writing this command works flawlessly on
+ Windows and in KDE compilations.
+ @seealso:
+ [cmd]window.demandAttention[/cmd]
+*/
+
+static bool window_kvs_cmd_demandAttention(KviKvsModuleCommandCall * c)
+{
+ GET_KVS_WINDOW_ID
+ if(pWnd)
+ {
+ pWnd->demandAttention();
+ }
+ return true;
+}
+
+/*
+ @doc: window.isMaximized
+ @type:
+ function
+ @title:
+ $window.isMaximized
+ @short:
+ Checks if a window is currently maximized
+ @syntax:
+ $window.isMaximized
+ $window.isMaximized(<window_id>)
+ @description:
+ Returns 1 if the window specified by <window_id> is currently maximized and 0 otherwise.
+ The form with no parameters works on the current window. If the specified window
+ doesn't exist then 0 is returned.
+ @seealso:
+ [fnc]$window.isMinimized[/fnc], [cmd]window.maximize[/cmd],
+ [cmd]window.minimize[/cmd], [cmd]window.restore[/cmd]
+*/
+
+static bool window_kvs_fnc_isMaximized(KviKvsModuleFunctionCall * c)
+{
+ GET_KVS_FNC_WINDOW_ID
+ if(pWnd)
+ {
+ c->returnValue()->setBoolean(pWnd->isMaximized() ? true : false);
+ }
+ return true;
+}
+
+/*
+ @doc: window.activityLevel
+ @type:
+ function
+ @title:
+ $window.activityLevel
+ @short:
+ Returns the current activity level of a window
+ @syntax:
+ $window.activityLevel
+ $window.activityLevel(<window_id>)
+ @description:
+ Returns the current activity level of the window specified by <window_id>.
+ The form without parameters works on the current window.[br]
+ The activity level is a number describing the level of traffic in the window
+ and depends on the window type. On channels and queries it is dependant on the number
+ and frequency of actions performed by the users.
+ @seealso:
+ [fnc]$window.activityTemperature[/fnc]
+*/
+
+static bool window_kvs_fnc_activityLevel(KviKvsModuleFunctionCall * c)
+{
+ GET_KVS_FNC_WINDOW_ID
+ if(pWnd)
+ {
+ unsigned int v,t;
+ pWnd->activityMeter(&v,&t);
+ c->returnValue()->setInteger(v);
+ } else {
+ c->returnValue()->setInteger(0);
+ }
+ return true;
+}
+
+/*
+ @doc: window.activityTemperature
+ @type:
+ function
+ @title:
+ $window.activityTemperature
+ @short:
+ Returns the current activity temperature of a window
+ @syntax:
+ $window.activityTemperature
+ $window.activityTemperature(<window_id>)
+ @description:
+ Returns the current activity temperature of the window specified by <window_id>.
+ The form without parameters works on the current window.[br]
+ The activity temperature describes the type of traffic in the window and is
+ strictly related to the [fnc]$window.activityLevel[/fnc].[br]
+ On channels and queries the temperature describes the type of the actions
+ performed by the users. High temperatures denote more "human" behaviour (like
+ speaking to the channel, changing the topic etc...),
+ low temperatures denote automatic behaviours (like changing the channel limit
+ or mode: actions often performed by bots).[br]
+ @seealso:
+ [fnc]$window.activityLevel[/fnc]
+*/
+
+static bool window_kvs_fnc_activityTemperature(KviKvsModuleFunctionCall * c)
+{
+ GET_KVS_FNC_WINDOW_ID
+ if(pWnd)
+ {
+ unsigned int v,t;
+ pWnd->activityMeter(&v,&t);
+ c->returnValue()->setInteger(t);
+ } else {
+ c->returnValue()->setInteger(0);
+ }
+ return true;
+}
+
+/*
+ @doc: window.isMinimized
+ @type:
+ function
+ @title:
+ $window.isMinimized
+ @short:
+ Checks if a window is currently minimized
+ @syntax:
+ $window.isMinimized
+ $window.isMinimized(<window_id>)
+ @description:
+ Returns 1 if the window specified by <window_id> is currently minimized and 0 otherwise.
+ The form with no parameters works on the current window. If the specified window
+ doesn't exist then 0 is returned.
+ @seealso:
+ [fnc]$window.isMaximized[/fnc], [cmd]window.maximize[/cmd],
+ [cmd]window.minimize[/cmd], [cmd]window.restore[/cmd]
+*/
+
+static bool window_kvs_fnc_isMinimized(KviKvsModuleFunctionCall * c)
+{
+ GET_KVS_FNC_WINDOW_ID
+ if(pWnd)
+ {
+ c->returnValue()->setBoolean(pWnd->isMinimized() ? true : false);
+ }
+ return true;
+}
+
+/*
+ @doc: window.hasInput
+ @type:
+ function
+ @title:
+ $window.hasInput
+ @short:
+ Checks if a window has an input field
+ @syntax:
+ $window.hasInput
+ $window.hasInput(<window_id>)
+ @description:
+ Returns 1 if the window specified by <window_id> has an input field and 0 otherwise.
+ The form with no parameters works on the current window. If the specified window
+ doesn't exist then 0 is returned.
+ @seealso:
+ [fnc]$window.hasOutput[/fnc]
+*/
+
+static bool window_kvs_fnc_hasInput(KviKvsModuleFunctionCall * c)
+{
+ GET_KVS_FNC_WINDOW_ID
+ if(pWnd)
+ {
+ c->returnValue()->setBoolean(pWnd->input() ? true : false);
+ } else
+ c->returnValue()->setBoolean(false);
+ return true;
+}
+
+/*
+ @doc: window.hasUserFocus
+ @type:
+ function
+ @title:
+ $window.hasUserFocus
+ @short:
+ Checks if a window has the user focus
+ @syntax:
+ $window.hasUserFocus
+ $window.hasUserFocus(<window_id>)
+ @description:
+ Returns 1 if the window specified by <window_id> has
+ currently the user focus and 0 otherwise.
+ The form with no parameters works on the current window.
+ If the specified window doesn't exist then 0 is returned.
+ A window has the user focus if it is the KVIrc's active
+ window and has the user's input focus (i.e. typing
+ on the keyboard will write in this window).
+ @seealso:
+*/
+
+static bool window_kvs_fnc_hasUserFocus(KviKvsModuleFunctionCall * c)
+{
+ GET_KVS_FNC_WINDOW_ID
+ if(pWnd)
+ {
+ bool b = (pWnd == g_pActiveWindow) && pWnd->isActiveWindow();
+ c->returnValue()->setBoolean(b ? true : false);
+ } else
+ c->returnValue()->setBoolean(false);
+ return true;
+}
+
+/*
+ @doc: window.console
+ @type:
+ function
+ @title:
+ $window.console
+ @short:
+ Returns the console that a window is attacched to
+ @syntax:
+ $window.console
+ $window.console(<window_id>)
+ @description:
+ Returns the id of the console window that the window specified by window_id is attacched to.
+ The console is the main (and only) console of the IRC context. If window_id is missing then
+ the current window is used. If this window does not belong to an irc context (and thus has
+ no attacched console) then 0 is returned.
+ @seealso:
+*/
+
+static bool window_kvs_fnc_console(KviKvsModuleFunctionCall * c)
+{
+ GET_KVS_FNC_WINDOW_ID
+ if(pWnd)
+ {
+ c->returnValue()->setInteger(pWnd->console() ? QString(pWnd->console()->id()).toInt() : 0);
+ }
+ return true;
+}
+
+/*
+ @doc: window.hasOutput
+ @type:
+ function
+ @title:
+ $window.hasOutput
+ @short:
+ Checks if a window has a text output widget
+ @syntax:
+ $window.hasOutput
+ $window.hasOutput(<window_id>)
+ @description:
+ Returns 1 if the window specified by <window_id> has a text output widget and 0 otherwise.
+ The form with no parameters works on the current window. If the specified window
+ doesn't exist then 0 is returned.
+ @seealso:
+ [fnc]$window.hasInput[/fnc]
+*/
+
+static bool window_kvs_fnc_hasOutput(KviKvsModuleFunctionCall * c)
+{
+ GET_KVS_FNC_WINDOW_ID
+ if(pWnd)
+ {
+ c->returnValue()->setBoolean(pWnd->view() ? true : false);
+ } else
+ c->returnValue()->setBoolean(false);
+ return true;
+}
+
+/*
+ @doc: window.exists
+ @type:
+ function
+ @title:
+ $window.exists
+ @short:
+ Checks for the existence of a window
+ @syntax:
+ $window.exists(<window_id>)
+ @description:
+ Returns 1 if a specified window exists
+ @seealso:
+*/
+
+static bool window_kvs_fnc_exists(KviKvsModuleFunctionCall * c)
+{
+ GET_KVS_FNC_WINDOW_ID
+ if(pWnd)
+ {
+ c->returnValue()->setBoolean(true);
+ } else
+ c->returnValue()->setBoolean(false);
+ return true;
+}
+
+/*
+ @doc: window.type
+ @type:
+ function
+ @title:
+ $window.type
+ @short:
+ Returns the type of a window
+ @syntax:
+ $window.type
+ $window.type(<window_id>)
+ @description:
+ Returns the type of the window with <window_id>.[br]
+ The form with no parameters returns the type of the current window.[br]
+ If the window with the specified id does not exist, an empty string is returned.[br]
+ @seealso:
+*/
+
+static bool window_kvs_fnc_type(KviKvsModuleFunctionCall * c)
+{
+ GET_KVS_FNC_WINDOW_ID
+ if(pWnd)
+ {
+ c->returnValue()->setString(pWnd->typeString());
+ }
+ return true;
+}
+
+/*
+ @doc: window.context
+ @type:
+ function
+ @title:
+ $window.context
+ @short:
+ Returns the IRC context of a window
+ @syntax:
+ $window.context
+ $window.context(<window_id>)
+ @description:
+ Returns the IRC context of the window with the specified <window_id>.[br]
+ The form with no parameters returns the IRC context of the current window.[br]
+ If the window with the specified id does not exist, an empty string is returned.[br]
+ @seealso:
+*/
+
+static bool window_kvs_fnc_context(KviKvsModuleFunctionCall * c)
+{
+ GET_KVS_FNC_WINDOW_ID
+ if(pWnd)
+ {
+ c->returnValue()->setInteger(pWnd->console() ? pWnd->console()->ircContextId() : 0);
+ }
+ return true;
+}
+
+/*
+ @doc: window.caption
+ @type:
+ function
+ @title:
+ $window.caption
+ @short:
+ Returns the caption of a window
+ @syntax:
+ $window.caption
+ $window.caption(<window_id>)
+ @description:
+ Returns the caption of the window with <window_id>.[br]
+ The form with no parameters returns the caption of the current window.[br]
+ If the window with the specified id does not exist, an empty string is returned.[br]
+ @seealso:
+*/
+
+static bool window_kvs_fnc_caption(KviKvsModuleFunctionCall * c)
+{
+ GET_KVS_FNC_WINDOW_ID
+ if(pWnd)
+ {
+ c->returnValue()->setString(pWnd->plainTextCaption());
+ }
+ return true;
+}
+
+/*
+ @doc: window.listtypes
+ @type:
+ command
+ @title:
+ window.listtypes
+ @short:
+ Lists available types of windows
+ @syntax:
+ window.listtypes
+ @description:
+ Lists the types of windows that are built in the current release of KVIrc.[br]
+ This is actually a command and not a static list just because new window
+ types may be added in subsequent releases.[br]
+ @seealso:
+ [cmd]window.listtypes[/cmd]
+*/
+
+static bool window_kvs_cmd_listtypes(KviKvsModuleCommandCall * c)
+{
+ c->window()->listWindowTypes();
+ return true;
+}
+
+/*
+ @doc: window.list
+ @type:
+ function
+ @title:
+ $window.list
+ @short:
+ Generates lists of windows
+ @syntax:
+ $window.list(<type>[,<irc_context_id>])
+ @description:
+ Returns an array of window identifiers with a speficied type and eventually belonging to a specified
+ irc context.[br]
+ <type> is a window type such as 'query' or 'channel'.[br]
+ See [cmd]window.listtypes[/cmd] for a list of available window types in this KVIrc release.[br]
+ If <type> is the special word 'all', all the window types are listed.[br]
+ <irc_context_id> specifies the irc context in which the windows are searched.[br]
+ If no <irc_context_id> is specified , the current one is used.[br]
+ If <irc_context_id> is the special word 'all', all the irc context are searched.[br]
+ If <irc_context_id> is the special word 'none' then only windows not belonging to any
+ irc context are listed.[br]
+ The special word 'any' used as <irc_context_id> merges the effects of 'all' and 'none'
+ by searching all the irc contexts AND the windows not belonging to any irc context.[br]
+ The windows that do not belong to any irc context (such as DCC windows), must be searched
+ by using 'none' or 'any' as <irc_context_id>.
+ @examples:
+ [example]
+ [comment]# List all the queries of the current irc context[/comment]
+ [cmd]echo[/cmd] $window.list(query)
+ [comment]# Equivalent to the above[/comment]
+ [cmd]echo[/cmd] $window.list(query,[fnc]$ic[/fnc])
+ [comment]# List all the channels in all the irc contexts[/comment]
+ [cmd]echo[/cmd] $window.list(channel,all)
+ [comment]# List all the windows in the current irc context[/comment]
+ [cmd]echo[/cmd] $window.list(all)
+ [comment]# List all the windows in all irc contexts[/comment]
+ [cmd]echo[/cmd] $window.list(all,all)
+ [comment]# List all the DCC Send windows: They don't belong to any irc context[/comment]
+ [cmd]echo[/cmd] $window.list(dccsend,none)
+ [comment]# List all the user windows created with $window.open[/comment]
+ [comment]# They may either belong to an irc context or not[/comment]
+ [cmd]echo[/cmd] $window.list(userwnd,any)
+ [comment]# Ok , let's use it[/comment]
+ [comment]# A nice alias that allows iterating commands through all the consoles[/comment]
+ [comment]# Note the array returned by $window.list[/comment]
+ [comment]# This is by LatinSuD :)[/comment]
+ [cmd]alias[/cmd](iterate)
+ {
+ %ctxt[]=[fnc]$window.list[/fnc](console,all)
+ [cmd]for[/cmd](%i=0;%i<%ctxt[]#;%i++)
+ {
+ [cmd]eval[/cmd] -r=%ctxt[%i] $0-
+ }
+ }
+ iterate [cmd]echo[/cmd] Hi ppl! :)
+ [comment]# The returned array works nicely also in [cmd]foreach[/cmd][/comment]
+ [comment]# Say hi to all the channels :)[/comment]
+ [cmd]alias[/cmd](sayallchans)
+ {
+ [cmd]foreach[/cmd](%x,[fnc]$window.list[/fnc](channel,all))
+ [cmd]say[/cmd] -r=%x $0-;
+ }
+ sayallchans Hi ppl :)
+ [/example]
+ @seealso:
+ [cmd]window.listtypes[/cmd]
+*/
+
+static bool window_kvs_fnc_list(KviKvsModuleFunctionCall * c)
+{
+ QString szType;
+ QString szContext;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("type",KVS_PT_STRING,0,szType)
+ KVSM_PARAMETER("irc_context_id",KVS_PT_STRING,KVS_PF_OPTIONAL,szContext)
+ KVSM_PARAMETERS_END(c)
+ KviKvsArray* pArray = new KviKvsArray();
+ c->returnValue()->setArray(pArray);
+
+ if(szType.isEmpty())
+ {
+ c->warning(__tr2qs("Window type or 'all' expected as first parameter"));
+ return true;
+ }
+
+ int id=0;
+
+ if(KviQString::equalCI(szContext,"all"))
+ {
+ // all contexts but no "no_context" windows
+ bool bAllWindows = KviQString::equalCI(szType,"all");
+ KviPointerHashTableIterator<const char *,KviWindow> it(*g_pGlobalWindowDict);
+
+ while(KviWindow * wnd = it.current())
+ {
+ if(wnd->context())
+ {
+ if(bAllWindows)
+ {
+ pArray->set(id, new KviKvsVariant(QString(wnd->id())));
+ id++;
+ } else {
+ if(szType.lower()==wnd->typeString())
+ {
+ pArray->set(id, new KviKvsVariant(QString(wnd->id())));
+ id++;
+ }
+ }
+ }
+ ++it;
+ }
+ } else if(KviQString::equalCI(szContext,"any"))
+ {
+ // all contexts and also "no_context" windows
+ bool bAllWindows = KviQString::equalCI(szType.lower(),"all");
+ KviPointerHashTableIterator<const char *,KviWindow> it(*g_pGlobalWindowDict);
+
+ while(KviWindow * wnd = it.current())
+ {
+ if(bAllWindows)
+ {
+ pArray->set(id, new KviKvsVariant(QString(wnd->id())));
+ id++;
+ } else {
+ if(szType.lower()==wnd->typeString())
+ {
+ pArray->set(id, new KviKvsVariant(QString(wnd->id())));
+ id++;
+ }
+ }
+ ++it;
+ }
+ } else if(KviQString::equalCI(szContext,"none"))
+ {
+ // only "no_context" windows
+ bool bAllWindows = KviQString::equalCI(szType.lower(),"all");
+ KviPointerHashTableIterator<const char *,KviWindow> it(*g_pGlobalWindowDict);
+
+ while(KviWindow * wnd = it.current())
+ {
+ if(!wnd->context())
+ {
+ if(bAllWindows)
+ {
+ pArray->set(id, new KviKvsVariant(QString(wnd->id())));
+ id++;
+ } else {
+ if(szType.lower()==wnd->typeString())
+ {
+ pArray->set(id, new KviKvsVariant(QString(wnd->id())));
+ id++;
+ }
+ }
+ }
+ ++it;
+ }
+
+ } else {
+ // some specified context
+ unsigned int uId = 0;
+
+ if(!szContext.isEmpty())
+ {
+ // specific context
+ bool bOk;
+ uId = szContext.toUInt(&bOk);
+ if(!bOk)
+ {
+ c->warning(__tr2qs("Invalid IRC context id '%Q'"),&szContext);
+ return true;
+ }
+ } else {
+ // current irc context
+ if(!c->window()->console())
+ {
+ return true;
+ }
+ uId = c->window()->console()->ircContextId();
+ }
+
+ bool bAllWindows = KviQString::equalCI(szType.lower(),"all");
+ KviPointerHashTableIterator<const char *,KviWindow> it(*g_pGlobalWindowDict);
+
+ while(KviWindow * wnd = it.current())
+ {
+ if(wnd->console())
+ {
+ if(wnd->console()->ircContextId() == uId)
+ {
+ if(bAllWindows)
+ {
+ pArray->set(id, new KviKvsVariant(QString(wnd->id())));
+ id++;
+ } else {
+ if(szType.lower()==wnd->typeString())
+ {
+ pArray->set(id, new KviKvsVariant(QString(wnd->id())));
+ id++;
+ }
+ }
+ }
+ }
+ ++it;
+ }
+ }
+ return true;
+
+}
+
+/*
+ @doc: window.open
+ @type:
+ function
+ @title:
+ $window.open
+ @short:
+ Creates and opens a new window
+ @syntax:
+ $window.open([<flags:string>[,<caption:string>[,<irc_context:integer>[,<icon:integer>]]]])
+ @description:
+ Creates a new window, opens it and returns its window identifier.
+ <flags> may be any combination of the following flag characters:[br]
+ [b]i[/b]: Causes the window to have an input field in that
+ the user can type commands or text. The text typed is reported
+ by the [event:ontextinput]OnTextInput[/event] event.[br]
+ [b]m[/b]: Creates a window that is initially minimized.[br]
+ [b]q[/b]: Don't print warning messages during the creation.[br]
+ If <caption> is given then the new window will have it as the initial plain text <caption>.
+ You can change the caption later by calling [cmd]window.setCaption[/cmd].[br]
+ If <irc_context> is given then the new window is bound to the specified irc context
+ and will be destroyed when the attacched console closes.
+ If <irc_context> is omitted or is 0 then the window will be context free (not bound
+ to any context) and will exist until it is closed by the GUI, by a [cmd]window.close[/cmd]
+ call or until KVIrc terminates. When <irc_context> is given but is not valid
+ then a warning is printed (unless the q flag is used) and the created window is context free.[br]
+ You will generally use the [fnc]$context[/fnc] function to retrieve the current IRC context id.[br]
+ [br]
+ <icon> is intepreted as the index of the internal icon to be used
+ for the window. If <icon> is omitted then a default icon is used.[br]
+ @examples:
+ [example]
+ %w = $window.open()
+ [cmd]window.close[/cmd] %w
+ %w = $window.open("m","My funky window")
+ [cmd]window.close[/cmd] %w
+ %w = $window.open("im","My funky window 2",$context,10)
+ [/example]
+ @seealso:
+ [cmd]window.close[/cmd]
+*/
+
+static bool window_kvs_fnc_open(KviKvsModuleFunctionCall * c)
+{
+ QString szFlags;
+ QString szCaption;
+ kvs_uint_t uCtx;
+ kvs_int_t iIcon;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("flags",KVS_PT_STRING,KVS_PF_OPTIONAL,szFlags)
+ KVSM_PARAMETER("caption",KVS_PT_STRING,KVS_PF_OPTIONAL,szCaption)
+ KVSM_PARAMETER("irc_context",KVS_PT_UINT,KVS_PF_OPTIONAL,uCtx)
+ KVSM_PARAMETER("icon",KVS_PT_INT,KVS_PF_OPTIONAL,iIcon)
+ KVSM_PARAMETERS_END(c)
+ iIcon = iIcon % KVI_NUM_SMALL_ICONS;
+
+ int iFlags = 0;
+ if(szFlags.contains('i'))iFlags |= KviUserWindow::HasInput;
+
+ KviConsole * pConsole = 0;
+ if(c->parameterList()->count() >= 3)
+ {
+ pConsole = g_pApp->findConsole(uCtx);
+ if(!pConsole && !szFlags.contains('q'))
+ {
+ c->warning(__tr2qs("The specified IRC context is not valid: creating a context free window"));
+ }
+ }
+
+ KviUserWindow * wnd = new KviUserWindow(
+ c->window()->frame(),
+ szCaption,
+ iIcon,
+ pConsole,
+ iFlags);
+
+ c->window()->frame()->addWindow(wnd,!szFlags.contains('m'));
+ if(szFlags.contains('m'))wnd->minimize();
+
+ c->returnValue()->setInteger(QString(wnd->id()).toUInt());
+ return true;
+}
+
+/*
+ @doc: window.setCaption
+ @type:
+ command
+ @title:
+ window.setCaption
+ @short:
+ Sets the caption of an user window
+ @syntax:
+ window.setCaption [-q] <window_id> <plain_text_caption> [html_inactive_caption] [html_active_caption]
+ @switches:
+ !sw: -q | --quiet
+ Be quiet
+ @description:
+ Sets the caption of the user window specified by <window_id> to <plain_text_caption>.[br]
+ If <window_id> is an empty string then the current window is assumed.[br]
+ The window must be of type userwnd and must have been created by [fnc]$window.open[/fnc]:
+ it is not possible to change the caption of other window types.[br]
+ If the window is not of the expected type then a warning is printed unless the -q switch is used.[br]
+ If [html_inactive_caption] and/or [html_active_caption] are given then
+ the html versions of the captions displayed in the window caption bars
+ are set too. If one of these parameters is missing then <plain_text_caption> is
+ used for the html versions too. The html captions can contain limited html code. In particular
+ you're allowed to use the &lt;nobr&gt;,&lt;font&gt;,&lt;b&gt; and &lt;i&gt; html tags.
+ It is better to avoid using colored fonts since you can't know which color scheme the
+ user will have set.[br]
+ If the specified window does not exist a warning is printed unless the -q switch is used.
+ @seealso:
+*/
+
+static bool window_kvs_cmd_setCaption(KviKvsModuleCommandCall * c)
+{
+ QString szWnd;
+ QString szPlain;
+ QString szInactive;
+ QString szActive;
+ KviWindow * pWnd;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("window_id",KVS_PT_STRING,0,szWnd)
+ KVSM_PARAMETER("plain_text_caption",KVS_PT_STRING,0,szPlain)
+ KVSM_PARAMETER("html_inactive_caption",KVS_PT_STRING,KVS_PF_OPTIONAL,szInactive)
+ KVSM_PARAMETER("html_active_caption",KVS_PT_STRING,KVS_PF_OPTIONAL,szActive)
+ KVSM_PARAMETERS_END(c)
+
+ pWnd = g_pApp->findWindow(szWnd.utf8().data());
+ if(!pWnd)
+ {
+ if(!c->hasSwitch('q',"quiet"))
+ c->warning(__tr2qs("The window with id '%s' does not exist"),szWnd.utf8().data());
+ return true;
+ }
+
+ if(pWnd->type() == KVI_WINDOW_TYPE_USERWINDOW)
+ {
+ ((KviUserWindow *)pWnd)->setCaptionStrings(szPlain,szInactive,szActive);
+ } else {
+ if(!c->hasSwitch('q',"quiet"))c->warning(__tr2qs("The specified window is not of type \"userwnd\""));
+ }
+ return true;
+}
+
+/*
+ @doc: window.setInputText
+ @type:
+ command
+ @title:
+ window.setInputText
+ @short:
+ Sets the window input text to <text>
+ @syntax:
+ window.setInputText [-q] <window_id:integer> <text:string>
+ @switches:
+ !sw: -q | --quiet
+ Be quiet
+ @description:
+ Sets the window input text to <text>
+ @seealso:
+ [cmd]window.setInputText[/cmd] [cmd]window.insertInInputText[/cmd] [fnc]$window.inputText[/fnc]
+*/
+
+static bool window_kvs_cmd_setInputText(KviKvsModuleCommandCall * c)
+{
+ QString szWnd;
+ QString szText;
+ KviWindow * pWnd;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("window_id",KVS_PT_STRING,0,szWnd)
+ KVSM_PARAMETER("text",KVS_PT_STRING,0, szText)
+ KVSM_PARAMETERS_END(c)
+
+ pWnd = g_pApp->findWindow(szWnd.utf8().data());
+ if(!pWnd)
+ {
+ if(!c->hasSwitch('q',"quiet"))
+ c->warning(__tr2qs("The window with id '%s' does not exist"),szWnd.utf8().data());
+ return true;
+ }
+ if(pWnd->input())
+ pWnd->input()->setText(szText);
+ else
+ if(!c->hasSwitch('q',"quiet")) c->warning(__tr2qs("Window doesn't have input widget"));
+
+ return true;
+}
+
+
+/*
+ @doc: window.insertInInputText
+ @type:
+ command
+ @title:
+ window.insertInInputText
+ @short:
+ Sets the window input text to <text>
+ @syntax:
+ window.insertInInputText [-q] <window_id:integer> <text:string>
+ @switches:
+ !sw: -q | --quiet
+ Be quiet
+ @description:
+ Sets the window input text to <text>
+ @seealso:
+ [cmd]window.setInputText[/cmd], [fnc]$window.inputText[/fnc]
+*/
+
+static bool window_kvs_cmd_insertInInputText(KviKvsModuleCommandCall * c)
+{
+ QString szWnd;
+ QString szText;
+ KviWindow * pWnd;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("window_id",KVS_PT_STRING,0,szWnd)
+ KVSM_PARAMETER("text",KVS_PT_STRING,0, szText)
+ KVSM_PARAMETERS_END(c)
+
+ pWnd = g_pApp->findWindow(szWnd.utf8().data());
+ if(!pWnd)
+ {
+ if(!c->hasSwitch('q',"quiet"))
+ c->warning(__tr2qs("The window with id '%s' does not exist"),szWnd.utf8().data());
+ return true;
+ }
+ if(pWnd->input())
+ pWnd->input()->insertText(szText);
+ else
+ if(!c->hasSwitch('q',"quiet")) c->warning(__tr2qs("Window doesn't have input widget"));
+
+ return true;
+}
+
+/*
+ @doc: $window.inputText
+ @type:
+ function
+ @title:
+ $window.inputText
+ @short:
+ Returns the window input line text
+ @syntax:
+ $window.inputText(<window_id:integer>)
+ @description:
+ Returns the window input line text
+ @seealso:
+ [cmd]window.setInputText[/cmd],
+ [cmd]window.insertInInputText[/cmd]
+*/
+
+static bool window_kvs_fnc_inputText(KviKvsModuleFunctionCall * c)
+{
+ GET_KVS_FNC_WINDOW_ID
+ if(pWnd)
+ {
+ if(pWnd->input())
+ c->returnValue()->setString(pWnd->input()->text());
+ }
+ return true;
+}
+
+/*
+ @doc: window.setBackground
+ @type:
+ command
+ @title:
+ window.setBackground
+ @short:
+ Sets the background image of a window
+ @syntax:
+ window.setBackground [-q] <window_id:integer> <image_id:string>
+ @switches:
+ !sw: -q | --quiet
+ Be quiet
+ @description:
+ Sets the background image of the window specified by <window_id> to <image_id>.[br]
+ If <window_id> is an empty string then the current window is assumed.[br]
+ If the specified window or the background image does not exist a warning is printed unless the -q switch is used.
+ @seealso:
+*/
+
+static bool window_kvs_cmd_setBackground(KviKvsModuleCommandCall * c)
+{
+ QString szWnd;
+ QString szBackground;
+ KviWindow * pWnd;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("window_id",KVS_PT_STRING,0,szWnd)
+ KVSM_PARAMETER("plain_text_caption",KVS_PT_STRING,0, szBackground)
+ KVSM_PARAMETERS_END(c)
+
+ pWnd = g_pApp->findWindow(szWnd.utf8().data());
+ if(!pWnd)
+ {
+ if(!c->hasSwitch('q',"quiet"))
+ c->warning(__tr2qs("The window with id '%s' does not exist"),szWnd.utf8().data());
+ return true;
+ }
+
+ /*
+ QPixmap *pix=0;
+ pix = g_pIconManager->getImage(szBackground);
+ if (!pix){
+ KviScriptObject * ob = g_pScriptObjectController->lookupObject(szBackground);
+ if(!ob){
+ if(!c->hasSwitch('q',"quiet")) c->warning(__tr2qs("Background not found %Q "),&szBackground);
+ return true;
+ }
+ if(!ob->inherits("KviScriptPixmapObject")){
+ c->warning(__tr("Pixmap objects required !"));
+ return true;
+ }
+ QVariant pix1= ob->property("pixmap");
+ if (!pix1.asPixmap().isNull()){
+ c->warning(__tr("Pixmap is null"));
+ return true;
+ }
+ pWnd->view()->setPrivateBackgroundPixmap(pix1.asPixmap());
+ return true;
+ }
+ if(pWnd)
+ pWnd->view()->setPrivateBackgroundPixmap(*pix);
+ */
+
+ //FIXME: This is broken
+
+ return true;
+}
+
+/*
+ @doc: window.setCryptEngine
+ @type:
+ command
+ @title:
+ window.setCryptEngine
+ @short:
+ Sets the crypt engine for a window that supports it
+ @syntax:
+ window.setCryptEngine [-q] [-n] [-m] <window_id:integer> <enginename:string> <hex_encrypt_key;string> [hex_decrypt_key:string]
+ @switches:
+ !sw: -q | --quiet
+ Be quiet: do echo the raw data.
+ !sw: -n | --onlydecrypt
+ Disables encryption
+ !sw: -m | --onlyencrypt
+ Disables decryption
+ @description:
+ Sets the specified [doc:crypt_engines]cryptographic engine[/doc] for the window. If <enginename> is empty
+ then any current crypting engine is removed (i.e. crypting is disabled).
+ The must be both expressed in hexadecimal notation and are internally transformed in bytes.
+ If only the encrypt key is specified then it will be used for both encrypting and
+ decrypting. This command works only if crypt support is compiled in.
+ @examples:
+ [example]
+ [comment]# This is a really lame example :D[/comment]
+ alias(saylame)
+ {
+ window.setCryptEngine $window Lamerizer
+ say $0-
+ window.setCryptEngine $window
+ }
+ saylame Hello eleet!
+ [/example]
+
+ @seealso:
+ [fnc]$asciiToHex[/fnc], [fnc]$features[/fnc]
+*/
+
+
+#ifdef COMPILE_CRYPT_SUPPORT
+static bool initializeCryptEngine(KviCryptEngine * eng,KviStr &szEncryptKey,KviStr &szDecryptKey,QString &szError)
+{
+ char * encKey = 0;
+ int encKeyLen = 0;
+
+ char * tmpKey;
+ encKeyLen = szEncryptKey.hexToBuffer(&tmpKey,false);
+ if(encKeyLen > 0)
+ {
+ encKey = (char *)kvi_malloc(encKeyLen);
+ kvi_memmove(encKey,tmpKey,encKeyLen);
+ KviStr::freeBuffer(tmpKey);
+ } else {
+ szError = __tr2qs("The encrypt key wasn't a valid hexadecimal string");
+ return false;
+ }
+
+ char * decKey = 0;
+ int decKeyLen = 0;
+
+ decKeyLen = szDecryptKey.hexToBuffer(&tmpKey,false);
+ if(decKeyLen > 0)
+ {
+ decKey = (char *)kvi_malloc(decKeyLen);
+ kvi_memmove(decKey,tmpKey,decKeyLen);
+ KviStr::freeBuffer(tmpKey);
+ } else {
+ szError = __tr2qs("The decrypt key wasn't a valid hexadecimal string");
+ return false;
+ }
+ bool bRet = eng->init(encKey,encKeyLen,decKey,decKeyLen);
+ if(!bRet)
+ szError = eng->lastError();
+ if(encKey)kvi_free(encKey);
+ if(decKey)kvi_free(decKey);
+ return bRet;
+}
+#endif
+
+static bool window_kvs_cmd_setCryptEngine(KviKvsModuleCommandCall * c)
+{
+ QString szWnd;
+ QString szEngine;
+ QString szEncryptKey;
+ QString szDecryptKey;
+ KviWindow * pWnd;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("window_id",KVS_PT_STRING,0,szWnd)
+ KVSM_PARAMETER("enginename",KVS_PT_STRING,KVS_PF_OPTIONAL,szEngine)
+ KVSM_PARAMETER("hex_encrypt_key",KVS_PT_STRING,KVS_PF_OPTIONAL,szEncryptKey)
+ KVSM_PARAMETER("hex_decrypt_key",KVS_PT_STRING,KVS_PF_OPTIONAL,szDecryptKey)
+ KVSM_PARAMETERS_END(c)
+ if(szDecryptKey.isEmpty())szDecryptKey = szEncryptKey;
+#ifdef COMPILE_CRYPT_SUPPORT
+ pWnd = g_pApp->findWindow(szWnd.utf8().data());
+ if(!pWnd)
+ {
+ if(!c->hasSwitch('q',"quiet"))
+ c->warning(__tr2qs("The window with id '%s' does not exist"),szWnd.utf8().data());
+ return true;
+ }
+ if(c->hasSwitch('n',"onlydecrypt") && c->hasSwitch('m',"onlyencrypt"))
+ {
+ if(!c->hasSwitch('q',"quiet"))
+ c->warning(__tr2qs("Both -n and -m switchess specified, -n takes precedence"));
+ }
+
+ if(szEngine.isEmpty())
+ {
+ pWnd->setCryptSessionInfo(0);
+ } else {
+ if(szEncryptKey.isEmpty() || szDecryptKey.isEmpty())
+ {
+ if(!c->hasSwitch('q',"quiet"))
+ c->warning(__tr2qs("No encrypt key specified: can't allocate engine"));
+ return true;
+ }
+
+ (void)g_pModuleManager->loadModulesByCaps("crypt");
+
+ KviCryptEngine * e = g_pCryptEngineManager->allocateEngine(szEngine.utf8().data());
+ if(e)
+ {
+ KviStr enc = KviStr(szEncryptKey.utf8().data());
+ KviStr dec = KviStr(szDecryptKey.utf8().data());
+ QString szError;
+ if(initializeCryptEngine(e,enc,dec,szError))
+ {
+ KviCryptSessionInfo * inf = KviCryptController::allocateCryptSessionInfo();
+ inf->pEngine = e;
+ inf->szEngineName = szEngine;
+
+ inf->bDoEncrypt = (!c->hasSwitch('n',"onlydecrypt"));
+ inf->bDoDecrypt = (!c->hasSwitch('m',"onlyencrypt")) || c->hasSwitch('n',"onlydecrypt");
+ pWnd->setCryptSessionInfo(inf);
+ } else {
+ if(szError.isEmpty())szError = __tr2qs("Unknown engine error");
+ g_pCryptEngineManager->deallocateEngine(e);
+ if(!c->hasSwitch('q',"quiet"))
+ c->warning(__tr2qs("Failed to initialize the specified crypt engine: %Q"),&szError);
+ }
+ } else {
+ if(!c->hasSwitch('q',"quiet"))
+ c->warning(__tr2qs("The crypt engine \"%Q\" does not exist"),&szEngine);
+ }
+ }
+#else
+ if(!c->hasSwitch('q',"quiet"))
+ c->warning(__tr2qs("This executable has been compiled without crypt support"));
+#endif
+ return true;
+}
+
+static bool window_module_init(KviModule *m)
+{
+ g_pUserWindowList = new KviPointerList<KviUserWindow>();
+ g_pUserWindowList->setAutoDelete(false);
+
+ KVSM_REGISTER_FUNCTION(m,"activityTemperature",window_kvs_fnc_activityTemperature);
+ KVSM_REGISTER_FUNCTION(m,"activityLevel",window_kvs_fnc_activityLevel);
+ KVSM_REGISTER_FUNCTION(m,"console",window_kvs_fnc_console);
+ KVSM_REGISTER_FUNCTION(m,"hasUserFocus",window_kvs_fnc_hasUserFocus);
+ KVSM_REGISTER_FUNCTION(m,"hasOutput",window_kvs_fnc_hasOutput);
+ KVSM_REGISTER_FUNCTION(m,"isMinimized",window_kvs_fnc_isMinimized);
+ KVSM_REGISTER_FUNCTION(m,"isMaximized",window_kvs_fnc_isMaximized);
+ KVSM_REGISTER_FUNCTION(m,"caption",window_kvs_fnc_caption);
+ KVSM_REGISTER_FUNCTION(m,"type",window_kvs_fnc_type);
+ KVSM_REGISTER_FUNCTION(m,"exists",window_kvs_fnc_exists);
+ KVSM_REGISTER_FUNCTION(m,"hasInput",window_kvs_fnc_hasInput);
+ KVSM_REGISTER_FUNCTION(m,"list",window_kvs_fnc_list);
+ KVSM_REGISTER_FUNCTION(m,"open",window_kvs_fnc_open);
+ KVSM_REGISTER_FUNCTION(m,"inputText",window_kvs_fnc_inputText);
+ KVSM_REGISTER_FUNCTION(m,"context",window_kvs_fnc_context);
+
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"close",window_kvs_cmd_close);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"clearOutput",window_kvs_cmd_clearOutput);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"dock",window_kvs_cmd_dock);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"undock",window_kvs_cmd_undock);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"maximize",window_kvs_cmd_maximize);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"minimize",window_kvs_cmd_minimize);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"restore",window_kvs_cmd_restore);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"activate",window_kvs_cmd_activate);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"demandAttention",window_kvs_cmd_demandAttention);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"listtypes",window_kvs_cmd_listtypes);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"setBackground",window_kvs_cmd_setBackground);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"setCaption",window_kvs_cmd_setCaption);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"setCryptEngine",window_kvs_cmd_setCryptEngine);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"setInputText",window_kvs_cmd_setInputText);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"insertInInputText",window_kvs_cmd_insertInInputText);
+
+ // saveOutput (view()->saveBuffer())
+/*
+ m->registerFunction("geometry",window_module_fnc_geometry);
+ m->registerCommand("setGeometry",window_module_cmd_setGeometry);
+
+ m->registerFunction("isActive",window_module_fnc_isActive);
+
+
+ // Output stuff
+ m->registerFunction("outputBufferSize",window_module_fnc_outputBufferSize);
+ m->registerCommand("setOutputBufferSize",window_module_cmd_setOutputBufferSize);
+
+ m->registerFunction("outputShowsImages",window_module_fnc_outputShowsImages);
+ m->registerCommand("setOutputShowsImages",window_module_cmd_setOutputShowsImages);
+
+ m->registerFunction("outputTimestamp",window_module_fnc_outputTimestamp);
+ m->registerCommand("setOutputTimestamp",window_module_cmd_setOutputTimestamp);
+
+ m->registerFunction("hasOutputBackgroundPixmap",window_module_fnc_hasOutputBackgroundPixmap);
+ m->registerCommand("setOutputBackgroundPixmap",window_module_cmd_setOutputBackgroundPixmap);
+
+*/
+ return true;
+}
+
+static bool window_module_cleanup(KviModule *m)
+{
+ while(KviUserWindow * w = g_pUserWindowList->first())
+ w->close();
+ delete g_pUserWindowList;
+ return true;
+}
+
+static bool window_module_can_unload(KviModule *m)
+{
+ return g_pUserWindowList->isEmpty();
+}
+
+KVIRC_MODULE(
+ "Window", // module name
+ "1.0.0", // module version
+ "Copyright (C) 2001-2004 Szymon Stefanek (pragma at kvirc dot net)", // author & (C)
+ "KVIrc window management functions",
+ window_module_init,
+ window_module_can_unload,
+ 0,
+ window_module_cleanup
+)
diff --git a/src/modules/window/userwindow.cpp b/src/modules/window/userwindow.cpp
new file mode 100644
index 00000000..08a7405b
--- /dev/null
+++ b/src/modules/window/userwindow.cpp
@@ -0,0 +1,107 @@
+//=============================================================================
+//
+// File : userwindow.cpp
+// Created on Mon 30 Aug 2004 15:00:52 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "userwindow.h"
+
+#include "kvi_iconmanager.h"
+#include "kvi_input.h"
+#include "kvi_ircview.h"
+#include "kvi_frame.h"
+#include "kvi_console.h"
+
+extern KviPointerList<KviUserWindow> * g_pUserWindowList;
+
+
+KviUserWindow::KviUserWindow(KviFrame * pFrm,const char * name,int iIcon,KviConsole * pConsole,int iCreationFlags)
+: KviWindow(KVI_WINDOW_TYPE_USERWINDOW,pFrm,name,pConsole)
+{
+ g_pUserWindowList->append(this);
+
+ m_iIcon = iIcon;
+
+ m_szPlainTextCaption = name;
+ m_szHtmlActiveCaption = name;
+ m_szHtmlInactiveCaption = name;
+
+ // Register ourselves
+ //connection()->registerChannel(this);
+ // Central splitter
+// m_pSplitter = new QSplitter(QSplitter::Horizontal,this,"main_splitter");
+ // Spitted vertially on the left
+// m_pVertSplitter = new QSplitter(QSplitter::Vertical,m_pSplitter,
+// "vertical_splitter");
+ // With the IRC view over
+ m_pIrcView = new KviIrcView(this,pFrm,this);
+ // connect(m_pIrcView,SIGNAL(rightClicked()),this,SLOT(textViewRightClicked()));
+ // The userlist on the right
+// m_pUserListView = new KviUserListView(m_pSplitter,connection()->userDataBase(),this,
+// AVERAGE_CHANNEL_USERS,__tr2qs("User List"),"user_list_view");
+ // And finally the input line on the bottom
+ if(iCreationFlags & HasInput)
+ m_pInput = new KviInput(this,0);
+ else
+ m_pInput = 0;
+ // applyOptions();
+
+ if(context())context()->registerContextWindow(this);
+}
+
+KviUserWindow::~KviUserWindow()
+{
+ if(context())context()->unregisterContextWindow(this);
+ g_pUserWindowList->removeRef(this);
+}
+
+QPixmap * KviUserWindow::myIconPtr()
+{
+ return g_pIconManager->getSmallIcon(m_iIcon);
+}
+
+void KviUserWindow::resizeEvent(QResizeEvent *e)
+{
+ if(m_pInput)
+ {
+ int hght = m_pInput->heightHint();
+ m_pIrcView->setGeometry(0,0,width(),height() - hght);
+ m_pInput->setGeometry(0,height() - hght,width(),hght);
+ } else {
+ m_pIrcView->setGeometry(0,0,width(),height());
+ }
+}
+
+void KviUserWindow::fillCaptionBuffers()
+{
+ // nothing here
+}
+
+void KviUserWindow::setCaptionStrings(const QString &szPlainText,const QString &szHtmlInactive,const QString &szHtmlActive)
+{
+ m_szPlainTextCaption = szPlainText;
+ m_szHtmlActiveCaption = szHtmlActive;
+ m_szHtmlInactiveCaption = szHtmlInactive;
+ if(m_szHtmlActiveCaption.isEmpty())m_szHtmlActiveCaption = szPlainText;
+ if(m_szHtmlInactiveCaption.isEmpty())m_szHtmlInactiveCaption = szPlainText;
+ updateCaption();
+}
+
diff --git a/src/modules/window/userwindow.h b/src/modules/window/userwindow.h
new file mode 100644
index 00000000..333b7edb
--- /dev/null
+++ b/src/modules/window/userwindow.h
@@ -0,0 +1,48 @@
+#ifndef _USERWINDOW_H_
+#define _USERWINDOW_H_
+//=============================================================================
+//
+// File : userwindow.h
+// Created on Mon 30 Aug 2004 15:00:52 by Szymon Stefanek
+//
+// This file is part of the KVIrc IRC client distribution
+// Copyright (C) 2004 Szymon Stefanek <pragma at kvirc dot 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 opinion) 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.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_window.h"
+
+class KviUserWindow : public KviWindow
+{
+ Q_OBJECT
+public:
+ enum CreationFlags { HasInput = 1 };
+public:
+ KviUserWindow(KviFrame * pFrm,const char * name,int iIcon,KviConsole * pConsole = 0,int iCreationFlags = 0);
+ ~KviUserWindow();
+protected:
+ int m_iIcon;
+protected:
+ virtual void resizeEvent(QResizeEvent *e);
+ virtual QPixmap * myIconPtr();
+ virtual void fillCaptionBuffers();
+public:
+ void setCaptionStrings(const QString &szPlainText,const QString &szHtmlInactive,const QString &szHtmlActive);
+};
+
+#endif //!_USERWINDOW_H_