Added console-links support.

Shift click IPs/words/links on the console to enter them as arguments.
Fixed some utf-8 issues.
Fixed issue with csaddon.dat not loading in release builds.
Fixed berkelium inputs, should have a full range of keys now, though there's still no 'back' support.
Bad name rejection made more paranoid.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4124 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2012-10-13 00:56:31 +00:00
parent fc2ab857f5
commit 5d9ba4b548
20 changed files with 866 additions and 179 deletions

View file

@ -1024,16 +1024,17 @@ int CL_LoadModels(int stage, qboolean dontactuallyload)
{ {
char *s; char *s;
qboolean anycsqc; qboolean anycsqc;
char *endptr;
unsigned int chksum;
#ifdef _DEBUG #ifdef _DEBUG
anycsqc = true; anycsqc = true;
#else #else
anycsqc = atoi(Info_ValueForKey(cl.serverinfo, "anycsqc")); anycsqc = atoi(Info_ValueForKey(cl.serverinfo, "anycsqc"));
#endif #endif
if (cls.demoplayback)
anycsqc = true;
s = Info_ValueForKey(cl.serverinfo, "*csprogs"); s = Info_ValueForKey(cl.serverinfo, "*csprogs");
if (anycsqc || *s || cls.demoplayback) //only allow csqc if the server says so, and the 'checksum' matches. chksum = strtoul(s, &endptr, 0);
{
char *endptr;
unsigned int chksum = strtoul(s, &endptr, 0);
if (*endptr) if (*endptr)
{ {
Con_Printf("corrupt *csprogs key in serverinfo\n"); Con_Printf("corrupt *csprogs key in serverinfo\n");
@ -1041,14 +1042,13 @@ int CL_LoadModels(int stage, qboolean dontactuallyload)
chksum = 0; chksum = 0;
} }
SCR_SetLoadingFile("csprogs"); SCR_SetLoadingFile("csprogs");
if (!CSQC_Init(anycsqc, chksum)) if (!CSQC_Init(anycsqc, *s?true:false, chksum))
{ {
Sbar_Start(); //try and start this before we're actually on the server, Sbar_Start(); //try and start this before we're actually on the server,
//this'll stop the mod from sending so much stuffed data at us, whilst we're frozen while trying to load. //this'll stop the mod from sending so much stuffed data at us, whilst we're frozen while trying to load.
//hopefully this'll make it more robust. //hopefully this'll make it more robust.
//csqc is expected to use it's own huds, or to run on decent servers. :p //csqc is expected to use it's own huds, or to run on decent servers. :p
} }
}
endstage(); endstage();
} }
#endif #endif
@ -1285,7 +1285,6 @@ Sound_NextDownload
*/ */
void Sound_CheckDownloads (void) void Sound_CheckDownloads (void)
{ {
char *s;
int i; int i;
@ -1294,6 +1293,7 @@ void Sound_CheckDownloads (void)
#ifdef CSQC_DAT #ifdef CSQC_DAT
// if (cls.fteprotocolextensions & PEXT_CSQC) // if (cls.fteprotocolextensions & PEXT_CSQC)
{ {
char *s;
s = Info_ValueForKey(cl.serverinfo, "*csprogs"); s = Info_ValueForKey(cl.serverinfo, "*csprogs");
if (*s) //only allow csqc if the server says so, and the 'checksum' matches. if (*s) //only allow csqc if the server says so, and the 'checksum' matches.
{ {
@ -2843,8 +2843,7 @@ void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution.
#ifdef PEXT_CSQC #ifdef PEXT_CSQC
CSQC_Shutdown(); CSQC_Shutdown();
if (cls.demoplayback) CSQC_Init(cls.demoplayback, false, 0);
CSQC_Init(true, 0);
#endif #endif
} }
void CLNQ_SignonReply (void) void CLNQ_SignonReply (void)
@ -2881,10 +2880,7 @@ Con_DPrintf ("CL_SignonReply: %i\n", cls.signon);
{ {
char *s; char *s;
s = Info_ValueForKey(cl.serverinfo, "*csprogs"); s = Info_ValueForKey(cl.serverinfo, "*csprogs");
if (*s) CSQC_Init(false, *s?true:false, atoi(s));
CSQC_Init(false, atoi(s));
else
CSQC_Shutdown();
} }
#endif #endif
} }
@ -4786,18 +4782,15 @@ void CL_PrintChat(player_info_t *plr, char *rawmsg, char *msg, int plrflags)
if (plrflags & (TPM_TEAM|TPM_OBSERVEDTEAM)) // for team chat don't highlight the name, just the brackets if (plrflags & (TPM_TEAM|TPM_OBSERVEDTEAM)) // for team chat don't highlight the name, just the brackets
{ {
// color is reset every printf so we're safe here Q_strncatz(fullchatmessage, va("\1(^[%s%s^d\\player\\%i^])", name_coloured?"^m":"", name, plr-cl.players), sizeof(fullchatmessage));
Q_strncatz(fullchatmessage, va("\1(%s^%c", name_coloured?"":"^m", c), sizeof(fullchatmessage));
Q_strncatz(fullchatmessage, va("%s%s^d", name_coloured?"^m":"", name), sizeof(fullchatmessage));
Q_strncatz(fullchatmessage, va("%s^%c)", name_coloured?"^m":"", c), sizeof(fullchatmessage));
} }
else if (cl_standardchat.ival) else if (cl_standardchat.ival)
{ {
Q_strncatz(fullchatmessage, va("\1%s", name), sizeof(fullchatmessage)); Q_strncatz(fullchatmessage, va("\1^[%s%s^d\\player\\%i^]", name_coloured?"^m":"", name, plr-cl.players), sizeof(fullchatmessage));
} }
else else
{ {
Q_strncatz(fullchatmessage, va("\1%s^%c%s^d", name_coloured?"":"^m", c, name), sizeof(fullchatmessage)); Q_strncatz(fullchatmessage, va("\1^[%s^%c%s^d\\player\\%i^]", name_coloured?"^m":"", c, name, plr-cl.players), sizeof(fullchatmessage));
} }
if (!memessage) if (!memessage)
@ -4935,7 +4928,7 @@ void CL_PrintStandardMessage(char *msg, int printlevel)
c = '0' + CL_PlayerColor(p, &coloured); c = '0' + CL_PlayerColor(p, &coloured);
// print name // print name
Q_strncatz(fullmessage, va("%s^%c%s^7%s", coloured?"^m":"", c, name, coloured?"^m":""), sizeof(fullmessage)); Q_strncatz(fullmessage, va("^[%s^%c%s^d\\player\\%i^]", coloured?"^m":"", c, name, p - cl.players), sizeof(fullmessage));
break; break;
} }
} }

View file

@ -1075,7 +1075,8 @@ char *CG_GetConfigString(int num);
#ifdef CSQC_DAT #ifdef CSQC_DAT
qboolean CSQC_Inited(void); qboolean CSQC_Inited(void);
void CSQC_RendererRestarted(void); void CSQC_RendererRestarted(void);
qboolean CSQC_Init (qboolean anycsqc, unsigned int checksum); qboolean CSQC_Init (qboolean anycsqc, qboolean csdatenabled, unsigned int checksum);
qboolean CSQC_ConsoleLink(char *text, char *info);
void CSQC_RegisterCvarsAndThings(void); void CSQC_RegisterCvarsAndThings(void);
qboolean CSQC_DrawView(void); qboolean CSQC_DrawView(void);
void CSQC_Shutdown(void); void CSQC_Shutdown(void);

View file

