Skip to content
Snippets Groups Projects
DDMsgReader.js 575 KiB
Newer Older
12001 12002 12003 12004 12005 12006 12007 12008 12009 12010 12011 12012 12013 12014 12015 12016 12017 12018 12019 12020 12021 12022 12023 12024 12025 12026 12027 12028 12029 12030 12031 12032 12033 12034 12035 12036 12037 12038 12039 12040 12041 12042 12043 12044 12045 12046 12047 12048 12049 12050 12051 12052 12053 12054 12055 12056 12057 12058 12059 12060 12061 12062 12063 12064 12065 12066 12067 12068 12069 12070 12071 12072 12073 12074 12075 12076 12077 12078 12079 12080 12081 12082 12083 12084 12085 12086 12087 12088 12089 12090 12091 12092 12093 12094 12095 12096 12097 12098 12099 12100 12101 12102 12103 12104 12105 12106 12107 12108 12109 12110 12111 12112 12113 12114 12115 12116 12117 12118 12119 12120 12121 12122 12123 12124 12125 12126 12127 12128 12129 12130 12131 12132 12133 12134 12135 12136 12137 12138 12139 12140 12141 12142 12143 12144 12145 12146 12147 12148 12149 12150 12151 12152 12153 12154 12155 12156 12157 12158 12159 12160 12161 12162 12163 12164 12165 12166 12167 12168 12169 12170 12171 12172 12173 12174 12175 12176 12177 12178 12179 12180 12181 12182 12183 12184 12185 12186 12187 12188 12189 12190 12191 12192 12193 12194 12195 12196 12197 12198 12199 12200 12201 12202 12203 12204 12205 12206 12207 12208 12209 12210 12211 12212 12213 12214 12215 12216 12217 12218 12219 12220 12221 12222 12223 12224 12225 12226 12227 12228 12229 12230 12231 12232 12233 12234 12235 12236 12237 12238 12239 12240 12241 12242 12243 12244 12245 12246 12247 12248 12249 12250 12251 12252 12253 12254 12255 12256 12257 12258 12259 12260 12261 12262 12263 12264 12265 12266 12267 12268 12269 12270 12271 12272 12273 12274 12275 12276 12277 12278 12279 12280 12281 12282 12283 12284 12285 12286 12287 12288 12289 12290 12291 12292 12293 12294 12295 12296 12297 12298 12299 12300 12301 12302 12303 12304 12305 12306 12307 12308 12309 12310 12311 12312 12313 12314 12315 12316 12317 12318 12319 12320 12321 12322 12323 12324 12325 12326 12327 12328 12329 12330 12331 12332 12333 12334 12335 12336 12337 12338 12339 12340 12341 12342 12343 12344 12345 12346 12347 12348 12349 12350 12351 12352 12353 12354 12355 12356 12357 12358 12359 12360 12361 12362 12363 12364 12365 12366 12367 12368 12369 12370 12371 12372 12373 12374 12375 12376 12377 12378 12379 12380 12381 12382 12383 12384 12385 12386 12387 12388 12389 12390 12391 12392 12393 12394 12395 12396 12397 12398 12399 12400 12401 12402 12403 12404 12405 12406 12407 12408 12409 12410 12411 12412 12413 12414 12415 12416 12417 12418 12419 12420 12421 12422 12423 12424 12425 12426 12427 12428 12429 12430 12431 12432 12433 12434 12435 12436 12437 12438 12439 12440 12441 12442 12443 12444 12445 12446 12447 12448 12449 12450 12451 12452 12453 12454 12455 12456 12457 12458 12459 12460 12461 12462 12463 12464 12465 12466 12467 12468 12469 12470 12471 12472 12473 12474 12475 12476 12477 12478 12479 12480 12481 12482 12483 12484 12485 12486 12487 12488 12489 12490 12491 12492 12493 12494 12495 12496 12497 12498 12499 12500 12501 12502 12503 12504 12505 12506 12507 12508 12509 12510 12511 12512 12513 12514 12515 12516 12517 12518 12519 12520 12521 12522 12523 12524 12525 12526 12527 12528 12529 12530 12531 12532 12533 12534 12535 12536 12537 12538 12539 12540 12541 12542 12543 12544 12545 12546 12547 12548 12549 12550 12551 12552 12553 12554 12555 12556 12557 12558 12559 12560 12561 12562 12563 12564 12565 12566 12567 12568 12569 12570 12571 12572 12573 12574 12575 12576 12577 12578 12579 12580 12581 12582 12583 12584 12585 12586 12587 12588 12589 12590 12591 12592 12593 12594 12595 12596 12597 12598 12599 12600 12601 12602 12603 12604 12605 12606 12607 12608 12609 12610 12611 12612 12613 12614 12615 12616 12617 12618 12619 12620 12621 12622 12623 12624 12625 12626 12627 12628 12629 12630 12631 12632 12633 12634 12635 12636 12637 12638 12639 12640 12641 12642 12643 12644 12645 12646 12647 12648 12649 12650 12651 12652 12653 12654 12655 12656 12657 12658 12659 12660 12661 12662 12663 12664 12665 12666 12667 12668 12669 12670 12671 12672 12673 12674 12675 12676 12677 12678 12679 12680 12681 12682 12683 12684 12685 12686 12687 12688 12689 12690 12691 12692 12693 12694 12695 12696 12697 12698 12699 12700 12701 12702 12703 12704 12705 12706 12707 12708 12709 12710 12711 12712 12713 12714 12715 12716 12717 12718 12719 12720 12721 12722 12723 12724 12725 12726 12727 12728 12729 12730 12731 12732 12733 12734 12735 12736 12737 12738 12739 12740 12741 12742 12743 12744 12745 12746 12747 12748 12749 12750 12751 12752 12753 12754 12755 12756 12757 12758 12759 12760 12761 12762 12763 12764 12765 12766 12767 12768 12769 12770 12771 12772 12773 12774 12775 12776 12777 12778 12779 12780 12781 12782 12783 12784 12785 12786 12787 12788 12789 12790 12791 12792 12793 12794 12795 12796 12797 12798 12799 12800 12801 12802 12803 12804 12805 12806 12807 12808 12809 12810 12811 12812 12813 12814 12815 12816 12817 12818 12819 12820 12821 12822 12823 12824 12825 12826 12827 12828 12829 12830 12831 12832 12833 12834 12835 12836 12837 12838 12839 12840 12841 12842 12843 12844 12845 12846 12847 12848 12849 12850 12851 12852 12853 12854 12855 12856 12857 12858 12859 12860 12861 12862 12863 12864 12865 12866 12867 12868 12869 12870 12871 12872 12873 12874 12875 12876 12877 12878 12879 12880 12881 12882 12883 12884 12885 12886 12887 12888 12889 12890 12891 12892 12893 12894 12895 12896 12897 12898 12899 12900 12901 12902 12903 12904 12905 12906 12907 12908 12909 12910 12911 12912 12913 12914 12915 12916 12917 12918 12919 12920 12921 12922 12923 12924 12925 12926 12927 12928 12929 12930 12931 12932 12933 12934 12935 12936 12937 12938 12939 12940 12941 12942 12943 12944 12945 12946 12947 12948 12949 12950 12951 12952 12953 12954 12955 12956 12957 12958 12959 12960 12961 12962 12963 12964 12965 12966 12967 12968 12969 12970 12971 12972 12973 12974 12975 12976 12977 12978 12979 12980 12981 12982 12983 12984 12985 12986 12987 12988 12989 12990 12991 12992 12993 12994 12995 12996 12997 12998 12999 13000
			startMsgIndex = pStartIndex;
	}
	if (typeof(pEndIndex) == "number")
	{
		if ((pEndIndex >= 0) && (pEndIndex > startMsgIndex) && (pEndIndex <= pMsgbase.total_msgs))
			endMsgIndex = pEndIndex;
	}

	// Define a search function for the message field we're going to search
	var readingPersonalEmailFromUser = (typeof(pListingPersonalEmailFromUser) == "boolean" ? pListingPersonalEmailFromUser : false);
	var matchFn = null;
	switch (pSearchType)
	{
		// It might seem odd to have SEARCH_NONE in here, but it's here because
		// when reading personal email, we need to search for messages only to
		// the current user.
		case SEARCH_NONE:
			if (pSubCode == "mail")
			{
				// Set up the match function slightly differently depending on whether
				// we're looking for mail from the current user or to the current user.
				if (readingPersonalEmailFromUser)
				{
					matchFn = function(pSearchStr, pMsgHdr, pMsgBase, pSubBoardCode) {
						var msgText = strip_ctrl(pMsgBase.get_msg_body(true, pMsgHdr.offset));
						return msgIsFromUser(pMsgHdr);
					}
				}
				else
				{
					matchFn = function(pSearchStr, pMsgHdr, pMsgBase, pSubBoardCode) {
						var msgText = strip_ctrl(pMsgBase.get_msg_body(true, pMsgHdr.offset));
						return msgIsToLoggedInUserNum(pMsgHdr);
					}
				}
			}
			break;
		case SEARCH_KEYWORD:
			matchFn = function(pSearchStr, pMsgHdr, pMsgBase, pSubBoardCode) {
				var msgText = strip_ctrl(pMsgBase.get_msg_body(true, pMsgHdr.offset));
				//return ((pMsgHdr["subject"].toUpperCase().indexOf(pSearchStr) > -1) || (msgText.toUpperCase().indexOf(pSearchStr) > -1));
				var keywordFound = ((pMsgHdr.subject.toUpperCase().indexOf(pSearchStr) > -1) || (msgText.toUpperCase().indexOf(pSearchStr) > -1));
				if (pSubBoardCode == "mail")
					return keywordFound && msgIsToLoggedInUserNum(pMsgHdr);
				else
					return keywordFound;
			}
			break;
		case SEARCH_FROM_NAME:
			matchFn = function(pSearchStr, pMsgHdr, pMsgBase, pSubBoardCode) {
				var fromNameFound = (pMsgHdr.from.toUpperCase() == pSearchStr.toUpperCase());
				if (pSubBoardCode == "mail")
					return fromNameFound && msgIsToLoggedInUserNum(pMsgHdr);
				else
					return fromNameFound;
			}
			break;
		case SEARCH_TO_NAME_CUR_MSG_AREA:
			matchFn = function(pSearchStr, pMsgHdr, pMsgBase, pSubBoardCode) {
				return (pMsgHdr.to.toUpperCase() == pSearchStr);
			}
			break;
		case SEARCH_TO_USER_CUR_MSG_AREA:
		case SEARCH_ALL_TO_USER_SCAN:
			matchFn = function(pSearchStr, pMsgHdr, pMsgBase, pSubBoardCode) {
				// See if the message is not marked as deleted and the 'To' name
				// matches the user's handle, alias, and/or username.
				return (((pMsgHdr.attr & MSG_DELETE) == 0) && userNameHandleAliasMatch(pMsgHdr.to));
			}
			break;
		case SEARCH_TO_USER_NEW_SCAN:
		case SEARCH_TO_USER_NEW_SCAN_CUR_SUB:
		case SEARCH_TO_USER_NEW_SCAN_CUR_GRP:
		case SEARCH_TO_USER_NEW_SCAN_ALL:
			if (pSubCode != "mail")
			{
				// If pStartIndex or pEndIndex aren't specified, then set
				// startMsgIndex to the scan pointer and endMsgIndex to one
				// past the index of the last message in the sub-board
				if (typeof(pStartIndex) != "number")
				{
					// First, write some messages to the log if verbose logging is enabled
					if (gCmdLineArgVals.verboselogging)
					{
						writeToSysAndNodeLog("New-to-user scan for " +
						                   subBoardGrpAndName(pSubCode) + " -- Scan pointer: " +
						                   msg_area.sub[pSubCode].scan_ptr);
					}
					//startMsgIndex = absMsgNumToIdx(pMsgbase, msg_area.sub[pSubCode].last_read);
					startMsgIndex = absMsgNumToIdx(pMsgbase, msg_area.sub[pSubCode].scan_ptr);
					if (startMsgIndex == -1)
					{
						msg_area.sub[pSubCode].scan_ptr = 0;
						startMsgIndex = 0;
					}
				}
				if (typeof(pEndIndex) != "number")
					endMsgIndex = (pMsgbase.total_msgs > 0 ? pMsgbase.total_msgs : 0);
			}
			matchFn = function(pSearchStr, pMsgHdr, pMsgBase, pSubBoardCode) {
				// Note: This assumes pSubBoardCode is not "mail" (personal mail).
				// See if the message 'To' name matches the user's handle, alias,
				// and/or username and is not marked as deleted and is unread.
				return (((pMsgHdr.attr & MSG_DELETE) == 0) && ((pMsgHdr.attr & MSG_READ) == 0) && userNameHandleAliasMatch(pMsgHdr.to));
			}
			break;
		case SEARCH_MSG_NEWSCAN:
		case SEARCH_MSG_NEWSCAN_CUR_SUB:
		case SEARCH_MSG_NEWSCAN_CUR_GRP:
		case SEARCH_MSG_NEWSCAN_ALL:
			matchFn = function(pSearchStr, pMsgHdr, pMsgBase, pSubBoardCode) {
				// Note: This assumes pSubBoardCode is not "mail" (personal mail).
				// Get the offset of the last read message and compare it with the
				// offset of the given message header
				var lastReadMsgHdr = pMsgBase.get_msg_header(false, msg_area.sub[pSubBoardCode].last_read, true);
				var lastReadMsgOffset = (lastReadMsgHdr != null ? lastReadMsgHdr.offset : 0);
				return (pMsgHdr.offset > lastReadMsgOffset);
			}
			break;
	}
	// Search the messages
	if (matchFn != null)
	{
		for (var msgIdx = startMsgIndex; msgIdx < endMsgIndex; ++msgIdx)
		{
			var msgHeader = pMsgbase.get_msg_header(true, msgIdx, true);
			// I've seen situations where the message header object is null for
			// some reason, so check that before running the search function.
			if (msgHeader != null)
			{
				if (matchFn(pSearchString, msgHeader, pMsgbase, pSubCode))
					msgHeaders.indexed.push(msgHeader);
			}
		}
	}
	return msgHeaders;
}

