summaryrefslogtreecommitdiffstats
path: root/src/kvirc
diff options
context:
space:
mode:
Diffstat (limited to 'src/kvirc')
-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
448 files changed, 124680 insertions, 0 deletions
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) IR©Simpson
+
+
+// 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