@ -848,7 +848,7 @@ int Con_DrawInput (int left, int right, int y)
text[key_linepos] = 0; text[key_linepos] = 0;
cursor = COM_ParseFunString(CON_WHITEMASK, text, maskedtext, sizeof(maskedtext) - sizeof(maskedtext[0]), true); cursor = COM_ParseFunString(CON_WHITEMASK, text, maskedtext, sizeof(maskedtext) - sizeof(maskedtext[0]), true);
text[key_linepos] = i; text[key_linepos] = i;
endmtext = COM_ParseFunString(CON_WHITEMASK, text, maskedtext, sizeof(maskedtext) - sizeof(maskedtext[0]), true); endmtext = COM_ParseFunString(CON_WHITEMASK, text+key_linepos, cursor, ((char*)maskedtext)+sizeof(maskedtext) - (char*)(cursor+1), true);
endmtext[1] = 0; endmtext[1] = 0;
@ -890,11 +890,11 @@ int Con_DrawInput (int left, int right, int y)
#endif #endif
cursorframe = ((int)(realtime*con_cursorspeed)&1); cursorframe = ((int)(realtime*con_cursorspeed)&1);
for (lhs = 0, i = key_linepos-1; i >= 0; i--) for (lhs = 0, i = cursor - maskedtext-1; i >= 0; i--)
{ {
lhs += Font_CharWidth(maskedtext[i]); lhs += Font_CharWidth(maskedtext[i]);
} }
for (rhs = 0, i = key_linepos+1; maskedtext[i]; i++) for (rhs = 0, i = cursor - maskedtext; maskedtext[i]; i++)
{ {
rhs += Font_CharWidth(maskedtext[i]); rhs += Font_CharWidth(maskedtext[i]);
} }
@ -1575,11 +1575,12 @@ void Con_DrawConsole (int lines, qboolean noback)
char *Con_CopyConsole(void) char *Con_CopyConsole(qboolean nomarkup)
{ {
conchar_t *cur; conchar_t *cur;
conline_t *l; conline_t *l;
conchar_t *lend; conchar_t *lend;
conchar_t col = CON_WHITEMASK;
char *result; char *result;
int outlen, maxlen; int outlen, maxlen;
int finalendoffset; int finalendoffset;
@ -1590,6 +1591,9 @@ char *Con_CopyConsole(void)
maxlen = 1024*1024; maxlen = 1024*1024;
result = Z_Malloc(maxlen+1); result = Z_Malloc(maxlen+1);
// for (cur = (conchar_t*)(selstartline+1), finalendoffset = 0; cur < (conchar_t*)(selstartline+1) + selstartline->length; cur++, finalendoffset++)
// result[finalendoffset] = *cur & 0xffff;
l = selstartline; l = selstartline;
cur = (conchar_t*)(l+1) + selstartoffset; cur = (conchar_t*)(l+1) + selstartoffset;
finalendoffset = selendoffset; finalendoffset = selendoffset;
@ -1603,15 +1607,17 @@ char *Con_CopyConsole(void)
while (cur > (conchar_t*)(l+1)) while (cur > (conchar_t*)(l+1))
{ {
cur--; cur--;
if ((*cur & 0xff) == ' ') if ((*cur & CON_CHARMASK) == ' ')
{ {
cur++; cur++;
break; break;
} }
if (*cur == CON_LINKSTART)
break;
} }
while (finalendoffset < selendline->length) while (finalendoffset < selendline->length)
{ {
if ((((conchar_t*)(l+1))[finalendoffset] & 0xff) != ' ') if ((((conchar_t*)(l+1))[finalendoffset] & CON_CHARMASK) != ' ')
finalendoffset++; finalendoffset++;
else else
break; break;
@ -1619,6 +1625,31 @@ char *Con_CopyConsole(void)
} }
} }
//scan backwards to find any link enclosure
for(lend = cur; lend >= (conchar_t*)(l+1); lend--)
{
if (*lend == CON_LINKSTART)
{
//found one
cur = lend;
break;
}
if (*lend == CON_LINKEND)
{
//some other link ended here. don't use its start.
break;
}
}
//scan forwards to find the end of the selected link
for(lend = (conchar_t*)(selendline+1) + finalendoffset; lend < (conchar_t*)(selendline+1) + selendline->length; lend++)
{
if (*lend == CON_LINKEND)
{
finalendoffset = lend+1 - (conchar_t*)(selendline+1);
break;
}
}
outlen = 0; outlen = 0;
for (;;) for (;;)
{ {
@ -1626,12 +1657,8 @@ char *Con_CopyConsole(void)
lend = (conchar_t*)(l+1) + finalendoffset; lend = (conchar_t*)(l+1) + finalendoffset;
else else
lend = (conchar_t*)(l+1) + l->length; lend = (conchar_t*)(l+1) + l->length;
while (cur < lend)
{ outlen = COM_DeFunString(cur, lend, result + outlen, maxlen - outlen, nomarkup) - result;
if (outlen == maxlen)
break;
result[outlen++] = *cur++;
}
if (l == selendline) if (l == selendline)
break; break;
@ -1642,6 +1669,9 @@ char *Con_CopyConsole(void)
Con_Printf("Error: Bad console buffer\n"); Con_Printf("Error: Bad console buffer\n");
break; break;
} }
if (outlen+3 > maxlen)
break;
#ifdef _WIN32 #ifdef _WIN32
result[outlen++] = '\r'; result[outlen++] = '\r';
#endif #endif

View file

