properlyish distinguish between primary+clipboard x11 selections. Fix possible font crash. Fix possible QC weirdness with uri_get callbacks unexpectedly stomping globals.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5321 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2018-10-14 16:16:34 +00:00
parent 2cdbe035df
commit 487201eeec
14 changed files with 218 additions and 135 deletions

View File

@ -2021,7 +2021,10 @@ static int Con_DrawConsoleLines(console_t *con, conline_t *l, int sx, int ex, in
x = selex; x = selex;
selex = selsx; selex = selsx;
selsx = x; selsx = x;
con->flags &= ~CONF_BACKSELECTION;
} }
else
con->flags |= CONF_BACKSELECTION;
// selsy *= Font_CharHeight(); // selsy *= Font_CharHeight();
// seley *= Font_CharHeight(); // seley *= Font_CharHeight();
selsy += y; selsy += y;
@ -2594,10 +2597,16 @@ void Con_DrawConsole (int lines, qboolean noback)
con_current->mousecursor[0] = mousecursor_x; con_current->mousecursor[0] = mousecursor_x;
con_current->mousecursor[1] = mousecursor_y; con_current->mousecursor[1] = mousecursor_y;
con_current->selstartline = NULL; if (!(con_current->flags & CONF_KEEPSELECTION))
con_current->selendline = NULL; {
con_current->selstartline = NULL;
con_current->selendline = NULL;
}
selactive = Key_GetConsoleSelectionBox(con_current, &selsx, &selsy, &selex, &seley); selactive = Key_GetConsoleSelectionBox(con_current, &selsx, &selsy, &selex, &seley);
if ((con_current->flags & CONF_KEEPSELECTION) && con_current->selstartline && con_current->selendline)
selactive = -1;
Font_BeginString(font_console, x, y, &x, &y); Font_BeginString(font_console, x, y, &x, &y);
Font_BeginString(font_console, selsx, selsy, &selsx, &selsy); Font_BeginString(font_console, selsx, selsy, &selsx, &selsy);
Font_BeginString(font_console, selex, seley, &selex, &seley); Font_BeginString(font_console, selex, seley, &selex, &seley);

View File

