Page Menu
Home
Phabricator (Chris)
Search
Configure Global Search
Log In
Files
F131186
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
48 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/util/gui/context-box.cpp b/util/gui/context-box.cpp
index c23ac227..f002c0bb 100644
--- a/util/gui/context-box.cpp
+++ b/util/gui/context-box.cpp
@@ -1,358 +1,359 @@
#include "util/graphics/bitmap.h"
#include "context-box.h"
#include "util/font.h"
#include <math.h>
#include "util/token.h"
static const double FONT_SPACER = 1.3;
static const int GradientMax = 50;
static Graphics::Color selectedGradientStart(){
static Graphics::Color color = Graphics::makeColor(19, 167, 168);
return color;
}
static Graphics::Color selectedGradientEnd(){
static Graphics::Color color = Graphics::makeColor(27, 237, 239);
return color;
}
using namespace std;
namespace Gui{
Effects::Gradient standardGradient(int max){
Effects::Gradient standard(max, selectedGradientStart(), selectedGradientEnd());
return standard;
}
Effects::Gradient modifiedGradient(Graphics::Color low, Graphics::Color high, int max){
Effects::Gradient modified(max, low, high);
return modified;
}
ListValues::ListValues():
interpolate(true),
lowColor(selectedGradientStart()),
highColor(selectedGradientEnd()),
maxGradient(GradientMax),
selectedColor(selectedGradientStart()),
selectedAlpha(255),
otherColor(Graphics::makeColor(255, 255, 255)),
otherAlpha(255),
distanceFadeMultiplier(35),
fade(true){
}
ListValues::ListValues(const ListValues & copy):
interpolate(copy.interpolate),
lowColor(copy.lowColor),
highColor(copy.highColor),
maxGradient(copy.maxGradient),
selectedColor(copy.selectedColor),
selectedAlpha(copy.selectedAlpha),
otherColor(copy.otherColor),
otherAlpha(copy.otherAlpha),
distanceFadeMultiplier(copy.distanceFadeMultiplier),
fade(copy.fade){
}
ListValues::~ListValues(){
}
const ListValues & ListValues::operator=(const ListValues & copy){
interpolate = copy.interpolate;
lowColor = copy.lowColor;
highColor = copy.highColor;
maxGradient = copy.maxGradient;
selectedColor = copy.selectedColor;
selectedAlpha = copy.selectedAlpha;
otherColor = copy.otherColor;
otherAlpha = copy.otherAlpha;
distanceFadeMultiplier = copy.distanceFadeMultiplier;
fade = copy.fade;
return *this;
}
static int clamp(int in, int low = 0, int high = 255){
if (in < low){
return low;
}
if (in > high){
return high;
}
return in;
}
void ListValues::getValues(const Token * token){
TokenView view = token->view();
while (view.hasMore()){
const Token * token;
view >> token;
try{
int red = 0, green = 0, blue = 0, alpha = 0, gradient=1;
if (token->match("interpolate-selected", interpolate)){
} else if (token->match("color-low", red, green, blue)){
lowColor = Graphics::makeColor(clamp(red), clamp(green), clamp(blue));
} else if (token->match("color-high", red, green, blue)){
highColor = Graphics::makeColor(clamp(red), clamp(green), clamp(blue));
} else if (token->match("interpolate-distance", gradient)){
maxGradient = clamp(gradient, 1, 1000);
} else if (token->match("selected-color", red, green, blue)){
selectedColor = Graphics::makeColor(clamp(red), clamp(green), clamp(blue));
} else if (token->match("selected-color-alpha", alpha)){
selectedAlpha = clamp(alpha);
} else if (token->match("other-color", red, green, blue)){
otherColor = Graphics::makeColor(clamp(red), clamp(green), clamp(blue));
} else if (token->match("other-color-alpha", alpha)){
otherAlpha = clamp(alpha);
} else if (token->match("distance-fade-multiplier", distanceFadeMultiplier)){
} else if (token->match("distance-fade", fade)){
}
} catch (const TokenException & ex){
// Output something
}
}
}
ContextItem::ContextItem(const std::string & name, const ContextBox & parent):
text(name),
parent(parent){
}
ContextItem::~ContextItem(){
}
void ContextItem::draw(int x, int y, const Graphics::Bitmap & where, const Font & font, int distance) const {
if (distance == 0){
if (parent.getListValues().getInterpolate()){
Graphics::Bitmap::transBlender(0, 0, 0, parent.getFadeAlpha());
font.printf(x, y, parent.getSelectedColor(), where.translucent(), getText(), 0);
} else {
Graphics::Bitmap::transBlender(0, 0, 0, parent.getListValues().getSelectedAlpha());
font.printf(x, y, parent.getListValues().getSelectedColor(), where.translucent(), getText(), 0);
}
} else {
if (parent.getListValues().getDistanceFade()){
int alpha = parent.getListValues().getOtherAlpha() - fabs((double) distance) * parent.getListValues().getDistanceFadeMultiplier();
alpha = clamp(alpha);
Graphics::Bitmap::transBlender(0, 0, 0, alpha);
font.printf(x, y, parent.getListValues().getOtherColor(), where.translucent(), getText(), 0);
} else {
Graphics::Bitmap::transBlender(0, 0, 0, parent.getListValues().getOtherAlpha());
font.printf(x, y, parent.getListValues().getOtherColor(), where.translucent(), getText(), 0);
}
}
}
void ContextItem::setText(const LanguageString & t){
text = t;
}
int ContextItem::size(const Font & font) const {
return font.textLength(getText().c_str());
}
ContextBox::ContextBox():
fadeState(NotActive),
list(new ScrollList()),
fadeSpeed(12),
fadeAlpha(0),
cursorCenter(0),
cursorLocation(0),
scrollWait(4),
selectedGradient(standardGradient(GradientMax)),
renderOnlyText(false){
}
ContextBox::ContextBox( const ContextBox & copy ):
fadeState(NotActive),
list(new ScrollList()),
selectedGradient(standardGradient(GradientMax)),
renderOnlyText(false){
this->list = copy.list;
this->fadeSpeed = copy.fadeSpeed;
this->fadeAlpha = copy.fadeAlpha;
this->cursorCenter = copy.cursorCenter;
this->cursorLocation = copy.cursorLocation;
this->scrollWait = copy.scrollWait;
this->renderOnlyText = copy.renderOnlyText;
}
ContextBox::~ContextBox(){
}
ContextBox & ContextBox::operator=( const ContextBox & copy){
this->fadeState = NotActive;
this->list = copy.list;
this->fadeSpeed = copy.fadeSpeed;
this->fadeAlpha = copy.fadeAlpha;
this->cursorCenter = copy.cursorCenter;
this->cursorLocation = copy.cursorLocation;
this->scrollWait = copy.scrollWait;
this->renderOnlyText = copy.renderOnlyText;
return *this;
}
void ContextBox::act(const Font & font){
// update board
board.act(font);
// Calculate text info
list->act();
// do fade
doFade();
// Update gradient
selectedGradient.update();
}
void ContextBox::render(const Graphics::Bitmap & work){
}
void ContextBox::render(const Graphics::Bitmap & work, const Font & font){
if (!renderOnlyText){
board.render(work);
}
drawText(work, font);
}
bool ContextBox::next(const Font & font){
if (fadeState == FadeOut){
return false;
}
list->next();
return true;
}
bool ContextBox::previous(const Font & font){
if (fadeState == FadeOut){
return false;
}
list->previous();
return true;
}
Graphics::Color ContextBox::getSelectedColor() const {
return values.getInterpolate() ? selectedGradient.current() : values.getSelectedColor();
}
void ContextBox::setListValues(const Gui::ListValues & values){
this->values = values;
selectedGradient = modifiedGradient(values.getLowColor(), values.getHighColor(), values.getMaxGradient());
}
void ContextBox::adjustLeft(){
}
void ContextBox::adjustRight(){
}
void ContextBox::open(){
// Set the fade stuff
fadeState = FadeIn;
//board.position = position;
board.location = location;
board.transforms = transforms;
board.colors = colors;
board.open();
fadeAlpha = 0;
cursorLocation = 0;
}
void ContextBox::close(){
fadeState = FadeOut;
board.close();
fadeAlpha = 255;
cursorLocation = 480;
}
void ContextBox::doFade(){
switch (fadeState){
case FadeIn: {
if (fadeAlpha < 255){
fadeAlpha += (fadeSpeed+2);
}
if (fadeAlpha >= 255){
fadeAlpha = 255;
if (board.isActive()){
fadeState = Active;
}
}
break;
}
case FadeOut: {
if (fadeAlpha > 0){
fadeAlpha -= (fadeSpeed+2);
}
if (fadeAlpha <= 0){
fadeAlpha = 0;
if (!board.isActive()){
fadeState = NotActive;
}
}
break;
}
case Active:
case NotActive:
default:
break;
}
}
void ContextBox::setList(const std::vector<Util::ReferenceCount<ContextItem> > & list){
this->list->clearItems();
for (vector<Util::ReferenceCount<ContextItem> >::const_iterator it = list.begin(); it != list.end(); it++){
const Util::ReferenceCount<ContextItem> & item = *it;
this->list->addItem(item.convert<ScrollItem>());
}
}
void ContextBox::addItem(const Util::ReferenceCount<ContextItem> & item){
this->list->addItem(item.convert<ScrollItem>());
}
void ContextBox::setListType(const ListType & type){
switch (type){
case Normal:{
Util::ReferenceCount<ScrollListInterface> newList(new NormalList());
newList->addItems(list->getItems());
list = newList;
break;
}
case Scroll:{
Util::ReferenceCount<ScrollListInterface> newList(new ScrollList());
newList->addItems(list->getItems());
list = newList;
break;
}
default:
break;
}
}
void ContextBox::setListWrap(bool wrap){
list->setWrap(wrap);
}
void ContextBox::drawText(const Graphics::Bitmap & bmp, const Font & font){
const int x1 = board.getArea().getX()+(int)(board.getTransforms().getRadius()/2);
const int y1 = board.getArea().getY()+2;//(board.getArea().radius/2);
const int x2 = board.getArea().getX2()-(int)(board.getTransforms().getRadius()/2);
const int y2 = board.getArea().getY2()-2;//(board.getArea().radius/2);
-
- Graphics::Bitmap area(bmp, x1, y1, x2 - x1, y2 - y1);
-
- list->render(area, font);
+
+ if (x2 > x1 && y2 > y1){
+ Graphics::Bitmap area(bmp, x1, y1, x2 - x1, y2 - y1);
+ list->render(area, font);
+ }
}
}
diff --git a/util/gui/lineedit.cpp b/util/gui/lineedit.cpp
index 1849a31d..abbc28b8 100644
--- a/util/gui/lineedit.cpp
+++ b/util/gui/lineedit.cpp
@@ -1,254 +1,258 @@
#include "util/graphics/bitmap.h"
#include "util/font.h"
#include "lineedit.h"
#include "util/debug.h"
#include <iostream>
using namespace Gui;
static Global::stream_type & debug(int level){
Global::debug(level) << "[line edit] ";
return Global::debug(level);
}
LineEdit::LineEdit() :
currentSetFont(0),
hAlignment(T_Middle),
hAlignMod(T_Middle),
vAlignment(T_Middle),
inputTypeValue(inputGeneral),
changed_(0),
autoResizable(0),
textX(0),
textY(0),
cursorX(0),
cursorY(0),
cursorIndex(0),
textColor(Graphics::makeColor(0, 0, 0)),
textSizeH(0),
limit(0),
blinkRate(500),
blink(false),
focused(false),
changeCounter(0){
cursorTime.reset();
}
LineEdit::~LineEdit(){
if (focused){
input.disable();
}
}
void LineEdit::hookKey(int key, void (*callback)(void *), void * arg){
input.addBlockingHandle(key, callback, arg);
}
bool LineEdit::didChanged(unsigned long long & counter){
bool did = counter < changeCounter;
counter = changeCounter;
return did;
}
// If the font size changes
void LineEdit::fontChange(){
changed();
}
// Update
void LineEdit::act(const Font & font){
+ if (currentSetFont == NULL){
+ currentSetFont = &font;
+ }
if (cursorTime.msecs() >= blinkRate){
cursorTime.reset();
blink = !blink;
changed();
}
/*
if ((blinkRate * 2) <= cursorTime.msecs()){
cursorTime.reset();
changed();
}
*/
if (input.doInput()){
changed();
cursorIndex = input.getText().size();
}
if (changed_){
textSizeH = currentSetFont->getHeight();
if (autoResizable) {
location.setDimensions(textSizeH+2, currentSetFont->textLength(input.getText().c_str()) + 4);
} else {
if (hAlignMod==T_Left){
if (currentSetFont->textLength(input.getText().c_str())>location.getWidth()){
hAlignment = T_Right;
} else {
hAlignment = T_Left;
}
}
}
switch (hAlignment) {
case T_Left:
textX = 2;
cursorX = textX + currentSetFont->textLength(input.getText().substr(0,cursorIndex).c_str()) + 1;
break;
case T_Middle:
textX = (location.getWidth()/2) - (currentSetFont->textLength(input.getText().c_str())/2);
cursorX = (textX) + currentSetFont->textLength(input.getText().substr(0,cursorIndex).c_str()) + 1;
break;
case T_Right:
textX = location.getWidth() - currentSetFont->textLength(input.getText().c_str());//(position.width - 1)-2;
cursorX = location.getWidth() - currentSetFont->textLength(input.getText().substr(0, input.getText().length()-cursorIndex).c_str());
break;
case T_Bottom:
case T_Top:
break;
}
switch (vAlignment) {
case T_Top:
textY = 1;
cursorY = 1;
break;
case T_Middle:
textY = cursorY = (location.getHeight() - textSizeH-(5))/2;
break;
case T_Bottom:
textY = (location.getHeight() - 1) - textSizeH - 1;
cursorY = textY - textSizeH;
break;
case T_Right:
case T_Left:
break;
}
//textY++;
//textX++;
stable();
}
}
// Draw
void LineEdit::render(const Graphics::Bitmap & work){
- Util::ReferenceCount<Graphics::Bitmap> workArea = checkWorkArea(work);
+ //Util::ReferenceCount<Graphics::Bitmap> workArea = checkWorkArea(work);
+ Graphics::Bitmap workArea = Graphics::Bitmap(workArea, location.getX(), location.getY(), location.getWidth(), location.getHeight());
/* Check if we are using a rounded box */
if (transforms.getRadius() > 0){
- workArea->translucent(0, 0, 0, colors.bodyAlpha).roundRectFill((int)transforms.getRadius(), 0, 0, location.getWidth()-1, location.getHeight()-1, colors.body );
- workArea->translucent(0, 0, 0, colors.borderAlpha).roundRect((int)transforms.getRadius(), 0, 0, location.getWidth()-1, location.getHeight()-1, colors.border);
+ workArea.translucent(0, 0, 0, colors.bodyAlpha).roundRectFill((int)transforms.getRadius(), 0, 0, location.getWidth()-1, location.getHeight()-1, colors.body );
+ workArea.translucent(0, 0, 0, colors.borderAlpha).roundRect((int)transforms.getRadius(), 0, 0, location.getWidth()-1, location.getHeight()-1, colors.border);
} else {
- workArea->translucent(0, 0, 0, colors.bodyAlpha).rectangleFill(0, 0, location.getWidth()-1, location.getHeight()-1, colors.body);
- workArea->translucent(0, 0, 0, colors.borderAlpha).rectangle(0, 0, location.getWidth()-1, location.getHeight()-1, colors.border);
+ workArea.translucent(0, 0, 0, colors.bodyAlpha).rectangleFill(0, 0, location.getWidth()-1, location.getHeight()-1, colors.body);
+ workArea.translucent(0, 0, 0, colors.borderAlpha).rectangle(0, 0, location.getWidth()-1, location.getHeight()-1, colors.border);
}
if (currentSetFont){
- currentSetFont->printf(textX, textY, textColor, *workArea, input.getText(), 0);
+ currentSetFont->printf(textX, textY, textColor, workArea, input.getText(), 0);
}
if (focused){
if (blink){
- workArea->line(cursorX, cursorY, cursorX, cursorY+textSizeH-5, textColor);
+ workArea.line(cursorX, cursorY, cursorX, cursorY+textSizeH-5, textColor);
}
}
}
// Set text
void LineEdit::setText(const std::string & text){
input.setText(text);
if (limit!=0) {
if (input.getText().length() > limit) {
while (input.getText().length() > limit){
// currentSetText.erase(currentSetText.begin()+currentSetText.length()-1);
}
}
}
cursorIndex = input.getText().length();
changed();
}
//! Get text
const std::string LineEdit::getText(){
return input.getText();
}
//! Clear text
void LineEdit::clearText(){
input.clearInput();
cursorIndex=0;
changed();
}
//! Set text limit
void LineEdit::setLimit(unsigned int l){
limit = l;
if (limit!=0){
if (input.getText().length()>limit){
while (input.getText().length()>limit){
// currentSetText.erase(currentSetText.begin()+currentSetText.length()-1);
}
}
}
cursorIndex = input.getText().length();
changed();
}
// Set Horizontal Alignment
void LineEdit::setHorizontalAlign(const textAlign & a){
hAlignment = hAlignMod = a;
changed();
}
// Set Vertical Alignment
void LineEdit::setVerticalAlign(const textAlign & a){
vAlignment = a;
changed();
}
//! Set the type of input default general
void LineEdit::setInputType(const inputType i){
inputTypeValue = i;
}
// Set textColor
void LineEdit::setTextColor(const Graphics::Color color){
textColor = color;
}
//! Set textColor
void LineEdit::setCursorColor(const Graphics::Color color){
textColor = color;
}
// Set font
void LineEdit::setFont(const Font *f){
currentSetFont = f;
if (currentSetFont) changed();
}
// Set autoResizeable
void LineEdit::setAutoResize(bool r){
autoResizable = r;
}
// Set the cursor blink rate in miliseconds (default 500)
void LineEdit::setCursorBlinkRate(unsigned int msecs){
blinkRate = msecs;
}
//! set Focus
void LineEdit::setFocused(bool focus){
focused = focus;
if (focus){
input.enable();
} else {
input.disable();
}
}
//! check Focus
bool LineEdit::isFocused(){
return focused;
}
diff --git a/util/network/irc.cpp b/util/network/irc.cpp
index 32108c3b..2041ad8a 100644
--- a/util/network/irc.cpp
+++ b/util/network/irc.cpp
@@ -1,617 +1,635 @@
#include "irc.h"
+#include "util/font.h"
#include "util/regex.h"
-
#include "util/graphics/bitmap.h"
+#include "util/configuration.h"
#include <stdexcept>
namespace Network{
namespace IRC{
static Command::Type convertCommand(const std::string & cmd){
Command::Type command = Command::Unknown;
if (cmd == "PASS"){
command = Command::Pass;
} else if (cmd == "NICK"){
command = Command::Nick;
} else if (cmd == "USER"){
command = Command::User;
} else if (cmd == "SERVER"){
command = Command::Server;
} else if (cmd == "OPER"){
command = Command::Oper;
} else if (cmd == "QUIT"){
command = Command::Quit;
} else if (cmd == "SQUIT"){
command = Command::Squit;
} else if (cmd == "JOIN"){
command = Command::Join;
} else if (cmd == "PART"){
command = Command::Part;
} else if (cmd == "MODE"){
command = Command::Mode;
} else if (cmd == "TOPIC"){
command = Command::Topic;
} else if (cmd == "NAMES"){
command = Command::Names;
} else if (cmd == "LIST"){
command = Command::List;
} else if (cmd == "INVITE"){
command = Command::Invite;
} else if (cmd == "KICK"){
command = Command::Kick;
} else if (cmd == "VERSION"){
command = Command::Version;
} else if (cmd == "STATS"){
command = Command::Stats;
} else if (cmd == "LINKS"){
command = Command::Links;
} else if (cmd == "TIME"){
command = Command::Time;
} else if (cmd == "CONNECT"){
command = Command::Connect;
} else if (cmd == "TRACE"){
command = Command::Trace;
} else if (cmd == "ADMIN"){
command = Command::Admin;
} else if (cmd == "INFO"){
command = Command::Info;
} else if (cmd == "PRIVMSG"){
command = Command::PrivateMessage;
} else if (cmd == "NOTICE"){
command = Command::Notice;
} else if (cmd == "WHO"){
command = Command::Who;
} else if (cmd == "WHOIS"){
command = Command::Whois;
} else if (cmd == "WHOWAS"){
command = Command::Whowas;
} else if (cmd == "KILL"){
command = Command::Kill;
} else if (cmd == "PING"){
command = Command::Ping;
} else if (cmd == "PONG"){
command = Command::Pong;
} else if (cmd == "ERROR"){
command = Command::Error;
} else if (cmd == "433"){
command = Command::ErrorNickInUse;
} else if (cmd == "401"){
command = Command::ErrorNoSuchNick;
} else if (cmd == "403"){
command = Command::ErrorNoSuchChannel;
} else if (cmd == "461"){
command = Command::ErrorNeedMoreParams;
} else if (cmd == "473"){
command = Command::ErrorInviteOnlyChannel;
} else if (cmd == "474"){
command = Command::ErrorBannedFromChannel;
} else if (cmd == "475"){
command = Command::ErrorBadChannelKey;
} else if (cmd == "471"){
command = Command::ErrorChannelIsFull;
} else if (cmd == "331"){
command = Command::ReplyNoTopic;
} else if (cmd == "332"){
command = Command::ReplyTopic;
} else if (cmd == "333"){
command = Command::ReplyTopicAuthor;
} else if (cmd == "353"){
command = Command::ReplyNames;
} else if (cmd == "366"){
command = Command::ReplyNamesEndOf;
} else if (cmd == "372"){
command = Command::ReplyMOTD;
} else if (cmd == "375"){
command = Command::ReplyMOTDStart;
} else if (cmd == "376"){
command = Command::ReplyMOTDEndOf;
}
return command;
}
static std::string convertCommand(const Command::Type & cmd){
switch (cmd){
case Command::Pass: return "PASS";
case Command::Nick: return "NICK";
case Command::User: return "USER";
case Command::Server: return "SERVER";
case Command::Oper: return "OPER";
case Command::Quit: return "QUIT";
case Command::Squit: return "SQUIT";
case Command::Join: return "JOIN";
case Command::Part: return "PART";
case Command::Mode: return "MODE";
case Command::Topic: return "TOPIC";
case Command::Names: return "NAMES";
case Command::List: return "LIST";
case Command::Invite: return "INVITE";
case Command::Kick: return "KICK";
case Command::Version: return "VERSION";
case Command::Stats: return "STATS";
case Command::Links: return "LINKS";
case Command::Time: return "TIME";
case Command::Connect: return "CONNECT";
case Command::Trace: return "TRACE";
case Command::Admin: return "ADMIN";
case Command::Info: return "INFO";
case Command::PrivateMessage: return "PRIVMSG";
case Command::Notice: return "NOTICE";
case Command::Who: return "WHO";
case Command::Whois: return "WHOIS";
case Command::Whowas: return "WHOAS";
case Command::Kill: return "KILL";
case Command::Ping: return "PING";
case Command::Pong: return "PONG";
case Command::Error: return "ERROR";
case Command::Unknown:
default:
break;
}
return "";
}
static std::vector<std::string> split(std::string str, char splitter){
std::vector<std::string> strings;
size_t next = str.find(splitter);
while (next != std::string::npos){
strings.push_back(str.substr(0, next));
str = str.substr(next+1);
next = str.find(splitter);
}
if (str != ""){
strings.push_back(str);
}
return strings;
}
Command::Command(const std::string & message){
std::vector< std::string > messageSplit = split(message, ' ');
std::vector< std::string >::iterator current = messageSplit.begin();
if (Util::matchRegex(*current, Util::Regex("^:.*"))){
// Found owner (":") indicates the user, otherwise it's going to be the command
// Grab just the username, ignore everything else
try{
owner = split(*current, '!').at(0).substr(1);
} catch (const std::out_of_range & ex){
}
current++;
}
// Next is the actual command
type = convertCommand(*current);
if (type == Unknown){
Global::debug(0) << "Got unhandled response: " << message << std::endl;
}
current++;
// Parameters
bool foundCtcp = false;
bool concactenate = false;
std::string concactenated;
for (std::vector< std::string >::iterator i = current; i != messageSplit.end(); ++i){
const std::string & parameter = *i;
// If there is a colon in the parameter the rest of split string is the whole parameter rejoin
if (Util::matchRegex(parameter, Util::Regex("^:\001.*")) && !foundCtcp){
foundCtcp = true;
// Drop the ':\001'
ctcp.push_back(parameter.substr(2));
continue;
} else if (Util::matchRegex(parameter, Util::Regex(".*\001")) && foundCtcp){
foundCtcp = false;
// Drop the '\001'
ctcp.push_back(parameter.substr(0, parameter.size()-1));
continue;
} else if (Util::matchRegex(parameter, Util::Regex("^:.*")) && !concactenate){
concactenate = true;
// Drop the ':'
concactenated += parameter.substr(1) + " ";
continue;
} else if (Util::matchRegex(parameter, Util::Regex("=")) ||
Util::matchRegex(parameter, Util::Regex("@"))){
// Ignore
continue;
}
if (concactenate){
concactenated += parameter + " ";
} else {
if (!foundCtcp){
parameters.push_back(parameter);
} else {
ctcp.push_back(parameter);
}
}
}
if (concactenate){
parameters.push_back(concactenated);
}
}
Command::Command(const std::string & owner, const Type & type):
owner(owner),
type(type){
}
Command::Command(const Command & copy):
owner(copy.owner),
type(copy.type),
parameters(copy.parameters),
ctcp(copy.ctcp){
}
Command::~Command(){
}
const Command & Command::operator=(const Command & copy){
owner = copy.owner;
type = copy.type;
parameters = copy.parameters;
ctcp = copy.ctcp;
return *this;
}
std::string Command::getSendable() const {
std::string sendable;
// Name
if (!owner.empty()){
sendable += ":" + owner + " ";
}
// Command
sendable += convertCommand(type) + " ";
// Params
/*for (std::vector<std::string>::const_iterator i = parameters.begin(); i != parameters.end(); ++i){
sendable+= *i + " ";
}*/
for (unsigned int i = 0; i < parameters.size(); ++i){
sendable += parameters[i] + (i < parameters.size()-1 ? " " : "");
}
// End
sendable += "\r\n";
return sendable;
}
Channel::Channel(){
}
Channel::Channel(const std::string & name):
name(name){
}
Channel::Channel(const Channel & copy):
name(copy.name),
topic(copy.topic),
topicAuthor(copy.topicAuthor),
topicDate(copy.topicDate),
users(copy.users){
}
Channel::~Channel(){
}
const Channel & Channel::operator=(const Channel & copy){
name = copy.name;
topic = copy.topic;
topicAuthor = copy.topicAuthor;
topicDate = copy.topicDate;
users = copy.users;
return *this;
}
void Channel::addUser(const std::string & user){
// Can't add same user twice
for (std::vector<std::string>::iterator i = users.begin(); i != users.end(); ++i){
const std::string & name = *i;
if (name == user){
return;
}
}
users.push_back(user);
}
void Channel::removeUser(const std::string & user){
for (std::vector<std::string>::iterator i = users.begin(); i != users.end(); ++i){
const std::string & name = *i;
if (name == user){
users.erase(i);
break;
}
}
}
void Channel::addUsers(const std::vector<std::string> & list){
for (std::vector<std::string>::const_iterator i = list.begin(); i != list.end(); ++i){
const std::string & name = *i;
addUser(name);
}
}
Client::Client(const std::string & hostname, int port):
previousUsername("AUTH"),
username("AUTH"),
previousActiveChannel(0),
currentChannel(0),
hostname(hostname),
port(port),
end(false){
}
Client::~Client(){
}
void Client::connect(){
if (username.empty()){
throw NetworkException("Set username first.");
}
Global::debug(0) << "Connecting to " << hostname << " on port " << port << std::endl;
socket = Network::connectReliable(hostname, port);
start();
setName("paintown-test");
Command user("AUTH", Command::User);
user.setParameters(username, "*", "0", ":auth");
sendCommand(user);
// ^^^^^^^^ Should get a response from this crap!
joinChannel("#paintown");
Global::debug(0) << "Connected" << std::endl;
}
bool Client::hasCommands() const{
::Util::Thread::ScopedLock scope(lock);
return !commands.empty();
}
Command Client::nextCommand() const {
::Util::Thread::ScopedLock scope(lock);
Command command = commands.front();
commands.pop();
return command;
}
void Client::sendCommand(const Command & command){
const std::string & sendable = command.getSendable();
Network::sendBytes(socket, (uint8_t *) sendable.c_str(), sendable.size());
}
void Client::sendCommand(const Command::Type & type){
Command command(username, type);
sendCommand(command);
}
void Client::sendCommand(const Command::Type & type, const std::string & param1){
Command command(username, type);
command.setParameters(param1);
sendCommand(command);
}
void Client::sendCommand(const Command::Type & type, const std::string & param1, const std::string & param2){
Command command(username, type);
command.setParameters(param1, param2);
sendCommand(command);
}
void Client::sendCommand(const Command::Type & type, const std::string & param1, const std::string & param2, const std::string & param3){
Command command(username, type);
command.setParameters(param1, param2, param3);
sendCommand(command);
}
void Client::sendCommand(const Command::Type & type, const std::string & param1, const std::string & param2, const std::string & param3, const std::string & param4){
Command command(username, type);
command.setParameters(param1, param2, param3, param4);
sendCommand(command);
}
void Client::setName(const std::string & name){
previousUsername = username;
// Update channel list
//channel.removeUser(username);
//channel.addUser(name);
for (std::vector< ChannelPointer >::iterator i = activeChannels.begin(); i != activeChannels.end(); ++i){
ChannelPointer activeChannel = *i;
activeChannel->removeUser(username);
activeChannel->addUser(name);
}
username = name;
sendCommand(Command::Nick, name);
}
void Client::joinChannel(const std::string & chan){
for (std::vector< ChannelPointer >::iterator i = activeChannels.begin(); i != activeChannels.end(); ++i){
ChannelPointer activeChannel = *i;
if (activeChannel->getName() == chan){
// Already belonging to this channel
return;
}
}
previousActiveChannel = currentChannel;
ChannelPointer newChannel = ChannelPointer(new Channel(chan));
/*if (!currentChannel.getName().empty()){
sendCommand(Command::Part, currentChannel.getName());
}*/
activeChannels.push_back(newChannel);
currentChannel = activeChannels.size()-1;
sendCommand(Command::Join, getChannel()->getName());
}
std::string Client::channelListAsString(){
std::string list;
for (std::vector<ChannelPointer>::iterator i = activeChannels.begin(); i != activeChannels.end(); ++i){
ChannelPointer activeChannel = *i;
list += activeChannel->getName() + ", ";
}
return list.substr(0, list.size()-2);
}
unsigned int Client::getChannelIndex(const std::string & channel){
for (unsigned int i = 0; i < activeChannels.size(); ++i){
if (activeChannels[i]->getName() == channel){
return i;
}
}
return 0;
}
bool Client::isCurrentChannel(const std::string & channel){
return (activeChannels[currentChannel]->getName() == channel);
}
void Client::setChannel(unsigned int channel){
if (channel >= activeChannels.size()){
return;
}
currentChannel = channel;
}
void Client::nextChannel(){
currentChannel = (currentChannel + 1) % activeChannels.size();
}
void Client::previousChannel(){
if (currentChannel == 0){
currentChannel = activeChannels.size()-1;
} else {
currentChannel--;
}
}
void Client::removeChannel(const std::string & name){
for (std::vector< ChannelPointer >::iterator i = activeChannels.begin(); i != activeChannels.end(); ++i){
ChannelPointer activeChannel = *i;
if (activeChannel->getName() == name){
activeChannels.erase(i);
return;
}
}
}
ChannelPointer Client::findChannel(const std::string & name){
for (std::vector< ChannelPointer >::iterator i = activeChannels.begin(); i != activeChannels.end(); ++i){
ChannelPointer activeChannel = *i;
if (activeChannel->getName() == name){
return activeChannel;
}
}
return ChannelPointer(NULL);
}
void Client::sendMessage(const std::string & msg){
sendCommand(Command::PrivateMessage, getChannel()->getName(), ":" + msg);
}
void Client::sendPong(const Command & ping){
Command pong(username, Command::Pong);
pong.setParameters(ping.getParameters());
sendCommand(pong);
}
std::string Client::readMessage(){
std::string received;
bool foundReturn = false;
while (true){
try {
char nextCharacter = Network::read8(socket);
/* NOTE the latest RFC says that either \r or \n is the end of the message
* http://www.irchelp.org/irchelp/rfc/chapter8.html
*/
if (nextCharacter == '\r'){
// Found return
foundReturn = true;
continue;
} else if ((nextCharacter == '\n') && foundReturn){
// Should be the end of the message assuming \r is before it
break;
}
received += nextCharacter;
} catch (const Network::MessageEnd & ex){
// end of message get out
throw ex;
}
}
//Global::debug(0) << "Read next string: " << received << std::endl;
return received;
}
void Client::checkResponseAndHandle(const Command & command){
// Checks for username or channel errors
if (command.getType() == Command::ErrorNickInUse){
::Util::Thread::ScopedLock scope(lock);
// Change the username back to what it was
getChannel()->removeUser(username);
username = previousUsername;
getChannel()->addUser(username);
} else if (command.getType() == Command::ErrorBannedFromChannel ||
command.getType() == Command::ErrorInviteOnlyChannel ||
command.getType() == Command::ErrorBadChannelKey ||
command.getType() == Command::ErrorChannelIsFull ||
command.getType() == Command::ErrorNoSuchChannel){
::Util::Thread::ScopedLock scope(lock);
// Revert old channel
removeChannel(getChannel()->getName());
currentChannel = previousActiveChannel;
} else if (command.getType() == Command::ReplyTopic){
::Util::Thread::ScopedLock scope(lock);
// Set topic
getChannel()->setTopic(command.getParameters().at(2));
} else if (command.getType() == Command::ReplyTopicAuthor){
::Util::Thread::ScopedLock scope(lock);
// Set topic and author
const std::vector<std::string> & params = command.getParameters();
getChannel()->setTopicAuthor(split(params.at(1), '!').at(0), atoi(params.at(2).c_str()));
} else if (command.getType() == Command::ReplyNames){
// Add names
const std::vector<std::string> & params = command.getParameters();
//if (params.at(1) == currentChannel->getName()){
const std::vector<std::string> & names = split(params.at(2), ' ');
::Util::Thread::ScopedLock scope(lock);
//currentChannel->addUsers(names);
ChannelPointer update = findChannel(params.at(1));
if (update != NULL){
update->addUsers(names);
}
//}
}
}
void Client::run(){
while (!end){
try {
const std::string & message = readMessage();
// Check if the message is empty it might be because of (\n)
if (!message.empty()){
Command command(message);
::Util::Thread::ScopedLock scope(lock);
checkResponseAndHandle(command);
commands.push(command);
} else {
}
} catch (const Network::MessageEnd & ex){
end = true;
}
}
}
-ChatInterface::ChatInterface(){
- // Just go to irc.freenode.net for now
- //client = Util::ReferenceCount< Client >(new Client("irc.freenode.net", 8001));
+ChatInterface::ChatInterface(const std::string & host, int port){
+ //client = Util::ReferenceCount< Client >(new Client(host, port));
//client->connect();
+
+ // Setup window size and chat list
+ int width = Configuration::getScreenWidth();
+ int height = Configuration::getScreenHeight();
+
+ Global::debug(0) << "Current Height: " << height * .8 << " Current Width: " << width *.09 << std::endl;
+
+ // chat panel 80% width 90% height
+ chatBox.location.set(0, 0, 0, 0);
+ chatBox.location.setDimensions(width * .8, height * .9);
+ // edit box
+ inputBox.location.set(0, height * .91, 0, 0);
+ inputBox.location.setDimensions(width * .8, height * .09);
+ // Set the location of user list width * .8 and height
}
ChatInterface::~ChatInterface(){
}
void ChatInterface::act(){
+ chatBox.act(Font::getDefaultFont());
+ inputBox.act(Font::getDefaultFont());
}
void ChatInterface::draw(const Graphics::Bitmap & work){
+ chatBox.render(work);
+ inputBox.render(work);
}
Util::ReferenceCount<Client> ChatInterface::getClient(){
return client;
}
}
}
diff --git a/util/network/irc.h b/util/network/irc.h
index ea6efc3c..4212a957 100644
--- a/util/network/irc.h
+++ b/util/network/irc.h
@@ -1,272 +1,274 @@
#ifndef _util_network_irc_h
#define _util_network_irc_h
#include "network.h"
#include "chat.h"
#include "util/pointer.h"
#include "util/thread.h"
#include "util/gui/tabbed-box.h"
+#include "util/gui/lineedit.h"
#include <string>
#include <vector>
#include <queue>
namespace Network{
namespace IRC{
class Command{
public:
enum Type{
Unknown,
Pass,
Nick,
User,
Server,
Oper,
Quit,
Squit,
Join,
Part,
Mode,
Topic,
Names,
List,
Invite,
Kick,
Version,
Stats,
Links,
Time,
Connect,
Trace,
Admin,
Info,
PrivateMessage,
Notice,
Who,
Whois,
Whowas,
Kill,
Ping,
Pong,
Error,
ErrorNickInUse,
ErrorNoSuchNick,
ErrorNoSuchChannel,
ErrorNeedMoreParams,
ErrorBannedFromChannel,
ErrorInviteOnlyChannel,
ErrorBadChannelKey,
ErrorChannelIsFull,
ReplyNames,
ReplyNamesEndOf,
ReplyNoTopic,
ReplyTopic,
ReplyTopicAuthor,
ReplyMOTD,
ReplyMOTDStart,
ReplyMOTDEndOf,
};
// Initializes it from an incoming message off of socket
Command(const std::string &);
// Create a message with owner and type
Command(const std::string &, const Type &);
Command(const Command &);
virtual ~Command();
virtual const Command & operator=(const Command &);
virtual std::string getSendable() const;
virtual inline const std::string & getOwner() const {
return this->owner;
}
virtual inline const Type & getType() const {
return this->type;
}
virtual inline void setParameters(const std::string & param1){
this->parameters.clear();
this->parameters.push_back(param1);
}
virtual inline void setParameters(const std::string & param1, const std::string & param2){
this->parameters.clear();
this->parameters.push_back(param1);
this->parameters.push_back(param2);
}
virtual inline void setParameters(const std::string & param1, const std::string & param2, const std::string & param3){
this->parameters.clear();
this->parameters.push_back(param1);
this->parameters.push_back(param2);
this->parameters.push_back(param3);
}
virtual inline void setParameters(const std::string & param1, const std::string & param2, const std::string & param3, const std::string & param4){
this->parameters.clear();
this->parameters.push_back(param1);
this->parameters.push_back(param2);
this->parameters.push_back(param3);
this->parameters.push_back(param4);
}
virtual inline void setParameters(const std::vector< std::string > & params){
this->parameters = params;
}
virtual inline const std::vector< std::string > & getParameters() const {
return this->parameters;
}
virtual inline bool hasCtcp() {
return !this->ctcp.empty();
}
virtual inline const std::vector< std::string > & getCtcp() const {
return this->ctcp;
}
protected:
std::string owner;
Type type;
std::vector< std::string > parameters;
std::vector< std::string > ctcp;
};
class Channel{
public:
Channel();
Channel(const std::string &);
Channel(const Channel &);
~Channel();
const Channel & operator=(const Channel &);
void addUser(const std::string &);
void removeUser(const std::string &);
void addUsers(const std::vector<std::string> &);
inline const std::vector<std::string> & getUsers() const{
return this->users;
}
inline const std::string & getName() const {
return this->name;
}
inline void setTopic(const std::string & topic){
this->topic = topic;
}
inline void setTopicAuthor(const std::string & topicAuthor, uint64_t topicDate){
this->topicAuthor = topicAuthor;
this->topicDate = topicDate;
}
protected:
std::string name;
std::string topic;
std::string topicAuthor;
uint64_t topicDate;
std::vector<std::string> users;
};
// Channel ReferenceCount
typedef Util::ReferenceCount<Channel> ChannelPointer;
class Client : public Chat::Threadable{
public:
Client(const std::string &, int port);
virtual ~Client();
virtual void connect();
virtual void run();
virtual bool hasCommands() const;
virtual Command nextCommand() const;
virtual void sendCommand(const Command &);
virtual void sendCommand(const Command::Type &);
virtual void sendCommand(const Command::Type &, const std::string &);
virtual void sendCommand(const Command::Type &, const std::string &, const std::string &);
virtual void sendCommand(const Command::Type &, const std::string &, const std::string &, const std::string &);
virtual void sendCommand(const Command::Type &, const std::string &, const std::string &, const std::string &, const std::string &);
virtual void setName(const std::string &);
virtual inline const std::string & getName() const {
return this->username;
}
virtual void joinChannel(const std::string &);
virtual inline ChannelPointer getChannel() const {
return this->activeChannels[this->currentChannel];
}
virtual inline std::vector< ChannelPointer > & channelList(){
return this->activeChannels;
}
virtual std::string channelListAsString();
virtual unsigned int getChannelIndex(const std::string &);
virtual bool isCurrentChannel(const std::string &);
virtual void setChannel(unsigned int channel);
virtual void nextChannel();
virtual void previousChannel();
virtual void sendMessage(const std::string &);
virtual void sendPong(const Command &);
protected:
void removeChannel(const std::string &);
ChannelPointer findChannel(const std::string &);
std::string readMessage();
//! Doesn't do anything to the command just handle some internal changes like username and channel stuff
void checkResponseAndHandle(const Command &);
Network::Socket socket;
std::string previousUsername;
std::string username;
unsigned int previousActiveChannel;
unsigned int currentChannel;
std::vector< ChannelPointer > activeChannels;
std::string hostname;
int port;
bool end;
mutable std::queue< Command > commands;
};
// Create a tabbed chatter to implement in games
class ChatInterface{
public:
- ChatInterface();
+ ChatInterface(const std::string &, int port);
virtual ~ChatInterface();
void act();
void draw(const Graphics::Bitmap &);
Util::ReferenceCount<Client> getClient();
protected:
Util::ReferenceCount<Client> client;
Gui::TabbedBox chatBox;
+ Gui::LineEdit inputBox;
};
}// end irc
}
#endif
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Tue, Jun 16, 12:07 AM (2 w, 2 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
71182
Default Alt Text
(48 KB)
Attached To
Mode
R75 R-Tech1
Attached
Detach File
Event Timeline