@ -409,6 +409,12 @@ qboolean Key_GetConsoleSelectionBox(int *sx, int *sy, int *ex, int *ey)
con_mousedown[1] -= 8; con_mousedown[1] -= 8;
con_current->display = con_current->display->newer; con_current->display = con_current->display->newer;
} }
*sx = mousecursor_x;
*sy = mousecursor_y;
*ex = mousecursor_x;
*ey = mousecursor_y;
return true;
} }
else if (con_mousedown[2] == 2) else if (con_mousedown[2] == 2)
{ {
@ -421,16 +427,253 @@ qboolean Key_GetConsoleSelectionBox(int *sx, int *sy, int *ex, int *ey)
return false; return false;
} }
/*insert the given text at the console input line at the current cursor pos*/
void Key_ConsoleInsert(char *instext)
{
int i;
int len;
len = strlen(instext);
if (len + strlen(key_lines[edit_line]) > MAXCMDLINE - 1)
len = MAXCMDLINE - 1 - strlen(key_lines[edit_line]);
if (len > 0)
{ // insert the string
memmove (key_lines[edit_line] + key_linepos + len,
key_lines[edit_line] + key_linepos, strlen(key_lines[edit_line]) - key_linepos + 1);
memcpy (key_lines[edit_line] + key_linepos, instext, len);
for (i = 0; i < len; i++)
{
if (key_lines[edit_line][key_linepos+i] == '\r')
key_lines[edit_line][key_linepos+i] = ' ';
else if (key_lines[edit_line][key_linepos+i] == '\n')
key_lines[edit_line][key_linepos+i] = ';';
}
key_linepos += len;
}
}
void Key_ConsoleRelease(int key, int unicode) void Key_ConsoleRelease(int key, int unicode)
{ {
if (key == K_MOUSE1)
con_mousedown[2] = 0;
if (key == K_MOUSE2 && con_mousedown[2] == 2)
{
extern int mousecursor_x, mousecursor_y; extern int mousecursor_x, mousecursor_y;
char *buffer; char *buffer;
if (key == K_MOUSE1)
{
con_mousedown[2] = 0; con_mousedown[2] = 0;
buffer = Con_CopyConsole(); if (abs(con_mousedown[0] - mousecursor_x) < 5 && abs(con_mousedown[1] - mousecursor_y) < 5)
{
buffer = Con_CopyConsole(false);
if (!buffer)
return;
if (keydown[K_SHIFT])
{
int len;
len = strlen(buffer);
//strip any trailing dots/elipsis
while (len > 1 && !strcmp(buffer+len-1, "."))
{
len-=1;
buffer[len] = 0;
}
//strip any enclosing quotes
while (*buffer == '\"' && len > 2 && !strcmp(buffer+len-1, "\""))
{
len-=2;
memmove(buffer, buffer+1, len);
buffer[len] = 0;
}
Key_ConsoleInsert(buffer);
}
else
{
if (buffer[0] == '^' && buffer[1] == '[')
{
//looks like it might be a link!
char *end = NULL;
char *info;
for (info = buffer + 2; *info; )
{
if (info[0] == '^' && info[1] == ']')
{
break;
}
if (*info == '\\')
break;
else if (info[0] == '^' && info[1] == '^')
info+=2;
else
info++;
}
for(end = info; *end; )
{
if (end[0] == '^' && end[1] == ']')
{
char *c;
//okay, its a valid link that they clicked
*end = 0;
#ifdef CSQC_DAT
if (!CSQC_ConsoleLink(buffer+2, info))
#endif
{
/*the engine supports specific default links*/
/*we don't support everything. a: there's no point. b: unbindall links are evil.*/
c = Info_ValueForKey(info, "player");
if (*c)
{
unsigned int player = atoi(c);
int i;
if (player >= MAX_CLIENTS)
break;
c = Info_ValueForKey(info, "action");
if (*c)
{
if (!strcmp(c, "mute"))
{
if (!cl.players[player].vignored)
{
cl.players[player].vignored = true;
Con_Printf("^[%s\\player\\%i^] muted\n", cl.players[player].name, player);
}
else
{
cl.players[player].vignored = false;
Con_Printf("^[%s\\player\\%i^] unmuted\n", cl.players[player].name, player);
}
}
else if (!strcmp(c, "ignore"))
{
if (!cl.players[player].ignored)
{
cl.players[player].ignored = true;
cl.players[player].vignored = true;
Con_Printf("^[%s\\player\\%i^] ignored\n", cl.players[player].name, player);
}
else
{
cl.players[player].ignored = false;
cl.players[player].vignored = false;
Con_Printf("^[%s\\player\\%i^] unignored\n", cl.players[player].name, player);
}
}
else if (!strcmp(c, "kick"))
{
#ifndef CLIENTONLY
if (sv.active)
{
//use the q3 command, because we can.
Cbuf_AddText(va("\nclientkick %i\n", player), RESTRICT_LOCAL);
}
else
#endif
Cbuf_AddText(va("\nrcon kick %s\n", cl.players[player].name), RESTRICT_LOCAL);
}
else if (!strcmp(c, "ban"))
{
#ifndef CLIENTONLY
if (sv.active)
{
//use the q3 command, because we can.
Cbuf_AddText(va("\nbanname %s QuickBan\n", cl.players[player].name), RESTRICT_LOCAL);
}
else
#endif
Cbuf_AddText(va("\nrcon banname %s QuickBan\n", cl.players[player].name), RESTRICT_LOCAL);
}
break;
}
Con_Printf("^m#^m ^[%s\\player\\%i^]: %if %ims", cl.players[player].name, player, cl.players[player].frags, cl.players[player].ping);
for (i = 0; i < cl.splitclients; i++)
{
if (cl.playernum[i] == player)
break;
}
if (i == cl.splitclients)
{
extern cvar_t rcon_password;
if (cls.protocol == CP_QUAKEWORLD && strcmp(cl.players[cl.playernum[0]].team, cl.players[player].team))
Con_Printf(" ^[[Join Team %s]\\cmd\\setinfo team %s^]", cl.players[player].team, cl.players[player].team);
Con_Printf(" ^[%sgnore\\player\\%i\\action\\ignore^]", cl.players[player].ignored?"Uni":"I", player);
// if (cl_voip_play.ival)
Con_Printf(" ^[%sute\\player\\%i\\action\\mute^]", cl.players[player].vignored?"Unm":"M", player);
if (*rcon_password.string
#ifndef CLIENTONLY
|| (sv.state && svs.clients[player].netchan.remote_address.type != NA_LOOPBACK)
#endif
)
{
Con_Printf(" ^[Kick\\player\\%i\\action\\kick^]", player);
Con_Printf(" ^[Ban\\player\\%i\\action\\ban^]", player);
}
}
else
{
char cmdprefix[6];
snprintf(cmdprefix, sizeof(cmdprefix), "%i ", i);
//hey look! its you!
Con_Printf(" ^[Suicide\\cmd\\kill^]");
#ifndef CLIENTONLY
if (!sv.state)
Con_Printf(" ^[Disconnect\\cmd\\disconnect^]");
if (cls.allow_cheats || (sv.state && sv.allocated_client_slots == 1))
#else
Con_Printf(" ^[Disconnect\\cmd\\disconnect^]");
if (cls.allow_cheats)
#endif
{
Con_Printf(" ^[Noclip\\cmd\\noclip^]");
Con_Printf(" ^[Fly\\cmd\\fly^]");
Con_Printf(" ^[God\\cmd\\god^]");
Con_Printf(" ^[Give\\impulse\\9^]");
}
}
Con_Printf("\r");
break;
}
c = Info_ValueForKey(info, "connect");
if (*c && !strchr(c, ';') && !strchr(c, '\n'))
{
Cbuf_AddText(va("\nconnect %s\n", c), RESTRICT_LOCAL);
break;
}
c = Info_ValueForKey(info, "qtv");
if (*c && !strchr(c, ';') && !strchr(c, '\n'))
{
Cbuf_AddText(va("\nqtvplay %s\n", c), RESTRICT_LOCAL);
break;
}
c = Info_ValueForKey(info, "cmd");
if (*c && !strchr(c, ';') && !strchr(c, '\n'))
{
Cbuf_AddText(va("\ncmd %s\n", c), RESTRICT_LOCAL);
break;
}
c = Info_ValueForKey(info, "impulse");
if (*c && !strchr(c, ';') && !strchr(c, '\n'))
{
Cbuf_AddText(va("\nimpulse %s\n", c), RESTRICT_LOCAL);
break;
}
}
break;
}
if (end[0] == '^' && end[1] == '^')
end+=2;
else
end++;
}
}
}
Z_Free(buffer);
}
}
if (key == K_MOUSE2 && con_mousedown[2] == 2)
{
con_mousedown[2] = 0;
buffer = Con_CopyConsole(true); //don't keep markup if we're copying to the clipboard
if (!buffer) if (!buffer)
return; return;
Sys_SaveClipboard(buffer); Sys_SaveClipboard(buffer);
@ -439,6 +682,91 @@ void Key_ConsoleRelease(int key, int unicode)
} }
} }
//move the cursor one char to the left. cursor must be within the 'start' string.
unsigned char *utf_left(unsigned char *start, unsigned char *cursor)
{
extern cvar_t com_parseutf8;
if (cursor == start)
return cursor;
if (com_parseutf8.ival>0)
{
cursor--;
while ((*cursor & 0xc0) == 0x80 && cursor > start)
cursor--;
}
else
cursor--;
if (*cursor == ']' && cursor > start && cursor[-1] == '^')
{
//just stepped onto a link
char *linkstart;
linkstart = cursor-1;
while(linkstart >= start)
{
if (linkstart[0] == '^' && linkstart[1] == '[')
return linkstart;
linkstart--;
}
}
return cursor;
}
//move the cursor one char to the right.
unsigned char *utf_right(unsigned char *cursor)
{
extern cvar_t com_parseutf8;
if (*cursor == '^' && cursor[1] == '[')
{
//just stepped over a link
char *linkend;
linkend = cursor+2;
while(*linkend)
{
if (linkend[0] == '^' && linkend[1] == '^')
linkend += 2;
else if (linkend[0] == '^' && linkend[1] == ']')
return linkend+2;
else
linkend++;
}
return linkend;
}
if (com_parseutf8.ival>0)
{
int skip = 1;
//figure out the length of the char
if ((*cursor & 0xc0) == 0x80)
skip = 1; //error
else if ((*cursor & 0xe0) == 0xc0)
skip = 2;
else if ((*cursor & 0xf0) == 0xe0)
skip = 3;
else if ((*cursor & 0xf1) == 0xf0)
skip = 4;
else if ((*cursor & 0xf3) == 0xf1)
skip = 5;
else if ((*cursor & 0xf7) == 0xf3)
skip = 6;
else if ((*cursor & 0xff) == 0xf7)
skip = 7;
else skip = 1;
while (*cursor && skip)
{
cursor++;
skip--;
}
}
else if (*cursor)
cursor++;
return cursor;
}
/* /*
==================== ====================
Key_Console Key_Console
@ -544,15 +872,14 @@ void Key_Console (unsigned int unicode, int key)
if (key == K_LEFTARROW) if (key == K_LEFTARROW)
{ {
if (key_linepos > 1) key_linepos = utf_left(key_lines[edit_line]+1, key_lines[edit_line] + key_linepos) - key_lines[edit_line];
key_linepos--;
return; return;
} }
if (key == K_RIGHTARROW) if (key == K_RIGHTARROW)
{ {
if (key_lines[edit_line][key_linepos]) if (key_lines[edit_line][key_linepos])
{ {
key_linepos++; key_linepos = utf_right(key_lines[edit_line] + key_linepos) - key_lines[edit_line];
return; return;
} }
else else
@ -563,15 +890,8 @@ void Key_Console (unsigned int unicode, int key)
{ {
if (key_lines[edit_line][key_linepos]) if (key_lines[edit_line][key_linepos])
{ {
int charlen = 1; int charlen = utf_right(key_lines[edit_line] + key_linepos) - (key_lines[edit_line] + key_linepos);
if (com_parseutf8.ival>0 && memmove(key_lines[edit_line]+key_linepos, key_lines[edit_line]+key_linepos+charlen, strlen(key_lines[edit_line]+key_linepos+charlen)+1);
(key_lines[edit_line][key_linepos] & 0xc0) != 0x80)
{
while((key_lines[edit_line][key_linepos+charlen] & 0xc0) == 0x80)
charlen++;
}
memmove(key_lines[edit_line]+key_linepos, key_lines[edit_line]+key_linepos+charlen, strlen(key_lines[edit_line]+key_linepos+charlen)+charlen);
return; return;
} }
else else
@ -582,13 +902,8 @@ void Key_Console (unsigned int unicode, int key)
{ {
if (key_linepos > 1) if (key_linepos > 1)
{ {
int charlen = 1; int charlen = (key_lines[edit_line]+key_linepos) - utf_left(key_lines[edit_line]+1, key_lines[edit_line] + key_linepos);
if (com_parseutf8.ival>0) memmove(key_lines[edit_line]+key_linepos-charlen, key_lines[edit_line]+key_linepos, strlen(key_lines[edit_line]+key_linepos)+1);
{
while (key_linepos > charlen && (key_lines[edit_line][key_linepos-charlen] & 0xc0) == 0x80)
charlen++;
}
memmove(key_lines[edit_line]+key_linepos-charlen, key_lines[edit_line]+key_linepos, strlen(key_lines[edit_line]+key_linepos)+charlen);
key_linepos -= charlen; key_linepos -= charlen;
} }
return; return;
@ -692,36 +1007,19 @@ void Key_Console (unsigned int unicode, int key)
return; return;
} }
if (((unicode=='C' || unicode=='c') && keydown[K_CTRL]) || (keydown[K_CTRL] && key == K_INS)) //beware that windows translates ctrl+c and ctrl+v to a control char
if (((unicode=='C' || unicode=='c' || unicode==3) && keydown[K_CTRL]) || (keydown[K_CTRL] && key == K_INS))
{ {
Sys_SaveClipboard(key_lines[edit_line]+1); Sys_SaveClipboard(key_lines[edit_line]+1);
return; return;
} }
if (((unicode=='V' || unicode=='v') && keydown[K_CTRL]) || (keydown[K_SHIFT] && key == K_INS)) if (((unicode=='V' || unicode=='v' || unicode==22) && keydown[K_CTRL]) || (keydown[K_SHIFT] && key == K_INS))
{ {
clipText = Sys_GetClipboard(); clipText = Sys_GetClipboard();
if (clipText) if (clipText)
{ {
int i; Key_ConsoleInsert(clipText);
int len;
len = strlen(clipText);
if (len + strlen(key_lines[edit_line]) > MAXCMDLINE - 1)
len = MAXCMDLINE - 1 - strlen(key_lines[edit_line]);
if (len > 0)
{ // insert the string
memmove (key_lines[edit_line] + key_linepos + len,
key_lines[edit_line] + key_linepos, strlen(key_lines[edit_line]) - key_linepos + 1);
memcpy (key_lines[edit_line] + key_linepos, clipText, len);
for (i = 0; i < len; i++)
{
if (key_lines[edit_line][key_linepos+i] == '\r')
key_lines[edit_line][key_linepos+i] = ' ';
else if (key_lines[edit_line][key_linepos+i] == '\n')
key_lines[edit_line][key_linepos+i] = ';';
}
key_linepos += len;
}
Sys_CloseClipboard(clipText); Sys_CloseClipboard(clipText);
} }
return; return;
@ -1466,7 +1764,7 @@ void Key_Event (int devid, int key, unsigned int unicode, qboolean down)
//yes, csqc is allowed to steal the escape key. //yes, csqc is allowed to steal the escape key.
if (key != '`' && key != '~') if (key != '`' && key != '~')
if (key_dest == key_game) if (key_dest == key_game && !Media_PlayingFullScreen())
{ {
#ifdef CSQC_DAT #ifdef CSQC_DAT
if (CSQC_KeyPress(key, unicode, down, devid)) //give csqc a chance to handle it. if (CSQC_KeyPress(key, unicode, down, devid)) //give csqc a chance to handle it.

View file

@ -2199,6 +2199,8 @@ qboolean Media_PlayFilm(char *name)
cin->ended = false; cin->ended = false;
if (cin->rewind) if (cin->rewind)
cin->rewind(cin); cin->rewind(cin);
if (cin->changestream)
cin->changestream(cin, "cmd:focus");
} }
else else
{ {

View file

@ -107,6 +107,7 @@ extern sfx_t *cl_sfx_r_exp3;
globalfunction(input_event, "CSQC_InputEvent"); \ globalfunction(input_event, "CSQC_InputEvent"); \
globalfunction(input_frame, "CSQC_Input_Frame");/*EXT_CSQC_1*/ \ globalfunction(input_frame, "CSQC_Input_Frame");/*EXT_CSQC_1*/ \
globalfunction(console_command, "CSQC_ConsoleCommand"); \ globalfunction(console_command, "CSQC_ConsoleCommand"); \
globalfunction(console_link, "CSQC_ConsoleLink"); \
globalfunction(gamecommand, "GameCommand"); /*DP extension*/\ globalfunction(gamecommand, "GameCommand"); /*DP extension*/\
\ \
globalfunction(ent_update, "CSQC_Ent_Update"); \ globalfunction(ent_update, "CSQC_Ent_Update"); \
@ -1251,6 +1252,15 @@ static void QCBUILTIN PF_R_GetViewFlag(progfuncs_t *prinst, struct globalvars_s
*r = r_refdef.useperspective; *r = r_refdef.useperspective;
break; break;
case VF_SCREENVSIZE:
r[0] = vid.width;
r[1] = vid.height;
break;
case VF_SCREENPSIZE:
r[0] = vid.rotpixelwidth;
r[1] = vid.rotpixelheight;
break;
default: default:
Con_DPrintf("GetViewFlag: %i not recognised\n", parametertype); Con_DPrintf("GetViewFlag: %i not recognised\n", parametertype);
break; break;
@ -4947,7 +4957,7 @@ qboolean CSQC_Inited(void)
} }
double csqctime; double csqctime;
qboolean CSQC_Init (qboolean anycsqc, unsigned int checksum) qboolean CSQC_Init (qboolean anycsqc, qboolean csdatenabled, unsigned int checksum)
{ {
int i; int i;
string_t *str; string_t *str;
@ -5054,6 +5064,8 @@ qboolean CSQC_Init (qboolean anycsqc, unsigned int checksum)
} }
csqc_isdarkplaces = false; csqc_isdarkplaces = false;
if (csdatenabled || csqc_singlecheats || anycsqc)
{
if (PR_LoadProgs(csqcprogs, "csprogs.dat", 22390, NULL, 0) >= 0) if (PR_LoadProgs(csqcprogs, "csprogs.dat", 22390, NULL, 0) >= 0)
loaded = true; loaded = true;
else else
@ -5068,9 +5080,11 @@ qboolean CSQC_Init (qboolean anycsqc, unsigned int checksum)
if (loaded) if (loaded)
Con_Printf(CON_WARNING "Running outdated or unknown csprogs.dat version\n"); Con_Printf(CON_WARNING "Running outdated or unknown csprogs.dat version\n");
} }
}
if (csqc_singlecheats) if (csqc_singlecheats || anycsqc)
{ {
Con_DPrintf("loading csaddon.dat...\n");
if (PR_LoadProgs(csqcprogs, "csaddon.dat", 0, NULL, 0) >= 0) if (PR_LoadProgs(csqcprogs, "csaddon.dat", 0, NULL, 0) >= 0)
loaded = true; loaded = true;
} }
@ -5518,6 +5532,21 @@ qboolean CSQC_Accelerometer(float x, float y, float z)
return G_FLOAT(OFS_RETURN); return G_FLOAT(OFS_RETURN);
} }
qboolean CSQC_ConsoleLink(char *text, char *info)
{
void *pr_globals;
if (!csqcprogs || !csqcg.console_link)
return false;
pr_globals = PR_globals(csqcprogs, PR_CURRENT);
(((string_t *)pr_globals)[OFS_PARM1] = PR_TempString(csqcprogs, info));
*info = 0;
(((string_t *)pr_globals)[OFS_PARM0] = PR_TempString(csqcprogs, text));
*info = '\\';
PR_ExecuteProgram (csqcprogs, csqcg.console_link);
return G_FLOAT(OFS_RETURN);
}
qboolean CSQC_ConsoleCommand(char *cmd) qboolean CSQC_ConsoleCommand(char *cmd)
{ {
void *pr_globals; void *pr_globals;

View file

@ -1863,31 +1863,74 @@ conchar_t q3codemasks[MAXQ3COLOURS] = {
0x07000000 // 9, "half-intensity" (BX_COLOREDTEXT) 0x07000000 // 9, "half-intensity" (BX_COLOREDTEXT)
}; };
//Converts a conchar_t string into a char string. returns the null terminator. pass NULL for stop to calc it
//Strips out the flags char *COM_DeFunString(conchar_t *str, conchar_t *stop, char *out, int outsize, qboolean ignoreflags)
void COM_DeFunString(conchar_t *str, char *out, int outsize, qboolean ignoreflags)
{ {
if (ignoreflags) if (!stop)
{ {
while(*str) for (stop = str; *stop; stop++)
;
}
#ifdef _DEBUG
if (!outsize)
Sys_Error("COM_DeFunString given outsize=0");
#endif
/*if (ignoreflags)
{
while(str < stop)
{ {
if (!--outsize) if (!--outsize)
break; break;
*out++ = (unsigned char)(*str++&255); *out++ = (unsigned char)(*str++&255);
} }
*out++ = 0; *out = 0;
} }
else else*/
{ {
int fl, d; int fl, d;
unsigned int c;
int prelinkflags = CON_WHITEMASK; //if used, its already an error.
//FIXME: TEST! //FIXME: TEST!
fl = CON_WHITEMASK; fl = CON_WHITEMASK;
while(*str) while(str < stop)
{ {
if (!--outsize) if ((*str & CON_HIDDEN) && ignoreflags)
{
str++;
continue;
}
if (*str == CON_LINKSTART)
{
if (!ignoreflags)
{
if (outsize<=2)
break; break;
if ((*str & CON_FLAGSMASK) != fl) outsize -= 2;
*out++ = '^';
*out++ = '[';
}
prelinkflags = fl;
fl = COLOR_RED << CON_FGSHIFT;
str++;
continue;
}
else if (*str == CON_LINKEND)
{
if (!ignoreflags)
{
if (outsize<=2)
break;
outsize -= 2;
*out++ = '^';
*out++ = ']';
}
fl = prelinkflags;
str++;
continue;
}
else if ((*str & CON_FLAGSMASK) != fl && !ignoreflags)
{ {
d = fl^(*str & CON_FLAGSMASK); d = fl^(*str & CON_FLAGSMASK);
// if (fl & CON_NONCLEARBG) //not represented. // if (fl & CON_NONCLEARBG) //not represented.
@ -1917,6 +1960,22 @@ void COM_DeFunString(conchar_t *str, char *out, int outsize, qboolean ignoreflag
} }
if (d & (CON_FGMASK | CON_BGMASK | CON_NONCLEARBG)) if (d & (CON_FGMASK | CON_BGMASK | CON_NONCLEARBG))
{
static char q3[16] = { '0', 0, 0, 0,
0, 0, 0, 0,
0, '4', '2', '5',
'1', '6', '3', '7'};
if (!(d & (CON_BGMASK | CON_NONCLEARBG)) && q3[(*str & CON_FGMASK) >> CON_FGSHIFT] && !((d|fl) & CON_HALFALPHA))
{
if (outsize<=2)
break;
outsize -= 2;
d = (*str & CON_FLAGSMASK);
*out++ = '^';
*out++ = q3[(*str & CON_FGMASK) >> CON_FGSHIFT];
}
else
{ {
if (outsize<=4) if (outsize<=4)
break; break;
@ -1926,23 +1985,106 @@ void COM_DeFunString(conchar_t *str, char *out, int outsize, qboolean ignoreflag
*out++ = '^'; *out++ = '^';
*out++ = '&'; *out++ = '&';
if ((d & CON_FGMASK) == CON_WHITEMASK) if ((d & CON_FGMASK) == CON_WHITEMASK)
*out++ = '-'; *out = '-';
else else
sprintf(out, "%X", d>>24); sprintf(out, "%X", d>>24);
out++;
if (d & CON_NONCLEARBG) if (d & CON_NONCLEARBG)
{
sprintf(out, "%X", d>>28); sprintf(out, "%X", d>>28);
}
else else
*out++ = '-'; *out = '-';
out++;
}
} }
fl = (*str & CON_FLAGSMASK); fl = (*str & CON_FLAGSMASK);
} }
*out++ = (unsigned char)(*str++&255);
//don't magically show hidden text
if (ignoreflags && (*str & CON_HIDDEN))
continue;
c = *str++ & 0xffff;
if (com_parseutf8.ival > 0)
{
//utf-8
if (c > 0x7ff)
{
if (outsize<=3)
break;
outsize -= 3;
*out++ = (unsigned char)((c>>12)&0x0f) | 0xe0;
*out++ = (unsigned char)((c>>6)&0x3f) | 0x80;
*out++ = (unsigned char)(c&0x3f) | 0x80;
} }
*out++ = 0; else if (c > 0x7f)
{
if (outsize<=2)
break;
outsize -= 2;
*out++ = (unsigned char)((c>>6)&0x1f) | 0xc0;
*out++ = (unsigned char)(c&0x3f) | 0x80;
} }
else
{
if (outsize<=1)
break;
outsize -= 1;
*out++ = (unsigned char)(c&0x7f);
}
}
else if (com_parseutf8.ival)
{
//iso8859-1
if ((c >= 0 && c < 255) || (c >= 0xe000+32 && c < 0xe000+127)) //quake chars between 32 and 127 are identical to iso8859-1
{
if (!--outsize)
break;
*out++ = (unsigned char)(c&255);
}
else //any other quake char is not iso8859-1
{
const char hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
if (outsize<=6)
break;
outsize -= 6;
*out++ = '^';
*out++ = 'U';
*out++ = hex[(c>>12)&15];
*out++ = hex[(c>>8)&15];
*out++ = hex[(c>>4)&15];
*out++ = hex[(c>>0)&15];
}
}
else
{
//quake chars
if (c == '\n' || c == '\r' || c == '\t' || (c >= 32 && c < 127) || (c >= 0xe000 && c < 0xe100)) //quake chars between 32 and 127 are identical to iso8859-1
{
if (!--outsize)
break;
*out++ = (unsigned char)(c&255);
}
else //any other char is not quake
{
const char hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
if (outsize<=6)
break;
outsize -= 6;
*out++ = '^';
*out++ = 'U';
*out++ = hex[(c>>12)&15];
*out++ = hex[(c>>8)&15];
*out++ = hex[(c>>4)&15];
*out++ = hex[(c>>0)&15];
}
}
}
*out = 0;
}
return out;
} }
static int dehex(int i) static int dehex(int i)
@ -1963,6 +2105,9 @@ conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t
int extstackdepth = 0; int extstackdepth = 0;
unsigned int uc, l; unsigned int uc, l;
int utf8 = com_parseutf8.ival; int utf8 = com_parseutf8.ival;
conchar_t linkinitflags = CON_WHITEMASK;/*doesn't need the init, but msvc is stupid*/
qboolean linkkeep = keepmarkup;
conchar_t *linkstart = NULL;
conchar_t ext; conchar_t ext;
@ -2120,6 +2265,40 @@ conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t
// else invalid code // else invalid code
goto messedup; goto messedup;
} }
else if (str[1] == '[' && !linkstart)
{
//preserved flags and reset to white. links must contain their own colours.
linkinitflags = ext;
ext = COLOR_RED << CON_FGSHIFT;
linkstart = out;
*out++ = '[';
//never keep the markup
linkkeep = keepmarkup;
keepmarkup = false;
str+=2;
continue;
}
else if (str[1] == ']' && linkstart)
{
*out++ = ']';
//its a valid link, so we can hide it all now
*linkstart++ |= CON_HIDDEN; //leading [ is hidden
while(linkstart < out-1 && (*linkstart&CON_CHARMASK) != '\\') //link text is NOT hidden
linkstart++;
while(linkstart < out) //but the infostring behind it is, as well as the terminator
*linkstart++ |= CON_HIDDEN;
//reset colours to how they used to be
ext = linkinitflags;
linkstart = NULL;
keepmarkup = linkkeep;
//never keep the markup
str+=2;
continue;
}
else if (str[1] == 'a') else if (str[1] == 'a')
{ {
ext ^= CON_2NDCHARSETTEXT; ext ^= CON_2NDCHARSETTEXT;
@ -2130,6 +2309,9 @@ conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t
} }
else if (str[1] == 'd') else if (str[1] == 'd')
{ {
if (linkstart)
ext = COLOR_RED << CON_FGSHIFT;
else
ext = defaultflags; ext = defaultflags;
} }
else if (str[1] == 'm') else if (str[1] == 'm')

