fixed up sort ordering to be more correct.

drawstrings now tint the string, and should now work as expected with ^3 colours.
tweaked qcc's utf-8 parsing. utf-8 chars are now valid in identifiers. invalid chars (like pesky nbsp) are more verbose, and can actually be found.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4667 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2014-05-21 06:21:09 +00:00
parent 23dc0cbe21
commit faae661e9e
8 changed files with 402 additions and 112 deletions

View File

@ -138,7 +138,17 @@ static qboolean SL_TitlesKey (menucustom_t *ths, menu_t *menu, int key)
if (sortkey == SLKEY_ADDRESS)
return true;
Master_SetSortField(sortkey, Master_GetSortField()!=sortkey||!Master_GetSortDescending());
switch(sortkey)
{
case SLKEY_NUMPLAYERS:
//favour descending order (low first)
Master_SetSortField(sortkey, Master_GetSortField()!=sortkey||!Master_GetSortDescending());
break;
default:
//favour ascending order (low first)
Master_SetSortField(sortkey, Master_GetSortField()==sortkey&&!Master_GetSortDescending());
break;
}
return true;
}
@ -679,7 +689,7 @@ void M_Menu_ServerList2_f(void)
CalcFilters(menu);
Master_SetSortField(SLKEY_PING, true);
Master_SetSortField(SLKEY_PING, false);
MasterInfo_Refresh();
}

View File