@ -1071,6 +1071,7 @@ void Key_DefaultLinkClicked(console_t *con, char *text, char *info)
} }
} }
#define Key_IsTouchScreen() false
void Key_ConsoleRelease(console_t *con, int key, unsigned int unicode) void Key_ConsoleRelease(console_t *con, int key, unsigned int unicode)
{ {
char *buffer; char *buffer;
@ -1085,10 +1086,28 @@ void Key_ConsoleRelease(console_t *con, int key, unsigned int unicode)
con->flags &= ~CONF_KEEPSELECTION; con->flags &= ~CONF_KEEPSELECTION;
else else
con->flags |= CONF_KEEPSELECTION; con->flags |= CONF_KEEPSELECTION;
con->userline = con->selstartline; if (con->userdata)
con->useroffset = con->selstartoffset; {
if (con->flags & CONF_BACKSELECTION)
{
con->userline = con->selendline;
con->useroffset = con->selendoffset;
}
else
{
con->userline = con->selstartline;
con->useroffset = con->selstartoffset;
}
}
} }
con->buttonsdown = CB_NONE; con->buttonsdown = CB_NONE;
buffer = Con_CopyConsole(con, true, false); //don't keep markup if we're copying to the clipboard
if (buffer)
{
Sys_SaveClipboard(CBT_SELECTION, buffer);
Z_Free(buffer);
}
} }
if (key == K_MOUSE1 && con->buttonsdown == CB_SCROLL) if (key == K_MOUSE1 && con->buttonsdown == CB_SCROLL)
{ {
@ -1172,7 +1191,7 @@ void Key_ConsoleRelease(console_t *con, int key, unsigned int unicode)
buffer = Con_CopyConsole(con, true, false); //don't keep markup if we're copying to the clipboard buffer = Con_CopyConsole(con, true, false); //don't keep markup if we're copying to the clipboard
if (!buffer) if (!buffer)
return; return;
Sys_SaveClipboard(CBT_SELECTION, buffer); Sys_SaveClipboard(CBT_CLIPBOARD, buffer);
Z_Free(buffer); Z_Free(buffer);
} }
if (con->buttonsdown == CB_CLOSE) if (con->buttonsdown == CB_CLOSE)
@ -1327,7 +1346,7 @@ static void Key_ConsolePaste(void *ctx, char *utf8)
if (utf8) if (utf8)
Key_EntryInsert(line, linepos, utf8); Key_EntryInsert(line, linepos, utf8);
} }
qboolean Key_EntryLine(unsigned char **line, int lineoffset, int *linepos, int key, unsigned int unicode) qboolean Key_EntryLine(console_t *con, unsigned char **line, int lineoffset, int *linepos, int key, unsigned int unicode)
{ {
qboolean alt = keydown[K_LALT] || keydown[K_RALT]; qboolean alt = keydown[K_LALT] || keydown[K_RALT];
qboolean ctrl = keydown[K_LCTRL] || keydown[K_RCTRL]; qboolean ctrl = keydown[K_LCTRL] || keydown[K_RCTRL];
@ -1415,21 +1434,29 @@ qboolean Key_EntryLine(unsigned char **line, int lineoffset, int *linepos, int k
//beware that windows translates ctrl+c and ctrl+v to a control char //beware that windows translates ctrl+c and ctrl+v to a control char
if (((unicode=='C' || unicode=='c' || unicode==3) && ctrl) || (ctrl && key == K_INS)) if (((unicode=='C' || unicode=='c' || unicode==3) && ctrl) || (ctrl && key == K_INS))
{ {
if (con && (con->flags & CONF_KEEPSELECTION))
{ //copy selected text to the system clipboard
char *buffer = Con_CopyConsole(con, true, false);
if (buffer)
{
Sys_SaveClipboard(CBT_CLIPBOARD, buffer);
Z_Free(buffer);
}
return true;
}
//copy the entire input line if there's nothing selected.
Sys_SaveClipboard(CBT_CLIPBOARD, *line); Sys_SaveClipboard(CBT_CLIPBOARD, *line);
return true; return true;
} }
if (key == K_MOUSE3)
{ //middle-click to paste from the unixy primary buffer.
Sys_Clipboard_PasteText(CBT_SELECTION, Key_ConsolePaste, line);
return true;
}
if (((unicode=='V' || unicode=='v' || unicode==22) && ctrl) || (shift && key == K_INS)) if (((unicode=='V' || unicode=='v' || unicode==22) && ctrl) || (shift && key == K_INS))
{ { //ctrl+v to paste from the windows-style clipboard.
Sys_Clipboard_PasteText(CBT_CLIPBOARD, Key_ConsolePaste, line); Sys_Clipboard_PasteText(CBT_CLIPBOARD, Key_ConsolePaste, line);
/*
char *clipText = Sys_GetClipboard();
if (clipText)
{
Key_EntryInsert(line, linepos, clipText);
Sys_CloseClipboard(clipText);
}
*/
return true; return true;
} }
@ -1598,7 +1625,14 @@ qboolean Key_Console (console_t *con, int key, unsigned int unicode)
{ {
if (con->redirect && con->redirect(con, unicode, key)) if (con->redirect && con->redirect(con, unicode, key))
return true; return true;
con->buttonsdown = CB_SCROLL; if (Key_IsTouchScreen())
{ //just scroll the console up/down
con->buttonsdown = CB_SCROLL;
}
else
{ //selecting text. woo.
con->buttonsdown = CB_SELECT;
}
con->flags &= ~CONF_KEEPSELECTION; con->flags &= ~CONF_KEEPSELECTION;
} }
} }
@ -1681,6 +1715,10 @@ qboolean Key_Console (console_t *con, int key, unsigned int unicode)
} }
#endif #endif
if (key == K_MOUSE3) //mousewheel click/middle button
{
}
//console does not have any way to accept input, so don't try giving it any. //console does not have any way to accept input, so don't try giving it any.
if (!con->linebuffered) if (!con->linebuffered)
{ {
@ -1822,7 +1860,7 @@ qboolean Key_Console (console_t *con, int key, unsigned int unicode)
cmd_completion_t *c; cmd_completion_t *c;
char *txt = key_lines[edit_line]; char *txt = key_lines[edit_line];
char *guess = Cmd_CompleteCommand(*txt=='/'?txt+1:txt, true, true, con_commandmatch, NULL); char *guess = Cmd_CompleteCommand(*txt=='/'?txt+1:txt, true, true, con_commandmatch, NULL);
Key_EntryLine(&key_lines[edit_line], 0, &key_linepos, key, unicode); Key_EntryLine(con, &key_lines[edit_line], 0, &key_linepos, key, unicode);
if (!key_linepos) if (!key_linepos)
con_commandmatch = 0; con_commandmatch = 0;
else if (guess) else if (guess)
@ -1839,7 +1877,7 @@ qboolean Key_Console (console_t *con, int key, unsigned int unicode)
} }
} }
else else
Key_EntryLine(&key_lines[edit_line], 0, &key_linepos, key, unicode); Key_EntryLine(con, &key_lines[edit_line], 0, &key_linepos, key, unicode);
return true; return true;
} }
@ -1897,7 +1935,7 @@ void Key_Message (int key, int unicode)
return; return;
} }
Key_EntryLine(&chat_buffer, 0, &chat_bufferpos, key, unicode); Key_EntryLine(NULL, &chat_buffer, 0, &chat_bufferpos, key, unicode);
} }
//============================================================================ //============================================================================