View file

@ -275,7 +275,7 @@ void COM_InitArgv (int argc, const char **argv);
void COM_ParsePlusSets (void); void COM_ParsePlusSets (void);
typedef unsigned int conchar_t; typedef unsigned int conchar_t;
void COM_DeFunString(conchar_t *str, char *out, int outsize, qboolean ignoreflags); char *COM_DeFunString(conchar_t *str, conchar_t *stop, char *out, int outsize, qboolean ignoreflags);
conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t *out, int outsize, qboolean keepmarkup); //ext is usually CON_WHITEMASK, returns its null terminator conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t *out, int outsize, qboolean keepmarkup); //ext is usually CON_WHITEMASK, returns its null terminator
int COM_FunStringLength(unsigned char *str); int COM_FunStringLength(unsigned char *str);

View file

@ -38,7 +38,7 @@ extern conchar_t q3codemasks[MAXQ3COLOURS];
#define CON_HIGHCHARSMASK 0x00000080 // Quake's alternative mask #define CON_HIGHCHARSMASK 0x00000080 // Quake's alternative mask
#define CON_FLAGSMASK 0xFFF00000 #define CON_FLAGSMASK 0xFFF00000
#define CON_UNUSEDMASK 0x000F0000 #define CON_HIDDEN 0x000F0000
#define CON_CHARMASK 0x0000FFFF #define CON_CHARMASK 0x0000FFFF
#define CON_FGMASK 0x0F000000 #define CON_FGMASK 0x0F000000
@ -51,6 +51,9 @@ extern conchar_t q3codemasks[MAXQ3COLOURS];
#define CON_DEFAULTCHAR (CON_WHITEMASK | 32) #define CON_DEFAULTCHAR (CON_WHITEMASK | 32)
#define CON_LINKSTART (CON_HIDDEN | '[')
#define CON_LINKEND (CON_HIDDEN | ']')
// RGBI standard colors // RGBI standard colors
#define COLOR_BLACK 0 #define COLOR_BLACK 0
#define COLOR_DARKBLUE 1 #define COLOR_DARKBLUE 1
@ -142,7 +145,7 @@ void Con_ForceActiveNow(void);
void Con_Init (void); void Con_Init (void);
void Con_Shutdown (void); void Con_Shutdown (void);
void Con_DrawConsole (int lines, qboolean noback); void Con_DrawConsole (int lines, qboolean noback);
char *Con_CopyConsole(void); char *Con_CopyConsole(qboolean nomarkup);
void Con_Print (char *txt); void Con_Print (char *txt);
void VARGS Con_Printf (const char *fmt, ...) LIKEPRINTF(1); void VARGS Con_Printf (const char *fmt, ...) LIKEPRINTF(1);
void VARGS Con_TPrintf (translation_t text, ...); void VARGS Con_TPrintf (translation_t text, ...);

