From 731eb3f38731a2b5e5115c72243af02fa1aced62 Mon Sep 17 00:00:00 2001 From: Someone Date: Fri, 18 Jan 2013 08:16:58 +0100 Subject: [PATCH] Pjirc 2.2.1 as available on the net, reformatted and made it compile. --- files/AppletWithJS.html | 49 + files/HeavyApplet.html | 58 + files/NormalApplet.html | 48 + files/SimpleApplet.html | 18 + files/background.gif | Bin 0 -> 17704 bytes files/english.lng | 93 ++ files/french.lng | 93 ++ files/img/OH-1.gif | Bin 0 -> 132 bytes files/img/OH-2.gif | Bin 0 -> 131 bytes files/img/OH-3.gif | Bin 0 -> 128 bytes files/img/ange.gif | Bin 0 -> 175 bytes files/img/arbre.gif | Bin 0 -> 130 bytes files/img/argh.gif | Bin 0 -> 141 bytes files/img/ballon.gif | Bin 0 -> 84 bytes files/img/biere.gif | Bin 0 -> 140 bytes files/img/bombe.gif | Bin 0 -> 112 bytes files/img/bouche.gif | Bin 0 -> 104 bytes files/img/bouqin.gif | Bin 0 -> 90 bytes files/img/cadeau.gif | Bin 0 -> 137 bytes files/img/chien.gif | Bin 0 -> 153 bytes files/img/clin-oeuil-langue.gif | Bin 0 -> 126 bytes files/img/clin-oeuil.gif | Bin 0 -> 123 bytes files/img/coeur-brise.gif | Bin 0 -> 129 bytes files/img/coeur.gif | Bin 0 -> 94 bytes files/img/comprends-pas.gif | Bin 0 -> 141 bytes files/img/content.gif | Bin 0 -> 123 bytes files/img/cool.gif | Bin 0 -> 124 bytes files/img/diable.gif | Bin 0 -> 166 bytes files/img/dwchat.gif | Bin 0 -> 136 bytes files/img/enerve1.gif | Bin 0 -> 123 bytes files/img/enerve2.gif | Bin 0 -> 125 bytes files/img/femme.gif | Bin 0 -> 85 bytes files/img/fille.gif | Bin 0 -> 100 bytes files/img/fleur.gif | Bin 0 -> 165 bytes files/img/fume.gif | Bin 0 -> 152 bytes files/img/garcon.gif | Bin 0 -> 129 bytes files/img/grognon.gif | Bin 0 -> 119 bytes files/img/halloween.gif | Bin 0 -> 155 bytes files/img/hamburger.gif | Bin 0 -> 104 bytes files/img/homme.gif | Bin 0 -> 106 bytes files/img/langue.gif | Bin 0 -> 125 bytes files/img/lettre.gif | Bin 0 -> 96 bytes files/img/lit.gif | Bin 0 -> 134 bytes files/img/love.gif | Bin 0 -> 123 bytes files/img/lune.gif | Bin 0 -> 100 bytes files/img/mecontent.gif | Bin 0 -> 125 bytes files/img/newbie.gif | Bin 0 -> 168 bytes files/img/ordi.gif | Bin 0 -> 127 bytes files/img/pere-noel.gif | Bin 0 -> 267 bytes files/img/pleure.gif | Bin 0 -> 132 bytes files/img/poisson.gif | Bin 0 -> 96 bytes files/img/pomme.gif | Bin 0 -> 118 bytes files/img/portable.gif | Bin 0 -> 135 bytes files/img/pouce-non.gif | Bin 0 -> 165 bytes files/img/pouce-oui.gif | Bin 0 -> 166 bytes files/img/roll-eyes.gif | Bin 0 -> 126 bytes files/img/rouge.gif | Bin 0 -> 101 bytes files/img/sapin.gif | Bin 0 -> 94 bytes files/img/sleep.gif | Bin 0 -> 138 bytes files/img/soleil.gif | Bin 0 -> 146 bytes files/img/sourire.gif | Bin 0 -> 123 bytes files/img/terre.gif | Bin 0 -> 126 bytes files/img/triste.gif | Bin 0 -> 125 bytes files/img/verre-eau.gif | Bin 0 -> 89 bytes files/img/verre-vin.gif | Bin 0 -> 89 bytes files/img/yinyang.gif | Bin 0 -> 95 bytes files/license.txt | 125 ++ files/pixx-english.lng | 75 + files/pixx-french.lng | 75 + files/pjirc.cfg | 28 + files/readme.txt | 682 ++++++++ files/snd/bell2.au | Bin 0 -> 2772 bytes files/snd/ding.au | Bin 0 -> 4217 bytes files/thanks.txt | 61 + files/versions.txt | 271 ++++ src/main/java/IRCApplet.java | 251 +++ src/main/java/irc/AWTImageLoader.java | 44 + src/main/java/irc/AboutDialog.java | 115 ++ src/main/java/irc/AppletFileHandler.java | 61 + src/main/java/irc/AppletImageLoader.java | 61 + src/main/java/irc/AppletSoundHandler.java | 57 + src/main/java/irc/AppletURLHandler.java | 93 ++ src/main/java/irc/AudioConfiguration.java | 136 ++ src/main/java/irc/BasicInterpretor.java | 156 ++ src/main/java/irc/CTCPInterpretor.java | 160 ++ src/main/java/irc/ChanList.java | 181 +++ src/main/java/irc/ChanListListener.java | 61 + src/main/java/irc/Channel.java | 405 +++++ src/main/java/irc/ChannelInfo.java | 64 + src/main/java/irc/ChannelInterpretor.java | 88 + src/main/java/irc/ChannelListener.java | 159 ++ src/main/java/irc/ChannelListener2.java | 43 + src/main/java/irc/CodingHandler.java | 386 +++++ src/main/java/irc/ConfigurationLoader.java | 392 +++++ src/main/java/irc/DefaultInterpretor.java | 94 ++ src/main/java/irc/DefaultSource.java | 64 + src/main/java/irc/EventDispatcher.java | 469 ++++++ src/main/java/irc/FileHandler.java | 46 + src/main/java/irc/FileTextProvider.java | 179 +++ src/main/java/irc/IRCApplication.java | 812 ++++++++++ src/main/java/irc/IRCConfiguration.java | 874 ++++++++++ src/main/java/irc/IRCInterpretor.java | 154 ++ src/main/java/irc/IRCObject.java | 125 ++ src/main/java/irc/IRCServer.java | 1409 +++++++++++++++++ src/main/java/irc/IRCSource.java | 57 + src/main/java/irc/IRCTextProvider.java | 287 ++++ src/main/java/irc/ImageLoader.java | 46 + src/main/java/irc/Interpretor.java | 78 + src/main/java/irc/LinkedList.java | 112 ++ src/main/java/irc/ListHandler.java | 114 ++ src/main/java/irc/ListenerGroup.java | 310 ++++ src/main/java/irc/LocalFileHandler.java | 48 + src/main/java/irc/MessageServerListener.java | 50 + src/main/java/irc/ModeHandler.java | 227 +++ src/main/java/irc/MultiModeHandler.java | 175 ++ .../irc/NotEnoughParametersException.java | 46 + src/main/java/irc/NullImageLoader.java | 42 + src/main/java/irc/NullInterpretor.java | 47 + src/main/java/irc/NullServer.java | 126 ++ src/main/java/irc/NullSoundHandler.java | 40 + src/main/java/irc/NullURLHandler.java | 57 + src/main/java/irc/ParameterMixer.java | 63 + src/main/java/irc/ParameterProvider.java | 44 + src/main/java/irc/PluginManager.java | 53 + .../java/irc/PrefixedParameterProvider.java | 56 + src/main/java/irc/Query.java | 140 ++ src/main/java/irc/QueryInterpretor.java | 45 + src/main/java/irc/QueryListener.java | 55 + src/main/java/irc/ReplyServerListener.java | 51 + src/main/java/irc/RootInterpretor.java | 190 +++ src/main/java/irc/RuleList.java | 128 ++ src/main/java/irc/Server.java | 155 ++ src/main/java/irc/ServerListener.java | 105 ++ src/main/java/irc/ServerManager.java | 45 + src/main/java/irc/ServerProtocol.java | 271 ++++ src/main/java/irc/ServerProtocolListener.java | 85 + src/main/java/irc/SmileyTable.java | 124 ++ src/main/java/irc/SoundHandler.java | 43 + src/main/java/irc/Source.java | 258 +++ src/main/java/irc/SourceListener.java | 89 ++ src/main/java/irc/StartupConfiguration.java | 161 ++ src/main/java/irc/Status.java | 220 +++ src/main/java/irc/StatusInterpretor.java | 45 + src/main/java/irc/StatusListener.java | 67 + .../java/irc/StreamParameterProvider.java | 86 + src/main/java/irc/StringParser.java | 101 ++ src/main/java/irc/StyleContext.java | 45 + src/main/java/irc/TextProvider.java | 105 ++ src/main/java/irc/URLHandler.java | 61 + src/main/java/irc/dcc/DCCChat.java | 77 + src/main/java/irc/dcc/DCCChatInterpretor.java | 73 + src/main/java/irc/dcc/DCCFile.java | 261 +++ src/main/java/irc/dcc/DCCFileListener.java | 61 + src/main/java/irc/dcc/DCCSource.java | 61 + src/main/java/irc/dcc/prv/DCCChatServer.java | 341 ++++ src/main/java/irc/dcc/prv/DCCFileHandler.java | 389 +++++ src/main/java/irc/gui/GUISource.java | 78 + src/main/java/irc/gui/IRCInterface.java | 151 ++ .../java/irc/gui/IRCInterfaceListener.java | 46 + .../java/irc/gui/common/AWTIrcTextField.java | 352 ++++ .../java/irc/gui/common/DockablePanel.java | 261 +++ .../irc/gui/common/DockablePanelListener.java | 51 + .../gui/common/MouseWheelPanelListener.java | 43 + .../gui/common/MouseWheelPanelWrapper.java | 98 ++ src/main/java/irc/gui/pixx/AWTChanList.java | 222 +++ src/main/java/irc/gui/pixx/AWTChannel.java | 394 +++++ src/main/java/irc/gui/pixx/AWTDCCChat.java | 50 + src/main/java/irc/gui/pixx/AWTDCCFile.java | 183 +++ .../java/irc/gui/pixx/AWTDefaultSource.java | 50 + .../java/irc/gui/pixx/AWTInterpretor.java | 141 ++ .../java/irc/gui/pixx/AWTProgressBar.java | 77 + src/main/java/irc/gui/pixx/AWTQuery.java | 133 ++ src/main/java/irc/gui/pixx/AWTStatus.java | 126 ++ .../java/irc/gui/pixx/AWTStyleSelector.java | 299 ++++ .../java/irc/gui/pixx/AWTStyleSelectorEx.java | 142 ++ .../gui/pixx/AWTStyleSelectorExListener.java | 45 + src/main/java/irc/gui/pixx/BaseAWTSource.java | 790 +++++++++ .../irc/gui/pixx/BaseAWTSourceListener.java | 52 + src/main/java/irc/gui/pixx/FontSelector.java | 165 ++ .../irc/gui/pixx/FontSelectorListener.java | 45 + src/main/java/irc/gui/pixx/Interface.java | 48 + .../java/irc/gui/pixx/NickMenuHandler.java | 163 ++ .../java/irc/gui/pixx/NonFocusableButton.java | 65 + .../irc/gui/pixx/NonFocusableTextField.java | 76 + .../java/irc/gui/pixx/PixxColorModel.java | 225 +++ .../java/irc/gui/pixx/PixxConfiguration.java | 468 ++++++ .../irc/gui/pixx/PixxConfigurationLoader.java | 309 ++++ .../irc/gui/pixx/PixxHorizontalScrollBar.java | 549 +++++++ .../java/irc/gui/pixx/PixxMDIInterface.java | 782 +++++++++ src/main/java/irc/gui/pixx/PixxMenuBar.java | 730 +++++++++ .../irc/gui/pixx/PixxMenuBarListener.java | 83 + src/main/java/irc/gui/pixx/PixxNickList.java | 500 ++++++ .../irc/gui/pixx/PixxNickListListener.java | 57 + src/main/java/irc/gui/pixx/PixxPanel.java | 191 +++ src/main/java/irc/gui/pixx/PixxScrollBar.java | 82 + .../irc/gui/pixx/PixxScrollBarListener.java | 43 + src/main/java/irc/gui/pixx/PixxSeparator.java | 122 ++ src/main/java/irc/gui/pixx/PixxTaskBar.java | 809 ++++++++++ .../irc/gui/pixx/PixxTaskBarListener.java | 89 ++ .../java/irc/gui/pixx/PixxTextProvider.java | 239 +++ .../irc/gui/pixx/PixxVerticalScrollBar.java | 503 ++++++ .../irc/gui/pixx/ScrollablePixxNickList.java | 142 ++ .../java/irc/gui/prv/MouseWheelPanel.java | 80 + src/main/java/irc/ident/IdentListener.java | 81 + src/main/java/irc/ident/IdentWrapper.java | 87 + src/main/java/irc/ident/prv/IdentServer.java | 275 ++++ src/main/java/irc/plugin/Plugin.java | 175 ++ src/main/java/irc/plugin/test/Test.java | 57 + .../irc/security/DefaultSecuredProvider.java | 137 ++ .../java/irc/security/SecuredProvider.java | 163 ++ .../java/irc/security/SecurityProvider.java | 353 +++++ .../prv/SpecificMSSecuredProvider.java | 240 +++ .../prv/SpecificMSSecuredServerSocket.java | 67 + .../java/irc/style/ChannelRecognizer.java | 46 + src/main/java/irc/style/CharactersDrawer.java | 258 +++ src/main/java/irc/style/DecodedLine.java | 48 + src/main/java/irc/style/DrawResult.java | 60 + src/main/java/irc/style/DrawResultItem.java | 78 + .../java/irc/style/FormattedStringDrawer.java | 1036 ++++++++++++ .../style/FormattedStringDrawerListener.java | 59 + .../java/irc/style/MultipleWordCatcher.java | 68 + src/main/java/irc/style/StyledList.java | 1300 +++++++++++++++ .../java/irc/style/StyledListListener.java | 93 ++ src/main/java/irc/style/StyledRectangle.java | 150 ++ src/main/java/irc/style/URLRecognizer.java | 73 + src/main/java/irc/style/WordCatcher.java | 44 + .../java/irc/style/WordListRecognizer.java | 71 + src/main/java/irc/style/WordRecognizer.java | 51 + src/main/java/irc/tree/Comparator.java | 47 + src/main/java/irc/tree/SortedList.java | 387 +++++ .../java/irc/tree/TreeTraversalListener.java | 62 + src/main/resources/english.lng | 93 ++ src/main/resources/pixx-english.lng | 75 + src/main/resources/pjirc.cfg | 28 + 234 files changed, 30942 insertions(+) create mode 100644 files/AppletWithJS.html create mode 100644 files/HeavyApplet.html create mode 100644 files/NormalApplet.html create mode 100644 files/SimpleApplet.html create mode 100644 files/background.gif create mode 100644 files/english.lng create mode 100644 files/french.lng create mode 100644 files/img/OH-1.gif create mode 100644 files/img/OH-2.gif create mode 100644 files/img/OH-3.gif create mode 100644 files/img/ange.gif create mode 100644 files/img/arbre.gif create mode 100644 files/img/argh.gif create mode 100644 files/img/ballon.gif create mode 100644 files/img/biere.gif create mode 100644 files/img/bombe.gif create mode 100644 files/img/bouche.gif create mode 100644 files/img/bouqin.gif create mode 100644 files/img/cadeau.gif create mode 100644 files/img/chien.gif create mode 100644 files/img/clin-oeuil-langue.gif create mode 100644 files/img/clin-oeuil.gif create mode 100644 files/img/coeur-brise.gif create mode 100644 files/img/coeur.gif create mode 100644 files/img/comprends-pas.gif create mode 100644 files/img/content.gif create mode 100644 files/img/cool.gif create mode 100644 files/img/diable.gif create mode 100644 files/img/dwchat.gif create mode 100644 files/img/enerve1.gif create mode 100644 files/img/enerve2.gif create mode 100644 files/img/femme.gif create mode 100644 files/img/fille.gif create mode 100644 files/img/fleur.gif create mode 100644 files/img/fume.gif create mode 100644 files/img/garcon.gif create mode 100644 files/img/grognon.gif create mode 100644 files/img/halloween.gif create mode 100644 files/img/hamburger.gif create mode 100644 files/img/homme.gif create mode 100644 files/img/langue.gif create mode 100644 files/img/lettre.gif create mode 100644 files/img/lit.gif create mode 100644 files/img/love.gif create mode 100644 files/img/lune.gif create mode 100644 files/img/mecontent.gif create mode 100644 files/img/newbie.gif create mode 100644 files/img/ordi.gif create mode 100644 files/img/pere-noel.gif create mode 100644 files/img/pleure.gif create mode 100644 files/img/poisson.gif create mode 100644 files/img/pomme.gif create mode 100644 files/img/portable.gif create mode 100644 files/img/pouce-non.gif create mode 100644 files/img/pouce-oui.gif create mode 100644 files/img/roll-eyes.gif create mode 100644 files/img/rouge.gif create mode 100644 files/img/sapin.gif create mode 100644 files/img/sleep.gif create mode 100644 files/img/soleil.gif create mode 100644 files/img/sourire.gif create mode 100644 files/img/terre.gif create mode 100644 files/img/triste.gif create mode 100644 files/img/verre-eau.gif create mode 100644 files/img/verre-vin.gif create mode 100644 files/img/yinyang.gif create mode 100644 files/license.txt create mode 100644 files/pixx-english.lng create mode 100644 files/pixx-french.lng create mode 100644 files/pjirc.cfg create mode 100644 files/readme.txt create mode 100644 files/snd/bell2.au create mode 100644 files/snd/ding.au create mode 100644 files/thanks.txt create mode 100644 files/versions.txt create mode 100644 src/main/java/IRCApplet.java create mode 100644 src/main/java/irc/AWTImageLoader.java create mode 100644 src/main/java/irc/AboutDialog.java create mode 100644 src/main/java/irc/AppletFileHandler.java create mode 100644 src/main/java/irc/AppletImageLoader.java create mode 100644 src/main/java/irc/AppletSoundHandler.java create mode 100644 src/main/java/irc/AppletURLHandler.java create mode 100644 src/main/java/irc/AudioConfiguration.java create mode 100644 src/main/java/irc/BasicInterpretor.java create mode 100644 src/main/java/irc/CTCPInterpretor.java create mode 100644 src/main/java/irc/ChanList.java create mode 100644 src/main/java/irc/ChanListListener.java create mode 100644 src/main/java/irc/Channel.java create mode 100644 src/main/java/irc/ChannelInfo.java create mode 100644 src/main/java/irc/ChannelInterpretor.java create mode 100644 src/main/java/irc/ChannelListener.java create mode 100644 src/main/java/irc/ChannelListener2.java create mode 100644 src/main/java/irc/CodingHandler.java create mode 100644 src/main/java/irc/ConfigurationLoader.java create mode 100644 src/main/java/irc/DefaultInterpretor.java create mode 100644 src/main/java/irc/DefaultSource.java create mode 100644 src/main/java/irc/EventDispatcher.java create mode 100644 src/main/java/irc/FileHandler.java create mode 100644 src/main/java/irc/FileTextProvider.java create mode 100644 src/main/java/irc/IRCApplication.java create mode 100644 src/main/java/irc/IRCConfiguration.java create mode 100644 src/main/java/irc/IRCInterpretor.java create mode 100644 src/main/java/irc/IRCObject.java create mode 100644 src/main/java/irc/IRCServer.java create mode 100644 src/main/java/irc/IRCSource.java create mode 100644 src/main/java/irc/IRCTextProvider.java create mode 100644 src/main/java/irc/ImageLoader.java create mode 100644 src/main/java/irc/Interpretor.java create mode 100644 src/main/java/irc/LinkedList.java create mode 100644 src/main/java/irc/ListHandler.java create mode 100644 src/main/java/irc/ListenerGroup.java create mode 100644 src/main/java/irc/LocalFileHandler.java create mode 100644 src/main/java/irc/MessageServerListener.java create mode 100644 src/main/java/irc/ModeHandler.java create mode 100644 src/main/java/irc/MultiModeHandler.java create mode 100644 src/main/java/irc/NotEnoughParametersException.java create mode 100644 src/main/java/irc/NullImageLoader.java create mode 100644 src/main/java/irc/NullInterpretor.java create mode 100644 src/main/java/irc/NullServer.java create mode 100644 src/main/java/irc/NullSoundHandler.java create mode 100644 src/main/java/irc/NullURLHandler.java create mode 100644 src/main/java/irc/ParameterMixer.java create mode 100644 src/main/java/irc/ParameterProvider.java create mode 100644 src/main/java/irc/PluginManager.java create mode 100644 src/main/java/irc/PrefixedParameterProvider.java create mode 100644 src/main/java/irc/Query.java create mode 100644 src/main/java/irc/QueryInterpretor.java create mode 100644 src/main/java/irc/QueryListener.java create mode 100644 src/main/java/irc/ReplyServerListener.java create mode 100644 src/main/java/irc/RootInterpretor.java create mode 100644 src/main/java/irc/RuleList.java create mode 100644 src/main/java/irc/Server.java create mode 100644 src/main/java/irc/ServerListener.java create mode 100644 src/main/java/irc/ServerManager.java create mode 100644 src/main/java/irc/ServerProtocol.java create mode 100644 src/main/java/irc/ServerProtocolListener.java create mode 100644 src/main/java/irc/SmileyTable.java create mode 100644 src/main/java/irc/SoundHandler.java create mode 100644 src/main/java/irc/Source.java create mode 100644 src/main/java/irc/SourceListener.java create mode 100644 src/main/java/irc/StartupConfiguration.java create mode 100644 src/main/java/irc/Status.java create mode 100644 src/main/java/irc/StatusInterpretor.java create mode 100644 src/main/java/irc/StatusListener.java create mode 100644 src/main/java/irc/StreamParameterProvider.java create mode 100644 src/main/java/irc/StringParser.java create mode 100644 src/main/java/irc/StyleContext.java create mode 100644 src/main/java/irc/TextProvider.java create mode 100644 src/main/java/irc/URLHandler.java create mode 100644 src/main/java/irc/dcc/DCCChat.java create mode 100644 src/main/java/irc/dcc/DCCChatInterpretor.java create mode 100644 src/main/java/irc/dcc/DCCFile.java create mode 100644 src/main/java/irc/dcc/DCCFileListener.java create mode 100644 src/main/java/irc/dcc/DCCSource.java create mode 100644 src/main/java/irc/dcc/prv/DCCChatServer.java create mode 100644 src/main/java/irc/dcc/prv/DCCFileHandler.java create mode 100644 src/main/java/irc/gui/GUISource.java create mode 100644 src/main/java/irc/gui/IRCInterface.java create mode 100644 src/main/java/irc/gui/IRCInterfaceListener.java create mode 100644 src/main/java/irc/gui/common/AWTIrcTextField.java create mode 100644 src/main/java/irc/gui/common/DockablePanel.java create mode 100644 src/main/java/irc/gui/common/DockablePanelListener.java create mode 100644 src/main/java/irc/gui/common/MouseWheelPanelListener.java create mode 100644 src/main/java/irc/gui/common/MouseWheelPanelWrapper.java create mode 100644 src/main/java/irc/gui/pixx/AWTChanList.java create mode 100644 src/main/java/irc/gui/pixx/AWTChannel.java create mode 100644 src/main/java/irc/gui/pixx/AWTDCCChat.java create mode 100644 src/main/java/irc/gui/pixx/AWTDCCFile.java create mode 100644 src/main/java/irc/gui/pixx/AWTDefaultSource.java create mode 100644 src/main/java/irc/gui/pixx/AWTInterpretor.java create mode 100644 src/main/java/irc/gui/pixx/AWTProgressBar.java create mode 100644 src/main/java/irc/gui/pixx/AWTQuery.java create mode 100644 src/main/java/irc/gui/pixx/AWTStatus.java create mode 100644 src/main/java/irc/gui/pixx/AWTStyleSelector.java create mode 100644 src/main/java/irc/gui/pixx/AWTStyleSelectorEx.java create mode 100644 src/main/java/irc/gui/pixx/AWTStyleSelectorExListener.java create mode 100644 src/main/java/irc/gui/pixx/BaseAWTSource.java create mode 100644 src/main/java/irc/gui/pixx/BaseAWTSourceListener.java create mode 100644 src/main/java/irc/gui/pixx/FontSelector.java create mode 100644 src/main/java/irc/gui/pixx/FontSelectorListener.java create mode 100644 src/main/java/irc/gui/pixx/Interface.java create mode 100644 src/main/java/irc/gui/pixx/NickMenuHandler.java create mode 100644 src/main/java/irc/gui/pixx/NonFocusableButton.java create mode 100644 src/main/java/irc/gui/pixx/NonFocusableTextField.java create mode 100644 src/main/java/irc/gui/pixx/PixxColorModel.java create mode 100644 src/main/java/irc/gui/pixx/PixxConfiguration.java create mode 100644 src/main/java/irc/gui/pixx/PixxConfigurationLoader.java create mode 100644 src/main/java/irc/gui/pixx/PixxHorizontalScrollBar.java create mode 100644 src/main/java/irc/gui/pixx/PixxMDIInterface.java create mode 100644 src/main/java/irc/gui/pixx/PixxMenuBar.java create mode 100644 src/main/java/irc/gui/pixx/PixxMenuBarListener.java create mode 100644 src/main/java/irc/gui/pixx/PixxNickList.java create mode 100644 src/main/java/irc/gui/pixx/PixxNickListListener.java create mode 100644 src/main/java/irc/gui/pixx/PixxPanel.java create mode 100644 src/main/java/irc/gui/pixx/PixxScrollBar.java create mode 100644 src/main/java/irc/gui/pixx/PixxScrollBarListener.java create mode 100644 src/main/java/irc/gui/pixx/PixxSeparator.java create mode 100644 src/main/java/irc/gui/pixx/PixxTaskBar.java create mode 100644 src/main/java/irc/gui/pixx/PixxTaskBarListener.java create mode 100644 src/main/java/irc/gui/pixx/PixxTextProvider.java create mode 100644 src/main/java/irc/gui/pixx/PixxVerticalScrollBar.java create mode 100644 src/main/java/irc/gui/pixx/ScrollablePixxNickList.java create mode 100644 src/main/java/irc/gui/prv/MouseWheelPanel.java create mode 100644 src/main/java/irc/ident/IdentListener.java create mode 100644 src/main/java/irc/ident/IdentWrapper.java create mode 100644 src/main/java/irc/ident/prv/IdentServer.java create mode 100644 src/main/java/irc/plugin/Plugin.java create mode 100644 src/main/java/irc/plugin/test/Test.java create mode 100644 src/main/java/irc/security/DefaultSecuredProvider.java create mode 100644 src/main/java/irc/security/SecuredProvider.java create mode 100644 src/main/java/irc/security/SecurityProvider.java create mode 100644 src/main/java/irc/security/prv/SpecificMSSecuredProvider.java create mode 100644 src/main/java/irc/security/prv/SpecificMSSecuredServerSocket.java create mode 100644 src/main/java/irc/style/ChannelRecognizer.java create mode 100644 src/main/java/irc/style/CharactersDrawer.java create mode 100644 src/main/java/irc/style/DecodedLine.java create mode 100644 src/main/java/irc/style/DrawResult.java create mode 100644 src/main/java/irc/style/DrawResultItem.java create mode 100644 src/main/java/irc/style/FormattedStringDrawer.java create mode 100644 src/main/java/irc/style/FormattedStringDrawerListener.java create mode 100644 src/main/java/irc/style/MultipleWordCatcher.java create mode 100644 src/main/java/irc/style/StyledList.java create mode 100644 src/main/java/irc/style/StyledListListener.java create mode 100644 src/main/java/irc/style/StyledRectangle.java create mode 100644 src/main/java/irc/style/URLRecognizer.java create mode 100644 src/main/java/irc/style/WordCatcher.java create mode 100644 src/main/java/irc/style/WordListRecognizer.java create mode 100644 src/main/java/irc/style/WordRecognizer.java create mode 100644 src/main/java/irc/tree/Comparator.java create mode 100644 src/main/java/irc/tree/SortedList.java create mode 100644 src/main/java/irc/tree/TreeTraversalListener.java create mode 100644 src/main/resources/english.lng create mode 100644 src/main/resources/pixx-english.lng create mode 100644 src/main/resources/pjirc.cfg diff --git a/files/AppletWithJS.html b/files/AppletWithJS.html new file mode 100644 index 0000000..fa9d08c --- /dev/null +++ b/files/AppletWithJS.html @@ -0,0 +1,49 @@ + + +IRCApplet + + +

Test page for IRCApplet Class


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+ + diff --git a/files/HeavyApplet.html b/files/HeavyApplet.html new file mode 100644 index 0000000..dcc50ad --- /dev/null +++ b/files/HeavyApplet.html @@ -0,0 +1,58 @@ + + +IRCApplet + + +

Test page for IRCApplet Class


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + diff --git a/files/NormalApplet.html b/files/NormalApplet.html new file mode 100644 index 0000000..92147a5 --- /dev/null +++ b/files/NormalApplet.html @@ -0,0 +1,48 @@ + + +IRCApplet + + +

Test page for IRCApplet Class


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ diff --git a/files/SimpleApplet.html b/files/SimpleApplet.html new file mode 100644 index 0000000..2ad167a --- /dev/null +++ b/files/SimpleApplet.html @@ -0,0 +1,18 @@ + + +IRCApplet + + +

Test page for IRCApplet Class


+ + + + + + + + + +
+ + diff --git a/files/background.gif b/files/background.gif new file mode 100644 index 0000000000000000000000000000000000000000..569d4bd29514e96baab2ea93e473bfb9cda7dea8 GIT binary patch literal 17704 zcmd3NWmg=|&-N~hyA+DMyL%~C+=>+~i@O)6xH}YgE$(i`-QC@NacA$}|M?WpyqGg@ zl5@>TGRfpzk(QO>7cl$@{0V#n{BJ>_&^^f0`^U%RI!mxesOqsw7R-B zKfiEtdcMA~wY7gTzqERJeRl!5J-@m+JUQPxJlWYl+TJ@{-`ZW>*j`!RdU$%de|)~W zzCAg+I667o-9KDdTA5#5etZ9TetCU*etCR)et3MkyMMU7yT7@;ySThMzqmX;IXyZ) zIXpVv-P_;U-P_*TU0qvWSzTLNURhjPURYe3Us#-*UznYnpP8MTo|#?WJGs1nJ-oQR zetg?LfovXKp5DG3UOlYupB`S`9bDXQ>>e&}?A$)REv{}X{0D3AaC7%yZEJTQ^0asL zczFH1dvU*gdcAc5Ir&cz^0<3`yK{E4eR8#Re7Sjav2l2Qcy+&X3R&AdTHX0i@$25{ z)$YmV&hf?S_WsV%+0*O$)y>`c)%DTo`N8q&#`b^L-&$H-Uszr}x_Lf;JnmmT?3~|j z9i49+oUZSmtnD3N+`sIfU+-St?_As+-#(w-z3gA!?VMe29G>l+UvC|ru59mLKfOU7 zUw2O~*0%RnHg}fRw-(nn@1Eawk50D_j<@!YHg*rzclP%nk1JcdOB>tUhbND(?~uEP z(@V(7#ntlq=Ii^%%iH_o^ULl1!}aYQO-Tm6u_S?tD-NVD%`}@o5>%-&Y_07%p&d%)I+|=~+{r&yP$;sZ{-p0np($dn* z%*_Auvj0yv=KtaPUn~F+p#Tsfu}n>FPaq-=quy{$USB9Cm0YGwZT>(cK9|+{aBaa* zEV)Dkv20!8$RBz&Jgt$sqOlZql)_Be`o9wy{78e|0=dOgIikLoztZYUW(s8N(a}a5 zO6Q6}A+%X?jb#f#9C=n7qqr91<>0;umXUfU6)cOnGW{{lO6_XNq0ub)lsx%*+uPHP zu_c@JHb2mh&h{jG9mOylrk~?2wX}T}tsl4wtv4gdI$jqpOXX}}9L*oXxE$6lC_RN5Y;x~Am; zrK;SDG0j)>&ly41SlavXCaQ@h%0!I3#{O$!3Sh9zZlX=_W;#Yy>W4Y# zruex!oNa@DT`8qxi<4xzPmc@Yq*jmfHKZ6Qvwy;uYNay1ARQOOA$j8EDg1LiCZM>K zDK4yNI<+eQbpt&vaP7}Z#V>Xkfo06i|B$pQt;|BsFLV5de1b7dTYg?QPHBB!;4~^n zS($d)%8-+F+GZWu$w)wDWIY&g9Ie*-%t$f8t2^9w-ZW;{HjaH`l_@ysDOH(H$!k)z z_VZ~s*P_(2kwSv4+@ak+X^(zYAT{8uOJbM{UiZ0FUC?iSzyu%Pn^Sr!nWkul+ zt7!7Z+7@VXE#gWD$#U1fgfEa`i_gCyGqJ2^mut>^(L?)*KkS|llB7i%$1hlkEI0XC zhnu&WZ{8Z40wNbGr_FGF=dP;fuk*IEk3~OUv>e5>uV+el^A+ayQMUd5ty^Aw^8GpU z#TO1xq}|<}-AR64N40i2=6Dw4LALI8_5QeN?d!45=9Ybaloaxh=em%LEx_Un+gGjI zf(UX5?QAg`%3k#3Kh`-_9I_{PnQj<76>kUUwC7B?$~z?c-vV5llK_Oz&m^WUTY`E$ zvx8k9+Oe)IDBw#}L=lSA=^zc6JY)@bahwE*S6hMZ!sb9X{Njl}66Mcp_CpcmY;+gA zLZlsNhv`=bG@HPPvs@_PsR4@+GngqV|5LHd0B+l~Uu$GK%hoVTwn`fIf-izJ^Kjr`{x%C=@X&%F2nTbHsr< zNGN_t^^pyaeb-hi45S?HL+Y)j0|!#eOs4iw(O$Z|Iu{`L0(z6a*?Q4@D*E)?GHRuB zn_j-Z_o*7O?^>)fF7$2}ZRxYrqlQWk6zE@y7Uj! zQW@!0W$PD?2+&0~Ul#l%>mg_8IafB7|C0*WOl;T;QQ9u^i+nEV?4OaR9~Ni zn%eFw9c<5Z!{~RD{@8J>c;&top}yNT+p->bDu#A4>&V)mbNOm|Qy7U^)rRL=rFJf4 zEws4iy40Sq!9v`RvVJG{)Pot~;1C-zDy(x|ubg4e-_^8#DukVw9=l^@I}u#A-)U9Ug6?mwQFLP z(!KtkZPzoV8~?I6s5My^{aZ+tq>C@ueZnE`On0@M@Od~W+Tt#bJ_l#Y7257>;z;%@ zax~sdbIg6xIht$jK<&S0XlQ~dE=7KUV(YQbc)eOvy5q3_=F`B}16I-w=_AHhoO;j6 zhQF3k+VQ9E!T#Bqsg_#DoL*Xg2|=`qfx{M5$xkkI@8o0o>z#6aPqQf-4OMO|J7Xbt zbBw5ssgH~%=~Wl)<-J%Of;Ambe6J zCQRuI718l|%jf5Oy&eP1*{)fYBtLA|UN;Z#dGxiP5Bw>c5ePrTK#HAxTsdAIl|S8# zk_a@{dS7cBl^`9@9=6`P>$~fR#mzmP0{;?{hYLa1Wv@vPaP4z{9ki)3v&;JAx8~a} z`;gn<df(#^NwNLpm9B7L z=#$!4bEk}~^OD3Ng57l{&qjTvpG6rYhmIG#U4fOVVxY`rnBp>nv1lFctI@6^7{R42 zR8x?0y4MYD4Qie+4sN4P0kleeS~8z7W4ezsz@K zP0N<3qwD9K29n7>RF=Qjb3yOBoc|%W7rE*BPQ9lhpG2Z7HXbF z>pZ5Kd#LASFA}PLzi@+o;6r`pLZJtu7;PcMyky@Nouv|7h8p_tEA1-TdgVNauRb=g%zT@1)_$o8nKX zD`x)wGNT=P7;K`yDv?}HK%I9r!WV|2h{czyF2xIi&q;_g1 zt7sO`c<<60`g>l=5z8V7-0}-IHE5vGo$EM=WSEBUSmH+tQIJ}&l2h;soFyZIE4qy7 z&!=F+me7@uAbE|Dl44IlYDnA=m#r3IVyM;?U#RzwPzI=sFQ$dBH-GqV{t(|~Ujq6t z$02{@Z*Kglfipcmi@}nJGNCAlu5CviozmeIE!Hog%05j&iY=a*VG<8mP62QcMr!;X zZcbXqVOWoTfyJSfT2WON;orA^?G6Q*%S5_3S!mH{wNpe?9Y#hy1!8=Ta>ox>21jiU zTUVz>eQt@W=MNJM^{Ia3v6BhDKma2=MH&wn#kv3Le~Nx6G2gN99Qf>Vh!}0|8s;p< zKcyCZRU-RUOVh0+!p0=G{BE9wxc-? zO*uEB{8y=X;xHO7=fIlc_zo@EhUT!pCBbM=`h@Q_5wt6Rv_lg1N)qx1V;vuZ ztimG2#R%+|V|0E*;JXAM9QsKO{Snbl@(PKneX<>=4|6h)EPjY>8y4mtuqiwaR6%l7 zWpKZ@NV4%rVrx;CD@i(7POAJITnZl-$nl5vM;uaW@J-5}WxgcpmE@pS)820(_{%}> zS}DSG(Z6aFg)NL|5u^N8g74_VgVWNuLXs*HQzbmSBawom)8c>BCQ>1S6HelN(xSyI z()z;E(g`v!2Gbk~!bpZhN1J6nkAxUnej-{))N_j~84k7*NUih8L?28WFwJ0o4r=C4 zFBHI?Z%HX#acLg%6KqW$Zp}I<%DfuL?5B16fTqTDf5M9s@bX^yx+IWEh8w>AoW1st zT*Du;jl{8An(>(+>+?PiNH#fqFK}EvbX6;}1}O(}l2tquw1byEa_2*U}uh zyp$5l{L_<^?+igGu4x;?`QnU#QKW)5_Z%3lg45JbN3vNo{Gp2=^<{$8uP^Chf`#Hb zh5P)84M7=XFG>61DfBai#4BcH47ru9(NrEqTIofs$njeOJ}9Soys0@OhZ+1jf6P3i zp@DxWOS5dt^6blEbp?1HPTbi_3lFqEnLv>Nx`?@529lBY+kXGFVB5tVG!%u9JALvcu1X_!@f#Ay`?MV_Zl z#MVm+c5(jGX?cZQPVj2cFRMt`wi09HYMi!WdfK9RxgycFnrFe1qxA4x+2R4hzc~?v zo&=#Z7Fmv;%qgJqSphUHL?zuT+nu!QwbWz~*4l{Ip8 zfVC<*FRZ!Jx*Mx33&tvIxrTkKsw2?EiX@* z@+#KS4B%@c&UHhxVCeB|g{4)sc}AIKd0AImCI(7*b3;}0abvtmttVmQcv&r*P}Og* zMslKJI& zsQnGuA+)Wk*{ij$upMr!y#jjD`Y700%hcANQB{NzoWj)XTH8^u+QCBf@1JhtzIO^?BD0|mU5;pGn5j9il)c0 zyyvs(ptVw)VXRW79+pFt#t}D96ETJymr~z5wj;F|f8LQnFgoC1}-I+q&`RYAz5rdrNgAFLP%)+(jd1}A;GxI<+^z42B<-jTx|Z~0y}9sQ$SZmk-dOhf7l zJt5vhshI;-6+JkuecWyTz(m6Wgt{gQL;aS$WrRp7xd^HNST%OoZz`}-qVOT?9yqyDR05S<7p1Kj9y3<4D_e1HJhK&-1cN0bMB}Y(ZpF~LSCSs}2xpC5W74mh#Ii`NfP-_sl>p2&Egj!w>ck z82%eM!VEFe5LBS@$SWgeov(@+%U&zmSg)+XW~7c_qD>Dr(GP{f4@5^YMXUH92oO00 zo+1~8fE{STZ`3>Ta0})-!C}e>sAb_}SkPl!&MRYFM zqiZoLLwVepb=_c{xrgg~dfR4{mSDn(9ZnYv-%>LVA)b9)hs6a0acWQq$x*@|@RT`V z2y0MM9FTFlCn<74LNzlt>&VgM@S@~PwrPC}qodhxJ;E3N+EI$)kUO_c$218h97Pep z-SGT1i&fLewz=@w0AMmZO!DvblrJb)4oD5t0KPbo9Lbd6G`wjy$dP42L!e|~ygGV) zWEeWu$%Z;6M%-PmKMcpb{D252!49vq4WIu$$qxo$hypEYfK)X|!&zHq*C?sBNS`oa zDjh%(ognU9SQB-o^MSx6#DPeDgW5!am^DDfkA3&5EkZwdYXA()=8TdG{Li>;eWhuGswxa9`bhA? z5+`vN?$0&pw`k98IO#Yf`A$$vH~hfwBah7!8W9+VOZd)<9ST2Ke+M{c+o;vf!N#>A zm5#m2gE^d^n=YvP2~}`$)5wrakWDUp=JrW9>G>B9n2gG^t4t7nE?h~~_MhW}KWiI7 zXG6x5dtbc{{aEG)=n?z@Nd40@6ks3~>-jG0xkWB~4%!sH3IfvPx#943^U3z#jOp@k z`BzN6F+LYZB>P}QIBf@5ho7kZaVV+mC{I~O@Z_k7IS}M72%-VZ9{NFw=mAMI(8O=m zyXCaZrUc=Acy;|>?PQ0Ket%>3Rpl`PIwlNc93`a&*pm%_h1{@{-Eu;qH;53(%LI~T z4RV1UNIDmet21=+U-wVu3({DrZS1vE?S9LuE9Mde<2WE>9grfr+Y^Jz<$KS;hRW-^ zn+isOpuz;yoL|@-PoW=fz7OQ+-2wLs%`PVjy>|?s5R@QS0$?B^1cK~$?`aRvwcpJY zMG@Uh9FvJeXBp2|wY||Av-EJ4BMlrba=+^a7hqpwN>yNPLPyo!35|DZ8v6uagD;9My z_9&Ab$P1a|>xT7(+)h;waO*xSjrYw>Es^=w+L9G@qF{P&OH$w;jEDh|a9K^3r*|a6 zuy9`T5(~6A_%M0VwwGu2q~j>Q`3OsO@5?4KDAMAu%pS<6av-={lxjN`cuvv zDd!?#h%n&8q31AayxjH7HAu&@2m8FqB$!|^Yb7ye3E)`&p;e@m{KbsfeXiXAhy3eP zx#iqnE%OG=fJTe&3uM8_!5*u>O5+$|5b%fz=OH_xqMYX~mWC2ChVeAYf0@Vq6k?Io z?W7n`Z_TIk5aN!(_4uruLSB?+@6HzA`K8MdwNF2lL4THMR!?5M@SbbMSk0jS7^_V| ztg+vltn}iO-DLOndb$8MB0Bo-@}6k?Z}y zr2$Rp!}F+y4QTHYas(Q~YHIIZ>2YD%XjMhS=|y>sCsI|#&ZJIcLDPDGJZoiopEcV_ ziTtTxK;7$AfAFyTUOpx>!3h4Nk@{ikn3N9rVB+B%7Pm3F%=Qp0Cd3ASCejjyk6NRG z_6-WdEyr7gD#>29j=w*_gg8K1E{?JyK3UnqUpUrUDw?U(-wn@%MM3+WcrPT9)!l~L z&>_l^AX&2RmKsh_TnZ=(!c_+v3v-&ONCFk1heIIb=qUhf0)xF2*uu~Tfu>5UPH{1l z8@ZG|Ly*0v6wk(?e6xF&lb>~>&A|_q&t#IdBlk>R5_`!zU=BLiy_1j3?r0m!BGhAM5H6<71es zEB){)cojMf*VqKg%U3mR&~<&*Pi@cSYh^dDTu}IahIf3aFYqWE^Xlqg9F$6F=gnm* zoZzkebwlW|U`sK7y$Y(zh|U1`HHp<{2A4S$BR-Oixe@vfn4l--JC%VJU*x6CuM2e!QBQ7gl){{h;o zlZNb6JE9T+Pzy}EV;zieKlgNhdZ@v{Rl?+@1(5`(x;8OA4+fSxYanj%(q>GcnO{om zbXleJ2OsyK4NL=RMFOMn|H4`dMt#qI`jKtw9i%mavkkB)VIK$&0^u>h6MT>dPspm+ zs95D6kDC>_$j<1iCw{I-a31gylQyVZORMT`!K5eNp=^Ie1&sA^7?MwG5vLVoVRmyr z0vrMP>*E|jj()xIL($O4)oUqLg) zhXHvxppt+ez{2i0TN_H*twd~S8WmDFaf7-?mF=y3J-R0qxzw$;8vy*|6tI&xXg{h#T>yKYZ@kkULjf@$HA^cKbF&A ziB!@0IP;bkX>1}OgQWGaFnb9L1i_^CVwPfR0QZZoPCCoB=6*#2{xfW{7VqaEOPxk& zzTb$*YrWZ(fCIo~9D|io4XMm`N4`%wQ0qAE%P{k)NyjT8dmP!|$MiF#V@+>U#^l0? z?ET;@oWJ8Ongu^C^Zc71u`#PGh;s`qA0$Xkt8E)=U5omU(l~b8; z{IQT98A2jOK?@U4)l@ASBLG7AY+;{7VQK4{H5ST?wlVS{!LwdVj4)UdKbt5;#6ReY5z4q8FE# z$TdECl^t@YI}|9Vk{JlN+@Yer|SwkKxZf$IRYZvRDGr*B(jtKD96@yO5G;r|W|E zj4kwd-IG?MMEQvw9IyN9smT=v+jOL_f}wohG3egu12y&F549H{A3P3si3!VG@m!y~ zQ4DRFIOwzj{c0~>e6YeGoDV*XD)~J~`bozz9yRQ52FKlaO603W(y=SxX>)GAOzw*0 zcmALOJA@SToU4I!J=~_T=|q!fI>hU-y{g?BiHh{H^W!WbzUJxMCV9F60=gyjkCE-a z6{CfFhybq4)U52jF+(K?T~VVKS9Lt5&F& zN0xnmrF6Q4XcJ(=y9;cQrOZRR^jJ0>11|j(;l8a;DQ1i8)dM#b7 z6MW0BqrNqhUvPb1bgX+P|Gaj1x&w>}F$rI2r|y%L4z|Qj30~5!?Q2 zcf=fs!y?d#99|g^&CH!{7+3p;DcRmBc6%3bjtdF&#PfArWHPSzDVI(LQ^Ep71lP{W zT_MWTA^K2IPASYu-BH-u9)JQy#eG7JQ%i*t4Ut@LH(H_Jix-;=E5K0*r@sv=DQF-e z@UM&y;&f;l{L|0*R>bvIOxDodkii7;?EAvRCZI0zr8|JCCLDuaEVV|2M;zncJ-n2X z_>?R0qpx`=U4)=VWL(RiPy%-KY@pgplq*rxP@zzsdGNM04TD2mPIZtvvrhn$WYq0X zmxvU*7WIVxg_t8(oZ9b?su=!VB>^nbU#@VtmO&uBKZv|L1;54!41!Vv0tLHk5h*2H zV5M9Wxh_1VDY&IP`agT_=PSWd<*x-Y0Q@7j0pk`joFKFy>R5n8E5kmczl~sA%Ls38 z6!ta|U0e{`F?Wh_eXKWEqF7&i5R$3)n3VTcFN$P1I#zG73)Qk`Ee981F6}k4)@ff6nL<7>3DM z_Q#1s!qV-3(o$&1tivxXI-u;oS?<-~Ojkz@$13>`AsjV6EGeKx=5Cp@z6~@yr827}n!($$xJ`p3SkmJ+H zz&e{uwl$2sGk4Vm&Or706y6w`&IHc&Mo_J#SomT7D_|v3T2y$f!n09{pXk3OmdMUK zW86wM&_&N)2Zdu<_(g()C7;HHELz{@mGSOXH{~Zz^d`oc{w0oo&y!I3lB&o$>=!xg z4<;upwGQ7&Or^b7(UFvoaZpIq8jE|8g9!^)P0d#5o*h8x^7a%al_a<=5Kb5uume>$ z^(E!%O0}xZ3E~$R#Q_axaEQ}pY2LH8J;exC>$cRt-E^z%1gVw!Bf%%oe`8md+)!q4unPx{rO%aHh1YTu9?tUleq$gbfEN=B zF+Tng4*?9)hrp}AzP<%SOGNIyYke(r7fUsL4Tza-91vuQ4r{8q^1? zy3>H;m^i*wyXb4X@&xveWq{WNFGn>5lFQ6UMlT282z@tXS8Z>~5c<(Hz5M4>^%rM) z*x-N)R2U(@AbAQn%U{a;PDo!_@NTJTBz|efix%wKtbAvW##9NgBMB1PZabXU=ELD3 zD{uAFq0Sq?%zq!#ETAq#)Ar~D(ejUft|4R(v9_=Bz2Y}&zSs2 zT_-%Y>3P@jPmu9yAwcjcK(Yon*zJ!uJf8MOq6nSnBYP_hjA5V zq8xMq4o($HnTMf#3gArj4?+uuk{D{-Xu(U5u#L=8z&%w9B&*meggmGaC-HyMhNTnv z8PZGA*$;<=jUODO5BQ0xdtkdgQI{P`*+ts1%N||MQTbi=i<%ppaj@tH2fCpQL@DB~ zrd!+ZogtmVF|`6)3r5SYLi`&UUT%fB-@rtfi9_m>{z1hHmIQbBBadXcm|tQrsj^nE ze5=3Y<>EoGk+hFVO`xdM0y#U)AY!?a%Z9KkoM6k`WFF2Q!!(R2e^8`MFhVrOy*gdl zf3yTjJQ&JkSgoTTkbJCY=6^PTQ%Meo<^7W?_-2b?s)A>Vm?&(kkxK55ms?B>hNEej z9WmXfcioH+Zw;SVFkIJwsynx6lt%;wWEC8M*$?*_$U&3y{@?o>uw?-1Bpf~Ugu()T zL8az@RFX|<2&ab4cfM2g%lbVy7!QrG8MnlDtC1QbV(Vc4jKv44;8Sw;`YSl>PQAfU zTA0KG3slM(R9j0UF4iMyN`4*~p=plTEba$y?}x1d@h!BC`9n-Z7vQvt)%$Zm7O~$r z!m(8vu*q}jsd67Xu|$=^VfmXxWDPis!>t*>hdTgu87-3kjHdLHnjTc_Q)@ z$g-466Qka~xtOV29imvXX+jSPFlhBxn%3D%M-9Xc2TfbADf+z;0&HK*|FAcu@D__R z5c*8+Wl2)Ou>+tmf;7eu!vQ34Jo_nDXCi?E=1-=9?Y;pUcs#Ngl}vvaX07=*tt%*V{3i`t}r>|`|y znValpisV39{I-`&UuzHvwHU9JAe*vV{Q>6B`2NbGaFf(jL@JjD@PR@lf#fZ84BIq{ z$-J}?Ch`47fGjg0jW`icZ=TZ<@KKVs1ra$e9BUf@4}ddJaj0ame40Sb!$ZS<3R2hd zi=>Aq8V(*{Ro73nXUz>@2(w`iIj+?$XUnqqcg{+9&^qzj6iuqY&I&UK0RH=pq#_zj zyzEbs3WUOo0*MWrXZZb9_|GYtftc=B;_nKm2tjB$f#_4(BgwpAN&ax9KE|cfUk9gU z6}s#pFbB!QH>i zju658{;K?NicBHIE&jajAUfLn1D8`4zw<9$_F`@FjaipXm3C1{HPLVmYsQ3^D z%F;sj`qQN*rWNmtVtocB?@30iOoPJcU==F96&a@s{Z6Sel9~nD_>*H0d3z z>GdA_IY#{v5s`4ngDnwU1nKTal3))cgJ>KAi2*MZLqGzVU_5?*`K9Ohr(hfhpn4pT zg6u~5M=*j4Y;BRYEIw>lGbkJZhIu*m=+F+BdY(;_G*WPL%5z;gxT$;Ow2}|X*bXk? z@&8`q-$xCv*B#uw^uX!�CJd5RMlC>MfIq5MfTRj+dX`>q7l@Mot$!(S!2E6Svl|nsV@5rAoHs_i`3+!xjh+m1 zl}j7D9fSt}imdwcb-Nx&-}L(Wu$F*?S^^hRV5wVt>F|Ho?s^de!iWUS;*4r`|AYgP zKXcj~Ln!*gkY&BGY0A_CiDBG6ooU(hFk;#!(tj_cpP{BsfcJmy4IIW}5v>`I&qqN1 z1Qc|;IX}6jo6Z#v6k#Adu=vF9@T874TZ};}{KYc}N$prVfjSber)>XTp+Yf(+Y)<5 z-q0TgxL9YJ;hKktmEJ!nxYvkXQK{|wiSd(})qJsd8RUBex7-Y!#Ahg%*}0!Fts)A6 zU-yoqMo0pkMpHu{4I(bNXoP4gm(^5NlAQ`uo-BuR}uL96>n$SqmcRy(SY~Xv3iA$=iA%;&JN;60rA~9f? zhHi!m_CqG$pPoVIY!RC^OZfFbfT=cqy-TbW)dcrhay@?4O6E9q7+X%y0favJO`6D# zZ(bC{#Eq$r49ewyrcV4WIMM@Tj=SkWB_9@*K;zvORp5|FNQDxiqk*RjWa((~3#hAq zxrLJW_0R7TdmTICd^$F5q06}-2%cBP5rNxL*L-&%`=PJlH0Wb8aG&D`#4b_MGqDZW z)&c6tmp&rNcptMVG>fWs_Wa4)b* zAkU}5UN-HPMBHK?4j-dgS4RP&KJ)|1h+?T5>sFr>3td`O=zTJ6|5L zw1P7bZNpQDd#1s%uyCrfV@C=;jUhfPouT%`Onz&m^qU3uN;qBTXRi(Xf6wrY2I}uW zlNL0ASA2Lq76j*ug&=&HrCtw~x>5r_4>>JET&9OcPigmk8xB55!bThGh`>)p_tRFK zF_x}jCR{NaU|2MF^bsGna$ zo7Hc3^+RCuaM={N+Vdk)p3ix{>6y89t7nVA(9S6id`P-1-cEwrcbp7QUcIy~N%psKNP#93YdKlJ7m5Ej32QN$xvoJs_ zTM^{eSuWvTBSp94Sm|@vPOjXW{OPZHp2r=>r~Hn`q{c>Dz*66)AEqn0lxdkE##}}a zJ$2c4ZPdW8{=HNd5+J_iC`IPy7fML-|q?!oL z4kO%R{;&=IyvU1P|Epe5HJ;@JEp7t^p;x}xZ9}}WmwcM*d+AK)I=wZn&rOkjYcvU5qubBX}DpzNcaYmmtT>e*gS(o$pteDh1^oPPzml z>ZYcBmPZcy2j3#Lo&akcJ)o#ioiNgqgZ&5xnjBA-0E!0 zB+u!;%#?Wv7MDC@OL{*GFX`3^+k8}A8;vhK9GjG81!f1QRqk?n!UD~mmn77`Mjphv zUsS<{NM=0^UdwB%X!e+q_$6jqo5T4tVXC5(qFd$LaAeiFGf7pyr!@_*CpFs#B=LQj z2!8?)ILl}BSOX=PcU8rjqi5j^p)ST=`o(yQF|YS_zOPzIUzN^lL8SCf8A7`xw_5aY z(NnBjh@IUrkbk&M5Lc$)a2*ysaxO|P{*2DR2s8j)jb8XNt$MXV9~JoVmGh3{xn z%Vm4G?A+xQhdk0;|HQKG5S#Uqp$*FeY-V{zd>UqEJ`vv9H0&857K>^cvqnFwi||n4 zoxigLBM5!Qsb`11@QMRvK&g5Ugvt}et;lK{RHxr1L_-FncPi#>1Sx7U$nC`3mc^7!*gIy6~ePd$>0DJel4M!c{p^ zLZ2Zh(t3ugtPf;tEHcsc!u`b64H};&)UE2>_c4cDL!M>AG`|*2eP?wa3$!y;MktHk zrY=^;GFXZ&0%QF`4+_u@P9M}Juf^|`>v zu2wBT!%OGWxwmb7>*bu%LP$%qhe`f&@dtzVpB?7X#ROheW*Ub~7;@2iPbo(xk zpU<09xr-hI?o!vAo(s?~kSof!f0zaxgF{b`dsjFGf;l47e9d<|KcC}=(2kaW{Cybs znKwcPyiB@COYMy&EBL5M>@nD*X&@eV&DMPtkC%al1Gv zI}Xcm$uUoY!myCu(2av)0Bs9LY8>4uhu~BnHzAuyY^w@M^Ld7xcr|x9EwlY(8!VZ( za6vJ4Pk}J9gvki*`>jtQ7l9}O-T-8x2go7ovq@S$mp`c%^XG;lld)4sniiU`yRP850tdY>qXOs z8*sT(@5JJ&k1X z_GB-$VpqthX-fQ)RFP5bDQchH^MEI$C@k7^Mtk2HF1z73m2_EA z&oBi(rK#d3g)Hfo-fU68%E3*^J|W}$cpi;Hnd$oS9zXBOnMRU^29?Ke8Y9kBqdF?Q zLufXtX1>_pB7+YaU6=w*^c<1hLPI%2^ZZ5gOL@_BnvaW3DeMEwj{^;}46Bbs;;iz(Z!d6t)lIuEq-JBv+7##|#bHiX5i?|Z5>1y0yI#)8Fm;^x10 z<7v%IRgsHPJO9dB(Gji`v3!_Z+QK=v?IR=<8y3-e)}?>zIgkiJ_6jKS@KqD_fMpEsUwWgJT8JO@oPHv{FGi9juu+B^R3QgH3(`R zeX|?gmilXRG3F<&*^TxOBXd_|%i_uce@aW$iK8evgD{bkFqlJy4>K35t?o`TN9@w% zMU;4KI`3Z$LEh$U3&koSdIkxlSqpn#61LrnPJAm*ZfwjP|D7b`mBP=Kb^pb!eY5w-xIwGwSH`UzX|N^W0V~1Ioz4cuR#<%Y5$t+Fusys?z6J9$x=8 zjia>69JO?t{cBBAny^S0oHXrR#+X>9Qf|a(jZF)OcN*b&S{$$y!fNIe^4DVXu=-zN zjUZvo203Lqy@MHJg{NFjC7t7}RsBbQ<%9mrHzvLaox7l7ci!X1e1pWMP1-8xVQm>* zv6De1;ZbW0X+s%PHSO{E^+EPvxevh{NE|G)S?>E${A2d?UkFV+V_8YBMbxTvbwnI_ zenvFmdC#FmDnmu*gGI&9li-;0j8&_WpY#o*p(%o8-RV}@57I-P=VbxsX#xAa2{si< zVJ)tV^^}MGF-&7GHd70w4RvP;qc$|iYBj6p6FOFt$h5vU%q=e!bumn>=oVcsOb9gQ zLcJC0cIUGKEFI#u9&#-DVK&Wme-(H0MhH*)Z>*OdG^%(9WmjR&IP)Z;l={>~8%W#jAn&&#kqN2#1dtHIIFmT3C0dU~H3>DE4=)+S-_BtE{Uz zkIw28&$BPi|0!N145Z~-E*P2hv9kV`(APtZAo=B|Rdz*i6+zFZ8&M*jH7W1DmY2|IqNBldGT6?YLpe9xZ5+PFYEHu11Wi_eQtg zX6+w6RhEs;yC4@IFO`2@*q|eZy~s5?N^HR~Ca(!qi{du@B1RyhldjdPTmR|j^FTfXB&551Sp8vD2xkqwM1@wbD$!lu(Den> zp#QNuNq`V!*KEjD?c!BmliFkPny(B(umiythw*66XRu!7z);95fz{D7dkfGJ)7%lc zx@uF-VLbhGHRu{Hw)QlM<1W8?a`xy>)jo@n^@_2asO$P_GMzY!F!l&r9tU&}kUPD)(>gn$H!58ab{+9dQbKY!N55LCL-n>*ubS&8C`{mCw+@;FVE! zy16QNggP8G^J79MhM{SOf;wVnLZ)WUF&`G@p*k9-3oNSIo83D6D^6lFrY4F-0#H4@ zJo&Xh1o&!0^y50mlr5>~hIsCZ$-b7$m!Z80@;UIBTL^kVtLqGUAahIO=v=%3fR4_h zIbRv=T5iz%61b??9E|e0sEI7yIO|25>kI0r;eI$^Gu3|aGGz00f;iSA?6ENnow8#$ zFtOcd|=(rlHo~S|;)r z%pYz!KF&N67r_E+iO5@OoZ9yh&OuK{;W4he)rN0-zbMR@Oi!JIoVWu4Jp5$rSJ*D! zi5gWiet8!1oR;0mL76sJuaWnz)Rk)#el)5i+gdKxYufXO?A5VdaeZ}jpzz{;MZTBt zG!i5Fg;C#VT+Abja+S$>tG0Ba_qASf%Y|jlNwFA8Y4F%+zy}MaQvf`28=4PHaxA|1 zaLdp&8MWU~vfUX^xyniN+VC~1wcp9h^9&AxpC-A@-FUx@v04}y5qR;?2i|{u9IzsL z0JigrvGE#9^CB^EyRhBa)^l?WHR?(8*wd+-NpmSW+pvCaHZZ!ixVrn{HD$@x%;$Th zg~I*I`q5VT(PfLzXQ|mWlFQAF&wI{A|HvqR`~GhH*5Rzq;|H0iSCv*`ljU6TSF#AJ zy(_+;JBl$<|J-*Obhu_K%u8(}M)$9sf%|UC8W@py{gzgfUZUI8ZI&VCIC^uk< z7JB6tL!n1!43`k=CmFXETVMXL|0b7W`NP$qE#X~UK_EAWdUsT+r^r9GQEPUADGz3^ zzk(d(PIVD*lvAp-PAq_sQ+;fM{s`%IdMmEiZ4Ta1j&n$l5v% zSgZ2n8kGXoe{FwEc5XFo=FR)u#?K~L-Yi&9-WGP&WZK84FhuOG%wEJLP;$g`H+!D> ze*s(sqx)|$#QlxsBgApa*)Fqxyw|IjleXvkQTvcXurJ3xI>SMCbY!$GMYN zGq6ADooC{VN8?xD@Tik|snhzhGrN5EoV33?tiS)ew6{CGKYF!WyCvT`t}pqv+j4

gtz#7}&^L;R_$d#y7!w(t90_xrB@JHR`H ziw``0VsoDBIlYE@!XG=bYdnQ3yN+8tyHC8#%RI){x~*?K$1kbJlOM>}=w5#|$%A{R zdwPSX{ARB_%R{l2mpaVHe9cF_)U$adzkJR!e6~~ifG7ROH+Zk(@`2O&&{t)_8~o8D zJ)igaxnsS?JN?ts`qWGP&HuO6=RCG&J%n%lW`F$8(=0s;{n%4#xQn~duPsj}J$tJ? zu7`Egd$ZNgJ>*9|#@BtmPxU(sIM4U|?)CpY*o*wg2fpB!z2|E4o+Cbc=l$X{e&f6S z<4gX{Q~t}h{oQB%n-6%uTY6qAuityV*n>WK4t|anKKdej!mItctN!XcKI|_)^V@xr zV}0stz3nHxrLVZ|cmACBzVADzu;;VzlRKzWfAQ!2@iRT!%Rc(2zxvBQ)-!zc*Z%ZV zKi^mR*JHJ}Z~qJffAIHul>@}4SOd=#taK1zLRbr7Epqs9Q4)z0DJCKG17k*w8Vhyw z_|fA=kr@e9Gzsw`Ls$t}Rw{UAV606uXKJ#kNkmQ&19TcVHfahZ__F_{LX{{Vnlw9cWZJZ6&ysbha%I?qFJTVsx)rC+ zt30bt_4^laV8Me4FRi+FKvu0cyLyd9S1v-hZp*T@d>J$4w<;sgeHpXyR>g?>7B+nv zb!yd75ARisw{c9mXF4B*+fXw^%$IXRyj|NRUC?($XC)nUb#mp)nFp?F)pb_bU1L6m z4E*-O-rKn^${x4&?CPP5>)rdjd3yEh*$;h=Sn*=UvA-1*_&M>xAKnaH~- zzT=Q<55WW#G_AGhbizxM#vHTGKL5hvuRjar0&u(m2{g{Y1w|Z@#Hrqc@3rZus}4Zg zG<@;J7ONAGxbn<9ue1_%+>!ssqE19nIu+@Ytwk4MjIqcWC9Dar0ulQu#~!7evcw-9 z3{uDyXDpISgFNd}#u;h!@WaubM32fe)g;l%tKyRn!X;@Eb4xJ8q|+`rH-WHB5DhF~ z%|HcR@Hyz7d=t(r^_&UMM)O>>MhFpok}os|y%f{+3Z;}ML=)u`(ojR?v&l(0Ei}_q zRn@dXN_+A2Q&MG}mDWDv>xI)w4_uYkUYFZ6*G^%5u-0O2^)y&rclDLoW>*6?*~EsO zmReJzMb+7CwNzPZmZ7237_gARDNXpMind zGh)@1y&Fs%Up6nv+P!H;7@NQua~{b;p~Wc+SDs>f@cbr|!~N)`*Ui|UmIu!bvz(=p gV6~{OhvBl}#7T=78^W@CO_n_Hc5&)eVPLQZ03?Ml{r~^~ literal 0 HcmV?d00001 diff --git a/files/img/OH-2.gif b/files/img/OH-2.gif new file mode 100644 index 0000000000000000000000000000000000000000..0aa4961fb31332bda4c92b7317c496647d2ad943 GIT binary patch literal 131 zcmZ?wbhEHbzPZmZ7237_gARDNXpMind zBVyH+y&Fs%Up6nv+P!H;7@NQua~{b;p~Wc+SDs>f@cbr|!~N)`*Ui|UmIu!bvz(=p fV6~{Ohv97Jq)Ce|Pc^-CL$GXO-{V~#3=Gx)4q!7G literal 0 HcmV?d00001 diff --git a/files/img/OH-3.gif b/files/img/OH-3.gif new file mode 100644 index 0000000000000000000000000000000000000000..beb100995bd3d32be29e0f110636b1ab646000db GIT binary patch literal 128 zcmZ?wbhEHbzPZmZ7237_gARDNXpMind zHDcA3y&Fs%Up6nv+P!H;7@NQua~{b;p~Wc+SDs>f@cbr|!~N)`*KJSri~sRtQgrV- b#-UK{7i7$^B5d)*w&Lne51C7@ObpflQ?M@H literal 0 HcmV?d00001 diff --git a/files/img/ange.gif b/files/img/ange.gif new file mode 100644 index 0000000000000000000000000000000000000000..fb1e5066f5acc5fa7df05c0c43a7c36e1ee9189f GIT binary patch literal 175 zcmZ?wbhEHb6lV}(Sj52a|3Aa;m!|(uGJM^o`2YWZ0RaI9kl=sCpDc_F4D1X#KrRDF zEdz5&#V*!=>(^M$)|PNTrF$nPTtcO@)jN_+XZ55hj%VDmcN-@zsjR)tB>7fh$yN`> z6ona=MQhj13NolT#kK2xZ&m5HEeEpv-O4g~W9Dw3W3&8Z!KDSc&f(tKt%(Npfvc1H|FfuT(FzA4IAhit4?jBy3 z?`fMkI5Q}(;>=lo&L}|CGmWQmX8f_*h6`)`JWm;zotx4y-E?yPisIh3!|hKD1sqH+ ZsBx{D7$oVVE^HdHwutdv*&GH2YXHKGC(Zx> literal 0 HcmV?d00001 diff --git a/files/img/argh.gif b/files/img/argh.gif new file mode 100644 index 0000000000000000000000000000000000000000..234f8be249c7cef325009bd90761023bcbc49bf7 GIT binary patch literal 141 zcmZ?wbhEHb6k*_JSj52a|0KiLU5dY7n*RU)p8?1PlR$>zPZmZ7237_gAe#ZCmVr4a zV%3$s8*JQKwhEuC+O2T$u&Fp_L-!9}XV(o!R!-Euxy7Nu>r49VT_NX-Prj9rV?VAT pb2mbl(RfL-Q?lbim+vjCn?#O%fAZs<(vU019|7T!eQ2fcl$iTqFpaWzxfaDpNRHulpJkH3^ m?7V>~bI#hJ{CBnfN<~jQmo;V0xtz7vUDe;=tW7>6gEaskT^i{C literal 0 HcmV?d00001 diff --git a/files/img/biere.gif b/files/img/biere.gif new file mode 100644 index 0000000000000000000000000000000000000000..86a8e4aee1e7bb17dfc854e784e5565cd0b9321e GIT binary patch literal 140 zcmZ?wbhEHb6l4%$Sj51fq$KzM*V(W4Hh-Dt&A`C$|Nnm=2?UBiSr{1@SQ&Ic9FSTD z=D>(uUgtLKkUZ3~?p3b%!^_uAZ<)+F{5X{5Rojx{ZJAnkrue+)`}cCQq@xnY)-tC@ p8v?WKI9&UUIb*$+txOEe{a>w4VW!jR4ha@-|tO4S$HG}{F literal 0 HcmV?d00001 diff --git a/files/img/bombe.gif b/files/img/bombe.gif new file mode 100644 index 0000000000000000000000000000000000000000..2cdf9062b7d927d6247f1fb03be2f00aaaa5de0f GIT binary patch literal 112 zcmZ?wbhEHb6lV}(n8?8JzlGud|Njg?#{d6{KUo+V7?>G!fLsQUJOh*Coc_uURZ4C? zJ(ih|TrS#i6iQBONSl$_#?BV-U=iQtc^{w6*|z3|_4$uK^$sPjt58z%6+bC-z1l4J O=*#07dztiE8LR<>kt+iL literal 0 HcmV?d00001 diff --git a/files/img/bouche.gif b/files/img/bouche.gif new file mode 100644 index 0000000000000000000000000000000000000000..0d0842ef8ded5e64d26c799bdd900cb1cd34bba9 GIT binary patch literal 104 zcmZ?wbhEHb6k*_ESj52apMfD1NT#JR0LlMA9uz44WMO1rU}4Y!@j+@Cm~}mNUA~p< wY1Wb(w&P~Q{{`CxV>9Xkh1cY~UiY$KUb1EP#FWdH;i(5MK4H}46K1dm0GFpApa1{> literal 0 HcmV?d00001 diff --git a/files/img/bouqin.gif b/files/img/bouqin.gif new file mode 100644 index 0000000000000000000000000000000000000000..6e5cc4ae47108c2afc2ae29e3ab53385f5b3ae8d GIT binary patch literal 90 zcmZ?wbhEHb6k_0Gn8?6z?%cWL`6|^L$0p8~NE5i}`h1d{a<-F#T6Xm77kO(rl(-nI0q)Zs`~Uy| literal 0 HcmV?d00001 diff --git a/files/img/cadeau.gif b/files/img/cadeau.gif new file mode 100644 index 0000000000000000000000000000000000000000..01b40f1a0b49d34d955a58534d5f5f3d3c2682bc GIT binary patch literal 137 zcmZ?wbhEHb6l4%!Sj51yQB*|H=VGTQFtyxU|u$}8!{Ppga2B|)m-xsx%BLbJ}$Tc%1 g3xAg}VhN5-RbG&=(tua|!`woZ*%N7+lY3r}lU->3zci3!+y<2zQoKem%_nz-ryidx3?G{1|)&Q(N BIiCOk literal 0 HcmV?d00001 diff --git a/files/img/clin-oeuil-langue.gif b/files/img/clin-oeuil-langue.gif new file mode 100644 index 0000000000000000000000000000000000000000..cdb16422ebd67826153b1152bf28e9fd2a3233c3 GIT binary patch literal 126 zcmZ?wbhEHb308 literal 0 HcmV?d00001 diff --git a/files/img/clin-oeuil.gif b/files/img/clin-oeuil.gif new file mode 100644 index 0000000000000000000000000000000000000000..13f40497be04e44758d2f1e544da77c4eddb7c22 GIT binary patch literal 123 zcmZ?wbhEHbCBX3+-2 z9ZR~!9`MLzI$9L=rgx@9dOE(ciFrLs&vUYTdHM|nP6IyG=fO`^4ts6fJWFNvnZ?gK V8QJDud8IXbPtA^y2s1_oYXC1ZEYko0 literal 0 HcmV?d00001 diff --git a/files/img/coeur.gif b/files/img/coeur.gif new file mode 100644 index 0000000000000000000000000000000000000000..e2bd8cbbd4e9c0b6e903235ad0390baa06e20d5d GIT binary patch literal 94 zcmZ?wbhEHb6k!l#n8?8JABg?~2@t9HlZBCiftf)E$YlV@Gcf7TY0Q|u;m(~7u1jK@ scFDZB$C_X{|NjF?2vGdV!pOkD!k`1zPZmZ7237_gARDNXpMind zA!5~)y&Fs%Up6nv+P&%QWCnqrRIZyExjF(ZIZqF5{88n1@5~Q}9}b6nK5?>X7_sWg z-VIwEUp6nv+WqMo<3WoQOie*)`yTowJG(gdu5BRqR!$=prpV@JuN0UA TG=f?(6_;P>Xc6&bV6X-NsGcl* literal 0 HcmV?d00001 diff --git a/files/img/diable.gif b/files/img/diable.gif new file mode 100644 index 0000000000000000000000000000000000000000..a9efa773998f561f88c77e6f71ef547bd41caa80 GIT binary patch literal 166 zcmZ?wbhEHbf0KW|H2r^$;r~g7ue%ig&1LwP%luD^;Xebzv}w~A zfNK5&nNXnklZBCifrmi{#0Qzdz!F@b>$Y_18KvDV&ubEv>` L_u0f`B?fB%aw0$l literal 0 HcmV?d00001 diff --git a/files/img/dwchat.gif b/files/img/dwchat.gif new file mode 100644 index 0000000000000000000000000000000000000000..4ef385d18f5a533edc2857e97588e44273ec83f7 GIT binary patch literal 136 zcmZ?wbhEHb6lM@&Sj50!S=4J)+v%)TDGxXu}{ zIXX|799HeQtU;~df_m2zBTMz!RZIpviWcoDy6+8rn_FhRRsWsI;3&wg(zDX)|XR4bD8h1+#<}Wcyjt@RYnGD0Guf<1^@s6 literal 0 HcmV?d00001 diff --git a/files/img/enerve1.gif b/files/img/enerve1.gif new file mode 100644 index 0000000000000000000000000000000000000000..f5aa1277dcb2b2dbdc2d17fd83f1f8f92469864f GIT binary patch literal 123 zcmZ?wbhEHb{|NjF?2vGdV!pOkD!k`1bM6Z^mSEGP`DgB$X59R#*>B*fpt9PK$ysJo2@k`( T^QlW3*Tg9au@_HdV6X-NF#ITU literal 0 HcmV?d00001 diff --git a/files/img/enerve2.gif b/files/img/enerve2.gif new file mode 100644 index 0000000000000000000000000000000000000000..1bee451c905d05c2f4542b308b1f63a4c10ef8ec GIT binary patch literal 125 zcmZ?wbhEHb{|NjF?2vGdV!pOkD!k`1bM6Z^mSEGP`DgB$R)qiLO*8d$Xc1y*HJGVzK*w-K VL&g@#OoR2)JB~bzQDI=P1^|D?Dh>bu literal 0 HcmV?d00001 diff --git a/files/img/femme.gif b/files/img/femme.gif new file mode 100644 index 0000000000000000000000000000000000000000..64ec60d81c7dc6a5ef6468ee3e865bdc1bf9e7e6 GIT binary patch literal 85 zcmZ?wbhEHb44kW~E1!pOkD#GnIYGl1k7nAE1oR(3x)IICLc l40r$Dkk9WDCvIT8Ib)9UPCczj$BMozT3e=Ud0K?Q8UQeh9UA}u literal 0 HcmV?d00001 diff --git a/files/img/fille.gif b/files/img/fille.gif new file mode 100644 index 0000000000000000000000000000000000000000..c8629fcfa4521f190eb4ba0c4accc1230ed6c224 GIT binary patch literal 100 zcmZ?wbhEHb*GftTnxTsB0>8Wui1A{dHE7CZH literal 0 HcmV?d00001 diff --git a/files/img/fume.gif b/files/img/fume.gif new file mode 100644 index 0000000000000000000000000000000000000000..b86b4e578a16112c5fef1f8aae694cbc1470a9b3 GIT binary patch literal 152 zcmZ?wbhEHb6lV}%Sj51Pn;ZK3rRo2Z3}1IC{%2tL{~t(zNX4Hlj0_Cy3_3tA14u0c zb8N+`YkLh2iDlIWNuADTJAJLNNwKlVHPDfBA-h7Hv^LK&riR}(VcX~Em3{czH1m;v z>lq2lzKmuE4qmt3rn1#bg?O7+m%RB9#okn6rQ>6CAhFDviQ9Fu_4c|Q9t;fD0KH#1 AH~;_u literal 0 HcmV?d00001 diff --git a/files/img/garcon.gif b/files/img/garcon.gif new file mode 100644 index 0000000000000000000000000000000000000000..56c8b56ea8185b8731c24debe361b60fec3a0430 GIT binary patch literal 129 zcmZ?wbhEHb{|NjF?2vGdV!pOkD!k`15WW(%({!h4T!fcQ6A4uU- P?w$WdXyO7TP6lfL+~O(I literal 0 HcmV?d00001 diff --git a/files/img/halloween.gif b/files/img/halloween.gif new file mode 100644 index 0000000000000000000000000000000000000000..cf68645369307ea17d3f806171d22418fb101942 GIT binary patch literal 155 zcmZ?wbhEHb6lV}(Sj51@aZ?;c+oyf?fH^7n#WhN^B+7p>u25B9S;6#GP5|WBsI4AsD$}B37y*_|Tr0lffDQ+|z`(|!17rhL z@-i?m>t;mVS-P6T;Ao0l*lyOLXj28RFt{{u2K$IF8+UX`~Uy{3=9kqQt>AXBLf2)gAP!H0i>3J z**hcZPMp>(rxj~M*L^SHOweEp_|m&5K(Fz^K7Gx?FFbcD_|^#9J=s5(Q(%v1;nJqO iN^hguv#cLps=VrA?)bEGNu_Lyfve21j{Wyo7_0%Zjy5s? literal 0 HcmV?d00001 diff --git a/files/img/love.gif b/files/img/love.gif new file mode 100644 index 0000000000000000000000000000000000000000..ceddd1453b2a2f1332a8804c4b8f59491010b4cf GIT binary patch literal 123 zcmZ?wbhEHb4`cqF<1itPDvnI literal 0 HcmV?d00001 diff --git a/files/img/mecontent.gif b/files/img/mecontent.gif new file mode 100644 index 0000000000000000000000000000000000000000..445d8d7b3d061cf37107c698cc0064ce7d51236d GIT binary patch literal 125 zcmZ?wbhEHb{|NjF?2vGdV!pOkD!k`1FPZmZ7 z1`Y-tkQB%a29{8Pla&Emjc*^`KCNA#=#h9AQ&nK*>vhXt^M$Y3w&m-#=MEE$X7;l% zu&^GDUs2)1)VyS2tAe!z*A1zu<-8T#B27QSKd@~`xR4lQS8pogw{z}4j|&et7_0%L CEj#`I literal 0 HcmV?d00001 diff --git a/files/img/ordi.gif b/files/img/ordi.gif new file mode 100644 index 0000000000000000000000000000000000000000..bf01417e428114a43ebff210b03afc8c7bea73db GIT binary patch literal 127 zcmZ?wbhEHb6lM@$Sj50^=FI=QAo9%V)2CfrTo@P_{{R0EBo%+MFfuT(G3Wr<3?Q`( z%q|&GckXG4Ij&x-I?Hp{|CR}!OpJ3hr24#P?pu9qZ>GB7_8>|AHT!^gwV%g5K-#oz3w)!fJ5H*-dp{j^Sw1q-_7 cbS$3P*V)BmFVMMi<%%V9Teh?)DKc0C06B+YI{*Lx literal 0 HcmV?d00001 diff --git a/files/img/pleure.gif b/files/img/pleure.gif new file mode 100644 index 0000000000000000000000000000000000000000..9025b2639165040fb64a1ddeb8050938f06ea913 GIT binary patch literal 132 zcmZ?wbhEHbc`LtEIud`PU4wza8UWndB4_{r literal 0 HcmV?d00001 diff --git a/files/img/pomme.gif b/files/img/pomme.gif new file mode 100644 index 0000000000000000000000000000000000000000..fa3fd72d8feb895ae61a2b087f5dcfc9b1500baa GIT binary patch literal 118 zcmZ?wbhEHb6krf!Sj51<@SlOf`S)v|SDk*nwNd#+v1Z4*nTx`cSR79s MbGHgrVPLQZ05|L>2LJ#7 literal 0 HcmV?d00001 diff --git a/files/img/portable.gif b/files/img/portable.gif new file mode 100644 index 0000000000000000000000000000000000000000..5354b05942add6dd779c03d39aa11ad9872e0c73 GIT binary patch literal 135 zcmZ?wbhEHb6k!lzSj51R{#J2 literal 0 HcmV?d00001 diff --git a/files/img/pouce-non.gif b/files/img/pouce-non.gif new file mode 100644 index 0000000000000000000000000000000000000000..fbb550ee40abab5118aa2c22344e194b74c8d659 GIT binary patch literal 165 zcmZ?wbhEHb6k`x#Sj52a|0KiLU5fwz|Ns5clmW>7{~t&Kf#OdVMg|5}1|1Lwq?Um> zD`HE`KLb5S)`@Qp-MJ&Bu*1g1HM2!x8FN-tm((`qg2Log@7J!K(R1@TGnY@pnwdfg zI-yOcmIhAjbWJ~V`?A)lhE47>lpKWlmYtid?$Ebs>+MnohvoZi5AZggm4EoSN>;_M OPOz;}s=bSo!5RRK`#@p< literal 0 HcmV?d00001 diff --git a/files/img/pouce-oui.gif b/files/img/pouce-oui.gif new file mode 100644 index 0000000000000000000000000000000000000000..d19f65ae5978321a72b3027aa00cc224a5e3dfdd GIT binary patch literal 166 zcmZ?wbhEHb6lV}(Sj5Wk|0KiLU5fwz|Ns5cl!1W($N-W+p!k!8k%57gK?lSEsbyf! zj&Sw)W#FX7GP&Z~t0J}8s;1#Ad2kU0t#@BO9U##?4u%N(! zg+kz Ot@`dB!YYEC4AuZ-Bt6&w literal 0 HcmV?d00001 diff --git a/files/img/roll-eyes.gif b/files/img/roll-eyes.gif new file mode 100644 index 0000000000000000000000000000000000000000..2f314b83e215fd2606bfd3c15206043958c8cd85 GIT binary patch literal 126 zcmZ?wbhEHbzPZmZ7237_gARDNXpMind zIbzk7y&Fs%Up6nv+P$eDj9K7}xz7>Lo=K*2o^i4SNB9=+&D^;?e6M`J8fS}u zrgiAx53ebaG0$8gzsAfxIZuFL!-kf#%jVt^jN7*Cnzg2$^!@ftR;FfL4;C^oSOWlk Cxg_ZT literal 0 HcmV?d00001 diff --git a/files/img/sapin.gif b/files/img/sapin.gif new file mode 100644 index 0000000000000000000000000000000000000000..61b765f1917e650b9f1d3d68b3cc34fe8126c746 GIT binary patch literal 94 zcmZ?wbhEHb(H}g%Q+=Y+YgV~u-Pk_2(`))m@oSN}pC1TuwDBE0u!w=d8UQ4^AeI0C literal 0 HcmV?d00001 diff --git a/files/img/sleep.gif b/files/img/sleep.gif new file mode 100644 index 0000000000000000000000000000000000000000..b92f62fdf297279373f62986bcecb8b621e0de31 GIT binary patch literal 138 zcmZ?wbhEHb6ldUPSj52a|0KiLU5X4048LER{{R0U$bbOFpDc_F3@i*fATCHP1GB%! zs!My19A&?~WBMjlt$#Pwj1)LZCW)j@GoBNmGbQc9QI%dsvw5%A&&y}yxmVz#@VD6K_c&}OJmZhoMlUwHC_qQ*V*o^%XVmO&92z@%O##R*<4}o@DZ}~ rI9L$2hIP&rtv6a<6OFDLtUqlOYIMnDW%AC__eQ5dX%GnC{H@x#|WIU&o%+l27_Bx%1 UVcz-09Lg3^`huQDlNcDR0n=40=l}o! literal 0 HcmV?d00001 diff --git a/files/img/terre.gif b/files/img/terre.gif new file mode 100644 index 0000000000000000000000000000000000000000..b3b031c4d035ee3ca7d3c23be1e554982d8fbe29 GIT binary patch literal 126 zcmZ?wbhEHb+=_~IBR6+wqQo| Xv<}9GkXJn>({6aX2=%BiFjxZs5(F%? literal 0 HcmV?d00001 diff --git a/files/img/verre-eau.gif b/files/img/verre-eau.gif new file mode 100644 index 0000000000000000000000000000000000000000..65c5b1b8786a0a3d4e187ce4bafd5bdb18137b29 GIT binary patch literal 89 zcmZ?wbhEHbFMYP8j=Q{ZqFu`A%iLB?dvmI*z-IrtH7uVGA2?~K!N6b*048`K4FCWD literal 0 HcmV?d00001 diff --git a/files/img/verre-vin.gif b/files/img/verre-vin.gif new file mode 100644 index 0000000000000000000000000000000000000000..e8eb3c6dc7af8f187488694cff5a866c9773127d GIT binary patch literal 89 zcmZ?wbhEHb8R6YWw?U*@)I+M82d1vdNFtzr0l_`pd+4F(2l0L(}p+5i9m literal 0 HcmV?d00001 diff --git a/files/img/yinyang.gif b/files/img/yinyang.gif new file mode 100644 index 0000000000000000000000000000000000000000..6956ce9d7185ca2093aa50a0f79eef253aab17b5 GIT binary patch literal 95 zcmZ?wbhEHb + + + + + + + +Test your applet +---------------- + A test tool is available at http://www.pjirc.com/check. + This tool will detect common errors and mistakes. + +What is a server? +----------------- + A server is any entity the client (PJIRC) connects to. There + are three types of servers : + - IRC server : usually referred as "the server", this is + the server PJIRC was designed to connect to. + + - DCC server : a DCC (for Direct Client to Client) is a + special server for handling direct + connections to other clients. + + - Null server : the Null server is a ghost server, + physically connected to nothing. + +What is a source? +----------------- + The term "source" will be used throughout the remaining of this + document. In short, a "source" stands for any "window" that can + receive or send text or data to or from a server. A Channel is a + Source, bound to an IRC server. A DCCChat is also a source, but + bound to a DCC server. Here is the list of all known sources : + + - Default : not bound to anything (bound to the Null server), + the Default source is used to handle any + server-independent operations. This source + cannot be left. It is only present if multiserver + support is enabled. + + - Status : bound to an IRC server, the Status is used for + any IRC server-specific operations or notifications. + Leaving this source will lead to the server + disconnection and eventually to all any sources + related to this server. This source is unique and + cannot be left is multiserver support is disabled. + + - Query : bound to an IRC server, the Query is a private + chat between two clients, via the IRC server. This + source can be left at any time. + + - Channel : bound to an IRC server, the Channel is a + public room where many clients can chat, via + the IRC server. This source can be left at + any time, provided it is not restricted to do + so by the application configuration. Leaving + this source may sometimes take several seconds + since a feedback from the server is required. + + - ChanList : bound to an IRC server, the ChanList enumerates + the listing of all available Channels on the + IRC server. This source can be left at any time. + + - DCCChat : bound to a DCC server, the DCCChat is a private + chat between two clients, via the DCC server. This + source can be left at any time. Leaving this + source will lead to the DCC server disconnection. + + - DCCFile : bound to a DCC server, the DCCFile is a special + source used for transmitting files from a client + to another, via the DCC server. This source can + be left at any time. Leaving this source will + lead to the DCC server disconnection. + +Parameters +---------- + parameters are passed to the applet via the following syntax : + + +Mandatory parameters +-------------------- + + nick : default nick to be used. '?' characters will be replaced by random + numbers. + Example : + will tell the applet to use nicks + such as Guest47 + + fullname : "real" user name, sent to IRC server. + Example : + + + host : IRC server host. + Example : + + + gui : PJIRC graphical user interface. + Example : + + + +Optional parameters +------------------- + + port : IRC server port. By default, the port is 6667. + ---- + + Example : + + + commandX, with X a figure : Tells the applet to execute this command once + -------- connected to the server. + + The first command MUST be command1, and there can + be no "gap" in the numbers : the command14 MUST be + after command13, and NOT after command12. + + If the command is not prefixed by /, then the + string is passed as it to the server. Otherwise, + it is sent through the status window interpretor. + + Example : + + + + language : sets the langage to be used. The name corresponds to a langage file + -------- that must be accessible from the applet. For example, if there is + a file lang/mylang.lng, then you may enter value="lang/mylang". + By default, the langage is english. + + Example : + + + quitmessage : sets the quit message. By default, this message is empty. + ----------- + + Example : + + + asl : enable or disable asl handling. Asl (for age, sex and localtion) is + --- parsed from the full user name. Other parts of the software may behave + differently provided the nick is male or female, its age, and so on... + The full name format is expected to be "age sex localtion", for instance + "22 m Belgium". By default, asl is disabled. + + Example : + + + aslmale : set the string corresponding to the male gender in the full name for + ------- asl parsing. Default value is "m". + + Example : + + + aslfemale : set the string corresponding to the female gender in the full name + --------- for asl parsing. Default value is "f". + + Example : + + + aslunknown : set the string corresponding to the unknown gender in the full + ---------- name for asl parsing. Default value is "x". + + Example : + + + useinfo : replace the status window by the info window. The info window acts + ------- exactly as the status window, but only shows motd and welcome + messages. Since whois etc... results are no more shown, popup + commands such as whois, finger, etc... are disabled. By default, + the info window is disabled. + + Example : + + + soundbeep : set the beep sound. The beep sound is the sound played when the + --------- /beep command is used. The file must be in .au format. + + Example : + + + soundquery : set the incoming private sound. The sound is played when a new + ---------- private source is opened. + + Example : + + + password : set the server password on connection. + -------- + + Example : + + + alternatenick : set the alternate nickname, to be used if primary nickname is + ------------- already used on the server. + + Example : + + + languageencoding : set the language file encoding to be used. If not + ---------------- specified, default encoding will be used. + + Example : + + + authorizedjoinlist : set the list of channels the user is authorized to join. + ------------------ Syntax is "all-#channel1-#channel2-..." or + "none+#channel1+#channel2+...". By default, authorized + join list is "all". + + Example : + + + authorizedleavelist : set the list of channels the user is authorized to + ------------------- leave. Syntax is "all-#channel1-#channel2-..." or + "none+#channel1+#channel2+...". By default, authorized + leave list is "all". + + Example : + + + authorizedcommandlist : set the list of command the user is athorized to do. + --------------------- Syntax is "all-command1-command2-..." or + "none+command1+command2+...". By default, authorized + command list is "all". Don't prefix the command with + the / character. + Example : + + + + coding : specify what encoding algorithm should be used for sending the text + ------ to the irc server. By default, encoding 1 is used. Values are : + 0 : strict ascii, MSB is dropped, shouldn't be used. + 1 : pjirc unicode to ascii protocol, charcode is sent as it if + below than \u0x00ff. Should be used if pjirc is used with + other non UTF-8 compatible clients. + 2 : UTF-8 + 3 : local charset coding, should be avoided when possible for + compatibility reasons + + Example : + + + lngextension : modify the default lng file extension. By default, lng + ------------ extension is "lng". + + Example : + + + userid : set the userid. The user id will be used for ident id and for + ------ user name at connect-time. If the id is empty, then full name + will be used for id, and nickname will be used as username + at connect time. By default, userid is empty. + + Example : + + + autoconnection : set whether the applet should try to trigger connection + -------------- as soon at it is launched. By default, the applet will + try to connect. + + Example : + + + useidentserver : enable or disable the ident server. By default, the + -------------- server is enabled. + + Example : + + + mutliserver : enable or disable the multiserver support. By default, + ----------- multiserver is disabled. + + Example : + + + alternateserverI : set the Ith alternate server. Syntax is + ---------------- "host port" or "host port password". + + Example : + + + serveralias : set the default server alias. By default, server alias + ----------- is empty string. + + Example : + + + noasldisplayprefix : set the "no display asl" full name prefix. If the + ------------------ user's full name begins with this prefix, then + the floating asl window won't be displayed. An + empty string disables this feature. By default, + prefix is disabled. + Example : + + + pluginX : set the Xth plugin to be loaded at startup. + ------- + + Example : + + + soundwordX : set the Xth sound configuration. Syntax is "word sound". When + ---------- "word" is detected in a message, then "sound" is played. + + Example : + + + fingerreply : set the finger reply. + ----------- + + Example : + + + userinforeply : set the user info reply. + ------------- + + Example : + + + fileparameter : URL to the file containing all PJIRC parameters. + ------------- The configuration file format is the same as the + pjirc.cfg file. If other parameters are specified + using the html tags, they will be mixed. + + Example : + + + aslseparatorstring : set the asl separator string. When the ASL parser + ------------------ reach this string, the parsing stops and any text + being found after this string (including the + separator) will be ignored. + + Example : + + + allowdccchat : set whether dcc chat is allowed. By default, this is + ------------ true. + + Example : + + + allowdccfile : set whether dcc file is allowed. By default, this is + ------------ true. + + Example : + + + disablequeries : disable all queries. By default, this is not enabled. + -------------- + + Example + + + autorejoin : enables the automatic channel rejoin when kicked out. By default, + ---------- autorejoin is disabled. + + Example + + + initX : set the Xth initial command to be executed when the applet starts + ----- up. This is usefull when several servers needs to be automatically + joined. + + Example + + +Style parameters +---------------- + +'Style' is the name of the library used inside PJIRC for text display. Even +if this display has nothing to do with the actual irc engine, a majority +of all GUI's are likely to use it. As a consequence, 'Style' is included in +the engine package. All 'Style' parameters are prefixed by 'style:'. + + + righttoleft : set right-to-left display, instead of left-to-right default + ----------- display. + + Example : + + + sourcecolorruleN : set the Nth source color rule. Rule syntax is + ---------------- "type name index1=color1 index2=color2 ...". + + Example : + + + + sourcefontruleN : set the Nth source font rule. Rule syntax is + ---------------- "type name fontname fontsize". + + Example : + + + + backgroundimage : toggle master background image switch. If this flag is + --------------- turned off, all background images will be ignored. By + default, background images are disabled. + + Example : + + + backgroundimageX : background image configuration number X. Syntax is + ---------------- "sourcetype sourcename tiling image" with sourcetype and + sourcename the target source type and name, tiling a + figure and image the image file name. Valid source types + are DCCChat, Channel, Query, Status, ChanList and Default. + As for the command parameter, there can't be any gap in the + X indexes. + + Possible tiling values are: + 0 : Center + 1 : Stretch + 2 : Tiling + 3 : Top left + 259 : Top right + 515 : Bottom left + 771 : Bottom right + + Example : + + + + bitmapsmileys : enable or disable bitmap smileys. Once enabled, bitmaps are + ------------- defined via the smiley parameter. By default, bitmap smileys + are disabled. + + Example : + + + smileyX : set the Xnth smiley. A smiley is a pair of text->image. Each time + ------- the text is found on a line, it will be replaced by the + corresponding image. As for the command parameter, the first smiley + must be smiley1 and there must'nt be any gap. The format of the + parameter is "text image", where image is any URL the applet can + access. + + Example : + + + + floatingasl : activate "mouseover" floating asl information. By default, + ----------- floating asl is disabled. "asl" parameter may be also activated, + but this is not mandatory. + + Example : + + + floatingaslalpha : set the floating asl alpha transparency value. Between 0 + ---------------- and 255, 0 is invisible and 255 fully opaque. By default, + alpha value is 170. This parameter may be ignored if the + java virtual machine doens't support transparency. + + Example : + + + linespacing : set the additional space that will be used between two lines + ----------- of text. Default value is zero. Unit is pixel. + + Example : + + + maximumlinecount : set the maximum line count in the history buffer. This + ---------------- can save memory for very long chats. Default value is + 1024. + + Example + + + highlightlinks : highlight links when mouse moves over them. By default, + -------------- this is not enabled. + + Example + + +GUI parameters +-------------- +The Pixx's GUI documentation is available in a separate file in the default +package. All GUI parameters begins with 'gui:', where gui is the name of the +gui. For instance, any Pixx GUI specific parameter will begin by 'pixx:'. + +JavaScript support +------------------ + + PJIRC is designed to support events from the "outside". The applet supports + the following methods : + + void sendString(String str) : + send the given string to the server, through the current source + interpretor. For instance, you can bring the channel list window by + calling sendString("/list") + + void setFieldText(String txt) : + set the textfield content. + + String getFieldText() : + get the textfield content. setFieldText and getFieldText can be combined + to append text for the user. For instance, adding a smiley can be done + using setFieldText(getFieldText()+':)') + + void validateText() : + validate the current textfield content, as if the user pressed the return + key. + + void requestSourceFocus() : + request the active source to gain focus. + + void sendPluginEvent(String pluginName,Object event) : + send the given event value to the given plugin. + + Object getPluginValue(String pluginName,Object valueName) : + Get the plugin value from the given plugin name. + + void requestSourceFocus(String serverName,String type,String name) : + request the given source to gain focus. If serverName is empty, the first + source matching the type and name will receive focus regardless of its + server. + + void sendString(String serverName,String type,String name,String cmd) : + send the given string to the server, through the given source + interpretor. If serverName is empty, the first source matching the type + and name will receive the string, regardless of its server. + + IRCApplication getIRCApplication() : + get the IRCApplication. For advanced use only. + +Minimal html fragment +--------------------- + + + + + + + + + + + +Runtime commands +---------------- + +A runtime command is any text prefixed by the / character. If the so-called +interpretor recognize a command, it will parse and handle it. If not, the +command will be sent as it (but without the initial / character) to the +server. + +Here are the list of all recognized commands. + +ame %message : send an action to all active channels +amsg %message : send a message to all active channels +away [%message] : configure the away status +beep : send a beep to the speakers +clear : clear the window +ctcp %command [%parameters] : send a ctcp request to the given nick +dcc %nick : send a dcc request to the given nick +disconnect : disconnect from the server +echo %message : echo the specified text to the active source +hop : leave and rejoin the active channel +ignore %nick : ignore the specified nick +j %channel [%password] : join the given channel +join %channel [%password] : same as j +kick %nick : kick the given nick +leave : leave the active source +load %plugin : load the given plugin +me %message : send an action to the active source +msg %target %message : send a message to the given target +newserver %alias %host [%port [%password]] : create a new server status +notice %target %message : send a notice to the given target +onotice %target %message : send a notice to all operators at the given target +part : same as leave +ping : ping the given nickname +play %sound : play the given sound, only on the local client +query %nick : query the given nickname +quit [%message] : same as disconnect, but with the given message +raw %command : send a raw command to the server +server %host [%port [%password]] : connect to the given server +sound %soundfile : play the given sound on the client and all other clients on + the source +sleep %millis : freeze the interpretor for the given amount of milliseconds +topic %channel %topic : change the given channel's topic +unignore %nick : unignore the specified nick +unload %plugin : unload the specified plugin +url %url [%target] : open the given url on a new browser window +onserver %server command : execute the following command only if the source + server matches the specified one. This is usefull when used with the + commandX parameters. + +Contacts +-------- + +PJIRC is developped by Plouf - plouf@pjirc.com +Have a look at http://www.pjirc.com/ for news about PJIRC. +PJIRC has an official italian website on http://www.pjirc.it +PJIRC has a CVS repository at SourceForge : + http://sourceforge.net/projects/pjirc diff --git a/files/snd/bell2.au b/files/snd/bell2.au new file mode 100644 index 0000000000000000000000000000000000000000..77fe5da5b01eea5fae53fa5e96fa4ad47b5cf161 GIT binary patch literal 2772 zcmb7^=~I&j0>;tSwz?kMt!G70kR#^{NyvRCB;+9B2oTPAYptSf)$O&r?6h@TXR7sV z1p!5Ykn1Ht?&D1$A$I~v07VW#X^X{eZM*LFnq7AGFW6`1H_x}CFFiO3KXtpYtmyuV9~RT7hp`vGU@oYfVibvYs&bD;yc=;Uf`IYMmn!Z@~eA*V& z)%KpX>n~sZ1ix|}so=^df90&)srpCHyN&HZ*4vgTc3HcJ-21g#*L+S^M9hx;6E!RvN?QOeC+mx@a)nC$(sybiY{CRV7>#nvu z?B!eNwP_bD1^S7HX{@V-SyZPMt-MBld2{o{*_o*W@U)iJ9lI&r7Wj43rk%Z)M_=vM z?Ml;MkZz!MsCm||9j{E?Fl9Yzfo&i9T=jBxtJ3zKS-g?Z+{r4?%x$l1?@rsIyh)=w zda}0MY~kjjR5V0$H+=h^Yy6$6F61BfUyfw5HI@u*3nCTMdMgdO4NC{E-%cfH6$JVX z?N*rbrU2-6X9DWh>>a&E5lPvWx=q_TlxuHGOYdrpY%gqQpbbi33)Chqg3d(t zxH6tiy5m4dbPhz}9Xpb$?L&~25CYJu&=}A_K!H6NlvBq?nRGZ5)Gf?$sG0C+$KKtK zRY~OGt`j+5Du>}hdaoTvGuVh!gORW-p%LvyYJszli+Ab^G2Y%{OsKaU z_*!2NOzV~~r@$p(4>*=D1p`(t`wK+<0UW>Ig=d;vM5YS6c;274cNK9hWz8k{g^ZTv$%%-DXiEO$Cc>41mVCSfn#tHc}6FN zWwO)gRx6!qGqR};6Q43@6yQUqVnW1Fjh`^cakB%D$q)2X1+N+I;cNS&_$p(xfM@a( zMg30dvVg>}KoqLoL8UltbP8nQklkh;#bYieMJ*!yj7?gwXsX5?xBeTy*EB;oVxGZE z&7*`;bCg(Y_EC6dH-&2-BGc{8eb{ zq=g+KTFhBSoq@{8llDW@r;dH(L+;n8Z`khB8|?RJd#z#q9(#}>f`Ux3)5k0t^0B#t z9$wKPB;b1;!~^&^gAeh9(#lP?RHa z`FWDTAV=U2au|_7A^{zOtb}%BSTBalz5sLyoksvlA;6#Uud10@VoAA^N640K)q({zv zHhhTvC3J@Kp7*KXM`*n0sCS+t^^X-+4Bcl}499uWz^F(P3W$~ofwfh`Zt@ec%+3ai4iTybQQUlAS`h+`u{(MU`z z98ZdPQwcHqt5A8-h`(MkNq8)_DE+fH zQF<~mFOrQ+it9q-CGv1WT0WALmW_;+mLx+8St8I_9uFwW?gknq3!xK|hv8%5FZ~PU zKgN!V-i|+$Hb$l^4n?OV2P2Qficq3*UpP^}KN71^j84cT_eQE^W68Smdm{?z}$D&`A)hA{uP6WowYNn>D>LZE0$CL4zlF8UX z`FNs6b~m=Ca(d)Q)lB46#e8h3ZZZ06Nn`9;*?jo#Rey{vRR1!zAU_hCs(K@uICv;F zR{vIFthRP)vbyTQc&+^2M194h`?az^J*bn-#*UOcNgkEHH+`i1+2|?RnY&NrzsA3- XJU#J_RPpuu<%-0N{Litun#2DA>EB+s literal 0 HcmV?d00001 diff --git a/files/snd/ding.au b/files/snd/ding.au new file mode 100644 index 0000000000000000000000000000000000000000..4ec78f03f968dfcbaa686825c027a544b2ad6f35 GIT binary patch literal 4217 zcmdT{O>5*x67~Lrh1r?uUbpS>*loLQ*9V0VLI{Bl$&j#l%EKO#y)EQzFZ)*(W_sMV zyWM4v?Q*$HAqr6x0v&Y7gHCzOACNyI_oYwsU>+IKQ>$P zI4iQV+|G8ggQH3O@ygyD2H~4LzQ1U$qtnr=nl68BZsj5QYo_`8a$fFao2NDVFr7bb zN85Xg?CiQ6?;P!J=KSKU8XxZNzpCxc&-rD%b@W}@EdG;Umz%wBPmKI|d_CSi{r-(h ze!cwd;$ZORHS2#oe`xjw-}Dmk^WDXCFaGv`NAJg>uuV<`1sq!Alm+(_OH+HKP2J7 zcj?LU?D5PDN8g15c{V#=o+hu3!{}mq`EbHEcS--^?q=L0+gq%6JAOEilfzfpV179} zXW{U5IMCIdn??Bi_6Huuuu)x&r^65BiR>E!m|GG)h`X>av8zp!zaNRo`1fJ<<8rrfA?_rDUpXeac_3_a4C3iEACe}PZte|-h@LoUR*9xw$&Sj zzs)~CW^(5+?mx`#ZiqYFO?&yn?260YR&Y|^KYcVT+6qqj?c!=l*miH2+~wmLbw3=1 zqsRRAmYKu7s5gI{eimYY`Xa*rumiT;m)WpCyUQZ#&>$7WV*PSQn!B)4(Csk zJ7(YQ$Gzojc5TJzhp4X~7B@9dcZWkZDQ*^2?DxZHTHHSpdGszBF7nx}kiC5vFDwS;kE=<+_)#y3 zpU@X`y^}O3^88+i(c3goPsN?#$w3&(S$PNUgJF`*is^#N<6aWw#r#po{<|btJr(y> zga>hGo>miu!Z4=u<#fgPF(8ZOQ_fxQG>cZn;*rbXB#U*vnrfcCOJcDoXC>pOL6R-Y z`GUK_AdAc80@>p@7I{6Z&_R@vqM8@DZ)0MJrXvn)y&HDG>ctPKQ)5&l7ts( zUU4}Hvusrs1()H7##On@g^ULz(W@#qg7mV)73xU|-cK@C)Qgh2QAEBS|xe6G{cnwDjDpp~2N?Kc*C2m6~&? z<&~~sM4WO~!>Cp_ZJ=9<3~CM9x15EPxk>>dA`ej|<^so9jd2K`MvUr8tt2M_rM7HV z1`xsoX3(I66moo_XQb$Pg|UU;E>+7-D5l}%L@7+Js~YYku(7To0^G!NTTa4^IzTkI zGb*q<=rke(d$0syK#0Zkkqt5s)+28ZKECmr5V1vz* zlE6Dmx^jLwm~EGX!3c@11tcXXM2JcI<-lsKmqRtBYnMaf43kbW?iUX>qL5*y9mnc$ z7*QK!FIGCMdXThb`hz zYin?)C{#vi?&VMo5z=#0(>O#jlU!)2EqH`r+8NCa<&qg|aSNxCS>qas2TyRPod$$R zE)iMoh?HDQW4L3?wGb{jb=+!)JrF2#4gTS3At6T_CNUP?7}Ib`iGw>9hB6|BRmw1z z0k2>blLRykvO<7RSV)vYB7zp}n4?hCIO_?y6WUrp@Fc=`r_nI6!Zr}gMTSpiHH1?~ zgoBI5BI4F_YbKyUXh`IoXShXyor)Bn;wtnb5^@Bw63j+2LGYm=G5)A=X;Fw=)TDYp^U#Ac9;# zFmkBz5yvga<7Ng!5keso5*N2}AOdnwh%;F192ZodG`JdtxWyOZaq;N3P@qu4Vt9_T7LDf$5jw#kdTq}$ER?0d5(e z!Lq%@7fQS4maQBQevY8qi|`u#s|&jO{OKPefGujioUO5tfDP@sf7Z3euDkyN`5pXh z&f563C7^Dj=j@C7z6`^U*Asd*kn=Uj`pkS0`!z6lUijHc?2G_<-HpfpKGk*9rhR{1 n_Sv#85RdNCUyD59SJSp*M0U;iGV*+Qt&b4+KiZ@J&5!>AuF`$s literal 0 HcmV?d00001 diff --git a/files/thanks.txt b/files/thanks.txt new file mode 100644 index 0000000..bca96ac --- /dev/null +++ b/files/thanks.txt @@ -0,0 +1,61 @@ +Thanks to : + +For direct project contribution + +Ezequiel +Jiquera +Pixx + +For enhancement and debugging support + +codemastr +dhruv +klaus +Phynubis + +For other help, comments and contribution + +Adam Stojanowski +Adam Xero +Adrian Saville +Ahmed +Beloil +Dave +Del Cardoso +Devis Lucato +dickiedoo +Djmccarthy2K +Drew S. Mercury +Ermin Sahinovic +Falcon.be +formula-one.go.ro +gaf +godrik +Goof +Guigui +Hrvoje Hladnik +Jerarckill +Joseph +Kombat +mera +Nadim Shaikli +nawawi +nexia +Nicolás Chaim +opsphey +Raistlin +Red Spider +safkanturk +Shaolin_p +Stilgar +Tim Freedom +Thema +ttyR2 +Uwe Janssen +Vien Tri +Vincent van den Berg +vladanzirojevic +WDgroup Design +Yann + +Sorry for all that I forgotten, just mail-bomb me :) diff --git a/files/versions.txt b/files/versions.txt new file mode 100644 index 0000000..82f5d30 --- /dev/null +++ b/files/versions.txt @@ -0,0 +1,271 @@ +Version history +--------------- + + 1.4b : 31/05/2002 + ---- + Initial version + + 1.41b : 14/06/2002 + ----- + User count on channels + Highlight support + Quit message + + 1.411b : 05/08/2002 + ------ + Fixed /notice alias bug + + 1.42b : 01/10/2002 + ----- + Handling semi-op (%) user flag + + 1.5b : 13/10/2002 + ---- + ASL handling + ShowXXX commands + Problems with autojoin or other "on connect" commands fixed + + 1.6b : 17/10/2002 + ---- + More complete ASL handling + Bitmap graphical smileys + New nicklistwidth, channelfont, chanlistfont and useinfo commands + Chanlist horizontal scrolling bug with incorrect mouse hit-box fixed + Moved unicode special characters to 0xE000 user-defined bank, in order + to avoid problems with mac users + Nick input field + Some other minor changes, fixes and updates + More than 12,000 lines of java so far... + + 1.61 : 23/10/2002 + ---- + Scrollbars now scroll when mouse boutton is maintained down + Chanlist window now optimized (expect dramatic speed increase) + Topic may be scrolled from left to right using mouse + Topic now contains smileys + Chanlist window now shows first channels when openned + Word and url catcher is now more clever, it understands that + matches nick. Same apply for (nick), "nick", etc... + Some bugs fixed + + 1.611 : 24/10/2002 + ----- + Deadlock bug that might occured with scrollbars is now fixed + + 1.62 : 28/10/2002 + ---- + [ and ] characters are no more ignored in word catcher + Sources (Channels, Status, Privates, ...) and Chanlist text color is now + configurable. + + 1.7 : 1/1/2003 + --- + Copy from buffer to system clipboard via a text area popup + Full buffer copy using shift+click on buffer + Sound support + Catchers enhanced + External langage files + + 1.71 : 16/1/2003 + ---- + Server password now supported + StyledList greatly enhanced : must faster drawing speed, more precise + copy behaviour from buffer, top-down support for channels list, less + memory used, ... + Copy from buffer now translates smiley back to original text + Text input field colors matches buffer colors + Little bug with nicklist scrollbar fixed + + 1.72 : 26/1/2003 + ---- + Style selector support added + Backup undocumented parameter source screen removed because lot of people + was using it as a primary end-user interface. Since this screen was only + shown when mandatory parameters weren't provided, I don't consider it as a + feature removal + Ident server now uses given user name for user name ident reply + Alternate nick now supported + Unicode encoding is now supported for file langage, allowing non-latin pjirc + translation + Unicode characters are now supported between PJIRC clients + + 1.73 : 14/2/2003 + ---- + Style selector + command bug fixed + Netscape 4.7 linux scrollbar's deadlock fixed + Netscape 4.7 non-compatible zip-file bug fixed + Mouse hit-test on styledlist bug fixed + Mouse wheel now supported on jvm1.4+ + + 1.8 : 21/3/2003 + --- + Netscape 4.7 linux scrollbar's deadlock fixed once again :) + Javascript external event now supported + The join command now supports password parameter + Background images can now be displayed on channels + Authorized command list can be defined + Authorized join/leave channel list can be defined + "On word" sound event added + Status screen can now be fully removed + Floating hint-box for asl support added + UTF-8 support + Some other minor enhancements + Some other minor bugs fixed + + 1.81 : 23/3/2003 + ---- + Authorizedcommandlist bug fixed + /me capitalized bug fixed + Tab-cycle is now disabled in order to use nick completion + Textfield keyboard focus can now be requested from javascript + + 1.82 : 20/4/2003 + ---- + showconnect bug fixed + ident id can now be configured + several dcc bugs fixed + new /echo command + new /sleep command + single or double-click can now be configured for url catcher + local charset coding may now be used for encoding + lng extension now can be configured + right to left display supported + commandX now go through server status interpretor if prefixed by / + + 1.83 : 21/5/2003 + ---- + 005 reply for server parameter handling + access control with channel containg '+' or a '-' + disable autoconnect + automatic queries configuration + query popup if nick error + popupmenu config + new packaging for the jar-files + + 1.8.4 : 6/6/2003 + ----- + fixed background image bug + fixed nick change deadlock bug + non-applet launch configuration support + advanced mouse configuration support + extended /url command + code size optimization + channel nicklist display optimized + + 1.9.0 : 8/7/2003 + ----- + nick completion now also works with pagedown key + textfield cursor now goes to end-of-line when historic is used + mode reprogrammed using 005 server configuration parameters + more strict RFC implementation for end-of-line symbols (PIRCD bug) + special %% character for popup command replacement + away messages now display in active window + fixed some focus bugs + dock/float support for sources and channel listing added + multiserver support added + alternate servers list on connection failure now supported + no-asl display code support + "unknown" choice for asl sex added + default language file support added + added /sound command + join/part etc messages can now be removed from the current source + + 1.9.1 : 25/8/2003 + ----- + major code refactoring for v2 preparation + CTCP sound handling and global sound command added + floating hint on taskbar, invite handling and other minor enhancements + + 2.0.0 : 1/11/2003 + ----- + multigui support + next z-ordered source should be activated when current active source is undocked + respect threading model for javascript external call + nick alignement to the left should be available + add a parameter for default taskbar item width + input field should have keyboard focus at startup + html page refresh problems + popup on taskbar closes the wrong source or doens't close anything at all + topic doesn't go from right to left when option is set + there are asv instead of asl in the manual + cancelling file selector for file reception via DCC doesn't prevent the file from being downloaded + + 2.0.1 : 25/4/2004 + ----- + /sound support bug + away messages are displayed in both status and query windows + regional issue regarding string case conversion is now fixed + PDK enhancement : javascript can call plugins methods + line spacing option is available in style configuration + + 2.0.2 : 6/6/2004 + ----- + away messages is fixed once again + code has been cleaned up so that Eclipse reports less warnings + automatic channel scrolling + maximum line count can be specified for the message history buffer + docking mechanism can now be configured so that the source is left upon window closure + the whois idle information is now formatted + the configuration parameters can be moved in a file server-side + CTCP userinfo and finger reply is now customizable + plugins and GUI can now add a custom string in the about window + error reporting has been enhanced in case of connection failure + right-clicking on the style selection now selects the background color instead of the foreground color + + 2.0.3 : 27/6/2004 + ----- + animated gif support + nickname format is now configurable + new asl separator string feature + new %4 parameter for popup menu + new interpretor commands for changing color, bold and underline status in Pixx interface + +l bug fixed + maximum line count is now defaulted to 1024 + fixed 'spaces in font names' bug + fixed background color + string beggining with a number bug + + 2.0.4 : 17/7/2004 + ----- + fixed static gif not appearing issue + fixed DCC support + fixed duplicate query on nickname change bug + added nickpostif blank space escaping sequence + enhanced whois reply information + background image can now be placed in any source corner + new "you're now talking in #channel as nickname" message + mIRC background color bug fixed + + 2.1.0 : 27/11/2004 + ----- + Fix : RFC compliance issue: if several spaces are used between IRC protocol parameters, PJIRC + incorectly decodes an empty string instead of the actual parameter + Fix : On Java plug-in 1.5, reloading the page containing the applet might freeze the software + added "enter text here" option + Fix : non-authorized commands can be used anyway if they are prefixed by a space. + parameters from the html tags and from the fileparameter option are now mixed + on-mouse events are now disablable + "on mouse over" link highlighting feature added + dcc chat acceptance popup is now displayed + queries are now disablable + undocked sources can now be removed from the taskbar + simple channel name and topic can be used instead of channel options and so on + + + 2.1.1 : 29/11/2004 + ----- + Fix : applet not working on Microsoft Java Virtual Machine + + 2.2.0 : 13/06/2005 + ----- + Fix : DCC file transfert might fail due to "file size equals -1" issue + Fix : Idle information reports wrong information when idle time is greater than one hour + new "onserver" and "init" commands + added auto-rejoin channel when kicked support + joining an already-joined channel prompts it instead of just ignoring the command + the highliht list is now dynamically configurable by the user + several javascript support enhancements + several PDK enhancements + + 2.2.1 : 20/06/2005 + ----- + Fix : when kicked using the autorejoin mode, all nicknames are reported twice or more in the channel nickname list. diff --git a/src/main/java/IRCApplet.java b/src/main/java/IRCApplet.java new file mode 100644 index 0000000..ee874d7 --- /dev/null +++ b/src/main/java/IRCApplet.java @@ -0,0 +1,251 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2005 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +import irc.AppletFileHandler; +import irc.AppletImageLoader; +import irc.AppletSoundHandler; +import irc.AppletURLHandler; +import irc.ConfigurationLoader; +import irc.EventDispatcher; +import irc.FileHandler; +import irc.IRCApplication; +import irc.IRCConfiguration; +import irc.ParameterMixer; +import irc.ParameterProvider; +import irc.StartupConfiguration; +import irc.StreamParameterProvider; + +import java.awt.FlowLayout; +import java.awt.Label; + +/** + * Root IRCApplet, what is actually displayed in the browser. + */ +public class IRCApplet extends java.applet.Applet implements ParameterProvider { + /** + * + */ + private static final long serialVersionUID = 1L; + private IRCApplication _application; + + @Override + public void init() { + try { + EventDispatcher.disableBadThreadWarning(); + EventDispatcher.dispatchEventSyncEx(this, "startEff", new Object[0]); + EventDispatcher.enableBadThreadWarning(); + } catch (Throwable ex) { + throw new RuntimeException(ex.toString()); + } + } + + @Override + public void destroy() { + try { + EventDispatcher.disableBadThreadWarning(); + EventDispatcher.dispatchEventSyncEx(this, "stopEff", new Object[0]); + EventDispatcher.enableBadThreadWarning(); + } catch (Throwable ex) { + throw new RuntimeException(ex.toString()); + } + } + + /** + * Internally used. + */ + public void startEff() { + try { + ParameterProvider provider = this; + + String useFileParameter = getParameter("fileparameter"); + if (useFileParameter == null) + useFileParameter = "pjirc.cfg"; + + FileHandler file = new AppletFileHandler(this); + provider = new ParameterMixer(provider, new StreamParameterProvider(file.getInputStream(useFileParameter))); + + ConfigurationLoader loader = new ConfigurationLoader(provider, new AppletURLHandler(getAppletContext()), + new AppletImageLoader(this), new AppletSoundHandler(this), new AppletFileHandler(this)); + IRCConfiguration ircConfiguration = loader.loadIRCConfiguration(); + StartupConfiguration startupConfiguration = loader.loadStartupConfiguration(); + + _application = new IRCApplication(ircConfiguration, startupConfiguration, this); + _application.init(); + setVisible(false); + setVisible(true); + } catch (Throwable e) { + setLayout(new FlowLayout(FlowLayout.LEFT)); + add(new Label("Startup error : " + e)); + } + } + + /** + * Internally used. + */ + public void stopEff() { + if (_application != null) + _application.uninit(); + _application = null; + + } + + /** -- javascript support -- **/ + + /** + * Send the given string to the current source interpretor. + * + * @param str + * string to send to the interpretor. + */ + public void sendString(String str) { + if (_application != null) + EventDispatcher.dispatchEventAsync(_application, "sendString", new Object[] { str }); + } + + /** + * Send the given command to the given source interpretor. + * + * @param serverName + * the source's server name, or an empty string if no server + * filtering needs to be done. + * @param type + * the source type. + * @param name + * the source name. + * @param cmd + * the command to send. + */ + public void sendString(String serverName, String type, String name, String cmd) { + if (_application != null) + EventDispatcher.dispatchEventAsync(_application, "sendString", new Object[] { serverName, type, name, cmd }); + } + + /** + * Set the current textfield text. + * + * @param txt + * new textfield text. + */ + public void setFieldText(String txt) { + if (_application != null) + EventDispatcher.dispatchEventAsync(_application, "setFieldText", new Object[] { txt }); + } + + /** + * Get the current textfield text. + * + * @return the current textfield text. + */ + public String getFieldText() { + if (_application != null) { + try { + return (String) EventDispatcher.dispatchEventAsyncAndWaitEx(_application, "getFieldText", new Object[0]); + } catch (Throwable ex) { + throw new RuntimeException(ex.toString()); + } + } + return ""; + } + + /** + * Validate the current textfield text, as if user pressed return key. + */ + public void validateText() { + if (_application != null) + EventDispatcher.dispatchEventAsync(_application, "validateText", new Object[0]); + } + + /** + * Request the active source to gain focus. + */ + public void requestSourceFocus() { + if (_application != null) + EventDispatcher.dispatchEventAsync(_application, "requestSourceFocus", new Object[0]); + } + + /** + * Request the given source to gain focus. + * + * @param serverName + * the source's server name, or an empty string if no server + * filtering needs to be done. + * @param type + * the source type. + * @param name + * the source name. + */ + public void requestSourceFocus(String serverName, String type, String name) { + if (_application != null) + EventDispatcher.dispatchEventAsync(_application, "requestSourceFocus", new Object[] { serverName, type, name }); + } + + /** + * Send the given event value to the given plugin. + * + * @param pluginName + * the plugin name. + * @param event + * the event value to be sent. + */ + public void sendPluginEvent(String pluginName, Object event) { + if (_application != null) + EventDispatcher.dispatchEventAsync(_application, "sendPluginEvent", new Object[] { pluginName, event }); + } + + /** + * Get the plugin value from the given plugin name. + * + * @param pluginName + * the plugin name. + * @param valueName + * the value name. + * @return the returned plugin value, or null if the plugin is not found. + */ + public Object getPluginValue(String pluginName, Object valueName) { + if (_application != null) { + try { + return EventDispatcher.dispatchEventAsyncAndWaitEx(_application, "getPluginValue", new Object[] { pluginName, + valueName }); + } catch (Throwable ex) { + throw new RuntimeException(ex.toString()); + } + } + return null; + } + + /** + * Get the IRCApplication instance. For advanced use only. + * + * @return the IRCApplication instance. + */ + public IRCApplication getIRCApplication() { + return _application; + } + +} \ No newline at end of file diff --git a/src/main/java/irc/AWTImageLoader.java b/src/main/java/irc/AWTImageLoader.java new file mode 100644 index 0000000..e6cff78 --- /dev/null +++ b/src/main/java/irc/AWTImageLoader.java @@ -0,0 +1,44 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +import java.awt.Image; +import java.awt.Toolkit; + +/** + * AWT image loading. + */ +public class AWTImageLoader implements ImageLoader { + @Override + public Image getImage(String source) { + Toolkit tk = Toolkit.getDefaultToolkit(); + return tk.getImage(source); + } +} diff --git a/src/main/java/irc/AboutDialog.java b/src/main/java/irc/AboutDialog.java new file mode 100644 index 0000000..e184090 --- /dev/null +++ b/src/main/java/irc/AboutDialog.java @@ -0,0 +1,115 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +import java.awt.BorderLayout; +import java.awt.Font; +import java.awt.Frame; +import java.awt.GridLayout; +import java.awt.Label; +import java.awt.Panel; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +/** + * The about dialog. + */ +public class AboutDialog extends WindowAdapter { + private Frame _aboutFrame; + + /** + * Open and display the about dialog, using the given IRCConfiguration. + * + * @param config + * the IRCConfiguration. + */ + public AboutDialog(IRCConfiguration config) { + displayAboutPage(config); + } + + private Label createLabel(String text) { + Label b = new Label(text, Label.CENTER); + b.setFont(new Font("", Font.PLAIN, 12)); + return b; + } + + private void displayAboutPage(IRCConfiguration config) { + if (_aboutFrame != null) + return; + _aboutFrame = new Frame(); + _aboutFrame.setTitle(config.getText(IRCTextProvider.ABOUT_ABOUT)); + _aboutFrame.setLayout(new BorderLayout()); + _aboutFrame.setFont(new Font("", Font.PLAIN, 12)); + + Panel text = new Panel(); + + text.setLayout(new GridLayout(20, 1)); + text.add(createLabel("PJIRC v" + config.getVersion())); + text.add(new Panel()); + text.add(createLabel(config.getText(IRCTextProvider.ABOUT_GPL))); + text.add(new Panel()); + text.add(createLabel(config.getText(IRCTextProvider.ABOUT_PROGRAMMING) + + " : Philippe Detournay alias Plouf (theplouf@yahoo.com)")); + text.add(createLabel(config.getText(IRCTextProvider.ABOUT_DESIGN) + + " : Raphael Seegmuller chez pixxservices.com (pixxservices@pixxservices.com)")); + text.add(new Panel()); + text.add(createLabel(config.getText(IRCTextProvider.ABOUT_THANKS))); + text.add(new Panel()); + text.add(createLabel("Mandragor : www.mandragor.org")); + text.add(createLabel("Diboo : www.diboo.net")); + text.add(createLabel("Kombat Falcon.be Jerarckill Red Spider")); + text.add(createLabel("Ezequiel Jiquera")); + text.add(new Panel()); + text.add(createLabel(config.getText(IRCTextProvider.ABOUT_SUPPORT))); + text.add(new Panel()); + text.add(createLabel(config.getGUIInfoString())); + text.add(new Panel()); + text.add(createLabel("http://www.pjirc.com")); + text.add(createLabel("http://www.pjirc.it")); + _aboutFrame.addWindowListener(this); + _aboutFrame.add(text, BorderLayout.CENTER); + + _aboutFrame.setSize(500, 300); + _aboutFrame.setResizable(false); + _aboutFrame.show(); + } + + @Override + public void windowClosed(WindowEvent e) { + _aboutFrame.removeWindowListener(this); + _aboutFrame = null; + } + + @Override + public void windowClosing(WindowEvent e) { + _aboutFrame.hide(); + _aboutFrame.dispose(); + } +} diff --git a/src/main/java/irc/AppletFileHandler.java b/src/main/java/irc/AppletFileHandler.java new file mode 100644 index 0000000..31bc07c --- /dev/null +++ b/src/main/java/irc/AppletFileHandler.java @@ -0,0 +1,61 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +import java.applet.Applet; +import java.io.InputStream; +import java.net.URL; + +/** + * File handling from applet. + */ +public class AppletFileHandler implements FileHandler { + private Applet _app; + + /** + * Create a new AppletFileHandler, using the given Applet. + * + * @param app + * the applet to use. + */ + public AppletFileHandler(Applet app) { + _app = app; + } + + @Override + public InputStream getInputStream(String fileName) { + try { + URL url = new URL(_app.getCodeBase(), fileName); + return url.openStream(); + } catch (Exception ex) { + return null; + } + } +} diff --git a/src/main/java/irc/AppletImageLoader.java b/src/main/java/irc/AppletImageLoader.java new file mode 100644 index 0000000..c2daa58 --- /dev/null +++ b/src/main/java/irc/AppletImageLoader.java @@ -0,0 +1,61 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +import java.applet.Applet; +import java.awt.Image; +import java.net.MalformedURLException; +import java.net.URL; + +/** + * Image loading via applet. + */ +public class AppletImageLoader implements ImageLoader { + private Applet _app; + + /** + * Create a new AppletImageLoader using the given applet. + * + * @param app + * the applet to use. + */ + public AppletImageLoader(Applet app) { + _app = app; + } + + @Override + public Image getImage(String source) { + try { + return _app.getImage(new URL(_app.getCodeBase(), source)); + } catch (MalformedURLException ex) { + return null; + } + } +} diff --git a/src/main/java/irc/AppletSoundHandler.java b/src/main/java/irc/AppletSoundHandler.java new file mode 100644 index 0000000..2cc9eac --- /dev/null +++ b/src/main/java/irc/AppletSoundHandler.java @@ -0,0 +1,57 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +import java.applet.Applet; +import java.applet.AudioClip; + +/** + * Sound handling via applet. + */ +public class AppletSoundHandler implements SoundHandler { + private Applet _applet; + + /** + * Create a new AppletSoundHandler, using the given Applet. + * + * @param applet + * the applet to use. + */ + public AppletSoundHandler(Applet applet) { + _applet = applet; + } + + @Override + public void playSound(String name) { + AudioClip clip = _applet.getAudioClip(_applet.getCodeBase(), name); + clip.play(); + } + +} diff --git a/src/main/java/irc/AppletURLHandler.java b/src/main/java/irc/AppletURLHandler.java new file mode 100644 index 0000000..c68e88f --- /dev/null +++ b/src/main/java/irc/AppletURLHandler.java @@ -0,0 +1,93 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2005 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +import java.applet.AppletContext; +import java.net.MalformedURLException; +import java.net.URL; + +/** + * URL handling via applet. + */ +public class AppletURLHandler implements URLHandler { + + private AppletContext _ctx; + + /** + * Create a new AppletURLHandler using the given AppletContext. + * + * @param ctx + * the applet context to use. + */ + public AppletURLHandler(AppletContext ctx) { + _ctx = ctx; + } + + private String replace(String on, String what, String with) { + int pos = on.indexOf(what); + while (pos >= 0) { + String before = on.substring(0, pos); + String after = on.substring(pos + what.length()); + on = before + with + after; + pos = on.indexOf(what); + } + return on; + } + + private URL decodeURL(String u) throws MalformedURLException { + if (u.indexOf("://") == -1) + u = "http://" + u; + replace(u, " ", "%20"); + return new URL(u); + } + + @Override + public void stateURL(String url) { + try { + _ctx.showStatus(decodeURL(url).toString()); + } catch (Exception e) { + throw new RuntimeException(e.toString()); + } + } + + @Override + public void openURL(String url) { + openURL(url, "_blank"); + } + + @Override + public void openURL(String url, String target) { + try { + _ctx.showDocument(decodeURL(url), target); + } catch (Exception e) { + throw new RuntimeException(e.toString()); + } + } +} diff --git a/src/main/java/irc/AudioConfiguration.java b/src/main/java/irc/AudioConfiguration.java new file mode 100644 index 0000000..a406969 --- /dev/null +++ b/src/main/java/irc/AudioConfiguration.java @@ -0,0 +1,136 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +import java.util.Enumeration; +import java.util.Hashtable; + +/** + * Audio configuration class. + */ +public class AudioConfiguration { + private SoundHandler _sound; + + private String _query; + private String _beep; + private Hashtable _word; + + /** + * Create a new AudioConfiguration, using the given SoundHandler. + * + * @param sound + * the SoundHandler to use. + */ + public AudioConfiguration(SoundHandler sound) { + _sound = sound; + _query = null; + _beep = null; + _word = new Hashtable(); + } + + /** + * Play the given sound. + * + * @param snd + * the sound to be played. + */ + public void play(String snd) { + _sound.playSound(snd); + } + + /** + * Set the query sound. + * + * @param snd + * sound name. + */ + public void setQuery(String snd) { + _query = snd; + } + + /** + * Set the beep sound. + * + * @param snd + * sound name. + */ + public void setBeep(String snd) { + _beep = snd; + } + + /** + * Set the word sound. + * + * @param word + * the word. + * @param snd + * the sound to play for the given word. + */ + public void setWord(String word, String snd) { + _word.put(word, snd); + } + + /** + * Play the sound associated with the new query. + */ + public void onQuery() { + if (_query != null) + _sound.playSound(_query); + } + + /** + * Play the beep sound. + */ + public void beep() { + if (_beep != null) + _sound.playSound(_beep); + } + + /** + * Play the word sound. + * + * @param word + * word sound to play. + */ + public void onWord(String word) { + String snd = (String) _word.get(word); + if (snd != null) + _sound.playSound(snd); + } + + /** + * Get an enumeration of all know sound words. + * + * @return an enumeration of string. + */ + public Enumeration getSoundWords() { + return _word.keys(); + } +} diff --git a/src/main/java/irc/BasicInterpretor.java b/src/main/java/irc/BasicInterpretor.java new file mode 100644 index 0000000..5cf7f37 --- /dev/null +++ b/src/main/java/irc/BasicInterpretor.java @@ -0,0 +1,156 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2005 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +import java.util.Enumeration; + +/** + * Basic interpretor. + */ +public class BasicInterpretor extends RootInterpretor implements Interpretor { + /** + * Create a new BasicInterpretor without default interpretor. + * + * @param config + * the configuration. + */ + public BasicInterpretor(IRCConfiguration config) { + this(config, null); + } + + /** + * Create a new BasicInterpretor. + * + * @param config + * the configuration. + * @param next + * next interpretor to be used if the command is unknown. If null, + * the command will be sent as it to the server. + */ + public BasicInterpretor(IRCConfiguration config, Interpretor next) { + super(config, next); + } + + /** + * Handle the received command. + * + * @param source + * the source that emitted the command. + * @param cmd + * the hole command line. + * @param parts + * the parsed command line. + * @param cumul + * the cumul parsed command line. + */ + @Override + protected void handleCommand(Source source, String cmd, String[] parts, String[] cumul) { + try { + Server server = source.getServer(); + if (cmd.equals("echo")) { + test(cmd, parts, 1); + source.report(cumul[1]); + } else if (cmd.equals("sleep")) { + test(cmd, parts, 1); + try { + int ms = (new Integer(parts[1])).intValue(); + Thread.sleep(ms); + } catch (Exception ex) { + // Invalid integer or interrupted, ignore it... + } + } else if (cmd.equals("me")) { + test(cmd, parts, 1); + sendString(source, "/ctcp action " + cumul[1]); + } else if (cmd.equals("beep")) { + _ircConfiguration.getAudioConfiguration().beep(); + } else if (cmd.equals("play")) { + test(cmd, parts, 1); + _ircConfiguration.getAudioConfiguration().play(parts[1]); + } else if (cmd.equals("sound")) { + test(cmd, parts, 1); + if (source.talkable()) { + sendString(source, "/ctcp sound " + cumul[1]); + sendString(source, "/play " + cumul[1]); + } else { + source.report(getText(IRCTextProvider.INTERPRETOR_NOT_ON_CHANNEL)); + } + } else if (cmd.equals("url")) { + test(cmd, parts, 1); + if (parts.length >= 3) + _ircConfiguration.getURLHandler().openURL(parts[1], parts[2]); + else + _ircConfiguration.getURLHandler().openURL(parts[1]); + } else if (cmd.equals("clear")) { + source.clear(); + } else if (cmd.equals("leave")) { + source.leave(); + } else if (cmd.equals("msg")) { + test(cmd, parts, 2); + boolean said = false; + Enumeration e = server.getSources(); + while (e.hasMoreElements()) { + Source s = (Source) e.nextElement(); + if (s.getName().equals(parts[1])) { + say(s, cumul[2]); + said = true; + } + } + if (!said) + server.say(parts[1], cumul[2]); + } else if (cmd.equals("ping")) { + test(cmd, parts, 1); + sendString(source, "/ctcp ping " + cumul[1]); + } else if (cmd.equals("dcc")) { + test(cmd, parts, 1); + sendString(source, "/ctcp dcc " + cumul[1]); + } else if (cmd.equals("raw")) { + server.execute(cumul[1]); + } else if (cmd.equals("version")) { + source.report("PJIRC v" + _ircConfiguration.getVersion()); + } else if (cmd.equals("gc")) { + System.gc(); + source.report(Runtime.getRuntime().freeMemory() + " " + Runtime.getRuntime().totalMemory()); + } else if (cmd.equals("onserver")) { + test(cmd, parts, 2); + String s = parts[1]; + if (s.equals(server.getServerName())) { + if ((cumul[2].startsWith("/")) && (server instanceof IRCServer)) + ((IRCServer) server).getStatus().sendString(cumul[2]); + else + server.execute(cumul[2]); + } + } else { + super.handleCommand(source, cmd, parts, cumul); + } + } catch (NotEnoughParametersException ex) { + source.report(getText(IRCTextProvider.INTERPRETOR_INSUFFICIENT_PARAMETERS, ex.getMessage())); + } + } +} diff --git a/src/main/java/irc/CTCPInterpretor.java b/src/main/java/irc/CTCPInterpretor.java new file mode 100644 index 0000000..f6a1371 --- /dev/null +++ b/src/main/java/irc/CTCPInterpretor.java @@ -0,0 +1,160 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2005 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +import irc.dcc.prv.DCCChatServer; +import irc.dcc.prv.DCCFileHandler; + +import java.io.File; +import java.util.Date; + +/** + * The CTCP interpretor. + */ +public class CTCPInterpretor extends BasicInterpretor { + /** + * The CTCPFilter. + */ + // protected CTCPFilter _filter; + protected ServerManager _mgr; + + /** + * Create a new CTCPInterpretor. + * + * @param config + * global configuration. + * @param next + * next interpretor to use if command is unknown. + * @param mgr + * server manager + */ + public CTCPInterpretor(IRCConfiguration config, Interpretor next/* + * ,CTCPFilter + * filter + */, ServerManager mgr) { + super(config, next); + _mgr = mgr; + // _filter=filter; + } + + private void send(Server s, String destination, String msg) { + s.say(destination, "\1" + msg + "\1"); + } + + @Override + protected void handleCommand(Source source, String cmd, String[] parts, String[] cumul) { + try { + if (cmd.equals("ctcp")) { + test(cmd, parts, 1); + if (parts[1].toLowerCase(java.util.Locale.ENGLISH).equals("ping")) { + test(cmd, parts, 2); + send(source.getServer(), parts[2], "PING " + (new Date()).getTime()); + // _filter.ping(source.getServer(),parts[2]); + } else if (parts[1].toLowerCase(java.util.Locale.ENGLISH).equals("action")) { + test(cmd, parts, 2); + if (source.talkable()) { + send(source.getServer(), source.getName(), "ACTION " + cumul[2]); + // _filter.action(source.getServer(),source.getName(),cumul[2]); + source.action(source.getServer().getNick(), cumul[2]); + } else { + source.report(getText(IRCTextProvider.INTERPRETOR_NOT_ON_CHANNEL)); + } + } else if (parts[1].toLowerCase(java.util.Locale.ENGLISH).equals("dcc")) { + test(cmd, parts, 2); + if (parts[2].toLowerCase(java.util.Locale.ENGLISH).equals("chat") && _ircConfiguration.getB("allowdccchat")) { + test(cmd, parts, 3); + // _filter.chat(source.getServer(),parts[3]); + Server s = source.getServer(); + String nick = parts[3]; + try { + DCCChatServer cserver = new DCCChatServer(_ircConfiguration, s.getNick(), nick); + String arg = cserver.openPassive(); + if (arg.length() == 0) { + cserver.sendStatusMessage(getText(IRCTextProvider.DCC_UNABLE_PASSIVE_MODE)); + } else { + send(s, nick, "DCC CHAT chat " + arg); + } + _mgr.newServer(cserver, false); + } catch (Throwable ex) { + _ircConfiguration.internalError("dcc chat error", ex, "plouf@pjirc.com"); + } + + } else if (parts[2].toLowerCase(java.util.Locale.ENGLISH).equals("send") + && _ircConfiguration.getB("allowdccfile")) { + String file = null; + test(cmd, parts, 3); + + if (parts.length > 4) + file = cumul[4]; + + Server s = source.getServer(); + String nick = parts[3]; + try { + File f; + if (file != null) + f = new File(file); + else + f = _ircConfiguration.getSecurityProvider().getLoadFile("Send file"); + + DCCFileHandler handler = new DCCFileHandler(_ircConfiguration, nick, f); + char guil = 34; + String filename = f.getName(); + if (filename.indexOf(" ") != -1) + filename = guil + filename + guil; + String arg = filename + " " + handler.send(); + send(s, nick, "DCC SEND " + arg); + _mgr.newServer(handler, false); + + } catch (Throwable ex) { + _ircConfiguration.internalError("dcc send error", ex, "plouf@pjirc.com"); + } + } else { + source.report(getText(IRCTextProvider.INTERPRETOR_UNKNOWN_DCC, parts[2])); + } + } else if (parts[1].toLowerCase(java.util.Locale.ENGLISH).equals("raw")) { + test(cmd, parts, 3); + send(source.getServer(), parts[2], cumul[3]); + // _filter.genericSend(source.getServer(),parts[2],cumul[3]); + } else if (parts[1].toLowerCase(java.util.Locale.ENGLISH).equals("sound")) { + test(cmd, parts, 2); + send(source.getServer(), source.getName(), "SOUND " + parts[2]); + } else { + test(cmd, parts, 2); + send(source.getServer(), parts[2], parts[1]); + // _filter.genericSend(source.getServer(),parts[2],parts[1]); + } + } else { + super.handleCommand(source, cmd, parts, cumul); + } + } catch (NotEnoughParametersException ex) { + source.report(getText(IRCTextProvider.INTERPRETOR_INSUFFICIENT_PARAMETERS, ex.getMessage())); + } + } +} diff --git a/src/main/java/irc/ChanList.java b/src/main/java/irc/ChanList.java new file mode 100644 index 0000000..fbef0d4 --- /dev/null +++ b/src/main/java/irc/ChanList.java @@ -0,0 +1,181 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +import java.util.Vector; + +/** + * A channel list handler. + */ +public class ChanList extends IRCSource { + private ListenerGroup _listeners; + private Vector _channels; + private String _name; + private boolean _running; + private int _ignored; + + /** + * Create a new ChanList. + * + * @param config + * the global configuration. + * @param server + * the IRCServer from where to retreive channel list. + * @param name + * the chanlist name. + */ + public ChanList(IRCConfiguration config, IRCServer server, String name) { + super(config, server); + _name = name; + _server = server; + _listeners = new ListenerGroup(); + _channels = new Vector(); + _running = false; + } + + @Override + public String getType() { + return "ChanList"; + } + + /** + * Get the chanlist name. + * + * @return the chanlist name. + */ + @Override + public String getName() { + return _name; + } + + /** + * Get the channels. + * + * @return array of all channels. + */ + public ChannelInfo[] getChannels() { + ChannelInfo[] ans = new ChannelInfo[_channels.size()]; + for (int i = 0; i < _channels.size(); i++) + ans[i] = (ChannelInfo) _channels.elementAt(i); + return ans; + } + + /** + * Get the channel count. + * + * @return the number of channels. + */ + public int getChannelCount() { + return _channels.size(); + } + + /** + * Get the ignored channel count. + * + * @return the number of channels that have been ignored. + */ + public int getIgnoredChannelCount() { + return _ignored; + } + + /** + * Add a channel in the channel list. + * + * @param nfo + * new channel to add. + */ + public void addChannel(ChannelInfo nfo) { + if (_channels.size() > 1024 && nfo.userCount < 5) { + _ignored++; + return; + } + _channels.insertElementAt(nfo, _channels.size()); + _listeners.sendEvent("channelAdded", nfo, this); + } + + /** + * Begin a new channel listing. The channel list is cleared. + */ + public void begin() { + _ignored = 0; + _running = true; + _channels = new Vector(); + _listeners.sendEvent("channelBegin", this); + } + + /** + * End the channel listing. + */ + public void end() { + _running = false; + _listeners.sendEvent("channelEnd", this); + } + + /** + * Add a ChanListListener. + * + * @param lis + * listener to add. + */ + public void addChanListListener(ChanListListener lis) { + _listeners.addListener(lis); + } + + /** + * Remove a chanListListener. + * + * @param lis + * listener to remove. + */ + public void removeChanListListeners(ChanListListener lis) { + _listeners.removeListener(lis); + } + + /** + * Request the destruction of this chanlist. + */ + @Override + public void leave() { + if (_running) + return; + getIRCServer().leaveChanList(_name); + } + + @Override + public boolean talkable() { + return false; + } + + @Override + public boolean mayDefault() { + return false; + } + +} diff --git a/src/main/java/irc/ChanListListener.java b/src/main/java/irc/ChanListListener.java new file mode 100644 index 0000000..475cca5 --- /dev/null +++ b/src/main/java/irc/ChanListListener.java @@ -0,0 +1,61 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +/** + * Channel list listener. + */ +public interface ChanListListener { + /** + * A new channel has been added in the channel list. + * + * @param item + * the newly added item. + * @param list + * the channel list. + */ + public void channelAdded(ChannelInfo item, ChanList list); + + /** + * A new listing has began. + * + * @param list + * the channel list. + */ + public void channelBegin(ChanList list); + + /** + * The current listing is terminated. + * + * @param list + * the channel list. + */ + public void channelEnd(ChanList list); +} diff --git a/src/main/java/irc/Channel.java b/src/main/java/irc/Channel.java new file mode 100644 index 0000000..f4ea49f --- /dev/null +++ b/src/main/java/irc/Channel.java @@ -0,0 +1,405 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +import java.util.Enumeration; +import java.util.Hashtable; + +/** + * Nickname. + */ +class Nick { + /** + * Create a new Nick + * + * @param n + * nickname. + * @param m + * mode. + * @param modes + * all modes. + * @param prefix + * all prefixes. + */ + public Nick(String n, String m, char[][] modes, char[] prefix) { + Name = n; + Mode = new ModeHandler(m, modes, prefix); + Whois = ""; + } + + /** + * Nickname. + */ + public String Name; + /** + * Whois information. + */ + public String Whois; + /** + * Nickname mode. + */ + public ModeHandler Mode; +} + +/** + * A channel source. + */ +public class Channel extends IRCSource implements ReplyServerListener { + private String _name; + private String _topic; + private ModeHandler _mode; + private ListenerGroup _listeners; + private Hashtable _nicks; + + /** + * Create a new Channel. + * + * @param config + * the global configuration. + * @param name + * channel name. + * @param s + * the source server. + */ + public Channel(IRCConfiguration config, String name, IRCServer s) { + super(config, s); + _name = name; + _topic = ""; + _mode = new ModeHandler(s.getChannelModes(), s.getNickModes()); + _listeners = new ListenerGroup(); + _nicks = new Hashtable(); + s.addReplyServerListener(this); + if (_ircConfiguration.getASLMaster()) + getIRCServer().execute("WHO " + _name); + setInterpretor(new ChannelInterpretor(config)); + } + + @Override + public void release() { + ((IRCServer) _server).removeReplyServerListener(this); + super.release(); + } + + /** + * Add a channel listener. + * + * @param lis + * listener to add. + * @deprecated use addChannelListener2 instead. + */ + @Deprecated + public void addChannelListener(ChannelListener lis) { + _listeners.addListener(lis); + } + + /** + * Remove a channel listener. + * + * @param lis + * listener to remove. + * @deprecated use removeChannelListener2 instead. + */ + @Deprecated + public void removeChannelListener(ChannelListener lis) { + _listeners.removeListener(lis); + } + + /** + * Add a channel listener. + * + * @param lis + * listener to add. + */ + public void addChannelListener2(ChannelListener2 lis) { + _listeners.addListener(lis); + } + + /** + * Remove a channel listener. + * + * @param lis + * listener to remove. + */ + public void removeChannelListener2(ChannelListener2 lis) { + _listeners.removeListener(lis); + } + + @Override + public String getType() { + return "Channel"; + } + + @Override + public String getName() { + return _name; + } + + @Override + public boolean talkable() { + return true; + } + + @Override + public void leave() { + getIRCServer().leaveChannel(getName()); + } + + /** + * Test wether this channel has the given nickname. + * + * @param nick + * nickname to test. + * @return true if nick is present on this channel, false otherwise. + */ + public boolean hasNick(String nick) { + return _nicks.get(nick.toLowerCase(java.util.Locale.ENGLISH)) != null; + } + + /** + * Notify this channel the given nick has joined, with the given options. + * + * @param nick + * new nick. + * @param mode + * nick mode. + */ + public void joinNick(String nick, String mode) { + _nicks.put(nick.toLowerCase(java.util.Locale.ENGLISH), new Nick(nick, mode, getIRCServer().getChannelModes(), + getIRCServer().getNickModes())); + if (_ircConfiguration.getASLMaster()) + getIRCServer().execute("WHO " + nick); + _listeners.sendEvent("nickJoin", nick, mode, this); + } + + /** + * Notify this channel it should reset its nick list. + */ + public void resetNicks() { + _nicks.clear(); + _listeners.sendEvent("nickReset", this); + } + + /** + * Notify this channel it should change its hole nick list. + * + * @param nicks + * new nicks. + * @param modes + * new modes. There is a one to one mapping between nicks and modes. + */ + public void setNicks(String[] nicks, String[] modes) { + for (int i = 0; i < nicks.length; i++) + _nicks.put(nicks[i].toLowerCase(java.util.Locale.ENGLISH), new Nick(nicks[i], modes[i], getIRCServer() + .getChannelModes(), getIRCServer().getNickModes())); + _listeners.sendEvent("nickSet", nicks, modes, this); + } + + /** + * Notify this channel the given nick has left the channel. + * + * @param nick + * the nick. + * @param reason + * the reason. + */ + public void partNick(String nick, String reason) { + _nicks.remove(nick.toLowerCase(java.util.Locale.ENGLISH)); + _listeners.sendEvent("nickPart", nick, reason, this); + } + + /** + * Notify this channel the given nick has been kicked. + * + * @param nick + * the kicked nick. + * @param by + * the nick who kicked nick. + * @param reason + * the kick reason. + */ + public void kickNick(String nick, String by, String reason) { + _nicks.remove(nick.toLowerCase(java.util.Locale.ENGLISH)); + _listeners.sendEvent("nickKick", new Object[] { nick, by, reason, this }); + } + + /** + * Notify this channel the given nick has quit. + * + * @param nick + * the nick who quit. + * @param reason + * reason. + */ + public void quitNick(String nick, String reason) { + _nicks.remove(nick.toLowerCase(java.util.Locale.ENGLISH)); + _listeners.sendEvent("nickQuit", nick, reason, this); + } + + /** + * Get all the nicks in this channel. + * + * @return array of all nick names. + */ + public String[] getNicks() { + String[] ans = new String[_nicks.size()]; + Enumeration e = _nicks.elements(); + int i = 0; + while (e.hasMoreElements()) + ans[i++] = ((Nick) e.nextElement()).Name; + return ans; + } + + /** + * Get the nick mode associated with the given nick. + * + * @param nick + * nickname to get mode. + * @return nick mode or null if nick not found. + */ + public String getNickMode(String nick) { + Nick n = (Nick) _nicks.get(nick.toLowerCase(java.util.Locale.ENGLISH)); + if (n == null) + return null; + return n.Mode.getMode(); + } + + /** + * Notify this channel its topic has changed. + * + * @param topic + * new topic. + * @param by + * nickname who changed topic. + */ + public void setTopic(String topic, String by) { + _topic = topic; + _listeners.sendEvent("topicChanged", topic, by, this); + } + + /** + * Notify this channel a nick mode has changed. + * + * @param nick + * the nick. + * @param mode + * the applied mode. + * @param from + * the nick who changed mode. + */ + public void applyUserMode(String nick, String mode, String from) { + Nick n = (Nick) _nicks.get(nick.toLowerCase(java.util.Locale.ENGLISH)); + if (n != null) + n.Mode.apply(mode); + _listeners.sendEvent("nickModeApply", new Object[] { nick, mode, from, this }); + } + + /** + * Notify this channel its mode has changed. + * + * @param mode + * applied mode. + * @param from + * user who changed mode. + */ + public void applyMode(String mode, String from) { + _mode.apply(mode); + _listeners.sendEvent("modeApply", mode, from, this); + } + + /** + * Get this channel mode. + * + * @return channel mode. + */ + public String getMode() { + return _mode.getMode(); + } + + /** + * Get this channel topic. + * + * @return channel topic. + */ + public String getTopic() { + return _topic; + } + + /** + * Notify this channel a nick has been renamed. + * + * @param oldNick + * old nickname. + * @param newNick + * new nickname. + */ + public void changeNick(String oldNick, String newNick) { + Nick n = (Nick) _nicks.get(oldNick.toLowerCase(java.util.Locale.ENGLISH)); + _nicks.remove(oldNick.toLowerCase(java.util.Locale.ENGLISH)); + n.Name = newNick; + _nicks.put(newNick.toLowerCase(java.util.Locale.ENGLISH), n); + + _listeners.sendEvent("nickChanged", oldNick, newNick, this); + } + + private void learn(String nick, String whois) { + Nick n = (Nick) _nicks.get(nick.toLowerCase(java.util.Locale.ENGLISH)); + if (n == null) + return; + n.Whois = whois; + _listeners.sendEvent("nickWhoisUpdated", nick, whois, this); + } + + /** + * Get bufferised whois data for the given nick. + * + * @param nick + * nickname. + * @return whois data for nick, or "" if not found. + */ + public String whois(String nick) { + Nick n = (Nick) _nicks.get(nick.toLowerCase(java.util.Locale.ENGLISH)); + if (n == null) + return ""; + return n.Whois; + } + + @Override + public Boolean replyReceived(String prefix, String id, String params[], IRCServer server) { + if (id.equals("352")) { + String name = params[params.length - 1]; + int pos = name.indexOf(" "); + if (pos != -1) + name = name.substring(pos + 1); + String nick = params[5]; + learn(nick, name); + } + return Boolean.FALSE; + } +} diff --git a/src/main/java/irc/ChannelInfo.java b/src/main/java/irc/ChannelInfo.java new file mode 100644 index 0000000..370021f --- /dev/null +++ b/src/main/java/irc/ChannelInfo.java @@ -0,0 +1,64 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +/** + * Channel information. + */ +public class ChannelInfo { + /** + * Create a new ChannelInfo. + * + * @param n + * channel name. + * @param t + * channel topic. + * @param c + * user count. + */ + public ChannelInfo(String n, String t, int c) { + name = n; + topic = t; + userCount = c; + } + + /** + * Channel name. + */ + public String name; + /** + * Channel topic. + */ + public String topic; + /** + * User count. + */ + public int userCount; +} diff --git a/src/main/java/irc/ChannelInterpretor.java b/src/main/java/irc/ChannelInterpretor.java new file mode 100644 index 0000000..553be2f --- /dev/null +++ b/src/main/java/irc/ChannelInterpretor.java @@ -0,0 +1,88 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +/** + * Channel interpretor. + */ +public class ChannelInterpretor extends IRCInterpretor { + /** + * Create a new ChannelInterpretor. + * + * @param config + * global configuration. + */ + public ChannelInterpretor(IRCConfiguration config) { + super(config); + } + + private boolean isChannel(String name, Source source) { + if (name.length() == 0) + return false; + Server s = source.getServer(); + if (s instanceof IRCServer) { + char[] prefixes = ((IRCServer) s).getChannelPrefixes(); + for (int i = 0; i < prefixes.length; i++) + if (name.charAt(0) == prefixes[i]) + return true; + } + return false; + } + + @Override + protected void handleCommand(Source source, String cmd, String[] parts, String[] cumul) { + try { + if (cmd.equals("part")) { + if (parts.length == 1) { + sendString(source, "/part " + source.getName()); + } else { + if (isChannel(parts[1], source)) + super.handleCommand(source, cmd, parts, cumul); + else + sendString(source, "/part " + source.getName() + " " + cumul[1]); + } + } else if (cmd.equals("hop")) { + sendString(source, "/part"); + sendString(source, "/join " + source.getName()); + } else if (cmd.equals("onotice")) { + test(cmd, parts, 1); + if (isChannel(parts[1], source)) + super.handleCommand(source, cmd, parts, cumul); + else + sendString(source, "/onotice " + source.getName() + " " + cumul[1]); + } else { + super.handleCommand(source, cmd, parts, cumul); + } + } catch (NotEnoughParametersException ex) { + source.report(getText(IRCTextProvider.INTERPRETOR_INSUFFICIENT_PARAMETERS, ex.getMessage())); + } + + } +} diff --git a/src/main/java/irc/ChannelListener.java b/src/main/java/irc/ChannelListener.java new file mode 100644 index 0000000..221fd61 --- /dev/null +++ b/src/main/java/irc/ChannelListener.java @@ -0,0 +1,159 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +/** + * Channel listener. Use ChannelListener2 instead. + */ +public interface ChannelListener extends SourceListener { + /** + * The channel has changed all its nick list. + * + * @param nicks + * new nicks. + * @param modes + * new modes. + * @param channel + * the channel. + */ + public void nickSet(String nicks[], String modes[], Channel channel); + + /** + * A new nick has joined. + * + * @param nick + * the nick who joined. + * @param mode + * nick mode. + * @param channel + * the channel. + */ + public void nickJoin(String nick, String mode, Channel channel); + + /** + * A nick has quit. + * + * @param nick + * the nick who quit. + * @param reason + * reason. + * @param channel + * the channel. + */ + public void nickQuit(String nick, String reason, Channel channel); + + /** + * A nick has part. + * + * @param nick + * the nick who part. + * @param reason + * reason. + * @param channel + * the channel. + */ + public void nickPart(String nick, String reason, Channel channel); + + /** + * A nick has been kicked. + * + * @param nick + * the nick who has been kicked. + * @param by + * the nick who kicked. + * @param reason + * kick reason. + * @param channel + * the channel. + */ + public void nickKick(String nick, String by, String reason, Channel channel); + + /** + * The topic has been changed. + * + * @param topic + * new topic. + * @param by + * user who changed topic. + * @param channel + * the channel. + */ + public void topicChanged(String topic, String by, Channel channel); + + /** + * Channel mode applied. + * + * @param mode + * applied mode. + * @param from + * user who applied mode. + * @param channel + * the channel. + */ + public void modeApply(String mode, String from, Channel channel); + + /** + * Nick mode applied. + * + * @param nick + * user on wich mode applied. + * @param mode + * applied mode. + * @param from + * user who applied mode. + * @param channel + * the channel. + */ + public void nickModeApply(String nick, String mode, String from, Channel channel); + + /** + * Nick changed. + * + * @param oldNick + * old nick. + * @param newNick + * new nick. + * @param channel + * the channel. + */ + public void nickChanged(String oldNick, String newNick, Channel channel); + + /** + * Whois bufferised information has been updated. + * + * @param nick + * nick on wich new whois information is available. + * @param whois + * whois string for nick. + * @param channel + * the channel. + */ + public void nickWhoisUpdated(String nick, String whois, Channel channel); +} diff --git a/src/main/java/irc/ChannelListener2.java b/src/main/java/irc/ChannelListener2.java new file mode 100644 index 0000000..43459bf --- /dev/null +++ b/src/main/java/irc/ChannelListener2.java @@ -0,0 +1,43 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2005 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +/** + * New channel listener interface. To be used instead of ChannelListener. + */ +public interface ChannelListener2 extends ChannelListener { + /** + * The channel should empty its nick list. + * + * @param channel + * the channel. + */ + public void nickReset(Channel channel); +} diff --git a/src/main/java/irc/CodingHandler.java b/src/main/java/irc/CodingHandler.java new file mode 100644 index 0000000..fc347cc --- /dev/null +++ b/src/main/java/irc/CodingHandler.java @@ -0,0 +1,386 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; + +/** + * MyPushbackStream, because of a bug in JDK1.1. + */ +class MyPushbackStream extends InputStream { + private InputStream _is; + private int _back; + private boolean _closed; + + /** + * Create a new MyPushbackStream + * + * @param is + * source input stream. + */ + public MyPushbackStream(InputStream is) { + _is = is; + _back = -1; + _closed = false; + } + + @Override + public void close() throws IOException { + _is.close(); + _back = -1; + _closed = true; + } + + @Override + public int read() throws IOException { + if (_back != -1) { + int res = _back; + _back = -1; + return res; + } + return _is.read(); + } + + @Override + public int read(byte[] b) throws IOException { + return read(b, 0, b.length); + } + + @Override + public int read(byte[] b, int offset, int length) throws IOException { + if (length == 0) + return 0; + if (_back != -1) { + b[offset] = (byte) _back; + _back = -1; + return 1; + } + return _is.read(b, offset, length); + } + + @Override + public int available() throws IOException { + if (_back != -1) + return 1 + _is.available(); + return _is.available(); + } + + /** + * Unread the last read byte. + * + * @param b + * last read byte value. + */ + public void unread(byte b) { + if (_closed) + return; + _back = b; + } +} + +/** + * Coding handler for unicode to ascii transfert via socket streams. + */ +public class CodingHandler extends IRCObject { + private MyPushbackStream _is; + private OutputStream _os; + private BufferedReader _reader; + private BufferedWriter _writer; + private int _coding; + + /** + * ASCII coding. + */ + public static final int CODING_ASCII = 0; + /** + * PJIRC proprietary coding format. + */ + public static final int CODING_PUAP = 1; + /** + * UTF-8 coding. + */ + public static final int CODING_UTF_8 = 2; + /** + * Local charset coding. + */ + public static final int CODING_LOCAL_CHARSET = 3; + + /** + * Create a new Coding handler, using the given input and output stream. + * + * @param config + * IRCConfiguration objet. + * @param is + * inputstream for reading. + * @param os + * outputstream for writing. + */ + public CodingHandler(IRCConfiguration config, InputStream is, OutputStream os) { + super(config); + _coding = config.getI("coding"); + if (_coding != CODING_LOCAL_CHARSET) { + _is = new MyPushbackStream(is); + _os = os; + _reader = null; + _writer = null; + } else { + _is = null; + _os = null; + _reader = new BufferedReader(new InputStreamReader(is)); + _writer = new BufferedWriter(new OutputStreamWriter(os)); + } + } + + /** + * Close the handler, and associated streams. + * + * @throws IOException + */ + public void close() throws IOException { + if (_is != null) + _is.close(); + if (_os != null) + _os.close(); + if (_reader != null) + _reader.close(); + if (_writer != null) + _writer.close(); + _is = null; + _os = null; + _reader = null; + _writer = null; + } + + /** + * Read a single line from the input stream. + * + * @return the read line. + * @throws IOException + */ + public String read() throws IOException { + if (_coding != CODING_LOCAL_CHARSET) { + String ans = readUTF(); + return asciiToWide(ans); + } + return _reader.readLine(); + } + + /** + * Write a single line to the output stream. + * + * @param s + * the line to write. + * @throws IOException + */ + public void write(String s) throws IOException { + if (_coding == CODING_ASCII) + writeASCII(s); + else if (_coding == CODING_PUAP) + writePUAP(s); + else if (_coding == CODING_UTF_8) + writeUTF(s); + else if (_coding == CODING_LOCAL_CHARSET) + writeCHARSET(s); + else + writePUAP(s); + + if (_os != null) + _os.flush(); + if (_writer != null) + _writer.flush(); + } + + private void writeCHARSET(String s) throws IOException { + _writer.write(s, 0, s.length()); + _writer.newLine(); + } + + private void writeASCII(String s) throws IOException { + for (int i = 0; i < s.length(); i++) + _os.write((byte) s.charAt(i)); + _os.write(13); + _os.write(10); + } + + private void writePUAP(String s) throws IOException { + writeASCII(wideToAscii(s)); + } + + private String readUTF() throws IOException { + String ans = ""; + String nonUTFans = ""; + boolean utf = true; + int c; + char ch = 0; + int expect = 0; + boolean terminated = false; + while (!terminated) { + c = _is.read(); + if (((c == 10) || (c == 13)) && (nonUTFans.length() == 0)) + continue; + if (c == -1) { + if (nonUTFans.length() == 0) + throw new IOException("EOF reached"); + if (expect != 0) + utf = false; + if (utf) + return ans; + return nonUTFans; + } + + if ((c == 10) || (c == 13)) { + if (expect != 0) + utf = false; + if (_is.available() >= 1) + c = _is.read(); + if ((c != 10) && (c != 13)) + _is.unread((byte) c); + if (utf) + return ans; + return nonUTFans; + } + + nonUTFans += (char) c; + + if (!utf) + continue; + + if (c < 128) { + if (expect != 0) { + utf = false; + } else { + ans += (char) c; + } + } else if (c < 192) { + if (expect == 0) { + utf = false; + } else { + ch = (char) ((ch << 6) | ((c - 128) & 63)); + expect--; + if (expect == 0) { + ans += ch; + ch = 0; + } + } + } else if (c < 224) { + if (expect != 0) + utf = false; + else { + expect = 1; + ch = (char) (c - 192); + } + } else { + if (expect != 0) + utf = false; + else { + expect = 2; + ch = (char) (c - 224); + } + } + } + return null; + } + + private void writeUTF(String str) throws IOException { + for (int i = 0; i < str.length(); i++) { + char ch = str.charAt(i); + if (ch < 0x007F) + _os.write((byte) ch); + else if (ch < 0x07FF) { + _os.write((byte) (192 + (ch >> 6))); + _os.write((byte) (128 + (ch & 63))); + } else { + _os.write((byte) (224 + (ch >> 12))); + _os.write((byte) (128 + ((ch >> 6) & 63))); + _os.write((byte) (128 + (ch & 63))); + } + } + _os.write(10); + _os.write(13); + } + + /** + * Convert an ascii string to a wide string, as defined in the PJIRC unicode + * transfert protocol. + * + * @param str + * ascii string. + * @return wide string. + */ + private static String asciiToWide(String str) { + try { + String res = ""; + for (int i = 0; i < str.length(); i++) { + if (str.charAt(i) == (char) 30) { + String hex = str.substring(i + 1, i + 5); + i += 4; + int code = Integer.parseInt(hex, 16); + res += (char) code; + } else { + res += str.charAt(i); + } + } + return res; + } catch (Exception ex) { + return str; + } + } + + /** + * Convert a wide string to an ascii string, as defined in the PJIRC unicode + * transfert protocol. + * + * @param str + * wide string. + * @return ascii string. + */ + private static String wideToAscii(String str) { + String res = ""; + for (int i = 0; i < str.length(); i++) { + int c = str.charAt(i); + if (c > 255) { + res += (char) 30; + String v = Integer.toHexString(c); + while (v.length() < 4) + v = "0" + v; + res += v; + } else { + res += (char) c; + } + } + return res; + } +} diff --git a/src/main/java/irc/ConfigurationLoader.java b/src/main/java/irc/ConfigurationLoader.java new file mode 100644 index 0000000..77321ef --- /dev/null +++ b/src/main/java/irc/ConfigurationLoader.java @@ -0,0 +1,392 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2005 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +import java.awt.Color; +import java.awt.Font; +import java.util.StringTokenizer; +import java.util.Vector; + +/** + * A single server. + */ +class ServerItem { + /** + * Hostname. + */ + public String host; + /** + * Server post. + */ + public int port; + /** + * Optionnal server password. + */ + public String pass; +} + +/** + * Toolkit for Configuration creation. + */ +public class ConfigurationLoader { + private ParameterProvider _provider; + private URLHandler _handler; + private ImageLoader _loader; + private SoundHandler _sound; + private FileHandler _file; + + /** + * Create a new IRCConfigurationLoader. + * + * @param provider + * parameter provider to load the configuration from. + * @param handler + * URL handler. + * @param loader + * Image loader. + * @param sound + * Sound handler. + * @param file + * File handler. + */ + public ConfigurationLoader(ParameterProvider provider, URLHandler handler, ImageLoader loader, SoundHandler sound, + FileHandler file) { + _provider = provider; + _handler = handler; + _loader = loader; + _sound = sound; + _file = file; + } + + /** + * Create a new IRCConfiguration object, using the given ParameterProvider. + * + * @return a new IRCConfiguration instance. + * @throws Exception + * if an error occurs. + */ + public IRCConfiguration loadIRCConfiguration() throws Exception { + return getIRCConfiguration(); + } + + /** + * Create a new StartupConfiguration object, using the given + * ParameterProvider. + * + * @return a new StartupConfiguration instance. + * @throws Exception + * if a mandatory parameter is not supplied or if an error occurs. + */ + public StartupConfiguration loadStartupConfiguration() throws Exception { + return getStartupConfiguration(); + } + + private String getParameter(String key) { + return _provider.getParameter(key); + } + + private boolean getBoolean(String key, boolean def) { + String v = getParameter(key); + if (v == null) + return def; + v = v.toLowerCase(java.util.Locale.ENGLISH).trim(); + if (v.equals("true") || v.equals("on") || v.equals("1")) + return true; + return false; + } + + private String getString(String key, String def) { + String v = getParameter(key); + if (v == null) + return def; + return v; + } + + private int getInt(String key, int def) { + String v = getParameter(key); + if (v == null) + return def; + try { + return Integer.parseInt(v); + } catch (Exception e) { + return def; + } + + } + + private void readBackgroundConfig(IRCConfiguration config) { + StringParser parser = new StringParser(); + String[] arr = getArray("style:backgroundimage"); + for (int i = 0; i < arr.length; i++) { + String cmd = arr[i]; + String back[] = parser.parseString(cmd); + if (back.length >= 4) { + String type = back[0]; + String name = back[1]; + int tiling = new Integer(back[2]).intValue(); + String image = back[3]; + config.setBackgroundImage(type, name, image); + config.setBackgroundTiling(type, name, tiling); + } + } + } + + private TextProvider getTextProvider() { + String lang = getString("language", "english"); + String encoding = getString("languageencoding", ""); + String extension = getString("lngextension", "lng"); + String backlang = getString("backuplanguage", "english"); + String backencoding = getString("backuplanguageencoding", ""); + return new FileTextProvider(lang + "." + extension, encoding, backlang + "." + extension, backencoding, _file); + } + + private String[] getArray(String name) { + Vector v = new Vector(); + String cmd; + int i = 1; + do { + cmd = getParameter(name + i); + if (cmd != null) + v.insertElementAt(cmd, v.size()); + i++; + } while (cmd != null); + String[] ans = new String[v.size()]; + for (i = 0; i < v.size(); i++) + ans[i] = (String) v.elementAt(i); + return ans; + } + + private void readSmileys(IRCConfiguration config) { + String[] arr = getArray("style:smiley"); + for (int i = 0; i < arr.length; i++) { + String cmd = arr[i]; + int pos = cmd.indexOf(" "); + if (pos != -1) { + String match = cmd.substring(0, pos).trim(); + String file = cmd.substring(pos + 1).trim(); + config.addSmiley(match, file); + } + } + } + + private void configureFonts(IRCConfiguration config) { + // type name fname fsize + StringParser parser = new StringParser(); + String[] arr = getArray("style:sourcefontrule"); + for (int i = 0; i < arr.length; i++) { + String cmd = arr[i]; + String back[] = parser.parseString(cmd); + if (back.length >= 4) { + String type = back[0].toLowerCase(java.util.Locale.ENGLISH); + String name = back[1].toLowerCase(java.util.Locale.ENGLISH); + String fname = back[2].toLowerCase(java.util.Locale.ENGLISH); + + if (fname.startsWith("'") && fname.endsWith("'")) + fname = fname.substring(1, fname.length() - 1); + + int fsize = new Integer(back[3].toLowerCase(java.util.Locale.ENGLISH)).intValue(); + config.setFont(type, name, new Font(fname, Font.PLAIN, fsize)); + } + } + } + + private void configureTextColors(IRCConfiguration config) { + // type name {index=value}* + String[] arr = getArray("style:sourcecolorrule"); + for (int i = 0; i < arr.length; i++) { + StringTokenizer tok = new StringTokenizer(arr[i]); + if (!tok.hasMoreElements()) + continue; + String type = (String) tok.nextElement(); + if (!tok.hasMoreElements()) + continue; + String name = (String) tok.nextElement(); + Color[] c = new Color[16]; + config.loadDefaultColors(c); + while (tok.hasMoreElements()) { + String s = (String) tok.nextElement(); + int pos = s.indexOf('='); + if (pos < 0) + continue; + String before = s.substring(0, pos).trim(); + String after = s.substring(pos + 1).trim(); + int index = Integer.parseInt(before); + Color col = new Color(Integer.parseInt(after, 16)); + if ((index >= 0) && (index <= 15)) + c[index] = col; + } + config.setSourceColor(type, name, c); + } + } + + private void readSound(IRCConfiguration config) { + AudioConfiguration ac = config.getAudioConfiguration(); + if (getParameter("soundbeep") != null) + ac.setBeep(getParameter("soundbeep")); + if (getParameter("soundquery") != null) + ac.setQuery(getParameter("soundquery")); + String[] arr = getArray("soundword"); + for (int i = 0; i < arr.length; i++) { + String cmd = arr[i]; + cmd = cmd.trim(); + int pos = cmd.indexOf(' '); + if (pos != -1) { + String word = cmd.substring(0, pos).trim(); + String sound = cmd.substring(pos + 1).trim(); + ac.setWord(word, sound); + } + } + } + + private IRCConfiguration getIRCConfiguration() throws Exception { + String gui = getString("gui", "notprovided"); + IRCConfiguration config = new IRCConfiguration(getTextProvider(), _handler, _loader, _sound, _file, _provider, + new PrefixedParameterProvider(_provider, gui + ":")); + + config.setJoinList(getString("authorizedjoinlist", "")); + config.setLeaveList(getString("authorizedleavelist", "")); + config.setCommandList(getString("authorizedcommandlist", "")); + + config.set("style:floatingasl", getBoolean("style:floatingasl", false)); + config.set("style:floatingaslalpha", getInt("style:floatingaslalpha", 170)); + config.set("style:backgroundimage", getBoolean("style:backgroundimage", false)); + config.set("style:bitmapsmileys", getBoolean("style:bitmapsmileys", false)); + config.set("style:linespacing", getInt("style:linespacing", 0)); + config.set("style:maximumlinecount", getInt("style:maximumlinecount", 1024)); + + config.set("style:highlightlinks", getBoolean("style:highlightlinks", false)); + + config.set("aslseparatorstring", getString("aslseparatorstring", "")); + config.set("noasldisplayprefix", getString("noasldisplayprefix", "")); + config.set("quitmessage", getString("quitmessage", "")); + config.set("asl", getBoolean("asl", false)); + config.set("aslmale", getString("aslmale", "m")); + config.set("aslfemale", getString("aslfemale", "f")); + config.set("useinfo", getBoolean("useinfo", false)); + config.set("coding", getInt("coding", 1)); + config.set("userid", getString("userid", "")); + config.set("style:righttoleft", getBoolean("style:righttoleft", false)); + config.set("autoconnection", getBoolean("autoconnection", true)); + config.set("useidentserver", getBoolean("useidentserver", true)); + config.set("multiserver", getBoolean("multiserver", false)); + config.set("aslunknown", getString("aslunknown", "x")); + config.set("gui", getString("gui", null)); + config.set("fingerreply", getString("fingerreply", "A lucky Plouf's IRC user")); + config.set("userinforeply", getString("userinforeply", "A lucky Plouf's IRC user")); + config.set("allowdccchat", getBoolean("allowdccchat", true)); + config.set("allowdccfile", getBoolean("allowdccfile", true)); + config.set("disablequeries", getBoolean("disablequeries", false)); + config.set("autorejoin", getBoolean("autorejoin", false)); + + config.setInitialisation(getArray("init")); + + readBackgroundConfig(config); + readSmileys(config); + configureFonts(config); + configureTextColors(config); + readSound(config); + + return config; + } + + private ServerItem[] readServers(String dhost, int dport, String dpass) { + Vector res = new Vector(); + ServerItem item = new ServerItem(); + item.host = dhost; + item.port = new Integer(dport).intValue(); + item.pass = dpass; + res.insertElementAt(item, res.size()); + + String[] arr = getArray("alternateserver"); + for (int i = 0; i < arr.length; i++) { + String cmd = arr[i]; + int pos = cmd.indexOf(" "); + if (pos >= 0) { + String host = cmd.substring(0, pos).trim(); + String port = cmd.substring(pos + 1).trim(); + String pass = ""; + pos = port.indexOf(" "); + if (pos >= 0) { + pass = port.substring(pos + 1).trim(); + port = port.substring(0, pos).trim(); + } + item = new ServerItem(); + item.host = host; + item.port = new Integer(port).intValue(); + item.pass = pass; + res.insertElementAt(item, res.size()); + } + } + ServerItem[] ans = new ServerItem[res.size()]; + for (int i = 0; i < ans.length; i++) + ans[i] = (ServerItem) res.elementAt(i); + return ans; + } + + private StartupConfiguration getStartupConfiguration() throws Exception { + String nick = getParameter("nick"); + if (nick == null) + throw new Exception("Mandatory 'nick' parameter not provided"); + String name = getParameter("name"); + if (name == null) + name = getParameter("fullname"); + if (name == null) + throw new Exception("Mandatory 'fullname' parameter not provided"); + String host = getParameter("host"); + if (host == null) + throw new Exception("Mandatory 'host' parameter not provided"); + String pass = getParameter("password"); + if (pass == null) + pass = ""; + String sport = getParameter("port"); + if (sport == null) + sport = "6667"; + int port = new Integer(sport).intValue(); + String altNick = getParameter("alternatenick"); + if (altNick == null) + altNick = nick + "?"; + String alias = getParameter("serveralias"); + if (alias == null) + alias = ""; + + ServerItem[] items = readServers(host, port, pass); + String[] hosts = new String[items.length]; + int[] ports = new int[items.length]; + String[] passs = new String[items.length]; + for (int i = 0; i < items.length; i++) { + hosts[i] = items[i].host; + ports[i] = items[i].port; + passs[i] = items[i].pass; + } + return new StartupConfiguration(nick, altNick, name, passs, hosts, ports, alias, getArray("command"), + getArray("plugin")); + } + +} diff --git a/src/main/java/irc/DefaultInterpretor.java b/src/main/java/irc/DefaultInterpretor.java new file mode 100644 index 0000000..739d11b --- /dev/null +++ b/src/main/java/irc/DefaultInterpretor.java @@ -0,0 +1,94 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +/** + * A default interpretor. + */ +public class DefaultInterpretor extends BasicInterpretor { + private StartupConfiguration _start; + private ServerManager _mgr; + private PluginManager _plugin; + + /** + * Create a new DefaultInterpretor. + * + * @param config + * global irc configuration. + * @param start + * statup configuration. + * @param mgr + * the server manager to be called upon server creation. + * @param plugin + * the plugin manager. + */ + public DefaultInterpretor(IRCConfiguration config, StartupConfiguration start, ServerManager mgr, PluginManager plugin) { + super(config); + _start = start; + _mgr = mgr; + _plugin = plugin; + } + + @Override + protected void handleCommand(Source source, String cmd, String[] parts, String[] cumul) { + try { + if (cmd.equals("newserver")) { + if (_ircConfiguration.getB("multiserver")) { + test(cmd, parts, 2); + int port = 6667; + String pass = ""; + String alias = parts[1]; + if (parts.length > 3) + port = new Integer(parts[3]).intValue(); + if (parts.length > 4) + pass = parts[4]; + String host = parts[2]; + + IRCServer server = new IRCServer(_ircConfiguration, _mgr, _start.getNick(), _start.getAltNick(), + _start.getName(), alias); + server.setServers(new String[] { host }, new int[] { port }, new String[] { pass }); + _mgr.newServer(server, true); + } else { + source.report(getText(IRCTextProvider.INTERPRETOR_MULTISERVER_DISABLED)); + } + } else if (cmd.equals("load")) { + test(cmd, parts, 1); + _plugin.loadPlugin(parts[1]); + } else if (cmd.equals("unload")) { + test(cmd, parts, 1); + _plugin.unloadPlugin(parts[1]); + } else { + super.handleCommand(source, cmd, parts, cumul); + } + } catch (NotEnoughParametersException ex) { + source.report(getText(IRCTextProvider.INTERPRETOR_INSUFFICIENT_PARAMETERS, ex.getMessage())); + } + } +} diff --git a/src/main/java/irc/DefaultSource.java b/src/main/java/irc/DefaultSource.java new file mode 100644 index 0000000..d71805b --- /dev/null +++ b/src/main/java/irc/DefaultSource.java @@ -0,0 +1,64 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2005 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +/** + * The Default No-Source. + */ +public class DefaultSource extends Source { + /** + * Create a new DefaultSource + * + * @param config + */ + public DefaultSource(IRCConfiguration config) { + super(config, new NullServer()); + } + + @Override + public boolean talkable() { + return false; + } + + @Override + public String getType() { + return "Default"; + } + + @Override + public String getName() { + return "Global"; + } + + @Override + public void leave() { + // nothing here + } +} diff --git a/src/main/java/irc/EventDispatcher.java b/src/main/java/irc/EventDispatcher.java new file mode 100644 index 0000000..13f8f32 --- /dev/null +++ b/src/main/java/irc/EventDispatcher.java @@ -0,0 +1,469 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2005 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Hashtable; + +/** + * EventItem. + */ +class EventItem { + /** + * Target object. + */ + public Object target; + /** + * Method name to call on target. + */ + public String method; + /** + * Method parameters. + */ + public Object[] params; + /** + * Lock that will be signaled upon completion. + */ + public Object endLock; + /** + * Method call result, if resultException is null. + */ + public Object result; + /** + * Method call exception, or null if all went well. + */ + public Throwable resultException; + /** + * True if call has completed. + */ + public boolean resultAvailable; + + /** + * Create a new EventItem + * + * @param atarget + * @param amethod + * @param aparams + */ + public EventItem(Object atarget, String amethod, Object[] aparams) { + target = atarget; + method = amethod; + params = aparams; + endLock = new Object(); + resultAvailable = false; + result = null; + } + +} + +/** + * DispatchThread. + */ +class DispatchThread extends Thread { + private irc.LinkedList _list; + + private Object _manageLock; + private boolean _terminated; + private boolean _processing; + + /** + * Create a new DispatchThread + * + * @param type + * thread type : will be added in the name. + */ + public DispatchThread(String type) { + super(type + " event dispatch thread"); + _manageLock = new Object(); + _list = new LinkedList(); + _terminated = false; + _processing = false; + setDaemon(true); + start(); + } + + /** + * Add an event in the dispatch thread queue. + * + * @param target + * target object. + * @param method + * method name to call. + * @param params + * call parameters. + * @return the newly created event item. + */ + public EventItem addEvent(Object target, String method, Object[] params) { + if (_terminated) + return null; + EventItem item = new EventItem(target, method, params); + synchronized (_manageLock) { + _list.addLast(item); + _manageLock.notify(); + } + return item; + } + + @Override + public void run() { + int size = 0; + do { + EventItem item; + synchronized (_manageLock) { + if (_list.size() > 0) + item = (EventItem) _list.removeFirst(); + else { + item = null; + try { + _manageLock.wait(); + } catch (InterruptedException ex) { + // ignore... + } + } + size = _list.size(); + } + if (item != null) { + _processing = true; + item.resultException = null; + try { + item.result = EventDispatcher.dispatchEventSyncEx(item.target, item.method, item.params); + } catch (Throwable e) { + item.resultException = e; + } + _processing = false; + synchronized (item.endLock) { + item.resultAvailable = true; + item.endLock.notify(); + } + } + } while (!(_terminated && (size == 0))); + } + + /** + * Terminate the event thread processing. + */ + public void terminate() { + _terminated = true; + if (!_processing) + interrupt(); + } +} + +/** + * Event dispatcher, using reflection and PJIRC threading model. The PJIRC + * threading model states that, unless specified otherwise, any call to any + * method of any object should be performed in the event dispatcher thread. This + * can be ensured via isEventThread. Any call to dispatchEventSync in an other + * thread will lead to an error message displayed on the error output. + */ +public class EventDispatcher { + private static final int USER = 0; + private static final int SECURITY = 1; + + private static final String[] _names = { "User", "Security" }; + + private static Hashtable _cache = new Hashtable(); + private static DispatchThread[] _thread = new DispatchThread[2]; + private static boolean _warning = true; + + private static void ensureAlive(int index) { + if ((_thread[index] == null) || (!_thread[index].isAlive())) { + _thread[index] = new DispatchThread(_names[index]); + } + } + + private static boolean match(Class[] t1, Class[] t2) { + if (t1.length != t2.length) + return false; + for (int i = 0; i < t1.length; i++) { + if (t2[i] != null) + if (!t1[i].isAssignableFrom(t2[i])) + return false; + } + return true; + } + + /** + * Clear the internal EventDispatcher method cache. + */ + public static void clearCache() { + synchronized (_cache) { + _cache.clear(); + } + } + + /** + * Disabe the synchroneous call thread check. + */ + public static void disableBadThreadWarning() { + _warning = false; + } + + /** + * Enable the synchroneous call thread check. + */ + public static void enableBadThreadWarning() { + _warning = true; + } + + /** + * Dispatch the given event in the current thread, ignoring any thrown + * exception. + * + * @param target + * event target. + * @param method + * event method name. + * @param params + * event parameters. + * @return the method result. + * @deprecated Use dispatchEventSyncEx instead. + */ + @Deprecated + public static Object dispatchEventSync(Object target, String method, Object[] params) { + try { + return dispatchEventSyncEx(target, method, params); + } catch (Throwable ex) { + ex.printStackTrace(); + return null; + } + } + + /** + * Dispatch the given event in the current thread, not ignoring any thrown + * exception. + * + * @param target + * event target. + * @param method + * event method name. + * @param params + * event parameters. + * @return the method result. + * @throws Throwable + */ + public static Object dispatchEventSyncEx(Object target, String method, Object[] params) throws Throwable { + ensureAlive(USER); + + if (_warning && !isEventThread()) { + System.err.println("Event dispatch in wrong thread"); + System.err.println("expected thread was " + _thread); + System.err.println("current thread is " + Thread.currentThread()); + System.err.println("please submit a bug report to plouf@pjirc.com with the following information :"); + Thread.dumpStack(); + } + + try { + Class c = target.getClass(); + + Method m[]; + synchronized (_cache) { + m = (Method[]) _cache.get(c); + if (m == null) { + m = c.getMethods(); + _cache.put(c, m); + } + } + + Class types[] = new Class[params.length]; + for (int i = 0; i < params.length; i++) { + if (params[i] != null) + types[i] = params[i].getClass(); + else + types[i] = null; + } + for (int i = 0; i < m.length; i++) { + if (m[i].getName().equals(method)) { + if (match(m[i].getParameterTypes(), types)) { + return m[i].invoke(target, params); + } + } + } + throw new NoSuchMethodException(method); + } catch (InvocationTargetException ex) { + throw ex.getTargetException(); + } catch (Throwable ex) { + System.err.println("internal error"); + System.err.println("please submit a bug report to plouf@pjirc.com with the following information :"); + ex.printStackTrace(); + return null; + } + } + + /** + * Dispatch a new event to the given target in the event thread. The method + * result is discarded. + * + * @param target + * target event listener. + * @param method + * method name to call. + * @param params + * parameters to pass to the called method. + */ + public static void dispatchEventAsync(Object target, String method, Object[] params) { + ensureAlive(USER); + _thread[USER].addEvent(target, method, params); + } + + private static void checkStack() { + // we want to avoid code other that irc.security.* calls this method + // unable to implement on 1.1... + } + + private static void checkDeadLock(int index) { + ensureAlive(index); + if (Thread.currentThread() == _thread[index]) { + try { + throw new RuntimeException("Deadlock protection"); + } catch (RuntimeException ex) { + ex.printStackTrace(); + throw ex; + } + } + } + + /** + * Dispatch a new event to the given target in the security event thread. The + * method result is discarded. + * + * @param target + * target event listener. + * @param method + * method name to call. + * @param params + * parameters to pass to the called method. + */ + public static void dispatchEventAsyncSecurity(Object target, String method, Object[] params) { + checkStack(); + ensureAlive(SECURITY); + _thread[SECURITY].addEvent(target, method, params); + } + + private static Object dispatchEventAsyncAndWaitExImp(Object target, String method, Object[] params, int index) + throws InterruptedException, Throwable { + checkDeadLock(index); + ensureAlive(index); + EventItem item = _thread[index].addEvent(target, method, params); + synchronized (item.endLock) { + if (item.resultAvailable) { + if (item.resultException != null) + throw item.resultException; + return item.result; + } + item.endLock.wait(); + if (item.resultException != null) + throw item.resultException; + return item.result; + } + } + + /** + * Dispatch a new event in the event thread, waiting for the result and + * returning it. + * + * @param target + * target event listener. + * @param method + * method name to call. + * @param params + * parameters to pass to the called method. + * @return method result. + * @throws InterruptedException + * if the wait is interrupted. + * @throws Throwable + */ + public static Object dispatchEventAsyncAndWaitEx(Object target, String method, Object[] params) + throws InterruptedException, Throwable { + return dispatchEventAsyncAndWaitExImp(target, method, params, USER); + } + + /** + * Dispatch a new event in the security event thread, waiting for the result + * and returning it. + * + * @param target + * target event listener. + * @param method + * method name to call. + * @param params + * parameters to pass to the called method. + * @return method result. + * @throws InterruptedException + * if the wait is interrupted. + * @throws Throwable + */ + public static Object dispatchEventAsyncAndWaitExSecurity(Object target, String method, Object[] params) + throws InterruptedException, Throwable { + checkStack(); + return dispatchEventAsyncAndWaitExImp(target, method, params, SECURITY); + } + + /** + * Dispatch a new event in the event thread, waiting for the result and + * returning it. + * + * @param target + * target event listener. + * @param method + * method name to call. + * @param params + * parameters to pass to the called method. + * @return method result. + * @throws InterruptedException + * if the wait is interrupted. + * @deprecated Use dispatchEventAsyncAndWaitEx instead. + */ + @Deprecated + public static Object dispatchEventAsyncAndWait(Object target, String method, Object[] params) + throws InterruptedException { + checkDeadLock(USER); + ensureAlive(USER); + EventItem item = _thread[USER].addEvent(target, method, params); + synchronized (item.endLock) { + if (item.resultAvailable) { + return item.result; + } + item.endLock.wait(); + return item.result; + } + } + + /** + * Check if the calling thread is the event thread. + * + * @return true if calling thread is event thread, false otherwise. + */ + public static boolean isEventThread() { + ensureAlive(USER); + return Thread.currentThread() == _thread[USER] || Thread.currentThread() == _thread[SECURITY]; + } +} diff --git a/src/main/java/irc/FileHandler.java b/src/main/java/irc/FileHandler.java new file mode 100644 index 0000000..cadd6e5 --- /dev/null +++ b/src/main/java/irc/FileHandler.java @@ -0,0 +1,46 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +import java.io.InputStream; + +/** + * File handling. + */ +public interface FileHandler { + /** + * Get an input stream from the given filename. + * + * @param fileName + * file name to get inputstream from. + * @return inputstream from the file, or null if unable. + */ + public InputStream getInputStream(String fileName); +} diff --git a/src/main/java/irc/FileTextProvider.java b/src/main/java/irc/FileTextProvider.java new file mode 100644 index 0000000..bc08b06 --- /dev/null +++ b/src/main/java/irc/FileTextProvider.java @@ -0,0 +1,179 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2005 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.Hashtable; + +/** + * Provides text from langage file. + */ +public class FileTextProvider implements TextProvider { + private Hashtable _mainlist; + private Hashtable _backlist; + + /** + * Create a new file text provider. + * + * @param fname + * langage file name. + * @param encoding + * langage file encoding. Empty string for default encoding. + * @param backname + * backup langage file name. + * @param backencoding + * backup langage file encoding. Empty string for default encoding. + * @param file + * a file handler to load file. + */ + public FileTextProvider(String fname, String encoding, String backname, String backencoding, FileHandler file) { + _mainlist = new Hashtable(); + _backlist = new Hashtable(); + load(_mainlist, fname, encoding, file); + load(_backlist, backname, backencoding, file); + } + + private void parse(Hashtable dest, String line) { + try { + int pos = line.indexOf(' '); + if (pos == -1) + return; + String id = line.substring(0, pos); + String end = line.substring(pos + 1).trim(); + if (line.indexOf('[') != -1) { + pos = line.indexOf(']'); + if (pos == -1) + return; + end = line.substring(pos + 1).trim(); + } + int iid = Integer.parseInt(id, 16); + end = replace(end, "\\s", " "); + dest.put(new Integer(iid), end); + } catch (Exception ex) { + throw new RuntimeException(ex.toString()); + } + } + + private void load(Hashtable dest, String fname, String encoding, FileHandler handler) { + InputStream stream = handler.getInputStream(fname); + if (stream == null) + return; + + BufferedReader reader = null; + try { + if (encoding.length() > 0) + reader = new BufferedReader(new InputStreamReader(stream, encoding)); + else + reader = new BufferedReader(new InputStreamReader(stream)); + } catch (Exception ex) { + return; + } + + try { + String line = reader.readLine(); + while (line != null) { + line = line.trim(); + if (line.length() > 0) { + if (line.charAt(0) != '#') { + parse(dest, line); + } + } + line = reader.readLine(); + } + reader.close(); + } catch (IOException ex) { + ex.printStackTrace(); + } + + } + + private String replace(String on, String what, String with) { + int pos = on.indexOf(what); + while (pos >= 0) { + String before = on.substring(0, pos); + String after = on.substring(pos + what.length()); + on = before + with + after; + pos = on.indexOf(what); + } + return on; + } + + @Override + public String getString(int code, String[] params) { + String ans = (String) _mainlist.get(new Integer(code)); + if (ans == null) + ans = (String) _backlist.get(new Integer(code)); + if (ans == null) + ans = (String) _mainlist.get(new Integer(ERROR_NOT_DEFINED)); + if (ans == null) + ans = (String) _backlist.get(new Integer(ERROR_NOT_DEFINED)); + if (ans == null) + return getStringP(ERROR_NOT_DEFINED); + for (int i = params.length - 1; i >= 0; i--) + ans = replace(ans, "%" + (i + 1), params[i]); + return ans; + } + + @Override + public String getString(int code) { + return getString(code, new String[0]); + } + + @Override + public String getString(int code, String p1) { + String p[] = { p1 }; + return getString(code, p); + } + + @Override + public String getString(int code, String p1, String p2) { + String p[] = { p1, p2 }; + return getString(code, p); + } + + @Override + public String getString(int code, String p1, String p2, String p3) { + String p[] = { p1, p2, p3 }; + return getString(code, p); + } + + private String getStringP(int code) { + switch (code) { + case ERROR_NOT_DEFINED: + return "Undefined string"; + default: + return null; + } + } + +} diff --git a/src/main/java/irc/IRCApplication.java b/src/main/java/irc/IRCApplication.java new file mode 100644 index 0000000..e2dfa92 --- /dev/null +++ b/src/main/java/irc/IRCApplication.java @@ -0,0 +1,812 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2005 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +import irc.gui.GUISource; +import irc.gui.IRCInterface; +import irc.gui.IRCInterfaceListener; +import irc.ident.IdentListener; +import irc.ident.IdentWrapper; +import irc.plugin.Plugin; + +import java.awt.Button; +import java.awt.Container; +import java.awt.FlowLayout; +import java.awt.Font; +import java.awt.Frame; +import java.awt.GridLayout; +import java.awt.TextField; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; +import java.io.File; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Vector; + +/** + * The IRC Application. This is the main class of PJIRC. + */ +public class IRCApplication extends IRCObject implements ServerListener, ServerManager, IdentListener, + IRCInterfaceListener, WindowListener, ActionListener, PluginManager { + private DefaultSource _defaultSource; + + private Interpretor _inter; + + private IdentWrapper _ident; + + private StartupConfiguration _start; + + private IRCInterface _interface; + private Vector _plugins; + private Hashtable _pluginsTable; + + private Frame _frame; + private Container _container; + + private Hashtable _servers; + + private Object _nickLock = new Object(); + + /** + * Create a new IRCApplication. + * + * @param config + * the IRC configuration. + * @param startupConfig + * the startup configuration. + * @param source + * a container in wich the application will display. Maybe null. If + * null, a new Frame will be opened. + */ + public IRCApplication(IRCConfiguration config, StartupConfiguration startupConfig, Container source) { + super(config); + _container = source; + _start = startupConfig; + _plugins = new Vector(); + _pluginsTable = new Hashtable(); + + String gui = config.getS("gui"); + try { + Class cl = Class.forName("irc.gui." + gui + ".Interface"); + java.lang.reflect.Constructor ctr = cl.getDeclaredConstructor(new Class[] { config.getClass() }); + _interface = (IRCInterface) ctr.newInstance(new Object[] { config }); + } catch (java.lang.reflect.InvocationTargetException iex) { + iex.getTargetException().printStackTrace(); + throw new Error("Unable to load interface " + gui + " : " + iex.getTargetException()); + } catch (Throwable ex) { + ex.printStackTrace(); + throw new Error("Unable to load interface " + gui + " : " + ex); + } + + _servers = new Hashtable(); + _defaultSource = new DefaultSource(_ircConfiguration); + DefaultInterpretor defaultInter = new DefaultInterpretor(_ircConfiguration, _start, this, this); + _defaultSource.setInterpretor(defaultInter); + } + + /** + * Init the application. + */ + public synchronized void init() { + loadPlugin(_interface); + + String[] plugins = _start.getPlugins(); + for (int i = 0; i < plugins.length; i++) + loadPlugin(plugins[i]); + + _interface.addIRCInterfaceListener(this); + if (_container == null) { + _frame = new Frame(); + _frame.addWindowListener(this); + if (_interface.getComponent() != null) + _frame.add(_interface.getComponent()); + _frame.setFont(new Font("", Font.PLAIN, 12)); + _frame.setSize(640, 400); + _frame.show(); + } else { + _frame = null; + _container.removeAll(); + _container.setLayout(new GridLayout(1, 1)); + if (_interface.getComponent() != null) + _container.add(_interface.getComponent()); + } + + _inter = new CTCPInterpretor(_ircConfiguration, _defaultSource.getInterpretor(), this); + _inter.addLast(_interface.getInterpretor()); + + if (_ircConfiguration.getB("useidentserver")) { + try { + _ident = new IdentWrapper(_ircConfiguration); + Exception e = _ident.start(_start.getName(), this); + if (e != null) { + _defaultSource.report("\3" + "6" + "*** " + getText(IRCTextProvider.IDENT_FAILED_LAUNCH, e.getMessage())); + } + } catch (Throwable ex) { + _ircConfiguration.internalError("ident error", ex, "plouf@pjirc.com"); + } + } else { + _ident = null; + } + + String[] init = _ircConfiguration.getInitialization(); + for (int i = 0; i < init.length; i++) + _defaultSource.sendString(init[i]); + + IRCServer server = new IRCServer(_ircConfiguration, this, _start.getNick(), _start.getAltNick(), _start.getName(), + _start.getAlias()); + server.setServers(_start.getHost(), _start.getPort(), _start.getPass()); + + newServer(server, _ircConfiguration.getB("autoconnection")); + + requestSourceFocus(); + } + + /** + * Get the IRC interface. + * + * @return the IRC interface. + */ + public IRCInterface getIRCInterface() { + return _interface; + } + + @Override + public void newServer(Server server, boolean connect) { + server.addServerListener(this); + _servers.put(server, server); + + Enumeration enum1 = _plugins.elements(); + while (enum1.hasMoreElements()) { + Plugin plugin = (Plugin) enum1.nextElement(); + plugin.serverCreated(server); + } + + server.enumerateSourcesAsCreated(this); + if (connect) + server.connect(); + } + + /** + * Uninit the application. + */ + public synchronized void uninit() { + Enumeration en = _servers.keys(); + while (en.hasMoreElements()) { + Server s = (Server) en.nextElement(); + s.leave(); + } + + if (_ident != null) + _ident.stop(); + _interface.removeIRCInterfaceListener(this); + + if (_frame != null) + _frame.removeWindowListener(this); + _frame = null; + + while (_plugins.size() > 0) { + unloadPlugin((Plugin) _plugins.elementAt(_plugins.size() - 1)); + } + _pluginsTable = new Hashtable(); + + if (_container != null) + _container.removeAll(); + + EventDispatcher.clearCache(); + } + + @Override + public boolean loadPlugin(String str) { + if (_pluginsTable.get(str) != null) + return false; + Plugin plugin; + try { + Class cl = Class.forName("irc.plugin." + str); + java.lang.reflect.Constructor ctr = cl.getDeclaredConstructor(new Class[] { _ircConfiguration.getClass() }); + plugin = (Plugin) ctr.newInstance(new Object[] { _ircConfiguration }); + loadPlugin(plugin); + } catch (Throwable ex) { + ex.printStackTrace(); + return false; + } + _pluginsTable.put(str, plugin); + return true; + } + + @Override + public boolean unloadPlugin(String str) { + Plugin plugin = (Plugin) _pluginsTable.get(str); + if (plugin == null) + return false; + _pluginsTable.remove(str); + unloadPlugin(plugin); + return true; + } + + private void loadPlugin(Plugin plugin) { + class addHandler implements ServerListener { + private Plugin _plugin; + + /** + * Create a new addHandler + * + * @param plug + * plugin. + */ + public addHandler(Plugin plug) { + _plugin = plug; + } + + @Override + public void serverConnected(Server s) {/* ... */ + } + + @Override + public void serverDisconnected(Server s) {/* ... */ + } + + @Override + public void serverLeft(Server s) {/* ... */ + } + + @Override + public String[] cannotUseRequestedNicknames(Server s) { + return null; + } + + @Override + public void sourceCreated(Source source, Server server, Boolean bring) { + _plugin.sourceCreated(source, bring); + } + + @Override + public void sourceRemoved(Source source, Server server) {/* ... */ + } + + @Override + public Object specialServerRequest(String request, Server server, Object[] params) { + return null; + } + } + + plugin.setIRCApplication(this); + plugin.load(); + _plugins.insertElementAt(plugin, _plugins.size()); + plugin.sourceCreated(_defaultSource, Boolean.TRUE); + + Enumeration en = _servers.keys(); + while (en.hasMoreElements()) { + Server s = (Server) en.nextElement(); + plugin.serverCreated(s); + + s.enumerateSourcesAsCreated(new addHandler(plugin)); + } + + } + + private void unloadPlugin(Plugin plugin) { + class removeHandler implements ServerListener { + private Plugin _plugin; + + /** + * Create a new removeHandler + * + * @param plug + * plugin. + */ + public removeHandler(Plugin plug) { + _plugin = plug; + } + + @Override + public void serverConnected(Server s) {/* ... */ + } + + @Override + public void serverDisconnected(Server s) {/* ... */ + } + + @Override + public void serverLeft(Server s) {/* ... */ + } + + @Override + public String[] cannotUseRequestedNicknames(Server s) { + return null; + } + + @Override + public void sourceCreated(Source source, Server server, Boolean bring) {/* ... */ + } + + @Override + public void sourceRemoved(Source source, Server server) { + _plugin.sourceRemoved(source); + } + + @Override + public Object specialServerRequest(String request, Server server, Object[] params) { + return null; + } + } + + for (int i = 0; i < _plugins.size(); i++) { + if (_plugins.elementAt(i) == plugin) { + _plugins.removeElementAt(i); + Enumeration en = _servers.keys(); + while (en.hasMoreElements()) { + Server s = (Server) en.nextElement(); + s.enumerateSourcesAsRemoved(new removeHandler(plugin)); + plugin.serverRemoved(s); + } + plugin.sourceRemoved(_defaultSource); + plugin.unload(); + return; + } + } + } + + @Override + public void sourceCreated(Source source, Server server, Boolean bring) { + source.getInterpretor().addLast(_inter); + Enumeration enum1 = _plugins.elements(); + while (enum1.hasMoreElements()) { + Plugin plugin = (Plugin) enum1.nextElement(); + plugin.sourceCreated(source, bring); + } + } + + @Override + public void sourceRemoved(Source source, Server server) { + Enumeration enum1 = _plugins.elements(); + while (enum1.hasMoreElements()) { + Plugin plugin = (Plugin) enum1.nextElement(); + plugin.sourceRemoved(source); + } + } + + @Override + public void serverLeft(Server s) { + Enumeration enum1 = _plugins.elements(); + while (enum1.hasMoreElements()) { + Plugin plugin = (Plugin) enum1.nextElement(); + plugin.serverRemoved(s); + } + _servers.remove(s); + s.removeServerListener(this); + } + + private Frame getParentFrame() { + if (_frame != null) + return _frame; + Container ans = _container; + while (ans != null) { + if (ans instanceof Frame) + return (Frame) ans; + ans = ans.getParent(); + } + return null; + } + + /** + * Get the application's parent container. The GUI instance will be added into + * this container or one of its children. + * + * @return application's parent container. + */ + public Container getContainer() { + if (_frame != null) + return _frame; + return _container; + } + + @Override + public Object specialServerRequest(String request, Server s, Object[] params) { + if (request.equals("DCCFileRequest")) { + File f = _ircConfiguration.getSecurityProvider().getSaveFile(params[1].toString(), + getText(IRCTextProvider.FILE_SAVEAS) + " [" + params[1] + "]"); + return f; + } else if (request.equals("DCCChatRequest")) { + boolean accept = _ircConfiguration.getSecurityProvider().confirm(getParentFrame(), + getText(IRCTextProvider.GUI_DCC_CHAT_WARNING_TITLE), + getText(IRCTextProvider.GUI_DCC_CHAT_WARNING_TEXT, (String) params[0])); + return new Boolean(accept); + } else { + _ircConfiguration.internalError("Unknown request : " + request, null, "plouf@pjirc.com"); + return null; + } + } + + @Override + public void serverConnected(Server server) { + for (int i = 0; i < _start.getCommands().length; i++) { + String cmd = _start.getCommands()[i]; + if ((cmd.startsWith("/")) && (server instanceof IRCServer)) + ((IRCServer) server).getStatus().sendString(_start.getCommands()[i]); + else + server.execute(_start.getCommands()[i]); + } + + Enumeration enum1 = _plugins.elements(); + while (enum1.hasMoreElements()) { + Plugin plugin = (Plugin) enum1.nextElement(); + plugin.serverConnected(server); + } + + } + + @Override + public void serverDisconnected(Server s) { + Enumeration enum1 = _plugins.elements(); + while (enum1.hasMoreElements()) { + Plugin plugin = (Plugin) enum1.nextElement(); + plugin.serverDisconnected(s); + } + } + + @Override + public void identRequested(String source, Integer result, String reply) { + _defaultSource.report("\3" + "6" + "*** " + getText(IRCTextProvider.IDENT_REQUEST, source)); + String s = ""; + switch (result.intValue()) { + case IdentListener.IDENT_ERROR: + s = getText(IRCTextProvider.IDENT_ERROR); + break; + case IdentListener.IDENT_OK: + s = getText(IRCTextProvider.IDENT_REPLIED, reply); + break; + case IdentListener.IDENT_DEFAULT: + s = getText(IRCTextProvider.IDENT_REPLIED, getText(IRCTextProvider.IDENT_DEFAULT_USER) + " : " + reply); + break; + case IdentListener.IDENT_NOT_FOUND: + s = getText(IRCTextProvider.IDENT_NO_USER); + break; + default: + s = getText(IRCTextProvider.IDENT_UNDEFINED); + break; + } + _defaultSource.report("\3" + "6" + "*** " + s); + + } + + @Override + public void identRunning(Integer port) { + _defaultSource.report("\3" + "6" + "*** " + getText(IRCTextProvider.IDENT_RUNNING_ON_PORT, port + "")); + } + + @Override + public void identLeaving(String message) { + _defaultSource.report("\3" + "6" + "*** " + getText(IRCTextProvider.IDENT_LEAVING, message)); + } + + @Override + public void activeChanged(GUISource source, IRCInterface inter) { + if (source != null) { + if (source.getSource().mayDefault()) + source.getSource().getServer().setDefaultSource(source.getSource()); + if (_frame != null) + _frame.setTitle(source.getTitle()); + } + } + + @Override + public void windowActivated(WindowEvent e) { + // nothing here + } + + @Override + public void windowClosed(WindowEvent e) { + if (e.getSource() == _frame) { + EventDispatcher.dispatchEventAsync(this, "uninit", new Object[0]); + } + } + + @Override + public void windowClosing(WindowEvent e) { + ((Frame) e.getSource()).hide(); + ((Frame) e.getSource()).dispose(); + } + + @Override + public void windowDeactivated(WindowEvent e) { + // nothing here + } + + @Override + public void windowDeiconified(WindowEvent e) { + // nothing here + } + + @Override + public void windowIconified(WindowEvent e) { + // nothing here + } + + @Override + public void windowOpened(WindowEvent e) { + // nothing here + } + + private GUISource getActiveSource() { + return _interface.getActive(); + } + + private Source getSource(String serverName, String type, String name) { + Enumeration e = _servers.keys(); + while (e.hasMoreElements()) { + Server s = (Server) e.nextElement(); + String sname = s.getServerName(); + if (sname.equals(serverName) || serverName.length() == 0) { + Enumeration f = s.getSources(); + while (f.hasMoreElements()) { + Source src = (Source) f.nextElement(); + if (src.getType().equals(type) && src.getName().equals(name)) + return src; + } + } + } + return null; + } + + /** + * Request the active source to gain focus. + */ + public void requestSourceFocus() { + GUISource current = getActiveSource(); + if (current == null) + return; + current.requestFocus(); + } + + /** + * Request the given source to gain focus. + * + * @param serverName + * the source's server name, or an empty string if no server + * filtering needs to be done. + * @param type + * the source type. + * @param name + * the source name. + */ + public void requestSourceFocus(String serverName, String type, String name) { + Source source = getSource(serverName, type, name); + if (source != null) { + GUISource gui = _interface.getGUISource(source); + if (gui != null) + _interface.setActive(gui); + } + } + + /** + * Send the given command to the given source interpretor. + * + * @param serverName + * the source's server name, or an empty string if no server + * filtering needs to be done. + * @param type + * the source type. + * @param name + * the source name. + * @param cmd + * the command to send. + */ + public void sendString(String serverName, String type, String name, String cmd) { + Source source = getSource(serverName, type, name); + if (source != null) + source.sendString(cmd); + } + + /** + * Send the given string to the current source interpretor. + * + * @param str + * string to send to the interpretor. + */ + public void sendString(String str) { + GUISource current = getActiveSource(); + if (current == null) + return; + current.getSource().sendString(str); + } + + /** + * Set the current textfield text. + * + * @param txt + * new textfield text. + */ + public void setFieldText(String txt) { + GUISource current = getActiveSource(); + if (current == null) + return; + current.setFieldText(txt); + } + + /** + * Get the current textfield text. + * + * @return the current textfield text. + */ + public String getFieldText() { + GUISource current = getActiveSource(); + if (current == null) + return ""; + return current.getFieldText(); + } + + /** + * Validate the current textfield text, as if user pressed return key. + */ + public void validateText() { + GUISource current = getActiveSource(); + if (current == null) + return; + current.validateText(); + } + + /** + * Send the given event value to the given plugin. + * + * @param pluginName + * the plugin name. + * @param event + * the event value to be sent. + */ + public void sendPluginEvent(String pluginName, Object event) { + Plugin plugin = (Plugin) _pluginsTable.get(pluginName); + if (plugin == null) + return; + plugin.externalEvent(event); + } + + /** + * Get the plugin value from the given plugin name. + * + * @param pluginName + * the plugin name. + * @param valueName + * the value name. + * @return the returned plugin value, or null if the plugin is not found. + */ + public Object getPluginValue(String pluginName, Object valueName) { + Plugin plugin = (Plugin) _pluginsTable.get(pluginName); + if (plugin == null) + return null; + return plugin.getValue(valueName); + } + + @Override + public String[] cannotUseRequestedNicknames(Server s) { + synchronized (_nickLock) { + if (_interface.getComponent() != null) + _interface.getComponent().setEnabled(false); + if (_frame != null) + _frame.setEnabled(false); + Frame f = new Frame(); + f.setLayout(new FlowLayout()); + f.setSize(200, 65); + f.setTitle(getText(IRCTextProvider.GUI_CHANGE_NICK)); + TextField field = new TextField(_start.getNick()); + Button b = new Button("Ok"); + b.addActionListener(this); + f.add(field); + f.add(b); + f.show(); + try { + _nickLock.wait(); + } catch (InterruptedException ex) { + // ignore... + } + f.hide(); + f.remove(b); + f.remove(field); + f.dispose(); + String[] ans = new String[1]; + ans[0] = field.getText(); + if (_frame != null) + _frame.setEnabled(true); + if (_interface.getComponent() != null) + _interface.getComponent().setEnabled(true); + return ans; + } + } + + @Override + public void actionPerformed(ActionEvent evt) { + synchronized (_nickLock) { + _nickLock.notifyAll(); + } + } + + private static void usage() { + System.out.println("Usage :"); + System.out.println(" java irc.IRCApplication -f configfile"); + System.out.println("or java irc.IRCApplication -p nick fullname host gui"); + System.out.println(""); + System.out.println("Without any parameter, '-f pjirc.cfg' parameters are assumed."); + } + + /** + * Actual entry point. + * + * @param args + * application parameters. + */ + public static void go(String[] args) { + FileHandler file = new LocalFileHandler(); + IRCConfiguration ircConfiguration; + StartupConfiguration startupConfiguration; + + try { + + if ((args.length == 0) || ((args.length >= 2) && (args[0].equals("-f")))) { + String f = "pjirc.cfg"; + if (args.length >= 2) + f = args[1]; + StreamParameterProvider provider = new StreamParameterProvider(file.getInputStream(f)); + ConfigurationLoader loader = new ConfigurationLoader(provider, new NullURLHandler(), new AWTImageLoader(), + new NullSoundHandler(), file); + ircConfiguration = loader.loadIRCConfiguration(); + startupConfiguration = loader.loadStartupConfiguration(); + } else if ((args.length >= 5) && (args[0].equals("-p"))) { + StreamParameterProvider provider = new StreamParameterProvider(null); + ConfigurationLoader loader = new ConfigurationLoader(provider, new NullURLHandler(), new AWTImageLoader(), + new NullSoundHandler(), file); + ircConfiguration = loader.loadIRCConfiguration(); + ircConfiguration.set("gui", args[4]); + startupConfiguration = new StartupConfiguration(args[1], "", args[2], new String[] { "" }, + new String[] { args[3] }, new int[] { 6667 }, "", new String[] {}, new String[] {}); + } else { + usage(); + return; + } + + IRCApplication application = new IRCApplication(ircConfiguration, startupConfiguration, null); + EventDispatcher.dispatchEventAsyncAndWaitEx(application, "init", new Object[0]); + } catch (Throwable ex) { + System.out.println("Error : " + ex.getMessage()); + ex.printStackTrace(); + } + } + + /** + * Main entry point. + * + * @param args + * application parameters. + */ + public static void main(String[] args) { + go(args); + } + +} diff --git a/src/main/java/irc/IRCConfiguration.java b/src/main/java/irc/IRCConfiguration.java new file mode 100644 index 0000000..ebf4131 --- /dev/null +++ b/src/main/java/irc/IRCConfiguration.java @@ -0,0 +1,874 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2005 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +import irc.security.SecurityProvider; + +import java.awt.Color; +import java.awt.Font; +import java.awt.Image; +import java.util.Hashtable; + +/** + * NullItem. + */ +class NullItem { + // empty +} + +/** + * Global IRC configuration. Any call is synchronized and can be performed from + * any thread. + */ +public class IRCConfiguration { + /** + * Image is centered. + */ + public static final int TILING_CENTER = 0; + /** + * Image is stretched. + */ + public static final int TILING_STRETCH = 1; + /** + * Image is tiled. + */ + public static final int TILING_TILE = 2; + /** + * Image position is fixed. + */ + public static final int TILING_FIXED = 3; + + /** + * Image position is fixed on the left. + */ + public static final int TILING_HORIZONTAL_LEFT = 0; + /** + * Image position is fixed on the right. + */ + public static final int TILING_HORIZONTAL_RIGHT = 256; + /** + * Image position if fixed upside. + */ + public static final int TILING_VERTICAL_UP = 0; + /** + * Image position is fixed downside. + */ + public static final int TILING_VERTICAL_DOWN = 512; + + private NullItem NULL_ITEM = new NullItem(); + + private TextProvider _textProvider; + private ImageLoader _loader; + private URLHandler _handler; + private FileHandler _file; + private AudioConfiguration _audioConfig; + + private RuleList _backgroundImageRules; + private RuleList _backgroundTilingRules; + private RuleList _colorsRules; + private RuleList _fontRules; + + private SmileyTable _table; + private ListHandler _mayJoinList; + private ListHandler _mayLeaveList; + private ListHandler _mayCommandList; + private Hashtable _htable; + private SecurityProvider _provider; + private ParameterProvider _paramProvider; + private ParameterProvider _interfaceParamProvider; + + private String _guiInfoString; + + private String[] _initCommands; + + /** + * Create a new IRCConfiguration. + * + * @param text + * text provider to use. + * @param handler + * URL handler to use. + * @param loader + * image loader to use. + * @param sound + * sound handler to use. + * @param file + * file handler to use. + * @param paramProvider + * parameter provider. + * @param interfaceParamProvider + * interface parameter provider. + */ + public IRCConfiguration(TextProvider text, URLHandler handler, ImageLoader loader, SoundHandler sound, + FileHandler file, ParameterProvider paramProvider, ParameterProvider interfaceParamProvider) { + _provider = new SecurityProvider(); + + _paramProvider = paramProvider; + _interfaceParamProvider = interfaceParamProvider; + + _htable = new Hashtable(); + + _backgroundImageRules = new RuleList(); + _backgroundTilingRules = new RuleList(); + _backgroundTilingRules.setDefaultValue(new Integer(0)); + + _fontRules = new RuleList(); + _fontRules.setDefaultValue(new Font("Monospaced", Font.PLAIN, 12)); + + _colorsRules = new RuleList(); + Color[] def = new Color[16]; + loadDefaultColors(def); + _colorsRules.setDefaultValue(def); + + _audioConfig = new AudioConfiguration(sound); + _table = new SmileyTable(); + + _file = file; + _loader = loader; + _textProvider = text; + _handler = handler; + + _guiInfoString = ""; + + _initCommands = new String[0]; + } + + /** + * Create a new dummy IRCConfiguration. All parameters are set to default. + * Note that the 'gui' parameter is not set. + * + * @return a new IRCConfiguration instance. + */ + public static IRCConfiguration createDummyIRCConfiguration() { + try { + FileHandler file = new LocalFileHandler(); + StreamParameterProvider provider = new StreamParameterProvider(null); + ConfigurationLoader loader = new ConfigurationLoader(provider, new NullURLHandler(), new AWTImageLoader(), + new NullSoundHandler(), file); + return loader.loadIRCConfiguration(); + } catch (Exception ex) { + /* should not reach here : bug */ + throw new Error("Error creating dummy IRCConfiguration : " + ex); + } + } + + /** + * Get the initialisation commands. + * + * @return the initialisation commands. + */ + public String[] getInitialization() { + return _initCommands; + } + + /** + * Set the initialisation commands. + * + * @param init + * the initialisation commands. + */ + public void setInitialisation(String[] init) { + _initCommands = init; + } + + /** + * Get the GUI information string. + * + * @return the GUI info string. + */ + public String getGUIInfoString() { + return _guiInfoString; + } + + /** + * Set the GUI information string. + * + * @param string + * the GUI information string. + */ + public void setGUIInfoString(String string) { + _guiInfoString = string; + } + + /** + * Get the file handler. + * + * @return the file handler. + */ + public FileHandler getFileHandler() { + return _file; + } + + /** + * Display the about page. + */ + public void displayAboutPage() { + new AboutDialog(this); + } + + /** + * Get the parameter provider used for creating this IRCConfiguration. + * + * @return the parameter provider. + */ + public ParameterProvider getParameterProvider() { + return _paramProvider; + } + + /** + * Get the parameter provider whose should be used by an user interface. + * + * @return the interface parameter provider. + */ + public ParameterProvider getInterfaceParameterProvider() { + return _interfaceParamProvider; + } + + /** + * Get the high version number. + * + * @return the high version number. + */ + public int getVersionHigh() { + return 2; + } + + /** + * Get the middle version number. + * + * @return the middle version number. + */ + public int getVersionMed() { + return 2; + } + + /** + * Get the low version number. + * + * @return the low version number. + */ + public int getVersionLow() { + return 1; + } + + /** + * Get the version modifiers. + * + * @return version modifiers. + */ + public String getVersionModifiers() { + return ""; + } + + /** + * Get version number as a string. + * + * @return high.med.lowmod version number. + */ + public String getVersion() { + return getVersionHigh() + "." + getVersionMed() + "." + getVersionLow() + getVersionModifiers(); + } + + /** + * Get the security provider. + * + * @return the security provider. + */ + public SecurityProvider getSecurityProvider() { + return _provider; + } + + /** + * Set the given property to the given value. This value may be null. + * + * @param key + * property name. + * @param obj + * property value. + */ + public synchronized void set(String key, Object obj) { + if (obj == null) + obj = NULL_ITEM; + _htable.put(key.toLowerCase(java.util.Locale.ENGLISH), obj); + } + + /** + * Set the given property to the given int value. + * + * @param key + * property name. + * @param val + * property value. + */ + public synchronized void set(String key, int val) { + set(key, new Integer(val)); + } + + /** + * Set the given property to the given boolean value. + * + * @param key + * property name. + * @param val + * property value. + */ + public synchronized void set(String key, boolean val) { + set(key, new Boolean(val)); + } + + /** + * Get the given property value. + * + * @param key + * property name. + * @return the property value. + * @throws RuntimeException + * if the property is unknown. + */ + public synchronized Object get(String key) { + Object v = _htable.get(key.toLowerCase(java.util.Locale.ENGLISH)); + if (v == null) + throw new RuntimeException("Unknown configuration property " + key); + if (v == NULL_ITEM) + v = null; + return v; + } + + /** + * Get the given property value as an int value. + * + * @param key + * property name. + * @return the property value. + * @throws RuntimeException + * if the property is unknown. + */ + public synchronized int getI(String key) { + Integer i = (Integer) get(key); + return i.intValue(); + } + + /** + * Get the given property value as a boolean value. + * + * @param key + * property name. + * @return the property value. + * @throws RuntimeException + * if the property is unknown. + */ + public synchronized boolean getB(String key) { + Boolean b = (Boolean) get(key); + return b.booleanValue(); + } + + /** + * Get the given property value as String value. + * + * @param key + * property name. + * @return the property value. + * @throws RuntimeException + * if the property is unknown. + */ + public synchronized String getS(String key) { + return (String) get(key); + } + + /** + * Test wether the given channel may be left. + * + * @param channel + * channel to be left. + * @return true if channel may be left, false otherwise. + */ + public synchronized boolean mayLeave(String channel) { + return _mayLeaveList.inList(channel); + } + + /** + * Test wether the given channel may be joined. + * + * @param channel + * channel to be joined. + * @return true if channel may be joined, false otherwise. + */ + public synchronized boolean mayJoin(String channel) { + return _mayJoinList.inList(channel); + } + + /** + * Set the "may join" list. + * + * @param list + * join list. + */ + public synchronized void setJoinList(String list) { + _mayJoinList = new ListHandler(list); + } + + /** + * Set the "may leave" list. + * + * @param list + * leave list. + */ + public synchronized void setLeaveList(String list) { + _mayLeaveList = new ListHandler(list); + } + + /** + * Set the authorized command list. + * + * @param list + * authorized command list. + */ + public synchronized void setCommandList(String list) { + _mayCommandList = new ListHandler(list); + } + + /** + * Check wether the given command may be executed by the user. + * + * @param cmd + * command to test, not prefixed by /. + * @return true if command may be executed, false otherwise. + */ + public synchronized boolean mayCommand(String cmd) { + if (cmd.startsWith("/")) + cmd = cmd.substring(1); + return _mayCommandList.inList(cmd); + } + + /** + * Get the background image associated with the given source type and name. + * + * @param type + * source type. + * @param name + * source name. + * @return background image, or null if no image is to be displayed. + */ + public synchronized Image getBackgroundImage(String type, String name) { + if (!getB("style:backgroundImage")) + return null; + return (Image) _backgroundImageRules.findValue(new String[] { type, name }); + } + + /** + * Get the background image tiling associated with the given source type and + * name. + * + * @param type + * source type. + * @param name + * source name. + * @return tiling mode for background image. + */ + public synchronized int getBackgroundTiling(String type, String name) { + return ((Integer) _backgroundTilingRules.findValue(new String[] { type, name })).intValue(); + } + + /** + * Set the background image to be used for the given source type and name. + * + * @param type + * source type. + * @param name + * source name. + * @param image + * image name. + */ + public synchronized void setBackgroundImage(String type, String name, String image) { + _backgroundImageRules.addRule(new String[] { type, name }, getImageLoader().getImage(image)); + } + + /** + * Set the background image tiling to be used for the given source type and + * name. + * + * @param type + * source type. + * @param name + * source name. + * @param tiling + * tiling mode to be used. + */ + public synchronized void setBackgroundTiling(String type, String name, int tiling) { + _backgroundTilingRules.addRule(new String[] { type, name }, new Integer(tiling)); + } + + /** + * Set the font to be used for the given source type and name. + * + * @param type + * source type. + * @param name + * source name. + * @param f + * font to be used. + */ + public synchronized void setFont(String type, String name, Font f) { + _fontRules.addRule(new String[] { type, name }, f); + } + + /** + * Format a string given asl info and current settings. + * + * @param info + * user whois information. + * @return formatted asl information. An empty string shouldn't be displayed. + */ + public synchronized String formatASL(String info) { + String noprefix = getS("noasldisplayprefix"); + if ((noprefix.length() > 0) && (info.startsWith(noprefix))) + return ""; + + String separator = getS("aslseparatorstring"); + if (separator.length() > 0) { + int pos = info.indexOf(separator); + if (pos >= 0) + info = info.substring(0, pos); + } + + String orig = info; + int pos = info.indexOf(' '); + if (pos < 0) + return orig; + + String age = info.substring(0, pos).trim(); + info = info.substring(pos + 1).trim(); + pos = info.indexOf(' '); + if (pos < 0) + return orig; + String gender = info.substring(0, pos).trim().toLowerCase(java.util.Locale.ENGLISH); + String location = info.substring(pos + 1).trim(); + + int text; + if (gender.equals(getS("aslmale").toLowerCase(java.util.Locale.ENGLISH))) + text = IRCTextProvider.ASL_MALE; + else if (gender.equals(getS("aslfemale").toLowerCase(java.util.Locale.ENGLISH))) + text = IRCTextProvider.ASL_FEMALE; + else if (gender.equals(getS("aslunknown").toLowerCase(java.util.Locale.ENGLISH))) + text = IRCTextProvider.ASL_UNKNOWN; + else + return orig; + + return getText(text, age, location); + } + + /** + * Find the correct ASL color for the given info. + * + * @param info + * user whois information. + * @param male + * male color. + * @param femeale + * femeale color. + * @param undef + * undefined gender color. + * @return asl color. + */ + public synchronized Color getASLColor(String info, Color male, Color femeale, Color undef) { + int pos = info.indexOf(' '); + if (pos < 0) + return undef; + info = info.substring(pos).trim(); + pos = info.indexOf(' '); + if (pos < 0) + return undef; + info = info.substring(0, pos).trim().toLowerCase(java.util.Locale.ENGLISH); + if (info.equals(getS("aslmale").toLowerCase(java.util.Locale.ENGLISH))) + return male; + if (info.equals(getS("aslfemale").toLowerCase(java.util.Locale.ENGLISH))) + return femeale; + return undef; + } + + /** + * Get the audio configuration. + * + * @return the audio configuration. + */ + public AudioConfiguration getAudioConfiguration() { + return _audioConfig; + } + + /** + * Get the default style context. + * + * @return the default style context. + */ + public synchronized StyleContext getDefaultStyleContext() { + return getStyleContext("", ""); + } + + /** + * Get the style context associated with the given source type and name. + * + * @param type + * source name. + * @param name + * source name. + * @return associated style context. + */ + public synchronized StyleContext getStyleContext(String type, String name) { + StyleContext ctx = new StyleContext(); + ctx.type = type; + ctx.name = name; + return ctx; + } + + /** + * Load the given color array with the default source colors. The array must + * be of length 16. + * + * @param cols + * color array to be filled. + */ + public synchronized void loadDefaultColors(Color[] cols) { + cols[0] = new Color(0xFFFFFF); + cols[1] = new Color(0x000000); + cols[2] = new Color(0x00007F); + cols[3] = new Color(0x009300); + cols[4] = new Color(0xFF0000); + cols[5] = new Color(0x7F0000); + cols[6] = new Color(0x9C009C); + cols[7] = new Color(0xFC7F00); + cols[8] = new Color(0xFFFF00); + cols[9] = new Color(0x00FC00); + cols[10] = new Color(0x009393); + cols[11] = new Color(0x00FFFF); + cols[12] = new Color(0x0000FC); + cols[13] = new Color(0xFF00FF); + cols[14] = new Color(0x7F7F7F); + cols[15] = new Color(0xD2D2D2); + } + + /** + * Set the source colors. + * + * @param type + * source type. + * @param name + * source name. + * @param c + * color array. + */ + public synchronized void setSourceColor(String type, String name, Color c[]) { + _colorsRules.addRule(new String[] { type, name }, c); + } + + /** + * Get the colors associated with the given style context. + * + * @param context + * the context to get colors from. + * @return color array for the given context. + */ + public synchronized Color[] getStyleColors(StyleContext context) { + return (Color[]) _colorsRules.findValue(new String[] { context.type, context.name }); + } + + /** + * Get the font associated with the given style context. + * + * @param context + * the context to get font from. + * @return font for the given context. + */ + public synchronized Font getStyleFont(StyleContext context) { + return (Font) _fontRules.findValue(new String[] { context.type, context.name }); + } + + /** + * Get the image background associated with the given style context. + * + * @param context + * the context to get background from. + * @return image for the given context. + */ + public synchronized Image getStyleBackgroundImage(StyleContext context) { + return getBackgroundImage(context.type, context.name); + } + + /** + * Get the tiling background associated with the given style context. + * + * @param context + * the context to get tiling from. + * @return tiling for the given context. + */ + public synchronized int getStyleBackgroundTiling(StyleContext context) { + return getBackgroundTiling(context.type, context.name); + } + + /** + * Add a smiley in the smiley table. + * + * @param match + * the matching text to replace. + * @param file + * image file name. + */ + public synchronized void addSmiley(String match, String file) { + _table.addSmiley(match, _loader.getImage(file)); + } + + /** + * Get the image loader. + * + * @return the image loader. + */ + public ImageLoader getImageLoader() { + return _loader; + } + + /** + * Get the smileys table. + * + * @return the smiley table. + */ + public SmileyTable getSmileyTable() { + return _table; + } + + /** + * Return wether asl should be processed, because asl field is enabled or + * floating asl is enabled. + * + * @return master asl status. + */ + public synchronized boolean getASLMaster() { + return getB("asl") | getB("style:floatingasl"); + } + + /** + * Get URLHandler. + * + * @return URLHandler. + */ + public URLHandler getURLHandler() { + return _handler; + } + + /** + * Get text provider. + * + * @return text provider. + */ + public TextProvider getTextProvider() { + return _textProvider; + } + + /** + * Report an internal error. + * + * @param message + * error message. + * @param ex + * optional (can be null) cause exception. + * @param mail + * mail address where the bug report should be sent. + */ + public void internalError(String message, Throwable ex, String mail) { + System.err.println("************ Internal error ************"); + System.err.println("Please submit a bug report to " + mail + " including the following information:"); + System.err.println("Message:"); + System.err.println(message); + + if (ex != null) { + System.err.println("Root cause:"); + ex.printStackTrace(); + } + System.err.println("Stack trace:"); + Thread.dumpStack(); + } + + /** + * Get formatted text associated with the given text code, with no parameter. + * + * @param code + * text code. + * @return formatted text. + */ + public synchronized String getText(int code) { + return _textProvider.getString(code); + } + + /** + * Get formatted text associated with the given text code, with one parameter. + * + * @param code + * text code. + * @param p1 + * first parameter. + * @return formatted text. + */ + public synchronized String getText(int code, String p1) { + return _textProvider.getString(code, p1); + } + + /** + * Get formatted text associated with the given text code, with two + * parameters. + * + * @param code + * text code. + * @param p1 + * first parameter. + * @param p2 + * second parameter. + * @return formatted text. + */ + public synchronized String getText(int code, String p1, String p2) { + return _textProvider.getString(code, p1, p2); + } + + /** + * Get formatted text associated with the given text code, with three + * parameters. + * + * @param code + * text code. + * @param p1 + * first parameter. + * @param p2 + * second parameter. + * @param p3 + * third parameter. + * @return formatted text. + */ + public synchronized String getText(int code, String p1, String p2, String p3) { + return _textProvider.getString(code, p1, p2, p3); + } + +} diff --git a/src/main/java/irc/IRCInterpretor.java b/src/main/java/irc/IRCInterpretor.java new file mode 100644 index 0000000..a60185c --- /dev/null +++ b/src/main/java/irc/IRCInterpretor.java @@ -0,0 +1,154 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +import java.util.Enumeration; + +/** + * IRC interpretor. + */ +public class IRCInterpretor extends BasicInterpretor { + /** + * Create a new IRCInterpretor. + * + * @param config + * global configuration. + */ + public IRCInterpretor(IRCConfiguration config) { + super(config); + } + + @Override + protected void handleCommand(Source source, String cmd, String[] parts, String[] cumul) { + try { + + IRCServer server = (IRCServer) source.getServer(); + if (cmd.equals("amsg")) { + test(cmd, parts, 1); + Enumeration e = server.getChannels(); + while (e.hasMoreElements()) { + ((Channel) e.nextElement()).sendString(cumul[1]); + } + } else if (cmd.equals("ame")) { + test(cmd, parts, 1); + Enumeration e = server.getChannels(); + while (e.hasMoreElements()) { + ((Channel) e.nextElement()).sendString("/me " + cumul[1]); + } + } else if (cmd.equals("list")) { + if (parts.length <= 1) + server.execute("LIST"); + else + server.execute("LIST " + parts[1]); + } else if (cmd.equals("topic")) { + test(cmd, parts, 2); + server.execute("TOPIC " + parts[1] + " :" + cumul[2]); + } else if (cmd.equals("away")) { + if (parts.length <= 1) + server.execute("AWAY"); + else + server.execute("AWAY :" + cumul[1]); + } else if (cmd.equals("quit")) { + if (parts.length > 1) + server.execute("QUIT :" + cumul[1]); + else + server.execute("QUIT"); + } else if (cmd.equals("part")) { + test(cmd, parts, 1); + if (parts.length == 2) { + server.execute("PART " + parts[1]); + } else { + server.execute("PART " + parts[1] + " :" + cumul[2]); + } + } else if (cmd.equals("kick")) { + test(cmd, parts, 2); + if (parts.length == 3) { + server.execute("KICK " + parts[1] + " " + parts[2]); + } else { + server.execute("KICK " + parts[1] + " " + parts[2] + " :" + cumul[3]); + } + } else if (cmd.equals("notice")) { + test(cmd, parts, 2); + server.execute("NOTICE " + parts[1] + " :" + cumul[2]); + source.report("-> -" + parts[1] + "- " + cumul[2]); + } else if (cmd.equals("onotice")) { + test(cmd, parts, 2); + sendString(source, "/notice @" + parts[1] + " " + cumul[2]); + } else if (cmd.equals("join")) { + test(cmd, parts, 1); + String chan = parts[1]; + if (!chan.startsWith("#") && !chan.startsWith("!") && !chan.startsWith("&") && !chan.startsWith("+")) + chan = '#' + chan; + if (parts.length <= 2) + server.execute("JOIN " + chan); + else + server.execute("JOIN " + chan + " " + parts[2]); + } else if (cmd.equals("j")) { + sendString(source, "/join " + cumul[1]); + } else if (cmd.equals("query")) { + test(cmd, parts, 1); + server.getQuery(parts[1], true); + } else if (cmd.equals("ignore")) { + test(cmd, parts, 1); + if (!server.ignore(parts[1])) { + server.addIgnore(parts[1]); + source.report(getText(IRCTextProvider.INTERPRETOR_IGNORE_ON, parts[1])); + } + } else if (cmd.equals("unignore")) { + test(cmd, parts, 1); + if (server.ignore(parts[1])) { + server.removeIgnore(parts[1]); + source.report(getText(IRCTextProvider.INTERPRETOR_IGNORE_OFF, parts[1])); + } + } else if (cmd.equals("server")) { + test(cmd, parts, 1); + int port = 6667; + String pass = ""; + if (parts.length > 2) + port = (new Integer(parts[2])).intValue(); + if (parts.length > 3) + pass = parts[3]; + String host = parts[1]; + if (server.isConnected()) + server.disconnect(); + server.setServers(new String[] { host }, new int[] { port }, new String[] { pass }); + server.connect(); + } else if (cmd.equals("connect")) { + server.connect(); + } else if (cmd.equals("disconnect")) { + server.disconnect(); + } else { + super.handleCommand(source, cmd, parts, cumul); + } + } catch (NotEnoughParametersException ex) { + source.report(getText(IRCTextProvider.INTERPRETOR_INSUFFICIENT_PARAMETERS, ex.getMessage())); + } + } +} diff --git a/src/main/java/irc/IRCObject.java b/src/main/java/irc/IRCObject.java new file mode 100644 index 0000000..ae09cdf --- /dev/null +++ b/src/main/java/irc/IRCObject.java @@ -0,0 +1,125 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2005 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +/** + * Root IRC Object. + */ +public class IRCObject { + /** + * The global IRC configuration. + */ + protected IRCConfiguration _ircConfiguration; + + /** + * Create a new IRCObject. + * + * @param ircConfiguration + * the global irc configuration. + */ + public IRCObject(IRCConfiguration ircConfiguration) { + _ircConfiguration = ircConfiguration; + } + + /** + * get the irc configuration. + * + * @return the global irc configuration. + */ + public IRCConfiguration getIRCConfiguration() { + return _ircConfiguration; + } + + /** + * Release this object. No further method call can be performed on this + * object. + */ + public void release() { + // empty default implementation + } + + /** + * Get formatted text associated with the given text code, with no parameter. + * + * @param code + * text code. + * @return formatted text. + */ + public String getText(int code) { + return _ircConfiguration.getText(code); + } + + /** + * Get formatted text associated with the given text code, with one parameter. + * + * @param code + * text code. + * @param p1 + * first parameter. + * @return formatted text. + */ + public String getText(int code, String p1) { + return _ircConfiguration.getText(code, p1); + } + + /** + * Get formatted text associated with the given text code, with two + * parameters. + * + * @param code + * text code. + * @param p1 + * first parameter. + * @param p2 + * second parameter. + * @return formatted text. + */ + public String getText(int code, String p1, String p2) { + return _ircConfiguration.getText(code, p1, p2); + } + + /** + * Get formatted text associated with the given text code, with three + * parameters. + * + * @param code + * text code. + * @param p1 + * first parameter. + * @param p2 + * second parameter. + * @param p3 + * third parameter. + * @return formatted text. + */ + public String getText(int code, String p1, String p2, String p3) { + return _ircConfiguration.getText(code, p1, p2, p3); + } +} diff --git a/src/main/java/irc/IRCServer.java b/src/main/java/irc/IRCServer.java new file mode 100644 index 0000000..df007ec --- /dev/null +++ b/src/main/java/irc/IRCServer.java @@ -0,0 +1,1409 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2005 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +import irc.dcc.prv.DCCChatServer; +import irc.dcc.prv.DCCFileHandler; + +import java.io.File; +import java.util.Date; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Vector; + +/** + * FirstLineFilter, used to handle CTCP codes. + */ +class FirstLineFilter { + private IRCServer _server; + private IRCConfiguration _ircConfiguration; + private ServerManager _mgr; + + /** + * Create a new FirstLineFilter + * + * @param serv + * @param mgr + * @param config + */ + public FirstLineFilter(IRCServer serv, ServerManager mgr, IRCConfiguration config) { + _ircConfiguration = config; + _mgr = mgr; + _server = serv; + } + + /** + * Release this object. + */ + public void release() { + _mgr = null; + _server = null; + } + + /** + * Perform any needed action from a channel message. + * + * @param channel + * channel name. + * @param nick + * nickname. + * @param msg + * actual message. + * @return true if message was handled, false otherwise. + */ + public boolean performFromChannelMessage(String channel, String nick, String msg) { + if (!msg.startsWith("\1")) + return false; + + msg = msg.substring(1); + msg = msg.substring(0, msg.length() - 1); + String cmd = ""; + String param = ""; + int pos = msg.indexOf(' '); + if (pos == -1) { + cmd = msg.toLowerCase(java.util.Locale.ENGLISH); + } else { + cmd = msg.substring(0, pos).toLowerCase(java.util.Locale.ENGLISH); + param = msg.substring(pos + 1); + } + + if (cmd.equals("action")) { + Channel c = _server.getChannel(channel, false); + if (c != null) + c.action(nick, param); + } else if (cmd.equals("sound")) { + _ircConfiguration.getAudioConfiguration().play(param); + _server.sendStatusMessage("\2\3" + "4" + "[" + nick + " " + cmd.toUpperCase(java.util.Locale.ENGLISH) + "]"); + } + return true; + } + + /** + * Perform any needed action from a nick message. + * + * @param nick + * nickname. + * @param msg + * actual message. + * @return true if message was handled, false otherwise. + */ + public boolean performFromNickMessage(String nick, String msg) { + if (!msg.startsWith("\1")) + return false; + + msg = msg.substring(1); + msg = msg.substring(0, msg.length() - 1); + String cmd = ""; + String param = ""; + int pos = msg.indexOf(' '); + if (pos == -1) { + cmd = msg.toLowerCase(java.util.Locale.ENGLISH); + } else { + cmd = msg.substring(0, pos).toLowerCase(java.util.Locale.ENGLISH); + param = msg.substring(pos + 1); + } + + boolean show = true; + if (cmd.equals("action")) { + show = false; + Query q = _server.getQuery(nick, false); + if (q != null) + q.action(nick, param); + } else if (cmd.equals("version")) { + String data = "PJIRC " + _ircConfiguration.getVersion(); + _server.execute("NOTICE " + nick + " :\1VERSION " + data + "\1"); + } else if (cmd.equals("ping")) { + _server.execute("NOTICE " + nick + " :\1PING " + param + "\1"); + } else if (cmd.equals("time")) { + String data = new Date().toString(); + _server.execute("NOTICE " + nick + " :\1TIME " + data + "\1"); + } else if (cmd.equals("finger")) { + String data = _ircConfiguration.getS("fingerreply"); + _server.execute("NOTICE " + nick + " :\1FINGER " + data + "\1"); + } else if (cmd.equals("userinfo")) { + String data = _ircConfiguration.getS("userinforeply"); + _server.execute("NOTICE " + nick + " :\1USERINFO " + data + "\1"); + } else if (cmd.equals("clientinfo")) { + String data = "This client is a Java application supporting the following CTCP tags : ACTION VERSION PING TIME FINGER USERINFO CLIENTINFO SOUND DCC"; + _server.execute("NOTICE " + nick + " :\1CLIENTINFO " + data + "\1"); + } else if (cmd.equals("sound")) { + _ircConfiguration.getAudioConfiguration().play(param); + } else if (cmd.equals("dcc")) { + StringParser sp = new StringParser(); + String[] args = sp.parseString(param.toLowerCase(java.util.Locale.ENGLISH)); + if (args.length >= 2) { + if (args[0].equals("chat") && args[1].equals("chat") && _ircConfiguration.getB("allowdccchat")) { + if (args.length >= 4) { + boolean bres = false; + Object[] res = _server.specialRequest("DCCChatRequest", new Object[] { nick }); + for (int i = 0; i < res.length; i++) + if (((Boolean) res[i]).booleanValue()) + bres = true; + + if (bres) { + try { + DCCChatServer cserver = new DCCChatServer(_ircConfiguration, _server.getNick(), nick); + cserver.openActive(args[2], args[3]); + _mgr.newServer(cserver, false); + } catch (Throwable ex) { + ex.printStackTrace(); + } + } + } + } + if (args[0].equals("send") && _ircConfiguration.getB("allowdccfile")) { + if (args.length >= 5) { + String fname = args[1]; + String ip = args[2]; + String port = args[3]; + String size = args[4]; + Object[] res = _server.specialRequest("DCCFileRequest", new Object[] { nick, fname, new Integer(size) }); + File dest = null; + if (res.length > 0) + dest = (File) res[0]; + if (dest != null) { + try { + DCCFileHandler handler = new DCCFileHandler(_ircConfiguration, nick, dest); + handler.receive(ip, port, size); + _mgr.newServer(handler, false); + } catch (Throwable ex) { + ex.printStackTrace(); + } + } + } + } + } + } + if (show) + _server.sendStatusMessage("\2\3" + "4" + "[" + nick + " " + cmd.toUpperCase(java.util.Locale.ENGLISH) + "]"); + return true; + } + + /** + * Perform any needed action from a notice message. + * + * @param nick + * nickname. + * @param msg + * actual message. + * @return true if message was handled, false otherwise. + */ + public boolean performFromNotice(String nick, String msg) { + if (!msg.startsWith("\1")) + return false; + + msg = msg.substring(1); + msg = msg.substring(0, msg.length() - 1); + String cmd = ""; + String param = ""; + int pos = msg.indexOf(' '); + if (pos == -1) { + cmd = msg.toLowerCase(java.util.Locale.ENGLISH); + } else { + cmd = msg.substring(0, pos).toLowerCase(java.util.Locale.ENGLISH); + param = msg.substring(pos + 1); + } + + Source source = _server.getDefaultSource(); + if (cmd.equals("ping")) { + long d = (new Long(param)).longValue(); + long delta = (new Date()).getTime() - d; + if (source != null) + source.report("\2\3" + "4" + + _ircConfiguration.getText(IRCTextProvider.CTCP_PING_REPLY, nick, (delta / 1000.0) + "")); + return true; + } + if (source != null) + source.report("\2\3" + "4" + "[" + nick + " " + cmd.toUpperCase(java.util.Locale.ENGLISH) + " reply] : " + param); + return true; + } +} + +/** + * The IRC server. + */ +public class IRCServer extends IRCObject implements Server, ServerProtocolListener { + private ServerProtocol _protocol; + private Hashtable _channels; + private Hashtable _queries; + private Hashtable _chanlist; + private Status _status; + + private Hashtable _ignoreList; + + private ListenerGroup _listeners; + private ListenerGroup _replylisteners; + private ListenerGroup _messagelisteners; + private String[] _askedNick; + private String _nick; + private String _userName; + private int _tryNickIndex; + private ModeHandler _mode; + private String[] _host; + private int[] _port; + private String _passWord[]; + private int _tryServerIndex; + private boolean _connected; + private String _name; + private Source _defaultSource; + private boolean _serverLeaving; + private boolean _registered; + private FirstLineFilter _filter; + // private boolean _nickWaiting=false; + + private char[] _nickModes = { 'o', 'h', 'v' }; + private char[] _nickPrefixes = { '@', '%', '+' }; + private char[] _channelPrefixes = { '#', '&', '!', '+' }; + private char[][] _globalModes = { { 'b' }, { 'k' }, { 'l' }, { 'i', 'm', 'n', 'p', 's', 't', 'a', 'q', 'r' } }; + + /** + * Create a new IRCServer. + * + * @param config + * global IRCConfiguration. + * @param mgr + * the server manager. + * @param nick + * claimed nick. + * @param altNick + * claimed alternate nick. + * @param userName + * user name. + * @param name + * the server name. + */ + public IRCServer(IRCConfiguration config, ServerManager mgr, String nick, String altNick, String userName, String name) { + super(config); + _filter = new FirstLineFilter(this, mgr, config); + _serverLeaving = false; + _name = name; + _userName = userName; + _askedNick = new String[2]; + _askedNick[0] = nick; + _askedNick[1] = altNick; + _nick = nick; + _connected = false; + _ignoreList = new Hashtable(); + + _channels = new Hashtable(); + _queries = new Hashtable(); + _chanlist = new Hashtable(); + + _listeners = new ListenerGroup(); + _replylisteners = new ListenerGroup(); + _messagelisteners = new ListenerGroup(); + + _status = new Status(_ircConfiguration, this); + _defaultSource = _status; + + _protocol = new ServerProtocol(_ircConfiguration); + _protocol.addServerProtocolListener(this); + + _host = null; + _mode = new ModeHandler(_globalModes, _nickModes); + } + + /** + * Send a special request event to all listeners. + * + * @param request + * request string. + * @param params + * request parameters. + * @return results. + */ + public Object[] specialRequest(String request, Object[] params) { + return _listeners.sendEvent("specialServerRequest", request, this, params); + } + + @Override + public void release() { + _protocol.removeServerProtocolListener(this); + _filter.release(); + super.release(); + } + + @Override + public Enumeration getSources() { + Vector v = new Vector(); + Enumeration e; + e = _channels.elements(); + while (e.hasMoreElements()) + v.insertElementAt(e.nextElement(), v.size()); + e = _queries.elements(); + while (e.hasMoreElements()) + v.insertElementAt(e.nextElement(), v.size()); + e = _chanlist.elements(); + while (e.hasMoreElements()) + v.insertElementAt(e.nextElement(), v.size()); + if (_status != null) + v.insertElementAt(_status, v.size()); + return v.elements(); + } + + @Override + public void enumerateSourcesAsCreated(ServerListener lis) { + Enumeration e; + e = _channels.elements(); + while (e.hasMoreElements()) + lis.sourceCreated((Source) e.nextElement(), this, new Boolean(false)); + e = _queries.elements(); + while (e.hasMoreElements()) + lis.sourceCreated((Source) e.nextElement(), this, new Boolean(false)); + e = _chanlist.elements(); + while (e.hasMoreElements()) + lis.sourceCreated((Source) e.nextElement(), this, new Boolean(false)); + if (_status != null) + lis.sourceCreated(_status, this, new Boolean(true)); + } + + @Override + public void enumerateSourcesAsRemoved(ServerListener lis) { + Enumeration e; + e = _channels.elements(); + while (e.hasMoreElements()) + lis.sourceRemoved((Source) e.nextElement(), this); + e = _queries.elements(); + while (e.hasMoreElements()) + lis.sourceRemoved((Source) e.nextElement(), this); + e = _chanlist.elements(); + while (e.hasMoreElements()) + lis.sourceRemoved((Source) e.nextElement(), this); + if (_status != null) + lis.sourceRemoved(_status, this); + } + + @Override + public void setDefaultSource(Source s) { + _defaultSource = s; + } + + /** + * Get the default server source, or null if no default source is defined. + * + * @return default source. + */ + public Source getDefaultSource() { + return _defaultSource; + } + + /** + * Set default configuration for the next connection. + * + * @param host + * server host. + * @param port + * server port. + * @param passWord + * server password. + */ + public void setServers(String host[], int port[], String passWord[]) { + _tryServerIndex = 0; + _host = new String[host.length]; + for (int i = 0; i < host.length; i++) + _host[i] = host[i]; + _port = new int[port.length]; + for (int i = 0; i < port.length; i++) + _port[i] = port[i]; + _passWord = new String[passWord.length]; + for (int i = 0; i < passWord.length; i++) + _passWord[i] = passWord[i]; + } + + @Override + public void connect() { + _tryServerIndex = 0; + if (_host != null) + connect(_host, _port, _passWord); + } + + private void connect(String host[], int port[], String[] passWord) { + _registered = false; + // if(_nickWaiting) return; + if (_tryServerIndex == _host.length) + return; + _tryNickIndex = 0; + _passWord = passWord; + if (_protocol.connecting()) { + sendStatusMessage(getText(IRCTextProvider.SERVER_UNABLE_TO_CONNECT_STILL, host[_tryServerIndex], + _host[_tryServerIndex])); + return; + } + if (_protocol.connected()) { + // sendStatusMessage(getText(IRCTextProvider.SERVER_DISCONNECTED,_host[_tryServerIndex])); + // disconnect(); + _protocol.disconnect(); + } + _connected = false; + sendStatusMessage(getText(IRCTextProvider.SERVER_CONNECTING)); + _protocol.connect(host[_tryServerIndex], port[_tryServerIndex]); + } + + /** + * Disconnect from the irc server. + */ + @Override + public void disconnect() { + // if(_nickWaiting) return; + if (_protocol.connected()) { + if (_ircConfiguration.getS("quitmessage").length() == 0) { + execute("QUIT"); + } else { + execute("QUIT :" + _ircConfiguration.get("quitmessage")); + } + } else { + sendStatusMessage(getText(IRCTextProvider.SERVER_NOT_CONNECTED)); + } + } + + /** + * Return true if connected to the server, false otherwise. + * + * @return connected state. + */ + @Override + public boolean isConnected() { + return _connected; + } + + @Override + public void connectionFailed(String message, String host) { + sendStatusMessage(getText(IRCTextProvider.SERVER_UNABLE_TO_CONNECT, message)); + _tryServerIndex++; + if (_tryServerIndex < _host.length) + connect(_host, _port, _passWord); + } + + private void nickUsed() { + if (_tryNickIndex >= _askedNick.length) { + // _nickWaiting=true; + Object[] res = _listeners.sendEvent("cannotUseRequestedNicknames", new Object[] { this }); + if (res.length > 0) + _askedNick = (String[]) res[0]; + // _nickWaiting=false; + _tryNickIndex = 0; + } else if (_askedNick[_tryNickIndex].indexOf("?") == -1) + _tryNickIndex++; + } + + private void register() { + String tryUseNick = _askedNick[_tryNickIndex]; + if (tryUseNick.length() == 0) + tryUseNick = "Anon????"; + String ans = ""; + for (int i = 0; i < tryUseNick.length(); i++) { + char c = tryUseNick.charAt(i); + if (c == '?') + c = (char) ('0' + Math.random() * 10); + ans += c; + } + if (_passWord[_tryServerIndex].length() > 0) + execute("pass " + _passWord[_tryServerIndex]); + execute("nick " + ans); + String name = _ircConfiguration.getS("userid"); + if (name.length() == 0) + name = ans; + if (!_registered) { + _registered = true; + execute("user " + name + " 0 0 :" + _userName); + } + } + + /** + * Get the local port of the remote connection. + * + * @return the local, client-side port of the remote connection. + */ + public int getLocalPort() { + return _protocol.getLocalPort(); + } + + @Override + public void connected(String host) { + sendStatusMessage(getText(IRCTextProvider.SERVER_LOGIN)); + register(); + } + + private void clear(Hashtable l) { + Enumeration e; + e = l.elements(); + while (e.hasMoreElements()) + _listeners.sendEvent("sourceRemoved", e.nextElement(), this); + e = l.elements(); + while (e.hasMoreElements()) + ((Source) e.nextElement()).release(); + l.clear(); + } + + @Override + public void disconnected(String host) { + sendStatusMessage(getText(IRCTextProvider.SERVER_DISCONNECTED, host)); + + clear(_channels); + clear(_queries); + clear(_chanlist); + + _mode.reset(); + if (_status != null) + _status.modeChanged(getMode()); + // _defaultSource=null; + + _connected = false; + _listeners.sendEvent("serverDisconnected", this); + + if (_serverLeaving) { + _listeners.sendEvent("sourceRemoved", _status, this); + deleteStatus(""); + _listeners.sendEvent("serverLeft", this); + } + } + + @Override + public void sendStatusMessage(String msg) { + if (_status != null) + _status.report(msg); + } + + /** + * Get all the channels. + * + * @return an enumeration of channels. + */ + public Enumeration getChannels() { + return _channels.elements(); + } + + /** + * Get all the queries. + * + * @return an enumeration of queries. + */ + public Enumeration getQueries() { + return _queries.elements(); + } + + /** + * Get all the chanlists. + * + * @return an enumeration of chanlists. + */ + public Enumeration getChanLists() { + return _chanlist.elements(); + } + + /** + * Get the channel from its name. If this channel doesn't exist, it is created + * only if create boolean is set. + * + * @param name + * channel name. + * @param create + * true if channel must be created if not existing. + * @return channel, or null. + */ + public Channel getChannel(String name, boolean create) { + Channel c = (Channel) _channels.get(name.toLowerCase(java.util.Locale.ENGLISH)); + if ((c == null) && create) { + c = new Channel(_ircConfiguration, name, this); + _channels.put(name.toLowerCase(java.util.Locale.ENGLISH), c); + _listeners.sendEvent("sourceCreated", c, this, new Boolean(true)); + } + return c; + } + + /** + * Get the query from its name. If this query doesn't exist, it is created. + * The query cannot be get if the server is not connected. + * + * @param nick + * query name. + * @param local + * true if this query has been created following a local request. + * @return query, or null if server was not connected. + */ + public Query getQuery(String nick, boolean local) { + if (!_connected) + return null; + if (_ircConfiguration.getB("disablequeries")) + return null; + Query c = (Query) _queries.get(nick.toLowerCase(java.util.Locale.ENGLISH)); + if (c == null) { + c = new Query(_ircConfiguration, nick, this); + _queries.put(nick.toLowerCase(java.util.Locale.ENGLISH), c); + _listeners.sendEvent("sourceCreated", c, this, new Boolean(local)); + + } + return c; + } + + /** + * Get the chanlist from its name. If this chanlist doesn't exist, it is + * created. + * + * @param name + * chanlist name. + * @return channel. + */ + private ChanList getChanList(String name) { + ChanList c = (ChanList) _chanlist.get(name.toLowerCase(java.util.Locale.ENGLISH)); + if (c == null) { + c = new ChanList(_ircConfiguration, this, name); + _chanlist.put(name.toLowerCase(java.util.Locale.ENGLISH), c); + _listeners.sendEvent("sourceCreated", c, this, new Boolean(true)); + } + return c; + } + + /** + * Request to leave the given channel. + * + * @param name + * channel name. + */ + public void leaveChannel(String name) { + execute("part " + name); + } + + /** + * Request to leave the given query. + * + * @param name + * query name. + */ + public void leaveQuery(String name) { + Query q = getQuery(name, false); + if (q == null) + return; + _listeners.sendEvent("sourceRemoved", q, this); + deleteQuery(name); + } + + @Override + public void leave() { + leaveStatus(""); + } + + /** + * Request to leave the status. This will cause server leaving. + * + * @param name + * Status name. Unused. + */ + public void leaveStatus(String name) { + if (_status == null) + return; + if (isConnected()) { + _serverLeaving = true; + disconnect(); + } else { + _listeners.sendEvent("sourceRemoved", _status, this); + deleteStatus(""); + _listeners.sendEvent("serverLeft", this); + } + /* + * long time=System.currentTimeMillis(); while(isConnected()) { try { + * Thread.sleep(100); if(System.currentTimeMillis()-time>10000) break; } + * catch(InterruptedException ex) { } } + */ + /* + * _listeners.sendEvent("sourceRemoved",_status,this); deleteStatus(name); + * _listeners.sendEvent("serverLeft",this); + */ + } + + /** + * Request to leave the given channel list. + * + * @param name + * chanlist name. + */ + public void leaveChanList(String name) { + _listeners.sendEvent("sourceRemoved", getChanList(name), this); + deleteChanList(name); + } + + private void deleteSource(Source src) { + if (src == _defaultSource) + _defaultSource = null; + src.release(); + } + + private void deleteChannel(String name) { + deleteSource((Source) _channels.remove(name.toLowerCase(java.util.Locale.ENGLISH))); + } + + private void deleteQuery(String name) { + deleteSource((Source) _queries.remove(name.toLowerCase(java.util.Locale.ENGLISH))); + } + + private void deleteChanList(String name) { + deleteSource((Source) _chanlist.remove(name.toLowerCase(java.util.Locale.ENGLISH))); + } + + private void deleteStatus(String name) { + deleteSource(_status); + _status = null; + } + + @Override + public String getServerName() { + if (_name.length() == 0) { + if (_tryServerIndex < _host.length) + return _host[_tryServerIndex]; + return _host[0]; + } + + return _name; + } + + /** + * Get this server's status, or null if this server has no status. + * + * @return the status, or null if the server hasno status. + */ + public Status getStatus() { + return _status; + } + + /** + * Add a server listener. + * + * @param l + * listener to add. + */ + @Override + public void addServerListener(ServerListener l) { + _listeners.addListener(l); + } + + /** + * Remove a listener. + * + * @param l + * listener to remove. + */ + @Override + public void removeServerListener(ServerListener l) { + _listeners.removeListener(l); + } + + /** + * Add a reply listener. + * + * @param l + * listener to add. + */ + public void addReplyServerListener(ReplyServerListener l) { + _replylisteners.addListener(l); + } + + /** + * Add a message listener. + * + * @param l + * listener to add. + */ + public void addMessageServerListener(MessageServerListener l) { + _messagelisteners.addListener(l); + } + + /** + * Remove a reply listener. + * + * @param l + * listener to remove. + */ + public void removeReplyServerListener(ReplyServerListener l) { + _replylisteners.removeListener(l); + } + + /** + * Remove a message listener. + * + * @param l + * listener to remove. + */ + public void removeMessageServerListener(MessageServerListener l) { + _messagelisteners.removeListener(l); + } + + /** + * Get an array of all known channel prefixes. + * + * @return an array of all channel prefixes. + */ + public char[] getChannelPrefixes() { + return _channelPrefixes; + } + + /** + * Get an array of all known nickname prefixes. + * + * @return array of all nickname prefixes. + */ + public char[] getNickPrefixes() { + return _nickPrefixes; + } + + /** + * Get an array of all known nickname modes. + * + * @return array of all nickname modes. + */ + public char[] getNickModes() { + return _nickModes; + } + + /** + * Get an array of all known A,B,C,D channel modes. + * + * @return array of all channel modes. This is an array of four char arrays. + */ + public char[][] getChannelModes() { + return _globalModes; + } + + /** + * Get the nick prefix associated with the given nick mode. + * + * @param mode + * nick mode. + * @return nick prefix for this mode. + */ + public String getNickPrefix(String mode) { + if (mode.length() == 0) + return ""; + char cmode = mode.charAt(0); + for (int i = 0; i < _nickModes.length; i++) + if (_nickModes[i] == cmode) + return "" + _nickPrefixes[i]; + return ""; + } + + /** + * Get the nick mode associated with the given nick prefix. + * + * @param prefix + * nick prefix. + * @return nick mode for this prefix. + */ + public String getNickMode(String prefix) { + if (prefix.length() == 0) + return ""; + char cprefix = prefix.charAt(0); + for (int i = 0; i < _nickPrefixes.length; i++) + if (_nickPrefixes[i] == cprefix) + return "" + _nickModes[i]; + return ""; + } + + private void setNicks(Channel c, Vector nicks) { + String[] n = new String[nicks.size()]; + String[] modes = new String[nicks.size()]; + + for (int i = 0; i < nicks.size(); i++) { + n[i] = (String) nicks.elementAt(i); + modes[i] = ""; + if (n[i].length() > 0) { + modes[i] = getNickMode("" + n[i].charAt(0)); + if (modes[i].length() != 0) + n[i] = n[i].substring(1); + } + } + c.setNicks(n, modes); + } + + private void decodeVariable(String key, String val) { + if (key.toLowerCase(java.util.Locale.ENGLISH).equals("prefix")) { + if (!val.startsWith("(")) + return; + int pos = val.indexOf(")"); + if (pos < 0) + return; + String modes = val.substring(1, pos); + String prefixes = val.substring(pos + 1); + if (prefixes.length() != modes.length()) + return; + + _nickModes = new char[modes.length()]; + for (int i = 0; i < modes.length(); i++) + _nickModes[i] = modes.charAt(i); + _nickPrefixes = new char[modes.length()]; + for (int i = 0; i < prefixes.length(); i++) + _nickPrefixes[i] = prefixes.charAt(i); + } else if (key.toLowerCase(java.util.Locale.ENGLISH).equals("chantypes")) { + _channelPrefixes = new char[val.length()]; + for (int i = 0; i < _channelPrefixes.length; i++) + _channelPrefixes[i] = val.charAt(i); + } else if (key.toLowerCase(java.util.Locale.ENGLISH).equals("chanmodes")) { + int pos = val.indexOf(','); + if (pos < 0) + return; + String a = val.substring(0, pos); + val = val.substring(pos + 1); + pos = val.indexOf(','); + if (pos < 0) + return; + String b = val.substring(0, pos); + val = val.substring(pos + 1); + pos = val.indexOf(','); + if (pos < 0) + return; + String c = val.substring(0, pos); + String d = val.substring(pos + 1); + _globalModes = new char[4][]; + _globalModes[0] = new char[a.length()]; + for (int i = 0; i < a.length(); i++) + _globalModes[0][i] = a.charAt(i); + _globalModes[1] = new char[b.length()]; + for (int i = 0; i < b.length(); i++) + _globalModes[1][i] = b.charAt(i); + _globalModes[2] = new char[c.length()]; + for (int i = 0; i < c.length(); i++) + _globalModes[2][i] = c.charAt(i); + _globalModes[3] = new char[d.length()]; + for (int i = 0; i < d.length(); i++) + _globalModes[3][i] = d.charAt(i); + } + } + + private void learnServerVariables(String var[]) { + for (int i = 1; i < var.length; i++) { + String v = var[i]; + int pos = v.indexOf('='); + String key; + String val; + if (pos < 0) { + key = v; + val = ""; + } else { + key = v.substring(0, pos); + val = v.substring(pos + 1); + } + decodeVariable(key, val); + } + _mode = new ModeHandler(_globalModes, _nickModes); + } + + @Override + public void replyReceived(String prefix, String id, String params[]) { + Object[] b = _replylisteners.sendEvent("replyReceived", new Object[] { prefix, id, params, this }); + for (int i = 0; i < b.length; i++) + if (((Boolean) b[i]).booleanValue()) + return; + + if (id.equals("324")) // mode : RPL_CHANNELMODEIS + { + Channel c = getChannel(params[1], false); + if (c != null) { + String mode = ""; + for (int i = 2; i < params.length; i++) + mode += " " + params[i]; + mode = mode.substring(1); + c.applyMode(mode, ""); + } + } else if (id.equals("332")) // topic : RPL_TOPIC + { + Channel c = getChannel(params[1], false); + if (c != null) + c.setTopic(params[2], ""); + } else if (id.equals("353")) // names : RPL_NAMREPLY + { + int first = 1; + if (params[1].length() == 1) + first++; + Channel c = getChannel(params[first], false); + if (c != null) { + String nick = ""; + Vector nicks = new Vector(); + for (int i = 0; i < params[first + 1].length(); i++) { + char u = params[first + 1].charAt(i); + if (u == ' ') { + if (nick.length() > 0) + nicks.insertElementAt(nick, nicks.size()); + nick = ""; + } else { + nick += u; + } + } + if (nick.length() > 0) + nicks.insertElementAt(nick, nicks.size()); + setNicks(c, nicks); + } + } else if (id.equals("001")) // RPL_WELCOME + { + String nick = params[0]; + if (!(nick.equals(_nick))) { + _nick = nick; + if (_status != null) + _status.nickChanged(nick); + } + _connected = true; + _listeners.sendEvent("serverConnected", this); + } else if (id.equals("005")) // RPL_ISUPPORT + { + learnServerVariables(params); + } else if (id.equals("321")) // /list begin : RPL_LISTSTART + { + getChanList(_host[_tryServerIndex]).begin(); + } else if (id.equals("322")) // /list : RPL_LIST + { + String name = params[1]; + int count = new Integer(params[2]).intValue(); + if ((count < 32767) && (isChannel(name))) { + String topic = params[3]; + getChanList(_host[_tryServerIndex]).addChannel(new ChannelInfo(name, topic, count)); + } + } else if (id.equals("323")) // /list end : RPL_LISTEND + { + getChanList(_host[_tryServerIndex]).end(); + } else if (id.equals("433")) // nick used : ERR_NICKNAMEINUSE + { + if (!_connected) { + nickUsed(); + register(); + } + } + // We failed to rejoin the channel + // ERR_INVITEONLYCHAN || ERR_CHANNELISFULL || ERR_NOSUCHCHANNEL || + // ERR_BANNEDFROMCHAN || ERR_BADCHANNELKEY || ERR_BADCHANMASK || + // ERR_TOOMANYCHANNELS + else if (id.equals("473") || id.equals("471") || id.equals("403") || id.equals("474") || id.equals("475") + || id.equals("476") || id.equals("405")) { + String cname = params[1]; + Channel channel = getChannel(cname, false); + if (channel != null) { + sendStatusMessage(getText(IRCTextProvider.SERVER_AUTOREJOIN_FAILED, cname)); + _listeners.sendEvent("sourceRemoved", channel, this); + deleteChannel(cname); + } + } + // We're performing an action on a channel we're not into + else if (id.equals("442")) // ERR_NOTONCHANNEL + { + Channel chan = getChannel(params[1], false); + if (chan != null) { + _listeners.sendEvent("sourceRemoved", chan, this); + deleteChannel(chan.getName()); + } + } else { + /* + * String toSend=""; for(int i=1;i 1) { + c.partNick(nick, params[1]); + } else { + c.partNick(nick, ""); + } + if (nick.equals(getNick())) { + _listeners.sendEvent("sourceRemoved", c, this); + deleteChannel(c.getName()); + } + } + } else if (command.equals("kick")) { + Channel c = getChannel(params[0], false); + if (c != null) { + String target = params[1]; + String reason = ""; + if (params.length > 2) + reason = params[2]; + c.kickNick(target, nick, reason); + if (target.equals(getNick())) { + if (_ircConfiguration.getB("autorejoin")) { + c.report(getText(IRCTextProvider.SERVER_AUTOREJOIN_ATTEMPT, c.getName())); + execute("join " + params[0]); + } else { + _listeners.sendEvent("sourceRemoved", c, this); + deleteChannel(c.getName()); + } + } + } + } else if (command.equals("topic")) { + Channel c = getChannel(params[0], false); + if (c != null) + c.setTopic(params[1], nick); + } else if (command.equals("mode")) { + String full = ""; + for (int i = 1; i < params.length; i++) + full += params[i] + " "; + if (isChannel(params[0])) { + Channel c = getChannel(params[0], false); + if (c != null) { + MultiModeHandler h = new MultiModeHandler(full, _globalModes, _nickModes); + while (!h.terminated()) { + h.next(); + if (h.isPrefix() || h.isModeA()) { + c.applyUserMode(h.getParameter(), h.getMode(), nick); + } else { + if (h.hasParameter()) + c.applyMode(h.getMode() + " " + h.getParameter(), nick); + else + c.applyMode(h.getMode(), nick); + } + } + } + } else if (nick.equals(getNick())) { + _mode.apply(full); + if (_status != null) + _status.modeChanged(getMode()); + } + } else if (command.equals("nick")) { + if (nick.equals(getNick())) { + _nick = params[0]; + if (_status != null) + _status.nickChanged(getNick()); + } + globalNickChange(nick, params[0]); + } else if (command.equals("quit")) { + if (params.length > 0) + globalNickRemove(nick, params[0]); + else + globalNickRemove(nick, ""); + } else if (command.equals("ping")) { + execute("pong :" + params[0]); + // sendStatusMessage("\3"+"3"+"PING? PONG!"); + } else if (command.equals("invite")) { + String invited = params[0]; + String channel = params[1]; + if (invited.equals(getNick())) { + if (_status != null) + _status.invited(channel, nick); + + // if(_defaultSource!=null) + // _defaultSource.report(getText(IRCTextProvider.SOURCE_YOU_INVITED,nick,channel)); + } + } else if (command.equals("error")) { + sendStatusMessage(getText(IRCTextProvider.SERVER_ERROR, params[0])); + } else { + // System.out.println("("+command+") "+prefix+" -> "+toSend); + } + + } + + @Override + public String getNick() { + return _nick; + } + + @Override + public String getUserName() { + return _userName; + } + + /** + * Get the current status mode. + * + * @return status mode. + */ + public String getMode() { + return _mode.getMode(); + } + + @Override + public void say(String destination, String str) { + execute("PRIVMSG " + destination + " :" + str); + } + + @Override + public void execute(String str) { + int pos = str.indexOf(' '); + if (pos >= 0) { + String cmd = str.substring(0, pos).toLowerCase(java.util.Locale.ENGLISH); + if (cmd.equals("join")) { + String rem = str.substring(pos + 1); + pos = rem.indexOf(' '); + if (pos >= 0) + rem = rem.substring(0, pos); + if (!_ircConfiguration.mayJoin(rem)) + return; + } else if (cmd.equals("part")) { + String rem = str.substring(pos + 1); + pos = rem.indexOf(' '); + if (pos >= 0) + rem = rem.substring(0, pos); + if (!_ircConfiguration.mayLeave(rem)) + return; + } + } + + pos = str.indexOf(' '); + if (pos > 0) { + String cmd = str.substring(0, pos).toUpperCase(java.util.Locale.ENGLISH); + String param = str.substring(pos + 1); + str = cmd + " " + param; + } else { + str = str.toUpperCase(java.util.Locale.ENGLISH); + } + sendString(str); + } + + private void sendString(String str) { + try { + _protocol.sendString(str); + } catch (Exception e) { + sendStatusMessage(getText(IRCTextProvider.SERVER_ERROR, e.getMessage())); + } + } + +} diff --git a/src/main/java/irc/IRCSource.java b/src/main/java/irc/IRCSource.java new file mode 100644 index 0000000..585e4be --- /dev/null +++ b/src/main/java/irc/IRCSource.java @@ -0,0 +1,57 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +/** + * An IRC source. + */ +public abstract class IRCSource extends Source { + /** + * Create a new IRCSource. + * + * @param config + * the global configuration. + * @param s + * the source IRCServer. + */ + public IRCSource(IRCConfiguration config, IRCServer s) { + super(config, s); + } + + /** + * Get the IRCServer. + * + * @return the IRCServer this source is bound to. + */ + public IRCServer getIRCServer() { + return (IRCServer) _server; + } + +} diff --git a/src/main/java/irc/IRCTextProvider.java b/src/main/java/irc/IRCTextProvider.java new file mode 100644 index 0000000..222a0df --- /dev/null +++ b/src/main/java/irc/IRCTextProvider.java @@ -0,0 +1,287 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +/** + * Text constants for the IRC engine. + */ +public interface IRCTextProvider { + /** + * Not on a channel + */ + public static final int INTERPRETOR_NOT_ON_CHANNEL = 0x001; + /** + * %1 : unknown dcc subcommand + */ + public static final int INTERPRETOR_UNKNOWN_DCC = 0x002; + /** + * %1 : insufficient parameters + */ + public static final int INTERPRETOR_INSUFFICIENT_PARAMETERS = 0x003; + /** + * %1 : unable to perform in current context + */ + public static final int INTERPRETOR_BAD_CONTEXT = 0x004; + /** + * Cannot send CTCP codes via DCC Chat + */ + public static final int INTERPRETOR_CANNOT_CTCP_IN_DCCCHAT = 0x005; + /** + * %1 : unknown config subcommand + */ + public static final int INTERPRETOR_UNKNOWN_CONFIG = 0x006; + /** + * Timestamp enabled + */ + public static final int INTERPRETOR_TIMESTAMP_ON = 0x007; + /** + * Timestamp disabled + */ + public static final int INTERPRETOR_TIMESTAMP_OFF = 0x008; + /** + * Graphical smileys enabled + */ + public static final int INTERPRETOR_SMILEYS_ON = 0x009; + /** + * Graphical smileys disabled + */ + public static final int INTERPRETOR_SMILEYS_OFF = 0x00A; + /** + * Now ignoring %1 + */ + public static final int INTERPRETOR_IGNORE_ON = 0x00B; + /** + * Not ignoring %1 anymore + */ + public static final int INTERPRETOR_IGNORE_OFF = 0x00C; + /** + * Multiserver support is disabled + */ + public static final int INTERPRETOR_MULTISERVER_DISABLED = 0x00D; + + /** + * Waiting for incoming connection... + */ + public static final int DCC_WAITING_INCOMING = 0x101; + /** + * Unable to open connection : %1 + */ + public static final int DCC_UNABLE_TO_OPEN_CONNECTION = 0x102; + /** + * DCC Connection established + */ + public static final int DCC_CONNECTION_ESTABLISHED = 0x103; + /** + * Connection closed + */ + public static final int DCC_CONNECTION_CLOSED = 0x104; + /** + * Error : %1 + */ + public static final int DCC_ERROR = 0x105; + /** + * %1 : unable to send to %2 + */ + public static final int DCC_UNABLE_TO_SEND_TO = 0x106; + /** + * Unable to execute command from current context + */ + public static final int DCC_BAD_CONTEXT = 0x107; + /** + * Not connected + */ + public static final int DCC_NOT_CONNECTED = 0x108; + /** + * Unable to initialize passive mode + */ + public static final int DCC_UNABLE_PASSIVE_MODE = 0x109; + /** + * [%1 PING reply] : %2 seconds + */ + public static final int CTCP_PING_REPLY = 0x10A; + /** + * Stream closed + */ + public static final int DCC_STREAM_CLOSED = 0x10B; + + /** + * Failed to launch Ident server : %1 + */ + public static final int IDENT_FAILED_LAUNCH = 0x201; + /** + * Ident request from %1 + */ + public static final int IDENT_REQUEST = 0x202; + /** + * Error occurred + */ + public static final int IDENT_ERROR = 0x203; + /** + * + */ + public static final int IDENT_REPLIED = 0x204; + /** + * default user + */ + public static final int IDENT_DEFAULT_USER = 0x205; + /** + * No user for request + */ + public static final int IDENT_NO_USER = 0x206; + /** + * Ident server running on port %1 + */ + public static final int IDENT_RUNNING_ON_PORT = 0x207; + /** + * Ident server leaving : %1 + */ + public static final int IDENT_LEAVING = 0x208; + /** + * none + */ + public static final int IDENT_NONE = 0x209; + /** + * unknown + */ + public static final int IDENT_UNKNOWN = 0x20A; + /** + * Undefined result + */ + public static final int IDENT_UNDEFINED = 0x20B; + + /** + * Save file as + */ + public static final int FILE_SAVEAS = 0x301; + + /** + * About + */ + public static final int ABOUT_ABOUT = 0x401; + /** + * Programming + */ + public static final int ABOUT_PROGRAMMING = 0x402; + /** + * Design + */ + public static final int ABOUT_DESIGN = 0x403; + /** + * Thanks to + */ + public static final int ABOUT_THANKS = 0x404; + /** + * for support, ideas and testing + */ + public static final int ABOUT_SUPPORT = 0x405; + /** + * This software is licensed under the GPL license + */ + public static final int ABOUT_GPL = 0x406; + + /** + * Unable to connect : %1 + */ + public static final int SERVER_UNABLE_TO_CONNECT = 0x501; + /** + * Unable to connect to %1 : currently trying to connect to %2 + */ + public static final int SERVER_UNABLE_TO_CONNECT_STILL = 0x502; + /** + * Disconnecting from %1 + */ + public static final int SERVER_DISCONNECTING = 0x503; + /** + * Connecting... + */ + public static final int SERVER_CONNECTING = 0x504; + /** + * Not connected + */ + public static final int SERVER_NOT_CONNECTED = 0x505; + /** + * Logging in... + */ + public static final int SERVER_LOGIN = 0x506; + /** + * Disconnected from %1 + */ + public static final int SERVER_DISCONNECTED = 0x507; + /** + * Error : %1 + */ + public static final int SERVER_ERROR = 0x508; + /** + * Attempting to rejoin channel %1... + */ + public static final int SERVER_AUTOREJOIN_ATTEMPT = 0x0509; + /** + * Unable to rejoin channel %1 + */ + public static final int SERVER_AUTOREJOIN_FAILED = 0x050a; + + /** + * Change nick to + */ + public static final int GUI_CHANGE_NICK = 0x71A; + /** + * Copy text + */ + public static final int GUI_COPY_WINDOW = 0x71B; + /** + * Warning + */ + public static final int GUI_DCC_CHAT_WARNING_TITLE = 0x71C; + /** + * Do you want to accept DCC chat from %1? + */ + public static final int GUI_DCC_CHAT_WARNING_TEXT = 0x71D; + /** + * Boy, %1 years old, %2 + */ + public static final int ASL_MALE = 0x801; + /** + * Girl, %1 years old, %2 + */ + public static final int ASL_FEMALE = 0x802; + /** + * %1 years old from %2 + */ + public static final int ASL_UNKNOWN = 0x803; + + /** + * %1 has been idle for %2 + */ + public static final int REPLY_IDLE = 0x901; + /** + * %1 connected on %2 + */ + public static final int REPLY_SIGNON = 0x902; +} diff --git a/src/main/java/irc/ImageLoader.java b/src/main/java/irc/ImageLoader.java new file mode 100644 index 0000000..16d317a --- /dev/null +++ b/src/main/java/irc/ImageLoader.java @@ -0,0 +1,46 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +import java.awt.Image; + +/** + * Image loader. + */ +public interface ImageLoader { + /** + * Load the given image. + * + * @param source + * image to load. + * @return loaded image, or null if unable. + */ + public Image getImage(String source); +} diff --git a/src/main/java/irc/Interpretor.java b/src/main/java/irc/Interpretor.java new file mode 100644 index 0000000..3fc391e --- /dev/null +++ b/src/main/java/irc/Interpretor.java @@ -0,0 +1,78 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +/** + * A source interpretor. + */ +public interface Interpretor { + /** + * Send the given string to the server. + * + * @param s + * the source. + * @param str + * the string to send. + */ + public void sendString(Source s, String str); + + /** + * Set the next interpretor. + * + * @param next + * interpretor to use. May be null. + */ + public void setNextInterpretor(Interpretor next); + + /** + * Get the next interpretor. + * + * @return the next interpretor, or null if this interpretor is the last. + */ + public Interpretor getNextInterpretor(); + + /** + * Check whether the given interpretor is already in the interpretor chain. + * + * @param in + * the interpretor to check. + * @return true if in is in the chain, false otherwise. + */ + public boolean isInside(Interpretor in); + + /** + * Add the given interpretor at the end of this interpretor chain. If in is + * already in the chain, nothing is done. + * + * @param in + * interpretor to add. + */ + public void addLast(Interpretor in); +} diff --git a/src/main/java/irc/LinkedList.java b/src/main/java/irc/LinkedList.java new file mode 100644 index 0000000..600d6e3 --- /dev/null +++ b/src/main/java/irc/LinkedList.java @@ -0,0 +1,112 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +/** + * LinkedListNode. + */ +class LinkedListNode { + /** + * Next node. + */ + public LinkedListNode next = null; + /** + * Previous node. + */ + public LinkedListNode prev = null; + /** + * Node content. + */ + public Object item = null; +} + +/** + * A very simple linked list. + */ +public class LinkedList { + private int _size; + private LinkedListNode _head; + private LinkedListNode _tail; + + /** + * Create a new, empty linked list. + */ + public LinkedList() { + _head = new LinkedListNode(); + _tail = new LinkedListNode(); + _head.next = _tail; + _tail.prev = _head; + _size = 0; + } + + /** + * Get the size of the list. + * + * @return list size. + */ + public int size() { + return _size; + } + + /** + * Add the given object at the end of the list. + * + * @param obj + * object to add. + */ + public void addLast(Object obj) { + LinkedListNode node = new LinkedListNode(); + node.item = obj; + node.next = _tail; + node.prev = _tail.prev; + node.prev.next = node; + node.next.prev = node; + _size++; + } + + /** + * Remove and return the first object of the list. + * + * @return removed object. + * @throws RuntimeException + * if list is empty. + */ + public Object removeFirst() { + if (_size == 0) + throw new RuntimeException("List empty"); + LinkedListNode node = _head.next; + + node.next.prev = _head; + _head.next = node.next; + _size--; + return node.item; + } + +} diff --git a/src/main/java/irc/ListHandler.java b/src/main/java/irc/ListHandler.java new file mode 100644 index 0000000..0250939 --- /dev/null +++ b/src/main/java/irc/ListHandler.java @@ -0,0 +1,114 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +import java.util.Hashtable; +import java.util.StringTokenizer; + +/** + * Handling for unbound list of items. + */ +public class ListHandler { + private boolean _baseAll; + private Hashtable _list; + private String _orig; + + /** + * Create a new list of items. + * + * @param list + * item list. Syntax is : "" or "none+item1+item2+item3+..." or + * "all-item1-item2-item3-..." If list is empty, it is equivalent to + * "all". Items containing + or - characters can be used by replacing + * them by \+ or \-. The \ character may be entenred using \\ syntax. + */ + public ListHandler(String list) { + _orig = list; + list = convert(list); + _baseAll = true; + _list = new Hashtable(); + StringTokenizer st = new StringTokenizer(list, "\1\2", true); + if (!st.hasMoreTokens()) + return; + String base = st.nextToken(); + if (base.equals("none")) + _baseAll = false; + while (st.hasMoreTokens()) { + String mod = st.nextToken(); + if (mod.equals("\1")) + mod = "-"; + else if (mod.equals("\2")) + mod = "+"; + if (!st.hasMoreTokens()) + break; + String token = st.nextToken().toLowerCase(java.util.Locale.ENGLISH); + _list.put(token, mod); + } + } + + private String convert(String txt) { + String ans = ""; + for (int i = 0; i < txt.length(); i++) { + char c = txt.charAt(i); + if (c == '-') + c = '\1'; + else if (c == '+') + c = '\2'; + else if (c == '\\' && (i != txt.length() - 1)) { + i++; + c = txt.charAt(i); + } + ans += c; + } + return ans; + } + + /** + * Test wether the given item is in the list. + * + * @param item + * item to check. + * @return true if item is in the list, false otherwise. + */ + public boolean inList(String item) { + item = item.toLowerCase(java.util.Locale.ENGLISH); + String mod = (String) _list.get(item); + if (mod == null) + return _baseAll; + if (mod.equals("+")) + return true; + return false; + } + + @Override + public String toString() { + return _orig; + } +} diff --git a/src/main/java/irc/ListenerGroup.java b/src/main/java/irc/ListenerGroup.java new file mode 100644 index 0000000..2d2a1f7 --- /dev/null +++ b/src/main/java/irc/ListenerGroup.java @@ -0,0 +1,310 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +import java.util.Enumeration; +import java.util.Vector; + +/** + * Handles a group of listeners. + */ +public class ListenerGroup { + private Vector _listeners; + + /** + * Create a new ListenerGroup. + */ + public ListenerGroup() { + _listeners = new Vector(); + } + + /** + * Add a listener to the group. + * + * @param listener + * listener to add. + */ + public synchronized void addListener(Object listener) { + _listeners.insertElementAt(listener, _listeners.size()); + } + + /** + * Remove a listener from the group. + * + * @param listener + * listener to remove. + */ + public synchronized void removeListener(Object listener) { + for (int i = 0; i < _listeners.size(); i++) { + if (_listeners.elementAt(i) == listener) { + _listeners.removeElementAt(i); + return; + } + } + } + + /** + * Send an event to all listeners in the group, in the event thread. + * + * @param method + * method to call on each listener. + * @param params + * parameters to pass to the called method. + */ + public synchronized void sendEventAsync(String method, Object[] params) { + Enumeration e = _listeners.elements(); + while (e.hasMoreElements()) + EventDispatcher.dispatchEventAsync(e.nextElement(), method, params); + } + + /** + * Send an event to all listeners in the group, in the event thread. + * + * @param method + * method to call on each listener. + */ + public synchronized void sendEventAsync(String method) { + sendEventAsync(method, new Object[0]); + } + + /** + * Send an event to all listeners in the group, in the event thread. + * + * @param method + * method to call on each listener. + * @param param1 + * first parameter to pass to the called method. + */ + public synchronized void sendEventAsync(String method, Object param1) { + Object[] p = { param1 }; + sendEventAsync(method, p); + } + + /** + * Send an event to all listeners in the group, in the event thread. + * + * @param method + * method to call on each listener. + * @param param1 + * first parameter to pass to the called method. + * @param param2 + * second parameter to pass to the called method. + */ + public synchronized void sendEventAsync(String method, Object param1, Object param2) { + Object[] p = { param1, param2 }; + sendEventAsync(method, p); + } + + /** + * Send an event to all listeners in the group, in the event thread. + * + * @param method + * method to call on each listener. + * @param param1 + * first parameter to pass to the called method. + * @param param2 + * second parameter to pass to the called method. + * @param param3 + * third parameter to pass to the called method. + */ + public synchronized void sendEventAsync(String method, Object param1, Object param2, Object param3) { + Object[] p = { param1, param2, param3 }; + sendEventAsync(method, p); + } + + /** + * Send an event to all listeners in the group. The event will be processed + * synchrounsly in the current thread. + * + * @param method + * method to call on each listener. + * @param params + * parameters to pass to the called method. + * @return array of returned resuluts for each method call. + * @deprecated use sendEventEx instead. + */ + @Deprecated + public synchronized Object[] sendEvent(String method, Object[] params) { + try { + return sendEventEx(method, params); + } catch (Throwable ex) { + ex.printStackTrace(); + return null; + } + } + + /** + * Send an event to all listeners in the group. The event will be processed + * synchrounsly in the current thread. + * + * @param method + * method to call on each listener. + * @param params + * parameters to pass to the called method. + * @return array of returned resuluts for each method call. + * @throws Throwable + */ + public synchronized Object[] sendEventEx(String method, Object[] params) throws Throwable { + Object[] res = new Object[_listeners.size()]; + int i = 0; + Enumeration e = _listeners.elements(); + while (e.hasMoreElements()) { + try { + res[i++] = EventDispatcher.dispatchEventSyncEx(e.nextElement(), method, params); + } catch (Throwable ex) { + ex.printStackTrace(); + } + } + return res; + } + + /** + * Send an event to all listeners in the group in the current thread. + * + * @param method + * method to call on each listener. + * @return array of returned resuluts for each method call. + */ + public synchronized Object[] sendEvent(String method) { + return sendEvent(method, new Object[0]); + } + + /** + * Send an event to all listeners in the group in the current thread. + * + * @param method + * method to call on each listener. + * @param param1 + * first parameter to pass to the called method. + * @return array of returned resuluts for each method call. + */ + public synchronized Object[] sendEvent(String method, Object param1) { + Object[] p = { param1 }; + return sendEvent(method, p); + } + + /** + * Send an event to all listeners in the group in the current thread. + * + * @param method + * method to call on each listener. + * @param param1 + * first parameter to pass to the called method. + * @param param2 + * second parameter to pass to the called method. + * @return array of returned resuluts for each method call. + */ + public synchronized Object[] sendEvent(String method, Object param1, Object param2) { + Object[] p = { param1, param2 }; + return sendEvent(method, p); + } + + /** + * Send an event to all listeners in the group in the current thread. + * + * @param method + * method to call on each listener. + * @param param1 + * first parameter to pass to the called method. + * @param param2 + * second parameter to pass to the called method. + * @param param3 + * third parameter to pass to the called method. + * @return array of returned resuluts for each method call. + */ + public synchronized Object[] sendEvent(String method, Object param1, Object param2, Object param3) { + Object[] p = { param1, param2, param3 }; + return sendEvent(method, p); + } + + /** + * Send an event to all listeners in the group in the current thread. + * + * @param method + * method to call on each listener. + * @return array of returned resuluts for each method call. + * @throws Throwable + */ + public synchronized Object[] sendEventEx(String method) throws Throwable { + return sendEventEx(method, new Object[0]); + } + + /** + * Send an event to all listeners in the group in the current thread. + * + * @param method + * method to call on each listener. + * @param param1 + * first parameter to pass to the called method. + * @return array of returned resuluts for each method call. + * @throws Throwable + */ + public synchronized Object[] sendEventEx(String method, Object param1) throws Throwable { + Object[] p = { param1 }; + return sendEventEx(method, p); + } + + /** + * Send an event to all listeners in the group in the current thread. + * + * @param method + * method to call on each listener. + * @param param1 + * first parameter to pass to the called method. + * @param param2 + * second parameter to pass to the called method. + * @return array of returned resuluts for each method call. + * @throws Throwable + */ + public synchronized Object[] sendEventEx(String method, Object param1, Object param2) throws Throwable { + Object[] p = { param1, param2 }; + return sendEventEx(method, p); + } + + /** + * Send an event to all listeners in the group in the current thread. + * + * @param method + * method to call on each listener. + * @param param1 + * first parameter to pass to the called method. + * @param param2 + * second parameter to pass to the called method. + * @param param3 + * third parameter to pass to the called method. + * @return array of returned resuluts for each method call. + * @throws Throwable + */ + public synchronized Object[] sendEventEx(String method, Object param1, Object param2, Object param3) throws Throwable { + Object[] p = { param1, param2, param3 }; + return sendEventEx(method, p); + } + +} diff --git a/src/main/java/irc/LocalFileHandler.java b/src/main/java/irc/LocalFileHandler.java new file mode 100644 index 0000000..df19e58 --- /dev/null +++ b/src/main/java/irc/LocalFileHandler.java @@ -0,0 +1,48 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; + +/** + * Local file handler. + */ +public class LocalFileHandler implements FileHandler { + @Override + public InputStream getInputStream(String fileName) { + try { + return new FileInputStream(new File(fileName)); + } catch (Exception ex) { + return null; + } + } +} diff --git a/src/main/java/irc/MessageServerListener.java b/src/main/java/irc/MessageServerListener.java new file mode 100644 index 0000000..eed9b5a --- /dev/null +++ b/src/main/java/irc/MessageServerListener.java @@ -0,0 +1,50 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +/** + * A message server listener. + */ +public interface MessageServerListener { + /** + * A new message has been received from the irc server. + * + * @param prefix + * message prefix. + * @param command + * message command. + * @param params + * message parameters. + * @param server + * the source IRCServer. + * @return true if the message has been handled, false otherwise. + */ + public Boolean messageReceived(String prefix, String command, String params[], IRCServer server); +} diff --git a/src/main/java/irc/ModeHandler.java b/src/main/java/irc/ModeHandler.java new file mode 100644 index 0000000..90f2725 --- /dev/null +++ b/src/main/java/irc/ModeHandler.java @@ -0,0 +1,227 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +import java.util.Vector; + +/** + * IRC mode handler. + */ +public class ModeHandler { + private String _mode; + private Vector _parameters; + private char[][] _modes; + private char[] _prefix; + + /** + * Create a new ModeHandler with empty mode. + * + * @param modes + * A,B,C,D known modes. This is an array of four arrays of chars. + * @param prefix + * prefix modes. + */ + public ModeHandler(char[][] modes, char[] prefix) { + this("", modes, prefix); + } + + /** + * Create a new ModeHandler with given mode. + * + * @param mode + * initial mode. + * @param modes + * A,B,C,D know modes. + * @param prefix + * prefix modes. + */ + public ModeHandler(String mode, char[][] modes, char[] prefix) { + _modes = modes; + _prefix = prefix; + _mode = ""; + _parameters = new Vector(); + if (mode.startsWith("+")) + mode = mode.substring(1); + apply("+" + mode); + } + + /** + * Reset current mode. + */ + public void reset() { + _mode = ""; + } + + /** + * Get password (+k), if defined. + * + * @return password. + */ + public String getPassword() { + if (hasMode('k')) + return findParameter('k'); + return ""; + } + + /** + * Get user limit (+l), if defined. + * + * @return the user limit. + */ + public int getLimit() { + if (hasMode('l')) + return new Integer(findParameter('l')).intValue(); + return 0; + } + + private boolean inside(char[] list, char c) { + for (int i = 0; i < list.length; i++) + if (list[i] == c) + return true; + return false; + } + + private String findParameter(char k) { + int index = getParameterIndex(k); + if (index >= 0) + return (String) _parameters.elementAt(index); + return ""; + } + + private boolean hasParameter(boolean positive, char c) { + if (inside(_prefix, c)) + return false; + else if (inside(_modes[0], c)) + return true; + else if (inside(_modes[1], c)) + return true; + else if (inside(_modes[2], c)) + return positive; + else + return false; + } + + private int getParameterIndex(char k) { + if (_parameters.size() == 0) + return -1; + int index = 0; + for (int i = 0; i < _mode.length(); i++) { + char c = _mode.charAt(i); + if (hasParameter(true, c)) { + if (c == k) + return index; + index++; + if (index >= _parameters.size()) + return -1; + } else { + if (c == k) + return -1; + } + } + return -1; + } + + private void addMode(char mode, String param) { + if (hasMode(mode)) + removeMode(mode, param); + _mode += mode; + if (hasParameter(true, mode)) + _parameters.insertElementAt(param, _parameters.size()); + } + + private void removeMode(char mode, String param) { + if (!hasMode(mode)) + return; + if (hasParameter(true, mode)) + _parameters.removeElementAt(getParameterIndex(mode)); + int pos = _mode.indexOf(mode); + _mode = _mode.substring(0, pos) + _mode.substring(pos + 1); + } + + private void applyOne(boolean positive, char mode, String param) { + if (positive) + addMode(mode, param); + else + removeMode(mode, param); + } + + /** + * Apply a new mode on the current mode. + * + * @param mode + * new mode to apply. + */ + public void apply(String mode) { + String[] params = (new StringParser()).parseString(mode); + boolean positive = true; + int index = 0; + + for (int i = 0; i < params[0].length(); i++) { + char c = params[0].charAt(i); + if (c == '+') { + positive = true; + } else if (c == '-') { + positive = false; + } else { + String param = ""; + if (hasParameter(positive, c)) { + index++; + if (index >= params.length) + return; + param = params[index]; + } + applyOne(positive, c, param); + } + } + } + + /** + * Test wether the given mode is set. + * + * @param mode + * mode to test. + * @return true if mode is set, false otherwise. + */ + public boolean hasMode(char mode) { + return _mode.indexOf(mode) != -1; + } + + /** + * Get a string representation of the current mode. + * + * @return string representation of current mode. + */ + public String getMode() { + String ans = _mode; + for (int i = 0; i < _parameters.size(); i++) + ans += " " + _parameters.elementAt(i); + return ans; + } +} diff --git a/src/main/java/irc/MultiModeHandler.java b/src/main/java/irc/MultiModeHandler.java new file mode 100644 index 0000000..6003f62 --- /dev/null +++ b/src/main/java/irc/MultiModeHandler.java @@ -0,0 +1,175 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +/** + * Combined IRC mode handler. + */ +public class MultiModeHandler { + private String[] _parameters; + private char[][] _modes; + private char[] _prefix; + private int _paramIndex; + private int _codeIndex; + private boolean _positive; + + private String _currentMode; + private char _currentModeChar; + private boolean _currentHasParameter; + private String _currentParameter; + private boolean _currentPrefix; + + /** + * Create a new ModeHandler with empty mode. + * + * @param code + * initial code. + * @param modes + * A,B,C,D know modes. This is an array of four arrays of chars. + * @param prefix + * prefix modes. + */ + public MultiModeHandler(String code, char[][] modes, char prefix[]) { + _modes = modes; + _prefix = prefix; + _parameters = (new StringParser()).parseString(code); + _paramIndex = 1; + _codeIndex = 0; + _positive = true; + } + + /** + * Check whether there is more modes to handle. + * + * @return true if there is more modes to handle, false otherwise. + */ + public boolean terminated() { + return (_codeIndex == _parameters[0].length()); + } + + /** + * Handle the next mode. This method must be called before first call to any + * other getter's method. + */ + public void next() { + if (terminated()) + return; + char c = _parameters[0].charAt(_codeIndex++); + if (c == '-') { + _positive = false; + next(); + return; + } + if (c == '+') { + _positive = true; + next(); + return; + } + _currentMode = "-"; + if (_positive) + _currentMode = "+"; + _currentMode += c; + _currentModeChar = c; + if (hasParameter(_positive, c) && _paramIndex < _parameters.length) { + _currentHasParameter = true; + _currentParameter = _parameters[_paramIndex++]; + } else { + _currentHasParameter = false; + _currentParameter = ""; + } + _currentPrefix = inside(_prefix, c); + } + + private boolean inside(char[] list, char c) { + for (int i = 0; i < list.length; i++) + if (list[i] == c) + return true; + return false; + } + + /** + * Get current mode to handle. + * + * @return mode. + */ + public String getMode() { + return _currentMode; + } + + /** + * Check whether the current mode has a parameter. + * + * @return true if the mode has a parameter, false otherwise. + */ + public boolean hasParameter() { + return _currentHasParameter; + } + + /** + * Get the current parameter, if defined. + * + * @return the current parameter, if defined. + */ + public String getParameter() { + return _currentParameter; + } + + /** + * Check wether the current mode comes from the prefix list instead of the + * A,B,C,D list. + * + * @return true if the mode is a prefix mode. + */ + public boolean isPrefix() { + return _currentPrefix; + } + + /** + * Check wether the current mode comes from the A list. + * + * @return true if the mode is a A code. + */ + public boolean isModeA() { + return inside(_modes[0], _currentModeChar); + } + + private boolean hasParameter(boolean positive, char c) { + if (inside(_prefix, c)) + return true; + else if (inside(_modes[0], c)) + return true; + else if (inside(_modes[1], c)) + return true; + else if (inside(_modes[2], c)) + return positive; + else + return false; + } +} diff --git a/src/main/java/irc/NotEnoughParametersException.java b/src/main/java/irc/NotEnoughParametersException.java new file mode 100644 index 0000000..d2f5357 --- /dev/null +++ b/src/main/java/irc/NotEnoughParametersException.java @@ -0,0 +1,46 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +/** + * Exception thrown by interpretor if not enough parameters are provided for a + * command. + */ +public class NotEnoughParametersException extends Exception { + /** + * Create a new NotEnoughParametersException. + * + * @param msg + * message. + */ + public NotEnoughParametersException(String msg) { + super(msg); + } +} diff --git a/src/main/java/irc/NullImageLoader.java b/src/main/java/irc/NullImageLoader.java new file mode 100644 index 0000000..ea3352a --- /dev/null +++ b/src/main/java/irc/NullImageLoader.java @@ -0,0 +1,42 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +import java.awt.Image; + +/** + * Null image loader. This class always fail to load image. + */ +public class NullImageLoader implements ImageLoader { + @Override + public Image getImage(String source) { + return null; + } +} diff --git a/src/main/java/irc/NullInterpretor.java b/src/main/java/irc/NullInterpretor.java new file mode 100644 index 0000000..840f723 --- /dev/null +++ b/src/main/java/irc/NullInterpretor.java @@ -0,0 +1,47 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +/** + * Null interpretor. This interpretor does nothing more than the root + * interpretor. + */ +public class NullInterpretor extends RootInterpretor { + /** + * Create a new NullInterpretor. + * + * @param config + * global irc configuration. + */ + public NullInterpretor(IRCConfiguration config) { + super(config); + } + +} diff --git a/src/main/java/irc/NullServer.java b/src/main/java/irc/NullServer.java new file mode 100644 index 0000000..f03141b --- /dev/null +++ b/src/main/java/irc/NullServer.java @@ -0,0 +1,126 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2005 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +import java.util.Enumeration; +import java.util.Vector; + +/** + * The null-server class. + */ +public class NullServer implements Server { + /** + * Create a new NullServer. + */ + public NullServer() { + // empty default implementation + } + + @Override + public void addServerListener(ServerListener l) { + // empty default implementation + } + + @Override + public void removeServerListener(ServerListener l) { + // empty default implementation + } + + @Override + public void say(String destination, String str) { + // empty default implementation + } + + @Override + public void execute(String str) { + // empty default implementation + } + + @Override + public void sendStatusMessage(String str) { + // empty default implementation + } + + @Override + public String getNick() { + return ""; + } + + @Override + public String getUserName() { + return ""; + } + + @Override + public String getServerName() { + return "Null"; + } + + @Override + public void connect() { + // empty default implementation + } + + @Override + public void disconnect() { + // empty default implementation + } + + @Override + public boolean isConnected() { + return false; + } + + @Override + public void setDefaultSource(Source def) { + // empty default implementation + } + + @Override + public void leave() { + // empty default implementation + } + + @Override + public void enumerateSourcesAsCreated(ServerListener lis) { + // empty default implementation + } + + @Override + public void enumerateSourcesAsRemoved(ServerListener lis) { + // empty default implementation + } + + @Override + public Enumeration getSources() { + return new Vector().elements(); + } + +} diff --git a/src/main/java/irc/NullSoundHandler.java b/src/main/java/irc/NullSoundHandler.java new file mode 100644 index 0000000..a854791 --- /dev/null +++ b/src/main/java/irc/NullSoundHandler.java @@ -0,0 +1,40 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2005 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +/** + * Null sound handler. This handler never plays sounds. + */ +public class NullSoundHandler implements SoundHandler { + @Override + public void playSound(String name) { + // empty default implementation + } +} diff --git a/src/main/java/irc/NullURLHandler.java b/src/main/java/irc/NullURLHandler.java new file mode 100644 index 0000000..686473d --- /dev/null +++ b/src/main/java/irc/NullURLHandler.java @@ -0,0 +1,57 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2005 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +/** + * Null URLHandler. This handler always fail to perform request operations. + */ +public class NullURLHandler implements URLHandler { + /** + * Create a new NullURLHandler. + */ + public NullURLHandler() { + // empty default implementation + } + + @Override + public void stateURL(String url) { + // empty default implementation + } + + @Override + public void openURL(String url) { + openURL(url, "_blank"); + } + + @Override + public void openURL(String url, String target) { + // empty default implementation + } +} diff --git a/src/main/java/irc/ParameterMixer.java b/src/main/java/irc/ParameterMixer.java new file mode 100644 index 0000000..8dce29a --- /dev/null +++ b/src/main/java/irc/ParameterMixer.java @@ -0,0 +1,63 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +/** + * The parameter mixer, designed to mix parameters from several other parameter + * providers. + */ +public class ParameterMixer implements ParameterProvider { + private ParameterProvider _p1; + private ParameterProvider _p2; + + /** + * Creates a new parameter mixer, combining parameters from the two given + * parameter providers. If a parameter is defined in both providers, the first + * one will have priority. + * + * @param p1 + * the first parameter provider. + * @param p2 + * the second parameter provider. + */ + public ParameterMixer(ParameterProvider p1, ParameterProvider p2) { + _p1 = p1; + _p2 = p2; + } + + @Override + public String getParameter(String name) { + String ans = _p1.getParameter(name); + if (ans == null) + return _p2.getParameter(name); + return ans; + } + +} diff --git a/src/main/java/irc/ParameterProvider.java b/src/main/java/irc/ParameterProvider.java new file mode 100644 index 0000000..610c701 --- /dev/null +++ b/src/main/java/irc/ParameterProvider.java @@ -0,0 +1,44 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +/** + * Parameter provider interface. + */ +public interface ParameterProvider { + /** + * Get the given parameter value. The parameter name is case insensitive. + * + * @param name + * parameter name. + * @return parameter value, or null if the parameter is not defined. + */ + public String getParameter(String name); +} diff --git a/src/main/java/irc/PluginManager.java b/src/main/java/irc/PluginManager.java new file mode 100644 index 0000000..e3c2b05 --- /dev/null +++ b/src/main/java/irc/PluginManager.java @@ -0,0 +1,53 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +/** + * The plugin manager interface. + */ +public interface PluginManager { + /** + * Load the given plugin. + * + * @param str + * the plugin to load. + * @return true if plugin is loaded, false otherwise. + */ + public boolean loadPlugin(String str); + + /** + * Unload the given plugin. + * + * @param str + * the plugin to unload. + * @return true if plugin is unloaded, false otherwise. + */ + public boolean unloadPlugin(String str); +} diff --git a/src/main/java/irc/PrefixedParameterProvider.java b/src/main/java/irc/PrefixedParameterProvider.java new file mode 100644 index 0000000..95d0c63 --- /dev/null +++ b/src/main/java/irc/PrefixedParameterProvider.java @@ -0,0 +1,56 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +/** + * Parameter provider with automatic prefix. + */ +public class PrefixedParameterProvider implements ParameterProvider { + private String _prefix; + private ParameterProvider _source; + + /** + * Create a new PrefixedParameterProvider with the given source and prefix. + * + * @param source + * for fetching parameters. + * @param prefix + * to add before all parameter name. + */ + public PrefixedParameterProvider(ParameterProvider source, String prefix) { + _source = source; + _prefix = prefix; + } + + @Override + public String getParameter(String name) { + return _source.getParameter(_prefix + name); + } +} diff --git a/src/main/java/irc/Query.java b/src/main/java/irc/Query.java new file mode 100644 index 0000000..4fcb651 --- /dev/null +++ b/src/main/java/irc/Query.java @@ -0,0 +1,140 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +/** + * A query. + */ +public class Query extends IRCSource implements ReplyServerListener { + private String _nick; + private String _whois; + + private ListenerGroup _listeners; + + /** + * Create a new Query. + * + * @param config + * global irc configuration. + * @param nick + * the remote nick. + * @param s + * the server. + */ + public Query(IRCConfiguration config, String nick, IRCServer s) { + super(config, s); + s.addReplyServerListener(this); + _listeners = new ListenerGroup(); + _nick = nick; + _whois = ""; + if (_ircConfiguration.getASLMaster()) + getIRCServer().execute("WHOIS " + _nick); + setInterpretor(new QueryInterpretor(config)); + } + + @Override + public void release() { + ((IRCServer) _server).removeReplyServerListener(this); + super.release(); + } + + /** + * Add a listener. + * + * @param lis + * listener to add. + */ + public void addQueryListener(QueryListener lis) { + _listeners.addListener(lis); + } + + /** + * Remove a listener. + * + * @param lis + * listener to remove. + */ + public void removeQueryListeners(QueryListener lis) { + _listeners.removeListener(lis); + } + + @Override + public String getType() { + return "Query"; + } + + @Override + public String getName() { + return _nick; + } + + /** + * Get whois information for remote nick. + * + * @return peer whois information. + */ + public String getWhois() { + return _whois; + } + + @Override + public boolean talkable() { + return true; + } + + @Override + public void leave() { + getIRCServer().leaveQuery(getName()); + } + + /** + * Notify this query the remote nick has changed. + * + * @param newNick + * new remote nick. + */ + public void changeNick(String newNick) { + _nick = newNick; + _listeners.sendEvent("nickChanged", newNick, this); + } + + @Override + public Boolean replyReceived(String prefix, String id, String params[], IRCServer server) { + if (id.equals("311")) { + if (params[1].toLowerCase(java.util.Locale.ENGLISH).equals(_nick.toLowerCase(java.util.Locale.ENGLISH))) { + String name = params[params.length - 1]; + _whois = name; + _listeners.sendEvent("whoisChanged", _whois, this); + } + } + return Boolean.FALSE; + } + +} diff --git a/src/main/java/irc/QueryInterpretor.java b/src/main/java/irc/QueryInterpretor.java new file mode 100644 index 0000000..a2494bc --- /dev/null +++ b/src/main/java/irc/QueryInterpretor.java @@ -0,0 +1,45 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +/** + * A query interpretor. + */ +public class QueryInterpretor extends IRCInterpretor { + /** + * Create a new QueryInterpretor. + * + * @param config + * global irc configuration. + */ + public QueryInterpretor(IRCConfiguration config) { + super(config); + } +} diff --git a/src/main/java/irc/QueryListener.java b/src/main/java/irc/QueryListener.java new file mode 100644 index 0000000..dab3553 --- /dev/null +++ b/src/main/java/irc/QueryListener.java @@ -0,0 +1,55 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +/** + * Query listener. + */ +public interface QueryListener extends SourceListener { + /** + * The remote nick has changed. + * + * @param newNick + * new remote nick. + * @param query + * the query. + */ + public void nickChanged(String newNick, Query query); + + /** + * The whois information has changed. + * + * @param whois + * new whois information. + * @param query + * the query. + */ + public void whoisChanged(String whois, Query query); +} diff --git a/src/main/java/irc/ReplyServerListener.java b/src/main/java/irc/ReplyServerListener.java new file mode 100644 index 0000000..56d8ede --- /dev/null +++ b/src/main/java/irc/ReplyServerListener.java @@ -0,0 +1,51 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +/** + * A reply server listener. + */ +public interface ReplyServerListener { + /** + * A new numeric reply has been received from the irc server. + * + * @param prefix + * reply prefix. + * @param id + * reply id. + * @param params + * reply parameters. + * @param server + * the source server. + * @return true if the reply has been handled, false otherwise. + */ + public Boolean replyReceived(String prefix, String id, String params[], IRCServer server); + +} diff --git a/src/main/java/irc/RootInterpretor.java b/src/main/java/irc/RootInterpretor.java new file mode 100644 index 0000000..f44b59a --- /dev/null +++ b/src/main/java/irc/RootInterpretor.java @@ -0,0 +1,190 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +/** + * Root interpretor. + */ +public abstract class RootInterpretor extends IRCObject implements Interpretor { + /** + * The used string parser. + */ + protected StringParser _parser; + + /** + * The next interpretor to be used if the command is unknown. + */ + protected Interpretor _next; + + /** + * Create a new BasicInterpretor without default interpretor. + * + * @param config + * the configuration. + */ + public RootInterpretor(IRCConfiguration config) { + this(config, null); + } + + /** + * Create a new BasicInterpretor. + * + * @param config + * the configuration. + * @param next + * next interpretor to be used if the command is unknown. If null, + * the command will be sent as it to the server. + */ + public RootInterpretor(IRCConfiguration config, Interpretor next) { + super(config); + setNextInterpretor(next); + _parser = new StringParser(); + } + + @Override + public void setNextInterpretor(Interpretor next) { + _next = next; + } + + @Override + public Interpretor getNextInterpretor() { + return _next; + } + + @Override + public boolean isInside(Interpretor in) { + while (in != null) { + if (in == this) + return true; + in = in.getNextInterpretor(); + } + return false; + } + + @Override + public void addLast(Interpretor in) { + if (isInside(in)) + return; + Interpretor c = this; + while (c.getNextInterpretor() != null) + c = c.getNextInterpretor(); + c.setNextInterpretor(in); + } + + /** + * Test the given command against the expected number of parameters. + * + * @param cmd + * the hole command line. + * @param parts + * the parsed command line. + * @param params + * expected amount of parameters. + * @throws NotEnoughParametersException + * if there is not enough parameters. That's it : if + * parts.length<=params. + */ + protected void test(String cmd, String[] parts, int params) throws NotEnoughParametersException { + if (parts.length <= params) + throw new NotEnoughParametersException(cmd); + } + + /** + * Handle the received command. + * + * @param source + * the source that emitted the command. + * @param cmd + * the hole command line. + * @param parts + * the parsed command line. + * @param cumul + * the cumul parsed command line. + */ + protected void handleCommand(Source source, String cmd, String[] parts, String[] cumul) { + if (_next == null) { + Server server = source.getServer(); + if (server.isConnected()) + server.execute(cumul[0]); + else + source.report(getText(IRCTextProvider.SERVER_NOT_CONNECTED)); + } else + _next.sendString(source, "/" + cumul[0]); + } + + @Override + public void sendString(Source source, String str) { + if (str.length() == 0) + return; + + if (str.startsWith("/")) { + str = str.substring(1); + String[] parts = _parser.parseString(str); + String[] cumul = new String[parts.length]; + for (int i = 0; i < cumul.length; i++) { + cumul[i] = ""; + for (int j = i; j < parts.length; j++) + cumul[i] += parts[j] + " "; + cumul[i] = StringParser.trim(cumul[i]); + } + + for (int i = 0; i < parts.length; i++) { + if (parts[i].startsWith("" + '"') && parts[i].endsWith("" + '"')) + parts[i] = parts[i].substring(1, parts[i].length() - 1); + else if (parts[i].startsWith("'") && parts[i].endsWith("'")) + parts[i] = parts[i].substring(1, parts[i].length() - 1); + } + + String cmd = parts[0]; + handleCommand(source, cmd.toLowerCase(java.util.Locale.ENGLISH), parts, cumul); + } else { + say(source, str); + } + } + + /** + * Say the given text. + * + * @param source + * the source. + * @param str + * what to say. + */ + protected void say(Source source, String str) { + Server server = source.getServer(); + if (source.talkable()) { + source.messageReceived(server.getNick(), str); + server.say(source.getName(), str); + } else { + source.report(getText(IRCTextProvider.INTERPRETOR_NOT_ON_CHANNEL)); + } + } + +} diff --git a/src/main/java/irc/RuleList.java b/src/main/java/irc/RuleList.java new file mode 100644 index 0000000..c11c4f4 --- /dev/null +++ b/src/main/java/irc/RuleList.java @@ -0,0 +1,128 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +import java.util.Vector; + +/** + * RuleItem. + */ +class RuleItem { + /** + * Handlers. + */ + public ListHandler[] handlers; + /** + * Value. + */ + public Object value; +} + +/** + * Implements a set of rules. + */ +public class RuleList { + private Vector _list; + private Object _def; + + /** + * Create a new, empty, set of rules. + */ + public RuleList() { + _list = new Vector(); + _def = null; + } + + /** + * Set the default value. By default, this value is null. + * + * @param v + * new default value. + */ + public void setDefaultValue(Object v) { + _def = v; + } + + /** + * Get the default value. + * + * @return the default value. + */ + public Object getDefaultValue() { + return _def; + } + + /** + * Add a new rule. The rule uses the given array of list patterns (see + * ListHandler) and has the given value. + * + * @param pattern + * array of pattern. + * @param value + * rule value. + */ + public void addRule(String[] pattern, Object value) { + ListHandler[] handlers = new ListHandler[pattern.length]; + for (int i = 0; i < pattern.length; i++) + handlers[i] = new ListHandler(pattern[i]); + RuleItem item = new RuleItem(); + item.handlers = handlers; + item.value = value; + _list.insertElementAt(item, _list.size()); + } + + private boolean match(RuleItem item, String[] pattern) { + ListHandler[] handlers = item.handlers; + if (pattern.length != handlers.length) + return false; + for (int i = 0; i < handlers.length; i++) + if (!handlers[i].inList(pattern[i])) + return false; + return true; + } + + /** + * Find the first matching rule for the given values. + * + * @param values + * array of values to be tested againts patterns. + * @return value of the first matching rule, or default value if no matcing + * rule is found. + */ + public Object findValue(String[] values) { + int l = _list.size(); + for (int i = 0; i < l; i++) { + RuleItem item = (RuleItem) _list.elementAt(i); + if (match(item, values)) + return item.value; + } + return _def; + } +} diff --git a/src/main/java/irc/Server.java b/src/main/java/irc/Server.java new file mode 100644 index 0000000..9fe8b6c --- /dev/null +++ b/src/main/java/irc/Server.java @@ -0,0 +1,155 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2005 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ +package irc; + +import java.util.Enumeration; + +/** + * The server class. + */ +public interface Server { + /** + * Say the specified string. This string is sent as it to the remote server. + * + * @param destination + * message destination. + * @param str + * message itself. + */ + public void say(String destination, String str); + + /** + * Execute the given command on the remote server. + * + * @param str + * the command to execute. + */ + public void execute(String str); + + /** + * Send the given message to the server's status. + * + * @param str + * string to send to the status. + */ + public void sendStatusMessage(String str); + + /** + * Get the nickname on this server. + * + * @return the nickname on the server. + */ + public String getNick(); + + /** + * Get the username on this server. + * + * @return the username on this server. + */ + public String getUserName(); + + /** + * Get the server name. + * + * @return the server name. + */ + public String getServerName(); + + /** + * Try to connect to the server, using default configuration. + */ + public void connect(); + + /** + * Disconnect from the server. + */ + public void disconnect(); + + /** + * Test whether the server is connected. + * + * @return true if server is connected, false otherwise. + */ + public boolean isConnected(); + + /** + * Get an enumeration of all the sources associated with this server. + * + * @return an enumeration of Source. + */ + public Enumeration getSources(); + + /** + * Enumerate all sources, as if they were created and notified to the given + * listener. + * + * @param l + * listener to call. + */ + public void enumerateSourcesAsCreated(ServerListener l); + + /** + * Enumerate all sources, as if they were removed and notified to the given + * listener. + * + * @param l + * listener to call. + */ + public void enumerateSourcesAsRemoved(ServerListener l); + + /** + * Set the default output source this server should use if the destination + * source is undefined. + * + * @param source + * default source. + */ + public void setDefaultSource(Source source); + + /** + * Add a server listener. + * + * @param l + * listener to add. + */ + public void addServerListener(ServerListener l); + + /** + * Remove a listener. + * + * @param l + * listener to remove. + */ + public void removeServerListener(ServerListener l); + + /** + * Leave all sources, then leave the server. + */ + public void leave(); +} diff --git a/src/main/java/irc/ServerListener.java b/src/main/java/irc/ServerListener.java new file mode 100644 index 0000000..858b269 --- /dev/null +++ b/src/main/java/irc/ServerListener.java @@ -0,0 +1,105 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +/** + * Server listener. + */ +public interface ServerListener { + /** + * The server has connected. + * + * @param s + * the server. + */ + public void serverConnected(Server s); + + /** + * The server has disconnected. + * + * @param s + * the server. + */ + public void serverDisconnected(Server s); + + /** + * The server has left. + * + * @param s + * the server. + */ + public void serverLeft(Server s); + + /** + * The nickname(s) provided to this server for registration cannot be used for + * any reason. + * + * @param s + * the server. + * @return an array of alternative nicknames. + */ + public String[] cannotUseRequestedNicknames(Server s); + + /** + * A new source has been created. + * + * @param source + * the created source. + * @param server + * the server. + * @param bring + * true if the newly created source must have immediate focus. + */ + public void sourceCreated(Source source, Server server, Boolean bring); + + /** + * An existing source has been removed. + * + * @param source + * the removed source. + * @param server + * the server. + */ + public void sourceRemoved(Source source, Server server); + + /** + * Send a special request from the server. This is a generic-purpose event and + * possible requests should be defined by server implementations. + * + * @param request + * the request. + * @param server + * the server. + * @param params + * request parameters. + * @return request result. + */ + public Object specialServerRequest(String request, Server server, Object[] params); +} diff --git a/src/main/java/irc/ServerManager.java b/src/main/java/irc/ServerManager.java new file mode 100644 index 0000000..00da491 --- /dev/null +++ b/src/main/java/irc/ServerManager.java @@ -0,0 +1,45 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +/** + * The server manager. The manager is notified unpon server creation. + */ +public interface ServerManager { + /** + * A new server has been created, but not yet connected. + * + * @param server + * the newly created server. + * @param connect + * true if the channel should be connected has soon as possible. + */ + public void newServer(Server server, boolean connect); +} diff --git a/src/main/java/irc/ServerProtocol.java b/src/main/java/irc/ServerProtocol.java new file mode 100644 index 0000000..e284ec3 --- /dev/null +++ b/src/main/java/irc/ServerProtocol.java @@ -0,0 +1,271 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2005 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.net.Socket; +import java.util.Vector; + +/** + * The raw irc server protocol handler. + */ +public class ServerProtocol extends IRCObject implements Runnable { + private ListenerGroup _listeners; + private String _host; + private int _port; + private Socket _socket; + private CodingHandler _handler; + private Thread _thread; + private boolean _connected; + private boolean _connecting; + + /** + * Create a new ServerProtocol. + * + * @param config + * global irc configuration. + */ + public ServerProtocol(IRCConfiguration config) { + super(config); + _connected = false; + _connecting = false; + _listeners = new ListenerGroup(); + } + + /** + * Connect to the server. + * + * @param host + * server host. + * @param port + * server port. + */ + public void connect(String host, int port) { + if (_connected) + disconnect(); + _connecting = true; + _host = host; + _port = port; + _thread = new Thread(this, "Read thread"); + _thread.start(); + } + + /** + * Return connected status. + * + * @return true if connected, false otherwise. + */ + public boolean connected() { + return _connected; + } + + /** + * Return connecting status. + * + * @return true if connecting, false otherwise. + */ + public boolean connecting() { + return _connecting; + } + + /** + * Disconnect from server. + */ + public synchronized void disconnect() { + if (!_connected) + return; + if (_connecting) + return; + try { + _socket.close(); + _handler.close(); + } catch (Exception e) { + // System.out.println("disconnection"); + // System.out.println(e); + } + _connected = false; + _listeners.sendEvent("disconnected", _host); + } + + /** + * Get the local, client-side tcp port for the current connection. + * + * @return the local port. + */ + public int getLocalPort() { + return _socket.getLocalPort(); + } + + private void decodeLine(String line) { + Vector res = new Vector(); + while (line.length() != 0) { + if (line.startsWith(":") && (res.size() != 0)) { + res.insertElementAt(line.substring(1), res.size()); + line = ""; + } else { + int pos = line.indexOf(' '); + if (pos == -1) { + res.insertElementAt(StringParser.trim(line), res.size()); + line = ""; + } else { + String part = StringParser.trim(line.substring(0, pos)); + line = StringParser.trim(line.substring(pos + 1)); + res.insertElementAt(part, res.size()); + } + } + } + if (res.size() == 0) + return; + + String source = ""; + if (((String) (res.elementAt(0))).startsWith(":")) { + source = (String) res.elementAt(0); + source = source.substring(1); + res.removeElementAt(0); + } + if (res.size() == 0) + return; + + String cmd = (String) res.elementAt(0); + res.removeElementAt(0); + + String[] param = new String[res.size()]; + for (int i = 0; i < res.size(); i++) + param[i] = (String) res.elementAt(i); + + if ((cmd.charAt(0) >= '0') && (cmd.charAt(0) <= '9')) { + + _listeners.sendEventAsync("replyReceived", source, cmd, param); + } else { + + _listeners.sendEventAsync("messageReceived", source, cmd, param); + } + } + + @Override + public void run() { + try { + _socket = _ircConfiguration.getSecurityProvider().getSocket(_host, _port); + + _handler = new CodingHandler(_ircConfiguration, new BufferedInputStream(_socket.getInputStream()), + new BufferedOutputStream(_socket.getOutputStream())); + _connected = true; + _connecting = false; + _listeners.sendEventAsync("connected", _host); + } catch (Exception e) { + // e.printStackTrace(); + _connecting = false; + + if (e.getMessage() != null) + _listeners.sendEventAsync("connectionFailed", e.getMessage(), _host); + else + _listeners.sendEventAsync("connectionFailed", e.getClass().getName(), _host); + + return; + } + boolean terminated = false; + while (!terminated) { + try { + String line = _handler.read(); + if (line == null) + throw new Exception(); + // System.out.println("--> "+line); + try { + if (line != null) + decodeLine(line); + } catch (Exception e) { + _ircConfiguration.internalError("internal error", e, "plouf@pjirc.com"); + } + } catch (Exception e) { + terminated = true; + } + } + EventDispatcher.dispatchEventAsync(this, "disconnect", new Object[0]); + } + + /** + * Add a listener. + * + * @param lis + * listener to add. + */ + public void addServerProtocolListener(ServerProtocolListener lis) { + _listeners.addListener(lis); + } + + /** + * Remove a listener. + * + * @param lis + * listener to remove. + */ + public void removeServerProtocolListener(ServerProtocolListener lis) { + _listeners.removeListener(lis); + } + + /** + * Send a raw string to the server. + * + * @param str + * string to send. + * @throws Exception + * if something went wrong. + */ + public void sendString(String str) throws Exception { + if (!connected()) + throw new Exception(getText(IRCTextProvider.SERVER_NOT_CONNECTED)); + _handler.write(str); + // System.out.println("<-- "+str); + } + + /** + * Send a formatted string to the server. + * + * @param command + * comment to send. + * @param params + * parameters list. Only the last parameter can contain blanks. + * @throws Exception + * if something went wrong. + */ + public void sendCommand(String command, String params[]) throws Exception { + String toSend = command; + + for (int i = 0; i < params.length; i++) { + toSend += " "; + if (params[i].indexOf(' ') != -1) + toSend += ":"; + toSend += params[i]; + } + sendString(toSend); + } + +} diff --git a/src/main/java/irc/ServerProtocolListener.java b/src/main/java/irc/ServerProtocolListener.java new file mode 100644 index 0000000..04af4a7 --- /dev/null +++ b/src/main/java/irc/ServerProtocolListener.java @@ -0,0 +1,85 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +/** + * Server irc protocol event listener. + */ +public interface ServerProtocolListener { + /** + * A new server numeric reply has been received. + * + * @param prefix + * reply prefix. + * @param id + * reply id. + * @param params + * reply parameters. + */ + public void replyReceived(String prefix, String id, String params[]); + + /** + * A new server message has been received. + * + * @param prefix + * message prefix. + * @param command + * message command. + * @param params + * message parameters. + */ + public void messageReceived(String prefix, String command, String params[]); + + /** + * The server is now connected. + * + * @param host + * connected host. + */ + public void connected(String host); + + /** + * The connection coulnd't be established. + * + * @param message + * error message. + * @param host + * remote host. + */ + public void connectionFailed(String message, String host); + + /** + * Connection to server has been lost. + * + * @param host + * lost host. + */ + public void disconnected(String host); +} diff --git a/src/main/java/irc/SmileyTable.java b/src/main/java/irc/SmileyTable.java new file mode 100644 index 0000000..a30c6be --- /dev/null +++ b/src/main/java/irc/SmileyTable.java @@ -0,0 +1,124 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +import java.awt.Image; +import java.util.Vector; + +/** + * SmileyItem. + */ +class SmileyItem { + /** + * Matching string. + */ + public String match; + /** + * Matching image. + */ + public Image img; + + /** + * Create a new SmileyItem + * + * @param amatch + * matching string. + * @param aimg + * matching image. + */ + public SmileyItem(String amatch, Image aimg) { + match = amatch; + img = aimg; + } +} + +/** + * Smiley table. + */ +public class SmileyTable { + private Vector _table; + + /** + * Create a new, empty, smiley table. + */ + public SmileyTable() { + _table = new Vector(); + } + + /** + * Add a smiley in the table. + * + * @param match + * the macthing text. + * @param img + * image of the smiley. + */ + public void addSmiley(String match, Image img) { + if (img != null) + _table.insertElementAt(new SmileyItem(match, img), _table.size()); + } + + /** + * Get the smileys count. + * + * @return the amount of smileys in the table. + */ + public int getSize() { + return _table.size(); + } + + /** + * Get the i'th match in the smiley table. + * + * @param index + * table index. + * @return i'th smiley match. + */ + public String getMatch(int index) { + SmileyItem item = (SmileyItem) _table.elementAt(index); + return item.match; + } + + /** + * Get the i'th image in the smiley table. + * + * @param index + * table index. + * @return i'th image. + */ + public Image getImage(int index) { + if (index < 0) + return null; + if (index >= getSize()) + return null; + SmileyItem item = (SmileyItem) _table.elementAt(index); + return item.img; + } +} diff --git a/src/main/java/irc/SoundHandler.java b/src/main/java/irc/SoundHandler.java new file mode 100644 index 0000000..753cf66 --- /dev/null +++ b/src/main/java/irc/SoundHandler.java @@ -0,0 +1,43 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +/** + * Sound handler. + */ +public interface SoundHandler { + /** + * Play the given sound. + * + * @param name + * sound file name. + */ + public void playSound(String name); +} diff --git a/src/main/java/irc/Source.java b/src/main/java/irc/Source.java new file mode 100644 index 0000000..b688829 --- /dev/null +++ b/src/main/java/irc/Source.java @@ -0,0 +1,258 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +/** + * The root source. + */ +public abstract class Source extends IRCObject { + /** + * The server. + */ + protected Server _server; + private ListenerGroup _listeners; + /** + * The interpretor. + */ + protected Interpretor _in; + + /** + * Create a new Source. + * + * @param config + * the global configuration. + * @param s + * the bound server. + */ + public Source(IRCConfiguration config, Server s) { + super(config); + _listeners = new ListenerGroup(); + _in = new NullInterpretor(config); + _server = s; + } + + @Override + public void release() { + _in = new NullInterpretor(_ircConfiguration); + super.release(); + } + + /** + * Get this source name. + * + * @return source name. + */ + public abstract String getName(); + + /** + * Get this source type. + * + * @return source type. + */ + public abstract String getType(); + + /** + * Test wether this source can accept messages from user. + * + * @return true if this source accepts user input, false otherwise. + */ + public abstract boolean talkable(); + + /** + * Request to leave (close) this source. + */ + public abstract void leave(); + + /** + * Set this source's interpretor. + * + * @param in + * new interpretor. + */ + public void setInterpretor(Interpretor in) { + _in = in; + } + + /** + * Send a string to this source. + * + * @param str + * user input. + */ + public void sendString(String str) { + _in.sendString(this, str); + } + + /** + * Send a string from user input to this source. The string is filtered + * against unauthorized commands. + * + * @param str + * user input. + */ + public void sendUserString(String str) { + if (!str.startsWith("/")) + sendString(str); + else { + String cmd = str.substring(1).trim(); + int pos = cmd.indexOf(' '); + if (pos >= 0) + cmd = cmd.substring(0, pos); + if (_ircConfiguration.mayCommand(cmd)) + sendString(str); + } + } + + /** + * Get this source's interpretor. + * + * @return this source's interpretor. + */ + public Interpretor getInterpretor() { + return _in; + } + + /** + * Request this source to clear all the history it could have. + */ + public void clear() { + _listeners.sendEvent("clear", this); + } + + /** + * Notify this source a new message has arrived. + * + * @param source + * the source of the message. It can be a user nickname or a channel + * name. + * @param msg + * the message. + */ + public void messageReceived(String source, String msg) { + if (msg.startsWith("\1")) { + msg = msg.substring(1); + msg = msg.substring(0, msg.length() - 1); + + String cmd = ""; + String param = ""; + int pos = msg.indexOf(' '); + if (pos == -1) { + cmd = msg.toLowerCase(java.util.Locale.ENGLISH); + } else { + cmd = msg.substring(0, pos).toLowerCase(java.util.Locale.ENGLISH); + param = msg.substring(pos + 1); + } + + if (cmd.equals("action")) + action(source, param); + else + getServer().sendStatusMessage( + "\2\3" + "4" + "[" + source + " " + cmd.toUpperCase(java.util.Locale.ENGLISH) + "]"); + } else { + _listeners.sendEvent("messageReceived", source, msg, this); + } + } + + /** + * Notify this source a new notice message has arrived. + * + * @param source + * the source of the message. It can be a user nickname or a channel + * name. + * @param msg + * the message. + */ + public void noticeReceived(String source, String msg) { + _listeners.sendEvent("noticeReceived", source, msg, this); + } + + /** + * Notify this source a new action message has arrived. + * + * @param nick + * the user who sent the action. + * @param msg + * the message. + */ + public void action(String nick, String msg) { + _listeners.sendEvent("action", nick, msg, this); + } + + /** + * Notify this source a new report has arrived. + * + * @param msg + * the report message. + */ + public void report(String msg) { + _listeners.sendEvent("reportReceived", msg, this); + } + + /** + * Add a new SourceListener. + * + * @param lis + * listener to add. + */ + public void addSourceListener(SourceListener lis) { + _listeners.addListener(lis); + } + + /** + * Remove a SourceListener. + * + * @param lis + * the listener to remove. + */ + public void removeSourceListener(SourceListener lis) { + _listeners.removeListener(lis); + } + + /** + * Get the source server. + * + * @return the source server. + */ + public Server getServer() { + return _server; + } + + /** + * Test whether this source may be used as a default source for system event + * output. + * + * @return true if this source may be used as a default source, false + * otherwise. + */ + public boolean mayDefault() { + return true; + } + +} diff --git a/src/main/java/irc/SourceListener.java b/src/main/java/irc/SourceListener.java new file mode 100644 index 0000000..ae69e7b --- /dev/null +++ b/src/main/java/irc/SourceListener.java @@ -0,0 +1,89 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +/** + * The Source Listener. + */ +public interface SourceListener { + /** + * A new message has been received. + * + * @param nick + * source nick. + * @param msg + * message. + * @param source + * source. + */ + public void messageReceived(String nick, String msg, Source source); + + /** + * A new report has been received. + * + * @param message + * report. + * @param source + * source. + */ + public void reportReceived(String message, Source source); + + /** + * A new notice has been received. + * + * @param nick + * source nick. + * @param message + * notice. + * @param source + * source. + */ + public void noticeReceived(String nick, String message, Source source); + + /** + * A new action has been received. + * + * @param nick + * source nick. + * @param msg + * message. + * @param source + * source. + */ + public void action(String nick, String msg, Source source); + + /** + * A new clear request has been received. + * + * @param source + * source. + */ + public void clear(Source source); +} diff --git a/src/main/java/irc/StartupConfiguration.java b/src/main/java/irc/StartupConfiguration.java new file mode 100644 index 0000000..7f4ec68 --- /dev/null +++ b/src/main/java/irc/StartupConfiguration.java @@ -0,0 +1,161 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +/** + * Startup configuration. + */ +public class StartupConfiguration { + private String _nick; + private String _altNick; + private String _name; + private String[] _pass; + private String[] _host; + private String _alias; + private int[] _port; + private String[] _commands; + private String[] _plugins; + + /** + * Create a new StartupConfiguration. + * + * @param nick + * claimed nickname. + * @param altNick + * claimed alternate nickname. + * @param name + * full user name. + * @param pass + * user server passwords. + * @param host + * IRC server hosts. + * @param port + * IRC server ports. + * @param alias + * IRC server alias. + * @param commands + * initial server commands. + * @param plugins + * autoloaded plugins. + */ + public StartupConfiguration(String nick, String altNick, String name, String pass[], String host[], int port[], + String alias, String[] commands, String[] plugins) { + _nick = nick; + _altNick = altNick; + _name = name; + _pass = pass; + _host = host; + _port = port; + _alias = alias; + _commands = commands; + _plugins = plugins; + } + + /** + * Get the nickname. + * + * @return the nickname. + */ + public String getNick() { + return _nick; + } + + /** + * Get the alternate nickname. + * + * @return the alternate nickname. + */ + public String getAltNick() { + return _altNick; + } + + /** + * Get the full name. + * + * @return the full name. + */ + public String getName() { + return _name; + } + + /** + * Get the server passwords. + * + * @return the server passwords. + */ + public String[] getPass() { + return _pass; + } + + /** + * Get the server host names. + * + * @return the server host names. + */ + public String[] getHost() { + return _host; + } + + /** + * Get the server ports. + * + * @return the server ports. + */ + public int[] getPort() { + return _port; + } + + /** + * Get the server alias. + * + * @return the server alias. + */ + public String getAlias() { + return _alias; + } + + /** + * Get initial server commands. + * + * @return initial on-connect server commands. + */ + public String[] getCommands() { + return _commands; + } + + /** + * Get the autoloaded scripts. + * + * @return autoloaded scripts. + */ + public String[] getPlugins() { + return _plugins; + } +} diff --git a/src/main/java/irc/Status.java b/src/main/java/irc/Status.java new file mode 100644 index 0000000..793c062 --- /dev/null +++ b/src/main/java/irc/Status.java @@ -0,0 +1,220 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2005 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +/** + * The status. + */ +public class Status extends IRCSource implements ReplyServerListener { + private ListenerGroup _listeners; + + /** + * Create a new Status. + * + * @param config + * global irc configuration. + * @param s + * server. + */ + public Status(IRCConfiguration config, IRCServer s) { + super(config, s); + s.addReplyServerListener(this); + _listeners = new ListenerGroup(); + setInterpretor(new StatusInterpretor(config)); + } + + @Override + public void release() { + ((IRCServer) _server).removeReplyServerListener(this); + super.release(); + } + + @Override + public String getType() { + return "Status"; + } + + @Override + public String getName() { + return getServerName(); + } + + /** + * Get the server name. + * + * @return the server name. + */ + public String getServerName() { + return getIRCServer().getServerName(); + } + + @Override + public boolean talkable() { + return false; + } + + @Override + public void leave() { + if (!_ircConfiguration.getB("multiserver")) + return; + + // sendString("/quit"); + getIRCServer().leaveStatus(getName()); + } + + /** + * Get this status nick. + * + * @return status nick. + */ + public String getNick() { + return _server.getNick(); + } + + /** + * Get this status mode. + * + * @return status mode. + */ + public String getMode() { + return getIRCServer().getMode(); + } + + /** + * Add listener. + * + * @param lis + * listener to add. + */ + public void addStatusListener(StatusListener lis) { + _listeners.addListener(lis); + } + + /** + * Remove listener. + * + * @param lis + * listener to remove. + */ + public void removeStatusListener(StatusListener lis) { + _listeners.removeListener(lis); + } + + /** + * Notify this status that the nick has changed. + * + * @param nick + * new nick. + */ + public void nickChanged(String nick) { + _listeners.sendEvent("nickChanged", nick, this); + } + + /** + * Notify this status that the mode has changed. + * + * @param mode + * new mode. + */ + public void modeChanged(String mode) { + _listeners.sendEvent("modeChanged", mode, this); + } + + /** + * We've been invited on a channel. + * + * @param channel + * channel we're invited to. + * @param who + * nickname who invited us. + */ + public void invited(String channel, String who) { + _listeners.sendEvent("invited", channel, who, this); + } + + @Override + public Boolean replyReceived(String prefix, String id, String params[], IRCServer server) { + if (id.equals("322")) + return Boolean.FALSE; // chanlist + if (_ircConfiguration.getB("useinfo")) { + int i = new Integer(id).intValue(); + if ((i >= 300) && (i != 372)) + return Boolean.FALSE; + } + if (id.equals("401")) // no such nick/channel + { + Source src = getIRCServer().getDefaultSource(); + String toSend = ""; + for (int i = 1; i < params.length; i++) + toSend += " " + params[i]; + toSend = toSend.substring(1); + if (src != null) + src.report(toSend); + } else if (id.equals("317")) // idle time + { + if (params.length > 3) { + String time = params[2]; + long tme = Long.parseLong(time); + long seconds = (tme) % 60; + long mins = (tme / (60)) % 60; + long hours = (tme / (60 * 60)) % 24; + long days = (tme / (60 * 60 * 24)) % 7; + long weeks = (tme / (60 * 60 * 24 * 7)); + + String res = ""; + + if (tme > (60 * 60 * 24 * 7)) + res += weeks + " weeks "; + if (tme > (60 * 60 * 24)) + res += days + " days "; + if (tme > (60 * 60)) + res += hours + " hours "; + if (tme > (60)) + res += mins + " minutes "; + res += seconds + " seconds"; + res = res.trim(); + + String signon = new java.util.Date(1000 * Long.parseLong(params[3])).toString(); + + report(_ircConfiguration.getText(IRCTextProvider.REPLY_IDLE, params[1], res)); + report(_ircConfiguration.getText(IRCTextProvider.REPLY_SIGNON, params[1], signon)); + } + + } else { + // Source src=getIRCServer().getDefaultSource(); + String toSend = ""; + for (int i = 1; i < params.length; i++) + toSend += " " + params[i]; + toSend = toSend.substring(1); + /* if(src!=null) src. */report(toSend); + } + return Boolean.FALSE; + } +} diff --git a/src/main/java/irc/StatusInterpretor.java b/src/main/java/irc/StatusInterpretor.java new file mode 100644 index 0000000..094092b --- /dev/null +++ b/src/main/java/irc/StatusInterpretor.java @@ -0,0 +1,45 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +/** + * Status interpretor. + */ +public class StatusInterpretor extends IRCInterpretor { + /** + * Create a new status interpretor. + * + * @param config + * irc configuration. + */ + public StatusInterpretor(IRCConfiguration config) { + super(config); + } +} diff --git a/src/main/java/irc/StatusListener.java b/src/main/java/irc/StatusListener.java new file mode 100644 index 0000000..293003c --- /dev/null +++ b/src/main/java/irc/StatusListener.java @@ -0,0 +1,67 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +/** + * Status listener. + */ +public interface StatusListener extends SourceListener { + /** + * Our nick has changed. + * + * @param nick + * new nick. + * @param status + * the status. + */ + public void nickChanged(String nick, Status status); + + /** + * Our mode has changed. + * + * @param mode + * new mode. + * @param status + * the status. + */ + public void modeChanged(String mode, Status status); + + /** + * We've been invited on a channel. + * + * @param channel + * channel we're invited to. + * @param who + * nickname who invited us. + * @param status + * the status. + */ + public void invited(String channel, String who, Status status); +} diff --git a/src/main/java/irc/StreamParameterProvider.java b/src/main/java/irc/StreamParameterProvider.java new file mode 100644 index 0000000..ef0bd58 --- /dev/null +++ b/src/main/java/irc/StreamParameterProvider.java @@ -0,0 +1,86 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.Hashtable; + +/** + * Parameter provider from a text stream. + */ +public class StreamParameterProvider implements ParameterProvider { + private Hashtable _table; + + /** + * Create a new StreamParameterProvider loading the given input stream. + * + * @param is + * the input stream to load from. If is is null, then the parameter + * list will be empty. + */ + public StreamParameterProvider(InputStream is) { + _table = new Hashtable(); + if (is == null) + return; + + try { + BufferedReader reader = new BufferedReader(new InputStreamReader(is)); + String line = reader.readLine(); + while (line != null) { + line = line.trim(); + if (line.length() > 0) { + if (line.charAt(0) != '#') { + parse(line); + } + } + line = reader.readLine(); + } + reader.close(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + private void parse(String str) { + int pos = str.indexOf('='); + if (pos < 0) + return; + String before = str.substring(0, pos).trim().toLowerCase(java.util.Locale.ENGLISH); + String after = str.substring(pos + 1).trim(); + _table.put(before, after); + } + + @Override + public String getParameter(String name) { + return (String) _table.get(name.toLowerCase(java.util.Locale.ENGLISH)); + } +} diff --git a/src/main/java/irc/StringParser.java b/src/main/java/irc/StringParser.java new file mode 100644 index 0000000..8797ef6 --- /dev/null +++ b/src/main/java/irc/StringParser.java @@ -0,0 +1,101 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +import java.util.Vector; + +/** + * String parser. + */ +public class StringParser { + /** + * Trim the given string, without removing non-printable characters. + * + * @param t + * string to trim. + * @return trimmed string. + */ + public static String trim(String t) { + int a = 0; + while ((a < t.length()) && (t.charAt(a) == ' ')) + a++; + if (a == t.length()) + return ""; + int b = t.length() - 1; + while ((b >= 0) && (t.charAt(b) == ' ')) + b--; + if (b < 0) + return ""; + return t.substring(a, b + 1); + } + + private int indexOf(String s, char toFind) { + int deep = 0; + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if ((deep == 0) && (c == toFind)) + return i; + if (c == '"') + deep = 1 - deep; + if (c == '\'') + deep = 1 - deep; + } + return -1; + } + + /** + * Parse the string. + * + * @param line + * string to parse. + * @return arrays of strings. + */ + public String[] parseString(String line) { + Vector res = new Vector(); + while (line.length() != 0) { + int pos = indexOf(line, ' '); + if (pos == -1) { + res.insertElementAt(line, res.size()); + line = ""; + } else { + String part = trim(line.substring(0, pos)); + line = trim(line.substring(pos)); + res.insertElementAt(part, res.size()); + } + } + + String[] param = new String[res.size()]; + for (int i = 0; i < res.size(); i++) + param[i] = (String) res.elementAt(i); + return param; + + } + +} diff --git a/src/main/java/irc/StyleContext.java b/src/main/java/irc/StyleContext.java new file mode 100644 index 0000000..3b491e6 --- /dev/null +++ b/src/main/java/irc/StyleContext.java @@ -0,0 +1,45 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +/** + * Style context. + */ +public class StyleContext { + /** + * Type. + */ + public String type; + + /** + * Name. + */ + public String name; +} diff --git a/src/main/java/irc/TextProvider.java b/src/main/java/irc/TextProvider.java new file mode 100644 index 0000000..28161ed --- /dev/null +++ b/src/main/java/irc/TextProvider.java @@ -0,0 +1,105 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +/** + * The text provider. + */ +public interface TextProvider { + + /** + * First user message. + */ + public static final int USER_BASE = 0x8000; + /** + * Undefined string. + */ + public static final int ERROR_NOT_DEFINED = 0xffff; + + /** + * Get the formatted string. + * + * @param formattedCode + * string code. + * @param param + * parameters. + * @return formatted string. + */ + public String getString(int formattedCode, String param[]); + + /** + * Get the formatted string. + * + * @param code + * string code. + * @return formatted string. + */ + public String getString(int code); + + /** + * Get the formatted string. + * + * @param code + * string code. + * @param param1 + * first parameter. + * @return formatted string. + */ + public String getString(int code, String param1); + + /** + * Get the formatted string. + * + * @param code + * string code. + * @param param1 + * first parameter. + * @param param2 + * second parameter. + * @return formatted string. + */ + public String getString(int code, String param1, String param2); + + /** + * Get the formatted string. + * + * @param code + * string code. + * @param param1 + * first parameter. + * @param param2 + * second parameter. + * @param param3 + * third parameter. + * @return formatted string. + */ + public String getString(int code, String param1, String param2, String param3); + +} diff --git a/src/main/java/irc/URLHandler.java b/src/main/java/irc/URLHandler.java new file mode 100644 index 0000000..4cc3069 --- /dev/null +++ b/src/main/java/irc/URLHandler.java @@ -0,0 +1,61 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc; + +/** + * Url handler. + */ +public interface URLHandler { + /** + * Print the given url in the status box of the application. + * + * @param url + * url to print. + */ + public void stateURL(String url); + + /** + * Open the given url. + * + * @param url + * url to open. + */ + public void openURL(String url); + + /** + * Open the given url. + * + * @param url + * url to open. + * @param target + * url target. + */ + public void openURL(String url, String target); +} diff --git a/src/main/java/irc/dcc/DCCChat.java b/src/main/java/irc/dcc/DCCChat.java new file mode 100644 index 0000000..5c485ad --- /dev/null +++ b/src/main/java/irc/dcc/DCCChat.java @@ -0,0 +1,77 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.dcc; + +import irc.IRCConfiguration; +import irc.dcc.prv.DCCChatServer; + +/** + * The DCCChat source. + */ +public class DCCChat extends DCCSource { + private String _nick; + + /** + * Create a new DCCChat. + * + * @param config + * global configuration. + * @param s + * dcc chat server. + * @param nick + * remove nick. + */ + public DCCChat(IRCConfiguration config, DCCChatServer s, String nick) { + super(config, s); + _nick = nick; + setInterpretor(new DCCChatInterpretor(config)); + } + + @Override + public String getType() { + return "DCCChat"; + } + + @Override + public String getName() { + return _nick; + } + + @Override + public boolean talkable() { + return true; + } + + @Override + public void leave() { + getDCCChatServer().close(); + getDCCChatServer().leave(); + } +} diff --git a/src/main/java/irc/dcc/DCCChatInterpretor.java b/src/main/java/irc/dcc/DCCChatInterpretor.java new file mode 100644 index 0000000..7177ac6 --- /dev/null +++ b/src/main/java/irc/dcc/DCCChatInterpretor.java @@ -0,0 +1,73 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.dcc; + +import irc.BasicInterpretor; +import irc.IRCConfiguration; +import irc.IRCTextProvider; +import irc.Server; +import irc.Source; + +/** + * The DCCChatInterpretor. + */ +public class DCCChatInterpretor extends BasicInterpretor { + /** + * Create a new DCCChatInterpretor. + * + * @param config + * global irc configuration. + */ + public DCCChatInterpretor(IRCConfiguration config) { + super(config); + } + + @Override + protected void handleCommand(Source source, String cmd, String[] parts, String[] cumul) { + if (cmd.equals("query")) { + source.report(getText(IRCTextProvider.INTERPRETOR_BAD_CONTEXT, "/query")); + } else if (cmd.equals("ctcp")) { + source.report(getText(IRCTextProvider.INTERPRETOR_CANNOT_CTCP_IN_DCCCHAT)); + } else { + super.handleCommand(source, cmd, parts, cumul); + } + } + + @Override + protected void say(Source source, String str) { + Server server = source.getServer(); + if (source.talkable()) { + source.messageReceived(server.getNick(), str); + server.say(source.getName(), str); + } else { + source.report(getText(IRCTextProvider.INTERPRETOR_NOT_ON_CHANNEL)); + } + } +} diff --git a/src/main/java/irc/dcc/DCCFile.java b/src/main/java/irc/dcc/DCCFile.java new file mode 100644 index 0000000..de12d71 --- /dev/null +++ b/src/main/java/irc/dcc/DCCFile.java @@ -0,0 +1,261 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2005 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.dcc; + +import irc.IRCConfiguration; +import irc.ListenerGroup; +import irc.Source; +import irc.dcc.prv.DCCFileHandler; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * The DCCFile, used for file transferts. + */ +public class DCCFile extends Source { + private OutputStream _os; + private InputStream _is; + private File _file; + private ListenerGroup _listeners; + private boolean _down = false; + private int _size; + private int _count; + private DCCFileHandler _handler; + + /** + * Create a new DCCFile. + * + * @param config + * the global configuration. + * @param f + * the file to transfert. + * @param handler + * the file handler. + */ + public DCCFile(IRCConfiguration config, File f, DCCFileHandler handler) { + super(config, handler); + _listeners = new ListenerGroup(); + _handler = handler; + _count = 0; + _file = f; + } + + /** + * Add a listener. + * + * @param lis + * listener to add. + */ + public void addDCCFileListener(DCCFileListener lis) { + _listeners.addListener(lis); + } + + /** + * Remove a listener. + * + * @param lis + * listener to remove. + */ + public void removeDCCFileListener(DCCFileListener lis) { + _listeners.removeListener(lis); + } + + /** + * Prepare to send the file. + */ + public void prepareSend() { + try { + _size = _ircConfiguration.getSecurityProvider().getFileSize(_file); + // _size=(int)_file.length(); + _is = new BufferedInputStream(_ircConfiguration.getSecurityProvider().getFileInputStream(_file)); + _down = false; + } catch (Exception e) { + _ircConfiguration.internalError("prepareSend failure", e, "plouf@pjirc.com"); + } + } + + /** + * Read the next bytes while sending. + * + * @param buffer + * the target buffer, where the bytes will be written. + * @param offset + * the position of the first written byte in the target buffer. + * @param length + * the maximum amount of bytes to read. + * @return the number of read bytes, or -1 if there is no more bytes to read. + * @throws IOException + * in case of error. + */ + public int readBytes(byte[] buffer, int offset, int length) throws IOException { + int actual = _is.read(buffer, offset, length); + if (actual >= 0) { + _count += actual; + _listeners.sendEventAsync("transmitted", new Integer(_count), this); + } + return actual; + } + + /** + * Get the file size. + * + * @return the file size, in byte. + */ + public int getSize() { + return _size; + } + + /** + * Return true if the transfert is an upload transfert. + * + * @return true if uplading, false otherwise. + */ + public boolean isUploading() { + return !isDownloading(); + } + + /** + * Return true if the transfert is a download transfert. + * + * @return true if downloading, false otherwise. + */ + public boolean isDownloading() { + return _down; + } + + /** + * Notify this file the sending is terminated. + */ + public void fileSent() { + try { + _listeners.sendEventAsync("finished", this); + _is.close(); + } catch (Exception e) { + _ircConfiguration.internalError("fileSent failure", e, "plouf@pjirc.com"); + } + } + + /** + * Notify this file the sending has failed. + */ + public void fileSentFailed() { + try { + _listeners.sendEventAsync("failed", this); + _is.close(); + } catch (Exception e) { + _ircConfiguration.internalError("fileSentFailed failure", e, "plouf@pjirc.com"); + } + } + + /** + * Prepare to receive file. + * + * @param size + * the file size. + */ + public void prepareReceive(int size) { + _down = true; + _size = size; + try { + _os = new BufferedOutputStream(_ircConfiguration.getSecurityProvider().getFileOutputStream(_file)); + } catch (Exception e) { + _os = null; + } + } + + /** + * Write new bytes in the destination file. + * + * @param buffer + * the buffer to write. + * @param offset + * the first byte of the buffer to write. + * @param length + * the number of bytes to write. + * @throws IOException + * in case of error. + */ + public void bytesReceived(byte[] buffer, int offset, int length) throws IOException { + _count += length; + _os.write(buffer, offset, length); + _listeners.sendEventAsync("transmitted", new Integer(_count), this); + } + + /** + * Notify this dcc file the file reception is terminated. + */ + public void fileReceived() { + try { + _listeners.sendEventAsync("finished", this); + _os.close(); + } catch (Exception e) { + _ircConfiguration.internalError("fileReceived failure", e, "plouf@pjirc.com"); + } + + } + + /** + * Notify this dcc file the file reception has failed. + */ + public void fileReceiveFailed() { + try { + _listeners.sendEventAsync("failed", this); + _os.close(); + } catch (Exception e) { + _ircConfiguration.internalError("fileReceiveFailed failure", e, "plouf@pjirc.com"); + } + } + + @Override + public String getName() { + return _file.getName(); + } + + @Override + public void leave() { + _handler.close(); + _handler.leave(); + } + + @Override + public boolean talkable() { + return false; + } + + @Override + public String getType() { + return "DCCFile"; + } +} diff --git a/src/main/java/irc/dcc/DCCFileListener.java b/src/main/java/irc/dcc/DCCFileListener.java new file mode 100644 index 0000000..31b5725 --- /dev/null +++ b/src/main/java/irc/dcc/DCCFileListener.java @@ -0,0 +1,61 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.dcc; + +/** + * The DCC file transfert listener. + */ +public interface DCCFileListener { + /** + * Notify a transfert progression. + * + * @param count + * amount of byte that are already transferred. + * @param file + * the file. + */ + public void transmitted(Integer count, DCCFile file); + + /** + * The transfert is finished sucessfully. + * + * @param file + * the file. + */ + public void finished(DCCFile file); + + /** + * The transfert failed. + * + * @param file + * the file. + */ + public void failed(DCCFile file); +} diff --git a/src/main/java/irc/dcc/DCCSource.java b/src/main/java/irc/dcc/DCCSource.java new file mode 100644 index 0000000..4c28f44 --- /dev/null +++ b/src/main/java/irc/dcc/DCCSource.java @@ -0,0 +1,61 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.dcc; + +import irc.IRCConfiguration; +import irc.Source; +import irc.dcc.prv.DCCChatServer; + +/** + * The DCC Source. + */ +public abstract class DCCSource extends Source { + /** + * Create a new DCCSource. + * + * @param config + * global irc configuration. + * @param s + * dcc server. + */ + public DCCSource(IRCConfiguration config, DCCChatServer s) { + super(config, s); + } + + /** + * Get the DCCChatServer. + * + * @return the DCCChatServer associated with this source. + */ + public DCCChatServer getDCCChatServer() { + return (DCCChatServer) _server; + } + +} diff --git a/src/main/java/irc/dcc/prv/DCCChatServer.java b/src/main/java/irc/dcc/prv/DCCChatServer.java new file mode 100644 index 0000000..dbfec00 --- /dev/null +++ b/src/main/java/irc/dcc/prv/DCCChatServer.java @@ -0,0 +1,341 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2005 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.dcc.prv; + +import irc.CodingHandler; +import irc.EventDispatcher; +import irc.IRCConfiguration; +import irc.IRCObject; +import irc.IRCTextProvider; +import irc.ListenerGroup; +import irc.Server; +import irc.ServerListener; +import irc.Source; +import irc.dcc.DCCChat; + +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.Enumeration; +import java.util.Vector; + +/** + * The DCCChat server. There is a distinct DCCChat server for each active + * DCCChat. + */ +public class DCCChatServer extends IRCObject implements Runnable, Server { + private Socket _socket; + private ServerSocket _serverSocket; + private CodingHandler _handler; + private Thread _thread; + private DCCChat _chat; + private String _remoteNick; + private String _thisNick; + private ListenerGroup _listeners; + private boolean _listening; + private int _action; + private boolean _connected; + + /** + * Create a new DCCChat server. + * + * @param config + * the global irc configuration. + * @param thisNick + * the local nick. + * @param remoteNick + * the remote nick. + */ + public DCCChatServer(IRCConfiguration config, String thisNick, String remoteNick) { + super(config); + _action = 0; + _listeners = new ListenerGroup(); + _remoteNick = remoteNick; + _thisNick = thisNick; + _connected = false; + _chat = new DCCChat(_ircConfiguration, this, _remoteNick); + } + + @Override + public void addServerListener(ServerListener l) { + _listeners.addListener(l); + } + + @Override + public void removeServerListener(ServerListener l) { + _listeners.removeListener(l); + } + + @Override + public void connect() { + // nothing here + } + + @Override + public void disconnect() { + close(); + } + + @Override + public boolean isConnected() { + return _connected; + } + + @Override + public Enumeration getSources() { + Vector v = new Vector(); + if (_chat != null) + v.insertElementAt(_chat, 0); + return v.elements(); + } + + @Override + public void enumerateSourcesAsCreated(ServerListener lis) { + if (_chat != null) + lis.sourceCreated(_chat, this, new Boolean(_action == 2)); + } + + @Override + public void enumerateSourcesAsRemoved(ServerListener lis) { + if (_chat != null) + lis.sourceRemoved(_chat, this); + } + + @Override + public void setDefaultSource(Source s) { + // nothing here + } + + @Override + public void release() { + cleanup(); + _chat = null; + super.release(); + } + + /** + * Open an active connection on the given chat. + * + * @param ip + * the ip to contact. + * @param port + * the port to contact. + */ + public void openActive(String ip, String port) { + _serverSocket = null; + _action = 1; + long iip = new Long(ip).longValue(); + int b1 = (int) (iip & 255); + int b2 = (int) ((iip >> 8) & 255); + int b3 = (int) ((iip >> 16) & 255); + int b4 = (int) ((iip >> 24) & 255); + ip = b4 + "." + b3 + "." + b2 + "." + b1; + + try { + _socket = _ircConfiguration.getSecurityProvider().getSocket(ip, new Integer(port).intValue()); + _handler = new CodingHandler(_ircConfiguration, _socket.getInputStream(), _socket.getOutputStream()); + _thread = new Thread(this, "DCCChat thread"); + _thread.start(); + } catch (Exception e) { + _ircConfiguration.internalError("openActive failure", e, "plouf@pjirc.com"); + } + + } + + /** + * Open a passive connection on the given chat. + * + * @return the string to send to the remote peer to begin the communication. + */ + public String openPassive() { + _action = 2; + _socket = null; + try { + _serverSocket = _ircConfiguration.getSecurityProvider().getServerSocket(0); + int port = _serverSocket.getLocalPort(); + + InetAddress addr = _ircConfiguration.getSecurityProvider().getLocalHost(); + byte[] ip = addr.getAddress(); + + int b1 = ip[0]; + if (b1 < 0) + b1 += 256; + int b2 = ip[1]; + if (b2 < 0) + b2 += 256; + int b3 = ip[2]; + if (b3 < 0) + b3 += 256; + int b4 = ip[3]; + if (b4 < 0) + b4 += 256; + + long high = (b1 << 24) + (b2 << 16) + (b3 << 8) + b4; + + String sip = "" + high; + _listening = false; + _thread = new Thread(this, "DCCChat thread"); + _thread.start(); + while (!_listening) + Thread.yield(); + return sip + " " + port; + } catch (Exception e) { + e.printStackTrace(); + return ""; + } + } + + private void reportChat(String str) { + EventDispatcher.dispatchEventAsync(_chat, "report", new Object[] { str }); + } + + private void messageChat(String src, String str) { + EventDispatcher.dispatchEventAsync(_chat, "messageReceived", new Object[] { src, str }); + } + + @Override + public void run() { + boolean terminated = false; + if (_action == 2) { + try { + _listening = true; + reportChat(getText(IRCTextProvider.DCC_WAITING_INCOMING)); + _serverSocket.setSoTimeout(30000); + _socket = _serverSocket.accept(); + _handler = new CodingHandler(_ircConfiguration, _socket.getInputStream(), _socket.getOutputStream()); + } catch (Exception e) { + reportChat(getText(IRCTextProvider.DCC_UNABLE_TO_OPEN_CONNECTION, e.getMessage())); + return; + } + } + reportChat(getText(IRCTextProvider.DCC_CONNECTION_ESTABLISHED)); + _connected = true; + _listeners.sendEventAsync("serverConnected", this); + while (!terminated) { + try { + String line = _handler.read(); + if (line == null) + throw new Exception(getText(IRCTextProvider.DCC_CONNECTION_CLOSED)); + try { + messageChat(_remoteNick, line); + } catch (Exception e) { + _ircConfiguration.internalError("internal error", e, "plouf@pjirc.com"); + } + } catch (Exception e) { + terminated = true; + reportChat(getText(IRCTextProvider.DCC_ERROR, e.getMessage())); + } + } + _connected = false; + _listeners.sendEventAsync("serverDisconnected", this); + cleanup(); + } + + @Override + public void say(String destination, String str) { + if (destination.equals(_remoteNick)) + sendString(str); + else + _chat.report(getText(IRCTextProvider.DCC_ERROR, getText(IRCTextProvider.DCC_UNABLE_TO_SEND_TO, destination))); + } + + @Override + public void execute(String str) { + _chat.report(getText(IRCTextProvider.DCC_BAD_CONTEXT)); + } + + private void sendString(String str) { + try { + if ((_handler == null) || (!_connected)) + throw new Exception(getText(IRCTextProvider.DCC_NOT_CONNECTED)); + _handler.write(str); + } catch (Exception e) { + _chat.report(getText(IRCTextProvider.DCC_ERROR, e.getMessage())); + } + } + + @Override + public void sendStatusMessage(String str) { + if (_chat != null) + _chat.report(str); + } + + private void cleanup() { + try { + if (_socket != null) + _socket.close(); + if (_serverSocket != null) + _serverSocket.close(); + _handler.close(); + } catch (Exception e) { + _ircConfiguration.internalError("cleanup failure", e, "plouf@pjirc.com"); + } + } + + /** + * Close this communication. + */ + public void close() { + cleanup(); + } + + @Override + public void leave() { + disconnect(); + long time = System.currentTimeMillis(); + while (isConnected()) { + try { + Thread.sleep(100); + if (System.currentTimeMillis() - time > 10000) + break; + } catch (InterruptedException ex) { + // ignore it... + } + } + _listeners.sendEvent("sourceRemoved", _chat, this); + _listeners.sendEvent("serverLeft", this); + _chat.release(); + } + + @Override + public String getNick() { + return _thisNick; + } + + @Override + public String getUserName() { + return ""; + } + + @Override + public String getServerName() { + return getNick(); + } +} diff --git a/src/main/java/irc/dcc/prv/DCCFileHandler.java b/src/main/java/irc/dcc/prv/DCCFileHandler.java new file mode 100644 index 0000000..5d6e64d --- /dev/null +++ b/src/main/java/irc/dcc/prv/DCCFileHandler.java @@ -0,0 +1,389 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2005 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.dcc.prv; + +import irc.IRCConfiguration; +import irc.IRCObject; +import irc.IRCTextProvider; +import irc.ListenerGroup; +import irc.Server; +import irc.ServerListener; +import irc.Source; +import irc.dcc.DCCFile; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.Enumeration; +import java.util.Vector; + +/** + * The dcc file handler. There is a handler for each file transfert. + */ +public class DCCFileHandler extends IRCObject implements Server, Runnable { + private Socket _socket; + private ServerSocket _serverSocket; + private Thread _thread; + + private OutputStream _os; + private InputStream _is; + private DCCFile _file; + + private int _action; + private int _size; + private boolean _listening; + private boolean _connected; + private ListenerGroup _listeners; + + /** + * Create a new DCCFileHandler. + * + * @param config + * the global configuration. + * @param remoteNick + * the remote nick. + * @param f + * the file to send or receive. + */ + public DCCFileHandler(IRCConfiguration config, String remoteNick, File f) { + super(config); + _action = 0; + _size = 0; + _connected = false; + _file = new DCCFile(config, f, this); + _listeners = new ListenerGroup(); + } + + @Override + public void release() { + cleanup(); + _file = null; + super.release(); + } + + /** + * Receive the file. + * + * @param ip + * the remote ip. + * @param port + * the remote port. + * @param size + * the file size. + */ + public void receive(String ip, String port, String size) { + _size = new Integer(size).intValue(); + _file.prepareReceive(_size); + _serverSocket = null; + _action = 1; + long iip = new Long(ip).longValue(); + int b1 = (int) (iip & 255); + int b2 = (int) ((iip >> 8) & 255); + int b3 = (int) ((iip >> 16) & 255); + int b4 = (int) ((iip >> 24) & 255); + ip = b4 + "." + b3 + "." + b2 + "." + b1; + + try { + _socket = _ircConfiguration.getSecurityProvider().getSocket(ip, new Integer(port).intValue()); + _is = new BufferedInputStream(_socket.getInputStream()); + _os = new BufferedOutputStream(_socket.getOutputStream()); + _thread = new Thread(this, "DCCFile thread"); + _thread.start(); + } catch (Exception e) { + _ircConfiguration.internalError("receive failure", e, "plouf@pjirc.com"); + } + + } + + /** + * Send the file in passive mode. + * + * @return the string to send to the remote peer to initiate the transfert. + */ + public String send() { + _action = 2; + _socket = null; + try { + _serverSocket = _ircConfiguration.getSecurityProvider().getServerSocket(0); + int port = _serverSocket.getLocalPort(); + + InetAddress addr = _ircConfiguration.getSecurityProvider().getLocalHost(); + byte[] ip = addr.getAddress(); + + int b1 = ip[0]; + if (b1 < 0) + b1 += 256; + int b2 = ip[1]; + if (b2 < 0) + b2 += 256; + int b3 = ip[2]; + if (b3 < 0) + b3 += 256; + int b4 = ip[3]; + if (b4 < 0) + b4 += 256; + + long high = (b1 << 24) + (b2 << 16) + (b3 << 8) + b4; + + _file.prepareSend(); + int size = _file.getSize(); + String sip = "" + high; + _listening = false; + _thread = new Thread(this, "DCCFile thread"); + _thread.start(); + while (!_listening) + Thread.yield(); + return sip + " " + port + " " + size; + } catch (Exception e) { + return ""; + } + } + + private void writeConf(OutputStream os, int v) throws IOException { + os.write((v >> 24) & 255); + os.write((v >> 16) & 255); + os.write((v >> 8) & 255); + os.write((v) & 255); + os.flush(); + } + + private int readConf(InputStream is) throws IOException { + int b1 = is.read(); + if (b1 < 0) + b1 += 256; + int b2 = is.read(); + if (b2 < 0) + b2 += 256; + int b3 = is.read(); + if (b3 < 0) + b3 += 256; + int b4 = is.read(); + if (b4 < 0) + b4 += 256; + return (b1 << 24) + (b2 << 16) + (b3 << 8) + b4; + } + + private void connected() { + _connected = true; + _listeners.sendEventAsync("serverConnected", this); + } + + private void disconnected() { + _connected = false; + _listeners.sendEventAsync("serverDisconnected", this); + } + + @Override + public void run() { + byte[] buffer = new byte[4096]; + if (_action == 1) // receive + { + try { + connected(); + int read = 0; + while (_size - read > 0) { + int r = _is.read(buffer, 0, buffer.length); + if (r == -1) + throw new Exception(getText(IRCTextProvider.DCC_STREAM_CLOSED)); + read += r; + _file.bytesReceived(buffer, 0, r); + Thread.yield(); + writeConf(_os, read); + } + writeConf(_os, _size); + _file.fileReceived(); + } catch (Exception e) { + e.printStackTrace(); + _file.fileReceiveFailed(); + } + disconnected(); + cleanup(); + } else if (_action == 2) // send + { + _listening = true; + try { + _serverSocket.setSoTimeout(30000); + _socket = _serverSocket.accept(); + _os = new BufferedOutputStream(_socket.getOutputStream()); + _is = new BufferedInputStream(_socket.getInputStream()); + connected(); + int size = _file.getSize(); + int toread = size; + int rec = 0; + while (toread > 0) { + int r = _file.readBytes(buffer, 0, buffer.length); + if (r < 0) + throw new Exception(getText(IRCTextProvider.DCC_STREAM_CLOSED)); + _os.write(buffer, 0, r); + toread -= r; + + if (_is.available() > 0) + rec = readConf(_is); + } + _os.flush(); + while (rec != size) { + rec = readConf(_is); + } + _os.close(); + _file.fileSent(); + } catch (Exception e) { + e.printStackTrace(); + _file.fileSentFailed(); + } + disconnected(); + cleanup(); + + } + } + + private void cleanup() { + try { + if (_socket != null) + _socket.close(); + if (_serverSocket != null) + _serverSocket.close(); + _is.close(); + _os.close(); + } catch (Exception e) { + _ircConfiguration.internalError("cleanup failure", e, "plouf@pjirc.com"); + } + } + + /** + * Close the current transfert. + */ + public void close() { + cleanup(); + } + + @Override + public void say(String destination, String str) { + // nothing here + } + + @Override + public void execute(String str) { + // nothing here + } + + @Override + public void sendStatusMessage(String str) { + // nothing here + } + + @Override + public String getNick() { + return ""; + } + + @Override + public String getUserName() { + return ""; + } + + @Override + public void connect() { + // nothing here... + } + + @Override + public void disconnect() { + close(); + } + + @Override + public boolean isConnected() { + return _connected; + } + + @Override + public Enumeration getSources() { + Vector v = new Vector(); + if (_file != null) + v.insertElementAt(_file, v.size()); + return v.elements(); + } + + @Override + public void enumerateSourcesAsCreated(ServerListener l) { + if (_file != null) + l.sourceCreated(_file, this, new Boolean(true)); + } + + @Override + public void enumerateSourcesAsRemoved(ServerListener l) { + if (_file != null) + l.sourceRemoved(_file, this); + } + + @Override + public void setDefaultSource(Source source) { + // nothing here... + } + + @Override + public void addServerListener(ServerListener l) { + _listeners.addListener(l); + } + + @Override + public void removeServerListener(ServerListener l) { + _listeners.removeListener(l); + } + + @Override + public void leave() { + disconnect(); + long time = System.currentTimeMillis(); + while (isConnected()) { + try { + Thread.sleep(100); + if (System.currentTimeMillis() - time > 10000) + break; + } catch (InterruptedException ex) { + // ignore it... + } + } + _listeners.sendEvent("sourceRemoved", _file, this); + _listeners.sendEvent("serverLeft", this); + _file.release(); + } + + @Override + public String getServerName() { + return getNick(); + } +} diff --git a/src/main/java/irc/gui/GUISource.java b/src/main/java/irc/gui/GUISource.java new file mode 100644 index 0000000..2eb1fce --- /dev/null +++ b/src/main/java/irc/gui/GUISource.java @@ -0,0 +1,78 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui; + +import irc.Source; + +/** + * The GUI source. + */ +public interface GUISource { + /** + * Set the current textfield text. + * + * @param txt + * new textfield text. + */ + public void setFieldText(String txt); + + /** + * Get the current textfield text. + * + * @return the current textfield text. + */ + public String getFieldText(); + + /** + * Validate the current textfield text, as if user pressed return key. + */ + public void validateText(); + + /** + * Get the source. + * + * @return the source. + */ + public Source getSource(); + + /** + * Request the keyboard focus on this awt source. + */ + public void requestFocus(); + + /** + * Get the source title. + * + * @return source title. + */ + public String getTitle(); + +} // GUISource + diff --git a/src/main/java/irc/gui/IRCInterface.java b/src/main/java/irc/gui/IRCInterface.java new file mode 100644 index 0000000..9af5b39 --- /dev/null +++ b/src/main/java/irc/gui/IRCInterface.java @@ -0,0 +1,151 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2005 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui; + +import irc.EventDispatcher; +import irc.IRCConfiguration; +import irc.Interpretor; +import irc.ListenerGroup; +import irc.NullInterpretor; +import irc.Source; + +import java.awt.Component; + +/** + * The common root class for all PJIRC user interfaces. + */ +public abstract class IRCInterface extends irc.plugin.Plugin { + /** + * The IRCInterfaceListener group. + */ + protected ListenerGroup _listenerGroup; + + private Interpretor _nullInterpretor; + + /** + * Create a new IRCInterface with the given IRCConfiguration instance. + * + * @param ircConfiguration + * the global IRCConfiguration instance. + */ + public IRCInterface(IRCConfiguration ircConfiguration) { + super(ircConfiguration); + _listenerGroup = new ListenerGroup(); + _nullInterpretor = new NullInterpretor(_ircConfiguration); + } + + /** + * Trigger the "activeChanged" event for all IRCInterfaceListeners. If this + * method is called in the event thread, event dispatching will be + * synchroneous. Otherwise, asynchroneous event will be dispatched. + * + * @param source + * the newly activated source. + */ + protected void triggerActiveChanged(GUISource source) { + if (EventDispatcher.isEventThread()) + _listenerGroup.sendEvent("activeChanged", source, this); + else + _listenerGroup.sendEventAsync("activeChanged", source, this); + } + + /** + * Add an IRCInterfaceListener on this interface. + * + * @param lis + * the listener to add. + */ + public void addIRCInterfaceListener(IRCInterfaceListener lis) { + _listenerGroup.addListener(lis); + } + + /** + * Remove an existing IRCInterfaceListener from this interface. + * + * @param lis + * the listener to remove. + */ + public void removeIRCInterfaceListener(IRCInterfaceListener lis) { + _listenerGroup.removeListener(lis); + } + + /** + * Get the active source. For instance, return the keyboard focused source. + * May be null if no particular source should be considered as being active. + * + * @return the active gui source. + */ + public GUISource getActive() { + return null; + } + + /** + * Set the active source. For instance, the one that should have the keybord + * focus. + * + * @param source + * the new source to be active. + */ + public void setActive(GUISource source) { + // nothing here + } + + /** + * Return the GUISource that belongs to the given source, or null if there is + * no such mapping available. + * + * @param source + * source to get the GUI source from. + * @return the GUISource, or null if there is no such mapping. + */ + public GUISource getGUISource(Source source) { + return null; + } + + /** + * Get the default interpretor to be used when an unknown command is entered + * by the user. + * + * @return the default interpretor. + */ + public Interpretor getInterpretor() { + return _nullInterpretor; + } + + /** + * Get the component associated with this interface. + * + * @return the interface component, or null if no component is defined. + */ + public Component getComponent() { + return null; + } + +} // IRCInterface diff --git a/src/main/java/irc/gui/IRCInterfaceListener.java b/src/main/java/irc/gui/IRCInterfaceListener.java new file mode 100644 index 0000000..adea58b --- /dev/null +++ b/src/main/java/irc/gui/IRCInterfaceListener.java @@ -0,0 +1,46 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui; + +/** + * The IRC interface listener. + */ +public interface IRCInterfaceListener { + /** + * The current active source has changed. + * + * @param source + * the new active source. + * @param inter + * the calling interface. + */ + public void activeChanged(GUISource source, IRCInterface inter); + +} // IRCInterfaceListener diff --git a/src/main/java/irc/gui/common/AWTIrcTextField.java b/src/main/java/irc/gui/common/AWTIrcTextField.java new file mode 100644 index 0000000..186290b --- /dev/null +++ b/src/main/java/irc/gui/common/AWTIrcTextField.java @@ -0,0 +1,352 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2005 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.common; + +import irc.EventDispatcher; +import irc.ListenerGroup; + +import java.awt.Color; +import java.awt.Container; +import java.awt.Font; +import java.awt.GridLayout; +import java.awt.TextField; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.util.Vector; + +/** + * The special input text field used in AWTSource. + */ +public class AWTIrcTextField extends Container implements ActionListener, KeyListener, FocusListener { + private int _index; + private int _tabCount; + private String _completing; + private String[] _completeList; + private Vector _historic; + private ListenerGroup _listeners; + private TextField _field; + private boolean _useEnterTextHere; + private String _enterTextHere; + + /** + * Create a new AWTIrcTextField. + */ + public AWTIrcTextField() { + super(); + _useEnterTextHere = false; + setLayout(new GridLayout(1, 1)); + _field = new TextField(); + add(_field); + _completeList = new String[0]; + _field.setFont(new Font("Monospaced", Font.PLAIN, 12)); + _tabCount = 0; + _completing = ""; + _index = 0; + _listeners = new ListenerGroup(); + _historic = new Vector(); + _field.addActionListener(this); + _field.addKeyListener(this); + + try { + Class c = _field.getClass(); + java.lang.reflect.Method m = c.getMethod("setFocusTraversalKeysEnabled", new Class[] { boolean.class }); + m.invoke(_field, new Object[] { new Boolean(false) }); + } catch (Exception ex) { + // ignore it... + } + + addFocusListener(this); + + } + + /** + * Release this object. + */ + public void release() { + removeFocusListener(this); + _field.removeActionListener(this); + _field.removeKeyListener(this); + _historic = new Vector(); + _field = null; + removeAll(); + } + + /** + * Configure the "enter text here" feature. + * + * @param b + * true if feature enabled, false otherwise. + * @param text + * text to be displayed. + */ + public void setEnterTextHere(boolean b, String text) { + _useEnterTextHere = b; + _enterTextHere = text; + + if (_useEnterTextHere) { + _field.setText(_enterTextHere); + _field.setSelectionStart(0); + _field.setSelectionEnd(_field.getText().length() + 1); + } + } + + @Override + public void setBackground(Color c) { + super.setBackground(c); + _field.setBackground(c); + } + + @Override + public void setForeground(Color c) { + super.setForeground(c); + _field.setForeground(c); + } + + @Override + public void focusGained(FocusEvent e) { + _field.requestFocus(); + } + + @Override + public void focusLost(FocusEvent e) { + // nothing here + } + + /** + * Add an action listener on the field. + * + * @param lis + * the action listener to add. + */ + public void addActionListener(ActionListener lis) { + _listeners.addListener(lis); + } + + /** + * Remove an action lsitener from the field. + * + * @param lis + * action listener to remove. + */ + public void removeActionListener(ActionListener lis) { + _listeners.removeListener(lis); + } + + /** + * Set the list of known words to be auto completed if the type key is + * pressed. + * + * @param list + * array of known words. + */ + public void setCompleteList(String[] list) { + _completeList = new String[list.length]; + for (int i = 0; i < list.length; i++) + _completeList[i] = list[i]; + } + + /** + * Set this field content. + * + * @param txt + * new text content. + */ + public void setText(String txt) { + _field.setText(txt); + } + + /** + * Return text content. + * + * @return text content. + */ + public String getText() { + return _field.getText(); + } + + /** + * Get the current caret position. + * + * @return caret position. + */ + public int getCaretPosition() { + return _field.getCaretPosition(); + } + + /** + * Set the caret position. + * + * @param pos + * new caret position. + */ + public void setCaretPosition(int pos) { + _field.setCaretPosition(pos); + } + + private void type(int c) { + int selA = _field.getSelectionStart(); + int selB = _field.getSelectionEnd(); + String t = _field.getText(); + if (selA != selB) { + t = t.substring(0, selA) + t.substring(selB); + _field.setCaretPosition(selA); + } + int p = _field.getCaretPosition(); + String before = t.substring(0, p); + String after = t.substring(p); + _field.setText(before + ((char) c) + after); + _field.setCaretPosition(p + 1); + } + + private void getCompleting() { + _completing = ""; + String t = _field.getText(); + + if ((_field.getCaretPosition() == t.length()) || (t.charAt(_field.getCaretPosition()) == ' ')) { + for (int i = _field.getCaretPosition() - 1; i >= 0; i--) { + if (t.charAt(i) == ' ') + break; + _completing = t.charAt(i) + _completing; + } + } + } + + private void complete() { + if (_completing.length() == 0) + return; + String begin = _completing.toLowerCase(java.util.Locale.ENGLISH); + Vector match = new Vector(); + for (int i = 0; i < _completeList.length; i++) { + if (_completeList[i].toLowerCase(java.util.Locale.ENGLISH).startsWith(begin)) { + match.insertElementAt(_completeList[i], match.size()); + } + } + if (match.size() > 0) { + String completeItem = (String) match.elementAt(_tabCount % match.size()); + int p = _field.getCaretPosition(); + String t = _field.getText(); + String before = t.substring(0, p); + String after = t.substring(p); + // supprimer le dernier mot de before (garder l'espace) + int space = before.lastIndexOf(' '); + if (space == -1) + before = ""; + else + before = before.substring(0, space + 1); + before += completeItem; + _field.setText(before + after); + _field.setCaretPosition(before.length()); + } + } + + @Override + public void keyPressed(KeyEvent e) { + if ((e.getKeyCode() == KeyEvent.VK_TAB) || (e.getKeyCode() == KeyEvent.VK_PAGE_DOWN)) { + if (_tabCount == 0) + getCompleting(); + complete(); + _tabCount++; + e.consume(); + } else { + _tabCount = 0; + } + if (e.getKeyCode() == KeyEvent.VK_UP) { + if (_historic.size() > 0) { + _index--; + if (_index == -1) + _index = 0; + _field.setText((String) _historic.elementAt(_index)); + setCaretPosition(getText().length()); + } + e.consume(); + } else if (e.getKeyCode() == KeyEvent.VK_DOWN) { + if (_historic.size() > 0) { + _index++; + if (_index > _historic.size()) + _index = _historic.size(); + if (_index < _historic.size()) { + _field.setText((String) _historic.elementAt(_index)); + } else { + _field.setText(""); + } + setCaretPosition(getText().length()); + } + e.consume(); + } else if ((e.getKeyCode() == KeyEvent.VK_K) && e.isControlDown()) { + type(3); + e.consume(); + } else if ((e.getKeyCode() == KeyEvent.VK_B) && e.isControlDown()) { + type(2); + e.consume(); + } else if ((e.getKeyCode() == KeyEvent.VK_U) && e.isControlDown()) { + type(31); + e.consume(); + } else if ((e.getKeyCode() == KeyEvent.VK_R) && e.isControlDown()) { + type(22); + e.consume(); + } else if ((e.getKeyCode() == KeyEvent.VK_O) && e.isControlDown()) { + type(15); + e.consume(); + } else if ((e.getKeyCode() == KeyEvent.VK_W) && e.isControlDown()) { + type(30); + e.consume(); + } + } + + @Override + public void keyReleased(KeyEvent e) { + // nothing here... + } + + @Override + public void keyTyped(KeyEvent e) { + // nothing here... + } + + /** + * Validate the curren text, as if user pressed enter key. + */ + public void validateText() { + if (getText().length() > 0) { + _historic.insertElementAt(getText(), _historic.size()); + _index = _historic.size(); + } + _listeners.sendEvent("actionPerformed", new Object[] { new ActionEvent(this, 0, "validate") }); + } + + @Override + public void actionPerformed(ActionEvent e) { + EventDispatcher.dispatchEventAsync(this, "validateText", new Object[0]); + } +} diff --git a/src/main/java/irc/gui/common/DockablePanel.java b/src/main/java/irc/gui/common/DockablePanel.java new file mode 100644 index 0000000..1162d40 --- /dev/null +++ b/src/main/java/irc/gui/common/DockablePanel.java @@ -0,0 +1,261 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2005 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.common; + +import irc.EventDispatcher; +import irc.ListenerGroup; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Frame; +import java.awt.Panel; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; + +/** + * A panel that can be docked. + */ +public class DockablePanel extends Panel implements WindowListener, Runnable { + private Component _comp; + private boolean _docked; + private Frame _frame; + private int _behaviour; + private ListenerGroup _listeners; + + /** + * Closing behaviour: the panel will be docked upon undocked window closure. + */ + public static final int DOCK_ON_CLOSE = 0; + + /** + * Closing behaviour: nothing will be done upon undocked window closure. + */ + public static final int DO_NOTHING_ON_CLOSE = 1; + + /** + * Create a new Dockable Panel using the given component inside, and the given + * color. + * + * @param c + * the unique component of this panel. + * @param col + * the background color when the component is undocked. + */ + public DockablePanel(Component c, Color col) { + setBackground(col); + setLayout(new BorderLayout()); + _comp = c; + _docked = true; + add(_comp, BorderLayout.CENTER); + validate(); + + _frame = new Frame(); + _frame.setLayout(new BorderLayout()); + _frame.addWindowListener(this); + + _behaviour = DOCK_ON_CLOSE; + _listeners = new ListenerGroup(); + } + + /** + * Add a new dockable panel listener. + * + * @param lis + * the listener to add. + */ + public void addDockablePanelListener(DockablePanelListener lis) { + _listeners.addListener(lis); + } + + /** + * Removes a dockable panel listener. + * + * @param lis + * the listener to remove. + */ + public void removeDockablePanelListener(DockablePanelListener lis) { + _listeners.removeListener(lis); + } + + /** + * Set the undocked window closing behaviour. + * + * @param behaviour + * the new behaviour. By default, the behaviour is DOCK_ON_CLOSE. + */ + public void setClosingBehaviour(int behaviour) { + _behaviour = behaviour; + } + + /** + * Get the undocked window closing behaviour. + * + * @return the window closing behaviour. + */ + public int getClosingBehaviour() { + return _behaviour; + } + + /** + * Get the component. + * + * @return the component. + */ + public Component getComponent() { + return _comp; + } + + /** + * Undock the panel. + * + * @param windowTitle + * the undocked window title. + */ + public void undock(String windowTitle) { + if (_comp == null) + return; + if (!_docked) + return; + _docked = false; + _comp.setVisible(true); + remove(_comp); + validate(); + _frame.add(_comp, BorderLayout.CENTER); + _frame.pack(); + _frame.setTitle(windowTitle); + _frame.show(); + } + + /** + * Dock the panel. + */ + public void dock() { + if (_comp == null) + return; + if (_docked) + return; + _docked = true; + _comp.setVisible(false); + _frame.hide(); + _frame.remove(_comp); + + add(_comp, BorderLayout.CENTER); + _comp.setVisible(isVisible()); + validate(); + } + + /** + * Check the dock state. + * + * @return if docked, false otherwise. + */ + public boolean isDocked() { + return _docked; + } + + /** + * If the source is undocked, this method will bring the undocked window to + * the front of the screen. + */ + public void bring() { + _frame.toFront(); + } + + @Override + public void run() { + if (_frame != null) + _frame.dispose(); + _frame = null; + } + + /** + * Release this object. + */ + public void release() { + if (_frame == null) + return; + dock(); + _frame.removeAll(); + removeAll(); + _frame.removeWindowListener(this); + // EventDispatcher.dispatchEventAsync(this,"disposeFrame",new Object[0]); + Thread t = new Thread(this, "Frame disposal thread"); + t.start(); + _comp = null; + } + + @Override + public void setVisible(boolean b) { + if (_comp == null) + return; + if (_docked) + _comp.setVisible(b); + super.setVisible(b); + } + + @Override + public void windowActivated(WindowEvent e) { + // nothing here... + } + + @Override + public void windowClosed(WindowEvent e) { + _listeners.sendEventAsync("DockablePanelWindowClosed", this); + } + + @Override + public void windowClosing(WindowEvent e) { + _listeners.sendEventAsync("DockablePanelWindowClosing", this); + if (_behaviour == DOCK_ON_CLOSE) + EventDispatcher.dispatchEventAsync(this, "dock", new Object[0]); + } + + @Override + public void windowDeactivated(WindowEvent e) { + // nothing here... + } + + @Override + public void windowDeiconified(WindowEvent e) { + // nothing here... + } + + @Override + public void windowIconified(WindowEvent e) { + // nothing here... + } + + @Override + public void windowOpened(WindowEvent e) { + // nothing here... + } + +} diff --git a/src/main/java/irc/gui/common/DockablePanelListener.java b/src/main/java/irc/gui/common/DockablePanelListener.java new file mode 100644 index 0000000..3eefb3b --- /dev/null +++ b/src/main/java/irc/gui/common/DockablePanelListener.java @@ -0,0 +1,51 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.common; + +/** + * Listener for DockablePanel events. + */ +public interface DockablePanelListener { + /** + * The undocked dockable panel window is closing. + * + * @param panel + * the closing panel. + */ + public void DockablePanelWindowClosing(DockablePanel panel); + + /** + * The undocked dockable panel window has been closed + * + * @param panel + * the closed panel. + */ + public void DockablePanelWindowClosed(DockablePanel panel); +} diff --git a/src/main/java/irc/gui/common/MouseWheelPanelListener.java b/src/main/java/irc/gui/common/MouseWheelPanelListener.java new file mode 100644 index 0000000..bf16a7c --- /dev/null +++ b/src/main/java/irc/gui/common/MouseWheelPanelListener.java @@ -0,0 +1,43 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.common; + +/** + * Mouse wheel listener. + */ +public interface MouseWheelPanelListener { + /** + * The mouse wheel moved. + * + * @param amount + * wheel move amplitude. + */ + public void mouseWheelMoved(Integer amount); +} diff --git a/src/main/java/irc/gui/common/MouseWheelPanelWrapper.java b/src/main/java/irc/gui/common/MouseWheelPanelWrapper.java new file mode 100644 index 0000000..a66cc8b --- /dev/null +++ b/src/main/java/irc/gui/common/MouseWheelPanelWrapper.java @@ -0,0 +1,98 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2005 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.common; + +import java.awt.Component; +import java.awt.GridLayout; +import java.awt.Panel; +import java.lang.reflect.Method; + +/** + * Wrapper for MouseWheelPanel. + */ +public class MouseWheelPanelWrapper extends Panel { + private Object _panel; + private Method _add; + private Method _remove; + + /** + * Create a new MouseWheelPanelWrapper with the specified component inside. + * + * @param c + * wrapper component. + */ + public MouseWheelPanelWrapper(Component c) { + setLayout(new GridLayout(1, 1)); + try { + Class cl = Class.forName("irc.gui.prv.MouseWheelPanel"); + _panel = cl.newInstance(); + Class[] types = { MouseWheelPanelListener.class }; + _add = cl.getMethod("addMouseWheelPanelListener", types); + _remove = cl.getMethod("removeMouseWheelPanelListener", types); + add((Component) _panel); + types[0] = Component.class; + Method m = cl.getMethod("add", types); + Object[] p = { c }; + m.invoke(_panel, p); + } catch (Throwable ex) { + add(c); + } + } + + /** + * Add a listener. + * + * @param lis + * listener to add. + */ + public void addMouseWheelPanelListener(MouseWheelPanelListener lis) { + try { + Object[] p = { lis }; + _add.invoke(_panel, p); + } catch (Throwable ex) { + // ignore... + } + } + + /** + * Remove a listener. + * + * @param lis + * listener to remove. + */ + public void removeMouseWheelPanelListener(MouseWheelPanelListener lis) { + try { + Object[] p = { lis }; + _remove.invoke(_panel, p); + } catch (Throwable ex) { + // ignore... + } + } +} diff --git a/src/main/java/irc/gui/pixx/AWTChanList.java b/src/main/java/irc/gui/pixx/AWTChanList.java new file mode 100644 index 0000000..f7d67a4 --- /dev/null +++ b/src/main/java/irc/gui/pixx/AWTChanList.java @@ -0,0 +1,222 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.pixx; + +import irc.ChanList; +import irc.ChanListListener; +import irc.ChannelInfo; +import irc.style.StyledList; + +import java.awt.BorderLayout; + +/** + * The AWT channel list. + */ +public class AWTChanList extends BaseAWTSource implements ChanListListener { + /** + * Horizontal scrollbar. + */ + protected PixxHorizontalScrollBar _hscroll; + + /** + * Create a new AWTChanList. + * + * @param config + * the global irc configuration. + * @param list + * the source channel list. + */ + public AWTChanList(PixxConfiguration config, ChanList list) { + super(config, list, true); + + list.addChanListListener(this); + + _hscroll = new PixxHorizontalScrollBar(_pixxConfiguration, 0, 0, 0.1); + _hscroll.addPixxScrollBarListener(this); + + _list.setWrap(false); + + remove(_textField); + add(_hscroll, BorderLayout.SOUTH); + + setTitle(getText(PixxTextProvider.SOURCE_CHANLIST, getChanList().getName())); + _list.clear(1024); + } + + @Override + public void release() { + ((ChanList) _source).removeChanListListeners(this); + _hscroll.removePixxScrollBarListener(this); + _hscroll.release(); + _hscroll = null; + super.release(); + } + + @Override + public String getShortTitle() { + return getText(PixxTextProvider.GUI_CHANNELS); + } + + @Override + public void setFieldText(String txt) { + } + + @Override + public String getFieldText() { + return ""; + } + + @Override + public void validateText() { + } + + /** + * Get the source chanlist. + * + * @return source chanlist. + */ + public ChanList getChanList() { + return (ChanList) getSource(); + } + + @Override + public void channelBegin(ChanList list) { + clear(getSource()); + print(_pixxConfiguration.getText(PixxTextProvider.SOURCE_CHANLIST_RETREIVING)); + _list.setFirst(0); + } + + private void sort(ChannelInfo[] info, int begin, int end, int deep) { + if (deep < 50) { + if (begin < end) { + ChannelInfo tmp; + + int f = (begin + end) / 2; + tmp = info[f]; + info[f] = info[begin]; + info[begin] = tmp; + + int p_pos = begin; + ChannelInfo pivot = info[p_pos]; + for (int i = begin; i <= end; i++) { + if (info[i].userCount > pivot.userCount) { + p_pos++; + tmp = info[p_pos]; + info[p_pos] = info[i]; + info[i] = tmp; + } + } + tmp = info[p_pos]; + info[p_pos] = info[begin]; + info[begin] = tmp; + + sort(info, begin, p_pos - 1, deep + 1); + sort(info, p_pos + 1, end, deep + 1); + } + } else { + for (int i = begin; i <= end; i++) { + ChannelInfo little = info[i]; + int littleindex = i; + int littleuser = little.userCount; + for (int j = i + 1; j <= end; j++) { + if (info[j].userCount > littleuser) { + little = info[j]; + littleindex = j; + littleuser = little.userCount; + } + } + + ChannelInfo tmp = info[i]; + info[i] = info[littleindex]; + info[littleindex] = tmp; + } + } + } + + private void sort(ChannelInfo[] info) { + sort(info, 0, info.length - 1, 0); + } + + @Override + public void channelEnd(ChanList list) { + ChannelInfo[] info = getChanList().getChannels(); + sort(info); + int count = info.length; + if (count > 1024) + count = 1024; + String[] lines = new String[count]; + for (int i = 0; i < count; i++) + lines[i] = format(info[i]); + + clear(getSource()); + _list.addLines(lines); + _list.setFirst(0); + _scroll.setMaximum(_list.getLineCount() - 1); + _scroll.setValue(_list.getLast()); + _hscroll.setMaximum(_list.getLogicalWidth() / 10); + } + + private String format(ChannelInfo item) { + String msg = item.name; + String count = "" + item.userCount; + for (int i = 0; i < 20 - item.name.length(); i++) + msg += " "; + msg += " " + item.userCount; + for (int i = 0; i < 5 - count.length(); i++) + msg += " "; + msg += " " + item.topic; + return msg; + } + + @Override + public void channelAdded(ChannelInfo item, ChanList list) { + int count = getChanList().getChannelCount(); + int total = getChanList().getIgnoredChannelCount() + count; + if (total % 100 == 0) { + clear(getSource()); + print(_pixxConfiguration.getText(PixxTextProvider.SOURCE_CHANLIST_RETREIVING) + " (" + count + "/" + total + ")"); + _list.setFirst(0); + } + } + + @Override + public void valueChanged(PixxScrollBar pixScrollBar) { + if (pixScrollBar == _hscroll) + _list.setLeft(_hscroll.getValue() * 10); + else + super.valueChanged(pixScrollBar); + } + + @Override + public void virtualSizeChanged(StyledList lis) { + _hscroll.setMaximum(_list.getLogicalWidth() / 10); + super.virtualSizeChanged(lis); + } +} diff --git a/src/main/java/irc/gui/pixx/AWTChannel.java b/src/main/java/irc/gui/pixx/AWTChannel.java new file mode 100644 index 0000000..0a4a3a8 --- /dev/null +++ b/src/main/java/irc/gui/pixx/AWTChannel.java @@ -0,0 +1,394 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.pixx; + +import irc.Channel; +import irc.ChannelListener2; +import irc.ModeHandler; +import irc.style.StyledList; +import irc.tree.SortedList; + +import java.awt.BorderLayout; +import java.awt.Label; +import java.awt.Panel; +import java.awt.event.MouseEvent; +import java.util.Enumeration; +import java.util.Hashtable; + +/** + * NickNameComparator. + */ +class NickNameComparator implements irc.tree.Comparator { + private char[] _prefixes; + + /** + * Create a new NickNameComparator + * + * @param prefixes + */ + public NickNameComparator(char[] prefixes) { + _prefixes = prefixes; + } + + private int getPrefixCompareIndex(String nick) { + if (nick.length() == 0) + return _prefixes.length; + for (int i = _prefixes.length - 1; i >= 0; i--) + if (nick.charAt(0) == _prefixes[i]) + return i; + return _prefixes.length; + } + + @Override + public int compare(Object i1, Object i2) { + String n1 = (String) i1; + String n2 = (String) i2; + n1 = n1.toLowerCase(java.util.Locale.ENGLISH).toUpperCase(java.util.Locale.ENGLISH); + n2 = n2.toLowerCase(java.util.Locale.ENGLISH).toUpperCase(java.util.Locale.ENGLISH); + int prefixCmp = getPrefixCompareIndex(n1) - getPrefixCompareIndex(n2); + if (prefixCmp < 0) + return -1; + if (prefixCmp > 0) + return 1; + + return n1.compareTo(n2); + } +} + +/** + * The AWT Channel. + */ +public class AWTChannel extends BaseAWTSource implements ChannelListener2, PixxNickListListener { + private ScrollablePixxNickList _nicks; + private Label _label; + private SortedList _sortedList; + private Hashtable _modeMapping; + private NickMenuHandler _menu; + + /** + * Create a new AWTChannel. + * + * @param config + * the global irc configuration. + * @param c + * the source channel. + */ + public AWTChannel(PixxConfiguration config, Channel c) { + super(config, c); + + _menu = new NickMenuHandler(config, this, c); + _nicks = new ScrollablePixxNickList(_pixxConfiguration, c.getIRCServer().getNickPrefixes()); + c.addChannelListener2(this); + _nicks.addPixxNickListListener(this); + _sortedList = new SortedList(new NickNameComparator(c.getIRCServer().getNickPrefixes())); + _modeMapping = new Hashtable(); + _label = new Label(""); + _label.setBackground(_pixxConfiguration.getColor(PixxColorModel.COLOR_BACK)); + _label.setForeground(_pixxConfiguration.getColor(PixxColorModel.COLOR_WHITE)); + if (_pixxConfiguration.getIRCConfiguration().getB("asl")) { + Panel right = new Panel(); + right.setLayout(new BorderLayout()); + right.add(_nicks, BorderLayout.CENTER); + Panel outlabel = new Panel(); + outlabel.setLayout(new BorderLayout()); + outlabel.add(new PixxSeparator(PixxSeparator.BORDER_LEFT), BorderLayout.WEST); + outlabel.add(new PixxSeparator(PixxSeparator.BORDER_RIGHT), BorderLayout.EAST); + outlabel.add(new PixxSeparator(PixxSeparator.BORDER_UP), BorderLayout.NORTH); + outlabel.add(new PixxSeparator(PixxSeparator.BORDER_DOWN), BorderLayout.SOUTH); + outlabel.add(_label, BorderLayout.CENTER); + right.add(outlabel, BorderLayout.SOUTH); + add(right, BorderLayout.EAST); + } else { + add(_nicks, BorderLayout.EAST); + } + doLayout(); + title(); + + if (_pixxConfiguration.getB("showchannelyoujoin")) + print("*** " + getText(PixxTextProvider.SOURCE_YOU_JOINED_AS, c.getName(), c.getServer().getNick()), 3); + } + + @Override + public void release() { + _menu.release(); + ((Channel) _source).removeChannelListener2(this); + _nicks.removePixxNickListListener(this); + _nicks.release(); + _menu = null; + super.release(); + } + + @Override + public void doLayout() { + _label.setText(""); + super.doLayout(); + } + + @Override + public void setVisible(boolean b) { + super.setVisible(b); + if (!b) + _nicks.dispose(); + } + + private String getFullModeNick(String nick, String mode) { + Channel c = (Channel) getSource(); + char[] _prefixes = c.getIRCServer().getNickPrefixes(); + char[] _modes = c.getIRCServer().getNickModes(); + char[][] chanmodes = c.getIRCServer().getChannelModes(); + ModeHandler h = new ModeHandler(mode, chanmodes, _modes); + for (int i = 0; i < _modes.length; i++) { + if (h.hasMode(_modes[i])) + return _prefixes[i] + nick; + } + + return nick; + } + + private String getUnprefixedNick(String nick) { + if (nick.length() == 0) + return nick; + Channel c = (Channel) getSource(); + char[] _prefixes = c.getIRCServer().getNickPrefixes(); + for (int i = 0; i < _prefixes.length; i++) + if (nick.charAt(0) == _prefixes[i]) + return nick.substring(1); + return nick; + } + + private void setNicks(String[] nicks) { + for (int i = 0; i < nicks.length; i++) + addNick(nicks[i]); + } + + private void addNick(String nick) { + String mode = ((Channel) _source).getNickMode(nick); + if (mode != null) { + String full = getFullModeNick(nick, mode); + _sortedList.add(full); + _modeMapping.put(nick, full); + } + } + + private void removeNick(String nick) { + String full = (String) _modeMapping.get(nick); + if (full != null) { + _sortedList.remove(full); + _modeMapping.remove(nick); + } + } + + private void updateNick(String nick) { + removeNick(nick); + addNick(nick); + } + + private void update() { + String[] n = new String[_modeMapping.size()]; + Enumeration e = _modeMapping.keys(); + int i = 0; + while (e.hasMoreElements()) + n[i++] = (String) e.nextElement(); + _textField.setCompleteList(n); + + n = new String[_modeMapping.size()]; + e = _modeMapping.keys(); + i = 0; + while (e.hasMoreElements()) { + String nick = (String) e.nextElement(); + n[i++] = nick + ":" + ((Channel) _source).whois(getUnprefixedNick(nick)); + } + _list.setNickList(n); + + n = new String[_sortedList.getSize()]; + e = _sortedList.getItems(); + i = 0; + while (e.hasMoreElements()) { + String nick = (String) e.nextElement(); + String whois = ((Channel) _source).whois(getUnprefixedNick(nick)); + n[i++] = nick + ":" + whois; + } + + _nicks.set(n); + title(); + } + + @Override + public synchronized void nickSet(String[] nicks, String[] modes, Channel channel) { + setNicks(nicks); + update(); + } + + @Override + public synchronized void nickReset(Channel channel) { + _sortedList.clear(); + _modeMapping.clear(); + _nicks.removeAll(); + update(); + } + + @Override + public synchronized void nickJoin(String nick, String mode, Channel channel) { + addNick(nick); + update(); + if (_pixxConfiguration.getB("showchannelnickjoin")) + print("*** " + getText(PixxTextProvider.SOURCE_HAS_JOINED, nick, _source.getName()), 3); + } + + @Override + public synchronized void nickPart(String nick, String reason, Channel channel) { + removeNick(nick); + update(); + if (_pixxConfiguration.getB("showchannelnickpart")) { + if (reason.length() > 0) + print("*** " + getText(PixxTextProvider.SOURCE_HAS_LEFT, nick, _source.getName()) + " (" + reason + ")", 3); + else + print("*** " + getText(PixxTextProvider.SOURCE_HAS_LEFT, nick, _source.getName()), 3); + } + } + + @Override + public synchronized void nickKick(String nick, String by, String reason, Channel channel) { + removeNick(nick); + update(); + if (_pixxConfiguration.getB("showchannelnickkick")) { + if (reason.length() > 0) + print("*** " + getText(PixxTextProvider.SOURCE_HAS_BEEN_KICKED_BY, nick, by) + " (" + reason + ")", 3); + else + print("*** " + getText(PixxTextProvider.SOURCE_HAS_BEEN_KICKED_BY, nick, by), 3); + } + if (nick.equals(_source.getServer().getNick())) { + _source.getServer().sendStatusMessage( + getText(PixxTextProvider.SOURCE_YOU_KICKED, channel.getName(), by) + " (" + reason + ")"); + } + } + + @Override + public synchronized void nickQuit(String nick, String reason, Channel channel) { + removeNick(nick); + update(); + if (_pixxConfiguration.getB("showchannelnickquit")) { + if (reason.length() > 0) + print("*** " + getText(PixxTextProvider.SOURCE_HAS_QUIT, nick) + " (" + reason + ")", 2); + else + print("*** " + getText(PixxTextProvider.SOURCE_HAS_QUIT, nick), 2); + } + } + + private void title() { + int count = _sortedList.getSize(); + String title = ""; + if (_pixxConfiguration.getB("displaychannelname")) + title += _source.getName(); + if (_pixxConfiguration.getB("displaychannelcount")) + title += " [" + count + "]"; + if (_pixxConfiguration.getB("displaychannelmode")) + title += " [" + ((Channel) _source).getMode() + "]"; + if (_pixxConfiguration.getB("displaychanneltopic")) { + if (title.length() != 0) + title += ": " + ((Channel) _source).getTopic(); + else + title = ((Channel) _source).getTopic(); + } + setTitle(title.trim()); + } + + @Override + public synchronized void topicChanged(String topic, String by, Channel channel) { + if (_pixxConfiguration.getB("showchanneltopicchanged")) { + if (by.length() == 0) + print("*** " + getText(PixxTextProvider.SOURCE_TOPIC_IS, topic), 3); + else + print("*** " + getText(PixxTextProvider.SOURCE_CHANGED_TOPIC, by, topic), 3); + } + title(); + } + + @Override + public synchronized void modeApply(String mode, String from, Channel channel) { + if (_pixxConfiguration.getB("showchannelmodeapply")) { + if (from.length() > 0) + print("*** " + getText(PixxTextProvider.SOURCE_CHANNEL_MODE, from, mode), 3); + else + print("*** " + getText(PixxTextProvider.SOURCE_CHANNEL_MODE_IS, mode), 3); + } + title(); + } + + @Override + public synchronized void nickModeApply(String nick, String mode, String from, Channel channel) { + if (_pixxConfiguration.getB("showchannelnickmodeapply")) + print("*** " + getText(PixxTextProvider.SOURCE_USER_MODE, from, mode, nick), 3); + updateNick(nick); + update(); + } + + @Override + public synchronized void nickChanged(String oldNick, String newNick, Channel channel) { + if (_pixxConfiguration.getB("showchannelnickchanged")) + print("*** " + getText(PixxTextProvider.SOURCE_KNOWN_AS, oldNick, newNick), 3); + removeNick(oldNick); + addNick(newNick); + update(); + } + + @Override + public void nickWhoisUpdated(String nick, String whois, Channel channel) { + update(); + } + + @Override + public void eventOccured(String nick, MouseEvent e) { + if (_pixxConfiguration.matchMouseConfiguration("nickpopup", e)) { + _menu.popup(nick, ((Channel) _source).whois(nick), _nicks, e.getX(), e.getY()); + } else if (_pixxConfiguration.matchMouseConfiguration("nickquery", e)) { + if (_pixxConfiguration.getB("automaticqueries")) { + if (!nick.equals(_source.getServer().getNick())) { + _source.sendString("/focus Query " + nick); + _source.sendString("/query " + nick); + } + } + } + } + + @Override + public void ASLEventOccured(String nick, String info) { + _label.setText(_pixxConfiguration.getIRCConfiguration().formatASL(info)); + } + + @Override + public void nickEvent(StyledList lis, String nick, MouseEvent e) { + if (_pixxConfiguration.matchMouseConfiguration("nickpopup", e)) { + _menu.popup(nick, ((Channel) _source).whois(nick), _list, e.getX(), e.getY()); + } else { + super.nickEvent(lis, nick, e); + } + } +} diff --git a/src/main/java/irc/gui/pixx/AWTDCCChat.java b/src/main/java/irc/gui/pixx/AWTDCCChat.java new file mode 100644 index 0000000..c2725b8 --- /dev/null +++ b/src/main/java/irc/gui/pixx/AWTDCCChat.java @@ -0,0 +1,50 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.pixx; + +import irc.dcc.DCCChat; + +/** + * The AWTDCCChat. + */ +public class AWTDCCChat extends BaseAWTSource { + /** + * Create a new AWTDCCChat. + * + * @param config + * global irc configuration. + * @param s + * source DCCChat. + */ + public AWTDCCChat(PixxConfiguration config, DCCChat s) { + super(config, s); + } + +} diff --git a/src/main/java/irc/gui/pixx/AWTDCCFile.java b/src/main/java/irc/gui/pixx/AWTDCCFile.java new file mode 100644 index 0000000..8c4a4f6 --- /dev/null +++ b/src/main/java/irc/gui/pixx/AWTDCCFile.java @@ -0,0 +1,183 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.pixx; + +import irc.EventDispatcher; +import irc.dcc.DCCFile; +import irc.dcc.DCCFileListener; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Frame; +import java.awt.Label; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; + +/** + * The AWT dcc file interface. + */ +public class AWTDCCFile implements DCCFileListener, WindowListener { + /** + * The file. + */ + protected DCCFile _file; + /** + * The displayed frame. + */ + protected Frame _frame; + /** + * The progress bar. + */ + protected AWTProgressBar _bar; + private PixxConfiguration _pixxConfiguration; + + /** + * Create a new AWTDCCFile. + * + * @param config + * the global irc configuration. + * @param file + * the source DCCFile. + */ + public AWTDCCFile(PixxConfiguration config, DCCFile file) { + _pixxConfiguration = config; + _file = file; + _file.addDCCFileListener(this); + + String str = ""; + if (file.isDownloading()) + str = _pixxConfiguration.getText(PixxTextProvider.GUI_RETREIVING_FILE, _file.getSize() + ""); + else + str = _pixxConfiguration.getText(PixxTextProvider.GUI_SENDING_FILE, _file.getSize() + ""); + + Label label = new Label(str); + + _frame = new Frame(); + _frame.setBackground(Color.white); + + _frame.setLayout(new BorderLayout()); + _frame.addWindowListener(this); + + _bar = new AWTProgressBar(); + _frame.add(label, BorderLayout.NORTH); + _frame.add(_bar, BorderLayout.CENTER); + + _frame.setTitle(_file.getName()); + _frame.setSize(400, 80); + _frame.show(); + } + + /** + * Release this object. + */ + public void release() { + _frame.removeAll(); + _file.removeDCCFileListener(this); + _file = null; + _frame.removeWindowListener(this); + _frame.dispose(); + _frame = null; + } + + /** + * Get the source DCCFile. + * + * @return source DCCFile. + */ + public DCCFile getFile() { + return _file; + } + + /** + * Close this transfert. + */ + public void close() { + _frame.hide(); + } + + @Override + public void transmitted(Integer icount, DCCFile file) { + // activate(); + int count = icount.intValue(); + if ((count & 32767) == 0) { + double pc = count; + pc /= _file.getSize(); + _bar.setColor(Color.blue); + _bar.setValue(pc); + _bar.repaint(); + } + } + + @Override + public void finished(DCCFile file) { + _frame.setTitle(_pixxConfiguration.getText(PixxTextProvider.GUI_TERMINATED, _file.getName())); + _bar.setColor(Color.green); + _bar.setValue(1); + _bar.repaint(); + } + + @Override + public void failed(DCCFile file) { + _frame.setTitle(_pixxConfiguration.getText(PixxTextProvider.GUI_FAILED, _file.getName())); + _bar.setColor(Color.red); + _bar.repaint(); + + } + + @Override + public void windowActivated(WindowEvent e) { + } + + @Override + public void windowClosed(WindowEvent e) { + } + + @Override + public void windowClosing(WindowEvent e) { + EventDispatcher.dispatchEventAsync(_file, "leave", new Object[0]); + } + + @Override + public void windowDeactivated(WindowEvent e) { + } + + @Override + public void windowDeiconified(WindowEvent e) { + } + + @Override + public void windowIconified(WindowEvent e) { + } + + @Override + public void windowOpened(WindowEvent e) { + } + +} diff --git a/src/main/java/irc/gui/pixx/AWTDefaultSource.java b/src/main/java/irc/gui/pixx/AWTDefaultSource.java new file mode 100644 index 0000000..62b01d3 --- /dev/null +++ b/src/main/java/irc/gui/pixx/AWTDefaultSource.java @@ -0,0 +1,50 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.pixx; + +import irc.DefaultSource; + +/** + * The AWTDefaultSource. + */ +public class AWTDefaultSource extends BaseAWTSource { + /** + * Create a new AWTDefaultSource. + * + * @param config + * the global irc configuration. + * @param source + * the default source. + */ + public AWTDefaultSource(PixxConfiguration config, DefaultSource source) { + super(config, source); + setTitle("PJIRC"); + } +} diff --git a/src/main/java/irc/gui/pixx/AWTInterpretor.java b/src/main/java/irc/gui/pixx/AWTInterpretor.java new file mode 100644 index 0000000..d99bbf6 --- /dev/null +++ b/src/main/java/irc/gui/pixx/AWTInterpretor.java @@ -0,0 +1,141 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2005 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.pixx; + +import irc.IRCTextProvider; +import irc.NotEnoughParametersException; +import irc.RootInterpretor; +import irc.Source; + +import java.util.Enumeration; +import java.util.Locale; + +/** + * The AWT interpretor for gui-relative commands. + */ +public class AWTInterpretor extends RootInterpretor { + private PixxMDIInterface _mdi; + private PixxConfiguration _config; + + /** + * Create a new DefaultInterpretor. + * + * @param config + * global irc configuration. + * @param mdi + * the interface. + */ + public AWTInterpretor(PixxConfiguration config, PixxMDIInterface mdi) { + super(config.getIRCConfiguration()); + _mdi = mdi; + _config = config; + } + + @Override + protected void handleCommand(Source source, String cmd, String[] parts, String[] cumul) { + try { + + if (cmd.equals("dock")) { + BaseAWTSource asource = _mdi.findBaseAWTSource(source); + if (asource != null) + _mdi.dock(asource); + } else if (cmd.equals("undock")) { + BaseAWTSource asource = _mdi.findBaseAWTSource(source); + if (asource != null) + _mdi.undock(asource); + } else if (cmd.equals("color")) { + test(cmd, parts, 1); + BaseAWTSource asource = _mdi.findBaseAWTSource(source); + if (asource != null) { + String front = parts[1]; + String back = ""; + int pos = front.indexOf(","); + if (pos >= 0) { + back = front.substring(pos + 1); + front = front.substring(0, pos); + } + try { + int c = Integer.parseInt(front); + asource.setFrontColor(c); + } catch (Exception ex) { + } + try { + int c = Integer.parseInt(back); + asource.setBackColor(c); + } catch (Exception ex) { + } + } + } else if (cmd.equals("bold")) { + test(cmd, parts, 1); + BaseAWTSource asource = _mdi.findBaseAWTSource(source); + if (asource != null) { + if (parts[1].equals("1")) + asource.setBold(true); + else if (parts[1].equals("0")) + asource.setBold(false); + } + } else if (cmd.equals("underline")) { + test(cmd, parts, 1); + BaseAWTSource asource = _mdi.findBaseAWTSource(source); + if (asource != null) { + if (parts[1].equals("1")) + asource.setUnderline(true); + else if (parts[1].equals("0")) + asource.setUnderline(false); + } + } else if (cmd.equals("highlight")) { + test(cmd, parts, 1); + for (int i = 1; i < parts.length; i++) + _config.addHighLightWord(parts[i]); + } else if (cmd.equals("unhighlight")) { + test(cmd, parts, 1); + for (int i = 1; i < parts.length; i++) + _config.removeHighLightWord(parts[i]); + } else if (cmd.equals("focus")) { + test(cmd, parts, 2); + Enumeration e = source.getServer().getSources(); + while (e.hasMoreElements()) { + Source s = (Source) e.nextElement(); + if (s.getType().equals(parts[1]) + && s.getName().toLowerCase(Locale.ENGLISH).equals(parts[2].toLowerCase(Locale.ENGLISH))) { + BaseAWTSource asource = _mdi.findBaseAWTSource(s); + if (asource != null) + _mdi.setActive(asource); + break; + } + } + } else { + super.handleCommand(source, cmd, parts, cumul); + } + } catch (NotEnoughParametersException ex) { + source.report(getText(IRCTextProvider.INTERPRETOR_INSUFFICIENT_PARAMETERS, ex.getMessage())); + } + } +} diff --git a/src/main/java/irc/gui/pixx/AWTProgressBar.java b/src/main/java/irc/gui/pixx/AWTProgressBar.java new file mode 100644 index 0000000..6a0e848 --- /dev/null +++ b/src/main/java/irc/gui/pixx/AWTProgressBar.java @@ -0,0 +1,77 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.pixx; + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Panel; + +/** + * A progress bar panel. + */ +public class AWTProgressBar extends Panel { + + private double _v; + private Color _c; + + /** + * Set the value, between 0 and 1 inclusive. + * + * @param v + * the value, between 0 and 1 inclusive. + */ + public void setValue(double v) { + _v = v; + } + + /** + * Set the display color. + * + * @param c + * the display color. + */ + public void setColor(Color c) { + _c = c; + } + + @Override + public void paint(Graphics g) { + super.paint(g); + int w = getSize().width; + int h = getSize().height; + + int pos = (int) (_v * w); + g.setColor(_c); + g.fillRect(0, 0, pos, h); + g.setColor(Color.white); + g.fillRect(pos, 0, w - pos, h); + } + +} diff --git a/src/main/java/irc/gui/pixx/AWTQuery.java b/src/main/java/irc/gui/pixx/AWTQuery.java new file mode 100644 index 0000000..edf72fd --- /dev/null +++ b/src/main/java/irc/gui/pixx/AWTQuery.java @@ -0,0 +1,133 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.pixx; + +import irc.IRCServer; +import irc.Query; +import irc.QueryListener; +import irc.ReplyServerListener; +import irc.style.StyledList; + +import java.awt.event.MouseEvent; + +/** + * The AWTQuery. + */ +public class AWTQuery extends BaseAWTSource implements QueryListener, ReplyServerListener { + private NickMenuHandler _menu; + + /** + * Create a new AWTQuery. + * + * @param config + * the global irc configuration. + * @param query + * the source query. + */ + public AWTQuery(PixxConfiguration config, Query query) { + super(config, query); + _menu = new NickMenuHandler(config, this, query); + query.addQueryListener(this); + query.getIRCServer().addReplyServerListener(this); + update(); + } + + @Override + public void release() { + ((Query) _source).removeQueryListeners(this); + ((Query) _source).getIRCServer().removeReplyServerListener(this); + _menu.release(); + _menu = null; + super.release(); + } + + private void update() { + String whois = ((Query) _source).getWhois(); + String[] nick = new String[2]; + nick[0] = _source.getName() + ":" + _pixxConfiguration.getIRCConfiguration().formatASL(whois); + nick[1] = _source.getServer().getNick() + ":" + + _pixxConfiguration.getIRCConfiguration().formatASL(_source.getServer().getUserName()); + _list.setNickList(nick); + title(); + } + + private void title() { + String whois = ((Query) _source).getWhois(); + if (whois.length() > 0) + setTitle(_source.getName() + " (" + _pixxConfiguration.getIRCConfiguration().formatASL(whois) + ")"); + else + setTitle(_source.getName()); + + } + + @Override + public void nickChanged(String newNick, Query query) { + update(); + } + + @Override + public void whoisChanged(String whois, Query query) { + update(); + } + + private String whois(String nick) { + nick = nick.toLowerCase(java.util.Locale.ENGLISH); + if (nick.equals(_source.getName().toLowerCase(java.util.Locale.ENGLISH))) + return ((Query) _source).getWhois(); + if (nick.equals(_source.getServer().getNick().toLowerCase(java.util.Locale.ENGLISH))) + return _source.getServer().getUserName(); + return ""; + } + + @Override + public void nickEvent(StyledList lis, String nick, MouseEvent e) { + if (_pixxConfiguration.matchMouseConfiguration("nickpopup", e)) { + _menu.popup(nick, whois(nick), _list, e.getX(), e.getY()); + } else { + super.nickEvent(lis, nick, e); + } + } + + @Override + public Boolean replyReceived(String prefix, String id, String params[], IRCServer server) { + if (id.equals("301")) // away + { + if (params[1].toLowerCase(java.util.Locale.ENGLISH).equals( + _source.getName().toLowerCase(java.util.Locale.ENGLISH))) { + String toSend = getText(PixxTextProvider.SOURCE_AWAY, params[1]) + " :"; + for (int i = 2; i < params.length; i++) + toSend += " " + params[i]; + _source.report(toSend); + } + } + return Boolean.FALSE; + } + +} diff --git a/src/main/java/irc/gui/pixx/AWTStatus.java b/src/main/java/irc/gui/pixx/AWTStatus.java new file mode 100644 index 0000000..628bceb --- /dev/null +++ b/src/main/java/irc/gui/pixx/AWTStatus.java @@ -0,0 +1,126 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.pixx; + +import irc.IRCServer; +import irc.ReplyServerListener; +import irc.Status; +import irc.StatusListener; + +/** + * The AWTStatus. + */ +public class AWTStatus extends BaseAWTSource implements StatusListener, ReplyServerListener { + + /** + * Create a new AWTStatus. + * + * @param config + * global irc configuration. + * @param s + * source status. + */ + public AWTStatus(PixxConfiguration config, Status s) { + super(config, s); + s.addStatusListener(this); + s.getIRCServer().addReplyServerListener(this); + title(); + } + + @Override + public void release() { + ((Status) _source).removeStatusListener(this); + ((Status) _source).getIRCServer().removeReplyServerListener(this); + super.release(); + } + + private String getSourceName() { + if (!_pixxConfiguration.getIRCConfiguration().getB("multiserver")) { + if (_pixxConfiguration.getIRCConfiguration().getB("useinfo")) + return getText(PixxTextProvider.SOURCE_INFO); + return getText(PixxTextProvider.SOURCE_STATUS); + } + + return ((Status) _source).getServerName(); + } + + private void title() { + setTitle(getSourceName() + ": " + ((Status) _source).getNick() + " [" + ((Status) _source).getMode() + "]"); + } + + @Override + public String getShortTitle() { + return getSourceName(); + } + + /** + * A notice has been received. + * + * @param from + * source nickname. + * @param msg + * notice string. + */ + public void noticeReceived(String from, String msg) { + print("-" + from + "- " + msg, 5); + } + + @Override + public void nickChanged(String nick, Status status) { + print("*** " + getText(PixxTextProvider.SOURCE_YOUR_NICK, nick), 3); + title(); + } + + @Override + public void modeChanged(String mode, Status status) { + if (mode.length() > 0) + print("*** " + getText(PixxTextProvider.SOURCE_YOUR_MODE, mode), 3); + title(); + } + + @Override + public void invited(String channel, String who, Status status) { + if (status.getIRCServer().getDefaultSource() != null) + status.getIRCServer().getDefaultSource().report(getText(PixxTextProvider.SOURCE_YOU_INVITED, who, channel)); + } + + @Override + public Boolean replyReceived(String prefix, String id, String params[], IRCServer server) { + if (id.equals("301")) // away + { + String toSend = getText(PixxTextProvider.SOURCE_AWAY, params[1]) + " :"; + for (int i = 2; i < params.length; i++) + toSend += " " + params[i]; + _source.report(toSend); + } + return Boolean.FALSE; + } + +} diff --git a/src/main/java/irc/gui/pixx/AWTStyleSelector.java b/src/main/java/irc/gui/pixx/AWTStyleSelector.java new file mode 100644 index 0000000..dd1f8ab --- /dev/null +++ b/src/main/java/irc/gui/pixx/AWTStyleSelector.java @@ -0,0 +1,299 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.pixx; + +import irc.StyleContext; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.Panel; +import java.awt.event.InputEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; + +/** + * The style selector. + */ +public class AWTStyleSelector extends Panel implements MouseListener { + private PixxConfiguration _pixxConfiguration; + private StyleContext _ct; + private int _color; + private int _backColor; + private boolean _bold; + private boolean _underline; + + /** + * Create a new AWTStyleSelector. + * + * @param config + * global irc configuration. + */ + public AWTStyleSelector(PixxConfiguration config) { + super(); + _pixxConfiguration = config; + _color = 1; + _backColor = 0; + _bold = false; + _underline = false; + addMouseListener(this); + _ct = _pixxConfiguration.getIRCConfiguration().getDefaultStyleContext(); + } + + /** + * Release this object. + */ + public void release() { + removeMouseListener(this); + _pixxConfiguration = null; + } + + /** + * Set the style context. + * + * @param ct + * style context. + */ + public void setStyleContext(StyleContext ct) { + _ct = ct; + } + + @Override + public void paint(Graphics g) { + update(g); + } + + private void drawSelect(Graphics g, int i, int j) { + int x = (int) (i * getItemWidth()); + int y = (int) (j * getItemHeight()); + int w = (int) getItemWidth(); + int h = (int) getItemHeight(); + g.setColor(Color.black); + g.drawRect(x + 1, y + 1, w - 2, h - 2); + g.setColor(Color.white); + g.drawRect(x, y, w - 2, h - 2); + } + + private void drawColor(Graphics g, int i, int j, Color c) { + int x = (int) (i * getItemWidth()); + int y = (int) (j * getItemHeight()); + int w = (int) getItemWidth(); + int h = (int) getItemHeight(); + g.setColor(c); + g.fillRect(x, y, w, h); + } + + private void drawBold(Graphics g, int i, int j) { + int x = (int) (i * getItemWidth()); + int y = (int) (j * getItemHeight()); + int w = (int) getItemWidth(); + int h = (int) getItemHeight(); + int tw = g.getFontMetrics().stringWidth("a"); + g.drawString("a", x + (w - tw) / 2, y + h - (h - g.getFont().getSize()) / 2 - 2); + g.drawString("a", x + (w - tw) / 2 + 1, y + h - (h - g.getFont().getSize()) / 2 - 2); + } + + private void drawUnderline(Graphics g, int i, int j) { + int x = (int) (i * getItemWidth()); + int y = (int) (j * getItemHeight()); + int w = (int) getItemWidth(); + int h = (int) getItemHeight(); + int tw = g.getFontMetrics().stringWidth("a"); + g.drawString("a", x + (w - tw) / 2, y + h - (h - g.getFont().getSize()) / 2 - 2); + + g.drawLine(x + w / 2 - tw / 2, y + h - 1, x + w / 2 + tw / 2, y + h - 1); + } + + @Override + public void update(Graphics g) { + int w = getSize().width; + int h = getSize().height; + + Image buffer; + Graphics gra; + try { + buffer = createImage(w, h); + gra = buffer.getGraphics(); + } catch (Throwable e) { + return; + } + + Color[] cols = _pixxConfiguration.getIRCConfiguration().getStyleColors(_ct); + int c = 0; + for (int y = 0; y < 2; y++) { + for (int x = 1; x < 9; x++) { + drawColor(gra, x, y, cols[c]); + if (c == _color) + drawSelect(gra, x, y); + c++; + } + } + + gra.setColor(cols[_backColor]); + gra.fillRect(0, 0, (int) getItemWidth(), h); + + gra.setColor(cols[_color]); + drawBold(gra, 0, 0); + drawUnderline(gra, 0, 1); + + if (_bold) + drawSelect(gra, 0, 0); + if (_underline) + drawSelect(gra, 0, 1); + + g.drawImage(buffer, 0, 0, this); + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(9 * 10, 10); + } + + private double getItemWidth() { + return getSize().width / 9.0; + } + + private double getItemHeight() { + return getSize().height / 2.0; + } + + /** + * Set the front color. + * + * @param c + * the new front color. + */ + public void setFrontColor(int c) { + _color = c; + repaint(); + } + + /** + * Set the back color. + * + * @param c + * the new back color. + */ + public void setBackColor(int c) { + _backColor = c; + repaint(); + } + + /** + * Set the new bold status. + * + * @param bold + * the new bold status. + */ + public void setBold(boolean bold) { + _bold = bold; + repaint(); + } + + /** + * Set the new underline status. + * + * @param underline + * the new underline statu. + */ + public void setUnderline(boolean underline) { + _underline = underline; + repaint(); + } + + /** + * Get prefix to be used for text styling. + * + * @return text style prefix. + */ + public String getPrefix() { + String pre = ""; + if (_color != 1 || _backColor != 0) { + String c1 = ""; + if (_color != 1) { + c1 = c1 + _color; + if (_color < 10) + c1 = "0" + c1; + } + String c2 = ""; + if (_backColor != 0) { + c2 = "" + _backColor; + if (_backColor < 10) + c2 = "0" + c2; + c2 = "," + c2; + } + if (c2.length() > 0 && c1.length() == 0) + c1 = "1"; + pre = pre + (char) 3 + c1 + c2; + } + if (_bold) + pre += (char) 2; + if (_underline) + pre += (char) 31; + return pre; + } + + @Override + public void mouseClicked(MouseEvent e) { + } + + @Override + public void mouseEntered(MouseEvent e) { + } + + @Override + public void mouseExited(MouseEvent e) { + } + + @Override + public void mousePressed(MouseEvent e) { + int x = (int) (e.getX() / getItemWidth()); + int y = (int) (e.getY() / getItemHeight()); + if (x == 0) { + if (y == 0) + _bold = !_bold; + if (y == 1) + _underline = !_underline; + } else { + x--; + if ((e.getModifiers() & InputEvent.BUTTON1_MASK) != 0) + _color = x + y * 8; + else + _backColor = x + y * 8; + } + repaint(); + } + + @Override + public void mouseReleased(MouseEvent e) { + } + +} diff --git a/src/main/java/irc/gui/pixx/AWTStyleSelectorEx.java b/src/main/java/irc/gui/pixx/AWTStyleSelectorEx.java new file mode 100644 index 0000000..ebc0eee --- /dev/null +++ b/src/main/java/irc/gui/pixx/AWTStyleSelectorEx.java @@ -0,0 +1,142 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.pixx; + +import irc.EventDispatcher; +import irc.ListenerGroup; +import irc.StyleContext; + +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Font; +import java.awt.Panel; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** + * Extension for the style selector. + */ +public class AWTStyleSelectorEx extends Panel implements ActionListener, FontSelectorListener { + private ListenerGroup _lis; + private AWTStyleSelector _selector; + private FontSelector _fs; + private Button _b; + + /** + * Create a new AWTStyleSelectorEx. + * + * @param config + * global irc configuration. + */ + public AWTStyleSelectorEx(PixxConfiguration config) { + _fs = new FontSelector(config); + _selector = new AWTStyleSelector(config); + setLayout(new BorderLayout()); + add(_selector, BorderLayout.CENTER); + _b = new NonFocusableButton(config.getText(PixxTextProvider.GUI_FONT)); + _b.setForeground(config.getColor(PixxColorModel.COLOR_WHITE)); + _b.setBackground(config.getColor(PixxColorModel.COLOR_FRONT)); + _b.addActionListener(this); + if (config.getB("setfontonstyle")) + add(_b, BorderLayout.EAST); + _lis = new ListenerGroup(); + } + + /** + * Release this object. + */ + public void release() { + removeAll(); + _b.removeActionListener(this); + _selector.release(); + _fs.release(); + _selector = null; + _fs = null; + } + + /** + * Set the style context. + * + * @param ct + * style context. + */ + public void setStyleContext(StyleContext ct) { + _selector.setStyleContext(ct); + } + + /** + * Get prefix to use. + * + * @return style prefix. + */ + public String getPrefix() { + return _selector.getPrefix(); + } + + /** + * Get the style selector. + * + * @return the style selector. + */ + public AWTStyleSelector getStyleSelector() { + return _selector; + } + + /** + * Add a listener. + * + * @param lis + * listener to add. + */ + public void addAWTStyleSelectorExListener(AWTStyleSelectorExListener lis) { + _lis.addListener(lis); + } + + /** + * Remove a listener. + * + * @param lis + * listener to remove. + */ + public void removeAWTStyleSelectorExListener(AWTStyleSelectorExListener lis) { + _lis.removeListener(lis); + } + + @Override + public void actionPerformed(ActionEvent e) { + EventDispatcher.dispatchEventAsync(_fs, "selectFont", new Object[] { this }); + } + + @Override + public void fontSelected(Font f) { + if (f != null) + _lis.sendEvent("fontSelected", f); + } +} diff --git a/src/main/java/irc/gui/pixx/AWTStyleSelectorExListener.java b/src/main/java/irc/gui/pixx/AWTStyleSelectorExListener.java new file mode 100644 index 0000000..c9a8eaa --- /dev/null +++ b/src/main/java/irc/gui/pixx/AWTStyleSelectorExListener.java @@ -0,0 +1,45 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.pixx; + +import java.awt.Font; + +/** + * Extended style selector listener. + */ +public interface AWTStyleSelectorExListener { + /** + * A new font has been selected. + * + * @param fnt + * new selected font. + */ + public void fontSelected(Font fnt); +} diff --git a/src/main/java/irc/gui/pixx/BaseAWTSource.java b/src/main/java/irc/gui/pixx/BaseAWTSource.java new file mode 100644 index 0000000..9957a84 --- /dev/null +++ b/src/main/java/irc/gui/pixx/BaseAWTSource.java @@ -0,0 +1,790 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.pixx; + +import irc.AudioConfiguration; +import irc.EventDispatcher; +import irc.IRCConfiguration; +import irc.IRCTextProvider; +import irc.ListenerGroup; +import irc.Source; +import irc.SourceListener; +import irc.StringParser; +import irc.StyleContext; +import irc.gui.GUISource; +import irc.gui.common.AWTIrcTextField; +import irc.gui.common.MouseWheelPanelListener; +import irc.gui.common.MouseWheelPanelWrapper; +import irc.style.FormattedStringDrawer; +import irc.style.StyledList; +import irc.style.StyledListListener; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Frame; +import java.awt.GridLayout; +import java.awt.Panel; +import java.awt.TextArea; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.MouseEvent; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; +import java.util.Calendar; +import java.util.Enumeration; +import java.util.Locale; + +/** + * The AWT source. + */ +public class BaseAWTSource extends Panel implements GUISource, SourceListener, ActionListener, PixxScrollBarListener, + FocusListener, StyledListListener, WindowListener, MouseWheelPanelListener, AWTStyleSelectorExListener { + /** + * Enclosed source. + */ + protected Source _source; + /** + * Vertical scrollbar. + */ + protected PixxVerticalScrollBar _scroll; + /** + * Main panel. + */ + protected Panel _panel; + /** + * Styled list. + */ + protected StyledList _list; + /** + * Input text field. + */ + protected AWTIrcTextField _textField; + /** + * Used to display the title bar. + */ + protected FormattedStringDrawer _styler; + /** + * Title string. + */ + protected String _title; + /** + * Stripped title string. + */ + protected String _strippedTitle; + private ListenerGroup _listeners; + /** + * Pixx configuration. + */ + protected PixxConfiguration _pixxConfiguration; + /** + * Style selector. + */ + protected AWTStyleSelectorEx _selector; + /** + * Overall alignment. + */ + protected boolean _topToBottom; + private MouseWheelPanelWrapper _wrapper; + private String _nickPrefix; + private String _nickPostfix; + + /** + * Create a new AWTSource. + * + * @param config + * the global configuration. + * @param source + * the source of this awt source. + */ + public BaseAWTSource(PixxConfiguration config, Source source) { + this(config, source, false); + } + + /** + * Create a new AWTSource. + * + * @param config + * the global configuration. + * @param source + * the source of this awt source. + * @param topToBottom + * true if the display should be performed from top to bottom instead + * of bottom to top. + */ + public BaseAWTSource(PixxConfiguration config, Source source, boolean topToBottom) { + _topToBottom = topToBottom; + _pixxConfiguration = config; + _listeners = new ListenerGroup(); + _source = source; + addFocusListener(this); + _source.addSourceListener(this); + _panel = new Panel(); + _panel.addFocusListener(this); + _panel.setBackground(Color.white); + _scroll = new PixxVerticalScrollBar(_pixxConfiguration, 0, 0, 0.1); + _scroll.addPixxScrollBarListener(this); + setLayout(new BorderLayout()); + + IRCConfiguration ircConfiguration = _pixxConfiguration.getIRCConfiguration(); + + Color aslMale = _pixxConfiguration.getColor(PixxColorModel.COLOR_MALE); + Color aslFemeale = _pixxConfiguration.getColor(PixxColorModel.COLOR_FEMEALE); + Color aslUndef = _pixxConfiguration.getColor(PixxColorModel.COLOR_UNDEF); + _list = new StyledList(ircConfiguration, true, + ircConfiguration.getStyleContext(source.getType(), source.getName()), aslMale, aslFemeale, aslUndef); + + _list.addFocusListener(this); + _list.addStyledListListener(this); + _styler = new FormattedStringDrawer(ircConfiguration, getStyleContext()); + _textField = new AWTIrcTextField(); + + boolean b = _pixxConfiguration.getB("displayentertexthere"); + if (b) + _textField.setEnterTextHere(true, getText(PixxTextProvider.GUI_ENTER_TEXT_HERE)); + + Color[] c = ircConfiguration.getStyleColors(getStyleContext()); + _textField.setBackground(c[0]); + _textField.setForeground(c[1]); + _textField.addFocusListener(this); + Panel p = new Panel(); + p.setLayout(new BorderLayout()); + + _wrapper = new MouseWheelPanelWrapper(_panel); + _wrapper.addMouseWheelPanelListener(this); + p.add(_wrapper, BorderLayout.CENTER); + + p.add(new PixxSeparator(PixxSeparator.BORDER_LEFT), BorderLayout.WEST); + p.add(new PixxSeparator(PixxSeparator.BORDER_RIGHT), BorderLayout.EAST); + p.add(new PixxSeparator(PixxSeparator.BORDER_UP), BorderLayout.NORTH); + p.add(new PixxSeparator(PixxSeparator.BORDER_DOWN), BorderLayout.SOUTH); + + add(p, BorderLayout.CENTER); + _panel.setLayout(new BorderLayout()); + _panel.add(_scroll, BorderLayout.EAST); + _selector = new AWTStyleSelectorEx(_pixxConfiguration); + _selector.setStyleContext(getStyleContext()); + _selector.addAWTStyleSelectorExListener(this); + if (_pixxConfiguration.getB("styleselector")) { + p = new Panel(new BorderLayout()); + p.add(_textField, BorderLayout.CENTER); + p.add(_selector, BorderLayout.EAST); + add(p, BorderLayout.SOUTH); + } else { + add(_textField, BorderLayout.SOUTH); + } + + if (_topToBottom) + _list.setFirst(0); + else + _list.setLast(0); + + _textField.addActionListener(this); + setTitle(_source.getName()); + _panel.add(_list, BorderLayout.CENTER); + + _nickPrefix = reformat(_pixxConfiguration.getS("nickprefix")); + _nickPostfix = reformat(_pixxConfiguration.getS("nickpostfix")); + } + + private String reformat(String string) { + String ans = ""; + for (int i = 0; i < string.length(); i++) { + char c = string.charAt(i); + if (c == '\\') { + if (i != string.length() - 1) { + i++; + c = string.charAt(i); + if (c == 'k') + c = (char) 3; + else if (c == 'b') + c = (char) 2; + else if (c == 'u') + c = (char) 31; + else if (c == 'r') + c = (char) 22; + else if (c == 'o') + c = (char) 15; + else if (c == 's') + c = ' '; + } + } + ans += c; + } + return ans; + } + + /** + * Release this object. No further call may be performed on this object. + */ + public void release() { + _wrapper.removeMouseWheelPanelListener(this); + _source.removeSourceListener(this); + _panel.removeFocusListener(this); + _scroll.removePixxScrollBarListener(this); + _scroll.release(); + _list.removeFocusListener(this); + _list.removeStyledListListener(this); + _textField.removeFocusListener(this); + _selector.removeAWTStyleSelectorExListener(this); + _selector.release(); + _textField.removeActionListener(this); + _textField.release(); + + _list.release(); + removeAll(); + } + + /** + * Change the front color of the style selector. + * + * @param color + * the new front color. + */ + public void setFrontColor(int color) { + _selector.getStyleSelector().setFrontColor(color); + } + + /** + * Change the background color of the style selector. + * + * @param color + * the new background color. + */ + public void setBackColor(int color) { + _selector.getStyleSelector().setBackColor(color); + } + + /** + * Set the new bold status. + * + * @param bold + * the new bold status. + */ + public void setBold(boolean bold) { + _selector.getStyleSelector().setBold(bold); + } + + /** + * Set the new underline status. + * + * @param underline + * the new underline statu. + */ + public void setUnderline(boolean underline) { + _selector.getStyleSelector().setUnderline(underline); + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(600, 300); + } + + /** + * Set the current textfield text. + * + * @param txt + * new textfield text. + */ + @Override + public void setFieldText(String txt) { + _textField.setText(txt); + _textField.setCaretPosition(txt.length()); + } + + /** + * Get the current textfield text. + * + * @return the current textfield text. + */ + @Override + public String getFieldText() { + return _textField.getText(); + } + + /** + * Validate the current textfield text, as if user pressed return key. + */ + @Override + public void validateText() { + _textField.validateText(); + } + + /** + * Get style context for this awt source. + * + * @return style context for this awt source. + */ + public StyleContext getStyleContext() { + return _pixxConfiguration.getIRCConfiguration().getStyleContext(_source.getType(), _source.getName()); + } + + /** + * Get formatted text associated with the given text code, with no parameter. + * + * @param code + * text code. + * @return formatted text. + */ + public String getText(int code) { + return _pixxConfiguration.getText(code); + } + + /** + * Get formatted text associated with the given text code, with one parameter. + * + * @param code + * text code. + * @param p1 + * first parameter. + * @return formatted text. + */ + public String getText(int code, String p1) { + return _pixxConfiguration.getText(code, p1); + } + + /** + * Get formatted text associated with the given text code, with two + * parameters. + * + * @param code + * text code. + * @param p1 + * first parameter. + * @param p2 + * second parameter. + * @return formatted text. + */ + public String getText(int code, String p1, String p2) { + return _pixxConfiguration.getText(code, p1, p2); + } + + /** + * Get formatted text associated with the given text code, with three + * parameters. + * + * @param code + * text code. + * @param p1 + * first parameter. + * @param p2 + * second parameter. + * @param p3 + * third parameter. + * @return formatted text. + */ + public String getText(int code, String p1, String p2, String p3) { + return _pixxConfiguration.getText(code, p1, p2, p3); + } + + /** + * Add listener. + * + * @param lis + * the listener to add. + */ + public void addBaseAWTSourceListener(BaseAWTSourceListener lis) { + _listeners.addListener(lis); + } + + /** + * Remove listener. + * + * @param lis + * the listener to remove. + */ + public void removeBaseAWTSourceListener(BaseAWTSourceListener lis) { + _listeners.removeListener(lis); + } + + /** + * Set this source title. + * + * @param title + * the source title. + */ + public void setTitle(String title) { + if (title.equals(_title)) + return; + _title = title; + _strippedTitle = _styler.getStripped(title); + _listeners.sendEvent("titleChanged", this); + } + + /** + * Get the stripped title. + * + * @return the stripped title. + */ + public String getStrippedTitle() { + return _strippedTitle; + } + + /** + * Get the title. + * + * @return the title. + */ + @Override + public String getTitle() { + return _title; + } + + /** + * Get a shorter title. + * + * @return a shorter title. + */ + public String getShortTitle() { + return _source.getName(); + } + + /** + * Get the source. + * + * @return the source. + */ + @Override + public Source getSource() { + return _source; + } + + @Override + public void actionPerformed(ActionEvent e) { + EventDispatcher.dispatchEventAsync(this, "actionPerformedEff", new Object[] { e }); + } + + /** + * Internally used. + * + * @param e + */ + public void actionPerformedEff(ActionEvent e) { + if (_textField.getText().length() == 0) + return; + String prefix = ""; + prefix = _selector.getPrefix(); + + if (!_textField.getText().startsWith("/")) { + _source.sendUserString(prefix + _textField.getText()); + } else { + StringParser parser = new StringParser(); + String[] parts = parser.parseString(StringParser.trim(_textField.getText())); + if (parts.length >= 2) { + if (parts[0].toLowerCase(Locale.ENGLISH).equals("/join")) { + _source.sendString("/focus Channel " + parts[1]); + } + } + _source.sendUserString(_textField.getText()); + } + + if (_textField != null) + _textField.setText(""); + + } + + @Override + public void fontSelected(Font fnt) { + _list.setFont(fnt); + } + + /** + * Clear this awt source display. + * + * @param source + * source to be cleared. + */ + @Override + public void clear(Source source) { + _list.clear(); + _scroll.setMaximum(_list.getLineCount() - 1); + _scroll.setValue(_list.getLast()); + _listeners.sendEvent("eventOccured", this); + } + + /** + * Test wether the specified line should be highlighted. + * + * @param msg + * line to test. + * @return true if msg should be highlighted, false otherwise. + */ + protected boolean needHighLight(String msg) { + msg = msg.toLowerCase(java.util.Locale.ENGLISH); + if (_pixxConfiguration.highLightNick()) { + String myNick = _source.getServer().getNick().toLowerCase(java.util.Locale.ENGLISH); + if (msg.indexOf(myNick) != -1) + return true; + } + + Enumeration e = _pixxConfiguration.getHighLightWords(); + while (e.hasMoreElements()) { + String word = ((String) (e.nextElement())).toLowerCase(java.util.Locale.ENGLISH); + if (msg.indexOf(word) != -1) + return true; + } + return false; + } + + /** + * Test wether the specified line should trigger "on word" sounds. Play the + * sounds associated with the words. + * + * @param msg + * line to test. + */ + protected void checkSound(String msg) { + msg = msg.toLowerCase(java.util.Locale.ENGLISH); + AudioConfiguration ac = _pixxConfiguration.getIRCConfiguration().getAudioConfiguration(); + Enumeration e = ac.getSoundWords(); + while (e.hasMoreElements()) { + String word = ((String) (e.nextElement())).toLowerCase(java.util.Locale.ENGLISH); + if (msg.indexOf(word) != -1) + ac.onWord(word); + } + } + + /** + * Print the given message on the awt source display. + * + * @param msg + * message to print. + * @param color + * color to use. + * @param bold + * true if message should be in bold. + * @param underline + * if message should be underlined. + */ + protected void print(String msg, int color, boolean bold, boolean underline) { + if (color != 1) + msg = "\3" + color + msg; + if (bold) + msg = "\2" + msg; + if (underline) + msg = ((char) 31) + msg; + + if (_pixxConfiguration.getB("timestamp")) { + Calendar cal = Calendar.getInstance(); + String hour = "" + cal.get(Calendar.HOUR_OF_DAY); + if (hour.length() == 1) + hour = "0" + hour; + String min = "" + cal.get(Calendar.MINUTE); + if (min.length() == 1) + min = "0" + min; + msg = "[" + hour + ":" + min + "] " + msg; + } + _list.addLine(msg); + _scroll.setMaximum(_list.getLineCount() - 1); + _scroll.setValue(_list.getLast()); + _listeners.sendEvent("eventOccured", this); + } + + /** + * Print the given message on the awt source display. + * + * @param msg + * message to print. + * @param color + * color to use. + */ + protected void print(String msg, int color) { + print(msg, color, false, false); + } + + /** + * Print the given message on the awt source display. + * + * @param msg + * message to print. + */ + protected void print(String msg) { + print(msg, 1, false, false); + } + + private String formatNick(String nick) { + return _nickPrefix + nick + _nickPostfix; + } + + @Override + public void messageReceived(String nick, String str, Source source) { + checkSound(str); + if (needHighLight(str)) { + print(formatNick(nick) + str, _pixxConfiguration.getI("highlightcolor")); + } else { + print(formatNick(nick) + str); + } + } + + @Override + public void reportReceived(String msg, Source source) { + print(msg); + } + + @Override + public void noticeReceived(String from, String msg, Source source) { + print("-" + from + "- " + msg, 5); + } + + @Override + public void action(String nick, String msg, Source source) { + print("* " + nick + " " + msg, 6); + } + + /** + * Leave this awt source. + */ + public void leave() { + _source.leave(); + } + + @Override + public void mouseWheelMoved(Integer amount) { + int i = amount.intValue(); + _scroll.setValue(_scroll.getValue() + i); + if (_topToBottom) + _list.setFirst(_scroll.getValue()); + else + _list.setLast(_scroll.getValue()); + } + + @Override + public void valueChanged(PixxScrollBar pixScrollBar) { + if (_topToBottom) + _list.setFirst(_scroll.getValue()); + else + _list.setLast(_scroll.getValue()); + } + + @Override + public void focusGained(FocusEvent e) { + if (e.getComponent() != _textField) + _textField.requestFocus(); + } + + @Override + public void focusLost(FocusEvent e) { + } + + @Override + public void channelEvent(StyledList lis, String chan, MouseEvent e) { + if (_pixxConfiguration.matchMouseConfiguration("channeljoin", e)) { + _source.sendString("/focus Channel " + chan); + _source.sendString("/join " + chan); + } + } + + @Override + public void URLEvent(StyledList lis, String url, MouseEvent e) { + if (_pixxConfiguration.matchMouseConfiguration("urlopen", e)) { + _source.sendString("/url " + url); + } + } + + @Override + public void nickEvent(StyledList lis, String nick, MouseEvent e) { + if (_pixxConfiguration.matchMouseConfiguration("nickquery", e)) { + if (nick.equals(getSource().getServer().getNick())) + return; + if (_pixxConfiguration.getB("automaticqueries")) { + _source.sendString("/focus Query " + nick); + _source.sendString("/query " + nick); + } + } + } + + @Override + public String toString() { + return "AWTSource : " + getStrippedTitle(); + } + + @Override + public void setVisible(boolean b) { + super.setVisible(b); + if (!b) + _list.dispose(); + } + + @Override + public void copyEvent(StyledList lis, String txt, MouseEvent e) { + Frame f = new Frame(); + f.setTitle(getText(IRCTextProvider.GUI_COPY_WINDOW)); + f.addWindowListener(this); + f.setLayout(new GridLayout(1, 1)); + Panel p = new Panel(); + p.setLayout(new GridLayout(1, 1)); + f.add(p); + TextArea c = new TextArea(); + c.setFont(new Font("", Font.PLAIN, 12)); + + c.setText(txt); + p.add(c); + f.setSize(400, 300); + f.show(); + } + + @Override + public void virtualSizeChanged(StyledList lis) { + } + + @Override + public void windowActivated(WindowEvent e) { + } + + @Override + public void windowClosed(WindowEvent e) { + } + + @Override + public void windowClosing(WindowEvent e) { + e.getWindow().hide(); + e.getWindow().dispose(); + } + + @Override + public void windowDeactivated(WindowEvent e) { + } + + @Override + public void windowDeiconified(WindowEvent e) { + } + + @Override + public void windowIconified(WindowEvent e) { + } + + @Override + public void windowOpened(WindowEvent e) { + } + +} diff --git a/src/main/java/irc/gui/pixx/BaseAWTSourceListener.java b/src/main/java/irc/gui/pixx/BaseAWTSourceListener.java new file mode 100644 index 0000000..56274cf --- /dev/null +++ b/src/main/java/irc/gui/pixx/BaseAWTSourceListener.java @@ -0,0 +1,52 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.pixx; + +/** + * The awt source listener. + */ +public interface BaseAWTSourceListener { + /** + * This source title has changed. + * + * @param source + * the source whose title has changed. + */ + public void titleChanged(BaseAWTSource source); + + /** + * An event has occured. + * + * @param source + * the source on whose event has occured. + */ + public void eventOccured(BaseAWTSource source); + +} diff --git a/src/main/java/irc/gui/pixx/FontSelector.java b/src/main/java/irc/gui/pixx/FontSelector.java new file mode 100644 index 0000000..9f6304d --- /dev/null +++ b/src/main/java/irc/gui/pixx/FontSelector.java @@ -0,0 +1,165 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.pixx; + +import irc.EventDispatcher; + +import java.awt.Button; +import java.awt.Choice; +import java.awt.FlowLayout; +import java.awt.Font; +import java.awt.Frame; +import java.awt.Panel; +import java.awt.TextField; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; + +/** + * The font selector window. + */ +public class FontSelector implements WindowListener, ActionListener, Runnable { + private Choice _name; + private TextField _size; + private Button _ok; + private Frame _f; + private FontSelectorListener _lis; + + /** + * Create a new font selector. + * + * @param config + * the irc configuration. + */ + public FontSelector(PixxConfiguration config) { + _f = new Frame(); + _f.setTitle(config.getText(PixxTextProvider.GUI_FONT_WINDOW)); + _name = new Choice(); + _name.add("Monospaced"); + _name.add("Serif"); + _name.add("SansSerif"); + _name.add("Dialog"); + _name.add("DialogInput"); + _size = new TextField("12"); + _ok = new Button(config.getText(PixxTextProvider.GUI_FONT_WINDOW_OK)); + _ok.addActionListener(this); + Panel p = new Panel(); + _f.add(p); + p.setLayout(new FlowLayout(FlowLayout.CENTER)); + p.add(_name); + p.add(_size); + p.add(_ok); + + // _f.setResizable(false); + _f.setSize(200, 80); + _f.addWindowListener(this); + } + + @Override + public void run() { + if (_f != null) + _f.dispose(); + _f = null; + } + + /** + * Release this object. + */ + public void release() { + _ok.removeActionListener(this); + _f.removeWindowListener(this); + _f.removeAll(); + Thread t = new Thread(this, "Frame disposal thread"); + t.start(); + // _f.dispose(); + // _f=null; + _lis = null; + } + + /** + * Ask for a font to be selected, calling back the given listener once choice + * is performed. + * + * @param lis + * listener to be called once font is selected. + */ + public void selectFont(FontSelectorListener lis) { + _lis = lis; + _f.show(); + } + + @Override + public void windowActivated(WindowEvent e) { + } + + @Override + public void windowClosed(WindowEvent e) { + } + + @Override + public void windowClosing(WindowEvent e) { + _f.hide(); + } + + @Override + public void windowDeactivated(WindowEvent e) { + } + + @Override + public void windowDeiconified(WindowEvent e) { + } + + @Override + public void windowIconified(WindowEvent e) { + } + + @Override + public void windowOpened(WindowEvent e) { + } + + private Font getResult() { + String name = _name.getSelectedItem(); + int size = 12; + try { + size = (new Integer(_size.getText())).intValue(); + } catch (Exception ex) { + } + return new Font(name, Font.PLAIN, size); + } + + @Override + public void actionPerformed(ActionEvent e) { + _f.hide(); + Font f = getResult(); + if (_lis != null) + EventDispatcher.dispatchEventAsync(_lis, "fontSelected", new Object[] { f }); + } +} diff --git a/src/main/java/irc/gui/pixx/FontSelectorListener.java b/src/main/java/irc/gui/pixx/FontSelectorListener.java new file mode 100644 index 0000000..927af38 --- /dev/null +++ b/src/main/java/irc/gui/pixx/FontSelectorListener.java @@ -0,0 +1,45 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.pixx; + +import java.awt.Font; + +/** + * The font selector listener. + */ +public interface FontSelectorListener { + /** + * The given font has been selected. + * + * @param fnt + * the selected font. + */ + public void fontSelected(Font fnt); +} diff --git a/src/main/java/irc/gui/pixx/Interface.java b/src/main/java/irc/gui/pixx/Interface.java new file mode 100644 index 0000000..294a2df --- /dev/null +++ b/src/main/java/irc/gui/pixx/Interface.java @@ -0,0 +1,48 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.pixx; + +import irc.IRCConfiguration; + +/** + * Interface entry point. + */ +public class Interface extends PixxMDIInterface { + /** + * Create a new Interface + * + * @param conf + * IRCConfiguraion. + * @throws Exception + */ + public Interface(IRCConfiguration conf) throws Exception { + super(conf); + } +} diff --git a/src/main/java/irc/gui/pixx/NickMenuHandler.java b/src/main/java/irc/gui/pixx/NickMenuHandler.java new file mode 100644 index 0000000..58ee2e6 --- /dev/null +++ b/src/main/java/irc/gui/pixx/NickMenuHandler.java @@ -0,0 +1,163 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.pixx; + +import irc.EventDispatcher; +import irc.Source; + +import java.awt.Component; +import java.awt.MenuItem; +import java.awt.PopupMenu; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Enumeration; + +/** + * Popupmenu handling for nicknames. + */ +public class NickMenuHandler implements ActionListener { + private String _selectedNick; + private String _whoisNick; + private PopupMenu _menu; + private Source _source; + private Component _parent; + private PixxConfiguration _pixxConfiguration; + + /** + * Create a new NickMenuHandler. + * + * @param config + * the pixx configuration. + * @param parent + * a parent component for the popup menu. + * @param source + * the source associated with this popup menu. + */ + public NickMenuHandler(PixxConfiguration config, Component parent, Source source) { + _pixxConfiguration = config; + _parent = parent; + _source = source; + _menu = new PopupMenu(); + _menu.addActionListener(this); + _parent.add(_menu); + } + + /** + * Release this instance. + */ + public void release() { + _menu.removeActionListener(this); + _parent.remove(_menu); + _menu = null; + _parent = null; + _source = null; + _pixxConfiguration = null; + } + + private String parameters(String on, String[] params) { + for (int i = 0; i < on.length() - 1; i++) { + if (on.charAt(i) == '%') { + char next = on.charAt(i + 1); + if (next == '%') { + String before = on.substring(0, i); + String after = on.substring(i + 2); + on = before + "%" + after; + } else if ((next >= '1') && (next <= '9')) { + int c = next - '1'; + if (c < params.length) { + String before = on.substring(0, i); + String after = on.substring(i + 2); + on = before + params[c] + after; + } + } + } + } + return on; + } + + @Override + public void actionPerformed(ActionEvent e) { + EventDispatcher.dispatchEventAsync(this, "actionPerformedEff", new Object[] { e }); + } + + /** + * Internally used. + * + * @param e + */ + public void actionPerformedEff(ActionEvent e) { + String cmd = e.getActionCommand(); + String[] params = new String[] { _selectedNick, _source.getName(), + _pixxConfiguration.getIRCConfiguration().formatASL(_whoisNick), _whoisNick }; + for (int j = 0; j < _pixxConfiguration.getNickMenuVector().size(); j++) { + String[] cmds = (String[]) _pixxConfiguration.getNickMenuVector().elementAt(j); + if (cmds[0].equals(cmd)) { + for (int i = 1; i < cmds.length; i++) + _source.sendString(parameters(cmds[i], params)); + } + } + } + + /** + * Open and handle a popup menu for a nickname. + * + * @param nick + * the nickname. + * @param whois + * the whois or asl nickname information. + * @param c + * the component where the menu is to be displayed. This component + * must be a child of the parent component for this menu. + * @param x + * x-position relative to c. + * @param y + * y-position relative to c. + */ + public void popup(String nick, String whois, Component c, int x, int y) { + if (_pixxConfiguration.getNickMenuVector().size() == 0) + return; + _selectedNick = nick; + _whoisNick = whois; + + _menu.removeAll(); + + Enumeration keys = _pixxConfiguration.getNickMenuVector().elements(); + while (keys.hasMoreElements()) { + String[] v = (String[]) keys.nextElement(); + if (v[0].equals("--")) + _menu.addSeparator(); + else + _menu.add(new MenuItem(v[0])); + } + + _menu.show(c, x, y); + } + +} diff --git a/src/main/java/irc/gui/pixx/NonFocusableButton.java b/src/main/java/irc/gui/pixx/NonFocusableButton.java new file mode 100644 index 0000000..cb59e44 --- /dev/null +++ b/src/main/java/irc/gui/pixx/NonFocusableButton.java @@ -0,0 +1,65 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.pixx; + +import java.awt.Button; + +/** + * A NonFocusableButton is a Button that cannot receive focus via focus cycle. + */ +public class NonFocusableButton extends Button { + + /** + * Create a new NonFocusableButton. + */ + public NonFocusableButton() { + super(); + } + + /** + * Create a new NonFocusableButton. + * + * @param label + * button text. + */ + public NonFocusableButton(String label) { + super(label); + } + + @Override + public boolean isFocusTraversable() { + return false; + } + + @Override + public boolean isFocusable() { + return false; + } +} diff --git a/src/main/java/irc/gui/pixx/NonFocusableTextField.java b/src/main/java/irc/gui/pixx/NonFocusableTextField.java new file mode 100644 index 0000000..6d2d654 --- /dev/null +++ b/src/main/java/irc/gui/pixx/NonFocusableTextField.java @@ -0,0 +1,76 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.pixx; + +import java.awt.TextField; + +/** + * A NonFocusableTextField is a TextField that cannot receive focus via focus + * cycle. + */ +public class NonFocusableTextField extends TextField { + /** + * Create a new NonFocusableTextField. + */ + public NonFocusableTextField() { + super(); + } + + /** + * Create a new NonFocusableTextField. + * + * @param text + * initial field text. + */ + public NonFocusableTextField(String text) { + super(text); + } + + @Override + public boolean isFocusTraversable() { + try { + String version = System.getProperty("java.version"); + int pos = version.indexOf('.'); + String major = version.substring(0, pos); + version = version.substring(pos + 1); + pos = version.indexOf('.'); + String med = version.substring(0, pos); + int ma = Integer.parseInt(major); + int me = Integer.parseInt(med); + if (ma > 1) + return true; + if (me > 1) + return true; + return false; + } catch (Exception ex) { + return true; + } + } +} diff --git a/src/main/java/irc/gui/pixx/PixxColorModel.java b/src/main/java/irc/gui/pixx/PixxColorModel.java new file mode 100644 index 0000000..89ec08c --- /dev/null +++ b/src/main/java/irc/gui/pixx/PixxColorModel.java @@ -0,0 +1,225 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.pixx; + +import java.awt.Color; + +/** + * PixxInterface color model. + */ +public class PixxColorModel { + /** + * Black. + */ + public static final int COLOR_BLACK = 0; + /** + * White. + */ + public static final int COLOR_WHITE = 1; + /** + * Dark gray. + */ + public static final int COLOR_DARK_GRAY = 2; + /** + * Gray. + */ + public static final int COLOR_GRAY = 3; + /** + * Light gray. + */ + public static final int COLOR_LIGHT_GRAY = 4; + /** + * Front. + */ + public static final int COLOR_FRONT = 5; + /** + * Back. + */ + public static final int COLOR_BACK = 6; + /** + * Selected. + */ + public static final int COLOR_SELECTED = 7; + /** + * Event. + */ + public static final int COLOR_EVENT = 8; + /** + * Close. + */ + public static final int COLOR_CLOSE = 9; + /** + * Voice. + */ + public static final int COLOR_VOICE = 10; + /** + * Op. + */ + public static final int COLOR_OP = 11; + /** + * Semiop. + */ + public static final int COLOR_SEMIOP = 12; + /** + * ASL male. + */ + public static final int COLOR_MALE = 13; + /** + * ASL femeale. + */ + public static final int COLOR_FEMEALE = 14; + /** + * ASL undefined. + */ + public static final int COLOR_UNDEF = 15; + + private Color[] _colors; + + /** + * Create a new PixxColorModel using default colors. + */ + public PixxColorModel() { + Color[] cols = new Color[16]; + cols[0] = Color.black; + cols[1] = Color.white; + cols[2] = new Color(0x868686); + cols[3] = Color.gray; + cols[4] = new Color(0xD0D0D0); + cols[5] = new Color(0x336699); + cols[6] = new Color(0x084079); + cols[7] = new Color(0x003167); + cols[8] = new Color(0xa40000); + cols[9] = new Color(0x4B8ECE); + cols[10] = new Color(0x008000); + cols[11] = new Color(0x336699); + cols[12] = new Color(0x336699); + cols[13] = new Color(0x4040ff); + cols[14] = new Color(0xff40ff); + cols[15] = new Color(0x336699); + init(cols); + } + + /** + * Set the i'th color. + * + * @param i + * index. + * @param c + * color. + */ + public void setColor(int i, Color c) { + if ((i >= 0) && (i < _colors.length)) + _colors[i] = c; + } + + /** + * Get the number of color in the mode. + * + * @return color count. + */ + public int getColorCount() { + return _colors.length; + } + + private Color computeColor(int r, int g, int b, int i) { + r *= i; + g *= i; + b *= i; + r /= 256; + g /= 256; + b /= 256; + if (r > 255) + r = 255; + if (g > 255) + g = 255; + if (b > 255) + b = 255; + return new Color(r, g, b); + } + + /** + * Create a new PixxColorModel using given r g b basecolor. + * + * @param r + * red base color. + * @param g + * green base color. + * @param b + * blue base color. + */ + public PixxColorModel(int r, int g, int b) { + Color[] cols = new Color[16]; + cols[0] = Color.black; + cols[1] = Color.white; + cols[2] = new Color(0x868686); + cols[3] = Color.gray; + cols[4] = new Color(0xD0D0D0); + cols[8] = new Color(0xa40000); + cols[10] = new Color(0x008000); + cols[13] = new Color(0x4040ff); + cols[14] = new Color(0xff40ff); + + cols[5] = computeColor(r, g, b, 0x66); + cols[6] = computeColor(r, g, b, 0x55); + cols[7] = computeColor(r, g, b, 0x4B); + cols[9] = computeColor(r, g, b, 0x80); + cols[11] = computeColor(r, g, b, 0x66); + cols[12] = computeColor(r, g, b, 0x66); + cols[15] = computeColor(r, g, b, 0x66); + init(cols); + } + + /** + * Create a new PixxColorModel using given colors. + * + * @param cols + * colors to use. + */ + public PixxColorModel(Color[] cols) { + init(cols); + } + + private void init(Color[] cols) { + _colors = new Color[cols.length]; + for (int i = 0; i < cols.length; i++) + _colors[i] = cols[i]; + } + + /** + * Get the color at the given index. + * + * @param i + * index. + * @return the i'th color. + */ + public Color getColor(int i) { + return _colors[i]; + } +} diff --git a/src/main/java/irc/gui/pixx/PixxConfiguration.java b/src/main/java/irc/gui/pixx/PixxConfiguration.java new file mode 100644 index 0000000..651c090 --- /dev/null +++ b/src/main/java/irc/gui/pixx/PixxConfiguration.java @@ -0,0 +1,468 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2005 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.pixx; + +import irc.IRCConfiguration; +import irc.RuleList; +import irc.TextProvider; + +import java.awt.Color; +import java.awt.event.InputEvent; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Vector; + +/** + * NullItem. + */ +class NullItem { +} + +/** + * MouseEventConfiguration. + */ +class MouseEventConfiguration { + /** + * Create a new MouseEventConfiguration + * + * @param m + * mouse button mack. + * @param c + * click count. + */ + public MouseEventConfiguration(int m, int c) { + Mask = m; + ClickCount = c; + } + + /** + * Mouse button mask. + */ + public int Mask; + /** + * Click count. + */ + public int ClickCount; +} + +/** + * PixxConfiguration. + */ +public class PixxConfiguration { + private IRCConfiguration _config; + private PixxColorModel _colorModel = new PixxColorModel(); + private TextProvider _textProvider; + + private RuleList _dockingRules; + private Hashtable _htable; + private Hashtable _mouseConfig; + private Vector _highLightWords; + private Vector _nickMenuVector; + + private NullItem NULL_ITEM = new NullItem(); + + /** + * Create a new PixxConfiguration + * + * @param config + * original global configuration. + */ + public PixxConfiguration(IRCConfiguration config) { + _config = config; + _htable = new Hashtable(); + _mouseConfig = new Hashtable(); + _dockingRules = new RuleList(); + _dockingRules.setDefaultValue(new Boolean(false)); + _highLightWords = new Vector(); + _nickMenuVector = new Vector(); + } + + /** + * Get the nick menu configuration vector. + * + * @return the nick menu vector. + */ + public synchronized Vector getNickMenuVector() { + return _nickMenuVector; + } + + /** + * Set the text provider to be used. + * + * @param txt + * text provider. + */ + public void setTextProvider(TextProvider txt) { + _textProvider = txt; + } + + /** + * Configure the given mouse event name. + * + * @param eventName + * event name. + * @param button + * mouse button index. + * @param count + * mouse click count. + */ + public synchronized void setMouseConfiguration(String eventName, int button, int count) { + int mask; + switch (button) { + case 1: + mask = InputEvent.BUTTON1_MASK; + break; + case 2: + mask = InputEvent.BUTTON2_MASK; + break; + case 3: + mask = InputEvent.BUTTON3_MASK; + break; + default: + mask = InputEvent.BUTTON1_MASK; + break; + } + _mouseConfig.put(eventName.toLowerCase(java.util.Locale.ENGLISH), new MouseEventConfiguration(mask, count)); + } + + /** + * Check whether the given event name and the given mouse event match. + * + * @param eventName + * mouse event name. + * @param event + * mouse event. + * @return true if events match, false otherwise. + */ + public synchronized boolean matchMouseConfiguration(String eventName, java.awt.event.MouseEvent event) { + if (getB("ignoreallmouseevents")) + return false; + MouseEventConfiguration config = (MouseEventConfiguration) _mouseConfig.get(eventName + .toLowerCase(java.util.Locale.ENGLISH)); + if (config == null) + throw new Error(eventName + " : unknown mouse event name"); + if (config.ClickCount != event.getClickCount()) + return false; + return (event.getModifiers() & config.Mask) != 0; + } + + /** + * Set the given property to the given value. This value may be null. + * + * @param key + * property name. + * @param obj + * property value. + */ + public synchronized void set(String key, Object obj) { + if (obj == null) + obj = NULL_ITEM; + _htable.put(key.toLowerCase(java.util.Locale.ENGLISH), obj); + } + + /** + * Set the given property to the given int value. + * + * @param key + * property name. + * @param val + * property value. + */ + public synchronized void set(String key, int val) { + set(key, new Integer(val)); + } + + /** + * Set the given property to the given boolean value. + * + * @param key + * property name. + * @param val + * property value. + */ + public synchronized void set(String key, boolean val) { + set(key, new Boolean(val)); + } + + /** + * Get the given property value. + * + * @param key + * property name. + * @return the property value. + * @throws RuntimeException + * if the property is unknown. + */ + public synchronized Object get(String key) { + Object v = _htable.get(key.toLowerCase(java.util.Locale.ENGLISH)); + if (v == null) + throw new RuntimeException("Unknown configuration property " + key); + if (v == NULL_ITEM) + v = null; + return v; + } + + /** + * Get the given property value as an int value. + * + * @param key + * property name. + * @return the property value. + * @throws RuntimeException + * if the property is unknown. + */ + public synchronized int getI(String key) { + Integer i = (Integer) get(key); + return i.intValue(); + } + + /** + * Get the given property value as a boolean value. + * + * @param key + * property name. + * @return the property value. + * @throws RuntimeException + * if the property is unknown. + */ + public synchronized boolean getB(String key) { + Boolean b = (Boolean) get(key); + return b.booleanValue(); + } + + /** + * Get the given property value as String value. + * + * @param key + * property name. + * @return the property value. + * @throws RuntimeException + * if the property is unknown. + */ + public synchronized String getS(String key) { + return (String) get(key); + } + + /** + * Set highlight configuration. + * + * @param color + * hightlight color. + * @param nick + * true if nick highlight enabled. + * @param words + * hightlight words set. + */ + public synchronized void setHighLightConfig(int color, boolean nick, Vector words) { + set("highlightcolor", color); + set("highlightnick", nick); + _highLightWords = new Vector(); + for (int i = 0; i < words.size(); i++) + _highLightWords.insertElementAt(words.elementAt(i), _highLightWords.size()); + } + + /** + * Get nick highlight flag. + * + * @return nick highlight flag. + */ + public synchronized boolean highLightNick() { + return getB("highlightnick") && getB("highlight"); + } + + /** + * Get highlight words. + * + * @return enumeration of String. + */ + public synchronized Enumeration getHighLightWords() { + if (!getB("highlight")) + return new Vector().elements(); + return _highLightWords.elements(); + } + + /** + * Add a word into the highlight word list. + * + * @param word + * new word to add. + */ + public synchronized void addHighLightWord(String word) { + _highLightWords.insertElementAt(word, _highLightWords.size()); + } + + /** + * Remove a word from the highlight word list. + * + * @param word + * the word to remove. + */ + public synchronized void removeHighLightWord(String word) { + for (int i = 0; i < _highLightWords.size(); i++) { + if (((String) _highLightWords.elementAt(i)).equals(word)) { + _highLightWords.removeElementAt(i); + i--; + } + } + } + + /** + * Set the color model to be used. + * + * @param model + * the color model. + */ + public void setColorModel(PixxColorModel model) { + _colorModel = model; + } + + /** + * Get the original IRC configuration. + * + * @return original IRCConfiguration. + */ + public IRCConfiguration getIRCConfiguration() { + return _config; + } + + /** + * Get color model in use. + * + * @return color model. + */ + public PixxColorModel getColorModel() { + return _colorModel; + } + + /** + * Get the color at given index. + * + * @param i + * index. + * @return the i'th color. + */ + public Color getColor(int i) { + return _colorModel.getColor(i); + } + + /** + * Set the docking policy associated with the given source type and name. + * + * @param type + * source type. + * @param name + * source name. + * @param action + * true if source should be undocked, false otherwise. + */ + public synchronized void setDockingPolicy(String type, String name, boolean action) { + _dockingRules.addRule(new String[] { type, name }, new Boolean(action)); + } + + /** + * Get the docking policy for the given source type and name. + * + * @param type + * source type. + * @param name + * source name. + * @return true if the source should be undocked, false otherwise. + */ + public synchronized boolean getDockingPolicy(String type, String name) { + return ((Boolean) (_dockingRules.findValue(new String[] { type, name }))).booleanValue(); + } + + /** + * Get formatted text associated with the given text code, with no parameter. + * + * @param code + * text code. + * @return formatted text. + */ + public synchronized String getText(int code) { + if (code < TextProvider.USER_BASE) + return _config.getText(code); + return _textProvider.getString(code); + } + + /** + * Get formatted text associated with the given text code, with one parameter. + * + * @param code + * text code. + * @param p1 + * first parameter. + * @return formatted text. + */ + public synchronized String getText(int code, String p1) { + if (code < TextProvider.USER_BASE) + return _config.getText(code, p1); + return _textProvider.getString(code, p1); + } + + /** + * Get formatted text associated with the given text code, with two + * parameters. + * + * @param code + * text code. + * @param p1 + * first parameter. + * @param p2 + * second parameter. + * @return formatted text. + */ + public synchronized String getText(int code, String p1, String p2) { + if (code < TextProvider.USER_BASE) + return _config.getText(code, p1, p2); + return _textProvider.getString(code, p1, p2); + } + + /** + * Get formatted text associated with the given text code, with three + * parameters. + * + * @param code + * text code. + * @param p1 + * first parameter. + * @param p2 + * second parameter. + * @param p3 + * third parameter. + * @return formatted text. + */ + public synchronized String getText(int code, String p1, String p2, String p3) { + if (code < TextProvider.USER_BASE) + return _config.getText(code, p1, p2, p3); + return _textProvider.getString(code, p1, p2, p3); + } + +} diff --git a/src/main/java/irc/gui/pixx/PixxConfigurationLoader.java b/src/main/java/irc/gui/pixx/PixxConfigurationLoader.java new file mode 100644 index 0000000..81308ad --- /dev/null +++ b/src/main/java/irc/gui/pixx/PixxConfigurationLoader.java @@ -0,0 +1,309 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.pixx; + +import irc.FileTextProvider; +import irc.IRCConfiguration; +import irc.ParameterProvider; +import irc.StringParser; +import irc.TextProvider; + +import java.awt.Color; +import java.util.Vector; + +/** + * Toolkit for Configuration creation. + */ +public class PixxConfigurationLoader { + private IRCConfiguration _config; + private ParameterProvider _provider; + + /** + * Create a new PixxConfigurationLoader. + * + * @param config + * the irc configuration. + */ + public PixxConfigurationLoader(IRCConfiguration config) { + _config = config; + _provider = _config.getInterfaceParameterProvider(); + + } + + /** + * Create a new PixxConfiguration object, using the given IRCConfiguration. + * + * @return a new PixxConfiguration instance. + * @throws Exception + * if an error occurs. + */ + public PixxConfiguration loadPixxConfiguration() throws Exception { + return getPixxConfiguration(); + } + + private String getParameter(String key) { + return _provider.getParameter(key); + } + + private boolean getBoolean(String key, boolean def) { + String v = getParameter(key); + if (v == null) + return def; + v = v.toLowerCase(java.util.Locale.ENGLISH).trim(); + if (v.equals("true") || v.equals("on") || v.equals("1")) + return true; + return false; + } + + private String getString(String key, String def) { + String v = getParameter(key); + if (v == null) + return def; + return v; + } + + private int getInt(String key, int def) { + String v = getParameter(key); + if (v == null) + return def; + try { + return Integer.parseInt(v); + } catch (Exception e) { + return def; + } + + } + + private TextProvider getTextProvider() { + String lang = getString("language", "pixx-english"); + String encoding = getString("languageencoding", ""); + String extension = getString("lngextension", "lng"); + String backlang = getString("backuplanguage", "pixx-english"); + String backencoding = getString("backuplanguageencoding", ""); + return new FileTextProvider(lang + "." + extension, encoding, backlang + "." + extension, backencoding, + _config.getFileHandler()); + } + + private String[] getArray(String name) { + Vector v = new Vector(); + String cmd; + int i = 1; + do { + cmd = getParameter(name + i); + if (cmd != null) + v.insertElementAt(cmd, v.size()); + i++; + } while (cmd != null); + String[] ans = new String[v.size()]; + for (i = 0; i < v.size(); i++) + ans[i] = (String) v.elementAt(i); + return ans; + } + + private void readDocking(PixxConfiguration config) { + StringParser parser = new StringParser(); + String[] arr = getArray("dockingconfig"); + for (int i = 0; i < arr.length; i++) { + String cmd = arr[i]; + String back[] = parser.parseString(cmd); + if (back.length >= 3) { + String type = back[0].toLowerCase(java.util.Locale.ENGLISH); + String name = back[1].toLowerCase(java.util.Locale.ENGLISH); + String action = back[2].toLowerCase(java.util.Locale.ENGLISH); + boolean undock = false; + if (action.equals("undock")) + undock = true; + config.setDockingPolicy(type, name, undock); + } + } + } + + private void readMouse(PixxConfiguration config, String name, int button, int click) throws Exception { + String s = getString("mouse" + name.toLowerCase(java.util.Locale.ENGLISH), button + " " + click); + int pos = s.indexOf(' '); + if (pos < 0) + throw new Exception("mouse" + name.toLowerCase(java.util.Locale.ENGLISH) + " parameter syntax error"); + String before = s.substring(0, pos).trim(); + String after = s.substring(pos + 1).trim(); + config.setMouseConfiguration(name, new Integer(before).intValue(), new Integer(after).intValue()); + } + + private String[] getHighLightWords() { + String words = getParameter("highlightwords"); + if (words == null) + return new String[0]; + return new StringParser().parseString(words); + } + + private void add(Vector v, Object o) { + v.insertElementAt(o, v.size()); + } + + private void str2(Vector v, PixxConfiguration c, int id, String str) { + add(v, new String[] { c.getText(id), str }); + } + + /** + * Load default popup menu configuration, based on the global + * IRCConfiguration. + * + * @param config + * global IRCConfiguration. + */ + public void loadDefaultPopup(PixxConfiguration config) { + Vector v = config.getNickMenuVector(); + String[] str; + + boolean b = config.getB("showstatus") && !config.getIRCConfiguration().getB("useinfo"); + if (b) + str2(v, config, PixxTextProvider.GUI_WHOIS, "/whois %1"); + str2(v, config, PixxTextProvider.GUI_QUERY, "/query %1"); + str2(v, config, PixxTextProvider.GUI_KICK, "/kick %2 %1"); + str2(v, config, PixxTextProvider.GUI_BAN, "/mode %2 +b %1"); + str = new String[4]; + str[0] = config.getText(PixxTextProvider.GUI_KICKBAN); + str[1] = "/mode %2 -o %1"; + str[2] = "/mode %2 +b %1"; + str[3] = "/kick %2 %1"; + add(v, str); + + add(v, new String[] { "--" }); + str2(v, config, PixxTextProvider.GUI_OP, "/mode %2 +o %1"); + str2(v, config, PixxTextProvider.GUI_DEOP, "/mode %2 -o %1"); + str2(v, config, PixxTextProvider.GUI_VOICE, "/mode %2 +v %1"); + str2(v, config, PixxTextProvider.GUI_DEVOICE, "/mode %2 -v %1"); + if (b) { + add(v, new String[] { "--" }); + str2(v, config, PixxTextProvider.GUI_PING, "/ctcp ping %1"); + str2(v, config, PixxTextProvider.GUI_VERSION, "/ctcp version %1"); + str2(v, config, PixxTextProvider.GUI_TIME, "/ctcp time %1"); + str2(v, config, PixxTextProvider.GUI_FINGER, "/ctcp finger %1"); + } + } + + private void readPopup(PixxConfiguration config) { + if (!getBoolean("configurepopup", false)) { + loadDefaultPopup(config); + return; + } + Vector v = config.getNickMenuVector(); + String[] str = getArray("popupmenustring"); + for (int i = 0; i < str.length; i++) { + + String cmd[] = getArray("popupmenucommand" + (i + 1) + "_"); + String[] fin = new String[1 + cmd.length]; + fin[0] = str[i]; + for (int j = 0; j < cmd.length; j++) + fin[j + 1] = cmd[j]; + add(v, fin); + } + } + + private PixxColorModel getColorModel() { + PixxColorModel model = new PixxColorModel(); + + for (int i = 0; i < model.getColorCount(); i++) { + String color = getParameter("color" + i); + try { + if (color != null) { + model.setColor(i, new Color(Integer.parseInt(color, 16))); + } + } catch (Exception e) { + } + } + return model; + } + + private PixxConfiguration getPixxConfiguration() throws Exception { + PixxConfiguration config = new PixxConfiguration(_config); + config.setTextProvider(getTextProvider()); + + Vector v = new Vector(); + String[] words = getHighLightWords(); + for (int i = 0; i < words.length; i++) + v.insertElementAt(words[i], v.size()); + config.setHighLightConfig(getInt("highlightcolor", 5), getBoolean("highlightnick", false), v); + config.set("highlight", getBoolean("highlight", false)); + + config.set("timestamp", getBoolean("timestamp", false)); + config.set("showclose", getBoolean("showclose", true)); + config.set("showconnect", getBoolean("showconnect", true)); + config.set("showchanlist", getBoolean("showchanlist", true)); + config.set("showabout", getBoolean("showabout", true)); + config.set("showhelp", getBoolean("showhelp", true)); + config.set("nicklistwidth", getInt("nicklistwidth", 130)); + config.set("nickfield", getBoolean("nickfield", false)); + config.set("showstatus", getBoolean("showstatus", true)); + config.set("styleselector", getBoolean("styleselector", false)); + config.set("setfontonstyle", getBoolean("setfontonstyle", false)); + config.set("helppage", getString("helppage", "http://www.pjirc.com/help.php")); + config.set("showchannelnickchanged", getBoolean("showchannelnickchanged", true)); + config.set("showchannelnickmodeapply", getBoolean("showchannelnickmodeapply", true)); + config.set("showchannelmodeapply", getBoolean("showchannelmodeapply", true)); + config.set("showchanneltopicchanged", getBoolean("showchanneltopicchanged", true)); + config.set("showchannelnickquit", getBoolean("showchannelnickquit", true)); + config.set("showchannelnickkick", getBoolean("showchannelnickkick", true)); + config.set("showchannelnickpart", getBoolean("showchannelnickpart", true)); + config.set("showchannelnickjoin", getBoolean("showchannelnickjoin", true)); + config.set("showdock", getBoolean("showdock", true)); + config.set("automaticqueries", getBoolean("automaticqueries", true)); + config.set("leftnickalign", getBoolean("leftnickalign", false)); + config.set("taskbaritemwidth", getInt("taskbaritemwidth", 100)); + config.set("scrollspeed", getInt("scrollspeed", 0)); + config.set("leaveonundockedwindowclose", getBoolean("leaveonundockedwindowclose", false)); + config.set("nickprefix", getString("nickprefix", "<")); + config.set("nickpostfix", getString("nickpostfix", "> ")); + config.set("showchannelyoujoin", getBoolean("showchannelyoujoin", false)); + + config.set("displayentertexthere", getBoolean("displayentertexthere", false)); + config.set("ignoreallmouseevents", getBoolean("ignoreallmouseevents", false)); + config.set("hideundockedsources", getBoolean("hideundockedsources", false)); + + config.set("displaychannelname", getBoolean("displaychannelname", true)); + config.set("displaychannelmode", getBoolean("displaychannelmode", true)); + config.set("displaychannelcount", getBoolean("displaychannelcount", true)); + config.set("displaychanneltopic", getBoolean("displaychanneltopic", true)); + + config.setColorModel(getColorModel()); + + readMouse(config, "nickquery", 1, 2); + readMouse(config, "urlopen", 1, 2); + readMouse(config, "channeljoin", 1, 2); + readMouse(config, "nickpopup", 3, 1); + readMouse(config, "taskbarpopup", 3, 1); + + readPopup(config); + + readDocking(config); + + return config; + } + +} diff --git a/src/main/java/irc/gui/pixx/PixxHorizontalScrollBar.java b/src/main/java/irc/gui/pixx/PixxHorizontalScrollBar.java new file mode 100644 index 0000000..29bd03f --- /dev/null +++ b/src/main/java/irc/gui/pixx/PixxHorizontalScrollBar.java @@ -0,0 +1,549 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.pixx; + +import irc.ListenerGroup; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; + +/** + * The horizontal pixx scroll bar. + */ +public class PixxHorizontalScrollBar extends PixxPanel implements PixxScrollBar, MouseListener, MouseMotionListener, + Runnable { + private double _min; + private double _max; + private double _val; + private boolean _mouseDown; + private boolean _mouseDownUp; + private boolean _mouseDownDown; + private int _base; + + private final int _arrow = 10; + private double _view; + + private MouseEvent _repeatEvent; + private int _repeatEventCount; + private Thread _repeatThread; + + private ListenerGroup _listeners; + + /** + * Create a new PixxVerticalScrollBar. + * + * @param config + * global irc configuration. + * @param min + * minimum value. + * @param max + * maximum value. + * @param view + * width of the display. + */ + public PixxHorizontalScrollBar(PixxConfiguration config, int min, int max, double view) { + super(config); + _mouseDown = false; + _view = view; + _listeners = new ListenerGroup(); + setMinimum(min); + setMaximum(max); + setValue(min); + addMouseListener(this); + addMouseMotionListener(this); + } + + @Override + public void run() { + boolean terminated = false; + _repeatEventCount = 0; + while (!terminated) { + try { + if (_repeatEventCount++ == 0) + Thread.sleep(500); + else + Thread.sleep(50); + mousePressed(_repeatEvent); + } catch (InterruptedException ex) { + terminated = true; + } + } + } + + @Override + public void release() { + removeMouseListener(this); + removeMouseMotionListener(this); + super.release(); + } + + /** + * Add a listener. + * + * @param lis + * listener to add. + */ + @Override + public void addPixxScrollBarListener(PixxScrollBarListener lis) { + _listeners.addListener(lis); + } + + /** + * Remove a listener. + * + * @param lis + * listener to remove. + */ + @Override + public void removePixxScrollBarListener(PixxScrollBarListener lis) { + _listeners.removeListener(lis); + } + + private Color[] getColors(boolean invert) { + Color[] c = new Color[5]; + if (!invert) { + c[0] = getColor(COLOR_FRONT); + c[1] = getColor(COLOR_BLACK); + c[2] = getColor(COLOR_GRAY); + c[3] = getColor(COLOR_LIGHT_GRAY); + c[4] = getColor(COLOR_WHITE); + } else { + c[0] = getColor(COLOR_SELECTED); + c[1] = getColor(COLOR_BLACK); + c[2] = getColor(COLOR_GRAY); + c[3] = getColor(COLOR_LIGHT_GRAY); + c[4] = getColor(COLOR_WHITE); + } + + return c; + } + + private void drawA(Graphics g, int pos, boolean invert) { + // int w=getSize().width; + int h = getSize().height; + int x = pos; + + Color c[] = getColors(invert); + + g.setColor(c[0]); + /* + * for(int i=0;i (h - 2 * margin) / 3) + cursorLong = (h - 2 * margin) / 3; + return cursorLong; + } + + private int getPos() { + int h = getSize().width; + int lng = h; + + int margin = getMargin(); + int cursorLong = getCursorLong(); + return (int) ((_val * (lng - margin - cursorLong) + (_max - _val) * margin) / (_max) - margin); + } + + @Override + public void update(Graphics g) { + int w = getSize().width; + int h = getSize().height; + int margin = getMargin(); + int cursorLong = getCursorLong(); + + Image buffer; + Graphics gra; + try { + buffer = createImage(w, h); + gra = buffer.getGraphics(); + } catch (Throwable e) { + return; + } + + gra.setColor(getColor(COLOR_BACK)); + gra.fillRect(0, 0, w, h); + + // fleche de gauche + drawInside(gra, 2, _arrow - 2, _mouseDownUp); + drawB(gra, margin - h, _mouseDownUp); + + Color c[] = getColors(_mouseDownUp); + gra.setColor(c[3]); + // gra.drawLine(1,0,w-2,0); + gra.drawLine(0, 1, 0, h - 2); + // gra.drawLine(0,0,0,1); + gra.drawLine(0, 0, 1, 0); + gra.setColor(c[4]); + // gra.drawLine(1,1,w-2,1); + gra.drawLine(1, 1, 1, h - 2); + gra.setColor(c[1]); + // gra.drawLine(w-1,0,w-1,1); + gra.drawLine(0, h - 1, 1, h - 1); + + gra.setColor(c[4]); + // gra.drawLine(w/2,4,w/4+1,4+w/4-1); + gra.drawLine(4, h / 2, 4 + h / 4 - 1, h / 4 + 1); + // gra.drawLine(w/2,4,3*w/4-1,4+w/4-1); + gra.drawLine(4, h / 2, 4 + h / 4 - 1, 3 * h / 4 - 1); + + // fleche de droite + drawInside(gra, w - _arrow, _arrow - 2, _mouseDownDown); + drawA(gra, w - margin + h, _mouseDownDown); + + c = getColors(_mouseDownDown); + gra.setColor(c[3]); + // gra.drawLine(0,h-2,0,h-1); + gra.drawLine(w - 2, 0, w - 1, 0); + gra.setColor(c[1]); + // gra.drawLine(w-1,h-2,w-1,h-1); + gra.drawLine(w - 2, h - 1, w - 1, h - 1); + // gra.drawLine(1,h-1,w-2,h-1); + gra.drawLine(w - 1, 1, w - 1, h - 2); + gra.setColor(c[4]); + // gra.drawLine(1,h-2,w-2,h-2); + gra.drawLine(w - 2, 1, w - 2, h - 2); + + gra.setColor(c[4]); + // gra.drawLine(w/2,h-5,w/4+1,h-5-w/4+1); + gra.drawLine(w - 5, h / 2, w - 5 - h / 4 + 1, h / 4 + 1); + // gra.drawLine(w/2,h-5,3*w/4-1,h-5-w/4+1); + gra.drawLine(w - 5, h / 2, w - 5 - h / 4 + 1, 3 * h / 4 - 1); + + // curseur + int pos = getPos() + margin; + drawInside(gra, pos, cursorLong, _mouseDown); + drawA(gra, pos, _mouseDown); + drawB(gra, pos + cursorLong, _mouseDown); + + g.drawImage(buffer, 0, 0, this); + } + + /** + * Set minimum position. + * + * @param v + * new minimum position. + */ + @Override + public void setMinimum(int v) { + _min = v; + if (_min > _max) + _min = _max; + if (_val < _min) + updateValue(_min); + repaint(); + } + + /** + * Set maximum position. + * + * @param v + * new maximum position. + */ + @Override + public void setMaximum(int v) { + _max = v; + if (_max < _min) + _max = _min; + if (_val > _max) + updateValue(_max); + repaint(); + } + + /** + * Set value. + * + * @param v + * new value. + */ + @Override + public void setValue(int v) { + _val = v; + if (_val < _min) + _val = _min; + if (_val > _max) + _val = _max; + repaint(); + } + + /** + * Get current value. + * + * @return value. + */ + @Override + public int getValue() { + return (int) (_val + 0.5); + } + + private boolean inCursor(int x, int y) { + // int w=getSize().width; + int h = getSize().height; + int l = getCursorLong(); + x -= getMargin(); + x -= getPos(); + + return (x + y >= -1) && (y + x - l - h <= -1); + } + + private boolean inSubArrow(int x, int y) { + x -= getMargin(); + return (x + y <= -1); + } + + private boolean inAddArrow(int x, int y) { + int w = getSize().width; + int h = getSize().height; + return (y + x - w + getMargin() - h >= -1); + } + + private double getValue(int x, int y) { + int w = getSize().width; + int lng = w; + int margin = getMargin(); + + lng -= margin * 2 + getCursorLong(); + + int px = x - margin - _base; + return (_max - _min) * px / lng + _min; + } + + private void updateValue(double v) { + int oldVal = getValue(); + _val = v; + if (_val < _min) + _val = _min; + if (_val > _max) + _val = _max; + repaint(); + if (getValue() != oldVal) { + _listeners.sendEventAsync("valueChanged", this); + } + } + + @Override + public void mouseClicked(MouseEvent e) { + } + + @Override + public void mouseEntered(MouseEvent e) { + } + + @Override + public void mouseExited(MouseEvent e) { + } + + private void beginRepeat(MouseEvent e) { + _repeatEvent = e; + _repeatThread = new Thread(this, "Scrolling thread"); + _repeatThread.start(); + } + + private void endRepeat() { + if (_repeatThread != null) { + try { + _repeatThread.interrupt(); + } catch (Exception ex) { + } + try { + _repeatThread.join(1000); + } catch (Exception ex) { + } + _repeatThread = null; + } + } + + @Override + public void mousePressed(MouseEvent e) { + if (inCursor(e.getX(), e.getY())) { + _base = e.getX() - getMargin() - getPos(); + _mouseDown = true; + repaint(); + return; + } else if (inSubArrow(e.getX(), e.getY())) { + _mouseDownUp = true; + updateValue(_val - 1); + repaint(); + } else if (inAddArrow(e.getX(), e.getY())) { + _mouseDownDown = true; + updateValue(_val + 1); + repaint(); + } else if (getValue(e.getX(), e.getY()) < _val) { + updateValue(_val - 10); + repaint(); + } else if (getValue(e.getX(), e.getY()) > _val) { + updateValue(_val + 10); + repaint(); + } + if (_repeatThread == null) + beginRepeat(e); + } + + @Override + public void mouseReleased(MouseEvent e) { + endRepeat(); + _mouseDown = false; + _mouseDownUp = false; + _mouseDownDown = false; + repaint(); + } + + @Override + public void mouseDragged(MouseEvent e) { + mouseMoved(e); + } + + @Override + public void mouseMoved(MouseEvent e) { + _repeatEvent = e; + if (_mouseDown) { + updateValue(getValue(e.getX(), e.getY())); + } + } +} diff --git a/src/main/java/irc/gui/pixx/PixxMDIInterface.java b/src/main/java/irc/gui/pixx/PixxMDIInterface.java new file mode 100644 index 0000000..5f4d75c --- /dev/null +++ b/src/main/java/irc/gui/pixx/PixxMDIInterface.java @@ -0,0 +1,782 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2005 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.pixx; + +import irc.ChanList; +import irc.Channel; +import irc.DefaultSource; +import irc.EventDispatcher; +import irc.IRCConfiguration; +import irc.Interpretor; +import irc.Query; +import irc.Server; +import irc.Source; +import irc.Status; +import irc.StyleContext; +import irc.dcc.DCCChat; +import irc.dcc.DCCFile; +import irc.gui.GUISource; +import irc.gui.IRCInterface; +import irc.gui.common.DockablePanel; +import irc.gui.common.DockablePanelListener; +import irc.gui.common.MouseWheelPanelListener; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Label; +import java.awt.LayoutManager; +import java.awt.MenuItem; +import java.awt.Panel; +import java.awt.PopupMenu; +import java.awt.TextField; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseEvent; +import java.util.Enumeration; +import java.util.Hashtable; + +/** + * MDILayout. + */ +class MDILayout implements LayoutManager { + private Hashtable _components; + + /** + * Create a new MDILayout + */ + public MDILayout() { + _components = new Hashtable(); + } + + @Override + public void addLayoutComponent(String name, Component comp) { + _components.put(comp, comp); + } + + private Component getVisible(Container parent) { + Component[] c = parent.getComponents(); + for (int i = 0; i < c.length; i++) + if (c[i].isVisible()) + return c[i]; + return null; + } + + @Override + public void layoutContainer(Container parent) { + Component c = getVisible(parent); + if (c == null) + return; + int w = parent.getSize().width; + int h = parent.getSize().height; + c.setBounds(0, 0, w, h); + } + + @Override + public Dimension minimumLayoutSize(Container parent) { + return new Dimension(0, 0); + } + + @Override + public Dimension preferredLayoutSize(Container parent) { + Component visible = getVisible(parent); + if (visible != null) + return visible.getPreferredSize(); + return new Dimension(0, 0); + } + + @Override + public void removeLayoutComponent(Component comp) { + _components.remove(comp); + } +} + +/** + * The multiplie document interface. + */ +public class PixxMDIInterface extends IRCInterface implements PixxTaskBarListener, PixxMenuBarListener, ActionListener, + MouseWheelPanelListener, BaseAWTSourceListener, DockablePanelListener { + private PixxPanel _panel; + private PixxMenuBar _menu; + private PixxTaskBar _task; + private Panel _mdi; + private PopupMenu _popMenu; + private TextField _nickField; + private Hashtable _awt2Dock; + private AWTInterpretor _interpretor; + private PixxConfiguration _pixxConfiguration; + + private Hashtable _status; + private Hashtable _channels; + private Hashtable _queries; + private Hashtable _dccChats; + private Hashtable _dccFiles; + private Hashtable _lists; + private DefaultSource _defaultSource; + private AWTDefaultSource _awtDefaultSource; + + /** + * Create a new PixxMDIInterface. + * + * @param config + * global irc configuration. + * @throws Exception + */ + public PixxMDIInterface(IRCConfiguration config) throws Exception { + super(config); + } + + @Override + public void load() { + super.load(); + try { + _ircConfiguration.setGUIInfoString("Pixx's designed interface"); + _pixxConfiguration = new PixxConfigurationLoader(_ircConfiguration).loadPixxConfiguration(); + _panel = new PixxPanel(_pixxConfiguration); + _defaultSource = null; + _task = new PixxTaskBar(_pixxConfiguration); + _interpretor = new AWTInterpretor(_pixxConfiguration, this); + _awt2Dock = new Hashtable(); + _popMenu = new PopupMenu(); + _panel.setLayout(new BorderLayout()); + _mdi = new Panel(); + _mdi.setLayout(new MDILayout()); + _mdi.setBackground(Color.white); + _task.add(_popMenu); + _popMenu.addActionListener(this); + _task.addPixxTaskBarListener(this); + _menu = new PixxMenuBar(_pixxConfiguration, true); + _menu.addPixxMenuBarListener(this); + _panel.add(_menu, BorderLayout.NORTH); + _panel.add(_mdi, BorderLayout.CENTER); + _nickField = new NonFocusableTextField(""); + _nickField.addActionListener(this); + _nickField.setBackground(_pixxConfiguration.getColor(PixxColorModel.COLOR_WHITE)); + + if (!_pixxConfiguration.getB("nickfield")) { + _panel.add(_task, BorderLayout.SOUTH); + } else { + Panel bottom = new Panel(); + bottom.setLayout(new BorderLayout()); + bottom.add(_task, BorderLayout.CENTER); + Panel nickConfig = new Panel(); + nickConfig.setLayout(new BorderLayout()); + Label label = new Label(_panel.getText(PixxTextProvider.GUI_CHANGE_NICK)); + label.setBackground(_pixxConfiguration.getColor(PixxColorModel.COLOR_BACK)); + label.setForeground(_pixxConfiguration.getColor(PixxColorModel.COLOR_WHITE)); + Panel outerNickLabel = new Panel(); + outerNickLabel.setLayout(new BorderLayout()); + outerNickLabel.add(label, BorderLayout.CENTER); + outerNickLabel.add(new PixxSeparator(PixxSeparator.BORDER_LEFT), BorderLayout.WEST); + outerNickLabel.add(new PixxSeparator(PixxSeparator.BORDER_RIGHT), BorderLayout.EAST); + outerNickLabel.add(new PixxSeparator(PixxSeparator.BORDER_UP), BorderLayout.NORTH); + outerNickLabel.add(new PixxSeparator(PixxSeparator.BORDER_DOWN), BorderLayout.SOUTH); + + nickConfig.add(outerNickLabel, BorderLayout.NORTH); + nickConfig.add(_nickField, BorderLayout.CENTER); + + bottom.add(nickConfig, (BorderLayout.EAST)); + _panel.add(bottom, BorderLayout.SOUTH); + } + + _channels = new Hashtable(); + _queries = new Hashtable(); + _dccChats = new Hashtable(); + _dccFiles = new Hashtable(); + _lists = new Hashtable(); + _status = new Hashtable(); + + _panel.validate(); + } catch (Exception ex) { + ex.printStackTrace(); + throw new Error(ex.getMessage()); + } + } + + @Override + public Component getComponent() { + return _panel; + } + + @Override + public void unload() { + removeAWTDefault(); + _popMenu.removeActionListener(this); + _task.removePixxTaskBarListener(this); + _menu.removePixxMenuBarListener(this); + _nickField.removeActionListener(this); + _task = null; + _menu = null; + _popMenu = null; + _awt2Dock = null; + _panel.release(); + _panel = null; + _pixxConfiguration = null; + super.unload(); + } + + private void addAWTDefault() { + if (_defaultSource == null) + return; + if (_awtDefaultSource == null) { + _awtDefaultSource = new AWTDefaultSource(_pixxConfiguration, _defaultSource); + _task.addDefaultSource(_awtDefaultSource, true); + } + } + + private void removeAWTDefault() { + if (_awtDefaultSource == null) + return; + _task.removeDefaultSource(_awtDefaultSource); + _awtDefaultSource.release(); + _awtDefaultSource = null; + } + + private void channelCreated(Channel chan, Boolean bring) { + AWTChannel awt = new AWTChannel(_pixxConfiguration, chan); + awt.addBaseAWTSourceListener(this); + _task.addChannel(awt, bring.booleanValue()); + _channels.put(chan, awt); + } + + private void channelRemoved(Channel chan) { + AWTChannel s = (AWTChannel) _channels.get(chan); + s.removeBaseAWTSourceListener(this); + _task.removeChannel(s); + _channels.remove(chan); + } + + private void queryCreated(Query query, Boolean bring) { + AWTQuery awt = new AWTQuery(_pixxConfiguration, query); + awt.addBaseAWTSourceListener(this); + _task.addQuery(awt, bring.booleanValue()); + _queries.put(query, awt); + if (!bring.booleanValue()) + _pixxConfiguration.getIRCConfiguration().getAudioConfiguration().onQuery(); + } + + private void queryRemoved(Query query) { + AWTQuery q = (AWTQuery) _queries.get(query); + q.removeBaseAWTSourceListener(this); + _task.removeQuery(q); + _queries.remove(query); + } + + private void statusCreated(Status status, Boolean bring) { + AWTStatus awt = new AWTStatus(_pixxConfiguration, status); + _task.addStatus(awt, bring.booleanValue()); + awt.addBaseAWTSourceListener(this); + _status.put(status, awt); + } + + private void statusRemoved(Status status) { + AWTStatus s = (AWTStatus) _status.get(status); + s.removeBaseAWTSourceListener(this); + _task.removeStatus(s); + _status.remove(status); + } + + private void chanListCreated(ChanList list, Boolean bring) { + AWTChanList cl = new AWTChanList(_pixxConfiguration, list); + _task.addChanList(cl, bring.booleanValue()); + cl.addBaseAWTSourceListener(this); + _lists.put(list, cl); + } + + private void chanListRemoved(ChanList list) { + AWTChanList l = (AWTChanList) _lists.get(list); + l.removeBaseAWTSourceListener(this); + _task.removeChanList(l); + _lists.remove(list); + } + + private void DCCChatCreated(DCCChat chat, Boolean bbring) { + boolean bring = bbring.booleanValue(); + AWTDCCChat awt = new AWTDCCChat(_pixxConfiguration, chat); + awt.addBaseAWTSourceListener(this); + _task.addDCCChat(awt, bring); + _dccChats.put(chat, awt); + } + + private void DCCChatRemoved(DCCChat chat) { + AWTDCCChat c = (AWTDCCChat) _dccChats.get(chat); + c.removeBaseAWTSourceListener(this); + _task.removeDCCChat(c); + _dccChats.remove(chat); + } + + /** + * A DCCFile has been created. + * + * @param file + * created file. + * @param bring + * true if source should be brang. + */ + public void DCCFileCreated(DCCFile file, Boolean bring) { + _dccFiles.put(file, new AWTDCCFile(_pixxConfiguration, file)); + } + + /** + * A DCCFile has been removed. + * + * @param file + * removed file. + */ + public void DCCFileRemoved(DCCFile file) { + AWTDCCFile f = (AWTDCCFile) _dccFiles.get(file); + _dccFiles.remove(file); + f.close(); + f.release(); + } + + @Override + public void sourceCreated(Source source, Boolean bring) { + if (source instanceof DefaultSource) { + _defaultSource = (DefaultSource) source; + if (_pixxConfiguration.getIRCConfiguration().getB("multiserver")) + addAWTDefault(); + } + + if (source instanceof Channel) + channelCreated((Channel) source, bring); + if (source instanceof Query) + queryCreated((Query) source, bring); + if (source instanceof Status) { + if (_pixxConfiguration.getB("showstatus")) + statusCreated((Status) source, bring); + } + if (source instanceof ChanList) + chanListCreated((ChanList) source, bring); + if (source instanceof DCCChat) + DCCChatCreated((DCCChat) source, bring); + if (source instanceof DCCFile) + DCCFileCreated((DCCFile) source, bring); + } + + @Override + public void sourceRemoved(Source source) { + if (source instanceof DefaultSource) { + _defaultSource = null; + removeAWTDefault(); + } + if (source instanceof Channel) + channelRemoved((Channel) source); + if (source instanceof Query) + queryRemoved((Query) source); + if (source instanceof Status) { + if (_pixxConfiguration.getB("showstatus")) + statusRemoved((Status) source); + } + if (source instanceof ChanList) + chanListRemoved((ChanList) source); + if (source instanceof DCCChat) + DCCChatRemoved((DCCChat) source); + if (source instanceof DCCFile) + DCCFileRemoved((DCCFile) source); + } + + @Override + public void serverCreated(Server s) { + } + + @Override + public void serverConnected(Server s) { + updateConnect(); + } + + @Override + public void serverDisconnected(Server s) { + updateConnect(); + } + + @Override + public void serverRemoved(Server s) { + } + + /** + * Set the title. + * + * @param title + * title string. + * @param context + * title stle context. + */ + public void setTitle(String title, StyleContext context) { + _menu.setTitle(title, context); + } + + /** + * Set the connected state. + * + * @param b + * true if connected to server, false otherwise. + */ + public void setConnected(boolean b) { + _menu.setConnected(b); + } + + private void test() { + updateConnect(); + if (_task.getActive() != null) { + setTitle(_task.getActive().getTitle(), _task.getActive().getStyleContext()); + } else { + setTitle("", _pixxConfiguration.getIRCConfiguration().getDefaultStyleContext()); + } + + triggerActiveChanged(_task.getActive()); + } + + /** + * Get active awt source. + * + * @return the current active awt source. + */ + @Override + public GUISource getActive() { + return _task.getActive(); + } + + @Override + public void setActive(GUISource source) { + _task.activate((BaseAWTSource) source); + } + + @Override + public GUISource getGUISource(Source source) { + if (source instanceof DefaultSource) + return _awtDefaultSource; + if (source instanceof Channel) + return (GUISource) _channels.get(source); + if (source instanceof Query) + return (GUISource) _queries.get(source); + if (source instanceof Status) + return (GUISource) _status.get(source); + if (source instanceof ChanList) + return (GUISource) _lists.get(source); + if (source instanceof DCCChat) + return (GUISource) _dccChats.get(source); + if (source instanceof DCCFile) + return (GUISource) _dccFiles.get(source); + return null; + } + + private DockablePanel createSource(BaseAWTSource asource) { + DockablePanel source = new DockablePanel(asource, _panel.getColor(PixxPanel.COLOR_BACK)); + source.addDockablePanelListener(this); + source.setClosingBehaviour(DockablePanel.DO_NOTHING_ON_CLOSE); + _awt2Dock.put(asource, source); + return source; + } + + private DockablePanel getSource(BaseAWTSource source) { + return (DockablePanel) _awt2Dock.get(source); + } + + private void deleteSource(BaseAWTSource source) { + DockablePanel panel = getSource(source); + if (panel != null) + panel.removeDockablePanelListener(this); + _awt2Dock.remove(source); + } + + /** + * Dock the specified source. + * + * @param source + * the source to be docked. + */ + public void dock(BaseAWTSource source) { + getSource(source).dock(); + source.requestFocus(); + if (_pixxConfiguration.getB("hideundockedsources")) + _task.show(source); + } + + /** + * Undock the specified source. + * + * @param source + * the source to be undocked. + */ + public void undock(BaseAWTSource source) { + DockablePanel todock = getSource(source); + BaseAWTSource[] srcs = _task.getZOrderedSources(); + for (int i = 0; i < srcs.length; i++) { + DockablePanel dock = getSource(srcs[i]); + if ((dock.isDocked()) && (dock != todock)) { + _task.activate(srcs[i]); + break; + } + } + todock.undock(source.getShortTitle()); + source.requestFocus(); + if (_pixxConfiguration.getB("hideundockedsources")) + _task.hide(source); + } + + /** + * Check whether the given source is docked or not. + * + * @param source + * the source to be checked. + * @return true if the source is docked, false otherwise. + */ + public boolean isDocked(BaseAWTSource source) { + return getSource(source).isDocked(); + } + + /** + * Get the interpretor for this interface. Any unrecognized command will be + * passed to this interpretor. + * + * @return the interpretor for this interface, or null if no default interface + * interpretor should be used. + */ + @Override + public Interpretor getInterpretor() { + return _interpretor; + } + + /** + * Find the AWTSource relative to the given source. + * + * @param src + * source to find AWTSource from. + * @return AWTSource relative to the given source, or null if not found. + */ + public BaseAWTSource findBaseAWTSource(Source src) { + Enumeration e = _awt2Dock.keys(); + while (e.hasMoreElements()) { + BaseAWTSource asrc = (BaseAWTSource) e.nextElement(); + if (asrc.getSource() == src) + return asrc; + } + return null; + } + + @Override + public void AWTSourceAdded(PixxTaskBar bar, BaseAWTSource asource) { + DockablePanel source = createSource(asource); + _mdi.add(source); + source.setVisible(false); + _panel.validate(); + test(); + if (_pixxConfiguration.getDockingPolicy(asource.getSource().getType().toLowerCase(java.util.Locale.ENGLISH), + asource.getSource().getName().toLowerCase(java.util.Locale.ENGLISH))) + undock(asource); + } + + @Override + public void AWTSourceRemoved(PixxTaskBar bar, BaseAWTSource asource) { + DockablePanel source = getSource(asource); + source.dock(); + deleteSource(asource); + _mdi.remove(source); + source.release(); + _panel.validate(); + test(); + } + + @Override + public void AWTSourceDesactivated(PixxTaskBar bar, BaseAWTSource asource) { + DockablePanel source = getSource(asource); + _panel.setBackground(_ircConfiguration.getStyleColors((asource.getStyleContext()))[0]); + source.setVisible(false); + _panel.validate(); + test(); + } + + @Override + public void AWTSourceActivated(PixxTaskBar bar, BaseAWTSource asource) { + if (asource != null) { + DockablePanel source = getSource(asource); + source.setVisible(true); + _panel.validate(); + source.requestFocus(); + source.bring(); + } + test(); + } + + @Override + public void eventOccured(PixxTaskBar bar, BaseAWTSource asource, MouseEvent e) { + DockablePanel source = getSource(asource); + if (_pixxConfiguration.matchMouseConfiguration("taskbarpopup", e)) { + + // _selectedSource=asource; + bar.activate(asource); + + _popMenu.removeAll(); + _popMenu.add(new MenuItem(_panel.getText(PixxTextProvider.GUI_CLOSE))); + + _popMenu.show(_task, e.getX(), e.getY()); + } + source.requestFocus(); + } + + @Override + public void actionPerformed(ActionEvent e) { + EventDispatcher.dispatchEventAsync(this, "actionPerformedEff", new Object[] { e }); + } + + /** + * Internally used. + * + * @param e + */ + public void actionPerformedEff(ActionEvent e) { + if (e.getActionCommand().equals(_panel.getText(PixxTextProvider.GUI_CLOSE))) { + // _selectedSource.leave(); + + BaseAWTSource src = _task.getActive(); + if (src != null) + src.leave(); + } else if (e.getSource() == _nickField) { + BaseAWTSource src = _task.getActive(); + if (src == null) + return; + src.getSource().sendString("/nick " + _nickField.getText()); + } + } + + @Override + public void connectionClicked(PixxMenuBar bar) { + GUISource current = getActiveSource(); + if (current == null) + return; + Server currentServer = current.getSource().getServer(); + if (currentServer == null) + return; + + if (currentServer.isConnected()) + currentServer.disconnect(); + else + currentServer.connect(); + } + + @Override + public void chanListClicked(PixxMenuBar bar) { + GUISource src = _task.getActive(); + if (src == null) + return; + src.getSource().sendString("/list"); + } + + @Override + public void aboutClicked(PixxMenuBar bar) { + _pixxConfiguration.getIRCConfiguration().displayAboutPage(); + } + + @Override + public void helpClicked(PixxMenuBar bar) { + IRCConfiguration cfg = _pixxConfiguration.getIRCConfiguration(); + if (_pixxConfiguration.getS("helppage") != null) + cfg.getURLHandler().openURL(_pixxConfiguration.getS("helppage")); + } + + @Override + public void closeClicked(PixxMenuBar bar) { + BaseAWTSource src = _task.getActive(); + if (src == null) + return; + src.leave(); + } + + @Override + public void dockClicked(PixxMenuBar bar) { + BaseAWTSource src = _task.getActive(); + if (src == null) + return; + if (isDocked(src)) + undock(src); + else + dock(src); + } + + @Override + public void mouseWheelMoved(Integer amount) { + BaseAWTSource src = _task.getActive(); + if (src == null) + return; + src.mouseWheelMoved(amount); + } + + private void updateConnect() { + BaseAWTSource active = _task.getActive(); + if (active == null) + return; + Server currentServer = active.getSource().getServer(); + setConnected(currentServer.isConnected()); + } + + /** + * Get the active source, or null if none is active. + * + * @return active source, or null. + */ + public GUISource getActiveSource() { + return _task.getActive(); + } + + @Override + public void titleChanged(BaseAWTSource source) { + if (source != getActive()) + return; + setTitle(source.getTitle(), source.getStyleContext()); + } + + @Override + public void eventOccured(BaseAWTSource source) { + } + + @Override + public void DockablePanelWindowClosing(DockablePanel panel) { + BaseAWTSource source; + Enumeration e = _awt2Dock.keys(); + while (e.hasMoreElements()) { + source = (BaseAWTSource) e.nextElement(); + if (_awt2Dock.get(source) == panel) { + if (_pixxConfiguration.getB("leaveonundockedwindowclose")) + source.leave(); + else + panel.dock(); + _task.show(source); + } + } + } + + @Override + public void DockablePanelWindowClosed(DockablePanel panel) { + } + +} diff --git a/src/main/java/irc/gui/pixx/PixxMenuBar.java b/src/main/java/irc/gui/pixx/PixxMenuBar.java new file mode 100644 index 0000000..04ed8e8 --- /dev/null +++ b/src/main/java/irc/gui/pixx/PixxMenuBar.java @@ -0,0 +1,730 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.pixx; + +import irc.IRCConfiguration; +import irc.ListenerGroup; +import irc.StyleContext; +import irc.style.DecodedLine; +import irc.style.DrawResult; +import irc.style.FormattedStringDrawer; +import irc.style.FormattedStringDrawerListener; + +import java.awt.Color; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; + +/** + * The menu bar. + */ +public class PixxMenuBar extends PixxPanel implements MouseListener, MouseMotionListener, Runnable, + FormattedStringDrawerListener { + + private int _pressedIndex; + private boolean _closePressed; + private boolean _dockPressed; + private ListenerGroup _listeners; + private boolean _connected; + private boolean _title; + private Image _buffer; + private FormattedStringDrawer _drawer; + private String _titleString; + private DecodedLine _decodedTitle; + private int _connectIndex; + private int _chanlistIndex; + private int _aboutIndex; + private int _helpIndex; + private int _titleLeft; + private int _mouseDownX; + private boolean _mouseScroll; + private DrawResult _drawResult; + private boolean _terminated; + private boolean _redrawTitle; + private Thread _scrollThread; + private Object _scrollLock; + private boolean _freeze; + private int _scrollDelay; + + /** + * Create a new PixxMenuBar without title displayed. + * + * @param config + * the global irc configuration. + */ + public PixxMenuBar(PixxConfiguration config) { + this(config, false); + } + + /** + * Create a new PixxMenuBar. + * + * @param config + * the global irc configuration. + * @param title + * true if this menu bar should display its own title, false + * otherwise. + */ + public PixxMenuBar(PixxConfiguration config, boolean title) { + super(config); + _titleLeft = 0; + _title = title; + _mouseScroll = false; + _titleString = ""; + IRCConfiguration _ircConfiguration = config.getIRCConfiguration(); + _drawer = new FormattedStringDrawer(_ircConfiguration, _ircConfiguration.getDefaultStyleContext(), this); + _decodedTitle = _drawer.decodeLine(_titleString); + _connected = false; + _pressedIndex = -1; + _closePressed = false; + _dockPressed = false; + _listeners = new ListenerGroup(); + int currentIndex = 0; + if (config.getB("showconnect")) + _connectIndex = currentIndex++; + if (config.getB("showchanlist")) + _chanlistIndex = currentIndex++; + if (config.getB("showabout")) + _aboutIndex = currentIndex++; + if (config.getB("showhelp")) + _helpIndex = currentIndex++; + _scrollDelay = config.getI("scrollspeed"); + if (_scrollDelay != 0) + _scrollDelay = 1000 / _scrollDelay; + _drawResult = new DrawResult(); + addMouseListener(this); + addMouseMotionListener(this); + _terminated = false; + _redrawTitle = false; + _scrollLock = new Object(); + if (_scrollDelay > 0) { + _scrollThread = new Thread(this); + _scrollThread.start(); + } + } + + @Override + public void release() { + removeMouseListener(this); + removeMouseMotionListener(this); + super.release(); + } + + /** + * Set title. + * + * @param title + * title string. + * @param context + * title style context. + */ + public void setTitle(String title, StyleContext context) { + _drawer.setStyleContext(context); + _titleString = title; + _decodedTitle = _drawer.decodeLine(_titleString); + _buffer = null; + repaint(); + } + + /** + * Add listener. + * + * @param lis + * listener to add. + */ + public void addPixxMenuBarListener(PixxMenuBarListener lis) { + _listeners.addListener(lis); + } + + /** + * Remove listener. + * + * @param lis + * listener to remove. + */ + public void removePixxMenuBarListener(PixxMenuBarListener lis) { + _listeners.removeListener(lis); + } + + /** + * Set the connected flag. + * + * @param b + * true if application is connected to the server, false otherwise. + */ + public void setConnected(boolean b) { + _connected = b; + _buffer = null; + repaint(); + } + + @Override + public Dimension getPreferredSize() { + if (_title) + return new Dimension(16, getItemHeight() + getTitleHeight() + 4); + return new Dimension(16, getItemHeight() + 4); + } + + private int getClosePositionX() { + int w = getSize().width; + return w - 18; + } + + private int getClosePositionY() { + return getY(0) + 1; + } + + private int getDockPositionX() { + int w = getSize().width; + if (!_pixxConfiguration.getB("showclose")) + return w - 18; + return w - 18 - 18; + } + + private int getDockPositionY() { + return getY(0) + 1; + } + + private boolean isClosePressed(int x, int y) { + if (!_pixxConfiguration.getB("showclose")) + return false; + x -= getClosePositionX(); + if (x < 0) + return false; + if (x >= 16) + return false; + y -= getClosePositionY(); + if (y < 0) + return false; + if (y >= 16) + return false; + return true; + } + + private boolean isDockPressed(int x, int y) { + if (!_pixxConfiguration.getB("showdock")) + return false; + x -= getDockPositionX(); + if (x < 0) + return false; + if (x >= 16) + return false; + y -= getDockPositionY(); + if (y < 0) + return false; + if (y >= 16) + return false; + return true; + } + + private int getItemWidth() { + return 100; + } + + private int getItemHeight() { + return 17; + } + + private int getIconWidth() { + return 16; + } + + private int getIconHeight() { + return getItemHeight() - 4; + } + + private int getX(int pos) { + return pos * (getItemWidth() + 8) + 2; + } + + private int getPos(int x) { + return (x - 2) / (getItemWidth() + 8); + } + + private int getY(int pos) { + if (!_title) + return 2; + return 2 + getTitleHeight() * 0; + } + + private int getTitleY() { + // return 0; + return getItemHeight() + 4; + } + + private int getTitleHeight() { + return 18; + } + + private int getIndex(int x) { + int pos = getPos(x); + if (pos < 0) + return -1; + if (pos > 4) + return -1; + x -= getX(pos); + if (x >= getItemWidth()) + return -1; + return pos; + } + + private int getIndex(int x, int y) { + if (y < getY(0)) + return -1; + y -= getY(0); + if (y >= getItemHeight()) + return -1; + return getIndex(x); + } + + private void drawTitle(Graphics g, int y) { + int w = getSize().width; + + g.setColor(_drawer.getColor(0)); + g.fillRect(0, y, w, getTitleHeight()); + g.setClip(0, y, w, getTitleHeight()); + _drawer.draw(_decodedTitle, g, 5 + _titleLeft, w - 5 + _titleLeft, y + getTitleHeight() - 2, 0, w - 1, false, + false, _drawResult); + g.setClip(0, 0, getSize().width, getSize().height); + + drawSeparator(g, 0, y, w, getTitleHeight()); + } + + private void drawDisconnectIcon(Graphics g, int x, int y) { + int w = getIconWidth(); + int h = getIconHeight(); + g.setColor(new Color(0xEFEFEF)); + g.fillRect(x, y, w, h); + + g.setColor(new Color(0xAFAFAF)); + g.drawLine(x, y + h / 2 - 1, x + 5, y + h / 2 - 1); + g.drawLine(x + w - 1, y + h / 2 - 1, x + w - 5, y + h / 2 - 1); + g.setColor(Color.black); + g.drawLine(x, y + h / 2, x + 4, y + h / 2); + g.drawLine(x + w - 1, y + h / 2, x + w - 6, y + h / 2); + + g.drawLine(x + 4, y + h / 2 + 1, x + 7, y + h / 2 - 2); + g.drawLine(x + 8, y + h / 2 + 1, x + 11, y + h / 2 - 2); + } + + private void drawConnectIcon(Graphics g, int x, int y) { + int w = getIconWidth(); + int h = getIconHeight(); + g.setColor(new Color(0xEFEFEF)); + g.fillRect(x, y, w, h); + + g.setColor(new Color(0xA2A2A2)); + g.drawLine(x, y + h / 2 - 1, x + w - 1, y + h / 2 - 1); + g.setColor(Color.black); + g.drawLine(x, y + h / 2, x + w - 1, y + h / 2); + + g.setColor(new Color(0x960000)); + g.drawLine(x + 2, y + 2, x + 14, y + 2); + g.drawLine(x + 12, y, x + 14, y + 2); + g.drawLine(x + 12, y + 4, x + 14, y + 2); + + g.setColor(new Color(0x2A5B90)); + g.drawLine(x + 2, y + 9, x + 14, y + 9); + g.drawLine(x + 2, y + 9, x + 4, y + 7); + g.drawLine(x + 2, y + 9, x + 4, y + 11); + } + + private void drawChanListIcon(Graphics g, int x, int y) { + int w = getIconWidth(); + int h = getIconHeight(); + g.setColor(new Color(0xEFEFEF)); + g.fillRect(x, y, w, h); + g.setColor(Color.black); + x++; + g.drawLine(x, y + 1, x + 9, y + 1); + g.drawLine(x, y + 3, x + 5, y + 3); + g.drawLine(x, y + 5, x + 12, y + 5); + g.drawLine(x, y + 7, x + 11, y + 7); + g.drawLine(x, y + 9, x + 9, y + 9); + g.drawLine(x, y + 11, x + 13, y + 11); + } + + private void drawHelpIcon(Graphics g, int x, int y) { + int w = getIconWidth(); + int h = getIconHeight(); + g.setColor(new Color(0xEFEFEF)); + g.fillRect(x, y, w, h); + g.setColor(Color.black); + x += 4; + y++; + g.fillRect(x + 0, y + 0, 2, 3); + g.fillRect(x + 2, y + 0, 4, 2); + g.fillRect(x + 6, y + 0, 2, 6); + g.fillRect(x + 3, y + 4, 3, 2); + g.fillRect(x + 3, y + 6, 2, 2); + g.fillRect(x + 3, y + 9, 2, 2); + } + + private void drawAboutIcon(Graphics g, int x, int y) { + int w = getIconWidth(); + int h = getIconHeight(); + g.setColor(new Color(0xEFEFEF)); + g.fillRect(x, y, w, h); + g.setColor(Color.black); + g.drawLine(x + 5, y + 4, x + 8, y + 4); + g.drawLine(x + 5, y + 11, x + 10, y + 11); + g.fillRect(x + 7, y + 4, 2, 7); + g.fillRect(x + 7, y + 1, 2, 2); + } + + private void drawCloseButtonCross(Graphics g, int x, int y) { + int w = 13; + int h = 11; + g.setColor(getColor(COLOR_CLOSE)); + g.fillRect(x, y, w, h); + g.setColor(getColor(COLOR_BLACK)); + for (int i = 0; i < 4; i++) { + g.drawLine(x + 3 + i, y + 2 + i, x + 4 + i, y + 2 + i); + g.drawLine(x + 9 - i, y + 2 + i, x + 10 - i, y + 2 + i); + + g.drawLine(x + 3 + i, y + 8 - i, x + 4 + i, y + 8 - i); + g.drawLine(x + 9 - i, y + 8 - i, x + 10 - i, y + 8 - i); + } + } + + private void drawDockButtonInternal(Graphics g, int x, int y) { + int w = 13; + int h = 11; + g.setColor(getColor(COLOR_CLOSE)); + g.fillRect(x, y, w, h); + g.setColor(getColor(COLOR_BLACK)); + int ox = 4; + int oy = 1; + g.drawRect(x + ox, y + oy, 6, 5); + g.drawLine(x + ox + 1, y + oy + 1, x + ox + 6, y + oy + 1); + ox = 2; + oy = 4; + g.setColor(getColor(COLOR_BLACK)); + g.drawRect(x + ox, y + oy, 6, 5); + g.drawLine(x + ox + 1, y + oy + 1, x + ox + 6, y + oy + 1); + g.setColor(getColor(COLOR_CLOSE)); + g.fillRect(x + ox + 1, y + oy + 2, 5, 3); + } + + private void drawItem(Graphics g, int x, int y, boolean selected, String s) { + int w = getItemWidth(); + int h = getItemHeight(); + int iw = getIconWidth(); + g.setColor(getColor(COLOR_FRONT)); + if (selected) + g.setColor(getColor(COLOR_SELECTED)); + g.fillRect(x, y, w, h); + g.setColor(getColor(COLOR_BLACK)); + g.drawRect(x, y, w - 1, h - 1); + g.setColor(getColor(COLOR_WHITE)); + g.drawRect(x + 1, y + 1, w - 3, h - 3); + g.drawLine(x + iw + 2, y + 1, x + iw + 2, y + h - 2); + int sw = g.getFontMetrics().stringWidth(s); + w -= (5 + iw); + g.drawString(s, x + iw + 3 + (w - sw) / 2, y + h - 4); + } + + private void drawDisconnectItem(Graphics g, int x, int y, boolean pressed) { + drawItem(g, x, y, pressed, getText(PixxTextProvider.GUI_DISCONNECT)); + drawDisconnectIcon(g, x + 2, y + 2); + } + + private void drawConnectItem(Graphics g, int x, int y, boolean pressed) { + drawItem(g, x, y, pressed, getText(PixxTextProvider.GUI_CONNECT)); + drawConnectIcon(g, x + 2, y + 2); + } + + private void drawChanListItem(Graphics g, int x, int y, boolean pressed) { + drawItem(g, x, y, pressed, getText(PixxTextProvider.GUI_CHANNELS)); + drawChanListIcon(g, x + 2, y + 2); + } + + private void drawAboutItem(Graphics g, int x, int y, boolean pressed) { + drawItem(g, x, y, pressed, getText(PixxTextProvider.GUI_ABOUT)); + drawAboutIcon(g, x + 2, y + 2); + } + + private void drawHelpItem(Graphics g, int x, int y, boolean pressed) { + drawItem(g, x, y, pressed, getText(PixxTextProvider.GUI_HELP)); + drawHelpIcon(g, x + 2, y + 2); + } + + private void drawSmallButton(Graphics g, int x, int y, boolean pressed) { + int w = 16; + int h = 16; + if (!pressed) { + g.setColor(getColor(COLOR_WHITE)); + g.drawLine(x + 0, y + 1, x + w - 2, y + 1); + g.drawLine(x + 0, y + 1, x + 0, y + h - 2); + g.setColor(getColor(COLOR_BLACK)); + g.drawLine(x + w - 1, y + h - 2, x + w - 1, y + 1); + g.drawLine(x + w - 1, y + h - 2, x + 0, y + h - 2); + g.setColor(getColor(COLOR_DARK_GRAY)); + g.drawLine(x + w - 2, y + h - 3, x + w - 2, y + 2); + g.drawLine(x + w - 2, y + h - 3, x + 1, y + h - 3); + } else { + g.setColor(getColor(COLOR_BLACK)); + g.drawLine(x + 0, y + 1, x + w - 2, y + 1); + g.drawLine(x + 0, y + 1, x + 0, y + h - 2); + g.setColor(getColor(COLOR_WHITE)); + g.drawLine(x + w - 1, y + h - 2, x + w - 1, y + 1); + g.drawLine(x + w - 1, y + h - 2, x + 0, y + h - 2); + g.setColor(getColor(COLOR_DARK_GRAY)); + g.drawLine(x + 1, y + 2, x + 1, y + h - 3); + g.drawLine(x + 1, y + 2, x + w - 2, y + 2); + } + } + + private void drawCloseButtonItem(Graphics g, int x, int y, boolean pressed) { + drawSmallButton(g, x, y, pressed); + if (!pressed) + drawCloseButtonCross(g, x + 1, y + 2); + else + drawCloseButtonCross(g, x + 2, y + 3); + } + + private void drawDockButtonItem(Graphics g, int x, int y, boolean pressed) { + drawSmallButton(g, x, y, pressed); + if (!pressed) + drawDockButtonInternal(g, x + 1, y + 2); + else + drawDockButtonInternal(g, x + 2, y + 3); + } + + @Override + public void paint(Graphics g) { + update(g); + } + + @Override + public void update(Graphics ug) { + int w = getSize().width; + int h = getSize().height; + + if (_buffer != null) { + if ((_buffer.getWidth(this) != w) || (_buffer.getHeight(this) != h)) + _buffer = null; + } + + if (_buffer == null) { + Graphics g; + try { + _buffer = createImage(w, h); + g = _buffer.getGraphics(); + } catch (Throwable e) { + return; + } + + g.setFont(new Font("", Font.PLAIN, 12)); + + // g.setColor(new Color(0x084079)); + g.setColor(getColor(COLOR_BACK)); + g.fillRect(0, 0, w, h); + + // drawSeparator(g,0,0,w,getItemHeight()+4); + + if (_pixxConfiguration.getB("showconnect")) { + if (!_connected) + drawConnectItem(g, getX(_connectIndex), getY(0), _pressedIndex == _connectIndex); + else + drawDisconnectItem(g, getX(_connectIndex), getY(0), _pressedIndex == _connectIndex); + } + if (_pixxConfiguration.getB("showchanlist")) + drawChanListItem(g, getX(_chanlistIndex), getY(0), _pressedIndex == _chanlistIndex); + if (_pixxConfiguration.getB("showabout")) + drawAboutItem(g, getX(_aboutIndex), getY(0), _pressedIndex == _aboutIndex); + if (_pixxConfiguration.getB("showhelp")) + drawHelpItem(g, getX(_helpIndex), getY(0), _pressedIndex == _helpIndex); + + if (_pixxConfiguration.getB("showclose")) + drawCloseButtonItem(g, getClosePositionX(), getClosePositionY(), _closePressed); + if (_pixxConfiguration.getB("showdock")) + drawDockButtonItem(g, getDockPositionX(), getDockPositionY(), _dockPressed); + + if (_title) + drawTitle(g, getTitleY()); + + } else { + Graphics g = _buffer.getGraphics(); + if (_redrawTitle) + drawTitle(g, getTitleY()); + } + + _redrawTitle = false; + + if (_buffer != null) + ug.drawImage(_buffer, 0, 0, this); + + } + + @Override + public void mouseClicked(MouseEvent e) { + } + + @Override + public void mouseEntered(MouseEvent e) { + } + + @Override + public void mouseExited(MouseEvent e) { + } + + @Override + public void mousePressed(MouseEvent e) { + _pressedIndex = getIndex(e.getX(), e.getY()); + _closePressed = isClosePressed(e.getX(), e.getY()); + _dockPressed = isDockPressed(e.getX(), e.getY()); + _buffer = null; + if (_title && (e.getY() >= getTitleY())) { + _mouseDownX = e.getX(); + _mouseScroll = true; + } + repaint(); + } + + @Override + public void mouseReleased(MouseEvent e) { + _mouseScroll = false; + int index = getIndex(e.getX(), e.getY()); + boolean close = isClosePressed(e.getX(), e.getY()); + boolean dock = isDockPressed(e.getX(), e.getY()); + if (index == _connectIndex) + if (_pixxConfiguration.getB("showconnect")) + _listeners.sendEventAsync("connectionClicked", this); + if (index == _chanlistIndex) + if (_pixxConfiguration.getB("showchanlist")) + _listeners.sendEventAsync("chanListClicked", this); + if (index == _aboutIndex) + if (_pixxConfiguration.getB("showabout")) + _listeners.sendEventAsync("aboutClicked", this); + if (index == _helpIndex) + if (_pixxConfiguration.getB("showhelp")) + _listeners.sendEventAsync("helpClicked", this); + if (close) + _listeners.sendEventAsync("closeClicked", this); + if (dock) + _listeners.sendEventAsync("dockClicked", this); + _closePressed = false; + _dockPressed = false; + _pressedIndex = -1; + _buffer = null; + repaint(); + } + + @Override + public void mouseMoved(MouseEvent e) { + if (_title && (e.getY() >= getTitleY())) { + if (!getCursor().equals(new Cursor(Cursor.E_RESIZE_CURSOR))) + setCursor(new Cursor(Cursor.E_RESIZE_CURSOR)); + } else { + if (!getCursor().equals(new Cursor(Cursor.DEFAULT_CURSOR))) + setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + } + } + + /** + * Release any ressources used by this component. + */ + public void dispose() { + _terminated = true; + } + + private void scrollTitle(int deltaX) { + synchronized (_scrollLock) { + + if (_drawResult.rectangle == null) + return; + _titleLeft -= deltaX; + /** --- WRAP BEHAVIOUR --- **/ + int min = -_drawResult.rectangle.width; + int max = getSize().width; + if (_titleLeft > max) + _titleLeft = min; + if (_titleLeft < min) + _titleLeft = max; + + /** --- CLAMP BEHAVIOUR --- **/ + /* + * int min=-_drawResult.rectangle.width; int max=0; if(_titleLeft>max) + * _titleLeft=max; if(_titleLeft 0) { + y -= fh + 6; + i--; + } + while ((i < _nicks.size()) && (y <= ytop + height)) { + String nick = (String) _nicks.elementAt(i); + String info = ""; + int pos = nick.indexOf(":"); + Color back = getColor(COLOR_FRONT); + if (pos != -1) { + info = nick.substring(pos + 1); + nick = nick.substring(0, pos); + back = findColor(info); + } + if (_selected == i) + back = getColor(COLOR_SELECTED); + + char prefix = 0; + for (int ci = 0; ci < _prefixes.length; ci++) + if ((nick.length() > 0) && (nick.charAt(0) == _prefixes[ci])) + prefix = _prefixes[ci]; + if (prefix > 0) + nick = nick.substring(1); + + int sw = fm.stringWidth(nick); + + gra.setColor(back); + gra.fillRect(20, y - 1, w - 28, fh + 2); + gra.setColor(getColor(COLOR_WHITE)); + gra.drawRect(20, y - 1, w - 28, fh + 2); + + gra.setColor(getColor(COLOR_WHITE)); + gra.setClip(20, y - 1, w - 28, fh + 2); + int px = w - sw - 12; + if (px < 22) + px = 22; + + if (_leftAlign) + px = 22; + + gra.drawString(nick, px, y + fh - 1); + gra.setClip(0, 0, getSize().width, getSize().height); + + if (prefix > 0) { + if (prefix == '@') + gra.setColor(getColor(COLOR_OP)); + else if (prefix == '+') + gra.setColor(getColor(COLOR_VOICE)); + else if (prefix == '%') + gra.setColor(getColor(COLOR_SEMIOP)); + else + gra.setColor(getColor(COLOR_FRONT)); + gra.fillRect(20 - fh - 6, y - 1, fh + 2, fh + 2); + gra.setColor(getColor(COLOR_WHITE)); + gra.drawRect(20 - fh - 6, y - 1, fh + 2, fh + 2); + + gra.setColor(getColor(COLOR_WHITE)); + sw = fm.stringWidth("" + prefix); + int tx = 20 - fh - 6 + (fh + 2 - sw) / 2 + 1; + int ty = y + fh - 1; + if (prefix == '@') { + tx--; + ty--; + } + gra.drawString("" + prefix, tx, ty); + } + + y += fh + 6; + i++; + } + } + + @Override + public void update(Graphics g) { + int w = getSize().width; + int h = getSize().height; + int fh = _font.getSize(); + + if (_buffer != null) { + if ((_buffer.getWidth(this) != w) || (_buffer.getHeight(this) != h)) + _buffer = null; + } + + if (_buffer == null) { + Graphics gra; + try { + _buffer = createImage(w, h); + gra = _buffer.getGraphics(); + update(gra, 0, h); + } catch (Throwable e) { + return; + } + } else { + int scr = getScrollValue(); + if (scr != 0) { + Graphics gra = _buffer.getGraphics(); + int dy = -(fh + 6) * scr; + if (dy < 0) { + gra.copyArea(0, -dy, w, h + dy, 0, dy); + update(gra, h + dy, -dy); + } else { + gra.copyArea(0, 0, w, h - dy, 0, dy); + update(gra, 0, dy); + } + } + } + + if (_buffer != null) + g.drawImage(_buffer, 0, 0, this); + if ((_overindex != -1) && _pixxConfiguration.getIRCConfiguration().getB("style:floatingasl")) { + int x = _overX; + int y = 8 + (_overindex - _base) * (fh + 6) + 2; + if (y + fh + 5 >= h) + y = h - fh - 5; + String info = getInfo(_overindex); + String text = _pixxConfiguration.getIRCConfiguration().formatASL(info); + if (text.length() > 0) { + int tw = g.getFontMetrics().stringWidth(text); + if (x + tw + 5 >= w) + x = w - tw - 5; + if (x < 0) + x = 0; + g.setColor(getAlphaColor(findColor(info), + _pixxConfiguration.getIRCConfiguration().getI("style:floatingaslalpha"))); + g.fillRect(x, y, tw + 4, fh + 4); + g.setColor(getColor(COLOR_WHITE)); + g.drawRect(x, y, tw + 4, fh + 4); + g.drawString(text, x + 2, y + fh); + } + } + } + + private Color getAlphaColor(Color c, int alpha) { + try { + return new Color(c.getRed(), c.getGreen(), c.getBlue(), alpha); + } catch (Throwable ex) { + return c; + } + } + + private int getIndex(int x, int y) { + int fh = _font.getSize(); + // increase y value so that it won't reach negative value. neg y is a + // problem since / rounds to 0, not to lower : -0.5 will lead to 0, not + // to -1. + y += fh + 6; + y -= 8; + y /= fh + 6; + y--; + y += _base; + if (y < 0) + y = -1; + if (y >= _nicks.size()) + y = -1; + return y; + } + + @Override + public void mouseClicked(MouseEvent e) { + } + + @Override + public void mouseEntered(MouseEvent e) { + } + + @Override + public void mouseExited(MouseEvent e) { + if (_overindex != -1) { + _overindex = -1; + repaint(); + } + } + + @Override + public void mousePressed(MouseEvent e) { + int index = getIndex(e.getX(), e.getY()); + _selected = index; + reinit(); + repaint(); + if (_selected != -1) + _listeners.sendEventAsync("eventOccured", getNick(_selected), e); + } + + @Override + public void mouseReleased(MouseEvent e) { + } + + @Override + public void mouseDragged(MouseEvent e) { + mouseMoved(e); + } + + private String getUnprefixedNick(String nick) { + if (nick.length() == 0) + return nick; + for (int i = 0; i < _prefixes.length; i++) + if (nick.charAt(0) == _prefixes[i]) + return nick.substring(1); + return nick; + } + + private String getNick(int index) { + if (index == -1) + return ""; + String nick = (String) _nicks.elementAt(index); + nick = getUnprefixedNick(nick); + int pos = nick.indexOf(":"); + if (pos != -1) { + nick = nick.substring(0, pos); + } + return nick; + } + + private String getInfo(int index) { + if (index == -1) + return ""; + String nick = (String) _nicks.elementAt(index); + nick = getUnprefixedNick(nick); + int pos = nick.indexOf(":"); + String info = ""; + if (pos != -1) { + info = nick.substring(pos + 1); + } + return info; + } + + @Override + public void mouseMoved(MouseEvent e) { + if (!_pixxConfiguration.getIRCConfiguration().getASLMaster()) + return; + int index = getIndex(e.getX(), e.getY()); + if (index == _overindex) + return; + _overindex = index; + _overX = e.getX(); + repaint(); + if (index != -1) + _listeners.sendEventAsync("ASLEventOccured", getNick(index), getInfo(index)); + } +} diff --git a/src/main/java/irc/gui/pixx/PixxNickListListener.java b/src/main/java/irc/gui/pixx/PixxNickListListener.java new file mode 100644 index 0000000..46787a5 --- /dev/null +++ b/src/main/java/irc/gui/pixx/PixxNickListListener.java @@ -0,0 +1,57 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.pixx; + +import java.awt.event.MouseEvent; + +/** + * Pixx nick list listener. + */ +public interface PixxNickListListener { + /** + * Some mouse event occured on a nick. + * + * @param nick + * the nick. + * @param e + * the mouse event. + */ + public void eventOccured(String nick, MouseEvent e); + + /** + * An ASL event occured. + * + * @param nick + * the nickname. + * @param info + * the nick name whois information string. + */ + public void ASLEventOccured(String nick, String info); +} diff --git a/src/main/java/irc/gui/pixx/PixxPanel.java b/src/main/java/irc/gui/pixx/PixxPanel.java new file mode 100644 index 0000000..6b3405e --- /dev/null +++ b/src/main/java/irc/gui/pixx/PixxPanel.java @@ -0,0 +1,191 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.pixx; + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Panel; + +/** + * Root panel for all PixxComponents. + */ +public class PixxPanel extends Panel { + /** + * Black. + */ + public static final int COLOR_BLACK = PixxColorModel.COLOR_BLACK; + /** + * White. + */ + public static final int COLOR_WHITE = PixxColorModel.COLOR_WHITE; + /** + * Dark gray. + */ + public static final int COLOR_DARK_GRAY = PixxColorModel.COLOR_DARK_GRAY; + /** + * Gray. + */ + public static final int COLOR_GRAY = PixxColorModel.COLOR_GRAY; + /** + * Light gray. + */ + public static final int COLOR_LIGHT_GRAY = PixxColorModel.COLOR_LIGHT_GRAY; + /** + * Front. + */ + public static final int COLOR_FRONT = PixxColorModel.COLOR_FRONT; + /** + * Back. + */ + public static final int COLOR_BACK = PixxColorModel.COLOR_BACK; + /** + * Selected. + */ + public static final int COLOR_SELECTED = PixxColorModel.COLOR_SELECTED; + /** + * Event. + */ + public static final int COLOR_EVENT = PixxColorModel.COLOR_EVENT; + /** + * Close. + */ + public static final int COLOR_CLOSE = PixxColorModel.COLOR_CLOSE; + /** + * Voice. + */ + public static final int COLOR_VOICE = PixxColorModel.COLOR_VOICE; + /** + * Op. + */ + public static final int COLOR_OP = PixxColorModel.COLOR_OP; + /** + * Semiop. + */ + public static final int COLOR_SEMIOP = PixxColorModel.COLOR_SEMIOP; + /** + * ASL male. + */ + public static final int COLOR_MALE = PixxColorModel.COLOR_MALE; + /** + * ASL femeale. + */ + public static final int COLOR_FEMEALE = PixxColorModel.COLOR_FEMEALE; + /** + * ASL undefined. + */ + public static final int COLOR_UNDEF = PixxColorModel.COLOR_UNDEF; + + /** + * Pixx Configuration. + */ + protected PixxConfiguration _pixxConfiguration; + + /** + * Create a new PixxPanel. + * + * @param config + * global pixx configuration. + */ + public PixxPanel(PixxConfiguration config) { + _pixxConfiguration = config; + } + + /** + * Release this object. No further method call may be performed. + */ + public void release() { + _pixxConfiguration = null; + } + + /** + * Get the formatted text from the formatted text code. + * + * @param code + * text code. + * @return formatted string. + */ + public String getText(int code) { + return _pixxConfiguration.getText(code); + } + + /** + * Draw a 3d box at given position. + * + * @param g + * where to draw. + * @param x + * x position. + * @param y + * y position. + * @param w + * width. + * @param h + * height. + */ + protected void drawSeparator(Graphics g, int x, int y, int w, int h) { + g.setColor(new Color(0x868686)); + g.drawLine(x + 0, y + 0, x + w - 1, y + 0); + g.drawLine(x + 0, y + 0, x + 0, y + 1); + g.drawLine(x + w - 1, y + 0, x + w - 1, y + 1); + g.setColor(Color.black); + g.drawLine(x + 1, y + 1, x + w - 2, y + 1); + + g.setColor(new Color(0x868686)); + g.drawLine(x + 0, y + 0, x + 0, y + h - 1); + g.setColor(Color.black); + g.drawLine(x + 1, y + 1, x + 1, y + h - 1); + + g.setColor(new Color(0xD7D3CB)); + g.drawLine(x + 0, y + h - 1, x + w - 1, y + h - 1); + + g.setColor(new Color(0xD7D3CB)); + g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1); + } + + /** + * Return the i'th color from the color model. + * + * @param col + * color index. + * @return i'th color from color model. + */ + public Color getColor(int col) { + return _pixxConfiguration.getColor(col); + } + + /** + * Get the current IRC color model. + * + * @return the irc color model. + */ + public PixxColorModel getPixxColorModel() { + return _pixxConfiguration.getColorModel(); + } +} diff --git a/src/main/java/irc/gui/pixx/PixxScrollBar.java b/src/main/java/irc/gui/pixx/PixxScrollBar.java new file mode 100644 index 0000000..e728cc1 --- /dev/null +++ b/src/main/java/irc/gui/pixx/PixxScrollBar.java @@ -0,0 +1,82 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.pixx; + +/** + * The pixx scroll bar. + */ +public interface PixxScrollBar { + /** + * Add a listener. + * + * @param lis + * listener to add. + */ + public void addPixxScrollBarListener(PixxScrollBarListener lis); + + /** + * Remove a listener. + * + * @param lis + * listener to remove. + */ + public void removePixxScrollBarListener(PixxScrollBarListener lis); + + /** + * Set minimum position. + * + * @param v + * new minimum position. + */ + public void setMinimum(int v); + + /** + * Set maximum position. + * + * @param v + * new maximum position. + */ + public void setMaximum(int v); + + /** + * Set value. + * + * @param v + * new value. + */ + public void setValue(int v); + + /** + * Get current value. + * + * @return value. + */ + public int getValue(); +} diff --git a/src/main/java/irc/gui/pixx/PixxScrollBarListener.java b/src/main/java/irc/gui/pixx/PixxScrollBarListener.java new file mode 100644 index 0000000..9afe6bb --- /dev/null +++ b/src/main/java/irc/gui/pixx/PixxScrollBarListener.java @@ -0,0 +1,43 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.pixx; + +/** + * Pixx Scrollbar listener. + */ +public interface PixxScrollBarListener { + /** + * Position has changed. + * + * @param pixScrollBar + * scrollbar whose position has changed. + */ + public void valueChanged(PixxScrollBar pixScrollBar); +} diff --git a/src/main/java/irc/gui/pixx/PixxSeparator.java b/src/main/java/irc/gui/pixx/PixxSeparator.java new file mode 100644 index 0000000..825219a --- /dev/null +++ b/src/main/java/irc/gui/pixx/PixxSeparator.java @@ -0,0 +1,122 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.pixx; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Panel; + +/** + * Separator panel. + */ +public class PixxSeparator extends Panel { + private int _type; + /** + * Upside border. + */ + public static final int BORDER_UP = 0; + /** + * Downside border. + */ + public static final int BORDER_DOWN = 1; + /** + * Left border. + */ + public static final int BORDER_LEFT = 2; + /** + * Right border. + */ + public static final int BORDER_RIGHT = 3; + + /** + * Create a new PixxSeparator. + * + * @param type + * separator type. + */ + public PixxSeparator(int type) { + super(); + _type = type; + } + + @Override + public Dimension getPreferredSize() { + + switch (_type) { + case BORDER_UP: + return new Dimension(16, 2); + case BORDER_DOWN: + return new Dimension(16, 1); + case BORDER_LEFT: + return new Dimension(2, 16); + case BORDER_RIGHT: + return new Dimension(1, 16); + default: + return new Dimension(16, 16); + + } + } + + @Override + public void paint(Graphics g) { + update(g); + } + + @Override + public void update(Graphics g) { + int w = getSize().width; + int h = getSize().height; + switch (_type) { + case BORDER_UP: + g.setColor(new Color(0x868686)); + g.drawLine(0, 0, w - 1, 0); + g.drawLine(0, 0, 0, 1); + g.drawLine(w - 1, 0, w - 1, 1); + g.setColor(Color.black); + g.drawLine(1, 1, w - 2, 1); + break; + case BORDER_LEFT: + g.setColor(new Color(0x868686)); + g.drawLine(0, 0, 0, h - 1); + g.setColor(Color.black); + g.drawLine(1, 0, 1, h - 1); + break; + case BORDER_DOWN: + g.setColor(new Color(0xD7D3CB)); + g.drawLine(0, h - 1, w - 1, h - 1); + break; + case BORDER_RIGHT: + g.setColor(new Color(0xD7D3CB)); + g.drawLine(w - 1, 0, w - 1, h - 1); + break; + } + } +} diff --git a/src/main/java/irc/gui/pixx/PixxTaskBar.java b/src/main/java/irc/gui/pixx/PixxTaskBar.java new file mode 100644 index 0000000..3ebe833 --- /dev/null +++ b/src/main/java/irc/gui/pixx/PixxTaskBar.java @@ -0,0 +1,809 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2005 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.pixx; + +import irc.EventDispatcher; +import irc.ListenerGroup; + +import java.awt.Color; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.event.InputEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.util.Enumeration; +import java.util.Vector; + +/** + * TaskBarItem. + */ +class TaskBarItem { + /** + * Create a new TaskBarItem + * + * @param src + * source. + * @param arow + * row. + * @param abring + * if should be brang. + */ + public TaskBarItem(BaseAWTSource src, int arow, boolean abring) { + source = src; + eventWaiting = false; + row = arow; + bring = abring; + visible = true; + } + + /** + * Source. + */ + public BaseAWTSource source; + /** + * Row. + */ + public int row; + /** + * True if some event is waiting. + */ + public boolean eventWaiting; + /** + * True if source must be brang. + */ + public boolean bring; + /** + * Source z-order. + */ + public int zorder; + /** + * True if source is visible in the taskbar. + */ + public boolean visible; +} + +/** + * The task bar. + */ +public class PixxTaskBar extends PixxPanel implements MouseListener, MouseMotionListener, BaseAWTSourceListener { + private final ListenerGroup _listeners; + + private TaskBarItem _active; + private TaskBarItem _pressed; + private final Vector _items; + + private final int[] _itemCount; + private final int[] _visibleItemCount; + private final Font _font; + private Image _buffer; + private int _iwidth; + private int _ileft; + private int _zorder; + private boolean _handCursor; + private int _overX; + private int _overY; + private final int _maxWidth; + + /** + * Create a new PixxTaskBar. + * + * @param config + * global irc configuration. + */ + public PixxTaskBar(PixxConfiguration config) { + super(config); + _font = new Font("", 0, 12); + _listeners = new ListenerGroup(); + _active = null; + _pressed = null; + _items = new Vector(); + _itemCount = new int[2]; + _visibleItemCount = new int[2]; + _itemCount[0] = 0; + _itemCount[1] = 0; + _visibleItemCount[0] = 0; + _visibleItemCount[1] = 0; + _ileft = 60; + _zorder = 0; + _handCursor = false; + _overX = -1; + _overY = -1; + computeWidth(); + + addMouseListener(this); + addMouseMotionListener(this); + _maxWidth = config.getI("taskbaritemwidth"); + } + + @Override + public void release() { + _buffer = null; + removeMouseMotionListener(this); + removeMouseListener(this); + super.release(); + } + + /** + * Add a listener. + * + * @param lis + * listener to add. + */ + public void addPixxTaskBarListener(PixxTaskBarListener lis) { + _listeners.addListener(lis); + } + + /** + * Remove a listener. + * + * @param lis + * listener to remove. + */ + public void removePixxTaskBarListener(PixxTaskBarListener lis) { + _listeners.removeListener(lis); + } + + private TaskBarItem findItem(BaseAWTSource source) { + if (source == null) + return null; + for (int i = 0; i < _items.size(); i++) + if (((TaskBarItem) _items.elementAt(i)).source == source) + return (TaskBarItem) _items.elementAt(i); + return null; + } + + private void removeFromVector(Vector v, Object o) { + for (int i = 0; i < v.size(); i++) + if (v.elementAt(i) == o) + v.removeElementAt(i); + } + + private synchronized void enter(BaseAWTSource source, int row, boolean bring) { + TaskBarItem item = new TaskBarItem(source, row, bring); + source.addBaseAWTSourceListener(this); + _items.insertElementAt(item, _items.size()); + _itemCount[row]++; + _visibleItemCount[row]++; + _listeners.sendEvent("AWTSourceAdded", this, source); + if (bring) + activate(source); + _buffer = null; + repaint(); + } + + private synchronized void leave(BaseAWTSource source, int row) { + TaskBarItem item = findItem(source); + source.removeBaseAWTSourceListener(this); + _itemCount[row]--; + _visibleItemCount[row]--; + boolean change = getActive() == source; + removeFromVector(_items, item); + if (change) + activate(null); + _listeners.sendEvent("AWTSourceRemoved", this, source); + _buffer = null; + repaint(); + } + + /** + * Get icons count in this task bar. + * + * @return icons count. + */ + public int getCount() { + return _itemCount[0] + _itemCount[1]; + } + + /** + * Add a new channel in the taskbar. + * + * @param chan + * channel to add. + * @param bring + * true if this new channel must be made the active awt source. + */ + public void addChannel(AWTChannel chan, boolean bring) { + enter(chan, 0, bring); + } + + /** + * Remove the given channel from the taskbar. + * + * @param chan + * channel to remove. + */ + public void removeChannel(AWTChannel chan) { + leave(chan, 0); + } + + /** + * Add a new status in the taskbar. + * + * @param status + * status to add. + * @param bring + * true if this new status must be made the active awt source. + */ + public void addStatus(AWTStatus status, boolean bring) { + enter(status, 1, bring); + } + + /** + * Remove the given status from the taskbar. + * + * @param status + * status to remove. + */ + public void removeStatus(AWTStatus status) { + leave(status, 1); + } + + /** + * Add a new default source in the taskbar. + * + * @param source + * default source to add. + * @param bring + * true if this new default source must be made the active awt + * source. + */ + public void addDefaultSource(AWTDefaultSource source, boolean bring) { + enter(source, 1, bring); + } + + /** + * Remove the given default source from the taskbar. + * + * @param source + * default sourceto remove. + */ + public void removeDefaultSource(AWTDefaultSource source) { + leave(source, 1); + } + + /** + * Add a new query in the taskbar. + * + * @param query + * query to add. + * @param bring + * true if this new query must be made the active awt source. + */ + public void addQuery(AWTQuery query, boolean bring) { + enter(query, 1, bring); + } + + /** + * Remove the given query from the taskbar. + * + * @param query + * query to remove. + */ + public void removeQuery(AWTQuery query) { + leave(query, 1); + } + + /** + * Add a new chanlist in the taskbar. + * + * @param chanlist + * chanlist to add. + * @param bring + * true if this new chanlist must be made the active awt source. + */ + public void addChanList(AWTChanList chanlist, boolean bring) { + enter(chanlist, 1, bring); + } + + /** + * Remove the given chanlist from the taskbar. + * + * @param chanlist + * chanlist to remove. + */ + public void removeChanList(AWTChanList chanlist) { + leave(chanlist, 1); + } + + /** + * Add a new dcc chat in the taskbar. + * + * @param chat + * dcc chat to add. + * @param bring + * true if this new dcc chat must be made the active awt source. + */ + public void addDCCChat(AWTDCCChat chat, boolean bring) { + enter(chat, 1, bring); + } + + /** + * Remove the given dcc chat from the taskbar. + * + * @param chat + * dcc chat to remove. + */ + public void removeDCCChat(AWTDCCChat chat) { + leave(chat, 1); + } + + private BaseAWTSource findFirst() { + TaskBarItem first = null; + int maxz = -1; + for (int i = 0; i < _items.size(); i++) { + TaskBarItem item = (TaskBarItem) _items.elementAt(i); + if (item.zorder > maxz) { + maxz = item.zorder; + first = item; + } + } + if (first == null) + return null; + return first.source; + } + + /** + * Get all sources sorted by their z-order. + * + * @return z-ordered sources. + */ + public BaseAWTSource[] getZOrderedSources() { + TaskBarItem[] items = new TaskBarItem[_items.size()]; + for (int i = 0; i < items.length; i++) + items[i] = (TaskBarItem) _items.elementAt(i); + + for (int i = 0; i < items.length - 1; i++) { + TaskBarItem item = items[i]; + int max = item.zorder; + int maxIndex = i; + for (int j = i + 1; j < items.length; j++) { + item = items[j]; + if (item.zorder > max) { + max = item.zorder; + maxIndex = j; + } + } + TaskBarItem tmp = items[i]; + items[i] = items[maxIndex]; + items[maxIndex] = tmp; + } + + BaseAWTSource[] ans = new BaseAWTSource[items.length]; + for (int i = 0; i < ans.length; i++) + ans[i] = items[i].source; + return ans; + } + + /** + * Make the given source visible in the taskbar. + * + * @param source + * the source that should be visible. + */ + public void show(BaseAWTSource source) { + if (source == null) + return; + TaskBarItem item = findItem(source); + if (item.visible) + return; + + item.visible = true; + _visibleItemCount[item.row]++; + + _buffer = null; + repaint(); + } + + /** + * Make the given source invisible in the taskbar. + * + * @param source + * the source that should be invisible. + */ + public void hide(BaseAWTSource source) { + if (source == null) + return; + TaskBarItem item = findItem(source); + if (!item.visible) + return; + + item.visible = false; + _visibleItemCount[item.row]--; + + _buffer = null; + repaint(); + } + + /** + * Activate the given source. + * + * @param source + * the source to activate. + */ + public void activate(BaseAWTSource source) { + if (source == null) + source = findFirst(); + if (source == null) + return; + TaskBarItem item = findItem(source); + if (item == _active) + return; + if (!item.visible) + return; + if (_active != null) + _listeners.sendEvent("AWTSourceDesactivated", this, _active.source); + + _active = item; + if (_active != null) { + _active.zorder = _zorder++; + _active.eventWaiting = false; + _listeners.sendEvent("AWTSourceActivated", this, _active.source); + } else { + _listeners.sendEvent("AWTSourceActivated", this, null); + } + source.requestFocus(); + _buffer = null; + repaint(); + } + + /** + * Get the current active source. + * + * @return active source, or null if there is no active source. + */ + public BaseAWTSource getActive() { + if (_active == null) + return null; + return _active.source; + } + + @Override + public void paint(Graphics g) { + update(g); + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(16, 2 * getItemHeight() + 16); + } + + private int getItemWidth() { + return _iwidth; + // return 100; + } + + private int getItemHeight() { + return _font.getSize() + 4; + } + + private synchronized void computeWidth() { + int w = getSize().width - 63; + int n = Math.max(_visibleItemCount[0], _visibleItemCount[1]); + + w -= 9 * n; + if (n != 0) + _iwidth = Math.min(_maxWidth, w / n); + else + _iwidth = _maxWidth; + } + + private int getX(int col) { + return col * (getItemWidth() + 9) + _ileft; + } + + private int getCol(int x) { + return (x - _ileft) / (9 + getItemWidth()); + } + + private int getY(int row) { + return 4 + (getItemHeight() + 8) * row; + } + + private int getRow(int y) { + return (y - 4) / (8 + getItemHeight()); + } + + private void drawItem(Graphics g, int col, int row, Color c, String s) { + int x = getX(col); + int y = getY(row); + int w = getItemWidth(); + int h = getItemHeight(); + g.setClip(x + 1, y + 1, w - 1, h - 1); + g.setColor(c); + g.fillRect(x, y, w, h); + g.setColor(getColor(COLOR_BLACK)); + g.drawRect(x, y, w, h); + g.setColor(getColor(COLOR_WHITE)); + g.drawRect(x + 1, y + 1, w - 2, h - 2); + y += h; + int strw = g.getFontMetrics().stringWidth(s); + y -= (h - _font.getSize()) / 2; + g.drawString(s, x + (w - strw) / 2, y - 1); + g.setClip(0, 0, getSize().width, getSize().height); + } + + private void drawItem(Graphics g, TaskBarItem item, int col) { + int row = item.row; + Color c = getColor(COLOR_FRONT); + if ((item == _active) || (item == _pressed)) + c = getColor(COLOR_SELECTED); + if ((item != _active) && (item.eventWaiting)) + c = getColor(COLOR_EVENT); + drawItem(g, col++, row, c, item.source.getShortTitle()); + } + + @Override + public void update(Graphics ug) { + // int col=0; + int w = getSize().width; + int h = getSize().height; + + if (_buffer != null) { + if ((_buffer.getWidth(this) != w) || (_buffer.getHeight(this) != h)) + _buffer = null; + } + + if (_buffer == null) { + Graphics g; + try { + _buffer = createImage(w, h); + g = _buffer.getGraphics(); + } catch (Throwable e) { + return; + } + + g.setFont(new Font("", Font.PLAIN, 12)); + int sw = Math.max(g.getFontMetrics().stringWidth(getText(PixxTextProvider.GUI_PRIVATE)), g.getFontMetrics() + .stringWidth(getText(PixxTextProvider.GUI_PUBLIC))); + _ileft = 25 + sw; + computeWidth(); + + // g.setColor(new Color(0x084079)); + g.setColor(getColor(COLOR_BACK)); + g.fillRect(0, 0, w, h); + int col0 = 0; + int col1 = 0; + Enumeration el = _items.elements(); + while (el.hasMoreElements()) { + TaskBarItem item = (TaskBarItem) el.nextElement(); + if (item.visible) { + if (item.row == 0) + drawItem(g, item, col0++); + else + drawItem(g, item, col1++); + } + + } + + // g.setColor(new Color(0x336699)); + g.setColor(getColor(COLOR_FRONT)); + g.fillRect(4, 5, sw + 2, h - 9); + + for (int y = 3; y < h / 4; y++) { + g.drawLine(sw + 3 + y, y + 3, sw + 3 + y, h / 2 + 2 - y); + g.drawLine(sw + 3 + y, h - 3 - y, sw + 3 + y, h / 2 - 1 + y); + } + + // g.setColor(Color.black); + g.setColor(getColor(COLOR_BLACK)); + g.drawLine(4, h / 2 - 1, w - 1, h / 2 - 1); + g.drawLine(4, h / 2 + 1, w - 1, h / 2 + 1); + // g.setColor(Color.white); + g.setColor(getColor(COLOR_WHITE)); + g.drawLine(4, h / 2, w - 1, h / 2); + + int y = getY(0) + getItemHeight(); + y -= (getItemHeight() - _font.getSize()) / 2; + + g.drawString(getText(PixxTextProvider.GUI_PUBLIC), 8, y + 1); + + y = getY(1) + getItemHeight(); + y -= (getItemHeight() - _font.getSize()) / 2; + + g.drawString(getText(PixxTextProvider.GUI_PRIVATE), 8, y - 4); + + // g.setColor(Color.black); + g.setColor(getColor(COLOR_BLACK)); + g.drawLine(4, 5, 4, h - 5); + + g.drawLine(4, 5, sw + 6, 5); + g.drawLine(4, h - 5, sw + 6, h - 5); + + g.drawLine(sw + 6, 5, sw + 3 + h / 4, h / 4 + 2); + g.drawLine(sw + 3 + h / 4, h / 4 + 2, sw + 6, h / 2 - 1); + + g.drawLine(sw + 6, h - 5, sw + 3 + h / 4, h - 1 - h / 4 - 1); + g.drawLine(sw + 3 + h / 4, h - h / 4 - 2, sw + 6, h - 3 - h / 2 + 4); + + // g.setColor(Color.white); + g.setColor(getColor(COLOR_WHITE)); + g.drawLine(5, 6, 5, h - 6); + + g.drawLine(5, 6, sw + 5, 6); + g.drawLine(5, h - 6, sw + 5, h - 6); + + g.drawLine(sw + 6, 6, sw + 2 + h / 4, h / 4 + 2); + g.drawLine(sw + 2 + h / 4, h / 4 + 2, sw + 5, h / 2 - 1); + + g.drawLine(sw + 6, h - 6, sw + 2 + h / 4, h - 1 - h / 4 - 1); + g.drawLine(sw + 2 + h / 4, h - 2 - h / 4, sw + 5, h - 1 - h / 2 + 2); + + } + + if (_buffer != null) + ug.drawImage(_buffer, 0, 0, this); + TaskBarItem item = getItemAt(_overX, _overY); + if (item != null) { + String text = item.source.getShortTitle(); + int tw = ug.getFontMetrics().stringWidth(text); + int x = getX(getCol(_overX)) + (getItemWidth() - tw) / 2 - 2; + int y = getY(getRow(_overY)) - (getItemHeight() - _font.getSize()) / 2 - 1; + + int fh = getItemHeight(); + if (text.length() > 0) { + if (tw >= getItemWidth()) { + + if (x + tw + 5 >= w) + x = w - tw - 5; + if (x < 0) + x = 0; + ug.setColor(getAlphaColor(getColor(COLOR_FRONT), 200)); + ug.fillRect(x, y, tw + 4, fh + 4); + ug.setColor(getColor(COLOR_WHITE)); + ug.drawRect(x, y, tw + 4, fh + 4); + ug.drawString(text, x + 2, y + fh); + } + } + } + } + + private Color getAlphaColor(Color c, int alpha) { + try { + return new Color(c.getRed(), c.getGreen(), c.getBlue(), alpha); + } catch (Throwable ex) { + return c; + } + } + + private TaskBarItem getItemAt(int x, int y) { + int row = getRow(y); + int col = getCol(x); + + x -= getX(col); + y -= getY(row); + if ((x >= getItemWidth()) || (y >= getItemHeight())) + return null; + if ((x < 0) || (y < 0)) + return null; + + int currentcol = 0; + Enumeration el = _items.elements(); + while (el.hasMoreElements()) { + TaskBarItem item = (TaskBarItem) el.nextElement(); + if (item.visible) { + if (item.row == row) { + if (currentcol == col) + return item; + currentcol++; + } + } + } + return null; + } + + @Override + public void mouseMoved(MouseEvent e) { + TaskBarItem item = getItemAt(e.getX(), e.getY()); + if (item != null) { + if (!_handCursor) { + setCursor(new Cursor(Cursor.HAND_CURSOR)); + _handCursor = true; + } + } else { + if (_handCursor) { + setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + _handCursor = false; + } + } + TaskBarItem oldItem = getItemAt(_overX, _overY); + if (oldItem != item) { + _overX = e.getX(); + _overY = e.getY(); + repaint(); + } + } + + @Override + public void mouseDragged(MouseEvent e) { + mouseMoved(e); + } + + @Override + public void mouseClicked(MouseEvent e) { + } + + @Override + public void mouseEntered(MouseEvent e) { + } + + @Override + public void mouseExited(MouseEvent e) { + mouseMoved(e); + } + + @Override + public void mousePressed(MouseEvent e) { + TaskBarItem np = getItemAt(e.getX(), e.getY()); + _pressed = np; + _buffer = null; + repaint(); + if (_pressed != null) + _listeners.sendEventAsync("eventOccured", this, _pressed.source, e); + } + + @Override + public void mouseReleased(MouseEvent e) { + _pressed = null; + TaskBarItem src = getItemAt(e.getX(), e.getY()); + try { + if ((e.getModifiers() & InputEvent.BUTTON1_MASK) != 0) + if (src != null) + EventDispatcher.dispatchEventAsyncAndWaitEx(this, "activate", new Object[] { src.source }); + } catch (InterruptedException ex) { + } catch (Throwable ex) { + } + + _buffer = null; + repaint(); + } + + @Override + public void titleChanged(BaseAWTSource source) { + _buffer = null; + repaint(); + } + + @Override + public void eventOccured(BaseAWTSource source) { + TaskBarItem item = findItem(source); + if (item == null) + return; + if (item == _active) + return; + item.eventWaiting = true; + _buffer = null; + repaint(); + } + +} diff --git a/src/main/java/irc/gui/pixx/PixxTaskBarListener.java b/src/main/java/irc/gui/pixx/PixxTaskBarListener.java new file mode 100644 index 0000000..5d858ea --- /dev/null +++ b/src/main/java/irc/gui/pixx/PixxTaskBarListener.java @@ -0,0 +1,89 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.pixx; + +import java.awt.event.MouseEvent; + +/** + * Task bar listener. + */ +public interface PixxTaskBarListener { + /** + * The active awt source has been desactivated. + * + * @param bar + * the taskbar. + * @param source + * the desactivated source. + */ + public void AWTSourceDesactivated(PixxTaskBar bar, BaseAWTSource source); + + /** + * A new awt source has been activated. + * + * @param bar + * the taskbar. + * @param source + * the activated source. + */ + public void AWTSourceActivated(PixxTaskBar bar, BaseAWTSource source); + + /** + * A new awt source has been added in the taskbar. + * + * @param bar + * the taskbar. + * @param source + * the added source. + */ + public void AWTSourceAdded(PixxTaskBar bar, BaseAWTSource source); + + /** + * An awt source has been removed from the taskbar. + * + * @param bar + * the taskbar. + * @param source + * the removed source. + */ + public void AWTSourceRemoved(PixxTaskBar bar, BaseAWTSource source); + + /** + * An mouse event occured on an awt source icon. + * + * @param bar + * the taskbar. + * @param source + * the awt source. + * @param e + * the mouse event. + */ + public void eventOccured(PixxTaskBar bar, BaseAWTSource source, MouseEvent e); +} diff --git a/src/main/java/irc/gui/pixx/PixxTextProvider.java b/src/main/java/irc/gui/pixx/PixxTextProvider.java new file mode 100644 index 0000000..a92b139 --- /dev/null +++ b/src/main/java/irc/gui/pixx/PixxTextProvider.java @@ -0,0 +1,239 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.pixx; + +import irc.TextProvider; + +/** + * PixxTextProvider. + */ +public interface PixxTextProvider { + /** + * You've been kicked out of %1 by %2 + */ + public static final int SOURCE_YOU_KICKED = TextProvider.USER_BASE + 0x601; + /** + * Status + */ + public static final int SOURCE_STATUS = TextProvider.USER_BASE + 0x602; + /** + * Channels for %1 + */ + public static final int SOURCE_CHANLIST = TextProvider.USER_BASE + 0x603; + /** + * Retrieving channels... + */ + public static final int SOURCE_CHANLIST_RETREIVING = TextProvider.USER_BASE + 0x604; + /** + * %1 has joined %2 + */ + public static final int SOURCE_HAS_JOINED = TextProvider.USER_BASE + 0x605; + /** + * %1 has left %2 + */ + public static final int SOURCE_HAS_LEFT = TextProvider.USER_BASE + 0x606; + /** + * %1 has been kicked by %2 + */ + public static final int SOURCE_HAS_BEEN_KICKED_BY = TextProvider.USER_BASE + 0x607; + /** + * %1 has quit + */ + public static final int SOURCE_HAS_QUIT = TextProvider.USER_BASE + 0x608; + /** + * Topic is %1 + */ + public static final int SOURCE_TOPIC_IS = TextProvider.USER_BASE + 0x609; + /** + * %1 changed topic to %2 + */ + public static final int SOURCE_CHANGED_TOPIC = TextProvider.USER_BASE + 0x60A; + /** + * %1 sets channel mode to %2 + */ + public static final int SOURCE_CHANNEL_MODE = TextProvider.USER_BASE + 0x60B; + /** + * Channel mode is %1 + */ + public static final int SOURCE_CHANNEL_MODE_IS = TextProvider.USER_BASE + 0x60C; + /** + * %1 sets mode %2 on %3 + */ + public static final int SOURCE_USER_MODE = TextProvider.USER_BASE + 0x60D; + /** + * %1 is now known as %2 + */ + public static final int SOURCE_KNOWN_AS = TextProvider.USER_BASE + 0x60E; + /** + * Mode changed to %1 + */ + public static final int SOURCE_YOUR_MODE = TextProvider.USER_BASE + 0x60F; + /** + * Your nick is now %1 + */ + public static final int SOURCE_YOUR_NICK = TextProvider.USER_BASE + 0x610; + /** + * Infos + */ + public static final int SOURCE_INFO = TextProvider.USER_BASE + 0x611; + /** + * %1 is away + */ + public static final int SOURCE_AWAY = TextProvider.USER_BASE + 0x612; + /** + * %1 invites you to join %2 + */ + public static final int SOURCE_YOU_INVITED = TextProvider.USER_BASE + 0x613; + /** + * You're talking in %1 as %2 + */ + public static final int SOURCE_YOU_JOINED_AS = TextProvider.USER_BASE + 0x614; + + /** + * Whois + */ + public static final int GUI_WHOIS = TextProvider.USER_BASE + 0x701; + /** + * Query + */ + public static final int GUI_QUERY = TextProvider.USER_BASE + 0x702; + /** + * Kick + */ + public static final int GUI_KICK = TextProvider.USER_BASE + 0x703; + /** + * Ban + */ + public static final int GUI_BAN = TextProvider.USER_BASE + 0x704; + /** + * Kick + Ban + */ + public static final int GUI_KICKBAN = TextProvider.USER_BASE + 0x705; + /** + * Op + */ + public static final int GUI_OP = TextProvider.USER_BASE + 0x706; + /** + * DeOp + */ + public static final int GUI_DEOP = TextProvider.USER_BASE + 0x707; + /** + * Voice + */ + public static final int GUI_VOICE = TextProvider.USER_BASE + 0x708; + /** + * DeVoice + */ + public static final int GUI_DEVOICE = TextProvider.USER_BASE + 0x709; + /** + * Ping + */ + public static final int GUI_PING = TextProvider.USER_BASE + 0x70A; + /** + * Version + */ + public static final int GUI_VERSION = TextProvider.USER_BASE + 0x70B; + /** + * Time + */ + public static final int GUI_TIME = TextProvider.USER_BASE + 0x70C; + /** + * Finger + */ + public static final int GUI_FINGER = TextProvider.USER_BASE + 0x70D; + /** + * Receiving file (%1 bytes) + */ + public static final int GUI_RETREIVING_FILE = TextProvider.USER_BASE + 0x70E; + /** + * Sending file (%1 bytes) + */ + public static final int GUI_SENDING_FILE = TextProvider.USER_BASE + 0x70F; + /** + * %1 terminated + */ + public static final int GUI_TERMINATED = TextProvider.USER_BASE + 0x710; + /** + * %1 failed + */ + public static final int GUI_FAILED = TextProvider.USER_BASE + 0x711; + /** + * Close + */ + public static final int GUI_CLOSE = TextProvider.USER_BASE + 0x712; + /** + * Disconnect + */ + public static final int GUI_DISCONNECT = TextProvider.USER_BASE + 0x713; + /** + * Channels + */ + public static final int GUI_CHANNELS = TextProvider.USER_BASE + 0x714; + /** + * Help + */ + public static final int GUI_HELP = TextProvider.USER_BASE + 0x715; + /** + * private + */ + public static final int GUI_PRIVATE = TextProvider.USER_BASE + 0x716; + /** + * public + */ + public static final int GUI_PUBLIC = TextProvider.USER_BASE + 0x717; + /** + * Connect + */ + public static final int GUI_CONNECT = TextProvider.USER_BASE + 0x718; + /** + * About + */ + public static final int GUI_ABOUT = TextProvider.USER_BASE + 0x719; + /** + * Change nick to + */ + public static final int GUI_CHANGE_NICK = TextProvider.USER_BASE + 0x71A; + /** + * Font + */ + public static final int GUI_FONT = TextProvider.USER_BASE + 0x71C; + /** + * Select font + */ + public static final int GUI_FONT_WINDOW = TextProvider.USER_BASE + 0x71D; + /** + * Ok + */ + public static final int GUI_FONT_WINDOW_OK = TextProvider.USER_BASE + 0x71E; + /** + * Enter text here... + */ + public static final int GUI_ENTER_TEXT_HERE = TextProvider.USER_BASE + 0x71F; +} diff --git a/src/main/java/irc/gui/pixx/PixxVerticalScrollBar.java b/src/main/java/irc/gui/pixx/PixxVerticalScrollBar.java new file mode 100644 index 0000000..64113d0 --- /dev/null +++ b/src/main/java/irc/gui/pixx/PixxVerticalScrollBar.java @@ -0,0 +1,503 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.pixx; + +import irc.ListenerGroup; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; + +/** + * The vertical pixx scroll bar. + */ +public class PixxVerticalScrollBar extends PixxPanel implements PixxScrollBar, MouseListener, MouseMotionListener, + Runnable { + private double _min; + private double _max; + private double _val; + private boolean _mouseDown; + private boolean _mouseDownUp; + private boolean _mouseDownDown; + private int _base; + + private final int _arrow = 10; + private double _view; + + private MouseEvent _repeatEvent; + private int _repeatEventCount; + private Thread _repeatThread; + + private ListenerGroup _listeners; + + /** + * Create a new PixxVerticalScrollBar. + * + * @param config + * global irc configuration. + * @param min + * minimum value. + * @param max + * maximum value. + * @param view + * width of the display. + */ + public PixxVerticalScrollBar(PixxConfiguration config, int min, int max, double view) { + super(config); + _mouseDown = false; + _view = view; + _listeners = new ListenerGroup(); + setMinimum(min); + setMaximum(max); + setValue(min); + addMouseListener(this); + addMouseMotionListener(this); + } + + @Override + public void run() { + boolean terminated = false; + _repeatEventCount = 0; + while (!terminated) { + try { + if (_repeatEventCount++ == 0) + Thread.sleep(500); + else + Thread.sleep(50); + mousePressed(_repeatEvent); + } catch (InterruptedException ex) { + terminated = true; + } + } + } + + @Override + public void release() { + removeMouseListener(this); + removeMouseMotionListener(this); + super.release(); + } + + /** + * Add a listener. + * + * @param lis + * listener to add. + */ + @Override + public void addPixxScrollBarListener(PixxScrollBarListener lis) { + _listeners.addListener(lis); + } + + /** + * Remove a listener. + * + * @param lis + * listener to remove. + */ + @Override + public void removePixxScrollBarListener(PixxScrollBarListener lis) { + _listeners.removeListener(lis); + } + + private Color[] getColors(boolean invert) { + Color[] c = new Color[5]; + if (!invert) { + c[0] = getColor(COLOR_FRONT); + c[1] = getColor(COLOR_BLACK); + c[2] = getColor(COLOR_GRAY); + c[3] = getColor(COLOR_LIGHT_GRAY); + c[4] = getColor(COLOR_WHITE); + } else { + c[0] = getColor(COLOR_SELECTED); + c[1] = getColor(COLOR_BLACK); + c[2] = getColor(COLOR_GRAY); + c[3] = getColor(COLOR_LIGHT_GRAY); + c[4] = getColor(COLOR_WHITE); + } + + return c; + } + + private void drawA(Graphics g, int pos, boolean invert) { + int w = getSize().width; + // int h=getSize().height; + int y = pos; + + Color c[] = getColors(invert); + + g.setColor(c[0]); + for (int i = 0; i < w - 5; i++) + g.drawLine(i + 3, y - 1, i + 3, y - 1 - i); + + g.setColor(c[1]); + g.drawLine(0, y - 1, w - 2, y - w + 1); + g.setColor(c[2]); + g.drawLine(1, y - 1, w - 2, y - w + 2); + g.setColor(c[4]); + g.drawLine(2, y - 1, w - 2, y - w + 3); + + g.setColor(c[1]); + g.drawLine(w - 1, y - 1, w - 1, y - w); + g.setColor(c[4]); + g.drawLine(w - 2, y - 1, w - 2, y + 3 - w); + + } + + private void drawB(Graphics g, int pos, boolean invert) { + int w = getSize().width; + // int h=getSize().height; + int y = pos; + + Color c[] = getColors(invert); + + g.setColor(c[0]); + for (int i = 0; i < w - 5; i++) + g.drawLine(w - 1 - i - 3, y, w - 1 - i - 3, y + i); + + g.setColor(c[1]); + g.drawLine(0, y + w - 1, w - 1, y); + g.setColor(c[2]); + g.drawLine(1, y + w - 3, w - 2, y); + g.setColor(c[4]); + g.drawLine(1, y + w - 4, w - 3, y); + + g.setColor(c[3]); + g.drawLine(0, y, 0, y + w - 2); + g.setColor(c[4]); + g.drawLine(1, y, 1, y + w - 4); + + } + + private void drawInside(Graphics g, int pos, int lng, boolean invert) { + int w = getSize().width; + // int h=getSize().height; + Color c[] = getColors(invert); + int y = pos; + + g.setColor(c[3]); + g.drawLine(0, y, 0, y + lng - 1); + g.setColor(c[4]); + g.drawLine(1, y, 1, y + lng - 1); + g.drawLine(w - 2, y, w - 2, y + lng - 1); + g.setColor(c[1]); + g.drawLine(w - 1, y, w - 1, y + lng - 1); + g.setColor(c[0]); + g.fillRect(2, y, w - 4, lng); + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(16, 100); + } + + @Override + public void paint(Graphics g) { + update(g); + } + + private int getMargin() { + return _arrow + getSize().width; + } + + private int getCursorLong() { + int h = getSize().height; + int margin = getMargin(); + if (_min == _max) + return h - 2 * margin; + double iSee = (h - 2 * margin) * _view; + + int cursorLong = (int) ((iSee / (_max - _min + 1)) * (h - 2 * margin)); + if (cursorLong > (h - 2 * margin) / 3) + cursorLong = (h - 2 * margin) / 3; + return cursorLong; + } + + private int getPos() { + int h = getSize().height; + int lng = h; + + int margin = getMargin(); + int cursorLong = getCursorLong(); + return (int) ((_val * (lng - margin - cursorLong) + (_max - _val) * margin) / (_max) - margin); + } + + @Override + public void update(Graphics g) { + int w = getSize().width; + int h = getSize().height; + int margin = getMargin(); + int cursorLong = getCursorLong(); + + Image buffer; + Graphics gra; + try { + buffer = createImage(w, h); + gra = buffer.getGraphics(); + } catch (Throwable e) { + return; + } + + gra.setColor(getColor(COLOR_BACK)); + gra.fillRect(0, 0, w, h); + + // fleche du haut + drawInside(gra, 2, _arrow - 2, _mouseDownUp); + drawB(gra, margin - w, _mouseDownUp); + + Color c[] = getColors(_mouseDownUp); + gra.setColor(c[3]); + gra.drawLine(1, 0, w - 2, 0); + gra.drawLine(0, 0, 0, 1); + gra.setColor(c[4]); + gra.drawLine(1, 1, w - 2, 1); + gra.setColor(c[1]); + gra.drawLine(w - 1, 0, w - 1, 1); + + gra.setColor(c[4]); + gra.drawLine(w / 2, 4, w / 4 + 1, 4 + w / 4 - 1); + gra.drawLine(w / 2, 4, 3 * w / 4 - 1, 4 + w / 4 - 1); + + // fleche du bas + drawInside(gra, h - _arrow, _arrow - 2, _mouseDownDown); + drawA(gra, h - margin + w, _mouseDownDown); + + c = getColors(_mouseDownDown); + gra.setColor(c[3]); + gra.drawLine(0, h - 2, 0, h - 1); + gra.setColor(c[1]); + gra.drawLine(w - 1, h - 2, w - 1, h - 1); + gra.drawLine(1, h - 1, w - 2, h - 1); + gra.setColor(c[4]); + gra.drawLine(1, h - 2, w - 2, h - 2); + + gra.setColor(c[4]); + gra.drawLine(w / 2, h - 5, w / 4 + 1, h - 5 - w / 4 + 1); + gra.drawLine(w / 2, h - 5, 3 * w / 4 - 1, h - 5 - w / 4 + 1); + + // curseur + int pos = getPos() + margin; + drawInside(gra, pos, cursorLong, _mouseDown); + drawA(gra, pos, _mouseDown); + drawB(gra, pos + cursorLong, _mouseDown); + + g.drawImage(buffer, 0, 0, this); + } + + /** + * Set minimum position. + * + * @param v + * new minimum position. + */ + @Override + public void setMinimum(int v) { + _min = v; + if (_min > _max) + _min = _max; + if (_val < _min) + updateValue(_min); + repaint(); + } + + /** + * Set maximum position. + * + * @param v + * new maximum position. + */ + @Override + public void setMaximum(int v) { + _max = v; + if (_max < _min) + _max = _min; + if (_val > _max) + updateValue(_max); + repaint(); + } + + /** + * Set value. + * + * @param v + * new value. + */ + @Override + public void setValue(int v) { + _val = v; + if (_val < _min) + _val = _min; + if (_val > _max) + _val = _max; + repaint(); + } + + /** + * Get current value. + * + * @return value. + */ + @Override + public int getValue() { + return (int) (_val + 0.5); + } + + private boolean inCursor(int x, int y) { + int w = getSize().width; + // int h=getSize().height; + int l = getCursorLong(); + y -= getMargin(); + y -= getPos(); + + return (x + y >= -1) && (y + x - l - w <= -1); + } + + private boolean inSubArrow(int x, int y) { + y -= getMargin(); + return (x + y <= -1); + } + + private boolean inAddArrow(int x, int y) { + int w = getSize().width; + int h = getSize().height; + return (y + x - h + getMargin() - w >= -1); + } + + private double getValue(int x, int y) { + // int w=getSize().width; + int h = getSize().height; + // int lrg=w; + int lng = h; + int margin = getMargin(); + + lng -= margin * 2 + getCursorLong(); + + int py = y - margin - _base; + + return (_max - _min) * py / lng + _min; + } + + private void updateValue(double v) { + int oldVal = getValue(); + _val = v; + if (_val < _min) + _val = _min; + if (_val > _max) + _val = _max; + repaint(); + if (getValue() != oldVal) { + _listeners.sendEventAsync("valueChanged", this); + } + } + + @Override + public void mouseClicked(MouseEvent e) { + } + + @Override + public void mouseEntered(MouseEvent e) { + } + + @Override + public void mouseExited(MouseEvent e) { + } + + private void beginRepeat(MouseEvent e) { + _repeatEvent = e; + _repeatThread = new Thread(this, "Scrolling thread"); + _repeatThread.start(); + } + + private void endRepeat() { + if (_repeatThread != null) { + try { + _repeatThread.interrupt(); + } catch (Exception ex) { + } + try { + _repeatThread.join(1000); + } catch (Exception ex) { + } + _repeatThread = null; + } + } + + @Override + public void mousePressed(MouseEvent e) { + if (inCursor(e.getX(), e.getY())) { + _base = e.getY() - getMargin() - getPos(); + _mouseDown = true; + repaint(); + return; + } else if (inSubArrow(e.getX(), e.getY())) { + _mouseDownUp = true; + updateValue(_val - 1); + repaint(); + } else if (inAddArrow(e.getX(), e.getY())) { + _mouseDownDown = true; + updateValue(_val + 1); + repaint(); + } else if (getValue(e.getX(), e.getY()) < _val) { + updateValue(_val - 10); + repaint(); + } else if (getValue(e.getX(), e.getY()) > _val) { + updateValue(_val + 10); + repaint(); + } + if (_repeatThread == null) + beginRepeat(e); + } + + @Override + public void mouseReleased(MouseEvent e) { + endRepeat(); + _mouseDown = false; + _mouseDownUp = false; + _mouseDownDown = false; + repaint(); + } + + @Override + public void mouseDragged(MouseEvent e) { + mouseMoved(e); + } + + @Override + public void mouseMoved(MouseEvent e) { + _repeatEvent = e; + if (_mouseDown) { + updateValue(getValue(e.getX(), e.getY())); + } + } +} diff --git a/src/main/java/irc/gui/pixx/ScrollablePixxNickList.java b/src/main/java/irc/gui/pixx/ScrollablePixxNickList.java new file mode 100644 index 0000000..0c9709c --- /dev/null +++ b/src/main/java/irc/gui/pixx/ScrollablePixxNickList.java @@ -0,0 +1,142 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.pixx; + +import java.awt.BorderLayout; +import java.awt.Panel; + +/** + * A scrollable nick list. + */ +public class ScrollablePixxNickList extends PixxPanel implements PixxScrollBarListener { + private PixxNickList _list; + private PixxVerticalScrollBar _scroll; + + /** + * Create a new ScrollablePixxNickList. + * + * @param config + * the global irc configuration. + * @param prefixes + * known nick prefixes. + */ + public ScrollablePixxNickList(PixxConfiguration config, char[] prefixes) { + super(config); + setLayout(new BorderLayout()); + Panel p = new Panel(); + p.setLayout(new BorderLayout()); + + _list = new PixxNickList(config, prefixes); + _scroll = new PixxVerticalScrollBar(config, 0, 0, 0.1); + _scroll.addPixxScrollBarListener(this); + p.add(_list, BorderLayout.CENTER); + p.add(_scroll, BorderLayout.EAST); + + add(p, BorderLayout.CENTER); + add(new PixxSeparator(PixxSeparator.BORDER_LEFT), BorderLayout.WEST); + add(new PixxSeparator(PixxSeparator.BORDER_RIGHT), BorderLayout.EAST); + add(new PixxSeparator(PixxSeparator.BORDER_UP), BorderLayout.NORTH); + add(new PixxSeparator(PixxSeparator.BORDER_DOWN), BorderLayout.SOUTH); + } + + @Override + public void release() { + _scroll.removePixxScrollBarListener(this); + _list.release(); + _scroll.release(); + _list = null; + _scroll = null; + super.release(); + } + + /** + * Add a listener. + * + * @param lis + * the listener to add. + */ + public void addPixxNickListListener(PixxNickListListener lis) { + _list.addPixxNickListListener(lis); + } + + /** + * Remove a listener. + * + * @param lis + * the listener to remove. + */ + public void removePixxNickListListener(PixxNickListListener lis) { + _list.removePixxNickListListener(lis); + } + + /** + * Set all the nicks. + * + * @param nicks + * new nick list. + */ + public void set(String[] nicks) { + _list.set(nicks); + _scroll.setMaximum(_list.getNickCount() - 1); + } + + /** + * Add a nick. + * + * @param nick + * nick to add. + */ + public void add(String nick) { + _list.add(nick); + _scroll.setMaximum(_list.getNickCount() - 1); + } + + /** + * Remove all nicks. + */ + @Override + public void removeAll() { + _list.removeAll(); + _scroll.setMaximum(_list.getNickCount() - 1); + } + + @Override + public void valueChanged(PixxScrollBar pixScrollBar) { + _list.setBase(pixScrollBar.getValue()); + } + + /** + * Clear any off-screen ressources. The next display might be slower. + */ + public void dispose() { + _list.dispose(); + } + +} diff --git a/src/main/java/irc/gui/prv/MouseWheelPanel.java b/src/main/java/irc/gui/prv/MouseWheelPanel.java new file mode 100644 index 0000000..51b5c9f --- /dev/null +++ b/src/main/java/irc/gui/prv/MouseWheelPanel.java @@ -0,0 +1,80 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.gui.prv; + +import irc.ListenerGroup; +import irc.gui.common.MouseWheelPanelListener; + +import java.awt.GridLayout; +import java.awt.Panel; +import java.awt.event.MouseWheelEvent; +import java.awt.event.MouseWheelListener; + +/** + * MouseWheelPanel. Should be compiled using java jdk1.4. + */ +public class MouseWheelPanel extends Panel implements MouseWheelListener { + private ListenerGroup _listeners; + + /** + * Create a new MouseWheelPanel. + */ + public MouseWheelPanel() { + super(); + _listeners = new ListenerGroup(); + addMouseWheelListener(this); + setLayout(new GridLayout(1, 1)); + } + + /** + * Add a listener. + * + * @param lis + * listener to add. + */ + public void addMouseWheelPanelListener(MouseWheelPanelListener lis) { + _listeners.addListener(lis); + } + + /** + * Remove a listener. + * + * @param lis + * listener to remove. + */ + public void removeMouseWheelPanelListener(MouseWheelPanelListener lis) { + _listeners.removeListener(lis); + } + + @Override + public void mouseWheelMoved(MouseWheelEvent e) { + _listeners.sendEventAsync("mouseWheelMoved", new Integer(e.getWheelRotation())); + } +} diff --git a/src/main/java/irc/ident/IdentListener.java b/src/main/java/irc/ident/IdentListener.java new file mode 100644 index 0000000..b4ca791 --- /dev/null +++ b/src/main/java/irc/ident/IdentListener.java @@ -0,0 +1,81 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.ident; + +/** + * The ident server listener. + */ +public interface IdentListener { + /** + * Error result. + */ + public static final int IDENT_ERROR = -1; + /** + * Success result. + */ + public static final int IDENT_OK = 0; + /** + * Replied default user. + */ + public static final int IDENT_DEFAULT = 1; + /** + * Replied not found user. + */ + public static final int IDENT_NOT_FOUND = 2; + + /** + * The ident server has received a request. + * + * @param source + * the request source. + * @param result + * the request result. + * @param reply + * the replied result. + */ + public void identRequested(String source, Integer result, String reply); + + /** + * The ident server is running. + * + * @param port + * port on wich the server is running. + */ + public void identRunning(Integer port); + + /** + * The ident server is leaving. + * + * @param message + * leaving message. + */ + public void identLeaving(String message); + +} diff --git a/src/main/java/irc/ident/IdentWrapper.java b/src/main/java/irc/ident/IdentWrapper.java new file mode 100644 index 0000000..1f671e7 --- /dev/null +++ b/src/main/java/irc/ident/IdentWrapper.java @@ -0,0 +1,87 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.ident; + +import irc.IRCConfiguration; +import irc.IRCObject; +import irc.ident.prv.IdentServer; + +/** + * Ident wrapper. + */ +public class IdentWrapper extends IRCObject { + private IdentServer _ident; + private IdentListener _lis; + + /** + * Create a new IdentWrapper. + * + * @param config + * the global configuration. + */ + public IdentWrapper(IRCConfiguration config) { + super(config); + } + + /** + * Start the execution of the ident server, using default configuration. + * + * @param userName + * ident user name. + * @param lis + * the listener to use. + * @return any occured exception if failed, or null if everything went well. + */ + public Exception start(String userName, IdentListener lis) { + _lis = lis; + _ident = new IdentServer(_ircConfiguration); + _ident.addIdentListener(lis); + String name = _ircConfiguration.getS("userid"); + if (name.length() == 0) + name = userName; + _ident.setDefaultUser("JAVA", name); + try { + int port = 113; + _ident.start(port); + return null; + } catch (Exception e) { + return e; + } + } + + /** + * Stop the execution of the ident server. + */ + public void stop() { + _ident.removeIdentListener(_lis); + _ident.stop(); + _lis = null; + } +} diff --git a/src/main/java/irc/ident/prv/IdentServer.java b/src/main/java/irc/ident/prv/IdentServer.java new file mode 100644 index 0000000..2297961 --- /dev/null +++ b/src/main/java/irc/ident/prv/IdentServer.java @@ -0,0 +1,275 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2005 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.ident.prv; + +import irc.IRCConfiguration; +import irc.IRCObject; +import irc.IRCTextProvider; +import irc.ListenerGroup; +import irc.ident.IdentListener; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.Hashtable; + +/** + * LocalInfo. + */ +class LocalInfo { + /** + * Create a new LocalInfo + * + * @param alocalPort + * local port. + * @param asystem + * system name. + * @param aid + * user id. + */ + public LocalInfo(int alocalPort, String asystem, String aid) { + localPort = alocalPort; + system = asystem; + id = aid; + } + + /** + * Local port. + */ + public int localPort; + /** + * System name. + */ + public String system; + /** + * User id. + */ + public String id; +} + +/** + * The built-in pjirc ident server. + */ +public class IdentServer extends IRCObject implements Runnable { + private Thread _thread; + private boolean _running; + private Hashtable _table; + private ServerSocket _serverSocket; + private boolean _defaultUser; + private String _system; + private String _id; + private ListenerGroup _listeners; + private int _port; + + /** + * Create a new IdentServer. + * + * @param config + * global irc configuration. + */ + public IdentServer(IRCConfiguration config) { + super(config); + resetDefaultUser(); + _table = new Hashtable(); + _listeners = new ListenerGroup(); + _thread = null; + } + + /** + * Start the ident server. + * + * @throws Exception + */ + public void start() throws Exception { + start(113); + } + + /** + * Erase the default user configuration. + */ + public void resetDefaultUser() { + _defaultUser = false; + } + + /** + * Set the default user configuration. + * + * @param system + * user system. + * @param id + * user id. + */ + public void setDefaultUser(String system, String id) { + _defaultUser = true; + _system = system; + _id = id; + } + + /** + * Start the ident server on the given port. + * + * @param port + * ident server port. + * @throws Exception + */ + public void start(int port) throws Exception { + _port = port; + _running = false; + _serverSocket = _ircConfiguration.getSecurityProvider().getServerSocket(_port); + _thread = new Thread(this, "IDENT server"); + _thread.start(); + while (!_running) + Thread.yield(); + } + + /** + * Stop the execution of the ident server. + */ + public void stop() { + if (_thread == null) + return; + try { + _serverSocket.close(); + _thread.join(); + _thread = null; + } catch (Exception e) { + // e.printStackTrace(); + } + } + + /** + * Register a new local connection. + * + * @param localPort + * the local port of this connection. + * @param system + * user system on this connection. + * @param id + * user id on this connection. + */ + public synchronized void registerLocalConnection(int localPort, String system, String id) { + _table.put(new Integer(localPort), new LocalInfo(localPort, system, id)); + } + + /** + * Unregister a local connection. + * + * @param localPort + * local port. + */ + public synchronized void unregisterLocalConnection(int localPort) { + _table.remove(new Integer(localPort)); + } + + private synchronized LocalInfo processRequest(int localPort) { + return (LocalInfo) _table.get(new Integer(localPort)); + } + + /** + * Add a listener. + * + * @param lis + * listener to add. + */ + public synchronized void addIdentListener(IdentListener lis) { + _listeners.addListener(lis); + } + + /** + * Remove a listener. + * + * @param lis + * listener to remove. + */ + public synchronized void removeIdentListener(IdentListener lis) { + _listeners.removeListener(lis); + } + + @Override + public void run() { + boolean terminated = false; + + _running = true; + _listeners.sendEventAsync("identRunning", new Integer(_port)); + while (!terminated) { + try { + Socket s = _serverSocket.accept(); + String from = getText(IRCTextProvider.IDENT_UNKNOWN); + int result = IdentListener.IDENT_ERROR; + String reply = getText(IRCTextProvider.IDENT_NONE); + try { + try { + from = _ircConfiguration.getSecurityProvider().resolve(s.getInetAddress()); + } catch (Exception e) { + from = s.getInetAddress().getHostAddress(); + } + BufferedReader reader = new BufferedReader(new InputStreamReader(s.getInputStream())); + BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(s.getOutputStream())); + String request = reader.readLine(); + int pos = request.indexOf(','); + String serverSide = request.substring(0, pos).trim(); + String clientSide = request.substring(pos + 1).trim(); + + LocalInfo info = processRequest(new Integer(serverSide).intValue()); + reply = serverSide + " , " + clientSide + " : "; + if (info == null) { + if (!_defaultUser) { + result = IdentListener.IDENT_NOT_FOUND; + reply += "ERROR : NO-USER"; + } else { + result = IdentListener.IDENT_DEFAULT; + reply += "USERID : " + _system + " : " + _id; + } + } else { + result = IdentListener.IDENT_OK; + reply += "USERID : " + info.system + " : " + info.id; + } + + writer.write(reply + "\n"); + writer.flush(); + reader.close(); + writer.close(); + s.close(); + _listeners.sendEventAsync("identRequested", from, new Integer(result), reply); + + } catch (Exception e) { + _listeners.sendEventAsync("identRequested", from, new Integer(IdentListener.IDENT_ERROR), e.getMessage()); + } + } catch (Exception e) { + _listeners.sendEventAsync("identLeaving", e.getMessage()); + terminated = true; + } + } + } + +} diff --git a/src/main/java/irc/plugin/Plugin.java b/src/main/java/irc/plugin/Plugin.java new file mode 100644 index 0000000..8c7ab68 --- /dev/null +++ b/src/main/java/irc/plugin/Plugin.java @@ -0,0 +1,175 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2005 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.plugin; + +import irc.IRCApplication; +import irc.IRCConfiguration; +import irc.Server; +import irc.Source; + +/** + * The root class for all plugins. + */ +public abstract class Plugin { + + /** + * The global IRCConfiguration instance. + */ + protected IRCConfiguration _ircConfiguration; + /** + * The running IRCApplication instance. + */ + protected IRCApplication _ircApplication; + + /** + * Create a new Plugin with the given IRCConfiguration instance. + * + * @param ircConfiguration + * the global IRCConfiguration instance. + */ + public Plugin(IRCConfiguration ircConfiguration) { + _ircConfiguration = ircConfiguration; + } + + /** + * Set the running IRCApplication instance. + * + * @param ircApplication + * the running IRCApplication. + */ + public void setIRCApplication(IRCApplication ircApplication) { + _ircApplication = ircApplication; + } + + /** + * Load the plugin. + */ + public void load() { + // default empty implementation... + } + + /** + * Unload any ressources used by this plugin. This should be the last method + * call on the instance. + */ + public void unload() { + _ircConfiguration = null; + _ircApplication = null; + } + + /** + * Notify this plugin that a new source has been created. + * + * @param source + * the newly created source. + * @param bring + * is true if the newly created source should gain immediate focus, + * false is no particular action is to be taken. + */ + public void sourceCreated(Source source, Boolean bring) { + // default empty implementation... + } + + /** + * Notify this plugin that an existing source has been removed. No further + * call should be performed on this source. + * + * @param source + * the removed source. + */ + public void sourceRemoved(Source source) { + // default empty implementation... + } + + /** + * Notify this plugin that a new server has been created. + * + * @param s + * the newly created server. + */ + public void serverCreated(Server s) { + // default empty implementation... + } + + /** + * Notify this plugin that an existing server has acheived connection to its + * remote host. + * + * @param s + * connected server. + */ + public void serverConnected(Server s) { + // default empty implementation... + } + + /** + * Notify this plugin that an existing server has disconnected from its remote + * host. + * + * @param s + * disconnected server. + */ + public void serverDisconnected(Server s) { + // default empty implementation... + } + + /** + * Notify this plugin that an existing server has been removed. No further + * call should be performed on this server. + * + * @param s + * server removed + */ + public void serverRemoved(Server s) { + // default empty implementation... + } + + /** + * Notify this plugin that an external event has been triggered on it. + * + * @param event + * the event value. + */ + public void externalEvent(Object event) { + // default empty implementation... + } + + /** + * Get the value from the name. + * + * @param name + * the value name. + * @return the plugin value for this name. + */ + public Object getValue(Object name) { + return null; + } + +} // Plugin diff --git a/src/main/java/irc/plugin/test/Test.java b/src/main/java/irc/plugin/test/Test.java new file mode 100644 index 0000000..cda8359 --- /dev/null +++ b/src/main/java/irc/plugin/test/Test.java @@ -0,0 +1,57 @@ +package irc.plugin.test; + +import irc.IRCConfiguration; +import irc.Source; +import irc.SourceListener; +import irc.plugin.Plugin; + +/** + * Simple test plugin. + */ +public class Test extends Plugin implements SourceListener { + /** + * Create a new Test + * + * @param config + */ + public Test(IRCConfiguration config) { + super(config); + } + + @Override + public void sourceCreated(Source source, Boolean bring) { + source.addSourceListener(this); + } + + @Override + public void sourceRemoved(Source source) { + source.removeSourceListener(this); + } + + @Override + public void messageReceived(String nick, String msg, Source source) { + if (msg.startsWith("!hello")) + source.sendUserString("World!"); + } + + @Override + public void reportReceived(String message, Source source) { + // default empty implementation... + } + + @Override + public void noticeReceived(String nick, String message, Source source) { + // default empty implementation... + } + + @Override + public void action(String nick, String msg, Source source) { + // default empty implementation... + } + + @Override + public void clear(Source source) { + // default empty implementation... + } + +} diff --git a/src/main/java/irc/security/DefaultSecuredProvider.java b/src/main/java/irc/security/DefaultSecuredProvider.java new file mode 100644 index 0000000..7ab33bd --- /dev/null +++ b/src/main/java/irc/security/DefaultSecuredProvider.java @@ -0,0 +1,137 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.security; + +import java.awt.FileDialog; +import java.awt.Frame; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.UnknownHostException; + +/** + * Default secured provider. + */ +public class DefaultSecuredProvider implements SecuredProvider { + + @Override + public Socket getSocket(String host, Integer port) throws UnknownHostException, IOException { + return new Socket(host, port.intValue()); + } + + @Override + public ServerSocket getServerSocket(Integer port) throws IOException { + return new ServerSocket(port.intValue()); + } + + @Override + public FileInputStream getFileInputStream(File file) throws IOException { + return new FileInputStream(file); + } + + @Override + public FileOutputStream getFileOutputStream(File file) throws IOException { + return new FileOutputStream(file); + } + + @Override + public Integer getFileSize(File file) { + return new Integer((int) file.length()); + } + + @Override + public File getLoadFile(String title) { + Frame f = new Frame(); + FileDialog dlg = new FileDialog(f, title, FileDialog.LOAD); + dlg.show(); + File ans = null; + if (dlg.getFile() != null) + ans = new File(dlg.getDirectory() + dlg.getFile()); + dlg.hide(); + dlg.dispose(); + f.dispose(); + return ans; + } + + @Override + public File getSaveFile(String title) { + Frame f = new Frame(); + FileDialog dlg = new FileDialog(f, title, FileDialog.SAVE); + dlg.show(); + File ans = null; + if (dlg.getFile() != null) + ans = new File(dlg.getDirectory() + dlg.getFile()); + dlg.hide(); + dlg.dispose(); + f.dispose(); + return ans; + } + + @Override + public File getSaveFile(String file, String title) { + Frame f = new Frame(); + FileDialog dlg = new FileDialog(f, title, FileDialog.SAVE); + dlg.setFile(file); + dlg.show(); + File ans = null; + if (dlg.getFile() != null) + ans = new File(dlg.getDirectory() + dlg.getFile()); + dlg.hide(); + dlg.dispose(); + f.dispose(); + return ans; + } + + @Override + public InetAddress getLocalHost() throws UnknownHostException { + InetAddress[] addresses = InetAddress.getAllByName(InetAddress.getLocalHost().getHostName()); + return addresses[addresses.length - 1]; + } + + @Override + public String resolve(InetAddress addr) { + return addr.getHostName(); + } + + @Override + public boolean tryProvider() { + return true; + } + + @Override + public String getName() { + return "Default Security Provider"; + } + +} diff --git a/src/main/java/irc/security/SecuredProvider.java b/src/main/java/irc/security/SecuredProvider.java new file mode 100644 index 0000000..3bb5715 --- /dev/null +++ b/src/main/java/irc/security/SecuredProvider.java @@ -0,0 +1,163 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.security; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.UnknownHostException; + +/** + * Provide methods for accessing protected operations. + */ +public interface SecuredProvider { + /** + * Get a new Socket. + * + * @param host + * server host. + * @param port + * server port. + * @throws UnknownHostException + * is host is not found. + * @throws IOException + * if an error occurs. + * @return a new Socket. + */ + public Socket getSocket(String host, Integer port) throws UnknownHostException, IOException; + + /** + * Get a new ServerSocket. + * + * @param port + * local port. + * @return the created server socket. + * @throws IOException + * if an error occurs. + */ + public ServerSocket getServerSocket(Integer port) throws IOException; + + /** + * Get an FileInputStream from a local file. + * + * @param file + * the local file. + * @throws IOException + * if an error occurs. + * @return an FileInputStream from the file. + */ + public FileInputStream getFileInputStream(File file) throws IOException; + + /** + * Get an FileOutputStream to a local file. + * + * @param file + * the local file. + * @throws IOException + * if an error occurs. + * @return an FileOutputStream from the file. + */ + public FileOutputStream getFileOutputStream(File file) throws IOException; + + /** + * Get the file size. + * + * @param file + * the file to get size. + * @return the file size, of a negative value if not able. + */ + public Integer getFileSize(File file); + + /** + * Open a load file dialog with the given title and return the user choice. + * + * @param title + * dialog title. + * @return user choice. + */ + public File getLoadFile(String title); + + /** + * Open a save file dialog with the given title and return the user choice. + * + * @param title + * dialog title. + * @return user choice. + */ + public File getSaveFile(String title); + + /** + * Open a save file dialog with the given title and return the user choice. + * + * @param file + * default file. + * @param title + * dialog title. + * @return user choice. + */ + public File getSaveFile(String file, String title); + + /** + * Get the local host address. + * + * @return local host address. + * @throws UnknownHostException + * if error occurs. + */ + public InetAddress getLocalHost() throws UnknownHostException; + + /** + * Perform a dns resolve of the given address. + * + * @param addr + * address to resolve. + * @return resolved address. + */ + public String resolve(InetAddress addr); + + /** + * Try to use this provider. Return false if this provider is not able to + * perform its task. + * + * @return true if this provider can be used, false otherwise. + */ + public boolean tryProvider(); + + /** + * Get this provider's name. + * + * @return the provder name. + */ + public String getName(); +} diff --git a/src/main/java/irc/security/SecurityProvider.java b/src/main/java/irc/security/SecurityProvider.java new file mode 100644 index 0000000..cbd7c16 --- /dev/null +++ b/src/main/java/irc/security/SecurityProvider.java @@ -0,0 +1,353 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2005 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.security; + +import irc.EventDispatcher; + +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Dialog; +import java.awt.Frame; +import java.awt.Label; +import java.awt.Panel; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.UnknownHostException; + +/** + * The security provider. Provides an interface for accessing protected data or + * operation. + */ +public class SecurityProvider implements ActionListener { + private SecuredProvider _provider; + // private Object _lock=new Object(); + private boolean _answer; + + /** + * Create a new SecurityProvider. + */ + public SecurityProvider() { + if (tryProvider("MS")) + return; + _provider = new DefaultSecuredProvider(); + } + + private boolean tryProvider(String name) { + SecuredProvider old = _provider; + try { + Class cl = Class.forName("irc.security.prv.Specific" + name + "SecuredProvider"); + _provider = (SecuredProvider) cl.newInstance(); + if (!_provider.tryProvider()) + throw new Exception(); + return true; + } catch (Exception ex) { + _provider = old; + return false; + } + } + + /** + * Get the used provider name. + * + * @return used provider name. + */ + public String getProviderName() { + return _provider.getName(); + } + + /** + * Get a new Socket. + * + * @param host + * server host. + * @param port + * server port. + * @throws UnknownHostException + * is host is not found. + * @throws IOException + * if an error occurs. + * @return a new Socket. + */ + public Socket getSocket(String host, int port) throws UnknownHostException, IOException { + try { + Socket ans = (Socket) EventDispatcher.dispatchEventAsyncAndWaitExSecurity(_provider, "getSocket", new Object[] { + host, new Integer(port) }); + return ans; + } catch (InterruptedException ex) { + throw new IOException("Interrupted"); + } catch (Throwable ex) { + throw new IOException(ex.getClass().getName() + " : " + ex.getMessage()); + } + } + + /** + * Get a new ServerSocket. + * + * @param port + * local port. + * @return the created server socket. + * @throws IOException + * if an error occurs. + */ + public ServerSocket getServerSocket(int port) throws IOException { + try { + return (ServerSocket) EventDispatcher.dispatchEventAsyncAndWaitExSecurity(_provider, "getServerSocket", + new Object[] { new Integer(port) }); + } catch (InterruptedException ex) { + throw new IOException("Interrupted"); + } catch (Throwable ex) { + throw new IOException(ex.getClass().getName() + " : " + ex.getMessage()); + } + } + + /** + * Display a request for confirmation. + * + * @param parent + * parent frame, or null if headless. + * @param title + * the message title. + * @param msg + * the message. + * @return true if the user replied yes, false otherwise. + */ + public boolean confirm(Frame parent, String title, String msg) { + Dialog f; + + Frame tmp = null; + + if (parent == null) { + tmp = new Frame(); + f = new Dialog(tmp, title, true); + } else { + f = new Dialog(parent, title, true); + } + + f.setLayout(new BorderLayout()); + f.add(new Label(msg), BorderLayout.CENTER); + Button b1 = new Button("Yes"); + Button b2 = new Button("No"); + Panel p = new Panel(); + f.setResizable(false); + f.add(p, BorderLayout.SOUTH); + p.add(b1); + p.add(b2); + b1.addActionListener(this); + b2.addActionListener(this); + f.pack(); + _answer = false; + f.show(); + /* + * synchronized(_lock) { try { _lock.wait(); } catch(InterruptedException + * ex) { } } + */ + + b1.removeActionListener(this); + b2.removeActionListener(this); + + f.hide(); + f.dispose(); + f = null; + + if (tmp != null) { + tmp.hide(); + tmp.dispose(); + tmp = null; + } + + return _answer; + } + + @Override + public void actionPerformed(ActionEvent e) { + Button b = (Button) e.getSource(); + _answer = false; + if (b.getLabel().equals("Yes")) + _answer = true; + /* + * synchronized(_lock) { _lock.notifyAll(); } + */ + ((Window) (b.getParent().getParent())).hide(); + } + + /** + * Get an FileInputStream from a local file. + * + * @param file + * the local file. + * @throws IOException + * if an error occurs. + * @return an FileInputStream from the file. + */ + public FileInputStream getFileInputStream(File file) throws IOException { + if (!confirm(null, "Security warning", "Authorize file read action on " + file + "?")) + throw new IOException("User denied access"); + + try { + return (FileInputStream) EventDispatcher.dispatchEventAsyncAndWaitExSecurity(_provider, "getFileInputStream", + new Object[] { file }); + } catch (InterruptedException ex) { + throw new IOException("Interrupted"); + } catch (Throwable ex) { + throw new IOException(ex.getMessage()); + } + } + + /** + * Get an FileOutputStream to a local file. + * + * @param file + * the local file. + * @throws IOException + * if an error occurs. + * @return an FileOutputStream from the file. + */ + public FileOutputStream getFileOutputStream(File file) throws IOException { + if (!confirm(null, "Security warning", "Authorize file write action on " + file + "?")) + throw new IOException("User denied access"); + + try { + return (FileOutputStream) EventDispatcher.dispatchEventAsyncAndWaitExSecurity(_provider, "getFileOutputStream", + new Object[] { file }); + } catch (InterruptedException ex) { + throw new IOException("Interrupted"); + } catch (Throwable ex) { + throw new IOException(ex.getMessage()); + } + } + + /** + * Get the file size. + * + * @param file + * the file to get size. + * @return the file size, of a negative value if not able. + */ + public int getFileSize(File file) { + try { + return ((Integer) EventDispatcher.dispatchEventAsyncAndWaitExSecurity(_provider, "getFileSize", + new Object[] { file })).intValue(); + } catch (Throwable ex) { + return -1; + } + } + + /** + * Open a load file dialog with the given title and return the user choice. + * + * @param title + * dialog title. + * @return user choice. + */ + public File getLoadFile(String title) { + try { + return (File) EventDispatcher.dispatchEventAsyncAndWaitExSecurity(_provider, "getLoadFile", + new Object[] { title }); + } catch (Throwable ex) { + return null; + } + } + + /** + * Open a save file dialog with the given title and return the user choice. + * + * @param title + * dialog title. + * @return user choice. + */ + public File getSaveFile(String title) { + try { + return (File) EventDispatcher.dispatchEventAsyncAndWaitExSecurity(_provider, "getSaveFile", + new Object[] { title }); + } catch (Throwable ex) { + return null; + } + } + + /** + * Open a save file dialog with the given title and return the user choice. + * + * @param file + * default target file. + * @param title + * dialog title. + * @return user choice. + */ + public File getSaveFile(String file, String title) { + try { + return (File) EventDispatcher.dispatchEventAsyncAndWaitExSecurity(_provider, "getSaveFile", new Object[] { file, + title }); + } catch (Throwable ex) { + return null; + } + } + + /** + * Get the local host address. + * + * @return local host address. + * @throws UnknownHostException + * if error occurs. + */ + public InetAddress getLocalHost() throws UnknownHostException { + try { + return (InetAddress) EventDispatcher.dispatchEventAsyncAndWaitExSecurity(_provider, "getLocalHost", + new Object[] {}); + } catch (InterruptedException ex) { + throw new UnknownHostException("Unable to resolve"); + } catch (Throwable ex) { + throw new UnknownHostException(ex.getMessage()); + } + } + + /** + * Perform a dns resolve of the given address. + * + * @param addr + * address to resolve. + * @return resolved address. + */ + public String resolve(InetAddress addr) { + try { + return (String) EventDispatcher.dispatchEventAsyncAndWaitExSecurity(_provider, "resolve", new Object[] { addr }); + } catch (Throwable ex) { + return null; + } + } + +} diff --git a/src/main/java/irc/security/prv/SpecificMSSecuredProvider.java b/src/main/java/irc/security/prv/SpecificMSSecuredProvider.java new file mode 100644 index 0000000..0b19c91 --- /dev/null +++ b/src/main/java/irc/security/prv/SpecificMSSecuredProvider.java @@ -0,0 +1,240 @@ +///*****************************************************/ +///* This java file is a part of the */ +///* */ +///* - Plouf's Java IRC Client - */ +///* */ +///* Copyright (C) 2002 - 2004 Philippe Detournay */ +///* */ +///* All contacts : theplouf@yahoo.com */ +///* */ +///* PJIRC is free software; you can redistribute */ +///* it and/or modify it under the terms of the GNU */ +///* General Public License as published by the */ +///* Free Software Foundation; version 2 or later of */ +///* the License. */ +///* */ +///* PJIRC is distributed in the hope that it will */ +///* be useful, but WITHOUT ANY WARRANTY; without */ +///* even the implied warranty of MERCHANTABILITY or */ +///* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +///* General Public License for more details. */ +///* */ +///* You should have received a copy of the GNU */ +///* General Public License along with PJIRC; if */ +///* not, write to the Free Software Foundation, */ +///* Inc., 59 Temple Place, Suite 330, Boston, */ +///* MA 02111-1307 USA */ +///* */ +///*****************************************************/ +// +//package irc.security.prv; +// +//import irc.security.SecuredProvider; +// +//import java.awt.FileDialog; +//import java.awt.Frame; +//import java.io.File; +//import java.io.FileInputStream; +//import java.io.FileOutputStream; +//import java.io.IOException; +//import java.net.InetAddress; +//import java.net.ServerSocket; +//import java.net.Socket; +//import java.net.UnknownHostException; +// +///** +// * Specific secured provider to use with microsoft internet explorer. +// */ +//public class SpecificMSSecuredProvider implements SecuredProvider { +// +// @Override +// public Socket getSocket(String host, Integer port) +// throws UnknownHostException, IOException { +// try { +// PolicyEngine.assertPermission(PermissionID.NETIO); +// return new Socket(host, port.intValue()); +// } catch (Throwable e) { +// return new Socket(host, port.intValue()); +// } +// } +// +// @Override +// public ServerSocket getServerSocket(Integer port) throws IOException { +// try { +// PolicyEngine.assertPermission(PermissionID.NETIO); +// return new SpecificMSSecuredServerSocket(port.intValue()); +// } catch (Throwable e) { +// return new SpecificMSSecuredServerSocket(port.intValue()); +// } +// } +// +// @Override +// public FileInputStream getFileInputStream(File file) throws IOException { +// try { +// PolicyEngine.assertPermission(PermissionID.FILEIO); +// return new FileInputStream(file); +// } catch (Throwable e) { +// return new FileInputStream(file); +// } +// } +// +// @Override +// public Integer getFileSize(File file) { +// try { +// PolicyEngine.assertPermission(PermissionID.FILEIO); +// return new Integer((int) file.length()); +// } catch (Throwable e) { +// return new Integer((int) file.length()); +// } +// } +// +// @Override +// public FileOutputStream getFileOutputStream(File file) throws IOException { +// try { +// PolicyEngine.assertPermission(PermissionID.FILEIO); +// return new FileOutputStream(file); +// } catch (Throwable e) { +// return new FileOutputStream(file); +// } +// } +// +// /** +// * Open a file dialog. +// * +// * @param top +// * parent window. +// * @param title +// * dialog title. +// * @param type +// * dialog type. +// * @return newly created file dialog. +// */ +// public FileDialog getFileDialog(Frame top, String title, int type) { +// try { +// PolicyEngine.assertPermission(PermissionID.UI); +// return new FileDialog(top, title, type); +// } catch (Throwable e) { +// return new FileDialog(top, title, type); +// } +// } +// +// @Override +// public File getLoadFile(String title) { +// try { +// PolicyEngine.assertPermission(PermissionID.UI); +// Frame f = new Frame(); +// FileDialog dlg = new FileDialog(f, title, FileDialog.LOAD); +// dlg.show(); +// File ans = null; +// if (dlg.getFile() != null) +// ans = new File(dlg.getDirectory() + dlg.getFile()); +// dlg.hide(); +// dlg.dispose(); +// f.dispose(); +// return ans; +// } catch (Throwable e) { +// Frame f = new Frame(); +// FileDialog dlg = new FileDialog(f, title, FileDialog.LOAD); +// dlg.show(); +// File ans = null; +// if (dlg.getFile() != null) +// ans = new File(dlg.getDirectory() + dlg.getFile()); +// dlg.hide(); +// dlg.dispose(); +// f.dispose(); +// return ans; +// } +// } +// +// @Override +// public File getSaveFile(String title) { +// try { +// PolicyEngine.assertPermission(PermissionID.UI); +// Frame f = new Frame(); +// FileDialog dlg = new FileDialog(f, title, FileDialog.SAVE); +// dlg.show(); +// File ans = new File(dlg.getDirectory() + dlg.getFile()); +// dlg.hide(); +// dlg.dispose(); +// f.dispose(); +// return ans; +// } catch (Throwable e) { +// Frame f = new Frame(); +// FileDialog dlg = new FileDialog(f, title, FileDialog.SAVE); +// dlg.show(); +// File ans = new File(dlg.getDirectory() + dlg.getFile()); +// dlg.hide(); +// dlg.dispose(); +// f.dispose(); +// return ans; +// } +// } +// +// @Override +// public File getSaveFile(String file, String title) { +// try { +// PolicyEngine.assertPermission(PermissionID.UI); +// Frame f = new Frame(); +// FileDialog dlg = new FileDialog(f, title, FileDialog.SAVE); +// dlg.setFile(file); +// dlg.show(); +// File ans = new File(dlg.getDirectory() + dlg.getFile()); +// dlg.hide(); +// dlg.dispose(); +// f.dispose(); +// return ans; +// } catch (Throwable e) { +// Frame f = new Frame(); +// FileDialog dlg = new FileDialog(f, title, FileDialog.SAVE); +// dlg.setFile(file); +// dlg.show(); +// File ans = new File(dlg.getDirectory() + dlg.getFile()); +// dlg.hide(); +// dlg.dispose(); +// f.dispose(); +// return ans; +// } +// } +// +// @Override +// public InetAddress getLocalHost() throws UnknownHostException { +// try { +// PolicyEngine.assertPermission(PermissionID.NETIO); +// InetAddress[] addresses = InetAddress.getAllByName(InetAddress +// .getLocalHost().getHostName()); +// return addresses[addresses.length - 1]; +// } catch (Throwable e) { +// InetAddress[] addresses = InetAddress.getAllByName(InetAddress +// .getLocalHost().getHostName()); +// return addresses[addresses.length - 1]; +// } +// } +// +// @Override +// public String resolve(InetAddress addr) { +// try { +// PolicyEngine.assertPermission(PermissionID.NETIO); +// return addr.getHostName(); +// } catch (Throwable e) { +// return addr.getHostName(); +// } +// +// } +// +// @Override +// public boolean tryProvider() { +// try { +// PolicyEngine.assertPermission(PermissionID.FILEIO); +// PolicyEngine.assertPermission(PermissionID.NETIO); +// PolicyEngine.assertPermission(PermissionID.UI); +// return true; +// } catch (Throwable e) { +// return false; +// } +// } +// +// @Override +// public String getName() { +// return "Microsoft Internet Explorer Security Provider"; +// } +// } diff --git a/src/main/java/irc/security/prv/SpecificMSSecuredServerSocket.java b/src/main/java/irc/security/prv/SpecificMSSecuredServerSocket.java new file mode 100644 index 0000000..e23ff25 --- /dev/null +++ b/src/main/java/irc/security/prv/SpecificMSSecuredServerSocket.java @@ -0,0 +1,67 @@ +///*****************************************************/ +///* This java file is a part of the */ +///* */ +///* - Plouf's Java IRC Client - */ +///* */ +///* Copyright (C) 2002 - 2004 Philippe Detournay */ +///* */ +///* All contacts : theplouf@yahoo.com */ +///* */ +///* PJIRC is free software; you can redistribute */ +///* it and/or modify it under the terms of the GNU */ +///* General Public License as published by the */ +///* Free Software Foundation; version 2 or later of */ +///* the License. */ +///* */ +///* PJIRC is distributed in the hope that it will */ +///* be useful, but WITHOUT ANY WARRANTY; without */ +///* even the implied warranty of MERCHANTABILITY or */ +///* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +///* General Public License for more details. */ +///* */ +///* You should have received a copy of the GNU */ +///* General Public License along with PJIRC; if */ +///* not, write to the Free Software Foundation, */ +///* Inc., 59 Temple Place, Suite 330, Boston, */ +///* MA 02111-1307 USA */ +///* */ +///*****************************************************/ +// +//package irc.security.prv; +// +//import java.io.*; +//import java.net.*; +//import com.ms.security.*; +// +///** +// * A secured server socket for microsoft internet explorer. +// */ +//public class SpecificMSSecuredServerSocket extends ServerSocket +//{ +// +// /** +// * Create a new ServerSocket. +// * @param port port on wich to listener. +// * @throws IOException if error occurs. +// */ +// public SpecificMSSecuredServerSocket(int port) throws IOException +// { +// super(port); +// } +// +// public Socket accept() throws IOException +// { +// try +// { +// PolicyEngine.assertPermission(PermissionID.NETIO); +// return super.accept(); +// } +// catch(Throwable e) +// { +// return super.accept(); +// } +// +// } +// +//} +// diff --git a/src/main/java/irc/style/ChannelRecognizer.java b/src/main/java/irc/style/ChannelRecognizer.java new file mode 100644 index 0000000..41b182e --- /dev/null +++ b/src/main/java/irc/style/ChannelRecognizer.java @@ -0,0 +1,46 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.style; + +/** + * The channel recognizer. + */ +public class ChannelRecognizer implements WordRecognizer { + @Override + public boolean recognize(String word) { + return word.startsWith("#") && (word.length() > 1); + } + + @Override + public String getType() { + return "channel"; + } + +} diff --git a/src/main/java/irc/style/CharactersDrawer.java b/src/main/java/irc/style/CharactersDrawer.java new file mode 100644 index 0000000..d7c7a76 --- /dev/null +++ b/src/main/java/irc/style/CharactersDrawer.java @@ -0,0 +1,258 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.style; + +import irc.IRCConfiguration; +import irc.SmileyTable; + +import java.awt.Dimension; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.image.ImageObserver; +import java.util.Vector; + +/** + * Atomic characters drawer. The CharactersDrawer handles graphical smileys. + */ +public class CharactersDrawer { + private IRCConfiguration _ircConfiguration; + private char[] _current; + private int _lineSpacing; + + /** + * Create a new CharactersDrawer. + * + * @param config + * the irc configuration. + */ + public CharactersDrawer(IRCConfiguration config) { + _ircConfiguration = config; + _current = new char[256]; + _lineSpacing = config.getI("style:linespacing"); + } + + private int getBitmapSmileyWidth(int c, ImageObserver obs) { + Image img = _ircConfiguration.getSmileyTable().getImage(c); + if (img == null) + return 0; + return img.getWidth(obs); + } + + private int getBitmapSmileyHeight(int c, ImageObserver obs) { + Image img = _ircConfiguration.getSmileyTable().getImage(c); + if (img == null) + return 0; + return img.getHeight(obs); + } + + private Object drawBitmapSmiley(Graphics g, FontMetrics fm, int smiley, int x, int y, ImageObserver obs) { + Image img = _ircConfiguration.getSmileyTable().getImage(smiley); + if (img == null) + return null; + int h = getBitmapSmileyHeight(smiley, obs); + y -= h; + y += fm.getDescent(); + + g.drawImage(img, x, y, obs); + return img; + } + + private String handleSmiley(String line, String ascii, char code) { + int pos = line.indexOf(ascii); + if (pos == -1) + return line; + + String previous = line.substring(0, pos); + String after = line.substring(pos + ascii.length()); + char toAdd = (char) (code + 0xE000); + line = previous + toAdd + after; + return handleSmiley(line, ascii, code); + } + + /** + * Prepare and decode the given line for smileys. + * + * @param line + * source line, before smileys replacement. + * @return prepared line with special characters. + */ + public String decodeLine(String line) { + SmileyTable table = _ircConfiguration.getSmileyTable(); + int s = table.getSize(); + for (int i = 0; i < s; i++) { + String m = table.getMatch(i); + line = handleSmiley(line, m, (char) (i)); + } + return line; + } + + /** + * Get the given string width, in pixel. + * + * @param str + * the prepared line. + * @param fm + * the FontMetrics that will be used on display. + * @param obs + * the image observer in case of bitmap handling. + * @return the string width, in pixel. + */ + public int getWidth(String str, FontMetrics fm, ImageObserver obs) { + if (_current.length < str.length()) + _current = new char[str.length() * 2]; + int size = 0; + int w = 0; + for (int i = 0; i < str.length(); i++) { + char c = str.charAt(i); + if ((c >= 0xE000) && (c <= 0xF8FF)) { + c -= 0xE000; + w += fm.charsWidth(_current, 0, size); + size = 0; + w += getBitmapSmileyWidth(c, obs); + } else { + _current[size++] = c; + } + } + w += fm.charsWidth(_current, 0, size); + return w; + } + + /** + * Get the given string height, in pixel. + * + * @param str + * the prepared line. + * @param fm + * the FontMetrics that will be used on display. + * @param obs + * the image observer in case of bitmap handling. + * @return the string height, in pixel. + */ + public int getHeight(String str, FontMetrics fm, ImageObserver obs) { + int h = 0; + int mh = 0; + for (int i = 0; i < str.length(); i++) { + char c = str.charAt(i); + if ((c >= 0xE000) && (c <= 0xF8FF)) { + c -= 0xE000; + h = getBitmapSmileyHeight(c, obs); + if (h > mh) + mh = h; + } + } + h = fm.getFont().getSize() + 1; + if (h > mh) + mh = h; + return mh + _lineSpacing; + } + + /** + * Get the given string width and height, in pixel. + * + * @param str + * the prepared line. + * @param fm + * the FontMetrics that will be used on display. + * @param res + * Dimension to be used for result. + * @param obs + * the image observer in case of bitmap handling. + */ + public void getWidthHeight(String str, FontMetrics fm, Dimension res, ImageObserver obs) { + if (_current.length < str.length()) + _current = new char[str.length() * 2]; + int size = 0; + int h = 0; + int w = 0; + int mh = 0; + for (int i = 0; i < str.length(); i++) { + char c = str.charAt(i); + if ((c >= 0xE000) && (c <= 0xF8FF)) { + c -= 0xE000; + w += fm.charsWidth(_current, 0, size); + h = getBitmapSmileyHeight(c, obs); + if (h > mh) + mh = h; + w += getBitmapSmileyWidth(c, obs); + size = 0; + } else { + _current[size++] = c; + } + } + w += fm.charsWidth(_current, 0, size); + h = fm.getFont().getSize() + 1; + if (h > mh) + mh = h; + res.width = w; + res.height = mh + _lineSpacing; + } + + /** + * Draw the given prepared line. + * + * @param str + * prepared line to draw. + * @param g + * graphics to draw onto. + * @param fm + * fontmetrics to use. + * @param x + * x position. + * @param y + * y position. + * @param obs + * the image observer in case of bitmap display. + * @param handles + * target vector, where all update handles will be put. + */ + public void draw(String str, Graphics g, FontMetrics fm, int x, int y, ImageObserver obs, Vector handles) { + if (_current.length < str.length()) + _current = new char[str.length() * 2]; + int size = 0; + for (int i = 0; i < str.length(); i++) { + char c = str.charAt(i); + if ((c >= 0xE000) && (c <= 0xF8FF)) { + c -= 0xE000; + g.drawChars(_current, 0, size, x, y); + x += fm.charsWidth(_current, 0, size); + size = 0; + Object handle = drawBitmapSmiley(g, fm, c, x, y, obs); + if (handles == null) + handles = new Vector(); + handles.insertElementAt(handle, handles.size()); + x += getBitmapSmileyWidth(c, obs); + } else { + _current[size++] = c; + } + } + g.drawChars(_current, 0, size, x, y); + } +} diff --git a/src/main/java/irc/style/DecodedLine.java b/src/main/java/irc/style/DecodedLine.java new file mode 100644 index 0000000..e00d0b4 --- /dev/null +++ b/src/main/java/irc/style/DecodedLine.java @@ -0,0 +1,48 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.style; + +/** + * A decoded line, ready for drawing. + */ +public abstract class DecodedLine { + /** + * Original string. + */ + public String original; + /** + * Decoded string. + */ + public String decoded; + /** + * Decoded string, but stripped of all color codes. + */ + public String decoded_stripped; +} diff --git a/src/main/java/irc/style/DrawResult.java b/src/main/java/irc/style/DrawResult.java new file mode 100644 index 0000000..e1675f6 --- /dev/null +++ b/src/main/java/irc/style/DrawResult.java @@ -0,0 +1,60 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.style; + +import java.util.Vector; + +/** + * A drawing result. + */ +public class DrawResult { + /** + * The list of all update handles for this draw result. + */ + public Vector updateHandles; + + /** + * The result rectangle. + */ + public StyledRectangle rectangle; + + /** + * An array of words in the rectangle. + */ + public DrawResultItem[] items; + + @Override + public String toString() { + String res = ""; + for (int i = 0; i < items.length; i++) + res += items[i].originalstrippedword; + return res; + } +} diff --git a/src/main/java/irc/style/DrawResultItem.java b/src/main/java/irc/style/DrawResultItem.java new file mode 100644 index 0000000..0c4e16a --- /dev/null +++ b/src/main/java/irc/style/DrawResultItem.java @@ -0,0 +1,78 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.style; + +/** + * A recognized item. + */ +public class DrawResultItem { + /** + * The item rectangle on display, relative to its parent. + */ + public StyledRectangle rectangle; + /** + * The item content. This content is the trimmed version of the stripped + * content. Characters like parenthesis and braces are also trimmed. For + * instance, "(text)" gives "text" in the itemized version. Item is used for + * word recognition. + */ + public String item; + /** + * The original word content. + */ + public String originalword; + /** + * The original word content, but stripped from all special codes. + */ + public String originalstrippedword; + /** + * The parent DrawResult. + */ + public DrawResult parent; + + @Override + public boolean equals(Object o) { + if (!(o instanceof DrawResultItem)) + return false; + DrawResultItem i = (DrawResultItem) o; + return i.rectangle.equals(rectangle) && i.originalword.equals(originalword) + && i.parent.rectangle.equals(parent.rectangle); + } + + @Override + public int hashCode() { + return rectangle.hashCode() + originalword.hashCode(); + } + + @Override + public String toString() { + return item + " at " + rectangle + " with parent at " + parent.rectangle; + } +} diff --git a/src/main/java/irc/style/FormattedStringDrawer.java b/src/main/java/irc/style/FormattedStringDrawer.java new file mode 100644 index 0000000..2f745c2 --- /dev/null +++ b/src/main/java/irc/style/FormattedStringDrawer.java @@ -0,0 +1,1036 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.style; + +import irc.EventDispatcher; +import irc.IRCConfiguration; +import irc.StyleContext; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.Rectangle; +import java.awt.image.ImageObserver; +import java.util.Vector; + +/** + * CharacterInfo. + */ +class CharacterInfo { + /** + * Create a new CharacterInfo + */ + public CharacterInfo() { + frontColor = Color.black; + backColor = Color.white; + isBold = false; + isUnderline = false; + isReverse = false; + isTransparent = true; + } + + /** + * Create a new CharacterInfo + * + * @param base + * base info that will be copied in the newly created instance. + */ + public CharacterInfo(CharacterInfo base) { + frontColor = base.frontColor; + backColor = base.backColor; + isBold = base.isBold; + isUnderline = base.isUnderline; + isReverse = base.isReverse; + isTransparent = base.isTransparent; + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof CharacterInfo)) + return false; + CharacterInfo c = (CharacterInfo) o; + if (!frontColor.equals(c.frontColor)) + return false; + if (!backColor.equals(c.backColor)) + return false; + if (isBold != c.isBold) + return false; + if (isUnderline != c.isUnderline) + return false; + if (isTransparent != c.isTransparent) + return false; + return true; + } + + @Override + public int hashCode() { + int c = 0; + if (isBold) + c++; + if (isUnderline) + c++; + if (isTransparent) + c++; + return c + frontColor.hashCode() + backColor.hashCode(); + } + + /** + * Front color. + */ + public Color frontColor; + /** + * Back color. + */ + public Color backColor; + /** + * True if bold. + */ + public boolean isBold; + /** + * True if underline. + */ + public boolean isUnderline; + /** + * True if reverse. + */ + public boolean isReverse; + /** + * True if transparent. + */ + public boolean isTransparent; +} + +/** + * CharacterGroupItem. + */ +class CharacterGroupItem { + /** + * String content. + */ + public String s; + /** + * String style. + */ + public CharacterInfo info; + + /** + * Create a new CharacterGroupItem + * + * @param nfo + * style. + */ + public CharacterGroupItem(CharacterInfo nfo) { + info = nfo; + s = ""; + } +} + +/** + * WordItem. + */ +class WordItem { + /** + * Items. + */ + public CharacterGroupItem[] items; + /** + * Original stripped word. + */ + public String originalstrippedword; + /** + * Original word. + */ + public String originalword; + /** + * Smiley-decoded word. + */ + public String decodedword; + /** + * Last character style. + */ + public CharacterInfo lastInfo; + + /** + * Create a new WordItem + * + * @param itm + * items. + * @param lInfo + * last character style. + */ + public WordItem(CharacterGroupItem[] itm, CharacterInfo lInfo) { + lastInfo = lInfo; + items = itm; + decodedword = ""; + for (int i = 0; i < items.length; i++) + decodedword += items[i].s; + originalword = decodedword; + originalstrippedword = decodedword; + } +} + +/** + * LineItem. + */ +class LineItem { + /** + * First item. + */ + public int first; + /** + * Number of items. + */ + public int count; +} + +/** + * DecodedLineInternal. + */ +class DecodedLineInternal extends DecodedLine { + /** + * All items. + */ + public WordItem[] words; +} + +/** + * The formatted string drawer. + */ +public class FormattedStringDrawer implements ImageObserver { + private Font _font; + private Font _fontPlain; + private Font _fontBold; + private Color[] _cols; + private CharactersDrawer _drawer; + private IRCConfiguration _config; + private Dimension _tmp; + private LineItem[] _lines; + private int _vdirection; + private int _hdirection; + private FormattedStringDrawerListener _listener; + + /** + * Bottom. + */ + public static final int BOTTOM = 0; + /** + * Top. + */ + public static final int TOP = 1; + /** + * Left. + */ + public static final int LEFT = 0; + /** + * Right. + */ + public static final int RIGHT = 1; + + /** + * Create a new FormattedStringDrawer. + * + * @param config + * the global configuration. + * @param context + * the style context to use. + * @param listener + * the listener to notify upon draw update. + */ + public FormattedStringDrawer(IRCConfiguration config, StyleContext context, FormattedStringDrawerListener listener) { + _listener = listener; + _tmp = new Dimension(); + _lines = new LineItem[8]; + for (int i = 0; i < _lines.length; i++) + _lines[i] = new LineItem(); + _config = config; + setFont(config.getStyleFont(context)); + _drawer = new CharactersDrawer(_config); + setStyleContext(context); + _vdirection = BOTTOM; + _hdirection = LEFT; + if (config.getB("style:righttoleft")) + setHorizontalDirection(RIGHT); + + } + + /** + * Create a new FormattedStringDrawer. + * + * @param config + * the global configuration. + * @param context + * the style context to use. + */ + public FormattedStringDrawer(IRCConfiguration config, StyleContext context) { + this(config, context, null); + } + + /** + * Set the vertical alignment direction. + * + * @param dir + * vertical direction. + */ + public void setVerticalDirection(int dir) { + _vdirection = dir; + } + + /** + * Get the vertical alignment direction. + * + * @return the vertical direction. + */ + public int getVerticalDirection() { + return _vdirection; + } + + /** + * Set the horizontal alignment direction. + * + * @param dir + * horizontal direction. + */ + public void setHorizontalDirection(int dir) { + _hdirection = dir; + } + + /** + * Get the horizontal alignment direction. + * + * @return horizontal direction. + */ + public int getHorizontalDirection() { + return _hdirection; + } + + /** + * Set the style context to use. + * + * @param context + * new color context. + */ + public void setStyleContext(StyleContext context) { + _cols = _config.getStyleColors(context); + } + + /** + * Prepare a line for display. + * + * @param str + * line to prepare. + * @return prepared line, ready for display. + */ + public DecodedLine decodeLine(String str) { + DecodedLineInternal ans = new DecodedLineInternal(); + ans.original = str; + str += (char) 15; + String decoded = _drawer.decodeLine(str); + ans.decoded = decoded; + ans.decoded_stripped = getStripped(decoded); + Vector v = doWords(str, decoded); + ans.words = new WordItem[v.size()]; + for (int i = 0; i < ans.words.length; i++) + ans.words[i] = (WordItem) v.elementAt(i); + return ans; + } + + private Vector doWords(String ostr, String dstr) { + Vector words = new Vector(); + CharacterInfo info = new CharacterInfo(); + info.frontColor = _cols[1]; + info.backColor = _cols[0]; + info.isTransparent = true; + + while (dstr.length() > 0) { + int opos = ostr.indexOf(' '); + int dpos = dstr.indexOf(' '); + WordItem word; + if (dpos == -1) { + word = decodeWord(info, dstr + " ", _cols); + word.originalword = ostr + " "; + word.originalstrippedword = getStripped(ostr + " "); + dstr = ""; + } else { + String owrd = ostr.substring(0, opos); + String dwrd = dstr.substring(0, dpos); + word = decodeWord(info, dwrd + " ", _cols); + word.originalword = owrd + " "; + word.originalstrippedword = getStripped(owrd + " "); + ostr = ostr.substring(opos + 1); + dstr = dstr.substring(dpos + 1); + } + words.insertElementAt(word, words.size()); + info = word.lastInfo; + } + + return words; + } + + /** + * Get the given string width, in pixel. + * + * @param str + * the prepared line. + * @param fm + * the FontMetrics that will be used on display. + * @return the string width, in pixel. + */ + public int getHeight(DecodedLine str, FontMetrics fm) { + return _drawer.getHeight(str.decoded_stripped, fm, this); + } + + /** + * Get the given string height, in pixel. + * + * @param str + * the prepared line. + * @param fm + * the FontMetrics that will be used on display. + * @return the string height, in pixel. + */ + public int getWidth(DecodedLine str, FontMetrics fm) { + return _drawer.getWidth(str.decoded_stripped, fm, this); + } + + private Font deriveFont(Font fnt, int style) { + return new Font(fnt.getName(), style, fnt.getSize()); + } + + /** + * Set the colors to use, overriding current colors from color context. + * + * @param cols + * colors to use. + */ + public void setColors(Color[] cols) { + _cols = cols; + } + + /** + * Get the current color at index i. + * + * @param i + * color index. + * @return the color at index i. + */ + public Color getColor(int i) { + return _cols[i]; + } + + /** + * Set the font to use. + * + * @param fnt + * the font to be used. + */ + public void setFont(Font fnt) { + _font = fnt; + _fontPlain = deriveFont(_font, Font.PLAIN); + _fontBold = deriveFont(_font, Font.BOLD); + } + + /** + * Get the used font. + * + * @return the used font. + */ + public Font getFont() { + return _font; + } + + private WordItem decodeWord(CharacterInfo base, String str, Color[] cols) { + Vector v = new Vector(); + CharacterInfo current = new CharacterInfo(base); + CharacterGroupItem currentItem = new CharacterGroupItem(new CharacterInfo(current)); + int size = str.length(); + for (int pos = 0; pos < size; pos++) { + char c = str.charAt(pos); + if (c < ' ') { + int code = c; + if (code == 15) { + current.isBold = false; + current.isUnderline = false; + current.isReverse = false; + current.frontColor = cols[1]; + current.backColor = cols[0]; + current.isTransparent = true; + } else if (code == 2) { + current.isBold = !current.isBold; + } else if (code == 31) { + current.isUnderline = !current.isUnderline; + } else if (code == 22) { + current.isReverse = !current.isReverse; + if (current.isReverse) { + current.frontColor = cols[0]; + current.backColor = cols[1]; + current.isTransparent = false; + } else { + current.frontColor = cols[1]; + current.backColor = cols[0]; + current.isTransparent = true; + } + } else if (code == 3) { + boolean front = true; + String frontC = ""; + String backC = ""; + pos++; + while (pos < size) { + char d = str.charAt(pos); + if ((d >= '0') && (d <= '9')) { + if (front) { + if (frontC.length() == 2) { + pos--; + break; + } + frontC += d; + } else { + if (backC.length() == 2) { + pos--; + break; + } + backC += d; + } + pos++; + } else if (d == ',') { + if (front) { + front = false; + pos++; + } else { + pos--; + break; + } + } else { + pos--; + break; + } + } + if (frontC.length() == 0) + backC = ""; + if (frontC.length() > 0) { + int col = Integer.parseInt(frontC); + col %= _cols.length; + current.frontColor = cols[col]; + } + if (backC.length() > 0) { + int col = Integer.parseInt(backC); + col %= _cols.length; + current.backColor = cols[col]; + current.isTransparent = (col == 0); + } + if ((frontC.length() == 0) && (backC.length() == 0)) { + current.frontColor = cols[1]; + current.backColor = cols[0]; + current.isTransparent = true; + } + } + if (!current.equals(currentItem.info)) { + v.insertElementAt(currentItem, v.size()); + currentItem = new CharacterGroupItem(new CharacterInfo(current)); + } + } else { + currentItem.s += c; + } + } + v.insertElementAt(currentItem, v.size()); + + CharacterGroupItem[] ans = new CharacterGroupItem[v.size()]; + for (int i = 0; i < v.size(); i++) { + ans[i] = (CharacterGroupItem) v.elementAt(i); + } + + return new WordItem(ans, current); + } + + private FontMetrics getFontMetrics(Graphics g, CharacterInfo nfo) { + Font old = g.getFont(); + if (nfo.isBold) + g.setFont(_fontBold); + else + g.setFont(_fontPlain); + FontMetrics res = g.getFontMetrics(); + g.setFont(old); + return res; + } + + private int drawPart(Graphics g, CharacterInfo nfo, String str, int x, int y, FontMetrics plainMetrics, int clipxl, + int clipxr, ImageObserver obs, Vector handles) { + FontMetrics fm = plainMetrics; + // int up=plainMetrics.getAscent(); + int down = plainMetrics.getDescent(); + + if (nfo.isBold) + g.setFont(_fontBold); + + fm = g.getFontMetrics(); + + int width = _drawer.getWidth(str, fm, this); + if ((x <= clipxr) && (x + width > clipxl)) { + int height = _drawer.getHeight(str, fm, this); + Rectangle originalClip = g.getClipBounds(); + int cx = clipxl; + int cy = y - height; + int cw = clipxr - clipxl + 1; + int ch = height; + + g.clipRect(cx, cy, cw, ch); + + g.setColor(nfo.backColor); + + if (!nfo.isTransparent) + g.fillRect(x, y - height, width, height); + + y -= down; + + g.setColor(nfo.frontColor); + _drawer.draw(str, g, fm, x, y, obs, handles); + + if (nfo.isUnderline) + g.drawLine(x, y + 1, x + width - 1, y + 1); + if (originalClip != null) + g.setClip(originalClip.x, originalClip.y, originalClip.width, originalClip.height); + else + g.setClip(null); + } + + if (nfo.isBold) + g.setFont(_fontPlain); + return width; + } + + private void drawWord(Graphics g, WordItem word, int x, int y, boolean last, FontMetrics plainMetrics, int clipxl, + int clipxr, ImageObserver obs, Vector handles) { + for (int pos = 0; pos < word.items.length; pos++) { + CharacterGroupItem item = word.items[pos]; + x += drawPart(g, item.info, item.s, x, y, plainMetrics, clipxl, clipxr, obs, handles); + } + } + + /** + * Strip a line from all its color and special codes. + * + * @param str + * string to strip. + * @return stripped line. + */ + public String getStripped(String str) { + CharacterInfo info = new CharacterInfo(); + info.frontColor = _cols[1]; + info.backColor = _cols[0]; + info.isTransparent = true; + String res = ""; + while (str.length() > 0) { + int pos = str.indexOf(' '); + WordItem word; + if (pos == -1) { + word = decodeWord(info, str, _cols); + str = ""; + } else { + String wrd = str.substring(0, pos); + word = decodeWord(info, wrd + " ", _cols); + str = str.substring(pos + 1); + } + if (res.length() > 0) + res += " " + word.originalword; + else + res += word.originalword; + } + return res; + } + + private boolean isAlphaNum(char c) { + if ((c == '(') || (c == ')')) + return false; + if ((c == '<') || (c == '>')) + return false; + if ((c == '"') || (c == '"')) + return false; + if ((c == '{') || (c == '}')) + return false; + if ((c == '.') || (c == ',')) + return false; + if (c == ':') + return false; + // if(c=='-') return false; + return true; + } + + private String trimAlphaNum(String s) { + int index = 0; + while ((index < s.length()) && !isAlphaNum(s.charAt(index))) + index++; + if (index == s.length()) + return ""; + s = s.substring(index); + index = s.length() - 1; + while ((index >= 0) && !isAlphaNum(s.charAt(index))) + index--; + if (index == -1) + return ""; + s = s.substring(0, index + 1); + return s; + } + + private void getWordItemWidthHeight(Graphics g, WordItem item, Dimension res) { + int resx = 0; + int resy = 0; + for (int i = 0; i < item.items.length; i++) { + FontMetrics fm = getFontMetrics(g, item.items[i].info); + _drawer.getWidthHeight(item.items[i].s, fm, res, this); + resx += res.width; + int h = res.height; + if (h > resy) + resy = h; + } + res.width = resx; + res.height = resy; + } + + private void expandLines() { + LineItem[] n = new LineItem[_lines.length * 2]; + System.arraycopy(_lines, 0, n, 0, _lines.length); + for (int i = _lines.length; i < n.length; i++) + n[i] = new LineItem(); + _lines = n; + } + + /** + * Get the height of the given decoded line. + * + * @param str + * decoded line. + * @param g + * graphics where the string will be displayed. + * @param x + * display position. + * @param wmax + * maximum width. + * @param wrap + * true if wrapping must occur. + * @return actual height. + */ + public int getHeight(DecodedLine str, Graphics g, int x, int wmax, boolean wrap) { + WordItem[] words = ((DecodedLineInternal) str).words; + + Font currFont = _fontPlain; + g.setFont(currFont); + FontMetrics plainFm = g.getFontMetrics(); + + int currentLineLength = 0; + int w = 0; + int h = 0; + + int mh = 0; + for (int i = 0; i < words.length; i++) { + WordItem word = words[i]; + getWordItemWidthHeight(g, word, _tmp); + int wordWidth = _tmp.width; + if ((w + wordWidth > wmax) && (currentLineLength > 0) && wrap) { + w = _drawer.getWidth(" ", plainFm, this); + currentLineLength = 0; + h += mh; + mh = 0; + } + if (_tmp.height > mh) + mh = _tmp.height; + currentLineLength++; + w += wordWidth; + } + if (currentLineLength > 0) + h += mh; + return h; + } + + /** + * Draw the given prepared line. + * + * @param str + * the prepared line to draw. + * @param g + * the graphics where to draw. + * @param left + * left margin. + * @param right + * right margin. + * @param y + * y position. + * @param clipxl + * left clip position : drawing doesn't have to be complete left to + * this position. + * @param clipxr + * right clip position : drawing doens't have to be complete right to + * this position. + * @param analyse + * true if word per word analyse must be performed, false otherwise. + * If not analyse is requested, the DrawResultItem array in res will + * be zero-sized. + * @param wrap + * true is wrapping must be done, false otherwise. + * @param res + * analyse report destination for the drawed line. + */ + public void draw(DecodedLine str, Graphics g, int left, int right, int y, int clipxl, int clipxr, boolean analyse, + boolean wrap, DrawResult res) { + WordItem[] words = ((DecodedLineInternal) str).words; + if (res.updateHandles == null) { + res.updateHandles = new Vector(); + } else { + if (res.updateHandles.size() > 0) + res.updateHandles.removeAllElements(); + } + + // split lines + Font currFont = _fontPlain; + g.setFont(currFont); + FontMetrics plainFm = g.getFontMetrics(); + + int lineCount = 0; + int firstWordInLine = 0; + int currentLineLength = 0; + int wmax = right - left + 1; + if (wrap) { + int w = 0; + for (int i = 0; i < words.length; i++) { + WordItem word = words[i]; + getWordItemWidthHeight(g, word, _tmp); + int wordWidth = _tmp.width; + if ((w + wordWidth > wmax) && (currentLineLength > 0)) { + w = _drawer.getWidth(" ", plainFm, this); + LineItem newLine = _lines[lineCount++]; + if (lineCount == _lines.length) + expandLines(); + newLine.first = firstWordInLine; + newLine.count = currentLineLength; + firstWordInLine = i; + currentLineLength = 0; + } + + currentLineLength++; + w += wordWidth; + } + if (currentLineLength != 0) { + LineItem newLine = _lines[lineCount++]; + if (lineCount == _lines.length) + expandLines(); + newLine.first = firstWordInLine; + newLine.count = currentLineLength; + } + } else { + LineItem newLine = _lines[lineCount++]; + newLine.first = 0; + newLine.count = words.length; + } + + // display + int s = 0; + if (analyse) + s = words.length; + if ((res.items == null) || (res.items.length != s)) + res.items = new DrawResultItem[s]; + + DrawResultItem[] dres = res.items; + int minX = right; + int maxX = left; + int h = 0; + int py = 0; + int marginWidth = _drawer.getWidth(" ", plainFm, this); + + int hdir = 1; + if (_hdirection == RIGHT) + hdir = -1; + + if (_vdirection == BOTTOM) { + for (int i = lineCount - 1; i >= 0; i--) { + int px = left; + if (hdir == -1) + px = right; + int maxHeight = 0; + if (i != 0) + px += hdir * marginWidth; + LineItem line = _lines[i]; + for (int j = line.first; j < line.first + line.count; j++) { + + getWordItemWidthHeight(g, words[j], _tmp); + + int wordWidth = _tmp.width; + int wordHeight = _tmp.height; + + if (hdir == -1) + px -= wordWidth; + + int trimmedWidth = wordWidth; + if (maxHeight < wordHeight) + maxHeight = wordHeight; + if ((px + wordWidth > clipxl) && (px <= clipxr)) + drawWord(g, words[j], px, y, j == line.first + line.count - 1, plainFm, clipxl, clipxr, this, + res.updateHandles); + + if (analyse) { + // String wrd=words[j].decodedword; + String owrd = words[j].originalword; + String swrd = words[j].originalstrippedword; + String twrd = trimAlphaNum(swrd.trim()); + if (dres[j] == null) + dres[j] = new DrawResultItem(); + DrawResultItem ritem = dres[j]; + ritem.parent = res; + ritem.item = twrd; + ritem.originalword = owrd; + ritem.originalstrippedword = swrd; + ritem.rectangle = new StyledRectangle(px, py - wordHeight, trimmedWidth, wordHeight); + } + if (hdir == 1) + px += wordWidth; + if (px > maxX) + maxX = px; + if (px < minX) + minX = px; + } + y -= maxHeight; + py -= maxHeight; + h += maxHeight; + } + + if (analyse) + for (int i = 0; i < dres.length; i++) + dres[i].rectangle.y += h; + } else if (_vdirection == TOP) { + for (int i = 0; i < lineCount; i++) { + int px = left; + if (hdir == -1) + px = right; + int maxHeight = 0; + if (i != 0) + px += hdir * marginWidth; + LineItem line = _lines[i]; + for (int j = line.first; j < line.first + line.count; j++) { + getWordItemWidthHeight(g, words[j], _tmp); + + int wordWidth = _tmp.width; + int wordHeight = _tmp.height; + if (hdir == -1) + px -= wordWidth; + + int trimmedWidth = wordWidth; + if (maxHeight < wordHeight) + maxHeight = wordHeight; + + if ((px + wordWidth > clipxl) && (px <= clipxr)) + drawWord(g, words[j], px, y + wordHeight, j == line.first + line.count - 1, plainFm, clipxl, clipxr, this, + res.updateHandles); + + if (analyse) { + String wrd = words[j].decodedword; + String owrd = words[j].originalword; + String swrd = words[j].originalstrippedword; + String twrd = trimAlphaNum(wrd.trim()); + if (dres[j] == null) + dres[j] = new DrawResultItem(); + DrawResultItem ritem = dres[j]; + ritem.parent = res; + ritem.item = twrd; + ritem.originalword = owrd; + ritem.originalstrippedword = swrd; + ritem.rectangle = new StyledRectangle(px, py, trimmedWidth, wordHeight); + } + if (hdir == 1) + px += wordWidth; + if (px > maxX) + maxX = px; + if (px < minX) + minX = px; + } + y += maxHeight; + py += maxHeight; + h += maxHeight; + } + y -= h; + } + + int x1 = left; + int x2 = maxX; + if (hdir == -1) { + x1 = minX; + x2 = right; + } + + if (analyse) + for (int i = 0; i < res.items.length; i++) + res.items[i].rectangle.x -= x1; + + if (res.rectangle == null) { + res.rectangle = new StyledRectangle(x1, y, x2 - x1 + 1, h); + } else { + res.rectangle.x = x1; + res.rectangle.y = y; + res.rectangle.width = x2 - x1 + 1; + res.rectangle.height = h; + } + } + + @Override + public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) { + if ((infoflags & ImageObserver.ERROR) != 0) + return false; + if ((infoflags & ImageObserver.ABORT) != 0) + return false; + + // We don't care about properties, just go ahead... + if ((infoflags & ImageObserver.PROPERTIES) != 0) + return true; + + if (_listener != null) { + Boolean b; + int what = 0; + if ((infoflags & ImageObserver.WIDTH) != 0) + what |= FormattedStringDrawerListener.SIZE; + if ((infoflags & ImageObserver.HEIGHT) != 0) + what |= FormattedStringDrawerListener.SIZE; + if ((infoflags & ImageObserver.ALLBITS) != 0) + what |= FormattedStringDrawerListener.DATA; + if ((infoflags & ImageObserver.FRAMEBITS) != 0) + what |= FormattedStringDrawerListener.FRAME; + if ((infoflags & ImageObserver.SOMEBITS) != 0) + what |= FormattedStringDrawerListener.DATA; + + try { + b = (Boolean) EventDispatcher.dispatchEventAsyncAndWaitEx(_listener, "displayUpdated", new Object[] { img, + new Integer(what) }); + return b.booleanValue(); + } catch (Throwable e) { + e.printStackTrace(); + return false; + } + } + return true; + } +} diff --git a/src/main/java/irc/style/FormattedStringDrawerListener.java b/src/main/java/irc/style/FormattedStringDrawerListener.java new file mode 100644 index 0000000..45ee82f --- /dev/null +++ b/src/main/java/irc/style/FormattedStringDrawerListener.java @@ -0,0 +1,59 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.style; + +/** + * This interface is used to notify that some drawn content has been updated. + */ +public interface FormattedStringDrawerListener { + /** + * Image data is updated. + */ + public static final int DATA = 1; + /** + * Size is updated. + */ + public static final int SIZE = 2; + /** + * Frame is updated. + */ + public static final int FRAME = 4; + + /** + * The given handle has been updated. + * + * @param handle + * updated handle. + * @param what + * type of update, bitfield. + * @return true if future handle update should be notified, false otherwise. + */ + public Boolean displayUpdated(Object handle, Integer what); +} diff --git a/src/main/java/irc/style/MultipleWordCatcher.java b/src/main/java/irc/style/MultipleWordCatcher.java new file mode 100644 index 0000000..992a605 --- /dev/null +++ b/src/main/java/irc/style/MultipleWordCatcher.java @@ -0,0 +1,68 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.style; + +import java.util.Enumeration; +import java.util.Vector; + +/** + * Multiple word catcher. + */ +public class MultipleWordCatcher implements WordCatcher { + private Vector _recognizers; + + /** + * Create a new MultipleWordCatcher. + */ + public MultipleWordCatcher() { + _recognizers = new Vector(); + } + + /** + * Add a recognizer in the list. + * + * @param wr + * recognizer to add. + */ + public void addRecognizer(WordRecognizer wr) { + _recognizers.insertElementAt(wr, _recognizers.size()); + } + + @Override + public String getType(String word) { + Enumeration e = _recognizers.elements(); + while (e.hasMoreElements()) { + WordRecognizer wr = (WordRecognizer) e.nextElement(); + if (wr.recognize(word)) + return wr.getType(); + } + return null; + } +} diff --git a/src/main/java/irc/style/StyledList.java b/src/main/java/irc/style/StyledList.java new file mode 100644 index 0000000..24df8cc --- /dev/null +++ b/src/main/java/irc/style/StyledList.java @@ -0,0 +1,1300 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2005 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.style; + +import irc.IRCConfiguration; +import irc.ListenerGroup; +import irc.StyleContext; + +import java.awt.Color; +import java.awt.Cursor; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.Panel; +import java.awt.Rectangle; +import java.awt.event.InputEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Vector; + +/** + * LimitedArray, used to remove too old lines from the text history. + */ +class LimitedArray { + private int _size; + private int _maximum; + private int _missing; + private Object[] _array; + + /** + * Create a new LimitedArray + * + * @param max + * maximum number of items. + */ + public LimitedArray(int max) { + _size = 0; + _missing = 0; + _maximum = max; + _array = new Object[4]; + } + + /** + * Expand the actual number of stockable items. + */ + public void expand() { + if (_array.length >= _maximum) + return; + int ns = _array.length << 1; + Object[] n = new Object[ns]; + System.arraycopy(_array, 0, n, 0, _array.length); + _array = n; + } + + /** + * Add an object. + * + * @param obj + * object to add. + */ + public void add(Object obj) { + if (size() >= _array.length) + expand(); + if (size() >= _array.length) + _missing++; + _array[size() % _array.length] = obj; + _size++; + } + + /** + * Get the object at given index. + * + * @param index + * index. + * @return the object at index, or null if object has been removed. + */ + public Object get(int index) { + if (index < _missing) + return null; + return _array[(index) % _array.length]; + } + + /** + * Get the number of objects. + * + * @return number of objects. + */ + public int size() { + return _size; + } +} + +/** + * ResultPair. + */ +class ResultPair { + /** + * Line count. + */ + public int line; + /** + * Draw result. + */ + public DrawResult result; +} + +/** + * A styled list is a panel designed for displaying lines of styled text, using + * special color and style codes, and smileys. + */ +public class StyledList extends Panel implements MouseListener, MouseMotionListener, FormattedStringDrawerListener { + private LimitedArray _list; + private Hashtable _nickInfos; + private boolean _wrap; + private int _last; + private int _first; + private int _left; + private int _width; + private int _toScrollX; + private int _toScrollY; + private FormattedStringDrawer _drawer; + private Image _buffer; + private int _bufferWidth; + private int _bufferHeight; + private int _lastWidth; + private int _lastHeight; + private Hashtable _results; + private MultipleWordCatcher _catcher; + private WordListRecognizer _wordListRecognizer; + private IRCConfiguration _ircConfiguration; + + private int _pressedX; + private int _pressedY; + private int _draggedX; + private int _draggedY; + private boolean _dragging; + private DrawResultItem _currentItem; + private DrawResultItem _currentFloatItem; + private DrawResultItem _currentHighLightItem; + private String _currentFloatText; + private String _copiedString; + private boolean _fullDraw; + + private ListenerGroup _listeners; + + private ResultPair[] _addedResults; + private int _addedCount; + + private int _hdirection; + private int _vdirection; + private Color _colormale; + private Color _colorfemeale; + private Color _colorundef; + + private Vector _updateItems; + private long _lastRefresh = System.currentTimeMillis(); + + private Image _backImage; + private int _backTiling; + + private int _maximumSize; + private DecodedLine _emptyLine; + + private final static int BOTTOM = FormattedStringDrawer.BOTTOM; + private final static int TOP = FormattedStringDrawer.TOP; + /** Left to right direction. */ + public final static int LEFT = FormattedStringDrawer.LEFT; + /** Right to left direction. */ + public final static int RIGHT = FormattedStringDrawer.RIGHT; + + private final static boolean _doubleBuffer = true; // NON-BUFFERED DISPLAY NOT + // YET FUNCTIONAL + + /** + * Create a new StyledList with automatic text wraping. + * + * @param config + * global irc configuration. + * @param context + * style context. + */ + public StyledList(IRCConfiguration config, StyleContext context) { + this(config, true, context); + } + + /** + * Create a new StyledList. + * + * @param config + * global irc configuration. + * @param wrap + * true if wrapping must occur, false otherwise. + * @param context + * style context. + */ + public StyledList(IRCConfiguration config, boolean wrap, StyleContext context) { + this(config, wrap, context, Color.blue, Color.pink, Color.gray); + } + + /** + * Create a new StyledList. + * + * @param config + * global irc configuration. + * @param wrap + * true if wrapping must occur, false otherwise. + * @param context + * style context. + * @param male + * male color for asl. + * @param femeale + * femeale color for asl. + * @param undef + * undefined gender color for asl. + */ + public StyledList(IRCConfiguration config, boolean wrap, StyleContext context, Color male, Color femeale, Color undef) { + super(); + _backImage = null; + _backTiling = IRCConfiguration.TILING_CENTER; + _colormale = male; + _colorfemeale = femeale; + _colorundef = undef; + _nickInfos = new Hashtable(); + _fullDraw = false; + _addedResults = new ResultPair[64]; + for (int i = 0; i < _addedResults.length; i++) + _addedResults[i] = new ResultPair(); + _addedCount = 0; + _hdirection = LEFT; + _vdirection = BOTTOM; + _ircConfiguration = config; + _copiedString = ""; + _dragging = false; + _currentFloatItem = null; + _currentFloatText = null; + _currentItem = null; + _toScrollX = 0; + _toScrollY = 0; + _left = 0; + _wrap = wrap; + _buffer = null; + _drawer = new FormattedStringDrawer(_ircConfiguration, context, this); + _drawer.setHorizontalDirection(_hdirection); + _drawer.setVerticalDirection(_vdirection); + _catcher = new MultipleWordCatcher(); + _wordListRecognizer = new WordListRecognizer(); + _catcher.addRecognizer(new ChannelRecognizer()); + _catcher.addRecognizer(new URLRecognizer()); + _catcher.addRecognizer(_wordListRecognizer); + _results = new Hashtable(); + _listeners = new ListenerGroup(); + addMouseListener(this); + addMouseMotionListener(this); + _maximumSize = _ircConfiguration.getI("style:maximumlinecount"); + _emptyLine = _drawer.decodeLine(""); + clear(); + setBackgroundImage(_ircConfiguration.getStyleBackgroundImage(context)); + setBackgroundTiling(_ircConfiguration.getStyleBackgroundTiling(context)); + if (_ircConfiguration.getB("style:righttoleft")) + setHorizontalDirection(RIGHT); + } + + /** + * Release this object. No further call may be performed on this object. + */ + public void release() { + clear(); + dispose(); + removeMouseListener(this); + removeMouseMotionListener(this); + } + + private void drawBackImage(Graphics g, int w, int h) { + int iw = _backImage.getWidth(this); + int ih = _backImage.getHeight(this); + switch (_backTiling & 0xff) { + case IRCConfiguration.TILING_FIXED: { + int x = 0; + int y = 0; + if ((_backTiling & IRCConfiguration.TILING_HORIZONTAL_RIGHT) != 0) + x = w - iw - 1; + if ((_backTiling & IRCConfiguration.TILING_VERTICAL_DOWN) != 0) + y = h - ih - 1; + g.setColor(_drawer.getColor(0)); + g.fillRect(0, 0, w, h); + g.drawImage(_backImage, x, y, _drawer.getColor(0), this); + break; + } + case IRCConfiguration.TILING_CENTER: { + int x = (w - iw) / 2; + int y = (h - ih) / 2; + g.setColor(_drawer.getColor(0)); + g.fillRect(0, 0, w, h); + g.drawImage(_backImage, x, y, _drawer.getColor(0), this); + break; + } + case IRCConfiguration.TILING_STRETCH: { + g.drawImage(_backImage, 0, 0, w, h, _drawer.getColor(0), this); + break; + } + case IRCConfiguration.TILING_TILE: { + int x = 0; + while (x < w) { + int y = 0; + while (y < h) { + g.drawImage(_backImage, x, y, _drawer.getColor(0), this); + y += ih; + } + x += iw; + } + break; + } + } + } + + private void expandResult() { + ResultPair[] n = new ResultPair[_addedResults.length * 2]; + System.arraycopy(_addedResults, 0, n, 0, _addedResults.length); + for (int i = _addedResults.length; i < n.length; i++) + n[i] = new ResultPair(); + _addedResults = n; + } + + /** + * Set the horizontal display direction. + * + * @param direction + * horizontal display direction. + */ + public void setHorizontalDirection(int direction) { + _hdirection = direction; + _drawer.setHorizontalDirection(_hdirection); + } + + /** + * Get the horizontal display direction. + * + * @return horizontal display direction. + */ + public int getHorizontalDirection() { + return _hdirection; + } + + /** + * Set the background image for display. + * + * @param img + * background image, or null if no background image is to be + * displayed. + */ + public void setBackgroundImage(Image img) { + _backImage = img; + repaint(); + } + + /** + * Set the background image tiling. + * + * @param t + * background image tiling mode. See IRCConfiguration for tiling + * modes. + */ + public void setBackgroundTiling(int t) { + _backTiling = t; + repaint(); + } + + /** + * Set the font to be used for display. + * + * @param fnt + * font to be used. + */ + @Override + public void setFont(Font fnt) { + _drawer.setFont(fnt); + reinit(); + repaint(); + } + + /** + * Set the wrap mode. + * + * @param wrap + * mode, true if end-of-line wrapping must be performed, false + * otherwise. + */ + public void setWrap(boolean wrap) { + _wrap = wrap; + reinit(); + repaint(); + } + + /** + * Set the nick list for recognition. + * + * @param list + * the nick list. + */ + public synchronized void setNickList(String[] list) { + String[] actualList = new String[list.length]; + _nickInfos.clear(); + for (int i = 0; i < list.length; i++) { + String nick = list[i]; + String info = ""; + int pos = nick.indexOf(":"); + if (pos != -1) { + info = nick.substring(pos + 1); + nick = nick.substring(0, pos); + } + actualList[i] = nick; + _nickInfos.put(nick.toLowerCase(java.util.Locale.ENGLISH), info); + } + _wordListRecognizer.setList(actualList); + } + + /** + * Add a listener. + * + * @param lis + * the new listener. + */ + public synchronized void addStyledListListener(StyledListListener lis) { + _listeners.addListener(lis); + } + + /** + * Remove a listener. + * + * @param lis + * the listener to remove. + */ + public synchronized void removeStyledListListener(StyledListListener lis) { + _listeners.removeListener(lis); + } + + /** + * Set the left offset for this list rendering. + * + * @param left + * the left offset, in pixel. + */ + public synchronized void setLeft(int left) { + // int w=getSize().width; + int oldLeft = _left; + _left = left; + if (_left < 0) + _left = 0; + if (_left >= getLogicalWidth()) + _left = getLogicalWidth() - 1; + + if (_hdirection == RIGHT) + _left = -_left; + + if (_left != oldLeft) { + addToScroll(_left - oldLeft, 0); + repaint(); + } + } + + /** + * Get the left offset. + * + * @return the left offset, in pixel. + */ + public int getLeft() { + if (_hdirection == RIGHT) + return -_left; + return _left; + } + + /** + * Set the first line to be displayed. + * + * @param first + * the first line to be displayed. + */ + public synchronized void setFirst(int first) { + if (_vdirection != TOP) + _fullDraw = true; + _vdirection = TOP; + _drawer.setVerticalDirection(TOP); + int oldFirst = _first; + _first = first; + if (_first < 0) + _last = 0; + if (_first >= _list.size()) + _last = _list.size() - 1; + if (_first != oldFirst) { + addToScroll(0, _first - oldFirst); + repaint(); + } + } + + /** + * Set the last line to be displayed. + * + * @param last + * last line to be displayed. + */ + public synchronized void setLast(int last) { + if (_vdirection != BOTTOM) + _fullDraw = true; + _vdirection = BOTTOM; + _drawer.setVerticalDirection(BOTTOM); + int oldLast = _last; + _last = last; + if (_last < 0) + _last = 0; + if (_last >= _list.size()) + _last = _list.size() - 1; + if (_last != oldLast) { + addToScroll(0, _last - oldLast); + repaint(); + } + } + + /** + * Get the logical width of this list. + * + * @return the logical width, in pixel. + */ + public int getLogicalWidth() { + return _width; + } + + /** + * Get the last displayed line. + * + * @return the last displayed line. + */ + public int getLast() { + return _last; + } + + /** + * Get the number of line in this list. + * + * @return the line count. + */ + public synchronized int getLineCount() { + return _list.size(); + } + + /** + * Add a line at the end of this list. + * + * @param line + * new line to add. + */ + public synchronized void addLine(String line) { + DecodedLine dline = _drawer.decodeLine(line); + _list.add(dline); + + if (_vdirection == BOTTOM) { + if (_last == _list.size() - 2) + setLast(_last + 1); + } else if (_vdirection == TOP) { + _fullDraw = true; + repaint(); + } + } + + /** + * Add the given lines at the end of this list. + * + * @param lines + * lines to add. + */ + public synchronized void addLines(String[] lines) { + boolean willScroll = (_list.size() - 1 == _last); + + for (int i = 0; i < lines.length; i++) + _list.add(_drawer.decodeLine(lines[i])); + + if (_vdirection == BOTTOM) { + if (willScroll) + setLast(_list.size() - 1); + } else if (_vdirection == TOP) { + _fullDraw = true; + repaint(); + } + } + + private void reinit() { + if (_buffer != null) + _buffer.flush(); + _buffer = null; + _results = new Hashtable(); + } + + /** + * Dispose any off-screen ressources used by the list. This method won't put + * the list in a non-drawable state, but next screen refresh might me slower. + */ + public synchronized void dispose() { + reinit(); + } + + /** + * Clear all the lines in this list. + */ + public synchronized void clear() { + _list = new LimitedArray(_maximumSize); + _last = _list.size() - 1; + _first = 0; + setLeft(0); + _width = getSize().width; + _fullDraw = true; + repaint(); + } + + /** + * Clear all the lines in this list, reconfiguring the maximum line count to + * max. + * + * @param max + * the new maximum line count. + */ + public synchronized void clear(int max) { + _maximumSize = max; + clear(); + } + + private void drawPart(Graphics g, int x, int y, int w, int h, boolean analyse, int gw, int gh) { + // System.out.println("draw part "+x+","+y+","+w+","+h); + if (y < 0) { + h += y; + y = 0; + } + + if (_backImage != null) { + drawBackImage(g, gw, gh); + } else { + g.setColor(_drawer.getColor(0)); + g.fillRect(x, y, w, h); + } + + if (_vdirection == BOTTOM) { + int first = _last; + int posY = getSize().height; + while ((posY > y + h) && (first >= 0)) + posY -= getHeight(first--, g); + if (first != _last) + posY += getHeight(++first, g); + draw(g, 0, first, posY, y, x, x + w - 1, analyse); + } else if (_vdirection == TOP) { + int first = _first; + int posY = 0; + while ((posY < y) && (first < _list.size())) + posY += getHeight(first++, g); + if (first != _first) + posY -= getHeight(--first, g); + draw(g, first, _list.size() - 1, posY, y + h, x, x + w - 1, analyse); + } + } + + @Override + public synchronized void paint(Graphics g) { + if (_doubleBuffer || (_toScrollX != 0) || (_toScrollY != 0)) { + if ((_toScrollX != 0) || (_toScrollY != 0)) + _fullDraw = true; + update(g); + return; + } + int x = 0; + int y = 0; + int w = getSize().width; + int h = getSize().height; + Rectangle cl = g.getClipBounds(); + if (cl != null) { + x = cl.x; + y = cl.y; + w = cl.width; + h = cl.height; + } + drawPart(g, x, y, w, h, false, w, h); + } + + private int getHeight(Graphics g, int a, int b) { + if (b < a) { + int tmp = a; + a = b; + b = tmp; + } + int res = 0; + for (int i = a; i <= b; i++) + res += getHeight(i, g); + return res; + } + + private void draw(Graphics g, int from, int to, int y, int crossy, int debx, int finx, boolean analyse) { + int w = getSize().width; + // int h=getSize().height; + // int wrapPos=w; + _addedCount = 0; + + DrawResult res = new DrawResult(); + + if (_vdirection == BOTTOM) { + int index = to; + while ((index >= from) && (y > crossy)) { + DecodedLine str = (DecodedLine) _list.get(index); + if (str == null) + str = _emptyLine; + _drawer.draw(str, g, -_left, w - 1 - _left, y, debx, finx, analyse, _wrap, res); + StyledRectangle rect = res.rectangle; + if (rect.width > _width) { + _width = rect.width; + _listeners.sendEventAsync("virtualSizeChanged", this); + } + if (analyse) { + ResultPair p = _addedResults[_addedCount++]; + if (_addedCount == _addedResults.length) + expandResult(); + p.line = index; + p.result = res; + res = new DrawResult(); + } + y -= rect.height; + index--; + } + } else { + int index = from; + while ((index <= to) && (y < crossy)) { + DecodedLine str = (DecodedLine) _list.get(index); + if (str == null) + str = _emptyLine; + _drawer.draw(str, g, -_left, w - 1 - _left, y, debx, finx, analyse, _wrap, res); + StyledRectangle rect = res.rectangle; + if (rect.width > _width) { + _width = rect.width; + _listeners.sendEventAsync("virtualSizeChanged", this); + } + if (analyse) { + ResultPair p = _addedResults[_addedCount++]; + if (_addedCount == _addedResults.length) + expandResult(); + p.line = index; + p.result = res; + res = new DrawResult(); + } + y += rect.height; + index++; + } + + } + } + + private void addToScroll(int vx, int vy) { + _toScrollX += vx; + _toScrollY += vy; + } + + private int getScrollX() { + if (_dragging) + return 0; + int res = _toScrollX; + _toScrollX = 0; + return res; + } + + private int getScrollY() { + if (_dragging) + return 0; + int res = _toScrollY; + _toScrollY = 0; + return res; + } + + private void scrollDrawItems(int dx, int dy) { + int h = getSize().height; + Enumeration e = _results.keys(); + while (e.hasMoreElements()) { + Integer key = (Integer) e.nextElement(); + DrawResult res = (DrawResult) _results.get(key); + res.rectangle.x += dx; + res.rectangle.y += dy; + if ((res.rectangle.y + res.rectangle.height < 0) || (res.rectangle.y >= h)) { + _results.remove(key); + } + } + } + + private void combineItems() { + for (int i = 0; i < _addedCount; i++) { + ResultPair k = _addedResults[i]; + _results.put(new Integer(k.line), k.result); + } + _addedCount = 0; + } + + private DrawResultItem findItem(int x, int y) { + Enumeration e = _results.elements(); + while (e.hasMoreElements()) { + DrawResult result = (DrawResult) e.nextElement(); + if (result.rectangle.contains(x, y)) { + int rx = x - result.rectangle.x; + int ry = y - result.rectangle.y; + for (int i = 0; i < result.items.length; i++) { + DrawResultItem item = result.items[i]; + if (item.rectangle.contains(rx, ry)) + return item; + } + } + } + return null; + } + + private int findLine(int y) { + Enumeration e = _results.keys(); + while (e.hasMoreElements()) { + Integer i = (Integer) e.nextElement(); + + DrawResult result = (DrawResult) _results.get(i); + if ((result.rectangle.y <= y) && (result.rectangle.y + result.rectangle.height > y)) { + return i.intValue(); + } + } + return -1; + } + + private int getHeight(int lineIndex, Graphics g) { + DrawResult r = (DrawResult) _results.get(new Integer(lineIndex)); + if (r != null) + return r.rectangle.height; + + int wrapPos = getSize().width; + DecodedLine str = (DecodedLine) _list.get(lineIndex); + if (str == null) + str = _emptyLine; + return _drawer.getHeight(str, g, -_left, wrapPos, _wrap); + } + + private Color findColor(String info) { + return _ircConfiguration.getASLColor(info, _colormale, _colorfemeale, _colorundef); + } + + private synchronized Vector getUpdateItems() { + Vector items = _updateItems; + _updateItems = null; + return items; + } + + private synchronized boolean addToUpdateItems(Integer line) { + if (_updateItems == null) + _updateItems = new Vector(); + for (int i = 0; i < _updateItems.size(); i++) { + Integer r = (Integer) _updateItems.elementAt(i); + if (r.equals(line)) + return false; + } + _updateItems.insertElementAt(line, _updateItems.size()); + return true; + } + + @Override + public synchronized void update(Graphics g) { + int w = getSize().width; + int h = getSize().height; + if (h <= 0 || w <= 0) + return; + + Graphics gra = g; + if (_doubleBuffer) { + if (_buffer != null) { + if ((_bufferWidth < w) || (_bufferHeight < h)) { + reinit(); + } + // Optimize memory usage + if ((_bufferHeight > w * 1.5) || (_bufferHeight > h * 1.5)) { + reinit(); + } + if ((_lastWidth != w) || (_lastHeight != h)) { + _fullDraw = true; + } + } + + _lastWidth = w; + _lastHeight = h; + + if (_buffer == null) { + _buffer = createImage(w, h); + if (_buffer == null) { + repaint(); + return; + } + _bufferWidth = w; + _bufferHeight = h; + _fullDraw = true; + } + + gra = _buffer.getGraphics(); + } + + if (_ircConfiguration.getB("style:backgroundimage")) + _fullDraw = true; + + int scrx = getScrollX(); + int scry = getScrollY(); + Vector items = getUpdateItems(); + + if (!_fullDraw) { + + if (scrx < 0) { + gra.copyArea(0, 0, w + scrx, h, -scrx, 0); + scrollDrawItems(-scrx, 0); + drawPart(gra, 0, 0, -scrx, h, false, w, h); + } else if (scrx > 0) { + gra.copyArea(scrx, 0, w - scrx, h, -scrx, 0); + scrollDrawItems(-scrx, 0); + drawPart(gra, w - scrx, 0, scrx, h, false, w, h); + } + + if (scry > 0) { + int baseY; + if (_vdirection == BOTTOM) + baseY = getHeight(gra, _last - scry + 1, _last); + else + baseY = getHeight(gra, _first - scry, _first - 1); + + gra.copyArea(0, baseY, w, h - baseY, 0, -baseY); + scrollDrawItems(0, -baseY); + drawPart(gra, 0, h - baseY, w, baseY, true, w, h); + combineItems(); + } else if (scry < 0) { + int baseY; + if (_vdirection == BOTTOM) + baseY = getHeight(gra, _last + 1, _last - scry); + else + baseY = getHeight(gra, _first, _first - scry - 1); + + gra.copyArea(0, 0, w, h - baseY, 0, baseY); + scrollDrawItems(0, baseY); + drawPart(gra, 0, 0, w, baseY, true, w, h); + combineItems(); + } + + if (items != null) { + for (int i = 0; i < items.size(); i++) { + Integer line = (Integer) items.elementAt(i); + DrawResult res = (DrawResult) _results.get(line); + if (res != null) { + StyledRectangle r = res.rectangle; + drawPart(gra, r.x, r.y, r.width, r.height, false, w, h); + } + } + } + + } else { + _results = new Hashtable(); + drawPart(gra, 0, 0, w, h, true, w, h); + combineItems(); + _fullDraw = false; + } + + if (_dragging) + makeXor(gra); + if (_doubleBuffer) + g.drawImage(_buffer, 0, 0, this); + if (_dragging) + makeXor(gra); + + if (!_dragging && (_currentFloatItem != null) && _ircConfiguration.getB("style:floatingasl")) { + int x = _currentFloatItem.rectangle.x + _currentFloatItem.parent.rectangle.x + 4; + int y = _currentFloatItem.rectangle.y + _currentFloatItem.parent.rectangle.y; + if (_vdirection == TOP) + y += 8; + else + y -= 8; + + if (y < 0) + y = 0; + + String info = _currentFloatText; + String text = _ircConfiguration.formatASL(info); + if (text.length() > 0) { + int tw = g.getFontMetrics().stringWidth(text); + int fh = g.getFont().getSize(); + + if (y + fh + 5 > h) + y = h - fh - 5; + if (x + tw + 5 > w) + x = w - tw - 5; + g.setColor(getAlphaColor(findColor(info), _ircConfiguration.getI("style:floatingaslalpha"))); + g.fillRect(x, y, tw + 4, fh + 4); + g.setColor(Color.white); + g.drawString(text, x + 2, y + fh); + } + } + + if (_ircConfiguration.getB("style:highlightlinks")) { + if (!_dragging && (_currentHighLightItem != null)) { + int x = _currentHighLightItem.rectangle.x + _currentHighLightItem.parent.rectangle.x; + int y = _currentHighLightItem.rectangle.y + _currentHighLightItem.parent.rectangle.y; + g.setXORMode(Color.white); + g.setColor(Color.black); + g.fillRect(x, y, _currentHighLightItem.rectangle.width, _currentHighLightItem.rectangle.height); + g.setPaintMode(); + } + } + } + + private Color getAlphaColor(Color c, int alpha) { + try { + return new Color(c.getRed(), c.getGreen(), c.getBlue(), alpha); + } catch (Throwable ex) { + return c; + } + } + + private void makeXor(Graphics g) { + String res = ""; + int dw = _draggedX - _pressedX; + int dh = _draggedY - _pressedY; + + int pressedX = _pressedX; + int pressedY = _pressedY; + + g.setXORMode(Color.white); + g.setColor(Color.black); + int i = findLine(pressedY); + int basei = i; + DrawResult result = (DrawResult) _results.get(new Integer(i)); + + if (result == null) { + _copiedString = ""; + return; + } + + int px, py; + + px = pressedX - result.rectangle.x; + py = pressedY - result.rectangle.y; + + DrawResultItem item = null; + int a, b = 0; + for (a = 0; a < result.items.length; a++) { + if (result.items[a].rectangle.contains(px, py)) { + item = result.items[a]; + b = a; + } + } + + if ((item == null) || ((px + dw < item.rectangle.x) && (py + dh < item.rectangle.y)) + || (py + dh < item.rectangle.y)) { + _copiedString = ""; + return; + } + boolean terminated = false; + while (!terminated) { + res += item.originalstrippedword; + StyledRectangle r = item.rectangle; + g.fillRect(r.x + result.rectangle.x, r.y + result.rectangle.y, r.width, r.height); + + if (!((i == basei) && (a == b)) && (item.rectangle.contains(px + dw, py + dh))) + break; + b++; + if (b >= result.items.length) { + b = 0; + i++; + result = (DrawResult) _results.get(new Integer(i)); + if (result == null) + break; + px = pressedX - result.rectangle.x; + py = pressedY - result.rectangle.y; + res += "\n"; + } + item = result.items[b]; + if (item.rectangle.y > py + dh) + terminated = true; + if (_hdirection == LEFT) + if ((item.rectangle.x > px + dw) && (item.rectangle.y + item.rectangle.height > py + dh)) + terminated = true; + if (_hdirection == RIGHT) + if ((item.rectangle.x + item.rectangle.width < px + dw) && (item.rectangle.y + item.rectangle.height > py + dh)) + terminated = true; + } + + _copiedString = res; + g.setPaintMode(); + } + + @Override + public synchronized void mouseClicked(MouseEvent e) { + if ((e.getModifiers() & InputEvent.SHIFT_MASK) != 0) { + String res = ""; + for (int i = 0; i < _list.size(); i++) { + DecodedLine str = (DecodedLine) _list.get(i); + if (str == null) + str = _emptyLine; + res += str.original + "\n"; + } + _listeners.sendEventAsync("copyEvent", this, res, e); + } + } + + @Override + public void mouseEntered(MouseEvent e) { + _currentFloatItem = null; + _currentItem = null; + _currentHighLightItem = null; + defCursor(); + mouseMoved(e); + } + + @Override + public void mouseExited(MouseEvent e) { + _currentFloatItem = null; + _currentItem = null; + _currentHighLightItem = null; + repaint(); + } + + @Override + public synchronized void mousePressed(MouseEvent e) { + _pressedX = e.getX(); + _pressedY = e.getY(); + _draggedX = _pressedX; + _draggedY = _pressedY; + _copiedString = ""; + _dragging = false; + _currentItem = null; + DrawResultItem item = findItem(e.getX(), e.getY()); + if (item != null) { + String type = _catcher.getType(item.item); + if (type == null) { + // ignore... + } else if (type.equals("channel")) { + _listeners.sendEventAsync("channelEvent", this, item.item, e); + } else if (type.equals("url")) { + _listeners.sendEventAsync("URLEvent", this, item.item, e); + } else if (type.equals("wordlist")) { + _listeners.sendEventAsync("nickEvent", this, item.item, e); + } + } + } + + @Override + public synchronized void mouseReleased(MouseEvent e) { + if (_dragging) { + _dragging = false; + repaint(); + if (_copiedString.length() > 0) + _listeners.sendEventAsync("copyEvent", this, _copiedString, e); + } + } + + @Override + public synchronized void mouseDragged(MouseEvent e) { + _draggedX = e.getX(); + _draggedY = e.getY(); + _dragging = true; + DrawResultItem item = findItem(e.getX(), e.getY()); + if (item != _currentItem) { + _currentItem = item; + repaint(); + } + } + + private void handCursor() { + if (!getCursor().equals(new Cursor(Cursor.HAND_CURSOR))) + setCursor(new Cursor(Cursor.HAND_CURSOR)); + } + + private void defCursor() { + if (!getCursor().equals(new Cursor(Cursor.DEFAULT_CURSOR))) + setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + } + + private boolean sameItem(DrawResultItem a, DrawResultItem b) { + if ((a == null) && (b == null)) + return true; + if (a == null) + return false; + if (b == null) + return false; + return a.equals(b); + } + + @Override + public synchronized void mouseMoved(MouseEvent e) { + DrawResultItem item = findItem(e.getX(), e.getY()); + DrawResultItem oldFloat = _currentFloatItem; + DrawResultItem oldHigh = _currentHighLightItem; + if (!sameItem(item, _currentItem)) { + _currentItem = item; + _currentFloatItem = null; + _currentHighLightItem = null; + if (item != null) { + String type = _catcher.getType(item.item); + if (type != null) { + handCursor(); + if (type.equals("wordlist")) { + String info = (String) _nickInfos.get(item.item.toLowerCase(java.util.Locale.ENGLISH)); + if (info == null) + info = ""; + if (info.length() == 0) { + _currentFloatItem = null; + } else { + _currentFloatItem = item; + _currentFloatText = info; + } + } + + if (_currentFloatItem == null) + _currentHighLightItem = item; + } else + defCursor(); + } else + defCursor(); + } + + boolean repaint = false; + if (!sameItem(oldFloat, _currentFloatItem)) + if (_ircConfiguration.getB("style:floatingasl")) + repaint = true; + if (!sameItem(oldHigh, _currentHighLightItem)) + repaint = true; + if (repaint) + repaint(); + } + + @Override + public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) { + // the background image has been updated + _fullDraw = true; + repaint(); + return true; + } + + @Override + public synchronized Boolean displayUpdated(Object handle, Integer what) { + boolean foundSome = false; + + // now we should go through all our draw results, and find which of them + // belong to this handle. + Enumeration e = _results.keys(); + while (e.hasMoreElements()) { + Integer line = (Integer) e.nextElement(); + DrawResult result = (DrawResult) _results.get(line); + if (result.updateHandles != null) { + for (int i = 0; i < result.updateHandles.size(); i++) { + if (result.updateHandles.elementAt(i).equals(handle)) { + if ((what.intValue() & FormattedStringDrawerListener.SIZE) != 0) { + _fullDraw = true; + repaint(); + return Boolean.TRUE; + } + + // ok, so the line number 'line' must be redrawn + foundSome = true; + + // invalidate line line + addToUpdateItems(line); + if ((System.currentTimeMillis() - _lastRefresh > 10) + || ((what.intValue() & FormattedStringDrawerListener.DATA) != 0)) { + repaint(); + _lastRefresh = System.currentTimeMillis(); + } + } + } + } + } + + if (foundSome) + return Boolean.TRUE; + return Boolean.FALSE; + } +} diff --git a/src/main/java/irc/style/StyledListListener.java b/src/main/java/irc/style/StyledListListener.java new file mode 100644 index 0000000..85035d1 --- /dev/null +++ b/src/main/java/irc/style/StyledListListener.java @@ -0,0 +1,93 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.style; + +import java.awt.event.MouseEvent; + +/** + * StyledListListener. + */ +public interface StyledListListener { + /** + * A mouse event has occured on a channel. + * + * @param list + * the source list. + * @param channel + * the channel name. + * @param e + * the mouse event associated with this event. + */ + public void channelEvent(StyledList list, String channel, MouseEvent e); + + /** + * An url event has occured on a channel. + * + * @param list + * the source list. + * @param url + * the url name. + * @param e + * the mouse event associated with this event. + */ + public void URLEvent(StyledList list, String url, MouseEvent e); + + /** + * A nick event has occured on a channel. + * + * @param list + * the source list. + * @param nick + * the nick name. + * @param e + * the mouse event associated with this event. + */ + public void nickEvent(StyledList list, String nick, MouseEvent e); + + /** + * A copy event has occured on a channel. + * + * @param list + * the source list. + * @param text + * the copied text. + * @param e + * the mouse event associated with this event. + */ + public void copyEvent(StyledList list, String text, MouseEvent e); + + /** + * The logical width or height of the list has changed. + * + * @param list + * the source list. + */ + public void virtualSizeChanged(StyledList list); +} diff --git a/src/main/java/irc/style/StyledRectangle.java b/src/main/java/irc/style/StyledRectangle.java new file mode 100644 index 0000000..a7fcf41 --- /dev/null +++ b/src/main/java/irc/style/StyledRectangle.java @@ -0,0 +1,150 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.style; + +/** + * A rectangle. + */ +public class StyledRectangle { + /** + * X position. + */ + public int x; + + /** + * Y position. + */ + public int y; + + /** + * Width. + */ + public int width; + + /** + * Height. + */ + public int height; + + /** + * Create a new StyledRectangle. + * + * @param ax + * x position. + * @param ay + * y position. + * @param w + * width. + * @param h + * height. + */ + public StyledRectangle(int ax, int ay, int w, int h) { + x = ax; + y = ay; + width = w; + height = h; + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof StyledRectangle)) + return false; + StyledRectangle r = (StyledRectangle) o; + return (r.x == x) && (r.y == y) && (r.width == width) && (r.height == height); + } + + @Override + public int hashCode() { + return x + y + width + height; + } + + /** + * Test wether the given point is inside the rectangle or not. + * + * @param px + * x coordinate of point to test. + * @param py + * y coordinate of point to test. + * @return true if the point is inside the rectangle, false otherwise. + */ + public boolean contains(int px, int py) { + return (px >= x) && (py >= y) && (px < x + width) && (py < y + height); + } + + private boolean noEmpty(int v1, int lv1, int v2, int lv2) { + if (v1 < v2) + return v1 + lv1 > v2; + return v2 + lv2 > v1; + } + + /** + * Test wether the given rectangle is partially or fully inside the rectangle + * or not. + * + * @param r + * rectangle to test. + * @return true if r is partially or fully inside the rectangle, false + * otherwise. + */ + public boolean hit(StyledRectangle r) { + if (!noEmpty(r.x, r.width, x, width)) + return false; + return noEmpty(r.y, r.height, y, height); + } + + /** + * Add the given rectangle to this rectangle. This rectangle will be the union + * of the two rectangles. + * + * @param r + * the rectangle to add. + */ + public void add(StyledRectangle r) { + if (r.x < x) { + width += (x - r.x); + x = r.x; + } + + if (r.y < y) { + height += (y - r.y); + y = r.y; + } + + if (r.width > width) + width = r.width; + if (r.height > height) + height = r.height; + } + + @Override + public String toString() { + return "StyledRectangle : " + x + "," + y + "," + width + "," + height; + } +} diff --git a/src/main/java/irc/style/URLRecognizer.java b/src/main/java/irc/style/URLRecognizer.java new file mode 100644 index 0000000..c1b8778 --- /dev/null +++ b/src/main/java/irc/style/URLRecognizer.java @@ -0,0 +1,73 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.style; + +/** + * The URLRecognizer. + */ +public class URLRecognizer implements WordRecognizer { + private boolean isAlpha(String s) { + s = s.toLowerCase(java.util.Locale.ENGLISH); + for (int i = 0; i < s.length(); i++) + if ((s.charAt(i) < 'a') || (s.charAt(i) > 'z')) + return false; + return true; + } + + @Override + public boolean recognize(String word) { + if (word.startsWith("http://")) + return true; + if (word.startsWith("ftp://")) + return true; + if (word.startsWith("www.")) + return true; + if (word.startsWith("ftp.")) + return true; + int a = word.indexOf('.'); + if (a == -1) + return false; + int b = word.lastIndexOf('.'); + if (a == b) + return false; + String ext = word.substring(b + 1); + if (!isAlpha(ext)) + return false; + if ((ext.length() == 2) || (ext.length() == 3)) + return true; + return false; + } + + @Override + public String getType() { + return "url"; + } + +} diff --git a/src/main/java/irc/style/WordCatcher.java b/src/main/java/irc/style/WordCatcher.java new file mode 100644 index 0000000..f560677 --- /dev/null +++ b/src/main/java/irc/style/WordCatcher.java @@ -0,0 +1,44 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.style; + +/** + * A word catcher. + */ +public interface WordCatcher { + /** + * Get the type of this word, or null if not found. + * + * @param word + * word to analyse. + * @return word type, or null if not found. + */ + public String getType(String word); +} diff --git a/src/main/java/irc/style/WordListRecognizer.java b/src/main/java/irc/style/WordListRecognizer.java new file mode 100644 index 0000000..5049540 --- /dev/null +++ b/src/main/java/irc/style/WordListRecognizer.java @@ -0,0 +1,71 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.style; + +/** + * Recognizer for list of words. + */ +public class WordListRecognizer implements WordRecognizer { + private String[] _list; + + /** + * Create a new WordListRecognizer. + */ + public WordListRecognizer() { + setList(new String[0]); + } + + /** + * Set the list of words to recognize. + * + * @param list + * the list of words. + */ + public void setList(String[] list) { + _list = new String[list.length]; + for (int i = 0; i < list.length; i++) + _list[i] = list[i].toLowerCase(java.util.Locale.ENGLISH); + } + + @Override + public boolean recognize(String word) { + String lcase = word.toLowerCase(java.util.Locale.ENGLISH); + for (int i = 0; i < _list.length; i++) + if (lcase.equals(_list[i])) + return true; + return false; + } + + @Override + public String getType() { + return "wordlist"; + } + +} diff --git a/src/main/java/irc/style/WordRecognizer.java b/src/main/java/irc/style/WordRecognizer.java new file mode 100644 index 0000000..206ee95 --- /dev/null +++ b/src/main/java/irc/style/WordRecognizer.java @@ -0,0 +1,51 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.style; + +/** + * The word recognizer. + */ +public interface WordRecognizer { + /** + * Try to recognize a word. + * + * @param word + * word to analyse. + * @return true if this word matches. + */ + public boolean recognize(String word); + + /** + * Get this recognizer type. + * + * @return recognizer type name. + */ + public String getType(); +} diff --git a/src/main/java/irc/tree/Comparator.java b/src/main/java/irc/tree/Comparator.java new file mode 100644 index 0000000..5fe4378 --- /dev/null +++ b/src/main/java/irc/tree/Comparator.java @@ -0,0 +1,47 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.tree; + +/** + * The comparator interface. + */ +public interface Comparator { + /** + * Compare two objects. + * + * @param a + * first object. + * @param b + * second object. + * @return negative if a lesser than b, positive if a greater than b, and zero + * if a equals b. + */ + public int compare(Object a, Object b); +} diff --git a/src/main/java/irc/tree/SortedList.java b/src/main/java/irc/tree/SortedList.java new file mode 100644 index 0000000..919e274 --- /dev/null +++ b/src/main/java/irc/tree/SortedList.java @@ -0,0 +1,387 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.tree; + +import java.util.Enumeration; +import java.util.Vector; + +//class GroupItem +//{ +// //private Hashtable t; +// //Object[] t; +// Object s; +// +// public GroupItem(Object o) +// { +// //t=new Hashtable(); +// //t=new Object +// //t=null; +// s=null; +// add(o); +// } +// +// public void add(Object o) +// { +// if(s==null) s=o; +// else +// { +// /*if(t==null) +// { +// t=new Object[] {o}; +// } +// else +// { +// }*/ +// throw new RuntimeException("Didn't expect similar keys!!"); +// } +// //t.put(o,o); +// } +// +// public void remove(Object o) +// { +// //t.remove(o); +// s=null; +// } +// +// public int size() +// { +// //return t.size(); +// if(s==null) return 0; +// //if(t==null) return 1; +// return 1; +// //return t.length+1; +// } +// +// public Object getFirstItem() +// { +// //return t.elements().nextElement(); +// return s; +// } +// +// //public Enumeration elements() +// //{ +// //return t.elements(); +// //} +//} + +/** + * TreeNode. + */ +class TreeNode { + /** + * Left node. + */ + public TreeNode left; + /** + * Right node. + */ + public TreeNode right; + // public GroupItem item; + // public Object objects[]; + /** + * Objects in this node. + */ + public Vector objects; + // private int count; + private Comparator _comparator; + + /** + * Create a new TreeNode + * + * @param itm + * first item. + * @param comparator + * item comparator. + */ + public TreeNode(Object itm, Comparator comparator) { + _comparator = comparator; + // item=itm; + objects = new Vector(1, 0); + objects.insertElementAt(itm, objects.size()); + // count=1; + left = new TreeNode(comparator); + right = new TreeNode(comparator); + } + + /** + * Create a new TreeNode + * + * @param comparator + * comparator. + */ + public TreeNode(Comparator comparator) { + _comparator = comparator; + // item=null; + objects = new Vector(1, 0); + left = null; + right = null; + // count=0; + } + + /** + * Returns true if node is external. + * + * @return true if node is external, false otherwise. + */ + public boolean external() { + return ((left == null) || (right == null)); + } + + /** + * Remove the given item. + * + * @param itm + * item to remove. + * @return resulting tree node. + * @throws Exception + */ + public TreeNode remove(Object itm) throws Exception { + if (external()) + throw new Exception(); + + int compare = _comparator.compare(itm,/* item.getFirstItem() */ + objects.elementAt(0)); + if (compare == 0) { + // item.remove(itm); + objects.removeElement(itm); + // count--; + if (objects.size() == 0) { + if (left.external()) + return right; + if (right.external()) + return left; + return right.addTree(left); + } + return this; + } else if (compare < 0) { + left = left.remove(itm); + return this; + } else { + right = right.remove(itm); + return this; + } + } + + private TreeNode addTree(TreeNode tree) throws Exception { + if (external()) + return tree; + if (tree.external()) + return this; + + int compare = _comparator.compare(tree.objects.elementAt(0), objects.elementAt(0)); + if (compare == 0) { + throw new Exception(); + } else if (compare < 0) { + left = left.addTree(tree); + return this; + } else { + right = right.addTree(tree); + return this; + } + } + + /** + * Add an object. + * + * @param itm + * object to tadd. + * @return resulting tree node. + * @throws Exception + */ + public TreeNode add(Object itm) throws Exception { + if (external()) { + return new TreeNode(itm, _comparator); + } + + int compare = _comparator.compare(itm, objects.elementAt(0)); + if (compare == 0) { + // item.add(itm); + objects.insertElementAt(itm, objects.size()); + // throw new RuntimeException("Duplicate key"); + return this; + } else if (compare < 0) { + left = left.add(itm); + return this; + } else { + right = right.add(itm); + return this; + } + } + + /** + * Start an inorder tree traversal. + * + * @param lis + * traversal listener. + * @param param + * user parameter. + */ + public void inorder(TreeTraversalListener lis, Object param) { + if (external()) + return; + left.inorder(lis, param); + // Enumeration e=item.elements(); + // while(e.hasMoreElements()) lis.nextItem(e.nextElement(),param); + // lis.nextItem(object,param); + for (int i = 0; i < objects.size(); i++) + lis.nextItem(objects.elementAt(i), param); + right.inorder(lis, param); + } +} + +/** + * A Sorted List. + */ +public class SortedList implements TreeTraversalListener { + private TreeNode _root; + private Vector _items; + private Comparator _comparator; + private boolean _upToDate; + + /** + * Create a new SortedList, using the given Comparator for the order + * definition. + * + * @param comparator + * comparator to be used for ordering. + */ + public SortedList(Comparator comparator) { + _comparator = comparator; + _root = new TreeNode(_comparator); + _items = new Vector(); + _upToDate = false; + } + + /** + * Get the amount of items in the list. + * + * @return list size. + */ + public int getSize() { + if (!_upToDate) + computeVector(); + return _items.size(); + } + + /** + * Add an item in the list. + * + * @param item + * item to add. + */ + public void add(Object item) { + try { + _root = _root.add(item); + } catch (Exception e) { + } + _upToDate = false; + } + + /** + * Remove the given item from the list. + * + * @param item + * item to remove from the list. + */ + public void remove(Object item) { + try { + _root = _root.remove(item); + } catch (Exception e) { + } + _upToDate = false; + } + + @Override + public void begin(Object param) { + _items = new Vector(); + } + + @Override + public void nextItem(Object item, Object param) { + _items.insertElementAt(item, _items.size()); + } + + @Override + public void end(Object param) { + _upToDate = true; + } + + private void computeVector() { + getItems(this, null); + } + + /** + * Get a sorted enumeration of items. + * + * @return a sorted enumeration of items in the list. + */ + public Enumeration getItems() { + if (!_upToDate) + computeVector(); + return _items.elements(); + } + + /** + * Get the i'th element in the list. Index are ordered. + * + * @param i + * index. + * @return object at i'th position. + */ + public Object getItemAt(int i) { + if (!_upToDate) + computeVector(); + return _items.elementAt(i); + } + + /** + * Begin a new traversal. + * + * @param lis + * traversal listener. + * @param param + * user parameter. + */ + public void getItems(TreeTraversalListener lis, Object param) { + lis.begin(param); + _root.inorder(lis, param); + lis.end(param); + } + + /** + * Clear the list. + */ + public void clear() { + _root = new TreeNode(_comparator); + _items = new Vector(); + _upToDate = false; + } + +} diff --git a/src/main/java/irc/tree/TreeTraversalListener.java b/src/main/java/irc/tree/TreeTraversalListener.java new file mode 100644 index 0000000..3e4ca0c --- /dev/null +++ b/src/main/java/irc/tree/TreeTraversalListener.java @@ -0,0 +1,62 @@ +/*****************************************************/ +/* This java file is a part of the */ +/* */ +/* - Plouf's Java IRC Client - */ +/* */ +/* Copyright (C) 2002 - 2004 Philippe Detournay */ +/* */ +/* All contacts : theplouf@yahoo.com */ +/* */ +/* PJIRC is free software; you can redistribute */ +/* it and/or modify it under the terms of the GNU */ +/* General Public License as published by the */ +/* Free Software Foundation; version 2 or later of */ +/* the License. */ +/* */ +/* PJIRC is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU */ +/* General Public License along with PJIRC; if */ +/* not, write to the Free Software Foundation, */ +/* Inc., 59 Temple Place, Suite 330, Boston, */ +/* MA 02111-1307 USA */ +/* */ +/*****************************************************/ + +package irc.tree; + +/** + * Interface used for traversing trees. + */ +public interface TreeTraversalListener { + /** + * The traversal is about to begin. + * + * @param param + * user parameter. + */ + public void begin(Object param); + + /** + * Next item in the tree. + * + * @param item + * item. + * @param param + * user parameter. + */ + public void nextItem(Object item, Object param); + + /** + * The traversal is finished. + * + * @param param + * user parameter. + */ + public void end(Object param); + +} diff --git a/src/main/resources/english.lng b/src/main/resources/english.lng new file mode 100644 index 0000000..b3521a7 --- /dev/null +++ b/src/main/resources/english.lng @@ -0,0 +1,93 @@ +# +# This java file is a part of the +# +# - Plouf's Java IRC Client - +# +# Copyright (C) 2004 Philippe Detournay +# +# This file is licensed under the GPL license +# +# All contacts : theplouf@yahoo.com +# +# +# Syntax : +# Comments begin with the # character. This character must be the first character of the line. +# A data line has three parts : the data id, the data id description, the data string. +# - Data id : An hexadecimal figure identifying the string. +# - Data description : Begins by [ and ends by ]. The description is not parsed and +# can be any string. +# - Data string : The string itself. Parameters are specified using the %i syntax. +# +# Trailing spaces can be added using the \s escape character. + +0001 [INTERPRETOR_NOT_ON_CHANNEL] Not on a channel +0002 [INTERPRETOR_UNKNOWN_DCC] %1 : unknown dcc subcommand +0003 [INTERPRETOR_INSUFFICIENT_PARAMETERS] %1 : insufficient parameters +0004 [INTERPRETOR_BAD_CONTEXT] %1 : unable to perform in current context +0005 [INTERPRETOR_CANNOT_CTCP_IN_DCCCHAT] Cannot send CTCP codes via DCC Chat +0006 [INTERPRETOR_UNKNOWN_CONFIG] %1 : unknown config subcommand +0007 [INTERPRETOR_TIMESTAMP_ON] Timestamp enabled +0008 [INTERPRETOR_TIMESTAMP_OFF] Timestamp disabled +0009 [INTERPRETOR_SMILEYS_ON] Graphical smileys enabled +000a [INTERPRETOR_SMILEYS_OFF] Graphical smileys disabled +000b [INTERPRETOR_IGNORE_ON] Now ignoring %1 +000c [INTERPRETOR_IGNORE_OFF] Not ignoring %1 anymore +000d [INTERPRETOR_MULTISERVER_DISABLED] Multiserver support is disabled + +0101 [DCC_WAITING_INCOMING] Waiting for incoming connection... +0102 [DCC_UNABLE_TO_OPEN_CONNECTION] Unable to open connection : %1 +0103 [DCC_CONNECTION_ESTABLISHED] DCC Connection established +0104 [DCC_CONNECTION_CLOSED] Connection closed +0105 [DCC_ERROR] Error : %1 +0106 [DCC_UNABLE_TO_SEND_TO] %1 : unable to send to %2 +0107 [DCC_BAD_CONTEXT] Unable to execute command from current context +0108 [DCC_NOT_CONNECTED] Not connected +0109 [DCC_UNABLE_PASSIVE_MODE] Unable to initialize passive mode +010a [CTCP_PING_REPLY] [%1 PING reply] : %2 seconds +010b [DCC_STREAM_CLOSED] Stream closed + +0201 [IDENT_FAILED_LAUNCH] Failed to launch Ident server : %1 +0202 [IDENT_REQUEST] Ident request from %1 +0203 [IDENT_ERROR] Error occurred +0204 [IDENT_REPLIED] Replied %1 +0205 [IDENT_DEFAULT_USER] default user +0206 [IDENT_NO_USER] No user for request +0207 [IDENT_RUNNING_ON_PORT] Ident server running on port %1 +0208 [IDENT_LEAVING] Ident server leaving : %1 +0209 [IDENT_NONE] none +020a [IDENT_UNKNOWN] unknown +020b [IDENT_UNDEFINED] Undefined result + +0301 [FILE_SAVEAS] Save file as + +0401 [ABOUT_ABOUT] About +0402 [ABOUT_PROGRAMMING] Programming +0403 [ABOUT_DESIGN] Design +0404 [ABOUT_THANKS] Thanks to +0405 [ABOUT_SUPPORT] for support, ideas and testing +0406 [ABOUT_GPL] This software is licensed under the GPL license + +0501 [SERVER_UNABLE_TO_CONNECT] Unable to connect : %1 +0502 [SERVER_UNABLE_TO_CONNECT_STILL] Unable to connect to %1 : currently trying to connect to %2 +0503 [SERVER_DISCONNECTING] Disconnecting from %1 +0504 [SERVER_CONNECTING] Connecting... +0505 [SERVER_NOT_CONNECTED] Not connected +0506 [SERVER_LOGIN] Logging in... +0507 [SERVER_DISCONNECTED] Disconnected from %1 +0508 [SERVER_ERROR] Error : %1 +0509 [SERVER_AUTOREJOIN_ATTEMPT] Attempting to rejoin channel %1... +050a [SERVER_AUTOREJOIN_FAILED] Unable to rejoin channel %1 + +071a [GUI_CHANGE_NICK] Change nick to +071b [GUI_COPY_WINDOW] Copy text +071c [GUI_DCC_CHAT_WARNING_TITLE] Warning +071d [GUI_DCC_CHAT_WARNING_TEXT] Do you want to accept DCC chat from %1? + +0801 [ASL_MALE] Boy, %1 years old, %2 +0802 [ASL_FEMALE] Girl, %1 years old, %2 +0803 [ASL_UNKNOWN] %1 years old from %2 + +0901 [REPLY_IDLE] %1 has been idle for %2 +0902 [REPLY_SIGNON] %1 connected on %2 + +ffff [ERROR_NOT_DEFINED] Undefined string diff --git a/src/main/resources/pixx-english.lng b/src/main/resources/pixx-english.lng new file mode 100644 index 0000000..ae38037 --- /dev/null +++ b/src/main/resources/pixx-english.lng @@ -0,0 +1,75 @@ +# +# This java file is a part of the +# +# - Plouf's Java IRC Client - +# +# Copyright (C) 2004 Philippe Detournay +# +# This file is licensed under the GPL license +# +# All contacts : theplouf@yahoo.com +# +# +# Syntax : +# Comments begin with the # character. This character must be the first character of the line. +# A data line has three parts : the data id, the data id description, the data string. +# - Data id : An hexadecimal figure identifying the string. +# - Data description : Begins by [ and ends by ]. The description is not parsed and +# can be any string. +# - Data string : The string itself. Parameters are specified using the %i syntax. +# +# Trailing spaces can be added using the \s escape character. + +8601 [SOURCE_YOU_KICKED] You've been kicked out of %1 by %2 +8602 [SOURCE_STATUS] Status +8603 [SOURCE_CHANLIST] Channels for %1 +8604 [SOURCE_CHANLIST_RETREIVING] Retrieving channels... +8605 [SOURCE_HAS_JOINED] %1 has joined %2 +8606 [SOURCE_HAS_LEFT] %1 has left %2 +8607 [SOURCE_HAS_BEEN_KICKED_BY] %1 has been kicked by %2 +8608 [SOURCE_HAS_QUIT] %1 has quit +8609 [SOURCE_TOPIC_IS] Topic is %1 +860a [SOURCE_CHANGED_TOPIC] %1 changed topic to %2 +860b [SOURCE_CHANNEL_MODE] %1 sets channel mode to %2 +860c [SOURCE_CHANNEL_MODE_IS] Channel mode is %1 +860d [SOURCE_USER_MODE] %1 sets mode %2 on %3 +860e [SOURCE_KNOWN_AS] %1 is now known as %2 +860f [SOURCE_YOUR_MODE] Mode changed to %1 +8610 [SOURCE_YOUR_NICK] Your nick is now %1 +8611 [SOURCE_INFO] Infos +8612 [SOURCE_AWAY] %1 is away +8613 [SOURCE_YOU_INVITED] %1 invites you to join %2 +8614 [SOURCE_YOU_JOINED_AS] You're talking in %1 as %2 + +8701 [GUI_WHOIS] Whois +8702 [GUI_QUERY] Query +8703 [GUI_KICK] Kick +8704 [GUI_BAN] Ban +8705 [GUI_KICKBAN] Kick + Ban +8706 [GUI_OP] Op +8707 [GUI_DEOP] DeOp +8708 [GUI_VOICE] Voice +8709 [GUI_DEVOICE] DeVoice +870a [GUI_PING] Ping +870b [GUI_VERSION] Version +870c [GUI_TIME] Time +870d [GUI_FINGER] Finger +870e [GUI_RETREIVING_FILE] Receiving file (%1 bytes) +870f [GUI_SENDING_FILE] Sending file (%1 bytes) +8710 [GUI_TERMINATED] %1 terminated +8711 [GUI_FAILED] %1 failed +8712 [GUI_CLOSE] Close +8713 [GUI_DISCONNECT] Disconnect +8714 [GUI_CHANNELS] Channels +8715 [GUI_HELP] Help +8716 [GUI_PRIVATE] private +8717 [GUI_PUBLIC] public +8718 [GUI_CONNECT] Connect +8719 [GUI_ABOUT] About +871a [GUI_CHANGE_NICK] Change nick to +871c [GUI_FONT] Font +871d [GUI_FONT_WINDOW] Select font +871e [GUI_FONT_WINDOW_OK] Ok +871f [GUI_ENTER_TEXT_HERE] Enter text here... + +ffff [ERROR_NOT_DEFINED] Undefined string diff --git a/src/main/resources/pjirc.cfg b/src/main/resources/pjirc.cfg new file mode 100644 index 0000000..2131084 --- /dev/null +++ b/src/main/resources/pjirc.cfg @@ -0,0 +1,28 @@ +# +# This file is part of the +# +# - Plouf's Java IRC Client - +# +# Copyright (C) 2002 -- 2004 Philippe Detournay +# +# This file is licensed under the GPL license +# +# All contacts : plouf@pjirc.com +# +# Syntax : +# Comments begin with the # character. This character must be the first character of the line. +# A data line has two parts : the parameter name and the parameter value. These parts +# are separated by the '=' character. Any further '=' character is understood as being part +# of the parameter value. + +# Mandatory parameters : + +nick=pjircTest +fullname=PJIRC user +host=irc.somenet.org +gui=pixx + +# Optional parameters : +asl=true +style:floatingasl=true +#coding=2 -- 2.43.0