View File

@ -80,6 +80,8 @@ void Sys_Clipboard_PasteText(clipboardtype_t cbt, void (*callback)(void *cb, cha
} }
void Sys_SaveClipboard(clipboardtype_t cbt, char *text) void Sys_SaveClipboard(clipboardtype_t cbt, char *text)
{ {
if (cbt != CBT_CLIPBOARD)
return; //don't copy on mere selection. windows users won't expect it.
Z_Free(clippy); Z_Free(clippy);
clippy = Z_StrDup(text); clippy = Z_StrDup(text);
} }

View File

@ -201,8 +201,9 @@ lame timers. :s
typedef struct cmdtimer_s { typedef struct cmdtimer_s {
struct cmdtimer_s *next; struct cmdtimer_s *next;
float timer; float timer;
int level; int iarg;
char cmdtext[1]; void(*callback)(int iarg, void *data);
char data[1];
} cmdtimer_t; } cmdtimer_t;
static cmdtimer_t *cmdtimers; static cmdtimer_t *cmdtimers;
static void Cmd_ExecuteTimers(void) static void Cmd_ExecuteTimers(void)
@ -215,16 +216,33 @@ static void Cmd_ExecuteTimers(void)
if (t->timer < realtime) if (t->timer < realtime)
{ {
*link = t->next; *link = t->next;
Cbuf_InsertText(t->cmdtext, t->level, true); t->callback(t->iarg, t->data);
Z_Free(t); Z_Free(t);
} }
else else
link = &t->next; link = &t->next;
} }
} }
void Cmd_AddTimer(float delay, void(*callback)(int iarg, void *data), int iarg, void *data, size_t datasize)
{
cmdtimer_t *n = Z_Malloc(sizeof(*n) + datasize);
n->iarg = iarg;
n->callback = callback;
memcpy(n->data, data, datasize);
n->data[datasize] = 0; //just in case.
n->timer = realtime + delay;
n->next = cmdtimers;
cmdtimers = n;
}
static void Cmd_In_Callback(int iarg, void *data)
{
Cbuf_AddText((char*)data, iarg);
Cbuf_AddText("\n", iarg);
}
static void Cmd_In_f(void) static void Cmd_In_f(void)
{ {
cmdtimer_t *n;
float delay = atof(Cmd_Argv(1)); float delay = atof(Cmd_Argv(1));
char *cmd; char *cmd;
if (Cmd_Argc() < 3) if (Cmd_Argc() < 3)
@ -236,15 +254,7 @@ static void Cmd_In_f(void)
cmd = Cmd_Args(); cmd = Cmd_Args();
if (ruleset_allow_in.ival || !delay) if (ruleset_allow_in.ival || !delay)
{ Cmd_AddTimer(delay, Cmd_In_Callback, Cmd_ExecLevel, cmd, strlen(cmd));
n = Z_Malloc(sizeof(*n) + strlen(cmd));
strcpy(n->cmdtext, cmd);
n->timer = realtime + delay;
n->level = Cmd_ExecLevel;
n->next = cmdtimers;
cmdtimers = n;
}
} }
/* /*

View File

@ -193,3 +193,4 @@ qboolean If_EvaluateBoolean(const char *text, int restriction);
extern cvar_t rcon_level; extern cvar_t rcon_level;
void Cmd_AddTimer(float delay, void(*callback)(int iarg, void *data), int iarg, void *data, size_t datasize); //wrong place, gah

View File

@ -5080,7 +5080,7 @@ static void COM_Version_f (void)
#elif defined(Q3CLIENT) #elif defined(Q3CLIENT)
Con_Printf(" Quake3(client)"); Con_Printf(" Quake3(client)");
#elif defined(Q3BSPS) #elif defined(Q3BSPS)
Con_Printf(" Quake3(bsp only)"); Con_DPrintf(" ^hQuake3(bsp only)^7");
#else #else
Con_DPrintf(" ^h(disabled: Quake3)^7"); Con_DPrintf(" ^h(disabled: Quake3)^7");
#endif #endif
@ -5091,7 +5091,7 @@ static void COM_Version_f (void)
#elif defined(Q2CLIENT) #elif defined(Q2CLIENT)
Con_Printf(" Quake2(client)"); Con_Printf(" Quake2(client)");
#elif defined(Q2BSPS) #elif defined(Q2BSPS)
Con_Printf(" Quake2(bsp only)"); Con_DPrintf(" ^hQuake2(bsp only)^7");
#else #else
Con_DPrintf(" ^h(disabled: Quake2)^7"); Con_DPrintf(" ^h(disabled: Quake2)^7");
#endif #endif

View File

@ -131,7 +131,8 @@ typedef struct conline_s {
#define CONF_KEYFOCUSED 32 #define CONF_KEYFOCUSED 32
#define CONF_ISWINDOW 64 #define CONF_ISWINDOW 64
#define CONF_NOWRAP 128 #define CONF_NOWRAP 128
#define CONF_KEEPSELECTION 256 #define CONF_KEEPSELECTION 256 //there's text selected, keep it selected.
#define CONF_BACKSELECTION 512 //a hint that the text was selected from the end
typedef struct console_s typedef struct console_s
{ {
int id; int id;

View File

@ -606,6 +606,8 @@ static qboolean FS_Manifest_ParseTokens(ftemanifest_t *man)
FS_Manifest_ParsePackage(man, mdt_installation); FS_Manifest_ParsePackage(man, mdt_installation);
else if (!Q_strcasecmp(cmd, "package") || !Q_strcasecmp(cmd, "archivedpackage")) else if (!Q_strcasecmp(cmd, "package") || !Q_strcasecmp(cmd, "archivedpackage"))
FS_Manifest_ParsePackage(man, mdt_singlepackage); FS_Manifest_ParsePackage(man, mdt_singlepackage);
else if (!Q_strcasecmp(cmd, "basedir"))
;
else else
{ {
Con_Printf("Unknown token: %s\n", cmd); Con_Printf("Unknown token: %s\n", cmd);

View File

@ -458,49 +458,6 @@ int QDECL QCEditor (pubprogfuncs_t *prinst, const char *filename, int *line, int
if (fatal) if (fatal)
return DEBUG_TRACE_ABORT; return DEBUG_TRACE_ABORT;
return DEBUG_TRACE_OFF; //get lost return DEBUG_TRACE_OFF; //get lost
{
int i;
char buffer[8192];
char *r;
vfsfile_t *f;
#ifndef CLIENTONLY
SV_EndRedirect();
#endif
if (developer.value && line)
{
f = FS_OpenVFS(filename, "rb", FS_GAME);
}
else
f = NULL; //faster.
if (!f)
{
Q_snprintfz(buffer, sizeof(buffer), "%s/%s", pr_sourcedir.string, filename);
f = FS_OpenVFS(buffer, "rb", FS_GAME);
}
if (!f)
{
if (reason)
Con_Printf("-%s - %i: %s\n", filename, line?*line:*statement, reason);
else
Con_Printf("-%s - %i\n", filename, line?*line:*statement);
}
else
{
for (i = 0; i < *line; i++)
{
VFS_GETS(f, buffer, sizeof(buffer));
}
if ((r = strchr(buffer, '\r')))
{ r[0] = '\n';r[1]='\0';}
Con_Printf("-%s", buffer);
VFS_CLOSE(f);
}
}
if (reason)
return DEBUG_TRACE_ABORT;
//PF_break(NULL);
return DEBUG_TRACE_OVER;
#endif #endif
} }
@ -4654,43 +4611,74 @@ void QCBUILTIN PF_uri_unescape (pubprogfuncs_t *prinst, struct globalvars_s *pr
} }
#ifdef WEBCLIENT #ifdef WEBCLIENT
static void PR_uri_get_callback(struct dl_download *dl) typedef struct
{ {
world_t *w = dl->user_ctx; world_t *w;
float id;
int selfnum;
int spawncount;
int response;
vfsfile_t *file;
} urigetcbctx_t;
static void PR_uri_get_callback2(int iarg, void *data)
{
urigetcbctx_t *ctx = data;
world_t *w = ctx->w;
pubprogfuncs_t *prinst = w->progs; pubprogfuncs_t *prinst = w->progs;
float id = dl->user_float; float id = ctx->id;
int selfnum = dl->user_num; int selfnum = ctx->selfnum;
int replycode = ctx->response;
func_t func; func_t func;
if (!prinst || dl->user_sequence != w->spawncount) //make sure the progs vm is still active and okay.
return; if (prinst && ctx->spawncount == w->spawncount)
func = PR_FindFunction(prinst, "URI_Get_Callback", PR_ANY);
if (!func)
Con_Printf("URI_Get_Callback missing\n");
else if (func)
{ {
int len; func = PR_FindFunction(prinst, "URI_Get_Callback", PR_ANY);
char *buffer; if (!func)
struct globalvars_s *pr_globals = PR_globals(prinst, PR_CURRENT); Con_Printf("URI_Get_Callback missing\n");
else if (func)
*w->g.self = selfnum;
G_FLOAT(OFS_PARM0) = id;
G_FLOAT(OFS_PARM1) = (dl->replycode!=200)?dl->replycode:0; //for compat with DP, we change any 200s to 0.
G_INT(OFS_PARM2) = 0;
if (dl->file)
{ {
len = VFS_GETLEN(dl->file); int len;
buffer = malloc(len+1); char *buffer;
buffer[len] = 0; struct globalvars_s *pr_globals = PR_globals(prinst, PR_CURRENT);
VFS_READ(dl->file, buffer, len); int oldself = *w->g.self;
G_INT(OFS_PARM2) = PR_TempString(prinst, buffer); *w->g.self = selfnum;
free(buffer); G_FLOAT(OFS_PARM0) = id;
} G_FLOAT(OFS_PARM1) = (replycode!=200)?replycode:0; //for compat with DP, we change any 200s to 0.
G_INT(OFS_PARM2) = 0;
PR_ExecuteProgram(prinst, func); if (ctx->file)
{
len = VFS_GETLEN(ctx->file);
buffer = malloc(len+1);
buffer[len] = 0;
VFS_READ(ctx->file, buffer, len);
G_INT(OFS_PARM2) = PR_TempString(prinst, buffer);
free(buffer);
}
PR_ExecuteProgram(prinst, func);
*w->g.self = oldself;
}
} }
if (ctx->file)
VFS_CLOSE(ctx->file);
}
static void PR_uri_get_callback(struct dl_download *dl)
{ //we might be sitting on a setmodel etc call (or really anywhere). don't call qc while the qc is already busy.
urigetcbctx_t ctx;
ctx.w = dl->user_ctx;
ctx.id = dl->user_float;
ctx.selfnum = dl->user_num;
ctx.spawncount = dl->user_sequence;
ctx.response = dl->replycode;
ctx.file = dl->file;
dl->file = NULL; //steal the file pointer, so the download code can't close it before we can read it.
//now post it to the timer queue, it'll get processed within a frame, ish, without screwing up any other qc state.
Cmd_AddTimer(0, PR_uri_get_callback2, 0, &ctx, sizeof(ctx));
} }
#endif #endif

View File

@ -2622,21 +2622,26 @@ unsigned int Mod_NearestCubeForSurf(msurface_t *surf, denvmap_t *envmap, size_t
size_t n, v; size_t n, v;
unsigned int best = ~0; unsigned int best = ~0;
float bestdist = FLT_MAX, dist; float bestdist = FLT_MAX, dist;
vec3_t diff, mid; vec3_t diff, mins, maxs, mid;
if (surf->mesh) if (surf->mesh && surf->mesh->numvertexes)
{ {
VectorClear(mid); VectorCopy(surf->mesh->xyz_array[0], mins);
for (v = 0; v < surf->mesh->numvertexes; v++) VectorCopy(surf->mesh->xyz_array[0], maxs);
VectorAdd(mid, surf->mesh->xyz_array[v], mid); for (v = 1; v < surf->mesh->numvertexes; v++)
VectorScale(mid, 1.0/surf->mesh->numvertexes, mid); AddPointToBounds(surf->mesh->xyz_array[0], mins, maxs);
VectorAvg(mins, maxs, mid);
for (n = 0; n < nenvmap; n++) for (n = 0; n < nenvmap; n++)
{ {
VectorSubtract(mid, envmap[n].origin, diff); VectorSubtract(envmap[n].origin, mid, diff);
#if 1 #if 1
//axial distance //axial distance
dist = min(min(fabs(diff[0]), fabs(diff[1])), fabs(diff[2])); dist = fabs(diff[0]);
if (dist > fabs(diff[1]))
dist = fabs(diff[1]);
if (dist > fabs(diff[2]))
dist = fabs(diff[2]);
#else #else
//radial distance (squared) //radial distance (squared)
dist = DotProduct(diff,diff); dist = DotProduct(diff,diff);
@ -2740,7 +2745,7 @@ void Mod_FindCubemaps_f(void)
if (nenvmap) if (nenvmap)
{ {
qsort(envmap, nenvmap, sizeof(*envmap), envmapsort); qsort(envmap, nenvmap, sizeof(*envmap), envmapsort); //sort them by size
if (ZF_ReallocElements((void**)&envmapidx, &nenvmapidx, cl.worldmodel->numsurfaces, sizeof(*envmapidx))) if (ZF_ReallocElements((void**)&envmapidx, &nenvmapidx, cl.worldmodel->numsurfaces, sizeof(*envmapidx)))
{ {
for(i = 0; i < cl.worldmodel->numsurfaces; i++) for(i = 0; i < cl.worldmodel->numsurfaces; i++)

View File

@ -1099,8 +1099,14 @@ static struct charcache_s *Font_TryLoadGlyph(font_t *f, CHARIDXTYPE charidx)
if (qface->ft.activeheight!=qface->ft.actualsize) if (qface->ft.activeheight!=qface->ft.actualsize)
{ {
//I'm just going to assume full-height raster glyphs here. I'm sure I'll be proven wrong some time but w/e. //I'm just going to assume full-height raster glyphs here. I'm sure I'll be proven wrong some time but w/e.
int nh = f->charheight; int nw, nh;
int nw = (bm->width*nh)/bm->rows; if (bm->rows)
{
nh = f->charheight;
nw = (bm->width*nh)/bm->rows;
}
else
nw = nh = 0;
if (bm->pixel_mode == FT_PIXEL_MODE_BGRA) if (bm->pixel_mode == FT_PIXEL_MODE_BGRA)
{ {
unsigned int *out = alloca(nw*nh*sizeof(*out)); unsigned int *out = alloca(nw*nh*sizeof(*out));

View File

@ -5841,7 +5841,7 @@ void Shader_DefaultScript(const char *shortname, shader_t *s, const void *args)
f++; f++;
Shader_ReadShader(s, (void*)f, 0); Shader_ReadShader(s, (void*)f, 0);
} }
}; }
void Shader_DefaultBSPLM(const char *shortname, shader_t *s, const void *args) void Shader_DefaultBSPLM(const char *shortname, shader_t *s, const void *args)
{ {

View File

@ -1284,8 +1284,7 @@ static qboolean XI2_Init(void)
//qboolean isPermedia = false; //qboolean isPermedia = false;
extern qboolean sys_gracefulexit; extern qboolean sys_gracefulexit;
#define SYS_CLIPBOARD_SIZE 512 char *clipboard_buffer[2];
char clipboard_buffer[SYS_CLIPBOARD_SIZE];
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
@ -2545,8 +2544,18 @@ static void GetEvent(void)
Atom xa_text = x11.pXInternAtom(vid_dpy, "TEXT", false); //selection owner decides encoding (and we pick UTF-8) Atom xa_text = x11.pXInternAtom(vid_dpy, "TEXT", false); //selection owner decides encoding (and we pick UTF-8)
Atom xa_targets = x11.pXInternAtom(vid_dpy, "TARGETS", false); Atom xa_targets = x11.pXInternAtom(vid_dpy, "TARGETS", false);
Atom xa_supportedtargets[] = {xa_u8string, xa_l1string, xa_text, xa_targets/*, xa_multiple, xa_timestamp*/}; Atom xa_supportedtargets[] = {xa_u8string, xa_l1string, xa_text, xa_targets/*, xa_multiple, xa_timestamp*/};
char *cliptext = NULL;
memset(&rep, 0, sizeof(rep)); memset(&rep, 0, sizeof(rep));
if (event.xselectionrequest.selection == x11.pXInternAtom(vid_dpy, "PRIMARY", false))
cliptext = clipboard_buffer[CBT_SELECTION];
else if (event.xselectionrequest.selection == x11.pXInternAtom(vid_dpy, "CLIPBOARD", false))
cliptext = clipboard_buffer[CBT_CLIPBOARD];
if (!cliptext) //err, nothing in the clipboard buffer... that's not meant to happen.
cliptext = "";
if (event.xselectionrequest.property == None) //no property sets a property matching the target atom, as a fallback.
event.xselectionrequest.property = event.xselectionrequest.target;
if (event.xselectionrequest.property == None) if (event.xselectionrequest.property == None)
event.xselectionrequest.property = x11.pXInternAtom(vid_dpy, "foobar2000", false); event.xselectionrequest.property = x11.pXInternAtom(vid_dpy, "foobar2000", false);
if (event.xselectionrequest.property != None && event.xselectionrequest.target == xa_targets) if (event.xselectionrequest.property != None && event.xselectionrequest.target == xa_targets)
@ -2556,18 +2565,18 @@ static void GetEvent(void)
} }
else if (event.xselectionrequest.property != None && (event.xselectionrequest.target == xa_u8string || event.xselectionrequest.target == xa_text)) else if (event.xselectionrequest.property != None && (event.xselectionrequest.target == xa_u8string || event.xselectionrequest.target == xa_text))
{ //UTF8_STRING or TEXT (which we choose to use utf-8 as our charset) { //UTF8_STRING or TEXT (which we choose to use utf-8 as our charset)
x11.pXChangeProperty(vid_dpy, event.xselectionrequest.requestor, event.xselectionrequest.property, event.xselectionrequest.target, 8, PropModeReplace, (void*)clipboard_buffer, strlen(clipboard_buffer)); x11.pXChangeProperty(vid_dpy, event.xselectionrequest.requestor, event.xselectionrequest.property, event.xselectionrequest.target, 8, PropModeReplace, (void*)cliptext, strlen(cliptext));
rep.xselection.property = event.xselectionrequest.property; rep.xselection.property = event.xselectionrequest.property;
} }
else if (event.xselectionrequest.property != None && event.xselectionrequest.target == xa_l1string) else if (event.xselectionrequest.property != None && event.xselectionrequest.target == xa_l1string)
{ //STRING == latin1. convert as needed. { //STRING == latin1. convert as needed.
char latin1[SYS_CLIPBOARD_SIZE]; char *latin1 = alloca(strlen(cliptext)+1); //may shorten
char *in = clipboard_buffer; char *in = cliptext;
int c = 0; int c = 0;
int err; int err;
while (*in && c < sizeof(latin1)) while (*in && c < sizeof(latin1))
{ {
int uc =utf8_decode(&err, in, &in); int uc = utf8_decode(&err, in, &in);
if ((uc >= 0xe000 && uc <= 0xe100) && (uc&0x7f) >= 32) if ((uc >= 0xe000 && uc <= 0xe100) && (uc&0x7f) >= 32)
uc = uc&0x7f; //don't do c0/c1 glyphs. otherwise treat as ascii. uc = uc&0x7f; //don't do c0/c1 glyphs. otherwise treat as ascii.
else if (uc > 255 || err) else if (uc > 255 || err)
@ -3739,7 +3748,7 @@ void Sys_Clipboard_PasteText(clipboardtype_t clipboardtype, void (*callback)(voi
x11paste.prop = x11.pXInternAtom(vid_dpy, "_FTE_PASTE", false); x11paste.prop = x11.pXInternAtom(vid_dpy, "_FTE_PASTE", false);
clipboardowner = x11.pXGetSelectionOwner(vid_dpy, x11paste.clipboard); clipboardowner = x11.pXGetSelectionOwner(vid_dpy, x11paste.clipboard);
if (clipboardowner == vid_window) if (clipboardowner == vid_window)
callback(ctx, clipboard_buffer); //we own it? no point doing round-robin stuff. callback(ctx, clipboard_buffer[clipboardtype]); //we own it? no point doing round-robin stuff.
else if (clipboardowner != None && clipboardowner != vid_window) else if (clipboardowner != None && clipboardowner != vid_window)
{ {
x11.pXConvertSelection(vid_dpy, x11paste.clipboard, xa_string, x11paste.prop, vid_window, CurrentTime); x11.pXConvertSelection(vid_dpy, x11paste.clipboard, xa_string, x11paste.prop, vid_window, CurrentTime);
@ -3751,7 +3760,7 @@ void Sys_Clipboard_PasteText(clipboardtype_t clipboardtype, void (*callback)(voi
callback(ctx, NULL); //nothing to paste (the window that owned it sucks callback(ctx, NULL); //nothing to paste (the window that owned it sucks
} }
else else
callback(ctx, clipboard_buffer); //if we're not using x11 then just instantly call the callback callback(ctx, clipboard_buffer[clipboardtype]); //if we're not using x11 then just instantly call the callback
} }
static qboolean X11_Clipboard_Notify(XSelectionEvent *xselection) static qboolean X11_Clipboard_Notify(XSelectionEvent *xselection)
{ //called once XConvertSelection completes { //called once XConvertSelection completes
@ -3806,14 +3815,22 @@ static qboolean X11_Clipboard_Notify(XSelectionEvent *xselection)
void Sys_SaveClipboard(clipboardtype_t clipboardtype, char *text) void Sys_SaveClipboard(clipboardtype_t clipboardtype, char *text)
{ {
Q_strncpyz(clipboard_buffer, text, SYS_CLIPBOARD_SIZE); free(clipboard_buffer[clipboardtype]);
clipboard_buffer[clipboardtype] = strdup(text);
if(vid_dpy) if(vid_dpy)
{ {
Atom xa_clipboard = x11.pXInternAtom(vid_dpy, "PRIMARY", false); Atom xa_clipboard;
x11.pXSetSelectionOwner(vid_dpy, xa_clipboard, vid_window, CurrentTime); switch(clipboardtype)
{
//Set both clipboards for now. Because x11 is kinda annoying. case CBT_SELECTION:
xa_clipboard = x11.pXInternAtom(vid_dpy, "CLIPBOARD", false); xa_clipboard = x11.pXInternAtom(vid_dpy, "PRIMARY", false);
break;
case CBT_CLIPBOARD:
xa_clipboard = x11.pXInternAtom(vid_dpy, "CLIPBOARD", false);
break;
default:
return;
}
x11.pXSetSelectionOwner(vid_dpy, xa_clipboard, vid_window, CurrentTime); x11.pXSetSelectionOwner(vid_dpy, xa_clipboard, vid_window, CurrentTime);
} }
} }

View File

@ -596,9 +596,13 @@ void QDECL World_LinkEdict (world_t *w, wedict_t *ent, qboolean touch_triggers)
if (!ent->v->solid) if (!ent->v->solid)
ent->solidsize = ES_SOLID_BSP; ent->solidsize = ES_SOLID_BSP;
else// if (1)///*ent->v->modelindex || */ent->v->model) else
{ {
model_t *mod = w->Get_CModel(w, ent->v->modelindex); model_t *mod;
if (ent->v->solid == SOLID_BSP)
mod = w->Get_CModel(w, ent->v->modelindex);
else
mod = NULL;
if (mod && mod->type == mod_brush) if (mod && mod->type == mod_brush)
ent->solidsize = ES_SOLID_BSP; ent->solidsize = ES_SOLID_BSP;
else else