View file

@ -5846,7 +5846,7 @@ int CM_WriteAreaBits (model_t *mod, qbyte *buffer, int area)
return bytes; return bytes;
} }
#ifndef CLIENTONLY
void CM_InitPortalState(void) void CM_InitPortalState(void)
{ {
int i; int i;
@ -5857,6 +5857,7 @@ void CM_InitPortalState(void)
map_q2areas[i].floodnum = 0; map_q2areas[i].floodnum = 0;
} }
} }
#endif
/* /*
=================== ===================

View file

@ -2290,7 +2290,7 @@ void QCBUILTIN PF_strdecolorize (progfuncs_t *prinst, struct globalvars_s *pr_gl
char result[8192]; char result[8192];
unsigned int flagged[8192]; unsigned int flagged[8192];
COM_ParseFunString(CON_WHITEMASK, in, flagged, sizeof(flagged), false); COM_ParseFunString(CON_WHITEMASK, in, flagged, sizeof(flagged), false);
COM_DeFunString(flagged, result, sizeof(result), true); COM_DeFunString(flagged, NULL, result, sizeof(result), true);
RETURN_TSTRING(result); RETURN_TSTRING(result);
} }

View file

@ -435,6 +435,8 @@ typedef enum
//201 used by DP... WTF? CLEARSCREEN //201 used by DP... WTF? CLEARSCREEN
VF_LPLAYER = 202, VF_LPLAYER = 202,
VF_AFOV = 203, //aproximate fov (match what the engine would normally use for the fov cvar). p0=fov, p1=zoom VF_AFOV = 203, //aproximate fov (match what the engine would normally use for the fov cvar). p0=fov, p1=zoom
VF_SCREENVSIZE = 204,
VF_SCREENPSIZE = 205,
} viewflags; } viewflags;
/*FIXME: this should be changed*/ /*FIXME: this should be changed*/

