//============================================================================= // // File : KviControlCodes.cpp // Creation date : Sat Aug 31 17:07:36 2002 GMT by Szymon Stefanek // // This file is part of the KVIrc IRC client distribution // Copyright (C) 2002-2010 Szymon Stefanek (pragma at kvirc dot net) // // This program is FREE software. You can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the HOPE that it will be USEFUL, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, write to the Free Software Foundation, // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // //============================================================================= #define _KVI_CONTROLCODE_CPP_ #include "KviControlCodes.h" #include namespace KviControlCodes { QString stripControlBytes(const QString & szData) { QString szRet; int i = 0; int iBegin = 0; unsigned char c1; unsigned char c2; while(i < szData.length()) { switch(szData[i].unicode()) { case KviControlCodes::Underline: case KviControlCodes::Bold: case KviControlCodes::Italic: case KviControlCodes::Monospace: case KviControlCodes::Reset: case KviControlCodes::Reverse: case KviControlCodes::CryptEscape: case KviControlCodes::CTCP: case KviControlCodes::Icon: if(i != iBegin) szRet += szData.mid(iBegin, i - iBegin); i++; iBegin = i; break; case KviControlCodes::Color: if(i != iBegin) szRet += szData.mid(iBegin, i - iBegin); i++; i = getUnicodeColorBytes(szData, i, &c1, &c2); iBegin = i; break; default: i++; break; } } if(i != iBegin) szRet += szData.mid(iBegin, i - iBegin); return szRet; } const kvi_wchar_t * getColorBytesW(const kvi_wchar_t * pwData, unsigned char * pcByte1, unsigned char * pcByte2) { // // Scans the pwData for a mIRC color code XX,XX // and fills the color values in the two bytes // //First we can have a digit or a comma if(((*pwData >= '0') && (*pwData <= '9'))) { //Something interesting ok. (*pcByte1) = ((*pwData) - '0'); //store the code pwData++; //and check the next if(((*pwData >= '0') && (*pwData <= '9')) || (*pwData == ',')) { //Yes we can understand it if(*pwData == ',') { //A comma, need to check for background pwData++; } else { //A number //(*pcByte1)=((((*pcByte1)*10)+((*pwData)-'0'))%16); (*pcByte1) = ((*pcByte1) * 10) + ((*pwData) - '0'); pwData++; if(*pwData == ',') { //A comma, need to check for background pwData++; } else { //Senseless return (*pcByte2) = KviControlCodes::NoChange; return pwData; } } } else { //Senseless character control code OK and return (*pcByte2) = KviControlCodes::NoChange; return pwData; } } else { //Senseless character : only a Ctrl+K code (*pcByte1) = KviControlCodes::NoChange; (*pcByte2) = KviControlCodes::NoChange; return pwData; } if((*pwData >= '0') && (*pwData <= '9')) { //Background, a color code (*pcByte2) = (*pwData) - '0'; pwData++; if((*pwData >= '0') && (*pwData <= '9')) { //(*pcByte2)=((((*pcByte2)*10)+((*pwData)-'0'))%16); (*pcByte2) = ((*pcByte2) * 10) + ((*pwData) - '0'); pwData++; } return pwData; } else { (*pcByte2) = KviControlCodes::NoChange; return pwData - 1; } } unsigned int getUnicodeColorBytes(const QString & szData, unsigned int iChar, unsigned char * pcByte1, unsigned char * pcByte2) { // // Scans the szData for a mIRC color code XX,XX // and fills the color values in the two bytes // if(iChar >= (unsigned int)szData.length()) { (*pcByte1) = KviControlCodes::NoChange; (*pcByte2) = KviControlCodes::NoChange; return iChar; } unsigned short c = szData[(int)iChar].unicode(); //First we can have a digit or a comma if(((c < '0') || (c > '9'))) { //Senseless : only a Ctrl+K code (*pcByte1) = KviControlCodes::NoChange; (*pcByte2) = KviControlCodes::NoChange; return iChar; } //Something interesting OK. (*pcByte1) = c - '0'; //store the code iChar++; if(iChar >= (unsigned int)szData.length()) { (*pcByte2) = KviControlCodes::NoChange; return iChar; } c = szData[(int)iChar].unicode(); if(((c < '0') || (c > '9')) && (c != ',')) { (*pcByte2) = KviControlCodes::NoChange; return iChar; } if((c >= '0') && (c <= '9')) { (*pcByte1) = (((*pcByte1) * 10) + (c - '0')); iChar++; if(iChar >= (unsigned int)szData.length()) { (*pcByte2) = KviControlCodes::NoChange; return iChar; } c = szData[(int)iChar].unicode(); } if(c == ',') { iChar++; if(iChar >= (unsigned int)szData.length()) { (*pcByte2) = KviControlCodes::NoChange; return iChar; } c = szData[(int)iChar].unicode(); } else { (*pcByte2) = KviControlCodes::NoChange; return iChar; } if((c < '0') || (c > '9')) { (*pcByte2) = KviControlCodes::NoChange; if(szData[(int)(iChar - 1)].unicode() == ',') return iChar - 1; else return iChar; } //Background, a color code (*pcByte2) = c - '0'; iChar++; if(iChar >= (unsigned int)szData.length()) return iChar; c = szData[(int)iChar].unicode(); if((c >= '0') && (c <= '9')) { (*pcByte2) = (((*pcByte2) * 10) + (c - '0')); iChar++; } return iChar; } #if 0 const char * getColorBytes(const char * pcData, unsigned char * pcByte1, unsigned char * pcByte2) { // // Scans the pcData for a mIRC color code XX,XX // and fills the color values in the two bytes // //First we can have a digit or a comma if(((*pcData >= '0') && (*pcData <='9'))) { //Something interesting ok. (*pcByte1)=(*pcData)-'0'; //store the code pcData++; //and check the next if(((*pcData >= '0') && (*pcData <= '9'))||(*pcData==',')) { //Yes we can understand it if(*pcData==',') { //A comma, need to check for background pcData++; } else { //A number (*pcByte1)=((((*pcByte1)*10)+((*pcData)-'0'))); pcData++; if(*pcData==',') { //A comma, need to check for background pcData++; } else { //Senseless return (*pcByte2)=KviControlCodes::NoChange; return pcData; } } } else { //Senseless character control code OK and return (*pcByte2)=KviControlCodes::NoChange; return pcData; } } else { //Senseless character : only a Ctrl+K code (*pcByte1)=KviControlCodes::NoChange; (*pcByte2)=KviControlCodes::NoChange; return pcData; } if((*pcData >= '0') && (*pcData <='9')) { //Background, a color code (*pcByte2)=(*pcData)-'0'; pcData++; if((*pcData >= '0') && (*pcData <='9')) { (*pcByte2)=((((*pcByte2)*10)+((*pcData)-'0'))); pcData++; } return pcData; } else { (*pcByte2)=KviControlCodes::NoChange; return pcData-1; } } #endif // Get extended (16-98) mIRC color. // Unlike the 0-15 ones, these are not configurable. // https://modern.ircdocs.horse/formatting.html#colors-16-98 // Returns (kvi_u32_t)-1 if index is out of bounds. kvi_u32_t getExtendedColor(int index) { const int minColor = KVI_MIRCCOLOR_MAX + 1; // 16 const int maxColor = KVI_EXTCOLOR_MAX; static const kvi_u32_t colors[maxColor - minColor + 1] = { 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, }; if (index < minColor || index > maxColor) return (kvi_u32_t)-1; return colors[index - minColor]; } }