if (c1 && isascii(c1) && (isdigit(c1) || isalpha(c1)))
if (c1 && (XP_IS_DIGIT(c1) || XP_IS_ALPHA(c1)))
char *DIR_Unescape (const char *src, PRBool makeHtml){/* Borrowed from libnet\mkparse.c */#define UNHEX(C) \	((C >= '0' && C <= '9') ? C - '0' : \	((C >= 'A' && C <= 'F') ? C - 'A' + 10 : \	((C >= 'a' && C <= 'f') ? C - 'a' + 10 : 0)))	char *dest = nsnull;	PRUint32 destLength = 0;	PRUint32 dollarCount = 0;	PRUint32 convertedLengthOfDollar = makeHtml ? 4 : 1;	const char *tmpSrc = src;	while (*tmpSrc)		if (*tmpSrc++ == '$')			dollarCount++;	destLength = PL_strlen(src) + (dollarCount * convertedLengthOfDollar);	dest = (char*) PR_Malloc (destLength + 1);	if (dest)	{		char *tmpDst = dest;		*dest = '\0';		tmpSrc = src;		while (*tmpSrc)		{			switch (*tmpSrc)			{			case '$':				/* A dollar sign is a linebreak. This is easy for HTML, but if we're converting				 * for the Address Book or something without multiple lines, just put in a space				 */				if (makeHtml)				{					*tmpDst++ = '<';					*tmpDst++ = 'B';					*tmpDst++ = 'R';					*tmpDst++ = '>';				}				else					*tmpDst++ = ' ';				break;			case '\\': {				/* A backslash indicates that two hex digits follow, which we're supposed to				 * convert. The spec sez that '$', '#' and '\'' (single quote) must be encoded				 * this way. 				 */				PRBool didEscape = PR_FALSE;				char c1 = *(tmpSrc + 1);				if (c1 && isascii(c1) && (isdigit(c1) || isalpha(c1)))				{					char c2 = *(tmpSrc + 2);					if (c2 && isascii(c2) && (isdigit(c2) || isalpha(c2)))					{						*tmpDst++ = (UNHEX(c1) << 4) | UNHEX(c2);						tmpSrc +=2;						didEscape = PR_TRUE;					}				}				if (!didEscape)					*tmpDst++ = *tmpSrc;			}			break;			default:				/* Just a plain old char -- copy it over */				*tmpDst++ = *tmpSrc;			}			tmpSrc++;		}		*tmpDst = '\0';	}	return dest;}