View file

@ -339,3 +339,4 @@ int D3D11Shader_FindUniform(union programhandle_u *h, int type, char *name)
return -1; return -1;
} }
#endif #endif

View file

@ -9,11 +9,6 @@
#define COBJMACROS #define COBJMACROS
#include <d3d11.h> #include <d3d11.h>
//#include <d3d9.h>
//#pragma comment(lib, "../libs/dxsdk9/lib/d3d9.lib")
/*Fixup outdated windows headers*/ /*Fixup outdated windows headers*/
#ifndef WM_XBUTTONDOWN #ifndef WM_XBUTTONDOWN
#define WM_XBUTTONDOWN 0x020B #define WM_XBUTTONDOWN 0x020B

View file

@ -22538,6 +22538,18 @@
/> />
</FileConfiguration> </FileConfiguration>
</File> </File>
<File
RelativePath="..\common\sha1.c"
>
<FileConfiguration
Name="GLDebug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
</File>
<File <File
RelativePath="..\common\translate.c" RelativePath="..\common\translate.c"
> >

View file

@ -3213,11 +3213,11 @@ void GLBE_SelectDLight(dlight_t *dl, vec3_t colour)
shaderstate.lastuniform = 0; shaderstate.lastuniform = 0;
lmode = 0; lmode = 0;
if (dl->fov && shaderstate.shader_light[lmode|LSHADER_SPOT]->prog) if (dl->fov && shaderstate.shader_light[lmode|LSHADER_SPOT] && shaderstate.shader_light[lmode|LSHADER_SPOT]->prog)
lmode |= LSHADER_SPOT; lmode |= LSHADER_SPOT;
if ((dl->flags & LFLAG_SHADOWMAP) && shaderstate.shader_light[lmode|LSHADER_SMAP]->prog) if ((dl->flags & LFLAG_SHADOWMAP) && shaderstate.shader_light[lmode|LSHADER_SMAP] && shaderstate.shader_light[lmode|LSHADER_SMAP]->prog)
lmode |= LSHADER_SMAP; lmode |= LSHADER_SMAP;
if (TEXVALID(shaderstate.lightcubemap) && shaderstate.shader_light[lmode|LSHADER_CUBE]->prog) if (TEXVALID(shaderstate.lightcubemap) && shaderstate.shader_light[lmode|LSHADER_CUBE] && shaderstate.shader_light[lmode|LSHADER_CUBE]->prog)
lmode |= LSHADER_CUBE; lmode |= LSHADER_CUBE;
shaderstate.lightmode = lmode; shaderstate.lightmode = lmode;
} }

