diff --git a/protocols/irc/IrcConstants.h b/protocols/irc/IrcConstants.h index 6ab4f6b..142af01 100644 --- a/protocols/irc/IrcConstants.h +++ b/protocols/irc/IrcConstants.h @@ -9,6 +9,34 @@ enum UserRole { }; +// Formatting information from https://modern.ircdocs.horse/formatting.html +#define FORMAT_BOLD 0x02 +#define FORMAT_COLOR 0x03 +#define FORMAT_RESET 0x0f +#define FORMAT_REVERSE 0x16 +#define FORMAT_ITALIC 0x1d +#define FORMAT_STRIKEOUT 0x1e +#define FORMAT_UNDERSCORE 0x1f + +#define FORMAT_COLOR_COUNT 99 +#define FORMAT_COLORS { 0xFFFFFF, 0x000000, 0x00007F, 0x009300, \ + 0xFF0000, 0x7F0000, 0x9C009C, 0xFC7F00, 0xFFFF00, 0x00FC00, 0x009393, \ + 0x00FFFF, 0x0000FC, 0xFF00FF, 0x7F7F7F, 0xD2D2D2, \ + 0x470000, 0x472100, 0x474700, 0x324700, 0x004700, 0x00472c, 0x004747, \ + 0x002747, 0x000047, 0x2e0047, 0x470047, 0x47002a, 0x740000, 0x743a00, \ + 0x747400, 0x517400, 0x007400, 0x007449, 0x007474, 0x004074, 0x000074, \ + 0x4b0074, 0x740074, 0x740045, 0xb50000, 0xb56300, 0xb5b500, 0x7db500, \ + 0x00b500, 0x00b571, 0x00b5b5, 0x0063b5, 0x0000b5, 0x7500b5, 0xb500b5, \ + 0xb5006b, 0xff0000, 0xff8c00, 0xffff00, 0xb2ff00, 0x00ff00, 0x00ffa0, \ + 0x00ffff, 0x008cff, 0x0000ff, 0xa500ff, 0xff00ff, 0xff0098, 0xff5959, \ + 0xffb459, 0xffff71, 0xcfff60, 0x6fff6f, 0x65ffc9, 0x6dffff, 0x59b4ff, \ + 0x5959ff, 0xc459ff, 0xff66ff, 0xff59bc, 0xff9c9c, 0xffd39c, 0xffff9c, \ + 0xe2ff9c, 0x9cff9c, 0x9cffdb, 0x9cffff, 0x9cd3ff, 0x9c9cff, 0xdc9cff, \ + 0xff9cff, 0xff94d3, 0x000000, 0x131313, 0x282828, 0x363636, 0x4d4d4d, \ + 0x656565, 0x818181, 0x9f9f9f, 0xbcbcbc, 0xe2e2e2, 0xffffff }; + + +// From RFC 2812 #define RPL_WELCOME 1 #define RPL_WHOISUSER 311 #define RPL_ENDOFWHO 315 diff --git a/protocols/irc/IrcProtocol.cpp b/protocols/irc/IrcProtocol.cpp index f52088c..ea9e5bd 100644 --- a/protocols/irc/IrcProtocol.cpp +++ b/protocols/irc/IrcProtocol.cpp @@ -1,5 +1,6 @@ /* * Copyright 2021, Jaidyn Levesque + * Copyright 2017, Akshay Agarwal * All rights reserved. Distributed under the terms of the MIT license. */ @@ -990,10 +991,22 @@ IrcProtocol::_IsChannelName(BString name) #define disable_all_faces(current) { \ - if (bold > -1) _ToggleAndAdd(msg, B_BOLD_FACE, &bold, current); \ - if (italics > -1) _ToggleAndAdd(msg, B_ITALIC_FACE, &italics, current); \ - if (strike > -1) _ToggleAndAdd(msg, B_STRIKEOUT_FACE, &strike, current); \ - if (underline > -1) _ToggleAndAdd(msg, B_UNDERSCORE_FACE, &underline, current); \ + if (bold > -1) _FormatToggleFace(msg, B_BOLD_FACE, &bold, current); \ + if (italics > -1) _FormatToggleFace(msg, B_ITALIC_FACE, &italics, current); \ + if (strike > -1) _FormatToggleFace(msg, B_STRIKEOUT_FACE, &strike, current); \ + if (underline > -1) _FormatToggleFace(msg, B_UNDERSCORE_FACE, &underline, current); \ + if (reverse > -1) _FormatToggleFace(msg, B_NEGATIVE_FACE, &reverse, current); \ +}; + + +#define disable_color(current) { \ + if (colorStart > -1) { \ + msg->AddInt32("color_start", colorStart); \ + msg->AddInt32("color_length", current - colorStart); \ + msg->AddColor("color", _IntToRgb(color)); \ + colorStart = -1; \ + color = -1; \ + } \ }; @@ -1002,26 +1015,72 @@ IrcProtocol::_AddFormatted(BMessage* msg, const char* name, BString text) { BString newText; int32 italics = -1, bold = -1, underline = -1, strike = -1, mono = -1; + int32 reverse = -1; + int32 color = -1, colorStart = -1; int32 length = text.CountBytes(0, text.CountChars()); for (int32 j=0, i=0; j < length; j++) { char c = text.ByteAt(j); switch (c) { - case 0x02: - _ToggleAndAdd(msg, B_BOLD_FACE, &bold, i); + case FORMAT_COLOR: + { + // Apply and reset previous color, if existant + disable_color(i); + + char one = text.ByteAt(j + 1); + char two = text.ByteAt(j + 2); + + // Try and get colors from either two-digits or one-digits + int32 colorIndex = -1; + if (isdigit(one) == true && isdigit(two) == true) { + char num[3] = { one, two, '\0' }; + colorIndex = atoi(num); + if (colorIndex >= 0 && colorIndex <= 99) + j += 2; + } + else if (isdigit(one) == true) { + char num[2] = { one, '\0' }; + colorIndex = atoi(num); + if (colorIndex >= 0 && colorIndex <= 99) + j++; + } + else + break; + + // Use color if valid + if (colorIndex >= 0 && colorIndex <= 99) { + int colors[FORMAT_COLOR_COUNT] = FORMAT_COLORS; + color = colors[colorIndex]; + colorStart = i; + } + + // Ignore setting of background + if (text.ByteAt(j + 1) == ',') + if (isdigit(text.ByteAt(j+2)) && isdigit(text.ByteAt(j+3))) + j += 3; + else if (isdigit(text.ByteAt(j + 2))) + j += 2; break; - case 0x1d: - _ToggleAndAdd(msg, B_ITALIC_FACE, &italics, i); + } + case FORMAT_BOLD: + _FormatToggleFace(msg, B_BOLD_FACE, &bold, i); break; - case 0x1f: - _ToggleAndAdd(msg, B_UNDERSCORE_FACE, &underline, i); + case FORMAT_ITALIC: + _FormatToggleFace(msg, B_ITALIC_FACE, &italics, i); break; - case 0x1e: - _ToggleAndAdd(msg, B_STRIKEOUT_FACE, &strike, i); + case FORMAT_UNDERSCORE: + _FormatToggleFace(msg, B_UNDERSCORE_FACE, &underline, i); break; - case 0x0f: + case FORMAT_STRIKEOUT: + _FormatToggleFace(msg, B_STRIKEOUT_FACE, &strike, i); + break; + case FORMAT_REVERSE: + _FormatToggleFace(msg, B_NEGATIVE_FACE, &reverse, i); + break; + case FORMAT_RESET: disable_all_faces(i); + disable_color(i); break; default: newText << c; @@ -1029,12 +1088,13 @@ IrcProtocol::_AddFormatted(BMessage* msg, const char* name, BString text) } } disable_all_faces(length); + disable_color(length); msg->AddString(name, newText); } void -IrcProtocol::_ToggleAndAdd(BMessage* msg, uint16 face, int32* start, +IrcProtocol::_FormatToggleFace(BMessage* msg, uint16 face, int32* start, int32 current) { if (*start == -1) @@ -1234,6 +1294,16 @@ IrcProtocol::_TrimStringToNewline(BString* str) } +rgb_color +IrcProtocol::_IntToRgb(int rgb) +{ + uint8 r = rgb >> 16; + uint8 g = rgb >> 8 & 0xFF; + uint8 b = rgb & 0xFF; + return (rgb_color){r, g, b}; +} + + BMessage IrcProtocol::_AccountTemplate() { diff --git a/protocols/irc/IrcProtocol.h b/protocols/irc/IrcProtocol.h index da28750..1efd21b 100644 --- a/protocols/irc/IrcProtocol.h +++ b/protocols/irc/IrcProtocol.h @@ -1,5 +1,6 @@ /* * Copyright 2021, Jaidyn Levesque + * Copyright 2017, Akshay Agarwal * All rights reserved. Distributed under the terms of the MIT license. */ #ifndef _IRC_PROTOCOL_H @@ -88,8 +89,8 @@ private: void _AddFormatted(BMessage* msg, const char* name, BString text); - void _ToggleAndAdd(BMessage* msg, uint16 face, int32* start, - int32 current); + void _FormatToggleFace(BMessage* msg, uint16 face, + int32* start, int32 current); void _UpdateContact(BString nick, BString ident, bool online); void _AddContact(BString nick); @@ -110,6 +111,9 @@ private: // Trim given string until newline hit, return trimmed part BString _TrimStringToNewline(BString* str); + // Borrowed from Calendar's ColorConverter + rgb_color _IntToRgb(int rgb); + // GUI templates BMessage _AccountTemplate(); BMessage _RoomTemplate();