// Returns whether or not a message is to the logged-in user and is not deleted.
//
// Parameters:
//  pMsgHdr: A message header object
//
// Return value: Boolean - Whether or not the message is to the logged-in user
//               and is not deleted.
function msgIsToLoggedInUserNum(pMsgHdr)
{
	if (typeof(pMsgHdr) != "object")
		return false;
	return (((pMsgHdr.attr & MSG_DELETE) == 0) && (pMsgHdr.to_ext == user.number));
}

// Returns whether or not a message is from the logged-in user and is not deleted.
//
// Parameters:
//  pMsgHdr: A message header object
//
// Return value: Boolean - Whether or not the message is from the logged-in user
//               and is not deleted.
function msgIsFromUser(pMsgHdr)
{
	if (typeof(pMsgHdr) != "object")
		return false;
	var isFromCurrentUser = false;
	if (((pMsgHdr.attr & MSG_DELETE) == 0) && pMsgHdr.hasOwnProperty("from_ext"))
		isFromCurrentUser = (pMsgHdr.from_ext == user.number);
	return isFromCurrentUser;
}

/////////////////////////////////////////////////////////////////////////
// Functions for converting other BBS color codes to Synchronet attribute codes

// Converts WWIV attribute codes to Synchronet attribute codes.
//
// Parameters:
//  pText: A string containing the text to convert
//
// Return value: The text with the color codes converted
function WWIVAttrsToSyncAttrs(pText)
{
	// First, see if the text has any WWIV-style attribute codes at
	// all.  We'll be performing a bunch of search & replace commands,
	// so we don't want to do all that work for nothing.. :)
	if (/\x03[0-9]/.test(pText))
	{
		var text = pText.replace(/\x030/g, "\1n");        // Normal
		text = text.replace(/\x031/g, "\1n\1c\1h");     // Bright cyan
		text = text.replace(/\x032/g, "\1n\1y\1h");     // Bright yellow
		text = text.replace(/\x033/g, "\1n\1m");         // Magenta
		text = text.replace(/\x034/g, "\1n\1h\1w\14"); // Bright white on blue
		text = text.replace(/\x035/g, "\1n\1g");         // Green
		text = text.replace(/\x036/g, "\1h\1r\1i");     // Bright red, blinking
		text = text.replace(/\x037/g, "\1n\1h\1b");     // Bright blue
		text = text.replace(/\x038/g, "\1n\1b");         // Blue
		text = text.replace(/\x039/g, "\1n\1c");         // Cyan
		return text;
	}
	else
		return pText; // No WWIV-style color attribute found, so just return the text.
}

