1
0
Fork 0
forked from fte/fteqw
fteqw/engine/client/sys_npfte.c
Spoike 8d5b217266 ------------------------------------------------------------------------
r4169 | acceptthis | 2013-01-17 08:55:12 +0000 (Thu, 17 Jan 2013) | 31 lines

removed MAX_VISEDICTS limit.
PEXT2_REPLACEMENTDELTAS tweaked, now has 4 million entity limit. still not enabled by default.
TE_BEAM now maps to a separate TEQW_BEAM to avoid conflicts with QW.
added android multitouch emulation for windows/rawinput (in_simulatemultitouch).
split topcolor/bottomcolor from scoreboard, for dp's colormap|1024 feature.
now using utf-8 for windows consoles.
qcc warnings/errors now give clickable console links for quick+easy editing.
disabled menutint when the currently active item changes contrast or gamma (for OneManClan).
Added support for drawfont/drawfontscale.
tweaked the qcvm a little to reduce the number of pointers.
.doll file loading. still experimental and will likely crash. requires csqc active, even if its a dummy progs. this will be fixed in time. Still other things that need cleaning up.
windows: gl_font "?" shows the standard windows font-selection dialog, and can be used to select windows fonts. not all work. and you probably don't want to use windings.
fixed splitscreen support when playing mvds. added mini-scoreboards to splitscreen. 
editor/debugger now shows asm if there's no linenumber info. also, pressing f1 for help shows the shortcuts.
Added support for .framegroups files for psk(psa) and iqm formats.
True support for ezquake's colour codes. Mutually exclusive with background colours.
path command output slightly more readable.
added support for digest_hex (MD4, SHA1, CRC16).
skingroups now colourmap correctly.
Fix terrain colour hints, and litdata from the wrong bsp.
fix ftp dual-homed issue. support epsv command, and enable ipv6 (eprt still not supported).
remove d3d11 compilation from the makefile. the required headers are not provided by mingw, and are not available to the build bot, so don't bother.
fix v *= v.x and similar opcodes.
fteqcc: fixed support for áéíóú type chars in names. utf-8 files now properly supported (even with the utf-8 bom/identifier). utf-16 also supported.
fteqcc: fixed '#if 1 == 3 && 4' parsing.
fteqcc: -Werror acts on the warning, rather than as a separate error. Line numbers are thus more readable.
fteqcc: copyright message now includes compile date instead.
fteqccgui: the treeview control is now coloured depending on whether there were warnings/errors in the last compile.
fteqccgui: the output window is now focused and scrolls down as compilation progresses.
pr_dumpplatform command dumps out some pragmas to convert more serious warnings to errors. This is to avoid the infamous 'fteqcc sucks cos my code sucks' issue.
rewrote prespawn/modelist/soundlist code. server tracks progress now.
------------------------------------------------------------------------


git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4167 fc73d0e0-1445-4013-8a0c-d673dee63da5
2013-03-12 22:29:40 +00:00

732 lines
18 KiB
C