View file

@ -1190,6 +1190,8 @@ int Font_CharEndCoord(struct font_s *font, int x, unsigned int charcode)
{ {
struct charcache_s *c; struct charcache_s *c;
#define TABWIDTH (8*20) #define TABWIDTH (8*20)
if (charcode&CON_HIDDEN)
return x;
if ((charcode&CON_CHARMASK) == '\t') if ((charcode&CON_CHARMASK) == '\t')
return x + ((TABWIDTH - (x % TABWIDTH)) % TABWIDTH); return x + ((TABWIDTH - (x % TABWIDTH)) % TABWIDTH);
@ -1212,6 +1214,8 @@ int Font_CharWidth(unsigned int charcode)
{ {
struct charcache_s *c; struct charcache_s *c;
struct font_s *font = curfont; struct font_s *font = curfont;
if (charcode&CON_HIDDEN)
return 0;
if ((charcode & CON_2NDCHARSETTEXT) && font->alt) if ((charcode & CON_2NDCHARSETTEXT) && font->alt)
font = font->alt; font = font->alt;
@ -1333,6 +1337,9 @@ int Font_DrawChar(int px, int py, unsigned int charcode)
int col; int col;
int v; int v;
struct font_s *font = curfont; struct font_s *font = curfont;
if (charcode & CON_HIDDEN)
return px;
if ((charcode & CON_2NDCHARSETTEXT) && font->alt) if ((charcode & CON_2NDCHARSETTEXT) && font->alt)
font = font->alt; font = font->alt;

View file

@ -9946,6 +9946,8 @@ void PR_DumpPlatform_f(void)
{"VF_PERSPECTIVE", "const float", CS, VF_PERSPECTIVE}, {"VF_PERSPECTIVE", "const float", CS, VF_PERSPECTIVE},
{"VF_LPLAYER", "const float", CS, VF_LPLAYER}, {"VF_LPLAYER", "const float", CS, VF_LPLAYER},
{"VF_AFOV", "const float", CS, VF_AFOV}, {"VF_AFOV", "const float", CS, VF_AFOV},
{"VF_SCREENVSIZE", "const float", CS, VF_SCREENVSIZE},
{"VF_SCREENPSIZE", "const float", CS, VF_SCREENPSIZE},
{"RF_VIEWMODEL", "const float", CS, CSQCRF_VIEWMODEL}, {"RF_VIEWMODEL", "const float", CS, CSQCRF_VIEWMODEL},
{"RF_EXTERNALMODEL", "const float", CS, CSQCRF_EXTERNALMODEL}, {"RF_EXTERNALMODEL", "const float", CS, CSQCRF_EXTERNALMODEL},

View file

@ -4523,6 +4523,7 @@ void SV_FixupName(char *in, char *out, unsigned int outlen)
{ {
char *s, *p; char *s, *p;
unsigned int len; unsigned int len;
conchar_t testbuf[1024], *t, *e;
if (outlen == 0) if (outlen == 0)
return; return;
@ -4544,7 +4545,20 @@ void SV_FixupName(char *in, char *out, unsigned int outlen)
} }
*s = '\0'; *s = '\0';
if (!*out) /*note: clients are not guarenteed to parse things the same as the server. utf-8 surrogates may be awkward here*/
e = COM_ParseFunString(CON_WHITEMASK, out, testbuf, sizeof(testbuf), false);
for (t = testbuf; t < e; t++)
{
/*reject anything hidden in names*/
if (*t & CON_HIDDEN)
break;
/*reject pictograms*/
if ((*t & CON_CHARMASK) >= 0xe100 && (*t & CON_CHARMASK) < 0xe200)
break;
/*FIXME: should we try to ensure that the chars are in most fonts? that might annoy speakers of more exotic languages I suppose. cvar it?*/
}
if (!*out || (t < e) || e == testbuf)
{ //reached end and it was all whitespace { //reached end and it was all whitespace
//white space only //white space only
strncpy(out, "unnamed", outlen); strncpy(out, "unnamed", outlen);

View file

@ -23,40 +23,105 @@ class MyDelegate : public Berkelium::WindowDelegate
private: private:
decctx *ctx; decctx *ctx;
virtual void onCrashedWorker(Berkelium::Window *win)
{
int i;
Con_Printf("Berkelium worker crashed\n");
/*black it out*/
for (i = 0; i < ctx->width*ctx->height; i++)
{
ctx->buffer[i] = 0xff000000;
}
ctx->repainted = true;
}
virtual void onCrashed(Berkelium::Window *win)
{
int i;
Con_Printf("Berkelium window crashed\n");
/*black it out*/
for (i = 0; i < ctx->width*ctx->height; i++)
{
ctx->buffer[i] = 0xff000000;
}
ctx->repainted = true;
}
virtual void onUnresponsive(Berkelium::Window *win)
{
Con_Printf("Berkelium window unresponsive\n");
}
virtual void onResponsive(Berkelium::Window *win)
{
Con_Printf("Berkelium window responsive again, yay\n");
}
virtual void onPaint(Berkelium::Window *wini, const unsigned char *bitmap_in, const Berkelium::Rect &bitmap_rect, size_t num_copy_rects, const Berkelium::Rect *copy_rects, int dx, int dy, const Berkelium::Rect& scroll_rect) virtual void onPaint(Berkelium::Window *wini, const unsigned char *bitmap_in, const Berkelium::Rect &bitmap_rect, size_t num_copy_rects, const Berkelium::Rect *copy_rects, int dx, int dy, const Berkelium::Rect& scroll_rect)
{ {
int i; int i;
// handle paint events... // handle paint events...
if (dx || dy) if (dx || dy)
{ {
int y; int y, m;
int t = scroll_rect.top(); int dt = scroll_rect.top();
int l = scroll_rect.left(); int dl = scroll_rect.left();
int w = scroll_rect.width(); int w = scroll_rect.width();
int h = scroll_rect.height(); int h = scroll_rect.height();
int st = dt - dy;
int sl = dl - dx;
/*bound the output rect*/
if (dt < 0)
{
st -= dt;
h += dt;
dt = 0;
}
if (dl < 0)
{
sl -= dl;
w += dl;
dl = 0;
}
/*bound the source rect*/
if (st < 0)
{
dt -= st;
h += st;
st = 0;
}
if (sl < 0)
{
dl -= sl;
w += sl;
sl = 0;
}
/*bound the width*/
m = (dl>sl)?dl:sl;
if (m + w > ctx->width)
w = ctx->width - m;
m = (dt>st)?dt:st;
if (m + h > ctx->height)
h = ctx->height - m;
if (w > 0 && h > 0)
{
if (dy > 0) if (dy > 0)
{ {
//if we're moving downwards, we need to write the bottom before the top (so we don't overwrite the data before its copied) //if we're moving downwards, we need to write the bottom before the top (so we don't overwrite the data before its copied)
for (y = t+h-1; y >= t; y--) for (y = h; y >= 0; y--)
{ {
if (y < 0 || y >= ctx->height) memmove(ctx->buffer + (dl + (dt+y)*ctx->width), ctx->buffer + (sl + (st+y)*ctx->width), w*4);
continue;
if (y+dy < 0 || y+dy >= ctx->height)
continue;
memmove(ctx->buffer + ((l+dx) + (y+dy)*ctx->width), ctx->buffer + (l + y*ctx->width), w*4);
} }
} }
else else
{ {
//moving upwards requires we write the top row first //moving upwards requires we write the top row first
for (y = t; y < t+h; y++) for (y = 0; y < h; y++)
{ {
if (y < 0 || y >= ctx->height) memmove(ctx->buffer + (dl + (dt+y)*ctx->width), ctx->buffer + (sl + (st+y)*ctx->width), w*4);
continue; }
if (y+dy < 0 || y+dy >= ctx->height)
continue;
memmove(ctx->buffer + ((l+dx) + (y+dy)*ctx->width), ctx->buffer + (l + y*ctx->width), w*4);
} }
} }
} }
@ -65,22 +130,37 @@ private:
unsigned int *out = ctx->buffer; unsigned int *out = ctx->buffer;
const unsigned int *in = (const unsigned int*)bitmap_in; const unsigned int *in = (const unsigned int*)bitmap_in;
int x, y; int x, y;
int t = copy_rects[i].top() - bitmap_rect.top(); int t = copy_rects[i].top();
int l = copy_rects[i].left() - bitmap_rect.left(); int l = copy_rects[i].left();
int r = copy_rects[i].width() + l; int r = copy_rects[i].width() + l;
int b = copy_rects[i].height() + t; int b = copy_rects[i].height() + t;
unsigned int instride = bitmap_rect.width() - (r - l); int w, h;
unsigned int outstride = ctx->width - (r - l);
out += copy_rects[i].left(); //Clip the rect to the display. This should generally happen anyway, but resizes can be lagged a bit with the whole multi-process/thread thing.
out += copy_rects[i].top() * ctx->width; //don't need to clip to the bitmap rect, that should be correct.
if (l < 0)
l = 0;
if (t < 0)
t = 0;
if (r > ctx->width)
r = ctx->width;
if (b > ctx->height)
b = ctx->height;
w = r - l;
h = b - t;
in += l; unsigned int instride = bitmap_rect.width() - (w);
in += t * bitmap_rect.width(); unsigned int outstride = ctx->width - (w);
for (y = t; y < b; y++) out += l;
out += t * ctx->width;
in += (l-bitmap_rect.left());
in += (t-bitmap_rect.top()) * bitmap_rect.width();
for (y = 0; y < h; y++)
{ {
for (x = l; x < r; x++) for (x = 0; x < w; x++)
{ {
*out++ = *in++; *out++ = *in++;
} }
@ -182,16 +262,47 @@ static void Dec_Key (void *vctx, int code, int unicode, int isup)
wchar_t wchr = unicode; wchar_t wchr = unicode;
if (code >= 178 && code < 178+6) if (code >= 178 && code < 178+6)
ctx->wnd->mouseButton(code - 178, !isup); {
code = code - 178;
//swap mouse2+3
if (code == 1)
code = 2;
else if (code == 2)
code = 1;
ctx->wnd->mouseButton(code, !isup);
}
else if (code == 188 || code == 189) else if (code == 188 || code == 189)
{
if (!isup)
ctx->wnd->mouseWheel(0, (code==189)?-30:30); ctx->wnd->mouseWheel(0, (code==189)?-30:30);
}
else else
{ {
if (code) if (code)
{ {
int mods = 0; int mods = 0;
if (code == 127) if (code == 127)
code = 0x08;
else if (code == 140) //del
code = 0x2e; code = 0x2e;
else if (code == 143) //home
code = 0x24;
else if (code == 144) //end
code = 0x23;
else if (code == 141) //pgdn
code = 0x22;
else if (code == 142) //pgup
code = 0x21;
else if (code == 139) //ins
code = 0x2d;
else if (code == 132) //up
code = 0x26;
else if (code == 133) //down
code = 0x28;
else if (code == 134) //left
code = 0x25;
else if (code == 135) //right
code = 0x27;
ctx->wnd->keyEvent(!isup, mods, code, 0); ctx->wnd->keyEvent(!isup, mods, code, 0);
} }
if (unicode && !isup) if (unicode && !isup)
@ -214,6 +325,10 @@ static void Dec_ChangeStream(void *vctx, char *newstream)
ctx->wnd->refresh(); ctx->wnd->refresh();
else if (!strcmp(newstream+4, "transparent")) else if (!strcmp(newstream+4, "transparent"))
ctx->wnd->setTransparent(true); ctx->wnd->setTransparent(true);
else if (!strcmp(newstream+4, "focus"))
ctx->wnd->focus();
else if (!strcmp(newstream+4, "unfocus"))
ctx->wnd->unfocus();
else if (!strcmp(newstream+4, "opaque")) else if (!strcmp(newstream+4, "opaque"))
ctx->wnd->setTransparent(true); ctx->wnd->setTransparent(true);
else if (!strcmp(newstream+4, "stop")) else if (!strcmp(newstream+4, "stop"))