// Converts PCBoard attribute codes to Synchronet attribute codes.
//
// Parameters:
//  pText: A string containing the text to convert
//
// Return value: The text with the color codes converted
function PCBoardAttrsToSyncAttrs(pText)
{
	// First, see if the text has any PCBoard-style attribute codes at
	// all.  We'll be performing a bunch of search & replace commands,
	// so we don't want to do all that work for nothing.. :)
	if (/@[xX][0-9A-Fa-f]{2}/.test(pText))
	{
		// Black background
		var text = pText.replace(/@[xX]00/g, "\1n\1k\10"); // Black on black
		text = text.replace(/@[xX]01/g, "\1n\1b\10"); // Blue on black
		text = text.replace(/@[xX]02/g, "\1n\1g\10"); // Green on black
		text = text.replace(/@[xX]03/g, "\1n\1c\10"); // Cyan on black
		text = text.replace(/@[xX]04/g, "\1n\1r\10"); // Red on black
		text = text.replace(/@[xX]05/g, "\1n\1m\10"); // Magenta on black
		text = text.replace(/@[xX]06/g, "\1n\1y\10"); // Yellow/brown on black
		text = text.replace(/@[xX]07/g, "\1n\1w\10"); // White on black
		text = text.replace(/@[xX]08/g, "\1n\1w\10"); // White on black
		text = text.replace(/@[xX]09/g, "\1n\1w\10"); // White on black
		text = text.replace(/@[xX]08/g, "\1h\1k\10"); // Bright black on black
		text = text.replace(/@[xX]09/g, "\1h\1b\10"); // Bright blue on black
		text = text.replace(/@[xX]0[Aa]/g, "\1h\1g\10"); // Bright green on black
		text = text.replace(/@[xX]0[Bb]/g, "\1h\1c\10"); // Bright cyan on black
		text = text.replace(/@[xX]0[Cc]/g, "\1h\1r\10"); // Bright red on black
		text = text.replace(/@[xX]0[Dd]/g, "\1h\1m\10"); // Bright magenta on black
		text = text.replace(/@[xX]0[Ee]/g, "\1h\1y\10"); // Bright yellow on black
		text = text.replace(/@[xX]0[Ff]/g, "\1h\1w\10"); // Bright white on black
		// Blinking foreground

		// Blue background
		text = text.replace(/@[xX]10/g, "\1n\1k\14"); // Black on blue
		text = text.replace(/@[xX]11/g, "\1n\1b\14"); // Blue on blue
		text = text.replace(/@[xX]12/g, "\1n\1g\14"); // Green on blue
		text = text.replace(/@[xX]13/g, "\1n\1c\14"); // Cyan on blue
		text = text.replace(/@[xX]14/g, "\1n\1r\14"); // Red on blue
		text = text.replace(/@[xX]15/g, "\1n\1m\14"); // Magenta on blue
		text = text.replace(/@[xX]16/g, "\1n\1y\14"); // Yellow/brown on blue
		text = text.replace(/@[xX]17/g, "\1n\1w\14"); // White on blue
		text = text.replace(/@[xX]18/g, "\1h\1k\14"); // Bright black on blue
		text = text.replace(/@[xX]19/g, "\1h\1b\14"); // Bright blue on blue
		text = text.replace(/@[xX]1[Aa]/g, "\1h\1g\14"); // Bright green on blue
		text = text.replace(/@[xX]1[Bb]/g, "\1h\1c\14"); // Bright cyan on blue
		text = text.replace(/@[xX]1[Cc]/g, "\1h\1r\14"); // Bright red on blue
		text = text.replace(/@[xX]1[Dd]/g, "\1h\1m\14"); // Bright magenta on blue
		text = text.replace(/@[xX]1[Ee]/g, "\1h\1y\14"); // Bright yellow on blue
		text = text.replace(/@[xX]1[Ff]/g, "\1h\1w\14"); // Bright white on blue

		// Green background
		text = text.replace(/@[xX]20/g, "\1n\1k\12"); // Black on green
		text = text.replace(/@[xX]21/g, "\1n\1b\12"); // Blue on green
		text = text.replace(/@[xX]22/g, "\1n\1g\12"); // Green on green
		text = text.replace(/@[xX]23/g, "\1n\1c\12"); // Cyan on green
		text = text.replace(/@[xX]24/g, "\1n\1r\12"); // Red on green
		text = text.replace(/@[xX]25/g, "\1n\1m\12"); // Magenta on green
		text = text.replace(/@[xX]26/g, "\1n\1y\12"); // Yellow/brown on green
		text = text.replace(/@[xX]27/g, "\1n\1w\12"); // White on green
		text = text.replace(/@[xX]28/g, "\1h\1k\12"); // Bright black on green
		text = text.replace(/@[xX]29/g, "\1h\1b\12"); // Bright blue on green
		text = text.replace(/@[xX]2[Aa]/g, "\1h\1g\12"); // Bright green on green
		text = text.replace(/@[xX]2[Bb]/g, "\1h\1c\12"); // Bright cyan on green
		text = text.replace(/@[xX]2[Cc]/g, "\1h\1r\12"); // Bright red on green
		text = text.replace(/@[xX]2[Dd]/g, "\1h\1m\12"); // Bright magenta on green
		text = text.replace(/@[xX]2[Ee]/g, "\1h\1y\12"); // Bright yellow on green
		text = text.replace(/@[xX]2[Ff]/g, "\1h\1w\12"); // Bright white on green

		// Cyan background
		text = text.replace(/@[xX]30/g, "\1n\1k\16"); // Black on cyan
		text = text.replace(/@[xX]31/g, "\1n\1b\16"); // Blue on cyan
		text = text.replace(/@[xX]32/g, "\1n\1g\16"); // Green on cyan
		text = text.replace(/@[xX]33/g, "\1n\1c\16"); // Cyan on cyan
		text = text.replace(/@[xX]34/g, "\1n\1r\16"); // Red on cyan
		text = text.replace(/@[xX]35/g, "\1n\1m\16"); // Magenta on cyan
		text = text.replace(/@[xX]36/g, "\1n\1y\16"); // Yellow/brown on cyan
		text = text.replace(/@[xX]37/g, "\1n\1w\16"); // White on cyan
		text = text.replace(/@[xX]38/g, "\1h\1k\16"); // Bright black on cyan
		text = text.replace(/@[xX]39/g, "\1h\1b\16"); // Bright blue on cyan
		text = text.replace(/@[xX]3[Aa]/g, "\1h\1g\16"); // Bright green on cyan
		text = text.replace(/@[xX]3[Bb]/g, "\1h\1c\16"); // Bright cyan on cyan
		text = text.replace(/@[xX]3[Cc]/g, "\1h\1r\16"); // Bright red on cyan
		text = text.replace(/@[xX]3[Dd]/g, "\1h\1m\16"); // Bright magenta on cyan
		text = text.replace(/@[xX]3[Ee]/g, "\1h\1y\16"); // Bright yellow on cyan
		text = text.replace(/@[xX]3[Ff]/g, "\1h\1w\16"); // Bright white on cyan

		// Red background
		text = text.replace(/@[xX]40/g, "\1n\1k\11"); // Black on red
		text = text.replace(/@[xX]41/g, "\1n\1b\11"); // Blue on red
		text = text.replace(/@[xX]42/g, "\1n\1g\11"); // Green on red
		text = text.replace(/@[xX]43/g, "\1n\1c\11"); // Cyan on red
		text = text.replace(/@[xX]44/g, "\1n\1r\11"); // Red on red
		text = text.replace(/@[xX]45/g, "\1n\1m\11"); // Magenta on red
		text = text.replace(/@[xX]46/g, "\1n\1y\11"); // Yellow/brown on red
		text = text.replace(/@[xX]47/g, "\1n\1w\11"); // White on red
		text = text.replace(/@[xX]48/g, "\1h\1k\11"); // Bright black on red
		text = text.replace(/@[xX]49/g, "\1h\1b\11"); // Bright blue on red
		text = text.replace(/@[xX]4[Aa]/g, "\1h\1g\11"); // Bright green on red
		text = text.replace(/@[xX]4[Bb]/g, "\1h\1c\11"); // Bright cyan on red
		text = text.replace(/@[xX]4[Cc]/g, "\1h\1r\11"); // Bright red on red
		text = text.replace(/@[xX]4[Dd]/g, "\1h\1m\11"); // Bright magenta on red
		text = text.replace(/@[xX]4[Ee]/g, "\1h\1y\11"); // Bright yellow on red
		text = text.replace(/@[xX]4[Ff]/g, "\1h\1w\11"); // Bright white on red

		// Magenta background
		text = text.replace(/@[xX]50/g, "\1n\1k\15"); // Black on magenta
		text = text.replace(/@[xX]51/g, "\1n\1b\15"); // Blue on magenta
		text = text.replace(/@[xX]52/g, "\1n\1g\15"); // Green on magenta
		text = text.replace(/@[xX]53/g, "\1n\1c\15"); // Cyan on magenta
		text = text.replace(/@[xX]54/g, "\1n\1r\15"); // Red on magenta
		text = text.replace(/@[xX]55/g, "\1n\1m\15"); // Magenta on magenta
		text = text.replace(/@[xX]56/g, "\1n\1y\15"); // Yellow/brown on magenta
		text = text.replace(/@[xX]57/g, "\1n\1w\15"); // White on magenta
		text = text.replace(/@[xX]58/g, "\1h\1k\15"); // Bright black on magenta
		text = text.replace(/@[xX]59/g, "\1h\1b\15"); // Bright blue on magenta
		text = text.replace(/@[xX]5[Aa]/g, "\1h\1g\15"); // Bright green on magenta
		text = text.replace(/@[xX]5[Bb]/g, "\1h\1c\15"); // Bright cyan on magenta
		text = text.replace(/@[xX]5[Cc]/g, "\1h\1r\15"); // Bright red on magenta
		text = text.replace(/@[xX]5[Dd]/g, "\1h\1m\15"); // Bright magenta on magenta
		text = text.replace(/@[xX]5[Ee]/g, "\1h\1y\15"); // Bright yellow on magenta
		text = text.replace(/@[xX]5[Ff]/g, "\1h\1w\15"); // Bright white on magenta

		// Brown background
		text = text.replace(/@[xX]60/g, "\1n\1k\13"); // Black on brown
		text = text.replace(/@[xX]61/g, "\1n\1b\13"); // Blue on brown
		text = text.replace(/@[xX]62/g, "\1n\1g\13"); // Green on brown
		text = text.replace(/@[xX]63/g, "\1n\1c\13"); // Cyan on brown
		text = text.replace(/@[xX]64/g, "\1n\1r\13"); // Red on brown
		text = text.replace(/@[xX]65/g, "\1n\1m\13"); // Magenta on brown
		text = text.replace(/@[xX]66/g, "\1n\1y\13"); // Yellow/brown on brown
		text = text.replace(/@[xX]67/g, "\1n\1w\13"); // White on brown
		text = text.replace(/@[xX]68/g, "\1h\1k\13"); // Bright black on brown
		text = text.replace(/@[xX]69/g, "\1h\1b\13"); // Bright blue on brown
		text = text.replace(/@[xX]6[Aa]/g, "\1h\1g\13"); // Bright breen on brown
		text = text.replace(/@[xX]6[Bb]/g, "\1h\1c\13"); // Bright cyan on brown
		text = text.replace(/@[xX]6[Cc]/g, "\1h\1r\13"); // Bright red on brown
		text = text.replace(/@[xX]6[Dd]/g, "\1h\1m\13"); // Bright magenta on brown
		text = text.replace(/@[xX]6[Ee]/g, "\1h\1y\13"); // Bright yellow on brown
		text = text.replace(/@[xX]6[Ff]/g, "\1h\1w\13"); // Bright white on brown

		// White background
		text = text.replace(/@[xX]70/g, "\1n\1k\17"); // Black on white
		text = text.replace(/@[xX]71/g, "\1n\1b\17"); // Blue on white
		text = text.replace(/@[xX]72/g, "\1n\1g\17"); // Green on white
		text = text.replace(/@[xX]73/g, "\1n\1c\17"); // Cyan on white
		text = text.replace(/@[xX]74/g, "\1n\1r\17"); // Red on white
		text = text.replace(/@[xX]75/g, "\1n\1m\17"); // Magenta on white
		text = text.replace(/@[xX]76/g, "\1n\1y\17"); // Yellow/brown on white
		text = text.replace(/@[xX]77/g, "\1n\1w\17"); // White on white
		text = text.replace(/@[xX]78/g, "\1h\1k\17"); // Bright black on white
		text = text.replace(/@[xX]79/g, "\1h\1b\17"); // Bright blue on white
		text = text.replace(/@[xX]7[Aa]/g, "\1h\1g\17"); // Bright green on white
		text = text.replace(/@[xX]7[Bb]/g, "\1h\1c\17"); // Bright cyan on white
		text = text.replace(/@[xX]7[Cc]/g, "\1h\1r\17"); // Bright red on white
		text = text.replace(/@[xX]7[Dd]/g, "\1h\1m\17"); // Bright magenta on white
		text = text.replace(/@[xX]7[Ee]/g, "\1h\1y\17"); // Bright yellow on white
		text = text.replace(/@[xX]7[Ff]/g, "\1h\1w\17"); // Bright white on white

		// Black background, blinking foreground
		text = text.replace(/@[xX]80/g, "\1n\1k\10\1i"); // Blinking black on black
		text = text.replace(/@[xX]81/g, "\1n\1b\10\1i"); // Blinking blue on black
		text = text.replace(/@[xX]82/g, "\1n\1g\10\1i"); // Blinking green on black
		text = text.replace(/@[xX]83/g, "\1n\1c\10\1i"); // Blinking cyan on black
		text = text.replace(/@[xX]84/g, "\1n\1r\10\1i"); // Blinking red on black
		text = text.replace(/@[xX]85/g, "\1n\1m\10\1i"); // Blinking magenta on black
		text = text.replace(/@[xX]86/g, "\1n\1y\10\1i"); // Blinking yellow/brown on black
		text = text.replace(/@[xX]87/g, "\1n\1w\10\1i"); // Blinking white on black
		text = text.replace(/@[xX]88/g, "\1h\1k\10\1i"); // Blinking bright black on black
		text = text.replace(/@[xX]89/g, "\1h\1b\10\1i"); // Blinking bright blue on black
		text = text.replace(/@[xX]8[Aa]/g, "\1h\1g\10\1i"); // Blinking bright green on black
		text = text.replace(/@[xX]8[Bb]/g, "\1h\1c\10\1i"); // Blinking bright cyan on black
		text = text.replace(/@[xX]8[Cc]/g, "\1h\1r\10\1i"); // Blinking bright red on black
		text = text.replace(/@[xX]8[Dd]/g, "\1h\1m\10\1i"); // Blinking bright magenta on black
		text = text.replace(/@[xX]8[Ee]/g, "\1h\1y\10\1i"); // Blinking bright yellow on black
		text = text.replace(/@[xX]8[Ff]/g, "\1h\1w\10\1i"); // Blinking bright white on black

		// Blue background, blinking foreground
		text = text.replace(/@[xX]90/g, "\1n\1k\14\1i"); // Blinking black on blue
		text = text.replace(/@[xX]91/g, "\1n\1b\14\1i"); // Blinking blue on blue
		text = text.replace(/@[xX]92/g, "\1n\1g\14\1i"); // Blinking green on blue
		text = text.replace(/@[xX]93/g, "\1n\1c\14\1i"); // Blinking cyan on blue
		text = text.replace(/@[xX]94/g, "\1n\1r\14\1i"); // Blinking red on blue
		text = text.replace(/@[xX]95/g, "\1n\1m\14\1i"); // Blinking magenta on blue
		text = text.replace(/@[xX]96/g, "\1n\1y\14\1i"); // Blinking yellow/brown on blue
		text = text.replace(/@[xX]97/g, "\1n\1w\14\1i"); // Blinking white on blue
		text = text.replace(/@[xX]98/g, "\1h\1k\14\1i"); // Blinking bright black on blue
		text = text.replace(/@[xX]99/g, "\1h\1b\14\1i"); // Blinking bright blue on blue
		text = text.replace(/@[xX]9[Aa]/g, "\1h\1g\14\1i"); // Blinking bright green on blue
		text = text.replace(/@[xX]9[Bb]/g, "\1h\1c\14\1i"); // Blinking bright cyan on blue
		text = text.replace(/@[xX]9[Cc]/g, "\1h\1r\14\1i"); // Blinking bright red on blue
		text = text.replace(/@[xX]9[Dd]/g, "\1h\1m\14\1i"); // Blinking bright magenta on blue
		text = text.replace(/@[xX]9[Ee]/g, "\1h\1y\14\1i"); // Blinking bright yellow on blue
		text = text.replace(/@[xX]9[Ff]/g, "\1h\1w\14\1i"); // Blinking bright white on blue

		// Green background, blinking foreground
		text = text.replace(/@[xX][Aa]0/g, "\1n\1k\12\1i"); // Blinking black on green
		text = text.replace(/@[xX][Aa]1/g, "\1n\1b\12\1i"); // Blinking blue on green
		text = text.replace(/@[xX][Aa]2/g, "\1n\1g\12\1i"); // Blinking green on green
		text = text.replace(/@[xX][Aa]3/g, "\1n\1c\12\1i"); // Blinking cyan on green
		text = text.replace(/@[xX][Aa]4/g, "\1n\1r\12\1i"); // Blinking red on green
		text = text.replace(/@[xX][Aa]5/g, "\1n\1m\12\1i"); // Blinking magenta on green
		text = text.replace(/@[xX][Aa]6/g, "\1n\1y\12\1i"); // Blinking yellow/brown on green
		text = text.replace(/@[xX][Aa]7/g, "\1n\1w\12\1i"); // Blinking white on green
		text = text.replace(/@[xX][Aa]8/g, "\1h\1k\12\1i"); // Blinking bright black on green
		text = text.replace(/@[xX][Aa]9/g, "\1h\1b\12\1i"); // Blinking bright blue on green
		text = text.replace(/@[xX][Aa][Aa]/g, "\1h\1g\12\1i"); // Blinking bright green on green
		text = text.replace(/@[xX][Aa][Bb]/g, "\1h\1c\12\1i"); // Blinking bright cyan on green
		text = text.replace(/@[xX][Aa][Cc]/g, "\1h\1r\12\1i"); // Blinking bright red on green
		text = text.replace(/@[xX][Aa][Dd]/g, "\1h\1m\12\1i"); // Blinking bright magenta on green
		text = text.replace(/@[xX][Aa][Ee]/g, "\1h\1y\12\1i"); // Blinking bright yellow on green
		text = text.replace(/@[xX][Aa][Ff]/g, "\1h\1w\12\1i"); // Blinking bright white on green

		// Cyan background, blinking foreground
		text = text.replace(/@[xX][Bb]0/g, "\1n\1k\16\1i"); // Blinking black on cyan
		text = text.replace(/@[xX][Bb]1/g, "\1n\1b\16\1i"); // Blinking blue on cyan
		text = text.replace(/@[xX][Bb]2/g, "\1n\1g\16\1i"); // Blinking green on cyan
		text = text.replace(/@[xX][Bb]3/g, "\1n\1c\16\1i"); // Blinking cyan on cyan
		text = text.replace(/@[xX][Bb]4/g, "\1n\1r\16\1i"); // Blinking red on cyan
		text = text.replace(/@[xX][Bb]5/g, "\1n\1m\16\1i"); // Blinking magenta on cyan
		text = text.replace(/@[xX][Bb]6/g, "\1n\1y\16\1i"); // Blinking yellow/brown on cyan
		text = text.replace(/@[xX][Bb]7/g, "\1n\1w\16\1i"); // Blinking white on cyan
		text = text.replace(/@[xX][Bb]8/g, "\1h\1k\16\1i"); // Blinking bright black on cyan
		text = text.replace(/@[xX][Bb]9/g, "\1h\1b\16\1i"); // Blinking bright blue on cyan
		text = text.replace(/@[xX][Bb][Aa]/g, "\1h\1g\16\1i"); // Blinking bright green on cyan
		text = text.replace(/@[xX][Bb][Bb]/g, "\1h\1c\16\1i"); // Blinking bright cyan on cyan
		text = text.replace(/@[xX][Bb][Cc]/g, "\1h\1r\16\1i"); // Blinking bright red on cyan
		text = text.replace(/@[xX][Bb][Dd]/g, "\1h\1m\16\1i"); // Blinking bright magenta on cyan
		text = text.replace(/@[xX][Bb][Ee]/g, "\1h\1y\16\1i"); // Blinking bright yellow on cyan
		text = text.replace(/@[xX][Bb][Ff]/g, "\1h\1w\16\1i"); // Blinking bright white on cyan

		// Red background, blinking foreground
		text = text.replace(/@[xX][Cc]0/g, "\1n\1k\11\1i"); // Blinking black on red
		text = text.replace(/@[xX][Cc]1/g, "\1n\1b\11\1i"); // Blinking blue on red
		text = text.replace(/@[xX][Cc]2/g, "\1n\1g\11\1i"); // Blinking green on red
		text = text.replace(/@[xX][Cc]3/g, "\1n\1c\11\1i"); // Blinking cyan on red
		text = text.replace(/@[xX][Cc]4/g, "\1n\1r\11\1i"); // Blinking red on red
		text = text.replace(/@[xX][Cc]5/g, "\1n\1m\11\1i"); // Blinking magenta on red
		text = text.replace(/@[xX][Cc]6/g, "\1n\1y\11\1i"); // Blinking yellow/brown on red
		text = text.replace(/@[xX][Cc]7/g, "\1n\1w\11\1i"); // Blinking white on red
		text = text.replace(/@[xX][Cc]8/g, "\1h\1k\11\1i"); // Blinking bright black on red
		text = text.replace(/@[xX][Cc]9/g, "\1h\1b\11\1i"); // Blinking bright blue on red
		text = text.replace(/@[xX][Cc][Aa]/g, "\1h\1g\11\1i"); // Blinking bright green on red
		text = text.replace(/@[xX][Cc][Bb]/g, "\1h\1c\11\1i"); // Blinking bright cyan on red
		text = text.replace(/@[xX][Cc][Cc]/g, "\1h\1r\11\1i"); // Blinking bright red on red
		text = text.replace(/@[xX][Cc][Dd]/g, "\1h\1m\11\1i"); // Blinking bright magenta on red
		text = text.replace(/@[xX][Cc][Ee]/g, "\1h\1y\11\1i"); // Blinking bright yellow on red
		text = text.replace(/@[xX][Cc][Ff]/g, "\1h\1w\11\1i"); // Blinking bright white on red1

		// Magenta background, blinking foreground
		text = text.replace(/@[xX][Dd]0/g, "\1n\1k\15\1i"); // Blinking black on magenta
		text = text.replace(/@[xX][Dd]1/g, "\1n\1b\15\1i"); // Blinking blue on magenta
		text = text.replace(/@[xX][Dd]2/g, "\1n\1g\15\1i"); // Blinking green on magenta
		text = text.replace(/@[xX][Dd]3/g, "\1n\1c\15\1i"); // Blinking cyan on magenta
		text = text.replace(/@[xX][Dd]4/g, "\1n\1r\15\1i"); // Blinking red on magenta
		text = text.replace(/@[xX][Dd]5/g, "\1n\1m\15\1i"); // Blinking magenta on magenta
		text = text.replace(/@[xX][Dd]6/g, "\1n\1y\15\1i"); // Blinking yellow/brown on magenta
		text = text.replace(/@[xX][Dd]7/g, "\1n\1w\15\1i"); // Blinking white on magenta
		text = text.replace(/@[xX][Dd]8/g, "\1h\1k\15\1i"); // Blinking bright black on magenta
		text = text.replace(/@[xX][Dd]9/g, "\1h\1b\15\1i"); // Blinking bright blue on magenta
		text = text.replace(/@[xX][Dd][Aa]/g, "\1h\1g\15\1i"); // Blinking bright green on magenta
		text = text.replace(/@[xX][Dd][Bb]/g, "\1h\1c\15\1i"); // Blinking bright cyan on magenta
		text = text.replace(/@[xX][Dd][Cc]/g, "\1h\1r\15\1i"); // Blinking bright red on magenta
		text = text.replace(/@[xX][Dd][Dd]/g, "\1h\1m\15\1i"); // Blinking bright magenta on magenta
		text = text.replace(/@[xX][Dd][Ee]/g, "\1h\1y\15\1i"); // Blinking bright yellow on magenta
		text = text.replace(/@[xX][Dd][Ff]/g, "\1h\1w\15\1i"); // Blinking bright white on magenta

		// Brown background, blinking foreground
		text = text.replace(/@[xX][Ee]0/g, "\1n\1k\13\1i"); // Blinking black on brown
		text = text.replace(/@[xX][Ee]1/g, "\1n\1b\13\1i"); // Blinking blue on brown
		text = text.replace(/@[xX][Ee]2/g, "\1n\1g\13\1i"); // Blinking green on brown
		text = text.replace(/@[xX][Ee]3/g, "\1n\1c\13\1i"); // Blinking cyan on brown
		text = text.replace(/@[xX][Ee]4/g, "\1n\1r\13\1i"); // Blinking red on brown
		text = text.replace(/@[xX][Ee]5/g, "\1n\1m\13\1i"); // Blinking magenta on brown
		text = text.replace(/@[xX][Ee]6/g, "\1n\1y\13\1i"); // Blinking yellow/brown on brown
		text = text.replace(/@[xX][Ee]7/g, "\1n\1w\13\1i"); // Blinking white on brown
		text = text.replace(/@[xX][Ee]8/g, "\1h\1k\13\1i"); // Blinking bright black on brown
		text = text.replace(/@[xX][Ee]9/g, "\1h\1b\13\1i"); // Blinking bright blue on brown
		text = text.replace(/@[xX][Ee][Aa]/g, "\1h\1g\13\1i"); // Blinking bright green on brown
		text = text.replace(/@[xX][Ee][Bb]/g, "\1h\1c\13\1i"); // Blinking bright cyan on brown
		text = text.replace(/@[xX][Ee][Cc]/g, "\1h\1r\13\1i"); // Blinking bright red on brown
		text = text.replace(/@[xX][Ee][Dd]/g, "\1h\1m\13\1i"); // Blinking bright magenta on brown
		text = text.replace(/@[xX][Ee][Ee]/g, "\1h\1y\13\1i"); // Blinking bright yellow on brown
		text = text.replace(/@[xX][Ee][Ff]/g, "\1h\1w\13\1i"); // Blinking bright white on brown

		// White background, blinking foreground
		text = text.replace(/@[xX][Ff]0/g, "\1n\1k\17\1i"); // Blinking black on white
		text = text.replace(/@[xX][Ff]1/g, "\1n\1b\17\1i"); // Blinking blue on white
		text = text.replace(/@[xX][Ff]2/g, "\1n\1g\17\1i"); // Blinking green on white
		text = text.replace(/@[xX][Ff]3/g, "\1n\1c\17\1i"); // Blinking cyan on white
		text = text.replace(/@[xX][Ff]4/g, "\1n\1r\17\1i"); // Blinking red on white
		text = text.replace(/@[xX][Ff]5/g, "\1n\1m\17\1i"); // Blinking magenta on white
		text = text.replace(/@[xX][Ff]6/g, "\1n\1y\17\1i"); // Blinking yellow/brown on white
		text = text.replace(/@[xX][Ff]7/g, "\1n\1w\17\1i"); // Blinking white on white
		text = text.replace(/@[xX][Ff]8/g, "\1h\1k\17\1i"); // Blinking bright black on white
		text = text.replace(/@[xX][Ff]9/g, "\1h\1b\17\1i"); // Blinking bright blue on white
		text = text.replace(/@[xX][Ff][Aa]/g, "\1h\1g\17\1i"); // Blinking bright green on white
		text = text.replace(/@[xX][Ff][Bb]/g, "\1h\1c\17\1i"); // Blinking bright cyan on white
		text = text.replace(/@[xX][Ff][Cc]/g, "\1h\1r\17\1i"); // Blinking bright red on white
		text = text.replace(/@[xX][Ff][Dd]/g, "\1h\1m\17\1i"); // Blinking bright magenta on white
		text = text.replace(/@[xX][Ff][Ee]/g, "\1h\1y\17\1i"); // Blinking bright yellow on white
		text = text.replace(/@[xX][Ff][Ff]/g, "\1h\1w\17\1i"); // Blinking bright white on white

		return text;
	}
	else
		return pText; // No PCBoard-style attribute codes found, so just return the text.
}