#include "quakedef.h"
#include "winquake.h"
#define bool int //we ain't c++ (grr microsoft stdbool.h gief!)
#ifdef _WIN32
#ifndef _WINDOWS
#define _WINDOWS //stupid GCC
#endif
#endif
#include "npapi/npupp.h"
#include "sys_plugfte.h"
/*work around absolute crapness in the npapi headers*/
#define Q_STRINGZ_TO_NPVARIANT(_val, _v) \
NP_BEGIN_MACRO \
NPString str = { _val, strlen(_val) }; \
(_v).type = NPVariantType_String; \
(_v).value.stringValue = str; \
NP_END_MACRO
#undef STRINGZ_TO_NPVARIANT
#define STRINGZ_TO_NPVARIANT Q_STRINGZ_TO_NPVARIANT
#define Q_STRINGN_TO_NPVARIANT(_val, _len, _v) \
NP_BEGIN_MACRO \
NPString str = { _val, _len }; \
(_v).type = NPVariantType_String; \
(_v).value.stringValue = str; \
NP_END_MACRO
#undef STRINGN_TO_NPVARIANT
#define STRINGN_TO_NPVARIANT Q_STRINGN_TO_NPVARIANT
#define FIREFOX_BUGS_OVER_25MB
//TODO: player name input (before allowing them to join)
//TODO: fix active gl context (per thread, and we hijacked the browser's thread)
NPNetscapeFuncs *browserfuncs;
#ifdef _WIN32
#ifndef GetWindowLongPtr
#define GetWindowLongPtr GetWindowLong
#endif
#ifndef SetWindowLongPtr
#define SetWindowLongPtr SetWindowLong
#define LONG_PTR LONG
#endif
#ifndef GWLP_WNDPROC
#define GWLP_WNDPROC GWL_WNDPROC
#endif
#ifndef GWLP_USERDATA
#define GWLP_USERDATA GWL_USERDATA
#endif
#endif
qboolean NPFTE_BeginDownload(void *ctx, struct pipetype *ftype, char *url)
{
return NPERR_NO_ERROR==browserfuncs->geturlnotify(ctx, url, NULL, ftype);
}
void NPFTE_StatusChanged(void *sysctx)
{ //potentially called from another thread
NPP instance = sysctx;
struct contextpublic *pub = instance->pdata;
InvalidateRgn(pub->oldwnd, NULL, FALSE);
}
#ifdef _WIN32
void DrawWndBack(struct context *ctx, HWND hWnd, HDC hdc, PAINTSTRUCT *p)
{
int width, height;
HBITMAP bmp = Plug_GetSplashBack(ctx, hdc, &width, &height);
if (bmp)
{
HDC memDC;
RECT irect;
memDC = CreateCompatibleDC(hdc);
SelectObject(memDC, bmp);
GetClientRect(hWnd, &irect);
StretchBlt(hdc, irect.left, irect.top, irect.right-irect.left,irect.bottom-irect.top, memDC, 0, 0, width, height, SRCCOPY);
SelectObject(memDC, NULL);
DeleteDC(memDC);
Plug_ReleaseSplashBack(ctx, bmp);
}
else
PatBlt(hdc, p->rcPaint.left, p->rcPaint.top, p->rcPaint.right-p->rcPaint.left,p->rcPaint.bottom-p->rcPaint.top,PATCOPY);
}
LRESULT CALLBACK MyPluginWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
struct context *ctx;
struct contextpublic *pub;
ctx = (struct context *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
if (!ctx)
return DefWindowProc(hWnd, msg, wParam, lParam);
pub = (struct contextpublic*)ctx;
switch(msg)
{
case WM_USER:
/*if the plugin is somewhere in video code, the plugin might depend upon us being able to respond to window messages*/
/* while(ctx->queuedstreams)
{
struct qstream *strm;
strm = ctx->queuedstreams;
ctx->queuedstreams = strm->next;
if (!browserfuncs->geturlnotify(ctx->nppinstance, strm->url, NULL, strm->type))
{
VS_DebugLocation(__FILE__, __LINE__, "Starting Download %s", strm->url);
if (strm->type->wait == WAIT_YES)
ctx->waitingfordatafiles++;
}
free(strm);
}
*/
return TRUE;
case WM_ERASEBKGND:
return FALSE;
case WM_PAINT:
if (*pub->statusmessage)
{
HDC hdc;
PAINTSTRUCT paint;
unsigned int progress;
unsigned int total;
progress = pub->dldone;
total = pub->dlsize;
hdc = BeginPaint(hWnd, &paint);
DrawWndBack(ctx, hWnd, hdc, &paint);
SetBkMode(hdc, TRANSPARENT);
TextOutA(hdc, 0, 0, pub->statusmessage, strlen(pub->statusmessage));
EndPaint(hWnd, &paint);
return TRUE;
}
else if (pub->downloading)
{
HDC hdc;
PAINTSTRUCT paint;
char s[32];
unsigned int progress;
unsigned int total;
progress = pub->dldone;
total = pub->dlsize;
hdc = BeginPaint(hWnd, &paint);
DrawWndBack(ctx, hWnd, hdc, &paint);
SetBkMode(hdc, TRANSPARENT);
TextOutA(hdc, 0, 0, "Downloading Data, please wait", 16);
if (!progress && !total)
sprintf(s, "connecting");
else if (total)
sprintf(s, "%i bytes (%i%%)", progress, (int)((100.0f*progress)/total));
else
sprintf(s, "%i bytes", progress);
TextOutA(hdc, 0, 32, s, strlen(s));
EndPaint(hWnd, &paint);
return TRUE;
}
else
{
HDC hdc;
PAINTSTRUCT paint;
char *s;
hdc = BeginPaint(hWnd, &paint);
DrawWndBack(ctx, hWnd, hdc, &paint);
SetBkMode(hdc, TRANSPARENT);
if (!pub->running)
{
s = "Click to activate";
TextOutA(hdc, 0, 0, s, strlen(s));
if (pub->availver)
{
s = "Your plugin may be incompatible";
TextOutA(hdc, 0, 32, s, strlen(s));
s = "A newer version is available. Your version is dated " __DATE__ ".";
TextOutA(hdc, 0, 48, s, strlen(s));
}
}
EndPaint(hWnd, &paint);
return TRUE;
}
break;
case WM_LBUTTONDOWN:
SetActiveWindow(hWnd);
if (!Plug_StartContext(ctx))
Plug_StopContext(NULL, false);
break;
default:
break;
}
//I would call the previous wndproc... but that crashes firefox
return DefWindowProc(hWnd, msg, wParam, lParam);
}
#endif
static const struct browserfuncs npfte_browserfuncs =
{
NPFTE_BeginDownload,
NPFTE_StatusChanged
};
NPError NP_LOADDS NPP_New(NPMIMEType pluginType, NPP instance,
uint16 mode, int16 argc, char* argn[],
char* argv[], NPSavedData* saved)
{
int i;
struct context *ctx;
if (!instance || instance->pdata)
{
return NPERR_INVALID_INSTANCE_ERROR;
}
if (mode != NP_EMBED && mode != NP_FULL)
{
return NPERR_INVALID_PLUGIN_ERROR;
}
ctx = Plug_CreateContext(instance, &npfte_browserfuncs);
instance->pdata = ctx;
if (!ctx)
{
return NPERR_OUT_OF_MEMORY_ERROR;
}
//parse out the properties
for (i = 0; i < argc; i++)
{
Plug_SetString(ctx, Plug_FindProp(ctx, argn[i]), argv[i]);
}
return NPERR_NO_ERROR;
}
NPError NP_LOADDS NPP_Destroy(NPP instance, NPSavedData** save)
{
struct context *ctx = instance->pdata;
struct contextpublic *pub = (struct contextpublic *)ctx;
if (!ctx)
return NPERR_INVALID_INSTANCE_ERROR;
#ifdef _WIN32
if (pub->oldwnd)
{
if (pub->oldproc)
SetWindowLongPtr(pub->oldwnd, GWLP_WNDPROC, (LONG_PTR)pub->oldproc);
SetWindowLongPtr(pub->oldwnd, GWLP_USERDATA, (LONG_PTR)NULL);
}
#endif
Plug_DestroyContext(ctx);
instance->pdata = NULL;
return NPERR_NO_ERROR;
}
NPError NP_LOADDS NPP_SetWindow(NPP instance, NPWindow* window)
{
struct context *ctx = instance->pdata;
struct contextpublic *pub = (struct contextpublic*)ctx;
#ifdef _WIN32
WNDPROC p;
if (!ctx)
return NPERR_INVALID_INSTANCE_ERROR;
//if the window changed
if (Plug_ChangeWindow(ctx, window->window, 0, 0, window->width, window->height))
{
//we switched window?
if (pub->oldwnd && pub->oldproc)
{
SetWindowLongPtr(pub->oldwnd, GWLP_WNDPROC, (LONG_PTR)pub->oldproc);
}
pub->oldproc = NULL;
p = (WNDPROC)GetWindowLongPtr(window->window, GWLP_WNDPROC);
if (p != MyPluginWndProc)
pub->oldproc = p;
pub->oldwnd = window->window;
SetWindowLongPtr(window->window, GWLP_WNDPROC, (LONG_PTR)MyPluginWndProc);
SetWindowLongPtr(window->window, GWLP_USERDATA, (LONG_PTR)ctx);
}
InvalidateRgn(window->window, NULL, FALSE);
#endif
return NPERR_NO_ERROR;
}
NPError NP_LOADDS NPP_NewStream(NPP instance, NPMIMEType type,
NPStream* stream, NPBool seekable,
uint16* stype)
{
return NPERR_NO_ERROR;
/* struct context *ctx = instance->pdata;
struct qstream *qstr;
stream->pdata = qstr = malloc(sizeof(*qstr) + strlen(stream->url));
memset(qstr, 0, sizeof(*qstr));
strcpy(qstr->url, stream->url);
Plug_LockPlugin(ctx, true);
qstr->next = ctx->activestreams;
if (qstr->next)
qstr->next->prev = qstr;
ctx->activestreams = qstr;
Plug_LockPlugin(ctx, false);
if (!stream->notifyData)
{
//choose source type based on mime type
if (!strncmp(type, "text/x-quaketvident", 5))
stream->notifyData = &QTVFileDescriptor;
else if (!strcmp(type, "application/x-multiviewdemo"))
stream->notifyData = &DemoFileDescriptor;
//well that failed, try choosing based on extension
else if (!strcmp(COM_FileExtension(stream->url), "qtv"))
stream->notifyData = &QTVFileDescriptor;
else
return NPERR_INVALID_PARAM;
}
qstr->type = stream->notifyData;
if (qstr->type->needseeking)
{
*stype = NP_ASFILEONLY; //everything is a download
#ifdef FIREFOX_BUGS_OVER_25MB
*stype = NP_NORMAL;
qstr->pipe = FS_OpenTemp();
#endif
}
else
{
*stype = NP_NORMAL;
qstr->pipe = VFSPIPE_Open();
}
return NPERR_NO_ERROR;*/
}
NPError NP_LOADDS NPP_DestroyStream(NPP instance, NPStream* stream,
NPReason reason)
{
return NPERR_NO_ERROR;
/* struct context *ctx = instance->pdata;
struct qstream *qstr = stream->pdata;
if (!qstr) //urm, got canceled before it finished downloading?
return NPERR_NO_ERROR;
if (qstr->type->wait == WAIT_YES)
{
ctx->waitingfordatafiles--;
}
if (qstr->next)
qstr->next->prev = qstr->prev;
if (qstr->prev)
qstr->prev->next = qstr->next;
else
ctx->activestreams = qstr->next;
if (qstr->type->wait == WAIT_NONACTIVE)
{
Plug_LockPlugin(ctx, true);
qstr->type->completionfunc(ctx, qstr->pipe, qstr->url);
Plug_LockPlugin(ctx, false);
}
else
{
qstr->next = ctx->donestreams;
ctx->donestreams = qstr;
}
if (qstr && qstr->type && qstr->type->wait)
{
InvalidateRgn(ctx->window.window, NULL, FALSE);
}
return NPERR_NO_ERROR;*/
}
int32 NP_LOADDS NPP_WriteReady(NPP instance, NPStream* stream)
{
return 8192;
/* struct qstream *qstr = stream->pdata;
vfsfile_t *pipe = qstr?qstr->pipe:NULL;
if (pipe && pipe->seekingisabadplan)
return 1024*1024 - VFS_GETLEN(pipe);
else
return 8192;*/
}
int32 NP_LOADDS NPP_Write(NPP instance, NPStream* stream, int32 offset,
int32 len, void* buffer)
{
return NPERR_NO_ERROR;
/* int bytes = NPP_WriteReady(instance, stream);
struct context *ctx = instance->pdata;
struct qstream *qstr = stream->pdata;
if (qstr && qstr->type && qstr->type->wait)
{
qstr->offset = offset;
qstr->size = stream->end;
InvalidateRgn(ctx->window.window, NULL, FALSE);
}
if (!qstr || !qstr->pipe)
return bytes;
//we're not meant to read more bytes than we said we could read.
if (len > bytes)
len = bytes;
return VFS_WRITE(qstr->pipe, buffer, len);*/
}
void NP_LOADDS NPP_StreamAsFile(NPP instance, NPStream* stream,
const char* fname)
{
return;
/* struct qstream *qstr = stream->pdata;
if (!qstr)
return;
if (qstr->pipe)
VFS_CLOSE(qstr->pipe);
qstr->pipe = VFSOS_Open(fname, "rb");
*/
}
void NP_LOADDS NPP_Print(NPP instance, NPPrint* platformPrint)
{
//we don't support printing.
//paper and ink doesn't give a good frame rate.
return;
}
int16 NP_LOADDS NPP_HandleEvent(NPP instance, void* event)
{
// MessageBox(NULL, "NPP_HandleEvent", "npapi", 0);
return NPERR_NO_ERROR;
}
void NP_LOADDS NPP_URLNotify(NPP instance, const char* url,
NPReason reason, void* notifyData)
{
}
struct npscript
{
NPObject obj;
struct context *ctx;
};
NPObject *npscript_allocate(NPP npp, NPClass *aClass)
{
struct npscript *obj;
obj = malloc(sizeof(*obj));
obj->obj._class = aClass;
obj->obj.referenceCount = 1;
obj->ctx = npp->pdata;
return (NPObject*)obj;
}
void npscript_deallocate(NPObject *npobj)
{
free(npobj);
}
void npscript_invalidate(NPObject *npobj)
{
struct npscript *obj = (struct npscript *)npobj;
obj->ctx = NULL;
}
bool npscript_hasMethod(NPObject *npobj, NPIdentifier name)
{
NPUTF8 *mname;
mname = browserfuncs->utf8fromidentifier(name);
return false;
}
bool npscript_invoke(NPObject *npobj, NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result)
{
return false;
}
bool npscript_invokeDefault(NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result)
{
return false;
}
bool npscript_hasProperty(NPObject *npobj, NPIdentifier name)
{
struct npscript *obj = (struct npscript *)npobj;
NPUTF8 *pname;
pname = browserfuncs->utf8fromidentifier(name);
if (Plug_FindProp(obj->ctx, pname))
return true;
return false;
}
bool npscript_getProperty(NPObject *npobj, NPIdentifier name, NPVariant *result)
{
struct npscript *obj = (struct npscript *)npobj;
struct context *ctx = obj->ctx;
NPUTF8 *pname;
int prop;
bool success = false;
char *strval;
int intval;
float floatval;
pname = browserfuncs->utf8fromidentifier(name);
Plug_LockPlugin(ctx, true);
prop = Plug_FindProp(obj->ctx, pname);
if (prop >= 0)
{
if (Plug_GetString(ctx, prop, &strval))
{
char *ns;
int len;
len = strlen(strval);
if (!len)
{
STRINGN_TO_NPVARIANT(NULL, 0, *result);
success = true;
}
else
{
ns = browserfuncs->memalloc(len+1);
if (ns)
{
memcpy(ns, strval, len+1);
STRINGZ_TO_NPVARIANT(ns, *result);
success = true;
}
}
Plug_GotString(strval);
}
else if (Plug_GetInteger(ctx, prop, &intval))
{
INT32_TO_NPVARIANT(intval, *result);
success = true;
}
else if (Plug_GetFloat(ctx, prop, &floatval))
{
DOUBLE_TO_NPVARIANT(floatval, *result);
success = true;
}
}
Plug_LockPlugin(ctx, false);
return success;
}
bool npscript_setProperty(NPObject *npobj, NPIdentifier name, const NPVariant *value)
{
struct npscript *obj = (struct npscript *)npobj;
struct context *ctx = obj->ctx;
NPUTF8 *pname;
NPString str;
int prop;
bool success = false;
pname = browserfuncs->utf8fromidentifier(name);
Plug_LockPlugin(ctx, true);
prop = Plug_FindProp(obj->ctx, pname);
if (prop >= 0)
{
success = true;
if (NPVARIANT_IS_STRING(*value))
{
char *t = NULL;
str = NPVARIANT_TO_STRING(*value);
if (str.utf8characters[str.utf8length] != 0)
{
t = malloc(str.utf8length+1);
memcpy(t, str.utf8characters, str.utf8length);
t[str.utf8length] = 0;
str.utf8characters = t;
}
Plug_SetString(ctx, prop, str.utf8characters);
if (t)
free(t);
}
else if (NPVARIANT_IS_INT32(*value))
Plug_SetInteger(ctx, prop, NPVARIANT_TO_INT32(*value));
else if (NPVARIANT_IS_BOOLEAN(*value))
Plug_SetInteger(ctx, prop, NPVARIANT_TO_BOOLEAN(*value));
else if (NPVARIANT_IS_DOUBLE(*value))
Plug_SetFloat(ctx, prop, NPVARIANT_TO_DOUBLE(*value));
else
success = false;
}
Plug_LockPlugin(ctx, false);
return success;
}
bool npscript_removeProperty(NPObject *npobj, NPIdentifier name)
{
return false;
}
bool npscript_enumerate(NPObject *npobj, NPIdentifier **value, uint32_t *count)
{
return false;
}
bool npscript_construct(NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result)
{
return false;
}
NPClass npscript_class =
{
NP_CLASS_STRUCT_VERSION,
npscript_allocate,
npscript_deallocate,
npscript_invalidate,
npscript_hasMethod,
npscript_invoke,
npscript_invokeDefault,
npscript_hasProperty,
npscript_getProperty,
npscript_setProperty,
npscript_removeProperty,
npscript_enumerate,
npscript_construct
};
NPError NP_LOADDS NPP_GetValue(NPP instance, NPPVariable variable, void *value)
{
switch(variable)
{
case NPPVpluginScriptableNPObject:
*(void**)value = browserfuncs->createobject(instance, &npscript_class);
return NPERR_NO_ERROR;
default:
return NPERR_INVALID_PARAM;
}
return NPERR_NO_ERROR;
}
NPError NP_LOADDS NPP_SetValue(NPP instance, NPNVariable variable, void *value)
{
switch(variable)
{
default:
return NPERR_INVALID_PARAM;
}
return NPERR_NO_ERROR;
}
NPError OSCALL NP_Initialize(NPNetscapeFuncs* pFuncs)
{
browserfuncs = pFuncs;
return NPERR_NO_ERROR;
}
NPError OSCALL NP_Shutdown(void)
{
/* if (contextlist)
{ //the browser isn't meant to call this when there's still instances left...
return NPERR_GENERIC_ERROR;
}
*/
return NPERR_NO_ERROR;
}
NPError OSCALL NP_GetValue(void *instance, NPPVariable variable, void *value)
{
if (value == NULL)
return NPERR_INVALID_PARAM;
switch(variable)
{
case NPPVpluginNameString:
*(char**)value = FULLENGINENAME;
break;
case NPPVpluginDescriptionString:
*(char**)value = FULLENGINENAME;
break;
default:
return NPERR_INVALID_PARAM;
}
return NPERR_NO_ERROR;
}
NPError OSCALL NP_GetEntryPoints (NPPluginFuncs* pFuncs)
{
if (pFuncs->size < sizeof(NPPluginFuncs))
return NPERR_INVALID_FUNCTABLE_ERROR;
pFuncs->size = sizeof(NPPluginFuncs);
pFuncs->version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
pFuncs->newp = NPP_New;
pFuncs->destroy = NPP_Destroy;
pFuncs->setwindow = NPP_SetWindow;
pFuncs->newstream = NPP_NewStream;
pFuncs->destroystream = NPP_DestroyStream;
pFuncs->asfile = NPP_StreamAsFile;
pFuncs->writeready = NPP_WriteReady;
pFuncs->write = NPP_Write;
pFuncs->print = NPP_Print;
pFuncs->event = NPP_HandleEvent;
pFuncs->urlnotify = NPP_URLNotify;
pFuncs->javaClass = NULL;
pFuncs->getvalue = NPP_GetValue;
pFuncs->setvalue = NPP_SetValue;
return NPERR_NO_ERROR;
}
char *NP_GetMIMEDescription(void)
{
return "test/x-qtv:qtv:QTV Stream Description";
}