@ -373,7 +373,7 @@ void Master_ShowServer(serverinfo_t *server)
return;
}
if (!decreasingorder)
if (decreasingorder)
{
for (i = 0; i < numvisibleservers; i++)
{

View File

@ -877,7 +877,12 @@ void QCBUILTIN PF_cvar_string (pubprogfuncs_t *prinst, struct globalvars_s *pr_g
const char *str = PR_GetStringOfs(prinst, OFS_PARM0);
cvar_t *cv = Cvar_Get(str, "", 0, "QC variables");
if (cv)
RETURN_CSTRING(cv->string);
{
if(cv->latched_string)
RETURN_CSTRING(cv->latched_string);
else
RETURN_CSTRING(cv->string);
}
else
G_INT(OFS_RETURN) = 0;
}

View File

@ -253,6 +253,7 @@ static texid_t font_texture;
static int font_colourmask;
static byte_vec4_t font_forecolour;
static byte_vec4_t font_backcolour;
static vec4_t font_foretint;
static struct font_s *curfont;
static float curfont_scale[2];
@ -1618,14 +1619,18 @@ void Font_LineDraw(int x, int y, conchar_t *start, conchar_t *end)
correct usage of this function thus requires calling this with 1111 before Font_EndString*/
void Font_ForceColour(float r, float g, float b, float a)
{
if (font_foretint[0] == r && font_foretint[1] == b && font_foretint[2] == b && font_foretint[3] == a)
return;
if (font_colourmask & CON_NONCLEARBG)
Font_Flush();
font_colourmask = CON_WHITEMASK;
font_forecolour[0] = r*255;
font_forecolour[1] = g*255;
font_forecolour[2] = b*255;
font_forecolour[3] = a*255;
font_foretint[0] = r;
font_foretint[1] = g;
font_foretint[2] = b;
font_foretint[3] = a;
Vector4Scale(font_foretint, 255, font_forecolour);
font_backcolour[3] = 0;
@ -1633,8 +1638,7 @@ void Font_ForceColour(float r, float g, float b, float a)
}
void Font_InvalidateColour(void)
{
Font_Flush();
font_colourmask = ~0;
Font_ForceColour(1,1,1,1);
}
//draw a character from the current font at a pixel location.
@ -1691,26 +1695,40 @@ int Font_DrawChar(int px, int py, unsigned int charcode)
col = charcode & (CON_2NDCHARSETTEXT|CON_RICHFORECOLOUR|(0xfff<<CON_RICHBSHIFT));
if (col != font_colourmask)
{
vec4_t rgba;
if (font_colourmask & CON_NONCLEARBG)
Font_Flush();
font_colourmask = col;
font_forecolour[0] = ((col>>CON_RICHRSHIFT)&0xf)*0x11;
font_forecolour[1] = ((col>>CON_RICHGSHIFT)&0xf)*0x11;
font_forecolour[2] = ((col>>CON_RICHBSHIFT)&0xf)*0x11;
font_forecolour[3] = 255;
rgba[0] = ((col>>CON_RICHRSHIFT)&0xf)*0x11;
rgba[1] = ((col>>CON_RICHGSHIFT)&0xf)*0x11;
rgba[2] = ((col>>CON_RICHBSHIFT)&0xf)*0x11;
rgba[3] = 255;
font_backcolour[0] = 0;
font_backcolour[1] = 0;
font_backcolour[2] = 0;
font_backcolour[3] = 0;
if (charcode & CON_2NDCHARSETTEXT)
{
font_forecolour[0] = min(font_forecolour[0]*1.16, 255);
font_forecolour[1] *= 0.54;
font_forecolour[2] *= 0.41;
rgba[0] *= font->alttint[0];
rgba[1] *= font->alttint[1];
rgba[2] *= font->alttint[2];
}
else
{
rgba[0] *= font->tint[0];
rgba[1] *= font->tint[1];
rgba[2] *= font->tint[2];
}
rgba[0] *= font_foretint[0];
rgba[1] *= font_foretint[1];
rgba[2] *= font_foretint[2];
rgba[3] *= font_foretint[3];
font_forecolour[0] = min(rgba[0], 255);
font_forecolour[1] = min(rgba[1], 255);
font_forecolour[2] = min(rgba[2], 255);
font_forecolour[3] = min(rgba[3], 255);
}
}
else
@ -1718,15 +1736,16 @@ int Font_DrawChar(int px, int py, unsigned int charcode)
col = charcode & (CON_2NDCHARSETTEXT|CON_NONCLEARBG|CON_BGMASK|CON_FGMASK|CON_HALFALPHA);
if (col != font_colourmask)
{
vec4_t rgba;
if ((col ^ font_colourmask) & CON_NONCLEARBG)
Font_Flush();
font_colourmask = col;
col = (charcode&CON_FGMASK)>>CON_FGSHIFT;
font_forecolour[0] = consolecolours[col].fr*255;
font_forecolour[1] = consolecolours[col].fg*255;
font_forecolour[2] = consolecolours[col].fb*255;
font_forecolour[3] = (charcode & CON_HALFALPHA)?127:255;
rgba[0] = consolecolours[col].fr*255;
rgba[1] = consolecolours[col].fg*255;
rgba[2] = consolecolours[col].fb*255;
rgba[3] = (charcode & CON_HALFALPHA)?127:255;
col = (charcode&CON_BGMASK)>>CON_BGSHIFT;
font_backcolour[0] = consolecolours[col].fr*255;
@ -1736,16 +1755,24 @@ int Font_DrawChar(int px, int py, unsigned int charcode)
if (charcode & CON_2NDCHARSETTEXT)
{
font_forecolour[0] = min(font_forecolour[0]*font->alttint[0], 255);
font_forecolour[1] = min(font_forecolour[1]*font->alttint[1], 255);
font_forecolour[2] = min(font_forecolour[2]*font->alttint[2], 255);
rgba[0] *= font->alttint[0];
rgba[1] *= font->alttint[1];
rgba[2] *= font->alttint[2];
}
else
{
font_forecolour[0] = min(font_forecolour[0]*font->tint[0], 255);
font_forecolour[1] = min(font_forecolour[1]*font->tint[1], 255);
font_forecolour[2] = min(font_forecolour[2]*font->tint[2], 255);
rgba[0] *= font->tint[0];
rgba[1] *= font->tint[1];
rgba[2] *= font->tint[2];
}
rgba[0] *= font_foretint[0];
rgba[1] *= font_foretint[1];
rgba[2] *= font_foretint[2];
rgba[3] *= font_foretint[3];
font_forecolour[0] = min(rgba[0], 255);
font_forecolour[1] = min(rgba[1], 255);
font_forecolour[2] = min(rgba[2], 255);
font_forecolour[3] = min(rgba[3], 255);
}
}
@ -1873,14 +1900,15 @@ float Font_DrawScaleChar(float px, float py, unsigned int charcode)
col = charcode & (CON_2NDCHARSETTEXT|CON_RICHFORECOLOUR|(0xfff<<CON_RICHBSHIFT));
if (col != font_colourmask)
{
vec4_t rgba;
if (font_backcolour[3])
Font_Flush();
font_colourmask = col;
font_forecolour[0] = ((col>>CON_RICHRSHIFT)&0xf)*0x11;
font_forecolour[1] = ((col>>CON_RICHGSHIFT)&0xf)*0x11;
font_forecolour[2] = ((col>>CON_RICHBSHIFT)&0xf)*0x11;
font_forecolour[3] = 255;
rgba[0] = ((col>>CON_RICHRSHIFT)&0xf)*0x11;
rgba[1] = ((col>>CON_RICHGSHIFT)&0xf)*0x11;
rgba[2] = ((col>>CON_RICHBSHIFT)&0xf)*0x11;
rgba[3] = 255;
font_backcolour[0] = 0;
font_backcolour[1] = 0;
@ -1889,10 +1917,24 @@ float Font_DrawScaleChar(float px, float py, unsigned int charcode)
if (charcode & CON_2NDCHARSETTEXT)
{
font_forecolour[0] = min(font_forecolour[0]*1.16, 255);
font_forecolour[1] *= 0.54;
font_forecolour[2] *= 0.41;
rgba[0] *= font->alttint[0];
rgba[1] *= font->alttint[1];
rgba[2] *= font->alttint[2];
}
else
{
rgba[0] *= font->tint[0];
rgba[1] *= font->tint[1];
rgba[2] *= font->tint[2];
}
rgba[0] *= font_foretint[0];
rgba[1] *= font_foretint[1];
rgba[2] *= font_foretint[2];
rgba[3] *= font_foretint[3];
font_forecolour[0] = min(rgba[0], 255);
font_forecolour[1] = min(rgba[1], 255);
font_forecolour[2] = min(rgba[2], 255);
font_forecolour[3] = min(rgba[3], 255);
}
}
else
@ -1900,15 +1942,16 @@ float Font_DrawScaleChar(float px, float py, unsigned int charcode)
col = charcode & (CON_2NDCHARSETTEXT|CON_NONCLEARBG|CON_BGMASK|CON_FGMASK|CON_HALFALPHA);
if (col != font_colourmask)
{
vec4_t rgba;
if (font_backcolour[3] != ((charcode & CON_NONCLEARBG)?127:0))
Font_Flush();
font_colourmask = col;
col = (charcode&CON_FGMASK)>>CON_FGSHIFT;
font_forecolour[0] = consolecolours[col].fr*255;
font_forecolour[1] = consolecolours[col].fg*255;
font_forecolour[2] = consolecolours[col].fb*255;
font_forecolour[3] = (charcode & CON_HALFALPHA)?127:255;
rgba[0] = consolecolours[col].fr*255;
rgba[1] = consolecolours[col].fg*255;
rgba[2] = consolecolours[col].fb*255;
rgba[3] = (charcode & CON_HALFALPHA)?127:255;
col = (charcode&CON_BGMASK)>>CON_BGSHIFT;
font_backcolour[0] = consolecolours[col].fr*255;
@ -1918,16 +1961,24 @@ float Font_DrawScaleChar(float px, float py, unsigned int charcode)
if (charcode & CON_2NDCHARSETTEXT)
{
font_forecolour[0] = min(font_forecolour[0]*font->alttint[0], 255);
font_forecolour[1] = min(font_forecolour[1]*font->alttint[1], 255);
font_forecolour[2] = min(font_forecolour[2]*font->alttint[2], 255);
rgba[0] *= font->alttint[0];
rgba[1] *= font->alttint[1];
rgba[2] *= font->alttint[2];
}
else
{
font_forecolour[0] = min(font_forecolour[0]*font->tint[0], 255);
font_forecolour[1] = min(font_forecolour[1]*font->tint[1], 255);
font_forecolour[2] = min(font_forecolour[2]*font->tint[2], 255);
rgba[0] *= font->tint[0];
rgba[1] *= font->tint[1];
rgba[2] *= font->tint[2];
}
rgba[0] *= font_foretint[0];
rgba[1] *= font_foretint[1];
rgba[2] *= font_foretint[2];
rgba[3] *= font_foretint[3];
font_forecolour[0] = min(rgba[0], 255);
font_forecolour[1] = min(rgba[1], 255);
font_forecolour[2] = min(rgba[2], 255);
font_forecolour[3] = min(rgba[3], 255);
}
}