// Converts Wildcat attribute codes to Synchronet attribute codes.
//
// Parameters:
//  pText: A string containing the text to convert
//
// Return value: The text with the color codes converted
function wildcatAttrsToSyncAttrs(pText)
{
	// First, see if the text has any Wildcat-style attribute codes at
	// all.  We'll be performing a bunch of search & replace commands,
	// so we don't want to do all that work for nothing.. :)
	if (/@[0-9A-Fa-f]{2}@/.test(pText))
	{
		// Black background
		var text = pText.replace(/@00@/g, "\1n\1k\10"); // Black on black
		text = text.replace(/@01@/g, "\1n\1b\10"); // Blue on black
		text = text.replace(/@02@/g, "\1n\1g\10"); // Green on black
		text = text.replace(/@03@/g, "\1n\1c\10"); // Cyan on black
		text = text.replace(/@04@/g, "\1n\1r\10"); // Red on black
		text = text.replace(/@05@/g, "\1n\1m\10"); // Magenta on black
		text = text.replace(/@06@/g, "\1n\1y\10"); // Yellow/brown on black
		text = text.replace(/@07@/g, "\1n\1w\10"); // White on black
		text = text.replace(/@08@/g, "\1n\1w\10"); // White on black
		text = text.replace(/@09@/g, "\1n\1w\10"); // White on black
		text = text.replace(/@08@/g, "\1h\1k\10"); // Bright black on black
		text = text.replace(/@09@/g, "\1h\1b\10"); // Bright blue on black
		text = text.replace(/@0[Aa]@/g, "\1h\1g\10"); // Bright green on black
		text = text.replace(/@0[Bb]@/g, "\1h\1c\10"); // Bright cyan on black
		text = text.replace(/@0[Cc]@/g, "\1h\1r\10"); // Bright red on black
		text = text.replace(/@0[Dd]@/g, "\1h\1m\10"); // Bright magenta on black
		text = text.replace(/@0[Ee]@/g, "\1h\1y\10"); // Bright yellow on black
		text = text.replace(/@0[Ff]@/g, "\1h\1w\10"); // Bright white on black
		// Blinking foreground

		// Blue background
		text = text.replace(/@10@/g, "\1n\1k\14"); // Black on blue
		text = text.replace(/@11@/g, "\1n\1b\14"); // Blue on blue
		text = text.replace(/@12@/g, "\1n\1g\14"); // Green on blue
		text = text.replace(/@13@/g, "\1n\1c\14"); // Cyan on blue
		text = text.replace(/@14@/g, "\1n\1r\14"); // Red on blue
		text = text.replace(/@15@/g, "\1n\1m\14"); // Magenta on blue
		text = text.replace(/@16@/g, "\1n\1y\14"); // Yellow/brown on blue
		text = text.replace(/@17@/g, "\1n\1w\14"); // White on blue
		text = text.replace(/@18@/g, "\1h\1k\14"); // Bright black on blue
		text = text.replace(/@19@/g, "\1h\1b\14"); // Bright blue on blue
		text = text.replace(/@1[Aa]@/g, "\1h\1g\14"); // Bright green on blue
		text = text.replace(/@1[Bb]@/g, "\1h\1c\14"); // Bright cyan on blue
		text = text.replace(/@1[Cc]@/g, "\1h\1r\14"); // Bright red on blue
		text = text.replace(/@1[Dd]@/g, "\1h\1m\14"); // Bright magenta on blue
		text = text.replace(/@1[Ee]@/g, "\1h\1y\14"); // Bright yellow on blue
		text = text.replace(/@1[Ff]@/g, "\1h\1w\14"); // Bright white on blue

		// Green background
		text = text.replace(/@20@/g, "\1n\1k\12"); // Black on green
		text = text.replace(/@21@/g, "\1n\1b\12"); // Blue on green
		text = text.replace(/@22@/g, "\1n\1g\12"); // Green on green
		text = text.replace(/@23@/g, "\1n\1c\12"); // Cyan on green
		text = text.replace(/@24@/g, "\1n\1r\12"); // Red on green
		text = text.replace(/@25@/g, "\1n\1m\12"); // Magenta on green
		text = text.replace(/@26@/g, "\1n\1y\12"); // Yellow/brown on green
		text = text.replace(/@27@/g, "\1n\1w\12"); // White on green
		text = text.replace(/@28@/g, "\1h\1k\12"); // Bright black on green
		text = text.replace(/@29@/g, "\1h\1b\12"); // Bright blue on green
		text = text.replace(/@2[Aa]@/g, "\1h\1g\12"); // Bright green on green
		text = text.replace(/@2[Bb]@/g, "\1h\1c\12"); // Bright cyan on green
		text = text.replace(/@2[Cc]@/g, "\1h\1r\12"); // Bright red on green
		text = text.replace(/@2[Dd]@/g, "\1h\1m\12"); // Bright magenta on green
		text = text.replace(/@2[Ee]@/g, "\1h\1y\12"); // Bright yellow on green
		text = text.replace(/@2[Ff]@/g, "\1h\1w\12"); // Bright white on green

		// Cyan background
		text = text.replace(/@30@/g, "\1n\1k\16"); // Black on cyan
		text = text.replace(/@31@/g, "\1n\1b\16"); // Blue on cyan
		text = text.replace(/@32@/g, "\1n\1g\16"); // Green on cyan
		text = text.replace(/@33@/g, "\1n\1c\16"); // Cyan on cyan
		text = text.replace(/@34@/g, "\1n\1r\16"); // Red on cyan
		text = text.replace(/@35@/g, "\1n\1m\16"); // Magenta on cyan
		text = text.replace(/@36@/g, "\1n\1y\16"); // Yellow/brown on cyan
		text = text.replace(/@37@/g, "\1n\1w\16"); // White on cyan
		text = text.replace(/@38@/g, "\1h\1k\16"); // Bright black on cyan
		text = text.replace(/@39@/g, "\1h\1b\16"); // Bright blue on cyan
		text = text.replace(/@3[Aa]@/g, "\1h\1g\16"); // Bright green on cyan
		text = text.replace(/@3[Bb]@/g, "\1h\1c\16"); // Bright cyan on cyan
		text = text.replace(/@3[Cc]@/g, "\1h\1r\16"); // Bright red on cyan
		text = text.replace(/@3[Dd]@/g, "\1h\1m\16"); // Bright magenta on cyan
		text = text.replace(/@3[Ee]@/g, "\1h\1y\16"); // Bright yellow on cyan
		text = text.replace(/@3[Ff]@/g, "\1h\1w\16"); // Bright white on cyan

		// Red background
		text = text.replace(/@40@/g, "\1n\1k\11"); // Black on red
		text = text.replace(/@41@/g, "\1n\1b\11"); // Blue on red
		text = text.replace(/@42@/g, "\1n\1g\11"); // Green on red
		text = text.replace(/@43@/g, "\1n\1c\11"); // Cyan on red
		text = text.replace(/@44@/g, "\1n\1r\11"); // Red on red
		text = text.replace(/@45@/g, "\1n\1m\11"); // Magenta on red
		text = text.replace(/@46@/g, "\1n\1y\11"); // Yellow/brown on red
		text = text.replace(/@47@/g, "\1n\1w\11"); // White on red
		text = text.replace(/@48@/g, "\1h\1k\11"); // Bright black on red
		text = text.replace(/@49@/g, "\1h\1b\11"); // Bright blue on red
		text = text.replace(/@4[Aa]@/g, "\1h\1g\11"); // Bright green on red
		text = text.replace(/@4[Bb]@/g, "\1h\1c\11"); // Bright cyan on red
		text = text.replace(/@4[Cc]@/g, "\1h\1r\11"); // Bright red on red
		text = text.replace(/@4[Dd]@/g, "\1h\1m\11"); // Bright magenta on red
		text = text.replace(/@4[Ee]@/g, "\1h\1y\11"); // Bright yellow on red
		text = text.replace(/@4[Ff]@/g, "\1h\1w\11"); // Bright white on red

		// Magenta background
		text = text.replace(/@50@/g, "\1n\1k\15"); // Black on magenta
		text = text.replace(/@51@/g, "\1n\1b\15"); // Blue on magenta
		text = text.replace(/@52@/g, "\1n\1g\15"); // Green on magenta
		text = text.replace(/@53@/g, "\1n\1c\15"); // Cyan on magenta
		text = text.replace(/@54@/g, "\1n\1r\15"); // Red on magenta
		text = text.replace(/@55@/g, "\1n\1m\15"); // Magenta on magenta
		text = text.replace(/@56@/g, "\1n\1y\15"); // Yellow/brown on magenta
		text = text.replace(/@57@/g, "\1n\1w\15"); // White on magenta
		text = text.replace(/@58@/g, "\1h\1k\15"); // Bright black on magenta
		text = text.replace(/@59@/g, "\1h\1b\15"); // Bright blue on magenta
		text = text.replace(/@5[Aa]@/g, "\1h\1g\15"); // Bright green on magenta
		text = text.replace(/@5[Bb]@/g, "\1h\1c\15"); // Bright cyan on magenta
		text = text.replace(/@5[Cc]@/g, "\1h\1r\15"); // Bright red on magenta
		text = text.replace(/@5[Dd]@/g, "\1h\1m\15"); // Bright magenta on magenta
		text = text.replace(/@5[Ee]@/g, "\1h\1y\15"); // Bright yellow on magenta
		text = text.replace(/@5[Ff]@/g, "\1h\1w\15"); // Bright white on magenta

		// Brown background
		text = text.replace(/@60@/g, "\1n\1k\13"); // Black on brown
		text = text.replace(/@61@/g, "\1n\1b\13"); // Blue on brown
		text = text.replace(/@62@/g, "\1n\1g\13"); // Green on brown
		text = text.replace(/@63@/g, "\1n\1c\13"); // Cyan on brown
		text = text.replace(/@64@/g, "\1n\1r\13"); // Red on brown
		text = text.replace(/@65@/g, "\1n\1m\13"); // Magenta on brown
		text = text.replace(/@66@/g, "\1n\1y\13"); // Yellow/brown on brown
		text = text.replace(/@67@/g, "\1n\1w\13"); // White on brown
		text = text.replace(/@68@/g, "\1h\1k\13"); // Bright black on brown
		text = text.replace(/@69@/g, "\1h\1b\13"); // Bright blue on brown
		text = text.replace(/@6[Aa]@/g, "\1h\1g\13"); // Bright breen on brown
		text = text.replace(/@6[Bb]@/g, "\1h\1c\13"); // Bright cyan on brown
		text = text.replace(/@6[Cc]@/g, "\1h\1r\13"); // Bright red on brown
		text = text.replace(/@6[Dd]@/g, "\1h\1m\13"); // Bright magenta on brown
		text = text.replace(/@6[Ee]@/g, "\1h\1y\13"); // Bright yellow on brown
		text = text.replace(/@6[Ff]@/g, "\1h\1w\13"); // Bright white on brown

		// White background
		text = text.replace(/@70@/g, "\1n\1k\17"); // Black on white
		text = text.replace(/@71@/g, "\1n\1b\17"); // Blue on white
		text = text.replace(/@72@/g, "\1n\1g\17"); // Green on white
		text = text.replace(/@73@/g, "\1n\1c\17"); // Cyan on white
		text = text.replace(/@74@/g, "\1n\1r\17"); // Red on white
		text = text.replace(/@75@/g, "\1n\1m\17"); // Magenta on white
		text = text.replace(/@76@/g, "\1n\1y\17"); // Yellow/brown on white
		text = text.replace(/@77@/g, "\1n\1w\17"); // White on white
		text = text.replace(/@78@/g, "\1h\1k\17"); // Bright black on white
		text = text.replace(/@79@/g, "\1h\1b\17"); // Bright blue on white
		text = text.replace(/@7[Aa]@/g, "\1h\1g\17"); // Bright green on white
		text = text.replace(/@7[Bb]@/g, "\1h\1c\17"); // Bright cyan on white
		text = text.replace(/@7[Cc]@/g, "\1h\1r\17"); // Bright red on white
		text = text.replace(/@7[Dd]@/g, "\1h\1m\17"); // Bright magenta on white
		text = text.replace(/@7[Ee]@/g, "\1h\1y\17"); // Bright yellow on white
		text = text.replace(/@7[Ff]@/g, "\1h\1w\17"); // Bright white on white

		// Black background, blinking foreground
		text = text.replace(/@80@/g, "\1n\1k\10\1i"); // Blinking black on black
		text = text.replace(/@81@/g, "\1n\1b\10\1i"); // Blinking blue on black
		text = text.replace(/@82@/g, "\1n\1g\10\1i"); // Blinking green on black
		text = text.replace(/@83@/g, "\1n\1c\10\1i"); // Blinking cyan on black
		text = text.replace(/@84@/g, "\1n\1r\10\1i"); // Blinking red on black
		text = text.replace(/@85@/g, "\1n\1m\10\1i"); // Blinking magenta on black
		text = text.replace(/@86@/g, "\1n\1y\10\1i"); // Blinking yellow/brown on black
		text = text.replace(/@87@/g, "\1n\1w\10\1i"); // Blinking white on black
		text = text.replace(/@88@/g, "\1h\1k\10\1i"); // Blinking bright black on black
		text = text.replace(/@89@/g, "\1h\1b\10\1i"); // Blinking bright blue on black
		text = text.replace(/@8[Aa]@/g, "\1h\1g\10\1i"); // Blinking bright green on black
		text = text.replace(/@8[Bb]@/g, "\1h\1c\10\1i"); // Blinking bright cyan on black
		text = text.replace(/@8[Cc]@/g, "\1h\1r\10\1i"); // Blinking bright red on black
		text = text.replace(/@8[Dd]@/g, "\1h\1m\10\1i"); // Blinking bright magenta on black
		text = text.replace(/@8[Ee]@/g, "\1h\1y\10\1i"); // Blinking bright yellow on black
		text = text.replace(/@8[Ff]@/g, "\1h\1w\10\1i"); // Blinking bright white on black

		// Blue background, blinking foreground
		text = text.replace(/@90@/g, "\1n\1k\14\1i"); // Blinking black on blue
		text = text.replace(/@91@/g, "\1n\1b\14\1i"); // Blinking blue on blue
		text = text.replace(/@92@/g, "\1n\1g\14\1i"); // Blinking green on blue
		text = text.replace(/@93@/g, "\1n\1c\14\1i"); // Blinking cyan on blue
		text = text.replace(/@94@/g, "\1n\1r\14\1i"); // Blinking red on blue
		text = text.replace(/@95@/g, "\1n\1m\14\1i"); // Blinking magenta on blue
		text = text.replace(/@96@/g, "\1n\1y\14\1i"); // Blinking yellow/brown on blue
		text = text.replace(/@97@/g, "\1n\1w\14\1i"); // Blinking white on blue
		text = text.replace(/@98@/g, "\1h\1k\14\1i"); // Blinking bright black on blue
		text = text.replace(/@99@/g, "\1h\1b\14\1i"); // Blinking bright blue on blue
		text = text.replace(/@9[Aa]@/g, "\1h\1g\14\1i"); // Blinking bright green on blue
		text = text.replace(/@9[Bb]@/g, "\1h\1c\14\1i"); // Blinking bright cyan on blue
		text = text.replace(/@9[Cc]@/g, "\1h\1r\14\1i"); // Blinking bright red on blue
		text = text.replace(/@9[Dd]@/g, "\1h\1m\14\1i"); // Blinking bright magenta on blue
		text = text.replace(/@9[Ee]@/g, "\1h\1y\14\1i"); // Blinking bright yellow on blue
		text = text.replace(/@9[Ff]@/g, "\1h\1w\14\1i"); // Blinking bright white on blue

		// Green background, blinking foreground
		text = text.replace(/@[Aa]0@/g, "\1n\1k\12\1i"); // Blinking black on green
		text = text.replace(/@[Aa]1@/g, "\1n\1b\12\1i"); // Blinking blue on green
		text = text.replace(/@[Aa]2@/g, "\1n\1g\12\1i"); // Blinking green on green
		text = text.replace(/@[Aa]3@/g, "\1n\1c\12\1i"); // Blinking cyan on green
		text = text.replace(/@[Aa]4@/g, "\1n\1r\12\1i"); // Blinking red on green
		text = text.replace(/@[Aa]5@/g, "\1n\1m\12\1i"); // Blinking magenta on green
		text = text.replace(/@[Aa]6@/g, "\1n\1y\12\1i"); // Blinking yellow/brown on green
		text = text.replace(/@[Aa]7@/g, "\1n\1w\12\1i"); // Blinking white on green
		text = text.replace(/@[Aa]8@/g, "\1h\1k\12\1i"); // Blinking bright black on green
		text = text.replace(/@[Aa]9@/g, "\1h\1b\12\1i"); // Blinking bright blue on green
		text = text.replace(/@[Aa][Aa]@/g, "\1h\1g\12\1i"); // Blinking bright green on green
		text = text.replace(/@[Aa][Bb]@/g, "\1h\1c\12\1i"); // Blinking bright cyan on green
		text = text.replace(/@[Aa][Cc]@/g, "\1h\1r\12\1i"); // Blinking bright red on green
		text = text.replace(/@[Aa][Dd]@/g, "\1h\1m\12\1i"); // Blinking bright magenta on green
		text = text.replace(/@[Aa][Ee]@/g, "\1h\1y\12\1i"); // Blinking bright yellow on green
		text = text.replace(/@[Aa][Ff]@/g, "\1h\1w\12\1i"); // Blinking bright white on green

		// Cyan background, blinking foreground
		text = text.replace(/@[Bb]0@/g, "\1n\1k\16\1i"); // Blinking black on cyan
		text = text.replace(/@[Bb]1@/g, "\1n\1b\16\1i"); // Blinking blue on cyan
		text = text.replace(/@[Bb]2@/g, "\1n\1g\16\1i"); // Blinking green on cyan
		text = text.replace(/@[Bb]3@/g, "\1n\1c\16\1i"); // Blinking cyan on cyan
		text = text.replace(/@[Bb]4@/g, "\1n\1r\16\1i"); // Blinking red on cyan
		text = text.replace(/@[Bb]5@/g, "\1n\1m\16\1i"); // Blinking magenta on cyan
		text = text.replace(/@[Bb]6@/g, "\1n\1y\16\1i"); // Blinking yellow/brown on cyan
		text = text.replace(/@[Bb]7@/g, "\1n\1w\16\1i"); // Blinking white on cyan
		text = text.replace(/@[Bb]8@/g, "\1h\1k\16\1i"); // Blinking bright black on cyan
		text = text.replace(/@[Bb]9@/g, "\1h\1b\16\1i"); // Blinking bright blue on cyan
		text = text.replace(/@[Bb][Aa]@/g, "\1h\1g\16\1i"); // Blinking bright green on cyan
		text = text.replace(/@[Bb][Bb]@/g, "\1h\1c\16\1i"); // Blinking bright cyan on cyan
		text = text.replace(/@[Bb][Cc]@/g, "\1h\1r\16\1i"); // Blinking bright red on cyan
		text = text.replace(/@[Bb][Dd]@/g, "\1h\1m\16\1i"); // Blinking bright magenta on cyan
		text = text.replace(/@[Bb][Ee]@/g, "\1h\1y\16\1i"); // Blinking bright yellow on cyan
		text = text.replace(/@[Bb][Ff]@/g, "\1h\1w\16\1i"); // Blinking bright white on cyan

		// Red background, blinking foreground
		text = text.replace(/@[Cc]0@/g, "\1n\1k\11\1i"); // Blinking black on red
		text = text.replace(/@[Cc]1@/g, "\1n\1b\11\1i"); // Blinking blue on red
		text = text.replace(/@[Cc]2@/g, "\1n\1g\11\1i"); // Blinking green on red
		text = text.replace(/@[Cc]3@/g, "\1n\1c\11\1i"); // Blinking cyan on red
		text = text.replace(/@[Cc]4@/g, "\1n\1r\11\1i"); // Blinking red on red
		text = text.replace(/@[Cc]5@/g, "\1n\1m\11\1i"); // Blinking magenta on red
		text = text.replace(/@[Cc]6@/g, "\1n\1y\11\1i"); // Blinking yellow/brown on red
		text = text.replace(/@[Cc]7@/g, "\1n\1w\11\1i"); // Blinking white on red
		text = text.replace(/@[Cc]8@/g, "\1h\1k\11\1i"); // Blinking bright black on red
		text = text.replace(/@[Cc]9@/g, "\1h\1b\11\1i"); // Blinking bright blue on red
		text = text.replace(/@[Cc][Aa]@/g, "\1h\1g\11\1i"); // Blinking bright green on red
		text = text.replace(/@[Cc][Bb]@/g, "\1h\1c\11\1i"); // Blinking bright cyan on red
		text = text.replace(/@[Cc][Cc]@/g, "\1h\1r\11\1i"); // Blinking bright red on red
		text = text.replace(/@[Cc][Dd]@/g, "\1h\1m\11\1i"); // Blinking bright magenta on red
		text = text.replace(/@[Cc][Ee]@/g, "\1h\1y\11\1i"); // Blinking bright yellow on red
		text = text.replace(/@[Cc][Ff]@/g, "\1h\1w\11\1i"); // Blinking bright white on red1

		// Magenta background, blinking foreground
		text = text.replace(/@[Dd]0@/g, "\1n\1k\15\1i"); // Blinking black on magenta
		text = text.replace(/@[Dd]1@/g, "\1n\1b\15\1i"); // Blinking blue on magenta
		text = text.replace(/@[Dd]2@/g, "\1n\1g\15\1i"); // Blinking green on magenta
		text = text.replace(/@[Dd]3@/g, "\1n\1c\15\1i"); // Blinking cyan on magenta
		text = text.replace(/@[Dd]4@/g, "\1n\1r\15\1i"); // Blinking red on magenta
		text = text.replace(/@[Dd]5@/g, "\1n\1m\15\1i"); // Blinking magenta on magenta
		text = text.replace(/@[Dd]6@/g, "\1n\1y\15\1i"); // Blinking yellow/brown on magenta
		text = text.replace(/@[Dd]7@/g, "\1n\1w\15\1i"); // Blinking white on magenta
		text = text.replace(/@[Dd]8@/g, "\1h\1k\15\1i"); // Blinking bright black on magenta
		text = text.replace(/@[Dd]9@/g, "\1h\1b\15\1i"); // Blinking bright blue on magenta
		text = text.replace(/@[Dd][Aa]@/g, "\1h\1g\15\1i"); // Blinking bright green on magenta
		text = text.replace(/@[Dd][Bb]@/g, "\1h\1c\15\1i"); // Blinking bright cyan on magenta
		text = text.replace(/@[Dd][Cc]@/g, "\1h\1r\15\1i"); // Blinking bright red on magenta
		text = text.replace(/@[Dd][Dd]@/g, "\1h\1m\15\1i"); // Blinking bright magenta on magenta
		text = text.replace(/@[Dd][Ee]@/g, "\1h\1y\15\1i"); // Blinking bright yellow on magenta
		text = text.replace(/@[Dd][Ff]@/g, "\1h\1w\15\1i"); // Blinking bright white on magenta

		// Brown background, blinking foreground
		text = text.replace(/@[Ee]0@/g, "\1n\1k\13\1i"); // Blinking black on brown
		text = text.replace(/@[Ee]1@/g, "\1n\1b\13\1i"); // Blinking blue on brown
		text = text.replace(/@[Ee]2@/g, "\1n\1g\13\1i"); // Blinking green on brown
		text = text.replace(/@[Ee]3@/g, "\1n\1c\13\1i"); // Blinking cyan on brown
		text = text.replace(/@[Ee]4@/g, "\1n\1r\13\1i"); // Blinking red on brown
		text = text.replace(/@[Ee]5@/g, "\1n\1m\13\1i"); // Blinking magenta on brown
		text = text.replace(/@[Ee]6@/g, "\1n\1y\13\1i"); // Blinking yellow/brown on brown
		text = text.replace(/@[Ee]7@/g, "\1n\1w\13\1i"); // Blinking white on brown
		text = text.replace(/@[Ee]8@/g, "\1h\1k\13\1i"); // Blinking bright black on brown
		text = text.replace(/@[Ee]9@/g, "\1h\1b\13\1i"); // Blinking bright blue on brown
		text = text.replace(/@[Ee][Aa]@/g, "\1h\1g\13\1i"); // Blinking bright green on brown
		text = text.replace(/@[Ee][Bb]@/g, "\1h\1c\13\1i"); // Blinking bright cyan on brown
		text = text.replace(/@[Ee][Cc]@/g, "\1h\1r\13\1i"); // Blinking bright red on brown
		text = text.replace(/@[Ee][Dd]@/g, "\1h\1m\13\1i"); // Blinking bright magenta on brown
		text = text.replace(/@[Ee][Ee]@/g, "\1h\1y\13\1i"); // Blinking bright yellow on brown
		text = text.replace(/@[Ee][Ff]@/g, "\1h\1w\13\1i"); // Blinking bright white on brown

		// White background, blinking foreground
		text = text.replace(/@[Ff]0@/g, "\1n\1k\17\1i"); // Blinking black on white
		text = text.replace(/@[Ff]1@/g, "\1n\1b\17\1i"); // Blinking blue on white
		text = text.replace(/@[Ff]2@/g, "\1n\1g\17\1i"); // Blinking green on white
		text = text.replace(/@[Ff]3@/g, "\1n\1c\17\1i"); // Blinking cyan on white
		text = text.replace(/@[Ff]4@/g, "\1n\1r\17\1i"); // Blinking red on white
		text = text.replace(/@[Ff]5@/g, "\1n\1m\17\1i"); // Blinking magenta on white
		text = text.replace(/@[Ff]6@/g, "\1n\1y\17\1i"); // Blinking yellow/brown on white
		text = text.replace(/@[Ff]7@/g, "\1n\1w\17\1i"); // Blinking white on white
		text = text.replace(/@[Ff]8@/g, "\1h\1k\17\1i"); // Blinking bright black on white
		text = text.replace(/@[Ff]9@/g, "\1h\1b\17\1i"); // Blinking bright blue on white
		text = text.replace(/@[Ff][Aa]@/g, "\1h\1g\17\1i"); // Blinking bright green on white
		text = text.replace(/@[Ff][Bb]@/g, "\1h\1c\17\1i"); // Blinking bright cyan on white
		text = text.replace(/@[Ff][Cc]@/g, "\1h\1r\17\1i"); // Blinking bright red on white
		text = text.replace(/@[Ff][Dd]@/g, "\1h\1m\17\1i"); // Blinking bright magenta on white
		text = text.replace(/@[Ff][Ee]@/g, "\1h\1y\17\1i"); // Blinking bright yellow on white
		text = text.replace(/@[Ff][Ff]@/g, "\1h\1w\17\1i"); // Blinking bright white on white

		return text;
	}
	else
		return pText; // No Wildcat-style attribute codes found, so just return the text.
}

