1 //============================================================================= 2 // 3 // File : KviControlCodes.cpp 4 // Creation date : Sat Aug 31 17:07:36 2002 GMT by Szymon Stefanek 5 // 6 // This file is part of the KVIrc IRC client distribution 7 // Copyright (C) 2002-2010 Szymon Stefanek (pragma at kvirc dot net) 8 // 9 // This program is FREE software. You can redistribute it and/or 10 // modify it under the terms of the GNU General Public License 11 // as published by the Free Software Foundation; either version 2 12 // of the License, or (at your option) any later version. 13 // 14 // This program is distributed in the HOPE that it will be USEFUL, 15 // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 17 // See the GNU General Public License for more details. 18 // 19 // You should have received a copy of the GNU General Public License 20 // along with this program. If not, write to the Free Software Foundation, 21 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 22 // 23 //============================================================================= 24 25 #define _KVI_CONTROLCODE_CPP_ 26 27 #include "KviControlCodes.h" 28 29 #include <QString> 30 31 namespace KviControlCodes 32 { stripControlBytes(const QString & szData)33 QString stripControlBytes(const QString & szData) 34 { 35 QString szRet; 36 37 int i = 0; 38 int iBegin = 0; 39 unsigned char c1; 40 unsigned char c2; 41 while(i < szData.length()) 42 { 43 switch(szData[i].unicode()) 44 { 45 case KviControlCodes::Underline: 46 case KviControlCodes::Bold: 47 case KviControlCodes::Italic: 48 case KviControlCodes::Reset: 49 case KviControlCodes::Reverse: 50 case KviControlCodes::CryptEscape: 51 case KviControlCodes::CTCP: 52 case KviControlCodes::Icon: 53 if(i != iBegin) 54 szRet += szData.mid(iBegin, i - iBegin); 55 i++; 56 iBegin = i; 57 break; 58 case KviControlCodes::Color: 59 if(i != iBegin) 60 szRet += szData.mid(iBegin, i - iBegin); 61 i++; 62 i = getUnicodeColorBytes(szData, i, &c1, &c2); 63 iBegin = i; 64 break; 65 default: 66 i++; 67 break; 68 } 69 } 70 if(i != iBegin) 71 szRet += szData.mid(iBegin, i - iBegin); 72 return szRet; 73 } 74 getColorBytesW(const kvi_wchar_t * pwData,unsigned char * pcByte1,unsigned char * pcByte2)75 const kvi_wchar_t * getColorBytesW(const kvi_wchar_t * pwData, unsigned char * pcByte1, unsigned char * pcByte2) 76 { 77 // 78 // Scans the pwData for a mIRC color code XX,XX 79 // and fills the color values in the two bytes 80 // 81 82 //First we can have a digit or a comma 83 if(((*pwData >= '0') && (*pwData <= '9'))) 84 { 85 //Something interesting ok. 86 (*pcByte1) = ((*pwData) - '0'); //store the code 87 pwData++; //and check the next 88 if(((*pwData >= '0') && (*pwData <= '9')) || (*pwData == ',')) 89 { 90 //Yes we can understand it 91 if(*pwData == ',') 92 { 93 //A comma, need to check for background 94 pwData++; 95 } 96 else 97 { 98 //A number 99 //(*pcByte1)=((((*pcByte1)*10)+((*pwData)-'0'))%16); 100 (*pcByte1) = ((*pcByte1) * 10) + ((*pwData) - '0'); 101 pwData++; 102 if(*pwData == ',') 103 { 104 //A comma, need to check for background 105 pwData++; 106 } 107 else 108 { 109 //Senseless return 110 (*pcByte2) = KviControlCodes::NoChange; 111 return pwData; 112 } 113 } 114 } 115 else 116 { 117 //Senseless character control code OK and return 118 (*pcByte2) = KviControlCodes::NoChange; 119 return pwData; 120 } 121 } 122 else 123 { 124 //Senseless character : only a Ctrl+K code 125 (*pcByte1) = KviControlCodes::NoChange; 126 (*pcByte2) = KviControlCodes::NoChange; 127 return pwData; 128 } 129 130 if((*pwData >= '0') && (*pwData <= '9')) 131 { 132 //Background, a color code 133 (*pcByte2) = (*pwData) - '0'; 134 pwData++; 135 if((*pwData >= '0') && (*pwData <= '9')) 136 { 137 //(*pcByte2)=((((*pcByte2)*10)+((*pwData)-'0'))%16); 138 (*pcByte2) = ((*pcByte2) * 10) + ((*pwData) - '0'); 139 pwData++; 140 } 141 return pwData; 142 } 143 else 144 { 145 (*pcByte2) = KviControlCodes::NoChange; 146 return pwData - 1; 147 } 148 } 149 getUnicodeColorBytes(const QString & szData,unsigned int iChar,unsigned char * pcByte1,unsigned char * pcByte2)150 unsigned int getUnicodeColorBytes(const QString & szData, unsigned int iChar, unsigned char * pcByte1, unsigned char * pcByte2) 151 { 152 // 153 // Scans the szData for a mIRC color code XX,XX 154 // and fills the color values in the two bytes 155 // 156 157 if(iChar >= (unsigned int)szData.length()) 158 { 159 (*pcByte1) = KviControlCodes::NoChange; 160 (*pcByte2) = KviControlCodes::NoChange; 161 return iChar; 162 } 163 164 unsigned short c = szData[(int)iChar].unicode(); 165 166 //First we can have a digit or a comma 167 if(((c < '0') || (c > '9'))) 168 { 169 //Senseless : only a Ctrl+K code 170 (*pcByte1) = KviControlCodes::NoChange; 171 (*pcByte2) = KviControlCodes::NoChange; 172 return iChar; 173 } 174 175 //Something interesting OK. 176 (*pcByte1) = c - '0'; //store the code 177 iChar++; 178 if(iChar >= (unsigned int)szData.length()) 179 { 180 (*pcByte2) = KviControlCodes::NoChange; 181 return iChar; 182 } 183 184 c = szData[(int)iChar].unicode(); 185 186 if(((c < '0') || (c > '9')) && (c != ',')) 187 { 188 (*pcByte2) = KviControlCodes::NoChange; 189 return iChar; 190 } 191 192 if((c >= '0') && (c <= '9')) 193 { 194 (*pcByte1) = (((*pcByte1) * 10) + (c - '0')); 195 iChar++; 196 if(iChar >= (unsigned int)szData.length()) 197 { 198 (*pcByte2) = KviControlCodes::NoChange; 199 return iChar; 200 } 201 c = szData[(int)iChar].unicode(); 202 } 203 204 if(c == ',') 205 { 206 iChar++; 207 if(iChar >= (unsigned int)szData.length()) 208 { 209 (*pcByte2) = KviControlCodes::NoChange; 210 return iChar; 211 } 212 c = szData[(int)iChar].unicode(); 213 } 214 else 215 { 216 (*pcByte2) = KviControlCodes::NoChange; 217 return iChar; 218 } 219 220 if((c < '0') || (c > '9')) 221 { 222 (*pcByte2) = KviControlCodes::NoChange; 223 if(szData[(int)(iChar - 1)].unicode() == ',') 224 return iChar - 1; 225 else 226 return iChar; 227 } 228 229 //Background, a color code 230 (*pcByte2) = c - '0'; 231 iChar++; 232 if(iChar >= (unsigned int)szData.length()) 233 return iChar; 234 c = szData[(int)iChar].unicode(); 235 236 if((c >= '0') && (c <= '9')) 237 { 238 (*pcByte2) = (((*pcByte2) * 10) + (c - '0')); 239 iChar++; 240 } 241 242 return iChar; 243 } 244 245 #if 0 246 const char * getColorBytes(const char * pcData, unsigned char * pcByte1, unsigned char * pcByte2) 247 { 248 // 249 // Scans the pcData for a mIRC color code XX,XX 250 // and fills the color values in the two bytes 251 // 252 253 //First we can have a digit or a comma 254 if(((*pcData >= '0') && (*pcData <='9'))) 255 { 256 //Something interesting ok. 257 (*pcByte1)=(*pcData)-'0'; //store the code 258 pcData++; //and check the next 259 if(((*pcData >= '0') && (*pcData <= '9'))||(*pcData==',')) 260 { 261 //Yes we can understand it 262 if(*pcData==',') 263 { 264 //A comma, need to check for background 265 pcData++; 266 } else { 267 //A number 268 (*pcByte1)=((((*pcByte1)*10)+((*pcData)-'0'))); 269 pcData++; 270 if(*pcData==',') 271 { 272 //A comma, need to check for background 273 pcData++; 274 } else { 275 //Senseless return 276 (*pcByte2)=KviControlCodes::NoChange; 277 return pcData; 278 } 279 } 280 } else { 281 //Senseless character control code OK and return 282 (*pcByte2)=KviControlCodes::NoChange; 283 return pcData; 284 } 285 } else { 286 //Senseless character : only a Ctrl+K code 287 (*pcByte1)=KviControlCodes::NoChange; 288 (*pcByte2)=KviControlCodes::NoChange; 289 return pcData; 290 } 291 292 if((*pcData >= '0') && (*pcData <='9')) 293 { 294 //Background, a color code 295 (*pcByte2)=(*pcData)-'0'; 296 pcData++; 297 if((*pcData >= '0') && (*pcData <='9')) 298 { 299 (*pcByte2)=((((*pcByte2)*10)+((*pcData)-'0'))); 300 pcData++; 301 } 302 return pcData; 303 } else { 304 (*pcByte2)=KviControlCodes::NoChange; 305 return pcData-1; 306 } 307 } 308 #endif 309 310 // Get extended (16-98) mIRC color. 311 // Unlike the 0-15 ones, these are not configurable. 312 // https://modern.ircdocs.horse/formatting.html#colors-16-98 313 // Returns (kvi_u32_t)-1 if index is out of bounds. getExtendedColor(int index)314 kvi_u32_t getExtendedColor(int index) 315 { 316 const int minColor = KVI_MIRCCOLOR_MAX + 1; // 16 317 const int maxColor = KVI_EXTCOLOR_MAX; 318 static const kvi_u32_t colors[maxColor - minColor + 1] = { 319 0x470000, 320 0x472100, 321 0x474700, 322 0x324700, 323 0x004700, 324 0x00472c, 325 0x004747, 326 0x002747, 327 0x000047, 328 0x2e0047, 329 0x470047, 330 0x47002a, 331 0x740000, 332 0x743a00, 333 0x747400, 334 0x517400, 335 0x007400, 336 0x007449, 337 0x007474, 338 0x004074, 339 0x000074, 340 0x4b0074, 341 0x740074, 342 0x740045, 343 0xb50000, 344 0xb56300, 345 0xb5b500, 346 0x7db500, 347 0x00b500, 348 0x00b571, 349 0x00b5b5, 350 0x0063b5, 351 0x0000b5, 352 0x7500b5, 353 0xb500b5, 354 0xb5006b, 355 0xff0000, 356 0xff8c00, 357 0xffff00, 358 0xb2ff00, 359 0x00ff00, 360 0x00ffa0, 361 0x00ffff, 362 0x008cff, 363 0x0000ff, 364 0xa500ff, 365 0xff00ff, 366 0xff0098, 367 0xff5959, 368 0xffb459, 369 0xffff71, 370 0xcfff60, 371 0x6fff6f, 372 0x65ffc9, 373 0x6dffff, 374 0x59b4ff, 375 0x5959ff, 376 0xc459ff, 377 0xff66ff, 378 0xff59bc, 379 0xff9c9c, 380 0xffd39c, 381 0xffff9c, 382 0xe2ff9c, 383 0x9cff9c, 384 0x9cffdb, 385 0x9cffff, 386 0x9cd3ff, 387 0x9c9cff, 388 0xdc9cff, 389 0xff9cff, 390 0xff94d3, 391 0x000000, 392 0x131313, 393 0x282828, 394 0x363636, 395 0x4d4d4d, 396 0x656565, 397 0x818181, 398 0x9f9f9f, 399 0xbcbcbc, 400 0xe2e2e2, 401 0xffffff, 402 }; 403 if (index < minColor || index > maxColor) 404 return (kvi_u32_t)-1; 405 return colors[index - minColor]; 406 } 407 } 408