View File

@ -95,6 +95,8 @@ long ParseNum (char *str);
char *QCC_COM_Parse (const char *data);
char *QCC_COM_Parse2 (char *data);
unsigned int utf8_check(const void *in, unsigned int *value);
extern char qcc_token[1024];
extern int qcc_eof;

View File

@ -874,9 +874,54 @@ enum
UTF32LE,
UTF32BE,
};
//return 0 if the input is not valid utf-8.
unsigned int utf8_check(const void *in, unsigned int *value)
{
//uc is the output unicode char
unsigned int uc = 0xfffdu; //replacement character
const unsigned char *str = in;
if (!(*str & 0x80))
{
*value = *str;
return 1;
}
else if ((*str & 0xe0) == 0xc0)
{
if ((str[1] & 0xc0) == 0x80)
{
*value = uc = ((str[0] & 0x1f)<<6) | (str[1] & 0x3f);
if (!uc || uc >= (1u<<7)) //allow modified utf-8
return 2;
}
}
else if ((*str & 0xf0) == 0xe0)
{
if ((str[1] & 0xc0) == 0x80 && (str[2] & 0xc0) == 0x80)
{
*value = uc = ((str[0] & 0x0f)<<12) | ((str[1] & 0x3f)<<6) | ((str[2] & 0x3f)<<0);
if (uc >= (1u<<11))
return 3;
}
}
else if ((*str & 0xf8) == 0xf0)
{
if ((str[1] & 0xc0) == 0x80 && (str[2] & 0xc0) == 0x80 && (str[3] & 0xc0) == 0x80)
{
*value = uc = ((str[0] & 0x07)<<18) | ((str[1] & 0x3f)<<12) | ((str[2] & 0x3f)<<6) | ((str[3] & 0x3f)<<0);
if (uc >= (1u<<16)) //overlong
if (uc <= 0x10ffff) //aand we're not allowed to exceed utf-16 surrogates.
return 4;
}
}
*value = 0xFFFD;
return 0;
}
//read utf-16 chars and output the 'native' utf-8.
//we don't expect essays written in code, so we don't need much actual support for utf-8.
static char *decodeUTF(int type, unsigned char *inputf, unsigned int inbytes, int *outlen)
static char *decodeUTF(int type, unsigned char *inputf, unsigned int inbytes, int *outlen, pbool usemalloc)
{
char *utf8, *start;
unsigned int inc;
@ -905,7 +950,10 @@ static char *decodeUTF(int type, unsigned char *inputf, unsigned int inbytes, in
return inputf;
}
chars = inbytes / w;
utf8 = start = qccHunkAlloc(chars * maxperchar + 2);
if (usemalloc)
utf8 = start = malloc(chars * maxperchar + 2);
else
utf8 = start = qccHunkAlloc(chars * maxperchar + 2);
for (i = 0; i < chars; i++)
{
switch(type)
@ -981,6 +1029,62 @@ static char *decodeUTF(int type, unsigned char *inputf, unsigned int inbytes, in
return start;
}
//the gui is a windows program.
//this means that its fucked.
//on the plus side, its okay with a bom...
unsigned short *QCC_makeutf16(char *mem, unsigned int len, int *outlen)
{
unsigned int code;
int l;
unsigned short *out, *outstart;
//sanitise the input.
if (len >= 4 && mem[0] == '\xff' && mem[1] == '\xfe' && mem[2] == '\x00' && mem[3] == '\x00')
mem = decodeUTF(UTF32LE, (unsigned char*)mem+4, len-4, &len, true);
else if (len >= 4 && mem[0] == '\x00' && mem[1] == '\x00' && mem[2] == '\xfe' && mem[3] == '\xff')
mem = decodeUTF(UTF32BE, (unsigned char*)mem+4, len-4, &len, true);
else if (len >= 2 && mem[0] == '\xff' && mem[1] == '\xfe')
{
//already utf8, just return it as-is
out = malloc(len+3);
memcpy(out, mem, len);
out[len/2] = 0;
return out;
//mem = decodeUTF(UTF16LE, (unsigned char*)mem+2, len-2, &len, false);
}
else if (len >= 2 && mem[0] == '\xfe' && mem[1] == '\xff')
mem = decodeUTF(UTF16BE, (unsigned char*)mem+2, len-2, &len, false);
//utf-8 BOM, for compat with broken text editors (like windows notepad).
else if (len >= 3 && mem[0] == '\xef' && mem[1] == '\xbb' && mem[2] == '\xbf')
{
mem += 3;
len -= 3;
}
outstart = malloc(len*2+3);
out = outstart;
while(len)
{
l = utf8_check(mem, &code);
if (!l)
{l = 1; code = 0xe000|(unsigned char)*mem;}//fucked up. convert to 0xe000 private-use range.
len -= l;
mem += l;
if (code > 0xffff)
{
code -= 0x10000;
*out++ = 0xd800u | ((code>>10) & 0x3ff);
// *out++ = 0xdc00u | ((code>>00) & 0x3ff);
}
else
*out++ = code;
}
if (outlen)
*outlen = out - outstart;
*out++ = 0;
return outstart;
}
long QCC_LoadFile (char *filename, void **bufferptr)
{
char *mem;
@ -1002,13 +1106,13 @@ long QCC_LoadFile (char *filename, void **bufferptr)
externs->ReadFile(filename, mem, len+2);
if (len >= 4 && mem[0] == '\xff' && mem[1] == '\xfe' && mem[2] == '\x00' && mem[3] == '\x00')
mem = decodeUTF(UTF32LE, (unsigned char*)mem+4, len-4, &len);
mem = decodeUTF(UTF32LE, (unsigned char*)mem+4, len-4, &len, false);
else if (len >= 4 && mem[0] == '\x00' && mem[1] == '\x00' && mem[2] == '\xfe' && mem[3] == '\xff')
mem = decodeUTF(UTF32BE, (unsigned char*)mem+4, len-4, &len);
mem = decodeUTF(UTF32BE, (unsigned char*)mem+4, len-4, &len, false);
else if (len >= 2 && mem[0] == '\xff' && mem[1] == '\xfe')
mem = decodeUTF(UTF16LE, (unsigned char*)mem+2, len-2, &len);
mem = decodeUTF(UTF16LE, (unsigned char*)mem+2, len-2, &len, false);
else if (len >= 2 && mem[0] == '\xfe' && mem[1] == '\xff')
mem = decodeUTF(UTF16BE, (unsigned char*)mem+2, len-2, &len);
mem = decodeUTF(UTF16BE, (unsigned char*)mem+2, len-2, &len, false);
//utf-8 BOM, for compat with broken text editors (like windows notepad).
else if (len >= 3 && mem[0] == '\xef' && mem[1] == '\xbb' && mem[2] == '\xbf')
{

View File

@ -392,6 +392,12 @@ static void QCC_PR_SkipToEndOfLine(pbool errorifnonwhite)
{
handleccomments = false;
pr_file_p += 2;
/*while(*pr_file_p)
{
if (*pr_file_p == '\n')
break;
pr_file_p++;
}*/
}
else if (*pr_file_p == '\\' && pr_file_p[1] == '\r' && pr_file_p[2] == '\n')
{ /*windows endings*/
@ -1329,6 +1335,7 @@ void QCC_PR_LexString (void)
char *end, *cnst;
int raw;
char rawdelim[64];
int code;
int texttype;
pbool first = true;
@ -1389,6 +1396,14 @@ void QCC_PR_LexString (void)
if (!c)
QCC_PR_ParseError (ERR_EOF, "EOF inside quote");
if (!qccwarningaction[WARN_NOTUTF8] && c < 0 && utf8_check(&pr_token[c-1], &code))
{
//convert 0xe000 private-use area to quake's charset (if they don't have the utf-8 warning enabled)
//note: this may have a small false-positive risk.
if (code >= 0xe000 && code <= 0xe0ff)
pr_file_p += utf8_check(&pr_token[c-1], &code)-1;
}
/* //these two conditions are generally part of the C preprocessor.
if (c == '\\' && *pr_file_p == '\r' && pr_file_p[1] == '\n')
{ //dos format
@ -1651,42 +1666,15 @@ void QCC_PR_LexString (void)
if (qccwarningaction[WARN_NOTUTF8])
{
len = 0;
//this doesn't do over-long checks.
for (c = 0; pr_token[c]; c++)
{
if (len)
len = utf8_check(&pr_token[c], &code);
if (!len)
{
if ((pr_token[c] & 0xc0) != 0x80)
break;
len--;
}
else if (pr_token[c] & 0x80)
{
if (!(pr_token[c] & 0x40))
{
//error.
len = 1;
break;
}
else if (!(pr_token[c] & 0x20))
len = 2;
else if (!(pr_token[c] & 0x10))
len = 3;
else if (!(pr_token[c] & 0x08))
len = 4;
else if (!(pr_token[c] & 0x04))
len = 5;
else if (!(pr_token[c] & 0x02))
len = 6;
else if (!(pr_token[c] & 0x01))
len = 7;
else
len = 8;
QCC_PR_ParseWarning(WARN_NOTUTF8, "String constant is not valid utf-8");
break;
}
}
if (len)
QCC_PR_ParseWarning(WARN_NOTUTF8, "String constant is not valid utf-8");
}
}
#endif
@ -1955,15 +1943,43 @@ void QCC_PR_LexName (void)
int len;
len = 0;
c = *pr_file_p;
do
{
pr_token[len] = c;
len++;
pr_file_p++;
int b = utf8_check(pr_file_p, &c);
if (!b)
{
unsigned char lead = *pr_file_p++;
char *o;
while(*pr_file_p && !utf8_check(pr_file_p, &c))
pr_file_p++;
o = pr_file_p;
while (qcc_iswhite(*pr_file_p))
{
if (*pr_file_p == '\n')
break;
pr_file_p++;
}
if (*pr_file_p == '\n')
QCC_PR_ParseError(ERR_NOTANAME, "Invalid UTF-8 code sequence at end of line. Lead byte was %#2x", lead);
else
{
len = 0;
while (*pr_file_p && !qcc_iswhite(*pr_file_p))
pr_token[len++] = *pr_file_p++;
pr_token[len++] = 0;
pr_file_p = o;
QCC_PR_ParseError(ERR_NOTANAME, "Invalid UTF-8 code sequence before %s. Lead byte was %#2x", pr_token, lead);
}
return;
}
while(b-->0)
{
pr_token[len] = *pr_file_p++;
len++;
}
c = *pr_file_p;
} while ( (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'
|| (c >= '0' && c <= '9'));
|| (c >= '0' && c <= '9') || c & 0x80);
pr_token[len] = 0;
pr_token_type = tt_name;
@ -1997,7 +2013,13 @@ void QCC_PR_LexPunctuation (void)
}
}
QCC_PR_ParseError (ERR_UNKNOWNPUCTUATION, "Unknown punctuation");
if ((unsigned char)*pr_file_p == (unsigned char)0xa0)
QCC_PR_ParseWarning (ERR_UNKNOWNPUCTUATION, "Unknown punctuation: '\\x%x' - non-breaking space", (unsigned char)*pr_file_p);
else
QCC_PR_ParseWarning (ERR_UNKNOWNPUCTUATION, "Unknown punctuation: '\\x%x'", *pr_file_p);
pr_file_p++;
QCC_PR_Lex();
}
@ -2159,7 +2181,7 @@ pbool QCC_PR_SimpleGetToken (void)
}
i = 0;
while ((c = *pr_file_p) && !qcc_iswhite(c) && c != ',' && c != ';' && c != ')' && c != '(' && c != ']')
while ((c = *pr_file_p) && !qcc_iswhite(c) && c != ',' && c != ';' && c != ')' && c != '(' && c != ']' && !(c == '/' && pr_file_p[1] == '/'))
{
if (i == sizeof(qcc_token)-1)
QCC_Error (ERR_INTERNAL, "token exceeds %i chars", i);
@ -2908,6 +2930,20 @@ int QCC_PR_CheckCompConst(void)
return true;
}
if (!strncmp(pr_file_p, "__QCCVER__", 8))
{
char retbuf[128];
time_t long_time;
time( &long_time );
strftime( retbuf, sizeof(retbuf),
"\"%a %d %b %Y\"", localtime( &long_time ));
pr_file_p += 10;
QCC_PR_IncludeChunkEx("FTEQCC "__DATE__","__TIME__"", true, NULL, NULL);
return true;
}
if (!strncmp(pr_file_p, "__FILE__", 8))
{
char retbuf[256];
@ -3110,7 +3146,7 @@ void QCC_PR_Lex (void)
return;
}
if ( (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' )
if ( (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || (c & 0x80))
{
if (flag_hashonly || !QCC_PR_CheckCompConst()) //look for a macro.
QCC_PR_LexName ();

View File

@ -79,6 +79,80 @@ int PDECL QCC_FileSize (const char *fname)
#include "../libs/zlib.h"
#endif
pbool PDECL QCC_WriteFileW (const char *name, wchar_t *data, int chars)
{
char *u8start = malloc(3+chars*4+1);
char *u8 = u8start;
int offset;
pbool result = false;
unsigned int inc;
FILE *f;
//start with the bom
//lets just always write a BOM when the file contains something outside ascii. it'll just be more robust when microsoft refuse to use utf8 by default.
//its just much less likely to fuck up when people use notepad/wordpad. :s
inc = 0xfeff;
*u8++ = ((inc>>12) & 0xf) | 0xe0;
*u8++ = ((inc>>6) & 0x3f) | 0x80;
*u8++ = ((inc>>0) & 0x3f) | 0x80;
offset = u8-u8start; //assume its not needed. will set to 0 if it is.
while(*data)
{
inc = *data++;
//handle surrogates
if (inc >= 0xd800u && inc < 0xdc00u)
{
unsigned int l = *data;
if (l >= 0xdc00u && l < 0xe000u)
{
data++;
inc = (((inc & 0x3ffu)<<10) | (l & 0x3ffu)) + 0x10000;
}
}
if (inc <= 127)
*u8++ = inc;
else
{
offset = 0;
if (inc <= 0x7ff)
{
*u8++ = ((inc>>6) & 0x1f) | 0xc0;
*u8++ = ((inc>>0) & 0x3f) | 0x80;
}
else if (inc <= 0xffff)
{
*u8++ = ((inc>>12) & 0xf) | 0xe0;
*u8++ = ((inc>>6) & 0x3f) | 0x80;
*u8++ = ((inc>>0) & 0x3f) | 0x80;
}
else if (inc <= 0x1fffff)
{
*u8++ = ((inc>>18) & 0x07) | 0xf0;
*u8++ = ((inc>>12) & 0x3f) | 0x80;
*u8++ = ((inc>> 6) & 0x3f) | 0x80;
*u8++ = ((inc>> 0) & 0x3f) | 0x80;
}
else
{
inc = 0xFFFD;
*u8++ = ((inc>>12) & 0xf) | 0xe0;
*u8++ = ((inc>>6) & 0x3f) | 0x80;
*u8++ = ((inc>>0) & 0x3f) | 0x80;
}
}
}
f = fopen(name, "wb");
if (f)
{
result = fwrite(u8start+offset, 1, u8-(u8start+offset), f) == (u8-(u8start+offset));
fclose(f);
}
free(u8start);
return result;
}
pbool PDECL QCC_WriteFile (const char *name, void *data, int len)
{
long length;
@ -303,9 +377,9 @@ HWND CreateAnEditControl(HWND parent)
if (!richedit)
richedit = LoadLibrary("RICHED32.DLL");
newc=CreateWindowEx(WS_EX_CLIENTEDGE,
richedit?RICHEDIT_CLASS:"EDIT",
"",
newc=CreateWindowExW(WS_EX_CLIENTEDGE,
richedit?RICHEDIT_CLASSW:L"EDIT",
L"",
WS_CHILD /*| ES_READONLY*/ | WS_VISIBLE |
WS_HSCROLL | WS_VSCROLL | ES_LEFT | ES_WANTRETURN |
ES_MULTILINE | ES_AUTOVSCROLL,
@ -1147,6 +1221,7 @@ int Rehighlight(editor_t *edit)
}
#endif
unsigned short *QCC_makeutf16(char *mem, unsigned int len, int *outlen);
void EditorReload(editor_t *editor)
{
struct stat sbuf;
@ -1157,7 +1232,10 @@ void EditorReload(editor_t *editor)
if (flen >= 0)
{
file = malloc(flen+1);
QCC_ReadFile(editor->filename, file, flen);
file[flen] = 0;
}
else
@ -1171,14 +1249,16 @@ void EditorReload(editor_t *editor)
if (file)
{
if (!fl_autohighlight)
char msg[1024];
wchar_t *ch = QCC_makeutf16(file, flen, NULL);
Edit_SetSel(editor->editpane,0,0);
SetWindowTextW(editor->editpane, ch);
/*if (errors)
{
GUIPrint(editor->editpane, file);
}
else
{
GUIFormattingPrint(editor->editpane, file);
}
QC_snprintfz(msg, sizeof(msg), "%s contains encoding errors. Invalid bytes have been converted to the 0xe000 private use area.", editor->filename);
MessageBox(editor->editpane, msg, "Encoding errors.", MB_ICONWARNING);
}*/
free(ch);
free(file);
}
@ -1321,16 +1401,16 @@ int EditorSave(editor_t *edit)
char title[2048];
struct stat sbuf;
int len;
char *file;
len = Edit_GetTextLength(edit->editpane);
file = malloc(len+1);
wchar_t *file;
len = GetWindowTextLengthW(edit->editpane);
file = malloc((len+1)*2);
if (!file)
{
MessageBox(NULL, "Save failed - not enough mem", "Error", 0);
return false;
}
Edit_GetText(edit->editpane, file, len+1);
if (!QCC_WriteFile(edit->filename, file, len))
GetWindowTextW(edit->editpane, file, len+1);
if (!QCC_WriteFileW(edit->filename, file, len))
{
MessageBox(NULL, "Save failed\nCheck path and ReadOnly flags", "Failure", 0);
return false;
@ -1361,8 +1441,10 @@ char *GUIReadFile(const char *fname, void *buffer, int blen)
{
if (e->window && !strcmp(e->filename, fname))
{
int elen = Edit_GetTextLength(e->editpane);
Edit_GetText(e->editpane, buffer, blen);
// int elen = GetWindowTextLengthW(e->editpane);
//our qcc itself is fine with utf-16, so long as it has a BOM.
*(short*)buffer = 0xfeff;
GetWindowTextW(e->editpane, (short*)buffer+1, blen);
return buffer;
}
}
@ -1377,7 +1459,7 @@ int GUIFileSize(const char *fname)
{
if (e->window && !strcmp(e->filename, fname))
{
int len = Edit_GetTextLength(e->editpane);
int len = (GetWindowTextLengthW(e->editpane)+1)*2;
return len;
}
}
@ -1639,7 +1721,7 @@ HWND optionsmenu;
HWND hexen2item;
HWND nokeywords_coexistitem;
HWND autoprototype_item;
HWND autohighlight_item;
//HWND autohighlight_item;
HWND extraparmsitem;
#ifdef EMBEDDEBUG
HWND w_enginebinary;
@ -1681,7 +1763,7 @@ static LRESULT CALLBACK OptionsWndProc(HWND hWnd,UINT message,
else
compiler_flag[i].flags &= ~FLAG_SETINGUI;
}
fl_autohighlight = Button_GetCheck(autohighlight_item);
fl_autohighlight = false;//Button_GetCheck(autohighlight_item);
Edit_GetText(extraparmsitem, parameters, sizeof(parameters)-1);
#ifdef EMBEDDEBUG
Edit_GetText(w_enginebinary, enginebinary, sizeof(enginebinary)-1);
@ -2086,7 +2168,7 @@ void OptionsDialog(void)
else
Button_SetCheck(wnd, 0);
autohighlight_item = wnd = CreateWindow("BUTTON","Syntax Highlighting",
/* autohighlight_item = wnd = CreateWindow("BUTTON","Syntax Highlighting",
WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
408,y,200-16,16,
optionsmenu,
@ -2098,7 +2180,7 @@ void OptionsDialog(void)
Button_SetCheck(wnd, 1);
else
Button_SetCheck(wnd, 0);
*/
x = 408;
my = y;
for (i = 0; compiler_flag[i].enabled; i++)