// Converts Celerity attribute codes to Synchronet attribute codes.
//
// Parameters:
//  pText: A string containing the text to convert
//
// Return value: The text with the color codes converted
function celerityAttrsToSyncAttrs(pText)
{
	// First, see if the text has any Celerity-style attribute codes at
	// all.  We'll be performing a bunch of search & replace commands,
	// so we don't want to do all that work for nothing.. :)
	if (/\|[kbgcrmywdBGCRMYWS]/.test(pText))
	{
		// Using the \|S code (swap foreground & background)

		// Blue background
		var text = pText.replace(/\|b\|S\|k/g, "\1n\1k\14"); // Black on blue
		text = text.replace(/\|b\|S\|b/g, "\1n\1b\14"); // Blue on blue
		text = text.replace(/\|b\|S\|g/g, "\1n\1g\14"); // Green on blue
		text = text.replace(/\|b\|S\|c/g, "\1n\1c\14"); // Cyan on blue
		text = text.replace(/\|b\|S\|r/g, "\1n\1r\14"); // Red on blue
		text = text.replace(/\|b\|S\|m/g, "\1n\1m\14"); // Magenta on blue
		text = text.replace(/\|b\|S\|y/g, "\1n\1y\14"); // Yellow/brown on blue
		text = text.replace(/\|b\|S\|w/g, "\1n\1w\14"); // White on blue
		text = text.replace(/\|b\|S\|d/g, "\1h\1k\14"); // Bright black on blue
		text = text.replace(/\|b\|S\|B/g, "\1h\1b\14"); // Bright blue on blue
		text = text.replace(/\|b\|S\|G/g, "\1h\1g\14"); // Bright green on blue
		text = text.replace(/\|b\|S\|C/g, "\1h\1c\14"); // Bright cyan on blue
		text = text.replace(/\|b\|S\|R/g, "\1h\1r\14"); // Bright red on blue
		text = text.replace(/\|b\|S\|M/g, "\1h\1m\14"); // Bright magenta on blue
		text = text.replace(/\|b\|S\|Y/g, "\1h\1y\14"); // Yellow on blue
		text = text.replace(/\|b\|S\|W/g, "\1h\1w\14"); // Bright white on blue

		// Green background
		text = text.replace(/\|g\|S\|k/g, "\1n\1k\12"); // Black on green
		text = text.replace(/\|g\|S\|b/g, "\1n\1b\12"); // Blue on green
		text = text.replace(/\|g\|S\|g/g, "\1n\1g\12"); // Green on green
		text = text.replace(/\|g\|S\|c/g, "\1n\1c\12"); // Cyan on green
		text = text.replace(/\|g\|S\|r/g, "\1n\1r\12"); // Red on green
		text = text.replace(/\|g\|S\|m/g, "\1n\1m\12"); // Magenta on green
		text = text.replace(/\|g\|S\|y/g, "\1n\1y\12"); // Yellow/brown on green
		text = text.replace(/\|g\|S\|w/g, "\1n\1w\12"); // White on green
		text = text.replace(/\|g\|S\|d/g, "\1h\1k\12"); // Bright black on green
		text = text.replace(/\|g\|S\|B/g, "\1h\1b\12"); // Bright blue on green
		text = text.replace(/\|g\|S\|G/g, "\1h\1g\12"); // Bright green on green
		text = text.replace(/\|g\|S\|C/g, "\1h\1c\12"); // Bright cyan on green
		text = text.replace(/\|g\|S\|R/g, "\1h\1r\12"); // Bright red on green
		text = text.replace(/\|g\|S\|M/g, "\1h\1m\12"); // Bright magenta on green
		text = text.replace(/\|g\|S\|Y/g, "\1h\1y\12"); // Yellow on green
		text = text.replace(/\|g\|S\|W/g, "\1h\1w\12"); // Bright white on green

		// Cyan background
		text = text.replace(/\|c\|S\|k/g, "\1n\1k\16"); // Black on cyan
		text = text.replace(/\|c\|S\|b/g, "\1n\1b\16"); // Blue on cyan
		text = text.replace(/\|c\|S\|g/g, "\1n\1g\16"); // Green on cyan
		text = text.replace(/\|c\|S\|c/g, "\1n\1c\16"); // Cyan on cyan
		text = text.replace(/\|c\|S\|r/g, "\1n\1r\16"); // Red on cyan
		text = text.replace(/\|c\|S\|m/g, "\1n\1m\16"); // Magenta on cyan
		text = text.replace(/\|c\|S\|y/g, "\1n\1y\16"); // Yellow/brown on cyan
		text = text.replace(/\|c\|S\|w/g, "\1n\1w\16"); // White on cyan
		text = text.replace(/\|c\|S\|d/g, "\1h\1k\16"); // Bright black on cyan
		text = text.replace(/\|c\|S\|B/g, "\1h\1b\16"); // Bright blue on cyan
		text = text.replace(/\|c\|S\|G/g, "\1h\1g\16"); // Bright green on cyan
		text = text.replace(/\|c\|S\|C/g, "\1h\1c\16"); // Bright cyan on cyan
		text = text.replace(/\|c\|S\|R/g, "\1h\1r\16"); // Bright red on cyan
		text = text.replace(/\|c\|S\|M/g, "\1h\1m\16"); // Bright magenta on cyan
		text = text.replace(/\|c\|S\|Y/g, "\1h\1y\16"); // Yellow on cyan
		text = text.replace(/\|c\|S\|W/g, "\1h\1w\16"); // Bright white on cyan

		// Red background
		text = text.replace(/\|r\|S\|k/g, "\1n\1k\11"); // Black on red
		text = text.replace(/\|r\|S\|b/g, "\1n\1b\11"); // Blue on red
		text = text.replace(/\|r\|S\|g/g, "\1n\1g\11"); // Green on red
		text = text.replace(/\|r\|S\|c/g, "\1n\1c\11"); // Cyan on red
		text = text.replace(/\|r\|S\|r/g, "\1n\1r\11"); // Red on red
		text = text.replace(/\|r\|S\|m/g, "\1n\1m\11"); // Magenta on red
		text = text.replace(/\|r\|S\|y/g, "\1n\1y\11"); // Yellow/brown on red
		text = text.replace(/\|r\|S\|w/g, "\1n\1w\11"); // White on red
		text = text.replace(/\|r\|S\|d/g, "\1h\1k\11"); // Bright black on red
		text = text.replace(/\|r\|S\|B/g, "\1h\1b\11"); // Bright blue on red
		text = text.replace(/\|r\|S\|G/g, "\1h\1g\11"); // Bright green on red
		text = text.replace(/\|r\|S\|C/g, "\1h\1c\11"); // Bright cyan on red
		text = text.replace(/\|r\|S\|R/g, "\1h\1r\11"); // Bright red on red
		text = text.replace(/\|r\|S\|M/g, "\1h\1m\11"); // Bright magenta on red
		text = text.replace(/\|r\|S\|Y/g, "\1h\1y\11"); // Yellow on red
		text = text.replace(/\|r\|S\|W/g, "\1h\1w\11"); // Bright white on red

		// Magenta background
		text = text.replace(/\|m\|S\|k/g, "\1n\1k\15"); // Black on magenta
		text = text.replace(/\|m\|S\|b/g, "\1n\1b\15"); // Blue on magenta
		text = text.replace(/\|m\|S\|g/g, "\1n\1g\15"); // Green on magenta
		text = text.replace(/\|m\|S\|c/g, "\1n\1c\15"); // Cyan on magenta
		text = text.replace(/\|m\|S\|r/g, "\1n\1r\15"); // Red on magenta
		text = text.replace(/\|m\|S\|m/g, "\1n\1m\15"); // Magenta on magenta
		text = text.replace(/\|m\|S\|y/g, "\1n\1y\15"); // Yellow/brown on magenta
		text = text.replace(/\|m\|S\|w/g, "\1n\1w\15"); // White on magenta
		text = text.replace(/\|m\|S\|d/g, "\1h\1k\15"); // Bright black on magenta
		text = text.replace(/\|m\|S\|B/g, "\1h\1b\15"); // Bright blue on magenta
		text = text.replace(/\|m\|S\|G/g, "\1h\1g\15"); // Bright green on magenta
		text = text.replace(/\|m\|S\|C/g, "\1h\1c\15"); // Bright cyan on magenta
		text = text.replace(/\|m\|S\|R/g, "\1h\1r\15"); // Bright red on magenta
		text = text.replace(/\|m\|S\|M/g, "\1h\1m\15"); // Bright magenta on magenta
		text = text.replace(/\|m\|S\|Y/g, "\1h\1y\15"); // Yellow on magenta
		text = text.replace(/\|m\|S\|W/g, "\1h\1w\15"); // Bright white on magenta

		// Brown background
		text = text.replace(/\|y\|S\|k/g, "\1n\1k\13"); // Black on brown
		text = text.replace(/\|y\|S\|b/g, "\1n\1b\13"); // Blue on brown
		text = text.replace(/\|y\|S\|g/g, "\1n\1g\13"); // Green on brown
		text = text.replace(/\|y\|S\|c/g, "\1n\1c\13"); // Cyan on brown
		text = text.replace(/\|y\|S\|r/g, "\1n\1r\13"); // Red on brown
		text = text.replace(/\|y\|S\|m/g, "\1n\1m\13"); // Magenta on brown
		text = text.replace(/\|y\|S\|y/g, "\1n\1y\13"); // Yellow/brown on brown
		text = text.replace(/\|y\|S\|w/g, "\1n\1w\13"); // White on brown
		text = text.replace(/\|y\|S\|d/g, "\1h\1k\13"); // Bright black on brown
		text = text.replace(/\|y\|S\|B/g, "\1h\1b\13"); // Bright blue on brown
		text = text.replace(/\|y\|S\|G/g, "\1h\1g\13"); // Bright green on brown
		text = text.replace(/\|y\|S\|C/g, "\1h\1c\13"); // Bright cyan on brown
		text = text.replace(/\|y\|S\|R/g, "\1h\1r\13"); // Bright red on brown
		text = text.replace(/\|y\|S\|M/g, "\1h\1m\13"); // Bright magenta on brown
		text = text.replace(/\|y\|S\|Y/g, "\1h\1y\13"); // Yellow on brown
		text = text.replace(/\|y\|S\|W/g, "\1h\1w\13"); // Bright white on brown

		// White background
		text = text.replace(/\|w\|S\|k/g, "\1n\1k\17"); // Black on white
		text = text.replace(/\|w\|S\|b/g, "\1n\1b\17"); // Blue on white
		text = text.replace(/\|w\|S\|g/g, "\1n\1g\17"); // Green on white
		text = text.replace(/\|w\|S\|c/g, "\1n\1c\17"); // Cyan on white
		text = text.replace(/\|w\|S\|r/g, "\1n\1r\17"); // Red on white
		text = text.replace(/\|w\|S\|m/g, "\1n\1m\17"); // Magenta on white
		text = text.replace(/\|w\|S\|y/g, "\1n\1y\17"); // Yellow/brown on white
		text = text.replace(/\|w\|S\|w/g, "\1n\1w\17"); // White on white
		text = text.replace(/\|w\|S\|d/g, "\1h\1k\17"); // Bright black on white
		text = text.replace(/\|w\|S\|B/g, "\1h\1b\17"); // Bright blue on white
		text = text.replace(/\|w\|S\|G/g, "\1h\1g\17"); // Bright green on white
		text = text.replace(/\|w\|S\|C/g, "\1h\1c\17"); // Bright cyan on white
		text = text.replace(/\|w\|S\|R/g, "\1h\1r\17"); // Bright red on white
		text = text.replace(/\|w\|S\|M/g, "\1h\1m\17"); // Bright magenta on white
		text = text.replace(/\|w\|S\|Y/g, "\1h\1y\17"); // Yellow on white
		text = text.replace(/\|w\|S\|W/g, "\1h\1w\17"); // Bright white on white

		// Colors on black background
		text = text.replace(/\|k/g, "\1n\1k\10");  // Black on black
		text = text.replace(/\|k\|S\|k/g, "\1n\1k\10"); // Black on black
		text = text.replace(/\|b/g, "\1n\1b\10");       // Blue on black
		text = text.replace(/\|k\|S\|b/g, "\1n\1b\10"); // Blue on black
		text = text.replace(/\|g/g, "\1n\1g\10");       // Green on black
		text = text.replace(/\|k\|S\|g/g, "\1n\1g\10"); // Green on black
		text = text.replace(/\|c/g, "\1n\1c\10");       // Cyan on black
		text = text.replace(/\|k\|S\|c/g, "\1n\1c\10"); // Cyan on black
		text = text.replace(/\|r/g, "\1n\1r\10");       // Red on black
		text = text.replace(/\|k\|S\|r/g, "\1n\1r\10"); // Red on black
		text = text.replace(/\|m/g, "\1n\1m\10");       // Magenta on black
		text = text.replace(/\|k\|S\|m/g, "\1n\1m\10"); // Magenta on black
		text = text.replace(/\|y/g, "\1n\1y\10");       // Yellow/brown on black
		text = text.replace(/\|k\|S\|y/g, "\1n\1y\10"); // Yellow/brown on black
		text = text.replace(/\|w/g, "\1n\1w\10");       // White on black
		text = text.replace(/\|k\|S\|w/g, "\1n\1w\10"); // White on black
		text = text.replace(/\|d/g, "\1h\1k\10");       // Bright black on black
		text = text.replace(/\|k\|S\|d/g, "\1h\1k\10"); // Bright black on black
		text = text.replace(/\|B/g, "\1h\1b\10");       // Bright blue on black
		text = text.replace(/\|k\|S\|B/g, "\1h\1b\10"); // Bright blue on black
		text = text.replace(/\|G/g, "\1h\1g\10");       // Bright green on black
		text = text.replace(/\|k\|S\|G/g, "\1h\1g\10"); // Bright green on black
		text = text.replace(/\|C/g, "\1h\1c\10");       // Bright cyan on black
		text = text.replace(/\|k\|S\|C/g, "\1h\1c\10"); // Bright cyan on black
		text = text.replace(/\|R/g, "\1h\1r\10");       // Bright red on black
		text = text.replace(/\|k\|S\|R/g, "\1h\1r\10"); // Bright red on black
		text = text.replace(/\|M/g, "\1h\1m\10");       // Bright magenta on black
		text = text.replace(/\|k\|S\|M/g, "\1h\1m\10"); // Bright magenta on black
		text = text.replace(/\|Y/g, "\1h\1y\10");       // Yellow on black
		text = text.replace(/\|k\|S\|Y/g, "\1h\1y\10"); // Yellow on black
		text = text.replace(/\|W/g, "\1h\1w\10");       // Bright white on black
		text = text.replace(/\|k\|S\|W/g, "\1h\1w\10"); // Bright white on black

		return text;
	}
	else
		return pText; // No Celerity-style attribute codes found, so just return the text.